feat(provider): new deployment provider: byteplus clb

This commit is contained in:
Fu Diwei
2026-06-04 01:14:21 +08:00
committed by RHQYZ
parent 155b186978
commit a4a0ed57e4
16 changed files with 707 additions and 13 deletions
@@ -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
})
}
+1
View File
@@ -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)
@@ -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
}
@@ -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})
})
}
@@ -0,0 +1,8 @@
package byteplusclb
const (
// 部署目标:部署到指定负载均衡器。
DEPLOY_TARGET_LOADBALANCER = "loadbalancer"
// 部署目标:部署到指定监听器。
DEPLOY_TARGET_LISTENER = "listener"
)
@@ -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
@@ -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
@@ -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
@@ -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
}
@@ -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<Record<DeploymentProviderType, React.Compone
[DEPLOYMENT_PROVIDERS.BYTEPLUS_ALB]: BizDeployNodeConfigFieldsProviderBytePlusALB,
[DEPLOYMENT_PROVIDERS.BYTEPLUS_CDN]: BizDeployNodeConfigFieldsProviderBytePlusCDN,
[DEPLOYMENT_PROVIDERS.BYTEPLUS_CERTCENTER]: BizDeployNodeConfigFieldsProviderBytePlusCertCenter,
[DEPLOYMENT_PROVIDERS.BYTEPLUS_CLB]: BizDeployNodeConfigFieldsProviderBytePlusCLB,
[DEPLOYMENT_PROVIDERS.BYTEPLUS_MEDIALIVE]: BizDeployNodeConfigFieldsProviderBytePlusMediaLive,
[DEPLOYMENT_PROVIDERS.CDNFLY]: BizDeployNodeConfigFieldsProviderCdnfly,
[DEPLOYMENT_PROVIDERS.CPANEL]: BizDeployNodeConfigFieldsProviderCPanel,
@@ -0,0 +1,135 @@
import { getI18n, useTranslation } from "react-i18next";
import { Form, Input, Select } from "antd";
import { createSchemaFieldRule } from "antd-zod";
import { z } from "zod";
import Show from "@/components/Show";
import { useFormNestedFieldsContext } from "./_context";
const DEPLOY_TARGET_LOADBALANCER = "loadbalancer" as const;
const DEPLOY_TARGET_LISTENER = "listener" as const;
const BizDeployNodeConfigFieldsProviderBytePlusCLB = () => {
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 (
<>
<Form.Item
name={[parentNamePath, "region"]}
initialValue={initialValues.region}
label={t("workflow_node.deploy.form.byteplus_clb_region.label")}
rules={[formRule]}
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.byteplus_clb_region.tooltip") }}></span>}
>
<Input placeholder={t("workflow_node.deploy.form.byteplus_clb_region.placeholder")} />
</Form.Item>
<Form.Item
name={[parentNamePath, "deployTarget"]}
initialValue={initialValues.deployTarget}
label={t("workflow_node.deploy.form.shared_deploy_target.label")}
rules={[formRule]}
>
<Select
options={[DEPLOY_TARGET_LOADBALANCER, DEPLOY_TARGET_LISTENER].map((s) => ({
value: s,
label: t(`workflow_node.deploy.form.byteplus_clb_deploy_target.option.${s}.label`),
}))}
placeholder={t("workflow_node.deploy.form.shared_deploy_target.placeholder")}
/>
</Form.Item>
<Show when={fieldResourceType === DEPLOY_TARGET_LOADBALANCER}>
<Form.Item
name={[parentNamePath, "loadbalancerId"]}
initialValue={initialValues.loadbalancerId}
label={t("workflow_node.deploy.form.byteplus_clb_loadbalancer_id.label")}
rules={[formRule]}
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.byteplus_clb_loadbalancer_id.tooltip") }}></span>}
>
<Input placeholder={t("workflow_node.deploy.form.byteplus_clb_loadbalancer_id.placeholder")} />
</Form.Item>
</Show>
<Show when={fieldResourceType === DEPLOY_TARGET_LISTENER}>
<Form.Item
name={[parentNamePath, "listenerId"]}
initialValue={initialValues.listenerId}
label={t("workflow_node.deploy.form.byteplus_clb_listener_id.label")}
rules={[formRule]}
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.byteplus_clb_listener_id.tooltip") }}></span>}
>
<Input placeholder={t("workflow_node.deploy.form.byteplus_clb_listener_id.placeholder")} />
</Form.Item>
</Show>
</>
);
};
const getInitialValues = (): Nullish<z.infer<ReturnType<typeof getSchema>>> => {
return {
region: "",
deployTarget: DEPLOY_TARGET_LISTENER,
};
};
const getSchema = ({ i18n = getI18n() }: { i18n?: ReturnType<typeof getI18n> }) => {
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;
+2
View File
@@ -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: Map<DeploymentProvider["type"] | string, De
[DEPLOYMENT_PROVIDERS.KSYUN_SLB, "provider.ksyun_slb", DEPLOYMENT_CATEGORIES.LOADBALANCE],
[DEPLOYMENT_PROVIDERS.BYTEPLUS_TOS, "provider.byteplus_tos", DEPLOYMENT_CATEGORIES.STORAGE],
[DEPLOYMENT_PROVIDERS.BYTEPLUS_CDN, "provider.byteplus_cdn", DEPLOYMENT_CATEGORIES.CDN],
[DEPLOYMENT_PROVIDERS.BYTEPLUS_CLB, "provider.byteplus_clb", DEPLOYMENT_CATEGORIES.LOADBALANCE],
[DEPLOYMENT_PROVIDERS.BYTEPLUS_ALB, "provider.byteplus_alb", DEPLOYMENT_CATEGORIES.LOADBALANCE],
[DEPLOYMENT_PROVIDERS.BYTEPLUS_MEDIALIVE, "provider.byteplus_medialive", DEPLOYMENT_CATEGORIES.AV],
[DEPLOYMENT_PROVIDERS.BYTEPLUS_CERTCENTER, "provider.byteplus_certcenter_upload", DEPLOYMENT_CATEGORIES.SSL],
+2 -1
View File
@@ -92,6 +92,7 @@
"byteplus_alb": "BytePlus - ALB (Application Load Balancer)",
"byteplus_cdn": "BytePlus - CDN (Content Delivery Network)",
"byteplus_certcenter_upload": "BytePlus - Upload to Certificate Center",
"byteplus_clb": "BytePlus - CLB (Classic Load Balancer)",
"byteplus_dns": "BytePlus - DNS Suite",
"byteplus_medialive": "BytePlus - MediaLive",
"byteplus_tos": "BytePlus - TOS (Torch Object Storage)",
@@ -254,7 +255,7 @@
"volcengine_apig": "Volcengine - API Gateway",
"volcengine_cdn": "Volcengine - CDN (Content Delivery Network)",
"volcengine_certcenter_upload": "Volcengine - Upload to Certificate Center",
"volcengine_clb": "Volcengine - CLB (Cloud Load Balancer)",
"volcengine_clb": "Volcengine - CLB (Classic Load Balancer)",
"volcengine_dcdn": "Volcengine - DCDN (Dynamic Content Delivery Network)",
"volcengine_dns": "Volcengine - DNS",
"volcengine_imagex": "Volcengine - ImageX",
@@ -1247,6 +1247,31 @@
"label": "BytePlus region",
"placeholder": "Please enter BytePlus Certificate Center region (e.g. ap-singapore-1)"
},
"byteplus_clb_region": {
"label": "BytePlus region",
"placeholder": "Please enter BytePlus CLB region (e.g. ap-southeast-1)",
"tooltip": "For more information, see <a href=\"https://docs.byteplus.com/en/docs/clb/Product-Overview-08\" target=\"_blank\">https://docs.byteplus.com/en/docs/clb/Product-Overview-08</a>"
},
"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 <a href=\"https://console.byteplus.com/clb/LoadBalancer\" target=\"_blank\">https://console.byteplus.com/clb/LoadBalancer</a>"
},
"byteplus_clb_listener_id": {
"label": "BytePlus CLB listener ID",
"placeholder": "Please enter BytePlus CLB listener ID",
"tooltip": "For more information, see <a href=\"https://console.byteplus.com/clb/LoadBalancer\" target=\"_blank\">https://console.byteplus.com/clb/LoadBalancer</a>"
},
"byteplus_medialive_domain": {
"label": "BytePlus MediaLive streaming domain",
"placeholder": "Please enter BytePlus MediaLive streaming domain name"
+2 -1
View File
@@ -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",
@@ -1220,7 +1220,7 @@
},
"byteplus_alb_region": {
"label": "BytePlus 服务地域",
"placeholder": "请输入 BytePlus ALB 服务地域(例如:cn-beijing)",
"placeholder": "请输入 BytePlus ALB 服务地域(例如:ap-southeast-1)",
"tooltip": "这是什么?请参阅 <a href=\"https://docs.byteplus.com/en/docs/clb/Regions-and-Availability-Zones\" target=\"_blank\">https://docs.byteplus.com/en/docs/clb/Regions-and-Availability-Zones</a>"
},
"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": "这是什么?请参阅 <a href=\"https://docs.byteplus.com/en/docs/clb/Product-Overview-08\" target=\"_blank\">https://docs.byteplus.com/en/docs/clb/Product-Overview-08</a>"
},
"byteplus_clb_deploy_target": {
"option": {
"loadbalancer": {
"label": "部署到指定负载均衡器下的全部 HTTPS 监听"
},
"listener": {
"label": "部署到 HTTPS 监听器"
}
}
},
"byteplus_clb_loadbalancer_id": {
"label": "BytePlus CLB 负载均衡器 ID",
"placeholder": "请输入 BytePlus CLB 负载均衡器 ID",
"tooltip": "这是什么?请参阅 <a href=\"https://console.byteplus.com/clb/LoadBalancer\" target=\"_blank\">https://console.byteplus.com/clb/LoadBalancer</a>"
},
"byteplus_clb_listener_id": {
"label": "BytePlus CLB 监听器 ID",
"placeholder": "请输入 BytePlus CLB 监听器 ID",
"tooltip": "这是什么?请参阅 <a href=\"https://console.byteplus.com/clb/LoadBalancer\" target=\"_blank\">https://console.byteplus.com/clb/LoadBalancer</a>"
},
"byteplus_medialive_domain": {
"label": "BytePlus 视频平台直播流域名",
"placeholder": "请输入 BytePlus 视频平台直播流域名"
@@ -2350,6 +2375,11 @@
"label": "又拍云云存储自定义域名",
"placeholder": "请输入又拍云云存储自定义域名"
},
"volcengine_alb_region": {
"label": "火山引擎服务地域",
"placeholder": "请输入火山引擎 ALB 服务地域(例如:cn-beijing)",
"tooltip": "这是什么?请参阅 <a href=\"https://www.volcengine.com/docs/6767/127501\" target=\"_blank\">https://www.volcengine.com/docs/6767/127501</a>"
},
"volcengine_alb_deploy_target": {
"option": {
"loadbalancer": {
@@ -2360,11 +2390,6 @@
}
}
},
"volcengine_alb_region": {
"label": "火山引擎服务地域",
"placeholder": "请输入火山引擎 ALB 服务地域(例如:cn-beijing)",
"tooltip": "这是什么?请参阅 <a href=\"https://www.volcengine.com/docs/6767/127501\" target=\"_blank\">https://www.volcengine.com/docs/6767/127501</a>"
},
"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": "这是什么?请参阅 <a href=\"https://www.volcengine.com/docs/6406/74892\" target=\"_blank\">https://www.volcengine.com/docs/6406/74892</a>"
},
"volcengine_clb_deploy_target": {
"option": {
"loadbalancer": {
@@ -2407,11 +2437,6 @@
}
}
},
"volcengine_clb_region": {
"label": "火山引擎服务地域",
"placeholder": "请输入火山引擎 CLB 服务地域(例如:cn-beijing)",
"tooltip": "这是什么?请参阅 <a href=\"https://www.volcengine.com/docs/6406/74892\" target=\"_blank\">https://www.volcengine.com/docs/6406/74892</a>"
},
"volcengine_clb_loadbalancer_id": {
"label": "火山引擎 CLB 负载均衡器 ID",
"placeholder": "请输入火山引擎 CLB 负载均衡器 ID",