From 716613a4db123ed395e55efc75934679410db8db Mon Sep 17 00:00:00 2001 From: zhengkunwang <31820853+zhengkunwang223@users.noreply.github.com> Date: Tue, 13 Aug 2024 15:28:55 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=BA=94=E7=94=A8=E5=8D=87=E7=BA=A7?= =?UTF-8?q?=E5=A4=87=E4=BB=BD=E4=BF=9D=E7=95=99=203=20=E4=BB=BD=20(#6116)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Refs https://github.com/1Panel-dev/1Panel/issues/6107 --- backend/app/dto/backup.go | 1 + backend/app/repo/backup.go | 9 ++++++++- backend/app/service/app_utils.go | 13 ++++++++++++- backend/app/service/backup.go | 15 +++++++++++++++ backend/app/service/backup_app.go | 5 ++++- frontend/src/lang/modules/en.ts | 2 +- frontend/src/lang/modules/tw.ts | 2 +- frontend/src/lang/modules/zh.ts | 2 +- 8 files changed, 43 insertions(+), 6 deletions(-) diff --git a/backend/app/dto/backup.go b/backend/app/dto/backup.go index 971c06519..48db32351 100644 --- a/backend/app/dto/backup.go +++ b/backend/app/dto/backup.go @@ -36,6 +36,7 @@ type CommonBackup struct { Name string `json:"name"` DetailName string `json:"detailName"` Secret string `json:"secret"` + FileName string `json:"fileName"` } type CommonRecover struct { Source string `json:"source" validate:"required,oneof=OSS S3 SFTP MINIO LOCAL COS KODO OneDrive WebDAV"` diff --git a/backend/app/repo/backup.go b/backend/app/repo/backup.go index 7548ba8ba..19aa09271 100644 --- a/backend/app/repo/backup.go +++ b/backend/app/repo/backup.go @@ -25,6 +25,7 @@ type IBackupRepo interface { WithByFileName(fileName string) DBOption WithByType(backupType string) DBOption WithByCronID(cronjobID uint) DBOption + WithFileNameStartWith(filePrefix string) DBOption } func NewIBackupRepo() IBackupRepo { @@ -47,7 +48,7 @@ func (u *BackupRepo) ListRecord(opts ...DBOption) ([]model.BackupRecord, error) for _, opt := range opts { db = opt(db) } - err := db.Find(&users).Error + err := db.Debug().Find(&users).Error return users, err } @@ -81,6 +82,12 @@ func (u *BackupRepo) WithByFileName(fileName string) DBOption { } } +func (u *BackupRepo) WithFileNameStartWith(filePrefix string) DBOption { + return func(g *gorm.DB) *gorm.DB { + return g.Where("file_name LIKE ?", filePrefix+"%") + } +} + func (u *BackupRepo) WithByType(backupType string) DBOption { return func(g *gorm.DB) *gorm.DB { if len(backupType) == 0 { diff --git a/backend/app/service/app_utils.go b/backend/app/service/app_utils.go index 80c740109..1197f46c0 100644 --- a/backend/app/service/app_utils.go +++ b/backend/app/service/app_utils.go @@ -516,8 +516,19 @@ func upgradeInstall(req request.AppInstallUpgrade) error { ) global.LOG.Infof(i18n.GetMsgWithName("UpgradeAppStart", install.Name, nil)) if req.Backup { - backupRecord, err := NewIBackupService().AppBackup(dto.CommonBackup{Name: install.App.Key, DetailName: install.Name}) + iBackUpService := NewIBackupService() + fileName := fmt.Sprintf("upgrade_backup_%s_%s.tar.gz", install.Name, time.Now().Format(constant.DateTimeSlimLayout)+common.RandStrAndNum(5)) + backupRecord, err := iBackUpService.AppBackup(dto.CommonBackup{Name: install.App.Key, DetailName: install.Name, FileName: fileName}) if err == nil { + backups, _ := iBackUpService.ListAppRecords(install.App.Key, install.Name, "upgrade_backup") + if len(backups) > 3 { + backupsToDelete := backups[:len(backups)-3] + var deleteIDs []uint + for _, backup := range backupsToDelete { + deleteIDs = append(deleteIDs, backup.ID) + } + _ = iBackUpService.BatchDeleteRecord(deleteIDs) + } localDir, err := loadLocalDir() if err == nil { backupFile = path.Join(localDir, backupRecord.FileDir, backupRecord.FileName) diff --git a/backend/app/service/backup.go b/backend/app/service/backup.go index f355430e1..09ac0afce 100644 --- a/backend/app/service/backup.go +++ b/backend/app/service/backup.go @@ -40,6 +40,7 @@ type IBackupService interface { DeleteRecordByName(backupType, name, detailName string, withDeleteFile bool) error BatchDeleteRecord(ids []uint) error NewClient(backup *model.BackupAccount) (cloud_storage.CloudStorageClient, error) + ListAppRecords(name, detailName, fileName string) ([]model.BackupRecord, error) ListFiles(req dto.BackupSearchFile) []string @@ -100,6 +101,20 @@ func (u *BackupService) SearchRecordsWithPage(search dto.RecordSearch) (int64, [ return total, datas, err } +func (u *BackupService) ListAppRecords(name, detailName, fileName string) ([]model.BackupRecord, error) { + records, err := backupRepo.ListRecord( + commonRepo.WithOrderBy("created_at asc"), + commonRepo.WithByName(name), + commonRepo.WithByType("app"), + backupRepo.WithFileNameStartWith(fileName), + backupRepo.WithByDetailName(detailName), + ) + if err != nil { + return nil, err + } + return records, err +} + func (u *BackupService) SearchRecordsByCronjobWithPage(search dto.RecordSearchByCronjob) (int64, []dto.BackupRecords, error) { total, records, err := backupRepo.PageRecord( search.Page, search.PageSize, diff --git a/backend/app/service/backup_app.go b/backend/app/service/backup_app.go index 2a1e0ccaf..0ff99139e 100644 --- a/backend/app/service/backup_app.go +++ b/backend/app/service/backup_app.go @@ -39,7 +39,10 @@ func (u *BackupService) AppBackup(req dto.CommonBackup) (*model.BackupRecord, er 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)) + fileName := req.FileName + if req.FileName == "" { + fileName = fmt.Sprintf("%s_%s.tar.gz", req.DetailName, timeNow+common.RandStrAndNum(5)) + } if err := handleAppBackup(&install, backupDir, fileName, "", req.Secret); err != nil { return nil, err } diff --git a/frontend/src/lang/modules/en.ts b/frontend/src/lang/modules/en.ts index 3994c15d8..33443f83d 100644 --- a/frontend/src/lang/modules/en.ts +++ b/frontend/src/lang/modules/en.ts @@ -1829,7 +1829,7 @@ const message = { appHelper: 'Please view the installation instructions of some applications on the application details page', backupApp: 'Backup application before upgrade', backupAppHelper: - 'If the upgrade fails, the backup will be automatically rolled back. Please check the failure reason in the log audit-system log', + 'If the upgrade fails, the backup will be automatically rolled back. Please check the failure reason in the log audit-system log. The backup will retain the latest 3 copies by default', delete: 'Delete', openrestyDeleteHelper: 'Forcibly deleting OpenResty will delete all websites, please confirm the risk before operation', diff --git a/frontend/src/lang/modules/tw.ts b/frontend/src/lang/modules/tw.ts index aae3a1526..0d350e1b2 100644 --- a/frontend/src/lang/modules/tw.ts +++ b/frontend/src/lang/modules/tw.ts @@ -1701,7 +1701,7 @@ const message = { ignoreList: '忽略列表', appHelper: '部分應用的安裝使用說明請在應用詳情頁查看', backupApp: '升級前備份應用', - backupAppHelper: '升級失敗會使用備份自動回滾,請在日誌審計-系統日誌中查看失敗原因', + backupAppHelper: '升級失敗會使用備份自動回滾,請在日誌審計-系統日誌中查看失敗原因,備份預設保留最新的3份', delete: '刪除', openrestyDeleteHelper: '強制刪除 OpenResty 會刪除所有的網站,請確認風險後操作', downloadLogHelper1: '即將下載 {0} 套用所有日誌,是否繼續? ', diff --git a/frontend/src/lang/modules/zh.ts b/frontend/src/lang/modules/zh.ts index 8689b6795..7d331cf26 100644 --- a/frontend/src/lang/modules/zh.ts +++ b/frontend/src/lang/modules/zh.ts @@ -1702,7 +1702,7 @@ const message = { ignoreList: '忽略列表', appHelper: '部分应用的安装使用说明请在应用详情页查看', backupApp: '升级前备份应用', - backupAppHelper: '升级失败会使用备份自动回滚,请在日志审计-系统日志中查看失败原因', + backupAppHelper: '升级失败会使用备份自动回滚,请在日志审计-系统日志中查看失败原因,备份默认保留最新的3份', delete: '删除', openrestyDeleteHelper: '强制删除 OpenResty 会删除所有的网站,请确认风险之后操作', downloadLogHelper1: '即将下载 {0} 应用所有日志,是否继续?',