refactor: use xwait utils instead of time.Sleep

This commit is contained in:
Fu Diwei
2026-01-20 14:51:06 +08:00
parent 8597cfc595
commit 2bec54eb55
17 changed files with 281 additions and 159 deletions
+3 -1
View File
@@ -4,6 +4,8 @@ import (
"fmt"
"log/slog"
"time"
xwait "github.com/certimate-go/certimate/pkg/utils/wait"
)
type delayNodeExecutor struct {
@@ -16,7 +18,7 @@ func (ne *delayNodeExecutor) Execute(execCtx *NodeExecutionContext) (*NodeExecut
nodeCfg := execCtx.Node.Data.Config.AsDelay()
ne.logger.Info(fmt.Sprintf("delay for %d second(s) before continuing ...", nodeCfg.Wait))
time.Sleep(time.Duration(nodeCfg.Wait) * time.Second)
xwait.DelayWithContext(execCtx.ctx, time.Duration(nodeCfg.Wait)*time.Second)
return execRes, nil
}
@@ -127,7 +127,24 @@ func (c *Certmgr) Upload(ctx context.Context, certPEM, privkeyPEM string) (*cert
}
func (c *Certmgr) Replace(ctx context.Context, certIdOrName string, certPEM, privkeyPEM string) (*certmgr.OperateResult, error) {
return nil, certmgr.ErrUnsupported
certId := certIdOrName
certName := fmt.Sprintf("certimate_%d", time.Now().UnixMilli())
// 修改证书
// REF: https://www.wangsu.com/document/api-doc/25568?productCode=certificatemanagement
updateCertificateReq := &wangsusdk.UpdateCertificateRequest{
Name: lo.ToPtr(certName),
Certificate: lo.ToPtr(certPEM),
PrivateKey: lo.ToPtr(privkeyPEM),
Comment: lo.ToPtr("upload from certimate"),
}
updateCertificateResp, err := c.sdkClient.UpdateCertificate(certId, updateCertificateReq)
c.logger.Debug("sdk request 'certificatemanagement.UpdateCertificate'", slog.Any("request", updateCertificateReq), slog.Any("response", updateCertificateResp))
if err != nil {
return nil, fmt.Errorf("failed to execute sdk request 'certificatemanagement.UpdateCertificate': %w", err)
}
return &certmgr.OperateResult{}, nil
}
func createSDKClient(accessKeyId, accessKeySecret string) (*wangsusdk.Client, error) {
+2 -1
View File
@@ -15,6 +15,7 @@ import (
onepanelsdk "github.com/certimate-go/certimate/pkg/sdk3rd/1panel"
onepanelsdk2 "github.com/certimate-go/certimate/pkg/sdk3rd/1panel/v2"
xcert "github.com/certimate-go/certimate/pkg/utils/cert"
xwait "github.com/certimate-go/certimate/pkg/utils/wait"
)
type DeployerConfig struct {
@@ -163,7 +164,7 @@ func (d *Deployer) deployToWebsite(ctx context.Context, certPEM, privkeyPEM stri
errs = append(errs, err)
}
if i < len(websiteIds)-1 {
time.Sleep(time.Second * 5)
xwait.DelayWithContext(ctx, time.Second*5)
}
}
}
@@ -17,6 +17,7 @@ import (
mcertmgr "github.com/certimate-go/certimate/pkg/core/certmgr/providers/aliyun-cas"
"github.com/certimate-go/certimate/pkg/core/deployer"
"github.com/certimate-go/certimate/pkg/core/deployer/providers/aliyun-cas-deploy/internal"
xwait "github.com/certimate-go/certimate/pkg/utils/wait"
)
type DeployerConfig struct {
@@ -129,33 +130,29 @@ func (d *Deployer) Deploy(ctx context.Context, certPEM, privkeyPEM string) (*dep
return nil, fmt.Errorf("failed to execute sdk request 'cas.CreateDeploymentJob': %w", err)
}
// 循环获取部署任务详情,等待任务状态变更
// 获取部署任务详情,等待任务状态变更
// REF: https://help.aliyun.com/zh/ssl-certificate/developer-reference/api-cas-2020-04-07-describedeploymentjob
for {
select {
case <-ctx.Done():
return nil, ctx.Err()
default:
}
if _, err := xwait.UntilWithContext(ctx, func(_ context.Context, _ int) (bool, error) {
describeDeploymentJobReq := &alicas.DescribeDeploymentJobRequest{
JobId: createDeploymentJobResp.Body.JobId,
}
describeDeploymentJobResp, err := d.sdkClient.DescribeDeploymentJobWithContext(ctx, describeDeploymentJobReq, &dara.RuntimeOptions{})
d.logger.Debug("sdk request 'cas.DescribeDeploymentJob'", slog.Any("request", describeDeploymentJobReq), slog.Any("response", describeDeploymentJobResp))
if err != nil {
return nil, fmt.Errorf("failed to execute sdk request 'cas.DescribeDeploymentJob': %w", err)
return false, fmt.Errorf("failed to execute sdk request 'cas.DescribeDeploymentJob': %w", err)
}
status := tea.StringValue(describeDeploymentJobResp.Body.Status)
if status == "" || status == "editing" {
return nil, errors.New("unexpected aliyun deployment job status")
} else if status == "success" || status == "error" {
break
switch tea.StringValue(describeDeploymentJobResp.Body.Status) {
case "success", "error":
return true, nil
case "", "editing":
return false, fmt.Errorf("unexpected aliyun deployment job status")
}
d.logger.Info("waiting for aliyun deployment job completion ...")
time.Sleep(time.Second * 5)
return false, nil
}, time.Second*5); err != nil {
return nil, err
}
return &deployer.DeployResult{}, nil
@@ -12,6 +12,7 @@ import (
"github.com/certimate-go/certimate/pkg/core/deployer"
btsdk "github.com/certimate-go/certimate/pkg/sdk3rd/btpanel"
xwait "github.com/certimate-go/certimate/pkg/utils/wait"
)
type DeployerConfig struct {
@@ -108,7 +109,7 @@ func (d *Deployer) Deploy(ctx context.Context, certPEM, privkeyPEM string) (*dep
errs = append(errs, err)
}
if i < len(d.config.SiteNames)-1 {
time.Sleep(time.Second * 5)
xwait.DelayWithContext(ctx, time.Second*5)
}
}
}
@@ -16,6 +16,7 @@ import (
"github.com/certimate-go/certimate/pkg/core/deployer"
btsdk "github.com/certimate-go/certimate/pkg/sdk3rd/btpanelgo"
xcert "github.com/certimate-go/certimate/pkg/utils/cert"
xwait "github.com/certimate-go/certimate/pkg/utils/wait"
)
type DeployerConfig struct {
@@ -85,7 +86,7 @@ func (d *Deployer) Deploy(ctx context.Context, certPEM, privkeyPEM string) (*dep
errs = append(errs, err)
}
if i < len(d.config.SiteNames)-1 {
time.Sleep(time.Second * 5)
xwait.DelayWithContext(ctx, time.Second*5)
}
}
}
@@ -12,6 +12,7 @@ import (
"github.com/certimate-go/certimate/pkg/core/deployer"
btwafsdk "github.com/certimate-go/certimate/pkg/sdk3rd/btwaf"
xwait "github.com/certimate-go/certimate/pkg/utils/wait"
)
type DeployerConfig struct {
@@ -77,7 +78,7 @@ func (d *Deployer) Deploy(ctx context.Context, certPEM, privkeyPEM string) (*dep
errs = append(errs, err)
}
if i < len(d.config.SiteNames)-1 {
time.Sleep(time.Second * 5)
xwait.DelayWithContext(ctx, time.Second*5)
}
}
}
@@ -16,6 +16,7 @@ import (
"github.com/certimate-go/certimate/pkg/core/deployer"
npmsdk "github.com/certimate-go/certimate/pkg/sdk3rd/nginxproxymanager"
xcert "github.com/certimate-go/certimate/pkg/utils/cert"
xwait "github.com/certimate-go/certimate/pkg/utils/wait"
)
type DeployerConfig struct {
@@ -201,7 +202,7 @@ func (d *Deployer) deployToHost(ctx context.Context, certPEM, privkeyPEM string)
errs = append(errs, err)
}
if i < len(hostIds)-1 {
time.Sleep(time.Second * 5)
xwait.DelayWithContext(ctx, time.Second*5)
}
}
}
@@ -119,7 +119,7 @@ func (d *Deployer) deployToCertificate(ctx context.Context, certPEM, privkeyPEM
return err
}
// 设置站点 SSL 证书
// 更新 SSL 证书
certUpdateReq := &ratpanelsdk.CertUpdateRequest{
CertId: d.config.CertificateId,
Type: "upload",
@@ -17,6 +17,7 @@ import (
mcertmgr "github.com/certimate-go/certimate/pkg/core/certmgr/providers/tencentcloud-ssl"
"github.com/certimate-go/certimate/pkg/core/deployer"
"github.com/certimate-go/certimate/pkg/core/deployer/providers/tencentcloud-clb/internal"
xwait "github.com/certimate-go/certimate/pkg/utils/wait"
)
type DeployerConfig struct {
@@ -217,32 +218,28 @@ func (d *Deployer) deployToRuleDomain(ctx context.Context, cloudCertId string) e
return fmt.Errorf("failed to execute sdk request 'clb.ModifyDomainAttributes': %w", err)
}
// 循环查询异步任务状态,等待任务状态变更
// 查询异步任务状态,等待任务状态变更
// REF: https://cloud.tencent.com/document/product/214/30683
for {
select {
case <-ctx.Done():
return ctx.Err()
default:
}
if _, err := xwait.UntilWithContext(ctx, func(_ context.Context, _ int) (bool, error) {
describeTaskStatusReq := tcclb.NewDescribeTaskStatusRequest()
describeTaskStatusReq.TaskId = modifyDomainAttributesResp.Response.RequestId
describeTaskStatusResp, err := d.sdkClient.DescribeTaskStatus(describeTaskStatusReq)
d.logger.Debug("sdk request 'clb.DescribeTaskStatus'", slog.Any("request", describeTaskStatusReq), slog.Any("response", describeTaskStatusResp))
if err != nil {
return fmt.Errorf("failed to execute sdk request 'clb.DescribeTaskStatus': %w", err)
return false, fmt.Errorf("failed to execute sdk request 'clb.DescribeTaskStatus': %w", err)
}
status := lo.FromPtr(describeTaskStatusResp.Response.Status)
if status == 1 {
return errors.New("unexpected tencentcloud task status")
} else if status == 0 {
break
switch lo.FromPtr(describeTaskStatusResp.Response.Status) {
case 0:
return true, nil
case 1:
return false, fmt.Errorf("unexpected tencentcloud task status")
}
d.logger.Info("waiting for tencentcloud task completion ...")
time.Sleep(time.Second * 5)
return false, nil
}, time.Second*5); err != nil {
return err
}
return nil
@@ -280,32 +277,28 @@ func (d *Deployer) updateListenerCertificate(ctx context.Context, cloudLoadbalan
return fmt.Errorf("failed to execute sdk request 'clb.ModifyListener': %w", err)
}
// 循环查询异步任务状态,等待任务状态变更
// 查询异步任务状态,等待任务状态变更
// REF: https://cloud.tencent.com/document/product/214/30683
for {
select {
case <-ctx.Done():
return ctx.Err()
default:
}
if _, err := xwait.UntilWithContext(ctx, func(_ context.Context, _ int) (bool, error) {
describeTaskStatusReq := tcclb.NewDescribeTaskStatusRequest()
describeTaskStatusReq.TaskId = modifyListenerResp.Response.RequestId
describeTaskStatusResp, err := d.sdkClient.DescribeTaskStatus(describeTaskStatusReq)
d.logger.Debug("sdk request 'clb.DescribeTaskStatus'", slog.Any("request", describeTaskStatusReq), slog.Any("response", describeTaskStatusResp))
if err != nil {
return fmt.Errorf("failed to execute sdk request 'clb.DescribeTaskStatus': %w", err)
return false, fmt.Errorf("failed to execute sdk request 'clb.DescribeTaskStatus': %w", err)
}
status := lo.FromPtr(describeTaskStatusResp.Response.Status)
if status == 1 {
return errors.New("unexpected tencentcloud task status")
} else if status == 0 {
break
switch lo.FromPtr(describeTaskStatusResp.Response.Status) {
case 0:
return true, nil
case 1:
return false, fmt.Errorf("unexpected tencentcloud task status")
}
d.logger.Info("waiting for tencentcloud task completion ...")
time.Sleep(time.Second * 5)
return false, nil
}, time.Second*5); err != nil {
return err
}
return nil
@@ -16,6 +16,7 @@ import (
mcertmgr "github.com/certimate-go/certimate/pkg/core/certmgr/providers/tencentcloud-ssl"
"github.com/certimate-go/certimate/pkg/core/deployer"
"github.com/certimate-go/certimate/pkg/core/deployer/providers/tencentcloud-cos/internal"
xwait "github.com/certimate-go/certimate/pkg/utils/wait"
)
type DeployerConfig struct {
@@ -115,26 +116,20 @@ func (d *Deployer) Deploy(ctx context.Context, certPEM, privkeyPEM string) (*dep
return nil, fmt.Errorf("failed to execute sdk request 'ssl.DeployCertificateInstance': %w", err)
}
// 循环获取部署任务详情,等待任务状态变更
// 获取部署任务详情,等待任务状态变更
// REF: https://cloud.tencent.com/document/api/400/91658
for {
select {
case <-ctx.Done():
return nil, ctx.Err()
default:
}
if _, err := xwait.UntilWithContext(ctx, func(_ context.Context, _ int) (bool, error) {
describeHostDeployRecordDetailReq := tcssl.NewDescribeHostDeployRecordDetailRequest()
describeHostDeployRecordDetailReq.DeployRecordId = common.StringPtr(fmt.Sprintf("%d", *deployCertificateInstanceResp.Response.DeployRecordId))
describeHostDeployRecordDetailResp, err := d.sdkClient.SSL.DescribeHostDeployRecordDetail(describeHostDeployRecordDetailReq)
d.logger.Debug("sdk request 'ssl.DescribeHostDeployRecordDetail'", slog.Any("request", describeHostDeployRecordDetailReq), slog.Any("response", describeHostDeployRecordDetailResp))
if err != nil {
return nil, fmt.Errorf("failed to execute sdk request 'ssl.DescribeHostDeployRecordDetail': %w", err)
return false, fmt.Errorf("failed to execute sdk request 'ssl.DescribeHostDeployRecordDetail': %w", err)
}
var pendingCount, runningCount, succeededCount, failedCount, totalCount int64
if describeHostDeployRecordDetailResp.Response.TotalCount == nil {
return nil, errors.New("unexpected tencentcloud deployment job status")
return false, fmt.Errorf("unexpected tencentcloud deployment job status")
} else {
pendingCount = lo.FromPtr(describeHostDeployRecordDetailResp.Response.PendingTotalCount)
runningCount = lo.FromPtr(describeHostDeployRecordDetailResp.Response.RunningTotalCount)
@@ -144,14 +139,16 @@ func (d *Deployer) Deploy(ctx context.Context, certPEM, privkeyPEM string) (*dep
if succeededCount+failedCount == totalCount {
if failedCount > 0 {
return nil, fmt.Errorf("tencentcloud deployment job failed (succeeded: %d, failed: %d, total: %d)", succeededCount, failedCount, totalCount)
return false, fmt.Errorf("tencentcloud deployment job failed (succeeded: %d, failed: %d, total: %d)", succeededCount, failedCount, totalCount)
}
break
return true, nil
}
}
d.logger.Info(fmt.Sprintf("waiting for tencentcloud deployment job completion (pending: %d, running: %d, succeeded: %d, failed: %d, total: %d) ...", pendingCount, runningCount, succeededCount, failedCount, totalCount))
time.Sleep(time.Second * 5)
return false, nil
}, time.Second*5); err != nil {
return nil, err
}
return &deployer.DeployResult{}, nil
@@ -16,6 +16,7 @@ import (
mcertmgr "github.com/certimate-go/certimate/pkg/core/certmgr/providers/tencentcloud-ssl"
"github.com/certimate-go/certimate/pkg/core/deployer"
"github.com/certimate-go/certimate/pkg/core/deployer/providers/tencentcloud-ssl-deploy/internal"
xwait "github.com/certimate-go/certimate/pkg/utils/wait"
)
type DeployerConfig struct {
@@ -110,27 +111,21 @@ func (d *Deployer) Deploy(ctx context.Context, certPEM, privkeyPEM string) (*dep
return nil, errors.New("failed to create deploy record")
}
// 循环获取部署任务详情,等待任务状态变更
// 获取部署任务详情,等待任务状态变更
// REF: https://cloud.tencent.com/document/api/400/91658
for {
select {
case <-ctx.Done():
return nil, ctx.Err()
default:
}
if _, err := xwait.UntilWithContext(ctx, func(_ context.Context, _ int) (bool, error) {
describeHostDeployRecordDetailReq := tcssl.NewDescribeHostDeployRecordDetailRequest()
describeHostDeployRecordDetailReq.DeployRecordId = common.StringPtr(fmt.Sprintf("%d", *deployCertificateInstanceResp.Response.DeployRecordId))
describeHostDeployRecordDetailReq.Limit = common.Uint64Ptr(200)
describeHostDeployRecordDetailResp, err := d.sdkClient.DescribeHostDeployRecordDetail(describeHostDeployRecordDetailReq)
d.logger.Debug("sdk request 'ssl.DescribeHostDeployRecordDetail'", slog.Any("request", describeHostDeployRecordDetailReq), slog.Any("response", describeHostDeployRecordDetailResp))
if err != nil {
return nil, fmt.Errorf("failed to execute sdk request 'ssl.DescribeHostDeployRecordDetail': %w", err)
return false, fmt.Errorf("failed to execute sdk request 'ssl.DescribeHostDeployRecordDetail': %w", err)
}
var pendingCount, runningCount, succeededCount, failedCount, totalCount int64
if describeHostDeployRecordDetailResp.Response.TotalCount == nil {
return nil, errors.New("unexpected tencentcloud deployment job status")
return false, fmt.Errorf("unexpected tencentcloud deployment job status")
} else {
pendingCount = lo.FromPtr(describeHostDeployRecordDetailResp.Response.PendingTotalCount)
runningCount = lo.FromPtr(describeHostDeployRecordDetailResp.Response.RunningTotalCount)
@@ -140,14 +135,16 @@ func (d *Deployer) Deploy(ctx context.Context, certPEM, privkeyPEM string) (*dep
if succeededCount+failedCount == totalCount {
if failedCount > 0 {
return nil, fmt.Errorf("tencentcloud deployment job failed (succeeded: %d, failed: %d, total: %d)", succeededCount, failedCount, totalCount)
return false, fmt.Errorf("tencentcloud deployment job failed (succeeded: %d, failed: %d, total: %d)", succeededCount, failedCount, totalCount)
}
break
return true, nil
}
}
d.logger.Info(fmt.Sprintf("waiting for tencentcloud deployment job completion (pending: %d, running: %d, succeeded: %d, failed: %d, total: %d) ...", pendingCount, runningCount, succeededCount, failedCount, totalCount))
time.Sleep(time.Second * 5)
return false, nil
}, time.Second*5); err != nil {
return nil, err
}
return &deployer.DeployResult{}, nil
@@ -17,6 +17,7 @@ import (
mcertmgr "github.com/certimate-go/certimate/pkg/core/certmgr/providers/tencentcloud-ssl"
"github.com/certimate-go/certimate/pkg/core/deployer"
"github.com/certimate-go/certimate/pkg/core/deployer/providers/tencentcloud-ssl-update/internal"
xwait "github.com/certimate-go/certimate/pkg/utils/wait"
)
type DeployerConfig struct {
@@ -115,13 +116,7 @@ func (d *Deployer) executeUpdateCertificateInstance(ctx context.Context, certPEM
// 一键更新新旧证书资源
// REF: https://cloud.tencent.com/document/product/400/91649
var deployRecordId string
for {
select {
case <-ctx.Done():
return ctx.Err()
default:
}
if _, err := xwait.UntilWithContext(ctx, func(_ context.Context, _ int) (bool, error) {
updateCertificateInstanceReq := tcssl.NewUpdateCertificateInstanceRequest()
updateCertificateInstanceReq.OldCertificateId = common.StringPtr(d.config.CertificateId)
updateCertificateInstanceReq.CertificateId = common.StringPtr(upres.CertId)
@@ -130,40 +125,36 @@ func (d *Deployer) executeUpdateCertificateInstance(ctx context.Context, certPEM
updateCertificateInstanceResp, err := d.sdkClient.UpdateCertificateInstance(updateCertificateInstanceReq)
d.logger.Debug("sdk request 'ssl.UpdateCertificateInstance'", slog.Any("request", updateCertificateInstanceReq), slog.Any("response", updateCertificateInstanceResp))
if err != nil {
return fmt.Errorf("failed to execute sdk request 'ssl.UpdateCertificateInstance': %w", err)
return false, fmt.Errorf("failed to execute sdk request 'ssl.UpdateCertificateInstance': %w", err)
}
if updateCertificateInstanceResp.Response.DeployStatus == nil || updateCertificateInstanceResp.Response.DeployRecordId == nil {
return errors.New("unexpected deployment job status")
return false, fmt.Errorf("unexpected deployment job status")
} else if *updateCertificateInstanceResp.Response.DeployRecordId > 0 {
deployRecordId = fmt.Sprintf("%d", *updateCertificateInstanceResp.Response.DeployRecordId)
break
return true, nil
}
time.Sleep(time.Second * 5)
return false, nil
}, time.Second*5); err != nil {
return err
}
// 循环查询证书云资源更新记录详情,等待任务状态变更
// 查询证书云资源更新记录详情,等待任务状态变更
// REF: https://cloud.tencent.com/document/api/400/91652
for {
select {
case <-ctx.Done():
return ctx.Err()
default:
}
if _, err := xwait.UntilWithContext(ctx, func(_ context.Context, _ int) (bool, error) {
describeHostUpdateRecordDetailReq := tcssl.NewDescribeHostUpdateRecordDetailRequest()
describeHostUpdateRecordDetailReq.DeployRecordId = common.StringPtr(deployRecordId)
describeHostUpdateRecordDetailReq.Limit = common.StringPtr("200")
describeHostUpdateRecordDetailResp, err := d.sdkClient.DescribeHostUpdateRecordDetail(describeHostUpdateRecordDetailReq)
d.logger.Debug("sdk request 'ssl.DescribeHostUpdateRecordDetail'", slog.Any("request", describeHostUpdateRecordDetailReq), slog.Any("response", describeHostUpdateRecordDetailResp))
if err != nil {
return fmt.Errorf("failed to execute sdk request 'ssl.DescribeHostUpdateRecordDetail': %w", err)
return false, fmt.Errorf("failed to execute sdk request 'ssl.DescribeHostUpdateRecordDetail': %w", err)
}
var pendingCount, runningCount, succeededCount, failedCount, totalCount int64
if describeHostUpdateRecordDetailResp.Response.TotalCount == nil {
return errors.New("unexpected tencentcloud deployment job status")
return false, fmt.Errorf("unexpected tencentcloud deployment job status")
} else {
pendingCount = lo.FromPtr(describeHostUpdateRecordDetailResp.Response.PendingTotalCount)
runningCount = lo.FromPtr(describeHostUpdateRecordDetailResp.Response.RunningTotalCount)
@@ -173,14 +164,16 @@ func (d *Deployer) executeUpdateCertificateInstance(ctx context.Context, certPEM
if succeededCount+failedCount == totalCount {
if failedCount > 0 {
return fmt.Errorf("tencentcloud deployment job failed (succeeded: %d, failed: %d, total: %d)", succeededCount, failedCount, totalCount)
return false, fmt.Errorf("tencentcloud deployment job failed (succeeded: %d, failed: %d, total: %d)", succeededCount, failedCount, totalCount)
}
break
return true, nil
}
}
d.logger.Info(fmt.Sprintf("waiting for tencentcloud deployment job completion (pending: %d, running: %d, succeeded: %d, failed: %d, total: %d) ...", pendingCount, runningCount, succeededCount, failedCount, totalCount))
time.Sleep(time.Second * 5)
return false, nil
}, time.Second*5); err != nil {
return err
}
return nil
@@ -190,13 +183,7 @@ func (d *Deployer) executeUploadUpdateCertificateInstance(ctx context.Context, c
// 更新证书内容并更新关联的云资源
// REF: https://cloud.tencent.com/document/product/400/119791
var deployRecordId int64
for {
select {
case <-ctx.Done():
return ctx.Err()
default:
}
if _, err := xwait.UntilWithContext(ctx, func(_ context.Context, _ int) (bool, error) {
uploadUpdateCertificateInstanceReq := tcssl.NewUploadUpdateCertificateInstanceRequest()
uploadUpdateCertificateInstanceReq.OldCertificateId = common.StringPtr(d.config.CertificateId)
uploadUpdateCertificateInstanceReq.CertificatePublicKey = common.StringPtr(certPEM)
@@ -206,40 +193,36 @@ func (d *Deployer) executeUploadUpdateCertificateInstance(ctx context.Context, c
uploadUpdateCertificateInstanceResp, err := d.sdkClient.UploadUpdateCertificateInstance(uploadUpdateCertificateInstanceReq)
d.logger.Debug("sdk request 'ssl.UploadUpdateCertificateInstance'", slog.Any("request", uploadUpdateCertificateInstanceReq), slog.Any("response", uploadUpdateCertificateInstanceResp))
if err != nil {
return fmt.Errorf("failed to execute sdk request 'ssl.UploadUpdateCertificateInstance': %w", err)
return false, fmt.Errorf("failed to execute sdk request 'ssl.UploadUpdateCertificateInstance': %w", err)
}
if uploadUpdateCertificateInstanceResp.Response.DeployStatus == nil {
return errors.New("unexpected deployment job status")
return false, fmt.Errorf("unexpected deployment job status")
} else if *uploadUpdateCertificateInstanceResp.Response.DeployStatus == 1 {
deployRecordId = int64(*uploadUpdateCertificateInstanceResp.Response.DeployRecordId)
break
return true, nil
}
time.Sleep(time.Second * 5)
return false, nil
}, time.Second*5); err != nil {
return err
}
// 循环查询证书云资源更新记录详情,等待任务状态变更
// 查询证书云资源更新记录详情,等待任务状态变更
// REF: https://cloud.tencent.com/document/product/400/120056
for {
select {
case <-ctx.Done():
return ctx.Err()
default:
}
if _, err := xwait.UntilWithContext(ctx, func(_ context.Context, _ int) (bool, error) {
describeHostUploadUpdateRecordDetailReq := tcssl.NewDescribeHostUploadUpdateRecordDetailRequest()
describeHostUploadUpdateRecordDetailReq.DeployRecordId = common.Int64Ptr(deployRecordId)
describeHostUploadUpdateRecordDetailReq.Limit = common.Int64Ptr(200)
describeHostUploadUpdateRecordDetailResp, err := d.sdkClient.DescribeHostUploadUpdateRecordDetail(describeHostUploadUpdateRecordDetailReq)
d.logger.Debug("sdk request 'ssl.DescribeHostUploadUpdateRecordDetail'", slog.Any("request", describeHostUploadUpdateRecordDetailReq), slog.Any("response", describeHostUploadUpdateRecordDetailResp))
if err != nil {
return fmt.Errorf("failed to execute sdk request 'ssl.DescribeHostUploadUpdateRecordDetail': %w", err)
return false, fmt.Errorf("failed to execute sdk request 'ssl.DescribeHostUploadUpdateRecordDetail': %w", err)
}
var runningCount, succeededCount, failedCount, totalCount int64
if describeHostUploadUpdateRecordDetailResp.Response.DeployRecordDetail == nil {
return errors.New("unexpected tencentcloud deployment job status")
return false, fmt.Errorf("unexpected tencentcloud deployment job status")
} else {
for _, record := range describeHostUploadUpdateRecordDetailResp.Response.DeployRecordDetail {
runningCount += lo.FromPtr(record.RunningTotalCount)
@@ -250,14 +233,16 @@ func (d *Deployer) executeUploadUpdateCertificateInstance(ctx context.Context, c
if succeededCount+failedCount == totalCount {
if failedCount > 0 {
return fmt.Errorf("tencentcloud deployment job failed (succeeded: %d, failed: %d, total: %d)", succeededCount, failedCount, totalCount)
return false, fmt.Errorf("tencentcloud deployment job failed (succeeded: %d, failed: %d, total: %d)", succeededCount, failedCount, totalCount)
}
break
return true, nil
}
}
d.logger.Info(fmt.Sprintf("waiting for tencentcloud deployment job completion (running: %d, succeeded: %d, failed: %d, total: %d) ...", runningCount, succeededCount, failedCount, totalCount))
time.Sleep(time.Second * 5)
return false, nil
}, time.Second*5); err != nil {
return err
}
return nil
@@ -21,6 +21,7 @@ import (
"github.com/certimate-go/certimate/pkg/core/deployer"
wangsucdn "github.com/certimate-go/certimate/pkg/sdk3rd/wangsu/cdnpro"
xcert "github.com/certimate-go/certimate/pkg/utils/cert"
xwait "github.com/certimate-go/certimate/pkg/utils/wait"
)
type DeployerConfig struct {
@@ -174,6 +175,7 @@ func (d *Deployer) Deploy(ctx context.Context, certPEM, privkeyPEM string) (*dep
// 创建部署任务
// REF: https://www.wangsu.com/document/api-doc/27034
var wangsuTaskId string
createDeploymentTaskReq := &wangsucdn.CreateDeploymentTaskRequest{
Name: lo.ToPtr(fmt.Sprintf("certimate_%d", time.Now().UnixMilli())),
Target: lo.ToPtr(d.config.Environment),
@@ -192,36 +194,32 @@ func (d *Deployer) Deploy(ctx context.Context, certPEM, privkeyPEM string) (*dep
d.logger.Debug("sdk request 'cdnpro.CreateCertificate'", slog.Any("request", createDeploymentTaskReq), slog.Any("response", createDeploymentTaskResp))
if err != nil {
return nil, fmt.Errorf("failed to execute sdk request 'cdnpro.CreateDeploymentTask': %w", err)
}
// 循环获取部署任务详细信息,等待任务状态变更
// REF: https://www.wangsu.com/document/api-doc/27038
var wangsuTaskId string
wangsuTaskMatches := regexp.MustCompile(`/deploymentTasks/([a-zA-Z0-9-]+)`).FindStringSubmatch(createDeploymentTaskResp.DeploymentTaskLocation)
if len(wangsuTaskMatches) > 1 {
wangsuTaskId = wangsuTaskMatches[1]
}
for {
select {
case <-ctx.Done():
return nil, ctx.Err()
default:
} else {
wangsuTaskMatches := regexp.MustCompile(`/deploymentTasks/([a-zA-Z0-9-]+)`).FindStringSubmatch(createDeploymentTaskResp.DeploymentTaskLocation)
if len(wangsuTaskMatches) > 1 {
wangsuTaskId = wangsuTaskMatches[1]
}
}
// 获取部署任务详细信息,等待任务状态变更
// REF: https://www.wangsu.com/document/api-doc/27038
if _, err := xwait.UntilWithContext(ctx, func(_ context.Context, _ int) (bool, error) {
getDeploymentTaskDetailResp, err := d.sdkClient.GetDeploymentTaskDetail(wangsuTaskId)
d.logger.Info("sdk request 'cdnpro.GetDeploymentTaskDetail'", slog.Any("taskId", wangsuTaskId), slog.Any("response", getDeploymentTaskDetailResp))
if err != nil {
return nil, fmt.Errorf("failed to execute sdk request 'cdnpro.GetDeploymentTaskDetail': %w", err)
return false, fmt.Errorf("failed to execute sdk request 'cdnpro.GetDeploymentTaskDetail': %w", err)
}
if getDeploymentTaskDetailResp.Status == "failed" {
return nil, errors.New("unexpected wangsu deployment task status")
return false, fmt.Errorf("unexpected wangsu deployment task status")
} else if getDeploymentTaskDetailResp.Status == "succeeded" || getDeploymentTaskDetailResp.FinishTime != "" {
break
return true, nil
}
d.logger.Info(fmt.Sprintf("waiting for wangsu deployment task completion (current status: %s) ...", getDeploymentTaskDetailResp.Status))
time.Sleep(time.Second * 5)
return false, nil
}, time.Second*5); err != nil {
return nil, err
}
return &deployer.DeployResult{}, nil
@@ -5,9 +5,6 @@ import (
"errors"
"fmt"
"log/slog"
"time"
"github.com/samber/lo"
"github.com/certimate-go/certimate/pkg/core/certmgr"
mcertmgr "github.com/certimate-go/certimate/pkg/core/certmgr/providers/wangsu-certificate"
@@ -78,18 +75,12 @@ func (d *Deployer) Deploy(ctx context.Context, certPEM, privkeyPEM string) (*dep
d.logger.Info("ssl certificate uploaded", slog.Any("result", upres))
}
} else {
// 修改证书
// REF: https://www.wangsu.com/document/api-doc/25568?productCode=certificatemanagement
updateCertificateReq := &wangsusdk.UpdateCertificateRequest{
Name: lo.ToPtr(fmt.Sprintf("certimate_%d", time.Now().UnixMilli())),
Certificate: lo.ToPtr(certPEM),
PrivateKey: lo.ToPtr(privkeyPEM),
Comment: lo.ToPtr("upload from certimate"),
}
updateCertificateResp, err := d.sdkClient.UpdateCertificate(d.config.CertificateId, updateCertificateReq)
d.logger.Debug("sdk request 'certificatemanagement.UpdateCertificate'", slog.Any("request", updateCertificateReq), slog.Any("response", updateCertificateResp))
// 替换证书
opres, err := d.sdkCertmgr.Replace(ctx, d.config.CertificateId, certPEM, privkeyPEM)
if err != nil {
return nil, fmt.Errorf("failed to execute sdk request 'certificatemanagement.CreateCertificate': %w", err)
return nil, fmt.Errorf("failed to replace certificate file: %w", err)
} else {
d.logger.Info("ssl certificate replaced", slog.Any("result", opres))
}
}
+37
View File
@@ -0,0 +1,37 @@
package wait
import (
"context"
"time"
)
// 等待一段时间。
//
// 入参:
// - wait: 等待时间。
//
// 出参:
// - err: 错误。
func Delay(wait time.Duration) error {
return DelayWithContext(context.Background(), wait)
}
// 等待一段时间,或上下文被取消。
//
// 入参:
// - ctx: 上下文。
// - wait: 等待时间。
//
// 出参:
// - err: 错误。
func DelayWithContext(ctx context.Context, wait time.Duration) error {
ticker := time.NewTimer(wait)
defer ticker.Stop()
select {
case <-ctx.Done():
return ctx.Err()
case <-ticker.C:
return nil
}
}
+103
View File
@@ -0,0 +1,103 @@
package wait
import (
"context"
"time"
)
// 等待直到条件满足。
//
// 入参:
// - condition: 条件函数,接收尝试次数作为参数,返回是否满足条件和错误。
// - interval: 执行条件函数的间隔时间。
//
// 出参:
// - ret: 是否满足条件。
// - err: 错误。
func Until(condition func(index int) (bool, error), interval time.Duration) (bool, error) {
conditionWithContext := func(_ context.Context, index int) (bool, error) {
return condition(index)
}
return UntilWithContext(context.Background(), conditionWithContext, interval)
}
// 等待直到条件满足,或上下文被取消。
//
// 入参:
// - ctx: 上下文。
// - condition: 条件函数,接收上下文和尝试次数作为参数,返回是否满足条件和错误。
// - interval: 执行条件函数的间隔时间。
//
// 出参:
// - ret: 是否满足条件。
// - err: 错误。
func UntilWithContext(ctx context.Context, condition func(ctx context.Context, index int) (bool, error), interval time.Duration) (bool, error) {
ticker := time.NewTicker(interval)
defer ticker.Stop()
attempt := 0
for {
select {
case <-ctx.Done():
return false, ctx.Err()
case <-ticker.C:
attempt++
ret, err := condition(ctx, attempt)
if ret || err != nil {
return ret, err
}
}
}
}
// 等待直到条件满足或超时。
//
// 入参:
// - condition: 条件函数,接收尝试次数作为参数,返回是否满足条件和错误。
// - timeout: 超时时间。
// - interval: 执行条件函数的间隔时间。
//
// 出参:
// - ret: 是否满足条件。
// - err: 错误。
func UntilTimeout(condition func(index int) (bool, error), timeout time.Duration, interval time.Duration) (bool, error) {
conditionWithContext := func(_ context.Context, index int) (bool, error) {
return condition(index)
}
return UntilTimeoutWithContext(context.Background(), conditionWithContext, timeout, interval)
}
// 等待直到条件满足或超时,或上下文被取消。
//
// 入参:
// - ctx: 上下文。
// - condition: 条件函数,接收上下文和尝试次数作为参数,返回是否满足条件和错误。
// - timeout: 超时时间。
// - interval: 执行条件函数的间隔时间。
//
// 出参:
// - ret: 是否满足条件。
// - err: 错误。
func UntilTimeoutWithContext(ctx context.Context, condition func(ctx context.Context, index int) (bool, error), timeout time.Duration, interval time.Duration) (bool, error) {
ctxWithTimeout, cancel := context.WithTimeout(ctx, timeout)
defer cancel()
ticker := time.NewTicker(interval)
defer ticker.Stop()
attempt := 0
for {
select {
case <-ctxWithTimeout.Done():
return false, ctx.Err()
case <-ticker.C:
attempt++
ret, err := condition(ctxWithTimeout, attempt)
if ret || err != nil {
return ret, err
}
}
}
}