diff --git a/backend/app/api/v1/container.go b/backend/app/api/v1/container.go index 56cac8cfe..4ba8e1197 100644 --- a/backend/app/api/v1/container.go +++ b/backend/app/api/v1/container.go @@ -715,7 +715,7 @@ func (b *BaseApi) ComposeUpdate(c *gin.Context) { // @Param follow query string false "是否追踪" // @Param tail query string false "显示行号" // @Security ApiKeyAuth -// @Router /containers/compose/search/log [post] +// @Router /containers/compose/search/log [get] func (b *BaseApi) ComposeLogs(c *gin.Context) { wsConn, err := upGrader.Upgrade(c.Writer, c.Request, nil) if err != nil { diff --git a/backend/app/dto/request/runtime.go b/backend/app/dto/request/runtime.go index eb26c3706..7838e58da 100644 --- a/backend/app/dto/request/runtime.go +++ b/backend/app/dto/request/runtime.go @@ -25,6 +25,7 @@ type RuntimeCreate struct { type NodeConfig struct { Install bool `json:"install"` Clean bool `json:"clean"` + Port int `json:"port"` } type RuntimeDelete struct { diff --git a/backend/app/dto/response/runtime.go b/backend/app/dto/response/runtime.go index 456661f68..09cb251b9 100644 --- a/backend/app/dto/response/runtime.go +++ b/backend/app/dto/response/runtime.go @@ -21,6 +21,8 @@ type RuntimeDTO struct { CreatedAt time.Time `json:"createdAt"` CodeDir string `json:"codeDir"` AppParams []AppParam `json:"appParams"` + Port int `json:"port"` + Path string `json:"path"` } type PackageScripts struct { @@ -41,5 +43,7 @@ func NewRuntimeDTO(runtime model.Runtime) RuntimeDTO { CreatedAt: runtime.CreatedAt, CodeDir: runtime.CodeDir, Version: runtime.Version, + Port: runtime.Port, + Path: runtime.GetPath(), } } diff --git a/backend/app/model/runtime.go b/backend/app/model/runtime.go index 937c367ae..d71051a44 100644 --- a/backend/app/model/runtime.go +++ b/backend/app/model/runtime.go @@ -18,6 +18,7 @@ type Runtime struct { Type string `gorm:"type:varchar;not null" json:"type"` Status string `gorm:"type:varchar;not null" json:"status"` Resource string `gorm:"type:varchar;not null" json:"resource"` + Port int `gorm:"type:integer;" json:"port"` Message string `gorm:"type:longtext;" json:"message"` CodeDir string `gorm:"type:varchar;" json:"codeDir"` } diff --git a/backend/app/repo/runtime.go b/backend/app/repo/runtime.go index 614f30a69..489743c62 100644 --- a/backend/app/repo/runtime.go +++ b/backend/app/repo/runtime.go @@ -17,6 +17,7 @@ type IRuntimeRepo interface { WithNotId(id uint) DBOption WithStatus(status string) DBOption WithDetailId(id uint) DBOption + WithPort(port int) DBOption Page(page, size int, opts ...DBOption) (int64, []model.Runtime, error) Create(ctx context.Context, runtime *model.Runtime) error Save(runtime *model.Runtime) error @@ -59,6 +60,12 @@ func (r *RuntimeRepo) WithNotId(id uint) DBOption { } } +func (r *RuntimeRepo) WithPort(port int) DBOption { + return func(g *gorm.DB) *gorm.DB { + return g.Where("port = ?", port) + } +} + func (r *RuntimeRepo) Page(page, size int, opts ...DBOption) (int64, []model.Runtime, error) { var runtimes []model.Runtime db := getDb(opts...).Model(&model.Runtime{}) diff --git a/backend/app/service/app_utils.go b/backend/app/service/app_utils.go index 5c19f9db4..ef8b0d912 100644 --- a/backend/app/service/app_utils.go +++ b/backend/app/service/app_utils.go @@ -82,6 +82,33 @@ func checkPort(key string, params map[string]interface{}) (int, error) { return 0, nil } +func checkPortExist(port int) error { + errMap := make(map[string]interface{}) + errMap["port"] = port + appInstall, _ := appInstallRepo.GetFirst(appInstallRepo.WithPort(port)) + if appInstall.ID > 0 { + errMap["type"] = i18n.GetMsgByKey("TYPE_APP") + errMap["name"] = appInstall.Name + return buserr.WithMap("ErrPortExist", errMap, nil) + } + runtime, _ := runtimeRepo.GetFirst(runtimeRepo.WithPort(port)) + if runtime != nil { + errMap["type"] = i18n.GetMsgByKey("TYPE_RUNTIME") + errMap["name"] = runtime.Name + return buserr.WithMap("ErrPortExist", errMap, nil) + } + domain, _ := websiteDomainRepo.GetFirst(websiteDomainRepo.WithPort(port)) + if domain.ID > 0 { + errMap["type"] = i18n.GetMsgByKey("TYPE_DOMAIN") + errMap["name"] = domain.Domain + return buserr.WithMap("ErrPortExist", errMap, nil) + } + if common.ScanPort(port) { + return buserr.WithDetail(constant.ErrPortInUsed, port, nil) + } + return nil +} + var DatabaseKeys = map[string]uint{ "mysql": 3306, "mariadb": 3306, @@ -559,6 +586,8 @@ func handleMap(params map[string]interface{}, envParams map[string]string) { envParams[k] = strconv.FormatFloat(t, 'f', -1, 32) case uint: envParams[k] = strconv.Itoa(int(t)) + case int: + envParams[k] = strconv.Itoa(t) default: envParams[k] = t.(string) } diff --git a/backend/app/service/runtime.go b/backend/app/service/runtime.go index 163337290..00a6b419f 100644 --- a/backend/app/service/runtime.go +++ b/backend/app/service/runtime.go @@ -39,7 +39,16 @@ func NewRuntimeService() IRuntimeService { } func (r *RuntimeService) Create(create request.RuntimeCreate) (err error) { - exist, _ := runtimeRepo.GetFirst(runtimeRepo.WithName(create.Name), commonRepo.WithByType(create.Type)) + var ( + opts []repo.DBOption + ) + if create.Name != "" { + opts = append(opts, commonRepo.WithLikeName(create.Name)) + } + if create.Type != "" { + opts = append(opts, commonRepo.WithByType(create.Type)) + } + exist, _ := runtimeRepo.GetFirst(opts...) if exist != nil { return buserr.New(constant.ErrNameIsExist) } @@ -66,6 +75,9 @@ func (r *RuntimeService) Create(create request.RuntimeCreate) (err error) { return buserr.New(constant.ErrPathNotFound) } create.Install = true + if err = checkPortExist(create.Port); err != nil { + return err + } } appDetail, err := appDetailRepo.GetFirst(commonRepo.WithByID(create.AppDetailID)) @@ -98,6 +110,7 @@ func (r *RuntimeService) Create(create request.RuntimeCreate) (err error) { return } case constant.RuntimeNode: + runtime.Port = create.Port if err = handleNode(create, runtime, fileOp, appVersionDir); err != nil { return } @@ -286,6 +299,13 @@ func (r *RuntimeService) Update(req request.RuntimeUpdate) error { if exist != nil { return buserr.New(constant.ErrImageExist) } + case constant.RuntimeNode: + if runtime.Port != req.Port { + if err = checkPortExist(req.Port); err != nil { + return err + } + runtime.Port = req.Port + } } projectDir := path.Join(constant.RuntimeDir, runtime.Type, runtime.Name) @@ -296,6 +316,9 @@ func (r *RuntimeService) Update(req request.RuntimeUpdate) error { Params: req.Params, CodeDir: req.CodeDir, Version: req.Version, + NodeConfig: request.NodeConfig{ + Port: req.Port, + }, } composeContent, envContent, _, err := handleParams(create, projectDir) if err != nil { @@ -321,6 +344,7 @@ func (r *RuntimeService) Update(req request.RuntimeUpdate) error { case constant.RuntimeNode: runtime.Version = req.Version runtime.CodeDir = req.CodeDir + runtime.Port = req.Port runtime.Status = constant.RuntimeReCreating _ = runtimeRepo.Save(runtime) go reCreateRuntime(runtime) diff --git a/backend/app/service/runtime_utils.go b/backend/app/service/runtime_utils.go index f1563eef6..95a2196f8 100644 --- a/backend/app/service/runtime_utils.go +++ b/backend/app/service/runtime_utils.go @@ -304,6 +304,7 @@ func handleParams(create request.RuntimeCreate, projectDir string) (composeConte case constant.RuntimeNode: create.Params["CODE_DIR"] = create.CodeDir create.Params["NODE_VERSION"] = create.Version + create.Params["PANEL_APP_PORT_HTTP"] = create.Port if create.NodeConfig.Install { create.Params["RUN_INSTALL"] = "1" } else { diff --git a/backend/i18n/lang/en.yaml b/backend/i18n/lang/en.yaml index 123aeb127..6f96b2841 100644 --- a/backend/i18n/lang/en.yaml +++ b/backend/i18n/lang/en.yaml @@ -14,6 +14,10 @@ ErrNameIsExist: "Name is already exist" ErrDemoEnvironment: "Demo server, prohibit this operation!" ErrCmdTimeout: "Command execution timed out!" ErrCmdIllegal: "The command contains illegal characters. Please modify and try again!" +ErrPortExist: '{{ .port }} port is already occupied by {{ .type }} [{{ .name }}]' +TYPE_APP: "Application" +TYPE_RUNTIME: "Runtime environment" +TYPE_DOMAIN: "Domain name" #app ErrPortInUsed: "{{ .detail }} port already in use" diff --git a/backend/i18n/lang/zh-Hant.yaml b/backend/i18n/lang/zh-Hant.yaml index e2bb4e071..2a36cd4b9 100644 --- a/backend/i18n/lang/zh-Hant.yaml +++ b/backend/i18n/lang/zh-Hant.yaml @@ -14,6 +14,10 @@ ErrNameIsExist: "名稱已存在" ErrDemoEnvironment: "演示伺服器,禁止此操作!" ErrCmdTimeout: "指令執行超時!" ErrCmdIllegal: "執行命令中存在不合法字符,請修改後重試!" +ErrPortExist: '{{ .port }} 埠已被 {{ .type }} [{{ .name }}] 佔用' +TYPE_APP: "應用" +TYPE_RUNTIME: "運作環境" +TYPE_DOMAIN: "網域名稱" #app ErrPortInUsed: "{{ .detail }} 端口已被佔用!" diff --git a/backend/i18n/lang/zh.yaml b/backend/i18n/lang/zh.yaml index 95420123d..8184db9fb 100644 --- a/backend/i18n/lang/zh.yaml +++ b/backend/i18n/lang/zh.yaml @@ -14,6 +14,10 @@ ErrNameIsExist: "名称已存在" ErrDemoEnvironment: "演示服务器,禁止此操作!" ErrCmdTimeout: "命令执行超时!" ErrCmdIllegal: "执行命令中存在不合法字符,请修改后重试!" +ErrPortExist: '{{ .port }} 端口已被 {{ .type }} [{{ .name }}] 占用' +TYPE_APP: "应用" +TYPE_RUNTIME: "运行环境" +TYPE_DOMAIN: "域名" #app ErrPortInUsed: "{{ .detail }} 端口已被占用!" diff --git a/backend/init/migration/migrations/v_1_7.go b/backend/init/migration/migrations/v_1_7.go index 6f1816795..3d824435d 100644 --- a/backend/init/migration/migrations/v_1_7.go +++ b/backend/init/migration/migrations/v_1_7.go @@ -17,7 +17,7 @@ var AddDefaultNetwork = &gormigrate.Migration{ } var UpdateRuntime = &gormigrate.Migration{ - ID: "20230920-update-runtime", + ID: "20230927-update-runtime", Migrate: func(tx *gorm.DB) error { if err := tx.AutoMigrate(&model.Runtime{}); err != nil { return err diff --git a/frontend/src/api/interface/runtime.ts b/frontend/src/api/interface/runtime.ts index 82075a8d1..ca22905e6 100644 --- a/frontend/src/api/interface/runtime.ts +++ b/frontend/src/api/interface/runtime.ts @@ -14,6 +14,7 @@ export namespace Runtime { version: string; status: string; codeDir: string; + port: number; } export interface RuntimeReq extends ReqPage { @@ -35,6 +36,7 @@ export namespace Runtime { appParams: App.InstallParams[]; appID: number; source?: string; + path?: string; } export interface RuntimeCreate { @@ -50,6 +52,7 @@ export namespace Runtime { rebuild?: boolean; source?: string; codeDir?: string; + port?: number; } export interface RuntimeUpdate { diff --git a/frontend/src/views/app-store/installed/index.vue b/frontend/src/views/app-store/installed/index.vue index 181d72dcc..5ee6ce27e 100644 --- a/frontend/src/views/app-store/installed/index.vue +++ b/frontend/src/views/app-store/installed/index.vue @@ -13,7 +13,7 @@ > {{ $t('app.all') }} -