feat: 应用升级备份保留 3 份 (#6116)

Refs https://github.com/1Panel-dev/1Panel/issues/6107
pull/6119/head
zhengkunwang 2024-08-13 15:28:55 +08:00 committed by GitHub
parent 12eaa66bc5
commit 716613a4db
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 43 additions and 6 deletions

View File

@ -36,6 +36,7 @@ type CommonBackup struct {
Name string `json:"name"` Name string `json:"name"`
DetailName string `json:"detailName"` DetailName string `json:"detailName"`
Secret string `json:"secret"` Secret string `json:"secret"`
FileName string `json:"fileName"`
} }
type CommonRecover struct { type CommonRecover struct {
Source string `json:"source" validate:"required,oneof=OSS S3 SFTP MINIO LOCAL COS KODO OneDrive WebDAV"` Source string `json:"source" validate:"required,oneof=OSS S3 SFTP MINIO LOCAL COS KODO OneDrive WebDAV"`

View File

@ -25,6 +25,7 @@ type IBackupRepo interface {
WithByFileName(fileName string) DBOption WithByFileName(fileName string) DBOption
WithByType(backupType string) DBOption WithByType(backupType string) DBOption
WithByCronID(cronjobID uint) DBOption WithByCronID(cronjobID uint) DBOption
WithFileNameStartWith(filePrefix string) DBOption
} }
func NewIBackupRepo() IBackupRepo { func NewIBackupRepo() IBackupRepo {
@ -47,7 +48,7 @@ func (u *BackupRepo) ListRecord(opts ...DBOption) ([]model.BackupRecord, error)
for _, opt := range opts { for _, opt := range opts {
db = opt(db) db = opt(db)
} }
err := db.Find(&users).Error err := db.Debug().Find(&users).Error
return users, err 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 { func (u *BackupRepo) WithByType(backupType string) DBOption {
return func(g *gorm.DB) *gorm.DB { return func(g *gorm.DB) *gorm.DB {
if len(backupType) == 0 { if len(backupType) == 0 {

View File

@ -516,8 +516,19 @@ func upgradeInstall(req request.AppInstallUpgrade) error {
) )
global.LOG.Infof(i18n.GetMsgWithName("UpgradeAppStart", install.Name, nil)) global.LOG.Infof(i18n.GetMsgWithName("UpgradeAppStart", install.Name, nil))
if req.Backup { 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 { 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() localDir, err := loadLocalDir()
if err == nil { if err == nil {
backupFile = path.Join(localDir, backupRecord.FileDir, backupRecord.FileName) backupFile = path.Join(localDir, backupRecord.FileDir, backupRecord.FileName)

View File

@ -40,6 +40,7 @@ type IBackupService interface {
DeleteRecordByName(backupType, name, detailName string, withDeleteFile bool) error DeleteRecordByName(backupType, name, detailName string, withDeleteFile bool) error
BatchDeleteRecord(ids []uint) error BatchDeleteRecord(ids []uint) error
NewClient(backup *model.BackupAccount) (cloud_storage.CloudStorageClient, error) NewClient(backup *model.BackupAccount) (cloud_storage.CloudStorageClient, error)
ListAppRecords(name, detailName, fileName string) ([]model.BackupRecord, error)
ListFiles(req dto.BackupSearchFile) []string ListFiles(req dto.BackupSearchFile) []string
@ -100,6 +101,20 @@ func (u *BackupService) SearchRecordsWithPage(search dto.RecordSearch) (int64, [
return total, datas, err 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) { func (u *BackupService) SearchRecordsByCronjobWithPage(search dto.RecordSearchByCronjob) (int64, []dto.BackupRecords, error) {
total, records, err := backupRepo.PageRecord( total, records, err := backupRepo.PageRecord(
search.Page, search.PageSize, search.Page, search.PageSize,

View File

@ -39,7 +39,10 @@ func (u *BackupService) AppBackup(req dto.CommonBackup) (*model.BackupRecord, er
itemDir := fmt.Sprintf("app/%s/%s", req.Name, req.DetailName) itemDir := fmt.Sprintf("app/%s/%s", req.Name, req.DetailName)
backupDir := path.Join(localDir, itemDir) 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 { if err := handleAppBackup(&install, backupDir, fileName, "", req.Secret); err != nil {
return nil, err return nil, err
} }

View File

@ -1829,7 +1829,7 @@ const message = {
appHelper: 'Please view the installation instructions of some applications on the application details page', appHelper: 'Please view the installation instructions of some applications on the application details page',
backupApp: 'Backup application before upgrade', backupApp: 'Backup application before upgrade',
backupAppHelper: 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', delete: 'Delete',
openrestyDeleteHelper: openrestyDeleteHelper:
'Forcibly deleting OpenResty will delete all websites, please confirm the risk before operation', 'Forcibly deleting OpenResty will delete all websites, please confirm the risk before operation',

View File

@ -1701,7 +1701,7 @@ const message = {
ignoreList: '', ignoreList: '',
appHelper: '使', appHelper: '使',
backupApp: '', backupApp: '',
backupAppHelper: '使,-', backupAppHelper: '使,-3',
delete: '', delete: '',
openrestyDeleteHelper: ' OpenResty ', openrestyDeleteHelper: ' OpenResty ',
downloadLogHelper1: ' {0} ', downloadLogHelper1: ' {0} ',

View File

@ -1702,7 +1702,7 @@ const message = {
ignoreList: '', ignoreList: '',
appHelper: '使', appHelper: '使',
backupApp: '', backupApp: '',
backupAppHelper: '使,-', backupAppHelper: '使,-3',
delete: '', delete: '',
openrestyDeleteHelper: ' OpenResty ', openrestyDeleteHelper: ' OpenResty ',
downloadLogHelper1: ' {0} ', downloadLogHelper1: ' {0} ',