feat: 删除 app_container ,修改安装逻辑

This commit is contained in:
zhengkunwang223 2022-10-11 16:27:58 +08:00 committed by zhengkunwang223
parent 12617f95dd
commit c65afb7083
23 changed files with 377 additions and 313 deletions

View File

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

View File

@ -6,7 +6,6 @@ services:
container_name: ${CONTAINER_NAME}
restart: always
environment:
TZ: ${TZ}
MYSQL_ROOT_PASSWORD: ${PANEL_DB_ROOT_PASSWORD}
networks:
- 1panel

View File

@ -6,7 +6,6 @@ services:
container_name: ${CONTAINER_NAME}
restart: always
environment:
TZ: ${TZ}
MYSQL_ROOT_PASSWORD: ${PANEL_DB_ROOT_PASSWORD}
networks:
- 1panel

View File

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

View File

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

View File

@ -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;"`
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:"-"`
Containers []AppContainer `json:"containers"`
}
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
}

View File

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

View File

@ -2,7 +2,6 @@ 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"`

View File

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

View File

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

View File

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

View File

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

View File

@ -14,7 +14,7 @@ type RepoGroup struct {
TagRepo
AppDetailRepo
AppInstallRepo
AppContainerRepo
AppInstallResourceRpo
DatabaseRepo
}

View File

@ -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)
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
}
if dir != 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
}
}
tx := global.DB.Begin()
ctx := context.WithValue(context.Background(), "db", tx)
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,13 +325,11 @@ 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,
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

View File

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

View File

@ -31,6 +31,6 @@ var (
appDetailRepo = repo.RepoGroupApp.AppDetailRepo
tagRepo = repo.RepoGroupApp.TagRepo
appInstallRepo = repo.RepoGroupApp.AppInstallRepo
appContainerRepo = repo.RepoGroupApp.AppContainerRepo
appInstallResourceRepo = repo.RepoGroupApp.AppInstallResourceRpo
dataBaseRepo = repo.RepoGroupApp.DatabaseRepo
)

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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