mirror of
https://github.com/woodchen-ink/certimate.git
synced 2025-07-18 09:21:56 +08:00
feat: new deployment provider: ctcccloud elb
This commit is contained in:
parent
5d6bc03f21
commit
898311c6e5
@ -46,6 +46,7 @@ import (
|
||||
pCTCCCloudAO "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/ctcccloud-ao"
|
||||
pCTCCCloudCDN "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/ctcccloud-cdn"
|
||||
pCTCCCloudCMS "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/ctcccloud-cms"
|
||||
pCTCCCloudELB "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/ctcccloud-elb"
|
||||
pCTCCCloudICDN "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/ctcccloud-icdn"
|
||||
pCTCCCloudLVDN "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/ctcccloud-lvdn"
|
||||
pDogeCDN "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/dogecloud-cdn"
|
||||
@ -626,7 +627,7 @@ func createDeployerProvider(options *deployerProviderOptions) (deployer.Deployer
|
||||
return deployer, err
|
||||
}
|
||||
|
||||
case domain.DeploymentProviderTypeCTCCCloudAO, domain.DeploymentProviderTypeCTCCCloudCDN, domain.DeploymentProviderTypeCTCCCloudCMS, domain.DeploymentProviderTypeCTCCCloudICDN, domain.DeploymentProviderTypeCTCCCloudLVDN:
|
||||
case domain.DeploymentProviderTypeCTCCCloudAO, domain.DeploymentProviderTypeCTCCCloudCDN, domain.DeploymentProviderTypeCTCCCloudCMS, domain.DeploymentProviderTypeCTCCCloudELB, domain.DeploymentProviderTypeCTCCCloudICDN, domain.DeploymentProviderTypeCTCCCloudLVDN:
|
||||
{
|
||||
access := domain.AccessConfigForCTCCCloud{}
|
||||
if err := maputil.Populate(options.ProviderAccessConfig, &access); err != nil {
|
||||
@ -657,6 +658,17 @@ func createDeployerProvider(options *deployerProviderOptions) (deployer.Deployer
|
||||
})
|
||||
return deployer, err
|
||||
|
||||
case domain.DeploymentProviderTypeCTCCCloudELB:
|
||||
deployer, err := pCTCCCloudELB.NewDeployer(&pCTCCCloudELB.DeployerConfig{
|
||||
AccessKeyId: access.AccessKeyId,
|
||||
SecretAccessKey: access.SecretAccessKey,
|
||||
RegionId: maputil.GetString(options.ProviderServiceConfig, "regionId"),
|
||||
ResourceType: pCTCCCloudELB.ResourceType(maputil.GetString(options.ProviderServiceConfig, "resourceType")),
|
||||
LoadbalancerId: maputil.GetString(options.ProviderServiceConfig, "loadbalancerId"),
|
||||
ListenerId: maputil.GetString(options.ProviderServiceConfig, "listenerId"),
|
||||
})
|
||||
return deployer, err
|
||||
|
||||
case domain.DeploymentProviderTypeCTCCCloudICDN:
|
||||
deployer, err := pCTCCCloudICDN.NewDeployer(&pCTCCCloudICDN.DeployerConfig{
|
||||
AccessKeyId: access.AccessKeyId,
|
||||
|
@ -218,7 +218,7 @@ const (
|
||||
DeploymentProviderTypeCTCCCloudAO = DeploymentProviderType(AccessProviderTypeCTCCCloud + "-ao")
|
||||
DeploymentProviderTypeCTCCCloudCDN = DeploymentProviderType(AccessProviderTypeCTCCCloud + "-cdn")
|
||||
DeploymentProviderTypeCTCCCloudCMS = DeploymentProviderType(AccessProviderTypeCTCCCloud + "-cms")
|
||||
DeploymentProviderTypeCTCCCloudELB = DeploymentProviderType(AccessProviderTypeCTCCCloud + "-elb") // (预留)
|
||||
DeploymentProviderTypeCTCCCloudELB = DeploymentProviderType(AccessProviderTypeCTCCCloud + "-elb")
|
||||
DeploymentProviderTypeCTCCCloudICDN = DeploymentProviderType(AccessProviderTypeCTCCCloud + "-icdn")
|
||||
DeploymentProviderTypeCTCCCloudLVDN = DeploymentProviderType(AccessProviderTypeCTCCCloud + "-ldvn")
|
||||
DeploymentProviderTypeDogeCloudCDN = DeploymentProviderType(AccessProviderTypeDogeCloud + "-cdn")
|
||||
|
10
internal/pkg/core/deployer/providers/ctcccloud-elb/consts.go
Normal file
10
internal/pkg/core/deployer/providers/ctcccloud-elb/consts.go
Normal file
@ -0,0 +1,10 @@
|
||||
package ctcccloudelb
|
||||
|
||||
type ResourceType string
|
||||
|
||||
const (
|
||||
// 资源类型:部署到指定负载均衡器。
|
||||
RESOURCE_TYPE_LOADBALANCER = ResourceType("loadbalancer")
|
||||
// 资源类型:部署到指定监听器。
|
||||
RESOURCE_TYPE_LISTENER = ResourceType("listener")
|
||||
)
|
@ -0,0 +1,199 @@
|
||||
package ctcccloudelb
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"log/slog"
|
||||
"strings"
|
||||
|
||||
"github.com/usual2970/certimate/internal/pkg/core/deployer"
|
||||
"github.com/usual2970/certimate/internal/pkg/core/uploader"
|
||||
uploadersp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/ctcccloud-elb"
|
||||
ctyunelb "github.com/usual2970/certimate/internal/pkg/sdk3rd/ctyun/elb"
|
||||
typeutil "github.com/usual2970/certimate/internal/pkg/utils/type"
|
||||
)
|
||||
|
||||
type DeployerConfig struct {
|
||||
// 天翼云 AccessKeyId。
|
||||
AccessKeyId string `json:"accessKeyId"`
|
||||
// 天翼云 SecretAccessKey。
|
||||
SecretAccessKey string `json:"secretAccessKey"`
|
||||
// 天翼云资源池 ID。
|
||||
RegionId string `json:"regionId"`
|
||||
// 部署资源类型。
|
||||
ResourceType ResourceType `json:"resourceType"`
|
||||
// 负载均衡实例 ID。
|
||||
// 部署资源类型为 [RESOURCE_TYPE_LOADBALANCER] 时必填。
|
||||
LoadbalancerId string `json:"loadbalancerId,omitempty"`
|
||||
// 负载均衡监听器 ID。
|
||||
// 部署资源类型为 [RESOURCE_TYPE_LISTENER] 时必填。
|
||||
ListenerId string `json:"listenerId,omitempty"`
|
||||
}
|
||||
|
||||
type DeployerProvider struct {
|
||||
config *DeployerConfig
|
||||
logger *slog.Logger
|
||||
sdkClient *ctyunelb.Client
|
||||
sslUploader uploader.Uploader
|
||||
}
|
||||
|
||||
var _ deployer.Deployer = (*DeployerProvider)(nil)
|
||||
|
||||
func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) {
|
||||
if config == nil {
|
||||
panic("config is nil")
|
||||
}
|
||||
|
||||
client, err := createSdkClient(config.AccessKeyId, config.SecretAccessKey)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to create sdk client: %w", err)
|
||||
}
|
||||
|
||||
uploader, err := uploadersp.NewUploader(&uploadersp.UploaderConfig{
|
||||
AccessKeyId: config.AccessKeyId,
|
||||
SecretAccessKey: config.SecretAccessKey,
|
||||
RegionId: config.RegionId,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to create ssl uploader: %w", err)
|
||||
}
|
||||
|
||||
return &DeployerProvider{
|
||||
config: config,
|
||||
logger: slog.Default(),
|
||||
sdkClient: client,
|
||||
sslUploader: uploader,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (d *DeployerProvider) WithLogger(logger *slog.Logger) deployer.Deployer {
|
||||
if logger == nil {
|
||||
d.logger = slog.New(slog.DiscardHandler)
|
||||
} else {
|
||||
d.logger = logger
|
||||
}
|
||||
return d
|
||||
}
|
||||
|
||||
func (d *DeployerProvider) Deploy(ctx context.Context, certPEM string, privkeyPEM string) (*deployer.DeployResult, error) {
|
||||
// 上传证书到 ELB
|
||||
upres, err := d.sslUploader.Upload(ctx, certPEM, privkeyPEM)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to upload certificate file: %w", err)
|
||||
} else {
|
||||
d.logger.Info("ssl certificate uploaded", slog.Any("result", upres))
|
||||
}
|
||||
|
||||
// 根据部署资源类型决定部署方式
|
||||
switch d.config.ResourceType {
|
||||
case RESOURCE_TYPE_LOADBALANCER:
|
||||
if err := d.deployToLoadbalancer(ctx, upres.CertId); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
case RESOURCE_TYPE_LISTENER:
|
||||
if err := d.deployToListener(ctx, upres.CertId); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
default:
|
||||
return nil, fmt.Errorf("unsupported resource type '%s'", d.config.ResourceType)
|
||||
}
|
||||
|
||||
return &deployer.DeployResult{}, nil
|
||||
}
|
||||
|
||||
func (d *DeployerProvider) deployToLoadbalancer(ctx context.Context, cloudCertId string) error {
|
||||
if d.config.LoadbalancerId == "" {
|
||||
return errors.New("config `loadbalancerId` is required")
|
||||
}
|
||||
|
||||
// 查询监听列表
|
||||
// REF: https://eop.ctyun.cn/ebp/ctapiDocument/search?sid=24&api=5654&data=88&isNormal=1&vid=82
|
||||
listenerIds := make([]string, 0)
|
||||
for {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return ctx.Err()
|
||||
default:
|
||||
}
|
||||
|
||||
listListenerReq := &ctyunelb.ListListenerRequest{
|
||||
RegionID: typeutil.ToPtr(d.config.RegionId),
|
||||
LoadBalancerID: typeutil.ToPtr(d.config.LoadbalancerId),
|
||||
}
|
||||
listListenerResp, err := d.sdkClient.ListListener(listListenerReq)
|
||||
d.logger.Debug("sdk request 'elb.ListListener'", slog.Any("request", listListenerReq), slog.Any("response", listListenerResp))
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to execute sdk request 'elb.ListListener': %w", err)
|
||||
}
|
||||
|
||||
for _, listener := range listListenerResp.ReturnObj {
|
||||
if strings.EqualFold(listener.Protocol, "HTTPS") {
|
||||
listenerIds = append(listenerIds, listener.ID)
|
||||
}
|
||||
}
|
||||
|
||||
break
|
||||
}
|
||||
|
||||
// 遍历更新监听证书
|
||||
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 *DeployerProvider) deployToListener(ctx context.Context, cloudCertId string) error {
|
||||
if d.config.ListenerId == "" {
|
||||
return errors.New("config `listenerId` is required")
|
||||
}
|
||||
|
||||
// 更新监听
|
||||
if err := d.updateListenerCertificate(ctx, d.config.ListenerId, cloudCertId); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *DeployerProvider) 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{
|
||||
RegionID: typeutil.ToPtr(d.config.RegionId),
|
||||
ListenerID: typeutil.ToPtr(cloudListenerId),
|
||||
CertificateID: typeutil.ToPtr(cloudCertId),
|
||||
}
|
||||
setLoadBalancerHTTPSListenerAttributeResp, err := d.sdkClient.UpdateListener(setLoadBalancerHTTPSListenerAttributeReq)
|
||||
d.logger.Debug("sdk request 'elb.UpdateListener'", slog.Any("request", setLoadBalancerHTTPSListenerAttributeReq), slog.Any("response", setLoadBalancerHTTPSListenerAttributeResp))
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to execute sdk request 'elb.UpdateListener': %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func createSdkClient(accessKeyId, secretAccessKey string) (*ctyunelb.Client, error) {
|
||||
return ctyunelb.NewClient(accessKeyId, secretAccessKey)
|
||||
}
|
@ -0,0 +1,118 @@
|
||||
package ctcccloudelb_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
provider "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/ctcccloud-elb"
|
||||
)
|
||||
|
||||
var (
|
||||
fInputCertPath string
|
||||
fInputKeyPath string
|
||||
fAccessKeyId string
|
||||
fSecretAccessKey string
|
||||
fRegionId string
|
||||
fLoadbalancerId string
|
||||
fListenerId string
|
||||
)
|
||||
|
||||
func init() {
|
||||
argsPrefix := "CERTIMATE_DEPLOYER_CTCCCLOUDELB_"
|
||||
|
||||
flag.StringVar(&fInputCertPath, argsPrefix+"INPUTCERTPATH", "", "")
|
||||
flag.StringVar(&fInputKeyPath, argsPrefix+"INPUTKEYPATH", "", "")
|
||||
flag.StringVar(&fAccessKeyId, argsPrefix+"ACCESSKEYID", "", "")
|
||||
flag.StringVar(&fSecretAccessKey, argsPrefix+"SECRETACCESSKEY", "", "")
|
||||
flag.StringVar(&fRegionId, argsPrefix+"REGIONID", "", "")
|
||||
flag.StringVar(&fLoadbalancerId, argsPrefix+"LOADBALANCERID", "", "")
|
||||
flag.StringVar(&fListenerId, argsPrefix+"LISTENERID", "", "")
|
||||
}
|
||||
|
||||
/*
|
||||
Shell command to run this test:
|
||||
|
||||
go test -v ./ctcccloud_elb_test.go -args \
|
||||
--CERTIMATE_DEPLOYER_CTCCCLOUDELB_INPUTCERTPATH="/path/to/your-input-cert.pem" \
|
||||
--CERTIMATE_DEPLOYER_CTCCCLOUDELB_INPUTKEYPATH="/path/to/your-input-key.pem" \
|
||||
--CERTIMATE_DEPLOYER_CTCCCLOUDELB_ACCESSKEYID="your-access-key-id" \
|
||||
--CERTIMATE_DEPLOYER_CTCCCLOUDELB_SECRETACCESSKEY="your-secret-access-key" \
|
||||
--CERTIMATE_DEPLOYER_CTCCCLOUDELB_REGIONID="your-region-id" \
|
||||
--CERTIMATE_DEPLOYER_CTCCCLOUDELB_LOADBALANCERID="your-elb-instance-id" \
|
||||
--CERTIMATE_DEPLOYER_CTCCCLOUDELB_LISTENERID="your-elb-listener-id"
|
||||
*/
|
||||
func TestDeploy(t *testing.T) {
|
||||
flag.Parse()
|
||||
|
||||
t.Run("Deploy_ToLoadbalancer", func(t *testing.T) {
|
||||
t.Log(strings.Join([]string{
|
||||
"args:",
|
||||
fmt.Sprintf("INPUTCERTPATH: %v", fInputCertPath),
|
||||
fmt.Sprintf("INPUTKEYPATH: %v", fInputKeyPath),
|
||||
fmt.Sprintf("ACCESSKEYID: %v", fAccessKeyId),
|
||||
fmt.Sprintf("SECRETACCESSKEY: %v", fSecretAccessKey),
|
||||
fmt.Sprintf("REGIONID: %v", fRegionId),
|
||||
fmt.Sprintf("LOADBALANCERID: %v", fLoadbalancerId),
|
||||
}, "\n"))
|
||||
|
||||
deployer, err := provider.NewDeployer(&provider.DeployerConfig{
|
||||
AccessKeyId: fAccessKeyId,
|
||||
SecretAccessKey: fSecretAccessKey,
|
||||
RegionId: fRegionId,
|
||||
ResourceType: provider.RESOURCE_TYPE_LOADBALANCER,
|
||||
LoadbalancerId: fLoadbalancerId,
|
||||
})
|
||||
if err != nil {
|
||||
t.Errorf("err: %+v", err)
|
||||
return
|
||||
}
|
||||
|
||||
fInputCertData, _ := os.ReadFile(fInputCertPath)
|
||||
fInputKeyData, _ := os.ReadFile(fInputKeyPath)
|
||||
res, err := deployer.Deploy(context.Background(), string(fInputCertData), string(fInputKeyData))
|
||||
if err != nil {
|
||||
t.Errorf("err: %+v", err)
|
||||
return
|
||||
}
|
||||
|
||||
t.Logf("ok: %v", res)
|
||||
})
|
||||
|
||||
t.Run("Deploy_ToListener", func(t *testing.T) {
|
||||
t.Log(strings.Join([]string{
|
||||
"args:",
|
||||
fmt.Sprintf("INPUTCERTPATH: %v", fInputCertPath),
|
||||
fmt.Sprintf("INPUTKEYPATH: %v", fInputKeyPath),
|
||||
fmt.Sprintf("ACCESSKEYID: %v", fAccessKeyId),
|
||||
fmt.Sprintf("SECRETACCESSKEY: %v", fSecretAccessKey),
|
||||
fmt.Sprintf("REGIONID: %v", fRegionId),
|
||||
fmt.Sprintf("LISTENERID: %v", fListenerId),
|
||||
}, "\n"))
|
||||
|
||||
deployer, err := provider.NewDeployer(&provider.DeployerConfig{
|
||||
AccessKeyId: fAccessKeyId,
|
||||
SecretAccessKey: fSecretAccessKey,
|
||||
RegionId: fRegionId,
|
||||
ResourceType: provider.RESOURCE_TYPE_LISTENER,
|
||||
ListenerId: fListenerId,
|
||||
})
|
||||
if err != nil {
|
||||
t.Errorf("err: %+v", err)
|
||||
return
|
||||
}
|
||||
|
||||
fInputCertData, _ := os.ReadFile(fInputCertPath)
|
||||
fInputKeyData, _ := os.ReadFile(fInputKeyPath)
|
||||
res, err := deployer.Deploy(context.Background(), string(fInputCertData), string(fInputKeyData))
|
||||
if err != nil {
|
||||
t.Errorf("err: %+v", err)
|
||||
return
|
||||
}
|
||||
|
||||
t.Logf("ok: %v", res)
|
||||
})
|
||||
}
|
@ -0,0 +1,133 @@
|
||||
package ctcccloudelb
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"log/slog"
|
||||
"time"
|
||||
|
||||
"github.com/google/uuid"
|
||||
|
||||
"github.com/usual2970/certimate/internal/pkg/core/uploader"
|
||||
ctyunelb "github.com/usual2970/certimate/internal/pkg/sdk3rd/ctyun/elb"
|
||||
certutil "github.com/usual2970/certimate/internal/pkg/utils/cert"
|
||||
typeutil "github.com/usual2970/certimate/internal/pkg/utils/type"
|
||||
)
|
||||
|
||||
type UploaderConfig struct {
|
||||
// 天翼云 AccessKeyId。
|
||||
AccessKeyId string `json:"accessKeyId"`
|
||||
// 天翼云 SecretAccessKey。
|
||||
SecretAccessKey string `json:"secretAccessKey"`
|
||||
// 天翼云资源池 ID。
|
||||
RegionId string `json:"regionId"`
|
||||
}
|
||||
|
||||
type UploaderProvider struct {
|
||||
config *UploaderConfig
|
||||
logger *slog.Logger
|
||||
sdkClient *ctyunelb.Client
|
||||
}
|
||||
|
||||
var _ uploader.Uploader = (*UploaderProvider)(nil)
|
||||
|
||||
func NewUploader(config *UploaderConfig) (*UploaderProvider, error) {
|
||||
if config == nil {
|
||||
panic("config is nil")
|
||||
}
|
||||
|
||||
client, err := createSdkClient(config.AccessKeyId, config.SecretAccessKey)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to create sdk client: %w", err)
|
||||
}
|
||||
|
||||
return &UploaderProvider{
|
||||
config: config,
|
||||
logger: slog.Default(),
|
||||
sdkClient: client,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (u *UploaderProvider) WithLogger(logger *slog.Logger) uploader.Uploader {
|
||||
if logger == nil {
|
||||
u.logger = slog.New(slog.DiscardHandler)
|
||||
} else {
|
||||
u.logger = logger
|
||||
}
|
||||
return u
|
||||
}
|
||||
|
||||
func (u *UploaderProvider) Upload(ctx context.Context, certPEM string, privkeyPEM string) (*uploader.UploadResult, error) {
|
||||
// 解析证书内容
|
||||
certX509, err := certutil.ParseCertificateFromPEM(certPEM)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 查询证书列表,避免重复上传
|
||||
// REF: https://eop.ctyun.cn/ebp/ctapiDocument/search?sid=24&api=5692&data=88&isNormal=1&vid=82
|
||||
listCertificateReq := &ctyunelb.ListCertificateRequest{
|
||||
RegionID: typeutil.ToPtr(u.config.RegionId),
|
||||
}
|
||||
listCertificateResp, err := u.sdkClient.ListCertificate(listCertificateReq)
|
||||
u.logger.Debug("sdk request 'elb.ListCertificate'", slog.Any("request", listCertificateReq), slog.Any("response", listCertificateResp))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to execute sdk request 'elb.ListCertificate': %w", err)
|
||||
} else {
|
||||
for _, certRecord := range listCertificateResp.ReturnObj {
|
||||
var isSameCert bool
|
||||
if certRecord.Certificate == certPEM {
|
||||
isSameCert = true
|
||||
} else {
|
||||
oldCertX509, err := certutil.ParseCertificateFromPEM(certRecord.Certificate)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
isSameCert = certutil.EqualCertificate(certX509, oldCertX509)
|
||||
}
|
||||
|
||||
// 如果已存在相同证书,直接返回
|
||||
if isSameCert {
|
||||
u.logger.Info("ssl certificate already exists")
|
||||
return &uploader.UploadResult{
|
||||
CertId: certRecord.ID,
|
||||
CertName: certRecord.Name,
|
||||
}, nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 生成新证书名(需符合天翼云命名规则)
|
||||
certName := fmt.Sprintf("certimate-%d", time.Now().UnixMilli())
|
||||
|
||||
// 创建证书
|
||||
// REF: https://eop.ctyun.cn/ebp/ctapiDocument/search?sid=24&api=5685&data=88&isNormal=1&vid=82
|
||||
createCertificateReq := &ctyunelb.CreateCertificateRequest{
|
||||
ClientToken: typeutil.ToPtr(generateClientToken()),
|
||||
RegionID: typeutil.ToPtr(u.config.RegionId),
|
||||
Name: typeutil.ToPtr(certName),
|
||||
Description: typeutil.ToPtr("upload from certimate"),
|
||||
Type: typeutil.ToPtr("Server"),
|
||||
Certificate: typeutil.ToPtr(certPEM),
|
||||
PrivateKey: typeutil.ToPtr(privkeyPEM),
|
||||
}
|
||||
createCertificateResp, err := u.sdkClient.CreateCertificate(createCertificateReq)
|
||||
u.logger.Debug("sdk request 'elb.CreateCertificate'", slog.Any("request", createCertificateReq), slog.Any("response", createCertificateResp))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to execute sdk request 'elb.CreateCertificate': %w", err)
|
||||
}
|
||||
|
||||
return &uploader.UploadResult{
|
||||
CertId: createCertificateResp.ReturnObj.ID,
|
||||
CertName: certName,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func createSdkClient(accessKeyId, secretAccessKey string) (*ctyunelb.Client, error) {
|
||||
return ctyunelb.NewClient(accessKeyId, secretAccessKey)
|
||||
}
|
||||
|
||||
func generateClientToken() string {
|
||||
return uuid.New().String()
|
||||
}
|
@ -0,0 +1,77 @@
|
||||
package ctcccloudelb_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
provider "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/ctcccloud-elb"
|
||||
)
|
||||
|
||||
var (
|
||||
fInputCertPath string
|
||||
fInputKeyPath string
|
||||
fAccessKeyId string
|
||||
fSecretAccessKey string
|
||||
fRegionId string
|
||||
)
|
||||
|
||||
func init() {
|
||||
argsPrefix := "CERTIMATE_UPLOADER_CTCCCLOUDELB_"
|
||||
|
||||
flag.StringVar(&fInputCertPath, argsPrefix+"INPUTCERTPATH", "", "")
|
||||
flag.StringVar(&fInputKeyPath, argsPrefix+"INPUTKEYPATH", "", "")
|
||||
flag.StringVar(&fAccessKeyId, argsPrefix+"ACCESSKEYID", "", "")
|
||||
flag.StringVar(&fSecretAccessKey, argsPrefix+"SECRETACCESSKEY", "", "")
|
||||
flag.StringVar(&fRegionId, argsPrefix+"REGIONID", "", "")
|
||||
}
|
||||
|
||||
/*
|
||||
Shell command to run this test:
|
||||
|
||||
go test -v ./ctcccloud_elb_test.go -args \
|
||||
--CERTIMATE_UPLOADER_CTCCCLOUDELB_INPUTCERTPATH="/path/to/your-input-cert.pem" \
|
||||
--CERTIMATE_UPLOADER_CTCCCLOUDELB_INPUTKEYPATH="/path/to/your-input-key.pem" \
|
||||
--CERTIMATE_UPLOADER_CTCCCLOUDELB_ACCESSKEYID="your-access-key-id" \
|
||||
--CERTIMATE_UPLOADER_CTCCCLOUDELB_SECRETACCESSKEY="your-secret-access-key" \
|
||||
--CERTIMATE_UPLOADER_CTCCCLOUDELB_REGIONID="your-region-id"
|
||||
*/
|
||||
func TestDeploy(t *testing.T) {
|
||||
flag.Parse()
|
||||
|
||||
t.Run("Deploy", func(t *testing.T) {
|
||||
t.Log(strings.Join([]string{
|
||||
"args:",
|
||||
fmt.Sprintf("INPUTCERTPATH: %v", fInputCertPath),
|
||||
fmt.Sprintf("INPUTKEYPATH: %v", fInputKeyPath),
|
||||
fmt.Sprintf("ACCESSKEYID: %v", fAccessKeyId),
|
||||
fmt.Sprintf("SECRETACCESSKEY: %v", fSecretAccessKey),
|
||||
fmt.Sprintf("REGIONID: %v", fRegionId),
|
||||
}, "\n"))
|
||||
|
||||
uploader, err := provider.NewUploader(&provider.UploaderConfig{
|
||||
AccessKeyId: fAccessKeyId,
|
||||
SecretAccessKey: fSecretAccessKey,
|
||||
RegionId: fRegionId,
|
||||
})
|
||||
if err != nil {
|
||||
t.Errorf("err: %+v", err)
|
||||
return
|
||||
}
|
||||
|
||||
fInputCertData, _ := os.ReadFile(fInputCertPath)
|
||||
fInputKeyData, _ := os.ReadFile(fInputKeyPath)
|
||||
res, err := uploader.Upload(context.Background(), string(fInputCertData), string(fInputKeyData))
|
||||
if err != nil {
|
||||
t.Errorf("err: %+v", err)
|
||||
return
|
||||
}
|
||||
|
||||
sres, _ := json.Marshal(res)
|
||||
t.Logf("ok: %s", string(sres))
|
||||
})
|
||||
}
|
45
internal/pkg/sdk3rd/ctyun/elb/api_create_certificate.go
Normal file
45
internal/pkg/sdk3rd/ctyun/elb/api_create_certificate.go
Normal file
@ -0,0 +1,45 @@
|
||||
package elb
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
type CreateCertificateRequest struct {
|
||||
ClientToken *string `json:"clientToken,omitempty"`
|
||||
RegionID *string `json:"regionID,omitempty"`
|
||||
Name *string `json:"name,omitempty"`
|
||||
Description *string `json:"description,omitempty"`
|
||||
Type *string `json:"type,omitempty"`
|
||||
Certificate *string `json:"certificate,omitempty"`
|
||||
PrivateKey *string `json:"privateKey,omitempty"`
|
||||
}
|
||||
|
||||
type CreateCertificateResponse struct {
|
||||
baseResult
|
||||
|
||||
ReturnObj *struct {
|
||||
ID string `json:"id"`
|
||||
} `json:"returnObj,omitempty"`
|
||||
}
|
||||
|
||||
func (c *Client) CreateCertificate(req *CreateCertificateRequest) (*CreateCertificateResponse, error) {
|
||||
return c.CreateCertificateWithContext(context.Background(), req)
|
||||
}
|
||||
|
||||
func (c *Client) CreateCertificateWithContext(ctx context.Context, req *CreateCertificateRequest) (*CreateCertificateResponse, error) {
|
||||
httpreq, err := c.newRequest(http.MethodPost, "/v4/elb/create-certificate")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
httpreq.SetBody(req)
|
||||
httpreq.SetContext(ctx)
|
||||
}
|
||||
|
||||
result := &CreateCertificateResponse{}
|
||||
if _, err := c.doRequestWithResult(httpreq, result); err != nil {
|
||||
return result, err
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
56
internal/pkg/sdk3rd/ctyun/elb/api_list_certificate.go
Normal file
56
internal/pkg/sdk3rd/ctyun/elb/api_list_certificate.go
Normal file
@ -0,0 +1,56 @@
|
||||
package elb
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
type ListCertificateRequest struct {
|
||||
ClientToken *string `json:"clientToken,omitempty"`
|
||||
RegionID *string `json:"regionID,omitempty"`
|
||||
IDs *string `json:"IDs,omitempty"`
|
||||
Name *string `json:"name,omitempty"`
|
||||
Type *string `json:"type,omitempty"`
|
||||
}
|
||||
|
||||
type ListCertificateResponse struct {
|
||||
baseResult
|
||||
|
||||
ReturnObj []*CertificateRecord `json:"returnObj,omitempty"`
|
||||
}
|
||||
|
||||
func (c *Client) ListCertificate(req *ListCertificateRequest) (*ListCertificateResponse, error) {
|
||||
return c.ListCertificateWithContext(context.Background(), req)
|
||||
}
|
||||
|
||||
func (c *Client) ListCertificateWithContext(ctx context.Context, req *ListCertificateRequest) (*ListCertificateResponse, error) {
|
||||
httpreq, err := c.newRequest(http.MethodGet, "/v4/elb/list-certificate")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
if req.ClientToken != nil {
|
||||
httpreq.SetQueryParam("clientToken", *req.ClientToken)
|
||||
}
|
||||
if req.RegionID != nil {
|
||||
httpreq.SetQueryParam("regionID", *req.RegionID)
|
||||
}
|
||||
if req.IDs != nil {
|
||||
httpreq.SetQueryParam("IDs", *req.IDs)
|
||||
}
|
||||
if req.Name != nil {
|
||||
httpreq.SetQueryParam("name", *req.Name)
|
||||
}
|
||||
if req.Type != nil {
|
||||
httpreq.SetQueryParam("type", *req.Type)
|
||||
}
|
||||
|
||||
httpreq.SetContext(ctx)
|
||||
}
|
||||
|
||||
result := &ListCertificateResponse{}
|
||||
if _, err := c.doRequestWithResult(httpreq, result); err != nil {
|
||||
return result, err
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
64
internal/pkg/sdk3rd/ctyun/elb/api_list_listener.go
Normal file
64
internal/pkg/sdk3rd/ctyun/elb/api_list_listener.go
Normal file
@ -0,0 +1,64 @@
|
||||
package elb
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
type ListListenerRequest struct {
|
||||
ClientToken *string `json:"clientToken,omitempty"`
|
||||
RegionID *string `json:"regionID,omitempty"`
|
||||
ProjectID *string `json:"projectID,omitempty"`
|
||||
IDs *string `json:"IDs,omitempty"`
|
||||
Name *string `json:"name,omitempty"`
|
||||
LoadBalancerID *string `json:"loadBalancerID,omitempty"`
|
||||
AccessControlID *string `json:"accessControlID,omitempty"`
|
||||
}
|
||||
|
||||
type ListListenerResponse struct {
|
||||
baseResult
|
||||
|
||||
ReturnObj []*ListenerRecord `json:"returnObj,omitempty"`
|
||||
}
|
||||
|
||||
func (c *Client) ListListener(req *ListListenerRequest) (*ListListenerResponse, error) {
|
||||
return c.ListListenerWithContext(context.Background(), req)
|
||||
}
|
||||
|
||||
func (c *Client) ListListenerWithContext(ctx context.Context, req *ListListenerRequest) (*ListListenerResponse, error) {
|
||||
httpreq, err := c.newRequest(http.MethodGet, "/v4/elb/list-listener")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
if req.ClientToken != nil {
|
||||
httpreq.SetQueryParam("clientToken", *req.ClientToken)
|
||||
}
|
||||
if req.RegionID != nil {
|
||||
httpreq.SetQueryParam("regionID", *req.RegionID)
|
||||
}
|
||||
if req.ProjectID != nil {
|
||||
httpreq.SetQueryParam("projectID", *req.ProjectID)
|
||||
}
|
||||
if req.IDs != nil {
|
||||
httpreq.SetQueryParam("IDs", *req.IDs)
|
||||
}
|
||||
if req.Name != nil {
|
||||
httpreq.SetQueryParam("name", *req.Name)
|
||||
}
|
||||
if req.LoadBalancerID != nil {
|
||||
httpreq.SetQueryParam("loadBalancerID", *req.LoadBalancerID)
|
||||
}
|
||||
if req.LoadBalancerID != nil {
|
||||
httpreq.SetQueryParam("accessControlID", *req.AccessControlID)
|
||||
}
|
||||
|
||||
httpreq.SetContext(ctx)
|
||||
}
|
||||
|
||||
result := &ListListenerResponse{}
|
||||
if _, err := c.doRequestWithResult(httpreq, result); err != nil {
|
||||
return result, err
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
48
internal/pkg/sdk3rd/ctyun/elb/api_show_listener.go
Normal file
48
internal/pkg/sdk3rd/ctyun/elb/api_show_listener.go
Normal file
@ -0,0 +1,48 @@
|
||||
package elb
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
type ShowListenerRequest struct {
|
||||
ClientToken *string `json:"clientToken,omitempty"`
|
||||
RegionID *string `json:"regionID,omitempty"`
|
||||
ListenerID *string `json:"listenerID,omitempty"`
|
||||
}
|
||||
|
||||
type ShowListenerResponse struct {
|
||||
baseResult
|
||||
|
||||
ReturnObj []*ListenerRecord `json:"returnObj,omitempty"`
|
||||
}
|
||||
|
||||
func (c *Client) ShowListener(req *ShowListenerRequest) (*ShowListenerResponse, error) {
|
||||
return c.ShowListenerWithContext(context.Background(), req)
|
||||
}
|
||||
|
||||
func (c *Client) ShowListenerWithContext(ctx context.Context, req *ShowListenerRequest) (*ShowListenerResponse, error) {
|
||||
httpreq, err := c.newRequest(http.MethodGet, "/v4/elb/show-listener")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
if req.ClientToken != nil {
|
||||
httpreq.SetQueryParam("clientToken", *req.ClientToken)
|
||||
}
|
||||
if req.RegionID != nil {
|
||||
httpreq.SetQueryParam("regionID", *req.RegionID)
|
||||
}
|
||||
if req.ListenerID != nil {
|
||||
httpreq.SetQueryParam("listenerID", *req.ListenerID)
|
||||
}
|
||||
|
||||
httpreq.SetContext(ctx)
|
||||
}
|
||||
|
||||
result := &ShowListenerResponse{}
|
||||
if _, err := c.doRequestWithResult(httpreq, result); err != nil {
|
||||
return result, err
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
44
internal/pkg/sdk3rd/ctyun/elb/api_update_listener.go
Normal file
44
internal/pkg/sdk3rd/ctyun/elb/api_update_listener.go
Normal file
@ -0,0 +1,44 @@
|
||||
package elb
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
type UpdateListenerRequest struct {
|
||||
ClientToken *string `json:"clientToken,omitempty"`
|
||||
RegionID *string `json:"regionID,omitempty"`
|
||||
ListenerID *string `json:"listenerID,omitempty"`
|
||||
Name *string `json:"name,omitempty"`
|
||||
Description *string `json:"description,omitempty"`
|
||||
CertificateID *string `json:"certificateID,omitempty"`
|
||||
CaEnabled *bool `json:"caEnabled,omitempty"`
|
||||
ClientCertificateID *string `json:"clientCertificateID,omitempty"`
|
||||
}
|
||||
|
||||
type UpdateListenerResponse struct {
|
||||
baseResult
|
||||
|
||||
ReturnObj []*ListenerRecord `json:"returnObj,omitempty"`
|
||||
}
|
||||
|
||||
func (c *Client) UpdateListener(req *UpdateListenerRequest) (*UpdateListenerResponse, error) {
|
||||
return c.UpdateListenerWithContext(context.Background(), req)
|
||||
}
|
||||
|
||||
func (c *Client) UpdateListenerWithContext(ctx context.Context, req *UpdateListenerRequest) (*UpdateListenerResponse, error) {
|
||||
httpreq, err := c.newRequest(http.MethodPost, "/v4/elb/update-listener")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
httpreq.SetBody(req)
|
||||
httpreq.SetContext(ctx)
|
||||
}
|
||||
|
||||
result := &UpdateListenerResponse{}
|
||||
if _, err := c.doRequestWithResult(httpreq, result); err != nil {
|
||||
return result, err
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
50
internal/pkg/sdk3rd/ctyun/elb/client.go
Normal file
50
internal/pkg/sdk3rd/ctyun/elb/client.go
Normal file
@ -0,0 +1,50 @@
|
||||
package elb
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/go-resty/resty/v2"
|
||||
"github.com/usual2970/certimate/internal/pkg/sdk3rd/ctyun/openapi"
|
||||
)
|
||||
|
||||
const endpoint = "https://ctelb-global.ctapi.ctyun.cn"
|
||||
|
||||
type Client struct {
|
||||
client *openapi.Client
|
||||
}
|
||||
|
||||
func NewClient(accessKeyId, secretAccessKey string) (*Client, error) {
|
||||
client, err := openapi.NewClient(endpoint, accessKeyId, secretAccessKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &Client{client: client}, nil
|
||||
}
|
||||
|
||||
func (c *Client) SetTimeout(timeout time.Duration) *Client {
|
||||
c.client.SetTimeout(timeout)
|
||||
return c
|
||||
}
|
||||
|
||||
func (c *Client) newRequest(method string, path string) (*resty.Request, error) {
|
||||
return c.client.NewRequest(method, path)
|
||||
}
|
||||
|
||||
func (c *Client) doRequest(request *resty.Request) (*resty.Response, error) {
|
||||
return c.client.DoRequest(request)
|
||||
}
|
||||
|
||||
func (c *Client) doRequestWithResult(request *resty.Request, result baseResultInterface) (*resty.Response, error) {
|
||||
response, err := c.client.DoRequestWithResult(request, result)
|
||||
if err == nil {
|
||||
statusCode := result.GetStatusCode()
|
||||
errorCode := result.GetError()
|
||||
if (statusCode != "" && statusCode != "200" && statusCode != "800") || (errorCode != "" && errorCode != "SUCCESS") {
|
||||
return response, fmt.Errorf("sdkerr: api error, code='%s', message='%s', errorCode='%s', description='%s'", statusCode, result.GetMessage(), result.GetMessage(), result.GetDescription())
|
||||
}
|
||||
}
|
||||
|
||||
return response, err
|
||||
}
|
104
internal/pkg/sdk3rd/ctyun/elb/types.go
Normal file
104
internal/pkg/sdk3rd/ctyun/elb/types.go
Normal file
@ -0,0 +1,104 @@
|
||||
package elb
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
type baseResultInterface interface {
|
||||
GetStatusCode() string
|
||||
GetMessage() string
|
||||
GetError() string
|
||||
GetDescription() string
|
||||
}
|
||||
|
||||
type baseResult struct {
|
||||
StatusCode json.RawMessage `json:"statusCode,omitempty"`
|
||||
Message *string `json:"message,omitempty"`
|
||||
Error *string `json:"error,omitempty"`
|
||||
Description *string `json:"description,omitempty"`
|
||||
RequestId *string `json:"requestId,omitempty"`
|
||||
}
|
||||
|
||||
func (r *baseResult) GetStatusCode() string {
|
||||
if r.StatusCode == nil {
|
||||
return ""
|
||||
}
|
||||
|
||||
decoder := json.NewDecoder(bytes.NewReader(r.StatusCode))
|
||||
token, err := decoder.Token()
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
|
||||
switch t := token.(type) {
|
||||
case string:
|
||||
return t
|
||||
case float64:
|
||||
return strconv.FormatFloat(t, 'f', -1, 64)
|
||||
case json.Number:
|
||||
return t.String()
|
||||
default:
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
||||
func (r *baseResult) GetMessage() string {
|
||||
if r.Message == nil {
|
||||
return ""
|
||||
}
|
||||
|
||||
return *r.Message
|
||||
}
|
||||
|
||||
func (r *baseResult) GetError() string {
|
||||
if r.Error == nil {
|
||||
return ""
|
||||
}
|
||||
|
||||
return *r.Error
|
||||
}
|
||||
|
||||
func (r *baseResult) GetDescription() string {
|
||||
if r.Description == nil {
|
||||
return ""
|
||||
}
|
||||
|
||||
return *r.Description
|
||||
}
|
||||
|
||||
var _ baseResultInterface = (*baseResult)(nil)
|
||||
|
||||
type CertificateRecord struct {
|
||||
ID string `json:"ID"`
|
||||
RegionID string `json:"regionID"`
|
||||
AzName string `json:"azName"`
|
||||
ProjectID string `json:"projectID"`
|
||||
Name string `json:"name"`
|
||||
Description string `json:"description"`
|
||||
Type string `json:"type"`
|
||||
Certificate string `json:"certificate"`
|
||||
PrivateKey string `json:"privateKey"`
|
||||
Status string `json:"status"`
|
||||
CreatedTime string `json:"createdTime"`
|
||||
UpdatedTime string `json:"updatedTime"`
|
||||
}
|
||||
|
||||
type ListenerRecord struct {
|
||||
ID string `json:"ID"`
|
||||
RegionID string `json:"regionID"`
|
||||
AzName string `json:"azName"`
|
||||
ProjectID string `json:"projectID"`
|
||||
Name string `json:"name"`
|
||||
Description string `json:"description"`
|
||||
LoadBalancerID string `json:"loadBalancerID"`
|
||||
Protocol string `json:"protocol"`
|
||||
ProtocolPort int32 `json:"protocolPort"`
|
||||
CertificateID string `json:"certificateID,omitempty"`
|
||||
CaEnabled bool `json:"caEnabled"`
|
||||
ClientCertificateID string `json:"clientCertificateID,omitempty"`
|
||||
Status string `json:"status"`
|
||||
CreatedTime string `json:"createdTime"`
|
||||
UpdatedTime string `json:"updatedTime"`
|
||||
}
|
@ -50,6 +50,7 @@ import DeployNodeConfigFormBytePlusCDNConfig from "./DeployNodeConfigFormBytePlu
|
||||
import DeployNodeConfigFormCdnflyConfig from "./DeployNodeConfigFormCdnflyConfig";
|
||||
import DeployNodeConfigFormCTCCCloudAOConfig from "./DeployNodeConfigFormCTCCCloudAOConfig";
|
||||
import DeployNodeConfigFormCTCCCloudCDNConfig from "./DeployNodeConfigFormCTCCCloudCDNConfig";
|
||||
import DeployNodeConfigFormCTCCCloudELBConfig from "./DeployNodeConfigFormCTCCCloudELBConfig";
|
||||
import DeployNodeConfigFormCTCCCloudICDNConfig from "./DeployNodeConfigFormCTCCCloudICDNConfig";
|
||||
import DeployNodeConfigFormCTCCCloudLVDNConfig from "./DeployNodeConfigFormCTCCCloudLVDNConfig";
|
||||
import DeployNodeConfigFormDogeCloudCDNConfig from "./DeployNodeConfigFormDogeCloudCDNConfig";
|
||||
@ -273,6 +274,8 @@ const DeployNodeConfigForm = forwardRef<DeployNodeConfigFormInstance, DeployNode
|
||||
return <DeployNodeConfigFormCTCCCloudAOConfig {...nestedFormProps} />;
|
||||
case DEPLOYMENT_PROVIDERS.CTCCCLOUD_CDN:
|
||||
return <DeployNodeConfigFormCTCCCloudCDNConfig {...nestedFormProps} />;
|
||||
case DEPLOYMENT_PROVIDERS.CTCCCLOUD_ELB:
|
||||
return <DeployNodeConfigFormCTCCCloudELBConfig {...nestedFormProps} />;
|
||||
case DEPLOYMENT_PROVIDERS.CTCCCLOUD_ICDN:
|
||||
return <DeployNodeConfigFormCTCCCloudICDNConfig {...nestedFormProps} />;
|
||||
case DEPLOYMENT_PROVIDERS.CTCCCLOUD_LVDN:
|
||||
|
@ -0,0 +1,121 @@
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Form, type FormInstance, Input, Select } from "antd";
|
||||
import { createSchemaFieldRule } from "antd-zod";
|
||||
import { z } from "zod";
|
||||
|
||||
import Show from "@/components/Show";
|
||||
|
||||
type DeployNodeConfigFormCTCCCloudELBConfigFieldValues = Nullish<{
|
||||
regionId: string;
|
||||
resourceType: string;
|
||||
loadbalancerId?: string;
|
||||
listenerId?: string;
|
||||
}>;
|
||||
|
||||
export type DeployNodeConfigFormCTCCCloudELBConfigProps = {
|
||||
form: FormInstance;
|
||||
formName: string;
|
||||
disabled?: boolean;
|
||||
initialValues?: DeployNodeConfigFormCTCCCloudELBConfigFieldValues;
|
||||
onValuesChange?: (values: DeployNodeConfigFormCTCCCloudELBConfigFieldValues) => void;
|
||||
};
|
||||
|
||||
const RESOURCE_TYPE_LOADBALANCER = "loadbalancer" as const;
|
||||
const RESOURCE_TYPE_LISTENER = "listener" as const;
|
||||
|
||||
const initFormModel = (): DeployNodeConfigFormCTCCCloudELBConfigFieldValues => {
|
||||
return {
|
||||
resourceType: RESOURCE_TYPE_LISTENER,
|
||||
};
|
||||
};
|
||||
|
||||
const DeployNodeConfigFormCTCCCloudELBConfig = ({
|
||||
form: formInst,
|
||||
formName,
|
||||
disabled,
|
||||
initialValues,
|
||||
onValuesChange,
|
||||
}: DeployNodeConfigFormCTCCCloudELBConfigProps) => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
const formSchema = z.object({
|
||||
resourceType: z.union([z.literal(RESOURCE_TYPE_LOADBALANCER), z.literal(RESOURCE_TYPE_LISTENER)], {
|
||||
message: t("workflow_node.deploy.form.ctcccloud_elb_resource_type.placeholder"),
|
||||
}),
|
||||
regionId: z
|
||||
.string({ message: t("workflow_node.deploy.form.ctcccloud_elb_region_id.placeholder") })
|
||||
.nonempty(t("workflow_node.deploy.form.ctcccloud_elb_region_id.placeholder")),
|
||||
loadbalancerId: z
|
||||
.string()
|
||||
.max(64, t("common.errmsg.string_max", { max: 64 }))
|
||||
.nullish()
|
||||
.refine((v) => fieldResourceType !== RESOURCE_TYPE_LOADBALANCER || !!v?.trim(), t("workflow_node.deploy.form.ctcccloud_elb_loadbalancer_id.placeholder")),
|
||||
listenerId: z
|
||||
.string()
|
||||
.max(64, t("common.errmsg.string_max", { max: 64 }))
|
||||
.nullish()
|
||||
.refine((v) => fieldResourceType !== RESOURCE_TYPE_LISTENER || !!v?.trim(), t("workflow_node.deploy.form.ctcccloud_elb_listener_id.placeholder")),
|
||||
});
|
||||
const formRule = createSchemaFieldRule(formSchema);
|
||||
|
||||
const fieldResourceType = Form.useWatch("resourceType", formInst);
|
||||
|
||||
const handleFormChange = (_: unknown, values: z.infer<typeof formSchema>) => {
|
||||
onValuesChange?.(values);
|
||||
};
|
||||
|
||||
return (
|
||||
<Form
|
||||
form={formInst}
|
||||
disabled={disabled}
|
||||
initialValues={initialValues ?? initFormModel()}
|
||||
layout="vertical"
|
||||
name={formName}
|
||||
onValuesChange={handleFormChange}
|
||||
>
|
||||
<Form.Item name="resourceType" label={t("workflow_node.deploy.form.ctcccloud_elb_resource_type.label")} rules={[formRule]}>
|
||||
<Select placeholder={t("workflow_node.deploy.form.ctcccloud_elb_resource_type.placeholder")}>
|
||||
<Select.Option key={RESOURCE_TYPE_LOADBALANCER} value={RESOURCE_TYPE_LOADBALANCER}>
|
||||
{t("workflow_node.deploy.form.ctcccloud_elb_resource_type.option.loadbalancer.label")}
|
||||
</Select.Option>
|
||||
<Select.Option key={RESOURCE_TYPE_LISTENER} value={RESOURCE_TYPE_LISTENER}>
|
||||
{t("workflow_node.deploy.form.ctcccloud_elb_resource_type.option.listener.label")}
|
||||
</Select.Option>
|
||||
</Select>
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
name="regionId"
|
||||
label={t("workflow_node.deploy.form.ctcccloud_elb_region_id.label")}
|
||||
rules={[formRule]}
|
||||
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.ctcccloud_elb_region_id.tooltip") }}></span>}
|
||||
>
|
||||
<Input placeholder={t("workflow_node.deploy.form.ctcccloud_elb_region_id.placeholder")} />
|
||||
</Form.Item>
|
||||
|
||||
<Show when={fieldResourceType === RESOURCE_TYPE_LOADBALANCER}>
|
||||
<Form.Item
|
||||
name="loadbalancerId"
|
||||
label={t("workflow_node.deploy.form.ctcccloud_elb_loadbalancer_id.label")}
|
||||
rules={[formRule]}
|
||||
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.ctcccloud_elb_loadbalancer_id.tooltip") }}></span>}
|
||||
>
|
||||
<Input placeholder={t("workflow_node.deploy.form.ctcccloud_elb_loadbalancer_id.placeholder")} />
|
||||
</Form.Item>
|
||||
</Show>
|
||||
|
||||
<Show when={fieldResourceType === RESOURCE_TYPE_LISTENER}>
|
||||
<Form.Item
|
||||
name="listenerId"
|
||||
label={t("workflow_node.deploy.form.ctcccloud_elb_listener_id.label")}
|
||||
rules={[formRule]}
|
||||
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.ctcccloud_elb_listener_id.tooltip") }}></span>}
|
||||
>
|
||||
<Input placeholder={t("workflow_node.deploy.form.ctcccloud_elb_listener_id.placeholder")} />
|
||||
</Form.Item>
|
||||
</Show>
|
||||
</Form>
|
||||
);
|
||||
};
|
||||
|
||||
export default DeployNodeConfigFormCTCCCloudELBConfig;
|
@ -416,6 +416,7 @@ export const DEPLOYMENT_PROVIDERS = Object.freeze({
|
||||
CTCCCLOUD_AO: `${ACCESS_PROVIDERS.CTCCCLOUD}-ao`,
|
||||
CTCCCLOUD_CDN: `${ACCESS_PROVIDERS.CTCCCLOUD}-cdn`,
|
||||
CTCCCLOUD_CMS: `${ACCESS_PROVIDERS.CTCCCLOUD}-cms`,
|
||||
CTCCCLOUD_ELB: `${ACCESS_PROVIDERS.CTCCCLOUD}-elb`,
|
||||
CTCCCLOUD_ICDN: `${ACCESS_PROVIDERS.CTCCCLOUD}-icdn`,
|
||||
CTCCCLOUD_LVDN: `${ACCESS_PROVIDERS.CTCCCLOUD}-lvdn`,
|
||||
DOGECLOUD_CDN: `${ACCESS_PROVIDERS.DOGECLOUD}-cdn`,
|
||||
@ -578,6 +579,7 @@ export const deploymentProvidersMap: Map<DeploymentProvider["type"] | string, De
|
||||
[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],
|
||||
[DEPLOYMENT_PROVIDERS.CTCCCLOUD_ELB, "provider.ctcccloud.elb", DEPLOYMENT_CATEGORIES.LOADBALANCE],
|
||||
[DEPLOYMENT_PROVIDERS.CTCCCLOUD_LVDN, "provider.ctcccloud.lvdn", DEPLOYMENT_CATEGORIES.AV],
|
||||
[DEPLOYMENT_PROVIDERS.CTCCCLOUD_CMS, "provider.ctcccloud.cms_upload", DEPLOYMENT_CATEGORIES.SSL],
|
||||
[DEPLOYMENT_PROVIDERS.RAINYUN_RCDN, "provider.rainyun.rcdn", DEPLOYMENT_CATEGORIES.CDN],
|
||||
|
@ -404,6 +404,20 @@
|
||||
"workflow_node.deploy.form.ctcccloud_cdn_domain.label": "CTCC StateCloud CDN domain",
|
||||
"workflow_node.deploy.form.ctcccloud_cdn_domain.placeholder": "Please enter CTCC StateCloud CDN domain name",
|
||||
"workflow_node.deploy.form.ctcccloud_cdn_domain.tooltip": "For more information, see <a href=\"https://cdn-console.ctyun.cn\" target=\"_blank\">https://cdn-console.ctyun.cn</a>",
|
||||
"workflow_node.deploy.form.ctcccloud_elb_resource_type.label": "Resource type",
|
||||
"workflow_node.deploy.form.ctcccloud_elb_resource_type.placeholder": "Please select resource type",
|
||||
"workflow_node.deploy.form.ctcccloud_elb_resource_type.option.certificate.label": "ELB certificate",
|
||||
"workflow_node.deploy.form.ctcccloud_elb_resource_type.option.loadbalancer.label": "ELB load balancer",
|
||||
"workflow_node.deploy.form.ctcccloud_elb_resource_type.option.listener.label": "ELB listener",
|
||||
"workflow_node.deploy.form.ctcccloud_elb_region_id.label": "CTCC StateCloud ELB region ID",
|
||||
"workflow_node.deploy.form.ctcccloud_elb_region_id.placeholder": "Please enter CTCC StateCloud ELB region ID",
|
||||
"workflow_node.deploy.form.ctcccloud_elb_region_id.tooltip": "For more information, see <a href=\"https://www.ctyun.cn/document/10026755/10196575\" target=\"_blank\">https://www.ctyun.cn/document/10026755/10196575</a>",
|
||||
"workflow_node.deploy.form.ctcccloud_elb_loadbalancer_id.label": "CTCC StateCloud ELB load balancer ID",
|
||||
"workflow_node.deploy.form.ctcccloud_elb_loadbalancer_id.placeholder": "Please enter CTCC StateCloud ELB load balancer ID",
|
||||
"workflow_node.deploy.form.ctcccloud_elb_loadbalancer_id.tooltip": "For more information, see <a href=\"https://console.ctyun.cn/network/index/#/elb/elbList\" target=\"_blank\">https://console.ctyun.cn/network/index/#/elb/elbList</a>",
|
||||
"workflow_node.deploy.form.ctcccloud_elb_listener_id.label": "CTCC StateCloud ELB listener ID",
|
||||
"workflow_node.deploy.form.ctcccloud_elb_listener_id.placeholder": "Please enter CTCC StateCloud ELB listener ID",
|
||||
"workflow_node.deploy.form.ctcccloud_elb_listener_id.tooltip": "For more information, see <a href=\"https://console.ctyun.cn/network/index/#/elb/elbList\" target=\"_blank\">https://console.ctyun.cn/network/index/#/elb/elbList</a>",
|
||||
"workflow_node.deploy.form.ctcccloud_icdn_domain.label": "CTCC StateCloud ICDN domain",
|
||||
"workflow_node.deploy.form.ctcccloud_icdn_domain.placeholder": "Please enter CTCC StateCloud ICDN domain name",
|
||||
"workflow_node.deploy.form.ctcccloud_icdn_domain.tooltip": "For more information, see <a href=\"https://cdn-console.ctyun.cn\" target=\"_blank\">https://cdn-console.ctyun.cn</a>",
|
||||
|
@ -403,6 +403,19 @@
|
||||
"workflow_node.deploy.form.ctcccloud_cdn_domain.label": "天翼云 CDN 加速域名",
|
||||
"workflow_node.deploy.form.ctcccloud_cdn_domain.placeholder": "请输入天翼云 CDN 加速域名(支持泛域名)",
|
||||
"workflow_node.deploy.form.ctcccloud_cdn_domain.tooltip": "这是什么?请参阅 <a href=\"https://cdn-console.ctyun.cn\" target=\"_blank\">https://cdn-console.ctyun.cn</a>",
|
||||
"workflow_node.deploy.form.ctcccloud_elb_resource_type.label": "证书部署方式",
|
||||
"workflow_node.deploy.form.ctcccloud_elb_resource_type.placeholder": "请选择证书部署方式",
|
||||
"workflow_node.deploy.form.ctcccloud_elb_resource_type.option.loadbalancer.label": "替换指定负载均衡器下的全部 HTTPS 监听器的证书",
|
||||
"workflow_node.deploy.form.ctcccloud_elb_resource_type.option.listener.label": "替换指定监听器的证书",
|
||||
"workflow_node.deploy.form.ctcccloud_elb_region_id.label": "天翼云 ELB 资源池 ID",
|
||||
"workflow_node.deploy.form.ctcccloud_elb_region_id.placeholder": "请输入天翼云 ELB 资源池 ID",
|
||||
"workflow_node.deploy.form.ctcccloud_elb_region_id.tooltip": "这是什么?请参阅 <a href=\"https://www.ctyun.cn/document/10026755/10196575\" target=\"_blank\">https://www.ctyun.cn/document/10026755/10196575</a>",
|
||||
"workflow_node.deploy.form.ctcccloud_elb_loadbalancer_id.label": "天翼云 ELB 负载均衡器 ID",
|
||||
"workflow_node.deploy.form.ctcccloud_elb_loadbalancer_id.placeholder": "请输入天翼云 ELB 负载均衡器 ID",
|
||||
"workflow_node.deploy.form.ctcccloud_elb_loadbalancer_id.tooltip": "这是什么?请参阅 <a href=\"https://console.ctyun.cn/network/index/#/elb/elbList\" target=\"_blank\">https://console.ctyun.cn/network/index/#/elb/elbList</a>",
|
||||
"workflow_node.deploy.form.ctcccloud_elb_listener_id.label": "天翼云 ELB 监听器 ID",
|
||||
"workflow_node.deploy.form.ctcccloud_elb_listener_id.placeholder": "请输入天翼云 ELB 监听器 ID",
|
||||
"workflow_node.deploy.form.ctcccloud_elb_listener_id.tooltip": "这是什么?请参阅 <a href=\"https://console.ctyun.cn/network/index/#/elb/elbList\" target=\"_blank\">https://console.ctyun.cn/network/index/#/elb/elbList</a>",
|
||||
"workflow_node.deploy.form.ctcccloud_icdn_domain.label": "天翼云 ICDN 加速域名",
|
||||
"workflow_node.deploy.form.ctcccloud_icdn_domain.placeholder": "请输入天翼云 ICDN 加速域名(支持泛域名)",
|
||||
"workflow_node.deploy.form.ctcccloud_icdn_domain.tooltip": "这是什么?请参阅 <a href=\"https://cdn-console.ctyun.cn\" target=\"_blank\">https://cdn-console.ctyun.cn</a>",
|
||||
|
Loading…
x
Reference in New Issue
Block a user