fix conflict

This commit is contained in:
Yoan.liu 2025-02-12 09:53:09 +08:00
commit 4a0e3c9a69
42 changed files with 1923 additions and 157 deletions

View File

@ -117,21 +117,22 @@ make local.run
<summary>[展开查看]</summary>
| 提供商 | 备注 |
| :-------------------------------------- | :------------------------------------------------------------------ |
| :-------------------------------------- | :----------------------------------------------------------------------- |
| 本地部署 | 可部署到本地服务器 |
| SSH 部署 | 可部署到远程服务器(通过 SSH+SFTP/SCP |
| Webhook 回调 | 可部署到 Webhook |
| [Kubernetes](https://kubernetes.io/) | 可部署到 Kubernetes Secret |
| [阿里云](https://www.aliyun.com/) | 可部署到阿里云 OSS、CDN、DCDN、SLBCLB/ALB/NLB、WAF、Live 等服务 |
| [阿里云](https://www.aliyun.com/) | 可部署到阿里云 OSS、CDN、DCDN、ESA、SLBCLB/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 等服务 |
| [宝塔面板](https://www.bt.cn/) | 可部署到宝塔面板 |
| [AWS](https://aws.amazon.com/) | 可部署到 AWS CloudFront 等服务 |
| [BytePlus](https://www.byteplus.com/) | 可部署到 BytePlus CDN 等服务 |
| [Edgio](https://edg.io/) | 可部署到 Edgio Applications 等服务 |
</details>

View File

@ -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 |
</details>

1
go.mod
View File

@ -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

2
go.sum
View File

@ -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=

View File

@ -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
}

View File

@ -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"`

View File

@ -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")
@ -83,15 +84,18 @@ type DeployProviderType string
*/
const (
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")
@ -108,6 +112,7 @@ const (
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")

View File

@ -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
}

View File

@ -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
}

View File

@ -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)
})
}

View File

@ -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),

View File

@ -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
}

View File

@ -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)
})
}

View File

@ -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")
// 资源类型:部署到指定监听器。

View File

@ -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")
}

View File

@ -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,

View File

@ -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
}

26
internal/pkg/vendors/btpanel-sdk/api.go vendored Normal file
View File

@ -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
}

View File

@ -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, &params)
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
}

View File

@ -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

View File

@ -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)
})
}

File diff suppressed because one or more lines are too long

View File

