diff --git a/README.md b/README.md
index b7cfc56e..6f90fb32 100644
--- a/README.md
+++ b/README.md
@@ -116,23 +116,24 @@ make local.run
[展开查看]
-| 提供商 | 备注 |
-| :-------------------------------------- | :------------------------------------------------------------------ |
-| 本地部署 | 可部署到本地服务器 |
-| SSH 部署 | 可部署到远程服务器(通过 SSH+SFTP/SCP) |
-| Webhook 回调 | 可部署到 Webhook |
-| [Kubernetes](https://kubernetes.io/) | 可部署到 Kubernetes Secret |
-| [阿里云](https://www.aliyun.com/) | 可部署到阿里云 OSS、CDN、DCDN、SLB(CLB/ALB/NLB)、WAF、Live 等服务 |
-| [腾讯云](https://cloud.tencent.com/) | 可部署到腾讯云 COS、CDN、ECDN、EdgeOne、CLB、CSS 等服务 |
-| [百度智能云](https://cloud.baidu.com/) | 可部署到百度智能云 CDN 等服务 |
-| [华为云](https://www.huaweicloud.com/) | 可部署到华为云 CDN、ELB 等服务 |
-| [火山引擎](https://www.volcengine.com/) | 可部署到火山引擎 TOS、CDN、DCDN、CLB、Live 等服务 |
-| [七牛云](https://www.qiniu.com/) | 可部署到七牛云 CDN、直播云等服务 |
-| [多吉云](https://www.dogecloud.com/) | 可部署到多吉云 CDN |
-| [BytePlus](https://www.byteplus.com/) | 可部署到 BytePlus CDN 等服务 |
-| [优刻得](https://www.ucloud.cn/) | 可部署到优刻得 US3、UCDN 等服务 |
-| [AWS](https://aws.amazon.com/) | 可部署到 AWS CloudFront 等服务 |
-| [Edgio](https://edg.io/) | 可部署到 Edgio Applications 等服务 |
+| 提供商 | 备注 |
+| :-------------------------------------- | :----------------------------------------------------------------------- |
+| 本地部署 | 可部署到本地服务器 |
+| SSH 部署 | 可部署到远程服务器(通过 SSH+SFTP/SCP) |
+| Webhook 回调 | 可部署到 Webhook |
+| [Kubernetes](https://kubernetes.io/) | 可部署到 Kubernetes Secret |
+| [阿里云](https://www.aliyun.com/) | 可部署到阿里云 OSS、CDN、DCDN、ESA、SLB(CLB/ALB/NLB)、WAF、Live 等服务 |
+| [腾讯云](https://cloud.tencent.com/) | 可部署到腾讯云 COS、CDN、ECDN、EdgeOne、CLB、CSS 等服务 |
+| [百度智能云](https://cloud.baidu.com/) | 可部署到百度智能云 CDN 等服务 |
+| [华为云](https://www.huaweicloud.com/) | 可部署到华为云 CDN、ELB 等服务 |
+| [火山引擎](https://www.volcengine.com/) | 可部署到火山引擎 TOS、CDN、DCDN、CLB、Live 等服务 |
+| [七牛云](https://www.qiniu.com/) | 可部署到七牛云 CDN、直播云等服务 |
+| [多吉云](https://www.dogecloud.com/) | 可部署到多吉云 CDN |
+| [优刻得](https://www.ucloud.cn/) | 可部署到优刻得 US3、UCDN 等服务 |
+| [宝塔面板](https://www.bt.cn/) | 可部署到宝塔面板 |
+| [AWS](https://aws.amazon.com/) | 可部署到 AWS CloudFront 等服务 |
+| [BytePlus](https://www.byteplus.com/) | 可部署到 BytePlus CDN 等服务 |
+| [Edgio](https://edg.io/) | 可部署到 Edgio Applications 等服务 |
diff --git a/README_EN.md b/README_EN.md
index c2174fad..d5300b07 100644
--- a/README_EN.md
+++ b/README_EN.md
@@ -128,9 +128,10 @@ The following hosting providers are supported:
| [Volcengine](https://www.volcengine.com/) | Supports deployment to Volcengine TOS, CDN, DCDN, CLB, Live |
| [Qiniu Cloud](https://www.qiniu.com/) | Supports deployment to Qiniu Cloud CDN, Pili |
| [Doge Cloud](https://www.dogecloud.com/) | Supports deployment to Doge Cloud CDN |
-| [BytePlus](https://www.byteplus.com/) | Supports deployment to BytePlus CDN |
+| [BaoTa Panel](https://www.bt.cn/) | Supports deployment to BaoTa Panel sites |
| [UCloud](https://www.ucloud-global.com/) | Supports deployment to UCloud US3, UCDN |
| [AWS](https://aws.amazon.com/) | Supports deployment to AWS CloudFront |
+| [BytePlus](https://www.byteplus.com/) | Supports deployment to BytePlus CDN |
| [Edgio](https://edg.io/) | Supports deployment to Edgio Applications |
diff --git a/go.mod b/go.mod
index cc7c0ff1..536d66e4 100644
--- a/go.mod
+++ b/go.mod
@@ -10,6 +10,7 @@ require (
github.com/alibabacloud-go/cas-20200407/v3 v3.0.4
github.com/alibabacloud-go/cdn-20180510/v5 v5.2.2
github.com/alibabacloud-go/darabonba-openapi/v2 v2.0.10
+ github.com/alibabacloud-go/esa-20240910/v2 v2.12.0
github.com/alibabacloud-go/live-20161101 v1.1.1
github.com/alibabacloud-go/nlb-20220430/v2 v2.0.3
github.com/alibabacloud-go/slb-20140515/v4 v4.0.10
diff --git a/go.sum b/go.sum
index 199c33dd..e470d833 100644
--- a/go.sum
+++ b/go.sum
@@ -137,6 +137,8 @@ github.com/alibabacloud-go/debug v1.0.1/go.mod h1:8gfgZCCAC3+SCzjWtY053FrOcd4/ql
github.com/alibabacloud-go/endpoint-util v1.1.0/go.mod h1:O5FuCALmCKs2Ff7JFJMudHs0I5EBgecXXxZRyswlEjE=
github.com/alibabacloud-go/endpoint-util v1.1.1 h1:ZkBv2/jnghxtU0p+upSU0GGzW1VL9GQdZO3mcSUTUy8=
github.com/alibabacloud-go/endpoint-util v1.1.1/go.mod h1:O5FuCALmCKs2Ff7JFJMudHs0I5EBgecXXxZRyswlEjE=
+github.com/alibabacloud-go/esa-20240910/v2 v2.12.0 h1:DPyKQSVf+uba5SBEGgBpXRA8NpFuym1cSTKm1LzSxEo=
+github.com/alibabacloud-go/esa-20240910/v2 v2.12.0/go.mod h1:P1w/+i7dE2xSXVHJznEOVImlLtqqrzUJQQk2AsyBJ6o=
github.com/alibabacloud-go/live-20161101 v1.1.1 h1:rUGfA8RHmCMtQ5M3yMSyRde+yRXWqVecmiXBU3XrGJ8=
github.com/alibabacloud-go/live-20161101 v1.1.1/go.mod h1:g84w6qeAodT0/IHdc0tEed2a8PyhQhYl7TAj3jGl4A4=
github.com/alibabacloud-go/nlb-20220430/v2 v2.0.3 h1:LtyUVlgBEKyzWgQJurzXM6MXCt84sQr9cE5OKqYymko=
diff --git a/internal/deployer/providers.go b/internal/deployer/providers.go
index c5f7f40a..97cb0861 100644
--- a/internal/deployer/providers.go
+++ b/internal/deployer/providers.go
@@ -2,19 +2,23 @@ package deployer
import (
"fmt"
+ "strings"
"github.com/usual2970/certimate/internal/domain"
"github.com/usual2970/certimate/internal/pkg/core/deployer"
providerAliyunALB "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/aliyun-alb"
+ providerAliyunCASDeploy "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/aliyun-cas-deploy"
providerAliyunCDN "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/aliyun-cdn"
providerAliyunCLB "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/aliyun-clb"
providerAliyunDCDN "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/aliyun-dcdn"
+ providerAliyunESA "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/aliyun-esa"
providerAliyunLive "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/aliyun-live"
providerAliyunNLB "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/aliyun-nlb"
providerAliyunOSS "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/aliyun-oss"
providerAliyunWAF "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/aliyun-waf"
providerAWSCloudFront "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/aws-cloudfront"
providerBaiduCloudCDN "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/baiducloud-cdn"
+ providerBaotaPanelSite "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/baotapanel-site"
providerBytePlusCDN "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/byteplus-cdn"
providerDogeCDN "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/dogecloud-cdn"
providerEdgioApplications "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/edgio-applications"
@@ -31,6 +35,7 @@ import (
providerTencentCloudCSS "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/tencentcloud-css"
providerTencentCloudECDN "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/tencentcloud-ecdn"
providerTencentCloudEO "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/tencentcloud-eo"
+ providerTencentCloudSSLDeploy "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/tencentcloud-ssl-deploy"
providerUCloudUCDN "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/ucloud-ucdn"
providerUCloudUS3 "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/ucloud-us3"
providerVolcEngineCDN "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/volcengine-cdn"
@@ -41,6 +46,7 @@ import (
providerWebhook "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/webhook"
"github.com/usual2970/certimate/internal/pkg/core/logger"
"github.com/usual2970/certimate/internal/pkg/utils/maps"
+ "github.com/usual2970/certimate/internal/pkg/utils/slices"
)
func createDeployer(options *deployerOptions) (deployer.Deployer, logger.Logger, error) {
@@ -51,7 +57,7 @@ func createDeployer(options *deployerOptions) (deployer.Deployer, logger.Logger,
NOTICE: If you add new constant, please keep ASCII order.
*/
switch options.Provider {
- case domain.DeployProviderTypeAliyunALB, domain.DeployProviderTypeAliyunCDN, domain.DeployProviderTypeAliyunCLB, domain.DeployProviderTypeAliyunDCDN, domain.DeployProviderTypeAliyunLive, domain.DeployProviderTypeAliyunNLB, domain.DeployProviderTypeAliyunOSS, domain.DeployProviderTypeAliyunWAF:
+ case domain.DeployProviderTypeAliyunALB, domain.DeployProviderTypeAliyunCASDeploy, domain.DeployProviderTypeAliyunCDN, domain.DeployProviderTypeAliyunCLB, domain.DeployProviderTypeAliyunDCDN, domain.DeployProviderTypeAliyunESA, domain.DeployProviderTypeAliyunLive, domain.DeployProviderTypeAliyunNLB, domain.DeployProviderTypeAliyunOSS, domain.DeployProviderTypeAliyunWAF:
{
access := domain.AccessConfigForAliyun{}
if err := maps.Populate(options.ProviderAccessConfig, &access); err != nil {
@@ -71,6 +77,16 @@ func createDeployer(options *deployerOptions) (deployer.Deployer, logger.Logger,
}, logger)
return deployer, logger, err
+ case domain.DeployProviderTypeAliyunCASDeploy:
+ deployer, err := providerAliyunCASDeploy.NewWithLogger(&providerAliyunCASDeploy.AliyunCASDeployDeployerConfig{
+ AccessKeyId: access.AccessKeyId,
+ AccessKeySecret: access.AccessKeySecret,
+ Region: maps.GetValueAsString(options.ProviderDeployConfig, "region"),
+ ResourceIds: slices.Filter(strings.Split(maps.GetValueAsString(options.ProviderDeployConfig, "resourceIds"), ";"), func(s string) bool { return s != "" }),
+ ContactIds: slices.Filter(strings.Split(maps.GetValueAsString(options.ProviderDeployConfig, "contactIds"), ";"), func(s string) bool { return s != "" }),
+ }, logger)
+ return deployer, logger, err
+
case domain.DeployProviderTypeAliyunCDN:
deployer, err := providerAliyunCDN.NewWithLogger(&providerAliyunCDN.AliyunCDNDeployerConfig{
AccessKeyId: access.AccessKeyId,
@@ -99,6 +115,15 @@ func createDeployer(options *deployerOptions) (deployer.Deployer, logger.Logger,
}, logger)
return deployer, logger, err
+ case domain.DeployProviderTypeAliyunESA:
+ deployer, err := providerAliyunESA.NewWithLogger(&providerAliyunESA.AliyunESADeployerConfig{
+ AccessKeyId: access.AccessKeyId,
+ AccessKeySecret: access.AccessKeySecret,
+ Region: maps.GetValueAsString(options.ProviderDeployConfig, "region"),
+ SiteId: maps.GetValueAsInt64(options.ProviderDeployConfig, "siteId"),
+ }, logger)
+ return deployer, logger, err
+
case domain.DeployProviderTypeAliyunLive:
deployer, err := providerAliyunLive.NewWithLogger(&providerAliyunLive.AliyunLiveDeployerConfig{
AccessKeyId: access.AccessKeyId,
@@ -186,6 +211,21 @@ func createDeployer(options *deployerOptions) (deployer.Deployer, logger.Logger,
}
}
+ case domain.DeployProviderTypeBaotaPanelSite:
+ {
+ access := domain.AccessConfigForBaotaPanel{}
+ if err := maps.Decode(options.ProviderAccessConfig, &access); err != nil {
+ return nil, nil, fmt.Errorf("failed to decode provider access config: %w", err)
+ }
+
+ deployer, err := providerBaotaPanelSite.NewWithLogger(&providerBaotaPanelSite.BaotaPanelSiteDeployerConfig{
+ ApiUrl: access.ApiUrl,
+ ApiKey: access.ApiKey,
+ SiteName: maps.GetValueAsString(options.ProviderDeployConfig, "siteName"),
+ }, logger)
+ return deployer, logger, err
+ }
+
case domain.DeployProviderTypeBytePlusCDN:
{
access := domain.AccessConfigForBytePlus{}
@@ -364,7 +404,7 @@ func createDeployer(options *deployerOptions) (deployer.Deployer, logger.Logger,
return deployer, logger, err
}
- case domain.DeployProviderTypeTencentCloudCDN, domain.DeployProviderTypeTencentCloudCLB, domain.DeployProviderTypeTencentCloudCOS, domain.DeployProviderTypeTencentCloudCSS, domain.DeployProviderTypeTencentCloudECDN, domain.DeployProviderTypeTencentCloudEO:
+ case domain.DeployProviderTypeTencentCloudCDN, domain.DeployProviderTypeTencentCloudCLB, domain.DeployProviderTypeTencentCloudCOS, domain.DeployProviderTypeTencentCloudCSS, domain.DeployProviderTypeTencentCloudECDN, domain.DeployProviderTypeTencentCloudEO, domain.DeployProviderTypeTencentCloudSSLDeploy:
{
access := domain.AccessConfigForTencentCloud{}
if err := maps.Populate(options.ProviderAccessConfig, &access); err != nil {
@@ -427,6 +467,16 @@ func createDeployer(options *deployerOptions) (deployer.Deployer, logger.Logger,
}, logger)
return deployer, logger, err
+ case domain.DeployProviderTypeTencentCloudSSLDeploy:
+ deployer, err := providerTencentCloudSSLDeploy.NewWithLogger(&providerTencentCloudSSLDeploy.TencentCloudSSLDeployDeployerConfig{
+ SecretId: access.SecretId,
+ SecretKey: access.SecretKey,
+ Region: maps.GetValueAsString(options.ProviderDeployConfig, "region"),
+ ResourceType: maps.GetValueAsString(options.ProviderDeployConfig, "resourceType"),
+ ResourceIds: slices.Filter(strings.Split(maps.GetValueAsString(options.ProviderDeployConfig, "resourceIds"), ";"), func(s string) bool { return s != "" }),
+ }, logger)
+ return deployer, logger, err
+
default:
break
}
diff --git a/internal/domain/access.go b/internal/domain/access.go
index c8448c21..e6d94764 100644
--- a/internal/domain/access.go
+++ b/internal/domain/access.go
@@ -54,6 +54,11 @@ type AccessConfigForBaiduCloud struct {
SecretAccessKey string `json:"secretAccessKey"`
}
+type AccessConfigForBaotaPanel struct {
+ ApiUrl string `json:"apiUrl"`
+ ApiKey string `json:"apiKey"`
+}
+
type AccessConfigForBytePlus struct {
AccessKey string `json:"accessKey"`
SecretKey string `json:"secretKey"`
diff --git a/internal/domain/provider.go b/internal/domain/provider.go
index 894f8007..49bf2cee 100644
--- a/internal/domain/provider.go
+++ b/internal/domain/provider.go
@@ -14,6 +14,7 @@ const (
AccessProviderTypeAWS = AccessProviderType("aws")
AccessProviderTypeAzure = AccessProviderType("azure")
AccessProviderTypeBaiduCloud = AccessProviderType("baiducloud")
+ AccessProviderTypeBaotaPanel = AccessProviderType("baotapanel")
AccessProviderTypeBytePlus = AccessProviderType("byteplus")
AccessProviderTypeCloudflare = AccessProviderType("cloudflare")
AccessProviderTypeClouDNS = AccessProviderType("cloudns")
@@ -82,38 +83,42 @@ type DeployProviderType string
NOTICE: If you add new constant, please keep ASCII order.
*/
const (
- DeployProviderTypeAliyunALB = DeployProviderType("aliyun-alb")
- DeployProviderTypeAliyunCDN = DeployProviderType("aliyun-cdn")
- DeployProviderTypeAliyunCLB = DeployProviderType("aliyun-clb")
- DeployProviderTypeAliyunDCDN = DeployProviderType("aliyun-dcdn")
- DeployProviderTypeAliyunLive = DeployProviderType("aliyun-live")
- DeployProviderTypeAliyunNLB = DeployProviderType("aliyun-nlb")
- DeployProviderTypeAliyunOSS = DeployProviderType("aliyun-oss")
- DeployProviderTypeAliyunWAF = DeployProviderType("aliyun-waf")
- DeployProviderTypeAWSCloudFront = DeployProviderType("aws-cloudfront")
- DeployProviderTypeBaiduCloudCDN = DeployProviderType("baiducloud-cdn")
- DeployProviderTypeBytePlusCDN = DeployProviderType("byteplus-cdn")
- DeployProviderTypeDogeCloudCDN = DeployProviderType("dogecloud-cdn")
- DeployProviderTypeEdgioApplications = DeployProviderType("edgio-applications")
- DeployProviderTypeHuaweiCloudCDN = DeployProviderType("huaweicloud-cdn")
- DeployProviderTypeHuaweiCloudELB = DeployProviderType("huaweicloud-elb")
- DeployProviderTypeKubernetesSecret = DeployProviderType("k8s-secret")
- DeployProviderTypeLocal = DeployProviderType("local")
- DeployProviderTypeQiniuCDN = DeployProviderType("qiniu-cdn")
- DeployProviderTypeQiniuPili = DeployProviderType("qiniu-pili")
- DeployProviderTypeSSH = DeployProviderType("ssh")
- DeployProviderTypeTencentCloudCDN = DeployProviderType("tencentcloud-cdn")
- DeployProviderTypeTencentCloudCLB = DeployProviderType("tencentcloud-clb")
- DeployProviderTypeTencentCloudCOS = DeployProviderType("tencentcloud-cos")
- DeployProviderTypeTencentCloudCSS = DeployProviderType("tencentcloud-css")
- DeployProviderTypeTencentCloudECDN = DeployProviderType("tencentcloud-ecdn")
- DeployProviderTypeTencentCloudEO = DeployProviderType("tencentcloud-eo")
- DeployProviderTypeUCloudUCDN = DeployProviderType("ucloud-ucdn")
- DeployProviderTypeUCloudUS3 = DeployProviderType("ucloud-us3")
- DeployProviderTypeVolcEngineCDN = DeployProviderType("volcengine-cdn")
- DeployProviderTypeVolcEngineCLB = DeployProviderType("volcengine-clb")
- DeployProviderTypeVolcEngineDCDN = DeployProviderType("volcengine-dcdn")
- DeployProviderTypeVolcEngineLive = DeployProviderType("volcengine-live")
- DeployProviderTypeVolcEngineTOS = DeployProviderType("volcengine-tos")
- DeployProviderTypeWebhook = DeployProviderType("webhook")
+ DeployProviderTypeAliyunALB = DeployProviderType("aliyun-alb")
+ DeployProviderTypeAliyunCASDeploy = DeployProviderType("aliyun-casdeploy")
+ DeployProviderTypeAliyunCDN = DeployProviderType("aliyun-cdn")
+ DeployProviderTypeAliyunCLB = DeployProviderType("aliyun-clb")
+ DeployProviderTypeAliyunDCDN = DeployProviderType("aliyun-dcdn")
+ DeployProviderTypeAliyunESA = DeployProviderType("aliyun-esa")
+ DeployProviderTypeAliyunLive = DeployProviderType("aliyun-live")
+ DeployProviderTypeAliyunNLB = DeployProviderType("aliyun-nlb")
+ DeployProviderTypeAliyunOSS = DeployProviderType("aliyun-oss")
+ DeployProviderTypeAliyunWAF = DeployProviderType("aliyun-waf")
+ DeployProviderTypeAWSCloudFront = DeployProviderType("aws-cloudfront")
+ DeployProviderTypeBaiduCloudCDN = DeployProviderType("baiducloud-cdn")
+ DeployProviderTypeBaotaPanelSite = DeployProviderType("baotapanel-site")
+ DeployProviderTypeBytePlusCDN = DeployProviderType("byteplus-cdn")
+ DeployProviderTypeDogeCloudCDN = DeployProviderType("dogecloud-cdn")
+ DeployProviderTypeEdgioApplications = DeployProviderType("edgio-applications")
+ DeployProviderTypeHuaweiCloudCDN = DeployProviderType("huaweicloud-cdn")
+ DeployProviderTypeHuaweiCloudELB = DeployProviderType("huaweicloud-elb")
+ DeployProviderTypeKubernetesSecret = DeployProviderType("k8s-secret")
+ DeployProviderTypeLocal = DeployProviderType("local")
+ DeployProviderTypeQiniuCDN = DeployProviderType("qiniu-cdn")
+ DeployProviderTypeQiniuPili = DeployProviderType("qiniu-pili")
+ DeployProviderTypeSSH = DeployProviderType("ssh")
+ DeployProviderTypeTencentCloudCDN = DeployProviderType("tencentcloud-cdn")
+ DeployProviderTypeTencentCloudCLB = DeployProviderType("tencentcloud-clb")
+ DeployProviderTypeTencentCloudCOS = DeployProviderType("tencentcloud-cos")
+ DeployProviderTypeTencentCloudCSS = DeployProviderType("tencentcloud-css")
+ DeployProviderTypeTencentCloudECDN = DeployProviderType("tencentcloud-ecdn")
+ DeployProviderTypeTencentCloudEO = DeployProviderType("tencentcloud-eo")
+ DeployProviderTypeTencentCloudSSLDeploy = DeployProviderType("tencentcloud-ssldeploy")
+ DeployProviderTypeUCloudUCDN = DeployProviderType("ucloud-ucdn")
+ DeployProviderTypeUCloudUS3 = DeployProviderType("ucloud-us3")
+ DeployProviderTypeVolcEngineCDN = DeployProviderType("volcengine-cdn")
+ DeployProviderTypeVolcEngineCLB = DeployProviderType("volcengine-clb")
+ DeployProviderTypeVolcEngineDCDN = DeployProviderType("volcengine-dcdn")
+ DeployProviderTypeVolcEngineLive = DeployProviderType("volcengine-live")
+ DeployProviderTypeVolcEngineTOS = DeployProviderType("volcengine-tos")
+ DeployProviderTypeWebhook = DeployProviderType("webhook")
)
diff --git a/internal/pkg/core/deployer/providers/aliyun-cas-deploy/aliyun_cas_deploy.go b/internal/pkg/core/deployer/providers/aliyun-cas-deploy/aliyun_cas_deploy.go
new file mode 100644
index 00000000..31dc66b8
--- /dev/null
+++ b/internal/pkg/core/deployer/providers/aliyun-cas-deploy/aliyun_cas_deploy.go
@@ -0,0 +1,187 @@
+package aliyuncasdeploy
+
+import (
+ "context"
+ "errors"
+ "fmt"
+ "strings"
+ "time"
+
+ aliyunCas "github.com/alibabacloud-go/cas-20200407/v3/client"
+ aliyunOpen "github.com/alibabacloud-go/darabonba-openapi/v2/client"
+ "github.com/alibabacloud-go/tea/tea"
+ xerrors "github.com/pkg/errors"
+
+ "github.com/usual2970/certimate/internal/pkg/core/deployer"
+ "github.com/usual2970/certimate/internal/pkg/core/logger"
+ "github.com/usual2970/certimate/internal/pkg/core/uploader"
+ uploaderp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/aliyun-cas"
+)
+
+type AliyunCASDeployDeployerConfig struct {
+ // 阿里云 AccessKeyId。
+ AccessKeyId string `json:"accessKeyId"`
+ // 阿里云 AccessKeySecret。
+ AccessKeySecret string `json:"accessKeySecret"`
+ // 阿里云地域。
+ Region string `json:"region"`
+ // 阿里云云产品资源 ID 数组。
+ ResourceIds []string `json:"resourceIds"`
+ // 阿里云云联系人 ID 数组。
+ // 零值时默认使用账号下第一个联系人。
+ ContactIds []string `json:"contactIds"`
+}
+
+type AliyunCASDeployDeployer struct {
+ config *AliyunCASDeployDeployerConfig
+ logger logger.Logger
+ sdkClient *aliyunCas.Client
+ sslUploader uploader.Uploader
+}
+
+var _ deployer.Deployer = (*AliyunCASDeployDeployer)(nil)
+
+func New(config *AliyunCASDeployDeployerConfig) (*AliyunCASDeployDeployer, error) {
+ return NewWithLogger(config, logger.NewNilLogger())
+}
+
+func NewWithLogger(config *AliyunCASDeployDeployerConfig, logger logger.Logger) (*AliyunCASDeployDeployer, error) {
+ if config == nil {
+ return nil, errors.New("config is nil")
+ }
+
+ if logger == nil {
+ return nil, errors.New("logger is nil")
+ }
+
+ client, err := createSdkClient(config.AccessKeyId, config.AccessKeySecret, config.Region)
+ if err != nil {
+ return nil, xerrors.Wrap(err, "failed to create sdk client")
+ }
+
+ uploader, err := createSslUploader(config.AccessKeyId, config.AccessKeySecret, config.Region)
+ if err != nil {
+ return nil, xerrors.Wrap(err, "failed to create ssl uploader")
+ }
+
+ return &AliyunCASDeployDeployer{
+ logger: logger,
+ config: config,
+ sdkClient: client,
+ sslUploader: uploader,
+ }, nil
+}
+
+func (d *AliyunCASDeployDeployer) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) {
+ if len(d.config.ResourceIds) == 0 {
+ return nil, errors.New("config `resourceIds` is required")
+ }
+
+ // 上传证书到 CAS
+ upres, err := d.sslUploader.Upload(ctx, certPem, privkeyPem)
+ if err != nil {
+ return nil, xerrors.Wrap(err, "failed to upload certificate file")
+ }
+
+ d.logger.Logt("certificate file uploaded", upres)
+
+ contactIds := d.config.ContactIds
+ if len(contactIds) == 0 {
+ // 获取联系人列表
+ // REF: https://help.aliyun.com/zh/ssl-certificate/developer-reference/api-cas-2020-04-07-listcontact
+ listContactReq := &aliyunCas.ListContactRequest{}
+ listContactReq.ShowSize = tea.Int32(1)
+ listContactReq.CurrentPage = tea.Int32(1)
+ listContactResp, err := d.sdkClient.ListContact(listContactReq)
+ if err != nil {
+ return nil, xerrors.Wrap(err, "failed to execute sdk request 'cas.ListContact'")
+ }
+
+ if len(listContactResp.Body.ContactList) > 0 {
+ contactIds = []string{fmt.Sprintf("%d", listContactResp.Body.ContactList[0].ContactId)}
+ }
+ }
+
+ // 创建部署任务
+ // REF: https://help.aliyun.com/zh/ssl-certificate/developer-reference/api-cas-2020-04-07-createdeploymentjob
+ createDeploymentJobReq := &aliyunCas.CreateDeploymentJobRequest{
+ Name: tea.String(fmt.Sprintf("certimate-%d", time.Now().UnixMilli())),
+ JobType: tea.String("user"),
+ CertIds: tea.String(upres.CertId),
+ ResourceIds: tea.String(strings.Join(d.config.ResourceIds, ",")),
+ ContactIds: tea.String(strings.Join(contactIds, ",")),
+ }
+ createDeploymentJobResp, err := d.sdkClient.CreateDeploymentJob(createDeploymentJobReq)
+ if err != nil {
+ return nil, xerrors.Wrap(err, "failed to execute sdk request 'cas.CreateDeploymentJob'")
+ }
+
+ d.logger.Logt("已创建部署任务", createDeploymentJobResp)
+
+ // 循环获取部署任务详情,等待任务状态变更
+ // REF: https://help.aliyun.com/zh/ssl-certificate/developer-reference/api-cas-2020-04-07-describedeploymentjob
+ for {
+ if ctx.Err() != nil {
+ return nil, ctx.Err()
+ }
+
+ describeDeploymentJobReq := &aliyunCas.DescribeDeploymentJobRequest{
+ JobId: createDeploymentJobResp.Body.JobId,
+ }
+ describeDeploymentJobResp, err := d.sdkClient.DescribeDeploymentJob(describeDeploymentJobReq)
+ if err != nil {
+ return nil, xerrors.Wrap(err, "failed to execute sdk request 'cas.DescribeDeploymentJob'")
+ }
+
+ if describeDeploymentJobResp.Body.Status == nil || *describeDeploymentJobResp.Body.Status == "editing" {
+ return nil, errors.New("部署任务状态异常")
+ }
+
+ if *describeDeploymentJobResp.Body.Status == "success" || *describeDeploymentJobResp.Body.Status == "error" {
+ d.logger.Logt("已获取部署任务详情", describeDeploymentJobResp)
+ break
+ }
+
+ d.logger.Logt("部署任务未完成 ...")
+ time.Sleep(time.Second * 5)
+ }
+
+ return &deployer.DeployResult{}, nil
+}
+
+func createSdkClient(accessKeyId, accessKeySecret, region string) (*aliyunCas.Client, error) {
+ if region == "" {
+ region = "cn-hangzhou" // CAS 服务默认区域:华东一杭州
+ }
+
+ // 接入点一览 https://help.aliyun.com/zh/ssl-certificate/developer-reference/endpoints
+ var endpoint string
+ switch region {
+ case "cn-hangzhou":
+ endpoint = "cas.aliyuncs.com"
+ default:
+ endpoint = fmt.Sprintf("cas.%s.aliyuncs.com", region)
+ }
+
+ config := &aliyunOpen.Config{
+ AccessKeyId: tea.String(accessKeyId),
+ AccessKeySecret: tea.String(accessKeySecret),
+ Endpoint: tea.String(endpoint),
+ }
+
+ client, err := aliyunCas.NewClient(config)
+ if err != nil {
+ return nil, err
+ }
+
+ return client, nil
+}
+
+func createSslUploader(accessKeyId, accessKeySecret, region string) (uploader.Uploader, error) {
+ uploader, err := uploaderp.New(&uploaderp.AliyunCASUploaderConfig{
+ AccessKeyId: accessKeyId,
+ AccessKeySecret: accessKeySecret,
+ Region: region,
+ })
+ return uploader, err
+}
diff --git a/internal/pkg/core/deployer/providers/aliyun-esa/aliyun_esa.go b/internal/pkg/core/deployer/providers/aliyun-esa/aliyun_esa.go
new file mode 100644
index 00000000..a09f8bbf
--- /dev/null
+++ b/internal/pkg/core/deployer/providers/aliyun-esa/aliyun_esa.go
@@ -0,0 +1,138 @@
+package aliyunesa
+
+import (
+ "context"
+ "errors"
+ "fmt"
+ "strconv"
+ "strings"
+
+ aliyunOpen "github.com/alibabacloud-go/darabonba-openapi/v2/client"
+ aliyunEsa "github.com/alibabacloud-go/esa-20240910/v2/client"
+ "github.com/alibabacloud-go/tea/tea"
+ xerrors "github.com/pkg/errors"
+
+ "github.com/usual2970/certimate/internal/pkg/core/deployer"
+ "github.com/usual2970/certimate/internal/pkg/core/logger"
+ "github.com/usual2970/certimate/internal/pkg/core/uploader"
+ uploaderp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/aliyun-cas"
+)
+
+type AliyunESADeployerConfig struct {
+ // 阿里云 AccessKeyId。
+ AccessKeyId string `json:"accessKeyId"`
+ // 阿里云 AccessKeySecret。
+ AccessKeySecret string `json:"accessKeySecret"`
+ // 阿里云地域。
+ Region string `json:"region"`
+ // 阿里云 ESA 站点 ID。
+ SiteId int64 `json:"siteId"`
+}
+
+type AliyunESADeployer struct {
+ config *AliyunESADeployerConfig
+ logger logger.Logger
+ sdkClient *aliyunEsa.Client
+ sslUploader uploader.Uploader
+}
+
+var _ deployer.Deployer = (*AliyunESADeployer)(nil)
+
+func New(config *AliyunESADeployerConfig) (*AliyunESADeployer, error) {
+ return NewWithLogger(config, logger.NewNilLogger())
+}
+
+func NewWithLogger(config *AliyunESADeployerConfig, logger logger.Logger) (*AliyunESADeployer, error) {
+ if config == nil {
+ return nil, errors.New("config is nil")
+ }
+
+ if logger == nil {
+ return nil, errors.New("logger is nil")
+ }
+
+ client, err := createSdkClient(config.AccessKeyId, config.AccessKeySecret, config.Region)
+ if err != nil {
+ return nil, xerrors.Wrap(err, "failed to create sdk client")
+ }
+
+ uploader, err := createSslUploader(config.AccessKeyId, config.AccessKeySecret, config.Region)
+ if err != nil {
+ return nil, xerrors.Wrap(err, "failed to create ssl uploader")
+ }
+
+ return &AliyunESADeployer{
+ logger: logger,
+ config: config,
+ sdkClient: client,
+ sslUploader: uploader,
+ }, nil
+}
+
+func (d *AliyunESADeployer) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) {
+ if d.config.SiteId == 0 {
+ return nil, errors.New("config `siteId` is required")
+ }
+
+ // 上传证书到 CAS
+ upres, err := d.sslUploader.Upload(ctx, certPem, privkeyPem)
+ if err != nil {
+ return nil, xerrors.Wrap(err, "failed to upload certificate file")
+ }
+
+ d.logger.Logt("certificate file uploaded", upres)
+
+ // 配置站点证书
+ // REF: https://help.aliyun.com/zh/edge-security-acceleration/esa/api-esa-2024-09-10-setcertificate
+ certId, _ := strconv.ParseInt(upres.CertId, 10, 64)
+ setCertificateReq := &aliyunEsa.SetCertificateRequest{
+ SiteId: tea.Int64(d.config.SiteId),
+ Type: tea.String("cas"),
+ CasId: tea.Int64(certId),
+ }
+ setCertificateResp, err := d.sdkClient.SetCertificate(setCertificateReq)
+ if err != nil {
+ return nil, xerrors.Wrap(err, "failed to execute sdk request 'esa.SetCertificate'")
+ }
+
+ d.logger.Logt("已配置站点证书", setCertificateResp)
+
+ return &deployer.DeployResult{}, nil
+}
+
+func createSdkClient(accessKeyId, accessKeySecret, region string) (*aliyunEsa.Client, error) {
+ // 接入点一览 https://help.aliyun.com/zh/edge-security-acceleration/esa/api-esa-2024-09-10-endpoint
+ config := &aliyunOpen.Config{
+ AccessKeyId: tea.String(accessKeyId),
+ AccessKeySecret: tea.String(accessKeySecret),
+ Endpoint: tea.String(fmt.Sprintf("esa.%s.aliyuncs.com", region)),
+ }
+
+ client, err := aliyunEsa.NewClient(config)
+ if err != nil {
+ return nil, err
+ }
+
+ return client, nil
+}
+
+func createSslUploader(accessKeyId, accessKeySecret, region string) (uploader.Uploader, error) {
+ casRegion := region
+ if casRegion != "" {
+ // 阿里云 CAS 服务接入点是独立于 ESA 服务的
+ // 国内版固定接入点:华东一杭州
+ // 国际版固定接入点:亚太东南一新加坡
+ if casRegion != "" && !strings.HasPrefix(casRegion, "cn-") {
+ casRegion = "ap-southeast-1"
+ } else {
+ casRegion = "cn-hangzhou"
+ }
+ }
+
+ uploader, err := uploaderp.New(&uploaderp.AliyunCASUploaderConfig{
+ AccessKeyId: accessKeyId,
+ AccessKeySecret: accessKeySecret,
+ Region: casRegion,
+ })
+ return uploader, err
+}
diff --git a/internal/pkg/core/deployer/providers/aliyun-esa/aliyun_esa_test.go b/internal/pkg/core/deployer/providers/aliyun-esa/aliyun_esa_test.go
new file mode 100644
index 00000000..980dc9a0
--- /dev/null
+++ b/internal/pkg/core/deployer/providers/aliyun-esa/aliyun_esa_test.go
@@ -0,0 +1,80 @@
+package aliyunesa_test
+
+import (
+ "context"
+ "flag"
+ "fmt"
+ "os"
+ "strings"
+ "testing"
+
+ provider "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/aliyun-esa"
+)
+
+var (
+ fInputCertPath string
+ fInputKeyPath string
+ fAccessKeyId string
+ fAccessKeySecret string
+ fRegion string
+ fSiteId int64
+)
+
+func init() {
+ argsPrefix := "CERTIMATE_DEPLOYER_ALIYUNESA_"
+
+ flag.StringVar(&fInputCertPath, argsPrefix+"INPUTCERTPATH", "", "")
+ flag.StringVar(&fInputKeyPath, argsPrefix+"INPUTKEYPATH", "", "")
+ flag.StringVar(&fAccessKeyId, argsPrefix+"ACCESSKEYID", "", "")
+ flag.StringVar(&fAccessKeySecret, argsPrefix+"ACCESSKEYSECRET", "", "")
+ flag.StringVar(&fRegion, argsPrefix+"REGION", "", "")
+ flag.Int64Var(&fSiteId, argsPrefix+"SITEID", "", "")
+}
+
+/*
+Shell command to run this test:
+
+ go test -v ./aliyun_esa_test.go -args \
+ --CERTIMATE_DEPLOYER_ALIYUNESA_INPUTCERTPATH="/path/to/your-input-cert.pem" \
+ --CERTIMATE_DEPLOYER_ALIYUNESA_INPUTKEYPATH="/path/to/your-input-key.pem" \
+ --CERTIMATE_DEPLOYER_ALIYUNESA_ACCESSKEYID="your-access-key-id" \
+ --CERTIMATE_DEPLOYER_ALIYUNESA_ACCESSKEYSECRET="your-access-key-secret" \
+ --CERTIMATE_DEPLOYER_ALIYUNOSS_REGION="cn-hangzhou" \
+ --CERTIMATE_DEPLOYER_ALIYUNESA_SITEID="your-esa-site-id"
+*/
+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("ACCESSKEYSECRET: %v", fAccessKeySecret),
+ fmt.Sprintf("REGION: %v", fRegion),
+ fmt.Sprintf("SITEID: %v", fSiteId),
+ }, "\n"))
+
+ deployer, err := provider.New(&provider.AliyunESADeployerConfig{
+ AccessKeyId: fAccessKeyId,
+ AccessKeySecret: fAccessKeySecret,
+ Region: fRegion,
+ SiteId: fSiteId,
+ })
+ 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/deployer/providers/aliyun-waf/aliyun_waf.go b/internal/pkg/core/deployer/providers/aliyun-waf/aliyun_waf.go
index 75c634b8..1cc7aecd 100644
--- a/internal/pkg/core/deployer/providers/aliyun-waf/aliyun_waf.go
+++ b/internal/pkg/core/deployer/providers/aliyun-waf/aliyun_waf.go
@@ -114,6 +114,7 @@ func (d *AliyunWAFDeployer) Deploy(ctx context.Context, certPem string, privkeyP
}
func createSdkClient(accessKeyId, accessKeySecret, region string) (*aliyunWaf.Client, error) {
+ // 接入点一览:https://help.aliyun.com/zh/waf/web-application-firewall-3-0/developer-reference/api-waf-openapi-2021-10-01-endpoint
config := &aliyunOpen.Config{
AccessKeyId: tea.String(accessKeyId),
AccessKeySecret: tea.String(accessKeySecret),
diff --git a/internal/pkg/core/deployer/providers/baotapanel-site/baotapanel-site.go b/internal/pkg/core/deployer/providers/baotapanel-site/baotapanel-site.go
new file mode 100644
index 00000000..336e2a5d
--- /dev/null
+++ b/internal/pkg/core/deployer/providers/baotapanel-site/baotapanel-site.go
@@ -0,0 +1,81 @@
+package baotapanelsite
+
+import (
+ "context"
+ "errors"
+
+ xerrors "github.com/pkg/errors"
+
+ "github.com/usual2970/certimate/internal/pkg/core/deployer"
+ "github.com/usual2970/certimate/internal/pkg/core/logger"
+ btsdk "github.com/usual2970/certimate/internal/pkg/vendors/btpanel-sdk"
+)
+
+type BaotaPanelSiteDeployerConfig struct {
+ // 宝塔面板地址。
+ ApiUrl string `json:"apiUrl"`
+ // 宝塔面板接口密钥。
+ ApiKey string `json:"apiKey"`
+ // 站点名称
+ SiteName string `json:"siteName"`
+}
+
+type BaotaPanelSiteDeployer struct {
+ config *BaotaPanelSiteDeployerConfig
+ logger logger.Logger
+ sdkClient *btsdk.BaoTaPanelClient
+}
+
+var _ deployer.Deployer = (*BaotaPanelSiteDeployer)(nil)
+
+func New(config *BaotaPanelSiteDeployerConfig) (*BaotaPanelSiteDeployer, error) {
+ return NewWithLogger(config, logger.NewNilLogger())
+}
+
+func NewWithLogger(config *BaotaPanelSiteDeployerConfig, logger logger.Logger) (*BaotaPanelSiteDeployer, error) {
+ if config == nil {
+ return nil, errors.New("config is nil")
+ }
+
+ if logger == nil {
+ return nil, errors.New("logger is nil")
+ }
+
+ client, err := createSdkClient(config.ApiUrl, config.ApiKey)
+ if err != nil {
+ return nil, xerrors.Wrap(err, "failed to create sdk client")
+ }
+
+ return &BaotaPanelSiteDeployer{
+ logger: logger,
+ config: config,
+ sdkClient: client,
+ }, nil
+}
+
+func (d *BaotaPanelSiteDeployer) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) {
+ if d.config.SiteName == "" {
+ return nil, errors.New("config `siteName` is required")
+ }
+
+ // 设置站点 SSL 证书
+ setSiteSSLReq := &btsdk.SetSiteSSLRequest{
+ SiteName: d.config.SiteName,
+ Type: "1",
+ Key: privkeyPem,
+ Csr: certPem,
+ }
+ setSiteSSLResp, err := d.sdkClient.SetSiteSSL(setSiteSSLReq)
+ if err != nil {
+ return nil, xerrors.Wrap(err, "failed to execute sdk request 'bt.SetSiteSSL'")
+ }
+
+ d.logger.Logt("已设置站点 SSL 证书", setSiteSSLResp)
+
+ return &deployer.DeployResult{}, nil
+}
+
+func createSdkClient(apiUrl, apiKey string) (*btsdk.BaoTaPanelClient, error) {
+ client := btsdk.NewBaoTaPanelClient(apiUrl, apiKey)
+ return client, nil
+}
diff --git a/internal/pkg/core/deployer/providers/baotapanel-site/baotapanel-site_test.go b/internal/pkg/core/deployer/providers/baotapanel-site/baotapanel-site_test.go
new file mode 100644
index 00000000..486e8428
--- /dev/null
+++ b/internal/pkg/core/deployer/providers/baotapanel-site/baotapanel-site_test.go
@@ -0,0 +1,75 @@
+package baotapanelsite_test
+
+import (
+ "context"
+ "flag"
+ "fmt"
+ "os"
+ "strings"
+ "testing"
+
+ provider "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/baotapanel-site"
+)
+
+var (
+ fInputCertPath string
+ fInputKeyPath string
+ fApiUrl string
+ fApiKey string
+ fSiteName string
+)
+
+func init() {
+ argsPrefix := "CERTIMATE_DEPLOYER_BAOTAPANELSITE_"
+
+ flag.StringVar(&fInputCertPath, argsPrefix+"INPUTCERTPATH", "", "")
+ flag.StringVar(&fInputKeyPath, argsPrefix+"INPUTKEYPATH", "", "")
+ flag.StringVar(&fApiUrl, argsPrefix+"APIURL", "", "")
+ flag.StringVar(&fApiKey, argsPrefix+"APIKEY", "", "")
+ flag.StringVar(&fSiteName, argsPrefix+"SITENAME", "", "")
+}
+
+/*
+Shell command to run this test:
+
+ go test -v ./baotapanel_site_test.go -args \
+ --CERTIMATE_DEPLOYER_BAOTAPANELSITE_INPUTCERTPATH="/path/to/your-input-cert.pem" \
+ --CERTIMATE_DEPLOYER_BAOTAPANELSITE_INPUTKEYPATH="/path/to/your-input-key.pem" \
+ --CERTIMATE_DEPLOYER_BAOTAPANELSITE_APIURL="your-baota-panel-url" \
+ --CERTIMATE_DEPLOYER_BAOTAPANELSITE_APIKEY="your-baota-panel-key" \
+ --CERTIMATE_DEPLOYER_BAOTAPANELSITE_SITENAME="your-baota-site-name"
+*/
+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("APIURL: %v", fApiUrl),
+ fmt.Sprintf("APIKEY: %v", fApiKey),
+ fmt.Sprintf("SITENAME: %v", fSiteName),
+ }, "\n"))
+
+ deployer, err := provider.New(&provider.BaotaPanelSiteDeployerConfig{
+ ApiUrl: fApiUrl,
+ ApiKey: fApiKey,
+ SiteName: fSiteName,
+ })
+ 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/deployer/providers/tencentcloud-clb/defines.go b/internal/pkg/core/deployer/providers/tencentcloud-clb/defines.go
index 47eedfb0..7e7eace9 100644
--- a/internal/pkg/core/deployer/providers/tencentcloud-clb/defines.go
+++ b/internal/pkg/core/deployer/providers/tencentcloud-clb/defines.go
@@ -4,7 +4,7 @@ type DeployResourceType string
const (
// 资源类型:通过 SSL 服务部署到云资源实例。
- DEPLOY_RESOURCE_USE_SSLDEPLOY = DeployResourceType("ssl-deploy")
+ DEPLOY_RESOURCE_VIA_SSLDEPLOY = DeployResourceType("ssl-deploy")
// 资源类型:部署到指定负载均衡器。
DEPLOY_RESOURCE_LOADBALANCER = DeployResourceType("loadbalancer")
// 资源类型:部署到指定监听器。
diff --git a/internal/pkg/core/deployer/providers/tencentcloud-clb/tencentcloud_clb.go b/internal/pkg/core/deployer/providers/tencentcloud-clb/tencentcloud_clb.go
index d67eb383..e6982817 100644
--- a/internal/pkg/core/deployer/providers/tencentcloud-clb/tencentcloud_clb.go
+++ b/internal/pkg/core/deployer/providers/tencentcloud-clb/tencentcloud_clb.go
@@ -96,8 +96,8 @@ func (d *TencentCloudCLBDeployer) Deploy(ctx context.Context, certPem string, pr
// 根据部署资源类型决定部署方式
switch d.config.ResourceType {
- case DEPLOY_RESOURCE_USE_SSLDEPLOY:
- if err := d.deployToInstanceUseSsl(ctx, upres.CertId); err != nil {
+ case DEPLOY_RESOURCE_VIA_SSLDEPLOY:
+ if err := d.deployViaSslService(ctx, upres.CertId); err != nil {
return nil, err
}
@@ -123,7 +123,7 @@ func (d *TencentCloudCLBDeployer) Deploy(ctx context.Context, certPem string, pr
return &deployer.DeployResult{}, nil
}
-func (d *TencentCloudCLBDeployer) deployToInstanceUseSsl(ctx context.Context, cloudCertId string) error {
+func (d *TencentCloudCLBDeployer) deployViaSslService(ctx context.Context, cloudCertId string) error {
if d.config.LoadbalancerId == "" {
return errors.New("config `loadbalancerId` is required")
}
diff --git a/internal/pkg/core/deployer/providers/tencentcloud-clb/tencentcloud_clb_test.go b/internal/pkg/core/deployer/providers/tencentcloud-clb/tencentcloud_clb_test.go
index 0af11dff..74a1e23e 100644
--- a/internal/pkg/core/deployer/providers/tencentcloud-clb/tencentcloud_clb_test.go
+++ b/internal/pkg/core/deployer/providers/tencentcloud-clb/tencentcloud_clb_test.go
@@ -68,7 +68,7 @@ func TestDeploy(t *testing.T) {
SecretId: fSecretId,
SecretKey: fSecretKey,
Region: fRegion,
- ResourceType: provider.DEPLOY_RESOURCE_USE_SSLDEPLOY,
+ ResourceType: provider.DEPLOY_RESOURCE_VIA_SSLDEPLOY,
LoadbalancerId: fLoadbalancerId,
ListenerId: fListenerId,
Domain: fDomain,
diff --git a/internal/pkg/core/deployer/providers/tencentcloud-ssl-deploy/tencentcloud_ssl_deploy.go b/internal/pkg/core/deployer/providers/tencentcloud-ssl-deploy/tencentcloud_ssl_deploy.go
new file mode 100644
index 00000000..37c00ea4
--- /dev/null
+++ b/internal/pkg/core/deployer/providers/tencentcloud-ssl-deploy/tencentcloud_ssl_deploy.go
@@ -0,0 +1,156 @@
+package tencentcloudssldeploy
+
+import (
+ "context"
+ "errors"
+ "fmt"
+ "time"
+
+ xerrors "github.com/pkg/errors"
+ "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common"
+ "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common/profile"
+ tcSsl "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/ssl/v20191205"
+
+ "github.com/usual2970/certimate/internal/pkg/core/deployer"
+ "github.com/usual2970/certimate/internal/pkg/core/logger"
+ "github.com/usual2970/certimate/internal/pkg/core/uploader"
+ uploaderp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/tencentcloud-ssl"
+)
+
+type TencentCloudSSLDeployDeployerConfig struct {
+ // 腾讯云 SecretId。
+ SecretId string `json:"secretId"`
+ // 腾讯云 SecretKey。
+ SecretKey string `json:"secretKey"`
+ // 腾讯云地域。
+ Region string `json:"region"`
+ // 腾讯云云资源类型。
+ ResourceType string `json:"resourceType"`
+ // 腾讯云云资源 ID 数组。
+ ResourceIds []string `json:"resourceIds"`
+}
+
+type TencentCloudSSLDeployDeployer struct {
+ config *TencentCloudSSLDeployDeployerConfig
+ logger logger.Logger
+ sdkClient *tcSsl.Client
+ sslUploader uploader.Uploader
+}
+
+var _ deployer.Deployer = (*TencentCloudSSLDeployDeployer)(nil)
+
+func New(config *TencentCloudSSLDeployDeployerConfig) (*TencentCloudSSLDeployDeployer, error) {
+ return NewWithLogger(config, logger.NewNilLogger())
+}
+
+func NewWithLogger(config *TencentCloudSSLDeployDeployerConfig, logger logger.Logger) (*TencentCloudSSLDeployDeployer, error) {
+ if config == nil {
+ return nil, errors.New("config is nil")
+ }
+
+ if logger == nil {
+ return nil, errors.New("logger is nil")
+ }
+
+ client, err := createSdkClient(config.SecretId, config.SecretKey, config.Region)
+ if err != nil {
+ return nil, xerrors.Wrap(err, "failed to create sdk client")
+ }
+
+ uploader, err := uploaderp.New(&uploaderp.TencentCloudSSLUploaderConfig{
+ SecretId: config.SecretId,
+ SecretKey: config.SecretKey,
+ })
+ if err != nil {
+ return nil, xerrors.Wrap(err, "failed to create ssl uploader")
+ }
+
+ return &TencentCloudSSLDeployDeployer{
+ logger: logger,
+ config: config,
+ sdkClient: client,
+ sslUploader: uploader,
+ }, nil
+}
+
+func (d *TencentCloudSSLDeployDeployer) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) {
+ if d.config.ResourceType == "" {
+ return nil, errors.New("config `resourceType` is required")
+ }
+ if len(d.config.ResourceIds) == 0 {
+ return nil, errors.New("config `resourceIds` is required")
+ }
+
+ // 上传证书到 SSL
+ upres, err := d.sslUploader.Upload(ctx, certPem, privkeyPem)
+ if err != nil {
+ return nil, xerrors.Wrap(err, "failed to upload certificate file")
+ }
+
+ d.logger.Logt("certificate file uploaded", upres)
+
+ // 证书部署到云资源实例列表
+ // REF: https://cloud.tencent.com/document/product/400/91667
+ deployCertificateInstanceReq := tcSsl.NewDeployCertificateInstanceRequest()
+ deployCertificateInstanceReq.CertificateId = common.StringPtr(upres.CertId)
+ deployCertificateInstanceReq.ResourceType = common.StringPtr(d.config.ResourceType)
+ deployCertificateInstanceReq.InstanceIdList = common.StringPtrs(d.config.ResourceIds)
+ deployCertificateInstanceReq.Status = common.Int64Ptr(1)
+ deployCertificateInstanceResp, err := d.sdkClient.DeployCertificateInstance(deployCertificateInstanceReq)
+ if err != nil {
+ return nil, xerrors.Wrap(err, "failed to execute sdk request 'ssl.DeployCertificateInstance'")
+ } else if deployCertificateInstanceResp.Response == nil || deployCertificateInstanceResp.Response.DeployRecordId == nil {
+ return nil, errors.New("failed to create deploy record")
+ }
+
+ d.logger.Logt("已部署证书到云资源实例", deployCertificateInstanceResp.Response)
+
+ // 循环获取部署任务详情,等待任务状态变更
+ // REF: https://cloud.tencent.com.cn/document/api/400/91658
+ for {
+ if ctx.Err() != nil {
+ return nil, ctx.Err()
+ }
+
+ describeHostDeployRecordDetailReq := tcSsl.NewDescribeHostDeployRecordDetailRequest()
+ describeHostDeployRecordDetailReq.DeployRecordId = common.StringPtr(fmt.Sprintf("%d", *deployCertificateInstanceResp.Response.DeployRecordId))
+ describeHostDeployRecordDetailReq.Limit = common.Uint64Ptr(100)
+ describeHostDeployRecordDetailResp, err := d.sdkClient.DescribeHostDeployRecordDetail(describeHostDeployRecordDetailReq)
+ if err != nil {
+ return nil, xerrors.Wrap(err, "failed to execute sdk request 'ssl.DescribeHostDeployRecordDetail'")
+ }
+
+ if describeHostDeployRecordDetailResp.Response.TotalCount == nil {
+ return nil, errors.New("部署任务状态异常")
+ } else {
+ acc := int64(0)
+ if describeHostDeployRecordDetailResp.Response.SuccessTotalCount != nil {
+ acc += *describeHostDeployRecordDetailResp.Response.SuccessTotalCount
+ }
+ if describeHostDeployRecordDetailResp.Response.FailedTotalCount != nil {
+ acc += *describeHostDeployRecordDetailResp.Response.FailedTotalCount
+ }
+
+ if acc == *describeHostDeployRecordDetailResp.Response.TotalCount {
+ d.logger.Logt("已获取部署任务详情", describeHostDeployRecordDetailResp)
+ break
+ }
+ }
+
+ d.logger.Logt("部署任务未完成 ...")
+ time.Sleep(time.Second * 5)
+ }
+
+ return &deployer.DeployResult{}, nil
+}
+
+func createSdkClient(secretId, secretKey, region string) (*tcSsl.Client, error) {
+ credential := common.NewCredential(secretId, secretKey)
+
+ client, err := tcSsl.NewClient(credential, region, profile.NewClientProfile())
+ if err != nil {
+ return nil, err
+ }
+
+ return client, nil
+}
diff --git a/internal/pkg/vendors/btpanel-sdk/api.go b/internal/pkg/vendors/btpanel-sdk/api.go
new file mode 100644
index 00000000..5c58e3df
--- /dev/null
+++ b/internal/pkg/vendors/btpanel-sdk/api.go
@@ -0,0 +1,26 @@
+package btpanelsdk
+
+type BaseResponse interface {
+ GetStatus() *bool
+ GetMsg() *string
+}
+
+type SetSiteSSLRequest struct {
+ Type string `json:"type"`
+ SiteName string `json:"siteName"`
+ Key string `json:"key"`
+ Csr string `json:"csr"`
+}
+
+type SetSiteSSLResponse struct {
+ Status *bool `json:"status,omitempty"`
+ Msg *string `json:"msg,omitempty"`
+}
+
+func (r *SetSiteSSLResponse) GetStatus() *bool {
+ return r.Status
+}
+
+func (r *SetSiteSSLResponse) GetMsg() *string {
+ return r.Msg
+}
diff --git a/internal/pkg/vendors/btpanel-sdk/client.go b/internal/pkg/vendors/btpanel-sdk/client.go
new file mode 100644
index 00000000..43e3d415
--- /dev/null
+++ b/internal/pkg/vendors/btpanel-sdk/client.go
@@ -0,0 +1,107 @@
+package btpanelsdk
+
+import (
+ "crypto/md5"
+ "encoding/hex"
+ "encoding/json"
+ "fmt"
+ "strings"
+ "time"
+
+ "github.com/go-resty/resty/v2"
+
+ "github.com/usual2970/certimate/internal/pkg/utils/maps"
+)
+
+type BaoTaPanelClient struct {
+ apiHost string
+ apiKey string
+ client *resty.Client
+}
+
+func NewBaoTaPanelClient(apiHost, apiKey string) *BaoTaPanelClient {
+ client := resty.New()
+
+ return &BaoTaPanelClient{
+ apiHost: apiHost,
+ apiKey: apiKey,
+ client: client,
+ }
+}
+
+func (c *BaoTaPanelClient) WithTimeout(timeout time.Duration) *BaoTaPanelClient {
+ c.client.SetTimeout(timeout)
+ return c
+}
+
+func (c *BaoTaPanelClient) SetSiteSSL(req *SetSiteSSLRequest) (*SetSiteSSLResponse, error) {
+ params := make(map[string]any)
+ jsonData, _ := json.Marshal(req)
+ json.Unmarshal(jsonData, ¶ms)
+
+ result := SetSiteSSLResponse{}
+ err := c.sendRequestWithResult("/site?action=SetSSL", params, &result)
+ if err != nil {
+ return nil, err
+ }
+ return &result, nil
+}
+
+func (c *BaoTaPanelClient) generateSignature(timestamp string) string {
+ keyMd5 := md5.Sum([]byte(c.apiKey))
+ keyMd5Hex := strings.ToLower(hex.EncodeToString(keyMd5[:]))
+
+ signMd5 := md5.Sum([]byte(timestamp + keyMd5Hex))
+ signMd5Hex := strings.ToLower(hex.EncodeToString(signMd5[:]))
+ return signMd5Hex
+}
+
+func (c *BaoTaPanelClient) sendRequest(path string, params map[string]any) (*resty.Response, error) {
+ if params == nil {
+ params = make(map[string]any)
+ }
+
+ timestamp := time.Now().Unix()
+ params["request_time"] = timestamp
+ params["request_token"] = c.generateSignature(fmt.Sprintf("%d", timestamp))
+
+ url := strings.TrimRight(c.apiHost, "/") + path
+ req := c.client.R().
+ SetHeader("Content-Type", "application/json").
+ SetBody(params)
+ resp, err := req.Post(url)
+ if err != nil {
+ return nil, fmt.Errorf("baota: failed to send request: %w", err)
+ }
+
+ if resp.IsError() {
+ return nil, fmt.Errorf("baota: unexpected status code: %d, %s", resp.StatusCode(), resp.Body())
+ }
+
+ return resp, nil
+}
+
+func (c *BaoTaPanelClient) sendRequestWithResult(path string, params map[string]any, result BaseResponse) error {
+ resp, err := c.sendRequest(path, params)
+ if err != nil {
+ return err
+ }
+
+ jsonResp := make(map[string]any)
+ if err := json.Unmarshal(resp.Body(), &jsonResp); err != nil {
+ return fmt.Errorf("baota: failed to parse response: %w", err)
+ }
+ if err := maps.Decode(jsonResp, &result); err != nil {
+ return fmt.Errorf("baota: failed to parse response: %w", err)
+ }
+
+ if result.GetStatus() != nil && !*result.GetStatus() {
+ if result.GetMsg() == nil {
+ return fmt.Errorf("baota api error: unknown error")
+ } else {
+ return fmt.Errorf("baota api error: %s", result.GetMsg())
+ }
+ }
+
+ return nil
+}
diff --git a/internal/pkg/vendors/gname-sdk/client.go b/internal/pkg/vendors/gname-sdk/client.go
index 507555e9..6bf4e2db 100644
--- a/internal/pkg/vendors/gname-sdk/client.go
+++ b/internal/pkg/vendors/gname-sdk/client.go
@@ -130,11 +130,11 @@ func (c *GnameClient) sendRequest(path string, params map[string]any) (*resty.Re
SetFormData(data)
resp, err := req.Post(url)
if err != nil {
- return nil, fmt.Errorf("failed to send request: %w", err)
+ return nil, fmt.Errorf("gname: failed to send request: %w", err)
}
if resp.IsError() {
- return nil, fmt.Errorf("unexpected status code: %d, %s", resp.StatusCode(), resp.Body())
+ return nil, fmt.Errorf("gname: unexpected status code: %d, %s", resp.StatusCode(), resp.Body())
}
return resp, nil
@@ -148,14 +148,14 @@ func (c *GnameClient) sendRequestWithResult(path string, params map[string]any,
jsonResp := make(map[string]any)
if err := json.Unmarshal(resp.Body(), &jsonResp); err != nil {
- return fmt.Errorf("failed to parse response: %w", err)
+ return fmt.Errorf("gname: failed to parse response: %w", err)
}
- if err := maps.Populate(jsonResp, &result); err != nil {
- return fmt.Errorf("failed to parse response: %w", err)
+ if err := maps.Decode(jsonResp, &result); err != nil {
+ return fmt.Errorf("gname: failed to parse response: %w", err)
}
if result.GetCode() != 1 {
- return fmt.Errorf("API error: %s", result.GetMsg())
+ return fmt.Errorf("gname api error: %s", result.GetMsg())
}
return nil
diff --git a/migrations/1739202463_updated_access.go b/migrations/1739202463_updated_access.go
new file mode 100644
index 00000000..ccaffbce
--- /dev/null
+++ b/migrations/1739202463_updated_access.go
@@ -0,0 +1,99 @@
+package migrations
+
+import (
+ "github.com/pocketbase/pocketbase/core"
+ m "github.com/pocketbase/pocketbase/migrations"
+)
+
+func init() {
+ m.Register(func(app core.App) error {
+ collection, err := app.FindCollectionByNameOrId("4yzbv8urny5ja1e")
+ if err != nil {
+ return err
+ }
+
+ // update field
+ if err := collection.Fields.AddMarshaledJSONAt(2, []byte(`{
+ "hidden": false,
+ "id": "hwy7m03o",
+ "maxSelect": 1,
+ "name": "provider",
+ "presentable": false,
+ "required": false,
+ "system": false,
+ "type": "select",
+ "values": [
+ "acmehttpreq",
+ "aliyun",
+ "aws",
+ "azure",
+ "baiducloud",
+ "baotapanel",
+ "byteplus",
+ "cloudflare",
+ "dogecloud",
+ "godaddy",
+ "huaweicloud",
+ "k8s",
+ "local",
+ "namedotcom",
+ "namesilo",
+ "powerdns",
+ "qiniu",
+ "ssh",
+ "tencentcloud",
+ "ucloud",
+ "volcengine",
+ "webhook"
+ ]
+ }`)); err != nil {
+ return err
+ }
+
+ return app.Save(collection)
+ }, func(app core.App) error {
+ collection, err := app.FindCollectionByNameOrId("4yzbv8urny5ja1e")
+ if err != nil {
+ return err
+ }
+
+ // update field
+ if err := collection.Fields.AddMarshaledJSONAt(2, []byte(`{
+ "hidden": false,
+ "id": "hwy7m03o",
+ "maxSelect": 1,
+ "name": "provider",
+ "presentable": false,
+ "required": false,
+ "system": false,
+ "type": "select",
+ "values": [
+ "acmehttpreq",
+ "aliyun",
+ "aws",
+ "azure",
+ "baiducloud",
+ "byteplus",
+ "cloudflare",
+ "dogecloud",
+ "godaddy",
+ "huaweicloud",
+ "k8s",
+ "local",
+ "namedotcom",
+ "namesilo",
+ "powerdns",
+ "qiniu",
+ "ssh",
+ "tencentcloud",
+ "ucloud",
+ "volcengine",
+ "webhook"
+ ]
+ }`)); err != nil {
+ return err
+ }
+
+ return app.Save(collection)
+ })
+}
diff --git a/ui/public/imgs/providers/baotapanel.svg b/ui/public/imgs/providers/baotapanel.svg
new file mode 100644
index 00000000..34ab8ec8
--- /dev/null
+++ b/ui/public/imgs/providers/baotapanel.svg
@@ -0,0 +1 @@
+
diff --git a/ui/src/components/access/AccessForm.tsx b/ui/src/components/access/AccessForm.tsx
index c6c44d2d..d9632f28 100644
--- a/ui/src/components/access/AccessForm.tsx
+++ b/ui/src/components/access/AccessForm.tsx
@@ -14,6 +14,7 @@ import AccessFormAliyunConfig from "./AccessFormAliyunConfig";
import AccessFormAWSConfig from "./AccessFormAWSConfig";
import AccessFormAzureConfig from "./AccessFormAzureConfig";
import AccessFormBaiduCloudConfig from "./AccessFormBaiduCloudConfig";
+import AccessFormBaotaPanelConfig from "./AccessFormBaotaPanelConfig";
import AccessFormBytePlusConfig from "./AccessFormBytePlusConfig";
import AccessFormCloudflareConfig from "./AccessFormCloudflareConfig";
import AccessFormClouDNSConfig from "./AccessFormClouDNSConfig";
@@ -99,6 +100,8 @@ const AccessForm = forwardRef(({ className,
return ;
case ACCESS_PROVIDERS.BAIDUCLOUD:
return ;
+ case ACCESS_PROVIDERS.BAOTAPANEL:
+ return ;
case ACCESS_PROVIDERS.BYTEPLUS:
return ;
case ACCESS_PROVIDERS.CLOUDFLARE:
diff --git a/ui/src/components/access/AccessFormBaotaPanelConfig.tsx b/ui/src/components/access/AccessFormBaotaPanelConfig.tsx
new file mode 100644
index 00000000..4f619c1c
--- /dev/null
+++ b/ui/src/components/access/AccessFormBaotaPanelConfig.tsx
@@ -0,0 +1,72 @@
+import { useTranslation } from "react-i18next";
+import { Form, type FormInstance, Input } from "antd";
+import { createSchemaFieldRule } from "antd-zod";
+import { z } from "zod";
+
+import { type AccessConfigForBaotaPanel } from "@/domain/access";
+
+type AccessFormBaotaPanelConfigFieldValues = Nullish;
+
+export type AccessFormBaotaPanelConfigProps = {
+ form: FormInstance;
+ formName: string;
+ disabled?: boolean;
+ initialValues?: AccessFormBaotaPanelConfigFieldValues;
+ onValuesChange?: (values: AccessFormBaotaPanelConfigFieldValues) => void;
+};
+
+const initFormModel = (): AccessFormBaotaPanelConfigFieldValues => {
+ return {
+ apiUrl: "",
+ apiKey: "",
+ };
+};
+
+const AccessFormBaotaPanelConfig = ({ form: formInst, formName, disabled, initialValues, onValuesChange }: AccessFormBaotaPanelConfigProps) => {
+ const { t } = useTranslation();
+
+ const formSchema = z.object({
+ apiUrl: z.string().url(t("common.errmsg.url_invalid")),
+ apiKey: z
+ .string()
+ .min(1, t("access.form.baotapanel_api_key.placeholder"))
+ .max(64, t("common.errmsg.string_max", { max: 64 }))
+ .trim(),
+ });
+ const formRule = createSchemaFieldRule(formSchema);
+
+ const handleFormChange = (_: unknown, values: z.infer) => {
+ onValuesChange?.(values);
+ };
+
+ return (
+ }
+ >
+
+
+
+ }
+ >
+
+
+
+ );
+};
+
+export default AccessFormBaotaPanelConfig;
diff --git a/ui/src/components/provider/ApplyDNSProviderPicker.tsx b/ui/src/components/provider/ApplyDNSProviderPicker.tsx
index f297716f..10fa39ff 100644
--- a/ui/src/components/provider/ApplyDNSProviderPicker.tsx
+++ b/ui/src/components/provider/ApplyDNSProviderPicker.tsx
@@ -1,6 +1,6 @@
-import { memo, useState } from "react";
+import { memo, useEffect, useRef, useState } from "react";
import { useTranslation } from "react-i18next";
-import { Avatar, Card, Col, Empty, Flex, Input, Row, Typography } from "antd";
+import { Avatar, Card, Col, Empty, Flex, Input, type InputRef, Row, Typography } from "antd";
import Show from "@/components/Show";
import { applyDNSProvidersMap } from "@/domain/provider";
@@ -8,20 +8,27 @@ import { applyDNSProvidersMap } from "@/domain/provider";
export type ApplyDNSProviderPickerProps = {
className?: string;
style?: React.CSSProperties;
+ autoFocus?: boolean;
placeholder?: string;
onSelect?: (value: string) => void;
};
-const ApplyDNSProviderPicker = ({ className, style, placeholder, onSelect }: ApplyDNSProviderPickerProps) => {
+const ApplyDNSProviderPicker = ({ className, style, autoFocus, placeholder, onSelect }: ApplyDNSProviderPickerProps) => {
const { t } = useTranslation();
const [keyword, setKeyword] = useState();
+ const keywordInputRef = useRef(null);
+ useEffect(() => {
+ if (autoFocus) {
+ setTimeout(() => keywordInputRef.current?.focus(), 1);
+ }
+ }, []);
const providers = Array.from(applyDNSProvidersMap.values());
const filteredProviders = providers.filter((provider) => {
if (keyword) {
const value = keyword.toLowerCase();
- return provider.type.toLowerCase().includes(value) || provider.name.toLowerCase().includes(value);
+ return provider.type.toLowerCase().includes(value) || t(provider.name).toLowerCase().includes(value);
}
return true;
@@ -33,7 +40,7 @@ const ApplyDNSProviderPicker = ({ className, style, placeholder, onSelect }: App
return (
-
setKeyword(e.target.value.trim())} />
+ setKeyword(e.target.value.trim())} />
0} fallback={}>
diff --git a/ui/src/components/provider/DeployProviderPicker.tsx b/ui/src/components/provider/DeployProviderPicker.tsx
index 537638bf..c90debb5 100644
--- a/ui/src/components/provider/DeployProviderPicker.tsx
+++ b/ui/src/components/provider/DeployProviderPicker.tsx
@@ -1,6 +1,6 @@
-import { memo, useState } from "react";
+import { memo, useEffect, useRef, useState } from "react";
import { useTranslation } from "react-i18next";
-import { Avatar, Card, Col, Empty, Flex, Input, Row, Typography } from "antd";
+import { Avatar, Card, Col, Empty, Flex, Input, type InputRef, Row, Typography } from "antd";
import Show from "@/components/Show";
import { deployProvidersMap } from "@/domain/provider";
@@ -8,20 +8,27 @@ import { deployProvidersMap } from "@/domain/provider";
export type DeployProviderPickerProps = {
className?: string;
style?: React.CSSProperties;
+ autoFocus?: boolean;
placeholder?: string;
onSelect?: (value: string) => void;
};
-const DeployProviderPicker = ({ className, style, placeholder, onSelect }: DeployProviderPickerProps) => {
+const DeployProviderPicker = ({ className, style, autoFocus, placeholder, onSelect }: DeployProviderPickerProps) => {
const { t } = useTranslation();
const [keyword, setKeyword] = useState();
+ const keywordInputRef = useRef(null);
+ useEffect(() => {
+ if (autoFocus) {
+ setTimeout(() => keywordInputRef.current?.focus(), 1);
+ }
+ }, []);
const providers = Array.from(deployProvidersMap.values());
const filteredProviders = providers.filter((provider) => {
if (keyword) {
const value = keyword.toLowerCase();
- return provider.type.toLowerCase().includes(value) || provider.name.toLowerCase().includes(value);
+ return provider.type.toLowerCase().includes(value) || t(provider.name).toLowerCase().includes(value);
}
return true;
@@ -33,7 +40,7 @@ const DeployProviderPicker = ({ className, style, placeholder, onSelect }: Deplo
return (
-
setKeyword(e.target.value.trim())} />
+ setKeyword(e.target.value.trim())} />
0} fallback={}>
diff --git a/ui/src/components/workflow/node/DeployNodeConfigForm.tsx b/ui/src/components/workflow/node/DeployNodeConfigForm.tsx
index c9b70570..92ce46cc 100644
--- a/ui/src/components/workflow/node/DeployNodeConfigForm.tsx
+++ b/ui/src/components/workflow/node/DeployNodeConfigForm.tsx
@@ -16,15 +16,18 @@ import { useAntdForm, useAntdFormName, useZustandShallowSelector } from "@/hooks
import { useWorkflowStore } from "@/stores/workflow";
import DeployNodeConfigFormAliyunALBConfig from "./DeployNodeConfigFormAliyunALBConfig";
+import DeployNodeConfigFormAliyunCASDeployConfig from "./DeployNodeConfigFormAliyunCASDeployConfig";
import DeployNodeConfigFormAliyunCDNConfig from "./DeployNodeConfigFormAliyunCDNConfig";
import DeployNodeConfigFormAliyunCLBConfig from "./DeployNodeConfigFormAliyunCLBConfig";
import DeployNodeConfigFormAliyunDCDNConfig from "./DeployNodeConfigFormAliyunDCDNConfig";
+import DeployNodeConfigFormAliyunESAConfig from "./DeployNodeConfigFormAliyunESAConfig";
import DeployNodeConfigFormAliyunLiveConfig from "./DeployNodeConfigFormAliyunLiveConfig";
import DeployNodeConfigFormAliyunNLBConfig from "./DeployNodeConfigFormAliyunNLBConfig";
import DeployNodeConfigFormAliyunOSSConfig from "./DeployNodeConfigFormAliyunOSSConfig";
import DeployNodeConfigFormAliyunWAFConfig from "./DeployNodeConfigFormAliyunWAFConfig";
import DeployNodeConfigFormAWSCloudFrontConfig from "./DeployNodeConfigFormAWSCloudFrontConfig";
import DeployNodeConfigFormBaiduCloudCDNConfig from "./DeployNodeConfigFormBaiduCloudCDNConfig";
+import DeployNodeConfigFormBaotaPanelSiteConfig from "./DeployNodeConfigFormBaotaPanelSiteConfig";
import DeployNodeConfigFormBytePlusCDNConfig from "./DeployNodeConfigFormBytePlusCDNConfig";
import DeployNodeConfigFormDogeCloudCDNConfig from "./DeployNodeConfigFormDogeCloudCDNConfig";
import DeployNodeConfigFormEdgioApplicationsConfig from "./DeployNodeConfigFormEdgioApplicationsConfig";
@@ -41,6 +44,7 @@ import DeployNodeConfigFormTencentCloudCOSConfig from "./DeployNodeConfigFormTen
import DeployNodeConfigFormTencentCloudCSSConfig from "./DeployNodeConfigFormTencentCloudCSSConfig.tsx";
import DeployNodeConfigFormTencentCloudECDNConfig from "./DeployNodeConfigFormTencentCloudECDNConfig.tsx";
import DeployNodeConfigFormTencentCloudEOConfig from "./DeployNodeConfigFormTencentCloudEOConfig.tsx";
+import DeployNodeConfigFormTencentCloudSSLDeployConfig from "./DeployNodeConfigFormTencentCloudSSLDeployConfig";
import DeployNodeConfigFormUCloudUCDNConfig from "./DeployNodeConfigFormUCloudUCDNConfig.tsx";
import DeployNodeConfigFormUCloudUS3Config from "./DeployNodeConfigFormUCloudUS3Config.tsx";
import DeployNodeConfigFormVolcEngineCDNConfig from "./DeployNodeConfigFormVolcEngineCDNConfig.tsx";
@@ -123,12 +127,16 @@ const DeployNodeConfigForm = forwardRef;
+ case DEPLOY_PROVIDERS.ALIYUN_CAS_DEPLOY:
+ return ;
case DEPLOY_PROVIDERS.ALIYUN_CLB:
return ;
case DEPLOY_PROVIDERS.ALIYUN_CDN:
return ;
case DEPLOY_PROVIDERS.ALIYUN_DCDN:
return ;
+ case DEPLOY_PROVIDERS.ALIYUN_ESA:
+ return ;
case DEPLOY_PROVIDERS.ALIYUN_LIVE:
return ;
case DEPLOY_PROVIDERS.ALIYUN_NLB:
@@ -141,6 +149,8 @@ const DeployNodeConfigForm = forwardRef;
case DEPLOY_PROVIDERS.BAIDUCLOUD_CDN:
return ;
+ case DEPLOY_PROVIDERS.BAOTAPANEL_SITE:
+ return ;
case DEPLOY_PROVIDERS.BYTEPLUS_CDN:
return ;
case DEPLOY_PROVIDERS.DOGECLOUD_CDN:
@@ -173,6 +183,8 @@ const DeployNodeConfigForm = forwardRef;
case DEPLOY_PROVIDERS.TENCENTCLOUD_EO:
return ;
+ case DEPLOY_PROVIDERS.TENCENTCLOUD_SSL_DEPLOY:
+ return ;
case DEPLOY_PROVIDERS.UCLOUD_UCDN:
return ;
case DEPLOY_PROVIDERS.UCLOUD_US3:
@@ -261,7 +273,7 @@ const DeployNodeConfigForm = forwardRef
}
+ fallback={}
>
;
+
+export type DeployNodeConfigFormAliyunCASDeployConfigProps = {
+ form: FormInstance;
+ formName: string;
+ disabled?: boolean;
+ initialValues?: DeployNodeConfigFormAliyunCASDeployConfigFieldValues;
+ onValuesChange?: (values: DeployNodeConfigFormAliyunCASDeployConfigFieldValues) => void;
+};
+
+const MULTIPLE_INPUT_DELIMITER = ";";
+
+const initFormModel = (): DeployNodeConfigFormAliyunCASDeployConfigFieldValues => {
+ return {};
+};
+
+const DeployNodeConfigFormAliyunCASDeployConfig = ({
+ form: formInst,
+ formName,
+ disabled,
+ initialValues,
+ onValuesChange,
+}: DeployNodeConfigFormAliyunCASDeployConfigProps) => {
+ const { t } = useTranslation();
+
+ const formSchema = z.object({
+ region: z
+ .string({ message: t("workflow_node.deploy.form.aliyun_cas_deploy_region.placeholder") })
+ .nonempty(t("workflow_node.deploy.form.aliyun_cas_deploy_region.placeholder"))
+ .trim(),
+ resourceIds: z.string({ message: t("workflow_node.deploy.form.aliyun_cas_deploy_resource_ids.placeholder") }).refine((v) => {
+ return String(v)
+ .split(MULTIPLE_INPUT_DELIMITER)
+ .every((e) => /^[1-9]\d*$/.test(e));
+ }, t("workflow_node.deploy.form.aliyun_cas_deploy_resource_ids.errmsg.invalid")),
+ contactIds: z
+ .string({ message: t("workflow_node.deploy.form.aliyun_cas_deploy_contact_ids.placeholder") })
+ .nullish()
+ .refine((v) => {
+ if (!v) return true;
+ return String(v)
+ .split(MULTIPLE_INPUT_DELIMITER)
+ .every((e) => /^[1-9]\d*$/.test(e));
+ }, t("workflow_node.deploy.form.aliyun_cas_deploy_contact_ids.errmsg.invalid")),
+ });
+ const formRule = createSchemaFieldRule(formSchema);
+
+ const fieldResourceIds = Form.useWatch("resourceIds", formInst);
+ const fieldContactIds = Form.useWatch("contactIds", formInst);
+
+ const handleFormChange = (_: unknown, values: z.infer) => {
+ onValuesChange?.(values);
+ };
+
+ return (
+ }
+ >
+
+
+
+ }
+ >
+
+
+ {
+ formInst.setFieldValue("resourceIds", e.target.value);
+ }}
+ />
+
+
+
+
+ }
+ onChange={(value) => {
+ formInst.setFieldValue("resourceIds", value);
+ }}
+ />
+
+
+
+ }
+ >
+
+
+ {
+ formInst.setFieldValue("contactIds", e.target.value);
+ }}
+ />
+
+
+
+
+ }
+ onChange={(value) => {
+ formInst.setFieldValue("contactIds", value);
+ }}
+ />
+
+
+
+
+ } />
+
+
+ );
+};
+
+const ResourceIdsModalInput = memo(({ value, trigger, onChange }: { value?: string; trigger?: React.ReactNode; onChange?: (value: string) => void }) => {
+ const { t } = useTranslation();
+
+ const formSchema = z.object({
+ resourceIds: z.array(z.string()).refine((v) => {
+ return v.every((e) => !e?.trim() || /^[1-9]\d*$/.test(e));
+ }, t("workflow_node.deploy.form.aliyun_cas_deploy_resource_ids.errmsg.invalid")),
+ });
+ const formRule = createSchemaFieldRule(formSchema);
+ const { form: formInst, formProps } = useAntdForm({
+ name: "workflowNodeDeployConfigFormAliyunCASResourceIdsModalInput",
+ initialValues: { resourceIds: value?.split(MULTIPLE_INPUT_DELIMITER) },
+ onSubmit: (values) => {
+ onChange?.(
+ values.resourceIds
+ .map((e) => e.trim())
+ .filter((e) => !!e)
+ .join(MULTIPLE_INPUT_DELIMITER)
+ );
+ },
+ });
+
+ return (
+
+
+
+
+
+ );
+});
+
+const ContactIdsModalInput = memo(({ value, trigger, onChange }: { value?: string; trigger?: React.ReactNode; onChange?: (value: string) => void }) => {
+ const { t } = useTranslation();
+
+ const formSchema = z.object({
+ contactIds: z.array(z.string()).refine((v) => {
+ return v.every((e) => !e?.trim() || /^[1-9]\d*$/.test(e));
+ }, t("workflow_node.deploy.form.aliyun_cas_deploy_contact_ids.errmsg.invalid")),
+ });
+ const formRule = createSchemaFieldRule(formSchema);
+ const { form: formInst, formProps } = useAntdForm({
+ name: "workflowNodeDeployConfigFormAliyunCASDeploymentJobContactIdsModalInput",
+ initialValues: { contactIds: value?.split(MULTIPLE_INPUT_DELIMITER) },
+ onSubmit: (values) => {
+ onChange?.(
+ values.contactIds
+ .map((e) => e.trim())
+ .filter((e) => !!e)
+ .join(MULTIPLE_INPUT_DELIMITER)
+ );
+ },
+ });
+
+ return (
+
+
+
+
+
+ );
+});
+
+export default DeployNodeConfigFormAliyunCASDeployConfig;
diff --git a/ui/src/components/workflow/node/DeployNodeConfigFormAliyunESAConfig.tsx b/ui/src/components/workflow/node/DeployNodeConfigFormAliyunESAConfig.tsx
new file mode 100644
index 00000000..338c0f97
--- /dev/null
+++ b/ui/src/components/workflow/node/DeployNodeConfigFormAliyunESAConfig.tsx
@@ -0,0 +1,78 @@
+import { useTranslation } from "react-i18next";
+import { Form, type FormInstance, Input } from "antd";
+import { createSchemaFieldRule } from "antd-zod";
+import { z } from "zod";
+
+type DeployNodeConfigFormAliyunESAConfigFieldValues = Nullish<{
+ region: string;
+ siteId: string;
+}>;
+
+export type DeployNodeConfigFormAliyunESAConfigProps = {
+ form: FormInstance;
+ formName: string;
+ disabled?: boolean;
+ initialValues?: DeployNodeConfigFormAliyunESAConfigFieldValues;
+ onValuesChange?: (values: DeployNodeConfigFormAliyunESAConfigFieldValues) => void;
+};
+
+const initFormModel = (): DeployNodeConfigFormAliyunESAConfigFieldValues => {
+ return {};
+};
+
+const DeployNodeConfigFormAliyunESAConfig = ({
+ form: formInst,
+ formName,
+ disabled,
+ initialValues,
+ onValuesChange,
+}: DeployNodeConfigFormAliyunESAConfigProps) => {
+ const { t } = useTranslation();
+
+ const formSchema = z.object({
+ region: z
+ .string({ message: t("workflow_node.deploy.form.aliyun_esa_region.placeholder") })
+ .nonempty(t("workflow_node.deploy.form.aliyun_esa_region.placeholder"))
+ .trim(),
+ siteId: z
+ .string({ message: t("workflow_node.deploy.form.aliyun_esa_site_id.placeholder") })
+ .regex(/^[1-9]\d*$/, t("workflow_node.deploy.form.aliyun_esa_site_id.placeholder"))
+ .trim(),
+ });
+ const formRule = createSchemaFieldRule(formSchema);
+
+ const handleFormChange = (_: unknown, values: z.infer) => {
+ onValuesChange?.(values);
+ };
+
+ return (
+ }
+ >
+
+
+
+ }
+ >
+
+
+
+ );
+};
+
+export default DeployNodeConfigFormAliyunESAConfig;
diff --git a/ui/src/components/workflow/node/DeployNodeConfigFormBaotaPanelSiteConfig.tsx b/ui/src/components/workflow/node/DeployNodeConfigFormBaotaPanelSiteConfig.tsx
new file mode 100644
index 00000000..aa891245
--- /dev/null
+++ b/ui/src/components/workflow/node/DeployNodeConfigFormBaotaPanelSiteConfig.tsx
@@ -0,0 +1,64 @@
+import { useTranslation } from "react-i18next";
+import { Form, type FormInstance, Input } from "antd";
+import { createSchemaFieldRule } from "antd-zod";
+import { z } from "zod";
+
+type DeployNodeConfigFormBaotaPanelSiteConfigFieldValues = Nullish<{
+ siteName: string;
+}>;
+
+export type DeployNodeConfigFormBaotaPanelSiteConfigProps = {
+ form: FormInstance;
+ formName: string;
+ disabled?: boolean;
+ initialValues?: DeployNodeConfigFormBaotaPanelSiteConfigFieldValues;
+ onValuesChange?: (values: DeployNodeConfigFormBaotaPanelSiteConfigFieldValues) => void;
+};
+
+const initFormModel = (): DeployNodeConfigFormBaotaPanelSiteConfigFieldValues => {
+ return {};
+};
+
+const DeployNodeConfigFormBaotaPanelSiteConfig = ({
+ form: formInst,
+ formName,
+ disabled,
+ initialValues,
+ onValuesChange,
+}: DeployNodeConfigFormBaotaPanelSiteConfigProps) => {
+ const { t } = useTranslation();
+
+ const formSchema = z.object({
+ siteName: z
+ .string({ message: t("workflow_node.deploy.form.baotapanel_site_name.placeholder") })
+ .nonempty(t("workflow_node.deploy.form.baotapanel_site_name.placeholder"))
+ .trim(),
+ });
+ const formRule = createSchemaFieldRule(formSchema);
+
+ const handleFormChange = (_: unknown, values: z.infer) => {
+ onValuesChange?.(values);
+ };
+
+ return (
+ }
+ >
+
+
+
+ );
+};
+
+export default DeployNodeConfigFormBaotaPanelSiteConfig;
diff --git a/ui/src/components/workflow/node/DeployNodeConfigFormTencentCloudCLBConfig.tsx b/ui/src/components/workflow/node/DeployNodeConfigFormTencentCloudCLBConfig.tsx
index dd6f6ead..2e7dc127 100644
--- a/ui/src/components/workflow/node/DeployNodeConfigFormTencentCloudCLBConfig.tsx
+++ b/ui/src/components/workflow/node/DeployNodeConfigFormTencentCloudCLBConfig.tsx
@@ -22,14 +22,14 @@ export type DeployNodeConfigFormTencentCloudCLBConfigProps = {
onValuesChange?: (values: DeployNodeConfigFormTencentCloudCLBConfigFieldValues) => void;
};
-const RESOURCE_TYPE_SSLDEPLOY = "ssl-deploy" as const;
+const RESOURCE_TYPE_VIA_SSLDEPLOY = "ssl-deploy" as const;
const RESOURCE_TYPE_LOADBALANCER = "loadbalancer" as const;
const RESOURCE_TYPE_LISTENER = "listener" as const;
const RESOURCE_TYPE_RULEDOMAIN = "ruledomain" as const;
const initFormModel = (): DeployNodeConfigFormTencentCloudCLBConfigFieldValues => {
return {
- resourceType: RESOURCE_TYPE_SSLDEPLOY,
+ resourceType: RESOURCE_TYPE_VIA_SSLDEPLOY,
};
};
@@ -44,7 +44,7 @@ const DeployNodeConfigFormTencentCloudCLBConfig = ({
const formSchema = z.object({
resourceType: z.union(
- [z.literal(RESOURCE_TYPE_SSLDEPLOY), z.literal(RESOURCE_TYPE_LOADBALANCER), z.literal(RESOURCE_TYPE_LISTENER), z.literal(RESOURCE_TYPE_RULEDOMAIN)],
+ [z.literal(RESOURCE_TYPE_VIA_SSLDEPLOY), z.literal(RESOURCE_TYPE_LOADBALANCER), z.literal(RESOURCE_TYPE_LISTENER), z.literal(RESOURCE_TYPE_RULEDOMAIN)],
{ message: t("workflow_node.deploy.form.tencentcloud_clb_resource_type.placeholder") }
),
region: z
@@ -62,7 +62,7 @@ const DeployNodeConfigFormTencentCloudCLBConfig = ({
.trim()
.nullish()
.refine(
- (v) => ![RESOURCE_TYPE_SSLDEPLOY, RESOURCE_TYPE_LISTENER, RESOURCE_TYPE_RULEDOMAIN].includes(fieldResourceType) || !!v?.trim(),
+ (v) => ![RESOURCE_TYPE_VIA_SSLDEPLOY, RESOURCE_TYPE_LISTENER, RESOURCE_TYPE_RULEDOMAIN].includes(fieldResourceType) || !!v?.trim(),
t("workflow_node.deploy.form.tencentcloud_clb_listener_id.placeholder")
),
domain: z
@@ -89,7 +89,7 @@ const DeployNodeConfigFormTencentCloudCLBConfig = ({
>
-
+
;
+
+export type DeployNodeConfigFormTencentCloudSSLDeployConfigProps = {
+ form: FormInstance;
+ formName: string;
+ disabled?: boolean;
+ initialValues?: DeployNodeConfigFormTencentCloudSSLDeployConfigFieldValues;
+ onValuesChange?: (values: DeployNodeConfigFormTencentCloudSSLDeployConfigFieldValues) => void;
+};
+
+const MULTIPLE_INPUT_DELIMITER = ";";
+
+const initFormModel = (): DeployNodeConfigFormTencentCloudSSLDeployConfigFieldValues => {
+ return {};
+};
+
+const DeployNodeConfigFormTencentCloudSSLDeployConfig = ({
+ form: formInst,
+ formName,
+ disabled,
+ initialValues,
+ onValuesChange,
+}: DeployNodeConfigFormTencentCloudSSLDeployConfigProps) => {
+ const { t } = useTranslation();
+
+ const formSchema = z.object({
+ region: z
+ .string({ message: t("workflow_node.deploy.form.tencentcloud_ssl_deploy_region.placeholder") })
+ .nonempty(t("workflow_node.deploy.form.tencentcloud_ssl_deploy_region.placeholder"))
+ .trim(),
+ resourceType: z
+ .string({ message: t("workflow_node.deploy.form.tencentcloud_ssl_deploy_resource_type.placeholder") })
+ .nonempty(t("workflow_node.deploy.form.tencentcloud_ssl_deploy_resource_type.placeholder"))
+ .trim(),
+ resourceIds: z.string({ message: t("workflow_node.deploy.form.tencentcloud_ssl_deploy_resource_ids.placeholder") }).refine((v) => {
+ return String(v)
+ .split(MULTIPLE_INPUT_DELIMITER)
+ .every((e) => /^[A-Za-z0-9._-]+$/.test(e));
+ }, t("workflow_node.deploy.form.tencentcloud_ssl_deploy_resource_ids.errmsg.invalid")),
+ });
+ const formRule = createSchemaFieldRule(formSchema);
+
+ const fieldResourceIds = Form.useWatch("resourceIds", formInst);
+
+ const handleFormChange = (_: unknown, values: z.infer) => {
+ onValuesChange?.(values);
+ };
+
+ return (
+ }
+ >
+
+
+
+ }
+ >
+
+
+ {
+ formInst.setFieldValue("resourceIds", e.target.value);
+ }}
+ />
+
+
+
+
+ }
+ onChange={(value) => {
+ formInst.setFieldValue("resourceIds", value);
+ }}
+ />
+
+
+
+
+ } />
+
+
+ );
+};
+
+const ResourceIdsModalInput = memo(({ value, trigger, onChange }: { value?: string; trigger?: React.ReactNode; onChange?: (value: string) => void }) => {
+ const { t } = useTranslation();
+
+ const formSchema = z.object({
+ resourceIds: z.array(z.string()).refine((v) => {
+ return v.every((e) => !e?.trim() || /^[A-Za-z0-9._-]+$/.test(e));
+ }, t("workflow_node.deploy.form.tencentcloud_ssl_deploy_resource_ids.errmsg.invalid")),
+ });
+ const formRule = createSchemaFieldRule(formSchema);
+ const { form: formInst, formProps } = useAntdForm({
+ name: "workflowNodeDeployConfigFormTencentCloudSSLDeployResourceIdsModalInput",
+ initialValues: { resourceIds: value?.split(MULTIPLE_INPUT_DELIMITER) },
+ onSubmit: (values) => {
+ onChange?.(
+ values.resourceIds
+ .map((e) => e.trim())
+ .filter((e) => !!e)
+ .join(MULTIPLE_INPUT_DELIMITER)
+ );
+ },
+ });
+
+ return (
+
+
+
+
+
+ );
+});
+
+export default DeployNodeConfigFormTencentCloudSSLDeployConfig;
diff --git a/ui/src/components/workflow/node/_SharedNode.tsx b/ui/src/components/workflow/node/_SharedNode.tsx
index f2a4df60..a7b88e4c 100644
--- a/ui/src/components/workflow/node/_SharedNode.tsx
+++ b/ui/src/components/workflow/node/_SharedNode.tsx
@@ -260,7 +260,7 @@ const SharedNodeConfigDrawer = ({
const oldValues = Object.fromEntries(Object.entries(node.config ?? {}).filter(([_, value]) => value !== null && value !== undefined));
const newValues = Object.fromEntries(Object.entries(getFormValues()).filter(([_, value]) => value !== null && value !== undefined));
- const changed = !isEqual(oldValues, newValues);
+ const changed = !isEqual(oldValues, {}) && !isEqual(oldValues, newValues);
const { promise, resolve, reject } = Promise.withResolvers();
if (changed) {
diff --git a/ui/src/domain/access.ts b/ui/src/domain/access.ts
index 1e229751..ed7f8559 100644
--- a/ui/src/domain/access.ts
+++ b/ui/src/domain/access.ts
@@ -13,6 +13,7 @@ export interface AccessModel extends BaseModel {
| AccessConfigForAWS
| AccessConfigForAzure
| AccessConfigForBaiduCloud
+ | AccessConfigForBaotaPanel
| AccessConfigForBytePlus
| AccessConfigForCloudflare
| AccessConfigForClouDNS
@@ -68,6 +69,11 @@ export type AccessConfigForBaiduCloud = {
secretAccessKey: string;
};
+export type AccessConfigForBaotaPanel = {
+ apiUrl: string;
+ apiKey: string;
+};
+
export type AccessConfigForBytePlus = {
accessKey: string;
secretKey: string;
diff --git a/ui/src/domain/provider.ts b/ui/src/domain/provider.ts
index 652f4332..15562238 100644
--- a/ui/src/domain/provider.ts
+++ b/ui/src/domain/provider.ts
@@ -9,6 +9,7 @@ export const ACCESS_PROVIDERS = Object.freeze({
AWS: "aws",
AZURE: "azure",
BAIDUCLOUD: "baiducloud",
+ BAOTAPANEL: "baotapanel",
BYTEPLUS: "byteplus",
CLOUDFLARE: "cloudflare",
CLOUDNS: "cloudns",
@@ -70,6 +71,7 @@ export const accessProvidersMap: Map [
type,
diff --git a/ui/src/i18n/locales/en/nls.access.json b/ui/src/i18n/locales/en/nls.access.json
index 4f0266ca..25f8765d 100644
--- a/ui/src/i18n/locales/en/nls.access.json
+++ b/ui/src/i18n/locales/en/nls.access.json
@@ -63,6 +63,12 @@
"access.form.baiducloud_secret_access_key.label": "Baidu Cloud SecretAccessKey",
"access.form.baiducloud_secret_access_key.placeholder": "Please enter Baidu Cloud SecretAccessKey",
"access.form.baiducloud_secret_access_key.tooltip": "For more information, see https://intl.cloud.baidu.com/doc/Reference/s/jjwvz2e3p-en",
+ "access.form.baotapanel_api_url.label": "BaoTa Panel URL",
+ "access.form.baotapanel_api_url.placeholder": "Please enter BaoTa Panel URL",
+ "access.form.baotapanel_api_url.tooltip": "For more information, see https://www.bt.cn/bbs/thread-20376-1-1.html",
+ "access.form.baotapanel_api_key.label": "BaoTa Panel API key",
+ "access.form.baotapanel_api_key.placeholder": "Please enter BaoTa Panel API key",
+ "access.form.baotapanel_api_key.tooltip": "For more information, see https://www.bt.cn/bbs/thread-113890-1-1.html",
"access.form.byteplus_access_key.label": "BytePlus AccessKey",
"access.form.byteplus_access_key.placeholder": "Please enter BytePlus AccessKey",
"access.form.byteplus_access_key.tooltip": "For more information, see https://docs.byteplus.com/en/docs/byteplus-platform/docs-managing-keys",
@@ -111,7 +117,7 @@
"access.form.k8s_kubeconfig.label": "KubeConfig",
"access.form.k8s_kubeconfig.placeholder": "Please enter KubeConfig file",
"access.form.k8s_kubeconfig.upload": "Choose File ...",
- "access.form.k8s_kubeconfig.tooltip": "For more information, see https://kubernetes.io/docs/concepts/configuration/organize-cluster-access-kubeconfig/
Leave blank to use the Pod's ServiceAccount.",
+ "access.form.k8s_kubeconfig.tooltip": "For more information, see https://kubernetes.io/docs/concepts/configuration/organize-cluster-access-kubeconfig/
Leave it blank to use the Pod's ServiceAccount.",
"access.form.namedotcom_username.label": "Name.com username",
"access.form.namedotcom_username.placeholder": "Please enter Name.com username",
"access.form.namedotcom_username.tooltip": "For more information, see https://www.name.com/account/settings/api",
diff --git a/ui/src/i18n/locales/en/nls.common.json b/ui/src/i18n/locales/en/nls.common.json
index cb5c2d41..5b305561 100644
--- a/ui/src/i18n/locales/en/nls.common.json
+++ b/ui/src/i18n/locales/en/nls.common.json
@@ -38,10 +38,12 @@
"common.provider.acmehttpreq": "Http Request (ACME Proxy)",
"common.provider.aliyun": "Alibaba Cloud",
"common.provider.aliyun.alb": "Alibaba Cloud - ALB (Application Load Balancer)",
+ "common.provider.aliyun.cas_deploy": "Alibaba Cloud - via CAS (Certificate Management Service) Deployment Job",
"common.provider.aliyun.cdn": "Alibaba Cloud - CDN (Content Delivery Network)",
"common.provider.aliyun.clb": "Alibaba Cloud - CLB (Classic Load Balancer)",
"common.provider.aliyun.dcdn": "Alibaba Cloud - DCDN (Dynamic Route for Content Delivery Network)",
"common.provider.aliyun.dns": "Alibaba Cloud - DNS (Domain Name Service)",
+ "common.provider.aliyun.esa": "Alibaba Cloud - ESA (Edge Security Acceleration)",
"common.provider.aliyun.live": "Alibaba Cloud - ApsaraVideo Live",
"common.provider.aliyun.nlb": "Alibaba Cloud - NLB (Network Load Balancer)",
"common.provider.aliyun.oss": "Alibaba Cloud - OSS (Object Storage Service)",
@@ -53,6 +55,8 @@
"common.provider.azure.dns": "Azure - DNS",
"common.provider.baiducloud": "Baidu Cloud",
"common.provider.baiducloud.cdn": "Baidu Cloud - CDN (Content Delivery Network)",
+ "common.provider.baotapanel": "BaoTa Panel",
+ "common.provider.baotapanel.site": "BaoTa Panel - Site",
"common.provider.byteplus": "BytePlus",
"common.provider.byteplus.cdn": "BytePlus - CDN (Content Delivery Network)",
"common.provider.cloudflare": "Cloudflare",
@@ -87,6 +91,7 @@
"common.provider.tencentcloud.dns": "Tencent Cloud - DNS (Domain Name Service)",
"common.provider.tencentcloud.ecdn": "Tencent Cloud - ECDN (Enterprise Content Delivery Network)",
"common.provider.tencentcloud.eo": "Tencent Cloud - EdgeOne",
+ "common.provider.tencentcloud.ssl_deploy": "Tencent Cloud - via SSL Certificate Service Deployment Job",
"common.provider.ucloud": "UCloud",
"common.provider.ucloud.ucdn": "UCloud - UCDN (UCloud Content Delivery Network)",
"common.provider.ucloud.us3": "UCloud - US3 (UCloud Object-based Storage)",
diff --git a/ui/src/i18n/locales/en/nls.settings.json b/ui/src/i18n/locales/en/nls.settings.json
index 7a12b408..0bb6ba40 100644
--- a/ui/src/i18n/locales/en/nls.settings.json
+++ b/ui/src/i18n/locales/en/nls.settings.json
@@ -30,7 +30,7 @@
"settings.notification.push_test.pushed": "Sent",
"settings.notification.channel.form.bark_server_url.label": "Server URL",
"settings.notification.channel.form.bark_server_url.placeholder": "Please enter server URL",
- "settings.notification.channel.form.bark_server_url.tooltip": "For more information, see https://bark.day.app/
Leave blank to use the default Bark server.",
+ "settings.notification.channel.form.bark_server_url.tooltip": "For more information, see https://bark.day.app/
Leave it blank to use the default Bark server.",
"settings.notification.channel.form.bark_device_key.label": "Device key",
"settings.notification.channel.form.bark_device_key.placeholder": "Please enter device key",
"settings.notification.channel.form.bark_device_key.tooltip": "For more information, see https://bark.day.app/",
diff --git a/ui/src/i18n/locales/en/nls.workflow.nodes.json b/ui/src/i18n/locales/en/nls.workflow.nodes.json
index 84f0f48e..a4b3a15e 100644
--- a/ui/src/i18n/locales/en/nls.workflow.nodes.json
+++ b/ui/src/i18n/locales/en/nls.workflow.nodes.json
@@ -37,8 +37,8 @@
"workflow_node.apply.form.provider_access.placeholder": "Please select an authorization of DNS provider",
"workflow_node.apply.form.provider_access.tooltip": "Used to manage DNS records during ACME DNS-01 authentication.",
"workflow_node.apply.form.provider_access.button": "Create",
- "workflow_node.apply.form.aws_route53_region.label": "AWS Region",
- "workflow_node.apply.form.aws_route53_region.placeholder": "Please enter AWS region (e.g. us-east-1)",
+ "workflow_node.apply.form.aws_route53_region.label": "AWS Route53 Region",
+ "workflow_node.apply.form.aws_route53_region.placeholder": "Please enter AWS Route53 region (e.g. us-east-1)",
"workflow_node.apply.form.aws_route53_region.tooltip": "For more information, see https://docs.aws.amazon.com/en_us/general/latest/gr/rande.html#regional-endpoints",
"workflow_node.apply.form.aws_route53_hosted_zone_id.label": "AWS Route53 hosted zone ID",
"workflow_node.apply.form.aws_route53_hosted_zone_id.placeholder": "Please enter AWS Route53 hosted zone ID",
@@ -57,11 +57,11 @@
"workflow_node.apply.form.dns_propagation_timeout.label": "DNS propagation timeout (Optional)",
"workflow_node.apply.form.dns_propagation_timeout.placeholder": "Please enter DNS propagation timeout",
"workflow_node.apply.form.dns_propagation_timeout.unit": "seconds",
- "workflow_node.apply.form.dns_propagation_timeout.tooltip": "It determines the maximum waiting time for DNS propagation checks during ACME DNS-01 authentication. If you don't understand this option, just keep it by default.
Leave blank to use the default value provided by the provider.",
+ "workflow_node.apply.form.dns_propagation_timeout.tooltip": "It determines the maximum waiting time for DNS propagation checks during ACME DNS-01 authentication. If you don't understand this option, just keep it by default.
Leave it blank to use the default value provided by the provider.",
"workflow_node.apply.form.dns_ttl.label": "DNS TTL (Optional)",
"workflow_node.apply.form.dns_ttl.placeholder": "Please enter DNS TTL",
"workflow_node.apply.form.dns_ttl.unit": "seconds",
- "workflow_node.apply.form.dns_ttl.tooltip": "It determines the time to live for DNS record during ACME DNS-01 authentication. If you don't understand this option, just keep it by default.
Leave blank to use the default value provided by the provider.",
+ "workflow_node.apply.form.dns_ttl.tooltip": "It determines the time to live for DNS record during ACME DNS-01 authentication. If you don't understand this option, just keep it by default.
Leave it blank to use the default value provided by the provider.",
"workflow_node.apply.form.disable_follow_cname.label": "Disable CNAME following",
"workflow_node.apply.form.disable_follow_cname.tooltip": "It determines whether to disable CNAME following during ACME DNS-01 authentication. If you don't understand this option, just keep it by default. Learn more.",
"workflow_node.apply.form.disable_ari.label": "Disable ARI",
@@ -91,8 +91,8 @@
"workflow_node.deploy.form.aliyun_alb_resource_type.placeholder": "Please select resource type",
"workflow_node.deploy.form.aliyun_alb_resource_type.option.loadbalancer.label": "ALB load balancer",
"workflow_node.deploy.form.aliyun_alb_resource_type.option.listener.label": "ALB listener",
- "workflow_node.deploy.form.aliyun_alb_region.label": "Alibaba Cloud region",
- "workflow_node.deploy.form.aliyun_alb_region.placeholder": "Please enter Alibaba Cloud region (e.g. cn-hangzhou)",
+ "workflow_node.deploy.form.aliyun_alb_region.label": "Alibaba Cloud ALB region",
+ "workflow_node.deploy.form.aliyun_alb_region.placeholder": "Please enter Alibaba Cloud ALB region (e.g. cn-hangzhou)",
"workflow_node.deploy.form.aliyun_alb_region.tooltip": "For more information, see https://www.alibabacloud.com/help/en/slb/application-load-balancer/product-overview/supported-regions-and-zones",
"workflow_node.deploy.form.aliyun_alb_loadbalancer_id.label": "Alibaba Cloud ALB load balancer ID",
"workflow_node.deploy.form.aliyun_alb_loadbalancer_id.placeholder": "Please enter Alibaba Cloud ALB load balancer ID",
@@ -103,12 +103,28 @@
"workflow_node.deploy.form.aliyun_alb_snidomain.label": "Alibaba Cloud ALB SNI domain (Optional)",
"workflow_node.deploy.form.aliyun_alb_snidomain.placeholder": "Please enter Alibaba Cloud ALB SNI domain name",
"workflow_node.deploy.form.aliyun_alb_snidomain.tooltip": "For more information, see https://slb.console.aliyun.com/alb",
+ "workflow_node.deploy.form.aliyun_cas_deploy.guide": "TIPS: You need to go to the Alibaba Cloud console to check the actual deployment results by yourself, because Alibaba Cloud deployment tasks are running asynchronously.",
+ "workflow_node.deploy.form.aliyun_cas_deploy_region.label": "Alibaba Cloud CAS region",
+ "workflow_node.deploy.form.aliyun_cas_deploy_region.placeholder": "Please enter Alibaba Cloud CAS region (e.g. cn-hangzhou)",
+ "workflow_node.deploy.form.aliyun_cas_deploy_region.tooltip": "For more information, see https://www.alibabacloud.com/help/en/ssl-certificate/developer-reference/endpoints",
+ "workflow_node.deploy.form.aliyun_cas_deploy_resource_ids.label": "Alibaba Cloud resource IDs",
+ "workflow_node.deploy.form.aliyun_cas_deploy_resource_ids.placeholder": "Please enter Alibaba Cloud resource IDs (separated by semicolons)",
+ "workflow_node.deploy.form.aliyun_cas_deploy_resource_ids.errmsg.invalid": "Please enter a valid Alibaba Cloud resource ID",
+ "workflow_node.deploy.form.aliyun_cas_deploy_resource_ids.tooltip": "For more information, see https://www.alibabacloud.com/help/en/ssl-certificate/developer-reference/api-cas-2020-04-07-listcloudresources
Supports Alibaba Cloud products only.",
+ "workflow_node.deploy.form.aliyun_cas_deploy_resource_ids.multiple_input_modal.title": "Change Alibaba Cloud resource IDs",
+ "workflow_node.deploy.form.aliyun_cas_deploy_resource_ids.multiple_input_modal.placeholder": "Please enter Alibaba Cloud resouce ID",
+ "workflow_node.deploy.form.aliyun_cas_deploy_contact_ids.label": "Alibaba Cloud contact IDs (Optional)",
+ "workflow_node.deploy.form.aliyun_cas_deploy_contact_ids.placeholder": "Please enter Alibaba Cloud contact IDs (separated by semicolons)",
+ "workflow_node.deploy.form.aliyun_cas_deploy_contact_ids.errmsg.invalid": "Please enter a valid Alibaba Cloud contact ID",
+ "workflow_node.deploy.form.aliyun_cas_deploy_contact_ids.tooltip": "For more information, see https://www.alibabacloud.com/help/en/ssl-certificate/developer-reference/api-cas-2020-04-07-listcontact
Leave it blank to use the first system contact.",
+ "workflow_node.deploy.form.aliyun_cas_deploy_contact_ids.multiple_input_modal.title": "Change Alibaba Cloud contact IDs",
+ "workflow_node.deploy.form.aliyun_cas_deploy_contact_ids.multiple_input_modal.placeholder": "Please enter Alibaba Cloud contact ID",
"workflow_node.deploy.form.aliyun_clb_resource_type.label": "Resource type",
"workflow_node.deploy.form.aliyun_clb_resource_type.placeholder": "Please select resource type",
"workflow_node.deploy.form.aliyun_clb_resource_type.option.loadbalancer.label": "CLB load balancer",
"workflow_node.deploy.form.aliyun_clb_resource_type.option.listener.label": "CLB listener",
- "workflow_node.deploy.form.aliyun_clb_region.label": "Alibaba Cloud region",
- "workflow_node.deploy.form.aliyun_clb_region.placeholder": "Please enter Alibaba Cloud region (e.g. cn-hangzhou)",
+ "workflow_node.deploy.form.aliyun_clb_region.label": "Alibaba Cloud CLB region",
+ "workflow_node.deploy.form.aliyun_clb_region.placeholder": "Please enter Alibaba Cloud CLB region (e.g. cn-hangzhou)",
"workflow_node.deploy.form.aliyun_clb_region.tooltip": "For more information, see https://www.alibabacloud.com/help/en/slb/classic-load-balancer/product-overview/regions-that-support-clb",
"workflow_node.deploy.form.aliyun_clb_loadbalancer_id.label": "Alibaba Cloud CLB load balancer ID",
"workflow_node.deploy.form.aliyun_clb_loadbalancer_id.placeholder": "Please enter Alibaba Cloud CLB load balancer ID",
@@ -125,8 +141,14 @@
"workflow_node.deploy.form.aliyun_dcdn_domain.label": "Alibaba Cloud DCDN domain",
"workflow_node.deploy.form.aliyun_dcdn_domain.placeholder": "Please enter Alibaba Cloud DCDN domain name",
"workflow_node.deploy.form.aliyun_dcdn_domain.tooltip": "For more information, see https://dcdn.console.aliyun.com",
- "workflow_node.deploy.form.aliyun_live_region.label": "Alibaba Cloud region",
- "workflow_node.deploy.form.aliyun_live_region.placeholder": "Please enter Alibaba Cloud region (e.g. cn-hangzhou)",
+ "workflow_node.deploy.form.aliyun_esa_region.label": "Alibaba Cloud ESA region",
+ "workflow_node.deploy.form.aliyun_esa_region.placeholder": "Please enter Alibaba Cloud ESA region (e.g. cn-hangzhou)",
+ "workflow_node.deploy.form.aliyun_esa_region.tooltip": "For more information, see https://www.alibabacloud.com/help/en/edge-security-acceleration/esa/api-esa-2024-09-10-endpoint",
+ "workflow_node.deploy.form.aliyun_esa_site_id.label": "Alibaba Cloud ESA site ID",
+ "workflow_node.deploy.form.aliyun_esa_site_id.placeholder": "Please enter Alibaba Cloud ESA site ID",
+ "workflow_node.deploy.form.aliyun_esa_site_id.tooltip": "For more information, see https://esa.console.aliyun.com/siteManage/list",
+ "workflow_node.deploy.form.aliyun_live_region.label": "Alibaba Cloud Live region",
+ "workflow_node.deploy.form.aliyun_live_region.placeholder": "Please enter Alibaba Cloud Live region (e.g. cn-hangzhou)",
"workflow_node.deploy.form.aliyun_live_region.tooltip": "For more information, see https://www.alibabacloud.com/help/en/live/product-overview/supported-regions",
"workflow_node.deploy.form.aliyun_live_domain.label": "Alibaba Cloud live streaming domain",
"workflow_node.deploy.form.aliyun_live_domain.placeholder": "Please enter Alibaba Cloud live streaming domain name",
@@ -135,8 +157,8 @@
"workflow_node.deploy.form.aliyun_nlb_resource_type.placeholder": "Please select resource type",
"workflow_node.deploy.form.aliyun_nlb_resource_type.option.loadbalancer.label": "NLB load balancer",
"workflow_node.deploy.form.aliyun_nlb_resource_type.option.listener.label": "NLB listener",
- "workflow_node.deploy.form.aliyun_nlb_region.label": "Alibaba Cloud region",
- "workflow_node.deploy.form.aliyun_nlb_region.placeholder": "Please enter Alibaba Cloud region (e.g. cn-hangzhou)",
+ "workflow_node.deploy.form.aliyun_nlb_region.label": "Alibaba Cloud NLB region",
+ "workflow_node.deploy.form.aliyun_nlb_region.placeholder": "Please enter Alibaba Cloud NLB region (e.g. cn-hangzhou)",
"workflow_node.deploy.form.aliyun_nlb_region.tooltip": "For more information, see https://www.alibabacloud.com/help/en/slb/network-load-balancer/product-overview/regions-that-support-nlb",
"workflow_node.deploy.form.aliyun_nlb_loadbalancer_id.label": "Alibaba Cloud NLB load balancer ID",
"workflow_node.deploy.form.aliyun_nlb_loadbalancer_id.placeholder": "Please enter Alibaba Cloud NLB load balancer ID",
@@ -144,8 +166,8 @@
"workflow_node.deploy.form.aliyun_nlb_listener_id.label": "Alibaba Cloud NLB listener ID",
"workflow_node.deploy.form.aliyun_nlb_listener_id.placeholder": "Please enter Alibaba Cloud NLB listener ID",
"workflow_node.deploy.form.aliyun_nlb_listener_id.tooltip": "For more information, see https://slb.console.aliyun.com/nlb",
- "workflow_node.deploy.form.aliyun_oss_region.label": "Alibaba Cloud region",
- "workflow_node.deploy.form.aliyun_oss_region.placeholder": "Please enter Alibaba Cloud region (e.g. cn-hangzhou)",
+ "workflow_node.deploy.form.aliyun_oss_region.label": "Alibaba Cloud OSS region",
+ "workflow_node.deploy.form.aliyun_oss_region.placeholder": "Please enter Alibaba Cloud OSS region (e.g. cn-hangzhou)",
"workflow_node.deploy.form.aliyun_oss_region.tooltip": "For more information, see https://www.alibabacloud.com/help/en/oss/user-guide/regions-and-endpoints",
"workflow_node.deploy.form.aliyun_oss_bucket.label": "Alibaba Cloud OSS bucket",
"workflow_node.deploy.form.aliyun_oss_bucket.placeholder": "Please enter Alibaba Cloud OSS bucket name",
@@ -153,14 +175,14 @@
"workflow_node.deploy.form.aliyun_oss_domain.label": "Alibaba Cloud OSS domain",
"workflow_node.deploy.form.aliyun_oss_domain.placeholder": "Please enter Alibaba Cloud OSS domain name",
"workflow_node.deploy.form.aliyun_oss_domain.tooltip": "For more information, see https://oss.console.aliyun.com",
- "workflow_node.deploy.form.aliyun_waf_region.label": "Alibaba Cloud region",
- "workflow_node.deploy.form.aliyun_waf_region.placeholder": "Please enter Alibaba Cloud region (e.g. cn-hangzhou)",
+ "workflow_node.deploy.form.aliyun_waf_region.label": "Alibaba Cloud WAF region",
+ "workflow_node.deploy.form.aliyun_waf_region.placeholder": "Please enter Alibaba Cloud WAF region (e.g. cn-hangzhou)",
"workflow_node.deploy.form.aliyun_waf_region.tooltip": "For more information, see https://www.alibabacloud.com/help/en/waf/web-application-firewall-3-0/developer-reference/api-waf-openapi-2021-10-01-endpoint",
"workflow_node.deploy.form.aliyun_waf_instance_id.label": "Alibaba Cloud WAF instance ID",
"workflow_node.deploy.form.aliyun_waf_instance_id.placeholder": "Please enter Alibaba Cloud WAF instance ID",
"workflow_node.deploy.form.aliyun_waf_instance_id.tooltip": "For more information, see https://waf.console.aliyun.com",
- "workflow_node.deploy.form.aws_cloudfront_region.label": "AWS Region",
- "workflow_node.deploy.form.aws_cloudfront_region.placeholder": "Please enter AWS region (e.g. us-east-1)",
+ "workflow_node.deploy.form.aws_cloudfront_region.label": "AWS CloudFront Region",
+ "workflow_node.deploy.form.aws_cloudfront_region.placeholder": "Please enter AWS CloudFront region (e.g. us-east-1)",
"workflow_node.deploy.form.aws_cloudfront_region.tooltip": "For more information, see https://docs.aws.amazon.com/en_us/general/latest/gr/rande.html#regional-endpoints",
"workflow_node.deploy.form.aws_cloudfront_distribution_id.label": "AWS CloudFront distribution ID",
"workflow_node.deploy.form.aws_cloudfront_distribution_id.placeholder": "Please enter AWS CloudFront distribution ID",
@@ -168,6 +190,9 @@
"workflow_node.deploy.form.baiducloud_cdn_domain.label": "Baidu Cloud CDN domain",
"workflow_node.deploy.form.baiducloud_cdn_domain.placeholder": "Please enter Baidu Cloud CDN domain name",
"workflow_node.deploy.form.baiducloud_cdn_domain.tooltip": "For more information, see https://console.bce.baidu.com/cdn",
+ "workflow_node.deploy.form.baotapanel_site_name.label": "BaoTa Panel site name",
+ "workflow_node.deploy.form.baotapanel_site_name.placeholder": "Please enter BaoTa Panel site name",
+ "workflow_node.deploy.form.baotapanel_site_name.tooltip": "Usually equal to the website domain name.",
"workflow_node.deploy.form.byteplus_cdn_domain.label": "BytePlus CDN domain",
"workflow_node.deploy.form.byteplus_cdn_domain.placeholder": "Please enter BytePlus CDN domain name",
"workflow_node.deploy.form.byteplus_cdn_domain.tooltip": "For more information, see https://console.byteplus.com/cdn",
@@ -177,8 +202,8 @@
"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/",
- "workflow_node.deploy.form.huaweicloud_cdn_region.label": "Huawei Cloud region",
- "workflow_node.deploy.form.huaweicloud_cdn_region.placeholder": "Please enter Huawei Cloud region (e.g. cn-north-1)",
+ "workflow_node.deploy.form.huaweicloud_cdn_region.label": "Huawei Cloud CDN region",
+ "workflow_node.deploy.form.huaweicloud_cdn_region.placeholder": "Please enter Huawei Cloud CDN region (e.g. cn-north-1)",
"workflow_node.deploy.form.huaweicloud_cdn_region.tooltip": "For more information, see https://console-intl.huaweicloud.com/apiexplorer/#/endpoint",
"workflow_node.deploy.form.huaweicloud_cdn_domain.label": "Huawei Cloud CDN domain",
"workflow_node.deploy.form.huaweicloud_cdn_domain.placeholder": "Please enter Huawei Cloud CDN domain name",
@@ -188,8 +213,8 @@
"workflow_node.deploy.form.huaweicloud_elb_resource_type.option.certificate.label": "ELB certificate",
"workflow_node.deploy.form.huaweicloud_elb_resource_type.option.loadbalancer.label": "ELB load balancer",
"workflow_node.deploy.form.huaweicloud_elb_resource_type.option.listener.label": "ELB listener",
- "workflow_node.deploy.form.huaweicloud_elb_region.label": "Huawei Cloud region",
- "workflow_node.deploy.form.huaweicloud_elb_region.placeholder": "Please enter Huawei Cloud region (e.g. cn-north-1)",
+ "workflow_node.deploy.form.huaweicloud_elb_region.label": "Huawei Cloud ELB region",
+ "workflow_node.deploy.form.huaweicloud_elb_region.placeholder": "Please enter Huawei Cloud ELB region (e.g. cn-north-1)",
"workflow_node.deploy.form.huaweicloud_elb_region.tooltip": "For more information, see https://console-intl.huaweicloud.com/apiexplorer/#/endpoint",
"workflow_node.deploy.form.huaweicloud_elb_certificate_id.label": "Huawei Cloud ELB certificate ID",
"workflow_node.deploy.form.huaweicloud_elb_certificate_id.placeholder": "Please enter Huawei Cloud ELB certificate ID",
@@ -298,12 +323,12 @@
"workflow_node.deploy.form.tencentcloud_cdn_domain.tooltip": "For more information, see https://console.tencentcloud.com/cdn",
"workflow_node.deploy.form.tencentcloud_clb_resource_type.label": "Resource type",
"workflow_node.deploy.form.tencentcloud_clb_resource_type.placeholder": "Please select resource type",
- "workflow_node.deploy.form.tencentcloud_clb_resource_type.option.ssl_deploy.label": "Through SSL deploy",
+ "workflow_node.deploy.form.tencentcloud_clb_resource_type.option.ssl_deploy.label": "Via SSL deploy",
"workflow_node.deploy.form.tencentcloud_clb_resource_type.option.loadbalancer.label": "CLB instance",
"workflow_node.deploy.form.tencentcloud_clb_resource_type.option.listener.label": "CLB listener",
"workflow_node.deploy.form.tencentcloud_clb_resource_type.option.ruledomain.label": "CLB rule domain",
- "workflow_node.deploy.form.tencentcloud_clb_region.label": "Tencent Cloud region",
- "workflow_node.deploy.form.tencentcloud_clb_region.placeholder": "Please enter Tencent Cloud region (e.g. ap-guangzhou)",
+ "workflow_node.deploy.form.tencentcloud_clb_region.label": "Tencent Cloud CLB region",
+ "workflow_node.deploy.form.tencentcloud_clb_region.placeholder": "Please enter Tencent Cloud CLB region (e.g. ap-guangzhou)",
"workflow_node.deploy.form.tencentcloud_clb_region.tooltip": "For more information, see https://www.tencentcloud.com/document/product/214/13629",
"workflow_node.deploy.form.tencentcloud_clb_loadbalancer_id.label": "Tencent Cloud CLB instance ID",
"workflow_node.deploy.form.tencentcloud_clb_loadbalancer_id.placeholder": "Please enter Tencent Cloud CLB instance ID",
@@ -317,8 +342,8 @@
"workflow_node.deploy.form.tencentcloud_clb_ruledomain.label": "Tencent Cloud CLB domain",
"workflow_node.deploy.form.tencentcloud_clb_ruledomain.placeholder": "Please enter Tencent Cloud CLB domain name",
"workflow_node.deploy.form.tencentcloud_clb_ruledomain.tooltip": "For more information, see https://console.tencentcloud.com/clb",
- "workflow_node.deploy.form.tencentcloud_cos_region.label": "Tencent Cloud region",
- "workflow_node.deploy.form.tencentcloud_cos_region.placeholder": "Please enter Tencent Cloud region (e.g. ap-guangzhou)",
+ "workflow_node.deploy.form.tencentcloud_cos_region.label": "Tencent Cloud COS region",
+ "workflow_node.deploy.form.tencentcloud_cos_region.placeholder": "Please enter Tencent Cloud COS region (e.g. ap-guangzhou)",
"workflow_node.deploy.form.tencentcloud_cos_region.tooltip": "For more information, see https://www.tencentcloud.com/document/product/436/6224",
"workflow_node.deploy.form.tencentcloud_cos_bucket.label": "Tencent Cloud COS bucket",
"workflow_node.deploy.form.tencentcloud_cos_bucket.placeholder": "Please enter Tencent Cloud COS bucket name",
@@ -338,11 +363,21 @@
"workflow_node.deploy.form.tencentcloud_eo_domain.label": "Tencent Cloud EdgeOne domain",
"workflow_node.deploy.form.tencentcloud_eo_domain.placeholder": "Please enter Tencent Cloud EdgeOne domain name",
"workflow_node.deploy.form.tencentcloud_eo_domain.tooltip": "For more information, see https://console.tencentcloud.com/edgeone",
+ "workflow_node.deploy.form.tencentcloud_ssl_deploy.guide": "TIPS: You need to go to the Tencent Cloud console to check the actual deployment results by yourself, because Tencent Cloud deployment tasks are running asynchronously.",
+ "workflow_node.deploy.form.tencentcloud_ssl_deploy_region.label": "Tencent Cloud service region",
+ "workflow_node.deploy.form.tencentcloud_ssl_deploy_region.placeholder": "Please enter Tencent Cloud service region (e.g. ap-guangzhou)",
+ "workflow_node.deploy.form.tencentcloud_ssl_deploy_region.tooltip": "For more information, see https://www.tencentcloud.com/document/product/1007/36573",
+ "workflow_node.deploy.form.tencentcloud_ssl_deploy_resource_ids.label": "Tencent Cloud resource IDs",
+ "workflow_node.deploy.form.tencentcloud_ssl_deploy_resource_ids.placeholder": "Please enter Tencent Cloud resource IDs (separated by semicolons)",
+ "workflow_node.deploy.form.tencentcloud_ssl_deploy_resource_ids.errmsg.invalid": "Please enter a valid Tencent Cloud resource ID",
+ "workflow_node.deploy.form.tencentcloud_ssl_deploy_resource_ids.tooltip": "For more information, see https://cloud.tencent.com.cn/document/product/400/91667",
+ "workflow_node.deploy.form.tencentcloud_ssl_deploy_resource_ids.multiple_input_modal.title": "Change Tencent Cloud resource IDs",
+ "workflow_node.deploy.form.tencentcloud_ssl_deploy_resource_ids.multiple_input_modal.placeholder": "Please enter Tencent Cloud resouce ID",
"workflow_node.deploy.form.ucloud_ucdn_domain_id.label": "UCloud UCDN domain ID",
"workflow_node.deploy.form.ucloud_ucdn_domain_id.placeholder": "Please enter UCloud UCDN domain ID",
"workflow_node.deploy.form.ucloud_ucdn_domain_id.tooltip": "For more information, see https://console.ucloud-global.com/ucdn",
- "workflow_node.deploy.form.ucloud_us3_region.label": "UCloud region",
- "workflow_node.deploy.form.ucloud_us3_region.placeholder": "Please enter VolcEngine region (e.g. cn-bj2)",
+ "workflow_node.deploy.form.ucloud_us3_region.label": "UCloud US3 region",
+ "workflow_node.deploy.form.ucloud_us3_region.placeholder": "Please enter UCloud US3 region (e.g. cn-bj2)",
"workflow_node.deploy.form.ucloud_us3_region.tooltip": "For more information, see https://www.ucloud-global.com/en/docs/api/summary/regionlist",
"workflow_node.deploy.form.ucloud_us3_bucket.label": "UCloud US3 bucket",
"workflow_node.deploy.form.ucloud_us3_bucket.placeholder": "Please enter UCloud US3 bucket name",
@@ -356,8 +391,8 @@
"workflow_node.deploy.form.volcengine_clb_resource_type.label": "Resource type",
"workflow_node.deploy.form.volcengine_clb_resource_type.placeholder": "Please select resource type",
"workflow_node.deploy.form.volcengine_clb_resource_type.option.listener.label": "CLB listener",
- "workflow_node.deploy.form.volcengine_clb_region.label": "VolcEngine region",
- "workflow_node.deploy.form.volcengine_clb_region.placeholder": "Please enter VolcEngine region (e.g. cn-beijing)",
+ "workflow_node.deploy.form.volcengine_clb_region.label": "VolcEngine CLB region",
+ "workflow_node.deploy.form.volcengine_clb_region.placeholder": "Please enter VolcEngine CLB region (e.g. cn-beijing)",
"workflow_node.deploy.form.volcengine_clb_region.tooltip": "For more information, see https://www.volcengine.com/docs/6406/74892",
"workflow_node.deploy.form.volcengine_clb_listener_id.label": "VolcEngine CLB listener ID",
"workflow_node.deploy.form.volcengine_clb_listener_id.placeholder": "Please enter VolcEngine CLB listener ID",
@@ -368,8 +403,8 @@
"workflow_node.deploy.form.volcengine_live_domain.label": "VolcEngine Live streaming domain",
"workflow_node.deploy.form.volcengine_live_domain.placeholder": "Please enter VolcEngine Live streaming domain name",
"workflow_node.deploy.form.volcengine_live_domain.tooltip": "For more information, see https://console.volcengine.com/live",
- "workflow_node.deploy.form.volcengine_tos_region.label": "VolcEngine region",
- "workflow_node.deploy.form.volcengine_tos_region.placeholder": "Please enter VolcEngine region (e.g. cn-beijing)",
+ "workflow_node.deploy.form.volcengine_tos_region.label": "VolcEngine TOS region",
+ "workflow_node.deploy.form.volcengine_tos_region.placeholder": "Please enter VolcEngine TOS region (e.g. cn-beijing)",
"workflow_node.deploy.form.volcengine_tos_region.tooltip": "For more information, see https://www.volcengine.com/docs/6349/107356",
"workflow_node.deploy.form.volcengine_tos_bucket.label": "VolcEngine TOS bucket",
"workflow_node.deploy.form.volcengine_tos_bucket.placeholder": "Please enter VolcEngine TOS bucket name",
diff --git a/ui/src/i18n/locales/zh/nls.access.json b/ui/src/i18n/locales/zh/nls.access.json
index d0c9037d..3581a527 100644
--- a/ui/src/i18n/locales/zh/nls.access.json
+++ b/ui/src/i18n/locales/zh/nls.access.json
@@ -63,6 +63,12 @@
"access.form.baiducloud_secret_access_key.label": "百度智能云 SecretAccessKey",
"access.form.baiducloud_secret_access_key.placeholder": "请输入百度智能云 SecretAccessKey",
"access.form.baiducloud_secret_access_key.tooltip": "这是什么?请参阅 https://cloud.baidu.com/doc/Reference/s/jjwvz2e3p",
+ "access.form.baotapanel_api_url.label": "宝塔面板 URL",
+ "access.form.baotapanel_api_url.placeholder": "请输入宝塔面板 URL",
+ "access.form.baotapanel_api_url.tooltip": "这是什么?请参阅 https://www.bt.cn/bbs/thread-20376-1-1.html",
+ "access.form.baotapanel_api_key.label": "宝塔面板接口密钥",
+ "access.form.baotapanel_api_key.placeholder": "请输入宝塔面板接口密钥",
+ "access.form.baotapanel_api_key.tooltip": "这是什么?请参阅 https://www.bt.cn/bbs/thread-113890-1-1.html",
"access.form.byteplus_access_key.label": "BytePlus AccessKey",
"access.form.byteplus_access_key.placeholder": "请输入 BytePlus AccessKey",
"access.form.byteplus_access_key.tooltip": "这是什么?请参阅 https://docs.byteplus.com/zh-CN/docs/byteplus-platform/docs-managing-keys",
@@ -147,11 +153,11 @@
"access.form.ssh_username.placeholder": "请输入用户名",
"access.form.ssh_password.label": "密码",
"access.form.ssh_password.placeholder": "请输入密码",
- "access.form.ssh_password.tooltip": "使用密码连接到 SSH 时必填。
该字段与密钥文件字段二选一。",
+ "access.form.ssh_password.tooltip": "使用密码连接到 SSH 时必填。
该字段与密钥文件字段二选一,如果同时填写优先使用 SSH 密钥登录。",
"access.form.ssh_key.label": "SSH 密钥",
"access.form.ssh_key.placeholder": "请输入 SSH 密钥文件",
"access.form.ssh_key.upload": "选择文件",
- "access.form.ssh_key.tooltip": "使用 SSH 密钥连接到 SSH 时必填。
该字段与密码字段二选一。",
+ "access.form.ssh_key.tooltip": "使用 SSH 密钥连接到 SSH 时必填。
该字段与密码字段二选一,如果同时填写优先使用 SSH 密钥登录。",
"access.form.ssh_key_passphrase.label": "SSH 密钥口令",
"access.form.ssh_key_passphrase.placeholder": "请输入 SSH 密钥口令",
"access.form.ssh_key_passphrase.tooltip": "使用 SSH 密钥连接到 SSH 时选填。",
diff --git a/ui/src/i18n/locales/zh/nls.common.json b/ui/src/i18n/locales/zh/nls.common.json
index b8b97842..cfc23730 100644
--- a/ui/src/i18n/locales/zh/nls.common.json
+++ b/ui/src/i18n/locales/zh/nls.common.json
@@ -38,9 +38,11 @@
"common.provider.acmehttpreq": "Http Request (ACME Proxy)",
"common.provider.aliyun": "阿里云",
"common.provider.aliyun.alb": "阿里云 - 应用型负载均衡 ALB",
+ "common.provider.aliyun.cas_deploy": "阿里云 - 通过数字证书管理服务 CAS 创建部署任务",
"common.provider.aliyun.cdn": "阿里云 - 内容分发网络 CDN",
"common.provider.aliyun.clb": "阿里云 - 传统型负载均衡 CLB",
"common.provider.aliyun.dcdn": "阿里云 - 全站加速 DCDN",
+ "common.provider.aliyun.esa": "阿里云 - 边缘安全加速 ESA",
"common.provider.aliyun.dns": "阿里云 - 云解析 DNS",
"common.provider.aliyun.live": "阿里云 - 视频直播 Live",
"common.provider.aliyun.nlb": "阿里云 - 网络型负载均衡 NLB",
@@ -53,6 +55,8 @@
"common.provider.azure.dns": "Azure - DNS",
"common.provider.baiducloud": "百度智能云",
"common.provider.baiducloud.cdn": "百度智能云 - 内容分发网络 CDN",
+ "common.provider.baotapanel": "宝塔面板",
+ "common.provider.baotapanel.site": "宝塔面板 - 网站",
"common.provider.byteplus": "BytePlus",
"common.provider.byteplus.cdn": "BytePlus - 内容分发网络 CDN",
"common.provider.cloudflare": "Cloudflare",
@@ -87,6 +91,7 @@
"common.provider.tencentcloud.dns": "腾讯云 - 云解析 DNS",
"common.provider.tencentcloud.ecdn": "腾讯云 - 全站加速网络 ECDN",
"common.provider.tencentcloud.eo": "腾讯云 - 边缘安全加速平台 EdgeOne",
+ "common.provider.tencentcloud.ssl_deploy": "腾讯云 - 通过 SSL 证书服务创建部署任务",
"common.provider.ucloud": "优刻得",
"common.provider.ucloud.ucdn": "优刻得 - 内容分发 UCDN",
"common.provider.ucloud.us3": "优刻得 - 对象存储 US3",
diff --git a/ui/src/i18n/locales/zh/nls.workflow.nodes.json b/ui/src/i18n/locales/zh/nls.workflow.nodes.json
index 40860e1e..705d8056 100644
--- a/ui/src/i18n/locales/zh/nls.workflow.nodes.json
+++ b/ui/src/i18n/locales/zh/nls.workflow.nodes.json
@@ -37,9 +37,8 @@
"workflow_node.apply.form.provider_access.placeholder": "请选择 DNS 提供商授权",
"workflow_node.apply.form.provider_access.tooltip": "用于 ACME DNS-01 认证时操作域名解析记录,注意与部署阶段所需的主机提供商相区分。",
"workflow_node.apply.form.provider_access.button": "新建",
- "workflow_node.deploy.form.provider_access.guide_for_local": "小贴士:由于表单限制,你同样需要为本地部署选择一个授权 —— 即使它是空白的。",
- "workflow_node.apply.form.aws_route53_region.label": "AWS 区域",
- "workflow_node.apply.form.aws_route53_region.placeholder": "请输入 AWS 区域(例如:us-east-1)",
+ "workflow_node.apply.form.aws_route53_region.label": "AWS Route53 服务区域",
+ "workflow_node.apply.form.aws_route53_region.placeholder": "请输入 AWS Route53 服务区域(例如:us-east-1)",
"workflow_node.apply.form.aws_route53_region.tooltip": "这是什么?请参阅 https://docs.aws.amazon.com/zh_cn/general/latest/gr/rande.html#regional-endpoints",
"workflow_node.apply.form.aws_route53_hosted_zone_id.label": "AWS Route53 托管区域 ID",
"workflow_node.apply.form.aws_route53_hosted_zone_id.placeholder": "请输入 AWS Route53 托管区域 ID",
@@ -58,11 +57,11 @@
"workflow_node.apply.form.dns_propagation_timeout.label": "DNS 传播检查超时时间(可选)",
"workflow_node.apply.form.dns_propagation_timeout.placeholder": "请输入 DNS 传播检查超时时间",
"workflow_node.apply.form.dns_propagation_timeout.unit": "秒",
- "workflow_node.apply.form.dns_propagation_timeout.tooltip": "在 ACME DNS-01 认证时等待 DNS 传播检查的最长时间。如果你不了解此选项的用途,保持默认即可。
为空时,将使用提供商提供的默认值。",
+ "workflow_node.apply.form.dns_propagation_timeout.tooltip": "在 ACME DNS-01 认证时等待 DNS 传播检查的最长时间。如果你不了解此选项的用途,保持默认即可。
不填写时,将使用提供商提供的默认值。",
"workflow_node.apply.form.dns_ttl.label": "DNS 解析 TTL(可选)",
"workflow_node.apply.form.dns_ttl.placeholder": "请输入 DNS 解析 TTL",
"workflow_node.apply.form.dns_ttl.unit": "秒",
- "workflow_node.apply.form.dns_ttl.tooltip": "在 ACME DNS-01 认证时 DNS 解析记录的 TTL。如果你不了解此选项的用途,保持默认即可。
为空时,将使用提供商提供的默认值。",
+ "workflow_node.apply.form.dns_ttl.tooltip": "在 ACME DNS-01 认证时 DNS 解析记录的 TTL。如果你不了解此选项的用途,保持默认即可。
不填写时,将使用提供商提供的默认值。",
"workflow_node.apply.form.disable_follow_cname.label": "关闭 CNAME 跟随",
"workflow_node.apply.form.disable_follow_cname.tooltip": "在 ACME DNS-01 认证时是否关闭 CNAME 跟随。如果你不了解该选项的用途,保持默认即可。点此了解更多。",
"workflow_node.apply.form.disable_ari.label": "关闭 ARI 续期",
@@ -83,6 +82,7 @@
"workflow_node.deploy.form.provider_access.placeholder": "请选择主机提供商授权",
"workflow_node.deploy.form.provider_access.tooltip": "用于部署证书,注意与申请阶段所需的 DNS 提供商相区分。",
"workflow_node.deploy.form.provider_access.button": "新建",
+ "workflow_node.deploy.form.provider_access.guide_for_local": "小贴士:由于表单限制,你同样需要为本地部署选择一个授权 —— 即使它是空白的。",
"workflow_node.deploy.form.certificate.label": "待部署证书",
"workflow_node.deploy.form.certificate.placeholder": "请选择待部署证书",
"workflow_node.deploy.form.certificate.tooltip": "待部署证书来自之前的申请阶段。如果选项为空请先确保前序节点配置正确。",
@@ -91,8 +91,8 @@
"workflow_node.deploy.form.aliyun_alb_resource_type.placeholder": "请选择证书替换方式",
"workflow_node.deploy.form.aliyun_alb_resource_type.option.loadbalancer.label": "替换指定负载均衡器下的全部 HTTPS/QUIC 监听的证书",
"workflow_node.deploy.form.aliyun_alb_resource_type.option.listener.label": "替换指定负载均衡监听器的证书",
- "workflow_node.deploy.form.aliyun_alb_region.label": "阿里云地域",
- "workflow_node.deploy.form.aliyun_alb_region.placeholder": "请输入阿里云地域(例如:cn-hangzhou)",
+ "workflow_node.deploy.form.aliyun_alb_region.label": "阿里云 ALB 服务地域",
+ "workflow_node.deploy.form.aliyun_alb_region.placeholder": "请输入阿里云 ALB 服务地域(例如:cn-hangzhou)",
"workflow_node.deploy.form.aliyun_alb_region.tooltip": "这是什么?请参阅 https://help.aliyun.com/zh/slb/application-load-balancer/product-overview/supported-regions-and-zones",
"workflow_node.deploy.form.aliyun_alb_loadbalancer_id.label": "阿里云 ALB 负载均衡器 ID",
"workflow_node.deploy.form.aliyun_alb_loadbalancer_id.placeholder": "请输入阿里云 ALB 负载均衡器 ID",
@@ -102,13 +102,29 @@
"workflow_node.deploy.form.aliyun_alb_listener_id.tooltip": "这是什么?请参阅 https://slb.console.aliyun.com/alb",
"workflow_node.deploy.form.aliyun_alb_snidomain.label": "阿里云 ALB 扩展域名(可选)",
"workflow_node.deploy.form.aliyun_alb_snidomain.placeholder": "请输入阿里云 ALB 扩展域名",
- "workflow_node.deploy.form.aliyun_alb_snidomain.tooltip": "这是什么?请参阅 https://slb.console.aliyun.com/alb
为空时,将替换监听器的默认证书。",
+ "workflow_node.deploy.form.aliyun_alb_snidomain.tooltip": "这是什么?请参阅 https://slb.console.aliyun.com/alb
不填写时,将替换监听器的默认证书。",
+ "workflow_node.deploy.form.aliyun_cas_deploy.guide": "小贴士:由于阿里云证书部署任务是异步的,此节点若执行成功仅代表已创建部署任务,实际部署结果需要你自行前往阿里云控制台查询。",
+ "workflow_node.deploy.form.aliyun_cas_deploy_region.label": "阿里云 CAS 服务地域",
+ "workflow_node.deploy.form.aliyun_cas_deploy_region.placeholder": "请输入阿里云 CAS 服务地域(例如:cn-hangzhou)",
+ "workflow_node.deploy.form.aliyun_cas_deploy_region.tooltip": "这是什么?请参阅 https://help.aliyun.com/zh/ssl-certificate/developer-reference/endpoints",
+ "workflow_node.deploy.form.aliyun_cas_deploy_resource_ids.label": "阿里云云产品资源 ID",
+ "workflow_node.deploy.form.aliyun_cas_deploy_resource_ids.placeholder": "请输入阿里云云产品资源 ID(多个值请用半角分号隔开)",
+ "workflow_node.deploy.form.aliyun_cas_deploy_resource_ids.errmsg.invalid": "请输入正确的阿里云云产品资源 ID",
+ "workflow_node.deploy.form.aliyun_cas_deploy_resource_ids.tooltip": "这是什么?请参阅 https://help.aliyun.com/zh/ssl-certificate/developer-reference/api-cas-2020-04-07-listcloudresources
仅支持阿里云产品,注意与各产品本身的实例 ID 区分。",
+ "workflow_node.deploy.form.aliyun_cas_deploy_resource_ids.multiple_input_modal.title": "修改阿里云云产品资源 ID",
+ "workflow_node.deploy.form.aliyun_cas_deploy_resource_ids.multiple_input_modal.placeholder": "请输入阿里云云产品资源 ID",
+ "workflow_node.deploy.form.aliyun_cas_deploy_contact_ids.label": "阿里云联系人 ID(可选)",
+ "workflow_node.deploy.form.aliyun_cas_deploy_contact_ids.placeholder": "请输入阿里云联系人 ID(多个值请用半角分号隔开)",
+ "workflow_node.deploy.form.aliyun_cas_deploy_contact_ids.errmsg.invalid": "请输入正确的阿里云联系人 ID",
+ "workflow_node.deploy.form.aliyun_cas_deploy_contact_ids.tooltip": "这是什么?请参阅 https://help.aliyun.com/zh/ssl-certificate/developer-reference/api-cas-2020-04-07-listcontact
不填写时,将使用系统联系人列表中的第一个。",
+ "workflow_node.deploy.form.aliyun_cas_deploy_contact_ids.multiple_input_modal.title": "修改阿里云联系人 ID",
+ "workflow_node.deploy.form.aliyun_cas_deploy_contact_ids.multiple_input_modal.placeholder": "请输入阿里云联系人 ID",
"workflow_node.deploy.form.aliyun_clb_resource_type.label": "证书替换方式",
"workflow_node.deploy.form.aliyun_clb_resource_type.placeholder": "请选择证书替换方式",
"workflow_node.deploy.form.aliyun_clb_resource_type.option.loadbalancer.label": "替换指定负载均衡器下的全部 HTTPS 监听的证书",
"workflow_node.deploy.form.aliyun_clb_resource_type.option.listener.label": "替换指定负载均衡监听的证书",
- "workflow_node.deploy.form.aliyun_clb_region.label": "阿里云地域",
- "workflow_node.deploy.form.aliyun_clb_region.placeholder": "请输入阿里云地域(例如:cn-hangzhou)",
+ "workflow_node.deploy.form.aliyun_clb_region.label": "阿里云 CLB 服务地域",
+ "workflow_node.deploy.form.aliyun_clb_region.placeholder": "请输入阿里云 CLB 服务地域(例如:cn-hangzhou)",
"workflow_node.deploy.form.aliyun_clb_region.tooltip": "这是什么?请参阅 https://help.aliyun.com/zh/slb/classic-load-balancer/product-overview/regions-that-support-clb",
"workflow_node.deploy.form.aliyun_clb_loadbalancer_id.label": "阿里云 CLB 负载均衡器 ID",
"workflow_node.deploy.form.aliyun_clb_loadbalancer_id.placeholder": "请输入阿里云 CLB 负载均衡器 ID",
@@ -118,15 +134,21 @@
"workflow_node.deploy.form.aliyun_clb_listener_port.tooltip": "这是什么?请参阅 https://slb.console.aliyun.com/clb",
"workflow_node.deploy.form.aliyun_clb_snidomain.label": "阿里云 CLB 扩展域名(可选)",
"workflow_node.deploy.form.aliyun_clb_snidomain.placeholder": "请输入阿里云 CLB 扩展域名",
- "workflow_node.deploy.form.aliyun_clb_snidomain.tooltip": "这是什么?请参阅 https://slb.console.aliyun.com/clb
为空时,将替换监听器的默认证书。",
+ "workflow_node.deploy.form.aliyun_clb_snidomain.tooltip": "这是什么?请参阅 https://slb.console.aliyun.com/clb
不填写时,将替换监听器的默认证书。",
"workflow_node.deploy.form.aliyun_cdn_domain.label": "阿里云 CDN 加速域名(支持泛域名)",
"workflow_node.deploy.form.aliyun_cdn_domain.placeholder": "请输入阿里云 CDN 加速域名",
"workflow_node.deploy.form.aliyun_cdn_domain.tooltip": "这是什么?请参阅 https://cdn.console.aliyun.com
泛域名表示形式为:*.example.com",
"workflow_node.deploy.form.aliyun_dcdn_domain.label": "阿里云 DCDN 加速域名(支持泛域名)",
"workflow_node.deploy.form.aliyun_dcdn_domain.placeholder": "请输入阿里云 DCDN 加速域名",
"workflow_node.deploy.form.aliyun_dcdn_domain.tooltip": "这是什么?请参阅 https://dcdn.console.aliyun.com
泛域名表示形式为:*.example.com",
- "workflow_node.deploy.form.aliyun_live_region.label": "阿里云地域",
- "workflow_node.deploy.form.aliyun_live_region.placeholder": "请输入阿里云地域(例如:cn-hangzhou)",
+ "workflow_node.deploy.form.aliyun_esa_region.label": "阿里云 ESA 服务地域",
+ "workflow_node.deploy.form.aliyun_esa_region.placeholder": "请输入阿里云 ESA 服务地域(例如:cn-hangzhou)",
+ "workflow_node.deploy.form.aliyun_esa_region.tooltip": "这是什么?请参阅 https://help.aliyun.com/zh/edge-security-acceleration/esa/api-esa-2024-09-10-endpoint",
+ "workflow_node.deploy.form.aliyun_esa_site_id.label": "阿里云 ESA 站点 ID",
+ "workflow_node.deploy.form.aliyun_esa_site_id.placeholder": "请输入阿里云 ESA 站点 ID",
+ "workflow_node.deploy.form.aliyun_esa_site_id.tooltip": "这是什么?请参阅 https://esa.console.aliyun.com/siteManage/list",
+ "workflow_node.deploy.form.aliyun_live_region.label": "阿里云视频直播服务地域",
+ "workflow_node.deploy.form.aliyun_live_region.placeholder": "请输入阿里云视频直播服务地域(例如:cn-hangzhou)",
"workflow_node.deploy.form.aliyun_live_region.tooltip": "这是什么?请参阅 https://help.aliyun.com/zh/live/product-overview/supported-regions",
"workflow_node.deploy.form.aliyun_live_domain.label": "阿里云视频直播流域名(支持泛域名)",
"workflow_node.deploy.form.aliyun_live_domain.placeholder": "请输入阿里云视频直播流域名",
@@ -135,8 +157,8 @@
"workflow_node.deploy.form.aliyun_nlb_resource_type.placeholder": "请选择证书替换方式",
"workflow_node.deploy.form.aliyun_nlb_resource_type.option.loadbalancer.label": "替换指定负载均衡器下的全部 HTTPS/QUIC 监听的证书",
"workflow_node.deploy.form.aliyun_nlb_resource_type.option.listener.label": "替换指定负载均衡监听器的证书",
- "workflow_node.deploy.form.aliyun_nlb_region.label": "阿里云地域",
- "workflow_node.deploy.form.aliyun_nlb_region.placeholder": "请输入阿里云地域(例如:cn-hangzhou)",
+ "workflow_node.deploy.form.aliyun_nlb_region.label": "阿里云 NLB 服务地域",
+ "workflow_node.deploy.form.aliyun_nlb_region.placeholder": "请输入阿里云 NLB 服务地域(例如:cn-hangzhou)",
"workflow_node.deploy.form.aliyun_nlb_region.tooltip": "这是什么?请参阅 https://help.aliyun.com/zh/slb/network-load-balancer/product-overview/regions-that-support-nlb",
"workflow_node.deploy.form.aliyun_nlb_loadbalancer_id.label": "阿里云 NLB 负载均衡器 ID",
"workflow_node.deploy.form.aliyun_nlb_loadbalancer_id.placeholder": "请输入阿里云 NLB 负载均衡器 ID",
@@ -144,8 +166,8 @@
"workflow_node.deploy.form.aliyun_nlb_listener_id.label": "阿里云 NLB 监听器 ID",
"workflow_node.deploy.form.aliyun_nlb_listener_id.placeholder": "请输入阿里云 NLB 监听器 ID",
"workflow_node.deploy.form.aliyun_nlb_listener_id.tooltip": "这是什么?请参阅 https://slb.console.aliyun.com/nlb",
- "workflow_node.deploy.form.aliyun_oss_region.label": "阿里云地域",
- "workflow_node.deploy.form.aliyun_oss_region.placeholder": "请输入阿里云地域(例如:cn-hangzhou)",
+ "workflow_node.deploy.form.aliyun_oss_region.label": "阿里云 OSS 服务地域",
+ "workflow_node.deploy.form.aliyun_oss_region.placeholder": "请输入阿里云 OSS 服务地域(例如:cn-hangzhou)",
"workflow_node.deploy.form.aliyun_oss_region.tooltip": "这是什么?请参阅 https://help.aliyun.com/zh/oss/user-guide/regions-and-endpoints",
"workflow_node.deploy.form.aliyun_oss_bucket.label": "阿里云 OSS 存储桶名",
"workflow_node.deploy.form.aliyun_oss_bucket.placeholder": "请输入阿里云 OSS 存储桶名",
@@ -153,14 +175,14 @@
"workflow_node.deploy.form.aliyun_oss_domain.label": "阿里云 OSS 自定义域名",
"workflow_node.deploy.form.aliyun_oss_domain.placeholder": "请输入阿里云 OSS 自定义域名",
"workflow_node.deploy.form.aliyun_oss_domain.tooltip": "这是什么?请参阅 see https://oss.console.aliyun.com",
- "workflow_node.deploy.form.aliyun_waf_region.label": "阿里云地域",
- "workflow_node.deploy.form.aliyun_waf_region.placeholder": "请输入阿里云地域(例如:cn-hangzhou)",
+ "workflow_node.deploy.form.aliyun_waf_region.label": "阿里云 WAF 服务地域",
+ "workflow_node.deploy.form.aliyun_waf_region.placeholder": "请输入阿里云 WAF 服务地域(例如:cn-hangzhou)",
"workflow_node.deploy.form.aliyun_waf_region.tooltip": "这是什么?请参阅 https://help.aliyun.com/zh/waf/web-application-firewall-3-0/developer-reference/api-waf-openapi-2021-10-01-endpoint",
"workflow_node.deploy.form.aliyun_waf_instance_id.label": "阿里云 WAF 实例 ID",
"workflow_node.deploy.form.aliyun_waf_instance_id.placeholder": "请输入阿里云 WAF 实例 ID",
"workflow_node.deploy.form.aliyun_waf_instance_id.tooltip": "这是什么?请参阅 https://waf.console.aliyun.com",
- "workflow_node.deploy.form.aws_cloudfront_region.label": "AWS 区域",
- "workflow_node.deploy.form.aws_cloudfront_region.placeholder": "请输入 AWS 区域(例如:us-east-1)",
+ "workflow_node.deploy.form.aws_cloudfront_region.label": "AWS CloudFront 服务区域",
+ "workflow_node.deploy.form.aws_cloudfront_region.placeholder": "请输入 AWS CloudFront 服务区域(例如:us-east-1)",
"workflow_node.deploy.form.aws_cloudfront_region.tooltip": "这是什么?请参阅 https://docs.aws.amazon.com/zh_cn/general/latest/gr/rande.html#regional-endpoints",
"workflow_node.deploy.form.aws_cloudfront_distribution_id.label": "AWS CloudFront 分配 ID",
"workflow_node.deploy.form.aws_cloudfront_distribution_id.placeholder": "请输入 AWS CloudFront 分配 ID",
@@ -168,6 +190,9 @@
"workflow_node.deploy.form.baiducloud_cdn_domain.label": "百度智能云 CDN 加速域名(支持泛域名)",
"workflow_node.deploy.form.baiducloud_cdn_domain.placeholder": "请输入百度智能云 CDN 加速域名",
"workflow_node.deploy.form.baiducloud_cdn_domain.tooltip": "这是什么?请参阅 https://console.bce.baidu.com/cdn
泛域名表示形式为:*.example.com",
+ "workflow_node.deploy.form.baotapanel_site_name.label": "宝塔面板网站名称",
+ "workflow_node.deploy.form.baotapanel_site_name.placeholder": "请输入宝塔面板网站名称",
+ "workflow_node.deploy.form.baotapanel_site_name.tooltip": "通常为网站域名。",
"workflow_node.deploy.form.byteplus_cdn_domain.label": "BytePlus CDN 域名(支持泛域名)",
"workflow_node.deploy.form.byteplus_cdn_domain.placeholder": "请输入 BytePlus CDN 域名",
"workflow_node.deploy.form.byteplus_cdn_domain.tooltip": "这是什么?请参阅 https://console.byteplus.com/cdn
泛域名表示形式为:*.example.com",
@@ -177,8 +202,8 @@
"workflow_node.deploy.form.edgio_applications_environment_id.label": "Edgio Applications 环境 ID",
"workflow_node.deploy.form.edgio_applications_environment_id.placeholder": "请输入 Edgio Applications 环境 ID",
"workflow_node.deploy.form.edgio_applications_environment_id.tooltip": "这是什么?请参阅 https://edgio.app/",
- "workflow_node.deploy.form.huaweicloud_cdn_region.label": "华为云区域",
- "workflow_node.deploy.form.huaweicloud_cdn_region.placeholder": "请输入华为云区域(例如:cn-north-1)",
+ "workflow_node.deploy.form.huaweicloud_cdn_region.label": "华为云 CDN 服务区域",
+ "workflow_node.deploy.form.huaweicloud_cdn_region.placeholder": "请输入华为云 CDN 服务区域(例如:cn-north-1)",
"workflow_node.deploy.form.huaweicloud_cdn_region.tooltip": "这是什么?请参阅 https://console.huaweicloud.com/apiexplorer/#/endpoint",
"workflow_node.deploy.form.huaweicloud_cdn_domain.label": "华为云 CDN 加速域名",
"workflow_node.deploy.form.huaweicloud_cdn_domain.placeholder": "请输入华为云 CDN 加速域名",
@@ -188,8 +213,8 @@
"workflow_node.deploy.form.huaweicloud_elb_resource_type.option.certificate.label": "替换指定证书",
"workflow_node.deploy.form.huaweicloud_elb_resource_type.option.loadbalancer.label": "替换指定负载均衡器下的全部 HTTPS 监听器的证书",
"workflow_node.deploy.form.huaweicloud_elb_resource_type.option.listener.label": "替换指定监听器的证书",
- "workflow_node.deploy.form.huaweicloud_elb_region.label": "华为云区域",
- "workflow_node.deploy.form.huaweicloud_elb_region.placeholder": "请输入华为云区域(例如:cn-north-1)",
+ "workflow_node.deploy.form.huaweicloud_elb_region.label": "华为云 ELB 服务区域",
+ "workflow_node.deploy.form.huaweicloud_elb_region.placeholder": "请输入华为云 ELB 服务区域(例如:cn-north-1)",
"workflow_node.deploy.form.huaweicloud_elb_region.tooltip": "这是什么?请参阅 https://console.huaweicloud.com/apiexplorer/#/endpoint",
"workflow_node.deploy.form.huaweicloud_elb_certificate_id.label": "华为云 ELB 证书 ID",
"workflow_node.deploy.form.huaweicloud_elb_certificate_id.placeholder": "请输入华为云 ELB 证书 ID",
@@ -302,8 +327,8 @@
"workflow_node.deploy.form.tencentcloud_clb_resource_type.option.loadbalancer.label": "替换指定实例下的全部 HTTPS/TCPSSL/QUIC 监听器的证书",
"workflow_node.deploy.form.tencentcloud_clb_resource_type.option.listener.label": "替换指定监听器的证书",
"workflow_node.deploy.form.tencentcloud_clb_resource_type.option.ruledomain.label": "替换指定七层监听转发规则域名的证书",
- "workflow_node.deploy.form.tencentcloud_clb_region.label": "腾讯云地域",
- "workflow_node.deploy.form.tencentcloud_clb_region.placeholder": "请输入腾讯云地域(例如:ap-guangzhou)",
+ "workflow_node.deploy.form.tencentcloud_clb_region.label": "腾讯云 CLB 产品地域",
+ "workflow_node.deploy.form.tencentcloud_clb_region.placeholder": "请输入腾讯云 CLB 服务地域(例如:ap-guangzhou)",
"workflow_node.deploy.form.tencentcloud_clb_region.tooltip": "这是什么?请参阅 https://cloud.tencent.com/document/product/214/33415",
"workflow_node.deploy.form.tencentcloud_clb_loadbalancer_id.label": "腾讯云 CLB 实例 ID",
"workflow_node.deploy.form.tencentcloud_clb_loadbalancer_id.placeholder": "请输入腾讯云 CLB 实例 ID",
@@ -313,12 +338,12 @@
"workflow_node.deploy.form.tencentcloud_clb_listener_id.tooltip": "这是什么?请参阅 https://console.cloud.tencent.com/clb",
"workflow_node.deploy.form.tencentcloud_clb_snidomain.label": "腾讯云 CLB SNI 域名(可选)",
"workflow_node.deploy.form.tencentcloud_clb_snidomain.placeholder": "请输入腾讯云 CLB SNI 域名",
- "workflow_node.deploy.form.tencentcloud_clb_snidomain.tooltip": "这是什么?请参阅 https://console.cloud.tencent.com/clb
为空时,将替换监听器的默认证书。",
+ "workflow_node.deploy.form.tencentcloud_clb_snidomain.tooltip": "这是什么?请参阅 https://console.cloud.tencent.com/clb
不填写时,将替换监听器的默认证书。",
"workflow_node.deploy.form.tencentcloud_clb_ruledomain.label": "腾讯云 CLB 七层转发规则域名",
"workflow_node.deploy.form.tencentcloud_clb_ruledomain.placeholder": "请输入腾讯云 CLB 七层转发规则域名",
"workflow_node.deploy.form.tencentcloud_clb_ruledomain.tooltip": "这是什么?请参阅 https://console.cloud.tencent.com/clb",
- "workflow_node.deploy.form.tencentcloud_cos_region.label": "腾讯云地域",
- "workflow_node.deploy.form.tencentcloud_cos_region.placeholder": "请输入腾讯云地域(例如:ap-guangzhou)",
+ "workflow_node.deploy.form.tencentcloud_cos_region.label": "腾讯云 COS 产品地域",
+ "workflow_node.deploy.form.tencentcloud_cos_region.placeholder": "请输入腾讯云 COS 产品地域(例如:ap-guangzhou)",
"workflow_node.deploy.form.tencentcloud_cos_region.tooltip": "这是什么?请参阅 https://cloud.tencent.com/document/product/436/6224",
"workflow_node.deploy.form.tencentcloud_cos_bucket.label": "腾讯云 COS 存储桶名",
"workflow_node.deploy.form.tencentcloud_cos_bucket.placeholder": "请输入腾讯云 COS 存储桶名",
@@ -338,11 +363,24 @@
"workflow_node.deploy.form.tencentcloud_eo_domain.label": "腾讯云 EdgeOne 加速域名",
"workflow_node.deploy.form.tencentcloud_eo_domain.placeholder": "请输入腾讯云 EdgeOne 加速域名",
"workflow_node.deploy.form.tencentcloud_eo_domain.tooltip": "这是什么?请参阅 https://console.cloud.tencent.com/edgeone",
+ "workflow_node.deploy.form.tencentcloud_ssl_deploy.guide": "小贴士:由于腾讯云证书部署任务是异步的,此节点若执行成功仅代表已创建部署任务,实际部署结果需要你自行前往腾讯云控制台查询。",
+ "workflow_node.deploy.form.tencentcloud_ssl_deploy_region.label": "腾讯云云产品地域",
+ "workflow_node.deploy.form.tencentcloud_ssl_deploy_region.placeholder": "请输入腾讯云云产品地域(例如:ap-guangzhou)",
+ "workflow_node.deploy.form.tencentcloud_ssl_deploy_region.tooltip": "这是什么?请参阅 https://cloud.tencent.com.cn/document/product/400/41659",
+ "workflow_node.deploy.form.tencentcloud_ssl_deploy_resource_type.label": "腾讯云云产品资源类型",
+ "workflow_node.deploy.form.tencentcloud_ssl_deploy_resource_type.placeholder": "请输入腾讯云产品资源类型",
+ "workflow_node.deploy.form.tencentcloud_ssl_deploy_resource_type.tooltip": "这是什么?请参阅 https://cloud.tencent.com.cn/document/product/400/91667",
+ "workflow_node.deploy.form.tencentcloud_ssl_deploy_resource_ids.label": "腾讯云云产品资源 ID",
+ "workflow_node.deploy.form.tencentcloud_ssl_deploy_resource_ids.placeholder": "请输入腾讯云云产品资源 ID(多个值请用半角分号隔开)",
+ "workflow_node.deploy.form.tencentcloud_ssl_deploy_resource_ids.errmsg.invalid": "请输入正确的腾讯云云产品资源 ID",
+ "workflow_node.deploy.form.tencentcloud_ssl_deploy_resource_ids.tooltip": "这是什么?请参阅 https://cloud.tencent.com.cn/document/product/400/91667
注意与各产品本身的实例 ID 区分。",
+ "workflow_node.deploy.form.tencentcloud_ssl_deploy_resource_ids.multiple_input_modal.title": "修改腾讯云云产品资源 ID",
+ "workflow_node.deploy.form.tencentcloud_ssl_deploy_resource_ids.multiple_input_modal.placeholder": "请输入腾讯云云产品资源 ID",
"workflow_node.deploy.form.ucloud_ucdn_domain_id.label": "优刻得 UCDN 域名 ID",
"workflow_node.deploy.form.ucloud_ucdn_domain_id.placeholder": "请输入优刻得 UCDN 域名 ID",
"workflow_node.deploy.form.ucloud_ucdn_domain_id.tooltip": "这是什么?请参阅 https://console.ucloud.cn/ucdn",
- "workflow_node.deploy.form.ucloud_us3_region.label": "优刻得地域",
- "workflow_node.deploy.form.ucloud_us3_region.placeholder": "优刻得地域(例如:cn-bj2)",
+ "workflow_node.deploy.form.ucloud_us3_region.label": "优刻得 US3 服务地域",
+ "workflow_node.deploy.form.ucloud_us3_region.placeholder": "优刻得 US3 服务地域(例如:cn-bj2)",
"workflow_node.deploy.form.ucloud_us3_region.tooltip": "这是什么?请参阅 https://docs.ucloud.cn/api/summary/regionlist",
"workflow_node.deploy.form.ucloud_us3_bucket.label": "优刻得 US3 存储桶名",
"workflow_node.deploy.form.ucloud_us3_bucket.placeholder": "请输入优刻得 US3 存储桶名",
@@ -356,8 +394,8 @@
"workflow_node.deploy.form.volcengine_clb_resource_type.label": "证书替换方式",
"workflow_node.deploy.form.volcengine_clb_resource_type.placeholder": "请选择证书替换方式",
"workflow_node.deploy.form.volcengine_clb_resource_type.option.listener.label": "替换指定监听器的证书",
- "workflow_node.deploy.form.volcengine_clb_region.label": "火山引擎地域",
- "workflow_node.deploy.form.volcengine_clb_region.placeholder": "请输入火山引擎地域(例如:cn-beijing)",
+ "workflow_node.deploy.form.volcengine_clb_region.label": "火山引擎 CLB 服务地域",
+ "workflow_node.deploy.form.volcengine_clb_region.placeholder": "请输入火山引擎 CLB 服务地域(例如:cn-beijing)",
"workflow_node.deploy.form.volcengine_clb_region.tooltip": "这是什么?请参阅 https://www.volcengine.com/docs/6406/74892",
"workflow_node.deploy.form.volcengine_clb_listener_id.label": "火山引擎 CLB 监听器 ID",
"workflow_node.deploy.form.volcengine_clb_listener_id.placeholder": "请输入火山引擎 CLB 监听器 ID",
@@ -368,8 +406,8 @@
"workflow_node.deploy.form.volcengine_live_domain.label": "火山引擎视频直播流域名(支持泛域名)",
"workflow_node.deploy.form.volcengine_live_domain.placeholder": "请输入火山引擎视频直播流域名",
"workflow_node.deploy.form.volcengine_live_domain.tooltip": "这是什么?请参阅 https://console.volcengine.com/live
泛域名表示形式为:*.example.com",
- "workflow_node.deploy.form.volcengine_tos_region.label": "火山引擎地域",
- "workflow_node.deploy.form.volcengine_tos_region.placeholder": "请输入火山引擎地域(例如:cn-beijing",
+ "workflow_node.deploy.form.volcengine_tos_region.label": "火山引擎 TOS 服务地域",
+ "workflow_node.deploy.form.volcengine_tos_region.placeholder": "请输入火山引擎 TOS 服务地域(例如:cn-beijing",
"workflow_node.deploy.form.volcengine_tos_region.tooltip": "这是什么?请参阅 https://www.volcengine.com/docs/6349/107356",
"workflow_node.deploy.form.volcengine_tos_bucket.label": "火山引擎 TOS 存储桶名",
"workflow_node.deploy.form.volcengine_tos_bucket.placeholder": "请输入火山引擎 TOS 存储桶名",