mirror of
https://github.com/certimate-go/certimate.git
synced 2026-09-24 23:10:13 +08:00
feat(provider): new deployment provider: cmcccloud vlb
This commit is contained in:
@@ -88,7 +88,8 @@ require (
|
||||
gitlab.ecloud.com/ecloud/ecloudsdkcloudcore v1.0.0
|
||||
gitlab.ecloud.com/ecloud/ecloudsdkclouddns v1.0.1
|
||||
gitlab.ecloud.com/ecloud/ecloudsdkcmcdn v1.0.0
|
||||
gitlab.ecloud.com/ecloud/ecloudsdkcore v1.0.2
|
||||
gitlab.ecloud.com/ecloud/ecloudsdkcore v1.0.6
|
||||
gitlab.ecloud.com/ecloud/ecloudsdkvlb v1.0.7
|
||||
golang.org/x/crypto v0.52.0
|
||||
golang.org/x/oauth2 v0.36.0
|
||||
golang.org/x/sync v0.20.0
|
||||
@@ -297,3 +298,7 @@ replace gitlab.ecloud.com/ecloud/ecloudsdkclouddns v1.0.1 => ./pkg/sdk3rd-forked
|
||||
replace gitlab.ecloud.com/ecloud/ecloudsdkcmcdn v1.0.0 => ./pkg/sdk3rd-forked/gitlab.ecloud.com/ecloud/ecloudsdkcmcdn@v1.0.0
|
||||
|
||||
replace gitlab.ecloud.com/ecloud/ecloudsdkcore v1.0.2 => ./pkg/sdk3rd-forked/gitlab.ecloud.com/ecloud/ecloudsdkcore@v1.0.2
|
||||
|
||||
replace gitlab.ecloud.com/ecloud/ecloudsdkcore v1.0.6 => ./pkg/sdk3rd-forked/gitlab.ecloud.com/ecloud/ecloudsdkcore@v1.0.6
|
||||
|
||||
replace gitlab.ecloud.com/ecloud/ecloudsdkvlb v1.0.7 => ./pkg/sdk3rd-forked/gitlab.ecloud.com/ecloud/ecloudsdkvlb@v1.0.7
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
package deployers
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/certimate-go/certimate/internal/domain"
|
||||
"github.com/certimate-go/certimate/pkg/core"
|
||||
dplyimpl "github.com/certimate-go/certimate/pkg/core/deployer/providers/cmcccloud-vlb"
|
||||
xmaps "github.com/certimate-go/certimate/pkg/utils/maps"
|
||||
)
|
||||
|
||||
func init() {
|
||||
Registries.MustRegister(domain.DeploymentProviderTypeCMCCCloudVLB, func(options *ProviderFactoryOptions) (core.Deployer, error) {
|
||||
credentials := domain.AccessConfigForCMCCCloud{}
|
||||
if err := xmaps.Populate(options.ProviderAccessConfig, &credentials); err != nil {
|
||||
return nil, fmt.Errorf("failed to populate provider access config: %w", err)
|
||||
}
|
||||
|
||||
provider, err := dplyimpl.NewDeployer(&dplyimpl.DeployerConfig{
|
||||
AccessKeyId: credentials.AccessKeyId,
|
||||
AccessKeySecret: credentials.AccessKeySecret,
|
||||
PoolId: xmaps.GetString(options.ProviderExtendedConfig, "poolId"),
|
||||
DeployTarget: xmaps.GetString(options.ProviderExtendedConfig, "deployTarget"),
|
||||
LoadbalancerId: xmaps.GetString(options.ProviderExtendedConfig, "loadbalancerId"),
|
||||
ListenerId: xmaps.GetString(options.ProviderExtendedConfig, "listenerId"),
|
||||
Domain: xmaps.GetString(options.ProviderExtendedConfig, "domain"),
|
||||
})
|
||||
return provider, err
|
||||
})
|
||||
}
|
||||
@@ -358,6 +358,7 @@ const (
|
||||
DeploymentProviderTypeCdnfly = DeploymentProviderType(AccessProviderTypeCdnfly)
|
||||
DeploymentProviderTypeCloudflareSSL = DeploymentProviderType(AccessProviderTypeCloudflare + "-ssl")
|
||||
DeploymentProviderTypeCMCCCloudCDN = DeploymentProviderType(AccessProviderTypeCMCCCloud + "-cdn")
|
||||
DeploymentProviderTypeCMCCCloudVLB = DeploymentProviderType(AccessProviderTypeCMCCCloud + "-vlb")
|
||||
DeploymentProviderTypeCPanel = DeploymentProviderType(AccessProviderTypeCPanel)
|
||||
DeploymentProviderTypeCTCCCloudAO = DeploymentProviderType(AccessProviderTypeCTCCCloud + "-ao")
|
||||
DeploymentProviderTypeCTCCCloudCDN = DeploymentProviderType(AccessProviderTypeCTCCCloud + "-cdn")
|
||||
|
||||
@@ -35,9 +35,9 @@ type Config struct {
|
||||
AccessKey string
|
||||
SecretKey string
|
||||
|
||||
TTL int
|
||||
PropagationTimeout time.Duration
|
||||
PollingInterval time.Duration
|
||||
TTL int
|
||||
ReadTimeout int
|
||||
ConnectTimeout int
|
||||
}
|
||||
@@ -52,11 +52,11 @@ type DNSProvider struct {
|
||||
|
||||
func NewDefaultConfig() *Config {
|
||||
return &Config{
|
||||
ReadTimeout: env.GetOrDefaultInt(EnvReadTimeout, 30),
|
||||
ConnectTimeout: env.GetOrDefaultInt(EnvConnectTimeout, 30),
|
||||
TTL: env.GetOrDefaultInt(EnvTTL, 600),
|
||||
PropagationTimeout: env.GetOrDefaultSecond(EnvPropagationTimeout, 10*time.Minute),
|
||||
PollingInterval: env.GetOrDefaultSecond(EnvPollingInterval, dns01.DefaultPollingInterval),
|
||||
ReadTimeout: env.GetOrDefaultInt(EnvReadTimeout, 30),
|
||||
ConnectTimeout: env.GetOrDefaultInt(EnvConnectTimeout, 30),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -79,10 +79,8 @@ func NewDNSProviderConfig(cfg *Config) (*DNSProvider, error) {
|
||||
}
|
||||
|
||||
client := ecloudsdkclouddns.NewClient(&config.Config{
|
||||
AccessKey: cfg.AccessKey,
|
||||
SecretKey: cfg.SecretKey,
|
||||
// 资源池常量见: https://ecloud.10086.cn/op-help-center/doc/article/54462
|
||||
// 默认全局
|
||||
AccessKey: cfg.AccessKey,
|
||||
SecretKey: cfg.SecretKey,
|
||||
PoolId: "CIDC-CORE-00",
|
||||
ReadTimeOut: cfg.ReadTimeout,
|
||||
ConnectTimeout: cfg.ConnectTimeout,
|
||||
|
||||
@@ -92,7 +92,7 @@ func (c *Certmgr) Upload(ctx context.Context, certPEM, privkeyPEM string) (*Uplo
|
||||
|
||||
// 对比证书内容
|
||||
getCertDetailResp, err := c.sdkClient.GetCertRawData(certItem.CertId)
|
||||
c.logger.Debug("sdk request 'cert.GetCertRawData'", slog.Any("certId", certItem.CertId), slog.Any("response", getCertDetailResp))
|
||||
c.logger.Debug("sdk request 'cert.GetCertRawData'", slog.String("params.certId", certItem.CertId), slog.Any("response", getCertDetailResp))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to execute sdk request 'cert.GetCertRawData': %w", err)
|
||||
} else {
|
||||
|
||||
@@ -0,0 +1,156 @@
|
||||
package cmcccloudvlb
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"log/slog"
|
||||
"time"
|
||||
|
||||
"github.com/samber/lo"
|
||||
"gitlab.ecloud.com/ecloud/ecloudsdkcore/config"
|
||||
"gitlab.ecloud.com/ecloud/ecloudsdkvlb/model"
|
||||
|
||||
"github.com/certimate-go/certimate/pkg/sdk3rd-trimmed/gitlab.ecloud.com/ecloud/ecloudsdkvlb"
|
||||
|
||||
"github.com/certimate-go/certimate/pkg/core"
|
||||
xcert "github.com/certimate-go/certimate/pkg/utils/cert"
|
||||
)
|
||||
|
||||
type (
|
||||
Provider = core.Certmgr
|
||||
UploadResult = core.CertmgrUploadResult
|
||||
ReplaceResult = core.CertmgrReplaceResult
|
||||
)
|
||||
|
||||
type CertmgrConfig struct {
|
||||
// 移动云 AccessKeyId。
|
||||
AccessKeyId string `json:"accessKeyId"`
|
||||
// 移动云 AccessKeySecret。
|
||||
AccessKeySecret string `json:"accessKeySecret"`
|
||||
// 移动云资源池 ID。
|
||||
PoolId string `json:"poolId"`
|
||||
// 是否是 SNI 证书。
|
||||
IsSNI bool `json:"isSni,omitempty"`
|
||||
}
|
||||
|
||||
type Certmgr struct {
|
||||
config *CertmgrConfig
|
||||
logger *slog.Logger
|
||||
sdkClient *ecloudsdkvlb.Client
|
||||
}
|
||||
|
||||
var _ Provider = (*Certmgr)(nil)
|
||||
|
||||
func NewCertmgr(config *CertmgrConfig) (*Certmgr, error) {
|
||||
if config == nil {
|
||||
return nil, fmt.Errorf("the configuration of the certmgr provider is nil")
|
||||
}
|
||||
|
||||
client, err := createSDKClient(config.AccessKeyId, config.AccessKeySecret, config.PoolId)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not create client: %w", err)
|
||||
}
|
||||
|
||||
return &Certmgr{
|
||||
config: config,
|
||||
logger: slog.Default(),
|
||||
sdkClient: client,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (c *Certmgr) SetLogger(logger *slog.Logger) {
|
||||
if logger == nil {
|
||||
c.logger = slog.New(slog.DiscardHandler)
|
||||
} else {
|
||||
c.logger = logger
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Certmgr) Upload(ctx context.Context, certPEM, privkeyPEM string) (*UploadResult, error) {
|
||||
// 解析证书内容
|
||||
certX509, err := xcert.ParseCertificateFromPEM(certPEM)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 查询弹性负载均衡证书列表,避免重复上传
|
||||
// REF: https://ecloud.10086.cn/op-help-center/doc/article/97613
|
||||
// REF: https://ecloud.10086.cn/op-help-center/doc/article/97399
|
||||
listLoadbalanceCertificationResp, err := c.sdkClient.ListLoadbalanceCertificationResp()
|
||||
c.logger.Debug("sdk request 'vlb.ListLoadbalanceCertification'", slog.Any("response", listLoadbalanceCertificationResp))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to execute sdk request 'vlb.ListLoadbalanceCertification': %w", err)
|
||||
} else {
|
||||
if listLoadbalanceCertificationResp.Body != nil && listLoadbalanceCertificationResp.Body.Content != nil {
|
||||
for _, certItem := range *listLoadbalanceCertificationResp.Body.Content {
|
||||
// 对比证书有效期
|
||||
oldCertNotAfter, _ := time.Parse(time.DateTime, lo.FromPtr(certItem.ExpirationTime))
|
||||
if !certX509.NotAfter.Equal(oldCertNotAfter) {
|
||||
continue
|
||||
}
|
||||
|
||||
// 对比证书内容
|
||||
getLoadbalanceCertificationDetailReq := &model.GetLoadbalanceCertificationDetailRespRequest{
|
||||
&model.GetLoadbalanceCertificationDetailRespPath{
|
||||
ContainerUuid: certItem.Id,
|
||||
},
|
||||
}
|
||||
getLoadbalanceCertificationDetailResp, err := c.sdkClient.GetLoadbalanceCertificationDetailResp(getLoadbalanceCertificationDetailReq)
|
||||
c.logger.Debug("sdk request 'vlb.GetLoadbalanceCertificationDetail'", slog.Any("request", getLoadbalanceCertificationDetailReq), slog.Any("response", getLoadbalanceCertificationDetailResp))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to execute sdk request 'vlb.GetLoadbalanceCertificationDetail': %w", err)
|
||||
} else {
|
||||
if !xcert.EqualCertificatesFromPEM(certPEM, lo.FromPtr(getLoadbalanceCertificationDetailResp.Body.PublicKey)) {
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
// 如果以上信息都一致,则视为已存在相同证书,直接返回
|
||||
c.logger.Info("ssl certificate already exists")
|
||||
return &UploadResult{
|
||||
CertId: lo.FromPtr(certItem.Id),
|
||||
CertName: lo.FromPtr(certItem.Name),
|
||||
}, nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 生成新证书名(需符合移动云命名规则)
|
||||
certName := fmt.Sprintf("certimate_%d", time.Now().UnixMilli())
|
||||
|
||||
// 创建弹性负载均衡证书
|
||||
// REF: https://ecloud.10086.cn/op-help-center/doc/article/97397
|
||||
createLoadbalanceCertificationReq := &model.CreateLoadbalanceCertificationRequest{
|
||||
&model.CreateLoadbalanceCertificationBody{
|
||||
Name: lo.ToPtr(certName),
|
||||
Type: lo.ToPtr(lo.Ternary(c.config.IsSNI, model.CreateLoadbalanceCertificationBodyTypeEnumSni, model.CreateLoadbalanceCertificationBodyTypeEnumServer)),
|
||||
Description: lo.ToPtr("upload from certimate"),
|
||||
PublicKey: lo.ToPtr(certPEM),
|
||||
PrivateKey: lo.ToPtr(privkeyPEM),
|
||||
},
|
||||
}
|
||||
createLoadbalanceCertificationResp, err := c.sdkClient.CreateLoadbalanceCertification(createLoadbalanceCertificationReq)
|
||||
c.logger.Debug("sdk request 'vlb.CreateLoadbalanceCertification'", slog.Any("request", createLoadbalanceCertificationReq), slog.Any("response", createLoadbalanceCertificationResp))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to execute sdk request 'vlb.CreateLoadbalanceCertification': %w", err)
|
||||
}
|
||||
|
||||
return &UploadResult{
|
||||
CertId: lo.FromPtr(createLoadbalanceCertificationResp.Body),
|
||||
CertName: certName,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (c *Certmgr) Replace(ctx context.Context, certIdOrName string, certPEM, privkeyPEM string) (*ReplaceResult, error) {
|
||||
return nil, core.ErrUnsupported
|
||||
}
|
||||
|
||||
func createSDKClient(accessKeyId, accessKeySecret, poolId string) (*ecloudsdkvlb.Client, error) {
|
||||
client := ecloudsdkvlb.NewClient(&config.Config{
|
||||
AccessKey: &accessKeyId,
|
||||
SecretKey: &accessKeySecret,
|
||||
RegionId: &poolId,
|
||||
})
|
||||
|
||||
return client, nil
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
package cmcccloudvlb_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/certimate-go/certimate/pkg/core/certmgr/internal/tester"
|
||||
impl "github.com/certimate-go/certimate/pkg/core/certmgr/providers/cmcccloud-vlb"
|
||||
)
|
||||
|
||||
var (
|
||||
fp = tester.Args("CMCCCLOUDVLB_")
|
||||
fTestCertPath string
|
||||
fTestKeyPath string
|
||||
fAccessKeyId string
|
||||
fAccessKeySecret string
|
||||
fPoolId string
|
||||
)
|
||||
|
||||
func init() {
|
||||
fp.DefineString(&fTestCertPath, "TESTCERTPATH")
|
||||
fp.DefineString(&fTestKeyPath, "TESTKEYPATH")
|
||||
fp.DefineString(&fAccessKeyId, "ACCESSKEYID")
|
||||
fp.DefineString(&fAccessKeySecret, "ACCESSKEYSECRET")
|
||||
fp.DefineString(&fPoolId, "POOLID")
|
||||
}
|
||||
|
||||
/*
|
||||
Shell command to run this test:
|
||||
|
||||
go test -v ./cmcccloud_vlb_test.go -args \
|
||||
--CMCCCLOUDVLB_TESTCERTPATH="/path/to/your-test-cert.pem" \
|
||||
--CMCCCLOUDVLB_TESTKEYPATH="/path/to/your-test-key.pem" \
|
||||
--CMCCCLOUDVLB_ACCESSKEYID="your-access-key-id" \
|
||||
--CMCCCLOUDVLB_ACCESSKEYSECRET="your-access-key-secret" \
|
||||
--CMCCCLOUDVLB_POOLID="CIDC-RP-29"
|
||||
*/
|
||||
func TestProvider(t *testing.T) {
|
||||
fp.Parse()
|
||||
|
||||
t.Run("Upload", func(t *testing.T) {
|
||||
provider, err := impl.NewCertmgr(&impl.CertmgrConfig{
|
||||
AccessKeyId: fAccessKeyId,
|
||||
AccessKeySecret: fAccessKeySecret,
|
||||
PoolId: fPoolId,
|
||||
})
|
||||
if err != nil {
|
||||
t.Errorf("err: %+v", err)
|
||||
return
|
||||
}
|
||||
|
||||
tester.TestUpload(t, provider, tester.TestUploadArgs{CertPath: fTestCertPath, KeyPath: fTestKeyPath})
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,310 @@
|
||||
package cmcccloudvlb
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"log/slog"
|
||||
|
||||
"github.com/samber/lo"
|
||||
"gitlab.ecloud.com/ecloud/ecloudsdkcore/config"
|
||||
"gitlab.ecloud.com/ecloud/ecloudsdkvlb/model"
|
||||
|
||||
"github.com/certimate-go/certimate/pkg/sdk3rd-trimmed/gitlab.ecloud.com/ecloud/ecloudsdkvlb"
|
||||
|
||||
"github.com/certimate-go/certimate/pkg/core"
|
||||
cmgrimpl "github.com/certimate-go/certimate/pkg/core/certmgr/providers/cmcccloud-vlb"
|
||||
)
|
||||
|
||||
type (
|
||||
Provider = core.Deployer
|
||||
DeployResult = core.DeployerDeployResult
|
||||
)
|
||||
|
||||
type DeployerConfig struct {
|
||||
// 移动云 AccessKeyId。
|
||||
AccessKeyId string `json:"accessKeyId"`
|
||||
// 移动云 AccessKeySecret。
|
||||
AccessKeySecret string `json:"accessKeySecret"`
|
||||
// 移动云资源池 ID。
|
||||
PoolId string `json:"poolId"`
|
||||
// 部署目标。
|
||||
DeployTarget string `json:"deployTarget"`
|
||||
// 负载均衡实例 ID。
|
||||
// 部署目标为 [DEPLOY_TARGET_LOADBALANCER] 时必填。
|
||||
LoadbalancerId string `json:"loadbalancerId,omitempty"`
|
||||
// 负载均衡监听器 ID。
|
||||
// 部署目标为 [DEPLOY_TARGET_LISTENER] 时必填。
|
||||
ListenerId string `json:"listenerId,omitempty"`
|
||||
// SNI 域名(支持泛域名)。
|
||||
// 部署目标为 [DEPLOY_TARGET_LOADBALANCER]、[DEPLOY_TARGET_LISTENER] 时选填。
|
||||
Domain string `json:"domain,omitempty"`
|
||||
}
|
||||
|
||||
type Deployer struct {
|
||||
config *DeployerConfig
|
||||
logger *slog.Logger
|
||||
sdkClient *ecloudsdkvlb.Client
|
||||
sdkCertmgr core.Certmgr
|
||||
}
|
||||
|
||||
var _ Provider = (*Deployer)(nil)
|
||||
|
||||
func NewDeployer(config *DeployerConfig) (*Deployer, error) {
|
||||
if config == nil {
|
||||
return nil, fmt.Errorf("the configuration of the deployer provider is nil")
|
||||
}
|
||||
|
||||
client, err := createSDKClient(config.AccessKeyId, config.AccessKeySecret, config.PoolId)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not create client: %w", err)
|
||||
}
|
||||
|
||||
pcertmgr, err := cmgrimpl.NewCertmgr(&cmgrimpl.CertmgrConfig{
|
||||
AccessKeyId: config.AccessKeyId,
|
||||
AccessKeySecret: config.AccessKeySecret,
|
||||
PoolId: config.PoolId,
|
||||
IsSNI: config.Domain != "",
|
||||
})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not create certmgr: %w", err)
|
||||
}
|
||||
|
||||
return &Deployer{
|
||||
config: config,
|
||||
logger: slog.Default(),
|
||||
sdkClient: client,
|
||||
sdkCertmgr: pcertmgr,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (d *Deployer) SetLogger(logger *slog.Logger) {
|
||||
if logger == nil {
|
||||
d.logger = slog.New(slog.DiscardHandler)
|
||||
} else {
|
||||
d.logger = logger
|
||||
}
|
||||
|
||||
d.sdkCertmgr.SetLogger(logger)
|
||||
}
|
||||
|
||||
func (d *Deployer) Deploy(ctx context.Context, certPEM, privkeyPEM string) (*DeployResult, error) {
|
||||
// 上传证书
|
||||
upres, err := d.sdkCertmgr.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))
|
||||
}
|
||||
|
||||
// 根据部署目标决定业务流程
|
||||
switch d.config.DeployTarget {
|
||||
case DEPLOY_TARGET_LOADBALANCER:
|
||||
if err := d.deployToLoadbalancer(ctx, upres.CertId); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
case DEPLOY_TARGET_LISTENER:
|
||||
if err := d.deployToListener(ctx, upres.CertId); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
default:
|
||||
return nil, fmt.Errorf("unsupported deploy target '%s'", d.config.DeployTarget)
|
||||
}
|
||||
|
||||
return &DeployResult{}, nil
|
||||
}
|
||||
|
||||
func (d *Deployer) deployToLoadbalancer(ctx context.Context, cloudCertId string) error {
|
||||
if d.config.LoadbalancerId == "" {
|
||||
return fmt.Errorf("config `loadbalancerId` is required")
|
||||
}
|
||||
|
||||
// 查询 HTTPS 监听器列表
|
||||
// REF: https://ecloud.10086.cn/op-help-center/doc/article/97026
|
||||
listenerIds := make([]string, 0)
|
||||
listLoadBalanceHTTPSListenerPage := 1
|
||||
listLoadBalanceHTTPSListenerPageSize := 10
|
||||
for {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return ctx.Err()
|
||||
default:
|
||||
}
|
||||
|
||||
listLoadBalanceHTTPSListenerReq := &model.ListLoadBalanceHTTPSListenerRequest{
|
||||
ListLoadBalanceHTTPSListenerPath: &model.ListLoadBalanceHTTPSListenerPath{
|
||||
LoadBalanceId: lo.ToPtr(d.config.LoadbalancerId),
|
||||
},
|
||||
ListLoadBalanceHTTPSListenerQuery: &model.ListLoadBalanceHTTPSListenerQuery{
|
||||
Page: lo.ToPtr(int32(listLoadBalanceHTTPSListenerPage)),
|
||||
PageSize: lo.ToPtr(int32(listLoadBalanceHTTPSListenerPageSize)),
|
||||
},
|
||||
}
|
||||
listLoadBalanceHTTPSListenerResp, err := d.sdkClient.ListLoadBalanceHTTPSListener(listLoadBalanceHTTPSListenerReq)
|
||||
d.logger.Debug("sdk request 'vlb.ListLoadBalanceHTTPSListener'", slog.Any("request", listLoadBalanceHTTPSListenerReq), slog.Any("response", listLoadBalanceHTTPSListenerResp))
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to execute sdk request 'vlb.ListLoadBalanceHTTPSListener': %w", err)
|
||||
}
|
||||
|
||||
if listLoadBalanceHTTPSListenerResp.Body == nil || listLoadBalanceHTTPSListenerResp.Body.Content == nil {
|
||||
break
|
||||
}
|
||||
|
||||
for _, listener := range *listLoadBalanceHTTPSListenerResp.Body.Content {
|
||||
listenerIds = append(listenerIds, lo.FromPtr(listener.Id))
|
||||
}
|
||||
|
||||
if len(*listLoadBalanceHTTPSListenerResp.Body.Content) < listLoadBalanceHTTPSListenerPageSize {
|
||||
break
|
||||
}
|
||||
|
||||
listLoadBalanceHTTPSListenerPage++
|
||||
}
|
||||
|
||||
// 遍历更新监听证书
|
||||
if len(listenerIds) == 0 {
|
||||
d.logger.Info("no elb listeners to deploy")
|
||||
} else {
|
||||
d.logger.Info("found https listeners to deploy", slog.Any("listenerIds", listenerIds))
|
||||
var errs []error
|
||||
|
||||
for _, listenerId := range listenerIds {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return ctx.Err()
|
||||
default:
|
||||
if err := d.updateListenerCertificate(ctx, listenerId, cloudCertId); err != nil {
|
||||
errs = append(errs, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if len(errs) > 0 {
|
||||
return errors.Join(errs...)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *Deployer) deployToListener(ctx context.Context, cloudCertId string) error {
|
||||
if d.config.ListenerId == "" {
|
||||
return fmt.Errorf("config `listenerId` is required")
|
||||
}
|
||||
|
||||
// 更新监听
|
||||
if err := d.updateListenerCertificate(ctx, d.config.ListenerId, cloudCertId); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *Deployer) updateListenerCertificate(ctx context.Context, cloudListenerId string, cloudCertId string) error {
|
||||
// 查询 HTTPS 监听器信息
|
||||
// REF: https://ecloud.10086.cn/op-help-center/doc/article/97026
|
||||
var listenerInfo *model.ListLoadBalanceHTTPSListenerResponseContent
|
||||
listLoadBalanceHTTPSListenerPage := 1
|
||||
listLoadBalanceHTTPSListenerPageSize := 10
|
||||
for {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return ctx.Err()
|
||||
default:
|
||||
}
|
||||
|
||||
listLoadBalanceHTTPSListenerReq := &model.ListLoadBalanceHTTPSListenerRequest{
|
||||
ListLoadBalanceHTTPSListenerPath: &model.ListLoadBalanceHTTPSListenerPath{
|
||||
LoadBalanceId: lo.ToPtr(d.config.LoadbalancerId),
|
||||
},
|
||||
ListLoadBalanceHTTPSListenerQuery: &model.ListLoadBalanceHTTPSListenerQuery{
|
||||
Page: lo.ToPtr(int32(listLoadBalanceHTTPSListenerPage)),
|
||||
PageSize: lo.ToPtr(int32(listLoadBalanceHTTPSListenerPageSize)),
|
||||
},
|
||||
}
|
||||
listLoadBalanceHTTPSListenerResp, err := d.sdkClient.ListLoadBalanceHTTPSListener(listLoadBalanceHTTPSListenerReq)
|
||||
d.logger.Debug("sdk request 'vlb.ListLoadBalanceHTTPSListener'", slog.Any("request", listLoadBalanceHTTPSListenerReq), slog.Any("response", listLoadBalanceHTTPSListenerResp))
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to execute sdk request 'vlb.ListLoadBalanceHTTPSListener': %w", err)
|
||||
}
|
||||
|
||||
if listLoadBalanceHTTPSListenerResp.Body == nil || listLoadBalanceHTTPSListenerResp.Body.Content == nil {
|
||||
break
|
||||
}
|
||||
|
||||
for _, listener := range *listLoadBalanceHTTPSListenerResp.Body.Content {
|
||||
if lo.FromPtr(listener.Id) == cloudListenerId {
|
||||
listenerInfo = &listener
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if len(*listLoadBalanceHTTPSListenerResp.Body.Content) < listLoadBalanceHTTPSListenerPageSize {
|
||||
break
|
||||
}
|
||||
|
||||
listLoadBalanceHTTPSListenerPage++
|
||||
}
|
||||
if listenerInfo == nil {
|
||||
return fmt.Errorf("could not find listener '%s'", cloudListenerId)
|
||||
}
|
||||
|
||||
if d.config.Domain == "" {
|
||||
// 未指定 SNI,只需部署到默认证书
|
||||
|
||||
if lo.FromPtr(listenerInfo.DefaultTlsContainerId) == cloudCertId {
|
||||
d.logger.Info("ssl certificate already deployed")
|
||||
return nil
|
||||
}
|
||||
|
||||
// 修改 HTTPS 监听器
|
||||
// REF: https://ecloud.10086.cn/op-help-center/doc/article/97024
|
||||
updateListenerReq := &model.UpdateListenerRequest{
|
||||
&model.UpdateListenerBody{
|
||||
Id: lo.ToPtr(cloudListenerId),
|
||||
DefaultTlsContainerId: lo.ToPtr(cloudCertId),
|
||||
},
|
||||
}
|
||||
updateListenerResp, err := d.sdkClient.UpdateListener(updateListenerReq)
|
||||
d.logger.Debug("sdk request 'vlb.UpdateListener'", slog.Any("request", updateListenerReq), slog.Any("response", updateListenerResp))
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to execute sdk request 'vlb.UpdateListener': %w", err)
|
||||
}
|
||||
} else {
|
||||
// 指定 SNI,需部署到 SNI 证书
|
||||
|
||||
if lo.Contains(listenerInfo.SniContainerIdList, cloudCertId) {
|
||||
d.logger.Info("ssl certificate already deployed")
|
||||
return nil
|
||||
}
|
||||
|
||||
// 修改 HTTPS 监听器
|
||||
// REF: https://ecloud.10086.cn/op-help-center/doc/article/97024
|
||||
updateListenerReq := &model.UpdateListenerRequest{
|
||||
&model.UpdateListenerBody{
|
||||
Id: lo.ToPtr(cloudListenerId),
|
||||
SniUp: lo.ToPtr(true),
|
||||
SniContainerIds: append(listenerInfo.SniContainerIdList, cloudCertId),
|
||||
},
|
||||
}
|
||||
updateListenerResp, err := d.sdkClient.UpdateListener(updateListenerReq)
|
||||
d.logger.Debug("sdk request 'vlb.UpdateListener'", slog.Any("request", updateListenerReq), slog.Any("response", updateListenerResp))
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to execute sdk request 'vlb.UpdateListener': %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func createSDKClient(accessKeyId, accessKeySecret, poolId string) (*ecloudsdkvlb.Client, error) {
|
||||
client := ecloudsdkvlb.NewClient(&config.Config{
|
||||
AccessKey: &accessKeyId,
|
||||
SecretKey: &accessKeySecret,
|
||||
PoolId: &poolId,
|
||||
})
|
||||
|
||||
return client, nil
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
package cmcccloudvlb_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/certimate-go/certimate/pkg/core/deployer/internal/tester"
|
||||
impl "github.com/certimate-go/certimate/pkg/core/deployer/providers/cmcccloud-vlb"
|
||||
)
|
||||
|
||||
var (
|
||||
fp = tester.Args("CMCCCLOUDVLB_")
|
||||
fTestCertPath string
|
||||
fTestKeyPath string
|
||||
fAccessKeyId string
|
||||
fAccessKeySecret string
|
||||
fPoolId string
|
||||
fLoadbalancerId string
|
||||
fListenerId string
|
||||
)
|
||||
|
||||
func init() {
|
||||
fp.DefineString(&fTestCertPath, "TESTCERTPATH")
|
||||
fp.DefineString(&fTestKeyPath, "TESTKEYPATH")
|
||||
fp.DefineString(&fAccessKeyId, "ACCESSKEYID")
|
||||
fp.DefineString(&fAccessKeySecret, "ACCESSKEYSECRET")
|
||||
fp.DefineString(&fPoolId, "POOLID")
|
||||
fp.DefineString(&fLoadbalancerId, "LOADBALANCERID")
|
||||
fp.DefineString(&fListenerId, "LISTENERID")
|
||||
}
|
||||
|
||||
/*
|
||||
Shell command to run this test:
|
||||
|
||||
go test -v ./cmcccloud_vlb_test.go -args \
|
||||
--CMCCCLOUDVLB_TESTCERTPATH="/path/to/your-test-cert.pem" \
|
||||
--CMCCCLOUDVLB_TESTKEYPATH="/path/to/your-test-key.pem" \
|
||||
--CMCCCLOUDVLB_ACCESSKEYID="your-access-key-id" \
|
||||
--CMCCCLOUDVLB_ACCESSKEYSECRET="your-access-key-secret" \
|
||||
--CMCCCLOUDVLB_POOLID="CIDC-RP-29" \
|
||||
--CMCCCLOUDVLB_LOADBALANCERID="your-vlb-instance-id" \
|
||||
--CMCCCLOUDVLB_LISTENERID="your-vlb-listener-id"
|
||||
*/
|
||||
func TestProvider(t *testing.T) {
|
||||
fp.Parse()
|
||||
|
||||
t.Run("Deploy_ToLoadbalancer", func(t *testing.T) {
|
||||
provider, err := impl.NewDeployer(&impl.DeployerConfig{
|
||||
AccessKeyId: fAccessKeyId,
|
||||
AccessKeySecret: fAccessKeySecret,
|
||||
PoolId: fPoolId,
|
||||
DeployTarget: impl.DEPLOY_TARGET_LOADBALANCER,
|
||||
LoadbalancerId: fLoadbalancerId,
|
||||
})
|
||||
if err != nil {
|
||||
t.Errorf("err: %+v", err)
|
||||
return
|
||||
}
|
||||
|
||||
tester.TestDeploy(t, provider, tester.TestDeployArgs{CertPath: fTestCertPath, KeyPath: fTestKeyPath})
|
||||
})
|
||||
|
||||
t.Run("Deploy_ToListener", func(t *testing.T) {
|
||||
provider, err := impl.NewDeployer(&impl.DeployerConfig{
|
||||
AccessKeyId: fAccessKeyId,
|
||||
AccessKeySecret: fAccessKeySecret,
|
||||
PoolId: fPoolId,
|
||||
DeployTarget: impl.DEPLOY_TARGET_LISTENER,
|
||||
ListenerId: fListenerId,
|
||||
})
|
||||
if err != nil {
|
||||
t.Errorf("err: %+v", err)
|
||||
return
|
||||
}
|
||||
|
||||
tester.TestDeploy(t, provider, tester.TestDeployArgs{CertPath: fTestCertPath, KeyPath: fTestKeyPath})
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package cmcccloudvlb
|
||||
|
||||
const (
|
||||
// 部署目标:部署到指定负载均衡器。
|
||||
DEPLOY_TARGET_LOADBALANCER = "loadbalancer"
|
||||
// 部署目标:部署到指定监听器。
|
||||
DEPLOY_TARGET_LISTENER = "listener"
|
||||
)
|
||||
@@ -178,13 +178,13 @@ func (d *Deployer) deployToListener(ctx context.Context, cloudCertId string) err
|
||||
func (d *Deployer) updateListenerCertificate(ctx context.Context, cloudListenerId string, cloudCertId string) error {
|
||||
// 更新监听器
|
||||
// REF: https://eop.ctyun.cn/ebp/ctapiDocument/search?sid=24&api=5652&data=88&isNormal=1&vid=82
|
||||
setLoadBalancerHTTPSListenerAttributeReq := &ctyunelb.UpdateListenerRequest{
|
||||
updateListenerReq := &ctyunelb.UpdateListenerRequest{
|
||||
RegionID: lo.ToPtr(d.config.RegionId),
|
||||
ListenerID: lo.ToPtr(cloudListenerId),
|
||||
CertificateID: lo.ToPtr(cloudCertId),
|
||||
}
|
||||
setLoadBalancerHTTPSListenerAttributeResp, err := d.sdkClient.UpdateListenerWithContext(ctx, setLoadBalancerHTTPSListenerAttributeReq)
|
||||
d.logger.Debug("sdk request 'elb.UpdateListener'", slog.Any("request", setLoadBalancerHTTPSListenerAttributeReq), slog.Any("response", setLoadBalancerHTTPSListenerAttributeResp))
|
||||
updateListenerResp, err := d.sdkClient.UpdateListenerWithContext(ctx, updateListenerReq)
|
||||
d.logger.Debug("sdk request 'elb.UpdateListener'", slog.Any("request", updateListenerReq), slog.Any("response", updateListenerResp))
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to execute sdk request 'elb.UpdateListener': %w", err)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,373 @@
|
||||
package ecloudsdkvlb
|
||||
|
||||
import (
|
||||
"gitlab.ecloud.com/ecloud/ecloudsdkcore"
|
||||
"gitlab.ecloud.com/ecloud/ecloudsdkcore/config"
|
||||
"gitlab.ecloud.com/ecloud/ecloudsdkcore/param"
|
||||
"gitlab.ecloud.com/ecloud/ecloudsdkcore/region"
|
||||
"gitlab.ecloud.com/ecloud/ecloudsdkcore/request"
|
||||
"gitlab.ecloud.com/ecloud/ecloudsdkcore/utils"
|
||||
"gitlab.ecloud.com/ecloud/ecloudsdkvlb/model"
|
||||
)
|
||||
|
||||
type Client struct {
|
||||
apiClient *ecloudsdkcore.APIClient
|
||||
config *config.Config
|
||||
httpRequest *request.HttpRequest
|
||||
allRegions []region.Region
|
||||
}
|
||||
|
||||
func NewClient(config *config.Config) *Client {
|
||||
httpRequest := request.DefaultHttpRequest()
|
||||
httpRequest.Product = product
|
||||
httpRequest.Version = version
|
||||
httpRequest.SdkVersion = sdkVersion
|
||||
ecloudsdkcore.InitConfig(config)
|
||||
apiClient := ecloudsdkcore.DefaultApiClient(config, httpRequest)
|
||||
client := &Client{
|
||||
apiClient: apiClient,
|
||||
config: config,
|
||||
httpRequest: httpRequest,
|
||||
}
|
||||
client.allRegions = client.initRegions()
|
||||
client.setEndpoint(config, httpRequest)
|
||||
return client
|
||||
}
|
||||
|
||||
const (
|
||||
product string = "vlb"
|
||||
version = "v1"
|
||||
sdkVersion = "1.0.7"
|
||||
)
|
||||
|
||||
func (c *Client) initRegions() []region.Region {
|
||||
var regions []region.Region
|
||||
regions = append(regions, region.Region{
|
||||
RegionId: utils.String("cn-jiangsu-1"),
|
||||
PoolId: utils.String("CIDC-RP-25"),
|
||||
Endpoint: utils.String("https://api-wuxi-1.cmecloud.cn:8443"),
|
||||
})
|
||||
regions = append(regions, region.Region{
|
||||
RegionId: utils.String("cn-guangdong-1"),
|
||||
PoolId: utils.String("CIDC-RP-26"),
|
||||
Endpoint: utils.String("https://api-dongguan-1.cmecloud.cn:8443"),
|
||||
})
|
||||
regions = append(regions, region.Region{
|
||||
RegionId: utils.String("cn-sichuan-1"),
|
||||
PoolId: utils.String("CIDC-RP-27"),
|
||||
Endpoint: utils.String("https://api-yaan-1.cmecloud.cn:8443"),
|
||||
})
|
||||
regions = append(regions, region.Region{
|
||||
RegionId: utils.String("cn-henan-1"),
|
||||
PoolId: utils.String("CIDC-RP-28"),
|
||||
Endpoint: utils.String("https://api-zhengzhou-1.cmecloud.cn:8443"),
|
||||
})
|
||||
regions = append(regions, region.Region{
|
||||
RegionId: utils.String("cn-beijing-1"),
|
||||
PoolId: utils.String("CIDC-RP-29"),
|
||||
Endpoint: utils.String("https://api-beijing-2.cmecloud.cn:8443"),
|
||||
})
|
||||
regions = append(regions, region.Region{
|
||||
RegionId: utils.String("cn-hunan-1"),
|
||||
PoolId: utils.String("CIDC-RP-30"),
|
||||
Endpoint: utils.String("https://api-zhuzhou-1.cmecloud.cn:8443"),
|
||||
})
|
||||
regions = append(regions, region.Region{
|
||||
RegionId: utils.String("cn-shandong-1"),
|
||||
PoolId: utils.String("CIDC-RP-31"),
|
||||
Endpoint: utils.String("https://api-jinan-1.cmecloud.cn:8443"),
|
||||
})
|
||||
regions = append(regions, region.Region{
|
||||
RegionId: utils.String("cn-shaanxi-1"),
|
||||
PoolId: utils.String("CIDC-RP-32"),
|
||||
Endpoint: utils.String("https://api-xian-1.cmecloud.cn:8443"),
|
||||
})
|
||||
regions = append(regions, region.Region{
|
||||
RegionId: utils.String("cn-shanghai-1"),
|
||||
PoolId: utils.String("CIDC-RP-33"),
|
||||
Endpoint: utils.String("https://api-shanghai-1.cmecloud.cn:8443"),
|
||||
})
|
||||
regions = append(regions, region.Region{
|
||||
RegionId: utils.String("cn-chongqing-1"),
|
||||
PoolId: utils.String("CIDC-RP-34"),
|
||||
Endpoint: utils.String("https://api-chongqing-1.cmecloud.cn:8443"),
|
||||
})
|
||||
regions = append(regions, region.Region{
|
||||
RegionId: utils.String("cn-zhejiang-1"),
|
||||
PoolId: utils.String("CIDC-RP-35"),
|
||||
Endpoint: utils.String("https://api-ningbo-1.cmecloud.cn:8443"),
|
||||
})
|
||||
regions = append(regions, region.Region{
|
||||
RegionId: utils.String("cn-tianjin-1"),
|
||||
PoolId: utils.String("CIDC-RP-36"),
|
||||
Endpoint: utils.String("https://api-tianjin-1.cmecloud.cn:8443"),
|
||||
})
|
||||
regions = append(regions, region.Region{
|
||||
RegionId: utils.String("cn-jilin-1"),
|
||||
PoolId: utils.String("CIDC-RP-37"),
|
||||
Endpoint: utils.String("https://api-jilin-1.cmecloud.cn:8443"),
|
||||
})
|
||||
regions = append(regions, region.Region{
|
||||
RegionId: utils.String("cn-hubei-1"),
|
||||
PoolId: utils.String("CIDC-RP-38"),
|
||||
Endpoint: utils.String("https://api-hubei-1.cmecloud.cn:8443"),
|
||||
})
|
||||
regions = append(regions, region.Region{
|
||||
RegionId: utils.String("cn-jiangxi-1"),
|
||||
PoolId: utils.String("CIDC-RP-39"),
|
||||
Endpoint: utils.String("https://api-jiangxi-1.cmecloud.cn:8443"),
|
||||
})
|
||||
regions = append(regions, region.Region{
|
||||
RegionId: utils.String("cn-gansu-1"),
|
||||
PoolId: utils.String("CIDC-RP-40"),
|
||||
Endpoint: utils.String("https://api-gansu-1.cmecloud.cn:8443"),
|
||||
})
|
||||
regions = append(regions, region.Region{
|
||||
RegionId: utils.String("cn-shangxi-1"),
|
||||
PoolId: utils.String("CIDC-RP-41"),
|
||||
Endpoint: utils.String("https://api-shanxi-1.cmecloud.cn:8443"),
|
||||
})
|
||||
regions = append(regions, region.Region{
|
||||
RegionId: utils.String("cn-liaoning-1"),
|
||||
PoolId: utils.String("CIDC-RP-42"),
|
||||
Endpoint: utils.String("https://api-liaoning-1.cmecloud.cn:8443"),
|
||||
})
|
||||
regions = append(regions, region.Region{
|
||||
RegionId: utils.String("cn-yunnan-1"),
|
||||
PoolId: utils.String("CIDC-RP-43"),
|
||||
Endpoint: utils.String("https://api-yunnan-2.cmecloud.cn:8443"),
|
||||
})
|
||||
regions = append(regions, region.Region{
|
||||
RegionId: utils.String("cn-hebei-1"),
|
||||
PoolId: utils.String("CIDC-RP-44"),
|
||||
Endpoint: utils.String("https://api-hebei-1.cmecloud.cn:8443"),
|
||||
})
|
||||
regions = append(regions, region.Region{
|
||||
RegionId: utils.String("cn-fujian-1"),
|
||||
PoolId: utils.String("CIDC-RP-45"),
|
||||
Endpoint: utils.String("https://api-fujian-1.cmecloud.cn:8443"),
|
||||
})
|
||||
regions = append(regions, region.Region{
|
||||
RegionId: utils.String("cn-guangxi-1"),
|
||||
PoolId: utils.String("CIDC-RP-46"),
|
||||
Endpoint: utils.String("https://api-guangxi-1.cmecloud.cn:8443"),
|
||||
})
|
||||
regions = append(regions, region.Region{
|
||||
RegionId: utils.String("cn-anhui-1"),
|
||||
PoolId: utils.String("CIDC-RP-47"),
|
||||
Endpoint: utils.String("https://api-anhui-1.cmecloud.cn:8443"),
|
||||
})
|
||||
regions = append(regions, region.Region{
|
||||
RegionId: utils.String("cn-neimenggu-1"),
|
||||
PoolId: utils.String("CIDC-RP-48"),
|
||||
Endpoint: utils.String("https://api-huhehaote-1.cmecloud.cn:8443"),
|
||||
})
|
||||
regions = append(regions, region.Region{
|
||||
RegionId: utils.String("cn-guzhou-1"),
|
||||
PoolId: utils.String("CIDC-RP-49"),
|
||||
Endpoint: utils.String("https://api-guiyang-1.cmecloud.cn:8443"),
|
||||
})
|
||||
regions = append(regions, region.Region{
|
||||
RegionId: utils.String("cn-hainan-1"),
|
||||
PoolId: utils.String("CIDC-RP-53"),
|
||||
Endpoint: utils.String("https://api-hainan-1.cmecloud.cn:8443"),
|
||||
})
|
||||
regions = append(regions, region.Region{
|
||||
RegionId: utils.String("cn-xinjiang-1"),
|
||||
PoolId: utils.String("CIDC-RP-54"),
|
||||
Endpoint: utils.String("https://api-xinjiang-1.cmecloud.cn:8443"),
|
||||
})
|
||||
regions = append(regions, region.Region{
|
||||
RegionId: utils.String("cn-heilongjiang-1"),
|
||||
PoolId: utils.String("CIDC-RP-55"),
|
||||
Endpoint: utils.String("https://api-heilongjiang-1.cmecloud.cn:8443"),
|
||||
})
|
||||
regions = append(regions, region.Region{
|
||||
RegionId: utils.String("cn-ningxia-1"),
|
||||
PoolId: utils.String("CIDC-RP-60"),
|
||||
Endpoint: utils.String("https://api-ningxia-1.cmecloud.cn:8443"),
|
||||
})
|
||||
regions = append(regions, region.Region{
|
||||
RegionId: utils.String("cn-qinghai-1"),
|
||||
PoolId: utils.String("CIDC-RP-61"),
|
||||
Endpoint: utils.String("https://api-qinghai-1.cmecloud.cn:8443"),
|
||||
})
|
||||
regions = append(regions, region.Region{
|
||||
RegionId: utils.String("cn-xizang-1"),
|
||||
PoolId: utils.String("CIDC-RP-62"),
|
||||
Endpoint: utils.String("https://api-xizang-1.cmecloud.cn:8443"),
|
||||
})
|
||||
regions = append(regions, region.Region{
|
||||
RegionId: utils.String("cn-hubei-2"),
|
||||
PoolId: utils.String("CIDC-RP-64"),
|
||||
Endpoint: utils.String("https://api-wuhan-1.cmecloud.cn:8443"),
|
||||
})
|
||||
regions = append(regions, region.Region{
|
||||
RegionId: utils.String("cn-xizang-2"),
|
||||
PoolId: utils.String("CIDC-RP-68"),
|
||||
Endpoint: utils.String("https://api-xizang-2.cmecloud.cn:8443"),
|
||||
})
|
||||
regions = append(regions, region.Region{
|
||||
RegionId: utils.String("cn-qinghai-2"),
|
||||
PoolId: utils.String("CIDC-RP-69"),
|
||||
Endpoint: utils.String("https://api-qinghai-2.cmecloud.cn:8443"),
|
||||
})
|
||||
regions = append(regions, region.Region{
|
||||
RegionId: utils.String("cn-ningxia-2"),
|
||||
PoolId: utils.String("CIDC-RP-71"),
|
||||
Endpoint: utils.String("https://api-ningxia-2.cmecloud.cn:8443"),
|
||||
})
|
||||
regions = append(regions, region.Region{
|
||||
RegionId: utils.String(""),
|
||||
PoolId: utils.String("CIDC-CORE-00"),
|
||||
Endpoint: utils.String("https://ecloud.10086.cn"),
|
||||
})
|
||||
return regions
|
||||
}
|
||||
|
||||
func (c *Client) setEndpoint(config *config.Config, httpRequest *request.HttpRequest) {
|
||||
if utils.IsUnSet(config.RegionId) && utils.IsUnSet(config.PoolId) {
|
||||
httpRequest.Endpoint = utils.DefaultEndpoint
|
||||
} else if utils.IsSet(config.RegionId) {
|
||||
c.findAndSetEndpointByRegionId(config.RegionId, httpRequest)
|
||||
} else {
|
||||
c.findAndSetEndpointByPoolId(config.PoolId, httpRequest)
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Client) findAndSetEndpointByRegionId(regionId *string, httpRequest *request.HttpRequest) {
|
||||
for _, r := range c.allRegions {
|
||||
if utils.StringValue(r.RegionId) == utils.StringValue(regionId) {
|
||||
endpoint := r.Endpoint
|
||||
if utils.IsUnSet(endpoint) {
|
||||
httpRequest.Endpoint = utils.DefaultEndpoint
|
||||
} else {
|
||||
httpRequest.Endpoint = *endpoint
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Client) findAndSetEndpointByPoolId(poolId *string, httpRequest *request.HttpRequest) {
|
||||
for _, r := range c.allRegions {
|
||||
if utils.StringValue(r.PoolId) == utils.StringValue(poolId) {
|
||||
endpoint := r.Endpoint
|
||||
if utils.IsUnSet(endpoint) {
|
||||
httpRequest.Endpoint = utils.DefaultEndpoint
|
||||
} else {
|
||||
httpRequest.Endpoint = *endpoint
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Client) CreateLoadbalanceCertification(request *model.CreateLoadbalanceCertificationRequest) (*model.CreateLoadbalanceCertificationResponse, error) {
|
||||
return c.CreateLoadbalanceCertificationWithConfig(request, nil)
|
||||
}
|
||||
|
||||
func (c *Client) CreateLoadbalanceCertificationWithConfig(request *model.CreateLoadbalanceCertificationRequest, runtimeConfig *config.RuntimeConfig) (*model.CreateLoadbalanceCertificationResponse, error) {
|
||||
params := param.NewParamsBuilder().
|
||||
Action("createLoadbalanceCertification").
|
||||
Uri("/acl/v3/certification").
|
||||
GatewayUri("/api/openapi-vlb/lb-console/acl/v3/certification").
|
||||
Protocol("http").
|
||||
ContentType("application/json").
|
||||
Method("POST").
|
||||
Request(request).
|
||||
Build()
|
||||
returnValue := &model.CreateLoadbalanceCertificationResponse{}
|
||||
if _, err := c.apiClient.Excute(params, runtimeConfig, returnValue); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
return returnValue, nil
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Client) GetLoadbalanceCertificationDetailResp(request *model.GetLoadbalanceCertificationDetailRespRequest) (*model.GetLoadbalanceCertificationDetailRespResponse, error) {
|
||||
return c.GetLoadbalanceCertificationDetailRespWithConfig(request, nil)
|
||||
}
|
||||
|
||||
func (c *Client) GetLoadbalanceCertificationDetailRespWithConfig(request *model.GetLoadbalanceCertificationDetailRespRequest, runtimeConfig *config.RuntimeConfig) (*model.GetLoadbalanceCertificationDetailRespResponse, error) {
|
||||
params := param.NewParamsBuilder().
|
||||
Action("getLoadbalanceCertificationDetailResp").
|
||||
Uri("/acl/v3/certification/{containerUuid}").
|
||||
GatewayUri("/api/openapi-vlb/lb-console/acl/v3/certification/{containerUuid}").
|
||||
Protocol("http").
|
||||
ContentType("application/json").
|
||||
Method("GET").
|
||||
Request(request).
|
||||
Build()
|
||||
returnValue := &model.GetLoadbalanceCertificationDetailRespResponse{}
|
||||
if _, err := c.apiClient.Excute(params, runtimeConfig, returnValue); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
return returnValue, nil
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Client) ListLoadbalanceCertificationResp() (*model.ListLoadbalanceCertificationRespResponse, error) {
|
||||
return c.ListLoadbalanceCertificationRespWithConfig(nil)
|
||||
}
|
||||
|
||||
func (c *Client) ListLoadbalanceCertificationRespWithConfig(runtimeConfig *config.RuntimeConfig) (*model.ListLoadbalanceCertificationRespResponse, error) {
|
||||
params := param.NewParamsBuilder().
|
||||
Action("listLoadbalanceCertificationResp").
|
||||
Uri("/acl/v3/certification").
|
||||
GatewayUri("/api/openapi-vlb/lb-console/acl/v3/certification").
|
||||
Protocol("http").
|
||||
ContentType("application/json").
|
||||
Method("GET").
|
||||
Build()
|
||||
returnValue := &model.ListLoadbalanceCertificationRespResponse{}
|
||||
if _, err := c.apiClient.Excute(params, runtimeConfig, returnValue); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
return returnValue, nil
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Client) ListLoadBalanceHTTPSListener(request *model.ListLoadBalanceHTTPSListenerRequest) (*model.ListLoadBalanceHTTPSListenerResponse, error) {
|
||||
return c.ListLoadBalanceHTTPSListenerWithConfig(request, nil)
|
||||
}
|
||||
|
||||
func (c *Client) ListLoadBalanceHTTPSListenerWithConfig(request *model.ListLoadBalanceHTTPSListenerRequest, runtimeConfig *config.RuntimeConfig) (*model.ListLoadBalanceHTTPSListenerResponse, error) {
|
||||
params := param.NewParamsBuilder().
|
||||
Action("listLoadBalanceHTTPSListener").
|
||||
Uri("/protocol/v3/listener/{loadBalanceId}/listeners/https").
|
||||
GatewayUri("/api/openapi-vlb/lb-console/protocol/v3/listener/{loadBalanceId}/listeners/https").
|
||||
Protocol("http").
|
||||
ContentType("application/json").
|
||||
Method("GET").
|
||||
Request(request).
|
||||
Build()
|
||||
returnValue := &model.ListLoadBalanceHTTPSListenerResponse{}
|
||||
if _, err := c.apiClient.Excute(params, runtimeConfig, returnValue); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
return returnValue, nil
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Client) UpdateListener(request *model.UpdateListenerRequest) (*model.UpdateListenerResponse, error) {
|
||||
return c.UpdateListenerWithConfig(request, nil)
|
||||
}
|
||||
|
||||
func (c *Client) UpdateListenerWithConfig(request *model.UpdateListenerRequest, runtimeConfig *config.RuntimeConfig) (*model.UpdateListenerResponse, error) {
|
||||
params := param.NewParamsBuilder().
|
||||
Action("updateListener").
|
||||
Uri("/acl/v3/listener").
|
||||
GatewayUri("/api/openapi-vlb/lb-console/acl/v3/listener").
|
||||
Protocol("http").
|
||||
ContentType("application/json").
|
||||
Method("PUT").
|
||||
Request(request).
|
||||
Build()
|
||||
returnValue := &model.UpdateListenerResponse{}
|
||||
if _, err := c.apiClient.Excute(params, runtimeConfig, returnValue); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
return returnValue, nil
|
||||
}
|
||||
}
|
||||
@@ -52,6 +52,7 @@ import BizDeployNodeConfigFieldsProviderBytePlusTOS from "./BizDeployNodeConfigF
|
||||
import BizDeployNodeConfigFieldsProviderCdnfly from "./BizDeployNodeConfigFieldsProviderCdnfly";
|
||||
import BizDeployNodeConfigFieldsProviderCloudflareSSL from "./BizDeployNodeConfigFieldsProviderCloudflareSSL";
|
||||
import BizDeployNodeConfigFieldsProviderCMCCCloudCDN from "./BizDeployNodeConfigFieldsProviderCMCCCloudCDN";
|
||||
import BizDeployNodeConfigFieldsProviderCMCCCloudVLB from "./BizDeployNodeConfigFieldsProviderCMCCCloudVLB";
|
||||
import BizDeployNodeConfigFieldsProviderCPanel from "./BizDeployNodeConfigFieldsProviderCPanel";
|
||||
import BizDeployNodeConfigFieldsProviderCTCCCloudAO from "./BizDeployNodeConfigFieldsProviderCTCCCloudAO";
|
||||
import BizDeployNodeConfigFieldsProviderCTCCCloudCDN from "./BizDeployNodeConfigFieldsProviderCTCCCloudCDN";
|
||||
@@ -197,6 +198,7 @@ const providerComponentMap: Partial<Record<DeploymentProviderType, React.Compone
|
||||
[DEPLOYMENT_PROVIDERS.CDNFLY]: BizDeployNodeConfigFieldsProviderCdnfly,
|
||||
[DEPLOYMENT_PROVIDERS.CLOUDFLARE_SSL]: BizDeployNodeConfigFieldsProviderCloudflareSSL,
|
||||
[DEPLOYMENT_PROVIDERS.CMCCCLOUD_CDN]: BizDeployNodeConfigFieldsProviderCMCCCloudCDN,
|
||||
[DEPLOYMENT_PROVIDERS.CMCCCLOUD_VLB]: BizDeployNodeConfigFieldsProviderCMCCCloudVLB,
|
||||
[DEPLOYMENT_PROVIDERS.CPANEL]: BizDeployNodeConfigFieldsProviderCPanel,
|
||||
[DEPLOYMENT_PROVIDERS.CTCCCLOUD_AO]: BizDeployNodeConfigFieldsProviderCTCCCloudAO,
|
||||
[DEPLOYMENT_PROVIDERS.CTCCCLOUD_CDN]: BizDeployNodeConfigFieldsProviderCTCCCloudCDN,
|
||||
|
||||
+155
@@ -0,0 +1,155 @@
|
||||
import { getI18n, useTranslation } from "react-i18next";
|
||||
import { Form, Input, Select } from "antd";
|
||||
import { createSchemaFieldRule } from "antd-zod";
|
||||
import { z } from "zod";
|
||||
|
||||
import Show from "@/components/Show";
|
||||
import { isDomain } from "@/utils/validator";
|
||||
|
||||
import { useFormNestedFieldsContext } from "./_context";
|
||||
|
||||
const DEPLOY_TARGET_LOADBALANCER = "loadbalancer" as const;
|
||||
const DEPLOY_TARGET_LISTENER = "listener" as const;
|
||||
|
||||
const BizDeployNodeConfigFieldsProviderCMCCCloudVLB = () => {
|
||||
const { i18n, t } = useTranslation();
|
||||
|
||||
const { parentNamePath } = useFormNestedFieldsContext();
|
||||
const formSchema = z.object({
|
||||
[parentNamePath]: getSchema({ i18n }),
|
||||
});
|
||||
const formRule = createSchemaFieldRule(formSchema);
|
||||
const formInst = Form.useFormInstance();
|
||||
const initialValues = getInitialValues();
|
||||
|
||||
const fieldResourceType = Form.useWatch([parentNamePath, "deployTarget"], formInst);
|
||||
|
||||
return (
|
||||
<>
|
||||
<Form.Item
|
||||
name={[parentNamePath, "poolId"]}
|
||||
initialValue={initialValues.poolId}
|
||||
label={t("workflow_node.deploy.form.cmcccloud_vlb_pool_id.label")}
|
||||
rules={[formRule]}
|
||||
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.cmcccloud_vlb_pool_id.tooltip") }}></span>}
|
||||
>
|
||||
<Input placeholder={t("workflow_node.deploy.form.cmcccloud_vlb_pool_id.placeholder")} />
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
name={[parentNamePath, "deployTarget"]}
|
||||
initialValue={initialValues.deployTarget}
|
||||
label={t("workflow_node.deploy.form.shared_deploy_target.label")}
|
||||
rules={[formRule]}
|
||||
>
|
||||
<Select
|
||||
options={[DEPLOY_TARGET_LOADBALANCER, DEPLOY_TARGET_LISTENER].map((s) => ({
|
||||
label: t(`workflow_node.deploy.form.cmcccloud_vlb_deploy_target.option.${s}.label`),
|
||||
value: s,
|
||||
}))}
|
||||
placeholder={t("workflow_node.deploy.form.shared_deploy_target.placeholder")}
|
||||
/>
|
||||
</Form.Item>
|
||||
|
||||
<Show when={fieldResourceType === DEPLOY_TARGET_LOADBALANCER}>
|
||||
<Form.Item
|
||||
name={[parentNamePath, "loadbalancerId"]}
|
||||
initialValue={initialValues.loadbalancerId}
|
||||
label={t("workflow_node.deploy.form.cmcccloud_vlb_loadbalancer_id.label")}
|
||||
rules={[formRule]}
|
||||
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.cmcccloud_vlb_loadbalancer_id.tooltip") }}></span>}
|
||||
>
|
||||
<Input placeholder={t("workflow_node.deploy.form.cmcccloud_vlb_loadbalancer_id.placeholder")} />
|
||||
</Form.Item>
|
||||
</Show>
|
||||
|
||||
<Show when={fieldResourceType === DEPLOY_TARGET_LISTENER}>
|
||||
<Form.Item
|
||||
name={[parentNamePath, "listenerId"]}
|
||||
initialValue={initialValues.listenerId}
|
||||
label={t("workflow_node.deploy.form.cmcccloud_vlb_listener_id.label")}
|
||||
rules={[formRule]}
|
||||
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.cmcccloud_vlb_listener_id.tooltip") }}></span>}
|
||||
>
|
||||
<Input placeholder={t("workflow_node.deploy.form.cmcccloud_vlb_listener_id.placeholder")} />
|
||||
</Form.Item>
|
||||
</Show>
|
||||
|
||||
<Show when={fieldResourceType === DEPLOY_TARGET_LOADBALANCER || fieldResourceType === DEPLOY_TARGET_LISTENER}>
|
||||
<Form.Item
|
||||
name={[parentNamePath, "domain"]}
|
||||
initialValue={initialValues.domain}
|
||||
label={t("workflow_node.deploy.form.cmcccloud_vlb_snidomain.label")}
|
||||
extra={t("workflow_node.deploy.form.cmcccloud_vlb_snidomain.help")}
|
||||
rules={[formRule]}
|
||||
>
|
||||
<Input allowClear placeholder={t("workflow_node.deploy.form.cmcccloud_vlb_snidomain.placeholder")} />
|
||||
</Form.Item>
|
||||
</Show>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
const getInitialValues = (): Nullish<z.infer<ReturnType<typeof getSchema>>> => {
|
||||
return {
|
||||
poolId: "",
|
||||
deployTarget: DEPLOY_TARGET_LISTENER,
|
||||
};
|
||||
};
|
||||
|
||||
const getSchema = ({ i18n = getI18n() }: { i18n?: ReturnType<typeof getI18n> }) => {
|
||||
const { t } = i18n;
|
||||
|
||||
return z
|
||||
.object({
|
||||
poolId: z.string().nonempty(),
|
||||
deployTarget: z.enum([DEPLOY_TARGET_LOADBALANCER, DEPLOY_TARGET_LISTENER]),
|
||||
loadbalancerId: z.string().nullish(),
|
||||
listenerId: z.string().nullish(),
|
||||
domain: z
|
||||
.string()
|
||||
.nullish()
|
||||
.refine((v) => {
|
||||
if (!v) return true;
|
||||
return isDomain(v, { allowWildcard: true });
|
||||
}, t("common.errmsg.domain_invalid")),
|
||||
})
|
||||
.superRefine((values, ctx) => {
|
||||
switch (values.deployTarget) {
|
||||
case DEPLOY_TARGET_LOADBALANCER:
|
||||
{
|
||||
const scLoadbalancerId = z.string().nonempty();
|
||||
const spLoadbalancerId = scLoadbalancerId.safeParse(values.loadbalancerId);
|
||||
if (!spLoadbalancerId.success) {
|
||||
ctx.addIssue({
|
||||
code: "custom",
|
||||
message: z.treeifyError(spLoadbalancerId.error).errors.join(),
|
||||
path: ["loadbalancerId"],
|
||||
});
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case DEPLOY_TARGET_LISTENER:
|
||||
{
|
||||
const scListenerId = z.string().nonempty();
|
||||
const spListenerId = scListenerId.safeParse(values.listenerId);
|
||||
if (!spListenerId.success) {
|
||||
ctx.addIssue({
|
||||
code: "custom",
|
||||
message: z.treeifyError(spListenerId.error).errors.join(),
|
||||
path: ["listenerId"],
|
||||
});
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
const _default = Object.assign(BizDeployNodeConfigFieldsProviderCMCCCloudVLB, {
|
||||
getInitialValues,
|
||||
getSchema,
|
||||
});
|
||||
|
||||
export default _default;
|
||||
@@ -644,6 +644,7 @@ export const DEPLOYMENT_PROVIDERS = Object.freeze({
|
||||
CDNFLY: `${ACCESS_PROVIDERS.CDNFLY}`,
|
||||
CLOUDFLARE_SSL: `${ACCESS_PROVIDERS.CLOUDFLARE}-ssl`,
|
||||
CMCCCLOUD_CDN: `${ACCESS_PROVIDERS.CMCCCLOUD}-cdn`,
|
||||
CMCCCLOUD_VLB: `${ACCESS_PROVIDERS.CMCCCLOUD}-vlb`,
|
||||
CPANEL: `${ACCESS_PROVIDERS.CPANEL}`,
|
||||
CTCCCLOUD_AO: `${ACCESS_PROVIDERS.CTCCCLOUD}-ao`,
|
||||
CTCCCLOUD_CDN: `${ACCESS_PROVIDERS.CTCCCLOUD}-cdn`,
|
||||
@@ -863,6 +864,7 @@ export const deploymentProvidersMap: Map<DeploymentProvider["type"] | string, De
|
||||
[DEPLOYMENT_PROVIDERS.BAIDUCLOUD_APPBLB, "provider.baiducloud_appblb", DEPLOYMENT_CATEGORIES.LOADBALANCE],
|
||||
[DEPLOYMENT_PROVIDERS.BAIDUCLOUD_CERT, "provider.baiducloud_cert_upload", DEPLOYMENT_CATEGORIES.SSL],
|
||||
[DEPLOYMENT_PROVIDERS.CMCCCLOUD_CDN, "provider.cmcccloud_cdn", DEPLOYMENT_CATEGORIES.CDN],
|
||||
[DEPLOYMENT_PROVIDERS.CMCCCLOUD_VLB, "provider.cmcccloud_vlb", DEPLOYMENT_CATEGORIES.LOADBALANCE],
|
||||
[DEPLOYMENT_PROVIDERS.CTCCCLOUD_CDN, "provider.ctcccloud_cdn", DEPLOYMENT_CATEGORIES.CDN],
|
||||
[DEPLOYMENT_PROVIDERS.CTCCCLOUD_ICDN, "provider.ctcccloud_icdn", DEPLOYMENT_CATEGORIES.CDN],
|
||||
[DEPLOYMENT_PROVIDERS.CTCCCLOUD_AO, "provider.ctcccloud_ao", DEPLOYMENT_CATEGORIES.CDN],
|
||||
|
||||
@@ -110,6 +110,7 @@
|
||||
"cmcccloud": "China Mobile ECloud",
|
||||
"cmcccloud_cdn": "China Mobile ECloud - CDN (Content Delivery Network)",
|
||||
"cmcccloud_dns": "China Mobile ECloud - DNS",
|
||||
"cmcccloud_vlb": "China Mobile ECloud - VLB (Virtual Load Balancer)",
|
||||
"conohavps": "ConoHa VPS",
|
||||
"constellix": "Constellix",
|
||||
"cpanel": "cPanel",
|
||||
|
||||
@@ -1432,6 +1432,36 @@
|
||||
"label": "CMCC ECloud CDN domain",
|
||||
"placeholder": "Please enter CMCC ECloud CDN domain name"
|
||||
},
|
||||
"cmcccloud_vlb_pool_id": {
|
||||
"label": "CMCC ECloud pool ID",
|
||||
"placeholder": "Please enter CMCC ECloud VLB pool ID (e.g. CIDC-RP-29)",
|
||||
"tooltip": "For more information, see <a href=\"https://ecloud.10086.cn/op-help-center/doc/article/54462\" target=\"_blank\">https://ecloud.10086.cn/op-help-center/doc/article/54462</a>"
|
||||
},
|
||||
"cmcccloud_vlb_deploy_target": {
|
||||
"option": {
|
||||
"loadbalancer": {
|
||||
"label": "VLB load balancer"
|
||||
},
|
||||
"listener": {
|
||||
"label": "VLB listener"
|
||||
}
|
||||
}
|
||||
},
|
||||
"cmcccloud_vlb_loadbalancer_id": {
|
||||
"label": "CMCC ECloud VLB load balancer ID",
|
||||
"placeholder": "Please enter CMCC ECloud VLB load balancer ID",
|
||||
"tooltip": "For more information, see <a href=\"https://ecloud.10086.cn/api/page/lb-console-manage-web/CIDC-RP-29/elb/instancelist\" target=\"_blank\">https://ecloud.10086.cn/api/page/lb-console-manage-web/CIDC-RP-29/elb/instancelist</a>"
|
||||
},
|
||||
"cmcccloud_vlb_listener_id": {
|
||||
"label": "CMCC ECloud VLB listener ID",
|
||||
"placeholder": "Please enter CMCC ECloud VLB listener ID",
|
||||
"tooltip": "For more information, see <a href=\"https://ecloud.10086.cn/api/page/lb-console-manage-web/CIDC-RP-29/elb/instancelist\" target=\"_blank\">https://ecloud.10086.cn/api/page/lb-console-manage-web/CIDC-RP-29/elb/instancelist</a>"
|
||||
},
|
||||
"cmcccloud_vlb_snidomain": {
|
||||
"label": "CMCC ECloud VLB SNI domain (Optional)",
|
||||
"placeholder": "Please enter CMCC ECloud VLB SNI domain name",
|
||||
"help": "Notes: Leave it blank to set the default certificate; otherwise, to set the extension one for SNI."
|
||||
},
|
||||
"cpanel_deploy_target": {
|
||||
"option": {
|
||||
"website": {
|
||||
@@ -1458,9 +1488,6 @@
|
||||
},
|
||||
"ctcccloud_elb_deploy_target": {
|
||||
"option": {
|
||||
"certificate": {
|
||||
"label": "ELB certificate"
|
||||
},
|
||||
"loadbalancer": {
|
||||
"label": "ELB load balancer"
|
||||
},
|
||||
|
||||
@@ -110,6 +110,7 @@
|
||||
"cmcccloud": "移动云",
|
||||
"cmcccloud_cdn": "移动云 - 内容分发网络 CDN",
|
||||
"cmcccloud_dns": "移动云 - 云解析 DNS",
|
||||
"cmcccloud_vlb": "移动云 - 弹性负载均衡 VLB",
|
||||
"conohavps": "ConoHa VPS",
|
||||
"constellix": "Constellix",
|
||||
"cpanel": "cPanel",
|
||||
|
||||
@@ -1431,6 +1431,36 @@
|
||||
"label": "移动云 CDN 加速域名",
|
||||
"placeholder": "请输入移动云 CDN 加速域名"
|
||||
},
|
||||
"cmcccloud_vlb_pool_id": {
|
||||
"label": "移动云资源池 ID",
|
||||
"placeholder": "请输入移动云 VLB 资源池 ID(例如:CIDC-RP-29)",
|
||||
"tooltip": "这是什么?请参阅 <a href=\"https://ecloud.10086.cn/op-help-center/doc/article/54462\" target=\"_blank\">https://ecloud.10086.cn/op-help-center/doc/article/54462</a>"
|
||||
},
|
||||
"cmcccloud_vlb_deploy_target": {
|
||||
"option": {
|
||||
"loadbalancer": {
|
||||
"label": "部署到指定负载均衡器下的全部 HTTPS 监听器"
|
||||
},
|
||||
"listener": {
|
||||
"label": "部署到指定 HTTPS 监听器"
|
||||
}
|
||||
}
|
||||
},
|
||||
"cmcccloud_vlb_loadbalancer_id": {
|
||||
"label": "移动云 VLB 负载均衡器 ID",
|
||||
"placeholder": "请输入移动云 VLB 负载均衡器 ID",
|
||||
"tooltip": "这是什么?请参阅 <a href=\"https://ecloud.10086.cn/api/page/lb-console-manage-web/CIDC-RP-29/elb/instancelist\" target=\"_blank\">https://ecloud.10086.cn/api/page/lb-console-manage-web/CIDC-RP-29/elb/instancelist</a>"
|
||||
},
|
||||
"cmcccloud_vlb_listener_id": {
|
||||
"label": "移动云 VLB 监听器 ID",
|
||||
"placeholder": "请输入移动云 VLB 监听器 ID",
|
||||
"tooltip": "这是什么?请参阅 <a href=\"https://ecloud.10086.cn/api/page/lb-console-manage-web/CIDC-RP-29/elb/instancelist\" target=\"_blank\">https://ecloud.10086.cn/api/page/lb-console-manage-web/CIDC-RP-29/elb/instancelist</a>"
|
||||
},
|
||||
"cmcccloud_vlb_snidomain": {
|
||||
"label": "移动云 VLB 扩展域名(可选)",
|
||||
"placeholder": "请输入移动云 VLB 扩展域名",
|
||||
"help": "提示:不填写时,将替换监听器的默认证书;否则,将替换扩展域名证书。"
|
||||
},
|
||||
"cpanel_deploy_target": {
|
||||
"option": {
|
||||
"website": {
|
||||
|
||||
Reference in New Issue
Block a user