From 0e575a0ce7465875cf4a6b1d226ac0dcdc96140d Mon Sep 17 00:00:00 2001 From: Leo Chen Date: Wed, 23 Oct 2024 17:40:32 +0800 Subject: [PATCH 1/9] rename tencent_cos.go --- internal/deployer/{tencent-cos.go => tencent_cos.go} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename internal/deployer/{tencent-cos.go => tencent_cos.go} (100%) diff --git a/internal/deployer/tencent-cos.go b/internal/deployer/tencent_cos.go similarity index 100% rename from internal/deployer/tencent-cos.go rename to internal/deployer/tencent_cos.go From 4b324e6a227238857a626077c3febd898282083a Mon Sep 17 00:00:00 2001 From: Leo Chen Date: Wed, 23 Oct 2024 18:19:35 +0800 Subject: [PATCH 2/9] fix tencent COS ui --- ui/src/components/certimate/DeployToTencentCOS.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/src/components/certimate/DeployToTencentCOS.tsx b/ui/src/components/certimate/DeployToTencentCOS.tsx index e006fc08..2704ac1c 100644 --- a/ui/src/components/certimate/DeployToTencentCOS.tsx +++ b/ui/src/components/certimate/DeployToTencentCOS.tsx @@ -32,7 +32,7 @@ const DeployToTencentCOS = () => { }, [data]); useEffect(() => { - const bucketResp = bucketSchema.safeParse(data.config?.domain); + const bucketResp = bucketSchema.safeParse(data.config?.bucket); if (!bucketResp.success) { setError({ ...error, From 195aa54cdc9f7ce5045cdac3fdc47bd5eb3595dc Mon Sep 17 00:00:00 2001 From: Leo Chen Date: Wed, 23 Oct 2024 18:21:18 +0800 Subject: [PATCH 3/9] add wildcase domain supported ui label --- ui/src/components/certimate/DeployToQiniuCDN.tsx | 2 +- ui/src/components/certimate/DeployToTencentCDN.tsx | 2 +- ui/src/i18n/locales/en/nls.domain.json | 1 + ui/src/i18n/locales/zh/nls.domain.json | 1 + 4 files changed, 4 insertions(+), 2 deletions(-) diff --git a/ui/src/components/certimate/DeployToQiniuCDN.tsx b/ui/src/components/certimate/DeployToQiniuCDN.tsx index 327edce8..8b8f0509 100644 --- a/ui/src/components/certimate/DeployToQiniuCDN.tsx +++ b/ui/src/components/certimate/DeployToQiniuCDN.tsx @@ -38,7 +38,7 @@ const DeployToQiniuCDN = () => { return (
- + { return (
- + Date: Wed, 23 Oct 2024 18:40:52 +0800 Subject: [PATCH 4/9] fix tencent cos input verify --- .../certimate/DeployToTencentCOS.tsx | 36 +++++++++++++++++-- 1 file changed, 34 insertions(+), 2 deletions(-) diff --git a/ui/src/components/certimate/DeployToTencentCOS.tsx b/ui/src/components/certimate/DeployToTencentCOS.tsx index 2704ac1c..645b9c30 100644 --- a/ui/src/components/certimate/DeployToTencentCOS.tsx +++ b/ui/src/components/certimate/DeployToTencentCOS.tsx @@ -46,6 +46,21 @@ const DeployToTencentCOS = () => { } }, []); + useEffect(() => { + const regionResp = regionSchema.safeParse(data.config?.bucket); + if (!regionResp.success) { + setError({ + ...error, + region: JSON.parse(regionResp.error.message)[0].message, + }); + } else { + setError({ + ...error, + region: "", + }); + } + }, []); + useEffect(() => { if (!data.id) { setDeploy({ @@ -63,10 +78,14 @@ const DeployToTencentCOS = () => { message: t("common.errmsg.domain_invalid"), }); - const bucketSchema = z.string().min(1, { + const regionSchema = z.string().regex(/^ap-[a-z]+$/, { message: t("domain.deployment.form.cos_region.placeholder"), }); + const bucketSchema = z.string().regex(/^.+-\d+$/, { + message: t("domain.deployment.form.cos_bucket.placeholder"), + }); + return (
@@ -78,6 +97,19 @@ const DeployToTencentCOS = () => { onChange={(e) => { const temp = e.target.value; + const resp = bucketSchema.safeParse(temp); + if (!resp.success) { + setError({ + ...error, + region: JSON.parse(resp.error.message)[0].message, + }); + } else { + setError({ + ...error, + region: "", + }); + } + const newData = produce(data, (draft) => { if (!draft.config) { draft.config = {}; @@ -87,7 +119,7 @@ const DeployToTencentCOS = () => { setDeploy(newData); }} /> -
{error?.endpoint}
+
{error?.region}
From d82a9c9253cb14b56dc7591904e31dc5390b5170 Mon Sep 17 00:00:00 2001 From: Leo Chen Date: Wed, 23 Oct 2024 18:45:36 +0800 Subject: [PATCH 5/9] fix tencent cos ui onload verify --- ui/src/components/certimate/DeployToTencentCOS.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/src/components/certimate/DeployToTencentCOS.tsx b/ui/src/components/certimate/DeployToTencentCOS.tsx index 645b9c30..b2f62a56 100644 --- a/ui/src/components/certimate/DeployToTencentCOS.tsx +++ b/ui/src/components/certimate/DeployToTencentCOS.tsx @@ -47,7 +47,7 @@ const DeployToTencentCOS = () => { }, []); useEffect(() => { - const regionResp = regionSchema.safeParse(data.config?.bucket); + const regionResp = regionSchema.safeParse(data.config?.region); if (!regionResp.success) { setError({ ...error, From 7c685646daaa2781f707fd03e3880d326c7128ba Mon Sep 17 00:00:00 2001 From: Leo Chen Date: Wed, 23 Oct 2024 18:48:01 +0800 Subject: [PATCH 6/9] fix tencent cos ui placeholder --- ui/src/components/certimate/DeployToTencentCOS.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/src/components/certimate/DeployToTencentCOS.tsx b/ui/src/components/certimate/DeployToTencentCOS.tsx index b2f62a56..9aae611d 100644 --- a/ui/src/components/certimate/DeployToTencentCOS.tsx +++ b/ui/src/components/certimate/DeployToTencentCOS.tsx @@ -159,7 +159,7 @@ const DeployToTencentCOS = () => {
{ From 7544286b0fe7a24c26ac43c524b7342b6e95b0a4 Mon Sep 17 00:00:00 2001 From: Leo Chen Date: Wed, 23 Oct 2024 18:57:12 +0800 Subject: [PATCH 7/9] add support for tencent CLB MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 新增腾讯云CLB负载均衡配置支持 --- internal/deployer/deployer.go | 3 + internal/deployer/tencent_clb.go | 117 +++++++++++ .../components/certimate/DeployEditDialog.tsx | 4 + .../certimate/DeployToTencentCLB.tsx | 197 ++++++++++++++++++ ui/src/domain/domain.ts | 1 + ui/src/i18n/locales/en/nls.common.json | 1 + ui/src/i18n/locales/en/nls.domain.json | 6 + ui/src/i18n/locales/zh/nls.common.json | 1 + ui/src/i18n/locales/zh/nls.domain.json | 6 + 9 files changed, 336 insertions(+) create mode 100644 internal/deployer/tencent_clb.go create mode 100644 ui/src/components/certimate/DeployToTencentCLB.tsx diff --git a/internal/deployer/deployer.go b/internal/deployer/deployer.go index 9d296065..d7fc67cd 100644 --- a/internal/deployer/deployer.go +++ b/internal/deployer/deployer.go @@ -19,6 +19,7 @@ const ( targetAliyunCDN = "aliyun-cdn" targetAliyunESA = "aliyun-dcdn" targetTencentCDN = "tencent-cdn" + targetTencentCLB = "tencent-clb" targetTencentCOS = "tencent-cos" targetHuaweiCloudCDN = "huaweicloud-cdn" targetQiniuCdn = "qiniu-cdn" @@ -106,6 +107,8 @@ func getWithDeployConfig(record *models.Record, cert *applicant.Certificate, dep return NewAliyunESADeployer(option) case targetTencentCDN: return NewTencentCDNDeployer(option) + case targetTencentCLB: + return NewTencentCLBDeployer(option) case targetTencentCOS: return NewTencentCOSDeployer(option) case targetHuaweiCloudCDN: diff --git a/internal/deployer/tencent_clb.go b/internal/deployer/tencent_clb.go new file mode 100644 index 00000000..4da6c34c --- /dev/null +++ b/internal/deployer/tencent_clb.go @@ -0,0 +1,117 @@ +package deployer + +import ( + "context" + "encoding/json" + "fmt" + + "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common" + "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common/profile" + ssl "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/ssl/v20191205" + + "github.com/usual2970/certimate/internal/domain" + "github.com/usual2970/certimate/internal/utils/rand" +) + +type TencentCLBDeployer struct { + option *DeployerOption + credential *common.Credential + infos []string +} + +func NewTencentCLBDeployer(option *DeployerOption) (Deployer, error) { + access := &domain.TencentAccess{} + if err := json.Unmarshal([]byte(option.Access), access); err != nil { + return nil, fmt.Errorf("failed to unmarshal tencent access: %w", err) + } + + credential := common.NewCredential( + access.SecretId, + access.SecretKey, + ) + + return &TencentCLBDeployer{ + option: option, + credential: credential, + infos: make([]string, 0), + }, nil +} + +func (d *TencentCLBDeployer) GetID() string { + return fmt.Sprintf("%s-%s", d.option.AccessRecord.GetString("name"), d.option.AccessRecord.Id) +} + +func (d *TencentCLBDeployer) GetInfo() []string { + return d.infos +} + +func (d *TencentCLBDeployer) Deploy(ctx context.Context) error { + // 上传证书 + certId, err := d.uploadCert() + if err != nil { + return fmt.Errorf("failed to upload certificate: %w", err) + } + d.infos = append(d.infos, toStr("上传证书", certId)) + + if err := d.deploy(certId); err != nil { + return fmt.Errorf("failed to deploy: %w", err) + } + + return nil +} + +func (d *TencentCLBDeployer) uploadCert() (string, error) { + cpf := profile.NewClientProfile() + cpf.HttpProfile.Endpoint = "ssl.tencentcloudapi.com" + + client, _ := ssl.NewClient(d.credential, "", cpf) + + request := ssl.NewUploadCertificateRequest() + + request.CertificatePublicKey = common.StringPtr(d.option.Certificate.Certificate) + request.CertificatePrivateKey = common.StringPtr(d.option.Certificate.PrivateKey) + request.Alias = common.StringPtr(d.option.Domain + "_" + rand.RandStr(6)) + request.Repeatable = common.BoolPtr(false) + + response, err := client.UploadCertificate(request) + if err != nil { + return "", fmt.Errorf("failed to upload certificate: %w", err) + } + + return *response.Response.CertificateId, nil +} + +func (d *TencentCLBDeployer) deploy(certId string) error { + cpf := profile.NewClientProfile() + cpf.HttpProfile.Endpoint = "ssl.tencentcloudapi.com" + // 实例化要请求产品的client对象,clientProfile是可选的 + client, _ := ssl.NewClient(d.credential, "", cpf) + + // 实例化一个请求对象,每个接口都会对应一个request对象 + request := ssl.NewDeployCertificateInstanceRequest() + + request.CertificateId = common.StringPtr(certId) + request.ResourceType = common.StringPtr("cdn") + request.Status = common.Int64Ptr(1) + + clbId := getDeployString(d.option.DeployConfig, "clbId") + lsnId := getDeployString(d.option.DeployConfig, "lsnId") + domain := getDeployString(d.option.DeployConfig, "domain") + + if(domain == ""){ + // 未开启SNI,只需要精确到监听器 + request.InstanceIdList = common.StringPtrs([]string{fmt.Sprintf("%s|%s", clbId, lsnId)}) + }else{ + // 开启SNI,需要精确到域名,支持泛域名 + request.InstanceIdList = common.StringPtrs([]string{fmt.Sprintf("%s|%s|%s", clbId, lsnId, domain)}) + } + + + // 返回的resp是一个DeployCertificateInstanceResponse的实例,与请求对象对应 + resp, err := client.DeployCertificateInstance(request) + if err != nil { + return fmt.Errorf("failed to deploy certificate: %w", err) + } + d.infos = append(d.infos, toStr("部署证书", resp.Response)) + return nil +} \ No newline at end of file diff --git a/ui/src/components/certimate/DeployEditDialog.tsx b/ui/src/components/certimate/DeployEditDialog.tsx index 54710e49..24149ff5 100644 --- a/ui/src/components/certimate/DeployEditDialog.tsx +++ b/ui/src/components/certimate/DeployEditDialog.tsx @@ -12,6 +12,7 @@ import { Context as DeployEditContext } from "./DeployEdit"; import DeployToAliyunOSS from "./DeployToAliyunOSS"; import DeployToAliyunCDN from "./DeployToAliyunCDN"; import DeployToTencentCDN from "./DeployToTencentCDN"; +import DeployToTencentCLB from "./DeployToTencentCLB"; import DeployToTencentCOS from "./DeployToTencentCOS"; import DeployToHuaweiCloudCDN from "./DeployToHuaweiCloudCDN"; import DeployToQiniuCDN from "./DeployToQiniuCDN"; @@ -119,6 +120,9 @@ const DeployEditDialog = ({ trigger, deployConfig, onSave }: DeployEditDialogPro case "tencent-cdn": childComponent = ; break; + case "tencent-clb": + childComponent = ; + break; case "tencent-cos": childComponent = ; break; diff --git a/ui/src/components/certimate/DeployToTencentCLB.tsx b/ui/src/components/certimate/DeployToTencentCLB.tsx new file mode 100644 index 00000000..1a7a2eb6 --- /dev/null +++ b/ui/src/components/certimate/DeployToTencentCLB.tsx @@ -0,0 +1,197 @@ +import { useEffect } from "react"; +import { useTranslation } from "react-i18next"; +import { z } from "zod"; +import { produce } from "immer"; + +import { Input } from "@/components/ui/input"; +import { Label } from "@/components/ui/label"; +import { useDeployEditContext } from "./DeployEdit"; + +const DeployToTencentCLB = () => { + const { deploy: data, setDeploy, error, setError } = useDeployEditContext(); + + const { t } = useTranslation(); + + useEffect(() => { + setError({}); + }, []); + + useEffect(() => { + const resp = domainSchema.safeParse(data.config?.domain); + if (!resp.success) { + setError({ + ...error, + domain: JSON.parse(resp.error.message)[0].message, + }); + } else { + setError({ + ...error, + domain: "", + }); + } + }, [data]); + + useEffect(() => { + const clbIdresp = clbIdSchema.safeParse(data.config?.clbId); + if (!clbIdresp.success) { + setError({ + ...error, + clbId: JSON.parse(clbIdresp.error.message)[0].message, + }); + } else { + setError({ + ...error, + clbId: "", + }); + } + }, [data]); + + useEffect(() => { + const lsnIdresp = lsnIdSchema.safeParse(data.config?.lsnId); + if (!lsnIdresp.success) { + setError({ + ...error, + lsnId: JSON.parse(lsnIdresp.error.message)[0].message, + }); + } else { + setError({ + ...error, + lsnId: "", + }); + } + }, [data]); + + + useEffect(() => { + if (!data.id) { + setDeploy({ + ...data, + config: { + lsnId: "", + clbId: "", + domain: "", + }, + }); + } + }, []); + + const domainSchema = z.string().regex(/^$|^(?:\*\.)?([a-zA-Z0-9-]+\.)+[a-zA-Z]{2,}$/, { + message: t("common.errmsg.domain_invalid"), + }); + + const clbIdSchema = z.string().regex(/^lb-[a-zA-Z0-9]{8}$/, { + message: t("domain.deployment.form.clb_id.placeholder"), + }); + + const lsnIdSchema = z.string().regex(/^lbl-.{8}$/, { + message: t("domain.deployment.form.clb_listener.placeholder"), + }); + + return ( +
+
+ + { + const temp = e.target.value; + + const resp = clbIdSchema.safeParse(temp); + if (!resp.success) { + setError({ + ...error, + clbId: JSON.parse(resp.error.message)[0].message, + }); + } else { + setError({ + ...error, + clbId: "", + }); + } + + const newData = produce(data, (draft) => { + if (!draft.config) { + draft.config = {}; + } + draft.config.clbId = temp; + }); + setDeploy(newData); + }} + /> +
{error?.clbId}
+
+ +
+ + { + const temp = e.target.value; + + const resp = lsnIdSchema.safeParse(temp); + if (!resp.success) { + setError({ + ...error, + lsnId: JSON.parse(resp.error.message)[0].message, + }); + } else { + setError({ + ...error, + lsnId: "", + }); + } + + const newData = produce(data, (draft) => { + if (!draft.config) { + draft.config = {}; + } + draft.config.lsnId = temp; + }); + setDeploy(newData); + }} + /> +
{error?.lsnId}
+
+ +
+ + { + const temp = e.target.value; + + const resp = domainSchema.safeParse(temp); + if (!resp.success) { + setError({ + ...error, + domain: JSON.parse(resp.error.message)[0].message, + }); + } else { + setError({ + ...error, + domain: "", + }); + } + + const newData = produce(data, (draft) => { + if (!draft.config) { + draft.config = {}; + } + draft.config.domain = temp; + }); + setDeploy(newData); + }} + /> +
{error?.domain}
+
+
+ ); +}; + +export default DeployToTencentCLB; diff --git a/ui/src/domain/domain.ts b/ui/src/domain/domain.ts index 350f89a4..cc67a54d 100644 --- a/ui/src/domain/domain.ts +++ b/ui/src/domain/domain.ts @@ -75,6 +75,7 @@ export const deployTargetsMap: Map = new Map ["aliyun-cdn", "common.provider.aliyun.cdn", "/imgs/providers/aliyun.svg"], ["aliyun-dcdn", "common.provider.aliyun.dcdn", "/imgs/providers/aliyun.svg"], ["tencent-cdn", "common.provider.tencent.cdn", "/imgs/providers/tencent.svg"], + ["tencent-clb", "common.provider.tencent.clb", "/imgs/providers/tencent.svg"], ["tencent-cos", "common.provider.tencent.cos", "/imgs/providers/tencent.svg"], ["huaweicloud-cdn", "common.provider.huaweicloud.cdn", "/imgs/providers/huaweicloud.svg"], ["qiniu-cdn", "common.provider.qiniu.cdn", "/imgs/providers/qiniu.svg"], diff --git a/ui/src/i18n/locales/en/nls.common.json b/ui/src/i18n/locales/en/nls.common.json index d3a17019..0f142747 100644 --- a/ui/src/i18n/locales/en/nls.common.json +++ b/ui/src/i18n/locales/en/nls.common.json @@ -58,6 +58,7 @@ "common.provider.aliyun.dcdn": "Alibaba Cloud - DCDN", "common.provider.tencent": "Tencent", "common.provider.tencent.cdn": "Tencent - CDN", + "common.provider.tencent.clb": "Tencent - CLB", "common.provider.tencent.cos": "Tencent - COS", "common.provider.huaweicloud": "Huawei Cloud", "common.provider.huaweicloud.cdn": "Huawei Cloud - CDN", diff --git a/ui/src/i18n/locales/en/nls.domain.json b/ui/src/i18n/locales/en/nls.domain.json index 15f57284..745ff670 100644 --- a/ui/src/i18n/locales/en/nls.domain.json +++ b/ui/src/i18n/locales/en/nls.domain.json @@ -58,6 +58,12 @@ "domain.deployment.form.cos_region.placeholder": "Please enter region, e.g. ap-guangzhou", "domain.deployment.form.cos_bucket.label": "Bucket", "domain.deployment.form.cos_bucket.placeholder": "Please enter bucket, e.g. example-1250000000", + "domain.deployment.form.clb_id.label": "CLB id", + "domain.deployment.form.clb_id.placeholder": "Please enter CLB id, e.g. lb-xxxxxxxx", + "domain.deployment.form.clb_listener.label": "Listener id", + "domain.deployment.form.clb_listener.placeholder": "Please enter listener id, e.g. lbl-xxxxxxxx", + "domain.deployment.form.clb_domain.label": "Deploy to domain (Wildcard domain is also supported)", + "domain.deployment.form.clb_domain.placeholder": "Please enter domain to be deployed. If SNI is not enabled, you can leave it blank.", "domain.deployment.form.domain.label": "Deploy to domain (Single domain only, not wildcard domain)", "domain.deployment.form.domain.label.wildsupported": "Deploy to domain (Wildcard domain is also supported)", "domain.deployment.form.domain.placeholder": "Please enter domain to be deployed", diff --git a/ui/src/i18n/locales/zh/nls.common.json b/ui/src/i18n/locales/zh/nls.common.json index 212d7b2e..6a27105c 100644 --- a/ui/src/i18n/locales/zh/nls.common.json +++ b/ui/src/i18n/locales/zh/nls.common.json @@ -54,6 +54,7 @@ "common.provider.tencent": "腾讯云", "common.provider.tencent.cdn": "腾讯云 - CDN", + "common.provider.tencent.clb": "腾讯云 - CLB", "common.provider.tencent.cos": "腾讯云 - COS", "common.provider.aliyun": "阿里云", "common.provider.aliyun.oss": "阿里云 - OSS", diff --git a/ui/src/i18n/locales/zh/nls.domain.json b/ui/src/i18n/locales/zh/nls.domain.json index d7dbadbc..b271def7 100644 --- a/ui/src/i18n/locales/zh/nls.domain.json +++ b/ui/src/i18n/locales/zh/nls.domain.json @@ -58,6 +58,12 @@ "domain.deployment.form.cos_region.placeholder": "请输入 region, 如 ap-guangzhou", "domain.deployment.form.cos_bucket.label": "存储桶", "domain.deployment.form.cos_bucket.placeholder": "请输入存储桶名, 如 example-1250000000", + "domain.deployment.form.clb_id.label": "CLB id", + "domain.deployment.form.clb_id.placeholder": "请输入CLB实例id, 如 lb-xxxxxxxx", + "domain.deployment.form.clb_listener.label": "监听器 id", + "domain.deployment.form.clb_listener.placeholder": "请输入监听器id, 如 lbl-xxxxxxxx", + "domain.deployment.form.clb_domain.label": "部署到域名(支持泛域名)", + "domain.deployment.form.clb_domain.placeholder": "请输入部署到的域名, 如未开启SNI, 可置空忽略此项", "domain.deployment.form.domain.label": "部署到域名(仅支持单个域名;不支持泛域名)", "domain.deployment.form.domain.label.wildsupported": "部署到域名(支持泛域名)", "domain.deployment.form.domain.placeholder": "请输入部署到的域名", From 68751517171cb8832b86f9999639899725c07d05 Mon Sep 17 00:00:00 2001 From: Leo Chen Date: Wed, 23 Oct 2024 23:56:22 +0800 Subject: [PATCH 8/9] fix tencent clb deploy failed MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增region参数 - 新增配置说明 --- internal/deployer/tencent_clb.go | 4 +- .../certimate/DeployToTencentCLB.tsx | 54 +++++++++++++++++++ ui/src/i18n/locales/en/nls.domain.json | 4 +- ui/src/i18n/locales/zh/nls.domain.json | 4 +- 4 files changed, 62 insertions(+), 4 deletions(-) diff --git a/internal/deployer/tencent_clb.go b/internal/deployer/tencent_clb.go index 4da6c34c..ba97e840 100644 --- a/internal/deployer/tencent_clb.go +++ b/internal/deployer/tencent_clb.go @@ -85,13 +85,13 @@ func (d *TencentCLBDeployer) deploy(certId string) error { cpf := profile.NewClientProfile() cpf.HttpProfile.Endpoint = "ssl.tencentcloudapi.com" // 实例化要请求产品的client对象,clientProfile是可选的 - client, _ := ssl.NewClient(d.credential, "", cpf) + client, _ := ssl.NewClient(d.credential, getDeployString(d.option.DeployConfig, "region"), cpf) // 实例化一个请求对象,每个接口都会对应一个request对象 request := ssl.NewDeployCertificateInstanceRequest() request.CertificateId = common.StringPtr(certId) - request.ResourceType = common.StringPtr("cdn") + request.ResourceType = common.StringPtr("clb") request.Status = common.Int64Ptr(1) clbId := getDeployString(d.option.DeployConfig, "clbId") diff --git a/ui/src/components/certimate/DeployToTencentCLB.tsx b/ui/src/components/certimate/DeployToTencentCLB.tsx index 1a7a2eb6..ff50b8fe 100644 --- a/ui/src/components/certimate/DeployToTencentCLB.tsx +++ b/ui/src/components/certimate/DeployToTencentCLB.tsx @@ -61,6 +61,21 @@ const DeployToTencentCLB = () => { } }, [data]); + useEffect(() => { + const regionResp = regionSchema.safeParse(data.config?.region); + if (!regionResp.success) { + setError({ + ...error, + region: JSON.parse(regionResp.error.message)[0].message, + }); + } else { + setError({ + ...error, + region: "", + }); + } + }, []); + useEffect(() => { if (!data.id) { @@ -70,11 +85,16 @@ const DeployToTencentCLB = () => { lsnId: "", clbId: "", domain: "", + region: "", }, }); } }, []); + const regionSchema = z.string().regex(/^ap-[a-z]+$/, { + message: t("domain.deployment.form.clb_region.placeholder"), + }); + const domainSchema = z.string().regex(/^$|^(?:\*\.)?([a-zA-Z0-9-]+\.)+[a-zA-Z]{2,}$/, { message: t("common.errmsg.domain_invalid"), }); @@ -89,6 +109,40 @@ const DeployToTencentCLB = () => { return (
+
+ + { + const temp = e.target.value; + + const resp = regionSchema.safeParse(temp); + if (!resp.success) { + setError({ + ...error, + region: JSON.parse(resp.error.message)[0].message, + }); + } else { + setError({ + ...error, + region: "", + }); + } + + const newData = produce(data, (draft) => { + if (!draft.config) { + draft.config = {}; + } + draft.config.region = temp; + }); + setDeploy(newData); + }} + /> +
{error?.region}
+
+
Date: Thu, 24 Oct 2024 00:00:24 +0800 Subject: [PATCH 9/9] update readme for tencent clb support --- README.md | 2 +- README_EN.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 2e36d3a2..bf7ea29c 100644 --- a/README.md +++ b/README.md @@ -74,7 +74,7 @@ make local.run | 服务商 | 支持申请证书 | 支持部署证书 | 备注 | | :--------: | :----------: | :----------: | ------------------------------------------------------------ | | 阿里云 | √ | √ | 可签发在阿里云注册的域名;可部署到阿里云 OSS、CDN | -| 腾讯云 | √ | √ | 可签发在腾讯云注册的域名;可部署到腾讯云 CDN、COS | +| 腾讯云 | √ | √ | 可签发在腾讯云注册的域名;可部署到腾讯云 CDN、COS、CLB | | 华为云 | √ | √ | 可签发在华为云注册的域名;可部署到华为云 CDN | | 七牛云 | | √ | 可部署到七牛云 CDN | | AWS | √ | | 可签发在 AWS Route53 托管的域名 | diff --git a/README_EN.md b/README_EN.md index f6356c86..7cfbec6f 100644 --- a/README_EN.md +++ b/README_EN.md @@ -73,7 +73,7 @@ password:1234567890 | Provider | Registration | Deployment | Remarks | | :-----------: | :----------: | :--------: | ------------------------------------------------------------------------------------------- | | Alibaba Cloud | √ | √ | Supports domains registered on Alibaba Cloud; supports deployment to Alibaba Cloud OSS, CDN | -| Tencent Cloud | √ | √ | Supports domains registered on Tencent Cloud; supports deployment to Tencent Cloud CDN, COS | +| Tencent Cloud | √ | √ | Supports domains registered on Tencent Cloud; supports deployment to Tencent Cloud CDN, COS, CLB | | Huawei Cloud | √ | √ | Supports domains registered on Huawei Cloud; supports deployment to Huawei Cloud CDN | | Qiniu Cloud | | √ | Supports deployment to Qiniu Cloud CDN | | AWS | √ | | Supports domains managed on AWS Route53 |