@ -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<AccessFormInstance, AccessFormProps>(({ className,
return <AccessFormAzureConfig {...nestedFormProps} />;
case ACCESS_PROVIDERS.BAIDUCLOUD:
return <AccessFormBaiduCloudConfig {...nestedFormProps} />;
case ACCESS_PROVIDERS.BAOTAPANEL:
return <AccessFormBaotaPanelConfig {...nestedFormProps} />;
case ACCESS_PROVIDERS.BYTEPLUS:
return <AccessFormBytePlusConfig {...nestedFormProps} />;
case ACCESS_PROVIDERS.CLOUDFLARE:

View File

@ -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<AccessConfigForBaotaPanel>;
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<typeof formSchema>) => {
onValuesChange?.(values);
};
return (
<Form
form={formInst}
disabled={disabled}
initialValues={initialValues ?? initFormModel()}
layout="vertical"
name={formName}
onValuesChange={handleFormChange}
>
<Form.Item
name="apiUrl"
label={t("access.form.baotapanel_api_url.label")}
rules={[formRule]}
tooltip={<span dangerouslySetInnerHTML={{ __html: t("access.form.baotapanel_api_url.tooltip") }}></span>}
>
<Input placeholder={t("access.form.baotapanel_api_url.placeholder")} />
</Form.Item>
<Form.Item
name="apiKey"
label={t("access.form.baotapanel_api_key.label")}
rules={[formRule]}
tooltip={<span dangerouslySetInnerHTML={{ __html: t("access.form.baotapanel_api_key.tooltip") }}></span>}
>
<Input.Password autoComplete="new-password" placeholder={t("access.form.baotapanel_api_key.placeholder")} />
</Form.Item>
</Form>
);
};
export default AccessFormBaotaPanelConfig;

View File

@ -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<string>();
const keywordInputRef = useRef<InputRef>(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 (
<div className={className} style={style}>
<Input.Search placeholder={placeholder} onChange={(e) => setKeyword(e.target.value.trim())} />
<Input.Search ref={keywordInputRef} placeholder={placeholder} onChange={(e) => setKeyword(e.target.value.trim())} />
<div className="mt-4">
<Show when={filteredProviders.length > 0} fallback={<Empty image={Empty.PRESENTED_IMAGE_SIMPLE} />}>

View File

@ -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<string>();
const keywordInputRef = useRef<InputRef>(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 (
<div className={className} style={style}>
<Input.Search placeholder={placeholder} onChange={(e) => setKeyword(e.target.value.trim())} />
<Input.Search ref={keywordInputRef} placeholder={placeholder} onChange={(e) => setKeyword(e.target.value.trim())} />
<div className="mt-4">
<Show when={filteredProviders.length > 0} fallback={<Empty image={Empty.PRESENTED_IMAGE_SIMPLE} />}>

View File

@ -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<DeployNodeConfigFormInstance, DeployNode
switch (fieldProvider) {
case DEPLOY_PROVIDERS.ALIYUN_ALB:
return <DeployNodeConfigFormAliyunALBConfig {...nestedFormProps} />;
case DEPLOY_PROVIDERS.ALIYUN_CAS_DEPLOY:
return <DeployNodeConfigFormAliyunCASDeployConfig {...nestedFormProps} />;
case DEPLOY_PROVIDERS.ALIYUN_CLB:
return <DeployNodeConfigFormAliyunCLBConfig {...nestedFormProps} />;
case DEPLOY_PROVIDERS.ALIYUN_CDN:
return <DeployNodeConfigFormAliyunCDNConfig {...nestedFormProps} />;
case DEPLOY_PROVIDERS.ALIYUN_DCDN:
return <DeployNodeConfigFormAliyunDCDNConfig {...nestedFormProps} />;
case DEPLOY_PROVIDERS.ALIYUN_ESA:
return <DeployNodeConfigFormAliyunESAConfig {...nestedFormProps} />;
case DEPLOY_PROVIDERS.ALIYUN_LIVE:
return <DeployNodeConfigFormAliyunLiveConfig {...nestedFormProps} />;
case DEPLOY_PROVIDERS.ALIYUN_NLB:
@ -141,6 +149,8 @@ const DeployNodeConfigForm = forwardRef<DeployNodeConfigFormInstance, DeployNode
return <DeployNodeConfigFormAWSCloudFrontConfig {...nestedFormProps} />;
case DEPLOY_PROVIDERS.BAIDUCLOUD_CDN:
return <DeployNodeConfigFormBaiduCloudCDNConfig {...nestedFormProps} />;
case DEPLOY_PROVIDERS.BAOTAPANEL_SITE:
return <DeployNodeConfigFormBaotaPanelSiteConfig {...nestedFormProps} />;
case DEPLOY_PROVIDERS.BYTEPLUS_CDN:
return <DeployNodeConfigFormBytePlusCDNConfig {...nestedFormProps} />;
case DEPLOY_PROVIDERS.DOGECLOUD_CDN:
@ -173,6 +183,8 @@ const DeployNodeConfigForm = forwardRef<DeployNodeConfigFormInstance, DeployNode
return <DeployNodeConfigFormTencentCloudECDNConfig {...nestedFormProps} />;
case DEPLOY_PROVIDERS.TENCENTCLOUD_EO:
return <DeployNodeConfigFormTencentCloudEOConfig {...nestedFormProps} />;
case DEPLOY_PROVIDERS.TENCENTCLOUD_SSL_DEPLOY:
return <DeployNodeConfigFormTencentCloudSSLDeployConfig {...nestedFormProps} />;
case DEPLOY_PROVIDERS.UCLOUD_UCDN:
return <DeployNodeConfigFormUCloudUCDNConfig {...nestedFormProps} />;
case DEPLOY_PROVIDERS.UCLOUD_US3:
@ -261,7 +273,7 @@ const DeployNodeConfigForm = forwardRef<DeployNodeConfigFormInstance, DeployNode
<Form className={className} style={style} {...formProps} disabled={disabled} layout="vertical" scrollToFirstError onValuesChange={handleFormChange}>
<Show
when={!!fieldProvider}
fallback={<DeployProviderPicker placeholder={t("workflow_node.deploy.search.provider.placeholder")} onSelect={handleProviderPick} />}
fallback={<DeployProviderPicker autoFocus placeholder={t("workflow_node.deploy.search.provider.placeholder")} onSelect={handleProviderPick} />}
>
<Form.Item name="provider" label={t("workflow_node.deploy.form.provider.label")} rules={[formRule]}>
<DeployProviderSelect

View File

@ -0,0 +1,235 @@
import { memo } from "react";
import { useTranslation } from "react-i18next";
import { FormOutlined as FormOutlinedIcon } from "@ant-design/icons";
import { Alert, Button, Form, type FormInstance, Input, Space } from "antd";
import { createSchemaFieldRule } from "antd-zod";
import { z } from "zod";
import ModalForm from "@/components/ModalForm";
import MultipleInput from "@/components/MultipleInput";
import { useAntdForm } from "@/hooks";
type DeployNodeConfigFormAliyunCASDeployConfigFieldValues = Nullish<{
region: string;
resourceIds: string;
contactIds?: string;
}>;
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<string>("resourceIds", formInst);
const fieldContactIds = Form.useWatch<string>("contactIds", formInst);
const handleFormChange = (_: unknown, values: z.infer<typeof formSchema>) => {
onValuesChange?.(values);
};
return (
<Form
form={formInst}
disabled={disabled}
initialValues={initialValues ?? initFormModel()}
layout="vertical"
name={formName}
onValuesChange={handleFormChange}
>
<Form.Item
name="region"
label={t("workflow_node.deploy.form.aliyun_cas_deploy_region.label")}
rules={[formRule]}
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.aliyun_cas_deploy_region.tooltip") }}></span>}
>
<Input placeholder={t("workflow_node.deploy.form.aliyun_cas_deploy_region.placeholder")} />
</Form.Item>
<Form.Item
label={t("workflow_node.deploy.form.aliyun_cas_deploy_resource_ids.label")}
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.aliyun_cas_deploy_resource_ids.tooltip") }}></span>}
>
<Space.Compact style={{ width: "100%" }}>
<Form.Item name="resourceIds" noStyle rules={[formRule]}>
<Input
allowClear
disabled={disabled}
value={fieldResourceIds}
placeholder={t("workflow_node.deploy.form.aliyun_cas_deploy_resource_ids.placeholder")}
onChange={(e) => {
formInst.setFieldValue("resourceIds", e.target.value);
}}
/>
</Form.Item>
<ResourceIdsModalInput
value={fieldResourceIds}
trigger={
<Button disabled={disabled}>
<FormOutlinedIcon />
</Button>
}
onChange={(value) => {
formInst.setFieldValue("resourceIds", value);
}}
/>
</Space.Compact>
</Form.Item>
<Form.Item
label={t("workflow_node.deploy.form.aliyun_cas_deploy_contact_ids.label")}
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.aliyun_cas_deploy_contact_ids.tooltip") }}></span>}
>
<Space.Compact style={{ width: "100%" }}>
<Form.Item name="contactIds" noStyle rules={[formRule]}>
<Input
allowClear
disabled={disabled}
value={fieldContactIds}
placeholder={t("workflow_node.deploy.form.aliyun_cas_deploy_contact_ids.placeholder")}
onChange={(e) => {
formInst.setFieldValue("contactIds", e.target.value);
}}
/>
</Form.Item>
<ContactIdsModalInput
value={fieldContactIds}
trigger={
<Button disabled={disabled}>
<FormOutlinedIcon />
</Button>
}
onChange={(value) => {
formInst.setFieldValue("contactIds", value);
}}
/>
</Space.Compact>
</Form.Item>
<Form.Item>
<Alert type="info" message={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.aliyun_cas_deploy.guide") }}></span>} />
</Form.Item>
</Form>
);
};
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 (
<ModalForm
{...formProps}
layout="vertical"
form={formInst}
modalProps={{ destroyOnClose: true }}
title={t("workflow_node.deploy.form.aliyun_cas_deploy_resource_ids.multiple_input_modal.title")}
trigger={trigger}
validateTrigger="onSubmit"
width={480}
>
<Form.Item name="resourceIds" rules={[formRule]}>
<MultipleInput placeholder={t("workflow_node.deploy.form.aliyun_cas_deploy_resource_ids.multiple_input_modal.placeholder")} />
</Form.Item>
</ModalForm>
);
});
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 (
<ModalForm
{...formProps}
layout="vertical"
form={formInst}
modalProps={{ destroyOnClose: true }}
title={t("workflow_node.deploy.form.aliyun_cas_deploy_contact_ids.multiple_input_modal.title")}
trigger={trigger}
validateTrigger="onSubmit"
width={480}
>
<Form.Item name="contactIds" rules={[formRule]}>
<MultipleInput placeholder={t("workflow_node.deploy.form.aliyun_cas_deploy_contact_ids.multiple_input_modal.placeholder")} />
</Form.Item>
</ModalForm>
);
});
export default DeployNodeConfigFormAliyunCASDeployConfig;

View File

@ -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<typeof formSchema>) => {
onValuesChange?.(values);
};
return (
<Form
form={formInst}
disabled={disabled}
initialValues={initialValues ?? initFormModel()}
layout="vertical"
name={formName}
onValuesChange={handleFormChange}
>
<Form.Item
name="region"
label={t("workflow_node.deploy.form.aliyun_esa_region.label")}
rules={[formRule]}
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.aliyun_esa_region.tooltip") }}></span>}
>
<Input placeholder={t("workflow_node.deploy.form.aliyun_esa_region.placeholder")} />
</Form.Item>
<Form.Item
name="siteId"
label={t("workflow_node.deploy.form.aliyun_esa_site_id.label")}
rules={[formRule]}
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.aliyun_esa_site_id.tooltip") }}></span>}
>
<Input placeholder={t("workflow_node.deploy.form.aliyun_esa_site_id.placeholder")} />
</Form.Item>
</Form>
);
};
export default DeployNodeConfigFormAliyunESAConfig;

