From 25311a729df6739c591658b72245a7280836ee5a Mon Sep 17 00:00:00 2001 From: ssongliu <73214554+ssongliu@users.noreply.github.com> Date: Thu, 31 Oct 2024 22:22:03 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=A4=87=E4=BB=BD=E8=B4=A6=E5=8F=B7?= =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E5=8F=88=E6=8B=8D=E4=BA=91=20(#6911)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Refs #2698 --- agent/app/service/backup.go | 3 + agent/constant/backup.go | 1 + agent/go.mod | 1 + agent/go.sum | 2 + agent/utils/cloud_storage/client/up.go | 94 +++++++++++++++++++ .../cloud_storage/cloud_storage_client.go | 2 + core/app/service/backup.go | 3 + core/constant/common.go | 1 + core/utils/cloud_storage/client/up.go | 47 ++++++++++ .../cloud_storage/cloud_storage_client.go | 2 + frontend/src/lang/modules/en.ts | 3 + frontend/src/lang/modules/tw.ts | 3 + frontend/src/lang/modules/zh.ts | 3 + .../setting/backup-account/operate/index.vue | 21 +++++ go.mod | 3 +- go.sum | 2 + 16 files changed, 190 insertions(+), 1 deletion(-) create mode 100644 agent/utils/cloud_storage/client/up.go create mode 100644 core/utils/cloud_storage/client/up.go diff --git a/agent/app/service/backup.go b/agent/app/service/backup.go index 162c59f52..af3188555 100644 --- a/agent/app/service/backup.go +++ b/agent/app/service/backup.go @@ -401,6 +401,9 @@ func newClient(account *model.BackupAccount) (cloud_storage.CloudStorageClient, case constant.OSS, constant.S3, constant.MinIo, constant.Cos, constant.Kodo: varMap["accessKey"] = account.AccessKey varMap["secretKey"] = account.Credential + case constant.UPYUN: + varMap["operator"] = account.AccessKey + varMap["password"] = account.Credential } client, err := cloud_storage.NewCloudStorageClient(account.Type, varMap) diff --git a/agent/constant/backup.go b/agent/constant/backup.go index 37baa994e..8636226b1 100644 --- a/agent/constant/backup.go +++ b/agent/constant/backup.go @@ -13,6 +13,7 @@ const ( Kodo = "KODO" WebDAV = "WebDAV" Local = "LOCAL" + UPYUN = "UPYUN" OneDriveRedirectURI = "http://localhost/login/authorized" ) diff --git a/agent/go.mod b/agent/go.mod index 33fd75995..a1d586f74 100644 --- a/agent/go.mod +++ b/agent/go.mod @@ -43,6 +43,7 @@ require ( github.com/studio-b12/gowebdav v0.9.0 github.com/subosito/gotenv v1.6.0 github.com/tencentyun/cos-go-sdk-v5 v0.7.54 + github.com/upyun/go-sdk v2.1.0+incompatible golang.org/x/crypto v0.25.0 golang.org/x/net v0.27.0 golang.org/x/oauth2 v0.21.0 diff --git a/agent/go.sum b/agent/go.sum index c39fc24f4..d5f32354c 100644 --- a/agent/go.sum +++ b/agent/go.sum @@ -753,6 +753,8 @@ github.com/ugorji/go/codec v1.2.12/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZ github.com/ulikunitz/xz v0.5.6/go.mod h1:2bypXElzHzzJZwzH67Y6wb67pO62Rzfn7BSiF4ABRW8= github.com/ulikunitz/xz v0.5.10 h1:t92gobL9l3HE202wg3rlk19F6X+JOxl9BBrCCMYEYd8= github.com/ulikunitz/xz v0.5.10/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= +github.com/upyun/go-sdk v2.1.0+incompatible h1:OdjXghQ/TVetWV16Pz3C1/SUpjhGBVPr+cLiqZLLyq0= +github.com/upyun/go-sdk v2.1.0+incompatible/go.mod h1:eu3F5Uz4b9ZE5bE5QsCL6mgSNWRwfj0zpJ9J626HEqs= github.com/vbatts/tar-split v0.11.5 h1:3bHCTIheBm1qFTcgh9oPu+nNBtX+XJIupG/vacinCts= github.com/vbatts/tar-split v0.11.5/go.mod h1:yZbwRsSeGjusneWgA781EKej9HF8vme8okylkAeNKLk= github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= diff --git a/agent/utils/cloud_storage/client/up.go b/agent/utils/cloud_storage/client/up.go new file mode 100644 index 000000000..d044f0c6f --- /dev/null +++ b/agent/utils/cloud_storage/client/up.go @@ -0,0 +1,94 @@ +package client + +import ( + "path" + + "github.com/upyun/go-sdk/upyun" +) + +type upClient struct { + bucket string + client *upyun.UpYun +} + +func NewUpClient(vars map[string]interface{}) (*upClient, error) { + operator := loadParamFromVars("operator", vars) + password := loadParamFromVars("password", vars) + bucket := loadParamFromVars("bucket", vars) + client := upyun.NewUpYun(&upyun.UpYunConfig{ + Bucket: bucket, + Operator: operator, + Password: password, + }) + + return &upClient{bucket: bucket, client: client}, nil +} + +func (o upClient) ListBuckets() ([]interface{}, error) { + var result []interface{} + return result, nil +} + +func (s upClient) Upload(src, target string) (bool, error) { + if _, err := s.client.GetInfo(path.Dir(src)); err != nil { + _ = s.client.Mkdir(path.Dir(src)) + } + if err := s.client.Put(&upyun.PutObjectConfig{ + Path: target, + LocalPath: src, + UseResumeUpload: true, + }); err != nil { + return false, err + } + return true, nil +} + +func (s upClient) Size(path string) (int64, error) { + fileInfo, err := s.client.GetInfo(path) + if err != nil { + return 0, err + } + return fileInfo.Size, nil +} + +func (s upClient) Delete(path string) (bool, error) { + if err := s.client.Delete(&upyun.DeleteObjectConfig{ + Path: path, + }); err != nil { + return false, err + } + return true, nil +} + +func (s upClient) Exist(filePath string) (bool, error) { + if _, err := s.client.GetInfo(filePath); err != nil { + return false, err + } + return true, nil +} + +func (s upClient) Download(src, target string) (bool, error) { + if _, err := s.client.Get(&upyun.GetObjectConfig{ + Path: src, + LocalPath: target, + }); err != nil { + return false, err + } + return true, nil +} + +func (s *upClient) ListObjects(prefix string) ([]string, error) { + objsChan := make(chan *upyun.FileInfo, 10) + if err := s.client.List(&upyun.GetObjectsConfig{ + Path: prefix, + ObjectsChan: objsChan, + MaxListTries: 1, + }); err != nil { + return nil, err + } + var files []string + for obj := range objsChan { + files = append(files, obj.Name) + } + return files, nil +} diff --git a/agent/utils/cloud_storage/cloud_storage_client.go b/agent/utils/cloud_storage/cloud_storage_client.go index 0cc233858..5cc59f1c3 100644 --- a/agent/utils/cloud_storage/cloud_storage_client.go +++ b/agent/utils/cloud_storage/cloud_storage_client.go @@ -36,6 +36,8 @@ func NewCloudStorageClient(backupType string, vars map[string]interface{}) (Clou return client.NewKodoClient(vars) case constant.OneDrive: return client.NewOneDriveClient(vars) + case constant.UPYUN: + return client.NewUpClient(vars) default: return nil, constant.ErrNotSupportType } diff --git a/core/app/service/backup.go b/core/app/service/backup.go index e249fe6d3..59204f4ed 100644 --- a/core/app/service/backup.go +++ b/core/app/service/backup.go @@ -378,6 +378,9 @@ func (u *BackupService) NewClient(backup *model.BackupAccount) (cloud_storage.Cl case constant.OSS, constant.S3, constant.MinIo, constant.Cos, constant.Kodo: varMap["accessKey"] = backup.AccessKey varMap["secretKey"] = backup.Credential + case constant.UPYUN: + varMap["operator"] = backup.AccessKey + varMap["password"] = backup.Credential } backClient, err := cloud_storage.NewCloudStorageClient(backup.Type, varMap) diff --git a/core/constant/common.go b/core/constant/common.go index fdb09a806..10f2a9c7e 100644 --- a/core/constant/common.go +++ b/core/constant/common.go @@ -28,5 +28,6 @@ const ( Kodo = "KODO" WebDAV = "WebDAV" Local = "LOCAL" + UPYUN = "UPYUN" OneDriveRedirectURI = "http://localhost/login/authorized" ) diff --git a/core/utils/cloud_storage/client/up.go b/core/utils/cloud_storage/client/up.go new file mode 100644 index 000000000..f96d5aa8e --- /dev/null +++ b/core/utils/cloud_storage/client/up.go @@ -0,0 +1,47 @@ +package client + +import ( + "fmt" + "path" + + "github.com/upyun/go-sdk/upyun" +) + +type upClient struct { + bucket string + client *upyun.UpYun +} + +func NewUpClient(vars map[string]interface{}) (*upClient, error) { + operator := loadParamFromVars("operator", vars) + password := loadParamFromVars("password", vars) + bucket := loadParamFromVars("bucket", vars) + client := upyun.NewUpYun(&upyun.UpYunConfig{ + Bucket: bucket, + Operator: operator, + Password: password, + UserAgent: "1panel-son.test.upcdn.net", + }) + + return &upClient{bucket: bucket, client: client}, nil +} + +func (o upClient) ListBuckets() ([]interface{}, error) { + var result []interface{} + return result, nil +} + +func (s upClient) Upload(src, target string) (bool, error) { + if _, err := s.client.GetInfo(path.Dir(target)); err != nil { + if err := s.client.Mkdir(path.Dir(target)); err != nil { + fmt.Println(err) + } + } + if err := s.client.Put(&upyun.PutObjectConfig{ + Path: target, + LocalPath: src, + }); err != nil { + return false, err + } + return true, nil +} diff --git a/core/utils/cloud_storage/cloud_storage_client.go b/core/utils/cloud_storage/cloud_storage_client.go index 6c4cb4f26..912f3cc8f 100644 --- a/core/utils/cloud_storage/cloud_storage_client.go +++ b/core/utils/cloud_storage/cloud_storage_client.go @@ -30,6 +30,8 @@ func NewCloudStorageClient(backupType string, vars map[string]interface{}) (Clou return client.NewKodoClient(vars) case constant.OneDrive: return client.NewOneDriveClient(vars) + case constant.UPYUN: + return client.NewUpClient(vars) default: return nil, constant.ErrNotSupportType } diff --git a/frontend/src/lang/modules/en.ts b/frontend/src/lang/modules/en.ts index 23b8716d5..b096a07d9 100644 --- a/frontend/src/lang/modules/en.ts +++ b/frontend/src/lang/modules/en.ts @@ -1451,6 +1451,9 @@ const message = { SFTP: 'SFTP', WebDAV: 'WebDAV', WebDAVAlist: 'WebDAV connect Alist can refer to the official documentation', + UPYUN: 'UPYUN', + serviceName: 'Service Name', + operator: 'Operator', OneDrive: 'Microsoft OneDrive', isCN: 'Century Internet', isNotCN: 'International Version', diff --git a/frontend/src/lang/modules/tw.ts b/frontend/src/lang/modules/tw.ts index 8114b446a..686845418 100644 --- a/frontend/src/lang/modules/tw.ts +++ b/frontend/src/lang/modules/tw.ts @@ -1364,6 +1364,9 @@ const message = { SFTP: 'SFTP', WebDAV: 'WebDAV', WebDAVAlist: 'WebDAV 連接 Alist 可參考官方文檔', + UPYUN: '又拍雲', + serviceName: '服務名稱', + operator: '操作員', OneDrive: '微軟 OneDrive', isCN: '世紀互聯', isNotCN: '國際版', diff --git a/frontend/src/lang/modules/zh.ts b/frontend/src/lang/modules/zh.ts index 7a1231471..3de1445ff 100644 --- a/frontend/src/lang/modules/zh.ts +++ b/frontend/src/lang/modules/zh.ts @@ -1366,6 +1366,9 @@ const message = { SFTP: 'SFTP', WebDAV: 'WebDAV', WebDAVAlist: 'WebDAV 连接 Alist 可参考官方文档', + UPYUN: '又拍云', + serviceName: '服务名称', + operator: '操作员', OneDrive: '微软 OneDrive', isCN: '世纪互联', isNotCN: '国际版', diff --git a/frontend/src/views/setting/backup-account/operate/index.vue b/frontend/src/views/setting/backup-account/operate/index.vue index d67d51829..21b34bd44 100644 --- a/frontend/src/views/setting/backup-account/operate/index.vue +++ b/frontend/src/views/setting/backup-account/operate/index.vue @@ -16,6 +16,7 @@ + @@ -24,6 +25,14 @@ +
+ + + + + + +
{{ $t('commons.rule.requiredSelect') }} + + + { + let itemType = dialogData.value.rowData!.type; + return itemType === 'UPYUN'; +}; const hasAccessKey = () => { let itemType = dialogData.value.rowData!.type; return itemType === 'COS' || itemType === 'KODO' || itemType === 'MINIO' || itemType === 'OSS' || itemType === 'S3'; diff --git a/go.mod b/go.mod index 835d325d9..7d7bec108 100644 --- a/go.mod +++ b/go.mod @@ -21,6 +21,7 @@ require ( github.com/minio/minio-go/v7 v7.0.74 github.com/mojocn/base64Captcha v1.3.6 github.com/nicksnyder/go-i18n/v2 v2.4.0 + github.com/oschwald/maxminddb-golang v1.13.1 github.com/pkg/errors v0.9.1 github.com/pkg/sftp v1.13.6 github.com/qiniu/go-sdk/v7 v7.21.1 @@ -34,6 +35,7 @@ require ( github.com/swaggo/gin-swagger v1.6.0 github.com/swaggo/swag v1.16.3 github.com/tencentyun/cos-go-sdk-v5 v0.7.54 + github.com/upyun/go-sdk v2.1.0+incompatible github.com/xlzd/gotp v0.1.0 golang.org/x/crypto v0.24.0 golang.org/x/oauth2 v0.18.0 @@ -99,7 +101,6 @@ require ( github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect github.com/mozillazg/go-httpheader v0.2.1 // indirect - github.com/oschwald/maxminddb-golang v1.13.1 // indirect github.com/pelletier/go-toml/v2 v2.2.2 // indirect github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect github.com/rs/xid v1.5.0 // indirect diff --git a/go.sum b/go.sum index 15345a83a..86c7e4c97 100644 --- a/go.sum +++ b/go.sum @@ -382,6 +382,8 @@ github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08= github.com/ugorji/go/codec v1.2.12 h1:9LC83zGrHhuUA9l16C9AHXAqEV/2wBQ4nkvumAE65EE= github.com/ugorji/go/codec v1.2.12/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg= +github.com/upyun/go-sdk v2.1.0+incompatible h1:OdjXghQ/TVetWV16Pz3C1/SUpjhGBVPr+cLiqZLLyq0= +github.com/upyun/go-sdk v2.1.0+incompatible/go.mod h1:eu3F5Uz4b9ZE5bE5QsCL6mgSNWRwfj0zpJ9J626HEqs= github.com/xlzd/gotp v0.1.0 h1:37blvlKCh38s+fkem+fFh7sMnceltoIEBYTVXyoa5Po= github.com/xlzd/gotp v0.1.0/go.mod h1:ndLJ3JKzi3xLmUProq4LLxCuECL93dG9WASNLpHz8qg= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=