Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions agent/app/service/backup_postgresql.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ func handlePostgresqlBackup(db DatabaseHelper, parentTask *task.Task, recordID u
}
}

itemHandler := func() error { return doPostgresqlgBackup(db, targetDir, fileName, secret) }
itemHandler := func() error { return doPostgresqlgBackup(db, targetDir, fileName, secret, backupTask) }
if parentTask != nil {
return itemHandler()
}
Expand Down Expand Up @@ -189,17 +189,19 @@ func handlePostgresqlRecover(req dto.CommonRecover, parentTask *task.Task, isRol
return nil
}

func doPostgresqlgBackup(db DatabaseHelper, targetDir, fileName, secret string) error {
func doPostgresqlgBackup(db DatabaseHelper, targetDir, fileName, secret string, task *task.Task) error {
cli, err := LoadPostgresqlClientByFrom(db.Database)
if err != nil {
return err
}
defer cli.Close()
backupInfo := pgclient.BackupInfo{
Database: db.Database,
Name: db.Name,
TargetDir: targetDir,
FileName: fileName,

Task: task,
Timeout: 300,
}
if err := cli.Backup(backupInfo); err != nil {
Expand Down
2 changes: 1 addition & 1 deletion agent/app/service/cronjob_backup.go
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@
return nil
}

func (u *CronjobService) handleDatabase(cronjob model.Cronjob, startTime time.Time, taskItem *task.Task) error {

Check failure on line 144 in agent/app/service/cronjob_backup.go

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Refactor this method to reduce its Cognitive Complexity from 41 to the 15 allowed.

See more on https://sonarcloud.io/project/issues?id=1Panel-dev_1Panel&issues=AZq00rK73glehZHkWmdt&open=AZq00rK73glehZHkWmdt&pullRequest=11048
dbs := loadDbsForJob(cronjob)
if len(dbs) == 0 {
addSkipTask("Database", taskItem)
Expand Down Expand Up @@ -178,7 +178,7 @@
}
}
} else {
if err := doPostgresqlgBackup(dbInfo, backupDir, record.FileName, cronjob.Secret); err != nil {
if err := doPostgresqlgBackup(dbInfo, backupDir, record.FileName, cronjob.Secret, taskItem); err != nil {
if retry < int(cronjob.RetryTimes) || !cronjob.IgnoreErr {
retry++
return err
Expand Down
2 changes: 2 additions & 0 deletions agent/i18n/lang/en.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,8 @@ ErrDatabaseIsExist: 'The current database already exists, please re-enter'
ErrExecTimeOut: 'SQL execution timed out, please check the database'
ErrRemoteExist: 'The remote database already exists with this name, please modify it and try again'
ErrLocalExist: 'The name already exists in the local database, please modify it and try again'
RemoteBackup: "To back up the remote database, the local container database service needs to be started first using the image {{ .name }}, please wait..."
RemoteRecover: "To restore the remote database, the local container database service needs to be started first using the image {{ .name }}, please wait..."

#redis
ErrTypeOfRedis: 'The recovery file type does not match the current persistence method, please modify it and try again'
Expand Down
2 changes: 2 additions & 0 deletions agent/i18n/lang/es-ES.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,8 @@ ErrDatabaseIsExist: 'La base de datos actual ya existe, intente con otro nombre'
ErrExecTimeOut: 'Tiempo de espera en la ejecución SQL, revise la base de datos'
ErrRemoteExist: 'La base de datos remota ya existe con ese nombre, modifíquelo e intente de nuevo'
ErrLocalExist: 'El nombre ya existe en la base de datos local, modifíquelo e intente de nuevo'
RemoteBackup: "Para hacer una copia de seguridad de la base de datos remota, primero debe iniciarse el servicio de base de datos del contenedor local utilizando la imagen {{ .name }}, espere por favor..."
RemoteRecover: "Para restaurar la base de datos remota, primero debe iniciarse el servicio de base de datos del contenedor local utilizando la imagen {{ .name }}, espere por favor..."

#redis
ErrTypeOfRedis: 'El tipo de archivo de recuperación no coincide con el método de persistencia actual, modifíquelo e intente'
Expand Down
2 changes: 2 additions & 0 deletions agent/i18n/lang/ja.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,8 @@ ErrDatabaseIsExist: '現在のデータベースは既に存在します。再
ErrExecTimeOut: 'SQL 実行がタイムアウトしました。データベースを確認してください'
ErrRemoteExist: 'この名前のリモート データベースは既に存在します。変更してもう一度お試しください'
ErrLocalExist: '名前はローカル データベースに既に存在します。変更してもう一度お試しください'
RemoteBackup: "リモートデータベースをバックアップするには、まずイメージ {{ .name }} を使用してローカルコンテナデータベースサービスを起動する必要があります。しばらくお待ちください..."
RemoteRecover: "リモートデータベースを復元するには、まずイメージ {{ .name }} を使用してローカルコンテナデータベースサービスを起動する必要があります。しばらくお待ちください..."

#redis
ErrTypeOfRedis: 'リカバリ ファイルの種類が現在の永続化方法と一致しません。変更して再試行してください'
Expand Down
2 changes: 2 additions & 0 deletions agent/i18n/lang/ko.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,8 @@ ErrDatabaseIsExist: '현재 데이터베이스가 이미 존재합니다. 다시
ErrExecTimeOut: 'SQL 실행 시간이 초과되었습니다. 데이터베이스를 확인하십시오.'
ErrRemoteExist: '이 이름을 가진 원격 데이터베이스가 이미 존재합니다. 수정하고 다시 시도하세요'
ErrLocalExist: '이름이 로컬 데이터베이스에 이미 존재합니다. 이름을 수정하고 다시 시도하세요'
RemoteBackup: "원격 데이터베이스를 백업하려면 먼저 이미지 {{ .name }}을(를) 사용하여 로컬 컨테이너 데이터베이스 서비스를 시작해야 합니다. 잠시만 기다려 주세요..."
RemoteRecover: "원격 데이터베이스를 복원하려면 먼저 이미지 {{ .name }}을(를) 사용하여 로컬 컨테이너 데이터베이스 서비스를 시작해야 합니다. 잠시만 기다려 주세요..."

#레디스
ErrTypeOfRedis: '복구 파일 유형이 현재 지속성 방법과 일치하지 않습니다. 수정하고 다시 시도하세요'
Expand Down
2 changes: 2 additions & 0 deletions agent/i18n/lang/ms.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,8 @@ ErrDatabaseIsExist: 'Pangkalan data semasa sudah wujud, sila masukkan semula'
ErrExecTimeOut: 'Pelaksanaan SQL tamat masa, sila semak pangkalan data'
ErrRemoteExist: 'Pangkalan data jauh sudah wujud dengan nama ini, sila ubah suainya dan cuba lagi'
ErrLocalExist: 'Nama sudah wujud dalam pangkalan data tempatan, sila ubah suai dan cuba lagi'
RemoteBackup: "Untuk menyandarkan pangkalan data jauh, perkhidmatan pangkalan data bekas tempatan perlu dimulakan terlebih dahulu menggunakan imej {{ .name }}, sila tunggu..."
RemoteRecover: "Untuk memulihkan pangkalan data jauh, perkhidmatan pangkalan data bekas tempatan perlu dimulakan terlebih dahulu menggunakan imej {{ .name }}, sila tunggu..."

#redis
ErrTypeOfRedis: 'Jenis fail pemulihan tidak sepadan dengan kaedah kegigihan semasa, sila ubah suai dan cuba lagi'
Expand Down
2 changes: 2 additions & 0 deletions agent/i18n/lang/pt-BR.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,8 @@ ErrDatabaseIsExist: 'O banco de dados atual já existe, digite novamente'
ErrExecTimeOut: 'Tempo limite de execução do SQL expirou, verifique o banco de dados'
ErrRemoteExist: 'O banco de dados remoto já existe com este nome, modifique-o e tente novamente'
ErrLocalExist: 'O nome já existe no banco de dados local, modifique-o e tente novamente'
RemoteBackup: "Para fazer backup do banco de dados remoto, o serviço de banco de dados do contêiner local precisa ser iniciado primeiro usando a imagem {{ .name }}, por favor aguarde..."
RemoteRecover: "Para restaurar o banco de dados remoto, o serviço de banco de dados do contêiner local precisa ser iniciado primeiro usando a imagem {{ .name }}, por favor aguarde..."

#redis
ErrTypeOfRedis: 'O tipo de arquivo de recuperação não corresponde ao método de persistência atual, modifique-o e tente novamente'
Expand Down
2 changes: 2 additions & 0 deletions agent/i18n/lang/ru.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,8 @@ ErrDatabaseIsExist: 'Текущая база данных уже существ
ErrExecTimeOut: 'Время выполнения SQL истекло, проверьте базу данных'
ErrRemoteExist: 'Удаленная база данных с таким именем уже существует. Измените его и повторите попытку'
ErrLocalExist: 'Имя уже существует в локальной базе данных, измените его и повторите попытку'
RemoteBackup: "Для резервного копирования удаленной базы данных необходимо сначала запустить службу базы данных локального контейнера с помощью образа {{ .name }}, пожалуйста, подождите..."
RemoteRecover: "Для восстановления удаленной базы данных необходимо сначала запустить службу базы данных локального контейнера с помощью образа {{ .name }}, пожалуйста, подождите..."

#редис
ErrTypeOfRedis: 'Тип файла восстановления не соответствует текущему методу сохранения. Измените его и повторите попытку'
Expand Down
2 changes: 2 additions & 0 deletions agent/i18n/lang/tr.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,8 @@ ErrDatabaseIsExist: 'Mevcut veritabanı zaten mevcut, lütfen yeniden girin'
ErrExecTimeOut: 'SQL yürütme zaman aşımı, lütfen veritabanını kontrol edin'
ErrRemoteExist: 'Uzak veritabanında bu adla zaten mevcut, lütfen değiştirin ve tekrar deneyin'
ErrLocalExist: 'Yerel veritabanında bu ad zaten mevcut, lütfen değiştirin ve tekrar deneyin'
RemoteBackup: "Uzak veritabanını yedeklemek için önce {{ .name }} görüntüsü kullanılarak yerel konteyner veritabanı hizmetinin başlatılması gerekiyor, lütfen bekleyin..."
RemoteRecover: "Uzak veritabanını geri yüklemek için önce {{ .name }} görüntüsü kullanılarak yerel konteyner veritabanı hizmetinin başlatılması gerekiyor, lütfen bekleyin..."

#redis
ErrTypeOfRedis: 'Kurtarma dosyası türü mevcut kalıcılık yöntemiyle eşleşmiyor, lütfen değiştirin ve tekrar deneyin'
Expand Down
2 changes: 2 additions & 0 deletions agent/i18n/lang/zh-Hant.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,8 @@ ErrDatabaseIsExist: '目前資料庫已存在,請重新輸入'
ErrExecTimeOut: 'SQL 執行逾時,請檢查資料庫'
ErrRemoteExist: '遠端資料庫已存在該名稱,請修改後重試'
ErrLocalExist: '本機資料庫已存在該名稱,請修改後重試'
RemoteBackup: "備份遠端資料庫需要先使用映像 {{ .name }} 啟動本機容器資料庫服務,請稍候..."
RemoteRecover: "恢復遠端資料庫需要先使用映像 {{ .name }} 啟動本機容器資料庫服務,請稍候..."

#redis
ErrTypeOfRedis: '復原檔案類型與目前持久化方式不符,請修改後重試'
Expand Down
2 changes: 2 additions & 0 deletions agent/i18n/lang/zh.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,8 @@ ErrDatabaseIsExist: "当前数据库已存在,请重新输入"
ErrExecTimeOut: "SQL 执行超时,请检查数据库"
ErrRemoteExist: "远程数据库已存在该名称,请修改后重试"
ErrLocalExist: "本地数据库已存在该名称,请修改后重试"
RemoteBackup: "备份远程数据库需要先使用镜像 {{ .name }} 启动本地容器数据库服务,请稍候..."
RemoteRecover: "恢复远程数据库需要先使用镜像 {{ .name }} 启动本地容器数据库服务,请稍候..."

#redis
ErrTypeOfRedis: "恢复文件类型与当前持久化方式不符,请修改后重试"
Expand Down
9 changes: 7 additions & 2 deletions agent/utils/postgresql/client/info.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package client

import (
"github.com/1Panel-dev/1Panel/agent/app/task"
_ "github.com/jackc/pgx/v5/stdlib"
)

Expand Down Expand Up @@ -49,19 +50,23 @@ type PasswordChangeInfo struct {
}

type BackupInfo struct {
Database string `json:"database"`
Name string `json:"name"`
TargetDir string `json:"targetDir"`
FileName string `json:"fileName"`

Timeout uint `json:"timeout"` // second
Task *task.Task `json:"-"`
Timeout uint `json:"timeout"` // second
}

type RecoverInfo struct {
Database string `json:"database"`
Name string `json:"name"`
SourceFile string `json:"sourceFile"`
Username string `json:"username"`

Timeout uint `json:"timeout"` // second
Task *task.Task `json:"-"`
Timeout uint `json:"timeout"` // second
}

type SyncDBInfo struct {
Expand Down
77 changes: 17 additions & 60 deletions agent/utils/postgresql/client/remote.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,12 @@ import (
"io"
"os"
"os/exec"
"sort"
"strings"
"time"

"github.com/1Panel-dev/1Panel/agent/app/model"
"github.com/1Panel-dev/1Panel/agent/global"
"github.com/1Panel-dev/1Panel/agent/i18n"
"github.com/docker/docker/api/types/image"
"github.com/pkg/errors"

Expand Down Expand Up @@ -119,10 +119,11 @@ func (r *Remote) ChangePassword(info PasswordChangeInfo) error {
}

func (r *Remote) Backup(info BackupInfo) error {
imageTag, err := loadImageTag()
imageTag, err := loadImageTag(info.Database)
if err != nil {
return err
}
info.Task.Log(i18n.GetWithName("RemoteBackup", imageTag))
fileOp := files.NewFileOp()
if !fileOp.Stat(info.TargetDir) {
if err := os.MkdirAll(info.TargetDir, os.ModePerm); err != nil {
Expand All @@ -144,7 +145,7 @@ func (r *Remote) Backup(info BackupInfo) error {
_, _ = handle.Read(b)
if string(b) != string(n) {
errBytes, _ := os.ReadFile(fileNameItem)
return fmt.Errorf("backup failed,err:%s", string(errBytes))
return fmt.Errorf("backup failed, err: %s", string(errBytes))
}

gzipCmd := exec.Command("gzip", fileNameItem)
Expand All @@ -156,10 +157,11 @@ func (r *Remote) Backup(info BackupInfo) error {
}

func (r *Remote) Recover(info RecoverInfo) error {
imageTag, err := loadImageTag()
imageTag, err := loadImageTag(info.Database)
if err != nil {
return err
}
info.Task.Log(i18n.GetWithName("RemoteRecover", imageTag))
fileName := info.SourceFile
if strings.HasSuffix(info.SourceFile, ".sql.gz") {
fileName = strings.TrimSuffix(info.SourceFile, ".gz")
Expand Down Expand Up @@ -244,69 +246,24 @@ func (r *Remote) ExecSQL(command string, timeout uint) error {
return nil
}

func loadImageTag() (string, error) {
var (
app model.App
appDetails []model.AppDetail
versions []string
)
if err := global.DB.Where("key = ?", "postgresql").First(&app).Error; err != nil {
versions = []string{"postgres:16.1-alpine", "postgres:16.0-alpine"}
} else {
if err := global.DB.Where("app_id = ?", app.ID).Find(&appDetails).Error; err != nil {
versions = []string{"postgres:16.1-alpine", "postgres:16.0-alpine"}
} else {
for _, item := range appDetails {
versions = append(versions, "postgres:"+item.Version)
}
}
func loadImageTag(database string) (string, error) {
var db model.Database
if err := global.DB.Model(&model.Database{}).Where("name = ?", database).First(&db).Error; err != nil {
return "", fmt.Errorf("load database %s info failed, err: %v", database, err)
}

client, err := docker.NewDockerClient()
if err != nil {
return "", err
return "", fmt.Errorf("create docker client failed, err: %v", err)
}
defer client.Close()
images, err := client.ImageList(context.Background(), image.ListOptions{})
if err != nil {
return "", err
}

itemTag := ""
for _, item := range versions {
for _, image := range images {
for _, tag := range image.RepoTags {
if tag == item {
itemTag = tag
break
}
}
if len(itemTag) != 0 {
break
images, _ := client.ImageList(context.Background(), image.ListOptions{})
for _, image := range images {
for _, tag := range image.RepoTags {
if strings.HasPrefix(tag, "postgres:"+strings.TrimSuffix(db.Version, "x")) {
return tag, nil
}
}
if len(itemTag) != 0 {
break
}
}
if len(itemTag) != 0 {
return itemTag, nil
}

sort.Strings(versions)
if len(versions) != 0 {
itemTag = versions[len(versions)-1]
}

ctx, cancel := context.WithTimeout(context.Background(), 3*time.Minute)
defer cancel()
if _, err := client.ImagePull(ctx, itemTag, image.PullOptions{}); err != nil {
if errors.Is(ctx.Err(), context.DeadlineExceeded) {
return itemTag, buserr.WithName("ErrPgImagePull", itemTag)
}
global.LOG.Errorf("image %s pull failed, err: %v", itemTag, err)
return itemTag, fmt.Errorf("image %s pull failed, err: %v", itemTag, err)
}

return itemTag, nil
return "postgres:" + strings.ReplaceAll(db.Version, ".x", "-alpine"), nil
}
2 changes: 1 addition & 1 deletion frontend/src/views/database/postgresql/remote/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ const onOpenDialog = async (
rowData: Partial<Database.DatabaseInfo> = {
name: '',
type: 'postgresql',
version: '17.x',
version: '18.x',
address: '',
port: 5432,
username: '',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
</el-form-item>
<el-form-item :label="$t('database.version')" prop="version">
<el-radio-group v-model="dialogData.rowData!.version" @change="isOK = false">
<el-radio label="18.x" value="18.x" />
<el-radio label="17.x" value="17.x" />
<el-radio label="16.x" value="16.x" />
<el-radio label="15.x" value="15.x" />
Expand Down
Loading