mirror of
https://github.com/1Panel-dev/1Panel.git
synced 2025-01-19 08:19:15 +08:00
feat: 修改本地应用同步逻辑
This commit is contained in:
parent
aeabed70db
commit
872581fa4b
@ -1,7 +1,7 @@
|
||||
package dto
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/1Panel-dev/1Panel/backend/app/model"
|
||||
)
|
||||
|
||||
type AppDatabase struct {
|
||||
@ -31,12 +31,6 @@ type AppVersion struct {
|
||||
DetailId uint `json:"detailId"`
|
||||
}
|
||||
|
||||
//type AppList struct {
|
||||
// Version string `json:"version"`
|
||||
// Tags []Tag `json:"tags"`
|
||||
// Items []AppDefine `json:"items"`
|
||||
//}
|
||||
|
||||
type AppList struct {
|
||||
Valid bool `json:"valid"`
|
||||
Violations []string `json:"violations"`
|
||||
@ -56,6 +50,18 @@ type AppDefine struct {
|
||||
Versions []AppConfigVersion `json:"versions"`
|
||||
}
|
||||
|
||||
type LocalAppAppDefine struct {
|
||||
AppProperty model.App `json:"additionalProperties" yaml:"additionalProperties"`
|
||||
}
|
||||
|
||||
type LocalAppParam struct {
|
||||
AppParams LocalAppInstallDefine `json:"additionalProperties" yaml:"additionalProperties"`
|
||||
}
|
||||
|
||||
type LocalAppInstallDefine struct {
|
||||
FormFields interface{} `json:"formFields" yaml:"formFields"`
|
||||
}
|
||||
|
||||
type ExtraProperties struct {
|
||||
Tags []Tag `json:"tags"`
|
||||
}
|
||||
@ -84,11 +90,6 @@ type AppConfigVersion struct {
|
||||
AppForm interface{} `json:"additionalProperties"`
|
||||
}
|
||||
|
||||
func (config AppProperty) GetRequired() string {
|
||||
by, _ := json.Marshal(config.Required)
|
||||
return string(by)
|
||||
}
|
||||
|
||||
type Tag struct {
|
||||
Key string `json:"key"`
|
||||
Name string `json:"name"`
|
||||
|
@ -3,13 +3,13 @@ package model
|
||||
type App struct {
|
||||
BaseModel
|
||||
Name string `json:"name" gorm:"type:varchar(64);not null"`
|
||||
Key string `json:"key" gorm:"type:varchar(64);not null;uniqueIndex"`
|
||||
ShortDescZh string `json:"shortDescZh" gorm:"type:longtext;"`
|
||||
ShortDescEn string `json:"shortDescEn" gorm:"type:longtext;"`
|
||||
Key string `json:"key" gorm:"type:varchar(64);not null;"`
|
||||
ShortDescZh string `json:"shortDescZh" yaml:"shortDescZh" gorm:"type:longtext;"`
|
||||
ShortDescEn string `json:"shortDescEn" yaml:"shortDescEn" gorm:"type:longtext;"`
|
||||
Icon string `json:"icon" gorm:"type:longtext;"`
|
||||
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"`
|
||||
Required string `json:"required" gorm:"type:varchar(64);"`
|
||||
CrossVersionUpdate bool `json:"crossVersionUpdate"`
|
||||
Limit int `json:"limit" gorm:"type:Integer;not null"`
|
||||
Website string `json:"website" gorm:"type:varchar(64);not null"`
|
||||
@ -21,6 +21,6 @@ type App struct {
|
||||
LastModified int `json:"lastModified" gorm:"type:Integer;"`
|
||||
|
||||
Details []AppDetail `json:"-" gorm:"-:migration"`
|
||||
TagsKey []string `json:"-" gorm:"-"`
|
||||
TagsKey []string `json:"tags" yaml:"tags" gorm:"-"`
|
||||
AppTags []AppTag `json:"-" gorm:"-:migration"`
|
||||
}
|
||||
|
@ -4,6 +4,7 @@ import (
|
||||
"context"
|
||||
"github.com/1Panel-dev/1Panel/backend/app/model"
|
||||
"gorm.io/gorm"
|
||||
"gorm.io/gorm/clause"
|
||||
)
|
||||
|
||||
type AppDetailRepo struct {
|
||||
@ -18,6 +19,7 @@ type IAppDetailRepo interface {
|
||||
DeleteByAppIds(ctx context.Context, appIds []uint) error
|
||||
GetBy(opts ...DBOption) ([]model.AppDetail, error)
|
||||
BatchUpdateBy(maps map[string]interface{}, opts ...DBOption) error
|
||||
BatchDelete(ctx context.Context, appDetails []model.AppDetail) error
|
||||
}
|
||||
|
||||
func NewIAppDetailRepo() IAppDetailRepo {
|
||||
@ -66,3 +68,7 @@ func (a AppDetailRepo) BatchUpdateBy(maps map[string]interface{}, opts ...DBOpti
|
||||
}
|
||||
return db.Updates(&maps).Error
|
||||
}
|
||||
|
||||
func (a AppDetailRepo) BatchDelete(ctx context.Context, appDetails []model.AppDetail) error {
|
||||
return getTx(ctx).Omit(clause.Associations).Delete(&appDetails).Error
|
||||
}
|
||||
|
@ -9,6 +9,7 @@ import (
|
||||
"github.com/1Panel-dev/1Panel/backend/utils/docker"
|
||||
"io"
|
||||
"net/http"
|
||||
"os"
|
||||
"path"
|
||||
"strconv"
|
||||
|
||||
@ -332,6 +333,10 @@ func (a AppService) Install(ctx context.Context, req request.AppInstallCreate) (
|
||||
}
|
||||
go func() {
|
||||
if err = downloadApp(app, appDetail, appInstall, req); err != nil {
|
||||
if appInstall.Status == constant.Installing {
|
||||
appInstall.Status = constant.Error
|
||||
appInstall.Message = err.Error()
|
||||
}
|
||||
_ = appInstallRepo.Save(ctx, appInstall)
|
||||
return
|
||||
}
|
||||
@ -376,152 +381,274 @@ func (a AppService) GetAppUpdate() (*response.AppUpdateRes, error) {
|
||||
}
|
||||
|
||||
func (a AppService) SyncAppListFromLocal() {
|
||||
//fileOp := files.NewFileOp()
|
||||
//appDir := constant.LocalAppResourceDir
|
||||
//listFile := path.Join(appDir, "list.json")
|
||||
//if !fileOp.Stat(listFile) {
|
||||
// return
|
||||
//}
|
||||
//global.LOG.Infof("start sync local apps...")
|
||||
//content, err := fileOp.GetContent(listFile)
|
||||
//if err != nil {
|
||||
// global.LOG.Errorf("get list.json content failed %s", err.Error())
|
||||
// return
|
||||
//}
|
||||
//list := &dto.AppList{}
|
||||
//if err := json.Unmarshal(content, list); err != nil {
|
||||
// global.LOG.Errorf("unmarshal list.json failed %s", err.Error())
|
||||
// return
|
||||
//}
|
||||
//oldApps, _ := appRepo.GetBy(appRepo.WithResource(constant.AppResourceLocal))
|
||||
//appsMap := getApps(oldApps, list.Apps, true)
|
||||
//for _, l := range list.Apps {
|
||||
// localKey := "local" + l.Config.Key
|
||||
// app := appsMap[localKey]
|
||||
// icon, err := os.ReadFile(path.Join(appDir, l.Config.Key, "metadata", "logo.png"))
|
||||
// if err != nil {
|
||||
// global.LOG.Errorf("get [%s] icon error: %s", l.Name, err.Error())
|
||||
// continue
|
||||
// }
|
||||
// iconStr := base64.StdEncoding.EncodeToString(icon)
|
||||
// app.Icon = iconStr
|
||||
// app.TagsKey = append(l.Tags, "Local")
|
||||
// app.Recommend = 9999
|
||||
// versions := l.Versions
|
||||
// detailsMap := getAppDetails(app.Details, versions)
|
||||
//
|
||||
// for _, v := range versions {
|
||||
// detail := detailsMap[v]
|
||||
// detailPath := path.Join(appDir, l.Key, "versions", v)
|
||||
// if _, err := os.Stat(detailPath); err != nil {
|
||||
// global.LOG.Errorf("get [%s] folder error: %s", detailPath, err.Error())
|
||||
// continue
|
||||
// }
|
||||
// readmeStr, err := os.ReadFile(path.Join(detailPath, "README.md"))
|
||||
// if err != nil {
|
||||
// global.LOG.Errorf("get [%s] README error: %s", detailPath, err.Error())
|
||||
// }
|
||||
// detail.Readme = string(readmeStr)
|
||||
// dockerComposeStr, err := os.ReadFile(path.Join(detailPath, "docker-compose.yml"))
|
||||
// if err != nil {
|
||||
// global.LOG.Errorf("get [%s] docker-compose.yml error: %s", detailPath, err.Error())
|
||||
// continue
|
||||
// }
|
||||
// detail.DockerCompose = string(dockerComposeStr)
|
||||
// paramStr, err := os.ReadFile(path.Join(detailPath, "config.json"))
|
||||
// if err != nil {
|
||||
// global.LOG.Errorf("get [%s] form.json error: %s", detailPath, err.Error())
|
||||
// }
|
||||
// detail.Params = string(paramStr)
|
||||
// detailsMap[v] = detail
|
||||
// }
|
||||
// var newDetails []model.AppDetail
|
||||
// for _, v := range detailsMap {
|
||||
// newDetails = append(newDetails, v)
|
||||
// }
|
||||
// app.Details = newDetails
|
||||
// appsMap[localKey] = app
|
||||
//}
|
||||
//var (
|
||||
// addAppArray []model.App
|
||||
// updateArray []model.App
|
||||
// appIds []uint
|
||||
//)
|
||||
//for _, v := range appsMap {
|
||||
// if v.ID == 0 {
|
||||
// addAppArray = append(addAppArray, v)
|
||||
// } else {
|
||||
// updateArray = append(updateArray, v)
|
||||
// appIds = append(appIds, v.ID)
|
||||
// }
|
||||
//}
|
||||
//tx, ctx := getTxAndContext()
|
||||
//if len(addAppArray) > 0 {
|
||||
// if err := appRepo.BatchCreate(ctx, addAppArray); err != nil {
|
||||
// tx.Rollback()
|
||||
// return
|
||||
// }
|
||||
//}
|
||||
//for _, update := range updateArray {
|
||||
// if err := appRepo.Save(ctx, &update); err != nil {
|
||||
// tx.Rollback()
|
||||
// return
|
||||
// }
|
||||
//}
|
||||
//if err := appTagRepo.DeleteByAppIds(ctx, appIds); err != nil {
|
||||
// tx.Rollback()
|
||||
// return
|
||||
//}
|
||||
//apps := append(addAppArray, updateArray...)
|
||||
//var (
|
||||
// addDetails []model.AppDetail
|
||||
// updateDetails []model.AppDetail
|
||||
// appTags []*model.AppTag
|
||||
//)
|
||||
//tags, _ := tagRepo.All()
|
||||
//tagMap := make(map[string]uint, len(tags))
|
||||
//for _, app := range tags {
|
||||
// tagMap[app.Key] = app.ID
|
||||
//}
|
||||
//for _, a := range apps {
|
||||
// for _, t := range a.TagsKey {
|
||||
// tagId, ok := tagMap[t]
|
||||
// if ok {
|
||||
// appTags = append(appTags, &model.AppTag{
|
||||
// AppId: a.ID,
|
||||
// TagId: tagId,
|
||||
// })
|
||||
// }
|
||||
// }
|
||||
// for _, d := range a.Details {
|
||||
// d.AppId = a.ID
|
||||
// if d.ID == 0 {
|
||||
// addDetails = append(addDetails, d)
|
||||
// } else {
|
||||
// updateDetails = append(updateDetails, d)
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
//if len(addDetails) > 0 {
|
||||
// if err := appDetailRepo.BatchCreate(ctx, addDetails); err != nil {
|
||||
// tx.Rollback()
|
||||
// return
|
||||
// }
|
||||
//}
|
||||
//for _, u := range updateDetails {
|
||||
// if err := appDetailRepo.Update(ctx, u); err != nil {
|
||||
// tx.Rollback()
|
||||
// return
|
||||
// }
|
||||
//}
|
||||
//if len(appTags) > 0 {
|
||||
// if err := appTagRepo.BatchCreate(ctx, appTags); err != nil {
|
||||
// tx.Rollback()
|
||||
// return
|
||||
// }
|
||||
//}
|
||||
//tx.Commit()
|
||||
//global.LOG.Infof("sync local apps success")
|
||||
fileOp := files.NewFileOp()
|
||||
localAppDir := constant.LocalAppResourceDir
|
||||
if !fileOp.Stat(localAppDir) {
|
||||
return
|
||||
}
|
||||
var (
|
||||
err error
|
||||
dirEntries []os.DirEntry
|
||||
localApps []model.App
|
||||
)
|
||||
|
||||
defer func() {
|
||||
if err != nil {
|
||||
global.LOG.Errorf("sync app failed %v", err)
|
||||
}
|
||||
}()
|
||||
|
||||
global.LOG.Infof("start sync local apps...")
|
||||
dirEntries, err = os.ReadDir(localAppDir)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
for _, dirEntry := range dirEntries {
|
||||
if dirEntry.IsDir() {
|
||||
appDir := path.Join(localAppDir, dirEntry.Name())
|
||||
appDirEntries, err := os.ReadDir(appDir)
|
||||
if err != nil || len(appDirEntries) == 0 {
|
||||
continue
|
||||
}
|
||||
configYamlPath := path.Join(appDir, "data.yml")
|
||||
if !fileOp.Stat(configYamlPath) {
|
||||
continue
|
||||
}
|
||||
iconPath := path.Join(appDir, "logo.png")
|
||||
if !fileOp.Stat(iconPath) {
|
||||
continue
|
||||
}
|
||||
configYamlByte, err := fileOp.GetContent(configYamlPath)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
localAppDefine := dto.LocalAppAppDefine{}
|
||||
if err := yaml.Unmarshal(configYamlByte, &localAppDefine); err != nil {
|
||||
continue
|
||||
}
|
||||
app := localAppDefine.AppProperty
|
||||
app.Resource = constant.AppResourceLocal
|
||||
app.Status = constant.AppNormal
|
||||
app.Recommend = 9999
|
||||
app.TagsKey = append(app.TagsKey, "Local")
|
||||
app.Key = "local" + app.Key
|
||||
readMePath := path.Join(appDir, "README.md")
|
||||
if fileOp.Stat(configYamlPath) {
|
||||
readMeByte, err := fileOp.GetContent(readMePath)
|
||||
if err == nil {
|
||||
app.ReadMe = string(readMeByte)
|
||||
}
|
||||
}
|
||||
|
||||
iconByte, _ := fileOp.GetContent(iconPath)
|
||||
if iconByte != nil {
|
||||
iconStr := base64.StdEncoding.EncodeToString(iconByte)
|
||||
app.Icon = iconStr
|
||||
}
|
||||
var appDetails []model.AppDetail
|
||||
for _, appDirEntry := range appDirEntries {
|
||||
if appDirEntry.IsDir() {
|
||||
appDetail := model.AppDetail{
|
||||
Version: appDirEntry.Name(),
|
||||
Status: constant.AppNormal,
|
||||
}
|
||||
versionDir := path.Join(appDir, appDirEntry.Name())
|
||||
dockerComposePath := path.Join(versionDir, "docker-compose.yml")
|
||||
if !fileOp.Stat(dockerComposePath) {
|
||||
continue
|
||||
}
|
||||
dockerComposeByte, _ := fileOp.GetContent(dockerComposePath)
|
||||
if dockerComposeByte == nil {
|
||||
continue
|
||||
}
|
||||
appDetail.DockerCompose = string(dockerComposeByte)
|
||||
paramPath := path.Join(versionDir, "data.yml")
|
||||
if !fileOp.Stat(paramPath) {
|
||||
continue
|
||||
}
|
||||
paramByte, _ := fileOp.GetContent(paramPath)
|
||||
if paramByte == nil {
|
||||
continue
|
||||
}
|
||||
appParamConfig := dto.LocalAppParam{}
|
||||
if err := yaml.Unmarshal(paramByte, &appParamConfig); err != nil {
|
||||
continue
|
||||
}
|
||||
dataJson, err := json.Marshal(appParamConfig.AppParams)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
appDetail.Params = string(dataJson)
|
||||
appDetails = append(appDetails, appDetail)
|
||||
}
|
||||
}
|
||||
app.Details = appDetails
|
||||
localApps = append(localApps, app)
|
||||
}
|
||||
}
|
||||
|
||||
var (
|
||||
newApps []model.App
|
||||
deleteApps []model.App
|
||||
updateApps []model.App
|
||||
oldAppIds []uint
|
||||
|
||||
deleteAppIds []uint
|
||||
deleteAppDetails []model.AppDetail
|
||||
newAppDetails []model.AppDetail
|
||||
updateDetails []model.AppDetail
|
||||
|
||||
appTags []*model.AppTag
|
||||
)
|
||||
|
||||
oldApps, _ := appRepo.GetBy(appRepo.WithResource(constant.AppResourceLocal))
|
||||
apps := make(map[string]model.App, len(oldApps))
|
||||
for _, old := range oldApps {
|
||||
old.Status = constant.AppTakeDown
|
||||
apps[old.Key] = old
|
||||
}
|
||||
for _, app := range localApps {
|
||||
if oldApp, ok := apps[app.Key]; ok {
|
||||
app.ID = oldApp.ID
|
||||
appDetails := make(map[string]model.AppDetail, len(oldApp.Details))
|
||||
for _, old := range oldApp.Details {
|
||||
old.Status = constant.AppTakeDown
|
||||
appDetails[old.Version] = old
|
||||
}
|
||||
for i, newDetail := range app.Details {
|
||||
version := newDetail.Version
|
||||
newDetail.Status = constant.AppNormal
|
||||
newDetail.AppId = app.ID
|
||||
oldDetail, exist := appDetails[version]
|
||||
if exist {
|
||||
newDetail.ID = oldDetail.ID
|
||||
}
|
||||
app.Details[i] = newDetail
|
||||
}
|
||||
}
|
||||
app.TagsKey = append(app.TagsKey, constant.AppResourceLocal)
|
||||
apps[app.Key] = app
|
||||
}
|
||||
|
||||
for _, app := range apps {
|
||||
if app.ID == 0 {
|
||||
newApps = append(newApps, app)
|
||||
} else {
|
||||
oldAppIds = append(oldAppIds, app.ID)
|
||||
if app.Status == constant.AppTakeDown {
|
||||
installs, _ := appInstallRepo.ListBy(appInstallRepo.WithAppId(app.ID))
|
||||
if len(installs) > 0 {
|
||||
continue
|
||||
}
|
||||
deleteAppIds = append(deleteAppIds, app.ID)
|
||||
deleteApps = append(deleteApps, app)
|
||||
deleteAppDetails = append(deleteAppDetails, app.Details...)
|
||||
} else {
|
||||
updateApps = append(updateApps, app)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
tags, _ := tagRepo.All()
|
||||
tagMap := make(map[string]uint, len(tags))
|
||||
for _, tag := range tags {
|
||||
tagMap[tag.Key] = tag.ID
|
||||
}
|
||||
|
||||
tx, ctx := getTxAndContext()
|
||||
defer tx.Rollback()
|
||||
if len(newApps) > 0 {
|
||||
if err := appRepo.BatchCreate(ctx, newApps); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
for _, update := range updateApps {
|
||||
if err := appRepo.Save(ctx, &update); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
if len(deleteApps) > 0 {
|
||||
if err := appRepo.BatchDelete(ctx, deleteApps); err != nil {
|
||||
return
|
||||
}
|
||||
if err := appDetailRepo.DeleteByAppIds(ctx, deleteAppIds); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if err := appTagRepo.DeleteByAppIds(ctx, oldAppIds); err != nil {
|
||||
return
|
||||
}
|
||||
var ()
|
||||
|
||||
for _, newApp := range newApps {
|
||||
if newApp.ID > 0 {
|
||||
for _, detail := range newApp.Details {
|
||||
detail.AppId = newApp.ID
|
||||
newAppDetails = append(newAppDetails, detail)
|
||||
}
|
||||
}
|
||||
}
|
||||
for _, update := range updateApps {
|
||||
for _, detail := range update.Details {
|
||||
if detail.ID == 0 {
|
||||
detail.AppId = update.ID
|
||||
newAppDetails = append(newAppDetails, detail)
|
||||
} else {
|
||||
if detail.Status == constant.AppNormal {
|
||||
updateDetails = append(updateDetails, detail)
|
||||
} else {
|
||||
deleteAppDetails = append(deleteAppDetails, detail)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
allApps := append(newApps, updateApps...)
|
||||
for _, app := range allApps {
|
||||
for _, t := range app.TagsKey {
|
||||
tagId, ok := tagMap[t]
|
||||
if ok {
|
||||
appTags = append(appTags, &model.AppTag{
|
||||
AppId: app.ID,
|
||||
TagId: tagId,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if len(newAppDetails) > 0 {
|
||||
if err := appDetailRepo.BatchCreate(ctx, newAppDetails); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
for _, updateAppDetail := range updateDetails {
|
||||
if err := appDetailRepo.Update(ctx, updateAppDetail); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if len(deleteAppDetails) > 0 {
|
||||
if err := appDetailRepo.BatchDelete(ctx, deleteAppDetails); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if len(oldAppIds) > 0 {
|
||||
if err := appTagRepo.DeleteByAppIds(ctx, oldAppIds); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if len(appTags) > 0 {
|
||||
if err := appTagRepo.BatchCreate(ctx, appTags); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
tx.Commit()
|
||||
global.LOG.Infof("sync local apps success")
|
||||
}
|
||||
func (a AppService) SyncAppListFromRemote() error {
|
||||
updateRes, err := a.GetAppUpdate()
|
||||
@ -533,9 +660,10 @@ func (a AppService) SyncAppListFromRemote() error {
|
||||
return nil
|
||||
}
|
||||
var (
|
||||
tags []*model.Tag
|
||||
appTags []*model.AppTag
|
||||
list = updateRes.List
|
||||
tags []*model.Tag
|
||||
appTags []*model.AppTag
|
||||
list = updateRes.List
|
||||
oldAppIds []uint
|
||||
)
|
||||
for _, t := range list.Extra.Tags {
|
||||
tags = append(tags, &model.Tag{
|
||||
@ -547,8 +675,12 @@ func (a AppService) SyncAppListFromRemote() error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, old := range oldApps {
|
||||
oldAppIds = append(oldAppIds, old.ID)
|
||||
}
|
||||
|
||||
baseRemoteUrl := fmt.Sprintf("%s/%s/1panel", global.CONF.System.AppRepo, global.CONF.System.Mode)
|
||||
appsMap := getApps(oldApps, list.Apps, false)
|
||||
appsMap := getApps(oldApps, list.Apps)
|
||||
for _, l := range list.Apps {
|
||||
app := appsMap[l.AppProperty.Key]
|
||||
iconRes, err := http.Get(l.Icon)
|
||||
@ -630,29 +762,25 @@ func (a AppService) SyncAppListFromRemote() error {
|
||||
}
|
||||
}
|
||||
tx, ctx := getTxAndContext()
|
||||
defer tx.Rollback()
|
||||
if len(addAppArray) > 0 {
|
||||
if err := appRepo.BatchCreate(ctx, addAppArray); err != nil {
|
||||
tx.Rollback()
|
||||
return err
|
||||
}
|
||||
}
|
||||
if len(deleteAppArray) > 0 {
|
||||
if err := appRepo.BatchDelete(ctx, deleteAppArray); err != nil {
|
||||
tx.Rollback()
|
||||
return err
|
||||
}
|
||||
if err := appDetailRepo.DeleteByAppIds(ctx, deleteIds); err != nil {
|
||||
tx.Rollback()
|
||||
return err
|
||||
}
|
||||
}
|
||||
if err := tagRepo.DeleteAll(ctx); err != nil {
|
||||
tx.Rollback()
|
||||
return err
|
||||
}
|
||||
if len(tags) > 0 {
|
||||
if err := tagRepo.BatchCreate(ctx, tags); err != nil {
|
||||
tx.Rollback()
|
||||
return err
|
||||
}
|
||||
for _, t := range tags {
|
||||
@ -661,7 +789,6 @@ func (a AppService) SyncAppListFromRemote() error {
|
||||
}
|
||||
for _, update := range updateAppArray {
|
||||
if err := appRepo.Save(ctx, &update); err != nil {
|
||||
tx.Rollback()
|
||||
return err
|
||||
}
|
||||
}
|
||||
@ -697,24 +824,23 @@ func (a AppService) SyncAppListFromRemote() error {
|
||||
}
|
||||
if len(addDetails) > 0 {
|
||||
if err := appDetailRepo.BatchCreate(ctx, addDetails); err != nil {
|
||||
tx.Rollback()
|
||||
return err
|
||||
}
|
||||
}
|
||||
for _, u := range updateDetails {
|
||||
if err := appDetailRepo.Update(ctx, u); err != nil {
|
||||
tx.Rollback()
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if err := appTagRepo.DeleteAll(ctx); err != nil {
|
||||
tx.Rollback()
|
||||
return err
|
||||
if len(oldAppIds) > 0 {
|
||||
if err := appTagRepo.DeleteByAppIds(ctx, oldAppIds); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if len(appTags) > 0 {
|
||||
if err := appTagRepo.BatchCreate(ctx, appTags); err != nil {
|
||||
tx.Rollback()
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
@ -316,34 +316,6 @@ func checkRequiredAndLimit(app model.App) error {
|
||||
if err := checkLimit(app); err != nil {
|
||||
return err
|
||||
}
|
||||
if app.Required != "" {
|
||||
var requiredArray []string
|
||||
if err := json.Unmarshal([]byte(app.Required), &requiredArray); err != nil {
|
||||
return err
|
||||
}
|
||||
for _, key := range requiredArray {
|
||||
if key == "" {
|
||||
continue
|
||||
}
|
||||
requireApp, err := appRepo.GetFirst(appRepo.WithKey(key))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
details, err := appDetailRepo.GetBy(appDetailRepo.WithAppId(requireApp.ID))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
var detailIds []uint
|
||||
for _, d := range details {
|
||||
detailIds = append(detailIds, d.ID)
|
||||
}
|
||||
|
||||
_, err = appInstallRepo.GetFirst(appInstallRepo.WithDetailIdsIn(detailIds))
|
||||
if err != nil {
|
||||
return buserr.WithDetail(constant.ErrAppRequired, requireApp.Name, nil)
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -391,7 +363,7 @@ func downloadApp(app model.App, appDetail model.AppDetail, appInstall *model.App
|
||||
installAppDir := path.Join(constant.AppInstallDir, app.Key)
|
||||
if app.Resource == constant.AppResourceLocal {
|
||||
appResourceDir = constant.LocalAppResourceDir
|
||||
appKey = strings.TrimPrefix(app.Resource, "local")
|
||||
appKey = strings.TrimPrefix(app.Key, "local")
|
||||
installAppDir = path.Join(constant.LocalAppInstallDir, appKey)
|
||||
}
|
||||
resourceDir := path.Join(appResourceDir, appKey, appDetail.Version)
|
||||
@ -520,7 +492,7 @@ func getAppDetails(details []model.AppDetail, versions []dto.AppConfigVersion) m
|
||||
return appDetails
|
||||
}
|
||||
|
||||
func getApps(oldApps []model.App, items []dto.AppDefine, isLocal bool) map[string]model.App {
|
||||
func getApps(oldApps []model.App, items []dto.AppDefine) map[string]model.App {
|
||||
apps := make(map[string]model.App, len(oldApps))
|
||||
for _, old := range oldApps {
|
||||
old.Status = constant.AppTakeDown
|
||||
@ -529,18 +501,11 @@ func getApps(oldApps []model.App, items []dto.AppDefine, isLocal bool) map[strin
|
||||
for _, item := range items {
|
||||
config := item.AppProperty
|
||||
key := config.Key
|
||||
if isLocal {
|
||||
key = "local" + key
|
||||
}
|
||||
app, ok := apps[key]
|
||||
if !ok {
|
||||
app = model.App{}
|
||||
}
|
||||
if isLocal {
|
||||
app.Resource = constant.AppResourceLocal
|
||||
} else {
|
||||
app.Resource = constant.AppResourceRemote
|
||||
}
|
||||
app.Resource = constant.AppResourceRemote
|
||||
app.Name = item.Name
|
||||
app.Limit = config.Limit
|
||||
app.Key = key
|
||||
@ -551,7 +516,6 @@ func getApps(oldApps []model.App, items []dto.AppDefine, isLocal bool) map[strin
|
||||
app.Github = config.Github
|
||||
app.Type = config.Type
|
||||
app.CrossVersionUpdate = config.CrossVersionUpdate
|
||||
app.Required = config.GetRequired()
|
||||
app.Status = constant.AppNormal
|
||||
app.LastModified = item.LastModified
|
||||
app.ReadMe = item.ReadMe
|
||||
@ -572,29 +536,6 @@ func handleErr(install model.AppInstall, err error, out string) error {
|
||||
return reErr
|
||||
}
|
||||
|
||||
func getAppFromRepo(downloadPath, version string) error {
|
||||
downloadUrl := downloadPath
|
||||
appDir := constant.AppResourceDir
|
||||
|
||||
global.LOG.Infof("download file from %s", downloadUrl)
|
||||
fileOp := files.NewFileOp()
|
||||
if _, err := fileOp.CopyAndBackup(appDir); err != nil {
|
||||
return err
|
||||
}
|
||||
packagePath := path.Join(constant.ResourceDir, path.Base(downloadUrl))
|
||||
if err := fileOp.DownloadFile(downloadUrl, packagePath); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := fileOp.Decompress(packagePath, constant.ResourceDir, files.TarGz); err != nil {
|
||||
return err
|
||||
}
|
||||
_ = NewISettingService().Update("AppStoreVersion", version)
|
||||
defer func() {
|
||||
_ = fileOp.DeleteFile(packagePath)
|
||||
}()
|
||||
return nil
|
||||
}
|
||||
|
||||
func handleInstalled(appInstallList []model.AppInstall, updated bool) ([]response.AppInstalledDTO, error) {
|
||||
var res []response.AppInstalledDTO
|
||||
for _, installed := range appInstallList {
|
||||
|
@ -7,11 +7,12 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
DataDir = global.CONF.System.DataDir
|
||||
ResourceDir = path.Join(DataDir, "resource")
|
||||
AppResourceDir = path.Join(ResourceDir, "apps")
|
||||
AppInstallDir = path.Join(DataDir, "apps")
|
||||
LocalAppResourceDir = path.Join(ResourceDir, "localApps")
|
||||
LocalAppInstallDir = path.Join(DataDir, "localApps")
|
||||
RuntimeDir = path.Join(DataDir, "runtime")
|
||||
DataDir = global.CONF.System.DataDir
|
||||
ResourceDir = path.Join(DataDir, "resource")
|
||||
AppResourceDir = path.Join(ResourceDir, "apps")
|
||||
AppInstallDir = path.Join(DataDir, "apps")
|
||||
LocalAppResourceDir = path.Join(AppResourceDir, "local")
|
||||
LocalAppInstallDir = path.Join(AppInstallDir, "local")
|
||||
RemoteAppResourceDir = path.Join(AppResourceDir, "remote")
|
||||
RuntimeDir = path.Join(DataDir, "runtime")
|
||||
)
|
||||
|
@ -15,10 +15,13 @@ func Init() {
|
||||
constant.AppResourceDir = path.Join(constant.ResourceDir, "apps")
|
||||
constant.AppInstallDir = path.Join(constant.DataDir, "apps")
|
||||
constant.RuntimeDir = path.Join(constant.DataDir, "runtime")
|
||||
constant.LocalAppResourceDir = path.Join(constant.ResourceDir, "localApps")
|
||||
constant.LocalAppInstallDir = path.Join(constant.DataDir, "localApps")
|
||||
|
||||
dirs := []string{constant.DataDir, constant.ResourceDir, constant.AppResourceDir, constant.AppInstallDir, global.CONF.System.Backup, constant.RuntimeDir, constant.LocalAppResourceDir}
|
||||
constant.LocalAppResourceDir = path.Join(constant.AppResourceDir, "local")
|
||||
constant.LocalAppInstallDir = path.Join(constant.AppInstallDir, "local")
|
||||
constant.RemoteAppResourceDir = path.Join(constant.AppResourceDir, "remote")
|
||||
|
||||
dirs := []string{constant.DataDir, constant.ResourceDir, constant.AppResourceDir, constant.AppInstallDir,
|
||||
global.CONF.System.Backup, constant.RuntimeDir, constant.LocalAppResourceDir, constant.RemoteAppResourceDir}
|
||||
|
||||
fileOp := files.NewFileOp()
|
||||
for _, dir := range dirs {
|
||||
|
@ -314,12 +314,9 @@ var AddEntranceAndSSL = &gormigrate.Migration{
|
||||
}
|
||||
|
||||
var UpdateTableSetting = &gormigrate.Migration{
|
||||
ID: "20200511-update-table-setting",
|
||||
ID: "20200516-update-table-setting",
|
||||
Migrate: func(tx *gorm.DB) error {
|
||||
if err := tx.AutoMigrate(&model.App{}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := tx.Create(&model.Setting{Key: "AppStoreLastModified", Value: ""}).Error; err != nil {
|
||||
if err := tx.Create(&model.Setting{Key: "AppStoreLastModified", Value: "0"}).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
@ -327,8 +324,11 @@ var UpdateTableSetting = &gormigrate.Migration{
|
||||
}
|
||||
|
||||
var UpdateTableAppDetail = &gormigrate.Migration{
|
||||
ID: "20200513-update-table-app-detail",
|
||||
ID: "20200517-update-table-app-detail",
|
||||
Migrate: func(tx *gorm.DB) error {
|
||||
if err := tx.AutoMigrate(&model.App{}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := tx.AutoMigrate(&model.AppDetail{}); err != nil {
|
||||
return err
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user