From c65afb7083cfad6f81edb715c4890ef86f35c3f7 Mon Sep 17 00:00:00 2001 From: zhengkunwang223 Date: Tue, 11 Oct 2022 16:27:58 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=88=A0=E9=99=A4=20app=5Fcontainer=20?= =?UTF-8?q?=EF=BC=8C=E4=BF=AE=E6=94=B9=E5=AE=89=E8=A3=85=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/list.json | 6 +- apps/mysql/5.7.39/docker-compose.yml | 1 - apps/mysql/8.0.30/docker-compose.yml | 1 - backend/app/api/v1/app.go | 14 +- backend/app/model/app_container.go | 11 -- backend/app/model/app_install.go | 37 ++-- backend/app/model/app_install_resource.go | 9 + backend/app/model/database.go | 11 +- backend/app/repo/app_container.go | 53 ------ backend/app/repo/app_install.go | 23 +-- backend/app/repo/app_install_resource.go | 36 ++++ backend/app/repo/common.go | 22 ++- backend/app/repo/entry.go | 2 +- backend/app/service/app.go | 200 +++++----------------- backend/app/service/app_utils.go | 136 ++++++++++++++- backend/app/service/entry.go | 30 ++-- backend/go.mod | 16 +- backend/go.sum | 36 +++- backend/init/migration/migrations/init.go | 2 +- backend/router/ro_app.go | 10 +- backend/utils/common/common.go | 4 +- backend/utils/compose/compose.go | 27 ++- frontend/src/api/interface/app.ts | 3 +- 23 files changed, 377 insertions(+), 313 deletions(-) delete mode 100644 backend/app/model/app_container.go create mode 100644 backend/app/model/app_install_resource.go delete mode 100644 backend/app/repo/app_container.go create mode 100644 backend/app/repo/app_install_resource.go diff --git a/apps/list.json b/apps/list.json index 639d3ec0f..c0275066a 100644 --- a/apps/list.json +++ b/apps/list.json @@ -23,7 +23,7 @@ "short_desc": "常用关系型数据库", "icon": "mysql.png", "author": "Oracle", - "type": "internal", + "type": "runtime", "required": [""], "crossVersionUpdate": false, "limit": 0, @@ -37,7 +37,7 @@ "short_desc": "高性能的HTTP和反向代理web服务器", "icon": "nginx.png", "author": "Nginx", - "type": "internal", + "type": "runtime", "required": [""], "limit": 1, "crossVersionUpdate": true, @@ -51,7 +51,7 @@ "short_desc": "老牌博客网站模版", "icon": "wordpress.png", "author": "Wordpress", - "type": "internal", + "type": "website", "required": ["mysql"], "limit": 0, "crossVersionUpdate": true, diff --git a/apps/mysql/5.7.39/docker-compose.yml b/apps/mysql/5.7.39/docker-compose.yml index 9e5b59dd3..f7c4402e2 100644 --- a/apps/mysql/5.7.39/docker-compose.yml +++ b/apps/mysql/5.7.39/docker-compose.yml @@ -6,7 +6,6 @@ services: container_name: ${CONTAINER_NAME} restart: always environment: - TZ: ${TZ} MYSQL_ROOT_PASSWORD: ${PANEL_DB_ROOT_PASSWORD} networks: - 1panel diff --git a/apps/mysql/8.0.30/docker-compose.yml b/apps/mysql/8.0.30/docker-compose.yml index 75d9f2cfd..8c6c3ee75 100644 --- a/apps/mysql/8.0.30/docker-compose.yml +++ b/apps/mysql/8.0.30/docker-compose.yml @@ -6,7 +6,6 @@ services: container_name: ${CONTAINER_NAME} restart: always environment: - TZ: ${TZ} MYSQL_ROOT_PASSWORD: ${PANEL_DB_ROOT_PASSWORD} networks: - 1panel diff --git a/backend/app/api/v1/app.go b/backend/app/api/v1/app.go index 39f4ef4dc..e94b2e983 100644 --- a/backend/app/api/v1/app.go +++ b/backend/app/api/v1/app.go @@ -8,14 +8,14 @@ import ( "strconv" ) -func (b *BaseApi) AppSearch(c *gin.Context) { +func (b *BaseApi) SearchApp(c *gin.Context) { var req dto.AppRequest if err := c.ShouldBindJSON(&req); err != nil { helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err) return } - list, err := appService.Page(req) + list, err := appService.PageApp(req) if err != nil { helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) return @@ -24,7 +24,7 @@ func (b *BaseApi) AppSearch(c *gin.Context) { helper.SuccessWithData(c, list) } -func (b *BaseApi) AppSync(c *gin.Context) { +func (b *BaseApi) SyncApp(c *gin.Context) { if err := appService.SyncAppList(); err != nil { helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) return @@ -75,7 +75,7 @@ func (b *BaseApi) InstallApp(c *gin.Context) { helper.SuccessWithData(c, nil) } -func (b *BaseApi) PageInstalled(c *gin.Context) { +func (b *BaseApi) SearchInstalled(c *gin.Context) { var req dto.AppInstalledRequest if err := c.ShouldBindJSON(&req); err != nil { helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err) @@ -93,13 +93,13 @@ func (b *BaseApi) PageInstalled(c *gin.Context) { }) } -func (b *BaseApi) InstallOperate(c *gin.Context) { +func (b *BaseApi) OperateInstalled(c *gin.Context) { var req dto.AppInstallOperate if err := c.ShouldBindJSON(&req); err != nil { helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err) return } - if err := appService.Operate(req); err != nil { + if err := appService.OperateInstall(req); err != nil { helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) return } @@ -107,7 +107,7 @@ func (b *BaseApi) InstallOperate(c *gin.Context) { helper.SuccessWithData(c, nil) } -func (b *BaseApi) InstalledSync(c *gin.Context) { +func (b *BaseApi) SyncInstalled(c *gin.Context) { if err := appService.SyncAllInstalled(); err != nil { helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) return diff --git a/backend/app/model/app_container.go b/backend/app/model/app_container.go deleted file mode 100644 index 3a0253213..000000000 --- a/backend/app/model/app_container.go +++ /dev/null @@ -1,11 +0,0 @@ -package model - -type AppContainer struct { - BaseModel - ServiceName string `json:"serviceName" gorm:"type:varchar(64);not null"` - ContainerName string `json:"containerName" gorm:"type:varchar(64);not null"` - AppInstallID uint `json:"appInstallId" gorm:"type:integer;not null"` - Port int `json:"port" gorm:"type:integer;not null"` - Auth string `json:"auth" gorm:"type:longtext;not null"` - AppInstall AppInstall `gorm:"-"` -} diff --git a/backend/app/model/app_install.go b/backend/app/model/app_install.go index 74c977de9..c9d0cc0e3 100644 --- a/backend/app/model/app_install.go +++ b/backend/app/model/app_install.go @@ -2,23 +2,27 @@ package model import ( "github.com/1Panel-dev/1Panel/global" - "gorm.io/gorm" "path" ) type AppInstall struct { BaseModel - Name string `json:"name" gorm:"type:varchar(64);not null"` - 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;"` - Status string `json:"status" gorm:"type:varchar(256);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"` + Name string `json:"name" gorm:"type:varchar(64);not null"` + AppId uint `json:"appId" gorm:"type:integer;not null"` + AppDetailId uint `json:"appDetailId" gorm:"type:integer;not null"` + Version string `json:"version" gorm:"type:varchar(64);not null"` + Param string `json:"param" gorm:"type:longtext;"` + Env string `json:"env" gorm:"type:longtext;"` + DockerCompose string `json:"dockerCompose" gorm:"type:longtext;"` + Status string `json:"status" gorm:"type:varchar(256);not null"` + Description string `json:"description" gorm:"type:varchar(256);"` + Message string `json:"message" gorm:"type:longtext;"` + CanUpdate bool `json:"canUpdate"` + ContainerName string `json:"containerName" gorm:"type:varchar(256);not null"` + ServiceName string `json:"ServiceName" gorm:"type:varchar(256);not null"` + HttpPort int `json:"httpPort" gorm:"type:integer;not null"` + HttpsPort int `json:"httpsPort" gorm:"type:integer;not null"` + App App `json:"-"` } func (i *AppInstall) GetPath() string { @@ -28,12 +32,3 @@ func (i *AppInstall) GetPath() string { func (i *AppInstall) GetComposePath() string { return path.Join(global.CONF.System.AppDir, i.App.Key, i.Name, "docker-compose.yml") } - -func (i *AppInstall) BeforeDelete(tx *gorm.DB) (err error) { - - if err = tx.Model(AppContainer{}).Debug().Where("app_install_id = ?", i.ID).Delete(AppContainer{}).Error; err != nil { - return err - } - - return -} diff --git a/backend/app/model/app_install_resource.go b/backend/app/model/app_install_resource.go new file mode 100644 index 000000000..5cdbabe3e --- /dev/null +++ b/backend/app/model/app_install_resource.go @@ -0,0 +1,9 @@ +package model + +type AppInstallResource struct { + BaseModel + AppInstallId uint `json:"appInstallId" gorm:"type:integer;not null;"` + LinkId uint `json:"linkId" gorm:"type:integer;not null;"` + ResourceId uint `json:"resourceId" gorm:"type:integer;"` + Key string `json:"key" gorm:"type:varchar(64);not null"` +} diff --git a/backend/app/model/database.go b/backend/app/model/database.go index 0f7fa5360..7b96c804c 100644 --- a/backend/app/model/database.go +++ b/backend/app/model/database.go @@ -2,10 +2,9 @@ package model type Database struct { BaseModel - AppContainerId uint `json:"appContainerId" gorm:"type:integer;not null"` - AppInstallId uint `json:"appInstallId" gorm:"type:integer;not null"` - Key string `json:"key" gorm:"type:varchar(64);not null"` - Dbname string `json:"dbname" gorm:"type:varchar(256);not null"` - Username string `json:"username" gorm:"type:varchar(256);not null"` - Password string `json:"password" gorm:"type:varchar(256);not null"` + AppInstallId uint `json:"appInstallId" gorm:"type:integer;not null"` + Key string `json:"key" gorm:"type:varchar(64);not null"` + Dbname string `json:"dbname" gorm:"type:varchar(256);not null"` + Username string `json:"username" gorm:"type:varchar(256);not null"` + Password string `json:"password" gorm:"type:varchar(256);not null"` } diff --git a/backend/app/repo/app_container.go b/backend/app/repo/app_container.go deleted file mode 100644 index b7e7f7820..000000000 --- a/backend/app/repo/app_container.go +++ /dev/null @@ -1,53 +0,0 @@ -package repo - -import ( - "context" - "github.com/1Panel-dev/1Panel/app/model" - "github.com/1Panel-dev/1Panel/global" - "gorm.io/gorm" -) - -type AppContainerRepo struct { -} - -func (a AppContainerRepo) WithAppId(appId uint) DBOption { - return func(db *gorm.DB) *gorm.DB { - return db.Where("app_id = ?", appId) - } -} - -func (a AppContainerRepo) WithServiceName(serviceName string) DBOption { - return func(db *gorm.DB) *gorm.DB { - return db.Where("service_name = ?", serviceName) - } -} - -func (a AppContainerRepo) GetBy(opts ...DBOption) ([]model.AppContainer, error) { - db := global.DB.Model(&model.AppContainer{}) - var appContainers []model.AppContainer - for _, opt := range opts { - db = opt(db) - } - err := db.Find(&appContainers).Error - return appContainers, err -} - -func (a AppContainerRepo) GetFirst(opts ...DBOption) (model.AppContainer, error) { - db := global.DB.Model(&model.AppContainer{}) - var appContainer model.AppContainer - for _, opt := range opts { - db = opt(db) - } - err := db.Find(&appContainer).Error - return appContainer, err -} - -func (a AppContainerRepo) Create(container *model.AppContainer) error { - db := global.DB.Model(&model.AppContainer{}) - return db.Create(&container).Error -} - -func (a AppContainerRepo) BatchCreate(ctx context.Context, containers []*model.AppContainer) error { - db := ctx.Value("db").(*gorm.DB) - return db.Model(&model.AppContainer{}).Create(&containers).Error -} diff --git a/backend/app/repo/app_install.go b/backend/app/repo/app_install.go index 55dc4e7cb..23eaf00fa 100644 --- a/backend/app/repo/app_install.go +++ b/backend/app/repo/app_install.go @@ -25,13 +25,19 @@ func (a AppInstallRepo) WithStatus(status string) DBOption { } } +func (a AppInstallRepo) WithServiceName(serviceName string) DBOption { + return func(db *gorm.DB) *gorm.DB { + return db.Where("service_name = ?", serviceName) + } +} + func (a AppInstallRepo) GetBy(opts ...DBOption) ([]model.AppInstall, error) { db := global.DB.Model(&model.AppInstall{}) for _, opt := range opts { db = opt(db) } var install []model.AppInstall - err := db.Preload("App").Preload("Containers").Find(&install).Error + err := db.Preload("App").Find(&install).Error return install, err } @@ -41,26 +47,21 @@ func (a AppInstallRepo) GetFirst(opts ...DBOption) (model.AppInstall, error) { db = opt(db) } var install model.AppInstall - err := db.Preload("App").Preload("Containers").First(&install).Error + err := db.Preload("App").First(&install).Error return install, err } func (a AppInstallRepo) Create(ctx context.Context, install *model.AppInstall) error { - db := ctx.Value("db").(*gorm.DB).Model(&model.AppInstall{}) + db := getTx(ctx).Model(&model.AppInstall{}) return db.Create(&install).Error } func (a AppInstallRepo) Save(install model.AppInstall) error { - db := global.DB - return db.Save(&install).Error + return getDb().Save(&install).Error } func (a AppInstallRepo) DeleteBy(opts ...DBOption) error { - db := global.DB.Model(&model.AppInstall{}) - for _, opt := range opts { - db = opt(db) - } - return db.Delete(&model.AppInstall{}).Error + return getDb(opts...).Delete(&model.AppInstall{}).Error } func (a AppInstallRepo) Delete(ctx context.Context, install model.AppInstall) error { @@ -76,7 +77,7 @@ func (a AppInstallRepo) Page(page, size int, opts ...DBOption) (int64, []model.A } count := int64(0) db = db.Count(&count) - 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").Find(&apps).Error return count, apps, err } diff --git a/backend/app/repo/app_install_resource.go b/backend/app/repo/app_install_resource.go new file mode 100644 index 000000000..bb033abbb --- /dev/null +++ b/backend/app/repo/app_install_resource.go @@ -0,0 +1,36 @@ +package repo + +import ( + "context" + "github.com/1Panel-dev/1Panel/app/model" + "github.com/1Panel-dev/1Panel/global" + "gorm.io/gorm" +) + +type AppInstallResourceRpo struct { +} + +func (a AppInstallResourceRpo) WithAppInstallId(appInstallId uint) DBOption { + return func(db *gorm.DB) *gorm.DB { + return db.Where("app_install_id = ?", appInstallId) + } +} + +func (a AppInstallResourceRpo) GetBy(opts ...DBOption) ([]model.AppInstallResource, error) { + db := global.DB.Model(&model.AppInstallResource{}) + var resources []model.AppInstallResource + for _, opt := range opts { + db = opt(db) + } + err := db.Find(&resources).Error + return resources, err +} + +func (a AppInstallResourceRpo) Create(ctx context.Context, resource *model.AppInstallResource) error { + db := getTx(ctx).Model(&model.AppInstallResource{}) + return db.Create(&resource).Error +} + +func (a AppInstallResourceRpo) DeleteBy(ctx context.Context, opts ...DBOption) error { + return getTx(ctx, opts...).Delete(&model.AppInstallResource{}).Error +} diff --git a/backend/app/repo/common.go b/backend/app/repo/common.go index a5962db67..a628f5ca5 100644 --- a/backend/app/repo/common.go +++ b/backend/app/repo/common.go @@ -1,6 +1,10 @@ package repo -import "gorm.io/gorm" +import ( + "context" + "github.com/1Panel-dev/1Panel/global" + "gorm.io/gorm" +) type DBOption func(*gorm.DB) *gorm.DB @@ -58,3 +62,19 @@ func (c *CommonRepo) WithIdsIn(ids []uint) DBOption { return g.Where("id in (?)", ids) } } + +func getTx(ctx context.Context, opts ...DBOption) *gorm.DB { + tx := ctx.Value("db").(*gorm.DB) + for _, opt := range opts { + tx = opt(tx) + } + return tx +} + +func getDb(opts ...DBOption) *gorm.DB { + db := global.DB + for _, opt := range opts { + db = opt(db) + } + return db +} diff --git a/backend/app/repo/entry.go b/backend/app/repo/entry.go index a666e1411..025b9b643 100644 --- a/backend/app/repo/entry.go +++ b/backend/app/repo/entry.go @@ -14,7 +14,7 @@ type RepoGroup struct { TagRepo AppDetailRepo AppInstallRepo - AppContainerRepo + AppInstallResourceRpo DatabaseRepo } diff --git a/backend/app/service/app.go b/backend/app/service/app.go index d714950c1..c96d49e42 100644 --- a/backend/app/service/app.go +++ b/backend/app/service/app.go @@ -4,6 +4,7 @@ import ( "encoding/base64" "encoding/json" "errors" + "fmt" "github.com/1Panel-dev/1Panel/app/dto" "github.com/1Panel-dev/1Panel/app/model" "github.com/1Panel-dev/1Panel/app/repo" @@ -15,18 +16,15 @@ import ( "github.com/1Panel-dev/1Panel/utils/files" "golang.org/x/net/context" "gopkg.in/yaml.v3" - "math" "os" "path" - "reflect" - "strconv" "strings" ) type AppService struct { } -func (a AppService) Page(req dto.AppRequest) (interface{}, error) { +func (a AppService) PageApp(req dto.AppRequest) (interface{}, error) { var opts []repo.DBOption opts = append(opts, commonRepo.WithOrderBy("name")) @@ -147,7 +145,7 @@ func (a AppService) GetAppDetail(appId uint, version string) (dto.AppDetailDTO, return appDetailDTO, nil } -func (a AppService) Operate(req dto.AppInstallOperate) error { +func (a AppService) OperateInstall(req dto.AppInstallOperate) error { install, err := appInstallRepo.GetFirst(commonRepo.WithByID(req.InstallId)) if err != nil { return err @@ -178,46 +176,24 @@ func (a AppService) Operate(req dto.AppInstallOperate) error { op := files.NewFileOp() appDir := install.GetPath() dir, _ := os.Stat(appDir) + if dir != nil { + out, err := compose.Down(dockerComposePath) + if err != nil { + return handleErr(install, err, out) + } + if err := op.DeleteDir(appDir); err != nil { + return err + } + } tx := global.DB.Begin() ctx := context.WithValue(context.Background(), "db", tx) - if dir == nil { - if err := appInstallRepo.Delete(ctx, install); err != nil { - return err - } - tx.Commit() - return nil - } - out, err := compose.Down(dockerComposePath) - if err != nil { - tx.Rollback() - return handleErr(install, err, out) - } - if err := op.DeleteDir(appDir); err != nil { - tx.Rollback() - return err - } + if err := appInstallRepo.Delete(ctx, install); err != nil { tx.Rollback() return err } - - database, _ := dataBaseRepo.GetFirst(dataBaseRepo.ByAppInstallId(install.ID)) - if reflect.DeepEqual(database, model.Database{}) { - tx.Commit() - return nil - } - if err := dataBaseRepo.DeleteBy(ctx, dataBaseRepo.ByAppInstallId(install.ID)); err != nil { - tx.Rollback() - return err - } - container, err := appContainerRepo.GetFirst(commonRepo.WithByID(database.AppContainerId)) - if err != nil { - tx.Commit() - return nil - } - - if err := execDockerCommand(database, container, Delete); err != nil { + if err := deleteLink(ctx, &install); err != nil { tx.Rollback() return err } @@ -235,25 +211,15 @@ func (a AppService) Operate(req dto.AppInstallOperate) error { return appInstallRepo.Save(install) } -func handleErr(install model.AppInstall, err error, out string) error { - reErr := err - install.Message = err.Error() - if out != "" { - install.Message = out - reErr = errors.New(out) - } - _ = appInstallRepo.Save(install) - return reErr -} - func (a AppService) Install(name string, appDetailId uint, params map[string]interface{}) error { - port, ok := params["PANEL_APP_PORT_HTTP"] - if ok { - portStr := strconv.FormatFloat(port.(float64), 'f', -1, 32) - if common.ScanPort(portStr) { - return errors.New("port is in used") - } + httpPort, err := checkPort("PANEL_APP_PORT_HTTP", params) + if err != nil { + return errors.New(fmt.Sprintf("%d port is in used", httpPort)) + } + httpsPort, err := checkPort("PANEL_APP_PORT_HTTPS", params) + if err != nil { + return errors.New(fmt.Sprintf("%d port is in used", httpsPort)) } appDetail, err := appDetailRepo.GetFirst(commonRepo.WithByID(appDetailId)) @@ -268,8 +234,7 @@ func (a AppService) Install(name string, appDetailId uint, params map[string]int if err := checkRequiredAndLimit(app); err != nil { return err } - composeFilePath, err := copyAppData(app.Key, appDetail.Version, name, params) - if err != nil { + if err := copyAppData(app.Key, appDetail.Version, name, params); err != nil { return err } @@ -283,42 +248,10 @@ func (a AppService) Install(name string, appDetailId uint, params map[string]int AppDetailId: appDetail.ID, Version: appDetail.Version, Status: constant.Installing, - Params: string(paramByte), - } - - var ( - auth string - dbConfig dto.AppDatabase - ) - tags, err := tagRepo.GetByAppId(app.ID) - if err != nil { - return err - } - for _, tag := range tags { - if tag.Key == "Database" { - var authParam dto.AuthParam - paramByte, err := json.Marshal(params) - if err != nil { - return err - } - if err := json.Unmarshal(paramByte, &authParam); err != nil { - return err - } - authByte, err := json.Marshal(authParam) - if err != nil { - return err - } - auth = string(authByte) - } - if tag.Key == "WebSite" { - paramByte, err := json.Marshal(params) - if err != nil { - return err - } - if err := json.Unmarshal(paramByte, &dbConfig); err != nil { - return err - } - } + Env: string(paramByte), + HttpPort: httpPort, + HttpsPort: httpsPort, + App: app, } composeMap := make(map[string]interface{}) @@ -327,27 +260,14 @@ func (a AppService) Install(name string, appDetailId uint, params map[string]int } servicesMap := composeMap["services"].(map[string]interface{}) changeKeys := make(map[string]string, len(servicesMap)) - var appContainers []*model.AppContainer for k, v := range servicesMap { serviceName := k + "-" + common.RandStr(4) changeKeys[k] = serviceName value := v.(map[string]interface{}) containerName := constant.ContainerPrefix + k + "-" + common.RandStr(4) value["container_name"] = containerName - servicePort := 0 - - port, ok := params["PANEL_APP_PORT_HTTP"] - if ok { - portN := int(math.Ceil(port.(float64))) - servicePort = portN - } - - appContainers = append(appContainers, &model.AppContainer{ - ServiceName: serviceName, - ContainerName: containerName, - Port: servicePort, - Auth: auth, - }) + appInstall.ServiceName = serviceName + appInstall.ContainerName = containerName } for k, v := range changeKeys { servicesMap[v] = servicesMap[k] @@ -357,61 +277,25 @@ func (a AppService) Install(name string, appDetailId uint, params map[string]int if err != nil { return err } + appInstall.DockerCompose = string(composeByte) + fileOp := files.NewFileOp() - if err := fileOp.WriteFile(composeFilePath, strings.NewReader(string(composeByte)), 0775); err != nil { + if err := fileOp.WriteFile(appInstall.GetComposePath(), strings.NewReader(string(composeByte)), 0775); err != nil { return err } tx := global.DB.Begin() ctx := context.WithValue(context.Background(), "db", tx) - if err := appInstallRepo.Create(ctx, &appInstall); err != nil { tx.Rollback() return err } - for _, c := range appContainers { - c.AppInstallID = appInstall.ID - } - if err := appContainerRepo.BatchCreate(ctx, appContainers); err != nil { + if err := createLink(ctx, app, &appInstall, params); err != nil { tx.Rollback() return err } - if !reflect.DeepEqual(dbConfig, dto.AppDatabase{}) { - container, err := appContainerRepo.GetFirst(appContainerRepo.WithServiceName(dbConfig.ServiceName)) - if err != nil { - tx.Rollback() - return err - } - install, err := appInstallRepo.GetFirst(commonRepo.WithByID(container.AppInstallID)) - if err != nil { - tx.Rollback() - return err - } - app, err := appRepo.GetFirst(commonRepo.WithByID(install.ID)) - if err != nil { - tx.Rollback() - return err - } - var database model.Database - database.AppContainerId = container.ID - database.Dbname = dbConfig.DbName - database.Username = dbConfig.DbUser - database.Password = dbConfig.Password - database.AppInstallId = appInstall.ID - database.Key = app.Key - if err := dataBaseRepo.Create(ctx, &database); err != nil { - tx.Rollback() - return err - } - - if err := execDockerCommand(database, container, Add); err != nil { - tx.Rollback() - return err - } - } - tx.Commit() - go upApp(composeFilePath, appInstall) + go upApp(appInstall.GetComposePath(), appInstall) return nil } @@ -441,12 +325,10 @@ func (a AppService) GetServices(key string) ([]dto.AppService, error) { } var res []dto.AppService for _, install := range installs { - for _, container := range install.Containers { - res = append(res, dto.AppService{ - Label: install.Name, - Value: container.ServiceName, - }) - } + res = append(res, dto.AppService{ + Label: install.Name, + Value: install.ServiceName, + }) } return res, nil } @@ -456,10 +338,12 @@ func (a AppService) SyncInstalled(installId uint) error { if err != nil { return err } - var containerNames []string - for _, a := range appInstall.Containers { - containerNames = append(containerNames, a.ContainerName) + + containerNames, err := getContainerNames(appInstall) + if err != nil { + return err } + cli, err := docker.NewClient() if err != nil { return err diff --git a/backend/app/service/app_utils.go b/backend/app/service/app_utils.go index 260c50283..cc8017b11 100644 --- a/backend/app/service/app_utils.go +++ b/backend/app/service/app_utils.go @@ -1,6 +1,7 @@ package service import ( + "context" "encoding/json" "fmt" "github.com/1Panel-dev/1Panel/app/dto" @@ -8,11 +9,14 @@ import ( "github.com/1Panel-dev/1Panel/constant" "github.com/1Panel-dev/1Panel/global" "github.com/1Panel-dev/1Panel/utils/cmd" + "github.com/1Panel-dev/1Panel/utils/common" "github.com/1Panel-dev/1Panel/utils/compose" "github.com/1Panel-dev/1Panel/utils/files" "github.com/joho/godotenv" "github.com/pkg/errors" + "math" "path" + "reflect" "strconv" ) @@ -23,15 +27,15 @@ var ( Delete DatabaseOp = "delete" ) -func execDockerCommand(database model.Database, container model.AppContainer, op DatabaseOp) error { +func execDockerCommand(database model.Database, dbInstall model.AppInstall, op DatabaseOp) error { var auth dto.AuthParam var dbConfig dto.AppDatabase dbConfig.Password = database.Password dbConfig.DbUser = database.Username dbConfig.DbName = database.Dbname - json.Unmarshal([]byte(container.Auth), &auth) + json.Unmarshal([]byte(dbInstall.Param), &auth) execConfig := dto.ContainerExec{ - ContainerName: container.ContainerName, + ContainerName: dbInstall.ContainerName, Auth: auth, DbParam: dbConfig, } @@ -59,6 +63,118 @@ func getSqlStr(key string, operate DatabaseOp, exec dto.ContainerExec) string { return str } +func checkPort(key string, params map[string]interface{}) (int, error) { + + port, ok := params[key] + if ok { + portN := int(math.Ceil(port.(float64))) + if common.ScanPort(portN) { + return portN, errors.New("port is in used") + } else { + return portN, nil + } + } + return 0, nil +} + +func createLink(ctx context.Context, app model.App, appInstall *model.AppInstall, params map[string]interface{}) error { + var dbConfig dto.AppDatabase + if app.Type == "runtime" { + var authParam dto.AuthParam + paramByte, err := json.Marshal(params) + if err != nil { + return err + } + if err := json.Unmarshal(paramByte, &authParam); err != nil { + return err + } + authByte, err := json.Marshal(authParam) + if err != nil { + return err + } + appInstall.Param = string(authByte) + } + if app.Type == "website" { + paramByte, err := json.Marshal(params) + if err != nil { + return err + } + if err := json.Unmarshal(paramByte, &dbConfig); err != nil { + return err + } + } + + if !reflect.DeepEqual(dbConfig, dto.AppDatabase{}) { + dbInstall, err := appInstallRepo.GetFirst(appInstallRepo.WithServiceName(dbConfig.ServiceName)) + if err != nil { + return err + } + var database model.Database + database.Dbname = dbConfig.DbName + database.Username = dbConfig.DbUser + database.Password = dbConfig.Password + database.AppInstallId = dbInstall.ID + database.Key = dbInstall.App.Key + if err := dataBaseRepo.Create(ctx, &database); err != nil { + return err + } + var installResource model.AppInstallResource + installResource.ResourceId = database.ID + installResource.AppInstallId = appInstall.ID + installResource.LinkId = dbInstall.ID + installResource.Key = dbInstall.App.Key + if err := appInstallResourceRepo.Create(ctx, &installResource); err != nil { + return err + } + if err := execDockerCommand(database, dbInstall, Add); err != nil { + return err + } + } + + return nil +} + +func deleteLink(ctx context.Context, install *model.AppInstall) error { + resources, _ := appInstallResourceRepo.GetBy(appInstallResourceRepo.WithAppInstallId(install.ID)) + if len(resources) == 0 { + return nil + } + for _, re := range resources { + if re.Key == "mysql" { + database, _ := dataBaseRepo.GetFirst(commonRepo.WithByID(re.ResourceId)) + if reflect.DeepEqual(database, model.Database{}) { + continue + } + appInstall, err := appInstallRepo.GetFirst(commonRepo.WithByID(database.AppInstallId)) + if err != nil { + return nil + } + if err := execDockerCommand(database, appInstall, Delete); err != nil { + return err + } + if err := dataBaseRepo.DeleteBy(ctx, commonRepo.WithByID(database.ID)); err != nil { + return err + } + } + } + return appInstallResourceRepo.DeleteBy(ctx, appInstallResourceRepo.WithAppInstallId(install.ID)) +} + +func getContainerNames(install model.AppInstall) ([]string, error) { + composeMap := install.DockerCompose + envMap := make(map[string]string) + _ = json.Unmarshal([]byte(install.Env), &envMap) + project, err := compose.GetComposeProject([]byte(composeMap), envMap) + if err != nil { + return nil, err + } + var containerNames []string + for _, service := range project.AllServices() { + containerNames = append(containerNames, service.ContainerName) + } + return containerNames, nil +} + func checkRequiredAndLimit(app model.App) error { if app.Limit > 0 { @@ -103,7 +219,7 @@ func checkRequiredAndLimit(app model.App) error { return nil } -func copyAppData(key, version, installName string, params map[string]interface{}) (composeFilePath string, err error) { +func copyAppData(key, version, installName string, params map[string]interface{}) (err error) { resourceDir := path.Join(global.CONF.System.ResourceDir, "apps", key, version) installDir := path.Join(global.CONF.System.AppDir, key) installVersionDir := path.Join(installDir, version) @@ -115,7 +231,6 @@ func copyAppData(key, version, installName string, params map[string]interface{} if err = fileOp.Rename(installVersionDir, appDir); err != nil { return } - composeFilePath = path.Join(appDir, "docker-compose.yml") envPath := path.Join(appDir, ".env") envParams := make(map[string]string, len(params)) @@ -197,3 +312,14 @@ func getApps(oldApps []model.App, items []dto.AppDefine) map[string]model.App { } return apps } + +func handleErr(install model.AppInstall, err error, out string) error { + reErr := err + install.Message = err.Error() + if out != "" { + install.Message = out + reErr = errors.New(out) + } + _ = appInstallRepo.Save(install) + return reErr +} diff --git a/backend/app/service/entry.go b/backend/app/service/entry.go index e9c6d2403..d3ad3316d 100644 --- a/backend/app/service/entry.go +++ b/backend/app/service/entry.go @@ -18,19 +18,19 @@ type ServiceGroup struct { var ServiceGroupApp = new(ServiceGroup) var ( - hostRepo = repo.RepoGroupApp.HostRepo - backupRepo = repo.RepoGroupApp.BackupRepo - groupRepo = repo.RepoGroupApp.GroupRepo - commandRepo = repo.RepoGroupApp.CommandRepo - operationRepo = repo.RepoGroupApp.OperationRepo - commonRepo = repo.RepoGroupApp.CommonRepo - cronjobRepo = repo.RepoGroupApp.CronjobRepo - settingRepo = repo.RepoGroupApp.SettingRepo - appRepo = repo.RepoGroupApp.AppRepo - appTagRepo = repo.RepoGroupApp.AppTagRepo - appDetailRepo = repo.RepoGroupApp.AppDetailRepo - tagRepo = repo.RepoGroupApp.TagRepo - appInstallRepo = repo.RepoGroupApp.AppInstallRepo - appContainerRepo = repo.RepoGroupApp.AppContainerRepo - dataBaseRepo = repo.RepoGroupApp.DatabaseRepo + hostRepo = repo.RepoGroupApp.HostRepo + backupRepo = repo.RepoGroupApp.BackupRepo + groupRepo = repo.RepoGroupApp.GroupRepo + commandRepo = repo.RepoGroupApp.CommandRepo + operationRepo = repo.RepoGroupApp.OperationRepo + commonRepo = repo.RepoGroupApp.CommonRepo + cronjobRepo = repo.RepoGroupApp.CronjobRepo + settingRepo = repo.RepoGroupApp.SettingRepo + appRepo = repo.RepoGroupApp.AppRepo + appTagRepo = repo.RepoGroupApp.AppTagRepo + appDetailRepo = repo.RepoGroupApp.AppDetailRepo + tagRepo = repo.RepoGroupApp.TagRepo + appInstallRepo = repo.RepoGroupApp.AppInstallRepo + appInstallResourceRepo = repo.RepoGroupApp.AppInstallResourceRpo + dataBaseRepo = repo.RepoGroupApp.DatabaseRepo ) diff --git a/backend/go.mod b/backend/go.mod index 418d0d9e2..abc110275 100644 --- a/backend/go.mod +++ b/backend/go.mod @@ -5,7 +5,9 @@ go 1.18 require ( github.com/aliyun/aliyun-oss-go-sdk v2.2.5+incompatible github.com/aws/aws-sdk-go v1.44.99 + github.com/compose-spec/compose-go v1.6.0 github.com/dgraph-io/badger/v3 v3.2103.2 + github.com/docker/docker v20.10.18+incompatible github.com/fsnotify/fsnotify v1.5.4 github.com/fvbock/endless v0.0.0-20170109170031-447134032cb6 github.com/gabriel-vasile/mimetype v1.4.1 @@ -43,6 +45,7 @@ require ( golang.org/x/net v0.0.0-20220722155237-a158d28d115b golang.org/x/text v0.3.7 gopkg.in/yaml.v2 v2.4.0 + gopkg.in/yaml.v3 v3.0.1 gorm.io/driver/mysql v1.3.5 gorm.io/driver/sqlite v1.3.6 gorm.io/gorm v1.23.8 @@ -55,10 +58,10 @@ require ( github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 // indirect github.com/andybalholm/brotli v1.0.4 // indirect github.com/cespare/xxhash v1.1.0 // indirect - github.com/cespare/xxhash/v2 v2.1.1 // indirect + github.com/cespare/xxhash/v2 v2.1.2 // indirect github.com/dgraph-io/ristretto v0.1.0 // indirect + github.com/distribution/distribution/v3 v3.0.0-20220725133111-4bf3547399eb // indirect github.com/docker/distribution v2.8.1+incompatible // indirect - github.com/docker/docker v20.10.18+incompatible // indirect github.com/docker/go-connections v0.4.0 // indirect github.com/docker/go-units v0.5.0 // indirect github.com/dsnet/compress v0.0.1 // indirect @@ -84,6 +87,7 @@ require ( github.com/google/uuid v1.3.0 // indirect github.com/gorilla/securecookie v1.1.1 // indirect github.com/hashicorp/hcl v1.0.0 // indirect + github.com/imdario/mergo v0.3.13 // indirect github.com/jinzhu/inflection v1.0.0 // indirect github.com/jinzhu/now v1.1.5 // indirect github.com/jmespath/go-jmespath v0.4.0 // indirect @@ -98,12 +102,15 @@ require ( github.com/mailru/easyjson v0.7.6 // indirect github.com/mattn/go-colorable v0.1.12 // indirect github.com/mattn/go-isatty v0.0.14 // indirect + github.com/mattn/go-shellwords v1.0.12 // indirect github.com/mattn/go-sqlite3 v2.0.3+incompatible // indirect github.com/minio/md5-simd v1.1.2 // indirect github.com/minio/sha256-simd v1.0.0 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect + github.com/moby/term v0.0.0-20220808134915-39b0c02b01ae // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect + github.com/morikuni/aec v1.0.0 // indirect github.com/nwaples/rardecode/v2 v2.0.0-beta.2 // indirect github.com/opencontainers/go-digest v1.0.0 // indirect github.com/opencontainers/image-spec v1.0.2 // indirect @@ -120,17 +127,20 @@ require ( github.com/tklauser/numcpus v0.4.0 // indirect github.com/ugorji/go/codec v1.2.7 // indirect github.com/ulikunitz/xz v0.5.10 // indirect + github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f // indirect + github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect + github.com/xeipuuv/gojsonschema v1.2.0 // indirect github.com/yusufpapurcu/wmi v1.2.2 // indirect go.opencensus.io v0.23.0 // indirect go.opentelemetry.io/otel v1.0.0 // indirect go.opentelemetry.io/otel/trace v1.0.0 // indirect golang.org/x/image v0.0.0-20190802002840-cff245a6509b // indirect golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 // indirect + golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4 // indirect golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f // indirect golang.org/x/time v0.0.0-20191024005414-555d28b269f0 // indirect golang.org/x/tools v0.1.12 // indirect google.golang.org/protobuf v1.28.0 // indirect gopkg.in/ini.v1 v1.66.6 // indirect gopkg.in/natefinch/lumberjack.v2 v2.0.0 // indirect - gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/backend/go.sum b/backend/go.sum index 8072eb0aa..4b6ec5882 100644 --- a/backend/go.sum +++ b/backend/go.sum @@ -36,6 +36,8 @@ cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RX cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3fOKtUw0Xmo= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= +github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOElx5B5HZ4hJQsoJ/PvUvKRhJHDQXO8P8= +github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= @@ -60,8 +62,9 @@ github.com/aws/aws-sdk-go v1.44.99/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX4 github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= -github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE= +github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= @@ -71,12 +74,15 @@ github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDk github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= +github.com/compose-spec/compose-go v1.6.0 h1:7Ol/UULMUtbPmB0EYrETASRoum821JpOh/XaEf+hN+Q= +github.com/compose-spec/compose-go v1.6.0/go.mod h1:os+Ulh2jlZxY1XT1hbciERadjSUU/BtZ6+gcN7vD7J0= github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +github.com/creack/pty v1.1.11/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -87,6 +93,8 @@ github.com/dgraph-io/ristretto v0.1.0 h1:Jv3CGQHp9OjuMBSne1485aDpUkTKEcUqF+jm/Lu github.com/dgraph-io/ristretto v0.1.0/go.mod h1:fux0lOrBhrVCJd3lcTHsIJhq1T2rokOu6v9Vcb3Q9ug= github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2 h1:tdlZCpZ/P9DhczCTSixgIKmwPv6+wP5DGjqLYw5SUiA= github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= +github.com/distribution/distribution/v3 v3.0.0-20220725133111-4bf3547399eb h1:oCCuuU3kMO3sjZH/p7LamvQNW9SWoT4yQuMGcdSxGAE= +github.com/distribution/distribution/v3 v3.0.0-20220725133111-4bf3547399eb/go.mod h1:28YO/VJk9/64+sTGNuYaBjWxrXTPrj0C0XmgTIOjxX4= github.com/docker/distribution v2.8.1+incompatible h1:Q50tZOPR6T/hjNsyc9g8/syEs6bk8XXApsHjKukMl68= github.com/docker/distribution v2.8.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= github.com/docker/docker v20.10.18+incompatible h1:SN84VYXTBNGn92T/QwIRPlum9zfemfitN7pbsp26WSc= @@ -263,6 +271,8 @@ github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/imdario/mergo v0.3.13 h1:lFzP57bqS/wsqKssCGmtLAb8A0wKjLGrve2q3PPVcBk= +github.com/imdario/mergo v0.3.13/go.mod h1:4lJ1jqUDcsbIECGy0RUJAXNIhg+6ocWgb1ALK2O4oXg= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/jackc/chunkreader/v2 v2.0.1 h1:i+RDz65UE+mmpjTfyz0MoVTnzeYxroil2G82ki7MGG8= github.com/jackc/pgconn v1.12.1 h1:rsDFzIpRk7xT4B8FufgpCCeyjdNpKyghZeSefViE5W8= @@ -336,6 +346,8 @@ github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9 github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0= github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= +github.com/mattn/go-shellwords v1.0.12 h1:M2zGm7EW6UQJvDeQxo4T51eKPurbeFbe8WtebGE2xrk= +github.com/mattn/go-shellwords v1.0.12/go.mod h1:EZzvwXDESEeg03EKmM+RmDnNOPKG4lLtQsUlTZDWQ8Y= github.com/mattn/go-sqlite3 v1.14.12/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= github.com/mattn/go-sqlite3 v2.0.3+incompatible h1:gXHsfypPkaMZrKbD5209QV9jbUTJKjyR5WD3HYQSd+U= github.com/mattn/go-sqlite3 v2.0.3+incompatible/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= @@ -351,6 +363,8 @@ github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrk github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/moby/term v0.0.0-20220808134915-39b0c02b01ae h1:O4SWKdcHVCvYqyDV+9CJA1fcDN2L11Bule0iFy3YlAI= +github.com/moby/term v0.0.0-20220808134915-39b0c02b01ae/go.mod h1:E2VnQOmVuvZB6UYnnDB0qG5Nq/1tD9acaOpo6xmt0Kw= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= @@ -359,6 +373,8 @@ github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9G github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/mojocn/base64Captcha v1.3.5 h1:Qeilr7Ta6eDtG4S+tQuZ5+hO+QHbiGAJdi4PfoagaA0= github.com/mojocn/base64Captcha v1.3.5/go.mod h1:/tTTXn4WTpX9CfrmipqRytCpJ27Uw3G6I7NcP2WwcmY= +github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A= +github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= github.com/natefinch/lumberjack v2.0.0+incompatible h1:4QJd3OLAMgj7ph+yZTuX13Ld4UpgHp07nNdFX7mqFfM= github.com/natefinch/lumberjack v2.0.0+incompatible/go.mod h1:Wi9p2TTF5DG5oU+6YfsmYQpsTIOm0B1VNzQg9Mw6nPk= github.com/nicksnyder/go-i18n/v2 v2.1.2 h1:QHYxcUJnGHBaq7XbvgunmZ2Pn0focXFqTD61CkH146c= @@ -386,6 +402,7 @@ github.com/pelletier/go-toml/v2 v2.0.2/go.mod h1:MovirKjgVRESsAvNZlAjtFwV867yGuw github.com/pierrec/lz4/v4 v4.1.15 h1:MO0/ucJhngq7299dKLwIMtgTfbkoSPF6AoMYDd8Q4q0= github.com/pierrec/lz4/v4 v4.1.15/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= +github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/sftp v1.13.1 h1:I2qBYMChEhIjOgazfJmV3/mZM256btk6wkCDRmW7JYs= @@ -471,6 +488,12 @@ github.com/ulikunitz/xz v0.5.6/go.mod h1:2bypXElzHzzJZwzH67Y6wb67pO62Rzfn7BSiF4A github.com/ulikunitz/xz v0.5.10 h1:t92gobL9l3HE202wg3rlk19F6X+JOxl9BBrCCMYEYd8= github.com/ulikunitz/xz v0.5.10/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI= +github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f h1:J9EGpcZtP0E/raorCMxlFGSTBrsSlaDGf3jU/qvAE2c= +github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= +github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0= +github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= +github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17UxZ74= +github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= github.com/xlzd/gotp v0.0.0-20220817083547-a63b9d03d72f h1:C8De+7emQKojPBC+mXA0fr39XN5mKjRm9IUzdxI4whI= github.com/xlzd/gotp v0.0.0-20220817083547-a63b9d03d72f/go.mod h1:ndLJ3JKzi3xLmUProq4LLxCuECL93dG9WASNLpHz8qg= github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= @@ -541,7 +564,6 @@ golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3 h1:kQgndtyPBW/JIYERgdxfwMYh3AVStj88WQTlNDi2a+o= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 h1:6zppjxzCulZykYSLyVDYbneBfbaBIQPYMevg0bEwv2s= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -605,6 +627,8 @@ golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4 h1:uVc8UZUe6tr40fFVnUP5Oj+veunVezqYl9z7DYw9xzw= +golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -646,6 +670,7 @@ golang.org/x/sys v0.0.0-20210420072515-93ed5bcd2bfe/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -686,6 +711,7 @@ golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBn golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190624222133-a101b041ded4/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= @@ -725,15 +751,12 @@ golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4f golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= golang.org/x/tools v0.1.7/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo= -golang.org/x/tools v0.1.10 h1:QjFRCZxdOhBJ/UNgnBZLbNV13DlbnK0quyivTnXJM20= -golang.org/x/tools v0.1.10/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E= golang.org/x/tools v0.1.12 h1:VveCTK38A2rkS8ZqFY25HIDFscX5X9OoEhJd3quQmXU= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20220517211312-f3a8303e98df h1:5Pf6pFKu98ODmgnpvkJ3kFUOQGGLIzLIkbzUHp47618= google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= @@ -846,6 +869,7 @@ gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gorm.io/driver/mysql v1.3.5 h1:iWBTVW/8Ij5AG4e0G/zqzaJblYkBI1VIL1LG2HUGsvY= @@ -857,6 +881,8 @@ gorm.io/driver/sqlserver v1.3.2 h1:yYt8f/xdAKLY7lCCyXxIUEgZ/WsURos3dHrx8MKFGAk= gorm.io/gorm v1.23.4/go.mod h1:l2lP/RyAtc1ynaTjFksBde/O8v9oOGIApu2/xRitmZk= gorm.io/gorm v1.23.8 h1:h8sGJ+biDgBA1AD1Ha9gFCx7h8npU7AsLdlkX0n2TpE= gorm.io/gorm v1.23.8/go.mod h1:l2lP/RyAtc1ynaTjFksBde/O8v9oOGIApu2/xRitmZk= +gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk= +gotest.tools/v3 v3.3.0 h1:MfDY1b1/0xN1CyMlQDac0ziEy9zJQd9CXBRRDHw2jJo= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= diff --git a/backend/init/migration/migrations/init.go b/backend/init/migration/migrations/init.go index 96032c324..c3fc6c03f 100644 --- a/backend/init/migration/migrations/init.go +++ b/backend/init/migration/migrations/init.go @@ -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.AppInstall{}, &model.AppContainer{}, &model.Database{}) + return tx.AutoMigrate(&model.App{}, &model.AppDetail{}, &model.Tag{}, &model.AppTag{}, &model.AppInstall{}, &model.AppInstallResource{}, &model.Database{}) }, } diff --git a/backend/router/ro_app.go b/backend/router/ro_app.go index 85405bc90..9dd23ac35 100644 --- a/backend/router/ro_app.go +++ b/backend/router/ro_app.go @@ -15,14 +15,14 @@ func (a *AppRouter) InitAppRouter(Router *gin.RouterGroup) { baseApi := v1.ApiGroupApp.BaseApi { - appRouter.POST("/sync", baseApi.AppSync) - appRouter.POST("/search", baseApi.AppSearch) + appRouter.POST("/sync", baseApi.SyncApp) + appRouter.POST("/search", baseApi.SearchApp) appRouter.GET("/:id", baseApi.GetApp) appRouter.GET("/detail/:appid/:version", baseApi.GetAppDetail) appRouter.POST("/install", baseApi.InstallApp) - appRouter.POST("/installed", baseApi.PageInstalled) - appRouter.POST("/installed/op", baseApi.InstallOperate) - appRouter.POST("/installed/sync", baseApi.InstalledSync) + appRouter.POST("/installed", baseApi.SearchInstalled) + appRouter.POST("/installed/op", baseApi.OperateInstalled) + appRouter.POST("/installed/sync", baseApi.SyncInstalled) appRouter.GET("/services/:key", baseApi.GetServices) } } diff --git a/backend/utils/common/common.go b/backend/utils/common/common.go index eafc9fa89..4d0685ee6 100644 --- a/backend/utils/common/common.go +++ b/backend/utils/common/common.go @@ -78,9 +78,9 @@ func RandStr(n int) string { return string(b) } -func ScanPort(port string) bool { +func ScanPort(port int) bool { - ln, err := net.Listen("tcp", ":"+port) + ln, err := net.Listen("tcp", ":"+strconv.Itoa(port)) if err != nil { return true } diff --git a/backend/utils/compose/compose.go b/backend/utils/compose/compose.go index c98562a4b..fbdd234dd 100644 --- a/backend/utils/compose/compose.go +++ b/backend/utils/compose/compose.go @@ -1,6 +1,10 @@ package compose -import "os/exec" +import ( + "github.com/compose-spec/compose-go/loader" + "github.com/compose-spec/compose-go/types" + "os/exec" +) func Up(filePath string) (string, error) { cmd := exec.Command("docker-compose", "-f", filePath, "up", "-d") @@ -25,3 +29,24 @@ func Rmf(filePath string) (string, error) { stdout, err := cmd.CombinedOutput() return string(stdout), err } + +func GetComposeProject(yml []byte, env map[string]string) (*types.Project, error) { + var configFiles []types.ConfigFile + configFiles = append(configFiles, types.ConfigFile{ + Filename: "docker-compose.yml", + Content: yml}, + ) + details := types.ConfigDetails{ + WorkingDir: "", + ConfigFiles: configFiles, + Environment: env, + } + + project, err := loader.Load(details, func(options *loader.Options) { + + }) + if err != nil { + return nil, err + } + return project, nil +} diff --git a/frontend/src/api/interface/app.ts b/frontend/src/api/interface/app.ts index 14f1c77a7..ccffbfb6d 100644 --- a/frontend/src/api/interface/app.ts +++ b/frontend/src/api/interface/app.ts @@ -64,7 +64,6 @@ export namespace App { export interface AppInstalled extends CommonModel { name: string; - version: string; appId: string; appDetailId: string; params: string; @@ -73,7 +72,7 @@ export namespace App { message: string; appName: string; icon: string; - constainers: any[]; + app: App; } export interface AppInstalledOp {