From a4a0ed57e43e7749c04bfa22b3c3d3df3e8a2ad3 Mon Sep 17 00:00:00 2001 From: Fu Diwei Date: Thu, 4 Jun 2026 01:08:23 +0800 Subject: [PATCH] feat(provider): new deployment provider: byteplus clb --- .../certmgmt/deployers/sp_byteplus_clb.go | 30 +++ internal/domain/provider.go | 1 + .../providers/byteplus-clb/byteplus_clb.go | 235 ++++++++++++++++++ .../byteplus-clb/byteplus_clb_test.go | 58 +++++ .../deployer/providers/byteplus-clb/consts.go | 8 + .../service/clb/api_describe_listeners.go | 37 +++ .../api_describe_load_balancer_attributes.go | 37 +++ .../clb/api_modify_listener_attributes.go | 37 +++ .../service/clb/service_clb.go | 60 +++++ .../BizDeployNodeConfigFieldsProvider.tsx | 2 + ...loyNodeConfigFieldsProviderBytePlusCLB.tsx | 135 ++++++++++ ui/src/domain/provider.ts | 2 + ui/src/i18n/resources/en/nls.provider.json | 3 +- .../i18n/resources/en/nls.workflow.nodes.json | 25 ++ ui/src/i18n/resources/zh/nls.provider.json | 3 +- .../i18n/resources/zh/nls.workflow.nodes.json | 47 +++- 16 files changed, 707 insertions(+), 13 deletions(-) create mode 100644 internal/certmgmt/deployers/sp_byteplus_clb.go create mode 100644 pkg/core/deployer/providers/byteplus-clb/byteplus_clb.go create mode 100644 pkg/core/deployer/providers/byteplus-clb/byteplus_clb_test.go create mode 100644 pkg/core/deployer/providers/byteplus-clb/consts.go create mode 100644 pkg/sdk3rd-trimmed/github.com/byteplus-sdk/byteplus-go-sdk-v2/service/clb/api_describe_listeners.go create mode 100644 pkg/sdk3rd-trimmed/github.com/byteplus-sdk/byteplus-go-sdk-v2/service/clb/api_describe_load_balancer_attributes.go create mode 100644 pkg/sdk3rd-trimmed/github.com/byteplus-sdk/byteplus-go-sdk-v2/service/clb/api_modify_listener_attributes.go create mode 100644 pkg/sdk3rd-trimmed/github.com/byteplus-sdk/byteplus-go-sdk-v2/service/clb/service_clb.go create mode 100644 ui/src/components/workflow/designer/forms/BizDeployNodeConfigFieldsProviderBytePlusCLB.tsx diff --git a/internal/certmgmt/deployers/sp_byteplus_clb.go b/internal/certmgmt/deployers/sp_byteplus_clb.go new file mode 100644 index 000000000..677b3e34c --- /dev/null +++ b/internal/certmgmt/deployers/sp_byteplus_clb.go @@ -0,0 +1,30 @@ +package deployers + +import ( + "fmt" + + "github.com/certimate-go/certimate/internal/domain" + "github.com/certimate-go/certimate/pkg/core" + dplyimpl "github.com/certimate-go/certimate/pkg/core/deployer/providers/byteplus-clb" + xmaps "github.com/certimate-go/certimate/pkg/utils/maps" +) + +func init() { + Registries.MustRegister(domain.DeploymentProviderTypeBytePlusCLB, func(options *ProviderFactoryOptions) (core.Deployer, error) { + credentials := domain.AccessConfigForBytePlus{} + if err := xmaps.Populate(options.ProviderAccessConfig, &credentials); err != nil { + return nil, fmt.Errorf("failed to populate provider access config: %w", err) + } + + provider, err := dplyimpl.NewDeployer(&dplyimpl.DeployerConfig{ + AccessKeyId: credentials.AccessKeyId, + SecretAccessKey: credentials.SecretAccessKey, + ProjectName: credentials.ProjectName, + Region: xmaps.GetString(options.ProviderExtendedConfig, "region"), + DeployTarget: xmaps.GetString(options.ProviderExtendedConfig, "deployTarget"), + LoadbalancerId: xmaps.GetString(options.ProviderExtendedConfig, "loadbalancerId"), + ListenerId: xmaps.GetString(options.ProviderExtendedConfig, "listenerId"), + }) + return provider, err + }) +} diff --git a/internal/domain/provider.go b/internal/domain/provider.go index 58743796f..7853d9589 100644 --- a/internal/domain/provider.go +++ b/internal/domain/provider.go @@ -341,6 +341,7 @@ const ( DeploymentProviderTypeBytePlusALB = DeploymentProviderType(AccessProviderTypeBytePlus + "-alb") DeploymentProviderTypeBytePlusCDN = DeploymentProviderType(AccessProviderTypeBytePlus + "-cdn") DeploymentProviderTypeBytePlusCertCenter = DeploymentProviderType(AccessProviderTypeBytePlus + "-certcenter") + DeploymentProviderTypeBytePlusCLB = DeploymentProviderType(AccessProviderTypeBytePlus + "-clb") DeploymentProviderTypeBytePlusMediaLive = DeploymentProviderType(AccessProviderTypeBytePlus + "-medialive") DeploymentProviderTypeBytePlusTOS = DeploymentProviderType(AccessProviderTypeBytePlus + "-tos") DeploymentProviderTypeCacheFly = DeploymentProviderType(AccessProviderTypeCacheFly) diff --git a/pkg/core/deployer/providers/byteplus-clb/byteplus_clb.go b/pkg/core/deployer/providers/byteplus-clb/byteplus_clb.go new file mode 100644 index 000000000..fbedf494b --- /dev/null +++ b/pkg/core/deployer/providers/byteplus-clb/byteplus_clb.go @@ -0,0 +1,235 @@ +package byteplusclb + +import ( + "context" + "errors" + "fmt" + "log/slog" + + bp "github.com/byteplus-sdk/byteplus-go-sdk-v2/byteplus" + bpsession "github.com/byteplus-sdk/byteplus-go-sdk-v2/byteplus/session" + + bpclb "github.com/certimate-go/certimate/pkg/sdk3rd-trimmed/github.com/byteplus-sdk/byteplus-go-sdk-v2/service/clb" + + "github.com/certimate-go/certimate/pkg/core" + cmgrimpl "github.com/certimate-go/certimate/pkg/core/certmgr/providers/byteplus-certcenter" +) + +type ( + Provider = core.Deployer + DeployResult = core.DeployerDeployResult +) + +type DeployerConfig struct { + // BytePlus AccessKeyId。 + AccessKeyId string `json:"accessKeyId"` + // BytePlus SecretAccessKey。 + SecretAccessKey string `json:"secretAccessKey"` + // BytePlus 项目名称。 + ProjectName string `json:"projectName,omitempty"` + // BytePlus 地域。 + Region string `json:"region"` + // 部署目标。 + DeployTarget string `json:"deployTarget"` + // 负载均衡实例 ID。 + // 部署目标为 [DEPLOY_TARGET_LOADBALANCER] 时必填。 + LoadbalancerId string `json:"loadbalancerId,omitempty"` + // 负载均衡监听器 ID。 + // 部署目标为 [DEPLOY_TARGET_LISTENER] 时必填。 + ListenerId string `json:"listenerId,omitempty"` +} + +type Deployer struct { + config *DeployerConfig + logger *slog.Logger + sdkClient *bpclb.CLB + sdkCertmgr core.Certmgr +} + +var _ Provider = (*Deployer)(nil) + +func NewDeployer(config *DeployerConfig) (*Deployer, error) { + if config == nil { + return nil, fmt.Errorf("the configuration of the deployer provider is nil") + } + + client, err := createSDKClient(config.AccessKeyId, config.SecretAccessKey, config.Region) + if err != nil { + return nil, fmt.Errorf("could not create client: %w", err) + } + + pcertmgr, err := cmgrimpl.NewCertmgr(&cmgrimpl.CertmgrConfig{ + AccessKeyId: config.AccessKeyId, + SecretAccessKey: config.SecretAccessKey, + ProjectName: config.ProjectName, + Region: "ap-singapore-1", + }) + if err != nil { + return nil, fmt.Errorf("could not create certmgr: %w", err) + } + + return &Deployer{ + config: config, + logger: slog.Default(), + sdkClient: client, + sdkCertmgr: pcertmgr, + }, nil +} + +func (d *Deployer) SetLogger(logger *slog.Logger) { + if logger == nil { + d.logger = slog.New(slog.DiscardHandler) + } else { + d.logger = logger + } + + d.sdkCertmgr.SetLogger(logger) +} + +func (d *Deployer) Deploy(ctx context.Context, certPEM, privkeyPEM string) (*DeployResult, error) { + // 上传证书 + upres, err := d.sdkCertmgr.Upload(ctx, certPEM, privkeyPEM) + if err != nil { + return nil, fmt.Errorf("failed to upload certificate file: %w", err) + } else { + d.logger.Info("ssl certificate uploaded", slog.Any("result", upres)) + } + + // 根据部署目标决定业务流程 + switch d.config.DeployTarget { + case DEPLOY_TARGET_LOADBALANCER: + if err := d.deployToLoadbalancer(ctx, upres.CertId); err != nil { + return nil, err + } + + case DEPLOY_TARGET_LISTENER: + if err := d.deployToListener(ctx, upres.CertId); err != nil { + return nil, err + } + + default: + return nil, fmt.Errorf("unsupported deploy target '%s'", d.config.DeployTarget) + } + + return &DeployResult{}, nil +} + +func (d *Deployer) deployToLoadbalancer(ctx context.Context, cloudCertId string) error { + if d.config.LoadbalancerId == "" { + return fmt.Errorf("config `loadbalancerId` is required") + } + + // 查看指定负载均衡实例的详情 + // REF: https://docs.byteplus.com/en/docs/clb/DescribeLoadBalancerAttributes + describeLoadBalancerAttributesReq := &bpclb.DescribeLoadBalancerAttributesInput{ + LoadBalancerId: bp.String(d.config.LoadbalancerId), + } + describeLoadBalancerAttributesResp, err := d.sdkClient.DescribeLoadBalancerAttributesWithContext(ctx, describeLoadBalancerAttributesReq) + d.logger.Debug("sdk request 'clb.DescribeLoadBalancerAttributes'", slog.Any("request", describeLoadBalancerAttributesReq), slog.Any("response", describeLoadBalancerAttributesResp)) + if err != nil { + return fmt.Errorf("failed to execute sdk request 'clb.DescribeLoadBalancerAttributes': %w", err) + } + + // 查询 HTTPS 监听器列表 + // REF: https://docs.byteplus.com/en/docs/clb/DescribeListeners + listenerIds := make([]string, 0) + describeListenersPageSize := 100 + describeListenersPageNumber := 1 + for { + select { + case <-ctx.Done(): + return ctx.Err() + default: + } + + describeListenersReq := &bpclb.DescribeListenersInput{ + LoadBalancerId: bp.String(d.config.LoadbalancerId), + Protocol: bp.String("HTTPS"), + PageNumber: bp.Int64(int64(describeListenersPageNumber)), + PageSize: bp.Int64(int64(describeListenersPageSize)), + } + describeListenersResp, err := d.sdkClient.DescribeListenersWithContext(ctx, describeListenersReq) + d.logger.Debug("sdk request 'clb.DescribeListeners'", slog.Any("request", describeListenersReq), slog.Any("response", describeListenersResp)) + if err != nil { + return fmt.Errorf("failed to execute sdk request 'clb.DescribeListeners': %w", err) + } + + for _, listener := range describeListenersResp.Listeners { + listenerIds = append(listenerIds, *listener.ListenerId) + } + + if len(describeListenersResp.Listeners) < describeListenersPageSize { + break + } + + describeListenersPageNumber++ + } + + // 遍历更新监听证书 + if len(listenerIds) == 0 { + d.logger.Info("no clb listeners to deploy") + } else { + d.logger.Info("found https listeners to deploy", slog.Any("listenerIds", listenerIds)) + var errs []error + + for _, listenerId := range listenerIds { + select { + case <-ctx.Done(): + return ctx.Err() + default: + if err := d.updateListenerCertificate(ctx, listenerId, cloudCertId); err != nil { + errs = append(errs, err) + } + } + } + + if len(errs) > 0 { + return errors.Join(errs...) + } + } + + return nil +} + +func (d *Deployer) deployToListener(ctx context.Context, cloudCertId string) error { + if d.config.ListenerId == "" { + return fmt.Errorf("config `listenerId` is required") + } + + if err := d.updateListenerCertificate(ctx, d.config.ListenerId, cloudCertId); err != nil { + return err + } + + return nil +} + +func (d *Deployer) updateListenerCertificate(ctx context.Context, cloudListenerId string, cloudCertId string) error { + // 修改指定监听器 + // REF: https://docs.byteplus.com/en/docs/clb/ModifyListenerAttributes + modifyListenerAttributesReq := &bpclb.ModifyListenerAttributesInput{ + ListenerId: bp.String(cloudListenerId), + CertificateSource: bp.String("cert_center"), + CertCenterCertificateId: bp.String(cloudCertId), + } + modifyListenerAttributesResp, err := d.sdkClient.ModifyListenerAttributesWithContext(ctx, modifyListenerAttributesReq) + d.logger.Debug("sdk request 'clb.ModifyListenerAttributes'", slog.Any("request", modifyListenerAttributesReq), slog.Any("response", modifyListenerAttributesResp)) + if err != nil { + return fmt.Errorf("failed to execute sdk request 'clb.ModifyListenerAttributes': %w", err) + } + + return nil +} + +func createSDKClient(accessKeyId, secretAccessKey, region string) (*bpclb.CLB, error) { + config := bp.NewConfig(). + WithAkSk(accessKeyId, secretAccessKey). + WithRegion(region) + + session, err := bpsession.NewSession(config) + if err != nil { + return nil, err + } + + client := bpclb.New(session) + return client, nil +} diff --git a/pkg/core/deployer/providers/byteplus-clb/byteplus_clb_test.go b/pkg/core/deployer/providers/byteplus-clb/byteplus_clb_test.go new file mode 100644 index 000000000..4a2a78588 --- /dev/null +++ b/pkg/core/deployer/providers/byteplus-clb/byteplus_clb_test.go @@ -0,0 +1,58 @@ +package byteplusclb_test + +import ( + "testing" + + "github.com/certimate-go/certimate/pkg/core/deployer/internal/tester" + impl "github.com/certimate-go/certimate/pkg/core/deployer/providers/byteplus-clb" +) + +var ( + fp = tester.Args("BYTEPLUSCLB_") + fTestCertPath string + fTestKeyPath string + fAccessKeyId string + fSecretAccessKey string + fRegion string + fListenerId string +) + +func init() { + fp.DefineString(&fTestCertPath, "TESTCERTPATH") + fp.DefineString(&fTestKeyPath, "TESTKEYPATH") + fp.DefineString(&fAccessKeyId, "ACCESSKEYID") + fp.DefineString(&fSecretAccessKey, "SECRETACCESSKEY") + fp.DefineString(&fRegion, "REGION") + fp.DefineString(&fListenerId, "LISTENERID") +} + +/* +Shell command to run this test: + + go test -v ./byteplus_clb_test.go -args \ + --BYTEPLUSCLB_TESTCERTPATH="/path/to/your-test-cert.pem" \ + --BYTEPLUSCLB_TESTKEYPATH="/path/to/your-test-key.pem" \ + --BYTEPLUSCLB_ACCESSKEYID="your-access-key-id" \ + --BYTEPLUSCLB_SECRETACCESSKEY="your-secret-access-key" \ + --BYTEPLUSCLB_REGION="ap-southeast-1" \ + --BYTEPLUSCLB_LISTENERID="your-listener-id" +*/ +func TestProvider(t *testing.T) { + fp.Parse() + + t.Run("Deploy_ToListener", func(t *testing.T) { + provider, err := impl.NewDeployer(&impl.DeployerConfig{ + AccessKeyId: fAccessKeyId, + SecretAccessKey: fSecretAccessKey, + Region: fRegion, + DeployTarget: impl.DEPLOY_TARGET_LISTENER, + ListenerId: fListenerId, + }) + if err != nil { + t.Errorf("err: %+v", err) + return + } + + tester.TestDeploy(t, provider, tester.TestDeployArgs{CertPath: fTestCertPath, KeyPath: fTestKeyPath}) + }) +} diff --git a/pkg/core/deployer/providers/byteplus-clb/consts.go b/pkg/core/deployer/providers/byteplus-clb/consts.go new file mode 100644 index 000000000..eabf846cc --- /dev/null +++ b/pkg/core/deployer/providers/byteplus-clb/consts.go @@ -0,0 +1,8 @@ +package byteplusclb + +const ( + // 部署目标:部署到指定负载均衡器。 + DEPLOY_TARGET_LOADBALANCER = "loadbalancer" + // 部署目标:部署到指定监听器。 + DEPLOY_TARGET_LISTENER = "listener" +) diff --git a/pkg/sdk3rd-trimmed/github.com/byteplus-sdk/byteplus-go-sdk-v2/service/clb/api_describe_listeners.go b/pkg/sdk3rd-trimmed/github.com/byteplus-sdk/byteplus-go-sdk-v2/service/clb/api_describe_listeners.go new file mode 100644 index 000000000..448038345 --- /dev/null +++ b/pkg/sdk3rd-trimmed/github.com/byteplus-sdk/byteplus-go-sdk-v2/service/clb/api_describe_listeners.go @@ -0,0 +1,37 @@ +package clb + +import ( + "github.com/byteplus-sdk/byteplus-go-sdk-v2/byteplus" + "github.com/byteplus-sdk/byteplus-go-sdk-v2/byteplus/request" + "github.com/byteplus-sdk/byteplus-go-sdk-v2/service/clb" +) + +const opDescribeListeners = "DescribeListeners" + +func (c *CLB) DescribeListenersRequest(input *DescribeListenersInput) (req *request.Request, output *DescribeListenersOutput) { + op := &request.Operation{ + Name: opDescribeListeners, + HTTPMethod: "GET", + HTTPPath: "/", + } + + if input == nil { + input = &DescribeListenersInput{} + } + + output = &DescribeListenersOutput{} + req = c.newRequest(op, input, output) + + return +} + +func (c *CLB) DescribeListenersWithContext(ctx byteplus.Context, input *DescribeListenersInput, opts ...request.Option) (*DescribeListenersOutput, error) { + req, out := c.DescribeListenersRequest(input) + req.SetContext(ctx) + req.ApplyOptions(opts...) + return out, req.Send() +} + +type DescribeListenersInput = clb.DescribeListenersInput + +type DescribeListenersOutput = clb.DescribeListenersOutput diff --git a/pkg/sdk3rd-trimmed/github.com/byteplus-sdk/byteplus-go-sdk-v2/service/clb/api_describe_load_balancer_attributes.go b/pkg/sdk3rd-trimmed/github.com/byteplus-sdk/byteplus-go-sdk-v2/service/clb/api_describe_load_balancer_attributes.go new file mode 100644 index 000000000..97c472d3e --- /dev/null +++ b/pkg/sdk3rd-trimmed/github.com/byteplus-sdk/byteplus-go-sdk-v2/service/clb/api_describe_load_balancer_attributes.go @@ -0,0 +1,37 @@ +package clb + +import ( + "github.com/byteplus-sdk/byteplus-go-sdk-v2/byteplus" + "github.com/byteplus-sdk/byteplus-go-sdk-v2/byteplus/request" + "github.com/byteplus-sdk/byteplus-go-sdk-v2/service/clb" +) + +const opDescribeLoadBalancerAttributes = "DescribeLoadBalancerAttributes" + +func (c *CLB) DescribeLoadBalancerAttributesRequest(input *DescribeLoadBalancerAttributesInput) (req *request.Request, output *DescribeLoadBalancerAttributesOutput) { + op := &request.Operation{ + Name: opDescribeLoadBalancerAttributes, + HTTPMethod: "GET", + HTTPPath: "/", + } + + if input == nil { + input = &DescribeLoadBalancerAttributesInput{} + } + + output = &DescribeLoadBalancerAttributesOutput{} + req = c.newRequest(op, input, output) + + return +} + +func (c *CLB) DescribeLoadBalancerAttributesWithContext(ctx byteplus.Context, input *DescribeLoadBalancerAttributesInput, opts ...request.Option) (*DescribeLoadBalancerAttributesOutput, error) { + req, out := c.DescribeLoadBalancerAttributesRequest(input) + req.SetContext(ctx) + req.ApplyOptions(opts...) + return out, req.Send() +} + +type DescribeLoadBalancerAttributesInput = clb.DescribeLoadBalancerAttributesInput + +type DescribeLoadBalancerAttributesOutput = clb.DescribeLoadBalancerAttributesOutput diff --git a/pkg/sdk3rd-trimmed/github.com/byteplus-sdk/byteplus-go-sdk-v2/service/clb/api_modify_listener_attributes.go b/pkg/sdk3rd-trimmed/github.com/byteplus-sdk/byteplus-go-sdk-v2/service/clb/api_modify_listener_attributes.go new file mode 100644 index 000000000..842c1a9a7 --- /dev/null +++ b/pkg/sdk3rd-trimmed/github.com/byteplus-sdk/byteplus-go-sdk-v2/service/clb/api_modify_listener_attributes.go @@ -0,0 +1,37 @@ +package clb + +import ( + "github.com/byteplus-sdk/byteplus-go-sdk-v2/byteplus" + "github.com/byteplus-sdk/byteplus-go-sdk-v2/byteplus/request" + "github.com/byteplus-sdk/byteplus-go-sdk-v2/service/clb" +) + +const opModifyListenerAttributes = "ModifyListenerAttributes" + +func (c *CLB) ModifyListenerAttributesRequest(input *ModifyListenerAttributesInput) (req *request.Request, output *ModifyListenerAttributesOutput) { + op := &request.Operation{ + Name: opModifyListenerAttributes, + HTTPMethod: "GET", + HTTPPath: "/", + } + + if input == nil { + input = &ModifyListenerAttributesInput{} + } + + output = &ModifyListenerAttributesOutput{} + req = c.newRequest(op, input, output) + + return +} + +func (c *CLB) ModifyListenerAttributesWithContext(ctx byteplus.Context, input *ModifyListenerAttributesInput, opts ...request.Option) (*ModifyListenerAttributesOutput, error) { + req, out := c.ModifyListenerAttributesRequest(input) + req.SetContext(ctx) + req.ApplyOptions(opts...) + return out, req.Send() +} + +type ModifyListenerAttributesInput = clb.ModifyListenerAttributesInput + +type ModifyListenerAttributesOutput = clb.ModifyListenerAttributesOutput diff --git a/pkg/sdk3rd-trimmed/github.com/byteplus-sdk/byteplus-go-sdk-v2/service/clb/service_clb.go b/pkg/sdk3rd-trimmed/github.com/byteplus-sdk/byteplus-go-sdk-v2/service/clb/service_clb.go new file mode 100644 index 000000000..b463a8344 --- /dev/null +++ b/pkg/sdk3rd-trimmed/github.com/byteplus-sdk/byteplus-go-sdk-v2/service/clb/service_clb.go @@ -0,0 +1,60 @@ +package clb + +import ( + "github.com/byteplus-sdk/byteplus-go-sdk-v2/byteplus" + "github.com/byteplus-sdk/byteplus-go-sdk-v2/byteplus/byteplusquery" + "github.com/byteplus-sdk/byteplus-go-sdk-v2/byteplus/client" + "github.com/byteplus-sdk/byteplus-go-sdk-v2/byteplus/client/metadata" + "github.com/byteplus-sdk/byteplus-go-sdk-v2/byteplus/corehandlers" + "github.com/byteplus-sdk/byteplus-go-sdk-v2/byteplus/request" + "github.com/byteplus-sdk/byteplus-go-sdk-v2/byteplus/signer/byteplussign" + "github.com/byteplus-sdk/byteplus-go-sdk-v2/service/clb" +) + +type CLB struct { + *client.Client +} + +const ( + ServiceName = clb.ServiceName + EndpointsID = clb.EndpointsID + ServiceID = clb.ServiceID +) + +func New(p client.ConfigProvider, cfgs ...*byteplus.Config) *CLB { + c := p.ClientConfig(clb.EndpointsID, cfgs...) + return newClient(*c.Config, c.Handlers, c.Endpoint, c.SigningRegion, c.SigningName) +} + +func newClient(cfg byteplus.Config, handlers request.Handlers, endpoint, signingRegion, signingName string) *CLB { + svc := &CLB{ + Client: client.New( + cfg, + metadata.ClientInfo{ + ServiceName: clb.ServiceName, + ServiceID: clb.ServiceID, + SigningName: signingName, + SigningRegion: signingRegion, + Endpoint: endpoint, + APIVersion: "2020-04-01", + }, + handlers, + ), + } + + svc.Handlers.Build.PushBackNamed(corehandlers.SDKVersionUserAgentHandler) + svc.Handlers.Build.PushBackNamed(corehandlers.AddHostExecEnvUserAgentHandler) + svc.Handlers.Sign.PushBackNamed(byteplussign.SignRequestHandler) + svc.Handlers.Build.PushBackNamed(byteplusquery.BuildHandler) + svc.Handlers.Unmarshal.PushBackNamed(byteplusquery.UnmarshalHandler) + svc.Handlers.UnmarshalMeta.PushBackNamed(byteplusquery.UnmarshalMetaHandler) + svc.Handlers.UnmarshalError.PushBackNamed(byteplusquery.UnmarshalErrorHandler) + + return svc +} + +func (c *CLB) newRequest(op *request.Operation, params, data interface{}) *request.Request { + req := c.NewRequest(op, params, data) + + return req +} diff --git a/ui/src/components/workflow/designer/forms/BizDeployNodeConfigFieldsProvider.tsx b/ui/src/components/workflow/designer/forms/BizDeployNodeConfigFieldsProvider.tsx index 525b951f1..e28f32455 100644 --- a/ui/src/components/workflow/designer/forms/BizDeployNodeConfigFieldsProvider.tsx +++ b/ui/src/components/workflow/designer/forms/BizDeployNodeConfigFieldsProvider.tsx @@ -40,6 +40,7 @@ import BizDeployNodeConfigFieldsProviderBunnyCDN from "./BizDeployNodeConfigFiel import BizDeployNodeConfigFieldsProviderBytePlusALB from "./BizDeployNodeConfigFieldsProviderBytePlusALB"; import BizDeployNodeConfigFieldsProviderBytePlusCDN from "./BizDeployNodeConfigFieldsProviderBytePlusCDN"; import BizDeployNodeConfigFieldsProviderBytePlusCertCenter from "./BizDeployNodeConfigFieldsProviderBytePlusCertCenter"; +import BizDeployNodeConfigFieldsProviderBytePlusCLB from "./BizDeployNodeConfigFieldsProviderBytePlusCLB"; import BizDeployNodeConfigFieldsProviderBytePlusMediaLive from "./BizDeployNodeConfigFieldsProviderBytePlusMediaLive"; import BizDeployNodeConfigFieldsProviderCdnfly from "./BizDeployNodeConfigFieldsProviderCdnfly"; import BizDeployNodeConfigFieldsProviderCPanel from "./BizDeployNodeConfigFieldsProviderCPanel"; @@ -171,6 +172,7 @@ const providerComponentMap: Partial { + const { i18n, t } = useTranslation(); + + const { parentNamePath } = useFormNestedFieldsContext(); + const formSchema = z.object({ + [parentNamePath]: getSchema({ i18n }), + }); + const formRule = createSchemaFieldRule(formSchema); + const formInst = Form.useFormInstance(); + const initialValues = getInitialValues(); + + const fieldResourceType = Form.useWatch([parentNamePath, "deployTarget"], formInst); + + return ( + <> + } + > + + + + + + + + + + } + > + + + + + ); +}; + +const getInitialValues = (): Nullish>> => { + return { + region: "", + deployTarget: DEPLOY_TARGET_LISTENER, + }; +}; + +const getSchema = ({ i18n = getI18n() }: { i18n?: ReturnType }) => { + const { t: _ } = i18n; + + return z + .object({ + region: z.string().nonempty(), + deployTarget: z.enum([DEPLOY_TARGET_LOADBALANCER, DEPLOY_TARGET_LISTENER]), + loadbalancerId: z.string().nullish(), + listenerId: z.string().nullish(), + }) + .superRefine((values, ctx) => { + switch (values.deployTarget) { + case DEPLOY_TARGET_LOADBALANCER: + { + const scLoadbalancerId = z.string().nonempty(); + const spLoadbalancerId = scLoadbalancerId.safeParse(values.loadbalancerId); + if (!spLoadbalancerId.success) { + ctx.addIssue({ + code: "custom", + message: z.treeifyError(spLoadbalancerId.error).errors.join(), + path: ["loadbalancerId"], + }); + } + } + break; + + case DEPLOY_TARGET_LISTENER: + { + const scListenerId = z.string().nonempty(); + const spListenerId = scListenerId.safeParse(values.listenerId); + if (!spListenerId.success) { + ctx.addIssue({ + code: "custom", + message: z.treeifyError(spListenerId.error).errors.join(), + path: ["listenerId"], + }); + } + } + break; + } + }); +}; + +const _default = Object.assign(BizDeployNodeConfigFieldsProviderBytePlusCLB, { + getInitialValues, + getSchema, +}); + +export default _default; diff --git a/ui/src/domain/provider.ts b/ui/src/domain/provider.ts index 4a17367a4..94b10d377 100644 --- a/ui/src/domain/provider.ts +++ b/ui/src/domain/provider.ts @@ -624,6 +624,7 @@ export const DEPLOYMENT_PROVIDERS = Object.freeze({ BYTEPLUS_ALB: `${ACCESS_PROVIDERS.BYTEPLUS}-alb`, BYTEPLUS_CDN: `${ACCESS_PROVIDERS.BYTEPLUS}-cdn`, BYTEPLUS_CERTCENTER: `${ACCESS_PROVIDERS.BYTEPLUS}-certcenter`, + BYTEPLUS_CLB: `${ACCESS_PROVIDERS.BYTEPLUS}-clb`, BYTEPLUS_MEDIALIVE: `${ACCESS_PROVIDERS.BYTEPLUS}-medialive`, BYTEPLUS_TOS: `${ACCESS_PROVIDERS.BYTEPLUS}-tos`, CACHEFLY: `${ACCESS_PROVIDERS.CACHEFLY}`, @@ -830,6 +831,7 @@ export const deploymentProvidersMap: Maphttps://docs.byteplus.com/en/docs/clb/Product-Overview-08" + }, + "byteplus_clb_deploy_target": { + "option": { + "loadbalancer": { + "label": "CLB load balancer" + }, + "listener": { + "label": "CLB listener" + } + } + }, + "byteplus_clb_loadbalancer_id": { + "label": "BytePlus CLB load balancer ID", + "placeholder": "Please enter BytePlus CLB load balancer ID", + "tooltip": "For more information, see https://console.byteplus.com/clb/LoadBalancer" + }, + "byteplus_clb_listener_id": { + "label": "BytePlus CLB listener ID", + "placeholder": "Please enter BytePlus CLB listener ID", + "tooltip": "For more information, see https://console.byteplus.com/clb/LoadBalancer" + }, "byteplus_medialive_domain": { "label": "BytePlus MediaLive streaming domain", "placeholder": "Please enter BytePlus MediaLive streaming domain name" diff --git a/ui/src/i18n/resources/zh/nls.provider.json b/ui/src/i18n/resources/zh/nls.provider.json index 7da7f255b..7b4d8a3f2 100644 --- a/ui/src/i18n/resources/zh/nls.provider.json +++ b/ui/src/i18n/resources/zh/nls.provider.json @@ -92,6 +92,7 @@ "byteplus_alb": "BytePlus - 应用型负载均衡 ALB", "byteplus_cdn": "BytePlus - 内容分发网络 CDN", "byteplus_certcenter_upload": "BytePlus - 上传到证书中心", + "byteplus_clb": "BytePlus - 传统型负载均衡 CLB", "byteplus_dns": "BytePlus - DNS Suite", "byteplus_medialive": "BytePlus - 视频平台 MediaLive", "byteplus_tos": "BytePlus - 对象存储 TOS", @@ -254,7 +255,7 @@ "volcengine_apig": "火山引擎 - API 网关", "volcengine_cdn": "火山引擎 - 内容分发网络 CDN", "volcengine_certcenter_upload": "火山引擎 - 上传到证书中心", - "volcengine_clb": "火山引擎 - 负载均衡 CLB", + "volcengine_clb": "火山引擎 - 传统型负载均衡 CLB", "volcengine_dcdn": "火山引擎 - 全站加速 DCDN", "volcengine_dns": "火山引擎 - 云解析 DNS", "volcengine_imagex": "火山引擎 - 图片服务 ImageX", diff --git a/ui/src/i18n/resources/zh/nls.workflow.nodes.json b/ui/src/i18n/resources/zh/nls.workflow.nodes.json index 2343e81d5..4429f1404 100644 --- a/ui/src/i18n/resources/zh/nls.workflow.nodes.json +++ b/ui/src/i18n/resources/zh/nls.workflow.nodes.json @@ -1220,7 +1220,7 @@ }, "byteplus_alb_region": { "label": "BytePlus 服务地域", - "placeholder": "请输入 BytePlus ALB 服务地域(例如:cn-beijing)", + "placeholder": "请输入 BytePlus ALB 服务地域(例如:ap-southeast-1)", "tooltip": "这是什么?请参阅 https://docs.byteplus.com/en/docs/clb/Regions-and-Availability-Zones" }, "byteplus_alb_loadbalancer_id": { @@ -1246,6 +1246,31 @@ "label": "BytePlus 服务地域", "placeholder": "请输入 BytePlus 证书中心服务地域(例如:ap-singapore-1)" }, + "byteplus_clb_region": { + "label": "BytePlus 服务地域", + "placeholder": "请输入 BytePlus CLB 服务地域(例如:ap-southeast-1)", + "tooltip": "这是什么?请参阅 https://docs.byteplus.com/en/docs/clb/Product-Overview-08" + }, + "byteplus_clb_deploy_target": { + "option": { + "loadbalancer": { + "label": "部署到指定负载均衡器下的全部 HTTPS 监听" + }, + "listener": { + "label": "部署到 HTTPS 监听器" + } + } + }, + "byteplus_clb_loadbalancer_id": { + "label": "BytePlus CLB 负载均衡器 ID", + "placeholder": "请输入 BytePlus CLB 负载均衡器 ID", + "tooltip": "这是什么?请参阅 https://console.byteplus.com/clb/LoadBalancer" + }, + "byteplus_clb_listener_id": { + "label": "BytePlus CLB 监听器 ID", + "placeholder": "请输入 BytePlus CLB 监听器 ID", + "tooltip": "这是什么?请参阅 https://console.byteplus.com/clb/LoadBalancer" + }, "byteplus_medialive_domain": { "label": "BytePlus 视频平台直播流域名", "placeholder": "请输入 BytePlus 视频平台直播流域名" @@ -2350,6 +2375,11 @@ "label": "又拍云云存储自定义域名", "placeholder": "请输入又拍云云存储自定义域名" }, + "volcengine_alb_region": { + "label": "火山引擎服务地域", + "placeholder": "请输入火山引擎 ALB 服务地域(例如:cn-beijing)", + "tooltip": "这是什么?请参阅 https://www.volcengine.com/docs/6767/127501" + }, "volcengine_alb_deploy_target": { "option": { "loadbalancer": { @@ -2360,11 +2390,6 @@ } } }, - "volcengine_alb_region": { - "label": "火山引擎服务地域", - "placeholder": "请输入火山引擎 ALB 服务地域(例如:cn-beijing)", - "tooltip": "这是什么?请参阅 https://www.volcengine.com/docs/6767/127501" - }, "volcengine_alb_loadbalancer_id": { "label": "火山引擎 ALB 负载均衡器 ID", "placeholder": "请输入火山引擎 ALB 负载均衡器 ID", @@ -2397,6 +2422,11 @@ "label": "火山引擎服务地域", "placeholder": "请输入火山引擎证书中心服务地域(例如:cn-beijing)" }, + "volcengine_clb_region": { + "label": "火山引擎服务地域", + "placeholder": "请输入火山引擎 CLB 服务地域(例如:cn-beijing)", + "tooltip": "这是什么?请参阅 https://www.volcengine.com/docs/6406/74892" + }, "volcengine_clb_deploy_target": { "option": { "loadbalancer": { @@ -2407,11 +2437,6 @@ } } }, - "volcengine_clb_region": { - "label": "火山引擎服务地域", - "placeholder": "请输入火山引擎 CLB 服务地域(例如:cn-beijing)", - "tooltip": "这是什么?请参阅 https://www.volcengine.com/docs/6406/74892" - }, "volcengine_clb_loadbalancer_id": { "label": "火山引擎 CLB 负载均衡器 ID", "placeholder": "请输入火山引擎 CLB 负载均衡器 ID",