From 879da92419c380a25b1a48a9fcecd2286a3678c2 Mon Sep 17 00:00:00 2001 From: Fu Diwei Date: Fri, 14 Feb 2025 21:01:33 +0800 Subject: [PATCH 01/34] feat: add volcengine imagex deployer --- README.md | 2 +- README_EN.md | 2 +- go.mod | 3 +- go.sum | 3 + internal/deployer/providers.go | 13 +- internal/domain/provider.go | 1 + .../volcengine-imagex/volcengine_imagex.go | 147 ++++++++++++++++++ .../volcengine_imagex_test.go | 85 ++++++++++ .../volcengine-tos/volcengine_tos_test.go | 2 + .../workflow/node/DeployNodeConfigForm.tsx | 3 + ...oyNodeConfigFormVolcEngineImageXConfig.tsx | 91 +++++++++++ ui/src/domain/provider.ts | 2 + ui/src/i18n/locales/en/nls.provider.json | 1 + .../i18n/locales/en/nls.workflow.nodes.json | 9 ++ ui/src/i18n/locales/zh/nls.provider.json | 1 + .../i18n/locales/zh/nls.workflow.nodes.json | 11 +- 16 files changed, 371 insertions(+), 5 deletions(-) create mode 100644 internal/pkg/core/deployer/providers/volcengine-imagex/volcengine_imagex.go create mode 100644 internal/pkg/core/deployer/providers/volcengine-imagex/volcengine_imagex_test.go create mode 100644 ui/src/components/workflow/node/DeployNodeConfigFormVolcEngineImageXConfig.tsx diff --git a/README.md b/README.md index 6f90fb32..9a377b9d 100644 --- a/README.md +++ b/README.md @@ -126,7 +126,7 @@ make local.run | [腾讯云](https://cloud.tencent.com/) | 可部署到腾讯云 COS、CDN、ECDN、EdgeOne、CLB、CSS 等服务 | | [百度智能云](https://cloud.baidu.com/) | 可部署到百度智能云 CDN 等服务 | | [华为云](https://www.huaweicloud.com/) | 可部署到华为云 CDN、ELB 等服务 | -| [火山引擎](https://www.volcengine.com/) | 可部署到火山引擎 TOS、CDN、DCDN、CLB、Live 等服务 | +| [火山引擎](https://www.volcengine.com/) | 可部署到火山引擎 TOS、CDN、DCDN、CLB、ImageX、Live 等服务 | | [七牛云](https://www.qiniu.com/) | 可部署到七牛云 CDN、直播云等服务 | | [多吉云](https://www.dogecloud.com/) | 可部署到多吉云 CDN | | [优刻得](https://www.ucloud.cn/) | 可部署到优刻得 US3、UCDN 等服务 | diff --git a/README_EN.md b/README_EN.md index d5300b07..47c654f2 100644 --- a/README_EN.md +++ b/README_EN.md @@ -125,7 +125,7 @@ The following hosting providers are supported: | [Tencent Cloud](https://www.tencentcloud.com/) | Supports deployment to Tencent Cloud COS, CDN, ECDN, EdgeOne, CLB, CSS | | [Baidu AI Cloud](https://intl.cloud.baidu.com/) | Supports deployment to Baidu AI CLoud CDN | | [Huawei Cloud](https://www.huaweicloud.com/) | Supports deployment to Huawei Cloud CDN, ELB | -| [Volcengine](https://www.volcengine.com/) | Supports deployment to Volcengine TOS, CDN, DCDN, CLB, Live | +| [Volcengine](https://www.volcengine.com/) | Supports deployment to Volcengine TOS, CDN, DCDN, CLB, ImageX, Live | | [Qiniu Cloud](https://www.qiniu.com/) | Supports deployment to Qiniu Cloud CDN, Pili | | [Doge Cloud](https://www.dogecloud.com/) | Supports deployment to Doge Cloud CDN | | [BaoTa Panel](https://www.bt.cn/) | Supports deployment to BaoTa Panel sites | diff --git a/go.mod b/go.mod index d3280f69..18045029 100644 --- a/go.mod +++ b/go.mod @@ -40,7 +40,7 @@ require ( github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/teo v1.0.1096 github.com/ucloud/ucloud-sdk-go v0.22.31 github.com/volcengine/ve-tos-golang-sdk/v2 v2.7.9 - github.com/volcengine/volc-sdk-golang v1.0.194 + github.com/volcengine/volc-sdk-golang v1.0.195 github.com/volcengine/volcengine-go-sdk v1.0.180 golang.org/x/crypto v0.33.0 golang.org/x/exp v0.0.0-20250210185358-939b2ce775ac @@ -62,6 +62,7 @@ require ( github.com/alibabacloud-go/tea-oss-sdk v1.1.3 // indirect github.com/alibabacloud-go/tea-oss-utils v1.1.0 // indirect github.com/alibabacloud-go/tea-utils/v2 v2.0.7 // indirect + github.com/avast/retry-go v3.0.0+incompatible // indirect github.com/aws/aws-sdk-go-v2/service/route53 v1.48.1 // indirect github.com/blinkbean/dingtalk v1.1.3 // indirect github.com/emicklei/go-restful/v3 v3.12.1 // indirect diff --git a/go.sum b/go.sum index e9239294..a9edfa88 100644 --- a/go.sum +++ b/go.sum @@ -205,6 +205,7 @@ github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgI github.com/asaskevich/govalidator v0.0.0-20200108200545-475eaeb16496/go.mod h1:oGkLhpf+kjZl6xBf758TQhh5XrAeiJv/7FRz/2spLIg= github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 h1:DklsrG3dyBCFEj5IhUbnKptjxatkF07cF2ak3yi77so= github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw= +github.com/avast/retry-go v3.0.0+incompatible h1:4SOWQ7Qs+oroOTQOYnAHqelpCO0biHSxpiH9JdtuBj0= github.com/avast/retry-go v3.0.0+incompatible/go.mod h1:XtSnn+n/sHqQIpZ10K1qAevBhOOCWBLXXy3hyiqqBrY= github.com/aws/aws-sdk-go v1.40.45/go.mod h1:585smgzpB/KqRA+K3y/NL/oYRqQvpNJYvLm+LY1U59Q= github.com/aws/aws-sdk-go v1.55.5 h1:KKUZBfBoyqy5d3swXyiC7Q76ic40rYcbqH7qjh59kzU= @@ -850,6 +851,8 @@ github.com/volcengine/ve-tos-golang-sdk/v2 v2.7.9/go.mod h1:IrjK84IJJTuOZOTMv/P1 github.com/volcengine/volc-sdk-golang v1.0.23/go.mod h1:AfG/PZRUkHJ9inETvbjNifTDgut25Wbkm2QoYBTbvyU= github.com/volcengine/volc-sdk-golang v1.0.194 h1:3o0INQzdtYJWvdGrtX02booCqPL5TsWSq2W1Ur7Bzlo= github.com/volcengine/volc-sdk-golang v1.0.194/go.mod h1:u0VtPvlXWpXDTmc9IHkaW1q+5Jjwus4oAqRhNMDRInE= +github.com/volcengine/volc-sdk-golang v1.0.195 h1:hKX4pBhmKcB3652BTdcAmtgizEPBnoQUpTM+j5blMA4= +github.com/volcengine/volc-sdk-golang v1.0.195/go.mod h1:stZX+EPgv1vF4nZwOlEe8iGcriUPRBKX8zA19gXycOQ= github.com/volcengine/volcengine-go-sdk v1.0.180 h1:lzcNlaxeGIUdXgDuVH7KJwZYZjIZzaCAYPDh91htU6U= github.com/volcengine/volcengine-go-sdk v1.0.180/go.mod h1:gfEDc1s7SYaGoY+WH2dRrS3qiuDJMkwqyfXWCa7+7oA= github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM= diff --git a/internal/deployer/providers.go b/internal/deployer/providers.go index a9878f8a..d6e149ed 100644 --- a/internal/deployer/providers.go +++ b/internal/deployer/providers.go @@ -41,6 +41,7 @@ import ( providerVolcEngineCDN "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/volcengine-cdn" providerVolcEngineCLB "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/volcengine-clb" providerVolcEngineDCDN "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/volcengine-dcdn" + providerVolcEngineImageX "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/volcengine-imagex" providerVolcEngineLive "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/volcengine-live" providerVolcEngineTOS "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/volcengine-tos" providerWebhook "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/webhook" @@ -515,7 +516,7 @@ func createDeployer(options *deployerOptions) (deployer.Deployer, logger.Logger, } } - case domain.DeployProviderTypeVolcEngineCDN, domain.DeployProviderTypeVolcEngineCLB, domain.DeployProviderTypeVolcEngineDCDN, domain.DeployProviderTypeVolcEngineLive, domain.DeployProviderTypeVolcEngineTOS: + case domain.DeployProviderTypeVolcEngineCDN, domain.DeployProviderTypeVolcEngineCLB, domain.DeployProviderTypeVolcEngineDCDN, domain.DeployProviderTypeVolcEngineImageX, domain.DeployProviderTypeVolcEngineLive, domain.DeployProviderTypeVolcEngineTOS: { access := domain.AccessConfigForVolcEngine{} if err := maps.Populate(options.ProviderAccessConfig, &access); err != nil { @@ -549,6 +550,16 @@ func createDeployer(options *deployerOptions) (deployer.Deployer, logger.Logger, }, logger) return deployer, logger, err + case domain.DeployProviderTypeVolcEngineImageX: + deployer, err := providerVolcEngineImageX.NewWithLogger(&providerVolcEngineImageX.VolcEngineImageXDeployerConfig{ + AccessKeyId: access.AccessKeyId, + AccessKeySecret: access.SecretAccessKey, + Region: maps.GetValueAsString(options.ProviderDeployConfig, "region"), + ServiceId: maps.GetValueAsString(options.ProviderDeployConfig, "serviceId"), + Domain: maps.GetValueAsString(options.ProviderDeployConfig, "domain"), + }, logger) + return deployer, logger, err + case domain.DeployProviderTypeVolcEngineLive: deployer, err := providerVolcEngineLive.NewWithLogger(&providerVolcEngineLive.VolcEngineLiveDeployerConfig{ AccessKeyId: access.AccessKeyId, diff --git a/internal/domain/provider.go b/internal/domain/provider.go index 350b3926..30c9dab1 100644 --- a/internal/domain/provider.go +++ b/internal/domain/provider.go @@ -130,6 +130,7 @@ const ( DeployProviderTypeVolcEngineCDN = DeployProviderType("volcengine-cdn") DeployProviderTypeVolcEngineCLB = DeployProviderType("volcengine-clb") DeployProviderTypeVolcEngineDCDN = DeployProviderType("volcengine-dcdn") + DeployProviderTypeVolcEngineImageX = DeployProviderType("volcengine-imagex") DeployProviderTypeVolcEngineLive = DeployProviderType("volcengine-live") DeployProviderTypeVolcEngineTOS = DeployProviderType("volcengine-tos") DeployProviderTypeWebhook = DeployProviderType("webhook") diff --git a/internal/pkg/core/deployer/providers/volcengine-imagex/volcengine_imagex.go b/internal/pkg/core/deployer/providers/volcengine-imagex/volcengine_imagex.go new file mode 100644 index 00000000..00102896 --- /dev/null +++ b/internal/pkg/core/deployer/providers/volcengine-imagex/volcengine_imagex.go @@ -0,0 +1,147 @@ +package volcengineimagex + +import ( + "context" + "errors" + + xerrors "github.com/pkg/errors" + veBase "github.com/volcengine/volc-sdk-golang/base" + veImageX "github.com/volcengine/volc-sdk-golang/service/imagex/v2" + + "github.com/usual2970/certimate/internal/pkg/core/deployer" + "github.com/usual2970/certimate/internal/pkg/core/logger" + "github.com/usual2970/certimate/internal/pkg/core/uploader" + uploaderp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/volcengine-certcenter" +) + +type VolcEngineImageXDeployerConfig struct { + // 火山引擎 AccessKeyId。 + AccessKeyId string `json:"accessKeyId"` + // 火山引擎 AccessKeySecret。 + AccessKeySecret string `json:"accessKeySecret"` + // 火山引擎地域。 + Region string `json:"region"` + // 服务 ID。 + ServiceId string `json:"serviceId"` + // 自定义域名(不支持泛域名)。 + Domain string `json:"domain"` +} + +type VolcEngineImageXDeployer struct { + config *VolcEngineImageXDeployerConfig + logger logger.Logger + sdkClient *veImageX.Imagex + sslUploader uploader.Uploader +} + +var _ deployer.Deployer = (*VolcEngineImageXDeployer)(nil) + +func New(config *VolcEngineImageXDeployerConfig) (*VolcEngineImageXDeployer, error) { + return NewWithLogger(config, logger.NewNilLogger()) +} + +func NewWithLogger(config *VolcEngineImageXDeployerConfig, logger logger.Logger) (*VolcEngineImageXDeployer, error) { + if config == nil { + return nil, errors.New("config is nil") + } + + if logger == nil { + return nil, errors.New("logger is nil") + } + + client, err := createSdkClient(config.AccessKeyId, config.AccessKeySecret, config.Region) + if err != nil { + return nil, xerrors.Wrap(err, "failed to create sdk client") + } + + uploader, err := uploaderp.New(&uploaderp.VolcEngineCertCenterUploaderConfig{ + AccessKeyId: config.AccessKeyId, + AccessKeySecret: config.AccessKeySecret, + Region: config.Region, + }) + if err != nil { + return nil, xerrors.Wrap(err, "failed to create ssl uploader") + } + + return &VolcEngineImageXDeployer{ + logger: logger, + config: config, + sdkClient: client, + sslUploader: uploader, + }, nil +} + +func (d *VolcEngineImageXDeployer) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { + if d.config.ServiceId == "" { + return nil, errors.New("config `serviceId` is required") + } + if d.config.Domain == "" { + return nil, errors.New("config `domain` is required") + } + + // 上传证书到证书中心 + upres, err := d.sslUploader.Upload(ctx, certPem, privkeyPem) + if err != nil { + return nil, xerrors.Wrap(err, "failed to upload certificate file") + } + + d.logger.Logt("certificate file uploaded", upres) + + // 获取域名配置 + // REF: https://www.volcengine.com/docs/508/9366 + getDomainConfigReq := &veImageX.GetDomainConfigQuery{ + ServiceID: d.config.ServiceId, + DomainName: d.config.Domain, + } + getDomainConfigResp, err := d.sdkClient.GetDomainConfig(context.TODO(), getDomainConfigReq) + if err != nil { + return nil, xerrors.Wrap(err, "failed to execute sdk request 'imagex.GetDomainConfig'") + } else { + d.logger.Logt("已获取域名配置", getDomainConfigResp) + } + + // 更新 HTTPS 配置 + // REF: https://www.volcengine.com/docs/508/66012 + updateHttpsReq := &veImageX.UpdateHTTPSReq{ + UpdateHTTPSQuery: &veImageX.UpdateHTTPSQuery{ + ServiceID: d.config.ServiceId, + }, + UpdateHTTPSBody: &veImageX.UpdateHTTPSBody{ + Domain: getDomainConfigResp.Result.Domain, + HTTPS: &veImageX.UpdateHTTPSBodyHTTPS{ + CertID: upres.CertId, + EnableHTTP2: getDomainConfigResp.Result.HTTPSConfig.EnableHTTP2, + EnableHTTPS: getDomainConfigResp.Result.HTTPSConfig.EnableHTTPS, + EnableOcsp: getDomainConfigResp.Result.HTTPSConfig.EnableOcsp, + TLSVersions: getDomainConfigResp.Result.HTTPSConfig.TLSVersions, + EnableForceRedirect: getDomainConfigResp.Result.HTTPSConfig.EnableForceRedirect, + ForceRedirectType: getDomainConfigResp.Result.HTTPSConfig.ForceRedirectType, + ForceRedirectCode: getDomainConfigResp.Result.HTTPSConfig.ForceRedirectCode, + }, + }, + } + updateHttpsResp, err := d.sdkClient.UpdateHTTPS(context.TODO(), updateHttpsReq) + if err != nil { + return nil, xerrors.Wrap(err, "failed to execute sdk request 'imagex.UpdateHttps'") + } else { + d.logger.Logt("已更新 HTTPS 配置", updateHttpsResp) + } + + return &deployer.DeployResult{}, nil +} + +func createSdkClient(accessKeyId, accessKeySecret, region string) (*veImageX.Imagex, error) { + var instance *veImageX.Imagex + if region == "" { + instance = veImageX.NewInstance() + } else { + instance = veImageX.NewInstanceWithRegion(region) + } + + instance.SetCredential(veBase.Credentials{ + AccessKeyID: accessKeyId, + SecretAccessKey: accessKeySecret, + }) + + return instance, nil +} diff --git a/internal/pkg/core/deployer/providers/volcengine-imagex/volcengine_imagex_test.go b/internal/pkg/core/deployer/providers/volcengine-imagex/volcengine_imagex_test.go new file mode 100644 index 00000000..3e15eec8 --- /dev/null +++ b/internal/pkg/core/deployer/providers/volcengine-imagex/volcengine_imagex_test.go @@ -0,0 +1,85 @@ +package volcengineimagex_test + +import ( + "context" + "flag" + "fmt" + "os" + "strings" + "testing" + + provider "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/volcengine-imagex" +) + +var ( + fInputCertPath string + fInputKeyPath string + fAccessKeyId string + fAccessKeySecret string + fRegion string + fServiceId string + fDomain string +) + +func init() { + argsPrefix := "CERTIMATE_DEPLOYER_VOLCENGINEIMAGEX_" + + flag.StringVar(&fInputCertPath, argsPrefix+"INPUTCERTPATH", "", "") + flag.StringVar(&fInputKeyPath, argsPrefix+"INPUTKEYPATH", "", "") + flag.StringVar(&fAccessKeyId, argsPrefix+"ACCESSKEYID", "", "") + flag.StringVar(&fAccessKeySecret, argsPrefix+"ACCESSKEYSECRET", "", "") + flag.StringVar(&fRegion, argsPrefix+"REGION", "", "") + flag.StringVar(&fServiceId, argsPrefix+"SERVICEID", "", "") + flag.StringVar(&fDomain, argsPrefix+"DOMAIN", "", "") +} + +/* +Shell command to run this test: + + go test -v ./volcengine_imagex_test.go -args \ + --CERTIMATE_DEPLOYER_VOLCENGINEIMAGEX_INPUTCERTPATH="/path/to/your-input-cert.pem" \ + --CERTIMATE_DEPLOYER_VOLCENGINEIMAGEX_INPUTKEYPATH="/path/to/your-input-key.pem" \ + --CERTIMATE_DEPLOYER_VOLCENGINEIMAGEX_ACCESSKEYID="your-access-key-id" \ + --CERTIMATE_DEPLOYER_VOLCENGINEIMAGEX_ACCESSKEYSECRET="your-access-key-secret" \ + --CERTIMATE_DEPLOYER_VOLCENGINEIMAGEX_REGION="cn-north-1" \ + --CERTIMATE_DEPLOYER_VOLCENGINEIMAGEX_SERVICEID="your-service-id" \ + --CERTIMATE_DEPLOYER_VOLCENGINEIMAGEX_DOMAIN="example.com" +*/ +func TestDeploy(t *testing.T) { + flag.Parse() + + t.Run("Deploy", func(t *testing.T) { + t.Log(strings.Join([]string{ + "args:", + fmt.Sprintf("INPUTCERTPATH: %v", fInputCertPath), + fmt.Sprintf("INPUTKEYPATH: %v", fInputKeyPath), + fmt.Sprintf("ACCESSKEYID: %v", fAccessKeyId), + fmt.Sprintf("ACCESSKEYSECRET: %v", fAccessKeySecret), + fmt.Sprintf("REGION: %v", fRegion), + fmt.Sprintf("SERVICEID: %v", fServiceId), + fmt.Sprintf("DOMAIN: %v", fDomain), + }, "\n")) + + deployer, err := provider.New(&provider.VolcEngineImageXDeployerConfig{ + AccessKeyId: fAccessKeyId, + AccessKeySecret: fAccessKeySecret, + Region: fRegion, + ServiceId: fServiceId, + Domain: fDomain, + }) + if err != nil { + t.Errorf("err: %+v", err) + return + } + + fInputCertData, _ := os.ReadFile(fInputCertPath) + fInputKeyData, _ := os.ReadFile(fInputKeyPath) + res, err := deployer.Deploy(context.Background(), string(fInputCertData), string(fInputKeyData)) + if err != nil { + t.Errorf("err: %+v", err) + return + } + + t.Logf("ok: %v", res) + }) +} diff --git a/internal/pkg/core/deployer/providers/volcengine-tos/volcengine_tos_test.go b/internal/pkg/core/deployer/providers/volcengine-tos/volcengine_tos_test.go index b70130c4..815d2f0d 100644 --- a/internal/pkg/core/deployer/providers/volcengine-tos/volcengine_tos_test.go +++ b/internal/pkg/core/deployer/providers/volcengine-tos/volcengine_tos_test.go @@ -63,6 +63,8 @@ func TestDeploy(t *testing.T) { deployer, err := provider.New(&provider.VolcEngineTOSDeployerConfig{ AccessKeyId: fAccessKeyId, AccessKeySecret: fAccessKeySecret, + Region: fRegion, + Bucket: fBucket, Domain: fDomain, }) if err != nil { diff --git a/ui/src/components/workflow/node/DeployNodeConfigForm.tsx b/ui/src/components/workflow/node/DeployNodeConfigForm.tsx index 78d1b99d..6f4d1f4a 100644 --- a/ui/src/components/workflow/node/DeployNodeConfigForm.tsx +++ b/ui/src/components/workflow/node/DeployNodeConfigForm.tsx @@ -50,6 +50,7 @@ import DeployNodeConfigFormUCloudUS3Config from "./DeployNodeConfigFormUCloudUS3 import DeployNodeConfigFormVolcEngineCDNConfig from "./DeployNodeConfigFormVolcEngineCDNConfig.tsx"; import DeployNodeConfigFormVolcEngineCLBConfig from "./DeployNodeConfigFormVolcEngineCLBConfig.tsx"; import DeployNodeConfigFormVolcEngineDCDNConfig from "./DeployNodeConfigFormVolcEngineDCDNConfig.tsx"; +import DeployNodeConfigFormVolcEngineImageXConfig from "./DeployNodeConfigFormVolcEngineImageXConfig.tsx"; import DeployNodeConfigFormVolcEngineLiveConfig from "./DeployNodeConfigFormVolcEngineLiveConfig.tsx"; import DeployNodeConfigFormVolcEngineTOSConfig from "./DeployNodeConfigFormVolcEngineTOSConfig.tsx"; import DeployNodeConfigFormWebhookConfig from "./DeployNodeConfigFormWebhookConfig.tsx"; @@ -195,6 +196,8 @@ const DeployNodeConfigForm = forwardRef; case DEPLOY_PROVIDERS.VOLCENGINE_DCDN: return ; + case DEPLOY_PROVIDERS.VOLCENGINE_IMAGEX: + return ; case DEPLOY_PROVIDERS.VOLCENGINE_LIVE: return ; case DEPLOY_PROVIDERS.VOLCENGINE_TOS: diff --git a/ui/src/components/workflow/node/DeployNodeConfigFormVolcEngineImageXConfig.tsx b/ui/src/components/workflow/node/DeployNodeConfigFormVolcEngineImageXConfig.tsx new file mode 100644 index 00000000..61f59e23 --- /dev/null +++ b/ui/src/components/workflow/node/DeployNodeConfigFormVolcEngineImageXConfig.tsx @@ -0,0 +1,91 @@ +import { useTranslation } from "react-i18next"; +import { Form, type FormInstance, Input } from "antd"; +import { createSchemaFieldRule } from "antd-zod"; +import { z } from "zod"; + +import { validDomainName } from "@/utils/validators"; + +type DeployNodeConfigFormVolcEngineImageXConfigFieldValues = Nullish<{ + domain: string; +}>; + +export type DeployNodeConfigFormVolcEngineImageXConfigProps = { + form: FormInstance; + formName: string; + disabled?: boolean; + initialValues?: DeployNodeConfigFormVolcEngineImageXConfigFieldValues; + onValuesChange?: (values: DeployNodeConfigFormVolcEngineImageXConfigFieldValues) => void; +}; + +const initFormModel = (): DeployNodeConfigFormVolcEngineImageXConfigFieldValues => { + return {}; +}; + +const DeployNodeConfigFormVolcEngineImageXConfig = ({ + form: formInst, + formName, + disabled, + initialValues, + onValuesChange, +}: DeployNodeConfigFormVolcEngineImageXConfigProps) => { + const { t } = useTranslation(); + + const formSchema = z.object({ + region: z + .string({ message: t("workflow_node.deploy.form.volcengine_imagex_region.placeholder") }) + .nonempty(t("workflow_node.deploy.form.volcengine_imagex_region.placeholder")) + .trim(), + serviceId: z + .string({ message: t("workflow_node.deploy.form.volcengine_imagex_service_id.placeholder") }) + .nonempty(t("workflow_node.deploy.form.volcengine_imagex_service_id.placeholder")) + .trim(), + domain: z + .string({ message: t("workflow_node.deploy.form.volcengine_imagex_domain.placeholder") }) + .refine((v) => validDomainName(v), t("common.errmsg.domain_invalid")), + }); + const formRule = createSchemaFieldRule(formSchema); + + const handleFormChange = (_: unknown, values: z.infer) => { + onValuesChange?.(values); + }; + + return ( +
+ } + > + + + + } + > + + + + } + > + + +
+ ); +}; + +export default DeployNodeConfigFormVolcEngineImageXConfig; diff --git a/ui/src/domain/provider.ts b/ui/src/domain/provider.ts index 1a3272cd..c6e92535 100644 --- a/ui/src/domain/provider.ts +++ b/ui/src/domain/provider.ts @@ -211,6 +211,7 @@ export const DEPLOY_PROVIDERS = Object.freeze({ VOLCENGINE_CDN: `${ACCESS_PROVIDERS.VOLCENGINE}-cdn`, VOLCENGINE_CLB: `${ACCESS_PROVIDERS.VOLCENGINE}-clb`, VOLCENGINE_DCDN: `${ACCESS_PROVIDERS.VOLCENGINE}-dcdn`, + VOLCENGINE_IMAGEX: `${ACCESS_PROVIDERS.VOLCENGINE}-imagex`, VOLCENGINE_LIVE: `${ACCESS_PROVIDERS.VOLCENGINE}-live`, VOLCENGINE_TOS: `${ACCESS_PROVIDERS.VOLCENGINE}-tos`, WEBHOOK: `${ACCESS_PROVIDERS.WEBHOOK}`, @@ -273,6 +274,7 @@ export const deployProvidersMap: Maphttps://console.volcengine.com/dcdn/dashboard", + "workflow_node.deploy.form.volcengine_imagex_region.label": "VolcEngine ImageX region", + "workflow_node.deploy.form.volcengine_imagex_region.placeholder": "Please enter VolcEngine ImageX region (e.g. cn-north-1)", + "workflow_node.deploy.form.volcengine_imagex_region.tooltip": "For more information, see https://www.volcengine.com/docs/508/23757", + "workflow_node.deploy.form.volcengine_imagex_service_id.label": "VolcEngine ImageX service ID", + "workflow_node.deploy.form.volcengine_imagex_service_id.placeholder": "Please enter VolcEngine ImageX service ID", + "workflow_node.deploy.form.volcengine_imagex_service_id.tooltip": "For more information, see https://console.volcengine.com/imagex", + "workflow_node.deploy.form.volcengine_imagex_domain.label": "VolcEngine ImageX domain", + "workflow_node.deploy.form.volcengine_imagex_domain.placeholder": "Please enter VolcEngine ImageX domain name", + "workflow_node.deploy.form.volcengine_imagex_domain.tooltip": "For more information, see https://console.volcengine.com/imagex", "workflow_node.deploy.form.volcengine_live_domain.label": "VolcEngine Live streaming domain", "workflow_node.deploy.form.volcengine_live_domain.placeholder": "Please enter VolcEngine Live streaming domain name", "workflow_node.deploy.form.volcengine_live_domain.tooltip": "For more information, see https://console.volcengine.com/live", diff --git a/ui/src/i18n/locales/zh/nls.provider.json b/ui/src/i18n/locales/zh/nls.provider.json index a4146670..42453b04 100644 --- a/ui/src/i18n/locales/zh/nls.provider.json +++ b/ui/src/i18n/locales/zh/nls.provider.json @@ -79,6 +79,7 @@ "provider.volcengine.clb": "火山引擎 - 负载均衡 CLB", "provider.volcengine.dcdn": "火山引擎 - 全站加速 DCDN", "provider.volcengine.dns": "火山引擎 - 云解析 DNS", + "provider.volcengine.imagex": "火山引擎 - 图片服务 ImageX", "provider.volcengine.live": "火山引擎 - 视频直播 Live", "provider.volcengine.tos": "火山引擎 - 对象存储 TOS", "provider.webhook": "Webhook", diff --git a/ui/src/i18n/locales/zh/nls.workflow.nodes.json b/ui/src/i18n/locales/zh/nls.workflow.nodes.json index 705d8056..a4062398 100644 --- a/ui/src/i18n/locales/zh/nls.workflow.nodes.json +++ b/ui/src/i18n/locales/zh/nls.workflow.nodes.json @@ -403,11 +403,20 @@ "workflow_node.deploy.form.volcengine_dcdn_domain.label": "火山引擎 DCDN 加速域名(支持泛域名)", "workflow_node.deploy.form.volcengine_dcdn_domain.placeholder": "请输入火山引擎 DCDN 加速域名", "workflow_node.deploy.form.volcengine_dcdn_domain.tooltip": "这是什么?请参阅 https://console.volcengine.com/dcdn/dashboard

泛域名表示形式为:*.example.com", + "workflow_node.deploy.form.volcengine_imagex_region.label": "火山引擎 ImageX 服务地域", + "workflow_node.deploy.form.volcengine_imagex_region.placeholder": "请输入火山引擎 ImageX 服务地域(例如:cn-north-1)", + "workflow_node.deploy.form.volcengine_imagex_region.tooltip": "这是什么?请参阅 https://www.volcengine.com/docs/508/23757", + "workflow_node.deploy.form.volcengine_imagex_service_id.label": "火山引擎 TOS 服务 ID", + "workflow_node.deploy.form.volcengine_imagex_service_id.placeholder": "请输入火山引擎 TOS 服务 ID", + "workflow_node.deploy.form.volcengine_imagex_service_id.tooltip": "这是什么?请参阅 https://console.volcengine.com/imagex", + "workflow_node.deploy.form.volcengine_imagex_domain.label": "火山引擎 ImageX 绑定域名", + "workflow_node.deploy.form.volcengine_imagex_domain.placeholder": "请输入火山引擎 ImageX 绑定域名", + "workflow_node.deploy.form.volcengine_imagex_domain.tooltip": "这是什么?请参阅 see https://console.volcengine.com/imagex", "workflow_node.deploy.form.volcengine_live_domain.label": "火山引擎视频直播流域名(支持泛域名)", "workflow_node.deploy.form.volcengine_live_domain.placeholder": "请输入火山引擎视频直播流域名", "workflow_node.deploy.form.volcengine_live_domain.tooltip": "这是什么?请参阅 https://console.volcengine.com/live

泛域名表示形式为:*.example.com", "workflow_node.deploy.form.volcengine_tos_region.label": "火山引擎 TOS 服务地域", - "workflow_node.deploy.form.volcengine_tos_region.placeholder": "请输入火山引擎 TOS 服务地域(例如:cn-beijing", + "workflow_node.deploy.form.volcengine_tos_region.placeholder": "请输入火山引擎 TOS 服务地域(例如:cn-beijing)", "workflow_node.deploy.form.volcengine_tos_region.tooltip": "这是什么?请参阅 https://www.volcengine.com/docs/6349/107356", "workflow_node.deploy.form.volcengine_tos_bucket.label": "火山引擎 TOS 存储桶名", "workflow_node.deploy.form.volcengine_tos_bucket.placeholder": "请输入火山引擎 TOS 存储桶名", From b734ffcf9d1c60334605c653dca9ee5a2df05498 Mon Sep 17 00:00:00 2001 From: Fu Diwei Date: Sat, 15 Feb 2025 23:32:09 +0800 Subject: [PATCH 02/34] feat: add baotapanel console deployer --- internal/applicant/providers.go | 68 +++--- internal/deployer/providers.go | 195 ++++++++++-------- internal/domain/provider.go | 1 + internal/notify/providers.go | 32 +-- .../baotapanel-console/baotapanel_console.go | 87 ++++++++ .../baotapanel_console_test.go | 70 +++++++ .../baotapanel-site/baotapanel_site.go | 18 +- internal/pkg/vendors/btpanel-sdk/api.go | 42 +++- internal/pkg/vendors/btpanel-sdk/client.go | 30 ++- .../workflow/node/DeployNodeConfigForm.tsx | 3 + ...yNodeConfigFormBaotaPanelConsoleConfig.tsx | 56 +++++ ui/src/domain/provider.ts | 2 + ui/src/i18n/locales/en/nls.provider.json | 1 + .../i18n/locales/en/nls.workflow.nodes.json | 1 + ui/src/i18n/locales/zh/nls.provider.json | 1 + .../i18n/locales/zh/nls.workflow.nodes.json | 1 + 16 files changed, 447 insertions(+), 161 deletions(-) create mode 100644 internal/pkg/core/deployer/providers/baotapanel-console/baotapanel_console.go create mode 100644 internal/pkg/core/deployer/providers/baotapanel-console/baotapanel_console_test.go create mode 100644 ui/src/components/workflow/node/DeployNodeConfigFormBaotaPanelConsoleConfig.tsx diff --git a/internal/applicant/providers.go b/internal/applicant/providers.go index d992e9c1..1866637e 100644 --- a/internal/applicant/providers.go +++ b/internal/applicant/providers.go @@ -6,23 +6,23 @@ import ( "github.com/go-acme/lego/v4/challenge" "github.com/usual2970/certimate/internal/domain" - providerACMEHttpReq "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/acmehttpreq" - providerAliyun "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/aliyun" - providerAWSRoute53 "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/aws-route53" - providerAzureDNS "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/azure-dns" - providerCloudflare "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/cloudflare" - providerClouDNS "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/cloudns" - providerGname "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/gname" - providerGoDaddy "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/godaddy" - providerHuaweiCloud "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/huaweicloud" - providerNameDotCom "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/namedotcom" - providerNameSilo "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/namesilo" - providerNS1 "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/ns1" - providerPowerDNS "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/powerdns" - providerRainYun "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/rainyun" - providerTencentCloud "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/tencentcloud" - providerVolcEngine "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/volcengine" - providerWestcn "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/westcn" + pACMEHttpReq "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/acmehttpreq" + pAliyun "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/aliyun" + pAWSRoute53 "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/aws-route53" + pAzureDNS "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/azure-dns" + pCloudflare "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/cloudflare" + pClouDNS "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/cloudns" + pGname "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/gname" + pGoDaddy "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/godaddy" + pHuaweiCloud "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/huaweicloud" + pNameDotCom "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/namedotcom" + pNameSilo "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/namesilo" + pNS1 "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/ns1" + pPowerDNS "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/powerdns" + pRainYun "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/rainyun" + pTencentCloud "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/tencentcloud" + pVolcEngine "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/volcengine" + pWestcn "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/westcn" "github.com/usual2970/certimate/internal/pkg/utils/maps" ) @@ -39,7 +39,7 @@ func createApplicant(options *applicantOptions) (challenge.Provider, error) { return nil, fmt.Errorf("failed to populate provider access config: %w", err) } - applicant, err := providerACMEHttpReq.NewChallengeProvider(&providerACMEHttpReq.ACMEHttpReqApplicantConfig{ + applicant, err := pACMEHttpReq.NewChallengeProvider(&pACMEHttpReq.ACMEHttpReqApplicantConfig{ Endpoint: access.Endpoint, Mode: access.Mode, Username: access.Username, @@ -56,7 +56,7 @@ func createApplicant(options *applicantOptions) (challenge.Provider, error) { return nil, fmt.Errorf("failed to populate provider access config: %w", err) } - applicant, err := providerAliyun.NewChallengeProvider(&providerAliyun.AliyunApplicantConfig{ + applicant, err := pAliyun.NewChallengeProvider(&pAliyun.AliyunApplicantConfig{ AccessKeyId: access.AccessKeyId, AccessKeySecret: access.AccessKeySecret, DnsPropagationTimeout: options.DnsPropagationTimeout, @@ -72,7 +72,7 @@ func createApplicant(options *applicantOptions) (challenge.Provider, error) { return nil, fmt.Errorf("failed to populate provider access config: %w", err) } - applicant, err := providerAWSRoute53.NewChallengeProvider(&providerAWSRoute53.AWSRoute53ApplicantConfig{ + applicant, err := pAWSRoute53.NewChallengeProvider(&pAWSRoute53.AWSRoute53ApplicantConfig{ AccessKeyId: access.AccessKeyId, SecretAccessKey: access.SecretAccessKey, Region: maps.GetValueAsString(options.ProviderApplyConfig, "region"), @@ -90,7 +90,7 @@ func createApplicant(options *applicantOptions) (challenge.Provider, error) { return nil, fmt.Errorf("failed to populate provider access config: %w", err) } - applicant, err := providerAzureDNS.NewChallengeProvider(&providerAzureDNS.AzureDNSApplicantConfig{ + applicant, err := pAzureDNS.NewChallengeProvider(&pAzureDNS.AzureDNSApplicantConfig{ TenantId: access.TenantId, ClientId: access.ClientId, ClientSecret: access.ClientSecret, @@ -108,7 +108,7 @@ func createApplicant(options *applicantOptions) (challenge.Provider, error) { return nil, fmt.Errorf("failed to populate provider access config: %w", err) } - applicant, err := providerCloudflare.NewChallengeProvider(&providerCloudflare.CloudflareApplicantConfig{ + applicant, err := pCloudflare.NewChallengeProvider(&pCloudflare.CloudflareApplicantConfig{ DnsApiToken: access.DnsApiToken, DnsPropagationTimeout: options.DnsPropagationTimeout, DnsTTL: options.DnsTTL, @@ -123,7 +123,7 @@ func createApplicant(options *applicantOptions) (challenge.Provider, error) { return nil, fmt.Errorf("failed to populate provider access config: %w", err) } - applicant, err := providerClouDNS.NewChallengeProvider(&providerClouDNS.ClouDNSApplicantConfig{ + applicant, err := pClouDNS.NewChallengeProvider(&pClouDNS.ClouDNSApplicantConfig{ AuthId: access.AuthId, AuthPassword: access.AuthPassword, DnsPropagationTimeout: options.DnsPropagationTimeout, @@ -139,7 +139,7 @@ func createApplicant(options *applicantOptions) (challenge.Provider, error) { return nil, fmt.Errorf("failed to populate provider access config: %w", err) } - applicant, err := providerGname.NewChallengeProvider(&providerGname.GnameApplicantConfig{ + applicant, err := pGname.NewChallengeProvider(&pGname.GnameApplicantConfig{ AppId: access.AppId, AppKey: access.AppKey, DnsPropagationTimeout: options.DnsPropagationTimeout, @@ -155,7 +155,7 @@ func createApplicant(options *applicantOptions) (challenge.Provider, error) { return nil, fmt.Errorf("failed to populate provider access config: %w", err) } - applicant, err := providerGoDaddy.NewChallengeProvider(&providerGoDaddy.GoDaddyApplicantConfig{ + applicant, err := pGoDaddy.NewChallengeProvider(&pGoDaddy.GoDaddyApplicantConfig{ ApiKey: access.ApiKey, ApiSecret: access.ApiSecret, DnsPropagationTimeout: options.DnsPropagationTimeout, @@ -171,7 +171,7 @@ func createApplicant(options *applicantOptions) (challenge.Provider, error) { return nil, fmt.Errorf("failed to populate provider access config: %w", err) } - applicant, err := providerHuaweiCloud.NewChallengeProvider(&providerHuaweiCloud.HuaweiCloudApplicantConfig{ + applicant, err := pHuaweiCloud.NewChallengeProvider(&pHuaweiCloud.HuaweiCloudApplicantConfig{ AccessKeyId: access.AccessKeyId, SecretAccessKey: access.SecretAccessKey, Region: maps.GetValueAsString(options.ProviderApplyConfig, "region"), @@ -188,7 +188,7 @@ func createApplicant(options *applicantOptions) (challenge.Provider, error) { return nil, fmt.Errorf("failed to populate provider access config: %w", err) } - applicant, err := providerNameDotCom.NewChallengeProvider(&providerNameDotCom.NameDotComApplicantConfig{ + applicant, err := pNameDotCom.NewChallengeProvider(&pNameDotCom.NameDotComApplicantConfig{ Username: access.Username, ApiToken: access.ApiToken, DnsPropagationTimeout: options.DnsPropagationTimeout, @@ -204,7 +204,7 @@ func createApplicant(options *applicantOptions) (challenge.Provider, error) { return nil, fmt.Errorf("failed to populate provider access config: %w", err) } - applicant, err := providerNameSilo.NewChallengeProvider(&providerNameSilo.NameSiloApplicantConfig{ + applicant, err := pNameSilo.NewChallengeProvider(&pNameSilo.NameSiloApplicantConfig{ ApiKey: access.ApiKey, DnsPropagationTimeout: options.DnsPropagationTimeout, DnsTTL: options.DnsTTL, @@ -219,7 +219,7 @@ func createApplicant(options *applicantOptions) (challenge.Provider, error) { return nil, fmt.Errorf("failed to populate provider access config: %w", err) } - applicant, err := providerNS1.NewChallengeProvider(&providerNS1.NS1ApplicantConfig{ + applicant, err := pNS1.NewChallengeProvider(&pNS1.NS1ApplicantConfig{ ApiKey: access.ApiKey, DnsPropagationTimeout: options.DnsPropagationTimeout, DnsTTL: options.DnsTTL, @@ -234,7 +234,7 @@ func createApplicant(options *applicantOptions) (challenge.Provider, error) { return nil, fmt.Errorf("failed to populate provider access config: %w", err) } - applicant, err := providerPowerDNS.NewChallengeProvider(&providerPowerDNS.PowerDNSApplicantConfig{ + applicant, err := pPowerDNS.NewChallengeProvider(&pPowerDNS.PowerDNSApplicantConfig{ ApiUrl: access.ApiUrl, ApiKey: access.ApiKey, DnsPropagationTimeout: options.DnsPropagationTimeout, @@ -250,7 +250,7 @@ func createApplicant(options *applicantOptions) (challenge.Provider, error) { return nil, fmt.Errorf("failed to populate provider access config: %w", err) } - applicant, err := providerRainYun.NewChallengeProvider(&providerRainYun.RainYunApplicantConfig{ + applicant, err := pRainYun.NewChallengeProvider(&pRainYun.RainYunApplicantConfig{ ApiKey: access.ApiKey, DnsPropagationTimeout: options.DnsPropagationTimeout, DnsTTL: options.DnsTTL, @@ -265,7 +265,7 @@ func createApplicant(options *applicantOptions) (challenge.Provider, error) { return nil, fmt.Errorf("failed to populate provider access config: %w", err) } - applicant, err := providerTencentCloud.NewChallengeProvider(&providerTencentCloud.TencentCloudApplicantConfig{ + applicant, err := pTencentCloud.NewChallengeProvider(&pTencentCloud.TencentCloudApplicantConfig{ SecretId: access.SecretId, SecretKey: access.SecretKey, DnsPropagationTimeout: options.DnsPropagationTimeout, @@ -281,7 +281,7 @@ func createApplicant(options *applicantOptions) (challenge.Provider, error) { return nil, fmt.Errorf("failed to populate provider access config: %w", err) } - applicant, err := providerVolcEngine.NewChallengeProvider(&providerVolcEngine.VolcEngineApplicantConfig{ + applicant, err := pVolcEngine.NewChallengeProvider(&pVolcEngine.VolcEngineApplicantConfig{ AccessKeyId: access.AccessKeyId, SecretAccessKey: access.SecretAccessKey, DnsPropagationTimeout: options.DnsPropagationTimeout, @@ -297,7 +297,7 @@ func createApplicant(options *applicantOptions) (challenge.Provider, error) { return nil, fmt.Errorf("failed to populate provider access config: %w", err) } - applicant, err := providerWestcn.NewChallengeProvider(&providerWestcn.WestcnApplicantConfig{ + applicant, err := pWestcn.NewChallengeProvider(&pWestcn.WestcnApplicantConfig{ Username: access.Username, ApiPassword: access.ApiPassword, DnsPropagationTimeout: options.DnsPropagationTimeout, diff --git a/internal/deployer/providers.go b/internal/deployer/providers.go index d6e149ed..8d92b10f 100644 --- a/internal/deployer/providers.go +++ b/internal/deployer/providers.go @@ -6,45 +6,46 @@ import ( "github.com/usual2970/certimate/internal/domain" "github.com/usual2970/certimate/internal/pkg/core/deployer" - providerAliyunALB "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/aliyun-alb" - providerAliyunCASDeploy "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/aliyun-cas-deploy" - providerAliyunCDN "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/aliyun-cdn" - providerAliyunCLB "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/aliyun-clb" - providerAliyunDCDN "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/aliyun-dcdn" - providerAliyunESA "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/aliyun-esa" - providerAliyunLive "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/aliyun-live" - providerAliyunNLB "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/aliyun-nlb" - providerAliyunOSS "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/aliyun-oss" - providerAliyunWAF "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/aliyun-waf" - providerAWSCloudFront "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/aws-cloudfront" - providerBaiduCloudCDN "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/baiducloud-cdn" - providerBaotaPanelSite "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/baotapanel-site" - providerBytePlusCDN "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/byteplus-cdn" - providerDogeCDN "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/dogecloud-cdn" - providerEdgioApplications "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/edgio-applications" - providerHuaweiCloudCDN "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/huaweicloud-cdn" - providerHuaweiCloudELB "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/huaweicloud-elb" - providerK8sSecret "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/k8s-secret" - providerLocal "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/local" - providerQiniuCDN "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/qiniu-cdn" - providerQiniuPili "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/qiniu-pili" + pAliyunALB "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/aliyun-alb" + pAliyunCASDeploy "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/aliyun-cas-deploy" + pAliyunCDN "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/aliyun-cdn" + pAliyunCLB "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/aliyun-clb" + pAliyunDCDN "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/aliyun-dcdn" + pAliyunESA "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/aliyun-esa" + pAliyunLive "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/aliyun-live" + pAliyunNLB "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/aliyun-nlb" + pAliyunOSS "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/aliyun-oss" + pAliyunWAF "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/aliyun-waf" + pAWSCloudFront "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/aws-cloudfront" + pBaiduCloudCDN "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/baiducloud-cdn" + pBaotaPanelConsole "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/baotapanel-console" + pBaotaPanelSite "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/baotapanel-site" + pBytePlusCDN "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/byteplus-cdn" + pDogeCDN "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/dogecloud-cdn" + pEdgioApplications "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/edgio-applications" + pHuaweiCloudCDN "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/huaweicloud-cdn" + pHuaweiCloudELB "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/huaweicloud-elb" + pK8sSecret "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/k8s-secret" + pLocal "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/local" + pQiniuCDN "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/qiniu-cdn" + pQiniuPili "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/qiniu-pili" providerSSH "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/ssh" - providerTencentCloudCDN "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/tencentcloud-cdn" - providerTencentCloudCLB "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/tencentcloud-clb" - providerTencentCloudCOS "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/tencentcloud-cos" - providerTencentCloudCSS "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/tencentcloud-css" - providerTencentCloudECDN "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/tencentcloud-ecdn" - providerTencentCloudEO "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/tencentcloud-eo" - providerTencentCloudSSLDeploy "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/tencentcloud-ssl-deploy" - providerUCloudUCDN "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/ucloud-ucdn" - providerUCloudUS3 "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/ucloud-us3" - providerVolcEngineCDN "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/volcengine-cdn" - providerVolcEngineCLB "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/volcengine-clb" - providerVolcEngineDCDN "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/volcengine-dcdn" - providerVolcEngineImageX "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/volcengine-imagex" - providerVolcEngineLive "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/volcengine-live" - providerVolcEngineTOS "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/volcengine-tos" - providerWebhook "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/webhook" + pTencentCloudCDN "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/tencentcloud-cdn" + pTencentCloudCLB "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/tencentcloud-clb" + pTencentCloudCOS "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/tencentcloud-cos" + pTencentCloudCSS "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/tencentcloud-css" + pTencentCloudECDN "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/tencentcloud-ecdn" + pTencentCloudEO "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/tencentcloud-eo" + pTencentCloudSSLDeploy "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/tencentcloud-ssl-deploy" + pUCloudUCDN "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/ucloud-ucdn" + pUCloudUS3 "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/ucloud-us3" + pVolcEngineCDN "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/volcengine-cdn" + pVolcEngineCLB "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/volcengine-clb" + pVolcEngineDCDN "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/volcengine-dcdn" + pVolcEngineImageX "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/volcengine-imagex" + pVolcEngineLive "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/volcengine-live" + pVolcEngineTOS "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/volcengine-tos" + pWebhook "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/webhook" "github.com/usual2970/certimate/internal/pkg/core/logger" "github.com/usual2970/certimate/internal/pkg/utils/maps" "github.com/usual2970/certimate/internal/pkg/utils/slices" @@ -67,11 +68,11 @@ func createDeployer(options *deployerOptions) (deployer.Deployer, logger.Logger, switch options.Provider { case domain.DeployProviderTypeAliyunALB: - deployer, err := providerAliyunALB.NewWithLogger(&providerAliyunALB.AliyunALBDeployerConfig{ + deployer, err := pAliyunALB.NewWithLogger(&pAliyunALB.AliyunALBDeployerConfig{ AccessKeyId: access.AccessKeyId, AccessKeySecret: access.AccessKeySecret, Region: maps.GetValueAsString(options.ProviderDeployConfig, "region"), - ResourceType: providerAliyunALB.DeployResourceType(maps.GetValueAsString(options.ProviderDeployConfig, "resourceType")), + ResourceType: pAliyunALB.DeployResourceType(maps.GetValueAsString(options.ProviderDeployConfig, "resourceType")), LoadbalancerId: maps.GetValueAsString(options.ProviderDeployConfig, "loadbalancerId"), ListenerId: maps.GetValueAsString(options.ProviderDeployConfig, "listenerId"), Domain: maps.GetValueAsString(options.ProviderDeployConfig, "domain"), @@ -79,7 +80,7 @@ func createDeployer(options *deployerOptions) (deployer.Deployer, logger.Logger, return deployer, logger, err case domain.DeployProviderTypeAliyunCASDeploy: - deployer, err := providerAliyunCASDeploy.NewWithLogger(&providerAliyunCASDeploy.AliyunCASDeployDeployerConfig{ + deployer, err := pAliyunCASDeploy.NewWithLogger(&pAliyunCASDeploy.AliyunCASDeployDeployerConfig{ AccessKeyId: access.AccessKeyId, AccessKeySecret: access.AccessKeySecret, Region: maps.GetValueAsString(options.ProviderDeployConfig, "region"), @@ -89,7 +90,7 @@ func createDeployer(options *deployerOptions) (deployer.Deployer, logger.Logger, return deployer, logger, err case domain.DeployProviderTypeAliyunCDN: - deployer, err := providerAliyunCDN.NewWithLogger(&providerAliyunCDN.AliyunCDNDeployerConfig{ + deployer, err := pAliyunCDN.NewWithLogger(&pAliyunCDN.AliyunCDNDeployerConfig{ AccessKeyId: access.AccessKeyId, AccessKeySecret: access.AccessKeySecret, Domain: maps.GetValueAsString(options.ProviderDeployConfig, "domain"), @@ -97,11 +98,11 @@ func createDeployer(options *deployerOptions) (deployer.Deployer, logger.Logger, return deployer, logger, err case domain.DeployProviderTypeAliyunCLB: - deployer, err := providerAliyunCLB.NewWithLogger(&providerAliyunCLB.AliyunCLBDeployerConfig{ + deployer, err := pAliyunCLB.NewWithLogger(&pAliyunCLB.AliyunCLBDeployerConfig{ AccessKeyId: access.AccessKeyId, AccessKeySecret: access.AccessKeySecret, Region: maps.GetValueAsString(options.ProviderDeployConfig, "region"), - ResourceType: providerAliyunCLB.DeployResourceType(maps.GetValueAsString(options.ProviderDeployConfig, "resourceType")), + ResourceType: pAliyunCLB.DeployResourceType(maps.GetValueAsString(options.ProviderDeployConfig, "resourceType")), LoadbalancerId: maps.GetValueAsString(options.ProviderDeployConfig, "loadbalancerId"), ListenerPort: maps.GetValueOrDefaultAsInt32(options.ProviderDeployConfig, "listenerPort", 443), Domain: maps.GetValueAsString(options.ProviderDeployConfig, "domain"), @@ -109,7 +110,7 @@ func createDeployer(options *deployerOptions) (deployer.Deployer, logger.Logger, return deployer, logger, err case domain.DeployProviderTypeAliyunDCDN: - deployer, err := providerAliyunDCDN.NewWithLogger(&providerAliyunDCDN.AliyunDCDNDeployerConfig{ + deployer, err := pAliyunDCDN.NewWithLogger(&pAliyunDCDN.AliyunDCDNDeployerConfig{ AccessKeyId: access.AccessKeyId, AccessKeySecret: access.AccessKeySecret, Domain: maps.GetValueAsString(options.ProviderDeployConfig, "domain"), @@ -117,7 +118,7 @@ func createDeployer(options *deployerOptions) (deployer.Deployer, logger.Logger, return deployer, logger, err case domain.DeployProviderTypeAliyunESA: - deployer, err := providerAliyunESA.NewWithLogger(&providerAliyunESA.AliyunESADeployerConfig{ + deployer, err := pAliyunESA.NewWithLogger(&pAliyunESA.AliyunESADeployerConfig{ AccessKeyId: access.AccessKeyId, AccessKeySecret: access.AccessKeySecret, Region: maps.GetValueAsString(options.ProviderDeployConfig, "region"), @@ -126,7 +127,7 @@ func createDeployer(options *deployerOptions) (deployer.Deployer, logger.Logger, return deployer, logger, err case domain.DeployProviderTypeAliyunLive: - deployer, err := providerAliyunLive.NewWithLogger(&providerAliyunLive.AliyunLiveDeployerConfig{ + deployer, err := pAliyunLive.NewWithLogger(&pAliyunLive.AliyunLiveDeployerConfig{ AccessKeyId: access.AccessKeyId, AccessKeySecret: access.AccessKeySecret, Region: maps.GetValueAsString(options.ProviderDeployConfig, "region"), @@ -135,18 +136,18 @@ func createDeployer(options *deployerOptions) (deployer.Deployer, logger.Logger, return deployer, logger, err case domain.DeployProviderTypeAliyunNLB: - deployer, err := providerAliyunNLB.NewWithLogger(&providerAliyunNLB.AliyunNLBDeployerConfig{ + deployer, err := pAliyunNLB.NewWithLogger(&pAliyunNLB.AliyunNLBDeployerConfig{ AccessKeyId: access.AccessKeyId, AccessKeySecret: access.AccessKeySecret, Region: maps.GetValueAsString(options.ProviderDeployConfig, "region"), - ResourceType: providerAliyunNLB.DeployResourceType(maps.GetValueAsString(options.ProviderDeployConfig, "resourceType")), + ResourceType: pAliyunNLB.DeployResourceType(maps.GetValueAsString(options.ProviderDeployConfig, "resourceType")), LoadbalancerId: maps.GetValueAsString(options.ProviderDeployConfig, "loadbalancerId"), ListenerId: maps.GetValueAsString(options.ProviderDeployConfig, "listenerId"), }, logger) return deployer, logger, err case domain.DeployProviderTypeAliyunOSS: - deployer, err := providerAliyunOSS.NewWithLogger(&providerAliyunOSS.AliyunOSSDeployerConfig{ + deployer, err := pAliyunOSS.NewWithLogger(&pAliyunOSS.AliyunOSSDeployerConfig{ AccessKeyId: access.AccessKeyId, AccessKeySecret: access.AccessKeySecret, Region: maps.GetValueAsString(options.ProviderDeployConfig, "region"), @@ -156,7 +157,7 @@ func createDeployer(options *deployerOptions) (deployer.Deployer, logger.Logger, return deployer, logger, err case domain.DeployProviderTypeAliyunWAF: - deployer, err := providerAliyunWAF.NewWithLogger(&providerAliyunWAF.AliyunWAFDeployerConfig{ + deployer, err := pAliyunWAF.NewWithLogger(&pAliyunWAF.AliyunWAFDeployerConfig{ AccessKeyId: access.AccessKeyId, AccessKeySecret: access.AccessKeySecret, Region: maps.GetValueAsString(options.ProviderDeployConfig, "region"), @@ -178,7 +179,7 @@ func createDeployer(options *deployerOptions) (deployer.Deployer, logger.Logger, switch options.Provider { case domain.DeployProviderTypeAWSCloudFront: - deployer, err := providerAWSCloudFront.NewWithLogger(&providerAWSCloudFront.AWSCloudFrontDeployerConfig{ + deployer, err := pAWSCloudFront.NewWithLogger(&pAWSCloudFront.AWSCloudFrontDeployerConfig{ AccessKeyId: access.AccessKeyId, SecretAccessKey: access.SecretAccessKey, Region: maps.GetValueAsString(options.ProviderDeployConfig, "region"), @@ -200,7 +201,7 @@ func createDeployer(options *deployerOptions) (deployer.Deployer, logger.Logger, switch options.Provider { case domain.DeployProviderTypeBaiduCloudCDN: - deployer, err := providerBaiduCloudCDN.NewWithLogger(&providerBaiduCloudCDN.BaiduCloudCDNDeployerConfig{ + deployer, err := pBaiduCloudCDN.NewWithLogger(&pBaiduCloudCDN.BaiduCloudCDNDeployerConfig{ AccessKeyId: access.AccessKeyId, SecretAccessKey: access.SecretAccessKey, Domain: maps.GetValueAsString(options.ProviderDeployConfig, "domain"), @@ -212,19 +213,33 @@ func createDeployer(options *deployerOptions) (deployer.Deployer, logger.Logger, } } - case domain.DeployProviderTypeBaotaPanelSite: + case domain.DeployProviderTypeBaotaPanelConsole, domain.DeployProviderTypeBaotaPanelSite: { access := domain.AccessConfigForBaotaPanel{} if err := maps.Populate(options.ProviderAccessConfig, &access); err != nil { return nil, nil, fmt.Errorf("failed to populate provider access config: %w", err) } - deployer, err := providerBaotaPanelSite.NewWithLogger(&providerBaotaPanelSite.BaotaPanelSiteDeployerConfig{ - ApiUrl: access.ApiUrl, - ApiKey: access.ApiKey, - SiteName: maps.GetValueAsString(options.ProviderDeployConfig, "siteName"), - }, logger) - return deployer, logger, err + switch options.Provider { + case domain.DeployProviderTypeBaotaPanelConsole: + deployer, err := pBaotaPanelConsole.NewWithLogger(&pBaotaPanelConsole.BaotaPanelConsoleDeployerConfig{ + ApiUrl: access.ApiUrl, + ApiKey: access.ApiKey, + AutoRestart: maps.GetValueAsBool(options.ProviderDeployConfig, "autoRestart"), + }, logger) + return deployer, logger, err + + case domain.DeployProviderTypeBaotaPanelSite: + deployer, err := pBaotaPanelSite.NewWithLogger(&pBaotaPanelSite.BaotaPanelSiteDeployerConfig{ + ApiUrl: access.ApiUrl, + ApiKey: access.ApiKey, + SiteName: maps.GetValueAsString(options.ProviderDeployConfig, "siteName"), + }, logger) + return deployer, logger, err + + default: + break + } } case domain.DeployProviderTypeBytePlusCDN: @@ -236,7 +251,7 @@ func createDeployer(options *deployerOptions) (deployer.Deployer, logger.Logger, switch options.Provider { case domain.DeployProviderTypeBytePlusCDN: - deployer, err := providerBytePlusCDN.NewWithLogger(&providerBytePlusCDN.BytePlusCDNDeployerConfig{ + deployer, err := pBytePlusCDN.NewWithLogger(&pBytePlusCDN.BytePlusCDNDeployerConfig{ AccessKey: access.AccessKey, SecretKey: access.SecretKey, Domain: maps.GetValueAsString(options.ProviderDeployConfig, "domain"), @@ -255,7 +270,7 @@ func createDeployer(options *deployerOptions) (deployer.Deployer, logger.Logger, return nil, nil, fmt.Errorf("failed to populate provider access config: %w", err) } - deployer, err := providerDogeCDN.NewWithLogger(&providerDogeCDN.DogeCloudCDNDeployerConfig{ + deployer, err := pDogeCDN.NewWithLogger(&pDogeCDN.DogeCloudCDNDeployerConfig{ AccessKey: access.AccessKey, SecretKey: access.SecretKey, Domain: maps.GetValueAsString(options.ProviderDeployConfig, "domain"), @@ -270,7 +285,7 @@ func createDeployer(options *deployerOptions) (deployer.Deployer, logger.Logger, return nil, nil, fmt.Errorf("failed to populate provider access config: %w", err) } - deployer, err := providerEdgioApplications.NewWithLogger(&providerEdgioApplications.EdgioApplicationsDeployerConfig{ + deployer, err := pEdgioApplications.NewWithLogger(&pEdgioApplications.EdgioApplicationsDeployerConfig{ ClientId: access.ClientId, ClientSecret: access.ClientSecret, EnvironmentId: maps.GetValueAsString(options.ProviderDeployConfig, "environmentId"), @@ -287,7 +302,7 @@ func createDeployer(options *deployerOptions) (deployer.Deployer, logger.Logger, switch options.Provider { case domain.DeployProviderTypeHuaweiCloudCDN: - deployer, err := providerHuaweiCloudCDN.NewWithLogger(&providerHuaweiCloudCDN.HuaweiCloudCDNDeployerConfig{ + deployer, err := pHuaweiCloudCDN.NewWithLogger(&pHuaweiCloudCDN.HuaweiCloudCDNDeployerConfig{ AccessKeyId: access.AccessKeyId, SecretAccessKey: access.SecretAccessKey, Region: maps.GetValueAsString(options.ProviderDeployConfig, "region"), @@ -296,11 +311,11 @@ func createDeployer(options *deployerOptions) (deployer.Deployer, logger.Logger, return deployer, logger, err case domain.DeployProviderTypeHuaweiCloudELB: - deployer, err := providerHuaweiCloudELB.NewWithLogger(&providerHuaweiCloudELB.HuaweiCloudELBDeployerConfig{ + deployer, err := pHuaweiCloudELB.NewWithLogger(&pHuaweiCloudELB.HuaweiCloudELBDeployerConfig{ AccessKeyId: access.AccessKeyId, SecretAccessKey: access.SecretAccessKey, Region: maps.GetValueAsString(options.ProviderDeployConfig, "region"), - ResourceType: providerHuaweiCloudELB.DeployResourceType(maps.GetValueAsString(options.ProviderDeployConfig, "resourceType")), + ResourceType: pHuaweiCloudELB.DeployResourceType(maps.GetValueAsString(options.ProviderDeployConfig, "resourceType")), CertificateId: maps.GetValueAsString(options.ProviderDeployConfig, "certificateId"), LoadbalancerId: maps.GetValueAsString(options.ProviderDeployConfig, "loadbalancerId"), ListenerId: maps.GetValueAsString(options.ProviderDeployConfig, "listenerId"), @@ -314,11 +329,11 @@ func createDeployer(options *deployerOptions) (deployer.Deployer, logger.Logger, case domain.DeployProviderTypeLocal: { - deployer, err := providerLocal.NewWithLogger(&providerLocal.LocalDeployerConfig{ - ShellEnv: providerLocal.ShellEnvType(maps.GetValueAsString(options.ProviderDeployConfig, "shellEnv")), + deployer, err := pLocal.NewWithLogger(&pLocal.LocalDeployerConfig{ + ShellEnv: pLocal.ShellEnvType(maps.GetValueAsString(options.ProviderDeployConfig, "shellEnv")), PreCommand: maps.GetValueAsString(options.ProviderDeployConfig, "preCommand"), PostCommand: maps.GetValueAsString(options.ProviderDeployConfig, "postCommand"), - OutputFormat: providerLocal.OutputFormatType(maps.GetValueOrDefaultAsString(options.ProviderDeployConfig, "format", string(providerLocal.OUTPUT_FORMAT_PEM))), + OutputFormat: pLocal.OutputFormatType(maps.GetValueOrDefaultAsString(options.ProviderDeployConfig, "format", string(pLocal.OUTPUT_FORMAT_PEM))), OutputCertPath: maps.GetValueAsString(options.ProviderDeployConfig, "certPath"), OutputKeyPath: maps.GetValueAsString(options.ProviderDeployConfig, "keyPath"), PfxPassword: maps.GetValueAsString(options.ProviderDeployConfig, "pfxPassword"), @@ -336,7 +351,7 @@ func createDeployer(options *deployerOptions) (deployer.Deployer, logger.Logger, return nil, nil, fmt.Errorf("failed to populate provider access config: %w", err) } - deployer, err := providerK8sSecret.NewWithLogger(&providerK8sSecret.K8sSecretDeployerConfig{ + deployer, err := pK8sSecret.NewWithLogger(&pK8sSecret.K8sSecretDeployerConfig{ KubeConfig: access.KubeConfig, Namespace: maps.GetValueOrDefaultAsString(options.ProviderDeployConfig, "namespace", "default"), SecretName: maps.GetValueAsString(options.ProviderDeployConfig, "secretName"), @@ -356,7 +371,7 @@ func createDeployer(options *deployerOptions) (deployer.Deployer, logger.Logger, switch options.Provider { case domain.DeployProviderTypeQiniuCDN: - deployer, err := providerQiniuCDN.NewWithLogger(&providerQiniuCDN.QiniuCDNDeployerConfig{ + deployer, err := pQiniuCDN.NewWithLogger(&pQiniuCDN.QiniuCDNDeployerConfig{ AccessKey: access.AccessKey, SecretKey: access.SecretKey, Domain: maps.GetValueAsString(options.ProviderDeployConfig, "domain"), @@ -364,7 +379,7 @@ func createDeployer(options *deployerOptions) (deployer.Deployer, logger.Logger, return deployer, logger, err case domain.DeployProviderTypeQiniuPili: - deployer, err := providerQiniuPili.NewWithLogger(&providerQiniuPili.QiniuPiliDeployerConfig{ + deployer, err := pQiniuPili.NewWithLogger(&pQiniuPili.QiniuPiliDeployerConfig{ AccessKey: access.AccessKey, SecretKey: access.SecretKey, Hub: maps.GetValueAsString(options.ProviderDeployConfig, "hub"), @@ -414,7 +429,7 @@ func createDeployer(options *deployerOptions) (deployer.Deployer, logger.Logger, switch options.Provider { case domain.DeployProviderTypeTencentCloudCDN: - deployer, err := providerTencentCloudCDN.NewWithLogger(&providerTencentCloudCDN.TencentCloudCDNDeployerConfig{ + deployer, err := pTencentCloudCDN.NewWithLogger(&pTencentCloudCDN.TencentCloudCDNDeployerConfig{ SecretId: access.SecretId, SecretKey: access.SecretKey, Domain: maps.GetValueAsString(options.ProviderDeployConfig, "domain"), @@ -422,11 +437,11 @@ func createDeployer(options *deployerOptions) (deployer.Deployer, logger.Logger, return deployer, logger, err case domain.DeployProviderTypeTencentCloudCLB: - deployer, err := providerTencentCloudCLB.NewWithLogger(&providerTencentCloudCLB.TencentCloudCLBDeployerConfig{ + deployer, err := pTencentCloudCLB.NewWithLogger(&pTencentCloudCLB.TencentCloudCLBDeployerConfig{ SecretId: access.SecretId, SecretKey: access.SecretKey, Region: maps.GetValueAsString(options.ProviderDeployConfig, "region"), - ResourceType: providerTencentCloudCLB.DeployResourceType(maps.GetValueAsString(options.ProviderDeployConfig, "resourceType")), + ResourceType: pTencentCloudCLB.DeployResourceType(maps.GetValueAsString(options.ProviderDeployConfig, "resourceType")), LoadbalancerId: maps.GetValueAsString(options.ProviderDeployConfig, "loadbalancerId"), ListenerId: maps.GetValueAsString(options.ProviderDeployConfig, "listenerId"), Domain: maps.GetValueAsString(options.ProviderDeployConfig, "domain"), @@ -434,7 +449,7 @@ func createDeployer(options *deployerOptions) (deployer.Deployer, logger.Logger, return deployer, logger, err case domain.DeployProviderTypeTencentCloudCOS: - deployer, err := providerTencentCloudCOS.NewWithLogger(&providerTencentCloudCOS.TencentCloudCOSDeployerConfig{ + deployer, err := pTencentCloudCOS.NewWithLogger(&pTencentCloudCOS.TencentCloudCOSDeployerConfig{ SecretId: access.SecretId, SecretKey: access.SecretKey, Region: maps.GetValueAsString(options.ProviderDeployConfig, "region"), @@ -444,7 +459,7 @@ func createDeployer(options *deployerOptions) (deployer.Deployer, logger.Logger, return deployer, logger, err case domain.DeployProviderTypeTencentCloudCSS: - deployer, err := providerTencentCloudCSS.NewWithLogger(&providerTencentCloudCSS.TencentCloudCSSDeployerConfig{ + deployer, err := pTencentCloudCSS.NewWithLogger(&pTencentCloudCSS.TencentCloudCSSDeployerConfig{ SecretId: access.SecretId, SecretKey: access.SecretKey, Domain: maps.GetValueAsString(options.ProviderDeployConfig, "domain"), @@ -452,7 +467,7 @@ func createDeployer(options *deployerOptions) (deployer.Deployer, logger.Logger, return deployer, logger, err case domain.DeployProviderTypeTencentCloudECDN: - deployer, err := providerTencentCloudECDN.NewWithLogger(&providerTencentCloudECDN.TencentCloudECDNDeployerConfig{ + deployer, err := pTencentCloudECDN.NewWithLogger(&pTencentCloudECDN.TencentCloudECDNDeployerConfig{ SecretId: access.SecretId, SecretKey: access.SecretKey, Domain: maps.GetValueAsString(options.ProviderDeployConfig, "domain"), @@ -460,7 +475,7 @@ func createDeployer(options *deployerOptions) (deployer.Deployer, logger.Logger, return deployer, logger, err case domain.DeployProviderTypeTencentCloudEO: - deployer, err := providerTencentCloudEO.NewWithLogger(&providerTencentCloudEO.TencentCloudEODeployerConfig{ + deployer, err := pTencentCloudEO.NewWithLogger(&pTencentCloudEO.TencentCloudEODeployerConfig{ SecretId: access.SecretId, SecretKey: access.SecretKey, ZoneId: maps.GetValueAsString(options.ProviderDeployConfig, "zoneId"), @@ -469,7 +484,7 @@ func createDeployer(options *deployerOptions) (deployer.Deployer, logger.Logger, return deployer, logger, err case domain.DeployProviderTypeTencentCloudSSLDeploy: - deployer, err := providerTencentCloudSSLDeploy.NewWithLogger(&providerTencentCloudSSLDeploy.TencentCloudSSLDeployDeployerConfig{ + deployer, err := pTencentCloudSSLDeploy.NewWithLogger(&pTencentCloudSSLDeploy.TencentCloudSSLDeployDeployerConfig{ SecretId: access.SecretId, SecretKey: access.SecretKey, Region: maps.GetValueAsString(options.ProviderDeployConfig, "region"), @@ -492,7 +507,7 @@ func createDeployer(options *deployerOptions) (deployer.Deployer, logger.Logger, switch options.Provider { case domain.DeployProviderTypeUCloudUCDN: - deployer, err := providerUCloudUCDN.NewWithLogger(&providerUCloudUCDN.UCloudUCDNDeployerConfig{ + deployer, err := pUCloudUCDN.NewWithLogger(&pUCloudUCDN.UCloudUCDNDeployerConfig{ PrivateKey: access.PrivateKey, PublicKey: access.PublicKey, ProjectId: access.ProjectId, @@ -501,7 +516,7 @@ func createDeployer(options *deployerOptions) (deployer.Deployer, logger.Logger, return deployer, logger, err case domain.DeployProviderTypeUCloudUS3: - deployer, err := providerUCloudUS3.NewWithLogger(&providerUCloudUS3.UCloudUS3DeployerConfig{ + deployer, err := pUCloudUS3.NewWithLogger(&pUCloudUS3.UCloudUS3DeployerConfig{ PrivateKey: access.PrivateKey, PublicKey: access.PublicKey, ProjectId: access.ProjectId, @@ -525,7 +540,7 @@ func createDeployer(options *deployerOptions) (deployer.Deployer, logger.Logger, switch options.Provider { case domain.DeployProviderTypeVolcEngineCDN: - deployer, err := providerVolcEngineCDN.NewWithLogger(&providerVolcEngineCDN.VolcEngineCDNDeployerConfig{ + deployer, err := pVolcEngineCDN.NewWithLogger(&pVolcEngineCDN.VolcEngineCDNDeployerConfig{ AccessKeyId: access.AccessKeyId, AccessKeySecret: access.SecretAccessKey, Domain: maps.GetValueAsString(options.ProviderDeployConfig, "domain"), @@ -533,17 +548,17 @@ func createDeployer(options *deployerOptions) (deployer.Deployer, logger.Logger, return deployer, logger, err case domain.DeployProviderTypeVolcEngineCLB: - deployer, err := providerVolcEngineCLB.NewWithLogger(&providerVolcEngineCLB.VolcEngineCLBDeployerConfig{ + deployer, err := pVolcEngineCLB.NewWithLogger(&pVolcEngineCLB.VolcEngineCLBDeployerConfig{ AccessKeyId: access.AccessKeyId, AccessKeySecret: access.SecretAccessKey, Region: maps.GetValueAsString(options.ProviderDeployConfig, "region"), - ResourceType: providerVolcEngineCLB.DeployResourceType(maps.GetValueAsString(options.ProviderDeployConfig, "resourceType")), + ResourceType: pVolcEngineCLB.DeployResourceType(maps.GetValueAsString(options.ProviderDeployConfig, "resourceType")), ListenerId: maps.GetValueAsString(options.ProviderDeployConfig, "listenerId"), }, logger) return deployer, logger, err case domain.DeployProviderTypeVolcEngineDCDN: - deployer, err := providerVolcEngineDCDN.NewWithLogger(&providerVolcEngineDCDN.VolcEngineDCDNDeployerConfig{ + deployer, err := pVolcEngineDCDN.NewWithLogger(&pVolcEngineDCDN.VolcEngineDCDNDeployerConfig{ AccessKeyId: access.AccessKeyId, AccessKeySecret: access.SecretAccessKey, Domain: maps.GetValueAsString(options.ProviderDeployConfig, "domain"), @@ -551,7 +566,7 @@ func createDeployer(options *deployerOptions) (deployer.Deployer, logger.Logger, return deployer, logger, err case domain.DeployProviderTypeVolcEngineImageX: - deployer, err := providerVolcEngineImageX.NewWithLogger(&providerVolcEngineImageX.VolcEngineImageXDeployerConfig{ + deployer, err := pVolcEngineImageX.NewWithLogger(&pVolcEngineImageX.VolcEngineImageXDeployerConfig{ AccessKeyId: access.AccessKeyId, AccessKeySecret: access.SecretAccessKey, Region: maps.GetValueAsString(options.ProviderDeployConfig, "region"), @@ -561,7 +576,7 @@ func createDeployer(options *deployerOptions) (deployer.Deployer, logger.Logger, return deployer, logger, err case domain.DeployProviderTypeVolcEngineLive: - deployer, err := providerVolcEngineLive.NewWithLogger(&providerVolcEngineLive.VolcEngineLiveDeployerConfig{ + deployer, err := pVolcEngineLive.NewWithLogger(&pVolcEngineLive.VolcEngineLiveDeployerConfig{ AccessKeyId: access.AccessKeyId, AccessKeySecret: access.SecretAccessKey, Domain: maps.GetValueAsString(options.ProviderDeployConfig, "domain"), @@ -569,7 +584,7 @@ func createDeployer(options *deployerOptions) (deployer.Deployer, logger.Logger, return deployer, logger, err case domain.DeployProviderTypeVolcEngineTOS: - deployer, err := providerVolcEngineTOS.NewWithLogger(&providerVolcEngineTOS.VolcEngineTOSDeployerConfig{ + deployer, err := pVolcEngineTOS.NewWithLogger(&pVolcEngineTOS.VolcEngineTOSDeployerConfig{ AccessKeyId: access.AccessKeyId, AccessKeySecret: access.SecretAccessKey, Region: maps.GetValueAsString(options.ProviderDeployConfig, "region"), @@ -590,7 +605,7 @@ func createDeployer(options *deployerOptions) (deployer.Deployer, logger.Logger, return nil, nil, fmt.Errorf("failed to populate provider access config: %w", err) } - deployer, err := providerWebhook.NewWithLogger(&providerWebhook.WebhookDeployerConfig{ + deployer, err := pWebhook.NewWithLogger(&pWebhook.WebhookDeployerConfig{ WebhookUrl: access.Url, WebhookData: maps.GetValueAsString(options.ProviderDeployConfig, "webhookData"), }, logger) diff --git a/internal/domain/provider.go b/internal/domain/provider.go index 30c9dab1..c8425b06 100644 --- a/internal/domain/provider.go +++ b/internal/domain/provider.go @@ -107,6 +107,7 @@ const ( DeployProviderTypeAliyunWAF = DeployProviderType("aliyun-waf") DeployProviderTypeAWSCloudFront = DeployProviderType("aws-cloudfront") DeployProviderTypeBaiduCloudCDN = DeployProviderType("baiducloud-cdn") + DeployProviderTypeBaotaPanelConsole = DeployProviderType("baotapanel-console") DeployProviderTypeBaotaPanelSite = DeployProviderType("baotapanel-site") DeployProviderTypeBytePlusCDN = DeployProviderType("byteplus-cdn") DeployProviderTypeDogeCloudCDN = DeployProviderType("dogecloud-cdn") diff --git a/internal/notify/providers.go b/internal/notify/providers.go index 6483a7a0..57247b26 100644 --- a/internal/notify/providers.go +++ b/internal/notify/providers.go @@ -5,14 +5,14 @@ import ( "github.com/usual2970/certimate/internal/domain" "github.com/usual2970/certimate/internal/pkg/core/notifier" - providerBark "github.com/usual2970/certimate/internal/pkg/core/notifier/providers/bark" - providerDingTalk "github.com/usual2970/certimate/internal/pkg/core/notifier/providers/dingtalk" - providerEmail "github.com/usual2970/certimate/internal/pkg/core/notifier/providers/email" - providerLark "github.com/usual2970/certimate/internal/pkg/core/notifier/providers/lark" - providerServerChan "github.com/usual2970/certimate/internal/pkg/core/notifier/providers/serverchan" - providerTelegram "github.com/usual2970/certimate/internal/pkg/core/notifier/providers/telegram" - providerWebhook "github.com/usual2970/certimate/internal/pkg/core/notifier/providers/webhook" - providerWeCom "github.com/usual2970/certimate/internal/pkg/core/notifier/providers/wecom" + pBark "github.com/usual2970/certimate/internal/pkg/core/notifier/providers/bark" + pDingTalk "github.com/usual2970/certimate/internal/pkg/core/notifier/providers/dingtalk" + pEmail "github.com/usual2970/certimate/internal/pkg/core/notifier/providers/email" + pLark "github.com/usual2970/certimate/internal/pkg/core/notifier/providers/lark" + pServerChan "github.com/usual2970/certimate/internal/pkg/core/notifier/providers/serverchan" + pTelegram "github.com/usual2970/certimate/internal/pkg/core/notifier/providers/telegram" + pWebhook "github.com/usual2970/certimate/internal/pkg/core/notifier/providers/webhook" + pWeCom "github.com/usual2970/certimate/internal/pkg/core/notifier/providers/wecom" "github.com/usual2970/certimate/internal/pkg/utils/maps" ) @@ -23,19 +23,19 @@ func createNotifier(channel domain.NotifyChannelType, channelConfig map[string]a */ switch channel { case domain.NotifyChannelTypeBark: - return providerBark.New(&providerBark.BarkNotifierConfig{ + return pBark.New(&pBark.BarkNotifierConfig{ DeviceKey: maps.GetValueAsString(channelConfig, "deviceKey"), ServerUrl: maps.GetValueAsString(channelConfig, "serverUrl"), }) case domain.NotifyChannelTypeDingTalk: - return providerDingTalk.New(&providerDingTalk.DingTalkNotifierConfig{ + return pDingTalk.New(&pDingTalk.DingTalkNotifierConfig{ AccessToken: maps.GetValueAsString(channelConfig, "accessToken"), Secret: maps.GetValueAsString(channelConfig, "secret"), }) case domain.NotifyChannelTypeEmail: - return providerEmail.New(&providerEmail.EmailNotifierConfig{ + return pEmail.New(&pEmail.EmailNotifierConfig{ SmtpHost: maps.GetValueAsString(channelConfig, "smtpHost"), SmtpPort: maps.GetValueAsInt32(channelConfig, "smtpPort"), SmtpTLS: maps.GetValueOrDefaultAsBool(channelConfig, "smtpTLS", true), @@ -46,28 +46,28 @@ func createNotifier(channel domain.NotifyChannelType, channelConfig map[string]a }) case domain.NotifyChannelTypeLark: - return providerLark.New(&providerLark.LarkNotifierConfig{ + return pLark.New(&pLark.LarkNotifierConfig{ WebhookUrl: maps.GetValueAsString(channelConfig, "webhookUrl"), }) case domain.NotifyChannelTypeServerChan: - return providerServerChan.New(&providerServerChan.ServerChanNotifierConfig{ + return pServerChan.New(&pServerChan.ServerChanNotifierConfig{ Url: maps.GetValueAsString(channelConfig, "url"), }) case domain.NotifyChannelTypeTelegram: - return providerTelegram.New(&providerTelegram.TelegramNotifierConfig{ + return pTelegram.New(&pTelegram.TelegramNotifierConfig{ ApiToken: maps.GetValueAsString(channelConfig, "apiToken"), ChatId: maps.GetValueAsInt64(channelConfig, "chatId"), }) case domain.NotifyChannelTypeWebhook: - return providerWebhook.New(&providerWebhook.WebhookNotifierConfig{ + return pWebhook.New(&pWebhook.WebhookNotifierConfig{ Url: maps.GetValueAsString(channelConfig, "url"), }) case domain.NotifyChannelTypeWeCom: - return providerWeCom.New(&providerWeCom.WeComNotifierConfig{ + return pWeCom.New(&pWeCom.WeComNotifierConfig{ WebhookUrl: maps.GetValueAsString(channelConfig, "webhookUrl"), }) } diff --git a/internal/pkg/core/deployer/providers/baotapanel-console/baotapanel_console.go b/internal/pkg/core/deployer/providers/baotapanel-console/baotapanel_console.go new file mode 100644 index 00000000..28765cff --- /dev/null +++ b/internal/pkg/core/deployer/providers/baotapanel-console/baotapanel_console.go @@ -0,0 +1,87 @@ +package baotapanelconsole + +import ( + "context" + "errors" + + xerrors "github.com/pkg/errors" + + "github.com/usual2970/certimate/internal/pkg/core/deployer" + "github.com/usual2970/certimate/internal/pkg/core/logger" + btsdk "github.com/usual2970/certimate/internal/pkg/vendors/btpanel-sdk" +) + +type BaotaPanelConsoleDeployerConfig struct { + // 宝塔面板地址。 + ApiUrl string `json:"apiUrl"` + // 宝塔面板接口密钥。 + ApiKey string `json:"apiKey"` + // 是否自动重启。 + AutoRestart bool `json:"autoRestart"` +} + +type BaotaPanelConsoleDeployer struct { + config *BaotaPanelConsoleDeployerConfig + logger logger.Logger + sdkClient *btsdk.BaoTaPanelClient +} + +var _ deployer.Deployer = (*BaotaPanelConsoleDeployer)(nil) + +func New(config *BaotaPanelConsoleDeployerConfig) (*BaotaPanelConsoleDeployer, error) { + return NewWithLogger(config, logger.NewNilLogger()) +} + +func NewWithLogger(config *BaotaPanelConsoleDeployerConfig, logger logger.Logger) (*BaotaPanelConsoleDeployer, error) { + if config == nil { + return nil, errors.New("config is nil") + } + + if logger == nil { + return nil, errors.New("logger is nil") + } + + client, err := createSdkClient(config.ApiUrl, config.ApiKey) + if err != nil { + return nil, xerrors.Wrap(err, "failed to create sdk client") + } + + return &BaotaPanelConsoleDeployer{ + logger: logger, + config: config, + sdkClient: client, + }, nil +} + +func (d *BaotaPanelConsoleDeployer) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { + // 设置面板 SSL 证书 + configSavePanelSSLReq := &btsdk.ConfigSavePanelSSLRequest{ + PrivateKey: privkeyPem, + Certificate: certPem, + } + configSavePanelSSLResp, err := d.sdkClient.ConfigSavePanelSSL(configSavePanelSSLReq) + if err != nil { + return nil, xerrors.Wrap(err, "failed to execute sdk request 'bt.ConfigSavePanelSSL'") + } else { + d.logger.Logt("已设置面板 SSL 证书", configSavePanelSSLResp) + } + + if d.config.AutoRestart { + // 重启面板 + systemServiceAdminReq := &btsdk.SystemServiceAdminRequest{ + Name: "nginx", + Type: "restart", + } + _, err := d.sdkClient.SystemServiceAdmin(systemServiceAdminReq) + if err != nil { + return nil, xerrors.Wrap(err, "failed to execute sdk request 'bt.SystemServiceAdmin'") + } + } + + return &deployer.DeployResult{}, nil +} + +func createSdkClient(apiUrl, apiKey string) (*btsdk.BaoTaPanelClient, error) { + client := btsdk.NewBaoTaPanelClient(apiUrl, apiKey) + return client, nil +} diff --git a/internal/pkg/core/deployer/providers/baotapanel-console/baotapanel_console_test.go b/internal/pkg/core/deployer/providers/baotapanel-console/baotapanel_console_test.go new file mode 100644 index 00000000..ff388440 --- /dev/null +++ b/internal/pkg/core/deployer/providers/baotapanel-console/baotapanel_console_test.go @@ -0,0 +1,70 @@ +package baotapanelconsole_test + +import ( + "context" + "flag" + "fmt" + "os" + "strings" + "testing" + + provider "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/baotapanel-console" +) + +var ( + fInputCertPath string + fInputKeyPath string + fApiUrl string + fApiKey string +) + +func init() { + argsPrefix := "CERTIMATE_DEPLOYER_BAOTAPANELCONSOLE_" + + flag.StringVar(&fInputCertPath, argsPrefix+"INPUTCERTPATH", "", "") + flag.StringVar(&fInputKeyPath, argsPrefix+"INPUTKEYPATH", "", "") + flag.StringVar(&fApiUrl, argsPrefix+"APIURL", "", "") + flag.StringVar(&fApiKey, argsPrefix+"APIKEY", "", "") +} + +/* +Shell command to run this test: + + go test -v ./baotapanel_console_test.go -args \ + --CERTIMATE_DEPLOYER_BAOTAPANELCONSOLE_INPUTCERTPATH="/path/to/your-input-cert.pem" \ + --CERTIMATE_DEPLOYER_BAOTAPANELCONSOLE_INPUTKEYPATH="/path/to/your-input-key.pem" \ + --CERTIMATE_DEPLOYER_BAOTAPANELCONSOLE_APIURL="your-baota-panel-url" \ + --CERTIMATE_DEPLOYER_BAOTAPANELCONSOLE_APIKEY="your-baota-panel-key" +*/ +func TestDeploy(t *testing.T) { + flag.Parse() + + t.Run("Deploy", func(t *testing.T) { + t.Log(strings.Join([]string{ + "args:", + fmt.Sprintf("INPUTCERTPATH: %v", fInputCertPath), + fmt.Sprintf("INPUTKEYPATH: %v", fInputKeyPath), + fmt.Sprintf("APIURL: %v", fApiUrl), + fmt.Sprintf("APIKEY: %v", fApiKey), + }, "\n")) + + deployer, err := provider.New(&provider.BaotaPanelConsoleDeployerConfig{ + ApiUrl: fApiUrl, + ApiKey: fApiKey, + }) + if err != nil { + t.Errorf("err: %+v", err) + return + } + + fInputCertData, _ := os.ReadFile(fInputCertPath) + fInputKeyData, _ := os.ReadFile(fInputKeyPath) + res, err := deployer.Deploy(context.Background(), string(fInputCertData), string(fInputKeyData)) + if err != nil { + t.Errorf("err: %+v", err) + return + } + + t.Logf("ok: %v", res) + }) +} diff --git a/internal/pkg/core/deployer/providers/baotapanel-site/baotapanel_site.go b/internal/pkg/core/deployer/providers/baotapanel-site/baotapanel_site.go index 336e2a5d..6422a2cb 100644 --- a/internal/pkg/core/deployer/providers/baotapanel-site/baotapanel_site.go +++ b/internal/pkg/core/deployer/providers/baotapanel-site/baotapanel_site.go @@ -59,19 +59,19 @@ func (d *BaotaPanelSiteDeployer) Deploy(ctx context.Context, certPem string, pri } // 设置站点 SSL 证书 - setSiteSSLReq := &btsdk.SetSiteSSLRequest{ - SiteName: d.config.SiteName, - Type: "1", - Key: privkeyPem, - Csr: certPem, + siteSetSSLReq := &btsdk.SiteSetSSLRequest{ + SiteName: d.config.SiteName, + Type: "1", + PrivateKey: privkeyPem, + Certificate: certPem, } - setSiteSSLResp, err := d.sdkClient.SetSiteSSL(setSiteSSLReq) + siteSetSSLResp, err := d.sdkClient.SiteSetSSL(siteSetSSLReq) if err != nil { - return nil, xerrors.Wrap(err, "failed to execute sdk request 'bt.SetSiteSSL'") + return nil, xerrors.Wrap(err, "failed to execute sdk request 'bt.SiteSetSSL'") + } else { + d.logger.Logt("已设置站点 SSL 证书", siteSetSSLResp) } - d.logger.Logt("已设置站点 SSL 证书", setSiteSSLResp) - return &deployer.DeployResult{}, nil } diff --git a/internal/pkg/vendors/btpanel-sdk/api.go b/internal/pkg/vendors/btpanel-sdk/api.go index 5c58e3df..f733d67a 100644 --- a/internal/pkg/vendors/btpanel-sdk/api.go +++ b/internal/pkg/vendors/btpanel-sdk/api.go @@ -5,22 +5,44 @@ type BaseResponse interface { GetMsg() *string } -type SetSiteSSLRequest struct { - Type string `json:"type"` - SiteName string `json:"siteName"` - Key string `json:"key"` - Csr string `json:"csr"` -} - -type SetSiteSSLResponse struct { +type baseResponse struct { Status *bool `json:"status,omitempty"` Msg *string `json:"msg,omitempty"` } -func (r *SetSiteSSLResponse) GetStatus() *bool { +func (r *baseResponse) GetStatus() *bool { return r.Status } -func (r *SetSiteSSLResponse) GetMsg() *string { +func (r *baseResponse) GetMsg() *string { return r.Msg } + +type ConfigSavePanelSSLRequest struct { + PrivateKey string `json:"privateKey"` + Certificate string `json:"certPem"` +} + +type ConfigSavePanelSSLResponse struct { + baseResponse +} + +type SiteSetSSLRequest struct { + Type string `json:"type"` + SiteName string `json:"siteName"` + PrivateKey string `json:"key"` + Certificate string `json:"csr"` +} + +type SiteSetSSLResponse struct { + baseResponse +} + +type SystemServiceAdminRequest struct { + Name string `json:"name"` + Type string `json:"type"` +} + +type SystemServiceAdminResponse struct { + baseResponse +} diff --git a/internal/pkg/vendors/btpanel-sdk/client.go b/internal/pkg/vendors/btpanel-sdk/client.go index 9557612a..76540ad7 100644 --- a/internal/pkg/vendors/btpanel-sdk/client.go +++ b/internal/pkg/vendors/btpanel-sdk/client.go @@ -34,12 +34,25 @@ func (c *BaoTaPanelClient) WithTimeout(timeout time.Duration) *BaoTaPanelClient return c } -func (c *BaoTaPanelClient) SetSiteSSL(req *SetSiteSSLRequest) (*SetSiteSSLResponse, error) { +func (c *BaoTaPanelClient) ConfigSavePanelSSL(req *ConfigSavePanelSSLRequest) (*ConfigSavePanelSSLResponse, error) { params := make(map[string]any) jsonData, _ := json.Marshal(req) json.Unmarshal(jsonData, ¶ms) - result := SetSiteSSLResponse{} + result := ConfigSavePanelSSLResponse{} + err := c.sendRequestWithResult("/config?action=SavePanelSSL", params, &result) + if err != nil { + return nil, err + } + return &result, nil +} + +func (c *BaoTaPanelClient) SiteSetSSL(req *SiteSetSSLRequest) (*SiteSetSSLResponse, error) { + params := make(map[string]any) + jsonData, _ := json.Marshal(req) + json.Unmarshal(jsonData, ¶ms) + + result := SiteSetSSLResponse{} err := c.sendRequestWithResult("/site?action=SetSSL", params, &result) if err != nil { return nil, err @@ -47,6 +60,19 @@ func (c *BaoTaPanelClient) SetSiteSSL(req *SetSiteSSLRequest) (*SetSiteSSLRespon return &result, nil } +func (c *BaoTaPanelClient) SystemServiceAdmin(req *SystemServiceAdminRequest) (*SystemServiceAdminResponse, error) { + params := make(map[string]any) + jsonData, _ := json.Marshal(req) + json.Unmarshal(jsonData, ¶ms) + + result := SystemServiceAdminResponse{} + err := c.sendRequestWithResult("/system?action=ServiceAdmin", params, &result) + if err != nil { + return nil, err + } + return &result, nil +} + func (c *BaoTaPanelClient) generateSignature(timestamp string) string { keyMd5 := md5.Sum([]byte(c.apiKey)) keyMd5Hex := strings.ToLower(hex.EncodeToString(keyMd5[:])) diff --git a/ui/src/components/workflow/node/DeployNodeConfigForm.tsx b/ui/src/components/workflow/node/DeployNodeConfigForm.tsx index 6f4d1f4a..e7a1f5d9 100644 --- a/ui/src/components/workflow/node/DeployNodeConfigForm.tsx +++ b/ui/src/components/workflow/node/DeployNodeConfigForm.tsx @@ -27,6 +27,7 @@ import DeployNodeConfigFormAliyunOSSConfig from "./DeployNodeConfigFormAliyunOSS import DeployNodeConfigFormAliyunWAFConfig from "./DeployNodeConfigFormAliyunWAFConfig"; import DeployNodeConfigFormAWSCloudFrontConfig from "./DeployNodeConfigFormAWSCloudFrontConfig"; import DeployNodeConfigFormBaiduCloudCDNConfig from "./DeployNodeConfigFormBaiduCloudCDNConfig"; +import DeployNodeConfigFormBaotaPanelConsoleConfig from "./DeployNodeConfigFormBaotaPanelConsoleConfig"; import DeployNodeConfigFormBaotaPanelSiteConfig from "./DeployNodeConfigFormBaotaPanelSiteConfig"; import DeployNodeConfigFormBytePlusCDNConfig from "./DeployNodeConfigFormBytePlusCDNConfig"; import DeployNodeConfigFormDogeCloudCDNConfig from "./DeployNodeConfigFormDogeCloudCDNConfig"; @@ -150,6 +151,8 @@ const DeployNodeConfigForm = forwardRef; case DEPLOY_PROVIDERS.BAIDUCLOUD_CDN: return ; + case DEPLOY_PROVIDERS.BAOTAPANEL_CONSOLE: + return ; case DEPLOY_PROVIDERS.BAOTAPANEL_SITE: return ; case DEPLOY_PROVIDERS.BYTEPLUS_CDN: diff --git a/ui/src/components/workflow/node/DeployNodeConfigFormBaotaPanelConsoleConfig.tsx b/ui/src/components/workflow/node/DeployNodeConfigFormBaotaPanelConsoleConfig.tsx new file mode 100644 index 00000000..40d93b7f --- /dev/null +++ b/ui/src/components/workflow/node/DeployNodeConfigFormBaotaPanelConsoleConfig.tsx @@ -0,0 +1,56 @@ +import { useTranslation } from "react-i18next"; +import { Form, type FormInstance, Switch } from "antd"; +import { createSchemaFieldRule } from "antd-zod"; +import { z } from "zod"; + +type DeployNodeConfigFormBaotaPanelConsoleConfigFieldValues = Nullish<{ + autoRestart?: boolean; +}>; + +export type DeployNodeConfigFormBaotaPanelConsoleConfigProps = { + form: FormInstance; + formName: string; + disabled?: boolean; + initialValues?: DeployNodeConfigFormBaotaPanelConsoleConfigFieldValues; + onValuesChange?: (values: DeployNodeConfigFormBaotaPanelConsoleConfigFieldValues) => void; +}; + +const initFormModel = (): DeployNodeConfigFormBaotaPanelConsoleConfigFieldValues => { + return {}; +}; + +const DeployNodeConfigFormBaotaPanelConsoleConfig = ({ + form: formInst, + formName, + disabled, + initialValues, + onValuesChange, +}: DeployNodeConfigFormBaotaPanelConsoleConfigProps) => { + const { t } = useTranslation(); + + const formSchema = z.object({ + autoRestart: z.boolean().nullish(), + }); + const formRule = createSchemaFieldRule(formSchema); + + const handleFormChange = (_: unknown, values: z.infer) => { + onValuesChange?.(values); + }; + + return ( +
+ + + +
+ ); +}; + +export default DeployNodeConfigFormBaotaPanelConsoleConfig; diff --git a/ui/src/domain/provider.ts b/ui/src/domain/provider.ts index c6e92535..6235e4c2 100644 --- a/ui/src/domain/provider.ts +++ b/ui/src/domain/provider.ts @@ -188,6 +188,7 @@ export const DEPLOY_PROVIDERS = Object.freeze({ ALIYUN_WAF: `${ACCESS_PROVIDERS.ALIYUN}-waf`, AWS_CLOUDFRONT: `${ACCESS_PROVIDERS.AWS}-cloudfront`, BAIDUCLOUD_CDN: `${ACCESS_PROVIDERS.BAIDUCLOUD}-cdn`, + BAOTAPANEL_CONSOLE: `${ACCESS_PROVIDERS.BAOTAPANEL}-console`, BAOTAPANEL_SITE: `${ACCESS_PROVIDERS.BAOTAPANEL}-site`, BYTEPLUS_CDN: `${ACCESS_PROVIDERS.BYTEPLUS}-cdn`, DOGECLOUD_CDN: `${ACCESS_PROVIDERS.DOGECLOUD}-cdn`, @@ -283,6 +284,7 @@ export const deployProvidersMap: Map [ diff --git a/ui/src/i18n/locales/en/nls.provider.json b/ui/src/i18n/locales/en/nls.provider.json index 326b9478..9b7e924b 100644 --- a/ui/src/i18n/locales/en/nls.provider.json +++ b/ui/src/i18n/locales/en/nls.provider.json @@ -25,6 +25,7 @@ "provider.baishan": "Baishan", "provider.baishan.cdn": "Baishan - CDN (Content Delivery Network)", "provider.baotapanel": "BaoTa Panel", + "provider.baotapanel.console": "BaoTa Panel - Console", "provider.baotapanel.site": "BaoTa Panel - Site", "provider.byteplus": "BytePlus", "provider.byteplus.cdn": "BytePlus - CDN (Content Delivery Network)", diff --git a/ui/src/i18n/locales/en/nls.workflow.nodes.json b/ui/src/i18n/locales/en/nls.workflow.nodes.json index dc56cdb4..9f5a8ecb 100644 --- a/ui/src/i18n/locales/en/nls.workflow.nodes.json +++ b/ui/src/i18n/locales/en/nls.workflow.nodes.json @@ -190,6 +190,7 @@ "workflow_node.deploy.form.baiducloud_cdn_domain.label": "Baidu Cloud CDN domain", "workflow_node.deploy.form.baiducloud_cdn_domain.placeholder": "Please enter Baidu Cloud CDN domain name", "workflow_node.deploy.form.baiducloud_cdn_domain.tooltip": "For more information, see https://console.bce.baidu.com/cdn", + "workflow_node.deploy.form.baotapanel_console_auto_restart.label": "Auto restart after deployment", "workflow_node.deploy.form.baotapanel_site_name.label": "BaoTa Panel site name", "workflow_node.deploy.form.baotapanel_site_name.placeholder": "Please enter BaoTa Panel site name", "workflow_node.deploy.form.baotapanel_site_name.tooltip": "Usually equal to the website domain name.", diff --git a/ui/src/i18n/locales/zh/nls.provider.json b/ui/src/i18n/locales/zh/nls.provider.json index 42453b04..2cbc066f 100644 --- a/ui/src/i18n/locales/zh/nls.provider.json +++ b/ui/src/i18n/locales/zh/nls.provider.json @@ -25,6 +25,7 @@ "provider.baishan": "白山云", "provider.baishan.cdn": "白山云 - 内容分发网络 CDN", "provider.baotapanel": "宝塔面板", + "provider.baotapanel.console": "宝塔面板 - 面板", "provider.baotapanel.site": "宝塔面板 - 网站", "provider.byteplus": "BytePlus", "provider.byteplus.cdn": "BytePlus - 内容分发网络 CDN", diff --git a/ui/src/i18n/locales/zh/nls.workflow.nodes.json b/ui/src/i18n/locales/zh/nls.workflow.nodes.json index a4062398..dd33be3b 100644 --- a/ui/src/i18n/locales/zh/nls.workflow.nodes.json +++ b/ui/src/i18n/locales/zh/nls.workflow.nodes.json @@ -190,6 +190,7 @@ "workflow_node.deploy.form.baiducloud_cdn_domain.label": "百度智能云 CDN 加速域名(支持泛域名)", "workflow_node.deploy.form.baiducloud_cdn_domain.placeholder": "请输入百度智能云 CDN 加速域名", "workflow_node.deploy.form.baiducloud_cdn_domain.tooltip": "这是什么?请参阅 https://console.bce.baidu.com/cdn

泛域名表示形式为:*.example.com", + "workflow_node.deploy.form.baotapanel_console_auto_restart.label": "部署后自动重启面板服务", "workflow_node.deploy.form.baotapanel_site_name.label": "宝塔面板网站名称", "workflow_node.deploy.form.baotapanel_site_name.placeholder": "请输入宝塔面板网站名称", "workflow_node.deploy.form.baotapanel_site_name.tooltip": "通常为网站域名。", From a6f1f21c18d1de6ce7cc01b587ebe1418f3914b8 Mon Sep 17 00:00:00 2001 From: Fu Diwei Date: Sun, 16 Feb 2025 20:23:16 +0800 Subject: [PATCH 03/34] feat: add huaweicloud waf uploader --- go.mod | 2 +- go.sum | 2 + .../providers/aliyun-alb/aliyun_alb.go | 12 +- .../providers/aliyun-alb/aliyun_alb_test.go | 4 +- .../deployer/providers/aliyun-alb/consts.go | 10 ++ .../deployer/providers/aliyun-alb/defines.go | 10 -- .../providers/aliyun-clb/aliyun_clb.go | 12 +- .../providers/aliyun-clb/aliyun_clb_test.go | 4 +- .../deployer/providers/aliyun-clb/consts.go | 10 ++ .../deployer/providers/aliyun-clb/defines.go | 10 -- .../providers/aliyun-nlb/aliyun_nlb.go | 10 +- .../providers/aliyun-nlb/aliyun_nlb_test.go | 4 +- .../deployer/providers/aliyun-nlb/consts.go | 10 ++ .../deployer/providers/aliyun-nlb/defines.go | 10 -- .../providers/huaweicloud-elb/consts.go | 12 ++ .../providers/huaweicloud-elb/defines.go | 12 -- .../huaweicloud-elb/huaweicloud_elb.go | 14 +- .../huaweicloud-elb/huaweicloud_elb_test.go | 6 +- .../providers/tencentcloud-clb/consts.go | 14 ++ .../providers/tencentcloud-clb/defines.go | 14 -- .../tencentcloud-clb/tencentcloud_clb.go | 16 +- .../tencentcloud-clb/tencentcloud_clb_test.go | 8 +- .../providers/volcengine-clb/consts.go | 8 + .../providers/volcengine-clb/defines.go | 8 - .../volcengine-clb/volcengine_clb.go | 6 +- .../volcengine-clb/volcengine_clb_test.go | 2 +- .../providers/aliyun-cas/aliyun_cas.go | 2 +- .../huaweicloud-waf/huaweicloud_waf.go | 167 ++++++++++++++++++ 28 files changed, 284 insertions(+), 115 deletions(-) create mode 100644 internal/pkg/core/deployer/providers/aliyun-alb/consts.go delete mode 100644 internal/pkg/core/deployer/providers/aliyun-alb/defines.go create mode 100644 internal/pkg/core/deployer/providers/aliyun-clb/consts.go delete mode 100644 internal/pkg/core/deployer/providers/aliyun-clb/defines.go create mode 100644 internal/pkg/core/deployer/providers/aliyun-nlb/consts.go delete mode 100644 internal/pkg/core/deployer/providers/aliyun-nlb/defines.go create mode 100644 internal/pkg/core/deployer/providers/huaweicloud-elb/consts.go delete mode 100644 internal/pkg/core/deployer/providers/huaweicloud-elb/defines.go create mode 100644 internal/pkg/core/deployer/providers/tencentcloud-clb/consts.go delete mode 100644 internal/pkg/core/deployer/providers/tencentcloud-clb/defines.go create mode 100644 internal/pkg/core/deployer/providers/volcengine-clb/consts.go delete mode 100644 internal/pkg/core/deployer/providers/volcengine-clb/defines.go create mode 100644 internal/pkg/core/uploader/providers/huaweicloud-waf/huaweicloud_waf.go diff --git a/go.mod b/go.mod index 18045029..47cb6e33 100644 --- a/go.mod +++ b/go.mod @@ -24,7 +24,7 @@ require ( github.com/go-acme/lego/v4 v4.21.0 github.com/go-resty/resty/v2 v2.16.5 github.com/go-viper/mapstructure/v2 v2.2.1 - github.com/huaweicloud/huaweicloud-sdk-go-v3 v0.1.135 + github.com/huaweicloud/huaweicloud-sdk-go-v3 v0.1.136 github.com/nikoksr/notify v1.3.0 github.com/pavlo-v-chernykh/keystore-go/v4 v4.5.0 github.com/pkg/sftp v1.13.7 diff --git a/go.sum b/go.sum index a9edfa88..7f36a13b 100644 --- a/go.sum +++ b/go.sum @@ -558,6 +558,8 @@ github.com/hashicorp/serf v0.9.5/go.mod h1:UWDWwZeL5cuWDJdl0C6wrvrUwEqtQ4ZKBKKEN github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/huaweicloud/huaweicloud-sdk-go-v3 v0.1.135 h1:UbNMlPfh0GhRY3iVkvv4fXFJ+bLqXoVCwjqe6geFdPs= github.com/huaweicloud/huaweicloud-sdk-go-v3 v0.1.135/go.mod h1:Y/+YLCFCJtS29i2MbYPTUlNNfwXvkzEsZKR0imY/2aY= +github.com/huaweicloud/huaweicloud-sdk-go-v3 v0.1.136 h1:T785NUg5245nWpPVHLVR8lBd+zGQYR14Vi/TCX1iu3A= +github.com/huaweicloud/huaweicloud-sdk-go-v3 v0.1.136/go.mod h1:Y/+YLCFCJtS29i2MbYPTUlNNfwXvkzEsZKR0imY/2aY= github.com/hudl/fargo v1.4.0/go.mod h1:9Ai6uvFy5fQNq6VPKtg+Ceq1+eTY4nKUlR2JElEOcDo= github.com/iancoleman/strcase v0.3.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= diff --git a/internal/pkg/core/deployer/providers/aliyun-alb/aliyun_alb.go b/internal/pkg/core/deployer/providers/aliyun-alb/aliyun_alb.go index 9878b6f4..c5b1ae35 100644 --- a/internal/pkg/core/deployer/providers/aliyun-alb/aliyun_alb.go +++ b/internal/pkg/core/deployer/providers/aliyun-alb/aliyun_alb.go @@ -29,15 +29,15 @@ type AliyunALBDeployerConfig struct { // 阿里云地域。 Region string `json:"region"` // 部署资源类型。 - ResourceType DeployResourceType `json:"resourceType"` + ResourceType ResourceType `json:"resourceType"` // 负载均衡实例 ID。 - // 部署资源类型为 [DEPLOY_RESOURCE_LOADBALANCER] 时必填。 + // 部署资源类型为 [RESOURCE_TYPE_LOADBALANCER] 时必填。 LoadbalancerId string `json:"loadbalancerId,omitempty"` // 负载均衡监听 ID。 - // 部署资源类型为 [DEPLOY_RESOURCE_LISTENER] 时必填。 + // 部署资源类型为 [RESOURCE_TYPE_LISTENER] 时必填。 ListenerId string `json:"listenerId,omitempty"` // SNI 域名(支持泛域名)。 - // 部署资源类型为 [DEPLOY_RESOURCE_LOADBALANCER]、[DEPLOY_RESOURCE_LISTENER] 时选填。 + // 部署资源类型为 [RESOURCE_TYPE_LOADBALANCER]、[RESOURCE_TYPE_LISTENER] 时选填。 Domain string `json:"domain,omitempty"` } @@ -97,12 +97,12 @@ func (d *AliyunALBDeployer) Deploy(ctx context.Context, certPem string, privkeyP // 根据部署资源类型决定部署方式 switch d.config.ResourceType { - case DEPLOY_RESOURCE_LOADBALANCER: + case RESOURCE_TYPE_LOADBALANCER: if err := d.deployToLoadbalancer(ctx, upres.CertId); err != nil { return nil, err } - case DEPLOY_RESOURCE_LISTENER: + case RESOURCE_TYPE_LISTENER: if err := d.deployToListener(ctx, upres.CertId); err != nil { return nil, err } diff --git a/internal/pkg/core/deployer/providers/aliyun-alb/aliyun_alb_test.go b/internal/pkg/core/deployer/providers/aliyun-alb/aliyun_alb_test.go index 15e6aff2..ceeea881 100644 --- a/internal/pkg/core/deployer/providers/aliyun-alb/aliyun_alb_test.go +++ b/internal/pkg/core/deployer/providers/aliyun-alb/aliyun_alb_test.go @@ -67,7 +67,7 @@ func TestDeploy(t *testing.T) { AccessKeyId: fAccessKeyId, AccessKeySecret: fAccessKeySecret, Region: fRegion, - ResourceType: provider.DEPLOY_RESOURCE_LOADBALANCER, + ResourceType: provider.RESOURCE_TYPE_LOADBALANCER, LoadbalancerId: fLoadbalancerId, Domain: fDomain, }) @@ -102,7 +102,7 @@ func TestDeploy(t *testing.T) { AccessKeyId: fAccessKeyId, AccessKeySecret: fAccessKeySecret, Region: fRegion, - ResourceType: provider.DEPLOY_RESOURCE_LISTENER, + ResourceType: provider.RESOURCE_TYPE_LISTENER, ListenerId: fListenerId, Domain: fDomain, }) diff --git a/internal/pkg/core/deployer/providers/aliyun-alb/consts.go b/internal/pkg/core/deployer/providers/aliyun-alb/consts.go new file mode 100644 index 00000000..a2d1aacc --- /dev/null +++ b/internal/pkg/core/deployer/providers/aliyun-alb/consts.go @@ -0,0 +1,10 @@ +package aliyunalb + +type ResourceType string + +const ( + // 资源类型:部署到指定负载均衡器。 + RESOURCE_TYPE_LOADBALANCER = ResourceType("loadbalancer") + // 资源类型:部署到指定监听器。 + RESOURCE_TYPE_LISTENER = ResourceType("listener") +) diff --git a/internal/pkg/core/deployer/providers/aliyun-alb/defines.go b/internal/pkg/core/deployer/providers/aliyun-alb/defines.go deleted file mode 100644 index 927e990a..00000000 --- a/internal/pkg/core/deployer/providers/aliyun-alb/defines.go +++ /dev/null @@ -1,10 +0,0 @@ -package aliyunalb - -type DeployResourceType string - -const ( - // 资源类型:部署到指定负载均衡器。 - DEPLOY_RESOURCE_LOADBALANCER = DeployResourceType("loadbalancer") - // 资源类型:部署到指定监听器。 - DEPLOY_RESOURCE_LISTENER = DeployResourceType("listener") -) diff --git a/internal/pkg/core/deployer/providers/aliyun-clb/aliyun_clb.go b/internal/pkg/core/deployer/providers/aliyun-clb/aliyun_clb.go index 4bd91611..1fd5532e 100644 --- a/internal/pkg/core/deployer/providers/aliyun-clb/aliyun_clb.go +++ b/internal/pkg/core/deployer/providers/aliyun-clb/aliyun_clb.go @@ -24,15 +24,15 @@ type AliyunCLBDeployerConfig struct { // 阿里云地域。 Region string `json:"region"` // 部署资源类型。 - ResourceType DeployResourceType `json:"resourceType"` + ResourceType ResourceType `json:"resourceType"` // 负载均衡实例 ID。 - // 部署资源类型为 [DEPLOY_RESOURCE_LOADBALANCER]、[DEPLOY_RESOURCE_LISTENER] 时必填。 + // 部署资源类型为 [RESOURCE_TYPE_LOADBALANCER]、[RESOURCE_TYPE_LISTENER] 时必填。 LoadbalancerId string `json:"loadbalancerId,omitempty"` // 负载均衡监听端口。 - // 部署资源类型为 [DEPLOY_RESOURCE_LISTENER] 时必填。 + // 部署资源类型为 [RESOURCE_TYPE_LISTENER] 时必填。 ListenerPort int32 `json:"listenerPort,omitempty"` // SNI 域名(支持泛域名)。 - // 部署资源类型为 [DEPLOY_RESOURCE_LOADBALANCER]、[DEPLOY_RESOURCE_LISTENER] 时选填。 + // 部署资源类型为 [RESOURCE_TYPE_LOADBALANCER]、[RESOURCE_TYPE_LISTENER] 时选填。 Domain string `json:"domain,omitempty"` } @@ -91,12 +91,12 @@ func (d *AliyunCLBDeployer) Deploy(ctx context.Context, certPem string, privkeyP // 根据部署资源类型决定部署方式 switch d.config.ResourceType { - case DEPLOY_RESOURCE_LOADBALANCER: + case RESOURCE_TYPE_LOADBALANCER: if err := d.deployToLoadbalancer(ctx, upres.CertId); err != nil { return nil, err } - case DEPLOY_RESOURCE_LISTENER: + case RESOURCE_TYPE_LISTENER: if err := d.deployToListener(ctx, upres.CertId); err != nil { return nil, err } diff --git a/internal/pkg/core/deployer/providers/aliyun-clb/aliyun_clb_test.go b/internal/pkg/core/deployer/providers/aliyun-clb/aliyun_clb_test.go index 0b27c5f8..79b16618 100644 --- a/internal/pkg/core/deployer/providers/aliyun-clb/aliyun_clb_test.go +++ b/internal/pkg/core/deployer/providers/aliyun-clb/aliyun_clb_test.go @@ -67,7 +67,7 @@ func TestDeploy(t *testing.T) { AccessKeyId: fAccessKeyId, AccessKeySecret: fAccessKeySecret, Region: fRegion, - ResourceType: provider.DEPLOY_RESOURCE_LOADBALANCER, + ResourceType: provider.RESOURCE_TYPE_LOADBALANCER, LoadbalancerId: fLoadbalancerId, Domain: fDomain, }) @@ -103,7 +103,7 @@ func TestDeploy(t *testing.T) { AccessKeyId: fAccessKeyId, AccessKeySecret: fAccessKeySecret, Region: fRegion, - ResourceType: provider.DEPLOY_RESOURCE_LISTENER, + ResourceType: provider.RESOURCE_TYPE_LISTENER, LoadbalancerId: fLoadbalancerId, ListenerPort: int32(fListenerPort), Domain: fDomain, diff --git a/internal/pkg/core/deployer/providers/aliyun-clb/consts.go b/internal/pkg/core/deployer/providers/aliyun-clb/consts.go new file mode 100644 index 00000000..ad4fb070 --- /dev/null +++ b/internal/pkg/core/deployer/providers/aliyun-clb/consts.go @@ -0,0 +1,10 @@ +package aliyunclb + +type ResourceType string + +const ( + // 资源类型:部署到指定负载均衡器。 + RESOURCE_TYPE_LOADBALANCER = ResourceType("loadbalancer") + // 资源类型:部署到指定监听器。 + RESOURCE_TYPE_LISTENER = ResourceType("listener") +) diff --git a/internal/pkg/core/deployer/providers/aliyun-clb/defines.go b/internal/pkg/core/deployer/providers/aliyun-clb/defines.go deleted file mode 100644 index 4a02ab20..00000000 --- a/internal/pkg/core/deployer/providers/aliyun-clb/defines.go +++ /dev/null @@ -1,10 +0,0 @@ -package aliyunclb - -type DeployResourceType string - -const ( - // 资源类型:部署到指定负载均衡器。 - DEPLOY_RESOURCE_LOADBALANCER = DeployResourceType("loadbalancer") - // 资源类型:部署到指定监听器。 - DEPLOY_RESOURCE_LISTENER = DeployResourceType("listener") -) diff --git a/internal/pkg/core/deployer/providers/aliyun-nlb/aliyun_nlb.go b/internal/pkg/core/deployer/providers/aliyun-nlb/aliyun_nlb.go index 6deee907..e18b13a3 100644 --- a/internal/pkg/core/deployer/providers/aliyun-nlb/aliyun_nlb.go +++ b/internal/pkg/core/deployer/providers/aliyun-nlb/aliyun_nlb.go @@ -25,12 +25,12 @@ type AliyunNLBDeployerConfig struct { // 阿里云地域。 Region string `json:"region"` // 部署资源类型。 - ResourceType DeployResourceType `json:"resourceType"` + ResourceType ResourceType `json:"resourceType"` // 负载均衡实例 ID。 - // 部署资源类型为 [DEPLOY_RESOURCE_LOADBALANCER] 时必填。 + // 部署资源类型为 [RESOURCE_TYPE_LOADBALANCER] 时必填。 LoadbalancerId string `json:"loadbalancerId,omitempty"` // 负载均衡监听 ID。 - // 部署资源类型为 [DEPLOY_RESOURCE_LISTENER] 时必填。 + // 部署资源类型为 [RESOURCE_TYPE_LISTENER] 时必填。 ListenerId string `json:"listenerId,omitempty"` } @@ -85,12 +85,12 @@ func (d *AliyunNLBDeployer) Deploy(ctx context.Context, certPem string, privkeyP // 根据部署资源类型决定部署方式 switch d.config.ResourceType { - case DEPLOY_RESOURCE_LOADBALANCER: + case RESOURCE_TYPE_LOADBALANCER: if err := d.deployToLoadbalancer(ctx, upres.CertId); err != nil { return nil, err } - case DEPLOY_RESOURCE_LISTENER: + case RESOURCE_TYPE_LISTENER: if err := d.deployToListener(ctx, upres.CertId); err != nil { return nil, err } diff --git a/internal/pkg/core/deployer/providers/aliyun-nlb/aliyun_nlb_test.go b/internal/pkg/core/deployer/providers/aliyun-nlb/aliyun_nlb_test.go index 45abd932..7c7c08e6 100644 --- a/internal/pkg/core/deployer/providers/aliyun-nlb/aliyun_nlb_test.go +++ b/internal/pkg/core/deployer/providers/aliyun-nlb/aliyun_nlb_test.go @@ -63,7 +63,7 @@ func TestDeploy(t *testing.T) { AccessKeyId: fAccessKeyId, AccessKeySecret: fAccessKeySecret, Region: fRegion, - ResourceType: provider.DEPLOY_RESOURCE_LOADBALANCER, + ResourceType: provider.RESOURCE_TYPE_LOADBALANCER, LoadbalancerId: fLoadbalancerId, }) if err != nil { @@ -98,7 +98,7 @@ func TestDeploy(t *testing.T) { AccessKeyId: fAccessKeyId, AccessKeySecret: fAccessKeySecret, Region: fRegion, - ResourceType: provider.DEPLOY_RESOURCE_LISTENER, + ResourceType: provider.RESOURCE_TYPE_LISTENER, ListenerId: fListenerId, }) if err != nil { diff --git a/internal/pkg/core/deployer/providers/aliyun-nlb/consts.go b/internal/pkg/core/deployer/providers/aliyun-nlb/consts.go new file mode 100644 index 00000000..1fa071df --- /dev/null +++ b/internal/pkg/core/deployer/providers/aliyun-nlb/consts.go @@ -0,0 +1,10 @@ +package aliyunnlb + +type ResourceType string + +const ( + // 资源类型:部署到指定负载均衡器。 + RESOURCE_TYPE_LOADBALANCER = ResourceType("loadbalancer") + // 资源类型:部署到指定监听器。 + RESOURCE_TYPE_LISTENER = ResourceType("listener") +) diff --git a/internal/pkg/core/deployer/providers/aliyun-nlb/defines.go b/internal/pkg/core/deployer/providers/aliyun-nlb/defines.go deleted file mode 100644 index 14e3c2b2..00000000 --- a/internal/pkg/core/deployer/providers/aliyun-nlb/defines.go +++ /dev/null @@ -1,10 +0,0 @@ -package aliyunnlb - -type DeployResourceType string - -const ( - // 资源类型:部署到指定负载均衡器。 - DEPLOY_RESOURCE_LOADBALANCER = DeployResourceType("loadbalancer") - // 资源类型:部署到指定监听器。 - DEPLOY_RESOURCE_LISTENER = DeployResourceType("listener") -) diff --git a/internal/pkg/core/deployer/providers/huaweicloud-elb/consts.go b/internal/pkg/core/deployer/providers/huaweicloud-elb/consts.go new file mode 100644 index 00000000..b097a958 --- /dev/null +++ b/internal/pkg/core/deployer/providers/huaweicloud-elb/consts.go @@ -0,0 +1,12 @@ +package huaweicloudelb + +type ResourceType string + +const ( + // 资源类型:替换指定证书。 + RESOURCE_TYPE_CERTIFICATE = ResourceType("certificate") + // 资源类型:部署到指定负载均衡器。 + RESOURCE_TYPE_LOADBALANCER = ResourceType("loadbalancer") + // 资源类型:部署到指定监听器。 + RESOURCE_TYPE_LISTENER = ResourceType("listener") +) diff --git a/internal/pkg/core/deployer/providers/huaweicloud-elb/defines.go b/internal/pkg/core/deployer/providers/huaweicloud-elb/defines.go deleted file mode 100644 index 093ab829..00000000 --- a/internal/pkg/core/deployer/providers/huaweicloud-elb/defines.go +++ /dev/null @@ -1,12 +0,0 @@ -package huaweicloudelb - -type DeployResourceType string - -const ( - // 资源类型:替换指定证书。 - DEPLOY_RESOURCE_CERTIFICATE = DeployResourceType("certificate") - // 资源类型:部署到指定负载均衡器。 - DEPLOY_RESOURCE_LOADBALANCER = DeployResourceType("loadbalancer") - // 资源类型:部署到指定监听器。 - DEPLOY_RESOURCE_LISTENER = DeployResourceType("listener") -) diff --git a/internal/pkg/core/deployer/providers/huaweicloud-elb/huaweicloud_elb.go b/internal/pkg/core/deployer/providers/huaweicloud-elb/huaweicloud_elb.go index 3fa17a70..2748913e 100644 --- a/internal/pkg/core/deployer/providers/huaweicloud-elb/huaweicloud_elb.go +++ b/internal/pkg/core/deployer/providers/huaweicloud-elb/huaweicloud_elb.go @@ -31,15 +31,15 @@ type HuaweiCloudELBDeployerConfig struct { // 华为云区域。 Region string `json:"region"` // 部署资源类型。 - ResourceType DeployResourceType `json:"resourceType"` + ResourceType ResourceType `json:"resourceType"` // 证书 ID。 - // 部署资源类型为 [DEPLOY_RESOURCE_CERTIFICATE] 时必填。 + // 部署资源类型为 [RESOURCE_TYPE_CERTIFICATE] 时必填。 CertificateId string `json:"certificateId,omitempty"` // 负载均衡器 ID。 - // 部署资源类型为 [DEPLOY_RESOURCE_LOADBALANCER] 时必填。 + // 部署资源类型为 [RESOURCE_TYPE_LOADBALANCER] 时必填。 LoadbalancerId string `json:"loadbalancerId,omitempty"` // 负载均衡监听 ID。 - // 部署资源类型为 [DEPLOY_RESOURCE_LISTENER] 时必填。 + // 部署资源类型为 [RESOURCE_TYPE_LISTENER] 时必填。 ListenerId string `json:"listenerId,omitempty"` } @@ -98,17 +98,17 @@ func (d *HuaweiCloudELBDeployer) Deploy(ctx context.Context, certPem string, pri // 根据部署资源类型决定部署方式 switch d.config.ResourceType { - case DEPLOY_RESOURCE_CERTIFICATE: + case RESOURCE_TYPE_CERTIFICATE: if err := d.deployToCertificate(ctx, certPem, privkeyPem); err != nil { return nil, err } - case DEPLOY_RESOURCE_LOADBALANCER: + case RESOURCE_TYPE_LOADBALANCER: if err := d.deployToLoadbalancer(ctx, certPem, privkeyPem); err != nil { return nil, err } - case DEPLOY_RESOURCE_LISTENER: + case RESOURCE_TYPE_LISTENER: if err := d.deployToListener(ctx, certPem, privkeyPem); err != nil { return nil, err } diff --git a/internal/pkg/core/deployer/providers/huaweicloud-elb/huaweicloud_elb_test.go b/internal/pkg/core/deployer/providers/huaweicloud-elb/huaweicloud_elb_test.go index 32582800..017f3b3c 100644 --- a/internal/pkg/core/deployer/providers/huaweicloud-elb/huaweicloud_elb_test.go +++ b/internal/pkg/core/deployer/providers/huaweicloud-elb/huaweicloud_elb_test.go @@ -66,7 +66,7 @@ func TestDeploy(t *testing.T) { AccessKeyId: fAccessKeyId, SecretAccessKey: fSecretAccessKey, Region: fRegion, - ResourceType: provider.DEPLOY_RESOURCE_CERTIFICATE, + ResourceType: provider.RESOURCE_TYPE_CERTIFICATE, CertificateId: fCertificateId, }) if err != nil { @@ -100,7 +100,7 @@ func TestDeploy(t *testing.T) { AccessKeyId: fAccessKeyId, SecretAccessKey: fSecretAccessKey, Region: fRegion, - ResourceType: provider.DEPLOY_RESOURCE_LOADBALANCER, + ResourceType: provider.RESOURCE_TYPE_LOADBALANCER, LoadbalancerId: fLoadbalancerId, }) if err != nil { @@ -134,7 +134,7 @@ func TestDeploy(t *testing.T) { AccessKeyId: fAccessKeyId, SecretAccessKey: fSecretAccessKey, Region: fRegion, - ResourceType: provider.DEPLOY_RESOURCE_LISTENER, + ResourceType: provider.RESOURCE_TYPE_LISTENER, ListenerId: fListenerId, }) if err != nil { diff --git a/internal/pkg/core/deployer/providers/tencentcloud-clb/consts.go b/internal/pkg/core/deployer/providers/tencentcloud-clb/consts.go new file mode 100644 index 00000000..7d72d5d3 --- /dev/null +++ b/internal/pkg/core/deployer/providers/tencentcloud-clb/consts.go @@ -0,0 +1,14 @@ +package tencentcloudclb + +type ResourceType string + +const ( + // 资源类型:通过 SSL 服务部署到云资源实例。 + RESOURCE_TYPE_VIA_SSLDEPLOY = ResourceType("ssl-deploy") + // 资源类型:部署到指定负载均衡器。 + RESOURCE_TYPE_LOADBALANCER = ResourceType("loadbalancer") + // 资源类型:部署到指定监听器。 + RESOURCE_TYPE_LISTENER = ResourceType("listener") + // 资源类型:部署到指定转发规则域名。 + RESOURCE_TYPE_RULEDOMAIN = ResourceType("ruledomain") +) diff --git a/internal/pkg/core/deployer/providers/tencentcloud-clb/defines.go b/internal/pkg/core/deployer/providers/tencentcloud-clb/defines.go deleted file mode 100644 index 7e7eace9..00000000 --- a/internal/pkg/core/deployer/providers/tencentcloud-clb/defines.go +++ /dev/null @@ -1,14 +0,0 @@ -package tencentcloudclb - -type DeployResourceType string - -const ( - // 资源类型:通过 SSL 服务部署到云资源实例。 - DEPLOY_RESOURCE_VIA_SSLDEPLOY = DeployResourceType("ssl-deploy") - // 资源类型:部署到指定负载均衡器。 - DEPLOY_RESOURCE_LOADBALANCER = DeployResourceType("loadbalancer") - // 资源类型:部署到指定监听器。 - DEPLOY_RESOURCE_LISTENER = DeployResourceType("listener") - // 资源类型:部署到指定转发规则域名。 - DEPLOY_RESOURCE_RULEDOMAIN = DeployResourceType("ruledomain") -) diff --git a/internal/pkg/core/deployer/providers/tencentcloud-clb/tencentcloud_clb.go b/internal/pkg/core/deployer/providers/tencentcloud-clb/tencentcloud_clb.go index e6982817..75eb5311 100644 --- a/internal/pkg/core/deployer/providers/tencentcloud-clb/tencentcloud_clb.go +++ b/internal/pkg/core/deployer/providers/tencentcloud-clb/tencentcloud_clb.go @@ -25,15 +25,15 @@ type TencentCloudCLBDeployerConfig struct { // 腾讯云地域。 Region string `json:"region"` // 部署资源类型。 - ResourceType DeployResourceType `json:"resourceType"` + ResourceType ResourceType `json:"resourceType"` // 负载均衡器 ID。 - // 部署资源类型为 [DEPLOY_RESOURCE_SSLDEPLOY]、[DEPLOY_RESOURCE_LOADBALANCER]、[DEPLOY_RESOURCE_RULEDOMAIN] 时必填。 + // 部署资源类型为 [RESOURCE_TYPE_SSLDEPLOY]、[RESOURCE_TYPE_LOADBALANCER]、[RESOURCE_TYPE_RULEDOMAIN] 时必填。 LoadbalancerId string `json:"loadbalancerId,omitempty"` // 负载均衡监听 ID。 - // 部署资源类型为 [DEPLOY_RESOURCE_SSLDEPLOY]、[DEPLOY_RESOURCE_LOADBALANCER]、[DEPLOY_RESOURCE_LISTENER]、[DEPLOY_RESOURCE_RULEDOMAIN] 时必填。 + // 部署资源类型为 [RESOURCE_TYPE_SSLDEPLOY]、[RESOURCE_TYPE_LOADBALANCER]、[RESOURCE_TYPE_LISTENER]、[RESOURCE_TYPE_RULEDOMAIN] 时必填。 ListenerId string `json:"listenerId,omitempty"` // SNI 域名或七层转发规则域名(支持泛域名)。 - // 部署资源类型为 [DEPLOY_RESOURCE_SSLDEPLOY] 时选填;部署资源类型为 [DEPLOY_RESOURCE_RULEDOMAIN] 时必填。 + // 部署资源类型为 [RESOURCE_TYPE_SSLDEPLOY] 时选填;部署资源类型为 [RESOURCE_TYPE_RULEDOMAIN] 时必填。 Domain string `json:"domain,omitempty"` } @@ -96,22 +96,22 @@ func (d *TencentCloudCLBDeployer) Deploy(ctx context.Context, certPem string, pr // 根据部署资源类型决定部署方式 switch d.config.ResourceType { - case DEPLOY_RESOURCE_VIA_SSLDEPLOY: + case RESOURCE_TYPE_VIA_SSLDEPLOY: if err := d.deployViaSslService(ctx, upres.CertId); err != nil { return nil, err } - case DEPLOY_RESOURCE_LOADBALANCER: + case RESOURCE_TYPE_LOADBALANCER: if err := d.deployToLoadbalancer(ctx, upres.CertId); err != nil { return nil, err } - case DEPLOY_RESOURCE_LISTENER: + case RESOURCE_TYPE_LISTENER: if err := d.deployToListener(ctx, upres.CertId); err != nil { return nil, err } - case DEPLOY_RESOURCE_RULEDOMAIN: + case RESOURCE_TYPE_RULEDOMAIN: if err := d.deployToRuleDomain(ctx, upres.CertId); err != nil { return nil, err } diff --git a/internal/pkg/core/deployer/providers/tencentcloud-clb/tencentcloud_clb_test.go b/internal/pkg/core/deployer/providers/tencentcloud-clb/tencentcloud_clb_test.go index 74a1e23e..6cc54e8f 100644 --- a/internal/pkg/core/deployer/providers/tencentcloud-clb/tencentcloud_clb_test.go +++ b/internal/pkg/core/deployer/providers/tencentcloud-clb/tencentcloud_clb_test.go @@ -68,7 +68,7 @@ func TestDeploy(t *testing.T) { SecretId: fSecretId, SecretKey: fSecretKey, Region: fRegion, - ResourceType: provider.DEPLOY_RESOURCE_VIA_SSLDEPLOY, + ResourceType: provider.RESOURCE_TYPE_VIA_SSLDEPLOY, LoadbalancerId: fLoadbalancerId, ListenerId: fListenerId, Domain: fDomain, @@ -104,7 +104,7 @@ func TestDeploy(t *testing.T) { SecretId: fSecretId, SecretKey: fSecretKey, Region: fRegion, - ResourceType: provider.DEPLOY_RESOURCE_LOADBALANCER, + ResourceType: provider.RESOURCE_TYPE_LOADBALANCER, LoadbalancerId: fLoadbalancerId, }) if err != nil { @@ -139,7 +139,7 @@ func TestDeploy(t *testing.T) { SecretId: fSecretId, SecretKey: fSecretKey, Region: fRegion, - ResourceType: provider.DEPLOY_RESOURCE_LISTENER, + ResourceType: provider.RESOURCE_TYPE_LISTENER, LoadbalancerId: fLoadbalancerId, ListenerId: fListenerId, }) @@ -176,7 +176,7 @@ func TestDeploy(t *testing.T) { SecretId: fSecretId, SecretKey: fSecretKey, Region: fRegion, - ResourceType: provider.DEPLOY_RESOURCE_RULEDOMAIN, + ResourceType: provider.RESOURCE_TYPE_RULEDOMAIN, LoadbalancerId: fLoadbalancerId, ListenerId: fListenerId, Domain: fDomain, diff --git a/internal/pkg/core/deployer/providers/volcengine-clb/consts.go b/internal/pkg/core/deployer/providers/volcengine-clb/consts.go new file mode 100644 index 00000000..dc1e992b --- /dev/null +++ b/internal/pkg/core/deployer/providers/volcengine-clb/consts.go @@ -0,0 +1,8 @@ +package volcengineclb + +type ResourceType string + +const ( + // 资源类型:部署到指定监听器。 + RESOURCE_TYPE_LISTENER = ResourceType("listener") +) diff --git a/internal/pkg/core/deployer/providers/volcengine-clb/defines.go b/internal/pkg/core/deployer/providers/volcengine-clb/defines.go deleted file mode 100644 index ec211199..00000000 --- a/internal/pkg/core/deployer/providers/volcengine-clb/defines.go +++ /dev/null @@ -1,8 +0,0 @@ -package volcengineclb - -type DeployResourceType string - -const ( - // 资源类型:部署到指定监听器。 - DEPLOY_RESOURCE_LISTENER = DeployResourceType("listener") -) diff --git a/internal/pkg/core/deployer/providers/volcengine-clb/volcengine_clb.go b/internal/pkg/core/deployer/providers/volcengine-clb/volcengine_clb.go index 08c096fd..4c03002d 100644 --- a/internal/pkg/core/deployer/providers/volcengine-clb/volcengine_clb.go +++ b/internal/pkg/core/deployer/providers/volcengine-clb/volcengine_clb.go @@ -24,9 +24,9 @@ type VolcEngineCLBDeployerConfig struct { // 火山引擎地域。 Region string `json:"region"` // 部署资源类型。 - ResourceType DeployResourceType `json:"resourceType"` + ResourceType ResourceType `json:"resourceType"` // 负载均衡监听器 ID。 - // 部署资源类型为 [DEPLOY_RESOURCE_LISTENER] 时必填。 + // 部署资源类型为 [RESOURCE_TYPE_LISTENER] 时必填。 ListenerId string `json:"listenerId,omitempty"` } @@ -85,7 +85,7 @@ func (d *VolcEngineCLBDeployer) Deploy(ctx context.Context, certPem string, priv // 根据部署资源类型决定部署方式 switch d.config.ResourceType { - case DEPLOY_RESOURCE_LISTENER: + case RESOURCE_TYPE_LISTENER: if err := d.deployToListener(ctx, upres.CertId); err != nil { return nil, err } diff --git a/internal/pkg/core/deployer/providers/volcengine-clb/volcengine_clb_test.go b/internal/pkg/core/deployer/providers/volcengine-clb/volcengine_clb_test.go index 45d79f44..730052a0 100644 --- a/internal/pkg/core/deployer/providers/volcengine-clb/volcengine_clb_test.go +++ b/internal/pkg/core/deployer/providers/volcengine-clb/volcengine_clb_test.go @@ -60,7 +60,7 @@ func TestDeploy(t *testing.T) { AccessKeyId: fAccessKeyId, AccessKeySecret: fAccessKeySecret, Region: fRegion, - ResourceType: provider.DEPLOY_RESOURCE_LISTENER, + ResourceType: provider.RESOURCE_TYPE_LISTENER, ListenerId: fListenerId, }) if err != nil { diff --git a/internal/pkg/core/uploader/providers/aliyun-cas/aliyun_cas.go b/internal/pkg/core/uploader/providers/aliyun-cas/aliyun_cas.go index ac71202e..3259bdb1 100644 --- a/internal/pkg/core/uploader/providers/aliyun-cas/aliyun_cas.go +++ b/internal/pkg/core/uploader/providers/aliyun-cas/aliyun_cas.go @@ -112,7 +112,7 @@ func (u *AliyunCASUploader) Upload(ctx context.Context, certPem string, privkeyP if listUserCertificateOrderResp.Body.CertificateOrderList == nil || len(listUserCertificateOrderResp.Body.CertificateOrderList) < int(listUserCertificateOrderLimit) { break } else { - listUserCertificateOrderPage += 1 + listUserCertificateOrderPage++ } } diff --git a/internal/pkg/core/uploader/providers/huaweicloud-waf/huaweicloud_waf.go b/internal/pkg/core/uploader/providers/huaweicloud-waf/huaweicloud_waf.go new file mode 100644 index 00000000..b4be3315 --- /dev/null +++ b/internal/pkg/core/uploader/providers/huaweicloud-waf/huaweicloud_waf.go @@ -0,0 +1,167 @@ +package huaweicloudwaf + +import ( + "context" + "errors" + "fmt" + "time" + + "github.com/huaweicloud/huaweicloud-sdk-go-v3/core/auth/basic" + hcWaf "github.com/huaweicloud/huaweicloud-sdk-go-v3/services/waf/v1" + hcWafModel "github.com/huaweicloud/huaweicloud-sdk-go-v3/services/waf/v1/model" + hcWafRegion "github.com/huaweicloud/huaweicloud-sdk-go-v3/services/waf/v1/region" + xerrors "github.com/pkg/errors" + + "github.com/usual2970/certimate/internal/pkg/core/uploader" + "github.com/usual2970/certimate/internal/pkg/utils/certs" + hwsdk "github.com/usual2970/certimate/internal/pkg/vendors/huaweicloud-sdk" +) + +type HuaweiCloudWAFUploaderConfig struct { + // 华为云 AccessKeyId。 + AccessKeyId string `json:"accessKeyId"` + // 华为云 SecretAccessKey。 + SecretAccessKey string `json:"secretAccessKey"` + // 华为云区域。 + Region string `json:"region"` +} + +type HuaweiCloudWAFUploader struct { + config *HuaweiCloudWAFUploaderConfig + sdkClient *hcWaf.WafClient +} + +var _ uploader.Uploader = (*HuaweiCloudWAFUploader)(nil) + +func New(config *HuaweiCloudWAFUploaderConfig) (*HuaweiCloudWAFUploader, error) { + if config == nil { + return nil, errors.New("config is nil") + } + + client, err := createSdkClient( + config.AccessKeyId, + config.SecretAccessKey, + config.Region, + ) + if err != nil { + return nil, xerrors.Wrap(err, "failed to create sdk client") + } + + return &HuaweiCloudWAFUploader{ + config: config, + sdkClient: client, + }, nil +} + +func (u *HuaweiCloudWAFUploader) Upload(ctx context.Context, certPem string, privkeyPem string) (res *uploader.UploadResult, err error) { + // 解析证书内容 + certX509, err := certs.ParseCertificateFromPEM(certPem) + if err != nil { + return nil, err + } + + // 遍历查询已有证书,避免重复上传 + // REF: https://support.huaweicloud.com/api-waf/ListCertificates.html + // REF: https://support.huaweicloud.com/api-waf/ShowCertificate.html + listCertificatesPage := int32(1) + listCertificatesLimit := int32(100) + for { + listCertificatesReq := &hcWafModel.ListCertificatesRequest{ + Page: hwsdk.Int32Ptr(listCertificatesPage), + Pagesize: hwsdk.Int32Ptr(listCertificatesLimit), + } + listCertificatesResp, err := u.sdkClient.ListCertificates(listCertificatesReq) + if err != nil { + return nil, xerrors.Wrap(err, "failed to execute sdk request 'waf.ListCertificates'") + } + + if listCertificatesResp.Items != nil { + for _, certItem := range *listCertificatesResp.Items { + showCertificateReq := &hcWafModel.ShowCertificateRequest{ + CertificateId: certItem.Id, + } + showCertificateResp, err := u.sdkClient.ShowCertificate(showCertificateReq) + if err != nil { + return nil, xerrors.Wrap(err, "failed to execute sdk request 'waf.ShowCertificate'") + } + + var isSameCert bool + if *showCertificateResp.Content == certPem { + isSameCert = true + } else { + oldCertX509, err := certs.ParseCertificateFromPEM(*showCertificateResp.Content) + if err != nil { + continue + } + + isSameCert = certs.EqualCertificate(certX509, oldCertX509) + } + + // 如果已存在相同证书,直接返回已有的证书信息 + if isSameCert { + return &uploader.UploadResult{ + CertId: certItem.Id, + CertName: certItem.Name, + }, nil + } + } + } + + if listCertificatesResp.Items == nil || len(*listCertificatesResp.Items) < int(listCertificatesLimit) { + break + } else { + listCertificatesPage++ + } + } + + // 生成新证书名(需符合华为云命名规则) + var certId, certName string + certName = fmt.Sprintf("certimate-%d", time.Now().UnixMilli()) + + // 创建证书 + // REF: https://support.huaweicloud.com/api-waf/CreateCertificate.html + createCertificateReq := &hcWafModel.CreateCertificateRequest{ + Body: &hcWafModel.CreateCertificateRequestBody{ + Name: certName, + Content: certPem, + Key: privkeyPem, + }, + } + createCertificateResp, err := u.sdkClient.CreateCertificate(createCertificateReq) + if err != nil { + return nil, xerrors.Wrap(err, "failed to execute sdk request 'waf.CreateCertificate'") + } + + certId = *createCertificateResp.Id + certName = *createCertificateResp.Name + return &uploader.UploadResult{ + CertId: certId, + CertName: certName, + }, nil +} + +func createSdkClient(accessKeyId, secretAccessKey, region string) (*hcWaf.WafClient, error) { + auth, err := basic.NewCredentialsBuilder(). + WithAk(accessKeyId). + WithSk(secretAccessKey). + SafeBuild() + if err != nil { + return nil, err + } + + hcRegion, err := hcWafRegion.SafeValueOf(region) + if err != nil { + return nil, err + } + + hcClient, err := hcWaf.WafClientBuilder(). + WithRegion(hcRegion). + WithCredential(auth). + SafeBuild() + if err != nil { + return nil, err + } + + client := hcWaf.NewWafClient(hcClient) + return client, nil +} From 61b7165bacdb36ffa1301657eceb420924cf97ef Mon Sep 17 00:00:00 2001 From: Fu Diwei Date: Mon, 17 Feb 2025 10:25:25 +0800 Subject: [PATCH 04/34] feat: add huaweicloud waf deployer --- README.md | 2 +- README_EN.md | 2 +- internal/deployer/providers.go | 26 +- internal/domain/provider.go | 1 + .../providers/huaweicloud-waf/consts.go | 12 + .../huaweicloud-waf/huaweicloud_waf.go | 358 ++++++++++++++++++ .../huaweicloud-waf/huaweicloud_waf_test.go | 84 ++++ .../volcengine-imagex/volcengine_imagex.go | 4 +- .../huaweicloud-waf/huaweicloud_waf.go | 53 ++- .../workflow/node/DeployNodeConfigForm.tsx | 3 + ...ployNodeConfigFormHuaweiCloudWAFConfig.tsx | 132 +++++++ ui/src/domain/provider.ts | 2 + ui/src/i18n/locales/en/nls.provider.json | 1 + .../i18n/locales/en/nls.workflow.nodes.json | 14 + ui/src/i18n/locales/zh/nls.provider.json | 1 + .../i18n/locales/zh/nls.workflow.nodes.json | 14 + 16 files changed, 695 insertions(+), 14 deletions(-) create mode 100644 internal/pkg/core/deployer/providers/huaweicloud-waf/consts.go create mode 100644 internal/pkg/core/deployer/providers/huaweicloud-waf/huaweicloud_waf.go create mode 100644 internal/pkg/core/deployer/providers/huaweicloud-waf/huaweicloud_waf_test.go create mode 100644 ui/src/components/workflow/node/DeployNodeConfigFormHuaweiCloudWAFConfig.tsx diff --git a/README.md b/README.md index 9a377b9d..3d826c0d 100644 --- a/README.md +++ b/README.md @@ -125,7 +125,7 @@ make local.run | [阿里云](https://www.aliyun.com/) | 可部署到阿里云 OSS、CDN、DCDN、ESA、SLB(CLB/ALB/NLB)、WAF、Live 等服务 | | [腾讯云](https://cloud.tencent.com/) | 可部署到腾讯云 COS、CDN、ECDN、EdgeOne、CLB、CSS 等服务 | | [百度智能云](https://cloud.baidu.com/) | 可部署到百度智能云 CDN 等服务 | -| [华为云](https://www.huaweicloud.com/) | 可部署到华为云 CDN、ELB 等服务 | +| [华为云](https://www.huaweicloud.com/) | 可部署到华为云 CDN、ELB、WAF 等服务 | | [火山引擎](https://www.volcengine.com/) | 可部署到火山引擎 TOS、CDN、DCDN、CLB、ImageX、Live 等服务 | | [七牛云](https://www.qiniu.com/) | 可部署到七牛云 CDN、直播云等服务 | | [多吉云](https://www.dogecloud.com/) | 可部署到多吉云 CDN | diff --git a/README_EN.md b/README_EN.md index 47c654f2..31713b7a 100644 --- a/README_EN.md +++ b/README_EN.md @@ -124,7 +124,7 @@ The following hosting providers are supported: | [Alibaba Cloud](https://www.alibabacloud.com/) | Supports deployment to Alibaba Cloud OSS, CDN, DCDN, SLB(CLB/ALB/NLB), WAF, Live | | [Tencent Cloud](https://www.tencentcloud.com/) | Supports deployment to Tencent Cloud COS, CDN, ECDN, EdgeOne, CLB, CSS | | [Baidu AI Cloud](https://intl.cloud.baidu.com/) | Supports deployment to Baidu AI CLoud CDN | -| [Huawei Cloud](https://www.huaweicloud.com/) | Supports deployment to Huawei Cloud CDN, ELB | +| [Huawei Cloud](https://www.huaweicloud.com/) | Supports deployment to Huawei Cloud CDN, ELB, WAF | | [Volcengine](https://www.volcengine.com/) | Supports deployment to Volcengine TOS, CDN, DCDN, CLB, ImageX, Live | | [Qiniu Cloud](https://www.qiniu.com/) | Supports deployment to Qiniu Cloud CDN, Pili | | [Doge Cloud](https://www.dogecloud.com/) | Supports deployment to Doge Cloud CDN | diff --git a/internal/deployer/providers.go b/internal/deployer/providers.go index 8d92b10f..22d294c8 100644 --- a/internal/deployer/providers.go +++ b/internal/deployer/providers.go @@ -25,6 +25,7 @@ import ( pEdgioApplications "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/edgio-applications" pHuaweiCloudCDN "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/huaweicloud-cdn" pHuaweiCloudELB "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/huaweicloud-elb" + pHuaweiCloudWAF "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/huaweicloud-waf" pK8sSecret "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/k8s-secret" pLocal "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/local" pQiniuCDN "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/qiniu-cdn" @@ -72,7 +73,7 @@ func createDeployer(options *deployerOptions) (deployer.Deployer, logger.Logger, AccessKeyId: access.AccessKeyId, AccessKeySecret: access.AccessKeySecret, Region: maps.GetValueAsString(options.ProviderDeployConfig, "region"), - ResourceType: pAliyunALB.DeployResourceType(maps.GetValueAsString(options.ProviderDeployConfig, "resourceType")), + ResourceType: pAliyunALB.ResourceType(maps.GetValueAsString(options.ProviderDeployConfig, "resourceType")), LoadbalancerId: maps.GetValueAsString(options.ProviderDeployConfig, "loadbalancerId"), ListenerId: maps.GetValueAsString(options.ProviderDeployConfig, "listenerId"), Domain: maps.GetValueAsString(options.ProviderDeployConfig, "domain"), @@ -102,7 +103,7 @@ func createDeployer(options *deployerOptions) (deployer.Deployer, logger.Logger, AccessKeyId: access.AccessKeyId, AccessKeySecret: access.AccessKeySecret, Region: maps.GetValueAsString(options.ProviderDeployConfig, "region"), - ResourceType: pAliyunCLB.DeployResourceType(maps.GetValueAsString(options.ProviderDeployConfig, "resourceType")), + ResourceType: pAliyunCLB.ResourceType(maps.GetValueAsString(options.ProviderDeployConfig, "resourceType")), LoadbalancerId: maps.GetValueAsString(options.ProviderDeployConfig, "loadbalancerId"), ListenerPort: maps.GetValueOrDefaultAsInt32(options.ProviderDeployConfig, "listenerPort", 443), Domain: maps.GetValueAsString(options.ProviderDeployConfig, "domain"), @@ -140,7 +141,7 @@ func createDeployer(options *deployerOptions) (deployer.Deployer, logger.Logger, AccessKeyId: access.AccessKeyId, AccessKeySecret: access.AccessKeySecret, Region: maps.GetValueAsString(options.ProviderDeployConfig, "region"), - ResourceType: pAliyunNLB.DeployResourceType(maps.GetValueAsString(options.ProviderDeployConfig, "resourceType")), + ResourceType: pAliyunNLB.ResourceType(maps.GetValueAsString(options.ProviderDeployConfig, "resourceType")), LoadbalancerId: maps.GetValueAsString(options.ProviderDeployConfig, "loadbalancerId"), ListenerId: maps.GetValueAsString(options.ProviderDeployConfig, "listenerId"), }, logger) @@ -293,7 +294,7 @@ func createDeployer(options *deployerOptions) (deployer.Deployer, logger.Logger, return deployer, logger, err } - case domain.DeployProviderTypeHuaweiCloudCDN, domain.DeployProviderTypeHuaweiCloudELB: + case domain.DeployProviderTypeHuaweiCloudCDN, domain.DeployProviderTypeHuaweiCloudELB, domain.DeployProviderTypeHuaweiCloudWAF: { access := domain.AccessConfigForHuaweiCloud{} if err := maps.Populate(options.ProviderAccessConfig, &access); err != nil { @@ -315,13 +316,24 @@ func createDeployer(options *deployerOptions) (deployer.Deployer, logger.Logger, AccessKeyId: access.AccessKeyId, SecretAccessKey: access.SecretAccessKey, Region: maps.GetValueAsString(options.ProviderDeployConfig, "region"), - ResourceType: pHuaweiCloudELB.DeployResourceType(maps.GetValueAsString(options.ProviderDeployConfig, "resourceType")), + ResourceType: pHuaweiCloudELB.ResourceType(maps.GetValueAsString(options.ProviderDeployConfig, "resourceType")), CertificateId: maps.GetValueAsString(options.ProviderDeployConfig, "certificateId"), LoadbalancerId: maps.GetValueAsString(options.ProviderDeployConfig, "loadbalancerId"), ListenerId: maps.GetValueAsString(options.ProviderDeployConfig, "listenerId"), }, logger) return deployer, logger, err + case domain.DeployProviderTypeHuaweiCloudWAF: + deployer, err := pHuaweiCloudWAF.NewWithLogger(&pHuaweiCloudWAF.HuaweiCloudWAFDeployerConfig{ + AccessKeyId: access.AccessKeyId, + SecretAccessKey: access.SecretAccessKey, + Region: maps.GetValueAsString(options.ProviderDeployConfig, "region"), + ResourceType: pHuaweiCloudWAF.ResourceType(maps.GetValueAsString(options.ProviderDeployConfig, "resourceType")), + CertificateId: maps.GetValueAsString(options.ProviderDeployConfig, "certificateId"), + Domain: maps.GetValueAsString(options.ProviderDeployConfig, "domain"), + }, logger) + return deployer, logger, err + default: break } @@ -441,7 +453,7 @@ func createDeployer(options *deployerOptions) (deployer.Deployer, logger.Logger, SecretId: access.SecretId, SecretKey: access.SecretKey, Region: maps.GetValueAsString(options.ProviderDeployConfig, "region"), - ResourceType: pTencentCloudCLB.DeployResourceType(maps.GetValueAsString(options.ProviderDeployConfig, "resourceType")), + ResourceType: pTencentCloudCLB.ResourceType(maps.GetValueAsString(options.ProviderDeployConfig, "resourceType")), LoadbalancerId: maps.GetValueAsString(options.ProviderDeployConfig, "loadbalancerId"), ListenerId: maps.GetValueAsString(options.ProviderDeployConfig, "listenerId"), Domain: maps.GetValueAsString(options.ProviderDeployConfig, "domain"), @@ -552,7 +564,7 @@ func createDeployer(options *deployerOptions) (deployer.Deployer, logger.Logger, AccessKeyId: access.AccessKeyId, AccessKeySecret: access.SecretAccessKey, Region: maps.GetValueAsString(options.ProviderDeployConfig, "region"), - ResourceType: pVolcEngineCLB.DeployResourceType(maps.GetValueAsString(options.ProviderDeployConfig, "resourceType")), + ResourceType: pVolcEngineCLB.ResourceType(maps.GetValueAsString(options.ProviderDeployConfig, "resourceType")), ListenerId: maps.GetValueAsString(options.ProviderDeployConfig, "listenerId"), }, logger) return deployer, logger, err diff --git a/internal/domain/provider.go b/internal/domain/provider.go index c8425b06..015e4f28 100644 --- a/internal/domain/provider.go +++ b/internal/domain/provider.go @@ -114,6 +114,7 @@ const ( DeployProviderTypeEdgioApplications = DeployProviderType("edgio-applications") DeployProviderTypeHuaweiCloudCDN = DeployProviderType("huaweicloud-cdn") DeployProviderTypeHuaweiCloudELB = DeployProviderType("huaweicloud-elb") + DeployProviderTypeHuaweiCloudWAF = DeployProviderType("huaweicloud-waf") DeployProviderTypeKubernetesSecret = DeployProviderType("k8s-secret") DeployProviderTypeLocal = DeployProviderType("local") DeployProviderTypeQiniuCDN = DeployProviderType("qiniu-cdn") diff --git a/internal/pkg/core/deployer/providers/huaweicloud-waf/consts.go b/internal/pkg/core/deployer/providers/huaweicloud-waf/consts.go new file mode 100644 index 00000000..fc574c32 --- /dev/null +++ b/internal/pkg/core/deployer/providers/huaweicloud-waf/consts.go @@ -0,0 +1,12 @@ +package huaweicloudwaf + +type ResourceType string + +const ( + // 资源类型:替换指定证书。 + RESOURCE_TYPE_CERTIFICATE = ResourceType("certificate") + // 资源类型:部署到云模式防护网站。 + RESOURCE_TYPE_CLOUDSERVER = ResourceType("cloudserver") + // 资源类型:部署到独享模式防护网站。 + RESOURCE_TYPE_PREMIUMHOST = ResourceType("premiumhost") +) diff --git a/internal/pkg/core/deployer/providers/huaweicloud-waf/huaweicloud_waf.go b/internal/pkg/core/deployer/providers/huaweicloud-waf/huaweicloud_waf.go new file mode 100644 index 00000000..80ac4fe6 --- /dev/null +++ b/internal/pkg/core/deployer/providers/huaweicloud-waf/huaweicloud_waf.go @@ -0,0 +1,358 @@ +package huaweicloudwaf + +import ( + "context" + "errors" + "fmt" + "strings" + + "github.com/huaweicloud/huaweicloud-sdk-go-v3/core/auth/basic" + "github.com/huaweicloud/huaweicloud-sdk-go-v3/core/auth/global" + hcIam "github.com/huaweicloud/huaweicloud-sdk-go-v3/services/iam/v3" + hcIamModel "github.com/huaweicloud/huaweicloud-sdk-go-v3/services/iam/v3/model" + hcIamRegion "github.com/huaweicloud/huaweicloud-sdk-go-v3/services/iam/v3/region" + hcWaf "github.com/huaweicloud/huaweicloud-sdk-go-v3/services/waf/v1" + hcWafModel "github.com/huaweicloud/huaweicloud-sdk-go-v3/services/waf/v1/model" + hcWafRegion "github.com/huaweicloud/huaweicloud-sdk-go-v3/services/waf/v1/region" + xerrors "github.com/pkg/errors" + + "github.com/usual2970/certimate/internal/pkg/core/deployer" + "github.com/usual2970/certimate/internal/pkg/core/logger" + "github.com/usual2970/certimate/internal/pkg/core/uploader" + uploaderp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/huaweicloud-waf" + hwsdk "github.com/usual2970/certimate/internal/pkg/vendors/huaweicloud-sdk" +) + +type HuaweiCloudWAFDeployerConfig struct { + // 华为云 AccessKeyId。 + AccessKeyId string `json:"accessKeyId"` + // 华为云 SecretAccessKey。 + SecretAccessKey string `json:"secretAccessKey"` + // 华为云区域。 + Region string `json:"region"` + // 部署资源类型。 + ResourceType ResourceType `json:"resourceType"` + // 证书 ID。 + // 部署资源类型为 [RESOURCE_TYPE_CERTIFICATE] 时必填。 + CertificateId string `json:"certificateId,omitempty"` + // 防护域名(支持泛域名)。 + // 部署资源类型为 [RESOURCE_TYPE_CLOUDSERVER]、[RESOURCE_TYPE_PREMIUMHOST] 时必填。 + Domain string `json:"domain,omitempty"` +} + +type HuaweiCloudWAFDeployer struct { + config *HuaweiCloudWAFDeployerConfig + logger logger.Logger + sdkClient *hcWaf.WafClient + sslUploader uploader.Uploader +} + +var _ deployer.Deployer = (*HuaweiCloudWAFDeployer)(nil) + +func New(config *HuaweiCloudWAFDeployerConfig) (*HuaweiCloudWAFDeployer, error) { + return NewWithLogger(config, logger.NewNilLogger()) +} + +func NewWithLogger(config *HuaweiCloudWAFDeployerConfig, logger logger.Logger) (*HuaweiCloudWAFDeployer, error) { + if config == nil { + return nil, errors.New("config is nil") + } + + if logger == nil { + return nil, errors.New("logger is nil") + } + + client, err := createSdkClient(config.AccessKeyId, config.SecretAccessKey, config.Region) + if err != nil { + return nil, xerrors.Wrap(err, "failed to create sdk client") + } + + uploader, err := uploaderp.New(&uploaderp.HuaweiCloudWAFUploaderConfig{ + AccessKeyId: config.AccessKeyId, + SecretAccessKey: config.SecretAccessKey, + Region: config.Region, + }) + if err != nil { + return nil, xerrors.Wrap(err, "failed to create ssl uploader") + } + + return &HuaweiCloudWAFDeployer{ + logger: logger, + config: config, + sdkClient: client, + sslUploader: uploader, + }, nil +} + +func (d *HuaweiCloudWAFDeployer) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { + // 上传证书到 WAF + upres, err := d.sslUploader.Upload(ctx, certPem, privkeyPem) + if err != nil { + return nil, xerrors.Wrap(err, "failed to upload certificate file") + } + + d.logger.Logt("certificate file uploaded", upres) + + // 根据部署资源类型决定部署方式 + switch d.config.ResourceType { + case RESOURCE_TYPE_CERTIFICATE: + if err := d.deployToCertificate(ctx, certPem, privkeyPem); err != nil { + return nil, err + } + + case RESOURCE_TYPE_CLOUDSERVER: + if err := d.deployToCloudServer(ctx, certPem, privkeyPem); err != nil { + return nil, err + } + + case RESOURCE_TYPE_PREMIUMHOST: + if err := d.deployToPremiumHost(ctx, certPem, privkeyPem); err != nil { + return nil, err + } + + default: + return nil, fmt.Errorf("unsupported resource type: %s", d.config.ResourceType) + } + + return &deployer.DeployResult{}, nil +} + +func (d *HuaweiCloudWAFDeployer) deployToCertificate(ctx context.Context, certPem string, privkeyPem string) error { + if d.config.CertificateId == "" { + return errors.New("config `certificateId` is required") + } + + // 查询证书 + // REF: https://support.huaweicloud.com/api-waf/ShowCertificate.html + showCertificateReq := &hcWafModel.ShowCertificateRequest{ + CertificateId: d.config.CertificateId, + } + showCertificateResp, err := d.sdkClient.ShowCertificate(showCertificateReq) + if err != nil { + return xerrors.Wrap(err, "failed to execute sdk request 'waf.ShowCertificate'") + } else { + d.logger.Logt("已获取 WAF 证书", showCertificateResp) + } + + // 更新证书 + // REF: https://support.huaweicloud.com/api-waf/UpdateCertificate.html + updateCertificateReq := &hcWafModel.UpdateCertificateRequest{ + CertificateId: d.config.CertificateId, + Body: &hcWafModel.UpdateCertificateRequestBody{ + Name: *showCertificateResp.Name, + Content: hwsdk.StringPtr(certPem), + Key: hwsdk.StringPtr(privkeyPem), + }, + } + updateCertificateResp, err := d.sdkClient.UpdateCertificate(updateCertificateReq) + if err != nil { + return xerrors.Wrap(err, "failed to execute sdk request 'waf.UpdateCertificate'") + } else { + d.logger.Logt("已更新 WAF 证书", updateCertificateResp) + } + + return nil +} + +func (d *HuaweiCloudWAFDeployer) deployToCloudServer(ctx context.Context, certPem string, privkeyPem string) error { + if d.config.Domain == "" { + return errors.New("config `domain` is required") + } + + // 上传证书到 WAF + upres, err := d.sslUploader.Upload(ctx, certPem, privkeyPem) + if err != nil { + return xerrors.Wrap(err, "failed to upload certificate file") + } else { + d.logger.Logt("certificate file uploaded", upres) + } + + // 遍历查询云模式防护域名列表,获取防护域名 ID + // REF: https://support.huaweicloud.com/api-waf/ListHost.html + hostId := "" + listHostPage := int32(1) + listHostPageSize := int32(100) + for { + listHostReq := &hcWafModel.ListHostRequest{ + Hostname: hwsdk.StringPtr(strings.TrimPrefix(d.config.Domain, "*")), + Page: hwsdk.Int32Ptr(listHostPage), + Pagesize: hwsdk.Int32Ptr(listHostPageSize), + } + listHostResp, err := d.sdkClient.ListHost(listHostReq) + if err != nil { + return xerrors.Wrap(err, "failed to execute sdk request 'waf.ListHost'") + } + + if listHostResp.Items != nil { + for _, hostItem := range *listHostResp.Items { + if strings.TrimPrefix(d.config.Domain, "*") == *hostItem.Hostname { + hostId = *hostItem.Id + break + } + } + } + + if listHostResp.Items == nil || len(*listHostResp.Items) < int(listHostPageSize) { + break + } else { + listHostPage++ + } + } + if hostId == "" { + return errors.New("host not found") + } + + // 更新云模式防护域名的配置 + // REF: https://support.huaweicloud.com/api-waf/UpdateHost.html + updateHostReq := &hcWafModel.UpdateHostRequest{ + InstanceId: hostId, + Body: &hcWafModel.UpdateHostRequestBody{ + Certificateid: hwsdk.StringPtr(upres.CertId), + Certificatename: hwsdk.StringPtr(upres.CertName), + }, + } + updateHostResp, err := d.sdkClient.UpdateHost(updateHostReq) + if err != nil { + return xerrors.Wrap(err, "failed to execute sdk request 'waf.UpdateHost'") + } else { + d.logger.Logt("已更新云模式防护域名的配置", updateHostResp) + } + + return nil +} + +func (d *HuaweiCloudWAFDeployer) deployToPremiumHost(ctx context.Context, certPem string, privkeyPem string) error { + if d.config.Domain == "" { + return errors.New("config `domain` is required") + } + + // 上传证书到 WAF + upres, err := d.sslUploader.Upload(ctx, certPem, privkeyPem) + if err != nil { + return xerrors.Wrap(err, "failed to upload certificate file") + } else { + d.logger.Logt("certificate file uploaded", upres) + } + + // 遍历查询独享模式域名列表,获取防护域名 ID + // REF: https://support.huaweicloud.com/api-waf/ListPremiumHost.html + hostId := "" + listPremiumHostPage := int32(1) + listPremiumHostPageSize := int32(100) + for { + listPremiumHostReq := &hcWafModel.ListPremiumHostRequest{ + Hostname: hwsdk.StringPtr(strings.TrimPrefix(d.config.Domain, "*")), + Page: hwsdk.StringPtr(fmt.Sprintf("%d", listPremiumHostPage)), + Pagesize: hwsdk.StringPtr(fmt.Sprintf("%d", listPremiumHostPageSize)), + } + listPremiumHostResp, err := d.sdkClient.ListPremiumHost(listPremiumHostReq) + if err != nil { + return xerrors.Wrap(err, "failed to execute sdk request 'waf.ListPremiumHost'") + } + + if listPremiumHostResp.Items != nil { + for _, hostItem := range *listPremiumHostResp.Items { + if strings.TrimPrefix(d.config.Domain, "*") == *hostItem.Hostname { + hostId = *hostItem.Id + break + } + } + } + + if listPremiumHostResp.Items == nil || len(*listPremiumHostResp.Items) < int(listPremiumHostPageSize) { + break + } else { + listPremiumHostPage++ + } + } + if hostId == "" { + return errors.New("host not found") + } + + // 修改独享模式域名配置 + // REF: https://support.huaweicloud.com/api-waf/UpdatePremiumHost.html + updatePremiumHostReq := &hcWafModel.UpdatePremiumHostRequest{ + HostId: hostId, + Body: &hcWafModel.UpdatePremiumHostRequestBody{ + Certificateid: hwsdk.StringPtr(upres.CertId), + Certificatename: hwsdk.StringPtr(upres.CertName), + }, + } + updatePremiumHostResp, err := d.sdkClient.UpdatePremiumHost(updatePremiumHostReq) + if err != nil { + return xerrors.Wrap(err, "failed to execute sdk request 'waf.UpdatePremiumHost'") + } else { + d.logger.Logt("已修改独享模式域名配置", updatePremiumHostResp) + } + + return nil +} + +func createSdkClient(accessKeyId, secretAccessKey, region string) (*hcWaf.WafClient, error) { + projectId, err := getSdkProjectId(accessKeyId, secretAccessKey, region) + if err != nil { + return nil, err + } + + auth, err := basic.NewCredentialsBuilder(). + WithAk(accessKeyId). + WithSk(secretAccessKey). + WithProjectId(projectId). + SafeBuild() + if err != nil { + return nil, err + } + + hcRegion, err := hcWafRegion.SafeValueOf(region) + if err != nil { + return nil, err + } + + hcClient, err := hcWaf.WafClientBuilder(). + WithRegion(hcRegion). + WithCredential(auth). + SafeBuild() + if err != nil { + return nil, err + } + + client := hcWaf.NewWafClient(hcClient) + return client, nil +} + +func getSdkProjectId(accessKeyId, secretAccessKey, region string) (string, error) { + auth, err := global.NewCredentialsBuilder(). + WithAk(accessKeyId). + WithSk(secretAccessKey). + SafeBuild() + if err != nil { + return "", err + } + + hcRegion, err := hcIamRegion.SafeValueOf(region) + if err != nil { + return "", err + } + + hcClient, err := hcIam.IamClientBuilder(). + WithRegion(hcRegion). + WithCredential(auth). + SafeBuild() + if err != nil { + return "", err + } + + client := hcIam.NewIamClient(hcClient) + + request := &hcIamModel.KeystoneListProjectsRequest{ + Name: ®ion, + } + response, err := client.KeystoneListProjects(request) + if err != nil { + return "", err + } else if response.Projects == nil || len(*response.Projects) == 0 { + return "", errors.New("no project found") + } + + return (*response.Projects)[0].Id, nil +} diff --git a/internal/pkg/core/deployer/providers/huaweicloud-waf/huaweicloud_waf_test.go b/internal/pkg/core/deployer/providers/huaweicloud-waf/huaweicloud_waf_test.go new file mode 100644 index 00000000..0ec57013 --- /dev/null +++ b/internal/pkg/core/deployer/providers/huaweicloud-waf/huaweicloud_waf_test.go @@ -0,0 +1,84 @@ +package huaweicloudwaf_test + +import ( + "context" + "flag" + "fmt" + "os" + "strings" + "testing" + + provider "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/huaweicloud-waf" +) + +var ( + fInputCertPath string + fInputKeyPath string + fAccessKeyId string + fSecretAccessKey string + fRegion string + fResourceType string + fDomain string +) + +func init() { + argsPrefix := "CERTIMATE_DEPLOYER_HUAWEICLOUDWAF_" + + flag.StringVar(&fInputCertPath, argsPrefix+"INPUTCERTPATH", "", "") + flag.StringVar(&fInputKeyPath, argsPrefix+"INPUTKEYPATH", "", "") + flag.StringVar(&fAccessKeyId, argsPrefix+"ACCESSKEYID", "", "") + flag.StringVar(&fSecretAccessKey, argsPrefix+"SECRETACCESSKEY", "", "") + flag.StringVar(&fRegion, argsPrefix+"REGION", "", "") + flag.StringVar(&fResourceType, argsPrefix+"RESOURCETYPE", "", "") + flag.StringVar(&fDomain, argsPrefix+"DOMAIN", "", "") +} + +/* +Shell command to run this test: + + go test -v ./huaweicloud_waf_test.go -args \ + --CERTIMATE_DEPLOYER_HUAWEICLOUDWAF_INPUTCERTPATH="/path/to/your-input-cert.pem" \ + --CERTIMATE_DEPLOYER_HUAWEICLOUDWAF_INPUTKEYPATH="/path/to/your-input-key.pem" \ + --CERTIMATE_DEPLOYER_HUAWEICLOUDWAF_ACCESSKEYID="your-access-key-id" \ + --CERTIMATE_DEPLOYER_HUAWEICLOUDWAF_SECRETACCESSKEY="your-secret-access-key" \ + --CERTIMATE_DEPLOYER_HUAWEICLOUDWAF_REGION="cn-north-1" \ + --CERTIMATE_DEPLOYER_HUAWEICLOUDWAF_RESOURCETYPE="premium" \ + --CERTIMATE_DEPLOYER_HUAWEICLOUDWAF_DOMAIN="example.com" +*/ +func TestDeploy(t *testing.T) { + flag.Parse() + + t.Run("Deploy", func(t *testing.T) { + t.Log(strings.Join([]string{ + "args:", + fmt.Sprintf("INPUTCERTPATH: %v", fInputCertPath), + fmt.Sprintf("INPUTKEYPATH: %v", fInputKeyPath), + fmt.Sprintf("ACCESSKEYID: %v", fAccessKeyId), + fmt.Sprintf("SECRETACCESSKEY: %v", fSecretAccessKey), + fmt.Sprintf("REGION: %v", fRegion), + fmt.Sprintf("RESOURCETYPE: %v", fResourceType), + }, "\n")) + + deployer, err := provider.New(&provider.HuaweiCloudWAFDeployerConfig{ + AccessKeyId: fAccessKeyId, + SecretAccessKey: fSecretAccessKey, + Region: fRegion, + ResourceType: provider.ResourceType(fResourceType), + Domain: fDomain, + }) + if err != nil { + t.Errorf("err: %+v", err) + return + } + + fInputCertData, _ := os.ReadFile(fInputCertPath) + fInputKeyData, _ := os.ReadFile(fInputKeyPath) + res, err := deployer.Deploy(context.Background(), string(fInputCertData), string(fInputKeyData)) + if err != nil { + t.Errorf("err: %+v", err) + return + } + + t.Logf("ok: %v", res) + }) +} diff --git a/internal/pkg/core/deployer/providers/volcengine-imagex/volcengine_imagex.go b/internal/pkg/core/deployer/providers/volcengine-imagex/volcengine_imagex.go index 00102896..dea81300 100644 --- a/internal/pkg/core/deployer/providers/volcengine-imagex/volcengine_imagex.go +++ b/internal/pkg/core/deployer/providers/volcengine-imagex/volcengine_imagex.go @@ -83,10 +83,10 @@ func (d *VolcEngineImageXDeployer) Deploy(ctx context.Context, certPem string, p upres, err := d.sslUploader.Upload(ctx, certPem, privkeyPem) if err != nil { return nil, xerrors.Wrap(err, "failed to upload certificate file") + } else { + d.logger.Logt("certificate file uploaded", upres) } - d.logger.Logt("certificate file uploaded", upres) - // 获取域名配置 // REF: https://www.volcengine.com/docs/508/9366 getDomainConfigReq := &veImageX.GetDomainConfigQuery{ diff --git a/internal/pkg/core/uploader/providers/huaweicloud-waf/huaweicloud_waf.go b/internal/pkg/core/uploader/providers/huaweicloud-waf/huaweicloud_waf.go index b4be3315..eb2eb7f2 100644 --- a/internal/pkg/core/uploader/providers/huaweicloud-waf/huaweicloud_waf.go +++ b/internal/pkg/core/uploader/providers/huaweicloud-waf/huaweicloud_waf.go @@ -7,6 +7,10 @@ import ( "time" "github.com/huaweicloud/huaweicloud-sdk-go-v3/core/auth/basic" + "github.com/huaweicloud/huaweicloud-sdk-go-v3/core/auth/global" + hcIam "github.com/huaweicloud/huaweicloud-sdk-go-v3/services/iam/v3" + hcIamModel "github.com/huaweicloud/huaweicloud-sdk-go-v3/services/iam/v3/model" + hcIamRegion "github.com/huaweicloud/huaweicloud-sdk-go-v3/services/iam/v3/region" hcWaf "github.com/huaweicloud/huaweicloud-sdk-go-v3/services/waf/v1" hcWafModel "github.com/huaweicloud/huaweicloud-sdk-go-v3/services/waf/v1/model" hcWafRegion "github.com/huaweicloud/huaweicloud-sdk-go-v3/services/waf/v1/region" @@ -64,11 +68,11 @@ func (u *HuaweiCloudWAFUploader) Upload(ctx context.Context, certPem string, pri // REF: https://support.huaweicloud.com/api-waf/ListCertificates.html // REF: https://support.huaweicloud.com/api-waf/ShowCertificate.html listCertificatesPage := int32(1) - listCertificatesLimit := int32(100) + listCertificatesPageSize := int32(100) for { listCertificatesReq := &hcWafModel.ListCertificatesRequest{ Page: hwsdk.Int32Ptr(listCertificatesPage), - Pagesize: hwsdk.Int32Ptr(listCertificatesLimit), + Pagesize: hwsdk.Int32Ptr(listCertificatesPageSize), } listCertificatesResp, err := u.sdkClient.ListCertificates(listCertificatesReq) if err != nil { @@ -107,7 +111,7 @@ func (u *HuaweiCloudWAFUploader) Upload(ctx context.Context, certPem string, pri } } - if listCertificatesResp.Items == nil || len(*listCertificatesResp.Items) < int(listCertificatesLimit) { + if listCertificatesResp.Items == nil || len(*listCertificatesResp.Items) < int(listCertificatesPageSize) { break } else { listCertificatesPage++ @@ -141,9 +145,15 @@ func (u *HuaweiCloudWAFUploader) Upload(ctx context.Context, certPem string, pri } func createSdkClient(accessKeyId, secretAccessKey, region string) (*hcWaf.WafClient, error) { + projectId, err := getSdkProjectId(accessKeyId, secretAccessKey, region) + if err != nil { + return nil, err + } + auth, err := basic.NewCredentialsBuilder(). WithAk(accessKeyId). WithSk(secretAccessKey). + WithProjectId(projectId). SafeBuild() if err != nil { return nil, err @@ -165,3 +175,40 @@ func createSdkClient(accessKeyId, secretAccessKey, region string) (*hcWaf.WafCli client := hcWaf.NewWafClient(hcClient) return client, nil } + +func getSdkProjectId(accessKeyId, secretAccessKey, region string) (string, error) { + auth, err := global.NewCredentialsBuilder(). + WithAk(accessKeyId). + WithSk(secretAccessKey). + SafeBuild() + if err != nil { + return "", err + } + + hcRegion, err := hcIamRegion.SafeValueOf(region) + if err != nil { + return "", err + } + + hcClient, err := hcIam.IamClientBuilder(). + WithRegion(hcRegion). + WithCredential(auth). + SafeBuild() + if err != nil { + return "", err + } + + client := hcIam.NewIamClient(hcClient) + + request := &hcIamModel.KeystoneListProjectsRequest{ + Name: ®ion, + } + response, err := client.KeystoneListProjects(request) + if err != nil { + return "", err + } else if response.Projects == nil || len(*response.Projects) == 0 { + return "", errors.New("no project found") + } + + return (*response.Projects)[0].Id, nil +} diff --git a/ui/src/components/workflow/node/DeployNodeConfigForm.tsx b/ui/src/components/workflow/node/DeployNodeConfigForm.tsx index e7a1f5d9..93cf857e 100644 --- a/ui/src/components/workflow/node/DeployNodeConfigForm.tsx +++ b/ui/src/components/workflow/node/DeployNodeConfigForm.tsx @@ -34,6 +34,7 @@ import DeployNodeConfigFormDogeCloudCDNConfig from "./DeployNodeConfigFormDogeCl import DeployNodeConfigFormEdgioApplicationsConfig from "./DeployNodeConfigFormEdgioApplicationsConfig"; import DeployNodeConfigFormHuaweiCloudCDNConfig from "./DeployNodeConfigFormHuaweiCloudCDNConfig"; import DeployNodeConfigFormHuaweiCloudELBConfig from "./DeployNodeConfigFormHuaweiCloudELBConfig"; +import DeployNodeConfigFormHuaweiCloudWAFConfig from "./DeployNodeConfigFormHuaweiCloudWAFConfig"; import DeployNodeConfigFormKubernetesSecretConfig from "./DeployNodeConfigFormKubernetesSecretConfig"; import DeployNodeConfigFormLocalConfig from "./DeployNodeConfigFormLocalConfig"; import DeployNodeConfigFormQiniuCDNConfig from "./DeployNodeConfigFormQiniuCDNConfig"; @@ -165,6 +166,8 @@ const DeployNodeConfigForm = forwardRef; case DEPLOY_PROVIDERS.HUAWEICLOUD_ELB: return ; + case DEPLOY_PROVIDERS.HUAWEICLOUD_WAF: + return ; case DEPLOY_PROVIDERS.KUBERNETES_SECRET: return ; case DEPLOY_PROVIDERS.LOCAL: diff --git a/ui/src/components/workflow/node/DeployNodeConfigFormHuaweiCloudWAFConfig.tsx b/ui/src/components/workflow/node/DeployNodeConfigFormHuaweiCloudWAFConfig.tsx new file mode 100644 index 00000000..cdcabef5 --- /dev/null +++ b/ui/src/components/workflow/node/DeployNodeConfigFormHuaweiCloudWAFConfig.tsx @@ -0,0 +1,132 @@ +import { useTranslation } from "react-i18next"; +import { Form, type FormInstance, Input, Select } from "antd"; +import { createSchemaFieldRule } from "antd-zod"; +import { z } from "zod"; + +import Show from "@/components/Show"; +import { validDomainName } from "@/utils/validators"; + +type DeployNodeConfigFormHuaweiCloudWAFConfigFieldValues = Nullish<{ + resourceType: string; + region: string; + certificateId?: string; + domain?: string; + listenerId?: string; +}>; + +export type DeployNodeConfigFormHuaweiCloudWAFConfigProps = { + form: FormInstance; + formName: string; + disabled?: boolean; + initialValues?: DeployNodeConfigFormHuaweiCloudWAFConfigFieldValues; + onValuesChange?: (values: DeployNodeConfigFormHuaweiCloudWAFConfigFieldValues) => void; +}; + +const RESOURCE_TYPE_CERTIFICATE = "certificate" as const; +const RESOURCE_TYPE_CLOUDSERVER = "cloudserver" as const; +const RESOURCE_TYPE_PREMIUMHOST = "premiumhost" as const; + +const initFormModel = (): DeployNodeConfigFormHuaweiCloudWAFConfigFieldValues => { + return {}; +}; + +const DeployNodeConfigFormHuaweiCloudWAFConfig = ({ + form: formInst, + formName, + disabled, + initialValues, + onValuesChange, +}: DeployNodeConfigFormHuaweiCloudWAFConfigProps) => { + const { t } = useTranslation(); + + const formSchema = z.object({ + resourceType: z.union([z.literal(RESOURCE_TYPE_CERTIFICATE), z.literal(RESOURCE_TYPE_CLOUDSERVER), z.literal(RESOURCE_TYPE_PREMIUMHOST)], { + message: t("workflow_node.deploy.form.huaweicloud_waf_resource_type.placeholder"), + }), + region: z + .string({ message: t("workflow_node.deploy.form.huaweicloud_waf_region.placeholder") }) + .nonempty(t("workflow_node.deploy.form.huaweicloud_waf_region.placeholder")) + .trim(), + certificateId: z + .string() + .max(64, t("common.errmsg.string_max", { max: 64 })) + .trim() + .nullish() + .refine((v) => { + if (fieldResourceType !== RESOURCE_TYPE_CERTIFICATE) return true; + return !!v?.trim(); + }, t("workflow_node.deploy.form.huaweicloud_waf_certificate_id.placeholder")), + domain: z + .string() + .nullish() + .refine((v) => { + if (fieldResourceType !== RESOURCE_TYPE_CLOUDSERVER && fieldResourceType !== RESOURCE_TYPE_PREMIUMHOST) return true; + return validDomainName(v!, { allowWildcard: true }); + }, t("workflow_node.deploy.form.huaweicloud_waf_domain.placeholder")), + }); + const formRule = createSchemaFieldRule(formSchema); + + const fieldResourceType = Form.useWatch("resourceType", formInst); + + const handleFormChange = (_: unknown, values: z.infer) => { + onValuesChange?.(values); + }; + + return ( +
+ + + + + } + > + + + + + } + > + + + + + + } + > + + + +
+ ); +}; + +export default DeployNodeConfigFormHuaweiCloudWAFConfig; diff --git a/ui/src/domain/provider.ts b/ui/src/domain/provider.ts index 6235e4c2..96c0230b 100644 --- a/ui/src/domain/provider.ts +++ b/ui/src/domain/provider.ts @@ -195,6 +195,7 @@ export const DEPLOY_PROVIDERS = Object.freeze({ EDGIO_APPLICATIONS: `${ACCESS_PROVIDERS.EDGIO}-applications`, HUAWEICLOUD_CDN: `${ACCESS_PROVIDERS.HUAWEICLOUD}-cdn`, HUAWEICLOUD_ELB: `${ACCESS_PROVIDERS.HUAWEICLOUD}-elb`, + HUAWEICLOUD_WAF: `${ACCESS_PROVIDERS.HUAWEICLOUD}-waf`, KUBERNETES_SECRET: `${ACCESS_PROVIDERS.KUBERNETES}-secret`, LOCAL: `${ACCESS_PROVIDERS.LOCAL}`, QINIU_CDN: `${ACCESS_PROVIDERS.QINIU}-cdn`, @@ -270,6 +271,7 @@ export const deployProvidersMap: Maphttps://console-intl.huaweicloud.com/vpc/#/elb/list/grid", + "workflow_node.deploy.form.huaweicloud_waf_resource_type.label": "Resource type", + "workflow_node.deploy.form.huaweicloud_waf_resource_type.placeholder": "Please select resource type", + "workflow_node.deploy.form.huaweicloud_waf_resource_type.option.certificate.label": "WAF certificate", + "workflow_node.deploy.form.huaweicloud_waf_resource_type.option.cloudserver.label": "WAF cloud server", + "workflow_node.deploy.form.huaweicloud_waf_resource_type.option.premiumhost.label": "WAF premium host", + "workflow_node.deploy.form.huaweicloud_waf_region.label": "Huawei Cloud WAF region", + "workflow_node.deploy.form.huaweicloud_waf_region.placeholder": "Please enter Huawei Cloud WAF region (e.g. cn-north-1)", + "workflow_node.deploy.form.huaweicloud_waf_region.tooltip": "For more information, see https://console-intl.huaweicloud.com/apiexplorer/#/endpoint", + "workflow_node.deploy.form.huaweicloud_waf_certificate_id.label": "Huawei Cloud WAF certificate ID", + "workflow_node.deploy.form.huaweicloud_waf_certificate_id.placeholder": "Please enter Huawei Cloud WAF certificate ID", + "workflow_node.deploy.form.huaweicloud_waf_certificate_id.tooltip": "For more information, see https://console-intl.huaweicloud.com/console/#/waf/certificateManagement", + "workflow_node.deploy.form.huaweicloud_waf_domain.label": "Huawei Cloud WAF domain", + "workflow_node.deploy.form.huaweicloud_waf_domain.placeholder": "Please enter Huawei Cloud WAF domain name", + "workflow_node.deploy.form.huaweicloud_waf_domain.tooltip": "For more information, see https://console-intl.huaweicloud.com/console/#/waf/domain/list", "workflow_node.deploy.form.k8s_namespace.label": "Kubernetes Namespace", "workflow_node.deploy.form.k8s_namespace.placeholder": "Please enter Kubernetes Namespace", "workflow_node.deploy.form.k8s_namespace.tooltip": "For more information, see https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/", diff --git a/ui/src/i18n/locales/zh/nls.provider.json b/ui/src/i18n/locales/zh/nls.provider.json index 2cbc066f..4efd7cd8 100644 --- a/ui/src/i18n/locales/zh/nls.provider.json +++ b/ui/src/i18n/locales/zh/nls.provider.json @@ -50,6 +50,7 @@ "provider.huaweicloud.cdn": "华为云 - 内容分发网络 CDN", "provider.huaweicloud.dns": "华为云 - 云解析 DNS", "provider.huaweicloud.elb": "华为云 - 弹性负载均衡 ELB", + "provider.huaweicloud.waf": "华为云 - Web 应用防火墙 WAF", "provider.kubernetes": "Kubernetes", "provider.kubernetes.secret": "Kubernetes - Secret", "provider.local": "本地部署", diff --git a/ui/src/i18n/locales/zh/nls.workflow.nodes.json b/ui/src/i18n/locales/zh/nls.workflow.nodes.json index dd33be3b..594b7421 100644 --- a/ui/src/i18n/locales/zh/nls.workflow.nodes.json +++ b/ui/src/i18n/locales/zh/nls.workflow.nodes.json @@ -226,6 +226,20 @@ "workflow_node.deploy.form.huaweicloud_elb_listener_id.label": "华为云 ELB 监听器 ID", "workflow_node.deploy.form.huaweicloud_elb_listener_id.placeholder": "请输入华为云 ELB 监听器 ID", "workflow_node.deploy.form.huaweicloud_elb_listener_id.tooltip": "这是什么?请参阅 https://console.huaweicloud.com/vpc/#/elb/list/grid", + "workflow_node.deploy.form.huaweicloud_waf_resource_type.label": "证书替换方式", + "workflow_node.deploy.form.huaweicloud_waf_resource_type.placeholder": "请选择证书替换方式", + "workflow_node.deploy.form.huaweicloud_waf_resource_type.option.certificate.label": "替换指定证书", + "workflow_node.deploy.form.huaweicloud_waf_resource_type.option.cloudserver.label": "替换指定云模式防护网站的证书", + "workflow_node.deploy.form.huaweicloud_waf_resource_type.option.premiumhost.label": "替换指定独享模式防护网站的证书", + "workflow_node.deploy.form.huaweicloud_waf_region.label": "华为云 WAF 服务区域", + "workflow_node.deploy.form.huaweicloud_waf_region.placeholder": "请输入华为云 WAF 服务区域(例如:cn-north-1)", + "workflow_node.deploy.form.huaweicloud_waf_region.tooltip": "这是什么?请参阅 https://console.huaweicloud.com/apiexplorer/#/endpoint", + "workflow_node.deploy.form.huaweicloud_waf_certificate_id.label": "华为云 WAF 证书 ID", + "workflow_node.deploy.form.huaweicloud_waf_certificate_id.placeholder": "请输入华为云 WAF 证书 ID", + "workflow_node.deploy.form.huaweicloud_waf_certificate_id.tooltip": "这是什么?请参阅 https://console.huaweicloud.com/console/#/waf/certificateManagement", + "workflow_node.deploy.form.huaweicloud_waf_domain.label": "华为云 WAF 防护域名(支持泛域名)", + "workflow_node.deploy.form.huaweicloud_waf_domain.placeholder": "请输入华为云 WAF 防护域名", + "workflow_node.deploy.form.huaweicloud_waf_domain.tooltip": "这是什么?请参阅 https://console.huaweicloud.com/console/#/waf/domain/list", "workflow_node.deploy.form.k8s_namespace.label": "Kubernetes 命名空间", "workflow_node.deploy.form.k8s_namespace.placeholder": "请输入 Kubernetes 命名空间", "workflow_node.deploy.form.k8s_namespace.tooltip": "这是什么?请参阅 https://kubernetes.io/zh-cn/docs/concepts/overview/working-with-objects/namespaces/", From a40b078e9c66d7f3b11d64c5cdb0320891e1dab3 Mon Sep 17 00:00:00 2001 From: Fu Diwei Date: Mon, 17 Feb 2025 12:52:51 +0800 Subject: [PATCH 05/34] feat: add tencentcloud waf deployer --- README.md | 2 +- README_EN.md | 2 +- go.mod | 3 +- go.sum | 4 + internal/deployer/providers.go | 13 +- internal/domain/provider.go | 1 + .../tencentcloud-cos/tencentcloud_cos.go | 2 +- .../tencentcloud-cos/tencentcloud_cos_test.go | 2 +- .../tencentcloud-eo/tencentcloud_eo.go | 2 +- .../tencentcloud-eo/tencentcloud_eo_test.go | 2 +- .../tencentcloud-waf/tencentcloud_waf.go | 134 ++++++++++++++++++ .../tencentcloud-waf/tencentcloud_waf_test.go | 89 ++++++++++++ .../workflow/node/DeployNodeConfigForm.tsx | 3 + ...loyNodeConfigFormTencentCloudWAFConfig.tsx | 107 ++++++++++++++ ui/src/domain/provider.ts | 2 + ui/src/i18n/locales/en/nls.provider.json | 1 + .../i18n/locales/en/nls.workflow.nodes.json | 12 ++ ui/src/i18n/locales/zh/nls.provider.json | 1 + .../i18n/locales/zh/nls.workflow.nodes.json | 12 ++ 19 files changed, 386 insertions(+), 8 deletions(-) create mode 100644 internal/pkg/core/deployer/providers/tencentcloud-waf/tencentcloud_waf.go create mode 100644 internal/pkg/core/deployer/providers/tencentcloud-waf/tencentcloud_waf_test.go create mode 100644 ui/src/components/workflow/node/DeployNodeConfigFormTencentCloudWAFConfig.tsx diff --git a/README.md b/README.md index 3d826c0d..7b735cc7 100644 --- a/README.md +++ b/README.md @@ -123,7 +123,7 @@ make local.run | Webhook 回调 | 可部署到 Webhook | | [Kubernetes](https://kubernetes.io/) | 可部署到 Kubernetes Secret | | [阿里云](https://www.aliyun.com/) | 可部署到阿里云 OSS、CDN、DCDN、ESA、SLB(CLB/ALB/NLB)、WAF、Live 等服务 | -| [腾讯云](https://cloud.tencent.com/) | 可部署到腾讯云 COS、CDN、ECDN、EdgeOne、CLB、CSS 等服务 | +| [腾讯云](https://cloud.tencent.com/) | 可部署到腾讯云 COS、CDN、ECDN、EdgeOne、CLB、WAF、CSS 等服务 | | [百度智能云](https://cloud.baidu.com/) | 可部署到百度智能云 CDN 等服务 | | [华为云](https://www.huaweicloud.com/) | 可部署到华为云 CDN、ELB、WAF 等服务 | | [火山引擎](https://www.volcengine.com/) | 可部署到火山引擎 TOS、CDN、DCDN、CLB、ImageX、Live 等服务 | diff --git a/README_EN.md b/README_EN.md index 31713b7a..580cfd34 100644 --- a/README_EN.md +++ b/README_EN.md @@ -122,7 +122,7 @@ The following hosting providers are supported: | Webhook | Supports deployment to Webhook | | [Kubernetes](https://kubernetes.io/) | Supports deployment to Kubernetes Secret | | [Alibaba Cloud](https://www.alibabacloud.com/) | Supports deployment to Alibaba Cloud OSS, CDN, DCDN, SLB(CLB/ALB/NLB), WAF, Live | -| [Tencent Cloud](https://www.tencentcloud.com/) | Supports deployment to Tencent Cloud COS, CDN, ECDN, EdgeOne, CLB, CSS | +| [Tencent Cloud](https://www.tencentcloud.com/) | Supports deployment to Tencent Cloud COS, CDN, ECDN, EdgeOne, CLB, WAF, CSS | | [Baidu AI Cloud](https://intl.cloud.baidu.com/) | Supports deployment to Baidu AI CLoud CDN | | [Huawei Cloud](https://www.huaweicloud.com/) | Supports deployment to Huawei Cloud CDN, ELB, WAF | | [Volcengine](https://www.volcengine.com/) | Supports deployment to Volcengine TOS, CDN, DCDN, CLB, ImageX, Live | diff --git a/go.mod b/go.mod index 47cb6e33..52c05aea 100644 --- a/go.mod +++ b/go.mod @@ -34,7 +34,7 @@ require ( github.com/qiniu/go-sdk/v7 v7.25.2 github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cdn v1.0.1096 github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/clb v1.0.1096 - github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1096 + github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1099 github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/live v1.0.1096 github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/ssl v1.0.1096 github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/teo v1.0.1096 @@ -95,6 +95,7 @@ require ( github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect github.com/sirupsen/logrus v1.9.3 // indirect github.com/technoweenie/multipartstreamer v1.0.1 // indirect + github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/waf v1.0.1099 // indirect github.com/x448/float16 v0.8.4 // indirect go.mongodb.org/mongo-driver v1.17.2 // indirect gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect diff --git a/go.sum b/go.sum index 7f36a13b..a0cd77e9 100644 --- a/go.sum +++ b/go.sum @@ -829,6 +829,8 @@ github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/clb v1.0.1096/go.mod h1 github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1084/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0= github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1096 h1:DMokC7T0UF8wMfT1kD+mX3M+hc2C06gmFvQ9gsfRPmI= github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1096/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0= +github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1099 h1:4fQ53ORk6Eayw1H2kg43PoBnUuhGR6WRG6rtec/i3oI= +github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1099/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0= github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/dnspod v1.0.1084 h1:kwctN0WQYt8/iKP+iRCTCwdzEMIXsXklbRIib5rjeQ8= github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/dnspod v1.0.1084/go.mod h1:qE67ApiBzeRvzeDsV+GxyIDbVIDemsKpHXllQATz/Vw= github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/live v1.0.1096 h1:h9FP40Ycg45egJlZcjbLyc4IUeFoq+wSpR43sHMALtM= @@ -837,6 +839,8 @@ github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/ssl v1.0.1096 h1:7ZmPus github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/ssl v1.0.1096/go.mod h1:aMpGcDskqqhXtfMaeo2egO61tgh/zt07L1ohSPwmjWk= github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/teo v1.0.1096 h1:N62IFKL1ZRNQ7WPLNn8x9eYnwM4lOUIVY3buW6kbGtg= github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/teo v1.0.1096/go.mod h1:4PZRRpZp+jvYBUbUajsoZREnk7sJXMnPAiGB4IX8IkM= +github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/waf v1.0.1099 h1:kD+8RKF0uJCr7VaurAUA11NNAoln0HaagMCgQV6EnUw= +github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/waf v1.0.1099/go.mod h1:ellbjD8eHKHS4ixscLdiPJI8QoFIk0YNEgaDjxXMECM= github.com/tjfoc/gmsm v1.3.2/go.mod h1:HaUcFuY0auTiaHB9MHFGCPx5IaLhTUd2atbCFBQXn9w= github.com/tjfoc/gmsm v1.4.1 h1:aMe1GlZb+0bLjn+cKTPEvvn9oUEBlJitaZiiBwsbgho= github.com/tjfoc/gmsm v1.4.1/go.mod h1:j4INPkHWMrhJb38G+J6W4Tw0AbuN8Thu3PbdVYhVcTE= diff --git a/internal/deployer/providers.go b/internal/deployer/providers.go index 22d294c8..9b272815 100644 --- a/internal/deployer/providers.go +++ b/internal/deployer/providers.go @@ -38,6 +38,7 @@ import ( pTencentCloudECDN "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/tencentcloud-ecdn" pTencentCloudEO "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/tencentcloud-eo" pTencentCloudSSLDeploy "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/tencentcloud-ssl-deploy" + pTencentCloudWAF "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/tencentcloud-waf" pUCloudUCDN "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/ucloud-ucdn" pUCloudUS3 "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/ucloud-us3" pVolcEngineCDN "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/volcengine-cdn" @@ -432,7 +433,7 @@ func createDeployer(options *deployerOptions) (deployer.Deployer, logger.Logger, return deployer, logger, err } - case domain.DeployProviderTypeTencentCloudCDN, domain.DeployProviderTypeTencentCloudCLB, domain.DeployProviderTypeTencentCloudCOS, domain.DeployProviderTypeTencentCloudCSS, domain.DeployProviderTypeTencentCloudECDN, domain.DeployProviderTypeTencentCloudEO, domain.DeployProviderTypeTencentCloudSSLDeploy: + case domain.DeployProviderTypeTencentCloudCDN, domain.DeployProviderTypeTencentCloudCLB, domain.DeployProviderTypeTencentCloudCOS, domain.DeployProviderTypeTencentCloudCSS, domain.DeployProviderTypeTencentCloudECDN, domain.DeployProviderTypeTencentCloudEO, domain.DeployProviderTypeTencentCloudSSLDeploy, domain.DeployProviderTypeTencentCloudWAF: { access := domain.AccessConfigForTencentCloud{} if err := maps.Populate(options.ProviderAccessConfig, &access); err != nil { @@ -505,6 +506,16 @@ func createDeployer(options *deployerOptions) (deployer.Deployer, logger.Logger, }, logger) return deployer, logger, err + case domain.DeployProviderTypeTencentCloudWAF: + deployer, err := pTencentCloudWAF.NewWithLogger(&pTencentCloudWAF.TencentCloudWAFDeployerConfig{ + SecretId: access.SecretId, + SecretKey: access.SecretKey, + Domain: maps.GetValueAsString(options.ProviderDeployConfig, "domain"), + DomainId: maps.GetValueAsString(options.ProviderDeployConfig, "domainId"), + InstanceId: maps.GetValueAsString(options.ProviderDeployConfig, "instanceId"), + }, logger) + return deployer, logger, err + default: break } diff --git a/internal/domain/provider.go b/internal/domain/provider.go index 015e4f28..4b77b45d 100644 --- a/internal/domain/provider.go +++ b/internal/domain/provider.go @@ -127,6 +127,7 @@ const ( DeployProviderTypeTencentCloudECDN = DeployProviderType("tencentcloud-ecdn") DeployProviderTypeTencentCloudEO = DeployProviderType("tencentcloud-eo") DeployProviderTypeTencentCloudSSLDeploy = DeployProviderType("tencentcloud-ssldeploy") + DeployProviderTypeTencentCloudWAF = DeployProviderType("tencentcloud-waf") DeployProviderTypeUCloudUCDN = DeployProviderType("ucloud-ucdn") DeployProviderTypeUCloudUS3 = DeployProviderType("ucloud-us3") DeployProviderTypeVolcEngineCDN = DeployProviderType("volcengine-cdn") diff --git a/internal/pkg/core/deployer/providers/tencentcloud-cos/tencentcloud_cos.go b/internal/pkg/core/deployer/providers/tencentcloud-cos/tencentcloud_cos.go index c2af84fb..ca20b9dc 100644 --- a/internal/pkg/core/deployer/providers/tencentcloud-cos/tencentcloud_cos.go +++ b/internal/pkg/core/deployer/providers/tencentcloud-cos/tencentcloud_cos.go @@ -1,4 +1,4 @@ -package tencentcloudcdn +package tencentcloudcos import ( "context" diff --git a/internal/pkg/core/deployer/providers/tencentcloud-cos/tencentcloud_cos_test.go b/internal/pkg/core/deployer/providers/tencentcloud-cos/tencentcloud_cos_test.go index d58e4f50..ee035ed8 100644 --- a/internal/pkg/core/deployer/providers/tencentcloud-cos/tencentcloud_cos_test.go +++ b/internal/pkg/core/deployer/providers/tencentcloud-cos/tencentcloud_cos_test.go @@ -1,4 +1,4 @@ -package tencentcloudcdn_test +package tencentcloudcos_test import ( "context" diff --git a/internal/pkg/core/deployer/providers/tencentcloud-eo/tencentcloud_eo.go b/internal/pkg/core/deployer/providers/tencentcloud-eo/tencentcloud_eo.go index 2de4dcc5..b0857f87 100644 --- a/internal/pkg/core/deployer/providers/tencentcloud-eo/tencentcloud_eo.go +++ b/internal/pkg/core/deployer/providers/tencentcloud-eo/tencentcloud_eo.go @@ -1,4 +1,4 @@ -package tencentcloudeteo +package tencentcloudeo import ( "context" diff --git a/internal/pkg/core/deployer/providers/tencentcloud-eo/tencentcloud_eo_test.go b/internal/pkg/core/deployer/providers/tencentcloud-eo/tencentcloud_eo_test.go index bc5280f7..0e280a91 100644 --- a/internal/pkg/core/deployer/providers/tencentcloud-eo/tencentcloud_eo_test.go +++ b/internal/pkg/core/deployer/providers/tencentcloud-eo/tencentcloud_eo_test.go @@ -1,4 +1,4 @@ -package tencentcloudeteo_test +package tencentcloudeo_test import ( "context" diff --git a/internal/pkg/core/deployer/providers/tencentcloud-waf/tencentcloud_waf.go b/internal/pkg/core/deployer/providers/tencentcloud-waf/tencentcloud_waf.go new file mode 100644 index 00000000..df54beef --- /dev/null +++ b/internal/pkg/core/deployer/providers/tencentcloud-waf/tencentcloud_waf.go @@ -0,0 +1,134 @@ +package tencentcloudwaf + +import ( + "context" + "errors" + + xerrors "github.com/pkg/errors" + "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common" + "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common/profile" + tcWaf "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/waf/v20180125" + + "github.com/usual2970/certimate/internal/pkg/core/deployer" + "github.com/usual2970/certimate/internal/pkg/core/logger" + "github.com/usual2970/certimate/internal/pkg/core/uploader" + uploaderp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/tencentcloud-ssl" +) + +type TencentCloudWAFDeployerConfig struct { + // 腾讯云 SecretId。 + SecretId string `json:"secretId"` + // 腾讯云 SecretKey。 + SecretKey string `json:"secretKey"` + // 腾讯云地域。 + Region string `json:"region"` + // 防护域名(不支持泛域名)。 + Domain string `json:"domain"` + // 防护域名 ID。 + DomainId string `json:"domainId"` + // 防护域名所属实例 ID。 + InstanceId string `json:"instanceId"` +} + +type TencentCloudWAFDeployer struct { + config *TencentCloudWAFDeployerConfig + logger logger.Logger + sdkClient *tcWaf.Client + sslUploader uploader.Uploader +} + +var _ deployer.Deployer = (*TencentCloudWAFDeployer)(nil) + +func New(config *TencentCloudWAFDeployerConfig) (*TencentCloudWAFDeployer, error) { + return NewWithLogger(config, logger.NewNilLogger()) +} + +func NewWithLogger(config *TencentCloudWAFDeployerConfig, logger logger.Logger) (*TencentCloudWAFDeployer, error) { + if config == nil { + return nil, errors.New("config is nil") + } + + if logger == nil { + return nil, errors.New("logger is nil") + } + + client, err := createSdkClient(config.SecretId, config.SecretKey, config.Region) + if err != nil { + return nil, xerrors.Wrap(err, "failed to create sdk clients") + } + + uploader, err := uploaderp.New(&uploaderp.TencentCloudSSLUploaderConfig{ + SecretId: config.SecretId, + SecretKey: config.SecretKey, + }) + if err != nil { + return nil, xerrors.Wrap(err, "failed to create ssl uploader") + } + + return &TencentCloudWAFDeployer{ + logger: logger, + config: config, + sdkClient: client, + sslUploader: uploader, + }, nil +} + +func (d *TencentCloudWAFDeployer) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { + if d.config.Domain == "" { + return nil, errors.New("config `domain` is required") + } + if d.config.DomainId == "" { + return nil, errors.New("config `domainId` is required") + } + if d.config.InstanceId == "" { + return nil, errors.New("config `instanceId` is required") + } + + // 上传证书到 SSL + upres, err := d.sslUploader.Upload(ctx, certPem, privkeyPem) + if err != nil { + return nil, xerrors.Wrap(err, "failed to upload certificate file") + } else { + d.logger.Logt("certificate file uploaded", upres) + } + + // 查询单个 SaaS 型 WAF 域名详情 + // REF: https://cloud.tencent.com/document/api/627/82938 + describeDomainDetailsSaasReq := tcWaf.NewDescribeDomainDetailsSaasRequest() + describeDomainDetailsSaasReq.Domain = common.StringPtr(d.config.Domain) + describeDomainDetailsSaasReq.DomainId = common.StringPtr(d.config.DomainId) + describeDomainDetailsSaasReq.InstanceId = common.StringPtr(d.config.InstanceId) + describeDomainDetailsSaasResp, err := d.sdkClient.DescribeDomainDetailsSaas(describeDomainDetailsSaasReq) + if err != nil { + return nil, xerrors.Wrap(err, "failed to execute sdk request 'waf.DescribeDomainDetailsSaas'") + } else { + d.logger.Logt("已查询到 SaaS 型 WAF 域名详情", describeDomainDetailsSaasResp.Response) + } + + // 编辑 SaaS 型 WAF 域名 + // REF: https://cloud.tencent.com/document/api/627/94309 + modifySpartaProtectionReq := tcWaf.NewModifySpartaProtectionRequest() + modifySpartaProtectionReq.Domain = common.StringPtr(d.config.Domain) + modifySpartaProtectionReq.DomainId = common.StringPtr(d.config.DomainId) + modifySpartaProtectionReq.InstanceID = common.StringPtr(d.config.InstanceId) + modifySpartaProtectionReq.CertType = common.Int64Ptr(2) + modifySpartaProtectionReq.SSLId = common.StringPtr(upres.CertId) + modifySpartaProtectionResp, err := d.sdkClient.ModifySpartaProtection(modifySpartaProtectionReq) + if err != nil { + return nil, xerrors.Wrap(err, "failed to execute sdk request 'waf.ModifySpartaProtection'") + } else { + d.logger.Logt("已编辑 SaaS 型 WAF 域名", modifySpartaProtectionResp.Response) + } + + return &deployer.DeployResult{}, nil +} + +func createSdkClient(secretId, secretKey, region string) (*tcWaf.Client, error) { + credential := common.NewCredential(secretId, secretKey) + client, err := tcWaf.NewClient(credential, region, profile.NewClientProfile()) + if err != nil { + return nil, err + } + + return client, nil +} diff --git a/internal/pkg/core/deployer/providers/tencentcloud-waf/tencentcloud_waf_test.go b/internal/pkg/core/deployer/providers/tencentcloud-waf/tencentcloud_waf_test.go new file mode 100644 index 00000000..98ee2d49 --- /dev/null +++ b/internal/pkg/core/deployer/providers/tencentcloud-waf/tencentcloud_waf_test.go @@ -0,0 +1,89 @@ +package tencentcloudwaf_test + +import ( + "context" + "flag" + "fmt" + "os" + "strings" + "testing" + + provider "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/tencentcloud-waf" +) + +var ( + fInputCertPath string + fInputKeyPath string + fSecretId string + fSecretKey string + fRegion string + fDomain string + fDomainId string + fInstanceId string +) + +func init() { + argsPrefix := "CERTIMATE_DEPLOYER_TENCENTCLOUDWAF_" + + flag.StringVar(&fInputCertPath, argsPrefix+"INPUTCERTPATH", "", "") + flag.StringVar(&fInputKeyPath, argsPrefix+"INPUTKEYPATH", "", "") + flag.StringVar(&fSecretId, argsPrefix+"SECRETID", "", "") + flag.StringVar(&fSecretKey, argsPrefix+"SECRETKEY", "", "") + flag.StringVar(&fRegion, argsPrefix+"REGION", "", "") + flag.StringVar(&fDomain, argsPrefix+"DOMAIN", "", "") + flag.StringVar(&fDomainId, argsPrefix+"DOMAINID", "", "") + flag.StringVar(&fInstanceId, argsPrefix+"INSTANCEID", "", "") +} + +/* +Shell command to run this test: + + go test -v ./tencentcloud_waf_test.go -args \ + --CERTIMATE_DEPLOYER_TENCENTCLOUDWAF_INPUTCERTPATH="/path/to/your-input-cert.pem" \ + --CERTIMATE_DEPLOYER_TENCENTCLOUDWAF_INPUTKEYPATH="/path/to/your-input-key.pem" \ + --CERTIMATE_DEPLOYER_TENCENTCLOUDWAF_SECRETID="your-secret-id" \ + --CERTIMATE_DEPLOYER_TENCENTCLOUDWAF_SECRETKEY="your-secret-key" \ + --CERTIMATE_DEPLOYER_TENCENTCLOUDWAF_REGION="ap-guangzhou" \ + --CERTIMATE_DEPLOYER_TENCENTCLOUDWAF_DOMAIN="example.com" \ + --CERTIMATE_DEPLOYER_TENCENTCLOUDWAF_DOMAINID="your-domain-id" \ + --CERTIMATE_DEPLOYER_TENCENTCLOUDWAF_INSTANCEID="your-instance-id" +*/ +func TestDeploy(t *testing.T) { + flag.Parse() + + t.Run("Deploy", func(t *testing.T) { + t.Log(strings.Join([]string{ + "args:", + fmt.Sprintf("INPUTCERTPATH: %v", fInputCertPath), + fmt.Sprintf("INPUTKEYPATH: %v", fInputKeyPath), + fmt.Sprintf("SECRETID: %v", fSecretId), + fmt.Sprintf("SECRETKEY: %v", fSecretKey), + fmt.Sprintf("REGION: %v", fRegion), + fmt.Sprintf("DOMAIN: %v", fDomain), + fmt.Sprintf("INSTANCEID: %v", fInstanceId), + }, "\n")) + + deployer, err := provider.New(&provider.TencentCloudWAFDeployerConfig{ + SecretId: fSecretId, + SecretKey: fSecretKey, + Region: fRegion, + Domain: fDomain, + DomainId: fDomainId, + InstanceId: fInstanceId, + }) + if err != nil { + t.Errorf("err: %+v", err) + return + } + + fInputCertData, _ := os.ReadFile(fInputCertPath) + fInputKeyData, _ := os.ReadFile(fInputKeyPath) + res, err := deployer.Deploy(context.Background(), string(fInputCertData), string(fInputKeyData)) + if err != nil { + t.Errorf("err: %+v", err) + return + } + + t.Logf("ok: %v", res) + }) +} diff --git a/ui/src/components/workflow/node/DeployNodeConfigForm.tsx b/ui/src/components/workflow/node/DeployNodeConfigForm.tsx index 93cf857e..fcf85a88 100644 --- a/ui/src/components/workflow/node/DeployNodeConfigForm.tsx +++ b/ui/src/components/workflow/node/DeployNodeConfigForm.tsx @@ -47,6 +47,7 @@ import DeployNodeConfigFormTencentCloudCSSConfig from "./DeployNodeConfigFormTen import DeployNodeConfigFormTencentCloudECDNConfig from "./DeployNodeConfigFormTencentCloudECDNConfig.tsx"; import DeployNodeConfigFormTencentCloudEOConfig from "./DeployNodeConfigFormTencentCloudEOConfig.tsx"; import DeployNodeConfigFormTencentCloudSSLDeployConfig from "./DeployNodeConfigFormTencentCloudSSLDeployConfig"; +import DeployNodeConfigFormTencentCloudWAFConfig from "./DeployNodeConfigFormTencentCloudWAFConfig"; import DeployNodeConfigFormUCloudUCDNConfig from "./DeployNodeConfigFormUCloudUCDNConfig.tsx"; import DeployNodeConfigFormUCloudUS3Config from "./DeployNodeConfigFormUCloudUS3Config.tsx"; import DeployNodeConfigFormVolcEngineCDNConfig from "./DeployNodeConfigFormVolcEngineCDNConfig.tsx"; @@ -192,6 +193,8 @@ const DeployNodeConfigForm = forwardRef; case DEPLOY_PROVIDERS.TENCENTCLOUD_SSL_DEPLOY: return ; + case DEPLOY_PROVIDERS.TENCENTCLOUD_WAF: + return ; case DEPLOY_PROVIDERS.UCLOUD_UCDN: return ; case DEPLOY_PROVIDERS.UCLOUD_US3: diff --git a/ui/src/components/workflow/node/DeployNodeConfigFormTencentCloudWAFConfig.tsx b/ui/src/components/workflow/node/DeployNodeConfigFormTencentCloudWAFConfig.tsx new file mode 100644 index 00000000..347ebaa2 --- /dev/null +++ b/ui/src/components/workflow/node/DeployNodeConfigFormTencentCloudWAFConfig.tsx @@ -0,0 +1,107 @@ +import { useTranslation } from "react-i18next"; +import { Form, type FormInstance, Input } from "antd"; +import { createSchemaFieldRule } from "antd-zod"; +import { z } from "zod"; + +import { validDomainName } from "@/utils/validators"; + +type DeployNodeConfigFormTencentCloudWAFConfigFieldValues = Nullish<{ + region: string; + domain: string; + domainId: string; + instanceId: string; +}>; + +export type DeployNodeConfigFormTencentCloudWAFConfigProps = { + form: FormInstance; + formName: string; + disabled?: boolean; + initialValues?: DeployNodeConfigFormTencentCloudWAFConfigFieldValues; + onValuesChange?: (values: DeployNodeConfigFormTencentCloudWAFConfigFieldValues) => void; +}; + +const initFormModel = (): DeployNodeConfigFormTencentCloudWAFConfigFieldValues => { + return {}; +}; + +const DeployNodeConfigFormTencentCloudWAFConfig = ({ + form: formInst, + formName, + disabled, + initialValues, + onValuesChange, +}: DeployNodeConfigFormTencentCloudWAFConfigProps) => { + const { t } = useTranslation(); + + const formSchema = z.object({ + region: z + .string({ message: t("workflow_node.deploy.form.tencentcloud_waf_region.placeholder") }) + .nonempty(t("workflow_node.deploy.form.tencentcloud_waf_region.placeholder")) + .trim(), + domain: z + .string({ message: t("workflow_node.deploy.form.tencentcloud_waf_domain.placeholder") }) + .refine((v) => validDomainName(v), t("common.errmsg.domain_invalid")), + domainId: z + .string({ message: t("workflow_node.deploy.form.tencentcloud_waf_domain_id.placeholder") }) + .nonempty(t("workflow_node.deploy.form.tencentcloud_waf_domain_id.placeholder")) + .trim(), + instanceId: z + .string({ message: t("workflow_node.deploy.form.tencentcloud_waf_instance_id.placeholder") }) + .nonempty(t("workflow_node.deploy.form.tencentcloud_waf_instance_id.placeholder")) + .trim(), + }); + const formRule = createSchemaFieldRule(formSchema); + + const handleFormChange = (_: unknown, values: z.infer) => { + onValuesChange?.(values); + }; + + return ( +
+ } + > + + + + } + > + + + + } + > + + + + } + > + + +
+ ); +}; + +export default DeployNodeConfigFormTencentCloudWAFConfig; diff --git a/ui/src/domain/provider.ts b/ui/src/domain/provider.ts index 96c0230b..96b69a85 100644 --- a/ui/src/domain/provider.ts +++ b/ui/src/domain/provider.ts @@ -208,6 +208,7 @@ export const DEPLOY_PROVIDERS = Object.freeze({ TENCENTCLOUD_ECDN: `${ACCESS_PROVIDERS.TENCENTCLOUD}-ecdn`, TENCENTCLOUD_EO: `${ACCESS_PROVIDERS.TENCENTCLOUD}-eo`, TENCENTCLOUD_SSL_DEPLOY: `${ACCESS_PROVIDERS.TENCENTCLOUD}-ssldeploy`, + TENCENTCLOUD_WAF: `${ACCESS_PROVIDERS.TENCENTCLOUD}-waf`, UCLOUD_UCDN: `${ACCESS_PROVIDERS.UCLOUD}-ucdn`, UCLOUD_US3: `${ACCESS_PROVIDERS.UCLOUD}-us3`, VOLCENGINE_CDN: `${ACCESS_PROVIDERS.VOLCENGINE}-cdn`, @@ -267,6 +268,7 @@ export const deployProvidersMap: Maphttps://cloud.tencent.com.cn/document/product/400/91667", "workflow_node.deploy.form.tencentcloud_ssl_deploy_resource_ids.multiple_input_modal.title": "Change Tencent Cloud resource IDs", "workflow_node.deploy.form.tencentcloud_ssl_deploy_resource_ids.multiple_input_modal.placeholder": "Please enter Tencent Cloud resouce ID", + "workflow_node.deploy.form.tencentcloud_waf_region.label": "Tencent Cloud WAF region", + "workflow_node.deploy.form.tencentcloud_waf_region.placeholder": "Please enter Tencent Cloud WAF region (e.g. ap-guangzhou)", + "workflow_node.deploy.form.tencentcloud_waf_region.tooltip": "For more information, see https://www.tencentcloud.com/document/product/627/38085", + "workflow_node.deploy.form.tencentcloud_waf_domain.label": "Tencent Cloud WAF domain", + "workflow_node.deploy.form.tencentcloud_waf_domain.placeholder": "Please enter Tencent Cloud WAF domain name", + "workflow_node.deploy.form.tencentcloud_waf_domain.tooltip": "For more information, see https://console.tencentcloud.com/waf", + "workflow_node.deploy.form.tencentcloud_waf_domain_id.label": "Tencent Cloud WAF domain ID", + "workflow_node.deploy.form.tencentcloud_waf_domain_id.placeholder": "Please enter Tencent Cloud WAF domain ID", + "workflow_node.deploy.form.tencentcloud_waf_domain_id.tooltip": "For more information, see https://console.tencentcloud.com/waf", + "workflow_node.deploy.form.tencentcloud_waf_instance_id.label": "Tencent Cloud WAF instance ID", + "workflow_node.deploy.form.tencentcloud_waf_instance_id.placeholder": "Please enter Tencent Cloud WAF instance ID", + "workflow_node.deploy.form.tencentcloud_waf_instance_id.tooltip": "For more information, see https://console.tencentcloud.com/waf", "workflow_node.deploy.form.ucloud_ucdn_domain_id.label": "UCloud UCDN domain ID", "workflow_node.deploy.form.ucloud_ucdn_domain_id.placeholder": "Please enter UCloud UCDN domain ID", "workflow_node.deploy.form.ucloud_ucdn_domain_id.tooltip": "For more information, see https://console.ucloud-global.com/ucdn", diff --git a/ui/src/i18n/locales/zh/nls.provider.json b/ui/src/i18n/locales/zh/nls.provider.json index 4efd7cd8..ec9f3241 100644 --- a/ui/src/i18n/locales/zh/nls.provider.json +++ b/ui/src/i18n/locales/zh/nls.provider.json @@ -73,6 +73,7 @@ "provider.tencentcloud.ecdn": "腾讯云 - 全站加速网络 ECDN", "provider.tencentcloud.eo": "腾讯云 - 边缘安全加速平台 EdgeOne", "provider.tencentcloud.ssl_deploy": "腾讯云 - 通过 SSL 证书服务创建部署任务", + "provider.tencentcloud.waf": "腾讯云 - Web 应用防火墙 WAF", "provider.ucloud": "优刻得", "provider.ucloud.ucdn": "优刻得 - 内容分发 UCDN", "provider.ucloud.us3": "优刻得 - 对象存储 US3", diff --git a/ui/src/i18n/locales/zh/nls.workflow.nodes.json b/ui/src/i18n/locales/zh/nls.workflow.nodes.json index 594b7421..f0c07485 100644 --- a/ui/src/i18n/locales/zh/nls.workflow.nodes.json +++ b/ui/src/i18n/locales/zh/nls.workflow.nodes.json @@ -391,6 +391,18 @@ "workflow_node.deploy.form.tencentcloud_ssl_deploy_resource_ids.tooltip": "这是什么?请参阅 https://cloud.tencent.com.cn/document/product/400/91667

注意与各产品本身的实例 ID 区分。", "workflow_node.deploy.form.tencentcloud_ssl_deploy_resource_ids.multiple_input_modal.title": "修改腾讯云云产品资源 ID", "workflow_node.deploy.form.tencentcloud_ssl_deploy_resource_ids.multiple_input_modal.placeholder": "请输入腾讯云云产品资源 ID", + "workflow_node.deploy.form.tencentcloud_waf_region.label": "腾讯云 WAF 产品地域", + "workflow_node.deploy.form.tencentcloud_waf_region.placeholder": "请输入腾讯云 WAF 产品地域(例如:ap-guangzhou)", + "workflow_node.deploy.form.tencentcloud_waf_region.tooltip": "这是什么?请参阅 https://cloud.tencent.com/document/product/627/47525", + "workflow_node.deploy.form.tencentcloud_waf_domain.label": "腾讯云 WAF 防护域名", + "workflow_node.deploy.form.tencentcloud_waf_domain.placeholder": "请输入腾讯云 WAF 防护域名", + "workflow_node.deploy.form.tencentcloud_waf_domain.tooltip": "这是什么?请参阅 see https://console.cloud.tencent.com/waf", + "workflow_node.deploy.form.tencentcloud_waf_domain_id.label": "腾讯云 WAF 域名 ID", + "workflow_node.deploy.form.tencentcloud_waf_domain_id.placeholder": "请输入腾讯云 WAF 域名 ID", + "workflow_node.deploy.form.tencentcloud_waf_domain_id.tooltip": "这是什么?请参阅 https://console.cloud.tencent.com/waf", + "workflow_node.deploy.form.tencentcloud_waf_instance_id.label": "腾讯云 WAF 实例 ID", + "workflow_node.deploy.form.tencentcloud_waf_instance_id.placeholder": "请输入腾讯云 WAF 实例 ID", + "workflow_node.deploy.form.tencentcloud_waf_instance_id.tooltip": "这是什么?请参阅 https://console.cloud.tencent.com/waf", "workflow_node.deploy.form.ucloud_ucdn_domain_id.label": "优刻得 UCDN 域名 ID", "workflow_node.deploy.form.ucloud_ucdn_domain_id.placeholder": "请输入优刻得 UCDN 域名 ID", "workflow_node.deploy.form.ucloud_ucdn_domain_id.tooltip": "这是什么?请参阅 https://console.ucloud.cn/ucdn", From c72dc0d2c40530cffa906aa9c00c4ee2ff3f28fa Mon Sep 17 00:00:00 2001 From: Fu Diwei Date: Mon, 17 Feb 2025 16:48:33 +0800 Subject: [PATCH 06/34] feat: add safeline deployer --- README.md | 1 + README_EN.md | 3 +- internal/deployer/providers.go | 23 +++- internal/domain/access.go | 5 + internal/domain/provider.go | 3 +- .../huaweicloud-waf/huaweicloud_waf.go | 4 +- .../deployer/providers/safeline/consts.go | 8 ++ .../deployer/providers/safeline/safeline.go | 102 ++++++++++++++++++ .../providers/safeline/safeline_test.go | 76 +++++++++++++ internal/pkg/vendors/btpanel-sdk/client.go | 8 +- internal/pkg/vendors/gname-sdk/api.go | 59 ++++------ internal/pkg/vendors/gname-sdk/client.go | 12 +-- internal/pkg/vendors/safeline-sdk/api.go | 34 ++++++ internal/pkg/vendors/safeline-sdk/client.go | 87 +++++++++++++++ ui/public/imgs/providers/safeline.svg | 1 + ui/src/components/access/AccessForm.tsx | 3 + .../access/AccessFormBaotaPanelConfig.tsx | 2 +- .../access/AccessFormPowerDNSConfig.tsx | 2 +- .../access/AccessFormSafeLineConfig.tsx | 72 +++++++++++++ .../provider/AccessProviderSelect.tsx | 12 ++- .../provider/ApplyDNSProviderSelect.tsx | 12 ++- .../provider/DeployProviderSelect.tsx | 12 ++- .../workflow/node/DeployNodeConfigForm.tsx | 5 +- .../DeployNodeConfigFormSafeLineConfig.tsx | 85 +++++++++++++++ ui/src/domain/access.ts | 6 ++ ui/src/domain/provider.ts | 4 + ui/src/i18n/locales/en/nls.access.json | 6 ++ .../i18n/locales/en/nls.workflow.nodes.json | 5 + ui/src/i18n/locales/zh/nls.access.json | 6 ++ .../i18n/locales/zh/nls.workflow.nodes.json | 5 + 30 files changed, 586 insertions(+), 77 deletions(-) create mode 100644 internal/pkg/core/deployer/providers/safeline/consts.go create mode 100644 internal/pkg/core/deployer/providers/safeline/safeline.go create mode 100644 internal/pkg/core/deployer/providers/safeline/safeline_test.go create mode 100644 internal/pkg/vendors/safeline-sdk/api.go create mode 100644 internal/pkg/vendors/safeline-sdk/client.go create mode 100644 ui/public/imgs/providers/safeline.svg create mode 100644 ui/src/components/access/AccessFormSafeLineConfig.tsx create mode 100644 ui/src/components/workflow/node/DeployNodeConfigFormSafeLineConfig.tsx diff --git a/README.md b/README.md index 7b735cc7..24f2859d 100644 --- a/README.md +++ b/README.md @@ -130,6 +130,7 @@ make local.run | [七牛云](https://www.qiniu.com/) | 可部署到七牛云 CDN、直播云等服务 | | [多吉云](https://www.dogecloud.com/) | 可部署到多吉云 CDN | | [优刻得](https://www.ucloud.cn/) | 可部署到优刻得 US3、UCDN 等服务 | +| [雷池](https://waf-ce.chaitin.cn/) | 可部署到雷池 WAF | | [宝塔面板](https://www.bt.cn/) | 可部署到宝塔面板 | | [AWS](https://aws.amazon.com/) | 可部署到 AWS CloudFront 等服务 | | [BytePlus](https://www.byteplus.com/) | 可部署到 BytePlus CDN 等服务 | diff --git a/README_EN.md b/README_EN.md index 580cfd34..dcb69efd 100644 --- a/README_EN.md +++ b/README_EN.md @@ -128,8 +128,9 @@ The following hosting providers are supported: | [Volcengine](https://www.volcengine.com/) | Supports deployment to Volcengine TOS, CDN, DCDN, CLB, ImageX, Live | | [Qiniu Cloud](https://www.qiniu.com/) | Supports deployment to Qiniu Cloud CDN, Pili | | [Doge Cloud](https://www.dogecloud.com/) | Supports deployment to Doge Cloud CDN | -| [BaoTa Panel](https://www.bt.cn/) | Supports deployment to BaoTa Panel sites | | [UCloud](https://www.ucloud-global.com/) | Supports deployment to UCloud US3, UCDN | +| [SafeLine](https://waf.chaitin.com/) | Supports deployment to SafeLine WAF | +| [BaoTa Panel](https://www.bt.cn/) | Supports deployment to BaoTa Panel sites | | [AWS](https://aws.amazon.com/) | Supports deployment to AWS CloudFront | | [BytePlus](https://www.byteplus.com/) | Supports deployment to BytePlus CDN | | [Edgio](https://edg.io/) | Supports deployment to Edgio Applications | diff --git a/internal/deployer/providers.go b/internal/deployer/providers.go index 9b272815..4c6acc22 100644 --- a/internal/deployer/providers.go +++ b/internal/deployer/providers.go @@ -30,7 +30,8 @@ import ( pLocal "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/local" pQiniuCDN "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/qiniu-cdn" pQiniuPili "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/qiniu-pili" - providerSSH "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/ssh" + pSafeLine "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/safeline" + pSSH "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/ssh" pTencentCloudCDN "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/tencentcloud-cdn" pTencentCloudCLB "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/tencentcloud-clb" pTencentCloudCOS "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/tencentcloud-cos" @@ -405,6 +406,22 @@ func createDeployer(options *deployerOptions) (deployer.Deployer, logger.Logger, } } + case domain.DeployProviderTypeSafeLine: + { + access := domain.AccessConfigForSafeLine{} + if err := maps.Populate(options.ProviderAccessConfig, &access); err != nil { + return nil, nil, fmt.Errorf("failed to populate provider access config: %w", err) + } + + deployer, err := pSafeLine.NewWithLogger(&pSafeLine.SafeLineDeployerConfig{ + ApiUrl: access.ApiUrl, + ApiToken: access.ApiToken, + ResourceType: pSafeLine.ResourceType(maps.GetValueAsString(options.ProviderDeployConfig, "resourceType")), + CertificateId: maps.GetValueAsInt32(options.ProviderDeployConfig, "certificateId"), + }, logger) + return deployer, logger, err + } + case domain.DeployProviderTypeSSH: { access := domain.AccessConfigForSSH{} @@ -412,7 +429,7 @@ func createDeployer(options *deployerOptions) (deployer.Deployer, logger.Logger, return nil, nil, fmt.Errorf("failed to populate provider access config: %w", err) } - deployer, err := providerSSH.NewWithLogger(&providerSSH.SshDeployerConfig{ + deployer, err := pSSH.NewWithLogger(&pSSH.SshDeployerConfig{ SshHost: access.Host, SshPort: access.Port, SshUsername: access.Username, @@ -422,7 +439,7 @@ func createDeployer(options *deployerOptions) (deployer.Deployer, logger.Logger, UseSCP: maps.GetValueAsBool(options.ProviderDeployConfig, "useSCP"), PreCommand: maps.GetValueAsString(options.ProviderDeployConfig, "preCommand"), PostCommand: maps.GetValueAsString(options.ProviderDeployConfig, "postCommand"), - OutputFormat: providerSSH.OutputFormatType(maps.GetValueOrDefaultAsString(options.ProviderDeployConfig, "format", string(providerSSH.OUTPUT_FORMAT_PEM))), + OutputFormat: pSSH.OutputFormatType(maps.GetValueOrDefaultAsString(options.ProviderDeployConfig, "format", string(pSSH.OUTPUT_FORMAT_PEM))), OutputCertPath: maps.GetValueAsString(options.ProviderDeployConfig, "certPath"), OutputKeyPath: maps.GetValueAsString(options.ProviderDeployConfig, "keyPath"), PfxPassword: maps.GetValueAsString(options.ProviderDeployConfig, "pfxPassword"), diff --git a/internal/domain/access.go b/internal/domain/access.go index e9df61d2..ec2e093e 100644 --- a/internal/domain/access.go +++ b/internal/domain/access.go @@ -130,6 +130,11 @@ type AccessConfigForRainYun struct { ApiKey string `json:"apiKey"` } +type AccessConfigForSafeLine struct { + ApiUrl string `json:"apiUrl"` + ApiToken string `json:"apiToken"` +} + type AccessConfigForSSH struct { Host string `json:"host"` Port int32 `json:"port"` diff --git a/internal/domain/provider.go b/internal/domain/provider.go index 4b77b45d..08ee9836 100644 --- a/internal/domain/provider.go +++ b/internal/domain/provider.go @@ -42,7 +42,7 @@ const ( AccessProviderTypePowerDNS = AccessProviderType("powerdns") AccessProviderTypeQiniu = AccessProviderType("qiniu") AccessProviderTypeRainYun = AccessProviderType("rainyun") - AccessProviderTypeSafeLine = AccessProviderType("safeline") // 雷池(预留) + AccessProviderTypeSafeLine = AccessProviderType("safeline") AccessProviderTypeSSH = AccessProviderType("ssh") AccessProviderTypeTencentCloud = AccessProviderType("tencentcloud") AccessProviderTypeUCloud = AccessProviderType("ucloud") @@ -119,6 +119,7 @@ const ( DeployProviderTypeLocal = DeployProviderType("local") DeployProviderTypeQiniuCDN = DeployProviderType("qiniu-cdn") DeployProviderTypeQiniuPili = DeployProviderType("qiniu-pili") + DeployProviderTypeSafeLine = DeployProviderType("safeline") DeployProviderTypeSSH = DeployProviderType("ssh") DeployProviderTypeTencentCloudCDN = DeployProviderType("tencentcloud-cdn") DeployProviderTypeTencentCloudCLB = DeployProviderType("tencentcloud-clb") diff --git a/internal/pkg/core/deployer/providers/huaweicloud-waf/huaweicloud_waf.go b/internal/pkg/core/deployer/providers/huaweicloud-waf/huaweicloud_waf.go index 80ac4fe6..8c0ff029 100644 --- a/internal/pkg/core/deployer/providers/huaweicloud-waf/huaweicloud_waf.go +++ b/internal/pkg/core/deployer/providers/huaweicloud-waf/huaweicloud_waf.go @@ -89,10 +89,10 @@ func (d *HuaweiCloudWAFDeployer) Deploy(ctx context.Context, certPem string, pri upres, err := d.sslUploader.Upload(ctx, certPem, privkeyPem) if err != nil { return nil, xerrors.Wrap(err, "failed to upload certificate file") + } else { + d.logger.Logt("certificate file uploaded", upres) } - d.logger.Logt("certificate file uploaded", upres) - // 根据部署资源类型决定部署方式 switch d.config.ResourceType { case RESOURCE_TYPE_CERTIFICATE: diff --git a/internal/pkg/core/deployer/providers/safeline/consts.go b/internal/pkg/core/deployer/providers/safeline/consts.go new file mode 100644 index 00000000..a19e3866 --- /dev/null +++ b/internal/pkg/core/deployer/providers/safeline/consts.go @@ -0,0 +1,8 @@ +package safeline + +type ResourceType string + +const ( + // 资源类型:替换指定证书。 + RESOURCE_TYPE_CERTIFICATE = ResourceType("certificate") +) diff --git a/internal/pkg/core/deployer/providers/safeline/safeline.go b/internal/pkg/core/deployer/providers/safeline/safeline.go new file mode 100644 index 00000000..b759981a --- /dev/null +++ b/internal/pkg/core/deployer/providers/safeline/safeline.go @@ -0,0 +1,102 @@ +package safeline + +import ( + "context" + "errors" + "fmt" + + xerrors "github.com/pkg/errors" + + "github.com/usual2970/certimate/internal/pkg/core/deployer" + "github.com/usual2970/certimate/internal/pkg/core/logger" + safelinesdk "github.com/usual2970/certimate/internal/pkg/vendors/safeline-sdk" +) + +type SafeLineDeployerConfig struct { + // 雷池 URL。 + ApiUrl string `json:"apiUrl"` + // 雷池 API Token。 + ApiToken string `json:"apiToken"` + // 部署资源类型。 + ResourceType ResourceType `json:"resourceType"` + // 证书 ID。 + // 部署资源类型为 [RESOURCE_TYPE_CERTIFICATE] 时必填。 + CertificateId int32 `json:"certificateId,omitempty"` +} + +type SafeLineDeployer struct { + config *SafeLineDeployerConfig + logger logger.Logger + sdkClient *safelinesdk.SafeLineClient +} + +var _ deployer.Deployer = (*SafeLineDeployer)(nil) + +func New(config *SafeLineDeployerConfig) (*SafeLineDeployer, error) { + return NewWithLogger(config, logger.NewNilLogger()) +} + +func NewWithLogger(config *SafeLineDeployerConfig, logger logger.Logger) (*SafeLineDeployer, error) { + if config == nil { + return nil, errors.New("config is nil") + } + + if logger == nil { + return nil, errors.New("logger is nil") + } + + client, err := createSdkClient(config.ApiUrl, config.ApiToken) + if err != nil { + return nil, xerrors.Wrap(err, "failed to create sdk clients") + } + + return &SafeLineDeployer{ + logger: logger, + config: config, + sdkClient: client, + }, nil +} + +func (d *SafeLineDeployer) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { + // 根据部署资源类型决定部署方式 + switch d.config.ResourceType { + case RESOURCE_TYPE_CERTIFICATE: + if err := d.deployToCertificate(ctx, certPem, privkeyPem); err != nil { + return nil, err + } + + default: + return nil, fmt.Errorf("unsupported resource type: %s", d.config.ResourceType) + } + + return &deployer.DeployResult{}, nil +} + +func (d *SafeLineDeployer) deployToCertificate(ctx context.Context, certPem string, privkeyPem string) error { + if d.config.CertificateId == 0 { + return errors.New("config `certificateId` is required") + } + + // 更新证书 + updateCertificateReq := &safelinesdk.UpdateCertificateRequest{ + Id: d.config.CertificateId, + Type: 2, + Manual: &safelinesdk.UpdateCertificateRequestBodyManul{ + Crt: certPem, + Key: privkeyPem, + }, + } + updateCertificateResp, err := d.sdkClient.UpdateCertificate(updateCertificateReq) + if err != nil { + return xerrors.Wrap(err, "failed to execute sdk request 'safeline.UpdateCertificate'") + } else { + d.logger.Logt("已更新证书", updateCertificateResp) + } + + return nil +} + +func createSdkClient(apiUrl, apiToken string) (*safelinesdk.SafeLineClient, error) { + client := safelinesdk.NewSafeLineClient(apiUrl, apiToken) + return client, nil +} diff --git a/internal/pkg/core/deployer/providers/safeline/safeline_test.go b/internal/pkg/core/deployer/providers/safeline/safeline_test.go new file mode 100644 index 00000000..052b0aab --- /dev/null +++ b/internal/pkg/core/deployer/providers/safeline/safeline_test.go @@ -0,0 +1,76 @@ +package safeline_test + +import ( + "context" + "flag" + "fmt" + "os" + "strings" + "testing" + + provider "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/safeline" +) + +var ( + fInputCertPath string + fInputKeyPath string + fApiUrl string + fApiToken string + fCertificateId int +) + +func init() { + argsPrefix := "CERTIMATE_DEPLOYER_SAFELINE_" + + flag.StringVar(&fInputCertPath, argsPrefix+"INPUTCERTPATH", "", "") + flag.StringVar(&fInputKeyPath, argsPrefix+"INPUTKEYPATH", "", "") + flag.StringVar(&fApiUrl, argsPrefix+"APIURL", "", "") + flag.StringVar(&fApiToken, argsPrefix+"APITOKEN", "", "") + flag.IntVar(&fCertificateId, argsPrefix+"CERTIFICATEID", 0, "") +} + +/* +Shell command to run this test: + + go test -v ./safeline_test.go -args \ + --CERTIMATE_DEPLOYER_SAFELINE_INPUTCERTPATH="/path/to/your-input-cert.pem" \ + --CERTIMATE_DEPLOYER_SAFELINE_INPUTKEYPATH="/path/to/your-input-key.pem" \ + --CERTIMATE_DEPLOYER_SAFELINE_APIURL="your-safeline-url" \ + --CERTIMATE_DEPLOYER_SAFELINE_APITOKEN="your-safeline-api-token" \ + --CERTIMATE_DEPLOYER_SAFELINE_CERTIFICATEID="your-cerficiate-id" +*/ +func TestDeploy(t *testing.T) { + flag.Parse() + + t.Run("Deploy", func(t *testing.T) { + t.Log(strings.Join([]string{ + "args:", + fmt.Sprintf("INPUTCERTPATH: %v", fInputCertPath), + fmt.Sprintf("INPUTKEYPATH: %v", fInputKeyPath), + fmt.Sprintf("APIURL: %v", fApiUrl), + fmt.Sprintf("APITOKEN: %v", fApiToken), + fmt.Sprintf("CERTIFICATEID: %v", fCertificateId), + }, "\n")) + + deployer, err := provider.New(&provider.SafeLineDeployerConfig{ + ApiUrl: fApiUrl, + ApiToken: fApiToken, + ResourceType: provider.ResourceType("certificate"), + CertificateId: fCertificateId, + }) + if err != nil { + t.Errorf("err: %+v", err) + return + } + + fInputCertData, _ := os.ReadFile(fInputCertPath) + fInputKeyData, _ := os.ReadFile(fInputKeyPath) + res, err := deployer.Deploy(context.Background(), string(fInputCertData), string(fInputKeyData)) + if err != nil { + t.Errorf("err: %+v", err) + return + } + + t.Logf("ok: %v", res) + }) +} diff --git a/internal/pkg/vendors/btpanel-sdk/client.go b/internal/pkg/vendors/btpanel-sdk/client.go index 76540ad7..047c9c54 100644 --- a/internal/pkg/vendors/btpanel-sdk/client.go +++ b/internal/pkg/vendors/btpanel-sdk/client.go @@ -9,8 +9,6 @@ import ( "time" "github.com/go-resty/resty/v2" - - "github.com/usual2970/certimate/internal/pkg/utils/maps" ) type BaoTaPanelClient struct { @@ -113,11 +111,7 @@ func (c *BaoTaPanelClient) sendRequestWithResult(path string, params map[string] return err } - jsonResp := make(map[string]any) - if err := json.Unmarshal(resp.Body(), &jsonResp); err != nil { - return fmt.Errorf("baota: failed to parse response: %w", err) - } - if err := maps.Populate(jsonResp, &result); err != nil { + if err := json.Unmarshal(resp.Body(), &result); err != nil { return fmt.Errorf("baota: failed to parse response: %w", err) } diff --git a/internal/pkg/vendors/gname-sdk/api.go b/internal/pkg/vendors/gname-sdk/api.go index 33972adc..282439d2 100644 --- a/internal/pkg/vendors/gname-sdk/api.go +++ b/internal/pkg/vendors/gname-sdk/api.go @@ -5,6 +5,19 @@ type BaseResponse interface { GetMsg() string } +type baseResponse struct { + Code int `json:"code"` + Msg string `json:"msg"` +} + +func (r *baseResponse) GetCode() int { + return r.Code +} + +func (r *baseResponse) GetMsg() string { + return r.Msg +} + type AddDomainResolutionRequest struct { ZoneName string `json:"ym"` RecordType string `json:"lx"` @@ -15,17 +28,8 @@ type AddDomainResolutionRequest struct { } type AddDomainResolutionResponse struct { - Code int `json:"code"` - Msg string `json:"msg"` - Data int `json:"data"` -} - -func (r *AddDomainResolutionResponse) GetCode() int { - return r.Code -} - -func (r *AddDomainResolutionResponse) GetMsg() string { - return r.Msg + baseResponse + Data int `json:"data"` } type ModifyDomainResolutionRequest struct { @@ -39,16 +43,7 @@ type ModifyDomainResolutionRequest struct { } type ModifyDomainResolutionResponse struct { - Code int `json:"code"` - Msg string `json:"msg"` -} - -func (r *ModifyDomainResolutionResponse) GetCode() int { - return r.Code -} - -func (r *ModifyDomainResolutionResponse) GetMsg() string { - return r.Msg + baseResponse } type DeleteDomainResolutionRequest struct { @@ -57,16 +52,7 @@ type DeleteDomainResolutionRequest struct { } type DeleteDomainResolutionResponse struct { - Code int `json:"code"` - Msg string `json:"msg"` -} - -func (r *DeleteDomainResolutionResponse) GetCode() int { - return r.Code -} - -func (r *DeleteDomainResolutionResponse) GetMsg() string { - return r.Msg + baseResponse } type ListDomainResolutionRequest struct { @@ -76,8 +62,7 @@ type ListDomainResolutionRequest struct { } type ListDomainResolutionResponse struct { - Code int `json:"code"` - Msg string `json:"msg"` + baseResponse Count int `json:"count"` Data []*ResolutionRecord `json:"data"` Page int `json:"page"` @@ -92,11 +77,3 @@ type ResolutionRecord struct { RecordValue string `json:"jxz"` MX int `json:"mx"` } - -func (r *ListDomainResolutionResponse) GetCode() int { - return r.Code -} - -func (r *ListDomainResolutionResponse) GetMsg() string { - return r.Msg -} diff --git a/internal/pkg/vendors/gname-sdk/client.go b/internal/pkg/vendors/gname-sdk/client.go index 64baab95..66c2b995 100644 --- a/internal/pkg/vendors/gname-sdk/client.go +++ b/internal/pkg/vendors/gname-sdk/client.go @@ -10,8 +10,6 @@ import ( "time" "github.com/go-resty/resty/v2" - - "github.com/usual2970/certimate/internal/pkg/utils/maps" ) type GnameClient struct { @@ -131,9 +129,7 @@ func (c *GnameClient) sendRequest(path string, params map[string]any) (*resty.Re resp, err := req.Post(url) if err != nil { return nil, fmt.Errorf("gname: failed to send request: %w", err) - } - - if resp.IsError() { + } else if resp.IsError() { return nil, fmt.Errorf("gname: unexpected status code: %d, %s", resp.StatusCode(), resp.Body()) } @@ -146,11 +142,7 @@ func (c *GnameClient) sendRequestWithResult(path string, params map[string]any, return err } - jsonResp := make(map[string]any) - if err := json.Unmarshal(resp.Body(), &jsonResp); err != nil { - return fmt.Errorf("gname: failed to parse response: %w", err) - } - if err := maps.Populate(jsonResp, &result); err != nil { + if err := json.Unmarshal(resp.Body(), &result); err != nil { return fmt.Errorf("gname: failed to parse response: %w", err) } diff --git a/internal/pkg/vendors/safeline-sdk/api.go b/internal/pkg/vendors/safeline-sdk/api.go new file mode 100644 index 00000000..9fbfb7c9 --- /dev/null +++ b/internal/pkg/vendors/safeline-sdk/api.go @@ -0,0 +1,34 @@ +package safelinesdk + +type BaseResponse interface { + GetErrCode() *string + GetErrMsg() *string +} + +type baseResponse struct { + ErrCode *string `json:"err,omitempty"` + ErrMsg *string `json:"msg,omitempty"` +} + +func (r *baseResponse) GetErrCode() *string { + return r.ErrCode +} + +func (r *baseResponse) GetErrMsg() *string { + return r.ErrMsg +} + +type UpdateCertificateRequest struct { + Id int32 `json:"id"` + Type int32 `json:"type"` + Manual *UpdateCertificateRequestBodyManul `json:"manual"` +} + +type UpdateCertificateRequestBodyManul struct { + Crt string `json:"crt"` + Key string `json:"key"` +} + +type UpdateCertificateResponse struct { + baseResponse +} diff --git a/internal/pkg/vendors/safeline-sdk/client.go b/internal/pkg/vendors/safeline-sdk/client.go new file mode 100644 index 00000000..45ec7f51 --- /dev/null +++ b/internal/pkg/vendors/safeline-sdk/client.go @@ -0,0 +1,87 @@ +package safelinesdk + +import ( + "encoding/json" + "fmt" + "strings" + "time" + + "github.com/go-resty/resty/v2" +) + +type SafeLineClient struct { + apiHost string + apiToken string + client *resty.Client +} + +func NewSafeLineClient(apiHost, apiToken string) *SafeLineClient { + client := resty.New() + + return &SafeLineClient{ + apiHost: apiHost, + apiToken: apiToken, + client: client, + } +} + +func (c *SafeLineClient) WithTimeout(timeout time.Duration) *SafeLineClient { + c.client.SetTimeout(timeout) + return c +} + +func (c *SafeLineClient) UpdateCertificate(req *UpdateCertificateRequest) (*UpdateCertificateResponse, error) { + params := make(map[string]any) + jsonData, _ := json.Marshal(req) + json.Unmarshal(jsonData, ¶ms) + + result := UpdateCertificateResponse{} + err := c.sendRequestWithResult("/api/open/cert", params, &result) + if err != nil { + return nil, err + } + return &result, nil +} + +func (c *SafeLineClient) sendRequest(path string, params map[string]any) (*resty.Response, error) { + if params == nil { + params = make(map[string]any) + } + + url := strings.TrimRight(c.apiHost, "/") + path + req := c.client.R(). + SetHeader("Content-Type", "application/json"). + SetHeader("X-SLCE-API-TOKEN", c.apiToken). + SetBody(params) + resp, err := req.Post(url) + if err != nil { + return nil, fmt.Errorf("safeline: failed to send request: %w", err) + } + + if resp.IsError() { + return nil, fmt.Errorf("safeline: unexpected status code: %d, %s", resp.StatusCode(), resp.Body()) + } + + return resp, nil +} + +func (c *SafeLineClient) sendRequestWithResult(path string, params map[string]any, result BaseResponse) error { + resp, err := c.sendRequest(path, params) + if err != nil { + return err + } + + if err := json.Unmarshal(resp.Body(), &result); err != nil { + return fmt.Errorf("safeline: failed to parse response: %w", err) + } + + if result.GetErrCode() != nil && *result.GetErrCode() != "" { + if result.GetErrMsg() == nil { + return fmt.Errorf("safeline api error: %s", *result.GetErrCode()) + } else { + return fmt.Errorf("safeline api error: %s, %s", *result.GetErrCode(), *result.GetErrMsg()) + } + } + + return nil +} diff --git a/ui/public/imgs/providers/safeline.svg b/ui/public/imgs/providers/safeline.svg new file mode 100644 index 00000000..b5490ac7 --- /dev/null +++ b/ui/public/imgs/providers/safeline.svg @@ -0,0 +1 @@ + diff --git a/ui/src/components/access/AccessForm.tsx b/ui/src/components/access/AccessForm.tsx index d9632f28..71aa3fba 100644 --- a/ui/src/components/access/AccessForm.tsx +++ b/ui/src/components/access/AccessForm.tsx @@ -31,6 +31,7 @@ import AccessFormNS1Config from "./AccessFormNS1Config"; import AccessFormPowerDNSConfig from "./AccessFormPowerDNSConfig"; import AccessFormQiniuConfig from "./AccessFormQiniuConfig"; import AccessFormRainYunConfig from "./AccessFormRainYunConfig"; +import AccessFormSafeLineConfig from "./AccessFormSafeLineConfig"; import AccessFormSSHConfig from "./AccessFormSSHConfig"; import AccessFormTencentCloudConfig from "./AccessFormTencentCloudConfig"; import AccessFormUCloudConfig from "./AccessFormUCloudConfig"; @@ -134,6 +135,8 @@ const AccessForm = forwardRef(({ className, return ; case ACCESS_PROVIDERS.RAINYUN: return ; + case ACCESS_PROVIDERS.SAFELINE: + return ; case ACCESS_PROVIDERS.SSH: return ; case ACCESS_PROVIDERS.TENCENTCLOUD: diff --git a/ui/src/components/access/AccessFormBaotaPanelConfig.tsx b/ui/src/components/access/AccessFormBaotaPanelConfig.tsx index 4f619c1c..accd80d0 100644 --- a/ui/src/components/access/AccessFormBaotaPanelConfig.tsx +++ b/ui/src/components/access/AccessFormBaotaPanelConfig.tsx @@ -17,7 +17,7 @@ export type AccessFormBaotaPanelConfigProps = { const initFormModel = (): AccessFormBaotaPanelConfigFieldValues => { return { - apiUrl: "", + apiUrl: "http://:8888/", apiKey: "", }; }; diff --git a/ui/src/components/access/AccessFormPowerDNSConfig.tsx b/ui/src/components/access/AccessFormPowerDNSConfig.tsx index 83a22b9b..e93980c7 100644 --- a/ui/src/components/access/AccessFormPowerDNSConfig.tsx +++ b/ui/src/components/access/AccessFormPowerDNSConfig.tsx @@ -17,7 +17,7 @@ export type AccessFormPowerDNSConfigProps = { const initFormModel = (): AccessFormPowerDNSConfigFieldValues => { return { - apiUrl: "", + apiUrl: "http://:8082/", apiKey: "", }; }; diff --git a/ui/src/components/access/AccessFormSafeLineConfig.tsx b/ui/src/components/access/AccessFormSafeLineConfig.tsx new file mode 100644 index 00000000..b9de115c --- /dev/null +++ b/ui/src/components/access/AccessFormSafeLineConfig.tsx @@ -0,0 +1,72 @@ +import { useTranslation } from "react-i18next"; +import { Form, type FormInstance, Input } from "antd"; +import { createSchemaFieldRule } from "antd-zod"; +import { z } from "zod"; + +import { type AccessConfigForSafeLine } from "@/domain/access"; + +type AccessFormSafeLineConfigFieldValues = Nullish; + +export type AccessFormSafeLineConfigProps = { + form: FormInstance; + formName: string; + disabled?: boolean; + initialValues?: AccessFormSafeLineConfigFieldValues; + onValuesChange?: (values: AccessFormSafeLineConfigFieldValues) => void; +}; + +const initFormModel = (): AccessFormSafeLineConfigFieldValues => { + return { + apiUrl: "http://:9443/", + apiToken: "", + }; +}; + +const AccessFormSafeLineConfig = ({ form: formInst, formName, disabled, initialValues, onValuesChange }: AccessFormSafeLineConfigProps) => { + const { t } = useTranslation(); + + const formSchema = z.object({ + apiUrl: z.string().url(t("common.errmsg.url_invalid")), + apiToken: z + .string() + .min(1, t("access.form.safeline_api_token.placeholder")) + .max(64, t("common.errmsg.string_max", { max: 64 })) + .trim(), + }); + const formRule = createSchemaFieldRule(formSchema); + + const handleFormChange = (_: unknown, values: z.infer) => { + onValuesChange?.(values); + }; + + return ( +
+ } + > + + + + } + > + + +
+ ); +}; + +export default AccessFormSafeLineConfig; diff --git a/ui/src/components/provider/AccessProviderSelect.tsx b/ui/src/components/provider/AccessProviderSelect.tsx index 04b859ac..97cd35fd 100644 --- a/ui/src/components/provider/AccessProviderSelect.tsx +++ b/ui/src/components/provider/AccessProviderSelect.tsx @@ -47,12 +47,18 @@ const AccessProviderSelect = (props: AccessProviderSelectProps) => { return ( { + if (!option) return false; + + const value = inputValue.toLowerCase(); + return option.value.toLowerCase().includes(value) || option.label.toLowerCase().includes(value); + }} labelRender={({ label, value }) => { - if (label) { - return renderOption(value as string); + if (!label) { + return {props.placeholder}; } - return {props.placeholder}; + return renderOption(value as string); }} options={options} optionFilterProp={undefined} diff --git a/ui/src/components/provider/DeployProviderSelect.tsx b/ui/src/components/provider/DeployProviderSelect.tsx index 54e3643b..cc2b13ea 100644 --- a/ui/src/components/provider/DeployProviderSelect.tsx +++ b/ui/src/components/provider/DeployProviderSelect.tsx @@ -33,12 +33,18 @@ const DeployProviderSelect = (props: DeployProviderSelectProps) => { return ( + + {t("workflow_node.deploy.form.safeline_resource_type.option.certificate.label")} + + + + + + + + + + + ); +}; + +export default DeployNodeConfigFormSafeLineConfig; diff --git a/ui/src/domain/access.ts b/ui/src/domain/access.ts index cf6b1055..d8a64dd4 100644 --- a/ui/src/domain/access.ts +++ b/ui/src/domain/access.ts @@ -27,6 +27,7 @@ export interface AccessModel extends BaseModel { | AccessConfigForPowerDNS | AccessConfigForQiniu | AccessConfigForRainYun + | AccessConfigForSafeLine | AccessConfigForSSH | AccessConfigForTencentCloud | AccessConfigForUCloud @@ -143,6 +144,11 @@ export type AccessConfigForRainYun = { apiKey: string; }; +export type AccessConfigForSafeLine = { + apiUrl: string; + apiToken: string; +}; + export type AccessConfigForSSH = { host: string; port: number; diff --git a/ui/src/domain/provider.ts b/ui/src/domain/provider.ts index 96b69a85..d68e5210 100644 --- a/ui/src/domain/provider.ts +++ b/ui/src/domain/provider.ts @@ -26,6 +26,7 @@ export const ACCESS_PROVIDERS = Object.freeze({ POWERDNS: "powerdns", QINIU: "qiniu", RAINYUN: "rainyun", + SAFELINE: "safeline", SSH: "ssh", TENCENTCLOUD: "tencentcloud", UCLOUD: "ucloud", @@ -70,6 +71,7 @@ export const accessProvidersMap: Map [ type, { diff --git a/ui/src/i18n/locales/en/nls.access.json b/ui/src/i18n/locales/en/nls.access.json index af3676b3..a3a16683 100644 --- a/ui/src/i18n/locales/en/nls.access.json +++ b/ui/src/i18n/locales/en/nls.access.json @@ -147,6 +147,12 @@ "access.form.rainyun_api_key.label": "Rain Yun API key", "access.form.rainyun_api_key.placeholder": "Please enter Rain Yun API key", "access.form.rainyun_api_key.tooltip": "For more information, see https://www.rainyun.com/docs/account/racc/setting", + "access.form.safeline_api_url.label": "SafeLine URL", + "access.form.safeline_api_url.placeholder": "Please enter SafeLine URL", + "access.form.safeline_api_url.tooltip": "For more information, see https://docs.waf.chaitin.com/en/tutorials/install", + "access.form.safeline_api_token.label": "SafeLine API token", + "access.form.safeline_api_token.placeholder": "Please enter SafeLine API token", + "access.form.safeline_api_token.tooltip": "For more information, see https://docs.waf.chaitin.com/en/reference/articles/openapi", "access.form.ssh_host.label": "Server host", "access.form.ssh_host.placeholder": "Please enter server host", "access.form.ssh_port.label": "Server port", diff --git a/ui/src/i18n/locales/en/nls.workflow.nodes.json b/ui/src/i18n/locales/en/nls.workflow.nodes.json index 9e226284..360a0607 100644 --- a/ui/src/i18n/locales/en/nls.workflow.nodes.json +++ b/ui/src/i18n/locales/en/nls.workflow.nodes.json @@ -300,6 +300,11 @@ "workflow_node.deploy.form.qiniu_pili_domain.label": "Qiniu Pili streaming domain", "workflow_node.deploy.form.qiniu_pili_domain.placeholder": "Please enter Qiniu Pili streaming domain name", "workflow_node.deploy.form.qiniu_pili_domain.tooltip": "For more information, see https://portal.qiniu.com/hub", + "workflow_node.deploy.form.safeline_resource_type.label": "Resource type", + "workflow_node.deploy.form.safeline_resource_type.placeholder": "Please select resource type", + "workflow_node.deploy.form.safeline_resource_type.option.certificate.label": "Certificate", + "workflow_node.deploy.form.safeline_certificate_id.label": "SafeLine certificate ID", + "workflow_node.deploy.form.safeline_certificate_id.placeholder": "Please enter SafeLine certificate ID", "workflow_node.deploy.form.ssh_format.label": "File format", "workflow_node.deploy.form.ssh_format.placeholder": "Please select file format", "workflow_node.deploy.form.ssh_format.option.pem.label": "PEM (*.pem, *.crt, *.key)", diff --git a/ui/src/i18n/locales/zh/nls.access.json b/ui/src/i18n/locales/zh/nls.access.json index 37ebb112..586af5f3 100644 --- a/ui/src/i18n/locales/zh/nls.access.json +++ b/ui/src/i18n/locales/zh/nls.access.json @@ -147,6 +147,12 @@ "access.form.rainyun_api_key.label": "雨云 API 密钥", "access.form.rainyun_api_key.placeholder": "请输入雨云 API 密钥", "access.form.rainyun_api_key.tooltip": "这是什么?请参阅 https://www.rainyun.com/docs/account/racc/setting", + "access.form.safeline_api_url.label": "雷池 URL", + "access.form.safeline_api_url.placeholder": "请输入雷池 URL", + "access.form.safeline_api_url.tooltip": "这是什么?请参阅 https://docs.waf-ce.chaitin.cn/zh/上手指南/安装雷池", + "access.form.safeline_api_token.label": "雷池 API Token", + "access.form.safeline_api_token.placeholder": "请输入雷池 API Token", + "access.form.safeline_api_token.tooltip": "这是什么?请参阅 https://docs.waf-ce.chaitin.cn/zh/更多技术文档/OPENAPI", "access.form.ssh_host.label": "服务器地址", "access.form.ssh_host.placeholder": "请输入服务器地址", "access.form.ssh_port.label": "服务器端口", diff --git a/ui/src/i18n/locales/zh/nls.workflow.nodes.json b/ui/src/i18n/locales/zh/nls.workflow.nodes.json index f0c07485..7fe81657 100644 --- a/ui/src/i18n/locales/zh/nls.workflow.nodes.json +++ b/ui/src/i18n/locales/zh/nls.workflow.nodes.json @@ -300,6 +300,11 @@ "workflow_node.deploy.form.qiniu_pili_domain.label": "七牛云视频直播流域名", "workflow_node.deploy.form.qiniu_pili_domain.placeholder": "请输入七牛云视频直播流域名", "workflow_node.deploy.form.qiniu_pili_domain.tooltip": "这是什么?请参阅 https://portal.qiniu.com/hub", + "workflow_node.deploy.form.safeline_resource_type.label": "证书替换方式", + "workflow_node.deploy.form.safeline_resource_type.placeholder": "请选择证书替换方式", + "workflow_node.deploy.form.safeline_resource_type.option.certificate.label": "替换指定证书", + "workflow_node.deploy.form.safeline_certificate_id.label": "雷池证书 ID", + "workflow_node.deploy.form.safeline_certificate_id.placeholder": "请输入雷池证书 ID", "workflow_node.deploy.form.ssh_format.label": "文件格式", "workflow_node.deploy.form.ssh_format.placeholder": "请选择文件格式", "workflow_node.deploy.form.ssh_format.option.pem.label": "PEM 格式(*.pem, *.crt, *.key)", From b2eb5d2754fbe99d322b7683a7c0ba3116d58e97 Mon Sep 17 00:00:00 2001 From: Fu Diwei Date: Mon, 17 Feb 2025 20:19:31 +0800 Subject: [PATCH 07/34] feat: add baishan cdn deployer --- README.md | 1 + README_EN.md | 1 + internal/deployer/providers.go | 21 ++++ internal/domain/access.go | 4 + internal/domain/provider.go | 3 +- .../lego-providers/gname/internal/lego.go | 4 +- .../providers/baishan-cdn/baishan_cdn.go | 116 ++++++++++++++++++ .../providers/baishan-cdn/baishan_cdn_test.go | 70 +++++++++++ .../baotapanel-console/baotapanel_console.go | 6 +- .../baotapanel-site/baotapanel_site.go | 8 +- .../deployer/providers/safeline/safeline.go | 6 +- internal/pkg/vendors/baishan-sdk/api.go | 45 +++++++ internal/pkg/vendors/baishan-sdk/client.go | 84 +++++++++++++ internal/pkg/vendors/baishan-sdk/models.go | 77 ++++++++++++ internal/pkg/vendors/btpanel-sdk/api.go | 76 ++++++------ internal/pkg/vendors/btpanel-sdk/client.go | 53 ++------ internal/pkg/vendors/btpanel-sdk/models.go | 48 ++++++++ internal/pkg/vendors/gname-sdk/api.go | 116 +++++++----------- internal/pkg/vendors/gname-sdk/client.go | 66 ++-------- internal/pkg/vendors/gname-sdk/models.go | 79 ++++++++++++ internal/pkg/vendors/safeline-sdk/api.go | 42 ++----- internal/pkg/vendors/safeline-sdk/client.go | 25 +--- internal/pkg/vendors/safeline-sdk/models.go | 34 +++++ ui/public/imgs/providers/baishan.png | Bin 0 -> 2565 bytes ui/src/components/access/AccessForm.tsx | 3 + .../access/AccessFormBaishanConfig.tsx | 56 +++++++++ .../workflow/node/DeployNodeConfigForm.tsx | 3 + .../DeployNodeConfigFormBaishanCDNConfig.tsx | 65 ++++++++++ ui/src/domain/access.ts | 5 + ui/src/domain/provider.ts | 4 + ui/src/i18n/locales/en/nls.access.json | 2 + .../i18n/locales/en/nls.workflow.nodes.json | 3 + ui/src/i18n/locales/zh/nls.access.json | 2 + .../i18n/locales/zh/nls.workflow.nodes.json | 23 ++-- 34 files changed, 866 insertions(+), 285 deletions(-) create mode 100644 internal/pkg/core/deployer/providers/baishan-cdn/baishan_cdn.go create mode 100644 internal/pkg/core/deployer/providers/baishan-cdn/baishan_cdn_test.go create mode 100644 internal/pkg/vendors/baishan-sdk/api.go create mode 100644 internal/pkg/vendors/baishan-sdk/client.go create mode 100644 internal/pkg/vendors/baishan-sdk/models.go create mode 100644 internal/pkg/vendors/btpanel-sdk/models.go create mode 100644 internal/pkg/vendors/gname-sdk/models.go create mode 100644 internal/pkg/vendors/safeline-sdk/models.go create mode 100644 ui/public/imgs/providers/baishan.png create mode 100644 ui/src/components/access/AccessFormBaishanConfig.tsx create mode 100644 ui/src/components/workflow/node/DeployNodeConfigFormBaishanCDNConfig.tsx diff --git a/README.md b/README.md index 24f2859d..32b5ce17 100644 --- a/README.md +++ b/README.md @@ -128,6 +128,7 @@ make local.run | [华为云](https://www.huaweicloud.com/) | 可部署到华为云 CDN、ELB、WAF 等服务 | | [火山引擎](https://www.volcengine.com/) | 可部署到火山引擎 TOS、CDN、DCDN、CLB、ImageX、Live 等服务 | | [七牛云](https://www.qiniu.com/) | 可部署到七牛云 CDN、直播云等服务 | +| [白山云](https://www.baishan.com/) | 可部署到白山云 CDN | | [多吉云](https://www.dogecloud.com/) | 可部署到多吉云 CDN | | [优刻得](https://www.ucloud.cn/) | 可部署到优刻得 US3、UCDN 等服务 | | [雷池](https://waf-ce.chaitin.cn/) | 可部署到雷池 WAF | diff --git a/README_EN.md b/README_EN.md index dcb69efd..1966512b 100644 --- a/README_EN.md +++ b/README_EN.md @@ -127,6 +127,7 @@ The following hosting providers are supported: | [Huawei Cloud](https://www.huaweicloud.com/) | Supports deployment to Huawei Cloud CDN, ELB, WAF | | [Volcengine](https://www.volcengine.com/) | Supports deployment to Volcengine TOS, CDN, DCDN, CLB, ImageX, Live | | [Qiniu Cloud](https://www.qiniu.com/) | Supports deployment to Qiniu Cloud CDN, Pili | +| [Baishan Cloud](https://intl.baishancloud.com/) | Supports deployment to Baishan Cloud CDN | | [Doge Cloud](https://www.dogecloud.com/) | Supports deployment to Doge Cloud CDN | | [UCloud](https://www.ucloud-global.com/) | Supports deployment to UCloud US3, UCDN | | [SafeLine](https://waf.chaitin.com/) | Supports deployment to SafeLine WAF | diff --git a/internal/deployer/providers.go b/internal/deployer/providers.go index 4c6acc22..d5ce4ae7 100644 --- a/internal/deployer/providers.go +++ b/internal/deployer/providers.go @@ -18,6 +18,7 @@ import ( pAliyunWAF "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/aliyun-waf" pAWSCloudFront "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/aws-cloudfront" pBaiduCloudCDN "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/baiducloud-cdn" + pBaishanCDN "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/baishan-cdn" pBaotaPanelConsole "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/baotapanel-console" pBaotaPanelSite "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/baotapanel-site" pBytePlusCDN "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/byteplus-cdn" @@ -216,6 +217,26 @@ func createDeployer(options *deployerOptions) (deployer.Deployer, logger.Logger, } } + case domain.DeployProviderTypeBaishanCDN: + { + access := domain.AccessConfigForBaishan{} + if err := maps.Populate(options.ProviderAccessConfig, &access); err != nil { + return nil, nil, fmt.Errorf("failed to populate provider access config: %w", err) + } + + switch options.Provider { + case domain.DeployProviderTypeBaishanCDN: + deployer, err := pBaishanCDN.NewWithLogger(&pBaishanCDN.BaishanCDNDeployerConfig{ + ApiToken: access.ApiToken, + Domain: maps.GetValueAsString(options.ProviderDeployConfig, "domain"), + }, logger) + return deployer, logger, err + + default: + break + } + } + case domain.DeployProviderTypeBaotaPanelConsole, domain.DeployProviderTypeBaotaPanelSite: { access := domain.AccessConfigForBaotaPanel{} diff --git a/internal/domain/access.go b/internal/domain/access.go index ec2e093e..d4f4f714 100644 --- a/internal/domain/access.go +++ b/internal/domain/access.go @@ -53,6 +53,10 @@ type AccessConfigForBaiduCloud struct { SecretAccessKey string `json:"secretAccessKey"` } +type AccessConfigForBaishan struct { + ApiToken string `json:"apiToken"` +} + type AccessConfigForBaotaPanel struct { ApiUrl string `json:"apiUrl"` ApiKey string `json:"apiKey"` diff --git a/internal/domain/provider.go b/internal/domain/provider.go index 08ee9836..70b90af5 100644 --- a/internal/domain/provider.go +++ b/internal/domain/provider.go @@ -16,7 +16,7 @@ const ( AccessProviderTypeAWS = AccessProviderType("aws") AccessProviderTypeAzure = AccessProviderType("azure") AccessProviderTypeBaiduCloud = AccessProviderType("baiducloud") - AccessProviderTypeBaishan = AccessProviderType("baishan") // 白山云(预留) + AccessProviderTypeBaishan = AccessProviderType("baishan") AccessProviderTypeBaotaPanel = AccessProviderType("baotapanel") AccessProviderTypeBytePlus = AccessProviderType("byteplus") AccessProviderTypeCacheFly = AccessProviderType("cachefly") // CacheFly(预留) @@ -107,6 +107,7 @@ const ( DeployProviderTypeAliyunWAF = DeployProviderType("aliyun-waf") DeployProviderTypeAWSCloudFront = DeployProviderType("aws-cloudfront") DeployProviderTypeBaiduCloudCDN = DeployProviderType("baiducloud-cdn") + DeployProviderTypeBaishanCDN = DeployProviderType("baishan-cdn") DeployProviderTypeBaotaPanelConsole = DeployProviderType("baotapanel-console") DeployProviderTypeBaotaPanelSite = DeployProviderType("baotapanel-site") DeployProviderTypeBytePlusCDN = DeployProviderType("byteplus-cdn") diff --git a/internal/pkg/core/applicant/acme-dns-01/lego-providers/gname/internal/lego.go b/internal/pkg/core/applicant/acme-dns-01/lego-providers/gname/internal/lego.go index 03dc633f..94a8c35d 100644 --- a/internal/pkg/core/applicant/acme-dns-01/lego-providers/gname/internal/lego.go +++ b/internal/pkg/core/applicant/acme-dns-01/lego-providers/gname/internal/lego.go @@ -37,7 +37,7 @@ type Config struct { } type DNSProvider struct { - client *gnamesdk.GnameClient + client *gnamesdk.Client config *Config } @@ -68,7 +68,7 @@ func NewDNSProviderConfig(config *Config) (*DNSProvider, error) { return nil, errors.New("gname: the configuration of the DNS provider is nil") } - client := gnamesdk.NewGnameClient(config.AppID, config.AppKey). + client := gnamesdk.NewClient(config.AppID, config.AppKey). WithTimeout(config.HTTPTimeout) return &DNSProvider{ diff --git a/internal/pkg/core/deployer/providers/baishan-cdn/baishan_cdn.go b/internal/pkg/core/deployer/providers/baishan-cdn/baishan_cdn.go new file mode 100644 index 00000000..214f050e --- /dev/null +++ b/internal/pkg/core/deployer/providers/baishan-cdn/baishan_cdn.go @@ -0,0 +1,116 @@ +package baishancdn + +import ( + "context" + "errors" + "fmt" + "time" + + xerrors "github.com/pkg/errors" + + "github.com/usual2970/certimate/internal/pkg/core/deployer" + "github.com/usual2970/certimate/internal/pkg/core/logger" + bssdk "github.com/usual2970/certimate/internal/pkg/vendors/baishan-sdk" +) + +type BaishanCDNDeployerConfig struct { + // 白山云 API Token。 + ApiToken string `json:"apiToken"` + // 加速域名(支持泛域名)。 + Domain string `json:"domain"` +} + +type BaishanCDNDeployer struct { + config *BaishanCDNDeployerConfig + logger logger.Logger + sdkClient *bssdk.Client +} + +var _ deployer.Deployer = (*BaishanCDNDeployer)(nil) + +func New(config *BaishanCDNDeployerConfig) (*BaishanCDNDeployer, error) { + return NewWithLogger(config, logger.NewNilLogger()) +} + +func NewWithLogger(config *BaishanCDNDeployerConfig, logger logger.Logger) (*BaishanCDNDeployer, error) { + if config == nil { + return nil, errors.New("config is nil") + } + + if logger == nil { + return nil, errors.New("logger is nil") + } + + client, err := createSdkClient(config.ApiToken) + if err != nil { + return nil, xerrors.Wrap(err, "failed to create sdk client") + } + + return &BaishanCDNDeployer{ + logger: logger, + config: config, + sdkClient: client, + }, nil +} + +func (d *BaishanCDNDeployer) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { + if d.config.Domain == "" { + return nil, errors.New("config `domain` is required") + } + + // 查询域名配置 + // REF: https://portal.baishancloud.com/track/document/api/1/1065 + getDomainConfigReq := &bssdk.GetDomainConfigRequest{ + Domains: d.config.Domain, + Config: "https", + } + getDomainConfigResp, err := d.sdkClient.GetDomainConfig(getDomainConfigReq) + if err != nil { + return nil, xerrors.Wrap(err, "failed to execute sdk request 'baishan.GetDomainConfig'") + } else if len(getDomainConfigResp.Data) == 0 { + return nil, errors.New("domain config not found") + } else { + d.logger.Logt("已查询到域名配置", getDomainConfigResp) + } + + // 新增证书 + // REF: https://portal.baishancloud.com/track/document/downloadPdf/1441 + createCertificateReq := &bssdk.CreateCertificateRequest{ + Certificate: certPem, + Key: privkeyPem, + Name: fmt.Sprintf("certimate_%d", time.Now().UnixMilli()), + } + createCertificateResp, err := d.sdkClient.CreateCertificate(createCertificateReq) + if err != nil { + return nil, xerrors.Wrap(err, "failed to execute sdk request 'baishan.CreateCertificate'") + } else { + d.logger.Logt("已新增证书", createCertificateResp) + } + + // 设置域名配置 + // REF: https://portal.baishancloud.com/track/document/api/1/1045 + setDomainConfigReq := &bssdk.SetDomainConfigRequest{ + Domains: d.config.Domain, + Config: &bssdk.DomainConfig{ + Https: &bssdk.DomainConfigHttps{ + CertId: createCertificateResp.Data.CertId, + ForceHttps: getDomainConfigResp.Data[0].Config.Https.ForceHttps, + EnableHttp2: getDomainConfigResp.Data[0].Config.Https.EnableHttp2, + EnableOcsp: getDomainConfigResp.Data[0].Config.Https.EnableOcsp, + }, + }, + } + setDomainConfigResp, err := d.sdkClient.SetDomainConfig(setDomainConfigReq) + if err != nil { + return nil, xerrors.Wrap(err, "failed to execute sdk request 'baishan.SetDomainConfig'") + } else { + d.logger.Logt("已设置域名配置", setDomainConfigResp) + } + + return &deployer.DeployResult{}, nil +} + +func createSdkClient(apiToken string) (*bssdk.Client, error) { + client := bssdk.NewClient(apiToken) + return client, nil +} diff --git a/internal/pkg/core/deployer/providers/baishan-cdn/baishan_cdn_test.go b/internal/pkg/core/deployer/providers/baishan-cdn/baishan_cdn_test.go new file mode 100644 index 00000000..b6ceb64f --- /dev/null +++ b/internal/pkg/core/deployer/providers/baishan-cdn/baishan_cdn_test.go @@ -0,0 +1,70 @@ +package baishancdn_test + +import ( + "context" + "flag" + "fmt" + "os" + "strings" + "testing" + + provider "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/baishan-cdn" +) + +var ( + fInputCertPath string + fInputKeyPath string + fApiToken string + fDomain string +) + +func init() { + argsPrefix := "CERTIMATE_DEPLOYER_BAISHANCDN_" + + flag.StringVar(&fInputCertPath, argsPrefix+"INPUTCERTPATH", "", "") + flag.StringVar(&fInputKeyPath, argsPrefix+"INPUTKEYPATH", "", "") + flag.StringVar(&fApiToken, argsPrefix+"APITOKEN", "", "") + flag.StringVar(&fDomain, argsPrefix+"DOMAIN", "", "") +} + +/* +Shell command to run this test: + + go test -v ./baishan_cdn_test.go -args \ + --CERTIMATE_DEPLOYER_BAISHANCDN_INPUTCERTPATH="/path/to/your-input-cert.pem" \ + --CERTIMATE_DEPLOYER_BAISHANCDN_INPUTKEYPATH="/path/to/your-input-key.pem" \ + --CERTIMATE_DEPLOYER_BAISHANCDN_APITOKEN="your-api-token" \ + --CERTIMATE_DEPLOYER_BAISHANCDN_DOMAIN="example.com" +*/ +func TestDeploy(t *testing.T) { + flag.Parse() + + t.Run("Deploy", func(t *testing.T) { + t.Log(strings.Join([]string{ + "args:", + fmt.Sprintf("INPUTCERTPATH: %v", fInputCertPath), + fmt.Sprintf("INPUTKEYPATH: %v", fInputKeyPath), + fmt.Sprintf("APITOKEN: %v", fApiToken), + fmt.Sprintf("DOMAIN: %v", fDomain), + }, "\n")) + + deployer, err := provider.New(&provider.BaishanCDNDeployerConfig{ + ApiToken: fApiToken, + Domain: fDomain, + }) + if err != nil { + t.Errorf("err: %+v", err) + return + } + + fInputCertData, _ := os.ReadFile(fInputCertPath) + fInputKeyData, _ := os.ReadFile(fInputKeyPath) + res, err := deployer.Deploy(context.Background(), string(fInputCertData), string(fInputKeyData)) + if err != nil { + t.Errorf("err: %+v", err) + return + } + + t.Logf("ok: %v", res) + }) +} diff --git a/internal/pkg/core/deployer/providers/baotapanel-console/baotapanel_console.go b/internal/pkg/core/deployer/providers/baotapanel-console/baotapanel_console.go index 28765cff..e9c955c7 100644 --- a/internal/pkg/core/deployer/providers/baotapanel-console/baotapanel_console.go +++ b/internal/pkg/core/deployer/providers/baotapanel-console/baotapanel_console.go @@ -23,7 +23,7 @@ type BaotaPanelConsoleDeployerConfig struct { type BaotaPanelConsoleDeployer struct { config *BaotaPanelConsoleDeployerConfig logger logger.Logger - sdkClient *btsdk.BaoTaPanelClient + sdkClient *btsdk.Client } var _ deployer.Deployer = (*BaotaPanelConsoleDeployer)(nil) @@ -81,7 +81,7 @@ func (d *BaotaPanelConsoleDeployer) Deploy(ctx context.Context, certPem string, return &deployer.DeployResult{}, nil } -func createSdkClient(apiUrl, apiKey string) (*btsdk.BaoTaPanelClient, error) { - client := btsdk.NewBaoTaPanelClient(apiUrl, apiKey) +func createSdkClient(apiUrl, apiKey string) (*btsdk.Client, error) { + client := btsdk.NewClient(apiUrl, apiKey) return client, nil } diff --git a/internal/pkg/core/deployer/providers/baotapanel-site/baotapanel_site.go b/internal/pkg/core/deployer/providers/baotapanel-site/baotapanel_site.go index 6422a2cb..d2d8622f 100644 --- a/internal/pkg/core/deployer/providers/baotapanel-site/baotapanel_site.go +++ b/internal/pkg/core/deployer/providers/baotapanel-site/baotapanel_site.go @@ -16,14 +16,14 @@ type BaotaPanelSiteDeployerConfig struct { ApiUrl string `json:"apiUrl"` // 宝塔面板接口密钥。 ApiKey string `json:"apiKey"` - // 站点名称 + // 站点名称。 SiteName string `json:"siteName"` } type BaotaPanelSiteDeployer struct { config *BaotaPanelSiteDeployerConfig logger logger.Logger - sdkClient *btsdk.BaoTaPanelClient + sdkClient *btsdk.Client } var _ deployer.Deployer = (*BaotaPanelSiteDeployer)(nil) @@ -75,7 +75,7 @@ func (d *BaotaPanelSiteDeployer) Deploy(ctx context.Context, certPem string, pri return &deployer.DeployResult{}, nil } -func createSdkClient(apiUrl, apiKey string) (*btsdk.BaoTaPanelClient, error) { - client := btsdk.NewBaoTaPanelClient(apiUrl, apiKey) +func createSdkClient(apiUrl, apiKey string) (*btsdk.Client, error) { + client := btsdk.NewClient(apiUrl, apiKey) return client, nil } diff --git a/internal/pkg/core/deployer/providers/safeline/safeline.go b/internal/pkg/core/deployer/providers/safeline/safeline.go index b759981a..d6b37aea 100644 --- a/internal/pkg/core/deployer/providers/safeline/safeline.go +++ b/internal/pkg/core/deployer/providers/safeline/safeline.go @@ -27,7 +27,7 @@ type SafeLineDeployerConfig struct { type SafeLineDeployer struct { config *SafeLineDeployerConfig logger logger.Logger - sdkClient *safelinesdk.SafeLineClient + sdkClient *safelinesdk.Client } var _ deployer.Deployer = (*SafeLineDeployer)(nil) @@ -96,7 +96,7 @@ func (d *SafeLineDeployer) deployToCertificate(ctx context.Context, certPem stri return nil } -func createSdkClient(apiUrl, apiToken string) (*safelinesdk.SafeLineClient, error) { - client := safelinesdk.NewSafeLineClient(apiUrl, apiToken) +func createSdkClient(apiUrl, apiToken string) (*safelinesdk.Client, error) { + client := safelinesdk.NewClient(apiUrl, apiToken) return client, nil } diff --git a/internal/pkg/vendors/baishan-sdk/api.go b/internal/pkg/vendors/baishan-sdk/api.go new file mode 100644 index 00000000..9e6a2bc6 --- /dev/null +++ b/internal/pkg/vendors/baishan-sdk/api.go @@ -0,0 +1,45 @@ +package baishansdk + +import ( + "encoding/json" + "net/http" +) + +func (c *Client) CreateCertificate(req *CreateCertificateRequest) (*CreateCertificateResponse, error) { + params := make(map[string]any) + jsonData, _ := json.Marshal(req) + json.Unmarshal(jsonData, ¶ms) + + result := CreateCertificateResponse{} + err := c.sendRequestWithResult(http.MethodPost, "/v2/domain/certificate", params, &result) + if err != nil { + return nil, err + } + return &result, nil +} + +func (c *Client) GetDomainConfig(req *GetDomainConfigRequest) (*GetDomainConfigResponse, error) { + params := make(map[string]any) + jsonData, _ := json.Marshal(req) + json.Unmarshal(jsonData, ¶ms) + + result := GetDomainConfigResponse{} + err := c.sendRequestWithResult(http.MethodGet, "/v2/domain/config", params, &result) + if err != nil { + return nil, err + } + return &result, nil +} + +func (c *Client) SetDomainConfig(req *SetDomainConfigRequest) (*SetDomainConfigResponse, error) { + params := make(map[string]any) + jsonData, _ := json.Marshal(req) + json.Unmarshal(jsonData, ¶ms) + + result := SetDomainConfigResponse{} + err := c.sendRequestWithResult(http.MethodPost, "/v2/domain/config", params, &result) + if err != nil { + return nil, err + } + return &result, nil +} diff --git a/internal/pkg/vendors/baishan-sdk/client.go b/internal/pkg/vendors/baishan-sdk/client.go new file mode 100644 index 00000000..28cb0bc3 --- /dev/null +++ b/internal/pkg/vendors/baishan-sdk/client.go @@ -0,0 +1,84 @@ +package baishansdk + +import ( + "encoding/json" + "fmt" + "net/http" + "time" + + "github.com/go-resty/resty/v2" +) + +type Client struct { + apiToken string + client *resty.Client +} + +func NewClient(apiToken string) *Client { + client := resty.New() + + return &Client{ + apiToken: apiToken, + client: client, + } +} + +func (c *Client) WithTimeout(timeout time.Duration) *Client { + c.client.SetTimeout(timeout) + return c +} + +func (c *Client) sendRequest(method string, path string, params map[string]any) (*resty.Response, error) { + url := "https://cdn.api.baishan.com" + path + + req := c.client.R() + if method == http.MethodGet { + data := make(map[string]string) + for k, v := range params { + data[k] = fmt.Sprintf("%v", v) + } + req = req. + SetQueryParams(data). + SetQueryParam("token", c.apiToken) + } else if method == http.MethodPost { + req = req. + SetHeader("Content-Type", "application/json"). + SetQueryParam("token", c.apiToken). + SetBody(params) + } + + var resp *resty.Response + var err error + if method == http.MethodGet { + resp, err = req.Get(url) + } else if method == http.MethodPost { + resp, err = req.Post(url) + } else { + return nil, fmt.Errorf("baishan: unsupported method: %s", method) + } + + if err != nil { + return nil, fmt.Errorf("baishan: failed to send request: %w", err) + } else if resp.IsError() { + return nil, fmt.Errorf("baishan: unexpected status code: %d, %s", resp.StatusCode(), resp.Body()) + } + + return resp, nil +} + +func (c *Client) sendRequestWithResult(method string, path string, params map[string]any, result BaseResponse) error { + resp, err := c.sendRequest(method, path, params) + if err != nil { + return err + } + + if err := json.Unmarshal(resp.Body(), &result); err != nil { + return fmt.Errorf("baishan: failed to parse response: %w", err) + } + + if result.GetCode() != 0 { + return fmt.Errorf("baishan api error: %d, %s", result.GetCode(), result.GetMessage()) + } + + return nil +} diff --git a/internal/pkg/vendors/baishan-sdk/models.go b/internal/pkg/vendors/baishan-sdk/models.go new file mode 100644 index 00000000..4cf1a918 --- /dev/null +++ b/internal/pkg/vendors/baishan-sdk/models.go @@ -0,0 +1,77 @@ +package baishansdk + +type BaseResponse interface { + GetCode() int + GetMessage() string +} + +type baseResponse struct { + Code int `json:"code"` + Message string `json:"message"` +} + +func (r *baseResponse) GetCode() int { + return r.Code +} + +func (r *baseResponse) GetMessage() string { + return r.Message +} + +type CreateCertificateRequest struct { + Certificate string `json:"certificate"` + Key string `json:"key"` + Name string `json:"name"` +} + +type CreateCertificateResponse struct { + baseResponse + Data *DomainCertificate `json:"data"` +} + +type GetDomainConfigRequest struct { + Domains string `json:"domains"` + Config string `json:"config"` +} + +type GetDomainConfigResponse struct { + baseResponse + Data []*GetDomainConfigResponseData `json:"data"` +} + +type GetDomainConfigResponseData struct { + Domain string `json:"domain"` + Config *DomainConfig `json:"config"` +} + +type SetDomainConfigRequest struct { + Domains string `json:"domains"` + Config *DomainConfig `json:"config"` +} + +type SetDomainConfigResponse struct { + baseResponse + Data *SetDomainConfigResponseData `json:"data"` +} + +type SetDomainConfigResponseData struct { + Config *DomainConfig `json:"config"` +} + +type DomainCertificate struct { + CertId int64 `json:"cert_id"` + Name string `json:"name"` + CertStartTime string `json:"cert_start_time"` + CertExpireTime string `json:"cert_expire_time"` +} + +type DomainConfig struct { + Https *DomainConfigHttps `json:"https"` +} + +type DomainConfigHttps struct { + CertId int64 `json:"cert_id"` + ForceHttps *string `json:"force_https,omitempty"` + EnableHttp2 *string `json:"http2,omitempty"` + EnableOcsp *string `json:"ocsp,omitempty"` +} diff --git a/internal/pkg/vendors/btpanel-sdk/api.go b/internal/pkg/vendors/btpanel-sdk/api.go index f733d67a..f197e081 100644 --- a/internal/pkg/vendors/btpanel-sdk/api.go +++ b/internal/pkg/vendors/btpanel-sdk/api.go @@ -1,48 +1,44 @@ package btpanelsdk -type BaseResponse interface { - GetStatus() *bool - GetMsg() *string +import ( + "encoding/json" +) + +func (c *Client) ConfigSavePanelSSL(req *ConfigSavePanelSSLRequest) (*ConfigSavePanelSSLResponse, error) { + params := make(map[string]any) + jsonData, _ := json.Marshal(req) + json.Unmarshal(jsonData, ¶ms) + + result := ConfigSavePanelSSLResponse{} + err := c.sendRequestWithResult("/config?action=SavePanelSSL", params, &result) + if err != nil { + return nil, err + } + return &result, nil } -type baseResponse struct { - Status *bool `json:"status,omitempty"` - Msg *string `json:"msg,omitempty"` +func (c *Client) SiteSetSSL(req *SiteSetSSLRequest) (*SiteSetSSLResponse, error) { + params := make(map[string]any) + jsonData, _ := json.Marshal(req) + json.Unmarshal(jsonData, ¶ms) + + result := SiteSetSSLResponse{} + err := c.sendRequestWithResult("/site?action=SetSSL", params, &result) + if err != nil { + return nil, err + } + return &result, nil } -func (r *baseResponse) GetStatus() *bool { - return r.Status -} +func (c *Client) SystemServiceAdmin(req *SystemServiceAdminRequest) (*SystemServiceAdminResponse, error) { + params := make(map[string]any) + jsonData, _ := json.Marshal(req) + json.Unmarshal(jsonData, ¶ms) -func (r *baseResponse) GetMsg() *string { - return r.Msg -} - -type ConfigSavePanelSSLRequest struct { - PrivateKey string `json:"privateKey"` - Certificate string `json:"certPem"` -} - -type ConfigSavePanelSSLResponse struct { - baseResponse -} - -type SiteSetSSLRequest struct { - Type string `json:"type"` - SiteName string `json:"siteName"` - PrivateKey string `json:"key"` - Certificate string `json:"csr"` -} - -type SiteSetSSLResponse struct { - baseResponse -} - -type SystemServiceAdminRequest struct { - Name string `json:"name"` - Type string `json:"type"` -} - -type SystemServiceAdminResponse struct { - baseResponse + result := SystemServiceAdminResponse{} + err := c.sendRequestWithResult("/system?action=ServiceAdmin", params, &result) + if err != nil { + return nil, err + } + return &result, nil } diff --git a/internal/pkg/vendors/btpanel-sdk/client.go b/internal/pkg/vendors/btpanel-sdk/client.go index 047c9c54..513a9eb3 100644 --- a/internal/pkg/vendors/btpanel-sdk/client.go +++ b/internal/pkg/vendors/btpanel-sdk/client.go @@ -11,67 +11,28 @@ import ( "github.com/go-resty/resty/v2" ) -type BaoTaPanelClient struct { +type Client struct { apiHost string apiKey string client *resty.Client } -func NewBaoTaPanelClient(apiHost, apiKey string) *BaoTaPanelClient { +func NewClient(apiHost, apiKey string) *Client { client := resty.New() - return &BaoTaPanelClient{ + return &Client{ apiHost: apiHost, apiKey: apiKey, client: client, } } -func (c *BaoTaPanelClient) WithTimeout(timeout time.Duration) *BaoTaPanelClient { +func (c *Client) WithTimeout(timeout time.Duration) *Client { c.client.SetTimeout(timeout) return c } -func (c *BaoTaPanelClient) ConfigSavePanelSSL(req *ConfigSavePanelSSLRequest) (*ConfigSavePanelSSLResponse, error) { - params := make(map[string]any) - jsonData, _ := json.Marshal(req) - json.Unmarshal(jsonData, ¶ms) - - result := ConfigSavePanelSSLResponse{} - err := c.sendRequestWithResult("/config?action=SavePanelSSL", params, &result) - if err != nil { - return nil, err - } - return &result, nil -} - -func (c *BaoTaPanelClient) SiteSetSSL(req *SiteSetSSLRequest) (*SiteSetSSLResponse, error) { - params := make(map[string]any) - jsonData, _ := json.Marshal(req) - json.Unmarshal(jsonData, ¶ms) - - result := SiteSetSSLResponse{} - err := c.sendRequestWithResult("/site?action=SetSSL", params, &result) - if err != nil { - return nil, err - } - return &result, nil -} - -func (c *BaoTaPanelClient) SystemServiceAdmin(req *SystemServiceAdminRequest) (*SystemServiceAdminResponse, error) { - params := make(map[string]any) - jsonData, _ := json.Marshal(req) - json.Unmarshal(jsonData, ¶ms) - - result := SystemServiceAdminResponse{} - err := c.sendRequestWithResult("/system?action=ServiceAdmin", params, &result) - if err != nil { - return nil, err - } - return &result, nil -} - -func (c *BaoTaPanelClient) generateSignature(timestamp string) string { +func (c *Client) generateSignature(timestamp string) string { keyMd5 := md5.Sum([]byte(c.apiKey)) keyMd5Hex := strings.ToLower(hex.EncodeToString(keyMd5[:])) @@ -80,7 +41,7 @@ func (c *BaoTaPanelClient) generateSignature(timestamp string) string { return signMd5Hex } -func (c *BaoTaPanelClient) sendRequest(path string, params map[string]any) (*resty.Response, error) { +func (c *Client) sendRequest(path string, params map[string]any) (*resty.Response, error) { if params == nil { params = make(map[string]any) } @@ -105,7 +66,7 @@ func (c *BaoTaPanelClient) sendRequest(path string, params map[string]any) (*res return resp, nil } -func (c *BaoTaPanelClient) sendRequestWithResult(path string, params map[string]any, result BaseResponse) error { +func (c *Client) sendRequestWithResult(path string, params map[string]any, result BaseResponse) error { resp, err := c.sendRequest(path, params) if err != nil { return err diff --git a/internal/pkg/vendors/btpanel-sdk/models.go b/internal/pkg/vendors/btpanel-sdk/models.go new file mode 100644 index 00000000..f733d67a --- /dev/null +++ b/internal/pkg/vendors/btpanel-sdk/models.go @@ -0,0 +1,48 @@ +package btpanelsdk + +type BaseResponse interface { + GetStatus() *bool + GetMsg() *string +} + +type baseResponse struct { + Status *bool `json:"status,omitempty"` + Msg *string `json:"msg,omitempty"` +} + +func (r *baseResponse) GetStatus() *bool { + return r.Status +} + +func (r *baseResponse) GetMsg() *string { + return r.Msg +} + +type ConfigSavePanelSSLRequest struct { + PrivateKey string `json:"privateKey"` + Certificate string `json:"certPem"` +} + +type ConfigSavePanelSSLResponse struct { + baseResponse +} + +type SiteSetSSLRequest struct { + Type string `json:"type"` + SiteName string `json:"siteName"` + PrivateKey string `json:"key"` + Certificate string `json:"csr"` +} + +type SiteSetSSLResponse struct { + baseResponse +} + +type SystemServiceAdminRequest struct { + Name string `json:"name"` + Type string `json:"type"` +} + +type SystemServiceAdminResponse struct { + baseResponse +} diff --git a/internal/pkg/vendors/gname-sdk/api.go b/internal/pkg/vendors/gname-sdk/api.go index 282439d2..20891405 100644 --- a/internal/pkg/vendors/gname-sdk/api.go +++ b/internal/pkg/vendors/gname-sdk/api.go @@ -1,79 +1,57 @@ package gnamesdk -type BaseResponse interface { - GetCode() int - GetMsg() string +import ( + "encoding/json" +) + +func (c *Client) AddDomainResolution(req *AddDomainResolutionRequest) (*AddDomainResolutionResponse, error) { + params := make(map[string]any) + jsonData, _ := json.Marshal(req) + json.Unmarshal(jsonData, ¶ms) + + result := AddDomainResolutionResponse{} + err := c.sendRequestWithResult("/api/resolution/add", params, &result) + if err != nil { + return nil, err + } + return &result, nil } -type baseResponse struct { - Code int `json:"code"` - Msg string `json:"msg"` +func (c *Client) ModifyDomainResolution(req *ModifyDomainResolutionRequest) (*ModifyDomainResolutionResponse, error) { + params := make(map[string]any) + jsonData, _ := json.Marshal(req) + json.Unmarshal(jsonData, ¶ms) + + result := ModifyDomainResolutionResponse{} + err := c.sendRequestWithResult("/api/resolution/edit", params, &result) + if err != nil { + return nil, err + } + return &result, nil } -func (r *baseResponse) GetCode() int { - return r.Code +func (c *Client) DeleteDomainResolution(req *DeleteDomainResolutionRequest) (*DeleteDomainResolutionResponse, error) { + params := make(map[string]any) + jsonData, _ := json.Marshal(req) + json.Unmarshal(jsonData, ¶ms) + + result := DeleteDomainResolutionResponse{} + err := c.sendRequestWithResult("/api/resolution/delete", params, &result) + if err != nil { + return nil, err + } + return &result, nil } -func (r *baseResponse) GetMsg() string { - return r.Msg -} +func (c *Client) ListDomainResolution(req *ListDomainResolutionRequest) (*ListDomainResolutionResponse, error) { + params := make(map[string]any) + jsonData, _ := json.Marshal(req) + json.Unmarshal(jsonData, ¶ms) -type AddDomainResolutionRequest struct { - ZoneName string `json:"ym"` - RecordType string `json:"lx"` - RecordName string `json:"zj"` - RecordValue string `json:"jlz"` - MX int `json:"mx"` - TTL int `json:"ttl"` -} - -type AddDomainResolutionResponse struct { - baseResponse - Data int `json:"data"` -} - -type ModifyDomainResolutionRequest struct { - ID string `json:"jxid"` - ZoneName string `json:"ym"` - RecordType string `json:"lx"` - RecordName string `json:"zj"` - RecordValue string `json:"jlz"` - MX int `json:"mx"` - TTL int `json:"ttl"` -} - -type ModifyDomainResolutionResponse struct { - baseResponse -} - -type DeleteDomainResolutionRequest struct { - ZoneName string `json:"ym"` - RecordID string `json:"jxid"` -} - -type DeleteDomainResolutionResponse struct { - baseResponse -} - -type ListDomainResolutionRequest struct { - ZoneName string `json:"ym"` - Page *int `json:"page,omitempty"` - PageSize *int `json:"limit,omitempty"` -} - -type ListDomainResolutionResponse struct { - baseResponse - Count int `json:"count"` - Data []*ResolutionRecord `json:"data"` - Page int `json:"page"` - PageSize int `json:"pagesize"` -} - -type ResolutionRecord struct { - ID string `json:"id"` - ZoneName string `json:"ym"` - RecordType string `json:"lx"` - RecordName string `json:"zjt"` - RecordValue string `json:"jxz"` - MX int `json:"mx"` + result := ListDomainResolutionResponse{} + err := c.sendRequestWithResult("/api/resolution/list", params, &result) + if err != nil { + return nil, err + } + return &result, nil } diff --git a/internal/pkg/vendors/gname-sdk/client.go b/internal/pkg/vendors/gname-sdk/client.go index 66c2b995..d73782e4 100644 --- a/internal/pkg/vendors/gname-sdk/client.go +++ b/internal/pkg/vendors/gname-sdk/client.go @@ -12,80 +12,28 @@ import ( "github.com/go-resty/resty/v2" ) -type GnameClient struct { +type Client struct { appId string appKey string client *resty.Client } -func NewGnameClient(appId, appKey string) *GnameClient { +func NewClient(appId, appKey string) *Client { client := resty.New() - return &GnameClient{ + return &Client{ appId: appId, appKey: appKey, client: client, } } -func (c *GnameClient) WithTimeout(timeout time.Duration) *GnameClient { +func (c *Client) WithTimeout(timeout time.Duration) *Client { c.client.SetTimeout(timeout) return c } -func (c *GnameClient) AddDomainResolution(req *AddDomainResolutionRequest) (*AddDomainResolutionResponse, error) { - params := make(map[string]any) - jsonData, _ := json.Marshal(req) - json.Unmarshal(jsonData, ¶ms) - - result := AddDomainResolutionResponse{} - err := c.sendRequestWithResult("/api/resolution/add", params, &result) - if err != nil { - return nil, err - } - return &result, nil -} - -func (c *GnameClient) ModifyDomainResolution(req *ModifyDomainResolutionRequest) (*ModifyDomainResolutionResponse, error) { - params := make(map[string]any) - jsonData, _ := json.Marshal(req) - json.Unmarshal(jsonData, ¶ms) - - result := ModifyDomainResolutionResponse{} - err := c.sendRequestWithResult("/api/resolution/edit", params, &result) - if err != nil { - return nil, err - } - return &result, nil -} - -func (c *GnameClient) DeleteDomainResolution(req *DeleteDomainResolutionRequest) (*DeleteDomainResolutionResponse, error) { - params := make(map[string]any) - jsonData, _ := json.Marshal(req) - json.Unmarshal(jsonData, ¶ms) - - result := DeleteDomainResolutionResponse{} - err := c.sendRequestWithResult("/api/resolution/delete", params, &result) - if err != nil { - return nil, err - } - return &result, nil -} - -func (c *GnameClient) ListDomainResolution(req *ListDomainResolutionRequest) (*ListDomainResolutionResponse, error) { - params := make(map[string]any) - jsonData, _ := json.Marshal(req) - json.Unmarshal(jsonData, ¶ms) - - result := ListDomainResolutionResponse{} - err := c.sendRequestWithResult("/api/resolution/list", params, &result) - if err != nil { - return nil, err - } - return &result, nil -} - -func (c *GnameClient) generateSignature(params map[string]string) string { +func (c *Client) generateSignature(params map[string]string) string { // Step 1: Sort parameters by ASCII order var keys []string for k := range params { @@ -109,7 +57,7 @@ func (c *GnameClient) generateSignature(params map[string]string) string { return strings.ToUpper(fmt.Sprintf("%x", hash)) } -func (c *GnameClient) sendRequest(path string, params map[string]any) (*resty.Response, error) { +func (c *Client) sendRequest(path string, params map[string]any) (*resty.Response, error) { if params == nil { params = make(map[string]any) } @@ -136,7 +84,7 @@ func (c *GnameClient) sendRequest(path string, params map[string]any) (*resty.Re return resp, nil } -func (c *GnameClient) sendRequestWithResult(path string, params map[string]any, result BaseResponse) error { +func (c *Client) sendRequestWithResult(path string, params map[string]any, result BaseResponse) error { resp, err := c.sendRequest(path, params) if err != nil { return err diff --git a/internal/pkg/vendors/gname-sdk/models.go b/internal/pkg/vendors/gname-sdk/models.go new file mode 100644 index 00000000..282439d2 --- /dev/null +++ b/internal/pkg/vendors/gname-sdk/models.go @@ -0,0 +1,79 @@ +package gnamesdk + +type BaseResponse interface { + GetCode() int + GetMsg() string +} + +type baseResponse struct { + Code int `json:"code"` + Msg string `json:"msg"` +} + +func (r *baseResponse) GetCode() int { + return r.Code +} + +func (r *baseResponse) GetMsg() string { + return r.Msg +} + +type AddDomainResolutionRequest struct { + ZoneName string `json:"ym"` + RecordType string `json:"lx"` + RecordName string `json:"zj"` + RecordValue string `json:"jlz"` + MX int `json:"mx"` + TTL int `json:"ttl"` +} + +type AddDomainResolutionResponse struct { + baseResponse + Data int `json:"data"` +} + +type ModifyDomainResolutionRequest struct { + ID string `json:"jxid"` + ZoneName string `json:"ym"` + RecordType string `json:"lx"` + RecordName string `json:"zj"` + RecordValue string `json:"jlz"` + MX int `json:"mx"` + TTL int `json:"ttl"` +} + +type ModifyDomainResolutionResponse struct { + baseResponse +} + +type DeleteDomainResolutionRequest struct { + ZoneName string `json:"ym"` + RecordID string `json:"jxid"` +} + +type DeleteDomainResolutionResponse struct { + baseResponse +} + +type ListDomainResolutionRequest struct { + ZoneName string `json:"ym"` + Page *int `json:"page,omitempty"` + PageSize *int `json:"limit,omitempty"` +} + +type ListDomainResolutionResponse struct { + baseResponse + Count int `json:"count"` + Data []*ResolutionRecord `json:"data"` + Page int `json:"page"` + PageSize int `json:"pagesize"` +} + +type ResolutionRecord struct { + ID string `json:"id"` + ZoneName string `json:"ym"` + RecordType string `json:"lx"` + RecordName string `json:"zjt"` + RecordValue string `json:"jxz"` + MX int `json:"mx"` +} diff --git a/internal/pkg/vendors/safeline-sdk/api.go b/internal/pkg/vendors/safeline-sdk/api.go index 9fbfb7c9..ae0a56d1 100644 --- a/internal/pkg/vendors/safeline-sdk/api.go +++ b/internal/pkg/vendors/safeline-sdk/api.go @@ -1,34 +1,18 @@ package safelinesdk -type BaseResponse interface { - GetErrCode() *string - GetErrMsg() *string -} +import ( + "encoding/json" +) -type baseResponse struct { - ErrCode *string `json:"err,omitempty"` - ErrMsg *string `json:"msg,omitempty"` -} +func (c *Client) UpdateCertificate(req *UpdateCertificateRequest) (*UpdateCertificateResponse, error) { + params := make(map[string]any) + jsonData, _ := json.Marshal(req) + json.Unmarshal(jsonData, ¶ms) -func (r *baseResponse) GetErrCode() *string { - return r.ErrCode -} - -func (r *baseResponse) GetErrMsg() *string { - return r.ErrMsg -} - -type UpdateCertificateRequest struct { - Id int32 `json:"id"` - Type int32 `json:"type"` - Manual *UpdateCertificateRequestBodyManul `json:"manual"` -} - -type UpdateCertificateRequestBodyManul struct { - Crt string `json:"crt"` - Key string `json:"key"` -} - -type UpdateCertificateResponse struct { - baseResponse + result := UpdateCertificateResponse{} + err := c.sendRequestWithResult("/api/open/cert", params, &result) + if err != nil { + return nil, err + } + return &result, nil } diff --git a/internal/pkg/vendors/safeline-sdk/client.go b/internal/pkg/vendors/safeline-sdk/client.go index 45ec7f51..be04cb94 100644 --- a/internal/pkg/vendors/safeline-sdk/client.go +++ b/internal/pkg/vendors/safeline-sdk/client.go @@ -9,41 +9,28 @@ import ( "github.com/go-resty/resty/v2" ) -type SafeLineClient struct { +type Client struct { apiHost string apiToken string client *resty.Client } -func NewSafeLineClient(apiHost, apiToken string) *SafeLineClient { +func NewClient(apiHost, apiToken string) *Client { client := resty.New() - return &SafeLineClient{ + return &Client{ apiHost: apiHost, apiToken: apiToken, client: client, } } -func (c *SafeLineClient) WithTimeout(timeout time.Duration) *SafeLineClient { +func (c *Client) WithTimeout(timeout time.Duration) *Client { c.client.SetTimeout(timeout) return c } -func (c *SafeLineClient) UpdateCertificate(req *UpdateCertificateRequest) (*UpdateCertificateResponse, error) { - params := make(map[string]any) - jsonData, _ := json.Marshal(req) - json.Unmarshal(jsonData, ¶ms) - - result := UpdateCertificateResponse{} - err := c.sendRequestWithResult("/api/open/cert", params, &result) - if err != nil { - return nil, err - } - return &result, nil -} - -func (c *SafeLineClient) sendRequest(path string, params map[string]any) (*resty.Response, error) { +func (c *Client) sendRequest(path string, params map[string]any) (*resty.Response, error) { if params == nil { params = make(map[string]any) } @@ -65,7 +52,7 @@ func (c *SafeLineClient) sendRequest(path string, params map[string]any) (*resty return resp, nil } -func (c *SafeLineClient) sendRequestWithResult(path string, params map[string]any, result BaseResponse) error { +func (c *Client) sendRequestWithResult(path string, params map[string]any, result BaseResponse) error { resp, err := c.sendRequest(path, params) if err != nil { return err diff --git a/internal/pkg/vendors/safeline-sdk/models.go b/internal/pkg/vendors/safeline-sdk/models.go new file mode 100644 index 00000000..9fbfb7c9 --- /dev/null +++ b/internal/pkg/vendors/safeline-sdk/models.go @@ -0,0 +1,34 @@ +package safelinesdk + +type BaseResponse interface { + GetErrCode() *string + GetErrMsg() *string +} + +type baseResponse struct { + ErrCode *string `json:"err,omitempty"` + ErrMsg *string `json:"msg,omitempty"` +} + +func (r *baseResponse) GetErrCode() *string { + return r.ErrCode +} + +func (r *baseResponse) GetErrMsg() *string { + return r.ErrMsg +} + +type UpdateCertificateRequest struct { + Id int32 `json:"id"` + Type int32 `json:"type"` + Manual *UpdateCertificateRequestBodyManul `json:"manual"` +} + +type UpdateCertificateRequestBodyManul struct { + Crt string `json:"crt"` + Key string `json:"key"` +} + +type UpdateCertificateResponse struct { + baseResponse +} diff --git a/ui/public/imgs/providers/baishan.png b/ui/public/imgs/providers/baishan.png new file mode 100644 index 0000000000000000000000000000000000000000..af1e555da93f0418d1e5678ea3adaa817b010f82 GIT binary patch literal 2565 zcmaJ@dpwi-AAitTmNdz&4l^qKWY0Dmwn*5PmElMzGP6Bc+NEu5Imy~NhbW~^2dB$% z=}P2MiqxW0gz}q8Dxz8>DJ10l`Qu6T_g!nCZ=nwW zfC1f`5};Yv%)D@2&9{)dy;HN8OQ<1|4T30%lqG@y4~`%bLeY7wXea<;advEPfLsAU zXBjszL=wXAA+rTM3~L61k@18YHUPM~%Y-a;EF?iiLeX5l8+xGnIvU00xS@lI3@k(F z1;uc^6GYI41m8e*LM)raLA$R;xyr~I0Ujh_p=7*md@)((hW?^U*6e4lK{Vag0ES z!V@q~D7#=TpCgcpS9~Eb7-TwMEMf845S`+N)<|HuTn^cbfF;rhPDCmNN5$c&G*3rI ziU)y6#d{J7L}wadmP-+^<9HBXGRx)s!*%*DcV--TLQP}}B;v+H9GXbLLw(7a%>BL> z$M5QW<#N97h45W2s4)Z1boReGJ$t1YpPB8q(bXKj4L`)!OuR@l+WUWgY779nade7D zpzKNi(NLc-s#$$>^QMTb?x1-hg!M>}*TUEn0R~zMxm`uEO5bx+Zn~fHks>{DuvX7% zt9RKli>`}%j6nz6&MG=QuZ6a7WVh^GD()h@H6Wtu9ZBt+!Z>;N-LZlG=1#>c$a>YP zpPG}DO#`S>UlpY6ztMC8_eT40X-{s@-a|%f+hgK=^fNk~b{b}fvNApv8YLF5SOyDe zt1vMi?)~Lr-7z5NQ;A~aw*>l+=TK$5-l=S(-1u!phmrATipB_A+>JspHG9@?#X?2r zE7h@~K5$`Mft8vy65HKJFIQIMr)55HEYa<=afj$g|Bkr2Fr2mAH)KQ1)wKR@j(MxL zi{JdN`Cw~as{Ng+t5+m;g)miSMf5z`+}2y(8v+qPEqGF;J)A{)qC1=)0PI%|malry z9(=lqQFd=m#;;1ay~~m~ZL{9>w^>Feu#nyA(Fj)H+=yI|J!b1;irq~p;~nZZdYg6l z-euI8k_lRPx#@)z`E~<&-COl?%a4>Wc~RCfqY`jszADRzd_{D+kCZgfo?}%x4=k~H zu_oCx-95b$(GenXPo*)}buPSCOn&gGmU2;;Uxu!=I)LUS-8z^d3n$!6ER596l$xd1 zO+dNZ{bwA}Vf>+n`ZlJ+pU&5;*LBgNbSB<61|(8or3&R>#MA8U1$5uRSaOP_Aajp? zjU6ei+K)W3#SM@K^aR3Y42i6HygCe!mLgUJmYh0Fr8_4S)!(;3 zYPlXso{HS~V`mv&%H+N_8@yrVVvjOlnaWRqb1G<@4>@6dMU$P4ldZ(LlaqydulKA{ zc&O!b&YD}<>rFRN$CLa}UC1+Mw~W5^c-B5BpOZ_r^gJ6`o8!C%aeUEr`Qk9o{L#EM z=jt+H&w3FbcP!YeY&w46v-wTS6MD}3pq;BKO2L)dcO0(d^o)>BPD>A>FtIU3)i=<< zXsFKn=URzBe6EE@W{}c5iQxe!euNv@WZB$iq;&=9ftWq>l(rGfzY4zCV;(lbKiPNf1v>C zJr?Q8i=niNp6k_tEd__SK2%t51{iIN%h+0p|3;<;GwBUf?}Ds@1sjyW61?3d?S;U2 zzRIl1;{}mAF_eey@32d_LLf4m&EW;To9=|)Fr412s+2N@ukJ$xSul&{K1krbJ38F9 zJjUHgrK7e$o-0|Q{}hw&ekn0{(&u3xarEKKqaDfr>NYoBe%**+_-V-C{7_nRHxwQH z9_X|2-z?Sw$1T^4ca@rtH@_^hx;paQdG%IHc8y_1`_@dSk+#;vfJphG4=_X@(b?~F zX-;C|)2>TJwk>Pb>Ia4-R{qsB^{2KCqi%;F@S|1t4;`~gP44i%`|9lG?w{i5<$wez;ZOgNX4WDnF^89d|(NuNxj}L~z zH!A7L2kR+nPeGR=PU~uKs2nl%^4KQJHbg)UHOgo>o2`|8cihBSYdpW&kyn`TaLG=g zZ9_3<^WBaW`<9k$^v!KCa}p|R*4x$SjvH-zuGahXI*s0vkwT8o@;Ksk`PzNA*LUH1 z1GFn1s|T2+wt#y=Pn;9S@-2?Jagx?JF*hrwbsw@&0bbH~@=hBVw@6T*KrRiJy}bK8 z*=v7A`QnD2ARCLnlGf?eO0_>t7G+)@%%AgYZS!QW`2i&qO!ac<81-Zhzd)=~jPByJ zEK)s+c}|5#NZ9zO`qnoK);@+;4zYFh?x`n17HX1C~0&oo{bl>MjotybF Nqf>n;=RG47{{d1>M6dt= literal 0 HcmV?d00001 diff --git a/ui/src/components/access/AccessForm.tsx b/ui/src/components/access/AccessForm.tsx index 71aa3fba..e10d2a89 100644 --- a/ui/src/components/access/AccessForm.tsx +++ b/ui/src/components/access/AccessForm.tsx @@ -14,6 +14,7 @@ import AccessFormAliyunConfig from "./AccessFormAliyunConfig"; import AccessFormAWSConfig from "./AccessFormAWSConfig"; import AccessFormAzureConfig from "./AccessFormAzureConfig"; import AccessFormBaiduCloudConfig from "./AccessFormBaiduCloudConfig"; +import AccessFormBaishanConfig from "./AccessFormBaishanConfig"; import AccessFormBaotaPanelConfig from "./AccessFormBaotaPanelConfig"; import AccessFormBytePlusConfig from "./AccessFormBytePlusConfig"; import AccessFormCloudflareConfig from "./AccessFormCloudflareConfig"; @@ -101,6 +102,8 @@ const AccessForm = forwardRef(({ className, return ; case ACCESS_PROVIDERS.BAIDUCLOUD: return ; + case ACCESS_PROVIDERS.BAISHAN: + return ; case ACCESS_PROVIDERS.BAOTAPANEL: return ; case ACCESS_PROVIDERS.BYTEPLUS: diff --git a/ui/src/components/access/AccessFormBaishanConfig.tsx b/ui/src/components/access/AccessFormBaishanConfig.tsx new file mode 100644 index 00000000..0450d9cd --- /dev/null +++ b/ui/src/components/access/AccessFormBaishanConfig.tsx @@ -0,0 +1,56 @@ +import { useTranslation } from "react-i18next"; +import { Form, type FormInstance, Input } from "antd"; +import { createSchemaFieldRule } from "antd-zod"; +import { z } from "zod"; + +import { type AccessConfigForBaishan } from "@/domain/access"; + +type AccessFormBaishanConfigFieldValues = Nullish; + +export type AccessFormBaishanConfigProps = { + form: FormInstance; + formName: string; + disabled?: boolean; + initialValues?: AccessFormBaishanConfigFieldValues; + onValuesChange?: (values: AccessFormBaishanConfigFieldValues) => void; +}; + +const initFormModel = (): AccessFormBaishanConfigFieldValues => { + return { + apiToken: "", + }; +}; + +const AccessFormBaishanConfig = ({ form: formInst, formName, disabled, initialValues, onValuesChange }: AccessFormBaishanConfigProps) => { + const { t } = useTranslation(); + + const formSchema = z.object({ + apiToken: z + .string() + .min(1, t("access.form.baishan_api_token.placeholder")) + .max(64, t("common.errmsg.string_max", { max: 64 })) + .trim(), + }); + const formRule = createSchemaFieldRule(formSchema); + + const handleFormChange = (_: unknown, values: z.infer) => { + onValuesChange?.(values); + }; + + return ( +
+ + + +
+ ); +}; + +export default AccessFormBaishanConfig; diff --git a/ui/src/components/workflow/node/DeployNodeConfigForm.tsx b/ui/src/components/workflow/node/DeployNodeConfigForm.tsx index 8cbc8c57..50faa78b 100644 --- a/ui/src/components/workflow/node/DeployNodeConfigForm.tsx +++ b/ui/src/components/workflow/node/DeployNodeConfigForm.tsx @@ -27,6 +27,7 @@ import DeployNodeConfigFormAliyunOSSConfig from "./DeployNodeConfigFormAliyunOSS import DeployNodeConfigFormAliyunWAFConfig from "./DeployNodeConfigFormAliyunWAFConfig"; import DeployNodeConfigFormAWSCloudFrontConfig from "./DeployNodeConfigFormAWSCloudFrontConfig"; import DeployNodeConfigFormBaiduCloudCDNConfig from "./DeployNodeConfigFormBaiduCloudCDNConfig"; +import DeployNodeConfigFormBaishanCDNConfig from "./DeployNodeConfigFormBaishanCDNConfig"; import DeployNodeConfigFormBaotaPanelConsoleConfig from "./DeployNodeConfigFormBaotaPanelConsoleConfig"; import DeployNodeConfigFormBaotaPanelSiteConfig from "./DeployNodeConfigFormBaotaPanelSiteConfig"; import DeployNodeConfigFormBytePlusCDNConfig from "./DeployNodeConfigFormBytePlusCDNConfig"; @@ -154,6 +155,8 @@ const DeployNodeConfigForm = forwardRef; case DEPLOY_PROVIDERS.BAIDUCLOUD_CDN: return ; + case DEPLOY_PROVIDERS.BAISHAN_CDN: + return ; case DEPLOY_PROVIDERS.BAOTAPANEL_CONSOLE: return ; case DEPLOY_PROVIDERS.BAOTAPANEL_SITE: diff --git a/ui/src/components/workflow/node/DeployNodeConfigFormBaishanCDNConfig.tsx b/ui/src/components/workflow/node/DeployNodeConfigFormBaishanCDNConfig.tsx new file mode 100644 index 00000000..828d5845 --- /dev/null +++ b/ui/src/components/workflow/node/DeployNodeConfigFormBaishanCDNConfig.tsx @@ -0,0 +1,65 @@ +import { useTranslation } from "react-i18next"; +import { Form, type FormInstance, Input } from "antd"; +import { createSchemaFieldRule } from "antd-zod"; +import { z } from "zod"; + +import { validDomainName } from "@/utils/validators"; + +type DeployNodeConfigFormBaishanCDNConfigFieldValues = Nullish<{ + domain: string; +}>; + +export type DeployNodeConfigFormBaishanCDNConfigProps = { + form: FormInstance; + formName: string; + disabled?: boolean; + initialValues?: DeployNodeConfigFormBaishanCDNConfigFieldValues; + onValuesChange?: (values: DeployNodeConfigFormBaishanCDNConfigFieldValues) => void; +}; + +const initFormModel = (): DeployNodeConfigFormBaishanCDNConfigFieldValues => { + return {}; +}; + +const DeployNodeConfigFormBaishanCDNConfig = ({ + form: formInst, + formName, + disabled, + initialValues, + onValuesChange, +}: DeployNodeConfigFormBaishanCDNConfigProps) => { + const { t } = useTranslation(); + + const formSchema = z.object({ + domain: z + .string({ message: t("workflow_node.deploy.form.baishan_cdn_domain.placeholder") }) + .refine((v) => validDomainName(v, { allowWildcard: true }), t("common.errmsg.domain_invalid")), + }); + const formRule = createSchemaFieldRule(formSchema); + + const handleFormChange = (_: unknown, values: z.infer) => { + onValuesChange?.(values); + }; + + return ( +
+ } + > + + +
+ ); +}; + +export default DeployNodeConfigFormBaishanCDNConfig; diff --git a/ui/src/domain/access.ts b/ui/src/domain/access.ts index d8a64dd4..548716b4 100644 --- a/ui/src/domain/access.ts +++ b/ui/src/domain/access.ts @@ -11,6 +11,7 @@ export interface AccessModel extends BaseModel { | AccessConfigForAWS | AccessConfigForAzure | AccessConfigForBaiduCloud + | AccessConfigForBaishan | AccessConfigForBaotaPanel | AccessConfigForBytePlus | AccessConfigForCloudflare @@ -67,6 +68,10 @@ export type AccessConfigForBaiduCloud = { secretAccessKey: string; }; +export type AccessConfigForBaishan = { + apiToken: string; +}; + export type AccessConfigForBaotaPanel = { apiUrl: string; apiKey: string; diff --git a/ui/src/domain/provider.ts b/ui/src/domain/provider.ts index d68e5210..75b954eb 100644 --- a/ui/src/domain/provider.ts +++ b/ui/src/domain/provider.ts @@ -9,6 +9,7 @@ export const ACCESS_PROVIDERS = Object.freeze({ AWS: "aws", AZURE: "azure", BAIDUCLOUD: "baiducloud", + BAISHAN: "baishan", BAOTAPANEL: "baotapanel", BYTEPLUS: "byteplus", CLOUDFLARE: "cloudflare", @@ -68,6 +69,7 @@ export const accessProvidersMap: Maphttps://intl.cloud.baidu.com/doc/Reference/s/jjwvz2e3p-en", + "access.form.baishan_api_token.label": "Baishan Cloud API token", + "access.form.baishan_api_token.placeholder": "Please enter Baishan Cloud API token", "access.form.baotapanel_api_url.label": "BaoTa Panel URL", "access.form.baotapanel_api_url.placeholder": "Please enter BaoTa Panel URL", "access.form.baotapanel_api_url.tooltip": "For more information, see https://www.bt.cn/bbs/thread-20376-1-1.html", diff --git a/ui/src/i18n/locales/en/nls.workflow.nodes.json b/ui/src/i18n/locales/en/nls.workflow.nodes.json index 360a0607..dbfded50 100644 --- a/ui/src/i18n/locales/en/nls.workflow.nodes.json +++ b/ui/src/i18n/locales/en/nls.workflow.nodes.json @@ -190,6 +190,9 @@ "workflow_node.deploy.form.baiducloud_cdn_domain.label": "Baidu Cloud CDN domain", "workflow_node.deploy.form.baiducloud_cdn_domain.placeholder": "Please enter Baidu Cloud CDN domain name", "workflow_node.deploy.form.baiducloud_cdn_domain.tooltip": "For more information, see https://console.bce.baidu.com/cdn", + "workflow_node.deploy.form.baishan_cdn_domain.label": "Baishan CDN domain", + "workflow_node.deploy.form.baishan_cdn_domain.placeholder": "Please enter Baishan CDN domain name", + "workflow_node.deploy.form.baishan_cdn_domain.tooltip": "For more information, see https://cdnx.console.baishan.com", "workflow_node.deploy.form.baotapanel_console_auto_restart.label": "Auto restart after deployment", "workflow_node.deploy.form.baotapanel_site_name.label": "BaoTa Panel site name", "workflow_node.deploy.form.baotapanel_site_name.placeholder": "Please enter BaoTa Panel site name", diff --git a/ui/src/i18n/locales/zh/nls.access.json b/ui/src/i18n/locales/zh/nls.access.json index 586af5f3..cca17a8d 100644 --- a/ui/src/i18n/locales/zh/nls.access.json +++ b/ui/src/i18n/locales/zh/nls.access.json @@ -65,6 +65,8 @@ "access.form.baiducloud_secret_access_key.label": "百度智能云 SecretAccessKey", "access.form.baiducloud_secret_access_key.placeholder": "请输入百度智能云 SecretAccessKey", "access.form.baiducloud_secret_access_key.tooltip": "这是什么?请参阅 https://cloud.baidu.com/doc/Reference/s/jjwvz2e3p", + "access.form.baishan_api_token.label": "白山云 API Token", + "access.form.baishan_api_token.placeholder": "请输入白山云 API Token", "access.form.baotapanel_api_url.label": "宝塔面板 URL", "access.form.baotapanel_api_url.placeholder": "请输入宝塔面板 URL", "access.form.baotapanel_api_url.tooltip": "这是什么?请参阅 https://www.bt.cn/bbs/thread-20376-1-1.html", diff --git a/ui/src/i18n/locales/zh/nls.workflow.nodes.json b/ui/src/i18n/locales/zh/nls.workflow.nodes.json index 7fe81657..2a0f2313 100644 --- a/ui/src/i18n/locales/zh/nls.workflow.nodes.json +++ b/ui/src/i18n/locales/zh/nls.workflow.nodes.json @@ -137,10 +137,10 @@ "workflow_node.deploy.form.aliyun_clb_snidomain.tooltip": "这是什么?请参阅 https://slb.console.aliyun.com/clb

不填写时,将替换监听器的默认证书。", "workflow_node.deploy.form.aliyun_cdn_domain.label": "阿里云 CDN 加速域名(支持泛域名)", "workflow_node.deploy.form.aliyun_cdn_domain.placeholder": "请输入阿里云 CDN 加速域名", - "workflow_node.deploy.form.aliyun_cdn_domain.tooltip": "这是什么?请参阅 https://cdn.console.aliyun.com

泛域名表示形式为:*.example.com", + "workflow_node.deploy.form.aliyun_cdn_domain.tooltip": "这是什么?请参阅 https://cdn.console.aliyun.com", "workflow_node.deploy.form.aliyun_dcdn_domain.label": "阿里云 DCDN 加速域名(支持泛域名)", "workflow_node.deploy.form.aliyun_dcdn_domain.placeholder": "请输入阿里云 DCDN 加速域名", - "workflow_node.deploy.form.aliyun_dcdn_domain.tooltip": "这是什么?请参阅 https://dcdn.console.aliyun.com

泛域名表示形式为:*.example.com", + "workflow_node.deploy.form.aliyun_dcdn_domain.tooltip": "这是什么?请参阅 https://dcdn.console.aliyun.com", "workflow_node.deploy.form.aliyun_esa_region.label": "阿里云 ESA 服务地域", "workflow_node.deploy.form.aliyun_esa_region.placeholder": "请输入阿里云 ESA 服务地域(例如:cn-hangzhou)", "workflow_node.deploy.form.aliyun_esa_region.tooltip": "这是什么?请参阅 https://help.aliyun.com/zh/edge-security-acceleration/esa/api-esa-2024-09-10-endpoint", @@ -189,14 +189,17 @@ "workflow_node.deploy.form.aws_cloudfront_distribution_id.tooltip": "这是什么?请参阅 https://docs.aws.amazon.com/zh_cn/AmazonCloudFront/latest/DeveloperGuide/distribution-working-with.html", "workflow_node.deploy.form.baiducloud_cdn_domain.label": "百度智能云 CDN 加速域名(支持泛域名)", "workflow_node.deploy.form.baiducloud_cdn_domain.placeholder": "请输入百度智能云 CDN 加速域名", - "workflow_node.deploy.form.baiducloud_cdn_domain.tooltip": "这是什么?请参阅 https://console.bce.baidu.com/cdn

泛域名表示形式为:*.example.com", + "workflow_node.deploy.form.baiducloud_cdn_domain.tooltip": "这是什么?请参阅 https://console.bce.baidu.com/cdn", + "workflow_node.deploy.form.baishan_cdn_domain.label": "白山云 CDN 加速域名(支持泛域名)", + "workflow_node.deploy.form.baishan_cdn_domain.placeholder": "请输入白山云 CDN 加速域名", + "workflow_node.deploy.form.baishan_cdn_domain.tooltip": "这是什么?请参阅 https://cdnx.console.baishan.com", "workflow_node.deploy.form.baotapanel_console_auto_restart.label": "部署后自动重启面板服务", "workflow_node.deploy.form.baotapanel_site_name.label": "宝塔面板网站名称", "workflow_node.deploy.form.baotapanel_site_name.placeholder": "请输入宝塔面板网站名称", "workflow_node.deploy.form.baotapanel_site_name.tooltip": "通常为网站域名。", "workflow_node.deploy.form.byteplus_cdn_domain.label": "BytePlus CDN 域名(支持泛域名)", "workflow_node.deploy.form.byteplus_cdn_domain.placeholder": "请输入 BytePlus CDN 域名", - "workflow_node.deploy.form.byteplus_cdn_domain.tooltip": "这是什么?请参阅 https://console.byteplus.com/cdn

泛域名表示形式为:*.example.com", + "workflow_node.deploy.form.byteplus_cdn_domain.tooltip": "这是什么?请参阅 https://console.byteplus.com/cdn", "workflow_node.deploy.form.dogecloud_cdn_domain.label": "多吉云 CDN 加速域名", "workflow_node.deploy.form.dogecloud_cdn_domain.placeholder": "请输入多吉云 CDN 加速域名", "workflow_node.deploy.form.dogecloud_cdn_domain.tooltip": "这是什么?请参阅 https://console.dogecloud.com", @@ -293,7 +296,7 @@ "workflow_node.deploy.form.local_preset_scripts.option.binding_netsh.label": "PowerShell - 导入并绑定到 netsh(需管理员权限)", "workflow_node.deploy.form.qiniu_cdn_domain.label": "七牛云 CDN 加速域名(支持泛域名)", "workflow_node.deploy.form.qiniu_cdn_domain.placeholder": "请输入七牛云 CDN 加速域名", - "workflow_node.deploy.form.qiniu_cdn_domain.tooltip": "这是什么?请参阅 https://portal.qiniu.com/cdn

泛域名表示形式为:*.example.com", + "workflow_node.deploy.form.qiniu_cdn_domain.tooltip": "这是什么?请参阅 https://portal.qiniu.com/cdn", "workflow_node.deploy.form.qiniu_pili_hub.label": "七牛云视频直播空间名", "workflow_node.deploy.form.qiniu_pili_hub.placeholder": "请输入七牛云视频直播空间名", "workflow_node.deploy.form.qiniu_pili_hub.tooltip": "这是什么?请参阅 https://portal.qiniu.com/hub", @@ -340,7 +343,7 @@ "workflow_node.deploy.form.ssh_use_scp.tooltip": "如果你的远程服务器不支持 SFTP,请开启此选项回退为 SCP。", "workflow_node.deploy.form.tencentcloud_cdn_domain.label": "腾讯云 CDN 加速域名(支持泛域名)", "workflow_node.deploy.form.tencentcloud_cdn_domain.placeholder": "请输入腾讯云 CDN 加速域名", - "workflow_node.deploy.form.tencentcloud_cdn_domain.tooltip": "这是什么?请参阅 https://console.cloud.tencent.com/cdn

泛域名表示形式为:*.example.com", + "workflow_node.deploy.form.tencentcloud_cdn_domain.tooltip": "这是什么?请参阅 https://console.cloud.tencent.com/cdn", "workflow_node.deploy.form.tencentcloud_clb_resource_type.label": "证书替换方式", "workflow_node.deploy.form.tencentcloud_clb_resource_type.placeholder": "请选择证书替换方式", "workflow_node.deploy.form.tencentcloud_clb_resource_type.option.ssl_deploy.label": "通过 SSL 服务部署到云资源实例", @@ -376,7 +379,7 @@ "workflow_node.deploy.form.tencentcloud_css_domain.tooltip": "这是什么?请参阅 https://console.cloud.tencent.com/live/livestat", "workflow_node.deploy.form.tencentcloud_ecdn_domain.label": "腾讯云 ECDN 加速域名(支持泛域名)", "workflow_node.deploy.form.tencentcloud_ecdn_domain.placeholder": "请输入腾讯云 ECDN 加速域名", - "workflow_node.deploy.form.tencentcloud_ecdn_domain.tooltip": "这是什么?请参阅 https://console.cloud.tencent.com/cdn

泛域名表示形式为:*.example.com", + "workflow_node.deploy.form.tencentcloud_ecdn_domain.tooltip": "这是什么?请参阅 https://console.cloud.tencent.com/cdn", "workflow_node.deploy.form.tencentcloud_eo_zone_id.label": "腾讯云 EdgeOne 站点 ID", "workflow_node.deploy.form.tencentcloud_eo_zone_id.placeholder": "请输入腾讯云 EdgeOne 站点 ID", "workflow_node.deploy.form.tencentcloud_eo_zone_id.tooltip": "这是什么?请参阅 https://console.cloud.tencent.com/edgeone", @@ -422,7 +425,7 @@ "workflow_node.deploy.form.ucloud_us3_domain.tooltip": "这是什么?请参阅 https://console.ucloud.cn/ufile", "workflow_node.deploy.form.volcengine_cdn_domain.label": "火山引擎 CDN 加速域名(支持泛域名)", "workflow_node.deploy.form.volcengine_cdn_domain.placeholder": "请输入火山引擎 CDN 加速域名", - "workflow_node.deploy.form.volcengine_cdn_domain.tooltip": "这是什么?请参阅 https://console.volcengine.com/cdn/homepage

泛域名表示形式为:*.example.com", + "workflow_node.deploy.form.volcengine_cdn_domain.tooltip": "这是什么?请参阅 https://console.volcengine.com/cdn/homepage", "workflow_node.deploy.form.volcengine_clb_resource_type.label": "证书替换方式", "workflow_node.deploy.form.volcengine_clb_resource_type.placeholder": "请选择证书替换方式", "workflow_node.deploy.form.volcengine_clb_resource_type.option.listener.label": "替换指定监听器的证书", @@ -434,7 +437,7 @@ "workflow_node.deploy.form.volcengine_clb_listener_id.tooltip": "这是什么?请参阅 https://console.volcengine.com/clb/LoadBalancer", "workflow_node.deploy.form.volcengine_dcdn_domain.label": "火山引擎 DCDN 加速域名(支持泛域名)", "workflow_node.deploy.form.volcengine_dcdn_domain.placeholder": "请输入火山引擎 DCDN 加速域名", - "workflow_node.deploy.form.volcengine_dcdn_domain.tooltip": "这是什么?请参阅 https://console.volcengine.com/dcdn/dashboard

泛域名表示形式为:*.example.com", + "workflow_node.deploy.form.volcengine_dcdn_domain.tooltip": "这是什么?请参阅 https://console.volcengine.com/dcdn/dashboard", "workflow_node.deploy.form.volcengine_imagex_region.label": "火山引擎 ImageX 服务地域", "workflow_node.deploy.form.volcengine_imagex_region.placeholder": "请输入火山引擎 ImageX 服务地域(例如:cn-north-1)", "workflow_node.deploy.form.volcengine_imagex_region.tooltip": "这是什么?请参阅 https://www.volcengine.com/docs/508/23757", @@ -446,7 +449,7 @@ "workflow_node.deploy.form.volcengine_imagex_domain.tooltip": "这是什么?请参阅 see https://console.volcengine.com/imagex", "workflow_node.deploy.form.volcengine_live_domain.label": "火山引擎视频直播流域名(支持泛域名)", "workflow_node.deploy.form.volcengine_live_domain.placeholder": "请输入火山引擎视频直播流域名", - "workflow_node.deploy.form.volcengine_live_domain.tooltip": "这是什么?请参阅 https://console.volcengine.com/live

泛域名表示形式为:*.example.com", + "workflow_node.deploy.form.volcengine_live_domain.tooltip": "这是什么?请参阅 https://console.volcengine.com/live", "workflow_node.deploy.form.volcengine_tos_region.label": "火山引擎 TOS 服务地域", "workflow_node.deploy.form.volcengine_tos_region.placeholder": "请输入火山引擎 TOS 服务地域(例如:cn-beijing)", "workflow_node.deploy.form.volcengine_tos_region.tooltip": "这是什么?请参阅 https://www.volcengine.com/docs/6349/107356", From e2a148c25f22aef5764586b2cc6f31205a1306b4 Mon Sep 17 00:00:00 2001 From: Fu Diwei Date: Mon, 17 Feb 2025 20:48:32 +0800 Subject: [PATCH 08/34] feat: add gcore dns-01 applicant --- README.md | 1 + README_EN.md | 1 + internal/applicant/providers.go | 16 +++++ internal/domain/access.go | 4 ++ internal/domain/provider.go | 3 +- .../acme-dns-01/lego-providers/gcore/gcore.go | 37 +++++++++++ ui/public/imgs/providers/gcore.png | Bin 0 -> 8101 bytes ui/src/components/access/AccessForm.tsx | 3 + .../access/AccessFormGcoreConfig.tsx | 61 ++++++++++++++++++ ui/src/domain/access.ts | 5 ++ ui/src/domain/provider.ts | 4 ++ ui/src/i18n/locales/en/nls.access.json | 3 + ui/src/i18n/locales/zh/nls.access.json | 3 + 13 files changed, 140 insertions(+), 1 deletion(-) create mode 100644 internal/pkg/core/applicant/acme-dns-01/lego-providers/gcore/gcore.go create mode 100644 ui/public/imgs/providers/gcore.png create mode 100644 ui/src/components/access/AccessFormGcoreConfig.tsx diff --git a/README.md b/README.md index 32b5ce17..1768b501 100644 --- a/README.md +++ b/README.md @@ -96,6 +96,7 @@ make local.run | [Azure](https://azure.microsoft.com/) | | | [CloudFlare](https://www.cloudflare.com/) | | | [ClouDNS](https://www.cloudns.net//) | | +| [Gcore](https://gcore.com/) | | | [GNAME](https://www.gname.com/) | | | [GoDaddy](https://www.godaddy.com/) | | | [Name.com](https://www.name.com/) | | diff --git a/README_EN.md b/README_EN.md index 1966512b..a13509a8 100644 --- a/README_EN.md +++ b/README_EN.md @@ -95,6 +95,7 @@ The following DNS providers are supported: | [Azure DNS](https://azure.microsoft.com/) | | | [CloudFlare](https://www.cloudflare.com/) | | | [ClouDNS](https://www.cloudns.net//) | | +| [Gcore](https://gcore.com/) | | | [GNAME](https://www.gname.com/) | | | [GoDaddy](https://www.godaddy.com/) | | | [Name.com](https://www.name.com/) | | diff --git a/internal/applicant/providers.go b/internal/applicant/providers.go index 1866637e..6c89b794 100644 --- a/internal/applicant/providers.go +++ b/internal/applicant/providers.go @@ -12,6 +12,7 @@ import ( pAzureDNS "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/azure-dns" pCloudflare "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/cloudflare" pClouDNS "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/cloudns" + pGcore "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/gcore" pGname "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/gname" pGoDaddy "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/godaddy" pHuaweiCloud "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/huaweicloud" @@ -132,6 +133,21 @@ func createApplicant(options *applicantOptions) (challenge.Provider, error) { return applicant, err } + case domain.ApplyDNSProviderTypeGcore: + { + access := domain.AccessConfigForGcore{} + if err := maps.Populate(options.ProviderAccessConfig, &access); err != nil { + return nil, fmt.Errorf("failed to populate provider access config: %w", err) + } + + applicant, err := pGcore.NewChallengeProvider(&pGcore.GcoreApplicantConfig{ + ApiToken: access.ApiToken, + DnsPropagationTimeout: options.DnsPropagationTimeout, + DnsTTL: options.DnsTTL, + }) + return applicant, err + } + case domain.ApplyDNSProviderTypeGname: { access := domain.AccessConfigForGname{} diff --git a/internal/domain/access.go b/internal/domain/access.go index d4f4f714..4136a276 100644 --- a/internal/domain/access.go +++ b/internal/domain/access.go @@ -86,6 +86,10 @@ type AccessConfigForEdgio struct { ClientSecret string `json:"clientSecret"` } +type AccessConfigForGcore struct { + ApiToken string `json:"apiToken"` +} + type AccessConfigForGname struct { AppId string `json:"appId"` AppKey string `json:"appKey"` diff --git a/internal/domain/provider.go b/internal/domain/provider.go index 70b90af5..8fe8da0f 100644 --- a/internal/domain/provider.go +++ b/internal/domain/provider.go @@ -30,7 +30,7 @@ const ( AccessProviderTypeEdgio = AccessProviderType("edgio") AccessProviderTypeFastly = AccessProviderType("fastly") // Fastly(预留) AccessProviderTypeGname = AccessProviderType("gname") - AccessProviderTypeGcore = AccessProviderType("gcore") // Gcore(预留) + AccessProviderTypeGcore = AccessProviderType("gcore") AccessProviderTypeGoDaddy = AccessProviderType("godaddy") AccessProviderTypeGoEdge = AccessProviderType("goedge") // GoEdge(预留) AccessProviderTypeHuaweiCloud = AccessProviderType("huaweicloud") @@ -69,6 +69,7 @@ const ( ApplyDNSProviderTypeAzureDNS = ApplyDNSProviderType("azure-dns") ApplyDNSProviderTypeCloudflare = ApplyDNSProviderType("cloudflare") ApplyDNSProviderTypeClouDNS = ApplyDNSProviderType("cloudns") + ApplyDNSProviderTypeGcore = ApplyDNSProviderType("gcore") ApplyDNSProviderTypeGname = ApplyDNSProviderType("gname") ApplyDNSProviderTypeGoDaddy = ApplyDNSProviderType("godaddy") ApplyDNSProviderTypeHuaweiCloud = ApplyDNSProviderType("huaweicloud") // 兼容旧值,等同于 [ApplyDNSProviderTypeHuaweiCloudDNS] diff --git a/internal/pkg/core/applicant/acme-dns-01/lego-providers/gcore/gcore.go b/internal/pkg/core/applicant/acme-dns-01/lego-providers/gcore/gcore.go new file mode 100644 index 00000000..1179d95d --- /dev/null +++ b/internal/pkg/core/applicant/acme-dns-01/lego-providers/gcore/gcore.go @@ -0,0 +1,37 @@ +package gcore + +import ( + "errors" + "time" + + "github.com/go-acme/lego/v4/challenge" + "github.com/go-acme/lego/v4/providers/dns/gcore" +) + +type GcoreApplicantConfig struct { + ApiToken string `json:"apiToken"` + DnsPropagationTimeout int32 `json:"dnsPropagationTimeout,omitempty"` + DnsTTL int32 `json:"dnsTTL,omitempty"` +} + +func NewChallengeProvider(config *GcoreApplicantConfig) (challenge.Provider, error) { + if config == nil { + return nil, errors.New("config is nil") + } + + providerConfig := gcore.NewDefaultConfig() + providerConfig.APIToken = config.ApiToken + if config.DnsPropagationTimeout != 0 { + providerConfig.PropagationTimeout = time.Duration(config.DnsPropagationTimeout) * time.Second + } + if config.DnsTTL != 0 { + providerConfig.TTL = int(config.DnsTTL) + } + + provider, err := gcore.NewDNSProviderConfig(providerConfig) + if err != nil { + return nil, err + } + + return provider, nil +} diff --git a/ui/public/imgs/providers/gcore.png b/ui/public/imgs/providers/gcore.png new file mode 100644 index 0000000000000000000000000000000000000000..3808329abe3cc982de7bfe21486b5e9c2c288986 GIT binary patch literal 8101 zcmaKRcUV(P*Y8dU5I7(KL{L;hZ_-QX3B4CViWKQhN|0WY2uSZ$lqS`J6h%4&1q4*2 zNe4j$0qGq=yYYPQdB6L|J$FA(p6pqBmEX*)J+s$uVh!}vsVT2f0sug*si9&B03g(# zAC!zJ=}RenN&LI&t7_(Jgm&@`u=REX6dllZj&My6TW3c@M_Y%W2fdDR06@a!ddJMy zOjk$79_=A$`$tDG(8G&p4FGb;KrdT+H%DK%oujj>r##zcGoB6Z>LAZ%DxoW^>!s}I z;;Iqs?PwINcgH^1&0gAp4XFT^3zQ)`@No3Cg$H`Ld-})(%Cr6LSB7~1M=Zn!|69e^ zO`h$4K$+gj+E@ZtU2Kv!2r)6>V-*3;fm zQ$?PQ=t9ud)j>u|L`?}HDIu<^BB~@JqN=8-DygO@Es0PRkx&v*RuTWlRt0VE=i%t- z`;V=||Jq9YtL>k3@bDr=R&n%p^>=ho^G18X|L(Jl>%U_W{a1hgv32-&EMos^D?|h% z^k-)OubKWwL`quribG}@=VE*^dYjlxADR*zjUL&oJH{Em$+o> zp`~17v&I|w=0~=ZEp!mjD2F8fjnsyp=GiB{NQFoa2jg81RUX zVNPP)+b7 znQ~%3#TS3Gp&-z5$9nz;-%`KqJ>hK1d|;UI;$$>kDXvC`_cbjXO!Yc4^ZDkdu1Z;9&RiErOxPg=L7LokMrpB0b?U(aPOi^Q3W2W21zT z;lrvIv!y6&+>x(T7Gfs@qXLNmjJ1T?R?m0Xo6QeRbTY?!;Y2sNNnlBKrCU9=_H(SR$dVS>T8j?~g z(0l}ifhsu^m}#_iLhiX6^;%JGe}3=1o2@cYYbF$u@%6WMjb7w&7JZR5zdQP}op_m1 zg2@!{IjDeASHYJpG%_D%vjz5@Z~obdXox&=+ThdYpu?ZFo_7N^b}Hnsq}EW%*dwIOM%!f(Zh(fo#mVsjI77cPRkJf2NX5qG0)BnOA271 zD7JQq&Lu5VS%2*JUP0#Q7RvYEo4)&`jX&V6H!WF|q#Qh?SF4m$i-cBtfNSgPHm!IR zkVkWmxPQ4Wf3VPsN!t{Z^j&_poWx1X)_wr>`rge*9iMdJV{~t?^ZJ?ev))Q8(ak27 zlh>NjU4jzcHaGF1?F?$TMEW_>;->T>A^jb7-K*6ucZz45M+0^mcvJV7g_PA2X>HOW zW+k+-EEtZqpr8;qojm8t2w#V+s%Y-T{Xn)aC+_`^0AtFnaiDuEa!(Wq%GxoxowHV@ zU;aKooP-l<@U&;?c`fFPKc}>Z`3&=$Hykj*nw^b*Bv8 z`*J389r$}k&@lmmw(TzC13NE_G`5-@$U)%t;FZm_Y-E1b6Yt>-pu{TFAC77QmkTo8K!UDZaoX$zQy19!5|!>4o#S2R-~P!yqAu5kvD zY^?zQ;~jiT_*EF2UaE-$O7L{O!M}vVw7?Mf8L5Vx=a8T%2MYI@Bd&F|d83N{YiI1^ z(gS&RqRgCr%!D4`yy*+G{qh$H#qo#j~(E$BAigX)Yy_3Txri^G_>EOs;nY zqXAHsF7_jp6n$xi(~aJrv|xyfAt8c}XimLLvO*FW^kJJ*)1(E`ylSpGkMWP~KKuTp zYON-tnKhGy#lK~c%5$!5V zOLkVNRw!h?t^vd2e#Y!W7H@j;b8>Hagu38rEujTAl_-Oh=q?u@%MdG6vwkjCqUhGdgZW9iJuE=TrFuv6GAG0! z>=D4s*M7WgcbeiV0JxR6EApmKuaHcmdM$KbqcFhgtj0)7{8f-iP@m^Xz)j%+kb#o) z*j+a}S@86oovCxp3h6l=U|IL!9w;j;G45T-c2!0TVC>b{h9Us3G74DM8kDdsC_ltq zIXH+<2Uo#P`domtQeG$p5_1YX$p=R}o|VJkJ0vbwxzR^(F^&fuB1(dJiL09M!^fVKDCQKw+vjRTR8EeqjlL z*kW%x7cd42tG}g#z!h=*LB?!2Zxa8}8&rz8rBZy+Y_cK^u)i>9zUixobMEawJTb1N zMgSQ)4x@ZT7!&1DLyU#e6%yPqP`)wY$$mZ$Fpw+C1TrLmAr@rpC@pK8&1V}(pxjwl z!I}X99BD+x-u|;C@nbFo$HnLs4vcAGcOTLa)zs`|h^sFNsL~xprT~~L)`eb8032)j z7*=QsIavqb?Td>`0l{~%A`*ZLec`QETM-HaHo`eD*)=q53xgB29+g^sQ^qmov8!P~ zljh{??VR~^%GW4S%xCqMNSkUf#~G;hNhtwDqKDhYNrDILc9uU}W-0*~jjV%fVYuqg zb0~Tn-{euyKrrYYledzk(j)I5MZnCx0lYJqtrNp6n z+{r=t8eL`juK?&G28o4p@PH<#dUX#|2l#++TAR%lYzxD;-mNJ|=1G;^e9H;MFP=Ov zwrlO5zAU3jHrcMS;y-dFy@=~LQfi}WgVbHuR`?k#=t0ZmgO4SZa&z@i{(7M{-PB;2o6rXgx>NR|fzMTZ3$Id0djJjP zp#tg9?U><#mm&JmfbMlCuq71^r98w^Ug&`+92B7o{b<>Kz}?=zK=wLikNg?=ZHhZM z?G`3d4Xgp}?SomZq!Rivpv%|g(d1{2oRo9(Psk#B)aNHC`of7le>pFaiLkGV+Oe5B zQJ3l%8dD<^Z2NkchFBsK4|+V?>Bqd3v5DK9-RmdxWW1p6T|unLZ0#=1W3 zl1K6$IWwMqq>|h-0Q_Yf6tzcAxu6W5hFVxy4;^V>t6jYz&@I-pyOMIy-@)p9kmcD+ zj9EaRg_ccN^$df1lzz*N${FyNpV$W@Bc({fIgXC$gAVrBGUqD=0Hl;cB~6M0SikIb zN0H+Ix6a4NhRzZsE*!roL(fEdb(okvy$AW_kK2(65`T9KNo(L+RJF4l=&t~ zQC-oV${3e*x#7iLcN*f!d-!0@&Dp3Y!0VhL;!e0Qa)5i zq6Q(NFEihoH;9Ma9PE6R)2o#_zfbQ+U_`?+cJfDj?H3N08`OvZ^y1aK;V~k%S?%$S zIF0K3J@r|ZT+holZbYZb(};n-u3k`3*AVu)oyxZ;x|TI?IS^Ue$uMngq|H8YD7Gk? z_>$&XDBeQyx!a*2lRtYgrQWRnuI2#WCzrqU=xVSDxE2#!QQ+$0|mF7`hk$V*v z4x6)sM_wj^lsVS%)p=Os99`h$A6e(G6wh&{n7ELdbdI#|AXWnDFxK{+f(rT}mR$Cm zH^2#0VDV_I0s{f09YyTTbaQ1fd#n>S6PEM@l<=BbN5v?40DC|DjuD_9AI=&*5Ux?gm7s_pemxhxl~3%CWi9UiOrIlaL58gFIy#pWpY9j0X$y*Q zfYQJZ_e`(Ie6qfKzRw6vxeP7Af9CHN!itp@bHoX@ZgPX=a=^~HP@W5lr~8u^oIV0m z#jnNtprD)j54on6bWn|h8fxqJ_P5VNUankNEG82-5V}*&{bnB>DS88wYZO05KwZCS z1QyY?lOb5xoVuyli6Rs1q2WuV5aMTgd~vf@5{H#vya*&vhV*8s7@108!k#m+c!Tu> ztgi&lRorW3ZP(Y@S`1?(EzhMe!_z(z-g@S~hcG{TR}bC#Vpc#SMNys4uqGTcRDV<% zw~=l-@k!R5z5VUYIb?Z1M|}ci$4i}G3@X6Jt{XOSP?R8RzC>yS-IAmDdg8@J^q7{z zAJ*~W`u85)!8eDq*A|7qmcM%q6Da$oXuVj2>R5DEEMRV_XOlvYm2ixuC?wx4r}iA& zE=z{L%gu8A@Z+ZXv?Q0SXRV!omBHpj>Gp(f7a?I^ovv%)XGQ#`jeL0S)*bk=LmDa| zVc0^C{rC#oz8(Hr&J0z8nE6XKvDW1oJhb{&r4v#V2~(I3nIB6&{P6pbzpXw$QGd}p z{t9f4Z>)7(lK;Yl=`u*)vyEC0^T?;@SsME`4YB;LFbeN7Y+PgJU}`#DYm+AU&`plj zh4kK#;73*@2%P{*xK%CTuY?a}6t;#5M`Ulmnz|9vMg1ogiSmJ}%dzqM`5MCF$E1k) zSE6USpO!HwoCYjqHm#FH9$_slCYtcBt~Fe=EdONw#6kT{Ae(s>DQJgZ{>*CDYSB@d z;pc44&PZ_fU>cwqjyp9`piovNH=3+T0Y1C4bwLJ?5Qp~UZgAvKLFJx0xWc?aC)M@p z1a4vJb!zfu`4lbrD-g3B$X$`4>3E(Oop;BsmnAD98D6Sk;y-6c->jC=(1=q##N@K))G!N$7rSHE zJK2qnLuyf1bLHL>nUe>3*(ctna!h@;#UNEHo-+9aSMkV znYAO5G<1b^bR|q2+co$O>L5+;5IB10gv$GtF=3-gOQoOW!>8v^GRF(&s}RLVknjQe zzP-|Jn#XG*g(g9;GA4-KEstAOrT|or_b+{&0r+`(lzjCY4h_Yleq~we?Cy8v|9S0l5Cf-`owhwc~kB9-%(Gcl8t$ z7P?x;=~vul$ZW8Lh zaWmaj*Di@R7Y-(4p z)o0sQO=$MZsRm~n)8OMP_m@eKTc*bW>Nt>uFS7N=Zo`tp8~&Q~XQPJ4R-eT5f`j%F zcItM94r#2;FeBM*P}r5-*1BBCu2q0{)5h$hLXa&*VXXHuTgWCC8?;&Y%Qjqglr5~-r?)}jy0EkdhuPZpj?hy z7LQP!t3EAotKtj72hRk|$x-n$2$sD83Bu+W;pT6%It>b{fytqODYUon zH$Q`Y-JoX>GN>^I(`owjG_Jnc@nuphvAmZ&4$Gd-;JLZl%=&8L=cXt{iUJBJ*}M7o z+gq~H9%pLtd#W;lNUaF$><(LfS5r7%30|sY*)t%_2Wi>h>U#8NEs^~W+mvRUf=)09 za6A%Wy(Bvjx^eR4yJJxI&uYNzr;tNNGJs?DJJ%YH z-so;KIqrRR`n0UTnE-&km9~|zn-u*r<~ z*^R+s0^#f-1cnR_P37K6TVAN$ zrQve%g6giZ$Cx%6olb{{6ty5^lV^EoG_mjtAKPdUn@HzjiJE>4v$pRXBXD{^tJOeP zxV;s+e&nCj{LFu;OvgHJ6ue**yZi9C@v0D?I*yulE>@gJ^fJGgO3YEl%(~*&b!D6c z<(A4daZxYl@mS$Qwonxxx2?qasuzCq@m~rb%(L&aw#$$n-M+TxSi|@%lVl9my+<#( zOvd|byQ@PjVHxvn?(CAF;QruPG=N}jPac|!eyia9!b>HnqV>zZ5Uc1+6ee*_J&?8# z49bT+i^cN)(Xh_w-cWlwV31iN9~(A%uPVrKBgC@Q79*^V)oUn%8YBY9yH{Aavuji) z9=CmXQl(yF$Nn4PZSd2#@#z#vP#)5yW0jZIMw`?uckht?dEXZOg_NJE<1I;+=xWfS z+SiNqg{XzW_IEM&*iR1hes&#l;ggSGHtdkVqFV|x$iOJ7#YDN%ht_Xe-rcT}7?ZIfF?BFH|gEjiqtEw5NdWs+(iFu z?Zb>~6+w}UBK(rxk1u9_rR5g196RTiJ`&Dm4d4}sOIQ7@6*r4VdU8t{o#sN)ehFS- z**zj2vRFzo+zW6W_tRHWiFB5@vXvFBn`FH2Z70@-mW-$mtc%@FgIQiPI z@`i%qPsqoJ$Ma!VEv#a9Zq$6t?$c!NT2@^$ZCb$GEyO;0k)GFA)^mxdW@ep$>3yo7 z(Dm26ZuwDbLw^&gw7$11E8@gcvmj^#)7W1xrb7On0tU>(({ className, return ; case ACCESS_PROVIDERS.DOGECLOUD: return ; + case ACCESS_PROVIDERS.GCORE: + return ; case ACCESS_PROVIDERS.GNAME: return ; case ACCESS_PROVIDERS.GODADDY: diff --git a/ui/src/components/access/AccessFormGcoreConfig.tsx b/ui/src/components/access/AccessFormGcoreConfig.tsx new file mode 100644 index 00000000..8619f7fe --- /dev/null +++ b/ui/src/components/access/AccessFormGcoreConfig.tsx @@ -0,0 +1,61 @@ +import { useTranslation } from "react-i18next"; +import { Form, type FormInstance, Input } from "antd"; +import { createSchemaFieldRule } from "antd-zod"; +import { z } from "zod"; + +import { type AccessConfigForGcore } from "@/domain/access"; + +type AccessFormGcoreConfigFieldValues = Nullish; + +export type AccessFormGcoreConfigProps = { + form: FormInstance; + formName: string; + disabled?: boolean; + initialValues?: AccessFormGcoreConfigFieldValues; + onValuesChange?: (values: AccessFormGcoreConfigFieldValues) => void; +}; + +const initFormModel = (): AccessFormGcoreConfigFieldValues => { + return { + apiToken: "", + }; +}; + +const AccessFormGcoreConfig = ({ form: formInst, formName, disabled, initialValues, onValuesChange }: AccessFormGcoreConfigProps) => { + const { t } = useTranslation(); + + const formSchema = z.object({ + apiToken: z + .string() + .min(1, t("access.form.gcore_api_token.placeholder")) + .max(64, t("common.errmsg.string_max", { max: 64 })) + .trim(), + }); + const formRule = createSchemaFieldRule(formSchema); + + const handleFormChange = (_: unknown, values: z.infer) => { + onValuesChange?.(values); + }; + + return ( +
+ } + > + + +
+ ); +}; + +export default AccessFormGcoreConfig; diff --git a/ui/src/domain/access.ts b/ui/src/domain/access.ts index 548716b4..1779c64c 100644 --- a/ui/src/domain/access.ts +++ b/ui/src/domain/access.ts @@ -18,6 +18,7 @@ export interface AccessModel extends BaseModel { | AccessConfigForClouDNS | AccessConfigForDogeCloud | AccessConfigForEdgio + | AccessConfigForGcore | AccessConfigForGname | AccessConfigForGoDaddy | AccessConfigForHuaweiCloud @@ -101,6 +102,10 @@ export type AccessConfigForEdgio = { clientSecret: string; }; +export type AccessConfigForGcore = { + apiToken: string; +}; + export type AccessConfigForGname = { appId: string; appKey: string; diff --git a/ui/src/domain/provider.ts b/ui/src/domain/provider.ts index 75b954eb..4ccd7f7b 100644 --- a/ui/src/domain/provider.ts +++ b/ui/src/domain/provider.ts @@ -15,6 +15,7 @@ export const ACCESS_PROVIDERS = Object.freeze({ CLOUDFLARE: "cloudflare", CLOUDNS: "cloudns", DOGECLOUD: "dogecloud", + GCORE: "gcore", GNAME: "gname", GODADDY: "godaddy", EDGIO: "edgio", @@ -79,6 +80,7 @@ export const accessProvidersMap: Maphttps://docs.edg.io/applications/v7/rest_api/authentication#administering-api-clients", + "access.form.gcore_api_token.label": "Gcore API token", + "access.form.gcore_api_token.placeholder": "Please enter Gcore API token", + "access.form.gcore_api_token.tooltip": "For more information, see https://api.gcore.com/docs/iam#section/Authentication", "access.form.gname_app_id.label": "GNAME AppId", "access.form.gname_app_id.placeholder": "Please enter GNAME AppId", "access.form.gname_app_id.tooltip": "For more information, see https://www.gname.com/user#/dealer_api", diff --git a/ui/src/i18n/locales/zh/nls.access.json b/ui/src/i18n/locales/zh/nls.access.json index cca17a8d..e3ae142c 100644 --- a/ui/src/i18n/locales/zh/nls.access.json +++ b/ui/src/i18n/locales/zh/nls.access.json @@ -100,6 +100,9 @@ "access.form.edgio_client_secret.label": "Edgio 客户端密码", "access.form.edgio_client_secret.placeholder": "请输入 Edgio 客户端密码", "access.form.edgio_client_secret.tooltip": "这是什么?请参阅 https://docs.edg.io/applications/v7/rest_api/authentication#administering-api-clients", + "access.form.gcore_api_token.label": "Gcore API Token", + "access.form.gcore_api_token.placeholder": "请输入 Gcore API Token", + "access.form.gcore_api_token.tooltip": "这是什么?请参阅 https://api.gcore.com/docs/iam#section/Authentication", "access.form.gname_app_id.label": "GNAME AppId", "access.form.gname_app_id.placeholder": "请输入 GNAME AppId", "access.form.gname_app_id.tooltip": "这是什么?请参阅 https://www.gname.com/user#/dealer_api", From ea02190ad5228932e8865e41ba1d0a5fc1c619be Mon Sep 17 00:00:00 2001 From: Fu Diwei Date: Mon, 17 Feb 2025 22:05:08 +0800 Subject: [PATCH 09/34] feat: add gcore uploader --- go.mod | 1 + go.sum | 2 + .../uploader/providers/gcore-cdn/gcore_cdn.go | 79 +++++++++++++++++++ .../pkg/vendors/gcore-sdk/common/endpoint.go | 3 + .../pkg/vendors/gcore-sdk/common/signer.go | 24 ++++++ 5 files changed, 109 insertions(+) create mode 100644 internal/pkg/core/uploader/providers/gcore-cdn/gcore_cdn.go create mode 100644 internal/pkg/vendors/gcore-sdk/common/endpoint.go create mode 100644 internal/pkg/vendors/gcore-sdk/common/signer.go diff --git a/go.mod b/go.mod index 52c05aea..ee281548 100644 --- a/go.mod +++ b/go.mod @@ -57,6 +57,7 @@ require ( github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/privatedns/armprivatedns v1.3.0 // indirect github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resourcegraph/armresourcegraph v0.9.0 // indirect github.com/AzureAD/microsoft-authentication-library-for-go v1.3.2 // indirect + github.com/G-Core/gcorelabscdn-go v1.0.26 // indirect github.com/alibabacloud-go/openplatform-20191219/v2 v2.0.1 // indirect github.com/alibabacloud-go/tea-fileform v1.1.1 // indirect github.com/alibabacloud-go/tea-oss-sdk v1.1.3 // indirect diff --git a/go.sum b/go.sum index a0cd77e9..c3d1b3a6 100644 --- a/go.sum +++ b/go.sum @@ -79,6 +79,8 @@ github.com/BurntSushi/toml v1.4.0 h1:kuoIxZQy2WRRk1pttg9asf+WVv6tWQuBNVmK8+nqPr0 github.com/BurntSushi/toml v1.4.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= +github.com/G-Core/gcorelabscdn-go v1.0.26 h1:22SqETUw64s+It/op1T7y3ukEOU62CJOsUcsfSkhvZs= +github.com/G-Core/gcorelabscdn-go v1.0.26/go.mod h1:iSGXaTvZBzDHQW+rKFS918BgFVpONcyLEijwh8WsXpE= github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.25.0 h1:3c8yed4lgqTt+oTQ+JNMDo+F4xprBf+O/il4ZC0nRLw= github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.25.0/go.mod h1:obipzmGjfSjam60XLwGfqUkJsfiheAl+TUjG+4yzyPM= github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.49.0 h1:o90wcURuxekmXrtxmYWTyNla0+ZEHhud6DI1ZTxd1vI= diff --git a/internal/pkg/core/uploader/providers/gcore-cdn/gcore_cdn.go b/internal/pkg/core/uploader/providers/gcore-cdn/gcore_cdn.go new file mode 100644 index 00000000..32cadb62 --- /dev/null +++ b/internal/pkg/core/uploader/providers/gcore-cdn/gcore_cdn.go @@ -0,0 +1,79 @@ +package gcorecdn + +import ( + "context" + "errors" + "fmt" + "time" + + gprovider "github.com/G-Core/gcorelabscdn-go/gcore/provider" + gsslcerts "github.com/G-Core/gcorelabscdn-go/sslcerts" + xerrors "github.com/pkg/errors" + + "github.com/usual2970/certimate/internal/pkg/core/uploader" + gcoresdk "github.com/usual2970/certimate/internal/pkg/vendors/gcore-sdk/common" +) + +type GcoreCDNUploaderConfig struct { + // Gcore API Token。 + ApiToken string `json:"apiToken"` +} + +type GcoreCDNUploader struct { + config *GcoreCDNUploaderConfig + sdkClient *gsslcerts.Service +} + +var _ uploader.Uploader = (*GcoreCDNUploader)(nil) + +func New(config *GcoreCDNUploaderConfig) (*GcoreCDNUploader, error) { + if config == nil { + return nil, errors.New("config is nil") + } + + client, err := createSdkClient(config.ApiToken) + if err != nil { + return nil, xerrors.Wrap(err, "failed to create sdk client") + } + + return &GcoreCDNUploader{ + config: config, + sdkClient: client, + }, nil +} + +func (u *GcoreCDNUploader) Upload(ctx context.Context, certPem string, privkeyPem string) (res *uploader.UploadResult, err error) { + // 生成新证书名(需符合 Gcore 命名规则) + var certId, certName string + certName = fmt.Sprintf("certimate_%d", time.Now().UnixMilli()) + + // 新增证书 + // REF: https://api.gcore.com/docs/cdn#tag/CA-certificates/operation/ca_certificates-add + createCertificateReq := &gsslcerts.CreateRequest{ + Name: certName, + Cert: certPem, + PrivateKey: privkeyPem, + Automated: false, + ValidateRootCA: false, + } + createCertificateResp, err := u.sdkClient.Create(context.TODO(), createCertificateReq) + if err != nil { + return nil, xerrors.Wrap(err, "failed to execute sdk request 'sslcerts.Create'") + } + + certId = fmt.Sprintf("%d", createCertificateResp.ID) + certName = createCertificateResp.Name + return &uploader.UploadResult{ + CertId: certId, + CertName: certName, + }, nil +} + +func createSdkClient(apiToken string) (*gsslcerts.Service, error) { + requester := gprovider.NewClient( + gcoresdk.BASE_URL, + gprovider.WithSigner(gcoresdk.NewAuthRequestSigner(apiToken)), + ) + service := gsslcerts.NewService(requester) + return service, nil +} diff --git a/internal/pkg/vendors/gcore-sdk/common/endpoint.go b/internal/pkg/vendors/gcore-sdk/common/endpoint.go new file mode 100644 index 00000000..d4032da3 --- /dev/null +++ b/internal/pkg/vendors/gcore-sdk/common/endpoint.go @@ -0,0 +1,3 @@ +package common + +const BASE_URL = "https://api.gcore.com" diff --git a/internal/pkg/vendors/gcore-sdk/common/signer.go b/internal/pkg/vendors/gcore-sdk/common/signer.go new file mode 100644 index 00000000..bc66ee09 --- /dev/null +++ b/internal/pkg/vendors/gcore-sdk/common/signer.go @@ -0,0 +1,24 @@ +package common + +import ( + "net/http" + + "github.com/G-Core/gcorelabscdn-go/gcore" +) + +type AuthRequestSigner struct { + apiToken string +} + +var _ gcore.RequestSigner = (*AuthRequestSigner)(nil) + +func NewAuthRequestSigner(apiToken string) *AuthRequestSigner { + return &AuthRequestSigner{ + apiToken: apiToken, + } +} + +func (s *AuthRequestSigner) Sign(req *http.Request) error { + req.Header.Set("Authorization", "APIKey "+s.apiToken) + return nil +} From 7c3f2399c276581e3eb664477621d27dcd6cc379 Mon Sep 17 00:00:00 2001 From: Fu Diwei Date: Mon, 17 Feb 2025 22:24:38 +0800 Subject: [PATCH 10/34] feat: add gcore cdn deployer --- README.md | 7 +- README_EN.md | 1 + internal/deployer/providers.go | 21 +++ internal/domain/provider.go | 1 + .../providers/aliyun-alb/aliyun_alb.go | 4 +- .../aliyun-cas-deploy/aliyun_cas_deploy.go | 4 +- .../providers/aliyun-clb/aliyun_clb.go | 4 +- .../providers/aliyun-esa/aliyun_esa.go | 4 +- .../providers/aliyun-nlb/aliyun_nlb.go | 4 +- .../providers/aliyun-waf/aliyun_waf.go | 4 +- .../aws-cloudfront/aws_cloudfront.go | 4 +- .../providers/byteplus-cdn/byteplus_cdn.go | 4 +- .../providers/dogecloud-cdn/dogecloud_cdn.go | 4 +- .../deployer/providers/gcore-cdn/gcore_cdn.go | 123 ++++++++++++++++++ .../providers/gcore-cdn/gcore_cdn_test.go | 70 ++++++++++ .../huaweicloud-cdn/huaweicloud_cdn.go | 4 +- .../huaweicloud-elb/huaweicloud_elb.go | 4 +- .../huaweicloud-waf/huaweicloud_waf.go | 4 +- .../deployer/providers/qiniu-cdn/qiniu_cdn.go | 4 +- .../providers/qiniu-pili/qiniu_pili.go | 4 +- .../tencentcloud-cdn/tencentcloud_cdn.go | 4 +- .../tencentcloud-clb/tencentcloud_clb.go | 4 +- .../tencentcloud-cos/tencentcloud_cos.go | 4 +- .../tencentcloud-css/tencentcloud_css.go | 4 +- .../tencentcloud-ecdn/tencentcloud_ecdn.go | 4 +- .../tencentcloud-eo/tencentcloud_eo.go | 4 +- .../tencentcloud_ssl_deploy.go | 4 +- .../tencentcloud-waf/tencentcloud_waf.go | 4 +- .../providers/ucloud-ucdn/ucloud_ucdn.go | 4 +- .../providers/ucloud-us3/ucloud_us3.go | 4 +- .../volcengine-cdn/volcengine_cdn.go | 4 +- .../volcengine-clb/volcengine_clb.go | 4 +- .../volcengine-dcdn/volcengine_dcdn.go | 4 +- .../volcengine-imagex/volcengine_imagex.go | 4 +- .../volcengine-live/volcengine_live.go | 4 +- .../volcengine-tos/volcengine_tos.go | 4 +- .../workflow/node/DeployNodeConfigForm.tsx | 5 +- .../DeployNodeConfigFormGcoreCDNConfig.tsx | 59 +++++++++ ui/src/domain/provider.ts | 8 +- ui/src/i18n/locales/en/nls.provider.json | 1 + .../i18n/locales/en/nls.workflow.nodes.json | 3 + ui/src/i18n/locales/zh/nls.provider.json | 1 + .../i18n/locales/zh/nls.workflow.nodes.json | 3 + 43 files changed, 356 insertions(+), 67 deletions(-) create mode 100644 internal/pkg/core/deployer/providers/gcore-cdn/gcore_cdn.go create mode 100644 internal/pkg/core/deployer/providers/gcore-cdn/gcore_cdn_test.go create mode 100644 ui/src/components/workflow/node/DeployNodeConfigFormGcoreCDNConfig.tsx diff --git a/README.md b/README.md index 1768b501..95180539 100644 --- a/README.md +++ b/README.md @@ -134,9 +134,10 @@ make local.run | [优刻得](https://www.ucloud.cn/) | 可部署到优刻得 US3、UCDN 等服务 | | [雷池](https://waf-ce.chaitin.cn/) | 可部署到雷池 WAF | | [宝塔面板](https://www.bt.cn/) | 可部署到宝塔面板 | -| [AWS](https://aws.amazon.com/) | 可部署到 AWS CloudFront 等服务 | -| [BytePlus](https://www.byteplus.com/) | 可部署到 BytePlus CDN 等服务 | -| [Edgio](https://edg.io/) | 可部署到 Edgio Applications 等服务 | +| [AWS](https://aws.amazon.com/) | 可部署到 AWS CloudFront | +| [BytePlus](https://www.byteplus.com/) | 可部署到 BytePlus CDN | +| [Edgio](https://edg.io/) | 可部署到 Edgio Applications | +| [Gcore](https://gcore.com/) | 可部署到 Gcore CDN | diff --git a/README_EN.md b/README_EN.md index a13509a8..c47de082 100644 --- a/README_EN.md +++ b/README_EN.md @@ -136,6 +136,7 @@ The following hosting providers are supported: | [AWS](https://aws.amazon.com/) | Supports deployment to AWS CloudFront | | [BytePlus](https://www.byteplus.com/) | Supports deployment to BytePlus CDN | | [Edgio](https://edg.io/) | Supports deployment to Edgio Applications | +| [Gcore](https://gcore.com/) | Supports deployment to Gcore CDN | diff --git a/internal/deployer/providers.go b/internal/deployer/providers.go index d5ce4ae7..8903f96b 100644 --- a/internal/deployer/providers.go +++ b/internal/deployer/providers.go @@ -24,6 +24,7 @@ import ( pBytePlusCDN "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/byteplus-cdn" pDogeCDN "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/dogecloud-cdn" pEdgioApplications "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/edgio-applications" + pGcoreCDN "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/gcore-cdn" pHuaweiCloudCDN "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/huaweicloud-cdn" pHuaweiCloudELB "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/huaweicloud-elb" pHuaweiCloudWAF "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/huaweicloud-waf" @@ -317,6 +318,26 @@ func createDeployer(options *deployerOptions) (deployer.Deployer, logger.Logger, return deployer, logger, err } + case domain.DeployProviderTypeGcoreCDN: + { + access := domain.AccessConfigForGcore{} + if err := maps.Populate(options.ProviderAccessConfig, &access); err != nil { + return nil, nil, fmt.Errorf("failed to populate provider access config: %w", err) + } + + switch options.Provider { + case domain.DeployProviderTypeGcoreCDN: + deployer, err := pGcoreCDN.NewWithLogger(&pGcoreCDN.GcoreCDNDeployerConfig{ + ApiToken: access.ApiToken, + ResourceId: maps.GetValueAsInt64(options.ProviderDeployConfig, "resourceId"), + }, logger) + return deployer, logger, err + + default: + break + } + } + case domain.DeployProviderTypeHuaweiCloudCDN, domain.DeployProviderTypeHuaweiCloudELB, domain.DeployProviderTypeHuaweiCloudWAF: { access := domain.AccessConfigForHuaweiCloud{} diff --git a/internal/domain/provider.go b/internal/domain/provider.go index 8fe8da0f..8d2fd046 100644 --- a/internal/domain/provider.go +++ b/internal/domain/provider.go @@ -114,6 +114,7 @@ const ( DeployProviderTypeBytePlusCDN = DeployProviderType("byteplus-cdn") DeployProviderTypeDogeCloudCDN = DeployProviderType("dogecloud-cdn") DeployProviderTypeEdgioApplications = DeployProviderType("edgio-applications") + DeployProviderTypeGcoreCDN = DeployProviderType("gcore-cdn") DeployProviderTypeHuaweiCloudCDN = DeployProviderType("huaweicloud-cdn") DeployProviderTypeHuaweiCloudELB = DeployProviderType("huaweicloud-elb") DeployProviderTypeHuaweiCloudWAF = DeployProviderType("huaweicloud-waf") diff --git a/internal/pkg/core/deployer/providers/aliyun-alb/aliyun_alb.go b/internal/pkg/core/deployer/providers/aliyun-alb/aliyun_alb.go index c5b1ae35..db4242d2 100644 --- a/internal/pkg/core/deployer/providers/aliyun-alb/aliyun_alb.go +++ b/internal/pkg/core/deployer/providers/aliyun-alb/aliyun_alb.go @@ -18,7 +18,7 @@ import ( "github.com/usual2970/certimate/internal/pkg/core/deployer" "github.com/usual2970/certimate/internal/pkg/core/logger" "github.com/usual2970/certimate/internal/pkg/core/uploader" - uploaderp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/aliyun-cas" + uploadersp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/aliyun-cas" ) type AliyunALBDeployerConfig struct { @@ -445,7 +445,7 @@ func createSslUploader(accessKeyId, accessKeySecret, region string) (uploader.Up } } - uploader, err := uploaderp.New(&uploaderp.AliyunCASUploaderConfig{ + uploader, err := uploadersp.New(&uploadersp.AliyunCASUploaderConfig{ AccessKeyId: accessKeyId, AccessKeySecret: accessKeySecret, Region: casRegion, diff --git a/internal/pkg/core/deployer/providers/aliyun-cas-deploy/aliyun_cas_deploy.go b/internal/pkg/core/deployer/providers/aliyun-cas-deploy/aliyun_cas_deploy.go index 31dc66b8..35f8edde 100644 --- a/internal/pkg/core/deployer/providers/aliyun-cas-deploy/aliyun_cas_deploy.go +++ b/internal/pkg/core/deployer/providers/aliyun-cas-deploy/aliyun_cas_deploy.go @@ -15,7 +15,7 @@ import ( "github.com/usual2970/certimate/internal/pkg/core/deployer" "github.com/usual2970/certimate/internal/pkg/core/logger" "github.com/usual2970/certimate/internal/pkg/core/uploader" - uploaderp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/aliyun-cas" + uploadersp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/aliyun-cas" ) type AliyunCASDeployDeployerConfig struct { @@ -178,7 +178,7 @@ func createSdkClient(accessKeyId, accessKeySecret, region string) (*aliyunCas.Cl } func createSslUploader(accessKeyId, accessKeySecret, region string) (uploader.Uploader, error) { - uploader, err := uploaderp.New(&uploaderp.AliyunCASUploaderConfig{ + uploader, err := uploadersp.New(&uploadersp.AliyunCASUploaderConfig{ AccessKeyId: accessKeyId, AccessKeySecret: accessKeySecret, Region: region, diff --git a/internal/pkg/core/deployer/providers/aliyun-clb/aliyun_clb.go b/internal/pkg/core/deployer/providers/aliyun-clb/aliyun_clb.go index 1fd5532e..25f223b6 100644 --- a/internal/pkg/core/deployer/providers/aliyun-clb/aliyun_clb.go +++ b/internal/pkg/core/deployer/providers/aliyun-clb/aliyun_clb.go @@ -13,7 +13,7 @@ import ( "github.com/usual2970/certimate/internal/pkg/core/deployer" "github.com/usual2970/certimate/internal/pkg/core/logger" "github.com/usual2970/certimate/internal/pkg/core/uploader" - uploaderp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/aliyun-slb" + uploadersp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/aliyun-slb" ) type AliyunCLBDeployerConfig struct { @@ -63,7 +63,7 @@ func NewWithLogger(config *AliyunCLBDeployerConfig, logger logger.Logger) (*Aliy return nil, xerrors.Wrap(err, "failed to create sdk client") } - uploader, err := uploaderp.New(&uploaderp.AliyunSLBUploaderConfig{ + uploader, err := uploadersp.New(&uploadersp.AliyunSLBUploaderConfig{ AccessKeyId: config.AccessKeyId, AccessKeySecret: config.AccessKeySecret, Region: config.Region, diff --git a/internal/pkg/core/deployer/providers/aliyun-esa/aliyun_esa.go b/internal/pkg/core/deployer/providers/aliyun-esa/aliyun_esa.go index a09f8bbf..8f492e36 100644 --- a/internal/pkg/core/deployer/providers/aliyun-esa/aliyun_esa.go +++ b/internal/pkg/core/deployer/providers/aliyun-esa/aliyun_esa.go @@ -15,7 +15,7 @@ import ( "github.com/usual2970/certimate/internal/pkg/core/deployer" "github.com/usual2970/certimate/internal/pkg/core/logger" "github.com/usual2970/certimate/internal/pkg/core/uploader" - uploaderp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/aliyun-cas" + uploadersp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/aliyun-cas" ) type AliyunESADeployerConfig struct { @@ -129,7 +129,7 @@ func createSslUploader(accessKeyId, accessKeySecret, region string) (uploader.Up } } - uploader, err := uploaderp.New(&uploaderp.AliyunCASUploaderConfig{ + uploader, err := uploadersp.New(&uploadersp.AliyunCASUploaderConfig{ AccessKeyId: accessKeyId, AccessKeySecret: accessKeySecret, Region: casRegion, diff --git a/internal/pkg/core/deployer/providers/aliyun-nlb/aliyun_nlb.go b/internal/pkg/core/deployer/providers/aliyun-nlb/aliyun_nlb.go index e18b13a3..e55c9b80 100644 --- a/internal/pkg/core/deployer/providers/aliyun-nlb/aliyun_nlb.go +++ b/internal/pkg/core/deployer/providers/aliyun-nlb/aliyun_nlb.go @@ -14,7 +14,7 @@ import ( "github.com/usual2970/certimate/internal/pkg/core/deployer" "github.com/usual2970/certimate/internal/pkg/core/logger" "github.com/usual2970/certimate/internal/pkg/core/uploader" - uploaderp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/aliyun-cas" + uploadersp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/aliyun-cas" ) type AliyunNLBDeployerConfig struct { @@ -248,7 +248,7 @@ func createSslUploader(accessKeyId, accessKeySecret, region string) (uploader.Up } } - uploader, err := uploaderp.New(&uploaderp.AliyunCASUploaderConfig{ + uploader, err := uploadersp.New(&uploadersp.AliyunCASUploaderConfig{ AccessKeyId: accessKeyId, AccessKeySecret: accessKeySecret, Region: casRegion, diff --git a/internal/pkg/core/deployer/providers/aliyun-waf/aliyun_waf.go b/internal/pkg/core/deployer/providers/aliyun-waf/aliyun_waf.go index 1cc7aecd..476ffaef 100644 --- a/internal/pkg/core/deployer/providers/aliyun-waf/aliyun_waf.go +++ b/internal/pkg/core/deployer/providers/aliyun-waf/aliyun_waf.go @@ -14,7 +14,7 @@ import ( "github.com/usual2970/certimate/internal/pkg/core/deployer" "github.com/usual2970/certimate/internal/pkg/core/logger" "github.com/usual2970/certimate/internal/pkg/core/uploader" - uploaderp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/aliyun-cas" + uploadersp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/aliyun-cas" ) type AliyunWAFDeployerConfig struct { @@ -142,7 +142,7 @@ func createSslUploader(accessKeyId, accessKeySecret, region string) (uploader.Up } } - uploader, err := uploaderp.New(&uploaderp.AliyunCASUploaderConfig{ + uploader, err := uploadersp.New(&uploadersp.AliyunCASUploaderConfig{ AccessKeyId: accessKeyId, AccessKeySecret: accessKeySecret, Region: casRegion, diff --git a/internal/pkg/core/deployer/providers/aws-cloudfront/aws_cloudfront.go b/internal/pkg/core/deployer/providers/aws-cloudfront/aws_cloudfront.go index 086dd415..cf520a75 100644 --- a/internal/pkg/core/deployer/providers/aws-cloudfront/aws_cloudfront.go +++ b/internal/pkg/core/deployer/providers/aws-cloudfront/aws_cloudfront.go @@ -14,7 +14,7 @@ import ( "github.com/usual2970/certimate/internal/pkg/core/deployer" "github.com/usual2970/certimate/internal/pkg/core/logger" "github.com/usual2970/certimate/internal/pkg/core/uploader" - uploaderp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/aws-acm" + uploadersp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/aws-acm" ) type AWSCloudFrontDeployerConfig struct { @@ -55,7 +55,7 @@ func NewWithLogger(config *AWSCloudFrontDeployerConfig, logger logger.Logger) (* return nil, xerrors.Wrap(err, "failed to create sdk client") } - uploader, err := uploaderp.New(&uploaderp.AWSCertificateManagerUploaderConfig{ + uploader, err := uploadersp.New(&uploadersp.AWSCertificateManagerUploaderConfig{ AccessKeyId: config.AccessKeyId, SecretAccessKey: config.SecretAccessKey, Region: config.Region, diff --git a/internal/pkg/core/deployer/providers/byteplus-cdn/byteplus_cdn.go b/internal/pkg/core/deployer/providers/byteplus-cdn/byteplus_cdn.go index 2a695513..514bbd08 100644 --- a/internal/pkg/core/deployer/providers/byteplus-cdn/byteplus_cdn.go +++ b/internal/pkg/core/deployer/providers/byteplus-cdn/byteplus_cdn.go @@ -12,7 +12,7 @@ import ( "github.com/usual2970/certimate/internal/pkg/core/deployer" "github.com/usual2970/certimate/internal/pkg/core/logger" "github.com/usual2970/certimate/internal/pkg/core/uploader" - uploaderp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/byteplus-cdn" + uploadersp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/byteplus-cdn" ) type BytePlusCDNDeployerConfig struct { @@ -50,7 +50,7 @@ func NewWithLogger(config *BytePlusCDNDeployerConfig, logger logger.Logger) (*By client.Client.SetAccessKey(config.AccessKey) client.Client.SetSecretKey(config.SecretKey) - uploader, err := uploaderp.New(&uploaderp.ByteplusCDNUploaderConfig{ + uploader, err := uploadersp.New(&uploadersp.ByteplusCDNUploaderConfig{ AccessKey: config.AccessKey, SecretKey: config.SecretKey, }) diff --git a/internal/pkg/core/deployer/providers/dogecloud-cdn/dogecloud_cdn.go b/internal/pkg/core/deployer/providers/dogecloud-cdn/dogecloud_cdn.go index 283d9907..58e79ee8 100644 --- a/internal/pkg/core/deployer/providers/dogecloud-cdn/dogecloud_cdn.go +++ b/internal/pkg/core/deployer/providers/dogecloud-cdn/dogecloud_cdn.go @@ -10,7 +10,7 @@ import ( "github.com/usual2970/certimate/internal/pkg/core/deployer" "github.com/usual2970/certimate/internal/pkg/core/logger" "github.com/usual2970/certimate/internal/pkg/core/uploader" - uploaderp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/dogecloud" + uploadersp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/dogecloud" dogesdk "github.com/usual2970/certimate/internal/pkg/vendors/dogecloud-sdk" ) @@ -47,7 +47,7 @@ func NewWithLogger(config *DogeCloudCDNDeployerConfig, logger logger.Logger) (*D client := dogesdk.NewClient(config.AccessKey, config.SecretKey) - uploader, err := uploaderp.New(&uploaderp.DogeCloudUploaderConfig{ + uploader, err := uploadersp.New(&uploadersp.DogeCloudUploaderConfig{ AccessKey: config.AccessKey, SecretKey: config.SecretKey, }) diff --git a/internal/pkg/core/deployer/providers/gcore-cdn/gcore_cdn.go b/internal/pkg/core/deployer/providers/gcore-cdn/gcore_cdn.go new file mode 100644 index 00000000..4c20c874 --- /dev/null +++ b/internal/pkg/core/deployer/providers/gcore-cdn/gcore_cdn.go @@ -0,0 +1,123 @@ +package gcorecdn + +import ( + "context" + "errors" + "strconv" + + gprovider "github.com/G-Core/gcorelabscdn-go/gcore/provider" + gresources "github.com/G-Core/gcorelabscdn-go/resources" + xerrors "github.com/pkg/errors" + + "github.com/usual2970/certimate/internal/pkg/core/deployer" + "github.com/usual2970/certimate/internal/pkg/core/logger" + "github.com/usual2970/certimate/internal/pkg/core/uploader" + uploadersp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/gcore-cdn" + gcoresdk "github.com/usual2970/certimate/internal/pkg/vendors/gcore-sdk/common" +) + +type GcoreCDNDeployerConfig struct { + // Gcore API Token。 + ApiToken string `json:"apiToken"` + // CDN 资源 ID。 + ResourceId int64 `json:"resourceId"` +} + +type GcoreCDNDeployer struct { + config *GcoreCDNDeployerConfig + logger logger.Logger + sdkClient *gresources.Service + sslUploader uploader.Uploader +} + +var _ deployer.Deployer = (*GcoreCDNDeployer)(nil) + +func New(config *GcoreCDNDeployerConfig) (*GcoreCDNDeployer, error) { + return NewWithLogger(config, logger.NewNilLogger()) +} + +func NewWithLogger(config *GcoreCDNDeployerConfig, logger logger.Logger) (*GcoreCDNDeployer, error) { + if config == nil { + return nil, errors.New("config is nil") + } + + if logger == nil { + return nil, errors.New("logger is nil") + } + + client, err := createSdkClient(config.ApiToken) + if err != nil { + return nil, xerrors.Wrap(err, "failed to create sdk client") + } + + uploader, err := uploadersp.New(&uploadersp.GcoreCDNUploaderConfig{ + ApiToken: config.ApiToken, + }) + if err != nil { + return nil, xerrors.Wrap(err, "failed to create ssl uploader") + } + + return &GcoreCDNDeployer{ + logger: logger, + config: config, + sdkClient: client, + sslUploader: uploader, + }, nil +} + +func (d *GcoreCDNDeployer) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { + if d.config.ResourceId == 0 { + return nil, errors.New("config `resourceId` is required") + } + + // 上传证书到 CDN + upres, err := d.sslUploader.Upload(ctx, certPem, privkeyPem) + if err != nil { + return nil, xerrors.Wrap(err, "failed to upload certificate file") + } else { + d.logger.Logt("certificate file uploaded", upres) + } + + // 获取 CDN 资源详情 + // REF: https://api.gcore.com/docs/cdn#tag/CDN-resources/paths/~1cdn~1resources~1%7Bresource_id%7D/get + getResourceResp, err := d.sdkClient.Get(context.TODO(), d.config.ResourceId) + if err != nil { + return nil, xerrors.Wrap(err, "failed to execute sdk request 'resources.Get'") + } else { + d.logger.Logt("已获取 CDN 资源详情", getResourceResp) + } + + // 更新 CDN 资源详情 + // REF: https://api.gcore.com/docs/cdn#tag/CDN-resources/operation/change_cdn_resource + updateResourceCertId, _ := strconv.ParseInt(upres.CertId, 10, 64) + updateResourceReq := &gresources.UpdateRequest{ + Description: getResourceResp.Description, + Active: getResourceResp.Active, + OriginGroup: int(getResourceResp.OriginGroup), + OriginProtocol: getResourceResp.OriginProtocol, + SecondaryHostnames: getResourceResp.SecondaryHostnames, + SSlEnabled: true, + SSLData: int(updateResourceCertId), + ProxySSLEnabled: getResourceResp.ProxySSLEnabled, + ProxySSLCA: &getResourceResp.ProxySSLCA, + ProxySSLData: &getResourceResp.ProxySSLData, + Options: getResourceResp.Options, + } + updateResourceResp, err := d.sdkClient.Update(context.TODO(), d.config.ResourceId, updateResourceReq) + if err != nil { + return nil, xerrors.Wrap(err, "failed to execute sdk request 'resources.Update'") + } else { + d.logger.Logt("已更新 CDN 资源详情", updateResourceResp) + } + + return &deployer.DeployResult{}, nil +} + +func createSdkClient(apiToken string) (*gresources.Service, error) { + requester := gprovider.NewClient( + gcoresdk.BASE_URL, + gprovider.WithSigner(gcoresdk.NewAuthRequestSigner(apiToken)), + ) + service := gresources.NewService(requester) + return service, nil +} diff --git a/internal/pkg/core/deployer/providers/gcore-cdn/gcore_cdn_test.go b/internal/pkg/core/deployer/providers/gcore-cdn/gcore_cdn_test.go new file mode 100644 index 00000000..bc36029b --- /dev/null +++ b/internal/pkg/core/deployer/providers/gcore-cdn/gcore_cdn_test.go @@ -0,0 +1,70 @@ +package gcorecdn_test + +import ( + "context" + "flag" + "fmt" + "os" + "strings" + "testing" + + provider "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/gcore-cdn" +) + +var ( + fInputCertPath string + fInputKeyPath string + fApiToken string + fResourceId int64 +) + +func init() { + argsPrefix := "CERTIMATE_DEPLOYER_GCORECDN_" + + flag.StringVar(&fInputCertPath, argsPrefix+"INPUTCERTPATH", "", "") + flag.StringVar(&fInputKeyPath, argsPrefix+"INPUTKEYPATH", "", "") + flag.StringVar(&fApiToken, argsPrefix+"APITOKEN", "", "") + flag.Int64Var(&fResourceId, argsPrefix+"RESOURCEID", 0, "") +} + +/* +Shell command to run this test: + + go test -v ./gcore_cdn_test.go -args \ + --CERTIMATE_DEPLOYER_GCORECDN_INPUTCERTPATH="/path/to/your-input-cert.pem" \ + --CERTIMATE_DEPLOYER_GCORECDN_INPUTKEYPATH="/path/to/your-input-key.pem" \ + --CERTIMATE_DEPLOYER_GCORECDN_APITOKEN="your-api-token" \ + --CERTIMATE_DEPLOYER_GCORECDN_RESOURCEID="your-cdn-resource-id" +*/ +func TestDeploy(t *testing.T) { + flag.Parse() + + t.Run("Deploy", func(t *testing.T) { + t.Log(strings.Join([]string{ + "args:", + fmt.Sprintf("INPUTCERTPATH: %v", fInputCertPath), + fmt.Sprintf("INPUTKEYPATH: %v", fInputKeyPath), + fmt.Sprintf("APITOKEN: %v", fApiToken), + fmt.Sprintf("RESOURCEID: %v", fResourceId), + }, "\n")) + + deployer, err := provider.New(&provider.GcoreCDNDeployerConfig{ + ApiToken: fApiToken, + ResourceId: fResourceId, + }) + if err != nil { + t.Errorf("err: %+v", err) + return + } + + fInputCertData, _ := os.ReadFile(fInputCertPath) + fInputKeyData, _ := os.ReadFile(fInputKeyPath) + res, err := deployer.Deploy(context.Background(), string(fInputCertData), string(fInputKeyData)) + if err != nil { + t.Errorf("err: %+v", err) + return + } + + t.Logf("ok: %v", res) + }) +} diff --git a/internal/pkg/core/deployer/providers/huaweicloud-cdn/huaweicloud_cdn.go b/internal/pkg/core/deployer/providers/huaweicloud-cdn/huaweicloud_cdn.go index 31782af3..b4356a0d 100644 --- a/internal/pkg/core/deployer/providers/huaweicloud-cdn/huaweicloud_cdn.go +++ b/internal/pkg/core/deployer/providers/huaweicloud-cdn/huaweicloud_cdn.go @@ -13,7 +13,7 @@ import ( "github.com/usual2970/certimate/internal/pkg/core/deployer" "github.com/usual2970/certimate/internal/pkg/core/logger" "github.com/usual2970/certimate/internal/pkg/core/uploader" - uploaderp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/huaweicloud-scm" + uploadersp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/huaweicloud-scm" hwsdk "github.com/usual2970/certimate/internal/pkg/vendors/huaweicloud-sdk" ) @@ -59,7 +59,7 @@ func NewWithLogger(config *HuaweiCloudCDNDeployerConfig, logger logger.Logger) ( return nil, xerrors.Wrap(err, "failed to create sdk client") } - uploader, err := uploaderp.New(&uploaderp.HuaweiCloudSCMUploaderConfig{ + uploader, err := uploadersp.New(&uploadersp.HuaweiCloudSCMUploaderConfig{ AccessKeyId: config.AccessKeyId, SecretAccessKey: config.SecretAccessKey, }) diff --git a/internal/pkg/core/deployer/providers/huaweicloud-elb/huaweicloud_elb.go b/internal/pkg/core/deployer/providers/huaweicloud-elb/huaweicloud_elb.go index 2748913e..f22a07fe 100644 --- a/internal/pkg/core/deployer/providers/huaweicloud-elb/huaweicloud_elb.go +++ b/internal/pkg/core/deployer/providers/huaweicloud-elb/huaweicloud_elb.go @@ -19,7 +19,7 @@ import ( "github.com/usual2970/certimate/internal/pkg/core/deployer" "github.com/usual2970/certimate/internal/pkg/core/logger" "github.com/usual2970/certimate/internal/pkg/core/uploader" - uploaderp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/huaweicloud-elb" + uploadersp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/huaweicloud-elb" hwsdk "github.com/usual2970/certimate/internal/pkg/vendors/huaweicloud-sdk" ) @@ -70,7 +70,7 @@ func NewWithLogger(config *HuaweiCloudELBDeployerConfig, logger logger.Logger) ( return nil, xerrors.Wrap(err, "failed to create sdk client") } - uploader, err := uploaderp.New(&uploaderp.HuaweiCloudELBUploaderConfig{ + uploader, err := uploadersp.New(&uploadersp.HuaweiCloudELBUploaderConfig{ AccessKeyId: config.AccessKeyId, SecretAccessKey: config.SecretAccessKey, Region: config.Region, diff --git a/internal/pkg/core/deployer/providers/huaweicloud-waf/huaweicloud_waf.go b/internal/pkg/core/deployer/providers/huaweicloud-waf/huaweicloud_waf.go index 8c0ff029..4273d7f7 100644 --- a/internal/pkg/core/deployer/providers/huaweicloud-waf/huaweicloud_waf.go +++ b/internal/pkg/core/deployer/providers/huaweicloud-waf/huaweicloud_waf.go @@ -19,7 +19,7 @@ import ( "github.com/usual2970/certimate/internal/pkg/core/deployer" "github.com/usual2970/certimate/internal/pkg/core/logger" "github.com/usual2970/certimate/internal/pkg/core/uploader" - uploaderp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/huaweicloud-waf" + uploadersp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/huaweicloud-waf" hwsdk "github.com/usual2970/certimate/internal/pkg/vendors/huaweicloud-sdk" ) @@ -67,7 +67,7 @@ func NewWithLogger(config *HuaweiCloudWAFDeployerConfig, logger logger.Logger) ( return nil, xerrors.Wrap(err, "failed to create sdk client") } - uploader, err := uploaderp.New(&uploaderp.HuaweiCloudWAFUploaderConfig{ + uploader, err := uploadersp.New(&uploadersp.HuaweiCloudWAFUploaderConfig{ AccessKeyId: config.AccessKeyId, SecretAccessKey: config.SecretAccessKey, Region: config.Region, diff --git a/internal/pkg/core/deployer/providers/qiniu-cdn/qiniu_cdn.go b/internal/pkg/core/deployer/providers/qiniu-cdn/qiniu_cdn.go index 8fac6459..098e05aa 100644 --- a/internal/pkg/core/deployer/providers/qiniu-cdn/qiniu_cdn.go +++ b/internal/pkg/core/deployer/providers/qiniu-cdn/qiniu_cdn.go @@ -11,7 +11,7 @@ import ( "github.com/usual2970/certimate/internal/pkg/core/deployer" "github.com/usual2970/certimate/internal/pkg/core/logger" "github.com/usual2970/certimate/internal/pkg/core/uploader" - uploaderp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/qiniu-sslcert" + uploadersp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/qiniu-sslcert" qiniusdk "github.com/usual2970/certimate/internal/pkg/vendors/qiniu-sdk" ) @@ -48,7 +48,7 @@ func NewWithLogger(config *QiniuCDNDeployerConfig, logger logger.Logger) (*Qiniu client := qiniusdk.NewClient(auth.New(config.AccessKey, config.SecretKey)) - uploader, err := uploaderp.New(&uploaderp.QiniuSSLCertUploaderConfig{ + uploader, err := uploadersp.New(&uploadersp.QiniuSSLCertUploaderConfig{ AccessKey: config.AccessKey, SecretKey: config.SecretKey, }) diff --git a/internal/pkg/core/deployer/providers/qiniu-pili/qiniu_pili.go b/internal/pkg/core/deployer/providers/qiniu-pili/qiniu_pili.go index 4530071c..1b34f379 100644 --- a/internal/pkg/core/deployer/providers/qiniu-pili/qiniu_pili.go +++ b/internal/pkg/core/deployer/providers/qiniu-pili/qiniu_pili.go @@ -10,7 +10,7 @@ import ( "github.com/usual2970/certimate/internal/pkg/core/deployer" "github.com/usual2970/certimate/internal/pkg/core/logger" "github.com/usual2970/certimate/internal/pkg/core/uploader" - uploaderp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/qiniu-sslcert" + uploadersp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/qiniu-sslcert" ) type QiniuPiliDeployerConfig struct { @@ -48,7 +48,7 @@ func NewWithLogger(config *QiniuPiliDeployerConfig, logger logger.Logger) (*Qini manager := pili.NewManager(pili.ManagerConfig{AccessKey: config.AccessKey, SecretKey: config.SecretKey}) - uploader, err := uploaderp.New(&uploaderp.QiniuSSLCertUploaderConfig{ + uploader, err := uploadersp.New(&uploadersp.QiniuSSLCertUploaderConfig{ AccessKey: config.AccessKey, SecretKey: config.SecretKey, }) diff --git a/internal/pkg/core/deployer/providers/tencentcloud-cdn/tencentcloud_cdn.go b/internal/pkg/core/deployer/providers/tencentcloud-cdn/tencentcloud_cdn.go index 61418845..37c982bf 100644 --- a/internal/pkg/core/deployer/providers/tencentcloud-cdn/tencentcloud_cdn.go +++ b/internal/pkg/core/deployer/providers/tencentcloud-cdn/tencentcloud_cdn.go @@ -15,7 +15,7 @@ import ( "github.com/usual2970/certimate/internal/pkg/core/deployer" "github.com/usual2970/certimate/internal/pkg/core/logger" "github.com/usual2970/certimate/internal/pkg/core/uploader" - uploaderp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/tencentcloud-ssl" + uploadersp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/tencentcloud-ssl" ) type TencentCloudCDNDeployerConfig struct { @@ -59,7 +59,7 @@ func NewWithLogger(config *TencentCloudCDNDeployerConfig, logger logger.Logger) return nil, xerrors.Wrap(err, "failed to create sdk clients") } - uploader, err := uploaderp.New(&uploaderp.TencentCloudSSLUploaderConfig{ + uploader, err := uploadersp.New(&uploadersp.TencentCloudSSLUploaderConfig{ SecretId: config.SecretId, SecretKey: config.SecretKey, }) diff --git a/internal/pkg/core/deployer/providers/tencentcloud-clb/tencentcloud_clb.go b/internal/pkg/core/deployer/providers/tencentcloud-clb/tencentcloud_clb.go index 75eb5311..0f5532bc 100644 --- a/internal/pkg/core/deployer/providers/tencentcloud-clb/tencentcloud_clb.go +++ b/internal/pkg/core/deployer/providers/tencentcloud-clb/tencentcloud_clb.go @@ -14,7 +14,7 @@ import ( "github.com/usual2970/certimate/internal/pkg/core/deployer" "github.com/usual2970/certimate/internal/pkg/core/logger" "github.com/usual2970/certimate/internal/pkg/core/uploader" - uploaderp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/tencentcloud-ssl" + uploadersp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/tencentcloud-ssl" ) type TencentCloudCLBDeployerConfig struct { @@ -69,7 +69,7 @@ func NewWithLogger(config *TencentCloudCLBDeployerConfig, logger logger.Logger) return nil, xerrors.Wrap(err, "failed to create sdk clients") } - uploader, err := uploaderp.New(&uploaderp.TencentCloudSSLUploaderConfig{ + uploader, err := uploadersp.New(&uploadersp.TencentCloudSSLUploaderConfig{ SecretId: config.SecretId, SecretKey: config.SecretKey, }) diff --git a/internal/pkg/core/deployer/providers/tencentcloud-cos/tencentcloud_cos.go b/internal/pkg/core/deployer/providers/tencentcloud-cos/tencentcloud_cos.go index ca20b9dc..0efc2e7a 100644 --- a/internal/pkg/core/deployer/providers/tencentcloud-cos/tencentcloud_cos.go +++ b/internal/pkg/core/deployer/providers/tencentcloud-cos/tencentcloud_cos.go @@ -13,7 +13,7 @@ import ( "github.com/usual2970/certimate/internal/pkg/core/deployer" "github.com/usual2970/certimate/internal/pkg/core/logger" "github.com/usual2970/certimate/internal/pkg/core/uploader" - uploaderp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/tencentcloud-ssl" + uploadersp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/tencentcloud-ssl" ) type TencentCloudCOSDeployerConfig struct { @@ -56,7 +56,7 @@ func NewWithLogger(config *TencentCloudCOSDeployerConfig, logger logger.Logger) return nil, xerrors.Wrap(err, "failed to create sdk clients") } - uploader, err := uploaderp.New(&uploaderp.TencentCloudSSLUploaderConfig{ + uploader, err := uploadersp.New(&uploadersp.TencentCloudSSLUploaderConfig{ SecretId: config.SecretId, SecretKey: config.SecretKey, }) diff --git a/internal/pkg/core/deployer/providers/tencentcloud-css/tencentcloud_css.go b/internal/pkg/core/deployer/providers/tencentcloud-css/tencentcloud_css.go index 31057017..85f92780 100644 --- a/internal/pkg/core/deployer/providers/tencentcloud-css/tencentcloud_css.go +++ b/internal/pkg/core/deployer/providers/tencentcloud-css/tencentcloud_css.go @@ -12,7 +12,7 @@ import ( "github.com/usual2970/certimate/internal/pkg/core/deployer" "github.com/usual2970/certimate/internal/pkg/core/logger" "github.com/usual2970/certimate/internal/pkg/core/uploader" - uploaderp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/tencentcloud-ssl" + uploadersp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/tencentcloud-ssl" ) type TencentCloudCSSDeployerConfig struct { @@ -51,7 +51,7 @@ func NewWithLogger(config *TencentCloudCSSDeployerConfig, logger logger.Logger) return nil, xerrors.Wrap(err, "failed to create sdk client") } - uploader, err := uploaderp.New(&uploaderp.TencentCloudSSLUploaderConfig{ + uploader, err := uploadersp.New(&uploadersp.TencentCloudSSLUploaderConfig{ SecretId: config.SecretId, SecretKey: config.SecretKey, }) diff --git a/internal/pkg/core/deployer/providers/tencentcloud-ecdn/tencentcloud_ecdn.go b/internal/pkg/core/deployer/providers/tencentcloud-ecdn/tencentcloud_ecdn.go index 4cddbc59..803c48f7 100644 --- a/internal/pkg/core/deployer/providers/tencentcloud-ecdn/tencentcloud_ecdn.go +++ b/internal/pkg/core/deployer/providers/tencentcloud-ecdn/tencentcloud_ecdn.go @@ -14,7 +14,7 @@ import ( "github.com/usual2970/certimate/internal/pkg/core/deployer" "github.com/usual2970/certimate/internal/pkg/core/logger" "github.com/usual2970/certimate/internal/pkg/core/uploader" - uploaderp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/tencentcloud-ssl" + uploadersp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/tencentcloud-ssl" ) type TencentCloudECDNDeployerConfig struct { @@ -58,7 +58,7 @@ func NewWithLogger(config *TencentCloudECDNDeployerConfig, logger logger.Logger) return nil, xerrors.Wrap(err, "failed to create sdk clients") } - uploader, err := uploaderp.New(&uploaderp.TencentCloudSSLUploaderConfig{ + uploader, err := uploadersp.New(&uploadersp.TencentCloudSSLUploaderConfig{ SecretId: config.SecretId, SecretKey: config.SecretKey, }) diff --git a/internal/pkg/core/deployer/providers/tencentcloud-eo/tencentcloud_eo.go b/internal/pkg/core/deployer/providers/tencentcloud-eo/tencentcloud_eo.go index b0857f87..9c183fec 100644 --- a/internal/pkg/core/deployer/providers/tencentcloud-eo/tencentcloud_eo.go +++ b/internal/pkg/core/deployer/providers/tencentcloud-eo/tencentcloud_eo.go @@ -13,7 +13,7 @@ import ( "github.com/usual2970/certimate/internal/pkg/core/deployer" "github.com/usual2970/certimate/internal/pkg/core/logger" "github.com/usual2970/certimate/internal/pkg/core/uploader" - uploaderp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/tencentcloud-ssl" + uploadersp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/tencentcloud-ssl" ) type TencentCloudEODeployerConfig struct { @@ -59,7 +59,7 @@ func NewWithLogger(config *TencentCloudEODeployerConfig, logger logger.Logger) ( return nil, xerrors.Wrap(err, "failed to create sdk clients") } - uploader, err := uploaderp.New(&uploaderp.TencentCloudSSLUploaderConfig{ + uploader, err := uploadersp.New(&uploadersp.TencentCloudSSLUploaderConfig{ SecretId: config.SecretId, SecretKey: config.SecretKey, }) diff --git a/internal/pkg/core/deployer/providers/tencentcloud-ssl-deploy/tencentcloud_ssl_deploy.go b/internal/pkg/core/deployer/providers/tencentcloud-ssl-deploy/tencentcloud_ssl_deploy.go index 37c00ea4..aea9d4a4 100644 --- a/internal/pkg/core/deployer/providers/tencentcloud-ssl-deploy/tencentcloud_ssl_deploy.go +++ b/internal/pkg/core/deployer/providers/tencentcloud-ssl-deploy/tencentcloud_ssl_deploy.go @@ -14,7 +14,7 @@ import ( "github.com/usual2970/certimate/internal/pkg/core/deployer" "github.com/usual2970/certimate/internal/pkg/core/logger" "github.com/usual2970/certimate/internal/pkg/core/uploader" - uploaderp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/tencentcloud-ssl" + uploadersp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/tencentcloud-ssl" ) type TencentCloudSSLDeployDeployerConfig struct { @@ -57,7 +57,7 @@ func NewWithLogger(config *TencentCloudSSLDeployDeployerConfig, logger logger.Lo return nil, xerrors.Wrap(err, "failed to create sdk client") } - uploader, err := uploaderp.New(&uploaderp.TencentCloudSSLUploaderConfig{ + uploader, err := uploadersp.New(&uploadersp.TencentCloudSSLUploaderConfig{ SecretId: config.SecretId, SecretKey: config.SecretKey, }) diff --git a/internal/pkg/core/deployer/providers/tencentcloud-waf/tencentcloud_waf.go b/internal/pkg/core/deployer/providers/tencentcloud-waf/tencentcloud_waf.go index df54beef..4482d1f9 100644 --- a/internal/pkg/core/deployer/providers/tencentcloud-waf/tencentcloud_waf.go +++ b/internal/pkg/core/deployer/providers/tencentcloud-waf/tencentcloud_waf.go @@ -12,7 +12,7 @@ import ( "github.com/usual2970/certimate/internal/pkg/core/deployer" "github.com/usual2970/certimate/internal/pkg/core/logger" "github.com/usual2970/certimate/internal/pkg/core/uploader" - uploaderp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/tencentcloud-ssl" + uploadersp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/tencentcloud-ssl" ) type TencentCloudWAFDeployerConfig struct { @@ -57,7 +57,7 @@ func NewWithLogger(config *TencentCloudWAFDeployerConfig, logger logger.Logger) return nil, xerrors.Wrap(err, "failed to create sdk clients") } - uploader, err := uploaderp.New(&uploaderp.TencentCloudSSLUploaderConfig{ + uploader, err := uploadersp.New(&uploadersp.TencentCloudSSLUploaderConfig{ SecretId: config.SecretId, SecretKey: config.SecretKey, }) diff --git a/internal/pkg/core/deployer/providers/ucloud-ucdn/ucloud_ucdn.go b/internal/pkg/core/deployer/providers/ucloud-ucdn/ucloud_ucdn.go index fa104ba3..3fdfd611 100644 --- a/internal/pkg/core/deployer/providers/ucloud-ucdn/ucloud_ucdn.go +++ b/internal/pkg/core/deployer/providers/ucloud-ucdn/ucloud_ucdn.go @@ -13,7 +13,7 @@ import ( "github.com/usual2970/certimate/internal/pkg/core/deployer" "github.com/usual2970/certimate/internal/pkg/core/logger" "github.com/usual2970/certimate/internal/pkg/core/uploader" - uploaderp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/ucloud-ussl" + uploadersp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/ucloud-ussl" ) type UCloudUCDNDeployerConfig struct { @@ -54,7 +54,7 @@ func NewWithLogger(config *UCloudUCDNDeployerConfig, logger logger.Logger) (*UCl return nil, xerrors.Wrap(err, "failed to create sdk client") } - uploader, err := uploaderp.New(&uploaderp.UCloudUSSLUploaderConfig{ + uploader, err := uploadersp.New(&uploadersp.UCloudUSSLUploaderConfig{ PrivateKey: config.PrivateKey, PublicKey: config.PublicKey, ProjectId: config.ProjectId, diff --git a/internal/pkg/core/deployer/providers/ucloud-us3/ucloud_us3.go b/internal/pkg/core/deployer/providers/ucloud-us3/ucloud_us3.go index ccf03224..93a3792c 100644 --- a/internal/pkg/core/deployer/providers/ucloud-us3/ucloud_us3.go +++ b/internal/pkg/core/deployer/providers/ucloud-us3/ucloud_us3.go @@ -11,7 +11,7 @@ import ( "github.com/usual2970/certimate/internal/pkg/core/deployer" "github.com/usual2970/certimate/internal/pkg/core/logger" "github.com/usual2970/certimate/internal/pkg/core/uploader" - uploaderp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/ucloud-ussl" + uploadersp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/ucloud-ussl" usdkFile "github.com/usual2970/certimate/internal/pkg/vendors/ucloud-sdk/ufile" ) @@ -57,7 +57,7 @@ func NewWithLogger(config *UCloudUS3DeployerConfig, logger logger.Logger) (*UClo return nil, xerrors.Wrap(err, "failed to create sdk client") } - uploader, err := uploaderp.New(&uploaderp.UCloudUSSLUploaderConfig{ + uploader, err := uploadersp.New(&uploadersp.UCloudUSSLUploaderConfig{ PrivateKey: config.PrivateKey, PublicKey: config.PublicKey, ProjectId: config.ProjectId, diff --git a/internal/pkg/core/deployer/providers/volcengine-cdn/volcengine_cdn.go b/internal/pkg/core/deployer/providers/volcengine-cdn/volcengine_cdn.go index de3e76e4..f2ddd753 100644 --- a/internal/pkg/core/deployer/providers/volcengine-cdn/volcengine_cdn.go +++ b/internal/pkg/core/deployer/providers/volcengine-cdn/volcengine_cdn.go @@ -12,7 +12,7 @@ import ( "github.com/usual2970/certimate/internal/pkg/core/deployer" "github.com/usual2970/certimate/internal/pkg/core/logger" "github.com/usual2970/certimate/internal/pkg/core/uploader" - uploaderp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/volcengine-cdn" + uploadersp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/volcengine-cdn" ) type VolcEngineCDNDeployerConfig struct { @@ -50,7 +50,7 @@ func NewWithLogger(config *VolcEngineCDNDeployerConfig, logger logger.Logger) (* client.Client.SetAccessKey(config.AccessKeyId) client.Client.SetSecretKey(config.AccessKeySecret) - uploader, err := uploaderp.New(&uploaderp.VolcEngineCDNUploaderConfig{ + uploader, err := uploadersp.New(&uploadersp.VolcEngineCDNUploaderConfig{ AccessKeyId: config.AccessKeyId, AccessKeySecret: config.AccessKeySecret, }) diff --git a/internal/pkg/core/deployer/providers/volcengine-clb/volcengine_clb.go b/internal/pkg/core/deployer/providers/volcengine-clb/volcengine_clb.go index 4c03002d..55311db9 100644 --- a/internal/pkg/core/deployer/providers/volcengine-clb/volcengine_clb.go +++ b/internal/pkg/core/deployer/providers/volcengine-clb/volcengine_clb.go @@ -13,7 +13,7 @@ import ( "github.com/usual2970/certimate/internal/pkg/core/deployer" "github.com/usual2970/certimate/internal/pkg/core/logger" "github.com/usual2970/certimate/internal/pkg/core/uploader" - uploaderp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/volcengine-certcenter" + uploadersp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/volcengine-certcenter" ) type VolcEngineCLBDeployerConfig struct { @@ -57,7 +57,7 @@ func NewWithLogger(config *VolcEngineCLBDeployerConfig, logger logger.Logger) (* return nil, xerrors.Wrap(err, "failed to create sdk client") } - uploader, err := uploaderp.New(&uploaderp.VolcEngineCertCenterUploaderConfig{ + uploader, err := uploadersp.New(&uploadersp.VolcEngineCertCenterUploaderConfig{ AccessKeyId: config.AccessKeyId, AccessKeySecret: config.AccessKeySecret, Region: config.Region, diff --git a/internal/pkg/core/deployer/providers/volcengine-dcdn/volcengine_dcdn.go b/internal/pkg/core/deployer/providers/volcengine-dcdn/volcengine_dcdn.go index 0f9f8e51..67686fa8 100644 --- a/internal/pkg/core/deployer/providers/volcengine-dcdn/volcengine_dcdn.go +++ b/internal/pkg/core/deployer/providers/volcengine-dcdn/volcengine_dcdn.go @@ -13,7 +13,7 @@ import ( "github.com/usual2970/certimate/internal/pkg/core/deployer" "github.com/usual2970/certimate/internal/pkg/core/logger" "github.com/usual2970/certimate/internal/pkg/core/uploader" - uploaderp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/volcengine-certcenter" + uploadersp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/volcengine-certcenter" ) type VolcEngineDCDNDeployerConfig struct { @@ -54,7 +54,7 @@ func NewWithLogger(config *VolcEngineDCDNDeployerConfig, logger logger.Logger) ( return nil, xerrors.Wrap(err, "failed to create sdk client") } - uploader, err := uploaderp.New(&uploaderp.VolcEngineCertCenterUploaderConfig{ + uploader, err := uploadersp.New(&uploadersp.VolcEngineCertCenterUploaderConfig{ AccessKeyId: config.AccessKeyId, AccessKeySecret: config.AccessKeySecret, Region: config.Region, diff --git a/internal/pkg/core/deployer/providers/volcengine-imagex/volcengine_imagex.go b/internal/pkg/core/deployer/providers/volcengine-imagex/volcengine_imagex.go index dea81300..1d174261 100644 --- a/internal/pkg/core/deployer/providers/volcengine-imagex/volcengine_imagex.go +++ b/internal/pkg/core/deployer/providers/volcengine-imagex/volcengine_imagex.go @@ -11,7 +11,7 @@ import ( "github.com/usual2970/certimate/internal/pkg/core/deployer" "github.com/usual2970/certimate/internal/pkg/core/logger" "github.com/usual2970/certimate/internal/pkg/core/uploader" - uploaderp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/volcengine-certcenter" + uploadersp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/volcengine-certcenter" ) type VolcEngineImageXDeployerConfig struct { @@ -54,7 +54,7 @@ func NewWithLogger(config *VolcEngineImageXDeployerConfig, logger logger.Logger) return nil, xerrors.Wrap(err, "failed to create sdk client") } - uploader, err := uploaderp.New(&uploaderp.VolcEngineCertCenterUploaderConfig{ + uploader, err := uploadersp.New(&uploadersp.VolcEngineCertCenterUploaderConfig{ AccessKeyId: config.AccessKeyId, AccessKeySecret: config.AccessKeySecret, Region: config.Region, diff --git a/internal/pkg/core/deployer/providers/volcengine-live/volcengine_live.go b/internal/pkg/core/deployer/providers/volcengine-live/volcengine_live.go index b23f4c6c..580d6ae1 100644 --- a/internal/pkg/core/deployer/providers/volcengine-live/volcengine_live.go +++ b/internal/pkg/core/deployer/providers/volcengine-live/volcengine_live.go @@ -13,7 +13,7 @@ import ( "github.com/usual2970/certimate/internal/pkg/core/deployer" "github.com/usual2970/certimate/internal/pkg/core/logger" "github.com/usual2970/certimate/internal/pkg/core/uploader" - uploaderp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/volcengine-live" + uploadersp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/volcengine-live" ) type VolcEngineLiveDeployerConfig struct { @@ -51,7 +51,7 @@ func NewWithLogger(config *VolcEngineLiveDeployerConfig, logger logger.Logger) ( client.SetAccessKey(config.AccessKeyId) client.SetSecretKey(config.AccessKeySecret) - uploader, err := uploaderp.New(&uploaderp.VolcEngineLiveUploaderConfig{ + uploader, err := uploadersp.New(&uploadersp.VolcEngineLiveUploaderConfig{ AccessKeyId: config.AccessKeyId, AccessKeySecret: config.AccessKeySecret, }) diff --git a/internal/pkg/core/deployer/providers/volcengine-tos/volcengine_tos.go b/internal/pkg/core/deployer/providers/volcengine-tos/volcengine_tos.go index 9a238f27..19c97fc7 100644 --- a/internal/pkg/core/deployer/providers/volcengine-tos/volcengine_tos.go +++ b/internal/pkg/core/deployer/providers/volcengine-tos/volcengine_tos.go @@ -11,7 +11,7 @@ import ( "github.com/usual2970/certimate/internal/pkg/core/deployer" "github.com/usual2970/certimate/internal/pkg/core/logger" "github.com/usual2970/certimate/internal/pkg/core/uploader" - uploaderp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/volcengine-certcenter" + uploadersp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/volcengine-certcenter" ) type VolcEngineTOSDeployerConfig struct { @@ -54,7 +54,7 @@ func NewWithLogger(config *VolcEngineTOSDeployerConfig, logger logger.Logger) (* return nil, xerrors.Wrap(err, "failed to create sdk client") } - uploader, err := uploaderp.New(&uploaderp.VolcEngineCertCenterUploaderConfig{ + uploader, err := uploadersp.New(&uploadersp.VolcEngineCertCenterUploaderConfig{ AccessKeyId: config.AccessKeyId, AccessKeySecret: config.AccessKeySecret, Region: config.Region, diff --git a/ui/src/components/workflow/node/DeployNodeConfigForm.tsx b/ui/src/components/workflow/node/DeployNodeConfigForm.tsx index 50faa78b..b0586aae 100644 --- a/ui/src/components/workflow/node/DeployNodeConfigForm.tsx +++ b/ui/src/components/workflow/node/DeployNodeConfigForm.tsx @@ -33,6 +33,7 @@ import DeployNodeConfigFormBaotaPanelSiteConfig from "./DeployNodeConfigFormBaot import DeployNodeConfigFormBytePlusCDNConfig from "./DeployNodeConfigFormBytePlusCDNConfig"; import DeployNodeConfigFormDogeCloudCDNConfig from "./DeployNodeConfigFormDogeCloudCDNConfig"; import DeployNodeConfigFormEdgioApplicationsConfig from "./DeployNodeConfigFormEdgioApplicationsConfig"; +import DeployNodeConfigFormGcoreCDNConfig from "./DeployNodeConfigFormGcoreCDNConfig"; import DeployNodeConfigFormHuaweiCloudCDNConfig from "./DeployNodeConfigFormHuaweiCloudCDNConfig"; import DeployNodeConfigFormHuaweiCloudELBConfig from "./DeployNodeConfigFormHuaweiCloudELBConfig"; import DeployNodeConfigFormHuaweiCloudWAFConfig from "./DeployNodeConfigFormHuaweiCloudWAFConfig"; @@ -167,6 +168,8 @@ const DeployNodeConfigForm = forwardRef; case DEPLOY_PROVIDERS.EDGIO_APPLICATIONS: return ; + case DEPLOY_PROVIDERS.GCORE_CDN: + return ; case DEPLOY_PROVIDERS.HUAWEICLOUD_CDN: return ; case DEPLOY_PROVIDERS.HUAWEICLOUD_ELB: @@ -237,7 +240,7 @@ const DeployNodeConfigForm = forwardRef = {}; for (const key in oldValues) { - if (key === "provider" || key === "providerAccessId" || key === "certificate") { + if (key === "provider" || key === "providerAccessId" || key === "certificate" || key === "skipOnLastSucceeded") { newValues[key] = oldValues[key]; } else { newValues[key] = undefined; diff --git a/ui/src/components/workflow/node/DeployNodeConfigFormGcoreCDNConfig.tsx b/ui/src/components/workflow/node/DeployNodeConfigFormGcoreCDNConfig.tsx new file mode 100644 index 00000000..84d5e410 --- /dev/null +++ b/ui/src/components/workflow/node/DeployNodeConfigFormGcoreCDNConfig.tsx @@ -0,0 +1,59 @@ +import { useTranslation } from "react-i18next"; +import { Form, type FormInstance, Input } from "antd"; +import { createSchemaFieldRule } from "antd-zod"; +import { z } from "zod"; + +type DeployNodeConfigFormGcoreCDNConfigFieldValues = Nullish<{ + resourceId?: string; +}>; + +export type DeployNodeConfigFormGcoreCDNConfigProps = { + form: FormInstance; + formName: string; + disabled?: boolean; + initialValues?: DeployNodeConfigFormGcoreCDNConfigFieldValues; + onValuesChange?: (values: DeployNodeConfigFormGcoreCDNConfigFieldValues) => void; +}; + +const initFormModel = (): DeployNodeConfigFormGcoreCDNConfigFieldValues => { + return { + resourceId: "", + }; +}; + +const DeployNodeConfigFormGcoreCDNConfig = ({ form: formInst, formName, disabled, initialValues, onValuesChange }: DeployNodeConfigFormGcoreCDNConfigProps) => { + const { t } = useTranslation(); + + const formSchema = z.object({ + resourceId: z + .string({ message: t("workflow_node.deploy.form.gcore_cdn_certificate_id.placeholder") }) + .regex(/^\d+$/, t("workflow_node.deploy.form.gcore_cdn_certificate_id.placeholder")), + }); + const formRule = createSchemaFieldRule(formSchema); + + const handleFormChange = (_: unknown, values: z.infer) => { + onValuesChange?.(values); + }; + + return ( +
+ } + > + + +
+ ); +}; + +export default DeployNodeConfigFormGcoreCDNConfig; diff --git a/ui/src/domain/provider.ts b/ui/src/domain/provider.ts index 4ccd7f7b..53eb7898 100644 --- a/ui/src/domain/provider.ts +++ b/ui/src/domain/provider.ts @@ -68,6 +68,7 @@ export const accessProvidersMap: Map [ type, diff --git a/ui/src/i18n/locales/en/nls.provider.json b/ui/src/i18n/locales/en/nls.provider.json index cb935fff..dcd555c3 100644 --- a/ui/src/i18n/locales/en/nls.provider.json +++ b/ui/src/i18n/locales/en/nls.provider.json @@ -42,6 +42,7 @@ "provider.edgio.applications": "Edgio - Applications", "provider.fastly": "Fastly", "provider.gcore": "Gcore", + "provider.gcore.cdn": "Gcore - CDN (Content Delivery Network)", "provider.gname": "GNAME", "provider.godaddy": "GoDaddy", "provider.goedge": "GoEdge", diff --git a/ui/src/i18n/locales/en/nls.workflow.nodes.json b/ui/src/i18n/locales/en/nls.workflow.nodes.json index dbfded50..e6a59086 100644 --- a/ui/src/i18n/locales/en/nls.workflow.nodes.json +++ b/ui/src/i18n/locales/en/nls.workflow.nodes.json @@ -206,6 +206,9 @@ "workflow_node.deploy.form.edgio_applications_environment_id.label": "Edgio Applications environment ID", "workflow_node.deploy.form.edgio_applications_environment_id.placeholder": "Please enter Edgio Applications environment ID", "workflow_node.deploy.form.edgio_applications_environment_id.tooltip": "For more information, see https://edgio.app/", + "workflow_node.deploy.form.gcore_cdn_resource_id.label": "Gcore CDN resource ID", + "workflow_node.deploy.form.gcore_cdn_resource_id.placeholder": "Please enter Gcore CDN resource ID", + "workflow_node.deploy.form.gcore_cdn_resource_id.tooltip": "For more information, see https://cdn.gcore.com/resources/list", "workflow_node.deploy.form.huaweicloud_cdn_region.label": "Huawei Cloud CDN region", "workflow_node.deploy.form.huaweicloud_cdn_region.placeholder": "Please enter Huawei Cloud CDN region (e.g. cn-north-1)", "workflow_node.deploy.form.huaweicloud_cdn_region.tooltip": "For more information, see https://console-intl.huaweicloud.com/apiexplorer/#/endpoint", diff --git a/ui/src/i18n/locales/zh/nls.provider.json b/ui/src/i18n/locales/zh/nls.provider.json index ec9f3241..95cbeef7 100644 --- a/ui/src/i18n/locales/zh/nls.provider.json +++ b/ui/src/i18n/locales/zh/nls.provider.json @@ -42,6 +42,7 @@ "provider.edgio.applications": "Edgio - Applications", "provider.fastly": "Fastly", "provider.gcore": "Gcore", + "provider.gcore.cdn": "Gcore - 内容分发网络 CDN", "provider.gname": "GNAME", "provider.godaddy": "GoDaddy", "provider.goedge": "GoEdge", diff --git a/ui/src/i18n/locales/zh/nls.workflow.nodes.json b/ui/src/i18n/locales/zh/nls.workflow.nodes.json index 2a0f2313..5335d5aa 100644 --- a/ui/src/i18n/locales/zh/nls.workflow.nodes.json +++ b/ui/src/i18n/locales/zh/nls.workflow.nodes.json @@ -206,6 +206,9 @@ "workflow_node.deploy.form.edgio_applications_environment_id.label": "Edgio Applications 环境 ID", "workflow_node.deploy.form.edgio_applications_environment_id.placeholder": "请输入 Edgio Applications 环境 ID", "workflow_node.deploy.form.edgio_applications_environment_id.tooltip": "这是什么?请参阅 https://edgio.app/", + "workflow_node.deploy.form.gcore_cdn_resource_id.label": "Gcore CDN 资源 ID", + "workflow_node.deploy.form.gcore_cdn_resource_id.placeholder": "请输入 Gcore CDN 资源 ID", + "workflow_node.deploy.form.gcore_cdn_resource_id.tooltip": "这是什么?请参阅 https://cdn.gcore.com/resources/list", "workflow_node.deploy.form.huaweicloud_cdn_region.label": "华为云 CDN 服务区域", "workflow_node.deploy.form.huaweicloud_cdn_region.placeholder": "请输入华为云 CDN 服务区域(例如:cn-north-1)", "workflow_node.deploy.form.huaweicloud_cdn_region.tooltip": "这是什么?请参阅 https://console.huaweicloud.com/apiexplorer/#/endpoint", From 46f02331fd8392c96a543d5e4c1996517f33f7ac Mon Sep 17 00:00:00 2001 From: Fu Diwei Date: Tue, 18 Feb 2025 11:45:41 +0800 Subject: [PATCH 11/34] feat: add cachefly deployer --- README.md | 1 + README_EN.md | 1 + internal/deployer/providers.go | 14 +++ internal/domain/access.go | 6 +- internal/domain/provider.go | 5 +- .../baotapanel-site/baotapanel_site.go | 2 +- .../deployer/providers/cachefly/cachefly.go | 71 +++++++++++++ .../providers/cachefly/cachefly_test.go | 65 ++++++++++++ internal/pkg/vendors/baishan-sdk/client.go | 30 ++---- internal/pkg/vendors/baishan-sdk/models.go | 18 ++-- internal/pkg/vendors/btpanel-sdk/client.go | 14 +-- internal/pkg/vendors/cachefly-sdk/api.go | 19 ++++ internal/pkg/vendors/cachefly-sdk/client.go | 72 +++++++++++++ internal/pkg/vendors/cachefly-sdk/models.go | 35 +++++++ internal/pkg/vendors/gname-sdk/client.go | 12 +-- internal/pkg/vendors/safeline-sdk/client.go | 16 ++- ui/public/imgs/acme/letsencrypt.svg | 2 +- ui/public/imgs/providers/acmehttpreq.svg | 2 +- ui/public/imgs/providers/aliyun.svg | 2 +- ui/public/imgs/providers/aws.svg | 2 +- ui/public/imgs/providers/azure.svg | 2 +- ui/public/imgs/providers/baiducloud.svg | 2 +- ui/public/imgs/providers/cachefly.png | Bin 0 -> 11406 bytes ui/public/imgs/providers/cloudflare.svg | 2 +- ui/public/imgs/providers/cloudns.png | Bin 0 -> 5314 bytes ui/public/imgs/providers/cloudns.svg | 99 ------------------ ui/public/imgs/providers/dogecloud.png | Bin 0 -> 8929 bytes ui/public/imgs/providers/dogecloud.svg | 1 - ui/public/imgs/providers/gname.png | Bin 0 -> 4480 bytes ui/public/imgs/providers/gname.svg | 1 - ui/public/imgs/providers/godaddy.svg | 2 +- ui/public/imgs/providers/huaweicloud.svg | 2 +- ui/public/imgs/providers/kubernetes.svg | 2 +- ui/public/imgs/providers/local.svg | 2 +- ui/public/imgs/providers/namesilo.svg | 2 +- ui/public/imgs/providers/powerdns.svg | 2 +- ui/public/imgs/providers/qiniu.svg | 2 +- ui/public/imgs/providers/safeline.svg | 2 +- ui/public/imgs/providers/ssh.svg | 2 +- ui/public/imgs/providers/tencentcloud.svg | 2 +- ui/public/imgs/providers/ucloud.svg | 2 +- ui/public/imgs/providers/webhook.svg | 2 +- ui/public/imgs/providers/westcn.svg | 2 +- ui/src/components/access/AccessForm.tsx | 3 + .../access/AccessFormCacheFlyConfig.tsx | 56 ++++++++++ .../workflow/node/DeployNodeConfigForm.tsx | 17 ++- ui/src/domain/access.ts | 5 + ui/src/domain/provider.ts | 12 ++- ui/src/i18n/locales/en/nls.access.json | 3 + ui/src/i18n/locales/en/nls.provider.json | 2 +- ui/src/i18n/locales/zh/nls.access.json | 3 + ui/src/i18n/locales/zh/nls.provider.json | 2 +- 52 files changed, 433 insertions(+), 192 deletions(-) create mode 100644 internal/pkg/core/deployer/providers/cachefly/cachefly.go create mode 100644 internal/pkg/core/deployer/providers/cachefly/cachefly_test.go create mode 100644 internal/pkg/vendors/cachefly-sdk/api.go create mode 100644 internal/pkg/vendors/cachefly-sdk/client.go create mode 100644 internal/pkg/vendors/cachefly-sdk/models.go create mode 100644 ui/public/imgs/providers/cachefly.png create mode 100644 ui/public/imgs/providers/cloudns.png delete mode 100644 ui/public/imgs/providers/cloudns.svg create mode 100644 ui/public/imgs/providers/dogecloud.png delete mode 100644 ui/public/imgs/providers/dogecloud.svg create mode 100644 ui/public/imgs/providers/gname.png delete mode 100644 ui/public/imgs/providers/gname.svg create mode 100644 ui/src/components/access/AccessFormCacheFlyConfig.tsx diff --git a/README.md b/README.md index 95180539..ab7d553c 100644 --- a/README.md +++ b/README.md @@ -136,6 +136,7 @@ make local.run | [宝塔面板](https://www.bt.cn/) | 可部署到宝塔面板 | | [AWS](https://aws.amazon.com/) | 可部署到 AWS CloudFront | | [BytePlus](https://www.byteplus.com/) | 可部署到 BytePlus CDN | +| [CacheFly](https://www.cachefly.com/) | 可部署到 CacheFly CDN | | [Edgio](https://edg.io/) | 可部署到 Edgio Applications | | [Gcore](https://gcore.com/) | 可部署到 Gcore CDN | diff --git a/README_EN.md b/README_EN.md index c47de082..1320f3ea 100644 --- a/README_EN.md +++ b/README_EN.md @@ -135,6 +135,7 @@ The following hosting providers are supported: | [BaoTa Panel](https://www.bt.cn/) | Supports deployment to BaoTa Panel sites | | [AWS](https://aws.amazon.com/) | Supports deployment to AWS CloudFront | | [BytePlus](https://www.byteplus.com/) | Supports deployment to BytePlus CDN | +| [CacheFly](https://www.cachefly.com/) | Supports deployment to CacheFly CDN | | [Edgio](https://edg.io/) | Supports deployment to Edgio Applications | | [Gcore](https://gcore.com/) | Supports deployment to Gcore CDN | diff --git a/internal/deployer/providers.go b/internal/deployer/providers.go index 8903f96b..5c3c53ed 100644 --- a/internal/deployer/providers.go +++ b/internal/deployer/providers.go @@ -22,6 +22,7 @@ import ( pBaotaPanelConsole "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/baotapanel-console" pBaotaPanelSite "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/baotapanel-site" pBytePlusCDN "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/byteplus-cdn" + pCacheFly "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/cachefly" pDogeCDN "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/dogecloud-cdn" pEdgioApplications "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/edgio-applications" pGcoreCDN "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/gcore-cdn" @@ -288,6 +289,19 @@ func createDeployer(options *deployerOptions) (deployer.Deployer, logger.Logger, } } + case domain.DeployProviderTypeCacheFly: + { + access := domain.AccessConfigForCacheFly{} + if err := maps.Populate(options.ProviderAccessConfig, &access); err != nil { + return nil, nil, fmt.Errorf("failed to populate provider access config: %w", err) + } + + deployer, err := pCacheFly.NewWithLogger(&pCacheFly.CacheFlyDeployerConfig{ + ApiToken: access.ApiToken, + }, logger) + return deployer, logger, err + } + case domain.DeployProviderTypeDogeCloudCDN: { access := domain.AccessConfigForDogeCloud{} diff --git a/internal/domain/access.go b/internal/domain/access.go index 4136a276..b21b5a3f 100644 --- a/internal/domain/access.go +++ b/internal/domain/access.go @@ -67,6 +67,10 @@ type AccessConfigForBytePlus struct { SecretKey string `json:"secretKey"` } +type AccessConfigForCacheFly struct { + ApiToken string `json:"apiToken"` +} + type AccessConfigForCloudflare struct { DnsApiToken string `json:"dnsApiToken"` } @@ -87,7 +91,7 @@ type AccessConfigForEdgio struct { } type AccessConfigForGcore struct { - ApiToken string `json:"apiToken"` + ApiToken string `json:"apiToken"` } type AccessConfigForGname struct { diff --git a/internal/domain/provider.go b/internal/domain/provider.go index 8d2fd046..94e8c7ae 100644 --- a/internal/domain/provider.go +++ b/internal/domain/provider.go @@ -19,8 +19,8 @@ const ( AccessProviderTypeBaishan = AccessProviderType("baishan") AccessProviderTypeBaotaPanel = AccessProviderType("baotapanel") AccessProviderTypeBytePlus = AccessProviderType("byteplus") - AccessProviderTypeCacheFly = AccessProviderType("cachefly") // CacheFly(预留) - AccessProviderTypeCdnfly = AccessProviderType("cdnfly") // Cdnly(预留) + AccessProviderTypeCacheFly = AccessProviderType("cachefly") + AccessProviderTypeCdnfly = AccessProviderType("cdnfly") // Cdnly(预留) AccessProviderTypeCloudflare = AccessProviderType("cloudflare") AccessProviderTypeClouDNS = AccessProviderType("cloudns") AccessProviderTypeCMCCCloud = AccessProviderType("cmcccloud") // 移动云(预留) @@ -112,6 +112,7 @@ const ( DeployProviderTypeBaotaPanelConsole = DeployProviderType("baotapanel-console") DeployProviderTypeBaotaPanelSite = DeployProviderType("baotapanel-site") DeployProviderTypeBytePlusCDN = DeployProviderType("byteplus-cdn") + DeployProviderTypeCacheFly = DeployProviderType("cachefly") DeployProviderTypeDogeCloudCDN = DeployProviderType("dogecloud-cdn") DeployProviderTypeEdgioApplications = DeployProviderType("edgio-applications") DeployProviderTypeGcoreCDN = DeployProviderType("gcore-cdn") diff --git a/internal/pkg/core/deployer/providers/baotapanel-site/baotapanel_site.go b/internal/pkg/core/deployer/providers/baotapanel-site/baotapanel_site.go index d2d8622f..14261968 100644 --- a/internal/pkg/core/deployer/providers/baotapanel-site/baotapanel_site.go +++ b/internal/pkg/core/deployer/providers/baotapanel-site/baotapanel_site.go @@ -61,7 +61,7 @@ func (d *BaotaPanelSiteDeployer) Deploy(ctx context.Context, certPem string, pri // 设置站点 SSL 证书 siteSetSSLReq := &btsdk.SiteSetSSLRequest{ SiteName: d.config.SiteName, - Type: "1", + Type: "0", PrivateKey: privkeyPem, Certificate: certPem, } diff --git a/internal/pkg/core/deployer/providers/cachefly/cachefly.go b/internal/pkg/core/deployer/providers/cachefly/cachefly.go new file mode 100644 index 00000000..fe3fb3e4 --- /dev/null +++ b/internal/pkg/core/deployer/providers/cachefly/cachefly.go @@ -0,0 +1,71 @@ +package cachefly + +import ( + "context" + "errors" + + xerrors "github.com/pkg/errors" + + "github.com/usual2970/certimate/internal/pkg/core/deployer" + "github.com/usual2970/certimate/internal/pkg/core/logger" + cfsdk "github.com/usual2970/certimate/internal/pkg/vendors/cachefly-sdk" +) + +type CacheFlyDeployerConfig struct { + // CacheFly API Token。 + ApiToken string `json:"apiToken"` +} + +type CacheFlyDeployer struct { + config *CacheFlyDeployerConfig + logger logger.Logger + sdkClient *cfsdk.Client +} + +var _ deployer.Deployer = (*CacheFlyDeployer)(nil) + +func New(config *CacheFlyDeployerConfig) (*CacheFlyDeployer, error) { + return NewWithLogger(config, logger.NewNilLogger()) +} + +func NewWithLogger(config *CacheFlyDeployerConfig, logger logger.Logger) (*CacheFlyDeployer, error) { + if config == nil { + return nil, errors.New("config is nil") + } + + if logger == nil { + return nil, errors.New("logger is nil") + } + + client, err := createSdkClient(config.ApiToken) + if err != nil { + return nil, xerrors.Wrap(err, "failed to create sdk client") + } + + return &CacheFlyDeployer{ + logger: logger, + config: config, + sdkClient: client, + }, nil +} + +func (d *CacheFlyDeployer) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { + // 上传证书 + createCertificateReq := &cfsdk.CreateCertificateRequest{ + Certificate: certPem, + CertificateKey: privkeyPem, + } + createCertificateResp, err := d.sdkClient.CreateCertificate(createCertificateReq) + if err != nil { + return nil, xerrors.Wrap(err, "failed to execute sdk request 'cachefly.CreateCertificate'") + } else { + d.logger.Logt("已上传证书", createCertificateResp) + } + + return &deployer.DeployResult{}, nil +} + +func createSdkClient(apiToken string) (*cfsdk.Client, error) { + client := cfsdk.NewClient(apiToken) + return client, nil +} diff --git a/internal/pkg/core/deployer/providers/cachefly/cachefly_test.go b/internal/pkg/core/deployer/providers/cachefly/cachefly_test.go new file mode 100644 index 00000000..fcef1172 --- /dev/null +++ b/internal/pkg/core/deployer/providers/cachefly/cachefly_test.go @@ -0,0 +1,65 @@ +package cachefly_test + +import ( + "context" + "flag" + "fmt" + "os" + "strings" + "testing" + + provider "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/cachefly" +) + +var ( + fInputCertPath string + fInputKeyPath string + fApiToken string +) + +func init() { + argsPrefix := "CERTIMATE_DEPLOYER_CACHEFLY_" + + flag.StringVar(&fInputCertPath, argsPrefix+"INPUTCERTPATH", "", "") + flag.StringVar(&fInputKeyPath, argsPrefix+"INPUTKEYPATH", "", "") + flag.StringVar(&fApiToken, argsPrefix+"APITOKEN", "", "") +} + +/* +Shell command to run this test: + + go test -v ./cachefly_test.go -args \ + --CERTIMATE_DEPLOYER_CACHEFLY_INPUTCERTPATH="/path/to/your-input-cert.pem" \ + --CERTIMATE_DEPLOYER_CACHEFLY_INPUTKEYPATH="/path/to/your-input-key.pem" \ + --CERTIMATE_DEPLOYER_CACHEFLY_APITOKEN="your-baota-panel-key" +*/ +func TestDeploy(t *testing.T) { + flag.Parse() + + t.Run("Deploy", func(t *testing.T) { + t.Log(strings.Join([]string{ + "args:", + fmt.Sprintf("INPUTCERTPATH: %v", fInputCertPath), + fmt.Sprintf("INPUTKEYPATH: %v", fInputKeyPath), + fmt.Sprintf("APITOKEN: %v", fApiToken), + }, "\n")) + + deployer, err := provider.New(&provider.CacheFlyDeployerConfig{ + ApiToken: fApiToken, + }) + if err != nil { + t.Errorf("err: %+v", err) + return + } + + fInputCertData, _ := os.ReadFile(fInputCertPath) + fInputKeyData, _ := os.ReadFile(fInputKeyPath) + res, err := deployer.Deploy(context.Background(), string(fInputCertData), string(fInputKeyData)) + if err != nil { + t.Errorf("err: %+v", err) + return + } + + t.Logf("ok: %v", res) + }) +} diff --git a/internal/pkg/vendors/baishan-sdk/client.go b/internal/pkg/vendors/baishan-sdk/client.go index 28cb0bc3..c49698ea 100644 --- a/internal/pkg/vendors/baishan-sdk/client.go +++ b/internal/pkg/vendors/baishan-sdk/client.go @@ -4,6 +4,7 @@ import ( "encoding/json" "fmt" "net/http" + "strings" "time" "github.com/go-resty/resty/v2" @@ -32,7 +33,9 @@ func (c *Client) sendRequest(method string, path string, params map[string]any) url := "https://cdn.api.baishan.com" + path req := c.client.R() - if method == http.MethodGet { + req.Method = method + req.URL = url + if strings.EqualFold(method, http.MethodGet) { data := make(map[string]string) for k, v := range params { data[k] = fmt.Sprintf("%v", v) @@ -40,27 +43,18 @@ func (c *Client) sendRequest(method string, path string, params map[string]any) req = req. SetQueryParams(data). SetQueryParam("token", c.apiToken) - } else if method == http.MethodPost { + } else { req = req. SetHeader("Content-Type", "application/json"). SetQueryParam("token", c.apiToken). SetBody(params) } - var resp *resty.Response - var err error - if method == http.MethodGet { - resp, err = req.Get(url) - } else if method == http.MethodPost { - resp, err = req.Post(url) - } else { - return nil, fmt.Errorf("baishan: unsupported method: %s", method) - } - + resp, err := req.Send() if err != nil { - return nil, fmt.Errorf("baishan: failed to send request: %w", err) + return nil, fmt.Errorf("baishan api error: failed to send request: %w", err) } else if resp.IsError() { - return nil, fmt.Errorf("baishan: unexpected status code: %d, %s", resp.StatusCode(), resp.Body()) + return nil, fmt.Errorf("baishan api error: unexpected status code: %d, %s", resp.StatusCode(), resp.Body()) } return resp, nil @@ -73,11 +67,9 @@ func (c *Client) sendRequestWithResult(method string, path string, params map[st } if err := json.Unmarshal(resp.Body(), &result); err != nil { - return fmt.Errorf("baishan: failed to parse response: %w", err) - } - - if result.GetCode() != 0 { - return fmt.Errorf("baishan api error: %d, %s", result.GetCode(), result.GetMessage()) + return fmt.Errorf("baishan api error: failed to parse response: %w", err) + } else if result.GetCode() != 0 { + return fmt.Errorf("baishan api error: %d - %s", result.GetCode(), result.GetMessage()) } return nil diff --git a/internal/pkg/vendors/baishan-sdk/models.go b/internal/pkg/vendors/baishan-sdk/models.go index 4cf1a918..78685571 100644 --- a/internal/pkg/vendors/baishan-sdk/models.go +++ b/internal/pkg/vendors/baishan-sdk/models.go @@ -36,12 +36,10 @@ type GetDomainConfigRequest struct { type GetDomainConfigResponse struct { baseResponse - Data []*GetDomainConfigResponseData `json:"data"` -} - -type GetDomainConfigResponseData struct { - Domain string `json:"domain"` - Config *DomainConfig `json:"config"` + Data []*struct { + Domain string `json:"domain"` + Config *DomainConfig `json:"config"` + } `json:"data"` } type SetDomainConfigRequest struct { @@ -51,11 +49,9 @@ type SetDomainConfigRequest struct { type SetDomainConfigResponse struct { baseResponse - Data *SetDomainConfigResponseData `json:"data"` -} - -type SetDomainConfigResponseData struct { - Config *DomainConfig `json:"config"` + Data *struct { + Config *DomainConfig `json:"config"` + } `json:"data"` } type DomainCertificate struct { diff --git a/internal/pkg/vendors/btpanel-sdk/client.go b/internal/pkg/vendors/btpanel-sdk/client.go index 513a9eb3..0620a80f 100644 --- a/internal/pkg/vendors/btpanel-sdk/client.go +++ b/internal/pkg/vendors/btpanel-sdk/client.go @@ -56,11 +56,9 @@ func (c *Client) sendRequest(path string, params map[string]any) (*resty.Respons SetBody(params) resp, err := req.Post(url) if err != nil { - return nil, fmt.Errorf("baota: failed to send request: %w", err) - } - - if resp.IsError() { - return nil, fmt.Errorf("baota: unexpected status code: %d, %s", resp.StatusCode(), resp.Body()) + return nil, fmt.Errorf("baota api error: failed to send request: %w", err) + } else if resp.IsError() { + return nil, fmt.Errorf("baota api error: unexpected status code: %d, %s", resp.StatusCode(), resp.Body()) } return resp, nil @@ -73,10 +71,8 @@ func (c *Client) sendRequestWithResult(path string, params map[string]any, resul } if err := json.Unmarshal(resp.Body(), &result); err != nil { - return fmt.Errorf("baota: failed to parse response: %w", err) - } - - if result.GetStatus() != nil && !*result.GetStatus() { + return fmt.Errorf("baota api error: failed to parse response: %w", err) + } else if result.GetStatus() != nil && !*result.GetStatus() { if result.GetMsg() == nil { return fmt.Errorf("baota api error: unknown error") } else { diff --git a/internal/pkg/vendors/cachefly-sdk/api.go b/internal/pkg/vendors/cachefly-sdk/api.go new file mode 100644 index 00000000..16a3411a --- /dev/null +++ b/internal/pkg/vendors/cachefly-sdk/api.go @@ -0,0 +1,19 @@ +package cacheflysdk + +import ( + "encoding/json" + "net/http" +) + +func (c *Client) CreateCertificate(req *CreateCertificateRequest) (*CreateCertificateResponse, error) { + params := make(map[string]any) + jsonData, _ := json.Marshal(req) + json.Unmarshal(jsonData, ¶ms) + + result := CreateCertificateResponse{} + err := c.sendRequestWithResult(http.MethodPost, "/certificates", params, &result) + if err != nil { + return nil, err + } + return &result, nil +} diff --git a/internal/pkg/vendors/cachefly-sdk/client.go b/internal/pkg/vendors/cachefly-sdk/client.go new file mode 100644 index 00000000..2516a388 --- /dev/null +++ b/internal/pkg/vendors/cachefly-sdk/client.go @@ -0,0 +1,72 @@ +package cacheflysdk + +import ( + "encoding/json" + "fmt" + "net/http" + "strings" + "time" + + "github.com/go-resty/resty/v2" +) + +type Client struct { + apiToken string + client *resty.Client +} + +func NewClient(apiToken string) *Client { + client := resty.New() + + return &Client{ + apiToken: apiToken, + client: client, + } +} + +func (c *Client) WithTimeout(timeout time.Duration) *Client { + c.client.SetTimeout(timeout) + return c +} + +func (c *Client) sendRequest(method string, path string, params map[string]any) (*resty.Response, error) { + url := "https://api.cachefly.com/api/2.5" + path + + req := c.client.R() + req.Method = method + req.URL = url + req = req.SetHeader("x-cf-authorization", "Bearer "+c.apiToken) + if strings.EqualFold(method, http.MethodGet) { + data := make(map[string]string) + for k, v := range params { + data[k] = fmt.Sprintf("%v", v) + } + req = req.SetQueryParams(data) + } else { + req = req. + SetHeader("Content-Type", "application/json"). + SetBody(params) + } + + resp, err := req.Send() + if err != nil { + return nil, fmt.Errorf("cachefly api error: failed to send request: %w", err) + } else if resp.IsError() { + return nil, fmt.Errorf("cachefly api error: unexpected status code: %d, %s", resp.StatusCode(), resp.Body()) + } + + return resp, nil +} + +func (c *Client) sendRequestWithResult(method string, path string, params map[string]any, result BaseResponse) error { + resp, err := c.sendRequest(method, path, params) + if err != nil { + return err + } + + if err := json.Unmarshal(resp.Body(), &result); err != nil { + return fmt.Errorf("cachefly api error: failed to parse response: %w", err) + } + + return nil +} diff --git a/internal/pkg/vendors/cachefly-sdk/models.go b/internal/pkg/vendors/cachefly-sdk/models.go new file mode 100644 index 00000000..aaca7723 --- /dev/null +++ b/internal/pkg/vendors/cachefly-sdk/models.go @@ -0,0 +1,35 @@ +package cacheflysdk + +type BaseResponse interface { + GetMessage() *string +} + +type baseResponse struct { + Message *string `json:"message,omitempty"` +} + +func (r *baseResponse) GetMessage() *string { + return r.Message +} + +type CreateCertificateRequest struct { + Certificate string `json:"certificate"` + CertificateKey string `json:"certificateKey"` + Password *string `json:"password"` +} + +type CreateCertificateResponse struct { + baseResponse + Id string `json:"_id"` + SubjectCommonName string `json:"subjectCommonName"` + SubjectNames []string `json:"subjectNames"` + Expired bool `json:"expired"` + Expiring bool `json:"expiring"` + InUse bool `json:"inUse"` + Managed bool `json:"managed"` + Services []string `json:"services"` + Domains []string `json:"domains"` + NotBefore string `json:"notBefore"` + NotAfter string `json:"notAfter"` + CreatedAt string `json:"createdAt"` +} diff --git a/internal/pkg/vendors/gname-sdk/client.go b/internal/pkg/vendors/gname-sdk/client.go index d73782e4..5d9ffa3f 100644 --- a/internal/pkg/vendors/gname-sdk/client.go +++ b/internal/pkg/vendors/gname-sdk/client.go @@ -76,9 +76,9 @@ func (c *Client) sendRequest(path string, params map[string]any) (*resty.Respons SetFormData(data) resp, err := req.Post(url) if err != nil { - return nil, fmt.Errorf("gname: failed to send request: %w", err) + return nil, fmt.Errorf("gname api error: failed to send request: %w", err) } else if resp.IsError() { - return nil, fmt.Errorf("gname: unexpected status code: %d, %s", resp.StatusCode(), resp.Body()) + return nil, fmt.Errorf("gname api error: unexpected status code: %d, %s", resp.StatusCode(), resp.Body()) } return resp, nil @@ -91,11 +91,9 @@ func (c *Client) sendRequestWithResult(path string, params map[string]any, resul } if err := json.Unmarshal(resp.Body(), &result); err != nil { - return fmt.Errorf("gname: failed to parse response: %w", err) - } - - if result.GetCode() != 1 { - return fmt.Errorf("gname api error: %s", result.GetMsg()) + return fmt.Errorf("gname api error: failed to parse response: %w", err) + } else if result.GetCode() != 1 { + return fmt.Errorf("gname api error: %d - %s", result.GetCode(), result.GetMsg()) } return nil diff --git a/internal/pkg/vendors/safeline-sdk/client.go b/internal/pkg/vendors/safeline-sdk/client.go index be04cb94..dbf54f66 100644 --- a/internal/pkg/vendors/safeline-sdk/client.go +++ b/internal/pkg/vendors/safeline-sdk/client.go @@ -42,11 +42,9 @@ func (c *Client) sendRequest(path string, params map[string]any) (*resty.Respons SetBody(params) resp, err := req.Post(url) if err != nil { - return nil, fmt.Errorf("safeline: failed to send request: %w", err) - } - - if resp.IsError() { - return nil, fmt.Errorf("safeline: unexpected status code: %d, %s", resp.StatusCode(), resp.Body()) + return nil, fmt.Errorf("safeline api error: failed to send request: %w", err) + } else if resp.IsError() { + return nil, fmt.Errorf("safeline api error: unexpected status code: %d, %s", resp.StatusCode(), resp.Body()) } return resp, nil @@ -59,14 +57,12 @@ func (c *Client) sendRequestWithResult(path string, params map[string]any, resul } if err := json.Unmarshal(resp.Body(), &result); err != nil { - return fmt.Errorf("safeline: failed to parse response: %w", err) - } - - if result.GetErrCode() != nil && *result.GetErrCode() != "" { + return fmt.Errorf("safeline api error: failed to parse response: %w", err) + } else if result.GetErrCode() != nil && *result.GetErrCode() != "" { if result.GetErrMsg() == nil { return fmt.Errorf("safeline api error: %s", *result.GetErrCode()) } else { - return fmt.Errorf("safeline api error: %s, %s", *result.GetErrCode(), *result.GetErrMsg()) + return fmt.Errorf("safeline api error: %s - %s", *result.GetErrCode(), *result.GetErrMsg()) } } diff --git a/ui/public/imgs/acme/letsencrypt.svg b/ui/public/imgs/acme/letsencrypt.svg index 3a6c2312..b13df853 100644 --- a/ui/public/imgs/acme/letsencrypt.svg +++ b/ui/public/imgs/acme/letsencrypt.svg @@ -1 +1 @@ - + diff --git a/ui/public/imgs/providers/acmehttpreq.svg b/ui/public/imgs/providers/acmehttpreq.svg index 88f2d6b2..936ca077 100644 --- a/ui/public/imgs/providers/acmehttpreq.svg +++ b/ui/public/imgs/providers/acmehttpreq.svg @@ -1,2 +1,2 @@ - + diff --git a/ui/public/imgs/providers/aliyun.svg b/ui/public/imgs/providers/aliyun.svg index 7d0b70e0..05bfc6fe 100644 --- a/ui/public/imgs/providers/aliyun.svg +++ b/ui/public/imgs/providers/aliyun.svg @@ -1 +1 @@ - + diff --git a/ui/public/imgs/providers/aws.svg b/ui/public/imgs/providers/aws.svg index 9f211f19..3b771872 100644 --- a/ui/public/imgs/providers/aws.svg +++ b/ui/public/imgs/providers/aws.svg @@ -1 +1 @@ - + diff --git a/ui/public/imgs/providers/azure.svg b/ui/public/imgs/providers/azure.svg index 01b62bc9..014647a3 100644 --- a/ui/public/imgs/providers/azure.svg +++ b/ui/public/imgs/providers/azure.svg @@ -1 +1 @@ - + diff --git a/ui/public/imgs/providers/baiducloud.svg b/ui/public/imgs/providers/baiducloud.svg index 25ab747a..e448fd3e 100644 --- a/ui/public/imgs/providers/baiducloud.svg +++ b/ui/public/imgs/providers/baiducloud.svg @@ -1 +1 @@ - + diff --git a/ui/public/imgs/providers/cachefly.png b/ui/public/imgs/providers/cachefly.png new file mode 100644 index 0000000000000000000000000000000000000000..86a13db55caf1c438794cb5ecbef7d48ba5fa3fd GIT binary patch literal 11406 zcmaia1z20%vNm3vKyXd5mSVx(-Ab|I65I*y7QCfMDellx++7oB3luNzP^=U!TKrGX zJ>R+KKlhw_^E}DkS($m)?6oJeXU)8EFPX15$B;*x6{?K&<`U2W`YrP|#T&bPc==G}J|{++4UI ze`L7)T%bs86clkOKPbe?$;Jz0X=CT$D#3Wv(ZdLGu$Exd7tjD}K;>-g9h3t+Y;*#i z>skdkS&3LPN=bsm{X~%fE;e2eke`dQtEZ@+1moXuMUm%!hPfF*e-rU?l3@HVqYN}& zfaKgfY(OGhJe*cwFb_ybgbN~U%`YUt$1lPG;sx{aafA7|dHFbb_(Z`1qWl7&zrPrf z6M9(NifYR%{(U;+Hwi|2FE6MlH@B~^FPASLmz#$jH;;&j2sfCQo0pdpDZ%OK@9G8d z<8<|8`U^qc#?#8f0qW)8<_h|Q2(fhY_L5*k8v9>Y;R5{!tgGkWR|>gi+*nVC*FwIqck^=dw0DDoc=@>mK~MD^T&>-FJ=y-IprIkE;_B%Iaka8hk(XdZLU1`a zSc?ja@XCk?%JC}5^U3k>C@9Jbi3o@Y@bC-r@W==$2=o4>EAM9I?PBBV^_Q;of9vx7 zN8LZ}-~vU?EN|oC;A3O0=;7u9`r9>&I{ar_!2c2N@4D9i*%qGvsLPEshWpQ*{ii$q z*AUWu{+#~9b&+5G;ruqPNRRhGy7nVxhD;Qcr}rxIGP-^X`@uLFCN`-T%X>3s(|TPc zVq){4eN-GAbW~I!a#T801}cRqDmqj;a;juvGAbqMabg98i()Q>N)UCvmjo^y2B;^g z_xZLwJ>68(a(I&O>89ta=dE|1=k-f4nBO>y@QN8g;0M8DALs=z#}Is$qrKF*MbN>NXJ(YDjO+JLJ(>&F;`%6NAlz z5$@ixjPC@OyT9F$8WX>mvtqz5q~~gAid-oD)y6jenIVU5jpN?hpMIs*y)stTbw_w& zupX9TF~ zzzV=vo4u!u#lvu3tW|awH~dN2rctURwro6t&I=V#KaklYCNEAvIY|!Hb!Q(h_>e`2 zI$F?vhbU74OXmuU>Ta?Umnv?jV*e(g6p=$6Ai9VKXurhX_oSP6%q z^JG`omLhrMh3~hIU3QQkj>6Ype04c#2>cSemr*vpjGvc%(^puHu=46EpqQF^si)zB z6~HVb*M!??g_=~1F8GcHP>!Z`V#v!}dx zuSM}4Ipi4l$9^8B0?(k<2R70PQYrStGKvIR$HP37oE1)2Pq8gRif)FiFKZ5WLl4hp z*1kTHUulvS!Yvle9-n_1ZgCZKR55Qdw$T>!n+0$yo&?F9T=A}Rc9KMwYhaO$PYC1a zt3yM#UEBIK)hv}{KrHjcqWjn~@U$!xwa{s{aVe~1CvZX?E!486{KI9bqb>Js7g3X} zjK(2mAxFGz4|t(x5g6d3=LG%yu<#zP5->fhE^G0Q;vHsCnhx#+!Mw?jd3D#-4S$vs z(S*wamY3H{uWMR{su;HX0|6sX_!rM6a%EXWEZu_G@|HXp;z)_D)z?IDo{TQ=+&;s8 zUITC4ei>uHiO?lk?$V^kVV;**2<~gX36LGjT_!R36&TaCK}-9Kvq8lwEJ!RI+eunY zJazC~{A2m<-P2*8HW!6)-+j$}kNzhZh>37&1qMF0uY(9Ck#5}0-z;%JV(Z~GVdEql z_T0sv0QOia+@_*ERp-i^M{nN!AgJj^p}ow11q(z?TCbTmIco4{xy1r}5y!QEwSn}| zRpNZhdW{zyd_trU|MBP{+1rL&6wyH}`jOU6QgOr5(ciE@lb zdTx3g&Th^XN)+^}&osf1LS&O_=XKGgabv)Sm)pX_q}x?f1E^_l3OTVD$P?VrFS!vqydMN!UWq5W(Y4 z;M64H$M+;R*5m7VGVC)t^D;3~j#(f$jRzRJ!OWVsaB-A8XS~W<_ZX&5jaB4kLJ`*$ z%oH66iFAwB&xVVMu1`lf(5`**#er3r&ZbKG)fi5mqJ!WYs*Px&A6$+kAfVXnX0;AG^8MSJl` z?)wM6!2GY<0eSW(bb&OZdB%liR?Hr^qyz2(ad^a=AOy;d+2N*PT^yN&M$r$6oT?1v zDfdxE2e45nW7~PPeeQU`jy4eo~RqKragy0p(|Pr?1eyffFRs5`W00^jB(E+d$N zbs$ti`KolmJ?85ocB2BF<3u7?(>wbHSRQ<&eGwZ{H<${+0D#5oI zzv^DFfC{R5$-?ti3!SF@=9Oc-o%1uPP%S2pcTDL=<}FfZ!{zotcS3dB=%?iz9{cyf z_G_s_9~r3?K?J;n1eQ)zT9iC)s$=If_sTjqSZ3|5?y3P@%Z^6O_oIn2+2X`!`Nw=3 zV;3=4GbUI^K(ScRBZiD$c*Q3LqG5 zkXT~M5-s~RHSp8$hp&!VyxhG)Dp=+1in`CLIh-vtn_dhOU=LVXf%t$R_|7RCWEjMFCEM>P z)a#(Q^Go;B%Uy}w+y4FdT2LRHPS0vk>oyL|GYvl90S|ZEGAvXPnkv=$m>UOQw4;oF zsVfM3l(0oixwHSR4$O<0#i5GvSe*tI+i7L%zgmu1(Y1Lg`3P4|Yr`1Vv7E-dP5iV4 zB8kiXRhoPlw|a4%P%?iI{~-8x-P#c>%P)~$1VZfqAYDklHLb)f%PoC+oFIq{k$so~ zT}qR@%WKAG5hAQsZ?2B5L~I4Ux~VjjCKHf43jhotiBh#LFW9`CRR)fb>K3Ry@m*`N zz`zTBEkDtMjTpO2{=FzUb zg3x)_YD=ZgCM4dIaMVu;NaNas4S!vI;iI)UJwEjEf%&ItyD)%fS z_rSwwtIw(w^6fTc)uX+WS@w9bfY zwBiTBuyh@6A68UE;(4@w=rp-D+s+5k<^B=u zvME!d9!SY5<7JAPqB1gdO>g`2XBIUY0npNMCLe&UBM%@wT%do1TLQ}k_N8*QwmD0a zV2B#NND2JnQK=ks=dEqKg9g%j0%!p4=)EF~<1EiwP^Eetx%*M3bpeA%EXDq7nB?fn z%ci7}^Ul~B$7issP0K1qPc%ptu{?a-#f1*7TOM1d|Kr6wo-K*|A|<7aXbcDs>V#W~ zYprGGuu-lGJRVnoHN8S74NVD|K+zv-$yy{R)SBheqpzdO0wQ*4{I)D*prhc9WD9+g z;q>oxrm(d`?WsAjH{AzGi(}3NmA{)xb}Hk|$jF*SC znGvBuk7bN!2+YOe`dR!mdG_1<;Um8JU`>R7f5~1%iu}=j*wLJMFQ|_&Ip6A??CnVS zT)V^M+Vkcn+SyIRYq{X~J(ch6>>@0kf?0D=InPOzo(++*F8%_e&z^12P_F|i_*$CS zdu*7)uFOOI13$%Q1df8K#`=5u-*h*aD{ZASZ!D{*&R5DZW}$O-IX^FH-HSDF^IjUE zA&hE2wr_}Cz*@#g4@~(?M@8~gKlnV8Wjxg+}1hA$bS~r=DZf=~W?1UJY0(5-Yb(WGqs1NQf z3oe}ObxAlFe)*0w*4CGhO_k|y%LSt?M82Qs4s5Ga5xT^P$h@J;o&k3lO$P|JaMss) zQ2Q3=v~ZBdRKeKEVk=Z+KbIoxf_f*I|7l(Fcm@cW1Bqm?GQ5=!6Ut-Rod$Cs zAs@*$1gQ&#nhcOCKl9&Pr|_j$R?Xb@*(gNiI;19isj^cnA9mjdB5qqzf?~1S zlkLhEvyGTYKh)3)^JzI-SjO3(iGJjikq*P4+{&)1tu%Wq^it=?@cn{hY;nWI{ctt2 zRs_OPI)^}iTu5cTD7P)h{=nKaX{>AWS-RE5=cYjjXIQbrm7f_-4Ld2xqO|wN@KQ;w zGp*G7@quwSXQ?`h0i*J?TOHZ8yWb+Y`C33R}%dANLCh<22TLe05TAbH{5 z$;6}mx^S==u4Oh`RIxPbpC56+LbAzL6qEU;iuF;^-aT=&s!OCrs9?rXKFjZJ4_2gWCDhpowIsWP0dTy|d(*c!qsC_~nshu6%%_AKJn~ zvBv2$O$6`joCd#99yyW&KFVae#u1qUfxZ`v7I>EW-gTtmy#U$_1A!syl-=CRjf!E~ z6n9y|Twjx){^eZqq&alYZ{jtH%opZ6(_~lS?D^%I398K6iy_$~=i+_3iZtcwD*7GF ze&p*#5;KhNGtE8#77Z$8GL_HXq+%SQ$#{+JjQCW>izr2I7ih=!2+g1>l1gOYPT`EH zE2fa|l;Ao#suRoQrFRvr8QLGl0BH?)${pq<=f-@-KP@x(JuwCBo5mXw3pbvHHE|dP zcxpbJR!9#7+q**QfcDXZ!=JUMen(HxqKG9~L`2m|zN_oy@(scWV$~Or8Q+P0(z28} zcxWtuLhC;4LV3{uCPVBO8)y*Z*w1 zbawuI$<{GPZY3FpqDIyL`^2o};K)PrppVq@5Bh=T?c%O#%m$ZO6V?xZ5 z18RQ)UsT`$w=WB+!q#0LCJ~~>7klQ%o?(1y;LB&JS{`=py8Bo<<@pmCAtiA2y*zCn z<2|aT92w|93JAYNW65?EN4l7V7wjZT12AuEYXtoh+krjrvu`H9 zK2JHFbK$gG*qY&Esyo;JlfKk=uV!^BnH`;Sv=Lj&3aZ{v3Jwmn*_8Q{E#2sG_3x|6 zCF}Q~L^!VgSn_%f+cVSa$eM~z`zgKY{kb`-shiu9dHP7~rw>N~d(W6K-k6`rlb{go zF2xA!#JyVX)|>_@!;qShaCuEW3tMxEQkfG~KMk&)*%7=IK?^;;Ykb(+v1Qu9V-m2n z!bHdW_5-4oQgz8Q67fbHr<#I?NU^R%O!G8aofR@Y&fCY42*kp#M1P|fLr56A=HztW z(KA&{L}KMOX63neuHFa2eOaowab&W%bXIutRUdnD&A0W@lUCY>QB2Q=LeYgj0*tE? z!o*@m8dR)0X8TX-FO7thlaLWE_}7_{UuFr}Sf;?H2eOWlDHl%PDe{rA37^KDX7S?qJ!GYUZ)$`ecNwxN)jI0@V6i4S0VHG;~IEN3iv3!UO{anCHs z>RH2$)^F3QLW%C!bCuMHxAS|T)KQmv$su|j`t7YDrN{F4*pM}Wcx^#P)L={?^tn=) zCV$U$PSU%#KcrA4v!ht>DN)Y?6K*em+SDi8$89z*77e~>fe8|lp^H^XUarsjo5q+L zG76c+Oip+wPfBjY^C!8&61_#?j)y71$8O?&xtqDaLxoAg4b&%~-j7DsHqslNC}8+c6SK1yOTI)HLG zVF91iTlvi~JW6qR-UP5><~EP*<^crm?X?B1R32z|%uT9yCgXV3Wp_-afh3;I{qX22{3KL9^Ae=*6r7Q36 z!F`|2tm58CmHUlu@H+SzqmZ`7Ui^MRLbVeXGm9#CoD9_oexw}%?^Cg&#_OwZ>g~w| z&bP?rxtpC^M9bn|95t`p?~Ea<5N2#uicy!3(}}9~2x{*A%%}|d1eFE7MQ!tlE~;O& zxp~ILKsA3yCE9vOaHobw6I{IAy?hW#oAX-49?WbZuZlv~&Wl>Oqx|eaFAb(99YLq{3w8<546YYPi$pKszD%NPd!wBZuZsS zod*A}QG&D?2zxN^M9bV(PT($J-9-{KFg?A{H}$scz*jeBxBr6-cnOcNR->l&@f!rc zM-brAJCNezM;GowV`6rCVpZUxeEyKhH#_TC40SyL%QP-EunWfV0#_Wg7axMQ`{H*alBK{i=m682%%TQ@FYSyU-| z0=fU`Ml;$A;s5oui8n8Mtn0UN*>JVgy7am?_bsk{Vzc7`s!^c1c-vKV)+xv;PkjA= z?gt8A-@eC8{MYHdCb3lH!%+zNj2WCx$kM>gVOF`1dPPFV=TNtecK1p(oR_Z6L~!=f zviNBGWPP@dfIa@b-fD}%V{8u!K6Oe0*7UvHu!GT}-G&A;J1RdFIQ znl~qtkw%h9nbXUDQ?n;m#~s4?JiQ=+pSnQWceEE5o@>U97JMpR7T;{gvZg)t+ZH`Awd+$3BAxqgI+ub=+bHt#d%p15v(e&$mu0g~ zzRyrgMuAO=#^6h5jl2&+Z#0+uXlwyfly5wl^y;bN(_&n-&-GC3DyU#KQ&Ycp!y%ip z=#!D0Q;FC(0yW-qp7hgdvi`>jvT}>8zDe=UDkZ-6xOXLAcRuja?{wBgu-=9n)_l?> z&kX;vlBeu)GhI3-CH_fdrvY`fPAD^18K3iw6GrdnMfZ<&n`y?F4U2{ISG9fA0?=F0 z;~{)_?7eJZ(j4kfPuDhb8E?Fc`_&uqm>zt>xiQ5Ksg9+9dTnKA8Adq4Wm;kZ2Yb5= zUn2}>+}!+T4vkiyeSXs8okh=};}DvjL`IE0Yqv;p!HTf63VCemXI&5g8ffF-6k^VN zvE4&$mBG>2@9RqESIaNgy8rk-m{IV zgxd%85uIaowSqAyj~O1ApofXevzKQ$l)Z|)x(+P#b_tMA?bV0y?-_Rvc?@~iy=iaz zrlx$LUYZ;`L@QQcOv&ugeg7XQtCI9OFt8R`c1ZdznYa~Oa>#=(RFf#~y@tBOtB)%; zb;#19Z877CfmW-KGND3T<)g{Ho;^aZG|!pFxjpe;i0u;K(Me#M*`Cj6$EU}>Ikv#N z*X~vDLRm&DsE5*|(-qY=hs(VM86C^F#UoU6tI6XZ#Chq_^W6_K69F?7W|u|m@Tkyj93zbwqMpW<)DSoYdCif+ShU@@=y$Qy+{)s^KIKF zE2a{!E!AW1C76C|EKvo{_Fec;SdfL^Z}x!fX_QZAROnD8^Qe2`#X_COLvOj)F2&P` z`o{Q&;t0dj#p*6lnl#;~gnDwm9^OYF!+w5r8!^X|7A(yW;pBh^JMi}h!|8?_Xq7J@ z!?Wu!Dx+qrTuNscyt}`mbhq#=ME!tml`xL>n9h?3|M`%Gbw^DBYqOOn8tBWqq91&AK9xKCV$l9f4Oj=h>bh=M{N(m-eG<*&QQqd&$1;s+$fP+=5j~)&Q zM@j`T`T3iwp(1vs;d=$O_E+wL++(VxEDyqZms}~!m->J#eH%8Y_TbC@Jrtd~;;ySk ziuKbNIJa@)1fDuOD*J}`oczqtw;>B-CGq*wO$1|qfk1M=kr4gPZOyA9JBJaDSj(x` zRE0r}?_~%ZJVK&h6<0d1oaL!E--v7jCR53Tj0U;nu{`yaI4QHBz4}3bW_ecsKVwh zpytDT(JakSs?k*~(TDHywZJ>B@tkxcf0ML%qf7;M%htPPKaa^o!e)F6_~W;JJJ&Pt zuS(^`O_W<-Hv{r9dJ~^6n*4&i55pIOzwf7$bxdew3_jJ zeV@ayu3}QjO!FhYpH(k5_0B}Ywtn}=Je#6oT3e=EB@0iREr8CMeE{Ceel|4)z+49rSd1Vs*j7t&qEtcHVov+_ERrBB&R1I zZv8{XzU_4$V(M?)wJ6%;vJtg>Z(FBDr)>~^=!MO*)REmV6aukle4u*3$r;~gi?84F zc03T}{i2e2aF@g0dqY9`xGrzH`0-0xRccJNPqrFRaX*pPjtoaK=#HPl!WT4|5 zd*Q7DcI!N77|%}>491y{NBf|xJ(NMx1P}BJ^<`rBdcvi< z@50QLA~$a;eo{Fq3Td!eiAoxmHJtBzuN5$8RUuM#4|;G3IThqArk+Nt z_LF3HOO=F|cdJ<9!Ch49X5<$v5(s1kXf%M>lSJZA0)q}euU6~fr>ggawtNHYv?rvP zJ;|!`aXYfY^B-r-NH!X7%0kq20%cOMj|Xrh(OKz@W^K>ldIE3qCNSd~eFTOFHol zv|#O&)*XEycdWGZW4~qT*}b3RqGmtKVv4&ZY~B=Vzf6=v^R#sEGUL@aeK^>=Rz*W? zX;dVgsOA?^nzO~x$j1aVT1$`gBxlpRgYX7z#^1hO1Tv>@@{%)pT}eGo$ap?oVYW`= zL%;Xj4&tKEMXuF4t^9*ein(ltGbx2yJHf3@8E^jhu>D-JvJ1my&T=U>Betsv(NTXI z4EzM2V0m0Sx==CTI$w$}_aNl`lg@UcbTH6w2ifW1u1A)Tgcc>w_OzQ7WHb(b90q>J z?t4*xri_zQP1gDX)3wr{CXsM(0ZIPIYMGy;kQN63+4U81M|DOvboFBAV7t&@>NM1XH>2{ zSjtJb(4-;!1R+|2#0U6}52|C1)1sZ?i@hupgnG;BKsm-%$Tkb)GQNG) z%4KA33a_W1M;3T1xxPQwNwVBpa}-CGLFWV(TSDM4I0Igg_PusVRhxqW~jg(mtb@`3z^AV;@8Xy=xab&tNWdr$A zxoqD;2P`X~=Dh@z-&dqvlIeKVwxSF+Py7PO`w0l&5^A;0zM5w8;;xKF?pTC3n|0O< zI%?6hr?qWoNdkr=9TWh7+j((ro&a}Za&@_huM5eREDT9#6si1sRj)_lZ;%a`{-5Wm zbOiezdu5ymvdizXLL5WnVbF8|M_fe^Eh)^xQH8bR5|Tz%r}3f!E(UX)_i+79->>3Y z(LHbU0e`p*;4_^;$wQYbEE3m*0(B;yJlrJ)me9%6x8lOKBThPN^U?4pwxz)T(pKwR5v1(Va#hW?}M@dtX<=i;|dA3hJpHqyF zs#mzESC5yi1Nwu-?c9_&qfk+ht!*5jyc8U#*g0`iBXH-)9t683+y>i%zH z9+LR?FRZ$M!@~PFLw~0S{u7b!FUH_M4gCw9@c(BRu7_ + diff --git a/ui/public/imgs/providers/cloudns.png b/ui/public/imgs/providers/cloudns.png new file mode 100644 index 0000000000000000000000000000000000000000..1ad3068d3ae2e6158e5474da51217b513a94ee85 GIT binary patch literal 5314 zcmcIoc|4SB``4nfMwZB6YzbqA84QypTT;kQ8SBj0XEkHU)?&$04w7U`wurGEvV_W3 z63ITcjD0UViJ#7U&Ut@-yyyMzeLkP(Uarse{a)8~U*G$W=ZQ2mG2mc5$I8US#9??v z&-`%y{nvZy=;2sa9EUla1j+igWDC42nd(f!FlnRlE*PL8*4YhXj&Vl&6F*?onV629 z_pr1j+Zr1oPiGcl=a`4OB^UKlda1>@#{(-2>&Z4d`~pf$v8l#LaP z3Az|}k1MxG7>ipbmZ)1^C^fXWmL^c$4{=C<#gLtWepqju55iAF{10Bl;rf>uA`bk+ zh3usv{;#BLjZJ~NcoGJv23C|uDJUoc;c8%KRkRXZ8K$HL0zws_Fo*&S0)@#d!Vn6| z2qk6UpO5%qKoZ&&VXk-i&v1u34RLoenSg*ms8lML3IpRwZV*K^H8qF=6at0HA9~39 z_~XdVe)2dUiN6^1Fg_@f2Z8K?#{qvaI=kR0WDW7dWdBtKmhd+%&gajQIy^IopECiX z2v+!2)nAUr#{bacgN62C$b5V|CcGZ{~^ z#N)mHI!IG@JQ?rfjwb-2N?;Y>1se|>8c+3+`2%2Vj4;IckezWTjG>-}_#p+@!vl>_ zf$1x&>FdJv_0;qf74O!@3;40e6x(ZMgU2UDeuzGkD1&hIv|H7jGjaB_e>@PWB z35SvOFeDFO4Eiz&j|KiwGs5Gab5Z_BzCW?(f6hhaAF+_bWFWsf`~N!qm+4SGzm|VX z_i*#K_%XOc#gh)D9c>vK!osDea}jslKSz0~wxx5>A0w;Ai4 zIu8BOeC3G|)HxnF?ibRjuKoc&w$*WQWp6FG)#z0Ckv}fv|74I5YN^s#E6LLx9$9qN zaMqQbfnU8Uo6;T9eu5Ztk=RuD(6;h^?fc@ih0leVPoG8Go6eKP8r){2$L^@MXtIPv z(M#fa6n4_Bi$d*Fb=?432lFIeyz+9pWiD(5F0W|CX7EB=n!iufZ@+&d z>tYxb{j=K6I*E12yne^fqKt)uW!>j=I_4bIKEJvorS3b*WA~s;8<2$*44AMvZY?|7 zS3wU+#Fnmg-=k9uGsWVf>-xf#NVc)0Sf;rNp6u9EMF{7F;>#GwgiSlG$u#y3>Zsz6 zMy0$L#vW%wzQOsfEg}FbG|J5G}AFc;%c3hn9%Cf;xU!7 zxg4D1*7R5?xwUfv#br2I+b(|R`*2?FI0zMKBzngvSu@}dE$GSB>C;d&gu@|kY}-RNe#YN)SjrR zbBbLe}mWX z-@U72Bm%CS4Qqe|?8I=wO+I#A9PNs1q>A#*eZ5%*kB~uF&OR93MQoj@F_W#ecCw+n zTiJ%4-Rnz@^FP|84R_vKV{Vn%40OpXX=Nb8)}}5pI=6DV6~6>}v+Vwu^s;IUT#=9= zej4IdrdJm53G@hd$74uCGXq~IML(N;^nz0e$FsgZ`mB`rd6J?~mqK}}GD zAAXQX*uI_#l|LgTFMN(wlK%!ZmAc%Z0+n+4dSvb;q$Ti-bQyHXMZG8A)Fl|$88kN? zbFCleq5OQ9_fyK;aOM7l`8|*!vFbHf2Ir29dqruCB<#1LOimGt^tNgO4>ZEOW1zM^ z2}_p>N$I49Y$<4MwKEGF@rCeM(a|D5celb3Nyk=-CtewT^wd}0v#!Yd?OSUi@*+%> z#?oo5)J)T^&@qf&b8Nu&Ev>gcRei?~+1|(Sm^45&YZ)8Utr6tPz997I*u(1cE1d#- zdVzhiXkhZOYha#?nP#8FIZW4pA*ra%y!_8oAb_!)Ll$AgWKq( zHwY~As~LJc+#J0Tn-*Z+y7C0oSy|!iP*IjLr!k$vnH>DH(JZJiOnnOPg$h!b>3hLr zpl?N?e@O8+9t9(*c$3;dZu}jah!7`JdVb1;8KA2Z6cobZn9ClyliS!HBeC1D?GMX^ zCKskg!%MqZ;!l}ZzVYlBW~l>(AJ=z{G8P(=n_cgVh=qxJt0*XbpB1{i3Ar% zz5uDbz57RwlRA+xyWdO)JuG%s8QWYLz!T_^XDxkya*8SE`nE$Ss4gOTxY*>z`PC>Ze z*7NVuY+h0#@VVw!gs*-9kz;Y~-F%`0c*{%o2M<1W2oQRUmGl9~{HOwCwDLMSel)=Q$l414A9zYJ8kM6 z2|IVcf2j5C6s?&L-er`HS(qMq+VV*r#{ zSx#OK-h?B>l3L~dEvhs7^N;&acwY_9PRExR6u+3)1aefqOp*d)zRXK6U#+DPLsQ{g z94>2dJw;q>`(|I`0>4W4D*EY!9)j;`)@e-C&^bEsJ0!Y`SO1-9KyRVNU2km!TK zIODVzP%*2^&OJRv>#d>Ko@?}qAC+qg?R%7VfHi+%#OP^L`b73Fix3jflYC5naBQS~ zjAnQ5&U1civj?hDR&&etUs`&vX-GxAstw`J6TN6Cq9D&s=l6W+7r>~Wqt$6~PWs*g zmUDNbT+$MA>orYWuZ|qQ(*tWhc;aac8u!1EXTcmQz{6*;SD7C7`cycoEt2-4*BruD zW&Xt^YBQEn2mk>>xvACOjRao4~OZ#b5ev{x)^5X+tid;nQNnJA_CY&JIB|l`fRCV%P>uRfvZT z_2jlOgVM_c#0yuZUe}cwIbAJt>;iE|1weQovwxrplh2;KmwJp?2U>?8G#-bATPCIM zoP=jh23wFpFEkLJD#?sDrf#xQ@?P**1JHLL6~Ue!j$nMM@StT$^G_!>KD>xYPFOj> zLTJy|ZRE3scun-NqxC9k+#imP@`@Ui`}HFjMqm01 zE#$^t%)19TJlY^`)Ph+x?t)I#L)D_?1$ua|%BPIky;sKN&BaTd4}O~uRT(9I>~x5# z;>c39G}xfKa>j@4PuHLS)U*okj3#wX#fMW?PwV-&uc907Xb$yP#VG^|6*gq4BC403 zjYv@d1R0ty!=lIKj9yhk=UPMH>`7w-(keY zjq=Z9d*iDgE>(j(d9$Cbo!_~XN@V9{tjC(*~oU{TEkVOGuy~5e6g9(6>95Po$ zM2FYTY$|@BDB+No?Y@LxI0ni<1+@v$GMH1}6;3-jjhF(N$}Sxv@#!V_yU2emS`PO&KS+*`E0{m?G%&!i!d!_Y8@$ z8Y=ocyYk}UL$5)5^VTDIv)1VHSnF`})z+adO0QP-1!?T3D!Hb_8j(s%^+m>;aK>^8 zeR}c-8-4o{K$6o_d#Q^kFZ`M7q^E^H-=u-CpGc}0OTIU^wTnSnxum4~b}N9LG2K4j z{qbnnjiNw-CTLpLVVxPU=rTShCE}cS6azLmoi2QoqXY=-lwlwVxmM-qelNq~f)g&>KgW2rLs+K`k#F+cXbLKx!#94Mtu0%k|%cJx}o zhMr;At9N+`$awqQ@r)ugxu!WqW<-^v#q+L4iB?0Y?QM&vbz)@$yBQh0Z0*P7T7N<= z=Cm}ep1Mq#TUfh(ACMSd9d=)O3RP#^q?6gB=N#oO)|c(sCln2#-n1gWXJ~wA^Q*^1 z;4{7~2{m^aV!1;yK9}xOR;g#IZKZAK_w&`~%v=`foMn(w^+_x{T;jLM?l*@$j^x{`G zRNI=pcrQN*?=^(%3oWqAtiw#C%QTHW(sL^)O{tPq==UyJr)H)*@Ih0})HxIr^{c;s zF11-0nU5K$(Ewey+BeIJzWugmUT}}SG=;$_d8@RjIU$$XlEX@*Dj>_$2k%u3O0#-!wRia9$WSiucTbxY|Q~yNCI$F7=vXbY^llx@Sly8Jhr$a&iIj zgWe`bCCRG?+3U*L2$PwC8^4sfhnPLWzjGymFtOm1H~A zU6efiBWBDoTSUlvX#Zh(^tDyDjPv!IyE{H^y8PhyB(18DvBqwTeZ<0S+%VEUIIiP3 z<6?pTTn>lGGA>PLeA-5(?I8I3O5LhGjW+xuQH~d{4Vd7}W?zR(qVGJHB>3J|w^M?{ z#faWJYv;LIx2NdEJJ&msi~LfO92G1dAAa^GmXv&ZqjtTm_Y!X_mkYa@NX|2vn3R+s zX|+=N{cLNiY+cbjgRMi%vFT-Cd6~J{S@#95X|$Vm;s4~v!XKn9po6ncOlP~oR~?z3 Qxc)L3>YM1%be!(~AIoNnr~m)} literal 0 HcmV?d00001 diff --git a/ui/public/imgs/providers/cloudns.svg b/ui/public/imgs/providers/cloudns.svg deleted file mode 100644 index 44cf1ed2..00000000 --- a/ui/public/imgs/providers/cloudns.svg +++ /dev/null @@ -1,99 +0,0 @@ - - diff --git a/ui/public/imgs/providers/dogecloud.png b/ui/public/imgs/providers/dogecloud.png new file mode 100644 index 0000000000000000000000000000000000000000..1897bc88f716cb9bfd59ecea1f3c79a2fa8034bf GIT binary patch literal 8929 zcmb_?WmH_-vTmcnLjsKx8j@gv#-(w0hv4oVXc`(1?jg9l69_?ryA#|Y1PJb~!R4~g zJ^S4E#(4Yvd2fxe*0ienzFAd2<{Y&`Rg|Q0vB-b%Sh27{AP^Q-b{2Ma<|heeM|V3X6E|i% z$Jc*bkg#wxLqP4Fpm00TUlvVF;m%HiG*4vzdlxYK|CqIN{I{o`e8%EtV$Z?`X8mhd ze+w!q{@+Dmu>VLqI;mOw58wZzVMh&jdkYpd3rDy!!t5z_maqSUvgZ>=SeQ7$5gKr~ z?ca`6v4%Ur9j)Q^Aa+hLH;7&fYG)32b!7OLf}$dytevBiiJh5+tb`!VlL;^sYR)Gi z$|E7h!z(5!0g+&1lazw6igQ8OdDtX4xp~DQY>>ZoCE#YxFbg}Uzje+3M_2qGb^l5S znEey7garcXVqq?YfWtul+A|;YpSeK((cZsx&HtH;=s)VRJdt7fE3*Gfr2n3JN}s>F z|4H4a!GDt9!tN>K5l^XozW4Ss06?WGDRKf$BX(#X@Dde< z_9DK@pBX61{5Ai}pLT+cSoMn9icf@NM5We}8Y16yRi{>s7&K8ej-?2XrJ_0dH<1zh zmP@Xgj~q=9mn8EjbCf10@2pYUrrXxr*0T}Mt(2{l6jwtLiGqBm#_sn-^bCLmLSH#K zERnZp*|D+6DzZpl^YZ~3Y5+!t|L;qHg!m_{C#b)$o}m81dV+ew%9v%BTm=E}t4NLK zBZ&6KC$1O?XrZ*3WjQe&L(zEjjLe!atzK-k=Nm{QSU@AmT}(avP!vgQU+#I!xU)NK zb)1D1ztq05qLPhm(g7fUMc7@?BRy#*FX6r4~<0WlXgGT#g zf7b>zKwGw4D;b>V!ZLiv9^I36ZR?#|QIRz%DjoBs8OP80i+FWxZ<$}XJ5q1^BgffI z>mdgv=9s9Di)!W1z4X#1AMGDASnVViNLD5M6S4#a?tLcdQZO4cz=W&D*j2Rs3Gr5x zjPT;v_aCKmRxsEH=dywoT#2EC_6p|vvE5cnmiE+V#`jjE9^bJ^n-zq18XJ-dj#L3Z zjPcoTYhtrFa^~q_T3I+CN0qAUVCrA7Xh~L{6JtkoCCs)!t+(EowBG#pPORfG>)5LD z$l4xE^f@neM^y#bUA2F1J@E?jf2U|cq9B8bt@9Q#M*-VW9! zHFt(Ma~M^bYtON@Wti+TdMK~kVsVYHubF&U8%x&(>_r6ynYU&E8}}UME7GZezN$Fc zI3x9NhJ9f-PRR@3b6sTkS6>hz;c*n5ArnTBo6basx&h zvJe;IH+NJLYk61f(ya#t;7H@0)~#WJ6wAXa(gw_cKDDUa@{wl{?XhSsV986arwIH) zsTEC;CiESD=~=?O^XaQ{9&&RilM+^oP_DI`YBPsdK-)%IHT$C)mel4L8cxBxir__C zZj5E>n>%z+bGW}x<(tvA(C0?ji;P3lei7^GMv}cpgC80_?>GgWOM!{HePXUFFX;nuICZ~wzhjto+@9w5Y%4uX4FddDhHW~6 z?F7z_YnZo^7TSuoX-<{lmVMwtsm45`##(littI|9j#bFVoY0@&Iw?$oQk*1R@!div zXjB`Ch|_sb&OelIj^a|$8Vn|j9(TBp<+pcu4YT_{&`q9%K6{M*b6?arf~JSB91XpeD-HbG{`&J?lLn({$lMLRQYy--Zmbsh-j_8?+XmFJ0|+HqoP14gM49 zL|01RoLW2jMU1~qblD$SM(EYrBemnrrK$9FNU`|wfv(tPi`HCRUNTOflxlny-eLEO zA>MCpE8{swtakM`&~Y`z&^3lftGKqAV3at~c1OPD*pSmo@8gqeO+tOC+gbXKdonaI zzAs^aEW9Dz(etjOIqnu;IfSU$ib@RZ8v$s}r~SByOE!17lk^=-1PH&r_ARXme9?DI zL`#PxQ;7464&&Hg*fTDRvGLP#gM8;qH^t*;%w|3N-c@Tq<=xQ$j=Flzv+4L}J~UTY zpE|NsX@?A(hlSXQ23QK1m*W%AP`=J)NRvM9rLrxSV^;Q*t)COOH0c!xs7{P8mqE@i zXyuBzvU_aCkXPyA6~ok+bl`5%6RrZ@)m5{mJG408AHUCYwDB(lHQ0OXyrsZ}u7s#G z&LC&QTpklsejN+Lk?6_=Qf0dh0_edf)v?>z3hwf2tIY5#bAnRwKh_en<(qyi3SPkq zdTxEOHH+k}vdZg^`fGCr!PI=f+L2%6xbBD}->FjcwY9Gh?{G}+*t;nPY+?G*$W27J zEC9y+MoYQLpJ~$CpLIn2^{h){s`JCJnP<(PBn^-cNMt?`HcNUNjCUvV8R8Xi`Kc>I zdGj)lkSYJnb+z-)^$uBtwTus0@JMGl}fasm56k4jhYpS{0ynnYQte< zK~+mM#D6XGVaLZTeH8eqh3cx_&8<4|3xh5Jx7qy)4z@N!CxM`7!0=^MpIh(3xzMQ> z#lS2xGPsQAy(js-S8vj;Gr*R2BZ|bLC+{G%(4KfT{F)tWS+1>btcVV@I6m29&JHfQeJSyGplv}yX zIaTQ28%KI4O8bcs0TJ0C>Zahtdj*p6y2Z;sNsGOenr|;8!Rz>%msLm^GS}=qt#T86YJg_kb!nc&UnhX1}#)kJv|FAUm~6>0A}*m$g)jeYImkgPQ=c zCj}yLEwsesIl*chcDe0sTraZM2lSEt(@^ZaXQs2#INjW7u&;(5C3{pu%IlzDP(Z7q zj2s%)FKvTJp|iu)^y?(Vk1xX0=za-+RjbGPw;o3H3ExW8bt=R5bciBnvrUM^WoYWM zfso45ujo1$AF6tz#knNQz>Ni1c+G?eog2MLb-?4fI}3ANS(*OWBV`z3#$9uH+;;2vHC^x`U ze7j-LNT&lZLPVXNFqkHi`@wbn z^DJRely+vU@>YrggmaeEd-o{Wzm!FNf%yq*$zqx;36WW{01GyEBg}w{^RxA_d$mi2 zS%i9<}J#C!qHa|odM89Q$%aNw9S z9ZR2hEP+&Z-NIj+<={Vk_J7~r5Yf7)D3YTtl?E2p51 z|4S+V{RJKYN79|U_{lThA7qD|@ahO9W_7@g?1=8TqAktz;t8seWq>9Y>9uHm+JmRw zZGt?p0R#I1I+uYoh9{NIu;5~af;Z}#Qx|ya;*W(QdHO8Fw}=cOQgil<5V3O_kU~w! zo5%7Y^W-#x`oS{CrO>*n&G&^(MpbmAO3m&0CrDFM7c_0rzwx#y{4*5tn#pBH)@5G6 z@60_0A5y6miivQP@5PX0Qco3RrNt+Y3KSYcQ*#5QTsSZ?VH7<+#8D#<)g=??Iy+Ls zy4kc?qq^C$y1f$bgrwQ#Sr>F}H--3%*sB_HG?yv^{U88x)0t z_xm@&`1VHY3*O(G#8-y+Kb{YTRfp#y>wFS~7~2@>b~vmW`<+cWD>vjBx%(UoTsLmj ztU5wS5Y`SjUWdR6dCVe)XWXApJu6`9`4L?Hv~m&N&gWd9aJXu*+nPsqz;XNL-ddCg zWb<|{x*$L9uAe3e^RuTXlDJcLTwRpr<4$?fhQ{5-=ko~c^1fy)-nKyYO|EYgWuWo% z*?3oZ2$}NIr@_6k{&CeK#BfOxn(ERO7bo(v)=1no7ulufvi z+@>eW`>b66;Xt(!uI0nI|FC49->ECD8iSlw-_;p5`|ML8JV{ zA`m~5)3MQCtwsRkR5o_T#uQ=mr9Z_Zq7_z4SBM^<lw2l($NKdVTHv8Rq;$ z^I4(WWBM2SRJ}4?g^o4hxXFh}_3-I*OscH@?x32JY}qo7F1;#}v6i+0ungf1a-^H^ z`$c~Ms1Nf64{LyOHB2~}s0uKULLVF{ju{_@d<4DmD_P=~KSeH=`bHXzmTXn~iO$%U zU6I71RTOn|>>808V~cnKuK~s8W5_ z&gi4rF@L{6V!zERiemx=%P%ZK{nci2lj?Xx9rZoELL6;pH-}WcF*Q{h#1@q#u{cWE zx<)x{7oN*@47_Pz;iHG=10Q<{eG|E5GyJe2MC5L-UM(AnkI>_ZPV@1u6S|iJ+M(98 zOD3!xrKl}6q_TC$1e!+jHVo2)zz984m&A%?9i|`WTZ4!TO!G%{Ul!y5q^|zyhLa8$ zU8O0y2yTQBVFY>`62|p&eG!>DcHPpSYLMIf*54iPKUQm8uB2cSSXjsL2X72$o9}rR z2XtOa2F-TeY^K@~dHaOPIUcBY(qDG*v z09SVNN3)dMk0((bRP3$p%jsmRUHAiqFD;4yAQFYouAnR{tRH)Ffz7VgyGqNTBu8xS z@{^gVM*SM6+m5TR=+QK~5WIOVHSNlP?)7_103Aoi9$cLf6p(GdkY?dWz9RiOb<7+~O5M}=gGwXFz- zOPHDh*w3=&x{-M6>nf0$C0Wq?y2ApuW5Pa{zT~W|fx6J2X`K4A#vuJ-Um1~7mg;kq z6B6`G3x5*({Q|b79sTK^>D!%jVbn_eZNpi^J^mf2$Gmo6v`)1kp#oY4wPN-Ko3AvT zZ=-x2zGou7tFnmS%IF)Ut5}D-SpQ_yxTQBp5i1Ur{=I2Q1Ry%j>ZCKk9x_Oe_}Pam z%J-=#el1wdfmkQR-}|!cDVMNw&ifI}N{bYK+Ixdqa`8l#9WXIyriuhYOJbncei~4Q zM_;9C%JDun1>IT}K%$s=?)7CCV!Q0^tj87iQF;lAH}FlRa0u4cDSy^TR6`_mUgeuP zAjs)O$GZwY!9Z5$C_cbF9S&;bxAhXBf|bcgr?cyP_7y%a%NI~V)nzT>Qm}!LfoDDj zXz=3L_NZLpSMvOA+`^Z%l6x zf@J8pr*19cka{3hKZ$|`Lp2t8*Ez51@N%xD?C?&Q&qOBlqrSeLj?SFSJk0>wZdZgp zz_3;>DS55p3QCx66o<4$mQM(~gQhtA*nLqIp4_{z0Hp7An>}GIyJ7F@Nv(F;|9k@N zT^}qYqFbjRYHura;`HgqF-Ph6K)LKV!Z7R6uM;b85m?!0#)5hh5?UOUN&MO{I{}&5 z#=7T6pDTRi_aG5qY|;S9qrVQ@s^)40b^n-jlvwgji4of?{mQ056dP|2oRTE`U&@R6 z8|2J<+$yO{I0yK);h|8D1^HMB4?>*ew^pb@>qpp@ofzPqmuvt?_C6MbkhZ2RXXdD& zG-5~r`}6w6WZQj=y-jGgyzbeR=%Nw0t*Xmp{mQ2rCT%?eY>IT4TtGl$t%F8ubs9y* zF1&&{M~WQ^#Lqm)X`W|WntLl^1YWBULYzYCpw8o_ zmUuQ&x+wE7h2}TCDwS)g4CHycY&MwMOR=7=X;CaDwkUWUQgGJp5aN`oZ&cFS!A={l7}V|C$l}g zLBbtemB>vvmaE2$vv$wtV|t2*}=d(l3_zH}(fU;hjrSrGWjQ+TEzsf%pP;OyvC zatqIHRx+3hmattp`o?!XZb*-dK;+U#vo5RYU3T;X@%R?OxpxBF8!z1PLk>b-6ZZ#$ zc)v4ij}NGT_(vo2KA6v~*AH27?^Edhvb&4JW5wtS!@0P^#h0I%akmFs3${@2-XhrG zhsEQ@wcOB$KI&Q=f4T&wh6a;mF@ValYxo&j7Nvq$hhT!R7@+nSV^%R7xi{loSQZ0isfofE3ko#=of?Ed1EZF#n#Gf5h%aR&WUs^dfO}vh| zM0Z5Nhqa%fSjFqTmFaLrR8z$vSSrFOL}@iFL=mU$&6fV{u*? z)&dQqcayb=yblcS3SC`1HM3ETR|LQr6mu~--EB_6WWU$Mw#)~s_Z#AM1@RbD+-jQM zWTNXE;+Tcbgp#{}mOAEJMEB;!wRi|8X_wmv+Hfg)NE=^Y7w z%P0^!xA7g`e|JBNwWB;ho}{}gaHnAy?_^9xmUPcJ8BQL(f@o~d#ULPwqWE#QVQ>o+ zVpZsOPE{!2B79XAu|4bSoM)5lb~)#7f(!Gp*8gErp{Wc66{v^43dKCdY0zN1qmuRx z;eZ@8?4V?Sd#gNSy1<%aeS?jL(#MmoWQ>z1{w8D&x67uHf^7e%gHLcF7eUqVVbURo zplxT|b=yk2#nLjG;(qYS4bI|=U7ql~gASWYL)(4b!cqnbrGycwwx;?H$DcwhyegM6 zG7J36GcD=_XyV5R`qfy2Sra+Gyer_N)MtjBl%uS_~YKM5}Tr*{Xy^tu-5SB zXp5T`{QZk(ZO2~wBARlw=lz*}7?M4Pksn>Z$@pZ{jCk9a-3mB){q*5veN4PC93gR( zNLd)9lRu9~-`7q0e%oq%oWVwP{N~;F3+>bd{@WPIW~_P=CCgIvIHv6V(2a^H{qk#{ z{j8JlOUOE<4H3ssUcrshQ9e&Eve^C6XZj#z5;1`rV?#}EGePgk2OTH0>)^9(I^s+r z?Cry$r2tSS(7J@Bj8VAJR>H3DxpDYSO!TIli^F=VoQLl$iA0hIHIfV1x*0ozAq}wJ z0VugP6!NiqNPpN78sA>0!y2)qz5Lqq=LH(Rz;lDC^)3{@g*rEfO#E#F9#<0x@`wMCqBn)2|FP6w$QDkd9fs4k}k)t+Mn+nNMjV zy7KOA@$Q1`hnvkM8Y?p=#l8578XWzY;5l*PIpT^SBl~?AjQfog;~9qGHwOWc1_bYj zNo|%v3PONI>^14rAuU!-0iF8q0`mV>)P1TS|5Ls9|8?n~YSql;kHp3RXWXt`(IwZ7 QzkWKAl~j@_6EpVzFXDrcY5)KL literal 0 HcmV?d00001 diff --git a/ui/public/imgs/providers/dogecloud.svg b/ui/public/imgs/providers/dogecloud.svg deleted file mode 100644 index 253f9ae7..00000000 --- a/ui/public/imgs/providers/dogecloud.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/ui/public/imgs/providers/gname.png b/ui/public/imgs/providers/gname.png new file mode 100644 index 0000000000000000000000000000000000000000..ef3772f5631e28272529e9d9908dad6ffa154644 GIT binary patch literal 4480 zcmaJ_XIK;4){X>JgotqHf&>IX1QJ3sp@b47AiXzfNq{IJAqicY2q*#q(&2zo1QFp< zl@<_0q^eYDQbYui-lce>_jvC237mhvN^rsqiS1I&4{j4UuQB7pn)a2;J~^BXE&TF&Kc|P)qzt10Du?p z=GIhe1APRBNRV;<=_BJuAkonPfC|!&&p*YUF?5mK_LB2>q+@5Q}moc{G3S;SsCch zS^ai2F!=vn3537BDO6M3fA#)PVv4yx2?sI7QHb7T41Mif&;JZXLTHh3&Qv1VoJjQe zok(MMB9%ySCz8N0c^O5pgcaTsOZ25&`~@&DKsLq}koGwaLgiaxY$72yNMW`ZF zQxUF>f@{mlYG2WmM`@#!G_|j2D=BEeKtMQN6pXERx(Ica9 zWV{a!dxcCSfPc*yf&XVMO8?0B7Z&@^S}y-17D5*T`MI+HXQh9e=;iaX`*-Qm2Y(ko z&XZp8WO`{Ms<|rYkK3v)O2gc5^xHL1{NMoBk!MA{6!H=aE9V(5PWv+#Pif*3kk2LW z7^B)}ntW^t)h?HYZ0!*GzEyF#mh%HHc6K3NS+}^%SEGd192qBWF`VLJXVOUWwz2*g z*s)aG(M9ucNK9==#fH4`e^5J;ni;qPpH%&lO(8p`c=fWIbqQbO)?h{J%Yx}=Tj;CM zSDZi&Acq+%`aedvNy6k=UQ7ZTIYbo_v<`}y6$m$vj7D)B-V@zS$vFK=xk?y-kTc$!+=ad7TFAt}R zdE{=0o9e0r^qX(vS?_3{MFZ!GPUZBW>NG^Aq-4=BJ3W4Ran@&ei%?#5QM0r@4(@>& z5ysQ{PXYPY6<6#PSO;GnfO13f3_gwXKJZ!|D6FPUSa0BSE_57lEy@OJD?BA^gpPl| zjQmlwz00ySS}9haBbqXCf}b?;XKF>^m?+q8XLY8~p9TByH`{={Y=*SeB7|0MKsI$+G|?@@N?-| zEs0P&!^X{;%y9ntSh=)xTGyAlSP5XUk?kfEQ`R3VFVYC^)u9Kj!a`aNDn^BWj-p*Z z0fZ^bLJ-%o8iYD4RHFIDB`0^(u>y#(EhD%^U(nEn$zsXj1pbW)ThB43Mtk?}ok zcpHrk9OKICytjAVM?H8QjEv)Mt{%AVYd9`D6ZiC`$7{J!7yMnWQQG8o_trvO<7`pP z?wGZ`y?@N4slE8<!a)jBk-3pAIy^ zJ_*HfUZ|-Y|5c3)O2C;Ha*9LA1!@gug{F~5s_?j_;{rbfA6|;c{8O1hu#e5>o;xFm z+3APIRA#_Kn#OLy>|RjEzc7$?D{qaMx6jm4ap@NQ9kZ_eXC4U-wA9_qaeSd#=I+=6 zondq`7IJbTKGgZr(s#5460oBIhCG2oAq)cUQ(O%$_0N;h=#`EyN;d%3J#IVsnU zDi)y+YGku~7+ODsHBVteecE2C{`n2fulUW+Ju1Gxz5eCLafXJ5FyZu0VuR0c`t7lz z7f>>Yoqg{JK~p{Hy!Ew{G;}78Io$iDwyq|{G6*15=KP@&nHHnz&$oC3wVHr`lWl8n zlBE2lANy8A@kR4M|C`O&>G*>Aoj|?}%DIS&2Zo<_m1}h&L)dN9Y^7UEJcw&>FGi=+ zv6_@_>>cqfMPli60tZa5Udw*pSu6t-bD@_xb~;xt$o`hNm-~}MDqc;gRCx`8eXw$Q zodG2^SKMhdFvLEHi#3rem~i&fk&d|Ce&Ka8dLil|sxw_k{3yahK1#gUekhFbf_SnA zS8u_L&oGN{#N!PbLi&AF`0V;QL*&--K-}#y!>jmRGV7~ZbULF)*4YA~quVj_Pqz{P zeWbLIruWiHsfJ%Vp-Z7L3gx%J5S*n(MHf^Kr^>|&waMGgMG_gYPqR9M5R z+RhpA*~j;N7uuUFfxrMSePPJe7vlwDPIdn499KWjZ6B z*GI|UTQa(ISNn3z4uPO%%3@<1pTj39=7yHC?eE92A*y9(9AcIL?k1wCMwj}R9Y6UR zZsMf1CeQUA4tktWo9GhUH{%RBjL@|_iYU=M!I&k8SaNhI469#CZhynsn69Oam9yl>gjRT&9Ew;8ObZmHzlEIbA|1jj-0mmAdIni^ z5`3#OonNwKHFv}moCzimunC01U6^tPg(`zPh)_3;g=E3nuZX4~yE?DA?;wR?PlOuvYTM?;S%ZguUk=qpFO1s4> zYa~~iPH-=20UUAdS_wrzfcV+!l9o3~~$@>z95q-og zn;==cEfpDZ5TlUp?y%S8eeI1TRsD^FB7;kQaV)iNPZ`;sSUs)~C7+i#_EBkVz$shu zv~sprg3*TZvi$*zjdpp_FcV+TsZq15=iXhJDp?tIY{Ig(0wH9=AK~fTw8uzsWF3o6 znN0JGmoePLAAn~guWW)&mT^w0FsL{0y2&#~@=AJkmuN1$SI7dC^SJVm-3nu;{JPhH zp`+o=#j$)nbvrh3n7U(TIshx9cPks3EDnAB;kCQ6rFu4=Co!s_22;Ch#E2H-*SfGNjc$%`YBC{aBh^-MdG98Nn2zsXkKRt*5RmK9#j z-p_=O1R416W8&OCc5J#a-ZA_nH@w!;lv%<6%-4Z`loOdvYLP4Gc|?{^8GW>_Pv5i% zH+S2RwKWRucRjNh54IVuPU3yds&GkGhVi6D`MD48rbXLJbYMHyE6r-`#x-}d zXPAvA_8!*JQbep#s_Ui)m<{ETsKr)h>h%#iH}B0{=OWNrbZTmpX_nQapU^h1!Er>b zKBr%oKsvWg(EjqX+>lY@c`Vzx;@HZmyDv-Kr#`RX|A;%lpOe zJK^x4#YF0h;j(JAfLr{Dn#D{~PHfesgexn7cN*D8*nAKUxt=DEveRxn2y1G<^&2pX zZ$A!AP+#LWniVPcG(SA%2U&6m91)#XR4d#ULkkTeg)QdwIN#q_V@_@7OfH}(NyWFi zcUj9L$C>qMtw9Mpz}E#Eo8QP6c4mnOLu>E}`fK31{l;K?A72B})C74Eg{~;s->S%3 z+lgK2mUlk6n&VjBpya}$UO3THJ=I@&2-dAK;_oY))~!($0$u#ZW6qPG{Rmko!hk3c zYMse!+wcu}ct-&~~mf(wgs3LHJ^^uZUBX=O^0La&JwS4c~FpE-#_JF%lB} zqgr9+nL3BrJ22=uL!ZhDBE7gf{1s7M?p+CJU_>;CXz4Ugp^O;K?k<>Sv{Mz%c5FW`_HQUDVT_~7an>x~Ii|HL>32H*R!H7>?ZIW+>5us- zfz`ob^(FYMrQAK0=!Rl-MEC6g~u_`}`oXIvW{Ml;*Ug-n=lO zbuI~R-pkwqcLIQ);$Pc^9doMU@0(}acrRg@Q}D2y;2w?25N@`9se)v=?oX`Yo@4n6 z6ICg>Xd3WZPe#t3oIW_T|7?qL%{PyO(33W6C1)GiQIP>D-{taOr5()0wJ3TW$76=M zS2NxvLpdyXveD`0cR4eMzji0_R`Tv|Ods-OyBnljLxmV$1El*B->XY_KoIC*g!a_4 zVXVzv-V%Os5EvPJj{G?axE6ggz&jvD*61uI%&F=$s9a{(yYrg7bgw77?V}m(q>kr| zwU$-AKl(0&KCyB&TkLP!WbJucu{HW?NSMYe`1vc8duiw}gtdKxW<1a({86cGa~K(M zB`b)rTp5*euI+k|mZro+RdR^b6Q*S5Eq#{-)*=rTQ3umBxC`@jjDpuHzg~WF@U42@ zGc0$XfAuJS36(Dr&*K%>m_N|HCFz|#0c!hh yuv4LBa$l9I?sA3wek00A}+UL?Za&i?rMPefPS5LK$_bnD+u0S1x) literal 0 HcmV?d00001 diff --git a/ui/public/imgs/providers/gname.svg b/ui/public/imgs/providers/gname.svg deleted file mode 100644 index ec409ca5..00000000 --- a/ui/public/imgs/providers/gname.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/ui/public/imgs/providers/godaddy.svg b/ui/public/imgs/providers/godaddy.svg index a859a7ae..f9471283 100644 --- a/ui/public/imgs/providers/godaddy.svg +++ b/ui/public/imgs/providers/godaddy.svg @@ -1 +1 @@ - + diff --git a/ui/public/imgs/providers/huaweicloud.svg b/ui/public/imgs/providers/huaweicloud.svg index 552e59e7..45a42dd2 100644 --- a/ui/public/imgs/providers/huaweicloud.svg +++ b/ui/public/imgs/providers/huaweicloud.svg @@ -1 +1 @@ - + diff --git a/ui/public/imgs/providers/kubernetes.svg b/ui/public/imgs/providers/kubernetes.svg index b7f555f7..88125935 100644 --- a/ui/public/imgs/providers/kubernetes.svg +++ b/ui/public/imgs/providers/kubernetes.svg @@ -1 +1 @@ - + diff --git a/ui/public/imgs/providers/local.svg b/ui/public/imgs/providers/local.svg index 2f59af07..46974fa7 100644 --- a/ui/public/imgs/providers/local.svg +++ b/ui/public/imgs/providers/local.svg @@ -1 +1 @@ - + diff --git a/ui/public/imgs/providers/namesilo.svg b/ui/public/imgs/providers/namesilo.svg index e0cc8da4..4284796d 100644 --- a/ui/public/imgs/providers/namesilo.svg +++ b/ui/public/imgs/providers/namesilo.svg @@ -1 +1 @@ - + diff --git a/ui/public/imgs/providers/powerdns.svg b/ui/public/imgs/providers/powerdns.svg index 192466ed..768bbacf 100644 --- a/ui/public/imgs/providers/powerdns.svg +++ b/ui/public/imgs/providers/powerdns.svg @@ -1 +1 @@ - + diff --git a/ui/public/imgs/providers/qiniu.svg b/ui/public/imgs/providers/qiniu.svg index d3b98877..20a88367 100644 --- a/ui/public/imgs/providers/qiniu.svg +++ b/ui/public/imgs/providers/qiniu.svg @@ -1 +1 @@ - + diff --git a/ui/public/imgs/providers/safeline.svg b/ui/public/imgs/providers/safeline.svg index b5490ac7..9a0db247 100644 --- a/ui/public/imgs/providers/safeline.svg +++ b/ui/public/imgs/providers/safeline.svg @@ -1 +1 @@ - + diff --git a/ui/public/imgs/providers/ssh.svg b/ui/public/imgs/providers/ssh.svg index 8dea9e89..d673cafa 100644 --- a/ui/public/imgs/providers/ssh.svg +++ b/ui/public/imgs/providers/ssh.svg @@ -1 +1 @@ - + diff --git a/ui/public/imgs/providers/tencentcloud.svg b/ui/public/imgs/providers/tencentcloud.svg index 76e54dbb..1fb8f4b6 100644 --- a/ui/public/imgs/providers/tencentcloud.svg +++ b/ui/public/imgs/providers/tencentcloud.svg @@ -1 +1 @@ - + diff --git a/ui/public/imgs/providers/ucloud.svg b/ui/public/imgs/providers/ucloud.svg index 9e246c65..3000023f 100644 --- a/ui/public/imgs/providers/ucloud.svg +++ b/ui/public/imgs/providers/ucloud.svg @@ -1 +1 @@ - + diff --git a/ui/public/imgs/providers/webhook.svg b/ui/public/imgs/providers/webhook.svg index 2ca5bff3..6c5eaee1 100644 --- a/ui/public/imgs/providers/webhook.svg +++ b/ui/public/imgs/providers/webhook.svg @@ -1 +1 @@ - + diff --git a/ui/public/imgs/providers/westcn.svg b/ui/public/imgs/providers/westcn.svg index 9ea5a83c..2ad4fa58 100644 --- a/ui/public/imgs/providers/westcn.svg +++ b/ui/public/imgs/providers/westcn.svg @@ -1 +1 @@ - + diff --git a/ui/src/components/access/AccessForm.tsx b/ui/src/components/access/AccessForm.tsx index 0b5632c3..fd3c4536 100644 --- a/ui/src/components/access/AccessForm.tsx +++ b/ui/src/components/access/AccessForm.tsx @@ -17,6 +17,7 @@ import AccessFormBaiduCloudConfig from "./AccessFormBaiduCloudConfig"; import AccessFormBaishanConfig from "./AccessFormBaishanConfig"; import AccessFormBaotaPanelConfig from "./AccessFormBaotaPanelConfig"; import AccessFormBytePlusConfig from "./AccessFormBytePlusConfig"; +import AccessFormCacheFlyConfig from "./AccessFormCacheFlyConfig"; import AccessFormCloudflareConfig from "./AccessFormCloudflareConfig"; import AccessFormClouDNSConfig from "./AccessFormClouDNSConfig"; import AccessFormDogeCloudConfig from "./AccessFormDogeCloudConfig"; @@ -109,6 +110,8 @@ const AccessForm = forwardRef(({ className, return ; case ACCESS_PROVIDERS.BYTEPLUS: return ; + case ACCESS_PROVIDERS.CACHEFLY: + return ; case ACCESS_PROVIDERS.CLOUDFLARE: return ; case ACCESS_PROVIDERS.CLOUDNS: diff --git a/ui/src/components/access/AccessFormCacheFlyConfig.tsx b/ui/src/components/access/AccessFormCacheFlyConfig.tsx new file mode 100644 index 00000000..b3172785 --- /dev/null +++ b/ui/src/components/access/AccessFormCacheFlyConfig.tsx @@ -0,0 +1,56 @@ +import { useTranslation } from "react-i18next"; +import { Form, type FormInstance, Input } from "antd"; +import { createSchemaFieldRule } from "antd-zod"; +import { z } from "zod"; + +import { type AccessConfigForCacheFly } from "@/domain/access"; + +type AccessFormCacheFlyConfigFieldValues = Nullish; + +export type AccessFormCacheFlyConfigProps = { + form: FormInstance; + formName: string; + disabled?: boolean; + initialValues?: AccessFormCacheFlyConfigFieldValues; + onValuesChange?: (values: AccessFormCacheFlyConfigFieldValues) => void; +}; + +const initFormModel = (): AccessFormCacheFlyConfigFieldValues => { + return { + apiToken: "", + }; +}; + +const AccessFormCacheFlyConfig = ({ form: formInst, formName, disabled, initialValues, onValuesChange }: AccessFormCacheFlyConfigProps) => { + const { t } = useTranslation(); + + const formSchema = z.object({ + apiToken: z + .string() + .min(1, t("access.form.cachefly_api_token.placeholder")) + .max(64, t("common.errmsg.string_max", { max: 64 })) + .trim(), + }); + const formRule = createSchemaFieldRule(formSchema); + + const handleFormChange = (_: unknown, values: z.infer) => { + onValuesChange?.(values); + }; + + return ( +
+ + + +
+ ); +}; + +export default AccessFormCacheFlyConfig; diff --git a/ui/src/components/workflow/node/DeployNodeConfigForm.tsx b/ui/src/components/workflow/node/DeployNodeConfigForm.tsx index b0586aae..9b992914 100644 --- a/ui/src/components/workflow/node/DeployNodeConfigForm.tsx +++ b/ui/src/components/workflow/node/DeployNodeConfigForm.tsx @@ -104,8 +104,7 @@ const DeployNodeConfigForm = forwardRef !!formInst.getFieldValue("provider"), t("workflow_node.deploy.form.provider.placeholder")), + .nonempty(t("workflow_node.deploy.form.provider_access.placeholder")), providerConfig: z.any(), skipOnLastSucceeded: z.boolean().nullish(), }); @@ -246,7 +245,7 @@ const DeployNodeConfigForm = forwardRef} > - + @@ -378,7 +383,7 @@ const DeployNodeConfigForm = forwardRef - + {t("workflow_node.deploy.form.params_config.label")} @@ -386,7 +391,9 @@ const DeployNodeConfigForm = forwardRef {nestedFormEl} + + {t("workflow_node.deploy.form.strategy_config.label")} diff --git a/ui/src/domain/access.ts b/ui/src/domain/access.ts index 1779c64c..c4132f60 100644 --- a/ui/src/domain/access.ts +++ b/ui/src/domain/access.ts @@ -14,6 +14,7 @@ export interface AccessModel extends BaseModel { | AccessConfigForBaishan | AccessConfigForBaotaPanel | AccessConfigForBytePlus + | AccessConfigForCacheFly | AccessConfigForCloudflare | AccessConfigForClouDNS | AccessConfigForDogeCloud @@ -83,6 +84,10 @@ export type AccessConfigForBytePlus = { secretKey: string; }; +export type AccessConfigForCacheFly = { + apiToken: string; +}; + export type AccessConfigForCloudflare = { dnsApiToken: string; }; diff --git a/ui/src/domain/provider.ts b/ui/src/domain/provider.ts index 53eb7898..f58299da 100644 --- a/ui/src/domain/provider.ts +++ b/ui/src/domain/provider.ts @@ -12,6 +12,7 @@ export const ACCESS_PROVIDERS = Object.freeze({ BAISHAN: "baishan", BAOTAPANEL: "baotapanel", BYTEPLUS: "byteplus", + CACHEFLY: "cachefly", CLOUDFLARE: "cloudflare", CLOUDNS: "cloudns", DOGECLOUD: "dogecloud", @@ -72,16 +73,17 @@ export const accessProvidersMap: Maphttps://docs.byteplus.com/en/docs/byteplus-platform/docs-managing-keys", + "access.form.cachefly_api_token.label": "CacheFly API token", + "access.form.cachefly_api_token.placeholder": "Please enter CacheFly API token", + "access.form.cachefly_api_token.tooltip": "For more information, see https://kb.cachefly.com/kb/guide/en/generating-tokens-and-keys-Oll9Irt5TI/Steps/2460228", "access.form.cloudflare_dns_api_token.label": "Cloudflare API token", "access.form.cloudflare_dns_api_token.placeholder": "Please enter Cloudflare API token", "access.form.cloudflare_dns_api_token.tooltip": "For more information, see https://developers.cloudflare.com/fundamentals/api/get-started/create-token/", diff --git a/ui/src/i18n/locales/en/nls.provider.json b/ui/src/i18n/locales/en/nls.provider.json index dcd555c3..e53e5efe 100644 --- a/ui/src/i18n/locales/en/nls.provider.json +++ b/ui/src/i18n/locales/en/nls.provider.json @@ -29,7 +29,7 @@ "provider.baotapanel.site": "BaoTa Panel - Site", "provider.byteplus": "BytePlus", "provider.byteplus.cdn": "BytePlus - CDN (Content Delivery Network)", - "provider.cachefly": "Cachefly", + "provider.cachefly": "CacheFly", "provider.cdnfly": "Cdnfly", "provider.cloudflare": "Cloudflare", "provider.cloudns": "ClouDNS", diff --git a/ui/src/i18n/locales/zh/nls.access.json b/ui/src/i18n/locales/zh/nls.access.json index e3ae142c..bb366764 100644 --- a/ui/src/i18n/locales/zh/nls.access.json +++ b/ui/src/i18n/locales/zh/nls.access.json @@ -79,6 +79,9 @@ "access.form.byteplus_secret_key.label": "BytePlus SecretKey", "access.form.byteplus_secret_key.placeholder": "请输入 BytePlus SecretKey", "access.form.byteplus_secret_key.tooltip": "这是什么?请参阅 https://docs.byteplus.com/zh-CN/docs/byteplus-platform/docs-managing-keys", + "access.form.cachefly_api_token.label": "CacheFly API Token", + "access.form.cachefly_api_token.placeholder": "请输入 CacheFly API Token", + "access.form.cachefly_api_token.tooltip": "这是什么?请参阅 https://kb.cachefly.com/kb/guide/en/generating-tokens-and-keys-Oll9Irt5TI/Steps/2460228", "access.form.cloudflare_dns_api_token.label": "Cloudflare API Token", "access.form.cloudflare_dns_api_token.placeholder": "请输入 Cloudflare API Token", "access.form.cloudflare_dns_api_token.tooltip": "这是什么?请参阅 https://developers.cloudflare.com/fundamentals/api/get-started/create-token/", diff --git a/ui/src/i18n/locales/zh/nls.provider.json b/ui/src/i18n/locales/zh/nls.provider.json index 95cbeef7..8bc10b25 100644 --- a/ui/src/i18n/locales/zh/nls.provider.json +++ b/ui/src/i18n/locales/zh/nls.provider.json @@ -29,7 +29,7 @@ "provider.baotapanel.site": "宝塔面板 - 网站", "provider.byteplus": "BytePlus", "provider.byteplus.cdn": "BytePlus - 内容分发网络 CDN", - "provider.cachefly": "Cachefly", + "provider.cachefly": "CacheFly", "provider.cdnfly": "Cdnfly", "provider.cloudflare": "Cloudflare", "provider.cloudns": "ClouDNS", From 03d2f4ca3266958988c2a89bb7e233c8d922bd37 Mon Sep 17 00:00:00 2001 From: Fu Diwei Date: Tue, 18 Feb 2025 15:14:24 +0800 Subject: [PATCH 12/34] feat: add cdnfly deployer --- README.md | 1 + README_EN.md | 1 + internal/deployer/providers.go | 19 ++ internal/domain/access.go | 6 + internal/domain/provider.go | 3 +- .../lego-providers/acmehttpreq/acmehttpreq.go | 3 +- .../lego-providers/aliyun/aliyun.go | 3 +- .../lego-providers/aws-route53/aws-route53.go | 3 +- .../lego-providers/azure-dns/azure-dns.go | 3 +- .../lego-providers/cloudflare/cloudflare.go | 3 +- .../lego-providers/cloudns/cloudns.go | 3 +- .../acme-dns-01/lego-providers/gcore/gcore.go | 3 +- .../acme-dns-01/lego-providers/gname/gname.go | 3 +- .../lego-providers/godaddy/godaddy.go | 3 +- .../lego-providers/huaweicloud/huaweicloud.go | 3 +- .../lego-providers/namedotcom/namedotcom.go | 3 +- .../lego-providers/namesilo/namesilo.go | 3 +- .../acme-dns-01/lego-providers/ns1/ns1.go | 3 +- .../lego-providers/powerdns/powerdns.go | 3 +- .../lego-providers/rainyun/rainyun.go | 3 +- .../tencentcloud/tencentcloud.go | 3 +- .../lego-providers/volcengine/volcengine.go | 3 +- .../lego-providers/westcn/westcn.go | 3 +- .../providers/aliyun-alb/aliyun_alb.go | 4 +- .../aliyun-cas-deploy/aliyun_cas_deploy.go | 4 +- .../providers/aliyun-cdn/aliyun_cdn.go | 5 +- .../providers/aliyun-clb/aliyun_clb.go | 4 +- .../providers/aliyun-dcdn/aliyun_dcdn.go | 5 +- .../providers/aliyun-esa/aliyun_esa.go | 4 +- .../providers/aliyun-live/aliyun_live.go | 5 +- .../providers/aliyun-nlb/aliyun_nlb.go | 4 +- .../providers/aliyun-oss/aliyun_oss.go | 4 +- .../providers/aliyun-waf/aliyun_waf.go | 4 +- .../aws-cloudfront/aws_cloudfront.go | 4 +- .../baiducloud-cdn/baiducloud_cdn.go | 5 +- .../providers/baishan-cdn/baishan_cdn.go | 8 +- .../baotapanel-console/baotapanel_console.go | 13 +- .../baotapanel_console_test.go | 4 +- .../baotapanel-site/baotapanel_site.go | 13 +- .../baotapanel-site/baotapanel_site_test.go | 6 +- .../providers/byteplus-cdn/byteplus_cdn.go | 4 +- .../deployer/providers/cachefly/cachefly.go | 8 +- .../providers/cachefly/cachefly_test.go | 2 +- .../core/deployer/providers/cdnfly/cdnfly.go | 180 ++++++++++++++++++ .../deployer/providers/cdnfly/cdnfly_test.go | 81 ++++++++ .../core/deployer/providers/cdnfly/consts.go | 10 + .../providers/dogecloud-cdn/dogecloud_cdn.go | 5 +- .../edgio-applications/edgio_applications.go | 5 +- .../deployer/providers/gcore-cdn/gcore_cdn.go | 8 +- .../huaweicloud-cdn/huaweicloud_cdn.go | 5 +- .../huaweicloud-elb/huaweicloud_elb.go | 4 +- .../huaweicloud-waf/huaweicloud_waf.go | 4 +- .../providers/k8s-secret/k8s_secret.go | 4 +- .../core/deployer/providers/local/local.go | 5 +- .../deployer/providers/qiniu-cdn/qiniu_cdn.go | 5 +- .../providers/qiniu-pili/qiniu_pili.go | 5 +- .../deployer/providers/safeline/safeline.go | 13 +- .../providers/safeline/safeline_test.go | 4 +- .../pkg/core/deployer/providers/ssh/ssh.go | 5 +- .../tencentcloud-cdn/tencentcloud_cdn.go | 5 +- .../tencentcloud-clb/tencentcloud_clb.go | 4 +- .../tencentcloud-cos/tencentcloud_cos.go | 4 +- .../tencentcloud-css/tencentcloud_css.go | 5 +- .../tencentcloud-ecdn/tencentcloud_ecdn.go | 5 +- .../tencentcloud-eo/tencentcloud_eo.go | 4 +- .../tencentcloud_ssl_deploy.go | 4 +- .../tencentcloud-waf/tencentcloud_waf.go | 4 +- .../providers/ucloud-ucdn/ucloud_ucdn.go | 4 +- .../providers/ucloud-us3/ucloud_us3.go | 5 +- .../volcengine-cdn/volcengine_cdn.go | 4 +- .../volcengine-clb/volcengine_clb.go | 4 +- .../volcengine-dcdn/volcengine_dcdn.go | 5 +- .../volcengine-imagex/volcengine_imagex.go | 4 +- .../volcengine-live/volcengine_live.go | 4 +- .../volcengine-tos/volcengine_tos.go | 4 +- .../deployer/providers/webhook/webhook.go | 5 +- .../pkg/core/notifier/providers/bark/bark.go | 3 +- .../notifier/providers/dingtalk/dingtalk.go | 3 +- .../core/notifier/providers/email/email.go | 3 +- .../pkg/core/notifier/providers/lark/lark.go | 3 +- .../providers/serverchan/serverchan.go | 3 +- .../notifier/providers/telegram/telegram.go | 3 +- .../notifier/providers/webhook/webhook.go | 3 +- .../core/notifier/providers/wecom/wecom.go | 3 +- .../providers/aliyun-cas/aliyun_cas.go | 3 +- .../providers/aliyun-slb/aliyun_slb.go | 3 +- .../uploader/providers/aws-acm/aws_acm.go | 3 +- .../providers/byteplus-cdn/byteplus_cdn.go | 3 +- .../uploader/providers/dogecloud/dogecloud.go | 3 +- .../uploader/providers/gcore-cdn/gcore_cdn.go | 6 +- .../huaweicloud-elb/huaweicloud_elb.go | 2 +- .../huaweicloud-scm/huaweicloud_scm.go | 3 +- .../huaweicloud-waf/huaweicloud_waf.go | 2 +- .../providers/qiniu-sslcert/qiniu_sslcert.go | 3 +- .../tencentcloud-ssl/tencentcloud_ssl.go | 3 +- .../providers/ucloud-ussl/ucloud_ussl.go | 2 +- .../volcengine-cdn/volcengine_cdn.go | 3 +- .../volcengine_certcenter.go | 3 +- .../volcengine-live/volcengine_live.go | 3 +- internal/pkg/vendors/baishan-sdk/client.go | 8 +- internal/pkg/vendors/btpanel-sdk/client.go | 9 +- internal/pkg/vendors/cachefly-sdk/client.go | 4 +- internal/pkg/vendors/cdnfly-sdk/api.go | 59 ++++++ internal/pkg/vendors/cdnfly-sdk/client.go | 79 ++++++++ internal/pkg/vendors/cdnfly-sdk/models.go | 70 +++++++ internal/pkg/vendors/gname-sdk/client.go | 5 +- internal/pkg/vendors/safeline-sdk/client.go | 13 +- ui/public/imgs/providers/cdnfly.png | Bin 0 -> 1086 bytes ui/src/components/access/AccessForm.tsx | 3 + .../access/AccessFormCdnflyConfig.tsx | 87 +++++++++ .../workflow/node/DeployNodeConfigForm.tsx | 5 +- .../DeployNodeConfigFormAliyunESAConfig.tsx | 11 +- .../node/DeployNodeConfigFormCdnflyConfig.tsx | 89 +++++++++ .../DeployNodeConfigFormGcoreCDNConfig.tsx | 10 +- .../DeployNodeConfigFormSafeLineConfig.tsx | 21 +- ui/src/domain/access.ts | 7 + ui/src/domain/provider.ts | 4 + ui/src/i18n/locales/en/nls.access.json | 9 + .../i18n/locales/en/nls.workflow.nodes.json | 8 + ui/src/i18n/locales/zh/nls.access.json | 9 + .../i18n/locales/zh/nls.workflow.nodes.json | 8 + ui/{src => types}/vite-env.d.ts | 0 122 files changed, 955 insertions(+), 243 deletions(-) create mode 100644 internal/pkg/core/deployer/providers/cdnfly/cdnfly.go create mode 100644 internal/pkg/core/deployer/providers/cdnfly/cdnfly_test.go create mode 100644 internal/pkg/core/deployer/providers/cdnfly/consts.go create mode 100644 internal/pkg/vendors/cdnfly-sdk/api.go create mode 100644 internal/pkg/vendors/cdnfly-sdk/client.go create mode 100644 internal/pkg/vendors/cdnfly-sdk/models.go create mode 100644 ui/public/imgs/providers/cdnfly.png create mode 100644 ui/src/components/access/AccessFormCdnflyConfig.tsx create mode 100644 ui/src/components/workflow/node/DeployNodeConfigFormCdnflyConfig.tsx rename ui/{src => types}/vite-env.d.ts (100%) diff --git a/README.md b/README.md index ab7d553c..bae31da1 100644 --- a/README.md +++ b/README.md @@ -137,6 +137,7 @@ make local.run | [AWS](https://aws.amazon.com/) | 可部署到 AWS CloudFront | | [BytePlus](https://www.byteplus.com/) | 可部署到 BytePlus CDN | | [CacheFly](https://www.cachefly.com/) | 可部署到 CacheFly CDN | +| [Cdnfly](https://www.cdnfly.cn/) | 可部署到 Cdnfly CDN | | [Edgio](https://edg.io/) | 可部署到 Edgio Applications | | [Gcore](https://gcore.com/) | 可部署到 Gcore CDN | diff --git a/README_EN.md b/README_EN.md index 1320f3ea..0daf5b2b 100644 --- a/README_EN.md +++ b/README_EN.md @@ -136,6 +136,7 @@ The following hosting providers are supported: | [AWS](https://aws.amazon.com/) | Supports deployment to AWS CloudFront | | [BytePlus](https://www.byteplus.com/) | Supports deployment to BytePlus CDN | | [CacheFly](https://www.cachefly.com/) | Supports deployment to CacheFly CDN | +| [Cdnfly](https://www.cdnfly.cn/) | Supports deployment to Cdnfly CDN | | [Edgio](https://edg.io/) | Supports deployment to Edgio Applications | | [Gcore](https://gcore.com/) | Supports deployment to Gcore CDN | diff --git a/internal/deployer/providers.go b/internal/deployer/providers.go index 5c3c53ed..9b2bd4f7 100644 --- a/internal/deployer/providers.go +++ b/internal/deployer/providers.go @@ -23,6 +23,7 @@ import ( pBaotaPanelSite "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/baotapanel-site" pBytePlusCDN "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/byteplus-cdn" pCacheFly "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/cachefly" + pCdnfly "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/cdnfly" pDogeCDN "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/dogecloud-cdn" pEdgioApplications "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/edgio-applications" pGcoreCDN "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/gcore-cdn" @@ -302,6 +303,24 @@ func createDeployer(options *deployerOptions) (deployer.Deployer, logger.Logger, return deployer, logger, err } + case domain.DeployProviderTypeCdnfly: + { + access := domain.AccessConfigForCdnfly{} + if err := maps.Populate(options.ProviderAccessConfig, &access); err != nil { + return nil, nil, fmt.Errorf("failed to populate provider access config: %w", err) + } + + deployer, err := pCdnfly.NewWithLogger(&pCdnfly.CdnflyDeployerConfig{ + ApiUrl: access.ApiUrl, + ApiKey: access.ApiKey, + ApiSecret: access.ApiSecret, + ResourceType: pCdnfly.ResourceType(maps.GetValueAsString(options.ProviderDeployConfig, "resourceType")), + SiteId: maps.GetValueAsString(options.ProviderDeployConfig, "siteId"), + CertificateId: maps.GetValueAsString(options.ProviderDeployConfig, "certificateId"), + }, logger) + return deployer, logger, err + } + case domain.DeployProviderTypeDogeCloudCDN: { access := domain.AccessConfigForDogeCloud{} diff --git a/internal/domain/access.go b/internal/domain/access.go index b21b5a3f..eaa3340e 100644 --- a/internal/domain/access.go +++ b/internal/domain/access.go @@ -71,6 +71,12 @@ type AccessConfigForCacheFly struct { ApiToken string `json:"apiToken"` } +type AccessConfigForCdnfly struct { + ApiUrl string `json:"apiUrl"` + ApiKey string `json:"apiKey"` + ApiSecret string `json:"apiSecret"` +} + type AccessConfigForCloudflare struct { DnsApiToken string `json:"dnsApiToken"` } diff --git a/internal/domain/provider.go b/internal/domain/provider.go index 94e8c7ae..2aaa69a9 100644 --- a/internal/domain/provider.go +++ b/internal/domain/provider.go @@ -20,7 +20,7 @@ const ( AccessProviderTypeBaotaPanel = AccessProviderType("baotapanel") AccessProviderTypeBytePlus = AccessProviderType("byteplus") AccessProviderTypeCacheFly = AccessProviderType("cachefly") - AccessProviderTypeCdnfly = AccessProviderType("cdnfly") // Cdnly(预留) + AccessProviderTypeCdnfly = AccessProviderType("cdnfly") AccessProviderTypeCloudflare = AccessProviderType("cloudflare") AccessProviderTypeClouDNS = AccessProviderType("cloudns") AccessProviderTypeCMCCCloud = AccessProviderType("cmcccloud") // 移动云(预留) @@ -113,6 +113,7 @@ const ( DeployProviderTypeBaotaPanelSite = DeployProviderType("baotapanel-site") DeployProviderTypeBytePlusCDN = DeployProviderType("byteplus-cdn") DeployProviderTypeCacheFly = DeployProviderType("cachefly") + DeployProviderTypeCdnfly = DeployProviderType("cdnfly") DeployProviderTypeDogeCloudCDN = DeployProviderType("dogecloud-cdn") DeployProviderTypeEdgioApplications = DeployProviderType("edgio-applications") DeployProviderTypeGcoreCDN = DeployProviderType("gcore-cdn") diff --git a/internal/pkg/core/applicant/acme-dns-01/lego-providers/acmehttpreq/acmehttpreq.go b/internal/pkg/core/applicant/acme-dns-01/lego-providers/acmehttpreq/acmehttpreq.go index a25c13bb..a484b1ca 100644 --- a/internal/pkg/core/applicant/acme-dns-01/lego-providers/acmehttpreq/acmehttpreq.go +++ b/internal/pkg/core/applicant/acme-dns-01/lego-providers/acmehttpreq/acmehttpreq.go @@ -1,7 +1,6 @@ package acmehttpreq import ( - "errors" "net/url" "time" @@ -19,7 +18,7 @@ type ACMEHttpReqApplicantConfig struct { func NewChallengeProvider(config *ACMEHttpReqApplicantConfig) (challenge.Provider, error) { if config == nil { - return nil, errors.New("config is nil") + panic("config is nil") } endpoint, _ := url.Parse(config.Endpoint) diff --git a/internal/pkg/core/applicant/acme-dns-01/lego-providers/aliyun/aliyun.go b/internal/pkg/core/applicant/acme-dns-01/lego-providers/aliyun/aliyun.go index 6f6d2d89..0f5673f3 100644 --- a/internal/pkg/core/applicant/acme-dns-01/lego-providers/aliyun/aliyun.go +++ b/internal/pkg/core/applicant/acme-dns-01/lego-providers/aliyun/aliyun.go @@ -1,7 +1,6 @@ package aliyun import ( - "errors" "time" "github.com/go-acme/lego/v4/challenge" @@ -17,7 +16,7 @@ type AliyunApplicantConfig struct { func NewChallengeProvider(config *AliyunApplicantConfig) (challenge.Provider, error) { if config == nil { - return nil, errors.New("config is nil") + panic("config is nil") } providerConfig := alidns.NewDefaultConfig() diff --git a/internal/pkg/core/applicant/acme-dns-01/lego-providers/aws-route53/aws-route53.go b/internal/pkg/core/applicant/acme-dns-01/lego-providers/aws-route53/aws-route53.go index 6799885f..cf6af901 100644 --- a/internal/pkg/core/applicant/acme-dns-01/lego-providers/aws-route53/aws-route53.go +++ b/internal/pkg/core/applicant/acme-dns-01/lego-providers/aws-route53/aws-route53.go @@ -1,7 +1,6 @@ package awsroute53 import ( - "errors" "time" "github.com/go-acme/lego/v4/challenge" @@ -19,7 +18,7 @@ type AWSRoute53ApplicantConfig struct { func NewChallengeProvider(config *AWSRoute53ApplicantConfig) (challenge.Provider, error) { if config == nil { - return nil, errors.New("config is nil") + panic("config is nil") } providerConfig := route53.NewDefaultConfig() diff --git a/internal/pkg/core/applicant/acme-dns-01/lego-providers/azure-dns/azure-dns.go b/internal/pkg/core/applicant/acme-dns-01/lego-providers/azure-dns/azure-dns.go index 7cfce4a7..858d937a 100644 --- a/internal/pkg/core/applicant/acme-dns-01/lego-providers/azure-dns/azure-dns.go +++ b/internal/pkg/core/applicant/acme-dns-01/lego-providers/azure-dns/azure-dns.go @@ -1,7 +1,6 @@ package azuredns import ( - "errors" "fmt" "strings" "time" @@ -22,7 +21,7 @@ type AzureDNSApplicantConfig struct { func NewChallengeProvider(config *AzureDNSApplicantConfig) (challenge.Provider, error) { if config == nil { - return nil, errors.New("config is nil") + panic("config is nil") } providerConfig := azuredns.NewDefaultConfig() diff --git a/internal/pkg/core/applicant/acme-dns-01/lego-providers/cloudflare/cloudflare.go b/internal/pkg/core/applicant/acme-dns-01/lego-providers/cloudflare/cloudflare.go index cea32e94..de8edbcd 100644 --- a/internal/pkg/core/applicant/acme-dns-01/lego-providers/cloudflare/cloudflare.go +++ b/internal/pkg/core/applicant/acme-dns-01/lego-providers/cloudflare/cloudflare.go @@ -1,7 +1,6 @@ package cloudflare import ( - "errors" "time" "github.com/go-acme/lego/v4/challenge" @@ -16,7 +15,7 @@ type CloudflareApplicantConfig struct { func NewChallengeProvider(config *CloudflareApplicantConfig) (challenge.Provider, error) { if config == nil { - return nil, errors.New("config is nil") + panic("config is nil") } providerConfig := cloudflare.NewDefaultConfig() diff --git a/internal/pkg/core/applicant/acme-dns-01/lego-providers/cloudns/cloudns.go b/internal/pkg/core/applicant/acme-dns-01/lego-providers/cloudns/cloudns.go index 09aac6df..acde9ee7 100644 --- a/internal/pkg/core/applicant/acme-dns-01/lego-providers/cloudns/cloudns.go +++ b/internal/pkg/core/applicant/acme-dns-01/lego-providers/cloudns/cloudns.go @@ -1,7 +1,6 @@ package cloudns import ( - "errors" "time" "github.com/go-acme/lego/v4/challenge" @@ -17,7 +16,7 @@ type ClouDNSApplicantConfig struct { func NewChallengeProvider(config *ClouDNSApplicantConfig) (challenge.Provider, error) { if config == nil { - return nil, errors.New("config is nil") + panic("config is nil") } providerConfig := cloudns.NewDefaultConfig() diff --git a/internal/pkg/core/applicant/acme-dns-01/lego-providers/gcore/gcore.go b/internal/pkg/core/applicant/acme-dns-01/lego-providers/gcore/gcore.go index 1179d95d..652d7550 100644 --- a/internal/pkg/core/applicant/acme-dns-01/lego-providers/gcore/gcore.go +++ b/internal/pkg/core/applicant/acme-dns-01/lego-providers/gcore/gcore.go @@ -1,7 +1,6 @@ package gcore import ( - "errors" "time" "github.com/go-acme/lego/v4/challenge" @@ -16,7 +15,7 @@ type GcoreApplicantConfig struct { func NewChallengeProvider(config *GcoreApplicantConfig) (challenge.Provider, error) { if config == nil { - return nil, errors.New("config is nil") + panic("config is nil") } providerConfig := gcore.NewDefaultConfig() diff --git a/internal/pkg/core/applicant/acme-dns-01/lego-providers/gname/gname.go b/internal/pkg/core/applicant/acme-dns-01/lego-providers/gname/gname.go index 90cec017..2f9d2443 100644 --- a/internal/pkg/core/applicant/acme-dns-01/lego-providers/gname/gname.go +++ b/internal/pkg/core/applicant/acme-dns-01/lego-providers/gname/gname.go @@ -1,7 +1,6 @@ package gname import ( - "errors" "time" "github.com/go-acme/lego/v4/challenge" @@ -18,7 +17,7 @@ type GnameApplicantConfig struct { func NewChallengeProvider(config *GnameApplicantConfig) (challenge.Provider, error) { if config == nil { - return nil, errors.New("config is nil") + panic("config is nil") } providerConfig := internal.NewDefaultConfig() diff --git a/internal/pkg/core/applicant/acme-dns-01/lego-providers/godaddy/godaddy.go b/internal/pkg/core/applicant/acme-dns-01/lego-providers/godaddy/godaddy.go index 3a44616b..433390ed 100644 --- a/internal/pkg/core/applicant/acme-dns-01/lego-providers/godaddy/godaddy.go +++ b/internal/pkg/core/applicant/acme-dns-01/lego-providers/godaddy/godaddy.go @@ -1,7 +1,6 @@ package godaddy import ( - "errors" "time" "github.com/go-acme/lego/v4/challenge" @@ -17,7 +16,7 @@ type GoDaddyApplicantConfig struct { func NewChallengeProvider(config *GoDaddyApplicantConfig) (challenge.Provider, error) { if config == nil { - return nil, errors.New("config is nil") + panic("config is nil") } providerConfig := godaddy.NewDefaultConfig() diff --git a/internal/pkg/core/applicant/acme-dns-01/lego-providers/huaweicloud/huaweicloud.go b/internal/pkg/core/applicant/acme-dns-01/lego-providers/huaweicloud/huaweicloud.go index cbdf2928..72c0a12c 100644 --- a/internal/pkg/core/applicant/acme-dns-01/lego-providers/huaweicloud/huaweicloud.go +++ b/internal/pkg/core/applicant/acme-dns-01/lego-providers/huaweicloud/huaweicloud.go @@ -1,7 +1,6 @@ package huaweicloud import ( - "errors" "time" "github.com/go-acme/lego/v4/challenge" @@ -18,7 +17,7 @@ type HuaweiCloudApplicantConfig struct { func NewChallengeProvider(config *HuaweiCloudApplicantConfig) (challenge.Provider, error) { if config == nil { - return nil, errors.New("config is nil") + panic("config is nil") } region := config.Region diff --git a/internal/pkg/core/applicant/acme-dns-01/lego-providers/namedotcom/namedotcom.go b/internal/pkg/core/applicant/acme-dns-01/lego-providers/namedotcom/namedotcom.go index c51b1a9b..d7b98d85 100644 --- a/internal/pkg/core/applicant/acme-dns-01/lego-providers/namedotcom/namedotcom.go +++ b/internal/pkg/core/applicant/acme-dns-01/lego-providers/namedotcom/namedotcom.go @@ -1,7 +1,6 @@ package namedotcom import ( - "errors" "time" "github.com/go-acme/lego/v4/challenge" @@ -17,7 +16,7 @@ type NameDotComApplicantConfig struct { func NewChallengeProvider(config *NameDotComApplicantConfig) (challenge.Provider, error) { if config == nil { - return nil, errors.New("config is nil") + panic("config is nil") } providerConfig := namedotcom.NewDefaultConfig() diff --git a/internal/pkg/core/applicant/acme-dns-01/lego-providers/namesilo/namesilo.go b/internal/pkg/core/applicant/acme-dns-01/lego-providers/namesilo/namesilo.go index 0f1bf8ea..c2c0618b 100644 --- a/internal/pkg/core/applicant/acme-dns-01/lego-providers/namesilo/namesilo.go +++ b/internal/pkg/core/applicant/acme-dns-01/lego-providers/namesilo/namesilo.go @@ -1,7 +1,6 @@ package namesilo import ( - "errors" "time" "github.com/go-acme/lego/v4/challenge" @@ -16,7 +15,7 @@ type NameSiloApplicantConfig struct { func NewChallengeProvider(config *NameSiloApplicantConfig) (challenge.Provider, error) { if config == nil { - return nil, errors.New("config is nil") + panic("config is nil") } providerConfig := namesilo.NewDefaultConfig() diff --git a/internal/pkg/core/applicant/acme-dns-01/lego-providers/ns1/ns1.go b/internal/pkg/core/applicant/acme-dns-01/lego-providers/ns1/ns1.go index efa40076..cf2f2c40 100644 --- a/internal/pkg/core/applicant/acme-dns-01/lego-providers/ns1/ns1.go +++ b/internal/pkg/core/applicant/acme-dns-01/lego-providers/ns1/ns1.go @@ -1,7 +1,6 @@ package ns1 import ( - "errors" "time" "github.com/go-acme/lego/v4/challenge" @@ -16,7 +15,7 @@ type NS1ApplicantConfig struct { func NewChallengeProvider(config *NS1ApplicantConfig) (challenge.Provider, error) { if config == nil { - return nil, errors.New("config is nil") + panic("config is nil") } providerConfig := ns1.NewDefaultConfig() diff --git a/internal/pkg/core/applicant/acme-dns-01/lego-providers/powerdns/powerdns.go b/internal/pkg/core/applicant/acme-dns-01/lego-providers/powerdns/powerdns.go index d5fa616c..9969b002 100644 --- a/internal/pkg/core/applicant/acme-dns-01/lego-providers/powerdns/powerdns.go +++ b/internal/pkg/core/applicant/acme-dns-01/lego-providers/powerdns/powerdns.go @@ -1,7 +1,6 @@ package namesilo import ( - "errors" "net/url" "time" @@ -18,7 +17,7 @@ type PowerDNSApplicantConfig struct { func NewChallengeProvider(config *PowerDNSApplicantConfig) (challenge.Provider, error) { if config == nil { - return nil, errors.New("config is nil") + panic("config is nil") } host, _ := url.Parse(config.ApiUrl) diff --git a/internal/pkg/core/applicant/acme-dns-01/lego-providers/rainyun/rainyun.go b/internal/pkg/core/applicant/acme-dns-01/lego-providers/rainyun/rainyun.go index d250a279..eef887d2 100644 --- a/internal/pkg/core/applicant/acme-dns-01/lego-providers/rainyun/rainyun.go +++ b/internal/pkg/core/applicant/acme-dns-01/lego-providers/rainyun/rainyun.go @@ -1,7 +1,6 @@ package rainyun import ( - "errors" "time" "github.com/go-acme/lego/v4/challenge" @@ -16,7 +15,7 @@ type RainYunApplicantConfig struct { func NewChallengeProvider(config *RainYunApplicantConfig) (challenge.Provider, error) { if config == nil { - return nil, errors.New("config is nil") + panic("config is nil") } providerConfig := rainyun.NewDefaultConfig() diff --git a/internal/pkg/core/applicant/acme-dns-01/lego-providers/tencentcloud/tencentcloud.go b/internal/pkg/core/applicant/acme-dns-01/lego-providers/tencentcloud/tencentcloud.go index f7e6bf7b..0e60328f 100644 --- a/internal/pkg/core/applicant/acme-dns-01/lego-providers/tencentcloud/tencentcloud.go +++ b/internal/pkg/core/applicant/acme-dns-01/lego-providers/tencentcloud/tencentcloud.go @@ -1,7 +1,6 @@ package tencentcloud import ( - "errors" "time" "github.com/go-acme/lego/v4/challenge" @@ -17,7 +16,7 @@ type TencentCloudApplicantConfig struct { func NewChallengeProvider(config *TencentCloudApplicantConfig) (challenge.Provider, error) { if config == nil { - return nil, errors.New("config is nil") + panic("config is nil") } providerConfig := tencentcloud.NewDefaultConfig() diff --git a/internal/pkg/core/applicant/acme-dns-01/lego-providers/volcengine/volcengine.go b/internal/pkg/core/applicant/acme-dns-01/lego-providers/volcengine/volcengine.go index a8f11ff9..dfeddccd 100644 --- a/internal/pkg/core/applicant/acme-dns-01/lego-providers/volcengine/volcengine.go +++ b/internal/pkg/core/applicant/acme-dns-01/lego-providers/volcengine/volcengine.go @@ -1,7 +1,6 @@ package volcengine import ( - "errors" "time" "github.com/go-acme/lego/v4/challenge" @@ -17,7 +16,7 @@ type VolcEngineApplicantConfig struct { func NewChallengeProvider(config *VolcEngineApplicantConfig) (challenge.Provider, error) { if config == nil { - return nil, errors.New("config is nil") + panic("config is nil") } providerConfig := volcengine.NewDefaultConfig() diff --git a/internal/pkg/core/applicant/acme-dns-01/lego-providers/westcn/westcn.go b/internal/pkg/core/applicant/acme-dns-01/lego-providers/westcn/westcn.go index f20b5d21..d7b26afd 100644 --- a/internal/pkg/core/applicant/acme-dns-01/lego-providers/westcn/westcn.go +++ b/internal/pkg/core/applicant/acme-dns-01/lego-providers/westcn/westcn.go @@ -1,7 +1,6 @@ package westcn import ( - "errors" "time" "github.com/go-acme/lego/v4/challenge" @@ -17,7 +16,7 @@ type WestcnApplicantConfig struct { func NewChallengeProvider(config *WestcnApplicantConfig) (challenge.Provider, error) { if config == nil { - return nil, errors.New("config is nil") + panic("config is nil") } providerConfig := westcn.NewDefaultConfig() diff --git a/internal/pkg/core/deployer/providers/aliyun-alb/aliyun_alb.go b/internal/pkg/core/deployer/providers/aliyun-alb/aliyun_alb.go index db4242d2..e81975ee 100644 --- a/internal/pkg/core/deployer/providers/aliyun-alb/aliyun_alb.go +++ b/internal/pkg/core/deployer/providers/aliyun-alb/aliyun_alb.go @@ -61,11 +61,11 @@ func New(config *AliyunALBDeployerConfig) (*AliyunALBDeployer, error) { func NewWithLogger(config *AliyunALBDeployerConfig, logger logger.Logger) (*AliyunALBDeployer, error) { if config == nil { - return nil, errors.New("config is nil") + panic("config is nil") } if logger == nil { - return nil, errors.New("logger is nil") + panic("logger is nil") } clients, err := createSdkClients(config.AccessKeyId, config.AccessKeySecret, config.Region) diff --git a/internal/pkg/core/deployer/providers/aliyun-cas-deploy/aliyun_cas_deploy.go b/internal/pkg/core/deployer/providers/aliyun-cas-deploy/aliyun_cas_deploy.go index 35f8edde..fb35364a 100644 --- a/internal/pkg/core/deployer/providers/aliyun-cas-deploy/aliyun_cas_deploy.go +++ b/internal/pkg/core/deployer/providers/aliyun-cas-deploy/aliyun_cas_deploy.go @@ -47,11 +47,11 @@ func New(config *AliyunCASDeployDeployerConfig) (*AliyunCASDeployDeployer, error func NewWithLogger(config *AliyunCASDeployDeployerConfig, logger logger.Logger) (*AliyunCASDeployDeployer, error) { if config == nil { - return nil, errors.New("config is nil") + panic("config is nil") } if logger == nil { - return nil, errors.New("logger is nil") + panic("logger is nil") } client, err := createSdkClient(config.AccessKeyId, config.AccessKeySecret, config.Region) diff --git a/internal/pkg/core/deployer/providers/aliyun-cdn/aliyun_cdn.go b/internal/pkg/core/deployer/providers/aliyun-cdn/aliyun_cdn.go index d2de5684..df188523 100644 --- a/internal/pkg/core/deployer/providers/aliyun-cdn/aliyun_cdn.go +++ b/internal/pkg/core/deployer/providers/aliyun-cdn/aliyun_cdn.go @@ -2,7 +2,6 @@ import ( "context" - "errors" "fmt" "strings" "time" @@ -39,11 +38,11 @@ func New(config *AliyunCDNDeployerConfig) (*AliyunCDNDeployer, error) { func NewWithLogger(config *AliyunCDNDeployerConfig, logger logger.Logger) (*AliyunCDNDeployer, error) { if config == nil { - return nil, errors.New("config is nil") + panic("config is nil") } if logger == nil { - return nil, errors.New("logger is nil") + panic("logger is nil") } client, err := createSdkClient(config.AccessKeyId, config.AccessKeySecret) diff --git a/internal/pkg/core/deployer/providers/aliyun-clb/aliyun_clb.go b/internal/pkg/core/deployer/providers/aliyun-clb/aliyun_clb.go index 25f223b6..f344d1b6 100644 --- a/internal/pkg/core/deployer/providers/aliyun-clb/aliyun_clb.go +++ b/internal/pkg/core/deployer/providers/aliyun-clb/aliyun_clb.go @@ -51,11 +51,11 @@ func New(config *AliyunCLBDeployerConfig) (*AliyunCLBDeployer, error) { func NewWithLogger(config *AliyunCLBDeployerConfig, logger logger.Logger) (*AliyunCLBDeployer, error) { if config == nil { - return nil, errors.New("config is nil") + panic("config is nil") } if logger == nil { - return nil, errors.New("logger is nil") + panic("logger is nil") } client, err := createSdkClient(config.AccessKeyId, config.AccessKeySecret, config.Region) diff --git a/internal/pkg/core/deployer/providers/aliyun-dcdn/aliyun_dcdn.go b/internal/pkg/core/deployer/providers/aliyun-dcdn/aliyun_dcdn.go index 65c9a375..8c571a3f 100644 --- a/internal/pkg/core/deployer/providers/aliyun-dcdn/aliyun_dcdn.go +++ b/internal/pkg/core/deployer/providers/aliyun-dcdn/aliyun_dcdn.go @@ -2,7 +2,6 @@ import ( "context" - "errors" "fmt" "strings" "time" @@ -39,11 +38,11 @@ func New(config *AliyunDCDNDeployerConfig) (*AliyunDCDNDeployer, error) { func NewWithLogger(config *AliyunDCDNDeployerConfig, logger logger.Logger) (*AliyunDCDNDeployer, error) { if config == nil { - return nil, errors.New("config is nil") + panic("config is nil") } if logger == nil { - return nil, errors.New("logger is nil") + panic("logger is nil") } client, err := createSdkClient(config.AccessKeyId, config.AccessKeySecret) diff --git a/internal/pkg/core/deployer/providers/aliyun-esa/aliyun_esa.go b/internal/pkg/core/deployer/providers/aliyun-esa/aliyun_esa.go index 8f492e36..87a483ff 100644 --- a/internal/pkg/core/deployer/providers/aliyun-esa/aliyun_esa.go +++ b/internal/pkg/core/deployer/providers/aliyun-esa/aliyun_esa.go @@ -44,11 +44,11 @@ func New(config *AliyunESADeployerConfig) (*AliyunESADeployer, error) { func NewWithLogger(config *AliyunESADeployerConfig, logger logger.Logger) (*AliyunESADeployer, error) { if config == nil { - return nil, errors.New("config is nil") + panic("config is nil") } if logger == nil { - return nil, errors.New("logger is nil") + panic("logger is nil") } client, err := createSdkClient(config.AccessKeyId, config.AccessKeySecret, config.Region) diff --git a/internal/pkg/core/deployer/providers/aliyun-live/aliyun_live.go b/internal/pkg/core/deployer/providers/aliyun-live/aliyun_live.go index 2e0c46af..fdc61d7d 100644 --- a/internal/pkg/core/deployer/providers/aliyun-live/aliyun_live.go +++ b/internal/pkg/core/deployer/providers/aliyun-live/aliyun_live.go @@ -2,7 +2,6 @@ import ( "context" - "errors" "fmt" "strings" "time" @@ -41,11 +40,11 @@ func New(config *AliyunLiveDeployerConfig) (*AliyunLiveDeployer, error) { func NewWithLogger(config *AliyunLiveDeployerConfig, logger logger.Logger) (*AliyunLiveDeployer, error) { if config == nil { - return nil, errors.New("config is nil") + panic("config is nil") } if logger == nil { - return nil, errors.New("logger is nil") + panic("logger is nil") } client, err := createSdkClient(config.AccessKeyId, config.AccessKeySecret, config.Region) diff --git a/internal/pkg/core/deployer/providers/aliyun-nlb/aliyun_nlb.go b/internal/pkg/core/deployer/providers/aliyun-nlb/aliyun_nlb.go index e55c9b80..8918e743 100644 --- a/internal/pkg/core/deployer/providers/aliyun-nlb/aliyun_nlb.go +++ b/internal/pkg/core/deployer/providers/aliyun-nlb/aliyun_nlb.go @@ -49,11 +49,11 @@ func New(config *AliyunNLBDeployerConfig) (*AliyunNLBDeployer, error) { func NewWithLogger(config *AliyunNLBDeployerConfig, logger logger.Logger) (*AliyunNLBDeployer, error) { if config == nil { - return nil, errors.New("config is nil") + panic("config is nil") } if logger == nil { - return nil, errors.New("logger is nil") + panic("logger is nil") } client, err := createSdkClient(config.AccessKeyId, config.AccessKeySecret, config.Region) diff --git a/internal/pkg/core/deployer/providers/aliyun-oss/aliyun_oss.go b/internal/pkg/core/deployer/providers/aliyun-oss/aliyun_oss.go index 9caf0a3b..7b8b8c54 100644 --- a/internal/pkg/core/deployer/providers/aliyun-oss/aliyun_oss.go +++ b/internal/pkg/core/deployer/providers/aliyun-oss/aliyun_oss.go @@ -39,11 +39,11 @@ func New(config *AliyunOSSDeployerConfig) (*AliyunOSSDeployer, error) { func NewWithLogger(config *AliyunOSSDeployerConfig, logger logger.Logger) (*AliyunOSSDeployer, error) { if config == nil { - return nil, errors.New("config is nil") + panic("config is nil") } if logger == nil { - return nil, errors.New("logger is nil") + panic("logger is nil") } client, err := createSdkClient(config.AccessKeyId, config.AccessKeySecret, config.Region) diff --git a/internal/pkg/core/deployer/providers/aliyun-waf/aliyun_waf.go b/internal/pkg/core/deployer/providers/aliyun-waf/aliyun_waf.go index 476ffaef..d355b382 100644 --- a/internal/pkg/core/deployer/providers/aliyun-waf/aliyun_waf.go +++ b/internal/pkg/core/deployer/providers/aliyun-waf/aliyun_waf.go @@ -43,11 +43,11 @@ func New(config *AliyunWAFDeployerConfig) (*AliyunWAFDeployer, error) { func NewWithLogger(config *AliyunWAFDeployerConfig, logger logger.Logger) (*AliyunWAFDeployer, error) { if config == nil { - return nil, errors.New("config is nil") + panic("config is nil") } if logger == nil { - return nil, errors.New("logger is nil") + panic("logger is nil") } client, err := createSdkClient(config.AccessKeyId, config.AccessKeySecret, config.Region) diff --git a/internal/pkg/core/deployer/providers/aws-cloudfront/aws_cloudfront.go b/internal/pkg/core/deployer/providers/aws-cloudfront/aws_cloudfront.go index cf520a75..21c13df6 100644 --- a/internal/pkg/core/deployer/providers/aws-cloudfront/aws_cloudfront.go +++ b/internal/pkg/core/deployer/providers/aws-cloudfront/aws_cloudfront.go @@ -43,11 +43,11 @@ func New(config *AWSCloudFrontDeployerConfig) (*AWSCloudFrontDeployer, error) { func NewWithLogger(config *AWSCloudFrontDeployerConfig, logger logger.Logger) (*AWSCloudFrontDeployer, error) { if config == nil { - return nil, errors.New("config is nil") + panic("config is nil") } if logger == nil { - return nil, errors.New("logger is nil") + panic("logger is nil") } client, err := createSdkClient(config.AccessKeyId, config.SecretAccessKey, config.Region) diff --git a/internal/pkg/core/deployer/providers/baiducloud-cdn/baiducloud_cdn.go b/internal/pkg/core/deployer/providers/baiducloud-cdn/baiducloud_cdn.go index ab932b42..ae34666a 100644 --- a/internal/pkg/core/deployer/providers/baiducloud-cdn/baiducloud_cdn.go +++ b/internal/pkg/core/deployer/providers/baiducloud-cdn/baiducloud_cdn.go @@ -2,7 +2,6 @@ import ( "context" - "errors" "fmt" "time" @@ -37,11 +36,11 @@ func New(config *BaiduCloudCDNDeployerConfig) (*BaiduCloudCDNDeployer, error) { func NewWithLogger(config *BaiduCloudCDNDeployerConfig, logger logger.Logger) (*BaiduCloudCDNDeployer, error) { if config == nil { - return nil, errors.New("config is nil") + panic("config is nil") } if logger == nil { - return nil, errors.New("logger is nil") + panic("logger is nil") } client, err := createSdkClient(config.AccessKeyId, config.SecretAccessKey) diff --git a/internal/pkg/core/deployer/providers/baishan-cdn/baishan_cdn.go b/internal/pkg/core/deployer/providers/baishan-cdn/baishan_cdn.go index 214f050e..454909fd 100644 --- a/internal/pkg/core/deployer/providers/baishan-cdn/baishan_cdn.go +++ b/internal/pkg/core/deployer/providers/baishan-cdn/baishan_cdn.go @@ -34,11 +34,11 @@ func New(config *BaishanCDNDeployerConfig) (*BaishanCDNDeployer, error) { func NewWithLogger(config *BaishanCDNDeployerConfig, logger logger.Logger) (*BaishanCDNDeployer, error) { if config == nil { - return nil, errors.New("config is nil") + panic("config is nil") } if logger == nil { - return nil, errors.New("logger is nil") + panic("logger is nil") } client, err := createSdkClient(config.ApiToken) @@ -111,6 +111,10 @@ func (d *BaishanCDNDeployer) Deploy(ctx context.Context, certPem string, privkey } func createSdkClient(apiToken string) (*bssdk.Client, error) { + if apiToken == "" { + return nil, errors.New("invalid baishan api token") + } + client := bssdk.NewClient(apiToken) return client, nil } diff --git a/internal/pkg/core/deployer/providers/baotapanel-console/baotapanel_console.go b/internal/pkg/core/deployer/providers/baotapanel-console/baotapanel_console.go index e9c955c7..19dda685 100644 --- a/internal/pkg/core/deployer/providers/baotapanel-console/baotapanel_console.go +++ b/internal/pkg/core/deployer/providers/baotapanel-console/baotapanel_console.go @@ -3,6 +3,7 @@ import ( "context" "errors" + "net/url" xerrors "github.com/pkg/errors" @@ -34,11 +35,11 @@ func New(config *BaotaPanelConsoleDeployerConfig) (*BaotaPanelConsoleDeployer, e func NewWithLogger(config *BaotaPanelConsoleDeployerConfig, logger logger.Logger) (*BaotaPanelConsoleDeployer, error) { if config == nil { - return nil, errors.New("config is nil") + panic("config is nil") } if logger == nil { - return nil, errors.New("logger is nil") + panic("logger is nil") } client, err := createSdkClient(config.ApiUrl, config.ApiKey) @@ -82,6 +83,14 @@ func (d *BaotaPanelConsoleDeployer) Deploy(ctx context.Context, certPem string, } func createSdkClient(apiUrl, apiKey string) (*btsdk.Client, error) { + if _, err := url.Parse(apiUrl); err != nil { + return nil, errors.New("invalid baota api url") + } + + if apiKey == "" { + return nil, errors.New("invalid baota api key") + } + client := btsdk.NewClient(apiUrl, apiKey) return client, nil } diff --git a/internal/pkg/core/deployer/providers/baotapanel-console/baotapanel_console_test.go b/internal/pkg/core/deployer/providers/baotapanel-console/baotapanel_console_test.go index ff388440..90a0a4ba 100644 --- a/internal/pkg/core/deployer/providers/baotapanel-console/baotapanel_console_test.go +++ b/internal/pkg/core/deployer/providers/baotapanel-console/baotapanel_console_test.go @@ -33,8 +33,8 @@ Shell command to run this test: go test -v ./baotapanel_console_test.go -args \ --CERTIMATE_DEPLOYER_BAOTAPANELCONSOLE_INPUTCERTPATH="/path/to/your-input-cert.pem" \ --CERTIMATE_DEPLOYER_BAOTAPANELCONSOLE_INPUTKEYPATH="/path/to/your-input-key.pem" \ - --CERTIMATE_DEPLOYER_BAOTAPANELCONSOLE_APIURL="your-baota-panel-url" \ - --CERTIMATE_DEPLOYER_BAOTAPANELCONSOLE_APIKEY="your-baota-panel-key" + --CERTIMATE_DEPLOYER_BAOTAPANELCONSOLE_APIURL="http://127.0.0.1:8888" \ + --CERTIMATE_DEPLOYER_BAOTAPANELCONSOLE_APIKEY="your-api-key" */ func TestDeploy(t *testing.T) { flag.Parse() diff --git a/internal/pkg/core/deployer/providers/baotapanel-site/baotapanel_site.go b/internal/pkg/core/deployer/providers/baotapanel-site/baotapanel_site.go index 14261968..6fffa670 100644 --- a/internal/pkg/core/deployer/providers/baotapanel-site/baotapanel_site.go +++ b/internal/pkg/core/deployer/providers/baotapanel-site/baotapanel_site.go @@ -3,6 +3,7 @@ import ( "context" "errors" + "net/url" xerrors "github.com/pkg/errors" @@ -34,11 +35,11 @@ func New(config *BaotaPanelSiteDeployerConfig) (*BaotaPanelSiteDeployer, error) func NewWithLogger(config *BaotaPanelSiteDeployerConfig, logger logger.Logger) (*BaotaPanelSiteDeployer, error) { if config == nil { - return nil, errors.New("config is nil") + panic("config is nil") } if logger == nil { - return nil, errors.New("logger is nil") + panic("logger is nil") } client, err := createSdkClient(config.ApiUrl, config.ApiKey) @@ -76,6 +77,14 @@ func (d *BaotaPanelSiteDeployer) Deploy(ctx context.Context, certPem string, pri } func createSdkClient(apiUrl, apiKey string) (*btsdk.Client, error) { + if _, err := url.Parse(apiUrl); err != nil { + return nil, errors.New("invalid baota api url") + } + + if apiKey == "" { + return nil, errors.New("invalid baota api key") + } + client := btsdk.NewClient(apiUrl, apiKey) return client, nil } diff --git a/internal/pkg/core/deployer/providers/baotapanel-site/baotapanel_site_test.go b/internal/pkg/core/deployer/providers/baotapanel-site/baotapanel_site_test.go index 486e8428..ad45b56c 100644 --- a/internal/pkg/core/deployer/providers/baotapanel-site/baotapanel_site_test.go +++ b/internal/pkg/core/deployer/providers/baotapanel-site/baotapanel_site_test.go @@ -35,9 +35,9 @@ Shell command to run this test: go test -v ./baotapanel_site_test.go -args \ --CERTIMATE_DEPLOYER_BAOTAPANELSITE_INPUTCERTPATH="/path/to/your-input-cert.pem" \ --CERTIMATE_DEPLOYER_BAOTAPANELSITE_INPUTKEYPATH="/path/to/your-input-key.pem" \ - --CERTIMATE_DEPLOYER_BAOTAPANELSITE_APIURL="your-baota-panel-url" \ - --CERTIMATE_DEPLOYER_BAOTAPANELSITE_APIKEY="your-baota-panel-key" \ - --CERTIMATE_DEPLOYER_BAOTAPANELSITE_SITENAME="your-baota-site-name" + --CERTIMATE_DEPLOYER_BAOTAPANELSITE_APIURL="http://127.0.0.1:8888" \ + --CERTIMATE_DEPLOYER_BAOTAPANELSITE_APIKEY="your-api-key" \ + --CERTIMATE_DEPLOYER_BAOTAPANELSITE_SITENAME="your-site-name" */ func TestDeploy(t *testing.T) { flag.Parse() diff --git a/internal/pkg/core/deployer/providers/byteplus-cdn/byteplus_cdn.go b/internal/pkg/core/deployer/providers/byteplus-cdn/byteplus_cdn.go index 514bbd08..55c3e216 100644 --- a/internal/pkg/core/deployer/providers/byteplus-cdn/byteplus_cdn.go +++ b/internal/pkg/core/deployer/providers/byteplus-cdn/byteplus_cdn.go @@ -39,11 +39,11 @@ func New(config *BytePlusCDNDeployerConfig) (*BytePlusCDNDeployer, error) { func NewWithLogger(config *BytePlusCDNDeployerConfig, logger logger.Logger) (*BytePlusCDNDeployer, error) { if config == nil { - return nil, errors.New("config is nil") + panic("config is nil") } if logger == nil { - return nil, errors.New("logger is nil") + panic("logger is nil") } client := bpCdn.NewInstance() diff --git a/internal/pkg/core/deployer/providers/cachefly/cachefly.go b/internal/pkg/core/deployer/providers/cachefly/cachefly.go index fe3fb3e4..352fba40 100644 --- a/internal/pkg/core/deployer/providers/cachefly/cachefly.go +++ b/internal/pkg/core/deployer/providers/cachefly/cachefly.go @@ -30,11 +30,11 @@ func New(config *CacheFlyDeployerConfig) (*CacheFlyDeployer, error) { func NewWithLogger(config *CacheFlyDeployerConfig, logger logger.Logger) (*CacheFlyDeployer, error) { if config == nil { - return nil, errors.New("config is nil") + panic("config is nil") } if logger == nil { - return nil, errors.New("logger is nil") + panic("logger is nil") } client, err := createSdkClient(config.ApiToken) @@ -66,6 +66,10 @@ func (d *CacheFlyDeployer) Deploy(ctx context.Context, certPem string, privkeyPe } func createSdkClient(apiToken string) (*cfsdk.Client, error) { + if apiToken == "" { + return nil, errors.New("invalid cachefly api token") + } + client := cfsdk.NewClient(apiToken) return client, nil } diff --git a/internal/pkg/core/deployer/providers/cachefly/cachefly_test.go b/internal/pkg/core/deployer/providers/cachefly/cachefly_test.go index fcef1172..776b2438 100644 --- a/internal/pkg/core/deployer/providers/cachefly/cachefly_test.go +++ b/internal/pkg/core/deployer/providers/cachefly/cachefly_test.go @@ -31,7 +31,7 @@ Shell command to run this test: go test -v ./cachefly_test.go -args \ --CERTIMATE_DEPLOYER_CACHEFLY_INPUTCERTPATH="/path/to/your-input-cert.pem" \ --CERTIMATE_DEPLOYER_CACHEFLY_INPUTKEYPATH="/path/to/your-input-key.pem" \ - --CERTIMATE_DEPLOYER_CACHEFLY_APITOKEN="your-baota-panel-key" + --CERTIMATE_DEPLOYER_CACHEFLY_APITOKEN="your-api-token" */ func TestDeploy(t *testing.T) { flag.Parse() diff --git a/internal/pkg/core/deployer/providers/cdnfly/cdnfly.go b/internal/pkg/core/deployer/providers/cdnfly/cdnfly.go new file mode 100644 index 00000000..27abbc2f --- /dev/null +++ b/internal/pkg/core/deployer/providers/cdnfly/cdnfly.go @@ -0,0 +1,180 @@ +package cdnfly + +import ( + "context" + "encoding/json" + "errors" + "fmt" + "net/url" + "time" + + xerrors "github.com/pkg/errors" + + "github.com/usual2970/certimate/internal/pkg/core/deployer" + "github.com/usual2970/certimate/internal/pkg/core/logger" + cfsdk "github.com/usual2970/certimate/internal/pkg/vendors/cdnfly-sdk" +) + +type CdnflyDeployerConfig struct { + // Cdnfly 地址。 + ApiUrl string `json:"apiUrl"` + // Cdnfly 用户端 API Key。 + ApiKey string `json:"apiKey"` + // Cdnfly 用户端 API Secret。 + ApiSecret string `json:"apiSecret"` + // 部署资源类型。 + ResourceType ResourceType `json:"resourceType"` + // 网站 ID。 + // 部署资源类型为 [RESOURCE_TYPE_SITE] 时必填。 + SiteId string `json:"siteId,omitempty"` + // 证书 ID。 + // 部署资源类型为 [RESOURCE_TYPE_CERTIFICATE] 时必填。 + CertificateId string `json:"certificateId,omitempty"` +} + +type CdnflyDeployer struct { + config *CdnflyDeployerConfig + logger logger.Logger + sdkClient *cfsdk.Client +} + +var _ deployer.Deployer = (*CdnflyDeployer)(nil) + +func New(config *CdnflyDeployerConfig) (*CdnflyDeployer, error) { + return NewWithLogger(config, logger.NewNilLogger()) +} + +func NewWithLogger(config *CdnflyDeployerConfig, logger logger.Logger) (*CdnflyDeployer, error) { + if config == nil { + panic("config is nil") + } + + if logger == nil { + panic("logger is nil") + } + + client, err := createSdkClient(config.ApiUrl, config.ApiKey, config.ApiSecret) + if err != nil { + return nil, xerrors.Wrap(err, "failed to create sdk client") + } + + return &CdnflyDeployer{ + logger: logger, + config: config, + sdkClient: client, + }, nil +} + +func (d *CdnflyDeployer) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { + // 根据部署资源类型决定部署方式 + switch d.config.ResourceType { + case RESOURCE_TYPE_SITE: + if err := d.deployToSite(ctx, certPem, privkeyPem); err != nil { + return nil, err + } + + case RESOURCE_TYPE_CERTIFICATE: + if err := d.deployToCertificate(ctx, certPem, privkeyPem); err != nil { + return nil, err + } + + default: + return nil, fmt.Errorf("unsupported resource type: %s", d.config.ResourceType) + } + + return &deployer.DeployResult{}, nil +} + +func (d *CdnflyDeployer) deployToSite(ctx context.Context, certPem string, privkeyPem string) error { + if d.config.SiteId == "" { + return errors.New("config `siteId` is required") + } + + // 获取单个网站详情 + // REF: https://doc.cdnfly.cn/wangzhanguanli-v1-sites.html#%E8%8E%B7%E5%8F%96%E5%8D%95%E4%B8%AA%E7%BD%91%E7%AB%99%E8%AF%A6%E6%83%85 + getSiteReq := &cfsdk.GetSiteRequest{ + Id: d.config.SiteId, + } + getSiteResp, err := d.sdkClient.GetSite(getSiteReq) + if err != nil { + return xerrors.Wrap(err, "failed to execute sdk request 'cdnfly.GetSite'") + } else { + d.logger.Logt("已获取网站详情", getSiteResp) + } + + // 添加单个证书 + // REF: https://doc.cdnfly.cn/wangzhanzhengshu-v1-certs.html#%E6%B7%BB%E5%8A%A0%E5%8D%95%E4%B8%AA%E6%88%96%E5%A4%9A%E4%B8%AA%E8%AF%81%E4%B9%A6-%E5%A4%9A%E4%B8%AA%E8%AF%81%E4%B9%A6%E6%97%B6%E6%95%B0%E6%8D%AE%E6%A0%BC%E5%BC%8F%E4%B8%BA%E6%95%B0%E7%BB%84 + createCertificateReq := &cfsdk.CreateCertificateRequest{ + Name: fmt.Sprintf("certimate-%d", time.Now().UnixMilli()), + Type: "custom", + Cert: certPem, + Key: privkeyPem, + } + createCertificateResp, err := d.sdkClient.CreateCertificate(createCertificateReq) + if err != nil { + return xerrors.Wrap(err, "failed to execute sdk request 'cdnfly.CreateCertificate'") + } else { + d.logger.Logt("已添加证书", createCertificateResp) + } + + // 修改单个网站 + // REF: https://doc.cdnfly.cn/wangzhanguanli-v1-sites.html#%E4%BF%AE%E6%94%B9%E5%8D%95%E4%B8%AA%E7%BD%91%E7%AB%99 + updateSiteHttpsListenMap := make(map[string]any) + _ = json.Unmarshal([]byte(getSiteResp.Data.HttpsListen), &updateSiteHttpsListenMap) + updateSiteHttpsListenMap["cert"] = createCertificateResp.Data + updateSiteHttpsListenData, _ := json.Marshal(updateSiteHttpsListenMap) + updateSiteHttpsListen := string(updateSiteHttpsListenData) + updateSiteReq := &cfsdk.UpdateSiteRequest{ + Id: d.config.SiteId, + HttpsListen: &updateSiteHttpsListen, + } + updateSiteResp, err := d.sdkClient.UpdateSite(updateSiteReq) + if err != nil { + return xerrors.Wrap(err, "failed to execute sdk request 'cdnfly.UpdateSite'") + } else { + d.logger.Logt("已修改网站", updateSiteResp) + } + + return nil +} + +func (d *CdnflyDeployer) deployToCertificate(ctx context.Context, certPem string, privkeyPem string) error { + if d.config.CertificateId == "" { + return errors.New("config `certificateId` is required") + } + + // 修改单个证书 + // REF: https://doc.cdnfly.cn/wangzhanzhengshu-v1-certs.html#%E4%BF%AE%E6%94%B9%E5%8D%95%E4%B8%AA%E8%AF%81%E4%B9%A6 + updateCertificateType := "custom" + updateCertificateReq := &cfsdk.UpdateCertificateRequest{ + Id: d.config.CertificateId, + Type: &updateCertificateType, + Cert: &certPem, + Key: &privkeyPem, + } + updateCertificateResp, err := d.sdkClient.UpdateCertificate(updateCertificateReq) + if err != nil { + return xerrors.Wrap(err, "failed to execute sdk request 'cdnfly.UpdateCertificate'") + } else { + d.logger.Logt("已修改证书", updateCertificateResp) + } + + return nil +} + +func createSdkClient(apiUrl, apiKey, apiSecret string) (*cfsdk.Client, error) { + if _, err := url.Parse(apiUrl); err != nil { + return nil, errors.New("invalid cachefly api url") + } + + if apiKey == "" { + return nil, errors.New("invalid cachefly api key") + } + + if apiSecret == "" { + return nil, errors.New("invalid cachefly api secret") + } + + client := cfsdk.NewClient(apiUrl, apiKey, apiSecret) + return client, nil +} diff --git a/internal/pkg/core/deployer/providers/cdnfly/cdnfly_test.go b/internal/pkg/core/deployer/providers/cdnfly/cdnfly_test.go new file mode 100644 index 00000000..2d9604cd --- /dev/null +++ b/internal/pkg/core/deployer/providers/cdnfly/cdnfly_test.go @@ -0,0 +1,81 @@ +package cdnfly_test + +import ( + "context" + "flag" + "fmt" + "os" + "strings" + "testing" + + provider "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/cdnfly" +) + +var ( + fInputCertPath string + fInputKeyPath string + fApiUrl string + fApiKey string + fApiSecret string + fCertificateId string +) + +func init() { + argsPrefix := "CERTIMATE_DEPLOYER_CDNFLY_" + + flag.StringVar(&fInputCertPath, argsPrefix+"INPUTCERTPATH", "", "") + flag.StringVar(&fInputKeyPath, argsPrefix+"INPUTKEYPATH", "", "") + flag.StringVar(&fApiUrl, argsPrefix+"APIURL", "", "") + flag.StringVar(&fApiKey, argsPrefix+"APIKEY", "", "") + flag.StringVar(&fApiSecret, argsPrefix+"APISECRET", "", "") + flag.StringVar(&fCertificateId, argsPrefix+"CERTIFICATEID", "", "") +} + +/* +Shell command to run this test: + + go test -v ./cdnfly_test.go -args \ + --CERTIMATE_DEPLOYER_CDNFLY_INPUTCERTPATH="/path/to/your-input-cert.pem" \ + --CERTIMATE_DEPLOYER_CDNFLY_INPUTKEYPATH="/path/to/your-input-key.pem" \ + --CERTIMATE_DEPLOYER_CDNFLY_APIURL="http://127.0.0.1:88" \ + --CERTIMATE_DEPLOYER_CDNFLY_APIKEY="your-api-key" \ + --CERTIMATE_DEPLOYER_CDNFLY_APISECRET="your-api-secret" \ + --CERTIMATE_DEPLOYER_CDNFLY_CERTIFICATEID="your-cert-id" +*/ +func TestDeploy(t *testing.T) { + flag.Parse() + + t.Run("Deploy", func(t *testing.T) { + t.Log(strings.Join([]string{ + "args:", + fmt.Sprintf("INPUTCERTPATH: %v", fInputCertPath), + fmt.Sprintf("INPUTKEYPATH: %v", fInputKeyPath), + fmt.Sprintf("APIURL: %v", fApiUrl), + fmt.Sprintf("APIKEY: %v", fApiKey), + fmt.Sprintf("APISECRET: %v", fApiSecret), + fmt.Sprintf("CERTIFICATEID: %v", fCertificateId), + }, "\n")) + + deployer, err := provider.New(&provider.CdnflyDeployerConfig{ + ApiUrl: fApiUrl, + ApiKey: fApiKey, + ApiSecret: fApiSecret, + ResourceType: provider.RESOURCE_TYPE_CERTIFICATE, + CertificateId: fCertificateId, + }) + if err != nil { + t.Errorf("err: %+v", err) + return + } + + fInputCertData, _ := os.ReadFile(fInputCertPath) + fInputKeyData, _ := os.ReadFile(fInputKeyPath) + res, err := deployer.Deploy(context.Background(), string(fInputCertData), string(fInputKeyData)) + if err != nil { + t.Errorf("err: %+v", err) + return + } + + t.Logf("ok: %v", res) + }) +} diff --git a/internal/pkg/core/deployer/providers/cdnfly/consts.go b/internal/pkg/core/deployer/providers/cdnfly/consts.go new file mode 100644 index 00000000..3f6c6db0 --- /dev/null +++ b/internal/pkg/core/deployer/providers/cdnfly/consts.go @@ -0,0 +1,10 @@ +package cdnfly + +type ResourceType string + +const ( + // 资源类型:替换指定网站的证书。 + RESOURCE_TYPE_SITE = ResourceType("site") + // 资源类型:替换指定证书。 + RESOURCE_TYPE_CERTIFICATE = ResourceType("certificate") +) diff --git a/internal/pkg/core/deployer/providers/dogecloud-cdn/dogecloud_cdn.go b/internal/pkg/core/deployer/providers/dogecloud-cdn/dogecloud_cdn.go index 58e79ee8..25aac09d 100644 --- a/internal/pkg/core/deployer/providers/dogecloud-cdn/dogecloud_cdn.go +++ b/internal/pkg/core/deployer/providers/dogecloud-cdn/dogecloud_cdn.go @@ -2,7 +2,6 @@ import ( "context" - "errors" "strconv" xerrors "github.com/pkg/errors" @@ -38,11 +37,11 @@ func New(config *DogeCloudCDNDeployerConfig) (*DogeCloudCDNDeployer, error) { func NewWithLogger(config *DogeCloudCDNDeployerConfig, logger logger.Logger) (*DogeCloudCDNDeployer, error) { if config == nil { - return nil, errors.New("config is nil") + panic("config is nil") } if logger == nil { - return nil, errors.New("logger is nil") + panic("logger is nil") } client := dogesdk.NewClient(config.AccessKey, config.SecretKey) diff --git a/internal/pkg/core/deployer/providers/edgio-applications/edgio_applications.go b/internal/pkg/core/deployer/providers/edgio-applications/edgio_applications.go index 5a6d4bf2..523e33cd 100644 --- a/internal/pkg/core/deployer/providers/edgio-applications/edgio_applications.go +++ b/internal/pkg/core/deployer/providers/edgio-applications/edgio_applications.go @@ -2,7 +2,6 @@ import ( "context" - "errors" xerrors "github.com/pkg/errors" @@ -36,11 +35,11 @@ func New(config *EdgioApplicationsDeployerConfig) (*EdgioApplicationsDeployer, e func NewWithLogger(config *EdgioApplicationsDeployerConfig, logger logger.Logger) (*EdgioApplicationsDeployer, error) { if config == nil { - return nil, errors.New("config is nil") + panic("config is nil") } if logger == nil { - return nil, errors.New("logger is nil") + panic("logger is nil") } client, err := createSdkClient(config.ClientId, config.ClientSecret) diff --git a/internal/pkg/core/deployer/providers/gcore-cdn/gcore_cdn.go b/internal/pkg/core/deployer/providers/gcore-cdn/gcore_cdn.go index 4c20c874..24f00d90 100644 --- a/internal/pkg/core/deployer/providers/gcore-cdn/gcore_cdn.go +++ b/internal/pkg/core/deployer/providers/gcore-cdn/gcore_cdn.go @@ -38,11 +38,11 @@ func New(config *GcoreCDNDeployerConfig) (*GcoreCDNDeployer, error) { func NewWithLogger(config *GcoreCDNDeployerConfig, logger logger.Logger) (*GcoreCDNDeployer, error) { if config == nil { - return nil, errors.New("config is nil") + panic("config is nil") } if logger == nil { - return nil, errors.New("logger is nil") + panic("logger is nil") } client, err := createSdkClient(config.ApiToken) @@ -114,6 +114,10 @@ func (d *GcoreCDNDeployer) Deploy(ctx context.Context, certPem string, privkeyPe } func createSdkClient(apiToken string) (*gresources.Service, error) { + if apiToken == "" { + return nil, errors.New("invalid gcore api token") + } + requester := gprovider.NewClient( gcoresdk.BASE_URL, gprovider.WithSigner(gcoresdk.NewAuthRequestSigner(apiToken)), diff --git a/internal/pkg/core/deployer/providers/huaweicloud-cdn/huaweicloud_cdn.go b/internal/pkg/core/deployer/providers/huaweicloud-cdn/huaweicloud_cdn.go index b4356a0d..20361673 100644 --- a/internal/pkg/core/deployer/providers/huaweicloud-cdn/huaweicloud_cdn.go +++ b/internal/pkg/core/deployer/providers/huaweicloud-cdn/huaweicloud_cdn.go @@ -2,7 +2,6 @@ import ( "context" - "errors" "github.com/huaweicloud/huaweicloud-sdk-go-v3/core/auth/global" hcCdn "github.com/huaweicloud/huaweicloud-sdk-go-v3/services/cdn/v2" @@ -43,11 +42,11 @@ func New(config *HuaweiCloudCDNDeployerConfig) (*HuaweiCloudCDNDeployer, error) func NewWithLogger(config *HuaweiCloudCDNDeployerConfig, logger logger.Logger) (*HuaweiCloudCDNDeployer, error) { if config == nil { - return nil, errors.New("config is nil") + panic("config is nil") } if logger == nil { - return nil, errors.New("logger is nil") + panic("logger is nil") } client, err := createSdkClient( diff --git a/internal/pkg/core/deployer/providers/huaweicloud-elb/huaweicloud_elb.go b/internal/pkg/core/deployer/providers/huaweicloud-elb/huaweicloud_elb.go index f22a07fe..457a8541 100644 --- a/internal/pkg/core/deployer/providers/huaweicloud-elb/huaweicloud_elb.go +++ b/internal/pkg/core/deployer/providers/huaweicloud-elb/huaweicloud_elb.go @@ -58,11 +58,11 @@ func New(config *HuaweiCloudELBDeployerConfig) (*HuaweiCloudELBDeployer, error) func NewWithLogger(config *HuaweiCloudELBDeployerConfig, logger logger.Logger) (*HuaweiCloudELBDeployer, error) { if config == nil { - return nil, errors.New("config is nil") + panic("config is nil") } if logger == nil { - return nil, errors.New("logger is nil") + panic("logger is nil") } client, err := createSdkClient(config.AccessKeyId, config.SecretAccessKey, config.Region) diff --git a/internal/pkg/core/deployer/providers/huaweicloud-waf/huaweicloud_waf.go b/internal/pkg/core/deployer/providers/huaweicloud-waf/huaweicloud_waf.go index 4273d7f7..aa77ba6a 100644 --- a/internal/pkg/core/deployer/providers/huaweicloud-waf/huaweicloud_waf.go +++ b/internal/pkg/core/deployer/providers/huaweicloud-waf/huaweicloud_waf.go @@ -55,11 +55,11 @@ func New(config *HuaweiCloudWAFDeployerConfig) (*HuaweiCloudWAFDeployer, error) func NewWithLogger(config *HuaweiCloudWAFDeployerConfig, logger logger.Logger) (*HuaweiCloudWAFDeployer, error) { if config == nil { - return nil, errors.New("config is nil") + panic("config is nil") } if logger == nil { - return nil, errors.New("logger is nil") + panic("logger is nil") } client, err := createSdkClient(config.AccessKeyId, config.SecretAccessKey, config.Region) diff --git a/internal/pkg/core/deployer/providers/k8s-secret/k8s_secret.go b/internal/pkg/core/deployer/providers/k8s-secret/k8s_secret.go index 2b7ab8fd..22772b58 100644 --- a/internal/pkg/core/deployer/providers/k8s-secret/k8s_secret.go +++ b/internal/pkg/core/deployer/providers/k8s-secret/k8s_secret.go @@ -45,11 +45,11 @@ func New(config *K8sSecretDeployerConfig) (*K8sSecretDeployer, error) { func NewWithLogger(config *K8sSecretDeployerConfig, logger logger.Logger) (*K8sSecretDeployer, error) { if config == nil { - return nil, errors.New("config is nil") + panic("config is nil") } if logger == nil { - return nil, errors.New("logger is nil") + panic("logger is nil") } return &K8sSecretDeployer{ diff --git a/internal/pkg/core/deployer/providers/local/local.go b/internal/pkg/core/deployer/providers/local/local.go index e254caf9..666bb3dd 100644 --- a/internal/pkg/core/deployer/providers/local/local.go +++ b/internal/pkg/core/deployer/providers/local/local.go @@ -3,7 +3,6 @@ package local import ( "bytes" "context" - "errors" "fmt" "os/exec" "runtime" @@ -57,11 +56,11 @@ func New(config *LocalDeployerConfig) (*LocalDeployer, error) { func NewWithLogger(config *LocalDeployerConfig, logger logger.Logger) (*LocalDeployer, error) { if config == nil { - return nil, errors.New("config is nil") + panic("config is nil") } if logger == nil { - return nil, errors.New("logger is nil") + panic("logger is nil") } return &LocalDeployer{ diff --git a/internal/pkg/core/deployer/providers/qiniu-cdn/qiniu_cdn.go b/internal/pkg/core/deployer/providers/qiniu-cdn/qiniu_cdn.go index 098e05aa..49e54b1d 100644 --- a/internal/pkg/core/deployer/providers/qiniu-cdn/qiniu_cdn.go +++ b/internal/pkg/core/deployer/providers/qiniu-cdn/qiniu_cdn.go @@ -2,7 +2,6 @@ import ( "context" - "errors" "strings" xerrors "github.com/pkg/errors" @@ -39,11 +38,11 @@ func New(config *QiniuCDNDeployerConfig) (*QiniuCDNDeployer, error) { func NewWithLogger(config *QiniuCDNDeployerConfig, logger logger.Logger) (*QiniuCDNDeployer, error) { if config == nil { - return nil, errors.New("config is nil") + panic("config is nil") } if logger == nil { - return nil, errors.New("logger is nil") + panic("logger is nil") } client := qiniusdk.NewClient(auth.New(config.AccessKey, config.SecretKey)) diff --git a/internal/pkg/core/deployer/providers/qiniu-pili/qiniu_pili.go b/internal/pkg/core/deployer/providers/qiniu-pili/qiniu_pili.go index 1b34f379..a2e25d4c 100644 --- a/internal/pkg/core/deployer/providers/qiniu-pili/qiniu_pili.go +++ b/internal/pkg/core/deployer/providers/qiniu-pili/qiniu_pili.go @@ -2,7 +2,6 @@ import ( "context" - "errors" xerrors "github.com/pkg/errors" "github.com/qiniu/go-sdk/v7/pili" @@ -39,11 +38,11 @@ func New(config *QiniuPiliDeployerConfig) (*QiniuPiliDeployer, error) { func NewWithLogger(config *QiniuPiliDeployerConfig, logger logger.Logger) (*QiniuPiliDeployer, error) { if config == nil { - return nil, errors.New("config is nil") + panic("config is nil") } if logger == nil { - return nil, errors.New("logger is nil") + panic("logger is nil") } manager := pili.NewManager(pili.ManagerConfig{AccessKey: config.AccessKey, SecretKey: config.SecretKey}) diff --git a/internal/pkg/core/deployer/providers/safeline/safeline.go b/internal/pkg/core/deployer/providers/safeline/safeline.go index d6b37aea..b24f6331 100644 --- a/internal/pkg/core/deployer/providers/safeline/safeline.go +++ b/internal/pkg/core/deployer/providers/safeline/safeline.go @@ -4,6 +4,7 @@ import ( "context" "errors" "fmt" + "net/url" xerrors "github.com/pkg/errors" @@ -38,11 +39,11 @@ func New(config *SafeLineDeployerConfig) (*SafeLineDeployer, error) { func NewWithLogger(config *SafeLineDeployerConfig, logger logger.Logger) (*SafeLineDeployer, error) { if config == nil { - return nil, errors.New("config is nil") + panic("config is nil") } if logger == nil { - return nil, errors.New("logger is nil") + panic("logger is nil") } client, err := createSdkClient(config.ApiUrl, config.ApiToken) @@ -97,6 +98,14 @@ func (d *SafeLineDeployer) deployToCertificate(ctx context.Context, certPem stri } func createSdkClient(apiUrl, apiToken string) (*safelinesdk.Client, error) { + if _, err := url.Parse(apiUrl); err != nil { + return nil, errors.New("invalid safeline api url") + } + + if apiToken == "" { + return nil, errors.New("invalid safeline api token") + } + client := safelinesdk.NewClient(apiUrl, apiToken) return client, nil } diff --git a/internal/pkg/core/deployer/providers/safeline/safeline_test.go b/internal/pkg/core/deployer/providers/safeline/safeline_test.go index 052b0aab..29b5ac3a 100644 --- a/internal/pkg/core/deployer/providers/safeline/safeline_test.go +++ b/internal/pkg/core/deployer/providers/safeline/safeline_test.go @@ -35,8 +35,8 @@ Shell command to run this test: go test -v ./safeline_test.go -args \ --CERTIMATE_DEPLOYER_SAFELINE_INPUTCERTPATH="/path/to/your-input-cert.pem" \ --CERTIMATE_DEPLOYER_SAFELINE_INPUTKEYPATH="/path/to/your-input-key.pem" \ - --CERTIMATE_DEPLOYER_SAFELINE_APIURL="your-safeline-url" \ - --CERTIMATE_DEPLOYER_SAFELINE_APITOKEN="your-safeline-api-token" \ + --CERTIMATE_DEPLOYER_SAFELINE_APIURL="http://127.0.0.1:9443" \ + --CERTIMATE_DEPLOYER_SAFELINE_APITOKEN="your-api-token" \ --CERTIMATE_DEPLOYER_SAFELINE_CERTIFICATEID="your-cerficiate-id" */ func TestDeploy(t *testing.T) { diff --git a/internal/pkg/core/deployer/providers/ssh/ssh.go b/internal/pkg/core/deployer/providers/ssh/ssh.go index 20ea348a..562e6506 100644 --- a/internal/pkg/core/deployer/providers/ssh/ssh.go +++ b/internal/pkg/core/deployer/providers/ssh/ssh.go @@ -3,7 +3,6 @@ package ssh import ( "bytes" "context" - "errors" "fmt" "os" "path/filepath" @@ -72,11 +71,11 @@ func New(config *SshDeployerConfig) (*SshDeployer, error) { func NewWithLogger(config *SshDeployerConfig, logger logger.Logger) (*SshDeployer, error) { if config == nil { - return nil, errors.New("config is nil") + panic("config is nil") } if logger == nil { - return nil, errors.New("logger is nil") + panic("logger is nil") } return &SshDeployer{ diff --git a/internal/pkg/core/deployer/providers/tencentcloud-cdn/tencentcloud_cdn.go b/internal/pkg/core/deployer/providers/tencentcloud-cdn/tencentcloud_cdn.go index 37c982bf..440b78dd 100644 --- a/internal/pkg/core/deployer/providers/tencentcloud-cdn/tencentcloud_cdn.go +++ b/internal/pkg/core/deployer/providers/tencentcloud-cdn/tencentcloud_cdn.go @@ -2,7 +2,6 @@ import ( "context" - "errors" "strings" xerrors "github.com/pkg/errors" @@ -47,11 +46,11 @@ func New(config *TencentCloudCDNDeployerConfig) (*TencentCloudCDNDeployer, error func NewWithLogger(config *TencentCloudCDNDeployerConfig, logger logger.Logger) (*TencentCloudCDNDeployer, error) { if config == nil { - return nil, errors.New("config is nil") + panic("config is nil") } if logger == nil { - return nil, errors.New("logger is nil") + panic("logger is nil") } clients, err := createSdkClients(config.SecretId, config.SecretKey) diff --git a/internal/pkg/core/deployer/providers/tencentcloud-clb/tencentcloud_clb.go b/internal/pkg/core/deployer/providers/tencentcloud-clb/tencentcloud_clb.go index 0f5532bc..28307f74 100644 --- a/internal/pkg/core/deployer/providers/tencentcloud-clb/tencentcloud_clb.go +++ b/internal/pkg/core/deployer/providers/tencentcloud-clb/tencentcloud_clb.go @@ -57,11 +57,11 @@ func New(config *TencentCloudCLBDeployerConfig) (*TencentCloudCLBDeployer, error func NewWithLogger(config *TencentCloudCLBDeployerConfig, logger logger.Logger) (*TencentCloudCLBDeployer, error) { if config == nil { - return nil, errors.New("config is nil") + panic("config is nil") } if logger == nil { - return nil, errors.New("logger is nil") + panic("logger is nil") } clients, err := createSdkClients(config.SecretId, config.SecretKey, config.Region) diff --git a/internal/pkg/core/deployer/providers/tencentcloud-cos/tencentcloud_cos.go b/internal/pkg/core/deployer/providers/tencentcloud-cos/tencentcloud_cos.go index 0efc2e7a..72653dcd 100644 --- a/internal/pkg/core/deployer/providers/tencentcloud-cos/tencentcloud_cos.go +++ b/internal/pkg/core/deployer/providers/tencentcloud-cos/tencentcloud_cos.go @@ -44,11 +44,11 @@ func New(config *TencentCloudCOSDeployerConfig) (*TencentCloudCOSDeployer, error func NewWithLogger(config *TencentCloudCOSDeployerConfig, logger logger.Logger) (*TencentCloudCOSDeployer, error) { if config == nil { - return nil, errors.New("config is nil") + panic("config is nil") } if logger == nil { - return nil, errors.New("logger is nil") + panic("logger is nil") } client, err := createSdkClient(config.SecretId, config.SecretKey, config.Region) diff --git a/internal/pkg/core/deployer/providers/tencentcloud-css/tencentcloud_css.go b/internal/pkg/core/deployer/providers/tencentcloud-css/tencentcloud_css.go index 85f92780..205649e5 100644 --- a/internal/pkg/core/deployer/providers/tencentcloud-css/tencentcloud_css.go +++ b/internal/pkg/core/deployer/providers/tencentcloud-css/tencentcloud_css.go @@ -2,7 +2,6 @@ import ( "context" - "errors" xerrors "github.com/pkg/errors" "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common" @@ -39,11 +38,11 @@ func New(config *TencentCloudCSSDeployerConfig) (*TencentCloudCSSDeployer, error func NewWithLogger(config *TencentCloudCSSDeployerConfig, logger logger.Logger) (*TencentCloudCSSDeployer, error) { if config == nil { - return nil, errors.New("config is nil") + panic("config is nil") } if logger == nil { - return nil, errors.New("logger is nil") + panic("logger is nil") } client, err := createSdkClient(config.SecretId, config.SecretKey) diff --git a/internal/pkg/core/deployer/providers/tencentcloud-ecdn/tencentcloud_ecdn.go b/internal/pkg/core/deployer/providers/tencentcloud-ecdn/tencentcloud_ecdn.go index 803c48f7..47349a73 100644 --- a/internal/pkg/core/deployer/providers/tencentcloud-ecdn/tencentcloud_ecdn.go +++ b/internal/pkg/core/deployer/providers/tencentcloud-ecdn/tencentcloud_ecdn.go @@ -2,7 +2,6 @@ import ( "context" - "errors" "strings" xerrors "github.com/pkg/errors" @@ -46,11 +45,11 @@ func New(config *TencentCloudECDNDeployerConfig) (*TencentCloudECDNDeployer, err func NewWithLogger(config *TencentCloudECDNDeployerConfig, logger logger.Logger) (*TencentCloudECDNDeployer, error) { if config == nil { - return nil, errors.New("config is nil") + panic("config is nil") } if logger == nil { - return nil, errors.New("logger is nil") + panic("logger is nil") } clients, err := createSdkClients(config.SecretId, config.SecretKey) diff --git a/internal/pkg/core/deployer/providers/tencentcloud-eo/tencentcloud_eo.go b/internal/pkg/core/deployer/providers/tencentcloud-eo/tencentcloud_eo.go index 9c183fec..90129cc4 100644 --- a/internal/pkg/core/deployer/providers/tencentcloud-eo/tencentcloud_eo.go +++ b/internal/pkg/core/deployer/providers/tencentcloud-eo/tencentcloud_eo.go @@ -47,11 +47,11 @@ func New(config *TencentCloudEODeployerConfig) (*TencentCloudEODeployer, error) func NewWithLogger(config *TencentCloudEODeployerConfig, logger logger.Logger) (*TencentCloudEODeployer, error) { if config == nil { - return nil, errors.New("config is nil") + panic("config is nil") } if logger == nil { - return nil, errors.New("logger is nil") + panic("logger is nil") } clients, err := createSdkClients(config.SecretId, config.SecretKey) diff --git a/internal/pkg/core/deployer/providers/tencentcloud-ssl-deploy/tencentcloud_ssl_deploy.go b/internal/pkg/core/deployer/providers/tencentcloud-ssl-deploy/tencentcloud_ssl_deploy.go index aea9d4a4..bab0c627 100644 --- a/internal/pkg/core/deployer/providers/tencentcloud-ssl-deploy/tencentcloud_ssl_deploy.go +++ b/internal/pkg/core/deployer/providers/tencentcloud-ssl-deploy/tencentcloud_ssl_deploy.go @@ -45,11 +45,11 @@ func New(config *TencentCloudSSLDeployDeployerConfig) (*TencentCloudSSLDeployDep func NewWithLogger(config *TencentCloudSSLDeployDeployerConfig, logger logger.Logger) (*TencentCloudSSLDeployDeployer, error) { if config == nil { - return nil, errors.New("config is nil") + panic("config is nil") } if logger == nil { - return nil, errors.New("logger is nil") + panic("logger is nil") } client, err := createSdkClient(config.SecretId, config.SecretKey, config.Region) diff --git a/internal/pkg/core/deployer/providers/tencentcloud-waf/tencentcloud_waf.go b/internal/pkg/core/deployer/providers/tencentcloud-waf/tencentcloud_waf.go index 4482d1f9..631750eb 100644 --- a/internal/pkg/core/deployer/providers/tencentcloud-waf/tencentcloud_waf.go +++ b/internal/pkg/core/deployer/providers/tencentcloud-waf/tencentcloud_waf.go @@ -45,11 +45,11 @@ func New(config *TencentCloudWAFDeployerConfig) (*TencentCloudWAFDeployer, error func NewWithLogger(config *TencentCloudWAFDeployerConfig, logger logger.Logger) (*TencentCloudWAFDeployer, error) { if config == nil { - return nil, errors.New("config is nil") + panic("config is nil") } if logger == nil { - return nil, errors.New("logger is nil") + panic("logger is nil") } client, err := createSdkClient(config.SecretId, config.SecretKey, config.Region) diff --git a/internal/pkg/core/deployer/providers/ucloud-ucdn/ucloud_ucdn.go b/internal/pkg/core/deployer/providers/ucloud-ucdn/ucloud_ucdn.go index 3fdfd611..4cb373ab 100644 --- a/internal/pkg/core/deployer/providers/ucloud-ucdn/ucloud_ucdn.go +++ b/internal/pkg/core/deployer/providers/ucloud-ucdn/ucloud_ucdn.go @@ -42,11 +42,11 @@ func New(config *UCloudUCDNDeployerConfig) (*UCloudUCDNDeployer, error) { func NewWithLogger(config *UCloudUCDNDeployerConfig, logger logger.Logger) (*UCloudUCDNDeployer, error) { if config == nil { - return nil, errors.New("config is nil") + panic("config is nil") } if logger == nil { - return nil, errors.New("logger is nil") + panic("logger is nil") } client, err := createSdkClient(config.PrivateKey, config.PublicKey) diff --git a/internal/pkg/core/deployer/providers/ucloud-us3/ucloud_us3.go b/internal/pkg/core/deployer/providers/ucloud-us3/ucloud_us3.go index 93a3792c..c7787a31 100644 --- a/internal/pkg/core/deployer/providers/ucloud-us3/ucloud_us3.go +++ b/internal/pkg/core/deployer/providers/ucloud-us3/ucloud_us3.go @@ -2,7 +2,6 @@ import ( "context" - "errors" xerrors "github.com/pkg/errors" usdk "github.com/ucloud/ucloud-sdk-go/ucloud" @@ -45,11 +44,11 @@ func New(config *UCloudUS3DeployerConfig) (*UCloudUS3Deployer, error) { func NewWithLogger(config *UCloudUS3DeployerConfig, logger logger.Logger) (*UCloudUS3Deployer, error) { if config == nil { - return nil, errors.New("config is nil") + panic("config is nil") } if logger == nil { - return nil, errors.New("logger is nil") + panic("logger is nil") } client, err := createSdkClient(config.PrivateKey, config.PublicKey, config.Region) diff --git a/internal/pkg/core/deployer/providers/volcengine-cdn/volcengine_cdn.go b/internal/pkg/core/deployer/providers/volcengine-cdn/volcengine_cdn.go index f2ddd753..dc631669 100644 --- a/internal/pkg/core/deployer/providers/volcengine-cdn/volcengine_cdn.go +++ b/internal/pkg/core/deployer/providers/volcengine-cdn/volcengine_cdn.go @@ -39,11 +39,11 @@ func New(config *VolcEngineCDNDeployerConfig) (*VolcEngineCDNDeployer, error) { func NewWithLogger(config *VolcEngineCDNDeployerConfig, logger logger.Logger) (*VolcEngineCDNDeployer, error) { if config == nil { - return nil, errors.New("config is nil") + panic("config is nil") } if logger == nil { - return nil, errors.New("logger is nil") + panic("logger is nil") } client := veCdn.NewInstance() diff --git a/internal/pkg/core/deployer/providers/volcengine-clb/volcengine_clb.go b/internal/pkg/core/deployer/providers/volcengine-clb/volcengine_clb.go index 55311db9..b06b0142 100644 --- a/internal/pkg/core/deployer/providers/volcengine-clb/volcengine_clb.go +++ b/internal/pkg/core/deployer/providers/volcengine-clb/volcengine_clb.go @@ -45,11 +45,11 @@ func New(config *VolcEngineCLBDeployerConfig) (*VolcEngineCLBDeployer, error) { func NewWithLogger(config *VolcEngineCLBDeployerConfig, logger logger.Logger) (*VolcEngineCLBDeployer, error) { if config == nil { - return nil, errors.New("config is nil") + panic("config is nil") } if logger == nil { - return nil, errors.New("logger is nil") + panic("logger is nil") } client, err := createSdkClient(config.AccessKeyId, config.AccessKeySecret, config.Region) diff --git a/internal/pkg/core/deployer/providers/volcengine-dcdn/volcengine_dcdn.go b/internal/pkg/core/deployer/providers/volcengine-dcdn/volcengine_dcdn.go index 67686fa8..9e7aa896 100644 --- a/internal/pkg/core/deployer/providers/volcengine-dcdn/volcengine_dcdn.go +++ b/internal/pkg/core/deployer/providers/volcengine-dcdn/volcengine_dcdn.go @@ -2,7 +2,6 @@ import ( "context" - "errors" "strings" xerrors "github.com/pkg/errors" @@ -42,11 +41,11 @@ func New(config *VolcEngineDCDNDeployerConfig) (*VolcEngineDCDNDeployer, error) func NewWithLogger(config *VolcEngineDCDNDeployerConfig, logger logger.Logger) (*VolcEngineDCDNDeployer, error) { if config == nil { - return nil, errors.New("config is nil") + panic("config is nil") } if logger == nil { - return nil, errors.New("logger is nil") + panic("logger is nil") } client, err := createSdkClient(config.AccessKeyId, config.AccessKeySecret, config.Region) diff --git a/internal/pkg/core/deployer/providers/volcengine-imagex/volcengine_imagex.go b/internal/pkg/core/deployer/providers/volcengine-imagex/volcengine_imagex.go index 1d174261..d02a6d1e 100644 --- a/internal/pkg/core/deployer/providers/volcengine-imagex/volcengine_imagex.go +++ b/internal/pkg/core/deployer/providers/volcengine-imagex/volcengine_imagex.go @@ -42,11 +42,11 @@ func New(config *VolcEngineImageXDeployerConfig) (*VolcEngineImageXDeployer, err func NewWithLogger(config *VolcEngineImageXDeployerConfig, logger logger.Logger) (*VolcEngineImageXDeployer, error) { if config == nil { - return nil, errors.New("config is nil") + panic("config is nil") } if logger == nil { - return nil, errors.New("logger is nil") + panic("logger is nil") } client, err := createSdkClient(config.AccessKeyId, config.AccessKeySecret, config.Region) diff --git a/internal/pkg/core/deployer/providers/volcengine-live/volcengine_live.go b/internal/pkg/core/deployer/providers/volcengine-live/volcengine_live.go index 580d6ae1..fa9e357a 100644 --- a/internal/pkg/core/deployer/providers/volcengine-live/volcengine_live.go +++ b/internal/pkg/core/deployer/providers/volcengine-live/volcengine_live.go @@ -40,11 +40,11 @@ func New(config *VolcEngineLiveDeployerConfig) (*VolcEngineLiveDeployer, error) func NewWithLogger(config *VolcEngineLiveDeployerConfig, logger logger.Logger) (*VolcEngineLiveDeployer, error) { if config == nil { - return nil, errors.New("config is nil") + panic("config is nil") } if logger == nil { - return nil, errors.New("logger is nil") + panic("logger is nil") } client := veLive.NewInstance() diff --git a/internal/pkg/core/deployer/providers/volcengine-tos/volcengine_tos.go b/internal/pkg/core/deployer/providers/volcengine-tos/volcengine_tos.go index 19c97fc7..273c92d4 100644 --- a/internal/pkg/core/deployer/providers/volcengine-tos/volcengine_tos.go +++ b/internal/pkg/core/deployer/providers/volcengine-tos/volcengine_tos.go @@ -42,11 +42,11 @@ func New(config *VolcEngineTOSDeployerConfig) (*VolcEngineTOSDeployer, error) { func NewWithLogger(config *VolcEngineTOSDeployerConfig, logger logger.Logger) (*VolcEngineTOSDeployer, error) { if config == nil { - return nil, errors.New("config is nil") + panic("config is nil") } if logger == nil { - return nil, errors.New("logger is nil") + panic("logger is nil") } client, err := createSdkClient(config.AccessKeyId, config.AccessKeySecret, config.Region) diff --git a/internal/pkg/core/deployer/providers/webhook/webhook.go b/internal/pkg/core/deployer/providers/webhook/webhook.go index 694befc5..cd6e941a 100644 --- a/internal/pkg/core/deployer/providers/webhook/webhook.go +++ b/internal/pkg/core/deployer/providers/webhook/webhook.go @@ -3,7 +3,6 @@ package webhook import ( "context" "encoding/json" - "errors" "strings" "time" @@ -36,11 +35,11 @@ func New(config *WebhookDeployerConfig) (*WebhookDeployer, error) { func NewWithLogger(config *WebhookDeployerConfig, logger logger.Logger) (*WebhookDeployer, error) { if config == nil { - return nil, errors.New("config is nil") + panic("config is nil") } if logger == nil { - return nil, errors.New("logger is nil") + panic("logger is nil") } client := resty.New(). diff --git a/internal/pkg/core/notifier/providers/bark/bark.go b/internal/pkg/core/notifier/providers/bark/bark.go index 74683f82..731e0a96 100644 --- a/internal/pkg/core/notifier/providers/bark/bark.go +++ b/internal/pkg/core/notifier/providers/bark/bark.go @@ -2,7 +2,6 @@ import ( "context" - "errors" "github.com/nikoksr/notify" "github.com/nikoksr/notify/service/bark" @@ -26,7 +25,7 @@ var _ notifier.Notifier = (*BarkNotifier)(nil) func New(config *BarkNotifierConfig) (*BarkNotifier, error) { if config == nil { - return nil, errors.New("config is nil") + panic("config is nil") } return &BarkNotifier{ diff --git a/internal/pkg/core/notifier/providers/dingtalk/dingtalk.go b/internal/pkg/core/notifier/providers/dingtalk/dingtalk.go index 52fe5f27..469d5e65 100644 --- a/internal/pkg/core/notifier/providers/dingtalk/dingtalk.go +++ b/internal/pkg/core/notifier/providers/dingtalk/dingtalk.go @@ -2,7 +2,6 @@ import ( "context" - "errors" "github.com/nikoksr/notify/service/dingding" @@ -24,7 +23,7 @@ var _ notifier.Notifier = (*DingTalkNotifier)(nil) func New(config *DingTalkNotifierConfig) (*DingTalkNotifier, error) { if config == nil { - return nil, errors.New("config is nil") + panic("config is nil") } return &DingTalkNotifier{ diff --git a/internal/pkg/core/notifier/providers/email/email.go b/internal/pkg/core/notifier/providers/email/email.go index 127c5528..2619188f 100644 --- a/internal/pkg/core/notifier/providers/email/email.go +++ b/internal/pkg/core/notifier/providers/email/email.go @@ -3,7 +3,6 @@ import ( "context" "crypto/tls" - "errors" "fmt" "net/smtp" @@ -38,7 +37,7 @@ var _ notifier.Notifier = (*EmailNotifier)(nil) func New(config *EmailNotifierConfig) (*EmailNotifier, error) { if config == nil { - return nil, errors.New("config is nil") + panic("config is nil") } return &EmailNotifier{ diff --git a/internal/pkg/core/notifier/providers/lark/lark.go b/internal/pkg/core/notifier/providers/lark/lark.go index 4714e280..b726fa1c 100644 --- a/internal/pkg/core/notifier/providers/lark/lark.go +++ b/internal/pkg/core/notifier/providers/lark/lark.go @@ -2,7 +2,6 @@ import ( "context" - "errors" "github.com/nikoksr/notify/service/lark" @@ -22,7 +21,7 @@ var _ notifier.Notifier = (*LarkNotifier)(nil) func New(config *LarkNotifierConfig) (*LarkNotifier, error) { if config == nil { - return nil, errors.New("config is nil") + panic("config is nil") } return &LarkNotifier{ diff --git a/internal/pkg/core/notifier/providers/serverchan/serverchan.go b/internal/pkg/core/notifier/providers/serverchan/serverchan.go index 7b5a6de0..1811c49e 100644 --- a/internal/pkg/core/notifier/providers/serverchan/serverchan.go +++ b/internal/pkg/core/notifier/providers/serverchan/serverchan.go @@ -2,7 +2,6 @@ import ( "context" - "errors" "net/http" notifyHttp "github.com/nikoksr/notify/service/http" @@ -23,7 +22,7 @@ var _ notifier.Notifier = (*ServerChanNotifier)(nil) func New(config *ServerChanNotifierConfig) (*ServerChanNotifier, error) { if config == nil { - return nil, errors.New("config is nil") + panic("config is nil") } return &ServerChanNotifier{ diff --git a/internal/pkg/core/notifier/providers/telegram/telegram.go b/internal/pkg/core/notifier/providers/telegram/telegram.go index d1dcc45f..ce86c881 100644 --- a/internal/pkg/core/notifier/providers/telegram/telegram.go +++ b/internal/pkg/core/notifier/providers/telegram/telegram.go @@ -2,7 +2,6 @@ import ( "context" - "errors" "github.com/nikoksr/notify/service/telegram" @@ -24,7 +23,7 @@ var _ notifier.Notifier = (*TelegramNotifier)(nil) func New(config *TelegramNotifierConfig) (*TelegramNotifier, error) { if config == nil { - return nil, errors.New("config is nil") + panic("config is nil") } return &TelegramNotifier{ diff --git a/internal/pkg/core/notifier/providers/webhook/webhook.go b/internal/pkg/core/notifier/providers/webhook/webhook.go index 3c2bc05f..66dd806b 100644 --- a/internal/pkg/core/notifier/providers/webhook/webhook.go +++ b/internal/pkg/core/notifier/providers/webhook/webhook.go @@ -2,7 +2,6 @@ import ( "context" - "errors" "github.com/nikoksr/notify/service/http" @@ -22,7 +21,7 @@ var _ notifier.Notifier = (*WebhookNotifier)(nil) func New(config *WebhookNotifierConfig) (*WebhookNotifier, error) { if config == nil { - return nil, errors.New("config is nil") + panic("config is nil") } return &WebhookNotifier{ diff --git a/internal/pkg/core/notifier/providers/wecom/wecom.go b/internal/pkg/core/notifier/providers/wecom/wecom.go index 20938009..7731a1b5 100644 --- a/internal/pkg/core/notifier/providers/wecom/wecom.go +++ b/internal/pkg/core/notifier/providers/wecom/wecom.go @@ -2,7 +2,6 @@ import ( "context" - "errors" "net/http" notifyHttp "github.com/nikoksr/notify/service/http" @@ -23,7 +22,7 @@ var _ notifier.Notifier = (*WeComNotifier)(nil) func New(config *WeComNotifierConfig) (*WeComNotifier, error) { if config == nil { - return nil, errors.New("config is nil") + panic("config is nil") } return &WeComNotifier{ diff --git a/internal/pkg/core/uploader/providers/aliyun-cas/aliyun_cas.go b/internal/pkg/core/uploader/providers/aliyun-cas/aliyun_cas.go index 3259bdb1..881dc57b 100644 --- a/internal/pkg/core/uploader/providers/aliyun-cas/aliyun_cas.go +++ b/internal/pkg/core/uploader/providers/aliyun-cas/aliyun_cas.go @@ -2,7 +2,6 @@ import ( "context" - "errors" "fmt" "strings" "time" @@ -34,7 +33,7 @@ var _ uploader.Uploader = (*AliyunCASUploader)(nil) func New(config *AliyunCASUploaderConfig) (*AliyunCASUploader, error) { if config == nil { - return nil, errors.New("config is nil") + panic("config is nil") } client, err := createSdkClient( diff --git a/internal/pkg/core/uploader/providers/aliyun-slb/aliyun_slb.go b/internal/pkg/core/uploader/providers/aliyun-slb/aliyun_slb.go index 63779b48..9bd6d930 100644 --- a/internal/pkg/core/uploader/providers/aliyun-slb/aliyun_slb.go +++ b/internal/pkg/core/uploader/providers/aliyun-slb/aliyun_slb.go @@ -4,7 +4,6 @@ import ( "context" "crypto/sha256" "encoding/hex" - "errors" "fmt" "regexp" "strings" @@ -37,7 +36,7 @@ var _ uploader.Uploader = (*AliyunSLBUploader)(nil) func New(config *AliyunSLBUploaderConfig) (*AliyunSLBUploader, error) { if config == nil { - return nil, errors.New("config is nil") + panic("config is nil") } client, err := createSdkClient( diff --git a/internal/pkg/core/uploader/providers/aws-acm/aws_acm.go b/internal/pkg/core/uploader/providers/aws-acm/aws_acm.go index cac4d833..836bacfc 100644 --- a/internal/pkg/core/uploader/providers/aws-acm/aws_acm.go +++ b/internal/pkg/core/uploader/providers/aws-acm/aws_acm.go @@ -2,7 +2,6 @@ import ( "context" - "errors" "fmt" "time" @@ -34,7 +33,7 @@ var _ uploader.Uploader = (*AWSCertificateManagerUploader)(nil) func New(config *AWSCertificateManagerUploaderConfig) (*AWSCertificateManagerUploader, error) { if config == nil { - return nil, errors.New("config is nil") + panic("config is nil") } client, err := createSdkClient(config.AccessKeyId, config.SecretAccessKey, config.Region) diff --git a/internal/pkg/core/uploader/providers/byteplus-cdn/byteplus_cdn.go b/internal/pkg/core/uploader/providers/byteplus-cdn/byteplus_cdn.go index f1bf2b46..bed962e2 100644 --- a/internal/pkg/core/uploader/providers/byteplus-cdn/byteplus_cdn.go +++ b/internal/pkg/core/uploader/providers/byteplus-cdn/byteplus_cdn.go @@ -5,7 +5,6 @@ import ( "crypto/sha1" "crypto/sha256" "encoding/hex" - "errors" "fmt" "strings" "time" @@ -33,7 +32,7 @@ var _ uploader.Uploader = (*ByteplusCDNUploader)(nil) func New(config *ByteplusCDNUploaderConfig) (*ByteplusCDNUploader, error) { if config == nil { - return nil, errors.New("config is nil") + panic("config is nil") } client := bpCdn.NewInstance() diff --git a/internal/pkg/core/uploader/providers/dogecloud/dogecloud.go b/internal/pkg/core/uploader/providers/dogecloud/dogecloud.go index a38e832c..c941a5a9 100644 --- a/internal/pkg/core/uploader/providers/dogecloud/dogecloud.go +++ b/internal/pkg/core/uploader/providers/dogecloud/dogecloud.go @@ -2,7 +2,6 @@ import ( "context" - "errors" "fmt" "time" @@ -28,7 +27,7 @@ var _ uploader.Uploader = (*DogeCloudUploader)(nil) func New(config *DogeCloudUploaderConfig) (*DogeCloudUploader, error) { if config == nil { - return nil, errors.New("config is nil") + panic("config is nil") } client, err := createSdkClient( diff --git a/internal/pkg/core/uploader/providers/gcore-cdn/gcore_cdn.go b/internal/pkg/core/uploader/providers/gcore-cdn/gcore_cdn.go index 32cadb62..933f61b4 100644 --- a/internal/pkg/core/uploader/providers/gcore-cdn/gcore_cdn.go +++ b/internal/pkg/core/uploader/providers/gcore-cdn/gcore_cdn.go @@ -28,7 +28,7 @@ var _ uploader.Uploader = (*GcoreCDNUploader)(nil) func New(config *GcoreCDNUploaderConfig) (*GcoreCDNUploader, error) { if config == nil { - return nil, errors.New("config is nil") + panic("config is nil") } client, err := createSdkClient(config.ApiToken) @@ -70,6 +70,10 @@ func (u *GcoreCDNUploader) Upload(ctx context.Context, certPem string, privkeyPe } func createSdkClient(apiToken string) (*gsslcerts.Service, error) { + if apiToken == "" { + return nil, errors.New("invalid gcore api token") + } + requester := gprovider.NewClient( gcoresdk.BASE_URL, gprovider.WithSigner(gcoresdk.NewAuthRequestSigner(apiToken)), diff --git a/internal/pkg/core/uploader/providers/huaweicloud-elb/huaweicloud_elb.go b/internal/pkg/core/uploader/providers/huaweicloud-elb/huaweicloud_elb.go index 2ea7d031..321c488f 100644 --- a/internal/pkg/core/uploader/providers/huaweicloud-elb/huaweicloud_elb.go +++ b/internal/pkg/core/uploader/providers/huaweicloud-elb/huaweicloud_elb.go @@ -39,7 +39,7 @@ var _ uploader.Uploader = (*HuaweiCloudELBUploader)(nil) func New(config *HuaweiCloudELBUploaderConfig) (*HuaweiCloudELBUploader, error) { if config == nil { - return nil, errors.New("config is nil") + panic("config is nil") } client, err := createSdkClient( diff --git a/internal/pkg/core/uploader/providers/huaweicloud-scm/huaweicloud_scm.go b/internal/pkg/core/uploader/providers/huaweicloud-scm/huaweicloud_scm.go index c0618da0..53f723f4 100644 --- a/internal/pkg/core/uploader/providers/huaweicloud-scm/huaweicloud_scm.go +++ b/internal/pkg/core/uploader/providers/huaweicloud-scm/huaweicloud_scm.go @@ -2,7 +2,6 @@ import ( "context" - "errors" "fmt" "time" @@ -35,7 +34,7 @@ var _ uploader.Uploader = (*HuaweiCloudSCMUploader)(nil) func New(config *HuaweiCloudSCMUploaderConfig) (*HuaweiCloudSCMUploader, error) { if config == nil { - return nil, errors.New("config is nil") + panic("config is nil") } client, err := createSdkClient( diff --git a/internal/pkg/core/uploader/providers/huaweicloud-waf/huaweicloud_waf.go b/internal/pkg/core/uploader/providers/huaweicloud-waf/huaweicloud_waf.go index eb2eb7f2..3fb89bf3 100644 --- a/internal/pkg/core/uploader/providers/huaweicloud-waf/huaweicloud_waf.go +++ b/internal/pkg/core/uploader/providers/huaweicloud-waf/huaweicloud_waf.go @@ -39,7 +39,7 @@ var _ uploader.Uploader = (*HuaweiCloudWAFUploader)(nil) func New(config *HuaweiCloudWAFUploaderConfig) (*HuaweiCloudWAFUploader, error) { if config == nil { - return nil, errors.New("config is nil") + panic("config is nil") } client, err := createSdkClient( diff --git a/internal/pkg/core/uploader/providers/qiniu-sslcert/qiniu_sslcert.go b/internal/pkg/core/uploader/providers/qiniu-sslcert/qiniu_sslcert.go index 851cbf01..3e32b73d 100644 --- a/internal/pkg/core/uploader/providers/qiniu-sslcert/qiniu_sslcert.go +++ b/internal/pkg/core/uploader/providers/qiniu-sslcert/qiniu_sslcert.go @@ -2,7 +2,6 @@ import ( "context" - "errors" "fmt" "time" @@ -30,7 +29,7 @@ var _ uploader.Uploader = (*QiniuSSLCertUploader)(nil) func New(config *QiniuSSLCertUploaderConfig) (*QiniuSSLCertUploader, error) { if config == nil { - return nil, errors.New("config is nil") + panic("config is nil") } client, err := createSdkClient( diff --git a/internal/pkg/core/uploader/providers/tencentcloud-ssl/tencentcloud_ssl.go b/internal/pkg/core/uploader/providers/tencentcloud-ssl/tencentcloud_ssl.go index a94af000..c802e77f 100644 --- a/internal/pkg/core/uploader/providers/tencentcloud-ssl/tencentcloud_ssl.go +++ b/internal/pkg/core/uploader/providers/tencentcloud-ssl/tencentcloud_ssl.go @@ -2,7 +2,6 @@ import ( "context" - "errors" xerrors "github.com/pkg/errors" "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common" @@ -28,7 +27,7 @@ var _ uploader.Uploader = (*TencentCloudSSLUploader)(nil) func New(config *TencentCloudSSLUploaderConfig) (*TencentCloudSSLUploader, error) { if config == nil { - return nil, errors.New("config is nil") + panic("config is nil") } client, err := createSdkClient( diff --git a/internal/pkg/core/uploader/providers/ucloud-ussl/ucloud_ussl.go b/internal/pkg/core/uploader/providers/ucloud-ussl/ucloud_ussl.go index 9c5fa2b3..56a66472 100644 --- a/internal/pkg/core/uploader/providers/ucloud-ussl/ucloud_ussl.go +++ b/internal/pkg/core/uploader/providers/ucloud-ussl/ucloud_ussl.go @@ -38,7 +38,7 @@ var _ uploader.Uploader = (*UCloudUSSLUploader)(nil) func New(config *UCloudUSSLUploaderConfig) (*UCloudUSSLUploader, error) { if config == nil { - return nil, errors.New("config is nil") + panic("config is nil") } client, err := createSdkClient(config.PrivateKey, config.PublicKey) diff --git a/internal/pkg/core/uploader/providers/volcengine-cdn/volcengine_cdn.go b/internal/pkg/core/uploader/providers/volcengine-cdn/volcengine_cdn.go index 23f05281..691effe6 100644 --- a/internal/pkg/core/uploader/providers/volcengine-cdn/volcengine_cdn.go +++ b/internal/pkg/core/uploader/providers/volcengine-cdn/volcengine_cdn.go @@ -5,7 +5,6 @@ import ( "crypto/sha1" "crypto/sha256" "encoding/hex" - "errors" "fmt" "strings" "time" @@ -34,7 +33,7 @@ var _ uploader.Uploader = (*VolcEngineCDNUploader)(nil) func New(config *VolcEngineCDNUploaderConfig) (*VolcEngineCDNUploader, error) { if config == nil { - return nil, errors.New("config is nil") + panic("config is nil") } client := veCdn.NewInstance() diff --git a/internal/pkg/core/uploader/providers/volcengine-certcenter/volcengine_certcenter.go b/internal/pkg/core/uploader/providers/volcengine-certcenter/volcengine_certcenter.go index 5e301ebd..05776396 100644 --- a/internal/pkg/core/uploader/providers/volcengine-certcenter/volcengine_certcenter.go +++ b/internal/pkg/core/uploader/providers/volcengine-certcenter/volcengine_certcenter.go @@ -2,7 +2,6 @@ package volcenginecertcenter import ( "context" - "errors" xerrors "github.com/pkg/errors" ve "github.com/volcengine/volcengine-go-sdk/volcengine" @@ -30,7 +29,7 @@ var _ uploader.Uploader = (*VolcEngineCertCenterUploader)(nil) func New(config *VolcEngineCertCenterUploaderConfig) (*VolcEngineCertCenterUploader, error) { if config == nil { - return nil, errors.New("config is nil") + panic("config is nil") } client, err := createSdkClient(config.AccessKeyId, config.AccessKeySecret, config.Region) diff --git a/internal/pkg/core/uploader/providers/volcengine-live/volcengine_live.go b/internal/pkg/core/uploader/providers/volcengine-live/volcengine_live.go index c7861cb6..ce85186f 100644 --- a/internal/pkg/core/uploader/providers/volcengine-live/volcengine_live.go +++ b/internal/pkg/core/uploader/providers/volcengine-live/volcengine_live.go @@ -2,7 +2,6 @@ package volcenginelive import ( "context" - "errors" "fmt" "strings" "time" @@ -31,7 +30,7 @@ var _ uploader.Uploader = (*VolcEngineLiveUploader)(nil) func New(config *VolcEngineLiveUploaderConfig) (*VolcEngineLiveUploader, error) { if config == nil { - return nil, errors.New("config is nil") + panic("config is nil") } client := veLive.NewInstance() diff --git a/internal/pkg/vendors/baishan-sdk/client.go b/internal/pkg/vendors/baishan-sdk/client.go index c49698ea..d30dd05f 100644 --- a/internal/pkg/vendors/baishan-sdk/client.go +++ b/internal/pkg/vendors/baishan-sdk/client.go @@ -30,11 +30,9 @@ func (c *Client) WithTimeout(timeout time.Duration) *Client { } func (c *Client) sendRequest(method string, path string, params map[string]any) (*resty.Response, error) { - url := "https://cdn.api.baishan.com" + path - req := c.client.R() req.Method = method - req.URL = url + req.URL = "https://cdn.api.baishan.com" + path if strings.EqualFold(method, http.MethodGet) { data := make(map[string]string) for k, v := range params { @@ -68,8 +66,8 @@ func (c *Client) sendRequestWithResult(method string, path string, params map[st if err := json.Unmarshal(resp.Body(), &result); err != nil { return fmt.Errorf("baishan api error: failed to parse response: %w", err) - } else if result.GetCode() != 0 { - return fmt.Errorf("baishan api error: %d - %s", result.GetCode(), result.GetMessage()) + } else if errcode := result.GetCode(); errcode != 0 { + return fmt.Errorf("baishan api error: %d - %s", errcode, result.GetMessage()) } return nil diff --git a/internal/pkg/vendors/btpanel-sdk/client.go b/internal/pkg/vendors/btpanel-sdk/client.go index 0620a80f..8134feca 100644 --- a/internal/pkg/vendors/btpanel-sdk/client.go +++ b/internal/pkg/vendors/btpanel-sdk/client.go @@ -14,14 +14,15 @@ import ( type Client struct { apiHost string apiKey string - client *resty.Client + + client *resty.Client } func NewClient(apiHost, apiKey string) *Client { client := resty.New() return &Client{ - apiHost: apiHost, + apiHost: strings.TrimRight(apiHost, "/"), apiKey: apiKey, client: client, } @@ -50,7 +51,7 @@ func (c *Client) sendRequest(path string, params map[string]any) (*resty.Respons params["request_time"] = timestamp params["request_token"] = c.generateSignature(fmt.Sprintf("%d", timestamp)) - url := strings.TrimRight(c.apiHost, "/") + path + url := c.apiHost + path req := c.client.R(). SetHeader("Content-Type", "application/json"). SetBody(params) @@ -72,7 +73,7 @@ func (c *Client) sendRequestWithResult(path string, params map[string]any, resul if err := json.Unmarshal(resp.Body(), &result); err != nil { return fmt.Errorf("baota api error: failed to parse response: %w", err) - } else if result.GetStatus() != nil && !*result.GetStatus() { + } else if errstatus := result.GetStatus(); errstatus != nil && !*errstatus { if result.GetMsg() == nil { return fmt.Errorf("baota api error: unknown error") } else { diff --git a/internal/pkg/vendors/cachefly-sdk/client.go b/internal/pkg/vendors/cachefly-sdk/client.go index 2516a388..6f6a4790 100644 --- a/internal/pkg/vendors/cachefly-sdk/client.go +++ b/internal/pkg/vendors/cachefly-sdk/client.go @@ -30,11 +30,9 @@ func (c *Client) WithTimeout(timeout time.Duration) *Client { } func (c *Client) sendRequest(method string, path string, params map[string]any) (*resty.Response, error) { - url := "https://api.cachefly.com/api/2.5" + path - req := c.client.R() req.Method = method - req.URL = url + req.URL = "https://api.cachefly.com/api/2.5" + path req = req.SetHeader("x-cf-authorization", "Bearer "+c.apiToken) if strings.EqualFold(method, http.MethodGet) { data := make(map[string]string) diff --git a/internal/pkg/vendors/cdnfly-sdk/api.go b/internal/pkg/vendors/cdnfly-sdk/api.go new file mode 100644 index 00000000..5f8ebb0a --- /dev/null +++ b/internal/pkg/vendors/cdnfly-sdk/api.go @@ -0,0 +1,59 @@ +package cdnflysdk + +import ( + "encoding/json" + "fmt" + "net/http" +) + +func (c *Client) GetSite(req *GetSiteRequest) (*GetSiteResponse, error) { + params := make(map[string]any) + jsonData, _ := json.Marshal(req) + json.Unmarshal(jsonData, ¶ms) + + result := GetSiteResponse{} + err := c.sendRequestWithResult(http.MethodGet, fmt.Sprintf("/v1/sites/%s", req.Id), params, &result) + if err != nil { + return nil, err + } + return &result, nil +} + +func (c *Client) UpdateSite(req *UpdateSiteRequest) (*UpdateSiteResponse, error) { + params := make(map[string]any) + jsonData, _ := json.Marshal(req) + json.Unmarshal(jsonData, ¶ms) + + result := UpdateSiteResponse{} + err := c.sendRequestWithResult(http.MethodPut, fmt.Sprintf("/v1/sites/%s", req.Id), params, &result) + if err != nil { + return nil, err + } + return &result, nil +} + +func (c *Client) CreateCertificate(req *CreateCertificateRequest) (*CreateCertificateResponse, error) { + params := make(map[string]any) + jsonData, _ := json.Marshal(req) + json.Unmarshal(jsonData, ¶ms) + + result := CreateCertificateResponse{} + err := c.sendRequestWithResult(http.MethodPost, "/v1/certs", params, &result) + if err != nil { + return nil, err + } + return &result, nil +} + +func (c *Client) UpdateCertificate(req *UpdateCertificateRequest) (*UpdateCertificateResponse, error) { + params := make(map[string]any) + jsonData, _ := json.Marshal(req) + json.Unmarshal(jsonData, ¶ms) + + result := UpdateCertificateResponse{} + err := c.sendRequestWithResult(http.MethodPut, fmt.Sprintf("/v1/certs/%s", req.Id), params, &result) + if err != nil { + return nil, err + } + return &result, nil +} diff --git a/internal/pkg/vendors/cdnfly-sdk/client.go b/internal/pkg/vendors/cdnfly-sdk/client.go new file mode 100644 index 00000000..910020b3 --- /dev/null +++ b/internal/pkg/vendors/cdnfly-sdk/client.go @@ -0,0 +1,79 @@ +package cdnflysdk + +import ( + "encoding/json" + "fmt" + "net/http" + "strings" + "time" + + "github.com/go-resty/resty/v2" +) + +type Client struct { + apiHost string + apiKey string + apiSecret string + + client *resty.Client +} + +func NewClient(apiHost, apiKey, apiSecret string) *Client { + client := resty.New() + + return &Client{ + apiHost: strings.TrimRight(apiHost, "/"), + apiKey: apiKey, + apiSecret: apiSecret, + client: client, + } +} + +func (c *Client) WithTimeout(timeout time.Duration) *Client { + c.client.SetTimeout(timeout) + return c +} + +func (c *Client) sendRequest(method string, path string, params map[string]any) (*resty.Response, error) { + req := c.client.R() + req.Method = method + req.URL = c.apiHost + path + req = req. + SetHeader("api-key", c.apiKey). + SetHeader("api-secret", c.apiSecret) + if strings.EqualFold(method, http.MethodGet) { + data := make(map[string]string) + for k, v := range params { + data[k] = fmt.Sprintf("%v", v) + } + req = req.SetQueryParams(data) + } else { + req = req. + SetHeader("Content-Type", "application/json"). + SetBody(params) + } + + resp, err := req.Send() + if err != nil { + return nil, fmt.Errorf("cdnfly api error: failed to send request: %w", err) + } else if resp.IsError() { + return nil, fmt.Errorf("cdnfly api error: unexpected status code: %d, %s", resp.StatusCode(), resp.Body()) + } + + return resp, nil +} + +func (c *Client) sendRequestWithResult(method string, path string, params map[string]any, result BaseResponse) error { + resp, err := c.sendRequest(method, path, params) + if err != nil { + return err + } + + if err := json.Unmarshal(resp.Body(), &result); err != nil { + return fmt.Errorf("cdnfly api error: failed to parse response: %w", err) + } else if errcode := result.GetCode(); errcode != "" && errcode != "0" { + return fmt.Errorf("cdnfly api error: %s - %s", errcode, result.GetMessage()) + } + + return nil +} diff --git a/internal/pkg/vendors/cdnfly-sdk/models.go b/internal/pkg/vendors/cdnfly-sdk/models.go new file mode 100644 index 00000000..873b80b0 --- /dev/null +++ b/internal/pkg/vendors/cdnfly-sdk/models.go @@ -0,0 +1,70 @@ +package cdnflysdk + +type BaseResponse interface { + GetCode() string + GetMessage() string +} + +type baseResponse struct { + Code string `json:"code"` + Message string `json:"msg"` +} + +func (r *baseResponse) GetCode() string { + return r.Code +} + +func (r *baseResponse) GetMessage() string { + return r.Message +} + +type GetSiteRequest struct { + Id string `json:"-"` +} + +type GetSiteResponse struct { + baseResponse + Data *struct { + Id string `json:"id"` + Name string `json:"name"` + Domain string `json:"domain"` + HttpsListen string `json:"https_listen"` + } `json:"data"` +} + +type UpdateSiteRequest struct { + Id string `json:"-"` + HttpsListen *string `json:"https_listen,omitempty"` + Enable *bool `json:"enable,omitempty"` +} + +type UpdateSiteResponse struct { + baseResponse +} + +type CreateCertificateRequest struct { + Name string `json:"name"` + Description *string `json:"des,omitempty"` + Type string `json:"type"` + Cert string `json:"cert"` + Key string `json:"key"` +} + +type CreateCertificateResponse struct { + baseResponse + Data string `json:"data"` +} + +type UpdateCertificateRequest struct { + Id string `json:"-"` + Name *string `json:"name,omitempty"` + Description *string `json:"des,omitempty"` + Type *string `json:"type,omitempty"` + Cert *string `json:"cert,omitempty"` + Key *string `json:"key,omitempty"` + Enable *bool `json:"enable,omitempty"` +} + +type UpdateCertificateResponse struct { + baseResponse +} diff --git a/internal/pkg/vendors/gname-sdk/client.go b/internal/pkg/vendors/gname-sdk/client.go index 5d9ffa3f..d3b9fb86 100644 --- a/internal/pkg/vendors/gname-sdk/client.go +++ b/internal/pkg/vendors/gname-sdk/client.go @@ -15,6 +15,7 @@ import ( type Client struct { appId string appKey string + client *resty.Client } @@ -92,8 +93,8 @@ func (c *Client) sendRequestWithResult(path string, params map[string]any, resul if err := json.Unmarshal(resp.Body(), &result); err != nil { return fmt.Errorf("gname api error: failed to parse response: %w", err) - } else if result.GetCode() != 1 { - return fmt.Errorf("gname api error: %d - %s", result.GetCode(), result.GetMsg()) + } else if errcode := result.GetCode(); errcode != 1 { + return fmt.Errorf("gname api error: %d - %s", errcode, result.GetMsg()) } return nil diff --git a/internal/pkg/vendors/safeline-sdk/client.go b/internal/pkg/vendors/safeline-sdk/client.go index dbf54f66..5aa19c07 100644 --- a/internal/pkg/vendors/safeline-sdk/client.go +++ b/internal/pkg/vendors/safeline-sdk/client.go @@ -12,14 +12,15 @@ import ( type Client struct { apiHost string apiToken string - client *resty.Client + + client *resty.Client } func NewClient(apiHost, apiToken string) *Client { client := resty.New() return &Client{ - apiHost: apiHost, + apiHost: strings.TrimRight(apiHost, "/"), apiToken: apiToken, client: client, } @@ -35,7 +36,7 @@ func (c *Client) sendRequest(path string, params map[string]any) (*resty.Respons params = make(map[string]any) } - url := strings.TrimRight(c.apiHost, "/") + path + url := c.apiHost + path req := c.client.R(). SetHeader("Content-Type", "application/json"). SetHeader("X-SLCE-API-TOKEN", c.apiToken). @@ -58,11 +59,11 @@ func (c *Client) sendRequestWithResult(path string, params map[string]any, resul if err := json.Unmarshal(resp.Body(), &result); err != nil { return fmt.Errorf("safeline api error: failed to parse response: %w", err) - } else if result.GetErrCode() != nil && *result.GetErrCode() != "" { + } else if errcode := result.GetErrCode(); errcode != nil && *errcode != "" { if result.GetErrMsg() == nil { - return fmt.Errorf("safeline api error: %s", *result.GetErrCode()) + return fmt.Errorf("safeline api error: %s", *errcode) } else { - return fmt.Errorf("safeline api error: %s - %s", *result.GetErrCode(), *result.GetErrMsg()) + return fmt.Errorf("safeline api error: %s - %s", *errcode, *result.GetErrMsg()) } } diff --git a/ui/public/imgs/providers/cdnfly.png b/ui/public/imgs/providers/cdnfly.png new file mode 100644 index 0000000000000000000000000000000000000000..3a8d984347d4daa824134e32fecc4c9780bdf365 GIT binary patch literal 1086 zcmV-E1i|}>P)Px&_(?=TRA@u(n_EcJQ5?s=N9QiOIn!BrDajPNScXzY7qAOaQ5f0HdhJ395 ziBv`0Cm`9J!b!>Q7#SJealCq`g-~a;aY9oV!}^oaF>J$XQgPtHDG;GlDn;S&oDiHO z6-D=(0J16^fFv0NG?I#<+93dX$>8t^a8O_&JXnIGP=JHW6TeZ4!~A*|oN~qC;PS+8 zl;SYI-UX*zaX7d<@f)Q$%+foZQG*4m<{)L632~`<=wj7~(yHKb`rsUJqyK{qU)!xP zzqVp*l+70Zzc{SYL?U-jCKhj=5BgcEIS1Wnt?5G7Qws!Pdcm0k$0TU6f%A*Ak+C*e)G%ZnMr}!x z_%78bcy>WLewrQVY2n1-S*dyyUS2QOMd<=`_k07a-M^$*Cq1X&+Z+2{2t@ca^LeUzu$l+&WRuO26!JnE>2eFqudFQe%N~;%@WhQr zcVjQ=%ffu)@z2)sLIbQHWo|7a2!t_?j)xnHv$1gE;o;&-4E4Jtry+?T$l0BNfgU?& z$3vY;+<+L9#*c??yBE!so#=XIp89wgL6DX^8##rUh@WrZ?|4Wd^(Gy*oX$mjnjzpU zE$MuJKL~rj3m%6LTD=-ECM}YeCO{Jt6^MIur42o;oE#4)&f6$$BywnpXH#$`9$E=$ zsq6$@?54XhTcxKGDi-nb=88_zMU9qo)X^%@WyhZ)-j~)sSl$dw`#IRJ=f46^w_Bl% zrvQhNHJB~ji)|}!#ueaiq;wF@QnF`xB%E^ z-W7oIqS})LC=2ELz*`^jl81OfD-MkSR`3QOQ*VcH#E}=csHIXx-V0;szZbRqS*qGw zrM5@uj|yWr1R`F=(({ className, return ; case ACCESS_PROVIDERS.CACHEFLY: return ; + case ACCESS_PROVIDERS.CDNFLY: + return ; case ACCESS_PROVIDERS.CLOUDFLARE: return ; case ACCESS_PROVIDERS.CLOUDNS: diff --git a/ui/src/components/access/AccessFormCdnflyConfig.tsx b/ui/src/components/access/AccessFormCdnflyConfig.tsx new file mode 100644 index 00000000..a9dd1139 --- /dev/null +++ b/ui/src/components/access/AccessFormCdnflyConfig.tsx @@ -0,0 +1,87 @@ +import { useTranslation } from "react-i18next"; +import { Form, type FormInstance, Input } from "antd"; +import { createSchemaFieldRule } from "antd-zod"; +import { z } from "zod"; + +import { type AccessConfigForCdnfly } from "@/domain/access"; + +type AccessFormCdnflyConfigFieldValues = Nullish; + +export type AccessFormCdnflyConfigProps = { + form: FormInstance; + formName: string; + disabled?: boolean; + initialValues?: AccessFormCdnflyConfigFieldValues; + onValuesChange?: (values: AccessFormCdnflyConfigFieldValues) => void; +}; + +const initFormModel = (): AccessFormCdnflyConfigFieldValues => { + return { + apiUrl: "http://:88/", + apiKey: "", + apiSecret: "", + }; +}; + +const AccessFormCdnflyConfig = ({ form: formInst, formName, disabled, initialValues, onValuesChange }: AccessFormCdnflyConfigProps) => { + const { t } = useTranslation(); + + const formSchema = z.object({ + apiUrl: z.string().url(t("common.errmsg.url_invalid")), + apiKey: z + .string() + .min(1, t("access.form.cdnfly_api_key.placeholder")) + .max(64, t("common.errmsg.string_max", { max: 64 })) + .trim(), + apiSecret: z + .string() + .min(1, t("access.form.cdnfly_api_secret.placeholder")) + .max(64, t("common.errmsg.string_max", { max: 64 })) + .trim(), + }); + const formRule = createSchemaFieldRule(formSchema); + + const handleFormChange = (_: unknown, values: z.infer) => { + onValuesChange?.(values); + }; + + return ( +
+ } + > + + + + } + > + + + + } + > + + +
+ ); +}; + +export default AccessFormCdnflyConfig; diff --git a/ui/src/components/workflow/node/DeployNodeConfigForm.tsx b/ui/src/components/workflow/node/DeployNodeConfigForm.tsx index 9b992914..4706e330 100644 --- a/ui/src/components/workflow/node/DeployNodeConfigForm.tsx +++ b/ui/src/components/workflow/node/DeployNodeConfigForm.tsx @@ -31,6 +31,7 @@ import DeployNodeConfigFormBaishanCDNConfig from "./DeployNodeConfigFormBaishanC import DeployNodeConfigFormBaotaPanelConsoleConfig from "./DeployNodeConfigFormBaotaPanelConsoleConfig"; import DeployNodeConfigFormBaotaPanelSiteConfig from "./DeployNodeConfigFormBaotaPanelSiteConfig"; import DeployNodeConfigFormBytePlusCDNConfig from "./DeployNodeConfigFormBytePlusCDNConfig"; +import DeployNodeConfigFormCdnflyConfig from "./DeployNodeConfigFormCdnflyConfig"; import DeployNodeConfigFormDogeCloudCDNConfig from "./DeployNodeConfigFormDogeCloudCDNConfig"; import DeployNodeConfigFormEdgioApplicationsConfig from "./DeployNodeConfigFormEdgioApplicationsConfig"; import DeployNodeConfigFormGcoreCDNConfig from "./DeployNodeConfigFormGcoreCDNConfig"; @@ -163,6 +164,8 @@ const DeployNodeConfigForm = forwardRef; case DEPLOY_PROVIDERS.BYTEPLUS_CDN: return ; + case DEPLOY_PROVIDERS.CDNFLY: + return ; case DEPLOY_PROVIDERS.DOGECLOUD_CDN: return ; case DEPLOY_PROVIDERS.EDGIO_APPLICATIONS: @@ -297,7 +300,7 @@ const DeployNodeConfigForm = forwardRef ; export type DeployNodeConfigFormAliyunESAConfigProps = { @@ -34,10 +34,9 @@ const DeployNodeConfigFormAliyunESAConfig = ({ .string({ message: t("workflow_node.deploy.form.aliyun_esa_region.placeholder") }) .nonempty(t("workflow_node.deploy.form.aliyun_esa_region.placeholder")) .trim(), - siteId: z - .string({ message: t("workflow_node.deploy.form.aliyun_esa_site_id.placeholder") }) - .regex(/^[1-9]\d*$/, t("workflow_node.deploy.form.aliyun_esa_site_id.placeholder")) - .trim(), + siteId: z.union([z.string(), z.number()]).refine((v) => { + return /^\d+$/.test(v + "") && +v > 0; + }, t("workflow_node.deploy.form.aliyun_esa_site_id.placeholder")), }); const formRule = createSchemaFieldRule(formSchema); @@ -69,7 +68,7 @@ const DeployNodeConfigFormAliyunESAConfig = ({ rules={[formRule]} tooltip={} > - +
); diff --git a/ui/src/components/workflow/node/DeployNodeConfigFormCdnflyConfig.tsx b/ui/src/components/workflow/node/DeployNodeConfigFormCdnflyConfig.tsx new file mode 100644 index 00000000..c9f61e02 --- /dev/null +++ b/ui/src/components/workflow/node/DeployNodeConfigFormCdnflyConfig.tsx @@ -0,0 +1,89 @@ +import { useTranslation } from "react-i18next"; +import { Form, type FormInstance, Input, Select } from "antd"; +import { createSchemaFieldRule } from "antd-zod"; +import { z } from "zod"; + +import Show from "@/components/Show"; + +type DeployNodeConfigFormCdnflyConfigFieldValues = Nullish<{ + resourceType: string; + certificateId?: string | number; +}>; + +export type DeployNodeConfigFormCdnflyConfigProps = { + form: FormInstance; + formName: string; + disabled?: boolean; + initialValues?: DeployNodeConfigFormCdnflyConfigFieldValues; + onValuesChange?: (values: DeployNodeConfigFormCdnflyConfigFieldValues) => void; +}; + +const RESOURCE_TYPE_SITE = "site" as const; +const RESOURCE_TYPE_CERTIFICATE = "certificate" as const; + +const initFormModel = (): DeployNodeConfigFormCdnflyConfigFieldValues => { + return { + resourceType: RESOURCE_TYPE_SITE, + }; +}; + +const DeployNodeConfigFormCdnflyConfig = ({ form: formInst, formName, disabled, initialValues, onValuesChange }: DeployNodeConfigFormCdnflyConfigProps) => { + const { t } = useTranslation(); + + const formSchema = z.object({ + resourceType: z.union([z.literal(RESOURCE_TYPE_SITE), z.literal(RESOURCE_TYPE_CERTIFICATE)], { + message: t("workflow_node.deploy.form.cdnfly_resource_type.placeholder"), + }), + siteId: z.union([z.string(), z.number().int()]).refine((v) => { + if (fieldResourceType !== RESOURCE_TYPE_SITE) return true; + return /^\d+$/.test(v + "") && +v > 0; + }, t("workflow_node.deploy.form.cdnfly_site_id.placeholder")), + certificateId: z.union([z.string(), z.number().int()]).refine((v) => { + if (fieldResourceType !== RESOURCE_TYPE_CERTIFICATE) return true; + return /^\d+$/.test(v + "") && +v > 0; + }, t("workflow_node.deploy.form.cdnfly_certificate_id.placeholder")), + }); + const formRule = createSchemaFieldRule(formSchema); + + const fieldResourceType = Form.useWatch("resourceType", formInst); + + const handleFormChange = (_: unknown, values: z.infer) => { + onValuesChange?.(values); + }; + + return ( +
+ + + + + + + + + + + + + + + +
+ ); +}; + +export default DeployNodeConfigFormCdnflyConfig; diff --git a/ui/src/components/workflow/node/DeployNodeConfigFormGcoreCDNConfig.tsx b/ui/src/components/workflow/node/DeployNodeConfigFormGcoreCDNConfig.tsx index 84d5e410..00dc48dd 100644 --- a/ui/src/components/workflow/node/DeployNodeConfigFormGcoreCDNConfig.tsx +++ b/ui/src/components/workflow/node/DeployNodeConfigFormGcoreCDNConfig.tsx @@ -4,7 +4,7 @@ import { createSchemaFieldRule } from "antd-zod"; import { z } from "zod"; type DeployNodeConfigFormGcoreCDNConfigFieldValues = Nullish<{ - resourceId?: string; + resourceId?: string | number; }>; export type DeployNodeConfigFormGcoreCDNConfigProps = { @@ -25,9 +25,9 @@ const DeployNodeConfigFormGcoreCDNConfig = ({ form: formInst, formName, disabled const { t } = useTranslation(); const formSchema = z.object({ - resourceId: z - .string({ message: t("workflow_node.deploy.form.gcore_cdn_certificate_id.placeholder") }) - .regex(/^\d+$/, t("workflow_node.deploy.form.gcore_cdn_certificate_id.placeholder")), + resourceId: z.union([z.string(), z.number()]).refine((v) => { + return /^\d+$/.test(v + "") && +v > 0; + }, t("workflow_node.deploy.form.gcore_cdn_certificate_id.placeholder")), }); const formRule = createSchemaFieldRule(formSchema); @@ -50,7 +50,7 @@ const DeployNodeConfigFormGcoreCDNConfig = ({ form: formInst, formName, disabled rules={[formRule]} tooltip={} > - + ); diff --git a/ui/src/components/workflow/node/DeployNodeConfigFormSafeLineConfig.tsx b/ui/src/components/workflow/node/DeployNodeConfigFormSafeLineConfig.tsx index d17681cf..239a6c92 100644 --- a/ui/src/components/workflow/node/DeployNodeConfigFormSafeLineConfig.tsx +++ b/ui/src/components/workflow/node/DeployNodeConfigFormSafeLineConfig.tsx @@ -7,7 +7,7 @@ import Show from "@/components/Show"; type DeployNodeConfigFormSafeLineConfigFieldValues = Nullish<{ resourceType: string; - certificateId?: string; + certificateId?: string | number; }>; export type DeployNodeConfigFormSafeLineConfigProps = { @@ -34,19 +34,10 @@ const DeployNodeConfigFormSafeLineConfig = ({ form: formInst, formName, disabled resourceType: z.literal(RESOURCE_TYPE_CERTIFICATE, { message: t("workflow_node.deploy.form.safeline_resource_type.placeholder"), }), - region: z - .string({ message: t("workflow_node.deploy.form.safeline_region.placeholder") }) - .nonempty(t("workflow_node.deploy.form.safeline_region.placeholder")) - .trim(), - certificateId: z - .string() - .max(64, t("common.errmsg.string_max", { max: 64 })) - .trim() - .nullish() - .refine((v) => { - if (fieldResourceType !== RESOURCE_TYPE_CERTIFICATE) return true; - return /^\d+$/.test(v!); - }, t("workflow_node.deploy.form.safeline_certificate_id.placeholder")), + certificateId: z.union([z.string(), z.number().int()]).refine((v) => { + if (fieldResourceType !== RESOURCE_TYPE_CERTIFICATE) return true; + return /^\d+$/.test(v + "") && +v > 0; + }, t("workflow_node.deploy.form.safeline_certificate_id.placeholder")), }); const formRule = createSchemaFieldRule(formSchema); @@ -75,7 +66,7 @@ const DeployNodeConfigFormSafeLineConfig = ({ form: formInst, formName, disabled - + diff --git a/ui/src/domain/access.ts b/ui/src/domain/access.ts index c4132f60..0ece4826 100644 --- a/ui/src/domain/access.ts +++ b/ui/src/domain/access.ts @@ -15,6 +15,7 @@ export interface AccessModel extends BaseModel { | AccessConfigForBaotaPanel | AccessConfigForBytePlus | AccessConfigForCacheFly + | AccessConfigForCdnfly | AccessConfigForCloudflare | AccessConfigForClouDNS | AccessConfigForDogeCloud @@ -88,6 +89,12 @@ export type AccessConfigForCacheFly = { apiToken: string; }; +export type AccessConfigForCdnfly = { + apiUrl: string; + apiKey: string; + apiSecret: string; +}; + export type AccessConfigForCloudflare = { dnsApiToken: string; }; diff --git a/ui/src/domain/provider.ts b/ui/src/domain/provider.ts index f58299da..ed14db23 100644 --- a/ui/src/domain/provider.ts +++ b/ui/src/domain/provider.ts @@ -13,6 +13,7 @@ export const ACCESS_PROVIDERS = Object.freeze({ BAOTAPANEL: "baotapanel", BYTEPLUS: "byteplus", CACHEFLY: "cachefly", + CDNFLY: "cdnfly", CLOUDFLARE: "cloudflare", CLOUDNS: "cloudns", DOGECLOUD: "dogecloud", @@ -79,6 +80,7 @@ export const accessProvidersMap: Maphttps://kb.cachefly.com/kb/guide/en/generating-tokens-and-keys-Oll9Irt5TI/Steps/2460228", + "access.form.cdnfly_api_url.label": "Cdnfly API URL", + "access.form.cdnfly_api_url.placeholder": "Please enter Cdnfly API URL", + "access.form.cdnfly_api_url.tooltip": "For more information, see https://doc.cdnfly.cn/anzhuangshuoming.html", + "access.form.cdnfly_api_key.label": "Cdnfly user API key", + "access.form.cdnfly_api_key.placeholder": "Please enter Cdnfly user API key", + "access.form.cdnfly_api_key.tooltip": "For more information, see https://doc.cdnfly.cn/shiyongjieshao.html", + "access.form.cdnfly_api_secret.label": "Cdnfly user API secret", + "access.form.cdnfly_api_secret.placeholder": "Please enter Cdnfly user API secret", + "access.form.cdnfly_api_secret.tooltip": "For more information, see https://doc.cdnfly.cn/shiyongjieshao.html", "access.form.cloudflare_dns_api_token.label": "Cloudflare API token", "access.form.cloudflare_dns_api_token.placeholder": "Please enter Cloudflare API token", "access.form.cloudflare_dns_api_token.tooltip": "For more information, see https://developers.cloudflare.com/fundamentals/api/get-started/create-token/", diff --git a/ui/src/i18n/locales/en/nls.workflow.nodes.json b/ui/src/i18n/locales/en/nls.workflow.nodes.json index e6a59086..ae79074f 100644 --- a/ui/src/i18n/locales/en/nls.workflow.nodes.json +++ b/ui/src/i18n/locales/en/nls.workflow.nodes.json @@ -200,6 +200,14 @@ "workflow_node.deploy.form.byteplus_cdn_domain.label": "BytePlus CDN domain", "workflow_node.deploy.form.byteplus_cdn_domain.placeholder": "Please enter BytePlus CDN domain name", "workflow_node.deploy.form.byteplus_cdn_domain.tooltip": "For more information, see https://console.byteplus.com/cdn", + "workflow_node.deploy.form.cdnfly_resource_type.label": "Resource type", + "workflow_node.deploy.form.cdnfly_resource_type.placeholder": "Please select resource type", + "workflow_node.deploy.form.cdnfly_resource_type.option.site.label": "Site", + "workflow_node.deploy.form.cdnfly_resource_type.option.certificate.label": "Certificate", + "workflow_node.deploy.form.cdnfly_site_id.label": "Cdnfly site ID", + "workflow_node.deploy.form.cdnfly_site_id.placeholder": "Please enter Cdnfly site ID", + "workflow_node.deploy.form.cdnfly_certificate_id.label": "Cdnfly certificate ID", + "workflow_node.deploy.form.cdnfly_certificate_id.placeholder": "Please enter Cdnfly certificate ID", "workflow_node.deploy.form.dogecloud_cdn_domain.label": "Doge Cloud CDN domain", "workflow_node.deploy.form.dogecloud_cdn_domain.placeholder": "Please enter Doge Cloud CDN domain name", "workflow_node.deploy.form.dogecloud_cdn_domain.tooltip": "For more information, see https://console.dogecloud.com/", diff --git a/ui/src/i18n/locales/zh/nls.access.json b/ui/src/i18n/locales/zh/nls.access.json index bb366764..ee7fea3a 100644 --- a/ui/src/i18n/locales/zh/nls.access.json +++ b/ui/src/i18n/locales/zh/nls.access.json @@ -82,6 +82,15 @@ "access.form.cachefly_api_token.label": "CacheFly API Token", "access.form.cachefly_api_token.placeholder": "请输入 CacheFly API Token", "access.form.cachefly_api_token.tooltip": "这是什么?请参阅 https://kb.cachefly.com/kb/guide/en/generating-tokens-and-keys-Oll9Irt5TI/Steps/2460228", + "access.form.cdnfly_api_url.label": "Cdnfly API URL", + "access.form.cdnfly_api_url.placeholder": "请输入 Cdnfly API URL", + "access.form.cdnfly_api_url.tooltip": "这是什么?请参阅 https://doc.cdnfly.cn/anzhuangshuoming.html", + "access.form.cdnfly_api_key.label": "Cdnfly 用户端 API Key", + "access.form.cdnfly_api_key.placeholder": "请输入 Cdnfly 用户端 API Key", + "access.form.cdnfly_api_key.tooltip": "这是什么?请参阅 https://doc.cdnfly.cn/shiyongjieshao.html", + "access.form.cdnfly_api_secret.label": "Cdnfly 用户端 API Secret", + "access.form.cdnfly_api_secret.placeholder": "请输入 Cdnfly 用户端 API Secret", + "access.form.cdnfly_api_secret.tooltip": "这是什么?请参阅 https://doc.cdnfly.cn/shiyongjieshao.html", "access.form.cloudflare_dns_api_token.label": "Cloudflare API Token", "access.form.cloudflare_dns_api_token.placeholder": "请输入 Cloudflare API Token", "access.form.cloudflare_dns_api_token.tooltip": "这是什么?请参阅 https://developers.cloudflare.com/fundamentals/api/get-started/create-token/", diff --git a/ui/src/i18n/locales/zh/nls.workflow.nodes.json b/ui/src/i18n/locales/zh/nls.workflow.nodes.json index 5335d5aa..ad886a02 100644 --- a/ui/src/i18n/locales/zh/nls.workflow.nodes.json +++ b/ui/src/i18n/locales/zh/nls.workflow.nodes.json @@ -200,6 +200,14 @@ "workflow_node.deploy.form.byteplus_cdn_domain.label": "BytePlus CDN 域名(支持泛域名)", "workflow_node.deploy.form.byteplus_cdn_domain.placeholder": "请输入 BytePlus CDN 域名", "workflow_node.deploy.form.byteplus_cdn_domain.tooltip": "这是什么?请参阅 https://console.byteplus.com/cdn", + "workflow_node.deploy.form.cdnfly_resource_type.label": "证书替换方式", + "workflow_node.deploy.form.cdnfly_resource_type.placeholder": "请选择证书替换方式", + "workflow_node.deploy.form.cdnfly_resource_type.option.site.label": "替换指定网站的证书", + "workflow_node.deploy.form.cdnfly_resource_type.option.certificate.label": "替换指定证书", + "workflow_node.deploy.form.cdnfly_site_id.label": "Cdnfly 网站 ID", + "workflow_node.deploy.form.cdnfly_site_id.placeholder": "请输入 Cdnfly 网站 ID", + "workflow_node.deploy.form.cdnfly_certificate_id.label": "Cdnfly 证书 ID", + "workflow_node.deploy.form.cdnfly_certificate_id.placeholder": "请输入 Cdnfly 证书 ID", "workflow_node.deploy.form.dogecloud_cdn_domain.label": "多吉云 CDN 加速域名", "workflow_node.deploy.form.dogecloud_cdn_domain.placeholder": "请输入多吉云 CDN 加速域名", "workflow_node.deploy.form.dogecloud_cdn_domain.tooltip": "这是什么?请参阅 https://console.dogecloud.com", diff --git a/ui/src/vite-env.d.ts b/ui/types/vite-env.d.ts similarity index 100% rename from ui/src/vite-env.d.ts rename to ui/types/vite-env.d.ts From c451bf5e030770c3f052ccb186977678b916b1bc Mon Sep 17 00:00:00 2001 From: Fu Diwei Date: Tue, 18 Feb 2025 16:14:54 +0800 Subject: [PATCH 13/34] feat: support multiple sites on deployment to baotapanel site --- internal/deployer/providers.go | 8 +- .../baotapanel-site/baotapanel_site.go | 83 ++++++++-- .../baotapanel-site/baotapanel_site_test.go | 4 + internal/pkg/vendors/btpanel-sdk/api.go | 26 +++ internal/pkg/vendors/btpanel-sdk/client.go | 4 +- internal/pkg/vendors/btpanel-sdk/models.go | 37 ++++- .../workflow/node/ApplyNodeConfigForm.tsx | 1 + ...loyNodeConfigFormAliyunCASDeployConfig.tsx | 1 + ...ployNodeConfigFormBaotaPanelSiteConfig.tsx | 148 ++++++++++++++++-- ...eConfigFormTencentCloudSSLDeployConfig.tsx | 1 + .../i18n/locales/en/nls.workflow.nodes.json | 10 ++ .../i18n/locales/zh/nls.workflow.nodes.json | 10 ++ 12 files changed, 293 insertions(+), 40 deletions(-) diff --git a/internal/deployer/providers.go b/internal/deployer/providers.go index 9b2bd4f7..34e3ef0c 100644 --- a/internal/deployer/providers.go +++ b/internal/deployer/providers.go @@ -258,9 +258,11 @@ func createDeployer(options *deployerOptions) (deployer.Deployer, logger.Logger, case domain.DeployProviderTypeBaotaPanelSite: deployer, err := pBaotaPanelSite.NewWithLogger(&pBaotaPanelSite.BaotaPanelSiteDeployerConfig{ - ApiUrl: access.ApiUrl, - ApiKey: access.ApiKey, - SiteName: maps.GetValueAsString(options.ProviderDeployConfig, "siteName"), + ApiUrl: access.ApiUrl, + ApiKey: access.ApiKey, + SiteType: maps.GetValueOrDefaultAsString(options.ProviderDeployConfig, "siteType", "other"), + SiteName: maps.GetValueAsString(options.ProviderDeployConfig, "siteName"), + SiteNames: slices.Filter(strings.Split(maps.GetValueAsString(options.ProviderDeployConfig, "siteNames"), ";"), func(s string) bool { return s != "" }), }, logger) return deployer, logger, err diff --git a/internal/pkg/core/deployer/providers/baotapanel-site/baotapanel_site.go b/internal/pkg/core/deployer/providers/baotapanel-site/baotapanel_site.go index 6fffa670..01cabdde 100644 --- a/internal/pkg/core/deployer/providers/baotapanel-site/baotapanel_site.go +++ b/internal/pkg/core/deployer/providers/baotapanel-site/baotapanel_site.go @@ -3,12 +3,14 @@ import ( "context" "errors" + "fmt" "net/url" xerrors "github.com/pkg/errors" "github.com/usual2970/certimate/internal/pkg/core/deployer" "github.com/usual2970/certimate/internal/pkg/core/logger" + "github.com/usual2970/certimate/internal/pkg/utils/slices" btsdk "github.com/usual2970/certimate/internal/pkg/vendors/btpanel-sdk" ) @@ -17,8 +19,12 @@ type BaotaPanelSiteDeployerConfig struct { ApiUrl string `json:"apiUrl"` // 宝塔面板接口密钥。 ApiKey string `json:"apiKey"` - // 站点名称。 - SiteName string `json:"siteName"` + // 站点类型。 + SiteType string `json:"siteType"` + // 站点名称(单个)。 + SiteName string `json:"siteName,omitempty"` + // 站点名称(多个)。 + SiteNames []string `json:"siteNames,omitempty"` } type BaotaPanelSiteDeployer struct { @@ -55,22 +61,65 @@ func NewWithLogger(config *BaotaPanelSiteDeployerConfig, logger logger.Logger) ( } func (d *BaotaPanelSiteDeployer) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { - if d.config.SiteName == "" { - return nil, errors.New("config `siteName` is required") - } + switch d.config.SiteType { + case "php": + { + if d.config.SiteName == "" { + return nil, errors.New("config `siteName` is required") + } - // 设置站点 SSL 证书 - siteSetSSLReq := &btsdk.SiteSetSSLRequest{ - SiteName: d.config.SiteName, - Type: "0", - PrivateKey: privkeyPem, - Certificate: certPem, - } - siteSetSSLResp, err := d.sdkClient.SiteSetSSL(siteSetSSLReq) - if err != nil { - return nil, xerrors.Wrap(err, "failed to execute sdk request 'bt.SiteSetSSL'") - } else { - d.logger.Logt("已设置站点 SSL 证书", siteSetSSLResp) + // 设置站点 SSL 证书 + siteSetSSLReq := &btsdk.SiteSetSSLRequest{ + SiteName: d.config.SiteName, + Type: "0", + Certificate: certPem, + PrivateKey: privkeyPem, + } + siteSetSSLResp, err := d.sdkClient.SiteSetSSL(siteSetSSLReq) + if err != nil { + return nil, xerrors.Wrap(err, "failed to execute sdk request 'bt.SiteSetSSL'") + } else { + d.logger.Logt("已设置站点证书", siteSetSSLResp) + } + } + + case "other": + { + if len(d.config.SiteNames) == 0 { + return nil, errors.New("config `siteNames` is required") + } + + // 上传证书 + sslCertSaveCertReq := &btsdk.SSLCertSaveCertRequest{ + Certificate: certPem, + PrivateKey: privkeyPem, + } + sslCertSaveCertResp, err := d.sdkClient.SSLCertSaveCert(sslCertSaveCertReq) + if err != nil { + return nil, xerrors.Wrap(err, "failed to execute sdk request 'bt.SSLCertSaveCert'") + } else { + d.logger.Logt("已上传证书", sslCertSaveCertResp) + } + + // 设置站点证书 + sslSetBatchCertToSiteReq := &btsdk.SSLSetBatchCertToSiteRequest{ + BatchInfo: slices.Map(d.config.SiteNames, func(siteName string) *btsdk.SSLSetBatchCertToSiteRequestBatchInfo { + return &btsdk.SSLSetBatchCertToSiteRequestBatchInfo{ + SiteName: siteName, + SSLHash: sslCertSaveCertResp.SSLHash, + } + }), + } + sslSetBatchCertToSiteResp, err := d.sdkClient.SSLSetBatchCertToSite(sslSetBatchCertToSiteReq) + if err != nil { + return nil, xerrors.Wrap(err, "failed to execute sdk request 'bt.SSLSetBatchCertToSite'") + } else { + d.logger.Logt("已设置站点证书", sslSetBatchCertToSiteResp) + } + } + + default: + return nil, fmt.Errorf("unsupported site type: %s", d.config.SiteType) } return &deployer.DeployResult{}, nil diff --git a/internal/pkg/core/deployer/providers/baotapanel-site/baotapanel_site_test.go b/internal/pkg/core/deployer/providers/baotapanel-site/baotapanel_site_test.go index ad45b56c..d3cc52cd 100644 --- a/internal/pkg/core/deployer/providers/baotapanel-site/baotapanel_site_test.go +++ b/internal/pkg/core/deployer/providers/baotapanel-site/baotapanel_site_test.go @@ -16,6 +16,7 @@ var ( fInputKeyPath string fApiUrl string fApiKey string + fSiteType string fSiteName string ) @@ -26,6 +27,7 @@ func init() { flag.StringVar(&fInputKeyPath, argsPrefix+"INPUTKEYPATH", "", "") flag.StringVar(&fApiUrl, argsPrefix+"APIURL", "", "") flag.StringVar(&fApiKey, argsPrefix+"APIKEY", "", "") + flag.StringVar(&fSiteType, argsPrefix+"SITETYPE", "", "") flag.StringVar(&fSiteName, argsPrefix+"SITENAME", "", "") } @@ -37,6 +39,7 @@ Shell command to run this test: --CERTIMATE_DEPLOYER_BAOTAPANELSITE_INPUTKEYPATH="/path/to/your-input-key.pem" \ --CERTIMATE_DEPLOYER_BAOTAPANELSITE_APIURL="http://127.0.0.1:8888" \ --CERTIMATE_DEPLOYER_BAOTAPANELSITE_APIKEY="your-api-key" \ + --CERTIMATE_DEPLOYER_BAOTAPANELSITE_SITETYPE="php" \ --CERTIMATE_DEPLOYER_BAOTAPANELSITE_SITENAME="your-site-name" */ func TestDeploy(t *testing.T) { @@ -49,6 +52,7 @@ func TestDeploy(t *testing.T) { fmt.Sprintf("INPUTKEYPATH: %v", fInputKeyPath), fmt.Sprintf("APIURL: %v", fApiUrl), fmt.Sprintf("APIKEY: %v", fApiKey), + fmt.Sprintf("SITETYPE: %v", fSiteType), fmt.Sprintf("SITENAME: %v", fSiteName), }, "\n")) diff --git a/internal/pkg/vendors/btpanel-sdk/api.go b/internal/pkg/vendors/btpanel-sdk/api.go index f197e081..b4efa433 100644 --- a/internal/pkg/vendors/btpanel-sdk/api.go +++ b/internal/pkg/vendors/btpanel-sdk/api.go @@ -42,3 +42,29 @@ func (c *Client) SystemServiceAdmin(req *SystemServiceAdminRequest) (*SystemServ } return &result, nil } + +func (c *Client) SSLCertSaveCert(req *SSLCertSaveCertRequest) (*SSLCertSaveCertResponse, error) { + params := make(map[string]any) + jsonData, _ := json.Marshal(req) + json.Unmarshal(jsonData, ¶ms) + + result := SSLCertSaveCertResponse{} + err := c.sendRequestWithResult("/ssl/cert/save_cert", params, &result) + if err != nil { + return nil, err + } + return &result, nil +} + +func (c *Client) SSLSetBatchCertToSite(req *SSLSetBatchCertToSiteRequest) (*SSLSetBatchCertToSiteResponse, error) { + params := make(map[string]any) + jsonData, _ := json.Marshal(req) + json.Unmarshal(jsonData, ¶ms) + + result := SSLSetBatchCertToSiteResponse{} + err := c.sendRequestWithResult("/ssl?action=SetBatchCertToSite", params, &result) + if err != nil { + return nil, err + } + return &result, nil +} diff --git a/internal/pkg/vendors/btpanel-sdk/client.go b/internal/pkg/vendors/btpanel-sdk/client.go index 8134feca..32f3eba8 100644 --- a/internal/pkg/vendors/btpanel-sdk/client.go +++ b/internal/pkg/vendors/btpanel-sdk/client.go @@ -74,10 +74,10 @@ func (c *Client) sendRequestWithResult(path string, params map[string]any, resul if err := json.Unmarshal(resp.Body(), &result); err != nil { return fmt.Errorf("baota api error: failed to parse response: %w", err) } else if errstatus := result.GetStatus(); errstatus != nil && !*errstatus { - if result.GetMsg() == nil { + if result.GetMessage() == nil { return fmt.Errorf("baota api error: unknown error") } else { - return fmt.Errorf("baota api error: %s", *result.GetMsg()) + return fmt.Errorf("baota api error: %s", *result.GetMessage()) } } diff --git a/internal/pkg/vendors/btpanel-sdk/models.go b/internal/pkg/vendors/btpanel-sdk/models.go index f733d67a..8625e539 100644 --- a/internal/pkg/vendors/btpanel-sdk/models.go +++ b/internal/pkg/vendors/btpanel-sdk/models.go @@ -2,20 +2,20 @@ package btpanelsdk type BaseResponse interface { GetStatus() *bool - GetMsg() *string + GetMessage() *string } type baseResponse struct { - Status *bool `json:"status,omitempty"` - Msg *string `json:"msg,omitempty"` + Status *bool `json:"status,omitempty"` + Message *string `json:"msg,omitempty"` } func (r *baseResponse) GetStatus() *bool { return r.Status } -func (r *baseResponse) GetMsg() *string { - return r.Msg +func (r *baseResponse) GetMessage() *string { + return r.Message } type ConfigSavePanelSSLRequest struct { @@ -46,3 +46,30 @@ type SystemServiceAdminRequest struct { type SystemServiceAdminResponse struct { baseResponse } + +type SSLCertSaveCertRequest struct { + PrivateKey string `json:"key"` + Certificate string `json:"csr"` +} + +type SSLCertSaveCertResponse struct { + baseResponse + SSLHash string `json:"ssl_hash"` +} + +type SSLSetBatchCertToSiteRequest struct { + BatchInfo []*SSLSetBatchCertToSiteRequestBatchInfo `json:"BatchInfo"` +} + +type SSLSetBatchCertToSiteRequestBatchInfo struct { + SSLHash string `json:"ssl_hash"` + SiteName string `json:"siteName"` + CertName string `json:"certName"` +} + +type SSLSetBatchCertToSiteResponse struct { + baseResponse + TotalCount int32 `json:"total"` + SuccessCount int32 `json:"success"` + FailedCount int32 `json:"faild"` +} diff --git a/ui/src/components/workflow/node/ApplyNodeConfigForm.tsx b/ui/src/components/workflow/node/ApplyNodeConfigForm.tsx index 5a0472dd..7b43cad2 100644 --- a/ui/src/components/workflow/node/ApplyNodeConfigForm.tsx +++ b/ui/src/components/workflow/node/ApplyNodeConfigForm.tsx @@ -70,6 +70,7 @@ const ApplyNodeConfigForm = forwardRef { + if (!v) return false; return String(v) .split(MULTIPLE_INPUT_DELIMITER) .every((e) => validDomainName(e, { allowWildcard: true })); diff --git a/ui/src/components/workflow/node/DeployNodeConfigFormAliyunCASDeployConfig.tsx b/ui/src/components/workflow/node/DeployNodeConfigFormAliyunCASDeployConfig.tsx index 05bc632c..065f752c 100644 --- a/ui/src/components/workflow/node/DeployNodeConfigFormAliyunCASDeployConfig.tsx +++ b/ui/src/components/workflow/node/DeployNodeConfigFormAliyunCASDeployConfig.tsx @@ -44,6 +44,7 @@ const DeployNodeConfigFormAliyunCASDeployConfig = ({ .nonempty(t("workflow_node.deploy.form.aliyun_cas_deploy_region.placeholder")) .trim(), resourceIds: z.string({ message: t("workflow_node.deploy.form.aliyun_cas_deploy_resource_ids.placeholder") }).refine((v) => { + if (!v) return false; return String(v) .split(MULTIPLE_INPUT_DELIMITER) .every((e) => /^[1-9]\d*$/.test(e)); diff --git a/ui/src/components/workflow/node/DeployNodeConfigFormBaotaPanelSiteConfig.tsx b/ui/src/components/workflow/node/DeployNodeConfigFormBaotaPanelSiteConfig.tsx index aa891245..f62379bb 100644 --- a/ui/src/components/workflow/node/DeployNodeConfigFormBaotaPanelSiteConfig.tsx +++ b/ui/src/components/workflow/node/DeployNodeConfigFormBaotaPanelSiteConfig.tsx @@ -1,10 +1,19 @@ +import { memo } from "react"; import { useTranslation } from "react-i18next"; -import { Form, type FormInstance, Input } from "antd"; +import { FormOutlined as FormOutlinedIcon } from "@ant-design/icons"; +import { Button, Form, type FormInstance, Input, Select, Space } from "antd"; import { createSchemaFieldRule } from "antd-zod"; import { z } from "zod"; +import ModalForm from "@/components/ModalForm"; +import MultipleInput from "@/components/MultipleInput"; +import Show from "@/components/Show"; +import { useAntdForm } from "@/hooks"; + type DeployNodeConfigFormBaotaPanelSiteConfigFieldValues = Nullish<{ - siteName: string; + siteType: string; + siteName?: string; + siteNames?: string; }>; export type DeployNodeConfigFormBaotaPanelSiteConfigProps = { @@ -15,8 +24,17 @@ export type DeployNodeConfigFormBaotaPanelSiteConfigProps = { onValuesChange?: (values: DeployNodeConfigFormBaotaPanelSiteConfigFieldValues) => void; }; +const SITE_TYPE_PHP = "php"; +const SITE_TYPE_OTHER = "other"; + +const MULTIPLE_INPUT_DELIMITER = ";"; + const initFormModel = (): DeployNodeConfigFormBaotaPanelSiteConfigFieldValues => { - return {}; + return { + siteType: SITE_TYPE_OTHER, + siteName: "", + siteNames: "", + }; }; const DeployNodeConfigFormBaotaPanelSiteConfig = ({ @@ -29,13 +47,32 @@ const DeployNodeConfigFormBaotaPanelSiteConfig = ({ const { t } = useTranslation(); const formSchema = z.object({ + siteType: z.union([z.literal(SITE_TYPE_PHP), z.literal(SITE_TYPE_OTHER)], { + message: t("workflow_node.deploy.form.baotapanel_site_type.placeholder"), + }), siteName: z - .string({ message: t("workflow_node.deploy.form.baotapanel_site_name.placeholder") }) - .nonempty(t("workflow_node.deploy.form.baotapanel_site_name.placeholder")) - .trim(), + .string() + .nullish() + .refine((v) => { + if (fieldSiteType !== SITE_TYPE_PHP) return true; + return !!v?.trim(); + }, t("workflow_node.deploy.form.baotapanel_site_name.placeholder")), + siteNames: z + .string() + .nullish() + .refine((v) => { + if (fieldSiteType !== SITE_TYPE_OTHER) return true; + if (!v) return false; + return String(v) + .split(MULTIPLE_INPUT_DELIMITER) + .every((e) => !!e.trim()); + }, t("workflow_node.deploy.form.baotapanel_site_names.placeholder")), }); const formRule = createSchemaFieldRule(formSchema); + const fieldSiteType = Form.useWatch("siteType", formInst); + const fieldSiteNames = Form.useWatch("siteNames", formInst); + const handleFormChange = (_: unknown, values: z.infer) => { onValuesChange?.(values); }; @@ -49,16 +86,101 @@ const DeployNodeConfigFormBaotaPanelSiteConfig = ({ name={formName} onValuesChange={handleFormChange} > - } - > - + + + + + } + > + + + + + + } + > + + + { + formInst.setFieldValue("siteNames", e.target.value); + }} + /> + + + + + } + onChange={(value) => { + formInst.setFieldValue("siteNames", value); + }} + /> + + + ); }; +const SiteNamesModalInput = memo(({ value, trigger, onChange }: { value?: string; trigger?: React.ReactNode; onChange?: (value: string) => void }) => { + const { t } = useTranslation(); + + const formSchema = z.object({ + siteNames: z.array(z.string()).refine((v) => { + return v.every((e) => !!e?.trim()); + }, t("workflow_node.deploy.form.baotapanel_site_names.errmsg.invalid")), + }); + const formRule = createSchemaFieldRule(formSchema); + const { form: formInst, formProps } = useAntdForm({ + name: "workflowNodeDeployConfigFormBaotaPanelSiteNamesModalInput", + initialValues: { siteNames: value?.split(MULTIPLE_INPUT_DELIMITER) }, + onSubmit: (values) => { + onChange?.( + values.siteNames + .map((e) => e.trim()) + .filter((e) => !!e) + .join(MULTIPLE_INPUT_DELIMITER) + ); + }, + }); + + return ( + + + + + + ); +}); + export default DeployNodeConfigFormBaotaPanelSiteConfig; diff --git a/ui/src/components/workflow/node/DeployNodeConfigFormTencentCloudSSLDeployConfig.tsx b/ui/src/components/workflow/node/DeployNodeConfigFormTencentCloudSSLDeployConfig.tsx index 14266151..67cdbf11 100644 --- a/ui/src/components/workflow/node/DeployNodeConfigFormTencentCloudSSLDeployConfig.tsx +++ b/ui/src/components/workflow/node/DeployNodeConfigFormTencentCloudSSLDeployConfig.tsx @@ -48,6 +48,7 @@ const DeployNodeConfigFormTencentCloudSSLDeployConfig = ({ .nonempty(t("workflow_node.deploy.form.tencentcloud_ssl_deploy_resource_type.placeholder")) .trim(), resourceIds: z.string({ message: t("workflow_node.deploy.form.tencentcloud_ssl_deploy_resource_ids.placeholder") }).refine((v) => { + if (!v) return false; return String(v) .split(MULTIPLE_INPUT_DELIMITER) .every((e) => /^[A-Za-z0-9._-]+$/.test(e)); diff --git a/ui/src/i18n/locales/en/nls.workflow.nodes.json b/ui/src/i18n/locales/en/nls.workflow.nodes.json index ae79074f..6bf12328 100644 --- a/ui/src/i18n/locales/en/nls.workflow.nodes.json +++ b/ui/src/i18n/locales/en/nls.workflow.nodes.json @@ -194,9 +194,19 @@ "workflow_node.deploy.form.baishan_cdn_domain.placeholder": "Please enter Baishan CDN domain name", "workflow_node.deploy.form.baishan_cdn_domain.tooltip": "For more information, see https://cdnx.console.baishan.com", "workflow_node.deploy.form.baotapanel_console_auto_restart.label": "Auto restart after deployment", + "workflow_node.deploy.form.baotapanel_site_type.label": "BaoTa Panel site type", + "workflow_node.deploy.form.baotapanel_site_type.placeholder": "Please select BaoTa Panel site type", + "workflow_node.deploy.form.baotapanel_site_type.option.php.label": "PHP sites", + "workflow_node.deploy.form.baotapanel_site_type.option.other.label": "Other sites", "workflow_node.deploy.form.baotapanel_site_name.label": "BaoTa Panel site name", "workflow_node.deploy.form.baotapanel_site_name.placeholder": "Please enter BaoTa Panel site name", "workflow_node.deploy.form.baotapanel_site_name.tooltip": "Usually equal to the website domain name.", + "workflow_node.deploy.form.baotapanel_site_names.label": "BaoTa Panel site names", + "workflow_node.deploy.form.baotapanel_site_names.placeholder": "Please enter BaoTa Panel site names (separated by semicolons)", + "workflow_node.deploy.form.baotapanel_site_names.errmsg.invalid": "Please enter a valid BaoTa Panel site name", + "workflow_node.deploy.form.baotapanel_site_names.tooltip": "Usually equal to the websites domain name.", + "workflow_node.deploy.form.baotapanel_site_names.multiple_input_modal.title": "Change BaoTa Panel site names", + "workflow_node.deploy.form.baotapanel_site_names.multiple_input_modal.placeholder": "Please enter BaoTa Panel site name", "workflow_node.deploy.form.byteplus_cdn_domain.label": "BytePlus CDN domain", "workflow_node.deploy.form.byteplus_cdn_domain.placeholder": "Please enter BytePlus CDN domain name", "workflow_node.deploy.form.byteplus_cdn_domain.tooltip": "For more information, see https://console.byteplus.com/cdn", diff --git a/ui/src/i18n/locales/zh/nls.workflow.nodes.json b/ui/src/i18n/locales/zh/nls.workflow.nodes.json index ad886a02..e4b341e7 100644 --- a/ui/src/i18n/locales/zh/nls.workflow.nodes.json +++ b/ui/src/i18n/locales/zh/nls.workflow.nodes.json @@ -194,9 +194,19 @@ "workflow_node.deploy.form.baishan_cdn_domain.placeholder": "请输入白山云 CDN 加速域名", "workflow_node.deploy.form.baishan_cdn_domain.tooltip": "这是什么?请参阅 https://cdnx.console.baishan.com", "workflow_node.deploy.form.baotapanel_console_auto_restart.label": "部署后自动重启面板服务", + "workflow_node.deploy.form.baotapanel_site_type.label": "宝塔面板网站类型", + "workflow_node.deploy.form.baotapanel_site_type.placeholder": "请选择宝塔面板网站类型", + "workflow_node.deploy.form.baotapanel_site_type.option.php.label": "PHP", + "workflow_node.deploy.form.baotapanel_site_type.option.other.label": "其他", "workflow_node.deploy.form.baotapanel_site_name.label": "宝塔面板网站名称", "workflow_node.deploy.form.baotapanel_site_name.placeholder": "请输入宝塔面板网站名称", "workflow_node.deploy.form.baotapanel_site_name.tooltip": "通常为网站域名。", + "workflow_node.deploy.form.baotapanel_site_names.label": "宝塔面板网站名称", + "workflow_node.deploy.form.baotapanel_site_names.placeholder": "请输入宝塔面板网站名称(多个值请用半角分号隔开)", + "workflow_node.deploy.form.baotapanel_site_names.errmsg.invalid": "请输入正确的宝塔面板网站名称", + "workflow_node.deploy.form.baotapanel_site_names.tooltip": "通常为网站域名。", + "workflow_node.deploy.form.baotapanel_site_names.multiple_input_modal.title": "修改宝塔面板网站名称", + "workflow_node.deploy.form.baotapanel_site_names.multiple_input_modal.placeholder": "请输入宝塔面板网站名称", "workflow_node.deploy.form.byteplus_cdn_domain.label": "BytePlus CDN 域名(支持泛域名)", "workflow_node.deploy.form.byteplus_cdn_domain.placeholder": "请输入 BytePlus CDN 域名", "workflow_node.deploy.form.byteplus_cdn_domain.tooltip": "这是什么?请参阅 https://console.byteplus.com/cdn", From 1bac6174ad2d702b0f6e627824080d779da20a0c Mon Sep 17 00:00:00 2001 From: Fu Diwei Date: Tue, 18 Feb 2025 17:31:42 +0800 Subject: [PATCH 14/34] feat: add baiducloud dns-01 applicant --- README.md | 1 + README_EN.md | 1 + go.mod | 2 +- go.sum | 2 + internal/applicant/providers.go | 17 ++ internal/domain/provider.go | 2 + .../lego-providers/baiducloud/baiducloud.go | 39 ++++ .../baiducloud/internal/lego.go | 195 ++++++++++++++++++ internal/pkg/utils/maps/maps.go | 5 - main.go | 5 + ui/src/domain/provider.ts | 5 +- ui/src/i18n/locales/en/nls.provider.json | 1 + ui/src/i18n/locales/zh/nls.provider.json | 1 + 13 files changed, 269 insertions(+), 7 deletions(-) create mode 100644 internal/pkg/core/applicant/acme-dns-01/lego-providers/baiducloud/baiducloud.go create mode 100644 internal/pkg/core/applicant/acme-dns-01/lego-providers/baiducloud/internal/lego.go diff --git a/README.md b/README.md index bae31da1..f9d4df00 100644 --- a/README.md +++ b/README.md @@ -90,6 +90,7 @@ make local.run | :----------------------------------------------------------------- | :-------------------------------------- | | [阿里云](https://www.aliyun.com/) | | | [腾讯云](https://cloud.tencent.com/) | | +| [百度智能云](https://cloud.baidu.com/) | | | [华为云](https://www.huaweicloud.com/) | | | [火山引擎](https://www.volcengine.com/) | | | [AWS Route53](https://aws.amazon.com/route53/) | | diff --git a/README_EN.md b/README_EN.md index 0daf5b2b..a6d13c26 100644 --- a/README_EN.md +++ b/README_EN.md @@ -89,6 +89,7 @@ The following DNS providers are supported: | :----------------------------------------------------------- | :------------------------------------ | | [Alibaba Cloud](https://www.alibabacloud.com/) | | | [Tencent Cloud](https://www.tencentcloud.com/) | | +| [Baidu AI Cloud](https://intl.cloud.baidu.com/) | | | [Huawei Cloud](https://www.huaweicloud.com/) | | | [Volcengine](https://www.volcengine.com/) | | | [AWS Route53](https://aws.amazon.com/route53/) | | diff --git a/go.mod b/go.mod index ee281548..c07f2a5b 100644 --- a/go.mod +++ b/go.mod @@ -19,7 +19,7 @@ require ( github.com/aliyun/aliyun-oss-go-sdk v3.0.2+incompatible github.com/aws/aws-sdk-go-v2/service/acm v1.30.18 github.com/aws/aws-sdk-go-v2/service/cloudfront v1.44.10 - github.com/baidubce/bce-sdk-go v0.9.216 + github.com/baidubce/bce-sdk-go v0.9.217 github.com/byteplus-sdk/byteplus-sdk-golang v1.0.41 github.com/go-acme/lego/v4 v4.21.0 github.com/go-resty/resty/v2 v2.16.5 diff --git a/go.sum b/go.sum index c3d1b3a6..f127aeb4 100644 --- a/go.sum +++ b/go.sum @@ -261,6 +261,8 @@ github.com/aws/smithy-go v1.22.2 h1:6D9hW43xKFrRx/tXXfAlIZc4JI+yQe6snnWcQyxSyLQ= github.com/aws/smithy-go v1.22.2/go.mod h1:irrKGvNn1InZwb2d7fkIRNucdfwR8R+Ts3wxYa/cJHg= github.com/baidubce/bce-sdk-go v0.9.216 h1:jRq4C1UGYcvHo6Gst2kuUzhWwJM6EqXCmhIsTKQvf4k= github.com/baidubce/bce-sdk-go v0.9.216/go.mod h1:zbYJMQwE4IZuyrJiFO8tO8NbtYiKTFTbwh4eIsqjVdg= +github.com/baidubce/bce-sdk-go v0.9.217 h1:dbMeVzpr9BGItTFHB1s2KSrpz0ayJC1y366VUMmaF0k= +github.com/baidubce/bce-sdk-go v0.9.217/go.mod h1:zbYJMQwE4IZuyrJiFO8tO8NbtYiKTFTbwh4eIsqjVdg= github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= diff --git a/internal/applicant/providers.go b/internal/applicant/providers.go index 6c89b794..65ddde65 100644 --- a/internal/applicant/providers.go +++ b/internal/applicant/providers.go @@ -10,6 +10,7 @@ import ( pAliyun "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/aliyun" pAWSRoute53 "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/aws-route53" pAzureDNS "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/azure-dns" + pBaiduCloud "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/baiducloud" pCloudflare "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/cloudflare" pClouDNS "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/cloudns" pGcore "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/gcore" @@ -102,6 +103,22 @@ func createApplicant(options *applicantOptions) (challenge.Provider, error) { return applicant, err } + case domain.ApplyDNSProviderTypeBaiduCloud, domain.ApplyDNSProviderTypeBaiduCloudDNS: + { + access := domain.AccessConfigForBaiduCloud{} + if err := maps.Populate(options.ProviderAccessConfig, &access); err != nil { + return nil, fmt.Errorf("failed to populate provider access config: %w", err) + } + + applicant, err := pBaiduCloud.NewChallengeProvider(&pBaiduCloud.BaiduCloudApplicantConfig{ + AccessKeyId: access.AccessKeyId, + SecretAccessKey: access.SecretAccessKey, + DnsPropagationTimeout: options.DnsPropagationTimeout, + DnsTTL: options.DnsTTL, + }) + return applicant, err + } + case domain.ApplyDNSProviderTypeCloudflare: { access := domain.AccessConfigForCloudflare{} diff --git a/internal/domain/provider.go b/internal/domain/provider.go index 2aaa69a9..93f85561 100644 --- a/internal/domain/provider.go +++ b/internal/domain/provider.go @@ -67,6 +67,8 @@ const ( ApplyDNSProviderTypeAWS = ApplyDNSProviderType("aws") // 兼容旧值,等同于 [ApplyDNSProviderTypeAWSRoute53] ApplyDNSProviderTypeAWSRoute53 = ApplyDNSProviderType("aws-route53") ApplyDNSProviderTypeAzureDNS = ApplyDNSProviderType("azure-dns") + ApplyDNSProviderTypeBaiduCloud = ApplyDNSProviderType("baiducloud") // 兼容旧值,等同于 [ApplyDNSProviderTypeBaiduCloudDNS] + ApplyDNSProviderTypeBaiduCloudDNS = ApplyDNSProviderType("baiducloud-dns") ApplyDNSProviderTypeCloudflare = ApplyDNSProviderType("cloudflare") ApplyDNSProviderTypeClouDNS = ApplyDNSProviderType("cloudns") ApplyDNSProviderTypeGcore = ApplyDNSProviderType("gcore") diff --git a/internal/pkg/core/applicant/acme-dns-01/lego-providers/baiducloud/baiducloud.go b/internal/pkg/core/applicant/acme-dns-01/lego-providers/baiducloud/baiducloud.go new file mode 100644 index 00000000..1328009a --- /dev/null +++ b/internal/pkg/core/applicant/acme-dns-01/lego-providers/baiducloud/baiducloud.go @@ -0,0 +1,39 @@ +package baiducloud + +import ( + "time" + + "github.com/go-acme/lego/v4/challenge" + + internal "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/baiducloud/internal" +) + +type BaiduCloudApplicantConfig struct { + AccessKeyId string `json:"accessKeyId"` + SecretAccessKey string `json:"secretAccessKey"` + DnsPropagationTimeout int32 `json:"dnsPropagationTimeout,omitempty"` + DnsTTL int32 `json:"dnsTTL,omitempty"` +} + +func NewChallengeProvider(config *BaiduCloudApplicantConfig) (challenge.Provider, error) { + if config == nil { + panic("config is nil") + } + + providerConfig := internal.NewDefaultConfig() + providerConfig.AccessKeyID = config.AccessKeyId + providerConfig.SecretAccessKey = config.SecretAccessKey + if config.DnsPropagationTimeout != 0 { + providerConfig.PropagationTimeout = time.Duration(config.DnsPropagationTimeout) * time.Second + } + if config.DnsTTL != 0 { + providerConfig.TTL = config.DnsTTL + } + + provider, err := internal.NewDNSProviderConfig(providerConfig) + if err != nil { + return nil, err + } + + return provider, nil +} diff --git a/internal/pkg/core/applicant/acme-dns-01/lego-providers/baiducloud/internal/lego.go b/internal/pkg/core/applicant/acme-dns-01/lego-providers/baiducloud/internal/lego.go new file mode 100644 index 00000000..fd138c6d --- /dev/null +++ b/internal/pkg/core/applicant/acme-dns-01/lego-providers/baiducloud/internal/lego.go @@ -0,0 +1,195 @@ +package lego_baiducloud + +import ( + "errors" + "fmt" + "strings" + "time" + + bceDns "github.com/baidubce/bce-sdk-go/services/dns" + "github.com/go-acme/lego/v4/challenge" + "github.com/go-acme/lego/v4/challenge/dns01" + "github.com/go-acme/lego/v4/platform/config/env" + "github.com/google/uuid" +) + +const ( + envNamespace = "BAIDUCLOUD_" + + EnvAccessKeyID = envNamespace + "ACCESS_KEY_ID" + EnvSecretAccessKey = envNamespace + "SECRET_ACCESS_KEY" + + EnvTTL = envNamespace + "TTL" + EnvPropagationTimeout = envNamespace + "PROPAGATION_TIMEOUT" + EnvPollingInterval = envNamespace + "POLLING_INTERVAL" + EnvHTTPTimeout = envNamespace + "HTTP_TIMEOUT" +) + +var _ challenge.ProviderTimeout = (*DNSProvider)(nil) + +type Config struct { + AccessKeyID string + SecretAccessKey string + + PropagationTimeout time.Duration + PollingInterval time.Duration + TTL int32 + HTTPTimeout time.Duration +} + +type DNSProvider struct { + client *bceDns.Client + config *Config +} + +func NewDefaultConfig() *Config { + return &Config{ + TTL: int32(env.GetOrDefaultInt(EnvTTL, 300)), + PropagationTimeout: env.GetOrDefaultSecond(EnvPropagationTimeout, 2*time.Minute), + PollingInterval: env.GetOrDefaultSecond(EnvPollingInterval, dns01.DefaultPollingInterval), + HTTPTimeout: env.GetOrDefaultSecond(EnvHTTPTimeout, 30*time.Second), + } +} + +func NewDNSProvider() (*DNSProvider, error) { + values, err := env.Get(EnvAccessKeyID, EnvSecretAccessKey) + if err != nil { + return nil, fmt.Errorf("baiducloud: %w", err) + } + + config := NewDefaultConfig() + config.AccessKeyID = values[EnvAccessKeyID] + config.SecretAccessKey = values[EnvSecretAccessKey] + + return NewDNSProviderConfig(config) +} + +func NewDNSProviderConfig(config *Config) (*DNSProvider, error) { + if config == nil { + return nil, errors.New("baiducloud: the configuration of the DNS provider is nil") + } + + client, err := bceDns.NewClient(config.AccessKeyID, config.SecretAccessKey, "") + if err != nil { + return nil, err + } else { + if client.Config != nil { + client.Config.ConnectionTimeoutInMillis = int(config.HTTPTimeout.Milliseconds()) + } + } + + return &DNSProvider{ + client: client, + config: config, + }, nil +} + +func (d *DNSProvider) Present(domain, token, keyAuth string) error { + info := dns01.GetChallengeInfo(domain, keyAuth) + + zoneName, err := dns01.FindZoneByFqdn(info.EffectiveFQDN) + if err != nil { + return fmt.Errorf("baiducloud: %w", err) + } + + subDomain, err := dns01.ExtractSubDomain(info.EffectiveFQDN, zoneName) + if err != nil { + return fmt.Errorf("baiducloud: %w", err) + } + + if err := d.addOrUpdateDNSRecord(domain, subDomain, info.Value); err != nil { + return fmt.Errorf("baiducloud: %w", err) + } + + return nil +} + +func (d *DNSProvider) CleanUp(domain, token, keyAuth string) error { + fqdn, value := dns01.GetRecord(domain, keyAuth) + subDomain := dns01.UnFqdn(fqdn) + + if err := d.removeDNSRecord(domain, subDomain, value); err != nil { + return fmt.Errorf("baiducloud: %w", err) + } + + return nil +} + +func (d *DNSProvider) Timeout() (timeout, interval time.Duration) { + return d.config.PropagationTimeout, d.config.PollingInterval +} + +func (d *DNSProvider) getDNSRecord(domain, subDomain string) (*bceDns.Record, error) { + pageMarker := "" + pageSize := 1000 + for { + request := &bceDns.ListRecordRequest{} + request.Rr = domain + request.Marker = pageMarker + request.MaxKeys = pageSize + + response, err := d.client.ListRecord(domain, request) + if err != nil { + return nil, err + } + + for _, record := range response.Records { + if record.Type == "TXT" && record.Rr == subDomain { + return &record, nil + } + } + + if len(response.Records) < pageSize { + break + } + + pageMarker = response.NextMarker + } + + return nil, nil +} + +func (d *DNSProvider) addOrUpdateDNSRecord(domain, subDomain, value string) error { + record, err := d.getDNSRecord(domain, subDomain) + if err != nil { + return err + } + + if record == nil { + request := &bceDns.CreateRecordRequest{ + Type: "TXT", + Rr: subDomain, + Value: value, + Ttl: &d.config.TTL, + } + err := d.client.CreateRecord(domain, request, d.generateClientToken()) + return err + } else { + request := &bceDns.UpdateRecordRequest{ + Type: "TXT", + Rr: subDomain, + Value: value, + Ttl: &d.config.TTL, + } + err := d.client.UpdateRecord(domain, record.Id, request, d.generateClientToken()) + return err + } +} + +func (d *DNSProvider) removeDNSRecord(domain, subDomain, value string) error { + record, err := d.getDNSRecord(domain, subDomain) + if err != nil { + return err + } + + if record == nil { + return nil + } + + err = d.client.DeleteRecord(domain, record.Id, d.generateClientToken()) + return err +} + +func (d *DNSProvider) generateClientToken() string { + return strings.ReplaceAll(uuid.New().String(), "-", "") +} diff --git a/internal/pkg/utils/maps/maps.go b/internal/pkg/utils/maps/maps.go index a88b6629..4a4417d0 100644 --- a/internal/pkg/utils/maps/maps.go +++ b/internal/pkg/utils/maps/maps.go @@ -207,8 +207,3 @@ func Populate(dict map[string]any, output any) error { return decoder.Decode(dict) } - -// Deprecated: Use [Populate] instead. -func Decode(dict map[string]any, output any) error { - return Populate(dict, output) -} diff --git a/main.go b/main.go index 73d1a2a9..76f7f1c0 100644 --- a/main.go +++ b/main.go @@ -29,6 +29,11 @@ func main() { var flagDir string flag.StringVar(&flagHttp, "http", "127.0.0.1:8090", "HTTP server address") flag.StringVar(&flagDir, "dir", "/pb_data/database", "Pocketbase data directory") + if len(os.Args) < 2 { + slog.Error("[CERTIMATE] missing exec args") + os.Exit(1) + return + } _ = flag.CommandLine.Parse(os.Args[2:]) // skip the first two arguments: "main.go serve" migratecmd.MustRegister(app, app.RootCmd, migratecmd.Config{ diff --git a/ui/src/domain/provider.ts b/ui/src/domain/provider.ts index ed14db23..b5bcaca7 100644 --- a/ui/src/domain/provider.ts +++ b/ui/src/domain/provider.ts @@ -67,11 +67,11 @@ export const accessProvidersMap: Map Date: Tue, 18 Feb 2025 19:18:28 +0800 Subject: [PATCH 15/34] refactor: normalize providers constructors --- internal/applicant/providers.go | 38 +- internal/deployer/deployer.go | 4 +- internal/deployer/providers.go | 329 +++++++++--------- internal/notify/providers.go | 16 +- .../lego-providers/acmehttpreq/acmehttpreq.go | 4 +- .../lego-providers/aliyun/aliyun.go | 4 +- .../lego-providers/aws-route53/aws-route53.go | 4 +- .../lego-providers/azure-dns/azure-dns.go | 4 +- .../lego-providers/baiducloud/baiducloud.go | 4 +- .../lego-providers/cloudflare/cloudflare.go | 4 +- .../lego-providers/cloudns/cloudns.go | 4 +- .../acme-dns-01/lego-providers/gcore/gcore.go | 4 +- .../acme-dns-01/lego-providers/gname/gname.go | 4 +- .../lego-providers/godaddy/godaddy.go | 4 +- .../lego-providers/huaweicloud/huaweicloud.go | 4 +- .../lego-providers/namedotcom/namedotcom.go | 4 +- .../lego-providers/namesilo/namesilo.go | 4 +- .../acme-dns-01/lego-providers/ns1/ns1.go | 4 +- .../lego-providers/powerdns/powerdns.go | 4 +- .../lego-providers/rainyun/rainyun.go | 4 +- .../tencentcloud/tencentcloud.go | 4 +- .../lego-providers/volcengine/volcengine.go | 4 +- .../lego-providers/westcn/westcn.go | 4 +- .../providers/aliyun-alb/aliyun_alb.go | 35 +- .../providers/aliyun-alb/aliyun_alb_test.go | 4 +- .../aliyun-cas-deploy/aliyun_cas_deploy.go | 29 +- .../providers/aliyun-cdn/aliyun_cdn.go | 29 +- .../providers/aliyun-cdn/aliyun_cdn_test.go | 2 +- .../providers/aliyun-clb/aliyun_clb.go | 35 +- .../providers/aliyun-clb/aliyun_clb_test.go | 4 +- .../providers/aliyun-dcdn/aliyun_dcdn.go | 29 +- .../providers/aliyun-dcdn/aliyun_dcdn_test.go | 2 +- .../providers/aliyun-esa/aliyun_esa.go | 29 +- .../providers/aliyun-esa/aliyun_esa_test.go | 2 +- .../providers/aliyun-live/aliyun_live.go | 29 +- .../providers/aliyun-live/aliyun_live_test.go | 2 +- .../providers/aliyun-nlb/aliyun_nlb.go | 35 +- .../providers/aliyun-nlb/aliyun_nlb_test.go | 4 +- .../providers/aliyun-oss/aliyun_oss.go | 29 +- .../providers/aliyun-oss/aliyun_oss_test.go | 2 +- .../providers/aliyun-waf/aliyun_waf.go | 29 +- .../providers/aliyun-waf/aliyun_waf_test.go | 2 +- .../aws-cloudfront/aws_cloudfront.go | 29 +- .../aws-cloudfront/aws_cloudfront_test.go | 4 +- .../baiducloud-cdn/baiducloud_cdn.go | 29 +- .../baiducloud-cdn/baiducloud_cdn_test.go | 2 +- .../providers/baishan-cdn/baishan_cdn.go | 29 +- .../providers/baishan-cdn/baishan_cdn_test.go | 2 +- .../baotapanel-console/baotapanel_console.go | 29 +- .../baotapanel_console_test.go | 2 +- .../baotapanel-site/baotapanel_site.go | 29 +- .../baotapanel-site/baotapanel_site_test.go | 2 +- .../providers/byteplus-cdn/byteplus_cdn.go | 29 +- .../byteplus-cdn/byteplus_cdn_test.go | 2 +- .../deployer/providers/cachefly/cachefly.go | 29 +- .../providers/cachefly/cachefly_test.go | 2 +- .../core/deployer/providers/cdnfly/cdnfly.go | 33 +- .../deployer/providers/cdnfly/cdnfly_test.go | 2 +- .../providers/dogecloud-cdn/dogecloud_cdn.go | 30 +- .../dogecloud-cdn/dogecloud_cdn_test.go | 2 +- .../edgio-applications/edgio_applications.go | 29 +- .../edgio_applications_test.go | 2 +- .../deployer/providers/gcore-cdn/gcore_cdn.go | 29 +- .../providers/gcore-cdn/gcore_cdn_test.go | 2 +- .../huaweicloud-cdn/huaweicloud_cdn.go | 29 +- .../huaweicloud-cdn/huaweicloud_cdn_test.go | 2 +- .../huaweicloud-elb/huaweicloud_elb.go | 37 +- .../huaweicloud-elb/huaweicloud_elb_test.go | 6 +- .../huaweicloud-waf/huaweicloud_waf.go | 35 +- .../huaweicloud-waf/huaweicloud_waf_test.go | 2 +- .../providers/k8s-secret/k8s_secret.go | 29 +- .../providers/k8s-secret/k8s_secret_test.go | 2 +- .../core/deployer/providers/local/local.go | 29 +- .../deployer/providers/local/local_test.go | 6 +- .../deployer/providers/qiniu-cdn/qiniu_cdn.go | 29 +- .../providers/qiniu-cdn/qiniu_cdn_test.go | 2 +- .../providers/qiniu-pili/qiniu_pili.go | 29 +- .../providers/qiniu-pili/qiniu_pili_test.go | 2 +- .../deployer/providers/safeline/safeline.go | 31 +- .../providers/safeline/safeline_test.go | 2 +- .../pkg/core/deployer/providers/ssh/ssh.go | 29 +- .../core/deployer/providers/ssh/ssh_test.go | 2 +- .../tencentcloud-cdn/tencentcloud_cdn.go | 33 +- .../tencentcloud-cdn/tencentcloud_cdn_test.go | 2 +- .../tencentcloud-clb/tencentcloud_clb.go | 39 +-- .../tencentcloud-clb/tencentcloud_clb_test.go | 8 +- .../tencentcloud-cos/tencentcloud_cos.go | 29 +- .../tencentcloud-cos/tencentcloud_cos_test.go | 2 +- .../tencentcloud-css/tencentcloud_css.go | 29 +- .../tencentcloud-css/tencentcloud_css_test.go | 2 +- .../tencentcloud-ecdn/tencentcloud_ecdn.go | 31 +- .../tencentcloud_ecdn_test.go | 2 +- .../tencentcloud-eo/tencentcloud_eo.go | 29 +- .../tencentcloud-eo/tencentcloud_eo_test.go | 2 +- .../tencentcloud_ssl_deploy.go | 29 +- .../tencentcloud-waf/tencentcloud_waf.go | 29 +- .../tencentcloud-waf/tencentcloud_waf_test.go | 2 +- .../providers/ucloud-ucdn/ucloud_ucdn.go | 29 +- .../providers/ucloud-ucdn/ucloud_ucdn_test.go | 2 +- .../providers/ucloud-us3/ucloud_us3.go | 29 +- .../providers/ucloud-us3/ucloud_us3_test.go | 2 +- .../volcengine-cdn/volcengine_cdn.go | 29 +- .../volcengine-cdn/volcengine_cdn_test.go | 2 +- .../volcengine-clb/volcengine_clb.go | 30 +- .../volcengine-clb/volcengine_clb_test.go | 2 +- .../volcengine-dcdn/volcengine_dcdn.go | 29 +- .../volcengine-dcdn/volcengine_dcdn_test.go | 2 +- .../volcengine-imagex/volcengine_imagex.go | 29 +- .../volcengine_imagex_test.go | 2 +- .../volcengine-live/volcengine_live.go | 29 +- .../volcengine-live/volcengine_live_test.go | 2 +- .../volcengine-tos/volcengine_tos.go | 29 +- .../volcengine-tos/volcengine_tos_test.go | 2 +- .../deployer/providers/webhook/webhook.go | 29 +- .../providers/webhook/webhook_test.go | 2 +- .../pkg/core/notifier/providers/bark/bark.go | 14 +- .../core/notifier/providers/bark/bark_test.go | 2 +- .../notifier/providers/dingtalk/dingtalk.go | 14 +- .../providers/dingtalk/dingtalk_test.go | 2 +- .../core/notifier/providers/email/email.go | 14 +- .../notifier/providers/email/email_test.go | 2 +- .../pkg/core/notifier/providers/lark/lark.go | 14 +- .../core/notifier/providers/lark/lark_test.go | 2 +- .../providers/serverchan/serverchan.go | 14 +- .../providers/serverchan/serverchan_test.go | 2 +- .../notifier/providers/telegram/telegram.go | 14 +- .../providers/telegram/telegram_test.go | 2 +- .../notifier/providers/webhook/webhook.go | 14 +- .../providers/webhook/webhook_test.go | 2 +- .../core/notifier/providers/wecom/wecom.go | 14 +- .../notifier/providers/wecom/wecom_test.go | 2 +- .../i18n/locales/zh/nls.workflow.nodes.json | 52 +-- 132 files changed, 1014 insertions(+), 1160 deletions(-) diff --git a/internal/applicant/providers.go b/internal/applicant/providers.go index 65ddde65..10466389 100644 --- a/internal/applicant/providers.go +++ b/internal/applicant/providers.go @@ -41,7 +41,7 @@ func createApplicant(options *applicantOptions) (challenge.Provider, error) { return nil, fmt.Errorf("failed to populate provider access config: %w", err) } - applicant, err := pACMEHttpReq.NewChallengeProvider(&pACMEHttpReq.ACMEHttpReqApplicantConfig{ + applicant, err := pACMEHttpReq.NewChallengeProvider(&pACMEHttpReq.ChallengeProviderConfig{ Endpoint: access.Endpoint, Mode: access.Mode, Username: access.Username, @@ -58,7 +58,7 @@ func createApplicant(options *applicantOptions) (challenge.Provider, error) { return nil, fmt.Errorf("failed to populate provider access config: %w", err) } - applicant, err := pAliyun.NewChallengeProvider(&pAliyun.AliyunApplicantConfig{ + applicant, err := pAliyun.NewChallengeProvider(&pAliyun.ChallengeProviderConfig{ AccessKeyId: access.AccessKeyId, AccessKeySecret: access.AccessKeySecret, DnsPropagationTimeout: options.DnsPropagationTimeout, @@ -74,7 +74,7 @@ func createApplicant(options *applicantOptions) (challenge.Provider, error) { return nil, fmt.Errorf("failed to populate provider access config: %w", err) } - applicant, err := pAWSRoute53.NewChallengeProvider(&pAWSRoute53.AWSRoute53ApplicantConfig{ + applicant, err := pAWSRoute53.NewChallengeProvider(&pAWSRoute53.ChallengeProviderConfig{ AccessKeyId: access.AccessKeyId, SecretAccessKey: access.SecretAccessKey, Region: maps.GetValueAsString(options.ProviderApplyConfig, "region"), @@ -92,7 +92,7 @@ func createApplicant(options *applicantOptions) (challenge.Provider, error) { return nil, fmt.Errorf("failed to populate provider access config: %w", err) } - applicant, err := pAzureDNS.NewChallengeProvider(&pAzureDNS.AzureDNSApplicantConfig{ + applicant, err := pAzureDNS.NewChallengeProvider(&pAzureDNS.ChallengeProviderConfig{ TenantId: access.TenantId, ClientId: access.ClientId, ClientSecret: access.ClientSecret, @@ -110,7 +110,7 @@ func createApplicant(options *applicantOptions) (challenge.Provider, error) { return nil, fmt.Errorf("failed to populate provider access config: %w", err) } - applicant, err := pBaiduCloud.NewChallengeProvider(&pBaiduCloud.BaiduCloudApplicantConfig{ + applicant, err := pBaiduCloud.NewChallengeProvider(&pBaiduCloud.ChallengeProviderConfig{ AccessKeyId: access.AccessKeyId, SecretAccessKey: access.SecretAccessKey, DnsPropagationTimeout: options.DnsPropagationTimeout, @@ -126,7 +126,7 @@ func createApplicant(options *applicantOptions) (challenge.Provider, error) { return nil, fmt.Errorf("failed to populate provider access config: %w", err) } - applicant, err := pCloudflare.NewChallengeProvider(&pCloudflare.CloudflareApplicantConfig{ + applicant, err := pCloudflare.NewChallengeProvider(&pCloudflare.ChallengeProviderConfig{ DnsApiToken: access.DnsApiToken, DnsPropagationTimeout: options.DnsPropagationTimeout, DnsTTL: options.DnsTTL, @@ -141,7 +141,7 @@ func createApplicant(options *applicantOptions) (challenge.Provider, error) { return nil, fmt.Errorf("failed to populate provider access config: %w", err) } - applicant, err := pClouDNS.NewChallengeProvider(&pClouDNS.ClouDNSApplicantConfig{ + applicant, err := pClouDNS.NewChallengeProvider(&pClouDNS.ChallengeProviderConfig{ AuthId: access.AuthId, AuthPassword: access.AuthPassword, DnsPropagationTimeout: options.DnsPropagationTimeout, @@ -157,7 +157,7 @@ func createApplicant(options *applicantOptions) (challenge.Provider, error) { return nil, fmt.Errorf("failed to populate provider access config: %w", err) } - applicant, err := pGcore.NewChallengeProvider(&pGcore.GcoreApplicantConfig{ + applicant, err := pGcore.NewChallengeProvider(&pGcore.ChallengeProviderConfig{ ApiToken: access.ApiToken, DnsPropagationTimeout: options.DnsPropagationTimeout, DnsTTL: options.DnsTTL, @@ -172,7 +172,7 @@ func createApplicant(options *applicantOptions) (challenge.Provider, error) { return nil, fmt.Errorf("failed to populate provider access config: %w", err) } - applicant, err := pGname.NewChallengeProvider(&pGname.GnameApplicantConfig{ + applicant, err := pGname.NewChallengeProvider(&pGname.ChallengeProviderConfig{ AppId: access.AppId, AppKey: access.AppKey, DnsPropagationTimeout: options.DnsPropagationTimeout, @@ -188,7 +188,7 @@ func createApplicant(options *applicantOptions) (challenge.Provider, error) { return nil, fmt.Errorf("failed to populate provider access config: %w", err) } - applicant, err := pGoDaddy.NewChallengeProvider(&pGoDaddy.GoDaddyApplicantConfig{ + applicant, err := pGoDaddy.NewChallengeProvider(&pGoDaddy.ChallengeProviderConfig{ ApiKey: access.ApiKey, ApiSecret: access.ApiSecret, DnsPropagationTimeout: options.DnsPropagationTimeout, @@ -204,7 +204,7 @@ func createApplicant(options *applicantOptions) (challenge.Provider, error) { return nil, fmt.Errorf("failed to populate provider access config: %w", err) } - applicant, err := pHuaweiCloud.NewChallengeProvider(&pHuaweiCloud.HuaweiCloudApplicantConfig{ + applicant, err := pHuaweiCloud.NewChallengeProvider(&pHuaweiCloud.ChallengeProviderConfig{ AccessKeyId: access.AccessKeyId, SecretAccessKey: access.SecretAccessKey, Region: maps.GetValueAsString(options.ProviderApplyConfig, "region"), @@ -221,7 +221,7 @@ func createApplicant(options *applicantOptions) (challenge.Provider, error) { return nil, fmt.Errorf("failed to populate provider access config: %w", err) } - applicant, err := pNameDotCom.NewChallengeProvider(&pNameDotCom.NameDotComApplicantConfig{ + applicant, err := pNameDotCom.NewChallengeProvider(&pNameDotCom.ChallengeProviderConfig{ Username: access.Username, ApiToken: access.ApiToken, DnsPropagationTimeout: options.DnsPropagationTimeout, @@ -237,7 +237,7 @@ func createApplicant(options *applicantOptions) (challenge.Provider, error) { return nil, fmt.Errorf("failed to populate provider access config: %w", err) } - applicant, err := pNameSilo.NewChallengeProvider(&pNameSilo.NameSiloApplicantConfig{ + applicant, err := pNameSilo.NewChallengeProvider(&pNameSilo.ChallengeProviderConfig{ ApiKey: access.ApiKey, DnsPropagationTimeout: options.DnsPropagationTimeout, DnsTTL: options.DnsTTL, @@ -252,7 +252,7 @@ func createApplicant(options *applicantOptions) (challenge.Provider, error) { return nil, fmt.Errorf("failed to populate provider access config: %w", err) } - applicant, err := pNS1.NewChallengeProvider(&pNS1.NS1ApplicantConfig{ + applicant, err := pNS1.NewChallengeProvider(&pNS1.ChallengeProviderConfig{ ApiKey: access.ApiKey, DnsPropagationTimeout: options.DnsPropagationTimeout, DnsTTL: options.DnsTTL, @@ -267,7 +267,7 @@ func createApplicant(options *applicantOptions) (challenge.Provider, error) { return nil, fmt.Errorf("failed to populate provider access config: %w", err) } - applicant, err := pPowerDNS.NewChallengeProvider(&pPowerDNS.PowerDNSApplicantConfig{ + applicant, err := pPowerDNS.NewChallengeProvider(&pPowerDNS.ChallengeProviderConfig{ ApiUrl: access.ApiUrl, ApiKey: access.ApiKey, DnsPropagationTimeout: options.DnsPropagationTimeout, @@ -283,7 +283,7 @@ func createApplicant(options *applicantOptions) (challenge.Provider, error) { return nil, fmt.Errorf("failed to populate provider access config: %w", err) } - applicant, err := pRainYun.NewChallengeProvider(&pRainYun.RainYunApplicantConfig{ + applicant, err := pRainYun.NewChallengeProvider(&pRainYun.ChallengeProviderConfig{ ApiKey: access.ApiKey, DnsPropagationTimeout: options.DnsPropagationTimeout, DnsTTL: options.DnsTTL, @@ -298,7 +298,7 @@ func createApplicant(options *applicantOptions) (challenge.Provider, error) { return nil, fmt.Errorf("failed to populate provider access config: %w", err) } - applicant, err := pTencentCloud.NewChallengeProvider(&pTencentCloud.TencentCloudApplicantConfig{ + applicant, err := pTencentCloud.NewChallengeProvider(&pTencentCloud.ChallengeProviderConfig{ SecretId: access.SecretId, SecretKey: access.SecretKey, DnsPropagationTimeout: options.DnsPropagationTimeout, @@ -314,7 +314,7 @@ func createApplicant(options *applicantOptions) (challenge.Provider, error) { return nil, fmt.Errorf("failed to populate provider access config: %w", err) } - applicant, err := pVolcEngine.NewChallengeProvider(&pVolcEngine.VolcEngineApplicantConfig{ + applicant, err := pVolcEngine.NewChallengeProvider(&pVolcEngine.ChallengeProviderConfig{ AccessKeyId: access.AccessKeyId, SecretAccessKey: access.SecretAccessKey, DnsPropagationTimeout: options.DnsPropagationTimeout, @@ -330,7 +330,7 @@ func createApplicant(options *applicantOptions) (challenge.Provider, error) { return nil, fmt.Errorf("failed to populate provider access config: %w", err) } - applicant, err := pWestcn.NewChallengeProvider(&pWestcn.WestcnApplicantConfig{ + applicant, err := pWestcn.NewChallengeProvider(&pWestcn.ChallengeProviderConfig{ Username: access.Username, ApiPassword: access.ApiPassword, DnsPropagationTimeout: options.DnsPropagationTimeout, diff --git a/internal/deployer/deployer.go b/internal/deployer/deployer.go index e64c8a88..f95442a6 100644 --- a/internal/deployer/deployer.go +++ b/internal/deployer/deployer.go @@ -42,7 +42,7 @@ func NewWithDeployNode(node *domain.WorkflowNode, certdata struct { return nil, fmt.Errorf("failed to unmarshal access config: %w", err) } - deployer, logger, err := createDeployer(&deployerOptions{ + deployer, err := createDeployer(&deployerOptions{ Provider: domain.DeployProviderType(nodeConfig.Provider), ProviderAccessConfig: accessConfig, ProviderDeployConfig: nodeConfig.ProviderConfig, @@ -52,7 +52,7 @@ func NewWithDeployNode(node *domain.WorkflowNode, certdata struct { } return &proxyDeployer{ - logger: logger, + logger: logger.NewNilLogger(), deployer: deployer, deployCertificate: certdata.Certificate, deployPrivateKey: certdata.PrivateKey, diff --git a/internal/deployer/providers.go b/internal/deployer/providers.go index 34e3ef0c..94e7dbf8 100644 --- a/internal/deployer/providers.go +++ b/internal/deployer/providers.go @@ -53,14 +53,11 @@ import ( pVolcEngineLive "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/volcengine-live" pVolcEngineTOS "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/volcengine-tos" pWebhook "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/webhook" - "github.com/usual2970/certimate/internal/pkg/core/logger" "github.com/usual2970/certimate/internal/pkg/utils/maps" "github.com/usual2970/certimate/internal/pkg/utils/slices" ) -func createDeployer(options *deployerOptions) (deployer.Deployer, logger.Logger, error) { - logger := logger.NewDefaultLogger() - +func createDeployer(options *deployerOptions) (deployer.Deployer, error) { /* 注意:如果追加新的常量值,请保持以 ASCII 排序。 NOTICE: If you add new constant, please keep ASCII order. @@ -70,12 +67,12 @@ func createDeployer(options *deployerOptions) (deployer.Deployer, logger.Logger, { access := domain.AccessConfigForAliyun{} if err := maps.Populate(options.ProviderAccessConfig, &access); err != nil { - return nil, nil, fmt.Errorf("failed to populate provider access config: %w", err) + return nil, fmt.Errorf("failed to populate provider access config: %w", err) } switch options.Provider { case domain.DeployProviderTypeAliyunALB: - deployer, err := pAliyunALB.NewWithLogger(&pAliyunALB.AliyunALBDeployerConfig{ + deployer, err := pAliyunALB.NewDeployer(&pAliyunALB.DeployerConfig{ AccessKeyId: access.AccessKeyId, AccessKeySecret: access.AccessKeySecret, Region: maps.GetValueAsString(options.ProviderDeployConfig, "region"), @@ -83,29 +80,29 @@ func createDeployer(options *deployerOptions) (deployer.Deployer, logger.Logger, LoadbalancerId: maps.GetValueAsString(options.ProviderDeployConfig, "loadbalancerId"), ListenerId: maps.GetValueAsString(options.ProviderDeployConfig, "listenerId"), Domain: maps.GetValueAsString(options.ProviderDeployConfig, "domain"), - }, logger) - return deployer, logger, err + }) + return deployer, err case domain.DeployProviderTypeAliyunCASDeploy: - deployer, err := pAliyunCASDeploy.NewWithLogger(&pAliyunCASDeploy.AliyunCASDeployDeployerConfig{ + deployer, err := pAliyunCASDeploy.NewDeployer(&pAliyunCASDeploy.DeployerConfig{ AccessKeyId: access.AccessKeyId, AccessKeySecret: access.AccessKeySecret, Region: maps.GetValueAsString(options.ProviderDeployConfig, "region"), ResourceIds: slices.Filter(strings.Split(maps.GetValueAsString(options.ProviderDeployConfig, "resourceIds"), ";"), func(s string) bool { return s != "" }), ContactIds: slices.Filter(strings.Split(maps.GetValueAsString(options.ProviderDeployConfig, "contactIds"), ";"), func(s string) bool { return s != "" }), - }, logger) - return deployer, logger, err + }) + return deployer, err case domain.DeployProviderTypeAliyunCDN: - deployer, err := pAliyunCDN.NewWithLogger(&pAliyunCDN.AliyunCDNDeployerConfig{ + deployer, err := pAliyunCDN.NewDeployer(&pAliyunCDN.DeployerConfig{ AccessKeyId: access.AccessKeyId, AccessKeySecret: access.AccessKeySecret, Domain: maps.GetValueAsString(options.ProviderDeployConfig, "domain"), - }, logger) - return deployer, logger, err + }) + return deployer, err case domain.DeployProviderTypeAliyunCLB: - deployer, err := pAliyunCLB.NewWithLogger(&pAliyunCLB.AliyunCLBDeployerConfig{ + deployer, err := pAliyunCLB.NewDeployer(&pAliyunCLB.DeployerConfig{ AccessKeyId: access.AccessKeyId, AccessKeySecret: access.AccessKeySecret, Region: maps.GetValueAsString(options.ProviderDeployConfig, "region"), @@ -113,64 +110,64 @@ func createDeployer(options *deployerOptions) (deployer.Deployer, logger.Logger, LoadbalancerId: maps.GetValueAsString(options.ProviderDeployConfig, "loadbalancerId"), ListenerPort: maps.GetValueOrDefaultAsInt32(options.ProviderDeployConfig, "listenerPort", 443), Domain: maps.GetValueAsString(options.ProviderDeployConfig, "domain"), - }, logger) - return deployer, logger, err + }) + return deployer, err case domain.DeployProviderTypeAliyunDCDN: - deployer, err := pAliyunDCDN.NewWithLogger(&pAliyunDCDN.AliyunDCDNDeployerConfig{ + deployer, err := pAliyunDCDN.NewDeployer(&pAliyunDCDN.DeployerConfig{ AccessKeyId: access.AccessKeyId, AccessKeySecret: access.AccessKeySecret, Domain: maps.GetValueAsString(options.ProviderDeployConfig, "domain"), - }, logger) - return deployer, logger, err + }) + return deployer, err case domain.DeployProviderTypeAliyunESA: - deployer, err := pAliyunESA.NewWithLogger(&pAliyunESA.AliyunESADeployerConfig{ + deployer, err := pAliyunESA.NewDeployer(&pAliyunESA.DeployerConfig{ AccessKeyId: access.AccessKeyId, AccessKeySecret: access.AccessKeySecret, Region: maps.GetValueAsString(options.ProviderDeployConfig, "region"), SiteId: maps.GetValueAsInt64(options.ProviderDeployConfig, "siteId"), - }, logger) - return deployer, logger, err + }) + return deployer, err case domain.DeployProviderTypeAliyunLive: - deployer, err := pAliyunLive.NewWithLogger(&pAliyunLive.AliyunLiveDeployerConfig{ + deployer, err := pAliyunLive.NewDeployer(&pAliyunLive.DeployerConfig{ AccessKeyId: access.AccessKeyId, AccessKeySecret: access.AccessKeySecret, Region: maps.GetValueAsString(options.ProviderDeployConfig, "region"), Domain: maps.GetValueAsString(options.ProviderDeployConfig, "domain"), - }, logger) - return deployer, logger, err + }) + return deployer, err case domain.DeployProviderTypeAliyunNLB: - deployer, err := pAliyunNLB.NewWithLogger(&pAliyunNLB.AliyunNLBDeployerConfig{ + deployer, err := pAliyunNLB.NewDeployer(&pAliyunNLB.DeployerConfig{ AccessKeyId: access.AccessKeyId, AccessKeySecret: access.AccessKeySecret, Region: maps.GetValueAsString(options.ProviderDeployConfig, "region"), ResourceType: pAliyunNLB.ResourceType(maps.GetValueAsString(options.ProviderDeployConfig, "resourceType")), LoadbalancerId: maps.GetValueAsString(options.ProviderDeployConfig, "loadbalancerId"), ListenerId: maps.GetValueAsString(options.ProviderDeployConfig, "listenerId"), - }, logger) - return deployer, logger, err + }) + return deployer, err case domain.DeployProviderTypeAliyunOSS: - deployer, err := pAliyunOSS.NewWithLogger(&pAliyunOSS.AliyunOSSDeployerConfig{ + deployer, err := pAliyunOSS.NewDeployer(&pAliyunOSS.DeployerConfig{ AccessKeyId: access.AccessKeyId, AccessKeySecret: access.AccessKeySecret, Region: maps.GetValueAsString(options.ProviderDeployConfig, "region"), Bucket: maps.GetValueAsString(options.ProviderDeployConfig, "bucket"), Domain: maps.GetValueAsString(options.ProviderDeployConfig, "domain"), - }, logger) - return deployer, logger, err + }) + return deployer, err case domain.DeployProviderTypeAliyunWAF: - deployer, err := pAliyunWAF.NewWithLogger(&pAliyunWAF.AliyunWAFDeployerConfig{ + deployer, err := pAliyunWAF.NewDeployer(&pAliyunWAF.DeployerConfig{ AccessKeyId: access.AccessKeyId, AccessKeySecret: access.AccessKeySecret, Region: maps.GetValueAsString(options.ProviderDeployConfig, "region"), InstanceId: maps.GetValueAsString(options.ProviderDeployConfig, "instanceId"), - }, logger) - return deployer, logger, err + }) + return deployer, err default: break @@ -181,18 +178,18 @@ func createDeployer(options *deployerOptions) (deployer.Deployer, logger.Logger, { access := domain.AccessConfigForAWS{} if err := maps.Populate(options.ProviderAccessConfig, &access); err != nil { - return nil, nil, fmt.Errorf("failed to populate provider access config: %w", err) + return nil, fmt.Errorf("failed to populate provider access config: %w", err) } switch options.Provider { case domain.DeployProviderTypeAWSCloudFront: - deployer, err := pAWSCloudFront.NewWithLogger(&pAWSCloudFront.AWSCloudFrontDeployerConfig{ + deployer, err := pAWSCloudFront.NewDeployer(&pAWSCloudFront.DeployerConfig{ AccessKeyId: access.AccessKeyId, SecretAccessKey: access.SecretAccessKey, Region: maps.GetValueAsString(options.ProviderDeployConfig, "region"), DistributionId: maps.GetValueAsString(options.ProviderDeployConfig, "distributionId"), - }, logger) - return deployer, logger, err + }) + return deployer, err default: break @@ -203,17 +200,17 @@ func createDeployer(options *deployerOptions) (deployer.Deployer, logger.Logger, { access := domain.AccessConfigForBaiduCloud{} if err := maps.Populate(options.ProviderAccessConfig, &access); err != nil { - return nil, nil, fmt.Errorf("failed to populate provider access config: %w", err) + return nil, fmt.Errorf("failed to populate provider access config: %w", err) } switch options.Provider { case domain.DeployProviderTypeBaiduCloudCDN: - deployer, err := pBaiduCloudCDN.NewWithLogger(&pBaiduCloudCDN.BaiduCloudCDNDeployerConfig{ + deployer, err := pBaiduCloudCDN.NewDeployer(&pBaiduCloudCDN.DeployerConfig{ AccessKeyId: access.AccessKeyId, SecretAccessKey: access.SecretAccessKey, Domain: maps.GetValueAsString(options.ProviderDeployConfig, "domain"), - }, logger) - return deployer, logger, err + }) + return deployer, err default: break @@ -224,16 +221,16 @@ func createDeployer(options *deployerOptions) (deployer.Deployer, logger.Logger, { access := domain.AccessConfigForBaishan{} if err := maps.Populate(options.ProviderAccessConfig, &access); err != nil { - return nil, nil, fmt.Errorf("failed to populate provider access config: %w", err) + return nil, fmt.Errorf("failed to populate provider access config: %w", err) } switch options.Provider { case domain.DeployProviderTypeBaishanCDN: - deployer, err := pBaishanCDN.NewWithLogger(&pBaishanCDN.BaishanCDNDeployerConfig{ + deployer, err := pBaishanCDN.NewDeployer(&pBaishanCDN.DeployerConfig{ ApiToken: access.ApiToken, Domain: maps.GetValueAsString(options.ProviderDeployConfig, "domain"), - }, logger) - return deployer, logger, err + }) + return deployer, err default: break @@ -244,27 +241,27 @@ func createDeployer(options *deployerOptions) (deployer.Deployer, logger.Logger, { access := domain.AccessConfigForBaotaPanel{} if err := maps.Populate(options.ProviderAccessConfig, &access); err != nil { - return nil, nil, fmt.Errorf("failed to populate provider access config: %w", err) + return nil, fmt.Errorf("failed to populate provider access config: %w", err) } switch options.Provider { case domain.DeployProviderTypeBaotaPanelConsole: - deployer, err := pBaotaPanelConsole.NewWithLogger(&pBaotaPanelConsole.BaotaPanelConsoleDeployerConfig{ + deployer, err := pBaotaPanelConsole.NewDeployer(&pBaotaPanelConsole.DeployerConfig{ ApiUrl: access.ApiUrl, ApiKey: access.ApiKey, AutoRestart: maps.GetValueAsBool(options.ProviderDeployConfig, "autoRestart"), - }, logger) - return deployer, logger, err + }) + return deployer, err case domain.DeployProviderTypeBaotaPanelSite: - deployer, err := pBaotaPanelSite.NewWithLogger(&pBaotaPanelSite.BaotaPanelSiteDeployerConfig{ + deployer, err := pBaotaPanelSite.NewDeployer(&pBaotaPanelSite.DeployerConfig{ ApiUrl: access.ApiUrl, ApiKey: access.ApiKey, SiteType: maps.GetValueOrDefaultAsString(options.ProviderDeployConfig, "siteType", "other"), SiteName: maps.GetValueAsString(options.ProviderDeployConfig, "siteName"), SiteNames: slices.Filter(strings.Split(maps.GetValueAsString(options.ProviderDeployConfig, "siteNames"), ";"), func(s string) bool { return s != "" }), - }, logger) - return deployer, logger, err + }) + return deployer, err default: break @@ -275,17 +272,17 @@ func createDeployer(options *deployerOptions) (deployer.Deployer, logger.Logger, { access := domain.AccessConfigForBytePlus{} if err := maps.Populate(options.ProviderAccessConfig, &access); err != nil { - return nil, nil, fmt.Errorf("failed to populate provider access config: %w", err) + return nil, fmt.Errorf("failed to populate provider access config: %w", err) } switch options.Provider { case domain.DeployProviderTypeBytePlusCDN: - deployer, err := pBytePlusCDN.NewWithLogger(&pBytePlusCDN.BytePlusCDNDeployerConfig{ + deployer, err := pBytePlusCDN.NewDeployer(&pBytePlusCDN.DeployerConfig{ AccessKey: access.AccessKey, SecretKey: access.SecretKey, Domain: maps.GetValueAsString(options.ProviderDeployConfig, "domain"), - }, logger) - return deployer, logger, err + }) + return deployer, err default: break @@ -296,77 +293,77 @@ func createDeployer(options *deployerOptions) (deployer.Deployer, logger.Logger, { access := domain.AccessConfigForCacheFly{} if err := maps.Populate(options.ProviderAccessConfig, &access); err != nil { - return nil, nil, fmt.Errorf("failed to populate provider access config: %w", err) + return nil, fmt.Errorf("failed to populate provider access config: %w", err) } - deployer, err := pCacheFly.NewWithLogger(&pCacheFly.CacheFlyDeployerConfig{ + deployer, err := pCacheFly.NewDeployer(&pCacheFly.DeployerConfig{ ApiToken: access.ApiToken, - }, logger) - return deployer, logger, err + }) + return deployer, err } case domain.DeployProviderTypeCdnfly: { access := domain.AccessConfigForCdnfly{} if err := maps.Populate(options.ProviderAccessConfig, &access); err != nil { - return nil, nil, fmt.Errorf("failed to populate provider access config: %w", err) + return nil, fmt.Errorf("failed to populate provider access config: %w", err) } - deployer, err := pCdnfly.NewWithLogger(&pCdnfly.CdnflyDeployerConfig{ + deployer, err := pCdnfly.NewDeployer(&pCdnfly.DeployerConfig{ ApiUrl: access.ApiUrl, ApiKey: access.ApiKey, ApiSecret: access.ApiSecret, ResourceType: pCdnfly.ResourceType(maps.GetValueAsString(options.ProviderDeployConfig, "resourceType")), SiteId: maps.GetValueAsString(options.ProviderDeployConfig, "siteId"), CertificateId: maps.GetValueAsString(options.ProviderDeployConfig, "certificateId"), - }, logger) - return deployer, logger, err + }) + return deployer, err } case domain.DeployProviderTypeDogeCloudCDN: { access := domain.AccessConfigForDogeCloud{} if err := maps.Populate(options.ProviderAccessConfig, &access); err != nil { - return nil, nil, fmt.Errorf("failed to populate provider access config: %w", err) + return nil, fmt.Errorf("failed to populate provider access config: %w", err) } - deployer, err := pDogeCDN.NewWithLogger(&pDogeCDN.DogeCloudCDNDeployerConfig{ + deployer, err := pDogeCDN.NewDeployer(&pDogeCDN.DeployerConfig{ AccessKey: access.AccessKey, SecretKey: access.SecretKey, Domain: maps.GetValueAsString(options.ProviderDeployConfig, "domain"), - }, logger) - return deployer, logger, err + }) + return deployer, err } case domain.DeployProviderTypeEdgioApplications: { access := domain.AccessConfigForEdgio{} if err := maps.Populate(options.ProviderAccessConfig, &access); err != nil { - return nil, nil, fmt.Errorf("failed to populate provider access config: %w", err) + return nil, fmt.Errorf("failed to populate provider access config: %w", err) } - deployer, err := pEdgioApplications.NewWithLogger(&pEdgioApplications.EdgioApplicationsDeployerConfig{ + deployer, err := pEdgioApplications.NewDeployer(&pEdgioApplications.DeployerConfig{ ClientId: access.ClientId, ClientSecret: access.ClientSecret, EnvironmentId: maps.GetValueAsString(options.ProviderDeployConfig, "environmentId"), - }, logger) - return deployer, logger, err + }) + return deployer, err } case domain.DeployProviderTypeGcoreCDN: { access := domain.AccessConfigForGcore{} if err := maps.Populate(options.ProviderAccessConfig, &access); err != nil { - return nil, nil, fmt.Errorf("failed to populate provider access config: %w", err) + return nil, fmt.Errorf("failed to populate provider access config: %w", err) } switch options.Provider { case domain.DeployProviderTypeGcoreCDN: - deployer, err := pGcoreCDN.NewWithLogger(&pGcoreCDN.GcoreCDNDeployerConfig{ + deployer, err := pGcoreCDN.NewDeployer(&pGcoreCDN.DeployerConfig{ ApiToken: access.ApiToken, ResourceId: maps.GetValueAsInt64(options.ProviderDeployConfig, "resourceId"), - }, logger) - return deployer, logger, err + }) + return deployer, err default: break @@ -377,21 +374,21 @@ func createDeployer(options *deployerOptions) (deployer.Deployer, logger.Logger, { access := domain.AccessConfigForHuaweiCloud{} if err := maps.Populate(options.ProviderAccessConfig, &access); err != nil { - return nil, nil, fmt.Errorf("failed to populate provider access config: %w", err) + return nil, fmt.Errorf("failed to populate provider access config: %w", err) } switch options.Provider { case domain.DeployProviderTypeHuaweiCloudCDN: - deployer, err := pHuaweiCloudCDN.NewWithLogger(&pHuaweiCloudCDN.HuaweiCloudCDNDeployerConfig{ + deployer, err := pHuaweiCloudCDN.NewDeployer(&pHuaweiCloudCDN.DeployerConfig{ AccessKeyId: access.AccessKeyId, SecretAccessKey: access.SecretAccessKey, Region: maps.GetValueAsString(options.ProviderDeployConfig, "region"), Domain: maps.GetValueAsString(options.ProviderDeployConfig, "domain"), - }, logger) - return deployer, logger, err + }) + return deployer, err case domain.DeployProviderTypeHuaweiCloudELB: - deployer, err := pHuaweiCloudELB.NewWithLogger(&pHuaweiCloudELB.HuaweiCloudELBDeployerConfig{ + deployer, err := pHuaweiCloudELB.NewDeployer(&pHuaweiCloudELB.DeployerConfig{ AccessKeyId: access.AccessKeyId, SecretAccessKey: access.SecretAccessKey, Region: maps.GetValueAsString(options.ProviderDeployConfig, "region"), @@ -399,19 +396,19 @@ func createDeployer(options *deployerOptions) (deployer.Deployer, logger.Logger, CertificateId: maps.GetValueAsString(options.ProviderDeployConfig, "certificateId"), LoadbalancerId: maps.GetValueAsString(options.ProviderDeployConfig, "loadbalancerId"), ListenerId: maps.GetValueAsString(options.ProviderDeployConfig, "listenerId"), - }, logger) - return deployer, logger, err + }) + return deployer, err case domain.DeployProviderTypeHuaweiCloudWAF: - deployer, err := pHuaweiCloudWAF.NewWithLogger(&pHuaweiCloudWAF.HuaweiCloudWAFDeployerConfig{ + deployer, err := pHuaweiCloudWAF.NewDeployer(&pHuaweiCloudWAF.DeployerConfig{ AccessKeyId: access.AccessKeyId, SecretAccessKey: access.SecretAccessKey, Region: maps.GetValueAsString(options.ProviderDeployConfig, "region"), ResourceType: pHuaweiCloudWAF.ResourceType(maps.GetValueAsString(options.ProviderDeployConfig, "resourceType")), CertificateId: maps.GetValueAsString(options.ProviderDeployConfig, "certificateId"), Domain: maps.GetValueAsString(options.ProviderDeployConfig, "domain"), - }, logger) - return deployer, logger, err + }) + return deployer, err default: break @@ -420,7 +417,7 @@ func createDeployer(options *deployerOptions) (deployer.Deployer, logger.Logger, case domain.DeployProviderTypeLocal: { - deployer, err := pLocal.NewWithLogger(&pLocal.LocalDeployerConfig{ + deployer, err := pLocal.NewDeployer(&pLocal.DeployerConfig{ ShellEnv: pLocal.ShellEnvType(maps.GetValueAsString(options.ProviderDeployConfig, "shellEnv")), PreCommand: maps.GetValueAsString(options.ProviderDeployConfig, "preCommand"), PostCommand: maps.GetValueAsString(options.ProviderDeployConfig, "postCommand"), @@ -431,52 +428,52 @@ func createDeployer(options *deployerOptions) (deployer.Deployer, logger.Logger, JksAlias: maps.GetValueAsString(options.ProviderDeployConfig, "jksAlias"), JksKeypass: maps.GetValueAsString(options.ProviderDeployConfig, "jksKeypass"), JksStorepass: maps.GetValueAsString(options.ProviderDeployConfig, "jksStorepass"), - }, logger) - return deployer, logger, err + }) + return deployer, err } case domain.DeployProviderTypeKubernetesSecret: { access := domain.AccessConfigForKubernetes{} if err := maps.Populate(options.ProviderAccessConfig, &access); err != nil { - return nil, nil, fmt.Errorf("failed to populate provider access config: %w", err) + return nil, fmt.Errorf("failed to populate provider access config: %w", err) } - deployer, err := pK8sSecret.NewWithLogger(&pK8sSecret.K8sSecretDeployerConfig{ + deployer, err := pK8sSecret.NewDeployer(&pK8sSecret.DeployerConfig{ KubeConfig: access.KubeConfig, Namespace: maps.GetValueOrDefaultAsString(options.ProviderDeployConfig, "namespace", "default"), SecretName: maps.GetValueAsString(options.ProviderDeployConfig, "secretName"), SecretType: maps.GetValueOrDefaultAsString(options.ProviderDeployConfig, "secretType", "kubernetes.io/tls"), SecretDataKeyForCrt: maps.GetValueOrDefaultAsString(options.ProviderDeployConfig, "secretDataKeyForCrt", "tls.crt"), SecretDataKeyForKey: maps.GetValueOrDefaultAsString(options.ProviderDeployConfig, "secretDataKeyForKey", "tls.key"), - }, logger) - return deployer, logger, err + }) + return deployer, err } case domain.DeployProviderTypeQiniuCDN, domain.DeployProviderTypeQiniuPili: { access := domain.AccessConfigForQiniu{} if err := maps.Populate(options.ProviderAccessConfig, &access); err != nil { - return nil, nil, fmt.Errorf("failed to populate provider access config: %w", err) + return nil, fmt.Errorf("failed to populate provider access config: %w", err) } switch options.Provider { case domain.DeployProviderTypeQiniuCDN: - deployer, err := pQiniuCDN.NewWithLogger(&pQiniuCDN.QiniuCDNDeployerConfig{ + deployer, err := pQiniuCDN.NewDeployer(&pQiniuCDN.DeployerConfig{ AccessKey: access.AccessKey, SecretKey: access.SecretKey, Domain: maps.GetValueAsString(options.ProviderDeployConfig, "domain"), - }, logger) - return deployer, logger, err + }) + return deployer, err case domain.DeployProviderTypeQiniuPili: - deployer, err := pQiniuPili.NewWithLogger(&pQiniuPili.QiniuPiliDeployerConfig{ + deployer, err := pQiniuPili.NewDeployer(&pQiniuPili.DeployerConfig{ AccessKey: access.AccessKey, SecretKey: access.SecretKey, Hub: maps.GetValueAsString(options.ProviderDeployConfig, "hub"), Domain: maps.GetValueAsString(options.ProviderDeployConfig, "domain"), - }, logger) - return deployer, logger, err + }) + return deployer, err default: break @@ -487,26 +484,26 @@ func createDeployer(options *deployerOptions) (deployer.Deployer, logger.Logger, { access := domain.AccessConfigForSafeLine{} if err := maps.Populate(options.ProviderAccessConfig, &access); err != nil { - return nil, nil, fmt.Errorf("failed to populate provider access config: %w", err) + return nil, fmt.Errorf("failed to populate provider access config: %w", err) } - deployer, err := pSafeLine.NewWithLogger(&pSafeLine.SafeLineDeployerConfig{ + deployer, err := pSafeLine.NewDeployer(&pSafeLine.DeployerConfig{ ApiUrl: access.ApiUrl, ApiToken: access.ApiToken, ResourceType: pSafeLine.ResourceType(maps.GetValueAsString(options.ProviderDeployConfig, "resourceType")), CertificateId: maps.GetValueAsInt32(options.ProviderDeployConfig, "certificateId"), - }, logger) - return deployer, logger, err + }) + return deployer, err } case domain.DeployProviderTypeSSH: { access := domain.AccessConfigForSSH{} if err := maps.Populate(options.ProviderAccessConfig, &access); err != nil { - return nil, nil, fmt.Errorf("failed to populate provider access config: %w", err) + return nil, fmt.Errorf("failed to populate provider access config: %w", err) } - deployer, err := pSSH.NewWithLogger(&pSSH.SshDeployerConfig{ + deployer, err := pSSH.NewDeployer(&pSSH.DeployerConfig{ SshHost: access.Host, SshPort: access.Port, SshUsername: access.Username, @@ -523,28 +520,28 @@ func createDeployer(options *deployerOptions) (deployer.Deployer, logger.Logger, JksAlias: maps.GetValueAsString(options.ProviderDeployConfig, "jksAlias"), JksKeypass: maps.GetValueAsString(options.ProviderDeployConfig, "jksKeypass"), JksStorepass: maps.GetValueAsString(options.ProviderDeployConfig, "jksStorepass"), - }, logger) - return deployer, logger, err + }) + return deployer, err } case domain.DeployProviderTypeTencentCloudCDN, domain.DeployProviderTypeTencentCloudCLB, domain.DeployProviderTypeTencentCloudCOS, domain.DeployProviderTypeTencentCloudCSS, domain.DeployProviderTypeTencentCloudECDN, domain.DeployProviderTypeTencentCloudEO, domain.DeployProviderTypeTencentCloudSSLDeploy, domain.DeployProviderTypeTencentCloudWAF: { access := domain.AccessConfigForTencentCloud{} if err := maps.Populate(options.ProviderAccessConfig, &access); err != nil { - return nil, nil, fmt.Errorf("failed to populate provider access config: %w", err) + return nil, fmt.Errorf("failed to populate provider access config: %w", err) } switch options.Provider { case domain.DeployProviderTypeTencentCloudCDN: - deployer, err := pTencentCloudCDN.NewWithLogger(&pTencentCloudCDN.TencentCloudCDNDeployerConfig{ + deployer, err := pTencentCloudCDN.NewDeployer(&pTencentCloudCDN.DeployerConfig{ SecretId: access.SecretId, SecretKey: access.SecretKey, Domain: maps.GetValueAsString(options.ProviderDeployConfig, "domain"), - }, logger) - return deployer, logger, err + }) + return deployer, err case domain.DeployProviderTypeTencentCloudCLB: - deployer, err := pTencentCloudCLB.NewWithLogger(&pTencentCloudCLB.TencentCloudCLBDeployerConfig{ + deployer, err := pTencentCloudCLB.NewDeployer(&pTencentCloudCLB.DeployerConfig{ SecretId: access.SecretId, SecretKey: access.SecretKey, Region: maps.GetValueAsString(options.ProviderDeployConfig, "region"), @@ -552,63 +549,63 @@ func createDeployer(options *deployerOptions) (deployer.Deployer, logger.Logger, LoadbalancerId: maps.GetValueAsString(options.ProviderDeployConfig, "loadbalancerId"), ListenerId: maps.GetValueAsString(options.ProviderDeployConfig, "listenerId"), Domain: maps.GetValueAsString(options.ProviderDeployConfig, "domain"), - }, logger) - return deployer, logger, err + }) + return deployer, err case domain.DeployProviderTypeTencentCloudCOS: - deployer, err := pTencentCloudCOS.NewWithLogger(&pTencentCloudCOS.TencentCloudCOSDeployerConfig{ + deployer, err := pTencentCloudCOS.NewDeployer(&pTencentCloudCOS.DeployerConfig{ SecretId: access.SecretId, SecretKey: access.SecretKey, Region: maps.GetValueAsString(options.ProviderDeployConfig, "region"), Bucket: maps.GetValueAsString(options.ProviderDeployConfig, "bucket"), Domain: maps.GetValueAsString(options.ProviderDeployConfig, "domain"), - }, logger) - return deployer, logger, err + }) + return deployer, err case domain.DeployProviderTypeTencentCloudCSS: - deployer, err := pTencentCloudCSS.NewWithLogger(&pTencentCloudCSS.TencentCloudCSSDeployerConfig{ + deployer, err := pTencentCloudCSS.NewDeployer(&pTencentCloudCSS.DeployerConfig{ SecretId: access.SecretId, SecretKey: access.SecretKey, Domain: maps.GetValueAsString(options.ProviderDeployConfig, "domain"), - }, logger) - return deployer, logger, err + }) + return deployer, err case domain.DeployProviderTypeTencentCloudECDN: - deployer, err := pTencentCloudECDN.NewWithLogger(&pTencentCloudECDN.TencentCloudECDNDeployerConfig{ + deployer, err := pTencentCloudECDN.NewDeployer(&pTencentCloudECDN.DeployerConfig{ SecretId: access.SecretId, SecretKey: access.SecretKey, Domain: maps.GetValueAsString(options.ProviderDeployConfig, "domain"), - }, logger) - return deployer, logger, err + }) + return deployer, err case domain.DeployProviderTypeTencentCloudEO: - deployer, err := pTencentCloudEO.NewWithLogger(&pTencentCloudEO.TencentCloudEODeployerConfig{ + deployer, err := pTencentCloudEO.NewDeployer(&pTencentCloudEO.DeployerConfig{ SecretId: access.SecretId, SecretKey: access.SecretKey, ZoneId: maps.GetValueAsString(options.ProviderDeployConfig, "zoneId"), Domain: maps.GetValueAsString(options.ProviderDeployConfig, "domain"), - }, logger) - return deployer, logger, err + }) + return deployer, err case domain.DeployProviderTypeTencentCloudSSLDeploy: - deployer, err := pTencentCloudSSLDeploy.NewWithLogger(&pTencentCloudSSLDeploy.TencentCloudSSLDeployDeployerConfig{ + deployer, err := pTencentCloudSSLDeploy.NewDeployer(&pTencentCloudSSLDeploy.DeployerConfig{ SecretId: access.SecretId, SecretKey: access.SecretKey, Region: maps.GetValueAsString(options.ProviderDeployConfig, "region"), ResourceType: maps.GetValueAsString(options.ProviderDeployConfig, "resourceType"), ResourceIds: slices.Filter(strings.Split(maps.GetValueAsString(options.ProviderDeployConfig, "resourceIds"), ";"), func(s string) bool { return s != "" }), - }, logger) - return deployer, logger, err + }) + return deployer, err case domain.DeployProviderTypeTencentCloudWAF: - deployer, err := pTencentCloudWAF.NewWithLogger(&pTencentCloudWAF.TencentCloudWAFDeployerConfig{ + deployer, err := pTencentCloudWAF.NewDeployer(&pTencentCloudWAF.DeployerConfig{ SecretId: access.SecretId, SecretKey: access.SecretKey, Domain: maps.GetValueAsString(options.ProviderDeployConfig, "domain"), DomainId: maps.GetValueAsString(options.ProviderDeployConfig, "domainId"), InstanceId: maps.GetValueAsString(options.ProviderDeployConfig, "instanceId"), - }, logger) - return deployer, logger, err + }) + return deployer, err default: break @@ -619,29 +616,29 @@ func createDeployer(options *deployerOptions) (deployer.Deployer, logger.Logger, { access := domain.AccessConfigForUCloud{} if err := maps.Populate(options.ProviderAccessConfig, &access); err != nil { - return nil, nil, fmt.Errorf("failed to populate provider access config: %w", err) + return nil, fmt.Errorf("failed to populate provider access config: %w", err) } switch options.Provider { case domain.DeployProviderTypeUCloudUCDN: - deployer, err := pUCloudUCDN.NewWithLogger(&pUCloudUCDN.UCloudUCDNDeployerConfig{ + deployer, err := pUCloudUCDN.NewDeployer(&pUCloudUCDN.DeployerConfig{ PrivateKey: access.PrivateKey, PublicKey: access.PublicKey, ProjectId: access.ProjectId, DomainId: maps.GetValueAsString(options.ProviderDeployConfig, "domainId"), - }, logger) - return deployer, logger, err + }) + return deployer, err case domain.DeployProviderTypeUCloudUS3: - deployer, err := pUCloudUS3.NewWithLogger(&pUCloudUS3.UCloudUS3DeployerConfig{ + deployer, err := pUCloudUS3.NewDeployer(&pUCloudUS3.DeployerConfig{ PrivateKey: access.PrivateKey, PublicKey: access.PublicKey, ProjectId: access.ProjectId, Region: maps.GetValueAsString(options.ProviderDeployConfig, "region"), Bucket: maps.GetValueAsString(options.ProviderDeployConfig, "bucket"), Domain: maps.GetValueAsString(options.ProviderDeployConfig, "domain"), - }, logger) - return deployer, logger, err + }) + return deployer, err default: break @@ -652,63 +649,63 @@ func createDeployer(options *deployerOptions) (deployer.Deployer, logger.Logger, { access := domain.AccessConfigForVolcEngine{} if err := maps.Populate(options.ProviderAccessConfig, &access); err != nil { - return nil, nil, fmt.Errorf("failed to populate provider access config: %w", err) + return nil, fmt.Errorf("failed to populate provider access config: %w", err) } switch options.Provider { case domain.DeployProviderTypeVolcEngineCDN: - deployer, err := pVolcEngineCDN.NewWithLogger(&pVolcEngineCDN.VolcEngineCDNDeployerConfig{ + deployer, err := pVolcEngineCDN.NewDeployer(&pVolcEngineCDN.DeployerConfig{ AccessKeyId: access.AccessKeyId, AccessKeySecret: access.SecretAccessKey, Domain: maps.GetValueAsString(options.ProviderDeployConfig, "domain"), - }, logger) - return deployer, logger, err + }) + return deployer, err case domain.DeployProviderTypeVolcEngineCLB: - deployer, err := pVolcEngineCLB.NewWithLogger(&pVolcEngineCLB.VolcEngineCLBDeployerConfig{ + deployer, err := pVolcEngineCLB.NewDeployer(&pVolcEngineCLB.DeployerConfig{ AccessKeyId: access.AccessKeyId, AccessKeySecret: access.SecretAccessKey, Region: maps.GetValueAsString(options.ProviderDeployConfig, "region"), ResourceType: pVolcEngineCLB.ResourceType(maps.GetValueAsString(options.ProviderDeployConfig, "resourceType")), ListenerId: maps.GetValueAsString(options.ProviderDeployConfig, "listenerId"), - }, logger) - return deployer, logger, err + }) + return deployer, err case domain.DeployProviderTypeVolcEngineDCDN: - deployer, err := pVolcEngineDCDN.NewWithLogger(&pVolcEngineDCDN.VolcEngineDCDNDeployerConfig{ + deployer, err := pVolcEngineDCDN.NewDeployer(&pVolcEngineDCDN.DeployerConfig{ AccessKeyId: access.AccessKeyId, AccessKeySecret: access.SecretAccessKey, Domain: maps.GetValueAsString(options.ProviderDeployConfig, "domain"), - }, logger) - return deployer, logger, err + }) + return deployer, err case domain.DeployProviderTypeVolcEngineImageX: - deployer, err := pVolcEngineImageX.NewWithLogger(&pVolcEngineImageX.VolcEngineImageXDeployerConfig{ + deployer, err := pVolcEngineImageX.NewDeployer(&pVolcEngineImageX.DeployerConfig{ AccessKeyId: access.AccessKeyId, AccessKeySecret: access.SecretAccessKey, Region: maps.GetValueAsString(options.ProviderDeployConfig, "region"), ServiceId: maps.GetValueAsString(options.ProviderDeployConfig, "serviceId"), Domain: maps.GetValueAsString(options.ProviderDeployConfig, "domain"), - }, logger) - return deployer, logger, err + }) + return deployer, err case domain.DeployProviderTypeVolcEngineLive: - deployer, err := pVolcEngineLive.NewWithLogger(&pVolcEngineLive.VolcEngineLiveDeployerConfig{ + deployer, err := pVolcEngineLive.NewDeployer(&pVolcEngineLive.DeployerConfig{ AccessKeyId: access.AccessKeyId, AccessKeySecret: access.SecretAccessKey, Domain: maps.GetValueAsString(options.ProviderDeployConfig, "domain"), - }, logger) - return deployer, logger, err + }) + return deployer, err case domain.DeployProviderTypeVolcEngineTOS: - deployer, err := pVolcEngineTOS.NewWithLogger(&pVolcEngineTOS.VolcEngineTOSDeployerConfig{ + deployer, err := pVolcEngineTOS.NewDeployer(&pVolcEngineTOS.DeployerConfig{ AccessKeyId: access.AccessKeyId, AccessKeySecret: access.SecretAccessKey, Region: maps.GetValueAsString(options.ProviderDeployConfig, "region"), Bucket: maps.GetValueAsString(options.ProviderDeployConfig, "bucket"), Domain: maps.GetValueAsString(options.ProviderDeployConfig, "domain"), - }, logger) - return deployer, logger, err + }) + return deployer, err default: break @@ -719,16 +716,16 @@ func createDeployer(options *deployerOptions) (deployer.Deployer, logger.Logger, { access := domain.AccessConfigForWebhook{} if err := maps.Populate(options.ProviderAccessConfig, &access); err != nil { - return nil, nil, fmt.Errorf("failed to populate provider access config: %w", err) + return nil, fmt.Errorf("failed to populate provider access config: %w", err) } - deployer, err := pWebhook.NewWithLogger(&pWebhook.WebhookDeployerConfig{ + deployer, err := pWebhook.NewDeployer(&pWebhook.DeployerConfig{ WebhookUrl: access.Url, WebhookData: maps.GetValueAsString(options.ProviderDeployConfig, "webhookData"), - }, logger) - return deployer, logger, err + }) + return deployer, err } } - return nil, nil, fmt.Errorf("unsupported deployer provider: %s", string(options.Provider)) + return nil, fmt.Errorf("unsupported deployer provider: %s", string(options.Provider)) } diff --git a/internal/notify/providers.go b/internal/notify/providers.go index 57247b26..6e18a84c 100644 --- a/internal/notify/providers.go +++ b/internal/notify/providers.go @@ -23,19 +23,19 @@ func createNotifier(channel domain.NotifyChannelType, channelConfig map[string]a */ switch channel { case domain.NotifyChannelTypeBark: - return pBark.New(&pBark.BarkNotifierConfig{ + return pBark.NewNotifier(&pBark.NotifierConfig{ DeviceKey: maps.GetValueAsString(channelConfig, "deviceKey"), ServerUrl: maps.GetValueAsString(channelConfig, "serverUrl"), }) case domain.NotifyChannelTypeDingTalk: - return pDingTalk.New(&pDingTalk.DingTalkNotifierConfig{ + return pDingTalk.NewNotifier(&pDingTalk.NotifierConfig{ AccessToken: maps.GetValueAsString(channelConfig, "accessToken"), Secret: maps.GetValueAsString(channelConfig, "secret"), }) case domain.NotifyChannelTypeEmail: - return pEmail.New(&pEmail.EmailNotifierConfig{ + return pEmail.NewNotifier(&pEmail.NotifierConfig{ SmtpHost: maps.GetValueAsString(channelConfig, "smtpHost"), SmtpPort: maps.GetValueAsInt32(channelConfig, "smtpPort"), SmtpTLS: maps.GetValueOrDefaultAsBool(channelConfig, "smtpTLS", true), @@ -46,28 +46,28 @@ func createNotifier(channel domain.NotifyChannelType, channelConfig map[string]a }) case domain.NotifyChannelTypeLark: - return pLark.New(&pLark.LarkNotifierConfig{ + return pLark.NewNotifier(&pLark.NotifierConfig{ WebhookUrl: maps.GetValueAsString(channelConfig, "webhookUrl"), }) case domain.NotifyChannelTypeServerChan: - return pServerChan.New(&pServerChan.ServerChanNotifierConfig{ + return pServerChan.NewNotifier(&pServerChan.NotifierConfig{ Url: maps.GetValueAsString(channelConfig, "url"), }) case domain.NotifyChannelTypeTelegram: - return pTelegram.New(&pTelegram.TelegramNotifierConfig{ + return pTelegram.NewNotifier(&pTelegram.NotifierConfig{ ApiToken: maps.GetValueAsString(channelConfig, "apiToken"), ChatId: maps.GetValueAsInt64(channelConfig, "chatId"), }) case domain.NotifyChannelTypeWebhook: - return pWebhook.New(&pWebhook.WebhookNotifierConfig{ + return pWebhook.NewNotifier(&pWebhook.NotifierConfig{ Url: maps.GetValueAsString(channelConfig, "url"), }) case domain.NotifyChannelTypeWeCom: - return pWeCom.New(&pWeCom.WeComNotifierConfig{ + return pWeCom.NewNotifier(&pWeCom.NotifierConfig{ WebhookUrl: maps.GetValueAsString(channelConfig, "webhookUrl"), }) } diff --git a/internal/pkg/core/applicant/acme-dns-01/lego-providers/acmehttpreq/acmehttpreq.go b/internal/pkg/core/applicant/acme-dns-01/lego-providers/acmehttpreq/acmehttpreq.go index a484b1ca..ab2b11a6 100644 --- a/internal/pkg/core/applicant/acme-dns-01/lego-providers/acmehttpreq/acmehttpreq.go +++ b/internal/pkg/core/applicant/acme-dns-01/lego-providers/acmehttpreq/acmehttpreq.go @@ -8,7 +8,7 @@ import ( "github.com/go-acme/lego/v4/providers/dns/httpreq" ) -type ACMEHttpReqApplicantConfig struct { +type ChallengeProviderConfig struct { Endpoint string `json:"endpoint"` Mode string `json:"mode"` Username string `json:"username"` @@ -16,7 +16,7 @@ type ACMEHttpReqApplicantConfig struct { DnsPropagationTimeout int32 `json:"dnsPropagationTimeout,omitempty"` } -func NewChallengeProvider(config *ACMEHttpReqApplicantConfig) (challenge.Provider, error) { +func NewChallengeProvider(config *ChallengeProviderConfig) (challenge.Provider, error) { if config == nil { panic("config is nil") } diff --git a/internal/pkg/core/applicant/acme-dns-01/lego-providers/aliyun/aliyun.go b/internal/pkg/core/applicant/acme-dns-01/lego-providers/aliyun/aliyun.go index 0f5673f3..8f5cc56b 100644 --- a/internal/pkg/core/applicant/acme-dns-01/lego-providers/aliyun/aliyun.go +++ b/internal/pkg/core/applicant/acme-dns-01/lego-providers/aliyun/aliyun.go @@ -7,14 +7,14 @@ import ( "github.com/go-acme/lego/v4/providers/dns/alidns" ) -type AliyunApplicantConfig struct { +type ChallengeProviderConfig struct { AccessKeyId string `json:"accessKeyId"` AccessKeySecret string `json:"accessKeySecret"` DnsPropagationTimeout int32 `json:"dnsPropagationTimeout,omitempty"` DnsTTL int32 `json:"dnsTTL,omitempty"` } -func NewChallengeProvider(config *AliyunApplicantConfig) (challenge.Provider, error) { +func NewChallengeProvider(config *ChallengeProviderConfig) (challenge.Provider, error) { if config == nil { panic("config is nil") } diff --git a/internal/pkg/core/applicant/acme-dns-01/lego-providers/aws-route53/aws-route53.go b/internal/pkg/core/applicant/acme-dns-01/lego-providers/aws-route53/aws-route53.go index cf6af901..be1cfecf 100644 --- a/internal/pkg/core/applicant/acme-dns-01/lego-providers/aws-route53/aws-route53.go +++ b/internal/pkg/core/applicant/acme-dns-01/lego-providers/aws-route53/aws-route53.go @@ -7,7 +7,7 @@ import ( "github.com/go-acme/lego/v4/providers/dns/route53" ) -type AWSRoute53ApplicantConfig struct { +type ChallengeProviderConfig struct { AccessKeyId string `json:"accessKeyId"` SecretAccessKey string `json:"secretAccessKey"` Region string `json:"region"` @@ -16,7 +16,7 @@ type AWSRoute53ApplicantConfig struct { DnsTTL int32 `json:"dnsTTL,omitempty"` } -func NewChallengeProvider(config *AWSRoute53ApplicantConfig) (challenge.Provider, error) { +func NewChallengeProvider(config *ChallengeProviderConfig) (challenge.Provider, error) { if config == nil { panic("config is nil") } diff --git a/internal/pkg/core/applicant/acme-dns-01/lego-providers/azure-dns/azure-dns.go b/internal/pkg/core/applicant/acme-dns-01/lego-providers/azure-dns/azure-dns.go index 858d937a..bf36f3fb 100644 --- a/internal/pkg/core/applicant/acme-dns-01/lego-providers/azure-dns/azure-dns.go +++ b/internal/pkg/core/applicant/acme-dns-01/lego-providers/azure-dns/azure-dns.go @@ -10,7 +10,7 @@ import ( "github.com/go-acme/lego/v4/providers/dns/azuredns" ) -type AzureDNSApplicantConfig struct { +type ChallengeProviderConfig struct { TenantId string `json:"tenantId"` ClientId string `json:"clientId"` ClientSecret string `json:"clientSecret"` @@ -19,7 +19,7 @@ type AzureDNSApplicantConfig struct { DnsTTL int32 `json:"dnsTTL,omitempty"` } -func NewChallengeProvider(config *AzureDNSApplicantConfig) (challenge.Provider, error) { +func NewChallengeProvider(config *ChallengeProviderConfig) (challenge.Provider, error) { if config == nil { panic("config is nil") } diff --git a/internal/pkg/core/applicant/acme-dns-01/lego-providers/baiducloud/baiducloud.go b/internal/pkg/core/applicant/acme-dns-01/lego-providers/baiducloud/baiducloud.go index 1328009a..ac63665e 100644 --- a/internal/pkg/core/applicant/acme-dns-01/lego-providers/baiducloud/baiducloud.go +++ b/internal/pkg/core/applicant/acme-dns-01/lego-providers/baiducloud/baiducloud.go @@ -8,14 +8,14 @@ import ( internal "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/baiducloud/internal" ) -type BaiduCloudApplicantConfig struct { +type ChallengeProviderConfig struct { AccessKeyId string `json:"accessKeyId"` SecretAccessKey string `json:"secretAccessKey"` DnsPropagationTimeout int32 `json:"dnsPropagationTimeout,omitempty"` DnsTTL int32 `json:"dnsTTL,omitempty"` } -func NewChallengeProvider(config *BaiduCloudApplicantConfig) (challenge.Provider, error) { +func NewChallengeProvider(config *ChallengeProviderConfig) (challenge.Provider, error) { if config == nil { panic("config is nil") } diff --git a/internal/pkg/core/applicant/acme-dns-01/lego-providers/cloudflare/cloudflare.go b/internal/pkg/core/applicant/acme-dns-01/lego-providers/cloudflare/cloudflare.go index de8edbcd..9782b39b 100644 --- a/internal/pkg/core/applicant/acme-dns-01/lego-providers/cloudflare/cloudflare.go +++ b/internal/pkg/core/applicant/acme-dns-01/lego-providers/cloudflare/cloudflare.go @@ -7,13 +7,13 @@ import ( "github.com/go-acme/lego/v4/providers/dns/cloudflare" ) -type CloudflareApplicantConfig struct { +type ChallengeProviderConfig struct { DnsApiToken string `json:"dnsApiToken"` DnsPropagationTimeout int32 `json:"dnsPropagationTimeout,omitempty"` DnsTTL int32 `json:"dnsTTL,omitempty"` } -func NewChallengeProvider(config *CloudflareApplicantConfig) (challenge.Provider, error) { +func NewChallengeProvider(config *ChallengeProviderConfig) (challenge.Provider, error) { if config == nil { panic("config is nil") } diff --git a/internal/pkg/core/applicant/acme-dns-01/lego-providers/cloudns/cloudns.go b/internal/pkg/core/applicant/acme-dns-01/lego-providers/cloudns/cloudns.go index acde9ee7..dc351bd3 100644 --- a/internal/pkg/core/applicant/acme-dns-01/lego-providers/cloudns/cloudns.go +++ b/internal/pkg/core/applicant/acme-dns-01/lego-providers/cloudns/cloudns.go @@ -7,14 +7,14 @@ import ( "github.com/go-acme/lego/v4/providers/dns/cloudns" ) -type ClouDNSApplicantConfig struct { +type ChallengeProviderConfig struct { AuthId string `json:"authId"` AuthPassword string `json:"authPassword"` DnsPropagationTimeout int32 `json:"dnsPropagationTimeout,omitempty"` DnsTTL int32 `json:"dnsTTL,omitempty"` } -func NewChallengeProvider(config *ClouDNSApplicantConfig) (challenge.Provider, error) { +func NewChallengeProvider(config *ChallengeProviderConfig) (challenge.Provider, error) { if config == nil { panic("config is nil") } diff --git a/internal/pkg/core/applicant/acme-dns-01/lego-providers/gcore/gcore.go b/internal/pkg/core/applicant/acme-dns-01/lego-providers/gcore/gcore.go index 652d7550..ac9f7e61 100644 --- a/internal/pkg/core/applicant/acme-dns-01/lego-providers/gcore/gcore.go +++ b/internal/pkg/core/applicant/acme-dns-01/lego-providers/gcore/gcore.go @@ -7,13 +7,13 @@ import ( "github.com/go-acme/lego/v4/providers/dns/gcore" ) -type GcoreApplicantConfig struct { +type ChallengeProviderConfig struct { ApiToken string `json:"apiToken"` DnsPropagationTimeout int32 `json:"dnsPropagationTimeout,omitempty"` DnsTTL int32 `json:"dnsTTL,omitempty"` } -func NewChallengeProvider(config *GcoreApplicantConfig) (challenge.Provider, error) { +func NewChallengeProvider(config *ChallengeProviderConfig) (challenge.Provider, error) { if config == nil { panic("config is nil") } diff --git a/internal/pkg/core/applicant/acme-dns-01/lego-providers/gname/gname.go b/internal/pkg/core/applicant/acme-dns-01/lego-providers/gname/gname.go index 2f9d2443..42057149 100644 --- a/internal/pkg/core/applicant/acme-dns-01/lego-providers/gname/gname.go +++ b/internal/pkg/core/applicant/acme-dns-01/lego-providers/gname/gname.go @@ -8,14 +8,14 @@ import ( internal "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/gname/internal" ) -type GnameApplicantConfig struct { +type ChallengeProviderConfig struct { AppId string `json:"appId"` AppKey string `json:"appKey"` DnsPropagationTimeout int32 `json:"dnsPropagationTimeout,omitempty"` DnsTTL int32 `json:"dnsTTL,omitempty"` } -func NewChallengeProvider(config *GnameApplicantConfig) (challenge.Provider, error) { +func NewChallengeProvider(config *ChallengeProviderConfig) (challenge.Provider, error) { if config == nil { panic("config is nil") } diff --git a/internal/pkg/core/applicant/acme-dns-01/lego-providers/godaddy/godaddy.go b/internal/pkg/core/applicant/acme-dns-01/lego-providers/godaddy/godaddy.go index 433390ed..957c9185 100644 --- a/internal/pkg/core/applicant/acme-dns-01/lego-providers/godaddy/godaddy.go +++ b/internal/pkg/core/applicant/acme-dns-01/lego-providers/godaddy/godaddy.go @@ -7,14 +7,14 @@ import ( "github.com/go-acme/lego/v4/providers/dns/godaddy" ) -type GoDaddyApplicantConfig struct { +type ChallengeProviderConfig struct { ApiKey string `json:"apiKey"` ApiSecret string `json:"apiSecret"` DnsPropagationTimeout int32 `json:"dnsPropagationTimeout,omitempty"` DnsTTL int32 `json:"dnsTTL,omitempty"` } -func NewChallengeProvider(config *GoDaddyApplicantConfig) (challenge.Provider, error) { +func NewChallengeProvider(config *ChallengeProviderConfig) (challenge.Provider, error) { if config == nil { panic("config is nil") } diff --git a/internal/pkg/core/applicant/acme-dns-01/lego-providers/huaweicloud/huaweicloud.go b/internal/pkg/core/applicant/acme-dns-01/lego-providers/huaweicloud/huaweicloud.go index 72c0a12c..08a629fc 100644 --- a/internal/pkg/core/applicant/acme-dns-01/lego-providers/huaweicloud/huaweicloud.go +++ b/internal/pkg/core/applicant/acme-dns-01/lego-providers/huaweicloud/huaweicloud.go @@ -7,7 +7,7 @@ import ( hwc "github.com/go-acme/lego/v4/providers/dns/huaweicloud" ) -type HuaweiCloudApplicantConfig struct { +type ChallengeProviderConfig struct { AccessKeyId string `json:"accessKeyId"` SecretAccessKey string `json:"secretAccessKey"` Region string `json:"region"` @@ -15,7 +15,7 @@ type HuaweiCloudApplicantConfig struct { DnsTTL int32 `json:"dnsTTL,omitempty"` } -func NewChallengeProvider(config *HuaweiCloudApplicantConfig) (challenge.Provider, error) { +func NewChallengeProvider(config *ChallengeProviderConfig) (challenge.Provider, error) { if config == nil { panic("config is nil") } diff --git a/internal/pkg/core/applicant/acme-dns-01/lego-providers/namedotcom/namedotcom.go b/internal/pkg/core/applicant/acme-dns-01/lego-providers/namedotcom/namedotcom.go index d7b98d85..daff3612 100644 --- a/internal/pkg/core/applicant/acme-dns-01/lego-providers/namedotcom/namedotcom.go +++ b/internal/pkg/core/applicant/acme-dns-01/lego-providers/namedotcom/namedotcom.go @@ -7,14 +7,14 @@ import ( "github.com/go-acme/lego/v4/providers/dns/namedotcom" ) -type NameDotComApplicantConfig struct { +type ChallengeProviderConfig struct { Username string `json:"username"` ApiToken string `json:"apiToken"` DnsPropagationTimeout int32 `json:"dnsPropagationTimeout,omitempty"` DnsTTL int32 `json:"dnsTTL,omitempty"` } -func NewChallengeProvider(config *NameDotComApplicantConfig) (challenge.Provider, error) { +func NewChallengeProvider(config *ChallengeProviderConfig) (challenge.Provider, error) { if config == nil { panic("config is nil") } diff --git a/internal/pkg/core/applicant/acme-dns-01/lego-providers/namesilo/namesilo.go b/internal/pkg/core/applicant/acme-dns-01/lego-providers/namesilo/namesilo.go index c2c0618b..5656136b 100644 --- a/internal/pkg/core/applicant/acme-dns-01/lego-providers/namesilo/namesilo.go +++ b/internal/pkg/core/applicant/acme-dns-01/lego-providers/namesilo/namesilo.go @@ -7,13 +7,13 @@ import ( "github.com/go-acme/lego/v4/providers/dns/namesilo" ) -type NameSiloApplicantConfig struct { +type ChallengeProviderConfig struct { ApiKey string `json:"apiKey"` DnsPropagationTimeout int32 `json:"dnsPropagationTimeout,omitempty"` DnsTTL int32 `json:"dnsTTL,omitempty"` } -func NewChallengeProvider(config *NameSiloApplicantConfig) (challenge.Provider, error) { +func NewChallengeProvider(config *ChallengeProviderConfig) (challenge.Provider, error) { if config == nil { panic("config is nil") } diff --git a/internal/pkg/core/applicant/acme-dns-01/lego-providers/ns1/ns1.go b/internal/pkg/core/applicant/acme-dns-01/lego-providers/ns1/ns1.go index cf2f2c40..1682e0c2 100644 --- a/internal/pkg/core/applicant/acme-dns-01/lego-providers/ns1/ns1.go +++ b/internal/pkg/core/applicant/acme-dns-01/lego-providers/ns1/ns1.go @@ -7,13 +7,13 @@ import ( "github.com/go-acme/lego/v4/providers/dns/ns1" ) -type NS1ApplicantConfig struct { +type ChallengeProviderConfig struct { ApiKey string `json:"apiKey"` DnsPropagationTimeout int32 `json:"dnsPropagationTimeout,omitempty"` DnsTTL int32 `json:"dnsTTL,omitempty"` } -func NewChallengeProvider(config *NS1ApplicantConfig) (challenge.Provider, error) { +func NewChallengeProvider(config *ChallengeProviderConfig) (challenge.Provider, error) { if config == nil { panic("config is nil") } diff --git a/internal/pkg/core/applicant/acme-dns-01/lego-providers/powerdns/powerdns.go b/internal/pkg/core/applicant/acme-dns-01/lego-providers/powerdns/powerdns.go index 9969b002..3dc86d66 100644 --- a/internal/pkg/core/applicant/acme-dns-01/lego-providers/powerdns/powerdns.go +++ b/internal/pkg/core/applicant/acme-dns-01/lego-providers/powerdns/powerdns.go @@ -8,14 +8,14 @@ import ( "github.com/go-acme/lego/v4/providers/dns/pdns" ) -type PowerDNSApplicantConfig struct { +type ChallengeProviderConfig struct { ApiUrl string `json:"apiUrl"` ApiKey string `json:"apiKey"` DnsPropagationTimeout int32 `json:"dnsPropagationTimeout,omitempty"` DnsTTL int32 `json:"dnsTTL,omitempty"` } -func NewChallengeProvider(config *PowerDNSApplicantConfig) (challenge.Provider, error) { +func NewChallengeProvider(config *ChallengeProviderConfig) (challenge.Provider, error) { if config == nil { panic("config is nil") } diff --git a/internal/pkg/core/applicant/acme-dns-01/lego-providers/rainyun/rainyun.go b/internal/pkg/core/applicant/acme-dns-01/lego-providers/rainyun/rainyun.go index eef887d2..2deda0f1 100644 --- a/internal/pkg/core/applicant/acme-dns-01/lego-providers/rainyun/rainyun.go +++ b/internal/pkg/core/applicant/acme-dns-01/lego-providers/rainyun/rainyun.go @@ -7,13 +7,13 @@ import ( "github.com/go-acme/lego/v4/providers/dns/rainyun" ) -type RainYunApplicantConfig struct { +type ChallengeProviderConfig struct { ApiKey string `json:"apiKey"` DnsPropagationTimeout int32 `json:"dnsPropagationTimeout,omitempty"` DnsTTL int32 `json:"dnsTTL,omitempty"` } -func NewChallengeProvider(config *RainYunApplicantConfig) (challenge.Provider, error) { +func NewChallengeProvider(config *ChallengeProviderConfig) (challenge.Provider, error) { if config == nil { panic("config is nil") } diff --git a/internal/pkg/core/applicant/acme-dns-01/lego-providers/tencentcloud/tencentcloud.go b/internal/pkg/core/applicant/acme-dns-01/lego-providers/tencentcloud/tencentcloud.go index 0e60328f..8ef3760c 100644 --- a/internal/pkg/core/applicant/acme-dns-01/lego-providers/tencentcloud/tencentcloud.go +++ b/internal/pkg/core/applicant/acme-dns-01/lego-providers/tencentcloud/tencentcloud.go @@ -7,14 +7,14 @@ import ( "github.com/go-acme/lego/v4/providers/dns/tencentcloud" ) -type TencentCloudApplicantConfig struct { +type ChallengeProviderConfig struct { SecretId string `json:"secretId"` SecretKey string `json:"secretKey"` DnsPropagationTimeout int32 `json:"dnsPropagationTimeout,omitempty"` DnsTTL int32 `json:"dnsTTL,omitempty"` } -func NewChallengeProvider(config *TencentCloudApplicantConfig) (challenge.Provider, error) { +func NewChallengeProvider(config *ChallengeProviderConfig) (challenge.Provider, error) { if config == nil { panic("config is nil") } diff --git a/internal/pkg/core/applicant/acme-dns-01/lego-providers/volcengine/volcengine.go b/internal/pkg/core/applicant/acme-dns-01/lego-providers/volcengine/volcengine.go index dfeddccd..e0a1ae91 100644 --- a/internal/pkg/core/applicant/acme-dns-01/lego-providers/volcengine/volcengine.go +++ b/internal/pkg/core/applicant/acme-dns-01/lego-providers/volcengine/volcengine.go @@ -7,14 +7,14 @@ import ( "github.com/go-acme/lego/v4/providers/dns/volcengine" ) -type VolcEngineApplicantConfig struct { +type ChallengeProviderConfig struct { AccessKeyId string `json:"accessKeyId"` SecretAccessKey string `json:"secretAccessKey"` DnsPropagationTimeout int32 `json:"dnsPropagationTimeout,omitempty"` DnsTTL int32 `json:"dnsTTL,omitempty"` } -func NewChallengeProvider(config *VolcEngineApplicantConfig) (challenge.Provider, error) { +func NewChallengeProvider(config *ChallengeProviderConfig) (challenge.Provider, error) { if config == nil { panic("config is nil") } diff --git a/internal/pkg/core/applicant/acme-dns-01/lego-providers/westcn/westcn.go b/internal/pkg/core/applicant/acme-dns-01/lego-providers/westcn/westcn.go index d7b26afd..f79c5a8c 100644 --- a/internal/pkg/core/applicant/acme-dns-01/lego-providers/westcn/westcn.go +++ b/internal/pkg/core/applicant/acme-dns-01/lego-providers/westcn/westcn.go @@ -7,14 +7,14 @@ import ( "github.com/go-acme/lego/v4/providers/dns/westcn" ) -type WestcnApplicantConfig struct { +type ChallengeProviderConfig struct { Username string `json:"username"` ApiPassword string `json:"apiPassword"` DnsPropagationTimeout int32 `json:"dnsPropagationTimeout,omitempty"` DnsTTL int32 `json:"dnsTTL,omitempty"` } -func NewChallengeProvider(config *WestcnApplicantConfig) (challenge.Provider, error) { +func NewChallengeProvider(config *ChallengeProviderConfig) (challenge.Provider, error) { if config == nil { panic("config is nil") } diff --git a/internal/pkg/core/deployer/providers/aliyun-alb/aliyun_alb.go b/internal/pkg/core/deployer/providers/aliyun-alb/aliyun_alb.go index e81975ee..dc2f1f3c 100644 --- a/internal/pkg/core/deployer/providers/aliyun-alb/aliyun_alb.go +++ b/internal/pkg/core/deployer/providers/aliyun-alb/aliyun_alb.go @@ -21,7 +21,7 @@ import ( uploadersp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/aliyun-cas" ) -type AliyunALBDeployerConfig struct { +type DeployerConfig struct { // 阿里云 AccessKeyId。 AccessKeyId string `json:"accessKeyId"` // 阿里云 AccessKeySecret。 @@ -41,33 +41,25 @@ type AliyunALBDeployerConfig struct { Domain string `json:"domain,omitempty"` } -type AliyunALBDeployer struct { - config *AliyunALBDeployerConfig +type DeployerProvider struct { + config *DeployerConfig logger logger.Logger sdkClients *wSdkClients sslUploader uploader.Uploader } -var _ deployer.Deployer = (*AliyunALBDeployer)(nil) +var _ deployer.Deployer = (*DeployerProvider)(nil) type wSdkClients struct { alb *aliyunAlb.Client cas *aliyunCas.Client } -func New(config *AliyunALBDeployerConfig) (*AliyunALBDeployer, error) { - return NewWithLogger(config, logger.NewNilLogger()) -} - -func NewWithLogger(config *AliyunALBDeployerConfig, logger logger.Logger) (*AliyunALBDeployer, error) { +func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { if config == nil { panic("config is nil") } - if logger == nil { - panic("logger is nil") - } - clients, err := createSdkClients(config.AccessKeyId, config.AccessKeySecret, config.Region) if err != nil { return nil, xerrors.Wrap(err, "failed to create sdk clients") @@ -78,15 +70,20 @@ func NewWithLogger(config *AliyunALBDeployerConfig, logger logger.Logger) (*Aliy return nil, xerrors.Wrap(err, "failed to create ssl uploader") } - return &AliyunALBDeployer{ - logger: logger, + return &DeployerProvider{ config: config, + logger: logger.NewNilLogger(), sdkClients: clients, sslUploader: uploader, }, nil } -func (d *AliyunALBDeployer) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { +func (d *DeployerProvider) WithLogger(logger logger.Logger) *DeployerProvider { + d.logger = logger + return d +} + +func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { // 上传证书到 CAS upres, err := d.sslUploader.Upload(ctx, certPem, privkeyPem) if err != nil { @@ -114,7 +111,7 @@ func (d *AliyunALBDeployer) Deploy(ctx context.Context, certPem string, privkeyP return &deployer.DeployResult{}, nil } -func (d *AliyunALBDeployer) deployToLoadbalancer(ctx context.Context, cloudCertId string) error { +func (d *DeployerProvider) deployToLoadbalancer(ctx context.Context, cloudCertId string) error { if d.config.LoadbalancerId == "" { return errors.New("config `loadbalancerId` is required") } @@ -213,7 +210,7 @@ func (d *AliyunALBDeployer) deployToLoadbalancer(ctx context.Context, cloudCertI return nil } -func (d *AliyunALBDeployer) deployToListener(ctx context.Context, cloudCertId string) error { +func (d *DeployerProvider) deployToListener(ctx context.Context, cloudCertId string) error { if d.config.ListenerId == "" { return errors.New("config `listenerId` is required") } @@ -226,7 +223,7 @@ func (d *AliyunALBDeployer) deployToListener(ctx context.Context, cloudCertId st return nil } -func (d *AliyunALBDeployer) updateListenerCertificate(ctx context.Context, cloudListenerId string, cloudCertId string) error { +func (d *DeployerProvider) updateListenerCertificate(ctx context.Context, cloudListenerId string, cloudCertId string) error { // 查询监听的属性 // REF: https://help.aliyun.com/zh/slb/application-load-balancer/developer-reference/api-alb-2020-06-16-getlistenerattribute getListenerAttributeReq := &aliyunAlb.GetListenerAttributeRequest{ diff --git a/internal/pkg/core/deployer/providers/aliyun-alb/aliyun_alb_test.go b/internal/pkg/core/deployer/providers/aliyun-alb/aliyun_alb_test.go index ceeea881..b5ae776a 100644 --- a/internal/pkg/core/deployer/providers/aliyun-alb/aliyun_alb_test.go +++ b/internal/pkg/core/deployer/providers/aliyun-alb/aliyun_alb_test.go @@ -63,7 +63,7 @@ func TestDeploy(t *testing.T) { fmt.Sprintf("DOMAIN: %v", fDomain), }, "\n")) - deployer, err := provider.New(&provider.AliyunALBDeployerConfig{ + deployer, err := provider.NewDeployer(&provider.DeployerConfig{ AccessKeyId: fAccessKeyId, AccessKeySecret: fAccessKeySecret, Region: fRegion, @@ -98,7 +98,7 @@ func TestDeploy(t *testing.T) { fmt.Sprintf("LISTENERID: %v", fListenerId), }, "\n")) - deployer, err := provider.New(&provider.AliyunALBDeployerConfig{ + deployer, err := provider.NewDeployer(&provider.DeployerConfig{ AccessKeyId: fAccessKeyId, AccessKeySecret: fAccessKeySecret, Region: fRegion, diff --git a/internal/pkg/core/deployer/providers/aliyun-cas-deploy/aliyun_cas_deploy.go b/internal/pkg/core/deployer/providers/aliyun-cas-deploy/aliyun_cas_deploy.go index fb35364a..2f86adf0 100644 --- a/internal/pkg/core/deployer/providers/aliyun-cas-deploy/aliyun_cas_deploy.go +++ b/internal/pkg/core/deployer/providers/aliyun-cas-deploy/aliyun_cas_deploy.go @@ -18,7 +18,7 @@ import ( uploadersp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/aliyun-cas" ) -type AliyunCASDeployDeployerConfig struct { +type DeployerConfig struct { // 阿里云 AccessKeyId。 AccessKeyId string `json:"accessKeyId"` // 阿里云 AccessKeySecret。 @@ -32,28 +32,20 @@ type AliyunCASDeployDeployerConfig struct { ContactIds []string `json:"contactIds"` } -type AliyunCASDeployDeployer struct { - config *AliyunCASDeployDeployerConfig +type DeployerProvider struct { + config *DeployerConfig logger logger.Logger sdkClient *aliyunCas.Client sslUploader uploader.Uploader } -var _ deployer.Deployer = (*AliyunCASDeployDeployer)(nil) +var _ deployer.Deployer = (*DeployerProvider)(nil) -func New(config *AliyunCASDeployDeployerConfig) (*AliyunCASDeployDeployer, error) { - return NewWithLogger(config, logger.NewNilLogger()) -} - -func NewWithLogger(config *AliyunCASDeployDeployerConfig, logger logger.Logger) (*AliyunCASDeployDeployer, error) { +func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { if config == nil { panic("config is nil") } - if logger == nil { - panic("logger is nil") - } - client, err := createSdkClient(config.AccessKeyId, config.AccessKeySecret, config.Region) if err != nil { return nil, xerrors.Wrap(err, "failed to create sdk client") @@ -64,15 +56,20 @@ func NewWithLogger(config *AliyunCASDeployDeployerConfig, logger logger.Logger) return nil, xerrors.Wrap(err, "failed to create ssl uploader") } - return &AliyunCASDeployDeployer{ - logger: logger, + return &DeployerProvider{ config: config, + logger: logger.NewNilLogger(), sdkClient: client, sslUploader: uploader, }, nil } -func (d *AliyunCASDeployDeployer) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { +func (d *DeployerProvider) WithLogger(logger logger.Logger) *DeployerProvider { + d.logger = logger + return d +} + +func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { if len(d.config.ResourceIds) == 0 { return nil, errors.New("config `resourceIds` is required") } diff --git a/internal/pkg/core/deployer/providers/aliyun-cdn/aliyun_cdn.go b/internal/pkg/core/deployer/providers/aliyun-cdn/aliyun_cdn.go index df188523..b0edd415 100644 --- a/internal/pkg/core/deployer/providers/aliyun-cdn/aliyun_cdn.go +++ b/internal/pkg/core/deployer/providers/aliyun-cdn/aliyun_cdn.go @@ -15,7 +15,7 @@ import ( "github.com/usual2970/certimate/internal/pkg/core/logger" ) -type AliyunCDNDeployerConfig struct { +type DeployerConfig struct { // 阿里云 AccessKeyId。 AccessKeyId string `json:"accessKeyId"` // 阿里云 AccessKeySecret。 @@ -24,40 +24,37 @@ type AliyunCDNDeployerConfig struct { Domain string `json:"domain"` } -type AliyunCDNDeployer struct { - config *AliyunCDNDeployerConfig +type DeployerProvider struct { + config *DeployerConfig logger logger.Logger sdkClient *aliyunCdn.Client } -var _ deployer.Deployer = (*AliyunCDNDeployer)(nil) +var _ deployer.Deployer = (*DeployerProvider)(nil) -func New(config *AliyunCDNDeployerConfig) (*AliyunCDNDeployer, error) { - return NewWithLogger(config, logger.NewNilLogger()) -} - -func NewWithLogger(config *AliyunCDNDeployerConfig, logger logger.Logger) (*AliyunCDNDeployer, error) { +func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { if config == nil { panic("config is nil") } - if logger == nil { - panic("logger is nil") - } - client, err := createSdkClient(config.AccessKeyId, config.AccessKeySecret) if err != nil { return nil, xerrors.Wrap(err, "failed to create sdk client") } - return &AliyunCDNDeployer{ - logger: logger, + return &DeployerProvider{ config: config, + logger: logger.NewNilLogger(), sdkClient: client, }, nil } -func (d *AliyunCDNDeployer) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { +func (d *DeployerProvider) WithLogger(logger logger.Logger) *DeployerProvider { + d.logger = logger + return d +} + +func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { // "*.example.com" → ".example.com",适配阿里云 CDN 要求的泛域名格式 domain := strings.TrimPrefix(d.config.Domain, "*") diff --git a/internal/pkg/core/deployer/providers/aliyun-cdn/aliyun_cdn_test.go b/internal/pkg/core/deployer/providers/aliyun-cdn/aliyun_cdn_test.go index da4d1d74..1f92947f 100644 --- a/internal/pkg/core/deployer/providers/aliyun-cdn/aliyun_cdn_test.go +++ b/internal/pkg/core/deployer/providers/aliyun-cdn/aliyun_cdn_test.go @@ -52,7 +52,7 @@ func TestDeploy(t *testing.T) { fmt.Sprintf("DOMAIN: %v", fDomain), }, "\n")) - deployer, err := provider.New(&provider.AliyunCDNDeployerConfig{ + deployer, err := provider.NewDeployer(&provider.DeployerConfig{ AccessKeyId: fAccessKeyId, AccessKeySecret: fAccessKeySecret, Domain: fDomain, diff --git a/internal/pkg/core/deployer/providers/aliyun-clb/aliyun_clb.go b/internal/pkg/core/deployer/providers/aliyun-clb/aliyun_clb.go index f344d1b6..151276b7 100644 --- a/internal/pkg/core/deployer/providers/aliyun-clb/aliyun_clb.go +++ b/internal/pkg/core/deployer/providers/aliyun-clb/aliyun_clb.go @@ -16,7 +16,7 @@ import ( uploadersp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/aliyun-slb" ) -type AliyunCLBDeployerConfig struct { +type DeployerConfig struct { // 阿里云 AccessKeyId。 AccessKeyId string `json:"accessKeyId"` // 阿里云 AccessKeySecret。 @@ -36,28 +36,20 @@ type AliyunCLBDeployerConfig struct { Domain string `json:"domain,omitempty"` } -type AliyunCLBDeployer struct { - config *AliyunCLBDeployerConfig +type DeployerProvider struct { + config *DeployerConfig logger logger.Logger sdkClient *aliyunSlb.Client sslUploader uploader.Uploader } -var _ deployer.Deployer = (*AliyunCLBDeployer)(nil) +var _ deployer.Deployer = (*DeployerProvider)(nil) -func New(config *AliyunCLBDeployerConfig) (*AliyunCLBDeployer, error) { - return NewWithLogger(config, logger.NewNilLogger()) -} - -func NewWithLogger(config *AliyunCLBDeployerConfig, logger logger.Logger) (*AliyunCLBDeployer, error) { +func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { if config == nil { panic("config is nil") } - if logger == nil { - panic("logger is nil") - } - client, err := createSdkClient(config.AccessKeyId, config.AccessKeySecret, config.Region) if err != nil { return nil, xerrors.Wrap(err, "failed to create sdk client") @@ -72,15 +64,20 @@ func NewWithLogger(config *AliyunCLBDeployerConfig, logger logger.Logger) (*Aliy return nil, xerrors.Wrap(err, "failed to create ssl uploader") } - return &AliyunCLBDeployer{ - logger: logger, + return &DeployerProvider{ config: config, + logger: logger.NewNilLogger(), sdkClient: client, sslUploader: uploader, }, nil } -func (d *AliyunCLBDeployer) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { +func (d *DeployerProvider) WithLogger(logger logger.Logger) *DeployerProvider { + d.logger = logger + return d +} + +func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { // 上传证书到 SLB upres, err := d.sslUploader.Upload(ctx, certPem, privkeyPem) if err != nil { @@ -108,7 +105,7 @@ func (d *AliyunCLBDeployer) Deploy(ctx context.Context, certPem string, privkeyP return &deployer.DeployResult{}, nil } -func (d *AliyunCLBDeployer) deployToLoadbalancer(ctx context.Context, cloudCertId string) error { +func (d *DeployerProvider) deployToLoadbalancer(ctx context.Context, cloudCertId string) error { if d.config.LoadbalancerId == "" { return errors.New("config `loadbalancerId` is required") } @@ -179,7 +176,7 @@ func (d *AliyunCLBDeployer) deployToLoadbalancer(ctx context.Context, cloudCertI return nil } -func (d *AliyunCLBDeployer) deployToListener(ctx context.Context, cloudCertId string) error { +func (d *DeployerProvider) deployToListener(ctx context.Context, cloudCertId string) error { if d.config.LoadbalancerId == "" { return errors.New("config `loadbalancerId` is required") } @@ -195,7 +192,7 @@ func (d *AliyunCLBDeployer) deployToListener(ctx context.Context, cloudCertId st return nil } -func (d *AliyunCLBDeployer) updateListenerCertificate(ctx context.Context, cloudLoadbalancerId string, cloudListenerPort int32, cloudCertId string) error { +func (d *DeployerProvider) updateListenerCertificate(ctx context.Context, cloudLoadbalancerId string, cloudListenerPort int32, cloudCertId string) error { // 查询监听配置 // REF: https://help.aliyun.com/zh/slb/classic-load-balancer/developer-reference/api-slb-2014-05-15-describeloadbalancerhttpslistenerattribute describeLoadBalancerHTTPSListenerAttributeReq := &aliyunSlb.DescribeLoadBalancerHTTPSListenerAttributeRequest{ diff --git a/internal/pkg/core/deployer/providers/aliyun-clb/aliyun_clb_test.go b/internal/pkg/core/deployer/providers/aliyun-clb/aliyun_clb_test.go index 79b16618..a845bf86 100644 --- a/internal/pkg/core/deployer/providers/aliyun-clb/aliyun_clb_test.go +++ b/internal/pkg/core/deployer/providers/aliyun-clb/aliyun_clb_test.go @@ -63,7 +63,7 @@ func TestDeploy(t *testing.T) { fmt.Sprintf("DOMAIN: %v", fDomain), }, "\n")) - deployer, err := provider.New(&provider.AliyunCLBDeployerConfig{ + deployer, err := provider.NewDeployer(&provider.DeployerConfig{ AccessKeyId: fAccessKeyId, AccessKeySecret: fAccessKeySecret, Region: fRegion, @@ -99,7 +99,7 @@ func TestDeploy(t *testing.T) { fmt.Sprintf("LISTENERPORT: %v", fListenerPort), }, "\n")) - deployer, err := provider.New(&provider.AliyunCLBDeployerConfig{ + deployer, err := provider.NewDeployer(&provider.DeployerConfig{ AccessKeyId: fAccessKeyId, AccessKeySecret: fAccessKeySecret, Region: fRegion, diff --git a/internal/pkg/core/deployer/providers/aliyun-dcdn/aliyun_dcdn.go b/internal/pkg/core/deployer/providers/aliyun-dcdn/aliyun_dcdn.go index 8c571a3f..bfa28e7b 100644 --- a/internal/pkg/core/deployer/providers/aliyun-dcdn/aliyun_dcdn.go +++ b/internal/pkg/core/deployer/providers/aliyun-dcdn/aliyun_dcdn.go @@ -15,7 +15,7 @@ import ( "github.com/usual2970/certimate/internal/pkg/core/logger" ) -type AliyunDCDNDeployerConfig struct { +type DeployerConfig struct { // 阿里云 AccessKeyId。 AccessKeyId string `json:"accessKeyId"` // 阿里云 AccessKeySecret。 @@ -24,40 +24,37 @@ type AliyunDCDNDeployerConfig struct { Domain string `json:"domain"` } -type AliyunDCDNDeployer struct { - config *AliyunDCDNDeployerConfig +type DeployerProvider struct { + config *DeployerConfig logger logger.Logger sdkClient *aliyunDcdn.Client } -var _ deployer.Deployer = (*AliyunDCDNDeployer)(nil) +var _ deployer.Deployer = (*DeployerProvider)(nil) -func New(config *AliyunDCDNDeployerConfig) (*AliyunDCDNDeployer, error) { - return NewWithLogger(config, logger.NewNilLogger()) -} - -func NewWithLogger(config *AliyunDCDNDeployerConfig, logger logger.Logger) (*AliyunDCDNDeployer, error) { +func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { if config == nil { panic("config is nil") } - if logger == nil { - panic("logger is nil") - } - client, err := createSdkClient(config.AccessKeyId, config.AccessKeySecret) if err != nil { return nil, xerrors.Wrap(err, "failed to create sdk client") } - return &AliyunDCDNDeployer{ - logger: logger, + return &DeployerProvider{ config: config, + logger: logger.NewNilLogger(), sdkClient: client, }, nil } -func (d *AliyunDCDNDeployer) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { +func (d *DeployerProvider) WithLogger(logger logger.Logger) *DeployerProvider { + d.logger = logger + return d +} + +func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { // "*.example.com" → ".example.com",适配阿里云 DCDN 要求的泛域名格式 domain := strings.TrimPrefix(d.config.Domain, "*") diff --git a/internal/pkg/core/deployer/providers/aliyun-dcdn/aliyun_dcdn_test.go b/internal/pkg/core/deployer/providers/aliyun-dcdn/aliyun_dcdn_test.go index ffbfcd1f..04ca4c48 100644 --- a/internal/pkg/core/deployer/providers/aliyun-dcdn/aliyun_dcdn_test.go +++ b/internal/pkg/core/deployer/providers/aliyun-dcdn/aliyun_dcdn_test.go @@ -52,7 +52,7 @@ func TestDeploy(t *testing.T) { fmt.Sprintf("DOMAIN: %v", fDomain), }, "\n")) - deployer, err := provider.New(&provider.AliyunDCDNDeployerConfig{ + deployer, err := provider.NewDeployer(&provider.DeployerConfig{ AccessKeyId: fAccessKeyId, AccessKeySecret: fAccessKeySecret, Domain: fDomain, diff --git a/internal/pkg/core/deployer/providers/aliyun-esa/aliyun_esa.go b/internal/pkg/core/deployer/providers/aliyun-esa/aliyun_esa.go index 87a483ff..e7f977ce 100644 --- a/internal/pkg/core/deployer/providers/aliyun-esa/aliyun_esa.go +++ b/internal/pkg/core/deployer/providers/aliyun-esa/aliyun_esa.go @@ -18,7 +18,7 @@ import ( uploadersp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/aliyun-cas" ) -type AliyunESADeployerConfig struct { +type DeployerConfig struct { // 阿里云 AccessKeyId。 AccessKeyId string `json:"accessKeyId"` // 阿里云 AccessKeySecret。 @@ -29,28 +29,20 @@ type AliyunESADeployerConfig struct { SiteId int64 `json:"siteId"` } -type AliyunESADeployer struct { - config *AliyunESADeployerConfig +type DeployerProvider struct { + config *DeployerConfig logger logger.Logger sdkClient *aliyunEsa.Client sslUploader uploader.Uploader } -var _ deployer.Deployer = (*AliyunESADeployer)(nil) +var _ deployer.Deployer = (*DeployerProvider)(nil) -func New(config *AliyunESADeployerConfig) (*AliyunESADeployer, error) { - return NewWithLogger(config, logger.NewNilLogger()) -} - -func NewWithLogger(config *AliyunESADeployerConfig, logger logger.Logger) (*AliyunESADeployer, error) { +func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { if config == nil { panic("config is nil") } - if logger == nil { - panic("logger is nil") - } - client, err := createSdkClient(config.AccessKeyId, config.AccessKeySecret, config.Region) if err != nil { return nil, xerrors.Wrap(err, "failed to create sdk client") @@ -61,15 +53,20 @@ func NewWithLogger(config *AliyunESADeployerConfig, logger logger.Logger) (*Aliy return nil, xerrors.Wrap(err, "failed to create ssl uploader") } - return &AliyunESADeployer{ - logger: logger, + return &DeployerProvider{ config: config, + logger: logger.NewNilLogger(), sdkClient: client, sslUploader: uploader, }, nil } -func (d *AliyunESADeployer) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { +func (d *DeployerProvider) WithLogger(logger logger.Logger) *DeployerProvider { + d.logger = logger + return d +} + +func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { if d.config.SiteId == 0 { return nil, errors.New("config `siteId` is required") } diff --git a/internal/pkg/core/deployer/providers/aliyun-esa/aliyun_esa_test.go b/internal/pkg/core/deployer/providers/aliyun-esa/aliyun_esa_test.go index 980dc9a0..c2d81aa3 100644 --- a/internal/pkg/core/deployer/providers/aliyun-esa/aliyun_esa_test.go +++ b/internal/pkg/core/deployer/providers/aliyun-esa/aliyun_esa_test.go @@ -56,7 +56,7 @@ func TestDeploy(t *testing.T) { fmt.Sprintf("SITEID: %v", fSiteId), }, "\n")) - deployer, err := provider.New(&provider.AliyunESADeployerConfig{ + deployer, err := provider.NewDeployer(&provider.DeployerConfig{ AccessKeyId: fAccessKeyId, AccessKeySecret: fAccessKeySecret, Region: fRegion, diff --git a/internal/pkg/core/deployer/providers/aliyun-live/aliyun_live.go b/internal/pkg/core/deployer/providers/aliyun-live/aliyun_live.go index fdc61d7d..5735da79 100644 --- a/internal/pkg/core/deployer/providers/aliyun-live/aliyun_live.go +++ b/internal/pkg/core/deployer/providers/aliyun-live/aliyun_live.go @@ -15,7 +15,7 @@ import ( "github.com/usual2970/certimate/internal/pkg/core/logger" ) -type AliyunLiveDeployerConfig struct { +type DeployerConfig struct { // 阿里云 AccessKeyId。 AccessKeyId string `json:"accessKeyId"` // 阿里云 AccessKeySecret。 @@ -26,40 +26,37 @@ type AliyunLiveDeployerConfig struct { Domain string `json:"domain"` } -type AliyunLiveDeployer struct { - config *AliyunLiveDeployerConfig +type DeployerProvider struct { + config *DeployerConfig logger logger.Logger sdkClient *aliyunLive.Client } -var _ deployer.Deployer = (*AliyunLiveDeployer)(nil) +var _ deployer.Deployer = (*DeployerProvider)(nil) -func New(config *AliyunLiveDeployerConfig) (*AliyunLiveDeployer, error) { - return NewWithLogger(config, logger.NewNilLogger()) -} - -func NewWithLogger(config *AliyunLiveDeployerConfig, logger logger.Logger) (*AliyunLiveDeployer, error) { +func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { if config == nil { panic("config is nil") } - if logger == nil { - panic("logger is nil") - } - client, err := createSdkClient(config.AccessKeyId, config.AccessKeySecret, config.Region) if err != nil { return nil, xerrors.Wrap(err, "failed to create sdk client") } - return &AliyunLiveDeployer{ - logger: logger, + return &DeployerProvider{ config: config, + logger: logger.NewNilLogger(), sdkClient: client, }, nil } -func (d *AliyunLiveDeployer) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { +func (d *DeployerProvider) WithLogger(logger logger.Logger) *DeployerProvider { + d.logger = logger + return d +} + +func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { // "*.example.com" → ".example.com",适配阿里云 Live 要求的泛域名格式 domain := strings.TrimPrefix(d.config.Domain, "*") diff --git a/internal/pkg/core/deployer/providers/aliyun-live/aliyun_live_test.go b/internal/pkg/core/deployer/providers/aliyun-live/aliyun_live_test.go index d66f647a..1c101d26 100644 --- a/internal/pkg/core/deployer/providers/aliyun-live/aliyun_live_test.go +++ b/internal/pkg/core/deployer/providers/aliyun-live/aliyun_live_test.go @@ -52,7 +52,7 @@ func TestDeploy(t *testing.T) { fmt.Sprintf("DOMAIN: %v", fDomain), }, "\n")) - deployer, err := provider.New(&provider.AliyunLiveDeployerConfig{ + deployer, err := provider.NewDeployer(&provider.DeployerConfig{ AccessKeyId: fAccessKeyId, AccessKeySecret: fAccessKeySecret, Domain: fDomain, diff --git a/internal/pkg/core/deployer/providers/aliyun-nlb/aliyun_nlb.go b/internal/pkg/core/deployer/providers/aliyun-nlb/aliyun_nlb.go index 8918e743..fb9f2cb3 100644 --- a/internal/pkg/core/deployer/providers/aliyun-nlb/aliyun_nlb.go +++ b/internal/pkg/core/deployer/providers/aliyun-nlb/aliyun_nlb.go @@ -17,7 +17,7 @@ import ( uploadersp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/aliyun-cas" ) -type AliyunNLBDeployerConfig struct { +type DeployerConfig struct { // 阿里云 AccessKeyId。 AccessKeyId string `json:"accessKeyId"` // 阿里云 AccessKeySecret。 @@ -34,28 +34,20 @@ type AliyunNLBDeployerConfig struct { ListenerId string `json:"listenerId,omitempty"` } -type AliyunNLBDeployer struct { - config *AliyunNLBDeployerConfig +type DeployerProvider struct { + config *DeployerConfig logger logger.Logger sdkClient *aliyunNlb.Client sslUploader uploader.Uploader } -var _ deployer.Deployer = (*AliyunNLBDeployer)(nil) +var _ deployer.Deployer = (*DeployerProvider)(nil) -func New(config *AliyunNLBDeployerConfig) (*AliyunNLBDeployer, error) { - return NewWithLogger(config, logger.NewNilLogger()) -} - -func NewWithLogger(config *AliyunNLBDeployerConfig, logger logger.Logger) (*AliyunNLBDeployer, error) { +func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { if config == nil { panic("config is nil") } - if logger == nil { - panic("logger is nil") - } - client, err := createSdkClient(config.AccessKeyId, config.AccessKeySecret, config.Region) if err != nil { return nil, xerrors.Wrap(err, "failed to create sdk client") @@ -66,15 +58,20 @@ func NewWithLogger(config *AliyunNLBDeployerConfig, logger logger.Logger) (*Aliy return nil, xerrors.Wrap(err, "failed to create ssl uploader") } - return &AliyunNLBDeployer{ - logger: logger, + return &DeployerProvider{ config: config, + logger: logger.NewNilLogger(), sdkClient: client, sslUploader: uploader, }, nil } -func (d *AliyunNLBDeployer) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { +func (d *DeployerProvider) WithLogger(logger logger.Logger) *DeployerProvider { + d.logger = logger + return d +} + +func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { // 上传证书到 CAS upres, err := d.sslUploader.Upload(ctx, certPem, privkeyPem) if err != nil { @@ -102,7 +99,7 @@ func (d *AliyunNLBDeployer) Deploy(ctx context.Context, certPem string, privkeyP return &deployer.DeployResult{}, nil } -func (d *AliyunNLBDeployer) deployToLoadbalancer(ctx context.Context, cloudCertId string) error { +func (d *DeployerProvider) deployToLoadbalancer(ctx context.Context, cloudCertId string) error { if d.config.LoadbalancerId == "" { return errors.New("config `loadbalancerId` is required") } @@ -171,7 +168,7 @@ func (d *AliyunNLBDeployer) deployToLoadbalancer(ctx context.Context, cloudCertI return nil } -func (d *AliyunNLBDeployer) deployToListener(ctx context.Context, cloudCertId string) error { +func (d *DeployerProvider) deployToListener(ctx context.Context, cloudCertId string) error { if d.config.ListenerId == "" { return errors.New("config `listenerId` is required") } @@ -184,7 +181,7 @@ func (d *AliyunNLBDeployer) deployToListener(ctx context.Context, cloudCertId st return nil } -func (d *AliyunNLBDeployer) updateListenerCertificate(ctx context.Context, cloudListenerId string, cloudCertId string) error { +func (d *DeployerProvider) updateListenerCertificate(ctx context.Context, cloudListenerId string, cloudCertId string) error { // 查询监听的属性 // REF: https://help.aliyun.com/zh/slb/network-load-balancer/developer-reference/api-nlb-2022-04-30-getlistenerattribute getListenerAttributeReq := &aliyunNlb.GetListenerAttributeRequest{ diff --git a/internal/pkg/core/deployer/providers/aliyun-nlb/aliyun_nlb_test.go b/internal/pkg/core/deployer/providers/aliyun-nlb/aliyun_nlb_test.go index 7c7c08e6..dfaf0916 100644 --- a/internal/pkg/core/deployer/providers/aliyun-nlb/aliyun_nlb_test.go +++ b/internal/pkg/core/deployer/providers/aliyun-nlb/aliyun_nlb_test.go @@ -59,7 +59,7 @@ func TestDeploy(t *testing.T) { fmt.Sprintf("LOADBALANCERID: %v", fLoadbalancerId), }, "\n")) - deployer, err := provider.New(&provider.AliyunNLBDeployerConfig{ + deployer, err := provider.NewDeployer(&provider.DeployerConfig{ AccessKeyId: fAccessKeyId, AccessKeySecret: fAccessKeySecret, Region: fRegion, @@ -94,7 +94,7 @@ func TestDeploy(t *testing.T) { fmt.Sprintf("LISTENERID: %v", fListenerId), }, "\n")) - deployer, err := provider.New(&provider.AliyunNLBDeployerConfig{ + deployer, err := provider.NewDeployer(&provider.DeployerConfig{ AccessKeyId: fAccessKeyId, AccessKeySecret: fAccessKeySecret, Region: fRegion, diff --git a/internal/pkg/core/deployer/providers/aliyun-oss/aliyun_oss.go b/internal/pkg/core/deployer/providers/aliyun-oss/aliyun_oss.go index 7b8b8c54..88adbf0b 100644 --- a/internal/pkg/core/deployer/providers/aliyun-oss/aliyun_oss.go +++ b/internal/pkg/core/deployer/providers/aliyun-oss/aliyun_oss.go @@ -12,7 +12,7 @@ import ( "github.com/usual2970/certimate/internal/pkg/core/logger" ) -type AliyunOSSDeployerConfig struct { +type DeployerConfig struct { // 阿里云 AccessKeyId。 AccessKeyId string `json:"accessKeyId"` // 阿里云 AccessKeySecret。 @@ -25,40 +25,37 @@ type AliyunOSSDeployerConfig struct { Domain string `json:"domain"` } -type AliyunOSSDeployer struct { - config *AliyunOSSDeployerConfig +type DeployerProvider struct { + config *DeployerConfig logger logger.Logger sdkClient *oss.Client } -var _ deployer.Deployer = (*AliyunOSSDeployer)(nil) +var _ deployer.Deployer = (*DeployerProvider)(nil) -func New(config *AliyunOSSDeployerConfig) (*AliyunOSSDeployer, error) { - return NewWithLogger(config, logger.NewNilLogger()) -} - -func NewWithLogger(config *AliyunOSSDeployerConfig, logger logger.Logger) (*AliyunOSSDeployer, error) { +func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { if config == nil { panic("config is nil") } - if logger == nil { - panic("logger is nil") - } - client, err := createSdkClient(config.AccessKeyId, config.AccessKeySecret, config.Region) if err != nil { return nil, xerrors.Wrap(err, "failed to create sdk client") } - return &AliyunOSSDeployer{ - logger: logger, + return &DeployerProvider{ config: config, + logger: logger.NewNilLogger(), sdkClient: client, }, nil } -func (d *AliyunOSSDeployer) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { +func (d *DeployerProvider) WithLogger(logger logger.Logger) *DeployerProvider { + d.logger = logger + return d +} + +func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { if d.config.Bucket == "" { return nil, errors.New("config `bucket` is required") } diff --git a/internal/pkg/core/deployer/providers/aliyun-oss/aliyun_oss_test.go b/internal/pkg/core/deployer/providers/aliyun-oss/aliyun_oss_test.go index e25f8156..7613a003 100644 --- a/internal/pkg/core/deployer/providers/aliyun-oss/aliyun_oss_test.go +++ b/internal/pkg/core/deployer/providers/aliyun-oss/aliyun_oss_test.go @@ -60,7 +60,7 @@ func TestDeploy(t *testing.T) { fmt.Sprintf("DOMAIN: %v", fDomain), }, "\n")) - deployer, err := provider.New(&provider.AliyunOSSDeployerConfig{ + deployer, err := provider.NewDeployer(&provider.DeployerConfig{ AccessKeyId: fAccessKeyId, AccessKeySecret: fAccessKeySecret, Region: fRegion, diff --git a/internal/pkg/core/deployer/providers/aliyun-waf/aliyun_waf.go b/internal/pkg/core/deployer/providers/aliyun-waf/aliyun_waf.go index d355b382..55d03382 100644 --- a/internal/pkg/core/deployer/providers/aliyun-waf/aliyun_waf.go +++ b/internal/pkg/core/deployer/providers/aliyun-waf/aliyun_waf.go @@ -17,7 +17,7 @@ import ( uploadersp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/aliyun-cas" ) -type AliyunWAFDeployerConfig struct { +type DeployerConfig struct { // 阿里云 AccessKeyId。 AccessKeyId string `json:"accessKeyId"` // 阿里云 AccessKeySecret。 @@ -28,28 +28,20 @@ type AliyunWAFDeployerConfig struct { InstanceId string `json:"instanceId"` } -type AliyunWAFDeployer struct { - config *AliyunWAFDeployerConfig +type DeployerProvider struct { + config *DeployerConfig logger logger.Logger sdkClient *aliyunWaf.Client sslUploader uploader.Uploader } -var _ deployer.Deployer = (*AliyunWAFDeployer)(nil) +var _ deployer.Deployer = (*DeployerProvider)(nil) -func New(config *AliyunWAFDeployerConfig) (*AliyunWAFDeployer, error) { - return NewWithLogger(config, logger.NewNilLogger()) -} - -func NewWithLogger(config *AliyunWAFDeployerConfig, logger logger.Logger) (*AliyunWAFDeployer, error) { +func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { if config == nil { panic("config is nil") } - if logger == nil { - panic("logger is nil") - } - client, err := createSdkClient(config.AccessKeyId, config.AccessKeySecret, config.Region) if err != nil { return nil, xerrors.Wrap(err, "failed to create sdk client") @@ -60,15 +52,20 @@ func NewWithLogger(config *AliyunWAFDeployerConfig, logger logger.Logger) (*Aliy return nil, xerrors.Wrap(err, "failed to create ssl uploader") } - return &AliyunWAFDeployer{ - logger: logger, + return &DeployerProvider{ config: config, + logger: logger.NewNilLogger(), sdkClient: client, sslUploader: uploader, }, nil } -func (d *AliyunWAFDeployer) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { +func (d *DeployerProvider) WithLogger(logger logger.Logger) *DeployerProvider { + d.logger = logger + return d +} + +func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { if d.config.InstanceId == "" { return nil, errors.New("config `instanceId` is required") } diff --git a/internal/pkg/core/deployer/providers/aliyun-waf/aliyun_waf_test.go b/internal/pkg/core/deployer/providers/aliyun-waf/aliyun_waf_test.go index 2498beca..06a76c63 100644 --- a/internal/pkg/core/deployer/providers/aliyun-waf/aliyun_waf_test.go +++ b/internal/pkg/core/deployer/providers/aliyun-waf/aliyun_waf_test.go @@ -56,7 +56,7 @@ func TestDeploy(t *testing.T) { fmt.Sprintf("INSTANCEID: %v", fInstanceId), }, "\n")) - deployer, err := provider.New(&provider.AliyunWAFDeployerConfig{ + deployer, err := provider.NewDeployer(&provider.DeployerConfig{ AccessKeyId: fAccessKeyId, AccessKeySecret: fAccessKeySecret, Region: fRegion, diff --git a/internal/pkg/core/deployer/providers/aws-cloudfront/aws_cloudfront.go b/internal/pkg/core/deployer/providers/aws-cloudfront/aws_cloudfront.go index 21c13df6..9912e973 100644 --- a/internal/pkg/core/deployer/providers/aws-cloudfront/aws_cloudfront.go +++ b/internal/pkg/core/deployer/providers/aws-cloudfront/aws_cloudfront.go @@ -17,7 +17,7 @@ import ( uploadersp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/aws-acm" ) -type AWSCloudFrontDeployerConfig struct { +type DeployerConfig struct { // AWS AccessKeyId。 AccessKeyId string `json:"accessKeyId"` // AWS SecretAccessKey。 @@ -28,28 +28,20 @@ type AWSCloudFrontDeployerConfig struct { DistributionId string `json:"distributionId"` } -type AWSCloudFrontDeployer struct { - config *AWSCloudFrontDeployerConfig +type DeployerProvider struct { + config *DeployerConfig logger logger.Logger sdkClient *awsCf.Client sslUploader uploader.Uploader } -var _ deployer.Deployer = (*AWSCloudFrontDeployer)(nil) +var _ deployer.Deployer = (*DeployerProvider)(nil) -func New(config *AWSCloudFrontDeployerConfig) (*AWSCloudFrontDeployer, error) { - return NewWithLogger(config, logger.NewNilLogger()) -} - -func NewWithLogger(config *AWSCloudFrontDeployerConfig, logger logger.Logger) (*AWSCloudFrontDeployer, error) { +func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { if config == nil { panic("config is nil") } - if logger == nil { - panic("logger is nil") - } - client, err := createSdkClient(config.AccessKeyId, config.SecretAccessKey, config.Region) if err != nil { return nil, xerrors.Wrap(err, "failed to create sdk client") @@ -64,15 +56,20 @@ func NewWithLogger(config *AWSCloudFrontDeployerConfig, logger logger.Logger) (* return nil, xerrors.Wrap(err, "failed to create ssl uploader") } - return &AWSCloudFrontDeployer{ - logger: logger, + return &DeployerProvider{ config: config, + logger: logger.NewNilLogger(), sdkClient: client, sslUploader: uploader, }, nil } -func (d *AWSCloudFrontDeployer) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { +func (d *DeployerProvider) WithLogger(logger logger.Logger) *DeployerProvider { + d.logger = logger + return d +} + +func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { if d.config.DistributionId == "" { return nil, errors.New("config `distribuitionId` is required") } diff --git a/internal/pkg/core/deployer/providers/aws-cloudfront/aws_cloudfront_test.go b/internal/pkg/core/deployer/providers/aws-cloudfront/aws_cloudfront_test.go index 89997b37..5b4c75db 100644 --- a/internal/pkg/core/deployer/providers/aws-cloudfront/aws_cloudfront_test.go +++ b/internal/pkg/core/deployer/providers/aws-cloudfront/aws_cloudfront_test.go @@ -56,11 +56,11 @@ func TestDeploy(t *testing.T) { fmt.Sprintf("DISTRIBUTIONID: %v", fDistribuitionId), }, "\n")) - deployer, err := provider.New(&provider.AWSCloudFrontDeployerConfig{ + deployer, err := provider.NewDeployer(&provider.DeployerConfig{ AccessKeyId: fAccessKeyId, SecretAccessKey: fSecretAccessKey, Region: fRegion, - DistribuitionId: fDistribuitionId, + DistributionId: fDistribuitionId, }) if err != nil { t.Errorf("err: %+v", err) diff --git a/internal/pkg/core/deployer/providers/baiducloud-cdn/baiducloud_cdn.go b/internal/pkg/core/deployer/providers/baiducloud-cdn/baiducloud_cdn.go index ae34666a..df57ea1d 100644 --- a/internal/pkg/core/deployer/providers/baiducloud-cdn/baiducloud_cdn.go +++ b/internal/pkg/core/deployer/providers/baiducloud-cdn/baiducloud_cdn.go @@ -13,7 +13,7 @@ import ( "github.com/usual2970/certimate/internal/pkg/core/logger" ) -type BaiduCloudCDNDeployerConfig struct { +type DeployerConfig struct { // 百度智能云 AccessKeyId。 AccessKeyId string `json:"accessKeyId"` // 百度智能云 SecretAccessKey。 @@ -22,40 +22,37 @@ type BaiduCloudCDNDeployerConfig struct { Domain string `json:"domain"` } -type BaiduCloudCDNDeployer struct { - config *BaiduCloudCDNDeployerConfig +type DeployerProvider struct { + config *DeployerConfig logger logger.Logger sdkClient *bceCdn.Client } -var _ deployer.Deployer = (*BaiduCloudCDNDeployer)(nil) +var _ deployer.Deployer = (*DeployerProvider)(nil) -func New(config *BaiduCloudCDNDeployerConfig) (*BaiduCloudCDNDeployer, error) { - return NewWithLogger(config, logger.NewNilLogger()) -} - -func NewWithLogger(config *BaiduCloudCDNDeployerConfig, logger logger.Logger) (*BaiduCloudCDNDeployer, error) { +func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { if config == nil { panic("config is nil") } - if logger == nil { - panic("logger is nil") - } - client, err := createSdkClient(config.AccessKeyId, config.SecretAccessKey) if err != nil { return nil, xerrors.Wrap(err, "failed to create sdk client") } - return &BaiduCloudCDNDeployer{ - logger: logger, + return &DeployerProvider{ config: config, + logger: logger.NewNilLogger(), sdkClient: client, }, nil } -func (d *BaiduCloudCDNDeployer) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { +func (d *DeployerProvider) WithLogger(logger logger.Logger) *DeployerProvider { + d.logger = logger + return d +} + +func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { // 修改域名证书 // REF: https://cloud.baidu.com/doc/CDN/s/qjzuz2hp8 putCertResp, err := d.sdkClient.PutCert( diff --git a/internal/pkg/core/deployer/providers/baiducloud-cdn/baiducloud_cdn_test.go b/internal/pkg/core/deployer/providers/baiducloud-cdn/baiducloud_cdn_test.go index 817600b6..ecb9a9d4 100644 --- a/internal/pkg/core/deployer/providers/baiducloud-cdn/baiducloud_cdn_test.go +++ b/internal/pkg/core/deployer/providers/baiducloud-cdn/baiducloud_cdn_test.go @@ -52,7 +52,7 @@ func TestDeploy(t *testing.T) { fmt.Sprintf("DOMAIN: %v", fDomain), }, "\n")) - deployer, err := provider.New(&provider.BaiduCloudCDNDeployerConfig{ + deployer, err := provider.NewDeployer(&provider.DeployerConfig{ AccessKeyId: fAccessKeyId, SecretAccessKey: fSecretAccessKey, Domain: fDomain, diff --git a/internal/pkg/core/deployer/providers/baishan-cdn/baishan_cdn.go b/internal/pkg/core/deployer/providers/baishan-cdn/baishan_cdn.go index 454909fd..efb3353e 100644 --- a/internal/pkg/core/deployer/providers/baishan-cdn/baishan_cdn.go +++ b/internal/pkg/core/deployer/providers/baishan-cdn/baishan_cdn.go @@ -13,47 +13,44 @@ import ( bssdk "github.com/usual2970/certimate/internal/pkg/vendors/baishan-sdk" ) -type BaishanCDNDeployerConfig struct { +type DeployerConfig struct { // 白山云 API Token。 ApiToken string `json:"apiToken"` // 加速域名(支持泛域名)。 Domain string `json:"domain"` } -type BaishanCDNDeployer struct { - config *BaishanCDNDeployerConfig +type DeployerProvider struct { + config *DeployerConfig logger logger.Logger sdkClient *bssdk.Client } -var _ deployer.Deployer = (*BaishanCDNDeployer)(nil) +var _ deployer.Deployer = (*DeployerProvider)(nil) -func New(config *BaishanCDNDeployerConfig) (*BaishanCDNDeployer, error) { - return NewWithLogger(config, logger.NewNilLogger()) -} - -func NewWithLogger(config *BaishanCDNDeployerConfig, logger logger.Logger) (*BaishanCDNDeployer, error) { +func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { if config == nil { panic("config is nil") } - if logger == nil { - panic("logger is nil") - } - client, err := createSdkClient(config.ApiToken) if err != nil { return nil, xerrors.Wrap(err, "failed to create sdk client") } - return &BaishanCDNDeployer{ - logger: logger, + return &DeployerProvider{ config: config, + logger: logger.NewNilLogger(), sdkClient: client, }, nil } -func (d *BaishanCDNDeployer) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { +func (d *DeployerProvider) WithLogger(logger logger.Logger) *DeployerProvider { + d.logger = logger + return d +} + +func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { if d.config.Domain == "" { return nil, errors.New("config `domain` is required") } diff --git a/internal/pkg/core/deployer/providers/baishan-cdn/baishan_cdn_test.go b/internal/pkg/core/deployer/providers/baishan-cdn/baishan_cdn_test.go index b6ceb64f..5534a232 100644 --- a/internal/pkg/core/deployer/providers/baishan-cdn/baishan_cdn_test.go +++ b/internal/pkg/core/deployer/providers/baishan-cdn/baishan_cdn_test.go @@ -48,7 +48,7 @@ func TestDeploy(t *testing.T) { fmt.Sprintf("DOMAIN: %v", fDomain), }, "\n")) - deployer, err := provider.New(&provider.BaishanCDNDeployerConfig{ + deployer, err := provider.NewDeployer(&provider.DeployerConfig{ ApiToken: fApiToken, Domain: fDomain, }) diff --git a/internal/pkg/core/deployer/providers/baotapanel-console/baotapanel_console.go b/internal/pkg/core/deployer/providers/baotapanel-console/baotapanel_console.go index 19dda685..6343acf7 100644 --- a/internal/pkg/core/deployer/providers/baotapanel-console/baotapanel_console.go +++ b/internal/pkg/core/deployer/providers/baotapanel-console/baotapanel_console.go @@ -12,7 +12,7 @@ import ( btsdk "github.com/usual2970/certimate/internal/pkg/vendors/btpanel-sdk" ) -type BaotaPanelConsoleDeployerConfig struct { +type DeployerConfig struct { // 宝塔面板地址。 ApiUrl string `json:"apiUrl"` // 宝塔面板接口密钥。 @@ -21,40 +21,37 @@ type BaotaPanelConsoleDeployerConfig struct { AutoRestart bool `json:"autoRestart"` } -type BaotaPanelConsoleDeployer struct { - config *BaotaPanelConsoleDeployerConfig +type DeployerProvider struct { + config *DeployerConfig logger logger.Logger sdkClient *btsdk.Client } -var _ deployer.Deployer = (*BaotaPanelConsoleDeployer)(nil) +var _ deployer.Deployer = (*DeployerProvider)(nil) -func New(config *BaotaPanelConsoleDeployerConfig) (*BaotaPanelConsoleDeployer, error) { - return NewWithLogger(config, logger.NewNilLogger()) -} - -func NewWithLogger(config *BaotaPanelConsoleDeployerConfig, logger logger.Logger) (*BaotaPanelConsoleDeployer, error) { +func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { if config == nil { panic("config is nil") } - if logger == nil { - panic("logger is nil") - } - client, err := createSdkClient(config.ApiUrl, config.ApiKey) if err != nil { return nil, xerrors.Wrap(err, "failed to create sdk client") } - return &BaotaPanelConsoleDeployer{ - logger: logger, + return &DeployerProvider{ config: config, + logger: logger.NewNilLogger(), sdkClient: client, }, nil } -func (d *BaotaPanelConsoleDeployer) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { +func (d *DeployerProvider) WithLogger(logger logger.Logger) *DeployerProvider { + d.logger = logger + return d +} + +func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { // 设置面板 SSL 证书 configSavePanelSSLReq := &btsdk.ConfigSavePanelSSLRequest{ PrivateKey: privkeyPem, diff --git a/internal/pkg/core/deployer/providers/baotapanel-console/baotapanel_console_test.go b/internal/pkg/core/deployer/providers/baotapanel-console/baotapanel_console_test.go index 90a0a4ba..06a2f096 100644 --- a/internal/pkg/core/deployer/providers/baotapanel-console/baotapanel_console_test.go +++ b/internal/pkg/core/deployer/providers/baotapanel-console/baotapanel_console_test.go @@ -48,7 +48,7 @@ func TestDeploy(t *testing.T) { fmt.Sprintf("APIKEY: %v", fApiKey), }, "\n")) - deployer, err := provider.New(&provider.BaotaPanelConsoleDeployerConfig{ + deployer, err := provider.NewDeployer(&provider.DeployerConfig{ ApiUrl: fApiUrl, ApiKey: fApiKey, }) diff --git a/internal/pkg/core/deployer/providers/baotapanel-site/baotapanel_site.go b/internal/pkg/core/deployer/providers/baotapanel-site/baotapanel_site.go index 01cabdde..62cef9de 100644 --- a/internal/pkg/core/deployer/providers/baotapanel-site/baotapanel_site.go +++ b/internal/pkg/core/deployer/providers/baotapanel-site/baotapanel_site.go @@ -14,7 +14,7 @@ import ( btsdk "github.com/usual2970/certimate/internal/pkg/vendors/btpanel-sdk" ) -type BaotaPanelSiteDeployerConfig struct { +type DeployerConfig struct { // 宝塔面板地址。 ApiUrl string `json:"apiUrl"` // 宝塔面板接口密钥。 @@ -27,40 +27,37 @@ type BaotaPanelSiteDeployerConfig struct { SiteNames []string `json:"siteNames,omitempty"` } -type BaotaPanelSiteDeployer struct { - config *BaotaPanelSiteDeployerConfig +type DeployerProvider struct { + config *DeployerConfig logger logger.Logger sdkClient *btsdk.Client } -var _ deployer.Deployer = (*BaotaPanelSiteDeployer)(nil) +var _ deployer.Deployer = (*DeployerProvider)(nil) -func New(config *BaotaPanelSiteDeployerConfig) (*BaotaPanelSiteDeployer, error) { - return NewWithLogger(config, logger.NewNilLogger()) -} - -func NewWithLogger(config *BaotaPanelSiteDeployerConfig, logger logger.Logger) (*BaotaPanelSiteDeployer, error) { +func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { if config == nil { panic("config is nil") } - if logger == nil { - panic("logger is nil") - } - client, err := createSdkClient(config.ApiUrl, config.ApiKey) if err != nil { return nil, xerrors.Wrap(err, "failed to create sdk client") } - return &BaotaPanelSiteDeployer{ - logger: logger, + return &DeployerProvider{ config: config, + logger: logger.NewNilLogger(), sdkClient: client, }, nil } -func (d *BaotaPanelSiteDeployer) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { +func (d *DeployerProvider) WithLogger(logger logger.Logger) *DeployerProvider { + d.logger = logger + return d +} + +func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { switch d.config.SiteType { case "php": { diff --git a/internal/pkg/core/deployer/providers/baotapanel-site/baotapanel_site_test.go b/internal/pkg/core/deployer/providers/baotapanel-site/baotapanel_site_test.go index d3cc52cd..00d32461 100644 --- a/internal/pkg/core/deployer/providers/baotapanel-site/baotapanel_site_test.go +++ b/internal/pkg/core/deployer/providers/baotapanel-site/baotapanel_site_test.go @@ -56,7 +56,7 @@ func TestDeploy(t *testing.T) { fmt.Sprintf("SITENAME: %v", fSiteName), }, "\n")) - deployer, err := provider.New(&provider.BaotaPanelSiteDeployerConfig{ + deployer, err := provider.NewDeployer(&provider.DeployerConfig{ ApiUrl: fApiUrl, ApiKey: fApiKey, SiteName: fSiteName, diff --git a/internal/pkg/core/deployer/providers/byteplus-cdn/byteplus_cdn.go b/internal/pkg/core/deployer/providers/byteplus-cdn/byteplus_cdn.go index 55c3e216..c49e965e 100644 --- a/internal/pkg/core/deployer/providers/byteplus-cdn/byteplus_cdn.go +++ b/internal/pkg/core/deployer/providers/byteplus-cdn/byteplus_cdn.go @@ -15,7 +15,7 @@ import ( uploadersp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/byteplus-cdn" ) -type BytePlusCDNDeployerConfig struct { +type DeployerConfig struct { // BytePlus AccessKey。 AccessKey string `json:"accessKey"` // BytePlus SecretKey。 @@ -24,28 +24,20 @@ type BytePlusCDNDeployerConfig struct { Domain string `json:"domain"` } -type BytePlusCDNDeployer struct { - config *BytePlusCDNDeployerConfig +type DeployerProvider struct { + config *DeployerConfig logger logger.Logger sdkClient *bpCdn.CDN sslUploader uploader.Uploader } -var _ deployer.Deployer = (*BytePlusCDNDeployer)(nil) +var _ deployer.Deployer = (*DeployerProvider)(nil) -func New(config *BytePlusCDNDeployerConfig) (*BytePlusCDNDeployer, error) { - return NewWithLogger(config, logger.NewNilLogger()) -} - -func NewWithLogger(config *BytePlusCDNDeployerConfig, logger logger.Logger) (*BytePlusCDNDeployer, error) { +func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { if config == nil { panic("config is nil") } - if logger == nil { - panic("logger is nil") - } - client := bpCdn.NewInstance() client.Client.SetAccessKey(config.AccessKey) client.Client.SetSecretKey(config.SecretKey) @@ -58,15 +50,20 @@ func NewWithLogger(config *BytePlusCDNDeployerConfig, logger logger.Logger) (*By return nil, xerrors.Wrap(err, "failed to create ssl uploader") } - return &BytePlusCDNDeployer{ - logger: logger, + return &DeployerProvider{ config: config, + logger: logger.NewNilLogger(), sdkClient: client, sslUploader: uploader, }, nil } -func (d *BytePlusCDNDeployer) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { +func (d *DeployerProvider) WithLogger(logger logger.Logger) *DeployerProvider { + d.logger = logger + return d +} + +func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { // 上传证书到 CDN upres, err := d.sslUploader.Upload(ctx, certPem, privkeyPem) if err != nil { diff --git a/internal/pkg/core/deployer/providers/byteplus-cdn/byteplus_cdn_test.go b/internal/pkg/core/deployer/providers/byteplus-cdn/byteplus_cdn_test.go index 9de97be6..ee09e8ee 100644 --- a/internal/pkg/core/deployer/providers/byteplus-cdn/byteplus_cdn_test.go +++ b/internal/pkg/core/deployer/providers/byteplus-cdn/byteplus_cdn_test.go @@ -52,7 +52,7 @@ func TestDeploy(t *testing.T) { fmt.Sprintf("DOMAIN: %v", fDomain), }, "\n")) - deployer, err := provider.New(&provider.BytePlusCDNDeployerConfig{ + deployer, err := provider.NewDeployer(&provider.DeployerConfig{ AccessKey: fAccessKey, SecretKey: fSecretKey, Domain: fDomain, diff --git a/internal/pkg/core/deployer/providers/cachefly/cachefly.go b/internal/pkg/core/deployer/providers/cachefly/cachefly.go index 352fba40..8c6f129d 100644 --- a/internal/pkg/core/deployer/providers/cachefly/cachefly.go +++ b/internal/pkg/core/deployer/providers/cachefly/cachefly.go @@ -11,45 +11,42 @@ import ( cfsdk "github.com/usual2970/certimate/internal/pkg/vendors/cachefly-sdk" ) -type CacheFlyDeployerConfig struct { +type DeployerConfig struct { // CacheFly API Token。 ApiToken string `json:"apiToken"` } -type CacheFlyDeployer struct { - config *CacheFlyDeployerConfig +type DeployerProvider struct { + config *DeployerConfig logger logger.Logger sdkClient *cfsdk.Client } -var _ deployer.Deployer = (*CacheFlyDeployer)(nil) +var _ deployer.Deployer = (*DeployerProvider)(nil) -func New(config *CacheFlyDeployerConfig) (*CacheFlyDeployer, error) { - return NewWithLogger(config, logger.NewNilLogger()) -} - -func NewWithLogger(config *CacheFlyDeployerConfig, logger logger.Logger) (*CacheFlyDeployer, error) { +func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { if config == nil { panic("config is nil") } - if logger == nil { - panic("logger is nil") - } - client, err := createSdkClient(config.ApiToken) if err != nil { return nil, xerrors.Wrap(err, "failed to create sdk client") } - return &CacheFlyDeployer{ - logger: logger, + return &DeployerProvider{ config: config, + logger: logger.NewNilLogger(), sdkClient: client, }, nil } -func (d *CacheFlyDeployer) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { +func (d *DeployerProvider) WithLogger(logger logger.Logger) *DeployerProvider { + d.logger = logger + return d +} + +func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { // 上传证书 createCertificateReq := &cfsdk.CreateCertificateRequest{ Certificate: certPem, diff --git a/internal/pkg/core/deployer/providers/cachefly/cachefly_test.go b/internal/pkg/core/deployer/providers/cachefly/cachefly_test.go index 776b2438..1de6047e 100644 --- a/internal/pkg/core/deployer/providers/cachefly/cachefly_test.go +++ b/internal/pkg/core/deployer/providers/cachefly/cachefly_test.go @@ -44,7 +44,7 @@ func TestDeploy(t *testing.T) { fmt.Sprintf("APITOKEN: %v", fApiToken), }, "\n")) - deployer, err := provider.New(&provider.CacheFlyDeployerConfig{ + deployer, err := provider.NewDeployer(&provider.DeployerConfig{ ApiToken: fApiToken, }) if err != nil { diff --git a/internal/pkg/core/deployer/providers/cdnfly/cdnfly.go b/internal/pkg/core/deployer/providers/cdnfly/cdnfly.go index 27abbc2f..c98d9ae4 100644 --- a/internal/pkg/core/deployer/providers/cdnfly/cdnfly.go +++ b/internal/pkg/core/deployer/providers/cdnfly/cdnfly.go @@ -15,7 +15,7 @@ import ( cfsdk "github.com/usual2970/certimate/internal/pkg/vendors/cdnfly-sdk" ) -type CdnflyDeployerConfig struct { +type DeployerConfig struct { // Cdnfly 地址。 ApiUrl string `json:"apiUrl"` // Cdnfly 用户端 API Key。 @@ -32,40 +32,37 @@ type CdnflyDeployerConfig struct { CertificateId string `json:"certificateId,omitempty"` } -type CdnflyDeployer struct { - config *CdnflyDeployerConfig +type DeployerProvider struct { + config *DeployerConfig logger logger.Logger sdkClient *cfsdk.Client } -var _ deployer.Deployer = (*CdnflyDeployer)(nil) +var _ deployer.Deployer = (*DeployerProvider)(nil) -func New(config *CdnflyDeployerConfig) (*CdnflyDeployer, error) { - return NewWithLogger(config, logger.NewNilLogger()) -} - -func NewWithLogger(config *CdnflyDeployerConfig, logger logger.Logger) (*CdnflyDeployer, error) { +func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { if config == nil { panic("config is nil") } - if logger == nil { - panic("logger is nil") - } - client, err := createSdkClient(config.ApiUrl, config.ApiKey, config.ApiSecret) if err != nil { return nil, xerrors.Wrap(err, "failed to create sdk client") } - return &CdnflyDeployer{ - logger: logger, + return &DeployerProvider{ config: config, + logger: logger.NewNilLogger(), sdkClient: client, }, nil } -func (d *CdnflyDeployer) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { +func (d *DeployerProvider) WithLogger(logger logger.Logger) *DeployerProvider { + d.logger = logger + return d +} + +func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { // 根据部署资源类型决定部署方式 switch d.config.ResourceType { case RESOURCE_TYPE_SITE: @@ -85,7 +82,7 @@ func (d *CdnflyDeployer) Deploy(ctx context.Context, certPem string, privkeyPem return &deployer.DeployResult{}, nil } -func (d *CdnflyDeployer) deployToSite(ctx context.Context, certPem string, privkeyPem string) error { +func (d *DeployerProvider) deployToSite(ctx context.Context, certPem string, privkeyPem string) error { if d.config.SiteId == "" { return errors.New("config `siteId` is required") } @@ -138,7 +135,7 @@ func (d *CdnflyDeployer) deployToSite(ctx context.Context, certPem string, privk return nil } -func (d *CdnflyDeployer) deployToCertificate(ctx context.Context, certPem string, privkeyPem string) error { +func (d *DeployerProvider) deployToCertificate(ctx context.Context, certPem string, privkeyPem string) error { if d.config.CertificateId == "" { return errors.New("config `certificateId` is required") } diff --git a/internal/pkg/core/deployer/providers/cdnfly/cdnfly_test.go b/internal/pkg/core/deployer/providers/cdnfly/cdnfly_test.go index 2d9604cd..fd17df9c 100644 --- a/internal/pkg/core/deployer/providers/cdnfly/cdnfly_test.go +++ b/internal/pkg/core/deployer/providers/cdnfly/cdnfly_test.go @@ -56,7 +56,7 @@ func TestDeploy(t *testing.T) { fmt.Sprintf("CERTIFICATEID: %v", fCertificateId), }, "\n")) - deployer, err := provider.New(&provider.CdnflyDeployerConfig{ + deployer, err := provider.NewDeployer(&provider.DeployerConfig{ ApiUrl: fApiUrl, ApiKey: fApiKey, ApiSecret: fApiSecret, diff --git a/internal/pkg/core/deployer/providers/dogecloud-cdn/dogecloud_cdn.go b/internal/pkg/core/deployer/providers/dogecloud-cdn/dogecloud_cdn.go index 25aac09d..8bc2278c 100644 --- a/internal/pkg/core/deployer/providers/dogecloud-cdn/dogecloud_cdn.go +++ b/internal/pkg/core/deployer/providers/dogecloud-cdn/dogecloud_cdn.go @@ -13,7 +13,7 @@ import ( dogesdk "github.com/usual2970/certimate/internal/pkg/vendors/dogecloud-sdk" ) -type DogeCloudCDNDeployerConfig struct { +type DeployerConfig struct { // 多吉云 AccessKey。 AccessKey string `json:"accessKey"` // 多吉云 SecretKey。 @@ -22,28 +22,20 @@ type DogeCloudCDNDeployerConfig struct { Domain string `json:"domain"` } -type DogeCloudCDNDeployer struct { - config *DogeCloudCDNDeployerConfig +type DeployerProvider struct { + config *DeployerConfig logger logger.Logger sdkClient *dogesdk.Client sslUploader uploader.Uploader } -var _ deployer.Deployer = (*DogeCloudCDNDeployer)(nil) +var _ deployer.Deployer = (*DeployerProvider)(nil) -func New(config *DogeCloudCDNDeployerConfig) (*DogeCloudCDNDeployer, error) { - return NewWithLogger(config, logger.NewNilLogger()) -} - -func NewWithLogger(config *DogeCloudCDNDeployerConfig, logger logger.Logger) (*DogeCloudCDNDeployer, error) { +func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { if config == nil { panic("config is nil") } - if logger == nil { - panic("logger is nil") - } - client := dogesdk.NewClient(config.AccessKey, config.SecretKey) uploader, err := uploadersp.New(&uploadersp.DogeCloudUploaderConfig{ @@ -54,15 +46,19 @@ func NewWithLogger(config *DogeCloudCDNDeployerConfig, logger logger.Logger) (*D return nil, xerrors.Wrap(err, "failed to create ssl uploader") } - return &DogeCloudCDNDeployer{ - logger: logger, - config: config, + return &DeployerProvider{ + logger: logger.NewNilLogger(), sdkClient: client, sslUploader: uploader, }, nil } -func (d *DogeCloudCDNDeployer) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { +func (d *DeployerProvider) WithLogger(logger logger.Logger) *DeployerProvider { + d.logger = logger + return d +} + +func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { // 上传证书到 CDN upres, err := d.sslUploader.Upload(ctx, certPem, privkeyPem) if err != nil { diff --git a/internal/pkg/core/deployer/providers/dogecloud-cdn/dogecloud_cdn_test.go b/internal/pkg/core/deployer/providers/dogecloud-cdn/dogecloud_cdn_test.go index 8d066484..f9c1e7c9 100644 --- a/internal/pkg/core/deployer/providers/dogecloud-cdn/dogecloud_cdn_test.go +++ b/internal/pkg/core/deployer/providers/dogecloud-cdn/dogecloud_cdn_test.go @@ -52,7 +52,7 @@ func TestDeploy(t *testing.T) { fmt.Sprintf("DOMAIN: %v", fDomain), }, "\n")) - deployer, err := provider.New(&provider.DogeCloudCDNDeployerConfig{ + deployer, err := provider.NewDeployer(&provider.DeployerConfig{ AccessKey: fAccessKey, SecretKey: fSecretKey, Domain: fDomain, diff --git a/internal/pkg/core/deployer/providers/edgio-applications/edgio_applications.go b/internal/pkg/core/deployer/providers/edgio-applications/edgio_applications.go index 523e33cd..890cfdf3 100644 --- a/internal/pkg/core/deployer/providers/edgio-applications/edgio_applications.go +++ b/internal/pkg/core/deployer/providers/edgio-applications/edgio_applications.go @@ -12,7 +12,7 @@ import ( edgsdkDtos "github.com/usual2970/certimate/internal/pkg/vendors/edgio-sdk/applications/v7/dtos" ) -type EdgioApplicationsDeployerConfig struct { +type DeployerConfig struct { // Edgio ClientId。 ClientId string `json:"clientId"` // Edgio ClientSecret。 @@ -21,40 +21,37 @@ type EdgioApplicationsDeployerConfig struct { EnvironmentId string `json:"environmentId"` } -type EdgioApplicationsDeployer struct { - config *EdgioApplicationsDeployerConfig +type DeployerProvider struct { + config *DeployerConfig logger logger.Logger sdkClient *edgsdk.EdgioClient } -var _ deployer.Deployer = (*EdgioApplicationsDeployer)(nil) +var _ deployer.Deployer = (*DeployerProvider)(nil) -func New(config *EdgioApplicationsDeployerConfig) (*EdgioApplicationsDeployer, error) { - return NewWithLogger(config, logger.NewNilLogger()) -} - -func NewWithLogger(config *EdgioApplicationsDeployerConfig, logger logger.Logger) (*EdgioApplicationsDeployer, error) { +func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { if config == nil { panic("config is nil") } - if logger == nil { - panic("logger is nil") - } - client, err := createSdkClient(config.ClientId, config.ClientSecret) if err != nil { return nil, xerrors.Wrap(err, "failed to create sdk client") } - return &EdgioApplicationsDeployer{ - logger: logger, + return &DeployerProvider{ config: config, + logger: logger.NewNilLogger(), sdkClient: client, }, nil } -func (d *EdgioApplicationsDeployer) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { +func (d *DeployerProvider) WithLogger(logger logger.Logger) *DeployerProvider { + d.logger = logger + return d +} + +func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { // 提取 Edgio 所需的服务端证书和中间证书内容 privateCertPem, intermediateCertPem, err := certs.ExtractCertificatesFromPEM(certPem) if err != nil { diff --git a/internal/pkg/core/deployer/providers/edgio-applications/edgio_applications_test.go b/internal/pkg/core/deployer/providers/edgio-applications/edgio_applications_test.go index 04f7a4cb..bd05b16c 100644 --- a/internal/pkg/core/deployer/providers/edgio-applications/edgio_applications_test.go +++ b/internal/pkg/core/deployer/providers/edgio-applications/edgio_applications_test.go @@ -52,7 +52,7 @@ func TestDeploy(t *testing.T) { fmt.Sprintf("ENVIRONMENTID: %v", fEnvironmentId), }, "\n")) - deployer, err := provider.New(&provider.EdgioApplicationsDeployerConfig{ + deployer, err := provider.NewDeployer(&provider.DeployerConfig{ ClientId: fClientId, ClientSecret: fClientSecret, EnvironmentId: fEnvironmentId, diff --git a/internal/pkg/core/deployer/providers/gcore-cdn/gcore_cdn.go b/internal/pkg/core/deployer/providers/gcore-cdn/gcore_cdn.go index 24f00d90..c2d8a6bc 100644 --- a/internal/pkg/core/deployer/providers/gcore-cdn/gcore_cdn.go +++ b/internal/pkg/core/deployer/providers/gcore-cdn/gcore_cdn.go @@ -16,35 +16,27 @@ import ( gcoresdk "github.com/usual2970/certimate/internal/pkg/vendors/gcore-sdk/common" ) -type GcoreCDNDeployerConfig struct { +type DeployerConfig struct { // Gcore API Token。 ApiToken string `json:"apiToken"` // CDN 资源 ID。 ResourceId int64 `json:"resourceId"` } -type GcoreCDNDeployer struct { - config *GcoreCDNDeployerConfig +type DeployerProvider struct { + config *DeployerConfig logger logger.Logger sdkClient *gresources.Service sslUploader uploader.Uploader } -var _ deployer.Deployer = (*GcoreCDNDeployer)(nil) +var _ deployer.Deployer = (*DeployerProvider)(nil) -func New(config *GcoreCDNDeployerConfig) (*GcoreCDNDeployer, error) { - return NewWithLogger(config, logger.NewNilLogger()) -} - -func NewWithLogger(config *GcoreCDNDeployerConfig, logger logger.Logger) (*GcoreCDNDeployer, error) { +func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { if config == nil { panic("config is nil") } - if logger == nil { - panic("logger is nil") - } - client, err := createSdkClient(config.ApiToken) if err != nil { return nil, xerrors.Wrap(err, "failed to create sdk client") @@ -57,15 +49,20 @@ func NewWithLogger(config *GcoreCDNDeployerConfig, logger logger.Logger) (*Gcore return nil, xerrors.Wrap(err, "failed to create ssl uploader") } - return &GcoreCDNDeployer{ - logger: logger, + return &DeployerProvider{ config: config, + logger: logger.NewNilLogger(), sdkClient: client, sslUploader: uploader, }, nil } -func (d *GcoreCDNDeployer) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { +func (d *DeployerProvider) WithLogger(logger logger.Logger) *DeployerProvider { + d.logger = logger + return d +} + +func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { if d.config.ResourceId == 0 { return nil, errors.New("config `resourceId` is required") } diff --git a/internal/pkg/core/deployer/providers/gcore-cdn/gcore_cdn_test.go b/internal/pkg/core/deployer/providers/gcore-cdn/gcore_cdn_test.go index bc36029b..34d4a9d6 100644 --- a/internal/pkg/core/deployer/providers/gcore-cdn/gcore_cdn_test.go +++ b/internal/pkg/core/deployer/providers/gcore-cdn/gcore_cdn_test.go @@ -48,7 +48,7 @@ func TestDeploy(t *testing.T) { fmt.Sprintf("RESOURCEID: %v", fResourceId), }, "\n")) - deployer, err := provider.New(&provider.GcoreCDNDeployerConfig{ + deployer, err := provider.NewDeployer(&provider.DeployerConfig{ ApiToken: fApiToken, ResourceId: fResourceId, }) diff --git a/internal/pkg/core/deployer/providers/huaweicloud-cdn/huaweicloud_cdn.go b/internal/pkg/core/deployer/providers/huaweicloud-cdn/huaweicloud_cdn.go index 20361673..cba85ad8 100644 --- a/internal/pkg/core/deployer/providers/huaweicloud-cdn/huaweicloud_cdn.go +++ b/internal/pkg/core/deployer/providers/huaweicloud-cdn/huaweicloud_cdn.go @@ -16,7 +16,7 @@ import ( hwsdk "github.com/usual2970/certimate/internal/pkg/vendors/huaweicloud-sdk" ) -type HuaweiCloudCDNDeployerConfig struct { +type DeployerConfig struct { // 华为云 AccessKeyId。 AccessKeyId string `json:"accessKeyId"` // 华为云 SecretAccessKey。 @@ -27,28 +27,20 @@ type HuaweiCloudCDNDeployerConfig struct { Domain string `json:"domain"` } -type HuaweiCloudCDNDeployer struct { - config *HuaweiCloudCDNDeployerConfig +type DeployerProvider struct { + config *DeployerConfig logger logger.Logger sdkClient *hcCdn.CdnClient sslUploader uploader.Uploader } -var _ deployer.Deployer = (*HuaweiCloudCDNDeployer)(nil) +var _ deployer.Deployer = (*DeployerProvider)(nil) -func New(config *HuaweiCloudCDNDeployerConfig) (*HuaweiCloudCDNDeployer, error) { - return NewWithLogger(config, logger.NewNilLogger()) -} - -func NewWithLogger(config *HuaweiCloudCDNDeployerConfig, logger logger.Logger) (*HuaweiCloudCDNDeployer, error) { +func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { if config == nil { panic("config is nil") } - if logger == nil { - panic("logger is nil") - } - client, err := createSdkClient( config.AccessKeyId, config.SecretAccessKey, @@ -66,15 +58,20 @@ func NewWithLogger(config *HuaweiCloudCDNDeployerConfig, logger logger.Logger) ( return nil, xerrors.Wrap(err, "failed to create ssl uploader") } - return &HuaweiCloudCDNDeployer{ - logger: logger, + return &DeployerProvider{ config: config, + logger: logger.NewNilLogger(), sdkClient: client, sslUploader: uploader, }, nil } -func (d *HuaweiCloudCDNDeployer) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { +func (d *DeployerProvider) WithLogger(logger logger.Logger) *DeployerProvider { + d.logger = logger + return d +} + +func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { // 上传证书到 SCM upres, err := d.sslUploader.Upload(ctx, certPem, privkeyPem) if err != nil { diff --git a/internal/pkg/core/deployer/providers/huaweicloud-cdn/huaweicloud_cdn_test.go b/internal/pkg/core/deployer/providers/huaweicloud-cdn/huaweicloud_cdn_test.go index d31b2a68..aaf8d6c7 100644 --- a/internal/pkg/core/deployer/providers/huaweicloud-cdn/huaweicloud_cdn_test.go +++ b/internal/pkg/core/deployer/providers/huaweicloud-cdn/huaweicloud_cdn_test.go @@ -56,7 +56,7 @@ func TestDeploy(t *testing.T) { fmt.Sprintf("DOMAIN: %v", fDomain), }, "\n")) - deployer, err := provider.New(&provider.HuaweiCloudCDNDeployerConfig{ + deployer, err := provider.NewDeployer(&provider.DeployerConfig{ AccessKeyId: fAccessKeyId, SecretAccessKey: fSecretAccessKey, Region: fRegion, diff --git a/internal/pkg/core/deployer/providers/huaweicloud-elb/huaweicloud_elb.go b/internal/pkg/core/deployer/providers/huaweicloud-elb/huaweicloud_elb.go index 457a8541..6348f9bc 100644 --- a/internal/pkg/core/deployer/providers/huaweicloud-elb/huaweicloud_elb.go +++ b/internal/pkg/core/deployer/providers/huaweicloud-elb/huaweicloud_elb.go @@ -23,7 +23,7 @@ import ( hwsdk "github.com/usual2970/certimate/internal/pkg/vendors/huaweicloud-sdk" ) -type HuaweiCloudELBDeployerConfig struct { +type DeployerConfig struct { // 华为云 AccessKeyId。 AccessKeyId string `json:"accessKeyId"` // 华为云 SecretAccessKey。 @@ -43,28 +43,20 @@ type HuaweiCloudELBDeployerConfig struct { ListenerId string `json:"listenerId,omitempty"` } -type HuaweiCloudELBDeployer struct { - config *HuaweiCloudELBDeployerConfig +type DeployerProvider struct { + config *DeployerConfig logger logger.Logger sdkClient *hcElb.ElbClient sslUploader uploader.Uploader } -var _ deployer.Deployer = (*HuaweiCloudELBDeployer)(nil) +var _ deployer.Deployer = (*DeployerProvider)(nil) -func New(config *HuaweiCloudELBDeployerConfig) (*HuaweiCloudELBDeployer, error) { - return NewWithLogger(config, logger.NewNilLogger()) -} - -func NewWithLogger(config *HuaweiCloudELBDeployerConfig, logger logger.Logger) (*HuaweiCloudELBDeployer, error) { +func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { if config == nil { panic("config is nil") } - if logger == nil { - panic("logger is nil") - } - client, err := createSdkClient(config.AccessKeyId, config.SecretAccessKey, config.Region) if err != nil { return nil, xerrors.Wrap(err, "failed to create sdk client") @@ -79,15 +71,20 @@ func NewWithLogger(config *HuaweiCloudELBDeployerConfig, logger logger.Logger) ( return nil, xerrors.Wrap(err, "failed to create ssl uploader") } - return &HuaweiCloudELBDeployer{ - logger: logger, + return &DeployerProvider{ config: config, + logger: logger.NewNilLogger(), sdkClient: client, sslUploader: uploader, }, nil } -func (d *HuaweiCloudELBDeployer) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { +func (d *DeployerProvider) WithLogger(logger logger.Logger) *DeployerProvider { + d.logger = logger + return d +} + +func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { // 上传证书到 SCM upres, err := d.sslUploader.Upload(ctx, certPem, privkeyPem) if err != nil { @@ -120,7 +117,7 @@ func (d *HuaweiCloudELBDeployer) Deploy(ctx context.Context, certPem string, pri return &deployer.DeployResult{}, nil } -func (d *HuaweiCloudELBDeployer) deployToCertificate(ctx context.Context, certPem string, privkeyPem string) error { +func (d *DeployerProvider) deployToCertificate(ctx context.Context, certPem string, privkeyPem string) error { if d.config.CertificateId == "" { return errors.New("config `certificateId` is required") } @@ -146,7 +143,7 @@ func (d *HuaweiCloudELBDeployer) deployToCertificate(ctx context.Context, certPe return nil } -func (d *HuaweiCloudELBDeployer) deployToLoadbalancer(ctx context.Context, certPem string, privkeyPem string) error { +func (d *DeployerProvider) deployToLoadbalancer(ctx context.Context, certPem string, privkeyPem string) error { if d.config.LoadbalancerId == "" { return errors.New("config `loadbalancerId` is required") } @@ -223,7 +220,7 @@ func (d *HuaweiCloudELBDeployer) deployToLoadbalancer(ctx context.Context, certP return nil } -func (d *HuaweiCloudELBDeployer) deployToListener(ctx context.Context, certPem string, privkeyPem string) error { +func (d *DeployerProvider) deployToListener(ctx context.Context, certPem string, privkeyPem string) error { if d.config.ListenerId == "" { return errors.New("config `listenerId` is required") } @@ -244,7 +241,7 @@ func (d *HuaweiCloudELBDeployer) deployToListener(ctx context.Context, certPem s return nil } -func (d *HuaweiCloudELBDeployer) modifyListenerCertificate(ctx context.Context, cloudListenerId string, cloudCertId string) error { +func (d *DeployerProvider) modifyListenerCertificate(ctx context.Context, cloudListenerId string, cloudCertId string) error { // 查询监听器详情 // REF: https://support.huaweicloud.com/api-elb/ShowListener.html showListenerReq := &hcElbModel.ShowListenerRequest{ diff --git a/internal/pkg/core/deployer/providers/huaweicloud-elb/huaweicloud_elb_test.go b/internal/pkg/core/deployer/providers/huaweicloud-elb/huaweicloud_elb_test.go index 017f3b3c..4325ba40 100644 --- a/internal/pkg/core/deployer/providers/huaweicloud-elb/huaweicloud_elb_test.go +++ b/internal/pkg/core/deployer/providers/huaweicloud-elb/huaweicloud_elb_test.go @@ -62,7 +62,7 @@ func TestDeploy(t *testing.T) { fmt.Sprintf("CERTIFICATEID: %v", fCertificateId), }, "\n")) - deployer, err := provider.New(&provider.HuaweiCloudELBDeployerConfig{ + deployer, err := provider.NewDeployer(&provider.DeployerConfig{ AccessKeyId: fAccessKeyId, SecretAccessKey: fSecretAccessKey, Region: fRegion, @@ -96,7 +96,7 @@ func TestDeploy(t *testing.T) { fmt.Sprintf("LOADBALANCERID: %v", fLoadbalancerId), }, "\n")) - deployer, err := provider.New(&provider.HuaweiCloudELBDeployerConfig{ + deployer, err := provider.NewDeployer(&provider.DeployerConfig{ AccessKeyId: fAccessKeyId, SecretAccessKey: fSecretAccessKey, Region: fRegion, @@ -130,7 +130,7 @@ func TestDeploy(t *testing.T) { fmt.Sprintf("LISTENERID: %v", fListenerId), }, "\n")) - deployer, err := provider.New(&provider.HuaweiCloudELBDeployerConfig{ + deployer, err := provider.NewDeployer(&provider.DeployerConfig{ AccessKeyId: fAccessKeyId, SecretAccessKey: fSecretAccessKey, Region: fRegion, diff --git a/internal/pkg/core/deployer/providers/huaweicloud-waf/huaweicloud_waf.go b/internal/pkg/core/deployer/providers/huaweicloud-waf/huaweicloud_waf.go index aa77ba6a..3af42d28 100644 --- a/internal/pkg/core/deployer/providers/huaweicloud-waf/huaweicloud_waf.go +++ b/internal/pkg/core/deployer/providers/huaweicloud-waf/huaweicloud_waf.go @@ -23,7 +23,7 @@ import ( hwsdk "github.com/usual2970/certimate/internal/pkg/vendors/huaweicloud-sdk" ) -type HuaweiCloudWAFDeployerConfig struct { +type DeployerConfig struct { // 华为云 AccessKeyId。 AccessKeyId string `json:"accessKeyId"` // 华为云 SecretAccessKey。 @@ -40,28 +40,20 @@ type HuaweiCloudWAFDeployerConfig struct { Domain string `json:"domain,omitempty"` } -type HuaweiCloudWAFDeployer struct { - config *HuaweiCloudWAFDeployerConfig +type DeployerProvider struct { + config *DeployerConfig logger logger.Logger sdkClient *hcWaf.WafClient sslUploader uploader.Uploader } -var _ deployer.Deployer = (*HuaweiCloudWAFDeployer)(nil) +var _ deployer.Deployer = (*DeployerProvider)(nil) -func New(config *HuaweiCloudWAFDeployerConfig) (*HuaweiCloudWAFDeployer, error) { - return NewWithLogger(config, logger.NewNilLogger()) -} - -func NewWithLogger(config *HuaweiCloudWAFDeployerConfig, logger logger.Logger) (*HuaweiCloudWAFDeployer, error) { +func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { if config == nil { panic("config is nil") } - if logger == nil { - panic("logger is nil") - } - client, err := createSdkClient(config.AccessKeyId, config.SecretAccessKey, config.Region) if err != nil { return nil, xerrors.Wrap(err, "failed to create sdk client") @@ -76,15 +68,20 @@ func NewWithLogger(config *HuaweiCloudWAFDeployerConfig, logger logger.Logger) ( return nil, xerrors.Wrap(err, "failed to create ssl uploader") } - return &HuaweiCloudWAFDeployer{ - logger: logger, + return &DeployerProvider{ config: config, + logger: logger.NewNilLogger(), sdkClient: client, sslUploader: uploader, }, nil } -func (d *HuaweiCloudWAFDeployer) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { +func (d *DeployerProvider) WithLogger(logger logger.Logger) *DeployerProvider { + d.logger = logger + return d +} + +func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { // 上传证书到 WAF upres, err := d.sslUploader.Upload(ctx, certPem, privkeyPem) if err != nil { @@ -117,7 +114,7 @@ func (d *HuaweiCloudWAFDeployer) Deploy(ctx context.Context, certPem string, pri return &deployer.DeployResult{}, nil } -func (d *HuaweiCloudWAFDeployer) deployToCertificate(ctx context.Context, certPem string, privkeyPem string) error { +func (d *DeployerProvider) deployToCertificate(ctx context.Context, certPem string, privkeyPem string) error { if d.config.CertificateId == "" { return errors.New("config `certificateId` is required") } @@ -154,7 +151,7 @@ func (d *HuaweiCloudWAFDeployer) deployToCertificate(ctx context.Context, certPe return nil } -func (d *HuaweiCloudWAFDeployer) deployToCloudServer(ctx context.Context, certPem string, privkeyPem string) error { +func (d *DeployerProvider) deployToCloudServer(ctx context.Context, certPem string, privkeyPem string) error { if d.config.Domain == "" { return errors.New("config `domain` is required") } @@ -221,7 +218,7 @@ func (d *HuaweiCloudWAFDeployer) deployToCloudServer(ctx context.Context, certPe return nil } -func (d *HuaweiCloudWAFDeployer) deployToPremiumHost(ctx context.Context, certPem string, privkeyPem string) error { +func (d *DeployerProvider) deployToPremiumHost(ctx context.Context, certPem string, privkeyPem string) error { if d.config.Domain == "" { return errors.New("config `domain` is required") } diff --git a/internal/pkg/core/deployer/providers/huaweicloud-waf/huaweicloud_waf_test.go b/internal/pkg/core/deployer/providers/huaweicloud-waf/huaweicloud_waf_test.go index 0ec57013..83142325 100644 --- a/internal/pkg/core/deployer/providers/huaweicloud-waf/huaweicloud_waf_test.go +++ b/internal/pkg/core/deployer/providers/huaweicloud-waf/huaweicloud_waf_test.go @@ -59,7 +59,7 @@ func TestDeploy(t *testing.T) { fmt.Sprintf("RESOURCETYPE: %v", fResourceType), }, "\n")) - deployer, err := provider.New(&provider.HuaweiCloudWAFDeployerConfig{ + deployer, err := provider.NewDeployer(&provider.DeployerConfig{ AccessKeyId: fAccessKeyId, SecretAccessKey: fSecretAccessKey, Region: fRegion, diff --git a/internal/pkg/core/deployer/providers/k8s-secret/k8s_secret.go b/internal/pkg/core/deployer/providers/k8s-secret/k8s_secret.go index 22772b58..c97e4386 100644 --- a/internal/pkg/core/deployer/providers/k8s-secret/k8s_secret.go +++ b/internal/pkg/core/deployer/providers/k8s-secret/k8s_secret.go @@ -17,7 +17,7 @@ import ( "github.com/usual2970/certimate/internal/pkg/utils/certs" ) -type K8sSecretDeployerConfig struct { +type DeployerConfig struct { // kubeconfig 文件内容。 KubeConfig string `json:"kubeConfig,omitempty"` // Kubernetes 命名空间。 @@ -32,33 +32,30 @@ type K8sSecretDeployerConfig struct { SecretDataKeyForKey string `json:"secretDataKeyForKey,omitempty"` } -type K8sSecretDeployer struct { - config *K8sSecretDeployerConfig +type DeployerProvider struct { + config *DeployerConfig logger logger.Logger } -var _ deployer.Deployer = (*K8sSecretDeployer)(nil) +var _ deployer.Deployer = (*DeployerProvider)(nil) -func New(config *K8sSecretDeployerConfig) (*K8sSecretDeployer, error) { - return NewWithLogger(config, logger.NewNilLogger()) -} - -func NewWithLogger(config *K8sSecretDeployerConfig, logger logger.Logger) (*K8sSecretDeployer, error) { +func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { if config == nil { panic("config is nil") } - if logger == nil { - panic("logger is nil") - } - - return &K8sSecretDeployer{ - logger: logger, + return &DeployerProvider{ + logger: logger.NewNilLogger(), config: config, }, nil } -func (d *K8sSecretDeployer) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { +func (d *DeployerProvider) WithLogger(logger logger.Logger) *DeployerProvider { + d.logger = logger + return d +} + +func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { if d.config.Namespace == "" { return nil, errors.New("config `namespace` is required") } diff --git a/internal/pkg/core/deployer/providers/k8s-secret/k8s_secret_test.go b/internal/pkg/core/deployer/providers/k8s-secret/k8s_secret_test.go index 913099ec..75f15502 100644 --- a/internal/pkg/core/deployer/providers/k8s-secret/k8s_secret_test.go +++ b/internal/pkg/core/deployer/providers/k8s-secret/k8s_secret_test.go @@ -56,7 +56,7 @@ func TestDeploy(t *testing.T) { fmt.Sprintf("SECRETDATAKEYFORKEY: %v", fSecretDataKeyForKey), }, "\n")) - deployer, err := provider.New(&provider.K8sSecretDeployerConfig{ + deployer, err := provider.NewDeployer(&provider.DeployerConfig{ Namespace: fNamespace, SecretName: fSecretName, SecretDataKeyForCrt: fSecretDataKeyForCrt, diff --git a/internal/pkg/core/deployer/providers/local/local.go b/internal/pkg/core/deployer/providers/local/local.go index 666bb3dd..7952f63c 100644 --- a/internal/pkg/core/deployer/providers/local/local.go +++ b/internal/pkg/core/deployer/providers/local/local.go @@ -15,7 +15,7 @@ import ( "github.com/usual2970/certimate/internal/pkg/utils/files" ) -type LocalDeployerConfig struct { +type DeployerConfig struct { // Shell 执行环境。 // 零值时默认根据操作系统决定。 ShellEnv ShellEnvType `json:"shellEnv,omitempty"` @@ -43,33 +43,30 @@ type LocalDeployerConfig struct { JksStorepass string `json:"jksStorepass,omitempty"` } -type LocalDeployer struct { - config *LocalDeployerConfig +type DeployerProvider struct { + config *DeployerConfig logger logger.Logger } -var _ deployer.Deployer = (*LocalDeployer)(nil) +var _ deployer.Deployer = (*DeployerProvider)(nil) -func New(config *LocalDeployerConfig) (*LocalDeployer, error) { - return NewWithLogger(config, logger.NewNilLogger()) -} - -func NewWithLogger(config *LocalDeployerConfig, logger logger.Logger) (*LocalDeployer, error) { +func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { if config == nil { panic("config is nil") } - if logger == nil { - panic("logger is nil") - } - - return &LocalDeployer{ - logger: logger, + return &DeployerProvider{ config: config, + logger: logger.NewNilLogger(), }, nil } -func (d *LocalDeployer) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { +func (d *DeployerProvider) WithLogger(logger logger.Logger) *DeployerProvider { + d.logger = logger + return d +} + +func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { // 执行前置命令 if d.config.PreCommand != "" { stdout, stderr, err := execCommand(d.config.ShellEnv, d.config.PreCommand) diff --git a/internal/pkg/core/deployer/providers/local/local_test.go b/internal/pkg/core/deployer/providers/local/local_test.go index 723ddf58..e86ba7e0 100644 --- a/internal/pkg/core/deployer/providers/local/local_test.go +++ b/internal/pkg/core/deployer/providers/local/local_test.go @@ -72,7 +72,7 @@ func TestDeploy(t *testing.T) { fmt.Sprintf("POSTCOMMAND: %v", fPostCommand), }, "\n")) - deployer, err := provider.New(&provider.LocalDeployerConfig{ + deployer, err := provider.NewDeployer(&provider.DeployerConfig{ OutputFormat: provider.OUTPUT_FORMAT_PEM, OutputCertPath: fOutputCertPath + ".pem", OutputKeyPath: fOutputKeyPath + ".pem", @@ -123,7 +123,7 @@ func TestDeploy(t *testing.T) { fmt.Sprintf("PFXPASSWORD: %v", fPfxPassword), }, "\n")) - deployer, err := provider.New(&provider.LocalDeployerConfig{ + deployer, err := provider.NewDeployer(&provider.DeployerConfig{ OutputFormat: provider.OUTPUT_FORMAT_PFX, OutputCertPath: fOutputCertPath + ".pfx", PfxPassword: fPfxPassword, @@ -164,7 +164,7 @@ func TestDeploy(t *testing.T) { fmt.Sprintf("JKSSTOREPASS: %v", fJksStorepass), }, "\n")) - deployer, err := provider.New(&provider.LocalDeployerConfig{ + deployer, err := provider.NewDeployer(&provider.DeployerConfig{ OutputFormat: provider.OUTPUT_FORMAT_JKS, OutputCertPath: fOutputCertPath + ".jks", JksAlias: fJksAlias, diff --git a/internal/pkg/core/deployer/providers/qiniu-cdn/qiniu_cdn.go b/internal/pkg/core/deployer/providers/qiniu-cdn/qiniu_cdn.go index 49e54b1d..d0341acb 100644 --- a/internal/pkg/core/deployer/providers/qiniu-cdn/qiniu_cdn.go +++ b/internal/pkg/core/deployer/providers/qiniu-cdn/qiniu_cdn.go @@ -14,7 +14,7 @@ import ( qiniusdk "github.com/usual2970/certimate/internal/pkg/vendors/qiniu-sdk" ) -type QiniuCDNDeployerConfig struct { +type DeployerConfig struct { // 七牛云 AccessKey。 AccessKey string `json:"accessKey"` // 七牛云 SecretKey。 @@ -23,28 +23,20 @@ type QiniuCDNDeployerConfig struct { Domain string `json:"domain"` } -type QiniuCDNDeployer struct { - config *QiniuCDNDeployerConfig +type DeployerProvider struct { + config *DeployerConfig logger logger.Logger sdkClient *qiniusdk.Client sslUploader uploader.Uploader } -var _ deployer.Deployer = (*QiniuCDNDeployer)(nil) +var _ deployer.Deployer = (*DeployerProvider)(nil) -func New(config *QiniuCDNDeployerConfig) (*QiniuCDNDeployer, error) { - return NewWithLogger(config, logger.NewNilLogger()) -} - -func NewWithLogger(config *QiniuCDNDeployerConfig, logger logger.Logger) (*QiniuCDNDeployer, error) { +func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { if config == nil { panic("config is nil") } - if logger == nil { - panic("logger is nil") - } - client := qiniusdk.NewClient(auth.New(config.AccessKey, config.SecretKey)) uploader, err := uploadersp.New(&uploadersp.QiniuSSLCertUploaderConfig{ @@ -55,15 +47,20 @@ func NewWithLogger(config *QiniuCDNDeployerConfig, logger logger.Logger) (*Qiniu return nil, xerrors.Wrap(err, "failed to create ssl uploader") } - return &QiniuCDNDeployer{ - logger: logger, + return &DeployerProvider{ config: config, + logger: logger.NewNilLogger(), sdkClient: client, sslUploader: uploader, }, nil } -func (d *QiniuCDNDeployer) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { +func (d *DeployerProvider) WithLogger(logger logger.Logger) *DeployerProvider { + d.logger = logger + return d +} + +func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { // 上传证书到 CDN upres, err := d.sslUploader.Upload(ctx, certPem, privkeyPem) if err != nil { diff --git a/internal/pkg/core/deployer/providers/qiniu-cdn/qiniu_cdn_test.go b/internal/pkg/core/deployer/providers/qiniu-cdn/qiniu_cdn_test.go index 85ca8316..eff0ab48 100644 --- a/internal/pkg/core/deployer/providers/qiniu-cdn/qiniu_cdn_test.go +++ b/internal/pkg/core/deployer/providers/qiniu-cdn/qiniu_cdn_test.go @@ -52,7 +52,7 @@ func TestDeploy(t *testing.T) { fmt.Sprintf("DOMAIN: %v", fDomain), }, "\n")) - deployer, err := provider.New(&provider.QiniuCDNDeployerConfig{ + deployer, err := provider.NewDeployer(&provider.DeployerConfig{ AccessKey: fAccessKey, SecretKey: fSecretKey, Domain: fDomain, diff --git a/internal/pkg/core/deployer/providers/qiniu-pili/qiniu_pili.go b/internal/pkg/core/deployer/providers/qiniu-pili/qiniu_pili.go index a2e25d4c..8b7601b6 100644 --- a/internal/pkg/core/deployer/providers/qiniu-pili/qiniu_pili.go +++ b/internal/pkg/core/deployer/providers/qiniu-pili/qiniu_pili.go @@ -12,7 +12,7 @@ import ( uploadersp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/qiniu-sslcert" ) -type QiniuPiliDeployerConfig struct { +type DeployerConfig struct { // 七牛云 AccessKey。 AccessKey string `json:"accessKey"` // 七牛云 SecretKey。 @@ -23,28 +23,20 @@ type QiniuPiliDeployerConfig struct { Domain string `json:"domain"` } -type QiniuPiliDeployer struct { - config *QiniuPiliDeployerConfig +type DeployerProvider struct { + config *DeployerConfig logger logger.Logger sdkClient *pili.Manager sslUploader uploader.Uploader } -var _ deployer.Deployer = (*QiniuPiliDeployer)(nil) +var _ deployer.Deployer = (*DeployerProvider)(nil) -func New(config *QiniuPiliDeployerConfig) (*QiniuPiliDeployer, error) { - return NewWithLogger(config, logger.NewNilLogger()) -} - -func NewWithLogger(config *QiniuPiliDeployerConfig, logger logger.Logger) (*QiniuPiliDeployer, error) { +func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { if config == nil { panic("config is nil") } - if logger == nil { - panic("logger is nil") - } - manager := pili.NewManager(pili.ManagerConfig{AccessKey: config.AccessKey, SecretKey: config.SecretKey}) uploader, err := uploadersp.New(&uploadersp.QiniuSSLCertUploaderConfig{ @@ -55,15 +47,20 @@ func NewWithLogger(config *QiniuPiliDeployerConfig, logger logger.Logger) (*Qini return nil, xerrors.Wrap(err, "failed to create ssl uploader") } - return &QiniuPiliDeployer{ - logger: logger, + return &DeployerProvider{ config: config, + logger: logger.NewNilLogger(), sdkClient: manager, sslUploader: uploader, }, nil } -func (d *QiniuPiliDeployer) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { +func (d *DeployerProvider) WithLogger(logger logger.Logger) *DeployerProvider { + d.logger = logger + return d +} + +func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { // 上传证书到 CDN upres, err := d.sslUploader.Upload(ctx, certPem, privkeyPem) if err != nil { diff --git a/internal/pkg/core/deployer/providers/qiniu-pili/qiniu_pili_test.go b/internal/pkg/core/deployer/providers/qiniu-pili/qiniu_pili_test.go index 06ef47e4..1d307dda 100644 --- a/internal/pkg/core/deployer/providers/qiniu-pili/qiniu_pili_test.go +++ b/internal/pkg/core/deployer/providers/qiniu-pili/qiniu_pili_test.go @@ -56,7 +56,7 @@ func TestDeploy(t *testing.T) { fmt.Sprintf("DOMAIN: %v", fDomain), }, "\n")) - deployer, err := provider.New(&provider.QiniuPiliDeployerConfig{ + deployer, err := provider.NewDeployer(&provider.DeployerConfig{ AccessKey: fAccessKey, SecretKey: fSecretKey, Domain: fDomain, diff --git a/internal/pkg/core/deployer/providers/safeline/safeline.go b/internal/pkg/core/deployer/providers/safeline/safeline.go index b24f6331..3b4006c4 100644 --- a/internal/pkg/core/deployer/providers/safeline/safeline.go +++ b/internal/pkg/core/deployer/providers/safeline/safeline.go @@ -13,7 +13,7 @@ import ( safelinesdk "github.com/usual2970/certimate/internal/pkg/vendors/safeline-sdk" ) -type SafeLineDeployerConfig struct { +type DeployerConfig struct { // 雷池 URL。 ApiUrl string `json:"apiUrl"` // 雷池 API Token。 @@ -25,40 +25,37 @@ type SafeLineDeployerConfig struct { CertificateId int32 `json:"certificateId,omitempty"` } -type SafeLineDeployer struct { - config *SafeLineDeployerConfig +type DeployerProvider struct { + config *DeployerConfig logger logger.Logger sdkClient *safelinesdk.Client } -var _ deployer.Deployer = (*SafeLineDeployer)(nil) +var _ deployer.Deployer = (*DeployerProvider)(nil) -func New(config *SafeLineDeployerConfig) (*SafeLineDeployer, error) { - return NewWithLogger(config, logger.NewNilLogger()) -} - -func NewWithLogger(config *SafeLineDeployerConfig, logger logger.Logger) (*SafeLineDeployer, error) { +func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { if config == nil { panic("config is nil") } - if logger == nil { - panic("logger is nil") - } - client, err := createSdkClient(config.ApiUrl, config.ApiToken) if err != nil { return nil, xerrors.Wrap(err, "failed to create sdk clients") } - return &SafeLineDeployer{ - logger: logger, + return &DeployerProvider{ config: config, + logger: logger.NewNilLogger(), sdkClient: client, }, nil } -func (d *SafeLineDeployer) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { +func (d *DeployerProvider) WithLogger(logger logger.Logger) *DeployerProvider { + d.logger = logger + return d +} + +func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { // 根据部署资源类型决定部署方式 switch d.config.ResourceType { case RESOURCE_TYPE_CERTIFICATE: @@ -73,7 +70,7 @@ func (d *SafeLineDeployer) Deploy(ctx context.Context, certPem string, privkeyPe return &deployer.DeployResult{}, nil } -func (d *SafeLineDeployer) deployToCertificate(ctx context.Context, certPem string, privkeyPem string) error { +func (d *DeployerProvider) deployToCertificate(ctx context.Context, certPem string, privkeyPem string) error { if d.config.CertificateId == 0 { return errors.New("config `certificateId` is required") } diff --git a/internal/pkg/core/deployer/providers/safeline/safeline_test.go b/internal/pkg/core/deployer/providers/safeline/safeline_test.go index 29b5ac3a..0d7f2223 100644 --- a/internal/pkg/core/deployer/providers/safeline/safeline_test.go +++ b/internal/pkg/core/deployer/providers/safeline/safeline_test.go @@ -52,7 +52,7 @@ func TestDeploy(t *testing.T) { fmt.Sprintf("CERTIFICATEID: %v", fCertificateId), }, "\n")) - deployer, err := provider.New(&provider.SafeLineDeployerConfig{ + deployer, err := provider.NewDeployer(&provider.DeployerConfig{ ApiUrl: fApiUrl, ApiToken: fApiToken, ResourceType: provider.ResourceType("certificate"), diff --git a/internal/pkg/core/deployer/providers/ssh/ssh.go b/internal/pkg/core/deployer/providers/ssh/ssh.go index 562e6506..a1617327 100644 --- a/internal/pkg/core/deployer/providers/ssh/ssh.go +++ b/internal/pkg/core/deployer/providers/ssh/ssh.go @@ -17,7 +17,7 @@ import ( "github.com/usual2970/certimate/internal/pkg/utils/certs" ) -type SshDeployerConfig struct { +type DeployerConfig struct { // SSH 主机。 // 零值时默认为 "localhost"。 SshHost string `json:"sshHost,omitempty"` @@ -58,33 +58,30 @@ type SshDeployerConfig struct { JksStorepass string `json:"jksStorepass,omitempty"` } -type SshDeployer struct { - config *SshDeployerConfig +type DeployerProvider struct { + config *DeployerConfig logger logger.Logger } -var _ deployer.Deployer = (*SshDeployer)(nil) +var _ deployer.Deployer = (*DeployerProvider)(nil) -func New(config *SshDeployerConfig) (*SshDeployer, error) { - return NewWithLogger(config, logger.NewNilLogger()) -} - -func NewWithLogger(config *SshDeployerConfig, logger logger.Logger) (*SshDeployer, error) { +func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { if config == nil { panic("config is nil") } - if logger == nil { - panic("logger is nil") - } - - return &SshDeployer{ - logger: logger, + return &DeployerProvider{ config: config, + logger: logger.NewNilLogger(), }, nil } -func (d *SshDeployer) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { +func (d *DeployerProvider) WithLogger(logger logger.Logger) *DeployerProvider { + d.logger = logger + return d +} + +func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { // 连接 client, err := createSshClient( d.config.SshHost, diff --git a/internal/pkg/core/deployer/providers/ssh/ssh_test.go b/internal/pkg/core/deployer/providers/ssh/ssh_test.go index 4221378e..8312d680 100644 --- a/internal/pkg/core/deployer/providers/ssh/ssh_test.go +++ b/internal/pkg/core/deployer/providers/ssh/ssh_test.go @@ -64,7 +64,7 @@ func TestDeploy(t *testing.T) { fmt.Sprintf("OUTPUTKEYPATH: %v", fOutputKeyPath), }, "\n")) - deployer, err := provider.New(&provider.SshDeployerConfig{ + deployer, err := provider.NewDeployer(&provider.DeployerConfig{ SshHost: fSshHost, SshPort: int32(fSshPort), SshUsername: fSshUsername, diff --git a/internal/pkg/core/deployer/providers/tencentcloud-cdn/tencentcloud_cdn.go b/internal/pkg/core/deployer/providers/tencentcloud-cdn/tencentcloud_cdn.go index 440b78dd..42fac9db 100644 --- a/internal/pkg/core/deployer/providers/tencentcloud-cdn/tencentcloud_cdn.go +++ b/internal/pkg/core/deployer/providers/tencentcloud-cdn/tencentcloud_cdn.go @@ -17,7 +17,7 @@ import ( uploadersp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/tencentcloud-ssl" ) -type TencentCloudCDNDeployerConfig struct { +type DeployerConfig struct { // 腾讯云 SecretId。 SecretId string `json:"secretId"` // 腾讯云 SecretKey。 @@ -26,33 +26,25 @@ type TencentCloudCDNDeployerConfig struct { Domain string `json:"domain"` } -type TencentCloudCDNDeployer struct { - config *TencentCloudCDNDeployerConfig +type DeployerProvider struct { + config *DeployerConfig logger logger.Logger sdkClients *wSdkClients sslUploader uploader.Uploader } -var _ deployer.Deployer = (*TencentCloudCDNDeployer)(nil) +var _ deployer.Deployer = (*DeployerProvider)(nil) type wSdkClients struct { ssl *tcSsl.Client cdn *tcCdn.Client } -func New(config *TencentCloudCDNDeployerConfig) (*TencentCloudCDNDeployer, error) { - return NewWithLogger(config, logger.NewNilLogger()) -} - -func NewWithLogger(config *TencentCloudCDNDeployerConfig, logger logger.Logger) (*TencentCloudCDNDeployer, error) { +func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { if config == nil { panic("config is nil") } - if logger == nil { - panic("logger is nil") - } - clients, err := createSdkClients(config.SecretId, config.SecretKey) if err != nil { return nil, xerrors.Wrap(err, "failed to create sdk clients") @@ -66,15 +58,20 @@ func NewWithLogger(config *TencentCloudCDNDeployerConfig, logger logger.Logger) return nil, xerrors.Wrap(err, "failed to create ssl uploader") } - return &TencentCloudCDNDeployer{ - logger: logger, + return &DeployerProvider{ config: config, + logger: logger.NewNilLogger(), sdkClients: clients, sslUploader: uploader, }, nil } -func (d *TencentCloudCDNDeployer) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { +func (d *DeployerProvider) WithLogger(logger logger.Logger) *DeployerProvider { + d.logger = logger + return d +} + +func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { // 上传证书到 SSL upres, err := d.sslUploader.Upload(ctx, certPem, privkeyPem) if err != nil { @@ -134,7 +131,7 @@ func (d *TencentCloudCDNDeployer) Deploy(ctx context.Context, certPem string, pr return &deployer.DeployResult{}, nil } -func (d *TencentCloudCDNDeployer) getDomainsByCertificateId(cloudCertId string) ([]string, error) { +func (d *DeployerProvider) getDomainsByCertificateId(cloudCertId string) ([]string, error) { // 获取证书中的可用域名 // REF: https://cloud.tencent.com/document/product/228/42491 describeCertDomainsReq := tcCdn.NewDescribeCertDomainsRequest() @@ -155,7 +152,7 @@ func (d *TencentCloudCDNDeployer) getDomainsByCertificateId(cloudCertId string) return domains, nil } -func (d *TencentCloudCDNDeployer) getDeployedDomainsByCertificateId(cloudCertId string) ([]string, error) { +func (d *DeployerProvider) getDeployedDomainsByCertificateId(cloudCertId string) ([]string, error) { // 根据证书查询关联 CDN 域名 // REF: https://cloud.tencent.com/document/product/400/62674 describeDeployedResourcesReq := tcSsl.NewDescribeDeployedResourcesRequest() diff --git a/internal/pkg/core/deployer/providers/tencentcloud-cdn/tencentcloud_cdn_test.go b/internal/pkg/core/deployer/providers/tencentcloud-cdn/tencentcloud_cdn_test.go index 088251b1..0361e17b 100644 --- a/internal/pkg/core/deployer/providers/tencentcloud-cdn/tencentcloud_cdn_test.go +++ b/internal/pkg/core/deployer/providers/tencentcloud-cdn/tencentcloud_cdn_test.go @@ -52,7 +52,7 @@ func TestDeploy(t *testing.T) { fmt.Sprintf("DOMAIN: %v", fDomain), }, "\n")) - deployer, err := provider.New(&provider.TencentCloudCDNDeployerConfig{ + deployer, err := provider.NewDeployer(&provider.DeployerConfig{ SecretId: fSecretId, SecretKey: fSecretKey, Domain: fDomain, diff --git a/internal/pkg/core/deployer/providers/tencentcloud-clb/tencentcloud_clb.go b/internal/pkg/core/deployer/providers/tencentcloud-clb/tencentcloud_clb.go index 28307f74..196cbeb7 100644 --- a/internal/pkg/core/deployer/providers/tencentcloud-clb/tencentcloud_clb.go +++ b/internal/pkg/core/deployer/providers/tencentcloud-clb/tencentcloud_clb.go @@ -17,7 +17,7 @@ import ( uploadersp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/tencentcloud-ssl" ) -type TencentCloudCLBDeployerConfig struct { +type DeployerConfig struct { // 腾讯云 SecretId。 SecretId string `json:"secretId"` // 腾讯云 SecretKey。 @@ -37,33 +37,25 @@ type TencentCloudCLBDeployerConfig struct { Domain string `json:"domain,omitempty"` } -type TencentCloudCLBDeployer struct { - config *TencentCloudCLBDeployerConfig +type DeployerProvider struct { + config *DeployerConfig logger logger.Logger sdkClients *wSdkClients sslUploader uploader.Uploader } -var _ deployer.Deployer = (*TencentCloudCLBDeployer)(nil) +var _ deployer.Deployer = (*DeployerProvider)(nil) type wSdkClients struct { ssl *tcSsl.Client clb *tcClb.Client } -func New(config *TencentCloudCLBDeployerConfig) (*TencentCloudCLBDeployer, error) { - return NewWithLogger(config, logger.NewNilLogger()) -} - -func NewWithLogger(config *TencentCloudCLBDeployerConfig, logger logger.Logger) (*TencentCloudCLBDeployer, error) { +func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { if config == nil { panic("config is nil") } - if logger == nil { - panic("logger is nil") - } - clients, err := createSdkClients(config.SecretId, config.SecretKey, config.Region) if err != nil { return nil, xerrors.Wrap(err, "failed to create sdk clients") @@ -77,15 +69,20 @@ func NewWithLogger(config *TencentCloudCLBDeployerConfig, logger logger.Logger) return nil, xerrors.Wrap(err, "failed to create ssl uploader") } - return &TencentCloudCLBDeployer{ - logger: logger, + return &DeployerProvider{ config: config, + logger: logger.NewNilLogger(), sdkClients: clients, sslUploader: uploader, }, nil } -func (d *TencentCloudCLBDeployer) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { +func (d *DeployerProvider) WithLogger(logger logger.Logger) *DeployerProvider { + d.logger = logger + return d +} + +func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { // 上传证书到 SSL upres, err := d.sslUploader.Upload(ctx, certPem, privkeyPem) if err != nil { @@ -123,7 +120,7 @@ func (d *TencentCloudCLBDeployer) Deploy(ctx context.Context, certPem string, pr return &deployer.DeployResult{}, nil } -func (d *TencentCloudCLBDeployer) deployViaSslService(ctx context.Context, cloudCertId string) error { +func (d *DeployerProvider) deployViaSslService(ctx context.Context, cloudCertId string) error { if d.config.LoadbalancerId == "" { return errors.New("config `loadbalancerId` is required") } @@ -154,7 +151,7 @@ func (d *TencentCloudCLBDeployer) deployViaSslService(ctx context.Context, cloud return nil } -func (d *TencentCloudCLBDeployer) deployToLoadbalancer(ctx context.Context, cloudCertId string) error { +func (d *DeployerProvider) deployToLoadbalancer(ctx context.Context, cloudCertId string) error { if d.config.LoadbalancerId == "" { return errors.New("config `loadbalancerId` is required") } @@ -201,7 +198,7 @@ func (d *TencentCloudCLBDeployer) deployToLoadbalancer(ctx context.Context, clou return nil } -func (d *TencentCloudCLBDeployer) deployToListener(ctx context.Context, cloudCertId string) error { +func (d *DeployerProvider) deployToListener(ctx context.Context, cloudCertId string) error { if d.config.LoadbalancerId == "" { return errors.New("config `loadbalancerId` is required") } @@ -217,7 +214,7 @@ func (d *TencentCloudCLBDeployer) deployToListener(ctx context.Context, cloudCer return nil } -func (d *TencentCloudCLBDeployer) deployToRuleDomain(ctx context.Context, cloudCertId string) error { +func (d *DeployerProvider) deployToRuleDomain(ctx context.Context, cloudCertId string) error { if d.config.LoadbalancerId == "" { return errors.New("config `loadbalancerId` is required") } @@ -248,7 +245,7 @@ func (d *TencentCloudCLBDeployer) deployToRuleDomain(ctx context.Context, cloudC return nil } -func (d *TencentCloudCLBDeployer) modifyListenerCertificate(ctx context.Context, cloudLoadbalancerId, cloudListenerId, cloudCertId string) error { +func (d *DeployerProvider) modifyListenerCertificate(ctx context.Context, cloudLoadbalancerId, cloudListenerId, cloudCertId string) error { // 查询监听器列表 // REF: https://cloud.tencent.com/document/api/214/30686 describeListenersReq := tcClb.NewDescribeListenersRequest() diff --git a/internal/pkg/core/deployer/providers/tencentcloud-clb/tencentcloud_clb_test.go b/internal/pkg/core/deployer/providers/tencentcloud-clb/tencentcloud_clb_test.go index 6cc54e8f..0aeb1e7c 100644 --- a/internal/pkg/core/deployer/providers/tencentcloud-clb/tencentcloud_clb_test.go +++ b/internal/pkg/core/deployer/providers/tencentcloud-clb/tencentcloud_clb_test.go @@ -64,7 +64,7 @@ func TestDeploy(t *testing.T) { fmt.Sprintf("DOMAIN: %v", fDomain), }, "\n")) - deployer, err := provider.New(&provider.TencentCloudCLBDeployerConfig{ + deployer, err := provider.NewDeployer(&provider.DeployerConfig{ SecretId: fSecretId, SecretKey: fSecretKey, Region: fRegion, @@ -100,7 +100,7 @@ func TestDeploy(t *testing.T) { fmt.Sprintf("LOADBALANCERID: %v", fLoadbalancerId), }, "\n")) - deployer, err := provider.New(&provider.TencentCloudCLBDeployerConfig{ + deployer, err := provider.NewDeployer(&provider.DeployerConfig{ SecretId: fSecretId, SecretKey: fSecretKey, Region: fRegion, @@ -135,7 +135,7 @@ func TestDeploy(t *testing.T) { fmt.Sprintf("LISTENERID: %v", fListenerId), }, "\n")) - deployer, err := provider.New(&provider.TencentCloudCLBDeployerConfig{ + deployer, err := provider.NewDeployer(&provider.DeployerConfig{ SecretId: fSecretId, SecretKey: fSecretKey, Region: fRegion, @@ -172,7 +172,7 @@ func TestDeploy(t *testing.T) { fmt.Sprintf("DOMAIN: %v", fDomain), }, "\n")) - deployer, err := provider.New(&provider.TencentCloudCLBDeployerConfig{ + deployer, err := provider.NewDeployer(&provider.DeployerConfig{ SecretId: fSecretId, SecretKey: fSecretKey, Region: fRegion, diff --git a/internal/pkg/core/deployer/providers/tencentcloud-cos/tencentcloud_cos.go b/internal/pkg/core/deployer/providers/tencentcloud-cos/tencentcloud_cos.go index 72653dcd..7f696305 100644 --- a/internal/pkg/core/deployer/providers/tencentcloud-cos/tencentcloud_cos.go +++ b/internal/pkg/core/deployer/providers/tencentcloud-cos/tencentcloud_cos.go @@ -16,7 +16,7 @@ import ( uploadersp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/tencentcloud-ssl" ) -type TencentCloudCOSDeployerConfig struct { +type DeployerConfig struct { // 腾讯云 SecretId。 SecretId string `json:"secretId"` // 腾讯云 SecretKey。 @@ -29,28 +29,20 @@ type TencentCloudCOSDeployerConfig struct { Domain string `json:"domain"` } -type TencentCloudCOSDeployer struct { - config *TencentCloudCOSDeployerConfig +type DeployerProvider struct { + config *DeployerConfig logger logger.Logger sdkClient *tcSsl.Client sslUploader uploader.Uploader } -var _ deployer.Deployer = (*TencentCloudCOSDeployer)(nil) +var _ deployer.Deployer = (*DeployerProvider)(nil) -func New(config *TencentCloudCOSDeployerConfig) (*TencentCloudCOSDeployer, error) { - return NewWithLogger(config, logger.NewNilLogger()) -} - -func NewWithLogger(config *TencentCloudCOSDeployerConfig, logger logger.Logger) (*TencentCloudCOSDeployer, error) { +func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { if config == nil { panic("config is nil") } - if logger == nil { - panic("logger is nil") - } - client, err := createSdkClient(config.SecretId, config.SecretKey, config.Region) if err != nil { return nil, xerrors.Wrap(err, "failed to create sdk clients") @@ -64,15 +56,20 @@ func NewWithLogger(config *TencentCloudCOSDeployerConfig, logger logger.Logger) return nil, xerrors.Wrap(err, "failed to create ssl uploader") } - return &TencentCloudCOSDeployer{ - logger: logger, + return &DeployerProvider{ config: config, + logger: logger.NewNilLogger(), sdkClient: client, sslUploader: uploader, }, nil } -func (d *TencentCloudCOSDeployer) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { +func (d *DeployerProvider) WithLogger(logger logger.Logger) *DeployerProvider { + d.logger = logger + return d +} + +func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { if d.config.Bucket == "" { return nil, errors.New("config `bucket` is required") } diff --git a/internal/pkg/core/deployer/providers/tencentcloud-cos/tencentcloud_cos_test.go b/internal/pkg/core/deployer/providers/tencentcloud-cos/tencentcloud_cos_test.go index ee035ed8..ab29a893 100644 --- a/internal/pkg/core/deployer/providers/tencentcloud-cos/tencentcloud_cos_test.go +++ b/internal/pkg/core/deployer/providers/tencentcloud-cos/tencentcloud_cos_test.go @@ -60,7 +60,7 @@ func TestDeploy(t *testing.T) { fmt.Sprintf("DOMAIN: %v", fDomain), }, "\n")) - deployer, err := provider.New(&provider.TencentCloudCOSDeployerConfig{ + deployer, err := provider.NewDeployer(&provider.DeployerConfig{ SecretId: fSecretId, SecretKey: fSecretKey, Region: fRegion, diff --git a/internal/pkg/core/deployer/providers/tencentcloud-css/tencentcloud_css.go b/internal/pkg/core/deployer/providers/tencentcloud-css/tencentcloud_css.go index 205649e5..1696e00b 100644 --- a/internal/pkg/core/deployer/providers/tencentcloud-css/tencentcloud_css.go +++ b/internal/pkg/core/deployer/providers/tencentcloud-css/tencentcloud_css.go @@ -14,7 +14,7 @@ import ( uploadersp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/tencentcloud-ssl" ) -type TencentCloudCSSDeployerConfig struct { +type DeployerConfig struct { // 腾讯云 SecretId。 SecretId string `json:"secretId"` // 腾讯云 SecretKey。 @@ -23,28 +23,20 @@ type TencentCloudCSSDeployerConfig struct { Domain string `json:"domain"` } -type TencentCloudCSSDeployer struct { - config *TencentCloudCSSDeployerConfig +type DeployerProvider struct { + config *DeployerConfig logger logger.Logger sdkClient *tcLive.Client sslUploader uploader.Uploader } -var _ deployer.Deployer = (*TencentCloudCSSDeployer)(nil) +var _ deployer.Deployer = (*DeployerProvider)(nil) -func New(config *TencentCloudCSSDeployerConfig) (*TencentCloudCSSDeployer, error) { - return NewWithLogger(config, logger.NewNilLogger()) -} - -func NewWithLogger(config *TencentCloudCSSDeployerConfig, logger logger.Logger) (*TencentCloudCSSDeployer, error) { +func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { if config == nil { panic("config is nil") } - if logger == nil { - panic("logger is nil") - } - client, err := createSdkClient(config.SecretId, config.SecretKey) if err != nil { return nil, xerrors.Wrap(err, "failed to create sdk client") @@ -58,15 +50,20 @@ func NewWithLogger(config *TencentCloudCSSDeployerConfig, logger logger.Logger) return nil, xerrors.Wrap(err, "failed to create ssl uploader") } - return &TencentCloudCSSDeployer{ - logger: logger, + return &DeployerProvider{ config: config, + logger: logger.NewNilLogger(), sdkClient: client, sslUploader: uploader, }, nil } -func (d *TencentCloudCSSDeployer) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { +func (d *DeployerProvider) WithLogger(logger logger.Logger) *DeployerProvider { + d.logger = logger + return d +} + +func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { // 上传证书到 SSL upres, err := d.sslUploader.Upload(ctx, certPem, privkeyPem) if err != nil { diff --git a/internal/pkg/core/deployer/providers/tencentcloud-css/tencentcloud_css_test.go b/internal/pkg/core/deployer/providers/tencentcloud-css/tencentcloud_css_test.go index 4efe7bba..92127b3b 100644 --- a/internal/pkg/core/deployer/providers/tencentcloud-css/tencentcloud_css_test.go +++ b/internal/pkg/core/deployer/providers/tencentcloud-css/tencentcloud_css_test.go @@ -52,7 +52,7 @@ func TestDeploy(t *testing.T) { fmt.Sprintf("DOMAIN: %v", fDomain), }, "\n")) - deployer, err := provider.New(&provider.TencentCloudCSSDeployerConfig{ + deployer, err := provider.NewDeployer(&provider.DeployerConfig{ SecretId: fSecretId, SecretKey: fSecretKey, Domain: fDomain, diff --git a/internal/pkg/core/deployer/providers/tencentcloud-ecdn/tencentcloud_ecdn.go b/internal/pkg/core/deployer/providers/tencentcloud-ecdn/tencentcloud_ecdn.go index 47349a73..22b83d8b 100644 --- a/internal/pkg/core/deployer/providers/tencentcloud-ecdn/tencentcloud_ecdn.go +++ b/internal/pkg/core/deployer/providers/tencentcloud-ecdn/tencentcloud_ecdn.go @@ -16,7 +16,7 @@ import ( uploadersp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/tencentcloud-ssl" ) -type TencentCloudECDNDeployerConfig struct { +type DeployerConfig struct { // 腾讯云 SecretId。 SecretId string `json:"secretId"` // 腾讯云 SecretKey。 @@ -25,33 +25,25 @@ type TencentCloudECDNDeployerConfig struct { Domain string `json:"domain"` } -type TencentCloudECDNDeployer struct { - config *TencentCloudECDNDeployerConfig +type DeployerProvider struct { + config *DeployerConfig logger logger.Logger sdkClients *wSdkClients sslUploader uploader.Uploader } -var _ deployer.Deployer = (*TencentCloudECDNDeployer)(nil) +var _ deployer.Deployer = (*DeployerProvider)(nil) type wSdkClients struct { ssl *tcSsl.Client cdn *tcCdn.Client } -func New(config *TencentCloudECDNDeployerConfig) (*TencentCloudECDNDeployer, error) { - return NewWithLogger(config, logger.NewNilLogger()) -} - -func NewWithLogger(config *TencentCloudECDNDeployerConfig, logger logger.Logger) (*TencentCloudECDNDeployer, error) { +func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { if config == nil { panic("config is nil") } - if logger == nil { - panic("logger is nil") - } - clients, err := createSdkClients(config.SecretId, config.SecretKey) if err != nil { return nil, xerrors.Wrap(err, "failed to create sdk clients") @@ -65,15 +57,20 @@ func NewWithLogger(config *TencentCloudECDNDeployerConfig, logger logger.Logger) return nil, xerrors.Wrap(err, "failed to create ssl uploader") } - return &TencentCloudECDNDeployer{ - logger: logger, + return &DeployerProvider{ config: config, + logger: logger.NewNilLogger(), sdkClients: clients, sslUploader: uploader, }, nil } -func (d *TencentCloudECDNDeployer) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { +func (d *DeployerProvider) WithLogger(logger logger.Logger) *DeployerProvider { + d.logger = logger + return d +} + +func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { // 上传证书到 SSL upres, err := d.sslUploader.Upload(ctx, certPem, privkeyPem) if err != nil { @@ -117,7 +114,7 @@ func (d *TencentCloudECDNDeployer) Deploy(ctx context.Context, certPem string, p return &deployer.DeployResult{}, nil } -func (d *TencentCloudECDNDeployer) getDomainsByCertificateId(cloudCertId string) ([]string, error) { +func (d *DeployerProvider) getDomainsByCertificateId(cloudCertId string) ([]string, error) { // 获取证书中的可用域名 // REF: https://cloud.tencent.com/document/product/228/42491 describeCertDomainsReq := tcCdn.NewDescribeCertDomainsRequest() diff --git a/internal/pkg/core/deployer/providers/tencentcloud-ecdn/tencentcloud_ecdn_test.go b/internal/pkg/core/deployer/providers/tencentcloud-ecdn/tencentcloud_ecdn_test.go index 764aa5fb..da03a7ab 100644 --- a/internal/pkg/core/deployer/providers/tencentcloud-ecdn/tencentcloud_ecdn_test.go +++ b/internal/pkg/core/deployer/providers/tencentcloud-ecdn/tencentcloud_ecdn_test.go @@ -52,7 +52,7 @@ func TestDeploy(t *testing.T) { fmt.Sprintf("DOMAIN: %v", fDomain), }, "\n")) - deployer, err := provider.New(&provider.TencentCloudECDNDeployerConfig{ + deployer, err := provider.NewDeployer(&provider.DeployerConfig{ SecretId: fSecretId, SecretKey: fSecretKey, Domain: fDomain, diff --git a/internal/pkg/core/deployer/providers/tencentcloud-eo/tencentcloud_eo.go b/internal/pkg/core/deployer/providers/tencentcloud-eo/tencentcloud_eo.go index 90129cc4..0ce55840 100644 --- a/internal/pkg/core/deployer/providers/tencentcloud-eo/tencentcloud_eo.go +++ b/internal/pkg/core/deployer/providers/tencentcloud-eo/tencentcloud_eo.go @@ -16,7 +16,7 @@ import ( uploadersp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/tencentcloud-ssl" ) -type TencentCloudEODeployerConfig struct { +type DeployerConfig struct { // 腾讯云 SecretId。 SecretId string `json:"secretId"` // 腾讯云 SecretKey。 @@ -27,33 +27,25 @@ type TencentCloudEODeployerConfig struct { Domain string `json:"domain"` } -type TencentCloudEODeployer struct { - config *TencentCloudEODeployerConfig +type DeployerProvider struct { + config *DeployerConfig logger logger.Logger sdkClients *wSdkClients sslUploader uploader.Uploader } -var _ deployer.Deployer = (*TencentCloudEODeployer)(nil) +var _ deployer.Deployer = (*DeployerProvider)(nil) type wSdkClients struct { ssl *tcSsl.Client teo *tcTeo.Client } -func New(config *TencentCloudEODeployerConfig) (*TencentCloudEODeployer, error) { - return NewWithLogger(config, logger.NewNilLogger()) -} - -func NewWithLogger(config *TencentCloudEODeployerConfig, logger logger.Logger) (*TencentCloudEODeployer, error) { +func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { if config == nil { panic("config is nil") } - if logger == nil { - panic("logger is nil") - } - clients, err := createSdkClients(config.SecretId, config.SecretKey) if err != nil { return nil, xerrors.Wrap(err, "failed to create sdk clients") @@ -67,15 +59,20 @@ func NewWithLogger(config *TencentCloudEODeployerConfig, logger logger.Logger) ( return nil, xerrors.Wrap(err, "failed to create ssl uploader") } - return &TencentCloudEODeployer{ - logger: logger, + return &DeployerProvider{ config: config, + logger: logger.NewNilLogger(), sdkClients: clients, sslUploader: uploader, }, nil } -func (d *TencentCloudEODeployer) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { +func (d *DeployerProvider) WithLogger(logger logger.Logger) *DeployerProvider { + d.logger = logger + return d +} + +func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { if d.config.ZoneId == "" { return nil, errors.New("config `zoneId` is required") } diff --git a/internal/pkg/core/deployer/providers/tencentcloud-eo/tencentcloud_eo_test.go b/internal/pkg/core/deployer/providers/tencentcloud-eo/tencentcloud_eo_test.go index 0e280a91..8e5b70fe 100644 --- a/internal/pkg/core/deployer/providers/tencentcloud-eo/tencentcloud_eo_test.go +++ b/internal/pkg/core/deployer/providers/tencentcloud-eo/tencentcloud_eo_test.go @@ -56,7 +56,7 @@ func TestDeploy(t *testing.T) { fmt.Sprintf("DOMAIN: %v", fDomain), }, "\n")) - deployer, err := provider.New(&provider.TencentCloudEODeployerConfig{ + deployer, err := provider.NewDeployer(&provider.DeployerConfig{ SecretId: fSecretId, SecretKey: fSecretKey, ZoneId: fZoneId, diff --git a/internal/pkg/core/deployer/providers/tencentcloud-ssl-deploy/tencentcloud_ssl_deploy.go b/internal/pkg/core/deployer/providers/tencentcloud-ssl-deploy/tencentcloud_ssl_deploy.go index bab0c627..527bfa51 100644 --- a/internal/pkg/core/deployer/providers/tencentcloud-ssl-deploy/tencentcloud_ssl_deploy.go +++ b/internal/pkg/core/deployer/providers/tencentcloud-ssl-deploy/tencentcloud_ssl_deploy.go @@ -17,7 +17,7 @@ import ( uploadersp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/tencentcloud-ssl" ) -type TencentCloudSSLDeployDeployerConfig struct { +type DeployerConfig struct { // 腾讯云 SecretId。 SecretId string `json:"secretId"` // 腾讯云 SecretKey。 @@ -30,28 +30,20 @@ type TencentCloudSSLDeployDeployerConfig struct { ResourceIds []string `json:"resourceIds"` } -type TencentCloudSSLDeployDeployer struct { - config *TencentCloudSSLDeployDeployerConfig +type DeployerProvider struct { + config *DeployerConfig logger logger.Logger sdkClient *tcSsl.Client sslUploader uploader.Uploader } -var _ deployer.Deployer = (*TencentCloudSSLDeployDeployer)(nil) +var _ deployer.Deployer = (*DeployerProvider)(nil) -func New(config *TencentCloudSSLDeployDeployerConfig) (*TencentCloudSSLDeployDeployer, error) { - return NewWithLogger(config, logger.NewNilLogger()) -} - -func NewWithLogger(config *TencentCloudSSLDeployDeployerConfig, logger logger.Logger) (*TencentCloudSSLDeployDeployer, error) { +func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { if config == nil { panic("config is nil") } - if logger == nil { - panic("logger is nil") - } - client, err := createSdkClient(config.SecretId, config.SecretKey, config.Region) if err != nil { return nil, xerrors.Wrap(err, "failed to create sdk client") @@ -65,15 +57,20 @@ func NewWithLogger(config *TencentCloudSSLDeployDeployerConfig, logger logger.Lo return nil, xerrors.Wrap(err, "failed to create ssl uploader") } - return &TencentCloudSSLDeployDeployer{ - logger: logger, + return &DeployerProvider{ config: config, + logger: logger.NewNilLogger(), sdkClient: client, sslUploader: uploader, }, nil } -func (d *TencentCloudSSLDeployDeployer) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { +func (d *DeployerProvider) WithLogger(logger logger.Logger) *DeployerProvider { + d.logger = logger + return d +} + +func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { if d.config.ResourceType == "" { return nil, errors.New("config `resourceType` is required") } diff --git a/internal/pkg/core/deployer/providers/tencentcloud-waf/tencentcloud_waf.go b/internal/pkg/core/deployer/providers/tencentcloud-waf/tencentcloud_waf.go index 631750eb..a51335c8 100644 --- a/internal/pkg/core/deployer/providers/tencentcloud-waf/tencentcloud_waf.go +++ b/internal/pkg/core/deployer/providers/tencentcloud-waf/tencentcloud_waf.go @@ -15,7 +15,7 @@ import ( uploadersp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/tencentcloud-ssl" ) -type TencentCloudWAFDeployerConfig struct { +type DeployerConfig struct { // 腾讯云 SecretId。 SecretId string `json:"secretId"` // 腾讯云 SecretKey。 @@ -30,28 +30,20 @@ type TencentCloudWAFDeployerConfig struct { InstanceId string `json:"instanceId"` } -type TencentCloudWAFDeployer struct { - config *TencentCloudWAFDeployerConfig +type DeployerProvider struct { + config *DeployerConfig logger logger.Logger sdkClient *tcWaf.Client sslUploader uploader.Uploader } -var _ deployer.Deployer = (*TencentCloudWAFDeployer)(nil) +var _ deployer.Deployer = (*DeployerProvider)(nil) -func New(config *TencentCloudWAFDeployerConfig) (*TencentCloudWAFDeployer, error) { - return NewWithLogger(config, logger.NewNilLogger()) -} - -func NewWithLogger(config *TencentCloudWAFDeployerConfig, logger logger.Logger) (*TencentCloudWAFDeployer, error) { +func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { if config == nil { panic("config is nil") } - if logger == nil { - panic("logger is nil") - } - client, err := createSdkClient(config.SecretId, config.SecretKey, config.Region) if err != nil { return nil, xerrors.Wrap(err, "failed to create sdk clients") @@ -65,15 +57,20 @@ func NewWithLogger(config *TencentCloudWAFDeployerConfig, logger logger.Logger) return nil, xerrors.Wrap(err, "failed to create ssl uploader") } - return &TencentCloudWAFDeployer{ - logger: logger, + return &DeployerProvider{ config: config, + logger: logger.NewNilLogger(), sdkClient: client, sslUploader: uploader, }, nil } -func (d *TencentCloudWAFDeployer) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { +func (d *DeployerProvider) WithLogger(logger logger.Logger) *DeployerProvider { + d.logger = logger + return d +} + +func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { if d.config.Domain == "" { return nil, errors.New("config `domain` is required") } diff --git a/internal/pkg/core/deployer/providers/tencentcloud-waf/tencentcloud_waf_test.go b/internal/pkg/core/deployer/providers/tencentcloud-waf/tencentcloud_waf_test.go index 98ee2d49..42ba1ffe 100644 --- a/internal/pkg/core/deployer/providers/tencentcloud-waf/tencentcloud_waf_test.go +++ b/internal/pkg/core/deployer/providers/tencentcloud-waf/tencentcloud_waf_test.go @@ -63,7 +63,7 @@ func TestDeploy(t *testing.T) { fmt.Sprintf("INSTANCEID: %v", fInstanceId), }, "\n")) - deployer, err := provider.New(&provider.TencentCloudWAFDeployerConfig{ + deployer, err := provider.NewDeployer(&provider.DeployerConfig{ SecretId: fSecretId, SecretKey: fSecretKey, Region: fRegion, diff --git a/internal/pkg/core/deployer/providers/ucloud-ucdn/ucloud_ucdn.go b/internal/pkg/core/deployer/providers/ucloud-ucdn/ucloud_ucdn.go index 4cb373ab..47acc5a0 100644 --- a/internal/pkg/core/deployer/providers/ucloud-ucdn/ucloud_ucdn.go +++ b/internal/pkg/core/deployer/providers/ucloud-ucdn/ucloud_ucdn.go @@ -16,7 +16,7 @@ import ( uploadersp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/ucloud-ussl" ) -type UCloudUCDNDeployerConfig struct { +type DeployerConfig struct { // 优刻得 API 私钥。 PrivateKey string `json:"privateKey"` // 优刻得 API 公钥。 @@ -27,28 +27,20 @@ type UCloudUCDNDeployerConfig struct { DomainId string `json:"domainId"` } -type UCloudUCDNDeployer struct { - config *UCloudUCDNDeployerConfig +type DeployerProvider struct { + config *DeployerConfig logger logger.Logger sdkClient *uCdn.UCDNClient sslUploader uploader.Uploader } -var _ deployer.Deployer = (*UCloudUCDNDeployer)(nil) +var _ deployer.Deployer = (*DeployerProvider)(nil) -func New(config *UCloudUCDNDeployerConfig) (*UCloudUCDNDeployer, error) { - return NewWithLogger(config, logger.NewNilLogger()) -} - -func NewWithLogger(config *UCloudUCDNDeployerConfig, logger logger.Logger) (*UCloudUCDNDeployer, error) { +func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { if config == nil { panic("config is nil") } - if logger == nil { - panic("logger is nil") - } - client, err := createSdkClient(config.PrivateKey, config.PublicKey) if err != nil { return nil, xerrors.Wrap(err, "failed to create sdk client") @@ -63,15 +55,20 @@ func NewWithLogger(config *UCloudUCDNDeployerConfig, logger logger.Logger) (*UCl return nil, xerrors.Wrap(err, "failed to create ssl uploader") } - return &UCloudUCDNDeployer{ - logger: logger, + return &DeployerProvider{ config: config, + logger: logger.NewNilLogger(), sdkClient: client, sslUploader: uploader, }, nil } -func (d *UCloudUCDNDeployer) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { +func (d *DeployerProvider) WithLogger(logger logger.Logger) *DeployerProvider { + d.logger = logger + return d +} + +func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { // 上传证书到 USSL upres, err := d.sslUploader.Upload(ctx, certPem, privkeyPem) if err != nil { diff --git a/internal/pkg/core/deployer/providers/ucloud-ucdn/ucloud_ucdn_test.go b/internal/pkg/core/deployer/providers/ucloud-ucdn/ucloud_ucdn_test.go index d8b703b5..fc952da1 100644 --- a/internal/pkg/core/deployer/providers/ucloud-ucdn/ucloud_ucdn_test.go +++ b/internal/pkg/core/deployer/providers/ucloud-ucdn/ucloud_ucdn_test.go @@ -52,7 +52,7 @@ func TestDeploy(t *testing.T) { fmt.Sprintf("DOMAIN: %v", fDomainId), }, "\n")) - deployer, err := provider.New(&provider.UCloudUCDNDeployerConfig{ + deployer, err := provider.NewDeployer(&provider.DeployerConfig{ PrivateKey: fPrivateKey, PublicKey: fPublicKey, DomainId: fDomainId, diff --git a/internal/pkg/core/deployer/providers/ucloud-us3/ucloud_us3.go b/internal/pkg/core/deployer/providers/ucloud-us3/ucloud_us3.go index c7787a31..f648c896 100644 --- a/internal/pkg/core/deployer/providers/ucloud-us3/ucloud_us3.go +++ b/internal/pkg/core/deployer/providers/ucloud-us3/ucloud_us3.go @@ -14,7 +14,7 @@ import ( usdkFile "github.com/usual2970/certimate/internal/pkg/vendors/ucloud-sdk/ufile" ) -type UCloudUS3DeployerConfig struct { +type DeployerConfig struct { // 优刻得 API 私钥。 PrivateKey string `json:"privateKey"` // 优刻得 API 公钥。 @@ -29,28 +29,20 @@ type UCloudUS3DeployerConfig struct { Domain string `json:"domain"` } -type UCloudUS3Deployer struct { - config *UCloudUS3DeployerConfig +type DeployerProvider struct { + config *DeployerConfig logger logger.Logger sdkClient *usdkFile.UFileClient sslUploader uploader.Uploader } -var _ deployer.Deployer = (*UCloudUS3Deployer)(nil) +var _ deployer.Deployer = (*DeployerProvider)(nil) -func New(config *UCloudUS3DeployerConfig) (*UCloudUS3Deployer, error) { - return NewWithLogger(config, logger.NewNilLogger()) -} - -func NewWithLogger(config *UCloudUS3DeployerConfig, logger logger.Logger) (*UCloudUS3Deployer, error) { +func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { if config == nil { panic("config is nil") } - if logger == nil { - panic("logger is nil") - } - client, err := createSdkClient(config.PrivateKey, config.PublicKey, config.Region) if err != nil { return nil, xerrors.Wrap(err, "failed to create sdk client") @@ -65,15 +57,20 @@ func NewWithLogger(config *UCloudUS3DeployerConfig, logger logger.Logger) (*UClo return nil, xerrors.Wrap(err, "failed to create ssl uploader") } - return &UCloudUS3Deployer{ - logger: logger, + return &DeployerProvider{ config: config, + logger: logger.NewNilLogger(), sdkClient: client, sslUploader: uploader, }, nil } -func (d *UCloudUS3Deployer) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { +func (d *DeployerProvider) WithLogger(logger logger.Logger) *DeployerProvider { + d.logger = logger + return d +} + +func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { // 上传证书到 USSL upres, err := d.sslUploader.Upload(ctx, certPem, privkeyPem) if err != nil { diff --git a/internal/pkg/core/deployer/providers/ucloud-us3/ucloud_us3_test.go b/internal/pkg/core/deployer/providers/ucloud-us3/ucloud_us3_test.go index e4175bfc..52f78664 100644 --- a/internal/pkg/core/deployer/providers/ucloud-us3/ucloud_us3_test.go +++ b/internal/pkg/core/deployer/providers/ucloud-us3/ucloud_us3_test.go @@ -60,7 +60,7 @@ func TestDeploy(t *testing.T) { fmt.Sprintf("DOMAIN: %v", fDomain), }, "\n")) - deployer, err := provider.New(&provider.UCloudUS3DeployerConfig{ + deployer, err := provider.NewDeployer(&provider.DeployerConfig{ PrivateKey: fPrivateKey, PublicKey: fPublicKey, Region: fRegion, diff --git a/internal/pkg/core/deployer/providers/volcengine-cdn/volcengine_cdn.go b/internal/pkg/core/deployer/providers/volcengine-cdn/volcengine_cdn.go index dc631669..b1852e6c 100644 --- a/internal/pkg/core/deployer/providers/volcengine-cdn/volcengine_cdn.go +++ b/internal/pkg/core/deployer/providers/volcengine-cdn/volcengine_cdn.go @@ -15,7 +15,7 @@ import ( uploadersp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/volcengine-cdn" ) -type VolcEngineCDNDeployerConfig struct { +type DeployerConfig struct { // 火山引擎 AccessKeyId。 AccessKeyId string `json:"accessKeyId"` // 火山引擎 AccessKeySecret。 @@ -24,28 +24,20 @@ type VolcEngineCDNDeployerConfig struct { Domain string `json:"domain"` } -type VolcEngineCDNDeployer struct { - config *VolcEngineCDNDeployerConfig +type DeployerProvider struct { + config *DeployerConfig logger logger.Logger sdkClient *veCdn.CDN sslUploader uploader.Uploader } -var _ deployer.Deployer = (*VolcEngineCDNDeployer)(nil) +var _ deployer.Deployer = (*DeployerProvider)(nil) -func New(config *VolcEngineCDNDeployerConfig) (*VolcEngineCDNDeployer, error) { - return NewWithLogger(config, logger.NewNilLogger()) -} - -func NewWithLogger(config *VolcEngineCDNDeployerConfig, logger logger.Logger) (*VolcEngineCDNDeployer, error) { +func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { if config == nil { panic("config is nil") } - if logger == nil { - panic("logger is nil") - } - client := veCdn.NewInstance() client.Client.SetAccessKey(config.AccessKeyId) client.Client.SetSecretKey(config.AccessKeySecret) @@ -58,15 +50,20 @@ func NewWithLogger(config *VolcEngineCDNDeployerConfig, logger logger.Logger) (* return nil, xerrors.Wrap(err, "failed to create ssl uploader") } - return &VolcEngineCDNDeployer{ - logger: logger, + return &DeployerProvider{ config: config, + logger: logger.NewNilLogger(), sdkClient: client, sslUploader: uploader, }, nil } -func (d *VolcEngineCDNDeployer) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { +func (d *DeployerProvider) WithLogger(logger logger.Logger) *DeployerProvider { + d.logger = logger + return d +} + +func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { // 上传证书到 CDN upres, err := d.sslUploader.Upload(ctx, certPem, privkeyPem) if err != nil { diff --git a/internal/pkg/core/deployer/providers/volcengine-cdn/volcengine_cdn_test.go b/internal/pkg/core/deployer/providers/volcengine-cdn/volcengine_cdn_test.go index 3a3ff62d..c94b9828 100644 --- a/internal/pkg/core/deployer/providers/volcengine-cdn/volcengine_cdn_test.go +++ b/internal/pkg/core/deployer/providers/volcengine-cdn/volcengine_cdn_test.go @@ -52,7 +52,7 @@ func TestDeploy(t *testing.T) { fmt.Sprintf("DOMAIN: %v", fDomain), }, "\n")) - deployer, err := provider.New(&provider.VolcEngineCDNDeployerConfig{ + deployer, err := provider.NewDeployer(&provider.DeployerConfig{ AccessKeyId: fAccessKeyId, AccessKeySecret: fAccessKeySecret, Domain: fDomain, diff --git a/internal/pkg/core/deployer/providers/volcengine-clb/volcengine_clb.go b/internal/pkg/core/deployer/providers/volcengine-clb/volcengine_clb.go index b06b0142..51b56a5f 100644 --- a/internal/pkg/core/deployer/providers/volcengine-clb/volcengine_clb.go +++ b/internal/pkg/core/deployer/providers/volcengine-clb/volcengine_clb.go @@ -16,7 +16,7 @@ import ( uploadersp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/volcengine-certcenter" ) -type VolcEngineCLBDeployerConfig struct { +type DeployerConfig struct { // 火山引擎 AccessKeyId。 AccessKeyId string `json:"accessKeyId"` // 火山引擎 AccessKeySecret。 @@ -30,28 +30,20 @@ type VolcEngineCLBDeployerConfig struct { ListenerId string `json:"listenerId,omitempty"` } -type VolcEngineCLBDeployer struct { - config *VolcEngineCLBDeployerConfig +type DeployerProvider struct { + config *DeployerConfig logger logger.Logger sdkClient *veClb.CLB sslUploader uploader.Uploader } -var _ deployer.Deployer = (*VolcEngineCLBDeployer)(nil) +var _ deployer.Deployer = (*DeployerProvider)(nil) -func New(config *VolcEngineCLBDeployerConfig) (*VolcEngineCLBDeployer, error) { - return NewWithLogger(config, logger.NewNilLogger()) -} - -func NewWithLogger(config *VolcEngineCLBDeployerConfig, logger logger.Logger) (*VolcEngineCLBDeployer, error) { +func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { if config == nil { panic("config is nil") } - if logger == nil { - panic("logger is nil") - } - client, err := createSdkClient(config.AccessKeyId, config.AccessKeySecret, config.Region) if err != nil { return nil, xerrors.Wrap(err, "failed to create sdk client") @@ -66,15 +58,19 @@ func NewWithLogger(config *VolcEngineCLBDeployerConfig, logger logger.Logger) (* return nil, xerrors.Wrap(err, "failed to create ssl uploader") } - return &VolcEngineCLBDeployer{ - logger: logger, + return &DeployerProvider{ config: config, sdkClient: client, sslUploader: uploader, }, nil } -func (d *VolcEngineCLBDeployer) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { +func (d *DeployerProvider) WithLogger(logger logger.Logger) *DeployerProvider { + d.logger = logger + return d +} + +func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { // 上传证书到证书中心 upres, err := d.sslUploader.Upload(ctx, certPem, privkeyPem) if err != nil { @@ -97,7 +93,7 @@ func (d *VolcEngineCLBDeployer) Deploy(ctx context.Context, certPem string, priv return &deployer.DeployResult{}, nil } -func (d *VolcEngineCLBDeployer) deployToListener(ctx context.Context, cloudCertId string) error { +func (d *DeployerProvider) deployToListener(ctx context.Context, cloudCertId string) error { if d.config.ListenerId == "" { return errors.New("config `listenerId` is required") } diff --git a/internal/pkg/core/deployer/providers/volcengine-clb/volcengine_clb_test.go b/internal/pkg/core/deployer/providers/volcengine-clb/volcengine_clb_test.go index 730052a0..0b589f88 100644 --- a/internal/pkg/core/deployer/providers/volcengine-clb/volcengine_clb_test.go +++ b/internal/pkg/core/deployer/providers/volcengine-clb/volcengine_clb_test.go @@ -56,7 +56,7 @@ func TestDeploy(t *testing.T) { fmt.Sprintf("LISTENERID: %v", fListenerId), }, "\n")) - deployer, err := provider.New(&provider.VolcEngineCLBDeployerConfig{ + deployer, err := provider.NewDeployer(&provider.DeployerConfig{ AccessKeyId: fAccessKeyId, AccessKeySecret: fAccessKeySecret, Region: fRegion, diff --git a/internal/pkg/core/deployer/providers/volcengine-dcdn/volcengine_dcdn.go b/internal/pkg/core/deployer/providers/volcengine-dcdn/volcengine_dcdn.go index 9e7aa896..7c775efe 100644 --- a/internal/pkg/core/deployer/providers/volcengine-dcdn/volcengine_dcdn.go +++ b/internal/pkg/core/deployer/providers/volcengine-dcdn/volcengine_dcdn.go @@ -15,7 +15,7 @@ import ( uploadersp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/volcengine-certcenter" ) -type VolcEngineDCDNDeployerConfig struct { +type DeployerConfig struct { // 火山引擎 AccessKeyId。 AccessKeyId string `json:"accessKeyId"` // 火山引擎 AccessKeySecret。 @@ -26,28 +26,20 @@ type VolcEngineDCDNDeployerConfig struct { Domain string `json:"domain"` } -type VolcEngineDCDNDeployer struct { - config *VolcEngineDCDNDeployerConfig +type DeployerProvider struct { + config *DeployerConfig logger logger.Logger sdkClient *veDcdn.DCDN sslUploader uploader.Uploader } -var _ deployer.Deployer = (*VolcEngineDCDNDeployer)(nil) +var _ deployer.Deployer = (*DeployerProvider)(nil) -func New(config *VolcEngineDCDNDeployerConfig) (*VolcEngineDCDNDeployer, error) { - return NewWithLogger(config, logger.NewNilLogger()) -} - -func NewWithLogger(config *VolcEngineDCDNDeployerConfig, logger logger.Logger) (*VolcEngineDCDNDeployer, error) { +func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { if config == nil { panic("config is nil") } - if logger == nil { - panic("logger is nil") - } - client, err := createSdkClient(config.AccessKeyId, config.AccessKeySecret, config.Region) if err != nil { return nil, xerrors.Wrap(err, "failed to create sdk client") @@ -62,15 +54,20 @@ func NewWithLogger(config *VolcEngineDCDNDeployerConfig, logger logger.Logger) ( return nil, xerrors.Wrap(err, "failed to create ssl uploader") } - return &VolcEngineDCDNDeployer{ - logger: logger, + return &DeployerProvider{ config: config, + logger: logger.NewNilLogger(), sdkClient: client, sslUploader: uploader, }, nil } -func (d *VolcEngineDCDNDeployer) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { +func (d *DeployerProvider) WithLogger(logger logger.Logger) *DeployerProvider { + d.logger = logger + return d +} + +func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { // 上传证书到证书中心 upres, err := d.sslUploader.Upload(ctx, certPem, privkeyPem) if err != nil { diff --git a/internal/pkg/core/deployer/providers/volcengine-dcdn/volcengine_dcdn_test.go b/internal/pkg/core/deployer/providers/volcengine-dcdn/volcengine_dcdn_test.go index 2236b1e1..1d34a295 100644 --- a/internal/pkg/core/deployer/providers/volcengine-dcdn/volcengine_dcdn_test.go +++ b/internal/pkg/core/deployer/providers/volcengine-dcdn/volcengine_dcdn_test.go @@ -52,7 +52,7 @@ func TestDeploy(t *testing.T) { fmt.Sprintf("DOMAIN: %v", fDomain), }, "\n")) - deployer, err := provider.New(&provider.VolcEngineDCDNDeployerConfig{ + deployer, err := provider.NewDeployer(&provider.DeployerConfig{ AccessKeyId: fAccessKeyId, AccessKeySecret: fAccessKeySecret, Domain: fDomain, diff --git a/internal/pkg/core/deployer/providers/volcengine-imagex/volcengine_imagex.go b/internal/pkg/core/deployer/providers/volcengine-imagex/volcengine_imagex.go index d02a6d1e..0e27dc27 100644 --- a/internal/pkg/core/deployer/providers/volcengine-imagex/volcengine_imagex.go +++ b/internal/pkg/core/deployer/providers/volcengine-imagex/volcengine_imagex.go @@ -14,7 +14,7 @@ import ( uploadersp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/volcengine-certcenter" ) -type VolcEngineImageXDeployerConfig struct { +type DeployerConfig struct { // 火山引擎 AccessKeyId。 AccessKeyId string `json:"accessKeyId"` // 火山引擎 AccessKeySecret。 @@ -27,28 +27,20 @@ type VolcEngineImageXDeployerConfig struct { Domain string `json:"domain"` } -type VolcEngineImageXDeployer struct { - config *VolcEngineImageXDeployerConfig +type DeployerProvider struct { + config *DeployerConfig logger logger.Logger sdkClient *veImageX.Imagex sslUploader uploader.Uploader } -var _ deployer.Deployer = (*VolcEngineImageXDeployer)(nil) +var _ deployer.Deployer = (*DeployerProvider)(nil) -func New(config *VolcEngineImageXDeployerConfig) (*VolcEngineImageXDeployer, error) { - return NewWithLogger(config, logger.NewNilLogger()) -} - -func NewWithLogger(config *VolcEngineImageXDeployerConfig, logger logger.Logger) (*VolcEngineImageXDeployer, error) { +func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { if config == nil { panic("config is nil") } - if logger == nil { - panic("logger is nil") - } - client, err := createSdkClient(config.AccessKeyId, config.AccessKeySecret, config.Region) if err != nil { return nil, xerrors.Wrap(err, "failed to create sdk client") @@ -63,15 +55,20 @@ func NewWithLogger(config *VolcEngineImageXDeployerConfig, logger logger.Logger) return nil, xerrors.Wrap(err, "failed to create ssl uploader") } - return &VolcEngineImageXDeployer{ - logger: logger, + return &DeployerProvider{ config: config, + logger: logger.NewNilLogger(), sdkClient: client, sslUploader: uploader, }, nil } -func (d *VolcEngineImageXDeployer) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { +func (d *DeployerProvider) WithLogger(logger logger.Logger) *DeployerProvider { + d.logger = logger + return d +} + +func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { if d.config.ServiceId == "" { return nil, errors.New("config `serviceId` is required") } diff --git a/internal/pkg/core/deployer/providers/volcengine-imagex/volcengine_imagex_test.go b/internal/pkg/core/deployer/providers/volcengine-imagex/volcengine_imagex_test.go index 3e15eec8..f2acb8f2 100644 --- a/internal/pkg/core/deployer/providers/volcengine-imagex/volcengine_imagex_test.go +++ b/internal/pkg/core/deployer/providers/volcengine-imagex/volcengine_imagex_test.go @@ -60,7 +60,7 @@ func TestDeploy(t *testing.T) { fmt.Sprintf("DOMAIN: %v", fDomain), }, "\n")) - deployer, err := provider.New(&provider.VolcEngineImageXDeployerConfig{ + deployer, err := provider.NewDeployer(&provider.DeployerConfig{ AccessKeyId: fAccessKeyId, AccessKeySecret: fAccessKeySecret, Region: fRegion, diff --git a/internal/pkg/core/deployer/providers/volcengine-live/volcengine_live.go b/internal/pkg/core/deployer/providers/volcengine-live/volcengine_live.go index fa9e357a..019af9ff 100644 --- a/internal/pkg/core/deployer/providers/volcengine-live/volcengine_live.go +++ b/internal/pkg/core/deployer/providers/volcengine-live/volcengine_live.go @@ -16,7 +16,7 @@ import ( uploadersp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/volcengine-live" ) -type VolcEngineLiveDeployerConfig struct { +type DeployerConfig struct { // 火山引擎 AccessKeyId。 AccessKeyId string `json:"accessKeyId"` // 火山引擎 AccessKeySecret。 @@ -25,28 +25,20 @@ type VolcEngineLiveDeployerConfig struct { Domain string `json:"domain"` } -type VolcEngineLiveDeployer struct { - config *VolcEngineLiveDeployerConfig +type DeployerProvider struct { + config *DeployerConfig logger logger.Logger sdkClient *veLive.Live sslUploader uploader.Uploader } -var _ deployer.Deployer = (*VolcEngineLiveDeployer)(nil) +var _ deployer.Deployer = (*DeployerProvider)(nil) -func New(config *VolcEngineLiveDeployerConfig) (*VolcEngineLiveDeployer, error) { - return NewWithLogger(config, logger.NewNilLogger()) -} - -func NewWithLogger(config *VolcEngineLiveDeployerConfig, logger logger.Logger) (*VolcEngineLiveDeployer, error) { +func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { if config == nil { panic("config is nil") } - if logger == nil { - panic("logger is nil") - } - client := veLive.NewInstance() client.SetAccessKey(config.AccessKeyId) client.SetSecretKey(config.AccessKeySecret) @@ -59,15 +51,20 @@ func NewWithLogger(config *VolcEngineLiveDeployerConfig, logger logger.Logger) ( return nil, xerrors.Wrap(err, "failed to create ssl uploader") } - return &VolcEngineLiveDeployer{ - logger: logger, + return &DeployerProvider{ config: config, + logger: logger.NewNilLogger(), sdkClient: client, sslUploader: uploader, }, nil } -func (d *VolcEngineLiveDeployer) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { +func (d *DeployerProvider) WithLogger(logger logger.Logger) *DeployerProvider { + d.logger = logger + return d +} + +func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { // 上传证书到 Live upres, err := d.sslUploader.Upload(ctx, certPem, privkeyPem) if err != nil { diff --git a/internal/pkg/core/deployer/providers/volcengine-live/volcengine_live_test.go b/internal/pkg/core/deployer/providers/volcengine-live/volcengine_live_test.go index 28097c75..2222e7b9 100644 --- a/internal/pkg/core/deployer/providers/volcengine-live/volcengine_live_test.go +++ b/internal/pkg/core/deployer/providers/volcengine-live/volcengine_live_test.go @@ -52,7 +52,7 @@ func TestDeploy(t *testing.T) { fmt.Sprintf("DOMAIN: %v", fDomain), }, "\n")) - deployer, err := provider.New(&provider.VolcEngineLiveDeployerConfig{ + deployer, err := provider.NewDeployer(&provider.DeployerConfig{ AccessKeyId: fAccessKeyId, AccessKeySecret: fAccessKeySecret, Domain: fDomain, diff --git a/internal/pkg/core/deployer/providers/volcengine-tos/volcengine_tos.go b/internal/pkg/core/deployer/providers/volcengine-tos/volcengine_tos.go index 273c92d4..f1c6ab08 100644 --- a/internal/pkg/core/deployer/providers/volcengine-tos/volcengine_tos.go +++ b/internal/pkg/core/deployer/providers/volcengine-tos/volcengine_tos.go @@ -14,7 +14,7 @@ import ( uploadersp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/volcengine-certcenter" ) -type VolcEngineTOSDeployerConfig struct { +type DeployerConfig struct { // 火山引擎 AccessKeyId。 AccessKeyId string `json:"accessKeyId"` // 火山引擎 AccessKeySecret。 @@ -27,28 +27,20 @@ type VolcEngineTOSDeployerConfig struct { Domain string `json:"domain"` } -type VolcEngineTOSDeployer struct { - config *VolcEngineTOSDeployerConfig +type DeployerProvider struct { + config *DeployerConfig logger logger.Logger sdkClient *veTos.ClientV2 sslUploader uploader.Uploader } -var _ deployer.Deployer = (*VolcEngineTOSDeployer)(nil) +var _ deployer.Deployer = (*DeployerProvider)(nil) -func New(config *VolcEngineTOSDeployerConfig) (*VolcEngineTOSDeployer, error) { - return NewWithLogger(config, logger.NewNilLogger()) -} - -func NewWithLogger(config *VolcEngineTOSDeployerConfig, logger logger.Logger) (*VolcEngineTOSDeployer, error) { +func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { if config == nil { panic("config is nil") } - if logger == nil { - panic("logger is nil") - } - client, err := createSdkClient(config.AccessKeyId, config.AccessKeySecret, config.Region) if err != nil { return nil, xerrors.Wrap(err, "failed to create sdk client") @@ -63,15 +55,20 @@ func NewWithLogger(config *VolcEngineTOSDeployerConfig, logger logger.Logger) (* return nil, xerrors.Wrap(err, "failed to create ssl uploader") } - return &VolcEngineTOSDeployer{ - logger: logger, + return &DeployerProvider{ config: config, + logger: logger.NewNilLogger(), sdkClient: client, sslUploader: uploader, }, nil } -func (d *VolcEngineTOSDeployer) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { +func (d *DeployerProvider) WithLogger(logger logger.Logger) *DeployerProvider { + d.logger = logger + return d +} + +func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { if d.config.Bucket == "" { return nil, errors.New("config `bucket` is required") } diff --git a/internal/pkg/core/deployer/providers/volcengine-tos/volcengine_tos_test.go b/internal/pkg/core/deployer/providers/volcengine-tos/volcengine_tos_test.go index 815d2f0d..0c9b398a 100644 --- a/internal/pkg/core/deployer/providers/volcengine-tos/volcengine_tos_test.go +++ b/internal/pkg/core/deployer/providers/volcengine-tos/volcengine_tos_test.go @@ -60,7 +60,7 @@ func TestDeploy(t *testing.T) { fmt.Sprintf("DOMAIN: %v", fDomain), }, "\n")) - deployer, err := provider.New(&provider.VolcEngineTOSDeployerConfig{ + deployer, err := provider.NewDeployer(&provider.DeployerConfig{ AccessKeyId: fAccessKeyId, AccessKeySecret: fAccessKeySecret, Region: fRegion, diff --git a/internal/pkg/core/deployer/providers/webhook/webhook.go b/internal/pkg/core/deployer/providers/webhook/webhook.go index cd6e941a..7a9edfda 100644 --- a/internal/pkg/core/deployer/providers/webhook/webhook.go +++ b/internal/pkg/core/deployer/providers/webhook/webhook.go @@ -14,47 +14,44 @@ import ( "github.com/usual2970/certimate/internal/pkg/utils/certs" ) -type WebhookDeployerConfig struct { +type DeployerConfig struct { // Webhook URL。 WebhookUrl string `json:"webhookUrl"` // Webhook 回调数据(JSON 格式)。 WebhookData string `json:"webhookData,omitempty"` } -type WebhookDeployer struct { - config *WebhookDeployerConfig +type DeployerProvider struct { + config *DeployerConfig logger logger.Logger httpClient *resty.Client } -var _ deployer.Deployer = (*WebhookDeployer)(nil) +var _ deployer.Deployer = (*DeployerProvider)(nil) -func New(config *WebhookDeployerConfig) (*WebhookDeployer, error) { - return NewWithLogger(config, logger.NewNilLogger()) -} - -func NewWithLogger(config *WebhookDeployerConfig, logger logger.Logger) (*WebhookDeployer, error) { +func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { if config == nil { panic("config is nil") } - if logger == nil { - panic("logger is nil") - } - client := resty.New(). SetTimeout(30 * time.Second). SetRetryCount(3). SetRetryWaitTime(5 * time.Second) - return &WebhookDeployer{ + return &DeployerProvider{ config: config, - logger: logger, + logger: logger.NewNilLogger(), httpClient: client, }, nil } -func (d *WebhookDeployer) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { +func (d *DeployerProvider) WithLogger(logger logger.Logger) *DeployerProvider { + d.logger = logger + return d +} + +func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { certX509, err := certs.ParseCertificateFromPEM(certPem) if err != nil { return nil, xerrors.Wrap(err, "failed to parse x509") diff --git a/internal/pkg/core/deployer/providers/webhook/webhook_test.go b/internal/pkg/core/deployer/providers/webhook/webhook_test.go index 92b57e56..7dd6f24a 100644 --- a/internal/pkg/core/deployer/providers/webhook/webhook_test.go +++ b/internal/pkg/core/deployer/providers/webhook/webhook_test.go @@ -48,7 +48,7 @@ func TestDeploy(t *testing.T) { fmt.Sprintf("WEBHOOKDATA: %v", fWebhookData), }, "\n")) - deployer, err := provider.New(&provider.WebhookDeployerConfig{ + deployer, err := provider.NewDeployer(&provider.DeployerConfig{ WebhookUrl: fWebhookUrl, WebhookData: fWebhookData, }) diff --git a/internal/pkg/core/notifier/providers/bark/bark.go b/internal/pkg/core/notifier/providers/bark/bark.go index 731e0a96..f9589096 100644 --- a/internal/pkg/core/notifier/providers/bark/bark.go +++ b/internal/pkg/core/notifier/providers/bark/bark.go @@ -9,7 +9,7 @@ import ( "github.com/usual2970/certimate/internal/pkg/core/notifier" ) -type BarkNotifierConfig struct { +type NotifierConfig struct { // Bark 服务地址。 // 零值时默认使用官方服务器。 ServerUrl string `json:"serverUrl"` @@ -17,23 +17,23 @@ type BarkNotifierConfig struct { DeviceKey string `json:"deviceKey"` } -type BarkNotifier struct { - config *BarkNotifierConfig +type NotifierProvider struct { + config *NotifierConfig } -var _ notifier.Notifier = (*BarkNotifier)(nil) +var _ notifier.Notifier = (*NotifierProvider)(nil) -func New(config *BarkNotifierConfig) (*BarkNotifier, error) { +func NewNotifier(config *NotifierConfig) (*NotifierProvider, error) { if config == nil { panic("config is nil") } - return &BarkNotifier{ + return &NotifierProvider{ config: config, }, nil } -func (n *BarkNotifier) Notify(ctx context.Context, subject string, message string) (res *notifier.NotifyResult, err error) { +func (n *NotifierProvider) Notify(ctx context.Context, subject string, message string) (res *notifier.NotifyResult, err error) { var srv notify.Notifier if n.config.ServerUrl == "" { srv = bark.New(n.config.DeviceKey) diff --git a/internal/pkg/core/notifier/providers/bark/bark_test.go b/internal/pkg/core/notifier/providers/bark/bark_test.go index e3045cae..bd0441b4 100644 --- a/internal/pkg/core/notifier/providers/bark/bark_test.go +++ b/internal/pkg/core/notifier/providers/bark/bark_test.go @@ -44,7 +44,7 @@ func TestNotify(t *testing.T) { fmt.Sprintf("DEVICEKEY: %v", fDeviceKey), }, "\n")) - notifier, err := provider.New(&provider.BarkNotifierConfig{ + notifier, err := provider.NewNotifier(&provider.NotifierConfig{ ServerUrl: fServerUrl, DeviceKey: fDeviceKey, }) diff --git a/internal/pkg/core/notifier/providers/dingtalk/dingtalk.go b/internal/pkg/core/notifier/providers/dingtalk/dingtalk.go index 469d5e65..f8eba8a7 100644 --- a/internal/pkg/core/notifier/providers/dingtalk/dingtalk.go +++ b/internal/pkg/core/notifier/providers/dingtalk/dingtalk.go @@ -8,30 +8,30 @@ import ( "github.com/usual2970/certimate/internal/pkg/core/notifier" ) -type DingTalkNotifierConfig struct { +type NotifierConfig struct { // 钉钉机器人的 Token。 AccessToken string `json:"accessToken"` // 钉钉机器人的 Secret。 Secret string `json:"secret"` } -type DingTalkNotifier struct { - config *DingTalkNotifierConfig +type NotifierProvider struct { + config *NotifierConfig } -var _ notifier.Notifier = (*DingTalkNotifier)(nil) +var _ notifier.Notifier = (*NotifierProvider)(nil) -func New(config *DingTalkNotifierConfig) (*DingTalkNotifier, error) { +func NewNotifier(config *NotifierConfig) (*NotifierProvider, error) { if config == nil { panic("config is nil") } - return &DingTalkNotifier{ + return &NotifierProvider{ config: config, }, nil } -func (n *DingTalkNotifier) Notify(ctx context.Context, subject string, message string) (res *notifier.NotifyResult, err error) { +func (n *NotifierProvider) Notify(ctx context.Context, subject string, message string) (res *notifier.NotifyResult, err error) { srv := dingding.New(&dingding.Config{ Token: n.config.AccessToken, Secret: n.config.Secret, diff --git a/internal/pkg/core/notifier/providers/dingtalk/dingtalk_test.go b/internal/pkg/core/notifier/providers/dingtalk/dingtalk_test.go index 621a57ca..836cf498 100644 --- a/internal/pkg/core/notifier/providers/dingtalk/dingtalk_test.go +++ b/internal/pkg/core/notifier/providers/dingtalk/dingtalk_test.go @@ -43,7 +43,7 @@ func TestNotify(t *testing.T) { fmt.Sprintf("SECRET: %v", fSecret), }, "\n")) - notifier, err := provider.New(&provider.DingTalkNotifierConfig{ + notifier, err := provider.NewNotifier(&provider.NotifierConfig{ AccessToken: fAccessToken, Secret: fSecret, }) diff --git a/internal/pkg/core/notifier/providers/email/email.go b/internal/pkg/core/notifier/providers/email/email.go index 2619188f..4a69d50a 100644 --- a/internal/pkg/core/notifier/providers/email/email.go +++ b/internal/pkg/core/notifier/providers/email/email.go @@ -11,7 +11,7 @@ import ( "github.com/usual2970/certimate/internal/pkg/core/notifier" ) -type EmailNotifierConfig struct { +type NotifierConfig struct { // SMTP 服务器地址。 SmtpHost string `json:"smtpHost"` // SMTP 服务器端口。 @@ -29,23 +29,23 @@ type EmailNotifierConfig struct { ReceiverAddress string `json:"receiverAddress"` } -type EmailNotifier struct { - config *EmailNotifierConfig +type NotifierProvider struct { + config *NotifierConfig } -var _ notifier.Notifier = (*EmailNotifier)(nil) +var _ notifier.Notifier = (*NotifierProvider)(nil) -func New(config *EmailNotifierConfig) (*EmailNotifier, error) { +func NewNotifier(config *NotifierConfig) (*NotifierProvider, error) { if config == nil { panic("config is nil") } - return &EmailNotifier{ + return &NotifierProvider{ config: config, }, nil } -func (n *EmailNotifier) Notify(ctx context.Context, subject string, message string) (res *notifier.NotifyResult, err error) { +func (n *NotifierProvider) Notify(ctx context.Context, subject string, message string) (res *notifier.NotifyResult, err error) { var smtpAuth smtp.Auth if n.config.Username != "" || n.config.Password != "" { smtpAuth = smtp.PlainAuth("", n.config.Username, n.config.Password, n.config.SmtpHost) diff --git a/internal/pkg/core/notifier/providers/email/email_test.go b/internal/pkg/core/notifier/providers/email/email_test.go index 1c52d4de..df006c24 100644 --- a/internal/pkg/core/notifier/providers/email/email_test.go +++ b/internal/pkg/core/notifier/providers/email/email_test.go @@ -64,7 +64,7 @@ func TestNotify(t *testing.T) { fmt.Sprintf("RECEIVERADDRESS: %v", fReceiverAddress), }, "\n")) - notifier, err := provider.New(&provider.EmailNotifierConfig{ + notifier, err := provider.NewNotifier(&provider.NotifierConfig{ SmtpHost: fSmtpHost, SmtpPort: int32(fSmtpPort), SmtpTLS: fSmtpTLS, diff --git a/internal/pkg/core/notifier/providers/lark/lark.go b/internal/pkg/core/notifier/providers/lark/lark.go index b726fa1c..9c92691a 100644 --- a/internal/pkg/core/notifier/providers/lark/lark.go +++ b/internal/pkg/core/notifier/providers/lark/lark.go @@ -8,28 +8,28 @@ import ( "github.com/usual2970/certimate/internal/pkg/core/notifier" ) -type LarkNotifierConfig struct { +type NotifierConfig struct { // 飞书机器人 Webhook 地址。 WebhookUrl string `json:"webhookUrl"` } -type LarkNotifier struct { - config *LarkNotifierConfig +type NotifierProvider struct { + config *NotifierConfig } -var _ notifier.Notifier = (*LarkNotifier)(nil) +var _ notifier.Notifier = (*NotifierProvider)(nil) -func New(config *LarkNotifierConfig) (*LarkNotifier, error) { +func NewNotifier(config *NotifierConfig) (*NotifierProvider, error) { if config == nil { panic("config is nil") } - return &LarkNotifier{ + return &NotifierProvider{ config: config, }, nil } -func (n *LarkNotifier) Notify(ctx context.Context, subject string, message string) (res *notifier.NotifyResult, err error) { +func (n *NotifierProvider) Notify(ctx context.Context, subject string, message string) (res *notifier.NotifyResult, err error) { srv := lark.NewWebhookService(n.config.WebhookUrl) err = srv.Send(ctx, subject, message) diff --git a/internal/pkg/core/notifier/providers/lark/lark_test.go b/internal/pkg/core/notifier/providers/lark/lark_test.go index 0b91ebd7..2b04a7a6 100644 --- a/internal/pkg/core/notifier/providers/lark/lark_test.go +++ b/internal/pkg/core/notifier/providers/lark/lark_test.go @@ -38,7 +38,7 @@ func TestNotify(t *testing.T) { fmt.Sprintf("WEBHOOKURL: %v", fWebhookUrl), }, "\n")) - notifier, err := provider.New(&provider.LarkNotifierConfig{ + notifier, err := provider.NewNotifier(&provider.NotifierConfig{ WebhookUrl: fWebhookUrl, }) if err != nil { diff --git a/internal/pkg/core/notifier/providers/serverchan/serverchan.go b/internal/pkg/core/notifier/providers/serverchan/serverchan.go index 1811c49e..51df0893 100644 --- a/internal/pkg/core/notifier/providers/serverchan/serverchan.go +++ b/internal/pkg/core/notifier/providers/serverchan/serverchan.go @@ -9,28 +9,28 @@ import ( "github.com/usual2970/certimate/internal/pkg/core/notifier" ) -type ServerChanNotifierConfig struct { +type NotifierConfig struct { // ServerChan 服务地址。 Url string `json:"url"` } -type ServerChanNotifier struct { - config *ServerChanNotifierConfig +type NotifierProvider struct { + config *NotifierConfig } -var _ notifier.Notifier = (*ServerChanNotifier)(nil) +var _ notifier.Notifier = (*NotifierProvider)(nil) -func New(config *ServerChanNotifierConfig) (*ServerChanNotifier, error) { +func NewNotifier(config *NotifierConfig) (*NotifierProvider, error) { if config == nil { panic("config is nil") } - return &ServerChanNotifier{ + return &NotifierProvider{ config: config, }, nil } -func (n *ServerChanNotifier) Notify(ctx context.Context, subject string, message string) (res *notifier.NotifyResult, err error) { +func (n *NotifierProvider) Notify(ctx context.Context, subject string, message string) (res *notifier.NotifyResult, err error) { srv := notifyHttp.New() srv.AddReceivers(¬ifyHttp.Webhook{ diff --git a/internal/pkg/core/notifier/providers/serverchan/serverchan_test.go b/internal/pkg/core/notifier/providers/serverchan/serverchan_test.go index db2a4946..6f9c61a3 100644 --- a/internal/pkg/core/notifier/providers/serverchan/serverchan_test.go +++ b/internal/pkg/core/notifier/providers/serverchan/serverchan_test.go @@ -38,7 +38,7 @@ func TestNotify(t *testing.T) { fmt.Sprintf("URL: %v", fUrl), }, "\n")) - notifier, err := provider.New(&provider.ServerChanNotifierConfig{ + notifier, err := provider.NewNotifier(&provider.NotifierConfig{ Url: fUrl, }) if err != nil { diff --git a/internal/pkg/core/notifier/providers/telegram/telegram.go b/internal/pkg/core/notifier/providers/telegram/telegram.go index ce86c881..6a1889b3 100644 --- a/internal/pkg/core/notifier/providers/telegram/telegram.go +++ b/internal/pkg/core/notifier/providers/telegram/telegram.go @@ -8,30 +8,30 @@ import ( "github.com/usual2970/certimate/internal/pkg/core/notifier" ) -type TelegramNotifierConfig struct { +type NotifierConfig struct { // Telegram API Token。 ApiToken string `json:"apiToken"` // Telegram Chat ID。 ChatId int64 `json:"chatId"` } -type TelegramNotifier struct { - config *TelegramNotifierConfig +type NotifierProvider struct { + config *NotifierConfig } -var _ notifier.Notifier = (*TelegramNotifier)(nil) +var _ notifier.Notifier = (*NotifierProvider)(nil) -func New(config *TelegramNotifierConfig) (*TelegramNotifier, error) { +func NewNotifier(config *NotifierConfig) (*NotifierProvider, error) { if config == nil { panic("config is nil") } - return &TelegramNotifier{ + return &NotifierProvider{ config: config, }, nil } -func (n *TelegramNotifier) Notify(ctx context.Context, subject string, message string) (res *notifier.NotifyResult, err error) { +func (n *NotifierProvider) Notify(ctx context.Context, subject string, message string) (res *notifier.NotifyResult, err error) { srv, err := telegram.New(n.config.ApiToken) if err != nil { return nil, err diff --git a/internal/pkg/core/notifier/providers/telegram/telegram_test.go b/internal/pkg/core/notifier/providers/telegram/telegram_test.go index fca71e8a..10e93547 100644 --- a/internal/pkg/core/notifier/providers/telegram/telegram_test.go +++ b/internal/pkg/core/notifier/providers/telegram/telegram_test.go @@ -44,7 +44,7 @@ func TestNotify(t *testing.T) { fmt.Sprintf("CHATID: %v", fChartId), }, "\n")) - notifier, err := provider.New(&provider.TelegramNotifierConfig{ + notifier, err := provider.NewNotifier(&provider.NotifierConfig{ ApiToken: fApiToken, ChatId: fChartId, }) diff --git a/internal/pkg/core/notifier/providers/webhook/webhook.go b/internal/pkg/core/notifier/providers/webhook/webhook.go index 66dd806b..55c0e668 100644 --- a/internal/pkg/core/notifier/providers/webhook/webhook.go +++ b/internal/pkg/core/notifier/providers/webhook/webhook.go @@ -8,28 +8,28 @@ import ( "github.com/usual2970/certimate/internal/pkg/core/notifier" ) -type WebhookNotifierConfig struct { +type NotifierConfig struct { // Webhook URL。 Url string `json:"url"` } -type WebhookNotifier struct { - config *WebhookNotifierConfig +type NotifierProvider struct { + config *NotifierConfig } -var _ notifier.Notifier = (*WebhookNotifier)(nil) +var _ notifier.Notifier = (*NotifierProvider)(nil) -func New(config *WebhookNotifierConfig) (*WebhookNotifier, error) { +func NewNotifier(config *NotifierConfig) (*NotifierProvider, error) { if config == nil { panic("config is nil") } - return &WebhookNotifier{ + return &NotifierProvider{ config: config, }, nil } -func (n *WebhookNotifier) Notify(ctx context.Context, subject string, message string) (res *notifier.NotifyResult, err error) { +func (n *NotifierProvider) Notify(ctx context.Context, subject string, message string) (res *notifier.NotifyResult, err error) { srv := http.New() srv.AddReceiversURLs(n.config.Url) diff --git a/internal/pkg/core/notifier/providers/webhook/webhook_test.go b/internal/pkg/core/notifier/providers/webhook/webhook_test.go index 14e2adf6..7afe6be4 100644 --- a/internal/pkg/core/notifier/providers/webhook/webhook_test.go +++ b/internal/pkg/core/notifier/providers/webhook/webhook_test.go @@ -38,7 +38,7 @@ func TestNotify(t *testing.T) { fmt.Sprintf("URL: %v", fUrl), }, "\n")) - notifier, err := provider.New(&provider.WebhookNotifierConfig{ + notifier, err := provider.NewNotifier(&provider.NotifierConfig{ Url: fUrl, }) if err != nil { diff --git a/internal/pkg/core/notifier/providers/wecom/wecom.go b/internal/pkg/core/notifier/providers/wecom/wecom.go index 7731a1b5..63342cb5 100644 --- a/internal/pkg/core/notifier/providers/wecom/wecom.go +++ b/internal/pkg/core/notifier/providers/wecom/wecom.go @@ -9,28 +9,28 @@ import ( "github.com/usual2970/certimate/internal/pkg/core/notifier" ) -type WeComNotifierConfig struct { +type NotifierConfig struct { // 企业微信机器人 Webhook 地址。 WebhookUrl string `json:"webhookUrl"` } -type WeComNotifier struct { - config *WeComNotifierConfig +type NotifierProvider struct { + config *NotifierConfig } -var _ notifier.Notifier = (*WeComNotifier)(nil) +var _ notifier.Notifier = (*NotifierProvider)(nil) -func New(config *WeComNotifierConfig) (*WeComNotifier, error) { +func NewNotifier(config *NotifierConfig) (*NotifierProvider, error) { if config == nil { panic("config is nil") } - return &WeComNotifier{ + return &NotifierProvider{ config: config, }, nil } -func (n *WeComNotifier) Notify(ctx context.Context, subject string, message string) (res *notifier.NotifyResult, err error) { +func (n *NotifierProvider) Notify(ctx context.Context, subject string, message string) (res *notifier.NotifyResult, err error) { srv := notifyHttp.New() srv.AddReceivers(¬ifyHttp.Webhook{ diff --git a/internal/pkg/core/notifier/providers/wecom/wecom_test.go b/internal/pkg/core/notifier/providers/wecom/wecom_test.go index e1378849..b823adea 100644 --- a/internal/pkg/core/notifier/providers/wecom/wecom_test.go +++ b/internal/pkg/core/notifier/providers/wecom/wecom_test.go @@ -38,7 +38,7 @@ func TestNotify(t *testing.T) { fmt.Sprintf("WEBHOOKURL: %v", fWebhookUrl), }, "\n")) - notifier, err := provider.New(&provider.WeComNotifierConfig{ + notifier, err := provider.NewNotifier(&provider.NotifierConfig{ WebhookUrl: fWebhookUrl, }) if err != nil { diff --git a/ui/src/i18n/locales/zh/nls.workflow.nodes.json b/ui/src/i18n/locales/zh/nls.workflow.nodes.json index e4b341e7..d5ac3aca 100644 --- a/ui/src/i18n/locales/zh/nls.workflow.nodes.json +++ b/ui/src/i18n/locales/zh/nls.workflow.nodes.json @@ -135,11 +135,11 @@ "workflow_node.deploy.form.aliyun_clb_snidomain.label": "阿里云 CLB 扩展域名(可选)", "workflow_node.deploy.form.aliyun_clb_snidomain.placeholder": "请输入阿里云 CLB 扩展域名", "workflow_node.deploy.form.aliyun_clb_snidomain.tooltip": "这是什么?请参阅 https://slb.console.aliyun.com/clb

不填写时,将替换监听器的默认证书。", - "workflow_node.deploy.form.aliyun_cdn_domain.label": "阿里云 CDN 加速域名(支持泛域名)", - "workflow_node.deploy.form.aliyun_cdn_domain.placeholder": "请输入阿里云 CDN 加速域名", + "workflow_node.deploy.form.aliyun_cdn_domain.label": "阿里云 CDN 加速域名", + "workflow_node.deploy.form.aliyun_cdn_domain.placeholder": "请输入阿里云 CDN 加速域名(支持泛域名)", "workflow_node.deploy.form.aliyun_cdn_domain.tooltip": "这是什么?请参阅 https://cdn.console.aliyun.com", - "workflow_node.deploy.form.aliyun_dcdn_domain.label": "阿里云 DCDN 加速域名(支持泛域名)", - "workflow_node.deploy.form.aliyun_dcdn_domain.placeholder": "请输入阿里云 DCDN 加速域名", + "workflow_node.deploy.form.aliyun_dcdn_domain.label": "阿里云 DCDN 加速域名", + "workflow_node.deploy.form.aliyun_dcdn_domain.placeholder": "请输入阿里云 DCDN 加速域名(支持泛域名)", "workflow_node.deploy.form.aliyun_dcdn_domain.tooltip": "这是什么?请参阅 https://dcdn.console.aliyun.com", "workflow_node.deploy.form.aliyun_esa_region.label": "阿里云 ESA 服务地域", "workflow_node.deploy.form.aliyun_esa_region.placeholder": "请输入阿里云 ESA 服务地域(例如:cn-hangzhou)", @@ -150,8 +150,8 @@ "workflow_node.deploy.form.aliyun_live_region.label": "阿里云视频直播服务地域", "workflow_node.deploy.form.aliyun_live_region.placeholder": "请输入阿里云视频直播服务地域(例如:cn-hangzhou)", "workflow_node.deploy.form.aliyun_live_region.tooltip": "这是什么?请参阅 https://help.aliyun.com/zh/live/product-overview/supported-regions", - "workflow_node.deploy.form.aliyun_live_domain.label": "阿里云视频直播流域名(支持泛域名)", - "workflow_node.deploy.form.aliyun_live_domain.placeholder": "请输入阿里云视频直播流域名", + "workflow_node.deploy.form.aliyun_live_domain.label": "阿里云视频直播流域名", + "workflow_node.deploy.form.aliyun_live_domain.placeholder": "请输入阿里云视频直播流域名(支持泛域名)", "workflow_node.deploy.form.aliyun_live_domain.tooltip": "这是什么?请参阅 https://live.console.aliyun.com", "workflow_node.deploy.form.aliyun_nlb_resource_type.label": "证书替换方式", "workflow_node.deploy.form.aliyun_nlb_resource_type.placeholder": "请选择证书替换方式", @@ -187,11 +187,11 @@ "workflow_node.deploy.form.aws_cloudfront_distribution_id.label": "AWS CloudFront 分配 ID", "workflow_node.deploy.form.aws_cloudfront_distribution_id.placeholder": "请输入 AWS CloudFront 分配 ID", "workflow_node.deploy.form.aws_cloudfront_distribution_id.tooltip": "这是什么?请参阅 https://docs.aws.amazon.com/zh_cn/AmazonCloudFront/latest/DeveloperGuide/distribution-working-with.html", - "workflow_node.deploy.form.baiducloud_cdn_domain.label": "百度智能云 CDN 加速域名(支持泛域名)", - "workflow_node.deploy.form.baiducloud_cdn_domain.placeholder": "请输入百度智能云 CDN 加速域名", + "workflow_node.deploy.form.baiducloud_cdn_domain.label": "百度智能云 CDN 加速域名", + "workflow_node.deploy.form.baiducloud_cdn_domain.placeholder": "请输入百度智能云 CDN 加速域名(支持泛域名)", "workflow_node.deploy.form.baiducloud_cdn_domain.tooltip": "这是什么?请参阅 https://console.bce.baidu.com/cdn", - "workflow_node.deploy.form.baishan_cdn_domain.label": "白山云 CDN 加速域名(支持泛域名)", - "workflow_node.deploy.form.baishan_cdn_domain.placeholder": "请输入白山云 CDN 加速域名", + "workflow_node.deploy.form.baishan_cdn_domain.label": "白山云 CDN 加速域名", + "workflow_node.deploy.form.baishan_cdn_domain.placeholder": "请输入白山云 CDN 加速域名(支持泛域名)", "workflow_node.deploy.form.baishan_cdn_domain.tooltip": "这是什么?请参阅 https://cdnx.console.baishan.com", "workflow_node.deploy.form.baotapanel_console_auto_restart.label": "部署后自动重启面板服务", "workflow_node.deploy.form.baotapanel_site_type.label": "宝塔面板网站类型", @@ -207,8 +207,8 @@ "workflow_node.deploy.form.baotapanel_site_names.tooltip": "通常为网站域名。", "workflow_node.deploy.form.baotapanel_site_names.multiple_input_modal.title": "修改宝塔面板网站名称", "workflow_node.deploy.form.baotapanel_site_names.multiple_input_modal.placeholder": "请输入宝塔面板网站名称", - "workflow_node.deploy.form.byteplus_cdn_domain.label": "BytePlus CDN 域名(支持泛域名)", - "workflow_node.deploy.form.byteplus_cdn_domain.placeholder": "请输入 BytePlus CDN 域名", + "workflow_node.deploy.form.byteplus_cdn_domain.label": "BytePlus CDN 域名", + "workflow_node.deploy.form.byteplus_cdn_domain.placeholder": "请输入 BytePlus CDN 域名(支持泛域名)", "workflow_node.deploy.form.byteplus_cdn_domain.tooltip": "这是什么?请参阅 https://console.byteplus.com/cdn", "workflow_node.deploy.form.cdnfly_resource_type.label": "证书替换方式", "workflow_node.deploy.form.cdnfly_resource_type.placeholder": "请选择证书替换方式", @@ -261,8 +261,8 @@ "workflow_node.deploy.form.huaweicloud_waf_certificate_id.label": "华为云 WAF 证书 ID", "workflow_node.deploy.form.huaweicloud_waf_certificate_id.placeholder": "请输入华为云 WAF 证书 ID", "workflow_node.deploy.form.huaweicloud_waf_certificate_id.tooltip": "这是什么?请参阅 https://console.huaweicloud.com/console/#/waf/certificateManagement", - "workflow_node.deploy.form.huaweicloud_waf_domain.label": "华为云 WAF 防护域名(支持泛域名)", - "workflow_node.deploy.form.huaweicloud_waf_domain.placeholder": "请输入华为云 WAF 防护域名", + "workflow_node.deploy.form.huaweicloud_waf_domain.label": "华为云 WAF 防护域名", + "workflow_node.deploy.form.huaweicloud_waf_domain.placeholder": "请输入华为云 WAF 防护域名(支持泛域名)", "workflow_node.deploy.form.huaweicloud_waf_domain.tooltip": "这是什么?请参阅 https://console.huaweicloud.com/console/#/waf/domain/list", "workflow_node.deploy.form.k8s_namespace.label": "Kubernetes 命名空间", "workflow_node.deploy.form.k8s_namespace.placeholder": "请输入 Kubernetes 命名空间", @@ -315,8 +315,8 @@ "workflow_node.deploy.form.local_preset_scripts.option.reload_nginx.label": "POSIX Bash - 重启 nginx 进程", "workflow_node.deploy.form.local_preset_scripts.option.binding_iis.label": "PowerShell - 导入并绑定到 IIS(需管理员权限)", "workflow_node.deploy.form.local_preset_scripts.option.binding_netsh.label": "PowerShell - 导入并绑定到 netsh(需管理员权限)", - "workflow_node.deploy.form.qiniu_cdn_domain.label": "七牛云 CDN 加速域名(支持泛域名)", - "workflow_node.deploy.form.qiniu_cdn_domain.placeholder": "请输入七牛云 CDN 加速域名", + "workflow_node.deploy.form.qiniu_cdn_domain.label": "七牛云 CDN 加速域名", + "workflow_node.deploy.form.qiniu_cdn_domain.placeholder": "请输入七牛云 CDN 加速域名(支持泛域名)", "workflow_node.deploy.form.qiniu_cdn_domain.tooltip": "这是什么?请参阅 https://portal.qiniu.com/cdn", "workflow_node.deploy.form.qiniu_pili_hub.label": "七牛云视频直播空间名", "workflow_node.deploy.form.qiniu_pili_hub.placeholder": "请输入七牛云视频直播空间名", @@ -362,8 +362,8 @@ "workflow_node.deploy.form.ssh_preset_scripts.option.reload_nginx.label": "POSIX Bash - 重启 nginx 进程", "workflow_node.deploy.form.ssh_use_scp.label": "回退使用 SCP", "workflow_node.deploy.form.ssh_use_scp.tooltip": "如果你的远程服务器不支持 SFTP,请开启此选项回退为 SCP。", - "workflow_node.deploy.form.tencentcloud_cdn_domain.label": "腾讯云 CDN 加速域名(支持泛域名)", - "workflow_node.deploy.form.tencentcloud_cdn_domain.placeholder": "请输入腾讯云 CDN 加速域名", + "workflow_node.deploy.form.tencentcloud_cdn_domain.label": "腾讯云 CDN 加速域名", + "workflow_node.deploy.form.tencentcloud_cdn_domain.placeholder": "请输入腾讯云 CDN 加速域名(支持泛域名)", "workflow_node.deploy.form.tencentcloud_cdn_domain.tooltip": "这是什么?请参阅 https://console.cloud.tencent.com/cdn", "workflow_node.deploy.form.tencentcloud_clb_resource_type.label": "证书替换方式", "workflow_node.deploy.form.tencentcloud_clb_resource_type.placeholder": "请选择证书替换方式", @@ -398,8 +398,8 @@ "workflow_node.deploy.form.tencentcloud_css_domain.label": "腾讯云云直播播放域名", "workflow_node.deploy.form.tencentcloud_css_domain.placeholder": "请输入腾讯云云直播播放域名", "workflow_node.deploy.form.tencentcloud_css_domain.tooltip": "这是什么?请参阅 https://console.cloud.tencent.com/live/livestat", - "workflow_node.deploy.form.tencentcloud_ecdn_domain.label": "腾讯云 ECDN 加速域名(支持泛域名)", - "workflow_node.deploy.form.tencentcloud_ecdn_domain.placeholder": "请输入腾讯云 ECDN 加速域名", + "workflow_node.deploy.form.tencentcloud_ecdn_domain.label": "腾讯云 ECDN 加速域名", + "workflow_node.deploy.form.tencentcloud_ecdn_domain.placeholder": "请输入腾讯云 ECDN 加速域名(支持泛域名)", "workflow_node.deploy.form.tencentcloud_ecdn_domain.tooltip": "这是什么?请参阅 https://console.cloud.tencent.com/cdn", "workflow_node.deploy.form.tencentcloud_eo_zone_id.label": "腾讯云 EdgeOne 站点 ID", "workflow_node.deploy.form.tencentcloud_eo_zone_id.placeholder": "请输入腾讯云 EdgeOne 站点 ID", @@ -444,8 +444,8 @@ "workflow_node.deploy.form.ucloud_us3_domain.label": "优刻得 US3 自定义域名", "workflow_node.deploy.form.ucloud_us3_domain.placeholder": "请输入优刻得 US3 自定义域名", "workflow_node.deploy.form.ucloud_us3_domain.tooltip": "这是什么?请参阅 https://console.ucloud.cn/ufile", - "workflow_node.deploy.form.volcengine_cdn_domain.label": "火山引擎 CDN 加速域名(支持泛域名)", - "workflow_node.deploy.form.volcengine_cdn_domain.placeholder": "请输入火山引擎 CDN 加速域名", + "workflow_node.deploy.form.volcengine_cdn_domain.label": "火山引擎 CDN 加速域名", + "workflow_node.deploy.form.volcengine_cdn_domain.placeholder": "请输入火山引擎 CDN 加速域名(支持泛域名)", "workflow_node.deploy.form.volcengine_cdn_domain.tooltip": "这是什么?请参阅 https://console.volcengine.com/cdn/homepage", "workflow_node.deploy.form.volcengine_clb_resource_type.label": "证书替换方式", "workflow_node.deploy.form.volcengine_clb_resource_type.placeholder": "请选择证书替换方式", @@ -456,8 +456,8 @@ "workflow_node.deploy.form.volcengine_clb_listener_id.label": "火山引擎 CLB 监听器 ID", "workflow_node.deploy.form.volcengine_clb_listener_id.placeholder": "请输入火山引擎 CLB 监听器 ID", "workflow_node.deploy.form.volcengine_clb_listener_id.tooltip": "这是什么?请参阅 https://console.volcengine.com/clb/LoadBalancer", - "workflow_node.deploy.form.volcengine_dcdn_domain.label": "火山引擎 DCDN 加速域名(支持泛域名)", - "workflow_node.deploy.form.volcengine_dcdn_domain.placeholder": "请输入火山引擎 DCDN 加速域名", + "workflow_node.deploy.form.volcengine_dcdn_domain.label": "火山引擎 DCDN 加速域名", + "workflow_node.deploy.form.volcengine_dcdn_domain.placeholder": "请输入火山引擎 DCDN 加速域名(支持泛域名)", "workflow_node.deploy.form.volcengine_dcdn_domain.tooltip": "这是什么?请参阅 https://console.volcengine.com/dcdn/dashboard", "workflow_node.deploy.form.volcengine_imagex_region.label": "火山引擎 ImageX 服务地域", "workflow_node.deploy.form.volcengine_imagex_region.placeholder": "请输入火山引擎 ImageX 服务地域(例如:cn-north-1)", @@ -468,8 +468,8 @@ "workflow_node.deploy.form.volcengine_imagex_domain.label": "火山引擎 ImageX 绑定域名", "workflow_node.deploy.form.volcengine_imagex_domain.placeholder": "请输入火山引擎 ImageX 绑定域名", "workflow_node.deploy.form.volcengine_imagex_domain.tooltip": "这是什么?请参阅 see https://console.volcengine.com/imagex", - "workflow_node.deploy.form.volcengine_live_domain.label": "火山引擎视频直播流域名(支持泛域名)", - "workflow_node.deploy.form.volcengine_live_domain.placeholder": "请输入火山引擎视频直播流域名", + "workflow_node.deploy.form.volcengine_live_domain.label": "火山引擎视频直播流域名", + "workflow_node.deploy.form.volcengine_live_domain.placeholder": "请输入火山引擎视频直播流域名(支持泛域名)", "workflow_node.deploy.form.volcengine_live_domain.tooltip": "这是什么?请参阅 https://console.volcengine.com/live", "workflow_node.deploy.form.volcengine_tos_region.label": "火山引擎 TOS 服务地域", "workflow_node.deploy.form.volcengine_tos_region.placeholder": "请输入火山引擎 TOS 服务地域(例如:cn-beijing)", From 688a013d73040305cdbcb699bbaa1e6e256c0ed2 Mon Sep 17 00:00:00 2001 From: Fu Diwei Date: Tue, 18 Feb 2025 21:21:29 +0800 Subject: [PATCH 16/34] feat(ui): version checker --- ui/src/components/Version.tsx | 18 +++++--- ui/src/hooks/index.ts | 3 +- ui/src/hooks/useVersionChecker.ts | 70 +++++++++++++++++++++++++++++++ 3 files changed, 85 insertions(+), 6 deletions(-) create mode 100644 ui/src/hooks/useVersionChecker.ts diff --git a/ui/src/components/Version.tsx b/ui/src/components/Version.tsx index 4832cce8..fcdf1170 100644 --- a/ui/src/components/Version.tsx +++ b/ui/src/components/Version.tsx @@ -1,8 +1,10 @@ +import { memo, useEffect, useState } from "react"; import { useTranslation } from "react-i18next"; import { ReadOutlined as ReadOutlinedIcon } from "@ant-design/icons"; -import { Divider, Space, Typography } from "antd"; +import { Badge, Divider, Space, Typography } from "antd"; import { version } from "@/domain/version"; +import { useVersionChecker } from "@/hooks"; export type VersionProps = { className?: string; @@ -12,6 +14,8 @@ export type VersionProps = { const Version = ({ className, style }: VersionProps) => { const { t } = useTranslation(); + const { data: hasNewVersions } = useVersionChecker(); + return ( @@ -20,12 +24,16 @@ const Version = ({ className, style }: VersionProps) => { {t("common.menu.document")} + - - {version} - + + + + {version} + + ); }; -export default Version; +export default memo(Version); diff --git a/ui/src/hooks/index.ts b/ui/src/hooks/index.ts index 045c0aad..6f154701 100644 --- a/ui/src/hooks/index.ts +++ b/ui/src/hooks/index.ts @@ -2,6 +2,7 @@ import useAntdFormName from "./useAntdFormName"; import useBrowserTheme from "./useBrowserTheme"; import useTriggerElement from "./useTriggerElement"; +import useVersionChecker from "./useVersionChecker"; import useZustandShallowSelector from "./useZustandShallowSelector"; -export { useAntdForm, useAntdFormName, useBrowserTheme, useTriggerElement, useZustandShallowSelector }; +export { useAntdForm, useAntdFormName, useBrowserTheme, useTriggerElement, useVersionChecker, useZustandShallowSelector }; diff --git a/ui/src/hooks/useVersionChecker.ts b/ui/src/hooks/useVersionChecker.ts new file mode 100644 index 00000000..e77b69f9 --- /dev/null +++ b/ui/src/hooks/useVersionChecker.ts @@ -0,0 +1,70 @@ +import { useRequest } from "ahooks"; + +import { version } from "@/domain/version"; + +export type UseVersionCheckerReturns = { + data: boolean; + check: () => void; +}; + +const extractSemver = (vers: string) => { + let semver = String(vers ?? ""); + semver = semver.replace(/^v/i, ""); + semver = semver.split("-")[0]; + return semver; +}; + +const compareVersions = (a: string, b: string) => { + const aSemver = extractSemver(a); + const bSemver = extractSemver(b); + const aSemverParts = aSemver.split("."); + const bSemverParts = bSemver.split("."); + + const len = Math.max(aSemverParts.length, bSemverParts.length); + for (let i = 0; i < len; i++) { + const aPart = parseInt(aSemverParts[i] ?? "0"); + const bPart = parseInt(bSemverParts[i] ?? "0"); + if (aPart > bPart) return 1; + if (bPart > aPart) return -1; + } + + return 0; +}; + +/** + * 获取版本检查器。 + * @returns {UseVersionCheckerReturns} + */ +const useVersionChecker = () => { + const { data, refresh } = useRequest( + async () => { + const releases = await fetch("https://api.github.com/repos/usual2970/certimate/releases") + .then((res) => res.json()) + .then((res) => Array.from(res)); + + const cIdx = releases.findIndex((e: any) => e.name === version); + if (cIdx === 0) { + return false; + } + + const nIdx = releases.findIndex((e: any) => compareVersions(e.name, version) !== -1); + if (cIdx >= nIdx) { + return false; + } + + return !!releases[nIdx]; + }, + { + pollingInterval: 6 * 60 * 60 * 1000, + refreshOnWindowFocus: true, + focusTimespan: 15 * 60 * 1000, + } + ); + + return { + data: !!data, + check: refresh, + }; +}; + +export default useVersionChecker; From 469c24751e63b3de519c717879a608c78e40a671 Mon Sep 17 00:00:00 2001 From: Fu Diwei Date: Wed, 19 Feb 2025 21:55:38 +0800 Subject: [PATCH 17/34] refactor: reimpl 3rd sdks --- internal/domain/provider.go | 2 + .../baotapanel-site/baotapanel_site_test.go | 8 +-- internal/pkg/vendors/baishan-sdk/api.go | 31 ++++------- internal/pkg/vendors/baishan-sdk/client.go | 18 ++++--- internal/pkg/vendors/btpanel-sdk/api.go | 54 ++++++------------- internal/pkg/vendors/btpanel-sdk/client.go | 24 +++++---- internal/pkg/vendors/cachefly-sdk/api.go | 11 ++-- internal/pkg/vendors/cachefly-sdk/client.go | 18 ++++--- internal/pkg/vendors/cdnfly-sdk/api.go | 41 +++++--------- internal/pkg/vendors/cdnfly-sdk/client.go | 18 ++++--- internal/pkg/vendors/gname-sdk/api.go | 40 ++++---------- internal/pkg/vendors/gname-sdk/client.go | 19 +++---- internal/pkg/vendors/gname-sdk/models.go | 10 ++-- internal/pkg/vendors/safeline-sdk/api.go | 14 ++--- internal/pkg/vendors/safeline-sdk/client.go | 8 +-- migrations/1739462400_collections_snapshot.go | 4 ++ 16 files changed, 131 insertions(+), 189 deletions(-) diff --git a/internal/domain/provider.go b/internal/domain/provider.go index 93f85561..08527fdd 100644 --- a/internal/domain/provider.go +++ b/internal/domain/provider.go @@ -34,6 +34,7 @@ const ( AccessProviderTypeGoDaddy = AccessProviderType("godaddy") AccessProviderTypeGoEdge = AccessProviderType("goedge") // GoEdge(预留) AccessProviderTypeHuaweiCloud = AccessProviderType("huaweicloud") + AccessProviderTypeJDCloud = AccessProviderType("jdcloud") // 京东云(预留) AccessProviderTypeKubernetes = AccessProviderType("k8s") AccessProviderTypeLocal = AccessProviderType("local") AccessProviderTypeNameDotCom = AccessProviderType("namedotcom") @@ -41,6 +42,7 @@ const ( AccessProviderTypeNS1 = AccessProviderType("ns1") AccessProviderTypePowerDNS = AccessProviderType("powerdns") AccessProviderTypeQiniu = AccessProviderType("qiniu") + AccessProviderTypeQingCloud = AccessProviderType("qingcloud") // 青云(预留) AccessProviderTypeRainYun = AccessProviderType("rainyun") AccessProviderTypeSafeLine = AccessProviderType("safeline") AccessProviderTypeSSH = AccessProviderType("ssh") diff --git a/internal/pkg/core/deployer/providers/baotapanel-site/baotapanel_site_test.go b/internal/pkg/core/deployer/providers/baotapanel-site/baotapanel_site_test.go index 00d32461..4c31b021 100644 --- a/internal/pkg/core/deployer/providers/baotapanel-site/baotapanel_site_test.go +++ b/internal/pkg/core/deployer/providers/baotapanel-site/baotapanel_site_test.go @@ -57,9 +57,11 @@ func TestDeploy(t *testing.T) { }, "\n")) deployer, err := provider.NewDeployer(&provider.DeployerConfig{ - ApiUrl: fApiUrl, - ApiKey: fApiKey, - SiteName: fSiteName, + ApiUrl: fApiUrl, + ApiKey: fApiKey, + SiteType: fSiteType, + SiteName: fSiteName, + SiteNames: []string{fSiteName}, }) if err != nil { t.Errorf("err: %+v", err) diff --git a/internal/pkg/vendors/baishan-sdk/api.go b/internal/pkg/vendors/baishan-sdk/api.go index 9e6a2bc6..c2f76adc 100644 --- a/internal/pkg/vendors/baishan-sdk/api.go +++ b/internal/pkg/vendors/baishan-sdk/api.go @@ -1,45 +1,32 @@ package baishansdk import ( - "encoding/json" "net/http" ) func (c *Client) CreateCertificate(req *CreateCertificateRequest) (*CreateCertificateResponse, error) { - params := make(map[string]any) - jsonData, _ := json.Marshal(req) - json.Unmarshal(jsonData, ¶ms) - - result := CreateCertificateResponse{} - err := c.sendRequestWithResult(http.MethodPost, "/v2/domain/certificate", params, &result) + resp := CreateCertificateResponse{} + err := c.sendRequestWithResult(http.MethodPost, "/v2/domain/certificate", req, &resp) if err != nil { return nil, err } - return &result, nil + return &resp, nil } func (c *Client) GetDomainConfig(req *GetDomainConfigRequest) (*GetDomainConfigResponse, error) { - params := make(map[string]any) - jsonData, _ := json.Marshal(req) - json.Unmarshal(jsonData, ¶ms) - - result := GetDomainConfigResponse{} - err := c.sendRequestWithResult(http.MethodGet, "/v2/domain/config", params, &result) + resp := GetDomainConfigResponse{} + err := c.sendRequestWithResult(http.MethodGet, "/v2/domain/config", req, &resp) if err != nil { return nil, err } - return &result, nil + return &resp, nil } func (c *Client) SetDomainConfig(req *SetDomainConfigRequest) (*SetDomainConfigResponse, error) { - params := make(map[string]any) - jsonData, _ := json.Marshal(req) - json.Unmarshal(jsonData, ¶ms) - - result := SetDomainConfigResponse{} - err := c.sendRequestWithResult(http.MethodPost, "/v2/domain/config", params, &result) + resp := SetDomainConfigResponse{} + err := c.sendRequestWithResult(http.MethodPost, "/v2/domain/config", req, &resp) if err != nil { return nil, err } - return &result, nil + return &resp, nil } diff --git a/internal/pkg/vendors/baishan-sdk/client.go b/internal/pkg/vendors/baishan-sdk/client.go index d30dd05f..ff66af5b 100644 --- a/internal/pkg/vendors/baishan-sdk/client.go +++ b/internal/pkg/vendors/baishan-sdk/client.go @@ -29,17 +29,23 @@ func (c *Client) WithTimeout(timeout time.Duration) *Client { return c } -func (c *Client) sendRequest(method string, path string, params map[string]any) (*resty.Response, error) { +func (c *Client) sendRequest(method string, path string, params interface{}) (*resty.Response, error) { req := c.client.R() req.Method = method req.URL = "https://cdn.api.baishan.com" + path if strings.EqualFold(method, http.MethodGet) { - data := make(map[string]string) - for k, v := range params { - data[k] = fmt.Sprintf("%v", v) + qs := make(map[string]string) + if params != nil { + temp := make(map[string]any) + jsonData, _ := json.Marshal(params) + json.Unmarshal(jsonData, &temp) + for k, v := range temp { + qs[k] = fmt.Sprintf("%v", v) + } } + req = req. - SetQueryParams(data). + SetQueryParams(qs). SetQueryParam("token", c.apiToken) } else { req = req. @@ -58,7 +64,7 @@ func (c *Client) sendRequest(method string, path string, params map[string]any) return resp, nil } -func (c *Client) sendRequestWithResult(method string, path string, params map[string]any, result BaseResponse) error { +func (c *Client) sendRequestWithResult(method string, path string, params interface{}, result BaseResponse) error { resp, err := c.sendRequest(method, path, params) if err != nil { return err diff --git a/internal/pkg/vendors/btpanel-sdk/api.go b/internal/pkg/vendors/btpanel-sdk/api.go index b4efa433..434e7f6e 100644 --- a/internal/pkg/vendors/btpanel-sdk/api.go +++ b/internal/pkg/vendors/btpanel-sdk/api.go @@ -1,70 +1,46 @@ package btpanelsdk -import ( - "encoding/json" -) - func (c *Client) ConfigSavePanelSSL(req *ConfigSavePanelSSLRequest) (*ConfigSavePanelSSLResponse, error) { - params := make(map[string]any) - jsonData, _ := json.Marshal(req) - json.Unmarshal(jsonData, ¶ms) - - result := ConfigSavePanelSSLResponse{} - err := c.sendRequestWithResult("/config?action=SavePanelSSL", params, &result) + resp := ConfigSavePanelSSLResponse{} + err := c.sendRequestWithResult("/config?action=SavePanelSSL", req, &resp) if err != nil { return nil, err } - return &result, nil + return &resp, nil } func (c *Client) SiteSetSSL(req *SiteSetSSLRequest) (*SiteSetSSLResponse, error) { - params := make(map[string]any) - jsonData, _ := json.Marshal(req) - json.Unmarshal(jsonData, ¶ms) - - result := SiteSetSSLResponse{} - err := c.sendRequestWithResult("/site?action=SetSSL", params, &result) + resp := SiteSetSSLResponse{} + err := c.sendRequestWithResult("/site?action=SetSSL", req, &resp) if err != nil { return nil, err } - return &result, nil + return &resp, nil } func (c *Client) SystemServiceAdmin(req *SystemServiceAdminRequest) (*SystemServiceAdminResponse, error) { - params := make(map[string]any) - jsonData, _ := json.Marshal(req) - json.Unmarshal(jsonData, ¶ms) - - result := SystemServiceAdminResponse{} - err := c.sendRequestWithResult("/system?action=ServiceAdmin", params, &result) + resp := SystemServiceAdminResponse{} + err := c.sendRequestWithResult("/system?action=ServiceAdmin", req, &resp) if err != nil { return nil, err } - return &result, nil + return &resp, nil } func (c *Client) SSLCertSaveCert(req *SSLCertSaveCertRequest) (*SSLCertSaveCertResponse, error) { - params := make(map[string]any) - jsonData, _ := json.Marshal(req) - json.Unmarshal(jsonData, ¶ms) - - result := SSLCertSaveCertResponse{} - err := c.sendRequestWithResult("/ssl/cert/save_cert", params, &result) + resp := SSLCertSaveCertResponse{} + err := c.sendRequestWithResult("/ssl/cert/save_cert", req, &resp) if err != nil { return nil, err } - return &result, nil + return &resp, nil } func (c *Client) SSLSetBatchCertToSite(req *SSLSetBatchCertToSiteRequest) (*SSLSetBatchCertToSiteResponse, error) { - params := make(map[string]any) - jsonData, _ := json.Marshal(req) - json.Unmarshal(jsonData, ¶ms) - - result := SSLSetBatchCertToSiteResponse{} - err := c.sendRequestWithResult("/ssl?action=SetBatchCertToSite", params, &result) + resp := SSLSetBatchCertToSiteResponse{} + err := c.sendRequestWithResult("/ssl?action=SetBatchCertToSite", req, &resp) if err != nil { return nil, err } - return &result, nil + return &resp, nil } diff --git a/internal/pkg/vendors/btpanel-sdk/client.go b/internal/pkg/vendors/btpanel-sdk/client.go index 32f3eba8..8ef38864 100644 --- a/internal/pkg/vendors/btpanel-sdk/client.go +++ b/internal/pkg/vendors/btpanel-sdk/client.go @@ -42,19 +42,25 @@ func (c *Client) generateSignature(timestamp string) string { return signMd5Hex } -func (c *Client) sendRequest(path string, params map[string]any) (*resty.Response, error) { - if params == nil { - params = make(map[string]any) - } - +func (c *Client) sendRequest(path string, params interface{}) (*resty.Response, error) { timestamp := time.Now().Unix() - params["request_time"] = timestamp - params["request_token"] = c.generateSignature(fmt.Sprintf("%d", timestamp)) + + data := make(map[string]any) + if params != nil { + temp := make(map[string]any) + jsonData, _ := json.Marshal(params) + json.Unmarshal(jsonData, &temp) + for k, v := range temp { + data[k] = v + } + } + data["request_time"] = timestamp + data["request_token"] = c.generateSignature(fmt.Sprintf("%d", timestamp)) url := c.apiHost + path req := c.client.R(). SetHeader("Content-Type", "application/json"). - SetBody(params) + SetBody(data) resp, err := req.Post(url) if err != nil { return nil, fmt.Errorf("baota api error: failed to send request: %w", err) @@ -65,7 +71,7 @@ func (c *Client) sendRequest(path string, params map[string]any) (*resty.Respons return resp, nil } -func (c *Client) sendRequestWithResult(path string, params map[string]any, result BaseResponse) error { +func (c *Client) sendRequestWithResult(path string, params interface{}, result BaseResponse) error { resp, err := c.sendRequest(path, params) if err != nil { return err diff --git a/internal/pkg/vendors/cachefly-sdk/api.go b/internal/pkg/vendors/cachefly-sdk/api.go index 16a3411a..ad6e3b8d 100644 --- a/internal/pkg/vendors/cachefly-sdk/api.go +++ b/internal/pkg/vendors/cachefly-sdk/api.go @@ -1,19 +1,14 @@ package cacheflysdk import ( - "encoding/json" "net/http" ) func (c *Client) CreateCertificate(req *CreateCertificateRequest) (*CreateCertificateResponse, error) { - params := make(map[string]any) - jsonData, _ := json.Marshal(req) - json.Unmarshal(jsonData, ¶ms) - - result := CreateCertificateResponse{} - err := c.sendRequestWithResult(http.MethodPost, "/certificates", params, &result) + resp := CreateCertificateResponse{} + err := c.sendRequestWithResult(http.MethodPost, "/certificates", req, &resp) if err != nil { return nil, err } - return &result, nil + return &resp, nil } diff --git a/internal/pkg/vendors/cachefly-sdk/client.go b/internal/pkg/vendors/cachefly-sdk/client.go index 6f6a4790..e48e2010 100644 --- a/internal/pkg/vendors/cachefly-sdk/client.go +++ b/internal/pkg/vendors/cachefly-sdk/client.go @@ -29,17 +29,23 @@ func (c *Client) WithTimeout(timeout time.Duration) *Client { return c } -func (c *Client) sendRequest(method string, path string, params map[string]any) (*resty.Response, error) { +func (c *Client) sendRequest(method string, path string, params interface{}) (*resty.Response, error) { req := c.client.R() req.Method = method req.URL = "https://api.cachefly.com/api/2.5" + path req = req.SetHeader("x-cf-authorization", "Bearer "+c.apiToken) if strings.EqualFold(method, http.MethodGet) { - data := make(map[string]string) - for k, v := range params { - data[k] = fmt.Sprintf("%v", v) + qs := make(map[string]string) + if params != nil { + temp := make(map[string]any) + jsonData, _ := json.Marshal(params) + json.Unmarshal(jsonData, &temp) + for k, v := range temp { + qs[k] = fmt.Sprintf("%v", v) + } } - req = req.SetQueryParams(data) + + req = req.SetQueryParams(qs) } else { req = req. SetHeader("Content-Type", "application/json"). @@ -56,7 +62,7 @@ func (c *Client) sendRequest(method string, path string, params map[string]any) return resp, nil } -func (c *Client) sendRequestWithResult(method string, path string, params map[string]any, result BaseResponse) error { +func (c *Client) sendRequestWithResult(method string, path string, params interface{}, result BaseResponse) error { resp, err := c.sendRequest(method, path, params) if err != nil { return err diff --git a/internal/pkg/vendors/cdnfly-sdk/api.go b/internal/pkg/vendors/cdnfly-sdk/api.go index 5f8ebb0a..211baa33 100644 --- a/internal/pkg/vendors/cdnfly-sdk/api.go +++ b/internal/pkg/vendors/cdnfly-sdk/api.go @@ -1,59 +1,42 @@ package cdnflysdk import ( - "encoding/json" "fmt" "net/http" ) func (c *Client) GetSite(req *GetSiteRequest) (*GetSiteResponse, error) { - params := make(map[string]any) - jsonData, _ := json.Marshal(req) - json.Unmarshal(jsonData, ¶ms) - - result := GetSiteResponse{} - err := c.sendRequestWithResult(http.MethodGet, fmt.Sprintf("/v1/sites/%s", req.Id), params, &result) + resp := GetSiteResponse{} + err := c.sendRequestWithResult(http.MethodGet, fmt.Sprintf("/v1/sites/%s", req.Id), req, &resp) if err != nil { return nil, err } - return &result, nil + return &resp, nil } func (c *Client) UpdateSite(req *UpdateSiteRequest) (*UpdateSiteResponse, error) { - params := make(map[string]any) - jsonData, _ := json.Marshal(req) - json.Unmarshal(jsonData, ¶ms) - - result := UpdateSiteResponse{} - err := c.sendRequestWithResult(http.MethodPut, fmt.Sprintf("/v1/sites/%s", req.Id), params, &result) + resp := UpdateSiteResponse{} + err := c.sendRequestWithResult(http.MethodPut, fmt.Sprintf("/v1/sites/%s", req.Id), req, &resp) if err != nil { return nil, err } - return &result, nil + return &resp, nil } func (c *Client) CreateCertificate(req *CreateCertificateRequest) (*CreateCertificateResponse, error) { - params := make(map[string]any) - jsonData, _ := json.Marshal(req) - json.Unmarshal(jsonData, ¶ms) - - result := CreateCertificateResponse{} - err := c.sendRequestWithResult(http.MethodPost, "/v1/certs", params, &result) + resp := CreateCertificateResponse{} + err := c.sendRequestWithResult(http.MethodPost, "/v1/certs", req, &resp) if err != nil { return nil, err } - return &result, nil + return &resp, nil } func (c *Client) UpdateCertificate(req *UpdateCertificateRequest) (*UpdateCertificateResponse, error) { - params := make(map[string]any) - jsonData, _ := json.Marshal(req) - json.Unmarshal(jsonData, ¶ms) - - result := UpdateCertificateResponse{} - err := c.sendRequestWithResult(http.MethodPut, fmt.Sprintf("/v1/certs/%s", req.Id), params, &result) + resp := UpdateCertificateResponse{} + err := c.sendRequestWithResult(http.MethodPut, fmt.Sprintf("/v1/certs/%s", req.Id), req, &resp) if err != nil { return nil, err } - return &result, nil + return &resp, nil } diff --git a/internal/pkg/vendors/cdnfly-sdk/client.go b/internal/pkg/vendors/cdnfly-sdk/client.go index 910020b3..630e156c 100644 --- a/internal/pkg/vendors/cdnfly-sdk/client.go +++ b/internal/pkg/vendors/cdnfly-sdk/client.go @@ -34,7 +34,7 @@ func (c *Client) WithTimeout(timeout time.Duration) *Client { return c } -func (c *Client) sendRequest(method string, path string, params map[string]any) (*resty.Response, error) { +func (c *Client) sendRequest(method string, path string, params interface{}) (*resty.Response, error) { req := c.client.R() req.Method = method req.URL = c.apiHost + path @@ -42,11 +42,17 @@ func (c *Client) sendRequest(method string, path string, params map[string]any) SetHeader("api-key", c.apiKey). SetHeader("api-secret", c.apiSecret) if strings.EqualFold(method, http.MethodGet) { - data := make(map[string]string) - for k, v := range params { - data[k] = fmt.Sprintf("%v", v) + qs := make(map[string]string) + if params != nil { + temp := make(map[string]any) + jsonData, _ := json.Marshal(params) + json.Unmarshal(jsonData, &temp) + for k, v := range temp { + qs[k] = fmt.Sprintf("%v", v) + } } - req = req.SetQueryParams(data) + + req = req.SetQueryParams(qs) } else { req = req. SetHeader("Content-Type", "application/json"). @@ -63,7 +69,7 @@ func (c *Client) sendRequest(method string, path string, params map[string]any) return resp, nil } -func (c *Client) sendRequestWithResult(method string, path string, params map[string]any, result BaseResponse) error { +func (c *Client) sendRequestWithResult(method string, path string, params interface{}, result BaseResponse) error { resp, err := c.sendRequest(method, path, params) if err != nil { return err diff --git a/internal/pkg/vendors/gname-sdk/api.go b/internal/pkg/vendors/gname-sdk/api.go index 20891405..d01574c7 100644 --- a/internal/pkg/vendors/gname-sdk/api.go +++ b/internal/pkg/vendors/gname-sdk/api.go @@ -1,16 +1,8 @@ package gnamesdk -import ( - "encoding/json" -) - func (c *Client) AddDomainResolution(req *AddDomainResolutionRequest) (*AddDomainResolutionResponse, error) { - params := make(map[string]any) - jsonData, _ := json.Marshal(req) - json.Unmarshal(jsonData, ¶ms) - result := AddDomainResolutionResponse{} - err := c.sendRequestWithResult("/api/resolution/add", params, &result) + err := c.sendRequestWithResult("/api/resolution/add", req, &result) if err != nil { return nil, err } @@ -18,40 +10,28 @@ func (c *Client) AddDomainResolution(req *AddDomainResolutionRequest) (*AddDomai } func (c *Client) ModifyDomainResolution(req *ModifyDomainResolutionRequest) (*ModifyDomainResolutionResponse, error) { - params := make(map[string]any) - jsonData, _ := json.Marshal(req) - json.Unmarshal(jsonData, ¶ms) - - result := ModifyDomainResolutionResponse{} - err := c.sendRequestWithResult("/api/resolution/edit", params, &result) + resp := ModifyDomainResolutionResponse{} + err := c.sendRequestWithResult("/api/resolution/edit", req, &resp) if err != nil { return nil, err } - return &result, nil + return &resp, nil } func (c *Client) DeleteDomainResolution(req *DeleteDomainResolutionRequest) (*DeleteDomainResolutionResponse, error) { - params := make(map[string]any) - jsonData, _ := json.Marshal(req) - json.Unmarshal(jsonData, ¶ms) - - result := DeleteDomainResolutionResponse{} - err := c.sendRequestWithResult("/api/resolution/delete", params, &result) + resp := DeleteDomainResolutionResponse{} + err := c.sendRequestWithResult("/api/resolution/delete", req, &resp) if err != nil { return nil, err } - return &result, nil + return &resp, nil } func (c *Client) ListDomainResolution(req *ListDomainResolutionRequest) (*ListDomainResolutionResponse, error) { - params := make(map[string]any) - jsonData, _ := json.Marshal(req) - json.Unmarshal(jsonData, ¶ms) - - result := ListDomainResolutionResponse{} - err := c.sendRequestWithResult("/api/resolution/list", params, &result) + resp := ListDomainResolutionResponse{} + err := c.sendRequestWithResult("/api/resolution/list", req, &resp) if err != nil { return nil, err } - return &result, nil + return &resp, nil } diff --git a/internal/pkg/vendors/gname-sdk/client.go b/internal/pkg/vendors/gname-sdk/client.go index d3b9fb86..c4225357 100644 --- a/internal/pkg/vendors/gname-sdk/client.go +++ b/internal/pkg/vendors/gname-sdk/client.go @@ -58,14 +58,15 @@ func (c *Client) generateSignature(params map[string]string) string { return strings.ToUpper(fmt.Sprintf("%x", hash)) } -func (c *Client) sendRequest(path string, params map[string]any) (*resty.Response, error) { - if params == nil { - params = make(map[string]any) - } - +func (c *Client) sendRequest(path string, params interface{}) (*resty.Response, error) { data := make(map[string]string) - for k, v := range params { - data[k] = fmt.Sprintf("%v", v) + if params != nil { + temp := make(map[string]any) + jsonData, _ := json.Marshal(params) + json.Unmarshal(jsonData, &temp) + for k, v := range temp { + data[k] = fmt.Sprintf("%v", v) + } } data["appid"] = c.appId data["gntime"] = fmt.Sprintf("%d", time.Now().Unix()) @@ -85,7 +86,7 @@ func (c *Client) sendRequest(path string, params map[string]any) (*resty.Respons return resp, nil } -func (c *Client) sendRequestWithResult(path string, params map[string]any, result BaseResponse) error { +func (c *Client) sendRequestWithResult(path string, params interface{}, result BaseResponse) error { resp, err := c.sendRequest(path, params) if err != nil { return err @@ -94,7 +95,7 @@ func (c *Client) sendRequestWithResult(path string, params map[string]any, resul if err := json.Unmarshal(resp.Body(), &result); err != nil { return fmt.Errorf("gname api error: failed to parse response: %w", err) } else if errcode := result.GetCode(); errcode != 1 { - return fmt.Errorf("gname api error: %d - %s", errcode, result.GetMsg()) + return fmt.Errorf("gname api error: %d - %s", errcode, result.GetMessage()) } return nil diff --git a/internal/pkg/vendors/gname-sdk/models.go b/internal/pkg/vendors/gname-sdk/models.go index 282439d2..c7ade452 100644 --- a/internal/pkg/vendors/gname-sdk/models.go +++ b/internal/pkg/vendors/gname-sdk/models.go @@ -2,20 +2,20 @@ package gnamesdk type BaseResponse interface { GetCode() int - GetMsg() string + GetMessage() string } type baseResponse struct { - Code int `json:"code"` - Msg string `json:"msg"` + Code int `json:"code"` + Message string `json:"msg"` } func (r *baseResponse) GetCode() int { return r.Code } -func (r *baseResponse) GetMsg() string { - return r.Msg +func (r *baseResponse) GetMessage() string { + return r.Message } type AddDomainResolutionRequest struct { diff --git a/internal/pkg/vendors/safeline-sdk/api.go b/internal/pkg/vendors/safeline-sdk/api.go index ae0a56d1..17af6c83 100644 --- a/internal/pkg/vendors/safeline-sdk/api.go +++ b/internal/pkg/vendors/safeline-sdk/api.go @@ -1,18 +1,10 @@ package safelinesdk -import ( - "encoding/json" -) - func (c *Client) UpdateCertificate(req *UpdateCertificateRequest) (*UpdateCertificateResponse, error) { - params := make(map[string]any) - jsonData, _ := json.Marshal(req) - json.Unmarshal(jsonData, ¶ms) - - result := UpdateCertificateResponse{} - err := c.sendRequestWithResult("/api/open/cert", params, &result) + resp := UpdateCertificateResponse{} + err := c.sendRequestWithResult("/api/open/cert", req, &resp) if err != nil { return nil, err } - return &result, nil + return &resp, nil } diff --git a/internal/pkg/vendors/safeline-sdk/client.go b/internal/pkg/vendors/safeline-sdk/client.go index 5aa19c07..c6e6caf1 100644 --- a/internal/pkg/vendors/safeline-sdk/client.go +++ b/internal/pkg/vendors/safeline-sdk/client.go @@ -31,11 +31,7 @@ func (c *Client) WithTimeout(timeout time.Duration) *Client { return c } -func (c *Client) sendRequest(path string, params map[string]any) (*resty.Response, error) { - if params == nil { - params = make(map[string]any) - } - +func (c *Client) sendRequest(path string, params interface{}) (*resty.Response, error) { url := c.apiHost + path req := c.client.R(). SetHeader("Content-Type", "application/json"). @@ -51,7 +47,7 @@ func (c *Client) sendRequest(path string, params map[string]any) (*resty.Respons return resp, nil } -func (c *Client) sendRequestWithResult(path string, params map[string]any, result BaseResponse) error { +func (c *Client) sendRequestWithResult(path string, params interface{}, result BaseResponse) error { resp, err := c.sendRequest(path, params) if err != nil { return err diff --git a/migrations/1739462400_collections_snapshot.go b/migrations/1739462400_collections_snapshot.go index 523792c7..9c079405 100644 --- a/migrations/1739462400_collections_snapshot.go +++ b/migrations/1739462400_collections_snapshot.go @@ -73,6 +73,7 @@ func init() { "godaddy", "goedge", "huaweicloud", + "jdcloud", "k8s", "local", "namedotcom", @@ -80,6 +81,7 @@ func init() { "ns1", "powerdns", "qiniu", + "qingcloud", "rainyun", "safeline", "ssh", @@ -179,6 +181,7 @@ func init() { "godaddy", "goedge", "huaweicloud", + "jdcloud", "k8s", "local", "namedotcom", @@ -186,6 +189,7 @@ func init() { "ns1", "powerdns", "qiniu", + "qingcloud", "rainyun", "safeline", "ssh", From 72896e052ccd5f8ccb26d98baa336c950cfd4a27 Mon Sep 17 00:00:00 2001 From: Fu Diwei Date: Wed, 19 Feb 2025 23:57:22 +0800 Subject: [PATCH 18/34] feat: add jdcloud dns-01 applicant --- README.md | 1 + README_EN.md | 1 + go.mod | 2 + go.sum | 4 + internal/applicant/providers.go | 20 +- internal/domain/access.go | 7 +- internal/domain/provider.go | 5 +- .../baiducloud/internal/lego.go | 6 +- .../lego-providers/jdcloud/internal/lego.go | 229 ++++++++++++++++++ .../lego-providers/jdcloud/jdcloud.go | 47 ++++ ui/public/imgs/providers/jdcloud.svg | 1 + ui/src/components/Version.tsx | 2 +- ui/src/components/access/AccessForm.tsx | 3 + .../access/AccessFormJDCloudConfig.tsx | 76 ++++++ .../workflow/node/ApplyNodeConfigForm.tsx | 4 + .../ApplyNodeConfigFormJDCloudDNSConfig.tsx | 61 +++++ ui/src/domain/access.ts | 6 + ui/src/domain/provider.ts | 6 + ui/src/i18n/locales/en/nls.access.json | 10 +- ui/src/i18n/locales/en/nls.common.json | 10 +- .../i18n/locales/en/nls.workflow.nodes.json | 2 + ui/src/i18n/locales/zh/nls.access.json | 10 +- ui/src/i18n/locales/zh/nls.provider.json | 2 + .../i18n/locales/zh/nls.workflow.nodes.json | 2 + 24 files changed, 502 insertions(+), 15 deletions(-) create mode 100644 internal/pkg/core/applicant/acme-dns-01/lego-providers/jdcloud/internal/lego.go create mode 100644 internal/pkg/core/applicant/acme-dns-01/lego-providers/jdcloud/jdcloud.go create mode 100644 ui/public/imgs/providers/jdcloud.svg create mode 100644 ui/src/components/access/AccessFormJDCloudConfig.tsx create mode 100644 ui/src/components/workflow/node/ApplyNodeConfigFormJDCloudDNSConfig.tsx diff --git a/README.md b/README.md index f9d4df00..fcc0ad27 100644 --- a/README.md +++ b/README.md @@ -93,6 +93,7 @@ make local.run | [百度智能云](https://cloud.baidu.com/) | | | [华为云](https://www.huaweicloud.com/) | | | [火山引擎](https://www.volcengine.com/) | | +| [京东云](https://www.jdcloud.com/) | | | [AWS Route53](https://aws.amazon.com/route53/) | | | [Azure](https://azure.microsoft.com/) | | | [CloudFlare](https://www.cloudflare.com/) | | diff --git a/README_EN.md b/README_EN.md index a6d13c26..cae7e0f7 100644 --- a/README_EN.md +++ b/README_EN.md @@ -92,6 +92,7 @@ The following DNS providers are supported: | [Baidu AI Cloud](https://intl.cloud.baidu.com/) | | | [Huawei Cloud](https://www.huaweicloud.com/) | | | [Volcengine](https://www.volcengine.com/) | | +| [JD Cloud](https://www.jdcloud.com/) | | | [AWS Route53](https://aws.amazon.com/route53/) | | | [Azure DNS](https://azure.microsoft.com/) | | | [CloudFlare](https://www.cloudflare.com/) | | diff --git a/go.mod b/go.mod index c07f2a5b..5a1949f5 100644 --- a/go.mod +++ b/go.mod @@ -77,12 +77,14 @@ require ( github.com/go-playground/universal-translator v0.18.1 // indirect github.com/go-playground/validator/v10 v10.16.0 // indirect github.com/go-telegram-bot-api/telegram-bot-api v4.6.4+incompatible // indirect + github.com/gofrs/uuid v4.4.0+incompatible // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang-jwt/jwt/v5 v5.2.1 // indirect github.com/golang/protobuf v1.5.4 // indirect github.com/google/gnostic-models v0.6.9 // indirect github.com/google/go-cmp v0.6.0 // indirect github.com/google/gofuzz v1.2.0 // indirect + github.com/jdcloud-api/jdcloud-sdk-go v1.62.0 // indirect github.com/josharian/intern v1.0.0 // indirect github.com/kylelemons/godebug v1.1.0 // indirect github.com/leodido/go-urn v1.4.0 // indirect diff --git a/go.sum b/go.sum index f127aeb4..1929c808 100644 --- a/go.sum +++ b/go.sum @@ -427,6 +427,8 @@ github.com/goccy/go-json v0.10.4 h1:JSwxQzIqKfmFX1swYPpUThQZp/Ka4wzJdK0LWVytLPM= github.com/goccy/go-json v0.10.4/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/gofrs/flock v0.8.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU= +github.com/gofrs/uuid v4.4.0+incompatible h1:3qXRTX8/NbyulANqlc0lchS1gqAVxRgsuW1YrTJupqA= +github.com/gofrs/uuid v4.4.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= @@ -576,6 +578,8 @@ github.com/jcmturner/gofork v1.0.0/go.mod h1:MK8+TM0La+2rjBD4jE12Kj1pCCxK7d2LK/U github.com/jcmturner/goidentity/v6 v6.0.1/go.mod h1:X1YW3bgtvwAXju7V3LCIMpY0Gbxyjn/mY9zx4tFonSg= github.com/jcmturner/gokrb5/v8 v8.4.2/go.mod h1:sb+Xq/fTY5yktf/VxLsE3wlfPqQjp0aWNYyvBVK62bc= github.com/jcmturner/rpc/v2 v2.0.3/go.mod h1:VUJYCIDm3PVOEHw8sgt091/20OJjskO/YJki3ELg/Hc= +github.com/jdcloud-api/jdcloud-sdk-go v1.62.0 h1:uPfyOSY16mBrhggriDNeySFB4ZkzMMXpNac2P0fbDRw= +github.com/jdcloud-api/jdcloud-sdk-go v1.62.0/go.mod h1:UrKjuULIWLjHFlG6aSPunArE5QX57LftMmStAZJBEX8= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg= github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= diff --git a/internal/applicant/providers.go b/internal/applicant/providers.go index 10466389..d1e80083 100644 --- a/internal/applicant/providers.go +++ b/internal/applicant/providers.go @@ -17,6 +17,7 @@ import ( pGname "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/gname" pGoDaddy "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/godaddy" pHuaweiCloud "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/huaweicloud" + pJDCloud "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/jdcloud" pNameDotCom "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/namedotcom" pNameSilo "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/namesilo" pNS1 "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/ns1" @@ -85,7 +86,7 @@ func createApplicant(options *applicantOptions) (challenge.Provider, error) { return applicant, err } - case domain.ApplyDNSProviderTypeAzureDNS: + case domain.ApplyDNSProviderTypeAzure, domain.ApplyDNSProviderTypeAzureDNS: { access := domain.AccessConfigForAzure{} if err := maps.Populate(options.ProviderAccessConfig, &access); err != nil { @@ -214,6 +215,23 @@ func createApplicant(options *applicantOptions) (challenge.Provider, error) { return applicant, err } + case domain.ApplyDNSProviderTypeJDCloud, domain.ApplyDNSProviderTypeJDCloudDNS: + { + access := domain.AccessConfigForJDCloud{} + if err := maps.Populate(options.ProviderAccessConfig, &access); err != nil { + return nil, fmt.Errorf("failed to populate provider access config: %w", err) + } + + applicant, err := pJDCloud.NewChallengeProvider(&pJDCloud.ChallengeProviderConfig{ + AccessKeyId: access.AccessKeyId, + AccessKeySecret: access.AccessKeySecret, + RegionId: maps.GetValueAsString(options.ProviderApplyConfig, "region_id"), + DnsPropagationTimeout: options.DnsPropagationTimeout, + DnsTTL: options.DnsTTL, + }) + return applicant, err + } + case domain.ApplyDNSProviderTypeNameDotCom: { access := domain.AccessConfigForNameDotCom{} diff --git a/internal/domain/access.go b/internal/domain/access.go index eaa3340e..ddd00b1c 100644 --- a/internal/domain/access.go +++ b/internal/domain/access.go @@ -115,12 +115,17 @@ type AccessConfigForHuaweiCloud struct { SecretAccessKey string `json:"secretAccessKey"` } -type AccessConfigForLocal struct{} +type AccessConfigForJDCloud struct { + AccessKeyId string `json:"accessKeyId"` + AccessKeySecret string `json:"accessKeySecret"` +} type AccessConfigForKubernetes struct { KubeConfig string `json:"kubeConfig,omitempty"` } +type AccessConfigForLocal struct{} + type AccessConfigForNameDotCom struct { Username string `json:"username"` ApiToken string `json:"apiToken"` diff --git a/internal/domain/provider.go b/internal/domain/provider.go index 08527fdd..5f36117e 100644 --- a/internal/domain/provider.go +++ b/internal/domain/provider.go @@ -34,7 +34,7 @@ const ( AccessProviderTypeGoDaddy = AccessProviderType("godaddy") AccessProviderTypeGoEdge = AccessProviderType("goedge") // GoEdge(预留) AccessProviderTypeHuaweiCloud = AccessProviderType("huaweicloud") - AccessProviderTypeJDCloud = AccessProviderType("jdcloud") // 京东云(预留) + AccessProviderTypeJDCloud = AccessProviderType("jdcloud") AccessProviderTypeKubernetes = AccessProviderType("k8s") AccessProviderTypeLocal = AccessProviderType("local") AccessProviderTypeNameDotCom = AccessProviderType("namedotcom") @@ -68,6 +68,7 @@ const ( ApplyDNSProviderTypeAliyunDNS = ApplyDNSProviderType("aliyun-dns") ApplyDNSProviderTypeAWS = ApplyDNSProviderType("aws") // 兼容旧值,等同于 [ApplyDNSProviderTypeAWSRoute53] ApplyDNSProviderTypeAWSRoute53 = ApplyDNSProviderType("aws-route53") + ApplyDNSProviderTypeAzure = ApplyDNSProviderType("azure") // 兼容旧值,等同于 [ApplyDNSProviderTypeAzure] ApplyDNSProviderTypeAzureDNS = ApplyDNSProviderType("azure-dns") ApplyDNSProviderTypeBaiduCloud = ApplyDNSProviderType("baiducloud") // 兼容旧值,等同于 [ApplyDNSProviderTypeBaiduCloudDNS] ApplyDNSProviderTypeBaiduCloudDNS = ApplyDNSProviderType("baiducloud-dns") @@ -78,6 +79,8 @@ const ( ApplyDNSProviderTypeGoDaddy = ApplyDNSProviderType("godaddy") ApplyDNSProviderTypeHuaweiCloud = ApplyDNSProviderType("huaweicloud") // 兼容旧值,等同于 [ApplyDNSProviderTypeHuaweiCloudDNS] ApplyDNSProviderTypeHuaweiCloudDNS = ApplyDNSProviderType("huaweicloud-dns") + ApplyDNSProviderTypeJDCloud = ApplyDNSProviderType("jdcloud") // 兼容旧值,等同于 [ApplyDNSProviderTypeJDCloudDNS] + ApplyDNSProviderTypeJDCloudDNS = ApplyDNSProviderType("jdcloud-dns") ApplyDNSProviderTypeNameDotCom = ApplyDNSProviderType("namedotcom") ApplyDNSProviderTypeNameSilo = ApplyDNSProviderType("namesilo") ApplyDNSProviderTypeNS1 = ApplyDNSProviderType("ns1") diff --git a/internal/pkg/core/applicant/acme-dns-01/lego-providers/baiducloud/internal/lego.go b/internal/pkg/core/applicant/acme-dns-01/lego-providers/baiducloud/internal/lego.go index fd138c6d..558ad5eb 100644 --- a/internal/pkg/core/applicant/acme-dns-01/lego-providers/baiducloud/internal/lego.go +++ b/internal/pkg/core/applicant/acme-dns-01/lego-providers/baiducloud/internal/lego.go @@ -184,10 +184,10 @@ func (d *DNSProvider) removeDNSRecord(domain, subDomain, value string) error { if record == nil { return nil + } else { + err = d.client.DeleteRecord(domain, record.Id, d.generateClientToken()) + return err } - - err = d.client.DeleteRecord(domain, record.Id, d.generateClientToken()) - return err } func (d *DNSProvider) generateClientToken() string { diff --git a/internal/pkg/core/applicant/acme-dns-01/lego-providers/jdcloud/internal/lego.go b/internal/pkg/core/applicant/acme-dns-01/lego-providers/jdcloud/internal/lego.go new file mode 100644 index 00000000..a85fa79c --- /dev/null +++ b/internal/pkg/core/applicant/acme-dns-01/lego-providers/jdcloud/internal/lego.go @@ -0,0 +1,229 @@ +package lego_jdcloud + +import ( + "errors" + "fmt" + "time" + + "github.com/go-acme/lego/v4/challenge" + "github.com/go-acme/lego/v4/challenge/dns01" + "github.com/go-acme/lego/v4/platform/config/env" + jdCore "github.com/jdcloud-api/jdcloud-sdk-go/core" + jdDnsApi "github.com/jdcloud-api/jdcloud-sdk-go/services/domainservice/apis" + jdDnsClient "github.com/jdcloud-api/jdcloud-sdk-go/services/domainservice/client" + jdDnsModel "github.com/jdcloud-api/jdcloud-sdk-go/services/domainservice/models" +) + +const ( + envNamespace = "JDCLOUD_" + + EnvAccessKeyID = envNamespace + "ACCESS_KEY_ID" + EnvAccessKeySecret = envNamespace + "ACCESS_KEY_SECRET" + EnvRegionId = envNamespace + "REGION_ID" + + EnvTTL = envNamespace + "TTL" + EnvPropagationTimeout = envNamespace + "PROPAGATION_TIMEOUT" + EnvPollingInterval = envNamespace + "POLLING_INTERVAL" + EnvHTTPTimeout = envNamespace + "HTTP_TIMEOUT" +) + +var _ challenge.ProviderTimeout = (*DNSProvider)(nil) + +type Config struct { + AccessKeyID string + AccessKeySecret string + RegionId string + + PropagationTimeout time.Duration + PollingInterval time.Duration + TTL int32 + HTTPTimeout time.Duration +} + +type DNSProvider struct { + client *jdDnsClient.DomainserviceClient + config *Config +} + +func NewDefaultConfig() *Config { + return &Config{ + TTL: int32(env.GetOrDefaultInt(EnvTTL, 300)), + PropagationTimeout: env.GetOrDefaultSecond(EnvPropagationTimeout, 2*time.Minute), + PollingInterval: env.GetOrDefaultSecond(EnvPollingInterval, dns01.DefaultPollingInterval), + HTTPTimeout: env.GetOrDefaultSecond(EnvHTTPTimeout, 30*time.Second), + } +} + +func NewDNSProvider() (*DNSProvider, error) { + values, err := env.Get(EnvAccessKeyID, EnvAccessKeySecret) + if err != nil { + return nil, fmt.Errorf("jdcloud: %w", err) + } + + config := NewDefaultConfig() + config.AccessKeyID = values[EnvAccessKeyID] + config.AccessKeySecret = values[EnvAccessKeySecret] + config.RegionId = values[EnvRegionId] + + return NewDNSProviderConfig(config) +} + +func NewDNSProviderConfig(config *Config) (*DNSProvider, error) { + if config == nil { + return nil, errors.New("jdcloud: the configuration of the DNS provider is nil") + } + + clientCredentials := jdCore.NewCredentials(config.AccessKeyID, config.AccessKeySecret) + clientConfig := jdCore.NewConfig() + clientConfig.SetTimeout(config.HTTPTimeout) + client := jdDnsClient.NewDomainserviceClient(clientCredentials) + client.SetConfig(clientConfig) + + return &DNSProvider{ + client: client, + config: config, + }, nil +} + +func (d *DNSProvider) Present(domain, token, keyAuth string) error { + info := dns01.GetChallengeInfo(domain, keyAuth) + + zoneName, err := dns01.FindZoneByFqdn(info.EffectiveFQDN) + if err != nil { + return fmt.Errorf("jdcloud: %w", err) + } + + subDomain, err := dns01.ExtractSubDomain(info.EffectiveFQDN, zoneName) + if err != nil { + return fmt.Errorf("jdcloud: %w", err) + } + + if err := d.addOrUpdateDNSRecord(domain, subDomain, info.Value); err != nil { + return fmt.Errorf("jdcloud: %w", err) + } + + return nil +} + +func (d *DNSProvider) CleanUp(domain, token, keyAuth string) error { + fqdn, value := dns01.GetRecord(domain, keyAuth) + subDomain := dns01.UnFqdn(fqdn) + + if err := d.removeDNSRecord(domain, subDomain, value); err != nil { + return fmt.Errorf("jdcloud: %w", err) + } + + return nil +} + +func (d *DNSProvider) Timeout() (timeout, interval time.Duration) { + return d.config.PropagationTimeout, d.config.PollingInterval +} + +func (d *DNSProvider) getDNSZone(domain string) (*jdDnsModel.DomainInfo, error) { + pageNumber := 1 + pageSize := 100 + for { + request := &jdDnsApi.DescribeDomainsRequest{} + request.RegionId = d.config.RegionId + request.DomainName = &domain + request.PageNumber = pageNumber + request.PageSize = pageSize + + response, err := d.client.DescribeDomains(request) + if err != nil { + return nil, err + } + + for _, item := range response.Result.DataList { + if item.DomainName == domain { + return &item, nil + } + } + + if len(response.Result.DataList) < pageSize { + break + } + + pageNumber++ + } + + return nil, fmt.Errorf("jdcloud: zone %s not found", domain) +} + +func (d *DNSProvider) getDNSZoneAndRecord(domain, subDomain string) (*jdDnsModel.DomainInfo, *jdDnsModel.RRInfo, error) { + zone, err := d.getDNSZone(domain) + if err != nil { + return nil, nil, err + } + + pageNumber := 1 + pageSize := 100 + for { + request := jdDnsApi.NewDescribeResourceRecordRequest(d.config.RegionId, fmt.Sprintf("%d", &zone.Id)) + request.Search = &subDomain + request.PageNumber = &pageNumber + request.PageSize = &pageSize + + response, err := d.client.DescribeResourceRecord(request) + if err != nil { + return zone, nil, err + } + + for _, record := range response.Result.DataList { + if record.Type == "TXT" && record.HostRecord == subDomain { + return zone, &record, nil + } + } + + if len(response.Result.DataList) < pageSize { + break + } + + pageNumber++ + } + + return nil, nil, nil +} + +func (d *DNSProvider) addOrUpdateDNSRecord(domain, subDomain, value string) error { + zone, record, err := d.getDNSZoneAndRecord(domain, subDomain) + if err != nil { + return err + } + + if record == nil { + request := jdDnsApi.NewCreateResourceRecordRequest(d.config.RegionId, fmt.Sprintf("%d", &zone.Id), &jdDnsModel.AddRR{ + Type: "TXT", + HostRecord: subDomain, + HostValue: value, + Ttl: int(d.config.TTL), + }) + _, err := d.client.CreateResourceRecord(request) + return err + } else { + request := jdDnsApi.NewModifyResourceRecordRequest(d.config.RegionId, fmt.Sprintf("%d", &zone.Id), fmt.Sprintf("%d", &record.Id), &jdDnsModel.UpdateRR{ + Type: "TXT", + HostRecord: subDomain, + HostValue: value, + Ttl: int(d.config.TTL), + }) + _, err := d.client.ModifyResourceRecord(request) + return err + } +} + +func (d *DNSProvider) removeDNSRecord(domain, subDomain, value string) error { + zone, record, err := d.getDNSZoneAndRecord(domain, subDomain) + if err != nil { + return err + } + + if record == nil { + return nil + } else { + req := jdDnsApi.NewDeleteResourceRecordRequest(d.config.RegionId, fmt.Sprintf("%d", &zone.Id), fmt.Sprintf("%d", &record.Id)) + _, err = d.client.DeleteResourceRecord(req) + return err + } +} diff --git a/internal/pkg/core/applicant/acme-dns-01/lego-providers/jdcloud/jdcloud.go b/internal/pkg/core/applicant/acme-dns-01/lego-providers/jdcloud/jdcloud.go new file mode 100644 index 00000000..5729d932 --- /dev/null +++ b/internal/pkg/core/applicant/acme-dns-01/lego-providers/jdcloud/jdcloud.go @@ -0,0 +1,47 @@ +package jdcloud + +import ( + "time" + + "github.com/go-acme/lego/v4/challenge" + + internal "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/jdcloud/internal" +) + +type ChallengeProviderConfig struct { + AccessKeyId string `json:"accessKeyId"` + AccessKeySecret string `json:"accessKeySecret"` + RegionId string `json:"regionId"` + DnsPropagationTimeout int32 `json:"dnsPropagationTimeout,omitempty"` + DnsTTL int32 `json:"dnsTTL,omitempty"` +} + +func NewChallengeProvider(config *ChallengeProviderConfig) (challenge.Provider, error) { + if config == nil { + panic("config is nil") + } + + regionId := config.RegionId + if regionId == "" { + // 京东云的 SDK 要求必须传一个区域,实际上 DNS-01 流程里用不到,但不传会报错 + regionId = "cn-north-1" + } + + providerConfig := internal.NewDefaultConfig() + providerConfig.AccessKeyID = config.AccessKeyId + providerConfig.AccessKeySecret = config.AccessKeySecret + providerConfig.RegionId = regionId + if config.DnsPropagationTimeout != 0 { + providerConfig.PropagationTimeout = time.Duration(config.DnsPropagationTimeout) * time.Second + } + if config.DnsTTL != 0 { + providerConfig.TTL = config.DnsTTL + } + + provider, err := internal.NewDNSProviderConfig(providerConfig) + if err != nil { + return nil, err + } + + return provider, nil +} diff --git a/ui/public/imgs/providers/jdcloud.svg b/ui/public/imgs/providers/jdcloud.svg new file mode 100644 index 00000000..720dbf4d --- /dev/null +++ b/ui/public/imgs/providers/jdcloud.svg @@ -0,0 +1 @@ + diff --git a/ui/src/components/Version.tsx b/ui/src/components/Version.tsx index fcdf1170..3d736271 100644 --- a/ui/src/components/Version.tsx +++ b/ui/src/components/Version.tsx @@ -1,4 +1,4 @@ -import { memo, useEffect, useState } from "react"; +import { memo } from "react"; import { useTranslation } from "react-i18next"; import { ReadOutlined as ReadOutlinedIcon } from "@ant-design/icons"; import { Badge, Divider, Space, Typography } from "antd"; diff --git a/ui/src/components/access/AccessForm.tsx b/ui/src/components/access/AccessForm.tsx index f552e594..44d6ae0c 100644 --- a/ui/src/components/access/AccessForm.tsx +++ b/ui/src/components/access/AccessForm.tsx @@ -27,6 +27,7 @@ import AccessFormGcoreConfig from "./AccessFormGcoreConfig"; import AccessFormGnameConfig from "./AccessFormGnameConfig"; import AccessFormGoDaddyConfig from "./AccessFormGoDaddyConfig"; import AccessFormHuaweiCloudConfig from "./AccessFormHuaweiCloudConfig"; +import AccessFormJDCloudConfig from "./AccessFormJDCloudConfig"; import AccessFormKubernetesConfig from "./AccessFormKubernetesConfig"; import AccessFormLocalConfig from "./AccessFormLocalConfig"; import AccessFormNameDotComConfig from "./AccessFormNameDotComConfig"; @@ -131,6 +132,8 @@ const AccessForm = forwardRef(({ className, return ; case ACCESS_PROVIDERS.HUAWEICLOUD: return ; + case ACCESS_PROVIDERS.JDCLOUD: + return ; case ACCESS_PROVIDERS.KUBERNETES: return ; case ACCESS_PROVIDERS.LOCAL: diff --git a/ui/src/components/access/AccessFormJDCloudConfig.tsx b/ui/src/components/access/AccessFormJDCloudConfig.tsx new file mode 100644 index 00000000..7ab6b167 --- /dev/null +++ b/ui/src/components/access/AccessFormJDCloudConfig.tsx @@ -0,0 +1,76 @@ +import { useTranslation } from "react-i18next"; +import { Form, type FormInstance, Input } from "antd"; +import { createSchemaFieldRule } from "antd-zod"; +import { z } from "zod"; + +import { type AccessConfigForJDCloud } from "@/domain/access"; + +type AccessFormJDCloudConfigFieldValues = Nullish; + +export type AccessFormJDCloudConfigProps = { + form: FormInstance; + formName: string; + disabled?: boolean; + initialValues?: AccessFormJDCloudConfigFieldValues; + onValuesChange?: (values: AccessFormJDCloudConfigFieldValues) => void; +}; + +const initFormModel = (): AccessFormJDCloudConfigFieldValues => { + return { + accessKeyId: "", + accessKeySecret: "", + }; +}; + +const AccessFormJDCloudConfig = ({ form: formInst, formName, disabled, initialValues, onValuesChange: onValuesChange }: AccessFormJDCloudConfigProps) => { + const { t } = useTranslation(); + + const formSchema = z.object({ + accessKeyId: z + .string() + .min(1, t("access.form.jdcloud_access_key_id.placeholder")) + .max(64, t("common.errmsg.string_max", { max: 64 })) + .trim(), + accessKeySecret: z + .string() + .min(1, t("access.form.jdcloud_access_key_secret.placeholder")) + .max(64, t("common.errmsg.string_max", { max: 64 })) + .trim(), + }); + const formRule = createSchemaFieldRule(formSchema); + + const handleFormChange = (_: unknown, values: z.infer) => { + onValuesChange?.(values); + }; + + return ( +
+ } + > + + + + } + > + + +
+ ); +}; + +export default AccessFormJDCloudConfig; diff --git a/ui/src/components/workflow/node/ApplyNodeConfigForm.tsx b/ui/src/components/workflow/node/ApplyNodeConfigForm.tsx index 7b43cad2..c714e197 100644 --- a/ui/src/components/workflow/node/ApplyNodeConfigForm.tsx +++ b/ui/src/components/workflow/node/ApplyNodeConfigForm.tsx @@ -35,6 +35,7 @@ import { validDomainName, validIPv4Address, validIPv6Address } from "@/utils/val import ApplyNodeConfigFormAWSRoute53Config from "./ApplyNodeConfigFormAWSRoute53Config"; import ApplyNodeConfigFormHuaweiCloudDNSConfig from "./ApplyNodeConfigFormHuaweiCloudDNSConfig"; +import ApplyNodeConfigFormJDCloudDNSConfig from "./ApplyNodeConfigFormJDCloudDNSConfig"; type ApplyNodeConfigFormFieldValues = Partial; @@ -145,6 +146,9 @@ const ApplyNodeConfigForm = forwardRef; + case APPLY_DNS_PROVIDERS.JDCLOUD: + case APPLY_DNS_PROVIDERS.JDCLOUD_DNS: + return ; } }, [disabled, initialValues?.providerConfig, fieldProvider, nestedFormInst, nestedFormName]); diff --git a/ui/src/components/workflow/node/ApplyNodeConfigFormJDCloudDNSConfig.tsx b/ui/src/components/workflow/node/ApplyNodeConfigFormJDCloudDNSConfig.tsx new file mode 100644 index 00000000..f9533972 --- /dev/null +++ b/ui/src/components/workflow/node/ApplyNodeConfigFormJDCloudDNSConfig.tsx @@ -0,0 +1,61 @@ +import { useTranslation } from "react-i18next"; +import { Form, type FormInstance, Input } from "antd"; +import { createSchemaFieldRule } from "antd-zod"; +import { z } from "zod"; + +type ApplyNodeConfigFormJDCloudDNSConfigFieldValues = Nullish<{ + regionId: string; +}>; + +export type ApplyNodeConfigFormJDCloudDNSConfigProps = { + form: FormInstance; + formName: string; + disabled?: boolean; + initialValues?: ApplyNodeConfigFormJDCloudDNSConfigFieldValues; + onValuesChange?: (values: ApplyNodeConfigFormJDCloudDNSConfigFieldValues) => void; +}; + +const initFormModel = (): ApplyNodeConfigFormJDCloudDNSConfigFieldValues => { + return { + regionId: "cn-north-1", + }; +}; + +const ApplyNodeConfigFormJDCloudDNSConfig = ({ + form: formInst, + formName, + disabled, + initialValues, + onValuesChange, +}: ApplyNodeConfigFormJDCloudDNSConfigProps) => { + const { t } = useTranslation(); + + const formSchema = z.object({ + regionId: z + .string({ message: t("workflow_node.apply.form.jdcloud_dns_region_id.placeholder") }) + .nonempty(t("workflow_node.apply.form.jdcloud_dns_region_id.placeholder")) + .trim(), + }); + const formRule = createSchemaFieldRule(formSchema); + + const handleFormChange = (_: unknown, values: z.infer) => { + onValuesChange?.(values); + }; + + return ( +
+ + + +
+ ); +}; + +export default ApplyNodeConfigFormJDCloudDNSConfig; diff --git a/ui/src/domain/access.ts b/ui/src/domain/access.ts index 0ece4826..c91e647f 100644 --- a/ui/src/domain/access.ts +++ b/ui/src/domain/access.ts @@ -24,6 +24,7 @@ export interface AccessModel extends BaseModel { | AccessConfigForGname | AccessConfigForGoDaddy | AccessConfigForHuaweiCloud + | AccessConfigForJDCloud | AccessConfigForKubernetes | AccessConfigForLocal | AccessConfigForNameDotCom @@ -133,6 +134,11 @@ export type AccessConfigForHuaweiCloud = { secretAccessKey: string; }; +export type AccessConfigForJDCloud = { + accessKeyId: string; + accessKeySecret: string; +}; + export type AccessConfigForKubernetes = { kubeConfig?: string; }; diff --git a/ui/src/domain/provider.ts b/ui/src/domain/provider.ts index b5bcaca7..39a5424e 100644 --- a/ui/src/domain/provider.ts +++ b/ui/src/domain/provider.ts @@ -22,6 +22,7 @@ export const ACCESS_PROVIDERS = Object.freeze({ GODADDY: "godaddy", EDGIO: "edgio", HUAWEICLOUD: "huaweicloud", + JDCLOUD: "jdcloud", KUBERNETES: "k8s", LOCAL: "local", NAMEDOTCOM: "namedotcom", @@ -70,6 +71,7 @@ export const accessProvidersMap: Maphttps://www.alibabacloud.com/help/en/acr/create-and-obtain-an-accesskey-pair", - "access.form.aliyun_access_key_secret.label": "Aliyun AccessKey Secret", - "access.form.aliyun_access_key_secret.placeholder": "Please enter Aliyun AccessKey Secret", + "access.form.aliyun_access_key_secret.label": "Aliyun AccessKeySecret", + "access.form.aliyun_access_key_secret.placeholder": "Please enter Aliyun AccessKeySecret", "access.form.aliyun_access_key_secret.tooltip": "For more information, see https://www.alibabacloud.com/help/en/acr/create-and-obtain-an-accesskey-pair", "access.form.aws_access_key_id.label": "AWS AccessKeyId", "access.form.aws_access_key_id.placeholder": "Please enter AWS AccessKeyId", @@ -133,6 +133,12 @@ "access.form.huaweicloud_secret_access_key.label": "Huawei Cloud SecretAccessKey", "access.form.huaweicloud_secret_access_key.placeholder": "Please enter Huawei Cloud SecretAccessKey", "access.form.huaweicloud_secret_access_key.tooltip": "For more information, see https://support.huaweicloud.com/intl/en-us/usermanual-ca/ca_01_0003.html", + "access.form.jdcloud_access_key_id.label": "JD Cloud AccessKeyId", + "access.form.jdcloud_access_key_id.placeholder": "Please enter JD Cloud AccessKeyId", + "access.form.jdcloud_access_key_id.tooltip": "For more information, see https://docs.jdcloud.com/en/account-management/accesskey-management", + "access.form.jdcloud_access_key_secret.label": "JD Cloud AccessKeySecret", + "access.form.jdcloud_access_key_secret.placeholder": "Please enter JD Cloud AccessKeySecret", + "access.form.jdcloud_access_key_secret.tooltip": "For more information, see https://docs.jdcloud.com/en/account-management/accesskey-management", "access.form.k8s_kubeconfig.label": "KubeConfig", "access.form.k8s_kubeconfig.placeholder": "Please enter KubeConfig file", "access.form.k8s_kubeconfig.upload": "Choose File ...", diff --git a/ui/src/i18n/locales/en/nls.common.json b/ui/src/i18n/locales/en/nls.common.json index d5e5508b..eb288ce5 100644 --- a/ui/src/i18n/locales/en/nls.common.json +++ b/ui/src/i18n/locales/en/nls.common.json @@ -42,7 +42,7 @@ "provider.aliyun.cdn": "Alibaba Cloud - CDN (Content Delivery Network)", "provider.aliyun.clb": "Alibaba Cloud - CLB (Classic Load Balancer)", "provider.aliyun.dcdn": "Alibaba Cloud - DCDN (Dynamic Route for Content Delivery Network)", - "provider.aliyun.dns": "Alibaba Cloud - DNS (Domain Name Service)", + "provider.aliyun.dns": "Alibaba Cloud - DNS", "provider.aliyun.esa": "Alibaba Cloud - ESA (Edge Security Acceleration)", "provider.aliyun.live": "Alibaba Cloud - ApsaraVideo Live", "provider.aliyun.nlb": "Alibaba Cloud - NLB (Network Load Balancer)", @@ -69,8 +69,10 @@ "provider.godaddy": "GoDaddy", "provider.huaweicloud": "Huawei Cloud", "provider.huaweicloud.cdn": "Huawei Cloud - CDN (Content Delivery Network)", - "provider.huaweicloud.dns": "Huawei Cloud - DNS (Domain Name Service)", + "provider.huaweicloud.dns": "Huawei Cloud - DNS", "provider.huaweicloud.elb": "Huawei Cloud - ELB (Elastic Load Balance)", + "provider.jdcloud": "JD Cloud", + "provider.jdcloud.dns": "JD Cloud - DNS", "provider.kubernetes": "Kubernetes", "provider.kubernetes.secret": "Kubernetes - Secret", "provider.local": "Local deployment", @@ -88,7 +90,7 @@ "provider.tencentcloud.clb": "Tencent Cloud - CLB (Cloud Load Balancer)", "provider.tencentcloud.cos": "Tencent Cloud - COS (Cloud Object Storage)", "provider.tencentcloud.css": "Tencent Cloud - CSS (Cloud Streaming Service)", - "provider.tencentcloud.dns": "Tencent Cloud - DNS (Domain Name Service)", + "provider.tencentcloud.dns": "Tencent Cloud - DNS", "provider.tencentcloud.ecdn": "Tencent Cloud - ECDN (Enterprise Content Delivery Network)", "provider.tencentcloud.eo": "Tencent Cloud - EdgeOne", "provider.tencentcloud.ssl_deploy": "Tencent Cloud - via SSL Certificate Service Deployment Job", @@ -99,7 +101,7 @@ "provider.volcengine.cdn": "Volcengine - CDN (Content Delivery Network)", "provider.volcengine.clb": "Volcengine - CLB (Cloud Load Balancer)", "provider.volcengine.dcdn": "Volcengine - DCDN (Dynamic Content Delivery Network)", - "provider.volcengine.dns": "Volcengine - DNS (Domain Name Service)", + "provider.volcengine.dns": "Volcengine - DNS", "provider.volcengine.live": "Volcengine - Live", "provider.volcengine.tos": "Volcengine - TOS (Tinder Object Storage)", "provider.webhook": "Webhook", diff --git a/ui/src/i18n/locales/en/nls.workflow.nodes.json b/ui/src/i18n/locales/en/nls.workflow.nodes.json index 6bf12328..d0ae4173 100644 --- a/ui/src/i18n/locales/en/nls.workflow.nodes.json +++ b/ui/src/i18n/locales/en/nls.workflow.nodes.json @@ -46,6 +46,8 @@ "workflow_node.apply.form.huaweicloud_dns_region.label": "Huawei Cloud DNS region", "workflow_node.apply.form.huaweicloud_dns_region.placeholder": "Please enter Huawei Cloud DNS region (e.g. cn-north-1)", "workflow_node.apply.form.huaweicloud_dns_region.tooltip": "For more information, see https://console-intl.huaweicloud.com/apiexplorer/#/endpoint", + "workflow_node.apply.form.jdcloud_dns_region_id.label": "JD Cloud DNS region ID", + "workflow_node.apply.form.jdcloud_dns_region_id.placeholder": "Please enter JD Cloud DNS region ID (e.g. cn-north-1)", "workflow_node.apply.form.advanced_config.label": "Advanced settings", "workflow_node.apply.form.key_algorithm.label": "Certificate key algorithm", "workflow_node.apply.form.key_algorithm.placeholder": "Please select certificate key algorithm", diff --git a/ui/src/i18n/locales/zh/nls.access.json b/ui/src/i18n/locales/zh/nls.access.json index ee7fea3a..c35d65d3 100644 --- a/ui/src/i18n/locales/zh/nls.access.json +++ b/ui/src/i18n/locales/zh/nls.access.json @@ -38,8 +38,8 @@ "access.form.aliyun_access_key_id.label": "阿里云 AccessKeyId", "access.form.aliyun_access_key_id.placeholder": "请输入阿里云 AccessKeyId", "access.form.aliyun_access_key_id.tooltip": "这是什么?请参阅 https://help.aliyun.com/zh/ram/user-guide/create-an-accesskey-pair", - "access.form.aliyun_access_key_secret.label": "阿里云 AccessKey Secret", - "access.form.aliyun_access_key_secret.placeholder": "请输入阿里云 AccessKey Secret", + "access.form.aliyun_access_key_secret.label": "阿里云 AccessKeySecret", + "access.form.aliyun_access_key_secret.placeholder": "请输入阿里云 AccessKeySecret", "access.form.aliyun_access_key_secret.tooltip": "这是什么?请参阅 https://help.aliyun.com/zh/ram/user-guide/create-an-accesskey-pair", "access.form.aws_access_key_id.label": "AWS AccessKeyId", "access.form.aws_access_key_id.placeholder": "请输入 AWS AccessKeyId", @@ -133,6 +133,12 @@ "access.form.huaweicloud_secret_access_key.label": "华为云 SecretAccessKey", "access.form.huaweicloud_secret_access_key.placeholder": "请输入华为云 SecretAccessKey", "access.form.huaweicloud_secret_access_key.tooltip": "这是什么?请参阅 https://support.huaweicloud.com/usermanual-ca/ca_01_0003.html", + "access.form.jdcloud_access_key_id.label": "京东云 AccessKeyId", + "access.form.jdcloud_access_key_id.placeholder": "请输入京东云 AccessKeyId", + "access.form.jdcloud_access_key_id.tooltip": "这是什么?请参阅 https://docs.jdcloud.com/cn/account-management/accesskey-management", + "access.form.jdcloud_access_key_secret.label": "京东云 AccessKeySecret", + "access.form.jdcloud_access_key_secret.placeholder": "请输入京东云 AccessKeySecret", + "access.form.jdcloud_access_key_secret.tooltip": "这是什么?请参阅 https://docs.jdcloud.com/cn/account-management/accesskey-management", "access.form.k8s_kubeconfig.label": "KubeConfig", "access.form.k8s_kubeconfig.placeholder": "请选择 KubeConfig 文件", "access.form.k8s_kubeconfig.upload": "选择文件", diff --git a/ui/src/i18n/locales/zh/nls.provider.json b/ui/src/i18n/locales/zh/nls.provider.json index e120b343..958f54a3 100644 --- a/ui/src/i18n/locales/zh/nls.provider.json +++ b/ui/src/i18n/locales/zh/nls.provider.json @@ -53,6 +53,8 @@ "provider.huaweicloud.dns": "华为云 - 云解析 DNS", "provider.huaweicloud.elb": "华为云 - 弹性负载均衡 ELB", "provider.huaweicloud.waf": "华为云 - Web 应用防火墙 WAF", + "provider.jdcloud": "京东云", + "provider.jdcloud.dns": "京东云 - 云解析 DNS", "provider.kubernetes": "Kubernetes", "provider.kubernetes.secret": "Kubernetes - Secret", "provider.local": "本地部署", diff --git a/ui/src/i18n/locales/zh/nls.workflow.nodes.json b/ui/src/i18n/locales/zh/nls.workflow.nodes.json index d5ac3aca..5860ba08 100644 --- a/ui/src/i18n/locales/zh/nls.workflow.nodes.json +++ b/ui/src/i18n/locales/zh/nls.workflow.nodes.json @@ -46,6 +46,8 @@ "workflow_node.apply.form.huaweicloud_dns_region.label": "华为云 DNS 服务区域", "workflow_node.apply.form.huaweicloud_dns_region.placeholder": "请输入华为云 DNS 服务区域(例如:cn-north-1)", "workflow_node.apply.form.huaweicloud_dns_region.tooltip": "这是什么?请参阅 https://console.huaweicloud.com/apiexplorer/#/endpoint", + "workflow_node.apply.form.jdcloud_dns_region_id.label": "京东云 DNS 服务地域 ID", + "workflow_node.apply.form.jdcloud_dns_region_id.placeholder": "请输入京东云 DNS 服务地域 ID(例如:cn-north-1)", "workflow_node.apply.form.advanced_config.label": "高级设置", "workflow_node.apply.form.key_algorithm.label": "数字证书算法", "workflow_node.apply.form.key_algorithm.placeholder": "请选择数字证书算法", From 0e1f720419e43298970a5f2cbe2f8461a3711b81 Mon Sep 17 00:00:00 2001 From: Fu Diwei Date: Thu, 20 Feb 2025 00:16:26 +0800 Subject: [PATCH 19/34] refactor: normalize providers constructors --- .../deployer/providers/aliyun-alb/aliyun_alb.go | 2 +- .../aliyun-cas-deploy/aliyun_cas_deploy.go | 2 +- .../deployer/providers/aliyun-clb/aliyun_clb.go | 2 +- .../deployer/providers/aliyun-esa/aliyun_esa.go | 2 +- .../deployer/providers/aliyun-nlb/aliyun_nlb.go | 2 +- .../deployer/providers/aliyun-waf/aliyun_waf.go | 2 +- .../providers/aws-cloudfront/aws_cloudfront.go | 2 +- .../providers/byteplus-cdn/byteplus_cdn.go | 2 +- .../providers/dogecloud-cdn/dogecloud_cdn.go | 2 +- .../deployer/providers/gcore-cdn/gcore_cdn.go | 2 +- .../providers/huaweicloud-cdn/huaweicloud_cdn.go | 2 +- .../providers/huaweicloud-elb/huaweicloud_elb.go | 2 +- .../providers/huaweicloud-waf/huaweicloud_waf.go | 2 +- .../deployer/providers/qiniu-cdn/qiniu_cdn.go | 2 +- .../deployer/providers/qiniu-pili/qiniu_pili.go | 2 +- .../tencentcloud-cdn/tencentcloud_cdn.go | 2 +- .../tencentcloud-clb/tencentcloud_clb.go | 2 +- .../tencentcloud-cos/tencentcloud_cos.go | 2 +- .../tencentcloud-css/tencentcloud_css.go | 2 +- .../tencentcloud-ecdn/tencentcloud_ecdn.go | 2 +- .../providers/tencentcloud-eo/tencentcloud_eo.go | 2 +- .../tencentcloud_ssl_deploy.go | 2 +- .../tencentcloud-waf/tencentcloud_waf.go | 2 +- .../providers/ucloud-ucdn/ucloud_ucdn.go | 2 +- .../deployer/providers/ucloud-us3/ucloud_us3.go | 2 +- .../providers/volcengine-cdn/volcengine_cdn.go | 2 +- .../providers/volcengine-clb/volcengine_clb.go | 2 +- .../providers/volcengine-dcdn/volcengine_dcdn.go | 2 +- .../volcengine-imagex/volcengine_imagex.go | 2 +- .../providers/volcengine-live/volcengine_live.go | 2 +- .../providers/volcengine-tos/volcengine_tos.go | 2 +- .../uploader/providers/aliyun-cas/aliyun_cas.go | 14 +++++++------- .../uploader/providers/aliyun-slb/aliyun_slb.go | 14 +++++++------- .../core/uploader/providers/aws-acm/aws_acm.go | 14 +++++++------- .../providers/byteplus-cdn/byteplus_cdn.go | 14 +++++++------- .../uploader/providers/dogecloud/dogecloud.go | 14 +++++++------- .../uploader/providers/gcore-cdn/gcore_cdn.go | 14 +++++++------- .../providers/huaweicloud-elb/huaweicloud_elb.go | 14 +++++++------- .../providers/huaweicloud-scm/huaweicloud_scm.go | 14 +++++++------- .../providers/huaweicloud-waf/huaweicloud_waf.go | 14 +++++++------- .../providers/qiniu-sslcert/qiniu_sslcert.go | 14 +++++++------- .../tencentcloud-ssl/tencentcloud_ssl.go | 14 +++++++------- .../providers/ucloud-ussl/ucloud_ussl.go | 16 ++++++++-------- .../providers/ucloud-ussl/ucloud_ussl_test.go | 2 +- .../providers/volcengine-cdn/volcengine_cdn.go | 14 +++++++------- .../volcengine_certcenter.go | 14 +++++++------- .../volcengine_certcenter_test.go | 2 +- .../providers/volcengine-live/volcengine_live.go | 14 +++++++------- 48 files changed, 139 insertions(+), 139 deletions(-) diff --git a/internal/pkg/core/deployer/providers/aliyun-alb/aliyun_alb.go b/internal/pkg/core/deployer/providers/aliyun-alb/aliyun_alb.go index dc2f1f3c..27261a63 100644 --- a/internal/pkg/core/deployer/providers/aliyun-alb/aliyun_alb.go +++ b/internal/pkg/core/deployer/providers/aliyun-alb/aliyun_alb.go @@ -442,7 +442,7 @@ func createSslUploader(accessKeyId, accessKeySecret, region string) (uploader.Up } } - uploader, err := uploadersp.New(&uploadersp.AliyunCASUploaderConfig{ + uploader, err := uploadersp.NewUploader(&uploadersp.UploaderConfig{ AccessKeyId: accessKeyId, AccessKeySecret: accessKeySecret, Region: casRegion, diff --git a/internal/pkg/core/deployer/providers/aliyun-cas-deploy/aliyun_cas_deploy.go b/internal/pkg/core/deployer/providers/aliyun-cas-deploy/aliyun_cas_deploy.go index 2f86adf0..1cc36c6f 100644 --- a/internal/pkg/core/deployer/providers/aliyun-cas-deploy/aliyun_cas_deploy.go +++ b/internal/pkg/core/deployer/providers/aliyun-cas-deploy/aliyun_cas_deploy.go @@ -175,7 +175,7 @@ func createSdkClient(accessKeyId, accessKeySecret, region string) (*aliyunCas.Cl } func createSslUploader(accessKeyId, accessKeySecret, region string) (uploader.Uploader, error) { - uploader, err := uploadersp.New(&uploadersp.AliyunCASUploaderConfig{ + uploader, err := uploadersp.NewUploader(&uploadersp.UploaderConfig{ AccessKeyId: accessKeyId, AccessKeySecret: accessKeySecret, Region: region, diff --git a/internal/pkg/core/deployer/providers/aliyun-clb/aliyun_clb.go b/internal/pkg/core/deployer/providers/aliyun-clb/aliyun_clb.go index 151276b7..e18dccc4 100644 --- a/internal/pkg/core/deployer/providers/aliyun-clb/aliyun_clb.go +++ b/internal/pkg/core/deployer/providers/aliyun-clb/aliyun_clb.go @@ -55,7 +55,7 @@ func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { return nil, xerrors.Wrap(err, "failed to create sdk client") } - uploader, err := uploadersp.New(&uploadersp.AliyunSLBUploaderConfig{ + uploader, err := uploadersp.NewUploader(&uploadersp.UploaderConfig{ AccessKeyId: config.AccessKeyId, AccessKeySecret: config.AccessKeySecret, Region: config.Region, diff --git a/internal/pkg/core/deployer/providers/aliyun-esa/aliyun_esa.go b/internal/pkg/core/deployer/providers/aliyun-esa/aliyun_esa.go index e7f977ce..1ccbdae5 100644 --- a/internal/pkg/core/deployer/providers/aliyun-esa/aliyun_esa.go +++ b/internal/pkg/core/deployer/providers/aliyun-esa/aliyun_esa.go @@ -126,7 +126,7 @@ func createSslUploader(accessKeyId, accessKeySecret, region string) (uploader.Up } } - uploader, err := uploadersp.New(&uploadersp.AliyunCASUploaderConfig{ + uploader, err := uploadersp.NewUploader(&uploadersp.UploaderConfig{ AccessKeyId: accessKeyId, AccessKeySecret: accessKeySecret, Region: casRegion, diff --git a/internal/pkg/core/deployer/providers/aliyun-nlb/aliyun_nlb.go b/internal/pkg/core/deployer/providers/aliyun-nlb/aliyun_nlb.go index fb9f2cb3..0f1f1bca 100644 --- a/internal/pkg/core/deployer/providers/aliyun-nlb/aliyun_nlb.go +++ b/internal/pkg/core/deployer/providers/aliyun-nlb/aliyun_nlb.go @@ -245,7 +245,7 @@ func createSslUploader(accessKeyId, accessKeySecret, region string) (uploader.Up } } - uploader, err := uploadersp.New(&uploadersp.AliyunCASUploaderConfig{ + uploader, err := uploadersp.NewUploader(&uploadersp.UploaderConfig{ AccessKeyId: accessKeyId, AccessKeySecret: accessKeySecret, Region: casRegion, diff --git a/internal/pkg/core/deployer/providers/aliyun-waf/aliyun_waf.go b/internal/pkg/core/deployer/providers/aliyun-waf/aliyun_waf.go index 55d03382..5747d23e 100644 --- a/internal/pkg/core/deployer/providers/aliyun-waf/aliyun_waf.go +++ b/internal/pkg/core/deployer/providers/aliyun-waf/aliyun_waf.go @@ -139,7 +139,7 @@ func createSslUploader(accessKeyId, accessKeySecret, region string) (uploader.Up } } - uploader, err := uploadersp.New(&uploadersp.AliyunCASUploaderConfig{ + uploader, err := uploadersp.NewUploader(&uploadersp.UploaderConfig{ AccessKeyId: accessKeyId, AccessKeySecret: accessKeySecret, Region: casRegion, diff --git a/internal/pkg/core/deployer/providers/aws-cloudfront/aws_cloudfront.go b/internal/pkg/core/deployer/providers/aws-cloudfront/aws_cloudfront.go index 9912e973..2e8e09ee 100644 --- a/internal/pkg/core/deployer/providers/aws-cloudfront/aws_cloudfront.go +++ b/internal/pkg/core/deployer/providers/aws-cloudfront/aws_cloudfront.go @@ -47,7 +47,7 @@ func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { return nil, xerrors.Wrap(err, "failed to create sdk client") } - uploader, err := uploadersp.New(&uploadersp.AWSCertificateManagerUploaderConfig{ + uploader, err := uploadersp.NewUploader(&uploadersp.UploaderConfig{ AccessKeyId: config.AccessKeyId, SecretAccessKey: config.SecretAccessKey, Region: config.Region, diff --git a/internal/pkg/core/deployer/providers/byteplus-cdn/byteplus_cdn.go b/internal/pkg/core/deployer/providers/byteplus-cdn/byteplus_cdn.go index c49e965e..909a2e7d 100644 --- a/internal/pkg/core/deployer/providers/byteplus-cdn/byteplus_cdn.go +++ b/internal/pkg/core/deployer/providers/byteplus-cdn/byteplus_cdn.go @@ -42,7 +42,7 @@ func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { client.Client.SetAccessKey(config.AccessKey) client.Client.SetSecretKey(config.SecretKey) - uploader, err := uploadersp.New(&uploadersp.ByteplusCDNUploaderConfig{ + uploader, err := uploadersp.NewUploader(&uploadersp.UploaderConfig{ AccessKey: config.AccessKey, SecretKey: config.SecretKey, }) diff --git a/internal/pkg/core/deployer/providers/dogecloud-cdn/dogecloud_cdn.go b/internal/pkg/core/deployer/providers/dogecloud-cdn/dogecloud_cdn.go index 8bc2278c..325a5319 100644 --- a/internal/pkg/core/deployer/providers/dogecloud-cdn/dogecloud_cdn.go +++ b/internal/pkg/core/deployer/providers/dogecloud-cdn/dogecloud_cdn.go @@ -38,7 +38,7 @@ func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { client := dogesdk.NewClient(config.AccessKey, config.SecretKey) - uploader, err := uploadersp.New(&uploadersp.DogeCloudUploaderConfig{ + uploader, err := uploadersp.NewUploader(&uploadersp.UploaderConfig{ AccessKey: config.AccessKey, SecretKey: config.SecretKey, }) diff --git a/internal/pkg/core/deployer/providers/gcore-cdn/gcore_cdn.go b/internal/pkg/core/deployer/providers/gcore-cdn/gcore_cdn.go index c2d8a6bc..e1598a5d 100644 --- a/internal/pkg/core/deployer/providers/gcore-cdn/gcore_cdn.go +++ b/internal/pkg/core/deployer/providers/gcore-cdn/gcore_cdn.go @@ -42,7 +42,7 @@ func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { return nil, xerrors.Wrap(err, "failed to create sdk client") } - uploader, err := uploadersp.New(&uploadersp.GcoreCDNUploaderConfig{ + uploader, err := uploadersp.NewUploader(&uploadersp.UploaderConfig{ ApiToken: config.ApiToken, }) if err != nil { diff --git a/internal/pkg/core/deployer/providers/huaweicloud-cdn/huaweicloud_cdn.go b/internal/pkg/core/deployer/providers/huaweicloud-cdn/huaweicloud_cdn.go index cba85ad8..4a40fbc1 100644 --- a/internal/pkg/core/deployer/providers/huaweicloud-cdn/huaweicloud_cdn.go +++ b/internal/pkg/core/deployer/providers/huaweicloud-cdn/huaweicloud_cdn.go @@ -50,7 +50,7 @@ func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { return nil, xerrors.Wrap(err, "failed to create sdk client") } - uploader, err := uploadersp.New(&uploadersp.HuaweiCloudSCMUploaderConfig{ + uploader, err := uploadersp.NewUploader(&uploadersp.UploaderConfig{ AccessKeyId: config.AccessKeyId, SecretAccessKey: config.SecretAccessKey, }) diff --git a/internal/pkg/core/deployer/providers/huaweicloud-elb/huaweicloud_elb.go b/internal/pkg/core/deployer/providers/huaweicloud-elb/huaweicloud_elb.go index 6348f9bc..17bc178b 100644 --- a/internal/pkg/core/deployer/providers/huaweicloud-elb/huaweicloud_elb.go +++ b/internal/pkg/core/deployer/providers/huaweicloud-elb/huaweicloud_elb.go @@ -62,7 +62,7 @@ func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { return nil, xerrors.Wrap(err, "failed to create sdk client") } - uploader, err := uploadersp.New(&uploadersp.HuaweiCloudELBUploaderConfig{ + uploader, err := uploadersp.NewUploader(&uploadersp.UploaderConfig{ AccessKeyId: config.AccessKeyId, SecretAccessKey: config.SecretAccessKey, Region: config.Region, diff --git a/internal/pkg/core/deployer/providers/huaweicloud-waf/huaweicloud_waf.go b/internal/pkg/core/deployer/providers/huaweicloud-waf/huaweicloud_waf.go index 3af42d28..2342edfa 100644 --- a/internal/pkg/core/deployer/providers/huaweicloud-waf/huaweicloud_waf.go +++ b/internal/pkg/core/deployer/providers/huaweicloud-waf/huaweicloud_waf.go @@ -59,7 +59,7 @@ func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { return nil, xerrors.Wrap(err, "failed to create sdk client") } - uploader, err := uploadersp.New(&uploadersp.HuaweiCloudWAFUploaderConfig{ + uploader, err := uploadersp.NewUploader(&uploadersp.UploaderConfig{ AccessKeyId: config.AccessKeyId, SecretAccessKey: config.SecretAccessKey, Region: config.Region, diff --git a/internal/pkg/core/deployer/providers/qiniu-cdn/qiniu_cdn.go b/internal/pkg/core/deployer/providers/qiniu-cdn/qiniu_cdn.go index d0341acb..cdb62b8c 100644 --- a/internal/pkg/core/deployer/providers/qiniu-cdn/qiniu_cdn.go +++ b/internal/pkg/core/deployer/providers/qiniu-cdn/qiniu_cdn.go @@ -39,7 +39,7 @@ func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { client := qiniusdk.NewClient(auth.New(config.AccessKey, config.SecretKey)) - uploader, err := uploadersp.New(&uploadersp.QiniuSSLCertUploaderConfig{ + uploader, err := uploadersp.NewUploader(&uploadersp.UploaderConfig{ AccessKey: config.AccessKey, SecretKey: config.SecretKey, }) diff --git a/internal/pkg/core/deployer/providers/qiniu-pili/qiniu_pili.go b/internal/pkg/core/deployer/providers/qiniu-pili/qiniu_pili.go index 8b7601b6..b9121694 100644 --- a/internal/pkg/core/deployer/providers/qiniu-pili/qiniu_pili.go +++ b/internal/pkg/core/deployer/providers/qiniu-pili/qiniu_pili.go @@ -39,7 +39,7 @@ func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { manager := pili.NewManager(pili.ManagerConfig{AccessKey: config.AccessKey, SecretKey: config.SecretKey}) - uploader, err := uploadersp.New(&uploadersp.QiniuSSLCertUploaderConfig{ + uploader, err := uploadersp.NewUploader(&uploadersp.UploaderConfig{ AccessKey: config.AccessKey, SecretKey: config.SecretKey, }) diff --git a/internal/pkg/core/deployer/providers/tencentcloud-cdn/tencentcloud_cdn.go b/internal/pkg/core/deployer/providers/tencentcloud-cdn/tencentcloud_cdn.go index 42fac9db..1784354d 100644 --- a/internal/pkg/core/deployer/providers/tencentcloud-cdn/tencentcloud_cdn.go +++ b/internal/pkg/core/deployer/providers/tencentcloud-cdn/tencentcloud_cdn.go @@ -50,7 +50,7 @@ func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { return nil, xerrors.Wrap(err, "failed to create sdk clients") } - uploader, err := uploadersp.New(&uploadersp.TencentCloudSSLUploaderConfig{ + uploader, err := uploadersp.NewUploader(&uploadersp.UploaderConfig{ SecretId: config.SecretId, SecretKey: config.SecretKey, }) diff --git a/internal/pkg/core/deployer/providers/tencentcloud-clb/tencentcloud_clb.go b/internal/pkg/core/deployer/providers/tencentcloud-clb/tencentcloud_clb.go index 196cbeb7..acaf84b2 100644 --- a/internal/pkg/core/deployer/providers/tencentcloud-clb/tencentcloud_clb.go +++ b/internal/pkg/core/deployer/providers/tencentcloud-clb/tencentcloud_clb.go @@ -61,7 +61,7 @@ func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { return nil, xerrors.Wrap(err, "failed to create sdk clients") } - uploader, err := uploadersp.New(&uploadersp.TencentCloudSSLUploaderConfig{ + uploader, err := uploadersp.NewUploader(&uploadersp.UploaderConfig{ SecretId: config.SecretId, SecretKey: config.SecretKey, }) diff --git a/internal/pkg/core/deployer/providers/tencentcloud-cos/tencentcloud_cos.go b/internal/pkg/core/deployer/providers/tencentcloud-cos/tencentcloud_cos.go index 7f696305..d3b3f881 100644 --- a/internal/pkg/core/deployer/providers/tencentcloud-cos/tencentcloud_cos.go +++ b/internal/pkg/core/deployer/providers/tencentcloud-cos/tencentcloud_cos.go @@ -48,7 +48,7 @@ func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { return nil, xerrors.Wrap(err, "failed to create sdk clients") } - uploader, err := uploadersp.New(&uploadersp.TencentCloudSSLUploaderConfig{ + uploader, err := uploadersp.NewUploader(&uploadersp.UploaderConfig{ SecretId: config.SecretId, SecretKey: config.SecretKey, }) diff --git a/internal/pkg/core/deployer/providers/tencentcloud-css/tencentcloud_css.go b/internal/pkg/core/deployer/providers/tencentcloud-css/tencentcloud_css.go index 1696e00b..ad5dbed5 100644 --- a/internal/pkg/core/deployer/providers/tencentcloud-css/tencentcloud_css.go +++ b/internal/pkg/core/deployer/providers/tencentcloud-css/tencentcloud_css.go @@ -42,7 +42,7 @@ func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { return nil, xerrors.Wrap(err, "failed to create sdk client") } - uploader, err := uploadersp.New(&uploadersp.TencentCloudSSLUploaderConfig{ + uploader, err := uploadersp.NewUploader(&uploadersp.UploaderConfig{ SecretId: config.SecretId, SecretKey: config.SecretKey, }) diff --git a/internal/pkg/core/deployer/providers/tencentcloud-ecdn/tencentcloud_ecdn.go b/internal/pkg/core/deployer/providers/tencentcloud-ecdn/tencentcloud_ecdn.go index 22b83d8b..e9438898 100644 --- a/internal/pkg/core/deployer/providers/tencentcloud-ecdn/tencentcloud_ecdn.go +++ b/internal/pkg/core/deployer/providers/tencentcloud-ecdn/tencentcloud_ecdn.go @@ -49,7 +49,7 @@ func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { return nil, xerrors.Wrap(err, "failed to create sdk clients") } - uploader, err := uploadersp.New(&uploadersp.TencentCloudSSLUploaderConfig{ + uploader, err := uploadersp.NewUploader(&uploadersp.UploaderConfig{ SecretId: config.SecretId, SecretKey: config.SecretKey, }) diff --git a/internal/pkg/core/deployer/providers/tencentcloud-eo/tencentcloud_eo.go b/internal/pkg/core/deployer/providers/tencentcloud-eo/tencentcloud_eo.go index 0ce55840..99669038 100644 --- a/internal/pkg/core/deployer/providers/tencentcloud-eo/tencentcloud_eo.go +++ b/internal/pkg/core/deployer/providers/tencentcloud-eo/tencentcloud_eo.go @@ -51,7 +51,7 @@ func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { return nil, xerrors.Wrap(err, "failed to create sdk clients") } - uploader, err := uploadersp.New(&uploadersp.TencentCloudSSLUploaderConfig{ + uploader, err := uploadersp.NewUploader(&uploadersp.UploaderConfig{ SecretId: config.SecretId, SecretKey: config.SecretKey, }) diff --git a/internal/pkg/core/deployer/providers/tencentcloud-ssl-deploy/tencentcloud_ssl_deploy.go b/internal/pkg/core/deployer/providers/tencentcloud-ssl-deploy/tencentcloud_ssl_deploy.go index 527bfa51..f943ad6e 100644 --- a/internal/pkg/core/deployer/providers/tencentcloud-ssl-deploy/tencentcloud_ssl_deploy.go +++ b/internal/pkg/core/deployer/providers/tencentcloud-ssl-deploy/tencentcloud_ssl_deploy.go @@ -49,7 +49,7 @@ func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { return nil, xerrors.Wrap(err, "failed to create sdk client") } - uploader, err := uploadersp.New(&uploadersp.TencentCloudSSLUploaderConfig{ + uploader, err := uploadersp.NewUploader(&uploadersp.UploaderConfig{ SecretId: config.SecretId, SecretKey: config.SecretKey, }) diff --git a/internal/pkg/core/deployer/providers/tencentcloud-waf/tencentcloud_waf.go b/internal/pkg/core/deployer/providers/tencentcloud-waf/tencentcloud_waf.go index a51335c8..7919516c 100644 --- a/internal/pkg/core/deployer/providers/tencentcloud-waf/tencentcloud_waf.go +++ b/internal/pkg/core/deployer/providers/tencentcloud-waf/tencentcloud_waf.go @@ -49,7 +49,7 @@ func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { return nil, xerrors.Wrap(err, "failed to create sdk clients") } - uploader, err := uploadersp.New(&uploadersp.TencentCloudSSLUploaderConfig{ + uploader, err := uploadersp.NewUploader(&uploadersp.UploaderConfig{ SecretId: config.SecretId, SecretKey: config.SecretKey, }) diff --git a/internal/pkg/core/deployer/providers/ucloud-ucdn/ucloud_ucdn.go b/internal/pkg/core/deployer/providers/ucloud-ucdn/ucloud_ucdn.go index 47acc5a0..8c19621b 100644 --- a/internal/pkg/core/deployer/providers/ucloud-ucdn/ucloud_ucdn.go +++ b/internal/pkg/core/deployer/providers/ucloud-ucdn/ucloud_ucdn.go @@ -46,7 +46,7 @@ func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { return nil, xerrors.Wrap(err, "failed to create sdk client") } - uploader, err := uploadersp.New(&uploadersp.UCloudUSSLUploaderConfig{ + uploader, err := uploadersp.NewUploader(&uploadersp.UploaderConfig{ PrivateKey: config.PrivateKey, PublicKey: config.PublicKey, ProjectId: config.ProjectId, diff --git a/internal/pkg/core/deployer/providers/ucloud-us3/ucloud_us3.go b/internal/pkg/core/deployer/providers/ucloud-us3/ucloud_us3.go index f648c896..592a1cf6 100644 --- a/internal/pkg/core/deployer/providers/ucloud-us3/ucloud_us3.go +++ b/internal/pkg/core/deployer/providers/ucloud-us3/ucloud_us3.go @@ -48,7 +48,7 @@ func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { return nil, xerrors.Wrap(err, "failed to create sdk client") } - uploader, err := uploadersp.New(&uploadersp.UCloudUSSLUploaderConfig{ + uploader, err := uploadersp.NewUploader(&uploadersp.UploaderConfig{ PrivateKey: config.PrivateKey, PublicKey: config.PublicKey, ProjectId: config.ProjectId, diff --git a/internal/pkg/core/deployer/providers/volcengine-cdn/volcengine_cdn.go b/internal/pkg/core/deployer/providers/volcengine-cdn/volcengine_cdn.go index b1852e6c..229c3c01 100644 --- a/internal/pkg/core/deployer/providers/volcengine-cdn/volcengine_cdn.go +++ b/internal/pkg/core/deployer/providers/volcengine-cdn/volcengine_cdn.go @@ -42,7 +42,7 @@ func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { client.Client.SetAccessKey(config.AccessKeyId) client.Client.SetSecretKey(config.AccessKeySecret) - uploader, err := uploadersp.New(&uploadersp.VolcEngineCDNUploaderConfig{ + uploader, err := uploadersp.NewUploader(&uploadersp.UploaderConfig{ AccessKeyId: config.AccessKeyId, AccessKeySecret: config.AccessKeySecret, }) diff --git a/internal/pkg/core/deployer/providers/volcengine-clb/volcengine_clb.go b/internal/pkg/core/deployer/providers/volcengine-clb/volcengine_clb.go index 51b56a5f..73372781 100644 --- a/internal/pkg/core/deployer/providers/volcengine-clb/volcengine_clb.go +++ b/internal/pkg/core/deployer/providers/volcengine-clb/volcengine_clb.go @@ -49,7 +49,7 @@ func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { return nil, xerrors.Wrap(err, "failed to create sdk client") } - uploader, err := uploadersp.New(&uploadersp.VolcEngineCertCenterUploaderConfig{ + uploader, err := uploadersp.NewUploader(&uploadersp.UploaderConfig{ AccessKeyId: config.AccessKeyId, AccessKeySecret: config.AccessKeySecret, Region: config.Region, diff --git a/internal/pkg/core/deployer/providers/volcengine-dcdn/volcengine_dcdn.go b/internal/pkg/core/deployer/providers/volcengine-dcdn/volcengine_dcdn.go index 7c775efe..835eae4b 100644 --- a/internal/pkg/core/deployer/providers/volcengine-dcdn/volcengine_dcdn.go +++ b/internal/pkg/core/deployer/providers/volcengine-dcdn/volcengine_dcdn.go @@ -45,7 +45,7 @@ func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { return nil, xerrors.Wrap(err, "failed to create sdk client") } - uploader, err := uploadersp.New(&uploadersp.VolcEngineCertCenterUploaderConfig{ + uploader, err := uploadersp.NewUploader(&uploadersp.UploaderConfig{ AccessKeyId: config.AccessKeyId, AccessKeySecret: config.AccessKeySecret, Region: config.Region, diff --git a/internal/pkg/core/deployer/providers/volcengine-imagex/volcengine_imagex.go b/internal/pkg/core/deployer/providers/volcengine-imagex/volcengine_imagex.go index 0e27dc27..57d133ec 100644 --- a/internal/pkg/core/deployer/providers/volcengine-imagex/volcengine_imagex.go +++ b/internal/pkg/core/deployer/providers/volcengine-imagex/volcengine_imagex.go @@ -46,7 +46,7 @@ func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { return nil, xerrors.Wrap(err, "failed to create sdk client") } - uploader, err := uploadersp.New(&uploadersp.VolcEngineCertCenterUploaderConfig{ + uploader, err := uploadersp.NewUploader(&uploadersp.UploaderConfig{ AccessKeyId: config.AccessKeyId, AccessKeySecret: config.AccessKeySecret, Region: config.Region, diff --git a/internal/pkg/core/deployer/providers/volcengine-live/volcengine_live.go b/internal/pkg/core/deployer/providers/volcengine-live/volcengine_live.go index 019af9ff..240e5c9c 100644 --- a/internal/pkg/core/deployer/providers/volcengine-live/volcengine_live.go +++ b/internal/pkg/core/deployer/providers/volcengine-live/volcengine_live.go @@ -43,7 +43,7 @@ func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { client.SetAccessKey(config.AccessKeyId) client.SetSecretKey(config.AccessKeySecret) - uploader, err := uploadersp.New(&uploadersp.VolcEngineLiveUploaderConfig{ + uploader, err := uploadersp.NewUploader(&uploadersp.UploaderConfig{ AccessKeyId: config.AccessKeyId, AccessKeySecret: config.AccessKeySecret, }) diff --git a/internal/pkg/core/deployer/providers/volcengine-tos/volcengine_tos.go b/internal/pkg/core/deployer/providers/volcengine-tos/volcengine_tos.go index f1c6ab08..142a8b9f 100644 --- a/internal/pkg/core/deployer/providers/volcengine-tos/volcengine_tos.go +++ b/internal/pkg/core/deployer/providers/volcengine-tos/volcengine_tos.go @@ -46,7 +46,7 @@ func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { return nil, xerrors.Wrap(err, "failed to create sdk client") } - uploader, err := uploadersp.New(&uploadersp.VolcEngineCertCenterUploaderConfig{ + uploader, err := uploadersp.NewUploader(&uploadersp.UploaderConfig{ AccessKeyId: config.AccessKeyId, AccessKeySecret: config.AccessKeySecret, Region: config.Region, diff --git a/internal/pkg/core/uploader/providers/aliyun-cas/aliyun_cas.go b/internal/pkg/core/uploader/providers/aliyun-cas/aliyun_cas.go index 881dc57b..202339c4 100644 --- a/internal/pkg/core/uploader/providers/aliyun-cas/aliyun_cas.go +++ b/internal/pkg/core/uploader/providers/aliyun-cas/aliyun_cas.go @@ -15,7 +15,7 @@ import ( "github.com/usual2970/certimate/internal/pkg/utils/certs" ) -type AliyunCASUploaderConfig struct { +type UploaderConfig struct { // 阿里云 AccessKeyId。 AccessKeyId string `json:"accessKeyId"` // 阿里云 AccessKeySecret。 @@ -24,14 +24,14 @@ type AliyunCASUploaderConfig struct { Region string `json:"region"` } -type AliyunCASUploader struct { - config *AliyunCASUploaderConfig +type UploaderProvider struct { + config *UploaderConfig sdkClient *aliyunCas.Client } -var _ uploader.Uploader = (*AliyunCASUploader)(nil) +var _ uploader.Uploader = (*UploaderProvider)(nil) -func New(config *AliyunCASUploaderConfig) (*AliyunCASUploader, error) { +func NewUploader(config *UploaderConfig) (*UploaderProvider, error) { if config == nil { panic("config is nil") } @@ -45,13 +45,13 @@ func New(config *AliyunCASUploaderConfig) (*AliyunCASUploader, error) { return nil, xerrors.Wrap(err, "failed to create sdk client") } - return &AliyunCASUploader{ + return &UploaderProvider{ config: config, sdkClient: client, }, nil } -func (u *AliyunCASUploader) Upload(ctx context.Context, certPem string, privkeyPem string) (res *uploader.UploadResult, err error) { +func (u *UploaderProvider) Upload(ctx context.Context, certPem string, privkeyPem string) (res *uploader.UploadResult, err error) { // 解析证书内容 certX509, err := certs.ParseCertificateFromPEM(certPem) if err != nil { diff --git a/internal/pkg/core/uploader/providers/aliyun-slb/aliyun_slb.go b/internal/pkg/core/uploader/providers/aliyun-slb/aliyun_slb.go index 9bd6d930..c53eced2 100644 --- a/internal/pkg/core/uploader/providers/aliyun-slb/aliyun_slb.go +++ b/internal/pkg/core/uploader/providers/aliyun-slb/aliyun_slb.go @@ -18,7 +18,7 @@ import ( "github.com/usual2970/certimate/internal/pkg/utils/certs" ) -type AliyunSLBUploaderConfig struct { +type UploaderConfig struct { // 阿里云 AccessKeyId。 AccessKeyId string `json:"accessKeyId"` // 阿里云 AccessKeySecret。 @@ -27,14 +27,14 @@ type AliyunSLBUploaderConfig struct { Region string `json:"region"` } -type AliyunSLBUploader struct { - config *AliyunSLBUploaderConfig +type UploaderProvider struct { + config *UploaderConfig sdkClient *aliyunSlb.Client } -var _ uploader.Uploader = (*AliyunSLBUploader)(nil) +var _ uploader.Uploader = (*UploaderProvider)(nil) -func New(config *AliyunSLBUploaderConfig) (*AliyunSLBUploader, error) { +func NewUploader(config *UploaderConfig) (*UploaderProvider, error) { if config == nil { panic("config is nil") } @@ -48,13 +48,13 @@ func New(config *AliyunSLBUploaderConfig) (*AliyunSLBUploader, error) { return nil, xerrors.Wrap(err, "failed to create sdk client") } - return &AliyunSLBUploader{ + return &UploaderProvider{ config: config, sdkClient: client, }, nil } -func (u *AliyunSLBUploader) Upload(ctx context.Context, certPem string, privkeyPem string) (res *uploader.UploadResult, err error) { +func (u *UploaderProvider) Upload(ctx context.Context, certPem string, privkeyPem string) (res *uploader.UploadResult, err error) { // 解析证书内容 certX509, err := certs.ParseCertificateFromPEM(certPem) if err != nil { diff --git a/internal/pkg/core/uploader/providers/aws-acm/aws_acm.go b/internal/pkg/core/uploader/providers/aws-acm/aws_acm.go index 836bacfc..18ffd3aa 100644 --- a/internal/pkg/core/uploader/providers/aws-acm/aws_acm.go +++ b/internal/pkg/core/uploader/providers/aws-acm/aws_acm.go @@ -15,7 +15,7 @@ import ( "github.com/usual2970/certimate/internal/pkg/utils/certs" ) -type AWSCertificateManagerUploaderConfig struct { +type UploaderConfig struct { // AWS AccessKeyId。 AccessKeyId string `json:"accessKeyId"` // AWS SecretAccessKey。 @@ -24,14 +24,14 @@ type AWSCertificateManagerUploaderConfig struct { Region string `json:"region"` } -type AWSCertificateManagerUploader struct { - config *AWSCertificateManagerUploaderConfig +type UploaderProvider struct { + config *UploaderConfig sdkClient *awsAcm.Client } -var _ uploader.Uploader = (*AWSCertificateManagerUploader)(nil) +var _ uploader.Uploader = (*UploaderProvider)(nil) -func New(config *AWSCertificateManagerUploaderConfig) (*AWSCertificateManagerUploader, error) { +func NewUploader(config *UploaderConfig) (*UploaderProvider, error) { if config == nil { panic("config is nil") } @@ -41,13 +41,13 @@ func New(config *AWSCertificateManagerUploaderConfig) (*AWSCertificateManagerUpl return nil, xerrors.Wrap(err, "failed to create sdk client") } - return &AWSCertificateManagerUploader{ + return &UploaderProvider{ config: config, sdkClient: client, }, nil } -func (u *AWSCertificateManagerUploader) Upload(ctx context.Context, certPem string, privkeyPem string) (res *uploader.UploadResult, err error) { +func (u *UploaderProvider) Upload(ctx context.Context, certPem string, privkeyPem string) (res *uploader.UploadResult, err error) { // 解析证书内容 certX509, err := certs.ParseCertificateFromPEM(certPem) if err != nil { diff --git a/internal/pkg/core/uploader/providers/byteplus-cdn/byteplus_cdn.go b/internal/pkg/core/uploader/providers/byteplus-cdn/byteplus_cdn.go index bed962e2..04116e31 100644 --- a/internal/pkg/core/uploader/providers/byteplus-cdn/byteplus_cdn.go +++ b/internal/pkg/core/uploader/providers/byteplus-cdn/byteplus_cdn.go @@ -16,21 +16,21 @@ import ( "github.com/usual2970/certimate/internal/pkg/utils/certs" ) -type ByteplusCDNUploaderConfig struct { +type UploaderConfig struct { // BytePlus AccessKey。 AccessKey string `json:"accessKey"` // BytePlus SecretKey。 SecretKey string `json:"secretKey"` } -type ByteplusCDNUploader struct { - config *ByteplusCDNUploaderConfig +type UploaderProvider struct { + config *UploaderConfig sdkClient *bpCdn.CDN } -var _ uploader.Uploader = (*ByteplusCDNUploader)(nil) +var _ uploader.Uploader = (*UploaderProvider)(nil) -func New(config *ByteplusCDNUploaderConfig) (*ByteplusCDNUploader, error) { +func NewUploader(config *UploaderConfig) (*UploaderProvider, error) { if config == nil { panic("config is nil") } @@ -39,13 +39,13 @@ func New(config *ByteplusCDNUploaderConfig) (*ByteplusCDNUploader, error) { client.Client.SetAccessKey(config.AccessKey) client.Client.SetSecretKey(config.SecretKey) - return &ByteplusCDNUploader{ + return &UploaderProvider{ config: config, sdkClient: client, }, nil } -func (u *ByteplusCDNUploader) Upload(ctx context.Context, certPem string, privkeyPem string) (res *uploader.UploadResult, err error) { +func (u *UploaderProvider) Upload(ctx context.Context, certPem string, privkeyPem string) (res *uploader.UploadResult, err error) { // 解析证书内容 certX509, err := certs.ParseCertificateFromPEM(certPem) if err != nil { diff --git a/internal/pkg/core/uploader/providers/dogecloud/dogecloud.go b/internal/pkg/core/uploader/providers/dogecloud/dogecloud.go index c941a5a9..82856b6e 100644 --- a/internal/pkg/core/uploader/providers/dogecloud/dogecloud.go +++ b/internal/pkg/core/uploader/providers/dogecloud/dogecloud.go @@ -11,21 +11,21 @@ import ( doge "github.com/usual2970/certimate/internal/pkg/vendors/dogecloud-sdk" ) -type DogeCloudUploaderConfig struct { +type UploaderConfig struct { // 多吉云 AccessKey。 AccessKey string `json:"accessKey"` // 多吉云 SecretKey。 SecretKey string `json:"secretKey"` } -type DogeCloudUploader struct { - config *DogeCloudUploaderConfig +type UploaderProvider struct { + config *UploaderConfig sdkClient *doge.Client } -var _ uploader.Uploader = (*DogeCloudUploader)(nil) +var _ uploader.Uploader = (*UploaderProvider)(nil) -func New(config *DogeCloudUploaderConfig) (*DogeCloudUploader, error) { +func NewUploader(config *UploaderConfig) (*UploaderProvider, error) { if config == nil { panic("config is nil") } @@ -38,13 +38,13 @@ func New(config *DogeCloudUploaderConfig) (*DogeCloudUploader, error) { return nil, xerrors.Wrap(err, "failed to create sdk client") } - return &DogeCloudUploader{ + return &UploaderProvider{ config: config, sdkClient: client, }, nil } -func (u *DogeCloudUploader) Upload(ctx context.Context, certPem string, privkeyPem string) (res *uploader.UploadResult, err error) { +func (u *UploaderProvider) Upload(ctx context.Context, certPem string, privkeyPem string) (res *uploader.UploadResult, err error) { // 生成新证书名(需符合多吉云命名规则) var certId, certName string certName = fmt.Sprintf("certimate-%d", time.Now().UnixMilli()) diff --git a/internal/pkg/core/uploader/providers/gcore-cdn/gcore_cdn.go b/internal/pkg/core/uploader/providers/gcore-cdn/gcore_cdn.go index 933f61b4..b990c694 100644 --- a/internal/pkg/core/uploader/providers/gcore-cdn/gcore_cdn.go +++ b/internal/pkg/core/uploader/providers/gcore-cdn/gcore_cdn.go @@ -14,19 +14,19 @@ import ( gcoresdk "github.com/usual2970/certimate/internal/pkg/vendors/gcore-sdk/common" ) -type GcoreCDNUploaderConfig struct { +type UploaderConfig struct { // Gcore API Token。 ApiToken string `json:"apiToken"` } -type GcoreCDNUploader struct { - config *GcoreCDNUploaderConfig +type UploaderProvider struct { + config *UploaderConfig sdkClient *gsslcerts.Service } -var _ uploader.Uploader = (*GcoreCDNUploader)(nil) +var _ uploader.Uploader = (*UploaderProvider)(nil) -func New(config *GcoreCDNUploaderConfig) (*GcoreCDNUploader, error) { +func NewUploader(config *UploaderConfig) (*UploaderProvider, error) { if config == nil { panic("config is nil") } @@ -36,13 +36,13 @@ func New(config *GcoreCDNUploaderConfig) (*GcoreCDNUploader, error) { return nil, xerrors.Wrap(err, "failed to create sdk client") } - return &GcoreCDNUploader{ + return &UploaderProvider{ config: config, sdkClient: client, }, nil } -func (u *GcoreCDNUploader) Upload(ctx context.Context, certPem string, privkeyPem string) (res *uploader.UploadResult, err error) { +func (u *UploaderProvider) Upload(ctx context.Context, certPem string, privkeyPem string) (res *uploader.UploadResult, err error) { // 生成新证书名(需符合 Gcore 命名规则) var certId, certName string certName = fmt.Sprintf("certimate_%d", time.Now().UnixMilli()) diff --git a/internal/pkg/core/uploader/providers/huaweicloud-elb/huaweicloud_elb.go b/internal/pkg/core/uploader/providers/huaweicloud-elb/huaweicloud_elb.go index 321c488f..96a1ff7b 100644 --- a/internal/pkg/core/uploader/providers/huaweicloud-elb/huaweicloud_elb.go +++ b/internal/pkg/core/uploader/providers/huaweicloud-elb/huaweicloud_elb.go @@ -21,7 +21,7 @@ import ( hwsdk "github.com/usual2970/certimate/internal/pkg/vendors/huaweicloud-sdk" ) -type HuaweiCloudELBUploaderConfig struct { +type UploaderConfig struct { // 华为云 AccessKeyId。 AccessKeyId string `json:"accessKeyId"` // 华为云 SecretAccessKey。 @@ -30,14 +30,14 @@ type HuaweiCloudELBUploaderConfig struct { Region string `json:"region"` } -type HuaweiCloudELBUploader struct { - config *HuaweiCloudELBUploaderConfig +type UploaderProvider struct { + config *UploaderConfig sdkClient *hcElb.ElbClient } -var _ uploader.Uploader = (*HuaweiCloudELBUploader)(nil) +var _ uploader.Uploader = (*UploaderProvider)(nil) -func New(config *HuaweiCloudELBUploaderConfig) (*HuaweiCloudELBUploader, error) { +func NewUploader(config *UploaderConfig) (*UploaderProvider, error) { if config == nil { panic("config is nil") } @@ -51,13 +51,13 @@ func New(config *HuaweiCloudELBUploaderConfig) (*HuaweiCloudELBUploader, error) return nil, xerrors.Wrap(err, "failed to create sdk client") } - return &HuaweiCloudELBUploader{ + return &UploaderProvider{ config: config, sdkClient: client, }, nil } -func (u *HuaweiCloudELBUploader) Upload(ctx context.Context, certPem string, privkeyPem string) (res *uploader.UploadResult, err error) { +func (u *UploaderProvider) Upload(ctx context.Context, certPem string, privkeyPem string) (res *uploader.UploadResult, err error) { // 解析证书内容 certX509, err := certs.ParseCertificateFromPEM(certPem) if err != nil { diff --git a/internal/pkg/core/uploader/providers/huaweicloud-scm/huaweicloud_scm.go b/internal/pkg/core/uploader/providers/huaweicloud-scm/huaweicloud_scm.go index 53f723f4..9406c55d 100644 --- a/internal/pkg/core/uploader/providers/huaweicloud-scm/huaweicloud_scm.go +++ b/internal/pkg/core/uploader/providers/huaweicloud-scm/huaweicloud_scm.go @@ -16,7 +16,7 @@ import ( hwsdk "github.com/usual2970/certimate/internal/pkg/vendors/huaweicloud-sdk" ) -type HuaweiCloudSCMUploaderConfig struct { +type UploaderConfig struct { // 华为云 AccessKeyId。 AccessKeyId string `json:"accessKeyId"` // 华为云 SecretAccessKey。 @@ -25,14 +25,14 @@ type HuaweiCloudSCMUploaderConfig struct { Region string `json:"region"` } -type HuaweiCloudSCMUploader struct { - config *HuaweiCloudSCMUploaderConfig +type UploaderProvider struct { + config *UploaderConfig sdkClient *hcScm.ScmClient } -var _ uploader.Uploader = (*HuaweiCloudSCMUploader)(nil) +var _ uploader.Uploader = (*UploaderProvider)(nil) -func New(config *HuaweiCloudSCMUploaderConfig) (*HuaweiCloudSCMUploader, error) { +func NewUploader(config *UploaderConfig) (*UploaderProvider, error) { if config == nil { panic("config is nil") } @@ -46,13 +46,13 @@ func New(config *HuaweiCloudSCMUploaderConfig) (*HuaweiCloudSCMUploader, error) return nil, xerrors.Wrap(err, "failed to create sdk client") } - return &HuaweiCloudSCMUploader{ + return &UploaderProvider{ config: config, sdkClient: client, }, nil } -func (u *HuaweiCloudSCMUploader) Upload(ctx context.Context, certPem string, privkeyPem string) (res *uploader.UploadResult, err error) { +func (u *UploaderProvider) Upload(ctx context.Context, certPem string, privkeyPem string) (res *uploader.UploadResult, err error) { // 解析证书内容 certX509, err := certs.ParseCertificateFromPEM(certPem) if err != nil { diff --git a/internal/pkg/core/uploader/providers/huaweicloud-waf/huaweicloud_waf.go b/internal/pkg/core/uploader/providers/huaweicloud-waf/huaweicloud_waf.go index 3fb89bf3..19e7cea7 100644 --- a/internal/pkg/core/uploader/providers/huaweicloud-waf/huaweicloud_waf.go +++ b/internal/pkg/core/uploader/providers/huaweicloud-waf/huaweicloud_waf.go @@ -21,7 +21,7 @@ import ( hwsdk "github.com/usual2970/certimate/internal/pkg/vendors/huaweicloud-sdk" ) -type HuaweiCloudWAFUploaderConfig struct { +type UploaderConfig struct { // 华为云 AccessKeyId。 AccessKeyId string `json:"accessKeyId"` // 华为云 SecretAccessKey。 @@ -30,14 +30,14 @@ type HuaweiCloudWAFUploaderConfig struct { Region string `json:"region"` } -type HuaweiCloudWAFUploader struct { - config *HuaweiCloudWAFUploaderConfig +type UploaderProvider struct { + config *UploaderConfig sdkClient *hcWaf.WafClient } -var _ uploader.Uploader = (*HuaweiCloudWAFUploader)(nil) +var _ uploader.Uploader = (*UploaderProvider)(nil) -func New(config *HuaweiCloudWAFUploaderConfig) (*HuaweiCloudWAFUploader, error) { +func NewUploader(config *UploaderConfig) (*UploaderProvider, error) { if config == nil { panic("config is nil") } @@ -51,13 +51,13 @@ func New(config *HuaweiCloudWAFUploaderConfig) (*HuaweiCloudWAFUploader, error) return nil, xerrors.Wrap(err, "failed to create sdk client") } - return &HuaweiCloudWAFUploader{ + return &UploaderProvider{ config: config, sdkClient: client, }, nil } -func (u *HuaweiCloudWAFUploader) Upload(ctx context.Context, certPem string, privkeyPem string) (res *uploader.UploadResult, err error) { +func (u *UploaderProvider) Upload(ctx context.Context, certPem string, privkeyPem string) (res *uploader.UploadResult, err error) { // 解析证书内容 certX509, err := certs.ParseCertificateFromPEM(certPem) if err != nil { diff --git a/internal/pkg/core/uploader/providers/qiniu-sslcert/qiniu_sslcert.go b/internal/pkg/core/uploader/providers/qiniu-sslcert/qiniu_sslcert.go index 3e32b73d..05c57be8 100644 --- a/internal/pkg/core/uploader/providers/qiniu-sslcert/qiniu_sslcert.go +++ b/internal/pkg/core/uploader/providers/qiniu-sslcert/qiniu_sslcert.go @@ -13,21 +13,21 @@ import ( qiniuEx "github.com/usual2970/certimate/internal/pkg/vendors/qiniu-sdk" ) -type QiniuSSLCertUploaderConfig struct { +type UploaderConfig struct { // 七牛云 AccessKey。 AccessKey string `json:"accessKey"` // 七牛云 SecretKey。 SecretKey string `json:"secretKey"` } -type QiniuSSLCertUploader struct { - config *QiniuSSLCertUploaderConfig +type UploaderProvider struct { + config *UploaderConfig sdkClient *qiniuEx.Client } -var _ uploader.Uploader = (*QiniuSSLCertUploader)(nil) +var _ uploader.Uploader = (*UploaderProvider)(nil) -func New(config *QiniuSSLCertUploaderConfig) (*QiniuSSLCertUploader, error) { +func NewUploader(config *UploaderConfig) (*UploaderProvider, error) { if config == nil { panic("config is nil") } @@ -40,13 +40,13 @@ func New(config *QiniuSSLCertUploaderConfig) (*QiniuSSLCertUploader, error) { return nil, xerrors.Wrap(err, "failed to create sdk client") } - return &QiniuSSLCertUploader{ + return &UploaderProvider{ config: config, sdkClient: client, }, nil } -func (u *QiniuSSLCertUploader) Upload(ctx context.Context, certPem string, privkeyPem string) (res *uploader.UploadResult, err error) { +func (u *UploaderProvider) Upload(ctx context.Context, certPem string, privkeyPem string) (res *uploader.UploadResult, err error) { // 解析证书内容 certX509, err := certs.ParseCertificateFromPEM(certPem) if err != nil { diff --git a/internal/pkg/core/uploader/providers/tencentcloud-ssl/tencentcloud_ssl.go b/internal/pkg/core/uploader/providers/tencentcloud-ssl/tencentcloud_ssl.go index c802e77f..a76bf2a0 100644 --- a/internal/pkg/core/uploader/providers/tencentcloud-ssl/tencentcloud_ssl.go +++ b/internal/pkg/core/uploader/providers/tencentcloud-ssl/tencentcloud_ssl.go @@ -11,21 +11,21 @@ import ( "github.com/usual2970/certimate/internal/pkg/core/uploader" ) -type TencentCloudSSLUploaderConfig struct { +type UploaderConfig struct { // 腾讯云 SecretId。 SecretId string `json:"secretId"` // 腾讯云 SecretKey。 SecretKey string `json:"secretKey"` } -type TencentCloudSSLUploader struct { - config *TencentCloudSSLUploaderConfig +type UploaderProvider struct { + config *UploaderConfig sdkClient *tcSsl.Client } -var _ uploader.Uploader = (*TencentCloudSSLUploader)(nil) +var _ uploader.Uploader = (*UploaderProvider)(nil) -func New(config *TencentCloudSSLUploaderConfig) (*TencentCloudSSLUploader, error) { +func NewUploader(config *UploaderConfig) (*UploaderProvider, error) { if config == nil { panic("config is nil") } @@ -38,13 +38,13 @@ func New(config *TencentCloudSSLUploaderConfig) (*TencentCloudSSLUploader, error return nil, xerrors.Wrap(err, "failed to create sdk client") } - return &TencentCloudSSLUploader{ + return &UploaderProvider{ config: config, sdkClient: client, }, nil } -func (u *TencentCloudSSLUploader) Upload(ctx context.Context, certPem string, privkeyPem string) (res *uploader.UploadResult, err error) { +func (u *UploaderProvider) Upload(ctx context.Context, certPem string, privkeyPem string) (res *uploader.UploadResult, err error) { // 上传新证书 // REF: https://cloud.tencent.com/document/product/400/41665 uploadCertificateReq := tcSsl.NewUploadCertificateRequest() diff --git a/internal/pkg/core/uploader/providers/ucloud-ussl/ucloud_ussl.go b/internal/pkg/core/uploader/providers/ucloud-ussl/ucloud_ussl.go index 56a66472..aaa03999 100644 --- a/internal/pkg/core/uploader/providers/ucloud-ussl/ucloud_ussl.go +++ b/internal/pkg/core/uploader/providers/ucloud-ussl/ucloud_ussl.go @@ -20,7 +20,7 @@ import ( usdkSsl "github.com/usual2970/certimate/internal/pkg/vendors/ucloud-sdk/ussl" ) -type UCloudUSSLUploaderConfig struct { +type UploaderConfig struct { // 优刻得 API 私钥。 PrivateKey string `json:"privateKey"` // 优刻得 API 公钥。 @@ -29,14 +29,14 @@ type UCloudUSSLUploaderConfig struct { ProjectId string `json:"projectId,omitempty"` } -type UCloudUSSLUploader struct { - config *UCloudUSSLUploaderConfig +type UploaderProvider struct { + config *UploaderConfig sdkClient *usdkSsl.USSLClient } -var _ uploader.Uploader = (*UCloudUSSLUploader)(nil) +var _ uploader.Uploader = (*UploaderProvider)(nil) -func New(config *UCloudUSSLUploaderConfig) (*UCloudUSSLUploader, error) { +func NewUploader(config *UploaderConfig) (*UploaderProvider, error) { if config == nil { panic("config is nil") } @@ -46,13 +46,13 @@ func New(config *UCloudUSSLUploaderConfig) (*UCloudUSSLUploader, error) { return nil, xerrors.Wrap(err, "failed to create sdk client") } - return &UCloudUSSLUploader{ + return &UploaderProvider{ config: config, sdkClient: client, }, nil } -func (u *UCloudUSSLUploader) Upload(ctx context.Context, certPem string, privkeyPem string) (res *uploader.UploadResult, err error) { +func (u *UploaderProvider) Upload(ctx context.Context, certPem string, privkeyPem string) (res *uploader.UploadResult, err error) { // 生成新证书名(需符合优刻得命名规则) var certId, certName string certName = fmt.Sprintf("certimate-%d", time.Now().UnixMilli()) @@ -92,7 +92,7 @@ func (u *UCloudUSSLUploader) Upload(ctx context.Context, certPem string, privkey }, nil } -func (u *UCloudUSSLUploader) getExistCert(ctx context.Context, certPem string) (res *uploader.UploadResult, err error) { +func (u *UploaderProvider) getExistCert(ctx context.Context, certPem string) (res *uploader.UploadResult, err error) { // 解析证书内容 certX509, err := certs.ParseCertificateFromPEM(certPem) if err != nil { diff --git a/internal/pkg/core/uploader/providers/ucloud-ussl/ucloud_ussl_test.go b/internal/pkg/core/uploader/providers/ucloud-ussl/ucloud_ussl_test.go index c0a0f719..b6324fd5 100644 --- a/internal/pkg/core/uploader/providers/ucloud-ussl/ucloud_ussl_test.go +++ b/internal/pkg/core/uploader/providers/ucloud-ussl/ucloud_ussl_test.go @@ -49,7 +49,7 @@ func TestDeploy(t *testing.T) { fmt.Sprintf("PUBLICKEY: %v", fPublicKey), }, "\n")) - uploader, err := provider.New(&provider.UCloudUSSLUploaderConfig{ + uploader, err := provider.NewUploader(&provider.UploaderConfig{ PrivateKey: fPrivateKey, PublicKey: fPublicKey, }) diff --git a/internal/pkg/core/uploader/providers/volcengine-cdn/volcengine_cdn.go b/internal/pkg/core/uploader/providers/volcengine-cdn/volcengine_cdn.go index 691effe6..9b5c9b56 100644 --- a/internal/pkg/core/uploader/providers/volcengine-cdn/volcengine_cdn.go +++ b/internal/pkg/core/uploader/providers/volcengine-cdn/volcengine_cdn.go @@ -17,21 +17,21 @@ import ( "github.com/usual2970/certimate/internal/pkg/utils/certs" ) -type VolcEngineCDNUploaderConfig struct { +type UploaderConfig struct { // 火山引擎 AccessKeyId。 AccessKeyId string `json:"accessKeyId"` // 火山引擎 AccessKeySecret。 AccessKeySecret string `json:"accessKeySecret"` } -type VolcEngineCDNUploader struct { - config *VolcEngineCDNUploaderConfig +type UploaderProvider struct { + config *UploaderConfig sdkClient *veCdn.CDN } -var _ uploader.Uploader = (*VolcEngineCDNUploader)(nil) +var _ uploader.Uploader = (*UploaderProvider)(nil) -func New(config *VolcEngineCDNUploaderConfig) (*VolcEngineCDNUploader, error) { +func NewUploader(config *UploaderConfig) (*UploaderProvider, error) { if config == nil { panic("config is nil") } @@ -40,13 +40,13 @@ func New(config *VolcEngineCDNUploaderConfig) (*VolcEngineCDNUploader, error) { client.Client.SetAccessKey(config.AccessKeyId) client.Client.SetSecretKey(config.AccessKeySecret) - return &VolcEngineCDNUploader{ + return &UploaderProvider{ config: config, sdkClient: client, }, nil } -func (u *VolcEngineCDNUploader) Upload(ctx context.Context, certPem string, privkeyPem string) (res *uploader.UploadResult, err error) { +func (u *UploaderProvider) Upload(ctx context.Context, certPem string, privkeyPem string) (res *uploader.UploadResult, err error) { // 解析证书内容 certX509, err := certs.ParseCertificateFromPEM(certPem) if err != nil { diff --git a/internal/pkg/core/uploader/providers/volcengine-certcenter/volcengine_certcenter.go b/internal/pkg/core/uploader/providers/volcengine-certcenter/volcengine_certcenter.go index 05776396..1ff133e5 100644 --- a/internal/pkg/core/uploader/providers/volcengine-certcenter/volcengine_certcenter.go +++ b/internal/pkg/core/uploader/providers/volcengine-certcenter/volcengine_certcenter.go @@ -11,7 +11,7 @@ import ( vesdkCc "github.com/usual2970/certimate/internal/pkg/vendors/volcengine-sdk/certcenter" ) -type VolcEngineCertCenterUploaderConfig struct { +type UploaderConfig struct { // 火山引擎 AccessKeyId。 AccessKeyId string `json:"accessKeyId"` // 火山引擎 AccessKeySecret。 @@ -20,14 +20,14 @@ type VolcEngineCertCenterUploaderConfig struct { Region string `json:"region"` } -type VolcEngineCertCenterUploader struct { - config *VolcEngineCertCenterUploaderConfig +type UploaderProvider struct { + config *UploaderConfig sdkClient *vesdkCc.CertCenter } -var _ uploader.Uploader = (*VolcEngineCertCenterUploader)(nil) +var _ uploader.Uploader = (*UploaderProvider)(nil) -func New(config *VolcEngineCertCenterUploaderConfig) (*VolcEngineCertCenterUploader, error) { +func NewUploader(config *UploaderConfig) (*UploaderProvider, error) { if config == nil { panic("config is nil") } @@ -37,13 +37,13 @@ func New(config *VolcEngineCertCenterUploaderConfig) (*VolcEngineCertCenterUploa return nil, xerrors.Wrap(err, "failed to create sdk client") } - return &VolcEngineCertCenterUploader{ + return &UploaderProvider{ config: config, sdkClient: client, }, nil } -func (u *VolcEngineCertCenterUploader) Upload(ctx context.Context, certPem string, privkeyPem string) (res *uploader.UploadResult, err error) { +func (u *UploaderProvider) Upload(ctx context.Context, certPem string, privkeyPem string) (res *uploader.UploadResult, err error) { // 上传证书 // REF: https://www.volcengine.com/docs/6638/1365580 importCertificateReq := &vesdkCc.ImportCertificateInput{ diff --git a/internal/pkg/core/uploader/providers/volcengine-certcenter/volcengine_certcenter_test.go b/internal/pkg/core/uploader/providers/volcengine-certcenter/volcengine_certcenter_test.go index 5f15c44f..5c312707 100644 --- a/internal/pkg/core/uploader/providers/volcengine-certcenter/volcengine_certcenter_test.go +++ b/internal/pkg/core/uploader/providers/volcengine-certcenter/volcengine_certcenter_test.go @@ -49,7 +49,7 @@ func TestDeploy(t *testing.T) { fmt.Sprintf("ACCESSKEYSECRET: %v", fAccessKeySecret), }, "\n")) - uploader, err := provider.New(&provider.VolcEngineCertCenterUploaderConfig{ + uploader, err := provider.NewUploader(&provider.UploaderConfig{ AccessKeyId: fAccessKeyId, AccessKeySecret: fAccessKeySecret, }) diff --git a/internal/pkg/core/uploader/providers/volcengine-live/volcengine_live.go b/internal/pkg/core/uploader/providers/volcengine-live/volcengine_live.go index ce85186f..3a7a39eb 100644 --- a/internal/pkg/core/uploader/providers/volcengine-live/volcengine_live.go +++ b/internal/pkg/core/uploader/providers/volcengine-live/volcengine_live.go @@ -14,21 +14,21 @@ import ( "github.com/usual2970/certimate/internal/pkg/utils/certs" ) -type VolcEngineLiveUploaderConfig struct { +type UploaderConfig struct { // 火山引擎 AccessKeyId。 AccessKeyId string `json:"accessKeyId"` // 火山引擎 AccessKeySecret。 AccessKeySecret string `json:"accessKeySecret"` } -type VolcEngineLiveUploader struct { - config *VolcEngineLiveUploaderConfig +type UploaderProvider struct { + config *UploaderConfig sdkClient *veLive.Live } -var _ uploader.Uploader = (*VolcEngineLiveUploader)(nil) +var _ uploader.Uploader = (*UploaderProvider)(nil) -func New(config *VolcEngineLiveUploaderConfig) (*VolcEngineLiveUploader, error) { +func NewUploader(config *UploaderConfig) (*UploaderProvider, error) { if config == nil { panic("config is nil") } @@ -37,13 +37,13 @@ func New(config *VolcEngineLiveUploaderConfig) (*VolcEngineLiveUploader, error) client.SetAccessKey(config.AccessKeyId) client.SetSecretKey(config.AccessKeySecret) - return &VolcEngineLiveUploader{ + return &UploaderProvider{ config: config, sdkClient: client, }, nil } -func (u *VolcEngineLiveUploader) Upload(ctx context.Context, certPem string, privkeyPem string) (res *uploader.UploadResult, err error) { +func (u *UploaderProvider) Upload(ctx context.Context, certPem string, privkeyPem string) (res *uploader.UploadResult, err error) { // 解析证书内容 certX509, err := certs.ParseCertificateFromPEM(certPem) if err != nil { From 513919869135c9a242fd4db72ed85e98ffd95ac0 Mon Sep 17 00:00:00 2001 From: Fu Diwei Date: Thu, 20 Feb 2025 00:51:34 +0800 Subject: [PATCH 20/34] feat: add jdcloud cdn deployer --- README.md | 1 + README_EN.md | 1 + internal/deployer/providers.go | 22 +++++ internal/domain/provider.go | 1 + .../providers/jdcloud-cdn/jdcloud_cdn.go | 88 +++++++++++++++++++ .../providers/jdcloud-cdn/jdcloud_cdn_test.go | 75 ++++++++++++++++ .../ApplyNodeConfigFormJDCloudDNSConfig.tsx | 7 +- .../workflow/node/DeployNodeConfigForm.tsx | 3 + .../DeployNodeConfigFormJDCloudCDNConfig.tsx | 65 ++++++++++++++ ui/src/domain/provider.ts | 2 + ui/src/i18n/locales/en/nls.common.json | 72 --------------- ui/src/i18n/locales/en/nls.provider.json | 3 + .../i18n/locales/en/nls.workflow.nodes.json | 4 + ui/src/i18n/locales/zh/nls.provider.json | 1 + .../i18n/locales/zh/nls.workflow.nodes.json | 4 + 15 files changed, 276 insertions(+), 73 deletions(-) create mode 100644 internal/pkg/core/deployer/providers/jdcloud-cdn/jdcloud_cdn.go create mode 100644 internal/pkg/core/deployer/providers/jdcloud-cdn/jdcloud_cdn_test.go create mode 100644 ui/src/components/workflow/node/DeployNodeConfigFormJDCloudCDNConfig.tsx diff --git a/README.md b/README.md index fcc0ad27..10051a19 100644 --- a/README.md +++ b/README.md @@ -130,6 +130,7 @@ make local.run | [百度智能云](https://cloud.baidu.com/) | 可部署到百度智能云 CDN 等服务 | | [华为云](https://www.huaweicloud.com/) | 可部署到华为云 CDN、ELB、WAF 等服务 | | [火山引擎](https://www.volcengine.com/) | 可部署到火山引擎 TOS、CDN、DCDN、CLB、ImageX、Live 等服务 | +| [京东云](https://www.jdcloud.com/) | 可部署到京东云 CDN | | [七牛云](https://www.qiniu.com/) | 可部署到七牛云 CDN、直播云等服务 | | [白山云](https://www.baishan.com/) | 可部署到白山云 CDN | | [多吉云](https://www.dogecloud.com/) | 可部署到多吉云 CDN | diff --git a/README_EN.md b/README_EN.md index cae7e0f7..b92a6982 100644 --- a/README_EN.md +++ b/README_EN.md @@ -129,6 +129,7 @@ The following hosting providers are supported: | [Baidu AI Cloud](https://intl.cloud.baidu.com/) | Supports deployment to Baidu AI CLoud CDN | | [Huawei Cloud](https://www.huaweicloud.com/) | Supports deployment to Huawei Cloud CDN, ELB, WAF | | [Volcengine](https://www.volcengine.com/) | Supports deployment to Volcengine TOS, CDN, DCDN, CLB, ImageX, Live | +| [JD Cloud](https://www.jdcloud.com/) | Supports deployment to JD Cloud CDN | | [Qiniu Cloud](https://www.qiniu.com/) | Supports deployment to Qiniu Cloud CDN, Pili | | [Baishan Cloud](https://intl.baishancloud.com/) | Supports deployment to Baishan Cloud CDN | | [Doge Cloud](https://www.dogecloud.com/) | Supports deployment to Doge Cloud CDN | diff --git a/internal/deployer/providers.go b/internal/deployer/providers.go index 94e7dbf8..c23dbed0 100644 --- a/internal/deployer/providers.go +++ b/internal/deployer/providers.go @@ -30,6 +30,7 @@ import ( pHuaweiCloudCDN "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/huaweicloud-cdn" pHuaweiCloudELB "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/huaweicloud-elb" pHuaweiCloudWAF "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/huaweicloud-waf" + pJDCloudCDN "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/jdcloud-cdn" pK8sSecret "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/k8s-secret" pLocal "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/local" pQiniuCDN "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/qiniu-cdn" @@ -415,6 +416,27 @@ func createDeployer(options *deployerOptions) (deployer.Deployer, error) { } } + case domain.DeployProviderTypeJDCloudCDN: + { + access := domain.AccessConfigForJDCloud{} + if err := maps.Populate(options.ProviderAccessConfig, &access); err != nil { + return nil, fmt.Errorf("failed to populate provider access config: %w", err) + } + + switch options.Provider { + case domain.DeployProviderTypeJDCloudCDN: + deployer, err := pJDCloudCDN.NewDeployer(&pJDCloudCDN.DeployerConfig{ + AccessKeyId: access.AccessKeyId, + AccessKeySecret: access.AccessKeySecret, + Domain: maps.GetValueAsString(options.ProviderDeployConfig, "domain"), + }) + return deployer, err + + default: + break + } + } + case domain.DeployProviderTypeLocal: { deployer, err := pLocal.NewDeployer(&pLocal.DeployerConfig{ diff --git a/internal/domain/provider.go b/internal/domain/provider.go index 5f36117e..a61a0c54 100644 --- a/internal/domain/provider.go +++ b/internal/domain/provider.go @@ -127,6 +127,7 @@ const ( DeployProviderTypeHuaweiCloudCDN = DeployProviderType("huaweicloud-cdn") DeployProviderTypeHuaweiCloudELB = DeployProviderType("huaweicloud-elb") DeployProviderTypeHuaweiCloudWAF = DeployProviderType("huaweicloud-waf") + DeployProviderTypeJDCloudCDN = DeployProviderType("jdcloud-cdn") DeployProviderTypeKubernetesSecret = DeployProviderType("k8s-secret") DeployProviderTypeLocal = DeployProviderType("local") DeployProviderTypeQiniuCDN = DeployProviderType("qiniu-cdn") diff --git a/internal/pkg/core/deployer/providers/jdcloud-cdn/jdcloud_cdn.go b/internal/pkg/core/deployer/providers/jdcloud-cdn/jdcloud_cdn.go new file mode 100644 index 00000000..9b29d9c1 --- /dev/null +++ b/internal/pkg/core/deployer/providers/jdcloud-cdn/jdcloud_cdn.go @@ -0,0 +1,88 @@ +package jdcloudcdn + +import ( + "context" + + jdCore "github.com/jdcloud-api/jdcloud-sdk-go/core" + jdCdnApi "github.com/jdcloud-api/jdcloud-sdk-go/services/cdn/apis" + jdCdnClient "github.com/jdcloud-api/jdcloud-sdk-go/services/cdn/client" + xerrors "github.com/pkg/errors" + + "github.com/usual2970/certimate/internal/pkg/core/deployer" + "github.com/usual2970/certimate/internal/pkg/core/logger" +) + +type DeployerConfig struct { + // 京东云 AccessKeyId。 + AccessKeyId string `json:"accessKeyId"` + // 京东云 AccessKeySecret。 + AccessKeySecret string `json:"accessKeySecret"` + // 加速域名(支持泛域名)。 + Domain string `json:"domain"` +} + +type DeployerProvider struct { + config *DeployerConfig + logger logger.Logger + sdkClient *jdCdnClient.CdnClient +} + +var _ deployer.Deployer = (*DeployerProvider)(nil) + +func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { + if config == nil { + panic("config is nil") + } + + client, err := createSdkClient(config.AccessKeyId, config.AccessKeySecret) + if err != nil { + return nil, xerrors.Wrap(err, "failed to create sdk client") + } + + return &DeployerProvider{ + config: config, + logger: logger.NewNilLogger(), + sdkClient: client, + }, nil +} + +func (d *DeployerProvider) WithLogger(logger logger.Logger) *DeployerProvider { + d.logger = logger + return d +} + +func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { + // 查询域名配置信息 + // REF: https://docs.jdcloud.com/cn/cdn/api/querydomainconfig + queryDomainConfigReq := jdCdnApi.NewQueryDomainConfigRequest(d.config.Domain) + queryDomainConfigResp, err := d.sdkClient.QueryDomainConfig(queryDomainConfigReq) + if err != nil { + return nil, xerrors.Wrap(err, "failed to execute sdk request 'cdn.QueryDomainConfig'") + } else { + d.logger.Logt("已查询到域名配置信息", queryDomainConfigResp) + } + + // 设置通讯协议 + // REF: https://docs.jdcloud.com/cn/cdn/api/sethttptype + setHttpTypeReq := jdCdnApi.NewSetHttpTypeRequest(d.config.Domain) + setHttpTypeReq.SetHttpType("https") + setHttpTypeReq.SetCertFrom("default") + setHttpTypeReq.SetCertificate(certPem) + setHttpTypeReq.SetRsaKey(privkeyPem) + setHttpTypeReq.SetSyncToSsl(false) + setHttpTypeReq.SetJumpType(queryDomainConfigResp.Result.HttpsJumpType) + setHttpTypeResp, err := d.sdkClient.SetHttpType(setHttpTypeReq) + if err != nil { + return nil, xerrors.Wrap(err, "failed to execute sdk request 'cdn.SetHttpType'") + } else { + d.logger.Logt("已设置通讯协议", setHttpTypeResp) + } + + return &deployer.DeployResult{}, nil +} + +func createSdkClient(accessKeyId, accessKeySecret string) (*jdCdnClient.CdnClient, error) { + clientCredentials := jdCore.NewCredentials(accessKeyId, accessKeySecret) + client := jdCdnClient.NewCdnClient(clientCredentials) + return client, nil +} diff --git a/internal/pkg/core/deployer/providers/jdcloud-cdn/jdcloud_cdn_test.go b/internal/pkg/core/deployer/providers/jdcloud-cdn/jdcloud_cdn_test.go new file mode 100644 index 00000000..b95636dc --- /dev/null +++ b/internal/pkg/core/deployer/providers/jdcloud-cdn/jdcloud_cdn_test.go @@ -0,0 +1,75 @@ +package jdcloudcdn_test + +import ( + "context" + "flag" + "fmt" + "os" + "strings" + "testing" + + provider "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/jdcloud-cdn" +) + +var ( + fInputCertPath string + fInputKeyPath string + fAccessKeyId string + fAccessKeySecret string + fDomain string +) + +func init() { + argsPrefix := "CERTIMATE_DEPLOYER_BAIDUCLOUDCDN_" + + flag.StringVar(&fInputCertPath, argsPrefix+"INPUTCERTPATH", "", "") + flag.StringVar(&fInputKeyPath, argsPrefix+"INPUTKEYPATH", "", "") + flag.StringVar(&fAccessKeyId, argsPrefix+"ACCESSKEYID", "", "") + flag.StringVar(&fAccessKeySecret, argsPrefix+"ACCESSKEYSECRET", "", "") + flag.StringVar(&fDomain, argsPrefix+"DOMAIN", "", "") +} + +/* +Shell command to run this test: + + go test -v ./jdcloud_cdn_test.go -args \ + --CERTIMATE_DEPLOYER_JDCLOUDCDN_INPUTCERTPATH="/path/to/your-input-cert.pem" \ + --CERTIMATE_DEPLOYER_JDCLOUDCDN_INPUTKEYPATH="/path/to/your-input-key.pem" \ + --CERTIMATE_DEPLOYER_JDCLOUDCDN_ACCESSKEYID="your-access-key-id" \ + --CERTIMATE_DEPLOYER_JDCLOUDCDN_ACCESSKEYSECRET="your-secret-access-key" \ + --CERTIMATE_DEPLOYER_JDCLOUDCDN_DOMAIN="example.com" +*/ +func TestDeploy(t *testing.T) { + flag.Parse() + + t.Run("Deploy", func(t *testing.T) { + t.Log(strings.Join([]string{ + "args:", + fmt.Sprintf("INPUTCERTPATH: %v", fInputCertPath), + fmt.Sprintf("INPUTKEYPATH: %v", fInputKeyPath), + fmt.Sprintf("ACCESSKEYID: %v", fAccessKeyId), + fmt.Sprintf("ACCESSKEYSECRET: %v", fAccessKeySecret), + fmt.Sprintf("DOMAIN: %v", fDomain), + }, "\n")) + + deployer, err := provider.NewDeployer(&provider.DeployerConfig{ + AccessKeyId: fAccessKeyId, + AccessKeySecret: fAccessKeySecret, + Domain: fDomain, + }) + if err != nil { + t.Errorf("err: %+v", err) + return + } + + fInputCertData, _ := os.ReadFile(fInputCertPath) + fInputKeyData, _ := os.ReadFile(fInputKeyPath) + res, err := deployer.Deploy(context.Background(), string(fInputCertData), string(fInputKeyData)) + if err != nil { + t.Errorf("err: %+v", err) + return + } + + t.Logf("ok: %v", res) + }) +} diff --git a/ui/src/components/workflow/node/ApplyNodeConfigFormJDCloudDNSConfig.tsx b/ui/src/components/workflow/node/ApplyNodeConfigFormJDCloudDNSConfig.tsx index f9533972..dba0b56c 100644 --- a/ui/src/components/workflow/node/ApplyNodeConfigFormJDCloudDNSConfig.tsx +++ b/ui/src/components/workflow/node/ApplyNodeConfigFormJDCloudDNSConfig.tsx @@ -51,7 +51,12 @@ const ApplyNodeConfigFormJDCloudDNSConfig = ({ name={formName} onValuesChange={handleFormChange} > - + } + > diff --git a/ui/src/components/workflow/node/DeployNodeConfigForm.tsx b/ui/src/components/workflow/node/DeployNodeConfigForm.tsx index 4706e330..824a0cfe 100644 --- a/ui/src/components/workflow/node/DeployNodeConfigForm.tsx +++ b/ui/src/components/workflow/node/DeployNodeConfigForm.tsx @@ -38,6 +38,7 @@ import DeployNodeConfigFormGcoreCDNConfig from "./DeployNodeConfigFormGcoreCDNCo import DeployNodeConfigFormHuaweiCloudCDNConfig from "./DeployNodeConfigFormHuaweiCloudCDNConfig"; import DeployNodeConfigFormHuaweiCloudELBConfig from "./DeployNodeConfigFormHuaweiCloudELBConfig"; import DeployNodeConfigFormHuaweiCloudWAFConfig from "./DeployNodeConfigFormHuaweiCloudWAFConfig"; +import DeployNodeConfigFormJDCloudCDNConfig from "./DeployNodeConfigFormJDCloudCDNConfig"; import DeployNodeConfigFormKubernetesSecretConfig from "./DeployNodeConfigFormKubernetesSecretConfig"; import DeployNodeConfigFormLocalConfig from "./DeployNodeConfigFormLocalConfig"; import DeployNodeConfigFormQiniuCDNConfig from "./DeployNodeConfigFormQiniuCDNConfig"; @@ -178,6 +179,8 @@ const DeployNodeConfigForm = forwardRef; case DEPLOY_PROVIDERS.HUAWEICLOUD_WAF: return ; + case DEPLOY_PROVIDERS.JDCLOUD_CDN: + return ; case DEPLOY_PROVIDERS.KUBERNETES_SECRET: return ; case DEPLOY_PROVIDERS.LOCAL: diff --git a/ui/src/components/workflow/node/DeployNodeConfigFormJDCloudCDNConfig.tsx b/ui/src/components/workflow/node/DeployNodeConfigFormJDCloudCDNConfig.tsx new file mode 100644 index 00000000..9d8af17e --- /dev/null +++ b/ui/src/components/workflow/node/DeployNodeConfigFormJDCloudCDNConfig.tsx @@ -0,0 +1,65 @@ +import { useTranslation } from "react-i18next"; +import { Form, type FormInstance, Input } from "antd"; +import { createSchemaFieldRule } from "antd-zod"; +import { z } from "zod"; + +import { validDomainName } from "@/utils/validators"; + +type DeployNodeConfigFormJDCloudCDNConfigFieldValues = Nullish<{ + domain: string; +}>; + +export type DeployNodeConfigFormJDCloudCDNConfigProps = { + form: FormInstance; + formName: string; + disabled?: boolean; + initialValues?: DeployNodeConfigFormJDCloudCDNConfigFieldValues; + onValuesChange?: (values: DeployNodeConfigFormJDCloudCDNConfigFieldValues) => void; +}; + +const initFormModel = (): DeployNodeConfigFormJDCloudCDNConfigFieldValues => { + return {}; +}; + +const DeployNodeConfigFormJDCloudCDNConfig = ({ + form: formInst, + formName, + disabled, + initialValues, + onValuesChange, +}: DeployNodeConfigFormJDCloudCDNConfigProps) => { + const { t } = useTranslation(); + + const formSchema = z.object({ + domain: z + .string({ message: t("workflow_node.deploy.form.jdcloud_cdn_domain.placeholder") }) + .refine((v) => validDomainName(v, { allowWildcard: true }), t("common.errmsg.domain_invalid")), + }); + const formRule = createSchemaFieldRule(formSchema); + + const handleFormChange = (_: unknown, values: z.infer) => { + onValuesChange?.(values); + }; + + return ( +
+ } + > + + +
+ ); +}; + +export default DeployNodeConfigFormJDCloudCDNConfig; diff --git a/ui/src/domain/provider.ts b/ui/src/domain/provider.ts index 39a5424e..c4757c22 100644 --- a/ui/src/domain/provider.ts +++ b/ui/src/domain/provider.ts @@ -221,6 +221,7 @@ export const DEPLOY_PROVIDERS = Object.freeze({ HUAWEICLOUD_CDN: `${ACCESS_PROVIDERS.HUAWEICLOUD}-cdn`, HUAWEICLOUD_ELB: `${ACCESS_PROVIDERS.HUAWEICLOUD}-elb`, HUAWEICLOUD_WAF: `${ACCESS_PROVIDERS.HUAWEICLOUD}-waf`, + JDCLOUD_CDN: `${ACCESS_PROVIDERS.JDCLOUD}-cdn`, KUBERNETES_SECRET: `${ACCESS_PROVIDERS.KUBERNETES}-secret`, LOCAL: `${ACCESS_PROVIDERS.LOCAL}`, QINIU_CDN: `${ACCESS_PROVIDERS.QINIU}-cdn`, @@ -307,6 +308,7 @@ export const deployProvidersMap: Maphttps://console-intl.huaweicloud.com/apiexplorer/#/endpoint", "workflow_node.apply.form.jdcloud_dns_region_id.label": "JD Cloud DNS region ID", "workflow_node.apply.form.jdcloud_dns_region_id.placeholder": "Please enter JD Cloud DNS region ID (e.g. cn-north-1)", + "workflow_node.apply.form.jdcloud_dns_region_id.tooltip": "For more information, see https://docs.jdcloud.com/en/common-declaration/api/introduction", "workflow_node.apply.form.advanced_config.label": "Advanced settings", "workflow_node.apply.form.key_algorithm.label": "Certificate key algorithm", "workflow_node.apply.form.key_algorithm.placeholder": "Please select certificate key algorithm", @@ -266,6 +267,9 @@ "workflow_node.deploy.form.huaweicloud_waf_domain.label": "Huawei Cloud WAF domain", "workflow_node.deploy.form.huaweicloud_waf_domain.placeholder": "Please enter Huawei Cloud WAF domain name", "workflow_node.deploy.form.huaweicloud_waf_domain.tooltip": "For more information, see https://console-intl.huaweicloud.com/console/#/waf/domain/list", + "workflow_node.deploy.form.jdcloud_cdn_domain.label": "JD Cloud CDN domain", + "workflow_node.deploy.form.jdcloud_cdn_domain.placeholder": "Please enter JD Cloud CDN domain name", + "workflow_node.deploy.form.jdcloud_cdn_domain.tooltip": "For more information, see https://cdn-console.jdcloud.com/", "workflow_node.deploy.form.k8s_namespace.label": "Kubernetes Namespace", "workflow_node.deploy.form.k8s_namespace.placeholder": "Please enter Kubernetes Namespace", "workflow_node.deploy.form.k8s_namespace.tooltip": "For more information, see https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/", diff --git a/ui/src/i18n/locales/zh/nls.provider.json b/ui/src/i18n/locales/zh/nls.provider.json index 958f54a3..87edb0f1 100644 --- a/ui/src/i18n/locales/zh/nls.provider.json +++ b/ui/src/i18n/locales/zh/nls.provider.json @@ -54,6 +54,7 @@ "provider.huaweicloud.elb": "华为云 - 弹性负载均衡 ELB", "provider.huaweicloud.waf": "华为云 - Web 应用防火墙 WAF", "provider.jdcloud": "京东云", + "provider.jdcloud.cdn": "京东云 - 内容分发网络 CDN", "provider.jdcloud.dns": "京东云 - 云解析 DNS", "provider.kubernetes": "Kubernetes", "provider.kubernetes.secret": "Kubernetes - Secret", diff --git a/ui/src/i18n/locales/zh/nls.workflow.nodes.json b/ui/src/i18n/locales/zh/nls.workflow.nodes.json index 5860ba08..3dcf31a5 100644 --- a/ui/src/i18n/locales/zh/nls.workflow.nodes.json +++ b/ui/src/i18n/locales/zh/nls.workflow.nodes.json @@ -48,6 +48,7 @@ "workflow_node.apply.form.huaweicloud_dns_region.tooltip": "这是什么?请参阅 https://console.huaweicloud.com/apiexplorer/#/endpoint", "workflow_node.apply.form.jdcloud_dns_region_id.label": "京东云 DNS 服务地域 ID", "workflow_node.apply.form.jdcloud_dns_region_id.placeholder": "请输入京东云 DNS 服务地域 ID(例如:cn-north-1)", + "workflow_node.apply.form.jdcloud_dns_region_id.tooltip": "这是什么?请参阅 https://docs.jdcloud.com/cn/common-declaration/api/introduction", "workflow_node.apply.form.advanced_config.label": "高级设置", "workflow_node.apply.form.key_algorithm.label": "数字证书算法", "workflow_node.apply.form.key_algorithm.placeholder": "请选择数字证书算法", @@ -266,6 +267,9 @@ "workflow_node.deploy.form.huaweicloud_waf_domain.label": "华为云 WAF 防护域名", "workflow_node.deploy.form.huaweicloud_waf_domain.placeholder": "请输入华为云 WAF 防护域名(支持泛域名)", "workflow_node.deploy.form.huaweicloud_waf_domain.tooltip": "这是什么?请参阅 https://console.huaweicloud.com/console/#/waf/domain/list", + "workflow_node.deploy.form.jdcloud_cdn_domain.label": "京东云 CDN 加速域名", + "workflow_node.deploy.form.jdcloud_cdn_domain.placeholder": "请输入京东云 CDN 加速域名(支持泛域名)", + "workflow_node.deploy.form.jdcloud_cdn_domain.tooltip": "这是什么?请参阅 https://cdn-console.jdcloud.com/", "workflow_node.deploy.form.k8s_namespace.label": "Kubernetes 命名空间", "workflow_node.deploy.form.k8s_namespace.placeholder": "请输入 Kubernetes 命名空间", "workflow_node.deploy.form.k8s_namespace.tooltip": "这是什么?请参阅 https://kubernetes.io/zh-cn/docs/concepts/overview/working-with-objects/namespaces/", From 22d971db4be12037a4bd84ef2cc162ccf9f8e465 Mon Sep 17 00:00:00 2001 From: Fu Diwei Date: Thu, 20 Feb 2025 10:13:02 +0800 Subject: [PATCH 21/34] feat: add jdcloud live video deployer --- README.md | 2 +- README_EN.md | 2 +- internal/deployer/providers.go | 11 ++- internal/domain/provider.go | 1 + .../providers/jdcloud-live/jdcloud_live.go | 74 ++++++++++++++++++ .../jdcloud-live/jdcloud_live_test.go | 75 +++++++++++++++++++ internal/pkg/vendors/gname-sdk/models.go | 2 +- ui/src/components/Version.tsx | 4 +- .../workflow/node/DeployNodeConfigForm.tsx | 3 + .../DeployNodeConfigFormJDCloudLiveConfig.tsx | 65 ++++++++++++++++ ui/src/domain/provider.ts | 2 + ui/src/hooks/useVersionChecker.ts | 4 +- ui/src/i18n/locales/en/nls.provider.json | 1 + .../i18n/locales/en/nls.workflow.nodes.json | 7 +- ui/src/i18n/locales/zh/nls.provider.json | 1 + .../i18n/locales/zh/nls.workflow.nodes.json | 3 + 16 files changed, 247 insertions(+), 10 deletions(-) create mode 100644 internal/pkg/core/deployer/providers/jdcloud-live/jdcloud_live.go create mode 100644 internal/pkg/core/deployer/providers/jdcloud-live/jdcloud_live_test.go create mode 100644 ui/src/components/workflow/node/DeployNodeConfigFormJDCloudLiveConfig.tsx diff --git a/README.md b/README.md index 10051a19..f744e1fe 100644 --- a/README.md +++ b/README.md @@ -130,7 +130,7 @@ make local.run | [百度智能云](https://cloud.baidu.com/) | 可部署到百度智能云 CDN 等服务 | | [华为云](https://www.huaweicloud.com/) | 可部署到华为云 CDN、ELB、WAF 等服务 | | [火山引擎](https://www.volcengine.com/) | 可部署到火山引擎 TOS、CDN、DCDN、CLB、ImageX、Live 等服务 | -| [京东云](https://www.jdcloud.com/) | 可部署到京东云 CDN | +| [京东云](https://www.jdcloud.com/) | 可部署到京东云 CDN、视频直播等服务 | | [七牛云](https://www.qiniu.com/) | 可部署到七牛云 CDN、直播云等服务 | | [白山云](https://www.baishan.com/) | 可部署到白山云 CDN | | [多吉云](https://www.dogecloud.com/) | 可部署到多吉云 CDN | diff --git a/README_EN.md b/README_EN.md index b92a6982..05003b60 100644 --- a/README_EN.md +++ b/README_EN.md @@ -129,7 +129,7 @@ The following hosting providers are supported: | [Baidu AI Cloud](https://intl.cloud.baidu.com/) | Supports deployment to Baidu AI CLoud CDN | | [Huawei Cloud](https://www.huaweicloud.com/) | Supports deployment to Huawei Cloud CDN, ELB, WAF | | [Volcengine](https://www.volcengine.com/) | Supports deployment to Volcengine TOS, CDN, DCDN, CLB, ImageX, Live | -| [JD Cloud](https://www.jdcloud.com/) | Supports deployment to JD Cloud CDN | +| [JD Cloud](https://www.jdcloud.com/) | Supports deployment to JD Cloud CDN, Live Video | | [Qiniu Cloud](https://www.qiniu.com/) | Supports deployment to Qiniu Cloud CDN, Pili | | [Baishan Cloud](https://intl.baishancloud.com/) | Supports deployment to Baishan Cloud CDN | | [Doge Cloud](https://www.dogecloud.com/) | Supports deployment to Doge Cloud CDN | diff --git a/internal/deployer/providers.go b/internal/deployer/providers.go index c23dbed0..9210a7e5 100644 --- a/internal/deployer/providers.go +++ b/internal/deployer/providers.go @@ -31,6 +31,7 @@ import ( pHuaweiCloudELB "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/huaweicloud-elb" pHuaweiCloudWAF "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/huaweicloud-waf" pJDCloudCDN "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/jdcloud-cdn" + pJDCloudLive "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/jdcloud-live" pK8sSecret "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/k8s-secret" pLocal "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/local" pQiniuCDN "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/qiniu-cdn" @@ -416,7 +417,7 @@ func createDeployer(options *deployerOptions) (deployer.Deployer, error) { } } - case domain.DeployProviderTypeJDCloudCDN: + case domain.DeployProviderTypeJDCloudCDN, domain.DeployProviderTypeJDCloudLive: { access := domain.AccessConfigForJDCloud{} if err := maps.Populate(options.ProviderAccessConfig, &access); err != nil { @@ -432,6 +433,14 @@ func createDeployer(options *deployerOptions) (deployer.Deployer, error) { }) return deployer, err + case domain.DeployProviderTypeJDCloudLive: + deployer, err := pJDCloudLive.NewDeployer(&pJDCloudLive.DeployerConfig{ + AccessKeyId: access.AccessKeyId, + AccessKeySecret: access.AccessKeySecret, + Domain: maps.GetValueAsString(options.ProviderDeployConfig, "domain"), + }) + return deployer, err + default: break } diff --git a/internal/domain/provider.go b/internal/domain/provider.go index a61a0c54..b39af710 100644 --- a/internal/domain/provider.go +++ b/internal/domain/provider.go @@ -128,6 +128,7 @@ const ( DeployProviderTypeHuaweiCloudELB = DeployProviderType("huaweicloud-elb") DeployProviderTypeHuaweiCloudWAF = DeployProviderType("huaweicloud-waf") DeployProviderTypeJDCloudCDN = DeployProviderType("jdcloud-cdn") + DeployProviderTypeJDCloudLive = DeployProviderType("jdcloud-live") DeployProviderTypeKubernetesSecret = DeployProviderType("k8s-secret") DeployProviderTypeLocal = DeployProviderType("local") DeployProviderTypeQiniuCDN = DeployProviderType("qiniu-cdn") diff --git a/internal/pkg/core/deployer/providers/jdcloud-live/jdcloud_live.go b/internal/pkg/core/deployer/providers/jdcloud-live/jdcloud_live.go new file mode 100644 index 00000000..42a474de --- /dev/null +++ b/internal/pkg/core/deployer/providers/jdcloud-live/jdcloud_live.go @@ -0,0 +1,74 @@ +package jdcloudlive + +import ( + "context" + + jdCore "github.com/jdcloud-api/jdcloud-sdk-go/core" + jdLiveApi "github.com/jdcloud-api/jdcloud-sdk-go/services/live/apis" + jdLiveClient "github.com/jdcloud-api/jdcloud-sdk-go/services/live/client" + xerrors "github.com/pkg/errors" + + "github.com/usual2970/certimate/internal/pkg/core/deployer" + "github.com/usual2970/certimate/internal/pkg/core/logger" +) + +type DeployerConfig struct { + // 京东云 AccessKeyId。 + AccessKeyId string `json:"accessKeyId"` + // 京东云 AccessKeySecret。 + AccessKeySecret string `json:"accessKeySecret"` + // 直播播放域名(不支持泛域名)。 + Domain string `json:"domain"` +} + +type DeployerProvider struct { + config *DeployerConfig + logger logger.Logger + sdkClient *jdLiveClient.LiveClient +} + +var _ deployer.Deployer = (*DeployerProvider)(nil) + +func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { + if config == nil { + panic("config is nil") + } + + client, err := createSdkClient(config.AccessKeyId, config.AccessKeySecret) + if err != nil { + return nil, xerrors.Wrap(err, "failed to create sdk client") + } + + return &DeployerProvider{ + config: config, + logger: logger.NewNilLogger(), + sdkClient: client, + }, nil +} + +func (d *DeployerProvider) WithLogger(logger logger.Logger) *DeployerProvider { + d.logger = logger + return d +} + +func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { + // 设置直播证书 + // REF: https://docs.jdcloud.com/cn/live-video/api/setlivedomaincertificate + setLiveDomainCertificateReq := jdLiveApi.NewSetLiveDomainCertificateRequest(d.config.Domain, "on") + setLiveDomainCertificateReq.SetCert(certPem) + setLiveDomainCertificateReq.SetKey(privkeyPem) + setLiveDomainCertificateResp, err := d.sdkClient.SetLiveDomainCertificate(setLiveDomainCertificateReq) + if err != nil { + return nil, xerrors.Wrap(err, "failed to execute sdk request 'live.SetLiveDomainCertificate'") + } else { + d.logger.Logt("已设置直播证书", setLiveDomainCertificateResp) + } + + return &deployer.DeployResult{}, nil +} + +func createSdkClient(accessKeyId, accessKeySecret string) (*jdLiveClient.LiveClient, error) { + clientCredentials := jdCore.NewCredentials(accessKeyId, accessKeySecret) + client := jdLiveClient.NewLiveClient(clientCredentials) + return client, nil +} diff --git a/internal/pkg/core/deployer/providers/jdcloud-live/jdcloud_live_test.go b/internal/pkg/core/deployer/providers/jdcloud-live/jdcloud_live_test.go new file mode 100644 index 00000000..510198cc --- /dev/null +++ b/internal/pkg/core/deployer/providers/jdcloud-live/jdcloud_live_test.go @@ -0,0 +1,75 @@ +package jdcloudlive_test + +import ( + "context" + "flag" + "fmt" + "os" + "strings" + "testing" + + provider "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/jdcloud-live" +) + +var ( + fInputCertPath string + fInputKeyPath string + fAccessKeyId string + fAccessKeySecret string + fDomain string +) + +func init() { + argsPrefix := "CERTIMATE_DEPLOYER_BAIDUCLOUDCDN_" + + flag.StringVar(&fInputCertPath, argsPrefix+"INPUTCERTPATH", "", "") + flag.StringVar(&fInputKeyPath, argsPrefix+"INPUTKEYPATH", "", "") + flag.StringVar(&fAccessKeyId, argsPrefix+"ACCESSKEYID", "", "") + flag.StringVar(&fAccessKeySecret, argsPrefix+"ACCESSKEYSECRET", "", "") + flag.StringVar(&fDomain, argsPrefix+"DOMAIN", "", "") +} + +/* +Shell command to run this test: + + go test -v ./jdcloud_live_test.go -args \ + --CERTIMATE_DEPLOYER_JDCLOUDLIVE_INPUTCERTPATH="/path/to/your-input-cert.pem" \ + --CERTIMATE_DEPLOYER_JDCLOUDLIVE_INPUTKEYPATH="/path/to/your-input-key.pem" \ + --CERTIMATE_DEPLOYER_JDCLOUDLIVE_ACCESSKEYID="your-access-key-id" \ + --CERTIMATE_DEPLOYER_JDCLOUDLIVE_ACCESSKEYSECRET="your-secret-access-key" \ + --CERTIMATE_DEPLOYER_JDCLOUDLIVE_DOMAIN="example.com" +*/ +func TestDeploy(t *testing.T) { + flag.Parse() + + t.Run("Deploy", func(t *testing.T) { + t.Log(strings.Join([]string{ + "args:", + fmt.Sprintf("INPUTCERTPATH: %v", fInputCertPath), + fmt.Sprintf("INPUTKEYPATH: %v", fInputKeyPath), + fmt.Sprintf("ACCESSKEYID: %v", fAccessKeyId), + fmt.Sprintf("ACCESSKEYSECRET: %v", fAccessKeySecret), + fmt.Sprintf("DOMAIN: %v", fDomain), + }, "\n")) + + deployer, err := provider.NewDeployer(&provider.DeployerConfig{ + AccessKeyId: fAccessKeyId, + AccessKeySecret: fAccessKeySecret, + Domain: fDomain, + }) + if err != nil { + t.Errorf("err: %+v", err) + return + } + + fInputCertData, _ := os.ReadFile(fInputCertPath) + fInputKeyData, _ := os.ReadFile(fInputKeyPath) + res, err := deployer.Deploy(context.Background(), string(fInputCertData), string(fInputKeyData)) + if err != nil { + t.Errorf("err: %+v", err) + return + } + + t.Logf("ok: %v", res) + }) +} diff --git a/internal/pkg/vendors/gname-sdk/models.go b/internal/pkg/vendors/gname-sdk/models.go index c7ade452..997fb2c4 100644 --- a/internal/pkg/vendors/gname-sdk/models.go +++ b/internal/pkg/vendors/gname-sdk/models.go @@ -29,7 +29,7 @@ type AddDomainResolutionRequest struct { type AddDomainResolutionResponse struct { baseResponse - Data int `json:"data"` + Data string `json:"data"` } type ModifyDomainResolutionRequest struct { diff --git a/ui/src/components/Version.tsx b/ui/src/components/Version.tsx index 3d736271..e9245b1c 100644 --- a/ui/src/components/Version.tsx +++ b/ui/src/components/Version.tsx @@ -14,7 +14,7 @@ export type VersionProps = { const Version = ({ className, style }: VersionProps) => { const { t } = useTranslation(); - const { data: hasNewVersions } = useVersionChecker(); + const { hasNewVersion } = useVersionChecker(); return ( @@ -27,7 +27,7 @@ const Version = ({ className, style }: VersionProps) => { - + {version} diff --git a/ui/src/components/workflow/node/DeployNodeConfigForm.tsx b/ui/src/components/workflow/node/DeployNodeConfigForm.tsx index 824a0cfe..3ae859b6 100644 --- a/ui/src/components/workflow/node/DeployNodeConfigForm.tsx +++ b/ui/src/components/workflow/node/DeployNodeConfigForm.tsx @@ -39,6 +39,7 @@ import DeployNodeConfigFormHuaweiCloudCDNConfig from "./DeployNodeConfigFormHuaw import DeployNodeConfigFormHuaweiCloudELBConfig from "./DeployNodeConfigFormHuaweiCloudELBConfig"; import DeployNodeConfigFormHuaweiCloudWAFConfig from "./DeployNodeConfigFormHuaweiCloudWAFConfig"; import DeployNodeConfigFormJDCloudCDNConfig from "./DeployNodeConfigFormJDCloudCDNConfig"; +import DeployNodeConfigFormJDCloudLiveConfig from "./DeployNodeConfigFormJDCloudLiveConfig"; import DeployNodeConfigFormKubernetesSecretConfig from "./DeployNodeConfigFormKubernetesSecretConfig"; import DeployNodeConfigFormLocalConfig from "./DeployNodeConfigFormLocalConfig"; import DeployNodeConfigFormQiniuCDNConfig from "./DeployNodeConfigFormQiniuCDNConfig"; @@ -181,6 +182,8 @@ const DeployNodeConfigForm = forwardRef; case DEPLOY_PROVIDERS.JDCLOUD_CDN: return ; + case DEPLOY_PROVIDERS.JDCLOUD_LIVE: + return ; case DEPLOY_PROVIDERS.KUBERNETES_SECRET: return ; case DEPLOY_PROVIDERS.LOCAL: diff --git a/ui/src/components/workflow/node/DeployNodeConfigFormJDCloudLiveConfig.tsx b/ui/src/components/workflow/node/DeployNodeConfigFormJDCloudLiveConfig.tsx new file mode 100644 index 00000000..5e13f5eb --- /dev/null +++ b/ui/src/components/workflow/node/DeployNodeConfigFormJDCloudLiveConfig.tsx @@ -0,0 +1,65 @@ +import { useTranslation } from "react-i18next"; +import { Form, type FormInstance, Input } from "antd"; +import { createSchemaFieldRule } from "antd-zod"; +import { z } from "zod"; + +import { validDomainName } from "@/utils/validators"; + +type DeployNodeConfigFormJDCloudLiveConfigFieldValues = Nullish<{ + domain: string; +}>; + +export type DeployNodeConfigFormJDCloudLiveConfigProps = { + form: FormInstance; + formName: string; + disabled?: boolean; + initialValues?: DeployNodeConfigFormJDCloudLiveConfigFieldValues; + onValuesChange?: (values: DeployNodeConfigFormJDCloudLiveConfigFieldValues) => void; +}; + +const initFormModel = (): DeployNodeConfigFormJDCloudLiveConfigFieldValues => { + return {}; +}; + +const DeployNodeConfigFormJDCloudLiveConfig = ({ + form: formInst, + formName, + disabled, + initialValues, + onValuesChange, +}: DeployNodeConfigFormJDCloudLiveConfigProps) => { + const { t } = useTranslation(); + + const formSchema = z.object({ + domain: z + .string({ message: t("workflow_node.deploy.form.jdcloud_live_domain.placeholder") }) + .refine((v) => validDomainName(v), t("common.errmsg.domain_invalid")), + }); + const formRule = createSchemaFieldRule(formSchema); + + const handleFormChange = (_: unknown, values: z.infer) => { + onValuesChange?.(values); + }; + + return ( +
+ } + > + + +
+ ); +}; + +export default DeployNodeConfigFormJDCloudLiveConfig; diff --git a/ui/src/domain/provider.ts b/ui/src/domain/provider.ts index c4757c22..a2b09baf 100644 --- a/ui/src/domain/provider.ts +++ b/ui/src/domain/provider.ts @@ -222,6 +222,7 @@ export const DEPLOY_PROVIDERS = Object.freeze({ HUAWEICLOUD_ELB: `${ACCESS_PROVIDERS.HUAWEICLOUD}-elb`, HUAWEICLOUD_WAF: `${ACCESS_PROVIDERS.HUAWEICLOUD}-waf`, JDCLOUD_CDN: `${ACCESS_PROVIDERS.JDCLOUD}-cdn`, + JDCLOUD_LIVE: `${ACCESS_PROVIDERS.JDCLOUD}-live`, KUBERNETES_SECRET: `${ACCESS_PROVIDERS.KUBERNETES}-secret`, LOCAL: `${ACCESS_PROVIDERS.LOCAL}`, QINIU_CDN: `${ACCESS_PROVIDERS.QINIU}-cdn`, @@ -309,6 +310,7 @@ export const deployProvidersMap: Map void; }; @@ -62,7 +62,7 @@ const useVersionChecker = () => { ); return { - data: !!data, + hasNewVersion: !!data, check: refresh, }; }; diff --git a/ui/src/i18n/locales/en/nls.provider.json b/ui/src/i18n/locales/en/nls.provider.json index b95f40b3..cccd18c2 100644 --- a/ui/src/i18n/locales/en/nls.provider.json +++ b/ui/src/i18n/locales/en/nls.provider.json @@ -56,6 +56,7 @@ "provider.jdcloud": "JD Cloud", "provider.jdcloud.cdn": "JD Cloud - CDN (Content Delivery Network)", "provider.jdcloud.dns": "JD Cloud - DNS", + "provider.jdcloud.live": "JD Cloud - Live Video", "provider.kubernetes": "Kubernetes", "provider.kubernetes.secret": "Kubernetes - Secret", "provider.local": "Local deployment", diff --git a/ui/src/i18n/locales/en/nls.workflow.nodes.json b/ui/src/i18n/locales/en/nls.workflow.nodes.json index 90a48bf8..2ce432d3 100644 --- a/ui/src/i18n/locales/en/nls.workflow.nodes.json +++ b/ui/src/i18n/locales/en/nls.workflow.nodes.json @@ -270,6 +270,9 @@ "workflow_node.deploy.form.jdcloud_cdn_domain.label": "JD Cloud CDN domain", "workflow_node.deploy.form.jdcloud_cdn_domain.placeholder": "Please enter JD Cloud CDN domain name", "workflow_node.deploy.form.jdcloud_cdn_domain.tooltip": "For more information, see https://cdn-console.jdcloud.com/", + "workflow_node.deploy.form.jdcloud_live_domain.label": "JD Cloud Live Video play domain", + "workflow_node.deploy.form.jdcloud_live_domain.placeholder": "Please enter JD Cloud Live Video play domain name", + "workflow_node.deploy.form.jdcloud_live_domain.tooltip": "For more information, see https://docs.jdcloud.com/en/live-video/domain-management", "workflow_node.deploy.form.k8s_namespace.label": "Kubernetes Namespace", "workflow_node.deploy.form.k8s_namespace.placeholder": "Please enter Kubernetes Namespace", "workflow_node.deploy.form.k8s_namespace.tooltip": "For more information, see https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/", @@ -401,8 +404,8 @@ "workflow_node.deploy.form.tencentcloud_cos_domain.label": "Tencent Cloud COS domain", "workflow_node.deploy.form.tencentcloud_cos_domain.placeholder": "Please enter Tencent Cloud COS domain name", "workflow_node.deploy.form.tencentcloud_cos_domain.tooltip": "For more information, see https://console.tencentcloud.com/cos", - "workflow_node.deploy.form.tencentcloud_css_domain.label": "Tencent Cloud CSS playing domain", - "workflow_node.deploy.form.tencentcloud_css_domain.placeholder": "Please enter Tencent Cloud CSS playing domain name", + "workflow_node.deploy.form.tencentcloud_css_domain.label": "Tencent Cloud CSS play domain", + "workflow_node.deploy.form.tencentcloud_css_domain.placeholder": "Please enter Tencent Cloud CSS play domain name", "workflow_node.deploy.form.tencentcloud_css_domain.tooltip": "For more information, see https://console.cloud.tencent.com/live/livestat", "workflow_node.deploy.form.tencentcloud_ecdn_domain.label": "Tencent Cloud ECDN domain", "workflow_node.deploy.form.tencentcloud_ecdn_domain.placeholder": "Please enter Tencent Cloud ECDN domain name", diff --git a/ui/src/i18n/locales/zh/nls.provider.json b/ui/src/i18n/locales/zh/nls.provider.json index 87edb0f1..0d8e2911 100644 --- a/ui/src/i18n/locales/zh/nls.provider.json +++ b/ui/src/i18n/locales/zh/nls.provider.json @@ -56,6 +56,7 @@ "provider.jdcloud": "京东云", "provider.jdcloud.cdn": "京东云 - 内容分发网络 CDN", "provider.jdcloud.dns": "京东云 - 云解析 DNS", + "provider.jdcloud.live": "京东云 - 视频直播", "provider.kubernetes": "Kubernetes", "provider.kubernetes.secret": "Kubernetes - Secret", "provider.local": "本地部署", diff --git a/ui/src/i18n/locales/zh/nls.workflow.nodes.json b/ui/src/i18n/locales/zh/nls.workflow.nodes.json index 3dcf31a5..a7331d08 100644 --- a/ui/src/i18n/locales/zh/nls.workflow.nodes.json +++ b/ui/src/i18n/locales/zh/nls.workflow.nodes.json @@ -270,6 +270,9 @@ "workflow_node.deploy.form.jdcloud_cdn_domain.label": "京东云 CDN 加速域名", "workflow_node.deploy.form.jdcloud_cdn_domain.placeholder": "请输入京东云 CDN 加速域名(支持泛域名)", "workflow_node.deploy.form.jdcloud_cdn_domain.tooltip": "这是什么?请参阅 https://cdn-console.jdcloud.com/", + "workflow_node.deploy.form.jdcloud_live_domain.label": "京东云视频直播播放域名", + "workflow_node.deploy.form.jdcloud_live_domain.placeholder": "请输入京东云视频直播播放域名", + "workflow_node.deploy.form.jdcloud_live_domain.tooltip": "这是什么?请参阅 https://docs.jdcloud.com/cn/live-video/domain-management", "workflow_node.deploy.form.k8s_namespace.label": "Kubernetes 命名空间", "workflow_node.deploy.form.k8s_namespace.placeholder": "请输入 Kubernetes 命名空间", "workflow_node.deploy.form.k8s_namespace.tooltip": "这是什么?请参阅 https://kubernetes.io/zh-cn/docs/concepts/overview/working-with-objects/namespaces/", From 9febe479755fca88237980a72cd7b88a7b2ca793 Mon Sep 17 00:00:00 2001 From: Fu Diwei Date: Thu, 20 Feb 2025 14:32:42 +0800 Subject: [PATCH 22/34] feat: add jdcloud ssl uploader --- .../providers/jdcloud-cdn/jdcloud_cdn.go | 36 ++++- .../providers/jdcloud-ssl/jdcloud_ssl.go | 138 ++++++++++++++++++ .../providers/jdcloud-ssl/jdcloud_ssl_test.go | 72 +++++++++ 3 files changed, 238 insertions(+), 8 deletions(-) create mode 100644 internal/pkg/core/uploader/providers/jdcloud-ssl/jdcloud_ssl.go create mode 100644 internal/pkg/core/uploader/providers/jdcloud-ssl/jdcloud_ssl_test.go diff --git a/internal/pkg/core/deployer/providers/jdcloud-cdn/jdcloud_cdn.go b/internal/pkg/core/deployer/providers/jdcloud-cdn/jdcloud_cdn.go index 9b29d9c1..17523d1c 100644 --- a/internal/pkg/core/deployer/providers/jdcloud-cdn/jdcloud_cdn.go +++ b/internal/pkg/core/deployer/providers/jdcloud-cdn/jdcloud_cdn.go @@ -10,6 +10,8 @@ import ( "github.com/usual2970/certimate/internal/pkg/core/deployer" "github.com/usual2970/certimate/internal/pkg/core/logger" + "github.com/usual2970/certimate/internal/pkg/core/uploader" + uploadersp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/jdcloud-ssl" ) type DeployerConfig struct { @@ -22,9 +24,10 @@ type DeployerConfig struct { } type DeployerProvider struct { - config *DeployerConfig - logger logger.Logger - sdkClient *jdCdnClient.CdnClient + config *DeployerConfig + logger logger.Logger + sdkClient *jdCdnClient.CdnClient + sslUploader uploader.Uploader } var _ deployer.Deployer = (*DeployerProvider)(nil) @@ -39,10 +42,19 @@ func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { return nil, xerrors.Wrap(err, "failed to create sdk client") } + uploader, err := uploadersp.NewUploader(&uploadersp.UploaderConfig{ + AccessKeyId: config.AccessKeyId, + AccessKeySecret: config.AccessKeySecret, + }) + if err != nil { + return nil, xerrors.Wrap(err, "failed to create ssl uploader") + } + return &DeployerProvider{ - config: config, - logger: logger.NewNilLogger(), - sdkClient: client, + config: config, + logger: logger.NewNilLogger(), + sdkClient: client, + sslUploader: uploader, }, nil } @@ -62,14 +74,22 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPe d.logger.Logt("已查询到域名配置信息", queryDomainConfigResp) } + // 上传证书到 SSL + upres, err := d.sslUploader.Upload(ctx, certPem, privkeyPem) + if err != nil { + return nil, xerrors.Wrap(err, "failed to upload certificate file") + } else { + d.logger.Logt("certificate file uploaded", upres) + } + // 设置通讯协议 // REF: https://docs.jdcloud.com/cn/cdn/api/sethttptype setHttpTypeReq := jdCdnApi.NewSetHttpTypeRequest(d.config.Domain) setHttpTypeReq.SetHttpType("https") - setHttpTypeReq.SetCertFrom("default") setHttpTypeReq.SetCertificate(certPem) setHttpTypeReq.SetRsaKey(privkeyPem) - setHttpTypeReq.SetSyncToSsl(false) + setHttpTypeReq.SetCertFrom("ssl") + setHttpTypeReq.SetSslCertId(upres.CertId) setHttpTypeReq.SetJumpType(queryDomainConfigResp.Result.HttpsJumpType) setHttpTypeResp, err := d.sdkClient.SetHttpType(setHttpTypeReq) if err != nil { diff --git a/internal/pkg/core/uploader/providers/jdcloud-ssl/jdcloud_ssl.go b/internal/pkg/core/uploader/providers/jdcloud-ssl/jdcloud_ssl.go new file mode 100644 index 00000000..6368bc51 --- /dev/null +++ b/internal/pkg/core/uploader/providers/jdcloud-ssl/jdcloud_ssl.go @@ -0,0 +1,138 @@ +package jdcloudssl + +import ( + "context" + "crypto/sha256" + "encoding/hex" + "fmt" + "strings" + "time" + + jdCore "github.com/jdcloud-api/jdcloud-sdk-go/core" + jdSslApi "github.com/jdcloud-api/jdcloud-sdk-go/services/ssl/apis" + jdSslClient "github.com/jdcloud-api/jdcloud-sdk-go/services/ssl/client" + xerrors "github.com/pkg/errors" + "golang.org/x/exp/slices" + + "github.com/usual2970/certimate/internal/pkg/core/uploader" + "github.com/usual2970/certimate/internal/pkg/utils/certs" +) + +type UploaderConfig struct { + // 京东云 AccessKeyId。 + AccessKeyId string `json:"accessKeyId"` + // 京东云 AccessKeySecret。 + AccessKeySecret string `json:"accessKeySecret"` +} + +type UploaderProvider struct { + config *UploaderConfig + sdkClient *jdSslClient.SslClient +} + +var _ uploader.Uploader = (*UploaderProvider)(nil) + +func NewUploader(config *UploaderConfig) (*UploaderProvider, error) { + if config == nil { + panic("config is nil") + } + + client, err := createSdkClient(config.AccessKeyId, config.AccessKeySecret) + if err != nil { + return nil, xerrors.Wrap(err, "failed to create sdk client") + } + + return &UploaderProvider{ + config: config, + sdkClient: client, + }, nil +} + +func (u *UploaderProvider) Upload(ctx context.Context, certPem string, privkeyPem string) (res *uploader.UploadResult, err error) { + // 解析证书内容 + certX509, err := certs.ParseCertificateFromPEM(certPem) + if err != nil { + return nil, err + } + + // 格式化私钥内容,以便后续计算私钥摘要 + privkeyPem = strings.TrimSpace(privkeyPem) + privkeyPem = strings.ReplaceAll(privkeyPem, "\r", "") + privkeyPem = strings.ReplaceAll(privkeyPem, "\n", "\r\n") + privkeyPem = privkeyPem + "\r\n" + + // 遍历查看证书列表,避免重复上传 + // REF: https://docs.jdcloud.com/cn/ssl-certificate/api/describecerts + describeCertsPageNumber := 1 + describeCertsPageSize := 100 + for { + describeCertsReq := jdSslApi.NewDescribeCertsRequest() + describeCertsReq.DomainName = &certX509.Subject.CommonName + describeCertsReq.PageNumber = &describeCertsPageNumber + describeCertsReq.PageSize = &describeCertsPageSize + describeCertsResp, err := u.sdkClient.DescribeCerts(describeCertsReq) + if err != nil { + return nil, xerrors.Wrap(err, "failed to execute sdk request 'ssl.DescribeCerts'") + } + + for _, certDetail := range describeCertsResp.Result.CertListDetails { + // 先尝试匹配 CN + if !strings.EqualFold(certX509.Subject.CommonName, certDetail.CommonName) { + continue + } + + // 再尝试匹配 SAN + if !slices.Equal(certX509.DNSNames, certDetail.DnsNames) { + continue + } + + // 再尝试匹配证书有效期 + oldCertNotBefore, _ := time.Parse(time.RFC3339, certDetail.StartTime) + oldCertNotAfter, _ := time.Parse(time.RFC3339, certDetail.EndTime) + if !certX509.NotBefore.Equal(oldCertNotBefore) || !certX509.NotAfter.Equal(oldCertNotAfter) { + continue + } + + // 最后尝试匹配私钥摘要 + newKeyDigest := sha256.Sum256([]byte(privkeyPem)) + newKeyDigestHex := hex.EncodeToString(newKeyDigest[:]) + if !strings.EqualFold(newKeyDigestHex, certDetail.Digest) { + continue + } + + // 如果以上都匹配,则视为已存在相同证书,直接返回已有的证书信息 + return &uploader.UploadResult{ + CertId: certDetail.CertId, + CertName: certDetail.CertName, + }, nil + } + + if len(describeCertsResp.Result.CertListDetails) < int(describeCertsPageSize) { + break + } else { + describeCertsPageNumber++ + } + } + + // 生成新证书名(需符合京东云命名规则) + certName := fmt.Sprintf("certimate-%d", time.Now().UnixMilli()) + + // 上传证书 + // REF: https://docs.jdcloud.com/cn/ssl-certificate/api/uploadcert + uploadCertReq := jdSslApi.NewUploadCertRequest(certName, privkeyPem, certPem) + uploadCertResp, err := u.sdkClient.UploadCert(uploadCertReq) + if err != nil { + return nil, xerrors.Wrap(err, "failed to execute sdk request 'ssl.UploadCertificate'") + } + + return &uploader.UploadResult{ + CertId: uploadCertResp.Result.CertId, + CertName: certName, + }, nil +} + +func createSdkClient(accessKeyId, accessKeySecret string) (*jdSslClient.SslClient, error) { + clientCredentials := jdCore.NewCredentials(accessKeyId, accessKeySecret) + client := jdSslClient.NewSslClient(clientCredentials) + return client, nil +} diff --git a/internal/pkg/core/uploader/providers/jdcloud-ssl/jdcloud_ssl_test.go b/internal/pkg/core/uploader/providers/jdcloud-ssl/jdcloud_ssl_test.go new file mode 100644 index 00000000..ec02ce49 --- /dev/null +++ b/internal/pkg/core/uploader/providers/jdcloud-ssl/jdcloud_ssl_test.go @@ -0,0 +1,72 @@ +package jdcloudssl_test + +import ( + "context" + "encoding/json" + "flag" + "fmt" + "os" + "strings" + "testing" + + provider "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/jdcloud-ssl" +) + +var ( + fInputCertPath string + fInputKeyPath string + fAccessKeyId string + fAccessKeySecret string +) + +func init() { + argsPrefix := "CERTIMATE_UPLOADER_JDCLOUDSSL_" + + flag.StringVar(&fInputCertPath, argsPrefix+"INPUTCERTPATH", "", "") + flag.StringVar(&fInputKeyPath, argsPrefix+"INPUTKEYPATH", "", "") + flag.StringVar(&fAccessKeyId, argsPrefix+"ACCESSKEYID", "", "") + flag.StringVar(&fAccessKeySecret, argsPrefix+"ACCESSKEYSECRET", "", "") +} + +/* +Shell command to run this test: + + go test -v ./jdcloud_ssl_test.go -args \ + --CERTIMATE_UPLOADER_JDCLOUDSSL_INPUTCERTPATH="/path/to/your-input-cert.pem" \ + --CERTIMATE_UPLOADER_JDCLOUDSSL_INPUTKEYPATH="/path/to/your-input-key.pem" \ + --CERTIMATE_UPLOADER_JDCLOUDSSL_ACCESSKEYID="your-access-key-id" \ + --CERTIMATE_UPLOADER_JDCLOUDSSL_ACCESSKEYSECRET="your-access-key-secret" +*/ +func TestDeploy(t *testing.T) { + flag.Parse() + + t.Run("Deploy", func(t *testing.T) { + t.Log(strings.Join([]string{ + "args:", + fmt.Sprintf("INPUTCERTPATH: %v", fInputCertPath), + fmt.Sprintf("INPUTKEYPATH: %v", fInputKeyPath), + fmt.Sprintf("ACCESSKEYID: %v", fAccessKeyId), + fmt.Sprintf("ACCESSKEYSECRET: %v", fAccessKeySecret), + }, "\n")) + + uploader, err := provider.NewUploader(&provider.UploaderConfig{ + AccessKeyId: fAccessKeyId, + AccessKeySecret: fAccessKeySecret, + }) + if err != nil { + t.Errorf("err: %+v", err) + return + } + + fInputCertData, _ := os.ReadFile(fInputCertPath) + fInputKeyData, _ := os.ReadFile(fInputKeyPath) + res, err := uploader.Upload(context.Background(), string(fInputCertData), string(fInputKeyData)) + if err != nil { + t.Errorf("err: %+v", err) + return + } + + sres, _ := json.Marshal(res) + t.Logf("ok: %s", string(sres)) + }) +} From ea704298897a2d3008008de7df380966946cdf0b Mon Sep 17 00:00:00 2001 From: Fu Diwei Date: Thu, 20 Feb 2025 17:39:15 +0800 Subject: [PATCH 23/34] feat: add jdcloud alb deployer --- README.md | 2 +- README_EN.md | 2 +- internal/deployer/providers.go | 14 +- internal/domain/provider.go | 1 + .../providers/aliyun-alb/aliyun_alb.go | 2 +- .../providers/aliyun-clb/aliyun_clb.go | 4 +- .../deployer/providers/jdcloud-alb/consts.go | 10 + .../providers/jdcloud-alb/jdcloud_alb.go | 251 ++++++++++++++++++ .../providers/jdcloud-alb/jdcloud_alb_test.go | 118 ++++++++ .../providers/jdcloud-cdn/jdcloud_cdn_test.go | 2 +- .../jdcloud-live/jdcloud_live_test.go | 2 +- .../tencentcloud-clb/tencentcloud_clb.go | 2 +- .../workflow/node/DeployNodeConfigForm.tsx | 3 + .../DeployNodeConfigFormJDCloudALBConfig.tsx | 142 ++++++++++ ui/src/domain/provider.ts | 2 + ui/src/i18n/locales/en/nls.provider.json | 1 + .../i18n/locales/en/nls.workflow.nodes.json | 16 ++ ui/src/i18n/locales/zh/nls.provider.json | 1 + .../i18n/locales/zh/nls.workflow.nodes.json | 20 +- 19 files changed, 583 insertions(+), 12 deletions(-) create mode 100644 internal/pkg/core/deployer/providers/jdcloud-alb/consts.go create mode 100644 internal/pkg/core/deployer/providers/jdcloud-alb/jdcloud_alb.go create mode 100644 internal/pkg/core/deployer/providers/jdcloud-alb/jdcloud_alb_test.go create mode 100644 ui/src/components/workflow/node/DeployNodeConfigFormJDCloudALBConfig.tsx diff --git a/README.md b/README.md index f744e1fe..3aa3f158 100644 --- a/README.md +++ b/README.md @@ -130,7 +130,7 @@ make local.run | [百度智能云](https://cloud.baidu.com/) | 可部署到百度智能云 CDN 等服务 | | [华为云](https://www.huaweicloud.com/) | 可部署到华为云 CDN、ELB、WAF 等服务 | | [火山引擎](https://www.volcengine.com/) | 可部署到火山引擎 TOS、CDN、DCDN、CLB、ImageX、Live 等服务 | -| [京东云](https://www.jdcloud.com/) | 可部署到京东云 CDN、视频直播等服务 | +| [京东云](https://www.jdcloud.com/) | 可部署到京东云 CDN、ALB、视频直播等服务 | | [七牛云](https://www.qiniu.com/) | 可部署到七牛云 CDN、直播云等服务 | | [白山云](https://www.baishan.com/) | 可部署到白山云 CDN | | [多吉云](https://www.dogecloud.com/) | 可部署到多吉云 CDN | diff --git a/README_EN.md b/README_EN.md index 05003b60..c9a5bdf4 100644 --- a/README_EN.md +++ b/README_EN.md @@ -129,7 +129,7 @@ The following hosting providers are supported: | [Baidu AI Cloud](https://intl.cloud.baidu.com/) | Supports deployment to Baidu AI CLoud CDN | | [Huawei Cloud](https://www.huaweicloud.com/) | Supports deployment to Huawei Cloud CDN, ELB, WAF | | [Volcengine](https://www.volcengine.com/) | Supports deployment to Volcengine TOS, CDN, DCDN, CLB, ImageX, Live | -| [JD Cloud](https://www.jdcloud.com/) | Supports deployment to JD Cloud CDN, Live Video | +| [JD Cloud](https://www.jdcloud.com/) | Supports deployment to JD Cloud CDN, ALB, Live Video | | [Qiniu Cloud](https://www.qiniu.com/) | Supports deployment to Qiniu Cloud CDN, Pili | | [Baishan Cloud](https://intl.baishancloud.com/) | Supports deployment to Baishan Cloud CDN | | [Doge Cloud](https://www.dogecloud.com/) | Supports deployment to Doge Cloud CDN | diff --git a/internal/deployer/providers.go b/internal/deployer/providers.go index 9210a7e5..24fc32f4 100644 --- a/internal/deployer/providers.go +++ b/internal/deployer/providers.go @@ -30,6 +30,7 @@ import ( pHuaweiCloudCDN "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/huaweicloud-cdn" pHuaweiCloudELB "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/huaweicloud-elb" pHuaweiCloudWAF "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/huaweicloud-waf" + pJDCloudALB "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/jdcloud-alb" pJDCloudCDN "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/jdcloud-cdn" pJDCloudLive "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/jdcloud-live" pK8sSecret "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/k8s-secret" @@ -417,7 +418,7 @@ func createDeployer(options *deployerOptions) (deployer.Deployer, error) { } } - case domain.DeployProviderTypeJDCloudCDN, domain.DeployProviderTypeJDCloudLive: + case domain.DeployProviderTypeJDCloudALB, domain.DeployProviderTypeJDCloudCDN, domain.DeployProviderTypeJDCloudLive: { access := domain.AccessConfigForJDCloud{} if err := maps.Populate(options.ProviderAccessConfig, &access); err != nil { @@ -425,6 +426,17 @@ func createDeployer(options *deployerOptions) (deployer.Deployer, error) { } switch options.Provider { + case domain.DeployProviderTypeJDCloudALB: + deployer, err := pJDCloudALB.NewDeployer(&pJDCloudALB.DeployerConfig{ + AccessKeyId: access.AccessKeyId, + AccessKeySecret: access.AccessKeySecret, + RegionId: maps.GetValueAsString(options.ProviderDeployConfig, "regionId"), + ResourceType: pJDCloudALB.ResourceType(maps.GetValueAsString(options.ProviderDeployConfig, "resourceType")), + LoadbalancerId: maps.GetValueAsString(options.ProviderDeployConfig, "loadbalancerId"), + ListenerId: maps.GetValueAsString(options.ProviderDeployConfig, "listenerId"), + }) + return deployer, err + case domain.DeployProviderTypeJDCloudCDN: deployer, err := pJDCloudCDN.NewDeployer(&pJDCloudCDN.DeployerConfig{ AccessKeyId: access.AccessKeyId, diff --git a/internal/domain/provider.go b/internal/domain/provider.go index b39af710..63528231 100644 --- a/internal/domain/provider.go +++ b/internal/domain/provider.go @@ -127,6 +127,7 @@ const ( DeployProviderTypeHuaweiCloudCDN = DeployProviderType("huaweicloud-cdn") DeployProviderTypeHuaweiCloudELB = DeployProviderType("huaweicloud-elb") DeployProviderTypeHuaweiCloudWAF = DeployProviderType("huaweicloud-waf") + DeployProviderTypeJDCloudALB = DeployProviderType("jdcloud-alb") DeployProviderTypeJDCloudCDN = DeployProviderType("jdcloud-cdn") DeployProviderTypeJDCloudLive = DeployProviderType("jdcloud-live") DeployProviderTypeKubernetesSecret = DeployProviderType("k8s-secret") diff --git a/internal/pkg/core/deployer/providers/aliyun-alb/aliyun_alb.go b/internal/pkg/core/deployer/providers/aliyun-alb/aliyun_alb.go index 27261a63..39600c7b 100644 --- a/internal/pkg/core/deployer/providers/aliyun-alb/aliyun_alb.go +++ b/internal/pkg/core/deployer/providers/aliyun-alb/aliyun_alb.go @@ -254,7 +254,7 @@ func (d *DeployerProvider) updateListenerCertificate(ctx context.Context, cloudL d.logger.Logt("已更新 ALB 监听配置", updateListenerAttributeResp) } else { - // 指定 SNI,需部署到扩展域名(支持泛域名) + // 指定 SNI,需部署到扩展域名 // 查询监听证书列表 // REF: https://help.aliyun.com/zh/slb/application-load-balancer/developer-reference/api-alb-2020-06-16-listlistenercertificates diff --git a/internal/pkg/core/deployer/providers/aliyun-clb/aliyun_clb.go b/internal/pkg/core/deployer/providers/aliyun-clb/aliyun_clb.go index e18dccc4..21a1e471 100644 --- a/internal/pkg/core/deployer/providers/aliyun-clb/aliyun_clb.go +++ b/internal/pkg/core/deployer/providers/aliyun-clb/aliyun_clb.go @@ -211,8 +211,6 @@ func (d *DeployerProvider) updateListenerCertificate(ctx context.Context, cloudL // 修改监听配置 // REF: https://help.aliyun.com/zh/slb/classic-load-balancer/developer-reference/api-slb-2014-05-15-setloadbalancerhttpslistenerattribute - // - // 注意修改监听配置要放在修改扩展域名之后 setLoadBalancerHTTPSListenerAttributeReq := &aliyunSlb.SetLoadBalancerHTTPSListenerAttributeRequest{ RegionId: tea.String(d.config.Region), LoadBalancerId: tea.String(cloudLoadbalancerId), @@ -226,7 +224,7 @@ func (d *DeployerProvider) updateListenerCertificate(ctx context.Context, cloudL d.logger.Logt("已更新 CLB HTTPS 监听配置", setLoadBalancerHTTPSListenerAttributeResp) } else { - // 指定 SNI,需部署到扩展域名(支持泛域名) + // 指定 SNI,需部署到扩展域名 // 查询扩展域名 // REF: https://help.aliyun.com/zh/slb/classic-load-balancer/developer-reference/api-slb-2014-05-15-describedomainextensions diff --git a/internal/pkg/core/deployer/providers/jdcloud-alb/consts.go b/internal/pkg/core/deployer/providers/jdcloud-alb/consts.go new file mode 100644 index 00000000..13525c20 --- /dev/null +++ b/internal/pkg/core/deployer/providers/jdcloud-alb/consts.go @@ -0,0 +1,10 @@ +package jdcloudalb + +type ResourceType string + +const ( + // 资源类型:部署到指定负载均衡器。 + RESOURCE_TYPE_LOADBALANCER = ResourceType("loadbalancer") + // 资源类型:部署到指定监听器。 + RESOURCE_TYPE_LISTENER = ResourceType("listener") +) diff --git a/internal/pkg/core/deployer/providers/jdcloud-alb/jdcloud_alb.go b/internal/pkg/core/deployer/providers/jdcloud-alb/jdcloud_alb.go new file mode 100644 index 00000000..a300bb4d --- /dev/null +++ b/internal/pkg/core/deployer/providers/jdcloud-alb/jdcloud_alb.go @@ -0,0 +1,251 @@ +package jdcloudalb + +import ( + "context" + "errors" + "fmt" + "strings" + + jdCore "github.com/jdcloud-api/jdcloud-sdk-go/core" + jdCommon "github.com/jdcloud-api/jdcloud-sdk-go/services/common/models" + jdLbApi "github.com/jdcloud-api/jdcloud-sdk-go/services/lb/apis" + jdLbClient "github.com/jdcloud-api/jdcloud-sdk-go/services/lb/client" + jdLbModel "github.com/jdcloud-api/jdcloud-sdk-go/services/lb/models" + xerrors "github.com/pkg/errors" + + "github.com/usual2970/certimate/internal/pkg/core/deployer" + "github.com/usual2970/certimate/internal/pkg/core/logger" + "github.com/usual2970/certimate/internal/pkg/core/uploader" + uploadersp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/jdcloud-ssl" + "github.com/usual2970/certimate/internal/pkg/utils/slices" +) + +type DeployerConfig struct { + // 京东云 AccessKeyId。 + AccessKeyId string `json:"accessKeyId"` + // 京东云 AccessKeySecret。 + AccessKeySecret string `json:"accessKeySecret"` + // 京东云地域 ID。 + RegionId string `json:"regionId"` + // 部署资源类型。 + ResourceType ResourceType `json:"resourceType"` + // 负载均衡器 ID。 + // 部署资源类型为 [RESOURCE_TYPE_LOADBALANCER] 时必填。 + LoadbalancerId string `json:"loadbalancerId,omitempty"` + // 监听器 ID。 + // 部署资源类型为 [RESOURCE_TYPE_LISTENER] 时必填。 + ListenerId string `json:"listenerId,omitempty"` + // SNI 域名(支持泛域名)。 + // 部署资源类型为 [RESOURCE_TYPE_LOADBALANCER]、[RESOURCE_TYPE_LISTENER] 时选填。 + Domain string `json:"domain,omitempty"` +} + +type DeployerProvider struct { + config *DeployerConfig + logger logger.Logger + sdkClient *jdLbClient.LbClient + sslUploader uploader.Uploader +} + +var _ deployer.Deployer = (*DeployerProvider)(nil) + +func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { + if config == nil { + panic("config is nil") + } + + client, err := createSdkClient(config.AccessKeyId, config.AccessKeySecret) + if err != nil { + return nil, xerrors.Wrap(err, "failed to create sdk client") + } + + uploader, err := uploadersp.NewUploader(&uploadersp.UploaderConfig{ + AccessKeyId: config.AccessKeyId, + AccessKeySecret: config.AccessKeySecret, + }) + if err != nil { + return nil, xerrors.Wrap(err, "failed to create ssl uploader") + } + + return &DeployerProvider{ + config: config, + logger: logger.NewNilLogger(), + sdkClient: client, + sslUploader: uploader, + }, nil +} + +func (d *DeployerProvider) WithLogger(logger logger.Logger) *DeployerProvider { + d.logger = logger + return d +} + +func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { + // 上传证书到 SSL + upres, err := d.sslUploader.Upload(ctx, certPem, privkeyPem) + if err != nil { + return nil, xerrors.Wrap(err, "failed to upload certificate file") + } else { + d.logger.Logt("certificate file uploaded", upres) + } + + // 根据部署资源类型决定部署方式 + switch d.config.ResourceType { + case RESOURCE_TYPE_LOADBALANCER: + if err := d.deployToLoadbalancer(ctx, upres.CertId); err != nil { + return nil, err + } + + case RESOURCE_TYPE_LISTENER: + if err := d.deployToListener(ctx, upres.CertId); err != nil { + return nil, err + } + + default: + return nil, fmt.Errorf("unsupported resource type: %s", d.config.ResourceType) + } + + return &deployer.DeployResult{}, nil +} + +func (d *DeployerProvider) deployToLoadbalancer(ctx context.Context, cloudCertId string) error { + if d.config.LoadbalancerId == "" { + return errors.New("config `loadbalancerId` is required") + } + + // 查询负载均衡器详情 + // REF: https://docs.jdcloud.com/cn/load-balancer/api/describeloadbalancer + describeLoadBalancerReq := jdLbApi.NewDescribeLoadBalancerRequest(d.config.RegionId, d.config.LoadbalancerId) + describeLoadBalancerResp, err := d.sdkClient.DescribeLoadBalancer(describeLoadBalancerReq) + if err != nil { + return xerrors.Wrap(err, "failed to execute sdk request 'lb.DescribeLoadBalancer'") + } else { + d.logger.Logt("已查询到负载均衡器详情", describeLoadBalancerResp) + } + + // 查询监听器列表 + // REF: https://docs.jdcloud.com/cn/load-balancer/api/describelisteners + listenerIds := make([]string, 0) + describeListenersPageNumber := 1 + describeListenersPageSize := 100 + for { + describeListenersReq := jdLbApi.NewDescribeListenersRequest(d.config.RegionId) + describeListenersReq.SetFilters([]jdCommon.Filter{{Name: "loadBalancerId", Values: []string{d.config.LoadbalancerId}}}) + describeListenersReq.SetPageSize(describeListenersPageNumber) + describeListenersReq.SetPageSize(describeListenersPageSize) + describeListenersResp, err := d.sdkClient.DescribeListeners(describeListenersReq) + if err != nil { + return xerrors.Wrap(err, "failed to execute sdk request 'lb.DescribeListeners'") + } + + for _, listener := range describeListenersResp.Result.Listeners { + if strings.EqualFold(listener.Protocol, "https") || strings.EqualFold(listener.Protocol, "tls") { + listenerIds = append(listenerIds, listener.ListenerId) + } + } + + if len(describeListenersResp.Result.Listeners) < int(describeListenersPageSize) { + break + } else { + describeListenersPageNumber++ + } + } + + // 遍历更新监听器证书 + if len(listenerIds) == 0 { + return errors.New("listener not found") + } else { + d.logger.Logt("已查询到负载均衡器下的全部 HTTPS/TLS 监听器", listenerIds) + + var errs []error + + for _, listenerId := range listenerIds { + if err := d.updateListenerCertificate(ctx, listenerId, cloudCertId); err != nil { + errs = append(errs, err) + } + } + + if len(errs) > 0 { + return errors.Join(errs...) + } + } + + return nil +} + +func (d *DeployerProvider) deployToListener(ctx context.Context, cloudCertId string) error { + if d.config.ListenerId == "" { + return errors.New("config `listenerId` is required") + } + + // 更新监听器证书 + if err := d.updateListenerCertificate(ctx, d.config.ListenerId, cloudCertId); err != nil { + return err + } + + return nil +} + +func (d *DeployerProvider) updateListenerCertificate(ctx context.Context, cloudListenerId string, cloudCertId string) error { + // 查询监听器详情 + // REF: https://docs.jdcloud.com/cn/load-balancer/api/describelistener + describeListenerReq := jdLbApi.NewDescribeListenerRequest(d.config.RegionId, cloudListenerId) + describeListenerResp, err := d.sdkClient.DescribeListener(describeListenerReq) + if err != nil { + return xerrors.Wrap(err, "failed to execute sdk request 'lb.DescribeListener'") + } else { + d.logger.Logt("已查询到监听器详情", describeListenerResp) + } + + if d.config.Domain == "" { + // 未指定 SNI,只需部署到监听器 + + // 修改监听器信息 + // REF: https://docs.jdcloud.com/cn/load-balancer/api/updatelistener + updateListenerReq := jdLbApi.NewUpdateListenerRequest(d.config.RegionId, cloudListenerId) + updateListenerReq.SetCertificateSpecs([]jdLbModel.CertificateSpec{{CertificateId: cloudCertId}}) + updateListenerResp, err := d.sdkClient.UpdateListener(updateListenerReq) + if err != nil { + return xerrors.Wrap(err, "failed to execute sdk request 'lb.UpdateListener'") + } else { + d.logger.Logt("已修改监听器信息", updateListenerResp) + } + } else { + // 指定 SNI,需部署到扩展证书 + + extCertSpecs := slices.Filter(describeListenerResp.Result.Listener.ExtensionCertificateSpecs, func(extCertSpec jdLbModel.ExtensionCertificateSpec) bool { + return extCertSpec.Domain == d.config.Domain + }) + if len(extCertSpecs) == 0 { + return errors.New("extension certificate spec not found") + } + + // 批量修改扩展证书 + // REF: https://docs.jdcloud.com/cn/load-balancer/api/updatelistenercertificates + updateListenerCertificatesReq := jdLbApi.NewUpdateListenerCertificatesRequest( + d.config.RegionId, + cloudListenerId, + slices.Map(extCertSpecs, func(extCertSpec jdLbModel.ExtensionCertificateSpec) jdLbModel.ExtCertificateUpdateSpec { + return jdLbModel.ExtCertificateUpdateSpec{ + CertificateBindId: extCertSpec.CertificateBindId, + CertificateId: &cloudCertId, + Domain: &extCertSpec.Domain, + } + }), + ) + updateListenerCertificatesResp, err := d.sdkClient.UpdateListenerCertificates(updateListenerCertificatesReq) + if err != nil { + return xerrors.Wrap(err, "failed to execute sdk request 'lb.UpdateListenerCertificates'") + } else { + d.logger.Logt("已批量修改扩展证书", updateListenerCertificatesResp) + } + } + + return nil +} + +func createSdkClient(accessKeyId, accessKeySecret string) (*jdLbClient.LbClient, error) { + clientCredentials := jdCore.NewCredentials(accessKeyId, accessKeySecret) + client := jdLbClient.NewLbClient(clientCredentials) + return client, nil +} diff --git a/internal/pkg/core/deployer/providers/jdcloud-alb/jdcloud_alb_test.go b/internal/pkg/core/deployer/providers/jdcloud-alb/jdcloud_alb_test.go new file mode 100644 index 00000000..9c9cc9cc --- /dev/null +++ b/internal/pkg/core/deployer/providers/jdcloud-alb/jdcloud_alb_test.go @@ -0,0 +1,118 @@ +package jdcloudalb_test + +import ( + "context" + "flag" + "fmt" + "os" + "strings" + "testing" + + provider "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/jdcloud-alb" +) + +var ( + fInputCertPath string + fInputKeyPath string + fAccessKeyId string + fAccessKeySecret string + fRegionId string + fLoadbalancerId string + fListenerId string +) + +func init() { + argsPrefix := "CERTIMATE_DEPLOYER_JDCLOUDALB_" + + flag.StringVar(&fInputCertPath, argsPrefix+"INPUTCERTPATH", "", "") + flag.StringVar(&fInputKeyPath, argsPrefix+"INPUTKEYPATH", "", "") + flag.StringVar(&fAccessKeyId, argsPrefix+"ACCESSKEYID", "", "") + flag.StringVar(&fAccessKeySecret, argsPrefix+"ACCESSKEYSECRET", "", "") + flag.StringVar(&fRegionId, argsPrefix+"REGIONID", "", "") + flag.StringVar(&fLoadbalancerId, argsPrefix+"LOADBALANCERID", "", "") + flag.StringVar(&fListenerId, argsPrefix+"LISTENERID", "", "") +} + +/* +Shell command to run this test: + + go test -v ./jdcloud_alb_test.go -args \ + --CERTIMATE_DEPLOYER_JDCLOUDALB_INPUTCERTPATH="/path/to/your-input-cert.pem" \ + --CERTIMATE_DEPLOYER_JDCLOUDALB_INPUTKEYPATH="/path/to/your-input-key.pem" \ + --CERTIMATE_DEPLOYER_JDCLOUDALB_ACCESSKEYID="your-access-key-id" \ + --CERTIMATE_DEPLOYER_JDCLOUDALB_ACCESSKEYSECRET="your-secret-access-key" \ + --CERTIMATE_DEPLOYER_JDCLOUDALB_REGION_ID="cn-north-1" \ + --CERTIMATE_DEPLOYER_JDCLOUDALB_LOADBALANCERID="your-alb-loadbalancer-id" \ + --CERTIMATE_DEPLOYER_JDCLOUDALB_LISTENERID="your-alb-listener-id" +*/ +func TestDeploy(t *testing.T) { + flag.Parse() + + t.Run("Deploy_ToLoadbalancer", func(t *testing.T) { + t.Log(strings.Join([]string{ + "args:", + fmt.Sprintf("INPUTCERTPATH: %v", fInputCertPath), + fmt.Sprintf("INPUTKEYPATH: %v", fInputKeyPath), + fmt.Sprintf("ACCESSKEYID: %v", fAccessKeyId), + fmt.Sprintf("ACCESSKEYSECRET: %v", fAccessKeySecret), + fmt.Sprintf("REGIONID: %v", fRegionId), + fmt.Sprintf("LOADBALANCERID: %v", fLoadbalancerId), + }, "\n")) + + deployer, err := provider.NewDeployer(&provider.DeployerConfig{ + AccessKeyId: fAccessKeyId, + AccessKeySecret: fAccessKeySecret, + RegionId: fRegionId, + ResourceType: provider.RESOURCE_TYPE_LOADBALANCER, + LoadbalancerId: fLoadbalancerId, + }) + if err != nil { + t.Errorf("err: %+v", err) + return + } + + fInputCertData, _ := os.ReadFile(fInputCertPath) + fInputKeyData, _ := os.ReadFile(fInputKeyPath) + res, err := deployer.Deploy(context.Background(), string(fInputCertData), string(fInputKeyData)) + if err != nil { + t.Errorf("err: %+v", err) + return + } + + t.Logf("ok: %v", res) + }) + + t.Run("Deploy_ToListener", func(t *testing.T) { + t.Log(strings.Join([]string{ + "args:", + fmt.Sprintf("INPUTCERTPATH: %v", fInputCertPath), + fmt.Sprintf("INPUTKEYPATH: %v", fInputKeyPath), + fmt.Sprintf("ACCESSKEYID: %v", fAccessKeyId), + fmt.Sprintf("ACCESSKEYSECRET: %v", fAccessKeySecret), + fmt.Sprintf("REGIONID: %v", fRegionId), + fmt.Sprintf("LISTENERID: %v", fListenerId), + }, "\n")) + + deployer, err := provider.NewDeployer(&provider.DeployerConfig{ + AccessKeyId: fAccessKeyId, + AccessKeySecret: fAccessKeySecret, + RegionId: fRegionId, + ResourceType: provider.RESOURCE_TYPE_LISTENER, + ListenerId: fListenerId, + }) + if err != nil { + t.Errorf("err: %+v", err) + return + } + + fInputCertData, _ := os.ReadFile(fInputCertPath) + fInputKeyData, _ := os.ReadFile(fInputKeyPath) + res, err := deployer.Deploy(context.Background(), string(fInputCertData), string(fInputKeyData)) + if err != nil { + t.Errorf("err: %+v", err) + return + } + + t.Logf("ok: %v", res) + }) +} diff --git a/internal/pkg/core/deployer/providers/jdcloud-cdn/jdcloud_cdn_test.go b/internal/pkg/core/deployer/providers/jdcloud-cdn/jdcloud_cdn_test.go index b95636dc..2d2f7ed0 100644 --- a/internal/pkg/core/deployer/providers/jdcloud-cdn/jdcloud_cdn_test.go +++ b/internal/pkg/core/deployer/providers/jdcloud-cdn/jdcloud_cdn_test.go @@ -20,7 +20,7 @@ var ( ) func init() { - argsPrefix := "CERTIMATE_DEPLOYER_BAIDUCLOUDCDN_" + argsPrefix := "CERTIMATE_DEPLOYER_JDCLOUDCDN_" flag.StringVar(&fInputCertPath, argsPrefix+"INPUTCERTPATH", "", "") flag.StringVar(&fInputKeyPath, argsPrefix+"INPUTKEYPATH", "", "") diff --git a/internal/pkg/core/deployer/providers/jdcloud-live/jdcloud_live_test.go b/internal/pkg/core/deployer/providers/jdcloud-live/jdcloud_live_test.go index 510198cc..076202b5 100644 --- a/internal/pkg/core/deployer/providers/jdcloud-live/jdcloud_live_test.go +++ b/internal/pkg/core/deployer/providers/jdcloud-live/jdcloud_live_test.go @@ -20,7 +20,7 @@ var ( ) func init() { - argsPrefix := "CERTIMATE_DEPLOYER_BAIDUCLOUDCDN_" + argsPrefix := "CERTIMATE_DEPLOYER_JDCLOUDLIVE_" flag.StringVar(&fInputCertPath, argsPrefix+"INPUTCERTPATH", "", "") flag.StringVar(&fInputKeyPath, argsPrefix+"INPUTKEYPATH", "", "") diff --git a/internal/pkg/core/deployer/providers/tencentcloud-clb/tencentcloud_clb.go b/internal/pkg/core/deployer/providers/tencentcloud-clb/tencentcloud_clb.go index acaf84b2..521f3e34 100644 --- a/internal/pkg/core/deployer/providers/tencentcloud-clb/tencentcloud_clb.go +++ b/internal/pkg/core/deployer/providers/tencentcloud-clb/tencentcloud_clb.go @@ -138,7 +138,7 @@ func (d *DeployerProvider) deployViaSslService(ctx context.Context, cloudCertId // 未指定 SNI,只需部署到监听器 deployCertificateInstanceReq.InstanceIdList = common.StringPtrs([]string{fmt.Sprintf("%s|%s", d.config.LoadbalancerId, d.config.ListenerId)}) } else { - // 指定 SNI,需部署到域名(支持泛域名) + // 指定 SNI,需部署到域名 deployCertificateInstanceReq.InstanceIdList = common.StringPtrs([]string{fmt.Sprintf("%s|%s|%s", d.config.LoadbalancerId, d.config.ListenerId, d.config.Domain)}) } deployCertificateInstanceResp, err := d.sdkClients.ssl.DeployCertificateInstance(deployCertificateInstanceReq) diff --git a/ui/src/components/workflow/node/DeployNodeConfigForm.tsx b/ui/src/components/workflow/node/DeployNodeConfigForm.tsx index 3ae859b6..f62191d0 100644 --- a/ui/src/components/workflow/node/DeployNodeConfigForm.tsx +++ b/ui/src/components/workflow/node/DeployNodeConfigForm.tsx @@ -38,6 +38,7 @@ import DeployNodeConfigFormGcoreCDNConfig from "./DeployNodeConfigFormGcoreCDNCo import DeployNodeConfigFormHuaweiCloudCDNConfig from "./DeployNodeConfigFormHuaweiCloudCDNConfig"; import DeployNodeConfigFormHuaweiCloudELBConfig from "./DeployNodeConfigFormHuaweiCloudELBConfig"; import DeployNodeConfigFormHuaweiCloudWAFConfig from "./DeployNodeConfigFormHuaweiCloudWAFConfig"; +import DeployNodeConfigFormJDCloudALBConfig from "./DeployNodeConfigFormJDCloudALBConfig"; import DeployNodeConfigFormJDCloudCDNConfig from "./DeployNodeConfigFormJDCloudCDNConfig"; import DeployNodeConfigFormJDCloudLiveConfig from "./DeployNodeConfigFormJDCloudLiveConfig"; import DeployNodeConfigFormKubernetesSecretConfig from "./DeployNodeConfigFormKubernetesSecretConfig"; @@ -180,6 +181,8 @@ const DeployNodeConfigForm = forwardRef; case DEPLOY_PROVIDERS.HUAWEICLOUD_WAF: return ; + case DEPLOY_PROVIDERS.JDCLOUD_ALB: + return ; case DEPLOY_PROVIDERS.JDCLOUD_CDN: return ; case DEPLOY_PROVIDERS.JDCLOUD_LIVE: diff --git a/ui/src/components/workflow/node/DeployNodeConfigFormJDCloudALBConfig.tsx b/ui/src/components/workflow/node/DeployNodeConfigFormJDCloudALBConfig.tsx new file mode 100644 index 00000000..f54477ce --- /dev/null +++ b/ui/src/components/workflow/node/DeployNodeConfigFormJDCloudALBConfig.tsx @@ -0,0 +1,142 @@ +import { useTranslation } from "react-i18next"; +import { Form, type FormInstance, Input, Select } from "antd"; +import { createSchemaFieldRule } from "antd-zod"; +import { z } from "zod"; + +import Show from "@/components/Show"; +import { validDomainName } from "@/utils/validators"; + +type DeployNodeConfigFormJDCloudALBConfigFieldValues = Nullish<{ + resourceType: string; + regionId: string; + loadbalancerId?: string; + listenerId?: string; + domain?: string; +}>; + +export type DeployNodeConfigFormJDCloudALBConfigProps = { + form: FormInstance; + formName: string; + disabled?: boolean; + initialValues?: DeployNodeConfigFormJDCloudALBConfigFieldValues; + onValuesChange?: (values: DeployNodeConfigFormJDCloudALBConfigFieldValues) => void; +}; + +const RESOURCE_TYPE_LOADBALANCER = "loadbalancer" as const; +const RESOURCE_TYPE_LISTENER = "listener" as const; + +const initFormModel = (): DeployNodeConfigFormJDCloudALBConfigFieldValues => { + return {}; +}; + +const DeployNodeConfigFormJDCloudALBConfig = ({ + form: formInst, + formName, + disabled, + initialValues, + onValuesChange, +}: DeployNodeConfigFormJDCloudALBConfigProps) => { + const { t } = useTranslation(); + + const formSchema = z.object({ + resourceType: z.union([z.literal(RESOURCE_TYPE_LOADBALANCER), z.literal(RESOURCE_TYPE_LISTENER)], { + message: t("workflow_node.deploy.form.jdcloud_alb_resource_type.placeholder"), + }), + regionId: z + .string({ message: t("workflow_node.deploy.form.jdcloud_alb_region_id.placeholder") }) + .nonempty(t("workflow_node.deploy.form.jdcloud_alb_region_id.placeholder")) + .trim(), + loadbalancerId: z + .string() + .max(64, t("common.errmsg.string_max", { max: 64 })) + .trim() + .nullish() + .refine((v) => fieldResourceType !== RESOURCE_TYPE_LOADBALANCER || !!v?.trim(), t("workflow_node.deploy.form.jdcloud_alb_loadbalancer_id.placeholder")), + listenerId: z + .string() + .max(64, t("common.errmsg.string_max", { max: 64 })) + .trim() + .nullish() + .refine((v) => fieldResourceType !== RESOURCE_TYPE_LISTENER || !!v?.trim(), t("workflow_node.deploy.form.jdcloud_alb_listener_id.placeholder")), + domain: z + .string() + .nullish() + .refine((v) => { + if (![RESOURCE_TYPE_LOADBALANCER, RESOURCE_TYPE_LISTENER].includes(fieldResourceType)) return true; + return !v || validDomainName(v!, { allowWildcard: true }); + }, t("common.errmsg.domain_invalid")), + }); + const formRule = createSchemaFieldRule(formSchema); + + const fieldResourceType = Form.useWatch("resourceType", formInst); + + const handleFormChange = (_: unknown, values: z.infer) => { + onValuesChange?.(values); + }; + + return ( +
+ + + + + } + > + + + + + } + > + + + + + + } + > + + + + + + } + > + + + +
+ ); +}; + +export default DeployNodeConfigFormJDCloudALBConfig; diff --git a/ui/src/domain/provider.ts b/ui/src/domain/provider.ts index a2b09baf..e2475247 100644 --- a/ui/src/domain/provider.ts +++ b/ui/src/domain/provider.ts @@ -221,6 +221,7 @@ export const DEPLOY_PROVIDERS = Object.freeze({ HUAWEICLOUD_CDN: `${ACCESS_PROVIDERS.HUAWEICLOUD}-cdn`, HUAWEICLOUD_ELB: `${ACCESS_PROVIDERS.HUAWEICLOUD}-elb`, HUAWEICLOUD_WAF: `${ACCESS_PROVIDERS.HUAWEICLOUD}-waf`, + JDCLOUD_ALB: `${ACCESS_PROVIDERS.JDCLOUD}-alb`, JDCLOUD_CDN: `${ACCESS_PROVIDERS.JDCLOUD}-cdn`, JDCLOUD_LIVE: `${ACCESS_PROVIDERS.JDCLOUD}-live`, KUBERNETES_SECRET: `${ACCESS_PROVIDERS.KUBERNETES}-secret`, @@ -309,6 +310,7 @@ export const deployProvidersMap: Maphttps://console-intl.huaweicloud.com/console/#/waf/domain/list", + "workflow_node.deploy.form.jdcloud_alb_resource_type.label": "Resource type", + "workflow_node.deploy.form.jdcloud_alb_resource_type.placeholder": "Please select resource type", + "workflow_node.deploy.form.jdcloud_alb_resource_type.option.loadbalancer.label": "ALB load balancer", + "workflow_node.deploy.form.jdcloud_alb_resource_type.option.listener.label": "ALB listener", + "workflow_node.deploy.form.jdcloud_alb_region_id.label": "JD Cloud ALB region ID", + "workflow_node.deploy.form.jdcloud_alb_region_id.placeholder": "Please enter JD Cloud ALB region ID (e.g. cn-north-1)", + "workflow_node.deploy.form.jdcloud_alb_region_id.tooltip": "For more information, see https://docs.jdcloud.com/en/common-declaration/api/introduction", + "workflow_node.deploy.form.jdcloud_alb_loadbalancer_id.label": "JD Cloud ALB load balancer ID", + "workflow_node.deploy.form.jdcloud_alb_loadbalancer_id.placeholder": "Please enter JD Cloud ALB load balancer ID", + "workflow_node.deploy.form.jdcloud_alb_loadbalancer_id.tooltip": "For more information, see https://cns-console.jdcloud.com/host/loadBalance/list", + "workflow_node.deploy.form.jdcloud_alb_listener_id.label": "JD Cloud ALB listener ID", + "workflow_node.deploy.form.jdcloud_alb_listener_id.placeholder": "Please enter JD Cloud ALB listener ID", + "workflow_node.deploy.form.jdcloud_alb_listener_id.tooltip": "For more information, see https://cns-console.jdcloud.com/host/loadBalance/list", + "workflow_node.deploy.form.jdcloud_alb_snidomain.label": "JD Cloud ALB SNI domain (Optional)", + "workflow_node.deploy.form.jdcloud_alb_snidomain.placeholder": "Please enter JD Cloud ALB SNI domain name", + "workflow_node.deploy.form.jdcloud_alb_snidomain.tooltip": "For more information, see https://cns-console.jdcloud.com/host/loadBalance/list", "workflow_node.deploy.form.jdcloud_cdn_domain.label": "JD Cloud CDN domain", "workflow_node.deploy.form.jdcloud_cdn_domain.placeholder": "Please enter JD Cloud CDN domain name", "workflow_node.deploy.form.jdcloud_cdn_domain.tooltip": "For more information, see https://cdn-console.jdcloud.com/", diff --git a/ui/src/i18n/locales/zh/nls.provider.json b/ui/src/i18n/locales/zh/nls.provider.json index 0d8e2911..dfa3022c 100644 --- a/ui/src/i18n/locales/zh/nls.provider.json +++ b/ui/src/i18n/locales/zh/nls.provider.json @@ -54,6 +54,7 @@ "provider.huaweicloud.elb": "华为云 - 弹性负载均衡 ELB", "provider.huaweicloud.waf": "华为云 - Web 应用防火墙 WAF", "provider.jdcloud": "京东云", + "provider.jdcloud.alb": "京东云 - 应用负载均衡 ALB", "provider.jdcloud.cdn": "京东云 - 内容分发网络 CDN", "provider.jdcloud.dns": "京东云 - 云解析 DNS", "provider.jdcloud.live": "京东云 - 视频直播", diff --git a/ui/src/i18n/locales/zh/nls.workflow.nodes.json b/ui/src/i18n/locales/zh/nls.workflow.nodes.json index a7331d08..0e68333b 100644 --- a/ui/src/i18n/locales/zh/nls.workflow.nodes.json +++ b/ui/src/i18n/locales/zh/nls.workflow.nodes.json @@ -104,7 +104,7 @@ "workflow_node.deploy.form.aliyun_alb_listener_id.placeholder": "请输入阿里云 ALB 监听器 ID", "workflow_node.deploy.form.aliyun_alb_listener_id.tooltip": "这是什么?请参阅 https://slb.console.aliyun.com/alb", "workflow_node.deploy.form.aliyun_alb_snidomain.label": "阿里云 ALB 扩展域名(可选)", - "workflow_node.deploy.form.aliyun_alb_snidomain.placeholder": "请输入阿里云 ALB 扩展域名", + "workflow_node.deploy.form.aliyun_alb_snidomain.placeholder": "请输入阿里云 ALB 扩展域名(支持泛域名)", "workflow_node.deploy.form.aliyun_alb_snidomain.tooltip": "这是什么?请参阅 https://slb.console.aliyun.com/alb

不填写时,将替换监听器的默认证书。", "workflow_node.deploy.form.aliyun_cas_deploy.guide": "小贴士:由于阿里云证书部署任务是异步的,此节点若执行成功仅代表已创建部署任务,实际部署结果需要你自行前往阿里云控制台查询。", "workflow_node.deploy.form.aliyun_cas_deploy_region.label": "阿里云 CAS 服务地域", @@ -136,7 +136,7 @@ "workflow_node.deploy.form.aliyun_clb_listener_port.placeholder": "请输入阿里云 CLB 监听端口", "workflow_node.deploy.form.aliyun_clb_listener_port.tooltip": "这是什么?请参阅 https://slb.console.aliyun.com/clb", "workflow_node.deploy.form.aliyun_clb_snidomain.label": "阿里云 CLB 扩展域名(可选)", - "workflow_node.deploy.form.aliyun_clb_snidomain.placeholder": "请输入阿里云 CLB 扩展域名", + "workflow_node.deploy.form.aliyun_clb_snidomain.placeholder": "请输入阿里云 CLB 扩展域名(支持泛域名)", "workflow_node.deploy.form.aliyun_clb_snidomain.tooltip": "这是什么?请参阅 https://slb.console.aliyun.com/clb

不填写时,将替换监听器的默认证书。", "workflow_node.deploy.form.aliyun_cdn_domain.label": "阿里云 CDN 加速域名", "workflow_node.deploy.form.aliyun_cdn_domain.placeholder": "请输入阿里云 CDN 加速域名(支持泛域名)", @@ -267,6 +267,22 @@ "workflow_node.deploy.form.huaweicloud_waf_domain.label": "华为云 WAF 防护域名", "workflow_node.deploy.form.huaweicloud_waf_domain.placeholder": "请输入华为云 WAF 防护域名(支持泛域名)", "workflow_node.deploy.form.huaweicloud_waf_domain.tooltip": "这是什么?请参阅 https://console.huaweicloud.com/console/#/waf/domain/list", + "workflow_node.deploy.form.jdcloud_alb_resource_type.label": "证书替换方式", + "workflow_node.deploy.form.jdcloud_alb_resource_type.placeholder": "请选择证书替换方式", + "workflow_node.deploy.form.jdcloud_alb_resource_type.option.loadbalancer.label": "替换指定负载均衡器下的全部 HTTPS/TLS 监听的证书", + "workflow_node.deploy.form.jdcloud_alb_resource_type.option.listener.label": "替换指定负载均衡监听器的证书", + "workflow_node.deploy.form.jdcloud_alb_region_id.label": "京东云 ALB 服务地域 ID", + "workflow_node.deploy.form.jdcloud_alb_region_id.placeholder": "请输入京东云 ALB 服务地域 ID(例如:cn-north-1", + "workflow_node.deploy.form.jdcloud_alb_region_id.tooltip": "这是什么?请参阅 https://docs.jdcloud.com/cn/common-declaration/api/introduction", + "workflow_node.deploy.form.jdcloud_alb_loadbalancer_id.label": "京东云 ALB 负载均衡器 ID", + "workflow_node.deploy.form.jdcloud_alb_loadbalancer_id.placeholder": "请输入京东云 ALB 负载均衡器 ID", + "workflow_node.deploy.form.jdcloud_alb_loadbalancer_id.tooltip": "这是什么?请参阅 https://cns-console.jdcloud.com/host/loadBalance/list", + "workflow_node.deploy.form.jdcloud_alb_listener_id.label": "京东云 ALB 监听器 ID", + "workflow_node.deploy.form.jdcloud_alb_listener_id.placeholder": "请输入京东云 ALB 监听器 ID", + "workflow_node.deploy.form.jdcloud_alb_listener_id.tooltip": "这是什么?请参阅 https://cns-console.jdcloud.com/host/loadBalance/list", + "workflow_node.deploy.form.jdcloud_alb_snidomain.label": "京东云 ALB 扩展域名(可选)", + "workflow_node.deploy.form.jdcloud_alb_snidomain.placeholder": "请输入京东云 ALB 扩展域名(支持泛域名)", + "workflow_node.deploy.form.jdcloud_alb_snidomain.tooltip": "这是什么?请参阅 https://cns-console.jdcloud.com/host/loadBalance/list

不填写时,将替换监听器的默认证书。", "workflow_node.deploy.form.jdcloud_cdn_domain.label": "京东云 CDN 加速域名", "workflow_node.deploy.form.jdcloud_cdn_domain.placeholder": "请输入京东云 CDN 加速域名(支持泛域名)", "workflow_node.deploy.form.jdcloud_cdn_domain.tooltip": "这是什么?请参阅 https://cdn-console.jdcloud.com/", From c492e2de2882e8f5ec9ebd1b025ca222d98fc426 Mon Sep 17 00:00:00 2001 From: Fu Diwei Date: Thu, 20 Feb 2025 21:02:24 +0800 Subject: [PATCH 24/34] feat: add aliyun vod deployer --- README.md | 48 +++++----- README_EN.md | 48 +++++----- go.mod | 4 + go.sum | 10 ++ internal/deployer/providers.go | 12 ++- internal/domain/provider.go | 1 + .../providers/aliyun-live/aliyun_live_test.go | 5 + .../providers/aliyun-vod/aliyun_vod.go | 95 +++++++++++++++++++ .../providers/aliyun-vod/aliyun_vod_test.go | 80 ++++++++++++++++ .../workflow/node/DeployNodeConfigForm.tsx | 3 + .../DeployNodeConfigFormAliyunVODConfig.tsx | 79 +++++++++++++++ ui/src/domain/provider.ts | 2 + ui/src/i18n/locales/en/nls.provider.json | 1 + .../i18n/locales/en/nls.workflow.nodes.json | 6 ++ ui/src/i18n/locales/zh/nls.provider.json | 1 + .../i18n/locales/zh/nls.workflow.nodes.json | 6 ++ 16 files changed, 352 insertions(+), 49 deletions(-) create mode 100644 internal/pkg/core/deployer/providers/aliyun-vod/aliyun_vod.go create mode 100644 internal/pkg/core/deployer/providers/aliyun-vod/aliyun_vod_test.go create mode 100644 ui/src/components/workflow/node/DeployNodeConfigFormAliyunVODConfig.tsx diff --git a/README.md b/README.md index 3aa3f158..59dcc6a9 100644 --- a/README.md +++ b/README.md @@ -119,30 +119,30 @@ make local.run [展开查看] -| 提供商 | 备注 | -| :-------------------------------------- | :----------------------------------------------------------------------- | -| 本地部署 | 可部署到本地服务器 | -| SSH 部署 | 可部署到远程服务器(通过 SSH+SFTP/SCP) | -| Webhook 回调 | 可部署到 Webhook | -| [Kubernetes](https://kubernetes.io/) | 可部署到 Kubernetes Secret | -| [阿里云](https://www.aliyun.com/) | 可部署到阿里云 OSS、CDN、DCDN、ESA、SLB(CLB/ALB/NLB)、WAF、Live 等服务 | -| [腾讯云](https://cloud.tencent.com/) | 可部署到腾讯云 COS、CDN、ECDN、EdgeOne、CLB、WAF、CSS 等服务 | -| [百度智能云](https://cloud.baidu.com/) | 可部署到百度智能云 CDN 等服务 | -| [华为云](https://www.huaweicloud.com/) | 可部署到华为云 CDN、ELB、WAF 等服务 | -| [火山引擎](https://www.volcengine.com/) | 可部署到火山引擎 TOS、CDN、DCDN、CLB、ImageX、Live 等服务 | -| [京东云](https://www.jdcloud.com/) | 可部署到京东云 CDN、ALB、视频直播等服务 | -| [七牛云](https://www.qiniu.com/) | 可部署到七牛云 CDN、直播云等服务 | -| [白山云](https://www.baishan.com/) | 可部署到白山云 CDN | -| [多吉云](https://www.dogecloud.com/) | 可部署到多吉云 CDN | -| [优刻得](https://www.ucloud.cn/) | 可部署到优刻得 US3、UCDN 等服务 | -| [雷池](https://waf-ce.chaitin.cn/) | 可部署到雷池 WAF | -| [宝塔面板](https://www.bt.cn/) | 可部署到宝塔面板 | -| [AWS](https://aws.amazon.com/) | 可部署到 AWS CloudFront | -| [BytePlus](https://www.byteplus.com/) | 可部署到 BytePlus CDN | -| [CacheFly](https://www.cachefly.com/) | 可部署到 CacheFly CDN | -| [Cdnfly](https://www.cdnfly.cn/) | 可部署到 Cdnfly CDN | -| [Edgio](https://edg.io/) | 可部署到 Edgio Applications | -| [Gcore](https://gcore.com/) | 可部署到 Gcore CDN | +| 提供商 | 备注 | +| :-------------------------------------- | :---------------------------------------------------------------------------- | +| 本地部署 | 可部署到本地服务器 | +| SSH 部署 | 可部署到远程服务器(通过 SSH+SFTP/SCP) | +| Webhook 回调 | 可部署到 Webhook | +| [Kubernetes](https://kubernetes.io/) | 可部署到 Kubernetes Secret | +| [阿里云](https://www.aliyun.com/) | 可部署到阿里云 OSS、CDN、DCDN、ESA、SLB(CLB/ALB/NLB)、WAF、Live、VOD 等服务 | +| [腾讯云](https://cloud.tencent.com/) | 可部署到腾讯云 COS、CDN、ECDN、EdgeOne、CLB、WAF、CSS 等服务 | +| [百度智能云](https://cloud.baidu.com/) | 可部署到百度智能云 CDN 等服务 | +| [华为云](https://www.huaweicloud.com/) | 可部署到华为云 CDN、ELB、WAF 等服务 | +| [火山引擎](https://www.volcengine.com/) | 可部署到火山引擎 TOS、CDN、DCDN、CLB、ImageX、Live 等服务 | +| [京东云](https://www.jdcloud.com/) | 可部署到京东云 CDN、ALB、视频直播等服务 | +| [七牛云](https://www.qiniu.com/) | 可部署到七牛云 CDN、直播云等服务 | +| [白山云](https://www.baishan.com/) | 可部署到白山云 CDN | +| [多吉云](https://www.dogecloud.com/) | 可部署到多吉云 CDN | +| [优刻得](https://www.ucloud.cn/) | 可部署到优刻得 US3、UCDN 等服务 | +| [雷池](https://waf-ce.chaitin.cn/) | 可部署到雷池 WAF | +| [宝塔面板](https://www.bt.cn/) | 可部署到宝塔面板 | +| [AWS](https://aws.amazon.com/) | 可部署到 AWS CloudFront | +| [BytePlus](https://www.byteplus.com/) | 可部署到 BytePlus CDN | +| [CacheFly](https://www.cachefly.com/) | 可部署到 CacheFly CDN | +| [Cdnfly](https://www.cdnfly.cn/) | 可部署到 Cdnfly CDN | +| [Edgio](https://edg.io/) | 可部署到 Edgio Applications | +| [Gcore](https://gcore.com/) | 可部署到 Gcore CDN | diff --git a/README_EN.md b/README_EN.md index c9a5bdf4..7b11ac3a 100644 --- a/README_EN.md +++ b/README_EN.md @@ -118,30 +118,30 @@ The following hosting providers are supported: [Fold/Unfold to view ...] -| Provider | Remarks | -| :---------------------------------------------- | :------------------------------------------------------------------------------- | -| Local | Supports deployment to local servers | -| SSH | Supports deployment to remote servers (via SSH+SFTP/SCP) | -| Webhook | Supports deployment to Webhook | -| [Kubernetes](https://kubernetes.io/) | Supports deployment to Kubernetes Secret | -| [Alibaba Cloud](https://www.alibabacloud.com/) | Supports deployment to Alibaba Cloud OSS, CDN, DCDN, SLB(CLB/ALB/NLB), WAF, Live | -| [Tencent Cloud](https://www.tencentcloud.com/) | Supports deployment to Tencent Cloud COS, CDN, ECDN, EdgeOne, CLB, WAF, CSS | -| [Baidu AI Cloud](https://intl.cloud.baidu.com/) | Supports deployment to Baidu AI CLoud CDN | -| [Huawei Cloud](https://www.huaweicloud.com/) | Supports deployment to Huawei Cloud CDN, ELB, WAF | -| [Volcengine](https://www.volcengine.com/) | Supports deployment to Volcengine TOS, CDN, DCDN, CLB, ImageX, Live | -| [JD Cloud](https://www.jdcloud.com/) | Supports deployment to JD Cloud CDN, ALB, Live Video | -| [Qiniu Cloud](https://www.qiniu.com/) | Supports deployment to Qiniu Cloud CDN, Pili | -| [Baishan Cloud](https://intl.baishancloud.com/) | Supports deployment to Baishan Cloud CDN | -| [Doge Cloud](https://www.dogecloud.com/) | Supports deployment to Doge Cloud CDN | -| [UCloud](https://www.ucloud-global.com/) | Supports deployment to UCloud US3, UCDN | -| [SafeLine](https://waf.chaitin.com/) | Supports deployment to SafeLine WAF | -| [BaoTa Panel](https://www.bt.cn/) | Supports deployment to BaoTa Panel sites | -| [AWS](https://aws.amazon.com/) | Supports deployment to AWS CloudFront | -| [BytePlus](https://www.byteplus.com/) | Supports deployment to BytePlus CDN | -| [CacheFly](https://www.cachefly.com/) | Supports deployment to CacheFly CDN | -| [Cdnfly](https://www.cdnfly.cn/) | Supports deployment to Cdnfly CDN | -| [Edgio](https://edg.io/) | Supports deployment to Edgio Applications | -| [Gcore](https://gcore.com/) | Supports deployment to Gcore CDN | +| Provider | Remarks | +| :---------------------------------------------- | :------------------------------------------------------------------------------------ | +| Local | Supports deployment to local servers | +| SSH | Supports deployment to remote servers (via SSH+SFTP/SCP) | +| Webhook | Supports deployment to Webhook | +| [Kubernetes](https://kubernetes.io/) | Supports deployment to Kubernetes Secret | +| [Alibaba Cloud](https://www.alibabacloud.com/) | Supports deployment to Alibaba Cloud OSS, CDN, DCDN, SLB(CLB/ALB/NLB), WAF, Live, VOD | +| [Tencent Cloud](https://www.tencentcloud.com/) | Supports deployment to Tencent Cloud COS, CDN, ECDN, EdgeOne, CLB, WAF, CSS | +| [Baidu AI Cloud](https://intl.cloud.baidu.com/) | Supports deployment to Baidu AI CLoud CDN | +| [Huawei Cloud](https://www.huaweicloud.com/) | Supports deployment to Huawei Cloud CDN, ELB, WAF | +| [Volcengine](https://www.volcengine.com/) | Supports deployment to Volcengine TOS, CDN, DCDN, CLB, ImageX, Live | +| [JD Cloud](https://www.jdcloud.com/) | Supports deployment to JD Cloud CDN, ALB, Live Video | +| [Qiniu Cloud](https://www.qiniu.com/) | Supports deployment to Qiniu Cloud CDN, Pili | +| [Baishan Cloud](https://intl.baishancloud.com/) | Supports deployment to Baishan Cloud CDN | +| [Doge Cloud](https://www.dogecloud.com/) | Supports deployment to Doge Cloud CDN | +| [UCloud](https://www.ucloud-global.com/) | Supports deployment to UCloud US3, UCDN | +| [SafeLine](https://waf.chaitin.com/) | Supports deployment to SafeLine WAF | +| [BaoTa Panel](https://www.bt.cn/) | Supports deployment to BaoTa Panel sites | +| [AWS](https://aws.amazon.com/) | Supports deployment to AWS CloudFront | +| [BytePlus](https://www.byteplus.com/) | Supports deployment to BytePlus CDN | +| [CacheFly](https://www.cachefly.com/) | Supports deployment to CacheFly CDN | +| [Cdnfly](https://www.cdnfly.cn/) | Supports deployment to Cdnfly CDN | +| [Edgio](https://edg.io/) | Supports deployment to Edgio Applications | +| [Gcore](https://gcore.com/) | Supports deployment to Gcore CDN | diff --git a/go.mod b/go.mod index 5a1949f5..5f318638 100644 --- a/go.mod +++ b/go.mod @@ -62,7 +62,11 @@ require ( github.com/alibabacloud-go/tea-fileform v1.1.1 // indirect github.com/alibabacloud-go/tea-oss-sdk v1.1.3 // indirect github.com/alibabacloud-go/tea-oss-utils v1.1.0 // indirect + github.com/alibabacloud-go/tea-rpc v1.1.3 // indirect + github.com/alibabacloud-go/tea-rpc-utils v1.1.0 // indirect github.com/alibabacloud-go/tea-utils/v2 v2.0.7 // indirect + github.com/alibabacloud-go/vod-20170321 v1.0.1 // indirect + github.com/alibabacloud-go/vod-20170321/v4 v4.6.1 // indirect github.com/avast/retry-go v3.0.0+incompatible // indirect github.com/aws/aws-sdk-go-v2/service/route53 v1.48.1 // indirect github.com/blinkbean/dingtalk v1.1.3 // indirect diff --git a/go.sum b/go.sum index 1929c808..a87e7bda 100644 --- a/go.sum +++ b/go.sum @@ -171,6 +171,11 @@ github.com/alibabacloud-go/tea-oss-sdk v1.1.3 h1:EhAHI6edMeqgkZEqP7r4nc9iMWAUBKG github.com/alibabacloud-go/tea-oss-sdk v1.1.3/go.mod h1:yUnodpR3Bf2rudLE7V/Gft5txjJF30Pk+hH77K/Eab0= github.com/alibabacloud-go/tea-oss-utils v1.1.0 h1:y65crjjcZ2Pbb6UZtC2deuIZHDVTS3IaDWE7M9nVLRc= github.com/alibabacloud-go/tea-oss-utils v1.1.0/go.mod h1:PFCF12e9yEKyBUIn7X1IrF/pNjvxgkHy0CgxX4+xRuY= +github.com/alibabacloud-go/tea-rpc v1.1.3 h1:uuxAIT9PB6MMABQfV/EMSnREZjh629WXu+hmPNF1IAs= +github.com/alibabacloud-go/tea-rpc v1.1.3/go.mod h1:uwhvnxPK69jcAYkVyP1WCFhTh1oVLiibUseSUpC7L8g= +github.com/alibabacloud-go/tea-rpc-utils v1.1.0 h1:kIG7+9sMRaDzvCbXfowycEwFRdnLAglRFQ/dnc0/JNE= +github.com/alibabacloud-go/tea-rpc-utils v1.1.0/go.mod h1:rxGY+fLbm3Fj3oJpeU0hBTmz52Ux50nm7JL01tyPv9c= +github.com/alibabacloud-go/tea-utils v1.3.0/go.mod h1:EI/o33aBfj3hETm4RLiAxF/ThQdSngxrpF8rKUDJjPE= github.com/alibabacloud-go/tea-utils v1.3.1/go.mod h1:EI/o33aBfj3hETm4RLiAxF/ThQdSngxrpF8rKUDJjPE= github.com/alibabacloud-go/tea-utils v1.3.6/go.mod h1:EI/o33aBfj3hETm4RLiAxF/ThQdSngxrpF8rKUDJjPE= github.com/alibabacloud-go/tea-utils v1.4.5 h1:h0/6Xd2f3bPE4XHTvkpjwxowIwRCJAJOqY6Eq8f3zfA= @@ -186,12 +191,17 @@ github.com/alibabacloud-go/tea-xml v1.1.1/go.mod h1:Rq08vgCcCAjHyRi/M7xlHKUykZCE github.com/alibabacloud-go/tea-xml v1.1.2/go.mod h1:Rq08vgCcCAjHyRi/M7xlHKUykZCEtyBy9+DPF6GgEu8= github.com/alibabacloud-go/tea-xml v1.1.3 h1:7LYnm+JbOq2B+T/B0fHC4Ies4/FofC4zHzYtqw7dgt0= github.com/alibabacloud-go/tea-xml v1.1.3/go.mod h1:Rq08vgCcCAjHyRi/M7xlHKUykZCEtyBy9+DPF6GgEu8= +github.com/alibabacloud-go/vod-20170321 v1.0.1 h1:ZiBggVoJegu0Q3iarHZyveTOJJE0kUym6RCSLM9epoc= +github.com/alibabacloud-go/vod-20170321 v1.0.1/go.mod h1:eKaYMCAd22pgBFMz0Ci/o2l+UJSrq24LLSF/XyaTiac= +github.com/alibabacloud-go/vod-20170321/v4 v4.6.1 h1:6JTNq23lMo3wOui5qjpUJu2VKBgSHR4ArMgbKDOej7Q= +github.com/alibabacloud-go/vod-20170321/v4 v4.6.1/go.mod h1:TkgLKMSLu0qZN8Qdcu8svfHREyI64kjFvrp/GhrD4VQ= github.com/alibabacloud-go/waf-openapi-20211001/v5 v5.0.4 h1:Od0KgA73DyG9X2XFwuZZTkDv2pzA6B5mhYapyyca6QE= github.com/alibabacloud-go/waf-openapi-20211001/v5 v5.0.4/go.mod h1:DohGoS8BnMxHXghHebtjPP7+GMdxPsRN19T3nn2HcCU= github.com/aliyun/alibaba-cloud-sdk-go v1.63.83 h1:YBkf7H5CSgrlb3C1aWcpDt7Vk8UEGFPeD2OOirtt6IM= github.com/aliyun/alibaba-cloud-sdk-go v1.63.83/go.mod h1:SOSDHfe1kX91v3W5QiBsWSLqeLxImobbMX1mxrFHsVQ= github.com/aliyun/aliyun-oss-go-sdk v3.0.2+incompatible h1:8psS8a+wKfiLt1iVDX79F7Y6wUM49Lcha2FMXt4UM8g= github.com/aliyun/aliyun-oss-go-sdk v3.0.2+incompatible/go.mod h1:T/Aws4fEfogEE9v+HPhhw+CntffsBHJ8nXQCwKr0/g8= +github.com/aliyun/credentials-go v1.1.0/go.mod h1:ZXrrxv386Mj6z8NpihLKpexQE550m7j3LlyCvYub9aE= github.com/aliyun/credentials-go v1.1.2/go.mod h1:ozcZaMR5kLM7pwtCMEpVmQ242suV6qTJya2bDq4X1Tw= github.com/aliyun/credentials-go v1.3.1/go.mod h1:8jKYhQuDawt8x2+fusqa1Y6mPxemTsBEN04dgcAcYz0= github.com/aliyun/credentials-go v1.3.6/go.mod h1:1LxUuX7L5YrZUWzBrRyk0SwSdH4OmPrib8NVePL3fxM= diff --git a/internal/deployer/providers.go b/internal/deployer/providers.go index 24fc32f4..d053b93e 100644 --- a/internal/deployer/providers.go +++ b/internal/deployer/providers.go @@ -15,6 +15,7 @@ import ( pAliyunLive "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/aliyun-live" pAliyunNLB "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/aliyun-nlb" pAliyunOSS "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/aliyun-oss" + pAliyunVOD "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/aliyun-vod" pAliyunWAF "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/aliyun-waf" pAWSCloudFront "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/aws-cloudfront" pBaiduCloudCDN "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/baiducloud-cdn" @@ -66,7 +67,7 @@ func createDeployer(options *deployerOptions) (deployer.Deployer, error) { NOTICE: If you add new constant, please keep ASCII order. */ switch options.Provider { - case domain.DeployProviderTypeAliyunALB, domain.DeployProviderTypeAliyunCASDeploy, domain.DeployProviderTypeAliyunCDN, domain.DeployProviderTypeAliyunCLB, domain.DeployProviderTypeAliyunDCDN, domain.DeployProviderTypeAliyunESA, domain.DeployProviderTypeAliyunLive, domain.DeployProviderTypeAliyunNLB, domain.DeployProviderTypeAliyunOSS, domain.DeployProviderTypeAliyunWAF: + case domain.DeployProviderTypeAliyunALB, domain.DeployProviderTypeAliyunCASDeploy, domain.DeployProviderTypeAliyunCDN, domain.DeployProviderTypeAliyunCLB, domain.DeployProviderTypeAliyunDCDN, domain.DeployProviderTypeAliyunESA, domain.DeployProviderTypeAliyunLive, domain.DeployProviderTypeAliyunNLB, domain.DeployProviderTypeAliyunOSS, domain.DeployProviderTypeAliyunVOD, domain.DeployProviderTypeAliyunWAF: { access := domain.AccessConfigForAliyun{} if err := maps.Populate(options.ProviderAccessConfig, &access); err != nil { @@ -163,6 +164,15 @@ func createDeployer(options *deployerOptions) (deployer.Deployer, error) { }) return deployer, err + case domain.DeployProviderTypeAliyunVOD: + deployer, err := pAliyunVOD.NewDeployer(&pAliyunVOD.DeployerConfig{ + AccessKeyId: access.AccessKeyId, + AccessKeySecret: access.AccessKeySecret, + Region: maps.GetValueAsString(options.ProviderDeployConfig, "region"), + Domain: maps.GetValueAsString(options.ProviderDeployConfig, "domain"), + }) + return deployer, err + case domain.DeployProviderTypeAliyunWAF: deployer, err := pAliyunWAF.NewDeployer(&pAliyunWAF.DeployerConfig{ AccessKeyId: access.AccessKeyId, diff --git a/internal/domain/provider.go b/internal/domain/provider.go index 63528231..8485b357 100644 --- a/internal/domain/provider.go +++ b/internal/domain/provider.go @@ -112,6 +112,7 @@ const ( DeployProviderTypeAliyunLive = DeployProviderType("aliyun-live") DeployProviderTypeAliyunNLB = DeployProviderType("aliyun-nlb") DeployProviderTypeAliyunOSS = DeployProviderType("aliyun-oss") + DeployProviderTypeAliyunVOD = DeployProviderType("aliyun-vod") DeployProviderTypeAliyunWAF = DeployProviderType("aliyun-waf") DeployProviderTypeAWSCloudFront = DeployProviderType("aws-cloudfront") DeployProviderTypeBaiduCloudCDN = DeployProviderType("baiducloud-cdn") diff --git a/internal/pkg/core/deployer/providers/aliyun-live/aliyun_live_test.go b/internal/pkg/core/deployer/providers/aliyun-live/aliyun_live_test.go index 1c101d26..fcf01147 100644 --- a/internal/pkg/core/deployer/providers/aliyun-live/aliyun_live_test.go +++ b/internal/pkg/core/deployer/providers/aliyun-live/aliyun_live_test.go @@ -16,6 +16,7 @@ var ( fInputKeyPath string fAccessKeyId string fAccessKeySecret string + fRegion string fDomain string ) @@ -26,6 +27,7 @@ func init() { flag.StringVar(&fInputKeyPath, argsPrefix+"INPUTKEYPATH", "", "") flag.StringVar(&fAccessKeyId, argsPrefix+"ACCESSKEYID", "", "") flag.StringVar(&fAccessKeySecret, argsPrefix+"ACCESSKEYSECRET", "", "") + flag.StringVar(&fRegion, argsPrefix+"REGION", "", "") flag.StringVar(&fDomain, argsPrefix+"DOMAIN", "", "") } @@ -37,6 +39,7 @@ Shell command to run this test: --CERTIMATE_DEPLOYER_ALIYUNLIVE_INPUTKEYPATH="/path/to/your-input-key.pem" \ --CERTIMATE_DEPLOYER_ALIYUNLIVE_ACCESSKEYID="your-access-key-id" \ --CERTIMATE_DEPLOYER_ALIYUNLIVE_ACCESSKEYSECRET="your-access-key-secret" \ + --CERTIMATE_DEPLOYER_ALIYUNLIVE_REGION="cn-hangzhou" \ --CERTIMATE_DEPLOYER_ALIYUNLIVE_DOMAIN="example.com" */ func TestDeploy(t *testing.T) { @@ -49,12 +52,14 @@ func TestDeploy(t *testing.T) { fmt.Sprintf("INPUTKEYPATH: %v", fInputKeyPath), fmt.Sprintf("ACCESSKEYID: %v", fAccessKeyId), fmt.Sprintf("ACCESSKEYSECRET: %v", fAccessKeySecret), + fmt.Sprintf("REGION: %v", fRegion), fmt.Sprintf("DOMAIN: %v", fDomain), }, "\n")) deployer, err := provider.NewDeployer(&provider.DeployerConfig{ AccessKeyId: fAccessKeyId, AccessKeySecret: fAccessKeySecret, + Region: fRegion, Domain: fDomain, }) if err != nil { diff --git a/internal/pkg/core/deployer/providers/aliyun-vod/aliyun_vod.go b/internal/pkg/core/deployer/providers/aliyun-vod/aliyun_vod.go new file mode 100644 index 00000000..740fbb56 --- /dev/null +++ b/internal/pkg/core/deployer/providers/aliyun-vod/aliyun_vod.go @@ -0,0 +1,95 @@ +package aliyunvod + +import ( + "context" + "fmt" + "time" + + aliyunOpen "github.com/alibabacloud-go/darabonba-openapi/v2/client" + "github.com/alibabacloud-go/tea/tea" + aliyunVod "github.com/alibabacloud-go/vod-20170321/v4/client" + xerrors "github.com/pkg/errors" + + "github.com/usual2970/certimate/internal/pkg/core/deployer" + "github.com/usual2970/certimate/internal/pkg/core/logger" +) + +type DeployerConfig struct { + // 阿里云 AccessKeyId。 + AccessKeyId string `json:"accessKeyId"` + // 阿里云 AccessKeySecret。 + AccessKeySecret string `json:"accessKeySecret"` + // 阿里云地域。 + Region string `json:"region"` + // 点播加速域名(不支持泛域名)。 + Domain string `json:"domain"` +} + +type DeployerProvider struct { + config *DeployerConfig + logger logger.Logger + sdkClient *aliyunVod.Client +} + +var _ deployer.Deployer = (*DeployerProvider)(nil) + +func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { + if config == nil { + panic("config is nil") + } + + client, err := createSdkClient(config.AccessKeyId, config.AccessKeySecret, config.Region) + if err != nil { + return nil, xerrors.Wrap(err, "failed to create sdk client") + } + + return &DeployerProvider{ + config: config, + logger: logger.NewNilLogger(), + sdkClient: client, + }, nil +} + +func (d *DeployerProvider) WithLogger(logger logger.Logger) *DeployerProvider { + d.logger = logger + return d +} + +func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { + // 设置域名证书 + // REF: https://help.aliyun.com/zh/vod/developer-reference/api-vod-2017-03-21-setvoddomainsslcertificate + setVodDomainSSLCertificateReq := &aliyunVod.SetVodDomainSSLCertificateRequest{ + DomainName: tea.String(d.config.Domain), + CertName: tea.String(fmt.Sprintf("certimate-%d", time.Now().UnixMilli())), + CertType: tea.String("upload"), + SSLProtocol: tea.String("on"), + SSLPub: tea.String(certPem), + SSLPri: tea.String(privkeyPem), + } + setVodDomainSSLCertificateResp, err := d.sdkClient.SetVodDomainSSLCertificate(setVodDomainSSLCertificateReq) + if err != nil { + return nil, xerrors.Wrap(err, "failed to execute sdk request 'live.SetVodDomainSSLCertificate'") + } else { + d.logger.Logt("已设置域名证书", setVodDomainSSLCertificateResp) + } + + return &deployer.DeployResult{}, nil +} + +func createSdkClient(accessKeyId, accessKeySecret, region string) (*aliyunVod.Client, error) { + // 接入点一览 https://help.aliyun.com/zh/vod/developer-reference/api-vod-2017-03-21-endpoint + endpoint := fmt.Sprintf("vod.%s.aliyuncs.com", region) + + config := &aliyunOpen.Config{ + AccessKeyId: tea.String(accessKeyId), + AccessKeySecret: tea.String(accessKeySecret), + Endpoint: tea.String(endpoint), + } + + client, err := aliyunVod.NewClient(config) + if err != nil { + return nil, err + } + + return client, nil +} diff --git a/internal/pkg/core/deployer/providers/aliyun-vod/aliyun_vod_test.go b/internal/pkg/core/deployer/providers/aliyun-vod/aliyun_vod_test.go new file mode 100644 index 00000000..552ddc0f --- /dev/null +++ b/internal/pkg/core/deployer/providers/aliyun-vod/aliyun_vod_test.go @@ -0,0 +1,80 @@ +package aliyunvod_test + +import ( + "context" + "flag" + "fmt" + "os" + "strings" + "testing" + + provider "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/aliyun-vod" +) + +var ( + fInputCertPath string + fInputKeyPath string + fAccessKeyId string + fAccessKeySecret string + fRegion string + fDomain string +) + +func init() { + argsPrefix := "CERTIMATE_DEPLOYER_ALIYUNVOD_" + + flag.StringVar(&fInputCertPath, argsPrefix+"INPUTCERTPATH", "", "") + flag.StringVar(&fInputKeyPath, argsPrefix+"INPUTKEYPATH", "", "") + flag.StringVar(&fAccessKeyId, argsPrefix+"ACCESSKEYID", "", "") + flag.StringVar(&fAccessKeySecret, argsPrefix+"ACCESSKEYSECRET", "", "") + flag.StringVar(&fRegion, argsPrefix+"REGION", "", "") + flag.StringVar(&fDomain, argsPrefix+"DOMAIN", "", "") +} + +/* +Shell command to run this test: + + go test -v ./aliyun_vod_test.go -args \ + --CERTIMATE_DEPLOYER_ALIYUNVOD_INPUTCERTPATH="/path/to/your-input-cert.pem" \ + --CERTIMATE_DEPLOYER_ALIYUNVOD_INPUTKEYPATH="/path/to/your-input-key.pem" \ + --CERTIMATE_DEPLOYER_ALIYUNVOD_ACCESSKEYID="your-access-key-id" \ + --CERTIMATE_DEPLOYER_ALIYUNVOD_ACCESSKEYSECRET="your-access-key-secret" \ + --CERTIMATE_DEPLOYER_ALIYUNVOD_REGION="cn-hangzhou" \ + --CERTIMATE_DEPLOYER_ALIYUNVOD_DOMAIN="example.com" +*/ +func TestDeploy(t *testing.T) { + flag.Parse() + + t.Run("Deploy", func(t *testing.T) { + t.Log(strings.Join([]string{ + "args:", + fmt.Sprintf("INPUTCERTPATH: %v", fInputCertPath), + fmt.Sprintf("INPUTKEYPATH: %v", fInputKeyPath), + fmt.Sprintf("ACCESSKEYID: %v", fAccessKeyId), + fmt.Sprintf("ACCESSKEYSECRET: %v", fAccessKeySecret), + fmt.Sprintf("REGION: %v", fRegion), + fmt.Sprintf("DOMAIN: %v", fDomain), + }, "\n")) + + deployer, err := provider.NewDeployer(&provider.DeployerConfig{ + AccessKeyId: fAccessKeyId, + AccessKeySecret: fAccessKeySecret, + Region: fRegion, + Domain: fDomain, + }) + if err != nil { + t.Errorf("err: %+v", err) + return + } + + fInputCertData, _ := os.ReadFile(fInputCertPath) + fInputKeyData, _ := os.ReadFile(fInputKeyPath) + res, err := deployer.Deploy(context.Background(), string(fInputCertData), string(fInputKeyData)) + if err != nil { + t.Errorf("err: %+v", err) + return + } + + t.Logf("ok: %v", res) + }) +} diff --git a/ui/src/components/workflow/node/DeployNodeConfigForm.tsx b/ui/src/components/workflow/node/DeployNodeConfigForm.tsx index f62191d0..c6842841 100644 --- a/ui/src/components/workflow/node/DeployNodeConfigForm.tsx +++ b/ui/src/components/workflow/node/DeployNodeConfigForm.tsx @@ -24,6 +24,7 @@ import DeployNodeConfigFormAliyunESAConfig from "./DeployNodeConfigFormAliyunESA import DeployNodeConfigFormAliyunLiveConfig from "./DeployNodeConfigFormAliyunLiveConfig"; import DeployNodeConfigFormAliyunNLBConfig from "./DeployNodeConfigFormAliyunNLBConfig"; import DeployNodeConfigFormAliyunOSSConfig from "./DeployNodeConfigFormAliyunOSSConfig"; +import DeployNodeConfigFormAliyunVODConfig from "./DeployNodeConfigFormAliyunVODConfig"; import DeployNodeConfigFormAliyunWAFConfig from "./DeployNodeConfigFormAliyunWAFConfig"; import DeployNodeConfigFormAWSCloudFrontConfig from "./DeployNodeConfigFormAWSCloudFrontConfig"; import DeployNodeConfigFormBaiduCloudCDNConfig from "./DeployNodeConfigFormBaiduCloudCDNConfig"; @@ -153,6 +154,8 @@ const DeployNodeConfigForm = forwardRef; case DEPLOY_PROVIDERS.ALIYUN_OSS: return ; + case DEPLOY_PROVIDERS.ALIYUN_VOD: + return ; case DEPLOY_PROVIDERS.ALIYUN_WAF: return ; case DEPLOY_PROVIDERS.AWS_CLOUDFRONT: diff --git a/ui/src/components/workflow/node/DeployNodeConfigFormAliyunVODConfig.tsx b/ui/src/components/workflow/node/DeployNodeConfigFormAliyunVODConfig.tsx new file mode 100644 index 00000000..d76e1193 --- /dev/null +++ b/ui/src/components/workflow/node/DeployNodeConfigFormAliyunVODConfig.tsx @@ -0,0 +1,79 @@ +import { useTranslation } from "react-i18next"; +import { Form, type FormInstance, Input } from "antd"; +import { createSchemaFieldRule } from "antd-zod"; +import { z } from "zod"; + +import { validDomainName } from "@/utils/validators"; + +type DeployNodeConfigFormAliyunVODConfigFieldValues = Nullish<{ + region: string; + domain: string; +}>; + +export type DeployNodeConfigFormAliyunVODConfigProps = { + form: FormInstance; + formName: string; + disabled?: boolean; + initialValues?: DeployNodeConfigFormAliyunVODConfigFieldValues; + onValuesChange?: (values: DeployNodeConfigFormAliyunVODConfigFieldValues) => void; +}; + +const initFormModel = (): DeployNodeConfigFormAliyunVODConfigFieldValues => { + return {}; +}; + +const DeployNodeConfigFormAliyunVODConfig = ({ + form: formInst, + formName, + disabled, + initialValues, + onValuesChange, +}: DeployNodeConfigFormAliyunVODConfigProps) => { + const { t } = useTranslation(); + + const formSchema = z.object({ + region: z + .string({ message: t("workflow_node.deploy.form.aliyun_vod_region.placeholder") }) + .nonempty(t("workflow_node.deploy.form.aliyun_vod_region.placeholder")) + .trim(), + domain: z + .string({ message: t("workflow_node.deploy.form.aliyun_vod_domain.placeholder") }) + .refine((v) => validDomainName(v), t("common.errmsg.domain_invalid")), + }); + const formRule = createSchemaFieldRule(formSchema); + + const handleFormChange = (_: unknown, values: z.infer) => { + onValuesChange?.(values); + }; + + return ( +
+ } + > + + + + } + > + + +
+ ); +}; + +export default DeployNodeConfigFormAliyunVODConfig; diff --git a/ui/src/domain/provider.ts b/ui/src/domain/provider.ts index e2475247..48dd1f8a 100644 --- a/ui/src/domain/provider.ts +++ b/ui/src/domain/provider.ts @@ -206,6 +206,7 @@ export const DEPLOY_PROVIDERS = Object.freeze({ ALIYUN_LIVE: `${ACCESS_PROVIDERS.ALIYUN}-live`, ALIYUN_NLB: `${ACCESS_PROVIDERS.ALIYUN}-nlb`, ALIYUN_OSS: `${ACCESS_PROVIDERS.ALIYUN}-oss`, + ALIYUN_VOD: `${ACCESS_PROVIDERS.ALIYUN}-vod`, ALIYUN_WAF: `${ACCESS_PROVIDERS.ALIYUN}-waf`, AWS_CLOUDFRONT: `${ACCESS_PROVIDERS.AWS}-cloudfront`, BAIDUCLOUD_CDN: `${ACCESS_PROVIDERS.BAIDUCLOUD}-cdn`, @@ -291,6 +292,7 @@ export const deployProvidersMap: Maphttps://oss.console.aliyun.com", + "workflow_node.deploy.form.aliyun_vod_region.label": "Alibaba Cloud VOD region", + "workflow_node.deploy.form.aliyun_vod_region.placeholder": "Please enter Alibaba Cloud VOD region (e.g. cn-hangzhou)", + "workflow_node.deploy.form.aliyun_vod_region.tooltip": "For more information, see https://www.alibabacloud.com/help/en/vod/product-overview/regions", + "workflow_node.deploy.form.aliyun_vod_domain.label": "Alibaba Cloud VOD domain", + "workflow_node.deploy.form.aliyun_vod_domain.placeholder": "Please enter Alibaba Cloud VOD domain name", + "workflow_node.deploy.form.aliyun_vod_domain.tooltip": "For more information, see https://vod.console.aliyun.com", "workflow_node.deploy.form.aliyun_waf_region.label": "Alibaba Cloud WAF region", "workflow_node.deploy.form.aliyun_waf_region.placeholder": "Please enter Alibaba Cloud WAF region (e.g. cn-hangzhou)", "workflow_node.deploy.form.aliyun_waf_region.tooltip": "For more information, see https://www.alibabacloud.com/help/en/waf/web-application-firewall-3-0/developer-reference/api-waf-openapi-2021-10-01-endpoint", diff --git a/ui/src/i18n/locales/zh/nls.provider.json b/ui/src/i18n/locales/zh/nls.provider.json index dfa3022c..b5eca74a 100644 --- a/ui/src/i18n/locales/zh/nls.provider.json +++ b/ui/src/i18n/locales/zh/nls.provider.json @@ -12,6 +12,7 @@ "provider.aliyun.live": "阿里云 - 视频直播 Live", "provider.aliyun.nlb": "阿里云 - 网络型负载均衡 NLB", "provider.aliyun.oss": "阿里云 - 对象存储 OSS", + "provider.aliyun.vod": "阿里云 - 视频点播 VOD", "provider.aliyun.waf": "阿里云 - Web 应用防火墙 WAF", "provider.akamai": "Akamai", "provider.akamai.cdn": "Akamai - 内容分发网络 CDN", diff --git a/ui/src/i18n/locales/zh/nls.workflow.nodes.json b/ui/src/i18n/locales/zh/nls.workflow.nodes.json index 0e68333b..4def5f34 100644 --- a/ui/src/i18n/locales/zh/nls.workflow.nodes.json +++ b/ui/src/i18n/locales/zh/nls.workflow.nodes.json @@ -178,6 +178,12 @@ "workflow_node.deploy.form.aliyun_oss_domain.label": "阿里云 OSS 自定义域名", "workflow_node.deploy.form.aliyun_oss_domain.placeholder": "请输入阿里云 OSS 自定义域名", "workflow_node.deploy.form.aliyun_oss_domain.tooltip": "这是什么?请参阅 see https://oss.console.aliyun.com", + "workflow_node.deploy.form.aliyun_vod_region.label": "阿里云视频点播服务地域", + "workflow_node.deploy.form.aliyun_vod_region.placeholder": "请输入阿里云视频点播服务地域(例如:cn-hangzhou)", + "workflow_node.deploy.form.aliyun_vod_region.tooltip": "这是什么?请参阅 https://help.aliyun.com/zh/vod/product-overview/regions", + "workflow_node.deploy.form.aliyun_vod_domain.label": "阿里云视频点播加速域名", + "workflow_node.deploy.form.aliyun_vod_domain.placeholder": "请输入阿里云视频点播加速域名", + "workflow_node.deploy.form.aliyun_vod_domain.tooltip": "这是什么?请参阅 https://vod.console.aliyun.com", "workflow_node.deploy.form.aliyun_waf_region.label": "阿里云 WAF 服务地域", "workflow_node.deploy.form.aliyun_waf_region.placeholder": "请输入阿里云 WAF 服务地域(例如:cn-hangzhou)", "workflow_node.deploy.form.aliyun_waf_region.tooltip": "这是什么?请参阅 https://help.aliyun.com/zh/waf/web-application-firewall-3-0/developer-reference/api-waf-openapi-2021-10-01-endpoint", From 2cfaf4e2312c97ad5b1c089469d05674ce71fa3a Mon Sep 17 00:00:00 2001 From: Fu Diwei Date: Thu, 20 Feb 2025 21:41:24 +0800 Subject: [PATCH 25/34] feat: add tencentcloud vod deployer --- README.md | 2 +- README_EN.md | 2 +- go.mod | 3 +- go.sum | 4 + internal/deployer/providers.go | 12 +- internal/domain/provider.go | 1 + .../tencentcloud-vod/tencentcloud_vod.go | 104 ++++++++++++++++++ .../tencentcloud-vod/tencentcloud_vod_test.go | 87 +++++++++++++++ .../provider/DeployProviderPicker.tsx | 2 +- .../workflow/node/DeployNodeConfigForm.tsx | 3 + ...loyNodeConfigFormTencentCloudVODConfig.tsx | 82 ++++++++++++++ ui/src/domain/provider.ts | 16 +-- ui/src/i18n/locales/en/nls.provider.json | 5 +- .../i18n/locales/en/nls.workflow.nodes.json | 8 +- ui/src/i18n/locales/zh/nls.provider.json | 3 +- .../i18n/locales/zh/nls.workflow.nodes.json | 8 +- 16 files changed, 325 insertions(+), 17 deletions(-) create mode 100644 internal/pkg/core/deployer/providers/tencentcloud-vod/tencentcloud_vod.go create mode 100644 internal/pkg/core/deployer/providers/tencentcloud-vod/tencentcloud_vod_test.go create mode 100644 ui/src/components/workflow/node/DeployNodeConfigFormTencentCloudVODConfig.tsx diff --git a/README.md b/README.md index 59dcc6a9..2c3ccbbc 100644 --- a/README.md +++ b/README.md @@ -126,7 +126,7 @@ make local.run | Webhook 回调 | 可部署到 Webhook | | [Kubernetes](https://kubernetes.io/) | 可部署到 Kubernetes Secret | | [阿里云](https://www.aliyun.com/) | 可部署到阿里云 OSS、CDN、DCDN、ESA、SLB(CLB/ALB/NLB)、WAF、Live、VOD 等服务 | -| [腾讯云](https://cloud.tencent.com/) | 可部署到腾讯云 COS、CDN、ECDN、EdgeOne、CLB、WAF、CSS 等服务 | +| [腾讯云](https://cloud.tencent.com/) | 可部署到腾讯云 COS、CDN、ECDN、EdgeOne、CLB、WAF、CSS、VOD 等服务 | | [百度智能云](https://cloud.baidu.com/) | 可部署到百度智能云 CDN 等服务 | | [华为云](https://www.huaweicloud.com/) | 可部署到华为云 CDN、ELB、WAF 等服务 | | [火山引擎](https://www.volcengine.com/) | 可部署到火山引擎 TOS、CDN、DCDN、CLB、ImageX、Live 等服务 | diff --git a/README_EN.md b/README_EN.md index 7b11ac3a..7ced5c04 100644 --- a/README_EN.md +++ b/README_EN.md @@ -125,7 +125,7 @@ The following hosting providers are supported: | Webhook | Supports deployment to Webhook | | [Kubernetes](https://kubernetes.io/) | Supports deployment to Kubernetes Secret | | [Alibaba Cloud](https://www.alibabacloud.com/) | Supports deployment to Alibaba Cloud OSS, CDN, DCDN, SLB(CLB/ALB/NLB), WAF, Live, VOD | -| [Tencent Cloud](https://www.tencentcloud.com/) | Supports deployment to Tencent Cloud COS, CDN, ECDN, EdgeOne, CLB, WAF, CSS | +| [Tencent Cloud](https://www.tencentcloud.com/) | Supports deployment to Tencent Cloud COS, CDN, ECDN, EdgeOne, CLB, WAF, CSS, VOD | | [Baidu AI Cloud](https://intl.cloud.baidu.com/) | Supports deployment to Baidu AI CLoud CDN | | [Huawei Cloud](https://www.huaweicloud.com/) | Supports deployment to Huawei Cloud CDN, ELB, WAF | | [Volcengine](https://www.volcengine.com/) | Supports deployment to Volcengine TOS, CDN, DCDN, CLB, ImageX, Live | diff --git a/go.mod b/go.mod index 5f318638..78549ec1 100644 --- a/go.mod +++ b/go.mod @@ -34,7 +34,7 @@ require ( github.com/qiniu/go-sdk/v7 v7.25.2 github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cdn v1.0.1096 github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/clb v1.0.1096 - github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1099 + github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1102 github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/live v1.0.1096 github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/ssl v1.0.1096 github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/teo v1.0.1096 @@ -102,6 +102,7 @@ require ( github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect github.com/sirupsen/logrus v1.9.3 // indirect github.com/technoweenie/multipartstreamer v1.0.1 // indirect + github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/vod v1.0.1102 // indirect github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/waf v1.0.1099 // indirect github.com/x448/float16 v0.8.4 // indirect go.mongodb.org/mongo-driver v1.17.2 // indirect diff --git a/go.sum b/go.sum index a87e7bda..e85c4f8d 100644 --- a/go.sum +++ b/go.sum @@ -849,6 +849,8 @@ github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1096 h1:DMo github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1096/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0= github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1099 h1:4fQ53ORk6Eayw1H2kg43PoBnUuhGR6WRG6rtec/i3oI= github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1099/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0= +github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1102 h1:DxsNhw67OHyQME20IULmi8lgNY9MHuQ+qS1XH1/yTvM= +github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1102/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0= github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/dnspod v1.0.1084 h1:kwctN0WQYt8/iKP+iRCTCwdzEMIXsXklbRIib5rjeQ8= github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/dnspod v1.0.1084/go.mod h1:qE67ApiBzeRvzeDsV+GxyIDbVIDemsKpHXllQATz/Vw= github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/live v1.0.1096 h1:h9FP40Ycg45egJlZcjbLyc4IUeFoq+wSpR43sHMALtM= @@ -857,6 +859,8 @@ github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/ssl v1.0.1096 h1:7ZmPus github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/ssl v1.0.1096/go.mod h1:aMpGcDskqqhXtfMaeo2egO61tgh/zt07L1ohSPwmjWk= github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/teo v1.0.1096 h1:N62IFKL1ZRNQ7WPLNn8x9eYnwM4lOUIVY3buW6kbGtg= github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/teo v1.0.1096/go.mod h1:4PZRRpZp+jvYBUbUajsoZREnk7sJXMnPAiGB4IX8IkM= +github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/vod v1.0.1102 h1:B0mJk0ojVOFCMLrBoxLNVgrGih11EezTekRffkACCAY= +github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/vod v1.0.1102/go.mod h1:0yyQ1r35jteb5DV4mcJZ5uh9NStWzjMYz9iSMnDMdJA= github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/waf v1.0.1099 h1:kD+8RKF0uJCr7VaurAUA11NNAoln0HaagMCgQV6EnUw= github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/waf v1.0.1099/go.mod h1:ellbjD8eHKHS4ixscLdiPJI8QoFIk0YNEgaDjxXMECM= github.com/tjfoc/gmsm v1.3.2/go.mod h1:HaUcFuY0auTiaHB9MHFGCPx5IaLhTUd2atbCFBQXn9w= diff --git a/internal/deployer/providers.go b/internal/deployer/providers.go index d053b93e..8da7fd0a 100644 --- a/internal/deployer/providers.go +++ b/internal/deployer/providers.go @@ -47,6 +47,7 @@ import ( pTencentCloudECDN "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/tencentcloud-ecdn" pTencentCloudEO "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/tencentcloud-eo" pTencentCloudSSLDeploy "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/tencentcloud-ssl-deploy" + pTencentCloudVOD "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/tencentcloud-vod" pTencentCloudWAF "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/tencentcloud-waf" pUCloudUCDN "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/ucloud-ucdn" pUCloudUS3 "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/ucloud-us3" @@ -577,7 +578,7 @@ func createDeployer(options *deployerOptions) (deployer.Deployer, error) { return deployer, err } - case domain.DeployProviderTypeTencentCloudCDN, domain.DeployProviderTypeTencentCloudCLB, domain.DeployProviderTypeTencentCloudCOS, domain.DeployProviderTypeTencentCloudCSS, domain.DeployProviderTypeTencentCloudECDN, domain.DeployProviderTypeTencentCloudEO, domain.DeployProviderTypeTencentCloudSSLDeploy, domain.DeployProviderTypeTencentCloudWAF: + case domain.DeployProviderTypeTencentCloudCDN, domain.DeployProviderTypeTencentCloudCLB, domain.DeployProviderTypeTencentCloudCOS, domain.DeployProviderTypeTencentCloudCSS, domain.DeployProviderTypeTencentCloudECDN, domain.DeployProviderTypeTencentCloudEO, domain.DeployProviderTypeTencentCloudSSLDeploy, domain.DeployProviderTypeTencentCloudVOD, domain.DeployProviderTypeTencentCloudWAF: { access := domain.AccessConfigForTencentCloud{} if err := maps.Populate(options.ProviderAccessConfig, &access); err != nil { @@ -650,6 +651,15 @@ func createDeployer(options *deployerOptions) (deployer.Deployer, error) { }) return deployer, err + case domain.DeployProviderTypeTencentCloudVOD: + deployer, err := pTencentCloudVOD.NewDeployer(&pTencentCloudVOD.DeployerConfig{ + SecretId: access.SecretId, + SecretKey: access.SecretKey, + SubAppId: maps.GetValueAsInt64(options.ProviderDeployConfig, "subAppId"), + Domain: maps.GetValueAsString(options.ProviderDeployConfig, "domain"), + }) + return deployer, err + case domain.DeployProviderTypeTencentCloudWAF: deployer, err := pTencentCloudWAF.NewDeployer(&pTencentCloudWAF.DeployerConfig{ SecretId: access.SecretId, diff --git a/internal/domain/provider.go b/internal/domain/provider.go index 8485b357..17e959e6 100644 --- a/internal/domain/provider.go +++ b/internal/domain/provider.go @@ -144,6 +144,7 @@ const ( DeployProviderTypeTencentCloudECDN = DeployProviderType("tencentcloud-ecdn") DeployProviderTypeTencentCloudEO = DeployProviderType("tencentcloud-eo") DeployProviderTypeTencentCloudSSLDeploy = DeployProviderType("tencentcloud-ssldeploy") + DeployProviderTypeTencentCloudVOD = DeployProviderType("tencentcloud-vod") DeployProviderTypeTencentCloudWAF = DeployProviderType("tencentcloud-waf") DeployProviderTypeUCloudUCDN = DeployProviderType("ucloud-ucdn") DeployProviderTypeUCloudUS3 = DeployProviderType("ucloud-us3") diff --git a/internal/pkg/core/deployer/providers/tencentcloud-vod/tencentcloud_vod.go b/internal/pkg/core/deployer/providers/tencentcloud-vod/tencentcloud_vod.go new file mode 100644 index 00000000..fbce8d6f --- /dev/null +++ b/internal/pkg/core/deployer/providers/tencentcloud-vod/tencentcloud_vod.go @@ -0,0 +1,104 @@ +package tencentcloudvod + +import ( + "context" + + xerrors "github.com/pkg/errors" + "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common" + "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common/profile" + tcVod "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/vod/v20180717" + + "github.com/usual2970/certimate/internal/pkg/core/deployer" + "github.com/usual2970/certimate/internal/pkg/core/logger" + "github.com/usual2970/certimate/internal/pkg/core/uploader" + uploadersp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/tencentcloud-ssl" +) + +type DeployerConfig struct { + // 腾讯云 SecretId。 + SecretId string `json:"secretId"` + // 腾讯云 SecretKey。 + SecretKey string `json:"secretKey"` + // 点播应用 ID。 + SubAppId int64 `json:"subAppId"` + // 点播加速域名(不支持泛域名)。 + Domain string `json:"domain"` +} + +type DeployerProvider struct { + config *DeployerConfig + logger logger.Logger + sdkClient *tcVod.Client + sslUploader uploader.Uploader +} + +var _ deployer.Deployer = (*DeployerProvider)(nil) + +func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { + if config == nil { + panic("config is nil") + } + + client, err := createSdkClient(config.SecretId, config.SecretKey) + if err != nil { + return nil, xerrors.Wrap(err, "failed to create sdk clients") + } + + uploader, err := uploadersp.NewUploader(&uploadersp.UploaderConfig{ + SecretId: config.SecretId, + SecretKey: config.SecretKey, + }) + if err != nil { + return nil, xerrors.Wrap(err, "failed to create ssl uploader") + } + + return &DeployerProvider{ + config: config, + logger: logger.NewNilLogger(), + sdkClient: client, + sslUploader: uploader, + }, nil +} + +func (d *DeployerProvider) WithLogger(logger logger.Logger) *DeployerProvider { + d.logger = logger + return d +} + +func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { + // 上传证书到 SSL + upres, err := d.sslUploader.Upload(ctx, certPem, privkeyPem) + if err != nil { + return nil, xerrors.Wrap(err, "failed to upload certificate file") + } else { + d.logger.Logt("certificate file uploaded", upres) + } + + // 设置点播域名 HTTPS 证书 + // REF: https://cloud.tencent.com/document/api/266/102015 + setVodDomainCertificateReq := tcVod.NewSetVodDomainCertificateRequest() + setVodDomainCertificateReq.Domain = common.StringPtr(d.config.Domain) + setVodDomainCertificateReq.Operation = common.StringPtr("Set") + setVodDomainCertificateReq.CertID = common.StringPtr(upres.CertId) + if d.config.SubAppId != 0 { + setVodDomainCertificateReq.SubAppId = common.Uint64Ptr(uint64(d.config.SubAppId)) + } + setVodDomainCertificateResp, err := d.sdkClient.SetVodDomainCertificate(setVodDomainCertificateReq) + if err != nil { + return nil, xerrors.Wrap(err, "failed to execute sdk request 'vod.SetVodDomainCertificate'") + } else { + d.logger.Logt("已设置点播域名 HTTPS 证书", setVodDomainCertificateResp.Response) + } + + return &deployer.DeployResult{}, nil +} + +func createSdkClient(secretId, secretKey string) (*tcVod.Client, error) { + credential := common.NewCredential(secretId, secretKey) + client, err := tcVod.NewClient(credential, "", profile.NewClientProfile()) + if err != nil { + return nil, err + } + + return client, nil +} diff --git a/internal/pkg/core/deployer/providers/tencentcloud-vod/tencentcloud_vod_test.go b/internal/pkg/core/deployer/providers/tencentcloud-vod/tencentcloud_vod_test.go new file mode 100644 index 00000000..60871a31 --- /dev/null +++ b/internal/pkg/core/deployer/providers/tencentcloud-vod/tencentcloud_vod_test.go @@ -0,0 +1,87 @@ +package tencentcloudvod_test + +import ( + "context" + "flag" + "fmt" + "os" + "strings" + "testing" + + provider "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/tencentcloud-vod" +) + +var ( + fInputCertPath string + fInputKeyPath string + fSecretId string + fSecretKey string + fRegion string + fDomain string + fSubAppId int64 + fInstanceId string +) + +func init() { + argsPrefix := "CERTIMATE_DEPLOYER_TENCENTCLOUDVOD_" + + flag.StringVar(&fInputCertPath, argsPrefix+"INPUTCERTPATH", "", "") + flag.StringVar(&fInputKeyPath, argsPrefix+"INPUTKEYPATH", "", "") + flag.StringVar(&fSecretId, argsPrefix+"SECRETID", "", "") + flag.StringVar(&fSecretKey, argsPrefix+"SECRETKEY", "", "") + flag.StringVar(&fRegion, argsPrefix+"REGION", "", "") + flag.StringVar(&fDomain, argsPrefix+"DOMAIN", "", "") + flag.Int64Var(&fSubAppId, argsPrefix+"SUBAPPID", 0, "") + flag.StringVar(&fInstanceId, argsPrefix+"INSTANCEID", "", "") +} + +/* +Shell command to run this test: + + go test -v ./tencentcloud_vod_test.go -args \ + --CERTIMATE_DEPLOYER_TENCENTCLOUDVOD_INPUTCERTPATH="/path/to/your-input-cert.pem" \ + --CERTIMATE_DEPLOYER_TENCENTCLOUDVOD_INPUTKEYPATH="/path/to/your-input-key.pem" \ + --CERTIMATE_DEPLOYER_TENCENTCLOUDVOD_SECRETID="your-secret-id" \ + --CERTIMATE_DEPLOYER_TENCENTCLOUDVOD_SECRETKEY="your-secret-key" \ + --CERTIMATE_DEPLOYER_TENCENTCLOUDVOD_REGION="ap-guangzhou" \ + --CERTIMATE_DEPLOYER_TENCENTCLOUDVOD_SUBAPPID="your-app-id" \ + --CERTIMATE_DEPLOYER_TENCENTCLOUDVOD_DOMAIN="example.com" +*/ +func TestDeploy(t *testing.T) { + flag.Parse() + + t.Run("Deploy", func(t *testing.T) { + t.Log(strings.Join([]string{ + "args:", + fmt.Sprintf("INPUTCERTPATH: %v", fInputCertPath), + fmt.Sprintf("INPUTKEYPATH: %v", fInputKeyPath), + fmt.Sprintf("SECRETID: %v", fSecretId), + fmt.Sprintf("SECRETKEY: %v", fSecretKey), + fmt.Sprintf("REGION: %v", fRegion), + fmt.Sprintf("DOMAIN: %v", fDomain), + fmt.Sprintf("INSTANCEID: %v", fInstanceId), + }, "\n")) + + deployer, err := provider.NewDeployer(&provider.DeployerConfig{ + SecretId: fSecretId, + SecretKey: fSecretKey, + Region: fRegion, + SubAppId: fSubAppId, + Domain: fDomain, + }) + if err != nil { + t.Errorf("err: %+v", err) + return + } + + fInputCertData, _ := os.ReadFile(fInputCertPath) + fInputKeyData, _ := os.ReadFile(fInputKeyPath) + res, err := deployer.Deploy(context.Background(), string(fInputCertData), string(fInputKeyData)) + if err != nil { + t.Errorf("err: %+v", err) + return + } + + t.Logf("ok: %v", res) + }) +} diff --git a/ui/src/components/provider/DeployProviderPicker.tsx b/ui/src/components/provider/DeployProviderPicker.tsx index af373255..57ba39a6 100644 --- a/ui/src/components/provider/DeployProviderPicker.tsx +++ b/ui/src/components/provider/DeployProviderPicker.tsx @@ -63,7 +63,7 @@ const DeployProviderPicker = ({ className, style, autoFocus, placeholder, onSele DEPLOY_CATEGORIES.STORAGE, DEPLOY_CATEGORIES.LOADBALANCE, DEPLOY_CATEGORIES.FIREWALL, - DEPLOY_CATEGORIES.LIVE, + DEPLOY_CATEGORIES.AV, DEPLOY_CATEGORIES.WEBSITE, DEPLOY_CATEGORIES.OTHER, ].map((key) => ({ diff --git a/ui/src/components/workflow/node/DeployNodeConfigForm.tsx b/ui/src/components/workflow/node/DeployNodeConfigForm.tsx index c6842841..000b67e3 100644 --- a/ui/src/components/workflow/node/DeployNodeConfigForm.tsx +++ b/ui/src/components/workflow/node/DeployNodeConfigForm.tsx @@ -55,6 +55,7 @@ import DeployNodeConfigFormTencentCloudCSSConfig from "./DeployNodeConfigFormTen import DeployNodeConfigFormTencentCloudECDNConfig from "./DeployNodeConfigFormTencentCloudECDNConfig.tsx"; import DeployNodeConfigFormTencentCloudEOConfig from "./DeployNodeConfigFormTencentCloudEOConfig.tsx"; import DeployNodeConfigFormTencentCloudSSLDeployConfig from "./DeployNodeConfigFormTencentCloudSSLDeployConfig"; +import DeployNodeConfigFormTencentCloudVODConfig from "./DeployNodeConfigFormTencentCloudVODConfig"; import DeployNodeConfigFormTencentCloudWAFConfig from "./DeployNodeConfigFormTencentCloudWAFConfig"; import DeployNodeConfigFormUCloudUCDNConfig from "./DeployNodeConfigFormUCloudUCDNConfig.tsx"; import DeployNodeConfigFormUCloudUS3Config from "./DeployNodeConfigFormUCloudUS3Config.tsx"; @@ -216,6 +217,8 @@ const DeployNodeConfigForm = forwardRef; case DEPLOY_PROVIDERS.TENCENTCLOUD_SSL_DEPLOY: return ; + case DEPLOY_PROVIDERS.TENCENTCLOUD_VOD: + return ; case DEPLOY_PROVIDERS.TENCENTCLOUD_WAF: return ; case DEPLOY_PROVIDERS.UCLOUD_UCDN: diff --git a/ui/src/components/workflow/node/DeployNodeConfigFormTencentCloudVODConfig.tsx b/ui/src/components/workflow/node/DeployNodeConfigFormTencentCloudVODConfig.tsx new file mode 100644 index 00000000..2c5742eb --- /dev/null +++ b/ui/src/components/workflow/node/DeployNodeConfigFormTencentCloudVODConfig.tsx @@ -0,0 +1,82 @@ +import { useTranslation } from "react-i18next"; +import { Form, type FormInstance, Input } from "antd"; +import { createSchemaFieldRule } from "antd-zod"; +import { z } from "zod"; + +import { validDomainName } from "@/utils/validators"; + +type DeployNodeConfigFormTencentCloudVODConfigFieldValues = Nullish<{ + subAppId?: string | number; + domain: string; +}>; + +export type DeployNodeConfigFormTencentCloudVODConfigProps = { + form: FormInstance; + formName: string; + disabled?: boolean; + initialValues?: DeployNodeConfigFormTencentCloudVODConfigFieldValues; + onValuesChange?: (values: DeployNodeConfigFormTencentCloudVODConfigFieldValues) => void; +}; + +const initFormModel = (): DeployNodeConfigFormTencentCloudVODConfigFieldValues => { + return {}; +}; + +const DeployNodeConfigFormTencentCloudVODConfig = ({ + form: formInst, + formName, + disabled, + initialValues, + onValuesChange, +}: DeployNodeConfigFormTencentCloudVODConfigProps) => { + const { t } = useTranslation(); + + const formSchema = z.object({ + subAppId: z + .union([z.string(), z.number()]) + .nullish() + .refine((v) => { + if (v == null) return true; + return /^\d+$/.test(v + "") && +v > 0; + }, t("workflow_node.deploy.form.tencentcloud_vod_sub_app_id.placeholder")), + domain: z + .string({ message: t("workflow_node.deploy.form.tencentcloud_vod_domain.placeholder") }) + .refine((v) => validDomainName(v), t("common.errmsg.domain_invalid")), + }); + const formRule = createSchemaFieldRule(formSchema); + + const handleFormChange = (_: unknown, values: z.infer) => { + onValuesChange?.(values); + }; + + return ( +
+ } + > + + + + } + > + + +
+ ); +}; + +export default DeployNodeConfigFormTencentCloudVODConfig; diff --git a/ui/src/domain/provider.ts b/ui/src/domain/provider.ts index 48dd1f8a..d549f4cd 100644 --- a/ui/src/domain/provider.ts +++ b/ui/src/domain/provider.ts @@ -238,6 +238,7 @@ export const DEPLOY_PROVIDERS = Object.freeze({ TENCENTCLOUD_ECDN: `${ACCESS_PROVIDERS.TENCENTCLOUD}-ecdn`, TENCENTCLOUD_EO: `${ACCESS_PROVIDERS.TENCENTCLOUD}-eo`, TENCENTCLOUD_SSL_DEPLOY: `${ACCESS_PROVIDERS.TENCENTCLOUD}-ssldeploy`, + TENCENTCLOUD_VOD: `${ACCESS_PROVIDERS.TENCENTCLOUD}-vod`, TENCENTCLOUD_WAF: `${ACCESS_PROVIDERS.TENCENTCLOUD}-waf`, UCLOUD_UCDN: `${ACCESS_PROVIDERS.UCLOUD}-ucdn`, UCLOUD_US3: `${ACCESS_PROVIDERS.UCLOUD}-us3`, @@ -258,7 +259,7 @@ export const DEPLOY_CATEGORIES = Object.freeze({ STORAGE: "storage", LOADBALANCE: "loadbalance", FIREWALL: "firewall", - LIVE: "live", + AV: "av", WEBSITE: "website", OTHER: "other", } as const); @@ -291,8 +292,8 @@ export const deployProvidersMap: Maphttps://console.tencentcloud.com/cos", "workflow_node.deploy.form.tencentcloud_css_domain.label": "Tencent Cloud CSS play domain", "workflow_node.deploy.form.tencentcloud_css_domain.placeholder": "Please enter Tencent Cloud CSS play domain name", - "workflow_node.deploy.form.tencentcloud_css_domain.tooltip": "For more information, see https://console.cloud.tencent.com/live/livestat", + "workflow_node.deploy.form.tencentcloud_css_domain.tooltip": "For more information, see https://console.cloud.tencent.com/live", "workflow_node.deploy.form.tencentcloud_ecdn_domain.label": "Tencent Cloud ECDN domain", "workflow_node.deploy.form.tencentcloud_ecdn_domain.placeholder": "Please enter Tencent Cloud ECDN domain name", "workflow_node.deploy.form.tencentcloud_ecdn_domain.tooltip": "For more information, see https://console.tencentcloud.com/cdn", @@ -448,6 +448,12 @@ "workflow_node.deploy.form.tencentcloud_ssl_deploy_resource_ids.tooltip": "For more information, see https://cloud.tencent.com.cn/document/product/400/91667", "workflow_node.deploy.form.tencentcloud_ssl_deploy_resource_ids.multiple_input_modal.title": "Change Tencent Cloud resource IDs", "workflow_node.deploy.form.tencentcloud_ssl_deploy_resource_ids.multiple_input_modal.placeholder": "Please enter Tencent Cloud resouce ID", + "workflow_node.deploy.form.tencentcloud_vod_sub_app_id.label": "Tencent Cloud VOD App ID", + "workflow_node.deploy.form.tencentcloud_vod_sub_app_id.placeholder": "Please enter Tencent Cloud VOD App ID", + "workflow_node.deploy.form.tencentcloud_vod_sub_app_id.tooltip": "For more information, see https://console.cloud.tencent.com/vod", + "workflow_node.deploy.form.tencentcloud_vod_domain.label": "Tencent Cloud VOD domain", + "workflow_node.deploy.form.tencentcloud_vod_domain.placeholder": "Please enter Tencent Cloud VOD domain name", + "workflow_node.deploy.form.tencentcloud_vod_domain.tooltip": "For more information, see https://console.cloud.tencent.com/vod", "workflow_node.deploy.form.tencentcloud_waf_region.label": "Tencent Cloud WAF region", "workflow_node.deploy.form.tencentcloud_waf_region.placeholder": "Please enter Tencent Cloud WAF region (e.g. ap-guangzhou)", "workflow_node.deploy.form.tencentcloud_waf_region.tooltip": "For more information, see https://www.tencentcloud.com/document/product/627/38085", diff --git a/ui/src/i18n/locales/zh/nls.provider.json b/ui/src/i18n/locales/zh/nls.provider.json index b5eca74a..5b4e8ee3 100644 --- a/ui/src/i18n/locales/zh/nls.provider.json +++ b/ui/src/i18n/locales/zh/nls.provider.json @@ -81,6 +81,7 @@ "provider.tencentcloud.ecdn": "腾讯云 - 全站加速网络 ECDN", "provider.tencentcloud.eo": "腾讯云 - 边缘安全加速平台 EdgeOne", "provider.tencentcloud.ssl_deploy": "腾讯云 - 通过 SSL 证书服务创建部署任务", + "provider.tencentcloud.vod": "腾讯云 - 云点播 VOD", "provider.tencentcloud.waf": "腾讯云 - Web 应用防火墙 WAF", "provider.ucloud": "优刻得", "provider.ucloud.ucdn": "优刻得 - 内容分发 UCDN", @@ -101,7 +102,7 @@ "provider.category.storage": "存储", "provider.category.loadbalance": "负载均衡", "provider.category.firewall": "防火墙", - "provider.category.live": "直播", + "provider.category.av": "音视频", "provider.category.website": "网站", "provider.category.other": "其他" } diff --git a/ui/src/i18n/locales/zh/nls.workflow.nodes.json b/ui/src/i18n/locales/zh/nls.workflow.nodes.json index 4def5f34..9298d2a8 100644 --- a/ui/src/i18n/locales/zh/nls.workflow.nodes.json +++ b/ui/src/i18n/locales/zh/nls.workflow.nodes.json @@ -428,7 +428,7 @@ "workflow_node.deploy.form.tencentcloud_cos_domain.tooltip": "这是什么?请参阅 see https://console.cloud.tencent.com/cos", "workflow_node.deploy.form.tencentcloud_css_domain.label": "腾讯云云直播播放域名", "workflow_node.deploy.form.tencentcloud_css_domain.placeholder": "请输入腾讯云云直播播放域名", - "workflow_node.deploy.form.tencentcloud_css_domain.tooltip": "这是什么?请参阅 https://console.cloud.tencent.com/live/livestat", + "workflow_node.deploy.form.tencentcloud_css_domain.tooltip": "这是什么?请参阅 https://console.cloud.tencent.com/live", "workflow_node.deploy.form.tencentcloud_ecdn_domain.label": "腾讯云 ECDN 加速域名", "workflow_node.deploy.form.tencentcloud_ecdn_domain.placeholder": "请输入腾讯云 ECDN 加速域名(支持泛域名)", "workflow_node.deploy.form.tencentcloud_ecdn_domain.tooltip": "这是什么?请参阅 https://console.cloud.tencent.com/cdn", @@ -451,6 +451,12 @@ "workflow_node.deploy.form.tencentcloud_ssl_deploy_resource_ids.tooltip": "这是什么?请参阅 https://cloud.tencent.com.cn/document/product/400/91667

注意与各产品本身的实例 ID 区分。", "workflow_node.deploy.form.tencentcloud_ssl_deploy_resource_ids.multiple_input_modal.title": "修改腾讯云云产品资源 ID", "workflow_node.deploy.form.tencentcloud_ssl_deploy_resource_ids.multiple_input_modal.placeholder": "请输入腾讯云云产品资源 ID", + "workflow_node.deploy.form.tencentcloud_vod_sub_app_id.label": "腾讯云云点播应用 ID", + "workflow_node.deploy.form.tencentcloud_vod_sub_app_id.placeholder": "请输入腾讯云云点播应用 ID", + "workflow_node.deploy.form.tencentcloud_vod_sub_app_id.tooltip": "这是什么?请参阅 https://console.cloud.tencent.com/vod", + "workflow_node.deploy.form.tencentcloud_vod_domain.label": "腾讯云云点播加速域名", + "workflow_node.deploy.form.tencentcloud_vod_domain.placeholder": "请输入腾讯云云点播加速域名", + "workflow_node.deploy.form.tencentcloud_vod_domain.tooltip": "这是什么?请参阅 https://console.cloud.tencent.com/vod", "workflow_node.deploy.form.tencentcloud_waf_region.label": "腾讯云 WAF 产品地域", "workflow_node.deploy.form.tencentcloud_waf_region.placeholder": "请输入腾讯云 WAF 产品地域(例如:ap-guangzhou)", "workflow_node.deploy.form.tencentcloud_waf_region.tooltip": "这是什么?请参阅 https://cloud.tencent.com/document/product/627/47525", From 906141a4155302c57c71db1fa4046ea52b731bb6 Mon Sep 17 00:00:00 2001 From: Fu Diwei Date: Thu, 20 Feb 2025 22:05:58 +0800 Subject: [PATCH 26/34] feat: add jdcloud vod deployer --- README.md | 2 +- README_EN.md | 2 +- internal/deployer/providers.go | 11 +- internal/domain/provider.go | 1 + .../providers/jdcloud-vod/jdcloud_vod.go | 122 ++++++++++++++++++ .../providers/jdcloud-vod/jdcloud_vod_test.go | 75 +++++++++++ .../providers/jdcloud-ssl/jdcloud_ssl.go | 6 +- .../workflow/node/DeployNodeConfigForm.tsx | 3 + .../DeployNodeConfigFormJDCloudVODConfig.tsx | 65 ++++++++++ ui/src/domain/provider.ts | 2 + ui/src/i18n/locales/en/nls.provider.json | 1 + .../i18n/locales/en/nls.workflow.nodes.json | 5 +- ui/src/i18n/locales/zh/nls.provider.json | 3 +- .../i18n/locales/zh/nls.workflow.nodes.json | 5 +- 14 files changed, 294 insertions(+), 9 deletions(-) create mode 100644 internal/pkg/core/deployer/providers/jdcloud-vod/jdcloud_vod.go create mode 100644 internal/pkg/core/deployer/providers/jdcloud-vod/jdcloud_vod_test.go create mode 100644 ui/src/components/workflow/node/DeployNodeConfigFormJDCloudVODConfig.tsx diff --git a/README.md b/README.md index 2c3ccbbc..5d11c865 100644 --- a/README.md +++ b/README.md @@ -130,7 +130,7 @@ make local.run | [百度智能云](https://cloud.baidu.com/) | 可部署到百度智能云 CDN 等服务 | | [华为云](https://www.huaweicloud.com/) | 可部署到华为云 CDN、ELB、WAF 等服务 | | [火山引擎](https://www.volcengine.com/) | 可部署到火山引擎 TOS、CDN、DCDN、CLB、ImageX、Live 等服务 | -| [京东云](https://www.jdcloud.com/) | 可部署到京东云 CDN、ALB、视频直播等服务 | +| [京东云](https://www.jdcloud.com/) | 可部署到京东云 CDN、ALB、视频直播、视频点播等服务 | | [七牛云](https://www.qiniu.com/) | 可部署到七牛云 CDN、直播云等服务 | | [白山云](https://www.baishan.com/) | 可部署到白山云 CDN | | [多吉云](https://www.dogecloud.com/) | 可部署到多吉云 CDN | diff --git a/README_EN.md b/README_EN.md index 7ced5c04..b8f2e2dc 100644 --- a/README_EN.md +++ b/README_EN.md @@ -129,7 +129,7 @@ The following hosting providers are supported: | [Baidu AI Cloud](https://intl.cloud.baidu.com/) | Supports deployment to Baidu AI CLoud CDN | | [Huawei Cloud](https://www.huaweicloud.com/) | Supports deployment to Huawei Cloud CDN, ELB, WAF | | [Volcengine](https://www.volcengine.com/) | Supports deployment to Volcengine TOS, CDN, DCDN, CLB, ImageX, Live | -| [JD Cloud](https://www.jdcloud.com/) | Supports deployment to JD Cloud CDN, ALB, Live Video | +| [JD Cloud](https://www.jdcloud.com/) | Supports deployment to JD Cloud CDN, ALB, Live Video, VOD | | [Qiniu Cloud](https://www.qiniu.com/) | Supports deployment to Qiniu Cloud CDN, Pili | | [Baishan Cloud](https://intl.baishancloud.com/) | Supports deployment to Baishan Cloud CDN | | [Doge Cloud](https://www.dogecloud.com/) | Supports deployment to Doge Cloud CDN | diff --git a/internal/deployer/providers.go b/internal/deployer/providers.go index 8da7fd0a..6a8a0b6c 100644 --- a/internal/deployer/providers.go +++ b/internal/deployer/providers.go @@ -34,6 +34,7 @@ import ( pJDCloudALB "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/jdcloud-alb" pJDCloudCDN "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/jdcloud-cdn" pJDCloudLive "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/jdcloud-live" + pJDCloudVOD "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/jdcloud-vod" pK8sSecret "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/k8s-secret" pLocal "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/local" pQiniuCDN "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/qiniu-cdn" @@ -429,7 +430,7 @@ func createDeployer(options *deployerOptions) (deployer.Deployer, error) { } } - case domain.DeployProviderTypeJDCloudALB, domain.DeployProviderTypeJDCloudCDN, domain.DeployProviderTypeJDCloudLive: + case domain.DeployProviderTypeJDCloudALB, domain.DeployProviderTypeJDCloudCDN, domain.DeployProviderTypeJDCloudLive, domain.DeployProviderTypeJDCloudVOD: { access := domain.AccessConfigForJDCloud{} if err := maps.Populate(options.ProviderAccessConfig, &access); err != nil { @@ -464,6 +465,14 @@ func createDeployer(options *deployerOptions) (deployer.Deployer, error) { }) return deployer, err + case domain.DeployProviderTypeJDCloudVOD: + deployer, err := pJDCloudVOD.NewDeployer(&pJDCloudVOD.DeployerConfig{ + AccessKeyId: access.AccessKeyId, + AccessKeySecret: access.AccessKeySecret, + Domain: maps.GetValueAsString(options.ProviderDeployConfig, "domain"), + }) + return deployer, err + default: break } diff --git a/internal/domain/provider.go b/internal/domain/provider.go index 17e959e6..7402cadf 100644 --- a/internal/domain/provider.go +++ b/internal/domain/provider.go @@ -131,6 +131,7 @@ const ( DeployProviderTypeJDCloudALB = DeployProviderType("jdcloud-alb") DeployProviderTypeJDCloudCDN = DeployProviderType("jdcloud-cdn") DeployProviderTypeJDCloudLive = DeployProviderType("jdcloud-live") + DeployProviderTypeJDCloudVOD = DeployProviderType("jdcloud-vod") DeployProviderTypeKubernetesSecret = DeployProviderType("k8s-secret") DeployProviderTypeLocal = DeployProviderType("local") DeployProviderTypeQiniuCDN = DeployProviderType("qiniu-cdn") diff --git a/internal/pkg/core/deployer/providers/jdcloud-vod/jdcloud_vod.go b/internal/pkg/core/deployer/providers/jdcloud-vod/jdcloud_vod.go new file mode 100644 index 00000000..8db109c1 --- /dev/null +++ b/internal/pkg/core/deployer/providers/jdcloud-vod/jdcloud_vod.go @@ -0,0 +1,122 @@ +package jdcloudvod + +import ( + "context" + "fmt" + "strconv" + "time" + + jdCore "github.com/jdcloud-api/jdcloud-sdk-go/core" + jdVodApi "github.com/jdcloud-api/jdcloud-sdk-go/services/vod/apis" + jdVodClient "github.com/jdcloud-api/jdcloud-sdk-go/services/vod/client" + xerrors "github.com/pkg/errors" + + "github.com/usual2970/certimate/internal/pkg/core/deployer" + "github.com/usual2970/certimate/internal/pkg/core/logger" +) + +type DeployerConfig struct { + // 京东云 AccessKeyId。 + AccessKeyId string `json:"accessKeyId"` + // 京东云 AccessKeySecret。 + AccessKeySecret string `json:"accessKeySecret"` + // 点播加速域名(不支持泛域名)。 + Domain string `json:"domain"` +} + +type DeployerProvider struct { + config *DeployerConfig + logger logger.Logger + sdkClient *jdVodClient.VodClient +} + +var _ deployer.Deployer = (*DeployerProvider)(nil) + +func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { + if config == nil { + panic("config is nil") + } + + client, err := createSdkClient(config.AccessKeyId, config.AccessKeySecret) + if err != nil { + return nil, xerrors.Wrap(err, "failed to create sdk client") + } + + return &DeployerProvider{ + config: config, + logger: logger.NewNilLogger(), + sdkClient: client, + }, nil +} + +func (d *DeployerProvider) WithLogger(logger logger.Logger) *DeployerProvider { + d.logger = logger + return d +} + +func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { + // 查询域名列表 + // REF: https://docs.jdcloud.com/cn/video-on-demand/api/listdomains + var domainId int + listDomainsPageNumber := 1 + listDomainsPageSize := 100 + for { + listDomainsReq := jdVodApi.NewListDomainsRequest() + listDomainsReq.SetPageNumber(1) + listDomainsReq.SetPageSize(100) + listDomainsResp, err := d.sdkClient.ListDomains(listDomainsReq) + if err != nil { + return nil, xerrors.Wrap(err, "failed to execute sdk request 'vod.ListDomains'") + } + + for _, domain := range listDomainsResp.Result.Content { + if domain.Name == d.config.Domain { + domainId, _ = strconv.Atoi(domain.Id) + break + } + } + + if len(listDomainsResp.Result.Content) < listDomainsPageSize { + break + } else { + listDomainsPageNumber++ + } + } + if domainId == 0 { + return nil, xerrors.New("domain not found") + } + + // 查询域名 SSL 配置 + // REF: https://docs.jdcloud.com/cn/video-on-demand/api/gethttpssl + getHttpSslReq := jdVodApi.NewGetHttpSslRequest(domainId) + getHttpSslResp, err := d.sdkClient.GetHttpSsl(getHttpSslReq) + if err != nil { + return nil, xerrors.Wrap(err, "failed to execute sdk request 'vod.GetHttpSsl'") + } else { + d.logger.Logt("已查询到域名 SSL 配置", getHttpSslResp) + } + + // 设置域名 SSL 配置 + // REF: https://docs.jdcloud.com/cn/video-on-demand/api/sethttpssl + setHttpSslReq := jdVodApi.NewSetHttpSslRequest(domainId) + setHttpSslReq.SetTitle(fmt.Sprintf("certimate-%d", time.Now().UnixMilli())) + setHttpSslReq.SetSslCert(certPem) + setHttpSslReq.SetSslKey(privkeyPem) + setHttpSslReq.SetSource("default") + setHttpSslReq.SetJumpType(getHttpSslResp.Result.JumpType) + setHttpSslReq.SetEnabled(true) + setHttpSslResp, err := d.sdkClient.SetHttpSsl(setHttpSslReq) + if err != nil { + return nil, xerrors.Wrap(err, "failed to execute sdk request 'vod.SetHttpSsl'") + } else { + d.logger.Logt("已设置域名 SSL 配置", setHttpSslResp) + } + + return &deployer.DeployResult{}, nil +} + +func createSdkClient(accessKeyId, accessKeySecret string) (*jdVodClient.VodClient, error) { + clientCredentials := jdCore.NewCredentials(accessKeyId, accessKeySecret) + client := jdVodClient.NewVodClient(clientCredentials) + return client, nil +} diff --git a/internal/pkg/core/deployer/providers/jdcloud-vod/jdcloud_vod_test.go b/internal/pkg/core/deployer/providers/jdcloud-vod/jdcloud_vod_test.go new file mode 100644 index 00000000..6046982b --- /dev/null +++ b/internal/pkg/core/deployer/providers/jdcloud-vod/jdcloud_vod_test.go @@ -0,0 +1,75 @@ +package jdcloudvod_test + +import ( + "context" + "flag" + "fmt" + "os" + "strings" + "testing" + + provider "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/jdcloud-vod" +) + +var ( + fInputCertPath string + fInputKeyPath string + fAccessKeyId string + fAccessKeySecret string + fDomain string +) + +func init() { + argsPrefix := "CERTIMATE_DEPLOYER_JDCLOUDVOD_" + + flag.StringVar(&fInputCertPath, argsPrefix+"INPUTCERTPATH", "", "") + flag.StringVar(&fInputKeyPath, argsPrefix+"INPUTKEYPATH", "", "") + flag.StringVar(&fAccessKeyId, argsPrefix+"ACCESSKEYID", "", "") + flag.StringVar(&fAccessKeySecret, argsPrefix+"ACCESSKEYSECRET", "", "") + flag.StringVar(&fDomain, argsPrefix+"DOMAIN", "", "") +} + +/* +Shell command to run this test: + + go test -v ./jdcloud_vod_test.go -args \ + --CERTIMATE_DEPLOYER_JDCLOUDVOD_INPUTCERTPATH="/path/to/your-input-cert.pem" \ + --CERTIMATE_DEPLOYER_JDCLOUDVOD_INPUTKEYPATH="/path/to/your-input-key.pem" \ + --CERTIMATE_DEPLOYER_JDCLOUDVOD_ACCESSKEYID="your-access-key-id" \ + --CERTIMATE_DEPLOYER_JDCLOUDVOD_ACCESSKEYSECRET="your-secret-access-key" \ + --CERTIMATE_DEPLOYER_JDCLOUDVOD_DOMAIN="example.com" +*/ +func TestDeploy(t *testing.T) { + flag.Parse() + + t.Run("Deploy", func(t *testing.T) { + t.Log(strings.Join([]string{ + "args:", + fmt.Sprintf("INPUTCERTPATH: %v", fInputCertPath), + fmt.Sprintf("INPUTKEYPATH: %v", fInputKeyPath), + fmt.Sprintf("ACCESSKEYID: %v", fAccessKeyId), + fmt.Sprintf("ACCESSKEYSECRET: %v", fAccessKeySecret), + fmt.Sprintf("DOMAIN: %v", fDomain), + }, "\n")) + + deployer, err := provider.NewDeployer(&provider.DeployerConfig{ + AccessKeyId: fAccessKeyId, + AccessKeySecret: fAccessKeySecret, + Domain: fDomain, + }) + if err != nil { + t.Errorf("err: %+v", err) + return + } + + fInputCertData, _ := os.ReadFile(fInputCertPath) + fInputKeyData, _ := os.ReadFile(fInputKeyPath) + res, err := deployer.Deploy(context.Background(), string(fInputCertData), string(fInputKeyData)) + if err != nil { + t.Errorf("err: %+v", err) + return + } + + t.Logf("ok: %v", res) + }) +} diff --git a/internal/pkg/core/uploader/providers/jdcloud-ssl/jdcloud_ssl.go b/internal/pkg/core/uploader/providers/jdcloud-ssl/jdcloud_ssl.go index 6368bc51..b53bf87c 100644 --- a/internal/pkg/core/uploader/providers/jdcloud-ssl/jdcloud_ssl.go +++ b/internal/pkg/core/uploader/providers/jdcloud-ssl/jdcloud_ssl.go @@ -67,9 +67,9 @@ func (u *UploaderProvider) Upload(ctx context.Context, certPem string, privkeyPe describeCertsPageSize := 100 for { describeCertsReq := jdSslApi.NewDescribeCertsRequest() - describeCertsReq.DomainName = &certX509.Subject.CommonName - describeCertsReq.PageNumber = &describeCertsPageNumber - describeCertsReq.PageSize = &describeCertsPageSize + describeCertsReq.SetDomainName(certX509.Subject.CommonName) + describeCertsReq.SetPageNumber(describeCertsPageNumber) + describeCertsReq.SetPageSize(describeCertsPageSize) describeCertsResp, err := u.sdkClient.DescribeCerts(describeCertsReq) if err != nil { return nil, xerrors.Wrap(err, "failed to execute sdk request 'ssl.DescribeCerts'") diff --git a/ui/src/components/workflow/node/DeployNodeConfigForm.tsx b/ui/src/components/workflow/node/DeployNodeConfigForm.tsx index 000b67e3..b9f65b08 100644 --- a/ui/src/components/workflow/node/DeployNodeConfigForm.tsx +++ b/ui/src/components/workflow/node/DeployNodeConfigForm.tsx @@ -42,6 +42,7 @@ import DeployNodeConfigFormHuaweiCloudWAFConfig from "./DeployNodeConfigFormHuaw import DeployNodeConfigFormJDCloudALBConfig from "./DeployNodeConfigFormJDCloudALBConfig"; import DeployNodeConfigFormJDCloudCDNConfig from "./DeployNodeConfigFormJDCloudCDNConfig"; import DeployNodeConfigFormJDCloudLiveConfig from "./DeployNodeConfigFormJDCloudLiveConfig"; +import DeployNodeConfigFormJDCloudVODConfig from "./DeployNodeConfigFormJDCloudVODConfig"; import DeployNodeConfigFormKubernetesSecretConfig from "./DeployNodeConfigFormKubernetesSecretConfig"; import DeployNodeConfigFormLocalConfig from "./DeployNodeConfigFormLocalConfig"; import DeployNodeConfigFormQiniuCDNConfig from "./DeployNodeConfigFormQiniuCDNConfig"; @@ -191,6 +192,8 @@ const DeployNodeConfigForm = forwardRef; case DEPLOY_PROVIDERS.JDCLOUD_LIVE: return ; + case DEPLOY_PROVIDERS.JDCLOUD_VOD: + return ; case DEPLOY_PROVIDERS.KUBERNETES_SECRET: return ; case DEPLOY_PROVIDERS.LOCAL: diff --git a/ui/src/components/workflow/node/DeployNodeConfigFormJDCloudVODConfig.tsx b/ui/src/components/workflow/node/DeployNodeConfigFormJDCloudVODConfig.tsx new file mode 100644 index 00000000..ad64a735 --- /dev/null +++ b/ui/src/components/workflow/node/DeployNodeConfigFormJDCloudVODConfig.tsx @@ -0,0 +1,65 @@ +import { useTranslation } from "react-i18next"; +import { Form, type FormInstance, Input } from "antd"; +import { createSchemaFieldRule } from "antd-zod"; +import { z } from "zod"; + +import { validDomainName } from "@/utils/validators"; + +type DeployNodeConfigFormJDCloudVODConfigFieldValues = Nullish<{ + domain: string; +}>; + +export type DeployNodeConfigFormJDCloudVODConfigProps = { + form: FormInstance; + formName: string; + disabled?: boolean; + initialValues?: DeployNodeConfigFormJDCloudVODConfigFieldValues; + onValuesChange?: (values: DeployNodeConfigFormJDCloudVODConfigFieldValues) => void; +}; + +const initFormModel = (): DeployNodeConfigFormJDCloudVODConfigFieldValues => { + return {}; +}; + +const DeployNodeConfigFormJDCloudVODConfig = ({ + form: formInst, + formName, + disabled, + initialValues, + onValuesChange, +}: DeployNodeConfigFormJDCloudVODConfigProps) => { + const { t } = useTranslation(); + + const formSchema = z.object({ + domain: z + .string({ message: t("workflow_node.deploy.form.jdcloud_vod_domain.placeholder") }) + .refine((v) => validDomainName(v), t("common.errmsg.domain_invalid")), + }); + const formRule = createSchemaFieldRule(formSchema); + + const handleFormChange = (_: unknown, values: z.infer) => { + onValuesChange?.(values); + }; + + return ( +
+ } + > + + +
+ ); +}; + +export default DeployNodeConfigFormJDCloudVODConfig; diff --git a/ui/src/domain/provider.ts b/ui/src/domain/provider.ts index d549f4cd..13a82a4c 100644 --- a/ui/src/domain/provider.ts +++ b/ui/src/domain/provider.ts @@ -225,6 +225,7 @@ export const DEPLOY_PROVIDERS = Object.freeze({ JDCLOUD_ALB: `${ACCESS_PROVIDERS.JDCLOUD}-alb`, JDCLOUD_CDN: `${ACCESS_PROVIDERS.JDCLOUD}-cdn`, JDCLOUD_LIVE: `${ACCESS_PROVIDERS.JDCLOUD}-live`, + JDCLOUD_VOD: `${ACCESS_PROVIDERS.JDCLOUD}-vod`, KUBERNETES_SECRET: `${ACCESS_PROVIDERS.KUBERNETES}-secret`, LOCAL: `${ACCESS_PROVIDERS.LOCAL}`, QINIU_CDN: `${ACCESS_PROVIDERS.QINIU}-cdn`, @@ -317,6 +318,7 @@ export const deployProvidersMap: Maphttps://cdn-console.jdcloud.com/", "workflow_node.deploy.form.jdcloud_live_domain.label": "JD Cloud Live Video play domain", "workflow_node.deploy.form.jdcloud_live_domain.placeholder": "Please enter JD Cloud Live Video play domain name", - "workflow_node.deploy.form.jdcloud_live_domain.tooltip": "For more information, see https://docs.jdcloud.com/en/live-video/domain-management", + "workflow_node.deploy.form.jdcloud_live_domain.tooltip": "For more information, see https://live-console.jdcloud.com/", + "workflow_node.deploy.form.jdcloud_vod_domain.label": "JD Cloud VOD domain", + "workflow_node.deploy.form.jdcloud_vod_domain.placeholder": "Please enter JD Cloud VOD domain name", + "workflow_node.deploy.form.jdcloud_vod_domain.tooltip": "For more information, see https://vod-console.jdcloud.com/", "workflow_node.deploy.form.k8s_namespace.label": "Kubernetes Namespace", "workflow_node.deploy.form.k8s_namespace.placeholder": "Please enter Kubernetes Namespace", "workflow_node.deploy.form.k8s_namespace.tooltip": "For more information, see https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/", diff --git a/ui/src/i18n/locales/zh/nls.provider.json b/ui/src/i18n/locales/zh/nls.provider.json index 5b4e8ee3..101b0553 100644 --- a/ui/src/i18n/locales/zh/nls.provider.json +++ b/ui/src/i18n/locales/zh/nls.provider.json @@ -59,6 +59,7 @@ "provider.jdcloud.cdn": "京东云 - 内容分发网络 CDN", "provider.jdcloud.dns": "京东云 - 云解析 DNS", "provider.jdcloud.live": "京东云 - 视频直播", + "provider.jdcloud.vod": "京东云 - 视频点播", "provider.kubernetes": "Kubernetes", "provider.kubernetes.secret": "Kubernetes - Secret", "provider.local": "本地部署", @@ -99,7 +100,7 @@ "provider.category.all": "全部", "provider.category.cdn": "CDN", - "provider.category.storage": "存储", + "provider.category.storage": "文件存储", "provider.category.loadbalance": "负载均衡", "provider.category.firewall": "防火墙", "provider.category.av": "音视频", diff --git a/ui/src/i18n/locales/zh/nls.workflow.nodes.json b/ui/src/i18n/locales/zh/nls.workflow.nodes.json index 9298d2a8..a4c0998b 100644 --- a/ui/src/i18n/locales/zh/nls.workflow.nodes.json +++ b/ui/src/i18n/locales/zh/nls.workflow.nodes.json @@ -294,7 +294,10 @@ "workflow_node.deploy.form.jdcloud_cdn_domain.tooltip": "这是什么?请参阅 https://cdn-console.jdcloud.com/", "workflow_node.deploy.form.jdcloud_live_domain.label": "京东云视频直播播放域名", "workflow_node.deploy.form.jdcloud_live_domain.placeholder": "请输入京东云视频直播播放域名", - "workflow_node.deploy.form.jdcloud_live_domain.tooltip": "这是什么?请参阅 https://docs.jdcloud.com/cn/live-video/domain-management", + "workflow_node.deploy.form.jdcloud_live_domain.tooltip": "这是什么?请参阅 https://live-console.jdcloud.com", + "workflow_node.deploy.form.jdcloud_vod_domain.label": "京东云视频点播加速域名", + "workflow_node.deploy.form.jdcloud_vod_domain.placeholder": "请输入京东云视频点播加速域名", + "workflow_node.deploy.form.jdcloud_vod_domain.tooltip": "这是什么?请参阅 https://vod-console.jdcloud.com/", "workflow_node.deploy.form.k8s_namespace.label": "Kubernetes 命名空间", "workflow_node.deploy.form.k8s_namespace.placeholder": "请输入 Kubernetes 命名空间", "workflow_node.deploy.form.k8s_namespace.tooltip": "这是什么?请参阅 https://kubernetes.io/zh-cn/docs/concepts/overview/working-with-objects/namespaces/", From 6f94f4d8824476fafc5921a219f9ccbdfc5fa8ab Mon Sep 17 00:00:00 2001 From: Fu Diwei Date: Thu, 20 Feb 2025 22:20:18 +0800 Subject: [PATCH 27/34] refactor: reimpl custom lego dns providers --- .../baiducloud/internal/lego.go | 41 +++++++++++-------- .../lego-providers/gname/internal/lego.go | 39 +++++++++++------- .../lego-providers/jdcloud/internal/lego.go | 33 +++++++++------ 3 files changed, 70 insertions(+), 43 deletions(-) diff --git a/internal/pkg/core/applicant/acme-dns-01/lego-providers/baiducloud/internal/lego.go b/internal/pkg/core/applicant/acme-dns-01/lego-providers/baiducloud/internal/lego.go index 558ad5eb..721326a7 100644 --- a/internal/pkg/core/applicant/acme-dns-01/lego-providers/baiducloud/internal/lego.go +++ b/internal/pkg/core/applicant/acme-dns-01/lego-providers/baiducloud/internal/lego.go @@ -87,17 +87,17 @@ func NewDNSProviderConfig(config *Config) (*DNSProvider, error) { func (d *DNSProvider) Present(domain, token, keyAuth string) error { info := dns01.GetChallengeInfo(domain, keyAuth) - zoneName, err := dns01.FindZoneByFqdn(info.EffectiveFQDN) + authZone, err := dns01.FindZoneByFqdn(info.EffectiveFQDN) if err != nil { return fmt.Errorf("baiducloud: %w", err) } - subDomain, err := dns01.ExtractSubDomain(info.EffectiveFQDN, zoneName) + subDomain, err := dns01.ExtractSubDomain(info.EffectiveFQDN, authZone) if err != nil { return fmt.Errorf("baiducloud: %w", err) } - if err := d.addOrUpdateDNSRecord(domain, subDomain, info.Value); err != nil { + if err := d.addOrUpdateDNSRecord(dns01.UnFqdn(authZone), subDomain, info.Value); err != nil { return fmt.Errorf("baiducloud: %w", err) } @@ -105,10 +105,19 @@ func (d *DNSProvider) Present(domain, token, keyAuth string) error { } func (d *DNSProvider) CleanUp(domain, token, keyAuth string) error { - fqdn, value := dns01.GetRecord(domain, keyAuth) - subDomain := dns01.UnFqdn(fqdn) + info := dns01.GetChallengeInfo(domain, keyAuth) - if err := d.removeDNSRecord(domain, subDomain, value); err != nil { + authZone, err := dns01.FindZoneByFqdn(info.EffectiveFQDN) + if err != nil { + return fmt.Errorf("baiducloud: %w", err) + } + + subDomain, err := dns01.ExtractSubDomain(info.EffectiveFQDN, authZone) + if err != nil { + return fmt.Errorf("baiducloud: %w", err) + } + + if err := d.removeDNSRecord(dns01.UnFqdn(authZone), subDomain); err != nil { return fmt.Errorf("baiducloud: %w", err) } @@ -119,16 +128,16 @@ func (d *DNSProvider) Timeout() (timeout, interval time.Duration) { return d.config.PropagationTimeout, d.config.PollingInterval } -func (d *DNSProvider) getDNSRecord(domain, subDomain string) (*bceDns.Record, error) { +func (d *DNSProvider) getDNSRecord(zoneName, subDomain string) (*bceDns.Record, error) { pageMarker := "" pageSize := 1000 for { request := &bceDns.ListRecordRequest{} - request.Rr = domain + request.Rr = zoneName request.Marker = pageMarker request.MaxKeys = pageSize - response, err := d.client.ListRecord(domain, request) + response, err := d.client.ListRecord(zoneName, request) if err != nil { return nil, err } @@ -149,8 +158,8 @@ func (d *DNSProvider) getDNSRecord(domain, subDomain string) (*bceDns.Record, er return nil, nil } -func (d *DNSProvider) addOrUpdateDNSRecord(domain, subDomain, value string) error { - record, err := d.getDNSRecord(domain, subDomain) +func (d *DNSProvider) addOrUpdateDNSRecord(zoneName, subDomain, value string) error { + record, err := d.getDNSRecord(zoneName, subDomain) if err != nil { return err } @@ -162,7 +171,7 @@ func (d *DNSProvider) addOrUpdateDNSRecord(domain, subDomain, value string) erro Value: value, Ttl: &d.config.TTL, } - err := d.client.CreateRecord(domain, request, d.generateClientToken()) + err := d.client.CreateRecord(zoneName, request, d.generateClientToken()) return err } else { request := &bceDns.UpdateRecordRequest{ @@ -171,13 +180,13 @@ func (d *DNSProvider) addOrUpdateDNSRecord(domain, subDomain, value string) erro Value: value, Ttl: &d.config.TTL, } - err := d.client.UpdateRecord(domain, record.Id, request, d.generateClientToken()) + err := d.client.UpdateRecord(zoneName, record.Id, request, d.generateClientToken()) return err } } -func (d *DNSProvider) removeDNSRecord(domain, subDomain, value string) error { - record, err := d.getDNSRecord(domain, subDomain) +func (d *DNSProvider) removeDNSRecord(zoneName, subDomain string) error { + record, err := d.getDNSRecord(zoneName, subDomain) if err != nil { return err } @@ -185,7 +194,7 @@ func (d *DNSProvider) removeDNSRecord(domain, subDomain, value string) error { if record == nil { return nil } else { - err = d.client.DeleteRecord(domain, record.Id, d.generateClientToken()) + err = d.client.DeleteRecord(zoneName, record.Id, d.generateClientToken()) return err } } diff --git a/internal/pkg/core/applicant/acme-dns-01/lego-providers/gname/internal/lego.go b/internal/pkg/core/applicant/acme-dns-01/lego-providers/gname/internal/lego.go index 94a8c35d..17e9162f 100644 --- a/internal/pkg/core/applicant/acme-dns-01/lego-providers/gname/internal/lego.go +++ b/internal/pkg/core/applicant/acme-dns-01/lego-providers/gname/internal/lego.go @@ -80,17 +80,17 @@ func NewDNSProviderConfig(config *Config) (*DNSProvider, error) { func (d *DNSProvider) Present(domain, token, keyAuth string) error { info := dns01.GetChallengeInfo(domain, keyAuth) - zoneName, err := dns01.FindZoneByFqdn(info.EffectiveFQDN) + authZone, err := dns01.FindZoneByFqdn(info.EffectiveFQDN) if err != nil { return fmt.Errorf("gname: %w", err) } - subDomain, err := dns01.ExtractSubDomain(info.EffectiveFQDN, zoneName) + subDomain, err := dns01.ExtractSubDomain(info.EffectiveFQDN, authZone) if err != nil { return fmt.Errorf("gname: %w", err) } - if err := d.addOrUpdateDNSRecord(domain, subDomain, info.Value); err != nil { + if err := d.addOrUpdateDNSRecord(dns01.UnFqdn(authZone), subDomain, info.Value); err != nil { return fmt.Errorf("gname: %w", err) } @@ -98,10 +98,19 @@ func (d *DNSProvider) Present(domain, token, keyAuth string) error { } func (d *DNSProvider) CleanUp(domain, token, keyAuth string) error { - fqdn, value := dns01.GetRecord(domain, keyAuth) - subDomain := dns01.UnFqdn(fqdn) + info := dns01.GetChallengeInfo(domain, keyAuth) - if err := d.removeDNSRecord(domain, subDomain, value); err != nil { + authZone, err := dns01.FindZoneByFqdn(info.EffectiveFQDN) + if err != nil { + return fmt.Errorf("gname: %w", err) + } + + subDomain, err := dns01.ExtractSubDomain(info.EffectiveFQDN, authZone) + if err != nil { + return fmt.Errorf("gname: %w", err) + } + + if err := d.removeDNSRecord(dns01.UnFqdn(authZone), subDomain); err != nil { return fmt.Errorf("gname: %w", err) } @@ -112,12 +121,12 @@ func (d *DNSProvider) Timeout() (timeout, interval time.Duration) { return d.config.PropagationTimeout, d.config.PollingInterval } -func (d *DNSProvider) getDNSRecord(domain, subDomain string) (*gnamesdk.ResolutionRecord, error) { +func (d *DNSProvider) getDNSRecord(zoneName, subDomain string) (*gnamesdk.ResolutionRecord, error) { page := 1 pageSize := 20 for { request := &gnamesdk.ListDomainResolutionRequest{} - request.ZoneName = domain + request.ZoneName = zoneName request.Page = &page request.PageSize = &pageSize @@ -145,15 +154,15 @@ func (d *DNSProvider) getDNSRecord(domain, subDomain string) (*gnamesdk.Resoluti return nil, nil } -func (d *DNSProvider) addOrUpdateDNSRecord(domain, subDomain, value string) error { - record, err := d.getDNSRecord(domain, subDomain) +func (d *DNSProvider) addOrUpdateDNSRecord(zoneName, subDomain, value string) error { + record, err := d.getDNSRecord(zoneName, subDomain) if err != nil { return err } if record == nil { request := &gnamesdk.AddDomainResolutionRequest{ - ZoneName: domain, + ZoneName: zoneName, RecordType: "TXT", RecordName: subDomain, RecordValue: value, @@ -164,7 +173,7 @@ func (d *DNSProvider) addOrUpdateDNSRecord(domain, subDomain, value string) erro } else { request := &gnamesdk.ModifyDomainResolutionRequest{ ID: record.ID, - ZoneName: domain, + ZoneName: zoneName, RecordType: "TXT", RecordName: subDomain, RecordValue: value, @@ -175,8 +184,8 @@ func (d *DNSProvider) addOrUpdateDNSRecord(domain, subDomain, value string) erro } } -func (d *DNSProvider) removeDNSRecord(domain, subDomain, value string) error { - record, err := d.getDNSRecord(domain, subDomain) +func (d *DNSProvider) removeDNSRecord(zoneName, subDomain string) error { + record, err := d.getDNSRecord(zoneName, subDomain) if err != nil { return err } @@ -186,7 +195,7 @@ func (d *DNSProvider) removeDNSRecord(domain, subDomain, value string) error { } request := &gnamesdk.DeleteDomainResolutionRequest{ - ZoneName: domain, + ZoneName: zoneName, RecordID: record.ID, } _, err = d.client.DeleteDomainResolution(request) diff --git a/internal/pkg/core/applicant/acme-dns-01/lego-providers/jdcloud/internal/lego.go b/internal/pkg/core/applicant/acme-dns-01/lego-providers/jdcloud/internal/lego.go index a85fa79c..d5103023 100644 --- a/internal/pkg/core/applicant/acme-dns-01/lego-providers/jdcloud/internal/lego.go +++ b/internal/pkg/core/applicant/acme-dns-01/lego-providers/jdcloud/internal/lego.go @@ -88,17 +88,17 @@ func NewDNSProviderConfig(config *Config) (*DNSProvider, error) { func (d *DNSProvider) Present(domain, token, keyAuth string) error { info := dns01.GetChallengeInfo(domain, keyAuth) - zoneName, err := dns01.FindZoneByFqdn(info.EffectiveFQDN) + authZone, err := dns01.FindZoneByFqdn(info.EffectiveFQDN) if err != nil { return fmt.Errorf("jdcloud: %w", err) } - subDomain, err := dns01.ExtractSubDomain(info.EffectiveFQDN, zoneName) + subDomain, err := dns01.ExtractSubDomain(info.EffectiveFQDN, authZone) if err != nil { return fmt.Errorf("jdcloud: %w", err) } - if err := d.addOrUpdateDNSRecord(domain, subDomain, info.Value); err != nil { + if err := d.addOrUpdateDNSRecord(dns01.UnFqdn(authZone), subDomain, info.Value); err != nil { return fmt.Errorf("jdcloud: %w", err) } @@ -106,10 +106,19 @@ func (d *DNSProvider) Present(domain, token, keyAuth string) error { } func (d *DNSProvider) CleanUp(domain, token, keyAuth string) error { - fqdn, value := dns01.GetRecord(domain, keyAuth) - subDomain := dns01.UnFqdn(fqdn) + info := dns01.GetChallengeInfo(domain, keyAuth) - if err := d.removeDNSRecord(domain, subDomain, value); err != nil { + authZone, err := dns01.FindZoneByFqdn(info.EffectiveFQDN) + if err != nil { + return fmt.Errorf("jdcloud: %w", err) + } + + subDomain, err := dns01.ExtractSubDomain(info.EffectiveFQDN, authZone) + if err != nil { + return fmt.Errorf("jdcloud: %w", err) + } + + if err := d.removeDNSRecord(dns01.UnFqdn(authZone), subDomain); err != nil { return fmt.Errorf("jdcloud: %w", err) } @@ -151,8 +160,8 @@ func (d *DNSProvider) getDNSZone(domain string) (*jdDnsModel.DomainInfo, error) return nil, fmt.Errorf("jdcloud: zone %s not found", domain) } -func (d *DNSProvider) getDNSZoneAndRecord(domain, subDomain string) (*jdDnsModel.DomainInfo, *jdDnsModel.RRInfo, error) { - zone, err := d.getDNSZone(domain) +func (d *DNSProvider) getDNSZoneAndRecord(zoneName, subDomain string) (*jdDnsModel.DomainInfo, *jdDnsModel.RRInfo, error) { + zone, err := d.getDNSZone(zoneName) if err != nil { return nil, nil, err } @@ -186,8 +195,8 @@ func (d *DNSProvider) getDNSZoneAndRecord(domain, subDomain string) (*jdDnsModel return nil, nil, nil } -func (d *DNSProvider) addOrUpdateDNSRecord(domain, subDomain, value string) error { - zone, record, err := d.getDNSZoneAndRecord(domain, subDomain) +func (d *DNSProvider) addOrUpdateDNSRecord(zoneName, subDomain, value string) error { + zone, record, err := d.getDNSZoneAndRecord(zoneName, subDomain) if err != nil { return err } @@ -213,8 +222,8 @@ func (d *DNSProvider) addOrUpdateDNSRecord(domain, subDomain, value string) erro } } -func (d *DNSProvider) removeDNSRecord(domain, subDomain, value string) error { - zone, record, err := d.getDNSZoneAndRecord(domain, subDomain) +func (d *DNSProvider) removeDNSRecord(zoneName, subDomain string) error { + zone, record, err := d.getDNSZoneAndRecord(zoneName, subDomain) if err != nil { return err } From 543d2d9d5062065163d96a9577fcdcf471e70ec8 Mon Sep 17 00:00:00 2001 From: Fu Diwei Date: Thu, 20 Feb 2025 23:42:07 +0800 Subject: [PATCH 28/34] feat: add cmcccloud dns-01 applicant --- README.md | 1 + README_EN.md | 1 + go.mod | 5 + internal/applicant/providers.go | 17 + internal/domain/access.go | 5 + internal/domain/provider.go | 3 +- .../lego-providers/cmcccloud/cmcccloud.go | 40 ++ .../lego-providers/cmcccloud/internal/lego.go | 221 ++++++++ internal/pkg/vendors/cmcc-sdk/README.md | 14 + .../ecloudsdkclouddns@v1.0.1/client.go | 144 +++++ .../cmcc-sdk/ecloudsdkclouddns@v1.0.1/go.mod | 7 + .../model/create_record_body.go | 54 ++ .../model/create_record_openapi_body.go | 51 ++ .../model/create_record_openapi_request.go | 12 + .../model/create_record_openapi_response.go | 29 + .../create_record_openapi_response_body.go | 80 +++ .../create_record_openapi_response_tags.go | 16 + .../model/create_record_request.go | 12 + .../model/create_record_response.go | 29 + .../model/create_record_response_body.go | 94 ++++ .../model/create_record_response_tags.go | 16 + .../model/delete_record_body.go | 15 + .../model/delete_record_openapi_body.go | 15 + .../model/delete_record_openapi_request.go | 12 + .../model/delete_record_openapi_response.go | 29 + .../delete_record_openapi_response_body.go | 29 + .../model/delete_record_request.go | 12 + .../model/delete_record_response.go | 29 + .../model/delete_record_response_body.go | 29 + .../model/list_record_body.go | 18 + .../model/list_record_openapi_body.go | 15 + .../model/list_record_openapi_query.go | 18 + .../model/list_record_openapi_request.go | 14 + .../model/list_record_openapi_response.go | 29 + .../list_record_openapi_response_body.go | 25 + .../list_record_openapi_response_data.go | 91 ++++ .../list_record_openapi_response_tags.go | 16 + .../model/list_record_query.go | 18 + .../model/list_record_request.go | 14 + .../model/list_record_response.go | 29 + .../model/list_record_response_body.go | 22 + .../model/list_record_response_results.go | 91 ++++ .../model/modify_record_body.go | 57 ++ .../model/modify_record_openapi_body.go | 54 ++ .../model/modify_record_openapi_request.go | 12 + .../model/modify_record_openapi_response.go | 29 + .../modify_record_openapi_response_body.go | 91 ++++ .../modify_record_openapi_response_tags.go | 16 + .../model/modify_record_request.go | 12 + .../model/modify_record_response.go | 29 + .../model/modify_record_response_body.go | 77 +++ .../ecloudsdkcore@v1.0.0/api_client.go | 507 ++++++++++++++++++ .../ecloudsdkcore@v1.0.0/api_response.go | 64 +++ .../ecloudsdkcore@v1.0.0/config/config.go | 9 + .../ecloudsdkcore@v1.0.0/configuration.go | 32 ++ .../cmcc-sdk/ecloudsdkcore@v1.0.0/go.mod | 3 + .../ecloudsdkcore@v1.0.0/http_request.go | 22 + .../ecloudsdkcore@v1.0.0/open_api_request.go | 16 + .../position/http_position.go | 13 + .../vendors/edgio-sdk/applications/README.md | 1 + .../edgio-sdk/applications/v7/README.md | 3 - ui/public/imgs/providers/cmcccloud.svg | 1 + ui/src/components/access/AccessForm.tsx | 3 + .../access/AccessFormCMCCCloudConfig.tsx | 75 +++ ui/src/domain/access.ts | 6 + ui/src/domain/provider.ts | 4 + ui/src/i18n/locales/en/nls.access.json | 6 + ui/src/i18n/locales/zh/nls.access.json | 6 + 68 files changed, 2565 insertions(+), 4 deletions(-) create mode 100644 internal/pkg/core/applicant/acme-dns-01/lego-providers/cmcccloud/cmcccloud.go create mode 100644 internal/pkg/core/applicant/acme-dns-01/lego-providers/cmcccloud/internal/lego.go create mode 100644 internal/pkg/vendors/cmcc-sdk/README.md create mode 100644 internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/client.go create mode 100644 internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/go.mod create mode 100644 internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/create_record_body.go create mode 100644 internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/create_record_openapi_body.go create mode 100644 internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/create_record_openapi_request.go create mode 100644 internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/create_record_openapi_response.go create mode 100644 internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/create_record_openapi_response_body.go create mode 100644 internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/create_record_openapi_response_tags.go create mode 100644 internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/create_record_request.go create mode 100644 internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/create_record_response.go create mode 100644 internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/create_record_response_body.go create mode 100644 internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/create_record_response_tags.go create mode 100644 internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/delete_record_body.go create mode 100644 internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/delete_record_openapi_body.go create mode 100644 internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/delete_record_openapi_request.go create mode 100644 internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/delete_record_openapi_response.go create mode 100644 internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/delete_record_openapi_response_body.go create mode 100644 internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/delete_record_request.go create mode 100644 internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/delete_record_response.go create mode 100644 internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/delete_record_response_body.go create mode 100644 internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/list_record_body.go create mode 100644 internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/list_record_openapi_body.go create mode 100644 internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/list_record_openapi_query.go create mode 100644 internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/list_record_openapi_request.go create mode 100644 internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/list_record_openapi_response.go create mode 100644 internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/list_record_openapi_response_body.go create mode 100644 internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/list_record_openapi_response_data.go create mode 100644 internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/list_record_openapi_response_tags.go create mode 100644 internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/list_record_query.go create mode 100644 internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/list_record_request.go create mode 100644 internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/list_record_response.go create mode 100644 internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/list_record_response_body.go create mode 100644 internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/list_record_response_results.go create mode 100644 internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/modify_record_body.go create mode 100644 internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/modify_record_openapi_body.go create mode 100644 internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/modify_record_openapi_request.go create mode 100644 internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/modify_record_openapi_response.go create mode 100644 internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/modify_record_openapi_response_body.go create mode 100644 internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/modify_record_openapi_response_tags.go create mode 100644 internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/modify_record_request.go create mode 100644 internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/modify_record_response.go create mode 100644 internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/modify_record_response_body.go create mode 100644 internal/pkg/vendors/cmcc-sdk/ecloudsdkcore@v1.0.0/api_client.go create mode 100644 internal/pkg/vendors/cmcc-sdk/ecloudsdkcore@v1.0.0/api_response.go create mode 100644 internal/pkg/vendors/cmcc-sdk/ecloudsdkcore@v1.0.0/config/config.go create mode 100644 internal/pkg/vendors/cmcc-sdk/ecloudsdkcore@v1.0.0/configuration.go create mode 100644 internal/pkg/vendors/cmcc-sdk/ecloudsdkcore@v1.0.0/go.mod create mode 100644 internal/pkg/vendors/cmcc-sdk/ecloudsdkcore@v1.0.0/http_request.go create mode 100644 internal/pkg/vendors/cmcc-sdk/ecloudsdkcore@v1.0.0/open_api_request.go create mode 100644 internal/pkg/vendors/cmcc-sdk/ecloudsdkcore@v1.0.0/position/http_position.go create mode 100644 internal/pkg/vendors/edgio-sdk/applications/README.md delete mode 100644 internal/pkg/vendors/edgio-sdk/applications/v7/README.md create mode 100644 ui/public/imgs/providers/cmcccloud.svg create mode 100644 ui/src/components/access/AccessFormCMCCCloudConfig.tsx diff --git a/README.md b/README.md index 5d11c865..10987477 100644 --- a/README.md +++ b/README.md @@ -104,6 +104,7 @@ make local.run | [Name.com](https://www.name.com/) | | | [NameSilo](https://www.namesilo.com/) | | | [IBM NS1 Connect](https://www.ibm.com/cn-zh/products/ns1-connect/) | | +| [移动云](https://ecloud.10086.cn/) | | | [雨云](https://www.rainyun.com/) | | | [西部数码](https://www.west.cn/) | | | [PowerDNS](https://www.powerdns.com/) | | diff --git a/README_EN.md b/README_EN.md index b8f2e2dc..bd58f8bb 100644 --- a/README_EN.md +++ b/README_EN.md @@ -103,6 +103,7 @@ The following DNS providers are supported: | [Name.com](https://www.name.com/) | | | [NameSilo](https://www.namesilo.com/) | | | [IBM NS1 Connect](https://www.ibm.com/products/ns1-connect/) | | +| [CMCC Cloud](https://ecloud.10086.cn/) | | | [Rain Yun](https://www.rainyun.com/) | | | [West.cn](https://www.west.cn/) | | | [PowerDNS](https://www.powerdns.com/) | | diff --git a/go.mod b/go.mod index 78549ec1..5694ec54 100644 --- a/go.mod +++ b/go.mod @@ -105,6 +105,8 @@ require ( github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/vod v1.0.1102 // indirect github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/waf v1.0.1099 // indirect github.com/x448/float16 v0.8.4 // indirect + gitlab.ecloud.com/ecloud/ecloudsdkclouddns v1.0.1 // indirect + gitlab.ecloud.com/ecloud/ecloudsdkcore v1.0.0 // indirect go.mongodb.org/mongo-driver v1.17.2 // indirect gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect gopkg.in/inf.v0 v0.9.1 // indirect @@ -211,3 +213,6 @@ require ( modernc.org/memory v1.8.2 // indirect modernc.org/sqlite v1.34.5 // indirect ) + +replace gitlab.ecloud.com/ecloud/ecloudsdkcore v1.0.0 => ./internal/pkg/vendors/cmcc-sdk/ecloudsdkcore@v1.0.0 +replace gitlab.ecloud.com/ecloud/ecloudsdkclouddns v1.0.1 => ./internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1 diff --git a/internal/applicant/providers.go b/internal/applicant/providers.go index d1e80083..9989da8f 100644 --- a/internal/applicant/providers.go +++ b/internal/applicant/providers.go @@ -13,6 +13,7 @@ import ( pBaiduCloud "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/baiducloud" pCloudflare "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/cloudflare" pClouDNS "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/cloudns" + pCMCCCloud "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/cmcccloud" pGcore "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/gcore" pGname "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/gname" pGoDaddy "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/godaddy" @@ -151,6 +152,22 @@ func createApplicant(options *applicantOptions) (challenge.Provider, error) { return applicant, err } + case domain.ApplyDNSProviderTypeCMCCCloud: + { + access := domain.AccessConfigForCMCCCloud{} + if err := maps.Populate(options.ProviderAccessConfig, &access); err != nil { + return nil, fmt.Errorf("failed to populate provider access config: %w", err) + } + + applicant, err := pCMCCCloud.NewChallengeProvider(&pCMCCCloud.ChallengeProviderConfig{ + AccessKeyId: access.AccessKeyId, + AccessKeySecret: access.AccessKeySecret, + DnsPropagationTimeout: options.DnsPropagationTimeout, + DnsTTL: options.DnsTTL, + }) + return applicant, err + } + case domain.ApplyDNSProviderTypeGcore: { access := domain.AccessConfigForGcore{} diff --git a/internal/domain/access.go b/internal/domain/access.go index ddd00b1c..fd01af3b 100644 --- a/internal/domain/access.go +++ b/internal/domain/access.go @@ -86,6 +86,11 @@ type AccessConfigForClouDNS struct { AuthPassword string `json:"authPassword"` } +type AccessConfigForCMCCCloud struct { + AccessKeyId string `json:"accessKeyId"` + AccessKeySecret string `json:"accessKeySecret"` +} + type AccessConfigForDogeCloud struct { AccessKey string `json:"accessKey"` SecretKey string `json:"secretKey"` diff --git a/internal/domain/provider.go b/internal/domain/provider.go index 7402cadf..375176ce 100644 --- a/internal/domain/provider.go +++ b/internal/domain/provider.go @@ -23,7 +23,7 @@ const ( AccessProviderTypeCdnfly = AccessProviderType("cdnfly") AccessProviderTypeCloudflare = AccessProviderType("cloudflare") AccessProviderTypeClouDNS = AccessProviderType("cloudns") - AccessProviderTypeCMCCCloud = AccessProviderType("cmcccloud") // 移动云(预留) + AccessProviderTypeCMCCCloud = AccessProviderType("cmcccloud") AccessProviderTypeCTCCCloud = AccessProviderType("ctcccloud") // 联通云(预留) AccessProviderTypeCUCCCloud = AccessProviderType("cucccloud") // 天翼云(预留) AccessProviderTypeDogeCloud = AccessProviderType("dogecloud") @@ -74,6 +74,7 @@ const ( ApplyDNSProviderTypeBaiduCloudDNS = ApplyDNSProviderType("baiducloud-dns") ApplyDNSProviderTypeCloudflare = ApplyDNSProviderType("cloudflare") ApplyDNSProviderTypeClouDNS = ApplyDNSProviderType("cloudns") + ApplyDNSProviderTypeCMCCCloud = ApplyDNSProviderType("cmcccloud") ApplyDNSProviderTypeGcore = ApplyDNSProviderType("gcore") ApplyDNSProviderTypeGname = ApplyDNSProviderType("gname") ApplyDNSProviderTypeGoDaddy = ApplyDNSProviderType("godaddy") diff --git a/internal/pkg/core/applicant/acme-dns-01/lego-providers/cmcccloud/cmcccloud.go b/internal/pkg/core/applicant/acme-dns-01/lego-providers/cmcccloud/cmcccloud.go new file mode 100644 index 00000000..ba0721fd --- /dev/null +++ b/internal/pkg/core/applicant/acme-dns-01/lego-providers/cmcccloud/cmcccloud.go @@ -0,0 +1,40 @@ +package cmcccloud + +import ( + "errors" + "time" + + "github.com/go-acme/lego/v4/challenge" + + "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/cmcccloud/internal" +) + +type ChallengeProviderConfig struct { + AccessKeyId string `json:"accessKeyId"` + AccessKeySecret string `json:"accessKeySecret"` + DnsPropagationTimeout int32 `json:"dnsPropagationTimeout,omitempty"` + DnsTTL int32 `json:"dnsTTL,omitempty"` +} + +func NewChallengeProvider(config *ChallengeProviderConfig) (challenge.Provider, error) { + if config == nil { + return nil, errors.New("config is nil") + } + + providerConfig := internal.NewDefaultConfig() + providerConfig.AccessKey = config.AccessKeyId + providerConfig.SecretKey = config.AccessKeySecret + if config.DnsTTL != 0 { + providerConfig.TTL = config.DnsTTL + } + if config.DnsPropagationTimeout != 0 { + providerConfig.PropagationTimeout = time.Duration(config.DnsPropagationTimeout) * time.Second + } + + provider, err := internal.NewDNSProviderConfig(providerConfig) + if err != nil { + return nil, err + } + + return provider, nil +} diff --git a/internal/pkg/core/applicant/acme-dns-01/lego-providers/cmcccloud/internal/lego.go b/internal/pkg/core/applicant/acme-dns-01/lego-providers/cmcccloud/internal/lego.go new file mode 100644 index 00000000..92ef6dfe --- /dev/null +++ b/internal/pkg/core/applicant/acme-dns-01/lego-providers/cmcccloud/internal/lego.go @@ -0,0 +1,221 @@ +package internal + +import ( + "encoding/json" + "errors" + "fmt" + "strings" + "time" + + "github.com/go-acme/lego/v4/challenge" + "github.com/go-acme/lego/v4/challenge/dns01" + "github.com/go-acme/lego/v4/platform/config/env" + "gitlab.ecloud.com/ecloud/ecloudsdkclouddns" + "gitlab.ecloud.com/ecloud/ecloudsdkclouddns/model" + "gitlab.ecloud.com/ecloud/ecloudsdkcore/config" +) + +const ( + envNamespace = "CMCCCLOUD_" + + EnvAccessKey = envNamespace + "ACCESS_KEY" + EnvSecretKey = envNamespace + "SECRET_KEY" + EnvTTL = envNamespace + "TTL" + EnvPropagationTimeout = envNamespace + "PROPAGATION_TIMEOUT" + EnvPollingInterval = envNamespace + "POLLING_INTERVAL" + EnvReadTimeOut = envNamespace + "READ_TIMEOUT" + EnvConnectTimeout = envNamespace + "CONNECT_TIMEOUT" +) + +var _ challenge.ProviderTimeout = (*DNSProvider)(nil) + +type Config struct { + AccessKey string + SecretKey string + ReadTimeOut int + ConnectTimeout int + PropagationTimeout time.Duration + PollingInterval time.Duration + TTL int32 +} + +type DNSProvider struct { + client *ecloudsdkclouddns.Client + config *Config +} + +func NewDefaultConfig() *Config { + return &Config{ + ReadTimeOut: env.GetOrDefaultInt(EnvReadTimeOut, 30), + ConnectTimeout: env.GetOrDefaultInt(EnvConnectTimeout, 30), + TTL: int32(env.GetOrDefaultInt(EnvTTL, 600)), + PropagationTimeout: env.GetOrDefaultSecond(EnvPropagationTimeout, 2*time.Minute), + PollingInterval: env.GetOrDefaultSecond(EnvPollingInterval, dns01.DefaultPollingInterval), + } +} + +func NewDNSProvider() (*DNSProvider, error) { + values, err := env.Get(EnvAccessKey, EnvSecretKey) + if err != nil { + return nil, fmt.Errorf("cmccecloud: %w", err) + } + + cfg := NewDefaultConfig() + cfg.AccessKey = values[EnvAccessKey] + cfg.SecretKey = values[EnvSecretKey] + + return NewDNSProviderConfig(cfg) +} + +func NewDNSProviderConfig(cfg *Config) (*DNSProvider, error) { + if cfg == nil { + return nil, errors.New("cmccecloud: the configuration of the DNS provider is nil") + } + + client := ecloudsdkclouddns.NewClient(&config.Config{ + AccessKey: cfg.AccessKey, + SecretKey: cfg.SecretKey, + // 资源池常量见: https://ecloud.10086.cn/op-help-center/doc/article/54462 + // 默认全局 + PoolId: "CIDC-CORE-00", + ReadTimeOut: cfg.ReadTimeOut, + ConnectTimeout: cfg.ConnectTimeout, + }) + + return &DNSProvider{ + client: client, + config: cfg, + }, nil +} + +func (d *DNSProvider) Present(domain, token, keyAuth string) error { + info := dns01.GetChallengeInfo(domain, keyAuth) + + zoneName, err := dns01.FindZoneByFqdn(info.EffectiveFQDN) + if err != nil { + return fmt.Errorf("cmccecloud: %w", err) + } + + subDomain, err := dns01.ExtractSubDomain(info.EffectiveFQDN, zoneName) + if err != nil { + return fmt.Errorf("cmccecloud: %w", err) + } + + readDomain := strings.Trim(zoneName, ".") + record, err := d.getDomainRecord(readDomain, subDomain) + if err != nil { + return err + } + if record == nil { + // add new record + resp, err := d.client.CreateRecordOpenapi(&model.CreateRecordOpenapiRequest{ + CreateRecordOpenapiBody: &model.CreateRecordOpenapiBody{ + LineId: "0", // 默认线路 + Rr: subDomain, + DomainName: readDomain, + Description: "from certimate", + Type: model.CreateRecordOpenapiBodyTypeEnumTxt, + Value: info.Value, + Ttl: &d.config.TTL, + }, + }) + if err != nil { + return fmt.Errorf("lego: %w", err) + } + if resp.State != model.CreateRecordOpenapiResponseStateEnumOk { + return fmt.Errorf("lego: create record failed, response state: %s, message: %s, code: %s", resp.State, resp.ErrorMessage, resp.ErrorCode) + } + return nil + } else { + // update record + resp, err := d.client.ModifyRecordOpenapi(&model.ModifyRecordOpenapiRequest{ + ModifyRecordOpenapiBody: &model.ModifyRecordOpenapiBody{ + RecordId: record.RecordId, + Rr: subDomain, + DomainName: readDomain, + Description: "from certmate", + LineId: "0", + Type: model.ModifyRecordOpenapiBodyTypeEnumTxt, + Value: info.Value, + Ttl: &d.config.TTL, + }, + }) + if err != nil { + return fmt.Errorf("lego: %w", err) + } + if resp.State != model.ModifyRecordOpenapiResponseStateEnumOk { + return fmt.Errorf("lego: create record failed, response state: %s", resp.State) + } + return nil + } +} + +func (d *DNSProvider) CleanUp(domain, token, keyAuth string) error { + challengeInfo := dns01.GetChallengeInfo(domain, keyAuth) + zoneName, err := dns01.FindZoneByFqdn(challengeInfo.FQDN) + if err != nil { + return fmt.Errorf("cmccecloud: %w", err) + } + subDomain, err := dns01.ExtractSubDomain(challengeInfo.FQDN, zoneName) + if err != nil { + return fmt.Errorf("cmccecloud: %w", err) + } + readDomain := strings.Trim(zoneName, ".") + record, err := d.getDomainRecord(readDomain, subDomain) + if err != nil { + return err + } + if record == nil { + return nil + } + resp, err := d.client.DeleteRecordOpenapi(&model.DeleteRecordOpenapiRequest{ + DeleteRecordOpenapiBody: &model.DeleteRecordOpenapiBody{ + RecordIdList: []string{record.RecordId}, + }, + }) + if err != nil { + return fmt.Errorf("lego: %w", err) + } + if resp.State != model.DeleteRecordOpenapiResponseStateEnumOk { + return fmt.Errorf("lego: delete record failed, response state: %s", resp.State) + } + return nil +} + +func (d *DNSProvider) Timeout() (timeout, interval time.Duration) { + return d.config.PropagationTimeout, d.config.PollingInterval +} + +func (d *DNSProvider) getDomainRecord(domain string, rr string) (*model.ListRecordOpenapiResponseData, error) { + pageSize := int32(50) + page := int32(1) + for { + resp, err := d.client.ListRecordOpenapi(&model.ListRecordOpenapiRequest{ + ListRecordOpenapiBody: &model.ListRecordOpenapiBody{ + DomainName: domain, + }, + ListRecordOpenapiQuery: &model.ListRecordOpenapiQuery{ + PageSize: &pageSize, + Page: &page, + }, + }) + if err != nil { + return nil, err + } + if resp.State != model.ListRecordOpenapiResponseStateEnumOk { + respStr, _ := json.Marshal(resp) + return nil, fmt.Errorf("request error. %s", string(respStr)) + } + if resp.Body.Data != nil { + for _, item := range *resp.Body.Data { + if item.Rr == rr { + return &item, nil + } + } + } + if resp.Body.TotalPages == nil || page >= *resp.Body.TotalPages { + return nil, nil + } + page++ + } +} diff --git a/internal/pkg/vendors/cmcc-sdk/README.md b/internal/pkg/vendors/cmcc-sdk/README.md new file mode 100644 index 00000000..c64eebe8 --- /dev/null +++ b/internal/pkg/vendors/cmcc-sdk/README.md @@ -0,0 +1,14 @@ +移动云 Go SDK 文档: [https://ecloud.10086.cn/op-help-center/doc/article/53799](https://ecloud.10086.cn/op-help-center/doc/article/53799) + +移动云 Go SDK 下载地址: [https://ecloud.10086.cn/api/query/developer/nexus/service/rest/repository/browse/go-sdk/gitlab.ecloud.com/ecloud/](https://ecloud.10086.cn/api/query/developer/nexus/service/rest/repository/browse/go-sdk/gitlab.ecloud.com/ecloud/) + +--- + +将其引入本地目录的原因是: + +1. 原始包必须通过移动云私有仓库获取, 为构建带来不便。 +2. 原始包存在部分内容错误, 需要自行修改, 如: + + - 存在一些编译错误; + - 返回错误的时候, 未返回错误信息; + - 解析响应体错误。 diff --git a/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/client.go b/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/client.go new file mode 100644 index 00000000..d2c2ccde --- /dev/null +++ b/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/client.go @@ -0,0 +1,144 @@ +// @Title Golang SDK Client +// @Description This code is auto generated +// @Author Ecloud SDK + +package ecloudsdkclouddns + +import ( + "gitlab.ecloud.com/ecloud/ecloudsdkclouddns/model" + "gitlab.ecloud.com/ecloud/ecloudsdkcore" + "gitlab.ecloud.com/ecloud/ecloudsdkcore/config" +) + +type Client struct { + APIClient *ecloudsdkcore.APIClient + config *config.Config + httpRequest *ecloudsdkcore.HttpRequest +} + +func NewClient(config *config.Config) *Client { + client := &Client{} + client.config = config + apiClient := ecloudsdkcore.NewAPIClient() + httpRequest := ecloudsdkcore.NewDefaultHttpRequest() + httpRequest.Product = product + httpRequest.Version = version + httpRequest.SdkVersion = sdkVersion + client.httpRequest = httpRequest + client.APIClient = apiClient + return client +} + +func NewClientByCustomized(config *config.Config, httpRequest *ecloudsdkcore.HttpRequest) *Client { + client := &Client{} + client.config = config + apiClient := ecloudsdkcore.NewAPIClient() + httpRequest.Product = product + httpRequest.Version = version + httpRequest.SdkVersion = sdkVersion + client.httpRequest = httpRequest + client.APIClient = apiClient + return client +} + +const ( + product string = "clouddns" + version string = "v1" + sdkVersion string = "1.0.1" +) + +// CreateRecord 新增解析记录 +func (c *Client) CreateRecord(request *model.CreateRecordRequest) (*model.CreateRecordResponse, error) { + c.httpRequest.Action = "createRecord" + c.httpRequest.Body = request + returnValue := &model.CreateRecordResponse{} + if _, err := c.APIClient.Excute(c.httpRequest, c.config, returnValue); err != nil { + return nil, err + } else { + return returnValue, nil + } +} + +// CreateRecordOpenapi 新增解析记录Openapi +func (c *Client) CreateRecordOpenapi(request *model.CreateRecordOpenapiRequest) (*model.CreateRecordOpenapiResponse, error) { + c.httpRequest.Action = "createRecordOpenapi" + c.httpRequest.Body = request + returnValue := &model.CreateRecordOpenapiResponse{} + if _, err := c.APIClient.Excute(c.httpRequest, c.config, returnValue); err != nil { + return nil, err + } else { + return returnValue, nil + } +} + +// DeleteRecord 删除解析记录 +func (c *Client) DeleteRecord(request *model.DeleteRecordRequest) (*model.DeleteRecordResponse, error) { + c.httpRequest.Action = "deleteRecord" + c.httpRequest.Body = request + returnValue := &model.DeleteRecordResponse{} + if _, err := c.APIClient.Excute(c.httpRequest, c.config, returnValue); err != nil { + return nil, err + } else { + return returnValue, nil + } +} + +// DeleteRecordOpenapi 删除解析记录Openapi +func (c *Client) DeleteRecordOpenapi(request *model.DeleteRecordOpenapiRequest) (*model.DeleteRecordOpenapiResponse, error) { + c.httpRequest.Action = "deleteRecordOpenapi" + c.httpRequest.Body = request + returnValue := &model.DeleteRecordOpenapiResponse{} + if _, err := c.APIClient.Excute(c.httpRequest, c.config, returnValue); err != nil { + return nil, err + } else { + return returnValue, nil + } +} + +// ListRecord 查询解析记录 +func (c *Client) ListRecord(request *model.ListRecordRequest) (*model.ListRecordResponse, error) { + c.httpRequest.Action = "listRecord" + c.httpRequest.Body = request + returnValue := &model.ListRecordResponse{} + if _, err := c.APIClient.Excute(c.httpRequest, c.config, returnValue); err != nil { + return nil, err + } else { + return returnValue, nil + } +} + +// ListRecordOpenapi 查询解析记录Openapi +func (c *Client) ListRecordOpenapi(request *model.ListRecordOpenapiRequest) (*model.ListRecordOpenapiResponse, error) { + c.httpRequest.Action = "listRecordOpenapi" + c.httpRequest.Body = request + returnValue := &model.ListRecordOpenapiResponse{} + if _, err := c.APIClient.Excute(c.httpRequest, c.config, returnValue); err != nil { + return nil, err + } else { + return returnValue, nil + } +} + +// ModifyRecord 修改解析记录 +func (c *Client) ModifyRecord(request *model.ModifyRecordRequest) (*model.ModifyRecordResponse, error) { + c.httpRequest.Action = "modifyRecord" + c.httpRequest.Body = request + returnValue := &model.ModifyRecordResponse{} + if _, err := c.APIClient.Excute(c.httpRequest, c.config, returnValue); err != nil { + return nil, err + } else { + return returnValue, nil + } +} + +// ModifyRecordOpenapi 修改解析记录Openapi +func (c *Client) ModifyRecordOpenapi(request *model.ModifyRecordOpenapiRequest) (*model.ModifyRecordOpenapiResponse, error) { + c.httpRequest.Action = "modifyRecordOpenapi" + c.httpRequest.Body = request + returnValue := &model.ModifyRecordOpenapiResponse{} + if _, err := c.APIClient.Excute(c.httpRequest, c.config, returnValue); err != nil { + return nil, err + } else { + return returnValue, nil + } +} diff --git a/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/go.mod b/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/go.mod new file mode 100644 index 00000000..39812459 --- /dev/null +++ b/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/go.mod @@ -0,0 +1,7 @@ +module gitlab.ecloud.com/ecloud/ecloudsdkclouddns + +go 1.23.0 + +require gitlab.ecloud.com/ecloud/ecloudsdkcore v1.0.0 + +replace gitlab.ecloud.com/ecloud/ecloudsdkcore v1.0.0 => ../ecloudsdkcore@v1.0.0 diff --git a/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/create_record_body.go b/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/create_record_body.go new file mode 100644 index 00000000..1175cde9 --- /dev/null +++ b/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/create_record_body.go @@ -0,0 +1,54 @@ +// @Title Golang SDK Client +// @Description This code is auto generated +// @Author Ecloud SDK + +package model + +import ( + "gitlab.ecloud.com/ecloud/ecloudsdkcore/position" +) +type CreateRecordBodyTypeEnum string + +// List of Type +const ( + CreateRecordBodyTypeEnumA CreateRecordBodyTypeEnum = "A" + CreateRecordBodyTypeEnumAaaa CreateRecordBodyTypeEnum = "AAAA" + CreateRecordBodyTypeEnumCaa CreateRecordBodyTypeEnum = "CAA" + CreateRecordBodyTypeEnumCmauth CreateRecordBodyTypeEnum = "CMAUTH" + CreateRecordBodyTypeEnumCname CreateRecordBodyTypeEnum = "CNAME" + CreateRecordBodyTypeEnumMx CreateRecordBodyTypeEnum = "MX" + CreateRecordBodyTypeEnumNs CreateRecordBodyTypeEnum = "NS" + CreateRecordBodyTypeEnumPtr CreateRecordBodyTypeEnum = "PTR" + CreateRecordBodyTypeEnumRp CreateRecordBodyTypeEnum = "RP" + CreateRecordBodyTypeEnumSpf CreateRecordBodyTypeEnum = "SPF" + CreateRecordBodyTypeEnumSrv CreateRecordBodyTypeEnum = "SRV" + CreateRecordBodyTypeEnumTxt CreateRecordBodyTypeEnum = "TXT" + CreateRecordBodyTypeEnumUrl CreateRecordBodyTypeEnum = "URL" +) + +type CreateRecordBody struct { + position.Body + // 主机头 + Rr string `json:"rr"` + + // 域名名称 + DomainName string `json:"domainName"` + + // 备注 + Description string `json:"description,omitempty"` + + // 线路ID + LineId string `json:"lineId"` + + // MX优先级,若“记录类型”选择”MX”,则需要配置该参数,默认是5 + MxPri *int32 `json:"mxPri,omitempty"` + + // 记录类型 + Type CreateRecordBodyTypeEnum `json:"type"` + + // 缓存的生命周期,默认可配置600s + Ttl *int32 `json:"ttl,omitempty"` + + // 记录值 + Value string `json:"value"` +} diff --git a/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/create_record_openapi_body.go b/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/create_record_openapi_body.go new file mode 100644 index 00000000..3db9f0f7 --- /dev/null +++ b/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/create_record_openapi_body.go @@ -0,0 +1,51 @@ +// @Title Golang SDK Client +// @Description This code is auto generated +// @Author Ecloud SDK + +package model + +import ( + "gitlab.ecloud.com/ecloud/ecloudsdkcore/position" +) +type CreateRecordOpenapiBodyTypeEnum string + +// List of Type +const ( + CreateRecordOpenapiBodyTypeEnumA CreateRecordOpenapiBodyTypeEnum = "A" + CreateRecordOpenapiBodyTypeEnumAaaa CreateRecordOpenapiBodyTypeEnum = "AAAA" + CreateRecordOpenapiBodyTypeEnumCname CreateRecordOpenapiBodyTypeEnum = "CNAME" + CreateRecordOpenapiBodyTypeEnumMx CreateRecordOpenapiBodyTypeEnum = "MX" + CreateRecordOpenapiBodyTypeEnumTxt CreateRecordOpenapiBodyTypeEnum = "TXT" + CreateRecordOpenapiBodyTypeEnumNs CreateRecordOpenapiBodyTypeEnum = "NS" + CreateRecordOpenapiBodyTypeEnumSpf CreateRecordOpenapiBodyTypeEnum = "SPF" + CreateRecordOpenapiBodyTypeEnumSrv CreateRecordOpenapiBodyTypeEnum = "SRV" + CreateRecordOpenapiBodyTypeEnumCaa CreateRecordOpenapiBodyTypeEnum = "CAA" + CreateRecordOpenapiBodyTypeEnumCmauth CreateRecordOpenapiBodyTypeEnum = "CMAUTH" +) + +type CreateRecordOpenapiBody struct { + position.Body + // 主机头 + Rr string `json:"rr"` + + // 域名名称 + DomainName string `json:"domainName"` + + // 备注 + Description string `json:"description,omitempty"` + + // 线路ID + LineId string `json:"lineId"` + + // MX优先级,若“记录类型”选择”MX”,则需要配置该参数,默认是5 + MxPri *int32 `json:"mxPri,omitempty"` + + // 记录类型 + Type CreateRecordOpenapiBodyTypeEnum `json:"type"` + + // 缓存的生命周期,默认可配置600s + Ttl *int32 `json:"ttl,omitempty"` + + // 记录值 + Value string `json:"value"` +} diff --git a/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/create_record_openapi_request.go b/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/create_record_openapi_request.go new file mode 100644 index 00000000..d43fded1 --- /dev/null +++ b/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/create_record_openapi_request.go @@ -0,0 +1,12 @@ +// @Title Golang SDK Client +// @Description This code is auto generated +// @Author Ecloud SDK + +package model + + + +type CreateRecordOpenapiRequest struct { + + CreateRecordOpenapiBody *CreateRecordOpenapiBody `json:"createRecordOpenapiBody,omitempty"` +} diff --git a/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/create_record_openapi_response.go b/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/create_record_openapi_response.go new file mode 100644 index 00000000..a33b47c7 --- /dev/null +++ b/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/create_record_openapi_response.go @@ -0,0 +1,29 @@ +// @Title Golang SDK Client +// @Description This code is auto generated +// @Author Ecloud SDK + +package model + + +type CreateRecordOpenapiResponseStateEnum string + +// List of State +const ( + CreateRecordOpenapiResponseStateEnumError CreateRecordOpenapiResponseStateEnum = "ERROR" + CreateRecordOpenapiResponseStateEnumException CreateRecordOpenapiResponseStateEnum = "EXCEPTION" + CreateRecordOpenapiResponseStateEnumForbidden CreateRecordOpenapiResponseStateEnum = "FORBIDDEN" + CreateRecordOpenapiResponseStateEnumOk CreateRecordOpenapiResponseStateEnum = "OK" +) + +type CreateRecordOpenapiResponse struct { + + RequestId string `json:"requestId,omitempty"` + + ErrorMessage string `json:"errorMessage,omitempty"` + + ErrorCode string `json:"errorCode,omitempty"` + + State CreateRecordOpenapiResponseStateEnum `json:"state,omitempty"` + + Body *CreateRecordOpenapiResponseBody `json:"body,omitempty"` +} diff --git a/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/create_record_openapi_response_body.go b/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/create_record_openapi_response_body.go new file mode 100644 index 00000000..e7c62769 --- /dev/null +++ b/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/create_record_openapi_response_body.go @@ -0,0 +1,80 @@ +// @Title Golang SDK Client +// @Description This code is auto generated +// @Author Ecloud SDK + +package model + + +type CreateRecordOpenapiResponseBodyTypeEnum string + +// List of Type +const ( + CreateRecordOpenapiResponseBodyTypeEnumA CreateRecordOpenapiResponseBodyTypeEnum = "A" + CreateRecordOpenapiResponseBodyTypeEnumAaaa CreateRecordOpenapiResponseBodyTypeEnum = "AAAA" + CreateRecordOpenapiResponseBodyTypeEnumCname CreateRecordOpenapiResponseBodyTypeEnum = "CNAME" + CreateRecordOpenapiResponseBodyTypeEnumMx CreateRecordOpenapiResponseBodyTypeEnum = "MX" + CreateRecordOpenapiResponseBodyTypeEnumTxt CreateRecordOpenapiResponseBodyTypeEnum = "TXT" + CreateRecordOpenapiResponseBodyTypeEnumNs CreateRecordOpenapiResponseBodyTypeEnum = "NS" + CreateRecordOpenapiResponseBodyTypeEnumSpf CreateRecordOpenapiResponseBodyTypeEnum = "SPF" + CreateRecordOpenapiResponseBodyTypeEnumSrv CreateRecordOpenapiResponseBodyTypeEnum = "SRV" + CreateRecordOpenapiResponseBodyTypeEnumCaa CreateRecordOpenapiResponseBodyTypeEnum = "CAA" + CreateRecordOpenapiResponseBodyTypeEnumCmauth CreateRecordOpenapiResponseBodyTypeEnum = "CMAUTH" +) +type CreateRecordOpenapiResponseBodyStateEnum string + +// List of State +const ( + CreateRecordOpenapiResponseBodyStateEnumDisabled CreateRecordOpenapiResponseBodyStateEnum = "DISABLED" + CreateRecordOpenapiResponseBodyStateEnumEnabled CreateRecordOpenapiResponseBodyStateEnum = "ENABLED" +) + +type CreateRecordOpenapiResponseBody struct { + + // 主机头 + Rr string `json:"rr,omitempty"` + + // 修改时间 + ModifiedTime string `json:"modifiedTime,omitempty"` + + // 线路中文名 + LineZh string `json:"lineZh,omitempty"` + + // 备注 + Description string `json:"description,omitempty"` + + // 线路ID + LineId string `json:"lineId,omitempty"` + + // 权重值 + Weight *int32 `json:"weight,omitempty"` + + // MX优先级 + MxPri *int32 `json:"mxPri,omitempty"` + + // 记录类型 + Type CreateRecordOpenapiResponseBodyTypeEnum `json:"type,omitempty"` + + // 缓存的生命周期 + Ttl *int32 `json:"ttl,omitempty"` + + // 标签 + Tags *[]CreateRecordOpenapiResponseTags `json:"tags,omitempty"` + + // 解析记录ID + RecordId string `json:"recordId,omitempty"` + + // 域名名称 + DomainName string `json:"domainName,omitempty"` + + // 线路英文名 + LineEn string `json:"lineEn,omitempty"` + + // 状态 + State CreateRecordOpenapiResponseBodyStateEnum `json:"state,omitempty"` + + // 记录值 + Value string `json:"value,omitempty"` + + // 定时发布时间 + Pubdate string `json:"pubdate,omitempty"` +} diff --git a/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/create_record_openapi_response_tags.go b/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/create_record_openapi_response_tags.go new file mode 100644 index 00000000..a4bda62c --- /dev/null +++ b/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/create_record_openapi_response_tags.go @@ -0,0 +1,16 @@ +// @Title Golang SDK Client +// @Description This code is auto generated +// @Author Ecloud SDK + +package model + + + +type CreateRecordOpenapiResponseTags struct { + + // 标签ID + TagId string `json:"tagId,omitempty"` + + // 标签名称 + Value string `json:"value,omitempty"` +} diff --git a/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/create_record_request.go b/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/create_record_request.go new file mode 100644 index 00000000..715f03ff --- /dev/null +++ b/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/create_record_request.go @@ -0,0 +1,12 @@ +// @Title Golang SDK Client +// @Description This code is auto generated +// @Author Ecloud SDK + +package model + + + +type CreateRecordRequest struct { + + CreateRecordBody *CreateRecordBody `json:"createRecordBody,omitempty"` +} diff --git a/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/create_record_response.go b/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/create_record_response.go new file mode 100644 index 00000000..bd277c0c --- /dev/null +++ b/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/create_record_response.go @@ -0,0 +1,29 @@ +// @Title Golang SDK Client +// @Description This code is auto generated +// @Author Ecloud SDK + +package model + + +type CreateRecordResponseStateEnum string + +// List of State +const ( + CreateRecordResponseStateEnumError CreateRecordResponseStateEnum = "ERROR" + CreateRecordResponseStateEnumException CreateRecordResponseStateEnum = "EXCEPTION" + CreateRecordResponseStateEnumForbidden CreateRecordResponseStateEnum = "FORBIDDEN" + CreateRecordResponseStateEnumOk CreateRecordResponseStateEnum = "OK" +) + +type CreateRecordResponse struct { + + RequestId string `json:"requestId,omitempty"` + + ErrorMessage string `json:"errorMessage,omitempty"` + + ErrorCode string `json:"errorCode,omitempty"` + + State CreateRecordResponseStateEnum `json:"state,omitempty"` + + Body *CreateRecordResponseBody `json:"body,omitempty"` +} diff --git a/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/create_record_response_body.go b/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/create_record_response_body.go new file mode 100644 index 00000000..64660b91 --- /dev/null +++ b/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/create_record_response_body.go @@ -0,0 +1,94 @@ +// @Title Golang SDK Client +// @Description This code is auto generated +// @Author Ecloud SDK + +package model + + +type CreateRecordResponseBodyTypeEnum string + +// List of Type +const ( + CreateRecordResponseBodyTypeEnumA CreateRecordResponseBodyTypeEnum = "A" + CreateRecordResponseBodyTypeEnumAaaa CreateRecordResponseBodyTypeEnum = "AAAA" + CreateRecordResponseBodyTypeEnumCaa CreateRecordResponseBodyTypeEnum = "CAA" + CreateRecordResponseBodyTypeEnumCmauth CreateRecordResponseBodyTypeEnum = "CMAUTH" + CreateRecordResponseBodyTypeEnumCname CreateRecordResponseBodyTypeEnum = "CNAME" + CreateRecordResponseBodyTypeEnumMx CreateRecordResponseBodyTypeEnum = "MX" + CreateRecordResponseBodyTypeEnumNs CreateRecordResponseBodyTypeEnum = "NS" + CreateRecordResponseBodyTypeEnumPtr CreateRecordResponseBodyTypeEnum = "PTR" + CreateRecordResponseBodyTypeEnumRp CreateRecordResponseBodyTypeEnum = "RP" + CreateRecordResponseBodyTypeEnumSpf CreateRecordResponseBodyTypeEnum = "SPF" + CreateRecordResponseBodyTypeEnumSrv CreateRecordResponseBodyTypeEnum = "SRV" + CreateRecordResponseBodyTypeEnumTxt CreateRecordResponseBodyTypeEnum = "TXT" + CreateRecordResponseBodyTypeEnumUrl CreateRecordResponseBodyTypeEnum = "URL" +) +type CreateRecordResponseBodyTimedStatusEnum string + +// List of TimedStatus +const ( + CreateRecordResponseBodyTimedStatusEnumDisabled CreateRecordResponseBodyTimedStatusEnum = "DISABLED" + CreateRecordResponseBodyTimedStatusEnumEnabled CreateRecordResponseBodyTimedStatusEnum = "ENABLED" + CreateRecordResponseBodyTimedStatusEnumTimed CreateRecordResponseBodyTimedStatusEnum = "TIMED" +) +type CreateRecordResponseBodyStateEnum string + +// List of State +const ( + CreateRecordResponseBodyStateEnumDisabled CreateRecordResponseBodyStateEnum = "DISABLED" + CreateRecordResponseBodyStateEnumEnabled CreateRecordResponseBodyStateEnum = "ENABLED" +) + +type CreateRecordResponseBody struct { + + // 主机头 + Rr string `json:"rr,omitempty"` + + // 修改时间 + ModifiedTime string `json:"modifiedTime,omitempty"` + + // 线路中文名 + LineZh string `json:"lineZh,omitempty"` + + // 备注 + Description string `json:"description,omitempty"` + + // 线路ID + LineId string `json:"lineId,omitempty"` + + // 权重值 + Weight *int32 `json:"weight,omitempty"` + + // MX优先级 + MxPri *int32 `json:"mxPri,omitempty"` + + // 记录类型 + Type CreateRecordResponseBodyTypeEnum `json:"type,omitempty"` + + // 缓存的生命周期 + Ttl *int32 `json:"ttl,omitempty"` + + // 标签 + Tags *[]CreateRecordResponseTags `json:"tags,omitempty"` + + // 解析记录ID + RecordId string `json:"recordId,omitempty"` + + // 定时状态 + TimedStatus CreateRecordResponseBodyTimedStatusEnum `json:"timedStatus,omitempty"` + + // 域名名称 + DomainName string `json:"domainName,omitempty"` + + // 线路英文名 + LineEn string `json:"lineEn,omitempty"` + + // 状态 + State CreateRecordResponseBodyStateEnum `json:"state,omitempty"` + + // 记录值 + Value string `json:"value,omitempty"` + + // 定时发布时间 + Pubdate string `json:"pubdate,omitempty"` +} diff --git a/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/create_record_response_tags.go b/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/create_record_response_tags.go new file mode 100644 index 00000000..003680d5 --- /dev/null +++ b/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/create_record_response_tags.go @@ -0,0 +1,16 @@ +// @Title Golang SDK Client +// @Description This code is auto generated +// @Author Ecloud SDK + +package model + + + +type CreateRecordResponseTags struct { + + // 标签ID + TagId string `json:"tagId,omitempty"` + + // 标签名称 + Value string `json:"value,omitempty"` +} diff --git a/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/delete_record_body.go b/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/delete_record_body.go new file mode 100644 index 00000000..326b9abb --- /dev/null +++ b/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/delete_record_body.go @@ -0,0 +1,15 @@ +// @Title Golang SDK Client +// @Description This code is auto generated +// @Author Ecloud SDK + +package model + +import ( + "gitlab.ecloud.com/ecloud/ecloudsdkcore/position" +) + +type DeleteRecordBody struct { + position.Body + // 解析记录ID列表 + RecordIdList []string `json:"recordIdList"` +} diff --git a/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/delete_record_openapi_body.go b/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/delete_record_openapi_body.go new file mode 100644 index 00000000..e5614ac5 --- /dev/null +++ b/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/delete_record_openapi_body.go @@ -0,0 +1,15 @@ +// @Title Golang SDK Client +// @Description This code is auto generated +// @Author Ecloud SDK + +package model + +import ( + "gitlab.ecloud.com/ecloud/ecloudsdkcore/position" +) + +type DeleteRecordOpenapiBody struct { + position.Body + // 待删除的解析记录ID请求体 + RecordIdList []string `json:"recordIdList"` +} diff --git a/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/delete_record_openapi_request.go b/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/delete_record_openapi_request.go new file mode 100644 index 00000000..1cb684d6 --- /dev/null +++ b/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/delete_record_openapi_request.go @@ -0,0 +1,12 @@ +// @Title Golang SDK Client +// @Description This code is auto generated +// @Author Ecloud SDK + +package model + + + +type DeleteRecordOpenapiRequest struct { + + DeleteRecordOpenapiBody *DeleteRecordOpenapiBody `json:"deleteRecordOpenapiBody,omitempty"` +} diff --git a/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/delete_record_openapi_response.go b/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/delete_record_openapi_response.go new file mode 100644 index 00000000..ca528148 --- /dev/null +++ b/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/delete_record_openapi_response.go @@ -0,0 +1,29 @@ +// @Title Golang SDK Client +// @Description This code is auto generated +// @Author Ecloud SDK + +package model + + +type DeleteRecordOpenapiResponseStateEnum string + +// List of State +const ( + DeleteRecordOpenapiResponseStateEnumError DeleteRecordOpenapiResponseStateEnum = "ERROR" + DeleteRecordOpenapiResponseStateEnumException DeleteRecordOpenapiResponseStateEnum = "EXCEPTION" + DeleteRecordOpenapiResponseStateEnumForbidden DeleteRecordOpenapiResponseStateEnum = "FORBIDDEN" + DeleteRecordOpenapiResponseStateEnumOk DeleteRecordOpenapiResponseStateEnum = "OK" +) + +type DeleteRecordOpenapiResponse struct { + + RequestId string `json:"requestId,omitempty"` + + ErrorMessage string `json:"errorMessage,omitempty"` + + ErrorCode string `json:"errorCode,omitempty"` + + State DeleteRecordOpenapiResponseStateEnum `json:"state,omitempty"` + + Body *[]DeleteRecordOpenapiResponseBody `json:"body,omitempty"` +} diff --git a/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/delete_record_openapi_response_body.go b/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/delete_record_openapi_response_body.go new file mode 100644 index 00000000..67da3ab7 --- /dev/null +++ b/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/delete_record_openapi_response_body.go @@ -0,0 +1,29 @@ +// @Title Golang SDK Client +// @Description This code is auto generated +// @Author Ecloud SDK + +package model + + +type DeleteRecordOpenapiResponseBodyCodeEnum string + +// List of Code +const ( + DeleteRecordOpenapiResponseBodyCodeEnumError DeleteRecordOpenapiResponseBodyCodeEnum = "ERROR" + DeleteRecordOpenapiResponseBodyCodeEnumSuccess DeleteRecordOpenapiResponseBodyCodeEnum = "SUCCESS" +) + +type DeleteRecordOpenapiResponseBody struct { + + // 结果说明 + Msg string `json:"msg,omitempty"` + + // 解析记录ID + RecordId string `json:"recordId,omitempty"` + + // 结果码 + Code DeleteRecordOpenapiResponseBodyCodeEnum `json:"code,omitempty"` + + // 域名 + DomainName string `json:"domainName,omitempty"` +} diff --git a/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/delete_record_request.go b/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/delete_record_request.go new file mode 100644 index 00000000..678fd8ef --- /dev/null +++ b/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/delete_record_request.go @@ -0,0 +1,12 @@ +// @Title Golang SDK Client +// @Description This code is auto generated +// @Author Ecloud SDK + +package model + + + +type DeleteRecordRequest struct { + + DeleteRecordBody *DeleteRecordBody `json:"deleteRecordBody,omitempty"` +} diff --git a/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/delete_record_response.go b/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/delete_record_response.go new file mode 100644 index 00000000..051d7105 --- /dev/null +++ b/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/delete_record_response.go @@ -0,0 +1,29 @@ +// @Title Golang SDK Client +// @Description This code is auto generated +// @Author Ecloud SDK + +package model + + +type DeleteRecordResponseStateEnum string + +// List of State +const ( + DeleteRecordResponseStateEnumError DeleteRecordResponseStateEnum = "ERROR" + DeleteRecordResponseStateEnumException DeleteRecordResponseStateEnum = "EXCEPTION" + DeleteRecordResponseStateEnumForbidden DeleteRecordResponseStateEnum = "FORBIDDEN" + DeleteRecordResponseStateEnumOk DeleteRecordResponseStateEnum = "OK" +) + +type DeleteRecordResponse struct { + + RequestId string `json:"requestId,omitempty"` + + ErrorMessage string `json:"errorMessage,omitempty"` + + ErrorCode string `json:"errorCode,omitempty"` + + State DeleteRecordResponseStateEnum `json:"state,omitempty"` + + Body *[]DeleteRecordResponseBody `json:"body,omitempty"` +} diff --git a/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/delete_record_response_body.go b/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/delete_record_response_body.go new file mode 100644 index 00000000..45320290 --- /dev/null +++ b/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/delete_record_response_body.go @@ -0,0 +1,29 @@ +// @Title Golang SDK Client +// @Description This code is auto generated +// @Author Ecloud SDK + +package model + + +type DeleteRecordResponseBodyCodeEnum string + +// List of Code +const ( + DeleteRecordResponseBodyCodeEnumError DeleteRecordResponseBodyCodeEnum = "ERROR" + DeleteRecordResponseBodyCodeEnumSuccess DeleteRecordResponseBodyCodeEnum = "SUCCESS" +) + +type DeleteRecordResponseBody struct { + + // 结果说明 + Msg string `json:"msg,omitempty"` + + // 解析记录ID + RecordId string `json:"recordId,omitempty"` + + // 结果码 + Code DeleteRecordResponseBodyCodeEnum `json:"code,omitempty"` + + // 域名 + DomainName string `json:"domainName,omitempty"` +} diff --git a/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/list_record_body.go b/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/list_record_body.go new file mode 100644 index 00000000..5eadce7a --- /dev/null +++ b/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/list_record_body.go @@ -0,0 +1,18 @@ +// @Title Golang SDK Client +// @Description This code is auto generated +// @Author Ecloud SDK + +package model + +import ( + "gitlab.ecloud.com/ecloud/ecloudsdkcore/position" +) + +type ListRecordBody struct { + position.Body + // 域名 + DomainName string `json:"domainName"` + + // 可以匹配主机头rr、记录值value、备注description,并且是模糊搜索 + DataLike string `json:"dataLike,omitempty"` +} diff --git a/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/list_record_openapi_body.go b/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/list_record_openapi_body.go new file mode 100644 index 00000000..63f5e13a --- /dev/null +++ b/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/list_record_openapi_body.go @@ -0,0 +1,15 @@ +// @Title Golang SDK Client +// @Description This code is auto generated +// @Author Ecloud SDK + +package model + +import ( + "gitlab.ecloud.com/ecloud/ecloudsdkcore/position" +) + +type ListRecordOpenapiBody struct { + position.Body + // 域名 + DomainName string `json:"domainName"` +} diff --git a/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/list_record_openapi_query.go b/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/list_record_openapi_query.go new file mode 100644 index 00000000..ee89a7f5 --- /dev/null +++ b/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/list_record_openapi_query.go @@ -0,0 +1,18 @@ +// @Title Golang SDK Client +// @Description This code is auto generated +// @Author Ecloud SDK + +package model + +import ( + "gitlab.ecloud.com/ecloud/ecloudsdkcore/position" +) + +type ListRecordOpenapiQuery struct { + position.Query + // 页大小 + PageSize *int32 `json:"pageSize,omitempty"` + + // 当前页 + Page *int32 `json:"page,omitempty"` +} diff --git a/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/list_record_openapi_request.go b/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/list_record_openapi_request.go new file mode 100644 index 00000000..34540481 --- /dev/null +++ b/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/list_record_openapi_request.go @@ -0,0 +1,14 @@ +// @Title Golang SDK Client +// @Description This code is auto generated +// @Author Ecloud SDK + +package model + + + +type ListRecordOpenapiRequest struct { + + ListRecordOpenapiQuery *ListRecordOpenapiQuery `json:"listRecordOpenapiQuery,omitempty"` + + ListRecordOpenapiBody *ListRecordOpenapiBody `json:"listRecordOpenapiBody,omitempty"` +} diff --git a/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/list_record_openapi_response.go b/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/list_record_openapi_response.go new file mode 100644 index 00000000..36646938 --- /dev/null +++ b/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/list_record_openapi_response.go @@ -0,0 +1,29 @@ +// @Title Golang SDK Client +// @Description This code is auto generated +// @Author Ecloud SDK + +package model + + +type ListRecordOpenapiResponseStateEnum string + +// List of State +const ( + ListRecordOpenapiResponseStateEnumError ListRecordOpenapiResponseStateEnum = "ERROR" + ListRecordOpenapiResponseStateEnumException ListRecordOpenapiResponseStateEnum = "EXCEPTION" + ListRecordOpenapiResponseStateEnumForbidden ListRecordOpenapiResponseStateEnum = "FORBIDDEN" + ListRecordOpenapiResponseStateEnumOk ListRecordOpenapiResponseStateEnum = "OK" +) + +type ListRecordOpenapiResponse struct { + + RequestId string `json:"requestId,omitempty"` + + ErrorMessage string `json:"errorMessage,omitempty"` + + ErrorCode string `json:"errorCode,omitempty"` + + State ListRecordOpenapiResponseStateEnum `json:"state,omitempty"` + + Body *ListRecordOpenapiResponseBody `json:"body,omitempty"` +} diff --git a/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/list_record_openapi_response_body.go b/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/list_record_openapi_response_body.go new file mode 100644 index 00000000..8c6f7302 --- /dev/null +++ b/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/list_record_openapi_response_body.go @@ -0,0 +1,25 @@ +// @Title Golang SDK Client +// @Description This code is auto generated +// @Author Ecloud SDK + +package model + + + +type ListRecordOpenapiResponseBody struct { + + // 当前页的具体数据列表 + Data *[]ListRecordOpenapiResponseData `json:"data,omitempty"` + + // 总数据量 + TotalNum *int32 `json:"totalNum,omitempty"` + + // 总页数 + TotalPages *int32 `json:"totalPages,omitempty"` + + // 页大小 + PageSize *int32 `json:"pageSize,omitempty"` + + // 当前页码,从0开始,0表示第一页 + Page *int32 `json:"page,omitempty"` +} diff --git a/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/list_record_openapi_response_data.go b/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/list_record_openapi_response_data.go new file mode 100644 index 00000000..19981aa9 --- /dev/null +++ b/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/list_record_openapi_response_data.go @@ -0,0 +1,91 @@ +// @Title Golang SDK Client +// @Description This code is auto generated +// @Author Ecloud SDK + +package model + + +type ListRecordOpenapiResponseDataTypeEnum string + +// List of Type +const ( + ListRecordOpenapiResponseDataTypeEnumA ListRecordOpenapiResponseDataTypeEnum = "A" + ListRecordOpenapiResponseDataTypeEnumAaaa ListRecordOpenapiResponseDataTypeEnum = "AAAA" + ListRecordOpenapiResponseDataTypeEnumCname ListRecordOpenapiResponseDataTypeEnum = "CNAME" + ListRecordOpenapiResponseDataTypeEnumMx ListRecordOpenapiResponseDataTypeEnum = "MX" + ListRecordOpenapiResponseDataTypeEnumTxt ListRecordOpenapiResponseDataTypeEnum = "TXT" + ListRecordOpenapiResponseDataTypeEnumNs ListRecordOpenapiResponseDataTypeEnum = "NS" + ListRecordOpenapiResponseDataTypeEnumSpf ListRecordOpenapiResponseDataTypeEnum = "SPF" + ListRecordOpenapiResponseDataTypeEnumSrv ListRecordOpenapiResponseDataTypeEnum = "SRV" + ListRecordOpenapiResponseDataTypeEnumCaa ListRecordOpenapiResponseDataTypeEnum = "CAA" + ListRecordOpenapiResponseDataTypeEnumCmauth ListRecordOpenapiResponseDataTypeEnum = "CMAUTH" +) +type ListRecordOpenapiResponseDataTimedStatusEnum string + +// List of TimedStatus +const ( + ListRecordOpenapiResponseDataTimedStatusEnumDisabled ListRecordOpenapiResponseDataTimedStatusEnum = "DISABLED" + ListRecordOpenapiResponseDataTimedStatusEnumEnabled ListRecordOpenapiResponseDataTimedStatusEnum = "ENABLED" + ListRecordOpenapiResponseDataTimedStatusEnumTimed ListRecordOpenapiResponseDataTimedStatusEnum = "TIMED" +) +type ListRecordOpenapiResponseDataStateEnum string + +// List of State +const ( + ListRecordOpenapiResponseDataStateEnumDisabled ListRecordOpenapiResponseDataStateEnum = "DISABLED" + ListRecordOpenapiResponseDataStateEnumEnabled ListRecordOpenapiResponseDataStateEnum = "ENABLED" +) + +type ListRecordOpenapiResponseData struct { + + // 主机头 + Rr string `json:"rr,omitempty"` + + // 修改时间 + ModifiedTime string `json:"modifiedTime,omitempty"` + + // 线路中文名 + LineZh string `json:"lineZh,omitempty"` + + // 备注 + Description string `json:"description,omitempty"` + + // 线路ID + LineId string `json:"lineId,omitempty"` + + // 权重值 + Weight *int32 `json:"weight,omitempty"` + + // MX优先级 + MxPri *int32 `json:"mxPri,omitempty"` + + // 记录类型 + Type ListRecordOpenapiResponseDataTypeEnum `json:"type,omitempty"` + + // 缓存的生命周期 + Ttl *int32 `json:"ttl,omitempty"` + + // 标签 + Tags *[]ListRecordOpenapiResponseTags `json:"tags,omitempty"` + + // 解析记录ID + RecordId string `json:"recordId,omitempty"` + + // 定时状态 + TimedStatus ListRecordOpenapiResponseDataTimedStatusEnum `json:"timedStatus,omitempty"` + + // 域名名称 + DomainName string `json:"domainName,omitempty"` + + // 线路英文名 + LineEn string `json:"lineEn,omitempty"` + + // 状态 + State ListRecordOpenapiResponseDataStateEnum `json:"state,omitempty"` + + // 记录值 + Value string `json:"value,omitempty"` + + // 定时发布时间 + Pubdate string `json:"pubdate,omitempty"` +} diff --git a/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/list_record_openapi_response_tags.go b/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/list_record_openapi_response_tags.go new file mode 100644 index 00000000..867f667f --- /dev/null +++ b/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/list_record_openapi_response_tags.go @@ -0,0 +1,16 @@ +// @Title Golang SDK Client +// @Description This code is auto generated +// @Author Ecloud SDK + +package model + + + +type ListRecordOpenapiResponseTags struct { + + // 标签ID + TagId string `json:"tagId,omitempty"` + + // 标签名称 + Value string `json:"value,omitempty"` +} diff --git a/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/list_record_query.go b/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/list_record_query.go new file mode 100644 index 00000000..df871a76 --- /dev/null +++ b/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/list_record_query.go @@ -0,0 +1,18 @@ +// @Title Golang SDK Client +// @Description This code is auto generated +// @Author Ecloud SDK + +package model + +import ( + "gitlab.ecloud.com/ecloud/ecloudsdkcore/position" +) + +type ListRecordQuery struct { + position.Query + // 页大小 + PageSize *int32 `json:"pageSize,omitempty"` + + // 当前页 + CurrentPage *int32 `json:"currentPage,omitempty"` +} diff --git a/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/list_record_request.go b/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/list_record_request.go new file mode 100644 index 00000000..5ff9df08 --- /dev/null +++ b/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/list_record_request.go @@ -0,0 +1,14 @@ +// @Title Golang SDK Client +// @Description This code is auto generated +// @Author Ecloud SDK + +package model + + + +type ListRecordRequest struct { + + ListRecordBody *ListRecordBody `json:"listRecordBody,omitempty"` + + ListRecordQuery *ListRecordQuery `json:"listRecordQuery,omitempty"` +} diff --git a/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/list_record_response.go b/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/list_record_response.go new file mode 100644 index 00000000..b11f3d21 --- /dev/null +++ b/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/list_record_response.go @@ -0,0 +1,29 @@ +// @Title Golang SDK Client +// @Description This code is auto generated +// @Author Ecloud SDK + +package model + + +type ListRecordResponseStateEnum string + +// List of State +const ( + ListRecordResponseStateEnumError ListRecordResponseStateEnum = "ERROR" + ListRecordResponseStateEnumException ListRecordResponseStateEnum = "EXCEPTION" + ListRecordResponseStateEnumForbidden ListRecordResponseStateEnum = "FORBIDDEN" + ListRecordResponseStateEnumOk ListRecordResponseStateEnum = "OK" +) + +type ListRecordResponse struct { + + RequestId string `json:"requestId,omitempty"` + + ErrorMessage string `json:"errorMessage,omitempty"` + + ErrorCode string `json:"errorCode,omitempty"` + + State ListRecordResponseStateEnum `json:"state,omitempty"` + + Body *ListRecordResponseBody `json:"body,omitempty"` +} diff --git a/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/list_record_response_body.go b/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/list_record_response_body.go new file mode 100644 index 00000000..0acf543d --- /dev/null +++ b/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/list_record_response_body.go @@ -0,0 +1,22 @@ +// @Title Golang SDK Client +// @Description This code is auto generated +// @Author Ecloud SDK + +package model + + + +type ListRecordResponseBody struct { + + // 总页数 + TotalPages *int32 `json:"totalPages,omitempty"` + + // 当前页码,从0开始,0表示第一页 + CurrentPage *int32 `json:"currentPage,omitempty"` + + // 当前页的具体数据列表 + Results *[]ListRecordResponseResults `json:"results,omitempty"` + + // 总数据量 + TotalElements *int64 `json:"totalElements,omitempty"` +} diff --git a/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/list_record_response_results.go b/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/list_record_response_results.go new file mode 100644 index 00000000..7498fca3 --- /dev/null +++ b/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/list_record_response_results.go @@ -0,0 +1,91 @@ +// @Title Golang SDK Client +// @Description This code is auto generated +// @Author Ecloud SDK + +package model + + +type ListRecordResponseResultsTypeEnum string + +// List of Type +const ( + ListRecordResponseResultsTypeEnumA ListRecordResponseResultsTypeEnum = "A" + ListRecordResponseResultsTypeEnumAaaa ListRecordResponseResultsTypeEnum = "AAAA" + ListRecordResponseResultsTypeEnumCaa ListRecordResponseResultsTypeEnum = "CAA" + ListRecordResponseResultsTypeEnumCmauth ListRecordResponseResultsTypeEnum = "CMAUTH" + ListRecordResponseResultsTypeEnumCname ListRecordResponseResultsTypeEnum = "CNAME" + ListRecordResponseResultsTypeEnumMx ListRecordResponseResultsTypeEnum = "MX" + ListRecordResponseResultsTypeEnumNs ListRecordResponseResultsTypeEnum = "NS" + ListRecordResponseResultsTypeEnumPtr ListRecordResponseResultsTypeEnum = "PTR" + ListRecordResponseResultsTypeEnumRp ListRecordResponseResultsTypeEnum = "RP" + ListRecordResponseResultsTypeEnumSpf ListRecordResponseResultsTypeEnum = "SPF" + ListRecordResponseResultsTypeEnumSrv ListRecordResponseResultsTypeEnum = "SRV" + ListRecordResponseResultsTypeEnumTxt ListRecordResponseResultsTypeEnum = "TXT" + ListRecordResponseResultsTypeEnumUrl ListRecordResponseResultsTypeEnum = "URL" +) +type ListRecordResponseResultsTimedStatusEnum string + +// List of TimedStatus +const ( + ListRecordResponseResultsTimedStatusEnumDisabled ListRecordResponseResultsTimedStatusEnum = "DISABLED" + ListRecordResponseResultsTimedStatusEnumEnabled ListRecordResponseResultsTimedStatusEnum = "ENABLED" + ListRecordResponseResultsTimedStatusEnumTimed ListRecordResponseResultsTimedStatusEnum = "TIMED" +) +type ListRecordResponseResultsStateEnum string + +// List of State +const ( + ListRecordResponseResultsStateEnumDisabled ListRecordResponseResultsStateEnum = "DISABLED" + ListRecordResponseResultsStateEnumEnabled ListRecordResponseResultsStateEnum = "ENABLED" +) + +type ListRecordResponseResults struct { + + // 主机头 + Rr string `json:"rr,omitempty"` + + // 修改时间 + ModifiedTime string `json:"modifiedTime,omitempty"` + + // 线路中文名 + LineZh string `json:"lineZh,omitempty"` + + // 备注 + Description string `json:"description,omitempty"` + + // 线路ID + LineId string `json:"lineId,omitempty"` + + // 权重值 + Weight *int32 `json:"weight,omitempty"` + + // MX优先级 + MxPri *int32 `json:"mxPri,omitempty"` + + // 记录类型 + Type ListRecordResponseResultsTypeEnum `json:"type,omitempty"` + + // 缓存的生命周期 + Ttl *int32 `json:"ttl,omitempty"` + + // 解析记录ID + RecordId string `json:"recordId,omitempty"` + + // 定时状态 + TimedStatus ListRecordResponseResultsTimedStatusEnum `json:"timedStatus,omitempty"` + + // 域名名称 + DomainName string `json:"domainName,omitempty"` + + // 线路英文名 + LineEn string `json:"lineEn,omitempty"` + + // 状态 + State ListRecordResponseResultsStateEnum `json:"state,omitempty"` + + // 记录值 + Value string `json:"value,omitempty"` + + // 定时发布时间 + Pubdate string `json:"pubdate,omitempty"` +} diff --git a/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/modify_record_body.go b/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/modify_record_body.go new file mode 100644 index 00000000..ab772c09 --- /dev/null +++ b/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/modify_record_body.go @@ -0,0 +1,57 @@ +// @Title Golang SDK Client +// @Description This code is auto generated +// @Author Ecloud SDK + +package model + +import ( + "gitlab.ecloud.com/ecloud/ecloudsdkcore/position" +) +type ModifyRecordBodyTypeEnum string + +// List of Type +const ( + ModifyRecordBodyTypeEnumA ModifyRecordBodyTypeEnum = "A" + ModifyRecordBodyTypeEnumAaaa ModifyRecordBodyTypeEnum = "AAAA" + ModifyRecordBodyTypeEnumCaa ModifyRecordBodyTypeEnum = "CAA" + ModifyRecordBodyTypeEnumCmauth ModifyRecordBodyTypeEnum = "CMAUTH" + ModifyRecordBodyTypeEnumCname ModifyRecordBodyTypeEnum = "CNAME" + ModifyRecordBodyTypeEnumMx ModifyRecordBodyTypeEnum = "MX" + ModifyRecordBodyTypeEnumNs ModifyRecordBodyTypeEnum = "NS" + ModifyRecordBodyTypeEnumPtr ModifyRecordBodyTypeEnum = "PTR" + ModifyRecordBodyTypeEnumRp ModifyRecordBodyTypeEnum = "RP" + ModifyRecordBodyTypeEnumSpf ModifyRecordBodyTypeEnum = "SPF" + ModifyRecordBodyTypeEnumSrv ModifyRecordBodyTypeEnum = "SRV" + ModifyRecordBodyTypeEnumTxt ModifyRecordBodyTypeEnum = "TXT" + ModifyRecordBodyTypeEnumUrl ModifyRecordBodyTypeEnum = "URL" +) + +type ModifyRecordBody struct { + position.Body + // 解析记录ID + RecordId string `json:"recordId"` + + // 主机头 + Rr string `json:"rr,omitempty"` + + // 域名名称 + DomainName string `json:"domainName"` + + // 备注 + Description string `json:"description,omitempty"` + + // 线路ID + LineId string `json:"lineId,omitempty"` + + // MX优先级 + MxPri *int32 `json:"mxPri,omitempty"` + + // 记录类型 + Type ModifyRecordBodyTypeEnum `json:"type,omitempty"` + + // 缓存的生命周期 + Ttl *int32 `json:"ttl,omitempty"` + + // 记录值 + Value string `json:"value,omitempty"` +} diff --git a/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/modify_record_openapi_body.go b/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/modify_record_openapi_body.go new file mode 100644 index 00000000..3bde8919 --- /dev/null +++ b/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/modify_record_openapi_body.go @@ -0,0 +1,54 @@ +// @Title Golang SDK Client +// @Description This code is auto generated +// @Author Ecloud SDK + +package model + +import ( + "gitlab.ecloud.com/ecloud/ecloudsdkcore/position" +) +type ModifyRecordOpenapiBodyTypeEnum string + +// List of Type +const ( + ModifyRecordOpenapiBodyTypeEnumA ModifyRecordOpenapiBodyTypeEnum = "A" + ModifyRecordOpenapiBodyTypeEnumAaaa ModifyRecordOpenapiBodyTypeEnum = "AAAA" + ModifyRecordOpenapiBodyTypeEnumCname ModifyRecordOpenapiBodyTypeEnum = "CNAME" + ModifyRecordOpenapiBodyTypeEnumMx ModifyRecordOpenapiBodyTypeEnum = "MX" + ModifyRecordOpenapiBodyTypeEnumTxt ModifyRecordOpenapiBodyTypeEnum = "TXT" + ModifyRecordOpenapiBodyTypeEnumNs ModifyRecordOpenapiBodyTypeEnum = "NS" + ModifyRecordOpenapiBodyTypeEnumSpf ModifyRecordOpenapiBodyTypeEnum = "SPF" + ModifyRecordOpenapiBodyTypeEnumSrv ModifyRecordOpenapiBodyTypeEnum = "SRV" + ModifyRecordOpenapiBodyTypeEnumCaa ModifyRecordOpenapiBodyTypeEnum = "CAA" + ModifyRecordOpenapiBodyTypeEnumCmauth ModifyRecordOpenapiBodyTypeEnum = "CMAUTH" +) + +type ModifyRecordOpenapiBody struct { + position.Body + // 解析记录ID + RecordId string `json:"recordId"` + + // 主机头 + Rr string `json:"rr,omitempty"` + + // 域名名称 + DomainName string `json:"domainName"` + + // 备注 + Description string `json:"description,omitempty"` + + // 线路ID + LineId string `json:"lineId,omitempty"` + + // MX优先级 + MxPri *int32 `json:"mxPri,omitempty"` + + // 记录类型 + Type ModifyRecordOpenapiBodyTypeEnum `json:"type,omitempty"` + + // 缓存的生命周期 + Ttl *int32 `json:"ttl,omitempty"` + + // 记录值 + Value string `json:"value,omitempty"` +} diff --git a/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/modify_record_openapi_request.go b/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/modify_record_openapi_request.go new file mode 100644 index 00000000..fd1ffe00 --- /dev/null +++ b/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/modify_record_openapi_request.go @@ -0,0 +1,12 @@ +// @Title Golang SDK Client +// @Description This code is auto generated +// @Author Ecloud SDK + +package model + + + +type ModifyRecordOpenapiRequest struct { + + ModifyRecordOpenapiBody *ModifyRecordOpenapiBody `json:"modifyRecordOpenapiBody,omitempty"` +} diff --git a/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/modify_record_openapi_response.go b/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/modify_record_openapi_response.go new file mode 100644 index 00000000..97d7552f --- /dev/null +++ b/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/modify_record_openapi_response.go @@ -0,0 +1,29 @@ +// @Title Golang SDK Client +// @Description This code is auto generated +// @Author Ecloud SDK + +package model + + +type ModifyRecordOpenapiResponseStateEnum string + +// List of State +const ( + ModifyRecordOpenapiResponseStateEnumError ModifyRecordOpenapiResponseStateEnum = "ERROR" + ModifyRecordOpenapiResponseStateEnumException ModifyRecordOpenapiResponseStateEnum = "EXCEPTION" + ModifyRecordOpenapiResponseStateEnumForbidden ModifyRecordOpenapiResponseStateEnum = "FORBIDDEN" + ModifyRecordOpenapiResponseStateEnumOk ModifyRecordOpenapiResponseStateEnum = "OK" +) + +type ModifyRecordOpenapiResponse struct { + + RequestId string `json:"requestId,omitempty"` + + ErrorMessage string `json:"errorMessage,omitempty"` + + ErrorCode string `json:"errorCode,omitempty"` + + State ModifyRecordOpenapiResponseStateEnum `json:"state,omitempty"` + + Body *ModifyRecordOpenapiResponseBody `json:"body,omitempty"` +} diff --git a/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/modify_record_openapi_response_body.go b/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/modify_record_openapi_response_body.go new file mode 100644 index 00000000..6dfcec71 --- /dev/null +++ b/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/modify_record_openapi_response_body.go @@ -0,0 +1,91 @@ +// @Title Golang SDK Client +// @Description This code is auto generated +// @Author Ecloud SDK + +package model + + +type ModifyRecordOpenapiResponseBodyTypeEnum string + +// List of Type +const ( + ModifyRecordOpenapiResponseBodyTypeEnumA ModifyRecordOpenapiResponseBodyTypeEnum = "A" + ModifyRecordOpenapiResponseBodyTypeEnumAaaa ModifyRecordOpenapiResponseBodyTypeEnum = "AAAA" + ModifyRecordOpenapiResponseBodyTypeEnumCname ModifyRecordOpenapiResponseBodyTypeEnum = "CNAME" + ModifyRecordOpenapiResponseBodyTypeEnumMx ModifyRecordOpenapiResponseBodyTypeEnum = "MX" + ModifyRecordOpenapiResponseBodyTypeEnumTxt ModifyRecordOpenapiResponseBodyTypeEnum = "TXT" + ModifyRecordOpenapiResponseBodyTypeEnumNs ModifyRecordOpenapiResponseBodyTypeEnum = "NS" + ModifyRecordOpenapiResponseBodyTypeEnumSpf ModifyRecordOpenapiResponseBodyTypeEnum = "SPF" + ModifyRecordOpenapiResponseBodyTypeEnumSrv ModifyRecordOpenapiResponseBodyTypeEnum = "SRV" + ModifyRecordOpenapiResponseBodyTypeEnumCaa ModifyRecordOpenapiResponseBodyTypeEnum = "CAA" + ModifyRecordOpenapiResponseBodyTypeEnumCmauth ModifyRecordOpenapiResponseBodyTypeEnum = "CMAUTH" +) +type ModifyRecordOpenapiResponseBodyTimedStatusEnum string + +// List of TimedStatus +const ( + ModifyRecordOpenapiResponseBodyTimedStatusEnumDisabled ModifyRecordOpenapiResponseBodyTimedStatusEnum = "DISABLED" + ModifyRecordOpenapiResponseBodyTimedStatusEnumEnabled ModifyRecordOpenapiResponseBodyTimedStatusEnum = "ENABLED" + ModifyRecordOpenapiResponseBodyTimedStatusEnumTimed ModifyRecordOpenapiResponseBodyTimedStatusEnum = "TIMED" +) +type ModifyRecordOpenapiResponseBodyStateEnum string + +// List of State +const ( + ModifyRecordOpenapiResponseBodyStateEnumDisabled ModifyRecordOpenapiResponseBodyStateEnum = "DISABLED" + ModifyRecordOpenapiResponseBodyStateEnumEnabled ModifyRecordOpenapiResponseBodyStateEnum = "ENABLED" +) + +type ModifyRecordOpenapiResponseBody struct { + + // 主机头 + Rr string `json:"rr,omitempty"` + + // 修改时间 + ModifiedTime string `json:"modifiedTime,omitempty"` + + // 线路中文名 + LineZh string `json:"lineZh,omitempty"` + + // 备注 + Description string `json:"description,omitempty"` + + // 线路ID + LineId string `json:"lineId,omitempty"` + + // 权重值 + Weight *int32 `json:"weight,omitempty"` + + // MX优先级 + MxPri *int32 `json:"mxPri,omitempty"` + + // 记录类型 + Type ModifyRecordOpenapiResponseBodyTypeEnum `json:"type,omitempty"` + + // 缓存的生命周期 + Ttl *int32 `json:"ttl,omitempty"` + + // 标签 + Tags *[]ModifyRecordOpenapiResponseTags `json:"tags,omitempty"` + + // 解析记录ID + RecordId string `json:"recordId,omitempty"` + + // 定时状态 + TimedStatus ModifyRecordOpenapiResponseBodyTimedStatusEnum `json:"timedStatus,omitempty"` + + // 域名名称 + DomainName string `json:"domainName,omitempty"` + + // 线路英文名 + LineEn string `json:"lineEn,omitempty"` + + // 状态 + State ModifyRecordOpenapiResponseBodyStateEnum `json:"state,omitempty"` + + // 记录值 + Value string `json:"value,omitempty"` + + // 定时发布时间 + Pubdate string `json:"pubdate,omitempty"` +} diff --git a/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/modify_record_openapi_response_tags.go b/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/modify_record_openapi_response_tags.go new file mode 100644 index 00000000..62c2e780 --- /dev/null +++ b/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/modify_record_openapi_response_tags.go @@ -0,0 +1,16 @@ +// @Title Golang SDK Client +// @Description This code is auto generated +// @Author Ecloud SDK + +package model + + + +type ModifyRecordOpenapiResponseTags struct { + + // 标签ID + TagId string `json:"tagId,omitempty"` + + // 标签名称 + Value string `json:"value,omitempty"` +} diff --git a/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/modify_record_request.go b/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/modify_record_request.go new file mode 100644 index 00000000..d92abb44 --- /dev/null +++ b/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/modify_record_request.go @@ -0,0 +1,12 @@ +// @Title Golang SDK Client +// @Description This code is auto generated +// @Author Ecloud SDK + +package model + + + +type ModifyRecordRequest struct { + + ModifyRecordBody *ModifyRecordBody `json:"modifyRecordBody,omitempty"` +} diff --git a/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/modify_record_response.go b/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/modify_record_response.go new file mode 100644 index 00000000..45b1ae0f --- /dev/null +++ b/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/modify_record_response.go @@ -0,0 +1,29 @@ +// @Title Golang SDK Client +// @Description This code is auto generated +// @Author Ecloud SDK + +package model + + +type ModifyRecordResponseStateEnum string + +// List of State +const ( + ModifyRecordResponseStateEnumError ModifyRecordResponseStateEnum = "ERROR" + ModifyRecordResponseStateEnumException ModifyRecordResponseStateEnum = "EXCEPTION" + ModifyRecordResponseStateEnumForbidden ModifyRecordResponseStateEnum = "FORBIDDEN" + ModifyRecordResponseStateEnumOk ModifyRecordResponseStateEnum = "OK" +) + +type ModifyRecordResponse struct { + + RequestId string `json:"requestId,omitempty"` + + ErrorMessage string `json:"errorMessage,omitempty"` + + ErrorCode string `json:"errorCode,omitempty"` + + State ModifyRecordResponseStateEnum `json:"state,omitempty"` + + Body *ModifyRecordResponseBody `json:"body,omitempty"` +} diff --git a/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/modify_record_response_body.go b/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/modify_record_response_body.go new file mode 100644 index 00000000..3df09342 --- /dev/null +++ b/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/modify_record_response_body.go @@ -0,0 +1,77 @@ +// @Title Golang SDK Client +// @Description This code is auto generated +// @Author Ecloud SDK + +package model + + +type ModifyRecordResponseBodyTypeEnum string + +// List of Type +const ( + ModifyRecordResponseBodyTypeEnumA ModifyRecordResponseBodyTypeEnum = "A" + ModifyRecordResponseBodyTypeEnumAaaa ModifyRecordResponseBodyTypeEnum = "AAAA" + ModifyRecordResponseBodyTypeEnumCaa ModifyRecordResponseBodyTypeEnum = "CAA" + ModifyRecordResponseBodyTypeEnumCmauth ModifyRecordResponseBodyTypeEnum = "CMAUTH" + ModifyRecordResponseBodyTypeEnumCname ModifyRecordResponseBodyTypeEnum = "CNAME" + ModifyRecordResponseBodyTypeEnumMx ModifyRecordResponseBodyTypeEnum = "MX" + ModifyRecordResponseBodyTypeEnumNs ModifyRecordResponseBodyTypeEnum = "NS" + ModifyRecordResponseBodyTypeEnumPtr ModifyRecordResponseBodyTypeEnum = "PTR" + ModifyRecordResponseBodyTypeEnumRp ModifyRecordResponseBodyTypeEnum = "RP" + ModifyRecordResponseBodyTypeEnumSpf ModifyRecordResponseBodyTypeEnum = "SPF" + ModifyRecordResponseBodyTypeEnumSrv ModifyRecordResponseBodyTypeEnum = "SRV" + ModifyRecordResponseBodyTypeEnumTxt ModifyRecordResponseBodyTypeEnum = "TXT" + ModifyRecordResponseBodyTypeEnumUrl ModifyRecordResponseBodyTypeEnum = "URL" +) +type ModifyRecordResponseBodyStateEnum string + +// List of State +const ( + ModifyRecordResponseBodyStateEnumDisabled ModifyRecordResponseBodyStateEnum = "DISABLED" + ModifyRecordResponseBodyStateEnumEnabled ModifyRecordResponseBodyStateEnum = "ENABLED" +) + +type ModifyRecordResponseBody struct { + + // 主机头 + Rr string `json:"rr,omitempty"` + + // 修改时间 + ModifiedTime string `json:"modifiedTime,omitempty"` + + // 线路中文名 + LineZh string `json:"lineZh,omitempty"` + + // 备注 + Description string `json:"description,omitempty"` + + // 线路ID + LineId string `json:"lineId,omitempty"` + + // 权重值 + Weight *int32 `json:"weight,omitempty"` + + // MX优先级 + MxPri *int32 `json:"mxPri,omitempty"` + + // 记录类型 + Type ModifyRecordResponseBodyTypeEnum `json:"type,omitempty"` + + // 缓存的生命周期 + Ttl *int32 `json:"ttl,omitempty"` + + // 解析记录ID + RecordId string `json:"recordId,omitempty"` + + // 域名名称 + DomainName string `json:"domainName,omitempty"` + + // 线路英文名 + LineEn string `json:"lineEn,omitempty"` + + // 状态 + State ModifyRecordResponseBodyStateEnum `json:"state,omitempty"` + + // 记录值 + Value string `json:"value,omitempty"` +} diff --git a/internal/pkg/vendors/cmcc-sdk/ecloudsdkcore@v1.0.0/api_client.go b/internal/pkg/vendors/cmcc-sdk/ecloudsdkcore@v1.0.0/api_client.go new file mode 100644 index 00000000..8f73b499 --- /dev/null +++ b/internal/pkg/vendors/cmcc-sdk/ecloudsdkcore@v1.0.0/api_client.go @@ -0,0 +1,507 @@ +package ecloudsdkcore + +import ( + "bytes" + "encoding/json" + "encoding/xml" + "errors" + "fmt" + "gitlab.ecloud.com/ecloud/ecloudsdkcore/config" + "io" + "io/ioutil" + "mime/multipart" + "net/http" + "net/url" + "os" + "path/filepath" + "reflect" + "regexp" + "strconv" + "strings" + "time" + "unicode/utf8" +) + +var ( + jsonCheck = regexp.MustCompile("(?i:(?:application|text)/json)") + xmlCheck = regexp.MustCompile("(?i:(?:application|text)/xml)") +) + +// APIClient manages communication +// In most cases there should be only one, shared, APIClient. +type APIClient struct { + cfg *Configuration + common service +} + +type service struct { + client *APIClient +} + +type HttpRequestPosition string + +const ( + BODY HttpRequestPosition = "Body" + QUERY HttpRequestPosition = "Query" + PATH HttpRequestPosition = "Path" + HEADER HttpRequestPosition = "Header" +) + +const SdkPortalUrl = "/op-apim-portal/apim/request/sdk" +const SdkPortalGatewayUrl = "/api/query/openapi/apim/request/sdk" + +// NewAPIClient creates a new API client. +func NewAPIClient() *APIClient { + cfg := NewConfiguration() + if cfg.HTTPClient == nil { + cfg.HTTPClient = http.DefaultClient + } + c := &APIClient{} + c.cfg = cfg + c.common.client = c + return c +} + +// atoi string to int +func atoi(in string) (int, error) { + return strconv.Atoi(in) +} + +// selectHeaderContentType select a content type from the available list. +func selectHeaderContentType(contentTypes []string) string { + if len(contentTypes) == 0 { + return "" + } + if contains(contentTypes, "application/json") { + return "application/json" + } + return contentTypes[0] +} + +// selectHeaderAccept join all accept types and return +func selectHeaderAccept(accepts []string) string { + if len(accepts) == 0 { + return "" + } + + if contains(accepts, "application/json") { + return "application/json" + } + + return strings.Join(accepts, ",") +} + +// contains is a case insenstive match, finding needle in a haystack +func contains(haystack []string, needle string) bool { + for _, a := range haystack { + if strings.ToLower(a) == strings.ToLower(needle) { + return true + } + } + return false +} + +// Verify optional parameters are of the correct type. +func typeCheckParameter(obj interface{}, expected string, name string) error { + if obj == nil { + return nil + } + if reflect.TypeOf(obj).String() != expected { + return fmt.Errorf("Expected %s to be of type %s but received %s.", name, expected, reflect.TypeOf(obj).String()) + } + return nil +} + +// parameterToString convert interface{} parameters to string, using a delimiter if format is provided. +func parameterToString(obj interface{}, collectionFormat string, request HttpRequest) (*http.Request, string) { + var delimiter string + + switch collectionFormat { + case "pipes": + delimiter = "|" + case "ssv": + delimiter = " " + case "tsv": + delimiter = "\t" + case "csv": + delimiter = "," + } + + if reflect.TypeOf(obj).Kind() == reflect.Slice { + return nil, strings.Trim(strings.Replace(fmt.Sprint(obj), " ", delimiter, -1), "[]") + } + + return nil, fmt.Sprintf("%v", obj) +} + +// Excute entry for http call +func (c *APIClient) Excute(httpRequest *HttpRequest, config *config.Config, returnType interface{}) (*http.Response, error) { + httpRequest = buildHttpRequest(httpRequest, config) + request := buildCall(httpRequest) + httpResponse, err := c.callAPI(request) + if err != nil || httpResponse == nil { + return nil, err + } + + responseBody, err := ioutil.ReadAll(httpResponse.Body) + httpResponse.Body.Close() + if err != nil { + return httpResponse, err + } + + if httpResponse.StatusCode < 300 { + // If we succeed, return the data, otherwise pass on to decode error. + err = c.decode(&returnType, responseBody, httpResponse.Header.Get("Content-Type")) + if err != nil { + return httpResponse, fmt.Errorf("%w, response body is: %s", err, string(responseBody)) + } + return httpResponse, nil + } + + if httpResponse.StatusCode >= 300 { + newErr := GenericResponseError{ + body: responseBody, + error: httpResponse.Status, + } + return httpResponse, newErr + } + return httpResponse, err +} + +// callAPI do the request. +func (c *APIClient) callAPI(request *http.Request) (*http.Response, error) { + return c.cfg.HTTPClient.Do(request) +} + +// ChangeBasePath Change base path to allow switching to mocks +func (c *APIClient) ChangeBasePath(path string) { + c.cfg.BasePath = path +} + +// buildHttpRequest build the request +func buildHttpRequest(httpRequest *HttpRequest, config *config.Config) *HttpRequest { + openApiRequest := &OpenApiRequest{ + AccessKey: config.AccessKey, + SecretKey: config.SecretKey, + PoolId: config.PoolId, + Api: httpRequest.Action, + Product: httpRequest.Product, + Version: httpRequest.Version, + SdkVersion: httpRequest.SdkVersion, + Language: "Golang", + } + if httpRequest.Body != nil { + reqType := reflect.TypeOf(httpRequest.Body) + if reqType.Kind() == reflect.Ptr { + reqType = reqType.Elem() + } + v := reflect.ValueOf(httpRequest.Body) + if v.Kind() == reflect.Ptr { + v = v.Elem() + } + var flag = false + for i := 0; i < reqType.NumField(); i++ { + fieldType := reqType.Field(i) + value := v.FieldByName(fieldType.Name) + if value.Kind() == reflect.Ptr { + if value.IsNil() { + continue + } + value = value.Elem() + + } + propertyType := fieldType.Type + if propertyType.Kind() == reflect.Ptr { + propertyType = propertyType.Elem() + } + + _, flag = propertyType.FieldByName(string(BODY)) + if flag { + openApiRequest.BodyParameter = value.Interface() + continue + } + _, flag = propertyType.FieldByName(string(HEADER)) + if flag { + openApiRequest.HeaderParameter = structToMap(value.Interface()) + continue + } + _, flag = propertyType.FieldByName(string(QUERY)) + if flag { + openApiRequest.QueryParameter = structToMap(value.Interface()) + continue + } + _, flag = propertyType.FieldByName(string(PATH)) + if flag { + openApiRequest.PathParameter = structToMap(value.Interface()) + continue + } + } + } + headers := make(map[string]interface{}) + if httpRequest.HeaderParams != nil { + if openApiRequest.HeaderParameter == nil { + headers = httpRequest.HeaderParams + } else { + headers = mergeMap(openApiRequest.HeaderParameter, httpRequest.HeaderParams) + } + openApiRequest.HeaderParameter = headers + } + httpRequest.Body = openApiRequest + return httpRequest +} + +// mergeMap merge the two map results +func mergeMap(mObj ...map[string]interface{}) map[string]interface{} { + newMap := map[string]interface{}{} + for _, m := range mObj { + for k, v := range m { + newMap[k] = v + } + } + return newMap +} + +// structToMap struct convert to map +func structToMap(value interface{}) map[string]interface{} { + data, _ := json.Marshal(value) + result := make(map[string]interface{}) + json.Unmarshal(data, &result) + return result +} + +func buildCall(httpRequest *HttpRequest) (request *http.Request) { + var url = "" + if len(httpRequest.Url) > 0 { + url = httpRequest.Url + SdkPortalUrl + } else { + url = httpRequest.DefaultUrl + SdkPortalGatewayUrl + } + request, _ = prepareRequest(url, "POST", httpRequest.Body) + return request +} + +// prepareRequest build the request +func prepareRequest(path string, method string, + postBody interface{}, +) (httpRequest *http.Request, err error) { + + var body *bytes.Buffer + + // Detect postBody type and post. + if postBody != nil { + var contentType = detectContentType(postBody) + body, err = setBody(postBody, contentType) + if err != nil { + return nil, err + } + } + + // Setup path and query parameters + url, err := url.Parse(path) + if err != nil { + return nil, err + } + + // Generate a new request + if body != nil { + httpRequest, err = http.NewRequest(method, url.String(), body) + } else { + httpRequest, err = http.NewRequest(method, url.String(), nil) + } + if err != nil { + return nil, err + } + + // add default header parameters + httpRequest.Header.Add("Content-Type", "application/json") + return httpRequest, nil +} + +func (c *APIClient) decode(v interface{}, b []byte, contentType string) (err error) { + if strings.Contains(contentType, "application/xml") { + if err = xml.Unmarshal(b, v); err != nil { + return err + } + return nil + } else if strings.Contains(contentType, "application/json") { + platformResponse := &APIPlatformResponse{} + if err = json.Unmarshal(b, platformResponse); err != nil { + newErr := GenericResponseError{ + body: b, + error: err.Error(), + } + return newErr + } + platformResponseBodyBytes, _ := json.Marshal(platformResponse.Body) + platformResponseBody := &APIPlatformResponseBody{} + if err = json.Unmarshal(platformResponseBodyBytes, platformResponseBody); err != nil { + return err + } + /* + 找到两层指针指向的元素 + */ + value := reflect.ValueOf(v).Elem().Elem() + + if !value.IsNil() { + structValue := value.Elem() + if structValue.NumField() == 1 && structValue.Field(0).Kind() == reflect.String { + n := len(platformResponseBody.ResponseBody) + structValue.Field(0).SetString(platformResponseBody.ResponseBody[1 : n-1]) + return nil + } + } + + if err = json.Unmarshal([]byte(platformResponseBody.ResponseBody), v); err != nil { + return err + } + return nil + } + return errors.New("undefined response type") +} + +// Add a file to the multipart request +func addFile(w *multipart.Writer, fieldName, path string) error { + file, err := os.Open(path) + if err != nil { + return err + } + defer file.Close() + + part, err := w.CreateFormFile(fieldName, filepath.Base(path)) + if err != nil { + return err + } + _, err = io.Copy(part, file) + + return err +} + +// Prevent trying to import "fmt" +func reportError(format string, a ...interface{}) error { + return fmt.Errorf(format, a...) +} + +// Set request body from an interface{} +func setBody(body interface{}, contentType string) (bodyBuf *bytes.Buffer, err error) { + if bodyBuf == nil { + bodyBuf = &bytes.Buffer{} + } + if reader, ok := body.(io.Reader); ok { + _, err = bodyBuf.ReadFrom(reader) + } else if b, ok := body.([]byte); ok { + _, err = bodyBuf.Write(b) + } else if s, ok := body.(string); ok { + _, err = bodyBuf.WriteString(s) + } else if s, ok := body.(*string); ok { + _, err = bodyBuf.WriteString(*s) + } else if jsonCheck.MatchString(contentType) { + err = json.NewEncoder(bodyBuf).Encode(body) + } else if xmlCheck.MatchString(contentType) { + xml.NewEncoder(bodyBuf).Encode(body) + } + + if err != nil { + return nil, err + } + + if bodyBuf.Len() == 0 { + err = fmt.Errorf("Invalid body type %s\n", contentType) + return nil, err + } + return bodyBuf, nil +} + +// detectContentType method is used to figure out `Request.Body` content type for request header +func detectContentType(body interface{}) string { + contentType := "text/plain; charset=utf-8" + kind := reflect.TypeOf(body).Kind() + + switch kind { + case reflect.Struct, reflect.Map, reflect.Ptr: + contentType = "application/json; charset=utf-8" + case reflect.String: + contentType = "text/plain; charset=utf-8" + default: + if b, ok := body.([]byte); ok { + contentType = http.DetectContentType(b) + } else if kind == reflect.Slice { + contentType = "application/json; charset=utf-8" + } + } + + return contentType +} + +type cacheControl map[string]string + +func parseCacheControl(headers http.Header) cacheControl { + cc := cacheControl{} + ccHeader := headers.Get("Cache-Control") + for _, part := range strings.Split(ccHeader, ",") { + part = strings.Trim(part, " ") + if part == "" { + continue + } + if strings.ContainsRune(part, '=') { + keyval := strings.Split(part, "=") + cc[strings.Trim(keyval[0], " ")] = strings.Trim(keyval[1], ",") + } else { + cc[part] = "" + } + } + return cc +} + +// CacheExpires helper function to determine remaining time before repeating a request. +func CacheExpires(r *http.Response) time.Time { + // Figure out when the cache expires. + var expires time.Time + now, err := time.Parse(time.RFC1123, r.Header.Get("date")) + if err != nil { + return time.Now() + } + respCacheControl := parseCacheControl(r.Header) + + if maxAge, ok := respCacheControl["max-age"]; ok { + lifetime, err := time.ParseDuration(maxAge + "s") + if err != nil { + expires = now + } + expires = now.Add(lifetime) + } else { + expiresHeader := r.Header.Get("Expires") + if expiresHeader != "" { + expires, err = time.Parse(time.RFC1123, expiresHeader) + if err != nil { + expires = now + } + } + } + return expires +} + +func strlen(s string) int { + return utf8.RuneCountInString(s) +} + +// GenericResponseError Provides access to the body, error and model on returned errors. +type GenericResponseError struct { + body []byte + error string + model interface{} +} + +// Error returns non-empty string if there was an error. +func (e GenericResponseError) Error() string { + return e.error +} + +// Body returns the raw bytes of the response +func (e GenericResponseError) Body() []byte { + return e.body +} + +// Model returns the unpacked model of the error +func (e GenericResponseError) Model() interface{} { + return e.model +} diff --git a/internal/pkg/vendors/cmcc-sdk/ecloudsdkcore@v1.0.0/api_response.go b/internal/pkg/vendors/cmcc-sdk/ecloudsdkcore@v1.0.0/api_response.go new file mode 100644 index 00000000..89110877 --- /dev/null +++ b/internal/pkg/vendors/cmcc-sdk/ecloudsdkcore@v1.0.0/api_response.go @@ -0,0 +1,64 @@ +package ecloudsdkcore + +import ( + "net/http" +) + +type ReturnState string + +const ( + OK ReturnState = "OK" + ERROR ReturnState = "ERROR" + EXCEPTION ReturnState = "EXCEPTION" + ALARM ReturnState = "ALARM" + FORBIDDEN ReturnState = "FORBIDDEN" +) + +type APIResponse struct { + *http.Response `json:"-"` + Message string `json:"message,omitempty"` + // Operation is the name of the swagger operation. + Operation string `json:"operation,omitempty"` + // RequestURL is the request URL. This value is always available, even if the + // embedded *http.Response is nil. + RequestURL string `json:"url,omitempty"` + // Method is the HTTP method used for the request. This value is always + // available, even if the embedded *http.Response is nil. + Method string `json:"method,omitempty"` + // Payload holds the contents of the response body (which may be nil or empty). + // This is provided here as the raw response.Body() reader will have already + // been drained. + Payload []byte `json:"-"` +} + +type APIPlatformResponse struct { + RequestId string `json:"requestId,omitempty"` + State ReturnState `json:"state,omitempty"` + Body interface{} `json:"body,omitempty"` + ErrorCode string `json:"errorCode,omitempty"` + ErrorParams []string `json:"errorParams,omitempty"` + ErrorMessage string `json:"errorMessage,omitempty"` +} + +type APIPlatformResponseBody struct { + // TimeConsuming int64 `json:"timeConsuming,omitempty"` + ResponseBody string `json:"responseBody,omitempty"` + RequestHeader map[string]interface{} `json:"requestHeader,omitempty"` + ResponseHeader map[string]interface{} `json:"responseHeader,omitempty"` + ResponseMessage string `json:"responseMessage,omitempty"` + StatusCode int `json:"statusCode,omitempty"` + HttpMethod string `json:"httpMethod,omitempty"` + RequestUrl string `json:"requestUrl,omitempty"` +} + +func NewAPIResponse(r *http.Response) *APIResponse { + + response := &APIResponse{Response: r} + return response +} + +func NewAPIResponseWithError(errorMessage string) *APIResponse { + + response := &APIResponse{Message: errorMessage} + return response +} diff --git a/internal/pkg/vendors/cmcc-sdk/ecloudsdkcore@v1.0.0/config/config.go b/internal/pkg/vendors/cmcc-sdk/ecloudsdkcore@v1.0.0/config/config.go new file mode 100644 index 00000000..08ba59e3 --- /dev/null +++ b/internal/pkg/vendors/cmcc-sdk/ecloudsdkcore@v1.0.0/config/config.go @@ -0,0 +1,9 @@ +package config + +type Config struct { + AccessKey string `json:"accessKey,string"` + SecretKey string `json:"secretKey,string"` + PoolId string `json:"poolId,string"` + ReadTimeOut int `json:"readTimeOut,int"` + ConnectTimeout int `json:"connectTimeout,int"` +} diff --git a/internal/pkg/vendors/cmcc-sdk/ecloudsdkcore@v1.0.0/configuration.go b/internal/pkg/vendors/cmcc-sdk/ecloudsdkcore@v1.0.0/configuration.go new file mode 100644 index 00000000..8eeb5df0 --- /dev/null +++ b/internal/pkg/vendors/cmcc-sdk/ecloudsdkcore@v1.0.0/configuration.go @@ -0,0 +1,32 @@ +package ecloudsdkcore + +import ( + "net/http" +) + +type APIKey struct { + Key string + Prefix string +} + +type Configuration struct { + BasePath string `json:"basePath,omitempty"` + Host string `json:"host,omitempty"` + Scheme string `json:"scheme,omitempty"` + DefaultHeader map[string]string `json:"defaultHeader,omitempty"` + UserAgent string `json:"userAgent,omitempty"` + HTTPClient *http.Client +} + +func NewConfiguration() *Configuration { + cfg := &Configuration{ + BasePath: "https://ecloud.10086.cn/", + DefaultHeader: make(map[string]string), + UserAgent: "Ecloud-SDK/1.0.0/go", + } + return cfg +} + +func (c *Configuration) AddDefaultHeader(key string, value string) { + c.DefaultHeader[key] = value +} diff --git a/internal/pkg/vendors/cmcc-sdk/ecloudsdkcore@v1.0.0/go.mod b/internal/pkg/vendors/cmcc-sdk/ecloudsdkcore@v1.0.0/go.mod new file mode 100644 index 00000000..141fa34e --- /dev/null +++ b/internal/pkg/vendors/cmcc-sdk/ecloudsdkcore@v1.0.0/go.mod @@ -0,0 +1,3 @@ +module gitlab.ecloud.com/ecloud/ecloudsdkcore + +go 1.23.0 diff --git a/internal/pkg/vendors/cmcc-sdk/ecloudsdkcore@v1.0.0/http_request.go b/internal/pkg/vendors/cmcc-sdk/ecloudsdkcore@v1.0.0/http_request.go new file mode 100644 index 00000000..e498463d --- /dev/null +++ b/internal/pkg/vendors/cmcc-sdk/ecloudsdkcore@v1.0.0/http_request.go @@ -0,0 +1,22 @@ +package ecloudsdkcore + +type HttpRequest struct { + Url string `json:"url,omitempty"` + DefaultUrl string `json:"defaultUrl,omitempty"` + Method string `json:"method,omitempty"` + Action string `json:"action,omitempty"` + Product string `json:"product,omitempty"` + Version string `json:"version,omitempty"` + SdkVersion string `json:"sdkVersion,omitempty"` + Body interface{} `json:"body,omitempty"` + PathParams map[string]interface{} `json:"pathParams,omitempty"` + QueryParams map[string]interface{} `json:"queryParams,omitempty"` + HeaderParams map[string]interface{} `json:"headerParams,omitempty"` +} + +func NewDefaultHttpRequest() *HttpRequest { + return &HttpRequest{ + DefaultUrl: "https://ecloud.10086.cn", + Method: "POST", + } +} diff --git a/internal/pkg/vendors/cmcc-sdk/ecloudsdkcore@v1.0.0/open_api_request.go b/internal/pkg/vendors/cmcc-sdk/ecloudsdkcore@v1.0.0/open_api_request.go new file mode 100644 index 00000000..a7cb4c0b --- /dev/null +++ b/internal/pkg/vendors/cmcc-sdk/ecloudsdkcore@v1.0.0/open_api_request.go @@ -0,0 +1,16 @@ +package ecloudsdkcore + +type OpenApiRequest struct { + Product string `json:"product,omitempty"` + Version string `json:"version,omitempty"` + SdkVersion string `json:"sdkVersion,omitempty"` + Language string `json:"language,omitempty"` + Api string `json:"api,omitempty"` + PoolId string `json:"poolId,omitempty"` + HeaderParameter map[string]interface{} `json:"headerParameter,omitempty"` + PathParameter map[string]interface{} `json:"pathParameter,omitempty"` + QueryParameter map[string]interface{} `json:"queryParameter,omitempty"` + BodyParameter interface{} `json:"bodyParameter,omitempty"` + AccessKey string `json:"accessKey,omitempty"` + SecretKey string `json:"secretKey,omitempty"` +} diff --git a/internal/pkg/vendors/cmcc-sdk/ecloudsdkcore@v1.0.0/position/http_position.go b/internal/pkg/vendors/cmcc-sdk/ecloudsdkcore@v1.0.0/position/http_position.go new file mode 100644 index 00000000..7c2eec1c --- /dev/null +++ b/internal/pkg/vendors/cmcc-sdk/ecloudsdkcore@v1.0.0/position/http_position.go @@ -0,0 +1,13 @@ +package position + +type Body struct { +} + +type Query struct { +} + +type Path struct { +} + +type Header struct { +} diff --git a/internal/pkg/vendors/edgio-sdk/applications/README.md b/internal/pkg/vendors/edgio-sdk/applications/README.md new file mode 100644 index 00000000..703b245a --- /dev/null +++ b/internal/pkg/vendors/edgio-sdk/applications/README.md @@ -0,0 +1 @@ +From https://github.com/Edgio/terraform-provider-edgio.git diff --git a/internal/pkg/vendors/edgio-sdk/applications/v7/README.md b/internal/pkg/vendors/edgio-sdk/applications/v7/README.md deleted file mode 100644 index fae60236..00000000 --- a/internal/pkg/vendors/edgio-sdk/applications/v7/README.md +++ /dev/null @@ -1,3 +0,0 @@ -```shell -git clone https://github.com/Edgio/terraform-provider-edgio.git -``` diff --git a/ui/public/imgs/providers/cmcccloud.svg b/ui/public/imgs/providers/cmcccloud.svg new file mode 100644 index 00000000..0a44fcfa --- /dev/null +++ b/ui/public/imgs/providers/cmcccloud.svg @@ -0,0 +1 @@ + diff --git a/ui/src/components/access/AccessForm.tsx b/ui/src/components/access/AccessForm.tsx index 44d6ae0c..90bb6ff5 100644 --- a/ui/src/components/access/AccessForm.tsx +++ b/ui/src/components/access/AccessForm.tsx @@ -21,6 +21,7 @@ import AccessFormCacheFlyConfig from "./AccessFormCacheFlyConfig"; import AccessFormCdnflyConfig from "./AccessFormCdnflyConfig"; import AccessFormCloudflareConfig from "./AccessFormCloudflareConfig"; import AccessFormClouDNSConfig from "./AccessFormClouDNSConfig"; +import AccessFormCMCCCloudConfig from "./AccessFormCMCCCloudConfig"; import AccessFormDogeCloudConfig from "./AccessFormDogeCloudConfig"; import AccessFormEdgioConfig from "./AccessFormEdgioConfig"; import AccessFormGcoreConfig from "./AccessFormGcoreConfig"; @@ -120,6 +121,8 @@ const AccessForm = forwardRef(({ className, return ; case ACCESS_PROVIDERS.CLOUDNS: return ; + case ACCESS_PROVIDERS.CMCCCLOUD: + return ; case ACCESS_PROVIDERS.DOGECLOUD: return ; case ACCESS_PROVIDERS.GCORE: diff --git a/ui/src/components/access/AccessFormCMCCCloudConfig.tsx b/ui/src/components/access/AccessFormCMCCCloudConfig.tsx new file mode 100644 index 00000000..9bc6e615 --- /dev/null +++ b/ui/src/components/access/AccessFormCMCCCloudConfig.tsx @@ -0,0 +1,75 @@ +import { useTranslation } from "react-i18next"; +import { Form, type FormInstance, Input } from "antd"; +import { createSchemaFieldRule } from "antd-zod"; +import { z } from "zod"; +import { type AccessConfigForCMCCCloud } from "@/domain/access"; + +type AccessFormCMCCCloudConfigFieldValues = Nullish; + +export type AccessFormCMCCCloudConfigProps = { + form: FormInstance; + formName: string; + disabled?: boolean; + initialValues?: AccessFormCMCCCloudConfigFieldValues; + onValuesChange?: (values: AccessFormCMCCCloudConfigFieldValues) => void; +}; + +const initFormModel = (): AccessFormCMCCCloudConfigFieldValues => { + return { + accessKeyId: "", + accessKeySecret: "", + }; +}; + +const AccessFormCMCCCloudConfig = ({ form: formInst, formName, disabled, initialValues, onValuesChange: onValuesChange }: AccessFormCMCCCloudConfigProps) => { + const { t } = useTranslation(); + + const formSchema = z.object({ + accessKeyId: z + .string() + .min(1, t("access.form.cmcccloud_access_key_id.placeholder")) + .max(64, t("common.errmsg.string_max", { max: 64 })) + .trim(), + accessKeySecret: z + .string() + .min(1, t("access.form.cmcccloud_access_key_secret.placeholder")) + .max(64, t("common.errmsg.string_max", { max: 64 })) + .trim(), + }); + const formRule = createSchemaFieldRule(formSchema); + + const handleFormChange = (_: unknown, values: z.infer) => { + onValuesChange?.(values); + }; + + return ( +
+ } + > + + + + } + > + + +
+ ); +}; + +export default AccessFormCMCCCloudConfig; diff --git a/ui/src/domain/access.ts b/ui/src/domain/access.ts index c91e647f..da8739b7 100644 --- a/ui/src/domain/access.ts +++ b/ui/src/domain/access.ts @@ -18,6 +18,7 @@ export interface AccessModel extends BaseModel { | AccessConfigForCdnfly | AccessConfigForCloudflare | AccessConfigForClouDNS + | AccessConfigForCMCCCloud | AccessConfigForDogeCloud | AccessConfigForEdgio | AccessConfigForGcore @@ -105,6 +106,11 @@ export type AccessConfigForClouDNS = { authPassword: string; }; +export type AccessConfigForCMCCCloud = { + accessKeyId: string; + accessKeySecret: string; +}; + export type AccessConfigForDogeCloud = { accessKey: string; secretKey: string; diff --git a/ui/src/domain/provider.ts b/ui/src/domain/provider.ts index 13a82a4c..e99abb5c 100644 --- a/ui/src/domain/provider.ts +++ b/ui/src/domain/provider.ts @@ -16,6 +16,7 @@ export const ACCESS_PROVIDERS = Object.freeze({ CDNFLY: "cdnfly", CLOUDFLARE: "cloudflare", CLOUDNS: "cloudns", + CMCCCLOUD: "cmcccloud", DOGECLOUD: "dogecloud", GCORE: "gcore", GNAME: "gname", @@ -74,6 +75,7 @@ export const accessProvidersMap: Maphttps://www.cloudns.net/wiki/article/42/", + "access.form.cmcccloud_access_key_id.label": "CMCC ECloud AccessKeyId", + "access.form.cmcccloud_access_key_id.placeholder": "Please enter CMCC ECloud AccessKeyId", + "access.form.cmcccloud_access_key_id.tooltip": "For more information, see https://ecloud.10086.cn/op-help-center/doc/article/49739", + "access.form.cmcccloud_access_key_secret.label": "CMCC ECloud AccessKeySecret", + "access.form.cmcccloud_access_key_secret.placeholder": "Please enter CMCC ECloud AccessKeySecret", + "access.form.cmcccloud_access_key_secret.tooltip": "For more information, see https://ecloud.10086.cn/op-help-center/doc/article/49739", "access.form.dogecloud_access_key.label": "Doge Cloud AccessKey", "access.form.dogecloud_access_key.placeholder": "Please enter Doge Cloud AccessKey", "access.form.dogecloud_access_key.tooltip": "For more information, see https://console.dogecloud.com/", diff --git a/ui/src/i18n/locales/zh/nls.access.json b/ui/src/i18n/locales/zh/nls.access.json index c35d65d3..f4648c4d 100644 --- a/ui/src/i18n/locales/zh/nls.access.json +++ b/ui/src/i18n/locales/zh/nls.access.json @@ -100,6 +100,12 @@ "access.form.cloudns_auth_password.label": "ClouDNS API 用户密码", "access.form.cloudns_auth_password.placeholder": "请输入 ClouDNS API 用户密码", "access.form.cloudns_auth_password.tooltip": "这是什么?请参阅 https://www.cloudns.net/wiki/article/42/", + "access.form.cmcccloud_access_key_id.label": "移动云 AccessKeyId", + "access.form.cmcccloud_access_key_id.placeholder": "请输入移动云 AccessKeyId", + "access.form.cmcccloud_access_key_id.tooltip": "这是什么?请参阅 https://ecloud.10086.cn/op-help-center/doc/article/49739", + "access.form.cmcccloud_access_key_secret.label": "移动云 AccessKeySecret", + "access.form.cmcccloud_access_key_secret.placeholder": "请输入移动云 AccessKeySecret", + "access.form.cmcccloud_access_key_secret.tooltip": "这是什么?请参阅 https://ecloud.10086.cn/op-help-center/doc/article/49739", "access.form.dogecloud_access_key.label": "多吉云 AccessKey", "access.form.dogecloud_access_key.placeholder": "请输入多吉云 AccessKey", "access.form.dogecloud_access_key.tooltip": "这是什么?请参阅 https://console.dogecloud.com/", From 63f824e3dda596ba8858aa4174e9ec95feb20af3 Mon Sep 17 00:00:00 2001 From: Fu Diwei Date: Fri, 21 Feb 2025 10:32:30 +0800 Subject: [PATCH 29/34] feat: add namecheap dns-01 applicant --- README.md | 1 + README_EN.md | 1 + go.mod | 3 +- go.sum | 2 + internal/applicant/providers.go | 17 +++++ internal/domain/access.go | 5 ++ internal/domain/provider.go | 3 + .../lego-providers/namecheap/namecheap.go | 38 ++++++++++ migrations/1739462400_collections_snapshot.go | 4 + ui/public/imgs/providers/namecheap.svg | 1 + ui/src/components/access/AccessForm.tsx | 3 + .../access/AccessFormNamecheapConfig.tsx | 76 +++++++++++++++++++ ui/src/domain/access.ts | 6 ++ ui/src/domain/provider.ts | 6 ++ ui/src/i18n/locales/en/nls.access.json | 6 ++ ui/src/i18n/locales/en/nls.provider.json | 2 + ui/src/i18n/locales/zh/nls.access.json | 6 ++ ui/src/i18n/locales/zh/nls.provider.json | 2 + 18 files changed, 181 insertions(+), 1 deletion(-) create mode 100644 internal/pkg/core/applicant/acme-dns-01/lego-providers/namecheap/namecheap.go create mode 100644 ui/public/imgs/providers/namecheap.svg create mode 100644 ui/src/components/access/AccessFormNamecheapConfig.tsx diff --git a/README.md b/README.md index 10987477..1bcf2034 100644 --- a/README.md +++ b/README.md @@ -102,6 +102,7 @@ make local.run | [GNAME](https://www.gname.com/) | | | [GoDaddy](https://www.godaddy.com/) | | | [Name.com](https://www.name.com/) | | +| [Namecheap](https://www.namecheap.com/) | | | [NameSilo](https://www.namesilo.com/) | | | [IBM NS1 Connect](https://www.ibm.com/cn-zh/products/ns1-connect/) | | | [移动云](https://ecloud.10086.cn/) | | diff --git a/README_EN.md b/README_EN.md index bd58f8bb..2e850330 100644 --- a/README_EN.md +++ b/README_EN.md @@ -101,6 +101,7 @@ The following DNS providers are supported: | [GNAME](https://www.gname.com/) | | | [GoDaddy](https://www.godaddy.com/) | | | [Name.com](https://www.name.com/) | | +| [Namecheap](https://www.namecheap.com/) | | | [NameSilo](https://www.namesilo.com/) | | | [IBM NS1 Connect](https://www.ibm.com/products/ns1-connect/) | | | [CMCC Cloud](https://ecloud.10086.cn/) | | diff --git a/go.mod b/go.mod index 5694ec54..40efa5a4 100644 --- a/go.mod +++ b/go.mod @@ -21,7 +21,7 @@ require ( github.com/aws/aws-sdk-go-v2/service/cloudfront v1.44.10 github.com/baidubce/bce-sdk-go v0.9.217 github.com/byteplus-sdk/byteplus-sdk-golang v1.0.41 - github.com/go-acme/lego/v4 v4.21.0 + github.com/go-acme/lego/v4 v4.22.2 github.com/go-resty/resty/v2 v2.16.5 github.com/go-viper/mapstructure/v2 v2.2.1 github.com/huaweicloud/huaweicloud-sdk-go-v3 v0.1.136 @@ -215,4 +215,5 @@ require ( ) replace gitlab.ecloud.com/ecloud/ecloudsdkcore v1.0.0 => ./internal/pkg/vendors/cmcc-sdk/ecloudsdkcore@v1.0.0 + replace gitlab.ecloud.com/ecloud/ecloudsdkclouddns v1.0.1 => ./internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1 diff --git a/go.sum b/go.sum index e85c4f8d..d15c396f 100644 --- a/go.sum +++ b/go.sum @@ -376,6 +376,8 @@ github.com/ganigeorgiev/fexpr v0.4.1/go.mod h1:RyGiGqmeXhEQ6+mlGdnUleLHgtzzu/VGO github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/go-acme/lego/v4 v4.21.0 h1:arEW+8o5p7VI8Bk1kr/PDlgD1DrxtTH1gJ4b7mehL8o= github.com/go-acme/lego/v4 v4.21.0/go.mod h1:HrSWzm3Ckj45Ie3i+p1zKVobbQoMOaGu9m4up0dUeDI= +github.com/go-acme/lego/v4 v4.22.2 h1:ck+HllWrV/rZGeYohsKQ5iKNnU/WAZxwOdiu6cxky+0= +github.com/go-acme/lego/v4 v4.22.2/go.mod h1:E2FndyI3Ekv0usNJt46mFb9LVpV/XBYT+4E3tz02Tzo= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= diff --git a/internal/applicant/providers.go b/internal/applicant/providers.go index 9989da8f..ef013490 100644 --- a/internal/applicant/providers.go +++ b/internal/applicant/providers.go @@ -19,6 +19,7 @@ import ( pGoDaddy "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/godaddy" pHuaweiCloud "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/huaweicloud" pJDCloud "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/jdcloud" + pNamecheap "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/namecheap" pNameDotCom "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/namedotcom" pNameSilo "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/namesilo" pNS1 "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/ns1" @@ -249,6 +250,22 @@ func createApplicant(options *applicantOptions) (challenge.Provider, error) { return applicant, err } + case domain.ApplyDNSProviderTypeNamecheap: + { + access := domain.AccessConfigForNamecheap{} + if err := maps.Populate(options.ProviderAccessConfig, &access); err != nil { + return nil, fmt.Errorf("failed to populate provider access config: %w", err) + } + + applicant, err := pNamecheap.NewChallengeProvider(&pNamecheap.ChallengeProviderConfig{ + Username: access.Username, + ApiKey: access.ApiKey, + DnsPropagationTimeout: options.DnsPropagationTimeout, + DnsTTL: options.DnsTTL, + }) + return applicant, err + } + case domain.ApplyDNSProviderTypeNameDotCom: { access := domain.AccessConfigForNameDotCom{} diff --git a/internal/domain/access.go b/internal/domain/access.go index fd01af3b..4b693522 100644 --- a/internal/domain/access.go +++ b/internal/domain/access.go @@ -131,6 +131,11 @@ type AccessConfigForKubernetes struct { type AccessConfigForLocal struct{} +type AccessConfigForNamecheap struct { + Username string `json:"username"` + ApiKey string `json:"apiKey"` +} + type AccessConfigForNameDotCom struct { Username string `json:"username"` ApiToken string `json:"apiToken"` diff --git a/internal/domain/provider.go b/internal/domain/provider.go index 375176ce..f0949e03 100644 --- a/internal/domain/provider.go +++ b/internal/domain/provider.go @@ -26,6 +26,7 @@ const ( AccessProviderTypeCMCCCloud = AccessProviderType("cmcccloud") AccessProviderTypeCTCCCloud = AccessProviderType("ctcccloud") // 联通云(预留) AccessProviderTypeCUCCCloud = AccessProviderType("cucccloud") // 天翼云(预留) + AccessProviderTypeDNSLA = AccessProviderType("dnsla") // DNS.LA(预留) AccessProviderTypeDogeCloud = AccessProviderType("dogecloud") AccessProviderTypeEdgio = AccessProviderType("edgio") AccessProviderTypeFastly = AccessProviderType("fastly") // Fastly(预留) @@ -37,6 +38,7 @@ const ( AccessProviderTypeJDCloud = AccessProviderType("jdcloud") AccessProviderTypeKubernetes = AccessProviderType("k8s") AccessProviderTypeLocal = AccessProviderType("local") + AccessProviderTypeNamecheap = AccessProviderType("namecheap") AccessProviderTypeNameDotCom = AccessProviderType("namedotcom") AccessProviderTypeNameSilo = AccessProviderType("namesilo") AccessProviderTypeNS1 = AccessProviderType("ns1") @@ -82,6 +84,7 @@ const ( ApplyDNSProviderTypeHuaweiCloudDNS = ApplyDNSProviderType("huaweicloud-dns") ApplyDNSProviderTypeJDCloud = ApplyDNSProviderType("jdcloud") // 兼容旧值,等同于 [ApplyDNSProviderTypeJDCloudDNS] ApplyDNSProviderTypeJDCloudDNS = ApplyDNSProviderType("jdcloud-dns") + ApplyDNSProviderTypeNamecheap = ApplyDNSProviderType("namecheap") ApplyDNSProviderTypeNameDotCom = ApplyDNSProviderType("namedotcom") ApplyDNSProviderTypeNameSilo = ApplyDNSProviderType("namesilo") ApplyDNSProviderTypeNS1 = ApplyDNSProviderType("ns1") diff --git a/internal/pkg/core/applicant/acme-dns-01/lego-providers/namecheap/namecheap.go b/internal/pkg/core/applicant/acme-dns-01/lego-providers/namecheap/namecheap.go new file mode 100644 index 00000000..9bf2f3c3 --- /dev/null +++ b/internal/pkg/core/applicant/acme-dns-01/lego-providers/namecheap/namecheap.go @@ -0,0 +1,38 @@ +package namedotcom + +import ( + "time" + + "github.com/go-acme/lego/v4/challenge" + "github.com/go-acme/lego/v4/providers/dns/namecheap" +) + +type ChallengeProviderConfig struct { + Username string `json:"username"` + ApiKey string `json:"apiKey"` + DnsPropagationTimeout int32 `json:"dnsPropagationTimeout,omitempty"` + DnsTTL int32 `json:"dnsTTL,omitempty"` +} + +func NewChallengeProvider(config *ChallengeProviderConfig) (challenge.Provider, error) { + if config == nil { + panic("config is nil") + } + + providerConfig := namecheap.NewDefaultConfig() + providerConfig.APIUser = config.Username + providerConfig.APIKey = config.ApiKey + if config.DnsPropagationTimeout != 0 { + providerConfig.PropagationTimeout = time.Duration(config.DnsPropagationTimeout) * time.Second + } + if config.DnsTTL != 0 { + providerConfig.TTL = int(config.DnsTTL) + } + + provider, err := namecheap.NewDNSProviderConfig(providerConfig) + if err != nil { + return nil, err + } + + return provider, nil +} diff --git a/migrations/1739462400_collections_snapshot.go b/migrations/1739462400_collections_snapshot.go index 9c079405..67453954 100644 --- a/migrations/1739462400_collections_snapshot.go +++ b/migrations/1739462400_collections_snapshot.go @@ -65,6 +65,7 @@ func init() { "cmcccloud", "ctcccloud", "cucccloud", + "dnsla", "dogecloud", "edgio", "fastly", @@ -76,6 +77,7 @@ func init() { "jdcloud", "k8s", "local", + "namecheap", "namedotcom", "namesilo", "ns1", @@ -173,6 +175,7 @@ func init() { "cmcccloud", "ctcccloud", "cucccloud", + "dnsla", "dogecloud", "edgio", "fastly", @@ -184,6 +187,7 @@ func init() { "jdcloud", "k8s", "local", + "namecheap", "namedotcom", "namesilo", "ns1", diff --git a/ui/public/imgs/providers/namecheap.svg b/ui/public/imgs/providers/namecheap.svg new file mode 100644 index 00000000..e90dbfe9 --- /dev/null +++ b/ui/public/imgs/providers/namecheap.svg @@ -0,0 +1 @@ + diff --git a/ui/src/components/access/AccessForm.tsx b/ui/src/components/access/AccessForm.tsx index 90bb6ff5..681d80f1 100644 --- a/ui/src/components/access/AccessForm.tsx +++ b/ui/src/components/access/AccessForm.tsx @@ -31,6 +31,7 @@ import AccessFormHuaweiCloudConfig from "./AccessFormHuaweiCloudConfig"; import AccessFormJDCloudConfig from "./AccessFormJDCloudConfig"; import AccessFormKubernetesConfig from "./AccessFormKubernetesConfig"; import AccessFormLocalConfig from "./AccessFormLocalConfig"; +import AccessFormNamecheapConfig from "./AccessFormNamecheapConfig"; import AccessFormNameDotComConfig from "./AccessFormNameDotComConfig"; import AccessFormNameSiloConfig from "./AccessFormNameSiloConfig"; import AccessFormNS1Config from "./AccessFormNS1Config"; @@ -141,6 +142,8 @@ const AccessForm = forwardRef(({ className, return ; case ACCESS_PROVIDERS.LOCAL: return ; + case ACCESS_PROVIDERS.NAMECHEAP: + return ; case ACCESS_PROVIDERS.NAMEDOTCOM: return ; case ACCESS_PROVIDERS.NAMESILO: diff --git a/ui/src/components/access/AccessFormNamecheapConfig.tsx b/ui/src/components/access/AccessFormNamecheapConfig.tsx new file mode 100644 index 00000000..d6a79f2a --- /dev/null +++ b/ui/src/components/access/AccessFormNamecheapConfig.tsx @@ -0,0 +1,76 @@ +import { useTranslation } from "react-i18next"; +import { Form, type FormInstance, Input } from "antd"; +import { createSchemaFieldRule } from "antd-zod"; +import { z } from "zod"; + +import { type AccessConfigForNamecheap } from "@/domain/access"; + +type AccessFormNamecheapConfigFieldValues = Nullish; + +export type AccessFormNamecheapConfigProps = { + form: FormInstance; + formName: string; + disabled?: boolean; + initialValues?: AccessFormNamecheapConfigFieldValues; + onValuesChange?: (values: AccessFormNamecheapConfigFieldValues) => void; +}; + +const initFormModel = (): AccessFormNamecheapConfigFieldValues => { + return { + username: "", + apiKey: "", + }; +}; + +const AccessFormNamecheapConfig = ({ form: formInst, formName, disabled, initialValues, onValuesChange }: AccessFormNamecheapConfigProps) => { + const { t } = useTranslation(); + + const formSchema = z.object({ + username: z + .string() + .min(1, t("access.form.namecheap_username.placeholder")) + .max(64, t("common.errmsg.string_max", { max: 64 })) + .trim(), + apiKey: z + .string() + .min(1, t("access.form.namecheap_api_key.placeholder")) + .max(64, t("common.errmsg.string_max", { max: 64 })) + .trim(), + }); + const formRule = createSchemaFieldRule(formSchema); + + const handleFormChange = (_: unknown, values: z.infer) => { + onValuesChange?.(values); + }; + + return ( +
+ } + > + + + + } + > + + +
+ ); +}; + +export default AccessFormNamecheapConfig; diff --git a/ui/src/domain/access.ts b/ui/src/domain/access.ts index da8739b7..a1e14d86 100644 --- a/ui/src/domain/access.ts +++ b/ui/src/domain/access.ts @@ -28,6 +28,7 @@ export interface AccessModel extends BaseModel { | AccessConfigForJDCloud | AccessConfigForKubernetes | AccessConfigForLocal + | AccessConfigForNamecheap | AccessConfigForNameDotCom | AccessConfigForNameSilo | AccessConfigForPowerDNS @@ -151,6 +152,11 @@ export type AccessConfigForKubernetes = { export type AccessConfigForLocal = NonNullable; +export type AccessConfigForNamecheap = { + username: string; + apiKey: string; +}; + export type AccessConfigForNameDotCom = { username: string; apiToken: string; diff --git a/ui/src/domain/provider.ts b/ui/src/domain/provider.ts index e99abb5c..3a806b88 100644 --- a/ui/src/domain/provider.ts +++ b/ui/src/domain/provider.ts @@ -26,6 +26,7 @@ export const ACCESS_PROVIDERS = Object.freeze({ JDCLOUD: "jdcloud", KUBERNETES: "k8s", LOCAL: "local", + NAMECHEAP: "namecheap", NAMEDOTCOM: "namedotcom", NAMESILO: "namesilo", NS1: "ns1", @@ -92,6 +93,7 @@ export const accessProvidersMap: Maphttps://kubernetes.io/docs/concepts/configuration/organize-cluster-access-kubeconfig/

Leave it blank to use the Pod's ServiceAccount.", + "access.form.namecheap_username.label": "Namecheap username", + "access.form.namecheap_username.placeholder": "Please enter Namecheap username", + "access.form.namecheap_username.tooltip": "For more information, see https://www.namecheap.com/support/api/intro/", + "access.form.namecheap_api_key.label": "Namecheap API key", + "access.form.namecheap_api_key.placeholder": "Please enter Namecheap API key", + "access.form.namecheap_api_key.tooltip": "For more information, see https://www.namecheap.com/support/api/intro/", "access.form.namedotcom_username.label": "Name.com username", "access.form.namedotcom_username.placeholder": "Please enter Name.com username", "access.form.namedotcom_username.tooltip": "For more information, see https://www.name.com/account/settings/api", diff --git a/ui/src/i18n/locales/en/nls.provider.json b/ui/src/i18n/locales/en/nls.provider.json index f0b13069..e924b43a 100644 --- a/ui/src/i18n/locales/en/nls.provider.json +++ b/ui/src/i18n/locales/en/nls.provider.json @@ -38,6 +38,7 @@ "provider.cmcccloud": "China Mobile Cloud (ECloud)", "provider.ctcccloud": "China Telecom Cloud (State Cloud)", "provider.cucccloud": "China Unicom Cloud", + "provider.dnsla": "DNS.LA", "provider.dogecloud": "Doge Cloud", "provider.dogecloud.cdn": "Doge Cloud - CDN (Content Delivery Network)", "provider.edgio": "Edgio", @@ -63,6 +64,7 @@ "provider.kubernetes": "Kubernetes", "provider.kubernetes.secret": "Kubernetes - Secret", "provider.local": "Local deployment", + "provider.namecheap": "Namecheap", "provider.namedotcom": "Name.com", "provider.namesilo": "NameSilo", "provider.ns1": "NS1 (IBM NS1 Connect)", diff --git a/ui/src/i18n/locales/zh/nls.access.json b/ui/src/i18n/locales/zh/nls.access.json index f4648c4d..cb9befa4 100644 --- a/ui/src/i18n/locales/zh/nls.access.json +++ b/ui/src/i18n/locales/zh/nls.access.json @@ -149,6 +149,12 @@ "access.form.k8s_kubeconfig.placeholder": "请选择 KubeConfig 文件", "access.form.k8s_kubeconfig.upload": "选择文件", "access.form.k8s_kubeconfig.tooltip": "这是什么?请参阅 https://kubernetes.io/zh-cn/docs/concepts/configuration/organize-cluster-access-kubeconfig/

为空时,将使用 Pod 的 ServiceAccount 作为凭证。", + "access.form.namecheap_username.label": "Namecheap 用户名", + "access.form.namecheap_username.placeholder": "请输入 Namecheap 用户名", + "access.form.namecheap_username.tooltip": "这是什么?请参阅 https://www.namecheap.com/support/api/intro/", + "access.form.namecheap_api_key.label": "Namecheap API Key", + "access.form.namecheap_api_key.placeholder": "请输入 Namecheap API Key", + "access.form.namecheap_api_key.tooltip": "这是什么?请参阅 https://www.namecheap.com/support/api/intro/", "access.form.namedotcom_username.label": "Name.com 用户名", "access.form.namedotcom_username.placeholder": "请输入 Name.com 用户名", "access.form.namedotcom_username.tooltip": "这是什么?请参阅 https://www.name.com/account/settings/api", diff --git a/ui/src/i18n/locales/zh/nls.provider.json b/ui/src/i18n/locales/zh/nls.provider.json index 101b0553..f8d36830 100644 --- a/ui/src/i18n/locales/zh/nls.provider.json +++ b/ui/src/i18n/locales/zh/nls.provider.json @@ -38,6 +38,7 @@ "provider.cmcccloud": "移动云", "provider.ctcccloud": "联通云", "provider.cucccloud": "天翼云", + "provider.dnsla": "DNS.LA", "provider.dogecloud": "多吉云", "provider.dogecloud.cdn": "多吉云 - 内容分发网络 CDN", "provider.edgio": "Edgio", @@ -63,6 +64,7 @@ "provider.kubernetes": "Kubernetes", "provider.kubernetes.secret": "Kubernetes - Secret", "provider.local": "本地部署", + "provider.namecheap": "Namecheap", "provider.namedotcom": "Name.com", "provider.namesilo": "NameSilo", "provider.ns1": "NS1(IBM NS1 Connect)", From 32fdb3ed88775cd695b2f98f957c97495c116190 Mon Sep 17 00:00:00 2001 From: Fu Diwei Date: Fri, 21 Feb 2025 13:53:44 +0800 Subject: [PATCH 30/34] fix: typo --- .../acme-dns-01/lego-providers/baiducloud/internal/lego.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/pkg/core/applicant/acme-dns-01/lego-providers/baiducloud/internal/lego.go b/internal/pkg/core/applicant/acme-dns-01/lego-providers/baiducloud/internal/lego.go index 721326a7..0d3f9c66 100644 --- a/internal/pkg/core/applicant/acme-dns-01/lego-providers/baiducloud/internal/lego.go +++ b/internal/pkg/core/applicant/acme-dns-01/lego-providers/baiducloud/internal/lego.go @@ -133,7 +133,7 @@ func (d *DNSProvider) getDNSRecord(zoneName, subDomain string) (*bceDns.Record, pageSize := 1000 for { request := &bceDns.ListRecordRequest{} - request.Rr = zoneName + request.Rr = subDomain request.Marker = pageMarker request.MaxKeys = pageSize From 92528edbfb856dcce1b1b06ae8a4f51f747ea4b7 Mon Sep 17 00:00:00 2001 From: Fu Diwei Date: Fri, 21 Feb 2025 14:15:23 +0800 Subject: [PATCH 31/34] chore: set default jdcloud logger level to warning --- .../lego-providers/jdcloud/internal/lego.go | 18 ++++++++---------- .../providers/jdcloud-alb/jdcloud_alb.go | 1 + .../providers/jdcloud-cdn/jdcloud_cdn.go | 1 + .../providers/jdcloud-live/jdcloud_live.go | 1 + .../providers/jdcloud-vod/jdcloud_vod.go | 1 + .../providers/jdcloud-ssl/jdcloud_ssl.go | 1 + 6 files changed, 13 insertions(+), 10 deletions(-) diff --git a/internal/pkg/core/applicant/acme-dns-01/lego-providers/jdcloud/internal/lego.go b/internal/pkg/core/applicant/acme-dns-01/lego-providers/jdcloud/internal/lego.go index d5103023..81f484b7 100644 --- a/internal/pkg/core/applicant/acme-dns-01/lego-providers/jdcloud/internal/lego.go +++ b/internal/pkg/core/applicant/acme-dns-01/lego-providers/jdcloud/internal/lego.go @@ -74,10 +74,11 @@ func NewDNSProviderConfig(config *Config) (*DNSProvider, error) { } clientCredentials := jdCore.NewCredentials(config.AccessKeyID, config.AccessKeySecret) - clientConfig := jdCore.NewConfig() - clientConfig.SetTimeout(config.HTTPTimeout) client := jdDnsClient.NewDomainserviceClient(clientCredentials) + clientConfig := &client.Config + clientConfig.SetTimeout(config.HTTPTimeout) client.SetConfig(clientConfig) + client.SetLogger(jdCore.NewDefaultLogger(jdCore.LogWarn)) return &DNSProvider{ client: client, @@ -133,11 +134,8 @@ func (d *DNSProvider) getDNSZone(domain string) (*jdDnsModel.DomainInfo, error) pageNumber := 1 pageSize := 100 for { - request := &jdDnsApi.DescribeDomainsRequest{} - request.RegionId = d.config.RegionId - request.DomainName = &domain - request.PageNumber = pageNumber - request.PageSize = pageSize + request := jdDnsApi.NewDescribeDomainsRequest(d.config.RegionId, pageNumber, pageSize) + request.SetDomainName(domain) response, err := d.client.DescribeDomains(request) if err != nil { @@ -170,9 +168,9 @@ func (d *DNSProvider) getDNSZoneAndRecord(zoneName, subDomain string) (*jdDnsMod pageSize := 100 for { request := jdDnsApi.NewDescribeResourceRecordRequest(d.config.RegionId, fmt.Sprintf("%d", &zone.Id)) - request.Search = &subDomain - request.PageNumber = &pageNumber - request.PageSize = &pageSize + request.SetSearch(subDomain) + request.SetPageNumber(pageNumber) + request.SetPageSize(pageSize) response, err := d.client.DescribeResourceRecord(request) if err != nil { diff --git a/internal/pkg/core/deployer/providers/jdcloud-alb/jdcloud_alb.go b/internal/pkg/core/deployer/providers/jdcloud-alb/jdcloud_alb.go index a300bb4d..41625b64 100644 --- a/internal/pkg/core/deployer/providers/jdcloud-alb/jdcloud_alb.go +++ b/internal/pkg/core/deployer/providers/jdcloud-alb/jdcloud_alb.go @@ -247,5 +247,6 @@ func (d *DeployerProvider) updateListenerCertificate(ctx context.Context, cloudL func createSdkClient(accessKeyId, accessKeySecret string) (*jdLbClient.LbClient, error) { clientCredentials := jdCore.NewCredentials(accessKeyId, accessKeySecret) client := jdLbClient.NewLbClient(clientCredentials) + client.SetLogger(jdCore.NewDefaultLogger(jdCore.LogWarn)) return client, nil } diff --git a/internal/pkg/core/deployer/providers/jdcloud-cdn/jdcloud_cdn.go b/internal/pkg/core/deployer/providers/jdcloud-cdn/jdcloud_cdn.go index 17523d1c..d5bdae4f 100644 --- a/internal/pkg/core/deployer/providers/jdcloud-cdn/jdcloud_cdn.go +++ b/internal/pkg/core/deployer/providers/jdcloud-cdn/jdcloud_cdn.go @@ -104,5 +104,6 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPe func createSdkClient(accessKeyId, accessKeySecret string) (*jdCdnClient.CdnClient, error) { clientCredentials := jdCore.NewCredentials(accessKeyId, accessKeySecret) client := jdCdnClient.NewCdnClient(clientCredentials) + client.SetLogger(jdCore.NewDefaultLogger(jdCore.LogWarn)) return client, nil } diff --git a/internal/pkg/core/deployer/providers/jdcloud-live/jdcloud_live.go b/internal/pkg/core/deployer/providers/jdcloud-live/jdcloud_live.go index 42a474de..7998fb16 100644 --- a/internal/pkg/core/deployer/providers/jdcloud-live/jdcloud_live.go +++ b/internal/pkg/core/deployer/providers/jdcloud-live/jdcloud_live.go @@ -70,5 +70,6 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPe func createSdkClient(accessKeyId, accessKeySecret string) (*jdLiveClient.LiveClient, error) { clientCredentials := jdCore.NewCredentials(accessKeyId, accessKeySecret) client := jdLiveClient.NewLiveClient(clientCredentials) + client.SetLogger(jdCore.NewDefaultLogger(jdCore.LogWarn)) return client, nil } diff --git a/internal/pkg/core/deployer/providers/jdcloud-vod/jdcloud_vod.go b/internal/pkg/core/deployer/providers/jdcloud-vod/jdcloud_vod.go index 8db109c1..b83fd430 100644 --- a/internal/pkg/core/deployer/providers/jdcloud-vod/jdcloud_vod.go +++ b/internal/pkg/core/deployer/providers/jdcloud-vod/jdcloud_vod.go @@ -118,5 +118,6 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPe func createSdkClient(accessKeyId, accessKeySecret string) (*jdVodClient.VodClient, error) { clientCredentials := jdCore.NewCredentials(accessKeyId, accessKeySecret) client := jdVodClient.NewVodClient(clientCredentials) + client.SetLogger(jdCore.NewDefaultLogger(jdCore.LogWarn)) return client, nil } diff --git a/internal/pkg/core/uploader/providers/jdcloud-ssl/jdcloud_ssl.go b/internal/pkg/core/uploader/providers/jdcloud-ssl/jdcloud_ssl.go index b53bf87c..e47b8aeb 100644 --- a/internal/pkg/core/uploader/providers/jdcloud-ssl/jdcloud_ssl.go +++ b/internal/pkg/core/uploader/providers/jdcloud-ssl/jdcloud_ssl.go @@ -134,5 +134,6 @@ func (u *UploaderProvider) Upload(ctx context.Context, certPem string, privkeyPe func createSdkClient(accessKeyId, accessKeySecret string) (*jdSslClient.SslClient, error) { clientCredentials := jdCore.NewCredentials(accessKeyId, accessKeySecret) client := jdSslClient.NewSslClient(clientCredentials) + client.SetLogger(jdCore.NewDefaultLogger(jdCore.LogWarn)) return client, nil } From 316a3c950f506c3404be8496bef8264fb1e9b96b Mon Sep 17 00:00:00 2001 From: Fu Diwei Date: Fri, 21 Feb 2025 14:48:04 +0800 Subject: [PATCH 32/34] fix: nil poiner dereference --- .../lego-providers/jdcloud/internal/lego.go | 18 ++++++++++-------- .../providers/jdcloud-ssl/jdcloud_ssl.go | 2 +- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/internal/pkg/core/applicant/acme-dns-01/lego-providers/jdcloud/internal/lego.go b/internal/pkg/core/applicant/acme-dns-01/lego-providers/jdcloud/internal/lego.go index 81f484b7..bdbe5235 100644 --- a/internal/pkg/core/applicant/acme-dns-01/lego-providers/jdcloud/internal/lego.go +++ b/internal/pkg/core/applicant/acme-dns-01/lego-providers/jdcloud/internal/lego.go @@ -132,7 +132,7 @@ func (d *DNSProvider) Timeout() (timeout, interval time.Duration) { func (d *DNSProvider) getDNSZone(domain string) (*jdDnsModel.DomainInfo, error) { pageNumber := 1 - pageSize := 100 + pageSize := 10 for { request := jdDnsApi.NewDescribeDomainsRequest(d.config.RegionId, pageNumber, pageSize) request.SetDomainName(domain) @@ -165,9 +165,9 @@ func (d *DNSProvider) getDNSZoneAndRecord(zoneName, subDomain string) (*jdDnsMod } pageNumber := 1 - pageSize := 100 + pageSize := 10 for { - request := jdDnsApi.NewDescribeResourceRecordRequest(d.config.RegionId, fmt.Sprintf("%d", &zone.Id)) + request := jdDnsApi.NewDescribeResourceRecordRequest(d.config.RegionId, fmt.Sprintf("%d", zone.Id)) request.SetSearch(subDomain) request.SetPageNumber(pageNumber) request.SetPageSize(pageSize) @@ -190,7 +190,7 @@ func (d *DNSProvider) getDNSZoneAndRecord(zoneName, subDomain string) (*jdDnsMod pageNumber++ } - return nil, nil, nil + return zone, nil, nil } func (d *DNSProvider) addOrUpdateDNSRecord(zoneName, subDomain, value string) error { @@ -200,20 +200,22 @@ func (d *DNSProvider) addOrUpdateDNSRecord(zoneName, subDomain, value string) er } if record == nil { - request := jdDnsApi.NewCreateResourceRecordRequest(d.config.RegionId, fmt.Sprintf("%d", &zone.Id), &jdDnsModel.AddRR{ + request := jdDnsApi.NewCreateResourceRecordRequest(d.config.RegionId, fmt.Sprintf("%d", zone.Id), &jdDnsModel.AddRR{ Type: "TXT", HostRecord: subDomain, HostValue: value, Ttl: int(d.config.TTL), + ViewValue: -1, }) _, err := d.client.CreateResourceRecord(request) return err } else { - request := jdDnsApi.NewModifyResourceRecordRequest(d.config.RegionId, fmt.Sprintf("%d", &zone.Id), fmt.Sprintf("%d", &record.Id), &jdDnsModel.UpdateRR{ + request := jdDnsApi.NewModifyResourceRecordRequest(d.config.RegionId, fmt.Sprintf("%d", zone.Id), fmt.Sprintf("%d", record.Id), &jdDnsModel.UpdateRR{ Type: "TXT", HostRecord: subDomain, HostValue: value, Ttl: int(d.config.TTL), + ViewValue: -1, }) _, err := d.client.ModifyResourceRecord(request) return err @@ -229,8 +231,8 @@ func (d *DNSProvider) removeDNSRecord(zoneName, subDomain string) error { if record == nil { return nil } else { - req := jdDnsApi.NewDeleteResourceRecordRequest(d.config.RegionId, fmt.Sprintf("%d", &zone.Id), fmt.Sprintf("%d", &record.Id)) - _, err = d.client.DeleteResourceRecord(req) + request := jdDnsApi.NewDeleteResourceRecordRequest(d.config.RegionId, fmt.Sprintf("%d", zone.Id), fmt.Sprintf("%d", record.Id)) + _, err = d.client.DeleteResourceRecord(request) return err } } diff --git a/internal/pkg/core/uploader/providers/jdcloud-ssl/jdcloud_ssl.go b/internal/pkg/core/uploader/providers/jdcloud-ssl/jdcloud_ssl.go index e47b8aeb..afbbf3e1 100644 --- a/internal/pkg/core/uploader/providers/jdcloud-ssl/jdcloud_ssl.go +++ b/internal/pkg/core/uploader/providers/jdcloud-ssl/jdcloud_ssl.go @@ -64,7 +64,7 @@ func (u *UploaderProvider) Upload(ctx context.Context, certPem string, privkeyPe // 遍历查看证书列表,避免重复上传 // REF: https://docs.jdcloud.com/cn/ssl-certificate/api/describecerts describeCertsPageNumber := 1 - describeCertsPageSize := 100 + describeCertsPageSize := 10 for { describeCertsReq := jdSslApi.NewDescribeCertsRequest() describeCertsReq.SetDomainName(certX509.Subject.CommonName) From f81fa2eb63f55217c109e20aa48785d8f26add19 Mon Sep 17 00:00:00 2001 From: Fu Diwei Date: Fri, 21 Feb 2025 17:21:39 +0800 Subject: [PATCH 33/34] feat: add dns.la dns-01 applicant --- README.md | 3 +- README_EN.md | 3 +- internal/applicant/providers.go | 19 +- internal/domain/access.go | 5 + internal/domain/provider.go | 3 +- .../acme-dns-01/lego-providers/dnsla/dnsla.go | 39 +++ .../lego-providers/dnsla/internal/lego.go | 240 ++++++++++++++++++ .../lego-providers/gname/internal/lego.go | 2 +- .../lego-providers/jdcloud/internal/lego.go | 8 +- internal/pkg/vendors/baishan-sdk/client.go | 3 +- internal/pkg/vendors/cachefly-sdk/client.go | 3 +- internal/pkg/vendors/dnsla-sdk/api.go | 52 ++++ internal/pkg/vendors/dnsla-sdk/client.go | 80 ++++++ internal/pkg/vendors/dnsla-sdk/models.go | 125 +++++++++ ui/public/imgs/providers/dnsla.svg | 1 + ui/src/components/access/AccessForm.tsx | 3 + .../access/AccessFormDNSLAConfig.tsx | 76 ++++++ ui/src/domain/access.ts | 6 + ui/src/domain/provider.ts | 6 +- ui/src/i18n/locales/en/nls.access.json | 6 + ui/src/i18n/locales/zh/nls.access.json | 6 + 21 files changed, 677 insertions(+), 12 deletions(-) create mode 100644 internal/pkg/core/applicant/acme-dns-01/lego-providers/dnsla/dnsla.go create mode 100644 internal/pkg/core/applicant/acme-dns-01/lego-providers/dnsla/internal/lego.go create mode 100644 internal/pkg/vendors/dnsla-sdk/api.go create mode 100644 internal/pkg/vendors/dnsla-sdk/client.go create mode 100644 internal/pkg/vendors/dnsla-sdk/models.go create mode 100644 ui/public/imgs/providers/dnsla.svg create mode 100644 ui/src/components/access/AccessFormDNSLAConfig.tsx diff --git a/README.md b/README.md index 1bcf2034..0899200e 100644 --- a/README.md +++ b/README.md @@ -97,7 +97,8 @@ make local.run | [AWS Route53](https://aws.amazon.com/route53/) | | | [Azure](https://azure.microsoft.com/) | | | [CloudFlare](https://www.cloudflare.com/) | | -| [ClouDNS](https://www.cloudns.net//) | | +| [ClouDNS](https://www.cloudns.net/) | | +| [DNS.LA](https://www.dns.la/) | | | [Gcore](https://gcore.com/) | | | [GNAME](https://www.gname.com/) | | | [GoDaddy](https://www.godaddy.com/) | | diff --git a/README_EN.md b/README_EN.md index 2e850330..b92fc82a 100644 --- a/README_EN.md +++ b/README_EN.md @@ -96,7 +96,8 @@ The following DNS providers are supported: | [AWS Route53](https://aws.amazon.com/route53/) | | | [Azure DNS](https://azure.microsoft.com/) | | | [CloudFlare](https://www.cloudflare.com/) | | -| [ClouDNS](https://www.cloudns.net//) | | +| [ClouDNS](https://www.cloudns.net/) | | +| [DNS.LA](https://www.dns.la/) | | | [Gcore](https://gcore.com/) | | | [GNAME](https://www.gname.com/) | | | [GoDaddy](https://www.godaddy.com/) | | diff --git a/internal/applicant/providers.go b/internal/applicant/providers.go index ef013490..cc8a3cfd 100644 --- a/internal/applicant/providers.go +++ b/internal/applicant/providers.go @@ -14,6 +14,7 @@ import ( pCloudflare "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/cloudflare" pClouDNS "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/cloudns" pCMCCCloud "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/cmcccloud" + pDNSLA "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/dnsla" pGcore "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/gcore" pGname "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/gname" pGoDaddy "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/godaddy" @@ -169,6 +170,22 @@ func createApplicant(options *applicantOptions) (challenge.Provider, error) { return applicant, err } + case domain.ApplyDNSProviderTypeDNSLA: + { + access := domain.AccessConfigForDNSLA{} + if err := maps.Populate(options.ProviderAccessConfig, &access); err != nil { + return nil, fmt.Errorf("failed to populate provider access config: %w", err) + } + + applicant, err := pDNSLA.NewChallengeProvider(&pDNSLA.ChallengeProviderConfig{ + ApiId: access.ApiId, + ApiSecret: access.ApiSecret, + DnsPropagationTimeout: options.DnsPropagationTimeout, + DnsTTL: options.DnsTTL, + }) + return applicant, err + } + case domain.ApplyDNSProviderTypeGcore: { access := domain.AccessConfigForGcore{} @@ -259,7 +276,7 @@ func createApplicant(options *applicantOptions) (challenge.Provider, error) { applicant, err := pNamecheap.NewChallengeProvider(&pNamecheap.ChallengeProviderConfig{ Username: access.Username, - ApiKey: access.ApiKey, + ApiKey: access.ApiKey, DnsPropagationTimeout: options.DnsPropagationTimeout, DnsTTL: options.DnsTTL, }) diff --git a/internal/domain/access.go b/internal/domain/access.go index 4b693522..25df3210 100644 --- a/internal/domain/access.go +++ b/internal/domain/access.go @@ -91,6 +91,11 @@ type AccessConfigForCMCCCloud struct { AccessKeySecret string `json:"accessKeySecret"` } +type AccessConfigForDNSLA struct { + ApiId string `json:"apiId"` + ApiSecret string `json:"apiSecret"` +} + type AccessConfigForDogeCloud struct { AccessKey string `json:"accessKey"` SecretKey string `json:"secretKey"` diff --git a/internal/domain/provider.go b/internal/domain/provider.go index f0949e03..950abc08 100644 --- a/internal/domain/provider.go +++ b/internal/domain/provider.go @@ -26,7 +26,7 @@ const ( AccessProviderTypeCMCCCloud = AccessProviderType("cmcccloud") AccessProviderTypeCTCCCloud = AccessProviderType("ctcccloud") // 联通云(预留) AccessProviderTypeCUCCCloud = AccessProviderType("cucccloud") // 天翼云(预留) - AccessProviderTypeDNSLA = AccessProviderType("dnsla") // DNS.LA(预留) + AccessProviderTypeDNSLA = AccessProviderType("dnsla") AccessProviderTypeDogeCloud = AccessProviderType("dogecloud") AccessProviderTypeEdgio = AccessProviderType("edgio") AccessProviderTypeFastly = AccessProviderType("fastly") // Fastly(预留) @@ -77,6 +77,7 @@ const ( ApplyDNSProviderTypeCloudflare = ApplyDNSProviderType("cloudflare") ApplyDNSProviderTypeClouDNS = ApplyDNSProviderType("cloudns") ApplyDNSProviderTypeCMCCCloud = ApplyDNSProviderType("cmcccloud") + ApplyDNSProviderTypeDNSLA = ApplyDNSProviderType("dnsla") ApplyDNSProviderTypeGcore = ApplyDNSProviderType("gcore") ApplyDNSProviderTypeGname = ApplyDNSProviderType("gname") ApplyDNSProviderTypeGoDaddy = ApplyDNSProviderType("godaddy") diff --git a/internal/pkg/core/applicant/acme-dns-01/lego-providers/dnsla/dnsla.go b/internal/pkg/core/applicant/acme-dns-01/lego-providers/dnsla/dnsla.go new file mode 100644 index 00000000..5b0bd977 --- /dev/null +++ b/internal/pkg/core/applicant/acme-dns-01/lego-providers/dnsla/dnsla.go @@ -0,0 +1,39 @@ +package dnsla + +import ( + "time" + + "github.com/go-acme/lego/v4/challenge" + + internal "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/dnsla/internal" +) + +type ChallengeProviderConfig struct { + ApiId string `json:"apiId"` + ApiSecret string `json:"apiSecret"` + DnsPropagationTimeout int32 `json:"dnsPropagationTimeout,omitempty"` + DnsTTL int32 `json:"dnsTTL,omitempty"` +} + +func NewChallengeProvider(config *ChallengeProviderConfig) (challenge.Provider, error) { + if config == nil { + panic("config is nil") + } + + providerConfig := internal.NewDefaultConfig() + providerConfig.APIId = config.ApiId + providerConfig.APISecret = config.ApiSecret + if config.DnsPropagationTimeout != 0 { + providerConfig.PropagationTimeout = time.Duration(config.DnsPropagationTimeout) * time.Second + } + if config.DnsTTL != 0 { + providerConfig.TTL = int(config.DnsTTL) + } + + provider, err := internal.NewDNSProviderConfig(providerConfig) + if err != nil { + return nil, err + } + + return provider, nil +} diff --git a/internal/pkg/core/applicant/acme-dns-01/lego-providers/dnsla/internal/lego.go b/internal/pkg/core/applicant/acme-dns-01/lego-providers/dnsla/internal/lego.go new file mode 100644 index 00000000..1b9603bd --- /dev/null +++ b/internal/pkg/core/applicant/acme-dns-01/lego-providers/dnsla/internal/lego.go @@ -0,0 +1,240 @@ +package lego_dnsla + +import ( + "errors" + "fmt" + "strings" + "time" + + "github.com/go-acme/lego/v4/challenge" + "github.com/go-acme/lego/v4/challenge/dns01" + "github.com/go-acme/lego/v4/platform/config/env" + + dnslasdk "github.com/usual2970/certimate/internal/pkg/vendors/dnsla-sdk" +) + +const ( + envNamespace = "DNSLA_" + + EnvAPIId = envNamespace + "API_ID" + EnvAPISecret = envNamespace + "API_KEY" + + EnvTTL = envNamespace + "TTL" + EnvPropagationTimeout = envNamespace + "PROPAGATION_TIMEOUT" + EnvPollingInterval = envNamespace + "POLLING_INTERVAL" + EnvHTTPTimeout = envNamespace + "HTTP_TIMEOUT" +) + +var _ challenge.ProviderTimeout = (*DNSProvider)(nil) + +type Config struct { + APIId string + APISecret string + + PropagationTimeout time.Duration + PollingInterval time.Duration + TTL int + HTTPTimeout time.Duration +} + +type DNSProvider struct { + client *dnslasdk.Client + config *Config +} + +func NewDefaultConfig() *Config { + return &Config{ + TTL: env.GetOrDefaultInt(EnvTTL, 300), + PropagationTimeout: env.GetOrDefaultSecond(EnvPropagationTimeout, 2*time.Minute), + PollingInterval: env.GetOrDefaultSecond(EnvPollingInterval, dns01.DefaultPollingInterval), + HTTPTimeout: env.GetOrDefaultSecond(EnvHTTPTimeout, 30*time.Second), + } +} + +func NewDNSProvider() (*DNSProvider, error) { + values, err := env.Get(EnvAPIId, EnvAPISecret) + if err != nil { + return nil, fmt.Errorf("dnsla: %w", err) + } + + config := NewDefaultConfig() + config.APIId = values[EnvAPIId] + config.APISecret = values[EnvAPISecret] + + return NewDNSProviderConfig(config) +} + +func NewDNSProviderConfig(config *Config) (*DNSProvider, error) { + if config == nil { + return nil, errors.New("dnsla: the configuration of the DNS provider is nil") + } + + client := dnslasdk.NewClient(config.APIId, config.APISecret). + WithTimeout(config.HTTPTimeout) + + return &DNSProvider{ + client: client, + config: config, + }, nil +} + +func (d *DNSProvider) Present(domain, token, keyAuth string) error { + info := dns01.GetChallengeInfo(domain, keyAuth) + + authZone, err := dns01.FindZoneByFqdn(info.EffectiveFQDN) + if err != nil { + return fmt.Errorf("dnsla: %w", err) + } + + subDomain, err := dns01.ExtractSubDomain(info.EffectiveFQDN, authZone) + if err != nil { + return fmt.Errorf("dnsla: %w", err) + } + + if err := d.addOrUpdateDNSRecord(dns01.UnFqdn(authZone), subDomain, info.Value); err != nil { + return fmt.Errorf("dnsla: %w", err) + } + + return nil +} + +func (d *DNSProvider) CleanUp(domain, token, keyAuth string) error { + info := dns01.GetChallengeInfo(domain, keyAuth) + + authZone, err := dns01.FindZoneByFqdn(info.EffectiveFQDN) + if err != nil { + return fmt.Errorf("dnsla: %w", err) + } + + subDomain, err := dns01.ExtractSubDomain(info.EffectiveFQDN, authZone) + if err != nil { + return fmt.Errorf("dnsla: %w", err) + } + + if err := d.removeDNSRecord(dns01.UnFqdn(authZone), subDomain); err != nil { + return fmt.Errorf("dnsla: %w", err) + } + + return nil +} + +func (d *DNSProvider) Timeout() (timeout, interval time.Duration) { + return d.config.PropagationTimeout, d.config.PollingInterval +} + +func (d *DNSProvider) getDNSZone(zoneName string) (*dnslasdk.DomainInfo, error) { + pageIndex := 1 + pageSize := 100 + for { + request := &dnslasdk.ListDomainsRequest{ + PageIndex: int32(pageIndex), + PageSize: int32(pageSize), + } + response, err := d.client.ListDomains(request) + if err != nil { + return nil, err + } + + if response.Data != nil { + for _, item := range response.Data.Results { + if strings.TrimRight(item.Domain, ".") == zoneName || strings.TrimRight(item.DisplayDomain, ".") == zoneName { + return item, nil + } + } + } + + if response.Data == nil || len(response.Data.Results) < pageSize { + break + } + + pageIndex++ + } + + return nil, fmt.Errorf("dnsla: zone %s not found", zoneName) +} + +func (d *DNSProvider) getDNSZoneAndRecord(zoneName, subDomain string) (*dnslasdk.DomainInfo, *dnslasdk.RecordInfo, error) { + zone, err := d.getDNSZone(zoneName) + if err != nil { + return nil, nil, err + } + + pageIndex := 1 + pageSize := 100 + for { + request := &dnslasdk.ListRecordsRequest{ + DomainId: zone.Id, + Host: &subDomain, + PageIndex: int32(pageIndex), + PageSize: int32(pageSize), + } + response, err := d.client.ListRecords(request) + if err != nil { + return zone, nil, err + } + + if response.Data != nil { + for _, record := range response.Data.Results { + if record.Type == 16 && (record.Host == subDomain || record.DisplayHost == subDomain) { + return zone, record, nil + } + } + } + + if response.Data == nil || len(response.Data.Results) < pageSize { + break + } + + pageIndex++ + } + + return zone, nil, nil +} + +func (d *DNSProvider) addOrUpdateDNSRecord(zoneName, subDomain, value string) error { + zone, record, err := d.getDNSZoneAndRecord(zoneName, subDomain) + if err != nil { + return err + } + + if record == nil { + request := &dnslasdk.CreateRecordRequest{ + DomainId: zone.Id, + Type: 16, + Host: subDomain, + Data: value, + Ttl: int32(d.config.TTL), + } + _, err := d.client.CreateRecord(request) + return err + } else { + reqType := int32(16) + reqTtl := int32(d.config.TTL) + request := &dnslasdk.UpdateRecordRequest{ + Id: record.Id, + Type: &reqType, + Host: &subDomain, + Data: &value, + Ttl: &reqTtl, + } + _, err := d.client.UpdateRecord(request) + return err + } +} + +func (d *DNSProvider) removeDNSRecord(zoneName, subDomain string) error { + _, record, err := d.getDNSZoneAndRecord(zoneName, subDomain) + if err != nil { + return err + } + + if record == nil { + return nil + } else { + request := &dnslasdk.DeleteRecordRequest{ + Id: record.Id, + } + _, err = d.client.DeleteRecord(request) + return err + } +} diff --git a/internal/pkg/core/applicant/acme-dns-01/lego-providers/gname/internal/lego.go b/internal/pkg/core/applicant/acme-dns-01/lego-providers/gname/internal/lego.go index 17e9162f..3d0f2e54 100644 --- a/internal/pkg/core/applicant/acme-dns-01/lego-providers/gname/internal/lego.go +++ b/internal/pkg/core/applicant/acme-dns-01/lego-providers/gname/internal/lego.go @@ -43,7 +43,7 @@ type DNSProvider struct { func NewDefaultConfig() *Config { return &Config{ - TTL: env.GetOrDefaultInt(EnvTTL, dns01.DefaultTTL), + TTL: env.GetOrDefaultInt(EnvTTL, 300), PropagationTimeout: env.GetOrDefaultSecond(EnvPropagationTimeout, 2*time.Minute), PollingInterval: env.GetOrDefaultSecond(EnvPollingInterval, dns01.DefaultPollingInterval), HTTPTimeout: env.GetOrDefaultSecond(EnvHTTPTimeout, 30*time.Second), diff --git a/internal/pkg/core/applicant/acme-dns-01/lego-providers/jdcloud/internal/lego.go b/internal/pkg/core/applicant/acme-dns-01/lego-providers/jdcloud/internal/lego.go index bdbe5235..68d81f7e 100644 --- a/internal/pkg/core/applicant/acme-dns-01/lego-providers/jdcloud/internal/lego.go +++ b/internal/pkg/core/applicant/acme-dns-01/lego-providers/jdcloud/internal/lego.go @@ -130,12 +130,12 @@ func (d *DNSProvider) Timeout() (timeout, interval time.Duration) { return d.config.PropagationTimeout, d.config.PollingInterval } -func (d *DNSProvider) getDNSZone(domain string) (*jdDnsModel.DomainInfo, error) { +func (d *DNSProvider) getDNSZone(zoneName string) (*jdDnsModel.DomainInfo, error) { pageNumber := 1 pageSize := 10 for { request := jdDnsApi.NewDescribeDomainsRequest(d.config.RegionId, pageNumber, pageSize) - request.SetDomainName(domain) + request.SetDomainName(zoneName) response, err := d.client.DescribeDomains(request) if err != nil { @@ -143,7 +143,7 @@ func (d *DNSProvider) getDNSZone(domain string) (*jdDnsModel.DomainInfo, error) } for _, item := range response.Result.DataList { - if item.DomainName == domain { + if item.DomainName == zoneName { return &item, nil } } @@ -155,7 +155,7 @@ func (d *DNSProvider) getDNSZone(domain string) (*jdDnsModel.DomainInfo, error) pageNumber++ } - return nil, fmt.Errorf("jdcloud: zone %s not found", domain) + return nil, fmt.Errorf("jdcloud: zone %s not found", zoneName) } func (d *DNSProvider) getDNSZoneAndRecord(zoneName, subDomain string) (*jdDnsModel.DomainInfo, *jdDnsModel.RRInfo, error) { diff --git a/internal/pkg/vendors/baishan-sdk/client.go b/internal/pkg/vendors/baishan-sdk/client.go index ff66af5b..e52e6af9 100644 --- a/internal/pkg/vendors/baishan-sdk/client.go +++ b/internal/pkg/vendors/baishan-sdk/client.go @@ -12,7 +12,8 @@ import ( type Client struct { apiToken string - client *resty.Client + + client *resty.Client } func NewClient(apiToken string) *Client { diff --git a/internal/pkg/vendors/cachefly-sdk/client.go b/internal/pkg/vendors/cachefly-sdk/client.go index e48e2010..d74c3698 100644 --- a/internal/pkg/vendors/cachefly-sdk/client.go +++ b/internal/pkg/vendors/cachefly-sdk/client.go @@ -12,7 +12,8 @@ import ( type Client struct { apiToken string - client *resty.Client + + client *resty.Client } func NewClient(apiToken string) *Client { diff --git a/internal/pkg/vendors/dnsla-sdk/api.go b/internal/pkg/vendors/dnsla-sdk/api.go new file mode 100644 index 00000000..df8e6026 --- /dev/null +++ b/internal/pkg/vendors/dnsla-sdk/api.go @@ -0,0 +1,52 @@ +package dnslasdk + +import ( + "fmt" + "net/http" + "net/url" +) + +func (c *Client) ListDomains(req *ListDomainsRequest) (*ListDomainsResponse, error) { + resp := ListDomainsResponse{} + err := c.sendRequestWithResult(http.MethodGet, "/domainList", req, &resp) + if err != nil { + return nil, err + } + return &resp, nil +} + +func (c *Client) ListRecords(req *ListRecordsRequest) (*ListRecordsResponse, error) { + resp := ListRecordsResponse{} + err := c.sendRequestWithResult(http.MethodGet, "/recordList", req, &resp) + if err != nil { + return nil, err + } + return &resp, nil +} + +func (c *Client) CreateRecord(req *CreateRecordRequest) (*CreateRecordResponse, error) { + resp := CreateRecordResponse{} + err := c.sendRequestWithResult(http.MethodPost, "/record", req, &resp) + if err != nil { + return nil, err + } + return &resp, nil +} + +func (c *Client) UpdateRecord(req *UpdateRecordRequest) (*UpdateRecordResponse, error) { + resp := UpdateRecordResponse{} + err := c.sendRequestWithResult(http.MethodPut, "/record", req, &resp) + if err != nil { + return nil, err + } + return &resp, nil +} + +func (c *Client) DeleteRecord(req *DeleteRecordRequest) (*DeleteRecordResponse, error) { + resp := DeleteRecordResponse{} + err := c.sendRequestWithResult(http.MethodDelete, fmt.Sprintf("/record?id=%s", url.QueryEscape(req.Id)), req, &resp) + if err != nil { + return nil, err + } + return &resp, nil +} diff --git a/internal/pkg/vendors/dnsla-sdk/client.go b/internal/pkg/vendors/dnsla-sdk/client.go new file mode 100644 index 00000000..936b634d --- /dev/null +++ b/internal/pkg/vendors/dnsla-sdk/client.go @@ -0,0 +1,80 @@ +package dnslasdk + +import ( + "encoding/json" + "fmt" + "net/http" + "strings" + "time" + + "github.com/go-resty/resty/v2" +) + +type Client struct { + apiId string + apiSecret string + + client *resty.Client +} + +func NewClient(apiId, apiSecret string) *Client { + client := resty.New() + + return &Client{ + apiId: apiId, + apiSecret: apiSecret, + client: client, + } +} + +func (c *Client) WithTimeout(timeout time.Duration) *Client { + c.client.SetTimeout(timeout) + return c +} + +func (c *Client) sendRequest(method string, path string, params interface{}) (*resty.Response, error) { + req := c.client.R().SetBasicAuth(c.apiId, c.apiSecret) + req.Method = method + req.URL = "https://api.dns.la/api" + path + if strings.EqualFold(method, http.MethodGet) { + qs := make(map[string]string) + if params != nil { + temp := make(map[string]any) + jsonData, _ := json.Marshal(params) + json.Unmarshal(jsonData, &temp) + for k, v := range temp { + qs[k] = fmt.Sprintf("%v", v) + } + } + + req = req.SetQueryParams(qs) + } else { + req = req. + SetHeader("Content-Type", "application/json"). + SetBody(params) + } + + resp, err := req.Send() + if err != nil { + return nil, fmt.Errorf("dnsla api error: failed to send request: %w", err) + } else if resp.IsError() { + return nil, fmt.Errorf("dnsla api error: unexpected status code: %d, %s", resp.StatusCode(), resp.Body()) + } + + return resp, nil +} + +func (c *Client) sendRequestWithResult(method string, path string, params interface{}, result BaseResponse) error { + resp, err := c.sendRequest(method, path, params) + if err != nil { + return err + } + + if err := json.Unmarshal(resp.Body(), &result); err != nil { + return fmt.Errorf("dnsla api error: failed to parse response: %w", err) + } else if errcode := result.GetCode(); errcode/100 != 2 { + return fmt.Errorf("dnsla api error: %d - %s", errcode, result.GetMessage()) + } + + return nil +} diff --git a/internal/pkg/vendors/dnsla-sdk/models.go b/internal/pkg/vendors/dnsla-sdk/models.go new file mode 100644 index 00000000..85fe7978 --- /dev/null +++ b/internal/pkg/vendors/dnsla-sdk/models.go @@ -0,0 +1,125 @@ +package dnslasdk + +type BaseResponse interface { + GetCode() int + GetMessage() string +} + +type baseResponse struct { + Code int `json:"code"` + Message string `json:"message"` +} + +func (r *baseResponse) GetCode() int { + return r.Code +} + +func (r *baseResponse) GetMessage() string { + return r.Message +} + +type DomainInfo struct { + Id string `json:"id"` + GroupId string `json:"groupId"` + GroupName string `json:"groupName"` + Domain string `json:"domain"` + DisplayDomain string `json:"displayDomain"` + CreatedAt int64 `json:"createdAt"` + UpdatedAt int64 `json:"updatedAt"` +} + +type RecordInfo struct { + Id string `json:"id"` + DomainId string `json:"domainId"` + GroupId string `json:"groupId"` + GroupName string `json:"groupName"` + LineId string `json:"lineId"` + LineCode string `json:"lineCode"` + LineName string `json:"lineName"` + Type int32 `json:"type"` + Host string `json:"host"` + DisplayHost string `json:"displayHost"` + Data string `json:"data"` + DisplayData string `json:"displayData"` + Ttl int32 `json:"ttl"` + Weight int32 `json:"weight"` + Preference int32 `json:"preference"` + CreatedAt int64 `json:"createdAt"` + UpdatedAt int64 `json:"updatedAt"` +} + +type ListDomainsRequest struct { + PageIndex int32 `json:"pageIndex"` + PageSize int32 `json:"pageSize"` + GroupId *string `json:"groupId,omitempty"` +} + +type ListDomainsResponse struct { + baseResponse + Data *struct { + Total int32 `json:"total"` + Results []*DomainInfo `json:"results"` + } `json:"data,omitempty"` +} + +type ListRecordsRequest struct { + PageIndex int32 `json:"pageIndex"` + PageSize int32 `json:"pageSize"` + DomainId string `json:"domainId"` + GroupId *string `json:"groupId,omitempty"` + LineId *string `json:"lineId,omitempty"` + Type *int32 `json:"type,omitempty"` + Host *string `json:"host,omitempty"` + Data *string `json:"data,omitempty"` +} + +type ListRecordsResponse struct { + baseResponse + Data *struct { + Total int32 `json:"total"` + Results []*RecordInfo `json:"results"` + } `json:"data,omitempty"` +} + +type CreateRecordRequest struct { + DomainId string `json:"domainId"` + GroupId *string `json:"groupId,omitempty"` + LineId *string `json:"lineId,omitempty"` + Type int32 `json:"type"` + Host string `json:"host"` + Data string `json:"data"` + Ttl int32 `json:"ttl"` + Weight *int32 `json:"weight,omitempty"` + Preference *int32 `json:"preference,omitempty"` +} + +type CreateRecordResponse struct { + baseResponse + Data *struct { + Id string `json:"id"` + } `json:"data,omitempty"` +} + +type UpdateRecordRequest struct { + Id string `json:"id"` + GroupId *string `json:"groupId,omitempty"` + LineId *string `json:"lineId,omitempty"` + Type *int32 `json:"type,omitempty"` + Host *string `json:"host,omitempty"` + Data *string `json:"data,omitempty"` + Ttl *int32 `json:"ttl,omitempty"` + Weight *int32 `json:"weight,omitempty"` + Preference *int32 `json:"preference,omitempty"` +} + +type UpdateRecordResponse struct { + baseResponse +} + +type DeleteRecordRequest struct { + Id string `json:"-"` +} + +type DeleteRecordResponse struct { + baseResponse +} diff --git a/ui/public/imgs/providers/dnsla.svg b/ui/public/imgs/providers/dnsla.svg new file mode 100644 index 00000000..7908049e --- /dev/null +++ b/ui/public/imgs/providers/dnsla.svg @@ -0,0 +1 @@ + diff --git a/ui/src/components/access/AccessForm.tsx b/ui/src/components/access/AccessForm.tsx index 681d80f1..47c6d8c6 100644 --- a/ui/src/components/access/AccessForm.tsx +++ b/ui/src/components/access/AccessForm.tsx @@ -22,6 +22,7 @@ import AccessFormCdnflyConfig from "./AccessFormCdnflyConfig"; import AccessFormCloudflareConfig from "./AccessFormCloudflareConfig"; import AccessFormClouDNSConfig from "./AccessFormClouDNSConfig"; import AccessFormCMCCCloudConfig from "./AccessFormCMCCCloudConfig"; +import AccessFormDNSLAConfig from "./AccessFormDNSLAConfig"; import AccessFormDogeCloudConfig from "./AccessFormDogeCloudConfig"; import AccessFormEdgioConfig from "./AccessFormEdgioConfig"; import AccessFormGcoreConfig from "./AccessFormGcoreConfig"; @@ -124,6 +125,8 @@ const AccessForm = forwardRef(({ className, return ; case ACCESS_PROVIDERS.CMCCCLOUD: return ; + case ACCESS_PROVIDERS.DNSLA: + return ; case ACCESS_PROVIDERS.DOGECLOUD: return ; case ACCESS_PROVIDERS.GCORE: diff --git a/ui/src/components/access/AccessFormDNSLAConfig.tsx b/ui/src/components/access/AccessFormDNSLAConfig.tsx new file mode 100644 index 00000000..df8403ea --- /dev/null +++ b/ui/src/components/access/AccessFormDNSLAConfig.tsx @@ -0,0 +1,76 @@ +import { useTranslation } from "react-i18next"; +import { Form, type FormInstance, Input } from "antd"; +import { createSchemaFieldRule } from "antd-zod"; +import { z } from "zod"; + +import { type AccessConfigForDNSLA } from "@/domain/access"; + +type AccessFormDNSLAConfigFieldValues = Nullish; + +export type AccessFormDNSLAConfigProps = { + form: FormInstance; + formName: string; + disabled?: boolean; + initialValues?: AccessFormDNSLAConfigFieldValues; + onValuesChange?: (values: AccessFormDNSLAConfigFieldValues) => void; +}; + +const initFormModel = (): AccessFormDNSLAConfigFieldValues => { + return { + apiId: "", + apiSecret: "", + }; +}; + +const AccessFormDNSLAConfig = ({ form: formInst, formName, disabled, initialValues, onValuesChange: onValuesChange }: AccessFormDNSLAConfigProps) => { + const { t } = useTranslation(); + + const formSchema = z.object({ + apiId: z + .string() + .min(1, t("access.form.dnsla_api_id.placeholder")) + .max(64, t("common.errmsg.string_max", { max: 64 })) + .trim(), + apiSecret: z + .string() + .min(1, t("access.form.dnsla_api_secret.placeholder")) + .max(64, t("common.errmsg.string_max", { max: 64 })) + .trim(), + }); + const formRule = createSchemaFieldRule(formSchema); + + const handleFormChange = (_: unknown, values: z.infer) => { + onValuesChange?.(values); + }; + + return ( +
+ } + > + + + + } + > + + +
+ ); +}; + +export default AccessFormDNSLAConfig; diff --git a/ui/src/domain/access.ts b/ui/src/domain/access.ts index a1e14d86..d32960ca 100644 --- a/ui/src/domain/access.ts +++ b/ui/src/domain/access.ts @@ -19,6 +19,7 @@ export interface AccessModel extends BaseModel { | AccessConfigForCloudflare | AccessConfigForClouDNS | AccessConfigForCMCCCloud + | AccessConfigForDNSLA | AccessConfigForDogeCloud | AccessConfigForEdgio | AccessConfigForGcore @@ -112,6 +113,11 @@ export type AccessConfigForCMCCCloud = { accessKeySecret: string; }; +export type AccessConfigForDNSLA = { + apiId: string; + apiSecret: string; +}; + export type AccessConfigForDogeCloud = { accessKey: string; secretKey: string; diff --git a/ui/src/domain/provider.ts b/ui/src/domain/provider.ts index 3a806b88..0841f39d 100644 --- a/ui/src/domain/provider.ts +++ b/ui/src/domain/provider.ts @@ -17,6 +17,7 @@ export const ACCESS_PROVIDERS = Object.freeze({ CLOUDFLARE: "cloudflare", CLOUDNS: "cloudns", CMCCCLOUD: "cmcccloud", + DNSLA: "dnsla", DOGECLOUD: "dogecloud", GCORE: "gcore", GNAME: "gname", @@ -91,6 +92,7 @@ export const accessProvidersMap: Maphttps://ecloud.10086.cn/op-help-center/doc/article/49739", + "access.form.dnsla_api_id.label": "DNS.LA API ID", + "access.form.dnsla_api_id.placeholder": "Please enter DNS.LA API ID", + "access.form.dnsla_api_id.tooltip": "For more information, see https://www.dns.la/docs/ApiDoc", + "access.form.dnsla_api_secret.label": "DNS.LA API secret", + "access.form.dnsla_api_secret.placeholder": "Please enter DNS.LA API secret", + "access.form.dnsla_api_secret.tooltip": "For more information, see https://www.dns.la/docs/ApiDoc", "access.form.dogecloud_access_key.label": "Doge Cloud AccessKey", "access.form.dogecloud_access_key.placeholder": "Please enter Doge Cloud AccessKey", "access.form.dogecloud_access_key.tooltip": "For more information, see https://console.dogecloud.com/", diff --git a/ui/src/i18n/locales/zh/nls.access.json b/ui/src/i18n/locales/zh/nls.access.json index cb9befa4..64b034d5 100644 --- a/ui/src/i18n/locales/zh/nls.access.json +++ b/ui/src/i18n/locales/zh/nls.access.json @@ -106,6 +106,12 @@ "access.form.cmcccloud_access_key_secret.label": "移动云 AccessKeySecret", "access.form.cmcccloud_access_key_secret.placeholder": "请输入移动云 AccessKeySecret", "access.form.cmcccloud_access_key_secret.tooltip": "这是什么?请参阅 https://ecloud.10086.cn/op-help-center/doc/article/49739", + "access.form.dnsla_api_id.label": "DNS.LA API ID", + "access.form.dnsla_api_id.placeholder": "请输入 DNS.LA API ID", + "access.form.dnsla_api_id.tooltip": "这是什么?请参阅 https://www.dns.la/docs/ApiDoc", + "access.form.dnsla_api_secret.label": "DNS.LA API 密钥", + "access.form.dnsla_api_secret.placeholder": "请输入 DNS.LA API 密钥", + "access.form.dnsla_api_secret.tooltip": "这是什么?请参阅 https://www.dns.la/docs/ApiDoc", "access.form.dogecloud_access_key.label": "多吉云 AccessKey", "access.form.dogecloud_access_key.placeholder": "请输入多吉云 AccessKey", "access.form.dogecloud_access_key.tooltip": "这是什么?请参阅 https://console.dogecloud.com/", From 97356328be7e075b504bfdd02d091fa98e1c6036 Mon Sep 17 00:00:00 2001 From: Fu Diwei Date: Fri, 21 Feb 2025 17:28:58 +0800 Subject: [PATCH 34/34] refactor: clean code --- internal/pkg/core/logger/builtin.go | 4 ++-- internal/pkg/vendors/baishan-sdk/client.go | 8 +++++--- internal/pkg/vendors/btpanel-sdk/client.go | 8 +++++--- internal/pkg/vendors/cachefly-sdk/client.go | 8 +++++--- internal/pkg/vendors/cdnfly-sdk/client.go | 8 +++++--- internal/pkg/vendors/dnsla-sdk/client.go | 8 +++++--- internal/pkg/vendors/gname-sdk/client.go | 8 +++++--- 7 files changed, 32 insertions(+), 20 deletions(-) diff --git a/internal/pkg/core/logger/builtin.go b/internal/pkg/core/logger/builtin.go index 9787817d..fa8932dc 100644 --- a/internal/pkg/core/logger/builtin.go +++ b/internal/pkg/core/logger/builtin.go @@ -35,8 +35,8 @@ func (l *DefaultLogger) Logt(tag string, data ...any) { reflect.Float32, reflect.Float64: s = fmt.Sprintf("%v", v) default: - jsonData, _ := json.Marshal(v) - s = string(jsonData) + jbytes, _ := json.Marshal(v) + s = string(jbytes) } } diff --git a/internal/pkg/vendors/baishan-sdk/client.go b/internal/pkg/vendors/baishan-sdk/client.go index e52e6af9..44015b62 100644 --- a/internal/pkg/vendors/baishan-sdk/client.go +++ b/internal/pkg/vendors/baishan-sdk/client.go @@ -38,10 +38,12 @@ func (c *Client) sendRequest(method string, path string, params interface{}) (*r qs := make(map[string]string) if params != nil { temp := make(map[string]any) - jsonData, _ := json.Marshal(params) - json.Unmarshal(jsonData, &temp) + jsonb, _ := json.Marshal(params) + json.Unmarshal(jsonb, &temp) for k, v := range temp { - qs[k] = fmt.Sprintf("%v", v) + if v != nil { + qs[k] = fmt.Sprintf("%v", v) + } } } diff --git a/internal/pkg/vendors/btpanel-sdk/client.go b/internal/pkg/vendors/btpanel-sdk/client.go index 8ef38864..67e9fdb1 100644 --- a/internal/pkg/vendors/btpanel-sdk/client.go +++ b/internal/pkg/vendors/btpanel-sdk/client.go @@ -48,10 +48,12 @@ func (c *Client) sendRequest(path string, params interface{}) (*resty.Response, data := make(map[string]any) if params != nil { temp := make(map[string]any) - jsonData, _ := json.Marshal(params) - json.Unmarshal(jsonData, &temp) + jsonb, _ := json.Marshal(params) + json.Unmarshal(jsonb, &temp) for k, v := range temp { - data[k] = v + if v != nil { + data[k] = v + } } } data["request_time"] = timestamp diff --git a/internal/pkg/vendors/cachefly-sdk/client.go b/internal/pkg/vendors/cachefly-sdk/client.go index d74c3698..505aafaf 100644 --- a/internal/pkg/vendors/cachefly-sdk/client.go +++ b/internal/pkg/vendors/cachefly-sdk/client.go @@ -39,10 +39,12 @@ func (c *Client) sendRequest(method string, path string, params interface{}) (*r qs := make(map[string]string) if params != nil { temp := make(map[string]any) - jsonData, _ := json.Marshal(params) - json.Unmarshal(jsonData, &temp) + jsonb, _ := json.Marshal(params) + json.Unmarshal(jsonb, &temp) for k, v := range temp { - qs[k] = fmt.Sprintf("%v", v) + if v != nil { + qs[k] = fmt.Sprintf("%v", v) + } } } diff --git a/internal/pkg/vendors/cdnfly-sdk/client.go b/internal/pkg/vendors/cdnfly-sdk/client.go index 630e156c..7e2e93f4 100644 --- a/internal/pkg/vendors/cdnfly-sdk/client.go +++ b/internal/pkg/vendors/cdnfly-sdk/client.go @@ -45,10 +45,12 @@ func (c *Client) sendRequest(method string, path string, params interface{}) (*r qs := make(map[string]string) if params != nil { temp := make(map[string]any) - jsonData, _ := json.Marshal(params) - json.Unmarshal(jsonData, &temp) + jsonb, _ := json.Marshal(params) + json.Unmarshal(jsonb, &temp) for k, v := range temp { - qs[k] = fmt.Sprintf("%v", v) + if v != nil { + qs[k] = fmt.Sprintf("%v", v) + } } } diff --git a/internal/pkg/vendors/dnsla-sdk/client.go b/internal/pkg/vendors/dnsla-sdk/client.go index 936b634d..60430fa1 100644 --- a/internal/pkg/vendors/dnsla-sdk/client.go +++ b/internal/pkg/vendors/dnsla-sdk/client.go @@ -40,10 +40,12 @@ func (c *Client) sendRequest(method string, path string, params interface{}) (*r qs := make(map[string]string) if params != nil { temp := make(map[string]any) - jsonData, _ := json.Marshal(params) - json.Unmarshal(jsonData, &temp) + jsonb, _ := json.Marshal(params) + json.Unmarshal(jsonb, &temp) for k, v := range temp { - qs[k] = fmt.Sprintf("%v", v) + if v != nil { + qs[k] = fmt.Sprintf("%v", v) + } } } diff --git a/internal/pkg/vendors/gname-sdk/client.go b/internal/pkg/vendors/gname-sdk/client.go index c4225357..8e2a2ba9 100644 --- a/internal/pkg/vendors/gname-sdk/client.go +++ b/internal/pkg/vendors/gname-sdk/client.go @@ -62,10 +62,12 @@ func (c *Client) sendRequest(path string, params interface{}) (*resty.Response, data := make(map[string]string) if params != nil { temp := make(map[string]any) - jsonData, _ := json.Marshal(params) - json.Unmarshal(jsonData, &temp) + jsonb, _ := json.Marshal(params) + json.Unmarshal(jsonb, &temp) for k, v := range temp { - data[k] = fmt.Sprintf("%v", v) + if v != nil { + data[k] = fmt.Sprintf("%v", v) + } } } data["appid"] = c.appId