fix: 解决应用升级失败没有回滚的问题 (#4677)

This commit is contained in:
zhengkunwang 2024-04-24 17:34:10 +08:00 committed by GitHub
parent 61f7374d71
commit c23dfc374f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 102 additions and 39 deletions

View File

@ -323,7 +323,7 @@ func (b *BaseApi) Backup(c *gin.Context) {
switch req.Type {
case "app":
if err := backupService.AppBackup(req); err != nil {
if _, err := backupService.AppBackup(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
return
}

View File

@ -318,7 +318,7 @@ func (b *BaseApi) UploadFiles(c *gin.Context) {
}
dir := path.Dir(paths[0])
info, err := os.Stat(dir)
_, err = os.Stat(dir)
if err != nil && os.IsNotExist(err) {
mode, err := files.GetParentMode(dir)
if err != nil {
@ -330,7 +330,7 @@ func (b *BaseApi) UploadFiles(c *gin.Context) {
return
}
}
info, err = os.Stat(dir)
info, err := os.Stat(dir)
if err != nil {
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
return

View File

@ -450,23 +450,40 @@ func upgradeInstall(installID uint, detailID uint, backup, pullImage bool) error
install.Status = constant.Upgrading
go func() {
var (
upErr error
backupFile string
)
global.LOG.Infof(i18n.GetMsgByKey("UpgradeAppStart"))
if backup {
if err = NewIBackupService().AppBackup(dto.CommonBackup{Name: install.App.Key, DetailName: install.Name}); err != nil {
global.LOG.Errorf(i18n.GetMsgWithMap("ErrAppBackup", map[string]interface{}{"name": install.Name, "err": err.Error()}))
backupRecord, err := NewIBackupService().AppBackup(dto.CommonBackup{Name: install.App.Key, DetailName: install.Name})
if err == nil {
localDir, err := loadLocalDir()
if err == nil {
backupFile = path.Join(localDir, backupRecord.FileDir, backupRecord.FileName)
} else {
global.LOG.Errorf(i18n.GetMsgWithName("ErrAppBackup", install.Name, err))
}
} else {
global.LOG.Errorf(i18n.GetMsgWithName("ErrAppBackup", install.Name, err))
}
}
var upErr error
defer func() {
if upErr != nil {
global.LOG.Infof(i18n.GetMsgWithName("ErrAppUpgrade", install.Name, upErr))
if backup {
if err := NewIBackupService().AppRecover(dto.CommonRecover{Name: install.App.Key, DetailName: install.Name, Type: "app", Source: constant.ResourceLocal}); err != 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 {
global.LOG.Errorf("recover app [%s] [%s] failed %v", install.App.Key, install.Name, err)
}
}
install.Status = constant.UpgradeErr
install.Message = upErr.Error()
_ = appInstallRepo.Save(context.Background(), &install)
existInstall, _ := appInstallRepo.GetFirst(commonRepo.WithByID(installID))
if existInstall.ID > 0 {
existInstall.Status = constant.UpgradeErr
existInstall.Message = upErr.Error()
_ = appInstallRepo.Save(context.Background(), &existInstall)
}
}
}()
@ -546,13 +563,15 @@ func upgradeInstall(installID uint, detailID uint, backup, pullImage bool) error
if upErr = addDockerComposeCommonParam(composeMap, install.ServiceName, config, envs); upErr != nil {
return
}
paramByte, upErr := json.Marshal(envs)
if upErr != nil {
paramByte, err := json.Marshal(envs)
if err != nil {
upErr = err
return
}
install.Env = string(paramByte)
composeByte, upErr := yaml.Marshal(composeMap)
if upErr != nil {
composeByte, err := yaml.Marshal(composeMap)
if err != nil {
upErr = err
return
}
@ -560,23 +579,6 @@ func upgradeInstall(installID uint, detailID uint, backup, pullImage bool) error
install.Version = detail.Version
install.AppDetailId = detailID
if out, err := compose.Down(install.GetComposePath()); err != nil {
if out != "" {
upErr = errors.New(out)
return
}
return
}
envParams := make(map[string]string, len(envs))
handleMap(envs, envParams)
if err = env.Write(envParams, install.GetEnvPath()); err != nil {
return
}
if err = runScript(&install, "upgrade"); err != nil {
return
}
content, err := fileOp.GetContent(install.GetEnvPath())
if err != nil {
upErr = err
@ -595,13 +597,34 @@ func upgradeInstall(installID uint, detailID uint, backup, pullImage bool) error
return
}
for _, image := range images {
global.LOG.Infof(i18n.GetMsgWithName("PullImageStart", image, nil))
if err = dockerCli.PullImage(image, true); err != nil {
upErr = buserr.WithNameAndErr("ErrDockerPullImage", "", err)
return
} else {
global.LOG.Infof(i18n.GetMsgByKey("PullImageSuccess"))
}
}
}
if out, err := compose.Down(install.GetComposePath()); err != nil {
if out != "" {
upErr = errors.New(out)
return
}
upErr = err
return
}
envParams := make(map[string]string, len(envs))
handleMap(envs, envParams)
if upErr = env.Write(envParams, install.GetEnvPath()); upErr != nil {
return
}
if upErr = runScript(&install, "upgrade"); upErr != nil {
return
}
if upErr = fileOp.WriteFile(install.GetComposePath(), strings.NewReader(install.DockerCompose), 0775); upErr != nil {
return
}
@ -615,6 +638,7 @@ func upgradeInstall(installID uint, detailID uint, backup, pullImage bool) error
}
install.Status = constant.Running
_ = appInstallRepo.Save(context.Background(), &install)
global.LOG.Infof(i18n.GetMsgWithName("UpgradeAppSuccess", install.Name, nil))
}()
return appInstallRepo.Save(context.Background(), &install)

View File

@ -55,7 +55,7 @@ type IBackupService interface {
WebsiteBackup(db dto.CommonBackup) error
WebsiteRecover(req dto.CommonRecover) error
AppBackup(db dto.CommonBackup) error
AppBackup(db dto.CommonBackup) (*model.BackupRecord, error)
AppRecover(req dto.CommonRecover) error
Run()

View File

@ -22,18 +22,18 @@ import (
"github.com/pkg/errors"
)
func (u *BackupService) AppBackup(req dto.CommonBackup) error {
func (u *BackupService) AppBackup(req dto.CommonBackup) (*model.BackupRecord, error) {
localDir, err := loadLocalDir()
if err != nil {
return err
return nil, err
}
app, err := appRepo.GetFirst(appRepo.WithKey(req.Name))
if err != nil {
return err
return nil, err
}
install, err := appInstallRepo.GetFirst(commonRepo.WithByName(req.DetailName), appInstallRepo.WithAppId(app.ID))
if err != nil {
return err
return nil, err
}
timeNow := time.Now().Format("20060102150405")
itemDir := fmt.Sprintf("app/%s/%s", req.Name, req.DetailName)
@ -41,7 +41,7 @@ func (u *BackupService) AppBackup(req dto.CommonBackup) error {
fileName := fmt.Sprintf("%s_%s.tar.gz", req.DetailName, timeNow+common.RandStrAndNum(5))
if err := handleAppBackup(&install, backupDir, fileName); err != nil {
return err
return nil, err
}
record := &model.BackupRecord{
@ -56,9 +56,9 @@ func (u *BackupService) AppBackup(req dto.CommonBackup) error {
if err := backupRepo.CreateRecord(record); err != nil {
global.LOG.Errorf("save backup record failed, err: %v", err)
return err
return nil, err
}
return nil
return record, nil
}
func (u *BackupService) AppRecover(req dto.CommonRecover) error {

View File

@ -31,6 +31,27 @@ func GetMsgWithMap(key string, maps map[string]interface{}) string {
}
}
func GetMsgWithName(key string, name string, err error) string {
var (
content string
dataMap = make(map[string]interface{})
)
dataMap["name"] = name
if err != nil {
dataMap["err"] = err.Error()
}
content, _ = global.I18n.Localize(&i18n.LocalizeConfig{
MessageID: key,
TemplateData: dataMap,
})
content = strings.ReplaceAll(content, "<no value>", "")
if content == "" {
return key
} else {
return content
}
}
func GetErrMsg(key string, maps map[string]interface{}) string {
var content string
if maps == nil {

View File

@ -61,6 +61,12 @@ AppStoreIsSyncing: 'The App Store is syncing, please try again later'
ErrGetCompose: "Failed to obtain docker-compose.yml file! {{ .detail }}"
ErrAppWarn: "Abnormal status, please check the log"
ErrAppParamKey: "Parameter {{ .name }} field exception"
ErrAppUpgrade: "Failed to upgrade application {{ .name }} {{ .err }}"
AppRecover: "App {{ .name }} rolled back "
PullImageStart: "Start pulling image {{ .name }}"
PullImageSuccess: "Image pulled successfully"
UpgradeAppStart: "Start upgrading application {{ .name }}"
UpgradeAppSuccess: "App {{ .name }} upgraded successfully"
#file
ErrFileCanNotRead: "File can not read"

View File

@ -62,6 +62,12 @@ AppStoreIsSyncing: '應用程式商店正在同步中,請稍後再試'
ErrGetCompose: "docker-compose.yml 檔案取得失敗!{{ .detail }}"
ErrAppWarn: "狀態異常,請查看日誌"
ErrAppParamKey: "參數 {{ .name }} 欄位異常"
ErrAppUpgrade: "應用程式 {{ .name }} 升級失敗 {{ .err }}"
AppRecover: "應用程式 {{ .name }} 回滾 "
PullImageStart: "開始拉取鏡像 {{ .name }}"
PullImageSuccess: "鏡像拉取成功"
UpgradeAppStart: "開始升級應用程式 {{ .name }}"
UpgradeAppSuccess: "應用程式 {{ .name }} 升級成功"
#file
ErrFileCanNotRead: "此文件不支持預覽"

View File

@ -61,6 +61,12 @@ AppStoreIsSyncing: '应用商店正在同步中,请稍后再试'
ErrGetCompose: "docker-compose.yml 文件获取失败!{{ .detail }}"
ErrAppWarn: "状态异常,请查看日志"
ErrAppParamKey: "参数 {{ .name }} 字段异常"
ErrAppUpgrade: "应用 {{ .name }} 升级失败 {{ .err }}"
AppRecover: "应用 {{ .name }} 回滚 "
PullImageStart: "开始拉取镜像 {{ .name }}"
PullImageSuccess: "镜像拉取成功"
UpgradeAppStart: "开始升级应用 {{ .name }}"
UpgradeAppSuccess: "应用 {{ .name }} 升级成功"
#file
ErrFileCanNotRead: "此文件不支持预览"