From 7a663d31cb328ecd447c7d47ed7b4e4372f93ce0 Mon Sep 17 00:00:00 2001 From: Fu Diwei Date: Tue, 20 May 2025 11:32:57 +0800 Subject: [PATCH] feat: new deployment provider: wangsu cdn --- internal/deployer/providers.go | 11 +- internal/domain/provider.go | 2 +- .../providers/wangsu-cdn/wangsu_cdn.go | 104 +++++++++++++ .../providers/wangsu-cdn/wangsu_cdn_test.go | 75 +++++++++ .../providers/wangsu-cdnpro/wangsu_cdnpro.go | 20 +-- internal/pkg/sdk3rd/wangsu/cdn/api.go | 15 ++ internal/pkg/sdk3rd/wangsu/cdn/client.go | 20 +++ internal/pkg/sdk3rd/wangsu/cdn/models.go | 26 ++++ .../workflow/node/DeployNodeConfigForm.tsx | 3 + .../DeployNodeConfigFormWangsuCDNConfig.tsx | 146 ++++++++++++++++++ ui/src/domain/provider.ts | 2 + ui/src/i18n/locales/en/nls.provider.json | 3 +- .../i18n/locales/en/nls.workflow.nodes.json | 7 +- ui/src/i18n/locales/zh/nls.provider.json | 3 +- .../i18n/locales/zh/nls.workflow.nodes.json | 7 +- 15 files changed, 428 insertions(+), 16 deletions(-) create mode 100644 internal/pkg/core/deployer/providers/wangsu-cdn/wangsu_cdn.go create mode 100644 internal/pkg/core/deployer/providers/wangsu-cdn/wangsu_cdn_test.go create mode 100644 internal/pkg/sdk3rd/wangsu/cdn/api.go create mode 100644 internal/pkg/sdk3rd/wangsu/cdn/client.go create mode 100644 internal/pkg/sdk3rd/wangsu/cdn/models.go create mode 100644 ui/src/components/workflow/node/DeployNodeConfigFormWangsuCDNConfig.tsx diff --git a/internal/deployer/providers.go b/internal/deployer/providers.go index 09cda5fe..3f0b2600 100644 --- a/internal/deployer/providers.go +++ b/internal/deployer/providers.go @@ -86,6 +86,7 @@ import ( 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" + pWangsuCDN "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/wangsu-cdn" pWangsuCDNPro "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/wangsu-cdnpro" pWangsuCertificate "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/wangsu-certificate" pWebhook "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/webhook" @@ -1206,7 +1207,7 @@ func createDeployerProvider(options *deployerProviderOptions) (deployer.Deployer } } - case domain.DeploymentProviderTypeWangsuCDNPro, domain.DeploymentProviderTypeWangsuCertificate: + case domain.DeploymentProviderTypeWangsuCDN, domain.DeploymentProviderTypeWangsuCDNPro, domain.DeploymentProviderTypeWangsuCertificate: { access := domain.AccessConfigForWangsu{} if err := maputil.Populate(options.ProviderAccessConfig, &access); err != nil { @@ -1214,6 +1215,14 @@ func createDeployerProvider(options *deployerProviderOptions) (deployer.Deployer } switch options.Provider { + case domain.DeploymentProviderTypeWangsuCDN: + deployer, err := pWangsuCDN.NewDeployer(&pWangsuCDN.DeployerConfig{ + AccessKeyId: access.AccessKeyId, + AccessKeySecret: access.AccessKeySecret, + Domains: sliceutil.Filter(strings.Split(maputil.GetString(options.ProviderServiceConfig, "domains"), ";"), func(s string) bool { return s != "" }), + }) + return deployer, err + case domain.DeploymentProviderTypeWangsuCDNPro: deployer, err := pWangsuCDNPro.NewDeployer(&pWangsuCDNPro.DeployerConfig{ AccessKeyId: access.AccessKeyId, diff --git a/internal/domain/provider.go b/internal/domain/provider.go index c518c3b9..fc2d4124 100644 --- a/internal/domain/provider.go +++ b/internal/domain/provider.go @@ -243,7 +243,7 @@ const ( DeploymentProviderTypeVolcEngineImageX = DeploymentProviderType(AccessProviderTypeVolcEngine + "-imagex") DeploymentProviderTypeVolcEngineLive = DeploymentProviderType(AccessProviderTypeVolcEngine + "-live") DeploymentProviderTypeVolcEngineTOS = DeploymentProviderType(AccessProviderTypeVolcEngine + "-tos") - DeploymentProviderTypeWangsuCDN = DeploymentProviderType(AccessProviderTypeWangsu + "-cdn") // 网宿 CDN(预留) + DeploymentProviderTypeWangsuCDN = DeploymentProviderType(AccessProviderTypeWangsu + "-cdn") DeploymentProviderTypeWangsuCDNPro = DeploymentProviderType(AccessProviderTypeWangsu + "-cdnpro") DeploymentProviderTypeWangsuCertificate = DeploymentProviderType(AccessProviderTypeWangsu + "-certificate") DeploymentProviderTypeWebhook = DeploymentProviderType(AccessProviderTypeWebhook) diff --git a/internal/pkg/core/deployer/providers/wangsu-cdn/wangsu_cdn.go b/internal/pkg/core/deployer/providers/wangsu-cdn/wangsu_cdn.go new file mode 100644 index 00000000..43c65de2 --- /dev/null +++ b/internal/pkg/core/deployer/providers/wangsu-cdn/wangsu_cdn.go @@ -0,0 +1,104 @@ +package wangsucdn + +import ( + "context" + "errors" + "fmt" + "log/slog" + "strconv" + + "github.com/usual2970/certimate/internal/pkg/core/deployer" + "github.com/usual2970/certimate/internal/pkg/core/uploader" + uploadersp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/wangsu-certificate" + wangsusdk "github.com/usual2970/certimate/internal/pkg/sdk3rd/wangsu/cdn" +) + +type DeployerConfig struct { + // 网宿云 AccessKeyId。 + AccessKeyId string `json:"accessKeyId"` + // 网宿云 AccessKeySecret。 + AccessKeySecret string `json:"accessKeySecret"` + // 加速域名数组。 + Domains []string `json:"domains"` +} + +type DeployerProvider struct { + config *DeployerConfig + logger *slog.Logger + sdkClient *wangsusdk.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.AccessKeyId, config.AccessKeySecret) + if err != nil { + return nil, fmt.Errorf("failed to create sdk client: %w", err) + } + + uploader, err := uploadersp.NewUploader(&uploadersp.UploaderConfig{ + AccessKeyId: config.AccessKeyId, + AccessKeySecret: config.AccessKeySecret, + }) + if err != nil { + return nil, fmt.Errorf("failed to create ssl uploader: %w", err) + } + + return &DeployerProvider{ + config: config, + logger: slog.Default(), + sdkClient: client, + sslUploader: uploader, + }, nil +} + +func (d *DeployerProvider) WithLogger(logger *slog.Logger) deployer.Deployer { + if logger == nil { + d.logger = slog.Default() + } else { + 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 { + return nil, fmt.Errorf("failed to upload certificate file: %w", err) + } else { + d.logger.Info("ssl certificate uploaded", slog.Any("result", upres)) + } + + // 批量修改域名证书配置 + // REF: https://www.wangsu.com/document/api-doc/37447 + certId, _ := strconv.ParseInt(upres.CertId, 10, 64) + batchUpdateCertificateConfigReq := &wangsusdk.BatchUpdateCertificateConfigRequest{ + CertificateId: certId, + DomainNames: d.config.Domains, + } + batchUpdateCertificateConfigResp, err := d.sdkClient.BatchUpdateCertificateConfig(batchUpdateCertificateConfigReq) + d.logger.Debug("sdk request 'cdn.BatchUpdateCertificateConfig'", slog.Any("request", batchUpdateCertificateConfigReq), slog.Any("response", batchUpdateCertificateConfigResp)) + if err != nil { + return nil, fmt.Errorf("failed to execute sdk request 'cdn.BatchUpdateCertificateConfig': %w", err) + } + + return &deployer.DeployResult{}, nil +} + +func createSdkClient(accessKeyId, accessKeySecret string) (*wangsusdk.Client, error) { + if accessKeyId == "" { + return nil, errors.New("invalid wangsu access key id") + } + + if accessKeySecret == "" { + return nil, errors.New("invalid wangsu access key secret") + } + + return wangsusdk.NewClient(accessKeyId, accessKeySecret), nil +} diff --git a/internal/pkg/core/deployer/providers/wangsu-cdn/wangsu_cdn_test.go b/internal/pkg/core/deployer/providers/wangsu-cdn/wangsu_cdn_test.go new file mode 100644 index 00000000..99859b85 --- /dev/null +++ b/internal/pkg/core/deployer/providers/wangsu-cdn/wangsu_cdn_test.go @@ -0,0 +1,75 @@ +package wangsucdn_test + +import ( + "context" + "flag" + "fmt" + "os" + "strings" + "testing" + + provider "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/wangsu-cdn" +) + +var ( + fInputCertPath string + fInputKeyPath string + fAccessKeyId string + fAccessKeySecret string + fDomain string +) + +func init() { + argsPrefix := "CERTIMATE_DEPLOYER_WANGSUCDN_" + + 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 ./wangsu_cdn_test.go -args \ + --CERTIMATE_DEPLOYER_WANGSUCDN_INPUTCERTPATH="/path/to/your-input-cert.pem" \ + --CERTIMATE_DEPLOYER_WANGSUCDN_INPUTKEYPATH="/path/to/your-input-key.pem" \ + --CERTIMATE_DEPLOYER_WANGSUCDN_ACCESSKEYID="your-access-key-id" \ + --CERTIMATE_DEPLOYER_WANGSUCDN_ACCESSKEYSECRET="your-access-key-secret" \ + --CERTIMATE_DEPLOYER_WANGSUCDN_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, + Domains: []string{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/wangsu-cdnpro/wangsu_cdnpro.go b/internal/pkg/core/deployer/providers/wangsu-cdnpro/wangsu_cdnpro.go index 436ea5a5..4d5f2e10 100644 --- a/internal/pkg/core/deployer/providers/wangsu-cdnpro/wangsu_cdnpro.go +++ b/internal/pkg/core/deployer/providers/wangsu-cdnpro/wangsu_cdnpro.go @@ -88,9 +88,9 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPEM string, privkeyPE // 查询已部署加速域名的详情 getHostnameDetailResp, err := d.sdkClient.GetHostnameDetail(d.config.Domain) - d.logger.Debug("sdk request 'cdn.GetHostnameDetail'", slog.String("hostname", d.config.Domain), slog.Any("response", getHostnameDetailResp)) + d.logger.Debug("sdk request 'cdnpro.GetHostnameDetail'", slog.String("hostname", d.config.Domain), slog.Any("response", getHostnameDetailResp)) if err != nil { - return nil, fmt.Errorf("failed to execute sdk request 'cdn.GetHostnameDetail': %w", err) + return nil, fmt.Errorf("failed to execute sdk request 'cdnpro.GetHostnameDetail': %w", err) } // 生成网宿云证书参数 @@ -126,9 +126,9 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPEM string, privkeyPE NewVersion: certificateNewVersionInfo, } createCertificateResp, err := d.sdkClient.CreateCertificate(createCertificateReq) - d.logger.Debug("sdk request 'cdn.CreateCertificate'", slog.Any("request", createCertificateReq), slog.Any("response", createCertificateResp)) + d.logger.Debug("sdk request 'cdnpro.CreateCertificate'", slog.Any("request", createCertificateReq), slog.Any("response", createCertificateResp)) if err != nil { - return nil, fmt.Errorf("failed to execute sdk request 'cdn.CreateCertificate': %w", err) + return nil, fmt.Errorf("failed to execute sdk request 'cdnpro.CreateCertificate': %w", err) } wangsuCertUrl = createCertificateResp.CertificateUrl @@ -149,9 +149,9 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPEM string, privkeyPE NewVersion: certificateNewVersionInfo, } updateCertificateResp, err := d.sdkClient.UpdateCertificate(d.config.CertificateId, updateCertificateReq) - d.logger.Debug("sdk request 'cdn.CreateCertificate'", slog.Any("certificateId", d.config.CertificateId), slog.Any("request", updateCertificateReq), slog.Any("response", updateCertificateResp)) + d.logger.Debug("sdk request 'cdnpro.CreateCertificate'", slog.Any("certificateId", d.config.CertificateId), slog.Any("request", updateCertificateReq), slog.Any("response", updateCertificateResp)) if err != nil { - return nil, fmt.Errorf("failed to execute sdk request 'cdn.UpdateCertificate': %w", err) + return nil, fmt.Errorf("failed to execute sdk request 'cdnpro.UpdateCertificate': %w", err) } wangsuCertUrl = updateCertificateResp.CertificateUrl @@ -186,9 +186,9 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPEM string, privkeyPE createDeploymentTaskReq.Webhook = typeutil.ToPtr(d.config.WebhookId) } createDeploymentTaskResp, err := d.sdkClient.CreateDeploymentTask(createDeploymentTaskReq) - d.logger.Debug("sdk request 'cdn.CreateCertificate'", slog.Any("request", createDeploymentTaskReq), slog.Any("response", createDeploymentTaskResp)) + d.logger.Debug("sdk request 'cdnpro.CreateCertificate'", slog.Any("request", createDeploymentTaskReq), slog.Any("response", createDeploymentTaskResp)) if err != nil { - return nil, fmt.Errorf("failed to execute sdk request 'cdn.CreateDeploymentTask': %w", err) + return nil, fmt.Errorf("failed to execute sdk request 'cdnpro.CreateDeploymentTask': %w", err) } // 循环获取部署任务详细信息,等待任务状态变更 @@ -206,9 +206,9 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPEM string, privkeyPE } getDeploymentTaskDetailResp, err := d.sdkClient.GetDeploymentTaskDetail(wangsuTaskId) - d.logger.Info("sdk request 'cdn.GetDeploymentTaskDetail'", slog.Any("taskId", wangsuTaskId), slog.Any("response", getDeploymentTaskDetailResp)) + d.logger.Info("sdk request 'cdnpro.GetDeploymentTaskDetail'", slog.Any("taskId", wangsuTaskId), slog.Any("response", getDeploymentTaskDetailResp)) if err != nil { - return nil, fmt.Errorf("failed to execute sdk request 'cdn.GetDeploymentTaskDetail': %w", err) + return nil, fmt.Errorf("failed to execute sdk request 'cdnpro.GetDeploymentTaskDetail': %w", err) } if getDeploymentTaskDetailResp.Status == "failed" { diff --git a/internal/pkg/sdk3rd/wangsu/cdn/api.go b/internal/pkg/sdk3rd/wangsu/cdn/api.go new file mode 100644 index 00000000..997c05bf --- /dev/null +++ b/internal/pkg/sdk3rd/wangsu/cdn/api.go @@ -0,0 +1,15 @@ +package cdn + +import ( + "net/http" +) + +func (c *Client) BatchUpdateCertificateConfig(req *BatchUpdateCertificateConfigRequest) (*BatchUpdateCertificateConfigResponse, error) { + resp := &BatchUpdateCertificateConfigResponse{} + _, err := c.client.SendRequestWithResult(http.MethodPut, "/api/config/certificate/batch", req, resp) + if err != nil { + return resp, err + } + + return resp, err +} diff --git a/internal/pkg/sdk3rd/wangsu/cdn/client.go b/internal/pkg/sdk3rd/wangsu/cdn/client.go new file mode 100644 index 00000000..ac53e171 --- /dev/null +++ b/internal/pkg/sdk3rd/wangsu/cdn/client.go @@ -0,0 +1,20 @@ +package cdn + +import ( + "time" + + "github.com/usual2970/certimate/internal/pkg/sdk3rd/wangsu/openapi" +) + +type Client struct { + client *openapi.Client +} + +func NewClient(accessKey, secretKey string) *Client { + return &Client{client: openapi.NewClient(accessKey, secretKey)} +} + +func (c *Client) WithTimeout(timeout time.Duration) *Client { + c.client.WithTimeout(timeout) + return c +} diff --git a/internal/pkg/sdk3rd/wangsu/cdn/models.go b/internal/pkg/sdk3rd/wangsu/cdn/models.go new file mode 100644 index 00000000..5bf934af --- /dev/null +++ b/internal/pkg/sdk3rd/wangsu/cdn/models.go @@ -0,0 +1,26 @@ +package cdn + +import ( + "github.com/usual2970/certimate/internal/pkg/sdk3rd/wangsu/openapi" +) + +type baseResponse struct { + RequestId *string `json:"requestId,omitempty"` + Code *string `json:"code,omitempty"` + Message *string `json:"message,omitempty"` +} + +var _ openapi.Result = (*baseResponse)(nil) + +func (r *baseResponse) SetRequestId(requestId string) { + r.RequestId = &requestId +} + +type BatchUpdateCertificateConfigRequest struct { + CertificateId int64 `json:"certificateId" required:"true"` + DomainNames []string `json:"domainNames" required:"true"` +} + +type BatchUpdateCertificateConfigResponse struct { + baseResponse +} diff --git a/ui/src/components/workflow/node/DeployNodeConfigForm.tsx b/ui/src/components/workflow/node/DeployNodeConfigForm.tsx index a46ae1be..67b43e77 100644 --- a/ui/src/components/workflow/node/DeployNodeConfigForm.tsx +++ b/ui/src/components/workflow/node/DeployNodeConfigForm.tsx @@ -91,6 +91,7 @@ import DeployNodeConfigFormVolcEngineDCDNConfig from "./DeployNodeConfigFormVolc import DeployNodeConfigFormVolcEngineImageXConfig from "./DeployNodeConfigFormVolcEngineImageXConfig.tsx"; import DeployNodeConfigFormVolcEngineLiveConfig from "./DeployNodeConfigFormVolcEngineLiveConfig.tsx"; import DeployNodeConfigFormVolcEngineTOSConfig from "./DeployNodeConfigFormVolcEngineTOSConfig.tsx"; +import DeployNodeConfigFormWangsuCDNConfig from "./DeployNodeConfigFormWangsuCDNConfig.tsx"; import DeployNodeConfigFormWangsuCDNProConfig from "./DeployNodeConfigFormWangsuCDNProConfig.tsx"; import DeployNodeConfigFormWangsuCertificateConfig from "./DeployNodeConfigFormWangsuCertificateConfig.tsx"; import DeployNodeConfigFormWebhookConfig from "./DeployNodeConfigFormWebhookConfig.tsx"; @@ -334,6 +335,8 @@ const DeployNodeConfigForm = forwardRef; case DEPLOYMENT_PROVIDERS.VOLCENGINE_TOS: return ; + case DEPLOYMENT_PROVIDERS.WANGSU_CDN: + return ; case DEPLOYMENT_PROVIDERS.WANGSU_CDNPRO: return ; case DEPLOYMENT_PROVIDERS.WANGSU_CERTIFICATE: diff --git a/ui/src/components/workflow/node/DeployNodeConfigFormWangsuCDNConfig.tsx b/ui/src/components/workflow/node/DeployNodeConfigFormWangsuCDNConfig.tsx new file mode 100644 index 00000000..57d0d381 --- /dev/null +++ b/ui/src/components/workflow/node/DeployNodeConfigFormWangsuCDNConfig.tsx @@ -0,0 +1,146 @@ +import { memo } from "react"; +import { useTranslation } from "react-i18next"; +import { FormOutlined as FormOutlinedIcon } from "@ant-design/icons"; +import { Button, Form, type FormInstance, Input, Space } from "antd"; +import { createSchemaFieldRule } from "antd-zod"; +import { z } from "zod"; + +import ModalForm from "@/components/ModalForm"; +import MultipleInput from "@/components/MultipleInput"; +import { useAntdForm } from "@/hooks"; +import { validDomainName } from "@/utils/validators"; + +type DeployNodeConfigFormWangsuCDNConfigFieldValues = Nullish<{ + domains: string; +}>; + +export type DeployNodeConfigFormWangsuCDNConfigProps = { + form: FormInstance; + formName: string; + disabled?: boolean; + initialValues?: DeployNodeConfigFormWangsuCDNConfigFieldValues; + onValuesChange?: (values: DeployNodeConfigFormWangsuCDNConfigFieldValues) => void; +}; + +const MULTIPLE_INPUT_DELIMITER = ";"; + +const initFormModel = (): DeployNodeConfigFormWangsuCDNConfigFieldValues => { + return { + domains: "", + }; +}; + +const DeployNodeConfigFormWangsuCDNConfig = ({ + form: formInst, + formName, + disabled, + initialValues, + onValuesChange, +}: DeployNodeConfigFormWangsuCDNConfigProps) => { + const { t } = useTranslation(); + + const formSchema = z.object({ + domains: z + .string() + .nullish() + .refine((v) => { + if (!v) return false; + return String(v) + .split(MULTIPLE_INPUT_DELIMITER) + .every((e) => validDomainName(e)); + }, t("workflow_node.deploy.form.wangsu_cdn_domains.placeholder")), + }); + const formRule = createSchemaFieldRule(formSchema); + + const fieldDomains = Form.useWatch("domains", formInst); + + const handleFormChange = (_: unknown, values: z.infer) => { + onValuesChange?.(values); + }; + + return ( +
+ } + > + + + { + formInst.setFieldValue("domains", e.target.value); + }} + onClear={() => { + formInst.setFieldValue("domains", ""); + }} + /> + + + + + } + onChange={(value) => { + formInst.setFieldValue("domains", value); + }} + /> + + +
+ ); +}; + +const SiteNamesModalInput = memo(({ value, trigger, onChange }: { value?: string; trigger?: React.ReactNode; onChange?: (value: string) => void }) => { + const { t } = useTranslation(); + + const formSchema = z.object({ + domains: z.array(z.string()).refine((v) => { + return v.every((e) => validDomainName(e)); + }, t("workflow_node.deploy.form.wangsu_cdn_domains.errmsg.invalid")), + }); + const formRule = createSchemaFieldRule(formSchema); + const { form: formInst, formProps } = useAntdForm({ + name: "workflowNodeDeployConfigFormWangsuCDNNamesModalInput", + initialValues: { domains: value?.split(MULTIPLE_INPUT_DELIMITER) }, + onSubmit: (values) => { + onChange?.( + values.domains + .map((e) => e.trim()) + .filter((e) => !!e) + .join(MULTIPLE_INPUT_DELIMITER) + ); + }, + }); + + return ( + + + + + + ); +}); + +export default DeployNodeConfigFormWangsuCDNConfig; diff --git a/ui/src/domain/provider.ts b/ui/src/domain/provider.ts index e679d13b..1c80910e 100644 --- a/ui/src/domain/provider.ts +++ b/ui/src/domain/provider.ts @@ -424,6 +424,7 @@ export const DEPLOYMENT_PROVIDERS = Object.freeze({ VOLCENGINE_IMAGEX: `${ACCESS_PROVIDERS.VOLCENGINE}-imagex`, VOLCENGINE_LIVE: `${ACCESS_PROVIDERS.VOLCENGINE}-live`, VOLCENGINE_TOS: `${ACCESS_PROVIDERS.VOLCENGINE}-tos`, + WANGSU_CDN: `${ACCESS_PROVIDERS.WANGSU}-cdn`, WANGSU_CDNPRO: `${ACCESS_PROVIDERS.WANGSU}-cdnpro`, WANGSU_CERTIFICATE: `${ACCESS_PROVIDERS.WANGSU}-certificate`, WEBHOOK: `${ACCESS_PROVIDERS.WEBHOOK}`, @@ -520,6 +521,7 @@ export const deploymentProvidersMap: Maphttps://console.volcengine.com/tos", + "workflow_node.deploy.form.wangsu_cdn_domains.label": "Wangsu Cloud CDN domains", + "workflow_node.deploy.form.wangsu_cdn_domains.placeholder": "Please enter Wangsu Cloud CDN domain names (separated by semicolons)", + "workflow_node.deploy.form.wangsu_cdn_domains.tooltip": "For more information, see https://cdn.console.wangsu.com/v2/index/#/property/list", + "workflow_node.deploy.form.wangsu_cdn_domains.multiple_input_modal.title": "Change Wangsu Cloud CDN domains", + "workflow_node.deploy.form.wangsu_cdn_domains.multiple_input_modal.placeholder": "Please enter Wangsu Cloud CDN domain", "workflow_node.deploy.form.wangsu_cdnpro_environment.label": "Wangsu Cloud environment", "workflow_node.deploy.form.wangsu_cdnpro_environment.placeholder": "Please select Wangsu Cloud environment", "workflow_node.deploy.form.wangsu_cdnpro_environment.option.production.label": "Production environment", @@ -770,7 +775,7 @@ "workflow_node.deploy.form.wangsu_cdnpro_webhook_id.tooltip": "For more information, see https://cdnpro.console.wangsu.com/v2/index/#/certificate", "workflow_node.deploy.form.wangsu_certificate_id.label": "Wangsu Cloud certificate ID (Optional)", "workflow_node.deploy.form.wangsu_certificate_id.placeholder": "Please enter Wangsu Cloud certificate ID", - "workflow_node.deploy.form.wangsu_certificate_id.tooltip": "For more information, see https://cdn.console.wangsu.com/v2/index#/certificate/list?code=cert_mylist&parentCode=cert_ssl&productCode=certificatemanagement", + "workflow_node.deploy.form.wangsu_certificate_id.tooltip": "For more information, see https://cdn.console.wangsu.com/v2/index#/certificate/list", "workflow_node.deploy.form.webhook_data.label": "Webhook data (Optional)", "workflow_node.deploy.form.webhook_data.placeholder": "Please enter Webhook data to override the default value", "workflow_node.deploy.form.webhook_data.tooltip": "Leave it blank to use the default Webhook data provided by the authorization.", diff --git a/ui/src/i18n/locales/zh/nls.provider.json b/ui/src/i18n/locales/zh/nls.provider.json index 8c1be41a..d69b1e38 100644 --- a/ui/src/i18n/locales/zh/nls.provider.json +++ b/ui/src/i18n/locales/zh/nls.provider.json @@ -145,7 +145,8 @@ "provider.volcengine.live": "火山引擎 - 视频直播 Live", "provider.volcengine.tos": "火山引擎 - 对象存储 TOS", "provider.wangsu": "网宿云", - "provider.wangsu.cdnpro": "网宿云 - CDN Pro", + "provider.wangsu.cdn": "网宿云 - 内容分发网络 CDN", + "provider.wangsu.cdnpro": "网宿云 - CDN Pro (CDN 360)", "provider.wangsu.certificate_upload": "网宿云 - 上传到证书管理", "provider.webhook": "Webhook", "provider.wecombot": "企业微信群机器人", diff --git a/ui/src/i18n/locales/zh/nls.workflow.nodes.json b/ui/src/i18n/locales/zh/nls.workflow.nodes.json index ada4ec22..13d21eed 100644 --- a/ui/src/i18n/locales/zh/nls.workflow.nodes.json +++ b/ui/src/i18n/locales/zh/nls.workflow.nodes.json @@ -754,6 +754,11 @@ "workflow_node.deploy.form.volcengine_tos_domain.label": "火山引擎 TOS 自定义域名", "workflow_node.deploy.form.volcengine_tos_domain.placeholder": "请输入火山引擎 TOS 自定义域名", "workflow_node.deploy.form.volcengine_tos_domain.tooltip": "这是什么?请参阅 see https://console.volcengine.com/tos", + "workflow_node.deploy.form.wangsu_cdn_domains.label": "网宿云 CDN 加速域名", + "workflow_node.deploy.form.wangsu_cdn_domains.placeholder": "请输入网宿云 CDN 加速域名(多个值请用半角分号隔开)", + "workflow_node.deploy.form.wangsu_cdn_domains.tooltip": "这是什么?请参阅 https://cdn.console.wangsu.com/v2/index/#/property/list", + "workflow_node.deploy.form.wangsu_cdn_domains.multiple_input_modal.title": "修改网宿云 CDN 加速域名", + "workflow_node.deploy.form.wangsu_cdn_domains.multiple_input_modal.placeholder": "请输入网宿云 CDN 加速域名", "workflow_node.deploy.form.wangsu_cdnpro_environment.label": "网宿云环境", "workflow_node.deploy.form.wangsu_cdnpro_environment.placeholder": "请选择网宿云环境", "workflow_node.deploy.form.wangsu_cdnpro_environment.option.production.label": "生产环境", @@ -769,7 +774,7 @@ "workflow_node.deploy.form.wangsu_cdnpro_webhook_id.tooltip": "这是什么?请参阅 https://cdnpro.console.wangsu.com/v2/index/#/certificate", "workflow_node.deploy.form.wangsu_certificate_id.label": "网宿云证书 ID(可选)", "workflow_node.deploy.form.wangsu_certificate_id.placeholder": "请输入网宿云证书 ID", - "workflow_node.deploy.form.wangsu_certificate_id.tooltip": "这是什么?请参阅 https://cdn.console.wangsu.com/v2/index#/certificate/list?code=cert_mylist&parentCode=cert_ssl&productCode=certificatemanagement

不填写时,将上传新证书;否则,将替换原证书。", + "workflow_node.deploy.form.wangsu_certificate_id.tooltip": "这是什么?请参阅 https://cdn.console.wangsu.com/v2/index#/certificate/list

不填写时,将上传新证书;否则,将替换原证书。", "workflow_node.deploy.form.webhook_data.label": "Webhook 回调数据(可选)", "workflow_node.deploy.form.webhook_data.placeholder": "请输入 Webhook 回调数据以覆盖默认值", "workflow_node.deploy.form.webhook_data.tooltip": "不填写时,将使用所选部署目标授权的默认 Webhook 回调数据。",