View File

@ -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<typeof formSchema>) => {
onValuesChange?.(values);
};
return (
<Form
form={formInst}
disabled={disabled}
initialValues={initialValues ?? initFormModel()}
layout="vertical"
name={formName}
onValuesChange={handleFormChange}
>
<Form.Item
name="siteName"
label={t("workflow_node.deploy.form.baotapanel_site_name.label")}
rules={[formRule]}
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.baotapanel_site_name.tooltip") }}></span>}
>
<Input placeholder={t("workflow_node.deploy.form.baotapanel_site_name.placeholder")} />
</Form.Item>
</Form>
);
};
export default DeployNodeConfigFormBaotaPanelSiteConfig;

View File

@ -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 = ({
>
<Form.Item name="resourceType" label={t("workflow_node.deploy.form.tencentcloud_clb_resource_type.label")} rules={[formRule]}>
<Select placeholder={t("workflow_node.deploy.form.tencentcloud_clb_resource_type.placeholder")}>
<Select.Option key={RESOURCE_TYPE_SSLDEPLOY} value={RESOURCE_TYPE_SSLDEPLOY}>
<Select.Option key={RESOURCE_TYPE_VIA_SSLDEPLOY} value={RESOURCE_TYPE_VIA_SSLDEPLOY}>
{t("workflow_node.deploy.form.tencentcloud_clb_resource_type.option.ssl_deploy.label")}
</Select.Option>
<Select.Option key={RESOURCE_TYPE_LOADBALANCER} value={RESOURCE_TYPE_LOADBALANCER}>
@ -123,7 +123,9 @@ const DeployNodeConfigFormTencentCloudCLBConfig = ({
</Form.Item>
<Show
when={fieldResourceType === RESOURCE_TYPE_SSLDEPLOY || fieldResourceType === RESOURCE_TYPE_LISTENER || fieldResourceType === RESOURCE_TYPE_RULEDOMAIN}
when={
fieldResourceType === RESOURCE_TYPE_VIA_SSLDEPLOY || fieldResourceType === RESOURCE_TYPE_LISTENER || fieldResourceType === RESOURCE_TYPE_RULEDOMAIN
}
>
<Form.Item
name="listenerId"
@ -135,7 +137,7 @@ const DeployNodeConfigFormTencentCloudCLBConfig = ({
</Form.Item>
</Show>
<Show when={fieldResourceType === RESOURCE_TYPE_SSLDEPLOY}>
<Show when={fieldResourceType === RESOURCE_TYPE_VIA_SSLDEPLOY}>
<Form.Item
name="domain"
label={t("workflow_node.deploy.form.tencentcloud_clb_snidomain.label")}

View File

@ -0,0 +1,159 @@
import { memo } from "react";
import { useTranslation } from "react-i18next";
import { FormOutlined as FormOutlinedIcon } from "@ant-design/icons";
import { Alert, Button, Form, type FormInstance, Input, Space } from "antd";
import { createSchemaFieldRule } from "antd-zod";
import { z } from "zod";
import ModalForm from "@/components/ModalForm";
import MultipleInput from "@/components/MultipleInput";
import { useAntdForm } from "@/hooks";
type DeployNodeConfigFormTencentCloudSSLDeployConfigFieldValues = Nullish<{
region: string;
resourceType: string;
resourceIds: string;
}>;
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<string>("resourceIds", formInst);
const handleFormChange = (_: unknown, values: z.infer<typeof formSchema>) => {
onValuesChange?.(values);
};
return (
<Form
form={formInst}
disabled={disabled}
initialValues={initialValues ?? initFormModel()}
layout="vertical"
name={formName}
onValuesChange={handleFormChange}
>
<Form.Item
name="region"
label={t("workflow_node.deploy.form.tencentcloud_ssl_deploy_region.label")}
rules={[formRule]}
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.tencentcloud_ssl_deploy_region.tooltip") }}></span>}
>
<Input placeholder={t("workflow_node.deploy.form.tencentcloud_ssl_deploy_region.placeholder")} />
</Form.Item>
<Form.Item
label={t("workflow_node.deploy.form.tencentcloud_ssl_deploy_resource_ids.label")}
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.tencentcloud_ssl_deploy_resource_ids.tooltip") }}></span>}
>
<Space.Compact style={{ width: "100%" }}>
<Form.Item name="resourceIds" noStyle rules={[formRule]}>
<Input
allowClear
disabled={disabled}
value={fieldResourceIds}
placeholder={t("workflow_node.deploy.form.tencentcloud_ssl_deploy_resource_ids.placeholder")}
onChange={(e) => {
formInst.setFieldValue("resourceIds", e.target.value);
}}
/>
</Form.Item>
<ResourceIdsModalInput
value={fieldResourceIds}
trigger={
<Button disabled={disabled}>
<FormOutlinedIcon />
</Button>
}
onChange={(value) => {
formInst.setFieldValue("resourceIds", value);
}}
/>
</Space.Compact>
</Form.Item>
<Form.Item>
<Alert type="info" message={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.tencentcloud_ssl_deploy.guide") }}></span>} />
</Form.Item>
</Form>
);
};
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 (
<ModalForm
{...formProps}
layout="vertical"
form={formInst}
modalProps={{ destroyOnClose: true }}
title={t("workflow_node.deploy.form.tencentcloud_ssl_deploy_resource_ids.multiple_input_modal.title")}
trigger={trigger}
validateTrigger="onSubmit"
width={480}
>
<Form.Item name="resourceIds" rules={[formRule]}>
<MultipleInput placeholder={t("workflow_node.deploy.form.tencentcloud_ssl_deploy_resource_ids.multiple_input_modal.placeholder")} />
</Form.Item>
</ModalForm>
);
});
export default DeployNodeConfigFormTencentCloudSSLDeployConfig;

View File

@ -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) {

View File

@ -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;

View File

@ -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<AccessProvider["type"] | string, AccessProv
[ACCESS_PROVIDERS.DOGECLOUD, "common.provider.dogecloud", "/imgs/providers/dogecloud.svg", ACCESS_USAGES.DEPLOY],
[ACCESS_PROVIDERS.BYTEPLUS, "common.provider.byteplus", "/imgs/providers/byteplus.svg", ACCESS_USAGES.DEPLOY],
[ACCESS_PROVIDERS.UCLOUD, "common.provider.ucloud", "/imgs/providers/ucloud.svg", ACCESS_USAGES.DEPLOY],
[ACCESS_PROVIDERS.BAOTAPANEL, "common.provider.baotapanel", "/imgs/providers/baotapanel.svg", ACCESS_USAGES.DEPLOY],
[ACCESS_PROVIDERS.EDGIO, "common.provider.edgio", "/imgs/providers/edgio.svg", ACCESS_USAGES.DEPLOY],
[ACCESS_PROVIDERS.AZURE, "common.provider.azure", "/imgs/providers/azure.svg", ACCESS_USAGES.APPLY],
[ACCESS_PROVIDERS.CLOUDFLARE, "common.provider.cloudflare", "/imgs/providers/cloudflare.svg", ACCESS_USAGES.APPLY],
@ -176,15 +178,18 @@ export const applyDNSProvidersMap: Map<ApplyDNSProvider["type"] | string, ApplyD
*/
export const DEPLOY_PROVIDERS = Object.freeze({
ALIYUN_ALB: `${ACCESS_PROVIDERS.ALIYUN}-alb`,
ALIYUN_CAS_DEPLOY: `${ACCESS_PROVIDERS.ALIYUN}-casdeploy`,
ALIYUN_CDN: `${ACCESS_PROVIDERS.ALIYUN}-cdn`,
ALIYUN_CLB: `${ACCESS_PROVIDERS.ALIYUN}-clb`,
ALIYUN_DCDN: `${ACCESS_PROVIDERS.ALIYUN}-dcdn`,
ALIYUN_ESA: `${ACCESS_PROVIDERS.ALIYUN}-esa`,
ALIYUN_LIVE: `${ACCESS_PROVIDERS.ALIYUN}-live`,
ALIYUN_NLB: `${ACCESS_PROVIDERS.ALIYUN}-nlb`,
ALIYUN_OSS: `${ACCESS_PROVIDERS.ALIYUN}-oss`,
ALIYUN_WAF: `${ACCESS_PROVIDERS.ALIYUN}-waf`,
AWS_CLOUDFRONT: `${ACCESS_PROVIDERS.AWS}-cloudfront`,
BAIDUCLOUD_CDN: `${ACCESS_PROVIDERS.BAIDUCLOUD}-cdn`,
BAOTAPANEL_SITE: `${ACCESS_PROVIDERS.BAOTAPANEL}-site`,
BYTEPLUS_CDN: `${ACCESS_PROVIDERS.BYTEPLUS}-cdn`,
DOGECLOUD_CDN: `${ACCESS_PROVIDERS.DOGECLOUD}-cdn`,
EDGIO_APPLICATIONS: `${ACCESS_PROVIDERS.EDGIO}-applications`,
@ -201,6 +206,7 @@ export const DEPLOY_PROVIDERS = Object.freeze({
TENCENTCLOUD_CSS: `${ACCESS_PROVIDERS.TENCENTCLOUD}-css`,
TENCENTCLOUD_ECDN: `${ACCESS_PROVIDERS.TENCENTCLOUD}-ecdn`,
TENCENTCLOUD_EO: `${ACCESS_PROVIDERS.TENCENTCLOUD}-eo`,
TENCENTCLOUD_SSL_DEPLOY: `${ACCESS_PROVIDERS.TENCENTCLOUD}-ssldeploy`,
UCLOUD_UCDN: `${ACCESS_PROVIDERS.UCLOUD}-ucdn`,
UCLOUD_US3: `${ACCESS_PROVIDERS.UCLOUD}-us3`,
VOLCENGINE_CDN: `${ACCESS_PROVIDERS.VOLCENGINE}-cdn`,
@ -233,17 +239,20 @@ export const deployProvidersMap: Map<DeployProvider["type"] | string, DeployProv
[DEPLOY_PROVIDERS.ALIYUN_OSS, "common.provider.aliyun.oss"],
[DEPLOY_PROVIDERS.ALIYUN_CDN, "common.provider.aliyun.cdn"],
[DEPLOY_PROVIDERS.ALIYUN_DCDN, "common.provider.aliyun.dcdn"],
[DEPLOY_PROVIDERS.ALIYUN_ESA, "common.provider.aliyun.esa"],
[DEPLOY_PROVIDERS.ALIYUN_CLB, "common.provider.aliyun.clb"],
[DEPLOY_PROVIDERS.ALIYUN_ALB, "common.provider.aliyun.alb"],
[DEPLOY_PROVIDERS.ALIYUN_NLB, "common.provider.aliyun.nlb"],
[DEPLOY_PROVIDERS.ALIYUN_WAF, "common.provider.aliyun.waf"],
[DEPLOY_PROVIDERS.ALIYUN_LIVE, "common.provider.aliyun.live"],
[DEPLOY_PROVIDERS.ALIYUN_CAS_DEPLOY, "common.provider.aliyun.cas_deploy"],
[DEPLOY_PROVIDERS.TENCENTCLOUD_COS, "common.provider.tencentcloud.cos"],
[DEPLOY_PROVIDERS.TENCENTCLOUD_CDN, "common.provider.tencentcloud.cdn"],
[DEPLOY_PROVIDERS.TENCENTCLOUD_ECDN, "common.provider.tencentcloud.ecdn"],
[DEPLOY_PROVIDERS.TENCENTCLOUD_EO, "common.provider.tencentcloud.eo"],
[DEPLOY_PROVIDERS.TENCENTCLOUD_CLB, "common.provider.tencentcloud.clb"],
[DEPLOY_PROVIDERS.TENCENTCLOUD_CSS, "common.provider.tencentcloud.css"],
[DEPLOY_PROVIDERS.TENCENTCLOUD_SSL_DEPLOY, "common.provider.tencentcloud.ssl_deploy"],
[DEPLOY_PROVIDERS.HUAWEICLOUD_CDN, "common.provider.huaweicloud.cdn"],
[DEPLOY_PROVIDERS.HUAWEICLOUD_ELB, "common.provider.huaweicloud.elb"],
[DEPLOY_PROVIDERS.BAIDUCLOUD_CDN, "common.provider.baiducloud.cdn"],
@ -259,6 +268,7 @@ export const deployProvidersMap: Map<DeployProvider["type"] | string, DeployProv
[DEPLOY_PROVIDERS.UCLOUD_US3, "common.provider.ucloud.us3"],
[DEPLOY_PROVIDERS.UCLOUD_UCDN, "common.provider.ucloud.ucdn"],
[DEPLOY_PROVIDERS.AWS_CLOUDFRONT, "common.provider.aws.cloudfront"],
[DEPLOY_PROVIDERS.BAOTAPANEL_SITE, "common.provider.baotapanel.site"],
[DEPLOY_PROVIDERS.EDGIO_APPLICATIONS, "common.provider.edgio.applications"],
].map(([type, name]) => [
type,

View File

@ -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 <a href=\"https://intl.cloud.baidu.com/doc/Reference/s/jjwvz2e3p-en\" target=\"_blank\">https://intl.cloud.baidu.com/doc/Reference/s/jjwvz2e3p-en</a>",
"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 <a href=\"https://www.bt.cn/bbs/thread-20376-1-1.html\" target=\"_blank\">https://www.bt.cn/bbs/thread-20376-1-1.html</a>",
"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 <a href=\"https://www.bt.cn/bbs/thread-113890-1-1.html\" target=\"_blank\">https://www.bt.cn/bbs/thread-113890-1-1.html</a>",
"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 <a href=\"https://docs.byteplus.com/en/docs/byteplus-platform/docs-managing-keys\" target=\"_blank\">https://docs.byteplus.com/en/docs/byteplus-platform/docs-managing-keys</a>",
@ -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 <a href=\"https://kubernetes.io/docs/concepts/configuration/organize-cluster-access-kubeconfig/\" target=\"_blank\">https://kubernetes.io/docs/concepts/configuration/organize-cluster-access-kubeconfig/</a><br><br>Leave blank to use the Pod's ServiceAccount.",
"access.form.k8s_kubeconfig.tooltip": "For more information, see <a href=\"https://kubernetes.io/docs/concepts/configuration/organize-cluster-access-kubeconfig/\" target=\"_blank\">https://kubernetes.io/docs/concepts/configuration/organize-cluster-access-kubeconfig/</a><br><br>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 <a href=\"https://www.name.com/account/settings/api\" target=\"_blank\">https://www.name.com/account/settings/api</a>",

View File

@ -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)",

View File

@ -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 <a href=\"https://bark.day.app/\" target=\"_blank\">https://bark.day.app/</a><br><br>Leave blank to use the default Bark server.",
"settings.notification.channel.form.bark_server_url.tooltip": "For more information, see <a href=\"https://bark.day.app/\" target=\"_blank\">https://bark.day.app/</a><br><br>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 <a href=\"https://bark.day.app/\" target=\"_blank\">https://bark.day.app/</a>",

View File

@ -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 <a href=\"https://docs.aws.amazon.com/en_us/general/latest/gr/rande.html#regional-endpoints\" target=\"_blank\">https://docs.aws.amazon.com/en_us/general/latest/gr/rande.html#regional-endpoints</a>",
"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.<br><br>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.<br><br>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.<br><br>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.<br><br>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. <a href=\"https://letsencrypt.org/2019/10/09/onboarding-your-customers-with-lets-encrypt-and-acme/#the-advantages-of-a-cname\" target=\"_blank\">Learn more</a>.",
"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 <a href=\"https://www.alibabacloud.com/help/en/slb/application-load-balancer/product-overview/supported-regions-and-zones\" target=\"_blank\">https://www.alibabacloud.com/help/en/slb/application-load-balancer/product-overview/supported-regions-and-zones</a>",
"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 <a href=\"https://slb.console.aliyun.com/alb\" target=\"_blank\">https://slb.console.aliyun.com/alb</a>",
"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 <a href=\"https://www.alibabacloud.com/help/en/ssl-certificate/developer-reference/endpoints\" target=\"_blank\">https://www.alibabacloud.com/help/en/ssl-certificate/developer-reference/endpoints</a>",
"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 <a href=\"https://www.alibabacloud.com/help/en/ssl-certificate/developer-reference/api-cas-2020-04-07-listcloudresources\" target=\"_blank\">https://www.alibabacloud.com/help/en/ssl-certificate/developer-reference/api-cas-2020-04-07-listcloudresources</a><br><br>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 <a href=\"https://www.alibabacloud.com/help/en/ssl-certificate/developer-reference/api-cas-2020-04-07-listcontact\" target=\"_blank\">https://www.alibabacloud.com/help/en/ssl-certificate/developer-reference/api-cas-2020-04-07-listcontact</a><br><br>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 <a href=\"https://www.alibabacloud.com/help/en/slb/classic-load-balancer/product-overview/regions-that-support-clb\" target=\"_blank\">https://www.alibabacloud.com/help/en/slb/classic-load-balancer/product-overview/regions-that-support-clb</a>",
"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 <a href=\"https://dcdn.console.aliyun.com\" target=\"_blank\">https://dcdn.console.aliyun.com</a>",
"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 <a href=\"https://www.alibabacloud.com/help/en/edge-security-acceleration/esa/api-esa-2024-09-10-endpoint\" target=\"_blank\">https://www.alibabacloud.com/help/en/edge-security-acceleration/esa/api-esa-2024-09-10-endpoint</a>",
"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 <a href=\"https://esa.console.aliyun.com/siteManage/list\" target=\"_blank\">https://esa.console.aliyun.com/siteManage/list</a>",
"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 <a href=\"https://www.alibabacloud.com/help/en/live/product-overview/supported-regions\" target=\"_blank\">https://www.alibabacloud.com/help/en/live/product-overview/supported-regions</a>",
"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 <a href=\"https://www.alibabacloud.com/help/en/slb/network-load-balancer/product-overview/regions-that-support-nlb\" target=\"_blank\">https://www.alibabacloud.com/help/en/slb/network-load-balancer/product-overview/regions-that-support-nlb</a>",
"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 <a href=\"https://slb.console.aliyun.com/nlb\" target=\"_blank\">https://slb.console.aliyun.com/nlb</a>",
"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 <a href=\"https://www.alibabacloud.com/help/en/oss/user-guide/regions-and-endpoints\" target=\"_blank\">https://www.alibabacloud.com/help/en/oss/user-guide/regions-and-endpoints</a>",
"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 <a href=\"https://oss.console.aliyun.com\" target=\"_blank\">https://oss.console.aliyun.com</a>",
"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 <a href=\"https://www.alibabacloud.com/help/en/waf/web-application-firewall-3-0/developer-reference/api-waf-openapi-2021-10-01-endpoint\" target=\"_blank\">https://www.alibabacloud.com/help/en/waf/web-application-firewall-3-0/developer-reference/api-waf-openapi-2021-10-01-endpoint</a>",
"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 <a href=\"https://waf.console.aliyun.com\" target=\"_blank\">https://waf.console.aliyun.com</a>",
"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 <a href=\"https://docs.aws.amazon.com/en_us/general/latest/gr/rande.html#regional-endpoints\" target=\"_blank\">https://docs.aws.amazon.com/en_us/general/latest/gr/rande.html#regional-endpoints</a>",
"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 <a href=\"https://console.bce.baidu.com/cdn\" target=\"_blank\">https://console.bce.baidu.com/cdn</a>",
"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 <a href=\"https://console.byteplus.com/cdn\" target=\"_blank\">https://console.byteplus.com/cdn</a>",
@ -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 <a href=\"https://edgio.app/\" target=\"_blank\">https://edgio.app/</a>",
"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 <a href=\"https://console-intl.huaweicloud.com/apiexplorer/#/endpoint?locale=en-us\" target=\"_blank\">https://console-intl.huaweicloud.com/apiexplorer/#/endpoint</a>",
"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 <a href=\"https://console-intl.huaweicloud.com/apiexplorer/#/endpoint?locale=en-us\" target=\"_blank\">https://console-intl.huaweicloud.com/apiexplorer/#/endpoint</a>",
"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 <a href=\"https://console.tencentcloud.com/cdn\" target=\"_blank\">https://console.tencentcloud.com/cdn</a>",
"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 <a href=\"https://www.tencentcloud.com/document/product/214/13629\" target=\"_blank\">https://www.tencentcloud.com/document/product/214/13629</a>",
"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 <a href=\"https://console.tencentcloud.com/clb\" target=\"_blank\">https://console.tencentcloud.com/clb</a>",
"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 <a href=\"https://www.tencentcloud.com/document/product/436/6224\" target=\"_blank\">https://www.tencentcloud.com/document/product/436/6224</a>",
"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 <a href=\"https://console.tencentcloud.com/edgeone\" target=\"_blank\">https://console.tencentcloud.com/edgeone</a>",
"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 <a href=\"https://www.tencentcloud.com/document/product/1007/36573\" target=\"_blank\">https://www.tencentcloud.com/document/product/1007/36573</a>",
"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 <a href=\"https://cloud.tencent.com.cn/document/product/400/91667\" target=\"_blank\">https://cloud.tencent.com.cn/document/product/400/91667</a>",
"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 <a href=\"https://console.ucloud-global.com/ucdn\" target=\"_blank\">https://console.ucloud-global.com/ucdn</a>",
"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 <a href=\"https://www.ucloud-global.com/en/docs/api/summary/regionlist\" target=\"_blank\">https://www.ucloud-global.com/en/docs/api/summary/regionlist</a>",
"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 <a href=\"https://www.volcengine.com/docs/6406/74892\" target=\"_blank\">https://www.volcengine.com/docs/6406/74892</a>",
"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 <a href=\"https://console.volcengine.com/live\" target=\"_blank\">https://console.volcengine.com/live</a>",
"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 <a href=\"https://www.volcengine.com/docs/6349/107356\" target=\"_blank\">https://www.volcengine.com/docs/6349/107356</a>",
"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",

View File

@ -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": "这是什么?请参阅 <a href=\"https://cloud.baidu.com/doc/Reference/s/jjwvz2e3p\" target=\"_blank\">https://cloud.baidu.com/doc/Reference/s/jjwvz2e3p</a>",
"access.form.baotapanel_api_url.label": "宝塔面板 URL",
"access.form.baotapanel_api_url.placeholder": "请输入宝塔面板 URL",
"access.form.baotapanel_api_url.tooltip": "这是什么?请参阅 <a href=\"https://www.bt.cn/bbs/thread-20376-1-1.html\" target=\"_blank\">https://www.bt.cn/bbs/thread-20376-1-1.html</a>",
"access.form.baotapanel_api_key.label": "宝塔面板接口密钥",
"access.form.baotapanel_api_key.placeholder": "请输入宝塔面板接口密钥",
"access.form.baotapanel_api_key.tooltip": "这是什么?请参阅 <a href=\"https://www.bt.cn/bbs/thread-113890-1-1.html\" target=\"_blank\">https://www.bt.cn/bbs/thread-113890-1-1.html</a>",
"access.form.byteplus_access_key.label": "BytePlus AccessKey",
"access.form.byteplus_access_key.placeholder": "请输入 BytePlus AccessKey",
"access.form.byteplus_access_key.tooltip": "这是什么?请参阅 <a href=\"https://docs.byteplus.com/zh-CN/docs/byteplus-platform/docs-managing-keys\" target=\"_blank\">https://docs.byteplus.com/zh-CN/docs/byteplus-platform/docs-managing-keys</a>",
@ -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 时必填。<br>该字段与密钥文件字段二选一。",
"access.form.ssh_password.tooltip": "使用密码连接到 SSH 时必填。<br>该字段与密钥文件字段二选一,如果同时填写优先使用 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 时必填。<br>该字段与密码字段二选一。",
"access.form.ssh_key.tooltip": "使用 SSH 密钥连接到 SSH 时必填。<br>该字段与密码字段二选一,如果同时填写优先使用 SSH 密钥登录。",
"access.form.ssh_key_passphrase.label": "SSH 密钥口令",
"access.form.ssh_key_passphrase.placeholder": "请输入 SSH 密钥口令",
"access.form.ssh_key_passphrase.tooltip": "使用 SSH 密钥连接到 SSH 时选填。",

View File

@ -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",

View File

@ -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": "这是什么?请参阅 <a href=\"https://docs.aws.amazon.com/zh_cn/general/latest/gr/rande.html#regional-endpoints\" tworkflow_node.applyank\">https://docs.aws.amazon.com/zh_cn/general/latest/gr/rande.html#regional-endpoints</a>",
"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 传播检查的最长时间。如果你不了解此选项的用途,保持默认即可。<br><br>为空时,将使用提供商提供的默认值。",
"workflow_node.apply.form.dns_propagation_timeout.tooltip": "在 ACME DNS-01 认证时等待 DNS 传播检查的最长时间。如果你不了解此选项的用途,保持默认即可。<br><br>不填写时,将使用提供商提供的默认值。",
"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。如果你不了解此选项的用途保持默认即可。<br><br>为空时,将使用提供商提供的默认值。",
"workflow_node.apply.form.dns_ttl.tooltip": "在 ACME DNS-01 认证时 DNS 解析记录的 TTL。如果你不了解此选项的用途保持默认即可。<br><br>不填写时,将使用提供商提供的默认值。",
"workflow_node.apply.form.disable_follow_cname.label": "关闭 CNAME 跟随",
"workflow_node.apply.form.disable_follow_cname.tooltip": "在 ACME DNS-01 认证时是否关闭 CNAME 跟随。如果你不了解该选项的用途,保持默认即可。<a href=\"https://letsencrypt.org/2019/10/09/onboarding-your-customers-with-lets-encrypt-and-acme/#the-advantages-of-a-cname\" target=\"_blank\">点此了解更多</a>。",
"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": "这是什么?请参阅 <a href=\"https://help.aliyun.com/zh/slb/application-load-balancer/product-overview/supported-regions-and-zones\" target=\"_blank\">https://help.aliyun.com/zh/slb/application-load-balancer/product-overview/supported-regions-and-zones</a>",
"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": "这是什么?请参阅 <a href=\"https://slb.console.aliyun.com/alb\" target=\"_blank\">https://slb.console.aliyun.com/alb</a>",
"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": "这是什么?请参阅 <a href=\"https://slb.console.aliyun.com/alb\" target=\"_blank\">https://slb.console.aliyun.com/alb</a><br><br>为空时,将替换监听器的默认证书。",
"workflow_node.deploy.form.aliyun_alb_snidomain.tooltip": "这是什么?请参阅 <a href=\"https://slb.console.aliyun.com/alb\" target=\"_blank\">https://slb.console.aliyun.com/alb</a><br><br>不填写时,将替换监听器的默认证书。",
"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": "这是什么?请参阅 <a href=\"https://help.aliyun.com/zh/ssl-certificate/developer-reference/endpoints\" target=\"_blank\">https://help.aliyun.com/zh/ssl-certificate/developer-reference/endpoints</a>",
"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": "这是什么?请参阅 <a href=\"https://help.aliyun.com/zh/ssl-certificate/developer-reference/api-cas-2020-04-07-listcloudresources\" target=\"_blank\">https://help.aliyun.com/zh/ssl-certificate/developer-reference/api-cas-2020-04-07-listcloudresources</a><br><br>仅支持阿里云产品,注意与各产品本身的实例 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": "这是什么?请参阅 <a href=\"https://help.aliyun.com/zh/ssl-certificate/developer-reference/api-cas-2020-04-07-listcontact\" target=\"_blank\">https://help.aliyun.com/zh/ssl-certificate/developer-reference/api-cas-2020-04-07-listcontact</a><br><br>不填写时,将使用系统联系人列表中的第一个。",
"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": "这是什么?请参阅 <a href=\"https://help.aliyun.com/zh/slb/classic-load-balancer/product-overview/regions-that-support-clb\" target=\"_blank\">https://help.aliyun.com/zh/slb/classic-load-balancer/product-overview/regions-that-support-clb</a>",
"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": "这是什么?请参阅 <a href=\"https://slb.console.aliyun.com/clb\" target=\"_blank\">https://slb.console.aliyun.com/clb</a>",
"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": "这是什么?请参阅 <a href=\"https://slb.console.aliyun.com/clb\" target=\"_blank\">https://slb.console.aliyun.com/clb</a><br><br>为空时,将替换监听器的默认证书。",
"workflow_node.deploy.form.aliyun_clb_snidomain.tooltip": "这是什么?请参阅 <a href=\"https://slb.console.aliyun.com/clb\" target=\"_blank\">https://slb.console.aliyun.com/clb</a><br><br>不填写时,将替换监听器的默认证书。",
"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": "这是什么?请参阅 <a href=\"https://cdn.console.aliyun.com\" target=\"_blank\">https://cdn.console.aliyun.com</a><br><br>泛域名表示形式为:*.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": "这是什么?请参阅 <a href=\"https://dcdn.console.aliyun.com\" target=\"_blank\">https://dcdn.console.aliyun.com</a><br><br>泛域名表示形式为:*.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": "这是什么?请参阅 <a href=\"https://help.aliyun.com/zh/edge-security-acceleration/esa/api-esa-2024-09-10-endpoint\" target=\"_blank\">https://help.aliyun.com/zh/edge-security-acceleration/esa/api-esa-2024-09-10-endpoint</a>",
"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": "这是什么?请参阅 <a href=\"https://esa.console.aliyun.com/siteManage/list\" target=\"_blank\">https://esa.console.aliyun.com/siteManage/list</a>",
"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": "这是什么?请参阅 <a href=\"https://help.aliyun.com/zh/live/product-overview/supported-regions\" target=\"_blank\">https://help.aliyun.com/zh/live/product-overview/supported-regions</a>",
"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": "这是什么?请参阅 <a href=\"https://help.aliyun.com/zh/slb/network-load-balancer/product-overview/regions-that-support-nlb\" target=\"_blank\">https://help.aliyun.com/zh/slb/network-load-balancer/product-overview/regions-that-support-nlb</a>",
"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": "这是什么?请参阅 <a href=\"https://slb.console.aliyun.com/nlb\" target=\"_blank\">https://slb.console.aliyun.com/nlb</a>",
"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": "这是什么?请参阅 <a href=\"https://help.aliyun.com/zh/oss/user-guide/regions-and-endpoints\" target=\"_blank\">https://help.aliyun.com/zh/oss/user-guide/regions-and-endpoints</a>",
"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 <a href=\"https://oss.console.aliyun.com\" target=\"_blank\">https://oss.console.aliyun.com</a>",
"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": "这是什么?请参阅 <a href=\"https://help.aliyun.com/zh/waf/web-application-firewall-3-0/developer-reference/api-waf-openapi-2021-10-01-endpoint\" target=\"_blank\">https://help.aliyun.com/zh/waf/web-application-firewall-3-0/developer-reference/api-waf-openapi-2021-10-01-endpoint</a>",
"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": "这是什么?请参阅 <a href=\"https://waf.console.aliyun.com\" target=\"_blank\">https://waf.console.aliyun.com</a>",
"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": "这是什么?请参阅 <a href=\"https://docs.aws.amazon.com/zh_cn/general/latest/gr/rande.html#regional-endpoints\" tworkflow_node.applyank\">https://docs.aws.amazon.com/zh_cn/general/latest/gr/rande.html#regional-endpoints</a>",
"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": "这是什么?请参阅 <a href=\"https://console.bce.baidu.com/cdn\" target=\"_blank\">https://console.bce.baidu.com/cdn</a><br><br>泛域名表示形式为:*.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": "这是什么?请参阅 <a href=\"https://console.byteplus.com/cdn\" target=\"_blank\">https://console.byteplus.com/cdn</a><br><br>泛域名表示形式为:*.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": "这是什么?请参阅 <a href=\"https://edgio.app/\" target=\"_blank\">https://edgio.app/</a>",
"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": "这是什么?请参阅 <a href=\"https://console.huaweicloud.com/apiexplorer/#/endpoint\" target=\"_blank\">https://console.huaweicloud.com/apiexplorer/#/endpoint</a>",
"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": "这是什么?请参阅 <a href=\"https://console.huaweicloud.com/apiexplorer/#/endpoint\" target=\"_blank\">https://console.huaweicloud.com/apiexplorer/#/endpoint</a>",
"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": "这是什么?请参阅 <a href=\"https://cloud.tencent.com/document/product/214/33415\" target=\"_blank\">https://cloud.tencent.com/document/product/214/33415</a>",
"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": "这是什么?请参阅 <a href=\"https://console.cloud.tencent.com/clb\" target=\"_blank\">https://console.cloud.tencent.com/clb</a>",
"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": "这是什么?请参阅 <a href=\"https://console.cloud.tencent.com/clb\" target=\"_blank\">https://console.cloud.tencent.com/clb</a><br><br>为空时,将替换监听器的默认证书。",
"workflow_node.deploy.form.tencentcloud_clb_snidomain.tooltip": "这是什么?请参阅 <a href=\"https://console.cloud.tencent.com/clb\" target=\"_blank\">https://console.cloud.tencent.com/clb</a><br><br>不填写时,将替换监听器的默认证书。",
"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": "这是什么?请参阅 <a href=\"https://console.cloud.tencent.com/clb\" target=\"_blank\">https://console.cloud.tencent.com/clb</a>",
"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": "这是什么?请参阅 <a href=\"https://cloud.tencent.com/document/product/436/6224\" target=\"_blank\">https://cloud.tencent.com/document/product/436/6224</a>",
"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": "这是什么?请参阅 <a href=\"https://console.cloud.tencent.com/edgeone\" target=\"_blank\">https://console.cloud.tencent.com/edgeone</a>",
"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": "这是什么?请参阅 <a href=\"https://cloud.tencent.com.cn/document/product/400/41659\" target=\"_blank\">https://cloud.tencent.com.cn/document/product/400/41659</a>",
"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": "这是什么?请参阅 <a href=\"https://cloud.tencent.com.cn/document/product/400/91667\" target=\"_blank\">https://cloud.tencent.com.cn/document/product/400/91667</a>",
"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": "这是什么?请参阅 <a href=\"https://cloud.tencent.com.cn/document/product/400/91667\" target=\"_blank\">https://cloud.tencent.com.cn/document/product/400/91667</a><br><br>注意与各产品本身的实例 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": "这是什么?请参阅 <a href=\"https://console.ucloud.cn/ucdn\" target=\"_blank\">https://console.ucloud.cn/ucdn</a>",
"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": "这是什么?请参阅 <a href=\"https://docs.ucloud.cn/api/summary/regionlist\" target=\"_blank\">https://docs.ucloud.cn/api/summary/regionlist</a>",
"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": "这是什么?请参阅 <a href=\"https://www.volcengine.com/docs/6406/74892\" target=\"_blank\">https://www.volcengine.com/docs/6406/74892</a>",
"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": "这是什么?请参阅 <a href=\"https://console.volcengine.com/live\" target=\"_blank\">https://console.volcengine.com/live</a><br><br>泛域名表示形式为:*.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": "这是什么?请参阅 <a href=\"https://www.volcengine.com/docs/6349/107356\" target=\"_blank\">https://www.volcengine.com/docs/6349/107356</a>",
"workflow_node.deploy.form.volcengine_tos_bucket.label": "火山引擎 TOS 存储桶名",
"workflow_node.deploy.form.volcengine_tos_bucket.placeholder": "请输入火山引擎 TOS 存储桶名",