mirror of
https://gitee.com/fit2cloud-feizhiyun/1Panel.git
synced 2024-12-02 11:57:56 +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"`
|
||||
Status string `json:"status" 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:"-"`
|
||||
TagsKey []string `json:"-" gorm:"-"`
|
||||
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"`
|
||||
ContainerName string `json:"containerName"`
|
||||
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"`
|
||||
Params string `json:"-" gorm:"type:longtext;"`
|
||||
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"`
|
||||
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"`
|
||||
AppId uint `json:"appId" 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"`
|
||||
Description string `json:"description" gorm:"type:varchar(256);not null"`
|
||||
Message string `json:"message" gorm:"type:longtext;not null"`
|
||||
Description string `json:"description" gorm:"type:varchar(256);"`
|
||||
Message string `json:"message" gorm:"type:longtext;"`
|
||||
CanUpdate bool `json:"canUpdate"`
|
||||
App App `json:"-"`
|
||||
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)
|
||||
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
|
||||
db := global.DB
|
||||
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
|
||||
}
|
||||
|
||||
func (a AppDetailRepo) GetByAppId(ctx context.Context, appId uint) ([]model.AppDetail, error) {
|
||||
db := ctx.Value("db").(*gorm.DB)
|
||||
func (a AppDetailRepo) GetBy(opts ...DBOption) ([]model.AppDetail, error) {
|
||||
var details []model.AppDetail
|
||||
if err := db.Where("app_id = ?", appId).Find(&details).Error; err != nil {
|
||||
return nil, err
|
||||
db := global.DB
|
||||
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 (
|
||||
"github.com/1Panel-dev/1Panel/app/model"
|
||||
"github.com/1Panel-dev/1Panel/global"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
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) {
|
||||
db := global.DB.Model(&model.AppInstall{})
|
||||
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
|
||||
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"
|
||||
"os"
|
||||
"path"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
@ -96,7 +95,7 @@ func (a AppService) GetApp(id uint) (dto.AppDTO, error) {
|
||||
return appDTO, err
|
||||
}
|
||||
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 {
|
||||
return appDTO, err
|
||||
}
|
||||
@ -105,10 +104,7 @@ func (a AppService) GetApp(id uint) (dto.AppDTO, error) {
|
||||
versionsRaw = append(versionsRaw, detail.Version)
|
||||
}
|
||||
|
||||
sort.Slice(versionsRaw, func(i, j int) bool {
|
||||
return common.CompareVersion(versionsRaw[i], versionsRaw[j])
|
||||
})
|
||||
appDTO.Versions = versionsRaw
|
||||
appDTO.Versions = common.GetSortedVersions(versionsRaw)
|
||||
|
||||
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))
|
||||
detail, err := appDetailRepo.GetAppDetail(opts...)
|
||||
detail, err := appDetailRepo.GetFirst(opts...)
|
||||
if err != nil {
|
||||
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 {
|
||||
return err
|
||||
}
|
||||
@ -289,14 +285,9 @@ func (a AppService) Install(name string, appDetailId uint, params map[string]int
|
||||
value := v.(map[string]interface{})
|
||||
containerName := constant.ContainerPrefix + k + "-" + common.RandStr(4)
|
||||
value["container_name"] = containerName
|
||||
var image string
|
||||
if i, ok := value["image"]; ok {
|
||||
image = i.(string)
|
||||
}
|
||||
appContainers = append(appContainers, &model.AppContainer{
|
||||
ServiceName: serviceName,
|
||||
ContainerName: containerName,
|
||||
Image: image,
|
||||
})
|
||||
}
|
||||
for k, v := range changeKeys {
|
||||
@ -666,5 +657,44 @@ func (a AppService) SyncAppList() error {
|
||||
}
|
||||
|
||||
tx.Commit()
|
||||
|
||||
go syncCanUpdate()
|
||||
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{
|
||||
ID: "20200921-add-table-app",
|
||||
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"
|
||||
"net"
|
||||
"regexp"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
@ -37,6 +38,21 @@ func CompareVersion(version1 string, version2 string) bool {
|
||||
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 {
|
||||
if a < b {
|
||||
return a
|
||||
|
Loading…
Reference in New Issue
Block a user