mirror of
https://github.com/certimate-go/certimate.git
synced 2026-09-24 23:10:13 +08:00
feat(provider): new deployment provider: tencentcloud eomakers
This commit is contained in:
@@ -0,0 +1,7 @@
|
||||
package tencentcloudeomakers
|
||||
|
||||
const (
|
||||
DomainMatchPatternExact = "exact"
|
||||
DomainMatchPatternWildcard = "wildcard"
|
||||
DomainMatchPatternCertSan = "certsan"
|
||||
)
|
||||
@@ -0,0 +1,357 @@
|
||||
package tencentcloudeomakers
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/x509"
|
||||
"errors"
|
||||
"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"
|
||||
|
||||
tceo "github.com/certimate-go/certimate/pkg/sdk3rd-trimmed/github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/teo/v20220901"
|
||||
|
||||
"github.com/certimate-go/certimate/pkg/core"
|
||||
cmgrimpl "github.com/certimate-go/certimate/pkg/core/certmgr/providers/tencentcloud-ssl"
|
||||
tceomakersssdk "github.com/certimate-go/certimate/pkg/sdk3rd/tencentcloud/teomakers"
|
||||
xcert "github.com/certimate-go/certimate/pkg/utils/cert"
|
||||
xcerthostname "github.com/certimate-go/certimate/pkg/utils/cert/hostname"
|
||||
xcertkey "github.com/certimate-go/certimate/pkg/utils/cert/key"
|
||||
xtencentcloud "github.com/certimate-go/certimate/pkg/utils/third-party/tencentcloud"
|
||||
)
|
||||
|
||||
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"`
|
||||
// EdgeOne Makers API Token。
|
||||
MakersApiToken string `json:"makersApiToken"`
|
||||
// EdgeOne Makers 项目 ID。
|
||||
MakersProjectId string `json:"makersProjectId"`
|
||||
// 域名匹配模式。
|
||||
// 零值时默认值 [DOMAIN_MATCH_PATTERN_EXACT]。
|
||||
DomainMatchPattern string `json:"domainMatchPattern,omitempty"`
|
||||
// 加速域名列表(支持泛域名)。
|
||||
Domains []string `json:"domains"`
|
||||
// 是否启用多证书模式。
|
||||
EnableMultipleSSL bool `json:"enableMultipleSSL,omitempty"`
|
||||
}
|
||||
|
||||
type Deployer struct {
|
||||
config *DeployerConfig
|
||||
logger *slog.Logger
|
||||
sdkClients *wSDKClients
|
||||
sdkCertmgr core.Certmgr
|
||||
}
|
||||
|
||||
var _ Provider = (*Deployer)(nil)
|
||||
|
||||
type wSDKClients struct {
|
||||
TEO *tceo.Client
|
||||
TEOMakers *tceomakersssdk.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, config.MakersApiToken)
|
||||
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.Ternary(xtencentcloud.IsIntlAPIEndpoint(config.Endpoint), "ssl.intl.tencentcloudapi.com", ""),
|
||||
})
|
||||
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) {
|
||||
if d.config.MakersProjectId == "" {
|
||||
return nil, fmt.Errorf("config `makersProjectId` is required")
|
||||
}
|
||||
|
||||
// 上传证书
|
||||
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))
|
||||
}
|
||||
|
||||
// 获取全部可部署的域名列表
|
||||
domainsInMakers, err := d.getAllDomainsInProject(ctx, d.config.MakersProjectId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 获取待部署的域名列表
|
||||
var domains []string
|
||||
switch d.config.DomainMatchPattern {
|
||||
case "", DomainMatchPatternExact:
|
||||
{
|
||||
if len(d.config.Domains) == 0 {
|
||||
return nil, fmt.Errorf("config `domains` is required")
|
||||
}
|
||||
|
||||
domains = d.config.Domains
|
||||
}
|
||||
|
||||
case DomainMatchPatternWildcard:
|
||||
{
|
||||
if len(d.config.Domains) == 0 {
|
||||
return nil, fmt.Errorf("config `domains` is required")
|
||||
}
|
||||
|
||||
domainCandidates := lo.Map(domainsInMakers, func(domainInfo *tceomakersssdk.PagesZoneCustomDomain, _ int) string {
|
||||
return lo.FromPtr(domainInfo.Domain)
|
||||
})
|
||||
domains = lo.Filter(domainCandidates, func(domain string, _ int) bool {
|
||||
for _, configDomain := range d.config.Domains {
|
||||
if xcerthostname.IsMatch(configDomain, domain) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
})
|
||||
if len(domains) == 0 {
|
||||
return nil, fmt.Errorf("could not find any domains matched by wildcard")
|
||||
}
|
||||
}
|
||||
|
||||
case DomainMatchPatternCertSan:
|
||||
{
|
||||
domainCandidates := lo.Map(domainsInMakers, func(domainInfo *tceomakersssdk.PagesZoneCustomDomain, _ int) string {
|
||||
return lo.FromPtr(domainInfo.Domain)
|
||||
})
|
||||
domains = lo.Filter(domainCandidates, func(domain string, _ int) bool {
|
||||
return xcerthostname.IsMatchByCertificatePEM(certPEM, domain)
|
||||
})
|
||||
if len(domains) == 0 {
|
||||
return nil, fmt.Errorf("could not find any domains matched by certificate")
|
||||
}
|
||||
}
|
||||
|
||||
default:
|
||||
return nil, fmt.Errorf("unsupported domain match pattern: '%s'", d.config.DomainMatchPattern)
|
||||
}
|
||||
|
||||
// 批量更新域名证书
|
||||
if len(domains) == 0 {
|
||||
d.logger.Info("no edgeone makers domains to deploy")
|
||||
} else {
|
||||
d.logger.Info("found edgeone makers domains to deploy", slog.Any("domains", domains))
|
||||
|
||||
// 获取站点 ID
|
||||
zoneId := domainsInMakers[0].ZoneId
|
||||
|
||||
// 获取证书列表
|
||||
describeHostCertificatesReq := tceo.NewDescribeHostCertificatesRequest()
|
||||
describeHostCertificatesReq.ZoneId = zoneId
|
||||
describeHostCertificatesResp, err := d.sdkClients.TEO.DescribeHostCertificatesWithContext(ctx, describeHostCertificatesReq)
|
||||
d.logger.Debug("sdk request 'teo.DescribeHostCertificates'", slog.Any("request", describeHostCertificatesReq), slog.Any("response", describeHostCertificatesResp))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to execute sdk request 'teo.DescribeHostCertificates': %w", err)
|
||||
}
|
||||
|
||||
// 跳过已部署过的域名
|
||||
domains = lo.Filter(domains, func(domain string, _ int) bool {
|
||||
var deployed bool
|
||||
|
||||
domainInfo, _ := lo.Find(domainsInMakers, func(domainInfo *tceomakersssdk.PagesZoneCustomDomain) bool {
|
||||
return domain == lo.FromPtr(domainInfo.Domain)
|
||||
})
|
||||
if domainInfo != nil && describeHostCertificatesResp.Response != nil {
|
||||
deployed = lo.SomeBy(describeHostCertificatesResp.Response.HostCertificates, func(hostInfo *tceo.HostCertificate) bool {
|
||||
return domain == lo.FromPtr(hostInfo.Host) &&
|
||||
lo.SomeBy(hostInfo.HostCertInfo, func(certInfo *tceo.CertificateInfo) bool {
|
||||
return upres.CertId == lo.FromPtr(certInfo.CertId)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
return !deployed
|
||||
})
|
||||
|
||||
// 配置域名证书
|
||||
// REF: https://cloud.tencent.com/document/api/1552/80764
|
||||
modifyHostsCertificateReqs := make([]*tceo.ModifyHostsCertificateRequest, 0)
|
||||
|
||||
if d.config.EnableMultipleSSL {
|
||||
const algRSA = "RSA"
|
||||
const algECC = "ECC"
|
||||
|
||||
privkey, err := xcert.ParsePrivateKeyFromPEM(privkeyPEM)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to parse private key: %w", err)
|
||||
}
|
||||
|
||||
privkeyAlg, _, _ := xcertkey.GetPrivateKeyAlgorithm(privkey)
|
||||
privkeyAlgStr := ""
|
||||
switch privkeyAlg {
|
||||
case x509.RSA:
|
||||
privkeyAlgStr = algRSA
|
||||
case x509.ECDSA:
|
||||
privkeyAlgStr = algECC
|
||||
}
|
||||
|
||||
for _, domain := range domains {
|
||||
modifyHostsCertificateReq := tceo.NewModifyHostsCertificateRequest()
|
||||
modifyHostsCertificateReq.ZoneId = zoneId
|
||||
modifyHostsCertificateReq.Mode = common.StringPtr("sslcert")
|
||||
modifyHostsCertificateReq.Hosts = common.StringPtrs([]string{domain})
|
||||
modifyHostsCertificateReq.ServerCertInfo = []*tceo.ServerCertInfo{{CertId: common.StringPtr(upres.CertId)}}
|
||||
|
||||
domainInfo, _ := lo.Find(domainsInMakers, func(domainInfo *tceomakersssdk.PagesZoneCustomDomain) bool {
|
||||
return domain == lo.FromPtr(domainInfo.Domain)
|
||||
})
|
||||
if domainInfo != nil && describeHostCertificatesResp.Response != nil {
|
||||
for _, hostInfo := range describeHostCertificatesResp.Response.HostCertificates {
|
||||
if lo.FromPtr(hostInfo.Host) != domain {
|
||||
continue
|
||||
}
|
||||
|
||||
for _, certInfo := range hostInfo.HostCertInfo {
|
||||
if lo.FromPtr(certInfo.CertId) == upres.CertId {
|
||||
continue
|
||||
}
|
||||
|
||||
if strings.Split(lo.FromPtr(certInfo.SignAlgo), " ")[0] == privkeyAlgStr {
|
||||
continue
|
||||
}
|
||||
|
||||
certExpireTime, _ := time.Parse("2006-01-02T15:04:05Z", lo.FromPtr(certInfo.ExpireTime))
|
||||
if certExpireTime.Before(time.Now()) {
|
||||
continue
|
||||
}
|
||||
|
||||
modifyHostsCertificateReq.ServerCertInfo = append(modifyHostsCertificateReq.ServerCertInfo, &tceo.ServerCertInfo{CertId: certInfo.CertId})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
modifyHostsCertificateReqs = append(modifyHostsCertificateReqs, modifyHostsCertificateReq)
|
||||
}
|
||||
} else {
|
||||
modifyHostsCertificateReq := tceo.NewModifyHostsCertificateRequest()
|
||||
modifyHostsCertificateReq.ZoneId = zoneId
|
||||
modifyHostsCertificateReq.Mode = common.StringPtr("sslcert")
|
||||
modifyHostsCertificateReq.Hosts = common.StringPtrs(domains)
|
||||
modifyHostsCertificateReq.ServerCertInfo = []*tceo.ServerCertInfo{{CertId: common.StringPtr(upres.CertId)}}
|
||||
|
||||
modifyHostsCertificateReqs = append(modifyHostsCertificateReqs, modifyHostsCertificateReq)
|
||||
}
|
||||
|
||||
var errs []error
|
||||
for _, modifyHostsCertificateReq := range modifyHostsCertificateReqs {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return nil, ctx.Err()
|
||||
default:
|
||||
modifyHostsCertificateResp, err := d.sdkClients.TEO.ModifyHostsCertificateWithContext(ctx, modifyHostsCertificateReq)
|
||||
d.logger.Debug("sdk request 'teo.ModifyHostsCertificate'", slog.Any("request", modifyHostsCertificateReq), slog.Any("response", modifyHostsCertificateResp))
|
||||
if err != nil {
|
||||
err = fmt.Errorf("failed to execute sdk request 'teo.ModifyHostsCertificate': %w", err)
|
||||
errs = append(errs, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
if len(errs) > 0 {
|
||||
return nil, errors.Join(errs...)
|
||||
}
|
||||
}
|
||||
|
||||
return &DeployResult{}, nil
|
||||
}
|
||||
|
||||
func (d *Deployer) getAllDomainsInProject(ctx context.Context, makersProjectId string) ([]*tceomakersssdk.PagesZoneCustomDomain, error) {
|
||||
// 查询创建过的 Pages 自定义域名列表
|
||||
// REF: https://docs.edgeone.site/#/?id=describepageszonecustomdomains
|
||||
describeMakersZoneCustomDomainsReq := &tceomakersssdk.DescribePagesZoneCustomDomainsRequest{
|
||||
ProjectId: common.StringPtr(makersProjectId),
|
||||
}
|
||||
describeMakersZoneCustomDomainsResp, err := d.sdkClients.TEOMakers.DescribePagesZoneCustomDomainsWithContext(ctx, describeMakersZoneCustomDomainsReq)
|
||||
d.logger.Debug("api request 'teo.makers.DescribePagesZoneCustomDomains'", slog.Any("request", describeMakersZoneCustomDomainsReq), slog.Any("response", describeMakersZoneCustomDomainsResp))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to execute sdk request 'teo.makers.DescribePagesZoneCustomDomains': %w", err)
|
||||
}
|
||||
|
||||
domains := make([]*tceomakersssdk.PagesZoneCustomDomain, 0)
|
||||
for _, domainItem := range describeMakersZoneCustomDomainsResp.Data.Response.PagesDomains {
|
||||
if lo.FromPtr(domainItem.Type) == "Custom" && lo.FromPtr(domainItem.ZoneId) != "" {
|
||||
domains = append(domains, domainItem)
|
||||
}
|
||||
}
|
||||
|
||||
return domains, nil
|
||||
}
|
||||
|
||||
func createSDKClients(secretId, secretKey, endpoint, makersApiToken string) (*wSDKClients, error) {
|
||||
wsdk := &wSDKClients{}
|
||||
|
||||
{
|
||||
credential := common.NewCredential(secretId, secretKey)
|
||||
|
||||
cpf := profile.NewClientProfile()
|
||||
if endpoint != "" {
|
||||
cpf.HttpProfile.Endpoint = endpoint
|
||||
}
|
||||
|
||||
client, err := tceo.NewClient(credential, "", cpf)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
wsdk.TEO = client
|
||||
}
|
||||
|
||||
{
|
||||
client, err := tceomakersssdk.NewClient(
|
||||
tceomakersssdk.WithApiToken(makersApiToken),
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
wsdk.TEOMakers = client
|
||||
}
|
||||
|
||||
return wsdk, nil
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
package tencentcloudeomakers_test
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/certimate-go/certimate/pkg/core/deployer/internal/tester"
|
||||
impl "github.com/certimate-go/certimate/pkg/core/deployer/providers/tencentcloud-eomakers"
|
||||
)
|
||||
|
||||
var (
|
||||
fp = tester.Args("TENCENTCLOUDEOMAKERS_")
|
||||
fTestCertPath string
|
||||
fTestKeyPath string
|
||||
fSecretId string
|
||||
fSecretKey string
|
||||
fMakersApiToken string
|
||||
fMakersProjectId string
|
||||
fDomains string
|
||||
)
|
||||
|
||||
func init() {
|
||||
fp.DefineString(&fTestCertPath, "TESTCERTPATH")
|
||||
fp.DefineString(&fTestKeyPath, "TESTKEYPATH")
|
||||
fp.DefineString(&fSecretId, "SECRETID")
|
||||
fp.DefineString(&fSecretKey, "SECRETKEY")
|
||||
fp.DefineString(&fMakersApiToken, "MAKERSAPITOKEN")
|
||||
fp.DefineString(&fMakersProjectId, "MAKERSPROJECTID")
|
||||
fp.DefineString(&fDomains, "DOMAINS")
|
||||
}
|
||||
|
||||
/*
|
||||
Shell command to run this test:
|
||||
|
||||
go test -v ./tencentcloud_eomakers_test.go -args \
|
||||
--TENCENTCLOUDEOMAKERS_TESTCERTPATH="/path/to/your-test-cert.pem" \
|
||||
--TENCENTCLOUDEOMAKERS_TESTKEYPATH="/path/to/your-test-key.pem" \
|
||||
--TENCENTCLOUDEOMAKERS_SECRETID="your-secret-id" \
|
||||
--TENCENTCLOUDEOMAKERS_SECRETKEY="your-secret-key" \
|
||||
--TENCENTCLOUDEOMAKERS_MAKERSAPITOKEN="your-makers-api-token" \
|
||||
--TENCENTCLOUDEOMAKERS_MAKERSPROJECTID="your-makers-project-id" \
|
||||
--TENCENTCLOUDEOMAKERS_DOMAINS="example.com"
|
||||
*/
|
||||
func TestProvider(t *testing.T) {
|
||||
fp.Parse()
|
||||
|
||||
t.Run("Deploy", func(t *testing.T) {
|
||||
provider, err := impl.NewDeployer(&impl.DeployerConfig{
|
||||
SecretId: fSecretId,
|
||||
SecretKey: fSecretKey,
|
||||
MakersApiToken: fMakersApiToken,
|
||||
MakersProjectId: fMakersProjectId,
|
||||
DomainMatchPattern: impl.DomainMatchPatternExact,
|
||||
Domains: strings.Split(fDomains, ";"),
|
||||
EnableMultipleSSL: true,
|
||||
})
|
||||
if err != nil {
|
||||
t.Errorf("err: %+v", err)
|
||||
return
|
||||
}
|
||||
|
||||
tester.TestDeploy(t, provider, tester.TestDeployArgs{CertPath: fTestCertPath, KeyPath: fTestKeyPath})
|
||||
})
|
||||
}
|
||||
+36
@@ -5,6 +5,7 @@ import (
|
||||
"errors"
|
||||
|
||||
"github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common"
|
||||
tchttp "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common/http"
|
||||
"github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common/profile"
|
||||
teo "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/teo/v20220901"
|
||||
)
|
||||
@@ -48,6 +49,41 @@ func (c *Client) DescribeAccelerationDomainsWithContext(ctx context.Context, req
|
||||
return
|
||||
}
|
||||
|
||||
func NewDescribeHostCertificatesRequest() (request *DescribeHostCertificatesRequest) {
|
||||
request = &DescribeHostCertificatesRequest{
|
||||
BaseRequest: &tchttp.BaseRequest{},
|
||||
}
|
||||
|
||||
request.Init().WithApiInfo("teo", APIVersion, "DescribeHostCertificates")
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func NewDescribeHostCertificatesResponse() (response *DescribeHostCertificatesResponse) {
|
||||
response = &DescribeHostCertificatesResponse{
|
||||
BaseResponse: &tchttp.BaseResponse{},
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (c *Client) DescribeHostCertificatesWithContext(ctx context.Context, request *DescribeHostCertificatesRequest) (response *DescribeHostCertificatesResponse, err error) {
|
||||
if request == nil {
|
||||
request = NewDescribeHostCertificatesRequest()
|
||||
}
|
||||
c.InitBaseRequest(&request.BaseRequest, "teo", APIVersion, "DescribeHostCertificates")
|
||||
|
||||
if c.GetCredential() == nil {
|
||||
return nil, errors.New("DescribeHostCertificates require credential")
|
||||
}
|
||||
|
||||
request.SetContext(ctx)
|
||||
|
||||
response = NewDescribeHostCertificatesResponse()
|
||||
err = c.Send(request, response)
|
||||
return
|
||||
}
|
||||
|
||||
func NewModifyHostsCertificateRequest() (request *ModifyHostsCertificateRequest) {
|
||||
return teo.NewModifyHostsCertificateRequest()
|
||||
}
|
||||
|
||||
+31
@@ -1,19 +1,50 @@
|
||||
package v20220901
|
||||
|
||||
import (
|
||||
tchttp "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common/http"
|
||||
teo "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/teo/v20220901"
|
||||
)
|
||||
|
||||
type (
|
||||
AccelerationDomain = teo.AccelerationDomain
|
||||
AdvancedFilter = teo.AdvancedFilter
|
||||
CertificateInfo = teo.CertificateInfo
|
||||
MutualTLS = teo.MutualTLS
|
||||
ServerCertInfo = teo.ServerCertInfo
|
||||
UpstreamCertInfo = teo.UpstreamCertInfo
|
||||
)
|
||||
|
||||
type DescribeAccelerationDomainsRequest = teo.DescribeAccelerationDomainsRequest
|
||||
|
||||
type DescribeAccelerationDomainsResponse = teo.DescribeAccelerationDomainsResponse
|
||||
|
||||
type DescribeHostCertificatesRequest struct {
|
||||
*tchttp.BaseRequest
|
||||
ZoneId *string `json:"ZoneId,omitnil,omitempty" name:"ZoneId"`
|
||||
Filters []*AdvancedFilter `json:"Filters,omitnil,omitempty" name:"Filters"`
|
||||
}
|
||||
|
||||
type DescribeHostCertificatesResponse struct {
|
||||
*tchttp.BaseResponse
|
||||
Response *DescribeHostCertificatesResponseParams `json:"Response" name:"Response"`
|
||||
}
|
||||
|
||||
type DescribeHostCertificatesResponseParams struct {
|
||||
RequestId *string `json:"RequestId,omitnil,omitempty" name:"RequestId"`
|
||||
TotalCount *int64 `json:"TotalCount,omitnil,omitempty" name:"TotalCount"`
|
||||
HostCertificates []*HostCertificate `json:"HostCertificates,omitnil,omitempty" name:"HostCertificates"`
|
||||
}
|
||||
|
||||
type ModifyHostsCertificateRequest = teo.ModifyHostsCertificateRequest
|
||||
|
||||
type ModifyHostsCertificateResponse = teo.ModifyHostsCertificateResponse
|
||||
|
||||
type HostCertificate struct {
|
||||
ApplyType *string `json:"ApplyType,omitnil,omitempty" name:"ApplyType"`
|
||||
ClientCertInfo *MutualTLS `json:"ClientCertInfo,omitnil,omitempty" name:"ClientCertInfo"`
|
||||
Host *string `json:"Host,omitnil,omitempty" name:"Host"`
|
||||
HostCertInfo []*CertificateInfo `json:"HostCertInfo,omitnil,omitempty" name:"HostCertInfo"`
|
||||
Mode *string `json:"Mode,omitnil,omitempty" name:"Mode"`
|
||||
ServerCertInfo []*ServerCertInfo `json:"ServerCertInfo,omitnil,omitempty" name:"ServerCertInfo"`
|
||||
UpstreamCertInfo *UpstreamCertInfo `json:"UpstreamCertInfo,omitnil,omitempty" name:"UpstreamCertInfo"`
|
||||
}
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
package teomakers
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
type DescribePagesZoneCustomDomainsRequest struct {
|
||||
sdkRequestBase
|
||||
|
||||
ProjectId *string `json:"ProjectId,omitempty"`
|
||||
}
|
||||
|
||||
type DescribePagesZoneCustomDomainsResponse struct {
|
||||
sdkResponseBase
|
||||
|
||||
Data *struct {
|
||||
Response *struct {
|
||||
RequestId *string `json:"RequestId,omitempty"`
|
||||
TotalCount *int64 `json:"TotalCount,omitempty"`
|
||||
PagesDomains []*PagesZoneCustomDomain `json:"PagesDomains,omitempty"`
|
||||
} `json:"Response,omitempty"`
|
||||
} `json:"Data,omitempty"`
|
||||
}
|
||||
|
||||
func (c *Client) DescribePagesZoneCustomDomains(req *DescribePagesZoneCustomDomainsRequest) (*DescribePagesZoneCustomDomainsResponse, error) {
|
||||
return c.DescribePagesZoneCustomDomainsWithContext(context.Background(), req)
|
||||
}
|
||||
|
||||
func (c *Client) DescribePagesZoneCustomDomainsWithContext(ctx context.Context, req *DescribePagesZoneCustomDomainsRequest) (*DescribePagesZoneCustomDomainsResponse, error) {
|
||||
httpreq, err := c.newRequest(http.MethodPost, "/", "DescribePagesZoneCustomDomains", req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
httpreq.SetBody(req)
|
||||
httpreq.SetContext(ctx)
|
||||
}
|
||||
|
||||
result := &DescribePagesZoneCustomDomainsResponse{}
|
||||
if _, err := c.doRequestWithResult(httpreq, result); err != nil {
|
||||
return result, err
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
@@ -0,0 +1,109 @@
|
||||
// A simple SDK client for Tencent Cloud EdgeOne Pages.
|
||||
// API documentation: https://docs.edgeone.site/
|
||||
package teomakers
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/go-resty/resty/v2"
|
||||
|
||||
"github.com/certimate-go/certimate/internal/app"
|
||||
)
|
||||
|
||||
type Client struct {
|
||||
rc *resty.Client
|
||||
}
|
||||
|
||||
func NewClient(optFns ...OptionsFunc) (*Client, error) {
|
||||
options := &Options{}
|
||||
for _, fn := range optFns {
|
||||
fn(options)
|
||||
}
|
||||
|
||||
if options.ApiToken == "" {
|
||||
return nil, fmt.Errorf("sdkerr: unset apiToken")
|
||||
}
|
||||
|
||||
httper := resty.New().
|
||||
SetBaseURL("https://pages-api.cloud.tencent.com/v1").
|
||||
SetHeader("Accept", "application/json").
|
||||
SetHeader("Authorization", "Bearer "+options.ApiToken).
|
||||
SetHeader("Content-Type", "application/json").
|
||||
SetHeader("User-Agent", app.AppUserAgent)
|
||||
|
||||
return &Client{rc: httper}, nil
|
||||
}
|
||||
|
||||
func (c *Client) SetTimeout(timeout time.Duration) *Client {
|
||||
c.rc.SetTimeout(timeout)
|
||||
return c
|
||||
}
|
||||
|
||||
func (c *Client) newRequest(method string, path string, action string, params sdkRequest) (*resty.Request, error) {
|
||||
if method == "" {
|
||||
return nil, fmt.Errorf("sdkerr: unset method")
|
||||
}
|
||||
if path == "" {
|
||||
return nil, fmt.Errorf("sdkerr: unset path")
|
||||
}
|
||||
if action == "" {
|
||||
return nil, fmt.Errorf("sdkerr: unset action")
|
||||
}
|
||||
|
||||
req := c.rc.R()
|
||||
req.Method = method
|
||||
req.URL = path
|
||||
|
||||
if params != nil {
|
||||
params.SetAction(action)
|
||||
req.SetBody(params)
|
||||
}
|
||||
|
||||
return req, nil
|
||||
}
|
||||
|
||||
func (c *Client) doRequest(req *resty.Request) (*resty.Response, error) {
|
||||
if req == nil {
|
||||
return nil, fmt.Errorf("sdkerr: nil request")
|
||||
}
|
||||
|
||||
// WARN:
|
||||
// PLEASE DO NOT USE `req.SetResult` or `req.SetError` HERE! USE `doRequestWithResult` INSTEAD.
|
||||
|
||||
resp, err := req.Send()
|
||||
if err != nil {
|
||||
return resp, fmt.Errorf("sdkerr: failed to send request: %w", err)
|
||||
} else if resp.IsError() {
|
||||
return resp, fmt.Errorf("sdkerr: unexpected status code: %d (resp: %s)", resp.StatusCode(), resp.String())
|
||||
}
|
||||
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
func (c *Client) doRequestWithResult(req *resty.Request, res sdkResponse) (*resty.Response, error) {
|
||||
if req == nil {
|
||||
return nil, fmt.Errorf("sdkerr: nil request")
|
||||
}
|
||||
|
||||
resp, err := c.doRequest(req)
|
||||
if err != nil {
|
||||
if resp != nil {
|
||||
json.Unmarshal(resp.Body(), &res)
|
||||
}
|
||||
return resp, err
|
||||
}
|
||||
|
||||
if len(resp.Body()) != 0 {
|
||||
if err := json.Unmarshal(resp.Body(), &res); err != nil {
|
||||
return resp, fmt.Errorf("sdkerr: failed to unmarshal response: %w (resp: %s)", err, resp.String())
|
||||
} else {
|
||||
if rCode := res.GetCode(); rCode != 0 {
|
||||
return resp, fmt.Errorf("sdkerr: api error: code='%d', message='%s'", rCode, res.GetMessage())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return resp, nil
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package teomakers
|
||||
|
||||
import (
|
||||
teo "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/teo/v20220901"
|
||||
)
|
||||
|
||||
type (
|
||||
OwnershipVerification = teo.OwnershipVerification
|
||||
DnsVerification = teo.DnsVerification
|
||||
FileVerification = teo.FileVerification
|
||||
NsVerification = teo.NsVerification
|
||||
)
|
||||
|
||||
type PagesZoneCustomDomain struct {
|
||||
Type *string `json:"Type,omitempty"`
|
||||
Domain *string `json:"Domain,omitempty"`
|
||||
ForceRedirectHTTPS *string `json:"ForceRedirectHTTPS,omitempty"`
|
||||
RedirectStatusCode *int32 `json:"RedirectStatusCode,omitempty"`
|
||||
CurrentCname *string `json:"CurrentCname,omitempty"`
|
||||
MainDomain *string `json:"MainDomain,omitempty"`
|
||||
Status *string `json:"Status,omitempty"`
|
||||
OwnershipVerification *OwnershipVerification `json:"OwnershipVerification,omitempty"`
|
||||
Cname *string `json:"Cname,omitempty"`
|
||||
Area *string `json:"Area,omitempty"`
|
||||
ZoneId *string `json:"ZoneId,omitempty"`
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package teomakers
|
||||
|
||||
type Options struct {
|
||||
ApiToken string
|
||||
}
|
||||
|
||||
type OptionsFunc func(*Options)
|
||||
|
||||
func WithApiToken(apiToken string) OptionsFunc {
|
||||
return func(o *Options) {
|
||||
o.ApiToken = apiToken
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
package teomakers
|
||||
|
||||
type sdkRequest interface {
|
||||
SetAction(action string)
|
||||
}
|
||||
|
||||
type sdkRequestBase struct {
|
||||
Action *string `json:"Action,omitempty"`
|
||||
}
|
||||
|
||||
func (r *sdkRequestBase) SetAction(action string) {
|
||||
r.Action = &action
|
||||
}
|
||||
|
||||
var _ sdkRequest = (*sdkRequestBase)(nil)
|
||||
|
||||
type sdkResponse interface {
|
||||
GetCode() int
|
||||
GetMessage() string
|
||||
}
|
||||
|
||||
type sdkResponseBase struct {
|
||||
Code *int `json:"Code,omitempty"`
|
||||
Message *string `json:"Message,omitempty"`
|
||||
RequestId *string `json:"RequestId,omitempty"`
|
||||
}
|
||||
|
||||
func (r *sdkResponseBase) GetCode() int {
|
||||
if r.Code == nil {
|
||||
return 0
|
||||
}
|
||||
|
||||
return *r.Code
|
||||
}
|
||||
|
||||
func (r *sdkResponseBase) GetMessage() string {
|
||||
if r.Message == nil {
|
||||
return ""
|
||||
}
|
||||
|
||||
return *r.Message
|
||||
}
|
||||
|
||||
var _ sdkResponse = (*sdkResponseBase)(nil)
|
||||
Reference in New Issue
Block a user