diff --git a/pkg/core/deployer/providers/baotapanel/baotapanel.go b/pkg/core/deployer/providers/baotapanel/baotapanel.go
index bec99eb5..6c40acaf 100644
--- a/pkg/core/deployer/providers/baotapanel/baotapanel.go
+++ b/pkg/core/deployer/providers/baotapanel/baotapanel.go
@@ -76,30 +76,12 @@ func (d *Deployer) Deploy(ctx context.Context, certPEM, privkeyPEM string) (*Dep
switch d.config.SiteType {
case "any":
{
- // 上传证书
- sslCertSaveCertReq := &btpanelsdk.SSLCertSaveCertRequest{
- Certificate: certPEM,
- PrivateKey: privkeyPEM,
- }
- sslCertSaveCertResp, err := d.sdkClient.SSLCertSaveCertWithContext(ctx, sslCertSaveCertReq)
- d.logger.Debug("sdk request 'ssl.cert.SaveCert'", slog.Any("request", sslCertSaveCertReq), slog.Any("response", sslCertSaveCertResp))
- if err != nil {
- return nil, fmt.Errorf("failed to execute sdk request 'ssl.cert.SaveCert': %w", err)
- }
-
- // 设置站点证书
- sslSetBatchCertToSiteReq := &btpanelsdk.SSLSetBatchCertToSiteRequest{
- BatchInfo: lo.Map(d.config.SiteNames, func(siteName string, _ int) *btpanelsdk.SSLSetBatchCertToSiteRequestBatchInfo {
- return &btpanelsdk.SSLSetBatchCertToSiteRequestBatchInfo{
- SiteName: siteName,
- SSLHash: sslCertSaveCertResp.SSLHash,
- }
- }),
- }
- sslSetBatchCertToSiteResp, err := d.sdkClient.SSLSetBatchCertToSiteWithContext(ctx, sslSetBatchCertToSiteReq)
- d.logger.Debug("sdk request 'ssl.SetBatchCertToSite'", slog.Any("request", sslSetBatchCertToSiteReq), slog.Any("response", sslSetBatchCertToSiteResp))
- if err != nil {
- return nil, fmt.Errorf("failed to execute sdk request 'ssl.SetBatchCertToSite': %w", err)
+ // 批量更新站点证书
+ // 注意,如果 v1 接口不可用,则尝试使用 v2 接口重试
+ if err1 := d.updateSitesCertificateByAny(ctx, d.config.SiteNames, certPEM, privkeyPEM); err1 != nil {
+ if err2 := d.updateSitesCertificateByAnyV2(ctx, d.config.SiteNames, certPEM, privkeyPEM); err2 != nil {
+ return nil, errors.Join(err1, err2)
+ }
}
}
@@ -171,6 +153,63 @@ func (d *Deployer) updateSiteCertificate(ctx context.Context, siteType, siteName
return nil
}
+func (d *Deployer) updateSitesCertificateByAny(ctx context.Context, siteNames []string, certPEM, privkeyPEM string) error {
+ // 上传证书
+ sslCertSaveCertReq := &btpanelsdk.SSLCertSaveCertRequest{
+ Certificate: certPEM,
+ PrivateKey: privkeyPEM,
+ }
+ sslCertSaveCertResp, err := d.sdkClient.SSLCertSaveCertWithContext(ctx, sslCertSaveCertReq)
+ d.logger.Debug("sdk request 'ssl.cert.SaveCert'", slog.Any("request", sslCertSaveCertReq), slog.Any("response", sslCertSaveCertResp))
+ if err != nil {
+ return fmt.Errorf("failed to execute sdk request 'ssl.cert.SaveCert': %w", err)
+ }
+
+ // 设置站点证书
+ sslSetBatchCertToSiteReq := &btpanelsdk.SSLSetBatchCertToSiteRequest{
+ BatchInfo: lo.Map(siteNames, func(siteName string, _ int) *btpanelsdk.SSLSetBatchCertToSiteRequestBatchInfo {
+ return &btpanelsdk.SSLSetBatchCertToSiteRequestBatchInfo{
+ SiteName: siteName,
+ SSLHash: sslCertSaveCertResp.SSLHash,
+ }
+ }),
+ }
+ sslSetBatchCertToSiteResp, err := d.sdkClient.SSLSetBatchCertToSiteWithContext(ctx, sslSetBatchCertToSiteReq)
+ d.logger.Debug("sdk request 'ssl.SetBatchCertToSite'", slog.Any("request", sslSetBatchCertToSiteReq), slog.Any("response", sslSetBatchCertToSiteResp))
+ if err != nil {
+ return fmt.Errorf("failed to execute sdk request 'ssl.SetBatchCertToSite': %w", err)
+ }
+
+ return nil
+}
+
+func (d *Deployer) updateSitesCertificateByAnyV2(ctx context.Context, siteNames []string, certPEM, privkeyPEM string) error {
+ // 上传证书
+ sslDomainUploadCertV2Req := &btpanelsdk.SSLDomainUploadCertV2Request{
+ Certificate: certPEM,
+ PrivateKey: privkeyPEM,
+ }
+ sslDomainUploadCertV2Resp, err := d.sdkClient.SSLDomainUploadCertV2WithContext(ctx, sslDomainUploadCertV2Req)
+ d.logger.Debug("sdk request 'v2.ssldomain.UploadCert'", slog.Any("request", sslDomainUploadCertV2Req), slog.Any("response", sslDomainUploadCertV2Resp))
+ if err != nil {
+ return fmt.Errorf("failed to execute sdk request 'v2.ssldomain.UploadCert': %w", err)
+ }
+
+ // 设置站点证书
+ sslDomainCertDeploySitesV2Req := &btpanelsdk.SSLDomainCertDeploySitesV2Request{
+ SSLHash: sslDomainUploadCertV2Resp.Message.SSLHash,
+ Domains: siteNames,
+ Append: 1,
+ }
+ sslDomainCertDeploySitesV2Resp, err := d.sdkClient.SSLDomainCertDeploySitesV2WithContext(ctx, sslDomainCertDeploySitesV2Req)
+ d.logger.Debug("sdk request 'v2.ssldomain.CertDeploySites'", slog.Any("request", sslDomainCertDeploySitesV2Req), slog.Any("response", sslDomainCertDeploySitesV2Resp))
+ if err != nil {
+ return fmt.Errorf("failed to execute sdk request 'v2.ssldomain.CertDeploySites': %w", err)
+ }
+
+ return nil
+}
+
func createSDKClient(serverUrl, apiKey string, skipTlsVerify bool) (*btpanelsdk.Client, error) {
client, err := btpanelsdk.NewClient(serverUrl,
btpanelsdk.WithApiKey(apiKey),
diff --git a/pkg/sdk3rd/btpanel/api_ssldomain_cert_deploy_sites_v2.go b/pkg/sdk3rd/btpanel/api_ssldomain_cert_deploy_sites_v2.go
new file mode 100644
index 00000000..99a1fdd7
--- /dev/null
+++ b/pkg/sdk3rd/btpanel/api_ssldomain_cert_deploy_sites_v2.go
@@ -0,0 +1,36 @@
+package btpanel
+
+import (
+ "context"
+ "net/http"
+)
+
+type SSLDomainCertDeploySitesV2Request struct {
+ SSLHash string `json:"hash"`
+ Domains []string `json:"domains"`
+ Append int32 `json:"append"`
+}
+
+type SSLDomainCertDeploySitesV2Response struct {
+ sdkResponseBaseV2
+}
+
+func (c *Client) SSLDomainCertDeploySitesV2(req *SSLDomainCertDeploySitesV2Request) (*SSLDomainCertDeploySitesV2Response, error) {
+ return c.SSLDomainCertDeploySitesV2WithContext(context.Background(), req)
+}
+
+func (c *Client) SSLDomainCertDeploySitesV2WithContext(ctx context.Context, req *SSLDomainCertDeploySitesV2Request) (*SSLDomainCertDeploySitesV2Response, error) {
+ httpreq, err := c.newRequest(http.MethodPost, "/v2/ssl_domain?action=cert_deploy_sites", req)
+ if err != nil {
+ return nil, err
+ } else {
+ httpreq.SetContext(ctx)
+ }
+
+ result := &SSLDomainCertDeploySitesV2Response{}
+ if _, err := c.doRequestWithResult(httpreq, result); err != nil {
+ return result, err
+ }
+
+ return result, nil
+}
diff --git a/pkg/sdk3rd/btpanel/api_ssldomain_upload_cert_v2.go b/pkg/sdk3rd/btpanel/api_ssldomain_upload_cert_v2.go
new file mode 100644
index 00000000..0ac23752
--- /dev/null
+++ b/pkg/sdk3rd/btpanel/api_ssldomain_upload_cert_v2.go
@@ -0,0 +1,39 @@
+package btpanel
+
+import (
+ "context"
+ "net/http"
+)
+
+type SSLDomainUploadCertV2Request struct {
+ PrivateKey string `json:"key"`
+ Certificate string `json:"cert"`
+}
+
+type SSLDomainUploadCertV2Response struct {
+ sdkResponseBaseV2
+
+ Message *struct {
+ SSLHash string `json:"hash,omitempty"`
+ } `json:"message,omitempty"`
+}
+
+func (c *Client) SSLDomainUploadCertV2(req *SSLDomainUploadCertV2Request) (*SSLDomainUploadCertV2Response, error) {
+ return c.SSLDomainUploadCertV2WithContext(context.Background(), req)
+}
+
+func (c *Client) SSLDomainUploadCertV2WithContext(ctx context.Context, req *SSLDomainUploadCertV2Request) (*SSLDomainUploadCertV2Response, error) {
+ httpreq, err := c.newRequest(http.MethodPost, "/v2/ssl_domain?action=upload_cert", req)
+ if err != nil {
+ return nil, err
+ } else {
+ httpreq.SetContext(ctx)
+ }
+
+ result := &SSLDomainUploadCertV2Response{}
+ if _, err := c.doRequestWithResult(httpreq, result); err != nil {
+ return result, err
+ }
+
+ return result, nil
+}
diff --git a/pkg/sdk3rd/btpanel/types.go b/pkg/sdk3rd/btpanel/types.go
index bf494904..9e5b05d3 100644
--- a/pkg/sdk3rd/btpanel/types.go
+++ b/pkg/sdk3rd/btpanel/types.go
@@ -17,3 +17,32 @@ func (r *sdkResponseBase) GetStatus() *bool {
func (r *sdkResponseBase) GetMessage() *string {
return r.Message
}
+
+var _ sdkResponse = (*sdkResponseBase)(nil)
+
+type sdkResponseBaseV2 struct {
+ Status *int32 `json:"status,omitempty"`
+ Timestamp *int64 `json:"timestamp,omitempty"`
+ Message *struct {
+ Result *string `json:"result,omitempty"`
+ } `json:"message,omitempty"`
+}
+
+func (r *sdkResponseBaseV2) GetStatus() *bool {
+ if r.Status != nil {
+ status := *r.Status == 0
+ return &status
+ }
+
+ return nil
+}
+
+func (r *sdkResponseBaseV2) GetMessage() *string {
+ if r.Message != nil {
+ return r.Message.Result
+ }
+
+ return nil
+}
+
+var _ sdkResponse = (*sdkResponseBaseV2)(nil)
diff --git a/pkg/sdk3rd/btpanelgo/types.go b/pkg/sdk3rd/btpanelgo/types.go
index 347f94f1..e60cd65e 100644
--- a/pkg/sdk3rd/btpanelgo/types.go
+++ b/pkg/sdk3rd/btpanelgo/types.go
@@ -22,3 +22,5 @@ func (r *sdkResponseBase) GetStatus() json.RawMessage {
func (r *sdkResponseBase) GetMessage() *string {
return r.Message
}
+
+var _ sdkResponse = (*sdkResponseBase)(nil)
diff --git a/ui/src/i18n/resources/en/nls.workflow.nodes.json b/ui/src/i18n/resources/en/nls.workflow.nodes.json
index d0f20ba4..a9d7991d 100644
--- a/ui/src/i18n/resources/en/nls.workflow.nodes.json
+++ b/ui/src/i18n/resources/en/nls.workflow.nodes.json
@@ -1173,7 +1173,7 @@
"tooltip": "For more information, see https://cdnx.console.baishan.com/#/cdn/cert"
},
"baotapanel": {
- "guide": "Requires aaPanel v7.0 or higher."
+ "guide": "Requires aaPanel v7.0 / BaotaPanel v8.3 or higher."
},
"baotapanel_site_type": {
"label": "aaPanel website type",
@@ -1204,7 +1204,7 @@
"label": "General Project"
},
"any": {
- "label": "Any Project (aaPanel v7.26+)"
+ "label": "Any Project (aaPanel v7.26+ / BaotaPanel v9.4+)"
}
}
},
diff --git a/ui/src/i18n/resources/zh/nls.workflow.nodes.json b/ui/src/i18n/resources/zh/nls.workflow.nodes.json
index 162cbcbe..e0ce0f54 100644
--- a/ui/src/i18n/resources/zh/nls.workflow.nodes.json
+++ b/ui/src/i18n/resources/zh/nls.workflow.nodes.json
@@ -1172,7 +1172,7 @@
"tooltip": "这是什么?请参阅 https://cdnx.console.baishan.com/#/cdn/cert"
},
"baotapanel": {
- "guide": "需要宝塔面板 v8.3 或更高版本。"
+ "guide": "需要宝塔面板 v8.3 / aaPanel v7.0 或更高版本。"
},
"baotapanel_site_type": {
"label": "宝塔面板网站类型",
@@ -1203,7 +1203,7 @@
"label": "通用项目"
},
"any": {
- "label": "任意类型(需要宝塔面板 v9.4+)"
+ "label": "任意类型(需要宝塔面板 v9.4+ / aaPanel v7.26+)"
}
}
},