diff --git a/internal/deployer/providers.go b/internal/deployer/providers.go index 23d89370..73b620be 100644 --- a/internal/deployer/providers.go +++ b/internal/deployer/providers.go @@ -27,6 +27,7 @@ import ( providerTencentCloudECDN "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/tencentcloud-ecdn" providerTencentCloudEO "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/tencentcloud-eo" providerVolcEngineCDN "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/volcengine-cdn" + providerVolcEngineDCDN "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/volcengine-dcdn" providerVolcEngineLive "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/volcengine-live" providerWebhook "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/webhook" "github.com/usual2970/certimate/internal/pkg/core/logger" @@ -330,7 +331,7 @@ func createDeployer(options *deployerOptions) (deployer.Deployer, logger.Logger, } } - case domain.DeployProviderTypeVolcEngineCDN, domain.DeployProviderTypeVolcEngineLive: + case domain.DeployProviderTypeVolcEngineCDN, domain.DeployProviderTypeVolcEngineDCDN, domain.DeployProviderTypeVolcEngineLive: { access := domain.AccessConfigForVolcEngine{} if err := maps.Decode(options.ProviderAccessConfig, &access); err != nil { @@ -346,6 +347,14 @@ func createDeployer(options *deployerOptions) (deployer.Deployer, logger.Logger, }, logger) return deployer, logger, err + case domain.DeployProviderTypeVolcEngineDCDN: + deployer, err := providerVolcEngineDCDN.NewWithLogger(&providerVolcEngineDCDN.VolcEngineDCDNDeployerConfig{ + AccessKeyId: access.AccessKeyId, + AccessKeySecret: access.SecretAccessKey, + 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 0c07e458..b19caab2 100644 --- a/internal/domain/provider.go +++ b/internal/domain/provider.go @@ -89,6 +89,7 @@ const ( DeployProviderTypeTencentCloudECDN = DeployProviderType("tencentcloud-ecdn") DeployProviderTypeTencentCloudEO = DeployProviderType("tencentcloud-eo") DeployProviderTypeVolcEngineCDN = DeployProviderType("volcengine-cdn") + DeployProviderTypeVolcEngineDCDN = DeployProviderType("volcengine-dcdn") DeployProviderTypeVolcEngineLive = DeployProviderType("volcengine-live") DeployProviderTypeWebhook = DeployProviderType("webhook") ) diff --git a/internal/pkg/core/deployer/providers/volcengine-dcdn/volcengine_dcdn.go b/internal/pkg/core/deployer/providers/volcengine-dcdn/volcengine_dcdn.go new file mode 100644 index 00000000..de314283 --- /dev/null +++ b/internal/pkg/core/deployer/providers/volcengine-dcdn/volcengine_dcdn.go @@ -0,0 +1,117 @@ +package volcenginecdn + +import ( + "context" + "errors" + "strings" + + xerrors "github.com/pkg/errors" + veDcdn "github.com/volcengine/volcengine-go-sdk/service/dcdn" + ve "github.com/volcengine/volcengine-go-sdk/volcengine" + veSession "github.com/volcengine/volcengine-go-sdk/volcengine/session" + + "github.com/usual2970/certimate/internal/pkg/core/deployer" + "github.com/usual2970/certimate/internal/pkg/core/logger" + "github.com/usual2970/certimate/internal/pkg/core/uploader" + providerCertCenter "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/volcengine-certcenter" +) + +type VolcEngineDCDNDeployerConfig struct { + // 火山引擎 AccessKeyId。 + AccessKeyId string `json:"accessKeyId"` + // 火山引擎 AccessKeySecret。 + AccessKeySecret string `json:"accessKeySecret"` + // 火山引擎区域。 + Region string `json:"region"` + // 加速域名(支持泛域名)。 + Domain string `json:"domain"` +} + +type VolcEngineDCDNDeployer struct { + config *VolcEngineDCDNDeployerConfig + logger logger.Logger + sdkClient *veDcdn.DCDN + sslUploader uploader.Uploader +} + +var _ deployer.Deployer = (*VolcEngineDCDNDeployer)(nil) + +func New(config *VolcEngineDCDNDeployerConfig) (*VolcEngineDCDNDeployer, error) { + return NewWithLogger(config, logger.NewNilLogger()) +} + +func NewWithLogger(config *VolcEngineDCDNDeployerConfig, logger logger.Logger) (*VolcEngineDCDNDeployer, 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 := providerCertCenter.New(&providerCertCenter.VolcEngineCertCenterUploaderConfig{ + AccessKeyId: config.AccessKeyId, + AccessKeySecret: config.AccessKeySecret, + Region: config.Region, + }) + if err != nil { + return nil, xerrors.Wrap(err, "failed to create ssl uploader") + } + + return &VolcEngineDCDNDeployer{ + logger: logger, + config: config, + sdkClient: client, + sslUploader: uploader, + }, nil +} + +func (d *VolcEngineDCDNDeployer) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { + // 上传证书到证书中心 + 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) + + // "*.example.com" → ".example.com",适配火山引擎 DCDN 要求的泛域名格式 + domain := strings.TrimPrefix(d.config.Domain, "*") + + // 绑定证书 + // REF: https://www.volcengine.com/docs/6559/1250189 + createCertBindReq := &veDcdn.CreateCertBindInput{ + CertSource: ve.String("volc"), + CertId: ve.String(upres.CertId), + DomainNames: ve.StringSlice([]string{domain}), + } + createCertBindResp, err := d.sdkClient.CreateCertBind(createCertBindReq) + if err != nil { + return nil, xerrors.Wrap(err, "failed to execute sdk request 'dcdn.CreateCertBind'") + } else { + d.logger.Logt("已绑定证书", createCertBindResp) + } + + return &deployer.DeployResult{}, nil +} + +func createSdkClient(accessKeyId, accessKeySecret, region string) (*veDcdn.DCDN, error) { + if region == "" { + region = "cn-beijing" + } + + config := ve.NewConfig().WithRegion(region).WithAkSk(accessKeyId, accessKeySecret) + + session, err := veSession.NewSession(config) + if err != nil { + return nil, err + } + + client := veDcdn.New(session) + return client, 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 new file mode 100644 index 00000000..c81df7c4 --- /dev/null +++ b/internal/pkg/core/deployer/providers/volcengine-dcdn/volcengine_dcdn_test.go @@ -0,0 +1,75 @@ +package volcenginecdn_test + +import ( + "context" + "flag" + "fmt" + "os" + "strings" + "testing" + + provider "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/volcengine-dcdn" +) + +var ( + fInputCertPath string + fInputKeyPath string + fAccessKeyId string + fAccessKeySecret string + fDomain string +) + +func init() { + argsPrefix := "CERTIMATE_DEPLOYER_VOLCENGINEDCDN_" + + 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 ./volcengine_dcdn_test.go -args \ + --CERTIMATE_DEPLOYER_VOLCENGINEDCDN_INPUTCERTPATH="/path/to/your-input-cert.pem" \ + --CERTIMATE_DEPLOYER_VOLCENGINEDCDN_INPUTKEYPATH="/path/to/your-input-key.pem" \ + --CERTIMATE_DEPLOYER_VOLCENGINEDCDN_ACCESSKEYID="your-access-key-id" \ + --CERTIMATE_DEPLOYER_VOLCENGINEDCDN_ACCESSKEYSECRET="your-access-key-secret" \ + --CERTIMATE_DEPLOYER_VOLCENGINEDCDN_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.New(&provider.VolcEngineDCDNDeployerConfig{ + 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/huaweicloud-elb/huaweicloud_elb.go b/internal/pkg/core/uploader/providers/huaweicloud-elb/huaweicloud_elb.go index d8ea91c6..6cc667a4 100644 --- a/internal/pkg/core/uploader/providers/huaweicloud-elb/huaweicloud_elb.go +++ b/internal/pkg/core/uploader/providers/huaweicloud-elb/huaweicloud_elb.go @@ -48,7 +48,7 @@ func New(config *HuaweiCloudELBUploaderConfig) (*HuaweiCloudELBUploader, error) config.Region, ) if err != nil { - return nil, xerrors.Wrap(err, "failed to create sdk client: %w") + return nil, xerrors.Wrap(err, "failed to create sdk client") } return &HuaweiCloudELBUploader{ 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 d984e727..a0e0e56e 100644 --- a/internal/pkg/core/uploader/providers/volcengine-certcenter/volcengine_certcenter.go +++ b/internal/pkg/core/uploader/providers/volcengine-certcenter/volcengine_certcenter.go @@ -35,7 +35,7 @@ func New(config *VolcEngineCertCenterUploaderConfig) (*VolcEngineCertCenterUploa client, err := createSdkClient(config.AccessKeyId, config.AccessKeySecret, config.Region) if err != nil { - return nil, xerrors.Wrap(err, "failed to create sdk client: %w") + return nil, xerrors.Wrap(err, "failed to create sdk client") } return &VolcEngineCertCenterUploader{ diff --git a/ui/src/components/workflow/node/ApplyNode.tsx b/ui/src/components/workflow/node/ApplyNode.tsx index 9cb45aa4..556188d9 100644 --- a/ui/src/components/workflow/node/ApplyNode.tsx +++ b/ui/src/components/workflow/node/ApplyNode.tsx @@ -5,7 +5,6 @@ import { produce } from "immer"; import { type WorkflowNodeConfigForApply, WorkflowNodeType } from "@/domain/workflow"; import { useZustandShallowSelector } from "@/hooks"; -import { useAccessesStore } from "@/stores/access"; import { useContactEmailsStore } from "@/stores/contact"; import { useWorkflowStore } from "@/stores/workflow"; diff --git a/ui/src/components/workflow/node/DeployNodeConfigForm.tsx b/ui/src/components/workflow/node/DeployNodeConfigForm.tsx index 272e5f18..4824975b 100644 --- a/ui/src/components/workflow/node/DeployNodeConfigForm.tsx +++ b/ui/src/components/workflow/node/DeployNodeConfigForm.tsx @@ -36,6 +36,7 @@ import DeployNodeConfigFormTencentCloudCOSConfig from "./DeployNodeConfigFormTen import DeployNodeConfigFormTencentCloudECDNConfig from "./DeployNodeConfigFormTencentCloudECDNConfig.tsx"; import DeployNodeConfigFormTencentCloudEOConfig from "./DeployNodeConfigFormTencentCloudEOConfig.tsx"; import DeployNodeConfigFormVolcEngineCDNConfig from "./DeployNodeConfigFormVolcEngineCDNConfig.tsx"; +import DeployNodeConfigFormVolcEngineDCDNConfig from "./DeployNodeConfigFormVolcEngineDCDNConfig.tsx"; import DeployNodeConfigFormVolcEngineLiveConfig from "./DeployNodeConfigFormVolcEngineLiveConfig.tsx"; import DeployNodeConfigFormWebhookConfig from "./DeployNodeConfigFormWebhookConfig.tsx"; @@ -149,6 +150,8 @@ const DeployNodeConfigForm = forwardRef; case DEPLOY_PROVIDERS.VOLCENGINE_CDN: return ; + case DEPLOY_PROVIDERS.VOLCENGINE_DCDN: + return ; case DEPLOY_PROVIDERS.VOLCENGINE_LIVE: return ; case DEPLOY_PROVIDERS.WEBHOOK: diff --git a/ui/src/components/workflow/node/DeployNodeConfigFormVolcEngineDCDNConfig.tsx b/ui/src/components/workflow/node/DeployNodeConfigFormVolcEngineDCDNConfig.tsx new file mode 100644 index 00000000..0d430e1e --- /dev/null +++ b/ui/src/components/workflow/node/DeployNodeConfigFormVolcEngineDCDNConfig.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 DeployNodeConfigFormVolcEngineDCDNConfigFieldValues = Nullish<{ + domain: string; +}>; + +export type DeployNodeConfigFormVolcEngineDCDNConfigProps = { + form: FormInstance; + formName: string; + disabled?: boolean; + initialValues?: DeployNodeConfigFormVolcEngineDCDNConfigFieldValues; + onValuesChange?: (values: DeployNodeConfigFormVolcEngineDCDNConfigFieldValues) => void; +}; + +const initFormModel = (): DeployNodeConfigFormVolcEngineDCDNConfigFieldValues => { + return {}; +}; + +const DeployNodeConfigFormVolcEngineDCDNConfig = ({ + form: formInst, + formName, + disabled, + initialValues, + onValuesChange, +}: DeployNodeConfigFormVolcEngineDCDNConfigProps) => { + const { t } = useTranslation(); + + const formSchema = z.object({ + domain: z + .string({ message: t("workflow_node.deploy.form.volcengine_dcdn_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 DeployNodeConfigFormVolcEngineDCDNConfig; diff --git a/ui/src/domain/provider.ts b/ui/src/domain/provider.ts index 4a0dc560..91b93c7b 100644 --- a/ui/src/domain/provider.ts +++ b/ui/src/domain/provider.ts @@ -163,6 +163,7 @@ export const DEPLOY_PROVIDERS = Object.freeze({ TENCENTCLOUD_ECDN: `${ACCESS_PROVIDERS.TENCENTCLOUD}-ecdn`, TENCENTCLOUD_EO: `${ACCESS_PROVIDERS.TENCENTCLOUD}-eo`, VOLCENGINE_CDN: `${ACCESS_PROVIDERS.VOLCENGINE}-cdn`, + VOLCENGINE_DCDN: `${ACCESS_PROVIDERS.VOLCENGINE}-dcdn`, VOLCENGINE_LIVE: `${ACCESS_PROVIDERS.VOLCENGINE}-live`, WEBHOOK: `${ACCESS_PROVIDERS.WEBHOOK}`, } as const); @@ -201,6 +202,7 @@ export const deployProvidersMap: Maphttps://console.volcengine.com/cdn/homepage", + "workflow_node.deploy.form.volcengine_dcdn_domain.label": "VolcEngine DCDN domain", + "workflow_node.deploy.form.volcengine_dcdn_domain.placeholder": "Please enter VolcEngine DCDN domain name", + "workflow_node.deploy.form.volcengine_dcdn_domain.tooltip": "For more information, see https://console.volcengine.com/dcdn/dashboard", "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.common.json b/ui/src/i18n/locales/zh/nls.common.json index 9ba8cbea..c3d17318 100644 --- a/ui/src/i18n/locales/zh/nls.common.json +++ b/ui/src/i18n/locales/zh/nls.common.json @@ -76,6 +76,7 @@ "common.provider.tencentcloud.eo": "腾讯云 - 边缘安全加速平台 EdgeOne", "common.provider.volcengine": "火山引擎", "common.provider.volcengine.cdn": "火山引擎 - 内容分发网络 CDN", + "common.provider.volcengine.dcdn": "火山引擎 - 全站加速 DCDN", "common.provider.volcengine.dns": "火山引擎 - 云解析 DNS", "common.provider.volcengine.live": "火山引擎 - 视频直播 Live", "common.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 6ede2b58..43e4963d 100644 --- a/ui/src/i18n/locales/zh/nls.workflow.nodes.json +++ b/ui/src/i18n/locales/zh/nls.workflow.nodes.json @@ -101,10 +101,10 @@ "workflow_node.deploy.form.aliyun_clb_listener_id.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", + "workflow_node.deploy.form.aliyun_cdn_domain.tooltip": "这是什么?请参阅 https://cdn.console.aliyun.com

泛域名表示形式为:*.example.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", + "workflow_node.deploy.form.aliyun_dcdn_domain.tooltip": "这是什么?请参阅 https://dcdn.console.aliyun.com

泛域名表示形式为:*.example.com", "workflow_node.deploy.form.aliyun_nlb_resource_type.label": "证书替换方式", "workflow_node.deploy.form.aliyun_nlb_resource_type.placeholder": "请选择证书替换方式", "workflow_node.deploy.form.aliyun_nlb_resource_type.option.loadbalancer.label": "替换指定负载均衡器下的全部 HTTPS/QUIC 监听的证书", @@ -129,10 +129,10 @@ "workflow_node.deploy.form.aliyun_oss_domain.tooltip": "这是什么?请参阅 see https://oss.console.aliyun.com", "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.baiducloud_cdn_domain.tooltip": "这是什么?请参阅 https://console.bce.baidu.com/cdn

泛域名表示形式为:*.example.com", "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.byteplus_cdn_domain.tooltip": "这是什么?请参阅 https://console.byteplus.com/cdn

泛域名表示形式为:*.example.com", "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", @@ -212,7 +212,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://kubernetes.io/zh-cn/docs/concepts/configuration/secret/", + "workflow_node.deploy.form.qiniu_cdn_domain.tooltip": "这是什么?请参阅 https://kubernetes.io/zh-cn/docs/concepts/configuration/secret/

泛域名表示形式为:*.example.com", "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)", @@ -246,7 +246,7 @@ "workflow_node.deploy.form.ssh_preset_scripts.option.reload_nginx.label": "POSIX Bash - 重启 nginx 进程", "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_cdn_domain.tooltip": "这是什么?请参阅 https://console.cloud.tencent.com/cdn

泛域名表示形式为:*.example.com", "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 服务部署到云资源实例", @@ -279,7 +279,7 @@ "workflow_node.deploy.form.tencentcloud_cos_domain.tooltip": "这是什么?请参阅 see https://console.cloud.tencent.com/cos", "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_ecdn_domain.tooltip": "这是什么?请参阅 https://console.cloud.tencent.com/cdn

泛域名表示形式为:*.example.com", "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", @@ -288,10 +288,13 @@ "workflow_node.deploy.form.tencentcloud_eo_domain.tooltip": "这是什么?请参阅 https://console.cloud.tencent.com/edgeone", "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_cdn_domain.tooltip": "这是什么?请参阅 https://console.volcengine.com/cdn/homepage

泛域名表示形式为:*.example.com", + "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_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_live_domain.tooltip": "这是什么?请参阅 https://console.volcengine.com/live

泛域名表示形式为:*.example.com", "workflow_node.deploy.form.webhook_data.label": "Webhook 回调数据(JSON 格式)", "workflow_node.deploy.form.webhook_data.placeholder": "请输入 Webhook 回调数据", "workflow_node.deploy.form.webhook_data.guide": "小贴士:回调数据是一个 JSON 格式的键值对。其中值支持模板变量,将在被发送到指定的 Webhook URL 时被替换为实际值;其他内容将保持原样。

支持的变量:
${DOMAIN}:证书的主域名(即 CommonName
${DOMAINS}:证书的多域名列表(即 SubjectAltNames
${CERTIFICATE}:证书文件 PEM 格式内容
${PRIVATE_KEY}:私钥文件 PEM 格式内容",