From 757b299654eeaf042ced5482714a58ef35ed212f Mon Sep 17 00:00:00 2001 From: Fu Diwei Date: Mon, 13 Jul 2026 15:06:37 +0800 Subject: [PATCH] feat(provider): new deployment provider: huaweicloud vod --- .../certmgmt/deployers/sp_huaweicloud_aad.go | 1 + .../certmgmt/deployers/sp_huaweicloud_vod.go | 29 ++ internal/domain/provider.go | 1 + .../huaweicloud-aad/huaweicloud_aad.go | 14 +- .../huaweicloud-apig/huaweicloud_apig.go | 4 +- .../huaweicloud-live/huaweicloud_live.go | 4 +- .../providers/huaweicloud-vod/consts.go | 6 + .../huaweicloud-vod/huaweicloud_vod.go | 249 ++++++++++++++++++ .../huaweicloud-vod/huaweicloud_vod_test.go | 58 ++++ .../huaweicloud-waf/huaweicloud_waf.go | 4 +- .../services/vod/v1/vod_client.go | 39 +++ .../services/vod/v1/vod_meta.go | 14 + .../BizDeployNodeConfigFieldsProvider.tsx | 2 + ...NodeConfigFieldsProviderHuaweiCloudAAD.tsx | 12 + ...odeConfigFieldsProviderHuaweiCloudLive.tsx | 12 + ...NodeConfigFieldsProviderHuaweiCloudVOD.tsx | 103 ++++++++ ui/src/domain/provider.ts | 2 + ui/src/i18n/resources/en/nls.provider.json | 1 + .../i18n/resources/en/nls.workflow.nodes.json | 20 +- ui/src/i18n/resources/zh/nls.provider.json | 1 + .../i18n/resources/zh/nls.workflow.nodes.json | 14 + 21 files changed, 575 insertions(+), 15 deletions(-) create mode 100644 internal/certmgmt/deployers/sp_huaweicloud_vod.go create mode 100644 pkg/core/deployer/providers/huaweicloud-vod/consts.go create mode 100644 pkg/core/deployer/providers/huaweicloud-vod/huaweicloud_vod.go create mode 100644 pkg/core/deployer/providers/huaweicloud-vod/huaweicloud_vod_test.go create mode 100644 pkg/sdk3rd-trimmed/github.com/huaweicloud/huaweicloud-sdk-go-v3/services/vod/v1/vod_client.go create mode 100644 pkg/sdk3rd-trimmed/github.com/huaweicloud/huaweicloud-sdk-go-v3/services/vod/v1/vod_meta.go create mode 100644 ui/src/components/workflow/designer/forms/BizDeployNodeConfigFieldsProviderHuaweiCloudVOD.tsx diff --git a/internal/certmgmt/deployers/sp_huaweicloud_aad.go b/internal/certmgmt/deployers/sp_huaweicloud_aad.go index 7aaa3ffc..34a00c1b 100644 --- a/internal/certmgmt/deployers/sp_huaweicloud_aad.go +++ b/internal/certmgmt/deployers/sp_huaweicloud_aad.go @@ -20,6 +20,7 @@ func init() { AccessKeyId: credentials.AccessKeyId, SecretAccessKey: credentials.SecretAccessKey, EnterpriseProjectId: credentials.EnterpriseProjectId, + Region: xmaps.GetString(options.ProviderExtendedConfig, "region"), InstanceId: xmaps.GetString(options.ProviderExtendedConfig, "instanceId"), DomainMatchPattern: xmaps.GetString(options.ProviderExtendedConfig, "domainMatchPattern"), Domain: xmaps.GetString(options.ProviderExtendedConfig, "domain"), diff --git a/internal/certmgmt/deployers/sp_huaweicloud_vod.go b/internal/certmgmt/deployers/sp_huaweicloud_vod.go new file mode 100644 index 00000000..4faf51cb --- /dev/null +++ b/internal/certmgmt/deployers/sp_huaweicloud_vod.go @@ -0,0 +1,29 @@ +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/huaweicloud-vod" + xmaps "github.com/certimate-go/certimate/pkg/utils/maps" +) + +func init() { + Registries.MustRegister(domain.DeploymentProviderTypeHuaweiCloudVOD, func(options *ProviderFactoryOptions) (core.Deployer, error) { + credentials := domain.AccessConfigForHuaweiCloud{} + 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, + EnterpriseProjectId: credentials.EnterpriseProjectId, + Region: xmaps.GetString(options.ProviderExtendedConfig, "region"), + DomainMatchPattern: xmaps.GetString(options.ProviderExtendedConfig, "domainMatchPattern"), + Domain: xmaps.GetString(options.ProviderExtendedConfig, "domain"), + }) + return provider, err + }) +} diff --git a/internal/domain/provider.go b/internal/domain/provider.go index 927489fb..840d7d5a 100644 --- a/internal/domain/provider.go +++ b/internal/domain/provider.go @@ -388,6 +388,7 @@ const ( DeploymentProviderTypeHuaweiCloudLive = DeploymentProviderType(AccessProviderTypeHuaweiCloud + "-live") DeploymentProviderTypeHuaweiCloudOBS = DeploymentProviderType(AccessProviderTypeHuaweiCloud + "-obs") DeploymentProviderTypeHuaweiCloudSCM = DeploymentProviderType(AccessProviderTypeHuaweiCloud + "-scm") + DeploymentProviderTypeHuaweiCloudVOD = DeploymentProviderType(AccessProviderTypeHuaweiCloud + "-vod") DeploymentProviderTypeHuaweiCloudWAF = DeploymentProviderType(AccessProviderTypeHuaweiCloud + "-waf") DeploymentProviderTypeJDCloudALB = DeploymentProviderType(AccessProviderTypeJDCloud + "-alb") DeploymentProviderTypeJDCloudCDN = DeploymentProviderType(AccessProviderTypeJDCloud + "-cdn") diff --git a/pkg/core/deployer/providers/huaweicloud-aad/huaweicloud_aad.go b/pkg/core/deployer/providers/huaweicloud-aad/huaweicloud_aad.go index 474e1891..80e619ea 100644 --- a/pkg/core/deployer/providers/huaweicloud-aad/huaweicloud_aad.go +++ b/pkg/core/deployer/providers/huaweicloud-aad/huaweicloud_aad.go @@ -32,6 +32,8 @@ type DeployerConfig struct { SecretAccessKey string `json:"secretAccessKey"` // 华为云企业项目 ID。 EnterpriseProjectId string `json:"enterpriseProjectId,omitempty"` + // 华为云区域。 + Region string `json:"region"` // DDoS 高防实例 ID。 InstanceId string `json:"instanceId"` // 域名匹配模式。 @@ -59,7 +61,7 @@ func NewDeployer(config *DeployerConfig) (*Deployer, error) { return nil, fmt.Errorf("the configuration of the deployer provider is nil") } - clients, err := createSDKClients(config.AccessKeyId, config.SecretAccessKey) + clients, err := createSDKClients(config.AccessKeyId, config.SecretAccessKey, config.Region) if err != nil { return nil, fmt.Errorf("could not create client: %w", err) } @@ -251,12 +253,14 @@ func (d *Deployer) updateDomainCertificate(ctx context.Context, cloudDomainId st return nil } -func createSDKClients(accessKeyId, secretAccessKey string) (*wSDKClients, error) { +func createSDKClients(accessKeyId, secretAccessKey, region string) (*wSDKClients, error) { wsdk := &wSDKClients{} - { - region := "cn-north-4" // AAD 服务默认区域:华北北京四 + if region == "" { + region = "cn-north-4" // AAD 服务默认区域:华北北京四 + } + { auth, err := global.NewCredentialsBuilder(). WithAk(accessKeyId). WithSk(secretAccessKey). @@ -283,8 +287,6 @@ func createSDKClients(accessKeyId, secretAccessKey string) (*wSDKClients, error) } { - region := "cn-north-4" // AAD 服务默认区域:华北北京四 - auth, err := global.NewCredentialsBuilder(). WithAk(accessKeyId). WithSk(secretAccessKey). diff --git a/pkg/core/deployer/providers/huaweicloud-apig/huaweicloud_apig.go b/pkg/core/deployer/providers/huaweicloud-apig/huaweicloud_apig.go index cab43f23..8b03b06a 100644 --- a/pkg/core/deployer/providers/huaweicloud-apig/huaweicloud_apig.go +++ b/pkg/core/deployer/providers/huaweicloud-apig/huaweicloud_apig.go @@ -11,7 +11,7 @@ import ( hwapigmodel "github.com/huaweicloud/huaweicloud-sdk-go-v3/services/apig/v2/model" hwapigregion "github.com/huaweicloud/huaweicloud-sdk-go-v3/services/apig/v2/region" hwiam "github.com/huaweicloud/huaweicloud-sdk-go-v3/services/iam/v3" - hwiamModel "github.com/huaweicloud/huaweicloud-sdk-go-v3/services/iam/v3/model" + hwiammodel "github.com/huaweicloud/huaweicloud-sdk-go-v3/services/iam/v3/model" hwiamregion "github.com/huaweicloud/huaweicloud-sdk-go-v3/services/iam/v3/region" "github.com/samber/lo" @@ -188,7 +188,7 @@ func getSDKProjectId(accessKeyId, secretAccessKey, region string) (string, error client := hwiam.NewIamClient(hcClient) - request := &hwiamModel.KeystoneListProjectsRequest{ + request := &hwiammodel.KeystoneListProjectsRequest{ Name: ®ion, } response, err := client.KeystoneListProjects(request) diff --git a/pkg/core/deployer/providers/huaweicloud-live/huaweicloud_live.go b/pkg/core/deployer/providers/huaweicloud-live/huaweicloud_live.go index 73382344..7a8c81d6 100644 --- a/pkg/core/deployer/providers/huaweicloud-live/huaweicloud_live.go +++ b/pkg/core/deployer/providers/huaweicloud-live/huaweicloud_live.go @@ -9,7 +9,7 @@ import ( "github.com/huaweicloud/huaweicloud-sdk-go-v3/core/auth/basic" "github.com/huaweicloud/huaweicloud-sdk-go-v3/core/auth/global" hwiam "github.com/huaweicloud/huaweicloud-sdk-go-v3/services/iam/v3" - hwiamModel "github.com/huaweicloud/huaweicloud-sdk-go-v3/services/iam/v3/model" + hwiammodel "github.com/huaweicloud/huaweicloud-sdk-go-v3/services/iam/v3/model" hwiamregion "github.com/huaweicloud/huaweicloud-sdk-go-v3/services/iam/v3/region" hwlivemodel "github.com/huaweicloud/huaweicloud-sdk-go-v3/services/live/v1/model" hwliveregion "github.com/huaweicloud/huaweicloud-sdk-go-v3/services/live/v1/region" @@ -262,7 +262,7 @@ func getSDKProjectId(accessKeyId, secretAccessKey, region string) (string, error client := hwiam.NewIamClient(hcClient) - request := &hwiamModel.KeystoneListProjectsRequest{ + request := &hwiammodel.KeystoneListProjectsRequest{ Name: ®ion, } response, err := client.KeystoneListProjects(request) diff --git a/pkg/core/deployer/providers/huaweicloud-vod/consts.go b/pkg/core/deployer/providers/huaweicloud-vod/consts.go new file mode 100644 index 00000000..4ebac3d6 --- /dev/null +++ b/pkg/core/deployer/providers/huaweicloud-vod/consts.go @@ -0,0 +1,6 @@ +package huaweicloudvod + +const ( + // 匹配模式:精确匹配。 + DOMAIN_MATCH_PATTERN_EXACT = "exact" +) diff --git a/pkg/core/deployer/providers/huaweicloud-vod/huaweicloud_vod.go b/pkg/core/deployer/providers/huaweicloud-vod/huaweicloud_vod.go new file mode 100644 index 00000000..1df65fc9 --- /dev/null +++ b/pkg/core/deployer/providers/huaweicloud-vod/huaweicloud_vod.go @@ -0,0 +1,249 @@ +package huaweicloudvod + +import ( + "context" + "errors" + "fmt" + "log/slog" + + "github.com/huaweicloud/huaweicloud-sdk-go-v3/core/auth/basic" + "github.com/huaweicloud/huaweicloud-sdk-go-v3/core/auth/global" + hwiam "github.com/huaweicloud/huaweicloud-sdk-go-v3/services/iam/v3" + hwiammodel "github.com/huaweicloud/huaweicloud-sdk-go-v3/services/iam/v3/model" + hwiamregion "github.com/huaweicloud/huaweicloud-sdk-go-v3/services/iam/v3/region" + hwvodmodel "github.com/huaweicloud/huaweicloud-sdk-go-v3/services/vod/v1/model" + hwvodregion "github.com/huaweicloud/huaweicloud-sdk-go-v3/services/vod/v1/region" + "github.com/samber/lo" + + hwvod "github.com/certimate-go/certimate/pkg/sdk3rd-trimmed/github.com/huaweicloud/huaweicloud-sdk-go-v3/services/vod/v1" + + "github.com/certimate-go/certimate/pkg/core" + cmgrimpl "github.com/certimate-go/certimate/pkg/core/certmgr/providers/huaweicloud-scm" +) + +type ( + Provider = core.Deployer + DeployResult = core.DeployerDeployResult +) + +type DeployerConfig struct { + // 华为云 AccessKeyId。 + AccessKeyId string `json:"accessKeyId"` + // 华为云 SecretAccessKey。 + SecretAccessKey string `json:"secretAccessKey"` + // 华为云企业项目 ID。 + EnterpriseProjectId string `json:"enterpriseProjectId,omitempty"` + // 华为云区域。 + Region string `json:"region"` + // 域名匹配模式。 + // 零值时默认值 [DOMAIN_MATCH_PATTERN_EXACT]。 + DomainMatchPattern string `json:"domainMatchPattern,omitempty"` + // 点播加速域名(不支持泛域名)。 + Domain string `json:"domain"` +} + +type Deployer struct { + config *DeployerConfig + logger *slog.Logger + sdkClient *hwvod.VodClient + 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, + EnterpriseProjectId: config.EnterpriseProjectId, + }) + 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)) + } + + // 获取待部署的域名列表 + var domains []string + switch d.config.DomainMatchPattern { + case "", DOMAIN_MATCH_PATTERN_EXACT: + { + if d.config.Domain == "" { + return nil, fmt.Errorf("config `domain` is required") + } + + domains = []string{d.config.Domain} + } + + default: + return nil, fmt.Errorf("unsupported domain match pattern: '%s'", d.config.DomainMatchPattern) + } + + // 遍历更新域名证书 + if len(domains) == 0 { + d.logger.Info("no vod domains to deploy") + } else { + d.logger.Info("found vod domains to deploy", slog.Any("domains", domains)) + var errs []error + + for _, domain := range domains { + select { + case <-ctx.Done(): + return nil, ctx.Err() + default: + if err := d.updateDomainsCertificate(ctx, domain, upres.CertId); err != nil { + errs = append(errs, err) + } + } + } + + if len(errs) > 0 { + return nil, errors.Join(errs...) + } + } + + return &DeployResult{}, nil +} + +func (d *Deployer) updateDomainsCertificate(ctx context.Context, domain string, cloudCertId string) error { + // 查询 HTTPS 配置 + // REF: https://support.huaweicloud.com/api-vod/ShowHttpsConfig.html + showHttpsConfigReq := &hwvodmodel.ShowHttpsConfigRequest{ + Domain: domain, + } + showHttpsConfigResp, err := d.sdkClient.ShowHttpsConfig(showHttpsConfigReq) + d.logger.Debug("sdk request 'vod.ShowHttpsConfig'", slog.Any("request", showHttpsConfigReq), slog.Any("response", showHttpsConfigResp)) + if err != nil { + return fmt.Errorf("failed to execute sdk request 'vod.ShowHttpsConfig': %w", err) + } else if lo.FromPtr(showHttpsConfigResp.CertId) == cloudCertId { + // 已部署过,直接返回 + return nil + } + + // 配置 HTTPS + // REF: https://support.huaweicloud.com/api-vod/UpdateHttpsConfig.html + updateHttpsConfigReq := &hwvodmodel.UpdateHttpsConfigRequest{ + Body: &hwvodmodel.ConfigCdnHttpsReq{ + Domain: domain, + Source: lo.ToPtr("scm"), + CertId: lo.ToPtr(cloudCertId), + HttpsStatus: lo.ToPtr(int32(1)), + Http2: showHttpsConfigResp.Http2, + ForceRedirectHttps: showHttpsConfigResp.ForceRedirectHttps, + }, + } + updateHttpsConfigResp, err := d.sdkClient.UpdateHttpsConfig(updateHttpsConfigReq) + d.logger.Debug("sdk request 'vod.UpdateHttpsConfig'", slog.Any("request", updateHttpsConfigReq), slog.Any("response", updateHttpsConfigResp)) + if err != nil { + return fmt.Errorf("failed to execute sdk request 'vod.UpdateHttpsConfig': %w", err) + } + + return nil +} + +func createSDKClient(accessKeyId, secretAccessKey, region string) (*hwvod.VodClient, error) { + projectId, err := getSDKProjectId(accessKeyId, secretAccessKey, region) + if err != nil { + return nil, err + } + + auth, err := basic.NewCredentialsBuilder(). + WithAk(accessKeyId). + WithSk(secretAccessKey). + WithProjectId(projectId). + SafeBuild() + if err != nil { + return nil, err + } + + hcRegion, err := hwvodregion.SafeValueOf(region) + if err != nil { + return nil, err + } + + hcClient, err := hwvod.VodClientBuilder(). + WithRegion(hcRegion). + WithCredential(auth). + SafeBuild() + if err != nil { + return nil, err + } + + client := hwvod.NewVodClient(hcClient) + return client, nil +} + +func getSDKProjectId(accessKeyId, secretAccessKey, region string) (string, error) { + auth, err := global.NewCredentialsBuilder(). + WithAk(accessKeyId). + WithSk(secretAccessKey). + SafeBuild() + if err != nil { + return "", err + } + + hcRegion, err := hwiamregion.SafeValueOf(region) + if err != nil { + return "", err + } + + hcClient, err := hwiam.IamClientBuilder(). + WithRegion(hcRegion). + WithCredential(auth). + SafeBuild() + if err != nil { + return "", err + } + + client := hwiam.NewIamClient(hcClient) + + request := &hwiammodel.KeystoneListProjectsRequest{ + Name: ®ion, + } + response, err := client.KeystoneListProjects(request) + if err != nil { + return "", err + } else if response.Projects == nil || len(*response.Projects) == 0 { + return "", fmt.Errorf("huaweicloud: no project found") + } + + return (*response.Projects)[0].Id, nil +} diff --git a/pkg/core/deployer/providers/huaweicloud-vod/huaweicloud_vod_test.go b/pkg/core/deployer/providers/huaweicloud-vod/huaweicloud_vod_test.go new file mode 100644 index 00000000..e7b68258 --- /dev/null +++ b/pkg/core/deployer/providers/huaweicloud-vod/huaweicloud_vod_test.go @@ -0,0 +1,58 @@ +package huaweicloudvod_test + +import ( + "testing" + + "github.com/certimate-go/certimate/pkg/core/deployer/internal/tester" + impl "github.com/certimate-go/certimate/pkg/core/deployer/providers/huaweicloud-vod" +) + +var ( + fp = tester.Args("HUAWEICLOUDVOD_") + fTestCertPath string + fTestKeyPath string + fAccessKeyId string + fSecretAccessKey string + fRegion string + fDomain 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(&fDomain, "DOMAIN") +} + +/* +Shell command to run this test: + + go test -v ./huaweicloud_vod_test.go -args \ + --HUAWEICLOUDVOD_TESTCERTPATH="/path/to/your-test-cert.pem" \ + --HUAWEICLOUDVOD_TESTKEYPATH="/path/to/your-test-key.pem" \ + --HUAWEICLOUDVOD_ACCESSKEYID="your-access-key-id" \ + --HUAWEICLOUDVOD_SECRETACCESSKEY="your-secret-access-key" \ + --HUAWEICLOUDVOD_REGION="cn-north-1" \ + --HUAWEICLOUDVOD_DOMAIN="example.com" +*/ +func TestProvider(t *testing.T) { + fp.Parse() + + t.Run("Deploy", func(t *testing.T) { + provider, err := impl.NewDeployer(&impl.DeployerConfig{ + AccessKeyId: fAccessKeyId, + SecretAccessKey: fSecretAccessKey, + Region: fRegion, + DomainMatchPattern: impl.DOMAIN_MATCH_PATTERN_EXACT, + Domain: fDomain, + }) + 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/huaweicloud-waf/huaweicloud_waf.go b/pkg/core/deployer/providers/huaweicloud-waf/huaweicloud_waf.go index 3ba0aaf9..7a1d5327 100644 --- a/pkg/core/deployer/providers/huaweicloud-waf/huaweicloud_waf.go +++ b/pkg/core/deployer/providers/huaweicloud-waf/huaweicloud_waf.go @@ -9,7 +9,7 @@ import ( "github.com/huaweicloud/huaweicloud-sdk-go-v3/core/auth/basic" "github.com/huaweicloud/huaweicloud-sdk-go-v3/core/auth/global" hwiam "github.com/huaweicloud/huaweicloud-sdk-go-v3/services/iam/v3" - hwiamModel "github.com/huaweicloud/huaweicloud-sdk-go-v3/services/iam/v3/model" + hwiammodel "github.com/huaweicloud/huaweicloud-sdk-go-v3/services/iam/v3/model" hwiamregion "github.com/huaweicloud/huaweicloud-sdk-go-v3/services/iam/v3/region" hwwafmodel "github.com/huaweicloud/huaweicloud-sdk-go-v3/services/waf/v1/model" hwwafregion "github.com/huaweicloud/huaweicloud-sdk-go-v3/services/waf/v1/region" @@ -372,7 +372,7 @@ func getSDKProjectId(accessKeyId, secretAccessKey, region string) (string, error client := hwiam.NewIamClient(hcClient) - request := &hwiamModel.KeystoneListProjectsRequest{ + request := &hwiammodel.KeystoneListProjectsRequest{ Name: ®ion, } response, err := client.KeystoneListProjects(request) diff --git a/pkg/sdk3rd-trimmed/github.com/huaweicloud/huaweicloud-sdk-go-v3/services/vod/v1/vod_client.go b/pkg/sdk3rd-trimmed/github.com/huaweicloud/huaweicloud-sdk-go-v3/services/vod/v1/vod_client.go new file mode 100644 index 00000000..7c21b7c6 --- /dev/null +++ b/pkg/sdk3rd-trimmed/github.com/huaweicloud/huaweicloud-sdk-go-v3/services/vod/v1/vod_client.go @@ -0,0 +1,39 @@ +package v1 + +import ( + httpclient "github.com/huaweicloud/huaweicloud-sdk-go-v3/core" + vod "github.com/huaweicloud/huaweicloud-sdk-go-v3/services/vod/v1" + "github.com/huaweicloud/huaweicloud-sdk-go-v3/services/vod/v1/model" +) + +type VodClient struct { + HcClient *httpclient.HcHttpClient +} + +func NewVodClient(hcClient *httpclient.HcHttpClient) *VodClient { + return &VodClient{HcClient: hcClient} +} + +func VodClientBuilder() *httpclient.HcHttpClientBuilder { + return vod.VodClientBuilder() +} + +func (c *VodClient) ShowHttpsConfig(request *model.ShowHttpsConfigRequest) (*model.ShowHttpsConfigResponse, error) { + requestDef := GenReqDefForShowHttpsConfig() + + if resp, err := c.HcClient.Sync(request, requestDef); err != nil { + return nil, err + } else { + return resp.(*model.ShowHttpsConfigResponse), nil + } +} + +func (c *VodClient) UpdateHttpsConfig(request *model.UpdateHttpsConfigRequest) (*model.UpdateHttpsConfigResponse, error) { + requestDef := GenReqDefForUpdateHttpsConfig() + + if resp, err := c.HcClient.Sync(request, requestDef); err != nil { + return nil, err + } else { + return resp.(*model.UpdateHttpsConfigResponse), nil + } +} diff --git a/pkg/sdk3rd-trimmed/github.com/huaweicloud/huaweicloud-sdk-go-v3/services/vod/v1/vod_meta.go b/pkg/sdk3rd-trimmed/github.com/huaweicloud/huaweicloud-sdk-go-v3/services/vod/v1/vod_meta.go new file mode 100644 index 00000000..e9fe347e --- /dev/null +++ b/pkg/sdk3rd-trimmed/github.com/huaweicloud/huaweicloud-sdk-go-v3/services/vod/v1/vod_meta.go @@ -0,0 +1,14 @@ +package v1 + +import ( + "github.com/huaweicloud/huaweicloud-sdk-go-v3/core/def" + vod "github.com/huaweicloud/huaweicloud-sdk-go-v3/services/vod/v1" +) + +func GenReqDefForShowHttpsConfig() *def.HttpRequestDef { + return vod.GenReqDefForShowHttpsConfig() +} + +func GenReqDefForUpdateHttpsConfig() *def.HttpRequestDef { + return vod.GenReqDefForUpdateHttpsConfig() +} diff --git a/ui/src/components/workflow/designer/forms/BizDeployNodeConfigFieldsProvider.tsx b/ui/src/components/workflow/designer/forms/BizDeployNodeConfigFieldsProvider.tsx index c0e683ff..cd8e8635 100644 --- a/ui/src/components/workflow/designer/forms/BizDeployNodeConfigFieldsProvider.tsx +++ b/ui/src/components/workflow/designer/forms/BizDeployNodeConfigFieldsProvider.tsx @@ -72,6 +72,7 @@ import BizDeployNodeConfigFieldsProviderHuaweiCloudCDN from "./BizDeployNodeConf import BizDeployNodeConfigFieldsProviderHuaweiCloudELB from "./BizDeployNodeConfigFieldsProviderHuaweiCloudELB"; import BizDeployNodeConfigFieldsProviderHuaweiCloudLive from "./BizDeployNodeConfigFieldsProviderHuaweiCloudLive"; import BizDeployNodeConfigFieldsProviderHuaweiCloudOBS from "./BizDeployNodeConfigFieldsProviderHuaweiCloudOBS"; +import BizDeployNodeConfigFieldsProviderHuaweiCloudVOD from "./BizDeployNodeConfigFieldsProviderHuaweiCloudVOD"; import BizDeployNodeConfigFieldsProviderHuaweiCloudWAF from "./BizDeployNodeConfigFieldsProviderHuaweiCloudWAF"; import BizDeployNodeConfigFieldsProviderJDCloudALB from "./BizDeployNodeConfigFieldsProviderJDCloudALB"; import BizDeployNodeConfigFieldsProviderJDCloudCDN from "./BizDeployNodeConfigFieldsProviderJDCloudCDN"; @@ -219,6 +220,7 @@ const providerComponentMap: Partial { return ( <> + } + > + + + { const getInitialValues = (): Nullish>> => { return { + region: "", instanceId: "", domainMatchPattern: DOMAIN_MATCH_PATTERN_EXACT, domain: "", @@ -85,6 +96,7 @@ const getSchema = ({ i18n = getI18n() }: { i18n?: ReturnType }) return z .object({ + region: z.string().nonempty(), instanceId: z.string().nonempty(), domainMatchPattern: z.string().nonempty().default(DOMAIN_MATCH_PATTERN_EXACT), domain: z.string().nullish(), diff --git a/ui/src/components/workflow/designer/forms/BizDeployNodeConfigFieldsProviderHuaweiCloudLive.tsx b/ui/src/components/workflow/designer/forms/BizDeployNodeConfigFieldsProviderHuaweiCloudLive.tsx index e291a7af..e68d6a17 100644 --- a/ui/src/components/workflow/designer/forms/BizDeployNodeConfigFieldsProviderHuaweiCloudLive.tsx +++ b/ui/src/components/workflow/designer/forms/BizDeployNodeConfigFieldsProviderHuaweiCloudLive.tsx @@ -26,6 +26,16 @@ const BizDeployNodeConfigFieldsProviderHuaweiCloudLive = () => { return ( <> + } + > + + + { const getInitialValues = (): Nullish>> => { return { + region: "", domainMatchPattern: DOMAIN_MATCH_PATTERN_EXACT, domain: "", }; @@ -66,6 +77,7 @@ const getSchema = ({ i18n = getI18n() }: { i18n?: ReturnType }) return z .object({ + region: z.string().nonempty(), domainMatchPattern: z.string().nonempty().default(DOMAIN_MATCH_PATTERN_EXACT), domain: z.string().nullish(), }) diff --git a/ui/src/components/workflow/designer/forms/BizDeployNodeConfigFieldsProviderHuaweiCloudVOD.tsx b/ui/src/components/workflow/designer/forms/BizDeployNodeConfigFieldsProviderHuaweiCloudVOD.tsx new file mode 100644 index 00000000..521c9de5 --- /dev/null +++ b/ui/src/components/workflow/designer/forms/BizDeployNodeConfigFieldsProviderHuaweiCloudVOD.tsx @@ -0,0 +1,103 @@ +import { getI18n, useTranslation } from "react-i18next"; +import { Form, Input, Radio } from "antd"; +import { createSchemaFieldRule } from "antd-zod"; +import { z } from "zod"; + +import { isDomain } from "@/utils/validator"; + +import { useFormNestedFieldsContext } from "./_context"; + +const DOMAIN_MATCH_PATTERN_EXACT = "exact" as const; + +const BizDeployNodeConfigFieldsProviderHuaweiCloudVOD = () => { + const { i18n, t } = useTranslation(); + + const { parentNamePath } = useFormNestedFieldsContext(); + const formSchema = z.object({ + [parentNamePath]: getSchema({ i18n }), + }); + const formRule = createSchemaFieldRule(formSchema); + const initialValues = getInitialValues(); + + return ( + <> + } + > + + + + + ({ + label: t(`workflow_node.deploy.form.shared_domain_match_pattern.option.${s}.label`), + value: s, + }))} + /> + + + + + + + ); +}; + +const getInitialValues = (): Nullish>> => { + return { + region: "", + domainMatchPattern: DOMAIN_MATCH_PATTERN_EXACT, + domain: "", + }; +}; + +const getSchema = ({ i18n = getI18n() }: { i18n?: ReturnType }) => { + const { t } = i18n; + + return z + .object({ + region: z.string().nonempty(), + domainMatchPattern: z.string().nonempty().default(DOMAIN_MATCH_PATTERN_EXACT), + domain: z.string().nullish(), + }) + .superRefine((values, ctx) => { + if (values.domainMatchPattern) { + switch (values.domainMatchPattern) { + case DOMAIN_MATCH_PATTERN_EXACT: + { + const scDomain = z.string().refine((v) => isDomain(v), t("common.errmsg.domain_invalid")); + const spDomain = scDomain.safeParse(values.domain); + if (!spDomain.success) { + ctx.addIssue({ + code: "custom", + message: z.treeifyError(spDomain.error).errors.join(), + path: ["domain"], + }); + } + } + break; + } + } + }); +}; + +const _default = Object.assign(BizDeployNodeConfigFieldsProviderHuaweiCloudVOD, { + getInitialValues, + getSchema, +}); + +export default _default; diff --git a/ui/src/domain/provider.ts b/ui/src/domain/provider.ts index c43c8f17..0513965a 100644 --- a/ui/src/domain/provider.ts +++ b/ui/src/domain/provider.ts @@ -678,6 +678,7 @@ export const DEPLOYMENT_PROVIDERS = Object.freeze({ HUAWEICLOUD_LIVE: `${ACCESS_PROVIDERS.HUAWEICLOUD}-live`, HUAWEICLOUD_OBS: `${ACCESS_PROVIDERS.HUAWEICLOUD}-obs`, HUAWEICLOUD_SCM: `${ACCESS_PROVIDERS.HUAWEICLOUD}-scm`, + HUAWEICLOUD_VOD: `${ACCESS_PROVIDERS.HUAWEICLOUD}-vod`, HUAWEICLOUD_WAF: `${ACCESS_PROVIDERS.HUAWEICLOUD}-waf`, JDCLOUD_ALB: `${ACCESS_PROVIDERS.JDCLOUD}-alb`, JDCLOUD_CDN: `${ACCESS_PROVIDERS.JDCLOUD}-cdn`, @@ -829,6 +830,7 @@ export const deploymentProvidersMap: Map
(Please open the browser devtools, and visit the \"网站列表 -> 证书管理 -> 证书\" page to capture network requests, then you can get the certificate ID.)" }, - "huaweicloud_aad_domain": { - "label": "Huawei Cloud AAD domain", - "placeholder": "Please enter Huawei Cloud AAD domain name" + "huaweicloud_aad_region": { + "label": "Huawei Cloud region", + "placeholder": "Please enter Huawei Cloud AAD region (e.g. cn-north-4)", + "tooltip": "For more information, see https://console-intl.huaweicloud.com/apiexplorer/#/endpoint" }, "huaweicloud_aad_instance_id": { "label": "Huawei Cloud AAD instance ID", "placeholder": "Please enter Huawei Cloud AAD instance ID", "tooltip": "For more information, see https://console-intl.huaweicloud.com/cnad/#/cnad/cad/list" }, + "huaweicloud_aad_domain": { + "label": "Huawei Cloud AAD domain", + "placeholder": "Please enter Huawei Cloud AAD domain name" + }, "huaweicloud_apig_region": { "label": "Huawei Cloud region", "placeholder": "Please enter Huawei Cloud API gateway region (e.g. cn-north-1)", @@ -1671,6 +1676,15 @@ "label": "Huawei Cloud Live streaming domain", "placeholder": "Please enter Huawei Cloud Live streaming domain name" }, + "huaweicloud_vod_region": { + "label": "Huawei Cloud region", + "placeholder": "Please enter Huawei Cloud VOD region (e.g. cn-north-1)", + "tooltip": "For more information, see https://console-intl.huaweicloud.com/apiexplorer/#/endpoint" + }, + "huaweicloud_vod_domain": { + "label": "Huawei Cloud VOD domain", + "placeholder": "Please enter Huawei Cloud VOD domain name" + }, "huaweicloud_waf_region": { "label": "Huawei Cloud region", "placeholder": "Please enter Huawei Cloud WAF region (e.g. cn-north-1)", diff --git a/ui/src/i18n/resources/zh/nls.provider.json b/ui/src/i18n/resources/zh/nls.provider.json index 830f91ea..d827c35f 100644 --- a/ui/src/i18n/resources/zh/nls.provider.json +++ b/ui/src/i18n/resources/zh/nls.provider.json @@ -168,6 +168,7 @@ "huaweicloud_live": "华为云 - 视频直播 Live", "huaweicloud_obs": "华为云 - 对象储存服务 OBS", "huaweicloud_scm_upload": "华为云 - 上传到云证书管理服务 SCM", + "huaweicloud_vod": "华为云 - 视频点播 VOD", "huaweicloud_waf": "华为云 - Web 应用防火墙 WAF", "infomaniak": "Infomaniak", "ionos": "IONOS", diff --git a/ui/src/i18n/resources/zh/nls.workflow.nodes.json b/ui/src/i18n/resources/zh/nls.workflow.nodes.json index 6d3273c4..cadbec10 100644 --- a/ui/src/i18n/resources/zh/nls.workflow.nodes.json +++ b/ui/src/i18n/resources/zh/nls.workflow.nodes.json @@ -1580,6 +1580,11 @@ "placeholder": "请输入 GoEdge 证书 ID", "tooltip": "请登录 GoEdge 控制台查看

(目前需要在「网站列表 -> 证书管理 -> 证书」页面,并打开浏览器开发者工具抓取网络请求后得到证书 ID)" }, + "huaweicloud_aad_region": { + "label": "华为云服务区域", + "placeholder": "请输入华为云 DDoS 高防服务区域(例如:cn-north-4)", + "tooltip": "这是什么?请参阅 https://console.huaweicloud.com/apiexplorer/#/endpoint" + }, "huaweicloud_aad_instance_id": { "label": "华为云 DDoS 高防实例 ID", "placeholder": "请输入华为云 DDoS 高防实例 ID", @@ -1670,6 +1675,15 @@ "label": "华为云视频直播流域名", "placeholder": "请输入华为云视频直播流域名" }, + "huaweicloud_vod_region": { + "label": "华为云服务区域", + "placeholder": "请输入华为云视频点播服务区域(例如:cn-north-1)", + "tooltip": "这是什么?请参阅 https://console.huaweicloud.com/apiexplorer/#/endpoint" + }, + "huaweicloud_vod_domain": { + "label": "华为云视频点播加速域名", + "placeholder": "请输入华为云视频点播加速域名" + }, "huaweicloud_waf_region": { "label": "华为云服务区域", "placeholder": "请输入华为云 WAF 服务区域(例如:cn-north-1)",