Skip to content

Commit

Permalink
fix: 解决应用升级失败没有回滚的问题 (#4677)
Browse files Browse the repository at this point in the history
  • Loading branch information
zhengkunwang223 committed Apr 24, 2024
1 parent 61f7374 commit c23dfc3
Show file tree
Hide file tree
Showing 9 changed files with 102 additions and 39 deletions.
2 changes: 1 addition & 1 deletion backend/app/api/v1/backup.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Expand Down
4 changes: 2 additions & 2 deletions backend/app/api/v1/file.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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
Expand Down
80 changes: 52 additions & 28 deletions backend/app/service/app_utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
}
}()

Expand Down Expand Up @@ -546,37 +563,22 @@ 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
}

install.DockerCompose = string(composeByte)
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
Expand All @@ -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
}
Expand All @@ -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)
Expand Down
2 changes: 1 addition & 1 deletion backend/app/service/backup.go
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down
14 changes: 7 additions & 7 deletions backend/app/service/backup_app.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,26 +22,26 @@ 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)
backupDir := path.Join(localDir, itemDir)

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{
Expand All @@ -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 {
Expand Down
21 changes: 21 additions & 0 deletions backend/i18n/i18n.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
6 changes: 6 additions & 0 deletions backend/i18n/lang/en.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
6 changes: 6 additions & 0 deletions backend/i18n/lang/zh-Hant.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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: "此文件不支持預覽"
Expand Down
6 changes: 6 additions & 0 deletions backend/i18n/lang/zh.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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: "此文件不支持预览"
Expand Down

0 comments on commit c23dfc3

Please sign in to comment.