diff --git a/go.mod b/go.mod index a567360f..7c710d35 100644 --- a/go.mod +++ b/go.mod @@ -12,7 +12,6 @@ require ( github.com/alibabacloud-go/nlb-20220430/v2 v2.0.3 github.com/alibabacloud-go/slb-20140515/v4 v4.0.9 github.com/alibabacloud-go/tea v1.2.2 - github.com/alibabacloud-go/tea-utils/v2 v2.0.6 github.com/aliyun/aliyun-oss-go-sdk v3.0.2+incompatible github.com/go-acme/lego/v4 v4.19.2 github.com/gojek/heimdall/v7 v7.0.3 @@ -25,7 +24,8 @@ require ( github.com/pocketbase/pocketbase v0.22.18 github.com/qiniu/go-sdk/v7 v7.22.0 github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cdn v1.0.1017 - github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1030 + github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/clb v1.0.1031 + github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1031 github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/ssl v1.0.992 github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/teo v1.0.1030 golang.org/x/crypto v0.28.0 @@ -41,6 +41,7 @@ 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-utils/v2 v2.0.6 // indirect github.com/aws/aws-sdk-go-v2/service/route53 v1.43.2 // indirect github.com/blinkbean/dingtalk v1.1.3 // indirect github.com/emicklei/go-restful/v3 v3.11.0 // indirect @@ -141,7 +142,7 @@ require ( github.com/ncruces/go-strftime v0.1.9 // indirect github.com/nrdcg/namesilo v0.2.1 // indirect github.com/opentracing/opentracing-go v1.2.1-0.20220228012449-10b1cf09e00b // indirect - github.com/pkg/errors v0.9.1 // indirect + github.com/pkg/errors v0.9.1 github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/spf13/cast v1.6.0 // indirect github.com/spf13/cobra v1.8.1 // indirect diff --git a/go.sum b/go.sum index 08ae184b..d93ba3da 100644 --- a/go.sum +++ b/go.sum @@ -204,8 +204,6 @@ github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHk github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= github.com/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv5E= github.com/fxamacker/cbor/v2 v2.7.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ= -github.com/gabriel-vasile/mimetype v1.4.4 h1:QjV6pZ7/XZ7ryI2KuyeEDE8wnh7fHP9YnQy+R0LnH8I= -github.com/gabriel-vasile/mimetype v1.4.4/go.mod h1:JwLei5XPtWdGiMFB5Pjle1oEeoSeEuJfJE+TtfvdB/s= github.com/gabriel-vasile/mimetype v1.4.6 h1:3+PzJTKLkvgjeTbts6msPJt4DixhT4YtFNf1gtGe3zc= github.com/gabriel-vasile/mimetype v1.4.6/go.mod h1:JX1qVKqZd40hUPpAfiNTe0Sne7hdfKSbOqqmkq8GCXc= github.com/gammazero/toposort v0.1.1/go.mod h1:H2cozTnNpMw0hg2VHAYsAxmkHXBYroNangj2NTBQDvw= @@ -460,11 +458,14 @@ github.com/technoweenie/multipartstreamer v1.0.1 h1:XRztA5MXiR1TIRHxH2uNxXxaIkKQ github.com/technoweenie/multipartstreamer v1.0.1/go.mod h1:jNVxdtShOxzAsukZwTSw6MDx5eUJoiEBsSvzDU9uzog= github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cdn v1.0.1017 h1:OymmfmyFkvHirY3WHsoRT3cdTEsqygLbMn8jM41erK4= github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cdn v1.0.1017/go.mod h1:gnLxGXlLmF+jDqWR1/RVoF/UUwxQxomQhkc0oN7KeuI= +github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/clb v1.0.1031 h1:/eVMCl+jadCex6HxNN6/hFbC0iWl+e8s4PSIcI8aqS4= +github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/clb v1.0.1031/go.mod h1:8Km0fRIaDS7PssuyxDFvRRFBUFmECqG+ICpViCs/Vak= github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.992/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0= github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1002/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0= github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1017/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0= -github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1030 h1:kwiUoCkooUgy7iPyhEEbio7WT21kGJUeZ5JeJfb/dYk= github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1030/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0= +github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1031 h1:3ouglYKE5cwhx2vwICGeW7pAlwyCLnpQd7O0l3hCSTg= +github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1031/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0= github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/dnspod v1.0.1002 h1:QwE0dRkAAbdf+eACnkNULgDn9ZKUJpPWRyXdqJolP5E= github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/dnspod v1.0.1002/go.mod h1:WdC0FYbqYhJwQ3kbqri6hVP5HAEp+rzX9FToItTAzUg= github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/ssl v1.0.992 h1:A6O89OlCJQUpNxGqC/E5By04UNKBryIt5olQIGOx8mg= diff --git a/internal/deployer/huaweicloud_cdn.go b/internal/deployer/huaweicloud_cdn.go index ff7b4328..3406b65a 100644 --- a/internal/deployer/huaweicloud_cdn.go +++ b/internal/deployer/huaweicloud_cdn.go @@ -4,7 +4,6 @@ import ( "context" "encoding/json" "fmt" - "time" "github.com/huaweicloud/huaweicloud-sdk-go-v3/core/auth/global" hcCdn "github.com/huaweicloud/huaweicloud-sdk-go-v3/services/cdn/v2" @@ -67,6 +66,14 @@ func (d *HuaweiCloudCDNDeployer) GetInfos() []string { } func (d *HuaweiCloudCDNDeployer) Deploy(ctx context.Context) error { + // 上传证书到 SCM + upres, err := d.sslUploader.Upload(ctx, d.option.Certificate.Certificate, d.option.Certificate.PrivateKey) + if err != nil { + return err + } + + d.infos = append(d.infos, toStr("已上传证书", upres)) + // 查询加速域名配置 // REF: https://support.huaweicloud.com/api-cdn/ShowDomainFullConfig.html showDomainFullConfigReq := &hcCdnModel.ShowDomainFullConfigRequest{ @@ -85,24 +92,9 @@ func (d *HuaweiCloudCDNDeployer) Deploy(ctx context.Context) error { updateDomainMultiCertificatesReqBodyContent := &hcCdnEx.UpdateDomainMultiCertificatesExRequestBodyContent{} updateDomainMultiCertificatesReqBodyContent.DomainName = d.option.DeployConfig.GetConfigAsString("domain") updateDomainMultiCertificatesReqBodyContent.HttpsSwitch = 1 - if d.option.DeployConfig.GetConfigAsBool("useSCM") { - // 上传证书到 SCM - upres, err := d.sslUploader.Upload(ctx, d.option.Certificate.Certificate, d.option.Certificate.PrivateKey) - if err != nil { - return err - } - - d.infos = append(d.infos, toStr("已上传证书", upres)) - - updateDomainMultiCertificatesReqBodyContent.CertificateType = cast.Int32Ptr(2) - updateDomainMultiCertificatesReqBodyContent.SCMCertificateId = cast.StringPtr(upres.CertId) - updateDomainMultiCertificatesReqBodyContent.CertName = cast.StringPtr(upres.CertName) - } else { - updateDomainMultiCertificatesReqBodyContent.CertificateType = cast.Int32Ptr(0) - updateDomainMultiCertificatesReqBodyContent.CertName = cast.StringPtr(fmt.Sprintf("certimate-%d", time.Now().UnixMilli())) - updateDomainMultiCertificatesReqBodyContent.Certificate = cast.StringPtr(d.option.Certificate.Certificate) - updateDomainMultiCertificatesReqBodyContent.PrivateKey = cast.StringPtr(d.option.Certificate.PrivateKey) - } + updateDomainMultiCertificatesReqBodyContent.CertificateType = cast.Int32Ptr(2) + updateDomainMultiCertificatesReqBodyContent.SCMCertificateId = cast.StringPtr(upres.CertId) + updateDomainMultiCertificatesReqBodyContent.CertName = cast.StringPtr(upres.CertName) updateDomainMultiCertificatesReqBodyContent = updateDomainMultiCertificatesReqBodyContent.MergeConfig(showDomainFullConfigResp.Configs) updateDomainMultiCertificatesReq := &hcCdnEx.UpdateDomainMultiCertificatesExRequest{ Body: &hcCdnEx.UpdateDomainMultiCertificatesExRequestBody{ diff --git a/internal/deployer/huaweicloud_elb.go b/internal/deployer/huaweicloud_elb.go index 05b94956..e813610f 100644 --- a/internal/deployer/huaweicloud_elb.go +++ b/internal/deployer/huaweicloud_elb.go @@ -268,7 +268,7 @@ func (d *HuaweiCloudELBDeployer) deployToLoadbalancer(ctx context.Context) error // 批量更新监听器证书 var errs []error for _, hcListenerId := range hcListenerIds { - if err := d.updateListenerCertificate(ctx, hcListenerId, upres.CertId); err != nil { + if err := d.modifyListenerCertificate(ctx, hcListenerId, upres.CertId); err != nil { errs = append(errs, err) } } @@ -294,14 +294,14 @@ func (d *HuaweiCloudELBDeployer) deployToListener(ctx context.Context) error { d.infos = append(d.infos, toStr("已上传证书", upres)) // 更新监听器证书 - if err := d.updateListenerCertificate(ctx, hcListenerId, upres.CertId); err != nil { + if err := d.modifyListenerCertificate(ctx, hcListenerId, upres.CertId); err != nil { return err } return nil } -func (d *HuaweiCloudELBDeployer) updateListenerCertificate(ctx context.Context, hcListenerId string, hcCertId string) error { +func (d *HuaweiCloudELBDeployer) modifyListenerCertificate(ctx context.Context, hcListenerId string, hcCertId string) error { // 查询监听器详情 // REF: https://support.huaweicloud.com/api-elb/ShowListener.html showListenerReq := &hcElbModel.ShowListenerRequest{ diff --git a/internal/deployer/tencent_clb.go b/internal/deployer/tencent_clb.go index e773a346..51b2bfb1 100644 --- a/internal/deployer/tencent_clb.go +++ b/internal/deployer/tencent_clb.go @@ -7,6 +7,7 @@ import ( "fmt" xerrors "github.com/pkg/errors" + tcClb "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/clb/v20180317" "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common" "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common/profile" tcSsl "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/ssl/v20191205" @@ -25,6 +26,7 @@ type TencentCLBDeployer struct { type tencentCLBDeployerSdkClients struct { ssl *tcSsl.Client + clb *tcClb.Client } func NewTencentCLBDeployer(option *DeployerOption) (Deployer, error) { @@ -69,10 +71,30 @@ func (d *TencentCLBDeployer) GetInfos() []string { func (d *TencentCLBDeployer) Deploy(ctx context.Context) error { // TODO: 直接部署方式 - // 通过 SSL 服务部署到云资源实例 - err := d.deployToInstanceUseSsl(ctx) - if err != nil { - return err + switch d.option.DeployConfig.GetConfigAsString("resourceType") { + case "ssl-deploy": + // 通过 SSL 服务部署到云资源实例 + err := d.deployToInstanceUseSsl(ctx) + if err != nil { + return err + } + case "loadbalancer": + // 部署到指定负载均衡器 + if err := d.deployToLoadbalancer(ctx); err != nil { + return err + } + case "listener": + // 部署到指定监听器 + if err := d.deployToListener(ctx); err != nil { + return err + } + case "ruledomain": + // 部署到指定七层监听转发规则域名 + if err := d.deployToRuleDomain(ctx); err != nil { + return err + } + default: + return errors.New("unsupported resource type") } return nil @@ -86,14 +108,20 @@ func (d *TencentCLBDeployer) createSdkClients(secretId, secretKey, region string return nil, err } + clbClient, err := tcClb.NewClient(credential, region, profile.NewClientProfile()) + if err != nil { + return nil, err + } + return &tencentCLBDeployerSdkClients{ ssl: sslClient, + clb: clbClient, }, nil } func (d *TencentCLBDeployer) deployToInstanceUseSsl(ctx context.Context) error { - tcLoadbalancerId := d.option.DeployConfig.GetConfigAsString("clbId") - tcListenerId := d.option.DeployConfig.GetConfigAsString("lsnId") + tcLoadbalancerId := d.option.DeployConfig.GetConfigAsString("loadbalancerId") + tcListenerId := d.option.DeployConfig.GetConfigAsString("listenerId") tcDomain := d.option.DeployConfig.GetConfigAsString("domain") if tcLoadbalancerId == "" { return errors.New("`loadbalancerId` is required") @@ -132,3 +160,170 @@ func (d *TencentCLBDeployer) deployToInstanceUseSsl(ctx context.Context) error { return nil } + +func (d *TencentCLBDeployer) deployToLoadbalancer(ctx context.Context) error { + tcLoadbalancerId := d.option.DeployConfig.GetConfigAsString("loadbalancerId") + tcListenerIds := make([]string, 0) + if tcLoadbalancerId == "" { + return errors.New("`loadbalancerId` is required") + } + + // 查询负载均衡器详细信息 + // REF: https://cloud.tencent.com/document/api/214/46916 + describeLoadBalancersDetailReq := tcClb.NewDescribeLoadBalancersDetailRequest() + describeLoadBalancersDetailResp, err := d.sdkClients.clb.DescribeLoadBalancersDetail(describeLoadBalancersDetailReq) + if err != nil { + return xerrors.Wrap(err, "failed to execute sdk request 'clb.DescribeLoadBalancersDetail'") + } + + d.infos = append(d.infos, toStr("已查询到负载均衡详细信息", describeLoadBalancersDetailResp)) + + // 查询监听器列表 + // REF: https://cloud.tencent.com/document/api/214/30686 + describeListenersReq := tcClb.NewDescribeListenersRequest() + describeListenersReq.LoadBalancerId = common.StringPtr(tcLoadbalancerId) + describeListenersResp, err := d.sdkClients.clb.DescribeListeners(describeListenersReq) + if err != nil { + return xerrors.Wrap(err, "failed to execute sdk request 'clb.DescribeListeners'") + } else { + if describeListenersResp.Response.Listeners != nil { + for _, listener := range describeListenersResp.Response.Listeners { + if listener.Protocol == nil || (*listener.Protocol != "HTTPS" && *listener.Protocol != "TCP_SSL" && *listener.Protocol != "QUIC") { + continue + } + + tcListenerIds = append(tcListenerIds, *listener.ListenerId) + } + } + } + + d.infos = append(d.infos, toStr("已查询到负载均衡器下的监听器", tcListenerIds)) + + // 上传证书到 SCM + upres, err := d.sslUploader.Upload(ctx, d.option.Certificate.Certificate, d.option.Certificate.PrivateKey) + if err != nil { + return err + } + + d.infos = append(d.infos, toStr("已上传证书", upres)) + + // 批量更新监听器证书 + var errs []error + for _, tcListenerId := range tcListenerIds { + if err := d.modifyListenerCertificate(ctx, tcLoadbalancerId, tcListenerId, upres.CertId); err != nil { + errs = append(errs, err) + } + } + if len(errs) > 0 { + return errors.Join(errs...) + } + + return nil +} + +func (d *TencentCLBDeployer) deployToListener(ctx context.Context) error { + tcLoadbalancerId := d.option.DeployConfig.GetConfigAsString("loadbalancerId") + tcListenerId := d.option.DeployConfig.GetConfigAsString("listenerId") + if tcLoadbalancerId == "" { + return errors.New("`loadbalancerId` is required") + } + if tcListenerId == "" { + return errors.New("`listenerId` is required") + } + + // 上传证书到 SSL + upres, err := d.sslUploader.Upload(ctx, d.option.Certificate.Certificate, d.option.Certificate.PrivateKey) + if err != nil { + return err + } + + d.infos = append(d.infos, toStr("已上传证书", upres)) + + // 更新监听器证书 + if err := d.modifyListenerCertificate(ctx, tcLoadbalancerId, tcListenerId, upres.CertId); err != nil { + return err + } + + return nil +} + +func (d *TencentCLBDeployer) deployToRuleDomain(ctx context.Context) error { + tcLoadbalancerId := d.option.DeployConfig.GetConfigAsString("loadbalancerId") + tcListenerId := d.option.DeployConfig.GetConfigAsString("listenerId") + tcDomain := d.option.DeployConfig.GetConfigAsString("domain") + if tcLoadbalancerId == "" { + return errors.New("`loadbalancerId` is required") + } + if tcListenerId == "" { + return errors.New("`listenerId` is required") + } + if tcDomain == "" { + return errors.New("`domain` is required") + } + + // 上传证书到 SSL + upres, err := d.sslUploader.Upload(ctx, d.option.Certificate.Certificate, d.option.Certificate.PrivateKey) + if err != nil { + return err + } + + d.infos = append(d.infos, toStr("已上传证书", upres)) + + // 修改负载均衡七层监听器转发规则的域名级别属性 + // REF: https://cloud.tencent.com/document/api/214/38092 + modifyDomainAttributesReq := tcClb.NewModifyDomainAttributesRequest() + modifyDomainAttributesReq.LoadBalancerId = common.StringPtr(tcLoadbalancerId) + modifyDomainAttributesReq.ListenerId = common.StringPtr(tcListenerId) + modifyDomainAttributesReq.Domain = common.StringPtr(tcDomain) + modifyDomainAttributesReq.Certificate = &tcClb.CertificateInput{ + SSLMode: common.StringPtr("UNIDIRECTIONAL"), + CertId: common.StringPtr(upres.CertId), + } + modifyDomainAttributesResp, err := d.sdkClients.clb.ModifyDomainAttributes(modifyDomainAttributesReq) + if err != nil { + return xerrors.Wrap(err, "failed to execute sdk request 'clb.ModifyDomainAttributes'") + } + + d.infos = append(d.infos, toStr("已修改七层监听器转发规则的域名级别属性", modifyDomainAttributesResp.Response)) + + return nil +} + +func (d *TencentCLBDeployer) modifyListenerCertificate(ctx context.Context, tcLoadbalancerId, tcListenerId, tcCertId string) error { + // 查询监听器列表 + // REF: https://cloud.tencent.com/document/api/214/30686 + describeListenersReq := tcClb.NewDescribeListenersRequest() + describeListenersReq.LoadBalancerId = common.StringPtr(tcLoadbalancerId) + describeListenersReq.ListenerIds = common.StringPtrs([]string{tcListenerId}) + describeListenersResp, err := d.sdkClients.clb.DescribeListeners(describeListenersReq) + if err != nil { + return xerrors.Wrap(err, "failed to execute sdk request 'clb.DescribeListeners'") + } + if len(describeListenersResp.Response.Listeners) == 0 { + d.infos = append(d.infos, toStr("未找到监听器", nil)) + return errors.New("listener not found") + } + + d.infos = append(d.infos, toStr("已查询到监听器属性", describeListenersResp.Response)) + + // 修改监听器属性 + // REF: https://cloud.tencent.com/document/product/214/30681 + modifyListenerReq := tcClb.NewModifyListenerRequest() + modifyListenerReq.LoadBalancerId = common.StringPtr(tcLoadbalancerId) + modifyListenerReq.ListenerId = common.StringPtr(tcListenerId) + modifyListenerReq.Certificate = &tcClb.CertificateInput{CertId: common.StringPtr(tcCertId)} + if describeListenersResp.Response.Listeners[0].Certificate != nil && describeListenersResp.Response.Listeners[0].Certificate.SSLMode != nil { + modifyListenerReq.Certificate.SSLMode = describeListenersResp.Response.Listeners[0].Certificate.SSLMode + modifyListenerReq.Certificate.CertCaId = describeListenersResp.Response.Listeners[0].Certificate.CertCaId + } else { + modifyListenerReq.Certificate.SSLMode = common.StringPtr("UNIDIRECTIONAL") + } + modifyListenerResp, err := d.sdkClients.clb.ModifyListener(modifyListenerReq) + if err != nil { + return xerrors.Wrap(err, "failed to execute sdk request 'clb.ModifyListener'") + } + + d.infos = append(d.infos, toStr("已修改监听器属性", modifyListenerResp.Response)) + + return nil +} diff --git a/ui/src/components/certimate/DeployToTencentCLB.tsx b/ui/src/components/certimate/DeployToTencentCLB.tsx index 80c6e761..a3828a78 100644 --- a/ui/src/components/certimate/DeployToTencentCLB.tsx +++ b/ui/src/components/certimate/DeployToTencentCLB.tsx @@ -5,106 +5,76 @@ import { produce } from "immer"; import { Input } from "@/components/ui/input"; import { Label } from "@/components/ui/label"; +import { Select, SelectContent, SelectGroup, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"; 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(() => { - const regionResp = regionSchema.safeParse(data.config?.region); - if (!regionResp.success) { - setError({ - ...error, - region: JSON.parse(regionResp.error.message)[0].message, - }); - } else { - setError({ - ...error, - region: "", - }); - } - }, []); + const { deploy: data, setDeploy, error, setError } = useDeployEditContext(); useEffect(() => { if (!data.id) { setDeploy({ ...data, config: { - lsnId: "", - clbId: "", + region: "ap-guangzhou", + resourceType: "", + loadbalancerId: "", + listenerId: "", domain: "", - region: "", }, }); } }, []); - const regionSchema = z.string().regex(/^ap-[a-z]+$/, { - message: t("domain.deployment.form.tencent_clb_region.placeholder"), - }); + useEffect(() => { + setError({}); + }, []); - const domainSchema = z.string().regex(/^$|^(?:\*\.)?([a-zA-Z0-9-]+\.)+[a-zA-Z]{2,}$/, { - message: t("common.errmsg.domain_invalid"), - }); + const formSchema = z + .object({ + region: z.string().min(1, t("domain.deployment.form.tencent_clb_region.placeholder")), + resourceType: z.union([z.literal("ssl-deploy"), z.literal("loadbalancer"), z.literal("listener"), z.literal("ruledomain")], { + message: t("domain.deployment.form.tencent_clb_resource_type.placeholder"), + }), + loadbalancerId: z.string().min(1, t("domain.deployment.form.tencent_clb_loadbalancer_id.placeholder")), + listenerId: z.string().optional(), + domain: z.string().regex(/^$|^(?:\*\.)?([a-zA-Z0-9-]+\.)+[a-zA-Z]{2,}$/, { + message: t("common.errmsg.domain_invalid"), + }), + }) + .refine( + (data) => { + switch (data.resourceType) { + case "ssl-deploy": + case "listener": + case "ruledomain": + return !!data.listenerId?.trim(); + } + return true; + }, + { + message: t("domain.deployment.form.tencent_clb_listener_id.placeholder"), + path: ["listenerId"], + } + ) + .refine((data) => (data.resourceType === "ruledomain" ? !!data.domain?.trim() : true), { + message: t("domain.deployment.form.tencent_clb_ruledomain.placeholder"), + path: ["domain"], + }); - const clbIdSchema = z.string().regex(/^lb-[a-zA-Z0-9]{8}$/, { - message: t("domain.deployment.form.tencent_clb_id.placeholder"), - }); - - const lsnIdSchema = z.string().regex(/^lbl-.{8}$/, { - message: t("domain.deployment.form.tencent_clb_listener.placeholder"), - }); + useEffect(() => { + const res = formSchema.safeParse(data.config); + setError({ + ...error, + region: res.error?.errors?.find((e) => e.path[0] === "region")?.message, + resourceType: res.error?.errors?.find((e) => e.path[0] === "resourceType")?.message, + loadbalancerId: res.error?.errors?.find((e) => e.path[0] === "loadbalancerId")?.message, + listenerId: res.error?.errors?.find((e) => e.path[0] === "listenerId")?.message, + domain: res.error?.errors?.find((e) => e.path[0] === "domain")?.message, + }); + }, [data]); return (