diff --git a/go.mod b/go.mod index 8fa0f6a6..c5116a5b 100644 --- a/go.mod +++ b/go.mod @@ -55,6 +55,7 @@ require ( github.com/go-openapi/jsonreference v0.20.2 // indirect github.com/go-openapi/swag v0.23.0 // indirect github.com/go-telegram-bot-api/telegram-bot-api v4.6.4+incompatible // indirect + github.com/go-viper/mapstructure/v2 v2.2.1 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/protobuf v1.5.4 // indirect github.com/google/gnostic-models v0.6.8 // indirect diff --git a/go.sum b/go.sum index d848839f..b212a754 100644 --- a/go.sum +++ b/go.sum @@ -379,6 +379,8 @@ github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1v github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8= github.com/go-telegram-bot-api/telegram-bot-api v4.6.4+incompatible h1:2cauKuaELYAEARXRkq2LrJ0yDDv1rW7+wrTEdVL3uaU= github.com/go-telegram-bot-api/telegram-bot-api v4.6.4+incompatible/go.mod h1:qf9acutJ8cwBUhm1bqgz6Bei9/C/c93FPDljKWwsOgM= +github.com/go-viper/mapstructure/v2 v2.2.1 h1:ZAaOCxANMuZx5RCeg0mBdEZk7DZasvvZIxtHqx8aGss= +github.com/go-viper/mapstructure/v2 v2.2.1/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= github.com/go-zookeeper/zk v1.0.2/go.mod h1:nOB03cncLtlp4t+UAkGSV+9beXP/akpekBwL+UX1Qcw= github.com/goccy/go-json v0.10.4 h1:JSwxQzIqKfmFX1swYPpUThQZp/Ka4wzJdK0LWVytLPM= github.com/goccy/go-json v0.10.4/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M= diff --git a/internal/applicant/applicant.go b/internal/applicant/applicant.go index 2f2f411f..51512416 100644 --- a/internal/applicant/applicant.go +++ b/internal/applicant/applicant.go @@ -18,16 +18,6 @@ import ( "github.com/usual2970/certimate/internal/repository" ) -type applyConfig struct { - Domains string - ContactEmail string - AccessConfig string - KeyAlgorithm string - Nameservers string - PropagationTimeout int32 - DisableFollowCNAME bool -} - type ApplyCertResult struct { Certificate string PrivateKey string @@ -41,6 +31,18 @@ type Applicant interface { Apply() (*ApplyCertResult, error) } +type applicantOptions struct { + Domains []string + ContactEmail string + Provider domain.ApplyDNSProviderType + ProviderAccessConfig map[string]any + ProviderApplyConfig map[string]any + KeyAlgorithm string + Nameservers []string + PropagationTimeout int32 + DisableFollowCNAME bool +} + func NewWithApplyNode(node *domain.WorkflowNode) (Applicant, error) { if node.Type != domain.WorkflowNodeTypeApply { return nil, fmt.Errorf("node type is not apply") @@ -53,28 +55,35 @@ func NewWithApplyNode(node *domain.WorkflowNode) (Applicant, error) { return nil, fmt.Errorf("failed to get access #%s record: %w", accessId, err) } - applyConfig := &applyConfig{ - Domains: node.GetConfigString("domains"), - ContactEmail: node.GetConfigString("contactEmail"), - AccessConfig: access.Config, - KeyAlgorithm: node.GetConfigString("keyAlgorithm"), - Nameservers: node.GetConfigString("nameservers"), - PropagationTimeout: node.GetConfigInt32("propagationTimeout"), - DisableFollowCNAME: node.GetConfigBool("disableFollowCNAME"), + accessConfig, err := access.UnmarshalConfigToMap() + if err != nil { + return nil, fmt.Errorf("failed to unmarshal access config: %w", err) } - challengeProvider, err := createChallengeProvider(domain.AccessProviderType(access.Provider), access.Config, applyConfig) + options := &applicantOptions{ + Domains: strings.Split(node.GetConfigString("domains"), ";"), + ContactEmail: node.GetConfigString("contactEmail"), + Provider: domain.ApplyDNSProviderType(node.GetConfigString("provider")), + ProviderAccessConfig: accessConfig, + ProviderApplyConfig: node.GetConfigMap("providerConfig"), + KeyAlgorithm: node.GetConfigString("keyAlgorithm"), + Nameservers: strings.Split(node.GetConfigString("nameservers"), ";"), + PropagationTimeout: node.GetConfigInt32("propagationTimeout"), + DisableFollowCNAME: node.GetConfigBool("disableFollowCNAME"), + } + + applicant, err := createApplicant(options) if err != nil { return nil, err } return &proxyApplicant{ - applicant: challengeProvider, - applyConfig: applyConfig, + applicant: applicant, + options: options, }, nil } -func apply(challengeProvider challenge.Provider, applyConfig *applyConfig) (*ApplyCertResult, error) { +func apply(challengeProvider challenge.Provider, options *applicantOptions) (*ApplyCertResult, error) { settingsRepo := repository.NewSettingsRepository() settings, _ := settingsRepo.GetByName(context.Background(), "sslProvider") @@ -92,20 +101,20 @@ func apply(challengeProvider challenge.Provider, applyConfig *applyConfig) (*App sslProviderConfig.Provider = defaultSSLProvider } - myUser, err := newAcmeUser(sslProviderConfig.Provider, applyConfig.ContactEmail) + myUser, err := newAcmeUser(sslProviderConfig.Provider, options.ContactEmail) if err != nil { return nil, err } // Some unified lego environment variables are configured here. // link: https://github.com/go-acme/lego/issues/1867 - os.Setenv("LEGO_DISABLE_CNAME_SUPPORT", strconv.FormatBool(applyConfig.DisableFollowCNAME)) + os.Setenv("LEGO_DISABLE_CNAME_SUPPORT", strconv.FormatBool(options.DisableFollowCNAME)) config := lego.NewConfig(myUser) // This CA URL is configured for a local dev instance of Boulder running in Docker in a VM. config.CADirURL = sslProviderUrls[sslProviderConfig.Provider] - config.Certificate.KeyType = parseKeyAlgorithm(applyConfig.KeyAlgorithm) + config.Certificate.KeyType = parseKeyAlgorithm(options.KeyAlgorithm) // A client facilitates communication with the CA server. client, err := lego.NewClient(config) @@ -114,8 +123,8 @@ func apply(challengeProvider challenge.Provider, applyConfig *applyConfig) (*App } challengeOptions := make([]dns01.ChallengeOption, 0) - if len(applyConfig.Nameservers) > 0 { - challengeOptions = append(challengeOptions, dns01.AddRecursiveNameservers(dns01.ParseNameservers(strings.Split(applyConfig.Nameservers, ";")))) + if len(options.Nameservers) > 0 { + challengeOptions = append(challengeOptions, dns01.AddRecursiveNameservers(dns01.ParseNameservers(options.Nameservers))) challengeOptions = append(challengeOptions, dns01.DisableAuthoritativeNssPropagationRequirement()) } @@ -131,7 +140,7 @@ func apply(challengeProvider challenge.Provider, applyConfig *applyConfig) (*App } certRequest := certificate.ObtainRequest{ - Domains: strings.Split(applyConfig.Domains, ";"), + Domains: options.Domains, Bundle: true, } certResource, err := client.Certificate.Obtain(certRequest) @@ -143,9 +152,9 @@ func apply(challengeProvider challenge.Provider, applyConfig *applyConfig) (*App PrivateKey: string(certResource.PrivateKey), Certificate: string(certResource.Certificate), IssuerCertificate: string(certResource.IssuerCertificate), - CSR: string(certResource.CSR), ACMECertUrl: certResource.CertURL, ACMECertStableUrl: certResource.CertStableURL, + CSR: string(certResource.CSR), }, nil } @@ -170,10 +179,10 @@ func parseKeyAlgorithm(algo string) certcrypto.KeyType { // TODO: 暂时使用代理模式以兼容之前版本代码,后续重新实现此处逻辑 type proxyApplicant struct { - applicant challenge.Provider - applyConfig *applyConfig + applicant challenge.Provider + options *applicantOptions } func (d *proxyApplicant) Apply() (*ApplyCertResult, error) { - return apply(d.applicant, d.applyConfig) + return apply(d.applicant, d.options) } diff --git a/internal/applicant/providers.go b/internal/applicant/providers.go index c8800093..94bd8541 100644 --- a/internal/applicant/providers.go +++ b/internal/applicant/providers.go @@ -1,7 +1,6 @@ package applicant import ( - "encoding/json" "fmt" "github.com/go-acme/lego/v4/challenge" @@ -18,19 +17,20 @@ import ( providerPowerDNS "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/powerdns" providerTencentCloud "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/tencentcloud" providerVolcEngine "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/volcengine" + "github.com/usual2970/certimate/internal/pkg/utils/maps" ) -func createChallengeProvider(provider domain.AccessProviderType, accessConfig string, applyConfig *applyConfig) (challenge.Provider, error) { +func createApplicant(options *applicantOptions) (challenge.Provider, error) { /* 注意:如果追加新的常量值,请保持以 ASCII 排序。 NOTICE: If you add new constant, please keep ASCII order. */ - switch provider { - case domain.AccessProviderTypeACMEHttpReq: + switch options.Provider { + case domain.ApplyDNSProviderTypeACMEHttpReq: { - access := &domain.AccessConfigForACMEHttpReq{} - if err := json.Unmarshal([]byte(accessConfig), access); err != nil { - return nil, fmt.Errorf("failed to unmarshal access config: %w", err) + access := domain.AccessConfigForACMEHttpReq{} + if err := maps.Decode(options.ProviderAccessConfig, &access); err != nil { + return nil, fmt.Errorf("failed to decode provider access config: %w", err) } applicant, err := providerACMEHttpReq.NewChallengeProvider(&providerACMEHttpReq.ACMEHttpReqApplicantConfig{ @@ -38,162 +38,162 @@ func createChallengeProvider(provider domain.AccessProviderType, accessConfig st Mode: access.Mode, Username: access.Username, Password: access.Password, - PropagationTimeout: applyConfig.PropagationTimeout, + PropagationTimeout: options.PropagationTimeout, }) return applicant, err } - case domain.AccessProviderTypeAliyun: + case domain.ApplyDNSProviderTypeAliyun, domain.ApplyDNSProviderTypeAliyunDNS: { - access := &domain.AccessConfigForAliyun{} - if err := json.Unmarshal([]byte(accessConfig), access); err != nil { - return nil, fmt.Errorf("failed to unmarshal access config: %w", err) + access := domain.AccessConfigForAliyun{} + if err := maps.Decode(options.ProviderAccessConfig, &access); err != nil { + return nil, fmt.Errorf("failed to decode provider access config: %w", err) } applicant, err := providerAliyun.NewChallengeProvider(&providerAliyun.AliyunApplicantConfig{ AccessKeyId: access.AccessKeyId, AccessKeySecret: access.AccessKeySecret, - PropagationTimeout: applyConfig.PropagationTimeout, + PropagationTimeout: options.PropagationTimeout, }) return applicant, err } - case domain.AccessProviderTypeAWS: + case domain.ApplyDNSProviderTypeAWS, domain.ApplyDNSProviderTypeAWSRoute53: { - access := &domain.AccessConfigForAWS{} - if err := json.Unmarshal([]byte(accessConfig), access); err != nil { - return nil, fmt.Errorf("failed to unmarshal access config: %w", err) + access := domain.AccessConfigForAWS{} + if err := maps.Decode(options.ProviderAccessConfig, &access); err != nil { + return nil, fmt.Errorf("failed to decode provider access config: %w", err) } applicant, err := providerAWS.NewChallengeProvider(&providerAWS.AWSApplicantConfig{ AccessKeyId: access.AccessKeyId, SecretAccessKey: access.SecretAccessKey, - Region: access.Region, - HostedZoneId: access.HostedZoneId, - PropagationTimeout: applyConfig.PropagationTimeout, + Region: maps.GetValueAsString(options.ProviderApplyConfig, "region"), + HostedZoneId: maps.GetValueAsString(options.ProviderApplyConfig, "hostedZoneId"), + PropagationTimeout: options.PropagationTimeout, }) return applicant, err } - case domain.AccessProviderTypeCloudflare: + case domain.ApplyDNSProviderTypeCloudflare: { - access := &domain.AccessConfigForCloudflare{} - if err := json.Unmarshal([]byte(accessConfig), access); err != nil { - return nil, fmt.Errorf("failed to unmarshal access config: %w", err) + access := domain.AccessConfigForCloudflare{} + if err := maps.Decode(options.ProviderAccessConfig, &access); err != nil { + return nil, fmt.Errorf("failed to decode provider access config: %w", err) } applicant, err := providerCloudflare.NewChallengeProvider(&providerCloudflare.CloudflareApplicantConfig{ DnsApiToken: access.DnsApiToken, - PropagationTimeout: applyConfig.PropagationTimeout, + PropagationTimeout: options.PropagationTimeout, }) return applicant, err } - case domain.AccessProviderTypeGoDaddy: + case domain.ApplyDNSProviderTypeGoDaddy: { - access := &domain.AccessConfigForGoDaddy{} - if err := json.Unmarshal([]byte(accessConfig), access); err != nil { - return nil, fmt.Errorf("failed to unmarshal access config: %w", err) + access := domain.AccessConfigForGoDaddy{} + if err := maps.Decode(options.ProviderAccessConfig, &access); err != nil { + return nil, fmt.Errorf("failed to decode provider access config: %w", err) } applicant, err := providerGoDaddy.NewChallengeProvider(&providerGoDaddy.GoDaddyApplicantConfig{ ApiKey: access.ApiKey, ApiSecret: access.ApiSecret, - PropagationTimeout: applyConfig.PropagationTimeout, + PropagationTimeout: options.PropagationTimeout, }) return applicant, err } - case domain.AccessProviderTypeHuaweiCloud: + case domain.ApplyDNSProviderTypeHuaweiCloud, domain.ApplyDNSProviderTypeHuaweiCloudDNS: { - access := &domain.AccessConfigForHuaweiCloud{} - if err := json.Unmarshal([]byte(accessConfig), access); err != nil { - return nil, fmt.Errorf("failed to unmarshal access config: %w", err) + access := domain.AccessConfigForHuaweiCloud{} + if err := maps.Decode(options.ProviderAccessConfig, &access); err != nil { + return nil, fmt.Errorf("failed to decode provider access config: %w", err) } applicant, err := providerHuaweiCloud.NewChallengeProvider(&providerHuaweiCloud.HuaweiCloudApplicantConfig{ AccessKeyId: access.AccessKeyId, SecretAccessKey: access.SecretAccessKey, - Region: access.Region, - PropagationTimeout: applyConfig.PropagationTimeout, + Region: maps.GetValueAsString(options.ProviderApplyConfig, "region"), + PropagationTimeout: options.PropagationTimeout, }) return applicant, err } - case domain.AccessProviderTypeNameDotCom: + case domain.ApplyDNSProviderTypeNameDotCom: { - access := &domain.AccessConfigForNameDotCom{} - if err := json.Unmarshal([]byte(accessConfig), access); err != nil { - return nil, fmt.Errorf("failed to unmarshal access config: %w", err) + access := domain.AccessConfigForNameDotCom{} + if err := maps.Decode(options.ProviderAccessConfig, &access); err != nil { + return nil, fmt.Errorf("failed to decode provider access config: %w", err) } applicant, err := providerNameDotCom.NewChallengeProvider(&providerNameDotCom.NameDotComApplicantConfig{ Username: access.Username, ApiToken: access.ApiToken, - PropagationTimeout: applyConfig.PropagationTimeout, + PropagationTimeout: options.PropagationTimeout, }) return applicant, err } - case domain.AccessProviderTypeNameSilo: + case domain.ApplyDNSProviderTypeNameSilo: { - access := &domain.AccessConfigForNameSilo{} - if err := json.Unmarshal([]byte(accessConfig), access); err != nil { - return nil, fmt.Errorf("failed to unmarshal access config: %w", err) + access := domain.AccessConfigForNameSilo{} + if err := maps.Decode(options.ProviderAccessConfig, &access); err != nil { + return nil, fmt.Errorf("failed to decode provider access config: %w", err) } applicant, err := providerNameSilo.NewChallengeProvider(&providerNameSilo.NameSiloApplicantConfig{ ApiKey: access.ApiKey, - PropagationTimeout: applyConfig.PropagationTimeout, + PropagationTimeout: options.PropagationTimeout, }) return applicant, err } - case domain.AccessProviderTypePowerDNS: + case domain.ApplyDNSProviderTypePowerDNS: { - access := &domain.AccessConfigForPowerDNS{} - if err := json.Unmarshal([]byte(accessConfig), access); err != nil { - return nil, fmt.Errorf("failed to unmarshal access config: %w", err) + access := domain.AccessConfigForPowerDNS{} + if err := maps.Decode(options.ProviderAccessConfig, &access); err != nil { + return nil, fmt.Errorf("failed to decode provider access config: %w", err) } applicant, err := providerPowerDNS.NewChallengeProvider(&providerPowerDNS.PowerDNSApplicantConfig{ ApiUrl: access.ApiUrl, ApiKey: access.ApiKey, - PropagationTimeout: applyConfig.PropagationTimeout, + PropagationTimeout: options.PropagationTimeout, }) return applicant, err } - case domain.AccessProviderTypeTencentCloud: + case domain.ApplyDNSProviderTypeTencentCloud, domain.ApplyDNSProviderTypeTencentCloudDNS: { - access := &domain.AccessConfigForTencentCloud{} - if err := json.Unmarshal([]byte(accessConfig), access); err != nil { - return nil, fmt.Errorf("failed to unmarshal access config: %w", err) + access := domain.AccessConfigForTencentCloud{} + if err := maps.Decode(options.ProviderAccessConfig, &access); err != nil { + return nil, fmt.Errorf("failed to decode provider access config: %w", err) } applicant, err := providerTencentCloud.NewChallengeProvider(&providerTencentCloud.TencentCloudApplicantConfig{ SecretId: access.SecretId, SecretKey: access.SecretKey, - PropagationTimeout: applyConfig.PropagationTimeout, + PropagationTimeout: options.PropagationTimeout, }) return applicant, err } - case domain.AccessProviderTypeVolcEngine: + case domain.ApplyDNSProviderTypeVolcEngine, domain.ApplyDNSProviderTypeVolcEngineDNS: { - access := &domain.AccessConfigForVolcEngine{} - if err := json.Unmarshal([]byte(accessConfig), access); err != nil { - return nil, fmt.Errorf("failed to unmarshal access config: %w", err) + access := domain.AccessConfigForVolcEngine{} + if err := maps.Decode(options.ProviderAccessConfig, &access); err != nil { + return nil, fmt.Errorf("failed to decode provider access config: %w", err) } applicant, err := providerVolcEngine.NewChallengeProvider(&providerVolcEngine.VolcEngineApplicantConfig{ AccessKeyId: access.AccessKeyId, SecretAccessKey: access.SecretAccessKey, - PropagationTimeout: applyConfig.PropagationTimeout, + PropagationTimeout: options.PropagationTimeout, }) return applicant, err } } - return nil, fmt.Errorf("unsupported applicant provider: %s", provider) + return nil, fmt.Errorf("unsupported applicant provider: %s", string(options.Provider)) } diff --git a/internal/deployer/deployer.go b/internal/deployer/deployer.go index 5ad5d6ce..41c589bc 100644 --- a/internal/deployer/deployer.go +++ b/internal/deployer/deployer.go @@ -14,6 +14,12 @@ type Deployer interface { Deploy(ctx context.Context) error } +type deployerOptions struct { + Provider domain.DeployProviderType + ProviderAccessConfig map[string]any + ProviderDeployConfig map[string]any +} + func NewWithDeployNode(node *domain.WorkflowNode, certdata struct { Certificate string PrivateKey string @@ -30,9 +36,16 @@ func NewWithDeployNode(node *domain.WorkflowNode, certdata struct { return nil, fmt.Errorf("failed to get access #%s record: %w", accessId, err) } - deployProvider := node.GetConfigString("provider") - deployConfig := node.GetConfigMap("providerConfig") - deployer, logger, err := createDeployer(domain.DeployProviderType(deployProvider), access.Config, deployConfig) + accessConfig, err := access.UnmarshalConfigToMap() + if err != nil { + return nil, fmt.Errorf("failed to unmarshal access config: %w", err) + } + + deployer, logger, err := createDeployer(&deployerOptions{ + Provider: domain.DeployProviderType(node.GetConfigString("provider")), + ProviderAccessConfig: accessConfig, + ProviderDeployConfig: node.GetConfigMap("providerConfig"), + }) if err != nil { return nil, err } diff --git a/internal/deployer/providers.go b/internal/deployer/providers.go index 62cc1313..dbb75851 100644 --- a/internal/deployer/providers.go +++ b/internal/deployer/providers.go @@ -1,7 +1,6 @@ package deployer import ( - "encoding/json" "fmt" "strconv" @@ -34,30 +33,30 @@ import ( "github.com/usual2970/certimate/internal/pkg/utils/maps" ) -func createDeployer(provider domain.DeployProviderType, accessConfig string, deployConfig map[string]any) (deployer.Deployer, logger.Logger, error) { +func createDeployer(options *deployerOptions) (deployer.Deployer, logger.Logger, error) { logger := logger.NewDefaultLogger() /* 注意:如果追加新的常量值,请保持以 ASCII 排序。 NOTICE: If you add new constant, please keep ASCII order. */ - switch provider { + switch options.Provider { case domain.DeployProviderTypeAliyunALB, domain.DeployProviderTypeAliyunCDN, domain.DeployProviderTypeAliyunCLB, domain.DeployProviderTypeAliyunDCDN, domain.DeployProviderTypeAliyunNLB, domain.DeployProviderTypeAliyunOSS: { - access := &domain.AccessConfigForAliyun{} - if err := json.Unmarshal([]byte(accessConfig), access); err != nil { - return nil, nil, fmt.Errorf("failed to unmarshal access config: %w", err) + access := domain.AccessConfigForAliyun{} + if err := maps.Decode(options.ProviderAccessConfig, &access); err != nil { + return nil, nil, fmt.Errorf("failed to decode provider access config: %w", err) } - switch provider { + switch options.Provider { case domain.DeployProviderTypeAliyunALB: deployer, err := providerAliyunALB.NewWithLogger(&providerAliyunALB.AliyunALBDeployerConfig{ AccessKeyId: access.AccessKeyId, AccessKeySecret: access.AccessKeySecret, - Region: maps.GetValueAsString(deployConfig, "region"), - ResourceType: providerAliyunALB.DeployResourceType(maps.GetValueAsString(deployConfig, "resourceType")), - LoadbalancerId: maps.GetValueAsString(deployConfig, "loadbalancerId"), - ListenerId: maps.GetValueAsString(deployConfig, "listenerId"), + Region: maps.GetValueAsString(options.ProviderDeployConfig, "region"), + ResourceType: providerAliyunALB.DeployResourceType(maps.GetValueAsString(options.ProviderDeployConfig, "resourceType")), + LoadbalancerId: maps.GetValueAsString(options.ProviderDeployConfig, "loadbalancerId"), + ListenerId: maps.GetValueAsString(options.ProviderDeployConfig, "listenerId"), }, logger) return deployer, logger, err @@ -65,7 +64,7 @@ func createDeployer(provider domain.DeployProviderType, accessConfig string, dep deployer, err := providerAliyunCDN.NewWithLogger(&providerAliyunCDN.AliyunCDNDeployerConfig{ AccessKeyId: access.AccessKeyId, AccessKeySecret: access.AccessKeySecret, - Domain: maps.GetValueAsString(deployConfig, "domain"), + Domain: maps.GetValueAsString(options.ProviderDeployConfig, "domain"), }, logger) return deployer, logger, err @@ -73,10 +72,10 @@ func createDeployer(provider domain.DeployProviderType, accessConfig string, dep deployer, err := providerAliyunCLB.NewWithLogger(&providerAliyunCLB.AliyunCLBDeployerConfig{ AccessKeyId: access.AccessKeyId, AccessKeySecret: access.AccessKeySecret, - Region: maps.GetValueAsString(deployConfig, "region"), - ResourceType: providerAliyunCLB.DeployResourceType(maps.GetValueAsString(deployConfig, "resourceType")), - LoadbalancerId: maps.GetValueAsString(deployConfig, "loadbalancerId"), - ListenerPort: maps.GetValueAsInt32(deployConfig, "listenerPort"), + Region: maps.GetValueAsString(options.ProviderDeployConfig, "region"), + ResourceType: providerAliyunCLB.DeployResourceType(maps.GetValueAsString(options.ProviderDeployConfig, "resourceType")), + LoadbalancerId: maps.GetValueAsString(options.ProviderDeployConfig, "loadbalancerId"), + ListenerPort: maps.GetValueAsInt32(options.ProviderDeployConfig, "listenerPort"), }, logger) return deployer, logger, err @@ -84,7 +83,7 @@ func createDeployer(provider domain.DeployProviderType, accessConfig string, dep deployer, err := providerAliyunDCDN.NewWithLogger(&providerAliyunDCDN.AliyunDCDNDeployerConfig{ AccessKeyId: access.AccessKeyId, AccessKeySecret: access.AccessKeySecret, - Domain: maps.GetValueAsString(deployConfig, "domain"), + Domain: maps.GetValueAsString(options.ProviderDeployConfig, "domain"), }, logger) return deployer, logger, err @@ -92,10 +91,10 @@ func createDeployer(provider domain.DeployProviderType, accessConfig string, dep deployer, err := providerAliyunNLB.NewWithLogger(&providerAliyunNLB.AliyunNLBDeployerConfig{ AccessKeyId: access.AccessKeyId, AccessKeySecret: access.AccessKeySecret, - Region: maps.GetValueAsString(deployConfig, "region"), - ResourceType: providerAliyunNLB.DeployResourceType(maps.GetValueAsString(deployConfig, "resourceType")), - LoadbalancerId: maps.GetValueAsString(deployConfig, "loadbalancerId"), - ListenerId: maps.GetValueAsString(deployConfig, "listenerId"), + Region: maps.GetValueAsString(options.ProviderDeployConfig, "region"), + ResourceType: providerAliyunNLB.DeployResourceType(maps.GetValueAsString(options.ProviderDeployConfig, "resourceType")), + LoadbalancerId: maps.GetValueAsString(options.ProviderDeployConfig, "loadbalancerId"), + ListenerId: maps.GetValueAsString(options.ProviderDeployConfig, "listenerId"), }, logger) return deployer, logger, err @@ -103,9 +102,9 @@ func createDeployer(provider domain.DeployProviderType, accessConfig string, dep deployer, err := providerAliyunOSS.NewWithLogger(&providerAliyunOSS.AliyunOSSDeployerConfig{ AccessKeyId: access.AccessKeyId, AccessKeySecret: access.AccessKeySecret, - Region: maps.GetValueAsString(deployConfig, "region"), - Bucket: maps.GetValueAsString(deployConfig, "bucket"), - Domain: maps.GetValueAsString(deployConfig, "domain"), + Region: maps.GetValueAsString(options.ProviderDeployConfig, "region"), + Bucket: maps.GetValueAsString(options.ProviderDeployConfig, "bucket"), + Domain: maps.GetValueAsString(options.ProviderDeployConfig, "domain"), }, logger) return deployer, logger, err @@ -116,63 +115,63 @@ func createDeployer(provider domain.DeployProviderType, accessConfig string, dep case domain.DeployProviderTypeBaiduCloudCDN: { - access := &domain.AccessConfigForBaiduCloud{} - if err := json.Unmarshal([]byte(accessConfig), access); err != nil { - return nil, nil, fmt.Errorf("failed to unmarshal access config: %w", err) + access := domain.AccessConfigForBaiduCloud{} + if err := maps.Decode(options.ProviderAccessConfig, &access); err != nil { + return nil, nil, fmt.Errorf("failed to decode provider access config: %w", err) } deployer, err := providerBaiduCloudCDN.NewWithLogger(&providerBaiduCloudCDN.BaiduCloudCDNDeployerConfig{ AccessKeyId: access.AccessKeyId, SecretAccessKey: access.SecretAccessKey, - Domain: maps.GetValueAsString(deployConfig, "domain"), + Domain: maps.GetValueAsString(options.ProviderDeployConfig, "domain"), }, logger) return deployer, logger, err } case domain.DeployProviderTypeBytePlusCDN: { - access := &domain.AccessConfigForBytePlus{} - if err := json.Unmarshal([]byte(accessConfig), access); err != nil { - return nil, nil, fmt.Errorf("failed to unmarshal access config: %w", err) + access := domain.AccessConfigForBytePlus{} + if err := maps.Decode(options.ProviderAccessConfig, &access); err != nil { + return nil, nil, fmt.Errorf("failed to decode provider access config: %w", err) } deployer, err := providerBytePlusCDN.NewWithLogger(&providerBytePlusCDN.BytePlusCDNDeployerConfig{ AccessKey: access.AccessKey, SecretKey: access.SecretKey, - Domain: maps.GetValueAsString(deployConfig, "domain"), + Domain: maps.GetValueAsString(options.ProviderDeployConfig, "domain"), }, logger) return deployer, logger, err } case domain.DeployProviderTypeDogeCloudCDN: { - access := &domain.AccessConfigForDogeCloud{} - if err := json.Unmarshal([]byte(accessConfig), access); err != nil { - return nil, nil, fmt.Errorf("failed to unmarshal access config: %w", err) + access := domain.AccessConfigForDogeCloud{} + if err := maps.Decode(options.ProviderAccessConfig, &access); err != nil { + return nil, nil, fmt.Errorf("failed to decode provider access config: %w", err) } deployer, err := providerDogeCDN.NewWithLogger(&providerDogeCDN.DogeCloudCDNDeployerConfig{ AccessKey: access.AccessKey, SecretKey: access.SecretKey, - Domain: maps.GetValueAsString(deployConfig, "domain"), + Domain: maps.GetValueAsString(options.ProviderDeployConfig, "domain"), }, logger) return deployer, logger, err } case domain.DeployProviderTypeHuaweiCloudCDN, domain.DeployProviderTypeHuaweiCloudELB: { - access := &domain.AccessConfigForHuaweiCloud{} - if err := json.Unmarshal([]byte(accessConfig), access); err != nil { - return nil, nil, fmt.Errorf("failed to unmarshal access config: %w", err) + access := domain.AccessConfigForHuaweiCloud{} + if err := maps.Decode(options.ProviderAccessConfig, &access); err != nil { + return nil, nil, fmt.Errorf("failed to decode provider access config: %w", err) } - switch provider { + switch options.Provider { case domain.DeployProviderTypeHuaweiCloudCDN: deployer, err := providerHuaweiCloudCDN.NewWithLogger(&providerHuaweiCloudCDN.HuaweiCloudCDNDeployerConfig{ AccessKeyId: access.AccessKeyId, SecretAccessKey: access.SecretAccessKey, - Region: maps.GetValueAsString(deployConfig, "region"), - Domain: maps.GetValueAsString(deployConfig, "domain"), + Region: maps.GetValueAsString(options.ProviderDeployConfig, "region"), + Domain: maps.GetValueAsString(options.ProviderDeployConfig, "domain"), }, logger) return deployer, logger, err @@ -180,11 +179,11 @@ func createDeployer(provider domain.DeployProviderType, accessConfig string, dep deployer, err := providerHuaweiCloudELB.NewWithLogger(&providerHuaweiCloudELB.HuaweiCloudELBDeployerConfig{ AccessKeyId: access.AccessKeyId, SecretAccessKey: access.SecretAccessKey, - Region: maps.GetValueAsString(deployConfig, "region"), - ResourceType: providerHuaweiCloudELB.DeployResourceType(maps.GetValueAsString(deployConfig, "resourceType")), - CertificateId: maps.GetValueAsString(deployConfig, "certificateId"), - LoadbalancerId: maps.GetValueAsString(deployConfig, "loadbalancerId"), - ListenerId: maps.GetValueAsString(deployConfig, "listenerId"), + Region: maps.GetValueAsString(options.ProviderDeployConfig, "region"), + ResourceType: providerHuaweiCloudELB.DeployResourceType(maps.GetValueAsString(options.ProviderDeployConfig, "resourceType")), + CertificateId: maps.GetValueAsString(options.ProviderDeployConfig, "certificateId"), + LoadbalancerId: maps.GetValueAsString(options.ProviderDeployConfig, "loadbalancerId"), + ListenerId: maps.GetValueAsString(options.ProviderDeployConfig, "listenerId"), }, logger) return deployer, logger, err @@ -196,58 +195,58 @@ func createDeployer(provider domain.DeployProviderType, accessConfig string, dep case domain.DeployProviderTypeLocal: { deployer, err := providerLocal.NewWithLogger(&providerLocal.LocalDeployerConfig{ - ShellEnv: providerLocal.ShellEnvType(maps.GetValueAsString(deployConfig, "shellEnv")), - PreCommand: maps.GetValueAsString(deployConfig, "preCommand"), - PostCommand: maps.GetValueAsString(deployConfig, "postCommand"), - OutputFormat: providerLocal.OutputFormatType(maps.GetValueOrDefaultAsString(deployConfig, "format", string(providerLocal.OUTPUT_FORMAT_PEM))), - OutputCertPath: maps.GetValueAsString(deployConfig, "certPath"), - OutputKeyPath: maps.GetValueAsString(deployConfig, "keyPath"), - PfxPassword: maps.GetValueAsString(deployConfig, "pfxPassword"), - JksAlias: maps.GetValueAsString(deployConfig, "jksAlias"), - JksKeypass: maps.GetValueAsString(deployConfig, "jksKeypass"), - JksStorepass: maps.GetValueAsString(deployConfig, "jksStorepass"), + ShellEnv: providerLocal.ShellEnvType(maps.GetValueAsString(options.ProviderDeployConfig, "shellEnv")), + PreCommand: maps.GetValueAsString(options.ProviderDeployConfig, "preCommand"), + PostCommand: maps.GetValueAsString(options.ProviderDeployConfig, "postCommand"), + OutputFormat: providerLocal.OutputFormatType(maps.GetValueOrDefaultAsString(options.ProviderDeployConfig, "format", string(providerLocal.OUTPUT_FORMAT_PEM))), + OutputCertPath: maps.GetValueAsString(options.ProviderDeployConfig, "certPath"), + OutputKeyPath: maps.GetValueAsString(options.ProviderDeployConfig, "keyPath"), + PfxPassword: maps.GetValueAsString(options.ProviderDeployConfig, "pfxPassword"), + JksAlias: maps.GetValueAsString(options.ProviderDeployConfig, "jksAlias"), + JksKeypass: maps.GetValueAsString(options.ProviderDeployConfig, "jksKeypass"), + JksStorepass: maps.GetValueAsString(options.ProviderDeployConfig, "jksStorepass"), }, logger) return deployer, logger, err } case domain.DeployProviderTypeKubernetesSecret: { - access := &domain.AccessConfigForKubernetes{} - if err := json.Unmarshal([]byte(accessConfig), access); err != nil { - return nil, nil, fmt.Errorf("failed to unmarshal access config: %w", err) + access := domain.AccessConfigForKubernetes{} + if err := maps.Decode(options.ProviderAccessConfig, &access); err != nil { + return nil, nil, fmt.Errorf("failed to decode provider access config: %w", err) } deployer, err := providerK8sSecret.NewWithLogger(&providerK8sSecret.K8sSecretDeployerConfig{ KubeConfig: access.KubeConfig, - Namespace: maps.GetValueOrDefaultAsString(deployConfig, "namespace", "default"), - SecretName: maps.GetValueAsString(deployConfig, "secretName"), - SecretType: maps.GetValueOrDefaultAsString(deployConfig, "secretType", "kubernetes.io/tls"), - SecretDataKeyForCrt: maps.GetValueOrDefaultAsString(deployConfig, "secretDataKeyForCrt", "tls.crt"), - SecretDataKeyForKey: maps.GetValueOrDefaultAsString(deployConfig, "secretDataKeyForKey", "tls.key"), + Namespace: maps.GetValueOrDefaultAsString(options.ProviderDeployConfig, "namespace", "default"), + SecretName: maps.GetValueAsString(options.ProviderDeployConfig, "secretName"), + SecretType: maps.GetValueOrDefaultAsString(options.ProviderDeployConfig, "secretType", "kubernetes.io/tls"), + SecretDataKeyForCrt: maps.GetValueOrDefaultAsString(options.ProviderDeployConfig, "secretDataKeyForCrt", "tls.crt"), + SecretDataKeyForKey: maps.GetValueOrDefaultAsString(options.ProviderDeployConfig, "secretDataKeyForKey", "tls.key"), }, logger) return deployer, logger, err } case domain.DeployProviderTypeQiniuCDN: { - access := &domain.AccessConfigForQiniu{} - if err := json.Unmarshal([]byte(accessConfig), access); err != nil { - return nil, nil, fmt.Errorf("failed to unmarshal access config: %w", err) + access := domain.AccessConfigForQiniu{} + if err := maps.Decode(options.ProviderAccessConfig, &access); err != nil { + return nil, nil, fmt.Errorf("failed to decode provider access config: %w", err) } deployer, err := providerQiniuCDN.NewWithLogger(&providerQiniuCDN.QiniuCDNDeployerConfig{ AccessKey: access.AccessKey, SecretKey: access.SecretKey, - Domain: maps.GetValueAsString(deployConfig, "domain"), + Domain: maps.GetValueAsString(options.ProviderDeployConfig, "domain"), }, logger) return deployer, logger, err } case domain.DeployProviderTypeSSH: { - access := &domain.AccessConfigForSSH{} - if err := json.Unmarshal([]byte(accessConfig), access); err != nil { - return nil, nil, fmt.Errorf("failed to unmarshal access config: %w", err) + access := domain.AccessConfigForSSH{} + if err := maps.Decode(options.ProviderAccessConfig, &access); err != nil { + return nil, nil, fmt.Errorf("failed to decode provider access config: %w", err) } sshPort, _ := strconv.ParseInt(access.Port, 10, 32) @@ -258,32 +257,32 @@ func createDeployer(provider domain.DeployProviderType, accessConfig string, dep SshPassword: access.Password, SshKey: access.Key, SshKeyPassphrase: access.KeyPassphrase, - PreCommand: maps.GetValueAsString(deployConfig, "preCommand"), - PostCommand: maps.GetValueAsString(deployConfig, "postCommand"), - OutputFormat: providerSSH.OutputFormatType(maps.GetValueOrDefaultAsString(deployConfig, "format", string(providerSSH.OUTPUT_FORMAT_PEM))), - OutputCertPath: maps.GetValueAsString(deployConfig, "certPath"), - OutputKeyPath: maps.GetValueAsString(deployConfig, "keyPath"), - PfxPassword: maps.GetValueAsString(deployConfig, "pfxPassword"), - JksAlias: maps.GetValueAsString(deployConfig, "jksAlias"), - JksKeypass: maps.GetValueAsString(deployConfig, "jksKeypass"), - JksStorepass: maps.GetValueAsString(deployConfig, "jksStorepass"), + PreCommand: maps.GetValueAsString(options.ProviderDeployConfig, "preCommand"), + PostCommand: maps.GetValueAsString(options.ProviderDeployConfig, "postCommand"), + OutputFormat: providerSSH.OutputFormatType(maps.GetValueOrDefaultAsString(options.ProviderDeployConfig, "format", string(providerSSH.OUTPUT_FORMAT_PEM))), + OutputCertPath: maps.GetValueAsString(options.ProviderDeployConfig, "certPath"), + OutputKeyPath: maps.GetValueAsString(options.ProviderDeployConfig, "keyPath"), + PfxPassword: maps.GetValueAsString(options.ProviderDeployConfig, "pfxPassword"), + JksAlias: maps.GetValueAsString(options.ProviderDeployConfig, "jksAlias"), + JksKeypass: maps.GetValueAsString(options.ProviderDeployConfig, "jksKeypass"), + JksStorepass: maps.GetValueAsString(options.ProviderDeployConfig, "jksStorepass"), }, logger) return deployer, logger, err } case domain.DeployProviderTypeTencentCloudCDN, domain.DeployProviderTypeTencentCloudCLB, domain.DeployProviderTypeTencentCloudCOS, domain.DeployProviderTypeTencentCloudECDN, domain.DeployProviderTypeTencentCloudEO: { - access := &domain.AccessConfigForTencentCloud{} - if err := json.Unmarshal([]byte(accessConfig), access); err != nil { - return nil, nil, fmt.Errorf("failed to unmarshal access config: %w", err) + access := domain.AccessConfigForTencentCloud{} + if err := maps.Decode(options.ProviderAccessConfig, &access); err != nil { + return nil, nil, fmt.Errorf("failed to decode provider access config: %w", err) } - switch provider { + switch options.Provider { case domain.DeployProviderTypeTencentCloudCDN: deployer, err := providerTencentCloudCDN.NewWithLogger(&providerTencentCloudCDN.TencentCloudCDNDeployerConfig{ SecretId: access.SecretId, SecretKey: access.SecretKey, - Domain: maps.GetValueAsString(deployConfig, "domain"), + Domain: maps.GetValueAsString(options.ProviderDeployConfig, "domain"), }, logger) return deployer, logger, err @@ -291,11 +290,11 @@ func createDeployer(provider domain.DeployProviderType, accessConfig string, dep deployer, err := providerTencentCloudCLB.NewWithLogger(&providerTencentCloudCLB.TencentCloudCLBDeployerConfig{ SecretId: access.SecretId, SecretKey: access.SecretKey, - Region: maps.GetValueAsString(deployConfig, "region"), - ResourceType: providerTencentCloudCLB.DeployResourceType(maps.GetValueAsString(deployConfig, "resourceType")), - LoadbalancerId: maps.GetValueAsString(deployConfig, "loadbalancerId"), - ListenerId: maps.GetValueAsString(deployConfig, "listenerId"), - Domain: maps.GetValueAsString(deployConfig, "domain"), + Region: maps.GetValueAsString(options.ProviderDeployConfig, "region"), + ResourceType: providerTencentCloudCLB.DeployResourceType(maps.GetValueAsString(options.ProviderDeployConfig, "resourceType")), + LoadbalancerId: maps.GetValueAsString(options.ProviderDeployConfig, "loadbalancerId"), + ListenerId: maps.GetValueAsString(options.ProviderDeployConfig, "listenerId"), + Domain: maps.GetValueAsString(options.ProviderDeployConfig, "domain"), }, logger) return deployer, logger, err @@ -303,9 +302,9 @@ func createDeployer(provider domain.DeployProviderType, accessConfig string, dep deployer, err := providerTencentCloudCOD.NewWithLogger(&providerTencentCloudCOD.TencentCloudCOSDeployerConfig{ SecretId: access.SecretId, SecretKey: access.SecretKey, - Region: maps.GetValueAsString(deployConfig, "region"), - Bucket: maps.GetValueAsString(deployConfig, "bucket"), - Domain: maps.GetValueAsString(deployConfig, "domain"), + Region: maps.GetValueAsString(options.ProviderDeployConfig, "region"), + Bucket: maps.GetValueAsString(options.ProviderDeployConfig, "bucket"), + Domain: maps.GetValueAsString(options.ProviderDeployConfig, "domain"), }, logger) return deployer, logger, err @@ -313,7 +312,7 @@ func createDeployer(provider domain.DeployProviderType, accessConfig string, dep deployer, err := providerTencentCloudECDN.NewWithLogger(&providerTencentCloudECDN.TencentCloudECDNDeployerConfig{ SecretId: access.SecretId, SecretKey: access.SecretKey, - Domain: maps.GetValueAsString(deployConfig, "domain"), + Domain: maps.GetValueAsString(options.ProviderDeployConfig, "domain"), }, logger) return deployer, logger, err @@ -321,8 +320,8 @@ func createDeployer(provider domain.DeployProviderType, accessConfig string, dep deployer, err := providerTencentCloudEO.NewWithLogger(&providerTencentCloudEO.TencentCloudEODeployerConfig{ SecretId: access.SecretId, SecretKey: access.SecretKey, - ZoneId: maps.GetValueAsString(deployConfig, "zoneId"), - Domain: maps.GetValueAsString(deployConfig, "domain"), + ZoneId: maps.GetValueAsString(options.ProviderDeployConfig, "zoneId"), + Domain: maps.GetValueAsString(options.ProviderDeployConfig, "domain"), }, logger) return deployer, logger, err @@ -333,17 +332,17 @@ func createDeployer(provider domain.DeployProviderType, accessConfig string, dep case domain.DeployProviderTypeVolcEngineCDN, domain.DeployProviderTypeVolcEngineLive: { - access := &domain.AccessConfigForVolcEngine{} - if err := json.Unmarshal([]byte(accessConfig), access); err != nil { - return nil, nil, fmt.Errorf("failed to unmarshal access config: %w", err) + access := domain.AccessConfigForVolcEngine{} + if err := maps.Decode(options.ProviderAccessConfig, &access); err != nil { + return nil, nil, fmt.Errorf("failed to decode provider access config: %w", err) } - switch provider { + switch options.Provider { case domain.DeployProviderTypeVolcEngineCDN: deployer, err := providerVolcEngineCDN.NewWithLogger(&providerVolcEngineCDN.VolcEngineCDNDeployerConfig{ AccessKey: access.AccessKeyId, SecretKey: access.SecretAccessKey, - Domain: maps.GetValueAsString(deployConfig, "domain"), + Domain: maps.GetValueAsString(options.ProviderDeployConfig, "domain"), }, logger) return deployer, logger, err @@ -351,7 +350,7 @@ func createDeployer(provider domain.DeployProviderType, accessConfig string, dep deployer, err := providerVolcEngineLive.NewWithLogger(&providerVolcEngineLive.VolcEngineLiveDeployerConfig{ AccessKey: access.AccessKeyId, SecretKey: access.SecretAccessKey, - Domain: maps.GetValueAsString(deployConfig, "domain"), + Domain: maps.GetValueAsString(options.ProviderDeployConfig, "domain"), }, logger) return deployer, logger, err @@ -362,18 +361,18 @@ func createDeployer(provider domain.DeployProviderType, accessConfig string, dep case domain.DeployProviderTypeWebhook: { - access := &domain.AccessConfigForWebhook{} - if err := json.Unmarshal([]byte(accessConfig), access); err != nil { - return nil, nil, fmt.Errorf("failed to unmarshal access config: %w", err) + access := domain.AccessConfigForWebhook{} + if err := maps.Decode(options.ProviderAccessConfig, &access); err != nil { + return nil, nil, fmt.Errorf("failed to decode provider access config: %w", err) } deployer, err := providerWebhook.NewWithLogger(&providerWebhook.WebhookDeployerConfig{ WebhookUrl: access.Url, - WebhookData: maps.GetValueAsString(deployConfig, "webhookData"), + WebhookData: maps.GetValueAsString(options.ProviderDeployConfig, "webhookData"), }, logger) return deployer, logger, err } } - return nil, nil, fmt.Errorf("unsupported deployer provider: %s", provider) + return nil, nil, fmt.Errorf("unsupported deployer provider: %s", string(options.Provider)) } diff --git a/internal/domain/access.go b/internal/domain/access.go index 9a2bcb7d..b90405e6 100644 --- a/internal/domain/access.go +++ b/internal/domain/access.go @@ -1,6 +1,9 @@ package domain -import "time" +import ( + "encoding/json" + "time" +) type Access struct { Meta @@ -11,6 +14,15 @@ type Access struct { DeletedAt time.Time `json:"deleted" db:"deleted"` } +func (a *Access) UnmarshalConfigToMap() (map[string]any, error) { + config := make(map[string]any) + if err := json.Unmarshal([]byte(a.Config), &config); err != nil { + return nil, err + } + + return config, nil +} + type AccessConfigForACMEHttpReq struct { Endpoint string `json:"endpoint"` Mode string `json:"mode"` @@ -26,8 +38,6 @@ type AccessConfigForAliyun struct { type AccessConfigForAWS struct { AccessKeyId string `json:"accessKeyId"` SecretAccessKey string `json:"secretAccessKey"` - Region string `json:"region"` - HostedZoneId string `json:"hostedZoneId"` } type AccessConfigForBaiduCloud struct { @@ -57,7 +67,6 @@ type AccessConfigForGoDaddy struct { type AccessConfigForHuaweiCloud struct { AccessKeyId string `json:"accessKeyId"` SecretAccessKey string `json:"secretAccessKey"` - Region string `json:"region"` } type AccessConfigForLocal struct{} diff --git a/internal/domain/provider.go b/internal/domain/provider.go index b0f9c05b..0c07e458 100644 --- a/internal/domain/provider.go +++ b/internal/domain/provider.go @@ -3,7 +3,7 @@ type AccessProviderType string /* -提供商类型常量值。 +授权提供商类型常量值。 注意:如果追加新的常量值,请保持以 ASCII 排序。 NOTICE: If you add new constant, please keep ASCII order. @@ -30,11 +30,39 @@ const ( AccessProviderTypeWebhook = AccessProviderType("webhook") ) +type ApplyDNSProviderType string + +/* +申请证书 DNS 提供商常量值。 +短横线前的部分始终等于授权提供商类型。 + + 注意:如果追加新的常量值,请保持以 ASCII 排序。 + NOTICE: If you add new constant, please keep ASCII order. +*/ +const ( + ApplyDNSProviderTypeACMEHttpReq = ApplyDNSProviderType("acmehttpreq") + ApplyDNSProviderTypeAliyun = ApplyDNSProviderType("aliyun") // 兼容旧值,等同于 [ApplyDNSProviderTypeAliyunDNS] + ApplyDNSProviderTypeAliyunDNS = ApplyDNSProviderType("aliyun-dns") + ApplyDNSProviderTypeAWS = ApplyDNSProviderType("aws") // 兼容旧值,等同于 [ApplyDNSProviderTypeAWSRoute53] + ApplyDNSProviderTypeAWSRoute53 = ApplyDNSProviderType("aws-route53") + ApplyDNSProviderTypeCloudflare = ApplyDNSProviderType("cloudflare") + ApplyDNSProviderTypeGoDaddy = ApplyDNSProviderType("godaddy") + ApplyDNSProviderTypeHuaweiCloud = ApplyDNSProviderType("huaweicloud") // 兼容旧值,等同于 [ApplyDNSProviderTypeHuaweiCloudDNS] + ApplyDNSProviderTypeHuaweiCloudDNS = ApplyDNSProviderType("huaweicloud-dns") + ApplyDNSProviderTypeNameDotCom = ApplyDNSProviderType("namedotcom") + ApplyDNSProviderTypeNameSilo = ApplyDNSProviderType("namesilo") + ApplyDNSProviderTypePowerDNS = ApplyDNSProviderType("powerdns") + ApplyDNSProviderTypeTencentCloud = ApplyDNSProviderType("tencentcloud") // 兼容旧值,等同于 [ApplyDNSProviderTypeTencentCloudDNS] + ApplyDNSProviderTypeTencentCloudDNS = ApplyDNSProviderType("tencentcloud-dns") + ApplyDNSProviderTypeVolcEngine = ApplyDNSProviderType("volcengine") // 兼容旧值,等同于 [ApplyDNSProviderTypeVolcEngineDNS] + ApplyDNSProviderTypeVolcEngineDNS = ApplyDNSProviderType("volcengine-dns") +) + type DeployProviderType string /* -提供商部署目标常量值。 -短横线前的部分始终等于提供商类型。 +部署目标提供商常量值。 +短横线前的部分始终等于授权提供商类型。 注意:如果追加新的常量值,请保持以 ASCII 排序。 NOTICE: If you add new constant, please keep ASCII order. diff --git a/internal/pkg/core/deployer/providers/aliyun-alb/aliyun_alb_test.go b/internal/pkg/core/deployer/providers/aliyun-alb/aliyun_alb_test.go index 143b65b4..fddf7ff2 100644 --- a/internal/pkg/core/deployer/providers/aliyun-alb/aliyun_alb_test.go +++ b/internal/pkg/core/deployer/providers/aliyun-alb/aliyun_alb_test.go @@ -36,7 +36,7 @@ func init() { /* Shell command to run this test: - go test -v aliyun_alb_test.go -args \ + go test -v ./aliyun_alb_test.go -args \ --CERTIMATE_DEPLOYER_ALIYUNALB_INPUTCERTPATH="/path/to/your-input-cert.pem" \ --CERTIMATE_DEPLOYER_ALIYUNALB_INPUTKEYPATH="/path/to/your-input-key.pem" \ --CERTIMATE_DEPLOYER_ALIYUNALB_ACCESSKEYID="your-access-key-id" \ diff --git a/internal/pkg/core/deployer/providers/aliyun-cdn/aliyun_cdn_test.go b/internal/pkg/core/deployer/providers/aliyun-cdn/aliyun_cdn_test.go index 66464aa1..da4d1d74 100644 --- a/internal/pkg/core/deployer/providers/aliyun-cdn/aliyun_cdn_test.go +++ b/internal/pkg/core/deployer/providers/aliyun-cdn/aliyun_cdn_test.go @@ -32,7 +32,7 @@ func init() { /* Shell command to run this test: - go test -v aliyun_cdn_test.go -args \ + go test -v ./aliyun_cdn_test.go -args \ --CERTIMATE_DEPLOYER_ALIYUNCDN_INPUTCERTPATH="/path/to/your-input-cert.pem" \ --CERTIMATE_DEPLOYER_ALIYUNCDN_INPUTKEYPATH="/path/to/your-input-key.pem" \ --CERTIMATE_DEPLOYER_ALIYUNCDN_ACCESSKEYID="your-access-key-id" \ 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 f9aa800d..761cbb38 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 @@ -36,7 +36,7 @@ func init() { /* Shell command to run this test: - go test -v aliyun_clb_test.go -args \ + go test -v ./aliyun_clb_test.go -args \ --CERTIMATE_DEPLOYER_ALIYUNCLB_INPUTCERTPATH="/path/to/your-input-cert.pem" \ --CERTIMATE_DEPLOYER_ALIYUNCLB_INPUTKEYPATH="/path/to/your-input-key.pem" \ --CERTIMATE_DEPLOYER_ALIYUNCLB_ACCESSKEYID="your-access-key-id" \ diff --git a/internal/pkg/core/deployer/providers/aliyun-dcdn/aliyun_dcdn_test.go b/internal/pkg/core/deployer/providers/aliyun-dcdn/aliyun_dcdn_test.go index 8fdddf80..ffbfcd1f 100644 --- a/internal/pkg/core/deployer/providers/aliyun-dcdn/aliyun_dcdn_test.go +++ b/internal/pkg/core/deployer/providers/aliyun-dcdn/aliyun_dcdn_test.go @@ -32,7 +32,7 @@ func init() { /* Shell command to run this test: - go test -v aliyun_dcdn_test.go -args \ + go test -v ./aliyun_dcdn_test.go -args \ --CERTIMATE_DEPLOYER_ALIYUNDCDN_INPUTCERTPATH="/path/to/your-input-cert.pem" \ --CERTIMATE_DEPLOYER_ALIYUNDCDN_INPUTKEYPATH="/path/to/your-input-key.pem" \ --CERTIMATE_DEPLOYER_ALIYUNDCDN_ACCESSKEYID="your-access-key-id" \ diff --git a/internal/pkg/core/deployer/providers/aliyun-nlb/aliyun_nlb_test.go b/internal/pkg/core/deployer/providers/aliyun-nlb/aliyun_nlb_test.go index 9c976dd9..45abd932 100644 --- a/internal/pkg/core/deployer/providers/aliyun-nlb/aliyun_nlb_test.go +++ b/internal/pkg/core/deployer/providers/aliyun-nlb/aliyun_nlb_test.go @@ -36,7 +36,7 @@ func init() { /* Shell command to run this test: - go test -v aliyun_nlb_test.go -args \ + go test -v ./aliyun_nlb_test.go -args \ --CERTIMATE_DEPLOYER_ALIYUNNLB_INPUTCERTPATH="/path/to/your-input-cert.pem" \ --CERTIMATE_DEPLOYER_ALIYUNNLB_INPUTKEYPATH="/path/to/your-input-key.pem" \ --CERTIMATE_DEPLOYER_ALIYUNNLB_ACCESSKEYID="your-access-key-id" \ diff --git a/internal/pkg/core/deployer/providers/aliyun-oss/aliyun_oss_test.go b/internal/pkg/core/deployer/providers/aliyun-oss/aliyun_oss_test.go index afb31853..e25f8156 100644 --- a/internal/pkg/core/deployer/providers/aliyun-oss/aliyun_oss_test.go +++ b/internal/pkg/core/deployer/providers/aliyun-oss/aliyun_oss_test.go @@ -36,7 +36,7 @@ func init() { /* Shell command to run this test: - go test -v aliyun_oss_test.go -args \ + go test -v ./aliyun_oss_test.go -args \ --CERTIMATE_DEPLOYER_ALIYUNOSS_INPUTCERTPATH="/path/to/your-input-cert.pem" \ --CERTIMATE_DEPLOYER_ALIYUNOSS_INPUTKEYPATH="/path/to/your-input-key.pem" \ --CERTIMATE_DEPLOYER_ALIYUNOSS_ACCESSKEYID="your-access-key-id" \ diff --git a/internal/pkg/core/deployer/providers/baiducloud-cdn/baiducloud_cdn_test.go b/internal/pkg/core/deployer/providers/baiducloud-cdn/baiducloud_cdn_test.go index e3398505..817600b6 100644 --- a/internal/pkg/core/deployer/providers/baiducloud-cdn/baiducloud_cdn_test.go +++ b/internal/pkg/core/deployer/providers/baiducloud-cdn/baiducloud_cdn_test.go @@ -32,7 +32,7 @@ func init() { /* Shell command to run this test: - go test -v baiducloud_cdn_test.go -args \ + go test -v ./baiducloud_cdn_test.go -args \ --CERTIMATE_DEPLOYER_BAIDUCLOUDCDN_INPUTCERTPATH="/path/to/your-input-cert.pem" \ --CERTIMATE_DEPLOYER_BAIDUCLOUDCDN_INPUTKEYPATH="/path/to/your-input-key.pem" \ --CERTIMATE_DEPLOYER_BAIDUCLOUDCDN_ACCESSKEYID="your-access-key-id" \ diff --git a/internal/pkg/core/deployer/providers/byteplus-cdn/byteplus_cdn_test.go b/internal/pkg/core/deployer/providers/byteplus-cdn/byteplus_cdn_test.go index 0c411062..9de97be6 100644 --- a/internal/pkg/core/deployer/providers/byteplus-cdn/byteplus_cdn_test.go +++ b/internal/pkg/core/deployer/providers/byteplus-cdn/byteplus_cdn_test.go @@ -32,7 +32,7 @@ func init() { /* Shell command to run this test: - go test -v byteplus_cdn_test.go -args \ + go test -v ./byteplus_cdn_test.go -args \ --CERTIMATE_DEPLOYER_BYTEPLUSCDN_INPUTCERTPATH="/path/to/your-input-cert.pem" \ --CERTIMATE_DEPLOYER_BYTEPLUSCDN_INPUTKEYPATH="/path/to/your-input-key.pem" \ --CERTIMATE_DEPLOYER_BYTEPLUSCDN_ACCESSKEY="your-access-key" \ diff --git a/internal/pkg/core/deployer/providers/dogecloud-cdn/dogecloud_cdn_test.go b/internal/pkg/core/deployer/providers/dogecloud-cdn/dogecloud_cdn_test.go index 2375e372..8d066484 100644 --- a/internal/pkg/core/deployer/providers/dogecloud-cdn/dogecloud_cdn_test.go +++ b/internal/pkg/core/deployer/providers/dogecloud-cdn/dogecloud_cdn_test.go @@ -32,7 +32,7 @@ func init() { /* Shell command to run this test: - go test -v dogecloud_cdn_test.go -args \ + go test -v ./dogecloud_cdn_test.go -args \ --CERTIMATE_DEPLOYER_DOGECLOUDCDN_INPUTCERTPATH="/path/to/your-input-cert.pem" \ --CERTIMATE_DEPLOYER_DOGECLOUDCDN_INPUTKEYPATH="/path/to/your-input-key.pem" \ --CERTIMATE_DEPLOYER_DOGECLOUDCDN_ACCESSKEY="your-access-key" \ diff --git a/internal/pkg/core/deployer/providers/huaweicloud-cdn/huaweicloud_cdn_test.go b/internal/pkg/core/deployer/providers/huaweicloud-cdn/huaweicloud_cdn_test.go index d50e3ea5..d31b2a68 100644 --- a/internal/pkg/core/deployer/providers/huaweicloud-cdn/huaweicloud_cdn_test.go +++ b/internal/pkg/core/deployer/providers/huaweicloud-cdn/huaweicloud_cdn_test.go @@ -34,7 +34,7 @@ func init() { /* Shell command to run this test: - go test -v huaweicloud_cdn_test.go -args \ + go test -v ./huaweicloud_cdn_test.go -args \ --CERTIMATE_DEPLOYER_HUAWEICLOUDCDN_INPUTCERTPATH="/path/to/your-input-cert.pem" \ --CERTIMATE_DEPLOYER_HUAWEICLOUDCDN_INPUTKEYPATH="/path/to/your-input-key.pem" \ --CERTIMATE_DEPLOYER_HUAWEICLOUDCDN_ACCESSKEYID="your-access-key-id" \ diff --git a/internal/pkg/core/deployer/providers/huaweicloud-elb/huaweicloud_elb_test.go b/internal/pkg/core/deployer/providers/huaweicloud-elb/huaweicloud_elb_test.go index f2e573ca..32582800 100644 --- a/internal/pkg/core/deployer/providers/huaweicloud-elb/huaweicloud_elb_test.go +++ b/internal/pkg/core/deployer/providers/huaweicloud-elb/huaweicloud_elb_test.go @@ -38,7 +38,7 @@ func init() { /* Shell command to run this test: - go test -v huaweicloud_elb_test.go -args \ + go test -v ./huaweicloud_elb_test.go -args \ --CERTIMATE_DEPLOYER_HUAWEICLOUDELB_INPUTCERTPATH="/path/to/your-input-cert.pem" \ --CERTIMATE_DEPLOYER_HUAWEICLOUDELB_INPUTKEYPATH="/path/to/your-input-key.pem" \ --CERTIMATE_DEPLOYER_HUAWEICLOUDELB_ACCESSKEYID="your-access-key-id" \ diff --git a/internal/pkg/core/deployer/providers/k8s-secret/k8s_secret.go b/internal/pkg/core/deployer/providers/k8s-secret/k8s_secret.go index f09e8331..9e74e794 100644 --- a/internal/pkg/core/deployer/providers/k8s-secret/k8s_secret.go +++ b/internal/pkg/core/deployer/providers/k8s-secret/k8s_secret.go @@ -65,6 +65,9 @@ func (d *K8sSecretDeployer) Deploy(ctx context.Context, certPem string, privkeyP if d.config.SecretName == "" { return nil, errors.New("config `secretName` is required") } + if d.config.SecretType == "" { + return nil, errors.New("config `secretType` is required") + } if d.config.SecretDataKeyForCrt == "" { return nil, errors.New("config `secretDataKeyForCrt` is required") } diff --git a/internal/pkg/core/deployer/providers/k8s-secret/k8s_secret_test.go b/internal/pkg/core/deployer/providers/k8s-secret/k8s_secret_test.go index ac47deba..913099ec 100644 --- a/internal/pkg/core/deployer/providers/k8s-secret/k8s_secret_test.go +++ b/internal/pkg/core/deployer/providers/k8s-secret/k8s_secret_test.go @@ -34,7 +34,7 @@ func init() { /* Shell command to run this test: - go test -v k8s_secret_test.go -args \ + go test -v ./k8s_secret_test.go -args \ --CERTIMATE_DEPLOYER_K8SSECRET_INPUTCERTPATH="/path/to/your-input-cert.pem" \ --CERTIMATE_DEPLOYER_K8SSECRET_INPUTKEYPATH="/path/to/your-input-key.pem" \ --CERTIMATE_DEPLOYER_K8SSECRET_NAMESPACE="default" \ diff --git a/internal/pkg/core/deployer/providers/local/local_test.go b/internal/pkg/core/deployer/providers/local/local_test.go index 18838c63..33ff4def 100644 --- a/internal/pkg/core/deployer/providers/local/local_test.go +++ b/internal/pkg/core/deployer/providers/local/local_test.go @@ -38,7 +38,7 @@ func init() { /* Shell command to run this test: - go test -v local_test.go -args \ + go test -v ./local_test.go -args \ --CERTIMATE_DEPLOYER_LOCAL_INPUTCERTPATH="/path/to/your-input-cert.pem" \ --CERTIMATE_DEPLOYER_LOCAL_INPUTKEYPATH="/path/to/your-input-key.pem" \ --CERTIMATE_DEPLOYER_LOCAL_OUTPUTCERTPATH="/path/to/your-output-cert" \ diff --git a/internal/pkg/core/deployer/providers/qiniu-cdn/qiniu_cdn_test.go b/internal/pkg/core/deployer/providers/qiniu-cdn/qiniu_cdn_test.go index df4ee008..85ca8316 100644 --- a/internal/pkg/core/deployer/providers/qiniu-cdn/qiniu_cdn_test.go +++ b/internal/pkg/core/deployer/providers/qiniu-cdn/qiniu_cdn_test.go @@ -32,7 +32,7 @@ func init() { /* Shell command to run this test: - go test -v qiniu_cdn_test.go -args \ + go test -v ./qiniu_cdn_test.go -args \ --CERTIMATE_DEPLOYER_QINIUCDN_INPUTCERTPATH="/path/to/your-input-cert.pem" \ --CERTIMATE_DEPLOYER_QINIUCDN_INPUTKEYPATH="/path/to/your-input-key.pem" \ --CERTIMATE_DEPLOYER_QINIUCDN_ACCESSKEY="your-access-key" \ diff --git a/internal/pkg/core/deployer/providers/ssh/ssh_test.go b/internal/pkg/core/deployer/providers/ssh/ssh_test.go index 0dd58358..f83a539d 100644 --- a/internal/pkg/core/deployer/providers/ssh/ssh_test.go +++ b/internal/pkg/core/deployer/providers/ssh/ssh_test.go @@ -38,7 +38,7 @@ func init() { /* Shell command to run this test: - go test -v ssh_test.go -args \ + go test -v ./ssh_test.go -args \ --CERTIMATE_DEPLOYER_SSH_INPUTCERTPATH="/path/to/your-input-cert.pem" \ --CERTIMATE_DEPLOYER_SSH_INPUTKEYPATH="/path/to/your-input-key.pem" \ --CERTIMATE_DEPLOYER_SSH_SSHHOST="localhost" \ diff --git a/internal/pkg/core/deployer/providers/tencentcloud-cdn/tencentcloud_cdn_test.go b/internal/pkg/core/deployer/providers/tencentcloud-cdn/tencentcloud_cdn_test.go index 70b3c59d..088251b1 100644 --- a/internal/pkg/core/deployer/providers/tencentcloud-cdn/tencentcloud_cdn_test.go +++ b/internal/pkg/core/deployer/providers/tencentcloud-cdn/tencentcloud_cdn_test.go @@ -32,7 +32,7 @@ func init() { /* Shell command to run this test: - go test -v tencentcloud_cdn_test.go -args \ + go test -v ./tencentcloud_cdn_test.go -args \ --CERTIMATE_DEPLOYER_TENCENTCLOUDCDN_INPUTCERTPATH="/path/to/your-input-cert.pem" \ --CERTIMATE_DEPLOYER_TENCENTCLOUDCDN_INPUTKEYPATH="/path/to/your-input-key.pem" \ --CERTIMATE_DEPLOYER_TENCENTCLOUDCDN_SECRETID="your-secret-id" \ diff --git a/internal/pkg/core/deployer/providers/tencentcloud-clb/tencentcloud_clb_test.go b/internal/pkg/core/deployer/providers/tencentcloud-clb/tencentcloud_clb_test.go index fe0cf023..0af11dff 100644 --- a/internal/pkg/core/deployer/providers/tencentcloud-clb/tencentcloud_clb_test.go +++ b/internal/pkg/core/deployer/providers/tencentcloud-clb/tencentcloud_clb_test.go @@ -38,7 +38,7 @@ func init() { /* Shell command to run this test: - go test -v tencentcloud_clb_test.go -args \ + go test -v ./tencentcloud_clb_test.go -args \ --CERTIMATE_DEPLOYER_TENCENTCLOUDCLB_INPUTCERTPATH="/path/to/your-input-cert.pem" \ --CERTIMATE_DEPLOYER_TENCENTCLOUDCLB_INPUTKEYPATH="/path/to/your-input-key.pem" \ --CERTIMATE_DEPLOYER_TENCENTCLOUDCLB_SECRETID="your-secret-id" \ diff --git a/internal/pkg/core/deployer/providers/tencentcloud-cos/tencentcloud_cos_test.go b/internal/pkg/core/deployer/providers/tencentcloud-cos/tencentcloud_cos_test.go index 5f105efe..d58e4f50 100644 --- a/internal/pkg/core/deployer/providers/tencentcloud-cos/tencentcloud_cos_test.go +++ b/internal/pkg/core/deployer/providers/tencentcloud-cos/tencentcloud_cos_test.go @@ -36,7 +36,7 @@ func init() { /* Shell command to run this test: - go test -v tencentcloud_cos_test.go -args \ + go test -v ./tencentcloud_cos_test.go -args \ --CERTIMATE_DEPLOYER_TENCENTCLOUDCOS_INPUTCERTPATH="/path/to/your-input-cert.pem" \ --CERTIMATE_DEPLOYER_TENCENTCLOUDCOS_INPUTKEYPATH="/path/to/your-input-key.pem" \ --CERTIMATE_DEPLOYER_TENCENTCLOUDCOS_SECRETID="your-secret-id" \ diff --git a/internal/pkg/core/deployer/providers/tencentcloud-ecdn/tencentcloud_ecdn_test.go b/internal/pkg/core/deployer/providers/tencentcloud-ecdn/tencentcloud_ecdn_test.go index 95d617cf..764aa5fb 100644 --- a/internal/pkg/core/deployer/providers/tencentcloud-ecdn/tencentcloud_ecdn_test.go +++ b/internal/pkg/core/deployer/providers/tencentcloud-ecdn/tencentcloud_ecdn_test.go @@ -32,7 +32,7 @@ func init() { /* Shell command to run this test: - go test -v tencentcloud_ecdn_test.go -args \ + go test -v ./tencentcloud_ecdn_test.go -args \ --CERTIMATE_DEPLOYER_TENCENTCLOUDECDN_INPUTCERTPATH="/path/to/your-input-cert.pem" \ --CERTIMATE_DEPLOYER_TENCENTCLOUDECDN_INPUTKEYPATH="/path/to/your-input-key.pem" \ --CERTIMATE_DEPLOYER_TENCENTCLOUDECDN_SECRETID="your-secret-id" \ diff --git a/internal/pkg/core/deployer/providers/tencentcloud-eo/tencentcloud_eo_test.go b/internal/pkg/core/deployer/providers/tencentcloud-eo/tencentcloud_eo_test.go index a45706ae..bc5280f7 100644 --- a/internal/pkg/core/deployer/providers/tencentcloud-eo/tencentcloud_eo_test.go +++ b/internal/pkg/core/deployer/providers/tencentcloud-eo/tencentcloud_eo_test.go @@ -21,7 +21,7 @@ var ( ) func init() { - argsPrefix := "CERTIMATE_DEPLOYER_TENCENTCLOUDEEO_" + argsPrefix := "CERTIMATE_DEPLOYER_TENCENTCLOUDEO_" flag.StringVar(&fInputCertPath, argsPrefix+"INPUTCERTPATH", "", "") flag.StringVar(&fInputKeyPath, argsPrefix+"INPUTKEYPATH", "", "") @@ -34,13 +34,13 @@ func init() { /* Shell command to run this test: - go test -v tencentcloud_cdn_test.go -args \ - --CERTIMATE_DEPLOYER_TENCENTCLOUDEEO_INPUTCERTPATH="/path/to/your-input-cert.pem" \ - --CERTIMATE_DEPLOYER_TENCENTCLOUDEEO_INPUTKEYPATH="/path/to/your-input-key.pem" \ - --CERTIMATE_DEPLOYER_TENCENTCLOUDEEO_SECRETID="your-secret-id" \ - --CERTIMATE_DEPLOYER_TENCENTCLOUDEEO_SECRETKEY="your-secret-key" \ - --CERTIMATE_DEPLOYER_TENCENTCLOUDEEO_ZONEID="your-zone-id" \ - --CERTIMATE_DEPLOYER_TENCENTCLOUDEEO_DOMAIN="example.com" + go test -v ./tencentcloud_eo_test.go -args \ + --CERTIMATE_DEPLOYER_TENCENTCLOUDEO_INPUTCERTPATH="/path/to/your-input-cert.pem" \ + --CERTIMATE_DEPLOYER_TENCENTCLOUDEO_INPUTKEYPATH="/path/to/your-input-key.pem" \ + --CERTIMATE_DEPLOYER_TENCENTCLOUDEO_SECRETID="your-secret-id" \ + --CERTIMATE_DEPLOYER_TENCENTCLOUDEO_SECRETKEY="your-secret-key" \ + --CERTIMATE_DEPLOYER_TENCENTCLOUDEO_ZONEID="your-zone-id" \ + --CERTIMATE_DEPLOYER_TENCENTCLOUDEO_DOMAIN="example.com" */ func TestDeploy(t *testing.T) { flag.Parse() diff --git a/internal/pkg/core/deployer/providers/volcengine-cdn/volcengine_cdn_test.go b/internal/pkg/core/deployer/providers/volcengine-cdn/volcengine_cdn_test.go index e24740be..639a41c1 100644 --- a/internal/pkg/core/deployer/providers/volcengine-cdn/volcengine_cdn_test.go +++ b/internal/pkg/core/deployer/providers/volcengine-cdn/volcengine_cdn_test.go @@ -32,7 +32,7 @@ func init() { /* Shell command to run this test: - go test -v volcengine_cdn_test.go -args \ + go test -v ./volcengine_cdn_test.go -args \ --CERTIMATE_DEPLOYER_VOLCENGINECDN_INPUTCERTPATH="/path/to/your-input-cert.pem" \ --CERTIMATE_DEPLOYER_VOLCENGINECDN_INPUTKEYPATH="/path/to/your-input-key.pem" \ --CERTIMATE_DEPLOYER_VOLCENGINECDN_ACCESSKEY="your-access-key" \ diff --git a/internal/pkg/core/deployer/providers/volcengine-live/volcengine_live_test.go b/internal/pkg/core/deployer/providers/volcengine-live/volcengine_live_test.go index 0ad66385..6d9da282 100644 --- a/internal/pkg/core/deployer/providers/volcengine-live/volcengine_live_test.go +++ b/internal/pkg/core/deployer/providers/volcengine-live/volcengine_live_test.go @@ -32,7 +32,7 @@ func init() { /* Shell command to run this test: - go test -v volcengine_live_test.go -args \ + go test -v ./volcengine_live_test.go -args \ --CERTIMATE_DEPLOYER_VOLCENGINELIVE_INPUTCERTPATH="/path/to/your-input-cert.pem" \ --CERTIMATE_DEPLOYER_VOLCENGINELIVE_INPUTKEYPATH="/path/to/your-input-key.pem" \ --CERTIMATE_DEPLOYER_VOLCENGINELIVE_ACCESSKEY="your-access-key" \ diff --git a/internal/pkg/core/deployer/providers/webhook/webhook_test.go b/internal/pkg/core/deployer/providers/webhook/webhook_test.go index ddb719c4..92b57e56 100644 --- a/internal/pkg/core/deployer/providers/webhook/webhook_test.go +++ b/internal/pkg/core/deployer/providers/webhook/webhook_test.go @@ -30,7 +30,7 @@ func init() { /* Shell command to run this test: - go test -v webhook_test.go -args \ + go test -v ./webhook_test.go -args \ --CERTIMATE_DEPLOYER_WEBHOOK_INPUTCERTPATH="/path/to/your-input-cert.pem" \ --CERTIMATE_DEPLOYER_WEBHOOK_INPUTKEYPATH="/path/to/your-input-key.pem" \ --CERTIMATE_DEPLOYER_WEBHOOK_URL="https://example.com/your-webhook-url" \ diff --git a/internal/pkg/core/logger/logger_test.go b/internal/pkg/core/logger/logger_test.go index 29308a83..e131a7b1 100644 --- a/internal/pkg/core/logger/logger_test.go +++ b/internal/pkg/core/logger/logger_test.go @@ -9,7 +9,7 @@ import ( /* Shell command to run this test: - go test -v logger_test.go + go test -v ./logger_test.go */ func TestLogger(t *testing.T) { t.Run("Logger_Appendt", func(t *testing.T) { diff --git a/internal/pkg/core/notifier/providers/bark/bark_test.go b/internal/pkg/core/notifier/providers/bark/bark_test.go index 3b9bef2d..e3045cae 100644 --- a/internal/pkg/core/notifier/providers/bark/bark_test.go +++ b/internal/pkg/core/notifier/providers/bark/bark_test.go @@ -30,7 +30,7 @@ func init() { /* Shell command to run this test: - go test -v bark_test.go -args \ + go test -v ./bark_test.go -args \ --CERTIMATE_NOTIFIER_BARK_SERVERURL="https://example.com/your-server-url" \ --CERTIMATE_NOTIFIER_BARK_DEVICEKEY="your-device-key" */ diff --git a/internal/pkg/core/notifier/providers/dingtalk/dingtalk_test.go b/internal/pkg/core/notifier/providers/dingtalk/dingtalk_test.go index ea2c9bc8..621a57ca 100644 --- a/internal/pkg/core/notifier/providers/dingtalk/dingtalk_test.go +++ b/internal/pkg/core/notifier/providers/dingtalk/dingtalk_test.go @@ -30,7 +30,7 @@ func init() { /* Shell command to run this test: - go test -v dingtalk_test.go -args \ + go test -v ./dingtalk_test.go -args \ --CERTIMATE_NOTIFIER_DINGTALK_URL="https://example.com/your-webhook-url" */ func TestNotify(t *testing.T) { diff --git a/internal/pkg/core/notifier/providers/email/email_test.go b/internal/pkg/core/notifier/providers/email/email_test.go index 34303d06..1c52d4de 100644 --- a/internal/pkg/core/notifier/providers/email/email_test.go +++ b/internal/pkg/core/notifier/providers/email/email_test.go @@ -40,7 +40,7 @@ func init() { /* Shell command to run this test: - go test -v email_test.go -args \ + go test -v ./email_test.go -args \ --CERTIMATE_NOTIFIER_EMAIL_SMTPHOST="smtp.example.com" \ --CERTIMATE_NOTIFIER_EMAIL_SMTPPORT=465 \ --CERTIMATE_NOTIFIER_EMAIL_SMTPTLS=true \ diff --git a/internal/pkg/core/notifier/providers/lark/lark_test.go b/internal/pkg/core/notifier/providers/lark/lark_test.go index b93d3606..0b91ebd7 100644 --- a/internal/pkg/core/notifier/providers/lark/lark_test.go +++ b/internal/pkg/core/notifier/providers/lark/lark_test.go @@ -26,7 +26,7 @@ func init() { /* Shell command to run this test: - go test -v lark_test.go -args \ + go test -v ./lark_test.go -args \ --CERTIMATE_NOTIFIER_LARK_WEBHOOKURL="https://example.com/your-webhook-url" */ func TestNotify(t *testing.T) { diff --git a/internal/pkg/core/notifier/providers/serverchan/serverchan_test.go b/internal/pkg/core/notifier/providers/serverchan/serverchan_test.go index 63407379..db2a4946 100644 --- a/internal/pkg/core/notifier/providers/serverchan/serverchan_test.go +++ b/internal/pkg/core/notifier/providers/serverchan/serverchan_test.go @@ -26,7 +26,7 @@ func init() { /* Shell command to run this test: - go test -v serverchan_test.go -args \ + go test -v ./serverchan_test.go -args \ --CERTIMATE_NOTIFIER_SERVERCHAN_URL="https://example.com/your-webhook-url" \ */ func TestNotify(t *testing.T) { diff --git a/internal/pkg/core/notifier/providers/telegram/telegram_test.go b/internal/pkg/core/notifier/providers/telegram/telegram_test.go index 062e2642..fca71e8a 100644 --- a/internal/pkg/core/notifier/providers/telegram/telegram_test.go +++ b/internal/pkg/core/notifier/providers/telegram/telegram_test.go @@ -30,7 +30,7 @@ func init() { /* Shell command to run this test: - go test -v telegram_test.go -args \ + go test -v ./telegram_test.go -args \ --CERTIMATE_NOTIFIER_TELEGRAM_APITOKEN="your-api-token" \ --CERTIMATE_NOTIFIER_TELEGRAM_CHATID=123456 */ diff --git a/internal/pkg/core/notifier/providers/webhook/webhook_test.go b/internal/pkg/core/notifier/providers/webhook/webhook_test.go index 2f83f8e0..14e2adf6 100644 --- a/internal/pkg/core/notifier/providers/webhook/webhook_test.go +++ b/internal/pkg/core/notifier/providers/webhook/webhook_test.go @@ -26,7 +26,7 @@ func init() { /* Shell command to run this test: - go test -v webhook_test.go -args \ + go test -v ./webhook_test.go -args \ --CERTIMATE_NOTIFIER_WEBHOOK_URL="https://example.com/your-webhook-url" */ func TestNotify(t *testing.T) { diff --git a/internal/pkg/core/notifier/providers/wecom/wecom_test.go b/internal/pkg/core/notifier/providers/wecom/wecom_test.go index a9ac9d16..e1378849 100644 --- a/internal/pkg/core/notifier/providers/wecom/wecom_test.go +++ b/internal/pkg/core/notifier/providers/wecom/wecom_test.go @@ -26,7 +26,7 @@ func init() { /* Shell command to run this test: - go test -v serverchan_test.go -args \ + go test -v ./wecom_test.go -args \ --CERTIMATE_NOTIFIER_WECOM_WEBHOOKURL="https://example.com/your-webhook-url" \ */ func TestNotify(t *testing.T) { diff --git a/internal/pkg/utils/maps/maps.go b/internal/pkg/utils/maps/maps.go index a7c11592..f0e82efc 100644 --- a/internal/pkg/utils/maps/maps.go +++ b/internal/pkg/utils/maps/maps.go @@ -1,6 +1,10 @@ package maps -import "strconv" +import ( + "strconv" + + mapstructure "github.com/go-viper/mapstructure/v2" +) // 以字符串形式从字典中获取指定键的值。 // @@ -178,3 +182,27 @@ func GetValueOrDefaultAsBool(dict map[string]any, key string, defaultValue bool) return defaultValue } + +// 将字典解码为指定类型的结构体。 +// +// 入参: +// - dict: 字典。 +// - output: 结构体指针。 +// +// 出参: +// - 错误信息。如果解码失败,则返回错误信息。 +func Decode(dict map[string]any, output any) error { + config := &mapstructure.DecoderConfig{ + Metadata: nil, + Result: output, + WeaklyTypedInput: true, + TagName: "json", + } + + decoder, err := mapstructure.NewDecoder(config) + if err != nil { + return err + } + + return decoder.Decode(dict) +} diff --git a/ui/src/api/workflow.ts b/ui/src/api/workflow.ts index d545b94e..c40fcce8 100644 --- a/ui/src/api/workflow.ts +++ b/ui/src/api/workflow.ts @@ -1,7 +1,6 @@ -import type { RecordModel, RecordSubscription } from "pocketbase"; -import { ClientResponseError } from "pocketbase"; +import { ClientResponseError, type RecordSubscription } from "pocketbase"; -import { WORKFLOW_TRIGGERS } from "@/domain/workflow"; +import { WORKFLOW_TRIGGERS, type WorkflowModel } from "@/domain/workflow"; import { getPocketBase } from "@/repository/pocketbase"; export const run = async (id: string) => { @@ -25,14 +24,14 @@ export const run = async (id: string) => { return resp; }; -export const subscribe = async (id: string, cb: (e: RecordSubscription) => void) => { +export const subscribe = async (id: string, cb: (e: RecordSubscription) => void) => { const pb = getPocketBase(); - pb.collection("workflow").subscribe(id, cb); + return pb.collection("workflow").subscribe(id, cb); }; export const unsubscribe = async (id: string) => { const pb = getPocketBase(); - pb.collection("workflow").unsubscribe(id); + return pb.collection("workflow").unsubscribe(id); }; diff --git a/ui/src/components/access/AccessForm.tsx b/ui/src/components/access/AccessForm.tsx index d5bdf7ad..1c1e99c8 100644 --- a/ui/src/components/access/AccessForm.tsx +++ b/ui/src/components/access/AccessForm.tsx @@ -130,20 +130,22 @@ const AccessForm = forwardRef(({ className, }; const handleFormChange = (_: unknown, values: AccessFormFieldValues) => { - if (values.provider !== fieldProvider) { - formInst.setFieldValue("provider", values.provider); - } - onValuesChange?.(values); }; useImperativeHandle(ref, () => { return { getFieldsValue: () => { - return formInst.getFieldsValue(true); + const values = formInst.getFieldsValue(true); + values.config = nestedFormInst.getFieldsValue(); + return values; }, resetFields: (fields) => { - return formInst.resetFields(fields); + formInst.resetFields(fields); + + if (!!fields && fields.includes("config")) { + nestedFormInst.resetFields(fields); + } }, validateFields: (nameList, config) => { const t1 = formInst.validateFields(nameList, config); diff --git a/ui/src/components/access/AccessFormAWSConfig.tsx b/ui/src/components/access/AccessFormAWSConfig.tsx index 5ca88099..1eee6247 100644 --- a/ui/src/components/access/AccessFormAWSConfig.tsx +++ b/ui/src/components/access/AccessFormAWSConfig.tsx @@ -19,8 +19,6 @@ const initFormModel = (): AccessFormAWSConfigFieldValues => { return { accessKeyId: "", secretAccessKey: "", - region: "us-east-1", - hostedZoneId: "", }; }; @@ -38,18 +36,6 @@ const AccessFormAWSConfig = ({ form: formInst, formName, disabled, initialValues .min(1, t("access.form.aws_secret_access_key.placeholder")) .max(64, t("common.errmsg.string_max", { max: 64 })) .trim(), - // TODO: 该字段仅用于申请证书,后续迁移到工作流表单中 - region: z - .string() - .max(64, t("common.errmsg.string_max", { max: 64 })) - .trim() - .nullish(), - // TODO: 该字段仅用于申请证书,后续迁移到工作流表单中 - hostedZoneId: z - .string() - .max(64, t("common.errmsg.string_max", { max: 64 })) - .trim() - .nullish(), }); const formRule = createSchemaFieldRule(formSchema); @@ -83,24 +69,6 @@ const AccessFormAWSConfig = ({ form: formInst, formName, disabled, initialValues > - - } - > - - - - } - > - - ); }; diff --git a/ui/src/components/access/AccessFormHuaweiCloudConfig.tsx b/ui/src/components/access/AccessFormHuaweiCloudConfig.tsx index d4765e81..f1d56ff0 100644 --- a/ui/src/components/access/AccessFormHuaweiCloudConfig.tsx +++ b/ui/src/components/access/AccessFormHuaweiCloudConfig.tsx @@ -19,7 +19,6 @@ const initFormModel = (): AccessFormHuaweiCloudConfigFieldValues => { return { accessKeyId: "", secretAccessKey: "", - region: "cn-north-1", }; }; @@ -37,12 +36,6 @@ const AccessFormHuaweiCloudConfig = ({ form: formInst, formName, disabled, initi .min(1, t("access.form.huaweicloud_secret_access_key.placeholder")) .max(64, t("common.errmsg.string_max", { max: 64 })) .trim(), - // TODO: 该字段仅用于申请证书,后续迁移到工作流表单中 - region: z - .string() - .max(64, t("common.errmsg.string_max", { max: 64 })) - .trim() - .nullish(), }); const formRule = createSchemaFieldRule(formSchema); @@ -76,15 +69,6 @@ const AccessFormHuaweiCloudConfig = ({ form: formInst, formName, disabled, initi > - - } - > - - ); }; diff --git a/ui/src/components/provider/ApplyDNSProviderPicker.tsx b/ui/src/components/provider/ApplyDNSProviderPicker.tsx new file mode 100644 index 00000000..e72935cc --- /dev/null +++ b/ui/src/components/provider/ApplyDNSProviderPicker.tsx @@ -0,0 +1,67 @@ +import { memo, useState } from "react"; +import { useTranslation } from "react-i18next"; +import { Avatar, Card, Col, Empty, Flex, Input, Row, Typography } from "antd"; + +import Show from "@/components/Show"; +import { applyDNSProvidersMap } from "@/domain/provider"; + +export type ApplyDNSProviderPickerProps = { + className?: string; + style?: React.CSSProperties; + placeholder?: string; + onSelect?: (value: string) => void; +}; + +const ApplyDNSProviderPicker = ({ className, style, placeholder, onSelect }: ApplyDNSProviderPickerProps) => { + const { t } = useTranslation(); + + const [keyword, setKeyword] = useState(); + + const providers = Array.from(applyDNSProvidersMap.values()); + const filteredProviders = providers.filter((provider) => { + if (keyword) { + const value = keyword.toLowerCase(); + return provider.type.toLowerCase().includes(value) || provider.name.toLowerCase().includes(value); + } + + return true; + }); + + const handleProviderTypeSelect = (value: string) => { + onSelect?.(value); + }; + + return ( +
+ setKeyword(e.target.value.trim())} /> + +
+ 0} fallback={}> + + {filteredProviders.map((provider, index) => { + return ( + + { + handleProviderTypeSelect(provider.type); + }} + > + + + {t(provider.name)} + + + + ); + })} + + +
+
+ ); +}; + +export default memo(ApplyDNSProviderPicker); diff --git a/ui/src/components/provider/ApplyDNSProviderSelect.tsx b/ui/src/components/provider/ApplyDNSProviderSelect.tsx new file mode 100644 index 00000000..3b76feff --- /dev/null +++ b/ui/src/components/provider/ApplyDNSProviderSelect.tsx @@ -0,0 +1,51 @@ +import { memo } from "react"; +import { useTranslation } from "react-i18next"; +import { Avatar, Select, type SelectProps, Space, Typography } from "antd"; + +import { applyDNSProvidersMap } from "@/domain/provider"; + +export type ApplyDNSProviderSelectProps = Omit< + SelectProps, + "filterOption" | "filterSort" | "labelRender" | "options" | "optionFilterProp" | "optionLabelProp" | "optionRender" +>; + +const ApplyDNSProviderSelect = (props: ApplyDNSProviderSelectProps) => { + const { t } = useTranslation(); + + const options = Array.from(applyDNSProvidersMap.values()).map((item) => ({ + key: item.type, + value: item.type, + label: t(item.name), + })); + + const renderOption = (key: string) => { + const provider = applyDNSProvidersMap.get(key); + return ( + + + + {t(provider?.name ?? "")} + + + ); + }; + + return ( + - - - - - } - onChange={(v) => { - formInst.setFieldValue("domains", v); - }} - /> - - + +
+ } + > + + + + + + + + } + onChange={(v) => { + formInst.setFieldValue("domains", v); + }} + /> + + - } - > - - + } + > + + - - - - { - const provider = accessProvidersMap.get(record.provider); - return ACCESS_USAGES.ALL === provider?.usage || ACCESS_USAGES.APPLY === provider?.usage; - }} + - + + + + + { + const provider = accessProvidersMap.get(record.provider); + return ACCESS_USAGES.ALL === provider?.usage || ACCESS_USAGES.APPLY === provider?.usage; + }} + onChange={handleProviderAccessSelect} + /> + + + + + {nestedFormEl} @@ -183,71 +271,73 @@ const ApplyNodeConfigForm = forwardRef - - ({ + label: e, + value: e, + }))} + placeholder={t("workflow_node.apply.form.key_algorithm.placeholder")} + /> + - } - > - - - } + > + + + { + formInst.setFieldValue("nameservers", e.target.value); + }} + /> + + { - formInst.setFieldValue("nameservers", e.target.value); + trigger={ + + } + onChange={(value) => { + formInst.setFieldValue("nameservers", value); }} /> - - - - - } - onChange={(value) => { - formInst.setFieldValue("nameservers", value); - }} + + + + } + > + - - +
- } - > - - - - } - > - - - + } + > + + + +
); } ); diff --git a/ui/src/components/workflow/node/ApplyNodeConfigFormAWSRoute53Config.tsx b/ui/src/components/workflow/node/ApplyNodeConfigFormAWSRoute53Config.tsx new file mode 100644 index 00000000..a14a7057 --- /dev/null +++ b/ui/src/components/workflow/node/ApplyNodeConfigFormAWSRoute53Config.tsx @@ -0,0 +1,81 @@ +import { useTranslation } from "react-i18next"; +import { Form, type FormInstance, Input } from "antd"; +import { createSchemaFieldRule } from "antd-zod"; +import { z } from "zod"; + +type ApplyNodeConfigFormAWSRoute53ConfigFieldValues = Nullish<{ + region: string; + hostedZoneId: string; +}>; + +export type ApplyNodeConfigFormAWSRoute53ConfigProps = { + form: FormInstance; + formName: string; + disabled?: boolean; + initialValues?: ApplyNodeConfigFormAWSRoute53ConfigFieldValues; + onValuesChange?: (values: ApplyNodeConfigFormAWSRoute53ConfigFieldValues) => void; +}; + +const initFormModel = (): ApplyNodeConfigFormAWSRoute53ConfigFieldValues => { + return { + region: "us-east-1", + hostedZoneId: "", + }; +}; + +const ApplyNodeConfigFormAWSRoute53Config = ({ + form: formInst, + formName, + disabled, + initialValues, + onValuesChange, +}: ApplyNodeConfigFormAWSRoute53ConfigProps) => { + const { t } = useTranslation(); + + const formSchema = z.object({ + region: z + .string({ message: t("workflow_node.apply.form.aws_route53_region.placeholder") }) + .nonempty(t("workflow_node.apply.form.aws_route53_region.placeholder")) + .trim(), + hostedZoneId: z + .string({ message: t("workflow_node.apply.form.aws_route53_hosted_zone_id.placeholder") }) + .nonempty(t("workflow_node.apply.form.aws_route53_hosted_zone_id.placeholder")) + .trim(), + }); + const formRule = createSchemaFieldRule(formSchema); + + const handleFormChange = (_: unknown, values: z.infer) => { + onValuesChange?.(values); + }; + + return ( +
+ } + > + + + + } + > + + +
+ ); +}; + +export default ApplyNodeConfigFormAWSRoute53Config; diff --git a/ui/src/components/workflow/node/ApplyNodeConfigFormHuaweiCloudDNSConfig.tsx b/ui/src/components/workflow/node/ApplyNodeConfigFormHuaweiCloudDNSConfig.tsx new file mode 100644 index 00000000..dcde7c75 --- /dev/null +++ b/ui/src/components/workflow/node/ApplyNodeConfigFormHuaweiCloudDNSConfig.tsx @@ -0,0 +1,66 @@ +import { useTranslation } from "react-i18next"; +import { Form, type FormInstance, Input } from "antd"; +import { createSchemaFieldRule } from "antd-zod"; +import { z } from "zod"; + +type ApplyNodeConfigFormHuaweiCloudDNSConfigFieldValues = Nullish<{ + region: string; +}>; + +export type ApplyNodeConfigFormHuaweiCloudDNSConfigProps = { + form: FormInstance; + formName: string; + disabled?: boolean; + initialValues?: ApplyNodeConfigFormHuaweiCloudDNSConfigFieldValues; + onValuesChange?: (values: ApplyNodeConfigFormHuaweiCloudDNSConfigFieldValues) => void; +}; + +const initFormModel = (): ApplyNodeConfigFormHuaweiCloudDNSConfigFieldValues => { + return { + region: "cn-north-1", + }; +}; + +const ApplyNodeConfigFormHuaweiCloudDNSConfig = ({ + form: formInst, + formName, + disabled, + initialValues, + onValuesChange, +}: ApplyNodeConfigFormHuaweiCloudDNSConfigProps) => { + const { t } = useTranslation(); + + const formSchema = z.object({ + region: z + .string({ message: t("workflow_node.apply.form.huaweicloud_dns_region.placeholder") }) + .nonempty(t("workflow_node.apply.form.huaweicloud_dns_region.placeholder")) + .trim(), + }); + const formRule = createSchemaFieldRule(formSchema); + + const handleFormChange = (_: unknown, values: z.infer) => { + onValuesChange?.(values); + }; + + return ( +
+ } + > + + +
+ ); +}; + +export default ApplyNodeConfigFormHuaweiCloudDNSConfig; diff --git a/ui/src/components/workflow/node/DeployNodeConfigForm.tsx b/ui/src/components/workflow/node/DeployNodeConfigForm.tsx index 5462eebb..272e5f18 100644 --- a/ui/src/components/workflow/node/DeployNodeConfigForm.tsx +++ b/ui/src/components/workflow/node/DeployNodeConfigForm.tsx @@ -80,7 +80,8 @@ const DeployNodeConfigForm = forwardRef !!formInst.getFieldValue("provider"), t("workflow_node.deploy.form.provider.placeholder")), providerConfig: z.any(), }); const formRule = createSchemaFieldRule(formSchema); @@ -200,10 +201,16 @@ const DeployNodeConfigForm = forwardRef { return { getFieldsValue: () => { - return formInst.getFieldsValue(true); + const values = formInst.getFieldsValue(true); + values.providerConfig = nestedFormInst.getFieldsValue(); + return values; }, resetFields: (fields) => { - return formInst.resetFields(fields); + formInst.resetFields(fields); + + if (!!fields && fields.includes("providerConfig")) { + nestedFormInst.resetFields(fields); + } }, validateFields: (nameList, config) => { const t1 = formInst.validateFields(nameList, config); @@ -216,7 +223,10 @@ const DeployNodeConfigForm = forwardRef
- }> + } + > - - - - {t("workflow_node.deploy.form.params_config.label")} - - - {nestedFormEl} + + + + {t("workflow_node.deploy.form.params_config.label")} + + + + {nestedFormEl} + ); } diff --git a/ui/src/domain/provider.ts b/ui/src/domain/provider.ts index 73eb805e..4a0dc560 100644 --- a/ui/src/domain/provider.ts +++ b/ui/src/domain/provider.ts @@ -1,3 +1,4 @@ +// #region AccessProvider /* 注意:如果追加新的常量值,请保持以 ASCII 排序。 NOTICE: If you add new constant, please keep ASCII order. @@ -47,25 +48,25 @@ export const accessProvidersMap: Map [ type, { @@ -76,7 +77,66 @@ export const accessProvidersMap: Map = new Map( + /* + 注意:此处的顺序决定显示在前端的顺序。 + NOTICE: The following order determines the order displayed at the frontend. + */ + [ + [APPLY_DNS_PROVIDERS.ALIYUN_DNS, "common.provider.aliyun.dns"], + [APPLY_DNS_PROVIDERS.TENCENTCLOUD_DNS, "common.provider.tencentcloud.dns"], + [APPLY_DNS_PROVIDERS.HUAWEICLOUD_DNS, "common.provider.huaweicloud.dns"], + [APPLY_DNS_PROVIDERS.VOLCENGINE_DNS, "common.provider.volcengine.dns"], + [APPLY_DNS_PROVIDERS.AWS_ROUTE53, "common.provider.aws.route53"], + [APPLY_DNS_PROVIDERS.CLOUDFLARE, "common.provider.cloudflare"], + [APPLY_DNS_PROVIDERS.GODADDY, "common.provider.godaddy"], + [APPLY_DNS_PROVIDERS.NAMEDOTCOM, "common.provider.namedotcom"], + [APPLY_DNS_PROVIDERS.NAMESILO, "common.provider.namesilo"], + [APPLY_DNS_PROVIDERS.POWERDNS, "common.provider.powerdns"], + [APPLY_DNS_PROVIDERS.ACMEHTTPREQ, "common.provider.acmehttpreq"], + ].map(([type, name]) => [ + type, + { + type: type as ApplyDNSProviderType, + name: name, + icon: accessProvidersMap.get(type.split("-")[0])!.icon, + provider: type.split("-")[0] as AccessProviderType, + }, + ]) +); +// #endregion + +// #region DeployProvider /* 注意:如果追加新的常量值,请保持以 ASCII 排序。 NOTICE: If you add new constant, please keep ASCII order. @@ -155,3 +215,4 @@ export const deployProvidersMap: Map; keyAlgorithm: string; nameservers?: string; propagationTimeout?: number; diff --git a/ui/src/hooks/useZustandShallowSelector.ts b/ui/src/hooks/useZustandShallowSelector.ts index 724cdf2c..23b23666 100644 --- a/ui/src/hooks/useZustandShallowSelector.ts +++ b/ui/src/hooks/useZustandShallowSelector.ts @@ -18,11 +18,11 @@ export type UseZustandShallowSelectorReturns ({ + * const { foo, bar, baz } = useStore(useShallow((state) => ({ * foo: state.foo, * bar: state.bar, * baz: state.baz, - * })); + * }))); * ``` */ const useZustandShallowSelector = (paths: MaybeMany): UseZustandShallowSelectorReturns => { diff --git a/ui/src/i18n/locales/en/nls.access.json b/ui/src/i18n/locales/en/nls.access.json index 0da23efb..94ca5979 100644 --- a/ui/src/i18n/locales/en/nls.access.json +++ b/ui/src/i18n/locales/en/nls.access.json @@ -45,12 +45,6 @@ "access.form.aws_secret_access_key.label": "AWS SecretAccessKey", "access.form.aws_secret_access_key.placeholder": "Please enter AWS SecretAccessKey", "access.form.aws_secret_access_key.tooltip": "For more information, see https://docs.aws.amazon.com/en_us/IAM/latest/UserGuide/id_credentials_access-keys.html", - "access.form.aws_region.label": "AWS Region", - "access.form.aws_region.placeholder": "Please enter AWS region (e.g. us-east-1)", - "access.form.aws_region.tooltip": "For more information, see https://docs.aws.amazon.com/en_us/general/latest/gr/rande.html#regional-endpoints", - "access.form.aws_hosted_zone_id.label": "AWS hosted zone ID", - "access.form.aws_hosted_zone_id.placeholder": "Please enter AWS hosted zone ID", - "access.form.aws_hosted_zone_id.tooltip": "For more information, see https://docs.aws.amazon.com/en_us/Route53/latest/DeveloperGuide/hosted-zones-working-with.html", "access.form.baiducloud_access_key_id.label": "Baidu Cloud AccessKeyID", "access.form.baiducloud_access_key_id.placeholder": "Please enter Baidu Cloud AccessKeyID", "access.form.baiducloud_access_key_id.tooltip": "For more information, see https://intl.cloud.baidu.com/doc/Reference/s/jjwvz2e3p-en", @@ -84,9 +78,6 @@ "access.form.huaweicloud_secret_access_key.label": "Huawei Cloud SecretAccessKey", "access.form.huaweicloud_secret_access_key.placeholder": "Please enter Huawei Cloud SecretAccessKey", "access.form.huaweicloud_secret_access_key.tooltip": "For more information, see https://support.huaweicloud.com/intl/en-us/usermanual-ca/ca_01_0003.html", - "access.form.huaweicloud_region.label": "Huawei Cloud region", - "access.form.huaweicloud_region.placeholder": "Please enter Huawei Cloud region (e.g. cn-north-1)", - "access.form.huaweicloud_region.tooltip": "For more information, see https://console-intl.huaweicloud.com/apiexplorer/#/endpoint", "access.form.k8s_kubeconfig.label": "KubeConfig", "access.form.k8s_kubeconfig.placeholder": "Please enter KubeConfig file", "access.form.k8s_kubeconfig.upload": "Choose File ...", diff --git a/ui/src/i18n/locales/en/nls.common.json b/ui/src/i18n/locales/en/nls.common.json index 8d78fd6e..fa48080f 100644 --- a/ui/src/i18n/locales/en/nls.common.json +++ b/ui/src/i18n/locales/en/nls.common.json @@ -41,9 +41,11 @@ "common.provider.aliyun.cdn": "Alibaba Cloud - CDN", "common.provider.aliyun.clb": "Alibaba Cloud - CLB", "common.provider.aliyun.dcdn": "Alibaba Cloud - DCDN", + "common.provider.aliyun.dns": "Alibaba Cloud - DNS", "common.provider.aliyun.nlb": "Alibaba Cloud - NLB", "common.provider.aliyun.oss": "Alibaba Cloud - OSS", "common.provider.aws": "AWS", + "common.provider.aws.route53": "AWS - Route53", "common.provider.baiducloud": "Baidu Cloud", "common.provider.baiducloud.cdn": "Baidu Cloud - CDN", "common.provider.byteplus": "BytePlus", @@ -54,6 +56,7 @@ "common.provider.godaddy": "GoDaddy", "common.provider.huaweicloud": "Huawei Cloud", "common.provider.huaweicloud.cdn": "Huawei Cloud - CDN", + "common.provider.huaweicloud.dns": "Huawei Cloud - DNS", "common.provider.huaweicloud.elb": "Huawei Cloud - ELB", "common.provider.kubernetes": "Kubernetes", "common.provider.kubernetes.secret": "Kubernetes - Secret", @@ -68,10 +71,12 @@ "common.provider.tencentcloud.cdn": "Tencent Cloud - CDN", "common.provider.tencentcloud.clb": "Tencent Cloud - CLB", "common.provider.tencentcloud.cos": "Tencent Cloud - COS", + "common.provider.tencentcloud.dns": "Tencent Cloud - DNS", "common.provider.tencentcloud.ecdn": "Tencent Cloud - ECDN", "common.provider.tencentcloud.eo": "Tencent Cloud - EdgeOne", "common.provider.volcengine": "Volcengine", "common.provider.volcengine.cdn": "Volcengine - CDN", + "common.provider.volcengine.dns": "Volcengine - DNS", "common.provider.volcengine.live": "Volcengine - Live", "common.provider.webhook": "Webhook", diff --git a/ui/src/i18n/locales/en/nls.workflow.json b/ui/src/i18n/locales/en/nls.workflow.json index d59fb3ae..465923d1 100644 --- a/ui/src/i18n/locales/en/nls.workflow.json +++ b/ui/src/i18n/locales/en/nls.workflow.json @@ -50,5 +50,6 @@ "workflow.detail.orchestration.action.release.failed.uncompleted": "Please complete the orchestration first", "workflow.detail.orchestration.action.run": "Run", "workflow.detail.orchestration.action.run.confirm": "You have unreleased changes. Do you really want to run this workflow based on the latest released version?", + "workflow.detail.orchestration.action.run.prompt": "Running... Please check the history later", "workflow.detail.runs.tab": "History runs" } diff --git a/ui/src/i18n/locales/en/nls.workflow.nodes.json b/ui/src/i18n/locales/en/nls.workflow.nodes.json index 1a99291e..2095445e 100644 --- a/ui/src/i18n/locales/en/nls.workflow.nodes.json +++ b/ui/src/i18n/locales/en/nls.workflow.nodes.json @@ -31,10 +31,21 @@ "workflow_node.apply.form.contact_email.label": "Contact email", "workflow_node.apply.form.contact_email.placeholder": "Please enter contact email", "workflow_node.apply.form.contact_email.tooltip": "Contact information required for SSL certificate application. Please pay attention to the rate limits.", + "workflow_node.apply.form.provider.label": "DNS provider", + "workflow_node.apply.form.provider.placeholder": "Please select DNS provider of the domains", "workflow_node.apply.form.provider_access.label": "DNS provider authorization", "workflow_node.apply.form.provider_access.placeholder": "Please select an authorization of DNS provider", "workflow_node.apply.form.provider_access.tooltip": "Used to manage DNS records during ACME DNS-01 authentication.", "workflow_node.apply.form.provider_access.button": "Create", + "workflow_node.apply.form.aws_route53_region.label": "AWS Route53 Region", + "workflow_node.apply.form.aws_route53_region.placeholder": "Please enter AWS Route53 region (e.g. us-east-1)", + "workflow_node.apply.form.aws_route53_region.tooltip": "For more information, see https://docs.aws.amazon.com/en_us/general/latest/gr/rande.html#regional-endpoints", + "workflow_node.apply.form.aws_route53_hosted_zone_id.label": "AWS Route53 hosted zone ID", + "workflow_node.apply.form.aws_route53_hosted_zone_id.placeholder": "Please enter AWS Route53 hosted zone ID", + "workflow_node.apply.form.aws_route53_hosted_zone_id.tooltip": "For more information, see https://docs.aws.amazon.com/en_us/Route53/latest/DeveloperGuide/hosted-zones-working-with.html", + "workflow_node.apply.form.huaweicloud_dns_region.label": "Huawei Cloud DNS region", + "workflow_node.apply.form.huaweicloud_dns_region.placeholder": "Please enter Huawei Cloud DNS region (e.g. cn-north-1)", + "workflow_node.apply.form.huaweicloud_dns_region.tooltip": "For more information, see https://console-intl.huaweicloud.com/apiexplorer/#/endpoint", "workflow_node.apply.form.advanced_config.label": "Advanced settings", "workflow_node.apply.form.key_algorithm.label": "Certificate key algorithm", "workflow_node.apply.form.key_algorithm.placeholder": "Please select certificate key algorithm", diff --git a/ui/src/i18n/locales/zh/nls.access.json b/ui/src/i18n/locales/zh/nls.access.json index 37645e5b..b908f33e 100644 --- a/ui/src/i18n/locales/zh/nls.access.json +++ b/ui/src/i18n/locales/zh/nls.access.json @@ -45,12 +45,6 @@ "access.form.aws_secret_access_key.label": "AWS SecretAccessKey", "access.form.aws_secret_access_key.placeholder": "请输入 AWS SecretAccessKey", "access.form.aws_secret_access_key.tooltip": "这是什么?请参阅 https://docs.aws.amazon.com/zh_cn/IAM/latest/UserGuide/id_credentials_access-keys.html", - "access.form.aws_region.label": "AWS 区域", - "access.form.aws_region.placeholder": "请输入 AWS 区域(例如:us-east-1)", - "access.form.aws_region.tooltip": "这是什么?请参阅 https://docs.aws.amazon.com/zh_cn/general/latest/gr/rande.html#regional-endpoints", - "access.form.aws_hosted_zone_id.label": "AWS 托管区域 ID", - "access.form.aws_hosted_zone_id.placeholder": "请输入 AWS 托管区域 ID", - "access.form.aws_hosted_zone_id.tooltip": "这是什么?请参阅 https://docs.aws.amazon.com/zh_cn/Route53/latest/DeveloperGuide/hosted-zones-working-with.html", "access.form.baiducloud_access_key_id.label": "百度智能云 AccessKeyID", "access.form.baiducloud_access_key_id.placeholder": "请输入百度智能云 AccessKeyID", "access.form.baiducloud_access_key_id.tooltip": "这是什么?请参阅 https://cloud.baidu.com/doc/Reference/s/jjwvz2e3p", @@ -84,9 +78,6 @@ "access.form.huaweicloud_secret_access_key.label": "华为云 SecretAccessKey", "access.form.huaweicloud_secret_access_key.placeholder": "请输入华为云 SecretAccessKey", "access.form.huaweicloud_secret_access_key.tooltip": "这是什么?请参阅 https://support.huaweicloud.com/usermanual-ca/ca_01_0003.html", - "access.form.huaweicloud_region.label": "华为云区域", - "access.form.huaweicloud_region.placeholder": "请输入华为云区域(例如:cn-north-1)", - "access.form.huaweicloud_region.tooltip": "这是什么?请参阅 https://console.huaweicloud.com/apiexplorer/#/endpoint", "access.form.k8s_kubeconfig.label": "KubeConfig", "access.form.k8s_kubeconfig.placeholder": "请选择 KubeConfig 文件", "access.form.k8s_kubeconfig.upload": "选择文件", diff --git a/ui/src/i18n/locales/zh/nls.common.json b/ui/src/i18n/locales/zh/nls.common.json index 8eaee862..9ba8cbea 100644 --- a/ui/src/i18n/locales/zh/nls.common.json +++ b/ui/src/i18n/locales/zh/nls.common.json @@ -41,9 +41,11 @@ "common.provider.aliyun.cdn": "阿里云 - 内容分发网络 CDN", "common.provider.aliyun.clb": "阿里云 - 传统型负载均衡 CLB", "common.provider.aliyun.dcdn": "阿里云 - 全站加速 DCDN", + "common.provider.aliyun.dns": "阿里云 - 云解析 DNS", "common.provider.aliyun.nlb": "阿里云 - 网络型负载均衡 NLB", "common.provider.aliyun.oss": "阿里云 - 对象存储 OSS", "common.provider.aws": "AWS", + "common.provider.aws.route53": "AWS - Route53", "common.provider.baiducloud": "百度智能云", "common.provider.baiducloud.cdn": "百度智能云 - 内容分发网络 CDN", "common.provider.byteplus": "BytePlus", @@ -54,6 +56,7 @@ "common.provider.godaddy": "GoDaddy", "common.provider.huaweicloud": "华为云", "common.provider.huaweicloud.cdn": "华为云 - 内容分发网络 CDN", + "common.provider.huaweicloud.dns": "华为云 - 云解析 DNS", "common.provider.huaweicloud.elb": "华为云 - 弹性负载均衡 ELB", "common.provider.kubernetes": "Kubernetes", "common.provider.kubernetes.secret": "Kubernetes - Secret", @@ -68,10 +71,12 @@ "common.provider.tencentcloud.cdn": "腾讯云 - 内容分发网络 CDN", "common.provider.tencentcloud.clb": "腾讯云 - 负载均衡 CLB", "common.provider.tencentcloud.cos": "腾讯云 - 对象存储 COS", + "common.provider.tencentcloud.dns": "腾讯云 - 云解析 DNS", "common.provider.tencentcloud.ecdn": "腾讯云 - 全站加速网络 ECDN", "common.provider.tencentcloud.eo": "腾讯云 - 边缘安全加速平台 EdgeOne", "common.provider.volcengine": "火山引擎", "common.provider.volcengine.cdn": "火山引擎 - 内容分发网络 CDN", + "common.provider.volcengine.dns": "火山引擎 - 云解析 DNS", "common.provider.volcengine.live": "火山引擎 - 视频直播 Live", "common.provider.webhook": "Webhook", diff --git a/ui/src/i18n/locales/zh/nls.workflow.json b/ui/src/i18n/locales/zh/nls.workflow.json index fe2644cb..46058991 100644 --- a/ui/src/i18n/locales/zh/nls.workflow.json +++ b/ui/src/i18n/locales/zh/nls.workflow.json @@ -9,7 +9,7 @@ "workflow.action.delete.confirm": "确定要删除此工作流吗?", "workflow.action.enable": "启用", "workflow.action.enable.failed.uncompleted": "请先完成流程编排并发布更改", - "workflow.action.disable": "禁用", + "workflow.action.disable": "停用", "workflow.props.name": "名称", "workflow.props.description": "描述", @@ -50,5 +50,6 @@ "workflow.detail.orchestration.action.release.failed.uncompleted": "流程编排未完成,请检查是否有节点未配置", "workflow.detail.orchestration.action.run": "执行", "workflow.detail.orchestration.action.run.confirm": "你有尚未发布的更改。你确定要以最近一次发布的版本继续执行吗?", + "workflow.detail.orchestration.action.run.prompt": "执行中……请稍后查看执行历史", "workflow.detail.runs.tab": "执行历史" } diff --git a/ui/src/i18n/locales/zh/nls.workflow.nodes.json b/ui/src/i18n/locales/zh/nls.workflow.nodes.json index 228dcb5c..6ede2b58 100644 --- a/ui/src/i18n/locales/zh/nls.workflow.nodes.json +++ b/ui/src/i18n/locales/zh/nls.workflow.nodes.json @@ -31,10 +31,21 @@ "workflow_node.apply.form.contact_email.label": "联系邮箱", "workflow_node.apply.form.contact_email.placeholder": "请输入联系邮箱", "workflow_node.apply.form.contact_email.tooltip": "申请签发 SSL 证书时所需的联系方式。请注意 Let's Encrypt 账户注册的速率限制。
点此了解更多。", + "workflow_node.apply.form.provider.label": "DNS 提供商", + "workflow_node.apply.form.provider.placeholder": "请选择 DNS 提供商", "workflow_node.apply.form.provider_access.label": "DNS 提供商授权", "workflow_node.apply.form.provider_access.placeholder": "请选择 DNS 提供商授权", "workflow_node.apply.form.provider_access.tooltip": "用于 ACME DNS-01 认证时操作域名解析记录,注意与部署阶段所需的主机提供商相区分。", "workflow_node.apply.form.provider_access.button": "新建", + "workflow_node.apply.form.aws_route53_region.label": "AWS Route53 区域", + "workflow_node.apply.form.aws_route53_region.placeholder": "请输入 AWS Route53 区域(例如:us-east-1)", + "workflow_node.apply.form.aws_route53_region.tooltip": "这是什么?请参阅 https://docs.aws.amazon.com/zh_cn/general/latest/gr/rande.html#regional-endpoints", + "workflow_node.apply.form.aws_route53_hosted_zone_id.label": "AWS Route53 托管区域 ID", + "workflow_node.apply.form.aws_route53_hosted_zone_id.placeholder": "请输入 AWS Route53 托管区域 ID", + "workflow_node.apply.form.aws_route53_hosted_zone_id.tooltip": "这是什么?请参阅 https://docs.aws.amazon.com/zh_cn/Route53/latest/DeveloperGuide/hosted-zones-working-with.html", + "workflow_node.apply.form.huaweicloud_dns_region.label": "华为云 DNS 服务区域", + "workflow_node.apply.form.huaweicloud_dns_region.placeholder": "请输入华为云 DNS 服务区域(例如:cn-north-1)", + "workflow_node.apply.form.huaweicloud_dns_region.tooltip": "这是什么?请参阅 https://console.huaweicloud.com/apiexplorer/#/endpoint", "workflow_node.apply.form.advanced_config.label": "高级设置", "workflow_node.apply.form.key_algorithm.label": "数字证书算法", "workflow_node.apply.form.key_algorithm.placeholder": "请选择数字证书算法", diff --git a/ui/src/pages/workflows/WorkflowDetail.tsx b/ui/src/pages/workflows/WorkflowDetail.tsx index 0d89ac2a..97eeda2d 100644 --- a/ui/src/pages/workflows/WorkflowDetail.tsx +++ b/ui/src/pages/workflows/WorkflowDetail.tsx @@ -13,16 +13,16 @@ import { import { PageHeader } from "@ant-design/pro-components"; import { Alert, Button, Card, Dropdown, Form, Input, Modal, Space, Tabs, Typography, message, notification } from "antd"; import { createSchemaFieldRule } from "antd-zod"; -import { ClientResponseError } from "pocketbase"; import { isEqual } from "radash"; import { z } from "zod"; -import { run as runWorkflow, subscribe, unsubscribe } from "@/api/workflow"; +import { run as runWorkflow, subscribe as subscribeWorkflow, unsubscribe as unsubscribeWorkflow } from "@/api/workflow"; import ModalForm from "@/components/ModalForm"; import Show from "@/components/Show"; import WorkflowElements from "@/components/workflow/WorkflowElements"; import WorkflowRuns from "@/components/workflow/WorkflowRuns"; import { isAllNodesValidated } from "@/domain/workflow"; +import { WORKFLOW_RUN_STATUSES } from "@/domain/workflowRun"; import { useAntdForm, useZustandShallowSelector } from "@/hooks"; import { remove as removeWorkflow } from "@/repository/workflow"; import { useWorkflowStore } from "@/stores/workflow"; @@ -63,21 +63,21 @@ const WorkflowDetail = () => { }, [workflow]); useEffect(() => { - if (lastRunStatus && lastRunStatus == "running") { - setIsRunning(true); - } else { - setIsRunning(false); - } + setIsRunning(lastRunStatus == WORKFLOW_RUN_STATUSES.RUNNING); }, [lastRunStatus]); useEffect(() => { - if (isRunning && workflowId) { - subscribe(workflowId, (e) => { - if (e.record.lastRunStatus !== "running") { + if (!!workflowId && isRunning) { + subscribeWorkflow(workflowId, (e) => { + if (e.record.lastRunStatus !== WORKFLOW_RUN_STATUSES.RUNNING) { setIsRunning(false); - unsubscribe(workflowId); + unsubscribeWorkflow(workflowId); } }); + + return () => { + unsubscribeWorkflow(workflowId); + }; } }, [workflowId, isRunning]); @@ -174,26 +174,28 @@ const WorkflowDetail = () => { } promise.then(async () => { + let unsubscribeFn: Awaited> | undefined = undefined; + try { + setIsRunning(true); + // subscribe before running workflow - subscribe(workflowId!, (e) => { - if (e.record.lastRunStatus !== "running") { + unsubscribeFn = await subscribeWorkflow(workflowId!, (e) => { + if (e.record.lastRunStatus !== WORKFLOW_RUN_STATUSES.RUNNING) { setIsRunning(false); - unsubscribe(workflowId!); + unsubscribeFn?.(); } }); + await runWorkflow(workflowId!); - setIsRunning(true); - messageApi.success(t("common.text.operation_succeeded")); + messageApi.info(t("workflow.detail.orchestration.action.run.prompt")); } catch (err) { - if (err instanceof ClientResponseError && err.isAbort) { - return; - } + setIsRunning(false); + unsubscribeFn?.(); console.error(err); messageApi.warning(t("common.text.operation_failed")); - setIsRunning(false); } }); };