diff --git a/README.md b/README.md
index 63d7898b..4fe79035 100644
--- a/README.md
+++ b/README.md
@@ -73,7 +73,7 @@ make local.run
| 服务商 | 支持申请证书 | 支持部署证书 | 备注 |
| :--------: | :----------: | :----------: | ------------------------------------------------------------ |
-| 阿里云 | √ | √ | 可签发在阿里云注册的域名;可部署到阿里云 OSS、CDN |
+| 阿里云 | √ | √ | 可签发在阿里云注册的域名;可部署到阿里云 OSS、CDN、CLB(SLB) |
| 腾讯云 | √ | √ | 可签发在腾讯云注册的域名;可部署到腾讯云 COS、CDN、CLB |
| 华为云 | √ | √ | 可签发在华为云注册的域名;可部署到华为云 CDN、ELB |
| 七牛云 | | √ | 可部署到七牛云 CDN |
diff --git a/README_EN.md b/README_EN.md
index 5bb30b38..74cb3098 100644
--- a/README_EN.md
+++ b/README_EN.md
@@ -70,22 +70,22 @@ password:1234567890
## List of Supported Providers
-| 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 COS, CDN, CLB |
-| Huawei Cloud | √ | √ | Supports domains registered on Huawei Cloud; supports deployment to Huawei Cloud CDN, ELB |
-| Qiniu Cloud | | √ | Supports deployment to Qiniu Cloud CDN |
-| AWS | √ | | Supports domains managed on AWS Route53 |
-| CloudFlare | √ | | Supports domains registered on CloudFlare; CloudFlare services come with SSL certificates |
-| GoDaddy | √ | | Supports domains registered on GoDaddy |
-| Namesilo | √ | | Supports domains registered on Namesilo |
-| PowerDNS | √ | | Supports domains managed on PowerDNS |
-| HTTP Request | √ | | Supports domains which allow managing DNS by HTTP request |
-| Local Deploy | | √ | Supports deployment to local servers |
-| SSH | | √ | Supports deployment to SSH servers |
-| Webhook | | √ | Supports callback to Webhook |
-| Kubernetes | | √ | Supports deployment to Kubernetes Secret |
+| Provider | Registration | Deployment | Remarks |
+| :-----------: | :----------: | :--------: | ----------------------------------------------------------------------------------------------------- |
+| Alibaba Cloud | √ | √ | Supports domains registered on Alibaba Cloud; supports deployment to Alibaba Cloud OSS, CDN, CLB(SLB) |
+| Tencent Cloud | √ | √ | Supports domains registered on Tencent Cloud; supports deployment to Tencent Cloud COS, CDN, CLB |
+| Huawei Cloud | √ | √ | Supports domains registered on Huawei Cloud; supports deployment to Huawei Cloud CDN, ELB |
+| Qiniu Cloud | | √ | Supports deployment to Qiniu Cloud CDN |
+| AWS | √ | | Supports domains managed on AWS Route53 |
+| CloudFlare | √ | | Supports domains registered on CloudFlare; CloudFlare services come with SSL certificates |
+| GoDaddy | √ | | Supports domains registered on GoDaddy |
+| Namesilo | √ | | Supports domains registered on Namesilo |
+| PowerDNS | √ | | Supports domains managed on PowerDNS |
+| HTTP Request | √ | | Supports domains which allow managing DNS by HTTP request |
+| Local Deploy | | √ | Supports deployment to local servers |
+| SSH | | √ | Supports deployment to SSH servers |
+| Webhook | | √ | Supports callback to Webhook |
+| Kubernetes | | √ | Supports deployment to Kubernetes Secret |
## Screenshots
diff --git a/internal/deployer/aliyun_clb.go b/internal/deployer/aliyun_clb.go
new file mode 100644
index 00000000..9a0f8789
--- /dev/null
+++ b/internal/deployer/aliyun_clb.go
@@ -0,0 +1,281 @@
+package deployer
+
+import (
+ "context"
+ "encoding/json"
+ "errors"
+ "fmt"
+
+ openapi "github.com/alibabacloud-go/darabonba-openapi/v2/client"
+ slb20140515 "github.com/alibabacloud-go/slb-20140515/v4/client"
+ "github.com/alibabacloud-go/tea/tea"
+
+ "github.com/usual2970/certimate/internal/domain"
+ "github.com/usual2970/certimate/internal/pkg/core/uploader"
+)
+
+type AliyunCLBDeployer struct {
+ option *DeployerOption
+ infos []string
+
+ sdkClient *slb20140515.Client
+ sslUploader uploader.Uploader
+}
+
+func NewAliyunCLBDeployer(option *DeployerOption) (Deployer, error) {
+ access := &domain.AliyunAccess{}
+ json.Unmarshal([]byte(option.Access), access)
+
+ client, err := (&AliyunCLBDeployer{}).createSdkClient(
+ access.AccessKeyId,
+ access.AccessKeySecret,
+ option.DeployConfig.GetConfigAsString("region"),
+ )
+ if err != nil {
+ return nil, err
+ }
+
+ uploader, err := uploader.NewAliyunSLBUploader(&uploader.AliyunSLBUploaderConfig{
+ AccessKeyId: access.AccessKeyId,
+ AccessKeySecret: access.AccessKeySecret,
+ Region: option.DeployConfig.GetConfigAsString("region"),
+ })
+ if err != nil {
+ return nil, err
+ }
+
+ return &AliyunCLBDeployer{
+ option: option,
+ infos: make([]string, 0),
+ sdkClient: client,
+ sslUploader: uploader,
+ }, nil
+}
+
+func (d *AliyunCLBDeployer) GetID() string {
+ return fmt.Sprintf("%s-%s", d.option.AccessRecord.GetString("name"), d.option.AccessRecord.Id)
+}
+
+func (d *AliyunCLBDeployer) GetInfo() []string {
+ return d.infos
+}
+
+func (d *AliyunCLBDeployer) Deploy(ctx context.Context) error {
+ switch d.option.DeployConfig.GetConfigAsString("resourceType") {
+ case "loadbalancer":
+ if err := d.deployToLoadbalancer(ctx); err != nil {
+ return err
+ }
+ case "listener":
+ if err := d.deployToListener(ctx); err != nil {
+ return err
+ }
+ default:
+ return errors.New("unsupported resource type")
+ }
+
+ return nil
+}
+
+func (d *AliyunCLBDeployer) createSdkClient(accessKeyId, accessKeySecret, region string) (*slb20140515.Client, error) {
+ if region == "" {
+ region = "cn-hangzhou" // CLB(SLB) 服务默认区域:华东一杭州
+ }
+
+ aConfig := &openapi.Config{
+ AccessKeyId: tea.String(accessKeyId),
+ AccessKeySecret: tea.String(accessKeySecret),
+ }
+
+ var endpoint string
+ switch region {
+ case "cn-hangzhou":
+ case "cn-hangzhou-finance":
+ case "cn-shanghai-finance-1":
+ case "cn-shenzhen-finance-1":
+ endpoint = "slb.aliyuncs.com"
+ default:
+ endpoint = fmt.Sprintf("slb.%s.aliyuncs.com", region)
+ }
+ aConfig.Endpoint = tea.String(endpoint)
+
+ client, err := slb20140515.NewClient(aConfig)
+ if err != nil {
+ return nil, err
+ }
+
+ return client, nil
+}
+
+func (d *AliyunCLBDeployer) deployToLoadbalancer(ctx context.Context) error {
+ aliLoadbalancerId := d.option.DeployConfig.GetConfigAsString("loadbalancerId")
+ if aliLoadbalancerId == "" {
+ return errors.New("`loadbalancerId` is required")
+ }
+
+ // 查询负载均衡器实例的详细信息
+ // REF: https://help.aliyun.com/zh/slb/classic-load-balancer/developer-reference/api-slb-2014-05-15-describeloadbalancerattribute
+ describeLoadBalancerAttributeReq := &slb20140515.DescribeLoadBalancerAttributeRequest{
+ RegionId: tea.String(d.option.DeployConfig.GetConfigAsString("region")),
+ LoadBalancerId: tea.String(aliLoadbalancerId),
+ }
+ describeLoadBalancerAttributeResp, err := d.sdkClient.DescribeLoadBalancerAttribute(describeLoadBalancerAttributeReq)
+ if err != nil {
+ return fmt.Errorf("failed to execute sdk request 'slb.DescribeLoadBalancerAttribute': %w", err)
+ }
+
+ d.infos = append(d.infos, toStr("已查询到 CLB 负载均衡器实例", describeLoadBalancerAttributeResp))
+
+ // 查询监听列表
+ // REF: https://help.aliyun.com/zh/slb/classic-load-balancer/developer-reference/api-slb-2014-05-15-describeloadbalancerlisteners
+ aliListenerPorts := make([]int32, 0)
+ listListenersPage := 1
+ listListenersLimit := int32(100)
+ var listListenersToken *string = nil
+ for {
+ describeLoadBalancerListenersReq := &slb20140515.DescribeLoadBalancerListenersRequest{
+ RegionId: tea.String(d.option.DeployConfig.GetConfigAsString("region")),
+ MaxResults: tea.Int32(listListenersLimit),
+ NextToken: listListenersToken,
+ LoadBalancerId: []*string{tea.String(aliLoadbalancerId)},
+ ListenerProtocol: tea.String("https"),
+ }
+ describeLoadBalancerListenersResp, err := d.sdkClient.DescribeLoadBalancerListeners(describeLoadBalancerListenersReq)
+ if err != nil {
+ return fmt.Errorf("failed to execute sdk request 'slb.DescribeLoadBalancerListeners': %w", err)
+ }
+
+ if describeLoadBalancerListenersResp.Body.Listeners != nil {
+ for _, listener := range describeLoadBalancerListenersResp.Body.Listeners {
+ aliListenerPorts = append(aliListenerPorts, *listener.ListenerPort)
+ }
+ }
+
+ if describeLoadBalancerListenersResp.Body.NextToken == nil {
+ break
+ } else {
+ listListenersToken = describeLoadBalancerListenersResp.Body.NextToken
+ listListenersPage += 1
+ }
+ }
+
+ d.infos = append(d.infos, toStr("已查询到 ELB 负载均衡器下的监听器", aliListenerPorts))
+
+ // 上传证书到 SLB
+ uploadResult, err := d.sslUploader.Upload(ctx, d.option.Certificate.Certificate, d.option.Certificate.PrivateKey)
+ if err != nil {
+ return err
+ }
+
+ d.infos = append(d.infos, toStr("已上传证书", uploadResult))
+
+ // 批量更新监听证书
+ var errs []error
+ for _, aliListenerPort := range aliListenerPorts {
+ if err := d.updateListenerCertificate(ctx, aliLoadbalancerId, aliListenerPort, uploadResult.CertId); err != nil {
+ errs = append(errs, err)
+ }
+ }
+ if len(errs) > 0 {
+ return errors.Join(errs...)
+ }
+
+ return nil
+}
+
+func (d *AliyunCLBDeployer) deployToListener(ctx context.Context) error {
+ aliLoadbalancerId := d.option.DeployConfig.GetConfigAsString("loadbalancerId")
+ if aliLoadbalancerId == "" {
+ return errors.New("`loadbalancerId` is required")
+ }
+
+ aliListenerPort := d.option.DeployConfig.GetConfigAsInt32("listenerPort")
+ if aliListenerPort == 0 {
+ return errors.New("`listenerPort` is required")
+ }
+
+ // 上传证书到 SLB
+ uploadResult, err := d.sslUploader.Upload(ctx, d.option.Certificate.Certificate, d.option.Certificate.PrivateKey)
+ if err != nil {
+ return err
+ }
+
+ d.infos = append(d.infos, toStr("已上传证书", uploadResult))
+
+ // 更新监听
+ if err := d.updateListenerCertificate(ctx, aliLoadbalancerId, aliListenerPort, uploadResult.CertId); err != nil {
+ return err
+ }
+
+ return nil
+}
+
+func (d *AliyunCLBDeployer) updateListenerCertificate(ctx context.Context, aliLoadbalancerId string, aliListenerPort int32, aliCertId string) error {
+ // 查询监听配置
+ // REF: https://help.aliyun.com/zh/slb/classic-load-balancer/developer-reference/api-slb-2014-05-15-describeloadbalancerhttpslistenerattribute
+ describeLoadBalancerHTTPSListenerAttributeReq := &slb20140515.DescribeLoadBalancerHTTPSListenerAttributeRequest{
+ LoadBalancerId: tea.String(aliLoadbalancerId),
+ ListenerPort: tea.Int32(aliListenerPort),
+ }
+ describeLoadBalancerHTTPSListenerAttributeResp, err := d.sdkClient.DescribeLoadBalancerHTTPSListenerAttribute(describeLoadBalancerHTTPSListenerAttributeReq)
+ if err != nil {
+ return fmt.Errorf("failed to execute sdk request 'slb.DescribeLoadBalancerHTTPSListenerAttribute': %w", err)
+ }
+
+ d.infos = append(d.infos, toStr("已查询到 CLB HTTPS 监听配置", describeLoadBalancerHTTPSListenerAttributeResp))
+
+ // 查询扩展域名
+ // REF: https://help.aliyun.com/zh/slb/classic-load-balancer/developer-reference/api-slb-2014-05-15-describedomainextensions
+ describeDomainExtensionsReq := &slb20140515.DescribeDomainExtensionsRequest{
+ RegionId: tea.String(d.option.DeployConfig.GetConfigAsString("region")),
+ LoadBalancerId: tea.String(aliLoadbalancerId),
+ ListenerPort: tea.Int32(aliListenerPort),
+ }
+ describeDomainExtensionsResp, err := d.sdkClient.DescribeDomainExtensions(describeDomainExtensionsReq)
+ if err != nil {
+ return fmt.Errorf("failed to execute sdk request 'slb.DescribeDomainExtensions': %w", err)
+ }
+
+ d.infos = append(d.infos, toStr("已查询到 CLB 扩展域名", describeDomainExtensionsResp))
+
+ // 遍历修改扩展域名
+ // REF: https://help.aliyun.com/zh/slb/classic-load-balancer/developer-reference/api-slb-2014-05-15-setdomainextensionattribute
+ //
+ // 这里仅修改跟被替换证书一致的扩展域名
+ if describeDomainExtensionsResp.Body.DomainExtensions == nil && describeDomainExtensionsResp.Body.DomainExtensions.DomainExtension == nil {
+ for _, domainExtension := range describeDomainExtensionsResp.Body.DomainExtensions.DomainExtension {
+ if *domainExtension.ServerCertificateId == *describeLoadBalancerHTTPSListenerAttributeResp.Body.ServerCertificateId {
+ break
+ }
+
+ setDomainExtensionAttributeReq := &slb20140515.SetDomainExtensionAttributeRequest{
+ RegionId: tea.String(d.option.DeployConfig.GetConfigAsString("region")),
+ DomainExtensionId: tea.String(*domainExtension.DomainExtensionId),
+ ServerCertificateId: tea.String(aliCertId),
+ }
+ _, err := d.sdkClient.SetDomainExtensionAttribute(setDomainExtensionAttributeReq)
+ if err != nil {
+ return fmt.Errorf("failed to execute sdk request 'slb.SetDomainExtensionAttribute': %w", err)
+ }
+ }
+ }
+
+ // 修改监听配置
+ // REF: https://help.aliyun.com/zh/slb/classic-load-balancer/developer-reference/api-slb-2014-05-15-setloadbalancerhttpslistenerattribute
+ //
+ // 注意修改监听配置要放在修改扩展域名之后
+ setLoadBalancerHTTPSListenerAttributeReq := &slb20140515.SetLoadBalancerHTTPSListenerAttributeRequest{
+ RegionId: tea.String(d.option.DeployConfig.GetConfigAsString("region")),
+ LoadBalancerId: tea.String(aliLoadbalancerId),
+ ListenerPort: tea.Int32(aliListenerPort),
+ ServerCertificateId: tea.String(aliCertId),
+ }
+ setLoadBalancerHTTPSListenerAttributeResp, err := d.sdkClient.SetLoadBalancerHTTPSListenerAttribute(setLoadBalancerHTTPSListenerAttributeReq)
+ if err != nil {
+ return fmt.Errorf("failed to execute sdk request 'slb.SetLoadBalancerHTTPSListenerAttribute': %w", err)
+ }
+
+ d.infos = append(d.infos, toStr("已更新 CLB HTTPS 监听配置", setLoadBalancerHTTPSListenerAttributeResp))
+
+ return nil
+}
diff --git a/internal/deployer/deployer.go b/internal/deployer/deployer.go
index 512fd748..8e130b3b 100644
--- a/internal/deployer/deployer.go
+++ b/internal/deployer/deployer.go
@@ -18,6 +18,7 @@ const (
targetAliyunOSS = "aliyun-oss"
targetAliyunCDN = "aliyun-cdn"
targetAliyunESA = "aliyun-dcdn"
+ targetAliyunCLB = "aliyun-clb"
targetTencentCDN = "tencent-cdn"
targetTencentCLB = "tencent-clb"
targetTencentCOS = "tencent-cos"
@@ -106,6 +107,8 @@ func getWithDeployConfig(record *models.Record, cert *applicant.Certificate, dep
return NewAliyunCDNDeployer(option)
case targetAliyunESA:
return NewAliyunESADeployer(option)
+ case targetAliyunCLB:
+ return NewAliyunCLBDeployer(option)
case targetTencentCDN:
return NewTencentCDNDeployer(option)
case targetTencentCLB:
diff --git a/internal/deployer/huaweicloud_cdn.go b/internal/deployer/huaweicloud_cdn.go
index f7835dcb..ab6e936b 100644
--- a/internal/deployer/huaweicloud_cdn.go
+++ b/internal/deployer/huaweicloud_cdn.go
@@ -41,9 +41,9 @@ func NewHuaweiCloudCDNDeployer(option *DeployerOption) (Deployer, error) {
// TODO: SCM 服务与 DNS 服务所支持的区域可能不一致,这里暂时不传而是使用默认值,仅支持华为云国内版
uploader, err := uploader.NewHuaweiCloudSCMUploader(&uploader.HuaweiCloudSCMUploaderConfig{
- Region: "",
AccessKeyId: access.AccessKeyId,
SecretAccessKey: access.SecretAccessKey,
+ Region: "",
})
if err != nil {
return nil, err
diff --git a/internal/deployer/huaweicloud_elb.go b/internal/deployer/huaweicloud_elb.go
index e9a6f243..fc5920bb 100644
--- a/internal/deployer/huaweicloud_elb.go
+++ b/internal/deployer/huaweicloud_elb.go
@@ -46,9 +46,9 @@ func NewHuaweiCloudELBDeployer(option *DeployerOption) (Deployer, error) {
}
uploader, err := uploader.NewHuaweiCloudELBUploader(&uploader.HuaweiCloudELBUploaderConfig{
- Region: option.DeployConfig.GetConfigAsString("region"),
AccessKeyId: access.AccessKeyId,
SecretAccessKey: access.SecretAccessKey,
+ Region: option.DeployConfig.GetConfigAsString("region"),
})
if err != nil {
return nil, err
@@ -176,10 +176,15 @@ func (u *HuaweiCloudELBDeployer) getSdkProjectId(accessKeyId, secretAccessKey, r
}
func (d *HuaweiCloudELBDeployer) deployToCertificate(ctx context.Context) error {
+ hcCertId := d.option.DeployConfig.GetConfigAsString("certificateId")
+ if hcCertId == "" {
+ return errors.New("`certificateId` is required")
+ }
+
// 更新证书
// REF: https://support.huaweicloud.com/api-elb/UpdateCertificate.html
updateCertificateReq := &hcElbModel.UpdateCertificateRequest{
- CertificateId: d.option.DeployConfig.GetConfigAsString("certificateId"),
+ CertificateId: hcCertId,
Body: &hcElbModel.UpdateCertificateRequestBody{
Certificate: &hcElbModel.UpdateCertificateOption{
Certificate: cast.StringPtr(d.option.Certificate.Certificate),
@@ -198,21 +203,26 @@ func (d *HuaweiCloudELBDeployer) deployToCertificate(ctx context.Context) error
}
func (d *HuaweiCloudELBDeployer) deployToLoadbalancer(ctx context.Context) error {
+ hcLoadbalancerId := d.option.DeployConfig.GetConfigAsString("loadbalancerId")
+ if hcLoadbalancerId == "" {
+ return errors.New("`loadbalancerId` is required")
+ }
+
// 查询负载均衡器详情
// REF: https://support.huaweicloud.com/api-elb/ShowLoadBalancer.html
showLoadBalancerReq := &hcElbModel.ShowLoadBalancerRequest{
- LoadbalancerId: d.option.DeployConfig.GetConfigAsString("loadbalancerId"),
+ LoadbalancerId: hcLoadbalancerId,
}
showLoadBalancerResp, err := d.sdkClient.ShowLoadBalancer(showLoadBalancerReq)
if err != nil {
return fmt.Errorf("failed to execute sdk request 'elb.ShowLoadBalancer': %w", err)
}
- d.infos = append(d.infos, toStr("已查询到到 ELB 负载均衡器", showLoadBalancerResp))
+ d.infos = append(d.infos, toStr("已查询到 ELB 负载均衡器", showLoadBalancerResp))
// 查询监听器列表
// REF: https://support.huaweicloud.com/api-elb/ListListeners.html
- listenerIds := make([]string, 0)
+ hcListenerIds := make([]string, 0)
listListenersLimit := int32(2000)
var listListenersMarker *string = nil
for {
@@ -229,7 +239,7 @@ func (d *HuaweiCloudELBDeployer) deployToLoadbalancer(ctx context.Context) error
if listListenersResp.Listeners != nil {
for _, listener := range *listListenersResp.Listeners {
- listenerIds = append(listenerIds, listener.Id)
+ hcListenerIds = append(hcListenerIds, listener.Id)
}
}
@@ -240,7 +250,7 @@ func (d *HuaweiCloudELBDeployer) deployToLoadbalancer(ctx context.Context) error
}
}
- d.infos = append(d.infos, toStr("已查询到到 ELB 负载均衡器下的监听器", listenerIds))
+ d.infos = append(d.infos, toStr("已查询到 ELB 负载均衡器下的监听器", hcListenerIds))
// 上传证书到 SCM
uploadResult, err := d.sslUploader.Upload(ctx, d.option.Certificate.Certificate, d.option.Certificate.PrivateKey)
@@ -252,8 +262,8 @@ func (d *HuaweiCloudELBDeployer) deployToLoadbalancer(ctx context.Context) error
// 批量更新监听器证书
var errs []error
- for _, listenerId := range listenerIds {
- if err := d.updateListenerCertificate(ctx, listenerId, uploadResult.CertId); err != nil {
+ for _, hcListenerId := range hcListenerIds {
+ if err := d.updateListenerCertificate(ctx, hcListenerId, uploadResult.CertId); err != nil {
errs = append(errs, err)
}
}
@@ -265,6 +275,11 @@ func (d *HuaweiCloudELBDeployer) deployToLoadbalancer(ctx context.Context) error
}
func (d *HuaweiCloudELBDeployer) deployToListener(ctx context.Context) error {
+ hcListenerId := d.option.DeployConfig.GetConfigAsString("listenerId")
+ if hcListenerId == "" {
+ return errors.New("`listenerId` is required")
+ }
+
// 上传证书到 SCM
uploadResult, err := d.sslUploader.Upload(ctx, d.option.Certificate.Certificate, d.option.Certificate.PrivateKey)
if err != nil {
@@ -274,7 +289,7 @@ func (d *HuaweiCloudELBDeployer) deployToListener(ctx context.Context) error {
d.infos = append(d.infos, toStr("已上传证书", uploadResult))
// 更新监听器证书
- if err := d.updateListenerCertificate(ctx, d.option.DeployConfig.GetConfigAsString("listenerId"), uploadResult.CertId); err != nil {
+ if err := d.updateListenerCertificate(ctx, hcListenerId, uploadResult.CertId); err != nil {
return err
}
@@ -292,7 +307,7 @@ func (d *HuaweiCloudELBDeployer) updateListenerCertificate(ctx context.Context,
return fmt.Errorf("failed to execute sdk request 'elb.ShowListener': %w", err)
}
- d.infos = append(d.infos, toStr("已查询到到 ELB 监听器", showListenerResp))
+ d.infos = append(d.infos, toStr("已查询到 ELB 监听器", showListenerResp))
// 更新监听器
// REF: https://support.huaweicloud.com/api-elb/UpdateListener.html
@@ -359,7 +374,7 @@ func (d *HuaweiCloudELBDeployer) updateListenerCertificate(ctx context.Context,
return fmt.Errorf("failed to execute sdk request 'elb.UpdateListener': %w", err)
}
- d.infos = append(d.infos, toStr("已更新监听器", updateListenerResp))
+ d.infos = append(d.infos, toStr("已更新 ELB 监听器", updateListenerResp))
return nil
}
diff --git a/internal/domain/domains.go b/internal/domain/domains.go
index 78acbb3d..bed38ac2 100644
--- a/internal/domain/domains.go
+++ b/internal/domain/domains.go
@@ -18,7 +18,6 @@ type DeployConfig struct {
Config map[string]any `json:"config"`
}
-
// 以字符串形式获取配置项。
//
// 入参:
@@ -52,6 +51,39 @@ func (dc *DeployConfig) GetConfigOrDefaultAsString(key string, defaultValue stri
return defaultValue
}
+// 以 32 位整数形式获取配置项。
+//
+// 入参:
+// - key: 配置项的键。
+//
+// 出参:
+// - 配置项的值。如果配置项不存在或者类型不是 32 位整数,则返回 0。
+func (dc *DeployConfig) GetConfigAsInt32(key string) int32 {
+ return dc.GetConfigOrDefaultAsInt32(key, 0)
+}
+
+// 以 32 位整数形式获取配置项。
+//
+// 入参:
+// - key: 配置项的键。
+// - defaultValue: 默认值。
+//
+// 出参:
+// - 配置项的值。如果配置项不存在或者类型不是 32 位整数,则返回默认值。
+func (dc *DeployConfig) GetConfigOrDefaultAsInt32(key string, defaultValue int32) int32 {
+ if dc.Config == nil {
+ return defaultValue
+ }
+
+ if value, ok := dc.Config[key]; ok {
+ if result, ok := value.(int32); ok {
+ return result
+ }
+ }
+
+ return defaultValue
+}
+
// 以布尔形式获取配置项。
//
// 入参:
diff --git a/ui/src/components/certimate/DeployEditDialog.tsx b/ui/src/components/certimate/DeployEditDialog.tsx
index 7ef5f291..5fdc4ab1 100644
--- a/ui/src/components/certimate/DeployEditDialog.tsx
+++ b/ui/src/components/certimate/DeployEditDialog.tsx
@@ -11,6 +11,7 @@ import AccessEditDialog from "./AccessEditDialog";
import { Context as DeployEditContext } from "./DeployEdit";
import DeployToAliyunOSS from "./DeployToAliyunOSS";
import DeployToAliyunCDN from "./DeployToAliyunCDN";
+import DeployToAliyunCLB from "./DeployToAliyunCLB";
import DeployToTencentCDN from "./DeployToTencentCDN";
import DeployToTencentCLB from "./DeployToTencentCLB";
import DeployToTencentCOS from "./DeployToTencentCOS";
@@ -118,6 +119,9 @@ const DeployEditDialog = ({ trigger, deployConfig, onSave }: DeployEditDialogPro
case "aliyun-dcdn":
childComponent =