mirror of
https://github.com/1Panel-dev/1Panel.git
synced 2025-01-19 08:19:15 +08:00
feat: 应用升级支持对比 docker-compose 文件 (#5274)
Refs https://github.com/1Panel-dev/1Panel/issues/2826
This commit is contained in:
parent
0182586869
commit
8b781d466a
@ -205,14 +205,13 @@ func (b *BaseApi) GetServices(c *gin.Context) {
|
|||||||
// @Param appInstallId path integer true "request"
|
// @Param appInstallId path integer true "request"
|
||||||
// @Success 200 {array} dto.AppVersion
|
// @Success 200 {array} dto.AppVersion
|
||||||
// @Security ApiKeyAuth
|
// @Security ApiKeyAuth
|
||||||
// @Router /apps/installed/:appInstallId/versions [get]
|
// @Router /apps/installed/update/versions [post]
|
||||||
func (b *BaseApi) GetUpdateVersions(c *gin.Context) {
|
func (b *BaseApi) GetUpdateVersions(c *gin.Context) {
|
||||||
appInstallId, err := helper.GetIntParamByKey(c, "appInstallId")
|
var req request.AppUpdateVersion
|
||||||
if err != nil {
|
if err := helper.CheckBindAndValidate(&req, c); err != nil {
|
||||||
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInternalServer, nil)
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
versions, err := appInstallService.GetUpdateVersions(appInstallId)
|
versions, err := appInstallService.GetUpdateVersions(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
|
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
|
||||||
return
|
return
|
||||||
|
@ -39,6 +39,7 @@ type AppOssConfig struct {
|
|||||||
type AppVersion struct {
|
type AppVersion struct {
|
||||||
Version string `json:"version"`
|
Version string `json:"version"`
|
||||||
DetailId uint `json:"detailId"`
|
DetailId uint `json:"detailId"`
|
||||||
|
DockerCompose string `json:"dockerCompose"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type AppList struct {
|
type AppList struct {
|
||||||
|
@ -70,6 +70,15 @@ type AppInstalledOperate struct {
|
|||||||
DeleteDB bool `json:"deleteDB"`
|
DeleteDB bool `json:"deleteDB"`
|
||||||
Backup bool `json:"backup"`
|
Backup bool `json:"backup"`
|
||||||
PullImage bool `json:"pullImage"`
|
PullImage bool `json:"pullImage"`
|
||||||
|
DockerCompose string `json:"dockerCompose"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type AppInstallUpgrade struct {
|
||||||
|
InstallID uint `json:"installId"`
|
||||||
|
DetailID uint `json:"detailId"`
|
||||||
|
Backup bool `json:"backup"`
|
||||||
|
PullImage bool `json:"pullImage"`
|
||||||
|
DockerCompose string `json:"dockerCompose"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type AppInstalledUpdate struct {
|
type AppInstalledUpdate struct {
|
||||||
@ -88,3 +97,8 @@ type PortUpdate struct {
|
|||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
Port int64 `json:"port"`
|
Port int64 `json:"port"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type AppUpdateVersion struct {
|
||||||
|
AppInstallID uint `json:"appInstallID" validate:"required"`
|
||||||
|
UpdateVersion string `json:"updateVersion"`
|
||||||
|
}
|
||||||
|
@ -31,7 +31,7 @@ type AppDTO struct {
|
|||||||
type AppDto struct {
|
type AppDto struct {
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
Key string `json:"key"`
|
Key string `json:"key"`
|
||||||
ID uint `json:"ID"`
|
ID uint `json:"id"`
|
||||||
ShortDescZh string `json:"shortDescZh"`
|
ShortDescZh string `json:"shortDescZh"`
|
||||||
ShortDescEn string `json:"shortDescEn"`
|
ShortDescEn string `json:"shortDescEn"`
|
||||||
Icon string `json:"icon"`
|
Icon string `json:"icon"`
|
||||||
@ -106,6 +106,7 @@ type AppInstallDTO struct {
|
|||||||
AppKey string `json:"appKey"`
|
AppKey string `json:"appKey"`
|
||||||
AppType string `json:"appType"`
|
AppType string `json:"appType"`
|
||||||
AppStatus string `json:"appStatus"`
|
AppStatus string `json:"appStatus"`
|
||||||
|
DockerCompose string `json:"dockerCompose"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type DatabaseConn struct {
|
type DatabaseConn struct {
|
||||||
|
@ -5,11 +5,14 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/1Panel-dev/1Panel/backend/utils/files"
|
"github.com/1Panel-dev/1Panel/backend/utils/files"
|
||||||
|
httpUtil "github.com/1Panel-dev/1Panel/backend/utils/http"
|
||||||
"github.com/docker/docker/api/types"
|
"github.com/docker/docker/api/types"
|
||||||
"gopkg.in/yaml.v3"
|
"gopkg.in/yaml.v3"
|
||||||
"math"
|
"math"
|
||||||
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
|
"path/filepath"
|
||||||
"reflect"
|
"reflect"
|
||||||
"sort"
|
"sort"
|
||||||
"strconv"
|
"strconv"
|
||||||
@ -49,7 +52,7 @@ type IAppInstallService interface {
|
|||||||
IgnoreUpgrade(req request.AppInstalledIgnoreUpgrade) error
|
IgnoreUpgrade(req request.AppInstalledIgnoreUpgrade) error
|
||||||
SyncAll(systemInit bool) error
|
SyncAll(systemInit bool) error
|
||||||
GetServices(key string) ([]response.AppService, error)
|
GetServices(key string) ([]response.AppService, error)
|
||||||
GetUpdateVersions(installId uint) ([]dto.AppVersion, error)
|
GetUpdateVersions(req request.AppUpdateVersion) ([]dto.AppVersion, error)
|
||||||
GetParams(id uint) (*response.AppConfig, error)
|
GetParams(id uint) (*response.AppConfig, error)
|
||||||
ChangeAppPort(req request.PortUpdate) error
|
ChangeAppPort(req request.PortUpdate) error
|
||||||
GetDefaultConfigByKey(key, name string) (string, error)
|
GetDefaultConfigByKey(key, name string) (string, error)
|
||||||
@ -262,7 +265,14 @@ func (a *AppInstallService) Operate(req request.AppInstalledOperate) error {
|
|||||||
case constant.Sync:
|
case constant.Sync:
|
||||||
return syncAppInstallStatus(&install)
|
return syncAppInstallStatus(&install)
|
||||||
case constant.Upgrade:
|
case constant.Upgrade:
|
||||||
return upgradeInstall(install.ID, req.DetailId, req.Backup, req.PullImage)
|
upgradeReq := request.AppInstallUpgrade{
|
||||||
|
InstallID: install.ID,
|
||||||
|
DetailID: req.DetailId,
|
||||||
|
Backup: req.Backup,
|
||||||
|
PullImage: req.PullImage,
|
||||||
|
DockerCompose: req.DockerCompose,
|
||||||
|
}
|
||||||
|
return upgradeInstall(upgradeReq)
|
||||||
case constant.Reload:
|
case constant.Reload:
|
||||||
return opNginx(install.ContainerName, constant.NginxReload)
|
return opNginx(install.ContainerName, constant.NginxReload)
|
||||||
default:
|
default:
|
||||||
@ -484,8 +494,8 @@ func (a *AppInstallService) GetServices(key string) ([]response.AppService, erro
|
|||||||
return res, nil
|
return res, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *AppInstallService) GetUpdateVersions(installId uint) ([]dto.AppVersion, error) {
|
func (a *AppInstallService) GetUpdateVersions(req request.AppUpdateVersion) ([]dto.AppVersion, error) {
|
||||||
install, err := appInstallRepo.GetFirst(commonRepo.WithByID(installId))
|
install, err := appInstallRepo.GetFirst(commonRepo.WithByID(req.AppInstallID))
|
||||||
var versions []dto.AppVersion
|
var versions []dto.AppVersion
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return versions, err
|
return versions, err
|
||||||
@ -506,9 +516,28 @@ func (a *AppInstallService) GetUpdateVersions(installId uint) ([]dto.AppVersion,
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if common.CompareVersion(detail.Version, install.Version) {
|
if common.CompareVersion(detail.Version, install.Version) {
|
||||||
|
var newCompose string
|
||||||
|
if req.UpdateVersion != "" && req.UpdateVersion == detail.Version && detail.DockerCompose == "" && !app.IsLocalApp() {
|
||||||
|
filename := filepath.Base(detail.DownloadUrl)
|
||||||
|
dockerComposeUrl := fmt.Sprintf("%s%s", strings.TrimSuffix(detail.DownloadUrl, filename), "docker-compose.yml")
|
||||||
|
statusCode, composeRes, err := httpUtil.HandleGet(dockerComposeUrl, http.MethodGet)
|
||||||
|
if err != nil {
|
||||||
|
return versions, err
|
||||||
|
}
|
||||||
|
if statusCode > 200 {
|
||||||
|
return versions, err
|
||||||
|
}
|
||||||
|
detail.DockerCompose = string(composeRes)
|
||||||
|
_ = appDetailRepo.Update(context.Background(), detail)
|
||||||
|
}
|
||||||
|
newCompose, err = getUpgradeCompose(install, detail)
|
||||||
|
if err != nil {
|
||||||
|
return versions, err
|
||||||
|
}
|
||||||
versions = append(versions, dto.AppVersion{
|
versions = append(versions, dto.AppVersion{
|
||||||
Version: detail.Version,
|
Version: detail.Version,
|
||||||
DetailId: detail.ID,
|
DetailId: detail.ID,
|
||||||
|
DockerCompose: newCompose,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -439,12 +439,65 @@ func deleteLink(ctx context.Context, install *model.AppInstall, deleteDB bool, f
|
|||||||
return appInstallResourceRepo.DeleteBy(ctx, appInstallResourceRepo.WithAppInstallId(install.ID))
|
return appInstallResourceRepo.DeleteBy(ctx, appInstallResourceRepo.WithAppInstallId(install.ID))
|
||||||
}
|
}
|
||||||
|
|
||||||
func upgradeInstall(installID uint, detailID uint, backup, pullImage bool) error {
|
func getUpgradeCompose(install model.AppInstall, detail model.AppDetail) (string, error) {
|
||||||
install, err := appInstallRepo.GetFirst(commonRepo.WithByID(installID))
|
if detail.DockerCompose == "" {
|
||||||
|
return "", nil
|
||||||
|
}
|
||||||
|
composeMap := make(map[string]interface{})
|
||||||
|
if err := yaml.Unmarshal([]byte(detail.DockerCompose), &composeMap); err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
value, ok := composeMap["services"]
|
||||||
|
if !ok {
|
||||||
|
return "", buserr.New(constant.ErrFileParse)
|
||||||
|
}
|
||||||
|
servicesMap := value.(map[string]interface{})
|
||||||
|
if len(servicesMap) == 1 {
|
||||||
|
index := 0
|
||||||
|
oldServiceName := ""
|
||||||
|
for k := range servicesMap {
|
||||||
|
oldServiceName = k
|
||||||
|
index++
|
||||||
|
if index > 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
servicesMap[install.ServiceName] = servicesMap[oldServiceName]
|
||||||
|
if install.ServiceName != oldServiceName {
|
||||||
|
delete(servicesMap, oldServiceName)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
envs := make(map[string]interface{})
|
||||||
|
if err := json.Unmarshal([]byte(install.Env), &envs); err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
config := getAppCommonConfig(envs)
|
||||||
|
if config.ContainerName == "" {
|
||||||
|
config.ContainerName = install.ContainerName
|
||||||
|
envs[constant.ContainerName] = install.ContainerName
|
||||||
|
}
|
||||||
|
config.Advanced = true
|
||||||
|
if err := addDockerComposeCommonParam(composeMap, install.ServiceName, config, envs); err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
paramByte, err := json.Marshal(envs)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
install.Env = string(paramByte)
|
||||||
|
composeByte, err := yaml.Marshal(composeMap)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
return string(composeByte), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func upgradeInstall(req request.AppInstallUpgrade) error {
|
||||||
|
install, err := appInstallRepo.GetFirst(commonRepo.WithByID(req.InstallID))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
detail, err := appDetailRepo.GetFirst(commonRepo.WithByID(detailID))
|
detail, err := appDetailRepo.GetFirst(commonRepo.WithByID(req.DetailID))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -459,7 +512,7 @@ func upgradeInstall(installID uint, detailID uint, backup, pullImage bool) error
|
|||||||
backupFile string
|
backupFile string
|
||||||
)
|
)
|
||||||
global.LOG.Infof(i18n.GetMsgWithName("UpgradeAppStart", install.Name, nil))
|
global.LOG.Infof(i18n.GetMsgWithName("UpgradeAppStart", install.Name, nil))
|
||||||
if backup {
|
if req.Backup {
|
||||||
backupRecord, err := NewIBackupService().AppBackup(dto.CommonBackup{Name: install.App.Key, DetailName: install.Name})
|
backupRecord, err := NewIBackupService().AppBackup(dto.CommonBackup{Name: install.App.Key, DetailName: install.Name})
|
||||||
if err == nil {
|
if err == nil {
|
||||||
localDir, err := loadLocalDir()
|
localDir, err := loadLocalDir()
|
||||||
@ -476,13 +529,13 @@ func upgradeInstall(installID uint, detailID uint, backup, pullImage bool) error
|
|||||||
defer func() {
|
defer func() {
|
||||||
if upErr != nil {
|
if upErr != nil {
|
||||||
global.LOG.Infof(i18n.GetMsgWithName("ErrAppUpgrade", install.Name, upErr))
|
global.LOG.Infof(i18n.GetMsgWithName("ErrAppUpgrade", install.Name, upErr))
|
||||||
if backup {
|
if req.Backup {
|
||||||
global.LOG.Infof(i18n.GetMsgWithName("AppRecover", install.Name, nil))
|
global.LOG.Infof(i18n.GetMsgWithName("AppRecover", install.Name, nil))
|
||||||
if err := NewIBackupService().AppRecover(dto.CommonRecover{Name: install.App.Key, DetailName: install.Name, Type: "app", Source: constant.ResourceLocal, File: backupFile}); err != nil {
|
if err := NewIBackupService().AppRecover(dto.CommonRecover{Name: install.App.Key, DetailName: install.Name, Type: "app", Source: constant.ResourceLocal, File: backupFile}); err != nil {
|
||||||
global.LOG.Errorf("recover app [%s] [%s] failed %v", install.App.Key, install.Name, err)
|
global.LOG.Errorf("recover app [%s] [%s] failed %v", install.App.Key, install.Name, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
existInstall, _ := appInstallRepo.GetFirst(commonRepo.WithByID(installID))
|
existInstall, _ := appInstallRepo.GetFirst(commonRepo.WithByID(req.InstallID))
|
||||||
if existInstall.ID > 0 {
|
if existInstall.ID > 0 {
|
||||||
existInstall.Status = constant.UpgradeErr
|
existInstall.Status = constant.UpgradeErr
|
||||||
existInstall.Message = upErr.Error()
|
existInstall.Message = upErr.Error()
|
||||||
@ -529,59 +582,19 @@ func upgradeInstall(installID uint, detailID uint, backup, pullImage bool) error
|
|||||||
_, _ = scriptCmd.CombinedOutput()
|
_, _ = scriptCmd.CombinedOutput()
|
||||||
}
|
}
|
||||||
|
|
||||||
composeMap := make(map[string]interface{})
|
var newCompose string
|
||||||
if upErr = yaml.Unmarshal([]byte(detail.DockerCompose), &composeMap); upErr != nil {
|
if req.DockerCompose == "" {
|
||||||
|
newCompose, upErr = getUpgradeCompose(install, detail)
|
||||||
|
if upErr != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
value, ok := composeMap["services"]
|
} else {
|
||||||
if !ok {
|
newCompose = req.DockerCompose
|
||||||
upErr = buserr.New(constant.ErrFileParse)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
servicesMap := value.(map[string]interface{})
|
|
||||||
if len(servicesMap) == 1 {
|
|
||||||
index := 0
|
|
||||||
oldServiceName := ""
|
|
||||||
for k := range servicesMap {
|
|
||||||
oldServiceName = k
|
|
||||||
index++
|
|
||||||
if index > 0 {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
servicesMap[install.ServiceName] = servicesMap[oldServiceName]
|
|
||||||
if install.ServiceName != oldServiceName {
|
|
||||||
delete(servicesMap, oldServiceName)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
envs := make(map[string]interface{})
|
|
||||||
if upErr = json.Unmarshal([]byte(install.Env), &envs); upErr != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
config := getAppCommonConfig(envs)
|
|
||||||
if config.ContainerName == "" {
|
|
||||||
config.ContainerName = install.ContainerName
|
|
||||||
envs[constant.ContainerName] = install.ContainerName
|
|
||||||
}
|
|
||||||
config.Advanced = true
|
|
||||||
if upErr = addDockerComposeCommonParam(composeMap, install.ServiceName, config, envs); upErr != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
paramByte, err := json.Marshal(envs)
|
|
||||||
if err != nil {
|
|
||||||
upErr = err
|
|
||||||
return
|
|
||||||
}
|
|
||||||
install.Env = string(paramByte)
|
|
||||||
composeByte, err := yaml.Marshal(composeMap)
|
|
||||||
if err != nil {
|
|
||||||
upErr = err
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
install.DockerCompose = string(composeByte)
|
install.DockerCompose = newCompose
|
||||||
install.Version = detail.Version
|
install.Version = detail.Version
|
||||||
install.AppDetailId = detailID
|
install.AppDetailId = req.DetailID
|
||||||
|
|
||||||
content, err := fileOp.GetContent(install.GetEnvPath())
|
content, err := fileOp.GetContent(install.GetEnvPath())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -589,7 +602,7 @@ func upgradeInstall(installID uint, detailID uint, backup, pullImage bool) error
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if pullImage {
|
if req.PullImage {
|
||||||
projectName := strings.ToLower(install.Name)
|
projectName := strings.ToLower(install.Name)
|
||||||
images, err := composeV2.GetDockerComposeImages(projectName, content, []byte(detail.DockerCompose))
|
images, err := composeV2.GetDockerComposeImages(projectName, content, []byte(detail.DockerCompose))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -621,6 +634,10 @@ func upgradeInstall(installID uint, detailID uint, backup, pullImage bool) error
|
|||||||
upErr = err
|
upErr = err
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
envs := make(map[string]interface{})
|
||||||
|
if upErr = json.Unmarshal([]byte(install.Env), &envs); upErr != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
envParams := make(map[string]string, len(envs))
|
envParams := make(map[string]string, len(envs))
|
||||||
handleMap(envs, envParams)
|
handleMap(envs, envParams)
|
||||||
if upErr = env.Write(envParams, install.GetEnvPath()); upErr != nil {
|
if upErr = env.Write(envParams, install.GetEnvPath()); upErr != nil {
|
||||||
@ -1134,6 +1151,7 @@ func synAppInstall(containers map[string]types.Container, appInstall *model.AppI
|
|||||||
if len(containers) == 0 {
|
if len(containers) == 0 {
|
||||||
appInstall.Status = constant.Error
|
appInstall.Status = constant.Error
|
||||||
appInstall.Message = buserr.WithName("ErrContainerNotFound", strings.Join(containerNames, ",")).Error()
|
appInstall.Message = buserr.WithName("ErrContainerNotFound", strings.Join(containerNames, ",")).Error()
|
||||||
|
_ = appInstallRepo.Save(context.Background(), appInstall)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
notFoundNames := make([]string, 0)
|
notFoundNames := make([]string, 0)
|
||||||
@ -1178,6 +1196,7 @@ func synAppInstall(containers map[string]types.Container, appInstall *model.AppI
|
|||||||
appInstall.Message = msg
|
appInstall.Message = msg
|
||||||
appInstall.Status = constant.UnHealthy
|
appInstall.Status = constant.UnHealthy
|
||||||
}
|
}
|
||||||
|
_ = appInstallRepo.Save(context.Background(), appInstall)
|
||||||
}
|
}
|
||||||
|
|
||||||
func handleInstalled(appInstallList []model.AppInstall, updated bool, sync bool) ([]response.AppInstallDTO, error) {
|
func handleInstalled(appInstallList []model.AppInstall, updated bool, sync bool) ([]response.AppInstallDTO, error) {
|
||||||
@ -1223,6 +1242,10 @@ func handleInstalled(appInstallList []model.AppInstall, updated bool, sync bool)
|
|||||||
AppName: installed.App.Name,
|
AppName: installed.App.Name,
|
||||||
AppKey: installed.App.Key,
|
AppKey: installed.App.Key,
|
||||||
AppType: installed.App.Type,
|
AppType: installed.App.Type,
|
||||||
|
Path: installed.GetPath(),
|
||||||
|
}
|
||||||
|
if updated {
|
||||||
|
installDTO.DockerCompose = installed.DockerCompose
|
||||||
}
|
}
|
||||||
app, err := appRepo.GetFirst(commonRepo.WithByID(installed.AppId))
|
app, err := appRepo.GetFirst(commonRepo.WithByID(installed.AppId))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -23,7 +23,6 @@ func (a *AppRouter) InitRouter(Router *gin.RouterGroup) {
|
|||||||
appRouter.GET("/details/:id", baseApi.GetAppDetailByID)
|
appRouter.GET("/details/:id", baseApi.GetAppDetailByID)
|
||||||
appRouter.POST("/install", baseApi.InstallApp)
|
appRouter.POST("/install", baseApi.InstallApp)
|
||||||
appRouter.GET("/tags", baseApi.GetAppTags)
|
appRouter.GET("/tags", baseApi.GetAppTags)
|
||||||
appRouter.GET("/installed/:appInstallId/versions", baseApi.GetUpdateVersions)
|
|
||||||
appRouter.POST("/installed/check", baseApi.CheckAppInstalled)
|
appRouter.POST("/installed/check", baseApi.CheckAppInstalled)
|
||||||
appRouter.POST("/installed/loadport", baseApi.LoadPort)
|
appRouter.POST("/installed/loadport", baseApi.LoadPort)
|
||||||
appRouter.POST("/installed/conninfo", baseApi.LoadConnInfo)
|
appRouter.POST("/installed/conninfo", baseApi.LoadConnInfo)
|
||||||
@ -39,5 +38,6 @@ func (a *AppRouter) InitRouter(Router *gin.RouterGroup) {
|
|||||||
appRouter.POST("/installed/params/update", baseApi.UpdateInstalled)
|
appRouter.POST("/installed/params/update", baseApi.UpdateInstalled)
|
||||||
appRouter.POST("/installed/ignore", baseApi.IgnoreUpgrade)
|
appRouter.POST("/installed/ignore", baseApi.IgnoreUpgrade)
|
||||||
appRouter.GET("/ignored/detail", baseApi.GetIgnoredApp)
|
appRouter.GET("/ignored/detail", baseApi.GetIgnoredApp)
|
||||||
|
appRouter.POST("/installed/update/versions", baseApi.GetUpdateVersions)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -236,4 +236,9 @@ export namespace App {
|
|||||||
version: string;
|
version: string;
|
||||||
icon: string;
|
icon: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface AppUpdateVersionReq {
|
||||||
|
appInstallID: number;
|
||||||
|
updateVersion?: string;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -79,8 +79,8 @@ export const GetAppService = (key: string | undefined) => {
|
|||||||
return http.get<App.AppService[]>(`apps/services/${key}`);
|
return http.get<App.AppService[]>(`apps/services/${key}`);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const GetAppUpdateVersions = (id: number) => {
|
export const GetAppUpdateVersions = (req: App.AppUpdateVersionReq) => {
|
||||||
return http.get<any>(`apps/installed/${id}/versions`);
|
return http.post<any>(`apps/installed/update/versions`, req);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const GetAppDefaultConfig = (key: string, name: string) => {
|
export const GetAppDefaultConfig = (key: string, name: string) => {
|
||||||
|
BIN
frontend/src/assets/images/theworld.png
Normal file
BIN
frontend/src/assets/images/theworld.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 333 B |
@ -1744,7 +1744,16 @@ const message = {
|
|||||||
showLocal: 'Show Local Application',
|
showLocal: 'Show Local Application',
|
||||||
reload: 'Reload',
|
reload: 'Reload',
|
||||||
upgradeWarn:
|
upgradeWarn:
|
||||||
'Upgrading the application will replace the docker-compose.yml file. If there is any change, please replace it after upgrading',
|
'Upgrading the application will replace the docker-compose.yml file. If there are any changes, you can click to view the file comparison',
|
||||||
|
newVersion: 'New version',
|
||||||
|
oldVersion: 'Current version',
|
||||||
|
composeDiff: 'File comparison',
|
||||||
|
showDiff: 'View comparison',
|
||||||
|
useNew: 'Use custom version',
|
||||||
|
useDefault: 'Use default version',
|
||||||
|
useCustom: 'Customize docker-compose.yml',
|
||||||
|
useCustomHelper:
|
||||||
|
'Using a custom docker-compose.yml file may cause the application upgrade to fail. If it is not necessary, do not check it',
|
||||||
},
|
},
|
||||||
website: {
|
website: {
|
||||||
website: 'Website',
|
website: 'Website',
|
||||||
|
@ -1624,7 +1624,15 @@ const message = {
|
|||||||
hostModeHelper: '目前應用網路模式為 host 模式,如需放開端口,請在防火牆頁面手動放開',
|
hostModeHelper: '目前應用網路模式為 host 模式,如需放開端口,請在防火牆頁面手動放開',
|
||||||
showLocal: '顯示本機應用程式',
|
showLocal: '顯示本機應用程式',
|
||||||
reload: '重載',
|
reload: '重載',
|
||||||
upgradeWarn: '升級應用程式會取代 docker-compose.yml 文件,如有更改,請升級之後替換',
|
upgradeWarn: '升級應用程式會取代 docker-compose.yml 文件,如有更改,可以點擊查看文件對比',
|
||||||
|
newVersion: '新版本',
|
||||||
|
oldVersion: '目前版本',
|
||||||
|
composeDiff: '文件對比',
|
||||||
|
showDiff: '看對比',
|
||||||
|
useNew: '使用自訂版本',
|
||||||
|
useDefault: '使用預設版本',
|
||||||
|
useCustom: '自訂 docker-compose.yml',
|
||||||
|
useCustomHelper: '使用自訂 docker-compose.yml 文件,可能會導致應用程式升級失敗,如無必要,請勿勾選',
|
||||||
},
|
},
|
||||||
website: {
|
website: {
|
||||||
website: '網站',
|
website: '網站',
|
||||||
|
@ -1624,7 +1624,15 @@ const message = {
|
|||||||
hostModeHelper: '当前应用网络模式为 host 模式,如需放开端口,请在防火墙页面手动放开',
|
hostModeHelper: '当前应用网络模式为 host 模式,如需放开端口,请在防火墙页面手动放开',
|
||||||
showLocal: '显示本地应用',
|
showLocal: '显示本地应用',
|
||||||
reload: '重载',
|
reload: '重载',
|
||||||
upgradeWarn: '升级应用会替换 docker-compose.yml 文件,如有更改,请升级之后替换',
|
upgradeWarn: '升级应用会替换 docker-compose.yml 文件,如有更改,可以点击查看文件对比',
|
||||||
|
newVersion: '新版本',
|
||||||
|
oldVersion: '当前版本',
|
||||||
|
composeDiff: '文件对比',
|
||||||
|
showDiff: '查看对比',
|
||||||
|
useNew: '使用自定义版本',
|
||||||
|
useDefault: '使用默认版本',
|
||||||
|
useCustom: '自定义 docker-compose.yml',
|
||||||
|
useCustomHelper: '使用自定义 docker-compose.yml 文件,可能会导致应用升级失败,如无必要,请勿勾选',
|
||||||
},
|
},
|
||||||
website: {
|
website: {
|
||||||
website: '网站',
|
website: '网站',
|
||||||
|
@ -21,10 +21,15 @@ import Components from '@/components';
|
|||||||
import ElementPlus from 'element-plus';
|
import ElementPlus from 'element-plus';
|
||||||
import Fit2CloudPlus from 'fit2cloud-ui-plus';
|
import Fit2CloudPlus from 'fit2cloud-ui-plus';
|
||||||
import * as Icons from '@element-plus/icons-vue';
|
import * as Icons from '@element-plus/icons-vue';
|
||||||
|
import VueDiff from 'vue-diff';
|
||||||
|
import 'vue-diff/dist/index.css';
|
||||||
|
import yaml from 'highlight.js/lib/languages/yaml';
|
||||||
|
VueDiff.hljs.registerLanguage('yaml', yaml);
|
||||||
|
|
||||||
const app = createApp(App);
|
const app = createApp(App);
|
||||||
app.component('SvgIcon', SvgIcon);
|
app.component('SvgIcon', SvgIcon);
|
||||||
app.use(ElementPlus);
|
app.use(ElementPlus);
|
||||||
|
app.use(VueDiff);
|
||||||
app.use(Fit2CloudPlus, { locale: i18n.global.messages.value[localStorage.getItem('lang') || 'zh'] });
|
app.use(Fit2CloudPlus, { locale: i18n.global.messages.value[localStorage.getItem('lang') || 'zh'] });
|
||||||
|
|
||||||
Object.keys(Icons).forEach((key) => {
|
Object.keys(Icons).forEach((key) => {
|
||||||
|
@ -435,7 +435,7 @@ const openOperate = (row: any, op: string) => {
|
|||||||
operateReq.installId = row.id;
|
operateReq.installId = row.id;
|
||||||
operateReq.operate = op;
|
operateReq.operate = op;
|
||||||
if (op == 'upgrade' || op == 'ignore') {
|
if (op == 'upgrade' || op == 'ignore') {
|
||||||
upgradeRef.value.acceptParams(row.id, row.name, op, row.app);
|
upgradeRef.value.acceptParams(row.id, row.name, row.dockerCompose, op, row.app);
|
||||||
} else if (op == 'delete') {
|
} else if (op == 'delete') {
|
||||||
AppInstalledDeleteCheck(row.id).then(async (res) => {
|
AppInstalledDeleteCheck(row.id).then(async (res) => {
|
||||||
const items = res.data;
|
const items = res.data;
|
||||||
|
@ -0,0 +1,88 @@
|
|||||||
|
<template>
|
||||||
|
<el-dialog
|
||||||
|
v-model="open"
|
||||||
|
:title="$t('app.composeDiff')"
|
||||||
|
:destroy-on-close="true"
|
||||||
|
:close-on-click-modal="false"
|
||||||
|
width="60%"
|
||||||
|
>
|
||||||
|
<el-row :gutter="10">
|
||||||
|
<el-col :span="11" :offset="1" class="mt-2">
|
||||||
|
<el-text type="info">{{ $t('app.oldVersion') }}</el-text>
|
||||||
|
<codemirror
|
||||||
|
placeholder=""
|
||||||
|
:indent-with-tab="true"
|
||||||
|
:tabSize="4"
|
||||||
|
style="width: 100%; height: calc(100vh - 500px)"
|
||||||
|
:lineWrapping="true"
|
||||||
|
:matchBrackets="true"
|
||||||
|
theme="cobalt"
|
||||||
|
:styleActiveLine="true"
|
||||||
|
:extensions="extensions"
|
||||||
|
v-model="oldContent"
|
||||||
|
:readOnly="true"
|
||||||
|
/>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="11" class="mt-2">
|
||||||
|
<el-text type="success">{{ $t('app.newVersion') }}</el-text>
|
||||||
|
<el-text type="warning" class="!ml-5">编辑之后点击使用自定义版本保存</el-text>
|
||||||
|
<codemirror
|
||||||
|
:autofocus="true"
|
||||||
|
placeholder=""
|
||||||
|
:indent-with-tab="true"
|
||||||
|
:tabSize="4"
|
||||||
|
style="width: 100%; height: calc(100vh - 500px)"
|
||||||
|
:lineWrapping="true"
|
||||||
|
:matchBrackets="true"
|
||||||
|
theme="cobalt"
|
||||||
|
:styleActiveLine="true"
|
||||||
|
:extensions="extensions"
|
||||||
|
v-model="newContent"
|
||||||
|
/>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
<template #footer>
|
||||||
|
<span class="dialog-footer">
|
||||||
|
<el-button @click="handleClose">{{ $t('commons.button.cancel') }}</el-button>
|
||||||
|
<el-button type="success" @click="confirm(newContent)">
|
||||||
|
{{ $t('app.useNew') }}
|
||||||
|
</el-button>
|
||||||
|
<el-button type="primary" @click="confirm('')">
|
||||||
|
{{ $t('app.useDefault') }}
|
||||||
|
</el-button>
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
</el-dialog>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { ref } from 'vue';
|
||||||
|
import { Codemirror } from 'vue-codemirror';
|
||||||
|
import { javascript } from '@codemirror/lang-javascript';
|
||||||
|
import { oneDark } from '@codemirror/theme-one-dark';
|
||||||
|
const extensions = [javascript(), oneDark];
|
||||||
|
|
||||||
|
const open = ref(false);
|
||||||
|
const newContent = ref('');
|
||||||
|
const oldContent = ref('');
|
||||||
|
const em = defineEmits(['confirm']);
|
||||||
|
|
||||||
|
const handleClose = () => {
|
||||||
|
open.value = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
const acceptParams = (oldCompose: string, newCompose: string) => {
|
||||||
|
oldContent.value = oldCompose;
|
||||||
|
newContent.value = newCompose;
|
||||||
|
open.value = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
const confirm = (content: string) => {
|
||||||
|
em('confirm', content);
|
||||||
|
handleClose();
|
||||||
|
};
|
||||||
|
|
||||||
|
defineExpose({
|
||||||
|
acceptParams,
|
||||||
|
});
|
||||||
|
</script>
|
@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<el-drawer :close-on-click-modal="false" :close-on-press-escape="false" v-model="open" size="30%">
|
<el-drawer :close-on-click-modal="false" :close-on-press-escape="false" v-model="open" size="50%">
|
||||||
<template #header>
|
<template #header>
|
||||||
<Header
|
<Header
|
||||||
:header="$t('commons.button.' + operateReq.operate)"
|
:header="$t('commons.button.' + operateReq.operate)"
|
||||||
@ -7,39 +7,9 @@
|
|||||||
:back="handleClose"
|
:back="handleClose"
|
||||||
></Header>
|
></Header>
|
||||||
</template>
|
</template>
|
||||||
<el-row>
|
<el-row :gutter="10">
|
||||||
<el-col :span="22" :offset="1">
|
<el-col :span="22" :offset="1">
|
||||||
<el-form
|
<div>
|
||||||
@submit.prevent
|
|
||||||
ref="updateRef"
|
|
||||||
:rules="rules"
|
|
||||||
label-position="top"
|
|
||||||
:model="operateReq"
|
|
||||||
v-loading="loading"
|
|
||||||
>
|
|
||||||
<el-form-item :label="$t('app.versionSelect')" prop="detailId">
|
|
||||||
<el-select v-model="operateReq.detailId">
|
|
||||||
<el-option
|
|
||||||
v-for="(version, index) in versions"
|
|
||||||
:key="index"
|
|
||||||
:value="version.detailId"
|
|
||||||
:label="version.version"
|
|
||||||
></el-option>
|
|
||||||
</el-select>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item prop="backup" v-if="operateReq.operate === 'upgrade'">
|
|
||||||
<el-checkbox v-model="operateReq.backup" :label="$t('app.backupApp')" />
|
|
||||||
<span class="input-help">{{ $t('app.backupAppHelper') }}</span>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item pro="pullImage" v-if="operateReq.operate === 'upgrade'">
|
|
||||||
<el-checkbox v-model="operateReq.pullImage" :label="$t('container.forcePull')" size="large" />
|
|
||||||
<span class="input-help">{{ $t('container.forcePullHelper') }}</span>
|
|
||||||
</el-form-item>
|
|
||||||
<el-text type="warning">{{ $t('app.upgradeWarn') }}</el-text>
|
|
||||||
</el-form>
|
|
||||||
</el-col>
|
|
||||||
<el-col :span="22" :offset="1">
|
|
||||||
<div class="descriptions">
|
|
||||||
<el-descriptions direction="vertical">
|
<el-descriptions direction="vertical">
|
||||||
<el-descriptions-item>
|
<el-descriptions-item>
|
||||||
<el-link @click="toLink(app.website)">
|
<el-link @click="toLink(app.website)">
|
||||||
@ -62,6 +32,60 @@
|
|||||||
</el-descriptions>
|
</el-descriptions>
|
||||||
</div>
|
</div>
|
||||||
</el-col>
|
</el-col>
|
||||||
|
<el-col :span="22" :offset="1">
|
||||||
|
<el-form
|
||||||
|
@submit.prevent
|
||||||
|
ref="updateRef"
|
||||||
|
:rules="rules"
|
||||||
|
label-position="top"
|
||||||
|
:model="operateReq"
|
||||||
|
v-loading="loading"
|
||||||
|
>
|
||||||
|
<el-form-item :label="$t('app.versionSelect')" prop="detailId">
|
||||||
|
<el-select v-model="operateReq.version" @change="getVersions(operateReq.version)">
|
||||||
|
<el-option
|
||||||
|
v-for="(version, index) in versions"
|
||||||
|
:key="index"
|
||||||
|
:value="version.version"
|
||||||
|
:label="version.version"
|
||||||
|
></el-option>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item prop="backup" v-if="operateReq.operate === 'upgrade'">
|
||||||
|
<el-checkbox v-model="operateReq.backup" :label="$t('app.backupApp')" />
|
||||||
|
<span class="input-help">{{ $t('app.backupAppHelper') }}</span>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item pro="pullImage" v-if="operateReq.operate === 'upgrade'">
|
||||||
|
<el-checkbox v-model="operateReq.pullImage" :label="$t('container.forcePull')" size="large" />
|
||||||
|
<span class="input-help">{{ $t('container.forcePullHelper') }}</span>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
</el-col>
|
||||||
|
|
||||||
|
<el-col :span="22" :offset="1" v-if="operateReq.operate === 'upgrade'">
|
||||||
|
<el-text type="warning">{{ $t('app.upgradeWarn') }}</el-text>
|
||||||
|
<el-button class="ml-1.5" type="text" @click="openDiff()">{{ $t('app.showDiff') }}</el-button>
|
||||||
|
<div>
|
||||||
|
<el-checkbox v-model="useNewCompose" :label="$t('app.useCustom')" size="large" />
|
||||||
|
</div>
|
||||||
|
<div v-if="useNewCompose">
|
||||||
|
<el-text type="danger">{{ $t('app.useCustomHelper') }}</el-text>
|
||||||
|
</div>
|
||||||
|
<codemirror
|
||||||
|
v-if="useNewCompose"
|
||||||
|
:autofocus="true"
|
||||||
|
placeholder=""
|
||||||
|
:indent-with-tab="true"
|
||||||
|
:tabSize="4"
|
||||||
|
style="width: 100%; height: calc(100vh - 500px); margin-top: 10px"
|
||||||
|
:lineWrapping="true"
|
||||||
|
:matchBrackets="true"
|
||||||
|
theme="cobalt"
|
||||||
|
:styleActiveLine="true"
|
||||||
|
:extensions="extensions"
|
||||||
|
v-model="newCompose"
|
||||||
|
/>
|
||||||
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
<template #footer>
|
<template #footer>
|
||||||
<span class="dialog-footer">
|
<span class="dialog-footer">
|
||||||
@ -71,6 +95,7 @@
|
|||||||
</el-button>
|
</el-button>
|
||||||
</span>
|
</span>
|
||||||
</template>
|
</template>
|
||||||
|
<Diff ref="composeDiffRef" @confirm="getNewCompose" />
|
||||||
</el-drawer>
|
</el-drawer>
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
@ -82,8 +107,14 @@ import { reactive, ref, onBeforeUnmount } from 'vue';
|
|||||||
import Header from '@/components/drawer-header/index.vue';
|
import Header from '@/components/drawer-header/index.vue';
|
||||||
import { MsgSuccess } from '@/utils/message';
|
import { MsgSuccess } from '@/utils/message';
|
||||||
import { Rules } from '@/global/form-rules';
|
import { Rules } from '@/global/form-rules';
|
||||||
|
import Diff from './diff/index.vue';
|
||||||
import bus from '../../bus';
|
import bus from '../../bus';
|
||||||
|
import { Codemirror } from 'vue-codemirror';
|
||||||
|
import { javascript } from '@codemirror/lang-javascript';
|
||||||
|
import { oneDark } from '@codemirror/theme-one-dark';
|
||||||
|
const extensions = [javascript(), oneDark];
|
||||||
|
|
||||||
|
const composeDiffRef = ref();
|
||||||
const updateRef = ref<FormInstance>();
|
const updateRef = ref<FormInstance>();
|
||||||
const open = ref(false);
|
const open = ref(false);
|
||||||
const loading = ref(false);
|
const loading = ref(false);
|
||||||
@ -94,39 +125,94 @@ const operateReq = reactive({
|
|||||||
installId: 0,
|
installId: 0,
|
||||||
backup: true,
|
backup: true,
|
||||||
pullImage: true,
|
pullImage: true,
|
||||||
|
version: '',
|
||||||
|
dockerCompose: '',
|
||||||
});
|
});
|
||||||
const resourceName = ref('');
|
const resourceName = ref('');
|
||||||
const rules = ref<any>({
|
const rules = ref<any>({
|
||||||
detailId: [Rules.requiredSelect],
|
detailId: [Rules.requiredSelect],
|
||||||
});
|
});
|
||||||
const app = ref();
|
const app = ref();
|
||||||
|
const oldContent = ref('');
|
||||||
|
const newContent = ref('');
|
||||||
const em = defineEmits(['close']);
|
const em = defineEmits(['close']);
|
||||||
const handleClose = () => {
|
const handleClose = () => {
|
||||||
open.value = false;
|
open.value = false;
|
||||||
em('close', open);
|
em('close', open);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const newCompose = ref('');
|
||||||
|
const useNewCompose = ref(false);
|
||||||
|
const appInstallID = ref(0);
|
||||||
|
|
||||||
const toLink = (link: string) => {
|
const toLink = (link: string) => {
|
||||||
window.open(link, '_blank');
|
window.open(link, '_blank');
|
||||||
};
|
};
|
||||||
|
|
||||||
const acceptParams = (id: number, name: string, op: string, appDetail: App.AppDetail) => {
|
const openDiff = () => {
|
||||||
|
composeDiffRef.value.acceptParams(oldContent.value, newContent.value);
|
||||||
|
};
|
||||||
|
|
||||||
|
const getNewCompose = (compose: string) => {
|
||||||
|
if (compose !== '') {
|
||||||
|
newCompose.value = compose;
|
||||||
|
useNewCompose.value = true;
|
||||||
|
} else {
|
||||||
|
newCompose.value = newContent.value;
|
||||||
|
useNewCompose.value = false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const initData = () => {
|
||||||
|
newCompose.value = '';
|
||||||
|
useNewCompose.value = false;
|
||||||
|
operateReq.backup = true;
|
||||||
|
operateReq.pullImage = true;
|
||||||
|
operateReq.dockerCompose = '';
|
||||||
|
};
|
||||||
|
|
||||||
|
const acceptParams = (id: number, name: string, dockerCompose: string, op: string, appDetail: App.AppDetail) => {
|
||||||
|
initData();
|
||||||
operateReq.installId = id;
|
operateReq.installId = id;
|
||||||
operateReq.operate = op;
|
operateReq.operate = op;
|
||||||
resourceName.value = name;
|
resourceName.value = name;
|
||||||
app.value = appDetail;
|
app.value = appDetail;
|
||||||
GetAppUpdateVersions(id).then((res) => {
|
oldContent.value = dockerCompose;
|
||||||
versions.value = res.data;
|
appInstallID.value = id;
|
||||||
if (res.data != null && res.data.length > 0) {
|
getVersions('');
|
||||||
operateReq.detailId = res.data[0].detailId;
|
|
||||||
}
|
|
||||||
open.value = true;
|
open.value = true;
|
||||||
});
|
};
|
||||||
|
|
||||||
|
const getVersions = async (version: string) => {
|
||||||
|
const req = {
|
||||||
|
appInstallID: appInstallID.value,
|
||||||
|
};
|
||||||
|
if (version !== '') {
|
||||||
|
req['updateVersion'] = version;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
const res = await GetAppUpdateVersions(req);
|
||||||
|
versions.value = res.data || [];
|
||||||
|
if (res.data != null && res.data.length > 0) {
|
||||||
|
let item = res.data[0];
|
||||||
|
if (version != '') {
|
||||||
|
item = res.data.find((v) => v.version === version);
|
||||||
|
}
|
||||||
|
operateReq.detailId = item.detailId;
|
||||||
|
operateReq.version = item.version;
|
||||||
|
newContent.value = item.dockerCompose;
|
||||||
|
newCompose.value = item.dockerCompose;
|
||||||
|
useNewCompose.value = false;
|
||||||
|
}
|
||||||
|
} catch (error) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
const operate = async () => {
|
const operate = async () => {
|
||||||
loading.value = true;
|
loading.value = true;
|
||||||
if (operateReq.operate === 'upgrade') {
|
if (operateReq.operate === 'upgrade') {
|
||||||
|
if (useNewCompose.value) {
|
||||||
|
operateReq.dockerCompose = newCompose.value;
|
||||||
|
}
|
||||||
await InstalledOp(operateReq)
|
await InstalledOp(operateReq)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
MsgSuccess(i18n.global.t('app.upgradeStart'));
|
MsgSuccess(i18n.global.t('app.upgradeStart'));
|
||||||
|
Loading…
x
Reference in New Issue
Block a user