diff --git a/internal/deployer/providers.go b/internal/deployer/providers.go
index c6238aff..5957fded 100644
--- a/internal/deployer/providers.go
+++ b/internal/deployer/providers.go
@@ -24,6 +24,7 @@ import (
pAWSACM "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/aws-acm"
pAWSCloudFront "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/aws-cloudfront"
pAzureKeyVault "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/azure-keyvault"
+ pBaiduCloudBLB "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/baiducloud-blb"
pBaiduCloudCDN "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/baiducloud-cdn"
pBaishanCDN "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/baishan-cdn"
pBaotaPanelConsole "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/baotapanel-console"
@@ -303,7 +304,7 @@ func createDeployer(options *deployerOptions) (deployer.Deployer, error) {
}
}
- case domain.DeployProviderTypeBaiduCloudCDN:
+ case domain.DeployProviderTypeBaiduCloudBLB, domain.DeployProviderTypeBaiduCloudCDN:
{
access := domain.AccessConfigForBaiduCloud{}
if err := maputil.Populate(options.ProviderAccessConfig, &access); err != nil {
@@ -311,6 +312,18 @@ func createDeployer(options *deployerOptions) (deployer.Deployer, error) {
}
switch options.Provider {
+ case domain.DeployProviderTypeBaiduCloudBLB:
+ deployer, err := pBaiduCloudBLB.NewDeployer(&pBaiduCloudBLB.DeployerConfig{
+ AccessKeyId: access.AccessKeyId,
+ SecretAccessKey: access.SecretAccessKey,
+ Region: maputil.GetString(options.ProviderDeployConfig, "region"),
+ ResourceType: pBaiduCloudBLB.ResourceType(maputil.GetString(options.ProviderDeployConfig, "resourceType")),
+ LoadbalancerId: maputil.GetString(options.ProviderDeployConfig, "loadbalancerId"),
+ ListenerPort: maputil.GetInt32(options.ProviderDeployConfig, "listenerPort"),
+ Domain: maputil.GetString(options.ProviderDeployConfig, "domain"),
+ })
+ return deployer, err
+
case domain.DeployProviderTypeBaiduCloudCDN:
deployer, err := pBaiduCloudCDN.NewDeployer(&pBaiduCloudCDN.DeployerConfig{
AccessKeyId: access.AccessKeyId,
diff --git a/internal/domain/provider.go b/internal/domain/provider.go
index af877778..6cc229a1 100644
--- a/internal/domain/provider.go
+++ b/internal/domain/provider.go
@@ -135,6 +135,7 @@ const (
DeployProviderTypeAWSACM = DeployProviderType("aws-acm")
DeployProviderTypeAWSCloudFront = DeployProviderType("aws-cloudfront")
DeployProviderTypeAzureKeyVault = DeployProviderType("azure-keyvault")
+ DeployProviderTypeBaiduCloudBLB = DeployProviderType("baiducloud-blb")
DeployProviderTypeBaiduCloudCDN = DeployProviderType("baiducloud-cdn")
DeployProviderTypeBaishanCDN = DeployProviderType("baishan-cdn")
DeployProviderTypeBaotaPanelConsole = DeployProviderType("baotapanel-console")
diff --git a/internal/pkg/core/deployer/providers/aliyun-clb/aliyun_clb_test.go b/internal/pkg/core/deployer/providers/aliyun-clb/aliyun_clb_test.go
index a845bf86..f688edf9 100644
--- a/internal/pkg/core/deployer/providers/aliyun-clb/aliyun_clb_test.go
+++ b/internal/pkg/core/deployer/providers/aliyun-clb/aliyun_clb_test.go
@@ -46,7 +46,7 @@ Shell command to run this test:
--CERTIMATE_DEPLOYER_ALIYUNCLB_REGION="cn-hangzhou" \
--CERTIMATE_DEPLOYER_ALIYUNCLB_LOADBALANCERID="your-clb-instance-id" \
--CERTIMATE_DEPLOYER_ALIYUNCLB_LISTENERPORT=443 \
- --CERTIMATE_DEPLOYER_ALIYUNCLB_DOMAIN="your-alb-sni-domain"
+ --CERTIMATE_DEPLOYER_ALIYUNCLB_DOMAIN="your-clb-sni-domain"
*/
func TestDeploy(t *testing.T) {
flag.Parse()
diff --git a/internal/pkg/core/deployer/providers/baiducloud-blb/baiducloud_blb.go b/internal/pkg/core/deployer/providers/baiducloud-blb/baiducloud_blb.go
new file mode 100644
index 00000000..1c0fe371
--- /dev/null
+++ b/internal/pkg/core/deployer/providers/baiducloud-blb/baiducloud_blb.go
@@ -0,0 +1,324 @@
+package baiducloudblb
+
+import (
+ "context"
+ "errors"
+ "fmt"
+ "log/slog"
+ "strconv"
+ "strings"
+
+ bceblb "github.com/baidubce/bce-sdk-go/services/blb"
+ xerrors "github.com/pkg/errors"
+
+ "github.com/usual2970/certimate/internal/pkg/core/deployer"
+ "github.com/usual2970/certimate/internal/pkg/core/uploader"
+ uploadersp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/baiducloud-cas"
+ "github.com/usual2970/certimate/internal/pkg/utils/sliceutil"
+)
+
+type DeployerConfig struct {
+ // 百度智能云 AccessKeyId。
+ AccessKeyId string `json:"accessKeyId"`
+ // 百度智能云 SecretAccessKey。
+ SecretAccessKey string `json:"secretAccessKey"`
+ // 百度智能云区域。
+ Region string `json:"region"`
+ // 部署资源类型。
+ ResourceType ResourceType `json:"resourceType"`
+ // 负载均衡实例 ID。
+ // 部署资源类型为 [RESOURCE_TYPE_LOADBALANCER]、[RESOURCE_TYPE_LISTENER] 时必填。
+ LoadbalancerId string `json:"loadbalancerId,omitempty"`
+ // 负载均衡监听端口。
+ // 部署资源类型为 [RESOURCE_TYPE_LISTENER] 时必填。
+ ListenerPort int32 `json:"listenerPort,omitempty"`
+ // SNI 域名(支持泛域名)。
+ // 部署资源类型为 [RESOURCE_TYPE_LOADBALANCER]、[RESOURCE_TYPE_LISTENER] 时选填。
+ Domain string `json:"domain,omitempty"`
+}
+
+type DeployerProvider struct {
+ config *DeployerConfig
+ logger *slog.Logger
+ sdkClient *bceblb.Client
+ sslUploader uploader.Uploader
+}
+
+var _ deployer.Deployer = (*DeployerProvider)(nil)
+
+func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) {
+ if config == nil {
+ panic("config is nil")
+ }
+
+ client, err := createSdkClient(config.AccessKeyId, config.SecretAccessKey, config.Region)
+ if err != nil {
+ return nil, xerrors.Wrap(err, "failed to create sdk client")
+ }
+
+ uploader, err := uploadersp.NewUploader(&uploadersp.UploaderConfig{
+ AccessKeyId: config.AccessKeyId,
+ SecretAccessKey: config.SecretAccessKey,
+ })
+ if err != nil {
+ return nil, xerrors.Wrap(err, "failed to create ssl uploader")
+ }
+
+ return &DeployerProvider{
+ config: config,
+ logger: slog.Default(),
+ sdkClient: client,
+ sslUploader: uploader,
+ }, nil
+}
+
+func (d *DeployerProvider) WithLogger(logger *slog.Logger) deployer.Deployer {
+ if logger == nil {
+ d.logger = slog.Default()
+ } else {
+ d.logger = logger
+ }
+ return d
+}
+
+func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) {
+ // 上传证书到 CAS
+ upres, err := d.sslUploader.Upload(ctx, certPem, privkeyPem)
+ if err != nil {
+ return nil, xerrors.Wrap(err, "failed to upload certificate file")
+ } else {
+ d.logger.Info("ssl certificate uploaded", slog.Any("result", upres))
+ }
+
+ // 根据部署资源类型决定部署方式
+ switch d.config.ResourceType {
+ case RESOURCE_TYPE_LOADBALANCER:
+ if err := d.deployToLoadbalancer(ctx, upres.CertId); err != nil {
+ return nil, err
+ }
+
+ case RESOURCE_TYPE_LISTENER:
+ if err := d.deployToListener(ctx, upres.CertId); err != nil {
+ return nil, err
+ }
+
+ default:
+ return nil, fmt.Errorf("unsupported resource type: %s", d.config.ResourceType)
+ }
+
+ return &deployer.DeployResult{}, nil
+}
+
+func (d *DeployerProvider) deployToLoadbalancer(ctx context.Context, cloudCertId string) error {
+ if d.config.LoadbalancerId == "" {
+ return errors.New("config `loadbalancerId` is required")
+ }
+
+ // 查询 BLB 实例详情
+ // REF: https://cloud.baidu.com/doc/BLB/s/njwvxnv79#describeloadbalancerdetail%E6%9F%A5%E8%AF%A2blb%E5%AE%9E%E4%BE%8B%E8%AF%A6%E6%83%85
+ describeLoadBalancerDetailResp, err := d.sdkClient.DescribeLoadBalancerDetail(d.config.LoadbalancerId)
+ d.logger.Debug("sdk request 'blb.DescribeLoadBalancerAttribute'", slog.String("blbId", d.config.LoadbalancerId), slog.Any("response", describeLoadBalancerDetailResp))
+ if err != nil {
+ return xerrors.Wrap(err, "failed to execute sdk request 'blb.DescribeLoadBalancerDetail'")
+ }
+
+ // 获取全部 HTTPS/SSL 监听端口
+ listeners := make([]struct {
+ Type string
+ Port int32
+ }, 0)
+ for _, listener := range describeLoadBalancerDetailResp.Listener {
+ if listener.Type == "HTTPS" || listener.Type == "SSL" {
+ listenerPort, err := strconv.Atoi(listener.Port)
+ if err != nil {
+ continue
+ }
+
+ listeners = append(listeners, struct {
+ Type string
+ Port int32
+ }{
+ Type: listener.Type,
+ Port: int32(listenerPort),
+ })
+ }
+ }
+
+ // 遍历更新监听证书
+ if len(listeners) == 0 {
+ d.logger.Info("no blb listeners to deploy")
+ } else {
+ d.logger.Info("found https/ssl listeners to deploy", slog.Any("listeners", listeners))
+ var errs []error
+
+ for _, listener := range listeners {
+ if err := d.updateListenerCertificate(ctx, d.config.LoadbalancerId, listener.Type, listener.Port, cloudCertId); err != nil {
+ errs = append(errs, err)
+ }
+ }
+
+ if len(errs) > 0 {
+ return errors.Join(errs...)
+ }
+ }
+
+ return nil
+}
+
+func (d *DeployerProvider) deployToListener(ctx context.Context, cloudCertId string) error {
+ if d.config.LoadbalancerId == "" {
+ return errors.New("config `loadbalancerId` is required")
+ }
+ if d.config.ListenerPort == 0 {
+ return errors.New("config `listenerPort` is required")
+ }
+
+ // 查询监听
+ // REF: https://cloud.baidu.com/doc/BLB/s/yjwvxnvl6#describealllisteners%E6%9F%A5%E8%AF%A2%E6%89%80%E6%9C%89%E7%9B%91%E5%90%AC
+ describeAllListenersRequest := &bceblb.DescribeListenerArgs{
+ ListenerPort: uint16(d.config.ListenerPort),
+ }
+ describeAllListenersResp, err := d.sdkClient.DescribeAllListeners(d.config.LoadbalancerId, describeAllListenersRequest)
+ d.logger.Debug("sdk request 'blb.DescribeAllListeners'", slog.String("blbId", d.config.LoadbalancerId), slog.Any("request", describeAllListenersRequest), slog.Any("response", describeAllListenersResp))
+ if err != nil {
+ return xerrors.Wrap(err, "failed to execute sdk request 'blb.DescribeAllListeners'")
+ }
+
+ // 获取全部 HTTPS/SSL 监听端口
+ listeners := make([]struct {
+ Type string
+ Port int32
+ }, 0)
+ for _, listener := range describeAllListenersResp.AllListenerList {
+ if listener.ListenerType == "HTTPS" || listener.ListenerType == "SSL" {
+ listeners = append(listeners, struct {
+ Type string
+ Port int32
+ }{
+ Type: listener.ListenerType,
+ Port: int32(listener.ListenerPort),
+ })
+ }
+ }
+
+ // 遍历更新监听证书
+ if len(listeners) == 0 {
+ d.logger.Info("no blb listeners to deploy")
+ } else {
+ d.logger.Info("found https/ssl listeners to deploy", slog.Any("listeners", listeners))
+ var errs []error
+
+ for _, listener := range listeners {
+ if err := d.updateListenerCertificate(ctx, d.config.LoadbalancerId, listener.Type, listener.Port, cloudCertId); err != nil {
+ errs = append(errs, err)
+ }
+ }
+
+ if len(errs) > 0 {
+ return errors.Join(errs...)
+ }
+ }
+
+ return nil
+}
+
+func (d *DeployerProvider) updateListenerCertificate(ctx context.Context, cloudLoadbalancerId string, cloudListenerType string, cloudListenerPort int32, cloudCertId string) error {
+ switch strings.ToUpper(cloudListenerType) {
+ case "HTTPS":
+ return d.updateHttpsListenerCertificate(ctx, cloudLoadbalancerId, cloudListenerPort, cloudCertId)
+ case "SSL":
+ return d.updateSslListenerCertificate(ctx, cloudLoadbalancerId, cloudListenerPort, cloudCertId)
+ default:
+ return fmt.Errorf("unsupported listener type: %s", cloudListenerType)
+ }
+}
+
+func (d *DeployerProvider) updateHttpsListenerCertificate(ctx context.Context, cloudLoadbalancerId string, cloudHttpsListenerPort int32, cloudCertId string) error {
+ // 查询 HTTPS 监听器
+ // REF: https://cloud.baidu.com/doc/BLB/s/yjwvxnvl6#describehttpslisteners%E6%9F%A5%E8%AF%A2https%E7%9B%91%E5%90%AC%E5%99%A8
+ describeHTTPSListenersReq := &bceblb.DescribeListenerArgs{
+ ListenerPort: uint16(cloudHttpsListenerPort),
+ MaxKeys: 1,
+ }
+ describeHTTPSListenersResp, err := d.sdkClient.DescribeHTTPSListeners(cloudLoadbalancerId, describeHTTPSListenersReq)
+ d.logger.Debug("sdk request 'blb.DescribeHTTPSListeners'", slog.String("blbId", cloudLoadbalancerId), slog.Any("request", describeHTTPSListenersReq), slog.Any("response", describeHTTPSListenersResp))
+ if err != nil {
+ return xerrors.Wrap(err, "failed to execute sdk request 'blb.DescribeHTTPSListeners'")
+ } else if len(describeHTTPSListenersResp.ListenerList) == 0 {
+ return fmt.Errorf("listener %s:%d not found", cloudLoadbalancerId, cloudHttpsListenerPort)
+ }
+
+ if d.config.Domain == "" {
+ // 未指定 SNI,只需部署到监听器
+
+ // 更新 HTTPS 监听器
+ // REF: https://cloud.baidu.com/doc/BLB/s/yjwvxnvl6#updatehttpslistener%E6%9B%B4%E6%96%B0https%E7%9B%91%E5%90%AC%E5%99%A8
+ updateHTTPSListenerReq := &bceblb.UpdateHTTPSListenerArgs{
+ ListenerPort: uint16(cloudHttpsListenerPort),
+ CertIds: []string{cloudCertId},
+ }
+ err := d.sdkClient.UpdateHTTPSListener(cloudLoadbalancerId, updateHTTPSListenerReq)
+ d.logger.Debug("sdk request 'blb.UpdateHTTPSListener'", slog.Any("request", updateHTTPSListenerReq))
+ if err != nil {
+ return xerrors.Wrap(err, "failed to execute sdk request 'blb.UpdateHTTPSListener'")
+ }
+ } else {
+ // 指定 SNI,需部署到扩展域名
+
+ // 更新 HTTPS 监听器
+ // REF: https://cloud.baidu.com/doc/BLB/s/yjwvxnvl6#updatehttpslistener%E6%9B%B4%E6%96%B0https%E7%9B%91%E5%90%AC%E5%99%A8
+ updateHTTPSListenerReq := &bceblb.UpdateHTTPSListenerArgs{
+ ListenerPort: uint16(cloudHttpsListenerPort),
+ AdditionalCertDomains: sliceutil.Map(describeHTTPSListenersResp.ListenerList[0].AdditionalCertDomains, func(domain bceblb.AdditionalCertDomainsModel) bceblb.AdditionalCertDomainsModel {
+ if domain.Host == d.config.Domain {
+ return bceblb.AdditionalCertDomainsModel{
+ Host: domain.Host,
+ CertId: cloudCertId,
+ }
+ }
+
+ return bceblb.AdditionalCertDomainsModel{
+ Host: domain.Host,
+ CertId: domain.CertId,
+ }
+ }),
+ }
+ err := d.sdkClient.UpdateHTTPSListener(cloudLoadbalancerId, updateHTTPSListenerReq)
+ d.logger.Debug("sdk request 'blb.UpdateHTTPSListener'", slog.Any("request", updateHTTPSListenerReq))
+ if err != nil {
+ return xerrors.Wrap(err, "failed to execute sdk request 'blb.UpdateHTTPSListener'")
+ }
+ }
+
+ return nil
+}
+
+func (d *DeployerProvider) updateSslListenerCertificate(ctx context.Context, cloudLoadbalancerId string, cloudHttpsListenerPort int32, cloudCertId string) error {
+ // 更新 SSL 监听器
+ // REF: https://cloud.baidu.com/doc/BLB/s/yjwvxnvl6#updatessllistener%E6%9B%B4%E6%96%B0ssl%E7%9B%91%E5%90%AC%E5%99%A8
+ updateSSLListenerReq := &bceblb.UpdateSSLListenerArgs{
+ ListenerPort: uint16(cloudHttpsListenerPort),
+ CertIds: []string{cloudCertId},
+ }
+ err := d.sdkClient.UpdateSSLListener(cloudLoadbalancerId, updateSSLListenerReq)
+ d.logger.Debug("sdk request 'blb.UpdateSSLListener'", slog.Any("request", updateSSLListenerReq))
+ if err != nil {
+ return xerrors.Wrap(err, "failed to execute sdk request 'blb.UpdateSSLListener'")
+ }
+
+ return nil
+}
+
+func createSdkClient(accessKeyId, secretAccessKey, region string) (*bceblb.Client, error) {
+ endpoint := ""
+ if region != "" {
+ endpoint = fmt.Sprintf("blb.%s.baidubce.com", region)
+ }
+
+ client, err := bceblb.NewClient(accessKeyId, secretAccessKey, endpoint)
+ if err != nil {
+ return nil, err
+ }
+
+ return client, nil
+}
diff --git a/internal/pkg/core/deployer/providers/baiducloud-blb/baiducloud_blb_test.go b/internal/pkg/core/deployer/providers/baiducloud-blb/baiducloud_blb_test.go
new file mode 100644
index 00000000..756e6f8f
--- /dev/null
+++ b/internal/pkg/core/deployer/providers/baiducloud-blb/baiducloud_blb_test.go
@@ -0,0 +1,86 @@
+package baiducloudblb_test
+
+import (
+ "context"
+ "flag"
+ "fmt"
+ "os"
+ "strings"
+ "testing"
+
+ provider "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/baiducloud-blb"
+)
+
+var (
+ fInputCertPath string
+ fInputKeyPath string
+ fAccessKeyId string
+ fSecretAccessKey string
+ fRegion string
+ fLoadbalancerId string
+ fDomain string
+)
+
+func init() {
+ argsPrefix := "CERTIMATE_DEPLOYER_BAIDUCLOUDBLB_"
+
+ flag.StringVar(&fInputCertPath, argsPrefix+"INPUTCERTPATH", "", "")
+ flag.StringVar(&fInputKeyPath, argsPrefix+"INPUTKEYPATH", "", "")
+ flag.StringVar(&fAccessKeyId, argsPrefix+"ACCESSKEYID", "", "")
+ flag.StringVar(&fSecretAccessKey, argsPrefix+"SECRETACCESSKEY", "", "")
+ flag.StringVar(&fRegion, argsPrefix+"REGION", "", "")
+ flag.StringVar(&fLoadbalancerId, argsPrefix+"LOADBALANCERID", "", "")
+ flag.StringVar(&fDomain, argsPrefix+"DOMAIN", "", "")
+}
+
+/*
+Shell command to run this test:
+
+ go test -v ./baiducloud_blb_test.go -args \
+ --CERTIMATE_DEPLOYER_BAIDUCLOUDBLB_INPUTCERTPATH="/path/to/your-input-cert.pem" \
+ --CERTIMATE_DEPLOYER_BAIDUCLOUDBLB_INPUTKEYPATH="/path/to/your-input-key.pem" \
+ --CERTIMATE_DEPLOYER_BAIDUCLOUDBLB_ACCESSKEYID="your-access-key-id" \
+ --CERTIMATE_DEPLOYER_BAIDUCLOUDBLB_SECRETACCESSKEY="your-secret-access-key" \
+ --CERTIMATE_DEPLOYER_BAIDUCLOUDBLB_REGION="bj" \
+ --CERTIMATE_DEPLOYER_BAIDUCLOUDBLB_LOADBALANCERID="your-blb-loadbalancer-id" \
+ --CERTIMATE_DEPLOYER_BAIDUCLOUDBLB_DOMAIN="your-blb-sni-domain"
+*/
+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("SECRETACCESSKEY: %v", fSecretAccessKey),
+ fmt.Sprintf("REGION: %v", fRegion),
+ fmt.Sprintf("LOADBALANCERID: %v", fLoadbalancerId),
+ fmt.Sprintf("DOMAIN: %v", fDomain),
+ }, "\n"))
+
+ deployer, err := provider.NewDeployer(&provider.DeployerConfig{
+ AccessKeyId: fAccessKeyId,
+ SecretAccessKey: fSecretAccessKey,
+ ResourceType: provider.RESOURCE_TYPE_LOADBALANCER,
+ Region: fRegion,
+ LoadbalancerId: fLoadbalancerId,
+ Domain: fDomain,
+ })
+ if err != nil {
+ t.Errorf("err: %+v", err)
+ return
+ }
+
+ fInputCertData, _ := os.ReadFile(fInputCertPath)
+ fInputKeyData, _ := os.ReadFile(fInputKeyPath)
+ res, err := deployer.Deploy(context.Background(), string(fInputCertData), string(fInputKeyData))
+ if err != nil {
+ t.Errorf("err: %+v", err)
+ return
+ }
+
+ t.Logf("ok: %v", res)
+ })
+}
diff --git a/internal/pkg/core/deployer/providers/baiducloud-blb/consts.go b/internal/pkg/core/deployer/providers/baiducloud-blb/consts.go
new file mode 100644
index 00000000..52cb8804
--- /dev/null
+++ b/internal/pkg/core/deployer/providers/baiducloud-blb/consts.go
@@ -0,0 +1,10 @@
+package baiducloudblb
+
+type ResourceType string
+
+const (
+ // 资源类型:部署到指定负载均衡器。
+ RESOURCE_TYPE_LOADBALANCER = ResourceType("loadbalancer")
+ // 资源类型:部署到指定监听器。
+ RESOURCE_TYPE_LISTENER = ResourceType("listener")
+)
diff --git a/ui/src/components/workflow/node/DeployNodeConfigForm.tsx b/ui/src/components/workflow/node/DeployNodeConfigForm.tsx
index fdf0aaa5..2ba13579 100644
--- a/ui/src/components/workflow/node/DeployNodeConfigForm.tsx
+++ b/ui/src/components/workflow/node/DeployNodeConfigForm.tsx
@@ -33,6 +33,7 @@ import DeployNodeConfigFormAliyunWAFConfig from "./DeployNodeConfigFormAliyunWAF
import DeployNodeConfigFormAWSACMConfig from "./DeployNodeConfigFormAWSACMConfig";
import DeployNodeConfigFormAWSCloudFrontConfig from "./DeployNodeConfigFormAWSCloudFrontConfig";
import DeployNodeConfigFormAzureKeyVaultConfig from "./DeployNodeConfigFormAzureKeyVaultConfig";
+import DeployNodeConfigFormBaiduCloudBLBConfig from "./DeployNodeConfigFormBaiduCloudBLBConfig";
import DeployNodeConfigFormBaiduCloudCDNConfig from "./DeployNodeConfigFormBaiduCloudCDNConfig";
import DeployNodeConfigFormBaishanCDNConfig from "./DeployNodeConfigFormBaishanCDNConfig";
import DeployNodeConfigFormBaotaPanelConsoleConfig from "./DeployNodeConfigFormBaotaPanelConsoleConfig";
@@ -185,6 +186,8 @@ const DeployNodeConfigForm = forwardRef;
case DEPLOY_PROVIDERS.AZURE_KEYVAULT:
return ;
+ case DEPLOY_PROVIDERS.BAIDUCLOUD_BLB:
+ return ;
case DEPLOY_PROVIDERS.BAIDUCLOUD_CDN:
return ;
case DEPLOY_PROVIDERS.BAISHAN_CDN:
diff --git a/ui/src/components/workflow/node/DeployNodeConfigFormAliyunCLBConfig.tsx b/ui/src/components/workflow/node/DeployNodeConfigFormAliyunCLBConfig.tsx
index dfbfc707..2dd66b42 100644
--- a/ui/src/components/workflow/node/DeployNodeConfigFormAliyunCLBConfig.tsx
+++ b/ui/src/components/workflow/node/DeployNodeConfigFormAliyunCLBConfig.tsx
@@ -54,20 +54,8 @@ const DeployNodeConfigFormAliyunCLBConfig = ({
.max(64, t("common.errmsg.string_max", { max: 64 }))
.trim(),
listenerPort: z
- .union([
- z
- .number()
- .refine(
- (v) => fieldResourceType === RESOURCE_TYPE_LISTENER && validPortNumber(v),
- t("workflow_node.deploy.form.aliyun_clb_listener_port.placeholder")
- ),
- z
- .string()
- .refine(
- (v) => fieldResourceType === RESOURCE_TYPE_LISTENER && validPortNumber(v),
- t("workflow_node.deploy.form.aliyun_clb_listener_port.placeholder")
- ),
- ])
+ .union([z.number(), z.string()])
+ .refine((v) => fieldResourceType === RESOURCE_TYPE_LISTENER && validPortNumber(v), t("workflow_node.deploy.form.aliyun_clb_listener_port.placeholder"))
.nullish(),
domain: z
.string()
diff --git a/ui/src/components/workflow/node/DeployNodeConfigFormBaiduCloudBLBConfig.tsx b/ui/src/components/workflow/node/DeployNodeConfigFormBaiduCloudBLBConfig.tsx
new file mode 100644
index 00000000..f6ab1750
--- /dev/null
+++ b/ui/src/components/workflow/node/DeployNodeConfigFormBaiduCloudBLBConfig.tsx
@@ -0,0 +1,142 @@
+import { useTranslation } from "react-i18next";
+import { Form, type FormInstance, Input, Select } from "antd";
+import { createSchemaFieldRule } from "antd-zod";
+import { z } from "zod";
+
+import Show from "@/components/Show";
+import { validDomainName, validPortNumber } from "@/utils/validators";
+
+type DeployNodeConfigFormBaiduCloudBLBConfigFieldValues = Nullish<{
+ resourceType: string;
+ region: string;
+ loadbalancerId?: string;
+ listenerPort?: string | number;
+ domain?: string;
+}>;
+
+export type DeployNodeConfigFormBaiduCloudBLBConfigProps = {
+ form: FormInstance;
+ formName: string;
+ disabled?: boolean;
+ initialValues?: DeployNodeConfigFormBaiduCloudBLBConfigFieldValues;
+ onValuesChange?: (values: DeployNodeConfigFormBaiduCloudBLBConfigFieldValues) => void;
+};
+
+const RESOURCE_TYPE_LOADBALANCER = "loadbalancer" as const;
+const RESOURCE_TYPE_LISTENER = "listener" as const;
+
+const initFormModel = (): DeployNodeConfigFormBaiduCloudBLBConfigFieldValues => {
+ return {
+ listenerPort: 443,
+ };
+};
+
+const DeployNodeConfigFormBaiduCloudBLBConfig = ({
+ form: formInst,
+ formName,
+ disabled,
+ initialValues,
+ onValuesChange,
+}: DeployNodeConfigFormBaiduCloudBLBConfigProps) => {
+ const { t } = useTranslation();
+
+ const formSchema = z.object({
+ resourceType: z.union([z.literal(RESOURCE_TYPE_LOADBALANCER), z.literal(RESOURCE_TYPE_LISTENER)], {
+ message: t("workflow_node.deploy.form.baiducloud_blb_resource_type.placeholder"),
+ }),
+ region: z
+ .string({ message: t("workflow_node.deploy.form.baiducloud_blb_region.placeholder") })
+ .nonempty(t("workflow_node.deploy.form.baiducloud_blb_region.placeholder"))
+ .trim(),
+ loadbalancerId: z
+ .string({ message: t("workflow_node.deploy.form.baiducloud_blb_loadbalancer_id.placeholder") })
+ .min(1, t("workflow_node.deploy.form.baiducloud_blb_loadbalancer_id.placeholder"))
+ .max(64, t("common.errmsg.string_max", { max: 64 }))
+ .trim(),
+ listenerPort: z
+ .union([z.number(), z.string()])
+ .refine(
+ (v) => fieldResourceType === RESOURCE_TYPE_LISTENER && validPortNumber(v),
+ t("workflow_node.deploy.form.baiducloud_blb_listener_port.placeholder")
+ )
+ .nullish(),
+ domain: z
+ .string()
+ .nullish()
+ .refine((v) => {
+ if (![RESOURCE_TYPE_LOADBALANCER, RESOURCE_TYPE_LISTENER].includes(fieldResourceType)) return true;
+ return !v || validDomainName(v!, { allowWildcard: true });
+ }, t("common.errmsg.domain_invalid")),
+ });
+ const formRule = createSchemaFieldRule(formSchema);
+
+ const fieldResourceType = Form.useWatch("resourceType", formInst);
+
+ const handleFormChange = (_: unknown, values: z.infer) => {
+ onValuesChange?.(values);
+ };
+
+ return (
+
+
+
+
+ }
+ >
+
+
+
+ }
+ >
+
+
+
+
+ }
+ >
+
+
+
+
+
+ }
+ >
+
+
+
+
+ );
+};
+
+export default DeployNodeConfigFormBaiduCloudBLBConfig;
diff --git a/ui/src/domain/provider.ts b/ui/src/domain/provider.ts
index a0119bca..37c4bc00 100644
--- a/ui/src/domain/provider.ts
+++ b/ui/src/domain/provider.ts
@@ -249,6 +249,7 @@ export const DEPLOY_PROVIDERS = Object.freeze({
AWS_ACM: `${ACCESS_PROVIDERS.AWS}-acm`,
AWS_CLOUDFRONT: `${ACCESS_PROVIDERS.AWS}-cloudfront`,
AZURE_KEYVAULT: `${ACCESS_PROVIDERS.AZURE}-keyvault`,
+ BAIDUCLOUD_BLB: `${ACCESS_PROVIDERS.BAIDUCLOUD}-blb`,
BAIDUCLOUD_CDN: `${ACCESS_PROVIDERS.BAIDUCLOUD}-cdn`,
BAISHAN_CDN: `${ACCESS_PROVIDERS.BAISHAN}-cdn`,
BAOTAPANEL_CONSOLE: `${ACCESS_PROVIDERS.BAOTAPANEL}-console`,
@@ -360,6 +361,7 @@ export const deployProvidersMap: Maphttps://learn.microsoft.com/en-us/azure/key-vault/general/about-keys-secrets-certificates",
+ "workflow_node.deploy.form.baiducloud_blb_resource_type.label": "Resource type",
+ "workflow_node.deploy.form.baiducloud_blb_resource_type.placeholder": "Please select resource type",
+ "workflow_node.deploy.form.baiducloud_blb_resource_type.option.loadbalancer.label": "BLB load balancer",
+ "workflow_node.deploy.form.baiducloud_blb_resource_type.option.listener.label": "BLB listener",
+ "workflow_node.deploy.form.baiducloud_blb_region.label": "Baidu Cloud BLB region",
+ "workflow_node.deploy.form.baiducloud_blb_region.placeholder": "Please enter Baidu Cloud BLB region (e.g. bj)",
+ "workflow_node.deploy.form.baiducloud_blb_region.tooltip": "For more information, see https://cloud.baidu.com/doc/BLB/s/cjwvxnzix",
+ "workflow_node.deploy.form.baiducloud_blb_loadbalancer_id.label": "Baidu Cloud BLB load balancer ID",
+ "workflow_node.deploy.form.baiducloud_blb_loadbalancer_id.placeholder": "Please enter Baidu Cloud BLB load balancer ID",
+ "workflow_node.deploy.form.baiducloud_blb_loadbalancer_id.tooltip": "For more information, see https://console.bce.baidu.com/blb/#/blb/list",
+ "workflow_node.deploy.form.baiducloud_blb_listener_port.label": "Baidu Cloud BLB listener port",
+ "workflow_node.deploy.form.baiducloud_blb_listener_port.placeholder": "Please enter Baidu Cloud BLB listener port",
+ "workflow_node.deploy.form.baiducloud_blb_listener_port.tooltip": "For more information, see https://console.bce.baidu.com/blb/#/blb/list",
+ "workflow_node.deploy.form.baiducloud_blb_snidomain.label": "Baidu Cloud BLB SNI domain (Optional)",
+ "workflow_node.deploy.form.baiducloud_blb_snidomain.placeholder": "Please enter Baidu Cloud BLB SNI domain name",
+ "workflow_node.deploy.form.baiducloud_blb_snidomain.tooltip": "For more information, see https://console.bce.baidu.com/blb/#/blb/list",
"workflow_node.deploy.form.baiducloud_cdn_domain.label": "Baidu Cloud CDN domain",
"workflow_node.deploy.form.baiducloud_cdn_domain.placeholder": "Please enter Baidu Cloud CDN domain name",
"workflow_node.deploy.form.baiducloud_cdn_domain.tooltip": "For more information, see https://console.bce.baidu.com/cdn",
diff --git a/ui/src/i18n/locales/zh/nls.provider.json b/ui/src/i18n/locales/zh/nls.provider.json
index d3086452..acee7a7b 100644
--- a/ui/src/i18n/locales/zh/nls.provider.json
+++ b/ui/src/i18n/locales/zh/nls.provider.json
@@ -28,6 +28,7 @@
"provider.azure.dns": "Azure - DNS",
"provider.azure.keyvault": "Azure - KeyVault",
"provider.baiducloud": "百度智能云",
+ "provider.baiducloud.blb": "百度智能云 - 普通型负载均衡 BLB",
"provider.baiducloud.cdn": "百度智能云 - 内容分发网络 CDN",
"provider.baiducloud.dns": "百度智能云 - 智能云解析 DNS",
"provider.baishan": "白山云",
diff --git a/ui/src/i18n/locales/zh/nls.workflow.nodes.json b/ui/src/i18n/locales/zh/nls.workflow.nodes.json
index 1f7ce4a5..05868ff3 100644
--- a/ui/src/i18n/locales/zh/nls.workflow.nodes.json
+++ b/ui/src/i18n/locales/zh/nls.workflow.nodes.json
@@ -222,6 +222,22 @@
"workflow_node.deploy.form.azure_keyvault_name.label": "Azure KeyVault 名称",
"workflow_node.deploy.form.azure_keyvault_name.placeholder": "请输入 Azure KeyVault 名称",
"workflow_node.deploy.form.azure_keyvault_name.tooltip": "这是什么?请参阅 https://learn.microsoft.com/zh-cn/azure/key-vault/general/about-keys-secrets-certificates",
+ "workflow_node.deploy.form.baiducloud_blb_resource_type.label": "证书替换方式",
+ "workflow_node.deploy.form.baiducloud_blb_resource_type.placeholder": "请选择证书替换方式",
+ "workflow_node.deploy.form.baiducloud_blb_resource_type.option.loadbalancer.label": "替换指定负载均衡器下的全部 HTTPS/SSL 监听的证书",
+ "workflow_node.deploy.form.baiducloud_blb_resource_type.option.listener.label": "替换指定负载均衡监听的证书",
+ "workflow_node.deploy.form.baiducloud_blb_region.label": "百度智能云 BLB 服务地域",
+ "workflow_node.deploy.form.baiducloud_blb_region.placeholder": "请输入百度智能云 BLB 服务地域(例如:bj)",
+ "workflow_node.deploy.form.baiducloud_blb_region.tooltip": "这是什么?请参阅 https://cloud.baidu.com/doc/BLB/s/cjwvxnzix",
+ "workflow_node.deploy.form.baiducloud_blb_loadbalancer_id.label": "百度智能云 BLB 负载均衡器 ID",
+ "workflow_node.deploy.form.baiducloud_blb_loadbalancer_id.placeholder": "请输入百度智能云 BLB 负载均衡器 ID",
+ "workflow_node.deploy.form.baiducloud_blb_loadbalancer_id.tooltip": "这是什么?请参阅 https://console.bce.baidu.com/blb/#/blb/list",
+ "workflow_node.deploy.form.baiducloud_blb_listener_port.label": "百度智能云 BLB 监听端口",
+ "workflow_node.deploy.form.baiducloud_blb_listener_port.placeholder": "请输入百度智能云 BLB 监听端口",
+ "workflow_node.deploy.form.baiducloud_blb_listener_port.tooltip": "这是什么?请参阅 https://console.bce.baidu.com/blb/#/blb/list",
+ "workflow_node.deploy.form.baiducloud_blb_snidomain.label": "百度智能云 BLB 扩展域名(可选)",
+ "workflow_node.deploy.form.baiducloud_blb_snidomain.placeholder": "请输入百度智能云 BLB 扩展域名(支持泛域名)",
+ "workflow_node.deploy.form.baiducloud_blb_snidomain.tooltip": "这是什么?请参阅 https://console.bce.baidu.com/blb/#/blb/list
不填写时,将替换监听器的默认证书。",
"workflow_node.deploy.form.baiducloud_cdn_domain.label": "百度智能云 CDN 加速域名",
"workflow_node.deploy.form.baiducloud_cdn_domain.placeholder": "请输入百度智能云 CDN 加速域名(支持泛域名)",
"workflow_node.deploy.form.baiducloud_cdn_domain.tooltip": "这是什么?请参阅 https://console.bce.baidu.com/cdn",