From 8cea61eec5292791e3989f09925f5d376fe5167b Mon Sep 17 00:00:00 2001 From: Fu Diwei Date: Thu, 11 Jun 2026 16:37:59 +0800 Subject: [PATCH] feat(provider): new deployment provider: tencentcloud ga2 --- go.mod | 3 +- go.sum | 5 +- .../certmgmt/deployers/sp_tencentcloud_ga2.go | 30 +++ internal/domain/provider.go | 1 + .../tencentcloud-gaap/tencentcloud_gaap.go | 179 +++++++++++++ .../tencentcloud_gaap_test.go | 49 ++++ .../tencentcloud-tse/tencentcloud_tse.go | 22 +- .../providers/aliyun-alb/aliyun_alb.go | 5 +- .../tencentcloud-cos/tencentcloud_cos.go | 18 +- .../providers/tencentcloud-ga2/consts.go | 6 + .../tencentcloud-ga2/tencentcloud_ga2.go | 247 ++++++++++++++++++ .../tencentcloud-ga2/tencentcloud_ga2_test.go | 58 ++++ .../tencentcloud-gaap/tencentcloud_gaap.go | 13 +- .../tencentcloud_gaap_test.go | 4 +- .../tencentcloud/ga2/v20250115/client.go | 74 ++++++ .../tencentcloud/ga2/v20250115/models.go | 17 ++ .../tencentcloud/gaap/v20180529/client.go | 75 ++++++ .../tencentcloud/gaap/v20180529/models.go | 12 + .../tencentcloud/ssl/v20191205/client.go | 24 ++ .../tencentcloud/ssl/v20191205/models.go | 4 + .../BizDeployNodeConfigFieldsProvider.tsx | 2 + ...odeConfigFieldsProviderTencentCloudGA2.tsx | 118 +++++++++ ui/src/domain/provider.ts | 2 + ui/src/i18n/resources/en/nls.provider.json | 1 + .../i18n/resources/en/nls.workflow.nodes.json | 22 ++ ui/src/i18n/resources/zh/nls.provider.json | 1 + .../i18n/resources/zh/nls.workflow.nodes.json | 22 ++ 27 files changed, 981 insertions(+), 33 deletions(-) create mode 100644 internal/certmgmt/deployers/sp_tencentcloud_ga2.go create mode 100644 pkg/core/certmgr/providers/tencentcloud-gaap/tencentcloud_gaap.go create mode 100644 pkg/core/certmgr/providers/tencentcloud-gaap/tencentcloud_gaap_test.go create mode 100644 pkg/core/deployer/providers/tencentcloud-ga2/consts.go create mode 100644 pkg/core/deployer/providers/tencentcloud-ga2/tencentcloud_ga2.go create mode 100644 pkg/core/deployer/providers/tencentcloud-ga2/tencentcloud_ga2_test.go create mode 100644 pkg/sdk3rd-trimmed/github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/ga2/v20250115/client.go create mode 100644 pkg/sdk3rd-trimmed/github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/ga2/v20250115/models.go create mode 100644 ui/src/components/workflow/designer/forms/BizDeployNodeConfigFieldsProviderTencentCloudGA2.tsx diff --git a/go.mod b/go.mod index 41592f78c..d6783b16e 100644 --- a/go.mod +++ b/go.mod @@ -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 diff --git a/go.sum b/go.sum index 8589b2c46..d0a10e722 100644 --- a/go.sum +++ b/go.sum @@ -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= diff --git a/internal/certmgmt/deployers/sp_tencentcloud_ga2.go b/internal/certmgmt/deployers/sp_tencentcloud_ga2.go new file mode 100644 index 000000000..1f951e2e6 --- /dev/null +++ b/internal/certmgmt/deployers/sp_tencentcloud_ga2.go @@ -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 + }) +} diff --git a/internal/domain/provider.go b/internal/domain/provider.go index c3fa00a75..f96ef9159 100644 --- a/internal/domain/provider.go +++ b/internal/domain/provider.go @@ -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") diff --git a/pkg/core/certmgr/providers/tencentcloud-gaap/tencentcloud_gaap.go b/pkg/core/certmgr/providers/tencentcloud-gaap/tencentcloud_gaap.go new file mode 100644 index 000000000..75fa0ad44 --- /dev/null +++ b/pkg/core/certmgr/providers/tencentcloud-gaap/tencentcloud_gaap.go @@ -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 +} diff --git a/pkg/core/certmgr/providers/tencentcloud-gaap/tencentcloud_gaap_test.go b/pkg/core/certmgr/providers/tencentcloud-gaap/tencentcloud_gaap_test.go new file mode 100644 index 000000000..e086faea8 --- /dev/null +++ b/pkg/core/certmgr/providers/tencentcloud-gaap/tencentcloud_gaap_test.go @@ -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}) + }) +} diff --git a/pkg/core/certmgr/providers/tencentcloud-tse/tencentcloud_tse.go b/pkg/core/certmgr/providers/tencentcloud-tse/tencentcloud_tse.go index 030ccba94..84d91568c 100644 --- a/pkg/core/certmgr/providers/tencentcloud-tse/tencentcloud_tse.go +++ b/pkg/core/certmgr/providers/tencentcloud-tse/tencentcloud_tse.go @@ -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) diff --git a/pkg/core/deployer/providers/aliyun-alb/aliyun_alb.go b/pkg/core/deployer/providers/aliyun-alb/aliyun_alb.go index c15470e6b..684fcbe28 100644 --- a/pkg/core/deployer/providers/aliyun-alb/aliyun_alb.go +++ b/pkg/core/deployer/providers/aliyun-alb/aliyun_alb.go @@ -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 } diff --git a/pkg/core/deployer/providers/tencentcloud-cos/tencentcloud_cos.go b/pkg/core/deployer/providers/tencentcloud-cos/tencentcloud_cos.go index b5ec317da..e52cbd49d 100644 --- a/pkg/core/deployer/providers/tencentcloud-cos/tencentcloud_cos.go +++ b/pkg/core/deployer/providers/tencentcloud-cos/tencentcloud_cos.go @@ -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 } diff --git a/pkg/core/deployer/providers/tencentcloud-ga2/consts.go b/pkg/core/deployer/providers/tencentcloud-ga2/consts.go new file mode 100644 index 000000000..55b102aed --- /dev/null +++ b/pkg/core/deployer/providers/tencentcloud-ga2/consts.go @@ -0,0 +1,6 @@ +package tencentcloudga2 + +const ( + // 部署目标:部署到指定监听器。 + DEPLOY_TARGET_LISTENER = "listener" +) diff --git a/pkg/core/deployer/providers/tencentcloud-ga2/tencentcloud_ga2.go b/pkg/core/deployer/providers/tencentcloud-ga2/tencentcloud_ga2.go new file mode 100644 index 000000000..4e9900267 --- /dev/null +++ b/pkg/core/deployer/providers/tencentcloud-ga2/tencentcloud_ga2.go @@ -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 +} diff --git a/pkg/core/deployer/providers/tencentcloud-ga2/tencentcloud_ga2_test.go b/pkg/core/deployer/providers/tencentcloud-ga2/tencentcloud_ga2_test.go new file mode 100644 index 000000000..2cac750d8 --- /dev/null +++ b/pkg/core/deployer/providers/tencentcloud-ga2/tencentcloud_ga2_test.go @@ -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}) + }) +} diff --git a/pkg/core/deployer/providers/tencentcloud-gaap/tencentcloud_gaap.go b/pkg/core/deployer/providers/tencentcloud-gaap/tencentcloud_gaap.go index f4d0ee3b3..e44f2db9b 100644 --- a/pkg/core/deployer/providers/tencentcloud-gaap/tencentcloud_gaap.go +++ b/pkg/core/deployer/providers/tencentcloud-gaap/tencentcloud_gaap.go @@ -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() diff --git a/pkg/core/deployer/providers/tencentcloud-gaap/tencentcloud_gaap_test.go b/pkg/core/deployer/providers/tencentcloud-gaap/tencentcloud_gaap_test.go index 7914dba01..5971a0225 100644 --- a/pkg/core/deployer/providers/tencentcloud-gaap/tencentcloud_gaap_test.go +++ b/pkg/core/deployer/providers/tencentcloud-gaap/tencentcloud_gaap_test.go @@ -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() diff --git a/pkg/sdk3rd-trimmed/github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/ga2/v20250115/client.go b/pkg/sdk3rd-trimmed/github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/ga2/v20250115/client.go new file mode 100644 index 000000000..938b381f0 --- /dev/null +++ b/pkg/sdk3rd-trimmed/github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/ga2/v20250115/client.go @@ -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 +} diff --git a/pkg/sdk3rd-trimmed/github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/ga2/v20250115/models.go b/pkg/sdk3rd-trimmed/github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/ga2/v20250115/models.go new file mode 100644 index 000000000..22fb8ebbb --- /dev/null +++ b/pkg/sdk3rd-trimmed/github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/ga2/v20250115/models.go @@ -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 diff --git a/pkg/sdk3rd-trimmed/github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/gaap/v20180529/client.go b/pkg/sdk3rd-trimmed/github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/gaap/v20180529/client.go index c9c430dbd..7c3ef6b0a 100644 --- a/pkg/sdk3rd-trimmed/github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/gaap/v20180529/client.go +++ b/pkg/sdk3rd-trimmed/github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/gaap/v20180529/client.go @@ -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() } diff --git a/pkg/sdk3rd-trimmed/github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/gaap/v20180529/models.go b/pkg/sdk3rd-trimmed/github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/gaap/v20180529/models.go index 740e0adf0..0f4c7afae 100644 --- a/pkg/sdk3rd-trimmed/github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/gaap/v20180529/models.go +++ b/pkg/sdk3rd-trimmed/github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/gaap/v20180529/models.go @@ -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 diff --git a/pkg/sdk3rd-trimmed/github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/ssl/v20191205/client.go b/pkg/sdk3rd-trimmed/github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/ssl/v20191205/client.go index 11ca35fd1..597aea734 100644 --- a/pkg/sdk3rd-trimmed/github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/ssl/v20191205/client.go +++ b/pkg/sdk3rd-trimmed/github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/ssl/v20191205/client.go @@ -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() } diff --git a/pkg/sdk3rd-trimmed/github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/ssl/v20191205/models.go b/pkg/sdk3rd-trimmed/github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/ssl/v20191205/models.go index e782335f1..d3db09f79 100644 --- a/pkg/sdk3rd-trimmed/github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/ssl/v20191205/models.go +++ b/pkg/sdk3rd-trimmed/github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/ssl/v20191205/models.go @@ -8,6 +8,10 @@ type ( ResourceTypeRegions = ssl.ResourceTypeRegions ) +type DescribeCertificateRequest = ssl.DescribeCertificateRequest + +type DescribeCertificateResponse = ssl.DescribeCertificateResponse + type DescribeHostCosInstanceListRequest = ssl.DescribeHostCosInstanceListRequest type DescribeHostCosInstanceListResponse = ssl.DescribeHostCosInstanceListResponse diff --git a/ui/src/components/workflow/designer/forms/BizDeployNodeConfigFieldsProvider.tsx b/ui/src/components/workflow/designer/forms/BizDeployNodeConfigFieldsProvider.tsx index 0a2e104c8..bd0025217 100644 --- a/ui/src/components/workflow/designer/forms/BizDeployNodeConfigFieldsProvider.tsx +++ b/ui/src/components/workflow/designer/forms/BizDeployNodeConfigFieldsProvider.tsx @@ -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 { + 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 ( + <> + } + > + + + + + + + + + } + > + + + + + ); +}; + +const getInitialValues = (): Nullish>> => { + return { + acceleratorId: "", + deployTarget: DEPLOY_TARGET_LISTENER, + }; +}; + +const getSchema = ({ i18n = getI18n() }: { i18n?: ReturnType }) => { + 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; diff --git a/ui/src/domain/provider.ts b/ui/src/domain/provider.ts index 6048c0f0d..96ace1506 100644 --- a/ui/src/domain/provider.ts +++ b/ui/src/domain/provider.ts @@ -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
  • ga2.intl.tencentcloudapi.com for Tencent Cloud International
  • ga2.tencentcloudapi.com for Tencent Cloud in China
  • " + }, + "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 https://console.tencentcloud.com/gaap" + }, + "tencentcloud_ga2_listener_id": { + "label": "Tencent Cloud GA2 listener ID", + "placeholder": "Please enter Tencent Cloud GA2 listener ID", + "tooltip": "For more information, see https://console.tencentcloud.com/gaap" + }, "tencentcloud_gaap_endpoint": { "label": "Tencent Cloud API endpoint (Optional)", "placeholder": "Please enter Tencent Cloud GAAP API endpoint (e.g. gaap.intl.tencentcloudapi.com)", diff --git a/ui/src/i18n/resources/zh/nls.provider.json b/ui/src/i18n/resources/zh/nls.provider.json index 130acc57d..485a01d9e 100644 --- a/ui/src/i18n/resources/zh/nls.provider.json +++ b/ui/src/i18n/resources/zh/nls.provider.json @@ -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 证书服务创建部署任务", diff --git a/ui/src/i18n/resources/zh/nls.workflow.nodes.json b/ui/src/i18n/resources/zh/nls.workflow.nodes.json index e830a9d84..b5e9ed598 100644 --- a/ui/src/i18n/resources/zh/nls.workflow.nodes.json +++ b/ui/src/i18n/resources/zh/nls.workflow.nodes.json @@ -2209,6 +2209,28 @@ "off": "不" } }, + "tencentcloud_ga2_endpoint": { + "label": "腾讯云接口端点(可选)", + "placeholder": "请输入腾讯云 GA2 接口端点(例如:ga2.tencentcloudapi.com)", + "tooltip": "这是什么?请参阅 https://cloud.tencent.com/document/product/1817/129372
    国际站用户请填写 ga2.intl.tencentcloudapi.com。" + }, + "tencentcloud_ga2_deploy_target": { + "option": { + "listener": { + "label": "部署到指定监听器" + } + } + }, + "tencentcloud_ga2_accelerator_id": { + "label": "腾讯云 GA2 加速实例 ID", + "placeholder": "请输入腾讯云 GA2 加速实例 ID", + "tooltip": "这是什么?请参阅 https://console.cloud.tencent.com/gaap" + }, + "tencentcloud_ga2_listener_id": { + "label": "腾讯云 GA2 监听器 ID", + "placeholder": "请输入腾讯云 GA2 监听器 ID", + "tooltip": "这是什么?请参阅 https://console.cloud.tencent.com/gaap" + }, "tencentcloud_gaap_endpoint": { "label": "腾讯云接口端点(可选)", "placeholder": "请输入腾讯云 GAAP 接口端点(例如:gaap.tencentcloudapi.com)",