diff --git a/internal/deployer/providers.go b/internal/deployer/providers.go
index 56234b95..f3d93a2c 100644
--- a/internal/deployer/providers.go
+++ b/internal/deployer/providers.go
@@ -43,6 +43,7 @@ import (
pBytePlusCDN "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/byteplus-cdn"
pCacheFly "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/cachefly"
pCdnfly "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/cdnfly"
+ pCTCCCloudCDN "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/ctcccloud-cdn"
pDogeCDN "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/dogecloud-cdn"
pEdgioApplications "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/edgio-applications"
pFlexCDN "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/flexcdn"
@@ -621,6 +622,27 @@ func createDeployerProvider(options *deployerProviderOptions) (deployer.Deployer
return deployer, err
}
+ case domain.DeploymentProviderTypeCTCCCloudCDN:
+ {
+ access := domain.AccessConfigForCTCCCloud{}
+ if err := maputil.Populate(options.ProviderAccessConfig, &access); err != nil {
+ return nil, fmt.Errorf("failed to populate provider access config: %w", err)
+ }
+
+ switch options.Provider {
+ case domain.DeploymentProviderTypeCTCCCloudCDN:
+ deployer, err := pCTCCCloudCDN.NewDeployer(&pCTCCCloudCDN.DeployerConfig{
+ AccessKeyId: access.AccessKeyId,
+ SecretAccessKey: access.SecretAccessKey,
+ Domain: maputil.GetString(options.ProviderServiceConfig, "domain"),
+ })
+ return deployer, err
+
+ default:
+ break
+ }
+ }
+
case domain.DeploymentProviderTypeDogeCloudCDN:
{
access := domain.AccessConfigForDogeCloud{}
diff --git a/internal/domain/provider.go b/internal/domain/provider.go
index b10cda8f..f399c21b 100644
--- a/internal/domain/provider.go
+++ b/internal/domain/provider.go
@@ -215,6 +215,12 @@ const (
DeploymentProviderTypeBytePlusCDN = DeploymentProviderType(AccessProviderTypeBytePlus + "-cdn")
DeploymentProviderTypeCacheFly = DeploymentProviderType(AccessProviderTypeCacheFly)
DeploymentProviderTypeCdnfly = DeploymentProviderType(AccessProviderTypeCdnfly)
+ DeploymentProviderTypeCTCCCloudAO = DeploymentProviderType(AccessProviderTypeCTCCCloud + "-ao") // (预留)
+ DeploymentProviderTypeCTCCCloudCDN = DeploymentProviderType(AccessProviderTypeCTCCCloud + "-cdn")
+ DeploymentProviderTypeCTCCCloudCMS = DeploymentProviderType(AccessProviderTypeCTCCCloud + "-cms") // (预留)
+ DeploymentProviderTypeCTCCCloudELB = DeploymentProviderType(AccessProviderTypeCTCCCloud + "-elb") // (预留)
+ DeploymentProviderTypeCTCCCloudICDN = DeploymentProviderType(AccessProviderTypeCTCCCloud + "-icdn") // (预留)
+ DeploymentProviderTypeDogeCloudLVDN = DeploymentProviderType(AccessProviderTypeDogeCloud + "-ldvn") // (预留)
DeploymentProviderTypeDogeCloudCDN = DeploymentProviderType(AccessProviderTypeDogeCloud + "-cdn")
DeploymentProviderTypeEdgioApplications = DeploymentProviderType(AccessProviderTypeEdgio + "-applications")
DeploymentProviderTypeFlexCDN = DeploymentProviderType(AccessProviderTypeFlexCDN)
diff --git a/internal/pkg/core/deployer/providers/ctcccloud-cdn/ctcccloud_cdn.go b/internal/pkg/core/deployer/providers/ctcccloud-cdn/ctcccloud_cdn.go
new file mode 100644
index 00000000..8cc9edaf
--- /dev/null
+++ b/internal/pkg/core/deployer/providers/ctcccloud-cdn/ctcccloud_cdn.go
@@ -0,0 +1,111 @@
+package ctcccloudcdn
+
+import (
+ "context"
+ "errors"
+ "fmt"
+ "log/slog"
+
+ "github.com/usual2970/certimate/internal/pkg/core/deployer"
+ "github.com/usual2970/certimate/internal/pkg/core/uploader"
+ uploadersp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/ctcccloud-cdn"
+ ctyuncdn "github.com/usual2970/certimate/internal/pkg/sdk3rd/ctyun/cdn"
+ typeutil "github.com/usual2970/certimate/internal/pkg/utils/type"
+)
+
+type DeployerConfig struct {
+ // 天翼云 AccessKeyId。
+ AccessKeyId string `json:"accessKeyId"`
+ // 天翼云 SecretAccessKey。
+ SecretAccessKey string `json:"secretAccessKey"`
+ // 加速域名(支持泛域名)。
+ Domain string `json:"domain"`
+}
+
+type DeployerProvider struct {
+ config *DeployerConfig
+ logger *slog.Logger
+ sdkClient *ctyuncdn.Client
+ sslUploader uploader.Uploader
+}
+
+var _ deployer.Deployer = (*DeployerProvider)(nil)
+
+func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) {
+ if config == nil {
+ panic("config is nil")
+ }
+
+ client, err := createSdkClient(config.AccessKeyId, config.SecretAccessKey)
+ if err != nil {
+ return nil, fmt.Errorf("failed to create sdk client: %w", err)
+ }
+
+ uploader, err := uploadersp.NewUploader(&uploadersp.UploaderConfig{
+ AccessKeyId: config.AccessKeyId,
+ SecretAccessKey: config.SecretAccessKey,
+ })
+ if err != nil {
+ return nil, fmt.Errorf("failed to create ssl uploader: %w", err)
+ }
+
+ return &DeployerProvider{
+ config: config,
+ logger: slog.Default(),
+ sdkClient: client,
+ sslUploader: uploader,
+ }, nil
+}
+
+func (d *DeployerProvider) WithLogger(logger *slog.Logger) deployer.Deployer {
+ if logger == nil {
+ d.logger = slog.New(slog.DiscardHandler)
+ } else {
+ d.logger = logger
+ }
+ return d
+}
+
+func (d *DeployerProvider) Deploy(ctx context.Context, certPEM string, privkeyPEM string) (*deployer.DeployResult, error) {
+ if d.config.Domain == "" {
+ return nil, errors.New("config `domain` is required")
+ }
+
+ // 上传证书到 CDN
+ upres, err := d.sslUploader.Upload(ctx, certPEM, privkeyPEM)
+ if err != nil {
+ return nil, fmt.Errorf("failed to upload certificate file: %w", err)
+ } else {
+ d.logger.Info("ssl certificate uploaded", slog.Any("result", upres))
+ }
+
+ // 查询域名配置信息
+ // REF: https://eop.ctyun.cn/ebp/ctapiDocument/search?sid=108&api=11304&data=161&isNormal=1&vid=154
+ queryDomainDetailReq := &ctyuncdn.QueryDomainDetailRequest{
+ Domain: typeutil.ToPtr(d.config.Domain),
+ }
+ queryDomainDetailResp, err := d.sdkClient.QueryDomainDetail(queryDomainDetailReq)
+ d.logger.Debug("sdk request 'cdn.QueryDomainDetail'", slog.Any("request", queryDomainDetailReq), slog.Any("response", queryDomainDetailResp))
+ if err != nil {
+ return nil, fmt.Errorf("failed to execute sdk request 'cdn.QueryDomainDetail': %w", err)
+ }
+
+ // 修改域名配置
+ // REF: https://eop.ctyun.cn/ebp/ctapiDocument/search?sid=108&api=11308&data=161&isNormal=1&vid=154
+ updateDomainReq := &ctyuncdn.UpdateDomainRequest{
+ Domain: typeutil.ToPtr(d.config.Domain),
+ HttpsStatus: typeutil.ToPtr("on"),
+ CertName: typeutil.ToPtr(upres.CertName),
+ }
+ updateDomainResp, err := d.sdkClient.UpdateDomain(updateDomainReq)
+ d.logger.Debug("sdk request 'cdn.UpdateDomain'", slog.Any("request", updateDomainReq), slog.Any("response", updateDomainResp))
+ if err != nil {
+ return nil, fmt.Errorf("failed to execute sdk request 'cdn.UpdateDomain': %w", err)
+ }
+
+ return &deployer.DeployResult{}, nil
+}
+
+func createSdkClient(accessKeyId, secretAccessKey string) (*ctyuncdn.Client, error) {
+ return ctyuncdn.NewClient(accessKeyId, secretAccessKey)
+}
diff --git a/internal/pkg/core/deployer/providers/ctcccloud-cdn/ctcccloud_cdn_test.go b/internal/pkg/core/deployer/providers/ctcccloud-cdn/ctcccloud_cdn_test.go
new file mode 100644
index 00000000..7a754305
--- /dev/null
+++ b/internal/pkg/core/deployer/providers/ctcccloud-cdn/ctcccloud_cdn_test.go
@@ -0,0 +1,75 @@
+package ctcccloudcdn_test
+
+import (
+ "context"
+ "flag"
+ "fmt"
+ "os"
+ "strings"
+ "testing"
+
+ provider "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/ctcccloud-cdn"
+)
+
+var (
+ fInputCertPath string
+ fInputKeyPath string
+ fAccessKeyId string
+ fSecretAccessKey string
+ fDomain string
+)
+
+func init() {
+ argsPrefix := "CERTIMATE_DEPLOYER_CTCCCLOUDCDN_"
+
+ flag.StringVar(&fInputCertPath, argsPrefix+"INPUTCERTPATH", "", "")
+ flag.StringVar(&fInputKeyPath, argsPrefix+"INPUTKEYPATH", "", "")
+ flag.StringVar(&fAccessKeyId, argsPrefix+"ACCESSKEYID", "", "")
+ flag.StringVar(&fSecretAccessKey, argsPrefix+"SECRETACCESSKEY", "", "")
+ flag.StringVar(&fDomain, argsPrefix+"DOMAIN", "", "")
+}
+
+/*
+Shell command to run this test:
+
+ go test -v ./ctcccloud_cdn_test.go -args \
+ --CERTIMATE_DEPLOYER_CTCCCLOUDCDN_INPUTCERTPATH="/path/to/your-input-cert.pem" \
+ --CERTIMATE_DEPLOYER_CTCCCLOUDCDN_INPUTKEYPATH="/path/to/your-input-key.pem" \
+ --CERTIMATE_DEPLOYER_CTCCCLOUDCDN_ACCESSKEYID="your-access-key-id" \
+ --CERTIMATE_DEPLOYER_CTCCCLOUDCDN_SECRETACCESSKEY="your-secret-access-key" \
+ --CERTIMATE_DEPLOYER_CTCCCLOUDCDN_DOMAIN="example.com"
+*/
+func TestDeploy(t *testing.T) {
+ flag.Parse()
+
+ t.Run("Deploy", func(t *testing.T) {
+ t.Log(strings.Join([]string{
+ "args:",
+ fmt.Sprintf("INPUTCERTPATH: %v", fInputCertPath),
+ fmt.Sprintf("INPUTKEYPATH: %v", fInputKeyPath),
+ fmt.Sprintf("ACCESSKEYID: %v", fAccessKeyId),
+ fmt.Sprintf("SECRETACCESSKEY: %v", fSecretAccessKey),
+ fmt.Sprintf("DOMAIN: %v", fDomain),
+ }, "\n"))
+
+ deployer, err := provider.NewDeployer(&provider.DeployerConfig{
+ AccessKeyId: fAccessKeyId,
+ SecretAccessKey: fSecretAccessKey,
+ Domain: fDomain,
+ })
+ if err != nil {
+ t.Errorf("err: %+v", err)
+ return
+ }
+
+ fInputCertData, _ := os.ReadFile(fInputCertPath)
+ fInputKeyData, _ := os.ReadFile(fInputKeyPath)
+ res, err := deployer.Deploy(context.Background(), string(fInputCertData), string(fInputKeyData))
+ if err != nil {
+ t.Errorf("err: %+v", err)
+ return
+ }
+
+ t.Logf("ok: %v", res)
+ })
+}
diff --git a/internal/pkg/core/uploader/providers/ctcccloud-cdn/ctcccloud_cdn.go b/internal/pkg/core/uploader/providers/ctcccloud-cdn/ctcccloud_cdn.go
new file mode 100644
index 00000000..6281ede8
--- /dev/null
+++ b/internal/pkg/core/uploader/providers/ctcccloud-cdn/ctcccloud_cdn.go
@@ -0,0 +1,171 @@
+package ctcccloudcdn
+
+import (
+ "context"
+ "fmt"
+ "log/slog"
+ "slices"
+ "strings"
+ "time"
+
+ "github.com/usual2970/certimate/internal/pkg/core/uploader"
+ ctyuncdn "github.com/usual2970/certimate/internal/pkg/sdk3rd/ctyun/cdn"
+ certutil "github.com/usual2970/certimate/internal/pkg/utils/cert"
+ typeutil "github.com/usual2970/certimate/internal/pkg/utils/type"
+)
+
+type UploaderConfig struct {
+ // 天翼云 AccessKeyId。
+ AccessKeyId string `json:"accessKeyId"`
+ // 天翼云 SecretAccessKey。
+ SecretAccessKey string `json:"secretAccessKey"`
+}
+
+type UploaderProvider struct {
+ config *UploaderConfig
+ logger *slog.Logger
+ sdkClient *ctyuncdn.Client
+}
+
+var _ uploader.Uploader = (*UploaderProvider)(nil)
+
+func NewUploader(config *UploaderConfig) (*UploaderProvider, error) {
+ if config == nil {
+ panic("config is nil")
+ }
+
+ client, err := createSdkClient(config.AccessKeyId, config.SecretAccessKey)
+ if err != nil {
+ return nil, fmt.Errorf("failed to create sdk client: %w", err)
+ }
+
+ return &UploaderProvider{
+ config: config,
+ logger: slog.Default(),
+ sdkClient: client,
+ }, nil
+}
+
+func (u *UploaderProvider) WithLogger(logger *slog.Logger) uploader.Uploader {
+ if logger == nil {
+ u.logger = slog.New(slog.DiscardHandler)
+ } else {
+ u.logger = logger
+ }
+ return u
+}
+
+func (u *UploaderProvider) Upload(ctx context.Context, certPEM string, privkeyPEM string) (*uploader.UploadResult, error) {
+ // 解析证书内容
+ certX509, err := certutil.ParseCertificateFromPEM(certPEM)
+ if err != nil {
+ return nil, err
+ }
+
+ // 查询证书列表,避免重复上传
+ // REF: https://eop.ctyun.cn/ebp/ctapiDocument/search?sid=108&api=10901&data=161&isNormal=1&vid=154
+ queryCertListPage := int32(1)
+ queryCertListPerPage := int32(1000)
+ for {
+ select {
+ case <-ctx.Done():
+ return nil, ctx.Err()
+ default:
+ }
+
+ queryCertListReq := &ctyuncdn.QueryCertListRequest{
+ Page: typeutil.ToPtr(queryCertListPage),
+ PerPage: typeutil.ToPtr(queryCertListPerPage),
+ UsageMode: typeutil.ToPtr(int32(0)),
+ }
+ queryCertListResp, err := u.sdkClient.QueryCertList(queryCertListReq)
+ u.logger.Debug("sdk request 'cdn.QueryCertList'", slog.Any("request", queryCertListReq), slog.Any("response", queryCertListResp))
+ if err != nil {
+ return nil, fmt.Errorf("failed to execute sdk request 'cdn.QueryCertList': %w", err)
+ }
+
+ if queryCertListResp.ReturnObj != nil {
+ for _, certRecord := range queryCertListResp.ReturnObj.Results {
+ // 对比证书通用名称
+ if !strings.EqualFold(certX509.Subject.CommonName, certRecord.CN) {
+ continue
+ }
+
+ // 对比证书扩展名称
+ if !slices.Equal(certX509.DNSNames, certRecord.SANs) {
+ continue
+ }
+
+ // 对比证书有效期
+ if !certX509.NotBefore.Equal(time.Unix(certRecord.IssueTime, 0).UTC()) {
+ continue
+ } else if !certX509.NotAfter.Equal(time.Unix(certRecord.ExpiresTime, 0).UTC()) {
+ continue
+ }
+
+ // 查询证书详情
+ // REF: https://eop.ctyun.cn/ebp/ctapiDocument/search?sid=108&api=10899&data=161&isNormal=1&vid=154
+ queryCertDetailReq := &ctyuncdn.QueryCertDetailRequest{
+ Id: typeutil.ToPtr(certRecord.Id),
+ }
+ queryCertDetailResp, err := u.sdkClient.QueryCertDetail(queryCertDetailReq)
+ u.logger.Debug("sdk request 'cdn.QueryCertDetail'", slog.Any("request", queryCertDetailReq), slog.Any("response", queryCertDetailResp))
+ if err != nil {
+ return nil, fmt.Errorf("failed to execute sdk request 'cdn.QueryCertDetail': %w", err)
+ } else if queryCertDetailResp.ReturnObj != nil && queryCertDetailResp.ReturnObj.Result != nil {
+ var isSameCert bool
+ if queryCertDetailResp.ReturnObj.Result.Certs == certPEM {
+ isSameCert = true
+ } else {
+ oldCertX509, err := certutil.ParseCertificateFromPEM(queryCertDetailResp.ReturnObj.Result.Certs)
+ if err != nil {
+ continue
+ }
+
+ isSameCert = certutil.EqualCertificate(certX509, oldCertX509)
+ }
+
+ // 如果已存在相同证书,直接返回
+ if isSameCert {
+ u.logger.Info("ssl certificate already exists")
+ return &uploader.UploadResult{
+ CertId: fmt.Sprintf("%d", queryCertDetailResp.ReturnObj.Result.Id),
+ CertName: queryCertDetailResp.ReturnObj.Result.Name,
+ }, nil
+ }
+ }
+ }
+ }
+
+ if queryCertListResp.ReturnObj == nil || len(queryCertListResp.ReturnObj.Results) < int(queryCertListPerPage) {
+ break
+ } else {
+ queryCertListPage++
+ }
+ }
+
+ // 生成新证书名(需符合天翼云命名规则)
+ certName := fmt.Sprintf("certimate-%d", time.Now().UnixMilli())
+
+ // 创建证书
+ // REF: https://eop.ctyun.cn/ebp/ctapiDocument/search?sid=108&api=10893&data=161&isNormal=1&vid=154
+ createCertReq := &ctyuncdn.CreateCertRequest{
+ Name: typeutil.ToPtr(certName),
+ Certs: typeutil.ToPtr(certPEM),
+ Key: typeutil.ToPtr(privkeyPEM),
+ }
+ createCertResp, err := u.sdkClient.CreateCert(createCertReq)
+ u.logger.Debug("sdk request 'cdn.CreateCert'", slog.Any("request", createCertReq), slog.Any("response", createCertResp))
+ if err != nil {
+ return nil, fmt.Errorf("failed to execute sdk request 'cdn.CreateCert': %w", err)
+ }
+
+ return &uploader.UploadResult{
+ CertId: fmt.Sprintf("%d", createCertResp.ReturnObj.Id),
+ CertName: certName,
+ }, nil
+}
+
+func createSdkClient(accessKeyId, secretAccessKey string) (*ctyuncdn.Client, error) {
+ return ctyuncdn.NewClient(accessKeyId, secretAccessKey)
+}
diff --git a/internal/pkg/core/uploader/providers/ctcccloud-cdn/ctcccloud_cdn_test.go b/internal/pkg/core/uploader/providers/ctcccloud-cdn/ctcccloud_cdn_test.go
new file mode 100644
index 00000000..4582132b
--- /dev/null
+++ b/internal/pkg/core/uploader/providers/ctcccloud-cdn/ctcccloud_cdn_test.go
@@ -0,0 +1,72 @@
+package ctcccloudcdn
+
+import (
+ "context"
+ "encoding/json"
+ "flag"
+ "fmt"
+ "os"
+ "strings"
+ "testing"
+
+ provider "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/ctcccloud-cdn"
+)
+
+var (
+ fInputCertPath string
+ fInputKeyPath string
+ fAccessKeyId string
+ fSecretAccessKey string
+)
+
+func init() {
+ argsPrefix := "CERTIMATE_UPLOADER_CTCCCLOUDCDN_"
+
+ flag.StringVar(&fInputCertPath, argsPrefix+"INPUTCERTPATH", "", "")
+ flag.StringVar(&fInputKeyPath, argsPrefix+"INPUTKEYPATH", "", "")
+ flag.StringVar(&fAccessKeyId, argsPrefix+"ACCESSKEYID", "", "")
+ flag.StringVar(&fSecretAccessKey, argsPrefix+"SECRETACCESSKEY", "", "")
+}
+
+/*
+Shell command to run this test:
+
+ go test -v ./ctcccloud_cdn_test.go -args \
+ --CERTIMATE_UPLOADER_CTCCCLOUDCDN_INPUTCERTPATH="/path/to/your-input-cert.pem" \
+ --CERTIMATE_UPLOADER_CTCCCLOUDCDN_INPUTKEYPATH="/path/to/your-input-key.pem" \
+ --CERTIMATE_DEPLOYER_CTCCCLOUDCDN_ACCESSKEYID="your-access-key-id" \
+ --CERTIMATE_DEPLOYER_CTCCCLOUDCDN_SECRETACCESSKEY="your-secret-access-key"
+*/
+func TestDeploy(t *testing.T) {
+ flag.Parse()
+
+ t.Run("Deploy", func(t *testing.T) {
+ t.Log(strings.Join([]string{
+ "args:",
+ fmt.Sprintf("INPUTCERTPATH: %v", fInputCertPath),
+ fmt.Sprintf("INPUTKEYPATH: %v", fInputKeyPath),
+ fmt.Sprintf("ACCESSKEYID: %v", fAccessKeyId),
+ fmt.Sprintf("SECRETACCESSKEY: %v", fSecretAccessKey),
+ }, "\n"))
+
+ uploader, err := provider.NewUploader(&provider.UploaderConfig{
+ AccessKeyId: fAccessKeyId,
+ SecretAccessKey: fSecretAccessKey,
+ })
+ if err != nil {
+ t.Errorf("err: %+v", err)
+ return
+ }
+
+ fInputCertData, _ := os.ReadFile(fInputCertPath)
+ fInputKeyData, _ := os.ReadFile(fInputKeyPath)
+ res, err := uploader.Upload(context.Background(), string(fInputCertData), string(fInputKeyData))
+ if err != nil {
+ t.Errorf("err: %+v", err)
+ return
+ }
+
+ sres, _ := json.Marshal(res)
+ t.Logf("ok: %s", string(sres))
+ })
+}
diff --git a/internal/pkg/core/uploader/providers/wangsu-certificate/wangsu_certificate.go b/internal/pkg/core/uploader/providers/wangsu-certificate/wangsu_certificate.go
index 6a12ceda..2a20f4e8 100644
--- a/internal/pkg/core/uploader/providers/wangsu-certificate/wangsu_certificate.go
+++ b/internal/pkg/core/uploader/providers/wangsu-certificate/wangsu_certificate.go
@@ -1,4 +1,4 @@
-package jdcloudssl
+package wangsucertificate
import (
"context"
@@ -9,9 +9,8 @@ import (
"strings"
"time"
- wangsusdk "github.com/usual2970/certimate/internal/pkg/sdk3rd/wangsu/certificate"
-
"github.com/usual2970/certimate/internal/pkg/core/uploader"
+ wangsusdk "github.com/usual2970/certimate/internal/pkg/sdk3rd/wangsu/certificate"
certutil "github.com/usual2970/certimate/internal/pkg/utils/cert"
typeutil "github.com/usual2970/certimate/internal/pkg/utils/type"
)
diff --git a/internal/pkg/core/uploader/providers/wangsu-certificate/wangsu_certificate_test.go b/internal/pkg/core/uploader/providers/wangsu-certificate/wangsu_certificate_test.go
index bdec8cfe..818fc7d0 100644
--- a/internal/pkg/core/uploader/providers/wangsu-certificate/wangsu_certificate_test.go
+++ b/internal/pkg/core/uploader/providers/wangsu-certificate/wangsu_certificate_test.go
@@ -1,4 +1,4 @@
-package jdcloudssl_test
+package wangsucertificate_test
import (
"context"
@@ -20,7 +20,7 @@ var (
)
func init() {
- argsPrefix := "CERTIMATE_UPLOADER_JDCLOUDSSL_"
+ argsPrefix := "CERTIMATE_UPLOADER_WANGSUCERTIFICATE_"
flag.StringVar(&fInputCertPath, argsPrefix+"INPUTCERTPATH", "", "")
flag.StringVar(&fInputKeyPath, argsPrefix+"INPUTKEYPATH", "", "")
diff --git a/internal/pkg/sdk3rd/ctyun/cdn/api_create_cert.go b/internal/pkg/sdk3rd/ctyun/cdn/api_create_cert.go
new file mode 100644
index 00000000..7a2290ab
--- /dev/null
+++ b/internal/pkg/sdk3rd/ctyun/cdn/api_create_cert.go
@@ -0,0 +1,41 @@
+package cdn
+
+import (
+ "context"
+ "net/http"
+)
+
+type CreateCertRequest struct {
+ Name *string `json:"name,omitempty"`
+ Certs *string `json:"certs,omitempty"`
+ Key *string `json:"key,omitempty"`
+}
+
+type CreateCertResponse struct {
+ baseResult
+
+ ReturnObj *struct {
+ Id int32 `json:"id"`
+ } `json:"returnObj,omitempty"`
+}
+
+func (c *Client) CreateCert(req *CreateCertRequest) (*CreateCertResponse, error) {
+ return c.CreateCertWithContext(context.Background(), req)
+}
+
+func (c *Client) CreateCertWithContext(ctx context.Context, req *CreateCertRequest) (*CreateCertResponse, error) {
+ httpreq, err := c.newRequest(http.MethodPost, "/v1/cert/creat-cert")
+ if err != nil {
+ return nil, err
+ } else {
+ httpreq.SetBody(req)
+ httpreq.SetContext(ctx)
+ }
+
+ result := &CreateCertResponse{}
+ if _, err := c.doRequestWithResult(httpreq, result); err != nil {
+ return result, err
+ }
+
+ return result, nil
+}
diff --git a/internal/pkg/sdk3rd/ctyun/cdn/api_query_cert_detail.go b/internal/pkg/sdk3rd/ctyun/cdn/api_query_cert_detail.go
new file mode 100644
index 00000000..02dfd5eb
--- /dev/null
+++ b/internal/pkg/sdk3rd/ctyun/cdn/api_query_cert_detail.go
@@ -0,0 +1,51 @@
+package cdn
+
+import (
+ "context"
+ "net/http"
+ "strconv"
+)
+
+type QueryCertDetailRequest struct {
+ Id *int32 `json:"id,omitempty"`
+ Name *string `json:"name,omitempty"`
+ UsageMode *int32 `json:"usage_mode,omitempty"`
+}
+
+type QueryCertDetailResponse struct {
+ baseResult
+
+ ReturnObj *struct {
+ Result *CertDetail `json:"result,omitempty"`
+ } `json:"returnObj,omitempty"`
+}
+
+func (c *Client) QueryCertDetail(req *QueryCertDetailRequest) (*QueryCertDetailResponse, error) {
+ return c.QueryCertDetailWithContext(context.Background(), req)
+}
+
+func (c *Client) QueryCertDetailWithContext(ctx context.Context, req *QueryCertDetailRequest) (*QueryCertDetailResponse, error) {
+ httpreq, err := c.newRequest(http.MethodGet, "/v1/cert/query-cert-detail")
+ if err != nil {
+ return nil, err
+ } else {
+ if req.Id != nil {
+ httpreq.SetQueryParam("id", strconv.Itoa(int(*req.Id)))
+ }
+ if req.Name != nil {
+ httpreq.SetQueryParam("name", *req.Name)
+ }
+ if req.UsageMode != nil {
+ httpreq.SetQueryParam("usage_mode", strconv.Itoa(int(*req.UsageMode)))
+ }
+
+ httpreq.SetContext(ctx)
+ }
+
+ result := &QueryCertDetailResponse{}
+ if _, err := c.doRequestWithResult(httpreq, result); err != nil {
+ return result, err
+ }
+
+ return result, nil
+}
diff --git a/internal/pkg/sdk3rd/ctyun/cdn/api_query_cert_list.go b/internal/pkg/sdk3rd/ctyun/cdn/api_query_cert_list.go
new file mode 100644
index 00000000..0f134594
--- /dev/null
+++ b/internal/pkg/sdk3rd/ctyun/cdn/api_query_cert_list.go
@@ -0,0 +1,55 @@
+package cdn
+
+import (
+ "context"
+ "net/http"
+ "strconv"
+)
+
+type QueryCertListRequest struct {
+ Page *int32 `json:"page,omitempty"`
+ PerPage *int32 `json:"per_page,omitempty"`
+ UsageMode *int32 `json:"usage_mode,omitempty"`
+}
+
+type QueryCertListResponse struct {
+ baseResult
+
+ ReturnObj *struct {
+ Results []*CertRecord `json:"result,omitempty"`
+ Page int32 `json:"page,omitempty"`
+ PerPage int32 `json:"per_page,omitempty"`
+ TotalPage int32 `json:"total_page,omitempty"`
+ TotalRecords int32 `json:"total_records,omitempty"`
+ } `json:"returnObj,omitempty"`
+}
+
+func (c *Client) QueryCertList(req *QueryCertListRequest) (*QueryCertListResponse, error) {
+ return c.QueryCertListWithContext(context.Background(), req)
+}
+
+func (c *Client) QueryCertListWithContext(ctx context.Context, req *QueryCertListRequest) (*QueryCertListResponse, error) {
+ httpreq, err := c.newRequest(http.MethodGet, "/v1/cert/query-cert-list")
+ if err != nil {
+ return nil, err
+ } else {
+ if req.Page != nil {
+ httpreq.SetQueryParam("page", strconv.Itoa(int(*req.Page)))
+ }
+ if req.PerPage != nil {
+ httpreq.SetQueryParam("per_page", strconv.Itoa(int(*req.PerPage)))
+ }
+ if req.UsageMode != nil {
+ httpreq.SetQueryParam("usage_mode", strconv.Itoa(int(*req.UsageMode)))
+ }
+
+ httpreq.SetContext(ctx)
+ }
+
+ result := &QueryCertListResponse{}
+ if _, err := c.doRequestWithResult(httpreq, result); err != nil {
+ return result, err
+ }
+
+ return result, nil
+}
diff --git a/internal/pkg/sdk3rd/ctyun/cdn/api_query_domain_detail.go b/internal/pkg/sdk3rd/ctyun/cdn/api_query_domain_detail.go
new file mode 100644
index 00000000..9a29b4f2
--- /dev/null
+++ b/internal/pkg/sdk3rd/ctyun/cdn/api_query_domain_detail.go
@@ -0,0 +1,64 @@
+package cdn
+
+import (
+ "context"
+ "net/http"
+)
+
+type QueryDomainDetailRequest struct {
+ Domain *string `json:"domain,omitempty"`
+ ProductCode *string `json:"product_code,omitempty"`
+ FunctionNames *string `json:"function_names,omitempty"`
+}
+
+type QueryDomainDetailResponse struct {
+ baseResult
+
+ ReturnObj *struct {
+ Domain string `json:"domain"`
+ ProductCode string `json:"product_code"`
+ Status int32 `json:"status"`
+ AreaScope int32 `json:"area_scope"`
+ Cname string `json:"cname"`
+ HttpsStatus string `json:"https_status"`
+ HttpsBasic *struct {
+ HttpsForce string `json:"https_force"`
+ HttpForce string `json:"http_force"`
+ ForceStatus string `json:"force_status"`
+ OriginProtocol string `json:"origin_protocol"`
+ } `json:"https_basic,omitempty"`
+ CertName string `json:"cert_name"`
+ Ssl string `json:"ssl"`
+ SslStapling string `json:"ssl_stapling"`
+ } `json:"returnObj,omitempty"`
+}
+
+func (c *Client) QueryDomainDetail(req *QueryDomainDetailRequest) (*QueryDomainDetailResponse, error) {
+ return c.QueryDomainDetailWithContext(context.Background(), req)
+}
+
+func (c *Client) QueryDomainDetailWithContext(ctx context.Context, req *QueryDomainDetailRequest) (*QueryDomainDetailResponse, error) {
+ httpreq, err := c.newRequest(http.MethodGet, "/v1/domain/query-domain-detail")
+ if err != nil {
+ return nil, err
+ } else {
+ if req.Domain != nil {
+ httpreq.SetQueryParam("domain", *req.Domain)
+ }
+ if req.ProductCode != nil {
+ httpreq.SetQueryParam("product_code", *req.ProductCode)
+ }
+ if req.FunctionNames != nil {
+ httpreq.SetQueryParam("function_names", *req.FunctionNames)
+ }
+
+ httpreq.SetContext(ctx)
+ }
+
+ result := &QueryDomainDetailResponse{}
+ if _, err := c.doRequestWithResult(httpreq, result); err != nil {
+ return result, err
+ }
+
+ return result, nil
+}
diff --git a/internal/pkg/sdk3rd/ctyun/cdn/api_update_domain.go b/internal/pkg/sdk3rd/ctyun/cdn/api_update_domain.go
new file mode 100644
index 00000000..65dd918c
--- /dev/null
+++ b/internal/pkg/sdk3rd/ctyun/cdn/api_update_domain.go
@@ -0,0 +1,37 @@
+package cdn
+
+import (
+ "context"
+ "net/http"
+)
+
+type UpdateDomainRequest struct {
+ Domain *string `json:"domain,omitempty"`
+ HttpsStatus *string `json:"https_status,omitempty"`
+ CertName *string `json:"cert_name,omitempty"`
+}
+
+type UpdateDomainResponse struct {
+ baseResult
+}
+
+func (c *Client) UpdateDomain(req *UpdateDomainRequest) (*UpdateDomainResponse, error) {
+ return c.UpdateDomainWithContext(context.Background(), req)
+}
+
+func (c *Client) UpdateDomainWithContext(ctx context.Context, req *UpdateDomainRequest) (*UpdateDomainResponse, error) {
+ httpreq, err := c.newRequest(http.MethodPost, "/v1/domain/update-domain")
+ if err != nil {
+ return nil, err
+ } else {
+ httpreq.SetBody(req)
+ httpreq.SetContext(ctx)
+ }
+
+ result := &UpdateDomainResponse{}
+ if _, err := c.doRequestWithResult(httpreq, result); err != nil {
+ return result, err
+ }
+
+ return result, nil
+}
diff --git a/internal/pkg/sdk3rd/ctyun/cdn/client.go b/internal/pkg/sdk3rd/ctyun/cdn/client.go
new file mode 100644
index 00000000..7a7896a6
--- /dev/null
+++ b/internal/pkg/sdk3rd/ctyun/cdn/client.go
@@ -0,0 +1,40 @@
+package cdn
+
+import (
+ "time"
+
+ "github.com/go-resty/resty/v2"
+ "github.com/usual2970/certimate/internal/pkg/sdk3rd/ctyun/openapi"
+)
+
+const endpoint = "https://ctcdn-global.ctapi.ctyun.cn"
+
+type Client struct {
+ client *openapi.Client
+}
+
+func NewClient(accessKeyId, secretAccessKey string) (*Client, error) {
+ client, err := openapi.NewClient(endpoint, accessKeyId, secretAccessKey)
+ if err != nil {
+ return nil, err
+ }
+
+ return &Client{client: client}, nil
+}
+
+func (c *Client) SetTimeout(timeout time.Duration) *Client {
+ c.client.SetTimeout(timeout)
+ return c
+}
+
+func (c *Client) newRequest(method string, path string) (*resty.Request, error) {
+ return c.client.NewRequest(method, path)
+}
+
+func (c *Client) doRequest(request *resty.Request) (*resty.Response, error) {
+ return c.client.DoRequest(request)
+}
+
+func (c *Client) doRequestWithResult(request *resty.Request, result any) (*resty.Response, error) {
+ return c.client.DoRequestWithResult(request, result)
+}
diff --git a/internal/pkg/sdk3rd/ctyun/cdn/types.go b/internal/pkg/sdk3rd/ctyun/cdn/types.go
new file mode 100644
index 00000000..c6366c56
--- /dev/null
+++ b/internal/pkg/sdk3rd/ctyun/cdn/types.go
@@ -0,0 +1,30 @@
+package cdn
+
+import "encoding/json"
+
+type baseResult struct {
+ StatusCode json.RawMessage `json:"statusCode,omitempty"`
+ Message *string `json:"message,omitempty"`
+ Error *string `json:"error,omitempty"`
+ ErrorMessage *string `json:"errorMessage,omitempty"`
+ RequestId *string `json:"requestId,omitempty"`
+}
+
+type CertRecord struct {
+ Id int32 `json:"id"`
+ Name string `json:"name"`
+ CN string `json:"cn"`
+ SANs []string `json:"sans"`
+ UsageMode int32 `json:"usage_mode"`
+ State int32 `json:"state"`
+ ExpiresTime int64 `json:"expires"`
+ IssueTime int64 `json:"issue"`
+ Issuer string `json:"issuer"`
+ CreatedTime int64 `json:"created"`
+}
+
+type CertDetail struct {
+ CertRecord
+ Certs string `json:"certs"`
+ Key string `json:"key"`
+}
diff --git a/internal/pkg/sdk3rd/ctyun/dns/api_add_record.go b/internal/pkg/sdk3rd/ctyun/dns/api_add_record.go
index 8bcdcb21..86227e5f 100644
--- a/internal/pkg/sdk3rd/ctyun/dns/api_add_record.go
+++ b/internal/pkg/sdk3rd/ctyun/dns/api_add_record.go
@@ -29,16 +29,16 @@ func (c *Client) AddRecord(req *AddRecordRequest) (*AddRecordResponse, error) {
}
func (c *Client) AddRecordWithContext(ctx context.Context, req *AddRecordRequest) (*AddRecordResponse, error) {
- request, err := c.newRequest(http.MethodPost, "/v2/addRecord")
+ httpreq, err := c.newRequest(http.MethodPost, "/v2/addRecord")
if err != nil {
return nil, err
} else {
- request.SetContext(ctx)
- request.SetBody(req)
+ httpreq.SetBody(req)
+ httpreq.SetContext(ctx)
}
result := &AddRecordResponse{}
- if _, err := c.doRequestWithResult(request, result); err != nil {
+ if _, err := c.doRequestWithResult(httpreq, result); err != nil {
return result, err
}
diff --git a/internal/pkg/sdk3rd/ctyun/dns/api_delete_record.go b/internal/pkg/sdk3rd/ctyun/dns/api_delete_record.go
index 679e6fcf..ad35a349 100644
--- a/internal/pkg/sdk3rd/ctyun/dns/api_delete_record.go
+++ b/internal/pkg/sdk3rd/ctyun/dns/api_delete_record.go
@@ -18,16 +18,16 @@ func (c *Client) DeleteRecord(req *DeleteRecordRequest) (*DeleteRecordResponse,
}
func (c *Client) DeleteRecordWithContext(ctx context.Context, req *DeleteRecordRequest) (*DeleteRecordResponse, error) {
- request, err := c.newRequest(http.MethodPost, "/v2/deleteRecord")
+ httpreq, err := c.newRequest(http.MethodPost, "/v2/deleteRecord")
if err != nil {
return nil, err
} else {
- request.SetContext(ctx)
- request.SetBody(req)
+ httpreq.SetBody(req)
+ httpreq.SetContext(ctx)
}
result := &DeleteRecordResponse{}
- if _, err := c.doRequestWithResult(request, result); err != nil {
+ if _, err := c.doRequestWithResult(httpreq, result); err != nil {
return result, err
}
diff --git a/internal/pkg/sdk3rd/ctyun/dns/api_query_record_list.go b/internal/pkg/sdk3rd/ctyun/dns/api_query_record_list.go
index 4d7f1617..d94afcde 100644
--- a/internal/pkg/sdk3rd/ctyun/dns/api_query_record_list.go
+++ b/internal/pkg/sdk3rd/ctyun/dns/api_query_record_list.go
@@ -18,16 +18,7 @@ type QueryRecordListResponse struct {
baseResult
ReturnObj *struct {
- Records []*struct {
- RecordId int32 `json:"recordId"`
- Host string `json:"host"`
- Type string `json:"type"`
- LineCode string `json:"lineCode"`
- Value string `json:"value"`
- TTL int32 `json:"ttl"`
- State int32 `json:"state"`
- Remark string `json:"remark"`
- } `json:"records,omitempty"`
+ Records []*DnsRecord `json:"records,omitempty"`
} `json:"returnObj,omitempty"`
}
@@ -36,16 +27,16 @@ func (c *Client) QueryRecordList(req *QueryRecordListRequest) (*QueryRecordListR
}
func (c *Client) QueryRecordListWithContext(ctx context.Context, req *QueryRecordListRequest) (*QueryRecordListResponse, error) {
- request, err := c.newRequest(http.MethodGet, "/v2/queryRecordList")
+ httpreq, err := c.newRequest(http.MethodGet, "/v2/queryRecordList")
if err != nil {
return nil, err
} else {
- request.SetContext(ctx)
- request.SetBody(req)
+ httpreq.SetBody(req)
+ httpreq.SetContext(ctx)
}
result := &QueryRecordListResponse{}
- if _, err := c.doRequestWithResult(request, result); err != nil {
+ if _, err := c.doRequestWithResult(httpreq, result); err != nil {
return result, err
}
diff --git a/internal/pkg/sdk3rd/ctyun/dns/api_update_record.go b/internal/pkg/sdk3rd/ctyun/dns/api_update_record.go
index ca827ce3..e6dbdc7e 100644
--- a/internal/pkg/sdk3rd/ctyun/dns/api_update_record.go
+++ b/internal/pkg/sdk3rd/ctyun/dns/api_update_record.go
@@ -30,16 +30,16 @@ func (c *Client) UpdateRecord(req *UpdateRecordRequest) (*UpdateRecordResponse,
}
func (c *Client) UpdateRecordWithContext(ctx context.Context, req *UpdateRecordRequest) (*UpdateRecordResponse, error) {
- request, err := c.newRequest(http.MethodPost, "/v2/updateRecord")
+ httpreq, err := c.newRequest(http.MethodPost, "/v2/updateRecord")
if err != nil {
return nil, err
} else {
- request.SetContext(ctx)
- request.SetBody(req)
+ httpreq.SetBody(req)
+ httpreq.SetContext(ctx)
}
result := &UpdateRecordResponse{}
- if _, err := c.doRequestWithResult(request, result); err != nil {
+ if _, err := c.doRequestWithResult(httpreq, result); err != nil {
return result, err
}
diff --git a/internal/pkg/sdk3rd/ctyun/dns/types.go b/internal/pkg/sdk3rd/ctyun/dns/types.go
index 8fe2eabd..bcd21d76 100644
--- a/internal/pkg/sdk3rd/ctyun/dns/types.go
+++ b/internal/pkg/sdk3rd/ctyun/dns/types.go
@@ -9,3 +9,14 @@ type baseResult struct {
ErrorMessage *string `json:"errorMessage,omitempty"`
RequestId *string `json:"requestId,omitempty"`
}
+
+type DnsRecord struct {
+ RecordId int32 `json:"recordId"`
+ Host string `json:"host"`
+ Type string `json:"type"`
+ LineCode string `json:"lineCode"`
+ Value string `json:"value"`
+ TTL int32 `json:"ttl"`
+ State int32 `json:"state"`
+ Remark string `json:"remark"`
+}
diff --git a/internal/pkg/sdk3rd/ctyun/openapi/client.go b/internal/pkg/sdk3rd/ctyun/openapi/client.go
index 6960c83c..ad790dc5 100644
--- a/internal/pkg/sdk3rd/ctyun/openapi/client.go
+++ b/internal/pkg/sdk3rd/ctyun/openapi/client.go
@@ -22,16 +22,16 @@ type Client struct {
func NewClient(endpoint, accessKeyId, secretAccessKey string) (*Client, error) {
if endpoint == "" {
- return nil, fmt.Errorf("sdk error: unset endpoint")
+ return nil, fmt.Errorf("sdkerr: unset endpoint")
}
if _, err := url.Parse(endpoint); err != nil {
- return nil, fmt.Errorf("sdk error: invalid endpoint: %w", err)
+ return nil, fmt.Errorf("sdkerr: invalid endpoint: %w", err)
}
if accessKeyId == "" {
- return nil, fmt.Errorf("sdk error: unset accessKey")
+ return nil, fmt.Errorf("sdkerr: unset accessKey")
}
if secretAccessKey == "" {
- return nil, fmt.Errorf("sdk error: unset secretKey")
+ return nil, fmt.Errorf("sdkerr: unset secretKey")
}
client := resty.New().
@@ -83,7 +83,7 @@ func NewClient(endpoint, accessKeyId, secretAccessKey string) (*Client, error) {
hasher.Write([]byte(accessKeyId))
kak := hasher.Sum(nil)
- // 生成 kdata
+ // 生成 kdate
hasher = hmac.New(sha256.New, kak)
hasher.Write([]byte(now.Format("20060102")))
kdate := hasher.Sum(nil)
@@ -114,10 +114,10 @@ func (c *Client) SetTimeout(timeout time.Duration) *Client {
func (c *Client) NewRequest(method string, path string) (*resty.Request, error) {
if method == "" {
- return nil, fmt.Errorf("sdk error: unset method")
+ return nil, fmt.Errorf("sdkerr: unset method")
}
if path == "" {
- return nil, fmt.Errorf("sdk error: unset path")
+ return nil, fmt.Errorf("sdkerr: unset path")
}
req := c.client.R()
@@ -128,7 +128,7 @@ func (c *Client) NewRequest(method string, path string) (*resty.Request, error)
func (c *Client) DoRequest(request *resty.Request) (*resty.Response, error) {
if request == nil {
- return nil, fmt.Errorf("sdk error: nil request")
+ return nil, fmt.Errorf("sdkerr: nil request")
}
// WARN:
@@ -136,9 +136,9 @@ func (c *Client) DoRequest(request *resty.Request) (*resty.Response, error) {
resp, err := request.Send()
if err != nil {
- return resp, fmt.Errorf("sdk error: failed to send request: %w", err)
+ return resp, fmt.Errorf("sdkerr: failed to send request: %w", err)
} else if resp.IsError() {
- return resp, fmt.Errorf("sdk error: unexpected status code: %d, resp: %s", resp.StatusCode(), resp.String())
+ return resp, fmt.Errorf("sdkerr: unexpected status code: %d, resp: %s", resp.StatusCode(), resp.String())
}
return resp, nil
@@ -146,7 +146,7 @@ func (c *Client) DoRequest(request *resty.Request) (*resty.Response, error) {
func (c *Client) DoRequestWithResult(request *resty.Request, result any) (*resty.Response, error) {
if request == nil {
- return nil, fmt.Errorf("sdk error: nil request")
+ return nil, fmt.Errorf("sdkerr: nil request")
}
response, err := c.DoRequest(request)
@@ -159,7 +159,7 @@ func (c *Client) DoRequestWithResult(request *resty.Request, result any) (*resty
if len(response.Body()) != 0 {
if err := json.Unmarshal(response.Body(), &result); err != nil {
- return response, fmt.Errorf("sdk error: failed to unmarshal response: %w", err)
+ return response, fmt.Errorf("sdkerr: failed to unmarshal response: %w", err)
}
}
diff --git a/internal/pkg/utils/slice/slice.go b/internal/pkg/utils/slice/iter.go
similarity index 100%
rename from internal/pkg/utils/slice/slice.go
rename to internal/pkg/utils/slice/iter.go
diff --git a/internal/pkg/utils/type/assert.go b/internal/pkg/utils/type/assert.go
index 509a77cc..e1413041 100644
--- a/internal/pkg/utils/type/assert.go
+++ b/internal/pkg/utils/type/assert.go
@@ -1,6 +1,8 @@
package typeutil
-import "reflect"
+import (
+ "reflect"
+)
// 判断对象是否为 nil。
// 与直接使用 `obj == nil` 不同,该函数会正确判断接口类型对象的真实值是否为空。
diff --git a/internal/pkg/utils/type/cast.go b/internal/pkg/utils/type/cast.go
index 77eb9dad..8c34dc0f 100644
--- a/internal/pkg/utils/type/cast.go
+++ b/internal/pkg/utils/type/cast.go
@@ -1,6 +1,8 @@
package typeutil
-import "reflect"
+import (
+ "reflect"
+)
// 将对象转换为指针。
//
diff --git a/ui/src/components/workflow/node/DeployNodeConfigForm.tsx b/ui/src/components/workflow/node/DeployNodeConfigForm.tsx
index 59e5146e..ba8f04b9 100644
--- a/ui/src/components/workflow/node/DeployNodeConfigForm.tsx
+++ b/ui/src/components/workflow/node/DeployNodeConfigForm.tsx
@@ -48,6 +48,7 @@ import DeployNodeConfigFormBaotaWAFSiteConfig from "./DeployNodeConfigFormBaotaW
import DeployNodeConfigFormBunnyCDNConfig from "./DeployNodeConfigFormBunnyCDNConfig.tsx";
import DeployNodeConfigFormBytePlusCDNConfig from "./DeployNodeConfigFormBytePlusCDNConfig";
import DeployNodeConfigFormCdnflyConfig from "./DeployNodeConfigFormCdnflyConfig";
+import DeployNodeConfigFormCTCCCloudCDNConfig from "./DeployNodeConfigFormCTCCCloudCDNConfig";
import DeployNodeConfigFormDogeCloudCDNConfig from "./DeployNodeConfigFormDogeCloudCDNConfig";
import DeployNodeConfigFormEdgioApplicationsConfig from "./DeployNodeConfigFormEdgioApplicationsConfig";
import DeployNodeConfigFormFlexCDNConfig from "./DeployNodeConfigFormFlexCDNConfig";
@@ -265,6 +266,8 @@ const DeployNodeConfigForm = forwardRef;
case DEPLOYMENT_PROVIDERS.CDNFLY:
return ;
+ case DEPLOYMENT_PROVIDERS.CTCCCLOUD_CDN:
+ return ;
case DEPLOYMENT_PROVIDERS.DOGECLOUD_CDN:
return ;
case DEPLOYMENT_PROVIDERS.EDGIO_APPLICATIONS:
diff --git a/ui/src/components/workflow/node/DeployNodeConfigFormCTCCCloudCDNConfig.tsx b/ui/src/components/workflow/node/DeployNodeConfigFormCTCCCloudCDNConfig.tsx
new file mode 100644
index 00000000..b7f564e5
--- /dev/null
+++ b/ui/src/components/workflow/node/DeployNodeConfigFormCTCCCloudCDNConfig.tsx
@@ -0,0 +1,65 @@
+import { useTranslation } from "react-i18next";
+import { Form, type FormInstance, Input } from "antd";
+import { createSchemaFieldRule } from "antd-zod";
+import { z } from "zod";
+
+import { validDomainName } from "@/utils/validators";
+
+type DeployNodeConfigFormCTCCCloudCDNConfigFieldValues = Nullish<{
+ domain: string;
+}>;
+
+export type DeployNodeConfigFormCTCCCloudCDNConfigProps = {
+ form: FormInstance;
+ formName: string;
+ disabled?: boolean;
+ initialValues?: DeployNodeConfigFormCTCCCloudCDNConfigFieldValues;
+ onValuesChange?: (values: DeployNodeConfigFormCTCCCloudCDNConfigFieldValues) => void;
+};
+
+const initFormModel = (): DeployNodeConfigFormCTCCCloudCDNConfigFieldValues => {
+ return {};
+};
+
+const DeployNodeConfigFormCTCCCloudCDNConfig = ({
+ form: formInst,
+ formName,
+ disabled,
+ initialValues,
+ onValuesChange,
+}: DeployNodeConfigFormCTCCCloudCDNConfigProps) => {
+ const { t } = useTranslation();
+
+ const formSchema = z.object({
+ domain: z
+ .string({ message: t("workflow_node.deploy.form.ctcccloud_cdn_domain.placeholder") })
+ .refine((v) => validDomainName(v, { allowWildcard: true }), t("common.errmsg.domain_invalid")),
+ });
+ const formRule = createSchemaFieldRule(formSchema);
+
+ const handleFormChange = (_: unknown, values: z.infer) => {
+ onValuesChange?.(values);
+ };
+
+ return (
+ }
+ >
+
+
+
+ );
+};
+
+export default DeployNodeConfigFormCTCCCloudCDNConfig;
diff --git a/ui/src/domain/provider.ts b/ui/src/domain/provider.ts
index 212ded80..29676de9 100644
--- a/ui/src/domain/provider.ts
+++ b/ui/src/domain/provider.ts
@@ -124,6 +124,7 @@ export const accessProvidersMap: Maphttps://cdn-console.ctyun.cn",
"workflow_node.deploy.form.dogecloud_cdn_domain.label": "Doge Cloud CDN domain",
"workflow_node.deploy.form.dogecloud_cdn_domain.placeholder": "Please enter Doge Cloud CDN domain name",
- "workflow_node.deploy.form.dogecloud_cdn_domain.tooltip": "For more information, see https://console.dogecloud.com/",
+ "workflow_node.deploy.form.dogecloud_cdn_domain.tooltip": "For more information, see https://console.dogecloud.com",
"workflow_node.deploy.form.edgio_applications_environment_id.label": "Edgio Applications environment ID",
"workflow_node.deploy.form.edgio_applications_environment_id.placeholder": "Please enter Edgio Applications environment ID",
"workflow_node.deploy.form.edgio_applications_environment_id.tooltip": "For more information, see https://edgio.app/",
@@ -477,13 +480,13 @@
"workflow_node.deploy.form.jdcloud_alb_snidomain.tooltip": "For more information, see https://cns-console.jdcloud.com/host/loadBalance/list",
"workflow_node.deploy.form.jdcloud_cdn_domain.label": "JD Cloud CDN domain",
"workflow_node.deploy.form.jdcloud_cdn_domain.placeholder": "Please enter JD Cloud CDN domain name",
- "workflow_node.deploy.form.jdcloud_cdn_domain.tooltip": "For more information, see https://cdn-console.jdcloud.com/",
+ "workflow_node.deploy.form.jdcloud_cdn_domain.tooltip": "For more information, see https://cdn-console.jdcloud.com",
"workflow_node.deploy.form.jdcloud_live_domain.label": "JD Cloud Live Video play domain",
"workflow_node.deploy.form.jdcloud_live_domain.placeholder": "Please enter JD Cloud Live Video play domain name",
- "workflow_node.deploy.form.jdcloud_live_domain.tooltip": "For more information, see https://live-console.jdcloud.com/",
+ "workflow_node.deploy.form.jdcloud_live_domain.tooltip": "For more information, see https://live-console.jdcloud.com",
"workflow_node.deploy.form.jdcloud_vod_domain.label": "JD Cloud VOD domain",
"workflow_node.deploy.form.jdcloud_vod_domain.placeholder": "Please enter JD Cloud VOD domain name",
- "workflow_node.deploy.form.jdcloud_vod_domain.tooltip": "For more information, see https://vod-console.jdcloud.com/",
+ "workflow_node.deploy.form.jdcloud_vod_domain.tooltip": "For more information, see https://vod-console.jdcloud.com",
"workflow_node.deploy.form.k8s_namespace.label": "Kubernetes Namespace",
"workflow_node.deploy.form.k8s_namespace.placeholder": "Please enter Kubernetes Namespace",
"workflow_node.deploy.form.k8s_namespace.tooltip": "For more information, see https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/",
diff --git a/ui/src/i18n/locales/zh/nls.provider.json b/ui/src/i18n/locales/zh/nls.provider.json
index f021a586..2134e402 100644
--- a/ui/src/i18n/locales/zh/nls.provider.json
+++ b/ui/src/i18n/locales/zh/nls.provider.json
@@ -60,6 +60,12 @@
"provider.cmcccloud.dns": "移动云 - 云解析 DNS",
"provider.constellix": "Constellix",
"provider.ctcccloud": "天翼云",
+ "provider.ctcccloud.accessone": "天翼云 - 边缘安全加速平台 AccessOne",
+ "provider.ctcccloud.cdn": "天翼云 - 内容分发网络 CDN",
+ "provider.ctcccloud.cms_upload": "天翼云 - 上传到证书管理服务 CMS",
+ "provider.ctcccloud.elb": "天翼云 - 弹性负载均衡 ELB",
+ "provider.ctcccloud.icdn": "天翼云 - 全站加速 ICDN",
+ "provider.ctcccloud.lvdn": "天翼云 - 视频直播 LVDN",
"provider.ctcccloud.smartdns": "天翼云 - 智能 DNS",
"provider.cucccloud": "联通云",
"provider.desec": "deSEC",
diff --git a/ui/src/i18n/locales/zh/nls.workflow.nodes.json b/ui/src/i18n/locales/zh/nls.workflow.nodes.json
index 7e216a69..b326b3e7 100644
--- a/ui/src/i18n/locales/zh/nls.workflow.nodes.json
+++ b/ui/src/i18n/locales/zh/nls.workflow.nodes.json
@@ -225,7 +225,7 @@
"workflow_node.deploy.form.aliyun_fc_service_version.placeholder": "请选择阿里云 FC 服务版本",
"workflow_node.deploy.form.aliyun_fc_domain.label": "阿里云 FC 自定义域名",
"workflow_node.deploy.form.aliyun_fc_domain.placeholder": "请输入阿里云 FC 自定义域名(支持泛域名)",
- "workflow_node.deploy.form.aliyun_fc_domain.tooltip": "这是什么?请参阅 see https://fcnext.console.aliyun.com/",
+ "workflow_node.deploy.form.aliyun_fc_domain.tooltip": "这是什么?请参阅 see https://fcnext.console.aliyun.com",
"workflow_node.deploy.form.aliyun_ga_resource_type.label": "证书部署方式",
"workflow_node.deploy.form.aliyun_ga_resource_type.placeholder": "请选择证书部署方式",
"workflow_node.deploy.form.aliyun_ga_resource_type.option.accelerator.label": "替换指定全球加速器下的全部 HTTPS 监听的证书",
@@ -397,6 +397,9 @@
"workflow_node.deploy.form.cdnfly_certificate_id.label": "Cdnfly 证书 ID",
"workflow_node.deploy.form.cdnfly_certificate_id.placeholder": "请输入 Cdnfly 证书 ID",
"workflow_node.deploy.form.cdnfly_certificate_id.tooltip": "请登录 Cdnfly 控制台查看。",
+ "workflow_node.deploy.form.ctcccloud_cdn_domain.label": "天翼云 CDN 加速域名",
+ "workflow_node.deploy.form.ctcccloud_cdn_domain.placeholder": "请输入天翼云 CDN 加速域名(支持泛域名)",
+ "workflow_node.deploy.form.ctcccloud_cdn_domain.tooltip": "这是什么?请参阅 https://cdn-console.ctyun.cn",
"workflow_node.deploy.form.dogecloud_cdn_domain.label": "多吉云 CDN 加速域名",
"workflow_node.deploy.form.dogecloud_cdn_domain.placeholder": "请输入多吉云 CDN 加速域名",
"workflow_node.deploy.form.dogecloud_cdn_domain.tooltip": "这是什么?请参阅 https://console.dogecloud.com",
@@ -476,13 +479,13 @@
"workflow_node.deploy.form.jdcloud_alb_snidomain.tooltip": "这是什么?请参阅 https://cns-console.jdcloud.com/host/loadBalance/list
不填写时,将替换监听器的默认证书;否则,将替换扩展域名证书。",
"workflow_node.deploy.form.jdcloud_cdn_domain.label": "京东云 CDN 加速域名",
"workflow_node.deploy.form.jdcloud_cdn_domain.placeholder": "请输入京东云 CDN 加速域名(支持泛域名)",
- "workflow_node.deploy.form.jdcloud_cdn_domain.tooltip": "这是什么?请参阅 https://cdn-console.jdcloud.com/",
+ "workflow_node.deploy.form.jdcloud_cdn_domain.tooltip": "这是什么?请参阅 https://cdn-console.jdcloud.com",
"workflow_node.deploy.form.jdcloud_live_domain.label": "京东云视频直播播放域名",
"workflow_node.deploy.form.jdcloud_live_domain.placeholder": "请输入京东云视频直播播放域名",
"workflow_node.deploy.form.jdcloud_live_domain.tooltip": "这是什么?请参阅 https://live-console.jdcloud.com",
"workflow_node.deploy.form.jdcloud_vod_domain.label": "京东云视频点播加速域名",
"workflow_node.deploy.form.jdcloud_vod_domain.placeholder": "请输入京东云视频点播加速域名",
- "workflow_node.deploy.form.jdcloud_vod_domain.tooltip": "这是什么?请参阅 https://vod-console.jdcloud.com/",
+ "workflow_node.deploy.form.jdcloud_vod_domain.tooltip": "这是什么?请参阅 https://vod-console.jdcloud.com",
"workflow_node.deploy.form.k8s_namespace.label": "Kubernetes 命名空间",
"workflow_node.deploy.form.k8s_namespace.placeholder": "请输入 Kubernetes 命名空间",
"workflow_node.deploy.form.k8s_namespace.tooltip": "这是什么?请参阅 https://kubernetes.io/zh-cn/docs/concepts/overview/working-with-objects/namespaces/",