feat: 增加应用可更新

This commit is contained in:
zhengkunwang223 2022-10-03 17:35:39 +08:00 committed by zhengkunwang223
parent 8ff65af7bf
commit 362d2d2616
11 changed files with 97 additions and 41 deletions

View File

@ -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:"-" `

View File

@ -1,8 +0,0 @@
package model
type AppConfig struct {
BaseModel
Version string `json:"version"`
OssPath string `json:"ossPath"`
CanUpdate bool `json:"canUpdate"`
}

View File

@ -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"`
} }

View File

@ -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);"`
} }

View File

@ -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"`
} }

View File

@ -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
}

View File

@ -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
} }

View File

@ -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
}

View File

@ -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())
}
}
}
}

View File

@ -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{})
}, },
} }

View File

@ -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