mirror of
https://github.com/1Panel-dev/1Panel.git
synced 2025-09-06 22:55:38 +08:00
fix: Fix the backup account synchronization exception (#8083)
This commit is contained in:
parent
9c238ce7aa
commit
b13302775e
11 changed files with 91 additions and 33 deletions
|
@ -17,7 +17,7 @@ func (b *BaseApi) CheckBackupUsed(c *gin.Context) {
|
|||
return
|
||||
}
|
||||
|
||||
if err := backupService.CheckUsed(name); err != nil {
|
||||
if err := backupService.CheckUsed(name, true); err != nil {
|
||||
helper.BadRequest(c, err)
|
||||
return
|
||||
}
|
||||
|
|
|
@ -68,13 +68,13 @@ func WithByDetailName(detailName string) DBOption {
|
|||
|
||||
func WithByType(tp string) DBOption {
|
||||
return func(g *gorm.DB) *gorm.DB {
|
||||
return g.Where("type = ?", tp)
|
||||
return g.Where("`type` = ?", tp)
|
||||
}
|
||||
}
|
||||
|
||||
func WithTypes(types []string) DBOption {
|
||||
return func(db *gorm.DB) *gorm.DB {
|
||||
return db.Where("type in (?)", types)
|
||||
return db.Where("`type` in (?)", types)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -28,7 +28,7 @@ import (
|
|||
type BackupService struct{}
|
||||
|
||||
type IBackupService interface {
|
||||
CheckUsed(name string) error
|
||||
CheckUsed(name string, isPublic bool) error
|
||||
Sync(req dto.SyncFromMaster) error
|
||||
|
||||
LoadBackupOptions() ([]dto.BackupOption, error)
|
||||
|
@ -152,7 +152,7 @@ func (u *BackupService) Create(req dto.BackupOperate) error {
|
|||
return err
|
||||
}
|
||||
}
|
||||
if req.Type != "LOCAL" {
|
||||
if req.Type != constant.Local {
|
||||
isOk, err := u.checkBackupConn(&backup)
|
||||
if err != nil || !isOk {
|
||||
return buserr.WithMap("ErrBackupCheck", map[string]interface{}{"err": err.Error()}, err)
|
||||
|
@ -212,6 +212,9 @@ func (u *BackupService) Delete(id uint) error {
|
|||
if backup.Type == constant.Local {
|
||||
return buserr.New("ErrBackupLocalDelete")
|
||||
}
|
||||
if err := u.CheckUsed(backup.Name, false); err != nil {
|
||||
return err
|
||||
}
|
||||
return backupRepo.Delete(repo.WithByID(id))
|
||||
}
|
||||
|
||||
|
@ -238,15 +241,8 @@ func (u *BackupService) Update(req dto.BackupOperate) error {
|
|||
}
|
||||
newBackup.Credential = string(itemCredential)
|
||||
if backup.Type == constant.Local {
|
||||
if newBackup.Vars != backup.Vars {
|
||||
oldPath := backup.BackupPath
|
||||
newPath := newBackup.BackupPath
|
||||
if strings.HasSuffix(newPath, "/") && newPath != "/" {
|
||||
newPath = newPath[:strings.LastIndex(newPath, "/")]
|
||||
}
|
||||
if err := files.NewFileOp().CopyDir(oldPath, newPath); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := changeLocalBackup(backup.BackupPath, newBackup.BackupPath); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -255,7 +251,7 @@ func (u *BackupService) Update(req dto.BackupOperate) error {
|
|||
return err
|
||||
}
|
||||
}
|
||||
if backup.Type != "LOCAL" {
|
||||
if backup.Type != constant.Local {
|
||||
isOk, err := u.checkBackupConn(&newBackup)
|
||||
if err != nil || !isOk {
|
||||
return buserr.WithMap("ErrBackupCheck", map[string]interface{}{"err": err.Error()}, err)
|
||||
|
@ -271,6 +267,8 @@ func (u *BackupService) Update(req dto.BackupOperate) error {
|
|||
return err
|
||||
}
|
||||
newBackup.ID = backup.ID
|
||||
newBackup.CreatedAt = backup.CreatedAt
|
||||
newBackup.UpdatedAt = backup.UpdatedAt
|
||||
if err := backupRepo.Save(&newBackup); err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -372,6 +370,8 @@ func (u *BackupService) Sync(req dto.SyncFromMaster) error {
|
|||
return buserr.New("ErrRecordNotFound")
|
||||
}
|
||||
accountItem.ID = account.ID
|
||||
accountItem.CreatedAt = account.CreatedAt
|
||||
accountItem.UpdatedAt = account.UpdatedAt
|
||||
return backupRepo.Save(&accountItem)
|
||||
default:
|
||||
return fmt.Errorf("not support such operation %s", req.Operation)
|
||||
|
@ -394,8 +394,8 @@ func (u *BackupService) LoadBackupOptions() ([]dto.BackupOption, error) {
|
|||
return data, nil
|
||||
}
|
||||
|
||||
func (u *BackupService) CheckUsed(name string) error {
|
||||
account, _ := backupRepo.Get(repo.WithByName(name), backupRepo.WithByPublic(true))
|
||||
func (u *BackupService) CheckUsed(name string, isPublic bool) error {
|
||||
account, _ := backupRepo.Get(repo.WithByName(name), backupRepo.WithByPublic(isPublic))
|
||||
if account.ID == 0 {
|
||||
return nil
|
||||
}
|
||||
|
@ -542,3 +542,38 @@ func loadBackupNamesByID(accountIDs string, downloadID uint) ([]string, string,
|
|||
}
|
||||
return accounts, downloadAccount, nil
|
||||
}
|
||||
|
||||
func changeLocalBackup(oldPath, newPath string) error {
|
||||
fileOp := files.NewFileOp()
|
||||
if fileOp.Stat(path.Join(oldPath, "app")) {
|
||||
if err := fileOp.Mv(path.Join(oldPath, "app"), newPath); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if fileOp.Stat(path.Join(oldPath, "database")) {
|
||||
if err := fileOp.Mv(path.Join(oldPath, "database"), newPath); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if fileOp.Stat(path.Join(oldPath, "directory")) {
|
||||
if err := fileOp.Mv(path.Join(oldPath, "directory"), newPath); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if fileOp.Stat(path.Join(oldPath, "system_snapshot")) {
|
||||
if err := fileOp.Mv(path.Join(oldPath, "system_snapshot"), newPath); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if fileOp.Stat(path.Join(oldPath, "website")) {
|
||||
if err := fileOp.CopyDir(path.Join(oldPath, "website"), newPath); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if fileOp.Stat(path.Join(oldPath, "log")) {
|
||||
if err := fileOp.Mv(path.Join(oldPath, "log"), newPath); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -112,7 +112,7 @@ func (u *BackupRecordService) DownloadRecord(info dto.DownloadRecord) (string, e
|
|||
}
|
||||
if exist, _ := client.Exist(srcPath); exist {
|
||||
isOK, err := client.Download(srcPath, targetPath)
|
||||
if !isOK {
|
||||
if !isOK || err != nil {
|
||||
return "", fmt.Errorf("cloud storage download failed, err: %v", err)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -256,7 +256,7 @@ func (u *DeviceService) Clean(req []dto.Clean) {
|
|||
case "task_log":
|
||||
pathItem := path.Join(global.Dir.BaseDir, logPath, item.Name)
|
||||
dropFileOrDir(pathItem)
|
||||
if len(item.Name) == 0 {
|
||||
if len(item.Name) != 0 {
|
||||
_ = taskRepo.Delete(repo.WithByType(item.Name))
|
||||
}
|
||||
case "images":
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package log
|
||||
|
||||
import (
|
||||
"github.com/1Panel-dev/1Panel/agent/constant"
|
||||
"log"
|
||||
"os"
|
||||
"path"
|
||||
|
@ -12,6 +11,7 @@ import (
|
|||
"time"
|
||||
"unsafe"
|
||||
|
||||
"github.com/1Panel-dev/1Panel/agent/constant"
|
||||
"github.com/1Panel-dev/1Panel/agent/global"
|
||||
)
|
||||
|
||||
|
@ -85,7 +85,7 @@ func NewWriterFromConfig(c *Config) (RollingWriter, error) {
|
|||
return nil, err
|
||||
}
|
||||
filepath := FilePath(c)
|
||||
file, err := os.OpenFile(filepath, os.O_RDWR|os.O_CREATE|os.O_APPEND, constant.DirPerm)
|
||||
file, err := os.OpenFile(filepath, os.O_RDWR|os.O_CREATE|os.O_APPEND, constant.FilePerm)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
@ -229,10 +229,12 @@ func (u *BackupService) Update(req dto.BackupOperate) error {
|
|||
return err
|
||||
}
|
||||
newBackup.ID = backup.ID
|
||||
newBackup.CreatedAt = backup.CreatedAt
|
||||
newBackup.UpdatedAt = backup.UpdatedAt
|
||||
if err := backupRepo.Save(&newBackup); err != nil {
|
||||
return err
|
||||
}
|
||||
go syncAccountToAgent(backup, "update")
|
||||
go syncAccountToAgent(newBackup, "update")
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
@ -62,7 +62,9 @@ var WebUrlMap = map[string]struct{}{
|
|||
"/containers/setting": {},
|
||||
"/containers/dashboard": {},
|
||||
|
||||
"/cronjobs": {},
|
||||
"/cronjobs": {},
|
||||
"/cronjobs/cronjob": {},
|
||||
"/cronjobs/library": {},
|
||||
|
||||
"/databases": {},
|
||||
"/databases/mysql": {},
|
||||
|
@ -146,7 +148,7 @@ var WebUrlMap = map[string]struct{}{
|
|||
}
|
||||
|
||||
var DynamicRoutes = []string{
|
||||
`^/containers/container/operate/[^/]+$`,
|
||||
`^/containers/container/operate/[^?]+$`,
|
||||
`^/containers/composeDetail/[^/]+$`,
|
||||
`^/databases/mysql/setting/[^/]+/[^/]+$`,
|
||||
`^/databases/postgresql/setting/[^/]+/[^/]+$`,
|
||||
|
|
|
@ -74,9 +74,13 @@
|
|||
<br />
|
||||
{{ $t('setting.refreshTime') + ':' + row.varsJson['refresh_time'] }}
|
||||
</template>
|
||||
<el-tag @click="refreshItemToken(row)" class="ml-1">
|
||||
{{ 'Token ' + $t('commons.button.refresh') }}
|
||||
</el-tag>
|
||||
<el-button
|
||||
type="primary"
|
||||
link
|
||||
icon="Refresh"
|
||||
@click="refreshItemToken(row)"
|
||||
class="ml-1"
|
||||
/>
|
||||
</el-tooltip>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
@ -279,6 +283,9 @@ const buttons = [
|
|||
},
|
||||
{
|
||||
label: i18n.global.t('commons.button.delete'),
|
||||
disabled: (row: Backup.BackupInfo) => {
|
||||
return row.type === 'LOCAL';
|
||||
},
|
||||
click: (row: Backup.BackupInfo) => {
|
||||
onDelete(row);
|
||||
},
|
||||
|
|
|
@ -51,7 +51,7 @@
|
|||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item v-if="hasAccessKey()" label="Access Key ID" prop="accessKey" :rules="Rules.requiredInput">
|
||||
<el-input v-model.trim="dialogData.rowData!.accessKey" />
|
||||
<el-input clearable v-model.trim="dialogData.rowData!.accessKey" />
|
||||
</el-form-item>
|
||||
<el-form-item v-if="hasAccessKey()" label="Secret Key" prop="credential" :rules="Rules.requiredInput">
|
||||
<el-input show-password clearable v-model.trim="dialogData.rowData!.credential" />
|
||||
|
@ -85,7 +85,7 @@
|
|||
</el-form-item>
|
||||
<div v-if="dialogData.rowData!.type === 'SFTP'">
|
||||
<el-form-item :label="$t('setting.address')" prop="varsJson.address" :rules="Rules.host">
|
||||
<el-input v-model.trim="dialogData.rowData!.varsJson['address']" />
|
||||
<el-input v-model.trim="dialogData.rowData!.varsJson['address']" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item :label="$t('commons.table.port')" prop="varsJson.port" :rules="[Rules.port]">
|
||||
<el-input-number :min="0" :max="65535" v-model.number="dialogData.rowData!.varsJson['port']" />
|
||||
|
@ -171,14 +171,14 @@
|
|||
</template>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
<el-form-item v-if="hasAccessKey()" label="Bucket" :rules="Rules.requiredInput">
|
||||
<el-form-item v-if="hasAccessKey()" label="Bucket" prop="bucket" :rules="Rules.requiredInput">
|
||||
<el-checkbox v-model="dialogData.rowData!.bucketInput" :label="$t('container.input')" />
|
||||
<el-input clearable v-if="dialogData.rowData!.bucketInput" v-model="dialogData.rowData!.bucket" />
|
||||
<div v-else class="w-full">
|
||||
<el-select class="!w-4/5" v-model="dialogData.rowData!.bucket">
|
||||
<el-option v-for="item in buckets" :key="item" :value="item" />
|
||||
</el-select>
|
||||
<el-button class="!w-1/5" plain @click="getBuckets()">
|
||||
<el-button class="!w-1/5" plain @click="getBuckets(formRef)">
|
||||
{{ $t('setting.loadBucket') }}
|
||||
</el-button>
|
||||
</div>
|
||||
|
@ -630,7 +630,15 @@ const handleClose = () => {
|
|||
drawerVisible.value = false;
|
||||
};
|
||||
|
||||
const getBuckets = async () => {
|
||||
const getBuckets = async (formEl: FormInstance | undefined) => {
|
||||
if (!formEl) return;
|
||||
const result1 = await formEl.validateField('varsJson.endpointItem', callback);
|
||||
const result2 = await formEl.validateField('accessKey', callback);
|
||||
const result3 = await formEl.validateField('credential', callback);
|
||||
const result4 = await formEl.validateField('varsJson.region', callback);
|
||||
if (!result1 || !result2 || !result3 || !result4) {
|
||||
return;
|
||||
}
|
||||
loading.value = true;
|
||||
let item = deepCopy(dialogData.value.rowData!.varsJson);
|
||||
if (dialogData.value.rowData!.type === 'KODO') {
|
||||
|
@ -668,7 +676,7 @@ const onSubmit = async (formEl: FormInstance | undefined) => {
|
|||
} else {
|
||||
dialogData.value.rowData!.varsJson['endpoint'] = itemEndpoint;
|
||||
}
|
||||
dialogData.value.rowData!.varsJson['endpointItem'] = undefined;
|
||||
dialogData.value.rowData!.varsJson['endpointItem'] = itemEndpoint;
|
||||
}
|
||||
if (isALIYUNYUN()) {
|
||||
dialogData.value.rowData!.varsJson['token'] = undefined;
|
||||
|
|
|
@ -642,6 +642,10 @@ function load18n(label: string) {
|
|||
case 'App':
|
||||
case 'System':
|
||||
return i18n.global.t('menu.' + label.toLowerCase());
|
||||
case 'RuntimeExtension':
|
||||
return i18n.global.t('website.runtime');
|
||||
case 'Image':
|
||||
return i18n.global.t('container.image');
|
||||
case 'Snapshot':
|
||||
return i18n.global.t('setting.snapshot');
|
||||
case 'AppStore':
|
||||
|
|
Loading…
Add table
Reference in a new issue