mirror of
https://gitee.com/fit2cloud-feizhiyun/1Panel.git
synced 2024-12-02 20:08:03 +08:00
feat: 增加应用可更新
This commit is contained in:
parent
8ff65af7bf
commit
362d2d2616
@ -11,7 +11,7 @@ type App struct {
|
|||||||
Type string `json:"type" gorm:"type:varchar(64);not null"`
|
Type string `json:"type" gorm:"type:varchar(64);not null"`
|
||||||
Status string `json:"status" gorm:"type:varchar(64);not null"`
|
Status string `json:"status" gorm:"type:varchar(64);not null"`
|
||||||
Required string `json:"required" gorm:"type:varchar(64);not null"`
|
Required string `json:"required" gorm:"type:varchar(64);not null"`
|
||||||
CrossVersionUpdate bool `json:"crossVersionUpdate" gorm:"type:varchar(64);not null"`
|
CrossVersionUpdate bool `json:"crossVersionUpdate"`
|
||||||
Details []AppDetail `json:"-"`
|
Details []AppDetail `json:"-"`
|
||||||
TagsKey []string `json:"-" gorm:"-"`
|
TagsKey []string `json:"-" gorm:"-"`
|
||||||
AppTags []AppTag `json:"-" `
|
AppTags []AppTag `json:"-" `
|
||||||
|
@ -1,8 +0,0 @@
|
|||||||
package model
|
|
||||||
|
|
||||||
type AppConfig struct {
|
|
||||||
BaseModel
|
|
||||||
Version string `json:"version"`
|
|
||||||
OssPath string `json:"ossPath"`
|
|
||||||
CanUpdate bool `json:"canUpdate"`
|
|
||||||
}
|
|
@ -5,5 +5,4 @@ type AppContainer struct {
|
|||||||
ServiceName string `json:"serviceName"`
|
ServiceName string `json:"serviceName"`
|
||||||
ContainerName string `json:"containerName"`
|
ContainerName string `json:"containerName"`
|
||||||
AppInstallId uint `json:"appInstallId"`
|
AppInstallId uint `json:"appInstallId"`
|
||||||
Image string `json:"image"`
|
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,7 @@ type AppDetail struct {
|
|||||||
Version string `json:"version" gorm:"type:varchar(64);not null"`
|
Version string `json:"version" gorm:"type:varchar(64);not null"`
|
||||||
Params string `json:"-" gorm:"type:longtext;"`
|
Params string `json:"-" gorm:"type:longtext;"`
|
||||||
DockerCompose string `json:"-" gorm:"type:longtext;not null"`
|
DockerCompose string `json:"-" gorm:"type:longtext;not null"`
|
||||||
Readme string `json:"readme" gorm:"type:longtext;not null"`
|
Readme string `json:"readme" gorm:"type:longtext;"`
|
||||||
Status string `json:"status" gorm:"type:varchar(64);not null"`
|
Status string `json:"status" gorm:"type:varchar(64);not null"`
|
||||||
|
LastVersion string `json:"lastVersion" gorm:"type:varchar(64);"`
|
||||||
}
|
}
|
||||||
|
@ -11,10 +11,11 @@ type AppInstall struct {
|
|||||||
Version string `json:"version" gorm:"type:varchar(256);not null"`
|
Version string `json:"version" gorm:"type:varchar(256);not null"`
|
||||||
AppId uint `json:"appId" gorm:"type:integer;not null"`
|
AppId uint `json:"appId" gorm:"type:integer;not null"`
|
||||||
AppDetailId uint `json:"appDetailId" gorm:"type:integer;not null"`
|
AppDetailId uint `json:"appDetailId" gorm:"type:integer;not null"`
|
||||||
Params string `json:"params" gorm:"type:longtext;not null"`
|
Params string `json:"params" gorm:"type:longtext;"`
|
||||||
Status string `json:"status" gorm:"type:varchar(256);not null"`
|
Status string `json:"status" gorm:"type:varchar(256);not null"`
|
||||||
Description string `json:"description" gorm:"type:varchar(256);not null"`
|
Description string `json:"description" gorm:"type:varchar(256);"`
|
||||||
Message string `json:"message" gorm:"type:longtext;not null"`
|
Message string `json:"message" gorm:"type:longtext;"`
|
||||||
|
CanUpdate bool `json:"canUpdate"`
|
||||||
App App `json:"-"`
|
App App `json:"-"`
|
||||||
Containers []AppContainer `json:"containers"`
|
Containers []AppContainer `json:"containers"`
|
||||||
}
|
}
|
||||||
|
@ -70,10 +70,3 @@ func (a AppRepo) Save(ctx context.Context, app *model.App) error {
|
|||||||
db := ctx.Value("db").(*gorm.DB)
|
db := ctx.Value("db").(*gorm.DB)
|
||||||
return db.Omit(clause.Associations).Save(app).Error
|
return db.Omit(clause.Associations).Save(app).Error
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a AppRepo) UpdateAppConfig(ctx context.Context, app *model.AppConfig) error {
|
|
||||||
db := ctx.Value("db").(*gorm.DB)
|
|
||||||
return db.Clauses(clause.OnConflict{
|
|
||||||
Columns: []clause.Column{{Name: "id"}},
|
|
||||||
}).Create(app).Error
|
|
||||||
}
|
|
||||||
|
@ -21,7 +21,7 @@ func (a AppDetailRepo) WithAppId(id uint) DBOption {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a AppDetailRepo) GetAppDetail(opts ...DBOption) (model.AppDetail, error) {
|
func (a AppDetailRepo) GetFirst(opts ...DBOption) (model.AppDetail, error) {
|
||||||
var detail model.AppDetail
|
var detail model.AppDetail
|
||||||
db := global.DB
|
db := global.DB
|
||||||
for _, opt := range opts {
|
for _, opt := range opts {
|
||||||
@ -46,11 +46,20 @@ func (a AppDetailRepo) DeleteByAppIds(ctx context.Context, appIds []uint) error
|
|||||||
return db.Where("app_id in (?)", appIds).Delete(&model.AppDetail{}).Error
|
return db.Where("app_id in (?)", appIds).Delete(&model.AppDetail{}).Error
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a AppDetailRepo) GetByAppId(ctx context.Context, appId uint) ([]model.AppDetail, error) {
|
func (a AppDetailRepo) GetBy(opts ...DBOption) ([]model.AppDetail, error) {
|
||||||
db := ctx.Value("db").(*gorm.DB)
|
|
||||||
var details []model.AppDetail
|
var details []model.AppDetail
|
||||||
if err := db.Where("app_id = ?", appId).Find(&details).Error; err != nil {
|
db := global.DB
|
||||||
return nil, err
|
for _, opt := range opts {
|
||||||
|
db = opt(db)
|
||||||
}
|
}
|
||||||
return details, nil
|
err := db.Find(&details).Error
|
||||||
|
return details, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a AppDetailRepo) BatchUpdateBy(update model.AppDetail, opts ...DBOption) error {
|
||||||
|
db := global.DB.Model(model.AppDetail{})
|
||||||
|
for _, opt := range opts {
|
||||||
|
db = opt(db)
|
||||||
|
}
|
||||||
|
return db.Updates(update).Error
|
||||||
}
|
}
|
||||||
|
@ -3,10 +3,17 @@ package repo
|
|||||||
import (
|
import (
|
||||||
"github.com/1Panel-dev/1Panel/app/model"
|
"github.com/1Panel-dev/1Panel/app/model"
|
||||||
"github.com/1Panel-dev/1Panel/global"
|
"github.com/1Panel-dev/1Panel/global"
|
||||||
|
"gorm.io/gorm"
|
||||||
)
|
)
|
||||||
|
|
||||||
type AppInstallRepo struct{}
|
type AppInstallRepo struct{}
|
||||||
|
|
||||||
|
func (a AppInstallRepo) WithDetailIdsIn(detailIds []uint) DBOption {
|
||||||
|
return func(g *gorm.DB) *gorm.DB {
|
||||||
|
return g.Where("app_detail_id in (?)", detailIds)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (a AppInstallRepo) GetBy(opts ...DBOption) ([]model.AppInstall, error) {
|
func (a AppInstallRepo) GetBy(opts ...DBOption) ([]model.AppInstall, error) {
|
||||||
db := global.DB.Model(&model.AppInstall{})
|
db := global.DB.Model(&model.AppInstall{})
|
||||||
for _, opt := range opts {
|
for _, opt := range opts {
|
||||||
@ -56,3 +63,11 @@ func (a AppInstallRepo) Page(page, size int, opts ...DBOption) (int64, []model.A
|
|||||||
err := db.Debug().Limit(size).Offset(size * (page - 1)).Preload("App").Preload("Containers").Find(&apps).Error
|
err := db.Debug().Limit(size).Offset(size * (page - 1)).Preload("App").Preload("Containers").Find(&apps).Error
|
||||||
return count, apps, err
|
return count, apps, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (a AppInstallRepo) BatchUpdateBy(update model.AppInstall, opts ...DBOption) error {
|
||||||
|
db := global.DB.Model(model.AppInstall{})
|
||||||
|
for _, opt := range opts {
|
||||||
|
db = opt(db)
|
||||||
|
}
|
||||||
|
return db.Updates(update).Error
|
||||||
|
}
|
||||||
|
@ -18,7 +18,6 @@ import (
|
|||||||
"gopkg.in/yaml.v3"
|
"gopkg.in/yaml.v3"
|
||||||
"os"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
"sort"
|
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
@ -96,7 +95,7 @@ func (a AppService) GetApp(id uint) (dto.AppDTO, error) {
|
|||||||
return appDTO, err
|
return appDTO, err
|
||||||
}
|
}
|
||||||
appDTO.App = app
|
appDTO.App = app
|
||||||
details, err := appDetailRepo.GetByAppId(context.WithValue(context.Background(), "db", global.DB), id)
|
details, err := appDetailRepo.GetBy(appDetailRepo.WithAppId(app.ID))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return appDTO, err
|
return appDTO, err
|
||||||
}
|
}
|
||||||
@ -105,10 +104,7 @@ func (a AppService) GetApp(id uint) (dto.AppDTO, error) {
|
|||||||
versionsRaw = append(versionsRaw, detail.Version)
|
versionsRaw = append(versionsRaw, detail.Version)
|
||||||
}
|
}
|
||||||
|
|
||||||
sort.Slice(versionsRaw, func(i, j int) bool {
|
appDTO.Versions = common.GetSortedVersions(versionsRaw)
|
||||||
return common.CompareVersion(versionsRaw[i], versionsRaw[j])
|
|
||||||
})
|
|
||||||
appDTO.Versions = versionsRaw
|
|
||||||
|
|
||||||
return appDTO, nil
|
return appDTO, nil
|
||||||
}
|
}
|
||||||
@ -139,7 +135,7 @@ func (a AppService) GetAppDetail(appId uint, version string) (dto.AppDetailDTO,
|
|||||||
)
|
)
|
||||||
|
|
||||||
opts = append(opts, appDetailRepo.WithAppId(appId), appDetailRepo.WithVersion(version))
|
opts = append(opts, appDetailRepo.WithAppId(appId), appDetailRepo.WithVersion(version))
|
||||||
detail, err := appDetailRepo.GetAppDetail(opts...)
|
detail, err := appDetailRepo.GetFirst(opts...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return appDetailDTO, err
|
return appDetailDTO, err
|
||||||
}
|
}
|
||||||
@ -225,7 +221,7 @@ func (a AppService) Install(name string, appDetailId uint, params map[string]int
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
appDetail, err := appDetailRepo.GetAppDetail(commonRepo.WithByID(appDetailId))
|
appDetail, err := appDetailRepo.GetFirst(commonRepo.WithByID(appDetailId))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -289,14 +285,9 @@ func (a AppService) Install(name string, appDetailId uint, params map[string]int
|
|||||||
value := v.(map[string]interface{})
|
value := v.(map[string]interface{})
|
||||||
containerName := constant.ContainerPrefix + k + "-" + common.RandStr(4)
|
containerName := constant.ContainerPrefix + k + "-" + common.RandStr(4)
|
||||||
value["container_name"] = containerName
|
value["container_name"] = containerName
|
||||||
var image string
|
|
||||||
if i, ok := value["image"]; ok {
|
|
||||||
image = i.(string)
|
|
||||||
}
|
|
||||||
appContainers = append(appContainers, &model.AppContainer{
|
appContainers = append(appContainers, &model.AppContainer{
|
||||||
ServiceName: serviceName,
|
ServiceName: serviceName,
|
||||||
ContainerName: containerName,
|
ContainerName: containerName,
|
||||||
Image: image,
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
for k, v := range changeKeys {
|
for k, v := range changeKeys {
|
||||||
@ -666,5 +657,44 @@ func (a AppService) SyncAppList() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
tx.Commit()
|
tx.Commit()
|
||||||
|
|
||||||
|
go syncCanUpdate()
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func syncCanUpdate() {
|
||||||
|
|
||||||
|
apps, err := appRepo.GetBy()
|
||||||
|
if err != nil {
|
||||||
|
global.LOG.Errorf("sync update app error: %s", err.Error())
|
||||||
|
}
|
||||||
|
for _, app := range apps {
|
||||||
|
details, err := appDetailRepo.GetBy(appDetailRepo.WithAppId(app.ID))
|
||||||
|
if err != nil {
|
||||||
|
global.LOG.Errorf("sync update app error: %s", err.Error())
|
||||||
|
}
|
||||||
|
var versions []string
|
||||||
|
for _, detail := range details {
|
||||||
|
versions = append(versions, detail.Version)
|
||||||
|
}
|
||||||
|
versions = common.GetSortedVersions(versions)
|
||||||
|
lastVersion := versions[0]
|
||||||
|
|
||||||
|
var updateDetailIds []uint
|
||||||
|
for _, detail := range details {
|
||||||
|
if common.CompareVersion(lastVersion, detail.Version) {
|
||||||
|
if app.CrossVersionUpdate || !common.IsCrossVersion(detail.Version, lastVersion) {
|
||||||
|
updateDetailIds = append(updateDetailIds, detail.ID)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(updateDetailIds) > 0 {
|
||||||
|
if err := appDetailRepo.BatchUpdateBy(model.AppDetail{LastVersion: lastVersion}, commonRepo.WithIdsIn(updateDetailIds)); err != nil {
|
||||||
|
global.LOG.Errorf("sync update app error: %s", err.Error())
|
||||||
|
}
|
||||||
|
if err := appInstallRepo.BatchUpdateBy(model.AppInstall{CanUpdate: true}, appInstallRepo.WithDetailIdsIn(updateDetailIds)); err != nil {
|
||||||
|
global.LOG.Errorf("sync update app error: %s", err.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -150,6 +150,6 @@ var AddTableCronjob = &gormigrate.Migration{
|
|||||||
var AddTableApp = &gormigrate.Migration{
|
var AddTableApp = &gormigrate.Migration{
|
||||||
ID: "20200921-add-table-app",
|
ID: "20200921-add-table-app",
|
||||||
Migrate: func(tx *gorm.DB) error {
|
Migrate: func(tx *gorm.DB) error {
|
||||||
return tx.AutoMigrate(&model.App{}, &model.AppDetail{}, &model.Tag{}, &model.AppTag{}, &model.AppConfig{}, &model.AppInstall{}, &model.AppContainer{}, &model.AppContainer{})
|
return tx.AutoMigrate(&model.App{}, &model.AppDetail{}, &model.Tag{}, &model.AppTag{}, &model.AppInstall{}, &model.AppContainer{}, &model.AppContainer{})
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,7 @@ import (
|
|||||||
mathRand "math/rand"
|
mathRand "math/rand"
|
||||||
"net"
|
"net"
|
||||||
"regexp"
|
"regexp"
|
||||||
|
"sort"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
@ -37,6 +38,21 @@ func CompareVersion(version1 string, version2 string) bool {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func GetSortedVersions(versions []string) []string {
|
||||||
|
sort.Slice(versions, func(i, j int) bool {
|
||||||
|
return CompareVersion(versions[i], versions[j])
|
||||||
|
})
|
||||||
|
return versions
|
||||||
|
}
|
||||||
|
|
||||||
|
func IsCrossVersion(version1, version2 string) bool {
|
||||||
|
version1s := strings.Split(version1, ".")
|
||||||
|
version2s := strings.Split(version2, ".")
|
||||||
|
v1num, _ := strconv.Atoi(version1s[0])
|
||||||
|
v2num, _ := strconv.Atoi(version2s[0])
|
||||||
|
return v2num > v1num
|
||||||
|
}
|
||||||
|
|
||||||
func min(a, b int) int {
|
func min(a, b int) int {
|
||||||
if a < b {
|
if a < b {
|
||||||
return a
|
return a
|
||||||
|
Loading…
Reference in New Issue
Block a user