feat(provider): new deployment provider: tencentcloud ga2

This commit is contained in:
Fu Diwei
2026-06-11 20:13:46 +08:00
committed by RHQYZ
parent fe05eefa45
commit 8cea61eec5
27 changed files with 981 additions and 33 deletions
+2 -1
View File
@@ -67,7 +67,8 @@ require (
github.com/spf13/pflag v1.0.10
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cdn v1.3.90
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/clb v1.3.105
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.3.112
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.3.113
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/ga2 v1.3.113
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/gaap v1.3.34
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/live v1.3.103
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/scf v1.3.101
+4 -1
View File
@@ -905,8 +905,11 @@ github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.3.103/go.mod
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.3.105/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.3.107/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.3.111/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.3.112 h1:PNCN4HXHVAfG87Msvelk7Ks5MhotAXk2vqPVvfy1Epw=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.3.112/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.3.113 h1:kDwta48HDOTca5opVg66MUoSmD5gvDXKf0OFEWcnDqM=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.3.113/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/ga2 v1.3.113 h1:3bIFxCPMNzAVt3f4BKuya4egCCXf9L5DmAZxZX4UQM4=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/ga2 v1.3.113/go.mod h1:F0YNVLpyAjYLg6unFc+R873i5YUwyXE/Vlf/lidlu6s=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/gaap v1.3.34 h1:/QJeztyMC2tYPJceIoObx7LZqqgFcdDM0SQ/Wd0RtEI=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/gaap v1.3.34/go.mod h1:LiTqyLKs+CUdXeiTezJrsMcgi1RhVQ2gFuCcDxQBK9U=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/live v1.3.103 h1:fQVRiT5cGIjomdYOJiy0lWBvBO71AaUTdXSu4/u2NwM=
@@ -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/tencentcloud-ga2"
xmaps "github.com/certimate-go/certimate/pkg/utils/maps"
)
func init() {
Registries.MustRegister(domain.DeploymentProviderTypeTencentCloudGA2, func(options *ProviderFactoryOptions) (core.Deployer, error) {
credentials := domain.AccessConfigForTencentCloud{}
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{
SecretId: credentials.SecretId,
SecretKey: credentials.SecretKey,
ProjectId: credentials.ProjectId,
Endpoint: xmaps.GetString(options.ProviderExtendedConfig, "endpoint"),
DeployTarget: xmaps.GetString(options.ProviderExtendedConfig, "deployTarget"),
AcceleratorId: xmaps.GetString(options.ProviderExtendedConfig, "acceleratorId"),
ListenerId: xmaps.GetString(options.ProviderExtendedConfig, "listenerId"),
})
return provider, err
})
}
+1
View File
@@ -414,6 +414,7 @@ const (
DeploymentProviderTypeTencentCloudCSS = DeploymentProviderType(AccessProviderTypeTencentCloud + "-css")
DeploymentProviderTypeTencentCloudECDN = DeploymentProviderType(AccessProviderTypeTencentCloud + "-ecdn")
DeploymentProviderTypeTencentCloudEO = DeploymentProviderType(AccessProviderTypeTencentCloud + "-eo")
DeploymentProviderTypeTencentCloudGA2 = DeploymentProviderType(AccessProviderTypeTencentCloud + "-ga2")
DeploymentProviderTypeTencentCloudGAAP = DeploymentProviderType(AccessProviderTypeTencentCloud + "-gaap")
DeploymentProviderTypeTencentCloudSCF = DeploymentProviderType(AccessProviderTypeTencentCloud + "-scf")
DeploymentProviderTypeTencentCloudSSL = DeploymentProviderType(AccessProviderTypeTencentCloud + "-ssl")
@@ -0,0 +1,179 @@
package tencentcloudgaap
import (
"context"
"fmt"
"log/slog"
"strings"
"time"
"github.com/samber/lo"
"github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common"
"github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common/profile"
tcgaap "github.com/certimate-go/certimate/pkg/sdk3rd-trimmed/github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/gaap/v20180529"
"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 {
// 腾讯云 SecretId。
SecretId string `json:"secretId"`
// 腾讯云 SecretKey。
SecretKey string `json:"secretKey"`
// 腾讯云项目 ID。
ProjectId int64 `json:"projectId,omitempty"`
// 腾讯云接口端点。
Endpoint string `json:"endpoint,omitempty"`
}
type Certmgr struct {
config *CertmgrConfig
logger *slog.Logger
sdkClient *tcgaap.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.SecretId, config.SecretKey, config.Endpoint)
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://cloud.tencent.com/document/api/1364/98588
// REF: https://cloud.tencent.com/document/api/608/36978
describeCertificatesOffset := 0
describeCertificatesLimit := 100
for {
select {
case <-ctx.Done():
return nil, ctx.Err()
default:
}
describeCertificatesReq := tcgaap.NewDescribeCertificatesRequest()
describeCertificatesReq.CertificateType = common.Int64Ptr(2)
describeCertificatesReq.Offset = common.Uint64Ptr(uint64(describeCertificatesOffset))
describeCertificatesReq.Limit = common.Uint64Ptr(uint64(describeCertificatesLimit))
describeCertificatesResp, err := c.sdkClient.DescribeCertificatesWithContext(ctx, describeCertificatesReq)
c.logger.Debug("sdk request 'gaap.DescribeCertificates'", slog.Any("request", describeCertificatesReq), slog.Any("response", describeCertificatesResp))
if err != nil {
return nil, fmt.Errorf("failed to execute sdk request 'gaap.DescribeCertificates': %w", err)
}
for _, certItem := range describeCertificatesResp.Response.CertificateSet {
// 对比证书通用名称
if !strings.EqualFold(certX509.Subject.CommonName, lo.FromPtr(certItem.SubjectCN)) {
continue
}
// 对比证书有效期
if certX509.NotBefore.Unix() != int64(lo.FromPtr(certItem.BeginTime)) ||
certX509.NotAfter.Unix() != int64(lo.FromPtr(certItem.EndTime)) {
continue
}
// 对比证书内容
describeCertificateDetailReq := tcgaap.NewDescribeCertificateDetailRequest()
describeCertificateDetailReq.CertificateId = certItem.CertificateId
describeCertificateDetailResp, err := c.sdkClient.DescribeCertificateDetailWithContext(ctx, describeCertificateDetailReq)
c.logger.Debug("sdk request 'gaap.DescribeCertificateDetail'", slog.Any("request", describeCertificateDetailReq), slog.Any("response", describeCertificateDetailResp))
if err != nil {
return nil, fmt.Errorf("failed to execute sdk request 'gaap.DescribeCertificateDetail': %w", err)
} else {
if !xcert.EqualCertificatesFromPEM(certPEM, lo.FromPtr(describeCertificateDetailResp.Response.CertificateDetail.CertificateContent)) {
continue
}
}
// 如果以上信息都一致,则视为已存在相同证书,直接返回
c.logger.Info("ssl certificate already exists")
return &UploadResult{
CertId: lo.FromPtr(certItem.CertificateId),
CertName: lo.FromPtr(certItem.CertificateAlias),
}, nil
}
if len(describeCertificatesResp.Response.CertificateSet) < describeCertificatesLimit {
break
}
describeCertificatesOffset += describeCertificatesLimit
}
// 生成新证书名(需符合腾讯云命名规则)
certName := fmt.Sprintf("certimate_%d", time.Now().UnixMilli())
// 创建云原生网关证书
// REF: https://cloud.tencent.com/document/api/608/36980
createCertificateReq := tcgaap.NewCreateCertificateRequest()
createCertificateReq.CertificateType = common.Int64Ptr(2)
createCertificateReq.CertificateAlias = common.StringPtr(certName)
createCertificateReq.CertificateContent = common.StringPtr(certPEM)
createCertificateReq.CertificateKey = common.StringPtr(privkeyPEM)
createCertificateResp, err := c.sdkClient.CreateCertificateWithContext(ctx, createCertificateReq)
c.logger.Debug("sdk request 'gaap.CreateCertificate'", slog.Any("request", createCertificateReq), slog.Any("response", createCertificateResp))
if err != nil {
return nil, fmt.Errorf("failed to execute sdk request 'gaap.CreateCertificate': %w", err)
}
return &UploadResult{
CertId: lo.FromPtr(createCertificateResp.Response.CertificateId),
CertName: certName,
}, nil
}
func (c *Certmgr) Replace(ctx context.Context, certIdOrName string, certPEM, privkeyPEM string) (*ReplaceResult, error) {
return nil, core.ErrUnsupported
}
func createSDKClient(secretId, secretKey, endpoint string) (*tcgaap.Client, error) {
credential := common.NewCredential(secretId, secretKey)
cpf := profile.NewClientProfile()
if endpoint != "" {
cpf.HttpProfile.Endpoint = endpoint
}
client, err := tcgaap.NewClient(credential, "", cpf)
if err != nil {
return nil, err
}
return client, nil
}
@@ -0,0 +1,49 @@
package tencentcloudgaap_test
import (
"testing"
"github.com/certimate-go/certimate/pkg/core/certmgr/internal/tester"
impl "github.com/certimate-go/certimate/pkg/core/certmgr/providers/tencentcloud-gaap"
)
var (
fp = tester.Args("TENCENTCLOUDGAAP_")
fTestCertPath string
fTestKeyPath string
fSecretId string
fSecretKey string
)
func init() {
fp.DefineString(&fTestCertPath, "TESTCERTPATH")
fp.DefineString(&fTestKeyPath, "TESTKEYPATH")
fp.DefineString(&fSecretId, "SECRETID")
fp.DefineString(&fSecretKey, "SECRETKEY")
}
/*
Shell command to run this test:
go test -v ./tencentcloud_gaap_test.go -args \
--TENCENTCLOUDGAAP_TESTCERTPATH="/path/to/your-test-cert.pem" \
--TENCENTCLOUDGAAP_TESTKEYPATH="/path/to/your-test-key.pem" \
--TENCENTCLOUDGAAP_SECRETID="your-secret-id" \
--TENCENTCLOUDGAAP_SECRETKEY="your-secret-key"
*/
func TestProvider(t *testing.T) {
fp.Parse()
t.Run("Upload", func(t *testing.T) {
provider, err := impl.NewCertmgr(&impl.CertmgrConfig{
SecretId: fSecretId,
SecretKey: fSecretKey,
})
if err != nil {
t.Errorf("err: %+v", err)
return
}
tester.TestUpload(t, provider, tester.TestUploadArgs{CertPath: fTestCertPath, KeyPath: fTestKeyPath})
})
}
@@ -46,9 +46,9 @@ type CertmgrConfig struct {
}
type Certmgr struct {
config *CertmgrConfig
logger *slog.Logger
sdkClient *wSDKClients
config *CertmgrConfig
logger *slog.Logger
sdkClients *wSDKClients
}
var _ Provider = (*Certmgr)(nil)
@@ -63,15 +63,15 @@ func NewCertmgr(config *CertmgrConfig) (*Certmgr, error) {
return nil, fmt.Errorf("the configuration of the certmgr provider is nil")
}
client, err := createSDKClients(config.SecretId, config.SecretKey, config.Endpoint, config.Region)
clients, err := createSDKClients(config.SecretId, config.SecretKey, config.Endpoint, config.Region)
if err != nil {
return nil, fmt.Errorf("could not create client: %w", err)
}
return &Certmgr{
config: config,
logger: slog.Default(),
sdkClient: client,
config: config,
logger: slog.Default(),
sdkClients: clients,
}, nil
}
@@ -117,7 +117,7 @@ func (c *Certmgr) uploadToCloudNative(ctx context.Context, certPEM, privkeyPEM s
uploadCertificateReq.CertificatePublicKey = common.StringPtr(certPEM)
uploadCertificateReq.CertificatePrivateKey = common.StringPtr(privkeyPEM)
uploadCertificateReq.Repeatable = common.BoolPtr(false)
uploadCertificateResp, err := c.sdkClient.SSL.UploadCertificateWithContext(ctx, uploadCertificateReq)
uploadCertificateResp, err := c.sdkClients.SSL.UploadCertificateWithContext(ctx, uploadCertificateReq)
c.logger.Debug("sdk request 'ssl.UploadCertificate'", slog.Any("request", uploadCertificateReq), slog.Any("response", uploadCertificateResp))
if err != nil {
return nil, fmt.Errorf("failed to execute sdk request 'ssl.UploadCertificate': %w", err)
@@ -138,7 +138,7 @@ func (c *Certmgr) uploadToCloudNative(ctx context.Context, certPEM, privkeyPEM s
describeCloudNativeAPIGatewayCertificatesReq.GatewayId = common.StringPtr(c.config.GatewayId)
describeCloudNativeAPIGatewayCertificatesReq.Offset = common.Int64Ptr(int64(describeCloudNativeAPIGatewayCertificatesOffset))
describeCloudNativeAPIGatewayCertificatesReq.Limit = common.Int64Ptr(int64(describeCloudNativeAPIGatewayCertificatesLimit))
describeCloudNativeAPIGatewayCertificatesResp, err := c.sdkClient.TSE.DescribeCloudNativeAPIGatewayCertificatesWithContext(ctx, describeCloudNativeAPIGatewayCertificatesReq)
describeCloudNativeAPIGatewayCertificatesResp, err := c.sdkClients.TSE.DescribeCloudNativeAPIGatewayCertificatesWithContext(ctx, describeCloudNativeAPIGatewayCertificatesReq)
c.logger.Debug("sdk request 'tse.DescribeCloudNativeAPIGatewayCertificates'", slog.Any("request", describeCloudNativeAPIGatewayCertificatesReq), slog.Any("response", describeCloudNativeAPIGatewayCertificatesResp))
if err != nil {
return nil, fmt.Errorf("failed to execute sdk request 'tse.DescribeCloudNativeAPIGatewayCertificates': %w", err)
@@ -173,7 +173,7 @@ func (c *Certmgr) uploadToCloudNative(ctx context.Context, certPEM, privkeyPEM s
createCloudNativeAPIGatewayCertificateReq.Name = common.StringPtr(certName)
createCloudNativeAPIGatewayCertificateReq.CertId = uploadCertificateResp.Response.CertificateId
createCloudNativeAPIGatewayCertificateReq.BindDomains = common.StringPtrs(lo.Ternary(len(c.config.Domains) != 0, c.config.Domains, certX509.DNSNames))
createCloudNativeAPIGatewayCertificateResp, err := c.sdkClient.TSE.CreateCloudNativeAPIGatewayCertificateWithContext(ctx, createCloudNativeAPIGatewayCertificateReq)
createCloudNativeAPIGatewayCertificateResp, err := c.sdkClients.TSE.CreateCloudNativeAPIGatewayCertificateWithContext(ctx, createCloudNativeAPIGatewayCertificateReq)
c.logger.Debug("sdk request 'tse.CreateCloudNativeAPIGatewayCertificate'", slog.Any("request", createCloudNativeAPIGatewayCertificateReq), slog.Any("response", createCloudNativeAPIGatewayCertificateResp))
if err != nil {
return nil, fmt.Errorf("failed to execute sdk request 'tse.CreateCloudNativeAPIGatewayCertificate': %w", err)
@@ -194,7 +194,7 @@ func (c *Certmgr) replaceToCloudNative(ctx context.Context, certIdOrName string,
modifyCloudNativeAPIGatewayCertificateReq.Crt = common.StringPtr(certPEM)
modifyCloudNativeAPIGatewayCertificateReq.Key = common.StringPtr(privkeyPEM)
modifyCloudNativeAPIGatewayCertificateReq.CertSource = common.StringPtr("native")
modifyCloudNativeAPIGatewayCertificateResp, err := c.sdkClient.TSE.ModifyCloudNativeAPIGatewayCertificateWithContext(ctx, modifyCloudNativeAPIGatewayCertificateReq)
modifyCloudNativeAPIGatewayCertificateResp, err := c.sdkClients.TSE.ModifyCloudNativeAPIGatewayCertificateWithContext(ctx, modifyCloudNativeAPIGatewayCertificateReq)
c.logger.Debug("sdk request 'tse.ModifyCloudNativeAPIGatewayCertificate'", slog.Any("request", modifyCloudNativeAPIGatewayCertificateReq), slog.Any("response", modifyCloudNativeAPIGatewayCertificateResp))
if err != nil {
return nil, fmt.Errorf("failed to execute sdk request 'tse.ModifyCloudNativeAPIGatewayCertificate': %w", err)
@@ -376,15 +376,14 @@ func (d *Deployer) updateListenerCertificate(ctx context.Context, cloudListenerI
errs = append(errs, fmt.Errorf("failed to execute sdk request 'cas.GetCertificateDetail': %w", err))
continue
} else {
certCNMatched := tea.StringValue(getCertificateDetailResp.Body.CommonName) == d.config.Domain
certSANDiff, _ := lo.Difference(tea.StringSliceValue(getCertificateDetailResp.Body.SubjectAlternativeNames), cloudCertSANs)
if certCNMatched || len(certSANDiff) == 0 {
if len(certSANDiff) == 0 { // 同域名证书需要删除
certificateIdsToDissociate = append(certificateIdsToDissociate, certIdWithRegion)
continue
}
certNotAfter := time.Unix(tea.Int64Value(getCertificateDetailResp.Body.NotAfter)/1000, 0)
if certNotAfter.Before(time.Now()) {
if certNotAfter.Before(time.Now()) { // 过期证书需要删除
certificateIdsToDissociate = append(certificateIdsToDissociate, certIdWithRegion)
continue
}
@@ -212,13 +212,17 @@ func (d *Deployer) checkIsBind(ctx context.Context, cloudCertId string) (bool, e
}
func createSDKClients(secretId, secretKey, region string) (*wSDKClients, error) {
credential := common.NewCredential(secretId, secretKey)
client, err := tcssl.NewClient(credential, region, profile.NewClientProfile())
if err != nil {
return nil, err
wsdk := &wSDKClients{}
{
credential := common.NewCredential(secretId, secretKey)
client, err := tcssl.NewClient(credential, region, profile.NewClientProfile())
if err != nil {
return nil, err
}
wsdk.SSL = client
}
return &wSDKClients{
SSL: client,
}, nil
return wsdk, nil
}
@@ -0,0 +1,6 @@
package tencentcloudga2
const (
// 部署目标:部署到指定监听器。
DEPLOY_TARGET_LISTENER = "listener"
)
@@ -0,0 +1,247 @@
package tencentcloudga2
import (
"context"
"fmt"
"log/slog"
"strings"
"github.com/samber/lo"
"github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common"
tcerrors "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common/errors"
"github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common/profile"
tcga2 "github.com/certimate-go/certimate/pkg/sdk3rd-trimmed/github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/ga2/v20250115"
tcssl "github.com/certimate-go/certimate/pkg/sdk3rd-trimmed/github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/ssl/v20191205"
"github.com/certimate-go/certimate/pkg/core"
cmgrimpl "github.com/certimate-go/certimate/pkg/core/certmgr/providers/tencentcloud-ssl"
xcert "github.com/certimate-go/certimate/pkg/utils/cert"
)
type (
Provider = core.Deployer
DeployResult = core.DeployerDeployResult
)
type DeployerConfig struct {
// 腾讯云 SecretId。
SecretId string `json:"secretId"`
// 腾讯云 SecretKey。
SecretKey string `json:"secretKey"`
// 腾讯云项目 ID。
ProjectId int64 `json:"projectId,omitempty"`
// 腾讯云接口端点。
Endpoint string `json:"endpoint,omitempty"`
// 部署目标。
DeployTarget string `json:"deployTarget"`
// 全球加速实例 ID。
// 部署目标为 [DEPLOY_TARGET_LISTENER] 时必填。
AcceleratorId string `json:"acceleratorId,omitempty"`
// 监听器 ID。
// 部署目标为 [DEPLOY_TARGET_LISTENER] 时必填。
ListenerId string `json:"listenerId,omitempty"`
}
type Deployer struct {
config *DeployerConfig
logger *slog.Logger
sdkClients *wSDKClients
sdkCertmgr core.Certmgr
}
var _ Provider = (*Deployer)(nil)
type wSDKClients struct {
GA2 *tcga2.Client
SSL *tcssl.Client
}
func NewDeployer(config *DeployerConfig) (*Deployer, error) {
if config == nil {
return nil, fmt.Errorf("the configuration of the deployer provider is nil")
}
clients, err := createSDKClients(config.SecretId, config.SecretKey, config.Endpoint)
if err != nil {
return nil, fmt.Errorf("could not create client: %w", err)
}
pcertmgr, err := cmgrimpl.NewCertmgr(&cmgrimpl.CertmgrConfig{
SecretId: config.SecretId,
SecretKey: config.SecretKey,
ProjectId: config.ProjectId,
Endpoint: lo.
If(strings.HasSuffix(config.Endpoint, "intl.tencentcloudapi.com"), "ssl.intl.tencentcloudapi.com"). // 国际站使用独立的接口端点
Else(""),
})
if err != nil {
return nil, fmt.Errorf("could not create certmgr: %w", err)
}
return &Deployer{
config: config,
logger: slog.Default(),
sdkClients: clients,
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) {
// 解析证书内容
certX509, err := xcert.ParseCertificateFromPEM(certPEM)
if err != nil {
return nil, err
}
// 上传证书
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_LISTENER:
if err := d.deployToListener(ctx, upres.CertId, certX509.DNSNames); err != nil {
return nil, err
}
default:
return nil, fmt.Errorf("unsupported deploy target '%s'", d.config.DeployTarget)
}
return &DeployResult{}, nil
}
func (d *Deployer) deployToListener(ctx context.Context, cloudCertId string, cloudCertSANs []string) error {
if d.config.AcceleratorId == "" {
return fmt.Errorf("config `acceleratorId` is required")
}
if d.config.ListenerId == "" {
return fmt.Errorf("config `listenerId` is required")
}
// 更新监听器证书
if err := d.updateListenerCertificate(ctx, d.config.AcceleratorId, d.config.ListenerId, cloudCertId, cloudCertSANs); err != nil {
return err
}
return nil
}
func (d *Deployer) updateListenerCertificate(ctx context.Context, cloudAcceleratorId, cloudListenerId, cloudCertId string, cloudCertSANs []string) error {
// 查询监听器
// REF: https://cloud.tencent.com/document/product/1817/130160
describeListenersReq := tcga2.NewDescribeListenersRequest()
describeListenersReq.GlobalAcceleratorId = common.StringPtr(cloudAcceleratorId)
describeListenersReq.Filters = []*tcga2.Filter{
{
Name: common.StringPtr("listener-id"),
Values: []*string{common.StringPtr(cloudListenerId)},
},
}
describeListenersReq.Offset = common.Uint64Ptr(0)
describeListenersReq.Limit = common.Uint64Ptr(1)
describeListenersResp, err := d.sdkClients.GA2.DescribeListenersWithContext(ctx, describeListenersReq)
d.logger.Debug("sdk request 'ga2.DescribeListeners'", slog.Any("request", describeListenersReq), slog.Any("response", describeListenersResp))
if err != nil {
return fmt.Errorf("failed to execute sdk request 'ga2.DescribeListeners': %w", err)
} else if len(describeListenersResp.Response.ListenerSet) == 0 {
return fmt.Errorf("could not find listener '%s'", cloudListenerId)
}
// 获取证书信息,避免重复绑定
// REF: https://cloud.tencent.com/document/api/400/41674
serverCertificateIds := make([]string, 0)
for _, serverCertificateId := range describeListenersResp.Response.ListenerSet[0].ServerCertificates {
if cloudCertId == lo.FromPtr(serverCertificateId) {
return nil
}
describeCertificateReq := tcssl.NewDescribeCertificateRequest()
describeCertificateReq.CertificateId = serverCertificateId
describeCertificateResp, err := d.sdkClients.SSL.DescribeCertificateWithContext(ctx, describeCertificateReq)
d.logger.Debug("sdk request 'ssl.DescribeCertificate'", slog.Any("request", describeCertificateReq), slog.Any("response", describeCertificateResp))
if err != nil {
if sdkerr, ok := err.(*tcerrors.TencentCloudSDKError); ok {
if sdkerr.Code == "FailedOperation.CertificateNotFound" {
continue
}
}
return fmt.Errorf("failed to execute sdk request 'ssl.DescribeCertificate': %w", err)
} else {
certSANDiff, _ := lo.Difference(lo.FromSlicePtr(describeCertificateResp.Response.SubjectAltName), cloudCertSANs)
if len(certSANDiff) == 0 { // 同域名证书需要删除
continue
}
serverCertificateIds = append(serverCertificateIds, lo.FromPtr(serverCertificateId))
}
}
// 修改监听器
// REF: https://cloud.tencent.com/document/product/1817/130155
modifyListenerReq := tcga2.NewModifyListenerRequest()
modifyListenerReq.GlobalAcceleratorId = common.StringPtr(cloudAcceleratorId)
modifyListenerReq.ListenerId = common.StringPtr(cloudListenerId)
modifyListenerReq.ServerCertificates = common.StringPtrs(append(serverCertificateIds, cloudCertId))
modifyListenerResp, err := d.sdkClients.GA2.ModifyListenerWithContext(ctx, modifyListenerReq)
d.logger.Debug("sdk request 'ga2.ModifyListener'", slog.Any("request", modifyListenerReq), slog.Any("response", modifyListenerResp))
if err != nil {
return fmt.Errorf("failed to execute sdk request 'ga2.ModifyListener': %w", err)
}
return nil
}
func createSDKClients(secretId, secretKey, endpoint string) (*wSDKClients, error) {
wsdk := &wSDKClients{}
{
credential := common.NewCredential(secretId, secretKey)
cpf := profile.NewClientProfile()
if endpoint != "" {
cpf.HttpProfile.Endpoint = endpoint
}
client, err := tcga2.NewClient(credential, "", cpf)
if err != nil {
return nil, err
}
wsdk.GA2 = client
}
{
credential := common.NewCredential(secretId, secretKey)
cpf := profile.NewClientProfile()
if strings.HasSuffix(endpoint, "intl.tencentcloudapi.com") {
cpf.HttpProfile.Endpoint = "ssl.intl.tencentcloudapi.com"
}
client, err := tcssl.NewClient(credential, "", cpf)
if err != nil {
return nil, err
}
wsdk.SSL = client
}
return wsdk, nil
}
@@ -0,0 +1,58 @@
package tencentcloudga2_test
import (
"testing"
"github.com/certimate-go/certimate/pkg/core/deployer/internal/tester"
impl "github.com/certimate-go/certimate/pkg/core/deployer/providers/tencentcloud-ga2"
)
var (
fp = tester.Args("TENCENTCLOUDGA2_")
fTestCertPath string
fTestKeyPath string
fSecretId string
fSecretKey string
fAcceleratorId string
fListenerId string
)
func init() {
fp.DefineString(&fTestCertPath, "TESTCERTPATH")
fp.DefineString(&fTestKeyPath, "TESTKEYPATH")
fp.DefineString(&fSecretId, "SECRETID")
fp.DefineString(&fSecretKey, "SECRETKEY")
fp.DefineString(&fAcceleratorId, "ACCELERATORID")
fp.DefineString(&fListenerId, "LISTENERID")
}
/*
Shell command to run this test:
go test -v ./tencentcloud_ga2_test.go -args \
--TENCENTCLOUDGA2_TESTCERTPATH="/path/to/your-test-cert.pem" \
--TENCENTCLOUDGA2_TESTKEYPATH="/path/to/your-test-key.pem" \
--TENCENTCLOUDGA2_SECRETID="your-secret-id" \
--TENCENTCLOUDGA2_SECRETKEY="your-secret-key" \
--TENCENTCLOUDGA2_ACCELERATORID="your-ga2-accelerator-id" \
--TENCENTCLOUDGA2_LISTENERID="your-ga2-listener-id"
*/
func TestProvider(t *testing.T) {
fp.Parse()
t.Run("Deploy_ToListener", func(t *testing.T) {
provider, err := impl.NewDeployer(&impl.DeployerConfig{
SecretId: fSecretId,
SecretKey: fSecretKey,
DeployTarget: impl.DEPLOY_TARGET_LISTENER,
AcceleratorId: fAcceleratorId,
ListenerId: fListenerId,
})
if err != nil {
t.Errorf("err: %+v", err)
return
}
tester.TestDeploy(t, provider, tester.TestDeployArgs{CertPath: fTestCertPath, KeyPath: fTestKeyPath})
})
}
@@ -4,7 +4,6 @@ import (
"context"
"fmt"
"log/slog"
"strings"
"github.com/samber/lo"
"github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common"
@@ -13,7 +12,7 @@ import (
tcgaap "github.com/certimate-go/certimate/pkg/sdk3rd-trimmed/github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/gaap/v20180529"
"github.com/certimate-go/certimate/pkg/core"
cmgrimpl "github.com/certimate-go/certimate/pkg/core/certmgr/providers/tencentcloud-ssl"
cmgrimpl "github.com/certimate-go/certimate/pkg/core/certmgr/providers/tencentcloud-gaap"
)
type (
@@ -35,7 +34,7 @@ type DeployerConfig struct {
// 通道 ID。
// 选填。
ProxyId string `json:"proxyId,omitempty"`
// 负载均衡监听 ID。
// 监听器 ID。
// 部署目标为 [DEPLOY_TARGET_LISTENER] 时必填。
ListenerId string `json:"listenerId,omitempty"`
}
@@ -54,7 +53,7 @@ func NewDeployer(config *DeployerConfig) (*Deployer, error) {
return nil, fmt.Errorf("the configuration of the deployer provider is nil")
}
client, err := createSDKClients(config.SecretId, config.SecretKey, config.Endpoint)
client, err := createSDKClient(config.SecretId, config.SecretKey, config.Endpoint)
if err != nil {
return nil, fmt.Errorf("could not create client: %w", err)
}
@@ -63,9 +62,7 @@ func NewDeployer(config *DeployerConfig) (*Deployer, error) {
SecretId: config.SecretId,
SecretKey: config.SecretKey,
ProjectId: config.ProjectId,
Endpoint: lo.
If(strings.HasSuffix(config.Endpoint, "intl.tencentcloudapi.com"), "ssl.intl.tencentcloudapi.com"). // 国际站使用独立的接口端点
Else(""),
Endpoint: config.Endpoint,
})
if err != nil {
return nil, fmt.Errorf("could not create certmgr: %w", err)
@@ -155,7 +152,7 @@ func (d *Deployer) updateHttpsListenerCertificate(ctx context.Context, cloudList
return nil
}
func createSDKClients(secretId, secretKey, endpoint string) (*tcgaap.Client, error) {
func createSDKClient(secretId, secretKey, endpoint string) (*tcgaap.Client, error) {
credential := common.NewCredential(secretId, secretKey)
cpf := profile.NewClientProfile()
@@ -8,7 +8,7 @@ import (
)
var (
fp = tester.Args("TENCENTCLOUDCDN_")
fp = tester.Args("TENCENTCLOUGAAP_")
fTestCertPath string
fTestKeyPath string
fSecretId string
@@ -35,7 +35,7 @@ Shell command to run this test:
--TENCENTCLOUDGAAP_SECRETID="your-secret-id" \
--TENCENTCLOUDGAAP_SECRETKEY="your-secret-key" \
--TENCENTCLOUDGAAP_PROXYID="your-gaap-group-id" \
--TENCENTCLOUDGAAP_LISTENERID="your-clb-listener-id"
--TENCENTCLOUDGAAP_LISTENERID="your-gaap-listener-id"
*/
func TestProvider(t *testing.T) {
fp.Parse()
@@ -0,0 +1,74 @@
package v20250115
import (
"context"
"errors"
"github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common"
"github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common/profile"
ga2 "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/ga2/v20250115"
)
const APIVersion = ga2.APIVersion
type Client struct {
common.Client
}
func NewClient(credential common.CredentialIface, region string, clientProfile *profile.ClientProfile) (client *Client, err error) {
client = &Client{}
client.Init(region).
WithCredential(credential).
WithProfile(clientProfile)
return
}
func NewDescribeListenersRequest() (request *DescribeListenersRequest) {
return ga2.NewDescribeListenersRequest()
}
func NewDescribeListenersResponse() (response *DescribeListenersResponse) {
return ga2.NewDescribeListenersResponse()
}
func (c *Client) DescribeListenersWithContext(ctx context.Context, request *DescribeListenersRequest) (response *DescribeListenersResponse, err error) {
if request == nil {
request = NewDescribeListenersRequest()
}
c.InitBaseRequest(&request.BaseRequest, "ga2", APIVersion, "DescribeListeners")
if c.GetCredential() == nil {
return nil, errors.New("DescribeListeners require credential")
}
request.SetContext(ctx)
response = NewDescribeListenersResponse()
err = c.Send(request, response)
return
}
func NewModifyListenerRequest() (request *ModifyListenerRequest) {
return ga2.NewModifyListenerRequest()
}
func NewModifyListenerResponse() (response *ModifyListenerResponse) {
return ga2.NewModifyListenerResponse()
}
func (c *Client) ModifyListenerWithContext(ctx context.Context, request *ModifyListenerRequest) (response *ModifyListenerResponse, err error) {
if request == nil {
request = NewModifyListenerRequest()
}
c.InitBaseRequest(&request.BaseRequest, "ga2", APIVersion, "ModifyListener")
if c.GetCredential() == nil {
return nil, errors.New("ModifyListener require credential")
}
request.SetContext(ctx)
response = NewModifyListenerResponse()
err = c.Send(request, response)
return
}
@@ -0,0 +1,17 @@
package v20250115
import (
ga2 "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/ga2/v20250115"
)
type (
Filter = ga2.Filter
)
type DescribeListenersRequest = ga2.DescribeListenersRequest
type DescribeListenersResponse = ga2.DescribeListenersResponse
type ModifyListenerRequest = ga2.ModifyListenerRequest
type ModifyListenerResponse = ga2.ModifyListenerResponse
@@ -23,6 +23,81 @@ func NewClient(credential common.CredentialIface, region string, clientProfile *
return
}
func NewCreateCertificateRequest() (request *CreateCertificateRequest) {
return gaap.NewCreateCertificateRequest()
}
func NewCreateCertificateResponse() (response *CreateCertificateResponse) {
return gaap.NewCreateCertificateResponse()
}
func (c *Client) CreateCertificateWithContext(ctx context.Context, request *CreateCertificateRequest) (response *CreateCertificateResponse, err error) {
if request == nil {
request = NewCreateCertificateRequest()
}
c.InitBaseRequest(&request.BaseRequest, "gaap", APIVersion, "CreateCertificate")
if c.GetCredential() == nil {
return nil, errors.New("CreateCertificate require credential")
}
request.SetContext(ctx)
response = NewCreateCertificateResponse()
err = c.Send(request, response)
return
}
func NewDescribeCertificatesRequest() (request *DescribeCertificatesRequest) {
return gaap.NewDescribeCertificatesRequest()
}
func NewDescribeCertificatesResponse() (response *DescribeCertificatesResponse) {
return gaap.NewDescribeCertificatesResponse()
}
func (c *Client) DescribeCertificatesWithContext(ctx context.Context, request *DescribeCertificatesRequest) (response *DescribeCertificatesResponse, err error) {
if request == nil {
request = NewDescribeCertificatesRequest()
}
c.InitBaseRequest(&request.BaseRequest, "gaap", APIVersion, "DescribeCertificates")
if c.GetCredential() == nil {
return nil, errors.New("DescribeCertificates require credential")
}
request.SetContext(ctx)
response = NewDescribeCertificatesResponse()
err = c.Send(request, response)
return
}
func NewDescribeCertificateDetailRequest() (request *DescribeCertificateDetailRequest) {
return gaap.NewDescribeCertificateDetailRequest()
}
func NewDescribeCertificateDetailResponse() (response *DescribeCertificateDetailResponse) {
return gaap.NewDescribeCertificateDetailResponse()
}
func (c *Client) DescribeCertificateDetailWithContext(ctx context.Context, request *DescribeCertificateDetailRequest) (response *DescribeCertificateDetailResponse, err error) {
if request == nil {
request = NewDescribeCertificateDetailRequest()
}
c.InitBaseRequest(&request.BaseRequest, "gaap", APIVersion, "DescribeCertificateDetail")
if c.GetCredential() == nil {
return nil, errors.New("DescribeCertificateDetail require credential")
}
request.SetContext(ctx)
response = NewDescribeCertificateDetailResponse()
err = c.Send(request, response)
return
}
func NewDescribeHTTPSListenersRequest() (request *DescribeHTTPSListenersRequest) {
return gaap.NewDescribeHTTPSListenersRequest()
}
@@ -4,6 +4,18 @@ import (
gaap "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/gaap/v20180529"
)
type CreateCertificateRequest = gaap.CreateCertificateRequest
type CreateCertificateResponse = gaap.CreateCertificateResponse
type DescribeCertificatesRequest = gaap.DescribeCertificatesRequest
type DescribeCertificatesResponse = gaap.DescribeCertificatesResponse
type DescribeCertificateDetailRequest = gaap.DescribeCertificateDetailRequest
type DescribeCertificateDetailResponse = gaap.DescribeCertificateDetailResponse
type DescribeHTTPSListenersRequest = gaap.DescribeHTTPSListenersRequest
type DescribeHTTPSListenersResponse = gaap.DescribeHTTPSListenersResponse
@@ -23,6 +23,30 @@ func NewClient(credential common.CredentialIface, region string, clientProfile *
return
}
func NewDescribeCertificateRequest() (request *DescribeCertificateRequest) {
return ssl.NewDescribeCertificateRequest()
}
func NewDescribeCertificateResponse() (response *DescribeCertificateResponse) {
return ssl.NewDescribeCertificateResponse()
}
func (c *Client) DescribeCertificateWithContext(ctx context.Context, request *DescribeCertificateRequest) (response *DescribeCertificateResponse, err error) {
if request == nil {
request = NewDescribeCertificateRequest()
}
c.InitBaseRequest(&request.BaseRequest, "ssl", ssl.APIVersion, "DescribeCertificate")
if c.GetCredential() == nil {
return nil, errors.New("DescribeCertificate require credential")
}
request.SetContext(ctx)
response = NewDescribeCertificateResponse()
err = c.Send(request, response)
return
}
func NewDescribeHostCosInstanceListRequest() (request *DescribeHostCosInstanceListRequest) {
return ssl.NewDescribeHostCosInstanceListRequest()
}
@@ -8,6 +8,10 @@ type (
ResourceTypeRegions = ssl.ResourceTypeRegions
)
type DescribeCertificateRequest = ssl.DescribeCertificateRequest
type DescribeCertificateResponse = ssl.DescribeCertificateResponse
type DescribeHostCosInstanceListRequest = ssl.DescribeHostCosInstanceListRequest
type DescribeHostCosInstanceListResponse = ssl.DescribeHostCosInstanceListResponse
@@ -103,6 +103,7 @@ import BizDeployNodeConfigFieldsProviderTencentCloudCOS from "./BizDeployNodeCon
import BizDeployNodeConfigFieldsProviderTencentCloudCSS from "./BizDeployNodeConfigFieldsProviderTencentCloudCSS";
import BizDeployNodeConfigFieldsProviderTencentCloudECDN from "./BizDeployNodeConfigFieldsProviderTencentCloudECDN";
import BizDeployNodeConfigFieldsProviderTencentCloudEO from "./BizDeployNodeConfigFieldsProviderTencentCloudEO";
import BizDeployNodeConfigFieldsProviderTencentCloudGA2 from "./BizDeployNodeConfigFieldsProviderTencentCloudGA2";
import BizDeployNodeConfigFieldsProviderTencentCloudGAAP from "./BizDeployNodeConfigFieldsProviderTencentCloudGAAP";
import BizDeployNodeConfigFieldsProviderTencentCloudSCF from "./BizDeployNodeConfigFieldsProviderTencentCloudSCF";
import BizDeployNodeConfigFieldsProviderTencentCloudSSL from "./BizDeployNodeConfigFieldsProviderTencentCloudSSL";
@@ -245,6 +246,7 @@ const providerComponentMap: Partial<Record<DeploymentProviderType, React.Compone
[DEPLOYMENT_PROVIDERS.TENCENTCLOUD_ECDN]: BizDeployNodeConfigFieldsProviderTencentCloudECDN,
[DEPLOYMENT_PROVIDERS.TENCENTCLOUD_EO]: BizDeployNodeConfigFieldsProviderTencentCloudEO,
[DEPLOYMENT_PROVIDERS.TENCENTCLOUD_GAAP]: BizDeployNodeConfigFieldsProviderTencentCloudGAAP,
[DEPLOYMENT_PROVIDERS.TENCENTCLOUD_GA2]: BizDeployNodeConfigFieldsProviderTencentCloudGA2,
[DEPLOYMENT_PROVIDERS.TENCENTCLOUD_SCF]: BizDeployNodeConfigFieldsProviderTencentCloudSCF,
[DEPLOYMENT_PROVIDERS.TENCENTCLOUD_SSL]: BizDeployNodeConfigFieldsProviderTencentCloudSSL,
[DEPLOYMENT_PROVIDERS.TENCENTCLOUD_SSL_DEPLOY]: BizDeployNodeConfigFieldsProviderTencentCloudSSLDeploy,
@@ -0,0 +1,118 @@
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 { useFormNestedFieldsContext } from "./_context";
const DEPLOY_TARGET_LISTENER = "listener" as const;
const BizDeployNodeConfigFieldsProviderTencentCloudGA2 = () => {
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, "endpoint"]}
initialValue={initialValues.endpoint}
label={t("workflow_node.deploy.form.tencentcloud_ga2_endpoint.label")}
rules={[formRule]}
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.tencentcloud_ga2_endpoint.tooltip") }}></span>}
>
<Input allowClear placeholder={t("workflow_node.deploy.form.tencentcloud_ga2_endpoint.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_LISTENER].map((s) => ({
label: t(`workflow_node.deploy.form.tencentcloud_ga2_deploy_target.option.${s}.label`),
value: s,
}))}
placeholder={t("workflow_node.deploy.form.shared_deploy_target.placeholder")}
/>
</Form.Item>
<Form.Item
name={[parentNamePath, "acceleratorId"]}
initialValue={initialValues.acceleratorId}
label={t("workflow_node.deploy.form.tencentcloud_ga2_accelerator_id.label")}
rules={[formRule]}
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.tencentcloud_ga2_accelerator_id.tooltip") }}></span>}
>
<Input placeholder={t("workflow_node.deploy.form.tencentcloud_ga2_accelerator_id.placeholder")} />
</Form.Item>
<Show when={fieldResourceType === DEPLOY_TARGET_LISTENER}>
<Form.Item
name={[parentNamePath, "listenerId"]}
initialValue={initialValues.listenerId}
label={t("workflow_node.deploy.form.tencentcloud_ga2_listener_id.label")}
rules={[formRule]}
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.tencentcloud_ga2_listener_id.tooltip") }}></span>}
>
<Input placeholder={t("workflow_node.deploy.form.tencentcloud_ga2_listener_id.placeholder")} />
</Form.Item>
</Show>
</>
);
};
const getInitialValues = (): Nullish<z.infer<ReturnType<typeof getSchema>>> => {
return {
acceleratorId: "",
deployTarget: DEPLOY_TARGET_LISTENER,
};
};
const getSchema = ({ i18n = getI18n() }: { i18n?: ReturnType<typeof getI18n> }) => {
const { t: _ } = i18n;
return z
.object({
endpoint: z.string().nullish(),
deployTarget: z.enum([DEPLOY_TARGET_LISTENER]),
acceleratorId: z.string().nonempty(),
listenerId: z.string().nullish(),
})
.superRefine((values, ctx) => {
switch (values.deployTarget) {
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(BizDeployNodeConfigFieldsProviderTencentCloudGA2, {
getInitialValues,
getSchema,
});
export default _default;
+2
View File
@@ -700,6 +700,7 @@ export const DEPLOYMENT_PROVIDERS = Object.freeze({
TENCENTCLOUD_ECDN: `${ACCESS_PROVIDERS.TENCENTCLOUD}-ecdn`,
TENCENTCLOUD_EO: `${ACCESS_PROVIDERS.TENCENTCLOUD}-eo`,
TENCENTCLOUD_GAAP: `${ACCESS_PROVIDERS.TENCENTCLOUD}-gaap`,
TENCENTCLOUD_GA2: `${ACCESS_PROVIDERS.TENCENTCLOUD}-ga2`,
TENCENTCLOUD_SCF: `${ACCESS_PROVIDERS.TENCENTCLOUD}-scf`,
TENCENTCLOUD_SSL: `${ACCESS_PROVIDERS.TENCENTCLOUD}-ssl`,
TENCENTCLOUD_SSL_DEPLOY: `${ACCESS_PROVIDERS.TENCENTCLOUD}-ssldeploy`,
@@ -800,6 +801,7 @@ export const deploymentProvidersMap: Map<DeploymentProvider["type"] | string, De
[DEPLOYMENT_PROVIDERS.TENCENTCLOUD_SCF, "provider.tencentcloud_scf", DEPLOYMENT_CATEGORIES.SERVERLESS],
[DEPLOYMENT_PROVIDERS.TENCENTCLOUD_TSE, "provider.tencentcloud_tse", DEPLOYMENT_CATEGORIES.APIGATEWAY],
[DEPLOYMENT_PROVIDERS.TENCENTCLOUD_GAAP, "provider.tencentcloud_gaap", DEPLOYMENT_CATEGORIES.ACCELERATOR],
[DEPLOYMENT_PROVIDERS.TENCENTCLOUD_GA2, "provider.tencentcloud_ga2", DEPLOYMENT_CATEGORIES.ACCELERATOR],
[DEPLOYMENT_PROVIDERS.TENCENTCLOUD_SSL, "provider.tencentcloud_ssl_upload", DEPLOYMENT_CATEGORIES.SSL],
[DEPLOYMENT_PROVIDERS.TENCENTCLOUD_SSL_DEPLOY, "provider.tencentcloud_ssl_deploy", DEPLOYMENT_CATEGORIES.SSL],
[DEPLOYMENT_PROVIDERS.TENCENTCLOUD_SSL_UPDATE, "provider.tencentcloud_ssl_update", DEPLOYMENT_CATEGORIES.SSL],
@@ -238,6 +238,7 @@
"tencentcloud_dns": "Tencent Cloud - DNS",
"tencentcloud_ecdn": "Tencent Cloud - ECDN (Enterprise Content Delivery Network)",
"tencentcloud_eo": "Tencent Cloud - EdgeOne",
"tencentcloud_ga2": "Tencent Cloud - GA2 (Global Accelerator 2.0)",
"tencentcloud_gaap": "Tencent Cloud - GAAP (Global Application Acceleration Platform)",
"tencentcloud_scf": "Tencent Cloud - SCF (Serverless Cloud Function)",
"tencentcloud_ssl_deploy": "Tencent Cloud - Deploy via SSL Certificate Service",
@@ -2213,6 +2213,28 @@
"off": "Disallow"
}
},
"tencentcloud_ga2_endpoint": {
"label": "Tencent Cloud API endpoint (Optional)",
"placeholder": "Please enter Tencent Cloud GA2 API endpoint (e.g. ga2.intl.tencentcloudapi.com)",
"tooltip": "<ul style=\"list-style: disc;\"><li><strong>ga2.intl.tencentcloudapi.com</strong> for Tencent Cloud International</li><li><strong>ga2.tencentcloudapi.com</strong> for Tencent Cloud in China</li></ul>"
},
"tencentcloud_ga2_deploy_target": {
"option": {
"listener": {
"label": "GA2 listener"
}
}
},
"tencentcloud_ga2_accelerator_id": {
"label": "Tencent Cloud GA2 accelerator ID (Optional)",
"placeholder": "Please enter Tencent Cloud GA2 accelerator ID",
"tooltip": "For more information, see <a href=\"https://console.tencentcloud.com/gaap\" target=\"_blank\">https://console.tencentcloud.com/gaap</a>"
},
"tencentcloud_ga2_listener_id": {
"label": "Tencent Cloud GA2 listener ID",
"placeholder": "Please enter Tencent Cloud GA2 listener ID",
"tooltip": "For more information, see <a href=\"https://console.tencentcloud.com/gaap\" target=\"_blank\">https://console.tencentcloud.com/gaap</a>"
},
"tencentcloud_gaap_endpoint": {
"label": "Tencent Cloud API endpoint (Optional)",
"placeholder": "Please enter Tencent Cloud GAAP API endpoint (e.g. gaap.intl.tencentcloudapi.com)",
@@ -238,6 +238,7 @@
"tencentcloud_dns": "腾讯云 - 云解析 DNS",
"tencentcloud_ecdn": "腾讯云 - 全站加速网络 ECDN",
"tencentcloud_eo": "腾讯云 - 边缘安全加速平台 EdgeOne",
"tencentcloud_ga2": "腾讯云 - 全球加速 2.0 GA2",
"tencentcloud_gaap": "腾讯云 - 全球应用加速 GAAP",
"tencentcloud_scf": "腾讯云 - 云函数 SCF",
"tencentcloud_ssl_deploy": "腾讯云 - 通过 SSL 证书服务创建部署任务",
@@ -2209,6 +2209,28 @@
"off": "不"
}
},
"tencentcloud_ga2_endpoint": {
"label": "腾讯云接口端点(可选)",
"placeholder": "请输入腾讯云 GA2 接口端点(例如:ga2.tencentcloudapi.com)",
"tooltip": "这是什么?请参阅 <a href=\"https://cloud.tencent.com/document/product/1817/129372\" target=\"_blank\">https://cloud.tencent.com/document/product/1817/129372</a><br>国际站用户请填写 <em>ga2.intl.tencentcloudapi.com</em>。"
},
"tencentcloud_ga2_deploy_target": {
"option": {
"listener": {
"label": "部署到指定监听器"
}
}
},
"tencentcloud_ga2_accelerator_id": {
"label": "腾讯云 GA2 加速实例 ID",
"placeholder": "请输入腾讯云 GA2 加速实例 ID",
"tooltip": "这是什么?请参阅 <a href=\"https://console.cloud.tencent.com/gaap\" target=\"_blank\">https://console.cloud.tencent.com/gaap</a>"
},
"tencentcloud_ga2_listener_id": {
"label": "腾讯云 GA2 监听器 ID",
"placeholder": "请输入腾讯云 GA2 监听器 ID",
"tooltip": "这是什么?请参阅 <a href=\"https://console.cloud.tencent.com/gaap\" target=\"_blank\">https://console.cloud.tencent.com/gaap</a>"
},
"tencentcloud_gaap_endpoint": {
"label": "腾讯云接口端点(可选)",
"placeholder": "请输入腾讯云 GAAP 接口端点(例如:gaap.tencentcloudapi.com)",