diff --git a/.editorconfig b/.editorconfig index f0b25219..14d9f966 100644 --- a/.editorconfig +++ b/.editorconfig @@ -10,5 +10,7 @@ trim_trailing_whitespace = true insert_final_newline = true [*.go] +charset = utf-8 +end_of_line = lf indent_size = 2 indent_style = tab diff --git a/go.mod b/go.mod index e5038ab0..fd7c0355 100644 --- a/go.mod +++ b/go.mod @@ -5,30 +5,32 @@ go 1.23.0 toolchain go1.23.2 require ( - github.com/Azure/azure-sdk-for-go/sdk/azcore v1.17.0 - github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.8.2 - github.com/Azure/azure-sdk-for-go/sdk/keyvault/azcertificates v0.9.0 + github.com/Azure/azure-sdk-for-go/sdk/azcore v1.18.0 + github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.9.0 + github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azcertificates v1.3.1 github.com/Edgio/edgio-api v0.0.0-workspace - github.com/G-Core/gcorelabscdn-go v1.0.28 + github.com/G-Core/gcorelabscdn-go v1.0.29 github.com/alibabacloud-go/alb-20200616/v2 v2.2.8 + github.com/alibabacloud-go/apig-20240327/v3 v3.2.2 github.com/alibabacloud-go/cas-20200407/v3 v3.0.4 github.com/alibabacloud-go/cdn-20180510/v5 v5.2.2 - github.com/alibabacloud-go/darabonba-openapi/v2 v2.1.4 - github.com/alibabacloud-go/esa-20240910/v2 v2.23.0 - github.com/alibabacloud-go/fc-20230330/v4 v4.1.7 + github.com/alibabacloud-go/cloudapi-20160714/v5 v5.7.2 + github.com/alibabacloud-go/darabonba-openapi/v2 v2.1.7 + github.com/alibabacloud-go/esa-20240910/v2 v2.31.1 + github.com/alibabacloud-go/fc-20230330/v4 v4.3.4 github.com/alibabacloud-go/fc-open-20210406/v2 v2.0.12 github.com/alibabacloud-go/live-20161101 v1.1.1 github.com/alibabacloud-go/nlb-20220430/v2 v2.0.3 github.com/alibabacloud-go/slb-20140515/v4 v4.0.10 - github.com/alibabacloud-go/tea v1.3.4 - github.com/alibabacloud-go/vod-20170321/v4 v4.7.0 - github.com/alibabacloud-go/waf-openapi-20211001/v5 v5.0.5 + github.com/alibabacloud-go/tea v1.3.9 + github.com/alibabacloud-go/vod-20170321/v4 v4.8.3 + github.com/alibabacloud-go/waf-openapi-20211001/v5 v5.1.1 github.com/aliyun/aliyun-oss-go-sdk v3.0.2+incompatible - github.com/aws/aws-sdk-go-v2/service/acm v1.31.1 - github.com/aws/aws-sdk-go-v2/service/cloudfront v1.45.2 - github.com/baidubce/bce-sdk-go v0.9.221 - github.com/byteplus-sdk/byteplus-sdk-golang v1.0.42 - github.com/go-acme/lego/v4 v4.22.2 + github.com/aws/aws-sdk-go-v2/service/acm v1.31.3 + github.com/aws/aws-sdk-go-v2/service/cloudfront v1.45.3 + github.com/baidubce/bce-sdk-go v0.9.224 + github.com/byteplus-sdk/byteplus-sdk-golang v1.0.44 + github.com/go-acme/lego/v4 v4.23.1 github.com/go-resty/resty/v2 v2.16.5 github.com/go-viper/mapstructure/v2 v2.2.1 github.com/huaweicloud/huaweicloud-sdk-go-v3 v0.1.141 @@ -37,28 +39,28 @@ require ( github.com/libdns/libdns v0.2.3 github.com/nikoksr/notify v1.3.0 github.com/pavlo-v-chernykh/keystore-go/v4 v4.5.0 - github.com/pkg/sftp v1.13.8 + github.com/pkg/sftp v1.13.9 github.com/pocketbase/dbx v1.11.0 - github.com/pocketbase/pocketbase v0.26.1 + github.com/pocketbase/pocketbase v0.27.1 github.com/povsister/scp v0.0.0-20240802064259-28781e87b246 - github.com/qiniu/go-sdk/v7 v7.25.2 - github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cdn v1.0.1115 - github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/clb v1.0.1127 - github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1127 - github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/live v1.0.1117 - github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/scf v1.0.1115 + github.com/qiniu/go-sdk/v7 v7.25.3 + github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cdn v1.0.1136 + github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/clb v1.0.1143 + github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1147 + github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/live v1.0.1143 + github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/scf v1.0.1120 github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/ssl v1.0.1124 - github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/teo v1.0.1126 - github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/vod v1.0.1115 - github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/waf v1.0.1125 - github.com/ucloud/ucloud-sdk-go v0.22.31 - github.com/volcengine/ve-tos-golang-sdk/v2 v2.7.9 - github.com/volcengine/volc-sdk-golang v1.0.199 - github.com/volcengine/volcengine-go-sdk v1.0.187 + github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/teo v1.0.1138 + github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/vod v1.0.1136 + github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/waf v1.0.1147 + github.com/ucloud/ucloud-sdk-go v0.22.33 + github.com/volcengine/ve-tos-golang-sdk/v2 v2.7.11 + github.com/volcengine/volc-sdk-golang v1.0.204 + github.com/volcengine/volcengine-go-sdk v1.1.4 gitlab.ecloud.com/ecloud/ecloudsdkclouddns v1.0.1 gitlab.ecloud.com/ecloud/ecloudsdkcore v1.0.0 - golang.org/x/crypto v0.36.0 - golang.org/x/exp v0.0.0-20250305212735-054e65f0b394 + golang.org/x/crypto v0.37.0 + golang.org/x/exp v0.0.0-20250408133849-7e4ce0ab07d0 k8s.io/api v0.32.3 k8s.io/apimachinery v0.32.3 k8s.io/client-go v0.32.3 @@ -66,23 +68,25 @@ require ( ) require ( - github.com/Azure/azure-sdk-for-go/sdk/internal v1.10.0 // indirect - github.com/Azure/azure-sdk-for-go/sdk/keyvault/internal v0.7.1 // indirect + github.com/Azure/azure-sdk-for-go/sdk/internal v1.11.1 // indirect github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/dns/armdns v1.2.0 // indirect github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/privatedns/armprivatedns v1.3.0 // indirect github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resourcegraph/armresourcegraph v0.9.0 // indirect - github.com/AzureAD/microsoft-authentication-library-for-go v1.3.3 // indirect + github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/internal v1.1.1 // indirect + github.com/AzureAD/microsoft-authentication-library-for-go v1.4.2 // indirect github.com/alibabacloud-go/alibabacloud-gateway-fc-util v0.0.7 // indirect - github.com/alibabacloud-go/apig-20240327/v3 v3.2.2 // indirect - github.com/alibabacloud-go/cloudapi-20160714/v5 v5.7.2 // indirect + github.com/alibabacloud-go/ddoscoo-20200101/v4 v4.0.0 // indirect github.com/alibabacloud-go/openplatform-20191219/v2 v2.0.1 // indirect github.com/alibabacloud-go/tea-fileform v1.1.1 // indirect github.com/alibabacloud-go/tea-oss-sdk v1.1.3 // indirect github.com/alibabacloud-go/tea-oss-utils v1.1.0 // indirect github.com/alibabacloud-go/tea-utils/v2 v2.0.7 // indirect github.com/avast/retry-go v3.0.0+incompatible // indirect - github.com/aws/aws-sdk-go-v2/service/route53 v1.48.1 // indirect + github.com/aws/aws-sdk-go-v2/service/route53 v1.50.0 // indirect github.com/blinkbean/dingtalk v1.1.3 // indirect + github.com/buger/goterm v1.0.4 // indirect + github.com/diskfs/go-diskfs v1.5.0 // indirect + github.com/djherbis/times v1.6.0 // indirect github.com/emicklei/go-restful/v3 v3.12.1 // indirect github.com/fxamacker/cbor/v2 v2.7.0 // indirect github.com/go-lark/lark v1.15.1 // indirect @@ -97,16 +101,20 @@ require ( github.com/go-telegram-bot-api/telegram-bot-api v4.6.4+incompatible // indirect github.com/gofrs/uuid v4.4.0+incompatible // indirect github.com/gogo/protobuf v1.3.2 // indirect - github.com/golang-jwt/jwt/v5 v5.2.1 // indirect + github.com/golang-jwt/jwt/v5 v5.2.2 // indirect github.com/golang/protobuf v1.5.4 // indirect github.com/google/gnostic-models v0.6.9 // indirect github.com/google/go-cmp v0.6.0 // indirect github.com/google/gofuzz v1.2.0 // indirect + github.com/gorilla/websocket v1.5.3 // indirect github.com/hashicorp/go-cleanhttp v0.5.2 // indirect github.com/hashicorp/go-retryablehttp v0.7.7 // indirect + github.com/jinzhu/copier v0.3.4 // indirect github.com/josharian/intern v1.0.0 // indirect github.com/kylelemons/godebug v1.1.0 // indirect github.com/leodido/go-urn v1.4.0 // indirect + github.com/luthermonson/go-proxmox v0.2.2 // indirect + github.com/magefile/mage v1.14.0 // indirect github.com/mailru/easyjson v0.9.0 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/namedotcom/go v0.0.0-20180403034216-08470befbe04 // indirect @@ -119,7 +127,7 @@ require ( github.com/qiniu/dyn v1.3.0 // indirect github.com/qiniu/x v1.10.5 // indirect github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect - github.com/sirupsen/logrus v1.9.3 // indirect + github.com/sirupsen/logrus v1.9.4-0.20230606125235-dd1b4c2e81af // indirect github.com/technoweenie/multipartstreamer v1.0.1 // indirect github.com/x448/float16 v0.8.4 // indirect go.mongodb.org/mongo-driver v1.17.2 // indirect @@ -136,7 +144,7 @@ require ( ) require ( - github.com/BurntSushi/toml v1.4.0 // indirect + github.com/BurntSushi/toml v1.5.0 // indirect github.com/alibabacloud-go/alibabacloud-gateway-spi v0.0.5 // indirect github.com/alibabacloud-go/dcdn-20180115/v3 v3.5.0 github.com/alibabacloud-go/debug v1.0.1 // indirect @@ -144,35 +152,35 @@ require ( github.com/alibabacloud-go/openapi-util v0.1.1 // indirect github.com/alibabacloud-go/tea-utils v1.4.5 // indirect github.com/alibabacloud-go/tea-xml v1.1.3 // indirect - github.com/aliyun/alibaba-cloud-sdk-go v1.63.83 // indirect - github.com/aliyun/credentials-go v1.4.3 // indirect + github.com/aliyun/alibaba-cloud-sdk-go v1.63.100 // indirect + github.com/aliyun/credentials-go v1.4.5 // indirect github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect github.com/aws/aws-sdk-go-v2 v1.36.3 - github.com/aws/aws-sdk-go-v2/config v1.29.5 - github.com/aws/aws-sdk-go-v2/credentials v1.17.58 - github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.28 // indirect + github.com/aws/aws-sdk-go-v2/config v1.29.9 + github.com/aws/aws-sdk-go-v2/credentials v1.17.62 + github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.30 // indirect github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.34 // indirect github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.34 // indirect - github.com/aws/aws-sdk-go-v2/internal/ini v1.8.2 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.2 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.13 // indirect - github.com/aws/aws-sdk-go-v2/service/sso v1.24.15 // indirect - github.com/aws/aws-sdk-go-v2/service/ssooidc v1.28.14 // indirect - github.com/aws/aws-sdk-go-v2/service/sts v1.33.14 // indirect + github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.3 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.15 // indirect + github.com/aws/aws-sdk-go-v2/service/sso v1.25.1 // indirect + github.com/aws/aws-sdk-go-v2/service/ssooidc v1.29.1 // indirect + github.com/aws/aws-sdk-go-v2/service/sts v1.33.17 // indirect github.com/aws/smithy-go v1.22.2 // indirect github.com/cenkalti/backoff/v4 v4.3.0 // indirect github.com/clbanning/mxj/v2 v2.7.0 // indirect - github.com/cloudflare/cloudflare-go v0.114.0 // indirect + github.com/cloudflare/cloudflare-go v0.115.0 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/disintegration/imaging v1.6.2 // indirect github.com/domodwyer/mailyak/v3 v3.6.2 github.com/dustin/go-humanize v1.0.1 // indirect github.com/fatih/color v1.18.0 // indirect github.com/gabriel-vasile/mimetype v1.4.8 // indirect - github.com/ganigeorgiev/fexpr v0.4.1 // indirect - github.com/go-jose/go-jose/v4 v4.0.4 // indirect + github.com/ganigeorgiev/fexpr v0.5.0 // indirect + github.com/go-jose/go-jose/v4 v4.0.5 // indirect github.com/go-ozzo/ozzo-validation/v4 v4.3.0 // indirect - github.com/goccy/go-json v0.10.4 // indirect + github.com/goccy/go-json v0.10.5 // indirect github.com/google/go-querystring v1.1.0 // indirect github.com/google/uuid v1.6.0 github.com/inconshreveable/mousetrap v1.1.0 // indirect @@ -181,42 +189,42 @@ require ( github.com/kr/fs v0.1.0 // indirect github.com/mattn/go-colorable v0.1.14 // indirect github.com/mattn/go-isatty v0.0.20 // indirect - github.com/miekg/dns v1.1.62 // indirect + github.com/miekg/dns v1.1.64 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect github.com/ncruces/go-strftime v0.1.9 // indirect github.com/nrdcg/namesilo v0.2.1 // indirect github.com/opentracing/opentracing-go v1.2.1-0.20220228012449-10b1cf09e00b // indirect - github.com/pkg/errors v0.9.1 + github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/spf13/cast v1.7.1 // indirect github.com/spf13/cobra v1.9.1 // indirect github.com/spf13/pflag v1.0.6 // indirect github.com/stretchr/objx v0.5.2 // indirect github.com/stretchr/testify v1.10.0 // indirect - github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/dnspod v1.0.1084 // indirect + github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/dnspod v1.0.1128 // indirect github.com/tjfoc/gmsm v1.4.1 // indirect - golang.org/x/image v0.25.0 // indirect + golang.org/x/image v0.26.0 // indirect golang.org/x/mod v0.24.0 // indirect - golang.org/x/net v0.37.0 // indirect - golang.org/x/oauth2 v0.28.0 // indirect - golang.org/x/sync v0.12.0 - golang.org/x/sys v0.31.0 // indirect - golang.org/x/term v0.30.0 // indirect - golang.org/x/text v0.23.0 // indirect - golang.org/x/time v0.9.0 - golang.org/x/tools v0.31.0 // indirect + golang.org/x/net v0.39.0 // indirect + golang.org/x/oauth2 v0.29.0 // indirect + golang.org/x/sync v0.13.0 + golang.org/x/sys v0.32.0 // indirect + golang.org/x/term v0.31.0 // indirect + golang.org/x/text v0.24.0 // indirect + golang.org/x/time v0.11.0 + golang.org/x/tools v0.32.0 // indirect google.golang.org/protobuf v1.36.5 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect - modernc.org/libc v1.61.13 // indirect + modernc.org/libc v1.62.1 // indirect modernc.org/mathutil v1.7.1 // indirect - modernc.org/memory v1.8.2 // indirect - modernc.org/sqlite v1.36.1 // indirect + modernc.org/memory v1.9.1 // indirect + modernc.org/sqlite v1.37.0 // indirect ) -replace github.com/Edgio/edgio-api v0.0.0-workspace => ./internal/pkg/vendors/edgio-sdk/edgio-api@v0.0.0-workspace +replace github.com/Edgio/edgio-api v0.0.0-workspace => ./internal/pkg/sdk3rd/edgio/edgio-api@v0.0.0-workspace -replace gitlab.ecloud.com/ecloud/ecloudsdkcore v1.0.0 => ./internal/pkg/vendors/cmcc-sdk/ecloudsdkcore@v1.0.0 +replace gitlab.ecloud.com/ecloud/ecloudsdkcore v1.0.0 => ./internal/pkg/sdk3rd/cmcc/ecloudsdkcore@v1.0.0 -replace gitlab.ecloud.com/ecloud/ecloudsdkclouddns v1.0.1 => ./internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1 +replace gitlab.ecloud.com/ecloud/ecloudsdkclouddns v1.0.1 => ./internal/pkg/sdk3rd/cmcc/ecloudsdkclouddns@v1.0.1 diff --git a/go.sum b/go.sum index 9caf29d6..7b7fcb73 100644 --- a/go.sum +++ b/go.sum @@ -34,18 +34,14 @@ dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7 filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= github.com/Azure/azure-sdk-for-go v68.0.0+incompatible h1:fcYLmCpyNYRnvJbPerq7U0hS+6+I79yEDJBqVNcqUzU= -github.com/Azure/azure-sdk-for-go/sdk/azcore v1.17.0 h1:g0EZJwz7xkXQiZAI5xi9f3WWFYBlX1CPTrR+NDToRkQ= -github.com/Azure/azure-sdk-for-go/sdk/azcore v1.17.0/go.mod h1:XCW7KnZet0Opnr7HccfUw1PLc4CjHqpcaxW8DHklNkQ= -github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.8.2 h1:F0gBpfdPLGsw+nsgk6aqqkZS1jiixa5WwFe3fk/T3Ys= -github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.8.2/go.mod h1:SqINnQ9lVVdRlyC8cd1lCI0SdX4n2paeABd2K8ggfnE= +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.18.0 h1:Gt0j3wceWMwPmiazCa8MzMA0MfhmPIz0Qp0FJ6qcM0U= +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.18.0/go.mod h1:Ot/6aikWnKWi4l9QB7qVSwa8iMphQNqkWALMoNT3rzM= +github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.9.0 h1:OVoM452qUFBrX+URdH3VpR299ma4kfom0yB0URYky9g= +github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.9.0/go.mod h1:kUjrAo8bgEwLeZ/CmHqNl3Z/kPm7y6FKfxxK0izYUg4= github.com/Azure/azure-sdk-for-go/sdk/azidentity/cache v0.3.2 h1:yz1bePFlP5Vws5+8ez6T3HWXPmwOK7Yvq8QxDBD3SKY= github.com/Azure/azure-sdk-for-go/sdk/azidentity/cache v0.3.2/go.mod h1:Pa9ZNPuoNu/GztvBSKk9J1cDJW6vk/n0zLtV4mgd8N8= -github.com/Azure/azure-sdk-for-go/sdk/internal v1.10.0 h1:ywEEhmNahHBihViHepv3xPBn1663uRv2t2q/ESv9seY= -github.com/Azure/azure-sdk-for-go/sdk/internal v1.10.0/go.mod h1:iZDifYGJTIgIIkYRNWPENUnqx6bJ2xnSDFI2tjwZNuY= -github.com/Azure/azure-sdk-for-go/sdk/keyvault/azcertificates v0.9.0 h1:btEsytNrA4TG3edZnnUnzOz8W2MjOd6Bu3/7xyOXSOY= -github.com/Azure/azure-sdk-for-go/sdk/keyvault/azcertificates v0.9.0/go.mod h1:5SlTxxL1U4LLipEr7pAbnu6Ck5y3aIEu4L/tVbGmpsY= -github.com/Azure/azure-sdk-for-go/sdk/keyvault/internal v0.7.1 h1:FbH3BbSb4bvGluTesZZ+ttN/MDsnMmQP36OSnDuSXqw= -github.com/Azure/azure-sdk-for-go/sdk/keyvault/internal v0.7.1/go.mod h1:9V2j0jn9jDEkCkv8w/bKTNppX/d0FVA1ud77xCIP4KA= +github.com/Azure/azure-sdk-for-go/sdk/internal v1.11.1 h1:FPKJS1T+clwv+OLGt13a8UjqeRuh0O4SJ3lUriThc+4= +github.com/Azure/azure-sdk-for-go/sdk/internal v1.11.1/go.mod h1:j2chePtV91HrC22tGoRX3sGY42uF13WzmmV80/OdVAA= github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/dns/armdns v1.2.0 h1:lpOxwrQ919lCZoNCd69rVt8u1eLZuMORrGXqy8sNf3c= github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/dns/armdns v1.2.0/go.mod h1:fSvRkb8d26z9dbL40Uf/OO6Vo9iExtZK3D0ulRV+8M0= github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/internal/v3 v3.1.0 h1:2qsIIvxVT+uE6yrNldntJKlLRgxGbZ85kgtz5SNBhMw= @@ -56,19 +52,23 @@ github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resourcegraph/armresourceg github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resourcegraph/armresourcegraph v0.9.0/go.mod h1:wVEOJfGTj0oPAUGA1JuRAvz/lxXQsWW16axmHPP47Bk= github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armresources v1.2.0 h1:Dd+RhdJn0OTtVGaeDLZpcumkIVCtA/3/Fo42+eoYvVM= github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armresources v1.2.0/go.mod h1:5kakwfW5CjC9KK+Q4wjXAg+ShuIm2mBMua0ZFj2C8PE= +github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azcertificates v1.3.1 h1:HUJQzFYTv7t3V1dxPms52eEgl0l9xCNqutDrY45Lvmw= +github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azcertificates v1.3.1/go.mod h1:ig/8nSkzmfxm5QGeIy5JYIEj8JEFy5JxvY3OB1YNRC4= +github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/internal v1.1.1 h1:bFWuoEKg+gImo7pvkiQEFAc8ocibADgXeiLAxWhWmkI= +github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/internal v1.1.1/go.mod h1:Vih/3yc6yac2JzU4hzpaDupBJP0Flaia9rXXrU8xyww= github.com/AzureAD/microsoft-authentication-extensions-for-go/cache v0.1.1 h1:WJTmL004Abzc5wDB5VtZG2PJk5ndYDgVacGqfirKxjM= github.com/AzureAD/microsoft-authentication-extensions-for-go/cache v0.1.1/go.mod h1:tCcJZ0uHAmvjsVYzEFivsRTN00oz5BEsRgQHu5JZ9WE= -github.com/AzureAD/microsoft-authentication-library-for-go v1.3.3 h1:H5xDQaE3XowWfhZRUpnfC+rGZMEVoSiji+b+/HFAPU4= -github.com/AzureAD/microsoft-authentication-library-for-go v1.3.3/go.mod h1:wP83P5OoQ5p6ip3ScPr0BAq0BvuPAvacpEuSzyouqAI= +github.com/AzureAD/microsoft-authentication-library-for-go v1.4.2 h1:oygO0locgZJe7PpYPXT5A29ZkwJaPqcva7BVeemZOZs= +github.com/AzureAD/microsoft-authentication-library-for-go v1.4.2/go.mod h1:wP83P5OoQ5p6ip3ScPr0BAq0BvuPAvacpEuSzyouqAI= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/toml v1.1.0/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= -github.com/BurntSushi/toml v1.4.0 h1:kuoIxZQy2WRRk1pttg9asf+WVv6tWQuBNVmK8+nqPr0= -github.com/BurntSushi/toml v1.4.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= +github.com/BurntSushi/toml v1.5.0 h1:W5quZX/G/csjUnuI8SUYlsHs9M38FC7znL0lIO+DvMg= +github.com/BurntSushi/toml v1.5.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= -github.com/G-Core/gcorelabscdn-go v1.0.28 h1:6ymVMV3HPTICO5BWJCEcZZzgY+Pc/+/TQMzeXMN77GQ= -github.com/G-Core/gcorelabscdn-go v1.0.28/go.mod h1:iSGXaTvZBzDHQW+rKFS918BgFVpONcyLEijwh8WsXpE= +github.com/G-Core/gcorelabscdn-go v1.0.29 h1:9jNCwzNZAgihTPe+nrsLD2c0GHjxvpuV3VEA74L5Kkk= +github.com/G-Core/gcorelabscdn-go v1.0.29/go.mod h1:iSGXaTvZBzDHQW+rKFS918BgFVpONcyLEijwh8WsXpE= github.com/HdrHistogram/hdrhistogram-go v1.1.0/go.mod h1:yDgFjdqOqDEKOvasDdhWNXYg9BVp4O+o5f6V/ehm6Oo= github.com/HdrHistogram/hdrhistogram-go v1.1.2/go.mod h1:yDgFjdqOqDEKOvasDdhWNXYg9BVp4O+o5f6V/ehm6Oo= github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= @@ -113,14 +113,17 @@ github.com/alibabacloud-go/darabonba-openapi/v2 v2.0.0/go.mod h1:5JHVmnHvGzR2wNd github.com/alibabacloud-go/darabonba-openapi/v2 v2.0.2/go.mod h1:5JHVmnHvGzR2wNdgaW1zDLQG8kOC4Uec8ubkMogW7OQ= github.com/alibabacloud-go/darabonba-openapi/v2 v2.0.5/go.mod h1:kUe8JqFmoVU7lfBauaDD5taFaW7mBI+xVsyHutYtabg= github.com/alibabacloud-go/darabonba-openapi/v2 v2.0.10/go.mod h1:26a14FGhZVELuz2cc2AolvW4RHmIO3/HRwsdHhaIPDE= -github.com/alibabacloud-go/darabonba-openapi/v2 v2.1.4 h1:IGSZHlOnWwBbLtX5xDplQvZOH0nkrV7Wmq+Fto7JK5w= -github.com/alibabacloud-go/darabonba-openapi/v2 v2.1.4/go.mod h1:Wxis0IBFusdbo44HO6KYYCJR1rRkoh47QQOYWvaheSU= +github.com/alibabacloud-go/darabonba-openapi/v2 v2.0.11/go.mod h1:wHxkgZT1ClZdcwEVP/pDgYK/9HucsnCfMipmJgCz4xY= +github.com/alibabacloud-go/darabonba-openapi/v2 v2.1.7 h1:ASXSBga98QrGMxbIThCD6jAti09gedLfvry6yJtsoBE= +github.com/alibabacloud-go/darabonba-openapi/v2 v2.1.7/go.mod h1:TBpgqm3XofZz2LCYjZhektGPU7ArEgascyzbm4SjFo4= github.com/alibabacloud-go/darabonba-signature-util v0.0.7 h1:UzCnKvsjPFzApvODDNEYqBHMFt1w98wC7FOo0InLyxg= github.com/alibabacloud-go/darabonba-signature-util v0.0.7/go.mod h1:oUzCYV2fcCH797xKdL6BDH8ADIHlzrtKVjeRtunBNTQ= github.com/alibabacloud-go/darabonba-string v1.0.2 h1:E714wms5ibdzCqGeYJ9JCFywE5nDyvIXIIQbZVFkkqo= github.com/alibabacloud-go/darabonba-string v1.0.2/go.mod h1:93cTfV3vuPhhEwGGpKKqhVW4jLe7tDpo3LUM0i0g6mA= github.com/alibabacloud-go/dcdn-20180115/v3 v3.5.0 h1:EQmKhYju6y38kJ1ZvZROeJG2Q1Wk6hlc8KQrVhvGyaw= github.com/alibabacloud-go/dcdn-20180115/v3 v3.5.0/go.mod h1:b9qzvr/2V1f0r1Z6xUmkLqEouKcPGy4LCC22yV+6HQo= +github.com/alibabacloud-go/ddoscoo-20200101/v4 v4.0.0 h1:z9dPOvBRxzpD+FQ2uu/p2Z92I+PY9MUZMauwC+8AC6M= +github.com/alibabacloud-go/ddoscoo-20200101/v4 v4.0.0/go.mod h1:Cdg3Fu4jFByamRzt3AkeiBssoVPRNDs+EPYMP2fIj78= github.com/alibabacloud-go/debug v0.0.0-20190504072949-9472017b5c68/go.mod h1:6pb/Qy8c+lqua8cFpEy7g39NRRqOWc3rOwAy8m5Y2BY= github.com/alibabacloud-go/debug v1.0.0/go.mod h1:8gfgZCCAC3+SCzjWtY053FrOcd4/qlH6IHTI4QyICOc= github.com/alibabacloud-go/debug v1.0.1 h1:MsW9SmUtbb1Fnt3ieC6NNZi6aEwrXfDksD4QA6GSbPg= @@ -128,10 +131,10 @@ github.com/alibabacloud-go/debug v1.0.1/go.mod h1:8gfgZCCAC3+SCzjWtY053FrOcd4/ql github.com/alibabacloud-go/endpoint-util v1.1.0/go.mod h1:O5FuCALmCKs2Ff7JFJMudHs0I5EBgecXXxZRyswlEjE= github.com/alibabacloud-go/endpoint-util v1.1.1 h1:ZkBv2/jnghxtU0p+upSU0GGzW1VL9GQdZO3mcSUTUy8= github.com/alibabacloud-go/endpoint-util v1.1.1/go.mod h1:O5FuCALmCKs2Ff7JFJMudHs0I5EBgecXXxZRyswlEjE= -github.com/alibabacloud-go/esa-20240910/v2 v2.23.0 h1:Z/AALmxhOfzN+35tNCvm62/pET4IlxhDQn4nsdLqNzk= -github.com/alibabacloud-go/esa-20240910/v2 v2.23.0/go.mod h1:P1w/+i7dE2xSXVHJznEOVImlLtqqrzUJQQk2AsyBJ6o= -github.com/alibabacloud-go/fc-20230330/v4 v4.1.7 h1:rQvPfzPaouL/WGNgMDMCplA4wDscmVFff7aLCUkjv4g= -github.com/alibabacloud-go/fc-20230330/v4 v4.1.7/go.mod h1:ssEfKO6MskPtq7QaQnyiOHGWLXOZcl7a8YIf8u56DGc= +github.com/alibabacloud-go/esa-20240910/v2 v2.31.1 h1:LACf71RxZjaystAfcWXa3EMtueVKNGxsCR3L+UihKtU= +github.com/alibabacloud-go/esa-20240910/v2 v2.31.1/go.mod h1:qa4hC7W/BQOc9liuJckLnBLxILEzYjg2xhAZ+UVeUUQ= +github.com/alibabacloud-go/fc-20230330/v4 v4.3.4 h1:DMUkeW24CWuvChy9uOD1DzMh3ToVARCB6m3xxWBslic= +github.com/alibabacloud-go/fc-20230330/v4 v4.3.4/go.mod h1:vEJimQ6E/e+m2z0/oXdeQWlFw/Pi/Ar6NKcMrSvcILE= github.com/alibabacloud-go/fc-open-20210406/v2 v2.0.12 h1:A3D8Mp6qf8DfR6Dt5MpS8aDVaWfS4N85T5CvGUvgrjM= github.com/alibabacloud-go/fc-open-20210406/v2 v2.0.12/go.mod h1:F5c0E5UB3k8v6neTtw3FBcJ1YCNFzVoL1JPRHTe33u4= github.com/alibabacloud-go/live-20161101 v1.1.1 h1:rUGfA8RHmCMtQ5M3yMSyRde+yRXWqVecmiXBU3XrGJ8= @@ -157,9 +160,9 @@ github.com/alibabacloud-go/tea v1.1.19/go.mod h1:nXxjm6CIFkBhwW4FQkNrolwbfon8Svy github.com/alibabacloud-go/tea v1.1.20/go.mod h1:nXxjm6CIFkBhwW4FQkNrolwbfon8Svy6cujmKFUq98A= github.com/alibabacloud-go/tea v1.2.1/go.mod h1:qbzof29bM/IFhLMtJPrgTGK3eauV5J2wSyEUo4OEmnA= github.com/alibabacloud-go/tea v1.2.2/go.mod h1:CF3vOzEMAG+bR4WOql8gc2G9H3EkH3ZLAQdpmpXMgwk= -github.com/alibabacloud-go/tea v1.3.2/go.mod h1:A560v/JTQ1n5zklt2BEpurJzZTI8TUT+Psg2drWlxRg= -github.com/alibabacloud-go/tea v1.3.4 h1:QGTns2930y+ANmoNcUS74TgYpsoqusSrLIyYDOvIFFI= -github.com/alibabacloud-go/tea v1.3.4/go.mod h1:A560v/JTQ1n5zklt2BEpurJzZTI8TUT+Psg2drWlxRg= +github.com/alibabacloud-go/tea v1.3.8/go.mod h1:A560v/JTQ1n5zklt2BEpurJzZTI8TUT+Psg2drWlxRg= +github.com/alibabacloud-go/tea v1.3.9 h1:bjgt1bvdY780vz/17iWNNtbXl4A77HWntWMeaUF3So0= +github.com/alibabacloud-go/tea v1.3.9/go.mod h1:A560v/JTQ1n5zklt2BEpurJzZTI8TUT+Psg2drWlxRg= github.com/alibabacloud-go/tea-fileform v1.1.1 h1:1YG6erAP3joQ0XdCXYIotuD7zyOM6qCR49xkp5FZDeU= github.com/alibabacloud-go/tea-fileform v1.1.1/go.mod h1:ZeCV91o4ISmxidd686f0ebdS5EDHWU+vW+TkjLhrsFE= github.com/alibabacloud-go/tea-oss-sdk v1.1.3 h1:EhAHI6edMeqgkZEqP7r4nc9iMWAUBKGxJHoBsOSKTtU= @@ -181,20 +184,20 @@ github.com/alibabacloud-go/tea-xml v1.1.1/go.mod h1:Rq08vgCcCAjHyRi/M7xlHKUykZCE github.com/alibabacloud-go/tea-xml v1.1.2/go.mod h1:Rq08vgCcCAjHyRi/M7xlHKUykZCEtyBy9+DPF6GgEu8= github.com/alibabacloud-go/tea-xml v1.1.3 h1:7LYnm+JbOq2B+T/B0fHC4Ies4/FofC4zHzYtqw7dgt0= github.com/alibabacloud-go/tea-xml v1.1.3/go.mod h1:Rq08vgCcCAjHyRi/M7xlHKUykZCEtyBy9+DPF6GgEu8= -github.com/alibabacloud-go/vod-20170321/v4 v4.7.0 h1:hpsnJBX5EeMrFujopMCjfq+p8XbNvPhFw6LOTV/WHd8= -github.com/alibabacloud-go/vod-20170321/v4 v4.7.0/go.mod h1:TkgLKMSLu0qZN8Qdcu8svfHREyI64kjFvrp/GhrD4VQ= -github.com/alibabacloud-go/waf-openapi-20211001/v5 v5.0.5 h1:ldAm1nvsCq66igjtcZyGhAoLClr+2eZ/pMIBUdKCOMM= -github.com/alibabacloud-go/waf-openapi-20211001/v5 v5.0.5/go.mod h1:DohGoS8BnMxHXghHebtjPP7+GMdxPsRN19T3nn2HcCU= -github.com/aliyun/alibaba-cloud-sdk-go v1.63.83 h1:YBkf7H5CSgrlb3C1aWcpDt7Vk8UEGFPeD2OOirtt6IM= -github.com/aliyun/alibaba-cloud-sdk-go v1.63.83/go.mod h1:SOSDHfe1kX91v3W5QiBsWSLqeLxImobbMX1mxrFHsVQ= +github.com/alibabacloud-go/vod-20170321/v4 v4.8.3 h1:IXDfINF3Wc88SKIijYgqy9HF3NiA68F97wgVeiRRwkc= +github.com/alibabacloud-go/vod-20170321/v4 v4.8.3/go.mod h1:5ocQ6hIc9tpGixD2iy099aOGwIgpzjT2le4Krd4aLn8= +github.com/alibabacloud-go/waf-openapi-20211001/v5 v5.1.1 h1:7gHYtb2swx96tG7rflKoiFOdjKZ/W3N7azS6LT1TVFI= +github.com/alibabacloud-go/waf-openapi-20211001/v5 v5.1.1/go.mod h1:DohGoS8BnMxHXghHebtjPP7+GMdxPsRN19T3nn2HcCU= +github.com/aliyun/alibaba-cloud-sdk-go v1.63.100 h1:yUkCbrSM1cWtgBfRVKMQtdt22KhDvKY7g4V+92eG9wA= +github.com/aliyun/alibaba-cloud-sdk-go v1.63.100/go.mod h1:SOSDHfe1kX91v3W5QiBsWSLqeLxImobbMX1mxrFHsVQ= github.com/aliyun/aliyun-oss-go-sdk v3.0.2+incompatible h1:8psS8a+wKfiLt1iVDX79F7Y6wUM49Lcha2FMXt4UM8g= github.com/aliyun/aliyun-oss-go-sdk v3.0.2+incompatible/go.mod h1:T/Aws4fEfogEE9v+HPhhw+CntffsBHJ8nXQCwKr0/g8= github.com/aliyun/credentials-go v1.1.2/go.mod h1:ozcZaMR5kLM7pwtCMEpVmQ242suV6qTJya2bDq4X1Tw= github.com/aliyun/credentials-go v1.3.1/go.mod h1:8jKYhQuDawt8x2+fusqa1Y6mPxemTsBEN04dgcAcYz0= github.com/aliyun/credentials-go v1.3.6/go.mod h1:1LxUuX7L5YrZUWzBrRyk0SwSdH4OmPrib8NVePL3fxM= github.com/aliyun/credentials-go v1.3.10/go.mod h1:Jm6d+xIgwJVLVWT561vy67ZRP4lPTQxMbEYRuT2Ti1U= -github.com/aliyun/credentials-go v1.4.3 h1:N3iHyvHRMyOwY1+0qBLSf3hb5JFiOujVSVuEpgeGttY= -github.com/aliyun/credentials-go v1.4.3/go.mod h1:Jm6d+xIgwJVLVWT561vy67ZRP4lPTQxMbEYRuT2Ti1U= +github.com/aliyun/credentials-go v1.4.5 h1:O76WYKgdy1oQYYiJkERjlA2dxGuvLRrzuO2ScrtGWSk= +github.com/aliyun/credentials-go v1.4.5/go.mod h1:Jm6d+xIgwJVLVWT561vy67ZRP4lPTQxMbEYRuT2Ti1U= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= @@ -210,40 +213,40 @@ github.com/aws/aws-sdk-go v1.40.45/go.mod h1:585smgzpB/KqRA+K3y/NL/oYRqQvpNJYvLm github.com/aws/aws-sdk-go-v2 v1.9.1/go.mod h1:cK/D0BBs0b/oWPIcX/Z/obahJK1TT7IPVjy53i/mX/4= github.com/aws/aws-sdk-go-v2 v1.36.3 h1:mJoei2CxPutQVxaATCzDUjcZEjVRdpsiiXi2o38yqWM= github.com/aws/aws-sdk-go-v2 v1.36.3/go.mod h1:LLXuLpgzEbD766Z5ECcRmi8AzSwfZItDtmABVkRLGzg= -github.com/aws/aws-sdk-go-v2/config v1.29.5 h1:4lS2IB+wwkj5J43Tq/AwvnscBerBJtQQ6YS7puzCI1k= -github.com/aws/aws-sdk-go-v2/config v1.29.5/go.mod h1:SNzldMlDVbN6nWxM7XsUiNXPSa1LWlqiXtvh/1PrJGg= -github.com/aws/aws-sdk-go-v2/credentials v1.17.58 h1:/d7FUpAPU8Lf2KUdjniQvfNdlMID0Sd9pS23FJ3SS9Y= -github.com/aws/aws-sdk-go-v2/credentials v1.17.58/go.mod h1:aVYW33Ow10CyMQGFgC0ptMRIqJWvJ4nxZb0sUiuQT/A= -github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.28 h1:KwsodFKVQTlI5EyhRSugALzsV6mG/SGrdjlMXSZSdso= -github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.28/go.mod h1:EY3APf9MzygVhKuPXAc5H+MkGb8k/DOSQjWS0LgkKqI= +github.com/aws/aws-sdk-go-v2/config v1.29.9 h1:Kg+fAYNaJeGXp1vmjtidss8O2uXIsXwaRqsQJKXVr+0= +github.com/aws/aws-sdk-go-v2/config v1.29.9/go.mod h1:oU3jj2O53kgOU4TXq/yipt6ryiooYjlkqqVaZk7gY/U= +github.com/aws/aws-sdk-go-v2/credentials v1.17.62 h1:fvtQY3zFzYJ9CfixuAQ96IxDrBajbBWGqjNTCa79ocU= +github.com/aws/aws-sdk-go-v2/credentials v1.17.62/go.mod h1:ElETBxIQqcxej++Cs8GyPBbgMys5DgQPTwo7cUPDKt8= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.30 h1:x793wxmUWVDhshP8WW2mlnXuFrO4cOd3HLBroh1paFw= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.30/go.mod h1:Jpne2tDnYiFascUEs2AWHJL9Yp7A5ZVy3TNyxaAjD6M= github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.34 h1:ZK5jHhnrioRkUNOc+hOgQKlUL5JeC3S6JgLxtQ+Rm0Q= github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.34/go.mod h1:p4VfIceZokChbA9FzMbRGz5OV+lekcVtHlPKEO0gSZY= github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.34 h1:SZwFm17ZUNNg5Np0ioo/gq8Mn6u9w19Mri8DnJ15Jf0= github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.34/go.mod h1:dFZsC0BLo346mvKQLWmoJxT+Sjp+qcVR1tRVHQGOH9Q= -github.com/aws/aws-sdk-go-v2/internal/ini v1.8.2 h1:Pg9URiobXy85kgFev3og2CuOZ8JZUBENF+dcgWBaYNk= -github.com/aws/aws-sdk-go-v2/internal/ini v1.8.2/go.mod h1:FbtygfRFze9usAadmnGJNc8KsP346kEe+y2/oyhGAGc= -github.com/aws/aws-sdk-go-v2/service/acm v1.31.1 h1:FB1PgU6vlXbqehxZiHuYQRWo5Ou6sQrFJcUaRe27lRo= -github.com/aws/aws-sdk-go-v2/service/acm v1.31.1/go.mod h1:3sKYAgRbuBa2QMYGh/WEclwnmfx+QoPhhX25PdSQSQM= -github.com/aws/aws-sdk-go-v2/service/cloudfront v1.45.2 h1:S3JpsBLyn/jqSJ6GgsbDQHubmop6fshQk/iOaOeotsc= -github.com/aws/aws-sdk-go-v2/service/cloudfront v1.45.2/go.mod h1:FIBJ48TS+qJb+Ne4qJ+0NeIhtPTVXItXooTeNeVI4Po= +github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3 h1:bIqFDwgGXXN1Kpp99pDOdKMTTb5d2KyU5X/BZxjOkRo= +github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3/go.mod h1:H5O/EsxDWyU+LP/V8i5sm8cxoZgc2fdNR9bxlOFrQTo= +github.com/aws/aws-sdk-go-v2/service/acm v1.31.3 h1:GwlU39usxM7E1LIhZchk93PtTQm2j3jb63of/YkBd+o= +github.com/aws/aws-sdk-go-v2/service/acm v1.31.3/go.mod h1:3sKYAgRbuBa2QMYGh/WEclwnmfx+QoPhhX25PdSQSQM= +github.com/aws/aws-sdk-go-v2/service/cloudfront v1.45.3 h1:xQnjN34F4I3a/I3Xj0g9vmD5hAqC7u5y3SC3eC6T1E8= +github.com/aws/aws-sdk-go-v2/service/cloudfront v1.45.3/go.mod h1:FIBJ48TS+qJb+Ne4qJ+0NeIhtPTVXItXooTeNeVI4Po= github.com/aws/aws-sdk-go-v2/service/cloudwatch v1.8.1/go.mod h1:CM+19rL1+4dFWnOQKwDc7H1KwXTz+h61oUSHyhV0b3o= -github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.2 h1:D4oz8/CzT9bAEYtVhSBmFj2dNOtaHOtMKc2vHBwYizA= -github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.2/go.mod h1:Za3IHqTQ+yNcRHxu1OFucBh0ACZT4j4VQFF0BqpZcLY= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.13 h1:SYVGSFQHlchIcy6e7x12bsrxClCXSP5et8cqVhL8cuw= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.13/go.mod h1:kizuDaLX37bG5WZaoxGPQR/LNFXpxp0vsUnqfkWXfNE= -github.com/aws/aws-sdk-go-v2/service/route53 v1.48.1 h1:njgAP7Rtt4DGdTGFPhJ4gaZXCD1CDj/SZDa5W4ZgSTs= -github.com/aws/aws-sdk-go-v2/service/route53 v1.48.1/go.mod h1:TN4PcCL0lvqmYcv+AV8iZFC4Sd0FM06QDaoBXrFEftU= -github.com/aws/aws-sdk-go-v2/service/sso v1.24.15 h1:/eE3DogBjYlvlbhd2ssWyeuovWunHLxfgw3s/OJa4GQ= -github.com/aws/aws-sdk-go-v2/service/sso v1.24.15/go.mod h1:2PCJYpi7EKeA5SkStAmZlF6fi0uUABuhtF8ILHjGc3Y= -github.com/aws/aws-sdk-go-v2/service/ssooidc v1.28.14 h1:M/zwXiL2iXUrHputuXgmO94TVNmcenPHxgLXLutodKE= -github.com/aws/aws-sdk-go-v2/service/ssooidc v1.28.14/go.mod h1:RVwIw3y/IqxC2YEXSIkAzRDdEU1iRabDPaYjpGCbCGQ= -github.com/aws/aws-sdk-go-v2/service/sts v1.33.14 h1:TzeR06UCMUq+KA3bDkujxK1GVGy+G8qQN/QVYzGLkQE= -github.com/aws/aws-sdk-go-v2/service/sts v1.33.14/go.mod h1:dspXf/oYWGWo6DEvj98wpaTeqt5+DMidZD0A9BYTizc= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.3 h1:eAh2A4b5IzM/lum78bZ590jy36+d/aFLgKF/4Vd1xPE= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.3/go.mod h1:0yKJC/kb8sAnmlYa6Zs3QVYqaC8ug2AbnNChv5Ox3uA= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.15 h1:dM9/92u2F1JbDaGooxTq18wmmFzbJRfXfVfy96/1CXM= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.15/go.mod h1:SwFBy2vjtA0vZbjjaFtfN045boopadnoVPhu4Fv66vY= +github.com/aws/aws-sdk-go-v2/service/route53 v1.50.0 h1:/nkJHXtJXJeelXHqG0898+fWKgvfaXBhGzbCsSmn9j8= +github.com/aws/aws-sdk-go-v2/service/route53 v1.50.0/go.mod h1:kGYOjvTa0Vw0qxrqrOLut1vMnui6qLxqv/SX3vYeM8Y= +github.com/aws/aws-sdk-go-v2/service/sso v1.25.1 h1:8JdC7Gr9NROg1Rusk25IcZeTO59zLxsKgE0gkh5O6h0= +github.com/aws/aws-sdk-go-v2/service/sso v1.25.1/go.mod h1:qs4a9T5EMLl/Cajiw2TcbNt2UNo/Hqlyp+GiuG4CFDI= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.29.1 h1:KwuLovgQPcdjNMfFt9OhUd9a2OwcOKhxfvF4glTzLuA= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.29.1/go.mod h1:MlYRNmYu/fGPoxBQVvBYr9nyr948aY/WLUvwBMBJubs= +github.com/aws/aws-sdk-go-v2/service/sts v1.33.17 h1:PZV5W8yk4OtH1JAuhV2PXwwO9v5G5Aoj+eMCn4T+1Kc= +github.com/aws/aws-sdk-go-v2/service/sts v1.33.17/go.mod h1:cQnB8CUnxbMU82JvlqjKR2HBOm3fe9pWorWBza6MBJ4= github.com/aws/smithy-go v1.8.0/go.mod h1:SObp3lf9smib00L/v3U2eAKG8FyQ7iLrJnQiAmR5n+E= github.com/aws/smithy-go v1.22.2 h1:6D9hW43xKFrRx/tXXfAlIZc4JI+yQe6snnWcQyxSyLQ= github.com/aws/smithy-go v1.22.2/go.mod h1:irrKGvNn1InZwb2d7fkIRNucdfwR8R+Ts3wxYa/cJHg= -github.com/baidubce/bce-sdk-go v0.9.221 h1:x5uTXND33m5TE3UBXYhlePuXcJi5rxNnBBt+bP7kPe0= -github.com/baidubce/bce-sdk-go v0.9.221/go.mod h1:zbYJMQwE4IZuyrJiFO8tO8NbtYiKTFTbwh4eIsqjVdg= +github.com/baidubce/bce-sdk-go v0.9.224 h1:z2L8alGw/y3IUHjrLRyrxrgCvMssYTjgCd7OQdb4gt0= +github.com/baidubce/bce-sdk-go v0.9.224/go.mod h1:zbYJMQwE4IZuyrJiFO8tO8NbtYiKTFTbwh4eIsqjVdg= github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= @@ -251,8 +254,10 @@ github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6r github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= github.com/blinkbean/dingtalk v1.1.3 h1:MbidFZYom7DTFHD/YIs+eaI7kRy52kmWE/sy0xjo6E4= github.com/blinkbean/dingtalk v1.1.3/go.mod h1:9BaLuGSBqY3vT5hstValh48DbsKO7vaHaJnG9pXwbto= -github.com/byteplus-sdk/byteplus-sdk-golang v1.0.42 h1:Dm9FDjQP2SlAjUH7WAV7DFYDBFQz2uBxX6JULs0Sxs0= -github.com/byteplus-sdk/byteplus-sdk-golang v1.0.42/go.mod h1:CIL/T2dxgbIA79os+wl0Fq0vCbADTZNIddV6PNYB6DY= +github.com/buger/goterm v1.0.4 h1:Z9YvGmOih81P0FbVtEYTFF6YsSgxSUKEhf/f9bTMXbY= +github.com/buger/goterm v1.0.4/go.mod h1:HiFWV3xnkolgrBV3mY8m0X0Pumt4zg4QhbdOzQtB8tE= +github.com/byteplus-sdk/byteplus-sdk-golang v1.0.44 h1:men5pKZNho+cw9/YU7TFerTspS3lKayS64zctl/D7Fk= +github.com/byteplus-sdk/byteplus-sdk-golang v1.0.44/go.mod h1:CIL/T2dxgbIA79os+wl0Fq0vCbADTZNIddV6PNYB6DY= github.com/casbin/casbin/v2 v2.37.0/go.mod h1:vByNa/Fchek0KZUgG5wEsl7iFsiviAYKRtgrQfcJqHg= github.com/cenkalti/backoff/v4 v4.1.1/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw= github.com/cenkalti/backoff/v4 v4.1.2/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw= @@ -275,8 +280,8 @@ github.com/clbanning/mxj/v2 v2.5.5/go.mod h1:hNiWqW14h+kc+MdF9C6/YoRfjEJoR3ou6tn github.com/clbanning/mxj/v2 v2.7.0 h1:WA/La7UGCanFe5NpHF0Q3DNtnCsVoxbPKuyBNHWRyME= github.com/clbanning/mxj/v2 v2.7.0/go.mod h1:hNiWqW14h+kc+MdF9C6/YoRfjEJoR3ou6tn/Qo+ve2s= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= -github.com/cloudflare/cloudflare-go v0.114.0 h1:ucoti4/7Exo0XQ+rzpn1H+IfVVe++zgiM+tyKtf0HUA= -github.com/cloudflare/cloudflare-go v0.114.0/go.mod h1:O7fYfFfA6wKqKFn2QIR9lhj7FDw6VQCGOY6hd2TBtd0= +github.com/cloudflare/cloudflare-go v0.115.0 h1:84/dxeeXweCc0PN5Cto44iTA8AkG1fyT11yPO5ZB7sM= +github.com/cloudflare/cloudflare-go v0.115.0/go.mod h1:Ds6urDwn/TF2uIU24mu7H91xkKP8gSAHxQ44DSZgVmU= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= @@ -294,6 +299,10 @@ github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/r github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc= github.com/disintegration/imaging v1.6.2 h1:w1LecBlG2Lnp8B3jk5zSuNqd7b4DXhcjwek1ei82L+c= github.com/disintegration/imaging v1.6.2/go.mod h1:44/5580QXChDfwIclfc/PCwrr44amcmDAg8hxG0Ewe4= +github.com/diskfs/go-diskfs v1.5.0 h1:0SANkrab4ifiZBytk380gIesYh5Gc+3i40l7qsrYP4s= +github.com/diskfs/go-diskfs v1.5.0/go.mod h1:bRFumZeGFCO8C2KNswrQeuj2m1WCVr4Ms5IjWMczMDk= +github.com/djherbis/times v1.6.0 h1:w2ctJ92J8fBvWPxugmXIv7Nz7Q3iDMKNx9v5ocVH20c= +github.com/djherbis/times v1.6.0/go.mod h1:gOHeRAz2h+VJNZ5Gmc/o7iD9k4wW7NMVqieYCY99oc0= github.com/domodwyer/mailyak/v3 v3.6.2 h1:x3tGMsyFhTCaxp6ycgR0FE/bu5QiNp+hetUuCOBXMn8= github.com/domodwyer/mailyak/v3 v3.6.2/go.mod h1:lOm/u9CyCVWHeaAmHIdF4RiKVxKUT/H5XX10lIKAL6c= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= @@ -332,16 +341,16 @@ github.com/fxamacker/cbor/v2 v2.7.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXE github.com/gabriel-vasile/mimetype v1.4.8 h1:FfZ3gj38NjllZIeJAmMhr+qKL8Wu+nOoI3GqacKw1NM= github.com/gabriel-vasile/mimetype v1.4.8/go.mod h1:ByKUIKGjh1ODkGM1asKUbQZOLGrPjydw3hYPU2YU9t8= github.com/gammazero/toposort v0.1.1/go.mod h1:H2cozTnNpMw0hg2VHAYsAxmkHXBYroNangj2NTBQDvw= -github.com/ganigeorgiev/fexpr v0.4.1 h1:hpUgbUEEWIZhSDBtf4M9aUNfQQ0BZkGRaMePy7Gcx5k= -github.com/ganigeorgiev/fexpr v0.4.1/go.mod h1:RyGiGqmeXhEQ6+mlGdnUleLHgtzzu/VGO2WtJkF5drE= +github.com/ganigeorgiev/fexpr v0.5.0 h1:XA9JxtTE/Xm+g/JFI6RfZEHSiQlk+1glLvRK1Lpv/Tk= +github.com/ganigeorgiev/fexpr v0.5.0/go.mod h1:RyGiGqmeXhEQ6+mlGdnUleLHgtzzu/VGO2WtJkF5drE= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= -github.com/go-acme/lego/v4 v4.22.2 h1:ck+HllWrV/rZGeYohsKQ5iKNnU/WAZxwOdiu6cxky+0= -github.com/go-acme/lego/v4 v4.22.2/go.mod h1:E2FndyI3Ekv0usNJt46mFb9LVpV/XBYT+4E3tz02Tzo= +github.com/go-acme/lego/v4 v4.23.1 h1:lZ5fGtGESA2L9FB8dNTvrQUq3/X4QOb8ExkKyY7LSV4= +github.com/go-acme/lego/v4 v4.23.1/go.mod h1:7UMVR7oQbIYw6V7mTgGwi4Er7B6Ww0c+c8feiBM0EgI= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= -github.com/go-jose/go-jose/v4 v4.0.4 h1:VsjPI33J0SB9vQM6PLmNjoHqMQNGPiZ0rHL7Ni7Q6/E= -github.com/go-jose/go-jose/v4 v4.0.4/go.mod h1:NKb5HO1EZccyMpiZNbdUw/14tiXNyUJh188dfnMCAfc= +github.com/go-jose/go-jose/v4 v4.0.5 h1:M6T8+mKZl/+fNNuFHvGIzDz7BTLQPIounk/b9dw3AaE= +github.com/go-jose/go-jose/v4 v4.0.5/go.mod h1:s3P1lRrkT8igV8D9OjyL4WRyHvjB6a4JSllnOrmmBOA= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/kit v0.12.0/go.mod h1:lHd+EkCZPIwYItmGDDRdhinkzX2A1sj+M9biaEaizzs= @@ -392,8 +401,8 @@ github.com/go-telegram-bot-api/telegram-bot-api v4.6.4+incompatible/go.mod h1:qf 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= +github.com/goccy/go-json v0.10.5 h1:Fq85nIqj+gXn/S5ahsiTlK3TmC85qgirsdTP/+DeaC4= +github.com/goccy/go-json v0.10.5/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/gofrs/flock v0.8.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU= github.com/gofrs/uuid v4.4.0+incompatible h1:3qXRTX8/NbyulANqlc0lchS1gqAVxRgsuW1YrTJupqA= @@ -403,8 +412,8 @@ github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/goji/httpauth v0.0.0-20160601135302-2da839ab0f4d/go.mod h1:nnjvkQ9ptGaCkuDUx6wNykzzlUixGxvkme+H/lnzb+A= github.com/golang-jwt/jwt/v4 v4.0.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg= -github.com/golang-jwt/jwt/v5 v5.2.1 h1:OuVbFODueb089Lh128TAcimifWaLhJwVflnrgM17wHk= -github.com/golang-jwt/jwt/v5 v5.2.1/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk= +github.com/golang-jwt/jwt/v5 v5.2.2 h1:Rl4B7itRWVtYIHFrSNd7vhTiz9UpLdi6gZhZ3wEeDy8= +github.com/golang-jwt/jwt/v5 v5.2.2/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk= github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -474,8 +483,8 @@ github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hf github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20250315033105-103756e64e1d h1:tx51Lf+wdE+aavqH8TcPJoCjTf4cE8hrMzROghCely0= -github.com/google/pprof v0.0.0-20250315033105-103756e64e1d/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144= +github.com/google/pprof v0.0.0-20250317173921-a4b03ec1a45e h1:ijClszYn+mADRFY17kjQEVQ1XRhq2/JR1M3sGqeJoxs= +github.com/google/pprof v0.0.0-20250317173921-a4b03ec1a45e/go.mod h1:boTsfXsheKC2y+lKOCMpSfarhxDeIzfZG1jqGcPl3cA= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= @@ -491,6 +500,8 @@ github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB7 github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ= github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4= github.com/gorilla/sessions v1.2.1/go.mod h1:dk2InVEVJ0sfLlnXv9EAgkf6ecYs/i80K/zI+bUmuGM= +github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg= +github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= github.com/hashicorp/consul/api v1.10.1/go.mod h1:XjsvQN+RJGWI2TWy1/kqaE16HrR2J/FWgkYjdZQsX9M= @@ -543,6 +554,8 @@ github.com/jcmturner/rpc/v2 v2.0.3/go.mod h1:VUJYCIDm3PVOEHw8sgt091/20OJjskO/YJk github.com/jdcloud-api/jdcloud-sdk-go v1.64.0 h1:xZc/ZRcrOhDx9Ra9htu6ui2gUUttmLsXIqH61LcvY4U= github.com/jdcloud-api/jdcloud-sdk-go v1.64.0/go.mod h1:UrKjuULIWLjHFlG6aSPunArE5QX57LftMmStAZJBEX8= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= +github.com/jinzhu/copier v0.3.4 h1:mfU6jI9PtCeUjkjQ322dlff9ELjGDu975C2p/nrubVI= +github.com/jinzhu/copier v0.3.4/go.mod h1:DfbEm0FYsaqBcKcFuvmOZb218JkPGtvSHsKg8S8hyyg= github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg= github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8= @@ -566,8 +579,8 @@ github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfV github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= github.com/jung-kurt/gofpdf v1.0.3-0.20190309125859-24315acbbda5/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes= -github.com/keybase/go-keychain v0.0.0-20231219164618-57a3676c3af6 h1:IsMZxCuZqKuao2vNdfD82fjjgPLfyHLpR41Z88viRWs= -github.com/keybase/go-keychain v0.0.0-20231219164618-57a3676c3af6/go.mod h1:3VeWNIJaW+O5xpRQbPp0Ybqu1vJd/pm7s2F473HRrkw= +github.com/keybase/go-keychain v0.0.1 h1:way+bWYa6lDppZoZcgMbYsvC7GxljxrskdNInRtuthU= +github.com/keybase/go-keychain v0.0.1/go.mod h1:PdEILRW3i9D8JcdM+FmY6RwkHGnhHxXwkPPMeUgOK1k= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/klauspost/compress v1.13.4/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg= @@ -599,6 +612,10 @@ github.com/libdns/dynv6 v1.0.0/go.mod h1:65PL/bAlyH0J+0WGlOJYnMpoIuXcg/FmW4dTBYW github.com/libdns/libdns v0.1.0/go.mod h1:yQCXzk1lEZmmCPa857bnk4TsOiqYasqpyOEeSObbb40= github.com/libdns/libdns v0.2.3 h1:ba30K4ObwMGB/QTmqUxf3H4/GmUrCAIkMWejeGl12v8= github.com/libdns/libdns v0.2.3/go.mod h1:4Bj9+5CQiNMVGf87wjX4CY3HQJypUHRuLvlsfsZqLWQ= +github.com/luthermonson/go-proxmox v0.2.2 h1:BZ7VEj302wxw2i/EwTcyEiBzQib8teocB2SSkLHyySY= +github.com/luthermonson/go-proxmox v0.2.2/go.mod h1:oyFgg2WwTEIF0rP6ppjiixOHa5ebK1p8OaRiFhvICBQ= +github.com/magefile/mage v1.14.0 h1:6QDX3g6z1YvJ4olPhT1wksUcSa/V0a1B+pJb73fBjyo= +github.com/magefile/mage v1.14.0/go.mod h1:z5UZb/iS3GoOSn0JgWuiw7dxlurVYTu+/jHXqQg881A= github.com/mailru/easyjson v0.9.0 h1:PrnmzHw7262yW8sTBwxi1PdJA3Iw/EKBa8psRf7d9a4= github.com/mailru/easyjson v0.9.0/go.mod h1:1+xMtQp2MRNVL/V1bOzuP3aP8VNwRW55fQUto+XFtTU= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= @@ -619,8 +636,8 @@ github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5 github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= github.com/miekg/dns v1.1.26/go.mod h1:bPDLeHnStXmXAq1m/Ch/hvfNHr14JKNPMBo3VZKjuso= github.com/miekg/dns v1.1.43/go.mod h1:+evo5L0630/F6ca/Z9+GAqzhjGyn8/c+TBaOyfEl0V4= -github.com/miekg/dns v1.1.62 h1:cN8OuEF1/x5Rq6Np+h1epln8OiyPWV+lROx9LxcGgIQ= -github.com/miekg/dns v1.1.62/go.mod h1:mvDlcItzm+br7MToIKqkglaGhlFMHJ9DTNNWONWXbNQ= +github.com/miekg/dns v1.1.64 h1:wuZgD9wwCE6XMT05UU/mlSko71eRSXEAm2EbjQXLKnQ= +github.com/miekg/dns v1.1.64/go.mod h1:Dzw9769uoKVaLuODMDZz9M6ynFU6Em65csPuoi8G0ck= github.com/minio/highwayhash v1.0.1/go.mod h1:BQskDq+xkJ12lmlUUi7U0M5Swg3EWR+dLTk+kldvVxY= github.com/minio/highwayhash v1.0.2/go.mod h1:BQskDq+xkJ12lmlUUi7U0M5Swg3EWR+dLTk+kldvVxY= github.com/mitchellh/cli v1.1.0/go.mod h1:xcISNoH86gajksDmfB23e/pu+B+GeFRMYmoHXxx3xhI= @@ -702,15 +719,15 @@ github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/profile v1.2.1/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA= -github.com/pkg/sftp v1.13.8 h1:Xt7eJ/xqXv7s0VuzFw7JXhZj6Oc1zI6l4GK8KP9sFB0= -github.com/pkg/sftp v1.13.8/go.mod h1:DmvEkvKE2lshEeuo2JMp06yqcx9HVnR7e3zqQl42F3U= +github.com/pkg/sftp v1.13.9 h1:4NGkvGudBL7GteO3m6qnaQ4pC0Kvf0onSVc9gR3EWBw= +github.com/pkg/sftp v1.13.9/go.mod h1:OBN7bVXdstkFFN/gdnHPUb5TE8eb8G1Rp9wCItqjkkA= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pocketbase/dbx v1.11.0 h1:LpZezioMfT3K4tLrqA55wWFw1EtH1pM4tzSVa7kgszU= github.com/pocketbase/dbx v1.11.0/go.mod h1:xXRCIAKTHMgUCyCKZm55pUOdvFziJjQfXaWKhu2vhMs= -github.com/pocketbase/pocketbase v0.26.1 h1:0WBqIRKKPCqp+xHPVLB4fevkoT9HVlR4BSuNwAt5oJ0= -github.com/pocketbase/pocketbase v0.26.1/go.mod h1:t5y5pfnhrEg//RuSzSg0a926OLZ0oQj66jYs3BzDJwA= +github.com/pocketbase/pocketbase v0.27.1 h1:KGCsS8idUVTC5QHxTj91qHDhIXOb5Yb50wwHhNvJRTQ= +github.com/pocketbase/pocketbase v0.27.1/go.mod h1:aTpwwloVJzeJ7MlwTRrbI/x62QNR2/kkCrovmyrXpqs= github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= github.com/posener/complete v1.2.3/go.mod h1:WZIdtGGp+qx0sLrYKtIRAruyNpv6hFCicSgv7Sy7s/s= github.com/povsister/scp v0.0.0-20240802064259-28781e87b246 h1:c4D8BPWLOxxdaxQLfLKQXH2YXY/E9yo3jrDSL54XrTw= @@ -737,14 +754,14 @@ github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1 github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= github.com/qiniu/dyn v1.3.0 h1:s+xPTeV0H8yikgM4ZMBc7Rrefam8UNI3asBlkaOQg5o= github.com/qiniu/dyn v1.3.0/go.mod h1:E8oERcm8TtwJiZvkQPbcAh0RL8jO1G0VXJMW3FAWdkk= -github.com/qiniu/go-sdk/v7 v7.25.2 h1:URwgZpxySdiwu2yQpHk93X4LXWHyFRp1x3Vmlk/YWvo= -github.com/qiniu/go-sdk/v7 v7.25.2/go.mod h1:dmKtJ2ahhPWFVi9o1D5GemmWoh/ctuB9peqTowyTO8o= +github.com/qiniu/go-sdk/v7 v7.25.3 h1:eYHh02q4i5MrlEn3qy823w7moieymFzb4dsP38Y43AI= +github.com/qiniu/go-sdk/v7 v7.25.3/go.mod h1:dmKtJ2ahhPWFVi9o1D5GemmWoh/ctuB9peqTowyTO8o= github.com/qiniu/x v1.10.5 h1:7V/CYWEmo9axJULvrJN6sMYh2FdY+esN5h8jwDkA4b0= github.com/qiniu/x v1.10.5/go.mod h1:03Ni9tj+N2h2aKnAz+6N0Xfl8FwMEDRC2PAlxekASDs= github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= -github.com/redis/go-redis/v9 v9.7.0 h1:HhLSs+B6O021gwzl+locl0zEDnyNkxMtf/Z3NNBMa9E= -github.com/redis/go-redis/v9 v9.7.0/go.mod h1:f6zhXITC7JUJIlPEiBOTXxJgPLdZcA93GewI7inzyWw= +github.com/redis/go-redis/v9 v9.7.3 h1:YpPyAayJV+XErNsatSElgRZZVCwXX9QzkKYNvO7x0wM= +github.com/redis/go-redis/v9 v9.7.3/go.mod h1:bGUrSggJ9X9GUmZpZNEOQKaANxSGgOEBRltRTZHSvrA= github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE= github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= @@ -766,6 +783,8 @@ github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= +github.com/sirupsen/logrus v1.9.4-0.20230606125235-dd1b4c2e81af h1:Sp5TG9f7K39yfB+If0vjp97vuT74F72r8hfRpP8jLU0= +github.com/sirupsen/logrus v1.9.4-0.20230606125235-dd1b4c2e81af/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/assertions v1.1.0/go.mod h1:tcbTF8ujkAEcZ8TElKY+i30BzYlVhC/LOxJk7iOWnoo= github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= @@ -801,32 +820,32 @@ github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOf github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/technoweenie/multipartstreamer v1.0.1 h1:XRztA5MXiR1TIRHxH2uNxXxaIkKQDeX7m2XsSOlQEnM= github.com/technoweenie/multipartstreamer v1.0.1/go.mod h1:jNVxdtShOxzAsukZwTSw6MDx5eUJoiEBsSvzDU9uzog= -github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cdn v1.0.1115 h1:HsrXyqKQB2mKfGq+ZkbylRCMrbtPCmmUBrwA8MhhEX0= -github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cdn v1.0.1115/go.mod h1:5cz1DtLlXK98U1Hh36oW4PjVOU+mbKg5wtCDmCc9Fcs= -github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/clb v1.0.1127 h1:PiLZflqaW0690YsqIM/hqaVYjZJ3+cCJp4NHfw7h/uw= -github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/clb v1.0.1127/go.mod h1:V1+julLUOH0jKoVH6o6xgM4STWowzAL57M4VanUEEag= -github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1084/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0= -github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1115/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0= -github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1117/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0= +github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cdn v1.0.1136 h1:H1pjtH5uZ4XZPj9qQ9tt9jzeWqZzrd8qYIw01Q60/08= +github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cdn v1.0.1136/go.mod h1:K6absuzpElv6mw2d7j8xkphOkwd23qvG0Rcmhl4rqlk= +github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/clb v1.0.1143 h1:7OL/ThUCqkntItSiqbY1g3s0Ua26Qr08G8fcSzyrAqA= +github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/clb v1.0.1143/go.mod h1:XO18PkKinF17cQOSlhbP7GOnj04N5L2iCaHn64yiMtE= +github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1120/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0= github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1124/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0= -github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1125/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0= -github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1126/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0= -github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1127 h1:1uG8zc0b9gLbyTr27T0CzGtcdrL86CGGJ6Flkq867f4= -github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1127/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0= -github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/dnspod v1.0.1084 h1:kwctN0WQYt8/iKP+iRCTCwdzEMIXsXklbRIib5rjeQ8= -github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/dnspod v1.0.1084/go.mod h1:qE67ApiBzeRvzeDsV+GxyIDbVIDemsKpHXllQATz/Vw= -github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/live v1.0.1117 h1:Yc/r5zUAyukVI3huIuwE7koowCjDjOWqeRpBILCvOSE= -github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/live v1.0.1117/go.mod h1:YxsorHl3sTRw+2GsUObMqcumDqAQ3zo9rLMtf3Cxj8U= -github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/scf v1.0.1115 h1:Qi7VWmJ0AQxEMlwKpbWfnsLA5QdNxekdcLJTBVdO85U= -github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/scf v1.0.1115/go.mod h1:P16nIMvmpSY+arTc2m2HyJmrYQP6CFnr48glz0+abyw= +github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1128/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0= +github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1136/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0= +github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1138/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0= +github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1143/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0= +github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1147 h1:6v559jM1v6A4KJinNZ28RqVZs+ipKMzCWtYWcWy+zZ4= +github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1147/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0= +github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/dnspod v1.0.1128 h1:mrJ5Fbkd7sZIJ5F6oRfh5zebPQaudPH9Y0+GUmFytYU= +github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/dnspod v1.0.1128/go.mod h1:zbsYIBT+VTX4z4ocjTAdLBIWyNYj3z0BRqd0iPdnjsk= +github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/live v1.0.1143 h1:fvK9kOsPquDTWrT2aXLWVnAMUokr4gFK7uYeY3JMB6U= +github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/live v1.0.1143/go.mod h1:SLYgasv8DdvRnesG+SLdqFdEBIJzietfVDytke8ASKQ= +github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/scf v1.0.1120 h1:z0t0lb5h1mZirXftO8MRg25COYZHx0ubQjSPhZT/LY0= +github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/scf v1.0.1120/go.mod h1:IFZL44Keyl+MHrhpFwUaQmJvMDwGr+t+cUfFAC+74lU= github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/ssl v1.0.1124 h1:LQKAlxFb0sYiE8ojK5h9+seuFzogoJtYnXmiRF+4F4Q= github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/ssl v1.0.1124/go.mod h1:tYbK0FbHVG+78od7eZpzczE8qk0JWKO/osTQWuiJ3Fo= -github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/teo v1.0.1126 h1:+CJQNXLdLP0GLaz2fnPECQsU+WdOmW3BQ54cNoQgMKA= -github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/teo v1.0.1126/go.mod h1:eY3GoWilNoCPOEw2Lp4o+h02nEfc+BoZnqK3TlK6F7I= -github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/vod v1.0.1115 h1:rO0LdbcNtT5VlL9sB/K3Ve848uLp1rgg3R8igT9xsFQ= -github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/vod v1.0.1115/go.mod h1:jJR8Y5sHuujSXZy0cpCgBk180TvPNsLw9hEoSH9w7iA= -github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/waf v1.0.1125 h1:IR9pJqHjHr7KyncRVxld9iltfnmy9sCC+0USZrs3rOw= -github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/waf v1.0.1125/go.mod h1:5+5QrF7x+AW1KPM7F+YRzD74L88RXHZ6BxDF07b8QkE= +github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/teo v1.0.1138 h1:SrQ+rlWLwnXU/6S8ULGhFaiV5faAeqL0ysdsqV6P1AA= +github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/teo v1.0.1138/go.mod h1:XvXgF+4yO4Ni6gYoqMszSkNNqFLkOxx2j5F7+u3lpKQ= +github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/vod v1.0.1136 h1:9GqM1URHNySj0f8TkUcKT6qSDiGep3IB1hWWu1ti6rY= +github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/vod v1.0.1136/go.mod h1:b5JZEbM4ROYUSVcgNkDHuHWdTJX5Qe4wC1asq2n0yes= +github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/waf v1.0.1147 h1:SxZsn9N4c1yx40kZOINIh9AnUKcgChUWbZoDiv6VvmQ= +github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/waf v1.0.1147/go.mod h1:T4sxG9+SJ038MBsam2upsEYRpQ82JpX+IkZ08+P9RlE= github.com/tjfoc/gmsm v1.3.2/go.mod h1:HaUcFuY0auTiaHB9MHFGCPx5IaLhTUd2atbCFBQXn9w= github.com/tjfoc/gmsm v1.4.1 h1:aMe1GlZb+0bLjn+cKTPEvvn9oUEBlJitaZiiBwsbgho= github.com/tjfoc/gmsm v1.4.1/go.mod h1:j4INPkHWMrhJb38G+J6W4Tw0AbuN8Thu3PbdVYhVcTE= @@ -835,16 +854,16 @@ github.com/uber/jaeger-client-go v2.30.0+incompatible h1:D6wyKGCecFaSRUpo8lCVbaO github.com/uber/jaeger-client-go v2.30.0+incompatible/go.mod h1:WVhlPFC8FDjOFMMWRy2pZqQJSXxYSwNYOkTr/Z6d3Kk= github.com/uber/jaeger-lib v2.4.1+incompatible h1:td4jdvLcExb4cBISKIpHuGoVXh+dVKhn2Um6rjCsSsg= github.com/uber/jaeger-lib v2.4.1+incompatible/go.mod h1:ComeNDZlWwrWnDv8aPp0Ba6+uUTzImX/AauajbLI56U= -github.com/ucloud/ucloud-sdk-go v0.22.31 h1:izZK+Re9ZkJAd1fHSVpFzgh8uKda4f5G6++iUw4n/mE= -github.com/ucloud/ucloud-sdk-go v0.22.31/go.mod h1:dyLmFHmUfgb4RZKYQP9IArlvQ2pxzFthfhwxRzOEPIw= +github.com/ucloud/ucloud-sdk-go v0.22.33 h1:YKY8VpFNttdnVNb0o3owGeZRoUtRJmoWPJYJPfcCf9A= +github.com/ucloud/ucloud-sdk-go v0.22.33/go.mod h1:dyLmFHmUfgb4RZKYQP9IArlvQ2pxzFthfhwxRzOEPIw= github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI= -github.com/volcengine/ve-tos-golang-sdk/v2 v2.7.9 h1:fEnScn2dXfvfNcFnvJnpf/cYdj8kLIe5QC5qORlFO2c= -github.com/volcengine/ve-tos-golang-sdk/v2 v2.7.9/go.mod h1:IrjK84IJJTuOZOTMv/P18Ydjy/x+ow7fF7q11jAxXLM= +github.com/volcengine/ve-tos-golang-sdk/v2 v2.7.11 h1:J4AweXxLqlSwb1Aam9npcb5optZmszDIrKWa/hs+e4U= +github.com/volcengine/ve-tos-golang-sdk/v2 v2.7.11/go.mod h1:IrjK84IJJTuOZOTMv/P18Ydjy/x+ow7fF7q11jAxXLM= github.com/volcengine/volc-sdk-golang v1.0.23/go.mod h1:AfG/PZRUkHJ9inETvbjNifTDgut25Wbkm2QoYBTbvyU= -github.com/volcengine/volc-sdk-golang v1.0.199 h1:zv9QOqTl/IsLwtfC37GlJtcz6vMAHi+pjq8ILWjLYUc= -github.com/volcengine/volc-sdk-golang v1.0.199/go.mod h1:stZX+EPgv1vF4nZwOlEe8iGcriUPRBKX8zA19gXycOQ= -github.com/volcengine/volcengine-go-sdk v1.0.187 h1:YpZjydoyHDA/ofnF6mYCelbOoo9pJsBEiQOOSJzGSOY= -github.com/volcengine/volcengine-go-sdk v1.0.187/go.mod h1:gfEDc1s7SYaGoY+WH2dRrS3qiuDJMkwqyfXWCa7+7oA= +github.com/volcengine/volc-sdk-golang v1.0.204 h1:Njid6coReHV2gWc3bsqWMQf+K8jveauzW8zEX08CTzI= +github.com/volcengine/volc-sdk-golang v1.0.204/go.mod h1:stZX+EPgv1vF4nZwOlEe8iGcriUPRBKX8zA19gXycOQ= +github.com/volcengine/volcengine-go-sdk v1.1.4 h1:xPT4KOy8VkXxhY7dbXzzvLvKQXUe4J6AtkQdNQU3wRY= +github.com/volcengine/volcengine-go-sdk v1.1.4/go.mod h1:gfEDc1s7SYaGoY+WH2dRrS3qiuDJMkwqyfXWCa7+7oA= github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM= github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg= github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI= @@ -912,8 +931,8 @@ golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOM golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8= golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM= golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk= -golang.org/x/crypto v0.36.0 h1:AnAEvhDddvBdpY+uR+MyHmuZzzNqXSe/GvuDeob5L34= -golang.org/x/crypto v0.36.0/go.mod h1:Y4J0ReaxCR1IMaabaSMugxJES1EpwhBHhv2bDHklZvc= +golang.org/x/crypto v0.37.0 h1:kJNSjF/Xp7kU0iB2Z+9viTPMW4EqqsrywMXLJOOsXSE= +golang.org/x/crypto v0.37.0/go.mod h1:vg+k43peMZ0pUMhYmVAWysMK35e6ioLh3wB8ZCAfbVc= golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -927,14 +946,14 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0 golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= -golang.org/x/exp v0.0.0-20250305212735-054e65f0b394 h1:nDVHiLt8aIbd/VzvPWN6kSOPE7+F/fNFDSXLVYkE/Iw= -golang.org/x/exp v0.0.0-20250305212735-054e65f0b394/go.mod h1:sIifuuw/Yco/y6yb6+bDNfyeQ/MdPUy/hKEMYQV17cM= +golang.org/x/exp v0.0.0-20250408133849-7e4ce0ab07d0 h1:R84qjqJb5nVJMxqWYb3np9L5ZsaDtB+a39EqjV0JSUM= +golang.org/x/exp v0.0.0-20250408133849-7e4ce0ab07d0/go.mod h1:S9Xr4PYopiDyqSyp5NjCrhFrqg6A5zA2E/iPHPhqnS8= golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= -golang.org/x/image v0.25.0 h1:Y6uW6rH1y5y/LK1J8BPWZtr6yZ7hrsy6hFrXjgsc2fQ= -golang.org/x/image v0.25.0/go.mod h1:tCAmOEGthTtkalusGp1g3xa2gke8J6c2N565dTyl9Rs= +golang.org/x/image v0.26.0 h1:4XjIFEZWQmCZi6Wv8BoxsDhRU3RVnLX04dToTDAEPlY= +golang.org/x/image v0.26.0/go.mod h1:lcxbMFAovzpnJxzXS3nyL83K27tmqtKzIJpctK8YO5c= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= @@ -1017,16 +1036,16 @@ golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE= -golang.org/x/net v0.37.0 h1:1zLorHbz+LYj7MQlSf1+2tPIIgibq2eL5xkrGk6f+2c= -golang.org/x/net v0.37.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8= +golang.org/x/net v0.39.0 h1:ZCu7HMWDxpXpaiKdhzIfaltL9Lp31x/3fCP11bc6/fY= +golang.org/x/net v0.39.0/go.mod h1:X7NRbYVEA+ewNkCNyJ513WmMdQ3BineSwVtN2zD/d+E= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.28.0 h1:CrgCKl8PPAVtLnU3c+EDw6x11699EWlsDeWNWKdIOkc= -golang.org/x/oauth2 v0.28.0/go.mod h1:onh5ek6nERTohokkhCD/y2cV4Do3fxFHFuAejCkRWT8= +golang.org/x/oauth2 v0.29.0 h1:WdYw2tdTK1S8olAzWHdgeqfy+Mtm9XNhv/xJsY65d98= +golang.org/x/oauth2 v0.29.0/go.mod h1:onh5ek6nERTohokkhCD/y2cV4Do3fxFHFuAejCkRWT8= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -1044,8 +1063,8 @@ golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= -golang.org/x/sync v0.12.0 h1:MHc5BpPuC30uJk597Ri8TV3CNZcTLu6B6z4lJy+g6Jw= -golang.org/x/sync v0.12.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= +golang.org/x/sync v0.13.0 h1:AauUjRAJ9OSnvULf/ARrrVywoJDy0YS2AwQ98I37610= +golang.org/x/sync v0.13.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -1098,6 +1117,7 @@ golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210331175145-43e1dd70ce54/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -1106,6 +1126,7 @@ golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210917161153-d61c044b1678/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220615213510-4f61da869c0c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -1122,8 +1143,8 @@ golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik= -golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= +golang.org/x/sys v0.32.0 h1:s77OFDvIQeibCmezSnk/q6iAfkdiQaJi4VzroCFrN20= +golang.org/x/sys v0.32.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= @@ -1139,8 +1160,8 @@ golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58= golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY= golang.org/x/term v0.21.0/go.mod h1:ooXLefLobQVslOqselCNF4SxFAaoS6KujMbsGzSDmX0= golang.org/x/term v0.27.0/go.mod h1:iMsnZpn0cago0GOrHO2+Y7u7JPn5AylBrcoWkElMTSM= -golang.org/x/term v0.30.0 h1:PQ39fJZ+mfadBm0y5WlL4vlM7Sx1Hgf13sMIY2+QS9Y= -golang.org/x/term v0.30.0/go.mod h1:NYYFdzHoI5wRh/h5tDMdMqCqPJZEuNqVR5xJLd/n67g= +golang.org/x/term v0.31.0 h1:erwDkOK1Msy6offm1mOgvspSkslFnIGsFnxOKoufg3o= +golang.org/x/term v0.31.0/go.mod h1:R4BeIy7D95HzImkxGkTW1UQTtP54tio2RyHz7PwK0aw= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -1159,15 +1180,15 @@ golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= -golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY= -golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4= +golang.org/x/text v0.24.0 h1:dd5Bzh4yt5KYA8f9CJHCP4FB4D51c2c6JvN37xJJkJ0= +golang.org/x/text v0.24.0/go.mod h1:L8rBsPeo2pSS+xqN0d5u2ikmjtmoJbDBT1b7nHvFCdU= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20200416051211-89c76fbcd5d1/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.9.0 h1:EsRrnYcQiGH+5FfbgvV4AP7qEZstoyrHB0DzarOQ4ZY= -golang.org/x/time v0.9.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= +golang.org/x/time v0.11.0 h1:/bpjEDfN9tkoN/ryeYHnv5hcMlc8ncjMcM4XBk5NWV0= +golang.org/x/time v0.11.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg= golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -1222,8 +1243,8 @@ golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= -golang.org/x/tools v0.31.0 h1:0EedkvKDbh+qistFTd0Bcwe/YLh4vHwWEkiI0toFIBU= -golang.org/x/tools v0.31.0/go.mod h1:naFTU+Cev749tSJRXJlna0T3WxKvb1kWEx15xA4SdmQ= +golang.org/x/tools v0.32.0 h1:Q7N1vhpkQv7ybVzLFtTjvQya2ewbwNDZzUgfXGqtMWU= +golang.org/x/tools v0.32.0/go.mod h1:ZxrU41P/wAbZD8EDa6dDCa6XfpkhJ7HFMjHJXfBDu8s= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -1375,27 +1396,27 @@ k8s.io/kube-openapi v0.0.0-20241212222426-2c72e554b1e7 h1:hcha5B1kVACrLujCKLbr8X k8s.io/kube-openapi v0.0.0-20241212222426-2c72e554b1e7/go.mod h1:GewRfANuJ70iYzvn+i4lezLDAFzvjxZYK1gn1lWcfas= k8s.io/utils v0.0.0-20241210054802-24370beab758 h1:sdbE21q2nlQtFh65saZY+rRM6x6aJJI8IUa1AmH/qa0= k8s.io/utils v0.0.0-20241210054802-24370beab758/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= -modernc.org/cc/v4 v4.24.4 h1:TFkx1s6dCkQpd6dKurBNmpo+G8Zl4Sq/ztJ+2+DEsh0= -modernc.org/cc/v4 v4.24.4/go.mod h1:uVtb5OGqUKpoLWhqwNQo/8LwvoiEBLvZXIQ/SmO6mL0= -modernc.org/ccgo/v4 v4.23.16 h1:Z2N+kk38b7SfySC1ZkpGLN2vthNJP1+ZzGZIlH7uBxo= -modernc.org/ccgo/v4 v4.23.16/go.mod h1:nNma8goMTY7aQZQNTyN9AIoJfxav4nvTnvKThAeMDdo= +modernc.org/cc/v4 v4.25.2 h1:T2oH7sZdGvTaie0BRNFbIYsabzCxUQg8nLqCdQ2i0ic= +modernc.org/cc/v4 v4.25.2/go.mod h1:uVtb5OGqUKpoLWhqwNQo/8LwvoiEBLvZXIQ/SmO6mL0= +modernc.org/ccgo/v4 v4.25.1 h1:TFSzPrAGmDsdnhT9X2UrcPMI3N/mJ9/X9ykKXwLhDsU= +modernc.org/ccgo/v4 v4.25.1/go.mod h1:njjuAYiPflywOOrm3B7kCB444ONP5pAVr8PIEoE0uDw= modernc.org/fileutil v1.0.0/go.mod h1:JHsWpkrk/CnVV1H/eGlFf85BEpfkrp56ro8nojIq9Q8= modernc.org/fileutil v1.3.0 h1:gQ5SIzK3H9kdfai/5x41oQiKValumqNTDXMvKo62HvE= modernc.org/fileutil v1.3.0/go.mod h1:XatxS8fZi3pS8/hKG2GH/ArUogfxjpEKs3Ku3aK4JyQ= -modernc.org/gc/v2 v2.6.3 h1:aJVhcqAte49LF+mGveZ5KPlsp4tdGdAOT4sipJXADjw= -modernc.org/gc/v2 v2.6.3/go.mod h1:YgIahr1ypgfe7chRuJi2gD7DBQiKSLMPgBQe9oIiito= -modernc.org/libc v1.61.13 h1:3LRd6ZO1ezsFiX1y+bHd1ipyEHIJKvuprv0sLTBwLW8= -modernc.org/libc v1.61.13/go.mod h1:8F/uJWL/3nNil0Lgt1Dpz+GgkApWh04N3el3hxJcA6E= +modernc.org/gc/v2 v2.6.5 h1:nyqdV8q46KvTpZlsw66kWqwXRHdjIlJOhG6kxiV/9xI= +modernc.org/gc/v2 v2.6.5/go.mod h1:YgIahr1ypgfe7chRuJi2gD7DBQiKSLMPgBQe9oIiito= +modernc.org/libc v1.62.1 h1:s0+fv5E3FymN8eJVmnk0llBe6rOxCu/DEU+XygRbS8s= +modernc.org/libc v1.62.1/go.mod h1:iXhATfJQLjG3NWy56a6WVU73lWOcdYVxsvwCgoPljuo= modernc.org/mathutil v1.7.1 h1:GCZVGXdaN8gTqB1Mf/usp1Y/hSqgI2vAGGP4jZMCxOU= modernc.org/mathutil v1.7.1/go.mod h1:4p5IwJITfppl0G4sUEDtCr4DthTaT47/N3aT6MhfgJg= -modernc.org/memory v1.8.2 h1:cL9L4bcoAObu4NkxOlKWBWtNHIsnnACGF/TbqQ6sbcI= -modernc.org/memory v1.8.2/go.mod h1:ZbjSvMO5NQ1A2i3bWeDiVMxIorXwdClKE/0SZ+BMotU= +modernc.org/memory v1.9.1 h1:V/Z1solwAVmMW1yttq3nDdZPJqV1rM05Ccq6KMSZ34g= +modernc.org/memory v1.9.1/go.mod h1:/JP4VbVC+K5sU2wZi9bHoq2MAkCnrt2r98UGeSK7Mjw= modernc.org/opt v0.1.4 h1:2kNGMRiUjrp4LcaPuLY2PzUfqM/w9N23quVwhKt5Qm8= modernc.org/opt v0.1.4/go.mod h1:03fq9lsNfvkYSfxrfUhZCWPk1lm4cq4N+Bh//bEtgns= modernc.org/sortutil v1.2.1 h1:+xyoGf15mM3NMlPDnFqrteY07klSFxLElE2PVuWIJ7w= modernc.org/sortutil v1.2.1/go.mod h1:7ZI3a3REbai7gzCLcotuw9AC4VZVpYMjDzETGsSMqJE= -modernc.org/sqlite v1.36.1 h1:bDa8BJUH4lg6EGkLbahKe/8QqoF8p9gArSc6fTqYhyQ= -modernc.org/sqlite v1.36.1/go.mod h1:7MPwH7Z6bREicF9ZVUR78P1IKuxfZ8mRIDHD0iD+8TU= +modernc.org/sqlite v1.37.0 h1:s1TMe7T3Q3ovQiK2Ouz4Jwh7dw4ZDqbebSDTlSJdfjI= +modernc.org/sqlite v1.37.0/go.mod h1:5YiWv+YviqGMuGw4V+PNplcyaJ5v+vQd7TQOgkACoJM= modernc.org/strutil v1.2.1 h1:UneZBkQA+DX2Rp35KcM69cSsNES9ly8mQWD71HKlOA0= modernc.org/strutil v1.2.1/go.mod h1:EHkiggD70koQxjVdSBM3JKM7k6L0FbGE5eymy9i3B9A= modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y= diff --git a/internal/applicant/acme_ca.go b/internal/applicant/acme_ca.go index 03d9dd65..67b7693e 100644 --- a/internal/applicant/acme_ca.go +++ b/internal/applicant/acme_ca.go @@ -1,14 +1,14 @@ -package applicant +package applicant import "github.com/usual2970/certimate/internal/domain" const ( - sslProviderLetsEncrypt = string(domain.ApplyCAProviderTypeLetsEncrypt) - sslProviderLetsEncryptStaging = string(domain.ApplyCAProviderTypeLetsEncryptStaging) - sslProviderBuypass = string(domain.ApplyCAProviderTypeBuypass) - sslProviderGoogleTrustServices = string(domain.ApplyCAProviderTypeGoogleTrustServices) - sslProviderSSLCom = string(domain.ApplyCAProviderTypeSSLCom) - sslProviderZeroSSL = string(domain.ApplyCAProviderTypeZeroSSL) + sslProviderLetsEncrypt = string(domain.CAProviderTypeLetsEncrypt) + sslProviderLetsEncryptStaging = string(domain.CAProviderTypeLetsEncryptStaging) + sslProviderBuypass = string(domain.CAProviderTypeBuypass) + sslProviderGoogleTrustServices = string(domain.CAProviderTypeGoogleTrustServices) + sslProviderSSLCom = string(domain.CAProviderTypeSSLCom) + sslProviderZeroSSL = string(domain.CAProviderTypeZeroSSL) sslProviderDefault = sslProviderLetsEncrypt ) @@ -25,6 +25,6 @@ var sslProviderUrls = map[string]string{ } type acmeSSLProviderConfig struct { - Config map[domain.ApplyCAProviderType]map[string]any `json:"config"` - Provider string `json:"provider"` + Config map[domain.CAProviderType]map[string]any `json:"config"` + Provider string `json:"provider"` } diff --git a/internal/applicant/acme_user.go b/internal/applicant/acme_user.go index 430db5a3..29ac80cd 100644 --- a/internal/applicant/acme_user.go +++ b/internal/applicant/acme_user.go @@ -1,4 +1,4 @@ -package applicant +package applicant import ( "context" @@ -13,8 +13,8 @@ import ( "golang.org/x/sync/singleflight" "github.com/usual2970/certimate/internal/domain" - "github.com/usual2970/certimate/internal/pkg/utils/certutil" - "github.com/usual2970/certimate/internal/pkg/utils/maputil" + certutil "github.com/usual2970/certimate/internal/pkg/utils/cert" + maputil "github.com/usual2970/certimate/internal/pkg/utils/map" "github.com/usual2970/certimate/internal/repository" ) @@ -146,7 +146,7 @@ func registerAcmeUser(client *lego.Client, user *acmeUser, userRegisterOptions m } default: - err = fmt.Errorf("unsupported ca provider: %s", user.CA) + err = fmt.Errorf("unsupported ca provider '%s'", user.CA) } if err != nil { return nil, err diff --git a/internal/applicant/applicant.go b/internal/applicant/applicant.go index 93ab30ae..e9ed4cb1 100644 --- a/internal/applicant/applicant.go +++ b/internal/applicant/applicant.go @@ -4,10 +4,12 @@ import ( "context" "encoding/json" "fmt" + "log/slog" "os" "strconv" "strings" "sync" + "time" "github.com/go-acme/lego/v4/certcrypto" "github.com/go-acme/lego/v4/certificate" @@ -18,11 +20,11 @@ import ( "golang.org/x/time/rate" "github.com/usual2970/certimate/internal/domain" - "github.com/usual2970/certimate/internal/pkg/utils/sliceutil" + sliceutil "github.com/usual2970/certimate/internal/pkg/utils/slice" "github.com/usual2970/certimate/internal/repository" ) -type ApplyCertResult struct { +type ApplyResult struct { CertificateFullChain string IssuerCertificate string PrivateKey string @@ -33,44 +35,35 @@ type ApplyCertResult struct { } type Applicant interface { - Apply() (*ApplyCertResult, error) + Apply(ctx context.Context) (*ApplyResult, error) } -type applicantOptions struct { - Domains []string - ContactEmail string - Provider domain.ApplyDNSProviderType - ProviderAccessConfig map[string]any - ProviderExtendedConfig map[string]any - CAProvider domain.ApplyCAProviderType - CAProviderAccessConfig map[string]any - CAProviderExtendedConfig map[string]any - KeyAlgorithm string - Nameservers []string - DnsPropagationTimeout int32 - DnsTTL int32 - DisableFollowCNAME bool - ReplacedARIAcct string - ReplacedARICert string +type ApplicantWithWorkflowNodeConfig struct { + Node *domain.WorkflowNode + Logger *slog.Logger } -func NewWithApplyNode(node *domain.WorkflowNode) (Applicant, error) { - if node.Type != domain.WorkflowNodeTypeApply { - return nil, fmt.Errorf("node type is not apply") +func NewWithWorkflowNode(config ApplicantWithWorkflowNodeConfig) (Applicant, error) { + if config.Node == nil { + return nil, fmt.Errorf("node is nil") + } + if config.Node.Type != domain.WorkflowNodeTypeApply { + return nil, fmt.Errorf("node type is not '%s'", string(domain.WorkflowNodeTypeApply)) } - nodeConfig := node.GetConfigForApply() - options := &applicantOptions{ + nodeConfig := config.Node.GetConfigForApply() + options := &applicantProviderOptions{ Domains: sliceutil.Filter(strings.Split(nodeConfig.Domains, ";"), func(s string) bool { return s != "" }), ContactEmail: nodeConfig.ContactEmail, - Provider: domain.ApplyDNSProviderType(nodeConfig.Provider), + Provider: domain.ACMEDns01ProviderType(nodeConfig.Provider), ProviderAccessConfig: make(map[string]any), ProviderExtendedConfig: nodeConfig.ProviderConfig, - CAProvider: domain.ApplyCAProviderType(nodeConfig.CAProvider), + CAProvider: domain.CAProviderType(nodeConfig.CAProvider), CAProviderAccessConfig: make(map[string]any), CAProviderExtendedConfig: nodeConfig.CAProviderConfig, KeyAlgorithm: nodeConfig.KeyAlgorithm, Nameservers: sliceutil.Filter(strings.Split(nodeConfig.Nameservers, ";"), func(s string) bool { return s != "" }), + DnsPropagationWait: nodeConfig.DnsPropagationWait, DnsPropagationTimeout: nodeConfig.DnsPropagationTimeout, DnsTTL: nodeConfig.DnsTTL, DisableFollowCNAME: nodeConfig.DisableFollowCNAME, @@ -97,7 +90,7 @@ func NewWithApplyNode(node *domain.WorkflowNode) (Applicant, error) { settings, _ := settingsRepo.GetByName(context.Background(), "sslProvider") sslProviderConfig := &acmeSSLProviderConfig{ - Config: make(map[domain.ApplyCAProviderType]map[string]any), + Config: make(map[domain.CAProviderType]map[string]any), Provider: sslProviderDefault, } if settings != nil { @@ -108,12 +101,12 @@ func NewWithApplyNode(node *domain.WorkflowNode) (Applicant, error) { } } - options.CAProvider = domain.ApplyCAProviderType(sslProviderConfig.Provider) + options.CAProvider = domain.CAProviderType(sslProviderConfig.Provider) options.CAProviderAccessConfig = sslProviderConfig.Config[options.CAProvider] } certRepo := repository.NewCertificateRepository() - lastCertificate, _ := certRepo.GetByWorkflowNodeId(context.Background(), node.Id) + lastCertificate, _ := certRepo.GetByWorkflowNodeId(context.Background(), config.Node.Id) if lastCertificate != nil { newCertSan := slices.Clone(options.Domains) oldCertSan := strings.Split(lastCertificate.SubjectAltNames, ";") @@ -130,18 +123,46 @@ func NewWithApplyNode(node *domain.WorkflowNode) (Applicant, error) { } } - applicant, err := createApplicant(options) + applicant, err := createApplicantProvider(options) if err != nil { return nil, err } - return &proxyApplicant{ + return &applicantImpl{ applicant: applicant, options: options, }, nil } -func apply(challengeProvider challenge.Provider, options *applicantOptions) (*ApplyCertResult, error) { +type applicantImpl struct { + applicant challenge.Provider + options *applicantProviderOptions +} + +var _ Applicant = (*applicantImpl)(nil) + +func (d *applicantImpl) Apply(ctx context.Context) (*ApplyResult, error) { + limiter := getLimiter(fmt.Sprintf("apply_%s", d.options.ContactEmail)) + if err := limiter.Wait(ctx); err != nil { + return nil, err + } + + return applyUseLego(d.applicant, d.options) +} + +const ( + limitBurst = 300 + limitRate float64 = float64(1) / float64(36) +) + +var limiters sync.Map + +func getLimiter(key string) *rate.Limiter { + limiter, _ := limiters.LoadOrStore(key, rate.NewLimiter(rate.Limit(limitRate), 300)) + return limiter.(*rate.Limiter) +} + +func applyUseLego(legoProvider challenge.Provider, options *applicantProviderOptions) (*ApplyResult, error) { user, err := newAcmeUser(string(options.CAProvider), options.ContactEmail) if err != nil { return nil, err @@ -153,7 +174,7 @@ func apply(challengeProvider challenge.Provider, options *applicantOptions) (*Ap // Create an ACME client config config := lego.NewConfig(user) - config.Certificate.KeyType = parseKeyAlgorithm(domain.CertificateKeyAlgorithmType(options.KeyAlgorithm)) + config.Certificate.KeyType = parseLegoKeyAlgorithm(domain.CertificateKeyAlgorithmType(options.KeyAlgorithm)) config.CADirURL = sslProviderUrls[user.CA] if user.CA == sslProviderSSLCom { if strings.HasPrefix(options.KeyAlgorithm, "RSA") { @@ -170,18 +191,26 @@ func apply(challengeProvider challenge.Provider, options *applicantOptions) (*Ap } // Set the DNS01 challenge provider - challengeOptions := make([]dns01.ChallengeOption, 0) - if len(options.Nameservers) > 0 { - challengeOptions = append(challengeOptions, dns01.AddRecursiveNameservers(dns01.ParseNameservers(options.Nameservers))) - challengeOptions = append(challengeOptions, dns01.DisableAuthoritativeNssPropagationRequirement()) - } - client.Challenge.SetDNS01Provider(challengeProvider, challengeOptions...) + client.Challenge.SetDNS01Provider(legoProvider, + dns01.CondOption( + len(options.Nameservers) > 0, + dns01.AddRecursiveNameservers(dns01.ParseNameservers(options.Nameservers)), + ), + dns01.CondOption( + options.DnsPropagationWait > 0, + dns01.PropagationWait(time.Duration(options.DnsPropagationWait)*time.Second, true), + ), + dns01.CondOption( + len(options.Nameservers) > 0 || options.DnsPropagationWait > 0, + dns01.DisableAuthoritativeNssPropagationRequirement(), + ), + ) // New users need to register first if !user.hasRegistration() { reg, err := registerAcmeUserWithSingleFlight(client, user, options.CAProviderAccessConfig) if err != nil { - return nil, fmt.Errorf("failed to register: %w", err) + return nil, fmt.Errorf("failed to register acme user: %w", err) } user.Registration = reg } @@ -199,7 +228,7 @@ func apply(challengeProvider challenge.Provider, options *applicantOptions) (*Ap return nil, err } - return &ApplyCertResult{ + return &ApplyResult{ CertificateFullChain: strings.TrimSpace(string(certResource.Certificate)), IssuerCertificate: strings.TrimSpace(string(certResource.IssuerCertificate)), PrivateKey: strings.TrimSpace(string(certResource.PrivateKey)), @@ -210,47 +239,20 @@ func apply(challengeProvider challenge.Provider, options *applicantOptions) (*Ap }, nil } -func parseKeyAlgorithm(algo domain.CertificateKeyAlgorithmType) certcrypto.KeyType { - switch algo { - case domain.CertificateKeyAlgorithmTypeRSA2048: - return certcrypto.RSA2048 - case domain.CertificateKeyAlgorithmTypeRSA3072: - return certcrypto.RSA3072 - case domain.CertificateKeyAlgorithmTypeRSA4096: - return certcrypto.RSA4096 - case domain.CertificateKeyAlgorithmTypeRSA8192: - return certcrypto.RSA8192 - case domain.CertificateKeyAlgorithmTypeEC256: - return certcrypto.EC256 - case domain.CertificateKeyAlgorithmTypeEC384: - return certcrypto.EC384 - case domain.CertificateKeyAlgorithmTypeEC512: - return certcrypto.KeyType("P512") +func parseLegoKeyAlgorithm(algo domain.CertificateKeyAlgorithmType) certcrypto.KeyType { + alogMap := map[domain.CertificateKeyAlgorithmType]certcrypto.KeyType{ + domain.CertificateKeyAlgorithmTypeRSA2048: certcrypto.RSA2048, + domain.CertificateKeyAlgorithmTypeRSA3072: certcrypto.RSA3072, + domain.CertificateKeyAlgorithmTypeRSA4096: certcrypto.RSA4096, + domain.CertificateKeyAlgorithmTypeRSA8192: certcrypto.RSA8192, + domain.CertificateKeyAlgorithmTypeEC256: certcrypto.EC256, + domain.CertificateKeyAlgorithmTypeEC384: certcrypto.EC384, + domain.CertificateKeyAlgorithmTypeEC512: certcrypto.KeyType("P512"), + } + + if keyType, ok := alogMap[algo]; ok { + return keyType } return certcrypto.RSA2048 } - -// TODO: 暂时使用代理模式以兼容之前版本代码,后续重新实现此处逻辑 -type proxyApplicant struct { - applicant challenge.Provider - options *applicantOptions -} - -var limiters sync.Map - -const ( - limitBurst = 300 - limitRate float64 = float64(1) / float64(36) -) - -func getLimiter(key string) *rate.Limiter { - limiter, _ := limiters.LoadOrStore(key, rate.NewLimiter(rate.Limit(limitRate), 300)) - return limiter.(*rate.Limiter) -} - -func (d *proxyApplicant) Apply() (*ApplyCertResult, error) { - limiter := getLimiter(fmt.Sprintf("apply_%s", d.options.ContactEmail)) - limiter.Wait(context.Background()) - return apply(d.applicant, d.options) -} diff --git a/internal/applicant/providers.go b/internal/applicant/providers.go index ddecad7c..454f9376 100644 --- a/internal/applicant/providers.go +++ b/internal/applicant/providers.go @@ -8,6 +8,7 @@ import ( "github.com/usual2970/certimate/internal/domain" pACMEHttpReq "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/acmehttpreq" pAliyun "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/aliyun" + pAliyunESA "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/aliyun-esa" pAWSRoute53 "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/aws-route53" pAzureDNS "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/azure-dns" pBaiduCloud "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/baiducloud" @@ -35,16 +36,35 @@ import ( pVercel "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/vercel" pVolcEngine "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/volcengine" pWestcn "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/westcn" - "github.com/usual2970/certimate/internal/pkg/utils/maputil" + maputil "github.com/usual2970/certimate/internal/pkg/utils/map" ) -func createApplicant(options *applicantOptions) (challenge.Provider, error) { +type applicantProviderOptions struct { + Domains []string + ContactEmail string + Provider domain.ACMEDns01ProviderType + ProviderAccessConfig map[string]any + ProviderExtendedConfig map[string]any + CAProvider domain.CAProviderType + CAProviderAccessConfig map[string]any + CAProviderExtendedConfig map[string]any + KeyAlgorithm string + Nameservers []string + DnsPropagationWait int32 + DnsPropagationTimeout int32 + DnsTTL int32 + DisableFollowCNAME bool + ReplacedARIAcct string + ReplacedARICert string +} + +func createApplicantProvider(options *applicantProviderOptions) (challenge.Provider, error) { /* 注意:如果追加新的常量值,请保持以 ASCII 排序。 NOTICE: If you add new constant, please keep ASCII order. */ switch options.Provider { - case domain.ApplyDNSProviderTypeACMEHttpReq: + case domain.ACMEDns01ProviderTypeACMEHttpReq: { access := domain.AccessConfigForACMEHttpReq{} if err := maputil.Populate(options.ProviderAccessConfig, &access); err != nil { @@ -61,23 +81,39 @@ func createApplicant(options *applicantOptions) (challenge.Provider, error) { return applicant, err } - case domain.ApplyDNSProviderTypeAliyun, domain.ApplyDNSProviderTypeAliyunDNS: + case domain.ACMEDns01ProviderTypeAliyun, domain.ACMEDns01ProviderTypeAliyunDNS, domain.ACMEDns01ProviderTypeAliyunESA: { access := domain.AccessConfigForAliyun{} if err := maputil.Populate(options.ProviderAccessConfig, &access); err != nil { return nil, fmt.Errorf("failed to populate provider access config: %w", err) } - applicant, err := pAliyun.NewChallengeProvider(&pAliyun.ChallengeProviderConfig{ - AccessKeyId: access.AccessKeyId, - AccessKeySecret: access.AccessKeySecret, - DnsPropagationTimeout: options.DnsPropagationTimeout, - DnsTTL: options.DnsTTL, - }) - return applicant, err + switch options.Provider { + case domain.ACMEDns01ProviderTypeAliyun, domain.ACMEDns01ProviderTypeAliyunDNS: + applicant, err := pAliyun.NewChallengeProvider(&pAliyun.ChallengeProviderConfig{ + AccessKeyId: access.AccessKeyId, + AccessKeySecret: access.AccessKeySecret, + DnsPropagationTimeout: options.DnsPropagationTimeout, + DnsTTL: options.DnsTTL, + }) + return applicant, err + + case domain.ACMEDns01ProviderTypeAliyunESA: + applicant, err := pAliyunESA.NewChallengeProvider(&pAliyunESA.ChallengeProviderConfig{ + AccessKeyId: access.AccessKeyId, + AccessKeySecret: access.AccessKeySecret, + Region: maputil.GetString(options.ProviderExtendedConfig, "region"), + DnsPropagationTimeout: options.DnsPropagationTimeout, + DnsTTL: options.DnsTTL, + }) + return applicant, err + + default: + break + } } - case domain.ApplyDNSProviderTypeAWS, domain.ApplyDNSProviderTypeAWSRoute53: + case domain.ACMEDns01ProviderTypeAWS, domain.ACMEDns01ProviderTypeAWSRoute53: { access := domain.AccessConfigForAWS{} if err := maputil.Populate(options.ProviderAccessConfig, &access); err != nil { @@ -95,7 +131,7 @@ func createApplicant(options *applicantOptions) (challenge.Provider, error) { return applicant, err } - case domain.ApplyDNSProviderTypeAzure, domain.ApplyDNSProviderTypeAzureDNS: + case domain.ACMEDns01ProviderTypeAzure, domain.ACMEDns01ProviderTypeAzureDNS: { access := domain.AccessConfigForAzure{} if err := maputil.Populate(options.ProviderAccessConfig, &access); err != nil { @@ -113,7 +149,7 @@ func createApplicant(options *applicantOptions) (challenge.Provider, error) { return applicant, err } - case domain.ApplyDNSProviderTypeBaiduCloud, domain.ApplyDNSProviderTypeBaiduCloudDNS: + case domain.ACMEDns01ProviderTypeBaiduCloud, domain.ACMEDns01ProviderTypeBaiduCloudDNS: { access := domain.AccessConfigForBaiduCloud{} if err := maputil.Populate(options.ProviderAccessConfig, &access); err != nil { @@ -129,7 +165,7 @@ func createApplicant(options *applicantOptions) (challenge.Provider, error) { return applicant, err } - case domain.ApplyDNSProviderTypeBunny: + case domain.ACMEDns01ProviderTypeBunny: { access := domain.AccessConfigForBunny{} if err := maputil.Populate(options.ProviderAccessConfig, &access); err != nil { @@ -144,7 +180,7 @@ func createApplicant(options *applicantOptions) (challenge.Provider, error) { return applicant, err } - case domain.ApplyDNSProviderTypeCloudflare: + case domain.ACMEDns01ProviderTypeCloudflare: { access := domain.AccessConfigForCloudflare{} if err := maputil.Populate(options.ProviderAccessConfig, &access); err != nil { @@ -160,7 +196,7 @@ func createApplicant(options *applicantOptions) (challenge.Provider, error) { return applicant, err } - case domain.ApplyDNSProviderTypeClouDNS: + case domain.ACMEDns01ProviderTypeClouDNS: { access := domain.AccessConfigForClouDNS{} if err := maputil.Populate(options.ProviderAccessConfig, &access); err != nil { @@ -176,7 +212,7 @@ func createApplicant(options *applicantOptions) (challenge.Provider, error) { return applicant, err } - case domain.ApplyDNSProviderTypeCMCCCloud: + case domain.ACMEDns01ProviderTypeCMCCCloud: { access := domain.AccessConfigForCMCCCloud{} if err := maputil.Populate(options.ProviderAccessConfig, &access); err != nil { @@ -192,7 +228,7 @@ func createApplicant(options *applicantOptions) (challenge.Provider, error) { return applicant, err } - case domain.ApplyDNSProviderTypeDeSEC: + case domain.ACMEDns01ProviderTypeDeSEC: { access := domain.AccessConfigForDeSEC{} if err := maputil.Populate(options.ProviderAccessConfig, &access); err != nil { @@ -207,7 +243,7 @@ func createApplicant(options *applicantOptions) (challenge.Provider, error) { return applicant, err } - case domain.ApplyDNSProviderTypeDNSLA: + case domain.ACMEDns01ProviderTypeDNSLA: { access := domain.AccessConfigForDNSLA{} if err := maputil.Populate(options.ProviderAccessConfig, &access); err != nil { @@ -223,7 +259,7 @@ func createApplicant(options *applicantOptions) (challenge.Provider, error) { return applicant, err } - case domain.ApplyDNSProviderTypeDynv6: + case domain.ACMEDns01ProviderTypeDynv6: { access := domain.AccessConfigForDynv6{} if err := maputil.Populate(options.ProviderAccessConfig, &access); err != nil { @@ -238,7 +274,7 @@ func createApplicant(options *applicantOptions) (challenge.Provider, error) { return applicant, err } - case domain.ApplyDNSProviderTypeGcore: + case domain.ACMEDns01ProviderTypeGcore: { access := domain.AccessConfigForGcore{} if err := maputil.Populate(options.ProviderAccessConfig, &access); err != nil { @@ -253,7 +289,7 @@ func createApplicant(options *applicantOptions) (challenge.Provider, error) { return applicant, err } - case domain.ApplyDNSProviderTypeGname: + case domain.ACMEDns01ProviderTypeGname: { access := domain.AccessConfigForGname{} if err := maputil.Populate(options.ProviderAccessConfig, &access); err != nil { @@ -269,7 +305,7 @@ func createApplicant(options *applicantOptions) (challenge.Provider, error) { return applicant, err } - case domain.ApplyDNSProviderTypeGoDaddy: + case domain.ACMEDns01ProviderTypeGoDaddy: { access := domain.AccessConfigForGoDaddy{} if err := maputil.Populate(options.ProviderAccessConfig, &access); err != nil { @@ -285,7 +321,7 @@ func createApplicant(options *applicantOptions) (challenge.Provider, error) { return applicant, err } - case domain.ApplyDNSProviderTypeHuaweiCloud, domain.ApplyDNSProviderTypeHuaweiCloudDNS: + case domain.ACMEDns01ProviderTypeHuaweiCloud, domain.ACMEDns01ProviderTypeHuaweiCloudDNS: { access := domain.AccessConfigForHuaweiCloud{} if err := maputil.Populate(options.ProviderAccessConfig, &access); err != nil { @@ -302,7 +338,7 @@ func createApplicant(options *applicantOptions) (challenge.Provider, error) { return applicant, err } - case domain.ApplyDNSProviderTypeJDCloud, domain.ApplyDNSProviderTypeJDCloudDNS: + case domain.ACMEDns01ProviderTypeJDCloud, domain.ACMEDns01ProviderTypeJDCloudDNS: { access := domain.AccessConfigForJDCloud{} if err := maputil.Populate(options.ProviderAccessConfig, &access); err != nil { @@ -319,7 +355,7 @@ func createApplicant(options *applicantOptions) (challenge.Provider, error) { return applicant, err } - case domain.ApplyDNSProviderTypeNamecheap: + case domain.ACMEDns01ProviderTypeNamecheap: { access := domain.AccessConfigForNamecheap{} if err := maputil.Populate(options.ProviderAccessConfig, &access); err != nil { @@ -335,7 +371,7 @@ func createApplicant(options *applicantOptions) (challenge.Provider, error) { return applicant, err } - case domain.ApplyDNSProviderTypeNameDotCom: + case domain.ACMEDns01ProviderTypeNameDotCom: { access := domain.AccessConfigForNameDotCom{} if err := maputil.Populate(options.ProviderAccessConfig, &access); err != nil { @@ -351,7 +387,7 @@ func createApplicant(options *applicantOptions) (challenge.Provider, error) { return applicant, err } - case domain.ApplyDNSProviderTypeNameSilo: + case domain.ACMEDns01ProviderTypeNameSilo: { access := domain.AccessConfigForNameSilo{} if err := maputil.Populate(options.ProviderAccessConfig, &access); err != nil { @@ -366,7 +402,7 @@ func createApplicant(options *applicantOptions) (challenge.Provider, error) { return applicant, err } - case domain.ApplyDNSProviderTypeNS1: + case domain.ACMEDns01ProviderTypeNS1: { access := domain.AccessConfigForNS1{} if err := maputil.Populate(options.ProviderAccessConfig, &access); err != nil { @@ -381,7 +417,7 @@ func createApplicant(options *applicantOptions) (challenge.Provider, error) { return applicant, err } - case domain.ApplyDNSProviderTypePorkbun: + case domain.ACMEDns01ProviderTypePorkbun: { access := domain.AccessConfigForPorkbun{} if err := maputil.Populate(options.ProviderAccessConfig, &access); err != nil { @@ -397,7 +433,7 @@ func createApplicant(options *applicantOptions) (challenge.Provider, error) { return applicant, err } - case domain.ApplyDNSProviderTypePowerDNS: + case domain.ACMEDns01ProviderTypePowerDNS: { access := domain.AccessConfigForPowerDNS{} if err := maputil.Populate(options.ProviderAccessConfig, &access); err != nil { @@ -405,15 +441,16 @@ func createApplicant(options *applicantOptions) (challenge.Provider, error) { } applicant, err := pPowerDNS.NewChallengeProvider(&pPowerDNS.ChallengeProviderConfig{ - ApiUrl: access.ApiUrl, - ApiKey: access.ApiKey, - DnsPropagationTimeout: options.DnsPropagationTimeout, - DnsTTL: options.DnsTTL, + ApiUrl: access.ApiUrl, + ApiKey: access.ApiKey, + AllowInsecureConnections: access.AllowInsecureConnections, + DnsPropagationTimeout: options.DnsPropagationTimeout, + DnsTTL: options.DnsTTL, }) return applicant, err } - case domain.ApplyDNSProviderTypeRainYun: + case domain.ACMEDns01ProviderTypeRainYun: { access := domain.AccessConfigForRainYun{} if err := maputil.Populate(options.ProviderAccessConfig, &access); err != nil { @@ -428,7 +465,7 @@ func createApplicant(options *applicantOptions) (challenge.Provider, error) { return applicant, err } - case domain.ApplyDNSProviderTypeTencentCloud, domain.ApplyDNSProviderTypeTencentCloudDNS, domain.ApplyDNSProviderTypeTencentCloudEO: + case domain.ACMEDns01ProviderTypeTencentCloud, domain.ACMEDns01ProviderTypeTencentCloudDNS, domain.ACMEDns01ProviderTypeTencentCloudEO: { access := domain.AccessConfigForTencentCloud{} if err := maputil.Populate(options.ProviderAccessConfig, &access); err != nil { @@ -436,7 +473,7 @@ func createApplicant(options *applicantOptions) (challenge.Provider, error) { } switch options.Provider { - case domain.ApplyDNSProviderTypeTencentCloud, domain.ApplyDNSProviderTypeTencentCloudDNS: + case domain.ACMEDns01ProviderTypeTencentCloud, domain.ACMEDns01ProviderTypeTencentCloudDNS: applicant, err := pTencentCloud.NewChallengeProvider(&pTencentCloud.ChallengeProviderConfig{ SecretId: access.SecretId, SecretKey: access.SecretKey, @@ -445,7 +482,7 @@ func createApplicant(options *applicantOptions) (challenge.Provider, error) { }) return applicant, err - case domain.ApplyDNSProviderTypeTencentCloudEO: + case domain.ACMEDns01ProviderTypeTencentCloudEO: applicant, err := pTencentCloudEO.NewChallengeProvider(&pTencentCloudEO.ChallengeProviderConfig{ SecretId: access.SecretId, SecretKey: access.SecretKey, @@ -460,7 +497,7 @@ func createApplicant(options *applicantOptions) (challenge.Provider, error) { } } - case domain.ApplyDNSProviderTypeVercel: + case domain.ACMEDns01ProviderTypeVercel: { access := domain.AccessConfigForVercel{} if err := maputil.Populate(options.ProviderAccessConfig, &access); err != nil { @@ -476,7 +513,7 @@ func createApplicant(options *applicantOptions) (challenge.Provider, error) { return applicant, err } - case domain.ApplyDNSProviderTypeVolcEngine, domain.ApplyDNSProviderTypeVolcEngineDNS: + case domain.ACMEDns01ProviderTypeVolcEngine, domain.ACMEDns01ProviderTypeVolcEngineDNS: { access := domain.AccessConfigForVolcEngine{} if err := maputil.Populate(options.ProviderAccessConfig, &access); err != nil { @@ -492,7 +529,7 @@ func createApplicant(options *applicantOptions) (challenge.Provider, error) { return applicant, err } - case domain.ApplyDNSProviderTypeWestcn: + case domain.ACMEDns01ProviderTypeWestcn: { access := domain.AccessConfigForWestcn{} if err := maputil.Populate(options.ProviderAccessConfig, &access); err != nil { @@ -509,5 +546,5 @@ func createApplicant(options *applicantOptions) (challenge.Provider, error) { } } - return nil, fmt.Errorf("unsupported applicant provider: %s", string(options.Provider)) + return nil, fmt.Errorf("unsupported applicant provider '%s'", string(options.Provider)) } diff --git a/internal/certificate/service.go b/internal/certificate/service.go index f8874f2d..ffb30d0f 100644 --- a/internal/certificate/service.go +++ b/internal/certificate/service.go @@ -17,7 +17,7 @@ import ( "github.com/usual2970/certimate/internal/domain" "github.com/usual2970/certimate/internal/domain/dtos" "github.com/usual2970/certimate/internal/notify" - "github.com/usual2970/certimate/internal/pkg/utils/certutil" + certutil "github.com/usual2970/certimate/internal/pkg/utils/cert" "github.com/usual2970/certimate/internal/repository" ) diff --git a/internal/deployer/deployer.go b/internal/deployer/deployer.go index c023a236..bdacf08e 100644 --- a/internal/deployer/deployer.go +++ b/internal/deployer/deployer.go @@ -11,31 +11,29 @@ import ( ) type Deployer interface { - SetLogger(*slog.Logger) - Deploy(ctx context.Context) error } -type deployerOptions struct { - Provider domain.DeployProviderType - ProviderAccessConfig map[string]any - ProviderDeployConfig map[string]any +type DeployerWithWorkflowNodeConfig struct { + Node *domain.WorkflowNode + Logger *slog.Logger + CertificatePEM string + PrivateKeyPEM string } -func NewWithDeployNode(node *domain.WorkflowNode, certdata struct { - Certificate string - PrivateKey string -}, -) (Deployer, error) { - if node.Type != domain.WorkflowNodeTypeDeploy { - return nil, fmt.Errorf("node type is not deploy") +func NewWithWorkflowNode(config DeployerWithWorkflowNodeConfig) (Deployer, error) { + if config.Node == nil { + return nil, fmt.Errorf("node is nil") + } + if config.Node.Type != domain.WorkflowNodeTypeDeploy { + return nil, fmt.Errorf("node type is not '%s'", string(domain.WorkflowNodeTypeDeploy)) } - nodeConfig := node.GetConfigForDeploy() - options := &deployerOptions{ - Provider: domain.DeployProviderType(nodeConfig.Provider), - ProviderAccessConfig: make(map[string]any), - ProviderDeployConfig: nodeConfig.ProviderConfig, + nodeConfig := config.Node.GetConfigForDeploy() + options := &deployerProviderOptions{ + Provider: domain.DeploymentProviderType(nodeConfig.Provider), + ProviderAccessConfig: make(map[string]any), + ProviderExtendedConfig: nodeConfig.ProviderConfig, } accessRepo := repository.NewAccessRepository() @@ -48,34 +46,27 @@ func NewWithDeployNode(node *domain.WorkflowNode, certdata struct { } } - deployer, err := createDeployer(options) + deployerProvider, err := createDeployerProvider(options) if err != nil { return nil, err } - return &proxyDeployer{ - deployer: deployer, - deployCertificate: certdata.Certificate, - deployPrivateKey: certdata.PrivateKey, + return &deployerImpl{ + provider: deployerProvider.WithLogger(config.Logger), + certPEM: config.CertificatePEM, + privkeyPEM: config.PrivateKeyPEM, }, nil } -// TODO: 暂时使用代理模式以兼容之前版本代码,后续重新实现此处逻辑 -type proxyDeployer struct { - deployer deployer.Deployer - deployCertificate string - deployPrivateKey string +type deployerImpl struct { + provider deployer.Deployer + certPEM string + privkeyPEM string } -func (d *proxyDeployer) SetLogger(logger *slog.Logger) { - if logger == nil { - panic("logger is nil") - } +var _ Deployer = (*deployerImpl)(nil) - d.deployer.WithLogger(logger) -} - -func (d *proxyDeployer) Deploy(ctx context.Context) error { - _, err := d.deployer.Deploy(ctx, d.deployCertificate, d.deployPrivateKey) +func (d *deployerImpl) Deploy(ctx context.Context) error { + _, err := d.provider.Deploy(ctx, d.certPEM, d.privkeyPEM) return err } diff --git a/internal/deployer/providers.go b/internal/deployer/providers.go index 71874c90..77ed8acb 100644 --- a/internal/deployer/providers.go +++ b/internal/deployer/providers.go @@ -2,6 +2,7 @@ package deployer import ( "fmt" + "net/http" "strings" "github.com/usual2970/certimate/internal/domain" @@ -15,6 +16,7 @@ import ( pAliyunCDN "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/aliyun-cdn" pAliyunCLB "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/aliyun-clb" pAliyunDCDN "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/aliyun-dcdn" + pAliyunDDoS "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/aliyun-ddos" pAliyunESA "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/aliyun-esa" pAliyunFC "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/aliyun-fc" pAliyunLive "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/aliyun-live" @@ -39,6 +41,7 @@ import ( pDogeCDN "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/dogecloud-cdn" pEdgioApplications "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/edgio-applications" pGcoreCDN "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/gcore-cdn" + pGoEdge "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/goedge" pHuaweiCloudCDN "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/huaweicloud-cdn" pHuaweiCloudELB "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/huaweicloud-elb" pHuaweiCloudSCM "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/huaweicloud-scm" @@ -49,6 +52,7 @@ import ( pJDCloudVOD "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/jdcloud-vod" pK8sSecret "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/k8s-secret" pLocal "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/local" + pProxmoxVE "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/proxmoxve" pQiniuCDN "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/qiniu-cdn" pQiniuPili "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/qiniu-pili" pRainYunRCDN "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/rainyun-rcdn" @@ -78,17 +82,24 @@ import ( pVolcEngineTOS "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/volcengine-tos" pWangsuCDNPro "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/wangsu-cdnpro" pWebhook "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/webhook" - "github.com/usual2970/certimate/internal/pkg/utils/maputil" - "github.com/usual2970/certimate/internal/pkg/utils/sliceutil" + httputil "github.com/usual2970/certimate/internal/pkg/utils/http" + maputil "github.com/usual2970/certimate/internal/pkg/utils/map" + sliceutil "github.com/usual2970/certimate/internal/pkg/utils/slice" ) -func createDeployer(options *deployerOptions) (deployer.Deployer, error) { +type deployerProviderOptions struct { + Provider domain.DeploymentProviderType + ProviderAccessConfig map[string]any + ProviderExtendedConfig map[string]any +} + +func createDeployerProvider(options *deployerProviderOptions) (deployer.Deployer, error) { /* 注意:如果追加新的常量值,请保持以 ASCII 排序。 NOTICE: If you add new constant, please keep ASCII order. */ switch options.Provider { - case domain.DeployProviderType1PanelConsole, domain.DeployProviderType1PanelSite: + case domain.DeploymentProviderType1PanelConsole, domain.DeploymentProviderType1PanelSite: { access := domain.AccessConfigFor1Panel{} if err := maputil.Populate(options.ProviderAccessConfig, &access); err != nil { @@ -96,23 +107,23 @@ func createDeployer(options *deployerOptions) (deployer.Deployer, error) { } switch options.Provider { - case domain.DeployProviderType1PanelConsole: + case domain.DeploymentProviderType1PanelConsole: deployer, err := p1PanelConsole.NewDeployer(&p1PanelConsole.DeployerConfig{ ApiUrl: access.ApiUrl, ApiKey: access.ApiKey, AllowInsecureConnections: access.AllowInsecureConnections, - AutoRestart: maputil.GetBool(options.ProviderDeployConfig, "autoRestart"), + AutoRestart: maputil.GetBool(options.ProviderExtendedConfig, "autoRestart"), }) return deployer, err - case domain.DeployProviderType1PanelSite: + case domain.DeploymentProviderType1PanelSite: deployer, err := p1PanelSite.NewDeployer(&p1PanelSite.DeployerConfig{ ApiUrl: access.ApiUrl, ApiKey: access.ApiKey, AllowInsecureConnections: access.AllowInsecureConnections, - ResourceType: p1PanelSite.ResourceType(maputil.GetOrDefaultString(options.ProviderDeployConfig, "resourceType", string(p1PanelSite.RESOURCE_TYPE_WEBSITE))), - WebsiteId: maputil.GetInt64(options.ProviderDeployConfig, "websiteId"), - CertificateId: maputil.GetInt64(options.ProviderDeployConfig, "certificateId"), + ResourceType: p1PanelSite.ResourceType(maputil.GetOrDefaultString(options.ProviderExtendedConfig, "resourceType", string(p1PanelSite.RESOURCE_TYPE_WEBSITE))), + WebsiteId: maputil.GetInt64(options.ProviderExtendedConfig, "websiteId"), + CertificateId: maputil.GetInt64(options.ProviderExtendedConfig, "certificateId"), }) return deployer, err @@ -121,7 +132,7 @@ func createDeployer(options *deployerOptions) (deployer.Deployer, error) { } } - case domain.DeployProviderTypeAliyunALB, domain.DeployProviderTypeAliyunAPIGW, domain.DeployProviderTypeAliyunCAS, domain.DeployProviderTypeAliyunCASDeploy, domain.DeployProviderTypeAliyunCDN, domain.DeployProviderTypeAliyunCLB, domain.DeployProviderTypeAliyunDCDN, domain.DeployProviderTypeAliyunESA, domain.DeployProviderTypeAliyunFC, domain.DeployProviderTypeAliyunLive, domain.DeployProviderTypeAliyunNLB, domain.DeployProviderTypeAliyunOSS, domain.DeployProviderTypeAliyunVOD, domain.DeployProviderTypeAliyunWAF: + case domain.DeploymentProviderTypeAliyunALB, domain.DeploymentProviderTypeAliyunAPIGW, domain.DeploymentProviderTypeAliyunCAS, domain.DeploymentProviderTypeAliyunCASDeploy, domain.DeploymentProviderTypeAliyunCDN, domain.DeploymentProviderTypeAliyunCLB, domain.DeploymentProviderTypeAliyunDCDN, domain.DeploymentProviderTypeAliyunDDoS, domain.DeploymentProviderTypeAliyunESA, domain.DeploymentProviderTypeAliyunFC, domain.DeploymentProviderTypeAliyunLive, domain.DeploymentProviderTypeAliyunNLB, domain.DeploymentProviderTypeAliyunOSS, domain.DeploymentProviderTypeAliyunVOD, domain.DeploymentProviderTypeAliyunWAF: { access := domain.AccessConfigForAliyun{} if err := maputil.Populate(options.ProviderAccessConfig, &access); err != nil { @@ -129,142 +140,151 @@ func createDeployer(options *deployerOptions) (deployer.Deployer, error) { } switch options.Provider { - case domain.DeployProviderTypeAliyunALB: + case domain.DeploymentProviderTypeAliyunALB: deployer, err := pAliyunALB.NewDeployer(&pAliyunALB.DeployerConfig{ AccessKeyId: access.AccessKeyId, AccessKeySecret: access.AccessKeySecret, - Region: maputil.GetString(options.ProviderDeployConfig, "region"), - ResourceType: pAliyunALB.ResourceType(maputil.GetString(options.ProviderDeployConfig, "resourceType")), - LoadbalancerId: maputil.GetString(options.ProviderDeployConfig, "loadbalancerId"), - ListenerId: maputil.GetString(options.ProviderDeployConfig, "listenerId"), - Domain: maputil.GetString(options.ProviderDeployConfig, "domain"), + Region: maputil.GetString(options.ProviderExtendedConfig, "region"), + ResourceType: pAliyunALB.ResourceType(maputil.GetString(options.ProviderExtendedConfig, "resourceType")), + LoadbalancerId: maputil.GetString(options.ProviderExtendedConfig, "loadbalancerId"), + ListenerId: maputil.GetString(options.ProviderExtendedConfig, "listenerId"), + Domain: maputil.GetString(options.ProviderExtendedConfig, "domain"), }) return deployer, err - case domain.DeployProviderTypeAliyunAPIGW: + case domain.DeploymentProviderTypeAliyunAPIGW: deployer, err := pAliyunAPIGW.NewDeployer(&pAliyunAPIGW.DeployerConfig{ AccessKeyId: access.AccessKeyId, AccessKeySecret: access.AccessKeySecret, - Region: maputil.GetString(options.ProviderDeployConfig, "region"), - ServiceType: pAliyunAPIGW.ServiceType(maputil.GetString(options.ProviderDeployConfig, "serviceType")), - GatewayId: maputil.GetString(options.ProviderDeployConfig, "gatewayId"), - GroupId: maputil.GetString(options.ProviderDeployConfig, "groupId"), - Domain: maputil.GetString(options.ProviderDeployConfig, "domain"), + Region: maputil.GetString(options.ProviderExtendedConfig, "region"), + ServiceType: pAliyunAPIGW.ServiceType(maputil.GetString(options.ProviderExtendedConfig, "serviceType")), + GatewayId: maputil.GetString(options.ProviderExtendedConfig, "gatewayId"), + GroupId: maputil.GetString(options.ProviderExtendedConfig, "groupId"), + Domain: maputil.GetString(options.ProviderExtendedConfig, "domain"), }) return deployer, err - case domain.DeployProviderTypeAliyunCAS: + case domain.DeploymentProviderTypeAliyunCAS: deployer, err := pAliyunCAS.NewDeployer(&pAliyunCAS.DeployerConfig{ AccessKeyId: access.AccessKeyId, AccessKeySecret: access.AccessKeySecret, - Region: maputil.GetString(options.ProviderDeployConfig, "region"), + Region: maputil.GetString(options.ProviderExtendedConfig, "region"), }) return deployer, err - case domain.DeployProviderTypeAliyunCASDeploy: + case domain.DeploymentProviderTypeAliyunCASDeploy: deployer, err := pAliyunCASDeploy.NewDeployer(&pAliyunCASDeploy.DeployerConfig{ AccessKeyId: access.AccessKeyId, AccessKeySecret: access.AccessKeySecret, - Region: maputil.GetString(options.ProviderDeployConfig, "region"), - ResourceIds: sliceutil.Filter(strings.Split(maputil.GetString(options.ProviderDeployConfig, "resourceIds"), ";"), func(s string) bool { return s != "" }), - ContactIds: sliceutil.Filter(strings.Split(maputil.GetString(options.ProviderDeployConfig, "contactIds"), ";"), func(s string) bool { return s != "" }), + Region: maputil.GetString(options.ProviderExtendedConfig, "region"), + ResourceIds: sliceutil.Filter(strings.Split(maputil.GetString(options.ProviderExtendedConfig, "resourceIds"), ";"), func(s string) bool { return s != "" }), + ContactIds: sliceutil.Filter(strings.Split(maputil.GetString(options.ProviderExtendedConfig, "contactIds"), ";"), func(s string) bool { return s != "" }), }) return deployer, err - case domain.DeployProviderTypeAliyunCDN: + case domain.DeploymentProviderTypeAliyunCDN: deployer, err := pAliyunCDN.NewDeployer(&pAliyunCDN.DeployerConfig{ AccessKeyId: access.AccessKeyId, AccessKeySecret: access.AccessKeySecret, - Domain: maputil.GetString(options.ProviderDeployConfig, "domain"), + Domain: maputil.GetString(options.ProviderExtendedConfig, "domain"), }) return deployer, err - case domain.DeployProviderTypeAliyunCLB: + case domain.DeploymentProviderTypeAliyunCLB: deployer, err := pAliyunCLB.NewDeployer(&pAliyunCLB.DeployerConfig{ AccessKeyId: access.AccessKeyId, AccessKeySecret: access.AccessKeySecret, - Region: maputil.GetString(options.ProviderDeployConfig, "region"), - ResourceType: pAliyunCLB.ResourceType(maputil.GetString(options.ProviderDeployConfig, "resourceType")), - LoadbalancerId: maputil.GetString(options.ProviderDeployConfig, "loadbalancerId"), - ListenerPort: maputil.GetOrDefaultInt32(options.ProviderDeployConfig, "listenerPort", 443), - Domain: maputil.GetString(options.ProviderDeployConfig, "domain"), + Region: maputil.GetString(options.ProviderExtendedConfig, "region"), + ResourceType: pAliyunCLB.ResourceType(maputil.GetString(options.ProviderExtendedConfig, "resourceType")), + LoadbalancerId: maputil.GetString(options.ProviderExtendedConfig, "loadbalancerId"), + ListenerPort: maputil.GetOrDefaultInt32(options.ProviderExtendedConfig, "listenerPort", 443), + Domain: maputil.GetString(options.ProviderExtendedConfig, "domain"), }) return deployer, err - case domain.DeployProviderTypeAliyunDCDN: + case domain.DeploymentProviderTypeAliyunDCDN: deployer, err := pAliyunDCDN.NewDeployer(&pAliyunDCDN.DeployerConfig{ AccessKeyId: access.AccessKeyId, AccessKeySecret: access.AccessKeySecret, - Domain: maputil.GetString(options.ProviderDeployConfig, "domain"), + Domain: maputil.GetString(options.ProviderExtendedConfig, "domain"), }) return deployer, err - case domain.DeployProviderTypeAliyunESA: + case domain.DeploymentProviderTypeAliyunDDoS: + deployer, err := pAliyunDDoS.NewDeployer(&pAliyunDDoS.DeployerConfig{ + AccessKeyId: access.AccessKeyId, + AccessKeySecret: access.AccessKeySecret, + Region: maputil.GetString(options.ProviderExtendedConfig, "region"), + Domain: maputil.GetString(options.ProviderExtendedConfig, "domain"), + }) + return deployer, err + + case domain.DeploymentProviderTypeAliyunESA: deployer, err := pAliyunESA.NewDeployer(&pAliyunESA.DeployerConfig{ AccessKeyId: access.AccessKeyId, AccessKeySecret: access.AccessKeySecret, - Region: maputil.GetString(options.ProviderDeployConfig, "region"), - SiteId: maputil.GetInt64(options.ProviderDeployConfig, "siteId"), + Region: maputil.GetString(options.ProviderExtendedConfig, "region"), + SiteId: maputil.GetInt64(options.ProviderExtendedConfig, "siteId"), }) return deployer, err - case domain.DeployProviderTypeAliyunFC: + case domain.DeploymentProviderTypeAliyunFC: deployer, err := pAliyunFC.NewDeployer(&pAliyunFC.DeployerConfig{ AccessKeyId: access.AccessKeyId, AccessKeySecret: access.AccessKeySecret, - Region: maputil.GetString(options.ProviderDeployConfig, "region"), - ServiceVersion: maputil.GetOrDefaultString(options.ProviderDeployConfig, "serviceVersion", "3.0"), - Domain: maputil.GetString(options.ProviderDeployConfig, "domain"), + Region: maputil.GetString(options.ProviderExtendedConfig, "region"), + ServiceVersion: maputil.GetOrDefaultString(options.ProviderExtendedConfig, "serviceVersion", "3.0"), + Domain: maputil.GetString(options.ProviderExtendedConfig, "domain"), }) return deployer, err - case domain.DeployProviderTypeAliyunLive: + case domain.DeploymentProviderTypeAliyunLive: deployer, err := pAliyunLive.NewDeployer(&pAliyunLive.DeployerConfig{ AccessKeyId: access.AccessKeyId, AccessKeySecret: access.AccessKeySecret, - Region: maputil.GetString(options.ProviderDeployConfig, "region"), - Domain: maputil.GetString(options.ProviderDeployConfig, "domain"), + Region: maputil.GetString(options.ProviderExtendedConfig, "region"), + Domain: maputil.GetString(options.ProviderExtendedConfig, "domain"), }) return deployer, err - case domain.DeployProviderTypeAliyunNLB: + case domain.DeploymentProviderTypeAliyunNLB: deployer, err := pAliyunNLB.NewDeployer(&pAliyunNLB.DeployerConfig{ AccessKeyId: access.AccessKeyId, AccessKeySecret: access.AccessKeySecret, - Region: maputil.GetString(options.ProviderDeployConfig, "region"), - ResourceType: pAliyunNLB.ResourceType(maputil.GetString(options.ProviderDeployConfig, "resourceType")), - LoadbalancerId: maputil.GetString(options.ProviderDeployConfig, "loadbalancerId"), - ListenerId: maputil.GetString(options.ProviderDeployConfig, "listenerId"), + Region: maputil.GetString(options.ProviderExtendedConfig, "region"), + ResourceType: pAliyunNLB.ResourceType(maputil.GetString(options.ProviderExtendedConfig, "resourceType")), + LoadbalancerId: maputil.GetString(options.ProviderExtendedConfig, "loadbalancerId"), + ListenerId: maputil.GetString(options.ProviderExtendedConfig, "listenerId"), }) return deployer, err - case domain.DeployProviderTypeAliyunOSS: + case domain.DeploymentProviderTypeAliyunOSS: deployer, err := pAliyunOSS.NewDeployer(&pAliyunOSS.DeployerConfig{ AccessKeyId: access.AccessKeyId, AccessKeySecret: access.AccessKeySecret, - Region: maputil.GetString(options.ProviderDeployConfig, "region"), - Bucket: maputil.GetString(options.ProviderDeployConfig, "bucket"), - Domain: maputil.GetString(options.ProviderDeployConfig, "domain"), + Region: maputil.GetString(options.ProviderExtendedConfig, "region"), + Bucket: maputil.GetString(options.ProviderExtendedConfig, "bucket"), + Domain: maputil.GetString(options.ProviderExtendedConfig, "domain"), }) return deployer, err - case domain.DeployProviderTypeAliyunVOD: + case domain.DeploymentProviderTypeAliyunVOD: deployer, err := pAliyunVOD.NewDeployer(&pAliyunVOD.DeployerConfig{ AccessKeyId: access.AccessKeyId, AccessKeySecret: access.AccessKeySecret, - Region: maputil.GetString(options.ProviderDeployConfig, "region"), - Domain: maputil.GetString(options.ProviderDeployConfig, "domain"), + Region: maputil.GetString(options.ProviderExtendedConfig, "region"), + Domain: maputil.GetString(options.ProviderExtendedConfig, "domain"), }) return deployer, err - case domain.DeployProviderTypeAliyunWAF: + case domain.DeploymentProviderTypeAliyunWAF: deployer, err := pAliyunWAF.NewDeployer(&pAliyunWAF.DeployerConfig{ AccessKeyId: access.AccessKeyId, AccessKeySecret: access.AccessKeySecret, - Region: maputil.GetString(options.ProviderDeployConfig, "region"), - ServiceVersion: maputil.GetOrDefaultString(options.ProviderDeployConfig, "serviceVersion", "3.0"), - InstanceId: maputil.GetString(options.ProviderDeployConfig, "instanceId"), - Domain: maputil.GetString(options.ProviderDeployConfig, "domain"), + Region: maputil.GetString(options.ProviderExtendedConfig, "region"), + ServiceVersion: maputil.GetOrDefaultString(options.ProviderExtendedConfig, "serviceVersion", "3.0"), + InstanceId: maputil.GetString(options.ProviderExtendedConfig, "instanceId"), + Domain: maputil.GetString(options.ProviderExtendedConfig, "domain"), }) return deployer, err @@ -273,7 +293,7 @@ func createDeployer(options *deployerOptions) (deployer.Deployer, error) { } } - case domain.DeployProviderTypeAWSACM, domain.DeployProviderTypeAWSCloudFront: + case domain.DeploymentProviderTypeAWSACM, domain.DeploymentProviderTypeAWSCloudFront: { access := domain.AccessConfigForAWS{} if err := maputil.Populate(options.ProviderAccessConfig, &access); err != nil { @@ -281,20 +301,20 @@ func createDeployer(options *deployerOptions) (deployer.Deployer, error) { } switch options.Provider { - case domain.DeployProviderTypeAWSACM: + case domain.DeploymentProviderTypeAWSACM: deployer, err := pAWSACM.NewDeployer(&pAWSACM.DeployerConfig{ AccessKeyId: access.AccessKeyId, SecretAccessKey: access.SecretAccessKey, - Region: maputil.GetString(options.ProviderDeployConfig, "region"), + Region: maputil.GetString(options.ProviderExtendedConfig, "region"), }) return deployer, err - case domain.DeployProviderTypeAWSCloudFront: + case domain.DeploymentProviderTypeAWSCloudFront: deployer, err := pAWSCloudFront.NewDeployer(&pAWSCloudFront.DeployerConfig{ AccessKeyId: access.AccessKeyId, SecretAccessKey: access.SecretAccessKey, - Region: maputil.GetString(options.ProviderDeployConfig, "region"), - DistributionId: maputil.GetString(options.ProviderDeployConfig, "distributionId"), + Region: maputil.GetString(options.ProviderExtendedConfig, "region"), + DistributionId: maputil.GetString(options.ProviderExtendedConfig, "distributionId"), }) return deployer, err @@ -303,7 +323,7 @@ func createDeployer(options *deployerOptions) (deployer.Deployer, error) { } } - case domain.DeployProviderTypeAzureKeyVault: + case domain.DeploymentProviderTypeAzureKeyVault: { access := domain.AccessConfigForAzure{} if err := maputil.Populate(options.ProviderAccessConfig, &access); err != nil { @@ -311,14 +331,14 @@ func createDeployer(options *deployerOptions) (deployer.Deployer, error) { } switch options.Provider { - case domain.DeployProviderTypeAzureKeyVault: + case domain.DeploymentProviderTypeAzureKeyVault: deployer, err := pAzureKeyVault.NewDeployer(&pAzureKeyVault.DeployerConfig{ TenantId: access.TenantId, ClientId: access.ClientId, ClientSecret: access.ClientSecret, CloudName: access.CloudName, - KeyVaultName: maputil.GetString(options.ProviderDeployConfig, "keyvaultName"), - CertificateName: maputil.GetString(options.ProviderDeployConfig, "certificateName"), + KeyVaultName: maputil.GetString(options.ProviderExtendedConfig, "keyvaultName"), + CertificateName: maputil.GetString(options.ProviderExtendedConfig, "certificateName"), }) return deployer, err @@ -327,7 +347,7 @@ func createDeployer(options *deployerOptions) (deployer.Deployer, error) { } } - case domain.DeployProviderTypeBaiduCloudAppBLB, domain.DeployProviderTypeBaiduCloudBLB, domain.DeployProviderTypeBaiduCloudCDN, domain.DeployProviderTypeBaiduCloudCert: + case domain.DeploymentProviderTypeBaiduCloudAppBLB, domain.DeploymentProviderTypeBaiduCloudBLB, domain.DeploymentProviderTypeBaiduCloudCDN, domain.DeploymentProviderTypeBaiduCloudCert: { access := domain.AccessConfigForBaiduCloud{} if err := maputil.Populate(options.ProviderAccessConfig, &access); err != nil { @@ -335,39 +355,39 @@ func createDeployer(options *deployerOptions) (deployer.Deployer, error) { } switch options.Provider { - case domain.DeployProviderTypeBaiduCloudAppBLB: + case domain.DeploymentProviderTypeBaiduCloudAppBLB: deployer, err := pBaiduCloudAppBLB.NewDeployer(&pBaiduCloudAppBLB.DeployerConfig{ AccessKeyId: access.AccessKeyId, SecretAccessKey: access.SecretAccessKey, - Region: maputil.GetString(options.ProviderDeployConfig, "region"), - ResourceType: pBaiduCloudAppBLB.ResourceType(maputil.GetString(options.ProviderDeployConfig, "resourceType")), - LoadbalancerId: maputil.GetString(options.ProviderDeployConfig, "loadbalancerId"), - ListenerPort: maputil.GetInt32(options.ProviderDeployConfig, "listenerPort"), - Domain: maputil.GetString(options.ProviderDeployConfig, "domain"), + Region: maputil.GetString(options.ProviderExtendedConfig, "region"), + ResourceType: pBaiduCloudAppBLB.ResourceType(maputil.GetString(options.ProviderExtendedConfig, "resourceType")), + LoadbalancerId: maputil.GetString(options.ProviderExtendedConfig, "loadbalancerId"), + ListenerPort: maputil.GetInt32(options.ProviderExtendedConfig, "listenerPort"), + Domain: maputil.GetString(options.ProviderExtendedConfig, "domain"), }) return deployer, err - case domain.DeployProviderTypeBaiduCloudBLB: + case domain.DeploymentProviderTypeBaiduCloudBLB: deployer, err := pBaiduCloudBLB.NewDeployer(&pBaiduCloudBLB.DeployerConfig{ AccessKeyId: access.AccessKeyId, SecretAccessKey: access.SecretAccessKey, - Region: maputil.GetString(options.ProviderDeployConfig, "region"), - ResourceType: pBaiduCloudBLB.ResourceType(maputil.GetString(options.ProviderDeployConfig, "resourceType")), - LoadbalancerId: maputil.GetString(options.ProviderDeployConfig, "loadbalancerId"), - ListenerPort: maputil.GetInt32(options.ProviderDeployConfig, "listenerPort"), - Domain: maputil.GetString(options.ProviderDeployConfig, "domain"), + Region: maputil.GetString(options.ProviderExtendedConfig, "region"), + ResourceType: pBaiduCloudBLB.ResourceType(maputil.GetString(options.ProviderExtendedConfig, "resourceType")), + LoadbalancerId: maputil.GetString(options.ProviderExtendedConfig, "loadbalancerId"), + ListenerPort: maputil.GetInt32(options.ProviderExtendedConfig, "listenerPort"), + Domain: maputil.GetString(options.ProviderExtendedConfig, "domain"), }) return deployer, err - case domain.DeployProviderTypeBaiduCloudCDN: + case domain.DeploymentProviderTypeBaiduCloudCDN: deployer, err := pBaiduCloudCDN.NewDeployer(&pBaiduCloudCDN.DeployerConfig{ AccessKeyId: access.AccessKeyId, SecretAccessKey: access.SecretAccessKey, - Domain: maputil.GetString(options.ProviderDeployConfig, "domain"), + Domain: maputil.GetString(options.ProviderExtendedConfig, "domain"), }) return deployer, err - case domain.DeployProviderTypeBaiduCloudCert: + case domain.DeploymentProviderTypeBaiduCloudCert: deployer, err := pBaiduCloudCert.NewDeployer(&pBaiduCloudCert.DeployerConfig{ AccessKeyId: access.AccessKeyId, SecretAccessKey: access.SecretAccessKey, @@ -379,7 +399,7 @@ func createDeployer(options *deployerOptions) (deployer.Deployer, error) { } } - case domain.DeployProviderTypeBaishanCDN: + case domain.DeploymentProviderTypeBaishanCDN: { access := domain.AccessConfigForBaishan{} if err := maputil.Populate(options.ProviderAccessConfig, &access); err != nil { @@ -387,11 +407,11 @@ func createDeployer(options *deployerOptions) (deployer.Deployer, error) { } switch options.Provider { - case domain.DeployProviderTypeBaishanCDN: + case domain.DeploymentProviderTypeBaishanCDN: deployer, err := pBaishanCDN.NewDeployer(&pBaishanCDN.DeployerConfig{ ApiToken: access.ApiToken, - Domain: maputil.GetString(options.ProviderDeployConfig, "domain"), - CertificateId: maputil.GetString(options.ProviderDeployConfig, "certificateId"), + Domain: maputil.GetString(options.ProviderExtendedConfig, "domain"), + CertificateId: maputil.GetString(options.ProviderExtendedConfig, "certificateId"), }) return deployer, err @@ -400,7 +420,7 @@ func createDeployer(options *deployerOptions) (deployer.Deployer, error) { } } - case domain.DeployProviderTypeBaotaPanelConsole, domain.DeployProviderTypeBaotaPanelSite: + case domain.DeploymentProviderTypeBaotaPanelConsole, domain.DeploymentProviderTypeBaotaPanelSite: { access := domain.AccessConfigForBaotaPanel{} if err := maputil.Populate(options.ProviderAccessConfig, &access); err != nil { @@ -408,23 +428,23 @@ func createDeployer(options *deployerOptions) (deployer.Deployer, error) { } switch options.Provider { - case domain.DeployProviderTypeBaotaPanelConsole: + case domain.DeploymentProviderTypeBaotaPanelConsole: deployer, err := pBaotaPanelConsole.NewDeployer(&pBaotaPanelConsole.DeployerConfig{ ApiUrl: access.ApiUrl, ApiKey: access.ApiKey, AllowInsecureConnections: access.AllowInsecureConnections, - AutoRestart: maputil.GetBool(options.ProviderDeployConfig, "autoRestart"), + AutoRestart: maputil.GetBool(options.ProviderExtendedConfig, "autoRestart"), }) return deployer, err - case domain.DeployProviderTypeBaotaPanelSite: + case domain.DeploymentProviderTypeBaotaPanelSite: deployer, err := pBaotaPanelSite.NewDeployer(&pBaotaPanelSite.DeployerConfig{ ApiUrl: access.ApiUrl, ApiKey: access.ApiKey, AllowInsecureConnections: access.AllowInsecureConnections, - SiteType: maputil.GetOrDefaultString(options.ProviderDeployConfig, "siteType", "other"), - SiteName: maputil.GetString(options.ProviderDeployConfig, "siteName"), - SiteNames: sliceutil.Filter(strings.Split(maputil.GetString(options.ProviderDeployConfig, "siteNames"), ";"), func(s string) bool { return s != "" }), + SiteType: maputil.GetOrDefaultString(options.ProviderExtendedConfig, "siteType", "other"), + SiteName: maputil.GetString(options.ProviderExtendedConfig, "siteName"), + SiteNames: sliceutil.Filter(strings.Split(maputil.GetString(options.ProviderExtendedConfig, "siteNames"), ";"), func(s string) bool { return s != "" }), }) return deployer, err @@ -433,7 +453,7 @@ func createDeployer(options *deployerOptions) (deployer.Deployer, error) { } } - case domain.DeployProviderTypeBunnyCDN: + case domain.DeploymentProviderTypeBunnyCDN: { access := domain.AccessConfigForBunny{} if err := maputil.Populate(options.ProviderAccessConfig, &access); err != nil { @@ -442,13 +462,13 @@ func createDeployer(options *deployerOptions) (deployer.Deployer, error) { deployer, err := pBunnyCDN.NewDeployer(&pBunnyCDN.DeployerConfig{ ApiKey: access.ApiKey, - PullZoneId: maputil.GetString(options.ProviderDeployConfig, "pullZoneId"), - HostName: maputil.GetString(options.ProviderDeployConfig, "hostName"), + PullZoneId: maputil.GetString(options.ProviderExtendedConfig, "pullZoneId"), + Hostname: maputil.GetString(options.ProviderExtendedConfig, "hostname"), }) return deployer, err } - case domain.DeployProviderTypeBytePlusCDN: + case domain.DeploymentProviderTypeBytePlusCDN: { access := domain.AccessConfigForBytePlus{} if err := maputil.Populate(options.ProviderAccessConfig, &access); err != nil { @@ -456,11 +476,11 @@ func createDeployer(options *deployerOptions) (deployer.Deployer, error) { } switch options.Provider { - case domain.DeployProviderTypeBytePlusCDN: + case domain.DeploymentProviderTypeBytePlusCDN: deployer, err := pBytePlusCDN.NewDeployer(&pBytePlusCDN.DeployerConfig{ AccessKey: access.AccessKey, SecretKey: access.SecretKey, - Domain: maputil.GetString(options.ProviderDeployConfig, "domain"), + Domain: maputil.GetString(options.ProviderExtendedConfig, "domain"), }) return deployer, err @@ -469,7 +489,7 @@ func createDeployer(options *deployerOptions) (deployer.Deployer, error) { } } - case domain.DeployProviderTypeCacheFly: + case domain.DeploymentProviderTypeCacheFly: { access := domain.AccessConfigForCacheFly{} if err := maputil.Populate(options.ProviderAccessConfig, &access); err != nil { @@ -482,7 +502,7 @@ func createDeployer(options *deployerOptions) (deployer.Deployer, error) { return deployer, err } - case domain.DeployProviderTypeCdnfly: + case domain.DeploymentProviderTypeCdnfly: { access := domain.AccessConfigForCdnfly{} if err := maputil.Populate(options.ProviderAccessConfig, &access); err != nil { @@ -490,17 +510,18 @@ func createDeployer(options *deployerOptions) (deployer.Deployer, error) { } deployer, err := pCdnfly.NewDeployer(&pCdnfly.DeployerConfig{ - ApiUrl: access.ApiUrl, - ApiKey: access.ApiKey, - ApiSecret: access.ApiSecret, - ResourceType: pCdnfly.ResourceType(maputil.GetOrDefaultString(options.ProviderDeployConfig, "resourceType", string(pCdnfly.RESOURCE_TYPE_SITE))), - SiteId: maputil.GetString(options.ProviderDeployConfig, "siteId"), - CertificateId: maputil.GetString(options.ProviderDeployConfig, "certificateId"), + ApiUrl: access.ApiUrl, + ApiKey: access.ApiKey, + ApiSecret: access.ApiSecret, + AllowInsecureConnections: access.AllowInsecureConnections, + ResourceType: pCdnfly.ResourceType(maputil.GetOrDefaultString(options.ProviderExtendedConfig, "resourceType", string(pCdnfly.RESOURCE_TYPE_SITE))), + SiteId: maputil.GetString(options.ProviderExtendedConfig, "siteId"), + CertificateId: maputil.GetString(options.ProviderExtendedConfig, "certificateId"), }) return deployer, err } - case domain.DeployProviderTypeDogeCloudCDN: + case domain.DeploymentProviderTypeDogeCloudCDN: { access := domain.AccessConfigForDogeCloud{} if err := maputil.Populate(options.ProviderAccessConfig, &access); err != nil { @@ -510,12 +531,12 @@ func createDeployer(options *deployerOptions) (deployer.Deployer, error) { deployer, err := pDogeCDN.NewDeployer(&pDogeCDN.DeployerConfig{ AccessKey: access.AccessKey, SecretKey: access.SecretKey, - Domain: maputil.GetString(options.ProviderDeployConfig, "domain"), + Domain: maputil.GetString(options.ProviderExtendedConfig, "domain"), }) return deployer, err } - case domain.DeployProviderTypeEdgioApplications: + case domain.DeploymentProviderTypeEdgioApplications: { access := domain.AccessConfigForEdgio{} if err := maputil.Populate(options.ProviderAccessConfig, &access); err != nil { @@ -525,12 +546,12 @@ func createDeployer(options *deployerOptions) (deployer.Deployer, error) { deployer, err := pEdgioApplications.NewDeployer(&pEdgioApplications.DeployerConfig{ ClientId: access.ClientId, ClientSecret: access.ClientSecret, - EnvironmentId: maputil.GetString(options.ProviderDeployConfig, "environmentId"), + EnvironmentId: maputil.GetString(options.ProviderExtendedConfig, "environmentId"), }) return deployer, err } - case domain.DeployProviderTypeGcoreCDN: + case domain.DeploymentProviderTypeGcoreCDN: { access := domain.AccessConfigForGcore{} if err := maputil.Populate(options.ProviderAccessConfig, &access); err != nil { @@ -538,10 +559,10 @@ func createDeployer(options *deployerOptions) (deployer.Deployer, error) { } switch options.Provider { - case domain.DeployProviderTypeGcoreCDN: + case domain.DeploymentProviderTypeGcoreCDN: deployer, err := pGcoreCDN.NewDeployer(&pGcoreCDN.DeployerConfig{ ApiToken: access.ApiToken, - ResourceId: maputil.GetInt64(options.ProviderDeployConfig, "resourceId"), + ResourceId: maputil.GetInt64(options.ProviderExtendedConfig, "resourceId"), }) return deployer, err @@ -550,7 +571,25 @@ func createDeployer(options *deployerOptions) (deployer.Deployer, error) { } } - case domain.DeployProviderTypeHuaweiCloudCDN, domain.DeployProviderTypeHuaweiCloudELB, domain.DeployProviderTypeHuaweiCloudSCM, domain.DeployProviderTypeHuaweiCloudWAF: + case domain.DeploymentProviderTypeGoEdge: + { + access := domain.AccessConfigForGoEdge{} + if err := maputil.Populate(options.ProviderAccessConfig, &access); err != nil { + return nil, fmt.Errorf("failed to populate provider access config: %w", err) + } + + deployer, err := pGoEdge.NewDeployer(&pGoEdge.DeployerConfig{ + ApiUrl: access.ApiUrl, + AccessKeyId: access.AccessKeyId, + AccessKey: access.AccessKey, + AllowInsecureConnections: access.AllowInsecureConnections, + ResourceType: pGoEdge.ResourceType(maputil.GetString(options.ProviderExtendedConfig, "resourceType")), + CertificateId: maputil.GetInt64(options.ProviderExtendedConfig, "certificateId"), + }) + return deployer, err + } + + case domain.DeploymentProviderTypeHuaweiCloudCDN, domain.DeploymentProviderTypeHuaweiCloudELB, domain.DeploymentProviderTypeHuaweiCloudSCM, domain.DeploymentProviderTypeHuaweiCloudWAF: { access := domain.AccessConfigForHuaweiCloud{} if err := maputil.Populate(options.ProviderAccessConfig, &access); err != nil { @@ -558,42 +597,42 @@ func createDeployer(options *deployerOptions) (deployer.Deployer, error) { } switch options.Provider { - case domain.DeployProviderTypeHuaweiCloudCDN: + case domain.DeploymentProviderTypeHuaweiCloudCDN: deployer, err := pHuaweiCloudCDN.NewDeployer(&pHuaweiCloudCDN.DeployerConfig{ AccessKeyId: access.AccessKeyId, SecretAccessKey: access.SecretAccessKey, - Region: maputil.GetString(options.ProviderDeployConfig, "region"), - Domain: maputil.GetString(options.ProviderDeployConfig, "domain"), + Region: maputil.GetString(options.ProviderExtendedConfig, "region"), + Domain: maputil.GetString(options.ProviderExtendedConfig, "domain"), }) return deployer, err - case domain.DeployProviderTypeHuaweiCloudELB: + case domain.DeploymentProviderTypeHuaweiCloudELB: deployer, err := pHuaweiCloudELB.NewDeployer(&pHuaweiCloudELB.DeployerConfig{ AccessKeyId: access.AccessKeyId, SecretAccessKey: access.SecretAccessKey, - Region: maputil.GetString(options.ProviderDeployConfig, "region"), - ResourceType: pHuaweiCloudELB.ResourceType(maputil.GetString(options.ProviderDeployConfig, "resourceType")), - CertificateId: maputil.GetString(options.ProviderDeployConfig, "certificateId"), - LoadbalancerId: maputil.GetString(options.ProviderDeployConfig, "loadbalancerId"), - ListenerId: maputil.GetString(options.ProviderDeployConfig, "listenerId"), + Region: maputil.GetString(options.ProviderExtendedConfig, "region"), + ResourceType: pHuaweiCloudELB.ResourceType(maputil.GetString(options.ProviderExtendedConfig, "resourceType")), + CertificateId: maputil.GetString(options.ProviderExtendedConfig, "certificateId"), + LoadbalancerId: maputil.GetString(options.ProviderExtendedConfig, "loadbalancerId"), + ListenerId: maputil.GetString(options.ProviderExtendedConfig, "listenerId"), }) return deployer, err - case domain.DeployProviderTypeHuaweiCloudSCM: + case domain.DeploymentProviderTypeHuaweiCloudSCM: deployer, err := pHuaweiCloudSCM.NewDeployer(&pHuaweiCloudSCM.DeployerConfig{ AccessKeyId: access.AccessKeyId, SecretAccessKey: access.SecretAccessKey, }) return deployer, err - case domain.DeployProviderTypeHuaweiCloudWAF: + case domain.DeploymentProviderTypeHuaweiCloudWAF: deployer, err := pHuaweiCloudWAF.NewDeployer(&pHuaweiCloudWAF.DeployerConfig{ AccessKeyId: access.AccessKeyId, SecretAccessKey: access.SecretAccessKey, - Region: maputil.GetString(options.ProviderDeployConfig, "region"), - ResourceType: pHuaweiCloudWAF.ResourceType(maputil.GetString(options.ProviderDeployConfig, "resourceType")), - CertificateId: maputil.GetString(options.ProviderDeployConfig, "certificateId"), - Domain: maputil.GetString(options.ProviderDeployConfig, "domain"), + Region: maputil.GetString(options.ProviderExtendedConfig, "region"), + ResourceType: pHuaweiCloudWAF.ResourceType(maputil.GetString(options.ProviderExtendedConfig, "resourceType")), + CertificateId: maputil.GetString(options.ProviderExtendedConfig, "certificateId"), + Domain: maputil.GetString(options.ProviderExtendedConfig, "domain"), }) return deployer, err @@ -602,7 +641,7 @@ func createDeployer(options *deployerOptions) (deployer.Deployer, error) { } } - case domain.DeployProviderTypeJDCloudALB, domain.DeployProviderTypeJDCloudCDN, domain.DeployProviderTypeJDCloudLive, domain.DeployProviderTypeJDCloudVOD: + case domain.DeploymentProviderTypeJDCloudALB, domain.DeploymentProviderTypeJDCloudCDN, domain.DeploymentProviderTypeJDCloudLive, domain.DeploymentProviderTypeJDCloudVOD: { access := domain.AccessConfigForJDCloud{} if err := maputil.Populate(options.ProviderAccessConfig, &access); err != nil { @@ -610,38 +649,38 @@ func createDeployer(options *deployerOptions) (deployer.Deployer, error) { } switch options.Provider { - case domain.DeployProviderTypeJDCloudALB: + case domain.DeploymentProviderTypeJDCloudALB: deployer, err := pJDCloudALB.NewDeployer(&pJDCloudALB.DeployerConfig{ AccessKeyId: access.AccessKeyId, AccessKeySecret: access.AccessKeySecret, - RegionId: maputil.GetString(options.ProviderDeployConfig, "regionId"), - ResourceType: pJDCloudALB.ResourceType(maputil.GetString(options.ProviderDeployConfig, "resourceType")), - LoadbalancerId: maputil.GetString(options.ProviderDeployConfig, "loadbalancerId"), - ListenerId: maputil.GetString(options.ProviderDeployConfig, "listenerId"), + RegionId: maputil.GetString(options.ProviderExtendedConfig, "regionId"), + ResourceType: pJDCloudALB.ResourceType(maputil.GetString(options.ProviderExtendedConfig, "resourceType")), + LoadbalancerId: maputil.GetString(options.ProviderExtendedConfig, "loadbalancerId"), + ListenerId: maputil.GetString(options.ProviderExtendedConfig, "listenerId"), }) return deployer, err - case domain.DeployProviderTypeJDCloudCDN: + case domain.DeploymentProviderTypeJDCloudCDN: deployer, err := pJDCloudCDN.NewDeployer(&pJDCloudCDN.DeployerConfig{ AccessKeyId: access.AccessKeyId, AccessKeySecret: access.AccessKeySecret, - Domain: maputil.GetString(options.ProviderDeployConfig, "domain"), + Domain: maputil.GetString(options.ProviderExtendedConfig, "domain"), }) return deployer, err - case domain.DeployProviderTypeJDCloudLive: + case domain.DeploymentProviderTypeJDCloudLive: deployer, err := pJDCloudLive.NewDeployer(&pJDCloudLive.DeployerConfig{ AccessKeyId: access.AccessKeyId, AccessKeySecret: access.AccessKeySecret, - Domain: maputil.GetString(options.ProviderDeployConfig, "domain"), + Domain: maputil.GetString(options.ProviderExtendedConfig, "domain"), }) return deployer, err - case domain.DeployProviderTypeJDCloudVOD: + case domain.DeploymentProviderTypeJDCloudVOD: deployer, err := pJDCloudVOD.NewDeployer(&pJDCloudVOD.DeployerConfig{ AccessKeyId: access.AccessKeyId, AccessKeySecret: access.AccessKeySecret, - Domain: maputil.GetString(options.ProviderDeployConfig, "domain"), + Domain: maputil.GetString(options.ProviderExtendedConfig, "domain"), }) return deployer, err @@ -650,24 +689,24 @@ func createDeployer(options *deployerOptions) (deployer.Deployer, error) { } } - case domain.DeployProviderTypeLocal: + case domain.DeploymentProviderTypeLocal: { deployer, err := pLocal.NewDeployer(&pLocal.DeployerConfig{ - ShellEnv: pLocal.ShellEnvType(maputil.GetString(options.ProviderDeployConfig, "shellEnv")), - PreCommand: maputil.GetString(options.ProviderDeployConfig, "preCommand"), - PostCommand: maputil.GetString(options.ProviderDeployConfig, "postCommand"), - OutputFormat: pLocal.OutputFormatType(maputil.GetOrDefaultString(options.ProviderDeployConfig, "format", string(pLocal.OUTPUT_FORMAT_PEM))), - OutputCertPath: maputil.GetString(options.ProviderDeployConfig, "certPath"), - OutputKeyPath: maputil.GetString(options.ProviderDeployConfig, "keyPath"), - PfxPassword: maputil.GetString(options.ProviderDeployConfig, "pfxPassword"), - JksAlias: maputil.GetString(options.ProviderDeployConfig, "jksAlias"), - JksKeypass: maputil.GetString(options.ProviderDeployConfig, "jksKeypass"), - JksStorepass: maputil.GetString(options.ProviderDeployConfig, "jksStorepass"), + ShellEnv: pLocal.ShellEnvType(maputil.GetString(options.ProviderExtendedConfig, "shellEnv")), + PreCommand: maputil.GetString(options.ProviderExtendedConfig, "preCommand"), + PostCommand: maputil.GetString(options.ProviderExtendedConfig, "postCommand"), + OutputFormat: pLocal.OutputFormatType(maputil.GetOrDefaultString(options.ProviderExtendedConfig, "format", string(pLocal.OUTPUT_FORMAT_PEM))), + OutputCertPath: maputil.GetString(options.ProviderExtendedConfig, "certPath"), + OutputKeyPath: maputil.GetString(options.ProviderExtendedConfig, "keyPath"), + PfxPassword: maputil.GetString(options.ProviderExtendedConfig, "pfxPassword"), + JksAlias: maputil.GetString(options.ProviderExtendedConfig, "jksAlias"), + JksKeypass: maputil.GetString(options.ProviderExtendedConfig, "jksKeypass"), + JksStorepass: maputil.GetString(options.ProviderExtendedConfig, "jksStorepass"), }) return deployer, err } - case domain.DeployProviderTypeKubernetesSecret: + case domain.DeploymentProviderTypeKubernetesSecret: { access := domain.AccessConfigForKubernetes{} if err := maputil.Populate(options.ProviderAccessConfig, &access); err != nil { @@ -676,16 +715,34 @@ func createDeployer(options *deployerOptions) (deployer.Deployer, error) { deployer, err := pK8sSecret.NewDeployer(&pK8sSecret.DeployerConfig{ KubeConfig: access.KubeConfig, - Namespace: maputil.GetOrDefaultString(options.ProviderDeployConfig, "namespace", "default"), - SecretName: maputil.GetString(options.ProviderDeployConfig, "secretName"), - SecretType: maputil.GetOrDefaultString(options.ProviderDeployConfig, "secretType", "kubernetes.io/tls"), - SecretDataKeyForCrt: maputil.GetOrDefaultString(options.ProviderDeployConfig, "secretDataKeyForCrt", "tls.crt"), - SecretDataKeyForKey: maputil.GetOrDefaultString(options.ProviderDeployConfig, "secretDataKeyForKey", "tls.key"), + Namespace: maputil.GetOrDefaultString(options.ProviderExtendedConfig, "namespace", "default"), + SecretName: maputil.GetString(options.ProviderExtendedConfig, "secretName"), + SecretType: maputil.GetOrDefaultString(options.ProviderExtendedConfig, "secretType", "kubernetes.io/tls"), + SecretDataKeyForCrt: maputil.GetOrDefaultString(options.ProviderExtendedConfig, "secretDataKeyForCrt", "tls.crt"), + SecretDataKeyForKey: maputil.GetOrDefaultString(options.ProviderExtendedConfig, "secretDataKeyForKey", "tls.key"), }) return deployer, err } - case domain.DeployProviderTypeQiniuCDN, domain.DeployProviderTypeQiniuKodo, domain.DeployProviderTypeQiniuPili: + case domain.DeploymentProviderTypeProxmoxVE: + { + access := domain.AccessConfigForProxmoxVE{} + if err := maputil.Populate(options.ProviderAccessConfig, &access); err != nil { + return nil, fmt.Errorf("failed to populate provider access config: %w", err) + } + + deployer, err := pProxmoxVE.NewDeployer(&pProxmoxVE.DeployerConfig{ + ApiUrl: access.ApiUrl, + ApiToken: access.ApiToken, + ApiTokenSecret: access.ApiTokenSecret, + AllowInsecureConnections: access.AllowInsecureConnections, + NodeName: maputil.GetString(options.ProviderExtendedConfig, "nodeName"), + AutoRestart: maputil.GetBool(options.ProviderExtendedConfig, "autoRestart"), + }) + return deployer, err + } + + case domain.DeploymentProviderTypeQiniuCDN, domain.DeploymentProviderTypeQiniuKodo, domain.DeploymentProviderTypeQiniuPili: { access := domain.AccessConfigForQiniu{} if err := maputil.Populate(options.ProviderAccessConfig, &access); err != nil { @@ -693,20 +750,20 @@ func createDeployer(options *deployerOptions) (deployer.Deployer, error) { } switch options.Provider { - case domain.DeployProviderTypeQiniuCDN, domain.DeployProviderTypeQiniuKodo: + case domain.DeploymentProviderTypeQiniuCDN, domain.DeploymentProviderTypeQiniuKodo: deployer, err := pQiniuCDN.NewDeployer(&pQiniuCDN.DeployerConfig{ AccessKey: access.AccessKey, SecretKey: access.SecretKey, - Domain: maputil.GetString(options.ProviderDeployConfig, "domain"), + Domain: maputil.GetString(options.ProviderExtendedConfig, "domain"), }) return deployer, err - case domain.DeployProviderTypeQiniuPili: + case domain.DeploymentProviderTypeQiniuPili: deployer, err := pQiniuPili.NewDeployer(&pQiniuPili.DeployerConfig{ AccessKey: access.AccessKey, SecretKey: access.SecretKey, - Hub: maputil.GetString(options.ProviderDeployConfig, "hub"), - Domain: maputil.GetString(options.ProviderDeployConfig, "domain"), + Hub: maputil.GetString(options.ProviderExtendedConfig, "hub"), + Domain: maputil.GetString(options.ProviderExtendedConfig, "domain"), }) return deployer, err @@ -715,7 +772,7 @@ func createDeployer(options *deployerOptions) (deployer.Deployer, error) { } } - case domain.DeployProviderTypeRainYunRCDN: + case domain.DeploymentProviderTypeRainYunRCDN: { access := domain.AccessConfigForRainYun{} if err := maputil.Populate(options.ProviderAccessConfig, &access); err != nil { @@ -723,11 +780,11 @@ func createDeployer(options *deployerOptions) (deployer.Deployer, error) { } switch options.Provider { - case domain.DeployProviderTypeTencentCloudCDN: + case domain.DeploymentProviderTypeTencentCloudCDN: deployer, err := pRainYunRCDN.NewDeployer(&pRainYunRCDN.DeployerConfig{ ApiKey: access.ApiKey, - InstanceId: maputil.GetInt32(options.ProviderDeployConfig, "instanceId"), - Domain: maputil.GetString(options.ProviderDeployConfig, "domain"), + InstanceId: maputil.GetInt32(options.ProviderExtendedConfig, "instanceId"), + Domain: maputil.GetString(options.ProviderExtendedConfig, "domain"), }) return deployer, err @@ -736,7 +793,7 @@ func createDeployer(options *deployerOptions) (deployer.Deployer, error) { } } - case domain.DeployProviderTypeSafeLine: + case domain.DeploymentProviderTypeSafeLine: { access := domain.AccessConfigForSafeLine{} if err := maputil.Populate(options.ProviderAccessConfig, &access); err != nil { @@ -747,13 +804,13 @@ func createDeployer(options *deployerOptions) (deployer.Deployer, error) { ApiUrl: access.ApiUrl, ApiToken: access.ApiToken, AllowInsecureConnections: access.AllowInsecureConnections, - ResourceType: pSafeLine.ResourceType(maputil.GetString(options.ProviderDeployConfig, "resourceType")), - CertificateId: maputil.GetInt32(options.ProviderDeployConfig, "certificateId"), + ResourceType: pSafeLine.ResourceType(maputil.GetString(options.ProviderExtendedConfig, "resourceType")), + CertificateId: maputil.GetInt32(options.ProviderExtendedConfig, "certificateId"), }) return deployer, err } - case domain.DeployProviderTypeSSH: + case domain.DeploymentProviderTypeSSH: { access := domain.AccessConfigForSSH{} if err := maputil.Populate(options.ProviderAccessConfig, &access); err != nil { @@ -767,21 +824,21 @@ func createDeployer(options *deployerOptions) (deployer.Deployer, error) { SshPassword: access.Password, SshKey: access.Key, SshKeyPassphrase: access.KeyPassphrase, - UseSCP: maputil.GetBool(options.ProviderDeployConfig, "useSCP"), - PreCommand: maputil.GetString(options.ProviderDeployConfig, "preCommand"), - PostCommand: maputil.GetString(options.ProviderDeployConfig, "postCommand"), - OutputFormat: pSSH.OutputFormatType(maputil.GetOrDefaultString(options.ProviderDeployConfig, "format", string(pSSH.OUTPUT_FORMAT_PEM))), - OutputCertPath: maputil.GetString(options.ProviderDeployConfig, "certPath"), - OutputKeyPath: maputil.GetString(options.ProviderDeployConfig, "keyPath"), - PfxPassword: maputil.GetString(options.ProviderDeployConfig, "pfxPassword"), - JksAlias: maputil.GetString(options.ProviderDeployConfig, "jksAlias"), - JksKeypass: maputil.GetString(options.ProviderDeployConfig, "jksKeypass"), - JksStorepass: maputil.GetString(options.ProviderDeployConfig, "jksStorepass"), + UseSCP: maputil.GetBool(options.ProviderExtendedConfig, "useSCP"), + PreCommand: maputil.GetString(options.ProviderExtendedConfig, "preCommand"), + PostCommand: maputil.GetString(options.ProviderExtendedConfig, "postCommand"), + OutputFormat: pSSH.OutputFormatType(maputil.GetOrDefaultString(options.ProviderExtendedConfig, "format", string(pSSH.OUTPUT_FORMAT_PEM))), + OutputCertPath: maputil.GetString(options.ProviderExtendedConfig, "certPath"), + OutputKeyPath: maputil.GetString(options.ProviderExtendedConfig, "keyPath"), + PfxPassword: maputil.GetString(options.ProviderExtendedConfig, "pfxPassword"), + JksAlias: maputil.GetString(options.ProviderExtendedConfig, "jksAlias"), + JksKeypass: maputil.GetString(options.ProviderExtendedConfig, "jksKeypass"), + JksStorepass: maputil.GetString(options.ProviderExtendedConfig, "jksStorepass"), }) return deployer, err } - case domain.DeployProviderTypeTencentCloudCDN, domain.DeployProviderTypeTencentCloudCLB, domain.DeployProviderTypeTencentCloudCOS, domain.DeployProviderTypeTencentCloudCSS, domain.DeployProviderTypeTencentCloudECDN, domain.DeployProviderTypeTencentCloudEO, domain.DeployProviderTypeTencentCloudSCF, domain.DeployProviderTypeTencentCloudSSL, domain.DeployProviderTypeTencentCloudSSLDeploy, domain.DeployProviderTypeTencentCloudVOD, domain.DeployProviderTypeTencentCloudWAF: + case domain.DeploymentProviderTypeTencentCloudCDN, domain.DeploymentProviderTypeTencentCloudCLB, domain.DeploymentProviderTypeTencentCloudCOS, domain.DeploymentProviderTypeTencentCloudCSS, domain.DeploymentProviderTypeTencentCloudECDN, domain.DeploymentProviderTypeTencentCloudEO, domain.DeploymentProviderTypeTencentCloudSCF, domain.DeploymentProviderTypeTencentCloudSSL, domain.DeploymentProviderTypeTencentCloudSSLDeploy, domain.DeploymentProviderTypeTencentCloudVOD, domain.DeploymentProviderTypeTencentCloudWAF: { access := domain.AccessConfigForTencentCloud{} if err := maputil.Populate(options.ProviderAccessConfig, &access); err != nil { @@ -789,103 +846,103 @@ func createDeployer(options *deployerOptions) (deployer.Deployer, error) { } switch options.Provider { - case domain.DeployProviderTypeTencentCloudCDN: + case domain.DeploymentProviderTypeTencentCloudCDN: deployer, err := pTencentCloudCDN.NewDeployer(&pTencentCloudCDN.DeployerConfig{ SecretId: access.SecretId, SecretKey: access.SecretKey, - Domain: maputil.GetString(options.ProviderDeployConfig, "domain"), + Domain: maputil.GetString(options.ProviderExtendedConfig, "domain"), }) return deployer, err - case domain.DeployProviderTypeTencentCloudCLB: + case domain.DeploymentProviderTypeTencentCloudCLB: deployer, err := pTencentCloudCLB.NewDeployer(&pTencentCloudCLB.DeployerConfig{ SecretId: access.SecretId, SecretKey: access.SecretKey, - Region: maputil.GetString(options.ProviderDeployConfig, "region"), - ResourceType: pTencentCloudCLB.ResourceType(maputil.GetString(options.ProviderDeployConfig, "resourceType")), - LoadbalancerId: maputil.GetString(options.ProviderDeployConfig, "loadbalancerId"), - ListenerId: maputil.GetString(options.ProviderDeployConfig, "listenerId"), - Domain: maputil.GetString(options.ProviderDeployConfig, "domain"), + Region: maputil.GetString(options.ProviderExtendedConfig, "region"), + ResourceType: pTencentCloudCLB.ResourceType(maputil.GetString(options.ProviderExtendedConfig, "resourceType")), + LoadbalancerId: maputil.GetString(options.ProviderExtendedConfig, "loadbalancerId"), + ListenerId: maputil.GetString(options.ProviderExtendedConfig, "listenerId"), + Domain: maputil.GetString(options.ProviderExtendedConfig, "domain"), }) return deployer, err - case domain.DeployProviderTypeTencentCloudCOS: + case domain.DeploymentProviderTypeTencentCloudCOS: deployer, err := pTencentCloudCOS.NewDeployer(&pTencentCloudCOS.DeployerConfig{ SecretId: access.SecretId, SecretKey: access.SecretKey, - Region: maputil.GetString(options.ProviderDeployConfig, "region"), - Bucket: maputil.GetString(options.ProviderDeployConfig, "bucket"), - Domain: maputil.GetString(options.ProviderDeployConfig, "domain"), + Region: maputil.GetString(options.ProviderExtendedConfig, "region"), + Bucket: maputil.GetString(options.ProviderExtendedConfig, "bucket"), + Domain: maputil.GetString(options.ProviderExtendedConfig, "domain"), }) return deployer, err - case domain.DeployProviderTypeTencentCloudCSS: + case domain.DeploymentProviderTypeTencentCloudCSS: deployer, err := pTencentCloudCSS.NewDeployer(&pTencentCloudCSS.DeployerConfig{ SecretId: access.SecretId, SecretKey: access.SecretKey, - Domain: maputil.GetString(options.ProviderDeployConfig, "domain"), + Domain: maputil.GetString(options.ProviderExtendedConfig, "domain"), }) return deployer, err - case domain.DeployProviderTypeTencentCloudECDN: + case domain.DeploymentProviderTypeTencentCloudECDN: deployer, err := pTencentCloudECDN.NewDeployer(&pTencentCloudECDN.DeployerConfig{ SecretId: access.SecretId, SecretKey: access.SecretKey, - Domain: maputil.GetString(options.ProviderDeployConfig, "domain"), + Domain: maputil.GetString(options.ProviderExtendedConfig, "domain"), }) return deployer, err - case domain.DeployProviderTypeTencentCloudEO: + case domain.DeploymentProviderTypeTencentCloudEO: deployer, err := pTencentCloudEO.NewDeployer(&pTencentCloudEO.DeployerConfig{ SecretId: access.SecretId, SecretKey: access.SecretKey, - ZoneId: maputil.GetString(options.ProviderDeployConfig, "zoneId"), - Domain: maputil.GetString(options.ProviderDeployConfig, "domain"), + ZoneId: maputil.GetString(options.ProviderExtendedConfig, "zoneId"), + Domain: maputil.GetString(options.ProviderExtendedConfig, "domain"), }) return deployer, err - case domain.DeployProviderTypeTencentCloudSCF: + case domain.DeploymentProviderTypeTencentCloudSCF: deployer, err := pTencentCloudSCF.NewDeployer(&pTencentCloudSCF.DeployerConfig{ SecretId: access.SecretId, SecretKey: access.SecretKey, - Region: maputil.GetString(options.ProviderDeployConfig, "region"), - Domain: maputil.GetString(options.ProviderDeployConfig, "domain"), + Region: maputil.GetString(options.ProviderExtendedConfig, "region"), + Domain: maputil.GetString(options.ProviderExtendedConfig, "domain"), }) return deployer, err - case domain.DeployProviderTypeTencentCloudSSL: + case domain.DeploymentProviderTypeTencentCloudSSL: deployer, err := pTencentCloudSSL.NewDeployer(&pTencentCloudSSL.DeployerConfig{ SecretId: access.SecretId, SecretKey: access.SecretKey, }) return deployer, err - case domain.DeployProviderTypeTencentCloudSSLDeploy: + case domain.DeploymentProviderTypeTencentCloudSSLDeploy: deployer, err := pTencentCloudSSLDeploy.NewDeployer(&pTencentCloudSSLDeploy.DeployerConfig{ SecretId: access.SecretId, SecretKey: access.SecretKey, - Region: maputil.GetString(options.ProviderDeployConfig, "region"), - ResourceType: maputil.GetString(options.ProviderDeployConfig, "resourceType"), - ResourceIds: sliceutil.Filter(strings.Split(maputil.GetString(options.ProviderDeployConfig, "resourceIds"), ";"), func(s string) bool { return s != "" }), + Region: maputil.GetString(options.ProviderExtendedConfig, "region"), + ResourceType: maputil.GetString(options.ProviderExtendedConfig, "resourceType"), + ResourceIds: sliceutil.Filter(strings.Split(maputil.GetString(options.ProviderExtendedConfig, "resourceIds"), ";"), func(s string) bool { return s != "" }), }) return deployer, err - case domain.DeployProviderTypeTencentCloudVOD: + case domain.DeploymentProviderTypeTencentCloudVOD: deployer, err := pTencentCloudVOD.NewDeployer(&pTencentCloudVOD.DeployerConfig{ SecretId: access.SecretId, SecretKey: access.SecretKey, - SubAppId: maputil.GetInt64(options.ProviderDeployConfig, "subAppId"), - Domain: maputil.GetString(options.ProviderDeployConfig, "domain"), + SubAppId: maputil.GetInt64(options.ProviderExtendedConfig, "subAppId"), + Domain: maputil.GetString(options.ProviderExtendedConfig, "domain"), }) return deployer, err - case domain.DeployProviderTypeTencentCloudWAF: + case domain.DeploymentProviderTypeTencentCloudWAF: deployer, err := pTencentCloudWAF.NewDeployer(&pTencentCloudWAF.DeployerConfig{ SecretId: access.SecretId, SecretKey: access.SecretKey, - Domain: maputil.GetString(options.ProviderDeployConfig, "domain"), - DomainId: maputil.GetString(options.ProviderDeployConfig, "domainId"), - InstanceId: maputil.GetString(options.ProviderDeployConfig, "instanceId"), + Domain: maputil.GetString(options.ProviderExtendedConfig, "domain"), + DomainId: maputil.GetString(options.ProviderExtendedConfig, "domainId"), + InstanceId: maputil.GetString(options.ProviderExtendedConfig, "instanceId"), }) return deployer, err @@ -894,7 +951,7 @@ func createDeployer(options *deployerOptions) (deployer.Deployer, error) { } } - case domain.DeployProviderTypeUCloudUCDN, domain.DeployProviderTypeUCloudUS3: + case domain.DeploymentProviderTypeUCloudUCDN, domain.DeploymentProviderTypeUCloudUS3: { access := domain.AccessConfigForUCloud{} if err := maputil.Populate(options.ProviderAccessConfig, &access); err != nil { @@ -902,23 +959,23 @@ func createDeployer(options *deployerOptions) (deployer.Deployer, error) { } switch options.Provider { - case domain.DeployProviderTypeUCloudUCDN: + case domain.DeploymentProviderTypeUCloudUCDN: deployer, err := pUCloudUCDN.NewDeployer(&pUCloudUCDN.DeployerConfig{ PrivateKey: access.PrivateKey, PublicKey: access.PublicKey, ProjectId: access.ProjectId, - DomainId: maputil.GetString(options.ProviderDeployConfig, "domainId"), + DomainId: maputil.GetString(options.ProviderExtendedConfig, "domainId"), }) return deployer, err - case domain.DeployProviderTypeUCloudUS3: + case domain.DeploymentProviderTypeUCloudUS3: deployer, err := pUCloudUS3.NewDeployer(&pUCloudUS3.DeployerConfig{ PrivateKey: access.PrivateKey, PublicKey: access.PublicKey, ProjectId: access.ProjectId, - Region: maputil.GetString(options.ProviderDeployConfig, "region"), - Bucket: maputil.GetString(options.ProviderDeployConfig, "bucket"), - Domain: maputil.GetString(options.ProviderDeployConfig, "domain"), + Region: maputil.GetString(options.ProviderExtendedConfig, "region"), + Bucket: maputil.GetString(options.ProviderExtendedConfig, "bucket"), + Domain: maputil.GetString(options.ProviderExtendedConfig, "domain"), }) return deployer, err @@ -927,7 +984,7 @@ func createDeployer(options *deployerOptions) (deployer.Deployer, error) { } } - case domain.DeployProviderTypeUpyunCDN, domain.DeployProviderTypeUpyunFile: + case domain.DeploymentProviderTypeUpyunCDN, domain.DeploymentProviderTypeUpyunFile: { access := domain.AccessConfigForUpyun{} if err := maputil.Populate(options.ProviderAccessConfig, &access); err != nil { @@ -935,11 +992,11 @@ func createDeployer(options *deployerOptions) (deployer.Deployer, error) { } switch options.Provider { - case domain.DeployProviderTypeUpyunCDN, domain.DeployProviderTypeUpyunFile: + case domain.DeploymentProviderTypeUpyunCDN, domain.DeploymentProviderTypeUpyunFile: deployer, err := pUpyunCDN.NewDeployer(&pUpyunCDN.DeployerConfig{ Username: access.Username, Password: access.Password, - Domain: maputil.GetString(options.ProviderDeployConfig, "domain"), + Domain: maputil.GetString(options.ProviderExtendedConfig, "domain"), }) return deployer, err @@ -948,7 +1005,7 @@ func createDeployer(options *deployerOptions) (deployer.Deployer, error) { } } - case domain.DeployProviderTypeVolcEngineALB, domain.DeployProviderTypeVolcEngineCDN, domain.DeployProviderTypeVolcEngineCertCenter, domain.DeployProviderTypeVolcEngineCLB, domain.DeployProviderTypeVolcEngineDCDN, domain.DeployProviderTypeVolcEngineImageX, domain.DeployProviderTypeVolcEngineLive, domain.DeployProviderTypeVolcEngineTOS: + case domain.DeploymentProviderTypeVolcEngineALB, domain.DeploymentProviderTypeVolcEngineCDN, domain.DeploymentProviderTypeVolcEngineCertCenter, domain.DeploymentProviderTypeVolcEngineCLB, domain.DeploymentProviderTypeVolcEngineDCDN, domain.DeploymentProviderTypeVolcEngineImageX, domain.DeploymentProviderTypeVolcEngineLive, domain.DeploymentProviderTypeVolcEngineTOS: { access := domain.AccessConfigForVolcEngine{} if err := maputil.Populate(options.ProviderAccessConfig, &access); err != nil { @@ -956,78 +1013,78 @@ func createDeployer(options *deployerOptions) (deployer.Deployer, error) { } switch options.Provider { - case domain.DeployProviderTypeVolcEngineALB: + case domain.DeploymentProviderTypeVolcEngineALB: deployer, err := pVolcEngineALB.NewDeployer(&pVolcEngineALB.DeployerConfig{ AccessKeyId: access.AccessKeyId, AccessKeySecret: access.SecretAccessKey, - Region: maputil.GetString(options.ProviderDeployConfig, "region"), - ResourceType: pVolcEngineALB.ResourceType(maputil.GetString(options.ProviderDeployConfig, "resourceType")), - LoadbalancerId: maputil.GetString(options.ProviderDeployConfig, "loadbalancerId"), - ListenerId: maputil.GetString(options.ProviderDeployConfig, "listenerId"), - Domain: maputil.GetString(options.ProviderDeployConfig, "domain"), + Region: maputil.GetString(options.ProviderExtendedConfig, "region"), + ResourceType: pVolcEngineALB.ResourceType(maputil.GetString(options.ProviderExtendedConfig, "resourceType")), + LoadbalancerId: maputil.GetString(options.ProviderExtendedConfig, "loadbalancerId"), + ListenerId: maputil.GetString(options.ProviderExtendedConfig, "listenerId"), + Domain: maputil.GetString(options.ProviderExtendedConfig, "domain"), }) return deployer, err - case domain.DeployProviderTypeVolcEngineCDN: + case domain.DeploymentProviderTypeVolcEngineCDN: deployer, err := pVolcEngineCDN.NewDeployer(&pVolcEngineCDN.DeployerConfig{ AccessKeyId: access.AccessKeyId, AccessKeySecret: access.SecretAccessKey, - Domain: maputil.GetString(options.ProviderDeployConfig, "domain"), + Domain: maputil.GetString(options.ProviderExtendedConfig, "domain"), }) return deployer, err - case domain.DeployProviderTypeVolcEngineCertCenter: + case domain.DeploymentProviderTypeVolcEngineCertCenter: deployer, err := pVolcEngineCertCenter.NewDeployer(&pVolcEngineCertCenter.DeployerConfig{ AccessKeyId: access.AccessKeyId, AccessKeySecret: access.SecretAccessKey, - Region: maputil.GetString(options.ProviderDeployConfig, "region"), + Region: maputil.GetString(options.ProviderExtendedConfig, "region"), }) return deployer, err - case domain.DeployProviderTypeVolcEngineCLB: + case domain.DeploymentProviderTypeVolcEngineCLB: deployer, err := pVolcEngineCLB.NewDeployer(&pVolcEngineCLB.DeployerConfig{ AccessKeyId: access.AccessKeyId, AccessKeySecret: access.SecretAccessKey, - Region: maputil.GetString(options.ProviderDeployConfig, "region"), - ResourceType: pVolcEngineCLB.ResourceType(maputil.GetString(options.ProviderDeployConfig, "resourceType")), - LoadbalancerId: maputil.GetString(options.ProviderDeployConfig, "loadbalancerId"), - ListenerId: maputil.GetString(options.ProviderDeployConfig, "listenerId"), + Region: maputil.GetString(options.ProviderExtendedConfig, "region"), + ResourceType: pVolcEngineCLB.ResourceType(maputil.GetString(options.ProviderExtendedConfig, "resourceType")), + LoadbalancerId: maputil.GetString(options.ProviderExtendedConfig, "loadbalancerId"), + ListenerId: maputil.GetString(options.ProviderExtendedConfig, "listenerId"), }) return deployer, err - case domain.DeployProviderTypeVolcEngineDCDN: + case domain.DeploymentProviderTypeVolcEngineDCDN: deployer, err := pVolcEngineDCDN.NewDeployer(&pVolcEngineDCDN.DeployerConfig{ AccessKeyId: access.AccessKeyId, AccessKeySecret: access.SecretAccessKey, - Domain: maputil.GetString(options.ProviderDeployConfig, "domain"), + Domain: maputil.GetString(options.ProviderExtendedConfig, "domain"), }) return deployer, err - case domain.DeployProviderTypeVolcEngineImageX: + case domain.DeploymentProviderTypeVolcEngineImageX: deployer, err := pVolcEngineImageX.NewDeployer(&pVolcEngineImageX.DeployerConfig{ AccessKeyId: access.AccessKeyId, AccessKeySecret: access.SecretAccessKey, - Region: maputil.GetString(options.ProviderDeployConfig, "region"), - ServiceId: maputil.GetString(options.ProviderDeployConfig, "serviceId"), - Domain: maputil.GetString(options.ProviderDeployConfig, "domain"), + Region: maputil.GetString(options.ProviderExtendedConfig, "region"), + ServiceId: maputil.GetString(options.ProviderExtendedConfig, "serviceId"), + Domain: maputil.GetString(options.ProviderExtendedConfig, "domain"), }) return deployer, err - case domain.DeployProviderTypeVolcEngineLive: + case domain.DeploymentProviderTypeVolcEngineLive: deployer, err := pVolcEngineLive.NewDeployer(&pVolcEngineLive.DeployerConfig{ AccessKeyId: access.AccessKeyId, AccessKeySecret: access.SecretAccessKey, - Domain: maputil.GetString(options.ProviderDeployConfig, "domain"), + Domain: maputil.GetString(options.ProviderExtendedConfig, "domain"), }) return deployer, err - case domain.DeployProviderTypeVolcEngineTOS: + case domain.DeploymentProviderTypeVolcEngineTOS: deployer, err := pVolcEngineTOS.NewDeployer(&pVolcEngineTOS.DeployerConfig{ AccessKeyId: access.AccessKeyId, AccessKeySecret: access.SecretAccessKey, - Region: maputil.GetString(options.ProviderDeployConfig, "region"), - Bucket: maputil.GetString(options.ProviderDeployConfig, "bucket"), - Domain: maputil.GetString(options.ProviderDeployConfig, "domain"), + Region: maputil.GetString(options.ProviderExtendedConfig, "region"), + Bucket: maputil.GetString(options.ProviderExtendedConfig, "bucket"), + Domain: maputil.GetString(options.ProviderExtendedConfig, "domain"), }) return deployer, err @@ -1036,7 +1093,7 @@ func createDeployer(options *deployerOptions) (deployer.Deployer, error) { } } - case domain.DeployProviderTypeWangsuCDNPro: + case domain.DeploymentProviderTypeWangsuCDNPro: { access := domain.AccessConfigForWangsu{} if err := maputil.Populate(options.ProviderAccessConfig, &access); err != nil { @@ -1044,15 +1101,15 @@ func createDeployer(options *deployerOptions) (deployer.Deployer, error) { } switch options.Provider { - case domain.DeployProviderTypeWangsuCDNPro: + case domain.DeploymentProviderTypeWangsuCDNPro: deployer, err := pWangsuCDNPro.NewDeployer(&pWangsuCDNPro.DeployerConfig{ AccessKeyId: access.AccessKeyId, AccessKeySecret: access.AccessKeySecret, ApiKey: access.ApiKey, - Environment: maputil.GetOrDefaultString(options.ProviderDeployConfig, "environment", "production"), - Domain: maputil.GetString(options.ProviderDeployConfig, "domain"), - CertificateId: maputil.GetString(options.ProviderDeployConfig, "certificateId"), - WebhookId: maputil.GetString(options.ProviderDeployConfig, "webhookId"), + Environment: maputil.GetOrDefaultString(options.ProviderExtendedConfig, "environment", "production"), + Domain: maputil.GetString(options.ProviderExtendedConfig, "domain"), + CertificateId: maputil.GetString(options.ProviderExtendedConfig, "certificateId"), + WebhookId: maputil.GetString(options.ProviderExtendedConfig, "webhookId"), }) return deployer, err @@ -1061,21 +1118,43 @@ func createDeployer(options *deployerOptions) (deployer.Deployer, error) { } } - case domain.DeployProviderTypeWebhook: + case domain.DeploymentProviderTypeWebhook: { access := domain.AccessConfigForWebhook{} if err := maputil.Populate(options.ProviderAccessConfig, &access); err != nil { return nil, fmt.Errorf("failed to populate provider access config: %w", err) } + mergedHeaders := make(map[string]string) + if defaultHeadersString := access.HeadersString; defaultHeadersString != "" { + h, err := httputil.ParseHeaders(defaultHeadersString) + if err != nil { + return nil, fmt.Errorf("failed to parse webhook headers: %w", err) + } + for key := range h { + mergedHeaders[http.CanonicalHeaderKey(key)] = h.Get(key) + } + } + if extendedHeadersString := maputil.GetString(options.ProviderExtendedConfig, "headers"); extendedHeadersString != "" { + h, err := httputil.ParseHeaders(extendedHeadersString) + if err != nil { + return nil, fmt.Errorf("failed to parse webhook headers: %w", err) + } + for key := range h { + mergedHeaders[http.CanonicalHeaderKey(key)] = h.Get(key) + } + } + deployer, err := pWebhook.NewDeployer(&pWebhook.DeployerConfig{ WebhookUrl: access.Url, - WebhookData: maputil.GetString(options.ProviderDeployConfig, "webhookData"), + WebhookData: maputil.GetOrDefaultString(options.ProviderExtendedConfig, "webhookData", access.DefaultDataForDeployment), + Method: access.Method, + Headers: mergedHeaders, AllowInsecureConnections: access.AllowInsecureConnections, }) return deployer, err } } - return nil, fmt.Errorf("unsupported deployer provider: %s", string(options.Provider)) + return nil, fmt.Errorf("unsupported deployer provider '%s'", string(options.Provider)) } diff --git a/internal/domain/access.go b/internal/domain/access.go index fdceae48..84afd292 100644 --- a/internal/domain/access.go +++ b/internal/domain/access.go @@ -11,6 +11,7 @@ type Access struct { Name string `json:"name" db:"name"` Provider string `json:"provider" db:"provider"` Config map[string]any `json:"config" db:"config"` + Reserve string `json:"reserve,omitempty" db:"reserve"` DeletedAt *time.Time `json:"deleted" db:"deleted"` } @@ -73,9 +74,10 @@ type AccessConfigForCacheFly struct { } type AccessConfigForCdnfly struct { - ApiUrl string `json:"apiUrl"` - ApiKey string `json:"apiKey"` - ApiSecret string `json:"apiSecret"` + ApiUrl string `json:"apiUrl"` + ApiKey string `json:"apiKey"` + ApiSecret string `json:"apiSecret"` + AllowInsecureConnections bool `json:"allowInsecureConnections,omitempty"` } type AccessConfigForCloudflare struct { @@ -97,6 +99,11 @@ type AccessConfigForDeSEC struct { Token string `json:"token"` } +type AccessConfigForDingTalkBot struct { + WebhookUrl string `json:"webhookUrl"` + Secret string `json:"secret"` +} + type AccessConfigForDNSLA struct { ApiId string `json:"apiId"` ApiSecret string `json:"apiSecret"` @@ -116,6 +123,16 @@ type AccessConfigForEdgio struct { ClientSecret string `json:"clientSecret"` } +type AccessConfigForEmail struct { + SmtpHost string `json:"smtpHost"` + SmtpPort int32 `json:"smtpPort"` + SmtpTls bool `json:"smtpTls"` + Username string `json:"username"` + Password string `json:"password"` + DefaultSenderAddress string `json:"defaultSenderAddress,omitempty"` + DefaultReceiverAddress string `json:"defaultReceiverAddress,omitempty"` +} + type AccessConfigForGcore struct { ApiToken string `json:"apiToken"` } @@ -130,6 +147,13 @@ type AccessConfigForGoDaddy struct { ApiSecret string `json:"apiSecret"` } +type AccessConfigForGoEdge struct { + ApiUrl string `json:"apiUrl"` + AccessKeyId string `json:"accessKeyId"` + AccessKey string `json:"accessKey"` + AllowInsecureConnections bool `json:"allowInsecureConnections,omitempty"` +} + type AccessConfigForGoogleTrustServices struct { EabKid string `json:"eabKid"` EabHmacKey string `json:"eabHmacKey"` @@ -149,6 +173,17 @@ type AccessConfigForKubernetes struct { KubeConfig string `json:"kubeConfig,omitempty"` } +type AccessConfigForLarkBot struct { + WebhookUrl string `json:"webhookUrl"` +} + +type AccessConfigForMattermost struct { + ServerUrl string `json:"serverUrl"` + Username string `json:"username"` + Password string `json:"password"` + DefaultChannelId string `json:"defaultChannelId,omitempty"` +} + type AccessConfigForNamecheap struct { Username string `json:"username"` ApiKey string `json:"apiKey"` @@ -173,8 +208,16 @@ type AccessConfigForPorkbun struct { } type AccessConfigForPowerDNS struct { - ApiUrl string `json:"apiUrl"` - ApiKey string `json:"apiKey"` + ApiUrl string `json:"apiUrl"` + ApiKey string `json:"apiKey"` + AllowInsecureConnections bool `json:"allowInsecureConnections,omitempty"` +} + +type AccessConfigForProxmoxVE struct { + ApiUrl string `json:"apiUrl"` + ApiToken string `json:"apiToken"` + ApiTokenSecret string `json:"apiTokenSecret,omitempty"` + AllowInsecureConnections bool `json:"allowInsecureConnections,omitempty"` } type AccessConfigForQiniu struct { @@ -206,6 +249,11 @@ type AccessConfigForSSLCom struct { EabHmacKey string `json:"eabHmacKey"` } +type AccessConfigForTelegram struct { + BotToken string `json:"botToken"` + DefaultChatId int64 `json:"defaultChatId,omitempty"` +} + type AccessConfigForTencentCloud struct { SecretId string `json:"secretId"` SecretKey string `json:"secretKey"` @@ -239,8 +287,16 @@ type AccessConfigForWangsu struct { } type AccessConfigForWebhook struct { - Url string `json:"url"` - AllowInsecureConnections bool `json:"allowInsecureConnections,omitempty"` + Url string `json:"url"` + Method string `json:"method,omitempty"` + HeadersString string `json:"headers,omitempty"` + AllowInsecureConnections bool `json:"allowInsecureConnections,omitempty"` + DefaultDataForDeployment string `json:"defaultDataForDeployment,omitempty"` + DefaultDataForNotification string `json:"defaultDataForNotification,omitempty"` +} + +type AccessConfigForWeComBot struct { + WebhookUrl string `json:"webhookUrl"` } type AccessConfigForWestcn struct { diff --git a/internal/domain/certificate.go b/internal/domain/certificate.go index 489af550..d2a998da 100644 --- a/internal/domain/certificate.go +++ b/internal/domain/certificate.go @@ -8,7 +8,7 @@ import ( "strings" "time" - "github.com/usual2970/certimate/internal/pkg/utils/certutil" + certutil "github.com/usual2970/certimate/internal/pkg/utils/cert" ) const CollectionNameCertificate = "certificate" diff --git a/internal/domain/dtos/certificate.go b/internal/domain/dtos/certificate.go index a1853df0..ce6b7d5e 100644 --- a/internal/domain/dtos/certificate.go +++ b/internal/domain/dtos/certificate.go @@ -1,4 +1,4 @@ -package dtos +package dtos type CertificateArchiveFileReq struct { CertificateId string `json:"-"` diff --git a/internal/domain/dtos/notify.go b/internal/domain/dtos/notify.go index 72c6cc79..ab72fff1 100644 --- a/internal/domain/dtos/notify.go +++ b/internal/domain/dtos/notify.go @@ -1,4 +1,4 @@ -package dtos +package dtos import "github.com/usual2970/certimate/internal/domain" diff --git a/internal/domain/dtos/workflow.go b/internal/domain/dtos/workflow.go index 3988220b..b0f75f58 100644 --- a/internal/domain/dtos/workflow.go +++ b/internal/domain/dtos/workflow.go @@ -1,4 +1,4 @@ -package dtos +package dtos import "github.com/usual2970/certimate/internal/domain" diff --git a/internal/domain/notify.go b/internal/domain/notify.go index 6142dae5..1a244e9b 100644 --- a/internal/domain/notify.go +++ b/internal/domain/notify.go @@ -8,6 +8,7 @@ type NotifyChannelType string 注意:如果追加新的常量值,请保持以 ASCII 排序。 NOTICE: If you add new constant, please keep ASCII order. */ +// Deprecated: v0.4.x 将废弃 const ( NotifyChannelTypeBark = NotifyChannelType("bark") NotifyChannelTypeDingTalk = NotifyChannelType("dingtalk") diff --git a/internal/domain/provider.go b/internal/domain/provider.go index 5c000b3d..728f89b6 100644 --- a/internal/domain/provider.go +++ b/internal/domain/provider.go @@ -1,4 +1,4 @@ -package domain +package domain type AccessProviderType string @@ -19,43 +19,50 @@ const ( AccessProviderTypeBaishan = AccessProviderType("baishan") AccessProviderTypeBaotaPanel = AccessProviderType("baotapanel") AccessProviderTypeBytePlus = AccessProviderType("byteplus") + AccessProviderTypeBunny = AccessProviderType("bunny") AccessProviderTypeBuypass = AccessProviderType("buypass") AccessProviderTypeCacheFly = AccessProviderType("cachefly") AccessProviderTypeCdnfly = AccessProviderType("cdnfly") AccessProviderTypeCloudflare = AccessProviderType("cloudflare") AccessProviderTypeClouDNS = AccessProviderType("cloudns") AccessProviderTypeCMCCCloud = AccessProviderType("cmcccloud") - AccessProviderTypeCTCCCloud = AccessProviderType("ctcccloud") // 联通云(预留) - AccessProviderTypeCUCCCloud = AccessProviderType("cucccloud") // 天翼云(预留) + AccessProviderTypeCTCCCloud = AccessProviderType("ctcccloud") // 天翼云(预留) + AccessProviderTypeCUCCCloud = AccessProviderType("cucccloud") // 联通云(预留) AccessProviderTypeDeSEC = AccessProviderType("desec") + AccessProviderTypeDingTalkBot = AccessProviderType("dingtalkbot") AccessProviderTypeDNSLA = AccessProviderType("dnsla") AccessProviderTypeDogeCloud = AccessProviderType("dogecloud") AccessProviderTypeDynv6 = AccessProviderType("dynv6") AccessProviderTypeEdgio = AccessProviderType("edgio") + AccessProviderTypeEmail = AccessProviderType("email") AccessProviderTypeFastly = AccessProviderType("fastly") // Fastly(预留) AccessProviderTypeGname = AccessProviderType("gname") AccessProviderTypeGcore = AccessProviderType("gcore") AccessProviderTypeGoDaddy = AccessProviderType("godaddy") - AccessProviderTypeGoEdge = AccessProviderType("goedge") // GoEdge(预留) + AccessProviderTypeGoEdge = AccessProviderType("goedge") AccessProviderTypeGoogleTrustServices = AccessProviderType("googletrustservices") AccessProviderTypeHuaweiCloud = AccessProviderType("huaweicloud") AccessProviderTypeJDCloud = AccessProviderType("jdcloud") AccessProviderTypeKubernetes = AccessProviderType("k8s") + AccessProviderTypeLarkBot = AccessProviderType("larkbot") AccessProviderTypeLetsEncrypt = AccessProviderType("letsencrypt") AccessProviderTypeLetsEncryptStaging = AccessProviderType("letsencryptstaging") AccessProviderTypeLocal = AccessProviderType("local") + AccessProviderTypeMattermost = AccessProviderType("mattermost") AccessProviderTypeNamecheap = AccessProviderType("namecheap") AccessProviderTypeNameDotCom = AccessProviderType("namedotcom") AccessProviderTypeNameSilo = AccessProviderType("namesilo") AccessProviderTypeNS1 = AccessProviderType("ns1") AccessProviderTypePorkbun = AccessProviderType("porkbun") AccessProviderTypePowerDNS = AccessProviderType("powerdns") + AccessProviderTypeProxmoxVE = AccessProviderType("proxmoxve") AccessProviderTypeQiniu = AccessProviderType("qiniu") AccessProviderTypeQingCloud = AccessProviderType("qingcloud") // 青云(预留) AccessProviderTypeRainYun = AccessProviderType("rainyun") AccessProviderTypeSafeLine = AccessProviderType("safeline") AccessProviderTypeSSH = AccessProviderType("ssh") AccessProviderTypeSSLCOM = AccessProviderType("sslcom") + AccessProviderTypeTelegram = AccessProviderType("telegram") AccessProviderTypeTencentCloud = AccessProviderType("tencentcloud") AccessProviderTypeUCloud = AccessProviderType("ucloud") AccessProviderTypeUpyun = AccessProviderType("upyun") @@ -63,78 +70,80 @@ const ( AccessProviderTypeVolcEngine = AccessProviderType("volcengine") AccessProviderTypeWangsu = AccessProviderType("wangsu") AccessProviderTypeWebhook = AccessProviderType("webhook") + AccessProviderTypeWeComBot = AccessProviderType("wecombot") AccessProviderTypeWestcn = AccessProviderType("westcn") AccessProviderTypeZeroSSL = AccessProviderType("zerossl") ) -type ApplyCAProviderType string +type CAProviderType string /* -申请证书 CA 提供商常量值。 -始终等于授权提供商类型。 - - 注意:如果追加新的常量值,请保持以 ASCII 排序。 - NOTICE: If you add new constant, please keep ASCII order. -*/ -const ( - ApplyCAProviderTypeBuypass = ApplyCAProviderType(string(AccessProviderTypeBuypass)) - ApplyCAProviderTypeGoogleTrustServices = ApplyCAProviderType(string(AccessProviderTypeGoogleTrustServices)) - ApplyCAProviderTypeLetsEncrypt = ApplyCAProviderType(string(AccessProviderTypeLetsEncrypt)) - ApplyCAProviderTypeLetsEncryptStaging = ApplyCAProviderType(string(AccessProviderTypeLetsEncryptStaging)) - ApplyCAProviderTypeSSLCom = ApplyCAProviderType(string(AccessProviderTypeSSLCOM)) - ApplyCAProviderTypeZeroSSL = ApplyCAProviderType(string(AccessProviderTypeZeroSSL)) -) - -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") - ApplyDNSProviderTypeAzure = ApplyDNSProviderType("azure") // 兼容旧值,等同于 [ApplyDNSProviderTypeAzure] - ApplyDNSProviderTypeAzureDNS = ApplyDNSProviderType("azure-dns") - ApplyDNSProviderTypeBaiduCloud = ApplyDNSProviderType("baiducloud") // 兼容旧值,等同于 [ApplyDNSProviderTypeBaiduCloudDNS] - ApplyDNSProviderTypeBaiduCloudDNS = ApplyDNSProviderType("baiducloud-dns") - ApplyDNSProviderTypeBunny = ApplyDNSProviderType("bunny") - ApplyDNSProviderTypeCloudflare = ApplyDNSProviderType("cloudflare") - ApplyDNSProviderTypeClouDNS = ApplyDNSProviderType("cloudns") - ApplyDNSProviderTypeCMCCCloud = ApplyDNSProviderType("cmcccloud") - ApplyDNSProviderTypeDeSEC = ApplyDNSProviderType("desec") - ApplyDNSProviderTypeDNSLA = ApplyDNSProviderType("dnsla") - ApplyDNSProviderTypeDynv6 = ApplyDNSProviderType("dynv6") - ApplyDNSProviderTypeGcore = ApplyDNSProviderType("gcore") - ApplyDNSProviderTypeGname = ApplyDNSProviderType("gname") - ApplyDNSProviderTypeGoDaddy = ApplyDNSProviderType("godaddy") - ApplyDNSProviderTypeHuaweiCloud = ApplyDNSProviderType("huaweicloud") // 兼容旧值,等同于 [ApplyDNSProviderTypeHuaweiCloudDNS] - ApplyDNSProviderTypeHuaweiCloudDNS = ApplyDNSProviderType("huaweicloud-dns") - ApplyDNSProviderTypeJDCloud = ApplyDNSProviderType("jdcloud") // 兼容旧值,等同于 [ApplyDNSProviderTypeJDCloudDNS] - ApplyDNSProviderTypeJDCloudDNS = ApplyDNSProviderType("jdcloud-dns") - ApplyDNSProviderTypeNamecheap = ApplyDNSProviderType("namecheap") - ApplyDNSProviderTypeNameDotCom = ApplyDNSProviderType("namedotcom") - ApplyDNSProviderTypeNameSilo = ApplyDNSProviderType("namesilo") - ApplyDNSProviderTypeNS1 = ApplyDNSProviderType("ns1") - ApplyDNSProviderTypePorkbun = ApplyDNSProviderType("porkbun") - ApplyDNSProviderTypePowerDNS = ApplyDNSProviderType("powerdns") - ApplyDNSProviderTypeRainYun = ApplyDNSProviderType("rainyun") - ApplyDNSProviderTypeTencentCloud = ApplyDNSProviderType("tencentcloud") // 兼容旧值,等同于 [ApplyDNSProviderTypeTencentCloudDNS] - ApplyDNSProviderTypeTencentCloudDNS = ApplyDNSProviderType("tencentcloud-dns") - ApplyDNSProviderTypeTencentCloudEO = ApplyDNSProviderType("tencentcloud-eo") - ApplyDNSProviderTypeVercel = ApplyDNSProviderType("vercel") - ApplyDNSProviderTypeVolcEngine = ApplyDNSProviderType("volcengine") // 兼容旧值,等同于 [ApplyDNSProviderTypeVolcEngineDNS] - ApplyDNSProviderTypeVolcEngineDNS = ApplyDNSProviderType("volcengine-dns") - ApplyDNSProviderTypeWestcn = ApplyDNSProviderType("westcn") + CAProviderTypeBuypass = CAProviderType(AccessProviderTypeBuypass) + CAProviderTypeGoogleTrustServices = CAProviderType(AccessProviderTypeGoogleTrustServices) + CAProviderTypeLetsEncrypt = CAProviderType(AccessProviderTypeLetsEncrypt) + CAProviderTypeLetsEncryptStaging = CAProviderType(AccessProviderTypeLetsEncryptStaging) + CAProviderTypeSSLCom = CAProviderType(AccessProviderTypeSSLCOM) + CAProviderTypeZeroSSL = CAProviderType(AccessProviderTypeZeroSSL) ) -type DeployProviderType string +type ACMEDns01ProviderType string + +/* +ACME DNS-01 提供商常量值。 +短横线前的部分始终等于授权提供商类型。 + + 注意:如果追加新的常量值,请保持以 ASCII 排序。 + NOTICE: If you add new constant, please keep ASCII order. +*/ +const ( + ACMEDns01ProviderTypeACMEHttpReq = ACMEDns01ProviderType(AccessProviderTypeACMEHttpReq) + ACMEDns01ProviderTypeAliyun = ACMEDns01ProviderType(AccessProviderTypeAliyun) // 兼容旧值,等同于 [ACMEDns01ProviderTypeAliyunDNS] + ACMEDns01ProviderTypeAliyunDNS = ACMEDns01ProviderType(AccessProviderTypeAliyun + "-dns") + ACMEDns01ProviderTypeAliyunESA = ACMEDns01ProviderType(AccessProviderTypeAliyun + "-esa") + ACMEDns01ProviderTypeAWS = ACMEDns01ProviderType(AccessProviderTypeAWS) // 兼容旧值,等同于 [ACMEDns01ProviderTypeAWSRoute53] + ACMEDns01ProviderTypeAWSRoute53 = ACMEDns01ProviderType(AccessProviderTypeAWS + "-route53") + ACMEDns01ProviderTypeAzure = ACMEDns01ProviderType(AccessProviderTypeAzure) // 兼容旧值,等同于 [ACMEDns01ProviderTypeAzure] + ACMEDns01ProviderTypeAzureDNS = ACMEDns01ProviderType(AccessProviderTypeAzure + "-dns") + ACMEDns01ProviderTypeBaiduCloud = ACMEDns01ProviderType(AccessProviderTypeBaiduCloud) // 兼容旧值,等同于 [ACMEDns01ProviderTypeBaiduCloudDNS] + ACMEDns01ProviderTypeBaiduCloudDNS = ACMEDns01ProviderType(AccessProviderTypeBaiduCloud + "-dns") + ACMEDns01ProviderTypeBunny = ACMEDns01ProviderType(AccessProviderTypeBunny) + ACMEDns01ProviderTypeCloudflare = ACMEDns01ProviderType(AccessProviderTypeCloudflare) + ACMEDns01ProviderTypeClouDNS = ACMEDns01ProviderType(AccessProviderTypeClouDNS) + ACMEDns01ProviderTypeCMCCCloud = ACMEDns01ProviderType(AccessProviderTypeCMCCCloud) + ACMEDns01ProviderTypeDeSEC = ACMEDns01ProviderType(AccessProviderTypeDeSEC) + ACMEDns01ProviderTypeDNSLA = ACMEDns01ProviderType(AccessProviderTypeDNSLA) + ACMEDns01ProviderTypeDynv6 = ACMEDns01ProviderType(AccessProviderTypeDynv6) + ACMEDns01ProviderTypeGcore = ACMEDns01ProviderType(AccessProviderTypeGcore) + ACMEDns01ProviderTypeGname = ACMEDns01ProviderType(AccessProviderTypeGname) + ACMEDns01ProviderTypeGoDaddy = ACMEDns01ProviderType(AccessProviderTypeGoDaddy) + ACMEDns01ProviderTypeHuaweiCloud = ACMEDns01ProviderType(AccessProviderTypeHuaweiCloud) // 兼容旧值,等同于 [ACMEDns01ProviderTypeHuaweiCloudDNS] + ACMEDns01ProviderTypeHuaweiCloudDNS = ACMEDns01ProviderType(AccessProviderTypeHuaweiCloud + "-dns") + ACMEDns01ProviderTypeJDCloud = ACMEDns01ProviderType(AccessProviderTypeJDCloud) // 兼容旧值,等同于 [ACMEDns01ProviderTypeJDCloudDNS] + ACMEDns01ProviderTypeJDCloudDNS = ACMEDns01ProviderType(AccessProviderTypeJDCloud + "-dns") + ACMEDns01ProviderTypeNamecheap = ACMEDns01ProviderType(AccessProviderTypeNamecheap) + ACMEDns01ProviderTypeNameDotCom = ACMEDns01ProviderType(AccessProviderTypeNameDotCom) + ACMEDns01ProviderTypeNameSilo = ACMEDns01ProviderType(AccessProviderTypeNameSilo) + ACMEDns01ProviderTypeNS1 = ACMEDns01ProviderType(AccessProviderTypeNS1) + ACMEDns01ProviderTypePorkbun = ACMEDns01ProviderType(AccessProviderTypePorkbun) + ACMEDns01ProviderTypePowerDNS = ACMEDns01ProviderType(AccessProviderTypePowerDNS) + ACMEDns01ProviderTypeRainYun = ACMEDns01ProviderType(AccessProviderTypeRainYun) + ACMEDns01ProviderTypeTencentCloud = ACMEDns01ProviderType(AccessProviderTypeTencentCloud) // 兼容旧值,等同于 [ACMEDns01ProviderTypeTencentCloudDNS] + ACMEDns01ProviderTypeTencentCloudDNS = ACMEDns01ProviderType(AccessProviderTypeTencentCloud + "-dns") + ACMEDns01ProviderTypeTencentCloudEO = ACMEDns01ProviderType(AccessProviderTypeTencentCloud + "-eo") + ACMEDns01ProviderTypeVercel = ACMEDns01ProviderType(AccessProviderTypeVercel) + ACMEDns01ProviderTypeVolcEngine = ACMEDns01ProviderType(AccessProviderTypeVolcEngine) // 兼容旧值,等同于 [ACMEDns01ProviderTypeVolcEngineDNS] + ACMEDns01ProviderTypeVolcEngineDNS = ACMEDns01ProviderType(AccessProviderTypeVolcEngine + "-dns") + ACMEDns01ProviderTypeWestcn = ACMEDns01ProviderType(AccessProviderTypeWestcn) +) + +type DeploymentProviderType string /* 部署证书主机提供商常量值。 @@ -144,78 +153,100 @@ type DeployProviderType string NOTICE: If you add new constant, please keep ASCII order. */ const ( - DeployProviderType1PanelConsole = DeployProviderType("1panel-console") - DeployProviderType1PanelSite = DeployProviderType("1panel-site") - DeployProviderTypeAliyunALB = DeployProviderType("aliyun-alb") - DeployProviderTypeAliyunAPIGW = DeployProviderType("aliyun-apigw") - DeployProviderTypeAliyunCAS = DeployProviderType("aliyun-cas") - DeployProviderTypeAliyunCASDeploy = DeployProviderType("aliyun-casdeploy") - DeployProviderTypeAliyunCDN = DeployProviderType("aliyun-cdn") - DeployProviderTypeAliyunCLB = DeployProviderType("aliyun-clb") - DeployProviderTypeAliyunDCDN = DeployProviderType("aliyun-dcdn") - DeployProviderTypeAliyunESA = DeployProviderType("aliyun-esa") - DeployProviderTypeAliyunFC = DeployProviderType("aliyun-fc") - DeployProviderTypeAliyunLive = DeployProviderType("aliyun-live") - DeployProviderTypeAliyunNLB = DeployProviderType("aliyun-nlb") - DeployProviderTypeAliyunOSS = DeployProviderType("aliyun-oss") - DeployProviderTypeAliyunVOD = DeployProviderType("aliyun-vod") - DeployProviderTypeAliyunWAF = DeployProviderType("aliyun-waf") - DeployProviderTypeAWSACM = DeployProviderType("aws-acm") - DeployProviderTypeAWSCloudFront = DeployProviderType("aws-cloudfront") - DeployProviderTypeAzureKeyVault = DeployProviderType("azure-keyvault") - DeployProviderTypeBaiduCloudAppBLB = DeployProviderType("baiducloud-appblb") - DeployProviderTypeBaiduCloudBLB = DeployProviderType("baiducloud-blb") - DeployProviderTypeBaiduCloudCDN = DeployProviderType("baiducloud-cdn") - DeployProviderTypeBaiduCloudCert = DeployProviderType("baiducloud-cert") - DeployProviderTypeBaishanCDN = DeployProviderType("baishan-cdn") - DeployProviderTypeBaotaPanelConsole = DeployProviderType("baotapanel-console") - DeployProviderTypeBaotaPanelSite = DeployProviderType("baotapanel-site") - DeployProviderTypeBunnyCDN = DeployProviderType("bunny-cdn") - DeployProviderTypeBytePlusCDN = DeployProviderType("byteplus-cdn") - DeployProviderTypeCacheFly = DeployProviderType("cachefly") - DeployProviderTypeCdnfly = DeployProviderType("cdnfly") - DeployProviderTypeDogeCloudCDN = DeployProviderType("dogecloud-cdn") - DeployProviderTypeEdgioApplications = DeployProviderType("edgio-applications") - DeployProviderTypeGcoreCDN = DeployProviderType("gcore-cdn") - DeployProviderTypeHuaweiCloudCDN = DeployProviderType("huaweicloud-cdn") - DeployProviderTypeHuaweiCloudELB = DeployProviderType("huaweicloud-elb") - DeployProviderTypeHuaweiCloudSCM = DeployProviderType("huaweicloud-scm") - DeployProviderTypeHuaweiCloudWAF = DeployProviderType("huaweicloud-waf") - DeployProviderTypeJDCloudALB = DeployProviderType("jdcloud-alb") - DeployProviderTypeJDCloudCDN = DeployProviderType("jdcloud-cdn") - DeployProviderTypeJDCloudLive = DeployProviderType("jdcloud-live") - DeployProviderTypeJDCloudVOD = DeployProviderType("jdcloud-vod") - DeployProviderTypeKubernetesSecret = DeployProviderType("k8s-secret") - DeployProviderTypeLocal = DeployProviderType("local") - DeployProviderTypeQiniuCDN = DeployProviderType("qiniu-cdn") - DeployProviderTypeQiniuKodo = DeployProviderType("qiniu-kodo") - DeployProviderTypeQiniuPili = DeployProviderType("qiniu-pili") - DeployProviderTypeRainYunRCDN = DeployProviderType("rainyun-rcdn") - DeployProviderTypeSafeLine = DeployProviderType("safeline") - DeployProviderTypeSSH = DeployProviderType("ssh") - DeployProviderTypeTencentCloudCDN = DeployProviderType("tencentcloud-cdn") - DeployProviderTypeTencentCloudCLB = DeployProviderType("tencentcloud-clb") - DeployProviderTypeTencentCloudCOS = DeployProviderType("tencentcloud-cos") - DeployProviderTypeTencentCloudCSS = DeployProviderType("tencentcloud-css") - DeployProviderTypeTencentCloudECDN = DeployProviderType("tencentcloud-ecdn") - DeployProviderTypeTencentCloudEO = DeployProviderType("tencentcloud-eo") - DeployProviderTypeTencentCloudSCF = DeployProviderType("tencentcloud-scf") - DeployProviderTypeTencentCloudSSL = DeployProviderType("tencentcloud-ssl") - DeployProviderTypeTencentCloudSSLDeploy = DeployProviderType("tencentcloud-ssldeploy") - DeployProviderTypeTencentCloudVOD = DeployProviderType("tencentcloud-vod") - DeployProviderTypeTencentCloudWAF = DeployProviderType("tencentcloud-waf") - DeployProviderTypeUCloudUCDN = DeployProviderType("ucloud-ucdn") - DeployProviderTypeUCloudUS3 = DeployProviderType("ucloud-us3") - DeployProviderTypeUpyunCDN = DeployProviderType("upyun-cdn") - DeployProviderTypeUpyunFile = DeployProviderType("upyun-file") - DeployProviderTypeVolcEngineALB = DeployProviderType("volcengine-alb") - DeployProviderTypeVolcEngineCDN = DeployProviderType("volcengine-cdn") - DeployProviderTypeVolcEngineCertCenter = DeployProviderType("volcengine-certcenter") - DeployProviderTypeVolcEngineCLB = DeployProviderType("volcengine-clb") - DeployProviderTypeVolcEngineDCDN = DeployProviderType("volcengine-dcdn") - DeployProviderTypeVolcEngineImageX = DeployProviderType("volcengine-imagex") - DeployProviderTypeVolcEngineLive = DeployProviderType("volcengine-live") - DeployProviderTypeVolcEngineTOS = DeployProviderType("volcengine-tos") - DeployProviderTypeWangsuCDNPro = DeployProviderType("wangsu-cdnpro") - DeployProviderTypeWebhook = DeployProviderType("webhook") + DeploymentProviderType1PanelConsole = DeploymentProviderType(AccessProviderType1Panel + "-console") + DeploymentProviderType1PanelSite = DeploymentProviderType(AccessProviderType1Panel + "-site") + DeploymentProviderTypeAliyunALB = DeploymentProviderType(AccessProviderTypeAliyun + "-alb") + DeploymentProviderTypeAliyunAPIGW = DeploymentProviderType(AccessProviderTypeAliyun + "-apigw") + DeploymentProviderTypeAliyunCAS = DeploymentProviderType(AccessProviderTypeAliyun + "-cas") + DeploymentProviderTypeAliyunCASDeploy = DeploymentProviderType(AccessProviderTypeAliyun + "-casdeploy") + DeploymentProviderTypeAliyunCDN = DeploymentProviderType(AccessProviderTypeAliyun + "-cdn") + DeploymentProviderTypeAliyunCLB = DeploymentProviderType(AccessProviderTypeAliyun + "-clb") + DeploymentProviderTypeAliyunDCDN = DeploymentProviderType(AccessProviderTypeAliyun + "-dcdn") + DeploymentProviderTypeAliyunDDoS = DeploymentProviderType(AccessProviderTypeAliyun + "-ddos") + DeploymentProviderTypeAliyunESA = DeploymentProviderType(AccessProviderTypeAliyun + "-esa") + DeploymentProviderTypeAliyunFC = DeploymentProviderType(AccessProviderTypeAliyun + "-fc") + DeploymentProviderTypeAliyunLive = DeploymentProviderType(AccessProviderTypeAliyun + "-live") + DeploymentProviderTypeAliyunNLB = DeploymentProviderType(AccessProviderTypeAliyun + "-nlb") + DeploymentProviderTypeAliyunOSS = DeploymentProviderType(AccessProviderTypeAliyun + "-oss") + DeploymentProviderTypeAliyunVOD = DeploymentProviderType(AccessProviderTypeAliyun + "-vod") + DeploymentProviderTypeAliyunWAF = DeploymentProviderType(AccessProviderTypeAliyun + "-waf") + DeploymentProviderTypeAWSACM = DeploymentProviderType(AccessProviderTypeAWS + "-acm") + DeploymentProviderTypeAWSCloudFront = DeploymentProviderType(AccessProviderTypeAWS + "-cloudfront") + DeploymentProviderTypeAzureKeyVault = DeploymentProviderType(AccessProviderTypeAzure + "-keyvault") + DeploymentProviderTypeBaiduCloudAppBLB = DeploymentProviderType(AccessProviderTypeBaiduCloud + "-appblb") + DeploymentProviderTypeBaiduCloudBLB = DeploymentProviderType(AccessProviderTypeBaiduCloud + "-blb") + DeploymentProviderTypeBaiduCloudCDN = DeploymentProviderType(AccessProviderTypeBaiduCloud + "-cdn") + DeploymentProviderTypeBaiduCloudCert = DeploymentProviderType(AccessProviderTypeBaiduCloud + "-cert") + DeploymentProviderTypeBaishanCDN = DeploymentProviderType(AccessProviderTypeBaishan + "-cdn") + DeploymentProviderTypeBaotaPanelConsole = DeploymentProviderType(AccessProviderTypeBaotaPanel + "-console") + DeploymentProviderTypeBaotaPanelSite = DeploymentProviderType(AccessProviderTypeBaotaPanel + "-site") + DeploymentProviderTypeBunnyCDN = DeploymentProviderType(AccessProviderTypeBunny + "-cdn") + DeploymentProviderTypeBytePlusCDN = DeploymentProviderType(AccessProviderTypeBytePlus + "-cdn") + DeploymentProviderTypeCacheFly = DeploymentProviderType(AccessProviderTypeCacheFly) + DeploymentProviderTypeCdnfly = DeploymentProviderType(AccessProviderTypeCdnfly) + DeploymentProviderTypeDogeCloudCDN = DeploymentProviderType(AccessProviderTypeDogeCloud + "-cdn") + DeploymentProviderTypeEdgioApplications = DeploymentProviderType(AccessProviderTypeEdgio + "-applications") + DeploymentProviderTypeGcoreCDN = DeploymentProviderType(AccessProviderTypeGcore + "-cdn") + DeploymentProviderTypeGoEdge = DeploymentProviderType(AccessProviderTypeGoEdge) + DeploymentProviderTypeHuaweiCloudCDN = DeploymentProviderType(AccessProviderTypeHuaweiCloud + "-cdn") + DeploymentProviderTypeHuaweiCloudELB = DeploymentProviderType(AccessProviderTypeHuaweiCloud + "-elb") + DeploymentProviderTypeHuaweiCloudSCM = DeploymentProviderType(AccessProviderTypeHuaweiCloud + "-scm") + DeploymentProviderTypeHuaweiCloudWAF = DeploymentProviderType(AccessProviderTypeHuaweiCloud + "-waf") + DeploymentProviderTypeJDCloudALB = DeploymentProviderType(AccessProviderTypeJDCloud + "-alb") + DeploymentProviderTypeJDCloudCDN = DeploymentProviderType(AccessProviderTypeJDCloud + "-cdn") + DeploymentProviderTypeJDCloudLive = DeploymentProviderType(AccessProviderTypeJDCloud + "-live") + DeploymentProviderTypeJDCloudVOD = DeploymentProviderType(AccessProviderTypeJDCloud + "-vod") + DeploymentProviderTypeKubernetesSecret = DeploymentProviderType(AccessProviderTypeKubernetes + "-secret") + DeploymentProviderTypeLocal = DeploymentProviderType(AccessProviderTypeLocal) + DeploymentProviderTypeProxmoxVE = DeploymentProviderType(AccessProviderTypeProxmoxVE) + DeploymentProviderTypeQiniuCDN = DeploymentProviderType(AccessProviderTypeQiniu + "-cdn") + DeploymentProviderTypeQiniuKodo = DeploymentProviderType(AccessProviderTypeQiniu + "-kodo") + DeploymentProviderTypeQiniuPili = DeploymentProviderType(AccessProviderTypeQiniu + "-pili") + DeploymentProviderTypeRainYunRCDN = DeploymentProviderType(AccessProviderTypeRainYun + "-rcdn") + DeploymentProviderTypeSafeLine = DeploymentProviderType(AccessProviderTypeSafeLine) + DeploymentProviderTypeSSH = DeploymentProviderType(AccessProviderTypeSSH) + DeploymentProviderTypeTencentCloudCDN = DeploymentProviderType(AccessProviderTypeTencentCloud + "-cdn") + DeploymentProviderTypeTencentCloudCLB = DeploymentProviderType(AccessProviderTypeTencentCloud + "-clb") + DeploymentProviderTypeTencentCloudCOS = DeploymentProviderType(AccessProviderTypeTencentCloud + "-cos") + DeploymentProviderTypeTencentCloudCSS = DeploymentProviderType(AccessProviderTypeTencentCloud + "-css") + DeploymentProviderTypeTencentCloudECDN = DeploymentProviderType(AccessProviderTypeTencentCloud + "-ecdn") + DeploymentProviderTypeTencentCloudEO = DeploymentProviderType(AccessProviderTypeTencentCloud + "-eo") + DeploymentProviderTypeTencentCloudSCF = DeploymentProviderType(AccessProviderTypeTencentCloud + "-scf") + DeploymentProviderTypeTencentCloudSSL = DeploymentProviderType(AccessProviderTypeTencentCloud + "-ssl") + DeploymentProviderTypeTencentCloudSSLDeploy = DeploymentProviderType(AccessProviderTypeTencentCloud + "-ssldeploy") + DeploymentProviderTypeTencentCloudVOD = DeploymentProviderType(AccessProviderTypeTencentCloud + "-vod") + DeploymentProviderTypeTencentCloudWAF = DeploymentProviderType(AccessProviderTypeTencentCloud + "-waf") + DeploymentProviderTypeUCloudUCDN = DeploymentProviderType(AccessProviderTypeUCloud + "-ucdn") + DeploymentProviderTypeUCloudUS3 = DeploymentProviderType(AccessProviderTypeUCloud + "-us3") + DeploymentProviderTypeUpyunCDN = DeploymentProviderType(AccessProviderTypeUpyun + "-cdn") + DeploymentProviderTypeUpyunFile = DeploymentProviderType(AccessProviderTypeUpyun + "-file") + DeploymentProviderTypeVolcEngineALB = DeploymentProviderType(AccessProviderTypeVolcEngine + "-alb") + DeploymentProviderTypeVolcEngineCDN = DeploymentProviderType(AccessProviderTypeVolcEngine + "-cdn") + DeploymentProviderTypeVolcEngineCertCenter = DeploymentProviderType(AccessProviderTypeVolcEngine + "-certcenter") + DeploymentProviderTypeVolcEngineCLB = DeploymentProviderType(AccessProviderTypeVolcEngine + "-clb") + DeploymentProviderTypeVolcEngineDCDN = DeploymentProviderType(AccessProviderTypeVolcEngine + "-dcdn") + DeploymentProviderTypeVolcEngineImageX = DeploymentProviderType(AccessProviderTypeVolcEngine + "-imagex") + DeploymentProviderTypeVolcEngineLive = DeploymentProviderType(AccessProviderTypeVolcEngine + "-live") + DeploymentProviderTypeVolcEngineTOS = DeploymentProviderType(AccessProviderTypeVolcEngine + "-tos") + DeploymentProviderTypeWangsuCDNPro = DeploymentProviderType(AccessProviderTypeWangsu + "-cdnpro") + DeploymentProviderTypeWebhook = DeploymentProviderType(AccessProviderTypeWebhook) +) + +type NotificationProviderType string + +/* +消息通知提供商常量值。 +短横线前的部分始终等于授权提供商类型。 + + 注意:如果追加新的常量值,请保持以 ASCII 排序。 + NOTICE: If you add new constant, please keep ASCII order. +*/ +const ( + NotificationProviderTypeDingTalkBot = NotificationProviderType(AccessProviderTypeDingTalkBot) + NotificationProviderTypeEmail = NotificationProviderType(AccessProviderTypeEmail) + NotificationProviderTypeLarkBot = NotificationProviderType(AccessProviderTypeLarkBot) + NotificationProviderTypeMattermost = NotificationProviderType(AccessProviderTypeMattermost) + NotificationProviderTypeTelegram = NotificationProviderType(AccessProviderTypeTelegram) + NotificationProviderTypeWebhook = NotificationProviderType(AccessProviderTypeWebhook) + NotificationProviderTypeWeComBot = NotificationProviderType(AccessProviderTypeWeComBot) ) diff --git a/internal/domain/settings.go b/internal/domain/settings.go index ebe6b9d7..7063ed83 100644 --- a/internal/domain/settings.go +++ b/internal/domain/settings.go @@ -13,6 +13,7 @@ type Settings struct { Content string `json:"content" db:"content"` } +// Deprecated: v0.4.x 将废弃 type NotifyTemplatesSettingsContent struct { NotifyTemplates []struct { Subject string `json:"subject"` @@ -20,8 +21,10 @@ type NotifyTemplatesSettingsContent struct { } `json:"notifyTemplates"` } +// Deprecated: v0.4.x 将废弃 type NotifyChannelsSettingsContent map[string]map[string]any +// Deprecated: v0.4.x 将废弃 func (s *Settings) GetNotifyChannelConfig(channel string) (map[string]any, error) { conf := &NotifyChannelsSettingsContent{} if err := json.Unmarshal([]byte(s.Content), conf); err != nil { diff --git a/internal/domain/workflow.go b/internal/domain/workflow.go index 841a041d..6f3cccea 100644 --- a/internal/domain/workflow.go +++ b/internal/domain/workflow.go @@ -3,7 +3,7 @@ package domain import ( "time" - "github.com/usual2970/certimate/internal/pkg/utils/maputil" + maputil "github.com/usual2970/certimate/internal/pkg/utils/map" ) const CollectionNameWorkflow = "workflow" @@ -71,10 +71,11 @@ type WorkflowNodeConfigForApply struct { CAProvider string `json:"caProvider,omitempty"` // CA 提供商(零值将使用全局配置) CAProviderAccessId string `json:"caProviderAccessId,omitempty"` // CA 提供商授权记录 ID CAProviderConfig map[string]any `json:"caProviderConfig,omitempty"` // CA 提供商额外配置 - KeyAlgorithm string `json:"keyAlgorithm"` // 密钥算法 + KeyAlgorithm string `json:"keyAlgorithm"` // 证书算法 Nameservers string `json:"nameservers,omitempty"` // DNS 服务器列表,以半角分号分隔 - DnsPropagationTimeout int32 `json:"dnsPropagationTimeout,omitempty"` // DNS 传播超时时间(零值取决于提供商的默认值) - DnsTTL int32 `json:"dnsTTL,omitempty"` // DNS TTL(零值取决于提供商的默认值) + DnsPropagationWait int32 `json:"dnsPropagationWait,omitempty"` // DNS 传播等待时间,等同于 lego 的 `--dns-propagation-wait` 参数 + DnsPropagationTimeout int32 `json:"dnsPropagationTimeout,omitempty"` // DNS 传播检查超时时间(零值取决于提供商的默认值) + DnsTTL int32 `json:"dnsTTL,omitempty"` // DNS 解析记录 TTL(零值取决于提供商的默认值) DisableFollowCNAME bool `json:"disableFollowCNAME,omitempty"` // 是否关闭 CNAME 跟随 DisableARI bool `json:"disableARI,omitempty"` // 是否关闭 ARI SkipBeforeExpiryDays int32 `json:"skipBeforeExpiryDays,omitempty"` // 证书到期前多少天前跳过续期(零值将使用默认值 30) @@ -95,9 +96,12 @@ type WorkflowNodeConfigForDeploy struct { } type WorkflowNodeConfigForNotify struct { - Channel string `json:"channel"` // 通知渠道 - Subject string `json:"subject"` // 通知主题 - Message string `json:"message"` // 通知内容 + Channel string `json:"channel,omitempty"` // Deprecated: v0.4.x 将废弃 + Provider string `json:"provider"` // 通知提供商 + ProviderAccessId string `json:"providerAccessId"` // 通知提供商授权记录 ID + ProviderConfig map[string]any `json:"providerConfig,omitempty"` // 通知提供商额外配置 + Subject string `json:"subject"` // 通知主题 + Message string `json:"message"` // 通知内容 } func (n *WorkflowNode) GetConfigForApply() WorkflowNodeConfigForApply { @@ -111,12 +115,13 @@ func (n *WorkflowNode) GetConfigForApply() WorkflowNodeConfigForApply { ContactEmail: maputil.GetString(n.Config, "contactEmail"), Provider: maputil.GetString(n.Config, "provider"), ProviderAccessId: maputil.GetString(n.Config, "providerAccessId"), - ProviderConfig: maputil.GetAnyMap(n.Config, "providerConfig"), + ProviderConfig: maputil.GetKVMapAny(n.Config, "providerConfig"), CAProvider: maputil.GetString(n.Config, "caProvider"), CAProviderAccessId: maputil.GetString(n.Config, "caProviderAccessId"), - CAProviderConfig: maputil.GetAnyMap(n.Config, "caProviderConfig"), + CAProviderConfig: maputil.GetKVMapAny(n.Config, "caProviderConfig"), KeyAlgorithm: maputil.GetString(n.Config, "keyAlgorithm"), Nameservers: maputil.GetString(n.Config, "nameservers"), + DnsPropagationWait: maputil.GetInt32(n.Config, "dnsPropagationWait"), DnsPropagationTimeout: maputil.GetInt32(n.Config, "dnsPropagationTimeout"), DnsTTL: maputil.GetInt32(n.Config, "dnsTTL"), DisableFollowCNAME: maputil.GetBool(n.Config, "disableFollowCNAME"), @@ -138,16 +143,19 @@ func (n *WorkflowNode) GetConfigForDeploy() WorkflowNodeConfigForDeploy { Certificate: maputil.GetString(n.Config, "certificate"), Provider: maputil.GetString(n.Config, "provider"), ProviderAccessId: maputil.GetString(n.Config, "providerAccessId"), - ProviderConfig: maputil.GetAnyMap(n.Config, "providerConfig"), + ProviderConfig: maputil.GetKVMapAny(n.Config, "providerConfig"), SkipOnLastSucceeded: maputil.GetBool(n.Config, "skipOnLastSucceeded"), } } func (n *WorkflowNode) GetConfigForNotify() WorkflowNodeConfigForNotify { return WorkflowNodeConfigForNotify{ - Channel: maputil.GetString(n.Config, "channel"), - Subject: maputil.GetString(n.Config, "subject"), - Message: maputil.GetString(n.Config, "message"), + Channel: maputil.GetString(n.Config, "channel"), + Provider: maputil.GetString(n.Config, "provider"), + ProviderAccessId: maputil.GetString(n.Config, "providerAccessId"), + ProviderConfig: maputil.GetKVMapAny(n.Config, "providerConfig"), + Subject: maputil.GetString(n.Config, "subject"), + Message: maputil.GetString(n.Config, "message"), } } diff --git a/internal/notify/notifier.go b/internal/notify/notifier.go new file mode 100644 index 00000000..955e88c3 --- /dev/null +++ b/internal/notify/notifier.go @@ -0,0 +1,72 @@ +package notify + +import ( + "context" + "fmt" + "log/slog" + + "github.com/usual2970/certimate/internal/domain" + "github.com/usual2970/certimate/internal/pkg/core/notifier" + "github.com/usual2970/certimate/internal/repository" +) + +type Notifier interface { + Notify(ctx context.Context) error +} + +type NotifierWithWorkflowNodeConfig struct { + Node *domain.WorkflowNode + Logger *slog.Logger + Subject string + Message string +} + +func NewWithWorkflowNode(config NotifierWithWorkflowNodeConfig) (Notifier, error) { + if config.Node == nil { + return nil, fmt.Errorf("node is nil") + } + if config.Node.Type != domain.WorkflowNodeTypeNotify { + return nil, fmt.Errorf("node type is not '%s'", string(domain.WorkflowNodeTypeNotify)) + } + + nodeConfig := config.Node.GetConfigForNotify() + options := ¬ifierProviderOptions{ + Provider: domain.NotificationProviderType(nodeConfig.Provider), + ProviderAccessConfig: make(map[string]any), + ProviderExtendedConfig: nodeConfig.ProviderConfig, + } + + accessRepo := repository.NewAccessRepository() + if nodeConfig.ProviderAccessId != "" { + access, err := accessRepo.GetById(context.Background(), nodeConfig.ProviderAccessId) + if err != nil { + return nil, fmt.Errorf("failed to get access #%s record: %w", nodeConfig.ProviderAccessId, err) + } else { + options.ProviderAccessConfig = access.Config + } + } + + notifierProvider, err := createNotifierProvider(options) + if err != nil { + return nil, err + } + + return ¬ifierImpl{ + provider: notifierProvider.WithLogger(config.Logger), + subject: config.Subject, + message: config.Message, + }, nil +} + +type notifierImpl struct { + provider notifier.Notifier + subject string + message string +} + +var _ Notifier = (*notifierImpl)(nil) + +func (n *notifierImpl) Notify(ctx context.Context) error { + _, err := n.provider.Notify(ctx, n.subject, n.message) + return err +} diff --git a/internal/notify/notify.go b/internal/notify/notify.go index d4b42ec9..92970341 100644 --- a/internal/notify/notify.go +++ b/internal/notify/notify.go @@ -9,10 +9,11 @@ import ( "github.com/usual2970/certimate/internal/domain" "github.com/usual2970/certimate/internal/pkg/core/notifier" - "github.com/usual2970/certimate/internal/pkg/utils/maputil" + maputil "github.com/usual2970/certimate/internal/pkg/utils/map" "github.com/usual2970/certimate/internal/repository" ) +// Deprecated: v0.4.x 将废弃 func SendToAllChannels(subject, message string) error { notifiers, err := getEnabledNotifiers() if err != nil { @@ -38,8 +39,9 @@ func SendToAllChannels(subject, message string) error { return err } +// Deprecated: v0.4.x 将废弃 func SendToChannel(subject, message string, channel string, channelConfig map[string]any) error { - notifier, err := createNotifier(domain.NotifyChannelType(channel), channelConfig) + notifier, err := createNotifierProviderUseGlobalSettings(domain.NotifyChannelType(channel), channelConfig) if err != nil { return err } @@ -48,6 +50,7 @@ func SendToChannel(subject, message string, channel string, channelConfig map[st return err } +// Deprecated: v0.4.x 将废弃 func getEnabledNotifiers() ([]notifier.Notifier, error) { settingsRepo := repository.NewSettingsRepository() settings, err := settingsRepo.GetByName(context.Background(), "notifyChannels") @@ -66,7 +69,7 @@ func getEnabledNotifiers() ([]notifier.Notifier, error) { continue } - notifier, err := createNotifier(domain.NotifyChannelType(k), v) + notifier, err := createNotifierProviderUseGlobalSettings(domain.NotifyChannelType(k), v) if err != nil { continue } diff --git a/internal/notify/providers.go b/internal/notify/providers.go index c5b5e975..c57b9c82 100644 --- a/internal/notify/providers.go +++ b/internal/notify/providers.go @@ -2,105 +2,152 @@ package notify import ( "fmt" + "net/http" "github.com/usual2970/certimate/internal/domain" "github.com/usual2970/certimate/internal/pkg/core/notifier" - pBark "github.com/usual2970/certimate/internal/pkg/core/notifier/providers/bark" pDingTalk "github.com/usual2970/certimate/internal/pkg/core/notifier/providers/dingtalk" pEmail "github.com/usual2970/certimate/internal/pkg/core/notifier/providers/email" - pGotify "github.com/usual2970/certimate/internal/pkg/core/notifier/providers/gotify" pLark "github.com/usual2970/certimate/internal/pkg/core/notifier/providers/lark" pMattermost "github.com/usual2970/certimate/internal/pkg/core/notifier/providers/mattermost" - pPushover "github.com/usual2970/certimate/internal/pkg/core/notifier/providers/pushover" - pPushPlus "github.com/usual2970/certimate/internal/pkg/core/notifier/providers/pushplus" - pServerChan "github.com/usual2970/certimate/internal/pkg/core/notifier/providers/serverchan" pTelegram "github.com/usual2970/certimate/internal/pkg/core/notifier/providers/telegram" pWebhook "github.com/usual2970/certimate/internal/pkg/core/notifier/providers/webhook" pWeCom "github.com/usual2970/certimate/internal/pkg/core/notifier/providers/wecom" - "github.com/usual2970/certimate/internal/pkg/utils/maputil" + httputil "github.com/usual2970/certimate/internal/pkg/utils/http" + maputil "github.com/usual2970/certimate/internal/pkg/utils/map" ) -func createNotifier(channel domain.NotifyChannelType, channelConfig map[string]any) (notifier.Notifier, error) { +type notifierProviderOptions struct { + Provider domain.NotificationProviderType + ProviderAccessConfig map[string]any + ProviderExtendedConfig map[string]any +} + +func createNotifierProvider(options *notifierProviderOptions) (notifier.Notifier, error) { /* 注意:如果追加新的常量值,请保持以 ASCII 排序。 NOTICE: If you add new constant, please keep ASCII order. */ - switch channel { - case domain.NotifyChannelTypeBark: - return pBark.NewNotifier(&pBark.NotifierConfig{ - DeviceKey: maputil.GetString(channelConfig, "deviceKey"), - ServerUrl: maputil.GetString(channelConfig, "serverUrl"), - }) + switch options.Provider { + case domain.NotificationProviderTypeDingTalkBot: + { + access := domain.AccessConfigForDingTalkBot{} + if err := maputil.Populate(options.ProviderAccessConfig, &access); err != nil { + return nil, fmt.Errorf("failed to populate provider access config: %w", err) + } - case domain.NotifyChannelTypeDingTalk: - return pDingTalk.NewNotifier(&pDingTalk.NotifierConfig{ - AccessToken: maputil.GetString(channelConfig, "accessToken"), - Secret: maputil.GetString(channelConfig, "secret"), - }) + return pDingTalk.NewNotifier(&pDingTalk.NotifierConfig{ + WebhookUrl: access.WebhookUrl, + Secret: access.Secret, + }) + } - case domain.NotifyChannelTypeEmail: - return pEmail.NewNotifier(&pEmail.NotifierConfig{ - SmtpHost: maputil.GetString(channelConfig, "smtpHost"), - SmtpPort: maputil.GetInt32(channelConfig, "smtpPort"), - SmtpTLS: maputil.GetOrDefaultBool(channelConfig, "smtpTLS", true), - Username: maputil.GetOrDefaultString(channelConfig, "username", maputil.GetString(channelConfig, "senderAddress")), - Password: maputil.GetString(channelConfig, "password"), - SenderAddress: maputil.GetString(channelConfig, "senderAddress"), - ReceiverAddress: maputil.GetString(channelConfig, "receiverAddress"), - }) + case domain.NotificationProviderTypeEmail: + { + access := domain.AccessConfigForEmail{} + if err := maputil.Populate(options.ProviderAccessConfig, &access); err != nil { + return nil, fmt.Errorf("failed to populate provider access config: %w", err) + } - case domain.NotifyChannelTypeGotify: - return pGotify.NewNotifier(&pGotify.NotifierConfig{ - Url: maputil.GetString(channelConfig, "url"), - Token: maputil.GetString(channelConfig, "token"), - Priority: maputil.GetOrDefaultInt64(channelConfig, "priority", 1), - }) + return pEmail.NewNotifier(&pEmail.NotifierConfig{ + SmtpHost: access.SmtpHost, + SmtpPort: access.SmtpPort, + SmtpTls: access.SmtpTls, + Username: access.Username, + Password: access.Password, + SenderAddress: maputil.GetOrDefaultString(options.ProviderExtendedConfig, "senderAddress", access.DefaultSenderAddress), + ReceiverAddress: maputil.GetOrDefaultString(options.ProviderExtendedConfig, "receiverAddress", access.DefaultReceiverAddress), + }) + } - case domain.NotifyChannelTypeLark: - return pLark.NewNotifier(&pLark.NotifierConfig{ - WebhookUrl: maputil.GetString(channelConfig, "webhookUrl"), - }) + case domain.NotificationProviderTypeLarkBot: + { + access := domain.AccessConfigForLarkBot{} + if err := maputil.Populate(options.ProviderAccessConfig, &access); err != nil { + return nil, fmt.Errorf("failed to populate provider access config: %w", err) + } - case domain.NotifyChannelTypeMattermost: - return pMattermost.NewNotifier(&pMattermost.NotifierConfig{ - ServerUrl: maputil.GetString(channelConfig, "serverUrl"), - ChannelId: maputil.GetString(channelConfig, "channelId"), - Username: maputil.GetString(channelConfig, "username"), - Password: maputil.GetString(channelConfig, "password"), - }) - case domain.NotifyChannelTypePushover: - return pPushover.NewNotifier(&pPushover.NotifierConfig{ - Token: maputil.GetString(channelConfig, "token"), - User: maputil.GetString(channelConfig, "user"), - }) + return pLark.NewNotifier(&pLark.NotifierConfig{ + WebhookUrl: access.WebhookUrl, + }) + } - case domain.NotifyChannelTypePushPlus: - return pPushPlus.NewNotifier(&pPushPlus.NotifierConfig{ - Token: maputil.GetString(channelConfig, "token"), - }) + case domain.NotificationProviderTypeMattermost: + { + access := domain.AccessConfigForMattermost{} + if err := maputil.Populate(options.ProviderAccessConfig, &access); err != nil { + return nil, fmt.Errorf("failed to populate provider access config: %w", err) + } - case domain.NotifyChannelTypeServerChan: - return pServerChan.NewNotifier(&pServerChan.NotifierConfig{ - Url: maputil.GetString(channelConfig, "url"), - }) + return pMattermost.NewNotifier(&pMattermost.NotifierConfig{ + ServerUrl: access.ServerUrl, + Username: access.Username, + Password: access.Password, + ChannelId: maputil.GetOrDefaultString(options.ProviderExtendedConfig, "channelId", access.DefaultChannelId), + }) + } - case domain.NotifyChannelTypeTelegram: - return pTelegram.NewNotifier(&pTelegram.NotifierConfig{ - ApiToken: maputil.GetString(channelConfig, "apiToken"), - ChatId: maputil.GetInt64(channelConfig, "chatId"), - }) + case domain.NotificationProviderTypeTelegram: + { + access := domain.AccessConfigForTelegram{} + if err := maputil.Populate(options.ProviderAccessConfig, &access); err != nil { + return nil, fmt.Errorf("failed to populate provider access config: %w", err) + } - case domain.NotifyChannelTypeWebhook: - return pWebhook.NewNotifier(&pWebhook.NotifierConfig{ - Url: maputil.GetString(channelConfig, "url"), - AllowInsecureConnections: maputil.GetBool(channelConfig, "allowInsecureConnections"), - }) + return pTelegram.NewNotifier(&pTelegram.NotifierConfig{ + BotToken: access.BotToken, + ChatId: maputil.GetOrDefaultInt64(options.ProviderExtendedConfig, "chatId", access.DefaultChatId), + }) + } - case domain.NotifyChannelTypeWeCom: - return pWeCom.NewNotifier(&pWeCom.NotifierConfig{ - WebhookUrl: maputil.GetString(channelConfig, "webhookUrl"), - }) + case domain.NotificationProviderTypeWebhook: + { + access := domain.AccessConfigForWebhook{} + if err := maputil.Populate(options.ProviderAccessConfig, &access); err != nil { + return nil, fmt.Errorf("failed to populate provider access config: %w", err) + } + + mergedHeaders := make(map[string]string) + if defaultHeadersString := access.HeadersString; defaultHeadersString != "" { + h, err := httputil.ParseHeaders(defaultHeadersString) + if err != nil { + return nil, fmt.Errorf("failed to parse webhook headers: %w", err) + } + for key := range h { + mergedHeaders[http.CanonicalHeaderKey(key)] = h.Get(key) + } + } + if extendedHeadersString := maputil.GetString(options.ProviderExtendedConfig, "headers"); extendedHeadersString != "" { + h, err := httputil.ParseHeaders(extendedHeadersString) + if err != nil { + return nil, fmt.Errorf("failed to parse webhook headers: %w", err) + } + for key := range h { + mergedHeaders[http.CanonicalHeaderKey(key)] = h.Get(key) + } + } + + return pWebhook.NewNotifier(&pWebhook.NotifierConfig{ + WebhookUrl: access.Url, + WebhookData: maputil.GetOrDefaultString(options.ProviderExtendedConfig, "webhookData", access.DefaultDataForNotification), + Method: access.Method, + Headers: mergedHeaders, + AllowInsecureConnections: access.AllowInsecureConnections, + }) + } + + case domain.NotificationProviderTypeWeComBot: + { + access := domain.AccessConfigForWeComBot{} + if err := maputil.Populate(options.ProviderAccessConfig, &access); err != nil { + return nil, fmt.Errorf("failed to populate provider access config: %w", err) + } + + return pWeCom.NewNotifier(&pWeCom.NotifierConfig{ + WebhookUrl: access.WebhookUrl, + }) + } } - return nil, fmt.Errorf("unsupported notifier channel: %s", channelConfig) + return nil, fmt.Errorf("unsupported notifier provider '%s'", options.Provider) } diff --git a/internal/notify/providers_deprecated.go b/internal/notify/providers_deprecated.go new file mode 100644 index 00000000..1e862866 --- /dev/null +++ b/internal/notify/providers_deprecated.go @@ -0,0 +1,108 @@ +package notify + +import ( + "fmt" + + "github.com/usual2970/certimate/internal/domain" + "github.com/usual2970/certimate/internal/pkg/core/notifier" + pBark "github.com/usual2970/certimate/internal/pkg/core/notifier/providers/bark" + pDingTalk "github.com/usual2970/certimate/internal/pkg/core/notifier/providers/dingtalk" + pEmail "github.com/usual2970/certimate/internal/pkg/core/notifier/providers/email" + pGotify "github.com/usual2970/certimate/internal/pkg/core/notifier/providers/gotify" + pLark "github.com/usual2970/certimate/internal/pkg/core/notifier/providers/lark" + pMattermost "github.com/usual2970/certimate/internal/pkg/core/notifier/providers/mattermost" + pPushover "github.com/usual2970/certimate/internal/pkg/core/notifier/providers/pushover" + pPushPlus "github.com/usual2970/certimate/internal/pkg/core/notifier/providers/pushplus" + pServerChan "github.com/usual2970/certimate/internal/pkg/core/notifier/providers/serverchan" + pTelegram "github.com/usual2970/certimate/internal/pkg/core/notifier/providers/telegram" + pWebhook "github.com/usual2970/certimate/internal/pkg/core/notifier/providers/webhook" + pWeCom "github.com/usual2970/certimate/internal/pkg/core/notifier/providers/wecom" + maputil "github.com/usual2970/certimate/internal/pkg/utils/map" +) + +// Deprecated: v0.4.x 将废弃 +func createNotifierProviderUseGlobalSettings(channel domain.NotifyChannelType, channelConfig map[string]any) (notifier.Notifier, error) { + /* + 注意:如果追加新的常量值,请保持以 ASCII 排序。 + NOTICE: If you add new constant, please keep ASCII order. + */ + switch channel { + case domain.NotifyChannelTypeBark: + return pBark.NewNotifier(&pBark.NotifierConfig{ + DeviceKey: maputil.GetString(channelConfig, "deviceKey"), + ServerUrl: maputil.GetString(channelConfig, "serverUrl"), + }) + + case domain.NotifyChannelTypeDingTalk: + return pDingTalk.NewNotifier(&pDingTalk.NotifierConfig{ + WebhookUrl: "https://oapi.dingtalk.com/robot/send?access_token=" + maputil.GetString(channelConfig, "accessToken"), + Secret: maputil.GetString(channelConfig, "secret"), + }) + + case domain.NotifyChannelTypeEmail: + return pEmail.NewNotifier(&pEmail.NotifierConfig{ + SmtpHost: maputil.GetString(channelConfig, "smtpHost"), + SmtpPort: maputil.GetInt32(channelConfig, "smtpPort"), + SmtpTls: maputil.GetOrDefaultBool(channelConfig, "smtpTLS", true), + Username: maputil.GetOrDefaultString(channelConfig, "username", maputil.GetString(channelConfig, "senderAddress")), + Password: maputil.GetString(channelConfig, "password"), + SenderAddress: maputil.GetString(channelConfig, "senderAddress"), + ReceiverAddress: maputil.GetString(channelConfig, "receiverAddress"), + }) + + case domain.NotifyChannelTypeGotify: + return pGotify.NewNotifier(&pGotify.NotifierConfig{ + Url: maputil.GetString(channelConfig, "url"), + Token: maputil.GetString(channelConfig, "token"), + Priority: maputil.GetOrDefaultInt64(channelConfig, "priority", 1), + }) + + case domain.NotifyChannelTypeLark: + return pLark.NewNotifier(&pLark.NotifierConfig{ + WebhookUrl: maputil.GetString(channelConfig, "webhookUrl"), + }) + + case domain.NotifyChannelTypeMattermost: + return pMattermost.NewNotifier(&pMattermost.NotifierConfig{ + ServerUrl: maputil.GetString(channelConfig, "serverUrl"), + ChannelId: maputil.GetString(channelConfig, "channelId"), + Username: maputil.GetString(channelConfig, "username"), + Password: maputil.GetString(channelConfig, "password"), + }) + + case domain.NotifyChannelTypePushover: + return pPushover.NewNotifier(&pPushover.NotifierConfig{ + Token: maputil.GetString(channelConfig, "token"), + User: maputil.GetString(channelConfig, "user"), + }) + + case domain.NotifyChannelTypePushPlus: + return pPushPlus.NewNotifier(&pPushPlus.NotifierConfig{ + Token: maputil.GetString(channelConfig, "token"), + }) + + case domain.NotifyChannelTypeServerChan: + return pServerChan.NewNotifier(&pServerChan.NotifierConfig{ + Url: maputil.GetString(channelConfig, "url"), + }) + + case domain.NotifyChannelTypeTelegram: + return pTelegram.NewNotifier(&pTelegram.NotifierConfig{ + BotToken: maputil.GetString(channelConfig, "apiToken"), + ChatId: maputil.GetInt64(channelConfig, "chatId"), + }) + + case domain.NotifyChannelTypeWebhook: + return pWebhook.NewNotifier(&pWebhook.NotifierConfig{ + WebhookUrl: maputil.GetString(channelConfig, "url"), + AllowInsecureConnections: maputil.GetBool(channelConfig, "allowInsecureConnections"), + }) + + case domain.NotifyChannelTypeWeCom: + return pWeCom.NewNotifier(&pWeCom.NotifierConfig{ + WebhookUrl: maputil.GetString(channelConfig, "webhookUrl"), + }) + } + + return nil, fmt.Errorf("unsupported notifier channel '%s'", channelConfig) +} diff --git a/internal/notify/service.go b/internal/notify/service.go index 9b7cc416..1d1f6c25 100644 --- a/internal/notify/service.go +++ b/internal/notify/service.go @@ -8,25 +8,30 @@ import ( "github.com/usual2970/certimate/internal/domain/dtos" ) +// Deprecated: v0.4.x 将废弃 const ( notifyTestTitle = "测试通知" notifyTestBody = "欢迎使用 Certimate ,这是一条测试通知。" ) +// Deprecated: v0.4.x 将废弃 type settingsRepository interface { GetByName(ctx context.Context, name string) (*domain.Settings, error) } +// Deprecated: v0.4.x 将废弃 type NotifyService struct { settingsRepo settingsRepository } +// Deprecated: v0.4.x 将废弃 func NewNotifyService(settingsRepo settingsRepository) *NotifyService { return &NotifyService{ settingsRepo: settingsRepo, } } +// Deprecated: v0.4.x 将废弃 func (n *NotifyService) Test(ctx context.Context, req *dtos.NotifyTestPushReq) error { settings, err := n.settingsRepo.GetByName(ctx, "notifyChannels") if err != nil { diff --git a/internal/pkg/core/applicant/acme-dns-01/lego-providers/acmehttpreq/acmehttpreq.go b/internal/pkg/core/applicant/acme-dns-01/lego-providers/acmehttpreq/acmehttpreq.go index ab2b11a6..bdd16234 100644 --- a/internal/pkg/core/applicant/acme-dns-01/lego-providers/acmehttpreq/acmehttpreq.go +++ b/internal/pkg/core/applicant/acme-dns-01/lego-providers/acmehttpreq/acmehttpreq.go @@ -1,4 +1,4 @@ -package acmehttpreq +package acmehttpreq import ( "net/url" diff --git a/internal/pkg/core/applicant/acme-dns-01/lego-providers/aliyun-esa/aliyun_esa.go b/internal/pkg/core/applicant/acme-dns-01/lego-providers/aliyun-esa/aliyun_esa.go new file mode 100644 index 00000000..bf7026da --- /dev/null +++ b/internal/pkg/core/applicant/acme-dns-01/lego-providers/aliyun-esa/aliyun_esa.go @@ -0,0 +1,40 @@ +package aliyunesa + +import ( + "time" + + "github.com/go-acme/lego/v4/challenge" + + internal "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/aliyun-esa/internal" +) + +type ChallengeProviderConfig struct { + AccessKeyId string `json:"accessKeyId"` + AccessKeySecret string `json:"accessKeySecret"` + Region string `json:"region"` + DnsPropagationTimeout int32 `json:"dnsPropagationTimeout,omitempty"` + DnsTTL int32 `json:"dnsTTL,omitempty"` +} + +func NewChallengeProvider(config *ChallengeProviderConfig) (challenge.Provider, error) { + if config == nil { + panic("config is nil") + } + + providerConfig := internal.NewDefaultConfig() + providerConfig.SecretID = config.AccessKeyId + providerConfig.SecretKey = config.AccessKeySecret + if config.DnsPropagationTimeout != 0 { + providerConfig.PropagationTimeout = time.Duration(config.DnsPropagationTimeout) * time.Second + } + if config.DnsTTL != 0 { + providerConfig.TTL = config.DnsTTL + } + + provider, err := internal.NewDNSProviderConfig(providerConfig) + if err != nil { + return nil, err + } + + return provider, nil +} diff --git a/internal/pkg/core/applicant/acme-dns-01/lego-providers/aliyun-esa/internal/lego.go b/internal/pkg/core/applicant/acme-dns-01/lego-providers/aliyun-esa/internal/lego.go new file mode 100644 index 00000000..79df4083 --- /dev/null +++ b/internal/pkg/core/applicant/acme-dns-01/lego-providers/aliyun-esa/internal/lego.go @@ -0,0 +1,266 @@ +package lego_aliyunesa + +import ( + "errors" + "fmt" + "strings" + "sync" + "time" + + aliopen "github.com/alibabacloud-go/darabonba-openapi/v2/client" + aliesa "github.com/alibabacloud-go/esa-20240910/v2/client" + "github.com/alibabacloud-go/tea/tea" + "github.com/go-acme/lego/v4/challenge" + "github.com/go-acme/lego/v4/challenge/dns01" + "github.com/go-acme/lego/v4/platform/config/env" +) + +const ( + envNamespace = "ALICLOUDESA_" + + EnvAccessKey = envNamespace + "ACCESS_KEY" + EnvSecretKey = envNamespace + "SECRET_KEY" + EnvRegionID = envNamespace + "REGION_ID" + + EnvTTL = envNamespace + "TTL" + EnvPropagationTimeout = envNamespace + "PROPAGATION_TIMEOUT" + EnvPollingInterval = envNamespace + "POLLING_INTERVAL" + EnvHTTPTimeout = envNamespace + "HTTP_TIMEOUT" +) + +var _ challenge.ProviderTimeout = (*DNSProvider)(nil) + +type Config struct { + SecretID string + SecretKey string + RegionID string + + PropagationTimeout time.Duration + PollingInterval time.Duration + TTL int32 + HTTPTimeout time.Duration +} + +type DNSProvider struct { + client *aliesa.Client + config *Config + + siteIDs map[string]int64 + siteIDsMtx sync.Mutex +} + +func NewDefaultConfig() *Config { + return &Config{ + TTL: int32(env.GetOrDefaultInt(EnvTTL, 300)), + PropagationTimeout: env.GetOrDefaultSecond(EnvPropagationTimeout, 2*time.Minute), + PollingInterval: env.GetOrDefaultSecond(EnvPollingInterval, dns01.DefaultPollingInterval), + HTTPTimeout: env.GetOrDefaultSecond(EnvHTTPTimeout, 30*time.Second), + } +} + +func NewDNSProvider() (*DNSProvider, error) { + values, err := env.Get(EnvAccessKey, EnvSecretKey, EnvRegionID) + if err != nil { + return nil, fmt.Errorf("alicloud-esa: %w", err) + } + + config := NewDefaultConfig() + config.SecretID = values[EnvAccessKey] + config.SecretKey = values[EnvSecretKey] + config.RegionID = values[EnvRegionID] + + return NewDNSProviderConfig(config) +} + +func NewDNSProviderConfig(config *Config) (*DNSProvider, error) { + if config == nil { + return nil, errors.New("alicloud-esa: the configuration of the DNS provider is nil") + } + + client, err := aliesa.NewClient(&aliopen.Config{ + AccessKeyId: tea.String(config.SecretID), + AccessKeySecret: tea.String(config.SecretKey), + Endpoint: tea.String(fmt.Sprintf("esa.%s.aliyuncs.com", config.RegionID)), + }) + if err != nil { + return nil, fmt.Errorf("alicloud-esa: %w", err) + } + + return &DNSProvider{ + client: client, + config: config, + }, nil +} + +func (d *DNSProvider) Present(domain, token, keyAuth string) error { + info := dns01.GetChallengeInfo(domain, keyAuth) + + authZone, err := dns01.FindZoneByFqdn(info.EffectiveFQDN) + if err != nil { + return fmt.Errorf("alicloud-esa: could not find zone for domain %q: %w", domain, err) + } + + siteId, err := d.getSiteId(authZone) + if err != nil { + return fmt.Errorf("alicloud-esa: could not find site for zone %q: %w", authZone, err) + } + + if err := d.addOrUpdateDNSRecord(siteId, strings.TrimRight(info.EffectiveFQDN, "."), info.Value); err != nil { + return fmt.Errorf("alicloud-esa: %w", err) + } + + return nil +} + +func (d *DNSProvider) CleanUp(domain, token, keyAuth string) error { + info := dns01.GetChallengeInfo(domain, keyAuth) + + authZone, err := dns01.FindZoneByFqdn(info.EffectiveFQDN) + if err != nil { + return fmt.Errorf("alicloud-esa: could not find zone for domain %q: %w", domain, err) + } + + siteId, err := d.getSiteId(authZone) + if err != nil { + return fmt.Errorf("alicloud-esa: could not find site for zone %q: %w", authZone, err) + } + + if err := d.removeDNSRecord(siteId, strings.TrimRight(info.EffectiveFQDN, ".")); err != nil { + return fmt.Errorf("alicloud-esa: %w", err) + } + + return nil +} + +func (d *DNSProvider) Timeout() (timeout, interval time.Duration) { + return d.config.PropagationTimeout, d.config.PollingInterval +} + +func (d *DNSProvider) getSiteId(siteName string) (int64, error) { + d.siteIDsMtx.Lock() + siteID, ok := d.siteIDs[siteName] + d.siteIDsMtx.Unlock() + if ok { + return siteID, nil + } + + pageNumber := 1 + pageSize := 500 + for { + request := &aliesa.ListSitesRequest{ + SiteName: tea.String(siteName), + PageNumber: tea.Int32(int32(pageNumber)), + PageSize: tea.Int32(int32(pageNumber)), + AccessType: tea.String("NS"), + } + response, err := d.client.ListSites(request) + if err != nil { + return 0, err + } + + if response.Body == nil { + break + } else { + for _, record := range response.Body.Sites { + if tea.StringValue(record.SiteName) == siteName { + d.siteIDsMtx.Lock() + d.siteIDs[siteName] = *record.SiteId + d.siteIDsMtx.Unlock() + return *record.SiteId, nil + } + } + + if len(response.Body.Sites) < pageSize { + break + } + + pageNumber++ + } + } + + return 0, errors.New("failed to get site id") +} + +func (d *DNSProvider) findDNSRecord(siteId int64, effectiveFQDN string) (*aliesa.ListRecordsResponseBodyRecords, error) { + pageNumber := 1 + pageSize := 500 + for { + request := &aliesa.ListRecordsRequest{ + SiteId: tea.Int64(siteId), + Type: tea.String("TXT"), + RecordName: tea.String(effectiveFQDN), + PageNumber: tea.Int32(int32(pageNumber)), + PageSize: tea.Int32(int32(pageNumber)), + } + response, err := d.client.ListRecords(request) + if err != nil { + return nil, err + } + + if response.Body == nil { + break + } else { + for _, record := range response.Body.Records { + if tea.StringValue(record.RecordName) == effectiveFQDN { + return record, nil + } + } + + if len(response.Body.Records) < pageSize { + break + } + + pageNumber++ + } + } + + return nil, nil +} + +func (d *DNSProvider) addOrUpdateDNSRecord(siteId int64, effectiveFQDN, value string) error { + record, err := d.findDNSRecord(siteId, effectiveFQDN) + if err != nil { + return err + } + + if record == nil { + request := &aliesa.CreateRecordRequest{ + SiteId: tea.Int64(siteId), + Type: tea.String("TXT"), + RecordName: tea.String(effectiveFQDN), + Data: &aliesa.CreateRecordRequestData{ + Value: tea.String(value), + }, + Ttl: tea.Int32(d.config.TTL), + } + _, err := d.client.CreateRecord(request) + return err + } else { + request := &aliesa.UpdateRecordRequest{ + RecordId: record.RecordId, + Ttl: tea.Int32(d.config.TTL), + Data: &aliesa.UpdateRecordRequestData{ + Value: tea.String(value), + }, + } + _, err := d.client.UpdateRecord(request) + return err + } +} + +func (d *DNSProvider) removeDNSRecord(siteId int64, effectiveFQDN string) error { + record, err := d.findDNSRecord(siteId, effectiveFQDN) + if err != nil { + return err + } + + if record == nil { + return nil + } else { + request := &aliesa.DeleteRecordRequest{ + RecordId: record.RecordId, + } + _, err = d.client.DeleteRecord(request) + return err + } +} diff --git a/internal/pkg/core/applicant/acme-dns-01/lego-providers/azure-dns/azure-dns.go b/internal/pkg/core/applicant/acme-dns-01/lego-providers/azure-dns/azure-dns.go index eaf46bce..d8d54c90 100644 --- a/internal/pkg/core/applicant/acme-dns-01/lego-providers/azure-dns/azure-dns.go +++ b/internal/pkg/core/applicant/acme-dns-01/lego-providers/azure-dns/azure-dns.go @@ -6,7 +6,7 @@ import ( "github.com/go-acme/lego/v4/challenge" "github.com/go-acme/lego/v4/providers/dns/azuredns" - azcommon "github.com/usual2970/certimate/internal/pkg/vendors/azure-sdk/common" + azcommon "github.com/usual2970/certimate/internal/pkg/sdk3rd/azure/common" ) type ChallengeProviderConfig struct { diff --git a/internal/pkg/core/applicant/acme-dns-01/lego-providers/baiducloud/internal/lego.go b/internal/pkg/core/applicant/acme-dns-01/lego-providers/baiducloud/internal/lego.go index da157bd0..f67662b5 100644 --- a/internal/pkg/core/applicant/acme-dns-01/lego-providers/baiducloud/internal/lego.go +++ b/internal/pkg/core/applicant/acme-dns-01/lego-providers/baiducloud/internal/lego.go @@ -1,4 +1,4 @@ -package lego_baiducloud +package lego_baiducloud import ( "errors" @@ -89,7 +89,7 @@ func (d *DNSProvider) Present(domain, token, keyAuth string) error { authZone, err := dns01.FindZoneByFqdn(info.EffectiveFQDN) if err != nil { - return fmt.Errorf("baiducloud: %w", err) + return fmt.Errorf("baiducloud: could not find zone for domain %q: %w", domain, err) } subDomain, err := dns01.ExtractSubDomain(info.EffectiveFQDN, authZone) @@ -109,7 +109,7 @@ func (d *DNSProvider) CleanUp(domain, token, keyAuth string) error { authZone, err := dns01.FindZoneByFqdn(info.EffectiveFQDN) if err != nil { - return fmt.Errorf("baiducloud: %w", err) + return fmt.Errorf("baiducloud: could not find zone for domain %q: %w", domain, err) } subDomain, err := dns01.ExtractSubDomain(info.EffectiveFQDN, authZone) @@ -128,7 +128,7 @@ func (d *DNSProvider) Timeout() (timeout, interval time.Duration) { return d.config.PropagationTimeout, d.config.PollingInterval } -func (d *DNSProvider) getDNSRecord(zoneName, subDomain string) (*bcedns.Record, error) { +func (d *DNSProvider) findDNSRecord(zoneName, subDomain string) (*bcedns.Record, error) { pageMarker := "" pageSize := 1000 for { @@ -159,7 +159,7 @@ func (d *DNSProvider) getDNSRecord(zoneName, subDomain string) (*bcedns.Record, } func (d *DNSProvider) addOrUpdateDNSRecord(zoneName, subDomain, value string) error { - record, err := d.getDNSRecord(zoneName, subDomain) + record, err := d.findDNSRecord(zoneName, subDomain) if err != nil { return err } @@ -186,7 +186,7 @@ func (d *DNSProvider) addOrUpdateDNSRecord(zoneName, subDomain, value string) er } func (d *DNSProvider) removeDNSRecord(zoneName, subDomain string) error { - record, err := d.getDNSRecord(zoneName, subDomain) + record, err := d.findDNSRecord(zoneName, subDomain) if err != nil { return err } diff --git a/internal/pkg/core/applicant/acme-dns-01/lego-providers/bunny/bunny.go b/internal/pkg/core/applicant/acme-dns-01/lego-providers/bunny/bunny.go index 558f7773..1f4fdffe 100644 --- a/internal/pkg/core/applicant/acme-dns-01/lego-providers/bunny/bunny.go +++ b/internal/pkg/core/applicant/acme-dns-01/lego-providers/bunny/bunny.go @@ -17,7 +17,7 @@ func NewChallengeProvider(config *ChallengeProviderConfig) (challenge.Provider, if config == nil { panic("config is nil") } - + providerConfig := bunny.NewDefaultConfig() providerConfig.APIKey = config.ApiKey if config.DnsPropagationTimeout != 0 { diff --git a/internal/pkg/core/applicant/acme-dns-01/lego-providers/cmcccloud/internal/lego.go b/internal/pkg/core/applicant/acme-dns-01/lego-providers/cmcccloud/internal/lego.go index 0329d18d..6bccb1dc 100644 --- a/internal/pkg/core/applicant/acme-dns-01/lego-providers/cmcccloud/internal/lego.go +++ b/internal/pkg/core/applicant/acme-dns-01/lego-providers/cmcccloud/internal/lego.go @@ -93,7 +93,7 @@ func (d *DNSProvider) Present(domain, token, keyAuth string) error { zoneName, err := dns01.FindZoneByFqdn(info.EffectiveFQDN) if err != nil { - return fmt.Errorf("cmccecloud: %w", err) + return fmt.Errorf("cmccecloud: could not find zone for domain %q: %w", domain, err) } subDomain, err := dns01.ExtractSubDomain(info.EffectiveFQDN, zoneName) @@ -108,33 +108,33 @@ func (d *DNSProvider) Present(domain, token, keyAuth string) error { } if record == nil { - // add new record resp, err := d.client.CreateRecordOpenapi(&model.CreateRecordOpenapiRequest{ CreateRecordOpenapiBody: &model.CreateRecordOpenapiBody{ LineId: "0", // 默认线路 Rr: subDomain, DomainName: readDomain, - Description: "from certimate", + Description: "certimate acme", Type: model.CreateRecordOpenapiBodyTypeEnumTxt, Value: info.Value, Ttl: &d.config.TTL, }, }) if err != nil { - return fmt.Errorf("lego: %w", err) + return fmt.Errorf("cmccecloud: %w", err) } + if resp.State != model.CreateRecordOpenapiResponseStateEnumOk { - return fmt.Errorf("lego: create record failed, response state: %s, message: %s, code: %s", resp.State, resp.ErrorMessage, resp.ErrorCode) + return fmt.Errorf("cmccecloud: create record failed, response state: %s, message: %s, code: %s", resp.State, resp.ErrorMessage, resp.ErrorCode) } + return nil } else { - // update record resp, err := d.client.ModifyRecordOpenapi(&model.ModifyRecordOpenapiRequest{ ModifyRecordOpenapiBody: &model.ModifyRecordOpenapiBody{ RecordId: record.RecordId, Rr: subDomain, DomainName: readDomain, - Description: "from certmate", + Description: "certmate acme", LineId: "0", Type: model.ModifyRecordOpenapiBodyTypeEnumTxt, Value: info.Value, @@ -142,44 +142,52 @@ func (d *DNSProvider) Present(domain, token, keyAuth string) error { }, }) if err != nil { - return fmt.Errorf("lego: %w", err) + return fmt.Errorf("cmccecloud: %w", err) } + if resp.State != model.ModifyRecordOpenapiResponseStateEnumOk { - return fmt.Errorf("lego: create record failed, response state: %s", resp.State) + return fmt.Errorf("cmccecloud: create record failed, response state: %s", resp.State) } + return nil } } func (d *DNSProvider) CleanUp(domain, token, keyAuth string) error { challengeInfo := dns01.GetChallengeInfo(domain, keyAuth) + zoneName, err := dns01.FindZoneByFqdn(challengeInfo.FQDN) if err != nil { - return fmt.Errorf("cmccecloud: %w", err) + return fmt.Errorf("cmccecloud: could not find zone for domain %q: %w", domain, err) } + subDomain, err := dns01.ExtractSubDomain(challengeInfo.FQDN, zoneName) if err != nil { return fmt.Errorf("cmccecloud: %w", err) } + readDomain := strings.Trim(zoneName, ".") record, err := d.getDomainRecord(readDomain, subDomain) if err != nil { return err } + if record == nil { return nil + } else { + resp, err := d.client.DeleteRecordOpenapi(&model.DeleteRecordOpenapiRequest{ + DeleteRecordOpenapiBody: &model.DeleteRecordOpenapiBody{ + RecordIdList: []string{record.RecordId}, + }, + }) + if err != nil { + return fmt.Errorf("cmccecloud: %w", err) + } + if resp.State != model.DeleteRecordOpenapiResponseStateEnumOk { + return fmt.Errorf("cmccecloud: delete record failed, unexpected response state: %s", resp.State) + } } - resp, err := d.client.DeleteRecordOpenapi(&model.DeleteRecordOpenapiRequest{ - DeleteRecordOpenapiBody: &model.DeleteRecordOpenapiBody{ - RecordIdList: []string{record.RecordId}, - }, - }) - if err != nil { - return fmt.Errorf("lego: %w", err) - } - if resp.State != model.DeleteRecordOpenapiResponseStateEnumOk { - return fmt.Errorf("lego: delete record failed, response state: %s", resp.State) - } + return nil } @@ -205,8 +213,9 @@ func (d *DNSProvider) getDomainRecord(domain string, rr string) (*model.ListReco } if resp.State != model.ListRecordOpenapiResponseStateEnumOk { respStr, _ := json.Marshal(resp) - return nil, fmt.Errorf("request error. %s", string(respStr)) + return nil, fmt.Errorf("cmccecloud: request error: %s", string(respStr)) } + if resp.Body.Data != nil { for _, item := range *resp.Body.Data { if item.Rr == rr { @@ -214,9 +223,11 @@ func (d *DNSProvider) getDomainRecord(domain string, rr string) (*model.ListReco } } } + if resp.Body.TotalPages == nil || page >= *resp.Body.TotalPages { return nil, nil } + page++ } } diff --git a/internal/pkg/core/applicant/acme-dns-01/lego-providers/dnsla/internal/lego.go b/internal/pkg/core/applicant/acme-dns-01/lego-providers/dnsla/internal/lego.go index 1b9603bd..87cb6cd9 100644 --- a/internal/pkg/core/applicant/acme-dns-01/lego-providers/dnsla/internal/lego.go +++ b/internal/pkg/core/applicant/acme-dns-01/lego-providers/dnsla/internal/lego.go @@ -1,4 +1,4 @@ -package lego_dnsla +package lego_dnsla import ( "errors" @@ -10,7 +10,7 @@ import ( "github.com/go-acme/lego/v4/challenge/dns01" "github.com/go-acme/lego/v4/platform/config/env" - dnslasdk "github.com/usual2970/certimate/internal/pkg/vendors/dnsla-sdk" + dnslasdk "github.com/usual2970/certimate/internal/pkg/sdk3rd/dnsla" ) const ( @@ -83,7 +83,7 @@ func (d *DNSProvider) Present(domain, token, keyAuth string) error { authZone, err := dns01.FindZoneByFqdn(info.EffectiveFQDN) if err != nil { - return fmt.Errorf("dnsla: %w", err) + return fmt.Errorf("dnsla: could not find zone for domain %q: %w", domain, err) } subDomain, err := dns01.ExtractSubDomain(info.EffectiveFQDN, authZone) @@ -103,7 +103,7 @@ func (d *DNSProvider) CleanUp(domain, token, keyAuth string) error { authZone, err := dns01.FindZoneByFqdn(info.EffectiveFQDN) if err != nil { - return fmt.Errorf("dnsla: %w", err) + return fmt.Errorf("dnsla: could not find zone for domain %q: %w", domain, err) } subDomain, err := dns01.ExtractSubDomain(info.EffectiveFQDN, authZone) diff --git a/internal/pkg/core/applicant/acme-dns-01/lego-providers/dynv6/internal/lego.go b/internal/pkg/core/applicant/acme-dns-01/lego-providers/dynv6/internal/lego.go index f83949a2..8b33cf9e 100644 --- a/internal/pkg/core/applicant/acme-dns-01/lego-providers/dynv6/internal/lego.go +++ b/internal/pkg/core/applicant/acme-dns-01/lego-providers/dynv6/internal/lego.go @@ -1,4 +1,4 @@ -package lego_dynv6 +package lego_dynv6 import ( "context" @@ -76,7 +76,7 @@ func (d *DNSProvider) Present(domain, token, keyAuth string) error { authZone, err := dns01.FindZoneByFqdn(info.EffectiveFQDN) if err != nil { - return fmt.Errorf("dynv6: %w", err) + return fmt.Errorf("dynv6: could not find zone for domain %q: %w", domain, err) } subDomain, err := dns01.ExtractSubDomain(info.EffectiveFQDN, authZone) @@ -96,7 +96,7 @@ func (d *DNSProvider) CleanUp(domain, token, keyAuth string) error { authZone, err := dns01.FindZoneByFqdn(info.EffectiveFQDN) if err != nil { - return fmt.Errorf("dynv6: %w", err) + return fmt.Errorf("dynv6: could not find zone for domain %q: %w", domain, err) } subDomain, err := dns01.ExtractSubDomain(info.EffectiveFQDN, authZone) @@ -115,7 +115,7 @@ func (d *DNSProvider) Timeout() (timeout, interval time.Duration) { return d.config.PropagationTimeout, d.config.PollingInterval } -func (d *DNSProvider) getDNSRecord(zoneName, subDomain string) (*libdns.Record, error) { +func (d *DNSProvider) findDNSRecord(zoneName, subDomain string) (*libdns.Record, error) { records, err := d.client.GetRecords(context.Background(), zoneName) if err != nil { return nil, err @@ -131,7 +131,7 @@ func (d *DNSProvider) getDNSRecord(zoneName, subDomain string) (*libdns.Record, } func (d *DNSProvider) addOrUpdateDNSRecord(zoneName, subDomain, value string) error { - record, err := d.getDNSRecord(zoneName, subDomain) + record, err := d.findDNSRecord(zoneName, subDomain) if err != nil { return err } @@ -153,7 +153,7 @@ func (d *DNSProvider) addOrUpdateDNSRecord(zoneName, subDomain, value string) er } func (d *DNSProvider) removeDNSRecord(zoneName, subDomain string) error { - record, err := d.getDNSRecord(zoneName, subDomain) + record, err := d.findDNSRecord(zoneName, subDomain) if err != nil { return err } diff --git a/internal/pkg/core/applicant/acme-dns-01/lego-providers/gname/internal/lego.go b/internal/pkg/core/applicant/acme-dns-01/lego-providers/gname/internal/lego.go index 3c9b1b13..7f1f5670 100644 --- a/internal/pkg/core/applicant/acme-dns-01/lego-providers/gname/internal/lego.go +++ b/internal/pkg/core/applicant/acme-dns-01/lego-providers/gname/internal/lego.go @@ -1,4 +1,4 @@ -package lego_gname +package lego_gname import ( "errors" @@ -9,7 +9,7 @@ import ( "github.com/go-acme/lego/v4/challenge/dns01" "github.com/go-acme/lego/v4/platform/config/env" - gnamesdk "github.com/usual2970/certimate/internal/pkg/vendors/gname-sdk" + gnamesdk "github.com/usual2970/certimate/internal/pkg/sdk3rd/gname" ) const ( @@ -82,7 +82,7 @@ func (d *DNSProvider) Present(domain, token, keyAuth string) error { authZone, err := dns01.FindZoneByFqdn(info.EffectiveFQDN) if err != nil { - return fmt.Errorf("gname: %w", err) + return fmt.Errorf("gname: could not find zone for domain %q: %w", domain, err) } subDomain, err := dns01.ExtractSubDomain(info.EffectiveFQDN, authZone) @@ -102,7 +102,7 @@ func (d *DNSProvider) CleanUp(domain, token, keyAuth string) error { authZone, err := dns01.FindZoneByFqdn(info.EffectiveFQDN) if err != nil { - return fmt.Errorf("gname: %w", err) + return fmt.Errorf("gname: could not find zone for domain %q: %w", domain, err) } subDomain, err := dns01.ExtractSubDomain(info.EffectiveFQDN, authZone) @@ -121,7 +121,7 @@ func (d *DNSProvider) Timeout() (timeout, interval time.Duration) { return d.config.PropagationTimeout, d.config.PollingInterval } -func (d *DNSProvider) getDNSRecord(zoneName, subDomain string) (*gnamesdk.ResolutionRecord, error) { +func (d *DNSProvider) findDNSRecord(zoneName, subDomain string) (*gnamesdk.ResolutionRecord, error) { page := int32(1) pageSize := int32(20) for { @@ -155,7 +155,7 @@ func (d *DNSProvider) getDNSRecord(zoneName, subDomain string) (*gnamesdk.Resolu } func (d *DNSProvider) addOrUpdateDNSRecord(zoneName, subDomain, value string) error { - record, err := d.getDNSRecord(zoneName, subDomain) + record, err := d.findDNSRecord(zoneName, subDomain) if err != nil { return err } @@ -186,7 +186,7 @@ func (d *DNSProvider) addOrUpdateDNSRecord(zoneName, subDomain, value string) er } func (d *DNSProvider) removeDNSRecord(zoneName, subDomain string) error { - record, err := d.getDNSRecord(zoneName, subDomain) + record, err := d.findDNSRecord(zoneName, subDomain) if err != nil { return err } diff --git a/internal/pkg/core/applicant/acme-dns-01/lego-providers/jdcloud/internal/lego.go b/internal/pkg/core/applicant/acme-dns-01/lego-providers/jdcloud/internal/lego.go index d5b5277b..a1851a11 100644 --- a/internal/pkg/core/applicant/acme-dns-01/lego-providers/jdcloud/internal/lego.go +++ b/internal/pkg/core/applicant/acme-dns-01/lego-providers/jdcloud/internal/lego.go @@ -1,4 +1,4 @@ -package lego_jdcloud +package lego_jdcloud import ( "errors" @@ -91,7 +91,7 @@ func (d *DNSProvider) Present(domain, token, keyAuth string) error { authZone, err := dns01.FindZoneByFqdn(info.EffectiveFQDN) if err != nil { - return fmt.Errorf("jdcloud: %w", err) + return fmt.Errorf("jdcloud: could not find zone for domain %q: %w", domain, err) } subDomain, err := dns01.ExtractSubDomain(info.EffectiveFQDN, authZone) @@ -111,7 +111,7 @@ func (d *DNSProvider) CleanUp(domain, token, keyAuth string) error { authZone, err := dns01.FindZoneByFqdn(info.EffectiveFQDN) if err != nil { - return fmt.Errorf("jdcloud: %w", err) + return fmt.Errorf("jdcloud: could not find zone for domain %q: %w", domain, err) } subDomain, err := dns01.ExtractSubDomain(info.EffectiveFQDN, authZone) diff --git a/internal/pkg/core/applicant/acme-dns-01/lego-providers/powerdns/powerdns.go b/internal/pkg/core/applicant/acme-dns-01/lego-providers/powerdns/powerdns.go index e5275efe..7630633c 100644 --- a/internal/pkg/core/applicant/acme-dns-01/lego-providers/powerdns/powerdns.go +++ b/internal/pkg/core/applicant/acme-dns-01/lego-providers/powerdns/powerdns.go @@ -1,6 +1,8 @@ package powerdns import ( + "crypto/tls" + "net/http" "net/url" "time" @@ -9,10 +11,11 @@ import ( ) type ChallengeProviderConfig struct { - ApiUrl string `json:"apiUrl"` - ApiKey string `json:"apiKey"` - DnsPropagationTimeout int32 `json:"dnsPropagationTimeout,omitempty"` - DnsTTL int32 `json:"dnsTTL,omitempty"` + ApiUrl string `json:"apiUrl"` + ApiKey string `json:"apiKey"` + AllowInsecureConnections bool `json:"allowInsecureConnections,omitempty"` + DnsPropagationTimeout int32 `json:"dnsPropagationTimeout,omitempty"` + DnsTTL int32 `json:"dnsTTL,omitempty"` } func NewChallengeProvider(config *ChallengeProviderConfig) (challenge.Provider, error) { @@ -24,6 +27,13 @@ func NewChallengeProvider(config *ChallengeProviderConfig) (challenge.Provider, providerConfig := pdns.NewDefaultConfig() providerConfig.Host = host providerConfig.APIKey = config.ApiKey + if config.AllowInsecureConnections { + providerConfig.HTTPClient.Transport = &http.Transport{ + TLSClientConfig: &tls.Config{ + InsecureSkipVerify: true, + }, + } + } if config.DnsPropagationTimeout != 0 { providerConfig.PropagationTimeout = time.Duration(config.DnsPropagationTimeout) * time.Second } diff --git a/internal/pkg/core/applicant/acme-dns-01/lego-providers/tencentcloud-eo/internal/lego.go b/internal/pkg/core/applicant/acme-dns-01/lego-providers/tencentcloud-eo/internal/lego.go index 57f74193..692c42d3 100644 --- a/internal/pkg/core/applicant/acme-dns-01/lego-providers/tencentcloud-eo/internal/lego.go +++ b/internal/pkg/core/applicant/acme-dns-01/lego-providers/tencentcloud-eo/internal/lego.go @@ -1,4 +1,4 @@ -package lego_tencentcloudeo +package lego_tencentcloudeo import ( "errors" @@ -20,7 +20,7 @@ const ( EnvSecretID = envNamespace + "SECRET_ID" EnvSecretKey = envNamespace + "SECRET_KEY" - EnvZoneId = envNamespace + "ZONE_ID" + EnvZoneID = envNamespace + "ZONE_ID" EnvTTL = envNamespace + "TTL" EnvPropagationTimeout = envNamespace + "PROPAGATION_TIMEOUT" @@ -33,7 +33,7 @@ var _ challenge.ProviderTimeout = (*DNSProvider)(nil) type Config struct { SecretID string SecretKey string - ZoneId string + ZoneID string PropagationTimeout time.Duration PollingInterval time.Duration @@ -56,7 +56,7 @@ func NewDefaultConfig() *Config { } func NewDNSProvider() (*DNSProvider, error) { - values, err := env.Get(EnvSecretID, EnvSecretKey, EnvZoneId) + values, err := env.Get(EnvSecretID, EnvSecretKey, EnvZoneID) if err != nil { return nil, fmt.Errorf("tencentcloud-eo: %w", err) } @@ -64,7 +64,7 @@ func NewDNSProvider() (*DNSProvider, error) { config := NewDefaultConfig() config.SecretID = values[EnvSecretID] config.SecretKey = values[EnvSecretKey] - config.ZoneId = values[EnvSecretKey] + config.ZoneID = values[EnvSecretKey] return NewDNSProviderConfig(config) } @@ -112,12 +112,12 @@ func (d *DNSProvider) Timeout() (timeout, interval time.Duration) { return d.config.PropagationTimeout, d.config.PollingInterval } -func (d *DNSProvider) getDNSRecord(effectiveFQDN string) (*teo.DnsRecord, error) { +func (d *DNSProvider) findDNSRecord(effectiveFQDN string) (*teo.DnsRecord, error) { pageOffset := 0 pageLimit := 1000 for { request := teo.NewDescribeDnsRecordsRequest() - request.ZoneId = common.StringPtr(d.config.ZoneId) + request.ZoneId = common.StringPtr(d.config.ZoneID) request.Offset = common.Int64Ptr(int64(pageOffset)) request.Limit = common.Int64Ptr(int64(pageLimit)) request.Filters = []*teo.AdvancedFilter{ @@ -141,7 +141,7 @@ func (d *DNSProvider) getDNSRecord(effectiveFQDN string) (*teo.DnsRecord, error) } } - if len(response.Response.DnsRecords) < int(pageLimit) { + if len(response.Response.DnsRecords) < pageLimit { break } @@ -153,14 +153,14 @@ func (d *DNSProvider) getDNSRecord(effectiveFQDN string) (*teo.DnsRecord, error) } func (d *DNSProvider) addOrUpdateDNSRecord(effectiveFQDN, value string) error { - record, err := d.getDNSRecord(effectiveFQDN) + record, err := d.findDNSRecord(effectiveFQDN) if err != nil { return err } if record == nil { request := teo.NewCreateDnsRecordRequest() - request.ZoneId = common.StringPtr(d.config.ZoneId) + request.ZoneId = common.StringPtr(d.config.ZoneID) request.Name = common.StringPtr(effectiveFQDN) request.Type = common.StringPtr("TXT") request.Content = common.StringPtr(value) @@ -169,8 +169,9 @@ func (d *DNSProvider) addOrUpdateDNSRecord(effectiveFQDN, value string) error { return err } else { record.Content = common.StringPtr(value) + record.TTL = common.Int64Ptr(int64(d.config.TTL)) request := teo.NewModifyDnsRecordsRequest() - request.ZoneId = common.StringPtr(d.config.ZoneId) + request.ZoneId = common.StringPtr(d.config.ZoneID) request.DnsRecords = []*teo.DnsRecord{record} if _, err := d.client.ModifyDnsRecords(request); err != nil { return err @@ -178,7 +179,7 @@ func (d *DNSProvider) addOrUpdateDNSRecord(effectiveFQDN, value string) error { if *record.Status == "disable" { request := teo.NewModifyDnsRecordsStatusRequest() - request.ZoneId = common.StringPtr(d.config.ZoneId) + request.ZoneId = common.StringPtr(d.config.ZoneID) request.RecordsToEnable = []*string{record.RecordId} if _, err = d.client.ModifyDnsRecordsStatus(request); err != nil { return err @@ -190,7 +191,7 @@ func (d *DNSProvider) addOrUpdateDNSRecord(effectiveFQDN, value string) error { } func (d *DNSProvider) removeDNSRecord(effectiveFQDN string) error { - record, err := d.getDNSRecord(effectiveFQDN) + record, err := d.findDNSRecord(effectiveFQDN) if err != nil { return err } @@ -199,7 +200,7 @@ func (d *DNSProvider) removeDNSRecord(effectiveFQDN string) error { return nil } else { request := teo.NewDeleteDnsRecordsRequest() - request.ZoneId = common.StringPtr(d.config.ZoneId) + request.ZoneId = common.StringPtr(d.config.ZoneID) request.RecordIds = []*string{record.RecordId} _, err = d.client.DeleteDnsRecords(request) return err diff --git a/internal/pkg/core/applicant/acme-dns-01/lego-providers/tencentcloud-eo/tencentcloud_eo.go b/internal/pkg/core/applicant/acme-dns-01/lego-providers/tencentcloud-eo/tencentcloud_eo.go index 33552ecf..427c79ea 100644 --- a/internal/pkg/core/applicant/acme-dns-01/lego-providers/tencentcloud-eo/tencentcloud_eo.go +++ b/internal/pkg/core/applicant/acme-dns-01/lego-providers/tencentcloud-eo/tencentcloud_eo.go @@ -24,7 +24,7 @@ func NewChallengeProvider(config *ChallengeProviderConfig) (challenge.Provider, providerConfig := internal.NewDefaultConfig() providerConfig.SecretID = config.SecretId providerConfig.SecretKey = config.SecretKey - providerConfig.ZoneId = config.ZoneId + providerConfig.ZoneID = config.ZoneId if config.DnsPropagationTimeout != 0 { providerConfig.PropagationTimeout = time.Duration(config.DnsPropagationTimeout) * time.Second } diff --git a/internal/pkg/core/deployer/deployer.go b/internal/pkg/core/deployer/deployer.go index 54b206bd..67ce7ef7 100644 --- a/internal/pkg/core/deployer/deployer.go +++ b/internal/pkg/core/deployer/deployer.go @@ -1,4 +1,4 @@ -package deployer +package deployer import ( "context" @@ -14,13 +14,13 @@ type Deployer interface { // // 入参: // - ctx:上下文。 - // - certPem:证书 PEM 内容。 - // - privkeyPem:私钥 PEM 内容。 + // - certPEM:证书 PEM 内容。 + // - privkeyPEM:私钥 PEM 内容。 // // 出参: // - res:部署结果。 // - err: 错误。 - Deploy(ctx context.Context, certPem string, privkeyPem string) (res *DeployResult, err error) + Deploy(ctx context.Context, certPEM string, privkeyPEM string) (res *DeployResult, err error) } // 表示证书部署结果的数据结构。 diff --git a/internal/pkg/core/deployer/providers/1panel-console/1panel_console.go b/internal/pkg/core/deployer/providers/1panel-console/1panel_console.go index 91143aa6..069e01f9 100644 --- a/internal/pkg/core/deployer/providers/1panel-console/1panel_console.go +++ b/internal/pkg/core/deployer/providers/1panel-console/1panel_console.go @@ -1,16 +1,15 @@ -package onepanelconsole +package onepanelconsole import ( "context" "crypto/tls" "errors" + "fmt" "log/slog" "net/url" - xerrors "github.com/pkg/errors" - "github.com/usual2970/certimate/internal/pkg/core/deployer" - opsdk "github.com/usual2970/certimate/internal/pkg/vendors/1panel-sdk" + opsdk "github.com/usual2970/certimate/internal/pkg/sdk3rd/1panel" ) type DeployerConfig struct { @@ -39,7 +38,7 @@ func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { client, err := createSdkClient(config.ApiUrl, config.ApiKey, config.AllowInsecureConnections) if err != nil { - return nil, xerrors.Wrap(err, "failed to create sdk client") + return nil, fmt.Errorf("failed to create sdk client: %w", err) } return &DeployerProvider{ @@ -58,11 +57,11 @@ func (d *DeployerProvider) WithLogger(logger *slog.Logger) deployer.Deployer { return d } -func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { +func (d *DeployerProvider) Deploy(ctx context.Context, certPEM string, privkeyPEM string) (*deployer.DeployResult, error) { // 设置面板 SSL 证书 updateSystemSSLReq := &opsdk.UpdateSystemSSLRequest{ - Cert: certPem, - Key: privkeyPem, + Cert: certPEM, + Key: privkeyPEM, SSL: "enable", SSLType: "import-paste", } @@ -74,13 +73,13 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPe updateSystemSSLResp, err := d.sdkClient.UpdateSystemSSL(updateSystemSSLReq) d.logger.Debug("sdk request '1panel.UpdateSystemSSL'", slog.Any("request", updateSystemSSLReq), slog.Any("response", updateSystemSSLResp)) if err != nil { - return nil, xerrors.Wrap(err, "failed to execute sdk request '1panel.UpdateSystemSSL'") + return nil, fmt.Errorf("failed to execute sdk request '1panel.UpdateSystemSSL': %w", err) } return &deployer.DeployResult{}, nil } -func createSdkClient(apiUrl, apiKey string, allowInsecure bool) (*opsdk.Client, error) { +func createSdkClient(apiUrl, apiKey string, skipTlsVerify bool) (*opsdk.Client, error) { if _, err := url.Parse(apiUrl); err != nil { return nil, errors.New("invalid 1panel api url") } @@ -90,7 +89,7 @@ func createSdkClient(apiUrl, apiKey string, allowInsecure bool) (*opsdk.Client, } client := opsdk.NewClient(apiUrl, apiKey) - if allowInsecure { + if skipTlsVerify { client.WithTLSConfig(&tls.Config{InsecureSkipVerify: true}) } diff --git a/internal/pkg/core/deployer/providers/1panel-console/1panel_console_test.go b/internal/pkg/core/deployer/providers/1panel-console/1panel_console_test.go index d4b7cfa9..abec586c 100644 --- a/internal/pkg/core/deployer/providers/1panel-console/1panel_console_test.go +++ b/internal/pkg/core/deployer/providers/1panel-console/1panel_console_test.go @@ -1,4 +1,4 @@ -package onepanelconsole_test +package onepanelconsole_test import ( "context" diff --git a/internal/pkg/core/deployer/providers/1panel-site/1panel_site.go b/internal/pkg/core/deployer/providers/1panel-site/1panel_site.go index 24f5daa3..7d360c77 100644 --- a/internal/pkg/core/deployer/providers/1panel-site/1panel_site.go +++ b/internal/pkg/core/deployer/providers/1panel-site/1panel_site.go @@ -1,4 +1,4 @@ -package onepanelsite +package onepanelsite import ( "context" @@ -9,12 +9,10 @@ import ( "net/url" "strconv" - xerrors "github.com/pkg/errors" - "github.com/usual2970/certimate/internal/pkg/core/deployer" "github.com/usual2970/certimate/internal/pkg/core/uploader" uploadersp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/1panel-ssl" - opsdk "github.com/usual2970/certimate/internal/pkg/vendors/1panel-sdk" + opsdk "github.com/usual2970/certimate/internal/pkg/sdk3rd/1panel" ) type DeployerConfig struct { @@ -50,7 +48,7 @@ func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { client, err := createSdkClient(config.ApiUrl, config.ApiKey, config.AllowInsecureConnections) if err != nil { - return nil, xerrors.Wrap(err, "failed to create sdk client") + return nil, fmt.Errorf("failed to create sdk client: %w", err) } uploader, err := uploadersp.NewUploader(&uploadersp.UploaderConfig{ @@ -58,7 +56,7 @@ func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { ApiKey: config.ApiKey, }) if err != nil { - return nil, xerrors.Wrap(err, "failed to create ssl uploader") + return nil, fmt.Errorf("failed to create ssl uploader: %w", err) } return &DeployerProvider{ @@ -79,27 +77,27 @@ func (d *DeployerProvider) WithLogger(logger *slog.Logger) deployer.Deployer { return d } -func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { +func (d *DeployerProvider) Deploy(ctx context.Context, certPEM string, privkeyPEM string) (*deployer.DeployResult, error) { // 根据部署资源类型决定部署方式 switch d.config.ResourceType { case RESOURCE_TYPE_WEBSITE: - if err := d.deployToWebsite(ctx, certPem, privkeyPem); err != nil { + if err := d.deployToWebsite(ctx, certPEM, privkeyPEM); err != nil { return nil, err } case RESOURCE_TYPE_CERTIFICATE: - if err := d.deployToCertificate(ctx, certPem, privkeyPem); err != nil { + if err := d.deployToCertificate(ctx, certPEM, privkeyPEM); err != nil { return nil, err } default: - return nil, fmt.Errorf("unsupported resource type: %s", d.config.ResourceType) + return nil, fmt.Errorf("unsupported resource type '%s'", d.config.ResourceType) } return &deployer.DeployResult{}, nil } -func (d *DeployerProvider) deployToWebsite(ctx context.Context, certPem string, privkeyPem string) error { +func (d *DeployerProvider) deployToWebsite(ctx context.Context, certPEM string, privkeyPEM string) error { if d.config.WebsiteId == 0 { return errors.New("config `websiteId` is required") } @@ -111,13 +109,13 @@ func (d *DeployerProvider) deployToWebsite(ctx context.Context, certPem string, getHttpsConfResp, err := d.sdkClient.GetHttpsConf(getHttpsConfReq) d.logger.Debug("sdk request '1panel.GetHttpsConf'", slog.Any("request", getHttpsConfReq), slog.Any("response", getHttpsConfResp)) if err != nil { - return xerrors.Wrap(err, "failed to execute sdk request '1panel.GetHttpsConf'") + return fmt.Errorf("failed to execute sdk request '1panel.GetHttpsConf': %w", err) } // 上传证书到面板 - upres, err := d.sslUploader.Upload(ctx, certPem, privkeyPem) + upres, err := d.sslUploader.Upload(ctx, certPEM, privkeyPEM) if err != nil { - return xerrors.Wrap(err, "failed to upload certificate file") + return fmt.Errorf("failed to upload certificate file: %w", err) } else { d.logger.Info("ssl certificate uploaded", slog.Any("result", upres)) } @@ -137,13 +135,13 @@ func (d *DeployerProvider) deployToWebsite(ctx context.Context, certPem string, updateHttpsConfResp, err := d.sdkClient.UpdateHttpsConf(updateHttpsConfReq) d.logger.Debug("sdk request '1panel.UpdateHttpsConf'", slog.Any("request", updateHttpsConfReq), slog.Any("response", updateHttpsConfResp)) if err != nil { - return xerrors.Wrap(err, "failed to execute sdk request '1panel.UpdateHttpsConf'") + return fmt.Errorf("failed to execute sdk request '1panel.UpdateHttpsConf': %w", err) } return nil } -func (d *DeployerProvider) deployToCertificate(ctx context.Context, certPem string, privkeyPem string) error { +func (d *DeployerProvider) deployToCertificate(ctx context.Context, certPEM string, privkeyPEM string) error { if d.config.CertificateId == 0 { return errors.New("config `certificateId` is required") } @@ -155,7 +153,7 @@ func (d *DeployerProvider) deployToCertificate(ctx context.Context, certPem stri getWebsiteSSLResp, err := d.sdkClient.GetWebsiteSSL(getWebsiteSSLReq) d.logger.Debug("sdk request '1panel.GetWebsiteSSL'", slog.Any("request", getWebsiteSSLReq), slog.Any("response", getWebsiteSSLResp)) if err != nil { - return xerrors.Wrap(err, "failed to execute sdk request '1panel.GetWebsiteSSL'") + return fmt.Errorf("failed to execute sdk request '1panel.GetWebsiteSSL': %w", err) } // 更新证书 @@ -163,19 +161,19 @@ func (d *DeployerProvider) deployToCertificate(ctx context.Context, certPem stri Type: "paste", SSLID: d.config.CertificateId, Description: getWebsiteSSLResp.Data.Description, - Certificate: certPem, - PrivateKey: privkeyPem, + Certificate: certPEM, + PrivateKey: privkeyPEM, } uploadWebsiteSSLResp, err := d.sdkClient.UploadWebsiteSSL(uploadWebsiteSSLReq) d.logger.Debug("sdk request '1panel.UploadWebsiteSSL'", slog.Any("request", uploadWebsiteSSLReq), slog.Any("response", uploadWebsiteSSLResp)) if err != nil { - return xerrors.Wrap(err, "failed to execute sdk request '1panel.UploadWebsiteSSL'") + return fmt.Errorf("failed to execute sdk request '1panel.UploadWebsiteSSL': %w", err) } return nil } -func createSdkClient(apiUrl, apiKey string, allowInsecure bool) (*opsdk.Client, error) { +func createSdkClient(apiUrl, apiKey string, skipTlsVerify bool) (*opsdk.Client, error) { if _, err := url.Parse(apiUrl); err != nil { return nil, errors.New("invalid 1panel api url") } @@ -185,7 +183,7 @@ func createSdkClient(apiUrl, apiKey string, allowInsecure bool) (*opsdk.Client, } client := opsdk.NewClient(apiUrl, apiKey) - if allowInsecure { + if skipTlsVerify { client.WithTLSConfig(&tls.Config{InsecureSkipVerify: true}) } diff --git a/internal/pkg/core/deployer/providers/1panel-site/1panel_site_test.go b/internal/pkg/core/deployer/providers/1panel-site/1panel_site_test.go index 5815fd5e..702584e3 100644 --- a/internal/pkg/core/deployer/providers/1panel-site/1panel_site_test.go +++ b/internal/pkg/core/deployer/providers/1panel-site/1panel_site_test.go @@ -1,4 +1,4 @@ -package onepanelsite_test +package onepanelsite_test import ( "context" diff --git a/internal/pkg/core/deployer/providers/1panel-site/consts.go b/internal/pkg/core/deployer/providers/1panel-site/consts.go index caba1d5c..85f85a0d 100644 --- a/internal/pkg/core/deployer/providers/1panel-site/consts.go +++ b/internal/pkg/core/deployer/providers/1panel-site/consts.go @@ -1,4 +1,4 @@ -package onepanelsite +package onepanelsite type ResourceType string diff --git a/internal/pkg/core/deployer/providers/aliyun-alb/aliyun_alb.go b/internal/pkg/core/deployer/providers/aliyun-alb/aliyun_alb.go index a019917a..3dca4a9d 100644 --- a/internal/pkg/core/deployer/providers/aliyun-alb/aliyun_alb.go +++ b/internal/pkg/core/deployer/providers/aliyun-alb/aliyun_alb.go @@ -1,4 +1,4 @@ -package aliyunalb +package aliyunalb import ( "context" @@ -13,7 +13,6 @@ import ( alicas "github.com/alibabacloud-go/cas-20200407/v3/client" aliopen "github.com/alibabacloud-go/darabonba-openapi/v2/client" "github.com/alibabacloud-go/tea/tea" - xerrors "github.com/pkg/errors" "golang.org/x/exp/slices" "github.com/usual2970/certimate/internal/pkg/core/deployer" @@ -62,12 +61,12 @@ func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { clients, err := createSdkClients(config.AccessKeyId, config.AccessKeySecret, config.Region) if err != nil { - return nil, xerrors.Wrap(err, "failed to create sdk clients") + return nil, fmt.Errorf("failed to create sdk clients: %w", err) } uploader, err := createSslUploader(config.AccessKeyId, config.AccessKeySecret, config.Region) if err != nil { - return nil, xerrors.Wrap(err, "failed to create ssl uploader") + return nil, fmt.Errorf("failed to create ssl uploader: %w", err) } return &DeployerProvider{ @@ -88,11 +87,11 @@ func (d *DeployerProvider) WithLogger(logger *slog.Logger) deployer.Deployer { return d } -func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { +func (d *DeployerProvider) Deploy(ctx context.Context, certPEM string, privkeyPEM string) (*deployer.DeployResult, error) { // 上传证书到 CAS - upres, err := d.sslUploader.Upload(ctx, certPem, privkeyPem) + upres, err := d.sslUploader.Upload(ctx, certPEM, privkeyPEM) if err != nil { - return nil, xerrors.Wrap(err, "failed to upload certificate file") + return nil, fmt.Errorf("failed to upload certificate file: %w", err) } else { d.logger.Info("ssl certificate uploaded", slog.Any("result", upres)) } @@ -110,7 +109,7 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPe } default: - return nil, fmt.Errorf("unsupported resource type: %s", d.config.ResourceType) + return nil, fmt.Errorf("unsupported resource type '%s'", d.config.ResourceType) } return &deployer.DeployResult{}, nil @@ -129,7 +128,7 @@ func (d *DeployerProvider) deployToLoadbalancer(ctx context.Context, cloudCertId getLoadBalancerAttributeResp, err := d.sdkClients.ALB.GetLoadBalancerAttribute(getLoadBalancerAttributeReq) d.logger.Debug("sdk request 'alb.GetLoadBalancerAttribute'", slog.Any("request", getLoadBalancerAttributeReq), slog.Any("response", getLoadBalancerAttributeResp)) if err != nil { - return xerrors.Wrap(err, "failed to execute sdk request 'alb.GetLoadBalancerAttribute'") + return fmt.Errorf("failed to execute sdk request 'alb.GetLoadBalancerAttribute': %w", err) } // 查询 HTTPS 监听列表 @@ -138,6 +137,12 @@ func (d *DeployerProvider) deployToLoadbalancer(ctx context.Context, cloudCertId listListenersLimit := int32(100) var listListenersToken *string = nil for { + select { + case <-ctx.Done(): + return ctx.Err() + default: + } + listListenersReq := &alialb.ListListenersRequest{ MaxResults: tea.Int32(listListenersLimit), NextToken: listListenersToken, @@ -147,7 +152,7 @@ func (d *DeployerProvider) deployToLoadbalancer(ctx context.Context, cloudCertId listListenersResp, err := d.sdkClients.ALB.ListListeners(listListenersReq) d.logger.Debug("sdk request 'alb.ListListeners'", slog.Any("request", listListenersReq), slog.Any("response", listListenersResp)) if err != nil { - return xerrors.Wrap(err, "failed to execute sdk request 'alb.ListListeners'") + return fmt.Errorf("failed to execute sdk request 'alb.ListListeners': %w", err) } if listListenersResp.Body.Listeners != nil { @@ -167,6 +172,12 @@ func (d *DeployerProvider) deployToLoadbalancer(ctx context.Context, cloudCertId // REF: https://help.aliyun.com/zh/slb/application-load-balancer/developer-reference/api-alb-2020-06-16-listlisteners listListenersToken = nil for { + select { + case <-ctx.Done(): + return ctx.Err() + default: + } + listListenersReq := &alialb.ListListenersRequest{ MaxResults: tea.Int32(listListenersLimit), NextToken: listListenersToken, @@ -176,7 +187,7 @@ func (d *DeployerProvider) deployToLoadbalancer(ctx context.Context, cloudCertId listListenersResp, err := d.sdkClients.ALB.ListListeners(listListenersReq) d.logger.Debug("sdk request 'alb.ListListeners'", slog.Any("request", listListenersReq), slog.Any("response", listListenersResp)) if err != nil { - return xerrors.Wrap(err, "failed to execute sdk request 'alb.ListListeners'") + return fmt.Errorf("failed to execute sdk request 'alb.ListListeners': %w", err) } if listListenersResp.Body.Listeners != nil { @@ -235,7 +246,7 @@ func (d *DeployerProvider) updateListenerCertificate(ctx context.Context, cloudL getListenerAttributeResp, err := d.sdkClients.ALB.GetListenerAttribute(getListenerAttributeReq) d.logger.Debug("sdk request 'alb.GetListenerAttribute'", slog.Any("request", getListenerAttributeReq), slog.Any("response", getListenerAttributeResp)) if err != nil { - return xerrors.Wrap(err, "failed to execute sdk request 'alb.GetListenerAttribute'") + return fmt.Errorf("failed to execute sdk request 'alb.GetListenerAttribute': %w", err) } if d.config.Domain == "" { @@ -252,7 +263,7 @@ func (d *DeployerProvider) updateListenerCertificate(ctx context.Context, cloudL updateListenerAttributeResp, err := d.sdkClients.ALB.UpdateListenerAttribute(updateListenerAttributeReq) d.logger.Debug("sdk request 'alb.UpdateListenerAttribute'", slog.Any("request", updateListenerAttributeReq), slog.Any("response", updateListenerAttributeResp)) if err != nil { - return xerrors.Wrap(err, "failed to execute sdk request 'alb.UpdateListenerAttribute'") + return fmt.Errorf("failed to execute sdk request 'alb.UpdateListenerAttribute': %w", err) } } else { // 指定 SNI,需部署到扩展域名 @@ -263,6 +274,12 @@ func (d *DeployerProvider) updateListenerCertificate(ctx context.Context, cloudL listListenerCertificatesLimit := int32(100) var listListenerCertificatesToken *string = nil for { + select { + case <-ctx.Done(): + return ctx.Err() + default: + } + listListenerCertificatesReq := &alialb.ListListenerCertificatesRequest{ NextToken: listListenerCertificatesToken, MaxResults: tea.Int32(listListenerCertificatesLimit), @@ -272,7 +289,7 @@ func (d *DeployerProvider) updateListenerCertificate(ctx context.Context, cloudL listListenerCertificatesResp, err := d.sdkClients.ALB.ListListenerCertificates(listListenerCertificatesReq) d.logger.Debug("sdk request 'alb.ListListenerCertificates'", slog.Any("request", listListenerCertificatesReq), slog.Any("response", listListenerCertificatesResp)) if err != nil { - return xerrors.Wrap(err, "failed to execute sdk request 'alb.ListListenerCertificates'") + return fmt.Errorf("failed to execute sdk request 'alb.ListListenerCertificates': %w", err) } if listListenerCertificatesResp.Body.Certificates != nil { @@ -331,7 +348,7 @@ func (d *DeployerProvider) updateListenerCertificate(ctx context.Context, cloudL } } - errs = append(errs, xerrors.Wrap(err, "failed to execute sdk request 'cas.GetUserCertificateDetail'")) + errs = append(errs, fmt.Errorf("failed to execute sdk request 'cas.GetUserCertificateDetail': %w", err)) continue } else { certCNMatched := tea.StringValue(getUserCertificateDetailResp.Body.Common) == d.config.Domain @@ -368,7 +385,7 @@ func (d *DeployerProvider) updateListenerCertificate(ctx context.Context, cloudL associateAdditionalCertificatesFromListenerResp, err := d.sdkClients.ALB.AssociateAdditionalCertificatesWithListener(associateAdditionalCertificatesFromListenerReq) d.logger.Debug("sdk request 'alb.AssociateAdditionalCertificatesWithListener'", slog.Any("request", associateAdditionalCertificatesFromListenerReq), slog.Any("response", associateAdditionalCertificatesFromListenerResp)) if err != nil { - return xerrors.Wrap(err, "failed to execute sdk request 'alb.AssociateAdditionalCertificatesWithListener'") + return fmt.Errorf("failed to execute sdk request 'alb.AssociateAdditionalCertificatesWithListener': %w", err) } } @@ -389,7 +406,7 @@ func (d *DeployerProvider) updateListenerCertificate(ctx context.Context, cloudL dissociateAdditionalCertificatesFromListenerResp, err := d.sdkClients.ALB.DissociateAdditionalCertificatesFromListener(dissociateAdditionalCertificatesFromListenerReq) d.logger.Debug("sdk request 'alb.DissociateAdditionalCertificatesFromListener'", slog.Any("request", dissociateAdditionalCertificatesFromListenerReq), slog.Any("response", dissociateAdditionalCertificatesFromListenerResp)) if err != nil { - return xerrors.Wrap(err, "failed to execute sdk request 'alb.DissociateAdditionalCertificatesFromListener'") + return fmt.Errorf("failed to execute sdk request 'alb.DissociateAdditionalCertificatesFromListener': %w", err) } } } @@ -447,7 +464,7 @@ func createSslUploader(accessKeyId, accessKeySecret, region string) (uploader.Up // 阿里云 CAS 服务接入点是独立于 ALB 服务的 // 国内版固定接入点:华东一杭州 // 国际版固定接入点:亚太东南一新加坡 - if casRegion != "" && !strings.HasPrefix(casRegion, "cn-") { + if !strings.HasPrefix(casRegion, "cn-") { casRegion = "ap-southeast-1" } else { casRegion = "cn-hangzhou" 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 b5ae776a..c75119e9 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 @@ -1,4 +1,4 @@ -package aliyunalb_test +package aliyunalb_test import ( "context" diff --git a/internal/pkg/core/deployer/providers/aliyun-alb/consts.go b/internal/pkg/core/deployer/providers/aliyun-alb/consts.go index a2d1aacc..286aef00 100644 --- a/internal/pkg/core/deployer/providers/aliyun-alb/consts.go +++ b/internal/pkg/core/deployer/providers/aliyun-alb/consts.go @@ -1,4 +1,4 @@ -package aliyunalb +package aliyunalb type ResourceType string diff --git a/internal/pkg/core/deployer/providers/aliyun-apigw/aliyun_apigw.go b/internal/pkg/core/deployer/providers/aliyun-apigw/aliyun_apigw.go index 12b43616..d74c7c27 100644 --- a/internal/pkg/core/deployer/providers/aliyun-apigw/aliyun_apigw.go +++ b/internal/pkg/core/deployer/providers/aliyun-apigw/aliyun_apigw.go @@ -1,4 +1,4 @@ -package aliyunapigw +package aliyunapigw import ( "context" @@ -12,7 +12,6 @@ import ( alicloudapi "github.com/alibabacloud-go/cloudapi-20160714/v5/client" aliopen "github.com/alibabacloud-go/darabonba-openapi/v2/client" "github.com/alibabacloud-go/tea/tea" - xerrors "github.com/pkg/errors" "github.com/usual2970/certimate/internal/pkg/core/deployer" "github.com/usual2970/certimate/internal/pkg/core/uploader" @@ -59,12 +58,12 @@ func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { clients, err := createSdkClients(config.AccessKeyId, config.AccessKeySecret, config.Region) if err != nil { - return nil, xerrors.Wrap(err, "failed to create sdk clients") + return nil, fmt.Errorf("failed to create sdk clients: %w", err) } uploader, err := createSslUploader(config.AccessKeyId, config.AccessKeySecret, config.Region) if err != nil { - return nil, xerrors.Wrap(err, "failed to create ssl uploader") + return nil, fmt.Errorf("failed to create ssl uploader: %w", err) } return &DeployerProvider{ @@ -84,26 +83,26 @@ func (d *DeployerProvider) WithLogger(logger *slog.Logger) deployer.Deployer { return d } -func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { +func (d *DeployerProvider) Deploy(ctx context.Context, certPEM string, privkeyPEM string) (*deployer.DeployResult, error) { switch d.config.ServiceType { case SERVICE_TYPE_TRADITIONAL: - if err := d.deployToTraditional(ctx, certPem, privkeyPem); err != nil { + if err := d.deployToTraditional(ctx, certPEM, privkeyPEM); err != nil { return nil, err } case SERVICE_TYPE_CLOUDNATIVE: - if err := d.deployToCloudNative(ctx, certPem, privkeyPem); err != nil { + if err := d.deployToCloudNative(ctx, certPEM, privkeyPEM); err != nil { return nil, err } default: - return nil, xerrors.Errorf("unsupported service type: %s", string(d.config.ServiceType)) + return nil, fmt.Errorf("unsupported service type '%s'", string(d.config.ServiceType)) } return &deployer.DeployResult{}, nil } -func (d *DeployerProvider) deployToTraditional(ctx context.Context, certPem string, privkeyPem string) error { +func (d *DeployerProvider) deployToTraditional(ctx context.Context, certPEM string, privkeyPEM string) error { if d.config.GroupId == "" { return errors.New("config `groupId` is required") } @@ -117,19 +116,19 @@ func (d *DeployerProvider) deployToTraditional(ctx context.Context, certPem stri GroupId: tea.String(d.config.GroupId), DomainName: tea.String(d.config.Domain), CertificateName: tea.String(fmt.Sprintf("certimate_%d", time.Now().UnixMilli())), - CertificateBody: tea.String(certPem), - CertificatePrivateKey: tea.String(privkeyPem), + CertificateBody: tea.String(certPEM), + CertificatePrivateKey: tea.String(privkeyPEM), } setDomainCertificateResp, err := d.sdkClients.TraditionalAPIGateway.SetDomainCertificate(setDomainCertificateReq) d.logger.Debug("sdk request 'apigateway.SetDomainCertificate'", slog.Any("request", setDomainCertificateReq), slog.Any("response", setDomainCertificateResp)) if err != nil { - return xerrors.Wrap(err, "failed to execute sdk request 'apigateway.SetDomainCertificate'") + return fmt.Errorf("failed to execute sdk request 'apigateway.SetDomainCertificate': %w", err) } return nil } -func (d *DeployerProvider) deployToCloudNative(ctx context.Context, certPem string, privkeyPem string) error { +func (d *DeployerProvider) deployToCloudNative(ctx context.Context, certPEM string, privkeyPEM string) error { if d.config.GatewayId == "" { return errors.New("config `gatewayId` is required") } @@ -143,6 +142,12 @@ func (d *DeployerProvider) deployToCloudNative(ctx context.Context, certPem stri listDomainsPageNumber := int32(1) listDomainsPageSize := int32(10) for { + select { + case <-ctx.Done(): + return ctx.Err() + default: + } + listDomainsReq := &aliapig.ListDomainsRequest{ GatewayId: tea.String(d.config.GatewayId), NameLike: tea.String(d.config.Domain), @@ -152,7 +157,7 @@ func (d *DeployerProvider) deployToCloudNative(ctx context.Context, certPem stri listDomainsResp, err := d.sdkClients.CloudNativeAPIGateway.ListDomains(listDomainsReq) d.logger.Debug("sdk request 'apig.ListDomains'", slog.Any("request", listDomainsReq), slog.Any("response", listDomainsResp)) if err != nil { - return xerrors.Wrap(err, "failed to execute sdk request 'apig.ListDomains'") + return fmt.Errorf("failed to execute sdk request 'apig.ListDomains': %w", err) } if listDomainsResp.Body.Data.Items != nil { @@ -184,13 +189,13 @@ func (d *DeployerProvider) deployToCloudNative(ctx context.Context, certPem stri getDomainResp, err := d.sdkClients.CloudNativeAPIGateway.GetDomain(tea.String(domainId), getDomainReq) d.logger.Debug("sdk request 'apig.GetDomain'", slog.Any("domainId", domainId), slog.Any("request", getDomainReq), slog.Any("response", getDomainResp)) if err != nil { - return xerrors.Wrap(err, "failed to execute sdk request 'apig.GetDomain'") + return fmt.Errorf("failed to execute sdk request 'apig.GetDomain': %w", err) } // 上传证书到 CAS - upres, err := d.sslUploader.Upload(ctx, certPem, privkeyPem) + upres, err := d.sslUploader.Upload(ctx, certPEM, privkeyPEM) if err != nil { - return xerrors.Wrap(err, "failed to upload certificate file") + return fmt.Errorf("failed to upload certificate file: %w", err) } else { d.logger.Info("ssl certificate uploaded", slog.Any("result", upres)) } @@ -210,7 +215,7 @@ func (d *DeployerProvider) deployToCloudNative(ctx context.Context, certPem stri updateDomainResp, err := d.sdkClients.CloudNativeAPIGateway.UpdateDomain(tea.String(domainId), updateDomainReq) d.logger.Debug("sdk request 'apig.UpdateDomain'", slog.Any("domainId", domainId), slog.Any("request", updateDomainReq), slog.Any("response", updateDomainResp)) if err != nil { - return xerrors.Wrap(err, "failed to execute sdk request 'apig.UpdateDomain'") + return fmt.Errorf("failed to execute sdk request 'apig.UpdateDomain': %w", err) } return nil @@ -253,7 +258,7 @@ func createSslUploader(accessKeyId, accessKeySecret, region string) (uploader.Up // 阿里云 CAS 服务接入点是独立于 APIGateway 服务的 // 国内版固定接入点:华东一杭州 // 国际版固定接入点:亚太东南一新加坡 - if casRegion != "" && !strings.HasPrefix(casRegion, "cn-") { + if !strings.HasPrefix(casRegion, "cn-") { casRegion = "ap-southeast-1" } else { casRegion = "cn-hangzhou" diff --git a/internal/pkg/core/deployer/providers/aliyun-apigw/aliyun_apigw_test.go b/internal/pkg/core/deployer/providers/aliyun-apigw/aliyun_apigw_test.go index dab028e2..7807a927 100644 --- a/internal/pkg/core/deployer/providers/aliyun-apigw/aliyun_apigw_test.go +++ b/internal/pkg/core/deployer/providers/aliyun-apigw/aliyun_apigw_test.go @@ -1,4 +1,4 @@ -package aliyunapigw_test +package aliyunapigw_test import ( "context" diff --git a/internal/pkg/core/deployer/providers/aliyun-apigw/consts.go b/internal/pkg/core/deployer/providers/aliyun-apigw/consts.go index b53c7645..1abe97e3 100644 --- a/internal/pkg/core/deployer/providers/aliyun-apigw/consts.go +++ b/internal/pkg/core/deployer/providers/aliyun-apigw/consts.go @@ -1,4 +1,4 @@ -package aliyunapigw +package aliyunapigw type ServiceType string diff --git a/internal/pkg/core/deployer/providers/aliyun-cas-deploy/aliyun_cas_deploy.go b/internal/pkg/core/deployer/providers/aliyun-cas-deploy/aliyun_cas_deploy.go index b50e8c5d..077dea5c 100644 --- a/internal/pkg/core/deployer/providers/aliyun-cas-deploy/aliyun_cas_deploy.go +++ b/internal/pkg/core/deployer/providers/aliyun-cas-deploy/aliyun_cas_deploy.go @@ -1,4 +1,4 @@ -package aliyuncasdeploy +package aliyuncasdeploy import ( "context" @@ -11,7 +11,6 @@ import ( alicas "github.com/alibabacloud-go/cas-20200407/v3/client" aliopen "github.com/alibabacloud-go/darabonba-openapi/v2/client" "github.com/alibabacloud-go/tea/tea" - xerrors "github.com/pkg/errors" "github.com/usual2970/certimate/internal/pkg/core/deployer" "github.com/usual2970/certimate/internal/pkg/core/uploader" @@ -48,7 +47,7 @@ func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { client, err := createSdkClient(config.AccessKeyId, config.AccessKeySecret, config.Region) if err != nil { - return nil, xerrors.Wrap(err, "failed to create sdk client") + return nil, fmt.Errorf("failed to create sdk client: %w", err) } uploader, err := uploadersp.NewUploader(&uploadersp.UploaderConfig{ @@ -57,7 +56,7 @@ func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { Region: config.Region, }) if err != nil { - return nil, xerrors.Wrap(err, "failed to create ssl uploader") + return nil, fmt.Errorf("failed to create ssl uploader: %w", err) } return &DeployerProvider{ @@ -78,15 +77,15 @@ func (d *DeployerProvider) WithLogger(logger *slog.Logger) deployer.Deployer { return d } -func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { +func (d *DeployerProvider) Deploy(ctx context.Context, certPEM string, privkeyPEM string) (*deployer.DeployResult, error) { if len(d.config.ResourceIds) == 0 { return nil, errors.New("config `resourceIds` is required") } // 上传证书到 CAS - upres, err := d.sslUploader.Upload(ctx, certPem, privkeyPem) + upres, err := d.sslUploader.Upload(ctx, certPEM, privkeyPEM) if err != nil { - return nil, xerrors.Wrap(err, "failed to upload certificate file") + return nil, fmt.Errorf("failed to upload certificate file: %w", err) } else { d.logger.Info("ssl certificate uploaded", slog.Any("result", upres)) } @@ -101,7 +100,7 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPe listContactResp, err := d.sdkClient.ListContact(listContactReq) d.logger.Debug("sdk request 'cas.ListContact'", slog.Any("request", listContactReq), slog.Any("response", listContactResp)) if err != nil { - return nil, xerrors.Wrap(err, "failed to execute sdk request 'cas.ListContact'") + return nil, fmt.Errorf("failed to execute sdk request 'cas.ListContact': %w", err) } if len(listContactResp.Body.ContactList) > 0 { @@ -121,14 +120,16 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPe createDeploymentJobResp, err := d.sdkClient.CreateDeploymentJob(createDeploymentJobReq) d.logger.Debug("sdk request 'cas.CreateDeploymentJob'", slog.Any("request", createDeploymentJobReq), slog.Any("response", createDeploymentJobResp)) if err != nil { - return nil, xerrors.Wrap(err, "failed to execute sdk request 'cas.CreateDeploymentJob'") + return nil, fmt.Errorf("failed to execute sdk request 'cas.CreateDeploymentJob': %w", err) } // 循环获取部署任务详情,等待任务状态变更 // REF: https://help.aliyun.com/zh/ssl-certificate/developer-reference/api-cas-2020-04-07-describedeploymentjob for { - if ctx.Err() != nil { + select { + case <-ctx.Done(): return nil, ctx.Err() + default: } describeDeploymentJobReq := &alicas.DescribeDeploymentJobRequest{ @@ -137,7 +138,7 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPe describeDeploymentJobResp, err := d.sdkClient.DescribeDeploymentJob(describeDeploymentJobReq) d.logger.Debug("sdk request 'cas.DescribeDeploymentJob'", slog.Any("request", describeDeploymentJobReq), slog.Any("response", describeDeploymentJobResp)) if err != nil { - return nil, xerrors.Wrap(err, "failed to execute sdk request 'cas.DescribeDeploymentJob'") + return nil, fmt.Errorf("failed to execute sdk request 'cas.DescribeDeploymentJob': %w", err) } if describeDeploymentJobResp.Body.Status == nil || *describeDeploymentJobResp.Body.Status == "editing" { diff --git a/internal/pkg/core/deployer/providers/aliyun-cas/aliyun_cas.go b/internal/pkg/core/deployer/providers/aliyun-cas/aliyun_cas.go index e00d3788..56681e57 100644 --- a/internal/pkg/core/deployer/providers/aliyun-cas/aliyun_cas.go +++ b/internal/pkg/core/deployer/providers/aliyun-cas/aliyun_cas.go @@ -1,11 +1,10 @@ -package aliyuncas +package aliyuncas import ( "context" + "fmt" "log/slog" - xerrors "github.com/pkg/errors" - "github.com/usual2970/certimate/internal/pkg/core/deployer" "github.com/usual2970/certimate/internal/pkg/core/uploader" uploadersp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/aliyun-cas" @@ -39,7 +38,7 @@ func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { Region: config.Region, }) if err != nil { - return nil, xerrors.Wrap(err, "failed to create ssl uploader") + return nil, fmt.Errorf("failed to create ssl uploader: %w", err) } return &DeployerProvider{ @@ -59,11 +58,11 @@ func (d *DeployerProvider) WithLogger(logger *slog.Logger) deployer.Deployer { return d } -func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { +func (d *DeployerProvider) Deploy(ctx context.Context, certPEM string, privkeyPEM string) (*deployer.DeployResult, error) { // 上传证书到 CAS - upres, err := d.sslUploader.Upload(ctx, certPem, privkeyPem) + upres, err := d.sslUploader.Upload(ctx, certPEM, privkeyPEM) if err != nil { - return nil, xerrors.Wrap(err, "failed to upload certificate file") + return nil, fmt.Errorf("failed to upload certificate file: %w", err) } else { d.logger.Info("ssl certificate uploaded", slog.Any("result", upres)) } diff --git a/internal/pkg/core/deployer/providers/aliyun-cdn/aliyun_cdn.go b/internal/pkg/core/deployer/providers/aliyun-cdn/aliyun_cdn.go index 2a9be884..ce5f9fd8 100644 --- a/internal/pkg/core/deployer/providers/aliyun-cdn/aliyun_cdn.go +++ b/internal/pkg/core/deployer/providers/aliyun-cdn/aliyun_cdn.go @@ -1,4 +1,4 @@ -package aliyuncdn +package aliyuncdn import ( "context" @@ -10,7 +10,6 @@ import ( alicdn "github.com/alibabacloud-go/cdn-20180510/v5/client" aliopen "github.com/alibabacloud-go/darabonba-openapi/v2/client" "github.com/alibabacloud-go/tea/tea" - xerrors "github.com/pkg/errors" "github.com/usual2970/certimate/internal/pkg/core/deployer" ) @@ -39,7 +38,7 @@ func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { client, err := createSdkClient(config.AccessKeyId, config.AccessKeySecret) if err != nil { - return nil, xerrors.Wrap(err, "failed to create sdk client") + return nil, fmt.Errorf("failed to create sdk client: %w", err) } return &DeployerProvider{ @@ -58,7 +57,7 @@ func (d *DeployerProvider) WithLogger(logger *slog.Logger) deployer.Deployer { return d } -func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { +func (d *DeployerProvider) Deploy(ctx context.Context, certPEM string, privkeyPEM string) (*deployer.DeployResult, error) { // "*.example.com" → ".example.com",适配阿里云 CDN 要求的泛域名格式 domain := strings.TrimPrefix(d.config.Domain, "*") @@ -69,13 +68,13 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPe CertName: tea.String(fmt.Sprintf("certimate-%d", time.Now().UnixMilli())), CertType: tea.String("upload"), SSLProtocol: tea.String("on"), - SSLPub: tea.String(certPem), - SSLPri: tea.String(privkeyPem), + SSLPub: tea.String(certPEM), + SSLPri: tea.String(privkeyPEM), } setCdnDomainSSLCertificateResp, err := d.sdkClient.SetCdnDomainSSLCertificate(setCdnDomainSSLCertificateReq) d.logger.Debug("sdk request 'cdn.SetCdnDomainSSLCertificate'", slog.Any("request", setCdnDomainSSLCertificateReq), slog.Any("response", setCdnDomainSSLCertificateResp)) if err != nil { - return nil, xerrors.Wrap(err, "failed to execute sdk request 'cdn.SetCdnDomainSSLCertificate'") + return nil, fmt.Errorf("failed to execute sdk request 'cdn.SetCdnDomainSSLCertificate': %w", err) } return &deployer.DeployResult{}, nil 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 1f92947f..b07611da 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 @@ -1,4 +1,4 @@ -package aliyuncdn_test +package aliyuncdn_test import ( "context" diff --git a/internal/pkg/core/deployer/providers/aliyun-clb/aliyun_clb.go b/internal/pkg/core/deployer/providers/aliyun-clb/aliyun_clb.go index 2fcdd0f0..41a78968 100644 --- a/internal/pkg/core/deployer/providers/aliyun-clb/aliyun_clb.go +++ b/internal/pkg/core/deployer/providers/aliyun-clb/aliyun_clb.go @@ -1,15 +1,15 @@ -package aliyunclb +package aliyunclb import ( "context" "errors" "fmt" "log/slog" + "strings" aliopen "github.com/alibabacloud-go/darabonba-openapi/v2/client" alislb "github.com/alibabacloud-go/slb-20140515/v4/client" "github.com/alibabacloud-go/tea/tea" - xerrors "github.com/pkg/errors" "github.com/usual2970/certimate/internal/pkg/core/deployer" "github.com/usual2970/certimate/internal/pkg/core/uploader" @@ -52,16 +52,12 @@ func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { client, err := createSdkClient(config.AccessKeyId, config.AccessKeySecret, config.Region) if err != nil { - return nil, xerrors.Wrap(err, "failed to create sdk client") + return nil, fmt.Errorf("failed to create sdk client: %w", err) } - uploader, err := uploadersp.NewUploader(&uploadersp.UploaderConfig{ - AccessKeyId: config.AccessKeyId, - AccessKeySecret: config.AccessKeySecret, - Region: config.Region, - }) + uploader, err := createSslUploader(config.AccessKeyId, config.AccessKeySecret, config.Region) if err != nil { - return nil, xerrors.Wrap(err, "failed to create ssl uploader") + return nil, fmt.Errorf("failed to create ssl uploader: %w", err) } return &DeployerProvider{ @@ -82,11 +78,11 @@ func (d *DeployerProvider) WithLogger(logger *slog.Logger) deployer.Deployer { return d } -func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { +func (d *DeployerProvider) Deploy(ctx context.Context, certPEM string, privkeyPEM string) (*deployer.DeployResult, error) { // 上传证书到 SLB - upres, err := d.sslUploader.Upload(ctx, certPem, privkeyPem) + upres, err := d.sslUploader.Upload(ctx, certPEM, privkeyPEM) if err != nil { - return nil, xerrors.Wrap(err, "failed to upload certificate file") + return nil, fmt.Errorf("failed to upload certificate file: %w", err) } else { d.logger.Info("ssl certificate uploaded", slog.Any("result", upres)) } @@ -104,7 +100,7 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPe } default: - return nil, fmt.Errorf("unsupported resource type: %s", d.config.ResourceType) + return nil, fmt.Errorf("unsupported resource type '%s'", d.config.ResourceType) } return &deployer.DeployResult{}, nil @@ -124,7 +120,7 @@ func (d *DeployerProvider) deployToLoadbalancer(ctx context.Context, cloudCertId describeLoadBalancerAttributeResp, err := d.sdkClient.DescribeLoadBalancerAttribute(describeLoadBalancerAttributeReq) d.logger.Debug("sdk request 'slb.DescribeLoadBalancerAttribute'", slog.Any("request", describeLoadBalancerAttributeReq), slog.Any("response", describeLoadBalancerAttributeResp)) if err != nil { - return xerrors.Wrap(err, "failed to execute sdk request 'slb.DescribeLoadBalancerAttribute'") + return fmt.Errorf("failed to execute sdk request 'slb.DescribeLoadBalancerAttribute': %w", err) } // 查询 HTTPS 监听列表 @@ -133,6 +129,12 @@ func (d *DeployerProvider) deployToLoadbalancer(ctx context.Context, cloudCertId describeLoadBalancerListenersLimit := int32(100) var describeLoadBalancerListenersToken *string = nil for { + select { + case <-ctx.Done(): + return ctx.Err() + default: + } + describeLoadBalancerListenersReq := &alislb.DescribeLoadBalancerListenersRequest{ RegionId: tea.String(d.config.Region), MaxResults: tea.Int32(describeLoadBalancerListenersLimit), @@ -143,7 +145,7 @@ func (d *DeployerProvider) deployToLoadbalancer(ctx context.Context, cloudCertId describeLoadBalancerListenersResp, err := d.sdkClient.DescribeLoadBalancerListeners(describeLoadBalancerListenersReq) d.logger.Debug("sdk request 'slb.DescribeLoadBalancerListeners'", slog.Any("request", describeLoadBalancerListenersReq), slog.Any("response", describeLoadBalancerListenersResp)) if err != nil { - return xerrors.Wrap(err, "failed to execute sdk request 'slb.DescribeLoadBalancerListeners'") + return fmt.Errorf("failed to execute sdk request 'slb.DescribeLoadBalancerListeners': %w", err) } if describeLoadBalancerListenersResp.Body.Listeners != nil { @@ -167,8 +169,14 @@ func (d *DeployerProvider) deployToLoadbalancer(ctx context.Context, cloudCertId var errs []error for _, listenerPort := range listenerPorts { - if err := d.updateListenerCertificate(ctx, d.config.LoadbalancerId, listenerPort, cloudCertId); err != nil { - errs = append(errs, err) + select { + case <-ctx.Done(): + return ctx.Err() + + default: + if err := d.updateListenerCertificate(ctx, d.config.LoadbalancerId, listenerPort, cloudCertId); err != nil { + errs = append(errs, err) + } } } @@ -206,7 +214,7 @@ func (d *DeployerProvider) updateListenerCertificate(ctx context.Context, cloudL describeLoadBalancerHTTPSListenerAttributeResp, err := d.sdkClient.DescribeLoadBalancerHTTPSListenerAttribute(describeLoadBalancerHTTPSListenerAttributeReq) d.logger.Debug("sdk request 'slb.DescribeLoadBalancerHTTPSListenerAttribute'", slog.Any("request", describeLoadBalancerHTTPSListenerAttributeReq), slog.Any("response", describeLoadBalancerHTTPSListenerAttributeResp)) if err != nil { - return xerrors.Wrap(err, "failed to execute sdk request 'slb.DescribeLoadBalancerHTTPSListenerAttribute'") + return fmt.Errorf("failed to execute sdk request 'slb.DescribeLoadBalancerHTTPSListenerAttribute': %w", err) } if d.config.Domain == "" { @@ -223,7 +231,7 @@ func (d *DeployerProvider) updateListenerCertificate(ctx context.Context, cloudL setLoadBalancerHTTPSListenerAttributeResp, err := d.sdkClient.SetLoadBalancerHTTPSListenerAttribute(setLoadBalancerHTTPSListenerAttributeReq) d.logger.Debug("sdk request 'slb.SetLoadBalancerHTTPSListenerAttribute'", slog.Any("request", setLoadBalancerHTTPSListenerAttributeReq), slog.Any("response", setLoadBalancerHTTPSListenerAttributeResp)) if err != nil { - return xerrors.Wrap(err, "failed to execute sdk request 'slb.SetLoadBalancerHTTPSListenerAttribute'") + return fmt.Errorf("failed to execute sdk request 'slb.SetLoadBalancerHTTPSListenerAttribute': %w", err) } } else { // 指定 SNI,需部署到扩展域名 @@ -238,7 +246,7 @@ func (d *DeployerProvider) updateListenerCertificate(ctx context.Context, cloudL describeDomainExtensionsResp, err := d.sdkClient.DescribeDomainExtensions(describeDomainExtensionsReq) d.logger.Debug("sdk request 'slb.DescribeDomainExtensions'", slog.Any("request", describeDomainExtensionsReq), slog.Any("response", describeDomainExtensionsResp)) if err != nil { - return xerrors.Wrap(err, "failed to execute sdk request 'slb.DescribeDomainExtensions'") + return fmt.Errorf("failed to execute sdk request 'slb.DescribeDomainExtensions': %w", err) } // 遍历修改扩展域名 @@ -259,7 +267,7 @@ func (d *DeployerProvider) updateListenerCertificate(ctx context.Context, cloudL setDomainExtensionAttributeResp, err := d.sdkClient.SetDomainExtensionAttribute(setDomainExtensionAttributeReq) d.logger.Debug("sdk request 'slb.SetDomainExtensionAttribute'", slog.Any("request", setDomainExtensionAttributeReq), slog.Any("response", setDomainExtensionAttributeResp)) if err != nil { - errs = append(errs, xerrors.Wrap(err, "failed to execute sdk request 'slb.SetDomainExtensionAttribute'")) + errs = append(errs, fmt.Errorf("failed to execute sdk request 'slb.SetDomainExtensionAttribute': %w", err)) continue } } @@ -300,3 +308,24 @@ func createSdkClient(accessKeyId, accessKeySecret, region string) (*alislb.Clien return client, nil } + +func createSslUploader(accessKeyId, accessKeySecret, region string) (uploader.Uploader, error) { + casRegion := region + if casRegion != "" { + // 阿里云 CAS 服务接入点是独立于 CLB 服务的 + // 国内版固定接入点:华东一杭州 + // 国际版固定接入点:亚太东南一新加坡 + if !strings.HasPrefix(casRegion, "cn-") { + casRegion = "ap-southeast-1" + } else { + casRegion = "cn-hangzhou" + } + } + + uploader, err := uploadersp.NewUploader(&uploadersp.UploaderConfig{ + AccessKeyId: accessKeyId, + AccessKeySecret: accessKeySecret, + Region: casRegion, + }) + return uploader, err +} 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 f688edf9..3b8ce12d 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 @@ -1,4 +1,4 @@ -package aliyunclb_test +package aliyunclb_test import ( "context" diff --git a/internal/pkg/core/deployer/providers/aliyun-clb/consts.go b/internal/pkg/core/deployer/providers/aliyun-clb/consts.go index ad4fb070..9d901095 100644 --- a/internal/pkg/core/deployer/providers/aliyun-clb/consts.go +++ b/internal/pkg/core/deployer/providers/aliyun-clb/consts.go @@ -1,4 +1,4 @@ -package aliyunclb +package aliyunclb type ResourceType string diff --git a/internal/pkg/core/deployer/providers/aliyun-dcdn/aliyun_dcdn.go b/internal/pkg/core/deployer/providers/aliyun-dcdn/aliyun_dcdn.go index b9ba9f23..4eb411fd 100644 --- a/internal/pkg/core/deployer/providers/aliyun-dcdn/aliyun_dcdn.go +++ b/internal/pkg/core/deployer/providers/aliyun-dcdn/aliyun_dcdn.go @@ -1,4 +1,4 @@ -package aliyundcdn +package aliyundcdn import ( "context" @@ -10,7 +10,6 @@ import ( aliopen "github.com/alibabacloud-go/darabonba-openapi/v2/client" alidcdn "github.com/alibabacloud-go/dcdn-20180115/v3/client" "github.com/alibabacloud-go/tea/tea" - xerrors "github.com/pkg/errors" "github.com/usual2970/certimate/internal/pkg/core/deployer" ) @@ -39,7 +38,7 @@ func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { client, err := createSdkClient(config.AccessKeyId, config.AccessKeySecret) if err != nil { - return nil, xerrors.Wrap(err, "failed to create sdk client") + return nil, fmt.Errorf("failed to create sdk client: %w", err) } return &DeployerProvider{ @@ -58,7 +57,7 @@ func (d *DeployerProvider) WithLogger(logger *slog.Logger) deployer.Deployer { return d } -func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { +func (d *DeployerProvider) Deploy(ctx context.Context, certPEM string, privkeyPEM string) (*deployer.DeployResult, error) { // "*.example.com" → ".example.com",适配阿里云 DCDN 要求的泛域名格式 domain := strings.TrimPrefix(d.config.Domain, "*") @@ -69,13 +68,13 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPe CertName: tea.String(fmt.Sprintf("certimate-%d", time.Now().UnixMilli())), CertType: tea.String("upload"), SSLProtocol: tea.String("on"), - SSLPub: tea.String(certPem), - SSLPri: tea.String(privkeyPem), + SSLPub: tea.String(certPEM), + SSLPri: tea.String(privkeyPEM), } setDcdnDomainSSLCertificateResp, err := d.sdkClient.SetDcdnDomainSSLCertificate(setDcdnDomainSSLCertificateReq) d.logger.Debug("sdk request 'dcdn.SetDcdnDomainSSLCertificate'", slog.Any("request", setDcdnDomainSSLCertificateReq), slog.Any("response", setDcdnDomainSSLCertificateResp)) if err != nil { - return nil, xerrors.Wrap(err, "failed to execute sdk request 'dcdn.SetDcdnDomainSSLCertificate'") + return nil, fmt.Errorf("failed to execute sdk request 'dcdn.SetDcdnDomainSSLCertificate': %w", err) } return &deployer.DeployResult{}, nil 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 04ca4c48..deb489c6 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 @@ -1,4 +1,4 @@ -package aliyundcdn_test +package aliyundcdn_test import ( "context" diff --git a/internal/pkg/core/deployer/providers/aliyun-ddos/aliyun_ddos.go b/internal/pkg/core/deployer/providers/aliyun-ddos/aliyun_ddos.go new file mode 100644 index 00000000..d1cb5b61 --- /dev/null +++ b/internal/pkg/core/deployer/providers/aliyun-ddos/aliyun_ddos.go @@ -0,0 +1,137 @@ +package aliyunddos + +import ( + "context" + "errors" + "fmt" + "log/slog" + "strconv" + "strings" + + aliopen "github.com/alibabacloud-go/darabonba-openapi/v2/client" + aliddos "github.com/alibabacloud-go/ddoscoo-20200101/v4/client" + "github.com/alibabacloud-go/tea/tea" + + "github.com/usual2970/certimate/internal/pkg/core/deployer" + "github.com/usual2970/certimate/internal/pkg/core/uploader" + uploadersp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/aliyun-slb" +) + +type DeployerConfig struct { + // 阿里云 AccessKeyId。 + AccessKeyId string `json:"accessKeyId"` + // 阿里云 AccessKeySecret。 + AccessKeySecret string `json:"accessKeySecret"` + // 阿里云地域。 + Region string `json:"region"` + // 网站域名(支持泛域名)。 + Domain string `json:"domain"` +} + +type DeployerProvider struct { + config *DeployerConfig + logger *slog.Logger + sdkClient *aliddos.Client + sslUploader uploader.Uploader +} + +var _ deployer.Deployer = (*DeployerProvider)(nil) + +func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { + if config == nil { + panic("config is nil") + } + + client, err := createSdkClient(config.AccessKeyId, config.AccessKeySecret, config.Region) + if err != nil { + return nil, fmt.Errorf("failed to create sdk client: %w", err) + } + + uploader, err := createSslUploader(config.AccessKeyId, config.AccessKeySecret, config.Region) + if err != nil { + return nil, fmt.Errorf("failed to create ssl uploader: %w", err) + } + + return &DeployerProvider{ + config: config, + logger: slog.Default(), + sdkClient: client, + sslUploader: uploader, + }, nil +} + +func (d *DeployerProvider) WithLogger(logger *slog.Logger) deployer.Deployer { + if logger == nil { + d.logger = slog.Default() + } else { + d.logger = logger + } + d.sslUploader.WithLogger(logger) + return d +} + +func (d *DeployerProvider) Deploy(ctx context.Context, certPEM string, privkeyPEM string) (*deployer.DeployResult, error) { + if d.config.Domain == "" { + return nil, errors.New("config `domain` is required") + } + + // 上传证书到 CAS + upres, err := d.sslUploader.Upload(ctx, certPEM, privkeyPEM) + if err != nil { + return nil, fmt.Errorf("failed to upload certificate file: %w", err) + } else { + d.logger.Info("ssl certificate uploaded", slog.Any("result", upres)) + } + + // 为网站业务转发规则关联 SSL 证书 + // REF: https://help.aliyun.com/zh/anti-ddos/anti-ddos-pro-and-premium/developer-reference/api-ddoscoo-2020-01-01-associatewebcert + certId, _ := strconv.Atoi(upres.CertId) + associateWebCertReq := &aliddos.AssociateWebCertRequest{ + Domain: tea.String(d.config.Domain), + CertId: tea.Int32(int32(certId)), + } + associateWebCertResp, err := d.sdkClient.AssociateWebCert(associateWebCertReq) + d.logger.Debug("sdk request 'dcdn.AssociateWebCert'", slog.Any("request", associateWebCertReq), slog.Any("response", associateWebCertResp)) + if err != nil { + return nil, fmt.Errorf("failed to execute sdk request 'dcdn.AssociateWebCert': %w", err) + } + + return &deployer.DeployResult{}, nil +} + +func createSdkClient(accessKeyId, accessKeySecret, region string) (*aliddos.Client, error) { + // 接入点一览 https://api.aliyun.com/product/ddoscoo + config := &aliopen.Config{ + AccessKeyId: tea.String(accessKeyId), + AccessKeySecret: tea.String(accessKeySecret), + Endpoint: tea.String(fmt.Sprintf("ddoscoo.%s.aliyuncs.com", region)), + } + + client, err := aliddos.NewClient(config) + if err != nil { + return nil, err + } + + return client, nil +} + +func createSslUploader(accessKeyId, accessKeySecret, region string) (uploader.Uploader, error) { + casRegion := region + if casRegion != "" { + // 阿里云 CAS 服务接入点是独立于 Anti-DDoS 服务的 + // 国内版固定接入点:华东一杭州 + // 国际版固定接入点:亚太东南一新加坡 + if !strings.HasPrefix(casRegion, "cn-") { + casRegion = "ap-southeast-1" + } else { + casRegion = "cn-hangzhou" + } + } + + uploader, err := uploadersp.NewUploader(&uploadersp.UploaderConfig{ + AccessKeyId: accessKeyId, + AccessKeySecret: accessKeySecret, + Region: casRegion, + }) + return uploader, err +} diff --git a/internal/pkg/core/deployer/providers/aliyun-ddos/aliyun_ddos_test.go b/internal/pkg/core/deployer/providers/aliyun-ddos/aliyun_ddos_test.go new file mode 100644 index 00000000..b7f5ad34 --- /dev/null +++ b/internal/pkg/core/deployer/providers/aliyun-ddos/aliyun_ddos_test.go @@ -0,0 +1,80 @@ +package aliyunddos_test + +import ( + "context" + "flag" + "fmt" + "os" + "strings" + "testing" + + provider "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/aliyun-ddos" +) + +var ( + fInputCertPath string + fInputKeyPath string + fAccessKeyId string + fAccessKeySecret string + fRegion string + fDomain string +) + +func init() { + argsPrefix := "CERTIMATE_DEPLOYER_ALIYUNDDOS_" + + flag.StringVar(&fInputCertPath, argsPrefix+"INPUTCERTPATH", "", "") + flag.StringVar(&fInputKeyPath, argsPrefix+"INPUTKEYPATH", "", "") + flag.StringVar(&fAccessKeyId, argsPrefix+"ACCESSKEYID", "", "") + flag.StringVar(&fAccessKeySecret, argsPrefix+"ACCESSKEYSECRET", "", "") + flag.StringVar(&fRegion, argsPrefix+"REGION", "", "") + flag.StringVar(&fDomain, argsPrefix+"DOMAIN", "", "") +} + +/* +Shell command to run this test: + + go test -v ./aliyun_ddos_test.go -args \ + --CERTIMATE_DEPLOYER_ALIYUNDDOS_INPUTCERTPATH="/path/to/your-input-cert.pem" \ + --CERTIMATE_DEPLOYER_ALIYUNDDOS_INPUTKEYPATH="/path/to/your-input-key.pem" \ + --CERTIMATE_DEPLOYER_ALIYUNDDOS_ACCESSKEYID="your-access-key-id" \ + --CERTIMATE_DEPLOYER_ALIYUNDDOS_ACCESSKEYSECRET="your-access-key-secret" \ + --CERTIMATE_DEPLOYER_ALIYUNDDOS_REGION="cn-hangzhou" \ + --CERTIMATE_DEPLOYER_ALIYUNDDOS_DOMAIN="example.com" +*/ +func TestDeploy(t *testing.T) { + flag.Parse() + + t.Run("Deploy", func(t *testing.T) { + t.Log(strings.Join([]string{ + "args:", + fmt.Sprintf("INPUTCERTPATH: %v", fInputCertPath), + fmt.Sprintf("INPUTKEYPATH: %v", fInputKeyPath), + fmt.Sprintf("ACCESSKEYID: %v", fAccessKeyId), + fmt.Sprintf("ACCESSKEYSECRET: %v", fAccessKeySecret), + fmt.Sprintf("REGION: %v", fRegion), + fmt.Sprintf("DOMAIN: %v", fDomain), + }, "\n")) + + deployer, err := provider.NewDeployer(&provider.DeployerConfig{ + AccessKeyId: fAccessKeyId, + AccessKeySecret: fAccessKeySecret, + Region: fRegion, + Domain: fDomain, + }) + if err != nil { + t.Errorf("err: %+v", err) + return + } + + fInputCertData, _ := os.ReadFile(fInputCertPath) + fInputKeyData, _ := os.ReadFile(fInputKeyPath) + res, err := deployer.Deploy(context.Background(), string(fInputCertData), string(fInputKeyData)) + if err != nil { + t.Errorf("err: %+v", err) + return + } + + t.Logf("ok: %v", res) + }) +} diff --git a/internal/pkg/core/deployer/providers/aliyun-esa/aliyun_esa.go b/internal/pkg/core/deployer/providers/aliyun-esa/aliyun_esa.go index 918ec095..1f29756f 100644 --- a/internal/pkg/core/deployer/providers/aliyun-esa/aliyun_esa.go +++ b/internal/pkg/core/deployer/providers/aliyun-esa/aliyun_esa.go @@ -1,4 +1,4 @@ -package aliyunesa +package aliyunesa import ( "context" @@ -11,7 +11,6 @@ import ( aliopen "github.com/alibabacloud-go/darabonba-openapi/v2/client" aliesa "github.com/alibabacloud-go/esa-20240910/v2/client" "github.com/alibabacloud-go/tea/tea" - xerrors "github.com/pkg/errors" "github.com/usual2970/certimate/internal/pkg/core/deployer" "github.com/usual2970/certimate/internal/pkg/core/uploader" @@ -45,12 +44,12 @@ func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { client, err := createSdkClient(config.AccessKeyId, config.AccessKeySecret, config.Region) if err != nil { - return nil, xerrors.Wrap(err, "failed to create sdk client") + return nil, fmt.Errorf("failed to create sdk client: %w", err) } uploader, err := createSslUploader(config.AccessKeyId, config.AccessKeySecret, config.Region) if err != nil { - return nil, xerrors.Wrap(err, "failed to create ssl uploader") + return nil, fmt.Errorf("failed to create ssl uploader: %w", err) } return &DeployerProvider{ @@ -71,15 +70,15 @@ func (d *DeployerProvider) WithLogger(logger *slog.Logger) deployer.Deployer { return d } -func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { +func (d *DeployerProvider) Deploy(ctx context.Context, certPEM string, privkeyPEM string) (*deployer.DeployResult, error) { if d.config.SiteId == 0 { return nil, errors.New("config `siteId` is required") } // 上传证书到 CAS - upres, err := d.sslUploader.Upload(ctx, certPem, privkeyPem) + upres, err := d.sslUploader.Upload(ctx, certPEM, privkeyPEM) if err != nil { - return nil, xerrors.Wrap(err, "failed to upload certificate file") + return nil, fmt.Errorf("failed to upload certificate file: %w", err) } else { d.logger.Info("ssl certificate uploaded", slog.Any("result", upres)) } @@ -95,7 +94,7 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPe setCertificateResp, err := d.sdkClient.SetCertificate(setCertificateReq) d.logger.Debug("sdk request 'esa.SetCertificate'", slog.Any("request", setCertificateReq), slog.Any("response", setCertificateResp)) if err != nil { - return nil, xerrors.Wrap(err, "failed to execute sdk request 'esa.SetCertificate'") + return nil, fmt.Errorf("failed to execute sdk request 'esa.SetCertificate': %w", err) } return &deployer.DeployResult{}, nil @@ -123,7 +122,7 @@ func createSslUploader(accessKeyId, accessKeySecret, region string) (uploader.Up // 阿里云 CAS 服务接入点是独立于 ESA 服务的 // 国内版固定接入点:华东一杭州 // 国际版固定接入点:亚太东南一新加坡 - if casRegion != "" && !strings.HasPrefix(casRegion, "cn-") { + if !strings.HasPrefix(casRegion, "cn-") { casRegion = "ap-southeast-1" } else { casRegion = "cn-hangzhou" diff --git a/internal/pkg/core/deployer/providers/aliyun-esa/aliyun_esa_test.go b/internal/pkg/core/deployer/providers/aliyun-esa/aliyun_esa_test.go index 0877d561..0b66d2fb 100644 --- a/internal/pkg/core/deployer/providers/aliyun-esa/aliyun_esa_test.go +++ b/internal/pkg/core/deployer/providers/aliyun-esa/aliyun_esa_test.go @@ -1,4 +1,4 @@ -package aliyunesa_test +package aliyunesa_test import ( "context" diff --git a/internal/pkg/core/deployer/providers/aliyun-fc/aliyun_fc.go b/internal/pkg/core/deployer/providers/aliyun-fc/aliyun_fc.go index 87f51130..8557068c 100644 --- a/internal/pkg/core/deployer/providers/aliyun-fc/aliyun_fc.go +++ b/internal/pkg/core/deployer/providers/aliyun-fc/aliyun_fc.go @@ -1,4 +1,4 @@ -package aliyunfc +package aliyunfc import ( "context" @@ -10,7 +10,6 @@ import ( alifc3 "github.com/alibabacloud-go/fc-20230330/v4/client" alifc2 "github.com/alibabacloud-go/fc-open-20210406/v2/client" "github.com/alibabacloud-go/tea/tea" - xerrors "github.com/pkg/errors" "github.com/usual2970/certimate/internal/pkg/core/deployer" ) @@ -48,7 +47,7 @@ func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { clients, err := createSdkClients(config.AccessKeyId, config.AccessKeySecret, config.Region) if err != nil { - return nil, xerrors.Wrap(err, "failed to create sdk clients") + return nil, fmt.Errorf("failed to create sdk clients: %w", err) } return &DeployerProvider{ @@ -67,32 +66,32 @@ func (d *DeployerProvider) WithLogger(logger *slog.Logger) deployer.Deployer { return d } -func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { +func (d *DeployerProvider) Deploy(ctx context.Context, certPEM string, privkeyPEM string) (*deployer.DeployResult, error) { switch d.config.ServiceVersion { case "3", "3.0": - if err := d.deployToFC3(ctx, certPem, privkeyPem); err != nil { + if err := d.deployToFC3(ctx, certPEM, privkeyPEM); err != nil { return nil, err } case "2", "2.0": - if err := d.deployToFC2(ctx, certPem, privkeyPem); err != nil { + if err := d.deployToFC2(ctx, certPEM, privkeyPEM); err != nil { return nil, err } default: - return nil, xerrors.Errorf("unsupported service version: %s", d.config.ServiceVersion) + return nil, fmt.Errorf("unsupported service version '%s'", d.config.ServiceVersion) } return &deployer.DeployResult{}, nil } -func (d *DeployerProvider) deployToFC3(ctx context.Context, certPem string, privkeyPem string) error { +func (d *DeployerProvider) deployToFC3(ctx context.Context, certPEM string, privkeyPEM string) error { // 获取自定义域名 // REF: https://help.aliyun.com/zh/functioncompute/fc-3-0/developer-reference/api-fc-2023-03-30-getcustomdomain getCustomDomainResp, err := d.sdkClients.FC3.GetCustomDomain(tea.String(d.config.Domain)) d.logger.Debug("sdk request 'fc.GetCustomDomain'", slog.Any("response", getCustomDomainResp)) if err != nil { - return xerrors.Wrap(err, "failed to execute sdk request 'fc.GetCustomDomain'") + return fmt.Errorf("failed to execute sdk request 'fc.GetCustomDomain': %w", err) } // 更新自定义域名 @@ -101,8 +100,8 @@ func (d *DeployerProvider) deployToFC3(ctx context.Context, certPem string, priv Body: &alifc3.UpdateCustomDomainInput{ CertConfig: &alifc3.CertConfig{ CertName: tea.String(fmt.Sprintf("certimate-%d", time.Now().UnixMilli())), - Certificate: tea.String(certPem), - PrivateKey: tea.String(privkeyPem), + Certificate: tea.String(certPEM), + PrivateKey: tea.String(privkeyPEM), }, Protocol: getCustomDomainResp.Body.Protocol, TlsConfig: getCustomDomainResp.Body.TlsConfig, @@ -111,19 +110,19 @@ func (d *DeployerProvider) deployToFC3(ctx context.Context, certPem string, priv updateCustomDomainResp, err := d.sdkClients.FC3.UpdateCustomDomain(tea.String(d.config.Domain), updateCustomDomainReq) d.logger.Debug("sdk request 'fc.UpdateCustomDomain'", slog.Any("request", updateCustomDomainReq), slog.Any("response", updateCustomDomainResp)) if err != nil { - return xerrors.Wrap(err, "failed to execute sdk request 'fc.UpdateCustomDomain'") + return fmt.Errorf("failed to execute sdk request 'fc.UpdateCustomDomain': %w", err) } return nil } -func (d *DeployerProvider) deployToFC2(ctx context.Context, certPem string, privkeyPem string) error { +func (d *DeployerProvider) deployToFC2(ctx context.Context, certPEM string, privkeyPEM string) error { // 获取自定义域名 // REF: https://help.aliyun.com/zh/functioncompute/fc-2-0/developer-reference/api-fc-open-2021-04-06-getcustomdomain getCustomDomainResp, err := d.sdkClients.FC2.GetCustomDomain(tea.String(d.config.Domain)) d.logger.Debug("sdk request 'fc.GetCustomDomain'", slog.Any("response", getCustomDomainResp)) if err != nil { - return xerrors.Wrap(err, "failed to execute sdk request 'fc.GetCustomDomain'") + return fmt.Errorf("failed to execute sdk request 'fc.GetCustomDomain': %w", err) } // 更新自定义域名 @@ -131,8 +130,8 @@ func (d *DeployerProvider) deployToFC2(ctx context.Context, certPem string, priv updateCustomDomainReq := &alifc2.UpdateCustomDomainRequest{ CertConfig: &alifc2.CertConfig{ CertName: tea.String(fmt.Sprintf("certimate-%d", time.Now().UnixMilli())), - Certificate: tea.String(certPem), - PrivateKey: tea.String(privkeyPem), + Certificate: tea.String(certPEM), + PrivateKey: tea.String(privkeyPEM), }, Protocol: getCustomDomainResp.Body.Protocol, TlsConfig: getCustomDomainResp.Body.TlsConfig, @@ -140,7 +139,7 @@ func (d *DeployerProvider) deployToFC2(ctx context.Context, certPem string, priv updateCustomDomainResp, err := d.sdkClients.FC2.UpdateCustomDomain(tea.String(d.config.Domain), updateCustomDomainReq) d.logger.Debug("sdk request 'fc.UpdateCustomDomain'", slog.Any("request", updateCustomDomainReq), slog.Any("response", updateCustomDomainResp)) if err != nil { - return xerrors.Wrap(err, "failed to execute sdk request 'fc.UpdateCustomDomain'") + return fmt.Errorf("failed to execute sdk request 'fc.UpdateCustomDomain': %w", err) } return nil diff --git a/internal/pkg/core/deployer/providers/aliyun-fc/aliyun_fc_test.go b/internal/pkg/core/deployer/providers/aliyun-fc/aliyun_fc_test.go index d83f2591..215ec93b 100644 --- a/internal/pkg/core/deployer/providers/aliyun-fc/aliyun_fc_test.go +++ b/internal/pkg/core/deployer/providers/aliyun-fc/aliyun_fc_test.go @@ -1,4 +1,4 @@ -package aliyunfc_test +package aliyunfc_test import ( "context" diff --git a/internal/pkg/core/deployer/providers/aliyun-live/aliyun_live.go b/internal/pkg/core/deployer/providers/aliyun-live/aliyun_live.go index e3f6a435..354c9601 100644 --- a/internal/pkg/core/deployer/providers/aliyun-live/aliyun_live.go +++ b/internal/pkg/core/deployer/providers/aliyun-live/aliyun_live.go @@ -1,4 +1,4 @@ -package aliyunlive +package aliyunlive import ( "context" @@ -10,7 +10,6 @@ import ( aliopen "github.com/alibabacloud-go/darabonba-openapi/v2/client" alilive "github.com/alibabacloud-go/live-20161101/client" "github.com/alibabacloud-go/tea/tea" - xerrors "github.com/pkg/errors" "github.com/usual2970/certimate/internal/pkg/core/deployer" ) @@ -41,7 +40,7 @@ func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { client, err := createSdkClient(config.AccessKeyId, config.AccessKeySecret, config.Region) if err != nil { - return nil, xerrors.Wrap(err, "failed to create sdk client") + return nil, fmt.Errorf("failed to create sdk client: %w", err) } return &DeployerProvider{ @@ -60,7 +59,7 @@ func (d *DeployerProvider) WithLogger(logger *slog.Logger) deployer.Deployer { return d } -func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { +func (d *DeployerProvider) Deploy(ctx context.Context, certPEM string, privkeyPEM string) (*deployer.DeployResult, error) { // "*.example.com" → ".example.com",适配阿里云 Live 要求的泛域名格式 domain := strings.TrimPrefix(d.config.Domain, "*") @@ -71,13 +70,13 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPe CertName: tea.String(fmt.Sprintf("certimate-%d", time.Now().UnixMilli())), CertType: tea.String("upload"), SSLProtocol: tea.String("on"), - SSLPub: tea.String(certPem), - SSLPri: tea.String(privkeyPem), + SSLPub: tea.String(certPEM), + SSLPri: tea.String(privkeyPEM), } setLiveDomainSSLCertificateResp, err := d.sdkClient.SetLiveDomainCertificate(setLiveDomainSSLCertificateReq) d.logger.Debug("sdk request 'live.SetLiveDomainCertificate'", slog.Any("request", setLiveDomainSSLCertificateReq), slog.Any("response", setLiveDomainSSLCertificateResp)) if err != nil { - return nil, xerrors.Wrap(err, "failed to execute sdk request 'live.SetLiveDomainCertificate'") + return nil, fmt.Errorf("failed to execute sdk request 'live.SetLiveDomainCertificate': %w", err) } return &deployer.DeployResult{}, nil diff --git a/internal/pkg/core/deployer/providers/aliyun-live/aliyun_live_test.go b/internal/pkg/core/deployer/providers/aliyun-live/aliyun_live_test.go index fcf01147..46608e38 100644 --- a/internal/pkg/core/deployer/providers/aliyun-live/aliyun_live_test.go +++ b/internal/pkg/core/deployer/providers/aliyun-live/aliyun_live_test.go @@ -1,4 +1,4 @@ -package aliyunlive_test +package aliyunlive_test import ( "context" diff --git a/internal/pkg/core/deployer/providers/aliyun-nlb/aliyun_nlb.go b/internal/pkg/core/deployer/providers/aliyun-nlb/aliyun_nlb.go index f851fee8..b8391144 100644 --- a/internal/pkg/core/deployer/providers/aliyun-nlb/aliyun_nlb.go +++ b/internal/pkg/core/deployer/providers/aliyun-nlb/aliyun_nlb.go @@ -1,4 +1,4 @@ -package aliyunnlb +package aliyunnlb import ( "context" @@ -10,7 +10,6 @@ import ( aliopen "github.com/alibabacloud-go/darabonba-openapi/v2/client" alinlb "github.com/alibabacloud-go/nlb-20220430/v2/client" "github.com/alibabacloud-go/tea/tea" - xerrors "github.com/pkg/errors" "github.com/usual2970/certimate/internal/pkg/core/deployer" "github.com/usual2970/certimate/internal/pkg/core/uploader" @@ -50,12 +49,12 @@ func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { client, err := createSdkClient(config.AccessKeyId, config.AccessKeySecret, config.Region) if err != nil { - return nil, xerrors.Wrap(err, "failed to create sdk client") + return nil, fmt.Errorf("failed to create sdk client: %w", err) } uploader, err := createSslUploader(config.AccessKeyId, config.AccessKeySecret, config.Region) if err != nil { - return nil, xerrors.Wrap(err, "failed to create ssl uploader") + return nil, fmt.Errorf("failed to create ssl uploader: %w", err) } return &DeployerProvider{ @@ -76,11 +75,11 @@ func (d *DeployerProvider) WithLogger(logger *slog.Logger) deployer.Deployer { return d } -func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { +func (d *DeployerProvider) Deploy(ctx context.Context, certPEM string, privkeyPEM string) (*deployer.DeployResult, error) { // 上传证书到 CAS - upres, err := d.sslUploader.Upload(ctx, certPem, privkeyPem) + upres, err := d.sslUploader.Upload(ctx, certPEM, privkeyPEM) if err != nil { - return nil, xerrors.Wrap(err, "failed to upload certificate file") + return nil, fmt.Errorf("failed to upload certificate file: %w", err) } else { d.logger.Info("ssl certificate uploaded", slog.Any("result", upres)) } @@ -98,7 +97,7 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPe } default: - return nil, fmt.Errorf("unsupported resource type: %s", d.config.ResourceType) + return nil, fmt.Errorf("unsupported resource type '%s'", d.config.ResourceType) } return &deployer.DeployResult{}, nil @@ -117,7 +116,7 @@ func (d *DeployerProvider) deployToLoadbalancer(ctx context.Context, cloudCertId getLoadBalancerAttributeResp, err := d.sdkClient.GetLoadBalancerAttribute(getLoadBalancerAttributeReq) d.logger.Debug("sdk request 'nlb.GetLoadBalancerAttribute'", slog.Any("request", getLoadBalancerAttributeReq), slog.Any("response", getLoadBalancerAttributeResp)) if err != nil { - return xerrors.Wrap(err, "failed to execute sdk request 'nlb.GetLoadBalancerAttribute'") + return fmt.Errorf("failed to execute sdk request 'nlb.GetLoadBalancerAttribute': %w", err) } // 查询 TCPSSL 监听列表 @@ -126,6 +125,12 @@ func (d *DeployerProvider) deployToLoadbalancer(ctx context.Context, cloudCertId listListenersLimit := int32(100) var listListenersToken *string = nil for { + select { + case <-ctx.Done(): + return ctx.Err() + default: + } + listListenersReq := &alinlb.ListListenersRequest{ MaxResults: tea.Int32(listListenersLimit), NextToken: listListenersToken, @@ -135,7 +140,7 @@ func (d *DeployerProvider) deployToLoadbalancer(ctx context.Context, cloudCertId listListenersResp, err := d.sdkClient.ListListeners(listListenersReq) d.logger.Debug("sdk request 'nlb.ListListeners'", slog.Any("request", listListenersReq), slog.Any("response", listListenersResp)) if err != nil { - return xerrors.Wrap(err, "failed to execute sdk request 'nlb.ListListeners'") + return fmt.Errorf("failed to execute sdk request 'nlb.ListListeners': %w", err) } if listListenersResp.Body.Listeners != nil { @@ -159,8 +164,14 @@ func (d *DeployerProvider) deployToLoadbalancer(ctx context.Context, cloudCertId var errs []error for _, listenerId := range listenerIds { - if err := d.updateListenerCertificate(ctx, listenerId, cloudCertId); err != nil { - errs = append(errs, err) + select { + case <-ctx.Done(): + return ctx.Err() + + default: + if err := d.updateListenerCertificate(ctx, listenerId, cloudCertId); err != nil { + errs = append(errs, err) + } } } @@ -194,7 +205,7 @@ func (d *DeployerProvider) updateListenerCertificate(ctx context.Context, cloudL getListenerAttributeResp, err := d.sdkClient.GetListenerAttribute(getListenerAttributeReq) d.logger.Debug("sdk request 'nlb.GetListenerAttribute'", slog.Any("request", getListenerAttributeReq), slog.Any("response", getListenerAttributeResp)) if err != nil { - return xerrors.Wrap(err, "failed to execute sdk request 'nlb.GetListenerAttribute'") + return fmt.Errorf("failed to execute sdk request 'nlb.GetListenerAttribute': %w", err) } // 修改监听的属性 @@ -206,7 +217,7 @@ func (d *DeployerProvider) updateListenerCertificate(ctx context.Context, cloudL updateListenerAttributeResp, err := d.sdkClient.UpdateListenerAttribute(updateListenerAttributeReq) d.logger.Debug("sdk request 'nlb.UpdateListenerAttribute'", slog.Any("request", updateListenerAttributeReq), slog.Any("response", updateListenerAttributeResp)) if err != nil { - return xerrors.Wrap(err, "failed to execute sdk request 'nlb.UpdateListenerAttribute'") + return fmt.Errorf("failed to execute sdk request 'nlb.UpdateListenerAttribute': %w", err) } return nil @@ -240,7 +251,7 @@ func createSslUploader(accessKeyId, accessKeySecret, region string) (uploader.Up // 阿里云 CAS 服务接入点是独立于 NLB 服务的 // 国内版固定接入点:华东一杭州 // 国际版固定接入点:亚太东南一新加坡 - if casRegion != "" && !strings.HasPrefix(casRegion, "cn-") { + if !strings.HasPrefix(casRegion, "cn-") { casRegion = "ap-southeast-1" } else { casRegion = "cn-hangzhou" 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 dfaf0916..f4d64219 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 @@ -1,4 +1,4 @@ -package aliyunnlb_test +package aliyunnlb_test import ( "context" diff --git a/internal/pkg/core/deployer/providers/aliyun-nlb/consts.go b/internal/pkg/core/deployer/providers/aliyun-nlb/consts.go index 1fa071df..40724727 100644 --- a/internal/pkg/core/deployer/providers/aliyun-nlb/consts.go +++ b/internal/pkg/core/deployer/providers/aliyun-nlb/consts.go @@ -1,4 +1,4 @@ -package aliyunnlb +package aliyunnlb type ResourceType string diff --git a/internal/pkg/core/deployer/providers/aliyun-oss/aliyun_oss.go b/internal/pkg/core/deployer/providers/aliyun-oss/aliyun_oss.go index 2f16b09d..474fe5b3 100644 --- a/internal/pkg/core/deployer/providers/aliyun-oss/aliyun_oss.go +++ b/internal/pkg/core/deployer/providers/aliyun-oss/aliyun_oss.go @@ -1,4 +1,4 @@ -package aliyunoss +package aliyunoss import ( "context" @@ -7,7 +7,6 @@ import ( "log/slog" "github.com/aliyun/aliyun-oss-go-sdk/oss" - xerrors "github.com/pkg/errors" "github.com/usual2970/certimate/internal/pkg/core/deployer" ) @@ -40,7 +39,7 @@ func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { client, err := createSdkClient(config.AccessKeyId, config.AccessKeySecret, config.Region) if err != nil { - return nil, xerrors.Wrap(err, "failed to create sdk client") + return nil, fmt.Errorf("failed to create sdk client: %w", err) } return &DeployerProvider{ @@ -59,7 +58,7 @@ func (d *DeployerProvider) WithLogger(logger *slog.Logger) deployer.Deployer { return d } -func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { +func (d *DeployerProvider) Deploy(ctx context.Context, certPEM string, privkeyPEM string) (*deployer.DeployResult, error) { if d.config.Bucket == "" { return nil, errors.New("config `bucket` is required") } @@ -72,15 +71,15 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPe putBucketCnameWithCertificateReq := oss.PutBucketCname{ Cname: d.config.Domain, CertificateConfiguration: &oss.CertificateConfiguration{ - Certificate: certPem, - PrivateKey: privkeyPem, + Certificate: certPEM, + PrivateKey: privkeyPEM, Force: true, }, } err := d.sdkClient.PutBucketCnameWithCertificate(d.config.Bucket, putBucketCnameWithCertificateReq) d.logger.Debug("sdk request 'oss.PutBucketCnameWithCertificate'", slog.Any("bucket", d.config.Bucket), slog.Any("request", putBucketCnameWithCertificateReq)) if err != nil { - return nil, xerrors.Wrap(err, "failed to execute sdk request 'oss.PutBucketCnameWithCertificate'") + return nil, fmt.Errorf("failed to execute sdk request 'oss.PutBucketCnameWithCertificate': %w", err) } return &deployer.DeployResult{}, nil 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 7613a003..412f7d16 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 @@ -1,4 +1,4 @@ -package aliyunoss_test +package aliyunoss_test import ( "context" diff --git a/internal/pkg/core/deployer/providers/aliyun-vod/aliyun_vod.go b/internal/pkg/core/deployer/providers/aliyun-vod/aliyun_vod.go index 95d4f631..48e52c26 100644 --- a/internal/pkg/core/deployer/providers/aliyun-vod/aliyun_vod.go +++ b/internal/pkg/core/deployer/providers/aliyun-vod/aliyun_vod.go @@ -1,4 +1,4 @@ -package aliyunvod +package aliyunvod import ( "context" @@ -9,7 +9,6 @@ import ( aliopen "github.com/alibabacloud-go/darabonba-openapi/v2/client" "github.com/alibabacloud-go/tea/tea" alivod "github.com/alibabacloud-go/vod-20170321/v4/client" - xerrors "github.com/pkg/errors" "github.com/usual2970/certimate/internal/pkg/core/deployer" ) @@ -40,7 +39,7 @@ func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { client, err := createSdkClient(config.AccessKeyId, config.AccessKeySecret, config.Region) if err != nil { - return nil, xerrors.Wrap(err, "failed to create sdk client") + return nil, fmt.Errorf("failed to create sdk client: %w", err) } return &DeployerProvider{ @@ -59,7 +58,7 @@ func (d *DeployerProvider) WithLogger(logger *slog.Logger) deployer.Deployer { return d } -func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { +func (d *DeployerProvider) Deploy(ctx context.Context, certPEM string, privkeyPEM string) (*deployer.DeployResult, error) { // 设置域名证书 // REF: https://help.aliyun.com/zh/vod/developer-reference/api-vod-2017-03-21-setvoddomainsslcertificate setVodDomainSSLCertificateReq := &alivod.SetVodDomainSSLCertificateRequest{ @@ -67,13 +66,13 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPe CertName: tea.String(fmt.Sprintf("certimate-%d", time.Now().UnixMilli())), CertType: tea.String("upload"), SSLProtocol: tea.String("on"), - SSLPub: tea.String(certPem), - SSLPri: tea.String(privkeyPem), + SSLPub: tea.String(certPEM), + SSLPri: tea.String(privkeyPEM), } setVodDomainSSLCertificateResp, err := d.sdkClient.SetVodDomainSSLCertificate(setVodDomainSSLCertificateReq) d.logger.Debug("sdk request 'live.SetVodDomainSSLCertificate'", slog.Any("request", setVodDomainSSLCertificateReq), slog.Any("response", setVodDomainSSLCertificateResp)) if err != nil { - return nil, xerrors.Wrap(err, "failed to execute sdk request 'live.SetVodDomainSSLCertificate'") + return nil, fmt.Errorf("failed to execute sdk request 'live.SetVodDomainSSLCertificate': %w", err) } return &deployer.DeployResult{}, nil diff --git a/internal/pkg/core/deployer/providers/aliyun-vod/aliyun_vod_test.go b/internal/pkg/core/deployer/providers/aliyun-vod/aliyun_vod_test.go index 552ddc0f..4d523d98 100644 --- a/internal/pkg/core/deployer/providers/aliyun-vod/aliyun_vod_test.go +++ b/internal/pkg/core/deployer/providers/aliyun-vod/aliyun_vod_test.go @@ -1,4 +1,4 @@ -package aliyunvod_test +package aliyunvod_test import ( "context" diff --git a/internal/pkg/core/deployer/providers/aliyun-waf/aliyun_waf.go b/internal/pkg/core/deployer/providers/aliyun-waf/aliyun_waf.go index bddefb42..26dbd008 100644 --- a/internal/pkg/core/deployer/providers/aliyun-waf/aliyun_waf.go +++ b/internal/pkg/core/deployer/providers/aliyun-waf/aliyun_waf.go @@ -1,4 +1,4 @@ -package aliyunwaf +package aliyunwaf import ( "context" @@ -10,12 +10,11 @@ import ( aliopen "github.com/alibabacloud-go/darabonba-openapi/v2/client" "github.com/alibabacloud-go/tea/tea" aliwaf "github.com/alibabacloud-go/waf-openapi-20211001/v5/client" - xerrors "github.com/pkg/errors" "github.com/usual2970/certimate/internal/pkg/core/deployer" "github.com/usual2970/certimate/internal/pkg/core/uploader" uploadersp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/aliyun-cas" - "github.com/usual2970/certimate/internal/pkg/utils/sliceutil" + sliceutil "github.com/usual2970/certimate/internal/pkg/utils/slice" ) type DeployerConfig struct { @@ -49,12 +48,12 @@ func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { client, err := createSdkClient(config.AccessKeyId, config.AccessKeySecret, config.Region) if err != nil { - return nil, xerrors.Wrap(err, "failed to create sdk client") + return nil, fmt.Errorf("failed to create sdk client: %w", err) } uploader, err := createSslUploader(config.AccessKeyId, config.AccessKeySecret, config.Region) if err != nil { - return nil, xerrors.Wrap(err, "failed to create ssl uploader") + return nil, fmt.Errorf("failed to create ssl uploader: %w", err) } return &DeployerProvider{ @@ -75,29 +74,29 @@ func (d *DeployerProvider) WithLogger(logger *slog.Logger) deployer.Deployer { return d } -func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { +func (d *DeployerProvider) Deploy(ctx context.Context, certPEM string, privkeyPEM string) (*deployer.DeployResult, error) { if d.config.InstanceId == "" { return nil, errors.New("config `instanceId` is required") } switch d.config.ServiceVersion { case "3", "3.0": - if err := d.deployToWAF3(ctx, certPem, privkeyPem); err != nil { + if err := d.deployToWAF3(ctx, certPEM, privkeyPEM); err != nil { return nil, err } default: - return nil, xerrors.Errorf("unsupported service version: %s", d.config.ServiceVersion) + return nil, fmt.Errorf("unsupported service version '%s'", d.config.ServiceVersion) } return &deployer.DeployResult{}, nil } -func (d *DeployerProvider) deployToWAF3(ctx context.Context, certPem string, privkeyPem string) error { +func (d *DeployerProvider) deployToWAF3(ctx context.Context, certPEM string, privkeyPEM string) error { // 上传证书到 CAS - upres, err := d.sslUploader.Upload(ctx, certPem, privkeyPem) + upres, err := d.sslUploader.Upload(ctx, certPEM, privkeyPEM) if err != nil { - return xerrors.Wrap(err, "failed to upload certificate file") + return fmt.Errorf("failed to upload certificate file: %w", err) } else { d.logger.Info("ssl certificate uploaded", slog.Any("result", upres)) } @@ -114,7 +113,7 @@ func (d *DeployerProvider) deployToWAF3(ctx context.Context, certPem string, pri describeDefaultHttpsResp, err := d.sdkClient.DescribeDefaultHttps(describeDefaultHttpsReq) d.logger.Debug("sdk request 'waf.DescribeDefaultHttps'", slog.Any("request", describeDefaultHttpsReq), slog.Any("response", describeDefaultHttpsResp)) if err != nil { - return xerrors.Wrap(err, "failed to execute sdk request 'waf.DescribeDefaultHttps'") + return fmt.Errorf("failed to execute sdk request 'waf.DescribeDefaultHttps': %w", err) } // 修改默认 SSL/TLS 设置 @@ -133,7 +132,7 @@ func (d *DeployerProvider) deployToWAF3(ctx context.Context, certPem string, pri modifyDefaultHttpsResp, err := d.sdkClient.ModifyDefaultHttps(modifyDefaultHttpsReq) d.logger.Debug("sdk request 'waf.ModifyDefaultHttps'", slog.Any("request", modifyDefaultHttpsReq), slog.Any("response", modifyDefaultHttpsResp)) if err != nil { - return xerrors.Wrap(err, "failed to execute sdk request 'waf.ModifyDefaultHttps'") + return fmt.Errorf("failed to execute sdk request 'waf.ModifyDefaultHttps': %w", err) } } else { // 指定接入域名 @@ -148,7 +147,7 @@ func (d *DeployerProvider) deployToWAF3(ctx context.Context, certPem string, pri describeDomainDetailResp, err := d.sdkClient.DescribeDomainDetail(describeDomainDetailReq) d.logger.Debug("sdk request 'waf.DescribeDomainDetail'", slog.Any("request", describeDomainDetailReq), slog.Any("response", describeDomainDetailResp)) if err != nil { - return xerrors.Wrap(err, "failed to execute sdk request 'waf.DescribeDomainDetail'") + return fmt.Errorf("failed to execute sdk request 'waf.DescribeDomainDetail': %w", err) } // 修改 CNAME 接入资源 @@ -164,7 +163,7 @@ func (d *DeployerProvider) deployToWAF3(ctx context.Context, certPem string, pri modifyDomainResp, err := d.sdkClient.ModifyDomain(modifyDomainReq) d.logger.Debug("sdk request 'waf.ModifyDomain'", slog.Any("request", modifyDomainReq), slog.Any("response", modifyDomainResp)) if err != nil { - return xerrors.Wrap(err, "failed to execute sdk request 'waf.ModifyDomain'") + return fmt.Errorf("failed to execute sdk request 'waf.ModifyDomain': %w", err) } } @@ -193,7 +192,7 @@ func createSslUploader(accessKeyId, accessKeySecret, region string) (uploader.Up // 阿里云 CAS 服务接入点是独立于 WAF 服务的 // 国内版固定接入点:华东一杭州 // 国际版固定接入点:亚太东南一新加坡 - if casRegion != "" && !strings.HasPrefix(casRegion, "cn-") { + if !strings.HasPrefix(casRegion, "cn-") { casRegion = "ap-southeast-1" } else { casRegion = "cn-hangzhou" diff --git a/internal/pkg/core/deployer/providers/aliyun-waf/aliyun_waf_test.go b/internal/pkg/core/deployer/providers/aliyun-waf/aliyun_waf_test.go index 2668db47..e1b92613 100644 --- a/internal/pkg/core/deployer/providers/aliyun-waf/aliyun_waf_test.go +++ b/internal/pkg/core/deployer/providers/aliyun-waf/aliyun_waf_test.go @@ -1,4 +1,4 @@ -package aliyunwaf_test +package aliyunwaf_test import ( "context" diff --git a/internal/pkg/core/deployer/providers/aws-acm/aws_acm.go b/internal/pkg/core/deployer/providers/aws-acm/aws_acm.go index 88482de3..3e817dcf 100644 --- a/internal/pkg/core/deployer/providers/aws-acm/aws_acm.go +++ b/internal/pkg/core/deployer/providers/aws-acm/aws_acm.go @@ -1,11 +1,10 @@ -package awsacm +package awsacm import ( "context" + "fmt" "log/slog" - xerrors "github.com/pkg/errors" - "github.com/usual2970/certimate/internal/pkg/core/deployer" "github.com/usual2970/certimate/internal/pkg/core/uploader" uploadersp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/aws-acm" @@ -39,7 +38,7 @@ func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { Region: config.Region, }) if err != nil { - return nil, xerrors.Wrap(err, "failed to create ssl uploader") + return nil, fmt.Errorf("failed to create ssl uploader: %w", err) } return &DeployerProvider{ @@ -59,11 +58,11 @@ func (d *DeployerProvider) WithLogger(logger *slog.Logger) deployer.Deployer { return d } -func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { +func (d *DeployerProvider) Deploy(ctx context.Context, certPEM string, privkeyPEM string) (*deployer.DeployResult, error) { // 上传证书到 ACM - upres, err := d.sslUploader.Upload(ctx, certPem, privkeyPem) + upres, err := d.sslUploader.Upload(ctx, certPEM, privkeyPEM) if err != nil { - return nil, xerrors.Wrap(err, "failed to upload certificate file") + return nil, fmt.Errorf("failed to upload certificate file: %w", err) } else { d.logger.Info("ssl certificate uploaded", slog.Any("result", upres)) } diff --git a/internal/pkg/core/deployer/providers/aws-cloudfront/aws_cloudfront.go b/internal/pkg/core/deployer/providers/aws-cloudfront/aws_cloudfront.go index 6ebfaad2..0808a4fb 100644 --- a/internal/pkg/core/deployer/providers/aws-cloudfront/aws_cloudfront.go +++ b/internal/pkg/core/deployer/providers/aws-cloudfront/aws_cloudfront.go @@ -1,8 +1,9 @@ -package awscloudfront +package awscloudfront import ( "context" "errors" + "fmt" "log/slog" aws "github.com/aws/aws-sdk-go-v2/aws" @@ -10,7 +11,6 @@ import ( awscred "github.com/aws/aws-sdk-go-v2/credentials" "github.com/aws/aws-sdk-go-v2/service/cloudfront" "github.com/aws/aws-sdk-go-v2/service/cloudfront/types" - xerrors "github.com/pkg/errors" "github.com/usual2970/certimate/internal/pkg/core/deployer" "github.com/usual2970/certimate/internal/pkg/core/uploader" @@ -44,7 +44,7 @@ func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { client, err := createSdkClient(config.AccessKeyId, config.SecretAccessKey, config.Region) if err != nil { - return nil, xerrors.Wrap(err, "failed to create sdk client") + return nil, fmt.Errorf("failed to create sdk client: %w", err) } uploader, err := uploadersp.NewUploader(&uploadersp.UploaderConfig{ @@ -53,7 +53,7 @@ func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { Region: config.Region, }) if err != nil { - return nil, xerrors.Wrap(err, "failed to create ssl uploader") + return nil, fmt.Errorf("failed to create ssl uploader: %w", err) } return &DeployerProvider{ @@ -74,15 +74,15 @@ func (d *DeployerProvider) WithLogger(logger *slog.Logger) deployer.Deployer { return d } -func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { +func (d *DeployerProvider) Deploy(ctx context.Context, certPEM string, privkeyPEM string) (*deployer.DeployResult, error) { if d.config.DistributionId == "" { return nil, errors.New("config `distribuitionId` is required") } // 上传证书到 ACM - upres, err := d.sslUploader.Upload(ctx, certPem, privkeyPem) + upres, err := d.sslUploader.Upload(ctx, certPEM, privkeyPEM) if err != nil { - return nil, xerrors.Wrap(err, "failed to upload certificate file") + return nil, fmt.Errorf("failed to upload certificate file: %w", err) } else { d.logger.Info("ssl certificate uploaded", slog.Any("result", upres)) } @@ -95,7 +95,7 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPe getDistributionConfigResp, err := d.sdkClient.GetDistributionConfig(context.TODO(), getDistributionConfigReq) d.logger.Debug("sdk request 'cloudfront.GetDistributionConfig'", slog.Any("request", getDistributionConfigReq), slog.Any("response", getDistributionConfigResp)) if err != nil { - return nil, xerrors.Wrap(err, "failed to execute sdk request 'cloudfront.GetDistributionConfig'") + return nil, fmt.Errorf("failed to execute sdk request 'cloudfront.GetDistributionConfig': %w", err) } // 更新分配配置 @@ -113,7 +113,7 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPe updateDistributionResp, err := d.sdkClient.UpdateDistribution(context.TODO(), updateDistributionReq) d.logger.Debug("sdk request 'cloudfront.UpdateDistribution'", slog.Any("request", updateDistributionReq), slog.Any("response", updateDistributionResp)) if err != nil { - return nil, xerrors.Wrap(err, "failed to execute sdk request 'cloudfront.UpdateDistribution'") + return nil, fmt.Errorf("failed to execute sdk request 'cloudfront.UpdateDistribution': %w", err) } return &deployer.DeployResult{}, nil diff --git a/internal/pkg/core/deployer/providers/aws-cloudfront/aws_cloudfront_test.go b/internal/pkg/core/deployer/providers/aws-cloudfront/aws_cloudfront_test.go index 5b4c75db..78228645 100644 --- a/internal/pkg/core/deployer/providers/aws-cloudfront/aws_cloudfront_test.go +++ b/internal/pkg/core/deployer/providers/aws-cloudfront/aws_cloudfront_test.go @@ -1,4 +1,4 @@ -package awscloudfront_test +package awscloudfront_test import ( "context" diff --git a/internal/pkg/core/deployer/providers/azure-keyvault/azure_keyvault.go b/internal/pkg/core/deployer/providers/azure-keyvault/azure_keyvault.go index 422d39d5..b1f21fdc 100644 --- a/internal/pkg/core/deployer/providers/azure-keyvault/azure_keyvault.go +++ b/internal/pkg/core/deployer/providers/azure-keyvault/azure_keyvault.go @@ -1,4 +1,4 @@ -package azurekeyvault +package azurekeyvault import ( "context" @@ -11,14 +11,13 @@ import ( "github.com/Azure/azure-sdk-for-go/sdk/azcore" "github.com/Azure/azure-sdk-for-go/sdk/azcore/to" "github.com/Azure/azure-sdk-for-go/sdk/azidentity" - "github.com/Azure/azure-sdk-for-go/sdk/keyvault/azcertificates" - xerrors "github.com/pkg/errors" + "github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azcertificates" "github.com/usual2970/certimate/internal/pkg/core/deployer" "github.com/usual2970/certimate/internal/pkg/core/uploader" uploadersp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/azure-keyvault" - "github.com/usual2970/certimate/internal/pkg/utils/certutil" - azcommon "github.com/usual2970/certimate/internal/pkg/vendors/azure-sdk/common" + azcommon "github.com/usual2970/certimate/internal/pkg/sdk3rd/azure/common" + certutil "github.com/usual2970/certimate/internal/pkg/utils/cert" ) type DeployerConfig struct { @@ -53,7 +52,7 @@ func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { client, err := createSdkClient(config.TenantId, config.ClientId, config.ClientSecret, config.CloudName, config.KeyVaultName) if err != nil { - return nil, xerrors.Wrap(err, "failed to create sdk client") + return nil, fmt.Errorf("failed to create sdk client: %w", err) } uploader, err := uploadersp.NewUploader(&uploadersp.UploaderConfig{ @@ -64,7 +63,7 @@ func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { KeyVaultName: config.KeyVaultName, }) if err != nil { - return nil, xerrors.Wrap(err, "failed to create ssl uploader") + return nil, fmt.Errorf("failed to create ssl uploader: %w", err) } return &DeployerProvider{ @@ -85,24 +84,24 @@ func (d *DeployerProvider) WithLogger(logger *slog.Logger) deployer.Deployer { return d } -func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { +func (d *DeployerProvider) Deploy(ctx context.Context, certPEM string, privkeyPEM string) (*deployer.DeployResult, error) { // 解析证书内容 - certX509, err := certutil.ParseCertificateFromPEM(certPem) + certX509, err := certutil.ParseCertificateFromPEM(certPEM) if err != nil { return nil, err } // 转换证书格式 - certPfx, err := certutil.TransformCertificateFromPEMToPFX(certPem, privkeyPem, "") + certPFX, err := certutil.TransformCertificateFromPEMToPFX(certPEM, privkeyPEM, "") if err != nil { - return nil, xerrors.Wrap(err, "failed to transform certificate from PEM to PFX") + return nil, fmt.Errorf("failed to transform certificate from PEM to PFX: %w", err) } if d.config.CertificateName == "" { // 上传证书到 KeyVault - upres, err := d.sslUploader.Upload(ctx, certPem, privkeyPem) + upres, err := d.sslUploader.Upload(ctx, certPEM, privkeyPEM) if err != nil { - return nil, xerrors.Wrap(err, "failed to upload certificate file") + return nil, fmt.Errorf("failed to upload certificate file: %w", err) } else { d.logger.Info("ssl certificate uploaded", slog.Any("result", upres)) } @@ -114,7 +113,7 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPe if err != nil { var respErr *azcore.ResponseError if !errors.As(err, &respErr) || (respErr.ErrorCode != "ResourceNotFound" && respErr.ErrorCode != "CertificateNotFound") { - return nil, xerrors.Wrap(err, "failed to execute sdk request 'keyvault.GetCertificate'") + return nil, fmt.Errorf("failed to execute sdk request 'keyvault.GetCertificate': %w", err) } } else { oldCertX509, err := x509.ParseCertificate(getCertificateResp.CER) @@ -128,7 +127,7 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPe // 导入证书 // REF: https://learn.microsoft.com/en-us/rest/api/keyvault/certificates/import-certificate/import-certificate importCertificateParams := azcertificates.ImportCertificateParameters{ - Base64EncodedCertificate: to.Ptr(base64.StdEncoding.EncodeToString(certPfx)), + Base64EncodedCertificate: to.Ptr(base64.StdEncoding.EncodeToString(certPFX)), CertificatePolicy: &azcertificates.CertificatePolicy{ SecretProperties: &azcertificates.SecretProperties{ ContentType: to.Ptr("application/x-pkcs12"), @@ -142,7 +141,7 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPe importCertificateResp, err := d.sdkClient.ImportCertificate(context.TODO(), d.config.CertificateName, importCertificateParams, nil) d.logger.Debug("sdk request 'keyvault.ImportCertificate'", slog.String("request.certificateName", d.config.CertificateName), slog.Any("request.parameters", importCertificateParams), slog.Any("response", importCertificateResp)) if err != nil { - return nil, xerrors.Wrap(err, "failed to execute sdk request 'keyvault.ImportCertificate'") + return nil, fmt.Errorf("failed to execute sdk request 'keyvault.ImportCertificate': %w", err) } } diff --git a/internal/pkg/core/deployer/providers/baiducloud-appblb/baiducloud_appblb.go b/internal/pkg/core/deployer/providers/baiducloud-appblb/baiducloud_appblb.go index 7a5f7ef2..3318135f 100644 --- a/internal/pkg/core/deployer/providers/baiducloud-appblb/baiducloud_appblb.go +++ b/internal/pkg/core/deployer/providers/baiducloud-appblb/baiducloud_appblb.go @@ -1,4 +1,4 @@ -package baiducloudappblb +package baiducloudappblb import ( "context" @@ -10,12 +10,11 @@ import ( bceappblb "github.com/baidubce/bce-sdk-go/services/appblb" "github.com/google/uuid" - xerrors "github.com/pkg/errors" "github.com/usual2970/certimate/internal/pkg/core/deployer" "github.com/usual2970/certimate/internal/pkg/core/uploader" uploadersp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/baiducloud-cert" - "github.com/usual2970/certimate/internal/pkg/utils/sliceutil" + sliceutil "github.com/usual2970/certimate/internal/pkg/utils/slice" ) type DeployerConfig struct { @@ -54,7 +53,7 @@ func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { client, err := createSdkClient(config.AccessKeyId, config.SecretAccessKey, config.Region) if err != nil { - return nil, xerrors.Wrap(err, "failed to create sdk client") + return nil, fmt.Errorf("failed to create sdk client: %w", err) } uploader, err := uploadersp.NewUploader(&uploadersp.UploaderConfig{ @@ -62,7 +61,7 @@ func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { SecretAccessKey: config.SecretAccessKey, }) if err != nil { - return nil, xerrors.Wrap(err, "failed to create ssl uploader") + return nil, fmt.Errorf("failed to create ssl uploader: %w", err) } return &DeployerProvider{ @@ -82,11 +81,11 @@ func (d *DeployerProvider) WithLogger(logger *slog.Logger) deployer.Deployer { return d } -func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { +func (d *DeployerProvider) Deploy(ctx context.Context, certPEM string, privkeyPEM string) (*deployer.DeployResult, error) { // 上传证书到 CAS - upres, err := d.sslUploader.Upload(ctx, certPem, privkeyPem) + upres, err := d.sslUploader.Upload(ctx, certPEM, privkeyPEM) if err != nil { - return nil, xerrors.Wrap(err, "failed to upload certificate file") + return nil, fmt.Errorf("failed to upload certificate file: %w", err) } else { d.logger.Info("ssl certificate uploaded", slog.Any("result", upres)) } @@ -104,7 +103,7 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPe } default: - return nil, fmt.Errorf("unsupported resource type: %s", d.config.ResourceType) + return nil, fmt.Errorf("unsupported resource type '%s'", d.config.ResourceType) } return &deployer.DeployResult{}, nil @@ -120,7 +119,7 @@ func (d *DeployerProvider) deployToLoadbalancer(ctx context.Context, cloudCertId describeLoadBalancerDetailResp, err := d.sdkClient.DescribeLoadBalancerDetail(d.config.LoadbalancerId) d.logger.Debug("sdk request 'appblb.DescribeLoadBalancerAttribute'", slog.String("blbId", d.config.LoadbalancerId), slog.Any("response", describeLoadBalancerDetailResp)) if err != nil { - return xerrors.Wrap(err, "failed to execute sdk request 'appblb.DescribeLoadBalancerDetail'") + return fmt.Errorf("failed to execute sdk request 'appblb.DescribeLoadBalancerDetail': %w", err) } // 获取全部 HTTPS/SSL 监听端口 @@ -153,8 +152,14 @@ func (d *DeployerProvider) deployToLoadbalancer(ctx context.Context, cloudCertId var errs []error for _, listener := range listeners { - if err := d.updateListenerCertificate(ctx, d.config.LoadbalancerId, listener.Type, listener.Port, cloudCertId); err != nil { - errs = append(errs, err) + select { + case <-ctx.Done(): + return ctx.Err() + + default: + if err := d.updateListenerCertificate(ctx, d.config.LoadbalancerId, listener.Type, listener.Port, cloudCertId); err != nil { + errs = append(errs, err) + } } } @@ -182,7 +187,7 @@ func (d *DeployerProvider) deployToListener(ctx context.Context, cloudCertId str describeAppAllListenersResp, err := d.sdkClient.DescribeAppAllListeners(d.config.LoadbalancerId, describeAppAllListenersRequest) d.logger.Debug("sdk request 'appblb.DescribeAppAllListeners'", slog.String("blbId", d.config.LoadbalancerId), slog.Any("request", describeAppAllListenersRequest), slog.Any("response", describeAppAllListenersResp)) if err != nil { - return xerrors.Wrap(err, "failed to execute sdk request 'appblb.DescribeAppAllListeners'") + return fmt.Errorf("failed to execute sdk request 'appblb.DescribeAppAllListeners': %w", err) } // 获取全部 HTTPS/SSL 监听端口 @@ -210,8 +215,14 @@ func (d *DeployerProvider) deployToListener(ctx context.Context, cloudCertId str var errs []error for _, listener := range listeners { - if err := d.updateListenerCertificate(ctx, d.config.LoadbalancerId, listener.Type, listener.Port, cloudCertId); err != nil { - errs = append(errs, err) + select { + case <-ctx.Done(): + return ctx.Err() + + default: + if err := d.updateListenerCertificate(ctx, d.config.LoadbalancerId, listener.Type, listener.Port, cloudCertId); err != nil { + errs = append(errs, err) + } } } @@ -230,7 +241,7 @@ func (d *DeployerProvider) updateListenerCertificate(ctx context.Context, cloudL case "SSL": return d.updateSslListenerCertificate(ctx, cloudLoadbalancerId, cloudListenerPort, cloudCertId) default: - return fmt.Errorf("unsupported listener type: %s", cloudListenerType) + return fmt.Errorf("unsupported listener type '%s'", cloudListenerType) } } @@ -244,7 +255,7 @@ func (d *DeployerProvider) updateHttpsListenerCertificate(ctx context.Context, c describeAppHTTPSListenersResp, err := d.sdkClient.DescribeAppHTTPSListeners(cloudLoadbalancerId, describeAppHTTPSListenersReq) d.logger.Debug("sdk request 'appblb.DescribeAppHTTPSListeners'", slog.String("blbId", cloudLoadbalancerId), slog.Any("request", describeAppHTTPSListenersReq), slog.Any("response", describeAppHTTPSListenersResp)) if err != nil { - return xerrors.Wrap(err, "failed to execute sdk request 'appblb.DescribeAppHTTPSListeners'") + return fmt.Errorf("failed to execute sdk request 'appblb.DescribeAppHTTPSListeners': %w", err) } else if len(describeAppHTTPSListenersResp.ListenerList) == 0 { return fmt.Errorf("listener %s:%d not found", cloudLoadbalancerId, cloudHttpsListenerPort) } @@ -257,12 +268,13 @@ func (d *DeployerProvider) updateHttpsListenerCertificate(ctx context.Context, c updateAppHTTPSListenerReq := &bceappblb.UpdateAppHTTPSListenerArgs{ ClientToken: generateClientToken(), ListenerPort: uint16(cloudHttpsListenerPort), + Scheduler: describeAppHTTPSListenersResp.ListenerList[0].Scheduler, CertIds: []string{cloudCertId}, } err := d.sdkClient.UpdateAppHTTPSListener(cloudLoadbalancerId, updateAppHTTPSListenerReq) d.logger.Debug("sdk request 'appblb.UpdateAppHTTPSListener'", slog.Any("request", updateAppHTTPSListenerReq)) if err != nil { - return xerrors.Wrap(err, "failed to execute sdk request 'appblb.UpdateAppHTTPSListener'") + return fmt.Errorf("failed to execute sdk request 'appblb.UpdateAppHTTPSListener': %w", err) } } else { // 指定 SNI,需部署到扩展域名 @@ -272,6 +284,7 @@ func (d *DeployerProvider) updateHttpsListenerCertificate(ctx context.Context, c updateAppHTTPSListenerReq := &bceappblb.UpdateAppHTTPSListenerArgs{ ClientToken: generateClientToken(), ListenerPort: uint16(cloudHttpsListenerPort), + Scheduler: describeAppHTTPSListenersResp.ListenerList[0].Scheduler, AdditionalCertDomains: sliceutil.Map(describeAppHTTPSListenersResp.ListenerList[0].AdditionalCertDomains, func(domain bceappblb.AdditionalCertDomainsModel) bceappblb.AdditionalCertDomainsModel { if domain.Host == d.config.Domain { return bceappblb.AdditionalCertDomainsModel{ @@ -289,7 +302,7 @@ func (d *DeployerProvider) updateHttpsListenerCertificate(ctx context.Context, c err := d.sdkClient.UpdateAppHTTPSListener(cloudLoadbalancerId, updateAppHTTPSListenerReq) d.logger.Debug("sdk request 'appblb.UpdateAppHTTPSListener'", slog.Any("request", updateAppHTTPSListenerReq)) if err != nil { - return xerrors.Wrap(err, "failed to execute sdk request 'appblb.UpdateAppHTTPSListener'") + return fmt.Errorf("failed to execute sdk request 'appblb.UpdateAppHTTPSListener': %w", err) } } @@ -307,7 +320,7 @@ func (d *DeployerProvider) updateSslListenerCertificate(ctx context.Context, clo err := d.sdkClient.UpdateAppSSLListener(cloudLoadbalancerId, updateAppSSLListenerReq) d.logger.Debug("sdk request 'appblb.UpdateAppSSLListener'", slog.Any("request", updateAppSSLListenerReq)) if err != nil { - return xerrors.Wrap(err, "failed to execute sdk request 'appblb.UpdateAppSSLListener'") + return fmt.Errorf("failed to execute sdk request 'appblb.UpdateAppSSLListener': %w", err) } return nil diff --git a/internal/pkg/core/deployer/providers/baiducloud-appblb/baiducloud_appblb_test.go b/internal/pkg/core/deployer/providers/baiducloud-appblb/baiducloud_appblb_test.go index 6753475c..1e60d5f0 100644 --- a/internal/pkg/core/deployer/providers/baiducloud-appblb/baiducloud_appblb_test.go +++ b/internal/pkg/core/deployer/providers/baiducloud-appblb/baiducloud_appblb_test.go @@ -1,4 +1,4 @@ -package baiducloudappblb_test +package baiducloudappblb_test import ( "context" diff --git a/internal/pkg/core/deployer/providers/baiducloud-appblb/consts.go b/internal/pkg/core/deployer/providers/baiducloud-appblb/consts.go index 3955f9a0..8e49730b 100644 --- a/internal/pkg/core/deployer/providers/baiducloud-appblb/consts.go +++ b/internal/pkg/core/deployer/providers/baiducloud-appblb/consts.go @@ -1,4 +1,4 @@ -package baiducloudappblb +package baiducloudappblb type ResourceType string diff --git a/internal/pkg/core/deployer/providers/baiducloud-blb/baiducloud_blb.go b/internal/pkg/core/deployer/providers/baiducloud-blb/baiducloud_blb.go index 6be94e6d..a16ea102 100644 --- a/internal/pkg/core/deployer/providers/baiducloud-blb/baiducloud_blb.go +++ b/internal/pkg/core/deployer/providers/baiducloud-blb/baiducloud_blb.go @@ -1,4 +1,4 @@ -package baiducloudblb +package baiducloudblb import ( "context" @@ -10,12 +10,11 @@ import ( bceblb "github.com/baidubce/bce-sdk-go/services/blb" "github.com/google/uuid" - xerrors "github.com/pkg/errors" "github.com/usual2970/certimate/internal/pkg/core/deployer" "github.com/usual2970/certimate/internal/pkg/core/uploader" uploadersp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/baiducloud-cert" - "github.com/usual2970/certimate/internal/pkg/utils/sliceutil" + sliceutil "github.com/usual2970/certimate/internal/pkg/utils/slice" ) type DeployerConfig struct { @@ -54,7 +53,7 @@ func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { client, err := createSdkClient(config.AccessKeyId, config.SecretAccessKey, config.Region) if err != nil { - return nil, xerrors.Wrap(err, "failed to create sdk client") + return nil, fmt.Errorf("failed to create sdk client: %w", err) } uploader, err := uploadersp.NewUploader(&uploadersp.UploaderConfig{ @@ -62,7 +61,7 @@ func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { SecretAccessKey: config.SecretAccessKey, }) if err != nil { - return nil, xerrors.Wrap(err, "failed to create ssl uploader") + return nil, fmt.Errorf("failed to create ssl uploader: %w", err) } return &DeployerProvider{ @@ -82,11 +81,11 @@ func (d *DeployerProvider) WithLogger(logger *slog.Logger) deployer.Deployer { return d } -func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { +func (d *DeployerProvider) Deploy(ctx context.Context, certPEM string, privkeyPEM string) (*deployer.DeployResult, error) { // 上传证书到 CAS - upres, err := d.sslUploader.Upload(ctx, certPem, privkeyPem) + upres, err := d.sslUploader.Upload(ctx, certPEM, privkeyPEM) if err != nil { - return nil, xerrors.Wrap(err, "failed to upload certificate file") + return nil, fmt.Errorf("failed to upload certificate file: %w", err) } else { d.logger.Info("ssl certificate uploaded", slog.Any("result", upres)) } @@ -104,7 +103,7 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPe } default: - return nil, fmt.Errorf("unsupported resource type: %s", d.config.ResourceType) + return nil, fmt.Errorf("unsupported resource type '%s'", d.config.ResourceType) } return &deployer.DeployResult{}, nil @@ -120,7 +119,7 @@ func (d *DeployerProvider) deployToLoadbalancer(ctx context.Context, cloudCertId describeLoadBalancerDetailResp, err := d.sdkClient.DescribeLoadBalancerDetail(d.config.LoadbalancerId) d.logger.Debug("sdk request 'blb.DescribeLoadBalancerAttribute'", slog.String("blbId", d.config.LoadbalancerId), slog.Any("response", describeLoadBalancerDetailResp)) if err != nil { - return xerrors.Wrap(err, "failed to execute sdk request 'blb.DescribeLoadBalancerDetail'") + return fmt.Errorf("failed to execute sdk request 'blb.DescribeLoadBalancerDetail': %w", err) } // 获取全部 HTTPS/SSL 监听端口 @@ -153,8 +152,14 @@ func (d *DeployerProvider) deployToLoadbalancer(ctx context.Context, cloudCertId var errs []error for _, listener := range listeners { - if err := d.updateListenerCertificate(ctx, d.config.LoadbalancerId, listener.Type, listener.Port, cloudCertId); err != nil { - errs = append(errs, err) + select { + case <-ctx.Done(): + return ctx.Err() + + default: + if err := d.updateListenerCertificate(ctx, d.config.LoadbalancerId, listener.Type, listener.Port, cloudCertId); err != nil { + errs = append(errs, err) + } } } @@ -182,7 +187,7 @@ func (d *DeployerProvider) deployToListener(ctx context.Context, cloudCertId str describeAllListenersResp, err := d.sdkClient.DescribeAllListeners(d.config.LoadbalancerId, describeAllListenersRequest) d.logger.Debug("sdk request 'blb.DescribeAllListeners'", slog.String("blbId", d.config.LoadbalancerId), slog.Any("request", describeAllListenersRequest), slog.Any("response", describeAllListenersResp)) if err != nil { - return xerrors.Wrap(err, "failed to execute sdk request 'blb.DescribeAllListeners'") + return fmt.Errorf("failed to execute sdk request 'blb.DescribeAllListeners': %w", err) } // 获取全部 HTTPS/SSL 监听端口 @@ -210,8 +215,14 @@ func (d *DeployerProvider) deployToListener(ctx context.Context, cloudCertId str var errs []error for _, listener := range listeners { - if err := d.updateListenerCertificate(ctx, d.config.LoadbalancerId, listener.Type, listener.Port, cloudCertId); err != nil { - errs = append(errs, err) + select { + case <-ctx.Done(): + return ctx.Err() + + default: + if err := d.updateListenerCertificate(ctx, d.config.LoadbalancerId, listener.Type, listener.Port, cloudCertId); err != nil { + errs = append(errs, err) + } } } @@ -230,7 +241,7 @@ func (d *DeployerProvider) updateListenerCertificate(ctx context.Context, cloudL case "SSL": return d.updateSslListenerCertificate(ctx, cloudLoadbalancerId, cloudListenerPort, cloudCertId) default: - return fmt.Errorf("unsupported listener type: %s", cloudListenerType) + return fmt.Errorf("unsupported listener type '%s'", cloudListenerType) } } @@ -244,7 +255,7 @@ func (d *DeployerProvider) updateHttpsListenerCertificate(ctx context.Context, c describeHTTPSListenersResp, err := d.sdkClient.DescribeHTTPSListeners(cloudLoadbalancerId, describeHTTPSListenersReq) d.logger.Debug("sdk request 'blb.DescribeHTTPSListeners'", slog.String("blbId", cloudLoadbalancerId), slog.Any("request", describeHTTPSListenersReq), slog.Any("response", describeHTTPSListenersResp)) if err != nil { - return xerrors.Wrap(err, "failed to execute sdk request 'blb.DescribeHTTPSListeners'") + return fmt.Errorf("failed to execute sdk request 'blb.DescribeHTTPSListeners': %w", err) } else if len(describeHTTPSListenersResp.ListenerList) == 0 { return fmt.Errorf("listener %s:%d not found", cloudLoadbalancerId, cloudHttpsListenerPort) } @@ -262,7 +273,7 @@ func (d *DeployerProvider) updateHttpsListenerCertificate(ctx context.Context, c err := d.sdkClient.UpdateHTTPSListener(cloudLoadbalancerId, updateHTTPSListenerReq) d.logger.Debug("sdk request 'blb.UpdateHTTPSListener'", slog.Any("request", updateHTTPSListenerReq)) if err != nil { - return xerrors.Wrap(err, "failed to execute sdk request 'blb.UpdateHTTPSListener'") + return fmt.Errorf("failed to execute sdk request 'blb.UpdateHTTPSListener': %w", err) } } else { // 指定 SNI,需部署到扩展域名 @@ -289,7 +300,7 @@ func (d *DeployerProvider) updateHttpsListenerCertificate(ctx context.Context, c err := d.sdkClient.UpdateHTTPSListener(cloudLoadbalancerId, updateHTTPSListenerReq) d.logger.Debug("sdk request 'blb.UpdateHTTPSListener'", slog.Any("request", updateHTTPSListenerReq)) if err != nil { - return xerrors.Wrap(err, "failed to execute sdk request 'blb.UpdateHTTPSListener'") + return fmt.Errorf("failed to execute sdk request 'blb.UpdateHTTPSListener': %w", err) } } @@ -307,7 +318,7 @@ func (d *DeployerProvider) updateSslListenerCertificate(ctx context.Context, clo err := d.sdkClient.UpdateSSLListener(cloudLoadbalancerId, updateSSLListenerReq) d.logger.Debug("sdk request 'blb.UpdateSSLListener'", slog.Any("request", updateSSLListenerReq)) if err != nil { - return xerrors.Wrap(err, "failed to execute sdk request 'blb.UpdateSSLListener'") + return fmt.Errorf("failed to execute sdk request 'blb.UpdateSSLListener': %w", err) } return nil diff --git a/internal/pkg/core/deployer/providers/baiducloud-blb/baiducloud_blb_test.go b/internal/pkg/core/deployer/providers/baiducloud-blb/baiducloud_blb_test.go index 756e6f8f..c96e4f0c 100644 --- a/internal/pkg/core/deployer/providers/baiducloud-blb/baiducloud_blb_test.go +++ b/internal/pkg/core/deployer/providers/baiducloud-blb/baiducloud_blb_test.go @@ -1,4 +1,4 @@ -package baiducloudblb_test +package baiducloudblb_test import ( "context" diff --git a/internal/pkg/core/deployer/providers/baiducloud-blb/consts.go b/internal/pkg/core/deployer/providers/baiducloud-blb/consts.go index 52cb8804..7af2d812 100644 --- a/internal/pkg/core/deployer/providers/baiducloud-blb/consts.go +++ b/internal/pkg/core/deployer/providers/baiducloud-blb/consts.go @@ -1,4 +1,4 @@ -package baiducloudblb +package baiducloudblb type ResourceType string diff --git a/internal/pkg/core/deployer/providers/baiducloud-cdn/baiducloud_cdn.go b/internal/pkg/core/deployer/providers/baiducloud-cdn/baiducloud_cdn.go index 87f5aa5c..7ef78fb1 100644 --- a/internal/pkg/core/deployer/providers/baiducloud-cdn/baiducloud_cdn.go +++ b/internal/pkg/core/deployer/providers/baiducloud-cdn/baiducloud_cdn.go @@ -1,4 +1,4 @@ -package baiducloudcdn +package baiducloudcdn import ( "context" @@ -8,7 +8,6 @@ import ( bcecdn "github.com/baidubce/bce-sdk-go/services/cdn" bcecdnapi "github.com/baidubce/bce-sdk-go/services/cdn/api" - xerrors "github.com/pkg/errors" "github.com/usual2970/certimate/internal/pkg/core/deployer" ) @@ -37,7 +36,7 @@ func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { client, err := createSdkClient(config.AccessKeyId, config.SecretAccessKey) if err != nil { - return nil, xerrors.Wrap(err, "failed to create sdk client") + return nil, fmt.Errorf("failed to create sdk client: %w", err) } return &DeployerProvider{ @@ -56,21 +55,21 @@ func (d *DeployerProvider) WithLogger(logger *slog.Logger) deployer.Deployer { return d } -func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { +func (d *DeployerProvider) Deploy(ctx context.Context, certPEM string, privkeyPEM string) (*deployer.DeployResult, error) { // 修改域名证书 // REF: https://cloud.baidu.com/doc/CDN/s/qjzuz2hp8 putCertResp, err := d.sdkClient.PutCert( d.config.Domain, &bcecdnapi.UserCertificate{ CertName: fmt.Sprintf("certimate-%d", time.Now().UnixMilli()), - ServerData: certPem, - PrivateData: privkeyPem, + ServerData: certPEM, + PrivateData: privkeyPEM, }, "ON", ) d.logger.Debug("sdk request 'cdn.PutCert'", slog.String("request.domain", d.config.Domain), slog.Any("response", putCertResp)) if err != nil { - return nil, xerrors.Wrap(err, "failed to execute sdk request 'cdn.PutCert'") + return nil, fmt.Errorf("failed to execute sdk request 'cdn.PutCert': %w", err) } return &deployer.DeployResult{}, nil 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 ecb9a9d4..cef03392 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 @@ -1,4 +1,4 @@ -package baiducloudcdn_test +package baiducloudcdn_test import ( "context" diff --git a/internal/pkg/core/deployer/providers/baiducloud-cert/baiducloud_cert.go b/internal/pkg/core/deployer/providers/baiducloud-cert/baiducloud_cert.go index d51018f0..200d34ec 100644 --- a/internal/pkg/core/deployer/providers/baiducloud-cert/baiducloud_cert.go +++ b/internal/pkg/core/deployer/providers/baiducloud-cert/baiducloud_cert.go @@ -1,11 +1,10 @@ -package baiducloudcert +package baiducloudcert import ( "context" + "fmt" "log/slog" - xerrors "github.com/pkg/errors" - "github.com/usual2970/certimate/internal/pkg/core/deployer" "github.com/usual2970/certimate/internal/pkg/core/uploader" uploadersp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/baiducloud-cert" @@ -36,7 +35,7 @@ func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { SecretAccessKey: config.SecretAccessKey, }) if err != nil { - return nil, xerrors.Wrap(err, "failed to create ssl uploader") + return nil, fmt.Errorf("failed to create ssl uploader: %w", err) } return &DeployerProvider{ @@ -55,11 +54,11 @@ func (d *DeployerProvider) WithLogger(logger *slog.Logger) deployer.Deployer { return d } -func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { +func (d *DeployerProvider) Deploy(ctx context.Context, certPEM string, privkeyPEM string) (*deployer.DeployResult, error) { // 上传证书到 CAS - upres, err := d.sslUploader.Upload(ctx, certPem, privkeyPem) + upres, err := d.sslUploader.Upload(ctx, certPEM, privkeyPEM) if err != nil { - return nil, xerrors.Wrap(err, "failed to upload certificate file") + return nil, fmt.Errorf("failed to upload certificate file: %w", err) } else { d.logger.Info("ssl certificate uploaded", slog.Any("result", upres)) } diff --git a/internal/pkg/core/deployer/providers/baishan-cdn/baishan_cdn.go b/internal/pkg/core/deployer/providers/baishan-cdn/baishan_cdn.go index ce204525..95c0f9f4 100644 --- a/internal/pkg/core/deployer/providers/baishan-cdn/baishan_cdn.go +++ b/internal/pkg/core/deployer/providers/baishan-cdn/baishan_cdn.go @@ -1,4 +1,4 @@ -package baishancdn +package baishancdn import ( "context" @@ -10,10 +10,8 @@ import ( "strings" "time" - xerrors "github.com/pkg/errors" - "github.com/usual2970/certimate/internal/pkg/core/deployer" - bssdk "github.com/usual2970/certimate/internal/pkg/vendors/baishan-sdk" + bssdk "github.com/usual2970/certimate/internal/pkg/sdk3rd/baishan" ) type DeployerConfig struct { @@ -41,7 +39,7 @@ func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { client, err := createSdkClient(config.ApiToken) if err != nil { - return nil, xerrors.Wrap(err, "failed to create sdk client") + return nil, fmt.Errorf("failed to create sdk client: %w", err) } return &DeployerProvider{ @@ -60,7 +58,7 @@ func (d *DeployerProvider) WithLogger(logger *slog.Logger) deployer.Deployer { return d } -func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { +func (d *DeployerProvider) Deploy(ctx context.Context, certPEM string, privkeyPEM string) (*deployer.DeployResult, error) { if d.config.Domain == "" { return nil, errors.New("config `domain` is required") } @@ -70,8 +68,8 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPe // REF: https://portal.baishancloud.com/track/document/downloadPdf/1441 certificateId := "" createCertificateReq := &bssdk.CreateCertificateRequest{ - Certificate: certPem, - Key: privkeyPem, + Certificate: certPEM, + Key: privkeyPEM, Name: fmt.Sprintf("certimate_%d", time.Now().UnixMilli()), } createCertificateResp, err := d.sdkClient.CreateCertificate(createCertificateReq) @@ -86,7 +84,7 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPe } if certificateId == "" { - return nil, xerrors.Wrap(err, "failed to execute sdk request 'baishan.CreateCertificate'") + return nil, fmt.Errorf("failed to execute sdk request 'baishan.CreateCertificate': %w", err) } } else { certificateId = createCertificateResp.Data.CertId.String() @@ -101,7 +99,7 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPe getDomainConfigResp, err := d.sdkClient.GetDomainConfig(getDomainConfigReq) d.logger.Debug("sdk request 'baishan.GetDomainConfig'", slog.Any("request", getDomainConfigReq), slog.Any("response", getDomainConfigResp)) if err != nil { - return nil, xerrors.Wrap(err, "failed to execute sdk request 'baishan.GetDomainConfig'") + return nil, fmt.Errorf("failed to execute sdk request 'baishan.GetDomainConfig': %w", err) } else if len(getDomainConfigResp.Data) == 0 { return nil, errors.New("domain config not found") } @@ -122,21 +120,21 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPe setDomainConfigResp, err := d.sdkClient.SetDomainConfig(setDomainConfigReq) d.logger.Debug("sdk request 'baishan.SetDomainConfig'", slog.Any("request", setDomainConfigReq), slog.Any("response", setDomainConfigResp)) if err != nil { - return nil, xerrors.Wrap(err, "failed to execute sdk request 'baishan.SetDomainConfig'") + return nil, fmt.Errorf("failed to execute sdk request 'baishan.SetDomainConfig': %w", err) } } else { // 替换证书 // REF: https://portal.baishancloud.com/track/document/downloadPdf/1441 createCertificateReq := &bssdk.CreateCertificateRequest{ CertificateId: &d.config.CertificateId, - Certificate: certPem, - Key: privkeyPem, + Certificate: certPEM, + Key: privkeyPEM, Name: fmt.Sprintf("certimate_%d", time.Now().UnixMilli()), } createCertificateResp, err := d.sdkClient.CreateCertificate(createCertificateReq) d.logger.Debug("sdk request 'baishan.CreateCertificate'", slog.Any("request", createCertificateReq), slog.Any("response", createCertificateResp)) if err != nil { - return nil, xerrors.Wrap(err, "failed to execute sdk request 'baishan.CreateCertificate'") + return nil, fmt.Errorf("failed to execute sdk request 'baishan.CreateCertificate': %w", err) } } diff --git a/internal/pkg/core/deployer/providers/baishan-cdn/baishan_cdn_test.go b/internal/pkg/core/deployer/providers/baishan-cdn/baishan_cdn_test.go index 5534a232..8e3a16b8 100644 --- a/internal/pkg/core/deployer/providers/baishan-cdn/baishan_cdn_test.go +++ b/internal/pkg/core/deployer/providers/baishan-cdn/baishan_cdn_test.go @@ -1,4 +1,4 @@ -package baishancdn_test +package baishancdn_test import ( "context" diff --git a/internal/pkg/core/deployer/providers/baotapanel-console/baotapanel_console.go b/internal/pkg/core/deployer/providers/baotapanel-console/baotapanel_console.go index 57e37f05..b1a57a81 100644 --- a/internal/pkg/core/deployer/providers/baotapanel-console/baotapanel_console.go +++ b/internal/pkg/core/deployer/providers/baotapanel-console/baotapanel_console.go @@ -1,16 +1,15 @@ -package baotapanelconsole +package baotapanelconsole import ( "context" "crypto/tls" "errors" + "fmt" "log/slog" "net/url" - xerrors "github.com/pkg/errors" - "github.com/usual2970/certimate/internal/pkg/core/deployer" - btsdk "github.com/usual2970/certimate/internal/pkg/vendors/btpanel-sdk" + btsdk "github.com/usual2970/certimate/internal/pkg/sdk3rd/btpanel" ) type DeployerConfig struct { @@ -39,7 +38,7 @@ func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { client, err := createSdkClient(config.ApiUrl, config.ApiKey, config.AllowInsecureConnections) if err != nil { - return nil, xerrors.Wrap(err, "failed to create sdk client") + return nil, fmt.Errorf("failed to create sdk client: %w", err) } return &DeployerProvider{ @@ -58,16 +57,16 @@ func (d *DeployerProvider) WithLogger(logger *slog.Logger) deployer.Deployer { return d } -func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { +func (d *DeployerProvider) Deploy(ctx context.Context, certPEM string, privkeyPEM string) (*deployer.DeployResult, error) { // 设置面板 SSL 证书 configSavePanelSSLReq := &btsdk.ConfigSavePanelSSLRequest{ - PrivateKey: privkeyPem, - Certificate: certPem, + PrivateKey: privkeyPEM, + Certificate: certPEM, } configSavePanelSSLResp, err := d.sdkClient.ConfigSavePanelSSL(configSavePanelSSLReq) d.logger.Debug("sdk request 'bt.ConfigSavePanelSSL'", slog.Any("request", configSavePanelSSLReq), slog.Any("response", configSavePanelSSLResp)) if err != nil { - return nil, xerrors.Wrap(err, "failed to execute sdk request 'bt.ConfigSavePanelSSL'") + return nil, fmt.Errorf("failed to execute sdk request 'bt.ConfigSavePanelSSL': %w", err) } if d.config.AutoRestart { @@ -83,7 +82,7 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPe return &deployer.DeployResult{}, nil } -func createSdkClient(apiUrl, apiKey string, allowInsecure bool) (*btsdk.Client, error) { +func createSdkClient(apiUrl, apiKey string, skipTlsVerify bool) (*btsdk.Client, error) { if _, err := url.Parse(apiUrl); err != nil { return nil, errors.New("invalid baota api url") } @@ -93,7 +92,7 @@ func createSdkClient(apiUrl, apiKey string, allowInsecure bool) (*btsdk.Client, } client := btsdk.NewClient(apiUrl, apiKey) - if allowInsecure { + if skipTlsVerify { client.WithTLSConfig(&tls.Config{InsecureSkipVerify: true}) } diff --git a/internal/pkg/core/deployer/providers/baotapanel-console/baotapanel_console_test.go b/internal/pkg/core/deployer/providers/baotapanel-console/baotapanel_console_test.go index a10afb37..5f3845e4 100644 --- a/internal/pkg/core/deployer/providers/baotapanel-console/baotapanel_console_test.go +++ b/internal/pkg/core/deployer/providers/baotapanel-console/baotapanel_console_test.go @@ -1,4 +1,4 @@ -package baotapanelconsole_test +package baotapanelconsole_test import ( "context" diff --git a/internal/pkg/core/deployer/providers/baotapanel-site/baotapanel_site.go b/internal/pkg/core/deployer/providers/baotapanel-site/baotapanel_site.go index 082b57b7..f8266791 100644 --- a/internal/pkg/core/deployer/providers/baotapanel-site/baotapanel_site.go +++ b/internal/pkg/core/deployer/providers/baotapanel-site/baotapanel_site.go @@ -1,4 +1,4 @@ -package baotapanelsite +package baotapanelsite import ( "context" @@ -8,11 +8,9 @@ import ( "log/slog" "net/url" - xerrors "github.com/pkg/errors" - "github.com/usual2970/certimate/internal/pkg/core/deployer" - "github.com/usual2970/certimate/internal/pkg/utils/sliceutil" - btsdk "github.com/usual2970/certimate/internal/pkg/vendors/btpanel-sdk" + btsdk "github.com/usual2970/certimate/internal/pkg/sdk3rd/btpanel" + sliceutil "github.com/usual2970/certimate/internal/pkg/utils/slice" ) type DeployerConfig struct { @@ -45,7 +43,7 @@ func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { client, err := createSdkClient(config.ApiUrl, config.ApiKey, config.AllowInsecureConnections) if err != nil { - return nil, xerrors.Wrap(err, "failed to create sdk client") + return nil, fmt.Errorf("failed to create sdk client: %w", err) } return &DeployerProvider{ @@ -64,7 +62,7 @@ func (d *DeployerProvider) WithLogger(logger *slog.Logger) deployer.Deployer { return d } -func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { +func (d *DeployerProvider) Deploy(ctx context.Context, certPEM string, privkeyPEM string) (*deployer.DeployResult, error) { switch d.config.SiteType { case "php": { @@ -76,13 +74,13 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPe siteSetSSLReq := &btsdk.SiteSetSSLRequest{ SiteName: d.config.SiteName, Type: "0", - Certificate: certPem, - PrivateKey: privkeyPem, + Certificate: certPEM, + PrivateKey: privkeyPEM, } siteSetSSLResp, err := d.sdkClient.SiteSetSSL(siteSetSSLReq) d.logger.Debug("sdk request 'bt.SiteSetSSL'", slog.Any("request", siteSetSSLReq), slog.Any("response", siteSetSSLResp)) if err != nil { - return nil, xerrors.Wrap(err, "failed to execute sdk request 'bt.SiteSetSSL'") + return nil, fmt.Errorf("failed to execute sdk request 'bt.SiteSetSSL': %w", err) } } @@ -94,13 +92,13 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPe // 上传证书 sslCertSaveCertReq := &btsdk.SSLCertSaveCertRequest{ - Certificate: certPem, - PrivateKey: privkeyPem, + Certificate: certPEM, + PrivateKey: privkeyPEM, } sslCertSaveCertResp, err := d.sdkClient.SSLCertSaveCert(sslCertSaveCertReq) d.logger.Debug("sdk request 'bt.SSLCertSaveCert'", slog.Any("request", sslCertSaveCertReq), slog.Any("response", sslCertSaveCertResp)) if err != nil { - return nil, xerrors.Wrap(err, "failed to execute sdk request 'bt.SSLCertSaveCert'") + return nil, fmt.Errorf("failed to execute sdk request 'bt.SSLCertSaveCert': %w", err) } // 设置站点证书 @@ -115,18 +113,18 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPe sslSetBatchCertToSiteResp, err := d.sdkClient.SSLSetBatchCertToSite(sslSetBatchCertToSiteReq) d.logger.Debug("sdk request 'bt.SSLSetBatchCertToSite'", slog.Any("request", sslSetBatchCertToSiteReq), slog.Any("response", sslSetBatchCertToSiteResp)) if err != nil { - return nil, xerrors.Wrap(err, "failed to execute sdk request 'bt.SSLSetBatchCertToSite'") + return nil, fmt.Errorf("failed to execute sdk request 'bt.SSLSetBatchCertToSite': %w", err) } } default: - return nil, fmt.Errorf("unsupported site type: %s", d.config.SiteType) + return nil, fmt.Errorf("unsupported site type '%s'", d.config.SiteType) } return &deployer.DeployResult{}, nil } -func createSdkClient(apiUrl, apiKey string, allowInsecure bool) (*btsdk.Client, error) { +func createSdkClient(apiUrl, apiKey string, skipTlsVerify bool) (*btsdk.Client, error) { if _, err := url.Parse(apiUrl); err != nil { return nil, errors.New("invalid baota api url") } @@ -136,7 +134,7 @@ func createSdkClient(apiUrl, apiKey string, allowInsecure bool) (*btsdk.Client, } client := btsdk.NewClient(apiUrl, apiKey) - if allowInsecure { + if skipTlsVerify { client.WithTLSConfig(&tls.Config{InsecureSkipVerify: true}) } diff --git a/internal/pkg/core/deployer/providers/baotapanel-site/baotapanel_site_test.go b/internal/pkg/core/deployer/providers/baotapanel-site/baotapanel_site_test.go index f36605fe..5fece978 100644 --- a/internal/pkg/core/deployer/providers/baotapanel-site/baotapanel_site_test.go +++ b/internal/pkg/core/deployer/providers/baotapanel-site/baotapanel_site_test.go @@ -1,4 +1,4 @@ -package baotapanelsite_test +package baotapanelsite_test import ( "context" diff --git a/internal/pkg/core/deployer/providers/bunny-cdn/bunny_cdn.go b/internal/pkg/core/deployer/providers/bunny-cdn/bunny_cdn.go index bcf22635..e2bfd696 100644 --- a/internal/pkg/core/deployer/providers/bunny-cdn/bunny_cdn.go +++ b/internal/pkg/core/deployer/providers/bunny-cdn/bunny_cdn.go @@ -1,23 +1,22 @@ -package bunnycdn +package bunnycdn import ( "context" "encoding/base64" + "fmt" "log/slog" - xerrors "github.com/pkg/errors" - "github.com/usual2970/certimate/internal/pkg/core/deployer" - bunnysdk "github.com/usual2970/certimate/internal/pkg/vendors/bunny-sdk" + bunnysdk "github.com/usual2970/certimate/internal/pkg/sdk3rd/bunny" ) type DeployerConfig struct { - // Bunny API Key + // Bunny API Key。 ApiKey string `json:"apiKey"` - // Bunny Pull Zone ID + // Bunny Pull Zone ID。 PullZoneId string `json:"pullZoneId"` - // Bunny CDN Hostname(支持泛域名) - HostName string `json:"hostName"` + // Bunny CDN Hostname(支持泛域名)。 + Hostname string `json:"hostname"` } type DeployerProvider struct { @@ -49,21 +48,18 @@ func (d *DeployerProvider) WithLogger(logger *slog.Logger) deployer.Deployer { return d } -func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { - // Prepare - certPemBase64 := base64.StdEncoding.EncodeToString([]byte(certPem)) - privkeyPemBase64 := base64.StdEncoding.EncodeToString([]byte(privkeyPem)) +func (d *DeployerProvider) Deploy(ctx context.Context, certPEM string, privkeyPEM string) (*deployer.DeployResult, error) { // 上传证书 createCertificateReq := &bunnysdk.AddCustomCertificateRequest{ - Hostname: d.config.HostName, + Hostname: d.config.Hostname, PullZoneId: d.config.PullZoneId, - Certificate: certPemBase64, - CertificateKey: privkeyPemBase64, + Certificate: base64.StdEncoding.EncodeToString([]byte(certPEM)), + CertificateKey: base64.StdEncoding.EncodeToString([]byte(privkeyPEM)), } createCertificateResp, err := d.sdkClient.AddCustomCertificate(createCertificateReq) - d.logger.Debug("sdk request 'bunny-cdn.AddCustomCertificate'", slog.Any("request", createCertificateReq), slog.Any("response", createCertificateResp)) + d.logger.Debug("sdk request 'bunny.AddCustomCertificate'", slog.Any("request", createCertificateReq), slog.Any("response", createCertificateResp)) if err != nil { - return nil, xerrors.Wrap(err, "failed to execute sdk request 'bunny-cdn.AddCustomCertificate'") + return nil, fmt.Errorf("failed to execute sdk request 'bunny.AddCustomCertificate': %w", err) } return &deployer.DeployResult{}, nil diff --git a/internal/pkg/core/deployer/providers/bunny-cdn/bunny_cdn_test.go b/internal/pkg/core/deployer/providers/bunny-cdn/bunny_cdn_test.go index e4e54a20..83fbb0f6 100644 --- a/internal/pkg/core/deployer/providers/bunny-cdn/bunny_cdn_test.go +++ b/internal/pkg/core/deployer/providers/bunny-cdn/bunny_cdn_test.go @@ -1,4 +1,4 @@ -package bunnycdn_test +package bunnycdn_test import ( "context" @@ -55,7 +55,7 @@ func TestDeploy(t *testing.T) { deployer, err := provider.NewDeployer(&provider.DeployerConfig{ ApiKey: fApiKey, PullZoneId: fPullZoneId, - HostName: fHostName, + Hostname: fHostName, }) if err != nil { t.Errorf("err: %+v", err) diff --git a/internal/pkg/core/deployer/providers/byteplus-cdn/byteplus_cdn.go b/internal/pkg/core/deployer/providers/byteplus-cdn/byteplus_cdn.go index 7406f074..e659c9a1 100644 --- a/internal/pkg/core/deployer/providers/byteplus-cdn/byteplus_cdn.go +++ b/internal/pkg/core/deployer/providers/byteplus-cdn/byteplus_cdn.go @@ -1,13 +1,13 @@ -package bytepluscdn +package bytepluscdn import ( "context" "errors" + "fmt" "log/slog" "strings" bpcdn "github.com/byteplus-sdk/byteplus-sdk-golang/service/cdn" - xerrors "github.com/pkg/errors" "github.com/usual2970/certimate/internal/pkg/core/deployer" "github.com/usual2970/certimate/internal/pkg/core/uploader" @@ -46,7 +46,7 @@ func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { SecretKey: config.SecretKey, }) if err != nil { - return nil, xerrors.Wrap(err, "failed to create ssl uploader") + return nil, fmt.Errorf("failed to create ssl uploader: %w", err) } return &DeployerProvider{ @@ -67,11 +67,11 @@ func (d *DeployerProvider) WithLogger(logger *slog.Logger) deployer.Deployer { return d } -func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { +func (d *DeployerProvider) Deploy(ctx context.Context, certPEM string, privkeyPEM string) (*deployer.DeployResult, error) { // 上传证书到 CDN - upres, err := d.sslUploader.Upload(ctx, certPem, privkeyPem) + upres, err := d.sslUploader.Upload(ctx, certPEM, privkeyPEM) if err != nil { - return nil, xerrors.Wrap(err, "failed to upload certificate file") + return nil, fmt.Errorf("failed to upload certificate file: %w", err) } else { d.logger.Info("ssl certificate uploaded", slog.Any("result", upres)) } @@ -86,7 +86,7 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPe describeCertConfigResp, err := d.sdkClient.DescribeCertConfig(describeCertConfigReq) d.logger.Debug("sdk request 'cdn.DescribeCertConfig'", slog.Any("request", describeCertConfigReq), slog.Any("response", describeCertConfigResp)) if err != nil { - return nil, xerrors.Wrap(err, "failed to execute sdk request 'cdn.DescribeCertConfig'") + return nil, fmt.Errorf("failed to execute sdk request 'cdn.DescribeCertConfig': %w", err) } if describeCertConfigResp.Result.CertNotConfig != nil { @@ -117,16 +117,22 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPe var errs []error for _, domain := range domains { - // 关联证书与加速域名 - // REF: https://docs.byteplus.com/en/docs/byteplus-cdn/reference-batchdeploycert - batchDeployCertReq := &bpcdn.BatchDeployCertRequest{ - CertId: upres.CertId, - Domain: domain, - } - batchDeployCertResp, err := d.sdkClient.BatchDeployCert(batchDeployCertReq) - d.logger.Debug("sdk request 'cdn.BatchDeployCert'", slog.Any("request", batchDeployCertReq), slog.Any("response", batchDeployCertResp)) - if err != nil { - errs = append(errs, err) + select { + case <-ctx.Done(): + return nil, ctx.Err() + + default: + // 关联证书与加速域名 + // REF: https://docs.byteplus.com/en/docs/byteplus-cdn/reference-batchdeploycert + batchDeployCertReq := &bpcdn.BatchDeployCertRequest{ + CertId: upres.CertId, + Domain: domain, + } + batchDeployCertResp, err := d.sdkClient.BatchDeployCert(batchDeployCertReq) + d.logger.Debug("sdk request 'cdn.BatchDeployCert'", slog.Any("request", batchDeployCertReq), slog.Any("response", batchDeployCertResp)) + if err != nil { + errs = append(errs, err) + } } } 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 ee09e8ee..34e657cb 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 @@ -1,4 +1,4 @@ -package bytepluscdn_test +package bytepluscdn_test import ( "context" diff --git a/internal/pkg/core/deployer/providers/cachefly/cachefly.go b/internal/pkg/core/deployer/providers/cachefly/cachefly.go index 63bb4e95..e3e819d7 100644 --- a/internal/pkg/core/deployer/providers/cachefly/cachefly.go +++ b/internal/pkg/core/deployer/providers/cachefly/cachefly.go @@ -1,14 +1,13 @@ -package cachefly +package cachefly import ( "context" "errors" + "fmt" "log/slog" - xerrors "github.com/pkg/errors" - "github.com/usual2970/certimate/internal/pkg/core/deployer" - cfsdk "github.com/usual2970/certimate/internal/pkg/vendors/cachefly-sdk" + cfsdk "github.com/usual2970/certimate/internal/pkg/sdk3rd/cachefly" ) type DeployerConfig struct { @@ -31,7 +30,7 @@ func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { client, err := createSdkClient(config.ApiToken) if err != nil { - return nil, xerrors.Wrap(err, "failed to create sdk client") + return nil, fmt.Errorf("failed to create sdk client: %w", err) } return &DeployerProvider{ @@ -50,16 +49,16 @@ func (d *DeployerProvider) WithLogger(logger *slog.Logger) deployer.Deployer { return d } -func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { +func (d *DeployerProvider) Deploy(ctx context.Context, certPEM string, privkeyPEM string) (*deployer.DeployResult, error) { // 上传证书 createCertificateReq := &cfsdk.CreateCertificateRequest{ - Certificate: certPem, - CertificateKey: privkeyPem, + Certificate: certPEM, + CertificateKey: privkeyPEM, } createCertificateResp, err := d.sdkClient.CreateCertificate(createCertificateReq) d.logger.Debug("sdk request 'cachefly.CreateCertificate'", slog.Any("request", createCertificateReq), slog.Any("response", createCertificateResp)) if err != nil { - return nil, xerrors.Wrap(err, "failed to execute sdk request 'cachefly.CreateCertificate'") + return nil, fmt.Errorf("failed to execute sdk request 'cachefly.CreateCertificate': %w", err) } return &deployer.DeployResult{}, nil diff --git a/internal/pkg/core/deployer/providers/cachefly/cachefly_test.go b/internal/pkg/core/deployer/providers/cachefly/cachefly_test.go index 1de6047e..802d8b49 100644 --- a/internal/pkg/core/deployer/providers/cachefly/cachefly_test.go +++ b/internal/pkg/core/deployer/providers/cachefly/cachefly_test.go @@ -1,4 +1,4 @@ -package cachefly_test +package cachefly_test import ( "context" diff --git a/internal/pkg/core/deployer/providers/cdnfly/cdnfly.go b/internal/pkg/core/deployer/providers/cdnfly/cdnfly.go index ec2c1883..909caf3e 100644 --- a/internal/pkg/core/deployer/providers/cdnfly/cdnfly.go +++ b/internal/pkg/core/deployer/providers/cdnfly/cdnfly.go @@ -1,7 +1,8 @@ -package cdnfly +package cdnfly import ( "context" + "crypto/tls" "encoding/json" "errors" "fmt" @@ -9,10 +10,8 @@ import ( "net/url" "time" - xerrors "github.com/pkg/errors" - "github.com/usual2970/certimate/internal/pkg/core/deployer" - cfsdk "github.com/usual2970/certimate/internal/pkg/vendors/cdnfly-sdk" + cfsdk "github.com/usual2970/certimate/internal/pkg/sdk3rd/cdnfly" ) type DeployerConfig struct { @@ -22,6 +21,8 @@ type DeployerConfig struct { ApiKey string `json:"apiKey"` // Cdnfly 用户端 API Secret。 ApiSecret string `json:"apiSecret"` + // 是否允许不安全的连接。 + AllowInsecureConnections bool `json:"allowInsecureConnections,omitempty"` // 部署资源类型。 ResourceType ResourceType `json:"resourceType"` // 网站 ID。 @@ -45,9 +46,9 @@ func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { panic("config is nil") } - client, err := createSdkClient(config.ApiUrl, config.ApiKey, config.ApiSecret) + client, err := createSdkClient(config.ApiUrl, config.ApiKey, config.ApiSecret, config.AllowInsecureConnections) if err != nil { - return nil, xerrors.Wrap(err, "failed to create sdk client") + return nil, fmt.Errorf("failed to create sdk client: %w", err) } return &DeployerProvider{ @@ -66,27 +67,27 @@ func (d *DeployerProvider) WithLogger(logger *slog.Logger) deployer.Deployer { return d } -func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { +func (d *DeployerProvider) Deploy(ctx context.Context, certPEM string, privkeyPEM string) (*deployer.DeployResult, error) { // 根据部署资源类型决定部署方式 switch d.config.ResourceType { case RESOURCE_TYPE_SITE: - if err := d.deployToSite(ctx, certPem, privkeyPem); err != nil { + if err := d.deployToSite(ctx, certPEM, privkeyPEM); err != nil { return nil, err } case RESOURCE_TYPE_CERTIFICATE: - if err := d.deployToCertificate(ctx, certPem, privkeyPem); err != nil { + if err := d.deployToCertificate(ctx, certPEM, privkeyPEM); err != nil { return nil, err } default: - return nil, fmt.Errorf("unsupported resource type: %s", d.config.ResourceType) + return nil, fmt.Errorf("unsupported resource type '%s'", d.config.ResourceType) } return &deployer.DeployResult{}, nil } -func (d *DeployerProvider) deployToSite(ctx context.Context, certPem string, privkeyPem string) error { +func (d *DeployerProvider) deployToSite(ctx context.Context, certPEM string, privkeyPEM string) error { if d.config.SiteId == "" { return errors.New("config `siteId` is required") } @@ -99,7 +100,7 @@ func (d *DeployerProvider) deployToSite(ctx context.Context, certPem string, pri getSiteResp, err := d.sdkClient.GetSite(getSiteReq) d.logger.Debug("sdk request 'cdnfly.GetSite'", slog.Any("request", getSiteReq), slog.Any("response", getSiteResp)) if err != nil { - return xerrors.Wrap(err, "failed to execute sdk request 'cdnfly.GetSite'") + return fmt.Errorf("failed to execute sdk request 'cdnfly.GetSite': %w", err) } // 添加单个证书 @@ -107,13 +108,13 @@ func (d *DeployerProvider) deployToSite(ctx context.Context, certPem string, pri createCertificateReq := &cfsdk.CreateCertificateRequest{ Name: fmt.Sprintf("certimate-%d", time.Now().UnixMilli()), Type: "custom", - Cert: certPem, - Key: privkeyPem, + Cert: certPEM, + Key: privkeyPEM, } createCertificateResp, err := d.sdkClient.CreateCertificate(createCertificateReq) d.logger.Debug("sdk request 'cdnfly.CreateCertificate'", slog.Any("request", createCertificateReq), slog.Any("response", createCertificateResp)) if err != nil { - return xerrors.Wrap(err, "failed to execute sdk request 'cdnfly.CreateCertificate'") + return fmt.Errorf("failed to execute sdk request 'cdnfly.CreateCertificate': %w", err) } // 修改单个网站 @@ -130,13 +131,13 @@ func (d *DeployerProvider) deployToSite(ctx context.Context, certPem string, pri updateSiteResp, err := d.sdkClient.UpdateSite(updateSiteReq) d.logger.Debug("sdk request 'cdnfly.UpdateSite'", slog.Any("request", updateSiteReq), slog.Any("response", updateSiteResp)) if err != nil { - return xerrors.Wrap(err, "failed to execute sdk request 'cdnfly.UpdateSite'") + return fmt.Errorf("failed to execute sdk request 'cdnfly.UpdateSite': %w", err) } return nil } -func (d *DeployerProvider) deployToCertificate(ctx context.Context, certPem string, privkeyPem string) error { +func (d *DeployerProvider) deployToCertificate(ctx context.Context, certPEM string, privkeyPEM string) error { if d.config.CertificateId == "" { return errors.New("config `certificateId` is required") } @@ -147,19 +148,19 @@ func (d *DeployerProvider) deployToCertificate(ctx context.Context, certPem stri updateCertificateReq := &cfsdk.UpdateCertificateRequest{ Id: d.config.CertificateId, Type: &updateCertificateType, - Cert: &certPem, - Key: &privkeyPem, + Cert: &certPEM, + Key: &privkeyPEM, } updateCertificateResp, err := d.sdkClient.UpdateCertificate(updateCertificateReq) d.logger.Debug("sdk request 'cdnfly.UpdateCertificate'", slog.Any("request", updateCertificateReq), slog.Any("response", updateCertificateResp)) if err != nil { - return xerrors.Wrap(err, "failed to execute sdk request 'cdnfly.UpdateCertificate'") + return fmt.Errorf("failed to execute sdk request 'cdnfly.UpdateCertificate': %w", err) } return nil } -func createSdkClient(apiUrl, apiKey, apiSecret string) (*cfsdk.Client, error) { +func createSdkClient(apiUrl, apiKey, apiSecret string, skipTlsVerify bool) (*cfsdk.Client, error) { if _, err := url.Parse(apiUrl); err != nil { return nil, errors.New("invalid cachefly api url") } @@ -173,5 +174,9 @@ func createSdkClient(apiUrl, apiKey, apiSecret string) (*cfsdk.Client, error) { } client := cfsdk.NewClient(apiUrl, apiKey, apiSecret) + if skipTlsVerify { + client.WithTLSConfig(&tls.Config{InsecureSkipVerify: true}) + } + return client, nil } diff --git a/internal/pkg/core/deployer/providers/cdnfly/cdnfly_test.go b/internal/pkg/core/deployer/providers/cdnfly/cdnfly_test.go index fd17df9c..26486721 100644 --- a/internal/pkg/core/deployer/providers/cdnfly/cdnfly_test.go +++ b/internal/pkg/core/deployer/providers/cdnfly/cdnfly_test.go @@ -1,4 +1,4 @@ -package cdnfly_test +package cdnfly_test import ( "context" @@ -57,11 +57,12 @@ func TestDeploy(t *testing.T) { }, "\n")) deployer, err := provider.NewDeployer(&provider.DeployerConfig{ - ApiUrl: fApiUrl, - ApiKey: fApiKey, - ApiSecret: fApiSecret, - ResourceType: provider.RESOURCE_TYPE_CERTIFICATE, - CertificateId: fCertificateId, + ApiUrl: fApiUrl, + ApiKey: fApiKey, + ApiSecret: fApiSecret, + AllowInsecureConnections: true, + ResourceType: provider.RESOURCE_TYPE_CERTIFICATE, + CertificateId: fCertificateId, }) if err != nil { t.Errorf("err: %+v", err) diff --git a/internal/pkg/core/deployer/providers/cdnfly/consts.go b/internal/pkg/core/deployer/providers/cdnfly/consts.go index 3f6c6db0..07d896b8 100644 --- a/internal/pkg/core/deployer/providers/cdnfly/consts.go +++ b/internal/pkg/core/deployer/providers/cdnfly/consts.go @@ -1,4 +1,4 @@ -package cdnfly +package cdnfly type ResourceType string diff --git a/internal/pkg/core/deployer/providers/dogecloud-cdn/dogecloud_cdn.go b/internal/pkg/core/deployer/providers/dogecloud-cdn/dogecloud_cdn.go index 94368998..efcf4b7c 100644 --- a/internal/pkg/core/deployer/providers/dogecloud-cdn/dogecloud_cdn.go +++ b/internal/pkg/core/deployer/providers/dogecloud-cdn/dogecloud_cdn.go @@ -1,16 +1,15 @@ -package dogecloudcdn +package dogecloudcdn import ( "context" + "fmt" "log/slog" "strconv" - xerrors "github.com/pkg/errors" - "github.com/usual2970/certimate/internal/pkg/core/deployer" "github.com/usual2970/certimate/internal/pkg/core/uploader" uploadersp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/dogecloud" - dogesdk "github.com/usual2970/certimate/internal/pkg/vendors/dogecloud-sdk" + dogesdk "github.com/usual2970/certimate/internal/pkg/sdk3rd/dogecloud" ) type DeployerConfig struct { @@ -43,7 +42,7 @@ func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { SecretKey: config.SecretKey, }) if err != nil { - return nil, xerrors.Wrap(err, "failed to create ssl uploader") + return nil, fmt.Errorf("failed to create ssl uploader: %w", err) } return &DeployerProvider{ @@ -64,11 +63,11 @@ func (d *DeployerProvider) WithLogger(logger *slog.Logger) deployer.Deployer { return d } -func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { +func (d *DeployerProvider) Deploy(ctx context.Context, certPEM string, privkeyPEM string) (*deployer.DeployResult, error) { // 上传证书到 CDN - upres, err := d.sslUploader.Upload(ctx, certPem, privkeyPem) + upres, err := d.sslUploader.Upload(ctx, certPEM, privkeyPEM) if err != nil { - return nil, xerrors.Wrap(err, "failed to upload certificate file") + return nil, fmt.Errorf("failed to upload certificate file: %w", err) } else { d.logger.Info("ssl certificate uploaded", slog.Any("result", upres)) } @@ -79,7 +78,7 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPe bindCdnCertResp, err := d.sdkClient.BindCdnCertWithDomain(bindCdnCertId, d.config.Domain) d.logger.Debug("sdk request 'cdn.BindCdnCert'", slog.Int64("request.certId", bindCdnCertId), slog.String("request.domain", d.config.Domain), slog.Any("response", bindCdnCertResp)) if err != nil { - return nil, xerrors.Wrap(err, "failed to execute sdk request 'cdn.BindCdnCert'") + return nil, fmt.Errorf("failed to execute sdk request 'cdn.BindCdnCert': %w", err) } return &deployer.DeployResult{}, nil 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 f9c1e7c9..b2484b0b 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 @@ -1,4 +1,4 @@ -package dogecloudcdn_test +package dogecloudcdn_test import ( "context" diff --git a/internal/pkg/core/deployer/providers/edgio-applications/edgio_applications.go b/internal/pkg/core/deployer/providers/edgio-applications/edgio_applications.go index 8dea5555..3dd202a3 100644 --- a/internal/pkg/core/deployer/providers/edgio-applications/edgio_applications.go +++ b/internal/pkg/core/deployer/providers/edgio-applications/edgio_applications.go @@ -1,15 +1,15 @@ -package edgioapplications +package edgioapplications import ( "context" + "fmt" "log/slog" edgio "github.com/Edgio/edgio-api/applications/v7" edgiodtos "github.com/Edgio/edgio-api/applications/v7/dtos" - xerrors "github.com/pkg/errors" "github.com/usual2970/certimate/internal/pkg/core/deployer" - "github.com/usual2970/certimate/internal/pkg/utils/certutil" + certutil "github.com/usual2970/certimate/internal/pkg/utils/cert" ) type DeployerConfig struct { @@ -36,7 +36,7 @@ func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { client, err := createSdkClient(config.ClientId, config.ClientSecret) if err != nil { - return nil, xerrors.Wrap(err, "failed to create sdk client") + return nil, fmt.Errorf("failed to create sdk client: %w", err) } return &DeployerProvider{ @@ -55,9 +55,9 @@ func (d *DeployerProvider) WithLogger(logger *slog.Logger) deployer.Deployer { return d } -func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { +func (d *DeployerProvider) Deploy(ctx context.Context, certPEM string, privkeyPEM string) (*deployer.DeployResult, error) { // 提取 Edgio 所需的服务端证书和中间证书内容 - privateCertPem, intermediateCertPem, err := certutil.ExtractCertificatesFromPEM(certPem) + privateCertPEM, intermediateCertPEM, err := certutil.ExtractCertificatesFromPEM(certPEM) if err != nil { return nil, err } @@ -66,14 +66,14 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPe // REF: https://docs.edg.io/rest_api/#tag/tls-certs/operation/postConfigV01TlsCerts uploadTlsCertReq := edgiodtos.UploadTlsCertRequest{ EnvironmentID: d.config.EnvironmentId, - PrimaryCert: privateCertPem, - IntermediateCert: intermediateCertPem, - PrivateKey: privkeyPem, + PrimaryCert: privateCertPEM, + IntermediateCert: intermediateCertPEM, + PrivateKey: privkeyPEM, } uploadTlsCertResp, err := d.sdkClient.UploadTlsCert(uploadTlsCertReq) d.logger.Debug("sdk request 'edgio.UploadTlsCert'", slog.Any("request", uploadTlsCertReq), slog.Any("response", uploadTlsCertResp)) if err != nil { - return nil, xerrors.Wrap(err, "failed to execute sdk request 'edgio.UploadTlsCert'") + return nil, fmt.Errorf("failed to execute sdk request 'edgio.UploadTlsCert': %w", err) } return &deployer.DeployResult{}, nil diff --git a/internal/pkg/core/deployer/providers/edgio-applications/edgio_applications_test.go b/internal/pkg/core/deployer/providers/edgio-applications/edgio_applications_test.go index bd05b16c..23f9c56e 100644 --- a/internal/pkg/core/deployer/providers/edgio-applications/edgio_applications_test.go +++ b/internal/pkg/core/deployer/providers/edgio-applications/edgio_applications_test.go @@ -1,4 +1,4 @@ -package edgioapplications_test +package edgioapplications_test import ( "context" diff --git a/internal/pkg/core/deployer/providers/gcore-cdn/gcore_cdn.go b/internal/pkg/core/deployer/providers/gcore-cdn/gcore_cdn.go index c0a9e5ba..2f36c35a 100644 --- a/internal/pkg/core/deployer/providers/gcore-cdn/gcore_cdn.go +++ b/internal/pkg/core/deployer/providers/gcore-cdn/gcore_cdn.go @@ -1,19 +1,19 @@ -package gcorecdn +package gcorecdn import ( "context" "errors" + "fmt" "log/slog" "strconv" gprovider "github.com/G-Core/gcorelabscdn-go/gcore/provider" gresources "github.com/G-Core/gcorelabscdn-go/resources" - xerrors "github.com/pkg/errors" "github.com/usual2970/certimate/internal/pkg/core/deployer" "github.com/usual2970/certimate/internal/pkg/core/uploader" uploadersp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/gcore-cdn" - gcoresdk "github.com/usual2970/certimate/internal/pkg/vendors/gcore-sdk/common" + gcoresdk "github.com/usual2970/certimate/internal/pkg/sdk3rd/gcore/common" ) type DeployerConfig struct { @@ -39,14 +39,14 @@ func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { client, err := createSdkClient(config.ApiToken) if err != nil { - return nil, xerrors.Wrap(err, "failed to create sdk client") + return nil, fmt.Errorf("failed to create sdk client: %w", err) } uploader, err := uploadersp.NewUploader(&uploadersp.UploaderConfig{ ApiToken: config.ApiToken, }) if err != nil { - return nil, xerrors.Wrap(err, "failed to create ssl uploader") + return nil, fmt.Errorf("failed to create ssl uploader: %w", err) } return &DeployerProvider{ @@ -67,15 +67,15 @@ func (d *DeployerProvider) WithLogger(logger *slog.Logger) deployer.Deployer { return d } -func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { +func (d *DeployerProvider) Deploy(ctx context.Context, certPEM string, privkeyPEM string) (*deployer.DeployResult, error) { if d.config.ResourceId == 0 { return nil, errors.New("config `resourceId` is required") } // 上传证书到 CDN - upres, err := d.sslUploader.Upload(ctx, certPem, privkeyPem) + upres, err := d.sslUploader.Upload(ctx, certPEM, privkeyPEM) if err != nil { - return nil, xerrors.Wrap(err, "failed to upload certificate file") + return nil, fmt.Errorf("failed to upload certificate file: %w", err) } else { d.logger.Info("ssl certificate uploaded", slog.Any("result", upres)) } @@ -85,7 +85,7 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPe getResourceResp, err := d.sdkClient.Get(context.TODO(), d.config.ResourceId) d.logger.Debug("sdk request 'resources.Get'", slog.Any("resourceId", d.config.ResourceId), slog.Any("response", getResourceResp)) if err != nil { - return nil, xerrors.Wrap(err, "failed to execute sdk request 'resources.Get'") + return nil, fmt.Errorf("failed to execute sdk request 'resources.Get': %w", err) } // 更新 CDN 资源详情 @@ -113,7 +113,7 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPe updateResourceResp, err := d.sdkClient.Update(context.TODO(), d.config.ResourceId, updateResourceReq) d.logger.Debug("sdk request 'resources.Update'", slog.Int64("resourceId", d.config.ResourceId), slog.Any("request", updateResourceReq), slog.Any("response", updateResourceResp)) if err != nil { - return nil, xerrors.Wrap(err, "failed to execute sdk request 'resources.Update'") + return nil, fmt.Errorf("failed to execute sdk request 'resources.Update': %w", err) } return &deployer.DeployResult{}, nil diff --git a/internal/pkg/core/deployer/providers/gcore-cdn/gcore_cdn_test.go b/internal/pkg/core/deployer/providers/gcore-cdn/gcore_cdn_test.go index 34d4a9d6..808d724d 100644 --- a/internal/pkg/core/deployer/providers/gcore-cdn/gcore_cdn_test.go +++ b/internal/pkg/core/deployer/providers/gcore-cdn/gcore_cdn_test.go @@ -1,4 +1,4 @@ -package gcorecdn_test +package gcorecdn_test import ( "context" diff --git a/internal/pkg/core/deployer/providers/goedge/consts.go b/internal/pkg/core/deployer/providers/goedge/consts.go new file mode 100644 index 00000000..91eaa9a3 --- /dev/null +++ b/internal/pkg/core/deployer/providers/goedge/consts.go @@ -0,0 +1,8 @@ +package goedge + +type ResourceType string + +const ( + // 资源类型:替换指定证书。 + RESOURCE_TYPE_CERTIFICATE = ResourceType("certificate") +) diff --git a/internal/pkg/core/deployer/providers/goedge/goedge.go b/internal/pkg/core/deployer/providers/goedge/goedge.go new file mode 100644 index 00000000..61153b1b --- /dev/null +++ b/internal/pkg/core/deployer/providers/goedge/goedge.go @@ -0,0 +1,138 @@ +package goedge + +import ( + "context" + "crypto/tls" + "encoding/base64" + "errors" + "fmt" + "log/slog" + "net/url" + "time" + + "github.com/usual2970/certimate/internal/pkg/core/deployer" + goedgesdk "github.com/usual2970/certimate/internal/pkg/sdk3rd/goedge" + certutil "github.com/usual2970/certimate/internal/pkg/utils/cert" +) + +type DeployerConfig struct { + // GoEdge URL。 + ApiUrl string `json:"apiUrl"` + // GoEdge 用户 AccessKeyId。 + AccessKeyId string `json:"accessKeyId"` + // GoEdge 用户 AccessKey。 + AccessKey string `json:"accessKey"` + // 是否允许不安全的连接。 + AllowInsecureConnections bool `json:"allowInsecureConnections,omitempty"` + // 部署资源类型。 + ResourceType ResourceType `json:"resourceType"` + // 证书 ID。 + // 部署资源类型为 [RESOURCE_TYPE_CERTIFICATE] 时必填。 + CertificateId int64 `json:"certificateId,omitempty"` +} + +type DeployerProvider struct { + config *DeployerConfig + logger *slog.Logger + sdkClient *goedgesdk.Client +} + +var _ deployer.Deployer = (*DeployerProvider)(nil) + +func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { + if config == nil { + panic("config is nil") + } + + client, err := createSdkClient(config.ApiUrl, config.AccessKeyId, config.AccessKey, config.AllowInsecureConnections) + if err != nil { + return nil, fmt.Errorf("failed to create sdk client: %w", err) + } + + return &DeployerProvider{ + config: config, + logger: slog.Default(), + sdkClient: client, + }, nil +} + +func (d *DeployerProvider) WithLogger(logger *slog.Logger) deployer.Deployer { + if logger == nil { + d.logger = slog.Default() + } else { + d.logger = logger + } + return d +} + +func (d *DeployerProvider) Deploy(ctx context.Context, certPEM string, privkeyPEM string) (*deployer.DeployResult, error) { + // 根据部署资源类型决定部署方式 + switch d.config.ResourceType { + case RESOURCE_TYPE_CERTIFICATE: + if err := d.deployToCertificate(ctx, certPEM, privkeyPEM); err != nil { + return nil, err + } + + default: + return nil, fmt.Errorf("unsupported resource type '%s'", d.config.ResourceType) + } + + return &deployer.DeployResult{}, nil +} + +func (d *DeployerProvider) deployToCertificate(ctx context.Context, certPEM string, privkeyPEM string) error { + if d.config.CertificateId == 0 { + return errors.New("config `certificateId` is required") + } + + // 解析证书内容 + certX509, err := certutil.ParseCertificateFromPEM(certPEM) + if err != nil { + return err + } + + // 修改证书 + // REF: https://goedge.cloud/dev/api/service/SSLCertService?role=user#updateSSLCert + updateSSLCertReq := &goedgesdk.UpdateSSLCertRequest{ + SSLCertId: d.config.CertificateId, + IsOn: true, + Name: fmt.Sprintf("certimate-%d", time.Now().UnixMilli()), + Description: "upload from certimate", + ServerName: certX509.Subject.CommonName, + IsCA: false, + CertData: base64.StdEncoding.EncodeToString([]byte(certPEM)), + KeyData: base64.StdEncoding.EncodeToString([]byte(privkeyPEM)), + TimeBeginAt: certX509.NotBefore.Unix(), + TimeEndAt: certX509.NotAfter.Unix(), + DNSNames: certX509.DNSNames, + CommonNames: []string{certX509.Subject.CommonName}, + } + updateSSLCertResp, err := d.sdkClient.UpdateSSLCert(updateSSLCertReq) + d.logger.Debug("sdk request 'goedge.UpdateSSLCert'", slog.Any("request", updateSSLCertReq), slog.Any("response", updateSSLCertResp)) + if err != nil { + return fmt.Errorf("failed to execute sdk request 'goedge.UpdateSSLCert': %w", err) + } + + return nil +} + +func createSdkClient(apiUrl, accessKeyId, accessKey string, skipTlsVerify bool) (*goedgesdk.Client, error) { + if _, err := url.Parse(apiUrl); err != nil { + return nil, errors.New("invalid goedge api url") + } + + if accessKeyId == "" { + return nil, errors.New("invalid goedge access key id") + } + + if accessKey == "" { + return nil, errors.New("invalid goedge access key") + } + + client := goedgesdk.NewClient(apiUrl, "user", accessKeyId, accessKey) + if skipTlsVerify { + client.WithTLSConfig(&tls.Config{InsecureSkipVerify: true}) + } + + return client, nil +} diff --git a/internal/pkg/core/deployer/providers/goedge/goedge_test.go b/internal/pkg/core/deployer/providers/goedge/goedge_test.go new file mode 100644 index 00000000..c8c32b37 --- /dev/null +++ b/internal/pkg/core/deployer/providers/goedge/goedge_test.go @@ -0,0 +1,82 @@ +package goedge_test + +import ( + "context" + "flag" + "fmt" + "os" + "strings" + "testing" + + provider "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/goedge" +) + +var ( + fInputCertPath string + fInputKeyPath string + fApiUrl string + fAccessKeyId string + fAccessKey string + fCertificateId int +) + +func init() { + argsPrefix := "CERTIMATE_DEPLOYER_GOEDGE_" + + flag.StringVar(&fInputCertPath, argsPrefix+"INPUTCERTPATH", "", "") + flag.StringVar(&fInputKeyPath, argsPrefix+"INPUTKEYPATH", "", "") + flag.StringVar(&fApiUrl, argsPrefix+"APIURL", "", "") + flag.StringVar(&fAccessKeyId, argsPrefix+"ACCESSKEYID", "", "") + flag.StringVar(&fAccessKey, argsPrefix+"ACCESSKEY", "", "") + flag.IntVar(&fCertificateId, argsPrefix+"CERTIFICATEID", 0, "") +} + +/* +Shell command to run this test: + + go test -v ./goedge_test.go -args \ + --CERTIMATE_DEPLOYER_GOEDGE_INPUTCERTPATH="/path/to/your-input-cert.pem" \ + --CERTIMATE_DEPLOYER_GOEDGE_INPUTKEYPATH="/path/to/your-input-key.pem" \ + --CERTIMATE_DEPLOYER_GOEDGE_APIURL="http://127.0.0.1:7788" \ + --CERTIMATE_DEPLOYER_GOEDGE_ACCESSKEYID="your-access-key-id" \ + --CERTIMATE_DEPLOYER_GOEDGE_ACCESSKEY="your-access-key" \ + --CERTIMATE_DEPLOYER_GOEDGE_CERTIFICATEID="your-cerficiate-id" +*/ +func TestDeploy(t *testing.T) { + flag.Parse() + + t.Run("Deploy", func(t *testing.T) { + t.Log(strings.Join([]string{ + "args:", + fmt.Sprintf("INPUTCERTPATH: %v", fInputCertPath), + fmt.Sprintf("INPUTKEYPATH: %v", fInputKeyPath), + fmt.Sprintf("APIURL: %v", fApiUrl), + fmt.Sprintf("ACCESSKEYID: %v", fAccessKeyId), + fmt.Sprintf("ACCESSKEY: %v", fAccessKey), + fmt.Sprintf("CERTIFICATEID: %v", fCertificateId), + }, "\n")) + + deployer, err := provider.NewDeployer(&provider.DeployerConfig{ + ApiUrl: fApiUrl, + AccessKeyId: fAccessKeyId, + AccessKey: fAccessKey, + AllowInsecureConnections: true, + ResourceType: provider.RESOURCE_TYPE_CERTIFICATE, + CertificateId: int64(fCertificateId), + }) + if err != nil { + t.Errorf("err: %+v", err) + return + } + + fInputCertData, _ := os.ReadFile(fInputCertPath) + fInputKeyData, _ := os.ReadFile(fInputKeyPath) + res, err := deployer.Deploy(context.Background(), string(fInputCertData), string(fInputKeyData)) + if err != nil { + t.Errorf("err: %+v", err) + return + } + + t.Logf("ok: %v", res) + }) +} diff --git a/internal/pkg/core/deployer/providers/huaweicloud-cdn/huaweicloud_cdn.go b/internal/pkg/core/deployer/providers/huaweicloud-cdn/huaweicloud_cdn.go index 048ccbd2..d33dafff 100644 --- a/internal/pkg/core/deployer/providers/huaweicloud-cdn/huaweicloud_cdn.go +++ b/internal/pkg/core/deployer/providers/huaweicloud-cdn/huaweicloud_cdn.go @@ -1,19 +1,19 @@ -package huaweicloudcdn +package huaweicloudcdn import ( "context" + "fmt" "log/slog" "github.com/huaweicloud/huaweicloud-sdk-go-v3/core/auth/global" hccdn "github.com/huaweicloud/huaweicloud-sdk-go-v3/services/cdn/v2" hccdnmodel "github.com/huaweicloud/huaweicloud-sdk-go-v3/services/cdn/v2/model" hccdnregion "github.com/huaweicloud/huaweicloud-sdk-go-v3/services/cdn/v2/region" - xerrors "github.com/pkg/errors" "github.com/usual2970/certimate/internal/pkg/core/deployer" "github.com/usual2970/certimate/internal/pkg/core/uploader" uploadersp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/huaweicloud-scm" - hwsdk "github.com/usual2970/certimate/internal/pkg/vendors/huaweicloud-sdk" + typeutil "github.com/usual2970/certimate/internal/pkg/utils/type" ) type DeployerConfig struct { @@ -47,7 +47,7 @@ func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { config.Region, ) if err != nil { - return nil, xerrors.Wrap(err, "failed to create sdk client") + return nil, fmt.Errorf("failed to create sdk client: %w", err) } uploader, err := uploadersp.NewUploader(&uploadersp.UploaderConfig{ @@ -55,7 +55,7 @@ func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { SecretAccessKey: config.SecretAccessKey, }) if err != nil { - return nil, xerrors.Wrap(err, "failed to create ssl uploader") + return nil, fmt.Errorf("failed to create ssl uploader: %w", err) } return &DeployerProvider{ @@ -76,11 +76,11 @@ func (d *DeployerProvider) WithLogger(logger *slog.Logger) deployer.Deployer { return d } -func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { +func (d *DeployerProvider) Deploy(ctx context.Context, certPEM string, privkeyPEM string) (*deployer.DeployResult, error) { // 上传证书到 SCM - upres, err := d.sslUploader.Upload(ctx, certPem, privkeyPem) + upres, err := d.sslUploader.Upload(ctx, certPEM, privkeyPEM) if err != nil { - return nil, xerrors.Wrap(err, "failed to upload certificate file") + return nil, fmt.Errorf("failed to upload certificate file: %w", err) } else { d.logger.Info("ssl certificate uploaded", slog.Any("result", upres)) } @@ -93,7 +93,7 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPe showDomainFullConfigResp, err := d.sdkClient.ShowDomainFullConfig(showDomainFullConfigReq) d.logger.Debug("sdk request 'cdn.ShowDomainFullConfig'", slog.Any("request", showDomainFullConfigReq), slog.Any("response", showDomainFullConfigResp)) if err != nil { - return nil, xerrors.Wrap(err, "failed to execute sdk request 'cdn.ShowDomainFullConfig'") + return nil, fmt.Errorf("failed to execute sdk request 'cdn.ShowDomainFullConfig': %w", err) } // 更新加速域名配置 @@ -102,9 +102,9 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPe updateDomainMultiCertificatesReqBodyContent := &hccdnmodel.UpdateDomainMultiCertificatesRequestBodyContent{} updateDomainMultiCertificatesReqBodyContent.DomainName = d.config.Domain updateDomainMultiCertificatesReqBodyContent.HttpsSwitch = 1 - updateDomainMultiCertificatesReqBodyContent.CertificateType = hwsdk.Int32Ptr(2) - updateDomainMultiCertificatesReqBodyContent.ScmCertificateId = hwsdk.StringPtr(upres.CertId) - updateDomainMultiCertificatesReqBodyContent.CertName = hwsdk.StringPtr(upres.CertName) + updateDomainMultiCertificatesReqBodyContent.CertificateType = typeutil.ToPtr(int32(2)) + updateDomainMultiCertificatesReqBodyContent.ScmCertificateId = typeutil.ToPtr(upres.CertId) + updateDomainMultiCertificatesReqBodyContent.CertName = typeutil.ToPtr(upres.CertName) updateDomainMultiCertificatesReqBodyContent = assign(updateDomainMultiCertificatesReqBodyContent, showDomainFullConfigResp.Configs) updateDomainMultiCertificatesReq := &hccdnmodel.UpdateDomainMultiCertificatesRequest{ Body: &hccdnmodel.UpdateDomainMultiCertificatesRequestBody{ @@ -114,7 +114,7 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPe updateDomainMultiCertificatesResp, err := d.sdkClient.UpdateDomainMultiCertificates(updateDomainMultiCertificatesReq) d.logger.Debug("sdk request 'cdn.UploadDomainMultiCertificates'", slog.Any("request", updateDomainMultiCertificatesReq), slog.Any("response", updateDomainMultiCertificatesResp)) if err != nil { - return nil, xerrors.Wrap(err, "failed to execute sdk request 'cdn.UploadDomainMultiCertificates'") + return nil, fmt.Errorf("failed to execute sdk request 'cdn.UploadDomainMultiCertificates': %w", err) } return &deployer.DeployResult{}, nil @@ -159,11 +159,11 @@ func assign(source *hccdnmodel.UpdateDomainMultiCertificatesRequestBodyContent, } if *target.OriginProtocol == "follow" { - source.AccessOriginWay = hwsdk.Int32Ptr(1) + source.AccessOriginWay = typeutil.ToPtr(int32(1)) } else if *target.OriginProtocol == "http" { - source.AccessOriginWay = hwsdk.Int32Ptr(2) + source.AccessOriginWay = typeutil.ToPtr(int32(2)) } else if *target.OriginProtocol == "https" { - source.AccessOriginWay = hwsdk.Int32Ptr(3) + source.AccessOriginWay = typeutil.ToPtr(int32(3)) } if target.ForceRedirect != nil { @@ -181,7 +181,7 @@ func assign(source *hccdnmodel.UpdateDomainMultiCertificatesRequestBodyContent, if target.Https != nil { if *target.Https.Http2Status == "on" { - source.Http2 = hwsdk.Int32Ptr(1) + source.Http2 = typeutil.ToPtr(int32(1)) } } 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 aaf8d6c7..cb4ab1a4 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 @@ -1,4 +1,4 @@ -package huaweicloudcdn_test +package huaweicloudcdn_test import ( "context" diff --git a/internal/pkg/core/deployer/providers/huaweicloud-elb/consts.go b/internal/pkg/core/deployer/providers/huaweicloud-elb/consts.go index b097a958..ecd3987d 100644 --- a/internal/pkg/core/deployer/providers/huaweicloud-elb/consts.go +++ b/internal/pkg/core/deployer/providers/huaweicloud-elb/consts.go @@ -1,4 +1,4 @@ -package huaweicloudelb +package huaweicloudelb type ResourceType string diff --git a/internal/pkg/core/deployer/providers/huaweicloud-elb/huaweicloud_elb.go b/internal/pkg/core/deployer/providers/huaweicloud-elb/huaweicloud_elb.go index 904c138f..748111dd 100644 --- a/internal/pkg/core/deployer/providers/huaweicloud-elb/huaweicloud_elb.go +++ b/internal/pkg/core/deployer/providers/huaweicloud-elb/huaweicloud_elb.go @@ -1,4 +1,4 @@ -package huaweicloudelb +package huaweicloudelb import ( "context" @@ -14,13 +14,12 @@ import ( hciam "github.com/huaweicloud/huaweicloud-sdk-go-v3/services/iam/v3" hciammodel "github.com/huaweicloud/huaweicloud-sdk-go-v3/services/iam/v3/model" hciamregion "github.com/huaweicloud/huaweicloud-sdk-go-v3/services/iam/v3/region" - xerrors "github.com/pkg/errors" "golang.org/x/exp/slices" "github.com/usual2970/certimate/internal/pkg/core/deployer" "github.com/usual2970/certimate/internal/pkg/core/uploader" uploadersp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/huaweicloud-elb" - hwsdk "github.com/usual2970/certimate/internal/pkg/vendors/huaweicloud-sdk" + typeutil "github.com/usual2970/certimate/internal/pkg/utils/type" ) type DeployerConfig struct { @@ -59,7 +58,7 @@ func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { client, err := createSdkClient(config.AccessKeyId, config.SecretAccessKey, config.Region) if err != nil { - return nil, xerrors.Wrap(err, "failed to create sdk client") + return nil, fmt.Errorf("failed to create sdk client: %w", err) } uploader, err := uploadersp.NewUploader(&uploadersp.UploaderConfig{ @@ -68,7 +67,7 @@ func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { Region: config.Region, }) if err != nil { - return nil, xerrors.Wrap(err, "failed to create ssl uploader") + return nil, fmt.Errorf("failed to create ssl uploader: %w", err) } return &DeployerProvider{ @@ -89,32 +88,32 @@ func (d *DeployerProvider) WithLogger(logger *slog.Logger) deployer.Deployer { return d } -func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { +func (d *DeployerProvider) Deploy(ctx context.Context, certPEM string, privkeyPEM string) (*deployer.DeployResult, error) { // 根据部署资源类型决定部署方式 switch d.config.ResourceType { case RESOURCE_TYPE_CERTIFICATE: - if err := d.deployToCertificate(ctx, certPem, privkeyPem); err != nil { + if err := d.deployToCertificate(ctx, certPEM, privkeyPEM); err != nil { return nil, err } case RESOURCE_TYPE_LOADBALANCER: - if err := d.deployToLoadbalancer(ctx, certPem, privkeyPem); err != nil { + if err := d.deployToLoadbalancer(ctx, certPEM, privkeyPEM); err != nil { return nil, err } case RESOURCE_TYPE_LISTENER: - if err := d.deployToListener(ctx, certPem, privkeyPem); err != nil { + if err := d.deployToListener(ctx, certPEM, privkeyPEM); err != nil { return nil, err } default: - return nil, fmt.Errorf("unsupported resource type: %s", d.config.ResourceType) + return nil, fmt.Errorf("unsupported resource type '%s'", d.config.ResourceType) } return &deployer.DeployResult{}, nil } -func (d *DeployerProvider) deployToCertificate(ctx context.Context, certPem string, privkeyPem string) error { +func (d *DeployerProvider) deployToCertificate(ctx context.Context, certPEM string, privkeyPEM string) error { if d.config.CertificateId == "" { return errors.New("config `certificateId` is required") } @@ -125,21 +124,21 @@ func (d *DeployerProvider) deployToCertificate(ctx context.Context, certPem stri CertificateId: d.config.CertificateId, Body: &hcelbmodel.UpdateCertificateRequestBody{ Certificate: &hcelbmodel.UpdateCertificateOption{ - Certificate: hwsdk.StringPtr(certPem), - PrivateKey: hwsdk.StringPtr(privkeyPem), + Certificate: typeutil.ToPtr(certPEM), + PrivateKey: typeutil.ToPtr(privkeyPEM), }, }, } updateCertificateResp, err := d.sdkClient.UpdateCertificate(updateCertificateReq) d.logger.Debug("sdk request 'elb.UpdateCertificate'", slog.Any("request", updateCertificateReq), slog.Any("response", updateCertificateResp)) if err != nil { - return xerrors.Wrap(err, "failed to execute sdk request 'elb.UpdateCertificate'") + return fmt.Errorf("failed to execute sdk request 'elb.UpdateCertificate': %w", err) } return nil } -func (d *DeployerProvider) deployToLoadbalancer(ctx context.Context, certPem string, privkeyPem string) error { +func (d *DeployerProvider) deployToLoadbalancer(ctx context.Context, certPEM string, privkeyPEM string) error { if d.config.LoadbalancerId == "" { return errors.New("config `loadbalancerId` is required") } @@ -152,7 +151,7 @@ func (d *DeployerProvider) deployToLoadbalancer(ctx context.Context, certPem str showLoadBalancerResp, err := d.sdkClient.ShowLoadBalancer(showLoadBalancerReq) d.logger.Debug("sdk request 'elb.ShowLoadBalancer'", slog.Any("request", showLoadBalancerReq), slog.Any("response", showLoadBalancerResp)) if err != nil { - return xerrors.Wrap(err, "failed to execute sdk request 'elb.ShowLoadBalancer'") + return fmt.Errorf("failed to execute sdk request 'elb.ShowLoadBalancer': %w", err) } // 查询监听器列表 @@ -161,8 +160,14 @@ func (d *DeployerProvider) deployToLoadbalancer(ctx context.Context, certPem str listListenersLimit := int32(2000) var listListenersMarker *string = nil for { + select { + case <-ctx.Done(): + return ctx.Err() + default: + } + listListenersReq := &hcelbmodel.ListListenersRequest{ - Limit: hwsdk.Int32Ptr(listListenersLimit), + Limit: typeutil.ToPtr(listListenersLimit), Marker: listListenersMarker, Protocol: &[]string{"HTTPS", "TERMINATED_HTTPS"}, LoadbalancerId: &[]string{showLoadBalancerResp.Loadbalancer.Id}, @@ -170,7 +175,7 @@ func (d *DeployerProvider) deployToLoadbalancer(ctx context.Context, certPem str listListenersResp, err := d.sdkClient.ListListeners(listListenersReq) d.logger.Debug("sdk request 'elb.ListListeners'", slog.Any("request", listListenersReq), slog.Any("response", listListenersResp)) if err != nil { - return xerrors.Wrap(err, "failed to execute sdk request 'elb.ListListeners'") + return fmt.Errorf("failed to execute sdk request 'elb.ListListeners': %w", err) } if listListenersResp.Listeners != nil { @@ -187,9 +192,9 @@ func (d *DeployerProvider) deployToLoadbalancer(ctx context.Context, certPem str } // 上传证书到 SCM - upres, err := d.sslUploader.Upload(ctx, certPem, privkeyPem) + upres, err := d.sslUploader.Upload(ctx, certPEM, privkeyPEM) if err != nil { - return xerrors.Wrap(err, "failed to upload certificate file") + return fmt.Errorf("failed to upload certificate file: %w", err) } else { d.logger.Info("ssl certificate uploaded", slog.Any("result", upres)) } @@ -202,8 +207,14 @@ func (d *DeployerProvider) deployToLoadbalancer(ctx context.Context, certPem str var errs []error for _, listenerId := range listenerIds { - if err := d.modifyListenerCertificate(ctx, listenerId, upres.CertId); err != nil { - errs = append(errs, err) + select { + case <-ctx.Done(): + return ctx.Err() + + default: + if err := d.modifyListenerCertificate(ctx, listenerId, upres.CertId); err != nil { + errs = append(errs, err) + } } } @@ -215,15 +226,15 @@ func (d *DeployerProvider) deployToLoadbalancer(ctx context.Context, certPem str return nil } -func (d *DeployerProvider) deployToListener(ctx context.Context, certPem string, privkeyPem string) error { +func (d *DeployerProvider) deployToListener(ctx context.Context, certPEM string, privkeyPEM string) error { if d.config.ListenerId == "" { return errors.New("config `listenerId` is required") } // 上传证书到 SCM - upres, err := d.sslUploader.Upload(ctx, certPem, privkeyPem) + upres, err := d.sslUploader.Upload(ctx, certPEM, privkeyPEM) if err != nil { - return xerrors.Wrap(err, "failed to upload certificate file") + return fmt.Errorf("failed to upload certificate file: %w", err) } else { d.logger.Info("ssl certificate uploaded", slog.Any("result", upres)) } @@ -245,7 +256,7 @@ func (d *DeployerProvider) modifyListenerCertificate(ctx context.Context, cloudL showListenerResp, err := d.sdkClient.ShowListener(showListenerReq) d.logger.Debug("sdk request 'elb.ShowListener'", slog.Any("request", showListenerReq), slog.Any("response", showListenerResp)) if err != nil { - return xerrors.Wrap(err, "failed to execute sdk request 'elb.ShowListener'") + return fmt.Errorf("failed to execute sdk request 'elb.ShowListener': %w", err) } // 更新监听器 @@ -254,7 +265,7 @@ func (d *DeployerProvider) modifyListenerCertificate(ctx context.Context, cloudL ListenerId: cloudListenerId, Body: &hcelbmodel.UpdateListenerRequestBody{ Listener: &hcelbmodel.UpdateListenerOption{ - DefaultTlsContainerRef: hwsdk.StringPtr(cloudCertId), + DefaultTlsContainerRef: typeutil.ToPtr(cloudCertId), }, }, } @@ -270,7 +281,7 @@ func (d *DeployerProvider) modifyListenerCertificate(ctx context.Context, cloudL listOldCertificateResp, err := d.sdkClient.ListCertificates(listOldCertificateReq) d.logger.Debug("sdk request 'elb.ListCertificates'", slog.Any("request", listOldCertificateReq), slog.Any("response", listOldCertificateResp)) if err != nil { - return xerrors.Wrap(err, "failed to execute sdk request 'elb.ListCertificates'") + return fmt.Errorf("failed to execute sdk request 'elb.ListCertificates': %w", err) } showNewCertificateReq := &hcelbmodel.ShowCertificateRequest{ @@ -279,7 +290,7 @@ func (d *DeployerProvider) modifyListenerCertificate(ctx context.Context, cloudL showNewCertificateResp, err := d.sdkClient.ShowCertificate(showNewCertificateReq) d.logger.Debug("sdk request 'elb.ShowCertificate'", slog.Any("request", showNewCertificateReq), slog.Any("response", showNewCertificateResp)) if err != nil { - return xerrors.Wrap(err, "failed to execute sdk request 'elb.ShowCertificate'") + return fmt.Errorf("failed to execute sdk request 'elb.ShowCertificate': %w", err) } for _, certificate := range *listOldCertificateResp.Certificates { @@ -303,13 +314,13 @@ func (d *DeployerProvider) modifyListenerCertificate(ctx context.Context, cloudL } if showListenerResp.Listener.SniMatchAlgo != "" { - updateListenerReq.Body.Listener.SniMatchAlgo = hwsdk.StringPtr(showListenerResp.Listener.SniMatchAlgo) + updateListenerReq.Body.Listener.SniMatchAlgo = typeutil.ToPtr(showListenerResp.Listener.SniMatchAlgo) } } updateListenerResp, err := d.sdkClient.UpdateListener(updateListenerReq) d.logger.Debug("sdk request 'elb.UpdateListener'", slog.Any("request", updateListenerReq), slog.Any("response", updateListenerResp)) if err != nil { - return xerrors.Wrap(err, "failed to execute sdk request 'elb.UpdateListener'") + return fmt.Errorf("failed to execute sdk request 'elb.UpdateListener': %w", err) } return nil 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 4325ba40..42fee652 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 @@ -1,4 +1,4 @@ -package huaweicloudelb_test +package huaweicloudelb_test import ( "context" diff --git a/internal/pkg/core/deployer/providers/huaweicloud-scm/huaweicloud_scm.go b/internal/pkg/core/deployer/providers/huaweicloud-scm/huaweicloud_scm.go index 69b75f2f..c8c208ad 100644 --- a/internal/pkg/core/deployer/providers/huaweicloud-scm/huaweicloud_scm.go +++ b/internal/pkg/core/deployer/providers/huaweicloud-scm/huaweicloud_scm.go @@ -1,11 +1,10 @@ -package huaweicloudscm +package huaweicloudscm import ( "context" + "fmt" "log/slog" - xerrors "github.com/pkg/errors" - "github.com/usual2970/certimate/internal/pkg/core/deployer" "github.com/usual2970/certimate/internal/pkg/core/uploader" uploadersp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/huaweicloud-scm" @@ -36,7 +35,7 @@ func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { SecretAccessKey: config.SecretAccessKey, }) if err != nil { - return nil, xerrors.Wrap(err, "failed to create ssl uploader") + return nil, fmt.Errorf("failed to create ssl uploader: %w", err) } return &DeployerProvider{ @@ -56,11 +55,11 @@ func (d *DeployerProvider) WithLogger(logger *slog.Logger) deployer.Deployer { return d } -func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { +func (d *DeployerProvider) Deploy(ctx context.Context, certPEM string, privkeyPEM string) (*deployer.DeployResult, error) { // 上传证书到 SCM - upres, err := d.sslUploader.Upload(ctx, certPem, privkeyPem) + upres, err := d.sslUploader.Upload(ctx, certPEM, privkeyPEM) if err != nil { - return nil, xerrors.Wrap(err, "failed to upload certificate file") + return nil, fmt.Errorf("failed to upload certificate file: %w", err) } else { d.logger.Info("ssl certificate uploaded", slog.Any("result", upres)) } diff --git a/internal/pkg/core/deployer/providers/huaweicloud-waf/consts.go b/internal/pkg/core/deployer/providers/huaweicloud-waf/consts.go index fc574c32..8f1b59c4 100644 --- a/internal/pkg/core/deployer/providers/huaweicloud-waf/consts.go +++ b/internal/pkg/core/deployer/providers/huaweicloud-waf/consts.go @@ -1,4 +1,4 @@ -package huaweicloudwaf +package huaweicloudwaf type ResourceType string diff --git a/internal/pkg/core/deployer/providers/huaweicloud-waf/huaweicloud_waf.go b/internal/pkg/core/deployer/providers/huaweicloud-waf/huaweicloud_waf.go index 0e29567c..8fe96ee0 100644 --- a/internal/pkg/core/deployer/providers/huaweicloud-waf/huaweicloud_waf.go +++ b/internal/pkg/core/deployer/providers/huaweicloud-waf/huaweicloud_waf.go @@ -1,4 +1,4 @@ -package huaweicloudwaf +package huaweicloudwaf import ( "context" @@ -15,12 +15,11 @@ import ( hcwaf "github.com/huaweicloud/huaweicloud-sdk-go-v3/services/waf/v1" hcwafmodel "github.com/huaweicloud/huaweicloud-sdk-go-v3/services/waf/v1/model" hcwafregion "github.com/huaweicloud/huaweicloud-sdk-go-v3/services/waf/v1/region" - xerrors "github.com/pkg/errors" "github.com/usual2970/certimate/internal/pkg/core/deployer" "github.com/usual2970/certimate/internal/pkg/core/uploader" uploadersp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/huaweicloud-waf" - hwsdk "github.com/usual2970/certimate/internal/pkg/vendors/huaweicloud-sdk" + typeutil "github.com/usual2970/certimate/internal/pkg/utils/type" ) type DeployerConfig struct { @@ -56,7 +55,7 @@ func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { client, err := createSdkClient(config.AccessKeyId, config.SecretAccessKey, config.Region) if err != nil { - return nil, xerrors.Wrap(err, "failed to create sdk client") + return nil, fmt.Errorf("failed to create sdk client: %w", err) } uploader, err := uploadersp.NewUploader(&uploadersp.UploaderConfig{ @@ -65,7 +64,7 @@ func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { Region: config.Region, }) if err != nil { - return nil, xerrors.Wrap(err, "failed to create ssl uploader") + return nil, fmt.Errorf("failed to create ssl uploader: %w", err) } return &DeployerProvider{ @@ -86,11 +85,11 @@ func (d *DeployerProvider) WithLogger(logger *slog.Logger) deployer.Deployer { return d } -func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { +func (d *DeployerProvider) Deploy(ctx context.Context, certPEM string, privkeyPEM string) (*deployer.DeployResult, error) { // 上传证书到 WAF - upres, err := d.sslUploader.Upload(ctx, certPem, privkeyPem) + upres, err := d.sslUploader.Upload(ctx, certPEM, privkeyPEM) if err != nil { - return nil, xerrors.Wrap(err, "failed to upload certificate file") + return nil, fmt.Errorf("failed to upload certificate file: %w", err) } else { d.logger.Info("ssl certificate uploaded", slog.Any("result", upres)) } @@ -98,28 +97,28 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPe // 根据部署资源类型决定部署方式 switch d.config.ResourceType { case RESOURCE_TYPE_CERTIFICATE: - if err := d.deployToCertificate(ctx, certPem, privkeyPem); err != nil { + if err := d.deployToCertificate(ctx, certPEM, privkeyPEM); err != nil { return nil, err } case RESOURCE_TYPE_CLOUDSERVER: - if err := d.deployToCloudServer(ctx, certPem, privkeyPem); err != nil { + if err := d.deployToCloudServer(ctx, certPEM, privkeyPEM); err != nil { return nil, err } case RESOURCE_TYPE_PREMIUMHOST: - if err := d.deployToPremiumHost(ctx, certPem, privkeyPem); err != nil { + if err := d.deployToPremiumHost(ctx, certPEM, privkeyPEM); err != nil { return nil, err } default: - return nil, fmt.Errorf("unsupported resource type: %s", d.config.ResourceType) + return nil, fmt.Errorf("unsupported resource type '%s'", d.config.ResourceType) } return &deployer.DeployResult{}, nil } -func (d *DeployerProvider) deployToCertificate(ctx context.Context, certPem string, privkeyPem string) error { +func (d *DeployerProvider) deployToCertificate(ctx context.Context, certPEM string, privkeyPEM string) error { if d.config.CertificateId == "" { return errors.New("config `certificateId` is required") } @@ -132,7 +131,7 @@ func (d *DeployerProvider) deployToCertificate(ctx context.Context, certPem stri showCertificateResp, err := d.sdkClient.ShowCertificate(showCertificateReq) d.logger.Debug("sdk request 'waf.ShowCertificate'", slog.Any("request", showCertificateReq), slog.Any("response", showCertificateResp)) if err != nil { - return xerrors.Wrap(err, "failed to execute sdk request 'waf.ShowCertificate'") + return fmt.Errorf("failed to execute sdk request 'waf.ShowCertificate': %w", err) } // 更新证书 @@ -141,28 +140,28 @@ func (d *DeployerProvider) deployToCertificate(ctx context.Context, certPem stri CertificateId: d.config.CertificateId, Body: &hcwafmodel.UpdateCertificateRequestBody{ Name: *showCertificateResp.Name, - Content: hwsdk.StringPtr(certPem), - Key: hwsdk.StringPtr(privkeyPem), + Content: typeutil.ToPtr(certPEM), + Key: typeutil.ToPtr(privkeyPEM), }, } updateCertificateResp, err := d.sdkClient.UpdateCertificate(updateCertificateReq) d.logger.Debug("sdk request 'waf.UpdateCertificate'", slog.Any("request", updateCertificateReq), slog.Any("response", updateCertificateResp)) if err != nil { - return xerrors.Wrap(err, "failed to execute sdk request 'waf.UpdateCertificate'") + return fmt.Errorf("failed to execute sdk request 'waf.UpdateCertificate': %w", err) } return nil } -func (d *DeployerProvider) deployToCloudServer(ctx context.Context, certPem string, privkeyPem string) error { +func (d *DeployerProvider) deployToCloudServer(ctx context.Context, certPEM string, privkeyPEM string) error { if d.config.Domain == "" { return errors.New("config `domain` is required") } // 上传证书到 WAF - upres, err := d.sslUploader.Upload(ctx, certPem, privkeyPem) + upres, err := d.sslUploader.Upload(ctx, certPEM, privkeyPEM) if err != nil { - return xerrors.Wrap(err, "failed to upload certificate file") + return fmt.Errorf("failed to upload certificate file: %w", err) } else { d.logger.Info("ssl certificate uploaded", slog.Any("result", upres)) } @@ -173,15 +172,21 @@ func (d *DeployerProvider) deployToCloudServer(ctx context.Context, certPem stri listHostPage := int32(1) listHostPageSize := int32(100) for { + select { + case <-ctx.Done(): + return ctx.Err() + default: + } + listHostReq := &hcwafmodel.ListHostRequest{ - Hostname: hwsdk.StringPtr(strings.TrimPrefix(d.config.Domain, "*")), - Page: hwsdk.Int32Ptr(listHostPage), - Pagesize: hwsdk.Int32Ptr(listHostPageSize), + Hostname: typeutil.ToPtr(strings.TrimPrefix(d.config.Domain, "*")), + Page: typeutil.ToPtr(listHostPage), + Pagesize: typeutil.ToPtr(listHostPageSize), } listHostResp, err := d.sdkClient.ListHost(listHostReq) d.logger.Debug("sdk request 'waf.ListHost'", slog.Any("request", listHostReq), slog.Any("response", listHostResp)) if err != nil { - return xerrors.Wrap(err, "failed to execute sdk request 'waf.ListHost'") + return fmt.Errorf("failed to execute sdk request 'waf.ListHost': %w", err) } if listHostResp.Items != nil { @@ -208,28 +213,28 @@ func (d *DeployerProvider) deployToCloudServer(ctx context.Context, certPem stri updateHostReq := &hcwafmodel.UpdateHostRequest{ InstanceId: hostId, Body: &hcwafmodel.UpdateHostRequestBody{ - Certificateid: hwsdk.StringPtr(upres.CertId), - Certificatename: hwsdk.StringPtr(upres.CertName), + Certificateid: typeutil.ToPtr(upres.CertId), + Certificatename: typeutil.ToPtr(upres.CertName), }, } updateHostResp, err := d.sdkClient.UpdateHost(updateHostReq) d.logger.Debug("sdk request 'waf.UpdateHost'", slog.Any("request", updateHostReq), slog.Any("response", updateHostResp)) if err != nil { - return xerrors.Wrap(err, "failed to execute sdk request 'waf.UpdateHost'") + return fmt.Errorf("failed to execute sdk request 'waf.UpdateHost': %w", err) } return nil } -func (d *DeployerProvider) deployToPremiumHost(ctx context.Context, certPem string, privkeyPem string) error { +func (d *DeployerProvider) deployToPremiumHost(ctx context.Context, certPEM string, privkeyPEM string) error { if d.config.Domain == "" { return errors.New("config `domain` is required") } // 上传证书到 WAF - upres, err := d.sslUploader.Upload(ctx, certPem, privkeyPem) + upres, err := d.sslUploader.Upload(ctx, certPEM, privkeyPEM) if err != nil { - return xerrors.Wrap(err, "failed to upload certificate file") + return fmt.Errorf("failed to upload certificate file: %w", err) } else { d.logger.Info("ssl certificate uploaded", slog.Any("result", upres)) } @@ -240,15 +245,21 @@ func (d *DeployerProvider) deployToPremiumHost(ctx context.Context, certPem stri listPremiumHostPage := int32(1) listPremiumHostPageSize := int32(100) for { + select { + case <-ctx.Done(): + return ctx.Err() + default: + } + listPremiumHostReq := &hcwafmodel.ListPremiumHostRequest{ - Hostname: hwsdk.StringPtr(strings.TrimPrefix(d.config.Domain, "*")), - Page: hwsdk.StringPtr(fmt.Sprintf("%d", listPremiumHostPage)), - Pagesize: hwsdk.StringPtr(fmt.Sprintf("%d", listPremiumHostPageSize)), + Hostname: typeutil.ToPtr(strings.TrimPrefix(d.config.Domain, "*")), + Page: typeutil.ToPtr(fmt.Sprintf("%d", listPremiumHostPage)), + Pagesize: typeutil.ToPtr(fmt.Sprintf("%d", listPremiumHostPageSize)), } listPremiumHostResp, err := d.sdkClient.ListPremiumHost(listPremiumHostReq) d.logger.Debug("sdk request 'waf.ListPremiumHost'", slog.Any("request", listPremiumHostReq), slog.Any("response", listPremiumHostResp)) if err != nil { - return xerrors.Wrap(err, "failed to execute sdk request 'waf.ListPremiumHost'") + return fmt.Errorf("failed to execute sdk request 'waf.ListPremiumHost': %w", err) } if listPremiumHostResp.Items != nil { @@ -275,14 +286,14 @@ func (d *DeployerProvider) deployToPremiumHost(ctx context.Context, certPem stri updatePremiumHostReq := &hcwafmodel.UpdatePremiumHostRequest{ HostId: hostId, Body: &hcwafmodel.UpdatePremiumHostRequestBody{ - Certificateid: hwsdk.StringPtr(upres.CertId), - Certificatename: hwsdk.StringPtr(upres.CertName), + Certificateid: typeutil.ToPtr(upres.CertId), + Certificatename: typeutil.ToPtr(upres.CertName), }, } updatePremiumHostResp, err := d.sdkClient.UpdatePremiumHost(updatePremiumHostReq) d.logger.Debug("sdk request 'waf.UpdatePremiumHost'", slog.Any("request", updatePremiumHostReq), slog.Any("response", updatePremiumHostResp)) if err != nil { - return xerrors.Wrap(err, "failed to execute sdk request 'waf.UpdatePremiumHost'") + return fmt.Errorf("failed to execute sdk request 'waf.UpdatePremiumHost': %w", err) } return nil diff --git a/internal/pkg/core/deployer/providers/huaweicloud-waf/huaweicloud_waf_test.go b/internal/pkg/core/deployer/providers/huaweicloud-waf/huaweicloud_waf_test.go index 83142325..4f6b5654 100644 --- a/internal/pkg/core/deployer/providers/huaweicloud-waf/huaweicloud_waf_test.go +++ b/internal/pkg/core/deployer/providers/huaweicloud-waf/huaweicloud_waf_test.go @@ -1,4 +1,4 @@ -package huaweicloudwaf_test +package huaweicloudwaf_test import ( "context" diff --git a/internal/pkg/core/deployer/providers/jdcloud-alb/consts.go b/internal/pkg/core/deployer/providers/jdcloud-alb/consts.go index 13525c20..de6e4ef0 100644 --- a/internal/pkg/core/deployer/providers/jdcloud-alb/consts.go +++ b/internal/pkg/core/deployer/providers/jdcloud-alb/consts.go @@ -1,4 +1,4 @@ -package jdcloudalb +package jdcloudalb type ResourceType string diff --git a/internal/pkg/core/deployer/providers/jdcloud-alb/jdcloud_alb.go b/internal/pkg/core/deployer/providers/jdcloud-alb/jdcloud_alb.go index d6c3f05a..ca42126e 100644 --- a/internal/pkg/core/deployer/providers/jdcloud-alb/jdcloud_alb.go +++ b/internal/pkg/core/deployer/providers/jdcloud-alb/jdcloud_alb.go @@ -1,4 +1,4 @@ -package jdcloudalb +package jdcloudalb import ( "context" @@ -12,12 +12,11 @@ import ( jdlbapi "github.com/jdcloud-api/jdcloud-sdk-go/services/lb/apis" jdlbclient "github.com/jdcloud-api/jdcloud-sdk-go/services/lb/client" jdlbmodel "github.com/jdcloud-api/jdcloud-sdk-go/services/lb/models" - xerrors "github.com/pkg/errors" "github.com/usual2970/certimate/internal/pkg/core/deployer" "github.com/usual2970/certimate/internal/pkg/core/uploader" uploadersp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/jdcloud-ssl" - "github.com/usual2970/certimate/internal/pkg/utils/sliceutil" + sliceutil "github.com/usual2970/certimate/internal/pkg/utils/slice" ) type DeployerConfig struct { @@ -56,7 +55,7 @@ func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { client, err := createSdkClient(config.AccessKeyId, config.AccessKeySecret) if err != nil { - return nil, xerrors.Wrap(err, "failed to create sdk client") + return nil, fmt.Errorf("failed to create sdk client: %w", err) } uploader, err := uploadersp.NewUploader(&uploadersp.UploaderConfig{ @@ -64,7 +63,7 @@ func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { AccessKeySecret: config.AccessKeySecret, }) if err != nil { - return nil, xerrors.Wrap(err, "failed to create ssl uploader") + return nil, fmt.Errorf("failed to create ssl uploader: %w", err) } return &DeployerProvider{ @@ -85,11 +84,11 @@ func (d *DeployerProvider) WithLogger(logger *slog.Logger) deployer.Deployer { return d } -func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { +func (d *DeployerProvider) Deploy(ctx context.Context, certPEM string, privkeyPEM string) (*deployer.DeployResult, error) { // 上传证书到 SSL - upres, err := d.sslUploader.Upload(ctx, certPem, privkeyPem) + upres, err := d.sslUploader.Upload(ctx, certPEM, privkeyPEM) if err != nil { - return nil, xerrors.Wrap(err, "failed to upload certificate file") + return nil, fmt.Errorf("failed to upload certificate file: %w", err) } else { d.logger.Info("ssl certificate uploaded", slog.Any("result", upres)) } @@ -107,7 +106,7 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPe } default: - return nil, fmt.Errorf("unsupported resource type: %s", d.config.ResourceType) + return nil, fmt.Errorf("unsupported resource type '%s'", d.config.ResourceType) } return &deployer.DeployResult{}, nil @@ -124,7 +123,7 @@ func (d *DeployerProvider) deployToLoadbalancer(ctx context.Context, cloudCertId describeLoadBalancerResp, err := d.sdkClient.DescribeLoadBalancer(describeLoadBalancerReq) d.logger.Debug("sdk request 'lb.DescribeLoadBalancer'", slog.Any("request", describeLoadBalancerReq), slog.Any("response", describeLoadBalancerResp)) if err != nil { - return xerrors.Wrap(err, "failed to execute sdk request 'lb.DescribeLoadBalancer'") + return fmt.Errorf("failed to execute sdk request 'lb.DescribeLoadBalancer': %w", err) } // 查询监听器列表 @@ -133,6 +132,12 @@ func (d *DeployerProvider) deployToLoadbalancer(ctx context.Context, cloudCertId describeListenersPageNumber := 1 describeListenersPageSize := 100 for { + select { + case <-ctx.Done(): + return ctx.Err() + default: + } + describeListenersReq := jdlbapi.NewDescribeListenersRequest(d.config.RegionId) describeListenersReq.SetFilters([]jdcommon.Filter{{Name: "loadBalancerId", Values: []string{d.config.LoadbalancerId}}}) describeListenersReq.SetPageSize(describeListenersPageNumber) @@ -140,7 +145,7 @@ func (d *DeployerProvider) deployToLoadbalancer(ctx context.Context, cloudCertId describeListenersResp, err := d.sdkClient.DescribeListeners(describeListenersReq) d.logger.Debug("sdk request 'lb.DescribeListeners'", slog.Any("request", describeListenersReq), slog.Any("response", describeListenersResp)) if err != nil { - return xerrors.Wrap(err, "failed to execute sdk request 'lb.DescribeListeners'") + return fmt.Errorf("failed to execute sdk request 'lb.DescribeListeners': %w", err) } for _, listener := range describeListenersResp.Result.Listeners { @@ -165,8 +170,13 @@ func (d *DeployerProvider) deployToLoadbalancer(ctx context.Context, cloudCertId var errs []error for _, listenerId := range listenerIds { - if err := d.updateListenerCertificate(ctx, listenerId, cloudCertId); err != nil { - errs = append(errs, err) + select { + case <-ctx.Done(): + return ctx.Err() + default: + if err := d.updateListenerCertificate(ctx, listenerId, cloudCertId); err != nil { + errs = append(errs, err) + } } } @@ -198,7 +208,7 @@ func (d *DeployerProvider) updateListenerCertificate(ctx context.Context, cloudL describeListenerResp, err := d.sdkClient.DescribeListener(describeListenerReq) d.logger.Debug("sdk request 'lb.DescribeListener'", slog.Any("request", describeListenerReq), slog.Any("response", describeListenerResp)) if err != nil { - return xerrors.Wrap(err, "failed to execute sdk request 'lb.DescribeListener'") + return fmt.Errorf("failed to execute sdk request 'lb.DescribeListener': %w", err) } if d.config.Domain == "" { @@ -211,7 +221,7 @@ func (d *DeployerProvider) updateListenerCertificate(ctx context.Context, cloudL updateListenerResp, err := d.sdkClient.UpdateListener(updateListenerReq) d.logger.Debug("sdk request 'lb.UpdateListener'", slog.Any("request", updateListenerReq), slog.Any("response", updateListenerResp)) if err != nil { - return xerrors.Wrap(err, "failed to execute sdk request 'lb.UpdateListener'") + return fmt.Errorf("failed to execute sdk request 'lb.UpdateListener': %w", err) } } else { // 指定 SNI,需部署到扩展证书 @@ -239,7 +249,7 @@ func (d *DeployerProvider) updateListenerCertificate(ctx context.Context, cloudL updateListenerCertificatesResp, err := d.sdkClient.UpdateListenerCertificates(updateListenerCertificatesReq) d.logger.Debug("sdk request 'lb.UpdateListenerCertificates'", slog.Any("request", updateListenerCertificatesReq), slog.Any("response", updateListenerCertificatesResp)) if err != nil { - return xerrors.Wrap(err, "failed to execute sdk request 'lb.UpdateListenerCertificates'") + return fmt.Errorf("failed to execute sdk request 'lb.UpdateListenerCertificates': %w", err) } } diff --git a/internal/pkg/core/deployer/providers/jdcloud-alb/jdcloud_alb_test.go b/internal/pkg/core/deployer/providers/jdcloud-alb/jdcloud_alb_test.go index 9c9cc9cc..b6c063e2 100644 --- a/internal/pkg/core/deployer/providers/jdcloud-alb/jdcloud_alb_test.go +++ b/internal/pkg/core/deployer/providers/jdcloud-alb/jdcloud_alb_test.go @@ -1,4 +1,4 @@ -package jdcloudalb_test +package jdcloudalb_test import ( "context" diff --git a/internal/pkg/core/deployer/providers/jdcloud-cdn/jdcloud_cdn.go b/internal/pkg/core/deployer/providers/jdcloud-cdn/jdcloud_cdn.go index 8fe7f6ea..10ccf19d 100644 --- a/internal/pkg/core/deployer/providers/jdcloud-cdn/jdcloud_cdn.go +++ b/internal/pkg/core/deployer/providers/jdcloud-cdn/jdcloud_cdn.go @@ -1,13 +1,13 @@ -package jdcloudcdn +package jdcloudcdn import ( "context" + "fmt" "log/slog" jdcore "github.com/jdcloud-api/jdcloud-sdk-go/core" jdcdnapi "github.com/jdcloud-api/jdcloud-sdk-go/services/cdn/apis" jdcdnclient "github.com/jdcloud-api/jdcloud-sdk-go/services/cdn/client" - xerrors "github.com/pkg/errors" "github.com/usual2970/certimate/internal/pkg/core/deployer" "github.com/usual2970/certimate/internal/pkg/core/uploader" @@ -39,7 +39,7 @@ func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { client, err := createSdkClient(config.AccessKeyId, config.AccessKeySecret) if err != nil { - return nil, xerrors.Wrap(err, "failed to create sdk client") + return nil, fmt.Errorf("failed to create sdk client: %w", err) } uploader, err := uploadersp.NewUploader(&uploadersp.UploaderConfig{ @@ -47,7 +47,7 @@ func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { AccessKeySecret: config.AccessKeySecret, }) if err != nil { - return nil, xerrors.Wrap(err, "failed to create ssl uploader") + return nil, fmt.Errorf("failed to create ssl uploader: %w", err) } return &DeployerProvider{ @@ -68,20 +68,20 @@ func (d *DeployerProvider) WithLogger(logger *slog.Logger) deployer.Deployer { return d } -func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { +func (d *DeployerProvider) Deploy(ctx context.Context, certPEM string, privkeyPEM string) (*deployer.DeployResult, error) { // 查询域名配置信息 // REF: https://docs.jdcloud.com/cn/cdn/api/querydomainconfig queryDomainConfigReq := jdcdnapi.NewQueryDomainConfigRequest(d.config.Domain) queryDomainConfigResp, err := d.sdkClient.QueryDomainConfig(queryDomainConfigReq) d.logger.Debug("sdk request 'cdn.QueryDomainConfig'", slog.Any("request", queryDomainConfigReq), slog.Any("response", queryDomainConfigResp)) if err != nil { - return nil, xerrors.Wrap(err, "failed to execute sdk request 'cdn.QueryDomainConfig'") + return nil, fmt.Errorf("failed to execute sdk request 'cdn.QueryDomainConfig': %w", err) } // 上传证书到 SSL - upres, err := d.sslUploader.Upload(ctx, certPem, privkeyPem) + upres, err := d.sslUploader.Upload(ctx, certPEM, privkeyPEM) if err != nil { - return nil, xerrors.Wrap(err, "failed to upload certificate file") + return nil, fmt.Errorf("failed to upload certificate file: %w", err) } else { d.logger.Info("ssl certificate uploaded", slog.Any("result", upres)) } @@ -90,15 +90,15 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPe // REF: https://docs.jdcloud.com/cn/cdn/api/sethttptype setHttpTypeReq := jdcdnapi.NewSetHttpTypeRequest(d.config.Domain) setHttpTypeReq.SetHttpType("https") - setHttpTypeReq.SetCertificate(certPem) - setHttpTypeReq.SetRsaKey(privkeyPem) + setHttpTypeReq.SetCertificate(certPEM) + setHttpTypeReq.SetRsaKey(privkeyPEM) setHttpTypeReq.SetCertFrom("ssl") setHttpTypeReq.SetSslCertId(upres.CertId) setHttpTypeReq.SetJumpType(queryDomainConfigResp.Result.HttpsJumpType) setHttpTypeResp, err := d.sdkClient.SetHttpType(setHttpTypeReq) d.logger.Debug("sdk request 'cdn.QueryDomainConfig'", slog.Any("request", setHttpTypeReq), slog.Any("response", setHttpTypeResp)) if err != nil { - return nil, xerrors.Wrap(err, "failed to execute sdk request 'cdn.SetHttpType'") + return nil, fmt.Errorf("failed to execute sdk request 'cdn.SetHttpType': %w", err) } return &deployer.DeployResult{}, nil diff --git a/internal/pkg/core/deployer/providers/jdcloud-cdn/jdcloud_cdn_test.go b/internal/pkg/core/deployer/providers/jdcloud-cdn/jdcloud_cdn_test.go index 2d2f7ed0..1bed5d15 100644 --- a/internal/pkg/core/deployer/providers/jdcloud-cdn/jdcloud_cdn_test.go +++ b/internal/pkg/core/deployer/providers/jdcloud-cdn/jdcloud_cdn_test.go @@ -1,4 +1,4 @@ -package jdcloudcdn_test +package jdcloudcdn_test import ( "context" diff --git a/internal/pkg/core/deployer/providers/jdcloud-live/jdcloud_live.go b/internal/pkg/core/deployer/providers/jdcloud-live/jdcloud_live.go index c89a67b9..24e5bc7a 100644 --- a/internal/pkg/core/deployer/providers/jdcloud-live/jdcloud_live.go +++ b/internal/pkg/core/deployer/providers/jdcloud-live/jdcloud_live.go @@ -1,13 +1,13 @@ -package jdcloudlive +package jdcloudlive import ( "context" + "fmt" "log/slog" jdcore "github.com/jdcloud-api/jdcloud-sdk-go/core" jdliveapi "github.com/jdcloud-api/jdcloud-sdk-go/services/live/apis" jdliveclient "github.com/jdcloud-api/jdcloud-sdk-go/services/live/client" - xerrors "github.com/pkg/errors" "github.com/usual2970/certimate/internal/pkg/core/deployer" ) @@ -36,7 +36,7 @@ func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { client, err := createSdkClient(config.AccessKeyId, config.AccessKeySecret) if err != nil { - return nil, xerrors.Wrap(err, "failed to create sdk client") + return nil, fmt.Errorf("failed to create sdk client: %w", err) } return &DeployerProvider{ @@ -55,16 +55,16 @@ func (d *DeployerProvider) WithLogger(logger *slog.Logger) deployer.Deployer { return d } -func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { +func (d *DeployerProvider) Deploy(ctx context.Context, certPEM string, privkeyPEM string) (*deployer.DeployResult, error) { // 设置直播证书 // REF: https://docs.jdcloud.com/cn/live-video/api/setlivedomaincertificate setLiveDomainCertificateReq := jdliveapi.NewSetLiveDomainCertificateRequest(d.config.Domain, "on") - setLiveDomainCertificateReq.SetCert(certPem) - setLiveDomainCertificateReq.SetKey(privkeyPem) + setLiveDomainCertificateReq.SetCert(certPEM) + setLiveDomainCertificateReq.SetKey(privkeyPEM) setLiveDomainCertificateResp, err := d.sdkClient.SetLiveDomainCertificate(setLiveDomainCertificateReq) d.logger.Debug("sdk request 'live.SetLiveDomainCertificate'", slog.Any("request", setLiveDomainCertificateReq), slog.Any("response", setLiveDomainCertificateResp)) if err != nil { - return nil, xerrors.Wrap(err, "failed to execute sdk request 'live.SetLiveDomainCertificate'") + return nil, fmt.Errorf("failed to execute sdk request 'live.SetLiveDomainCertificate': %w", err) } return &deployer.DeployResult{}, nil diff --git a/internal/pkg/core/deployer/providers/jdcloud-live/jdcloud_live_test.go b/internal/pkg/core/deployer/providers/jdcloud-live/jdcloud_live_test.go index 076202b5..d544690d 100644 --- a/internal/pkg/core/deployer/providers/jdcloud-live/jdcloud_live_test.go +++ b/internal/pkg/core/deployer/providers/jdcloud-live/jdcloud_live_test.go @@ -1,4 +1,4 @@ -package jdcloudlive_test +package jdcloudlive_test import ( "context" diff --git a/internal/pkg/core/deployer/providers/jdcloud-vod/jdcloud_vod.go b/internal/pkg/core/deployer/providers/jdcloud-vod/jdcloud_vod.go index 95be5c15..6f61625d 100644 --- a/internal/pkg/core/deployer/providers/jdcloud-vod/jdcloud_vod.go +++ b/internal/pkg/core/deployer/providers/jdcloud-vod/jdcloud_vod.go @@ -1,7 +1,8 @@ -package jdcloudvod +package jdcloudvod import ( "context" + "errors" "fmt" "log/slog" "strconv" @@ -10,7 +11,6 @@ import ( jdcore "github.com/jdcloud-api/jdcloud-sdk-go/core" jdvodapi "github.com/jdcloud-api/jdcloud-sdk-go/services/vod/apis" jdvodclient "github.com/jdcloud-api/jdcloud-sdk-go/services/vod/client" - xerrors "github.com/pkg/errors" "github.com/usual2970/certimate/internal/pkg/core/deployer" ) @@ -39,7 +39,7 @@ func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { client, err := createSdkClient(config.AccessKeyId, config.AccessKeySecret) if err != nil { - return nil, xerrors.Wrap(err, "failed to create sdk client") + return nil, fmt.Errorf("failed to create sdk client: %w", err) } return &DeployerProvider{ @@ -58,20 +58,26 @@ func (d *DeployerProvider) WithLogger(logger *slog.Logger) deployer.Deployer { return d } -func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { +func (d *DeployerProvider) Deploy(ctx context.Context, certPEM string, privkeyPEM string) (*deployer.DeployResult, error) { // 查询域名列表 // REF: https://docs.jdcloud.com/cn/video-on-demand/api/listdomains var domainId int listDomainsPageNumber := 1 listDomainsPageSize := 100 for { + select { + case <-ctx.Done(): + return nil, ctx.Err() + default: + } + listDomainsReq := jdvodapi.NewListDomainsRequest() listDomainsReq.SetPageNumber(1) listDomainsReq.SetPageSize(100) listDomainsResp, err := d.sdkClient.ListDomains(listDomainsReq) d.logger.Debug("sdk request 'vod.ListDomains'", slog.Any("request", listDomainsReq), slog.Any("response", listDomainsResp)) if err != nil { - return nil, xerrors.Wrap(err, "failed to execute sdk request 'vod.ListDomains'") + return nil, fmt.Errorf("failed to execute sdk request 'vod.ListDomains': %w", err) } for _, domain := range listDomainsResp.Result.Content { @@ -88,7 +94,7 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPe } } if domainId == 0 { - return nil, xerrors.New("domain not found") + return nil, errors.New("domain not found") } // 查询域名 SSL 配置 @@ -97,22 +103,22 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPe getHttpSslResp, err := d.sdkClient.GetHttpSsl(getHttpSslReq) d.logger.Debug("sdk request 'vod.GetHttpSsl'", slog.Any("request", getHttpSslReq), slog.Any("response", getHttpSslResp)) if err != nil { - return nil, xerrors.Wrap(err, "failed to execute sdk request 'vod.GetHttpSsl'") + return nil, fmt.Errorf("failed to execute sdk request 'vod.GetHttpSsl': %w", err) } // 设置域名 SSL 配置 // REF: https://docs.jdcloud.com/cn/video-on-demand/api/sethttpssl setHttpSslReq := jdvodapi.NewSetHttpSslRequest(domainId) setHttpSslReq.SetTitle(fmt.Sprintf("certimate-%d", time.Now().UnixMilli())) - setHttpSslReq.SetSslCert(certPem) - setHttpSslReq.SetSslKey(privkeyPem) + setHttpSslReq.SetSslCert(certPEM) + setHttpSslReq.SetSslKey(privkeyPEM) setHttpSslReq.SetSource("default") setHttpSslReq.SetJumpType(getHttpSslResp.Result.JumpType) setHttpSslReq.SetEnabled(true) setHttpSslResp, err := d.sdkClient.SetHttpSsl(setHttpSslReq) d.logger.Debug("sdk request 'vod.SetHttpSsl'", slog.Any("request", setHttpSslReq), slog.Any("response", setHttpSslResp)) if err != nil { - return nil, xerrors.Wrap(err, "failed to execute sdk request 'vod.SetHttpSsl'") + return nil, fmt.Errorf("failed to execute sdk request 'vod.SetHttpSsl': %w", err) } return &deployer.DeployResult{}, nil diff --git a/internal/pkg/core/deployer/providers/jdcloud-vod/jdcloud_vod_test.go b/internal/pkg/core/deployer/providers/jdcloud-vod/jdcloud_vod_test.go index 6046982b..b8c38b1d 100644 --- a/internal/pkg/core/deployer/providers/jdcloud-vod/jdcloud_vod_test.go +++ b/internal/pkg/core/deployer/providers/jdcloud-vod/jdcloud_vod_test.go @@ -1,4 +1,4 @@ -package jdcloudvod_test +package jdcloudvod_test import ( "context" 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 88b4b6a1..de2e62be 100644 --- a/internal/pkg/core/deployer/providers/k8s-secret/k8s_secret.go +++ b/internal/pkg/core/deployer/providers/k8s-secret/k8s_secret.go @@ -1,12 +1,12 @@ -package k8ssecret +package k8ssecret import ( "context" "errors" + "fmt" "log/slog" "strings" - xerrors "github.com/pkg/errors" k8score "k8s.io/api/core/v1" k8smeta "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/client-go/kubernetes" @@ -14,7 +14,7 @@ import ( "k8s.io/client-go/tools/clientcmd" "github.com/usual2970/certimate/internal/pkg/core/deployer" - "github.com/usual2970/certimate/internal/pkg/utils/certutil" + certutil "github.com/usual2970/certimate/internal/pkg/utils/cert" ) type DeployerConfig struct { @@ -59,7 +59,7 @@ func (d *DeployerProvider) WithLogger(logger *slog.Logger) deployer.Deployer { return d } -func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { +func (d *DeployerProvider) Deploy(ctx context.Context, certPEM string, privkeyPEM string) (*deployer.DeployResult, error) { if d.config.Namespace == "" { return nil, errors.New("config `namespace` is required") } @@ -76,7 +76,7 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPe return nil, errors.New("config `secretDataKeyForKey` is required") } - certX509, err := certutil.ParseCertificateFromPEM(certPem) + certX509, err := certutil.ParseCertificateFromPEM(certPEM) if err != nil { return nil, err } @@ -84,7 +84,7 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPe // 连接 client, err := createK8sClient(d.config.KubeConfig) if err != nil { - return nil, xerrors.Wrap(err, "failed to create k8s client") + return nil, fmt.Errorf("failed to create k8s client: %w", err) } var secretPayload *k8score.Secret @@ -111,13 +111,13 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPe Type: k8score.SecretType(d.config.SecretType), } secretPayload.Data = make(map[string][]byte) - secretPayload.Data[d.config.SecretDataKeyForCrt] = []byte(certPem) - secretPayload.Data[d.config.SecretDataKeyForKey] = []byte(privkeyPem) + secretPayload.Data[d.config.SecretDataKeyForCrt] = []byte(certPEM) + secretPayload.Data[d.config.SecretDataKeyForKey] = []byte(privkeyPEM) secretPayload, err = client.CoreV1().Secrets(d.config.Namespace).Create(context.TODO(), secretPayload, k8smeta.CreateOptions{}) d.logger.Debug("k8s operate 'Secrets.Create'", slog.String("namespace", d.config.Namespace), slog.Any("secret", secretPayload)) if err != nil { - return nil, xerrors.Wrap(err, "failed to create k8s secret") + return nil, fmt.Errorf("failed to create k8s secret: %w", err) } else { return &deployer.DeployResult{}, nil } @@ -135,12 +135,12 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPe if secretPayload.Data == nil { secretPayload.Data = make(map[string][]byte) } - secretPayload.Data[d.config.SecretDataKeyForCrt] = []byte(certPem) - secretPayload.Data[d.config.SecretDataKeyForKey] = []byte(privkeyPem) + secretPayload.Data[d.config.SecretDataKeyForCrt] = []byte(certPEM) + secretPayload.Data[d.config.SecretDataKeyForKey] = []byte(privkeyPEM) secretPayload, err = client.CoreV1().Secrets(d.config.Namespace).Update(context.TODO(), secretPayload, k8smeta.UpdateOptions{}) d.logger.Debug("k8s operate 'Secrets.Update'", slog.String("namespace", d.config.Namespace), slog.Any("secret", secretPayload)) if err != nil { - return nil, xerrors.Wrap(err, "failed to update k8s secret") + return nil, fmt.Errorf("failed to update k8s secret: %w", err) } return &deployer.DeployResult{}, nil 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 75f15502..90bdf4ab 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 @@ -1,4 +1,4 @@ -package k8ssecret_test +package k8ssecret_test import ( "context" diff --git a/internal/pkg/core/deployer/providers/local/defines.go b/internal/pkg/core/deployer/providers/local/defines.go index 5b3118d8..2021f1ea 100644 --- a/internal/pkg/core/deployer/providers/local/defines.go +++ b/internal/pkg/core/deployer/providers/local/defines.go @@ -1,4 +1,4 @@ -package local +package local type OutputFormatType string diff --git a/internal/pkg/core/deployer/providers/local/local.go b/internal/pkg/core/deployer/providers/local/local.go index b4d07711..77f96543 100644 --- a/internal/pkg/core/deployer/providers/local/local.go +++ b/internal/pkg/core/deployer/providers/local/local.go @@ -1,4 +1,4 @@ -package local +package local import ( "bytes" @@ -8,11 +8,9 @@ import ( "os/exec" "runtime" - xerrors "github.com/pkg/errors" - "github.com/usual2970/certimate/internal/pkg/core/deployer" - "github.com/usual2970/certimate/internal/pkg/utils/certutil" - "github.com/usual2970/certimate/internal/pkg/utils/fileutil" + certutil "github.com/usual2970/certimate/internal/pkg/utils/cert" + fileutil "github.com/usual2970/certimate/internal/pkg/utils/file" ) type DeployerConfig struct { @@ -70,55 +68,55 @@ func (d *DeployerProvider) WithLogger(logger *slog.Logger) deployer.Deployer { return d } -func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { +func (d *DeployerProvider) Deploy(ctx context.Context, certPEM string, privkeyPEM string) (*deployer.DeployResult, error) { // 执行前置命令 if d.config.PreCommand != "" { stdout, stderr, err := execCommand(d.config.ShellEnv, d.config.PreCommand) d.logger.Debug("run pre-command", slog.String("stdout", stdout), slog.String("stderr", stderr)) if err != nil { - return nil, xerrors.Wrapf(err, "failed to execute pre-command, stdout: %s, stderr: %s", stdout, stderr) + return nil, fmt.Errorf("failed to execute pre-command (stdout: %s, stderr: %s): %w ", stdout, stderr, err) } } // 写入证书和私钥文件 switch d.config.OutputFormat { case OUTPUT_FORMAT_PEM: - if err := fileutil.WriteString(d.config.OutputCertPath, certPem); err != nil { - return nil, xerrors.Wrap(err, "failed to save certificate file") + if err := fileutil.WriteString(d.config.OutputCertPath, certPEM); err != nil { + return nil, fmt.Errorf("failed to save certificate file: %w", err) } d.logger.Info("ssl certificate file saved", slog.String("path", d.config.OutputCertPath)) - if err := fileutil.WriteString(d.config.OutputKeyPath, privkeyPem); err != nil { - return nil, xerrors.Wrap(err, "failed to save private key file") + if err := fileutil.WriteString(d.config.OutputKeyPath, privkeyPEM); err != nil { + return nil, fmt.Errorf("failed to save private key file: %w", err) } d.logger.Info("ssl private key file saved", slog.String("path", d.config.OutputKeyPath)) case OUTPUT_FORMAT_PFX: - pfxData, err := certutil.TransformCertificateFromPEMToPFX(certPem, privkeyPem, d.config.PfxPassword) + pfxData, err := certutil.TransformCertificateFromPEMToPFX(certPEM, privkeyPEM, d.config.PfxPassword) if err != nil { - return nil, xerrors.Wrap(err, "failed to transform certificate to PFX") + return nil, fmt.Errorf("failed to transform certificate to PFX: %w", err) } d.logger.Info("ssl certificate transformed to pfx") if err := fileutil.Write(d.config.OutputCertPath, pfxData); err != nil { - return nil, xerrors.Wrap(err, "failed to save certificate file") + return nil, fmt.Errorf("failed to save certificate file: %w", err) } d.logger.Info("ssl certificate file saved", slog.String("path", d.config.OutputCertPath)) case OUTPUT_FORMAT_JKS: - jksData, err := certutil.TransformCertificateFromPEMToJKS(certPem, privkeyPem, d.config.JksAlias, d.config.JksKeypass, d.config.JksStorepass) + jksData, err := certutil.TransformCertificateFromPEMToJKS(certPEM, privkeyPEM, d.config.JksAlias, d.config.JksKeypass, d.config.JksStorepass) if err != nil { - return nil, xerrors.Wrap(err, "failed to transform certificate to JKS") + return nil, fmt.Errorf("failed to transform certificate to JKS: %w", err) } d.logger.Info("ssl certificate transformed to jks") if err := fileutil.Write(d.config.OutputCertPath, jksData); err != nil { - return nil, xerrors.Wrap(err, "failed to save certificate file") + return nil, fmt.Errorf("failed to save certificate file: %w", err) } d.logger.Info("ssl certificate file saved", slog.String("path", d.config.OutputCertPath)) default: - return nil, fmt.Errorf("unsupported output format: %s", d.config.OutputFormat) + return nil, fmt.Errorf("unsupported output format '%s'", d.config.OutputFormat) } // 执行后置命令 @@ -126,7 +124,7 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPe stdout, stderr, err := execCommand(d.config.ShellEnv, d.config.PostCommand) d.logger.Debug("run post-command", slog.String("stdout", stdout), slog.String("stderr", stderr)) if err != nil { - return nil, xerrors.Wrapf(err, "failed to execute post-command, stdout: %s, stderr: %s", stdout, stderr) + return nil, fmt.Errorf("failed to execute post-command (stdout: %s, stderr: %s): %w ", stdout, stderr, err) } } @@ -154,7 +152,7 @@ func execCommand(shellEnv ShellEnvType, command string) (string, string, error) } default: - return "", "", fmt.Errorf("unsupported shell env: %s", shellEnv) + return "", "", fmt.Errorf("unsupported shell env '%s'", shellEnv) } stdoutBuf := bytes.NewBuffer(nil) @@ -163,7 +161,7 @@ func execCommand(shellEnv ShellEnvType, command string) (string, string, error) cmd.Stderr = stderrBuf err := cmd.Run() if err != nil { - return stdoutBuf.String(), stderrBuf.String(), xerrors.Wrap(err, "failed to execute command") + return stdoutBuf.String(), stderrBuf.String(), fmt.Errorf("failed to execute command: %w", err) } return stdoutBuf.String(), stderrBuf.String(), nil diff --git a/internal/pkg/core/deployer/providers/local/local_test.go b/internal/pkg/core/deployer/providers/local/local_test.go index e86ba7e0..4225864b 100644 --- a/internal/pkg/core/deployer/providers/local/local_test.go +++ b/internal/pkg/core/deployer/providers/local/local_test.go @@ -1,4 +1,4 @@ -package local_test +package local_test import ( "context" diff --git a/internal/pkg/core/deployer/providers/proxmoxve/proxmoxve.go b/internal/pkg/core/deployer/providers/proxmoxve/proxmoxve.go new file mode 100644 index 00000000..d2e92460 --- /dev/null +++ b/internal/pkg/core/deployer/providers/proxmoxve/proxmoxve.go @@ -0,0 +1,121 @@ +package proxmoxve + +import ( + "context" + "crypto/tls" + "errors" + "fmt" + "log/slog" + "net/http" + "net/url" + "strings" + + "github.com/luthermonson/go-proxmox" + + "github.com/usual2970/certimate/internal/pkg/core/deployer" +) + +type DeployerConfig struct { + // Proxmox VE 地址。 + ApiUrl string `json:"apiUrl"` + // Proxmox VE API Token。 + ApiToken string `json:"apiToken"` + // Proxmox VE API Token Secret。 + ApiTokenSecret string `json:"apiTokenSecret,omitempty"` + // 是否允许不安全的连接。 + AllowInsecureConnections bool `json:"allowInsecureConnections,omitempty"` + // 集群节点名称。 + NodeName string `json:"nodeName"` + // 是否自动重启。 + AutoRestart bool `json:"autoRestart"` +} + +type DeployerProvider struct { + config *DeployerConfig + logger *slog.Logger + sdkClient *proxmox.Client +} + +var _ deployer.Deployer = (*DeployerProvider)(nil) + +func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { + if config == nil { + panic("config is nil") + } + + client, err := createSdkClient(config.ApiUrl, config.ApiToken, config.ApiTokenSecret, config.AllowInsecureConnections) + if err != nil { + return nil, fmt.Errorf("failed to create sdk client: %w", err) + } + + return &DeployerProvider{ + config: config, + logger: slog.Default(), + sdkClient: client, + }, nil +} + +func (d *DeployerProvider) WithLogger(logger *slog.Logger) deployer.Deployer { + if logger == nil { + d.logger = slog.Default() + } else { + d.logger = logger + } + return d +} + +func (d *DeployerProvider) Deploy(ctx context.Context, certPEM string, privkeyPEM string) (*deployer.DeployResult, error) { + if d.config.NodeName == "" { + return nil, errors.New("config `nodeName` is required") + } + + // 获取节点信息 + // REF: https://pve.proxmox.com/pve-docs/api-viewer/index.html#/nodes/{node} + node, err := d.sdkClient.Node(context.TODO(), d.config.NodeName) + if err != nil { + return nil, fmt.Errorf("failed to get node '%s': %w", d.config.NodeName, err) + } + + // 上传自定义证书 + // REF: https://pve.proxmox.com/pve-docs/api-viewer/index.html#/nodes/{node}/certificates/custom + err = node.UploadCustomCertificate(context.TODO(), &proxmox.CustomCertificate{ + Certificates: certPEM, + Key: privkeyPEM, + Force: true, + Restart: d.config.AutoRestart, + }) + if err != nil { + return nil, fmt.Errorf("failed to upload custom certificate to node '%s': %w", node.Name, err) + } + + return &deployer.DeployResult{}, nil +} + +func createSdkClient(apiUrl, apiToken, apiTokenSecret string, skipTlsVerify bool) (*proxmox.Client, error) { + if _, err := url.Parse(apiUrl); err != nil { + return nil, errors.New("invalid pve api url") + } + + if apiToken == "" { + return nil, errors.New("invalid pve api token") + } + + httpClient := &http.Client{ + Transport: http.DefaultTransport, + Timeout: http.DefaultClient.Timeout, + } + if skipTlsVerify { + httpClient.Transport = &http.Transport{ + TLSClientConfig: &tls.Config{ + InsecureSkipVerify: true, + }, + } + } + client := proxmox.NewClient( + strings.TrimRight(apiUrl, "/")+"/api2/json", + proxmox.WithHTTPClient(httpClient), + proxmox.WithAPIToken(apiToken, apiTokenSecret), + ) + + return client, nil +} diff --git a/internal/pkg/core/deployer/providers/proxmoxve/proxmoxve_test.go b/internal/pkg/core/deployer/providers/proxmoxve/proxmoxve_test.go new file mode 100644 index 00000000..6251bd75 --- /dev/null +++ b/internal/pkg/core/deployer/providers/proxmoxve/proxmoxve_test.go @@ -0,0 +1,82 @@ +package proxmoxve_test + +import ( + "context" + "flag" + "fmt" + "os" + "strings" + "testing" + + provider "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/proxmoxve" +) + +var ( + fInputCertPath string + fInputKeyPath string + fApiUrl string + fApiToken string + fApiTokenSecret string + fNodeName string +) + +func init() { + argsPrefix := "CERTIMATE_DEPLOYER_PROXMOXVE_" + + flag.StringVar(&fInputCertPath, argsPrefix+"INPUTCERTPATH", "", "") + flag.StringVar(&fInputKeyPath, argsPrefix+"INPUTKEYPATH", "", "") + flag.StringVar(&fApiUrl, argsPrefix+"APIURL", "", "") + flag.StringVar(&fApiToken, argsPrefix+"APITOKEN", "", "") + flag.StringVar(&fApiTokenSecret, argsPrefix+"APITOKENSECRET", "", "") + flag.StringVar(&fNodeName, argsPrefix+"NODENAME", "", "") +} + +/* +Shell command to run this test: + + go test -v ./proxmoxve_test.go -args \ + --CERTIMATE_DEPLOYER_PROXMOXVE_INPUTCERTPATH="/path/to/your-input-cert.pem" \ + --CERTIMATE_DEPLOYER_PROXMOXVE_INPUTKEYPATH="/path/to/your-input-key.pem" \ + --CERTIMATE_DEPLOYER_PROXMOXVE_APIURL="http://127.0.0.1:8006" \ + --CERTIMATE_DEPLOYER_PROXMOXVE_APITOKEN="your-api-token" \ + --CERTIMATE_DEPLOYER_PROXMOXVE_APITOKENSECRET="your-api-token-secret" \ + --CERTIMATE_DEPLOYER_PROXMOXVE_NODENAME="your-cluster-node-name" +*/ +func TestDeploy(t *testing.T) { + flag.Parse() + + t.Run("Deploy", func(t *testing.T) { + t.Log(strings.Join([]string{ + "args:", + fmt.Sprintf("INPUTCERTPATH: %v", fInputCertPath), + fmt.Sprintf("INPUTKEYPATH: %v", fInputKeyPath), + fmt.Sprintf("APIURL: %v", fApiUrl), + fmt.Sprintf("APITOKEN: %v", fApiToken), + fmt.Sprintf("APITOKENSECRET: %v", fApiTokenSecret), + fmt.Sprintf("NODENAME: %v", fNodeName), + }, "\n")) + + deployer, err := provider.NewDeployer(&provider.DeployerConfig{ + ApiUrl: fApiUrl, + ApiToken: fApiToken, + ApiTokenSecret: fApiTokenSecret, + AllowInsecureConnections: true, + NodeName: fNodeName, + AutoRestart: true, + }) + if err != nil { + t.Errorf("err: %+v", err) + return + } + + fInputCertData, _ := os.ReadFile(fInputCertPath) + fInputKeyData, _ := os.ReadFile(fInputKeyPath) + res, err := deployer.Deploy(context.Background(), string(fInputCertData), string(fInputKeyData)) + if err != nil { + t.Errorf("err: %+v", err) + return + } + + t.Logf("ok: %v", res) + }) +} diff --git a/internal/pkg/core/deployer/providers/qiniu-cdn/qiniu_cdn.go b/internal/pkg/core/deployer/providers/qiniu-cdn/qiniu_cdn.go index e8166afd..573eeb94 100644 --- a/internal/pkg/core/deployer/providers/qiniu-cdn/qiniu_cdn.go +++ b/internal/pkg/core/deployer/providers/qiniu-cdn/qiniu_cdn.go @@ -1,17 +1,17 @@ -package qiniucdn +package qiniucdn import ( "context" + "fmt" "log/slog" "strings" - xerrors "github.com/pkg/errors" "github.com/qiniu/go-sdk/v7/auth" "github.com/usual2970/certimate/internal/pkg/core/deployer" "github.com/usual2970/certimate/internal/pkg/core/uploader" uploadersp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/qiniu-sslcert" - qiniusdk "github.com/usual2970/certimate/internal/pkg/vendors/qiniu-sdk" + qiniusdk "github.com/usual2970/certimate/internal/pkg/sdk3rd/qiniu" ) type DeployerConfig struct { @@ -44,7 +44,7 @@ func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { SecretKey: config.SecretKey, }) if err != nil { - return nil, xerrors.Wrap(err, "failed to create ssl uploader") + return nil, fmt.Errorf("failed to create ssl uploader: %w", err) } return &DeployerProvider{ @@ -65,11 +65,11 @@ func (d *DeployerProvider) WithLogger(logger *slog.Logger) deployer.Deployer { return d } -func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { +func (d *DeployerProvider) Deploy(ctx context.Context, certPEM string, privkeyPEM string) (*deployer.DeployResult, error) { // 上传证书到 CDN - upres, err := d.sslUploader.Upload(ctx, certPem, privkeyPem) + upres, err := d.sslUploader.Upload(ctx, certPEM, privkeyPEM) if err != nil { - return nil, xerrors.Wrap(err, "failed to upload certificate file") + return nil, fmt.Errorf("failed to upload certificate file: %w", err) } else { d.logger.Info("ssl certificate uploaded", slog.Any("result", upres)) } @@ -82,7 +82,7 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPe getDomainInfoResp, err := d.sdkClient.GetDomainInfo(context.TODO(), domain) d.logger.Debug("sdk request 'cdn.GetDomainInfo'", slog.String("request.domain", domain), slog.Any("response", getDomainInfoResp)) if err != nil { - return nil, xerrors.Wrap(err, "failed to execute sdk request 'cdn.GetDomainInfo'") + return nil, fmt.Errorf("failed to execute sdk request 'cdn.GetDomainInfo': %w", err) } // 判断域名是否已启用 HTTPS。如果已启用,修改域名证书;否则,启用 HTTPS @@ -91,13 +91,13 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPe enableDomainHttpsResp, err := d.sdkClient.EnableDomainHttps(context.TODO(), domain, upres.CertId, true, true) d.logger.Debug("sdk request 'cdn.EnableDomainHttps'", slog.String("request.domain", domain), slog.String("request.certId", upres.CertId), slog.Any("response", enableDomainHttpsResp)) if err != nil { - return nil, xerrors.Wrap(err, "failed to execute sdk request 'cdn.EnableDomainHttps'") + return nil, fmt.Errorf("failed to execute sdk request 'cdn.EnableDomainHttps': %w", err) } } else if getDomainInfoResp.Https.CertID != upres.CertId { modifyDomainHttpsConfResp, err := d.sdkClient.ModifyDomainHttpsConf(context.TODO(), domain, upres.CertId, getDomainInfoResp.Https.ForceHttps, getDomainInfoResp.Https.Http2Enable) d.logger.Debug("sdk request 'cdn.ModifyDomainHttpsConf'", slog.String("request.domain", domain), slog.String("request.certId", upres.CertId), slog.Any("response", modifyDomainHttpsConfResp)) if err != nil { - return nil, xerrors.Wrap(err, "failed to execute sdk request 'cdn.ModifyDomainHttpsConf'") + return nil, fmt.Errorf("failed to execute sdk request 'cdn.ModifyDomainHttpsConf': %w", err) } } 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 fffbfca5..51c1201c 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 @@ -1,4 +1,4 @@ -package qiniucdn_test +package qiniucdn_test import ( "context" diff --git a/internal/pkg/core/deployer/providers/qiniu-pili/qiniu_pili.go b/internal/pkg/core/deployer/providers/qiniu-pili/qiniu_pili.go index f684253b..db8d899e 100644 --- a/internal/pkg/core/deployer/providers/qiniu-pili/qiniu_pili.go +++ b/internal/pkg/core/deployer/providers/qiniu-pili/qiniu_pili.go @@ -1,10 +1,10 @@ -package qiniupili +package qiniupili import ( "context" + "fmt" "log/slog" - xerrors "github.com/pkg/errors" "github.com/qiniu/go-sdk/v7/pili" "github.com/usual2970/certimate/internal/pkg/core/deployer" @@ -44,7 +44,7 @@ func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { SecretKey: config.SecretKey, }) if err != nil { - return nil, xerrors.Wrap(err, "failed to create ssl uploader") + return nil, fmt.Errorf("failed to create ssl uploader: %w", err) } return &DeployerProvider{ @@ -65,11 +65,11 @@ func (d *DeployerProvider) WithLogger(logger *slog.Logger) deployer.Deployer { return d } -func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { +func (d *DeployerProvider) Deploy(ctx context.Context, certPEM string, privkeyPEM string) (*deployer.DeployResult, error) { // 上传证书到 CDN - upres, err := d.sslUploader.Upload(ctx, certPem, privkeyPem) + upres, err := d.sslUploader.Upload(ctx, certPEM, privkeyPEM) if err != nil { - return nil, xerrors.Wrap(err, "failed to upload certificate file") + return nil, fmt.Errorf("failed to upload certificate file: %w", err) } else { d.logger.Info("ssl certificate uploaded", slog.Any("result", upres)) } @@ -84,7 +84,7 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPe err = d.sdkClient.SetDomainCert(context.TODO(), setDomainCertReq) d.logger.Debug("sdk request 'pili.SetDomainCert'", slog.Any("request", setDomainCertReq)) if err != nil { - return nil, xerrors.Wrap(err, "failed to execute sdk request 'pili.SetDomainCert'") + return nil, fmt.Errorf("failed to execute sdk request 'pili.SetDomainCert': %w", err) } return &deployer.DeployResult{}, nil diff --git a/internal/pkg/core/deployer/providers/qiniu-pili/qiniu_pili_test.go b/internal/pkg/core/deployer/providers/qiniu-pili/qiniu_pili_test.go index 73e69855..1c165e0e 100644 --- a/internal/pkg/core/deployer/providers/qiniu-pili/qiniu_pili_test.go +++ b/internal/pkg/core/deployer/providers/qiniu-pili/qiniu_pili_test.go @@ -1,4 +1,4 @@ -package qiniupili_test +package qiniupili_test import ( "context" diff --git a/internal/pkg/core/deployer/providers/rainyun-rcdn/rainyun_rcdn.go b/internal/pkg/core/deployer/providers/rainyun-rcdn/rainyun_rcdn.go index d2b56e07..0b003bee 100644 --- a/internal/pkg/core/deployer/providers/rainyun-rcdn/rainyun_rcdn.go +++ b/internal/pkg/core/deployer/providers/rainyun-rcdn/rainyun_rcdn.go @@ -1,17 +1,16 @@ -package rainyunrcdn +package rainyunrcdn import ( "context" "errors" + "fmt" "log/slog" "strconv" - xerrors "github.com/pkg/errors" - "github.com/usual2970/certimate/internal/pkg/core/deployer" "github.com/usual2970/certimate/internal/pkg/core/uploader" uploadersp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/rainyun-sslcenter" - rainyunsdk "github.com/usual2970/certimate/internal/pkg/vendors/rainyun-sdk" + rainyunsdk "github.com/usual2970/certimate/internal/pkg/sdk3rd/rainyun" ) type DeployerConfig struct { @@ -39,14 +38,14 @@ func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { client, err := createSdkClient(config.ApiKey) if err != nil { - return nil, xerrors.Wrap(err, "failed to create sdk client") + return nil, fmt.Errorf("failed to create sdk client: %w", err) } uploader, err := uploadersp.NewUploader(&uploadersp.UploaderConfig{ ApiKey: config.ApiKey, }) if err != nil { - return nil, xerrors.Wrap(err, "failed to create ssl uploader") + return nil, fmt.Errorf("failed to create ssl uploader: %w", err) } return &DeployerProvider{ @@ -67,11 +66,11 @@ func (d *DeployerProvider) WithLogger(logger *slog.Logger) deployer.Deployer { return d } -func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { +func (d *DeployerProvider) Deploy(ctx context.Context, certPEM string, privkeyPEM string) (*deployer.DeployResult, error) { // 上传证书到 SSL 证书 - upres, err := d.sslUploader.Upload(ctx, certPem, privkeyPem) + upres, err := d.sslUploader.Upload(ctx, certPEM, privkeyPEM) if err != nil { - return nil, xerrors.Wrap(err, "failed to upload certificate file") + return nil, fmt.Errorf("failed to upload certificate file: %w", err) } else { d.logger.Info("ssl certificate uploaded", slog.Any("result", upres)) } @@ -86,7 +85,7 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPe rcdnInstanceSslBindResp, err := d.sdkClient.RcdnInstanceSslBind(d.config.InstanceId, rcdnInstanceSslBindReq) d.logger.Debug("sdk request 'rcdn.InstanceSslBind'", slog.Any("instanceId", d.config.InstanceId), slog.Any("request", rcdnInstanceSslBindReq), slog.Any("response", rcdnInstanceSslBindResp)) if err != nil { - return nil, xerrors.Wrap(err, "failed to execute sdk request 'rcdn.InstanceSslBind'") + return nil, fmt.Errorf("failed to execute sdk request 'rcdn.InstanceSslBind': %w", err) } return &deployer.DeployResult{}, nil diff --git a/internal/pkg/core/deployer/providers/rainyun-rcdn/rainyun_rcdn_test.go b/internal/pkg/core/deployer/providers/rainyun-rcdn/rainyun_rcdn_test.go index 7c3e90f7..fd81bffa 100644 --- a/internal/pkg/core/deployer/providers/rainyun-rcdn/rainyun_rcdn_test.go +++ b/internal/pkg/core/deployer/providers/rainyun-rcdn/rainyun_rcdn_test.go @@ -1,4 +1,4 @@ -package rainyunrcdn_test +package rainyunrcdn_test import ( "context" diff --git a/internal/pkg/core/deployer/providers/safeline/consts.go b/internal/pkg/core/deployer/providers/safeline/consts.go index a19e3866..1777a32e 100644 --- a/internal/pkg/core/deployer/providers/safeline/consts.go +++ b/internal/pkg/core/deployer/providers/safeline/consts.go @@ -1,4 +1,4 @@ -package safeline +package safeline type ResourceType string diff --git a/internal/pkg/core/deployer/providers/safeline/safeline.go b/internal/pkg/core/deployer/providers/safeline/safeline.go index 8079027f..f737fda9 100644 --- a/internal/pkg/core/deployer/providers/safeline/safeline.go +++ b/internal/pkg/core/deployer/providers/safeline/safeline.go @@ -1,4 +1,4 @@ -package safeline +package safeline import ( "context" @@ -8,10 +8,8 @@ import ( "log/slog" "net/url" - xerrors "github.com/pkg/errors" - "github.com/usual2970/certimate/internal/pkg/core/deployer" - safelinesdk "github.com/usual2970/certimate/internal/pkg/vendors/safeline-sdk" + safelinesdk "github.com/usual2970/certimate/internal/pkg/sdk3rd/safeline" ) type DeployerConfig struct { @@ -43,7 +41,7 @@ func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { client, err := createSdkClient(config.ApiUrl, config.ApiToken, config.AllowInsecureConnections) if err != nil { - return nil, xerrors.Wrap(err, "failed to create sdk client") + return nil, fmt.Errorf("failed to create sdk client: %w", err) } return &DeployerProvider{ @@ -62,22 +60,22 @@ func (d *DeployerProvider) WithLogger(logger *slog.Logger) deployer.Deployer { return d } -func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { +func (d *DeployerProvider) Deploy(ctx context.Context, certPEM string, privkeyPEM string) (*deployer.DeployResult, error) { // 根据部署资源类型决定部署方式 switch d.config.ResourceType { case RESOURCE_TYPE_CERTIFICATE: - if err := d.deployToCertificate(ctx, certPem, privkeyPem); err != nil { + if err := d.deployToCertificate(ctx, certPEM, privkeyPEM); err != nil { return nil, err } default: - return nil, fmt.Errorf("unsupported resource type: %s", d.config.ResourceType) + return nil, fmt.Errorf("unsupported resource type '%s'", d.config.ResourceType) } return &deployer.DeployResult{}, nil } -func (d *DeployerProvider) deployToCertificate(ctx context.Context, certPem string, privkeyPem string) error { +func (d *DeployerProvider) deployToCertificate(ctx context.Context, certPEM string, privkeyPEM string) error { if d.config.CertificateId == 0 { return errors.New("config `certificateId` is required") } @@ -87,20 +85,20 @@ func (d *DeployerProvider) deployToCertificate(ctx context.Context, certPem stri Id: d.config.CertificateId, Type: 2, Manual: &safelinesdk.UpdateCertificateRequestBodyManul{ - Crt: certPem, - Key: privkeyPem, + Crt: certPEM, + Key: privkeyPEM, }, } updateCertificateResp, err := d.sdkClient.UpdateCertificate(updateCertificateReq) d.logger.Debug("sdk request 'safeline.UpdateCertificate'", slog.Any("request", updateCertificateReq), slog.Any("response", updateCertificateResp)) if err != nil { - return xerrors.Wrap(err, "failed to execute sdk request 'safeline.UpdateCertificate'") + return fmt.Errorf("failed to execute sdk request 'safeline.UpdateCertificate': %w", err) } return nil } -func createSdkClient(apiUrl, apiToken string, allowInsecure bool) (*safelinesdk.Client, error) { +func createSdkClient(apiUrl, apiToken string, skipTlsVerify bool) (*safelinesdk.Client, error) { if _, err := url.Parse(apiUrl); err != nil { return nil, errors.New("invalid safeline api url") } @@ -110,7 +108,7 @@ func createSdkClient(apiUrl, apiToken string, allowInsecure bool) (*safelinesdk. } client := safelinesdk.NewClient(apiUrl, apiToken) - if allowInsecure { + if skipTlsVerify { client.WithTLSConfig(&tls.Config{InsecureSkipVerify: true}) } diff --git a/internal/pkg/core/deployer/providers/safeline/safeline_test.go b/internal/pkg/core/deployer/providers/safeline/safeline_test.go index 42c6313f..294086c8 100644 --- a/internal/pkg/core/deployer/providers/safeline/safeline_test.go +++ b/internal/pkg/core/deployer/providers/safeline/safeline_test.go @@ -1,4 +1,4 @@ -package safeline_test +package safeline_test import ( "context" @@ -56,7 +56,7 @@ func TestDeploy(t *testing.T) { ApiUrl: fApiUrl, ApiToken: fApiToken, AllowInsecureConnections: true, - ResourceType: provider.ResourceType("certificate"), + ResourceType: provider.RESOURCE_TYPE_CERTIFICATE, CertificateId: int32(fCertificateId), }) if err != nil { diff --git a/internal/pkg/core/deployer/providers/ssh/defines.go b/internal/pkg/core/deployer/providers/ssh/defines.go index 6f30871b..de1b255f 100644 --- a/internal/pkg/core/deployer/providers/ssh/defines.go +++ b/internal/pkg/core/deployer/providers/ssh/defines.go @@ -1,4 +1,4 @@ -package ssh +package ssh type OutputFormatType string diff --git a/internal/pkg/core/deployer/providers/ssh/ssh.go b/internal/pkg/core/deployer/providers/ssh/ssh.go index 3093ab42..4b8b433d 100644 --- a/internal/pkg/core/deployer/providers/ssh/ssh.go +++ b/internal/pkg/core/deployer/providers/ssh/ssh.go @@ -1,4 +1,4 @@ -package ssh +package ssh import ( "bytes" @@ -8,13 +8,12 @@ import ( "os" "path/filepath" - xerrors "github.com/pkg/errors" "github.com/pkg/sftp" "github.com/povsister/scp" "golang.org/x/crypto/ssh" "github.com/usual2970/certimate/internal/pkg/core/deployer" - "github.com/usual2970/certimate/internal/pkg/utils/certutil" + certutil "github.com/usual2970/certimate/internal/pkg/utils/cert" ) type DeployerConfig struct { @@ -85,7 +84,7 @@ func (d *DeployerProvider) WithLogger(logger *slog.Logger) deployer.Deployer { return d } -func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { +func (d *DeployerProvider) Deploy(ctx context.Context, certPEM string, privkeyPEM string) (*deployer.DeployResult, error) { // 连接 client, err := createSshClient( d.config.SshHost, @@ -96,7 +95,7 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPe d.config.SshKeyPassphrase, ) if err != nil { - return nil, xerrors.Wrap(err, "failed to create ssh client") + return nil, fmt.Errorf("failed to create ssh client: %w", err) } defer client.Close() @@ -107,49 +106,49 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPe stdout, stderr, err := execSshCommand(client, d.config.PreCommand) d.logger.Debug("run pre-command", slog.String("stdout", stdout), slog.String("stderr", stderr)) if err != nil { - return nil, xerrors.Wrapf(err, "failed to execute pre-command: stdout: %s, stderr: %s", stdout, stderr) + return nil, fmt.Errorf("failed to execute pre-command (stdout: %s, stderr: %s): %w ", stdout, stderr, err) } } // 上传证书和私钥文件 switch d.config.OutputFormat { case OUTPUT_FORMAT_PEM: - if err := writeFileString(client, d.config.UseSCP, d.config.OutputCertPath, certPem); err != nil { - return nil, xerrors.Wrap(err, "failed to upload certificate file") + if err := writeFileString(client, d.config.UseSCP, d.config.OutputCertPath, certPEM); err != nil { + return nil, fmt.Errorf("failed to upload certificate file: %w", err) } d.logger.Info("ssl certificate file uploaded", slog.String("path", d.config.OutputCertPath)) - if err := writeFileString(client, d.config.UseSCP, d.config.OutputKeyPath, privkeyPem); err != nil { - return nil, xerrors.Wrap(err, "failed to upload private key file") + if err := writeFileString(client, d.config.UseSCP, d.config.OutputKeyPath, privkeyPEM); err != nil { + return nil, fmt.Errorf("failed to upload private key file: %w", err) } d.logger.Info("ssl private key file uploaded", slog.String("path", d.config.OutputKeyPath)) case OUTPUT_FORMAT_PFX: - pfxData, err := certutil.TransformCertificateFromPEMToPFX(certPem, privkeyPem, d.config.PfxPassword) + pfxData, err := certutil.TransformCertificateFromPEMToPFX(certPEM, privkeyPEM, d.config.PfxPassword) if err != nil { - return nil, xerrors.Wrap(err, "failed to transform certificate to PFX") + return nil, fmt.Errorf("failed to transform certificate to PFX: %w", err) } d.logger.Info("ssl certificate transformed to pfx") if err := writeFile(client, d.config.UseSCP, d.config.OutputCertPath, pfxData); err != nil { - return nil, xerrors.Wrap(err, "failed to upload certificate file") + return nil, fmt.Errorf("failed to upload certificate file: %w", err) } d.logger.Info("ssl certificate file uploaded", slog.String("path", d.config.OutputCertPath)) case OUTPUT_FORMAT_JKS: - jksData, err := certutil.TransformCertificateFromPEMToJKS(certPem, privkeyPem, d.config.JksAlias, d.config.JksKeypass, d.config.JksStorepass) + jksData, err := certutil.TransformCertificateFromPEMToJKS(certPEM, privkeyPEM, d.config.JksAlias, d.config.JksKeypass, d.config.JksStorepass) if err != nil { - return nil, xerrors.Wrap(err, "failed to transform certificate to JKS") + return nil, fmt.Errorf("failed to transform certificate to JKS: %w", err) } d.logger.Info("ssl certificate transformed to jks") if err := writeFile(client, d.config.UseSCP, d.config.OutputCertPath, jksData); err != nil { - return nil, xerrors.Wrap(err, "failed to upload certificate file") + return nil, fmt.Errorf("failed to upload certificate file: %w", err) } d.logger.Info("ssl certificate file uploaded", slog.String("path", d.config.OutputCertPath)) default: - return nil, fmt.Errorf("unsupported output format: %s", d.config.OutputFormat) + return nil, fmt.Errorf("unsupported output format '%s'", d.config.OutputFormat) } // 执行后置命令 @@ -157,7 +156,7 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPe stdout, stderr, err := execSshCommand(client, d.config.PostCommand) d.logger.Debug("run post-command", slog.String("stdout", stdout), slog.String("stderr", stderr)) if err != nil { - return nil, xerrors.Wrapf(err, "failed to execute post-command, stdout: %s, stderr: %s", stdout, stderr) + return nil, fmt.Errorf("failed to execute post-command (stdout: %s, stderr: %s): %w ", stdout, stderr, err) } } @@ -212,7 +211,7 @@ func execSshCommand(sshCli *ssh.Client, command string) (string, string, error) session.Stderr = stderrBuf err = session.Run(command) if err != nil { - return stdoutBuf.String(), stderrBuf.String(), xerrors.Wrap(err, "failed to execute ssh command") + return stdoutBuf.String(), stderrBuf.String(), fmt.Errorf("failed to execute ssh command: %w", err) } return stdoutBuf.String(), stderrBuf.String(), nil @@ -241,13 +240,13 @@ func writeFileStringWithSCP(sshCli *ssh.Client, path string, content string) err func writeFileWithSCP(sshCli *ssh.Client, path string, data []byte) error { scpCli, err := scp.NewClientFromExistingSSH(sshCli, &scp.ClientOption{}) if err != nil { - return xerrors.Wrap(err, "failed to create scp client") + return fmt.Errorf("failed to create scp client: %w", err) } reader := bytes.NewReader(data) err = scpCli.CopyToRemote(reader, path, &scp.FileTransferOption{}) if err != nil { - return xerrors.Wrap(err, "failed to write to remote file") + return fmt.Errorf("failed to write to remote file: %w", err) } return nil @@ -260,23 +259,23 @@ func writeFileStringWithSFTP(sshCli *ssh.Client, path string, content string) er func writeFileWithSFTP(sshCli *ssh.Client, path string, data []byte) error { sftpCli, err := sftp.NewClient(sshCli) if err != nil { - return xerrors.Wrap(err, "failed to create sftp client") + return fmt.Errorf("failed to create sftp client: %w", err) } defer sftpCli.Close() if err := sftpCli.MkdirAll(filepath.Dir(path)); err != nil { - return xerrors.Wrap(err, "failed to create remote directory") + return fmt.Errorf("failed to create remote directory: %w", err) } file, err := sftpCli.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_TRUNC) if err != nil { - return xerrors.Wrap(err, "failed to open remote file") + return fmt.Errorf("failed to open remote file: %w", err) } defer file.Close() _, err = file.Write(data) if err != nil { - return xerrors.Wrap(err, "failed to write to remote file") + return fmt.Errorf("failed to write to remote file: %w", err) } return nil diff --git a/internal/pkg/core/deployer/providers/ssh/ssh_test.go b/internal/pkg/core/deployer/providers/ssh/ssh_test.go index 8312d680..b63471d1 100644 --- a/internal/pkg/core/deployer/providers/ssh/ssh_test.go +++ b/internal/pkg/core/deployer/providers/ssh/ssh_test.go @@ -1,4 +1,4 @@ -package ssh_test +package ssh_test import ( "context" diff --git a/internal/pkg/core/deployer/providers/tencentcloud-cdn/tencentcloud_cdn.go b/internal/pkg/core/deployer/providers/tencentcloud-cdn/tencentcloud_cdn.go index 38e58c7b..01f71d9e 100644 --- a/internal/pkg/core/deployer/providers/tencentcloud-cdn/tencentcloud_cdn.go +++ b/internal/pkg/core/deployer/providers/tencentcloud-cdn/tencentcloud_cdn.go @@ -1,11 +1,11 @@ -package tencentcloudcdn +package tencentcloudcdn import ( "context" + "fmt" "log/slog" "strings" - xerrors "github.com/pkg/errors" tccdn "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cdn/v20180606" "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common" "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common/profile" @@ -47,7 +47,7 @@ func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { clients, err := createSdkClients(config.SecretId, config.SecretKey) if err != nil { - return nil, xerrors.Wrap(err, "failed to create sdk clients") + return nil, fmt.Errorf("failed to create sdk clients: %w", err) } uploader, err := uploadersp.NewUploader(&uploadersp.UploaderConfig{ @@ -55,7 +55,7 @@ func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { SecretKey: config.SecretKey, }) if err != nil { - return nil, xerrors.Wrap(err, "failed to create ssl uploader") + return nil, fmt.Errorf("failed to create ssl uploader: %w", err) } return &DeployerProvider{ @@ -76,11 +76,11 @@ func (d *DeployerProvider) WithLogger(logger *slog.Logger) deployer.Deployer { return d } -func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { +func (d *DeployerProvider) Deploy(ctx context.Context, certPEM string, privkeyPEM string) (*deployer.DeployResult, error) { // 上传证书到 SSL - upres, err := d.sslUploader.Upload(ctx, certPem, privkeyPem) + upres, err := d.sslUploader.Upload(ctx, certPEM, privkeyPEM) if err != nil { - return nil, xerrors.Wrap(err, "failed to upload certificate file") + return nil, fmt.Errorf("failed to upload certificate file: %w", err) } else { d.logger.Info("ssl certificate uploaded", slog.Any("result", upres)) } @@ -130,7 +130,7 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPe deployCertificateInstanceResp, err := d.sdkClients.SSL.DeployCertificateInstance(deployCertificateInstanceReq) d.logger.Debug("sdk request 'ssl.DeployCertificateInstance'", slog.Any("request", deployCertificateInstanceReq), slog.Any("response", deployCertificateInstanceResp)) if err != nil { - return nil, xerrors.Wrap(err, "failed to execute sdk request 'ssl.DeployCertificateInstance'") + return nil, fmt.Errorf("failed to execute sdk request 'ssl.DeployCertificateInstance': %w", err) } } @@ -146,7 +146,7 @@ func (d *DeployerProvider) getDomainsByCertificateId(cloudCertId string) ([]stri describeCertDomainsResp, err := d.sdkClients.CDN.DescribeCertDomains(describeCertDomainsReq) d.logger.Debug("sdk request 'cdn.DescribeCertDomains'", slog.Any("request", describeCertDomainsReq), slog.Any("response", describeCertDomainsResp)) if err != nil { - return nil, xerrors.Wrap(err, "failed to execute sdk request 'cdn.DescribeCertDomains'") + return nil, fmt.Errorf("failed to execute sdk request 'cdn.DescribeCertDomains': %w", err) } domains := make([]string, 0) @@ -168,7 +168,7 @@ func (d *DeployerProvider) getDeployedDomainsByCertificateId(cloudCertId string) describeDeployedResourcesResp, err := d.sdkClients.SSL.DescribeDeployedResources(describeDeployedResourcesReq) d.logger.Debug("sdk request 'cdn.DescribeDeployedResources'", slog.Any("request", describeDeployedResourcesReq), slog.Any("response", describeDeployedResourcesResp)) if err != nil { - return nil, xerrors.Wrap(err, "failed to execute sdk request 'cdn.DescribeDeployedResources'") + return nil, fmt.Errorf("failed to execute sdk request 'cdn.DescribeDeployedResources': %w", err) } domains := make([]string, 0) 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 0361e17b..95285930 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 @@ -1,4 +1,4 @@ -package tencentcloudcdn_test +package tencentcloudcdn_test import ( "context" diff --git a/internal/pkg/core/deployer/providers/tencentcloud-clb/consts.go b/internal/pkg/core/deployer/providers/tencentcloud-clb/consts.go index 7d72d5d3..2728e730 100644 --- a/internal/pkg/core/deployer/providers/tencentcloud-clb/consts.go +++ b/internal/pkg/core/deployer/providers/tencentcloud-clb/consts.go @@ -1,4 +1,4 @@ -package tencentcloudclb +package tencentcloudclb type ResourceType string diff --git a/internal/pkg/core/deployer/providers/tencentcloud-clb/tencentcloud_clb.go b/internal/pkg/core/deployer/providers/tencentcloud-clb/tencentcloud_clb.go index e8edb9cc..0c2f8902 100644 --- a/internal/pkg/core/deployer/providers/tencentcloud-clb/tencentcloud_clb.go +++ b/internal/pkg/core/deployer/providers/tencentcloud-clb/tencentcloud_clb.go @@ -1,4 +1,4 @@ -package tencentcloudclb +package tencentcloudclb import ( "context" @@ -6,7 +6,6 @@ import ( "fmt" "log/slog" - xerrors "github.com/pkg/errors" tcclb "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/clb/v20180317" "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common" "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common/profile" @@ -58,7 +57,7 @@ func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { clients, err := createSdkClients(config.SecretId, config.SecretKey, config.Region) if err != nil { - return nil, xerrors.Wrap(err, "failed to create sdk clients") + return nil, fmt.Errorf("failed to create sdk clients: %w", err) } uploader, err := uploadersp.NewUploader(&uploadersp.UploaderConfig{ @@ -66,7 +65,7 @@ func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { SecretKey: config.SecretKey, }) if err != nil { - return nil, xerrors.Wrap(err, "failed to create ssl uploader") + return nil, fmt.Errorf("failed to create ssl uploader: %w", err) } return &DeployerProvider{ @@ -87,11 +86,11 @@ func (d *DeployerProvider) WithLogger(logger *slog.Logger) deployer.Deployer { return d } -func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { +func (d *DeployerProvider) Deploy(ctx context.Context, certPEM string, privkeyPEM string) (*deployer.DeployResult, error) { // 上传证书到 SSL - upres, err := d.sslUploader.Upload(ctx, certPem, privkeyPem) + upres, err := d.sslUploader.Upload(ctx, certPEM, privkeyPEM) if err != nil { - return nil, xerrors.Wrap(err, "failed to upload certificate file") + return nil, fmt.Errorf("failed to upload certificate file: %w", err) } else { d.logger.Info("ssl certificate uploaded", slog.Any("result", upres)) } @@ -119,7 +118,7 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPe } default: - return nil, fmt.Errorf("unsupported resource type: %s", d.config.ResourceType) + return nil, fmt.Errorf("unsupported resource type '%s'", d.config.ResourceType) } return &deployer.DeployResult{}, nil @@ -149,7 +148,7 @@ func (d *DeployerProvider) deployViaSslService(ctx context.Context, cloudCertId deployCertificateInstanceResp, err := d.sdkClients.SSL.DeployCertificateInstance(deployCertificateInstanceReq) d.logger.Debug("sdk request 'ssl.DeployCertificateInstance'", slog.Any("request", deployCertificateInstanceReq), slog.Any("response", deployCertificateInstanceResp)) if err != nil { - return xerrors.Wrap(err, "failed to execute sdk request 'ssl.DeployCertificateInstance'") + return fmt.Errorf("failed to execute sdk request 'ssl.DeployCertificateInstance': %w", err) } return nil @@ -168,7 +167,7 @@ func (d *DeployerProvider) deployToLoadbalancer(ctx context.Context, cloudCertId describeListenersResp, err := d.sdkClients.CLB.DescribeListeners(describeListenersReq) d.logger.Debug("sdk request 'clb.DescribeListeners'", slog.Any("request", describeListenersReq), slog.Any("response", describeListenersResp)) if err != nil { - return xerrors.Wrap(err, "failed to execute sdk request 'clb.DescribeListeners'") + return fmt.Errorf("failed to execute sdk request 'clb.DescribeListeners': %w", err) } else { if describeListenersResp.Response.Listeners != nil { for _, listener := range describeListenersResp.Response.Listeners { @@ -189,8 +188,13 @@ func (d *DeployerProvider) deployToLoadbalancer(ctx context.Context, cloudCertId var errs []error for _, listenerId := range listenerIds { - if err := d.modifyListenerCertificate(ctx, d.config.LoadbalancerId, listenerId, cloudCertId); err != nil { - errs = append(errs, err) + select { + case <-ctx.Done(): + return ctx.Err() + default: + if err := d.modifyListenerCertificate(ctx, d.config.LoadbalancerId, listenerId, cloudCertId); err != nil { + errs = append(errs, err) + } } } @@ -242,7 +246,7 @@ func (d *DeployerProvider) deployToRuleDomain(ctx context.Context, cloudCertId s modifyDomainAttributesResp, err := d.sdkClients.CLB.ModifyDomainAttributes(modifyDomainAttributesReq) d.logger.Debug("sdk request 'clb.ModifyDomainAttributes'", slog.Any("request", modifyDomainAttributesReq), slog.Any("response", modifyDomainAttributesResp)) if err != nil { - return xerrors.Wrap(err, "failed to execute sdk request 'clb.ModifyDomainAttributes'") + return fmt.Errorf("failed to execute sdk request 'clb.ModifyDomainAttributes': %w", err) } return nil @@ -257,7 +261,7 @@ func (d *DeployerProvider) modifyListenerCertificate(ctx context.Context, cloudL describeListenersResp, err := d.sdkClients.CLB.DescribeListeners(describeListenersReq) d.logger.Debug("sdk request 'clb.DescribeListeners'", slog.Any("request", describeListenersReq), slog.Any("response", describeListenersResp)) if err != nil { - return xerrors.Wrap(err, "failed to execute sdk request 'clb.DescribeListeners'") + return fmt.Errorf("failed to execute sdk request 'clb.DescribeListeners': %w", err) } else if len(describeListenersResp.Response.Listeners) == 0 { return errors.New("listener not found") } @@ -277,7 +281,7 @@ func (d *DeployerProvider) modifyListenerCertificate(ctx context.Context, cloudL modifyListenerResp, err := d.sdkClients.CLB.ModifyListener(modifyListenerReq) d.logger.Debug("sdk request 'clb.ModifyListener'", slog.Any("request", modifyListenerReq), slog.Any("response", modifyListenerResp)) if err != nil { - return xerrors.Wrap(err, "failed to execute sdk request 'clb.ModifyListener'") + return fmt.Errorf("failed to execute sdk request 'clb.ModifyListener': %w", err) } return nil 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 0aeb1e7c..59cd9b8d 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 @@ -1,4 +1,4 @@ -package tencentcloudclb_test +package tencentcloudclb_test import ( "context" diff --git a/internal/pkg/core/deployer/providers/tencentcloud-cos/tencentcloud_cos.go b/internal/pkg/core/deployer/providers/tencentcloud-cos/tencentcloud_cos.go index 7f1992e9..0949c5a3 100644 --- a/internal/pkg/core/deployer/providers/tencentcloud-cos/tencentcloud_cos.go +++ b/internal/pkg/core/deployer/providers/tencentcloud-cos/tencentcloud_cos.go @@ -1,4 +1,4 @@ -package tencentcloudcos +package tencentcloudcos import ( "context" @@ -6,7 +6,6 @@ import ( "fmt" "log/slog" - xerrors "github.com/pkg/errors" "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common" "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common/profile" tcssl "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/ssl/v20191205" @@ -45,7 +44,7 @@ func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { client, err := createSdkClient(config.SecretId, config.SecretKey, config.Region) if err != nil { - return nil, xerrors.Wrap(err, "failed to create sdk client") + return nil, fmt.Errorf("failed to create sdk client: %w", err) } uploader, err := uploadersp.NewUploader(&uploadersp.UploaderConfig{ @@ -53,7 +52,7 @@ func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { SecretKey: config.SecretKey, }) if err != nil { - return nil, xerrors.Wrap(err, "failed to create ssl uploader") + return nil, fmt.Errorf("failed to create ssl uploader: %w", err) } return &DeployerProvider{ @@ -74,7 +73,7 @@ func (d *DeployerProvider) WithLogger(logger *slog.Logger) deployer.Deployer { return d } -func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { +func (d *DeployerProvider) Deploy(ctx context.Context, certPEM string, privkeyPEM string) (*deployer.DeployResult, error) { if d.config.Bucket == "" { return nil, errors.New("config `bucket` is required") } @@ -83,9 +82,9 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPe } // 上传证书到 SSL - upres, err := d.sslUploader.Upload(ctx, certPem, privkeyPem) + upres, err := d.sslUploader.Upload(ctx, certPEM, privkeyPEM) if err != nil { - return nil, xerrors.Wrap(err, "failed to upload certificate file") + return nil, fmt.Errorf("failed to upload certificate file: %w", err) } else { d.logger.Info("ssl certificate uploaded", slog.Any("result", upres)) } @@ -100,7 +99,7 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPe deployCertificateInstanceResp, err := d.sdkClient.DeployCertificateInstance(deployCertificateInstanceReq) d.logger.Debug("sdk request 'ssl.DeployCertificateInstance'", slog.Any("request", deployCertificateInstanceReq), slog.Any("response", deployCertificateInstanceResp)) if err != nil { - return nil, xerrors.Wrap(err, "failed to execute sdk request 'ssl.DeployCertificateInstance'") + return nil, fmt.Errorf("failed to execute sdk request 'ssl.DeployCertificateInstance': %w", err) } return &deployer.DeployResult{}, nil 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 ab29a893..24e41d47 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 @@ -1,4 +1,4 @@ -package tencentcloudcos_test +package tencentcloudcos_test import ( "context" diff --git a/internal/pkg/core/deployer/providers/tencentcloud-css/tencentcloud_css.go b/internal/pkg/core/deployer/providers/tencentcloud-css/tencentcloud_css.go index e29e25ea..7de626d9 100644 --- a/internal/pkg/core/deployer/providers/tencentcloud-css/tencentcloud_css.go +++ b/internal/pkg/core/deployer/providers/tencentcloud-css/tencentcloud_css.go @@ -1,10 +1,10 @@ -package tencentcloudcss +package tencentcloudcss import ( "context" + "fmt" "log/slog" - xerrors "github.com/pkg/errors" "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common" "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common/profile" tclive "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/live/v20180801" @@ -39,7 +39,7 @@ func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { client, err := createSdkClient(config.SecretId, config.SecretKey) if err != nil { - return nil, xerrors.Wrap(err, "failed to create sdk client") + return nil, fmt.Errorf("failed to create sdk client: %w", err) } uploader, err := uploadersp.NewUploader(&uploadersp.UploaderConfig{ @@ -47,7 +47,7 @@ func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { SecretKey: config.SecretKey, }) if err != nil { - return nil, xerrors.Wrap(err, "failed to create ssl uploader") + return nil, fmt.Errorf("failed to create ssl uploader: %w", err) } return &DeployerProvider{ @@ -68,11 +68,11 @@ func (d *DeployerProvider) WithLogger(logger *slog.Logger) deployer.Deployer { return d } -func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { +func (d *DeployerProvider) Deploy(ctx context.Context, certPEM string, privkeyPEM string) (*deployer.DeployResult, error) { // 上传证书到 SSL - upres, err := d.sslUploader.Upload(ctx, certPem, privkeyPem) + upres, err := d.sslUploader.Upload(ctx, certPEM, privkeyPEM) if err != nil { - return nil, xerrors.Wrap(err, "failed to upload certificate file") + return nil, fmt.Errorf("failed to upload certificate file: %w", err) } else { d.logger.Info("ssl certificate uploaded", slog.Any("result", upres)) } @@ -90,7 +90,7 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPe modifyLiveDomainCertBindingsResp, err := d.sdkClient.ModifyLiveDomainCertBindings(modifyLiveDomainCertBindingsReq) d.logger.Debug("sdk request 'live.ModifyLiveDomainCertBindings'", slog.Any("request", modifyLiveDomainCertBindingsReq), slog.Any("response", modifyLiveDomainCertBindingsResp)) if err != nil { - return nil, xerrors.Wrap(err, "failed to execute sdk request 'live.ModifyLiveDomainCertBindings'") + return nil, fmt.Errorf("failed to execute sdk request 'live.ModifyLiveDomainCertBindings': %w", err) } return &deployer.DeployResult{}, nil diff --git a/internal/pkg/core/deployer/providers/tencentcloud-css/tencentcloud_css_test.go b/internal/pkg/core/deployer/providers/tencentcloud-css/tencentcloud_css_test.go index 92127b3b..4aaa344a 100644 --- a/internal/pkg/core/deployer/providers/tencentcloud-css/tencentcloud_css_test.go +++ b/internal/pkg/core/deployer/providers/tencentcloud-css/tencentcloud_css_test.go @@ -1,4 +1,4 @@ -package tencentcloudcss_test +package tencentcloudcss_test import ( "context" diff --git a/internal/pkg/core/deployer/providers/tencentcloud-ecdn/tencentcloud_ecdn.go b/internal/pkg/core/deployer/providers/tencentcloud-ecdn/tencentcloud_ecdn.go index beb5a043..ebe87025 100644 --- a/internal/pkg/core/deployer/providers/tencentcloud-ecdn/tencentcloud_ecdn.go +++ b/internal/pkg/core/deployer/providers/tencentcloud-ecdn/tencentcloud_ecdn.go @@ -1,11 +1,11 @@ -package tencentcloudecdn +package tencentcloudecdn import ( "context" + "fmt" "log/slog" "strings" - xerrors "github.com/pkg/errors" tccdn "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cdn/v20180606" "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common" "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common/profile" @@ -46,7 +46,7 @@ func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { clients, err := createSdkClients(config.SecretId, config.SecretKey) if err != nil { - return nil, xerrors.Wrap(err, "failed to create sdk clients") + return nil, fmt.Errorf("failed to create sdk clients: %w", err) } uploader, err := uploadersp.NewUploader(&uploadersp.UploaderConfig{ @@ -54,7 +54,7 @@ func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { SecretKey: config.SecretKey, }) if err != nil { - return nil, xerrors.Wrap(err, "failed to create ssl uploader") + return nil, fmt.Errorf("failed to create ssl uploader: %w", err) } return &DeployerProvider{ @@ -75,11 +75,11 @@ func (d *DeployerProvider) WithLogger(logger *slog.Logger) deployer.Deployer { return d } -func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { +func (d *DeployerProvider) Deploy(ctx context.Context, certPEM string, privkeyPEM string) (*deployer.DeployResult, error) { // 上传证书到 SSL - upres, err := d.sslUploader.Upload(ctx, certPem, privkeyPem) + upres, err := d.sslUploader.Upload(ctx, certPEM, privkeyPEM) if err != nil { - return nil, xerrors.Wrap(err, "failed to upload certificate file") + return nil, fmt.Errorf("failed to upload certificate file: %w", err) } else { d.logger.Info("ssl certificate uploaded", slog.Any("result", upres)) } @@ -113,7 +113,7 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPe deployCertificateInstanceResp, err := d.sdkClients.SSL.DeployCertificateInstance(deployCertificateInstanceReq) d.logger.Debug("sdk request 'ssl.DeployCertificateInstance'", slog.Any("request", deployCertificateInstanceReq), slog.Any("response", deployCertificateInstanceResp)) if err != nil { - return nil, xerrors.Wrap(err, "failed to execute sdk request 'ssl.DeployCertificateInstance'") + return nil, fmt.Errorf("failed to execute sdk request 'ssl.DeployCertificateInstance': %w", err) } } @@ -129,7 +129,7 @@ func (d *DeployerProvider) getDomainsByCertificateId(cloudCertId string) ([]stri describeCertDomainsResp, err := d.sdkClients.CDN.DescribeCertDomains(describeCertDomainsReq) d.logger.Debug("sdk request 'cdn.DescribeCertDomains'", slog.Any("request", describeCertDomainsReq), slog.Any("response", describeCertDomainsResp)) if err != nil { - return nil, xerrors.Wrap(err, "failed to execute sdk request 'cdn.DescribeCertDomains'") + return nil, fmt.Errorf("failed to execute sdk request 'cdn.DescribeCertDomains': %w", err) } domains := make([]string, 0) 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 da03a7ab..1cffd10d 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 @@ -1,4 +1,4 @@ -package tencentcloudecdn_test +package tencentcloudecdn_test import ( "context" diff --git a/internal/pkg/core/deployer/providers/tencentcloud-eo/tencentcloud_eo.go b/internal/pkg/core/deployer/providers/tencentcloud-eo/tencentcloud_eo.go index b6ebbf94..919339bb 100644 --- a/internal/pkg/core/deployer/providers/tencentcloud-eo/tencentcloud_eo.go +++ b/internal/pkg/core/deployer/providers/tencentcloud-eo/tencentcloud_eo.go @@ -1,11 +1,11 @@ -package tencentcloudeo +package tencentcloudeo import ( "context" "errors" + "fmt" "log/slog" - xerrors "github.com/pkg/errors" "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common" "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common/profile" tcssl "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/ssl/v20191205" @@ -48,7 +48,7 @@ func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { clients, err := createSdkClients(config.SecretId, config.SecretKey) if err != nil { - return nil, xerrors.Wrap(err, "failed to create sdk clients") + return nil, fmt.Errorf("failed to create sdk clients: %w", err) } uploader, err := uploadersp.NewUploader(&uploadersp.UploaderConfig{ @@ -56,7 +56,7 @@ func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { SecretKey: config.SecretKey, }) if err != nil { - return nil, xerrors.Wrap(err, "failed to create ssl uploader") + return nil, fmt.Errorf("failed to create ssl uploader: %w", err) } return &DeployerProvider{ @@ -77,15 +77,15 @@ func (d *DeployerProvider) WithLogger(logger *slog.Logger) deployer.Deployer { return d } -func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { +func (d *DeployerProvider) Deploy(ctx context.Context, certPEM string, privkeyPEM string) (*deployer.DeployResult, error) { if d.config.ZoneId == "" { return nil, errors.New("config `zoneId` is required") } // 上传证书到 SSL - upres, err := d.sslUploader.Upload(ctx, certPem, privkeyPem) + upres, err := d.sslUploader.Upload(ctx, certPEM, privkeyPEM) if err != nil { - return nil, xerrors.Wrap(err, "failed to upload certificate file") + return nil, fmt.Errorf("failed to upload certificate file: %w", err) } else { d.logger.Info("ssl certificate uploaded", slog.Any("result", upres)) } @@ -100,7 +100,7 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPe modifyHostsCertificateResp, err := d.sdkClients.TEO.ModifyHostsCertificate(modifyHostsCertificateReq) d.logger.Debug("sdk request 'teo.ModifyHostsCertificate'", slog.Any("request", modifyHostsCertificateReq), slog.Any("response", modifyHostsCertificateResp)) if err != nil { - return nil, xerrors.Wrap(err, "failed to execute sdk request 'teo.ModifyHostsCertificate'") + return nil, fmt.Errorf("failed to execute sdk request 'teo.ModifyHostsCertificate': %w", err) } return &deployer.DeployResult{}, nil 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 8e5b70fe..81c3b9da 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 @@ -1,4 +1,4 @@ -package tencentcloudeo_test +package tencentcloudeo_test import ( "context" diff --git a/internal/pkg/core/deployer/providers/tencentcloud-scf/tencentcloud_scf.go b/internal/pkg/core/deployer/providers/tencentcloud-scf/tencentcloud_scf.go index 9d8512c2..bc8d8696 100644 --- a/internal/pkg/core/deployer/providers/tencentcloud-scf/tencentcloud_scf.go +++ b/internal/pkg/core/deployer/providers/tencentcloud-scf/tencentcloud_scf.go @@ -1,10 +1,10 @@ -package tencentcloudscf +package tencentcloudscf import ( "context" + "fmt" "log/slog" - xerrors "github.com/pkg/errors" "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common" "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common/profile" tcscf "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/scf/v20180416" @@ -41,7 +41,7 @@ func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { client, err := createSdkClient(config.SecretId, config.SecretKey, config.Region) if err != nil { - return nil, xerrors.Wrap(err, "failed to create sdk client") + return nil, fmt.Errorf("failed to create sdk client: %w", err) } uploader, err := uploadersp.NewUploader(&uploadersp.UploaderConfig{ @@ -49,7 +49,7 @@ func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { SecretKey: config.SecretKey, }) if err != nil { - return nil, xerrors.Wrap(err, "failed to create ssl uploader") + return nil, fmt.Errorf("failed to create ssl uploader: %w", err) } return &DeployerProvider{ @@ -70,7 +70,7 @@ func (d *DeployerProvider) WithLogger(logger *slog.Logger) deployer.Deployer { return d } -func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { +func (d *DeployerProvider) Deploy(ctx context.Context, certPEM string, privkeyPEM string) (*deployer.DeployResult, error) { // 查看云函数自定义域名详情 // REF: https://cloud.tencent.com/document/product/583/111924 getCustomDomainReq := tcscf.NewGetCustomDomainRequest() @@ -78,13 +78,13 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPe getCustomDomainResp, err := d.sdkClient.GetCustomDomain(getCustomDomainReq) d.logger.Debug("sdk request 'scf.GetCustomDomain'", slog.Any("request", getCustomDomainReq), slog.Any("response", getCustomDomainResp)) if err != nil { - return nil, xerrors.Wrap(err, "failed to execute sdk request 'scf.GetCustomDomain'") + return nil, fmt.Errorf("failed to execute sdk request 'scf.GetCustomDomain': %w", err) } // 上传证书到 SSL - upres, err := d.sslUploader.Upload(ctx, certPem, privkeyPem) + upres, err := d.sslUploader.Upload(ctx, certPEM, privkeyPEM) if err != nil { - return nil, xerrors.Wrap(err, "failed to upload certificate file") + return nil, fmt.Errorf("failed to upload certificate file: %w", err) } else { d.logger.Info("ssl certificate uploaded", slog.Any("result", upres)) } @@ -100,7 +100,7 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPe updateCustomDomainResp, err := d.sdkClient.UpdateCustomDomain(updateCustomDomainReq) d.logger.Debug("sdk request 'scf.UpdateCustomDomain'", slog.Any("request", updateCustomDomainReq), slog.Any("response", updateCustomDomainResp)) if err != nil { - return nil, xerrors.Wrap(err, "failed to execute sdk request 'scf.UpdateCustomDomain'") + return nil, fmt.Errorf("failed to execute sdk request 'scf.UpdateCustomDomain': %w", err) } return &deployer.DeployResult{}, nil diff --git a/internal/pkg/core/deployer/providers/tencentcloud-scf/tencentcloud_scf_test.go b/internal/pkg/core/deployer/providers/tencentcloud-scf/tencentcloud_scf_test.go index 84a1ad79..f0aa0cfe 100644 --- a/internal/pkg/core/deployer/providers/tencentcloud-scf/tencentcloud_scf_test.go +++ b/internal/pkg/core/deployer/providers/tencentcloud-scf/tencentcloud_scf_test.go @@ -1,4 +1,4 @@ -package tencentcloudscf_test +package tencentcloudscf_test import ( "context" diff --git a/internal/pkg/core/deployer/providers/tencentcloud-ssl-deploy/tencentcloud_ssl_deploy.go b/internal/pkg/core/deployer/providers/tencentcloud-ssl-deploy/tencentcloud_ssl_deploy.go index 8e06920a..5f13660d 100644 --- a/internal/pkg/core/deployer/providers/tencentcloud-ssl-deploy/tencentcloud_ssl_deploy.go +++ b/internal/pkg/core/deployer/providers/tencentcloud-ssl-deploy/tencentcloud_ssl_deploy.go @@ -1,4 +1,4 @@ -package tencentcloudssldeploy +package tencentcloudssldeploy import ( "context" @@ -7,7 +7,6 @@ import ( "log/slog" "time" - xerrors "github.com/pkg/errors" "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common" "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common/profile" tcssl "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/ssl/v20191205" @@ -46,7 +45,7 @@ func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { client, err := createSdkClient(config.SecretId, config.SecretKey, config.Region) if err != nil { - return nil, xerrors.Wrap(err, "failed to create sdk client") + return nil, fmt.Errorf("failed to create sdk client: %w", err) } uploader, err := uploadersp.NewUploader(&uploadersp.UploaderConfig{ @@ -54,7 +53,7 @@ func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { SecretKey: config.SecretKey, }) if err != nil { - return nil, xerrors.Wrap(err, "failed to create ssl uploader") + return nil, fmt.Errorf("failed to create ssl uploader: %w", err) } return &DeployerProvider{ @@ -75,7 +74,7 @@ func (d *DeployerProvider) WithLogger(logger *slog.Logger) deployer.Deployer { return d } -func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { +func (d *DeployerProvider) Deploy(ctx context.Context, certPEM string, privkeyPEM string) (*deployer.DeployResult, error) { if d.config.ResourceType == "" { return nil, errors.New("config `resourceType` is required") } @@ -84,9 +83,9 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPe } // 上传证书到 SSL - upres, err := d.sslUploader.Upload(ctx, certPem, privkeyPem) + upres, err := d.sslUploader.Upload(ctx, certPEM, privkeyPEM) if err != nil { - return nil, xerrors.Wrap(err, "failed to upload certificate file") + return nil, fmt.Errorf("failed to upload certificate file: %w", err) } else { d.logger.Info("ssl certificate uploaded", slog.Any("result", upres)) } @@ -101,7 +100,7 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPe deployCertificateInstanceResp, err := d.sdkClient.DeployCertificateInstance(deployCertificateInstanceReq) d.logger.Debug("sdk request 'ssl.DeployCertificateInstance'", slog.Any("request", deployCertificateInstanceReq), slog.Any("response", deployCertificateInstanceResp)) if err != nil { - return nil, xerrors.Wrap(err, "failed to execute sdk request 'ssl.DeployCertificateInstance'") + return nil, fmt.Errorf("failed to execute sdk request 'ssl.DeployCertificateInstance': %w", err) } else if deployCertificateInstanceResp.Response == nil || deployCertificateInstanceResp.Response.DeployRecordId == nil { return nil, errors.New("failed to create deploy record") } @@ -109,8 +108,10 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPe // 循环获取部署任务详情,等待任务状态变更 // REF: https://cloud.tencent.com.cn/document/api/400/91658 for { - if ctx.Err() != nil { + select { + case <-ctx.Done(): return nil, ctx.Err() + default: } describeHostDeployRecordDetailReq := tcssl.NewDescribeHostDeployRecordDetailRequest() @@ -119,7 +120,7 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPe describeHostDeployRecordDetailResp, err := d.sdkClient.DescribeHostDeployRecordDetail(describeHostDeployRecordDetailReq) d.logger.Debug("sdk request 'ssl.DescribeHostDeployRecordDetail'", slog.Any("request", describeHostDeployRecordDetailReq), slog.Any("response", describeHostDeployRecordDetailResp)) if err != nil { - return nil, xerrors.Wrap(err, "failed to execute sdk request 'ssl.DescribeHostDeployRecordDetail'") + return nil, fmt.Errorf("failed to execute sdk request 'ssl.DescribeHostDeployRecordDetail': %w", err) } if describeHostDeployRecordDetailResp.Response.TotalCount == nil { diff --git a/internal/pkg/core/deployer/providers/tencentcloud-ssl/tencentcloud_ssl.go b/internal/pkg/core/deployer/providers/tencentcloud-ssl/tencentcloud_ssl.go index 8f8676de..5fbdb7c6 100644 --- a/internal/pkg/core/deployer/providers/tencentcloud-ssl/tencentcloud_ssl.go +++ b/internal/pkg/core/deployer/providers/tencentcloud-ssl/tencentcloud_ssl.go @@ -1,11 +1,10 @@ -package tencentcloudssl +package tencentcloudssl import ( "context" + "fmt" "log/slog" - xerrors "github.com/pkg/errors" - "github.com/usual2970/certimate/internal/pkg/core/deployer" "github.com/usual2970/certimate/internal/pkg/core/uploader" uploadersp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/tencentcloud-ssl" @@ -36,7 +35,7 @@ func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { SecretKey: config.SecretKey, }) if err != nil { - return nil, xerrors.Wrap(err, "failed to create ssl uploader") + return nil, fmt.Errorf("failed to create ssl uploader: %w", err) } return &DeployerProvider{ @@ -56,11 +55,11 @@ func (d *DeployerProvider) WithLogger(logger *slog.Logger) deployer.Deployer { return d } -func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { +func (d *DeployerProvider) Deploy(ctx context.Context, certPEM string, privkeyPEM string) (*deployer.DeployResult, error) { // 上传证书到 SSL - upres, err := d.sslUploader.Upload(ctx, certPem, privkeyPem) + upres, err := d.sslUploader.Upload(ctx, certPEM, privkeyPEM) if err != nil { - return nil, xerrors.Wrap(err, "failed to upload certificate file") + return nil, fmt.Errorf("failed to upload certificate file: %w", err) } else { d.logger.Info("ssl certificate uploaded", slog.Any("result", upres)) } diff --git a/internal/pkg/core/deployer/providers/tencentcloud-vod/tencentcloud_vod.go b/internal/pkg/core/deployer/providers/tencentcloud-vod/tencentcloud_vod.go index 6a32eb62..1b8553c5 100644 --- a/internal/pkg/core/deployer/providers/tencentcloud-vod/tencentcloud_vod.go +++ b/internal/pkg/core/deployer/providers/tencentcloud-vod/tencentcloud_vod.go @@ -1,10 +1,10 @@ -package tencentcloudvod +package tencentcloudvod import ( "context" + "fmt" "log/slog" - xerrors "github.com/pkg/errors" "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common" "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common/profile" tcvod "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/vod/v20180717" @@ -41,7 +41,7 @@ func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { client, err := createSdkClient(config.SecretId, config.SecretKey) if err != nil { - return nil, xerrors.Wrap(err, "failed to create sdk client") + return nil, fmt.Errorf("failed to create sdk client: %w", err) } uploader, err := uploadersp.NewUploader(&uploadersp.UploaderConfig{ @@ -49,7 +49,7 @@ func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { SecretKey: config.SecretKey, }) if err != nil { - return nil, xerrors.Wrap(err, "failed to create ssl uploader") + return nil, fmt.Errorf("failed to create ssl uploader: %w", err) } return &DeployerProvider{ @@ -70,11 +70,11 @@ func (d *DeployerProvider) WithLogger(logger *slog.Logger) deployer.Deployer { return d } -func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { +func (d *DeployerProvider) Deploy(ctx context.Context, certPEM string, privkeyPEM string) (*deployer.DeployResult, error) { // 上传证书到 SSL - upres, err := d.sslUploader.Upload(ctx, certPem, privkeyPem) + upres, err := d.sslUploader.Upload(ctx, certPEM, privkeyPEM) if err != nil { - return nil, xerrors.Wrap(err, "failed to upload certificate file") + return nil, fmt.Errorf("failed to upload certificate file: %w", err) } else { d.logger.Info("ssl certificate uploaded", slog.Any("result", upres)) } @@ -91,7 +91,7 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPe setVodDomainCertificateResp, err := d.sdkClient.SetVodDomainCertificate(setVodDomainCertificateReq) d.logger.Debug("sdk request 'vod.SetVodDomainCertificate'", slog.Any("request", setVodDomainCertificateReq), slog.Any("response", setVodDomainCertificateResp)) if err != nil { - return nil, xerrors.Wrap(err, "failed to execute sdk request 'vod.SetVodDomainCertificate'") + return nil, fmt.Errorf("failed to execute sdk request 'vod.SetVodDomainCertificate': %w", err) } return &deployer.DeployResult{}, nil diff --git a/internal/pkg/core/deployer/providers/tencentcloud-vod/tencentcloud_vod_test.go b/internal/pkg/core/deployer/providers/tencentcloud-vod/tencentcloud_vod_test.go index ffd085cd..52382808 100644 --- a/internal/pkg/core/deployer/providers/tencentcloud-vod/tencentcloud_vod_test.go +++ b/internal/pkg/core/deployer/providers/tencentcloud-vod/tencentcloud_vod_test.go @@ -1,4 +1,4 @@ -package tencentcloudvod_test +package tencentcloudvod_test import ( "context" diff --git a/internal/pkg/core/deployer/providers/tencentcloud-waf/tencentcloud_waf.go b/internal/pkg/core/deployer/providers/tencentcloud-waf/tencentcloud_waf.go index 2921fb84..18380289 100644 --- a/internal/pkg/core/deployer/providers/tencentcloud-waf/tencentcloud_waf.go +++ b/internal/pkg/core/deployer/providers/tencentcloud-waf/tencentcloud_waf.go @@ -1,11 +1,11 @@ -package tencentcloudwaf +package tencentcloudwaf import ( "context" "errors" + "fmt" "log/slog" - xerrors "github.com/pkg/errors" "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common" "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common/profile" tcwaf "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/waf/v20180125" @@ -46,7 +46,7 @@ func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { client, err := createSdkClient(config.SecretId, config.SecretKey, config.Region) if err != nil { - return nil, xerrors.Wrap(err, "failed to create sdk client") + return nil, fmt.Errorf("failed to create sdk client: %w", err) } uploader, err := uploadersp.NewUploader(&uploadersp.UploaderConfig{ @@ -54,7 +54,7 @@ func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { SecretKey: config.SecretKey, }) if err != nil { - return nil, xerrors.Wrap(err, "failed to create ssl uploader") + return nil, fmt.Errorf("failed to create ssl uploader: %w", err) } return &DeployerProvider{ @@ -75,7 +75,7 @@ func (d *DeployerProvider) WithLogger(logger *slog.Logger) deployer.Deployer { return d } -func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { +func (d *DeployerProvider) Deploy(ctx context.Context, certPEM string, privkeyPEM string) (*deployer.DeployResult, error) { if d.config.Domain == "" { return nil, errors.New("config `domain` is required") } @@ -87,9 +87,9 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPe } // 上传证书到 SSL - upres, err := d.sslUploader.Upload(ctx, certPem, privkeyPem) + upres, err := d.sslUploader.Upload(ctx, certPEM, privkeyPEM) if err != nil { - return nil, xerrors.Wrap(err, "failed to upload certificate file") + return nil, fmt.Errorf("failed to upload certificate file: %w", err) } else { d.logger.Info("ssl certificate uploaded", slog.Any("result", upres)) } @@ -103,7 +103,7 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPe describeDomainDetailsSaasResp, err := d.sdkClient.DescribeDomainDetailsSaas(describeDomainDetailsSaasReq) d.logger.Debug("sdk request 'waf.DescribeDomainDetailsSaas'", slog.Any("request", describeDomainDetailsSaasReq), slog.Any("response", describeDomainDetailsSaasResp)) if err != nil { - return nil, xerrors.Wrap(err, "failed to execute sdk request 'waf.DescribeDomainDetailsSaas'") + return nil, fmt.Errorf("failed to execute sdk request 'waf.DescribeDomainDetailsSaas': %w", err) } // 编辑 SaaS 型 WAF 域名 @@ -117,7 +117,7 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPe modifySpartaProtectionResp, err := d.sdkClient.ModifySpartaProtection(modifySpartaProtectionReq) d.logger.Debug("sdk request 'waf.ModifySpartaProtection'", slog.Any("request", modifySpartaProtectionReq), slog.Any("response", modifySpartaProtectionResp)) if err != nil { - return nil, xerrors.Wrap(err, "failed to execute sdk request 'waf.ModifySpartaProtection'") + return nil, fmt.Errorf("failed to execute sdk request 'waf.ModifySpartaProtection': %w", err) } return &deployer.DeployResult{}, nil diff --git a/internal/pkg/core/deployer/providers/tencentcloud-waf/tencentcloud_waf_test.go b/internal/pkg/core/deployer/providers/tencentcloud-waf/tencentcloud_waf_test.go index 42ba1ffe..8cb63b7d 100644 --- a/internal/pkg/core/deployer/providers/tencentcloud-waf/tencentcloud_waf_test.go +++ b/internal/pkg/core/deployer/providers/tencentcloud-waf/tencentcloud_waf_test.go @@ -1,4 +1,4 @@ -package tencentcloudwaf_test +package tencentcloudwaf_test import ( "context" diff --git a/internal/pkg/core/deployer/providers/ucloud-ucdn/ucloud_ucdn.go b/internal/pkg/core/deployer/providers/ucloud-ucdn/ucloud_ucdn.go index 82be501c..5f90b943 100644 --- a/internal/pkg/core/deployer/providers/ucloud-ucdn/ucloud_ucdn.go +++ b/internal/pkg/core/deployer/providers/ucloud-ucdn/ucloud_ucdn.go @@ -1,12 +1,12 @@ -package uclouducdn +package uclouducdn import ( "context" "errors" + "fmt" "log/slog" "strconv" - xerrors "github.com/pkg/errors" "github.com/ucloud/ucloud-sdk-go/services/ucdn" "github.com/ucloud/ucloud-sdk-go/ucloud" "github.com/ucloud/ucloud-sdk-go/ucloud/auth" @@ -43,7 +43,7 @@ func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { client, err := createSdkClient(config.PrivateKey, config.PublicKey) if err != nil { - return nil, xerrors.Wrap(err, "failed to create sdk client") + return nil, fmt.Errorf("failed to create sdk client: %w", err) } uploader, err := uploadersp.NewUploader(&uploadersp.UploaderConfig{ @@ -52,7 +52,7 @@ func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { ProjectId: config.ProjectId, }) if err != nil { - return nil, xerrors.Wrap(err, "failed to create ssl uploader") + return nil, fmt.Errorf("failed to create ssl uploader: %w", err) } return &DeployerProvider{ @@ -73,11 +73,11 @@ func (d *DeployerProvider) WithLogger(logger *slog.Logger) deployer.Deployer { return d } -func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { +func (d *DeployerProvider) Deploy(ctx context.Context, certPEM string, privkeyPEM string) (*deployer.DeployResult, error) { // 上传证书到 USSL - upres, err := d.sslUploader.Upload(ctx, certPem, privkeyPem) + upres, err := d.sslUploader.Upload(ctx, certPEM, privkeyPEM) if err != nil { - return nil, xerrors.Wrap(err, "failed to upload certificate file") + return nil, fmt.Errorf("failed to upload certificate file: %w", err) } else { d.logger.Info("ssl certificate uploaded", slog.Any("result", upres)) } @@ -92,7 +92,7 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPe getUcdnDomainConfigResp, err := d.sdkClient.GetUcdnDomainConfig(getUcdnDomainConfigReq) d.logger.Debug("sdk request 'ucdn.GetUcdnDomainConfig'", slog.Any("request", getUcdnDomainConfigReq), slog.Any("response", getUcdnDomainConfigResp)) if err != nil { - return nil, xerrors.Wrap(err, "failed to execute sdk request 'ucdn.GetUcdnDomainConfig'") + return nil, fmt.Errorf("failed to execute sdk request 'ucdn.GetUcdnDomainConfig': %w", err) } else if len(getUcdnDomainConfigResp.DomainList) == 0 { return nil, errors.New("no domain found") } @@ -114,7 +114,7 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPe updateUcdnDomainHttpsConfigV2Resp, err := d.sdkClient.UpdateUcdnDomainHttpsConfigV2(updateUcdnDomainHttpsConfigV2Req) d.logger.Debug("sdk request 'ucdn.UpdateUcdnDomainHttpsConfigV2'", slog.Any("request", updateUcdnDomainHttpsConfigV2Req), slog.Any("response", updateUcdnDomainHttpsConfigV2Resp)) if err != nil { - return nil, xerrors.Wrap(err, "failed to execute sdk request 'ucdn.UpdateUcdnDomainHttpsConfigV2'") + return nil, fmt.Errorf("failed to execute sdk request 'ucdn.UpdateUcdnDomainHttpsConfigV2': %w", err) } return &deployer.DeployResult{}, nil diff --git a/internal/pkg/core/deployer/providers/ucloud-ucdn/ucloud_ucdn_test.go b/internal/pkg/core/deployer/providers/ucloud-ucdn/ucloud_ucdn_test.go index fc952da1..f49a026a 100644 --- a/internal/pkg/core/deployer/providers/ucloud-ucdn/ucloud_ucdn_test.go +++ b/internal/pkg/core/deployer/providers/ucloud-ucdn/ucloud_ucdn_test.go @@ -1,4 +1,4 @@ -package uclouducdn_test +package uclouducdn_test import ( "context" diff --git a/internal/pkg/core/deployer/providers/ucloud-us3/ucloud_us3.go b/internal/pkg/core/deployer/providers/ucloud-us3/ucloud_us3.go index d3a68868..5564e6a8 100644 --- a/internal/pkg/core/deployer/providers/ucloud-us3/ucloud_us3.go +++ b/internal/pkg/core/deployer/providers/ucloud-us3/ucloud_us3.go @@ -1,17 +1,17 @@ -package ucloudus3 +package ucloudus3 import ( "context" + "fmt" "log/slog" - xerrors "github.com/pkg/errors" "github.com/ucloud/ucloud-sdk-go/ucloud" "github.com/ucloud/ucloud-sdk-go/ucloud/auth" "github.com/usual2970/certimate/internal/pkg/core/deployer" "github.com/usual2970/certimate/internal/pkg/core/uploader" uploadersp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/ucloud-ussl" - usdkFile "github.com/usual2970/certimate/internal/pkg/vendors/ucloud-sdk/ufile" + usdkFile "github.com/usual2970/certimate/internal/pkg/sdk3rd/ucloud/ufile" ) type DeployerConfig struct { @@ -45,7 +45,7 @@ func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { client, err := createSdkClient(config.PrivateKey, config.PublicKey, config.Region) if err != nil { - return nil, xerrors.Wrap(err, "failed to create sdk client") + return nil, fmt.Errorf("failed to create sdk client: %w", err) } uploader, err := uploadersp.NewUploader(&uploadersp.UploaderConfig{ @@ -54,7 +54,7 @@ func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { ProjectId: config.ProjectId, }) if err != nil { - return nil, xerrors.Wrap(err, "failed to create ssl uploader") + return nil, fmt.Errorf("failed to create ssl uploader: %w", err) } return &DeployerProvider{ @@ -75,11 +75,11 @@ func (d *DeployerProvider) WithLogger(logger *slog.Logger) deployer.Deployer { return d } -func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { +func (d *DeployerProvider) Deploy(ctx context.Context, certPEM string, privkeyPEM string) (*deployer.DeployResult, error) { // 上传证书到 USSL - upres, err := d.sslUploader.Upload(ctx, certPem, privkeyPem) + upres, err := d.sslUploader.Upload(ctx, certPEM, privkeyPEM) if err != nil { - return nil, xerrors.Wrap(err, "failed to upload certificate file") + return nil, fmt.Errorf("failed to upload certificate file: %w", err) } else { d.logger.Info("ssl certificate uploaded", slog.Any("result", upres)) } @@ -97,7 +97,7 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPe addUFileSSLCertResp, err := d.sdkClient.AddUFileSSLCert(addUFileSSLCertReq) d.logger.Debug("sdk request 'us3.AddUFileSSLCert'", slog.Any("request", addUFileSSLCertReq), slog.Any("response", addUFileSSLCertResp)) if err != nil { - return nil, xerrors.Wrap(err, "failed to execute sdk request 'us3.AddUFileSSLCert'") + return nil, fmt.Errorf("failed to execute sdk request 'us3.AddUFileSSLCert': %w", err) } return &deployer.DeployResult{}, nil diff --git a/internal/pkg/core/deployer/providers/ucloud-us3/ucloud_us3_test.go b/internal/pkg/core/deployer/providers/ucloud-us3/ucloud_us3_test.go index 52f78664..9977ee42 100644 --- a/internal/pkg/core/deployer/providers/ucloud-us3/ucloud_us3_test.go +++ b/internal/pkg/core/deployer/providers/ucloud-us3/ucloud_us3_test.go @@ -1,4 +1,4 @@ -package ucloudus3_test +package ucloudus3_test import ( "context" diff --git a/internal/pkg/core/deployer/providers/upyun-cdn/upyun_cdn.go b/internal/pkg/core/deployer/providers/upyun-cdn/upyun_cdn.go index 84d6cafb..4c9987a3 100644 --- a/internal/pkg/core/deployer/providers/upyun-cdn/upyun_cdn.go +++ b/internal/pkg/core/deployer/providers/upyun-cdn/upyun_cdn.go @@ -1,17 +1,17 @@ -package upyuncdn +package upyuncdn import ( "context" "errors" + "fmt" "log/slog" - xerrors "github.com/pkg/errors" "golang.org/x/exp/slices" "github.com/usual2970/certimate/internal/pkg/core/deployer" "github.com/usual2970/certimate/internal/pkg/core/uploader" uploadersp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/upyun-ssl" - upyunsdk "github.com/usual2970/certimate/internal/pkg/vendors/upyun-sdk/console" + upyunsdk "github.com/usual2970/certimate/internal/pkg/sdk3rd/upyun/console" ) type DeployerConfig struct { @@ -39,7 +39,7 @@ func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { client, err := createSdkClient(config.Username, config.Password) if err != nil { - return nil, xerrors.Wrap(err, "failed to create sdk client") + return nil, fmt.Errorf("failed to create sdk client: %w", err) } uploader, err := uploadersp.NewUploader(&uploadersp.UploaderConfig{ @@ -47,7 +47,7 @@ func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { Password: config.Password, }) if err != nil { - return nil, xerrors.Wrap(err, "failed to create ssl uploader") + return nil, fmt.Errorf("failed to create ssl uploader: %w", err) } return &DeployerProvider{ @@ -68,11 +68,11 @@ func (d *DeployerProvider) WithLogger(logger *slog.Logger) deployer.Deployer { return d } -func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { +func (d *DeployerProvider) Deploy(ctx context.Context, certPEM string, privkeyPEM string) (*deployer.DeployResult, error) { // 上传证书到 SSL - upres, err := d.sslUploader.Upload(ctx, certPem, privkeyPem) + upres, err := d.sslUploader.Upload(ctx, certPEM, privkeyPEM) if err != nil { - return nil, xerrors.Wrap(err, "failed to upload certificate file") + return nil, fmt.Errorf("failed to upload certificate file: %w", err) } else { d.logger.Info("ssl certificate uploaded", slog.Any("result", upres)) } @@ -81,7 +81,7 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPe getHttpsServiceManagerResp, err := d.sdkClient.GetHttpsServiceManager(d.config.Domain) d.logger.Debug("sdk request 'console.GetHttpsServiceManager'", slog.String("request.domain", d.config.Domain), slog.Any("response", getHttpsServiceManagerResp)) if err != nil { - return nil, xerrors.Wrap(err, "failed to execute sdk request 'console.GetHttpsServiceManager'") + return nil, fmt.Errorf("failed to execute sdk request 'console.GetHttpsServiceManager': %w", err) } // 判断域名是否已启用 HTTPS。如果已启用,迁移域名证书;否则,设置新证书 @@ -98,7 +98,7 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPe updateHttpsCertificateManagerResp, err := d.sdkClient.UpdateHttpsCertificateManager(updateHttpsCertificateManagerReq) d.logger.Debug("sdk request 'console.EnableDomainHttps'", slog.Any("request", updateHttpsCertificateManagerReq), slog.Any("response", updateHttpsCertificateManagerResp)) if err != nil { - return nil, xerrors.Wrap(err, "failed to execute sdk request 'console.UpdateHttpsCertificateManager'") + return nil, fmt.Errorf("failed to execute sdk request 'console.UpdateHttpsCertificateManager': %w", err) } } else if getHttpsServiceManagerResp.Data.Domains[lastCertIndex].CertificateId != upres.CertId { migrateHttpsDomainReq := &upyunsdk.MigrateHttpsDomainRequest{ @@ -108,7 +108,7 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPe migrateHttpsDomainResp, err := d.sdkClient.MigrateHttpsDomain(migrateHttpsDomainReq) d.logger.Debug("sdk request 'console.MigrateHttpsDomain'", slog.Any("request", migrateHttpsDomainReq), slog.Any("response", migrateHttpsDomainResp)) if err != nil { - return nil, xerrors.Wrap(err, "failed to execute sdk request 'console.MigrateHttpsDomain'") + return nil, fmt.Errorf("failed to execute sdk request 'console.MigrateHttpsDomain': %w", err) } } diff --git a/internal/pkg/core/deployer/providers/upyun-cdn/upyun_cdn_test.go b/internal/pkg/core/deployer/providers/upyun-cdn/upyun_cdn_test.go index 7e9e16ff..9fd32fd4 100644 --- a/internal/pkg/core/deployer/providers/upyun-cdn/upyun_cdn_test.go +++ b/internal/pkg/core/deployer/providers/upyun-cdn/upyun_cdn_test.go @@ -1,4 +1,4 @@ -package upyuncdn_test +package upyuncdn_test import ( "context" diff --git a/internal/pkg/core/deployer/providers/volcengine-alb/consts.go b/internal/pkg/core/deployer/providers/volcengine-alb/consts.go index aba1182c..11944379 100644 --- a/internal/pkg/core/deployer/providers/volcengine-alb/consts.go +++ b/internal/pkg/core/deployer/providers/volcengine-alb/consts.go @@ -1,4 +1,4 @@ -package volcenginealb +package volcenginealb type ResourceType string diff --git a/internal/pkg/core/deployer/providers/volcengine-alb/volcengine_alb.go b/internal/pkg/core/deployer/providers/volcengine-alb/volcengine_alb.go index ceba0952..b17ae729 100644 --- a/internal/pkg/core/deployer/providers/volcengine-alb/volcengine_alb.go +++ b/internal/pkg/core/deployer/providers/volcengine-alb/volcengine_alb.go @@ -1,4 +1,4 @@ -package volcenginealb +package volcenginealb import ( "context" @@ -6,7 +6,6 @@ import ( "fmt" "log/slog" - xerrors "github.com/pkg/errors" vealb "github.com/volcengine/volcengine-go-sdk/service/alb" ve "github.com/volcengine/volcengine-go-sdk/volcengine" vesession "github.com/volcengine/volcengine-go-sdk/volcengine/session" @@ -14,7 +13,7 @@ import ( "github.com/usual2970/certimate/internal/pkg/core/deployer" "github.com/usual2970/certimate/internal/pkg/core/uploader" uploadersp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/volcengine-certcenter" - "github.com/usual2970/certimate/internal/pkg/utils/sliceutil" + sliceutil "github.com/usual2970/certimate/internal/pkg/utils/slice" ) type DeployerConfig struct { @@ -53,7 +52,7 @@ func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { client, err := createSdkClient(config.AccessKeyId, config.AccessKeySecret, config.Region) if err != nil { - return nil, xerrors.Wrap(err, "failed to create sdk client") + return nil, fmt.Errorf("failed to create sdk client: %w", err) } uploader, err := uploadersp.NewUploader(&uploadersp.UploaderConfig{ @@ -62,7 +61,7 @@ func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { Region: config.Region, }) if err != nil { - return nil, xerrors.Wrap(err, "failed to create ssl uploader") + return nil, fmt.Errorf("failed to create ssl uploader: %w", err) } return &DeployerProvider{ @@ -83,11 +82,11 @@ func (d *DeployerProvider) WithLogger(logger *slog.Logger) deployer.Deployer { return d } -func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { +func (d *DeployerProvider) Deploy(ctx context.Context, certPEM string, privkeyPEM string) (*deployer.DeployResult, error) { // 上传证书到证书中心 - upres, err := d.sslUploader.Upload(ctx, certPem, privkeyPem) + upres, err := d.sslUploader.Upload(ctx, certPEM, privkeyPEM) if err != nil { - return nil, xerrors.Wrap(err, "failed to upload certificate file") + return nil, fmt.Errorf("failed to upload certificate file: %w", err) } else { d.logger.Info("ssl certificate uploaded", slog.Any("result", upres)) } @@ -105,7 +104,7 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPe } default: - return nil, fmt.Errorf("unsupported resource type: %s", d.config.ResourceType) + return nil, fmt.Errorf("unsupported resource type '%s'", d.config.ResourceType) } return &deployer.DeployResult{}, nil @@ -124,7 +123,7 @@ func (d *DeployerProvider) deployToLoadbalancer(ctx context.Context, cloudCertId describeLoadBalancerAttributesResp, err := d.sdkClient.DescribeLoadBalancerAttributes(describeLoadBalancerAttributesReq) d.logger.Debug("sdk request 'alb.DescribeLoadBalancerAttributes'", slog.Any("request", describeLoadBalancerAttributesReq), slog.Any("response", describeLoadBalancerAttributesResp)) if err != nil { - return xerrors.Wrap(err, "failed to execute sdk request 'alb.DescribeLoadBalancerAttributes'") + return fmt.Errorf("failed to execute sdk request 'alb.DescribeLoadBalancerAttributes': %w", err) } // 查询 HTTPS 监听器列表 @@ -133,6 +132,12 @@ func (d *DeployerProvider) deployToLoadbalancer(ctx context.Context, cloudCertId describeListenersPageSize := int64(100) describeListenersPageNumber := int64(1) for { + select { + case <-ctx.Done(): + return ctx.Err() + default: + } + describeListenersReq := &vealb.DescribeListenersInput{ LoadBalancerId: ve.String(d.config.LoadbalancerId), Protocol: ve.String("HTTPS"), @@ -142,7 +147,7 @@ func (d *DeployerProvider) deployToLoadbalancer(ctx context.Context, cloudCertId describeListenersResp, err := d.sdkClient.DescribeListeners(describeListenersReq) d.logger.Debug("sdk request 'alb.DescribeListeners'", slog.Any("request", describeListenersReq), slog.Any("response", describeListenersResp)) if err != nil { - return xerrors.Wrap(err, "failed to execute sdk request 'alb.DescribeListeners'") + return fmt.Errorf("failed to execute sdk request 'alb.DescribeListeners': %w", err) } for _, listener := range describeListenersResp.Listeners { @@ -164,8 +169,13 @@ func (d *DeployerProvider) deployToLoadbalancer(ctx context.Context, cloudCertId var errs []error for _, listenerId := range listenerIds { - if err := d.updateListenerCertificate(ctx, listenerId, cloudCertId); err != nil { - errs = append(errs, err) + select { + case <-ctx.Done(): + return ctx.Err() + default: + if err := d.updateListenerCertificate(ctx, listenerId, cloudCertId); err != nil { + errs = append(errs, err) + } } } @@ -198,7 +208,7 @@ func (d *DeployerProvider) updateListenerCertificate(ctx context.Context, cloudL describeListenerAttributesResp, err := d.sdkClient.DescribeListenerAttributes(describeListenerAttributesReq) d.logger.Debug("sdk request 'alb.DescribeListenerAttributes'", slog.Any("request", describeListenerAttributesReq), slog.Any("response", describeListenerAttributesResp)) if err != nil { - return xerrors.Wrap(err, "failed to execute sdk request 'alb.DescribeListenerAttributes'") + return fmt.Errorf("failed to execute sdk request 'alb.DescribeListenerAttributes': %w", err) } if d.config.Domain == "" { @@ -214,7 +224,7 @@ func (d *DeployerProvider) updateListenerCertificate(ctx context.Context, cloudL modifyListenerAttributesResp, err := d.sdkClient.ModifyListenerAttributes(modifyListenerAttributesReq) d.logger.Debug("sdk request 'alb.ModifyListenerAttributes'", slog.Any("request", modifyListenerAttributesReq), slog.Any("response", modifyListenerAttributesResp)) if err != nil { - return xerrors.Wrap(err, "failed to execute sdk request 'alb.ModifyListenerAttributes'") + return fmt.Errorf("failed to execute sdk request 'alb.ModifyListenerAttributes': %w", err) } } else { // 指定 SNI,需部署到扩展域名 @@ -243,7 +253,7 @@ func (d *DeployerProvider) updateListenerCertificate(ctx context.Context, cloudL modifyListenerAttributesResp, err := d.sdkClient.ModifyListenerAttributes(modifyListenerAttributesReq) d.logger.Debug("sdk request 'alb.ModifyListenerAttributes'", slog.Any("request", modifyListenerAttributesReq), slog.Any("response", modifyListenerAttributesResp)) if err != nil { - return xerrors.Wrap(err, "failed to execute sdk request 'alb.ModifyListenerAttributes'") + return fmt.Errorf("failed to execute sdk request 'alb.ModifyListenerAttributes': %w", err) } } diff --git a/internal/pkg/core/deployer/providers/volcengine-alb/volcengine_alb_test.go b/internal/pkg/core/deployer/providers/volcengine-alb/volcengine_alb_test.go index 23a79200..18999397 100644 --- a/internal/pkg/core/deployer/providers/volcengine-alb/volcengine_alb_test.go +++ b/internal/pkg/core/deployer/providers/volcengine-alb/volcengine_alb_test.go @@ -1,4 +1,4 @@ -package volcenginealb_test +package volcenginealb_test import ( "context" diff --git a/internal/pkg/core/deployer/providers/volcengine-cdn/volcengine_cdn.go b/internal/pkg/core/deployer/providers/volcengine-cdn/volcengine_cdn.go index fe0844d9..e9b2c325 100644 --- a/internal/pkg/core/deployer/providers/volcengine-cdn/volcengine_cdn.go +++ b/internal/pkg/core/deployer/providers/volcengine-cdn/volcengine_cdn.go @@ -1,12 +1,12 @@ -package volcenginecdn +package volcenginecdn import ( "context" "errors" + "fmt" "log/slog" "strings" - xerrors "github.com/pkg/errors" vecdn "github.com/volcengine/volc-sdk-golang/service/cdn" "github.com/usual2970/certimate/internal/pkg/core/deployer" @@ -46,7 +46,7 @@ func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { AccessKeySecret: config.AccessKeySecret, }) if err != nil { - return nil, xerrors.Wrap(err, "failed to create ssl uploader") + return nil, fmt.Errorf("failed to create ssl uploader: %w", err) } return &DeployerProvider{ @@ -67,11 +67,11 @@ func (d *DeployerProvider) WithLogger(logger *slog.Logger) deployer.Deployer { return d } -func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { +func (d *DeployerProvider) Deploy(ctx context.Context, certPEM string, privkeyPEM string) (*deployer.DeployResult, error) { // 上传证书到 CDN - upres, err := d.sslUploader.Upload(ctx, certPem, privkeyPem) + upres, err := d.sslUploader.Upload(ctx, certPEM, privkeyPEM) if err != nil { - return nil, xerrors.Wrap(err, "failed to upload certificate file") + return nil, fmt.Errorf("failed to upload certificate file: %w", err) } else { d.logger.Info("ssl certificate uploaded", slog.Any("result", upres)) } @@ -86,7 +86,7 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPe describeCertConfigResp, err := d.sdkClient.DescribeCertConfig(describeCertConfigReq) d.logger.Debug("sdk request 'cdn.DescribeCertConfig'", slog.Any("request", describeCertConfigReq), slog.Any("response", describeCertConfigResp)) if err != nil { - return nil, xerrors.Wrap(err, "failed to execute sdk request 'cdn.DescribeCertConfig'") + return nil, fmt.Errorf("failed to execute sdk request 'cdn.DescribeCertConfig': %w", err) } if describeCertConfigResp.Result.CertNotConfig != nil { @@ -117,16 +117,21 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPe var errs []error for _, domain := range domains { - // 关联证书与加速域名 - // REF: https://www.volcengine.com/docs/6454/125712 - batchDeployCertReq := &vecdn.BatchDeployCertRequest{ - CertId: upres.CertId, - Domain: domain, - } - batchDeployCertResp, err := d.sdkClient.BatchDeployCert(batchDeployCertReq) - d.logger.Debug("sdk request 'cdn.BatchDeployCert'", slog.Any("request", batchDeployCertReq), slog.Any("response", batchDeployCertResp)) - if err != nil { - errs = append(errs, err) + select { + case <-ctx.Done(): + return nil, ctx.Err() + default: + // 关联证书与加速域名 + // REF: https://www.volcengine.com/docs/6454/125712 + batchDeployCertReq := &vecdn.BatchDeployCertRequest{ + CertId: upres.CertId, + Domain: domain, + } + batchDeployCertResp, err := d.sdkClient.BatchDeployCert(batchDeployCertReq) + d.logger.Debug("sdk request 'cdn.BatchDeployCert'", slog.Any("request", batchDeployCertReq), slog.Any("response", batchDeployCertResp)) + if err != nil { + errs = append(errs, err) + } } } 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 c94b9828..1535deae 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 @@ -1,4 +1,4 @@ -package volcenginecdn_test +package volcenginecdn_test import ( "context" diff --git a/internal/pkg/core/deployer/providers/volcengine-certcenter/volcengine_certcenter.go b/internal/pkg/core/deployer/providers/volcengine-certcenter/volcengine_certcenter.go index a8062641..3989a000 100644 --- a/internal/pkg/core/deployer/providers/volcengine-certcenter/volcengine_certcenter.go +++ b/internal/pkg/core/deployer/providers/volcengine-certcenter/volcengine_certcenter.go @@ -1,11 +1,10 @@ -package volcenginecertcenter +package volcenginecertcenter import ( "context" + "fmt" "log/slog" - xerrors "github.com/pkg/errors" - "github.com/usual2970/certimate/internal/pkg/core/deployer" "github.com/usual2970/certimate/internal/pkg/core/uploader" uploadersp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/volcengine-certcenter" @@ -39,7 +38,7 @@ func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { Region: config.Region, }) if err != nil { - return nil, xerrors.Wrap(err, "failed to create ssl uploader") + return nil, fmt.Errorf("failed to create ssl uploader: %w", err) } return &DeployerProvider{ @@ -59,11 +58,11 @@ func (d *DeployerProvider) WithLogger(logger *slog.Logger) deployer.Deployer { return d } -func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { +func (d *DeployerProvider) Deploy(ctx context.Context, certPEM string, privkeyPEM string) (*deployer.DeployResult, error) { // 上传证书到证书中心 - upres, err := d.sslUploader.Upload(ctx, certPem, privkeyPem) + upres, err := d.sslUploader.Upload(ctx, certPEM, privkeyPEM) if err != nil { - return nil, xerrors.Wrap(err, "failed to upload certificate file") + return nil, fmt.Errorf("failed to upload certificate file: %w", err) } else { d.logger.Info("ssl certificate uploaded", slog.Any("result", upres)) } diff --git a/internal/pkg/core/deployer/providers/volcengine-clb/consts.go b/internal/pkg/core/deployer/providers/volcengine-clb/consts.go index 4d9ab1e3..3dc0f557 100644 --- a/internal/pkg/core/deployer/providers/volcengine-clb/consts.go +++ b/internal/pkg/core/deployer/providers/volcengine-clb/consts.go @@ -1,4 +1,4 @@ -package volcengineclb +package volcengineclb type ResourceType string diff --git a/internal/pkg/core/deployer/providers/volcengine-clb/volcengine_clb.go b/internal/pkg/core/deployer/providers/volcengine-clb/volcengine_clb.go index 752b0f85..3b6a37bf 100644 --- a/internal/pkg/core/deployer/providers/volcengine-clb/volcengine_clb.go +++ b/internal/pkg/core/deployer/providers/volcengine-clb/volcengine_clb.go @@ -1,4 +1,4 @@ -package volcengineclb +package volcengineclb import ( "context" @@ -6,7 +6,6 @@ import ( "fmt" "log/slog" - xerrors "github.com/pkg/errors" veclb "github.com/volcengine/volcengine-go-sdk/service/clb" ve "github.com/volcengine/volcengine-go-sdk/volcengine" vesession "github.com/volcengine/volcengine-go-sdk/volcengine/session" @@ -49,7 +48,7 @@ func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { client, err := createSdkClient(config.AccessKeyId, config.AccessKeySecret, config.Region) if err != nil { - return nil, xerrors.Wrap(err, "failed to create sdk client") + return nil, fmt.Errorf("failed to create sdk client: %w", err) } uploader, err := uploadersp.NewUploader(&uploadersp.UploaderConfig{ @@ -58,7 +57,7 @@ func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { Region: config.Region, }) if err != nil { - return nil, xerrors.Wrap(err, "failed to create ssl uploader") + return nil, fmt.Errorf("failed to create ssl uploader: %w", err) } return &DeployerProvider{ @@ -79,11 +78,11 @@ func (d *DeployerProvider) WithLogger(logger *slog.Logger) deployer.Deployer { return d } -func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { +func (d *DeployerProvider) Deploy(ctx context.Context, certPEM string, privkeyPEM string) (*deployer.DeployResult, error) { // 上传证书到证书中心 - upres, err := d.sslUploader.Upload(ctx, certPem, privkeyPem) + upres, err := d.sslUploader.Upload(ctx, certPEM, privkeyPEM) if err != nil { - return nil, xerrors.Wrap(err, "failed to upload certificate file") + return nil, fmt.Errorf("failed to upload certificate file: %w", err) } else { d.logger.Info("ssl certificate uploaded", slog.Any("result", upres)) } @@ -101,7 +100,7 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPe } default: - return nil, fmt.Errorf("unsupported resource type: %s", d.config.ResourceType) + return nil, fmt.Errorf("unsupported resource type '%s'", d.config.ResourceType) } return &deployer.DeployResult{}, nil @@ -120,7 +119,7 @@ func (d *DeployerProvider) deployToLoadbalancer(ctx context.Context, cloudCertId describeLoadBalancerAttributesResp, err := d.sdkClient.DescribeLoadBalancerAttributes(describeLoadBalancerAttributesReq) d.logger.Debug("sdk request 'clb.DescribeLoadBalancerAttributes'", slog.Any("request", describeLoadBalancerAttributesReq), slog.Any("response", describeLoadBalancerAttributesResp)) if err != nil { - return xerrors.Wrap(err, "failed to execute sdk request 'clb.DescribeLoadBalancerAttributes'") + return fmt.Errorf("failed to execute sdk request 'clb.DescribeLoadBalancerAttributes': %w", err) } // 查询 HTTPS 监听器列表 @@ -129,6 +128,12 @@ func (d *DeployerProvider) deployToLoadbalancer(ctx context.Context, cloudCertId describeListenersPageSize := int64(100) describeListenersPageNumber := int64(1) for { + select { + case <-ctx.Done(): + return ctx.Err() + default: + } + describeListenersReq := &veclb.DescribeListenersInput{ LoadBalancerId: ve.String(d.config.LoadbalancerId), Protocol: ve.String("HTTPS"), @@ -138,7 +143,7 @@ func (d *DeployerProvider) deployToLoadbalancer(ctx context.Context, cloudCertId describeListenersResp, err := d.sdkClient.DescribeListeners(describeListenersReq) d.logger.Debug("sdk request 'clb.DescribeListeners'", slog.Any("request", describeListenersReq), slog.Any("response", describeListenersResp)) if err != nil { - return xerrors.Wrap(err, "failed to execute sdk request 'clb.DescribeListeners'") + return fmt.Errorf("failed to execute sdk request 'clb.DescribeListeners': %w", err) } for _, listener := range describeListenersResp.Listeners { @@ -160,8 +165,13 @@ func (d *DeployerProvider) deployToLoadbalancer(ctx context.Context, cloudCertId var errs []error for _, listenerId := range listenerIds { - if err := d.updateListenerCertificate(ctx, listenerId, cloudCertId); err != nil { - errs = append(errs, err) + select { + case <-ctx.Done(): + return ctx.Err() + default: + if err := d.updateListenerCertificate(ctx, listenerId, cloudCertId); err != nil { + errs = append(errs, err) + } } } @@ -196,7 +206,7 @@ func (d *DeployerProvider) updateListenerCertificate(ctx context.Context, cloudL modifyListenerAttributesResp, err := d.sdkClient.ModifyListenerAttributes(modifyListenerAttributesReq) d.logger.Debug("sdk request 'clb.ModifyListenerAttributes'", slog.Any("request", modifyListenerAttributesReq), slog.Any("response", modifyListenerAttributesResp)) if err != nil { - return xerrors.Wrap(err, "failed to execute sdk request 'clb.ModifyListenerAttributes'") + return fmt.Errorf("failed to execute sdk request 'clb.ModifyListenerAttributes': %w", err) } return nil diff --git a/internal/pkg/core/deployer/providers/volcengine-clb/volcengine_clb_test.go b/internal/pkg/core/deployer/providers/volcengine-clb/volcengine_clb_test.go index 9e9e63e2..fb78eba5 100644 --- a/internal/pkg/core/deployer/providers/volcengine-clb/volcengine_clb_test.go +++ b/internal/pkg/core/deployer/providers/volcengine-clb/volcengine_clb_test.go @@ -1,4 +1,4 @@ -package volcengineclb_test +package volcengineclb_test import ( "context" diff --git a/internal/pkg/core/deployer/providers/volcengine-dcdn/volcengine_dcdn.go b/internal/pkg/core/deployer/providers/volcengine-dcdn/volcengine_dcdn.go index 23af16e5..707ccde3 100644 --- a/internal/pkg/core/deployer/providers/volcengine-dcdn/volcengine_dcdn.go +++ b/internal/pkg/core/deployer/providers/volcengine-dcdn/volcengine_dcdn.go @@ -1,11 +1,11 @@ -package volcenginedcdn +package volcenginedcdn import ( "context" + "fmt" "log/slog" "strings" - xerrors "github.com/pkg/errors" vedcdn "github.com/volcengine/volcengine-go-sdk/service/dcdn" ve "github.com/volcengine/volcengine-go-sdk/volcengine" vesession "github.com/volcengine/volcengine-go-sdk/volcengine/session" @@ -42,7 +42,7 @@ func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { client, err := createSdkClient(config.AccessKeyId, config.AccessKeySecret, config.Region) if err != nil { - return nil, xerrors.Wrap(err, "failed to create sdk client") + return nil, fmt.Errorf("failed to create sdk client: %w", err) } uploader, err := uploadersp.NewUploader(&uploadersp.UploaderConfig{ @@ -51,7 +51,7 @@ func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { Region: config.Region, }) if err != nil { - return nil, xerrors.Wrap(err, "failed to create ssl uploader") + return nil, fmt.Errorf("failed to create ssl uploader: %w", err) } return &DeployerProvider{ @@ -72,11 +72,11 @@ func (d *DeployerProvider) WithLogger(logger *slog.Logger) deployer.Deployer { return d } -func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { +func (d *DeployerProvider) Deploy(ctx context.Context, certPEM string, privkeyPEM string) (*deployer.DeployResult, error) { // 上传证书到证书中心 - upres, err := d.sslUploader.Upload(ctx, certPem, privkeyPem) + upres, err := d.sslUploader.Upload(ctx, certPEM, privkeyPEM) if err != nil { - return nil, xerrors.Wrap(err, "failed to upload certificate file") + return nil, fmt.Errorf("failed to upload certificate file: %w", err) } else { d.logger.Info("ssl certificate uploaded", slog.Any("result", upres)) } @@ -94,7 +94,7 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPe createCertBindResp, err := d.sdkClient.CreateCertBind(createCertBindReq) d.logger.Debug("sdk request 'dcdn.CreateCertBind'", slog.Any("request", createCertBindReq), slog.Any("response", createCertBindResp)) if err != nil { - return nil, xerrors.Wrap(err, "failed to execute sdk request 'dcdn.CreateCertBind'") + return nil, fmt.Errorf("failed to execute sdk request 'dcdn.CreateCertBind': %w", err) } return &deployer.DeployResult{}, nil diff --git a/internal/pkg/core/deployer/providers/volcengine-dcdn/volcengine_dcdn_test.go b/internal/pkg/core/deployer/providers/volcengine-dcdn/volcengine_dcdn_test.go index 1d34a295..27bd02ce 100644 --- a/internal/pkg/core/deployer/providers/volcengine-dcdn/volcengine_dcdn_test.go +++ b/internal/pkg/core/deployer/providers/volcengine-dcdn/volcengine_dcdn_test.go @@ -1,4 +1,4 @@ -package volcenginedcdn_test +package volcenginedcdn_test import ( "context" diff --git a/internal/pkg/core/deployer/providers/volcengine-imagex/volcengine_imagex.go b/internal/pkg/core/deployer/providers/volcengine-imagex/volcengine_imagex.go index 26696d57..2f419752 100644 --- a/internal/pkg/core/deployer/providers/volcengine-imagex/volcengine_imagex.go +++ b/internal/pkg/core/deployer/providers/volcengine-imagex/volcengine_imagex.go @@ -1,11 +1,11 @@ -package volcengineimagex +package volcengineimagex import ( "context" "errors" + "fmt" "log/slog" - xerrors "github.com/pkg/errors" vebase "github.com/volcengine/volc-sdk-golang/base" veimagex "github.com/volcengine/volc-sdk-golang/service/imagex/v2" @@ -43,7 +43,7 @@ func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { client, err := createSdkClient(config.AccessKeyId, config.AccessKeySecret, config.Region) if err != nil { - return nil, xerrors.Wrap(err, "failed to create sdk client") + return nil, fmt.Errorf("failed to create sdk client: %w", err) } uploader, err := uploadersp.NewUploader(&uploadersp.UploaderConfig{ @@ -52,7 +52,7 @@ func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { Region: config.Region, }) if err != nil { - return nil, xerrors.Wrap(err, "failed to create ssl uploader") + return nil, fmt.Errorf("failed to create ssl uploader: %w", err) } return &DeployerProvider{ @@ -73,7 +73,7 @@ func (d *DeployerProvider) WithLogger(logger *slog.Logger) deployer.Deployer { return d } -func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { +func (d *DeployerProvider) Deploy(ctx context.Context, certPEM string, privkeyPEM string) (*deployer.DeployResult, error) { if d.config.ServiceId == "" { return nil, errors.New("config `serviceId` is required") } @@ -82,9 +82,9 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPe } // 上传证书到证书中心 - upres, err := d.sslUploader.Upload(ctx, certPem, privkeyPem) + upres, err := d.sslUploader.Upload(ctx, certPEM, privkeyPEM) if err != nil { - return nil, xerrors.Wrap(err, "failed to upload certificate file") + return nil, fmt.Errorf("failed to upload certificate file: %w", err) } else { d.logger.Info("ssl certificate uploaded", slog.Any("result", upres)) } @@ -98,7 +98,7 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPe getDomainConfigResp, err := d.sdkClient.GetDomainConfig(context.TODO(), getDomainConfigReq) d.logger.Debug("sdk request 'imagex.GetDomainConfig'", slog.Any("request", getDomainConfigReq), slog.Any("response", getDomainConfigResp)) if err != nil { - return nil, xerrors.Wrap(err, "failed to execute sdk request 'imagex.GetDomainConfig'") + return nil, fmt.Errorf("failed to execute sdk request 'imagex.GetDomainConfig': %w", err) } // 更新 HTTPS 配置 @@ -127,7 +127,7 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPe updateHttpsResp, err := d.sdkClient.UpdateHTTPS(context.TODO(), updateHttpsReq) d.logger.Debug("sdk request 'imagex.UpdateHttps'", slog.Any("request", updateHttpsReq), slog.Any("response", updateHttpsResp)) if err != nil { - return nil, xerrors.Wrap(err, "failed to execute sdk request 'imagex.UpdateHttps'") + return nil, fmt.Errorf("failed to execute sdk request 'imagex.UpdateHttps': %w", err) } return &deployer.DeployResult{}, nil diff --git a/internal/pkg/core/deployer/providers/volcengine-imagex/volcengine_imagex_test.go b/internal/pkg/core/deployer/providers/volcengine-imagex/volcengine_imagex_test.go index f2acb8f2..32a43555 100644 --- a/internal/pkg/core/deployer/providers/volcengine-imagex/volcengine_imagex_test.go +++ b/internal/pkg/core/deployer/providers/volcengine-imagex/volcengine_imagex_test.go @@ -1,4 +1,4 @@ -package volcengineimagex_test +package volcengineimagex_test import ( "context" diff --git a/internal/pkg/core/deployer/providers/volcengine-live/volcengine_live.go b/internal/pkg/core/deployer/providers/volcengine-live/volcengine_live.go index a12df9f2..46c0b9dc 100644 --- a/internal/pkg/core/deployer/providers/volcengine-live/volcengine_live.go +++ b/internal/pkg/core/deployer/providers/volcengine-live/volcengine_live.go @@ -1,12 +1,12 @@ -package volcenginelive +package volcenginelive import ( "context" "errors" + "fmt" "log/slog" "strings" - xerrors "github.com/pkg/errors" velive "github.com/volcengine/volc-sdk-golang/service/live/v20230101" ve "github.com/volcengine/volcengine-go-sdk/volcengine" @@ -47,7 +47,7 @@ func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { AccessKeySecret: config.AccessKeySecret, }) if err != nil { - return nil, xerrors.Wrap(err, "failed to create ssl uploader") + return nil, fmt.Errorf("failed to create ssl uploader: %w", err) } return &DeployerProvider{ @@ -68,11 +68,11 @@ func (d *DeployerProvider) WithLogger(logger *slog.Logger) deployer.Deployer { return d } -func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { +func (d *DeployerProvider) Deploy(ctx context.Context, certPEM string, privkeyPEM string) (*deployer.DeployResult, error) { // 上传证书到 Live - upres, err := d.sslUploader.Upload(ctx, certPem, privkeyPem) + upres, err := d.sslUploader.Upload(ctx, certPEM, privkeyPEM) if err != nil { - return nil, xerrors.Wrap(err, "failed to upload certificate file") + return nil, fmt.Errorf("failed to upload certificate file: %w", err) } else { d.logger.Info("ssl certificate uploaded", slog.Any("result", upres)) } @@ -92,7 +92,7 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPe listDomainDetailResp, err := d.sdkClient.ListDomainDetail(ctx, listDomainDetailReq) d.logger.Debug("sdk request 'live.ListDomainDetail'", slog.Any("request", listDomainDetailReq), slog.Any("response", listDomainDetailResp)) if err != nil { - return nil, xerrors.Wrap(err, "failed to execute sdk request 'live.ListDomainDetail'") + return nil, fmt.Errorf("failed to execute sdk request 'live.ListDomainDetail': %w", err) } if listDomainDetailResp.Result.DomainList != nil { @@ -125,17 +125,22 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPe var errs []error for _, domain := range domains { - // 绑定证书 - // REF: https://www.volcengine.com/docs/6469/1186278#%E7%BB%91%E5%AE%9A%E8%AF%81%E4%B9%A6 - bindCertReq := &velive.BindCertBody{ - ChainID: upres.CertId, - Domain: domain, - HTTPS: ve.Bool(true), - } - bindCertResp, err := d.sdkClient.BindCert(ctx, bindCertReq) - d.logger.Debug("sdk request 'live.BindCert'", slog.Any("request", bindCertReq), slog.Any("response", bindCertResp)) - if err != nil { - errs = append(errs, err) + select { + case <-ctx.Done(): + return nil, ctx.Err() + default: + // 绑定证书 + // REF: https://www.volcengine.com/docs/6469/1186278#%E7%BB%91%E5%AE%9A%E8%AF%81%E4%B9%A6 + bindCertReq := &velive.BindCertBody{ + ChainID: upres.CertId, + Domain: domain, + HTTPS: ve.Bool(true), + } + bindCertResp, err := d.sdkClient.BindCert(ctx, bindCertReq) + d.logger.Debug("sdk request 'live.BindCert'", slog.Any("request", bindCertReq), slog.Any("response", bindCertResp)) + if err != nil { + errs = append(errs, err) + } } } 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 2222e7b9..57891eea 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 @@ -1,4 +1,4 @@ -package volcenginelive_test +package volcenginelive_test import ( "context" diff --git a/internal/pkg/core/deployer/providers/volcengine-tos/volcengine_tos.go b/internal/pkg/core/deployer/providers/volcengine-tos/volcengine_tos.go index f2ac4128..365d95f2 100644 --- a/internal/pkg/core/deployer/providers/volcengine-tos/volcengine_tos.go +++ b/internal/pkg/core/deployer/providers/volcengine-tos/volcengine_tos.go @@ -1,4 +1,4 @@ -package volcenginetos +package volcenginetos import ( "context" @@ -6,7 +6,6 @@ import ( "fmt" "log/slog" - xerrors "github.com/pkg/errors" "github.com/volcengine/ve-tos-golang-sdk/v2/tos" "github.com/usual2970/certimate/internal/pkg/core/deployer" @@ -43,7 +42,7 @@ func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { client, err := createSdkClient(config.AccessKeyId, config.AccessKeySecret, config.Region) if err != nil { - return nil, xerrors.Wrap(err, "failed to create sdk client") + return nil, fmt.Errorf("failed to create sdk client: %w", err) } uploader, err := uploadersp.NewUploader(&uploadersp.UploaderConfig{ @@ -52,7 +51,7 @@ func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { Region: config.Region, }) if err != nil { - return nil, xerrors.Wrap(err, "failed to create ssl uploader") + return nil, fmt.Errorf("failed to create ssl uploader: %w", err) } return &DeployerProvider{ @@ -73,7 +72,7 @@ func (d *DeployerProvider) WithLogger(logger *slog.Logger) deployer.Deployer { return d } -func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { +func (d *DeployerProvider) Deploy(ctx context.Context, certPEM string, privkeyPEM string) (*deployer.DeployResult, error) { if d.config.Bucket == "" { return nil, errors.New("config `bucket` is required") } @@ -82,9 +81,9 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPe } // 上传证书到证书中心 - upres, err := d.sslUploader.Upload(ctx, certPem, privkeyPem) + upres, err := d.sslUploader.Upload(ctx, certPEM, privkeyPEM) if err != nil { - return nil, xerrors.Wrap(err, "failed to upload certificate file") + return nil, fmt.Errorf("failed to upload certificate file: %w", err) } else { d.logger.Info("ssl certificate uploaded", slog.Any("result", upres)) } @@ -101,7 +100,7 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPe putBucketCustomDomainResp, err := d.sdkClient.PutBucketCustomDomain(context.TODO(), putBucketCustomDomainReq) d.logger.Debug("sdk request 'tos.PutBucketCustomDomain'", slog.Any("request", putBucketCustomDomainReq), slog.Any("response", putBucketCustomDomainResp)) if err != nil { - return nil, xerrors.Wrap(err, "failed to execute sdk request 'tos.PutBucketCustomDomain'") + return nil, fmt.Errorf("failed to execute sdk request 'tos.PutBucketCustomDomain': %w", err) } return &deployer.DeployResult{}, nil diff --git a/internal/pkg/core/deployer/providers/volcengine-tos/volcengine_tos_test.go b/internal/pkg/core/deployer/providers/volcengine-tos/volcengine_tos_test.go index 0c9b398a..8dc1cf3d 100644 --- a/internal/pkg/core/deployer/providers/volcengine-tos/volcengine_tos_test.go +++ b/internal/pkg/core/deployer/providers/volcengine-tos/volcengine_tos_test.go @@ -1,4 +1,4 @@ -package volcenginetos_test +package volcenginetos_test import ( "context" diff --git a/internal/pkg/core/deployer/providers/wangsu-cdnpro/wangsu_cdnpro.go b/internal/pkg/core/deployer/providers/wangsu-cdnpro/wangsu_cdnpro.go index a0c1e586..2faf1b03 100644 --- a/internal/pkg/core/deployer/providers/wangsu-cdnpro/wangsu_cdnpro.go +++ b/internal/pkg/core/deployer/providers/wangsu-cdnpro/wangsu_cdnpro.go @@ -1,4 +1,4 @@ -package wangsucdnpro +package wangsucdnpro import ( "bytes" @@ -16,12 +16,10 @@ import ( "strconv" "time" - "github.com/alibabacloud-go/tea/tea" - xerrors "github.com/pkg/errors" - "github.com/usual2970/certimate/internal/pkg/core/deployer" - "github.com/usual2970/certimate/internal/pkg/utils/certutil" - wangsucdn "github.com/usual2970/certimate/internal/pkg/vendors/wangsu-sdk/cdn" + wangsucdn "github.com/usual2970/certimate/internal/pkg/sdk3rd/wangsu/cdn" + certutil "github.com/usual2970/certimate/internal/pkg/utils/cert" + typeutil "github.com/usual2970/certimate/internal/pkg/utils/type" ) type DeployerConfig struct { @@ -58,7 +56,7 @@ func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) { client, err := createSdkClient(config.AccessKeyId, config.AccessKeySecret) if err != nil { - return nil, xerrors.Wrap(err, "failed to create sdk client") + return nil, fmt.Errorf("failed to create sdk client: %w", err) } return &DeployerProvider{ @@ -77,13 +75,13 @@ func (d *DeployerProvider) WithLogger(logger *slog.Logger) deployer.Deployer { return d } -func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { +func (d *DeployerProvider) Deploy(ctx context.Context, certPEM string, privkeyPEM string) (*deployer.DeployResult, error) { if d.config.Domain == "" { return nil, errors.New("config `domain` is required") } // 解析证书内容 - certX509, err := certutil.ParseCertificateFromPEM(certPem) + certX509, err := certutil.ParseCertificateFromPEM(certPEM) if err != nil { return nil, err } @@ -92,19 +90,19 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPe getHostnameDetailResp, err := d.sdkClient.GetHostnameDetail(d.config.Domain) d.logger.Debug("sdk request 'cdn.GetHostnameDetail'", slog.String("hostname", d.config.Domain), slog.Any("response", getHostnameDetailResp)) if err != nil { - return nil, xerrors.Wrap(err, "failed to execute sdk request 'cdn.GetHostnameDetail'") + return nil, fmt.Errorf("failed to execute sdk request 'cdn.GetHostnameDetail': %w", err) } // 生成网宿云证书参数 - encryptedPrivateKey, err := encryptPrivateKey(privkeyPem, d.config.ApiKey, time.Now().Unix()) + encryptedPrivateKey, err := encryptPrivateKey(privkeyPEM, d.config.ApiKey, time.Now().Unix()) if err != nil { - return nil, xerrors.Wrap(err, "failed to encrypt private key") + return nil, fmt.Errorf("failed to encrypt private key: %w", err) } certificateNewVersionInfo := &wangsucdn.CertificateVersion{ - PrivateKey: tea.String(encryptedPrivateKey), - Certificate: tea.String(certPem), + PrivateKey: typeutil.ToPtr(encryptedPrivateKey), + Certificate: typeutil.ToPtr(certPEM), IdentificationInfo: &wangsucdn.CertificateVersionIdentificationInfo{ - CommonName: tea.String(certX509.Subject.CommonName), + CommonName: typeutil.ToPtr(certX509.Subject.CommonName), SubjectAlternativeNames: &certX509.DNSNames, }, } @@ -123,14 +121,14 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPe // 创建证书 createCertificateReq := &wangsucdn.CreateCertificateRequest{ Timestamp: timestamp, - Name: tea.String(fmt.Sprintf("certimate_%d", time.Now().UnixMilli())), - AutoRenew: tea.String("Off"), + Name: typeutil.ToPtr(fmt.Sprintf("certimate_%d", time.Now().UnixMilli())), + AutoRenew: typeutil.ToPtr("Off"), NewVersion: certificateNewVersionInfo, } createCertificateResp, err := d.sdkClient.CreateCertificate(createCertificateReq) d.logger.Debug("sdk request 'cdn.CreateCertificate'", slog.Any("request", createCertificateReq), slog.Any("response", createCertificateResp)) if err != nil { - return nil, xerrors.Wrap(err, "failed to execute sdk request 'cdn.CreateCertificate'") + return nil, fmt.Errorf("failed to execute sdk request 'cdn.CreateCertificate': %w", err) } wangsuCertUrl = createCertificateResp.CertificateUrl @@ -146,14 +144,14 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPe // 更新证书 updateCertificateReq := &wangsucdn.UpdateCertificateRequest{ Timestamp: timestamp, - Name: tea.String(fmt.Sprintf("certimate_%d", time.Now().UnixMilli())), - AutoRenew: tea.String("Off"), + Name: typeutil.ToPtr(fmt.Sprintf("certimate_%d", time.Now().UnixMilli())), + AutoRenew: typeutil.ToPtr("Off"), NewVersion: certificateNewVersionInfo, } updateCertificateResp, err := d.sdkClient.UpdateCertificate(d.config.CertificateId, updateCertificateReq) d.logger.Debug("sdk request 'cdn.CreateCertificate'", slog.Any("certificateId", d.config.CertificateId), slog.Any("request", updateCertificateReq), slog.Any("response", updateCertificateResp)) if err != nil { - return nil, xerrors.Wrap(err, "failed to execute sdk request 'cdn.UpdateCertificate'") + return nil, fmt.Errorf("failed to execute sdk request 'cdn.UpdateCertificate': %w", err) } wangsuCertUrl = updateCertificateResp.CertificateUrl @@ -174,23 +172,23 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPe // 创建部署任务 // REF: https://www.wangsu.com/document/api-doc/27034 createDeploymentTaskReq := &wangsucdn.CreateDeploymentTaskRequest{ - Name: tea.String(fmt.Sprintf("certimate_%d", time.Now().UnixMilli())), - Target: tea.String(d.config.Environment), + Name: typeutil.ToPtr(fmt.Sprintf("certimate_%d", time.Now().UnixMilli())), + Target: typeutil.ToPtr(d.config.Environment), Actions: &[]wangsucdn.DeploymentTaskAction{ { - Action: tea.String("deploy_cert"), - CertificateId: tea.String(wangsuCertId), - Version: tea.Int32(wangsuCertVer), + Action: typeutil.ToPtr("deploy_cert"), + CertificateId: typeutil.ToPtr(wangsuCertId), + Version: typeutil.ToPtr(wangsuCertVer), }, }, } if d.config.WebhookId != "" { - createDeploymentTaskReq.Webhook = tea.String(d.config.WebhookId) + createDeploymentTaskReq.Webhook = typeutil.ToPtr(d.config.WebhookId) } createDeploymentTaskResp, err := d.sdkClient.CreateDeploymentTask(createDeploymentTaskReq) d.logger.Debug("sdk request 'cdn.CreateCertificate'", slog.Any("request", createDeploymentTaskReq), slog.Any("response", createDeploymentTaskResp)) if err != nil { - return nil, xerrors.Wrap(err, "failed to execute sdk request 'cdn.CreateDeploymentTask'") + return nil, fmt.Errorf("failed to execute sdk request 'cdn.CreateDeploymentTask': %w", err) } // 循环获取部署任务详细信息,等待任务状态变更 @@ -201,14 +199,16 @@ func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPe wangsuTaskId = wangsuTaskMatches[1] } for { - if ctx.Err() != nil { + select { + case <-ctx.Done(): return nil, ctx.Err() + default: } getDeploymentTaskDetailResp, err := d.sdkClient.GetDeploymentTaskDetail(wangsuTaskId) d.logger.Info("sdk request 'cdn.GetDeploymentTaskDetail'", slog.Any("taskId", wangsuTaskId), slog.Any("response", getDeploymentTaskDetailResp)) if err != nil { - return nil, xerrors.Wrap(err, "failed to execute sdk request 'cdn.GetDeploymentTaskDetail'") + return nil, fmt.Errorf("failed to execute sdk request 'cdn.GetDeploymentTaskDetail': %w", err) } if getDeploymentTaskDetailResp.Status == "failed" { @@ -236,7 +236,7 @@ func createSdkClient(accessKeyId, accessKeySecret string) (*wangsucdn.Client, er return wangsucdn.NewClient(accessKeyId, accessKeySecret), nil } -func encryptPrivateKey(privkeyPem string, apiKey string, timestamp int64) (string, error) { +func encryptPrivateKey(privkeyPEM string, apiKey string, timestamp int64) (string, error) { date := time.Unix(timestamp, 0).UTC() dateStr := date.Format("Mon, 02 Jan 2006 15:04:05 GMT") @@ -266,7 +266,7 @@ func encryptPrivateKey(privkeyPem string, apiKey string, timestamp int64) (strin return "", err } - plainBytes := []byte(privkeyPem) + plainBytes := []byte(privkeyPEM) padlen := aes.BlockSize - len(plainBytes)%aes.BlockSize if padlen > 0 { paddata := bytes.Repeat([]byte{byte(padlen)}, padlen) diff --git a/internal/pkg/core/deployer/providers/wangsu-cdnpro/wangsu_cdnpro_test.go b/internal/pkg/core/deployer/providers/wangsu-cdnpro/wangsu_cdnpro_test.go index 2a868fab..51018fe4 100644 --- a/internal/pkg/core/deployer/providers/wangsu-cdnpro/wangsu_cdnpro_test.go +++ b/internal/pkg/core/deployer/providers/wangsu-cdnpro/wangsu_cdnpro_test.go @@ -1,4 +1,4 @@ -package wangsucdnpro_test +package wangsucdnpro_test import ( "context" diff --git a/internal/pkg/core/deployer/providers/webhook/webhook.go b/internal/pkg/core/deployer/providers/webhook/webhook.go index 0afc60f0..07b2eaaa 100644 --- a/internal/pkg/core/deployer/providers/webhook/webhook.go +++ b/internal/pkg/core/deployer/providers/webhook/webhook.go @@ -4,22 +4,29 @@ import ( "context" "crypto/tls" "encoding/json" + "fmt" "log/slog" + "net/http" + "net/url" "strings" "time" "github.com/go-resty/resty/v2" - xerrors "github.com/pkg/errors" "github.com/usual2970/certimate/internal/pkg/core/deployer" - "github.com/usual2970/certimate/internal/pkg/utils/certutil" + certutil "github.com/usual2970/certimate/internal/pkg/utils/cert" ) type DeployerConfig struct { // Webhook URL。 WebhookUrl string `json:"webhookUrl"` - // Webhook 回调数据(JSON 格式)。 + // Webhook 回调数据(application/json 或 application/x-www-form-urlencoded 格式)。 WebhookData string `json:"webhookData,omitempty"` + // 请求谓词。 + // 零值时默认为 "POST"。 + Method string `json:"method,omitempty"` + // 请求标头。 + Headers map[string]string `json:"headers,omitempty"` // 是否允许不安全的连接。 AllowInsecureConnections bool `json:"allowInsecureConnections,omitempty"` } @@ -61,33 +68,113 @@ func (d *DeployerProvider) WithLogger(logger *slog.Logger) deployer.Deployer { return d } -func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) { - certX509, err := certutil.ParseCertificateFromPEM(certPem) +func (d *DeployerProvider) Deploy(ctx context.Context, certPEM string, privkeyPEM string) (*deployer.DeployResult, error) { + // 解析证书内容 + certX509, err := certutil.ParseCertificateFromPEM(certPEM) if err != nil { - return nil, xerrors.Wrap(err, "failed to parse x509") + return nil, fmt.Errorf("failed to parse x509: %w", err) } + // 处理 Webhook URL + webhookUrl, err := url.Parse(d.config.WebhookUrl) + if err != nil { + return nil, fmt.Errorf("failed to parse webhook url: %w", err) + } else if webhookUrl.Scheme != "http" && webhookUrl.Scheme != "https" { + return nil, fmt.Errorf("unsupported webhook url scheme '%s'", webhookUrl.Scheme) + } else { + webhookUrl.Path = strings.ReplaceAll(webhookUrl.Path, "${DOMAIN}", url.PathEscape(certX509.Subject.CommonName)) + } + + // 处理 Webhook 请求谓词 + webhookMethod := strings.ToUpper(d.config.Method) + if webhookMethod == "" { + webhookMethod = http.MethodPost + } else if webhookMethod != http.MethodGet && + webhookMethod != http.MethodPost && + webhookMethod != http.MethodPut && + webhookMethod != http.MethodPatch && + webhookMethod != http.MethodDelete { + return nil, fmt.Errorf("unsupported webhook request method '%s'", webhookMethod) + } + + // 处理 Webhook 请求标头 + webhookHeaders := make(http.Header) + for k, v := range d.config.Headers { + webhookHeaders.Set(k, v) + } + + // 处理 Webhook 请求内容类型 + const CONTENT_TYPE_JSON = "application/json" + const CONTENT_TYPE_FORM = "application/x-www-form-urlencoded" + const CONTENT_TYPE_MULTIPART = "multipart/form-data" + webhookContentType := webhookHeaders.Get("Content-Type") + if webhookContentType == "" { + webhookContentType = CONTENT_TYPE_JSON + webhookHeaders.Set("Content-Type", CONTENT_TYPE_JSON) + } else if strings.HasPrefix(webhookContentType, CONTENT_TYPE_JSON) && + strings.HasPrefix(webhookContentType, CONTENT_TYPE_FORM) && + strings.HasPrefix(webhookContentType, CONTENT_TYPE_MULTIPART) { + return nil, fmt.Errorf("unsupported webhook content type '%s'", webhookContentType) + } + + // 处理 Webhook 请求数据 var webhookData interface{} - err = json.Unmarshal([]byte(d.config.WebhookData), &webhookData) - if err != nil { - return nil, xerrors.Wrap(err, "failed to unmarshall webhook data") + if d.config.WebhookData == "" { + webhookData = map[string]string{ + "name": strings.Join(certX509.DNSNames, ";"), + "cert": certPEM, + "privkey": privkeyPEM, + } + } else { + err = json.Unmarshal([]byte(d.config.WebhookData), &webhookData) + if err != nil { + return nil, fmt.Errorf("failed to unmarshal webhook data: %w", err) + } + + replaceJsonValueRecursively(webhookData, "${DOMAIN}", certX509.Subject.CommonName) + replaceJsonValueRecursively(webhookData, "${DOMAINS}", strings.Join(certX509.DNSNames, ";")) + replaceJsonValueRecursively(webhookData, "${CERTIFICATE}", certPEM) + replaceJsonValueRecursively(webhookData, "${PRIVATE_KEY}", privkeyPEM) + + if webhookMethod == http.MethodGet || webhookContentType == CONTENT_TYPE_FORM || webhookContentType == CONTENT_TYPE_MULTIPART { + temp := make(map[string]string) + jsonb, err := json.Marshal(webhookData) + if err != nil { + return nil, fmt.Errorf("failed to unmarshal webhook data: %w", err) + } else if err := json.Unmarshal(jsonb, &temp); err != nil { + return nil, fmt.Errorf("failed to unmarshal webhook data: %w", err) + } else { + webhookData = temp + } + } } - replaceJsonValueRecursively(webhookData, "${DOMAIN}", certX509.Subject.CommonName) - replaceJsonValueRecursively(webhookData, "${DOMAINS}", strings.Join(certX509.DNSNames, ";")) - replaceJsonValueRecursively(webhookData, "${SUBJECT_ALT_NAMES}", strings.Join(certX509.DNSNames, ";")) - replaceJsonValueRecursively(webhookData, "${CERTIFICATE}", certPem) - replaceJsonValueRecursively(webhookData, "${PRIVATE_KEY}", privkeyPem) - - resp, err := d.httpClient.R(). + // 生成请求 + // 其中 GET 请求需转换为查询参数 + req := d.httpClient.R(). SetContext(ctx). - SetHeader("Content-Type", "application/json"). - SetBody(webhookData). - Post(d.config.WebhookUrl) + SetHeaderMultiValues(webhookHeaders) + req.URL = webhookUrl.String() + req.Method = webhookMethod + if webhookMethod == http.MethodGet { + req.SetQueryParams(webhookData.(map[string]string)) + } else { + switch webhookContentType { + case CONTENT_TYPE_JSON: + req.SetBody(webhookData) + case CONTENT_TYPE_FORM: + req.SetFormData(webhookData.(map[string]string)) + case CONTENT_TYPE_MULTIPART: + req.SetMultipartFormData(webhookData.(map[string]string)) + } + } + + // 发送请求 + resp, err := req.SetDebug(true).Send() if err != nil { - return nil, xerrors.Wrap(err, "failed to send webhook request") - } else if resp.StatusCode() != 200 { - return nil, xerrors.Errorf("unexpected webhook response status code: %d", resp.StatusCode()) + return nil, fmt.Errorf("failed to send webhook request: %w", err) + } else if resp.IsError() { + return nil, fmt.Errorf("unexpected webhook response status code: %d", resp.StatusCode()) } d.logger.Debug("webhook responded", slog.Any("response", resp.String())) diff --git a/internal/pkg/core/deployer/providers/webhook/webhook_test.go b/internal/pkg/core/deployer/providers/webhook/webhook_test.go index a31ef913..8642ef14 100644 --- a/internal/pkg/core/deployer/providers/webhook/webhook_test.go +++ b/internal/pkg/core/deployer/providers/webhook/webhook_test.go @@ -1,4 +1,4 @@ -package webhook_test +package webhook_test import ( "context" @@ -12,10 +12,11 @@ import ( ) var ( - fInputCertPath string - fInputKeyPath string - fWebhookUrl string - fWebhookData string + fInputCertPath string + fInputKeyPath string + fWebhookUrl string + fWebhookContentType string + fWebhookData string ) func init() { @@ -24,6 +25,7 @@ func init() { flag.StringVar(&fInputCertPath, argsPrefix+"INPUTCERTPATH", "", "") flag.StringVar(&fInputKeyPath, argsPrefix+"INPUTKEYPATH", "", "") flag.StringVar(&fWebhookUrl, argsPrefix+"URL", "", "") + flag.StringVar(&fWebhookContentType, argsPrefix+"CONTENTTYPE", "application/json", "") flag.StringVar(&fWebhookData, argsPrefix+"DATA", "", "") } @@ -34,7 +36,8 @@ Shell command to run this test: --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" \ - --CERTIMATE_DEPLOYER_WEBHOOK_DATA="{\"certificate\":\"${Certificate}\",\"privateKey\":\"${PrivateKey}\"}" + --CERTIMATE_DEPLOYER_WEBHOOK_CONTENTTYPE="application/json" \ + --CERTIMATE_DEPLOYER_WEBHOOK_DATA="{\"certificate\":\"${CERTIFICATE}\",\"privateKey\":\"${PRIVATE_KEY}\"}" */ func TestDeploy(t *testing.T) { flag.Parse() @@ -45,12 +48,17 @@ func TestDeploy(t *testing.T) { fmt.Sprintf("INPUTCERTPATH: %v", fInputCertPath), fmt.Sprintf("INPUTKEYPATH: %v", fInputKeyPath), fmt.Sprintf("WEBHOOKURL: %v", fWebhookUrl), + fmt.Sprintf("WEBHOOKCONTENTTYPE: %v", fWebhookContentType), fmt.Sprintf("WEBHOOKDATA: %v", fWebhookData), }, "\n")) deployer, err := provider.NewDeployer(&provider.DeployerConfig{ - WebhookUrl: fWebhookUrl, - WebhookData: fWebhookData, + WebhookUrl: fWebhookUrl, + WebhookData: fWebhookData, + Method: "POST", + Headers: map[string]string{ + "Content-Type": fWebhookContentType, + }, AllowInsecureConnections: true, }) if err != nil { diff --git a/internal/pkg/core/notifier/providers/bark/bark.go b/internal/pkg/core/notifier/providers/bark/bark.go index a6833ae1..ccdd5736 100644 --- a/internal/pkg/core/notifier/providers/bark/bark.go +++ b/internal/pkg/core/notifier/providers/bark/bark.go @@ -1,4 +1,4 @@ -package bark +package bark import ( "context" @@ -32,6 +32,7 @@ func NewNotifier(config *NotifierConfig) (*NotifierProvider, error) { return &NotifierProvider{ config: config, + logger: slog.Default(), }, nil } diff --git a/internal/pkg/core/notifier/providers/bark/bark_test.go b/internal/pkg/core/notifier/providers/bark/bark_test.go index bd0441b4..f90448a9 100644 --- a/internal/pkg/core/notifier/providers/bark/bark_test.go +++ b/internal/pkg/core/notifier/providers/bark/bark_test.go @@ -1,4 +1,4 @@ -package bark_test +package bark_test import ( "context" diff --git a/internal/pkg/core/notifier/providers/dingtalk/dingtalk.go b/internal/pkg/core/notifier/providers/dingtalk/dingtalk.go index f0ab4741..9eb94dcf 100644 --- a/internal/pkg/core/notifier/providers/dingtalk/dingtalk.go +++ b/internal/pkg/core/notifier/providers/dingtalk/dingtalk.go @@ -1,8 +1,10 @@ -package dingtalk +package dingtalk import ( "context" + "fmt" "log/slog" + "net/url" "github.com/nikoksr/notify/service/dingding" @@ -10,8 +12,8 @@ import ( ) type NotifierConfig struct { - // 钉钉机器人的 Token。 - AccessToken string `json:"accessToken"` + // 钉钉机器人的 Webhook 地址。 + WebhookUrl string `json:"webhookUrl"` // 钉钉机器人的 Secret。 Secret string `json:"secret"` } @@ -30,6 +32,7 @@ func NewNotifier(config *NotifierConfig) (*NotifierProvider, error) { return &NotifierProvider{ config: config, + logger: slog.Default(), }, nil } @@ -43,8 +46,13 @@ func (n *NotifierProvider) WithLogger(logger *slog.Logger) notifier.Notifier { } func (n *NotifierProvider) Notify(ctx context.Context, subject string, message string) (res *notifier.NotifyResult, err error) { + webhookUrl, err := url.Parse(n.config.WebhookUrl) + if err != nil { + return nil, fmt.Errorf("invalid webhook url: %w", err) + } + srv := dingding.New(&dingding.Config{ - Token: n.config.AccessToken, + Token: webhookUrl.Query().Get("access_token"), Secret: n.config.Secret, }) diff --git a/internal/pkg/core/notifier/providers/dingtalk/dingtalk_test.go b/internal/pkg/core/notifier/providers/dingtalk/dingtalk_test.go index 836cf498..086e3a94 100644 --- a/internal/pkg/core/notifier/providers/dingtalk/dingtalk_test.go +++ b/internal/pkg/core/notifier/providers/dingtalk/dingtalk_test.go @@ -1,4 +1,4 @@ -package dingtalk_test +package dingtalk_test import ( "context" diff --git a/internal/pkg/core/notifier/providers/email/email.go b/internal/pkg/core/notifier/providers/email/email.go index ebf2d150..69d39012 100644 --- a/internal/pkg/core/notifier/providers/email/email.go +++ b/internal/pkg/core/notifier/providers/email/email.go @@ -1,4 +1,4 @@ -package email +package email import ( "context" @@ -19,7 +19,7 @@ type NotifierConfig struct { // 零值时根据是否启用 TLS 决定。 SmtpPort int32 `json:"smtpPort"` // 是否启用 TLS。 - SmtpTLS bool `json:"smtpTLS"` + SmtpTls bool `json:"smtpTls"` // 用户名。 Username string `json:"username"` // 密码。 @@ -44,6 +44,7 @@ func NewNotifier(config *NotifierConfig) (*NotifierProvider, error) { return &NotifierProvider{ config: config, + logger: slog.Default(), }, nil } @@ -64,7 +65,7 @@ func (n *NotifierProvider) Notify(ctx context.Context, subject string, message s var smtpAddr string if n.config.SmtpPort == 0 { - if n.config.SmtpTLS { + if n.config.SmtpTls { smtpAddr = fmt.Sprintf("%s:465", n.config.SmtpHost) } else { smtpAddr = fmt.Sprintf("%s:25", n.config.SmtpHost) @@ -74,7 +75,7 @@ func (n *NotifierProvider) Notify(ctx context.Context, subject string, message s } var yak *mailyak.MailYak - if n.config.SmtpTLS { + if n.config.SmtpTls { yak, err = mailyak.NewWithTLS(smtpAddr, smtpAuth, newTlsConfig()) if err != nil { return nil, err diff --git a/internal/pkg/core/notifier/providers/email/email_test.go b/internal/pkg/core/notifier/providers/email/email_test.go index df006c24..30bfba07 100644 --- a/internal/pkg/core/notifier/providers/email/email_test.go +++ b/internal/pkg/core/notifier/providers/email/email_test.go @@ -1,4 +1,4 @@ -package email_test +package email_test import ( "context" @@ -67,7 +67,7 @@ func TestNotify(t *testing.T) { notifier, err := provider.NewNotifier(&provider.NotifierConfig{ SmtpHost: fSmtpHost, SmtpPort: int32(fSmtpPort), - SmtpTLS: fSmtpTLS, + SmtpTls: fSmtpTLS, Username: fUsername, Password: fPassword, SenderAddress: fSenderAddress, diff --git a/internal/pkg/core/notifier/providers/gotify/gotify.go b/internal/pkg/core/notifier/providers/gotify/gotify.go index ad0c515e..aed6e7c8 100644 --- a/internal/pkg/core/notifier/providers/gotify/gotify.go +++ b/internal/pkg/core/notifier/providers/gotify/gotify.go @@ -9,25 +9,21 @@ import ( "log/slog" "net/http" - "github.com/pkg/errors" - "github.com/usual2970/certimate/internal/pkg/core/notifier" ) type NotifierConfig struct { - // Gotify 服务地址 - // 示例:https://gotify.example.com + // Gotify 服务地址。 Url string `json:"url"` - // Gotify Token + // Gotify Token。 Token string `json:"token"` - // Gotify 消息优先级 - Priority int64 `json:"priority"` + // Gotify 消息优先级。 + Priority int64 `json:"priority,omitempty"` } type NotifierProvider struct { - config *NotifierConfig - logger *slog.Logger - // 未来将移除 + config *NotifierConfig + logger *slog.Logger httpClient *http.Client } @@ -40,6 +36,7 @@ func NewNotifier(config *NotifierConfig) (*NotifierProvider, error) { return &NotifierProvider{ config: config, + logger: slog.Default(), httpClient: http.DefaultClient, }, nil } @@ -54,7 +51,6 @@ func (n *NotifierProvider) WithLogger(logger *slog.Logger) notifier.Notifier { } func (n *NotifierProvider) Notify(ctx context.Context, subject string, message string) (res *notifier.NotifyResult, err error) { - // Gotify 原生实现, notify 库没有实现, 等待合并 reqBody := &struct { Title string `json:"title"` Message string `json:"message"` @@ -65,10 +61,9 @@ func (n *NotifierProvider) Notify(ctx context.Context, subject string, message s Priority: n.config.Priority, } - // Make request body, err := json.Marshal(reqBody) if err != nil { - return nil, errors.Wrap(err, "encode message body") + return nil, fmt.Errorf("gotify api error: failed to encode message body: %w", err) } req, err := http.NewRequestWithContext( @@ -78,27 +73,24 @@ func (n *NotifierProvider) Notify(ctx context.Context, subject string, message s bytes.NewReader(body), ) if err != nil { - return nil, errors.Wrap(err, "create new request") + return nil, fmt.Errorf("gotify api error: failed to create new request: %w", err) } req.Header.Add("Authorization", fmt.Sprintf("Bearer %s", n.config.Token)) req.Header.Set("Content-Type", "application/json; charset=utf-8") - // Send request to gotify service resp, err := n.httpClient.Do(req) if err != nil { - return nil, errors.Wrapf(err, "send request to gotify server") + return nil, fmt.Errorf("gotify api error: failed to send request: %w", err) } defer resp.Body.Close() - // Read response and verify success result, err := io.ReadAll(resp.Body) if err != nil { - return nil, errors.Wrap(err, "read response") + return nil, fmt.Errorf("gotify api error: failed to read response: %w", err) + } else if resp.StatusCode != http.StatusOK { + return nil, fmt.Errorf("gotify api error: unexpected status code: %d, resp: %s", resp.StatusCode, string(result)) } - if resp.StatusCode != http.StatusOK { - return nil, fmt.Errorf("gotify returned status code %d: %s", resp.StatusCode, string(result)) - } return ¬ifier.NotifyResult{}, nil } diff --git a/internal/pkg/core/notifier/providers/lark/lark.go b/internal/pkg/core/notifier/providers/lark/lark.go index 150f4e04..e8ad7816 100644 --- a/internal/pkg/core/notifier/providers/lark/lark.go +++ b/internal/pkg/core/notifier/providers/lark/lark.go @@ -1,4 +1,4 @@ -package lark +package lark import ( "context" @@ -28,6 +28,7 @@ func NewNotifier(config *NotifierConfig) (*NotifierProvider, error) { return &NotifierProvider{ config: config, + logger: slog.Default(), }, nil } diff --git a/internal/pkg/core/notifier/providers/lark/lark_test.go b/internal/pkg/core/notifier/providers/lark/lark_test.go index 2b04a7a6..f72ca443 100644 --- a/internal/pkg/core/notifier/providers/lark/lark_test.go +++ b/internal/pkg/core/notifier/providers/lark/lark_test.go @@ -1,4 +1,4 @@ -package lark_test +package lark_test import ( "context" diff --git a/internal/pkg/core/notifier/providers/mattermost/mattermost.go b/internal/pkg/core/notifier/providers/mattermost/mattermost.go index 24890794..ed3a507a 100644 --- a/internal/pkg/core/notifier/providers/mattermost/mattermost.go +++ b/internal/pkg/core/notifier/providers/mattermost/mattermost.go @@ -4,22 +4,24 @@ import ( "bytes" "context" "encoding/json" - "github.com/nikoksr/notify/service/mattermost" - "github.com/usual2970/certimate/internal/pkg/core/notifier" "io" "log/slog" "net/http" + "strings" + + "github.com/nikoksr/notify/service/mattermost" + "github.com/usual2970/certimate/internal/pkg/core/notifier" ) type NotifierConfig struct { - // Mattermost 服务地址。 + // 服务地址。 ServerUrl string `json:"serverUrl"` - // 频道ID - ChannelId string `json:"channelId"` - // 用户名 + // 用户名。 Username string `json:"username"` - // 密码 + // 密码。 Password string `json:"password"` + // 频道 ID。 + ChannelId string `json:"channelId"` } type NotifierProvider struct { @@ -36,6 +38,7 @@ func NewNotifier(config *NotifierConfig) (*NotifierProvider, error) { return &NotifierProvider{ config: config, + logger: slog.Default(), }, nil } @@ -49,7 +52,7 @@ func (n *NotifierProvider) WithLogger(logger *slog.Logger) notifier.Notifier { } func (n *NotifierProvider) Notify(ctx context.Context, subject string, message string) (res *notifier.NotifyResult, err error) { - srv := mattermost.New(n.config.ServerUrl) + srv := mattermost.New(strings.TrimRight(n.config.ServerUrl, "/")) if err := srv.LoginWithCredentials(ctx, n.config.Username, n.config.Password); err != nil { return nil, err diff --git a/internal/pkg/core/notifier/providers/pushover/pushover.go b/internal/pkg/core/notifier/providers/pushover/pushover.go index 8f84dfd2..f306df1f 100644 --- a/internal/pkg/core/notifier/providers/pushover/pushover.go +++ b/internal/pkg/core/notifier/providers/pushover/pushover.go @@ -9,20 +9,19 @@ import ( "log/slog" "net/http" - "github.com/pkg/errors" - "github.com/usual2970/certimate/internal/pkg/core/notifier" ) type NotifierConfig struct { - Token string `json:"token"` // 应用 API Token - User string `json:"user"` // 用户/分组 Key + // Pushover API Token。 + Token string `json:"token"` + // 用户或分组标识。 + User string `json:"user"` } type NotifierProvider struct { - config *NotifierConfig - logger *slog.Logger - // 未来将移除 + config *NotifierConfig + logger *slog.Logger httpClient *http.Client } @@ -35,6 +34,7 @@ func NewNotifier(config *NotifierConfig) (*NotifierProvider, error) { return &NotifierProvider{ config: config, + logger: slog.Default(), httpClient: http.DefaultClient, }, nil } @@ -48,10 +48,8 @@ func (n *NotifierProvider) WithLogger(logger *slog.Logger) notifier.Notifier { return n } -// Notify 发送通知 -// 参考文档:https://pushover.net/api func (n *NotifierProvider) Notify(ctx context.Context, subject string, message string) (res *notifier.NotifyResult, err error) { - // 请求体 + // REF: https://pushover.net/api reqBody := &struct { Token string `json:"token"` User string `json:"user"` @@ -64,10 +62,9 @@ func (n *NotifierProvider) Notify(ctx context.Context, subject string, message s Message: message, } - // Make request body, err := json.Marshal(reqBody) if err != nil { - return nil, errors.Wrap(err, "encode message body") + return nil, fmt.Errorf("pushover api error: failed to encode message body: %w", err) } req, err := http.NewRequestWithContext( @@ -77,25 +74,22 @@ func (n *NotifierProvider) Notify(ctx context.Context, subject string, message s bytes.NewReader(body), ) if err != nil { - return nil, errors.Wrap(err, "create new request") + return nil, fmt.Errorf("pushover api error: failed to create new request: %w", err) } req.Header.Set("Content-Type", "application/json; charset=utf-8") - // Send request to pushover service resp, err := n.httpClient.Do(req) if err != nil { - return nil, errors.Wrapf(err, "send request to pushover server") + return nil, fmt.Errorf("pushover api error: failed to send request: %w", err) } defer resp.Body.Close() result, err := io.ReadAll(resp.Body) if err != nil { - return nil, errors.Wrap(err, "read response") - } - - if resp.StatusCode != http.StatusOK { - return nil, fmt.Errorf("pushover returned status code %d: %s", resp.StatusCode, string(result)) + return nil, fmt.Errorf("pushover api error: failed to read response: %w", err) + } else if resp.StatusCode != http.StatusOK { + return nil, fmt.Errorf("pushover api error: unexpected status code: %d, resp: %s", resp.StatusCode, string(result)) } return ¬ifier.NotifyResult{}, nil diff --git a/internal/pkg/core/notifier/providers/pushplus/pushplus.go b/internal/pkg/core/notifier/providers/pushplus/pushplus.go index 4edac14e..a0ef4c7f 100644 --- a/internal/pkg/core/notifier/providers/pushplus/pushplus.go +++ b/internal/pkg/core/notifier/providers/pushplus/pushplus.go @@ -9,20 +9,17 @@ import ( "log/slog" "net/http" - "github.com/pkg/errors" - "github.com/usual2970/certimate/internal/pkg/core/notifier" ) type NotifierConfig struct { - // PushPlus Token + // PushPlus Token。 Token string `json:"token"` } type NotifierProvider struct { - config *NotifierConfig - logger *slog.Logger - // 未来将移除 + config *NotifierConfig + logger *slog.Logger httpClient *http.Client } @@ -35,6 +32,7 @@ func NewNotifier(config *NotifierConfig) (*NotifierProvider, error) { return &NotifierProvider{ config: config, + logger: slog.Default(), httpClient: http.DefaultClient, }, nil } @@ -48,10 +46,8 @@ func (n *NotifierProvider) WithLogger(logger *slog.Logger) notifier.Notifier { return n } -// Notify 发送通知 -// 参考文档:https://pushplus.plus/doc/guide/api.html func (n *NotifierProvider) Notify(ctx context.Context, subject string, message string) (res *notifier.NotifyResult, err error) { - // 请求体 + // REF: https://pushplus.plus/doc/guide/api.html reqBody := &struct { Token string `json:"token"` Title string `json:"title"` @@ -62,10 +58,9 @@ func (n *NotifierProvider) Notify(ctx context.Context, subject string, message s Content: message, } - // Make request body, err := json.Marshal(reqBody) if err != nil { - return nil, errors.Wrap(err, "encode message body") + return nil, fmt.Errorf("pushplus api error: failed to encode message body: %w", err) } req, err := http.NewRequestWithContext( @@ -75,38 +70,32 @@ func (n *NotifierProvider) Notify(ctx context.Context, subject string, message s bytes.NewReader(body), ) if err != nil { - return nil, errors.Wrap(err, "create new request") + return nil, fmt.Errorf("pushplus api error: failed to create new request: %w", err) } req.Header.Set("Content-Type", "application/json; charset=utf-8") - // Send request to pushplus service resp, err := n.httpClient.Do(req) if err != nil { - return nil, errors.Wrapf(err, "send request to pushplus server") + return nil, fmt.Errorf("pushplus api error: failed to send request: %w", err) } defer resp.Body.Close() result, err := io.ReadAll(resp.Body) if err != nil { - return nil, errors.Wrap(err, "read response") + return nil, fmt.Errorf("pushplus api error: failed to read response: %w", err) + } else if resp.StatusCode != http.StatusOK { + return nil, fmt.Errorf("pushplus api error: unexpected status code: %d, resp: %s", resp.StatusCode, string(result)) } - if resp.StatusCode != http.StatusOK { - return nil, fmt.Errorf("pushplus returned status code %d: %s", resp.StatusCode, string(result)) - } - - // 解析响应 var errorResponse struct { Code int `json:"code"` Msg string `json:"msg"` } if err := json.Unmarshal(result, &errorResponse); err != nil { - return nil, errors.Wrap(err, "decode response") - } - - if errorResponse.Code != 200 { - return nil, fmt.Errorf("pushplus returned error: %s", errorResponse.Msg) + return nil, fmt.Errorf("pushplus api error: failed to decode response: %w", err) + } else if errorResponse.Code != 200 { + return nil, fmt.Errorf("pushplus api error: unexpected response code: %d, msg: %s", errorResponse.Code, errorResponse.Msg) } return ¬ifier.NotifyResult{}, nil diff --git a/internal/pkg/core/notifier/providers/serverchan/serverchan.go b/internal/pkg/core/notifier/providers/serverchan/serverchan.go index ac4d9fe6..89724b08 100644 --- a/internal/pkg/core/notifier/providers/serverchan/serverchan.go +++ b/internal/pkg/core/notifier/providers/serverchan/serverchan.go @@ -1,4 +1,4 @@ -package serverchan +package serverchan import ( "context" @@ -29,6 +29,7 @@ func NewNotifier(config *NotifierConfig) (*NotifierProvider, error) { return &NotifierProvider{ config: config, + logger: slog.Default(), }, nil } diff --git a/internal/pkg/core/notifier/providers/serverchan/serverchan_test.go b/internal/pkg/core/notifier/providers/serverchan/serverchan_test.go index 6f9c61a3..991b4050 100644 --- a/internal/pkg/core/notifier/providers/serverchan/serverchan_test.go +++ b/internal/pkg/core/notifier/providers/serverchan/serverchan_test.go @@ -1,4 +1,4 @@ -package serverchan_test +package serverchan_test import ( "context" diff --git a/internal/pkg/core/notifier/providers/telegram/telegram.go b/internal/pkg/core/notifier/providers/telegram/telegram.go index c3a2e973..218f7ee3 100644 --- a/internal/pkg/core/notifier/providers/telegram/telegram.go +++ b/internal/pkg/core/notifier/providers/telegram/telegram.go @@ -1,4 +1,4 @@ -package telegram +package telegram import ( "context" @@ -10,8 +10,8 @@ import ( ) type NotifierConfig struct { - // Telegram API Token。 - ApiToken string `json:"apiToken"` + // Telegram Bot API Token。 + BotToken string `json:"botToken"` // Telegram Chat ID。 ChatId int64 `json:"chatId"` } @@ -30,6 +30,7 @@ func NewNotifier(config *NotifierConfig) (*NotifierProvider, error) { return &NotifierProvider{ config: config, + logger: slog.Default(), }, nil } @@ -43,7 +44,7 @@ func (n *NotifierProvider) WithLogger(logger *slog.Logger) notifier.Notifier { } func (n *NotifierProvider) Notify(ctx context.Context, subject string, message string) (res *notifier.NotifyResult, err error) { - srv, err := telegram.New(n.config.ApiToken) + srv, err := telegram.New(n.config.BotToken) if err != nil { return nil, err } diff --git a/internal/pkg/core/notifier/providers/telegram/telegram_test.go b/internal/pkg/core/notifier/providers/telegram/telegram_test.go index 10e93547..e9a7d10b 100644 --- a/internal/pkg/core/notifier/providers/telegram/telegram_test.go +++ b/internal/pkg/core/notifier/providers/telegram/telegram_test.go @@ -1,4 +1,4 @@ -package telegram_test +package telegram_test import ( "context" @@ -45,7 +45,7 @@ func TestNotify(t *testing.T) { }, "\n")) notifier, err := provider.NewNotifier(&provider.NotifierConfig{ - ApiToken: fApiToken, + BotToken: fApiToken, ChatId: fChartId, }) if err != nil { diff --git a/internal/pkg/core/notifier/providers/webhook/webhook.go b/internal/pkg/core/notifier/providers/webhook/webhook.go index e11e5487..0e7caaa5 100644 --- a/internal/pkg/core/notifier/providers/webhook/webhook.go +++ b/internal/pkg/core/notifier/providers/webhook/webhook.go @@ -1,26 +1,39 @@ -package webhook +package webhook import ( "context" "crypto/tls" + "encoding/json" + "fmt" "log/slog" "net/http" + "net/url" + "strings" + "time" - webhook "github.com/nikoksr/notify/service/http" + "github.com/go-resty/resty/v2" "github.com/usual2970/certimate/internal/pkg/core/notifier" ) type NotifierConfig struct { // Webhook URL。 - Url string `json:"url"` + WebhookUrl string `json:"webhookUrl"` + // Webhook 回调数据(application/json 或 application/x-www-form-urlencoded 格式)。 + WebhookData string `json:"webhookData,omitempty"` + // 请求谓词。 + // 零值时默认为 "POST"。 + Method string `json:"method,omitempty"` + // 请求标头。 + Headers map[string]string `json:"headers,omitempty"` // 是否允许不安全的连接。 AllowInsecureConnections bool `json:"allowInsecureConnections,omitempty"` } type NotifierProvider struct { - config *NotifierConfig - logger *slog.Logger + config *NotifierConfig + logger *slog.Logger + httpClient *resty.Client } var _ notifier.Notifier = (*NotifierProvider)(nil) @@ -30,8 +43,18 @@ func NewNotifier(config *NotifierConfig) (*NotifierProvider, error) { panic("config is nil") } + client := resty.New(). + SetTimeout(30 * time.Second). + SetRetryCount(3). + SetRetryWaitTime(5 * time.Second) + if config.AllowInsecureConnections { + client.SetTLSClientConfig(&tls.Config{InsecureSkipVerify: true}) + } + return &NotifierProvider{ - config: config, + config: config, + logger: slog.Default(), + httpClient: client, }, nil } @@ -45,20 +68,120 @@ func (n *NotifierProvider) WithLogger(logger *slog.Logger) notifier.Notifier { } func (n *NotifierProvider) Notify(ctx context.Context, subject string, message string) (res *notifier.NotifyResult, err error) { - srv := webhook.New() - srv.AddReceiversURLs(n.config.Url) - - if n.config.AllowInsecureConnections { - tlsConfig := &tls.Config{InsecureSkipVerify: true} - transport := &http.Transport{TLSClientConfig: tlsConfig} - client := &http.Client{Transport: transport} - srv.WithClient(client) - } - - err = srv.Send(ctx, subject, message) + // 处理 Webhook URL + webhookUrl, err := url.Parse(n.config.WebhookUrl) if err != nil { - return nil, err + return nil, fmt.Errorf("failed to parse webhook url: %w", err) + } else if webhookUrl.Scheme != "http" && webhookUrl.Scheme != "https" { + return nil, fmt.Errorf("unsupported webhook url scheme '%s'", webhookUrl.Scheme) } + // 处理 Webhook 请求谓词 + webhookMethod := strings.ToUpper(n.config.Method) + if webhookMethod == "" { + webhookMethod = http.MethodPost + } else if webhookMethod != http.MethodGet && + webhookMethod != http.MethodPost && + webhookMethod != http.MethodPut && + webhookMethod != http.MethodPatch && + webhookMethod != http.MethodDelete { + return nil, fmt.Errorf("unsupported webhook request method '%s'", webhookMethod) + } + + // 处理 Webhook 请求标头 + webhookHeaders := make(http.Header) + for k, v := range n.config.Headers { + webhookHeaders.Set(k, v) + } + + // 处理 Webhook 请求内容类型 + const CONTENT_TYPE_JSON = "application/json" + const CONTENT_TYPE_FORM = "application/x-www-form-urlencoded" + const CONTENT_TYPE_MULTIPART = "multipart/form-data" + webhookContentType := webhookHeaders.Get("Content-Type") + if webhookContentType == "" { + webhookContentType = CONTENT_TYPE_JSON + webhookHeaders.Set("Content-Type", CONTENT_TYPE_JSON) + } else if strings.HasPrefix(webhookContentType, CONTENT_TYPE_JSON) && + strings.HasPrefix(webhookContentType, CONTENT_TYPE_FORM) && + strings.HasPrefix(webhookContentType, CONTENT_TYPE_MULTIPART) { + return nil, fmt.Errorf("unsupported webhook content type '%s'", webhookContentType) + } + + // 处理 Webhook 请求数据 + var webhookData interface{} + if n.config.WebhookData == "" { + webhookData = map[string]string{ + "subject": subject, + "message": message, + } + } else { + err = json.Unmarshal([]byte(n.config.WebhookData), &webhookData) + if err != nil { + return nil, fmt.Errorf("failed to unmarshal webhook data: %w", err) + } + + replaceJsonValueRecursively(webhookData, "${SUBJECT}", subject) + replaceJsonValueRecursively(webhookData, "${MESSAGE}", message) + + if webhookMethod == http.MethodGet || webhookContentType == CONTENT_TYPE_FORM || webhookContentType == CONTENT_TYPE_MULTIPART { + temp := make(map[string]string) + jsonb, err := json.Marshal(webhookData) + if err != nil { + return nil, fmt.Errorf("failed to unmarshal webhook data: %w", err) + } else if err := json.Unmarshal(jsonb, &temp); err != nil { + return nil, fmt.Errorf("failed to unmarshal webhook data: %w", err) + } else { + webhookData = temp + } + } + } + + // 生成请求 + // 其中 GET 请求需转换为查询参数 + req := n.httpClient.R(). + SetContext(ctx). + SetHeaderMultiValues(webhookHeaders) + req.URL = webhookUrl.String() + req.Method = webhookMethod + if webhookMethod == http.MethodGet { + req.SetQueryParams(webhookData.(map[string]string)) + } else { + switch webhookContentType { + case CONTENT_TYPE_JSON: + req.SetBody(webhookData) + case CONTENT_TYPE_FORM: + req.SetFormData(webhookData.(map[string]string)) + case CONTENT_TYPE_MULTIPART: + req.SetMultipartFormData(webhookData.(map[string]string)) + } + } + + // 发送请求 + resp, err := req.Send() + if err != nil { + return nil, fmt.Errorf("failed to send webhook request: %w", err) + } else if resp.IsError() { + return nil, fmt.Errorf("unexpected webhook response status code: %d", resp.StatusCode()) + } + + n.logger.Debug("webhook responded", slog.Any("response", resp.String())) + return ¬ifier.NotifyResult{}, nil } + +func replaceJsonValueRecursively(data interface{}, oldStr, newStr string) interface{} { + switch v := data.(type) { + case map[string]any: + for k, val := range v { + v[k] = replaceJsonValueRecursively(val, oldStr, newStr) + } + case []any: + for i, val := range v { + v[i] = replaceJsonValueRecursively(val, oldStr, newStr) + } + case string: + return strings.ReplaceAll(v, oldStr, newStr) + } + return data +} diff --git a/internal/pkg/core/notifier/providers/webhook/webhook_test.go b/internal/pkg/core/notifier/providers/webhook/webhook_test.go index 8210358b..c416b3c9 100644 --- a/internal/pkg/core/notifier/providers/webhook/webhook_test.go +++ b/internal/pkg/core/notifier/providers/webhook/webhook_test.go @@ -1,4 +1,4 @@ -package webhook_test +package webhook_test import ( "context" @@ -15,19 +15,24 @@ const ( mockMessage = "test_message" ) -var fUrl string +var ( + fWebhookUrl string + fWebhookContentType string +) func init() { argsPrefix := "CERTIMATE_NOTIFIER_WEBHOOK_" - flag.StringVar(&fUrl, argsPrefix+"URL", "", "") + flag.StringVar(&fWebhookUrl, argsPrefix+"URL", "", "") + flag.StringVar(&fWebhookContentType, argsPrefix+"CONTENTTYPE", "application/json", "") } /* Shell command to run this test: go test -v ./webhook_test.go -args \ - --CERTIMATE_NOTIFIER_WEBHOOK_URL="https://example.com/your-webhook-url" + --CERTIMATE_NOTIFIER_WEBHOOK_URL="https://example.com/your-webhook-url" \ + --CERTIMATE_NOTIFIER_WEBHOOK_CONTENTTYPE="application/json" */ func TestNotify(t *testing.T) { flag.Parse() @@ -35,11 +40,15 @@ func TestNotify(t *testing.T) { t.Run("Notify", func(t *testing.T) { t.Log(strings.Join([]string{ "args:", - fmt.Sprintf("URL: %v", fUrl), + fmt.Sprintf("URL: %v", fWebhookUrl), }, "\n")) notifier, err := provider.NewNotifier(&provider.NotifierConfig{ - Url: fUrl, + WebhookUrl: fWebhookUrl, + Method: "POST", + Headers: map[string]string{ + "Content-Type": fWebhookContentType, + }, AllowInsecureConnections: true, }) if err != nil { diff --git a/internal/pkg/core/notifier/providers/wecom/wecom.go b/internal/pkg/core/notifier/providers/wecom/wecom.go index ef76e97f..413f0d8d 100644 --- a/internal/pkg/core/notifier/providers/wecom/wecom.go +++ b/internal/pkg/core/notifier/providers/wecom/wecom.go @@ -1,4 +1,4 @@ -package serverchan +package serverchan import ( "context" diff --git a/internal/pkg/core/notifier/providers/wecom/wecom_test.go b/internal/pkg/core/notifier/providers/wecom/wecom_test.go index b823adea..01646121 100644 --- a/internal/pkg/core/notifier/providers/wecom/wecom_test.go +++ b/internal/pkg/core/notifier/providers/wecom/wecom_test.go @@ -1,4 +1,4 @@ -package serverchan_test +package serverchan_test import ( "context" diff --git a/internal/pkg/core/uploader/providers/1panel-ssl/1panel_ssl.go b/internal/pkg/core/uploader/providers/1panel-ssl/1panel_ssl.go index 4eeec679..e5a0b0ba 100644 --- a/internal/pkg/core/uploader/providers/1panel-ssl/1panel_ssl.go +++ b/internal/pkg/core/uploader/providers/1panel-ssl/1panel_ssl.go @@ -1,4 +1,4 @@ -package onepanelssl +package onepanelssl import ( "context" @@ -9,10 +9,8 @@ import ( "strings" "time" - xerrors "github.com/pkg/errors" - "github.com/usual2970/certimate/internal/pkg/core/uploader" - opsdk "github.com/usual2970/certimate/internal/pkg/vendors/1panel-sdk" + opsdk "github.com/usual2970/certimate/internal/pkg/sdk3rd/1panel" ) type UploaderConfig struct { @@ -37,7 +35,7 @@ func NewUploader(config *UploaderConfig) (*UploaderProvider, error) { client, err := createSdkClient(config.ApiUrl, config.ApiKey) if err != nil { - return nil, xerrors.Wrap(err, "failed to create sdk client") + return nil, fmt.Errorf("failed to create sdk client: %w", err) } return &UploaderProvider{ @@ -56,9 +54,9 @@ func (u *UploaderProvider) WithLogger(logger *slog.Logger) uploader.Uploader { return u } -func (u *UploaderProvider) Upload(ctx context.Context, certPem string, privkeyPem string) (res *uploader.UploadResult, err error) { +func (u *UploaderProvider) Upload(ctx context.Context, certPEM string, privkeyPEM string) (res *uploader.UploadResult, err error) { // 遍历证书列表,避免重复上传 - if res, err := u.getCertIfExists(ctx, certPem, privkeyPem); err != nil { + if res, err := u.getCertIfExists(ctx, certPEM, privkeyPEM); err != nil { return nil, err } else if res != nil { u.logger.Info("ssl certificate already exists") @@ -72,17 +70,17 @@ func (u *UploaderProvider) Upload(ctx context.Context, certPem string, privkeyPe uploadWebsiteSSLReq := &opsdk.UploadWebsiteSSLRequest{ Type: "paste", Description: certName, - Certificate: certPem, - PrivateKey: privkeyPem, + Certificate: certPEM, + PrivateKey: privkeyPEM, } uploadWebsiteSSLResp, err := u.sdkClient.UploadWebsiteSSL(uploadWebsiteSSLReq) u.logger.Debug("sdk request '1panel.UploadWebsiteSSL'", slog.Any("request", uploadWebsiteSSLReq), slog.Any("response", uploadWebsiteSSLResp)) if err != nil { - return nil, xerrors.Wrap(err, "failed to execute sdk request '1panel.UploadWebsiteSSL'") + return nil, fmt.Errorf("failed to execute sdk request '1panel.UploadWebsiteSSL': %w", err) } // 遍历证书列表,获取刚刚上传证书 ID - if res, err := u.getCertIfExists(ctx, certPem, privkeyPem); err != nil { + if res, err := u.getCertIfExists(ctx, certPEM, privkeyPEM); err != nil { return nil, err } else if res == nil { return nil, fmt.Errorf("no ssl certificate found, may be upload failed (code: %d, message: %s)", uploadWebsiteSSLResp.GetCode(), uploadWebsiteSSLResp.GetMessage()) @@ -91,10 +89,16 @@ func (u *UploaderProvider) Upload(ctx context.Context, certPem string, privkeyPe } } -func (u *UploaderProvider) getCertIfExists(ctx context.Context, certPem string, privkeyPem string) (res *uploader.UploadResult, err error) { +func (u *UploaderProvider) getCertIfExists(ctx context.Context, certPEM string, privkeyPEM string) (res *uploader.UploadResult, err error) { searchWebsiteSSLPageNumber := int32(1) searchWebsiteSSLPageSize := int32(100) for { + select { + case <-ctx.Done(): + return nil, ctx.Err() + default: + } + searchWebsiteSSLReq := &opsdk.SearchWebsiteSSLRequest{ Page: searchWebsiteSSLPageNumber, PageSize: searchWebsiteSSLPageSize, @@ -102,12 +106,12 @@ func (u *UploaderProvider) getCertIfExists(ctx context.Context, certPem string, searchWebsiteSSLResp, err := u.sdkClient.SearchWebsiteSSL(searchWebsiteSSLReq) u.logger.Debug("sdk request '1panel.SearchWebsiteSSL'", slog.Any("request", searchWebsiteSSLReq), slog.Any("response", searchWebsiteSSLResp)) if err != nil { - return nil, xerrors.Wrap(err, "failed to execute sdk request '1panel.SearchWebsiteSSL'") + return nil, fmt.Errorf("failed to execute sdk request '1panel.SearchWebsiteSSL': %w", err) } for _, sslItem := range searchWebsiteSSLResp.Data.Items { - if strings.TrimSpace(sslItem.PEM) == strings.TrimSpace(certPem) && - strings.TrimSpace(sslItem.PrivateKey) == strings.TrimSpace(privkeyPem) { + if strings.TrimSpace(sslItem.PEM) == strings.TrimSpace(certPEM) && + strings.TrimSpace(sslItem.PrivateKey) == strings.TrimSpace(privkeyPEM) { // 如果已存在相同证书,直接返回 return &uploader.UploadResult{ CertId: fmt.Sprintf("%d", sslItem.ID), diff --git a/internal/pkg/core/uploader/providers/1panel-ssl/1panel_ssl_test.go b/internal/pkg/core/uploader/providers/1panel-ssl/1panel_ssl_test.go index 5f146dd1..257030f5 100644 --- a/internal/pkg/core/uploader/providers/1panel-ssl/1panel_ssl_test.go +++ b/internal/pkg/core/uploader/providers/1panel-ssl/1panel_ssl_test.go @@ -1,4 +1,4 @@ -package onepanelssl_test +package onepanelssl_test import ( "context" diff --git a/internal/pkg/core/uploader/providers/aliyun-cas/aliyun_cas.go b/internal/pkg/core/uploader/providers/aliyun-cas/aliyun_cas.go index f7495c40..9d7be223 100644 --- a/internal/pkg/core/uploader/providers/aliyun-cas/aliyun_cas.go +++ b/internal/pkg/core/uploader/providers/aliyun-cas/aliyun_cas.go @@ -1,4 +1,4 @@ -package aliyuncas +package aliyuncas import ( "context" @@ -10,10 +10,9 @@ import ( alicas "github.com/alibabacloud-go/cas-20200407/v3/client" aliopen "github.com/alibabacloud-go/darabonba-openapi/v2/client" "github.com/alibabacloud-go/tea/tea" - xerrors "github.com/pkg/errors" "github.com/usual2970/certimate/internal/pkg/core/uploader" - "github.com/usual2970/certimate/internal/pkg/utils/certutil" + certutil "github.com/usual2970/certimate/internal/pkg/utils/cert" ) type UploaderConfig struct { @@ -40,7 +39,7 @@ func NewUploader(config *UploaderConfig) (*UploaderProvider, error) { client, err := createSdkClient(config.AccessKeyId, config.AccessKeySecret, config.Region) if err != nil { - return nil, xerrors.Wrap(err, "failed to create sdk client") + return nil, fmt.Errorf("failed to create sdk client: %w", err) } return &UploaderProvider{ @@ -59,9 +58,9 @@ func (u *UploaderProvider) WithLogger(logger *slog.Logger) uploader.Uploader { return u } -func (u *UploaderProvider) Upload(ctx context.Context, certPem string, privkeyPem string) (res *uploader.UploadResult, err error) { +func (u *UploaderProvider) Upload(ctx context.Context, certPEM string, privkeyPEM string) (res *uploader.UploadResult, err error) { // 解析证书内容 - certX509, err := certutil.ParseCertificateFromPEM(certPem) + certX509, err := certutil.ParseCertificateFromPEM(certPEM) if err != nil { return nil, err } @@ -72,6 +71,12 @@ func (u *UploaderProvider) Upload(ctx context.Context, certPem string, privkeyPe listUserCertificateOrderPage := int64(1) listUserCertificateOrderLimit := int64(50) for { + select { + case <-ctx.Done(): + return nil, ctx.Err() + default: + } + listUserCertificateOrderReq := &alicas.ListUserCertificateOrderRequest{ CurrentPage: tea.Int64(listUserCertificateOrderPage), ShowSize: tea.Int64(listUserCertificateOrderLimit), @@ -80,7 +85,7 @@ func (u *UploaderProvider) Upload(ctx context.Context, certPem string, privkeyPe listUserCertificateOrderResp, err := u.sdkClient.ListUserCertificateOrder(listUserCertificateOrderReq) u.logger.Debug("sdk request 'cas.ListUserCertificateOrder'", slog.Any("request", listUserCertificateOrderReq), slog.Any("response", listUserCertificateOrderResp)) if err != nil { - return nil, xerrors.Wrap(err, "failed to execute sdk request 'cas.ListUserCertificateOrder'") + return nil, fmt.Errorf("failed to execute sdk request 'cas.ListUserCertificateOrder': %w", err) } if listUserCertificateOrderResp.Body.CertificateOrderList != nil { @@ -95,11 +100,11 @@ func (u *UploaderProvider) Upload(ctx context.Context, certPem string, privkeyPe getUserCertificateDetailResp, err := u.sdkClient.GetUserCertificateDetail(getUserCertificateDetailReq) u.logger.Debug("sdk request 'cas.GetUserCertificateDetail'", slog.Any("request", getUserCertificateDetailReq), slog.Any("response", getUserCertificateDetailResp)) if err != nil { - return nil, xerrors.Wrap(err, "failed to execute sdk request 'cas.GetUserCertificateDetail'") + return nil, fmt.Errorf("failed to execute sdk request 'cas.GetUserCertificateDetail': %w", err) } var isSameCert bool - if *getUserCertificateDetailResp.Body.Cert == certPem { + if *getUserCertificateDetailResp.Body.Cert == certPEM { isSameCert = true } else { oldCertX509, err := certutil.ParseCertificateFromPEM(*getUserCertificateDetailResp.Body.Cert) @@ -139,13 +144,13 @@ func (u *UploaderProvider) Upload(ctx context.Context, certPem string, privkeyPe // REF: https://help.aliyun.com/zh/ssl-certificate/developer-reference/api-cas-2020-04-07-uploadusercertificate uploadUserCertificateReq := &alicas.UploadUserCertificateRequest{ Name: tea.String(certName), - Cert: tea.String(certPem), - Key: tea.String(privkeyPem), + Cert: tea.String(certPEM), + Key: tea.String(privkeyPEM), } uploadUserCertificateResp, err := u.sdkClient.UploadUserCertificate(uploadUserCertificateReq) u.logger.Debug("sdk request 'cas.UploadUserCertificate'", slog.Any("request", uploadUserCertificateReq), slog.Any("response", uploadUserCertificateResp)) if err != nil { - return nil, xerrors.Wrap(err, "failed to execute sdk request 'cas.UploadUserCertificate'") + return nil, fmt.Errorf("failed to execute sdk request 'cas.UploadUserCertificate': %w", err) } // 获取证书详情 @@ -157,7 +162,7 @@ func (u *UploaderProvider) Upload(ctx context.Context, certPem string, privkeyPe getUserCertificateDetailResp, err := u.sdkClient.GetUserCertificateDetail(getUserCertificateDetailReq) u.logger.Debug("sdk request 'cas.GetUserCertificateDetail'", slog.Any("request", getUserCertificateDetailReq), slog.Any("response", getUserCertificateDetailResp)) if err != nil { - return nil, xerrors.Wrap(err, "failed to execute sdk request 'cas.GetUserCertificateDetail'") + return nil, fmt.Errorf("failed to execute sdk request 'cas.GetUserCertificateDetail': %w", err) } return &uploader.UploadResult{ diff --git a/internal/pkg/core/uploader/providers/aliyun-slb/aliyun_slb.go b/internal/pkg/core/uploader/providers/aliyun-slb/aliyun_slb.go index 59607ade..cc1544c1 100644 --- a/internal/pkg/core/uploader/providers/aliyun-slb/aliyun_slb.go +++ b/internal/pkg/core/uploader/providers/aliyun-slb/aliyun_slb.go @@ -1,4 +1,4 @@ -package aliyunslb +package aliyunslb import ( "context" @@ -13,10 +13,9 @@ import ( aliopen "github.com/alibabacloud-go/darabonba-openapi/v2/client" alislb "github.com/alibabacloud-go/slb-20140515/v4/client" "github.com/alibabacloud-go/tea/tea" - xerrors "github.com/pkg/errors" "github.com/usual2970/certimate/internal/pkg/core/uploader" - "github.com/usual2970/certimate/internal/pkg/utils/certutil" + certutil "github.com/usual2970/certimate/internal/pkg/utils/cert" ) type UploaderConfig struct { @@ -43,7 +42,7 @@ func NewUploader(config *UploaderConfig) (*UploaderProvider, error) { client, err := createSdkClient(config.AccessKeyId, config.AccessKeySecret, config.Region) if err != nil { - return nil, xerrors.Wrap(err, "failed to create sdk client") + return nil, fmt.Errorf("failed to create sdk client: %w", err) } return &UploaderProvider{ @@ -62,9 +61,9 @@ func (u *UploaderProvider) WithLogger(logger *slog.Logger) uploader.Uploader { return u } -func (u *UploaderProvider) Upload(ctx context.Context, certPem string, privkeyPem string) (res *uploader.UploadResult, err error) { +func (u *UploaderProvider) Upload(ctx context.Context, certPEM string, privkeyPEM string) (res *uploader.UploadResult, err error) { // 解析证书内容 - certX509, err := certutil.ParseCertificateFromPEM(certPem) + certX509, err := certutil.ParseCertificateFromPEM(certPEM) if err != nil { return nil, err } @@ -77,7 +76,7 @@ func (u *UploaderProvider) Upload(ctx context.Context, certPem string, privkeyPe describeServerCertificatesResp, err := u.sdkClient.DescribeServerCertificates(describeServerCertificatesReq) u.logger.Debug("sdk request 'slb.DescribeServerCertificates'", slog.Any("request", describeServerCertificatesReq), slog.Any("response", describeServerCertificatesResp)) if err != nil { - return nil, xerrors.Wrap(err, "failed to execute sdk request 'slb.DescribeServerCertificates'") + return nil, fmt.Errorf("failed to execute sdk request 'slb.DescribeServerCertificates': %w", err) } if describeServerCertificatesResp.Body.ServerCertificates != nil && describeServerCertificatesResp.Body.ServerCertificates.ServerCertificate != nil { @@ -105,21 +104,21 @@ func (u *UploaderProvider) Upload(ctx context.Context, certPem string, privkeyPe // 去除证书和私钥内容中的空白行,以符合阿里云 API 要求 // REF: https://github.com/usual2970/certimate/issues/326 re := regexp.MustCompile(`(?m)^\s*$\n?`) - certPem = strings.TrimSpace(re.ReplaceAllString(certPem, "")) - privkeyPem = strings.TrimSpace(re.ReplaceAllString(privkeyPem, "")) + certPEM = strings.TrimSpace(re.ReplaceAllString(certPEM, "")) + privkeyPEM = strings.TrimSpace(re.ReplaceAllString(privkeyPEM, "")) // 上传新证书 // REF: https://help.aliyun.com/zh/slb/classic-load-balancer/developer-reference/api-slb-2014-05-15-uploadservercertificate uploadServerCertificateReq := &alislb.UploadServerCertificateRequest{ RegionId: tea.String(u.config.Region), ServerCertificateName: tea.String(certName), - ServerCertificate: tea.String(certPem), - PrivateKey: tea.String(privkeyPem), + ServerCertificate: tea.String(certPEM), + PrivateKey: tea.String(privkeyPEM), } uploadServerCertificateResp, err := u.sdkClient.UploadServerCertificate(uploadServerCertificateReq) u.logger.Debug("sdk request 'slb.UploadServerCertificate'", slog.Any("request", uploadServerCertificateReq), slog.Any("response", uploadServerCertificateResp)) if err != nil { - return nil, xerrors.Wrap(err, "failed to execute sdk request 'slb.UploadServerCertificate'") + return nil, fmt.Errorf("failed to execute sdk request 'slb.UploadServerCertificate': %w", err) } certId = *uploadServerCertificateResp.Body.ServerCertificateId diff --git a/internal/pkg/core/uploader/providers/aws-acm/aws_acm.go b/internal/pkg/core/uploader/providers/aws-acm/aws_acm.go index 8e30d554..f808083c 100644 --- a/internal/pkg/core/uploader/providers/aws-acm/aws_acm.go +++ b/internal/pkg/core/uploader/providers/aws-acm/aws_acm.go @@ -1,18 +1,18 @@ -package awsacm +package awsacm import ( "context" + "fmt" "log/slog" aws "github.com/aws/aws-sdk-go-v2/aws" awscfg "github.com/aws/aws-sdk-go-v2/config" awscred "github.com/aws/aws-sdk-go-v2/credentials" awsacm "github.com/aws/aws-sdk-go-v2/service/acm" - xerrors "github.com/pkg/errors" "golang.org/x/exp/slices" "github.com/usual2970/certimate/internal/pkg/core/uploader" - "github.com/usual2970/certimate/internal/pkg/utils/certutil" + certutil "github.com/usual2970/certimate/internal/pkg/utils/cert" ) type UploaderConfig struct { @@ -39,7 +39,7 @@ func NewUploader(config *UploaderConfig) (*UploaderProvider, error) { client, err := createSdkClient(config.AccessKeyId, config.SecretAccessKey, config.Region) if err != nil { - return nil, xerrors.Wrap(err, "failed to create sdk client") + return nil, fmt.Errorf("failed to create sdk client: %w", err) } return &UploaderProvider{ @@ -58,22 +58,28 @@ func (u *UploaderProvider) WithLogger(logger *slog.Logger) uploader.Uploader { return u } -func (u *UploaderProvider) Upload(ctx context.Context, certPem string, privkeyPem string) (res *uploader.UploadResult, err error) { +func (u *UploaderProvider) Upload(ctx context.Context, certPEM string, privkeyPEM string) (res *uploader.UploadResult, err error) { // 解析证书内容 - certX509, err := certutil.ParseCertificateFromPEM(certPem) + certX509, err := certutil.ParseCertificateFromPEM(certPEM) if err != nil { return nil, err } // 生成 AWS 业务参数 - scertPem, _ := certutil.ConvertCertificateToPEM(certX509) - bcertPem := certPem + scertPEM, _ := certutil.ConvertCertificateToPEM(certX509) + bcertPEM := certPEM // 获取证书列表,避免重复上传 // REF: https://docs.aws.amazon.com/en_us/acm/latest/APIReference/API_ListCertificates.html var listCertificatesNextToken *string = nil listCertificatesMaxItems := int32(1000) for { + select { + case <-ctx.Done(): + return nil, ctx.Err() + default: + } + listCertificatesReq := &awsacm.ListCertificatesInput{ NextToken: listCertificatesNextToken, MaxItems: aws.Int32(listCertificatesMaxItems), @@ -81,7 +87,7 @@ func (u *UploaderProvider) Upload(ctx context.Context, certPem string, privkeyPe listCertificatesResp, err := u.sdkClient.ListCertificates(context.TODO(), listCertificatesReq) u.logger.Debug("sdk request 'acm.ListCertificates'", slog.Any("request", listCertificatesReq), slog.Any("response", listCertificatesResp)) if err != nil { - return nil, xerrors.Wrap(err, "failed to execute sdk request 'acm.ListCertificates'") + return nil, fmt.Errorf("failed to execute sdk request 'acm.ListCertificates': %w", err) } for _, certSummary := range listCertificatesResp.CertificateSummaryList { @@ -105,14 +111,14 @@ func (u *UploaderProvider) Upload(ctx context.Context, certPem string, privkeyPe } getCertificateResp, err := u.sdkClient.GetCertificate(context.TODO(), getCertificateReq) if err != nil { - return nil, xerrors.Wrap(err, "failed to execute sdk request 'acm.GetCertificate'") + return nil, fmt.Errorf("failed to execute sdk request 'acm.GetCertificate': %w", err) } else { - oldCertPem := aws.ToString(getCertificateResp.CertificateChain) - if oldCertPem == "" { - oldCertPem = aws.ToString(getCertificateResp.Certificate) + oldCertPEM := aws.ToString(getCertificateResp.CertificateChain) + if oldCertPEM == "" { + oldCertPEM = aws.ToString(getCertificateResp.Certificate) } - oldCertX509, err := certutil.ParseCertificateFromPEM(oldCertPem) + oldCertX509, err := certutil.ParseCertificateFromPEM(oldCertPEM) if err != nil { continue } @@ -139,14 +145,14 @@ func (u *UploaderProvider) Upload(ctx context.Context, certPem string, privkeyPe // 导入证书 // REF: https://docs.aws.amazon.com/en_us/acm/latest/APIReference/API_ImportCertificate.html importCertificateReq := &awsacm.ImportCertificateInput{ - Certificate: ([]byte)(scertPem), - CertificateChain: ([]byte)(bcertPem), - PrivateKey: ([]byte)(privkeyPem), + Certificate: ([]byte)(scertPEM), + CertificateChain: ([]byte)(bcertPEM), + PrivateKey: ([]byte)(privkeyPEM), } importCertificateResp, err := u.sdkClient.ImportCertificate(context.TODO(), importCertificateReq) u.logger.Debug("sdk request 'acm.ImportCertificate'", slog.Any("request", importCertificateReq), slog.Any("response", importCertificateResp)) if err != nil { - return nil, xerrors.Wrap(err, "failed to execute sdk request 'acm.ImportCertificate'") + return nil, fmt.Errorf("failed to execute sdk request 'acm.ImportCertificate': %w", err) } return &uploader.UploadResult{ diff --git a/internal/pkg/core/uploader/providers/azure-keyvault/azure_keyvault.go b/internal/pkg/core/uploader/providers/azure-keyvault/azure_keyvault.go index 36af11c7..5ac68d69 100644 --- a/internal/pkg/core/uploader/providers/azure-keyvault/azure_keyvault.go +++ b/internal/pkg/core/uploader/providers/azure-keyvault/azure_keyvault.go @@ -1,4 +1,4 @@ -package azurekeyvault +package azurekeyvault import ( "context" @@ -11,12 +11,11 @@ import ( "github.com/Azure/azure-sdk-for-go/sdk/azcore" "github.com/Azure/azure-sdk-for-go/sdk/azcore/to" "github.com/Azure/azure-sdk-for-go/sdk/azidentity" - "github.com/Azure/azure-sdk-for-go/sdk/keyvault/azcertificates" - xerrors "github.com/pkg/errors" + "github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azcertificates" "github.com/usual2970/certimate/internal/pkg/core/uploader" - "github.com/usual2970/certimate/internal/pkg/utils/certutil" - azcommon "github.com/usual2970/certimate/internal/pkg/vendors/azure-sdk/common" + azcommon "github.com/usual2970/certimate/internal/pkg/sdk3rd/azure/common" + certutil "github.com/usual2970/certimate/internal/pkg/utils/cert" ) type UploaderConfig struct { @@ -47,7 +46,7 @@ func NewUploader(config *UploaderConfig) (*UploaderProvider, error) { client, err := createSdkClient(config.TenantId, config.ClientId, config.ClientSecret, config.CloudName, config.KeyVaultName) if err != nil { - return nil, xerrors.Wrap(err, "failed to create sdk client") + return nil, fmt.Errorf("failed to create sdk client: %w", err) } return &UploaderProvider{ @@ -66,9 +65,9 @@ func (u *UploaderProvider) WithLogger(logger *slog.Logger) uploader.Uploader { return u } -func (u *UploaderProvider) Upload(ctx context.Context, certPem string, privkeyPem string) (res *uploader.UploadResult, err error) { +func (u *UploaderProvider) Upload(ctx context.Context, certPEM string, privkeyPEM string) (res *uploader.UploadResult, err error) { // 解析证书内容 - certX509, err := certutil.ParseCertificateFromPEM(certPem) + certX509, err := certutil.ParseCertificateFromPEM(certPEM) if err != nil { return nil, err } @@ -81,44 +80,44 @@ func (u *UploaderProvider) Upload(ctx context.Context, certPem string, privkeyPe // 获取证书列表,避免重复上传 // REF: https://learn.microsoft.com/en-us/rest/api/keyvault/certificates/get-certificates/get-certificates - listCertificatesPager := u.sdkClient.NewListCertificatesPager(nil) + listCertificatesPager := u.sdkClient.NewListCertificatePropertiesPager(nil) for listCertificatesPager.More() { page, err := listCertificatesPager.NextPage(context.TODO()) if err != nil { - return nil, xerrors.Wrap(err, "failed to execute sdk request 'keyvault.GetCertificates'") + return nil, fmt.Errorf("failed to execute sdk request 'keyvault.GetCertificates': %w", err) } - for _, certItem := range page.Value { + for _, certProp := range page.Value { // 先对比证书有效期 - if certItem.Attributes == nil { + if certProp.Attributes == nil { continue } - if certItem.Attributes.NotBefore == nil || !certItem.Attributes.NotBefore.Equal(certX509.NotBefore) { + if certProp.Attributes.NotBefore == nil || !certProp.Attributes.NotBefore.Equal(certX509.NotBefore) { continue } - if certItem.Attributes.Expires == nil || !certItem.Attributes.Expires.Equal(certX509.NotAfter) { + if certProp.Attributes.Expires == nil || !certProp.Attributes.Expires.Equal(certX509.NotAfter) { continue } // 再对比 Tag 中的通用名称 - if v, ok := certItem.Tags[TAG_CERTCN]; !ok || v == nil { + if v, ok := certProp.Tags[TAG_CERTCN]; !ok || v == nil { continue } else if *v != certCN { continue } // 再对比 Tag 中的序列号 - if v, ok := certItem.Tags[TAG_CERTSN]; !ok || v == nil { + if v, ok := certProp.Tags[TAG_CERTSN]; !ok || v == nil { continue } else if *v != certSN { continue } // 最后对比证书内容 - getCertificateResp, err := u.sdkClient.GetCertificate(context.TODO(), certItem.ID.Name(), certItem.ID.Version(), nil) - u.logger.Debug("sdk request 'keyvault.GetCertificate'", slog.String("request.certificateName", certItem.ID.Name()), slog.String("request.certificateVersion", certItem.ID.Version()), slog.Any("response", getCertificateResp)) + getCertificateResp, err := u.sdkClient.GetCertificate(context.TODO(), certProp.ID.Name(), certProp.ID.Version(), nil) + u.logger.Debug("sdk request 'keyvault.GetCertificate'", slog.String("request.certificateName", certProp.ID.Name()), slog.String("request.certificateVersion", certProp.ID.Version()), slog.Any("response", getCertificateResp)) if err != nil { - return nil, xerrors.Wrap(err, "failed to execute sdk request 'keyvault.GetCertificate'") + return nil, fmt.Errorf("failed to execute sdk request 'keyvault.GetCertificate': %w", err) } else { oldCertX509, err := x509.ParseCertificate(getCertificateResp.CER) if err != nil { @@ -133,8 +132,8 @@ func (u *UploaderProvider) Upload(ctx context.Context, certPem string, privkeyPe // 如果以上信息都一致,则视为已存在相同证书,直接返回 u.logger.Info("ssl certificate already exists") return &uploader.UploadResult{ - CertId: string(*certItem.ID), - CertName: certItem.ID.Name(), + CertId: string(*certProp.ID), + CertName: certProp.ID.Name(), }, nil } } @@ -145,15 +144,15 @@ func (u *UploaderProvider) Upload(ctx context.Context, certPem string, privkeyPe // Azure Key Vault 不支持导入带有 Certificiate Chain 的 PEM 证书。 // Issue Link: https://github.com/Azure/azure-cli/issues/19017 // 暂时的解决方法是,将 PEM 证书转换成 PFX 格式,然后再导入。 - certPfx, err := certutil.TransformCertificateFromPEMToPFX(certPem, privkeyPem, "") + certPFX, err := certutil.TransformCertificateFromPEMToPFX(certPEM, privkeyPEM, "") if err != nil { - return nil, xerrors.Wrap(err, "failed to transform certificate from PEM to PFX") + return nil, fmt.Errorf("failed to transform certificate from PEM to PFX: %w", err) } // 导入证书 // REF: https://learn.microsoft.com/en-us/rest/api/keyvault/certificates/import-certificate/import-certificate importCertificateParams := azcertificates.ImportCertificateParameters{ - Base64EncodedCertificate: to.Ptr(base64.StdEncoding.EncodeToString(certPfx)), + Base64EncodedCertificate: to.Ptr(base64.StdEncoding.EncodeToString(certPFX)), CertificatePolicy: &azcertificates.CertificatePolicy{ SecretProperties: &azcertificates.SecretProperties{ ContentType: to.Ptr("application/x-pkcs12"), @@ -167,7 +166,7 @@ func (u *UploaderProvider) Upload(ctx context.Context, certPem string, privkeyPe importCertificateResp, err := u.sdkClient.ImportCertificate(context.TODO(), certName, importCertificateParams, nil) u.logger.Debug("sdk request 'keyvault.ImportCertificate'", slog.String("request.certificateName", certName), slog.Any("request.parameters", importCertificateParams), slog.Any("response", importCertificateResp)) if err != nil { - return nil, xerrors.Wrap(err, "failed to execute sdk request 'keyvault.ImportCertificate'") + return nil, fmt.Errorf("failed to execute sdk request 'keyvault.ImportCertificate': %w", err) } return &uploader.UploadResult{ diff --git a/internal/pkg/core/uploader/providers/azure-keyvault/azure_keyvault_test.go b/internal/pkg/core/uploader/providers/azure-keyvault/azure_keyvault_test.go index 8ef63a80..492f7e5c 100644 --- a/internal/pkg/core/uploader/providers/azure-keyvault/azure_keyvault_test.go +++ b/internal/pkg/core/uploader/providers/azure-keyvault/azure_keyvault_test.go @@ -1,4 +1,4 @@ -package azurekeyvault_test +package azurekeyvault_test import ( "context" diff --git a/internal/pkg/core/uploader/providers/baiducloud-cert/baiducloud_cert.go b/internal/pkg/core/uploader/providers/baiducloud-cert/baiducloud_cert.go index 1f311f87..727aa03f 100644 --- a/internal/pkg/core/uploader/providers/baiducloud-cert/baiducloud_cert.go +++ b/internal/pkg/core/uploader/providers/baiducloud-cert/baiducloud_cert.go @@ -1,4 +1,4 @@ -package baiducloudcert +package baiducloudcert import ( "context" @@ -7,11 +7,9 @@ import ( "strings" "time" - xerrors "github.com/pkg/errors" - "github.com/usual2970/certimate/internal/pkg/core/uploader" - "github.com/usual2970/certimate/internal/pkg/utils/certutil" - bdsdk "github.com/usual2970/certimate/internal/pkg/vendors/baiducloud-sdk/cert" + bdsdk "github.com/usual2970/certimate/internal/pkg/sdk3rd/baiducloud/cert" + certutil "github.com/usual2970/certimate/internal/pkg/utils/cert" ) type UploaderConfig struct { @@ -36,7 +34,7 @@ func NewUploader(config *UploaderConfig) (*UploaderProvider, error) { client, err := createSdkClient(config.AccessKeyId, config.SecretAccessKey) if err != nil { - return nil, xerrors.Wrap(err, "failed to create sdk client") + return nil, fmt.Errorf("failed to create sdk client: %w", err) } return &UploaderProvider{ @@ -55,9 +53,9 @@ func (u *UploaderProvider) WithLogger(logger *slog.Logger) uploader.Uploader { return u } -func (u *UploaderProvider) Upload(ctx context.Context, certPem string, privkeyPem string) (res *uploader.UploadResult, err error) { +func (u *UploaderProvider) Upload(ctx context.Context, certPEM string, privkeyPEM string) (res *uploader.UploadResult, err error) { // 解析证书内容 - certX509, err := certutil.ParseCertificateFromPEM(certPem) + certX509, err := certutil.ParseCertificateFromPEM(certPEM) if err != nil { return nil, err } @@ -67,7 +65,7 @@ func (u *UploaderProvider) Upload(ctx context.Context, certPem string, privkeyPe listCertDetail, err := u.sdkClient.ListCertDetail() u.logger.Debug("sdk request 'cert.ListCertDetail'", slog.Any("response", listCertDetail)) if err != nil { - return nil, xerrors.Wrap(err, "failed to execute sdk request 'cert.ListCertDetail'") + return nil, fmt.Errorf("failed to execute sdk request 'cert.ListCertDetail': %w", err) } else { for _, certDetail := range listCertDetail.Certs { // 先对比证书通用名称 @@ -91,7 +89,7 @@ func (u *UploaderProvider) Upload(ctx context.Context, certPem string, privkeyPe getCertDetailResp, err := u.sdkClient.GetCertRawData(certDetail.CertId) u.logger.Debug("sdk request 'cert.GetCertRawData'", slog.Any("certId", certDetail.CertId), slog.Any("response", getCertDetailResp)) if err != nil { - return nil, xerrors.Wrap(err, "failed to execute sdk request 'cert.GetCertRawData'") + return nil, fmt.Errorf("failed to execute sdk request 'cert.GetCertRawData': %w", err) } else { oldCertX509, err := certutil.ParseCertificateFromPEM(getCertDetailResp.CertServerData) if err != nil { @@ -115,12 +113,12 @@ func (u *UploaderProvider) Upload(ctx context.Context, certPem string, privkeyPe // REF: https://cloud.baidu.com/doc/Reference/s/Gjwvz27xu#31-%E5%88%9B%E5%BB%BA%E8%AF%81%E4%B9%A6 createCertReq := &bdsdk.CreateCertArgs{} createCertReq.CertName = fmt.Sprintf("certimate-%d", time.Now().UnixMilli()) - createCertReq.CertServerData = certPem - createCertReq.CertPrivateData = privkeyPem + createCertReq.CertServerData = certPEM + createCertReq.CertPrivateData = privkeyPEM createCertResp, err := u.sdkClient.CreateCert(createCertReq) u.logger.Debug("sdk request 'cert.CreateCert'", slog.Any("request", createCertReq), slog.Any("response", createCertResp)) if err != nil { - return nil, xerrors.Wrap(err, "failed to execute sdk request 'cert.CreateCert'") + return nil, fmt.Errorf("failed to execute sdk request 'cert.CreateCert': %w", err) } return &uploader.UploadResult{ diff --git a/internal/pkg/core/uploader/providers/baiducloud-cert/baiducloud_cert_test.go b/internal/pkg/core/uploader/providers/baiducloud-cert/baiducloud_cert_test.go index 55de1576..80b2a7ca 100644 --- a/internal/pkg/core/uploader/providers/baiducloud-cert/baiducloud_cert_test.go +++ b/internal/pkg/core/uploader/providers/baiducloud-cert/baiducloud_cert_test.go @@ -1,4 +1,4 @@ -package baiducloudcert_test +package baiducloudcert_test import ( "context" diff --git a/internal/pkg/core/uploader/providers/byteplus-cdn/byteplus_cdn.go b/internal/pkg/core/uploader/providers/byteplus-cdn/byteplus_cdn.go index cdba9d4f..1235893c 100644 --- a/internal/pkg/core/uploader/providers/byteplus-cdn/byteplus_cdn.go +++ b/internal/pkg/core/uploader/providers/byteplus-cdn/byteplus_cdn.go @@ -11,10 +11,9 @@ import ( "time" bytepluscdn "github.com/byteplus-sdk/byteplus-sdk-golang/service/cdn" - xerrors "github.com/pkg/errors" "github.com/usual2970/certimate/internal/pkg/core/uploader" - "github.com/usual2970/certimate/internal/pkg/utils/certutil" + certutil "github.com/usual2970/certimate/internal/pkg/utils/cert" ) type UploaderConfig struct { @@ -57,9 +56,9 @@ func (u *UploaderProvider) WithLogger(logger *slog.Logger) uploader.Uploader { return u } -func (u *UploaderProvider) Upload(ctx context.Context, certPem string, privkeyPem string) (res *uploader.UploadResult, err error) { +func (u *UploaderProvider) Upload(ctx context.Context, certPEM string, privkeyPEM string) (res *uploader.UploadResult, err error) { // 解析证书内容 - certX509, err := certutil.ParseCertificateFromPEM(certPem) + certX509, err := certutil.ParseCertificateFromPEM(certPEM) if err != nil { return nil, err } @@ -75,10 +74,16 @@ func (u *UploaderProvider) Upload(ctx context.Context, certPem string, privkeyPe Source: bytepluscdn.GetStrPtr("cert_center"), } for { + select { + case <-ctx.Done(): + return nil, ctx.Err() + default: + } + listCertInfoResp, err := u.sdkClient.ListCertInfo(listCertInfoReq) u.logger.Debug("sdk request 'cdn.ListCertInfo'", slog.Any("request", listCertInfoReq), slog.Any("response", listCertInfoResp)) if err != nil { - return nil, xerrors.Wrap(err, "failed to execute sdk request 'cdn.ListCertInfo'") + return nil, fmt.Errorf("failed to execute sdk request 'cdn.ListCertInfo': %w", err) } if listCertInfoResp.Result.CertInfo != nil { @@ -114,15 +119,15 @@ func (u *UploaderProvider) Upload(ctx context.Context, certPem string, privkeyPe // 上传新证书 // REF: https://docs.byteplus.com/en/docs/byteplus-cdn/reference-addcertificate addCertificateReq := &bytepluscdn.AddCertificateRequest{ - Certificate: certPem, - PrivateKey: privkeyPem, + Certificate: certPEM, + PrivateKey: privkeyPEM, Source: bytepluscdn.GetStrPtr("cert_center"), Desc: bytepluscdn.GetStrPtr(certName), } addCertificateResp, err := u.sdkClient.AddCertificate(addCertificateReq) u.logger.Debug("sdk request 'cdn.AddCertificate'", slog.Any("request", addCertificateReq), slog.Any("response", addCertificateResp)) if err != nil { - return nil, xerrors.Wrap(err, "failed to execute sdk request 'cdn.AddCertificate'") + return nil, fmt.Errorf("failed to execute sdk request 'cdn.AddCertificate': %w", err) } certId = addCertificateResp.Result.CertId diff --git a/internal/pkg/core/uploader/providers/dogecloud/dogecloud.go b/internal/pkg/core/uploader/providers/dogecloud/dogecloud.go index 420f93bc..ca98fc90 100644 --- a/internal/pkg/core/uploader/providers/dogecloud/dogecloud.go +++ b/internal/pkg/core/uploader/providers/dogecloud/dogecloud.go @@ -1,4 +1,4 @@ -package dogecloud +package dogecloud import ( "context" @@ -6,10 +6,8 @@ import ( "log/slog" "time" - xerrors "github.com/pkg/errors" - "github.com/usual2970/certimate/internal/pkg/core/uploader" - dogesdk "github.com/usual2970/certimate/internal/pkg/vendors/dogecloud-sdk" + dogesdk "github.com/usual2970/certimate/internal/pkg/sdk3rd/dogecloud" ) type UploaderConfig struct { @@ -34,7 +32,7 @@ func NewUploader(config *UploaderConfig) (*UploaderProvider, error) { client, err := createSdkClient(config.AccessKey, config.SecretKey) if err != nil { - return nil, xerrors.Wrap(err, "failed to create sdk client") + return nil, fmt.Errorf("failed to create sdk client: %w", err) } return &UploaderProvider{ @@ -53,17 +51,17 @@ func (u *UploaderProvider) WithLogger(logger *slog.Logger) uploader.Uploader { return u } -func (u *UploaderProvider) Upload(ctx context.Context, certPem string, privkeyPem string) (res *uploader.UploadResult, err error) { +func (u *UploaderProvider) Upload(ctx context.Context, certPEM string, privkeyPEM string) (res *uploader.UploadResult, err error) { // 生成新证书名(需符合多吉云命名规则) var certId, certName string certName = fmt.Sprintf("certimate-%d", time.Now().UnixMilli()) // 上传新证书 // REF: https://docs.dogecloud.com/cdn/api-cert-upload - uploadSslCertResp, err := u.sdkClient.UploadCdnCert(certName, certPem, privkeyPem) + uploadSslCertResp, err := u.sdkClient.UploadCdnCert(certName, certPEM, privkeyPEM) u.logger.Debug("sdk request 'cdn.UploadCdnCert'", slog.Any("response", uploadSslCertResp)) if err != nil { - return nil, xerrors.Wrap(err, "failed to execute sdk request 'cdn.UploadCdnCert'") + return nil, fmt.Errorf("failed to execute sdk request 'cdn.UploadCdnCert': %w", err) } certId = fmt.Sprintf("%d", uploadSslCertResp.Data.Id) diff --git a/internal/pkg/core/uploader/providers/gcore-cdn/gcore_cdn.go b/internal/pkg/core/uploader/providers/gcore-cdn/gcore_cdn.go index 7f0a6580..c5dc5296 100644 --- a/internal/pkg/core/uploader/providers/gcore-cdn/gcore_cdn.go +++ b/internal/pkg/core/uploader/providers/gcore-cdn/gcore_cdn.go @@ -1,4 +1,4 @@ -package gcorecdn +package gcorecdn import ( "context" @@ -9,10 +9,9 @@ import ( gprovider "github.com/G-Core/gcorelabscdn-go/gcore/provider" gsslcerts "github.com/G-Core/gcorelabscdn-go/sslcerts" - xerrors "github.com/pkg/errors" "github.com/usual2970/certimate/internal/pkg/core/uploader" - gcoresdk "github.com/usual2970/certimate/internal/pkg/vendors/gcore-sdk/common" + gcoresdk "github.com/usual2970/certimate/internal/pkg/sdk3rd/gcore/common" ) type UploaderConfig struct { @@ -35,7 +34,7 @@ func NewUploader(config *UploaderConfig) (*UploaderProvider, error) { client, err := createSdkClient(config.ApiToken) if err != nil { - return nil, xerrors.Wrap(err, "failed to create sdk client") + return nil, fmt.Errorf("failed to create sdk client: %w", err) } return &UploaderProvider{ @@ -54,7 +53,7 @@ func (u *UploaderProvider) WithLogger(logger *slog.Logger) uploader.Uploader { return u } -func (u *UploaderProvider) Upload(ctx context.Context, certPem string, privkeyPem string) (res *uploader.UploadResult, err error) { +func (u *UploaderProvider) Upload(ctx context.Context, certPEM string, privkeyPEM string) (res *uploader.UploadResult, err error) { // 生成新证书名(需符合 Gcore 命名规则) var certId, certName string certName = fmt.Sprintf("certimate_%d", time.Now().UnixMilli()) @@ -63,15 +62,15 @@ func (u *UploaderProvider) Upload(ctx context.Context, certPem string, privkeyPe // REF: https://api.gcore.com/docs/cdn#tag/CA-certificates/operation/ca_certificates-add createCertificateReq := &gsslcerts.CreateRequest{ Name: certName, - Cert: certPem, - PrivateKey: privkeyPem, + Cert: certPEM, + PrivateKey: privkeyPEM, Automated: false, ValidateRootCA: false, } createCertificateResp, err := u.sdkClient.Create(context.TODO(), createCertificateReq) u.logger.Debug("sdk request 'sslcerts.Create'", slog.Any("request", createCertificateReq), slog.Any("response", createCertificateResp)) if err != nil { - return nil, xerrors.Wrap(err, "failed to execute sdk request 'sslcerts.Create'") + return nil, fmt.Errorf("failed to execute sdk request 'sslcerts.Create': %w", err) } certId = fmt.Sprintf("%d", createCertificateResp.ID) diff --git a/internal/pkg/core/uploader/providers/huaweicloud-elb/huaweicloud_elb.go b/internal/pkg/core/uploader/providers/huaweicloud-elb/huaweicloud_elb.go index 50d716a1..9369144e 100644 --- a/internal/pkg/core/uploader/providers/huaweicloud-elb/huaweicloud_elb.go +++ b/internal/pkg/core/uploader/providers/huaweicloud-elb/huaweicloud_elb.go @@ -1,4 +1,4 @@ -package huaweicloudelb +package huaweicloudelb import ( "context" @@ -15,11 +15,10 @@ import ( hciam "github.com/huaweicloud/huaweicloud-sdk-go-v3/services/iam/v3" hciammodel "github.com/huaweicloud/huaweicloud-sdk-go-v3/services/iam/v3/model" hciamregion "github.com/huaweicloud/huaweicloud-sdk-go-v3/services/iam/v3/region" - xerrors "github.com/pkg/errors" "github.com/usual2970/certimate/internal/pkg/core/uploader" - "github.com/usual2970/certimate/internal/pkg/utils/certutil" - hwsdk "github.com/usual2970/certimate/internal/pkg/vendors/huaweicloud-sdk" + certutil "github.com/usual2970/certimate/internal/pkg/utils/cert" + typeutil "github.com/usual2970/certimate/internal/pkg/utils/type" ) type UploaderConfig struct { @@ -46,7 +45,7 @@ func NewUploader(config *UploaderConfig) (*UploaderProvider, error) { client, err := createSdkClient(config.AccessKeyId, config.SecretAccessKey, config.Region) if err != nil { - return nil, xerrors.Wrap(err, "failed to create sdk client") + return nil, fmt.Errorf("failed to create sdk client: %w", err) } return &UploaderProvider{ @@ -65,9 +64,9 @@ func (u *UploaderProvider) WithLogger(logger *slog.Logger) uploader.Uploader { return u } -func (u *UploaderProvider) Upload(ctx context.Context, certPem string, privkeyPem string) (res *uploader.UploadResult, err error) { +func (u *UploaderProvider) Upload(ctx context.Context, certPEM string, privkeyPEM string) (res *uploader.UploadResult, err error) { // 解析证书内容 - certX509, err := certutil.ParseCertificateFromPEM(certPem) + certX509, err := certutil.ParseCertificateFromPEM(certPEM) if err != nil { return nil, err } @@ -77,21 +76,27 @@ func (u *UploaderProvider) Upload(ctx context.Context, certPem string, privkeyPe listCertificatesLimit := int32(2000) var listCertificatesMarker *string = nil for { + select { + case <-ctx.Done(): + return nil, ctx.Err() + default: + } + listCertificatesReq := &hcelbmodel.ListCertificatesRequest{ - Limit: hwsdk.Int32Ptr(listCertificatesLimit), + Limit: typeutil.ToPtr(listCertificatesLimit), Marker: listCertificatesMarker, Type: &[]string{"server"}, } listCertificatesResp, err := u.sdkClient.ListCertificates(listCertificatesReq) u.logger.Debug("sdk request 'elb.ListCertificates'", slog.Any("request", listCertificatesReq), slog.Any("response", listCertificatesResp)) if err != nil { - return nil, xerrors.Wrap(err, "failed to execute sdk request 'elb.ListCertificates'") + return nil, fmt.Errorf("failed to execute sdk request 'elb.ListCertificates': %w", err) } if listCertificatesResp.Certificates != nil { for _, certDetail := range *listCertificatesResp.Certificates { var isSameCert bool - if certDetail.Certificate == certPem { + if certDetail.Certificate == certPEM { isSameCert = true } else { oldCertX509, err := certutil.ParseCertificateFromPEM(certDetail.Certificate) @@ -124,7 +129,7 @@ func (u *UploaderProvider) Upload(ctx context.Context, certPem string, privkeyPe // REF: https://support.huaweicloud.com/api-iam/iam_06_0001.html projectId, err := getSdkProjectId(u.config.AccessKeyId, u.config.SecretAccessKey, u.config.Region) if err != nil { - return nil, xerrors.Wrap(err, "failed to get SDK project id") + return nil, fmt.Errorf("failed to get SDK project id: %w", err) } // 生成新证书名(需符合华为云命名规则) @@ -136,17 +141,17 @@ func (u *UploaderProvider) Upload(ctx context.Context, certPem string, privkeyPe createCertificateReq := &hcelbmodel.CreateCertificateRequest{ Body: &hcelbmodel.CreateCertificateRequestBody{ Certificate: &hcelbmodel.CreateCertificateOption{ - ProjectId: hwsdk.StringPtr(projectId), - Name: hwsdk.StringPtr(certName), - Certificate: hwsdk.StringPtr(certPem), - PrivateKey: hwsdk.StringPtr(privkeyPem), + ProjectId: typeutil.ToPtr(projectId), + Name: typeutil.ToPtr(certName), + Certificate: typeutil.ToPtr(certPEM), + PrivateKey: typeutil.ToPtr(privkeyPEM), }, }, } createCertificateResp, err := u.sdkClient.CreateCertificate(createCertificateReq) u.logger.Debug("sdk request 'elb.CreateCertificate'", slog.Any("request", createCertificateReq), slog.Any("response", createCertificateResp)) if err != nil { - return nil, xerrors.Wrap(err, "failed to execute sdk request 'elb.CreateCertificate'") + return nil, fmt.Errorf("failed to execute sdk request 'elb.CreateCertificate': %w", err) } certId = createCertificateResp.Certificate.Id diff --git a/internal/pkg/core/uploader/providers/huaweicloud-scm/huaweicloud_scm.go b/internal/pkg/core/uploader/providers/huaweicloud-scm/huaweicloud_scm.go index 94413993..f8435733 100644 --- a/internal/pkg/core/uploader/providers/huaweicloud-scm/huaweicloud_scm.go +++ b/internal/pkg/core/uploader/providers/huaweicloud-scm/huaweicloud_scm.go @@ -1,4 +1,4 @@ -package huaweicloudscm +package huaweicloudscm import ( "context" @@ -10,11 +10,10 @@ import ( hcscm "github.com/huaweicloud/huaweicloud-sdk-go-v3/services/scm/v3" hcscmmodel "github.com/huaweicloud/huaweicloud-sdk-go-v3/services/scm/v3/model" hcscmregion "github.com/huaweicloud/huaweicloud-sdk-go-v3/services/scm/v3/region" - xerrors "github.com/pkg/errors" "github.com/usual2970/certimate/internal/pkg/core/uploader" - "github.com/usual2970/certimate/internal/pkg/utils/certutil" - hwsdk "github.com/usual2970/certimate/internal/pkg/vendors/huaweicloud-sdk" + certutil "github.com/usual2970/certimate/internal/pkg/utils/cert" + typeutil "github.com/usual2970/certimate/internal/pkg/utils/type" ) type UploaderConfig struct { @@ -41,7 +40,7 @@ func NewUploader(config *UploaderConfig) (*UploaderProvider, error) { client, err := createSdkClient(config.AccessKeyId, config.SecretAccessKey, config.Region) if err != nil { - return nil, xerrors.Wrap(err, "failed to create sdk client") + return nil, fmt.Errorf("failed to create sdk client: %w", err) } return &UploaderProvider{ @@ -60,9 +59,9 @@ func (u *UploaderProvider) WithLogger(logger *slog.Logger) uploader.Uploader { return u } -func (u *UploaderProvider) Upload(ctx context.Context, certPem string, privkeyPem string) (res *uploader.UploadResult, err error) { +func (u *UploaderProvider) Upload(ctx context.Context, certPEM string, privkeyPEM string) (res *uploader.UploadResult, err error) { // 解析证书内容 - certX509, err := certutil.ParseCertificateFromPEM(certPem) + certX509, err := certutil.ParseCertificateFromPEM(certPEM) if err != nil { return nil, err } @@ -73,16 +72,22 @@ func (u *UploaderProvider) Upload(ctx context.Context, certPem string, privkeyPe listCertificatesLimit := int32(50) listCertificatesOffset := int32(0) for { + select { + case <-ctx.Done(): + return nil, ctx.Err() + default: + } + listCertificatesReq := &hcscmmodel.ListCertificatesRequest{ - Limit: hwsdk.Int32Ptr(listCertificatesLimit), - Offset: hwsdk.Int32Ptr(listCertificatesOffset), - SortDir: hwsdk.StringPtr("DESC"), - SortKey: hwsdk.StringPtr("certExpiredTime"), + Limit: typeutil.ToPtr(listCertificatesLimit), + Offset: typeutil.ToPtr(listCertificatesOffset), + SortDir: typeutil.ToPtr("DESC"), + SortKey: typeutil.ToPtr("certExpiredTime"), } listCertificatesResp, err := u.sdkClient.ListCertificates(listCertificatesReq) u.logger.Debug("sdk request 'scm.ListCertificates'", slog.Any("request", listCertificatesReq), slog.Any("response", listCertificatesResp)) if err != nil { - return nil, xerrors.Wrap(err, "failed to execute sdk request 'scm.ListCertificates'") + return nil, fmt.Errorf("failed to execute sdk request 'scm.ListCertificates': %w", err) } if listCertificatesResp.Certificates != nil { @@ -96,11 +101,11 @@ func (u *UploaderProvider) Upload(ctx context.Context, certPem string, privkeyPe if exportCertificateResp != nil && exportCertificateResp.HttpStatusCode == 404 { continue } - return nil, xerrors.Wrap(err, "failed to execute sdk request 'scm.ExportCertificate'") + return nil, fmt.Errorf("failed to execute sdk request 'scm.ExportCertificate': %w", err) } var isSameCert bool - if *exportCertificateResp.Certificate == certPem { + if *exportCertificateResp.Certificate == certPEM { isSameCert = true } else { oldCertX509, err := certutil.ParseCertificateFromPEM(*exportCertificateResp.Certificate) @@ -138,14 +143,14 @@ func (u *UploaderProvider) Upload(ctx context.Context, certPem string, privkeyPe importCertificateReq := &hcscmmodel.ImportCertificateRequest{ Body: &hcscmmodel.ImportCertificateRequestBody{ Name: certName, - Certificate: certPem, - PrivateKey: privkeyPem, + Certificate: certPEM, + PrivateKey: privkeyPEM, }, } importCertificateResp, err := u.sdkClient.ImportCertificate(importCertificateReq) u.logger.Debug("sdk request 'scm.ImportCertificate'", slog.Any("request", importCertificateReq), slog.Any("response", importCertificateResp)) if err != nil { - return nil, xerrors.Wrap(err, "failed to execute sdk request 'scm.ImportCertificate'") + return nil, fmt.Errorf("failed to execute sdk request 'scm.ImportCertificate': %w", err) } certId = *importCertificateResp.CertificateId diff --git a/internal/pkg/core/uploader/providers/huaweicloud-waf/huaweicloud_waf.go b/internal/pkg/core/uploader/providers/huaweicloud-waf/huaweicloud_waf.go index 86d25426..d0c61775 100644 --- a/internal/pkg/core/uploader/providers/huaweicloud-waf/huaweicloud_waf.go +++ b/internal/pkg/core/uploader/providers/huaweicloud-waf/huaweicloud_waf.go @@ -1,4 +1,4 @@ -package huaweicloudwaf +package huaweicloudwaf import ( "context" @@ -15,11 +15,10 @@ import ( hcwaf "github.com/huaweicloud/huaweicloud-sdk-go-v3/services/waf/v1" hcwafmodel "github.com/huaweicloud/huaweicloud-sdk-go-v3/services/waf/v1/model" hcwafregion "github.com/huaweicloud/huaweicloud-sdk-go-v3/services/waf/v1/region" - xerrors "github.com/pkg/errors" "github.com/usual2970/certimate/internal/pkg/core/uploader" - "github.com/usual2970/certimate/internal/pkg/utils/certutil" - hwsdk "github.com/usual2970/certimate/internal/pkg/vendors/huaweicloud-sdk" + certutil "github.com/usual2970/certimate/internal/pkg/utils/cert" + typeutil "github.com/usual2970/certimate/internal/pkg/utils/type" ) type UploaderConfig struct { @@ -46,7 +45,7 @@ func NewUploader(config *UploaderConfig) (*UploaderProvider, error) { client, err := createSdkClient(config.AccessKeyId, config.SecretAccessKey, config.Region) if err != nil { - return nil, xerrors.Wrap(err, "failed to create sdk client") + return nil, fmt.Errorf("failed to create sdk client: %w", err) } return &UploaderProvider{ @@ -65,9 +64,9 @@ func (u *UploaderProvider) WithLogger(logger *slog.Logger) uploader.Uploader { return u } -func (u *UploaderProvider) Upload(ctx context.Context, certPem string, privkeyPem string) (res *uploader.UploadResult, err error) { +func (u *UploaderProvider) Upload(ctx context.Context, certPEM string, privkeyPEM string) (res *uploader.UploadResult, err error) { // 解析证书内容 - certX509, err := certutil.ParseCertificateFromPEM(certPem) + certX509, err := certutil.ParseCertificateFromPEM(certPEM) if err != nil { return nil, err } @@ -78,14 +77,20 @@ func (u *UploaderProvider) Upload(ctx context.Context, certPem string, privkeyPe listCertificatesPage := int32(1) listCertificatesPageSize := int32(100) for { + select { + case <-ctx.Done(): + return nil, ctx.Err() + default: + } + listCertificatesReq := &hcwafmodel.ListCertificatesRequest{ - Page: hwsdk.Int32Ptr(listCertificatesPage), - Pagesize: hwsdk.Int32Ptr(listCertificatesPageSize), + Page: typeutil.ToPtr(listCertificatesPage), + Pagesize: typeutil.ToPtr(listCertificatesPageSize), } listCertificatesResp, err := u.sdkClient.ListCertificates(listCertificatesReq) u.logger.Debug("sdk request 'waf.ShowCertificate'", slog.Any("request", listCertificatesReq), slog.Any("response", listCertificatesResp)) if err != nil { - return nil, xerrors.Wrap(err, "failed to execute sdk request 'waf.ListCertificates'") + return nil, fmt.Errorf("failed to execute sdk request 'waf.ListCertificates': %w", err) } if listCertificatesResp.Items != nil { @@ -96,11 +101,11 @@ func (u *UploaderProvider) Upload(ctx context.Context, certPem string, privkeyPe showCertificateResp, err := u.sdkClient.ShowCertificate(showCertificateReq) u.logger.Debug("sdk request 'waf.ShowCertificate'", slog.Any("request", showCertificateReq), slog.Any("response", showCertificateResp)) if err != nil { - return nil, xerrors.Wrap(err, "failed to execute sdk request 'waf.ShowCertificate'") + return nil, fmt.Errorf("failed to execute sdk request 'waf.ShowCertificate': %w", err) } var isSameCert bool - if *showCertificateResp.Content == certPem { + if *showCertificateResp.Content == certPEM { isSameCert = true } else { oldCertX509, err := certutil.ParseCertificateFromPEM(*showCertificateResp.Content) @@ -138,14 +143,14 @@ func (u *UploaderProvider) Upload(ctx context.Context, certPem string, privkeyPe createCertificateReq := &hcwafmodel.CreateCertificateRequest{ Body: &hcwafmodel.CreateCertificateRequestBody{ Name: certName, - Content: certPem, - Key: privkeyPem, + Content: certPEM, + Key: privkeyPEM, }, } createCertificateResp, err := u.sdkClient.CreateCertificate(createCertificateReq) u.logger.Debug("sdk request 'waf.CreateCertificate'", slog.Any("request", createCertificateReq), slog.Any("response", createCertificateResp)) if err != nil { - return nil, xerrors.Wrap(err, "failed to execute sdk request 'waf.CreateCertificate'") + return nil, fmt.Errorf("failed to execute sdk request 'waf.CreateCertificate': %w", err) } certId = *createCertificateResp.Id diff --git a/internal/pkg/core/uploader/providers/jdcloud-ssl/jdcloud_ssl.go b/internal/pkg/core/uploader/providers/jdcloud-ssl/jdcloud_ssl.go index 10f7c203..b26755a6 100644 --- a/internal/pkg/core/uploader/providers/jdcloud-ssl/jdcloud_ssl.go +++ b/internal/pkg/core/uploader/providers/jdcloud-ssl/jdcloud_ssl.go @@ -1,4 +1,4 @@ -package jdcloudssl +package jdcloudssl import ( "context" @@ -12,11 +12,10 @@ import ( jdcore "github.com/jdcloud-api/jdcloud-sdk-go/core" jdsslapi "github.com/jdcloud-api/jdcloud-sdk-go/services/ssl/apis" jdsslclient "github.com/jdcloud-api/jdcloud-sdk-go/services/ssl/client" - xerrors "github.com/pkg/errors" "golang.org/x/exp/slices" "github.com/usual2970/certimate/internal/pkg/core/uploader" - "github.com/usual2970/certimate/internal/pkg/utils/certutil" + certutil "github.com/usual2970/certimate/internal/pkg/utils/cert" ) type UploaderConfig struct { @@ -41,7 +40,7 @@ func NewUploader(config *UploaderConfig) (*UploaderProvider, error) { client, err := createSdkClient(config.AccessKeyId, config.AccessKeySecret) if err != nil { - return nil, xerrors.Wrap(err, "failed to create sdk client") + return nil, fmt.Errorf("failed to create sdk client: %w", err) } return &UploaderProvider{ @@ -60,24 +59,30 @@ func (u *UploaderProvider) WithLogger(logger *slog.Logger) uploader.Uploader { return u } -func (u *UploaderProvider) Upload(ctx context.Context, certPem string, privkeyPem string) (res *uploader.UploadResult, err error) { +func (u *UploaderProvider) Upload(ctx context.Context, certPEM string, privkeyPEM string) (res *uploader.UploadResult, err error) { // 解析证书内容 - certX509, err := certutil.ParseCertificateFromPEM(certPem) + certX509, err := certutil.ParseCertificateFromPEM(certPEM) if err != nil { return nil, err } // 格式化私钥内容,以便后续计算私钥摘要 - privkeyPem = strings.TrimSpace(privkeyPem) - privkeyPem = strings.ReplaceAll(privkeyPem, "\r", "") - privkeyPem = strings.ReplaceAll(privkeyPem, "\n", "\r\n") - privkeyPem = privkeyPem + "\r\n" + privkeyPEM = strings.TrimSpace(privkeyPEM) + privkeyPEM = strings.ReplaceAll(privkeyPEM, "\r", "") + privkeyPEM = strings.ReplaceAll(privkeyPEM, "\n", "\r\n") + privkeyPEM = privkeyPEM + "\r\n" // 遍历查看证书列表,避免重复上传 // REF: https://docs.jdcloud.com/cn/ssl-certificate/api/describecerts describeCertsPageNumber := 1 describeCertsPageSize := 10 for { + select { + case <-ctx.Done(): + return nil, ctx.Err() + default: + } + describeCertsReq := jdsslapi.NewDescribeCertsRequest() describeCertsReq.SetDomainName(certX509.Subject.CommonName) describeCertsReq.SetPageNumber(describeCertsPageNumber) @@ -85,7 +90,7 @@ func (u *UploaderProvider) Upload(ctx context.Context, certPem string, privkeyPe describeCertsResp, err := u.sdkClient.DescribeCerts(describeCertsReq) u.logger.Debug("sdk request 'ssl.DescribeCerts'", slog.Any("request", describeCertsReq), slog.Any("response", describeCertsResp)) if err != nil { - return nil, xerrors.Wrap(err, "failed to execute sdk request 'ssl.DescribeCerts'") + return nil, fmt.Errorf("failed to execute sdk request 'ssl.DescribeCerts': %w", err) } for _, certDetail := range describeCertsResp.Result.CertListDetails { @@ -107,7 +112,7 @@ func (u *UploaderProvider) Upload(ctx context.Context, certPem string, privkeyPe } // 最后对比私钥摘要 - newKeyDigest := sha256.Sum256([]byte(privkeyPem)) + newKeyDigest := sha256.Sum256([]byte(privkeyPEM)) newKeyDigestHex := hex.EncodeToString(newKeyDigest[:]) if !strings.EqualFold(newKeyDigestHex, certDetail.Digest) { continue @@ -133,11 +138,11 @@ func (u *UploaderProvider) Upload(ctx context.Context, certPem string, privkeyPe // 上传证书 // REF: https://docs.jdcloud.com/cn/ssl-certificate/api/uploadcert - uploadCertReq := jdsslapi.NewUploadCertRequest(certName, privkeyPem, certPem) + uploadCertReq := jdsslapi.NewUploadCertRequest(certName, privkeyPEM, certPEM) uploadCertResp, err := u.sdkClient.UploadCert(uploadCertReq) u.logger.Debug("sdk request 'ssl.UploadCertificate'", slog.Any("request", uploadCertReq), slog.Any("response", uploadCertResp)) if err != nil { - return nil, xerrors.Wrap(err, "failed to execute sdk request 'ssl.UploadCertificate'") + return nil, fmt.Errorf("failed to execute sdk request 'ssl.UploadCertificate': %w", err) } return &uploader.UploadResult{ diff --git a/internal/pkg/core/uploader/providers/jdcloud-ssl/jdcloud_ssl_test.go b/internal/pkg/core/uploader/providers/jdcloud-ssl/jdcloud_ssl_test.go index ec02ce49..273310e0 100644 --- a/internal/pkg/core/uploader/providers/jdcloud-ssl/jdcloud_ssl_test.go +++ b/internal/pkg/core/uploader/providers/jdcloud-ssl/jdcloud_ssl_test.go @@ -1,4 +1,4 @@ -package jdcloudssl_test +package jdcloudssl_test import ( "context" diff --git a/internal/pkg/core/uploader/providers/qiniu-sslcert/qiniu_sslcert.go b/internal/pkg/core/uploader/providers/qiniu-sslcert/qiniu_sslcert.go index 6bc71c3f..8dc2fefe 100644 --- a/internal/pkg/core/uploader/providers/qiniu-sslcert/qiniu_sslcert.go +++ b/internal/pkg/core/uploader/providers/qiniu-sslcert/qiniu_sslcert.go @@ -1,4 +1,4 @@ -package qiniusslcert +package qiniusslcert import ( "context" @@ -7,12 +7,11 @@ import ( "log/slog" "time" - xerrors "github.com/pkg/errors" "github.com/qiniu/go-sdk/v7/auth" "github.com/usual2970/certimate/internal/pkg/core/uploader" - "github.com/usual2970/certimate/internal/pkg/utils/certutil" - qiniusdk "github.com/usual2970/certimate/internal/pkg/vendors/qiniu-sdk" + qiniusdk "github.com/usual2970/certimate/internal/pkg/sdk3rd/qiniu" + certutil "github.com/usual2970/certimate/internal/pkg/utils/cert" ) type UploaderConfig struct { @@ -37,7 +36,7 @@ func NewUploader(config *UploaderConfig) (*UploaderProvider, error) { client, err := createSdkClient(config.AccessKey, config.SecretKey) if err != nil { - return nil, xerrors.Wrap(err, "failed to create sdk client") + return nil, fmt.Errorf("failed to create sdk client: %w", err) } return &UploaderProvider{ @@ -56,9 +55,9 @@ func (u *UploaderProvider) WithLogger(logger *slog.Logger) uploader.Uploader { return u } -func (u *UploaderProvider) Upload(ctx context.Context, certPem string, privkeyPem string) (res *uploader.UploadResult, err error) { +func (u *UploaderProvider) Upload(ctx context.Context, certPEM string, privkeyPEM string) (res *uploader.UploadResult, err error) { // 解析证书内容 - certX509, err := certutil.ParseCertificateFromPEM(certPem) + certX509, err := certutil.ParseCertificateFromPEM(certPEM) if err != nil { return nil, err } @@ -69,10 +68,10 @@ func (u *UploaderProvider) Upload(ctx context.Context, certPem string, privkeyPe // 上传新证书 // REF: https://developer.qiniu.com/fusion/8593/interface-related-certificate - uploadSslCertResp, err := u.sdkClient.UploadSslCert(context.TODO(), certName, certX509.Subject.CommonName, certPem, privkeyPem) + uploadSslCertResp, err := u.sdkClient.UploadSslCert(context.TODO(), certName, certX509.Subject.CommonName, certPEM, privkeyPEM) u.logger.Debug("sdk request 'cdn.UploadSslCert'", slog.Any("response", uploadSslCertResp)) if err != nil { - return nil, xerrors.Wrap(err, "failed to execute sdk request 'cdn.UploadSslCert'") + return nil, fmt.Errorf("failed to execute sdk request 'cdn.UploadSslCert': %w", err) } certId = uploadSslCertResp.CertID diff --git a/internal/pkg/core/uploader/providers/rainyun-sslcenter/rainyun_sslcenter.go b/internal/pkg/core/uploader/providers/rainyun-sslcenter/rainyun_sslcenter.go index f2ee4bde..cb493110 100644 --- a/internal/pkg/core/uploader/providers/rainyun-sslcenter/rainyun_sslcenter.go +++ b/internal/pkg/core/uploader/providers/rainyun-sslcenter/rainyun_sslcenter.go @@ -7,11 +7,9 @@ import ( "log/slog" "strings" - xerrors "github.com/pkg/errors" - "github.com/usual2970/certimate/internal/pkg/core/uploader" - "github.com/usual2970/certimate/internal/pkg/utils/certutil" - rainyunsdk "github.com/usual2970/certimate/internal/pkg/vendors/rainyun-sdk" + rainyunsdk "github.com/usual2970/certimate/internal/pkg/sdk3rd/rainyun" + certutil "github.com/usual2970/certimate/internal/pkg/utils/cert" ) type UploaderConfig struct { @@ -34,7 +32,7 @@ func NewUploader(config *UploaderConfig) (*UploaderProvider, error) { client, err := createSdkClient(config.ApiKey) if err != nil { - return nil, xerrors.Wrap(err, "failed to create sdk client") + return nil, fmt.Errorf("failed to create sdk client: %w", err) } return &UploaderProvider{ @@ -53,8 +51,8 @@ func (u *UploaderProvider) WithLogger(logger *slog.Logger) uploader.Uploader { return u } -func (u *UploaderProvider) Upload(ctx context.Context, certPem string, privkeyPem string) (res *uploader.UploadResult, err error) { - if res, err := u.getCertIfExists(ctx, certPem); err != nil { +func (u *UploaderProvider) Upload(ctx context.Context, certPEM string, privkeyPEM string) (res *uploader.UploadResult, err error) { + if res, err := u.getCertIfExists(ctx, certPEM); err != nil { return nil, err } else if res != nil { u.logger.Info("ssl certificate already exists") @@ -64,16 +62,16 @@ func (u *UploaderProvider) Upload(ctx context.Context, certPem string, privkeyPe // SSL 证书上传 // REF: https://apifox.com/apidoc/shared/a4595cc8-44c5-4678-a2a3-eed7738dab03/api-69943046 sslCenterCreateReq := &rainyunsdk.SslCenterCreateRequest{ - Cert: certPem, - Key: privkeyPem, + Cert: certPEM, + Key: privkeyPEM, } sslCenterCreateResp, err := u.sdkClient.SslCenterCreate(sslCenterCreateReq) u.logger.Debug("sdk request 'sslcenter.Create'", slog.Any("request", sslCenterCreateReq), slog.Any("response", sslCenterCreateResp)) if err != nil { - return nil, xerrors.Wrap(err, "failed to execute sdk request 'sslcenter.Create'") + return nil, fmt.Errorf("failed to execute sdk request 'sslcenter.Create': %w", err) } - if res, err := u.getCertIfExists(ctx, certPem); err != nil { + if res, err := u.getCertIfExists(ctx, certPEM); err != nil { return nil, err } else if res == nil { return nil, errors.New("rainyun sslcenter: no certificate found") @@ -82,9 +80,9 @@ func (u *UploaderProvider) Upload(ctx context.Context, certPem string, privkeyPe } } -func (u *UploaderProvider) getCertIfExists(ctx context.Context, certPem string) (res *uploader.UploadResult, err error) { +func (u *UploaderProvider) getCertIfExists(ctx context.Context, certPEM string) (res *uploader.UploadResult, err error) { // 解析证书内容 - certX509, err := certutil.ParseCertificateFromPEM(certPem) + certX509, err := certutil.ParseCertificateFromPEM(certPEM) if err != nil { return nil, err } @@ -95,6 +93,12 @@ func (u *UploaderProvider) getCertIfExists(ctx context.Context, certPem string) sslCenterListPage := int32(1) sslCenterListPerPage := int32(100) for { + select { + case <-ctx.Done(): + return nil, ctx.Err() + default: + } + sslCenterListReq := &rainyunsdk.SslCenterListRequest{ Filters: &rainyunsdk.SslCenterListFilters{ Domain: &certX509.Subject.CommonName, @@ -105,7 +109,7 @@ func (u *UploaderProvider) getCertIfExists(ctx context.Context, certPem string) sslCenterListResp, err := u.sdkClient.SslCenterList(sslCenterListReq) u.logger.Debug("sdk request 'sslcenter.List'", slog.Any("request", sslCenterListReq), slog.Any("response", sslCenterListResp)) if err != nil { - return nil, xerrors.Wrap(err, "failed to execute sdk request 'sslcenter.List'") + return nil, fmt.Errorf("failed to execute sdk request 'sslcenter.List': %w", err) } if sslCenterListResp.Data != nil && sslCenterListResp.Data.Records != nil { @@ -123,12 +127,12 @@ func (u *UploaderProvider) getCertIfExists(ctx context.Context, certPem string) // 最后对比证书内容 sslCenterGetResp, err := u.sdkClient.SslCenterGet(sslItem.ID) if err != nil { - return nil, xerrors.Wrap(err, "failed to execute sdk request 'sslcenter.Get'") + return nil, fmt.Errorf("failed to execute sdk request 'sslcenter.Get': %w", err) } var isSameCert bool if sslCenterGetResp.Data != nil { - if sslCenterGetResp.Data.Cert == certPem { + if sslCenterGetResp.Data.Cert == certPEM { isSameCert = true } else { oldCertX509, err := certutil.ParseCertificateFromPEM(sslCenterGetResp.Data.Cert) diff --git a/internal/pkg/core/uploader/providers/rainyun-sslcenter/rainyun_sslcenter_test.go b/internal/pkg/core/uploader/providers/rainyun-sslcenter/rainyun_sslcenter_test.go index 41619401..e6f801a1 100644 --- a/internal/pkg/core/uploader/providers/rainyun-sslcenter/rainyun_sslcenter_test.go +++ b/internal/pkg/core/uploader/providers/rainyun-sslcenter/rainyun_sslcenter_test.go @@ -1,4 +1,4 @@ -package rainyunsslcenter_test +package rainyunsslcenter_test import ( "context" diff --git a/internal/pkg/core/uploader/providers/tencentcloud-ssl/tencentcloud_ssl.go b/internal/pkg/core/uploader/providers/tencentcloud-ssl/tencentcloud_ssl.go index 45c7ba9e..59067de4 100644 --- a/internal/pkg/core/uploader/providers/tencentcloud-ssl/tencentcloud_ssl.go +++ b/internal/pkg/core/uploader/providers/tencentcloud-ssl/tencentcloud_ssl.go @@ -1,10 +1,10 @@ -package tencentcloudssl +package tencentcloudssl import ( "context" + "fmt" "log/slog" - xerrors "github.com/pkg/errors" "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common" "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common/profile" tcssl "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/ssl/v20191205" @@ -34,7 +34,7 @@ func NewUploader(config *UploaderConfig) (*UploaderProvider, error) { client, err := createSdkClient(config.SecretId, config.SecretKey) if err != nil { - return nil, xerrors.Wrap(err, "failed to create sdk client") + return nil, fmt.Errorf("failed to create sdk client: %w", err) } return &UploaderProvider{ @@ -53,17 +53,17 @@ func (u *UploaderProvider) WithLogger(logger *slog.Logger) uploader.Uploader { return u } -func (u *UploaderProvider) Upload(ctx context.Context, certPem string, privkeyPem string) (res *uploader.UploadResult, err error) { +func (u *UploaderProvider) Upload(ctx context.Context, certPEM string, privkeyPEM string) (res *uploader.UploadResult, err error) { // 上传新证书 // REF: https://cloud.tencent.com/document/product/400/41665 uploadCertificateReq := tcssl.NewUploadCertificateRequest() - uploadCertificateReq.CertificatePublicKey = common.StringPtr(certPem) - uploadCertificateReq.CertificatePrivateKey = common.StringPtr(privkeyPem) + uploadCertificateReq.CertificatePublicKey = common.StringPtr(certPEM) + uploadCertificateReq.CertificatePrivateKey = common.StringPtr(privkeyPEM) uploadCertificateReq.Repeatable = common.BoolPtr(false) uploadCertificateResp, err := u.sdkClient.UploadCertificate(uploadCertificateReq) u.logger.Debug("sdk request 'ssl.UploadCertificate'", slog.Any("request", uploadCertificateReq), slog.Any("response", uploadCertificateResp)) if err != nil { - return nil, xerrors.Wrap(err, "failed to execute sdk request 'ssl.UploadCertificate'") + return nil, fmt.Errorf("failed to execute sdk request 'ssl.UploadCertificate': %w", err) } certId := *uploadCertificateResp.Response.CertificateId diff --git a/internal/pkg/core/uploader/providers/ucloud-ussl/ucloud_ussl.go b/internal/pkg/core/uploader/providers/ucloud-ussl/ucloud_ussl.go index 4649c454..90eb1683 100644 --- a/internal/pkg/core/uploader/providers/ucloud-ussl/ucloud_ussl.go +++ b/internal/pkg/core/uploader/providers/ucloud-ussl/ucloud_ussl.go @@ -12,13 +12,12 @@ import ( "strings" "time" - xerrors "github.com/pkg/errors" "github.com/ucloud/ucloud-sdk-go/ucloud" ucloudauth "github.com/ucloud/ucloud-sdk-go/ucloud/auth" "github.com/usual2970/certimate/internal/pkg/core/uploader" - "github.com/usual2970/certimate/internal/pkg/utils/certutil" - usslsdk "github.com/usual2970/certimate/internal/pkg/vendors/ucloud-sdk/ussl" + usslsdk "github.com/usual2970/certimate/internal/pkg/sdk3rd/ucloud/ussl" + certutil "github.com/usual2970/certimate/internal/pkg/utils/cert" ) type UploaderConfig struct { @@ -45,7 +44,7 @@ func NewUploader(config *UploaderConfig) (*UploaderProvider, error) { client, err := createSdkClient(config.PrivateKey, config.PublicKey) if err != nil { - return nil, xerrors.Wrap(err, "failed to create sdk client") + return nil, fmt.Errorf("failed to create sdk client: %w", err) } return &UploaderProvider{ @@ -64,23 +63,23 @@ func (u *UploaderProvider) WithLogger(logger *slog.Logger) uploader.Uploader { return u } -func (u *UploaderProvider) Upload(ctx context.Context, certPem string, privkeyPem string) (res *uploader.UploadResult, err error) { +func (u *UploaderProvider) Upload(ctx context.Context, certPEM string, privkeyPEM string) (res *uploader.UploadResult, err error) { // 生成新证书名(需符合优刻得命名规则) var certId, certName string certName = fmt.Sprintf("certimate-%d", time.Now().UnixMilli()) // 生成优刻得所需的证书参数 - certPemBase64 := base64.StdEncoding.EncodeToString([]byte(certPem)) - privkeyPemBase64 := base64.StdEncoding.EncodeToString([]byte(privkeyPem)) - certMd5 := md5.Sum([]byte(certPemBase64 + privkeyPemBase64)) + certPEMBase64 := base64.StdEncoding.EncodeToString([]byte(certPEM)) + privkeyPEMBase64 := base64.StdEncoding.EncodeToString([]byte(privkeyPEM)) + certMd5 := md5.Sum([]byte(certPEMBase64 + privkeyPEMBase64)) certMd5Hex := hex.EncodeToString(certMd5[:]) // 上传托管证书 // REF: https://docs.ucloud.cn/api/usslcertificate-api/upload_normal_certificate uploadNormalCertificateReq := u.sdkClient.NewUploadNormalCertificateRequest() uploadNormalCertificateReq.CertificateName = ucloud.String(certName) - uploadNormalCertificateReq.SslPublicKey = ucloud.String(certPemBase64) - uploadNormalCertificateReq.SslPrivateKey = ucloud.String(privkeyPemBase64) + uploadNormalCertificateReq.SslPublicKey = ucloud.String(certPEMBase64) + uploadNormalCertificateReq.SslPrivateKey = ucloud.String(privkeyPEMBase64) uploadNormalCertificateReq.SslMD5 = ucloud.String(certMd5Hex) if u.config.ProjectId != "" { uploadNormalCertificateReq.ProjectId = ucloud.String(u.config.ProjectId) @@ -89,7 +88,7 @@ func (u *UploaderProvider) Upload(ctx context.Context, certPem string, privkeyPe u.logger.Debug("sdk request 'ussl.UploadNormalCertificate'", slog.Any("request", uploadNormalCertificateReq), slog.Any("response", uploadNormalCertificateResp)) if err != nil { if uploadNormalCertificateResp != nil && uploadNormalCertificateResp.GetRetCode() == 80035 { - if res, err := u.getCertIfExists(ctx, certPem); err != nil { + if res, err := u.getCertIfExists(ctx, certPEM); err != nil { return nil, err } else if res == nil { return nil, errors.New("ucloud ssl: no certificate found") @@ -99,7 +98,7 @@ func (u *UploaderProvider) Upload(ctx context.Context, certPem string, privkeyPe } } - return nil, xerrors.Wrap(err, "failed to execute sdk request 'ussl.UploadNormalCertificate'") + return nil, fmt.Errorf("failed to execute sdk request 'ussl.UploadNormalCertificate': %w", err) } certId = fmt.Sprintf("%d", uploadNormalCertificateResp.CertificateID) @@ -112,9 +111,9 @@ func (u *UploaderProvider) Upload(ctx context.Context, certPem string, privkeyPe }, nil } -func (u *UploaderProvider) getCertIfExists(ctx context.Context, certPem string) (res *uploader.UploadResult, err error) { +func (u *UploaderProvider) getCertIfExists(ctx context.Context, certPEM string) (res *uploader.UploadResult, err error) { // 解析证书内容 - certX509, err := certutil.ParseCertificateFromPEM(certPem) + certX509, err := certutil.ParseCertificateFromPEM(certPEM) if err != nil { return nil, err } @@ -125,6 +124,12 @@ func (u *UploaderProvider) getCertIfExists(ctx context.Context, certPem string) getCertificateListPage := int(1) getCertificateListLimit := int(1000) for { + select { + case <-ctx.Done(): + return nil, ctx.Err() + default: + } + getCertificateListReq := u.sdkClient.NewGetCertificateListRequest() getCertificateListReq.Mode = ucloud.String("trust") getCertificateListReq.Domain = ucloud.String(certX509.Subject.CommonName) @@ -137,7 +142,7 @@ func (u *UploaderProvider) getCertIfExists(ctx context.Context, certPem string) getCertificateListResp, err := u.sdkClient.GetCertificateList(getCertificateListReq) u.logger.Debug("sdk request 'ussl.GetCertificateList'", slog.Any("request", getCertificateListReq), slog.Any("response", getCertificateListResp)) if err != nil { - return nil, xerrors.Wrap(err, "failed to execute sdk request 'ussl.GetCertificateList'") + return nil, fmt.Errorf("failed to execute sdk request 'ussl.GetCertificateList': %w", err) } if getCertificateListResp.CertificateList != nil { @@ -164,7 +169,7 @@ func (u *UploaderProvider) getCertIfExists(ctx context.Context, certPem string) } getCertificateDetailInfoResp, err := u.sdkClient.GetCertificateDetailInfo(getCertificateDetailInfoReq) if err != nil { - return nil, xerrors.Wrap(err, "failed to execute sdk request 'ussl.GetCertificateDetailInfo'") + return nil, fmt.Errorf("failed to execute sdk request 'ussl.GetCertificateDetailInfo': %w", err) } switch certX509.SignatureAlgorithm { diff --git a/internal/pkg/core/uploader/providers/ucloud-ussl/ucloud_ussl_test.go b/internal/pkg/core/uploader/providers/ucloud-ussl/ucloud_ussl_test.go index b6324fd5..b459e005 100644 --- a/internal/pkg/core/uploader/providers/ucloud-ussl/ucloud_ussl_test.go +++ b/internal/pkg/core/uploader/providers/ucloud-ussl/ucloud_ussl_test.go @@ -1,4 +1,4 @@ -package ucloudussl_test +package ucloudussl_test import ( "context" diff --git a/internal/pkg/core/uploader/providers/upyun-ssl/upyun_ssl.go b/internal/pkg/core/uploader/providers/upyun-ssl/upyun_ssl.go index dbbe41fa..7a8bd3a0 100644 --- a/internal/pkg/core/uploader/providers/upyun-ssl/upyun_ssl.go +++ b/internal/pkg/core/uploader/providers/upyun-ssl/upyun_ssl.go @@ -1,14 +1,13 @@ -package upyunssl +package upyunssl import ( "context" "errors" + "fmt" "log/slog" - xerrors "github.com/pkg/errors" - "github.com/usual2970/certimate/internal/pkg/core/uploader" - upyunsdk "github.com/usual2970/certimate/internal/pkg/vendors/upyun-sdk/console" + upyunsdk "github.com/usual2970/certimate/internal/pkg/sdk3rd/upyun/console" ) type UploaderConfig struct { @@ -33,7 +32,7 @@ func NewUploader(config *UploaderConfig) (*UploaderProvider, error) { client, err := createSdkClient(config.Username, config.Password) if err != nil { - return nil, xerrors.Wrap(err, "failed to create sdk client") + return nil, fmt.Errorf("failed to create sdk client: %w", err) } return &UploaderProvider{ @@ -52,16 +51,16 @@ func (u *UploaderProvider) WithLogger(logger *slog.Logger) uploader.Uploader { return u } -func (u *UploaderProvider) Upload(ctx context.Context, certPem string, privkeyPem string) (res *uploader.UploadResult, err error) { +func (u *UploaderProvider) Upload(ctx context.Context, certPEM string, privkeyPEM string) (res *uploader.UploadResult, err error) { // 上传证书 uploadHttpsCertificateReq := &upyunsdk.UploadHttpsCertificateRequest{ - Certificate: certPem, - PrivateKey: privkeyPem, + Certificate: certPEM, + PrivateKey: privkeyPEM, } uploadHttpsCertificateResp, err := u.sdkClient.UploadHttpsCertificate(uploadHttpsCertificateReq) u.logger.Debug("sdk request 'console.UploadHttpsCertificate'", slog.Any("response", uploadHttpsCertificateResp)) if err != nil { - return nil, xerrors.Wrap(err, "failed to execute sdk request 'console.UploadHttpsCertificate'") + return nil, fmt.Errorf("failed to execute sdk request 'console.UploadHttpsCertificate': %w", err) } return &uploader.UploadResult{ diff --git a/internal/pkg/core/uploader/providers/upyun-ssl/upyun_ssl_test.go b/internal/pkg/core/uploader/providers/upyun-ssl/upyun_ssl_test.go index 1e6d81ec..baf53d74 100644 --- a/internal/pkg/core/uploader/providers/upyun-ssl/upyun_ssl_test.go +++ b/internal/pkg/core/uploader/providers/upyun-ssl/upyun_ssl_test.go @@ -1,4 +1,4 @@ -package upyunssl_test +package upyunssl_test import ( "context" diff --git a/internal/pkg/core/uploader/providers/volcengine-cdn/volcengine_cdn.go b/internal/pkg/core/uploader/providers/volcengine-cdn/volcengine_cdn.go index 2fe52472..b529e84a 100644 --- a/internal/pkg/core/uploader/providers/volcengine-cdn/volcengine_cdn.go +++ b/internal/pkg/core/uploader/providers/volcengine-cdn/volcengine_cdn.go @@ -10,12 +10,11 @@ import ( "strings" "time" - xerrors "github.com/pkg/errors" vecdn "github.com/volcengine/volc-sdk-golang/service/cdn" ve "github.com/volcengine/volcengine-go-sdk/volcengine" "github.com/usual2970/certimate/internal/pkg/core/uploader" - "github.com/usual2970/certimate/internal/pkg/utils/certutil" + certutil "github.com/usual2970/certimate/internal/pkg/utils/cert" ) type UploaderConfig struct { @@ -58,9 +57,9 @@ func (u *UploaderProvider) WithLogger(logger *slog.Logger) uploader.Uploader { return u } -func (u *UploaderProvider) Upload(ctx context.Context, certPem string, privkeyPem string) (res *uploader.UploadResult, err error) { +func (u *UploaderProvider) Upload(ctx context.Context, certPEM string, privkeyPEM string) (res *uploader.UploadResult, err error) { // 解析证书内容 - certX509, err := certutil.ParseCertificateFromPEM(certPem) + certX509, err := certutil.ParseCertificateFromPEM(certPEM) if err != nil { return nil, err } @@ -76,10 +75,16 @@ func (u *UploaderProvider) Upload(ctx context.Context, certPem string, privkeyPe Source: "volc_cert_center", } for { + select { + case <-ctx.Done(): + return nil, ctx.Err() + default: + } + listCertInfoResp, err := u.sdkClient.ListCertInfo(listCertInfoReq) u.logger.Debug("sdk request 'cdn.ListCertInfo'", slog.Any("request", listCertInfoReq), slog.Any("response", listCertInfoResp)) if err != nil { - return nil, xerrors.Wrap(err, "failed to execute sdk request 'cdn.ListCertInfo'") + return nil, fmt.Errorf("failed to execute sdk request 'cdn.ListCertInfo': %w", err) } if listCertInfoResp.Result.CertInfo != nil { @@ -115,15 +120,15 @@ func (u *UploaderProvider) Upload(ctx context.Context, certPem string, privkeyPe // 上传新证书 // REF: https://www.volcengine.com/docs/6454/1245763 addCertificateReq := &vecdn.AddCertificateRequest{ - Certificate: certPem, - PrivateKey: privkeyPem, + Certificate: certPEM, + PrivateKey: privkeyPEM, Source: ve.String("volc_cert_center"), Desc: ve.String(certName), } addCertificateResp, err := u.sdkClient.AddCertificate(addCertificateReq) u.logger.Debug("sdk request 'cdn.AddCertificate'", slog.Any("request", addCertificateResp), slog.Any("response", addCertificateResp)) if err != nil { - return nil, xerrors.Wrap(err, "failed to execute sdk request 'cdn.AddCertificate'") + return nil, fmt.Errorf("failed to execute sdk request 'cdn.AddCertificate': %w", err) } certId = addCertificateResp.Result.CertId diff --git a/internal/pkg/core/uploader/providers/volcengine-certcenter/volcengine_certcenter.go b/internal/pkg/core/uploader/providers/volcengine-certcenter/volcengine_certcenter.go index 66540699..99511ebf 100644 --- a/internal/pkg/core/uploader/providers/volcengine-certcenter/volcengine_certcenter.go +++ b/internal/pkg/core/uploader/providers/volcengine-certcenter/volcengine_certcenter.go @@ -2,14 +2,15 @@ package volcenginecertcenter import ( "context" + "errors" + "fmt" "log/slog" - xerrors "github.com/pkg/errors" ve "github.com/volcengine/volcengine-go-sdk/volcengine" vesession "github.com/volcengine/volcengine-go-sdk/volcengine/session" "github.com/usual2970/certimate/internal/pkg/core/uploader" - veccsdk "github.com/usual2970/certimate/internal/pkg/vendors/volcengine-sdk/certcenter" + veccsdk "github.com/usual2970/certimate/internal/pkg/sdk3rd/volcengine/certcenter" ) type UploaderConfig struct { @@ -36,7 +37,7 @@ func NewUploader(config *UploaderConfig) (*UploaderProvider, error) { client, err := createSdkClient(config.AccessKeyId, config.AccessKeySecret, config.Region) if err != nil { - return nil, xerrors.Wrap(err, "failed to create sdk client") + return nil, fmt.Errorf("failed to create sdk client: %w", err) } return &UploaderProvider{ @@ -55,20 +56,20 @@ func (u *UploaderProvider) WithLogger(logger *slog.Logger) uploader.Uploader { return u } -func (u *UploaderProvider) Upload(ctx context.Context, certPem string, privkeyPem string) (res *uploader.UploadResult, err error) { +func (u *UploaderProvider) Upload(ctx context.Context, certPEM string, privkeyPEM string) (res *uploader.UploadResult, err error) { // 上传证书 // REF: https://www.volcengine.com/docs/6638/1365580 importCertificateReq := &veccsdk.ImportCertificateInput{ CertificateInfo: &veccsdk.ImportCertificateInputCertificateInfo{ - CertificateChain: ve.String(certPem), - PrivateKey: ve.String(privkeyPem), + CertificateChain: ve.String(certPEM), + PrivateKey: ve.String(privkeyPEM), }, Repeatable: ve.Bool(false), } importCertificateResp, err := u.sdkClient.ImportCertificate(importCertificateReq) u.logger.Debug("sdk request 'certcenter.ImportCertificate'", slog.Any("request", importCertificateReq), slog.Any("response", importCertificateResp)) if err != nil { - return nil, xerrors.Wrap(err, "failed to execute sdk request 'certcenter.ImportCertificate'") + return nil, fmt.Errorf("failed to execute sdk request 'certcenter.ImportCertificate': %w", err) } var certId string @@ -80,7 +81,7 @@ func (u *UploaderProvider) Upload(ctx context.Context, certPem string, privkeyPe } if certId == "" { - return nil, xerrors.New("failed to get certificate id, both `InstanceId` and `RepeatId` are empty") + return nil, errors.New("failed to get certificate id from response, both `InstanceId` and `RepeatId` are empty") } return &uploader.UploadResult{ diff --git a/internal/pkg/core/uploader/providers/volcengine-certcenter/volcengine_certcenter_test.go b/internal/pkg/core/uploader/providers/volcengine-certcenter/volcengine_certcenter_test.go index 5c312707..1cfa15fe 100644 --- a/internal/pkg/core/uploader/providers/volcengine-certcenter/volcengine_certcenter_test.go +++ b/internal/pkg/core/uploader/providers/volcengine-certcenter/volcengine_certcenter_test.go @@ -1,4 +1,4 @@ -package volcenginecertcenter_test +package volcenginecertcenter_test import ( "context" diff --git a/internal/pkg/core/uploader/providers/volcengine-live/volcengine_live.go b/internal/pkg/core/uploader/providers/volcengine-live/volcengine_live.go index 46031c61..de5ec27d 100644 --- a/internal/pkg/core/uploader/providers/volcengine-live/volcengine_live.go +++ b/internal/pkg/core/uploader/providers/volcengine-live/volcengine_live.go @@ -7,12 +7,11 @@ import ( "strings" "time" - xerrors "github.com/pkg/errors" velive "github.com/volcengine/volc-sdk-golang/service/live/v20230101" ve "github.com/volcengine/volcengine-go-sdk/volcengine" "github.com/usual2970/certimate/internal/pkg/core/uploader" - "github.com/usual2970/certimate/internal/pkg/utils/certutil" + certutil "github.com/usual2970/certimate/internal/pkg/utils/cert" ) type UploaderConfig struct { @@ -55,9 +54,9 @@ func (u *UploaderProvider) WithLogger(logger *slog.Logger) uploader.Uploader { return u } -func (u *UploaderProvider) Upload(ctx context.Context, certPem string, privkeyPem string) (res *uploader.UploadResult, err error) { +func (u *UploaderProvider) Upload(ctx context.Context, certPEM string, privkeyPEM string) (res *uploader.UploadResult, err error) { // 解析证书内容 - certX509, err := certutil.ParseCertificateFromPEM(certPem) + certX509, err := certutil.ParseCertificateFromPEM(certPEM) if err != nil { return nil, err } @@ -68,7 +67,7 @@ func (u *UploaderProvider) Upload(ctx context.Context, certPem string, privkeyPe listCertResp, err := u.sdkClient.ListCertV2(ctx, listCertReq) u.logger.Debug("sdk request 'live.ListCertV2'", slog.Any("request", listCertReq), slog.Any("response", listCertResp)) if err != nil { - return nil, xerrors.Wrap(err, "failed to execute sdk request 'live.ListCertV2'") + return nil, fmt.Errorf("failed to execute sdk request 'live.ListCertV2': %w", err) } if listCertResp.Result.CertList != nil { for _, certDetail := range listCertResp.Result.CertList { @@ -85,7 +84,7 @@ func (u *UploaderProvider) Upload(ctx context.Context, certPem string, privkeyPe var isSameCert bool certificate := strings.Join(describeCertDetailSecretResp.Result.SSL.Chain, "\n\n") - if certificate == certPem { + if certificate == certPEM { isSameCert = true } else { oldCertX509, err := certutil.ParseCertificateFromPEM(certificate) @@ -118,14 +117,14 @@ func (u *UploaderProvider) Upload(ctx context.Context, certPem string, privkeyPe UseWay: "https", ProjectName: ve.String("default"), Rsa: velive.CreateCertBodyRsa{ - Prikey: privkeyPem, - Pubkey: certPem, + Prikey: privkeyPEM, + Pubkey: certPEM, }, } createCertResp, err := u.sdkClient.CreateCert(ctx, createCertReq) u.logger.Debug("sdk request 'live.CreateCert'", slog.Any("request", createCertReq), slog.Any("response", createCertResp)) if err != nil { - return nil, xerrors.Wrap(err, "failed to execute sdk request 'live.CreateCert'") + return nil, fmt.Errorf("failed to execute sdk request 'live.CreateCert': %w", err) } certId = *createCertResp.Result.ChainID diff --git a/internal/pkg/core/uploader/uploader.go b/internal/pkg/core/uploader/uploader.go index 5edcdce4..34d2813a 100644 --- a/internal/pkg/core/uploader/uploader.go +++ b/internal/pkg/core/uploader/uploader.go @@ -1,4 +1,4 @@ -package uploader +package uploader import ( "context" @@ -15,13 +15,13 @@ type Uploader interface { // // 入参: // - ctx:上下文。 - // - certPem:证书 PEM 内容。 - // - privkeyPem:私钥 PEM 内容。 + // - certPEM:证书 PEM 内容。 + // - privkeyPEM:私钥 PEM 内容。 // // 出参: // - res:上传结果。 // - err: 错误。 - Upload(ctx context.Context, certPem string, privkeyPem string) (res *UploadResult, err error) + Upload(ctx context.Context, certPEM string, privkeyPEM string) (res *UploadResult, err error) } // 表示证书上传结果的数据结构,包含上传后的证书 ID、名称和其他数据。 diff --git a/internal/pkg/logging/handler.go b/internal/pkg/logging/handler.go index 36174b45..7cdacdd7 100644 --- a/internal/pkg/logging/handler.go +++ b/internal/pkg/logging/handler.go @@ -1,4 +1,4 @@ -package logging +package logging import ( "context" diff --git a/internal/pkg/logging/level.go b/internal/pkg/logging/level.go index 2af1c2f4..1aefe84d 100644 --- a/internal/pkg/logging/level.go +++ b/internal/pkg/logging/level.go @@ -1,4 +1,4 @@ -package logging +package logging import "log/slog" diff --git a/internal/pkg/logging/record.go b/internal/pkg/logging/record.go index 9980489b..38208535 100644 --- a/internal/pkg/logging/record.go +++ b/internal/pkg/logging/record.go @@ -1,4 +1,4 @@ -package logging +package logging import ( "time" diff --git a/internal/pkg/vendors/1panel-sdk/api.go b/internal/pkg/sdk3rd/1panel/api.go similarity index 83% rename from internal/pkg/vendors/1panel-sdk/api.go rename to internal/pkg/sdk3rd/1panel/api.go index 8fa15393..baab2313 100644 --- a/internal/pkg/vendors/1panel-sdk/api.go +++ b/internal/pkg/sdk3rd/1panel/api.go @@ -18,6 +18,10 @@ func (c *Client) SearchWebsiteSSL(req *SearchWebsiteSSLRequest) (*SearchWebsiteS } func (c *Client) GetWebsiteSSL(req *GetWebsiteSSLRequest) (*GetWebsiteSSLResponse, error) { + if req.SSLID == 0 { + return nil, fmt.Errorf("1panel api error: invalid parameter: SSLID") + } + resp := &GetWebsiteSSLResponse{} err := c.sendRequestWithResult(http.MethodGet, fmt.Sprintf("/websites/ssl/%d", req.SSLID), req, resp) return resp, err @@ -30,12 +34,20 @@ func (c *Client) UploadWebsiteSSL(req *UploadWebsiteSSLRequest) (*UploadWebsiteS } func (c *Client) GetHttpsConf(req *GetHttpsConfRequest) (*GetHttpsConfResponse, error) { + if req.WebsiteID == 0 { + return nil, fmt.Errorf("1panel api error: invalid parameter: WebsiteID") + } + resp := &GetHttpsConfResponse{} err := c.sendRequestWithResult(http.MethodGet, fmt.Sprintf("/websites/%d/https", req.WebsiteID), req, resp) return resp, err } func (c *Client) UpdateHttpsConf(req *UpdateHttpsConfRequest) (*UpdateHttpsConfResponse, error) { + if req.WebsiteID == 0 { + return nil, fmt.Errorf("1panel api error: invalid parameter: WebsiteID") + } + resp := &UpdateHttpsConfResponse{} err := c.sendRequestWithResult(http.MethodPost, fmt.Sprintf("/websites/%d/https", req.WebsiteID), req, resp) return resp, err diff --git a/internal/pkg/vendors/1panel-sdk/client.go b/internal/pkg/sdk3rd/1panel/client.go similarity index 100% rename from internal/pkg/vendors/1panel-sdk/client.go rename to internal/pkg/sdk3rd/1panel/client.go diff --git a/internal/pkg/vendors/1panel-sdk/models.go b/internal/pkg/sdk3rd/1panel/models.go similarity index 100% rename from internal/pkg/vendors/1panel-sdk/models.go rename to internal/pkg/sdk3rd/1panel/models.go diff --git a/internal/pkg/vendors/azure-sdk/common/config.go b/internal/pkg/sdk3rd/azure/common/config.go similarity index 98% rename from internal/pkg/vendors/azure-sdk/common/config.go rename to internal/pkg/sdk3rd/azure/common/config.go index eca082f9..45a1e490 100644 --- a/internal/pkg/vendors/azure-sdk/common/config.go +++ b/internal/pkg/sdk3rd/azure/common/config.go @@ -1,4 +1,4 @@ -package common +package common import ( "fmt" diff --git a/internal/pkg/vendors/baiducloud-sdk/cert/api.go b/internal/pkg/sdk3rd/baiducloud/cert/api.go similarity index 100% rename from internal/pkg/vendors/baiducloud-sdk/cert/api.go rename to internal/pkg/sdk3rd/baiducloud/cert/api.go diff --git a/internal/pkg/vendors/baiducloud-sdk/cert/client.go b/internal/pkg/sdk3rd/baiducloud/cert/client.go similarity index 100% rename from internal/pkg/vendors/baiducloud-sdk/cert/client.go rename to internal/pkg/sdk3rd/baiducloud/cert/client.go diff --git a/internal/pkg/vendors/baiducloud-sdk/cert/models.go b/internal/pkg/sdk3rd/baiducloud/cert/models.go similarity index 100% rename from internal/pkg/vendors/baiducloud-sdk/cert/models.go rename to internal/pkg/sdk3rd/baiducloud/cert/models.go diff --git a/internal/pkg/vendors/baishan-sdk/api.go b/internal/pkg/sdk3rd/baishan/api.go similarity index 100% rename from internal/pkg/vendors/baishan-sdk/api.go rename to internal/pkg/sdk3rd/baishan/api.go diff --git a/internal/pkg/vendors/baishan-sdk/client.go b/internal/pkg/sdk3rd/baishan/client.go similarity index 100% rename from internal/pkg/vendors/baishan-sdk/client.go rename to internal/pkg/sdk3rd/baishan/client.go diff --git a/internal/pkg/vendors/baishan-sdk/models.go b/internal/pkg/sdk3rd/baishan/models.go similarity index 100% rename from internal/pkg/vendors/baishan-sdk/models.go rename to internal/pkg/sdk3rd/baishan/models.go diff --git a/internal/pkg/vendors/btpanel-sdk/api.go b/internal/pkg/sdk3rd/btpanel/api.go similarity index 100% rename from internal/pkg/vendors/btpanel-sdk/api.go rename to internal/pkg/sdk3rd/btpanel/api.go diff --git a/internal/pkg/vendors/btpanel-sdk/client.go b/internal/pkg/sdk3rd/btpanel/client.go similarity index 100% rename from internal/pkg/vendors/btpanel-sdk/client.go rename to internal/pkg/sdk3rd/btpanel/client.go diff --git a/internal/pkg/vendors/btpanel-sdk/models.go b/internal/pkg/sdk3rd/btpanel/models.go similarity index 100% rename from internal/pkg/vendors/btpanel-sdk/models.go rename to internal/pkg/sdk3rd/btpanel/models.go diff --git a/internal/pkg/vendors/bunny-sdk/api.go b/internal/pkg/sdk3rd/bunny/api.go similarity index 56% rename from internal/pkg/vendors/bunny-sdk/api.go rename to internal/pkg/sdk3rd/bunny/api.go index 8cff90b4..9c6aa285 100644 --- a/internal/pkg/vendors/bunny-sdk/api.go +++ b/internal/pkg/sdk3rd/bunny/api.go @@ -3,9 +3,14 @@ package bunnysdk import ( "fmt" "net/http" + "net/url" ) func (c *Client) AddCustomCertificate(req *AddCustomCertificateRequest) ([]byte, error) { - resp, err := c.sendRequest(http.MethodPost, fmt.Sprintf("/pullzone/%s/addCertificate", req.PullZoneId), req) + if req.PullZoneId == "" { + return nil, fmt.Errorf("bunny api error: invalid parameter: PullZoneId") + } + + resp, err := c.sendRequest(http.MethodPost, fmt.Sprintf("/pullzone/%s/addCertificate", url.PathEscape(req.PullZoneId)), req) return resp.Body(), err } diff --git a/internal/pkg/vendors/bunny-sdk/client.go b/internal/pkg/sdk3rd/bunny/client.go similarity index 96% rename from internal/pkg/vendors/bunny-sdk/client.go rename to internal/pkg/sdk3rd/bunny/client.go index 398d5cb2..90b43f39 100644 --- a/internal/pkg/vendors/bunny-sdk/client.go +++ b/internal/pkg/sdk3rd/bunny/client.go @@ -59,7 +59,7 @@ func (c *Client) sendRequest(method string, path string, params interface{}) (*r if err != nil { return resp, fmt.Errorf("bunny api error: failed to send request: %w", err) } else if resp.IsError() { - return resp, fmt.Errorf("bunny api error: unexpected status code: %d, %s", resp.StatusCode(), resp.Body()) + return resp, fmt.Errorf("bunny api error: unexpected status code: %d, resp: %s", resp.StatusCode(), resp.Body()) } return resp, nil diff --git a/internal/pkg/vendors/bunny-sdk/models.go b/internal/pkg/sdk3rd/bunny/models.go similarity index 100% rename from internal/pkg/vendors/bunny-sdk/models.go rename to internal/pkg/sdk3rd/bunny/models.go diff --git a/internal/pkg/vendors/cachefly-sdk/api.go b/internal/pkg/sdk3rd/cachefly/api.go similarity index 100% rename from internal/pkg/vendors/cachefly-sdk/api.go rename to internal/pkg/sdk3rd/cachefly/api.go diff --git a/internal/pkg/vendors/cachefly-sdk/client.go b/internal/pkg/sdk3rd/cachefly/client.go similarity index 100% rename from internal/pkg/vendors/cachefly-sdk/client.go rename to internal/pkg/sdk3rd/cachefly/client.go diff --git a/internal/pkg/vendors/cachefly-sdk/models.go b/internal/pkg/sdk3rd/cachefly/models.go similarity index 100% rename from internal/pkg/vendors/cachefly-sdk/models.go rename to internal/pkg/sdk3rd/cachefly/models.go diff --git a/internal/pkg/vendors/cdnfly-sdk/api.go b/internal/pkg/sdk3rd/cdnfly/api.go similarity index 79% rename from internal/pkg/vendors/cdnfly-sdk/api.go rename to internal/pkg/sdk3rd/cdnfly/api.go index 263bf2cd..4091a84d 100644 --- a/internal/pkg/vendors/cdnfly-sdk/api.go +++ b/internal/pkg/sdk3rd/cdnfly/api.go @@ -7,12 +7,20 @@ import ( ) func (c *Client) GetSite(req *GetSiteRequest) (*GetSiteResponse, error) { + if req.Id == "" { + return nil, fmt.Errorf("cdnfly api error: invalid parameter: Id") + } + resp := &GetSiteResponse{} err := c.sendRequestWithResult(http.MethodGet, fmt.Sprintf("/v1/sites/%s", url.PathEscape(req.Id)), req, resp) return resp, err } func (c *Client) UpdateSite(req *UpdateSiteRequest) (*UpdateSiteResponse, error) { + if req.Id == "" { + return nil, fmt.Errorf("cdnfly api error: invalid parameter: Id") + } + resp := &UpdateSiteResponse{} err := c.sendRequestWithResult(http.MethodPut, fmt.Sprintf("/v1/sites/%s", url.PathEscape(req.Id)), req, resp) return resp, err @@ -25,6 +33,10 @@ func (c *Client) CreateCertificate(req *CreateCertificateRequest) (*CreateCertif } func (c *Client) UpdateCertificate(req *UpdateCertificateRequest) (*UpdateCertificateResponse, error) { + if req.Id == "" { + return nil, fmt.Errorf("cdnfly api error: invalid parameter: Id") + } + resp := &UpdateCertificateResponse{} err := c.sendRequestWithResult(http.MethodPut, fmt.Sprintf("/v1/certs/%s", url.PathEscape(req.Id)), req, resp) return resp, err diff --git a/internal/pkg/vendors/cdnfly-sdk/client.go b/internal/pkg/sdk3rd/cdnfly/client.go similarity index 94% rename from internal/pkg/vendors/cdnfly-sdk/client.go rename to internal/pkg/sdk3rd/cdnfly/client.go index 47738f29..c1a810d9 100644 --- a/internal/pkg/vendors/cdnfly-sdk/client.go +++ b/internal/pkg/sdk3rd/cdnfly/client.go @@ -1,6 +1,7 @@ package cdnflysdk import ( + "crypto/tls" "encoding/json" "fmt" "net/http" @@ -34,6 +35,11 @@ func (c *Client) WithTimeout(timeout time.Duration) *Client { return c } +func (c *Client) WithTLSConfig(config *tls.Config) *Client { + c.client.SetTLSClientConfig(config) + return c +} + func (c *Client) sendRequest(method string, path string, params interface{}) (*resty.Response, error) { req := c.client.R() req.Method = method diff --git a/internal/pkg/vendors/cdnfly-sdk/models.go b/internal/pkg/sdk3rd/cdnfly/models.go similarity index 100% rename from internal/pkg/vendors/cdnfly-sdk/models.go rename to internal/pkg/sdk3rd/cdnfly/models.go diff --git a/internal/pkg/vendors/cmcc-sdk/README.md b/internal/pkg/sdk3rd/cmcc/README.md similarity index 100% rename from internal/pkg/vendors/cmcc-sdk/README.md rename to internal/pkg/sdk3rd/cmcc/README.md diff --git a/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/client.go b/internal/pkg/sdk3rd/cmcc/ecloudsdkclouddns@v1.0.1/client.go similarity index 100% rename from internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/client.go rename to internal/pkg/sdk3rd/cmcc/ecloudsdkclouddns@v1.0.1/client.go diff --git a/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/go.mod b/internal/pkg/sdk3rd/cmcc/ecloudsdkclouddns@v1.0.1/go.mod similarity index 100% rename from internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/go.mod rename to internal/pkg/sdk3rd/cmcc/ecloudsdkclouddns@v1.0.1/go.mod diff --git a/internal/pkg/sdk3rd/cmcc/ecloudsdkclouddns@v1.0.1/model/create_record_body.go b/internal/pkg/sdk3rd/cmcc/ecloudsdkclouddns@v1.0.1/model/create_record_body.go new file mode 100644 index 00000000..37d0457d --- /dev/null +++ b/internal/pkg/sdk3rd/cmcc/ecloudsdkclouddns@v1.0.1/model/create_record_body.go @@ -0,0 +1,55 @@ +// @Title Golang SDK Client +// @Description This code is auto generated +// @Author Ecloud SDK + +package model + +import ( + "gitlab.ecloud.com/ecloud/ecloudsdkcore/position" +) + +type CreateRecordBodyTypeEnum string + +// List of Type +const ( + CreateRecordBodyTypeEnumA CreateRecordBodyTypeEnum = "A" + CreateRecordBodyTypeEnumAaaa CreateRecordBodyTypeEnum = "AAAA" + CreateRecordBodyTypeEnumCaa CreateRecordBodyTypeEnum = "CAA" + CreateRecordBodyTypeEnumCmauth CreateRecordBodyTypeEnum = "CMAUTH" + CreateRecordBodyTypeEnumCname CreateRecordBodyTypeEnum = "CNAME" + CreateRecordBodyTypeEnumMx CreateRecordBodyTypeEnum = "MX" + CreateRecordBodyTypeEnumNs CreateRecordBodyTypeEnum = "NS" + CreateRecordBodyTypeEnumPtr CreateRecordBodyTypeEnum = "PTR" + CreateRecordBodyTypeEnumRp CreateRecordBodyTypeEnum = "RP" + CreateRecordBodyTypeEnumSpf CreateRecordBodyTypeEnum = "SPF" + CreateRecordBodyTypeEnumSrv CreateRecordBodyTypeEnum = "SRV" + CreateRecordBodyTypeEnumTxt CreateRecordBodyTypeEnum = "TXT" + CreateRecordBodyTypeEnumUrl CreateRecordBodyTypeEnum = "URL" +) + +type CreateRecordBody struct { + position.Body + // 主机头 + Rr string `json:"rr"` + + // 域名名称 + DomainName string `json:"domainName"` + + // 备注 + Description string `json:"description,omitempty"` + + // 线路ID + LineId string `json:"lineId"` + + // MX优先级,若“记录类型”选择”MX”,则需要配置该参数,默认是5 + MxPri *int32 `json:"mxPri,omitempty"` + + // 记录类型 + Type CreateRecordBodyTypeEnum `json:"type"` + + // 缓存的生命周期,默认可配置600s + Ttl *int32 `json:"ttl,omitempty"` + + // 记录值 + Value string `json:"value"` +} diff --git a/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/create_record_openapi_body.go b/internal/pkg/sdk3rd/cmcc/ecloudsdkclouddns@v1.0.1/model/create_record_openapi_body.go similarity index 50% rename from internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/create_record_openapi_body.go rename to internal/pkg/sdk3rd/cmcc/ecloudsdkclouddns@v1.0.1/model/create_record_openapi_body.go index 3db9f0f7..896d7dc3 100644 --- a/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/create_record_openapi_body.go +++ b/internal/pkg/sdk3rd/cmcc/ecloudsdkclouddns@v1.0.1/model/create_record_openapi_body.go @@ -5,26 +5,27 @@ package model import ( - "gitlab.ecloud.com/ecloud/ecloudsdkcore/position" + "gitlab.ecloud.com/ecloud/ecloudsdkcore/position" ) + type CreateRecordOpenapiBodyTypeEnum string // List of Type const ( - CreateRecordOpenapiBodyTypeEnumA CreateRecordOpenapiBodyTypeEnum = "A" - CreateRecordOpenapiBodyTypeEnumAaaa CreateRecordOpenapiBodyTypeEnum = "AAAA" - CreateRecordOpenapiBodyTypeEnumCname CreateRecordOpenapiBodyTypeEnum = "CNAME" - CreateRecordOpenapiBodyTypeEnumMx CreateRecordOpenapiBodyTypeEnum = "MX" - CreateRecordOpenapiBodyTypeEnumTxt CreateRecordOpenapiBodyTypeEnum = "TXT" - CreateRecordOpenapiBodyTypeEnumNs CreateRecordOpenapiBodyTypeEnum = "NS" - CreateRecordOpenapiBodyTypeEnumSpf CreateRecordOpenapiBodyTypeEnum = "SPF" - CreateRecordOpenapiBodyTypeEnumSrv CreateRecordOpenapiBodyTypeEnum = "SRV" - CreateRecordOpenapiBodyTypeEnumCaa CreateRecordOpenapiBodyTypeEnum = "CAA" - CreateRecordOpenapiBodyTypeEnumCmauth CreateRecordOpenapiBodyTypeEnum = "CMAUTH" + CreateRecordOpenapiBodyTypeEnumA CreateRecordOpenapiBodyTypeEnum = "A" + CreateRecordOpenapiBodyTypeEnumAaaa CreateRecordOpenapiBodyTypeEnum = "AAAA" + CreateRecordOpenapiBodyTypeEnumCname CreateRecordOpenapiBodyTypeEnum = "CNAME" + CreateRecordOpenapiBodyTypeEnumMx CreateRecordOpenapiBodyTypeEnum = "MX" + CreateRecordOpenapiBodyTypeEnumTxt CreateRecordOpenapiBodyTypeEnum = "TXT" + CreateRecordOpenapiBodyTypeEnumNs CreateRecordOpenapiBodyTypeEnum = "NS" + CreateRecordOpenapiBodyTypeEnumSpf CreateRecordOpenapiBodyTypeEnum = "SPF" + CreateRecordOpenapiBodyTypeEnumSrv CreateRecordOpenapiBodyTypeEnum = "SRV" + CreateRecordOpenapiBodyTypeEnumCaa CreateRecordOpenapiBodyTypeEnum = "CAA" + CreateRecordOpenapiBodyTypeEnumCmauth CreateRecordOpenapiBodyTypeEnum = "CMAUTH" ) type CreateRecordOpenapiBody struct { - position.Body + position.Body // 主机头 Rr string `json:"rr"` diff --git a/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/create_record_openapi_request.go b/internal/pkg/sdk3rd/cmcc/ecloudsdkclouddns@v1.0.1/model/create_record_openapi_request.go similarity index 98% rename from internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/create_record_openapi_request.go rename to internal/pkg/sdk3rd/cmcc/ecloudsdkclouddns@v1.0.1/model/create_record_openapi_request.go index d43fded1..888a66aa 100644 --- a/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/create_record_openapi_request.go +++ b/internal/pkg/sdk3rd/cmcc/ecloudsdkclouddns@v1.0.1/model/create_record_openapi_request.go @@ -4,9 +4,6 @@ package model - - type CreateRecordOpenapiRequest struct { - CreateRecordOpenapiBody *CreateRecordOpenapiBody `json:"createRecordOpenapiBody,omitempty"` } diff --git a/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/create_record_openapi_response.go b/internal/pkg/sdk3rd/cmcc/ecloudsdkclouddns@v1.0.1/model/create_record_openapi_response.go similarity index 57% rename from internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/create_record_openapi_response.go rename to internal/pkg/sdk3rd/cmcc/ecloudsdkclouddns@v1.0.1/model/create_record_openapi_response.go index a33b47c7..01c3294f 100644 --- a/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/create_record_openapi_response.go +++ b/internal/pkg/sdk3rd/cmcc/ecloudsdkclouddns@v1.0.1/model/create_record_openapi_response.go @@ -4,19 +4,17 @@ package model - type CreateRecordOpenapiResponseStateEnum string // List of State const ( - CreateRecordOpenapiResponseStateEnumError CreateRecordOpenapiResponseStateEnum = "ERROR" - CreateRecordOpenapiResponseStateEnumException CreateRecordOpenapiResponseStateEnum = "EXCEPTION" - CreateRecordOpenapiResponseStateEnumForbidden CreateRecordOpenapiResponseStateEnum = "FORBIDDEN" - CreateRecordOpenapiResponseStateEnumOk CreateRecordOpenapiResponseStateEnum = "OK" + CreateRecordOpenapiResponseStateEnumError CreateRecordOpenapiResponseStateEnum = "ERROR" + CreateRecordOpenapiResponseStateEnumException CreateRecordOpenapiResponseStateEnum = "EXCEPTION" + CreateRecordOpenapiResponseStateEnumForbidden CreateRecordOpenapiResponseStateEnum = "FORBIDDEN" + CreateRecordOpenapiResponseStateEnumOk CreateRecordOpenapiResponseStateEnum = "OK" ) type CreateRecordOpenapiResponse struct { - RequestId string `json:"requestId,omitempty"` ErrorMessage string `json:"errorMessage,omitempty"` diff --git a/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/create_record_openapi_response_body.go b/internal/pkg/sdk3rd/cmcc/ecloudsdkclouddns@v1.0.1/model/create_record_openapi_response_body.go similarity index 58% rename from internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/create_record_openapi_response_body.go rename to internal/pkg/sdk3rd/cmcc/ecloudsdkclouddns@v1.0.1/model/create_record_openapi_response_body.go index e7c62769..5bbdb75e 100644 --- a/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/create_record_openapi_response_body.go +++ b/internal/pkg/sdk3rd/cmcc/ecloudsdkclouddns@v1.0.1/model/create_record_openapi_response_body.go @@ -4,32 +4,31 @@ package model - type CreateRecordOpenapiResponseBodyTypeEnum string // List of Type const ( - CreateRecordOpenapiResponseBodyTypeEnumA CreateRecordOpenapiResponseBodyTypeEnum = "A" - CreateRecordOpenapiResponseBodyTypeEnumAaaa CreateRecordOpenapiResponseBodyTypeEnum = "AAAA" - CreateRecordOpenapiResponseBodyTypeEnumCname CreateRecordOpenapiResponseBodyTypeEnum = "CNAME" - CreateRecordOpenapiResponseBodyTypeEnumMx CreateRecordOpenapiResponseBodyTypeEnum = "MX" - CreateRecordOpenapiResponseBodyTypeEnumTxt CreateRecordOpenapiResponseBodyTypeEnum = "TXT" - CreateRecordOpenapiResponseBodyTypeEnumNs CreateRecordOpenapiResponseBodyTypeEnum = "NS" - CreateRecordOpenapiResponseBodyTypeEnumSpf CreateRecordOpenapiResponseBodyTypeEnum = "SPF" - CreateRecordOpenapiResponseBodyTypeEnumSrv CreateRecordOpenapiResponseBodyTypeEnum = "SRV" - CreateRecordOpenapiResponseBodyTypeEnumCaa CreateRecordOpenapiResponseBodyTypeEnum = "CAA" - CreateRecordOpenapiResponseBodyTypeEnumCmauth CreateRecordOpenapiResponseBodyTypeEnum = "CMAUTH" + CreateRecordOpenapiResponseBodyTypeEnumA CreateRecordOpenapiResponseBodyTypeEnum = "A" + CreateRecordOpenapiResponseBodyTypeEnumAaaa CreateRecordOpenapiResponseBodyTypeEnum = "AAAA" + CreateRecordOpenapiResponseBodyTypeEnumCname CreateRecordOpenapiResponseBodyTypeEnum = "CNAME" + CreateRecordOpenapiResponseBodyTypeEnumMx CreateRecordOpenapiResponseBodyTypeEnum = "MX" + CreateRecordOpenapiResponseBodyTypeEnumTxt CreateRecordOpenapiResponseBodyTypeEnum = "TXT" + CreateRecordOpenapiResponseBodyTypeEnumNs CreateRecordOpenapiResponseBodyTypeEnum = "NS" + CreateRecordOpenapiResponseBodyTypeEnumSpf CreateRecordOpenapiResponseBodyTypeEnum = "SPF" + CreateRecordOpenapiResponseBodyTypeEnumSrv CreateRecordOpenapiResponseBodyTypeEnum = "SRV" + CreateRecordOpenapiResponseBodyTypeEnumCaa CreateRecordOpenapiResponseBodyTypeEnum = "CAA" + CreateRecordOpenapiResponseBodyTypeEnumCmauth CreateRecordOpenapiResponseBodyTypeEnum = "CMAUTH" ) + type CreateRecordOpenapiResponseBodyStateEnum string // List of State const ( - CreateRecordOpenapiResponseBodyStateEnumDisabled CreateRecordOpenapiResponseBodyStateEnum = "DISABLED" - CreateRecordOpenapiResponseBodyStateEnumEnabled CreateRecordOpenapiResponseBodyStateEnum = "ENABLED" + CreateRecordOpenapiResponseBodyStateEnumDisabled CreateRecordOpenapiResponseBodyStateEnum = "DISABLED" + CreateRecordOpenapiResponseBodyStateEnumEnabled CreateRecordOpenapiResponseBodyStateEnum = "ENABLED" ) type CreateRecordOpenapiResponseBody struct { - // 主机头 Rr string `json:"rr,omitempty"` diff --git a/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/create_record_openapi_response_tags.go b/internal/pkg/sdk3rd/cmcc/ecloudsdkclouddns@v1.0.1/model/create_record_openapi_response_tags.go similarity index 98% rename from internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/create_record_openapi_response_tags.go rename to internal/pkg/sdk3rd/cmcc/ecloudsdkclouddns@v1.0.1/model/create_record_openapi_response_tags.go index a4bda62c..6cc5a35b 100644 --- a/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/create_record_openapi_response_tags.go +++ b/internal/pkg/sdk3rd/cmcc/ecloudsdkclouddns@v1.0.1/model/create_record_openapi_response_tags.go @@ -4,10 +4,7 @@ package model - - type CreateRecordOpenapiResponseTags struct { - // 标签ID TagId string `json:"tagId,omitempty"` diff --git a/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/create_record_request.go b/internal/pkg/sdk3rd/cmcc/ecloudsdkclouddns@v1.0.1/model/create_record_request.go similarity index 98% rename from internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/create_record_request.go rename to internal/pkg/sdk3rd/cmcc/ecloudsdkclouddns@v1.0.1/model/create_record_request.go index 715f03ff..d73c37b2 100644 --- a/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/create_record_request.go +++ b/internal/pkg/sdk3rd/cmcc/ecloudsdkclouddns@v1.0.1/model/create_record_request.go @@ -4,9 +4,6 @@ package model - - type CreateRecordRequest struct { - CreateRecordBody *CreateRecordBody `json:"createRecordBody,omitempty"` } diff --git a/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/create_record_response.go b/internal/pkg/sdk3rd/cmcc/ecloudsdkclouddns@v1.0.1/model/create_record_response.go similarity index 59% rename from internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/create_record_response.go rename to internal/pkg/sdk3rd/cmcc/ecloudsdkclouddns@v1.0.1/model/create_record_response.go index bd277c0c..017f02b1 100644 --- a/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/create_record_response.go +++ b/internal/pkg/sdk3rd/cmcc/ecloudsdkclouddns@v1.0.1/model/create_record_response.go @@ -4,19 +4,17 @@ package model - type CreateRecordResponseStateEnum string // List of State const ( - CreateRecordResponseStateEnumError CreateRecordResponseStateEnum = "ERROR" - CreateRecordResponseStateEnumException CreateRecordResponseStateEnum = "EXCEPTION" - CreateRecordResponseStateEnumForbidden CreateRecordResponseStateEnum = "FORBIDDEN" - CreateRecordResponseStateEnumOk CreateRecordResponseStateEnum = "OK" + CreateRecordResponseStateEnumError CreateRecordResponseStateEnum = "ERROR" + CreateRecordResponseStateEnumException CreateRecordResponseStateEnum = "EXCEPTION" + CreateRecordResponseStateEnumForbidden CreateRecordResponseStateEnum = "FORBIDDEN" + CreateRecordResponseStateEnumOk CreateRecordResponseStateEnum = "OK" ) type CreateRecordResponse struct { - RequestId string `json:"requestId,omitempty"` ErrorMessage string `json:"errorMessage,omitempty"` diff --git a/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/create_record_response_body.go b/internal/pkg/sdk3rd/cmcc/ecloudsdkclouddns@v1.0.1/model/create_record_response_body.go similarity index 53% rename from internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/create_record_response_body.go rename to internal/pkg/sdk3rd/cmcc/ecloudsdkclouddns@v1.0.1/model/create_record_response_body.go index 64660b91..8e604bd4 100644 --- a/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/create_record_response_body.go +++ b/internal/pkg/sdk3rd/cmcc/ecloudsdkclouddns@v1.0.1/model/create_record_response_body.go @@ -4,43 +4,43 @@ package model - type CreateRecordResponseBodyTypeEnum string // List of Type const ( - CreateRecordResponseBodyTypeEnumA CreateRecordResponseBodyTypeEnum = "A" - CreateRecordResponseBodyTypeEnumAaaa CreateRecordResponseBodyTypeEnum = "AAAA" - CreateRecordResponseBodyTypeEnumCaa CreateRecordResponseBodyTypeEnum = "CAA" - CreateRecordResponseBodyTypeEnumCmauth CreateRecordResponseBodyTypeEnum = "CMAUTH" - CreateRecordResponseBodyTypeEnumCname CreateRecordResponseBodyTypeEnum = "CNAME" - CreateRecordResponseBodyTypeEnumMx CreateRecordResponseBodyTypeEnum = "MX" - CreateRecordResponseBodyTypeEnumNs CreateRecordResponseBodyTypeEnum = "NS" - CreateRecordResponseBodyTypeEnumPtr CreateRecordResponseBodyTypeEnum = "PTR" - CreateRecordResponseBodyTypeEnumRp CreateRecordResponseBodyTypeEnum = "RP" - CreateRecordResponseBodyTypeEnumSpf CreateRecordResponseBodyTypeEnum = "SPF" - CreateRecordResponseBodyTypeEnumSrv CreateRecordResponseBodyTypeEnum = "SRV" - CreateRecordResponseBodyTypeEnumTxt CreateRecordResponseBodyTypeEnum = "TXT" - CreateRecordResponseBodyTypeEnumUrl CreateRecordResponseBodyTypeEnum = "URL" + CreateRecordResponseBodyTypeEnumA CreateRecordResponseBodyTypeEnum = "A" + CreateRecordResponseBodyTypeEnumAaaa CreateRecordResponseBodyTypeEnum = "AAAA" + CreateRecordResponseBodyTypeEnumCaa CreateRecordResponseBodyTypeEnum = "CAA" + CreateRecordResponseBodyTypeEnumCmauth CreateRecordResponseBodyTypeEnum = "CMAUTH" + CreateRecordResponseBodyTypeEnumCname CreateRecordResponseBodyTypeEnum = "CNAME" + CreateRecordResponseBodyTypeEnumMx CreateRecordResponseBodyTypeEnum = "MX" + CreateRecordResponseBodyTypeEnumNs CreateRecordResponseBodyTypeEnum = "NS" + CreateRecordResponseBodyTypeEnumPtr CreateRecordResponseBodyTypeEnum = "PTR" + CreateRecordResponseBodyTypeEnumRp CreateRecordResponseBodyTypeEnum = "RP" + CreateRecordResponseBodyTypeEnumSpf CreateRecordResponseBodyTypeEnum = "SPF" + CreateRecordResponseBodyTypeEnumSrv CreateRecordResponseBodyTypeEnum = "SRV" + CreateRecordResponseBodyTypeEnumTxt CreateRecordResponseBodyTypeEnum = "TXT" + CreateRecordResponseBodyTypeEnumUrl CreateRecordResponseBodyTypeEnum = "URL" ) + type CreateRecordResponseBodyTimedStatusEnum string // List of TimedStatus const ( - CreateRecordResponseBodyTimedStatusEnumDisabled CreateRecordResponseBodyTimedStatusEnum = "DISABLED" - CreateRecordResponseBodyTimedStatusEnumEnabled CreateRecordResponseBodyTimedStatusEnum = "ENABLED" - CreateRecordResponseBodyTimedStatusEnumTimed CreateRecordResponseBodyTimedStatusEnum = "TIMED" + CreateRecordResponseBodyTimedStatusEnumDisabled CreateRecordResponseBodyTimedStatusEnum = "DISABLED" + CreateRecordResponseBodyTimedStatusEnumEnabled CreateRecordResponseBodyTimedStatusEnum = "ENABLED" + CreateRecordResponseBodyTimedStatusEnumTimed CreateRecordResponseBodyTimedStatusEnum = "TIMED" ) + type CreateRecordResponseBodyStateEnum string // List of State const ( - CreateRecordResponseBodyStateEnumDisabled CreateRecordResponseBodyStateEnum = "DISABLED" - CreateRecordResponseBodyStateEnumEnabled CreateRecordResponseBodyStateEnum = "ENABLED" + CreateRecordResponseBodyStateEnumDisabled CreateRecordResponseBodyStateEnum = "DISABLED" + CreateRecordResponseBodyStateEnumEnabled CreateRecordResponseBodyStateEnum = "ENABLED" ) type CreateRecordResponseBody struct { - // 主机头 Rr string `json:"rr,omitempty"` diff --git a/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/create_record_response_tags.go b/internal/pkg/sdk3rd/cmcc/ecloudsdkclouddns@v1.0.1/model/create_record_response_tags.go similarity index 98% rename from internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/create_record_response_tags.go rename to internal/pkg/sdk3rd/cmcc/ecloudsdkclouddns@v1.0.1/model/create_record_response_tags.go index 003680d5..d225dfaf 100644 --- a/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/create_record_response_tags.go +++ b/internal/pkg/sdk3rd/cmcc/ecloudsdkclouddns@v1.0.1/model/create_record_response_tags.go @@ -4,10 +4,7 @@ package model - - type CreateRecordResponseTags struct { - // 标签ID TagId string `json:"tagId,omitempty"` diff --git a/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/delete_record_body.go b/internal/pkg/sdk3rd/cmcc/ecloudsdkclouddns@v1.0.1/model/delete_record_body.go similarity index 76% rename from internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/delete_record_body.go rename to internal/pkg/sdk3rd/cmcc/ecloudsdkclouddns@v1.0.1/model/delete_record_body.go index 326b9abb..86974b24 100644 --- a/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/delete_record_body.go +++ b/internal/pkg/sdk3rd/cmcc/ecloudsdkclouddns@v1.0.1/model/delete_record_body.go @@ -5,11 +5,11 @@ package model import ( - "gitlab.ecloud.com/ecloud/ecloudsdkcore/position" + "gitlab.ecloud.com/ecloud/ecloudsdkcore/position" ) type DeleteRecordBody struct { - position.Body + position.Body // 解析记录ID列表 RecordIdList []string `json:"recordIdList"` } diff --git a/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/delete_record_openapi_body.go b/internal/pkg/sdk3rd/cmcc/ecloudsdkclouddns@v1.0.1/model/delete_record_openapi_body.go similarity index 77% rename from internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/delete_record_openapi_body.go rename to internal/pkg/sdk3rd/cmcc/ecloudsdkclouddns@v1.0.1/model/delete_record_openapi_body.go index e5614ac5..220b5929 100644 --- a/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/delete_record_openapi_body.go +++ b/internal/pkg/sdk3rd/cmcc/ecloudsdkclouddns@v1.0.1/model/delete_record_openapi_body.go @@ -5,11 +5,11 @@ package model import ( - "gitlab.ecloud.com/ecloud/ecloudsdkcore/position" + "gitlab.ecloud.com/ecloud/ecloudsdkcore/position" ) type DeleteRecordOpenapiBody struct { - position.Body + position.Body // 待删除的解析记录ID请求体 RecordIdList []string `json:"recordIdList"` } diff --git a/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/delete_record_openapi_request.go b/internal/pkg/sdk3rd/cmcc/ecloudsdkclouddns@v1.0.1/model/delete_record_openapi_request.go similarity index 98% rename from internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/delete_record_openapi_request.go rename to internal/pkg/sdk3rd/cmcc/ecloudsdkclouddns@v1.0.1/model/delete_record_openapi_request.go index 1cb684d6..33e89735 100644 --- a/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/delete_record_openapi_request.go +++ b/internal/pkg/sdk3rd/cmcc/ecloudsdkclouddns@v1.0.1/model/delete_record_openapi_request.go @@ -4,9 +4,6 @@ package model - - type DeleteRecordOpenapiRequest struct { - DeleteRecordOpenapiBody *DeleteRecordOpenapiBody `json:"deleteRecordOpenapiBody,omitempty"` } diff --git a/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/delete_record_openapi_response.go b/internal/pkg/sdk3rd/cmcc/ecloudsdkclouddns@v1.0.1/model/delete_record_openapi_response.go similarity index 57% rename from internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/delete_record_openapi_response.go rename to internal/pkg/sdk3rd/cmcc/ecloudsdkclouddns@v1.0.1/model/delete_record_openapi_response.go index ca528148..469afa87 100644 --- a/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/delete_record_openapi_response.go +++ b/internal/pkg/sdk3rd/cmcc/ecloudsdkclouddns@v1.0.1/model/delete_record_openapi_response.go @@ -4,19 +4,17 @@ package model - type DeleteRecordOpenapiResponseStateEnum string // List of State const ( - DeleteRecordOpenapiResponseStateEnumError DeleteRecordOpenapiResponseStateEnum = "ERROR" - DeleteRecordOpenapiResponseStateEnumException DeleteRecordOpenapiResponseStateEnum = "EXCEPTION" - DeleteRecordOpenapiResponseStateEnumForbidden DeleteRecordOpenapiResponseStateEnum = "FORBIDDEN" - DeleteRecordOpenapiResponseStateEnumOk DeleteRecordOpenapiResponseStateEnum = "OK" + DeleteRecordOpenapiResponseStateEnumError DeleteRecordOpenapiResponseStateEnum = "ERROR" + DeleteRecordOpenapiResponseStateEnumException DeleteRecordOpenapiResponseStateEnum = "EXCEPTION" + DeleteRecordOpenapiResponseStateEnumForbidden DeleteRecordOpenapiResponseStateEnum = "FORBIDDEN" + DeleteRecordOpenapiResponseStateEnumOk DeleteRecordOpenapiResponseStateEnum = "OK" ) type DeleteRecordOpenapiResponse struct { - RequestId string `json:"requestId,omitempty"` ErrorMessage string `json:"errorMessage,omitempty"` diff --git a/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/delete_record_openapi_response_body.go b/internal/pkg/sdk3rd/cmcc/ecloudsdkclouddns@v1.0.1/model/delete_record_openapi_response_body.go similarity index 71% rename from internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/delete_record_openapi_response_body.go rename to internal/pkg/sdk3rd/cmcc/ecloudsdkclouddns@v1.0.1/model/delete_record_openapi_response_body.go index 67da3ab7..fb985000 100644 --- a/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/delete_record_openapi_response_body.go +++ b/internal/pkg/sdk3rd/cmcc/ecloudsdkclouddns@v1.0.1/model/delete_record_openapi_response_body.go @@ -4,17 +4,15 @@ package model - type DeleteRecordOpenapiResponseBodyCodeEnum string // List of Code const ( - DeleteRecordOpenapiResponseBodyCodeEnumError DeleteRecordOpenapiResponseBodyCodeEnum = "ERROR" - DeleteRecordOpenapiResponseBodyCodeEnumSuccess DeleteRecordOpenapiResponseBodyCodeEnum = "SUCCESS" + DeleteRecordOpenapiResponseBodyCodeEnumError DeleteRecordOpenapiResponseBodyCodeEnum = "ERROR" + DeleteRecordOpenapiResponseBodyCodeEnumSuccess DeleteRecordOpenapiResponseBodyCodeEnum = "SUCCESS" ) type DeleteRecordOpenapiResponseBody struct { - // 结果说明 Msg string `json:"msg,omitempty"` diff --git a/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/delete_record_request.go b/internal/pkg/sdk3rd/cmcc/ecloudsdkclouddns@v1.0.1/model/delete_record_request.go similarity index 98% rename from internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/delete_record_request.go rename to internal/pkg/sdk3rd/cmcc/ecloudsdkclouddns@v1.0.1/model/delete_record_request.go index 678fd8ef..93af08f4 100644 --- a/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/delete_record_request.go +++ b/internal/pkg/sdk3rd/cmcc/ecloudsdkclouddns@v1.0.1/model/delete_record_request.go @@ -4,9 +4,6 @@ package model - - type DeleteRecordRequest struct { - DeleteRecordBody *DeleteRecordBody `json:"deleteRecordBody,omitempty"` } diff --git a/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/delete_record_response.go b/internal/pkg/sdk3rd/cmcc/ecloudsdkclouddns@v1.0.1/model/delete_record_response.go similarity index 60% rename from internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/delete_record_response.go rename to internal/pkg/sdk3rd/cmcc/ecloudsdkclouddns@v1.0.1/model/delete_record_response.go index 051d7105..7c14860d 100644 --- a/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/delete_record_response.go +++ b/internal/pkg/sdk3rd/cmcc/ecloudsdkclouddns@v1.0.1/model/delete_record_response.go @@ -4,19 +4,17 @@ package model - type DeleteRecordResponseStateEnum string // List of State const ( - DeleteRecordResponseStateEnumError DeleteRecordResponseStateEnum = "ERROR" - DeleteRecordResponseStateEnumException DeleteRecordResponseStateEnum = "EXCEPTION" - DeleteRecordResponseStateEnumForbidden DeleteRecordResponseStateEnum = "FORBIDDEN" - DeleteRecordResponseStateEnumOk DeleteRecordResponseStateEnum = "OK" + DeleteRecordResponseStateEnumError DeleteRecordResponseStateEnum = "ERROR" + DeleteRecordResponseStateEnumException DeleteRecordResponseStateEnum = "EXCEPTION" + DeleteRecordResponseStateEnumForbidden DeleteRecordResponseStateEnum = "FORBIDDEN" + DeleteRecordResponseStateEnumOk DeleteRecordResponseStateEnum = "OK" ) type DeleteRecordResponse struct { - RequestId string `json:"requestId,omitempty"` ErrorMessage string `json:"errorMessage,omitempty"` diff --git a/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/delete_record_response_body.go b/internal/pkg/sdk3rd/cmcc/ecloudsdkclouddns@v1.0.1/model/delete_record_response_body.go similarity index 73% rename from internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/delete_record_response_body.go rename to internal/pkg/sdk3rd/cmcc/ecloudsdkclouddns@v1.0.1/model/delete_record_response_body.go index 45320290..40bf0af8 100644 --- a/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/delete_record_response_body.go +++ b/internal/pkg/sdk3rd/cmcc/ecloudsdkclouddns@v1.0.1/model/delete_record_response_body.go @@ -4,17 +4,15 @@ package model - type DeleteRecordResponseBodyCodeEnum string // List of Code const ( - DeleteRecordResponseBodyCodeEnumError DeleteRecordResponseBodyCodeEnum = "ERROR" - DeleteRecordResponseBodyCodeEnumSuccess DeleteRecordResponseBodyCodeEnum = "SUCCESS" + DeleteRecordResponseBodyCodeEnumError DeleteRecordResponseBodyCodeEnum = "ERROR" + DeleteRecordResponseBodyCodeEnumSuccess DeleteRecordResponseBodyCodeEnum = "SUCCESS" ) type DeleteRecordResponseBody struct { - // 结果说明 Msg string `json:"msg,omitempty"` diff --git a/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/list_record_body.go b/internal/pkg/sdk3rd/cmcc/ecloudsdkclouddns@v1.0.1/model/list_record_body.go similarity index 82% rename from internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/list_record_body.go rename to internal/pkg/sdk3rd/cmcc/ecloudsdkclouddns@v1.0.1/model/list_record_body.go index 5eadce7a..5509937c 100644 --- a/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/list_record_body.go +++ b/internal/pkg/sdk3rd/cmcc/ecloudsdkclouddns@v1.0.1/model/list_record_body.go @@ -5,11 +5,11 @@ package model import ( - "gitlab.ecloud.com/ecloud/ecloudsdkcore/position" + "gitlab.ecloud.com/ecloud/ecloudsdkcore/position" ) type ListRecordBody struct { - position.Body + position.Body // 域名 DomainName string `json:"domainName"` diff --git a/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/list_record_openapi_body.go b/internal/pkg/sdk3rd/cmcc/ecloudsdkclouddns@v1.0.1/model/list_record_openapi_body.go similarity index 74% rename from internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/list_record_openapi_body.go rename to internal/pkg/sdk3rd/cmcc/ecloudsdkclouddns@v1.0.1/model/list_record_openapi_body.go index 63f5e13a..f33462ea 100644 --- a/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/list_record_openapi_body.go +++ b/internal/pkg/sdk3rd/cmcc/ecloudsdkclouddns@v1.0.1/model/list_record_openapi_body.go @@ -5,11 +5,11 @@ package model import ( - "gitlab.ecloud.com/ecloud/ecloudsdkcore/position" + "gitlab.ecloud.com/ecloud/ecloudsdkcore/position" ) type ListRecordOpenapiBody struct { - position.Body + position.Body // 域名 DomainName string `json:"domainName"` } diff --git a/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/list_record_openapi_query.go b/internal/pkg/sdk3rd/cmcc/ecloudsdkclouddns@v1.0.1/model/list_record_openapi_query.go similarity index 79% rename from internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/list_record_openapi_query.go rename to internal/pkg/sdk3rd/cmcc/ecloudsdkclouddns@v1.0.1/model/list_record_openapi_query.go index ee89a7f5..5e2a9162 100644 --- a/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/list_record_openapi_query.go +++ b/internal/pkg/sdk3rd/cmcc/ecloudsdkclouddns@v1.0.1/model/list_record_openapi_query.go @@ -5,11 +5,11 @@ package model import ( - "gitlab.ecloud.com/ecloud/ecloudsdkcore/position" + "gitlab.ecloud.com/ecloud/ecloudsdkcore/position" ) type ListRecordOpenapiQuery struct { - position.Query + position.Query // 页大小 PageSize *int32 `json:"pageSize,omitempty"` diff --git a/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/list_record_openapi_request.go b/internal/pkg/sdk3rd/cmcc/ecloudsdkclouddns@v1.0.1/model/list_record_openapi_request.go similarity index 99% rename from internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/list_record_openapi_request.go rename to internal/pkg/sdk3rd/cmcc/ecloudsdkclouddns@v1.0.1/model/list_record_openapi_request.go index 34540481..107e6b1f 100644 --- a/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/list_record_openapi_request.go +++ b/internal/pkg/sdk3rd/cmcc/ecloudsdkclouddns@v1.0.1/model/list_record_openapi_request.go @@ -4,10 +4,7 @@ package model - - type ListRecordOpenapiRequest struct { - ListRecordOpenapiQuery *ListRecordOpenapiQuery `json:"listRecordOpenapiQuery,omitempty"` ListRecordOpenapiBody *ListRecordOpenapiBody `json:"listRecordOpenapiBody,omitempty"` diff --git a/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/list_record_openapi_response.go b/internal/pkg/sdk3rd/cmcc/ecloudsdkclouddns@v1.0.1/model/list_record_openapi_response.go similarity index 58% rename from internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/list_record_openapi_response.go rename to internal/pkg/sdk3rd/cmcc/ecloudsdkclouddns@v1.0.1/model/list_record_openapi_response.go index 36646938..a752b1b4 100644 --- a/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/list_record_openapi_response.go +++ b/internal/pkg/sdk3rd/cmcc/ecloudsdkclouddns@v1.0.1/model/list_record_openapi_response.go @@ -4,19 +4,17 @@ package model - type ListRecordOpenapiResponseStateEnum string // List of State const ( - ListRecordOpenapiResponseStateEnumError ListRecordOpenapiResponseStateEnum = "ERROR" - ListRecordOpenapiResponseStateEnumException ListRecordOpenapiResponseStateEnum = "EXCEPTION" - ListRecordOpenapiResponseStateEnumForbidden ListRecordOpenapiResponseStateEnum = "FORBIDDEN" - ListRecordOpenapiResponseStateEnumOk ListRecordOpenapiResponseStateEnum = "OK" + ListRecordOpenapiResponseStateEnumError ListRecordOpenapiResponseStateEnum = "ERROR" + ListRecordOpenapiResponseStateEnumException ListRecordOpenapiResponseStateEnum = "EXCEPTION" + ListRecordOpenapiResponseStateEnumForbidden ListRecordOpenapiResponseStateEnum = "FORBIDDEN" + ListRecordOpenapiResponseStateEnumOk ListRecordOpenapiResponseStateEnum = "OK" ) type ListRecordOpenapiResponse struct { - RequestId string `json:"requestId,omitempty"` ErrorMessage string `json:"errorMessage,omitempty"` diff --git a/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/list_record_openapi_response_body.go b/internal/pkg/sdk3rd/cmcc/ecloudsdkclouddns@v1.0.1/model/list_record_openapi_response_body.go similarity index 99% rename from internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/list_record_openapi_response_body.go rename to internal/pkg/sdk3rd/cmcc/ecloudsdkclouddns@v1.0.1/model/list_record_openapi_response_body.go index 8c6f7302..e37fdbe4 100644 --- a/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/list_record_openapi_response_body.go +++ b/internal/pkg/sdk3rd/cmcc/ecloudsdkclouddns@v1.0.1/model/list_record_openapi_response_body.go @@ -4,10 +4,7 @@ package model - - type ListRecordOpenapiResponseBody struct { - // 当前页的具体数据列表 Data *[]ListRecordOpenapiResponseData `json:"data,omitempty"` diff --git a/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/list_record_openapi_response_data.go b/internal/pkg/sdk3rd/cmcc/ecloudsdkclouddns@v1.0.1/model/list_record_openapi_response_data.go similarity index 56% rename from internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/list_record_openapi_response_data.go rename to internal/pkg/sdk3rd/cmcc/ecloudsdkclouddns@v1.0.1/model/list_record_openapi_response_data.go index 19981aa9..2594d14c 100644 --- a/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/list_record_openapi_response_data.go +++ b/internal/pkg/sdk3rd/cmcc/ecloudsdkclouddns@v1.0.1/model/list_record_openapi_response_data.go @@ -4,40 +4,40 @@ package model - type ListRecordOpenapiResponseDataTypeEnum string // List of Type const ( - ListRecordOpenapiResponseDataTypeEnumA ListRecordOpenapiResponseDataTypeEnum = "A" - ListRecordOpenapiResponseDataTypeEnumAaaa ListRecordOpenapiResponseDataTypeEnum = "AAAA" - ListRecordOpenapiResponseDataTypeEnumCname ListRecordOpenapiResponseDataTypeEnum = "CNAME" - ListRecordOpenapiResponseDataTypeEnumMx ListRecordOpenapiResponseDataTypeEnum = "MX" - ListRecordOpenapiResponseDataTypeEnumTxt ListRecordOpenapiResponseDataTypeEnum = "TXT" - ListRecordOpenapiResponseDataTypeEnumNs ListRecordOpenapiResponseDataTypeEnum = "NS" - ListRecordOpenapiResponseDataTypeEnumSpf ListRecordOpenapiResponseDataTypeEnum = "SPF" - ListRecordOpenapiResponseDataTypeEnumSrv ListRecordOpenapiResponseDataTypeEnum = "SRV" - ListRecordOpenapiResponseDataTypeEnumCaa ListRecordOpenapiResponseDataTypeEnum = "CAA" - ListRecordOpenapiResponseDataTypeEnumCmauth ListRecordOpenapiResponseDataTypeEnum = "CMAUTH" + ListRecordOpenapiResponseDataTypeEnumA ListRecordOpenapiResponseDataTypeEnum = "A" + ListRecordOpenapiResponseDataTypeEnumAaaa ListRecordOpenapiResponseDataTypeEnum = "AAAA" + ListRecordOpenapiResponseDataTypeEnumCname ListRecordOpenapiResponseDataTypeEnum = "CNAME" + ListRecordOpenapiResponseDataTypeEnumMx ListRecordOpenapiResponseDataTypeEnum = "MX" + ListRecordOpenapiResponseDataTypeEnumTxt ListRecordOpenapiResponseDataTypeEnum = "TXT" + ListRecordOpenapiResponseDataTypeEnumNs ListRecordOpenapiResponseDataTypeEnum = "NS" + ListRecordOpenapiResponseDataTypeEnumSpf ListRecordOpenapiResponseDataTypeEnum = "SPF" + ListRecordOpenapiResponseDataTypeEnumSrv ListRecordOpenapiResponseDataTypeEnum = "SRV" + ListRecordOpenapiResponseDataTypeEnumCaa ListRecordOpenapiResponseDataTypeEnum = "CAA" + ListRecordOpenapiResponseDataTypeEnumCmauth ListRecordOpenapiResponseDataTypeEnum = "CMAUTH" ) + type ListRecordOpenapiResponseDataTimedStatusEnum string // List of TimedStatus const ( - ListRecordOpenapiResponseDataTimedStatusEnumDisabled ListRecordOpenapiResponseDataTimedStatusEnum = "DISABLED" - ListRecordOpenapiResponseDataTimedStatusEnumEnabled ListRecordOpenapiResponseDataTimedStatusEnum = "ENABLED" - ListRecordOpenapiResponseDataTimedStatusEnumTimed ListRecordOpenapiResponseDataTimedStatusEnum = "TIMED" + ListRecordOpenapiResponseDataTimedStatusEnumDisabled ListRecordOpenapiResponseDataTimedStatusEnum = "DISABLED" + ListRecordOpenapiResponseDataTimedStatusEnumEnabled ListRecordOpenapiResponseDataTimedStatusEnum = "ENABLED" + ListRecordOpenapiResponseDataTimedStatusEnumTimed ListRecordOpenapiResponseDataTimedStatusEnum = "TIMED" ) + type ListRecordOpenapiResponseDataStateEnum string // List of State const ( - ListRecordOpenapiResponseDataStateEnumDisabled ListRecordOpenapiResponseDataStateEnum = "DISABLED" - ListRecordOpenapiResponseDataStateEnumEnabled ListRecordOpenapiResponseDataStateEnum = "ENABLED" + ListRecordOpenapiResponseDataStateEnumDisabled ListRecordOpenapiResponseDataStateEnum = "DISABLED" + ListRecordOpenapiResponseDataStateEnumEnabled ListRecordOpenapiResponseDataStateEnum = "ENABLED" ) type ListRecordOpenapiResponseData struct { - // 主机头 Rr string `json:"rr,omitempty"` diff --git a/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/list_record_openapi_response_tags.go b/internal/pkg/sdk3rd/cmcc/ecloudsdkclouddns@v1.0.1/model/list_record_openapi_response_tags.go similarity index 98% rename from internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/list_record_openapi_response_tags.go rename to internal/pkg/sdk3rd/cmcc/ecloudsdkclouddns@v1.0.1/model/list_record_openapi_response_tags.go index 867f667f..43230238 100644 --- a/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/list_record_openapi_response_tags.go +++ b/internal/pkg/sdk3rd/cmcc/ecloudsdkclouddns@v1.0.1/model/list_record_openapi_response_tags.go @@ -4,10 +4,7 @@ package model - - type ListRecordOpenapiResponseTags struct { - // 标签ID TagId string `json:"tagId,omitempty"` diff --git a/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/list_record_query.go b/internal/pkg/sdk3rd/cmcc/ecloudsdkclouddns@v1.0.1/model/list_record_query.go similarity index 79% rename from internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/list_record_query.go rename to internal/pkg/sdk3rd/cmcc/ecloudsdkclouddns@v1.0.1/model/list_record_query.go index df871a76..dca4b67c 100644 --- a/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/list_record_query.go +++ b/internal/pkg/sdk3rd/cmcc/ecloudsdkclouddns@v1.0.1/model/list_record_query.go @@ -5,11 +5,11 @@ package model import ( - "gitlab.ecloud.com/ecloud/ecloudsdkcore/position" + "gitlab.ecloud.com/ecloud/ecloudsdkcore/position" ) type ListRecordQuery struct { - position.Query + position.Query // 页大小 PageSize *int32 `json:"pageSize,omitempty"` diff --git a/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/list_record_request.go b/internal/pkg/sdk3rd/cmcc/ecloudsdkclouddns@v1.0.1/model/list_record_request.go similarity index 98% rename from internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/list_record_request.go rename to internal/pkg/sdk3rd/cmcc/ecloudsdkclouddns@v1.0.1/model/list_record_request.go index 5ff9df08..37e9512e 100644 --- a/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/list_record_request.go +++ b/internal/pkg/sdk3rd/cmcc/ecloudsdkclouddns@v1.0.1/model/list_record_request.go @@ -4,10 +4,7 @@ package model - - type ListRecordRequest struct { - ListRecordBody *ListRecordBody `json:"listRecordBody,omitempty"` ListRecordQuery *ListRecordQuery `json:"listRecordQuery,omitempty"` diff --git a/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/list_record_response.go b/internal/pkg/sdk3rd/cmcc/ecloudsdkclouddns@v1.0.1/model/list_record_response.go similarity index 60% rename from internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/list_record_response.go rename to internal/pkg/sdk3rd/cmcc/ecloudsdkclouddns@v1.0.1/model/list_record_response.go index b11f3d21..dde07b61 100644 --- a/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/list_record_response.go +++ b/internal/pkg/sdk3rd/cmcc/ecloudsdkclouddns@v1.0.1/model/list_record_response.go @@ -4,19 +4,17 @@ package model - type ListRecordResponseStateEnum string // List of State const ( - ListRecordResponseStateEnumError ListRecordResponseStateEnum = "ERROR" - ListRecordResponseStateEnumException ListRecordResponseStateEnum = "EXCEPTION" - ListRecordResponseStateEnumForbidden ListRecordResponseStateEnum = "FORBIDDEN" - ListRecordResponseStateEnumOk ListRecordResponseStateEnum = "OK" + ListRecordResponseStateEnumError ListRecordResponseStateEnum = "ERROR" + ListRecordResponseStateEnumException ListRecordResponseStateEnum = "EXCEPTION" + ListRecordResponseStateEnumForbidden ListRecordResponseStateEnum = "FORBIDDEN" + ListRecordResponseStateEnumOk ListRecordResponseStateEnum = "OK" ) type ListRecordResponse struct { - RequestId string `json:"requestId,omitempty"` ErrorMessage string `json:"errorMessage,omitempty"` diff --git a/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/list_record_response_body.go b/internal/pkg/sdk3rd/cmcc/ecloudsdkclouddns@v1.0.1/model/list_record_response_body.go similarity index 99% rename from internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/list_record_response_body.go rename to internal/pkg/sdk3rd/cmcc/ecloudsdkclouddns@v1.0.1/model/list_record_response_body.go index 0acf543d..3753d1aa 100644 --- a/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/list_record_response_body.go +++ b/internal/pkg/sdk3rd/cmcc/ecloudsdkclouddns@v1.0.1/model/list_record_response_body.go @@ -4,10 +4,7 @@ package model - - type ListRecordResponseBody struct { - // 总页数 TotalPages *int32 `json:"totalPages,omitempty"` diff --git a/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/list_record_response_results.go b/internal/pkg/sdk3rd/cmcc/ecloudsdkclouddns@v1.0.1/model/list_record_response_results.go similarity index 52% rename from internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/list_record_response_results.go rename to internal/pkg/sdk3rd/cmcc/ecloudsdkclouddns@v1.0.1/model/list_record_response_results.go index 7498fca3..1020dd56 100644 --- a/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/list_record_response_results.go +++ b/internal/pkg/sdk3rd/cmcc/ecloudsdkclouddns@v1.0.1/model/list_record_response_results.go @@ -4,43 +4,43 @@ package model - type ListRecordResponseResultsTypeEnum string // List of Type const ( - ListRecordResponseResultsTypeEnumA ListRecordResponseResultsTypeEnum = "A" - ListRecordResponseResultsTypeEnumAaaa ListRecordResponseResultsTypeEnum = "AAAA" - ListRecordResponseResultsTypeEnumCaa ListRecordResponseResultsTypeEnum = "CAA" - ListRecordResponseResultsTypeEnumCmauth ListRecordResponseResultsTypeEnum = "CMAUTH" - ListRecordResponseResultsTypeEnumCname ListRecordResponseResultsTypeEnum = "CNAME" - ListRecordResponseResultsTypeEnumMx ListRecordResponseResultsTypeEnum = "MX" - ListRecordResponseResultsTypeEnumNs ListRecordResponseResultsTypeEnum = "NS" - ListRecordResponseResultsTypeEnumPtr ListRecordResponseResultsTypeEnum = "PTR" - ListRecordResponseResultsTypeEnumRp ListRecordResponseResultsTypeEnum = "RP" - ListRecordResponseResultsTypeEnumSpf ListRecordResponseResultsTypeEnum = "SPF" - ListRecordResponseResultsTypeEnumSrv ListRecordResponseResultsTypeEnum = "SRV" - ListRecordResponseResultsTypeEnumTxt ListRecordResponseResultsTypeEnum = "TXT" - ListRecordResponseResultsTypeEnumUrl ListRecordResponseResultsTypeEnum = "URL" + ListRecordResponseResultsTypeEnumA ListRecordResponseResultsTypeEnum = "A" + ListRecordResponseResultsTypeEnumAaaa ListRecordResponseResultsTypeEnum = "AAAA" + ListRecordResponseResultsTypeEnumCaa ListRecordResponseResultsTypeEnum = "CAA" + ListRecordResponseResultsTypeEnumCmauth ListRecordResponseResultsTypeEnum = "CMAUTH" + ListRecordResponseResultsTypeEnumCname ListRecordResponseResultsTypeEnum = "CNAME" + ListRecordResponseResultsTypeEnumMx ListRecordResponseResultsTypeEnum = "MX" + ListRecordResponseResultsTypeEnumNs ListRecordResponseResultsTypeEnum = "NS" + ListRecordResponseResultsTypeEnumPtr ListRecordResponseResultsTypeEnum = "PTR" + ListRecordResponseResultsTypeEnumRp ListRecordResponseResultsTypeEnum = "RP" + ListRecordResponseResultsTypeEnumSpf ListRecordResponseResultsTypeEnum = "SPF" + ListRecordResponseResultsTypeEnumSrv ListRecordResponseResultsTypeEnum = "SRV" + ListRecordResponseResultsTypeEnumTxt ListRecordResponseResultsTypeEnum = "TXT" + ListRecordResponseResultsTypeEnumUrl ListRecordResponseResultsTypeEnum = "URL" ) + type ListRecordResponseResultsTimedStatusEnum string // List of TimedStatus const ( - ListRecordResponseResultsTimedStatusEnumDisabled ListRecordResponseResultsTimedStatusEnum = "DISABLED" - ListRecordResponseResultsTimedStatusEnumEnabled ListRecordResponseResultsTimedStatusEnum = "ENABLED" - ListRecordResponseResultsTimedStatusEnumTimed ListRecordResponseResultsTimedStatusEnum = "TIMED" + ListRecordResponseResultsTimedStatusEnumDisabled ListRecordResponseResultsTimedStatusEnum = "DISABLED" + ListRecordResponseResultsTimedStatusEnumEnabled ListRecordResponseResultsTimedStatusEnum = "ENABLED" + ListRecordResponseResultsTimedStatusEnumTimed ListRecordResponseResultsTimedStatusEnum = "TIMED" ) + type ListRecordResponseResultsStateEnum string // List of State const ( - ListRecordResponseResultsStateEnumDisabled ListRecordResponseResultsStateEnum = "DISABLED" - ListRecordResponseResultsStateEnumEnabled ListRecordResponseResultsStateEnum = "ENABLED" + ListRecordResponseResultsStateEnumDisabled ListRecordResponseResultsStateEnum = "DISABLED" + ListRecordResponseResultsStateEnumEnabled ListRecordResponseResultsStateEnum = "ENABLED" ) type ListRecordResponseResults struct { - // 主机头 Rr string `json:"rr,omitempty"` diff --git a/internal/pkg/sdk3rd/cmcc/ecloudsdkclouddns@v1.0.1/model/modify_record_body.go b/internal/pkg/sdk3rd/cmcc/ecloudsdkclouddns@v1.0.1/model/modify_record_body.go new file mode 100644 index 00000000..7db497b4 --- /dev/null +++ b/internal/pkg/sdk3rd/cmcc/ecloudsdkclouddns@v1.0.1/model/modify_record_body.go @@ -0,0 +1,58 @@ +// @Title Golang SDK Client +// @Description This code is auto generated +// @Author Ecloud SDK + +package model + +import ( + "gitlab.ecloud.com/ecloud/ecloudsdkcore/position" +) + +type ModifyRecordBodyTypeEnum string + +// List of Type +const ( + ModifyRecordBodyTypeEnumA ModifyRecordBodyTypeEnum = "A" + ModifyRecordBodyTypeEnumAaaa ModifyRecordBodyTypeEnum = "AAAA" + ModifyRecordBodyTypeEnumCaa ModifyRecordBodyTypeEnum = "CAA" + ModifyRecordBodyTypeEnumCmauth ModifyRecordBodyTypeEnum = "CMAUTH" + ModifyRecordBodyTypeEnumCname ModifyRecordBodyTypeEnum = "CNAME" + ModifyRecordBodyTypeEnumMx ModifyRecordBodyTypeEnum = "MX" + ModifyRecordBodyTypeEnumNs ModifyRecordBodyTypeEnum = "NS" + ModifyRecordBodyTypeEnumPtr ModifyRecordBodyTypeEnum = "PTR" + ModifyRecordBodyTypeEnumRp ModifyRecordBodyTypeEnum = "RP" + ModifyRecordBodyTypeEnumSpf ModifyRecordBodyTypeEnum = "SPF" + ModifyRecordBodyTypeEnumSrv ModifyRecordBodyTypeEnum = "SRV" + ModifyRecordBodyTypeEnumTxt ModifyRecordBodyTypeEnum = "TXT" + ModifyRecordBodyTypeEnumUrl ModifyRecordBodyTypeEnum = "URL" +) + +type ModifyRecordBody struct { + position.Body + // 解析记录ID + RecordId string `json:"recordId"` + + // 主机头 + Rr string `json:"rr,omitempty"` + + // 域名名称 + DomainName string `json:"domainName"` + + // 备注 + Description string `json:"description,omitempty"` + + // 线路ID + LineId string `json:"lineId,omitempty"` + + // MX优先级 + MxPri *int32 `json:"mxPri,omitempty"` + + // 记录类型 + Type ModifyRecordBodyTypeEnum `json:"type,omitempty"` + + // 缓存的生命周期 + Ttl *int32 `json:"ttl,omitempty"` + + // 记录值 + Value string `json:"value,omitempty"` +} diff --git a/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/modify_record_openapi_body.go b/internal/pkg/sdk3rd/cmcc/ecloudsdkclouddns@v1.0.1/model/modify_record_openapi_body.go similarity index 50% rename from internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/modify_record_openapi_body.go rename to internal/pkg/sdk3rd/cmcc/ecloudsdkclouddns@v1.0.1/model/modify_record_openapi_body.go index 3bde8919..e7ef4cff 100644 --- a/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/modify_record_openapi_body.go +++ b/internal/pkg/sdk3rd/cmcc/ecloudsdkclouddns@v1.0.1/model/modify_record_openapi_body.go @@ -5,26 +5,27 @@ package model import ( - "gitlab.ecloud.com/ecloud/ecloudsdkcore/position" + "gitlab.ecloud.com/ecloud/ecloudsdkcore/position" ) + type ModifyRecordOpenapiBodyTypeEnum string // List of Type const ( - ModifyRecordOpenapiBodyTypeEnumA ModifyRecordOpenapiBodyTypeEnum = "A" - ModifyRecordOpenapiBodyTypeEnumAaaa ModifyRecordOpenapiBodyTypeEnum = "AAAA" - ModifyRecordOpenapiBodyTypeEnumCname ModifyRecordOpenapiBodyTypeEnum = "CNAME" - ModifyRecordOpenapiBodyTypeEnumMx ModifyRecordOpenapiBodyTypeEnum = "MX" - ModifyRecordOpenapiBodyTypeEnumTxt ModifyRecordOpenapiBodyTypeEnum = "TXT" - ModifyRecordOpenapiBodyTypeEnumNs ModifyRecordOpenapiBodyTypeEnum = "NS" - ModifyRecordOpenapiBodyTypeEnumSpf ModifyRecordOpenapiBodyTypeEnum = "SPF" - ModifyRecordOpenapiBodyTypeEnumSrv ModifyRecordOpenapiBodyTypeEnum = "SRV" - ModifyRecordOpenapiBodyTypeEnumCaa ModifyRecordOpenapiBodyTypeEnum = "CAA" - ModifyRecordOpenapiBodyTypeEnumCmauth ModifyRecordOpenapiBodyTypeEnum = "CMAUTH" + ModifyRecordOpenapiBodyTypeEnumA ModifyRecordOpenapiBodyTypeEnum = "A" + ModifyRecordOpenapiBodyTypeEnumAaaa ModifyRecordOpenapiBodyTypeEnum = "AAAA" + ModifyRecordOpenapiBodyTypeEnumCname ModifyRecordOpenapiBodyTypeEnum = "CNAME" + ModifyRecordOpenapiBodyTypeEnumMx ModifyRecordOpenapiBodyTypeEnum = "MX" + ModifyRecordOpenapiBodyTypeEnumTxt ModifyRecordOpenapiBodyTypeEnum = "TXT" + ModifyRecordOpenapiBodyTypeEnumNs ModifyRecordOpenapiBodyTypeEnum = "NS" + ModifyRecordOpenapiBodyTypeEnumSpf ModifyRecordOpenapiBodyTypeEnum = "SPF" + ModifyRecordOpenapiBodyTypeEnumSrv ModifyRecordOpenapiBodyTypeEnum = "SRV" + ModifyRecordOpenapiBodyTypeEnumCaa ModifyRecordOpenapiBodyTypeEnum = "CAA" + ModifyRecordOpenapiBodyTypeEnumCmauth ModifyRecordOpenapiBodyTypeEnum = "CMAUTH" ) type ModifyRecordOpenapiBody struct { - position.Body + position.Body // 解析记录ID RecordId string `json:"recordId"` diff --git a/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/modify_record_openapi_request.go b/internal/pkg/sdk3rd/cmcc/ecloudsdkclouddns@v1.0.1/model/modify_record_openapi_request.go similarity index 98% rename from internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/modify_record_openapi_request.go rename to internal/pkg/sdk3rd/cmcc/ecloudsdkclouddns@v1.0.1/model/modify_record_openapi_request.go index fd1ffe00..ee118695 100644 --- a/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/modify_record_openapi_request.go +++ b/internal/pkg/sdk3rd/cmcc/ecloudsdkclouddns@v1.0.1/model/modify_record_openapi_request.go @@ -4,9 +4,6 @@ package model - - type ModifyRecordOpenapiRequest struct { - ModifyRecordOpenapiBody *ModifyRecordOpenapiBody `json:"modifyRecordOpenapiBody,omitempty"` } diff --git a/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/modify_record_openapi_response.go b/internal/pkg/sdk3rd/cmcc/ecloudsdkclouddns@v1.0.1/model/modify_record_openapi_response.go similarity index 57% rename from internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/modify_record_openapi_response.go rename to internal/pkg/sdk3rd/cmcc/ecloudsdkclouddns@v1.0.1/model/modify_record_openapi_response.go index 97d7552f..1c248f9c 100644 --- a/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/modify_record_openapi_response.go +++ b/internal/pkg/sdk3rd/cmcc/ecloudsdkclouddns@v1.0.1/model/modify_record_openapi_response.go @@ -4,19 +4,17 @@ package model - type ModifyRecordOpenapiResponseStateEnum string // List of State const ( - ModifyRecordOpenapiResponseStateEnumError ModifyRecordOpenapiResponseStateEnum = "ERROR" - ModifyRecordOpenapiResponseStateEnumException ModifyRecordOpenapiResponseStateEnum = "EXCEPTION" - ModifyRecordOpenapiResponseStateEnumForbidden ModifyRecordOpenapiResponseStateEnum = "FORBIDDEN" - ModifyRecordOpenapiResponseStateEnumOk ModifyRecordOpenapiResponseStateEnum = "OK" + ModifyRecordOpenapiResponseStateEnumError ModifyRecordOpenapiResponseStateEnum = "ERROR" + ModifyRecordOpenapiResponseStateEnumException ModifyRecordOpenapiResponseStateEnum = "EXCEPTION" + ModifyRecordOpenapiResponseStateEnumForbidden ModifyRecordOpenapiResponseStateEnum = "FORBIDDEN" + ModifyRecordOpenapiResponseStateEnumOk ModifyRecordOpenapiResponseStateEnum = "OK" ) type ModifyRecordOpenapiResponse struct { - RequestId string `json:"requestId,omitempty"` ErrorMessage string `json:"errorMessage,omitempty"` diff --git a/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/modify_record_openapi_response_body.go b/internal/pkg/sdk3rd/cmcc/ecloudsdkclouddns@v1.0.1/model/modify_record_openapi_response_body.go similarity index 56% rename from internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/modify_record_openapi_response_body.go rename to internal/pkg/sdk3rd/cmcc/ecloudsdkclouddns@v1.0.1/model/modify_record_openapi_response_body.go index 6dfcec71..0ba12f70 100644 --- a/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/modify_record_openapi_response_body.go +++ b/internal/pkg/sdk3rd/cmcc/ecloudsdkclouddns@v1.0.1/model/modify_record_openapi_response_body.go @@ -4,40 +4,40 @@ package model - type ModifyRecordOpenapiResponseBodyTypeEnum string // List of Type const ( - ModifyRecordOpenapiResponseBodyTypeEnumA ModifyRecordOpenapiResponseBodyTypeEnum = "A" - ModifyRecordOpenapiResponseBodyTypeEnumAaaa ModifyRecordOpenapiResponseBodyTypeEnum = "AAAA" - ModifyRecordOpenapiResponseBodyTypeEnumCname ModifyRecordOpenapiResponseBodyTypeEnum = "CNAME" - ModifyRecordOpenapiResponseBodyTypeEnumMx ModifyRecordOpenapiResponseBodyTypeEnum = "MX" - ModifyRecordOpenapiResponseBodyTypeEnumTxt ModifyRecordOpenapiResponseBodyTypeEnum = "TXT" - ModifyRecordOpenapiResponseBodyTypeEnumNs ModifyRecordOpenapiResponseBodyTypeEnum = "NS" - ModifyRecordOpenapiResponseBodyTypeEnumSpf ModifyRecordOpenapiResponseBodyTypeEnum = "SPF" - ModifyRecordOpenapiResponseBodyTypeEnumSrv ModifyRecordOpenapiResponseBodyTypeEnum = "SRV" - ModifyRecordOpenapiResponseBodyTypeEnumCaa ModifyRecordOpenapiResponseBodyTypeEnum = "CAA" - ModifyRecordOpenapiResponseBodyTypeEnumCmauth ModifyRecordOpenapiResponseBodyTypeEnum = "CMAUTH" + ModifyRecordOpenapiResponseBodyTypeEnumA ModifyRecordOpenapiResponseBodyTypeEnum = "A" + ModifyRecordOpenapiResponseBodyTypeEnumAaaa ModifyRecordOpenapiResponseBodyTypeEnum = "AAAA" + ModifyRecordOpenapiResponseBodyTypeEnumCname ModifyRecordOpenapiResponseBodyTypeEnum = "CNAME" + ModifyRecordOpenapiResponseBodyTypeEnumMx ModifyRecordOpenapiResponseBodyTypeEnum = "MX" + ModifyRecordOpenapiResponseBodyTypeEnumTxt ModifyRecordOpenapiResponseBodyTypeEnum = "TXT" + ModifyRecordOpenapiResponseBodyTypeEnumNs ModifyRecordOpenapiResponseBodyTypeEnum = "NS" + ModifyRecordOpenapiResponseBodyTypeEnumSpf ModifyRecordOpenapiResponseBodyTypeEnum = "SPF" + ModifyRecordOpenapiResponseBodyTypeEnumSrv ModifyRecordOpenapiResponseBodyTypeEnum = "SRV" + ModifyRecordOpenapiResponseBodyTypeEnumCaa ModifyRecordOpenapiResponseBodyTypeEnum = "CAA" + ModifyRecordOpenapiResponseBodyTypeEnumCmauth ModifyRecordOpenapiResponseBodyTypeEnum = "CMAUTH" ) + type ModifyRecordOpenapiResponseBodyTimedStatusEnum string // List of TimedStatus const ( - ModifyRecordOpenapiResponseBodyTimedStatusEnumDisabled ModifyRecordOpenapiResponseBodyTimedStatusEnum = "DISABLED" - ModifyRecordOpenapiResponseBodyTimedStatusEnumEnabled ModifyRecordOpenapiResponseBodyTimedStatusEnum = "ENABLED" - ModifyRecordOpenapiResponseBodyTimedStatusEnumTimed ModifyRecordOpenapiResponseBodyTimedStatusEnum = "TIMED" + ModifyRecordOpenapiResponseBodyTimedStatusEnumDisabled ModifyRecordOpenapiResponseBodyTimedStatusEnum = "DISABLED" + ModifyRecordOpenapiResponseBodyTimedStatusEnumEnabled ModifyRecordOpenapiResponseBodyTimedStatusEnum = "ENABLED" + ModifyRecordOpenapiResponseBodyTimedStatusEnumTimed ModifyRecordOpenapiResponseBodyTimedStatusEnum = "TIMED" ) + type ModifyRecordOpenapiResponseBodyStateEnum string // List of State const ( - ModifyRecordOpenapiResponseBodyStateEnumDisabled ModifyRecordOpenapiResponseBodyStateEnum = "DISABLED" - ModifyRecordOpenapiResponseBodyStateEnumEnabled ModifyRecordOpenapiResponseBodyStateEnum = "ENABLED" + ModifyRecordOpenapiResponseBodyStateEnumDisabled ModifyRecordOpenapiResponseBodyStateEnum = "DISABLED" + ModifyRecordOpenapiResponseBodyStateEnumEnabled ModifyRecordOpenapiResponseBodyStateEnum = "ENABLED" ) type ModifyRecordOpenapiResponseBody struct { - // 主机头 Rr string `json:"rr,omitempty"` diff --git a/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/modify_record_openapi_response_tags.go b/internal/pkg/sdk3rd/cmcc/ecloudsdkclouddns@v1.0.1/model/modify_record_openapi_response_tags.go similarity index 98% rename from internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/modify_record_openapi_response_tags.go rename to internal/pkg/sdk3rd/cmcc/ecloudsdkclouddns@v1.0.1/model/modify_record_openapi_response_tags.go index 62c2e780..f3e75774 100644 --- a/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/modify_record_openapi_response_tags.go +++ b/internal/pkg/sdk3rd/cmcc/ecloudsdkclouddns@v1.0.1/model/modify_record_openapi_response_tags.go @@ -4,10 +4,7 @@ package model - - type ModifyRecordOpenapiResponseTags struct { - // 标签ID TagId string `json:"tagId,omitempty"` diff --git a/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/modify_record_request.go b/internal/pkg/sdk3rd/cmcc/ecloudsdkclouddns@v1.0.1/model/modify_record_request.go similarity index 98% rename from internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/modify_record_request.go rename to internal/pkg/sdk3rd/cmcc/ecloudsdkclouddns@v1.0.1/model/modify_record_request.go index d92abb44..486f596b 100644 --- a/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/modify_record_request.go +++ b/internal/pkg/sdk3rd/cmcc/ecloudsdkclouddns@v1.0.1/model/modify_record_request.go @@ -4,9 +4,6 @@ package model - - type ModifyRecordRequest struct { - ModifyRecordBody *ModifyRecordBody `json:"modifyRecordBody,omitempty"` } diff --git a/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/modify_record_response.go b/internal/pkg/sdk3rd/cmcc/ecloudsdkclouddns@v1.0.1/model/modify_record_response.go similarity index 59% rename from internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/modify_record_response.go rename to internal/pkg/sdk3rd/cmcc/ecloudsdkclouddns@v1.0.1/model/modify_record_response.go index 45b1ae0f..cec7d420 100644 --- a/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/modify_record_response.go +++ b/internal/pkg/sdk3rd/cmcc/ecloudsdkclouddns@v1.0.1/model/modify_record_response.go @@ -4,19 +4,17 @@ package model - type ModifyRecordResponseStateEnum string // List of State const ( - ModifyRecordResponseStateEnumError ModifyRecordResponseStateEnum = "ERROR" - ModifyRecordResponseStateEnumException ModifyRecordResponseStateEnum = "EXCEPTION" - ModifyRecordResponseStateEnumForbidden ModifyRecordResponseStateEnum = "FORBIDDEN" - ModifyRecordResponseStateEnumOk ModifyRecordResponseStateEnum = "OK" + ModifyRecordResponseStateEnumError ModifyRecordResponseStateEnum = "ERROR" + ModifyRecordResponseStateEnumException ModifyRecordResponseStateEnum = "EXCEPTION" + ModifyRecordResponseStateEnumForbidden ModifyRecordResponseStateEnum = "FORBIDDEN" + ModifyRecordResponseStateEnumOk ModifyRecordResponseStateEnum = "OK" ) type ModifyRecordResponse struct { - RequestId string `json:"requestId,omitempty"` ErrorMessage string `json:"errorMessage,omitempty"` diff --git a/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/modify_record_response_body.go b/internal/pkg/sdk3rd/cmcc/ecloudsdkclouddns@v1.0.1/model/modify_record_response_body.go similarity index 52% rename from internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/modify_record_response_body.go rename to internal/pkg/sdk3rd/cmcc/ecloudsdkclouddns@v1.0.1/model/modify_record_response_body.go index 3df09342..eb373895 100644 --- a/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/modify_record_response_body.go +++ b/internal/pkg/sdk3rd/cmcc/ecloudsdkclouddns@v1.0.1/model/modify_record_response_body.go @@ -4,35 +4,34 @@ package model - type ModifyRecordResponseBodyTypeEnum string // List of Type const ( - ModifyRecordResponseBodyTypeEnumA ModifyRecordResponseBodyTypeEnum = "A" - ModifyRecordResponseBodyTypeEnumAaaa ModifyRecordResponseBodyTypeEnum = "AAAA" - ModifyRecordResponseBodyTypeEnumCaa ModifyRecordResponseBodyTypeEnum = "CAA" - ModifyRecordResponseBodyTypeEnumCmauth ModifyRecordResponseBodyTypeEnum = "CMAUTH" - ModifyRecordResponseBodyTypeEnumCname ModifyRecordResponseBodyTypeEnum = "CNAME" - ModifyRecordResponseBodyTypeEnumMx ModifyRecordResponseBodyTypeEnum = "MX" - ModifyRecordResponseBodyTypeEnumNs ModifyRecordResponseBodyTypeEnum = "NS" - ModifyRecordResponseBodyTypeEnumPtr ModifyRecordResponseBodyTypeEnum = "PTR" - ModifyRecordResponseBodyTypeEnumRp ModifyRecordResponseBodyTypeEnum = "RP" - ModifyRecordResponseBodyTypeEnumSpf ModifyRecordResponseBodyTypeEnum = "SPF" - ModifyRecordResponseBodyTypeEnumSrv ModifyRecordResponseBodyTypeEnum = "SRV" - ModifyRecordResponseBodyTypeEnumTxt ModifyRecordResponseBodyTypeEnum = "TXT" - ModifyRecordResponseBodyTypeEnumUrl ModifyRecordResponseBodyTypeEnum = "URL" + ModifyRecordResponseBodyTypeEnumA ModifyRecordResponseBodyTypeEnum = "A" + ModifyRecordResponseBodyTypeEnumAaaa ModifyRecordResponseBodyTypeEnum = "AAAA" + ModifyRecordResponseBodyTypeEnumCaa ModifyRecordResponseBodyTypeEnum = "CAA" + ModifyRecordResponseBodyTypeEnumCmauth ModifyRecordResponseBodyTypeEnum = "CMAUTH" + ModifyRecordResponseBodyTypeEnumCname ModifyRecordResponseBodyTypeEnum = "CNAME" + ModifyRecordResponseBodyTypeEnumMx ModifyRecordResponseBodyTypeEnum = "MX" + ModifyRecordResponseBodyTypeEnumNs ModifyRecordResponseBodyTypeEnum = "NS" + ModifyRecordResponseBodyTypeEnumPtr ModifyRecordResponseBodyTypeEnum = "PTR" + ModifyRecordResponseBodyTypeEnumRp ModifyRecordResponseBodyTypeEnum = "RP" + ModifyRecordResponseBodyTypeEnumSpf ModifyRecordResponseBodyTypeEnum = "SPF" + ModifyRecordResponseBodyTypeEnumSrv ModifyRecordResponseBodyTypeEnum = "SRV" + ModifyRecordResponseBodyTypeEnumTxt ModifyRecordResponseBodyTypeEnum = "TXT" + ModifyRecordResponseBodyTypeEnumUrl ModifyRecordResponseBodyTypeEnum = "URL" ) + type ModifyRecordResponseBodyStateEnum string // List of State const ( - ModifyRecordResponseBodyStateEnumDisabled ModifyRecordResponseBodyStateEnum = "DISABLED" - ModifyRecordResponseBodyStateEnumEnabled ModifyRecordResponseBodyStateEnum = "ENABLED" + ModifyRecordResponseBodyStateEnumDisabled ModifyRecordResponseBodyStateEnum = "DISABLED" + ModifyRecordResponseBodyStateEnumEnabled ModifyRecordResponseBodyStateEnum = "ENABLED" ) type ModifyRecordResponseBody struct { - // 主机头 Rr string `json:"rr,omitempty"` diff --git a/internal/pkg/vendors/cmcc-sdk/ecloudsdkcore@v1.0.0/api_client.go b/internal/pkg/sdk3rd/cmcc/ecloudsdkcore@v1.0.0/api_client.go similarity index 98% rename from internal/pkg/vendors/cmcc-sdk/ecloudsdkcore@v1.0.0/api_client.go rename to internal/pkg/sdk3rd/cmcc/ecloudsdkcore@v1.0.0/api_client.go index 8f73b499..af08cfd1 100644 --- a/internal/pkg/vendors/cmcc-sdk/ecloudsdkcore@v1.0.0/api_client.go +++ b/internal/pkg/sdk3rd/cmcc/ecloudsdkcore@v1.0.0/api_client.go @@ -6,7 +6,6 @@ import ( "encoding/xml" "errors" "fmt" - "gitlab.ecloud.com/ecloud/ecloudsdkcore/config" "io" "io/ioutil" "mime/multipart" @@ -20,6 +19,8 @@ import ( "strings" "time" "unicode/utf8" + + "gitlab.ecloud.com/ecloud/ecloudsdkcore/config" ) var ( @@ -47,8 +48,10 @@ const ( HEADER HttpRequestPosition = "Header" ) -const SdkPortalUrl = "/op-apim-portal/apim/request/sdk" -const SdkPortalGatewayUrl = "/api/query/openapi/apim/request/sdk" +const ( + SdkPortalUrl = "/op-apim-portal/apim/request/sdk" + SdkPortalGatewayUrl = "/api/query/openapi/apim/request/sdk" +) // NewAPIClient creates a new API client. func NewAPIClient() *APIClient { @@ -199,7 +202,7 @@ func buildHttpRequest(httpRequest *HttpRequest, config *config.Config) *HttpRequ if v.Kind() == reflect.Ptr { v = v.Elem() } - var flag = false + flag := false for i := 0; i < reqType.NumField(); i++ { fieldType := reqType.Field(i) value := v.FieldByName(fieldType.Name) @@ -270,7 +273,7 @@ func structToMap(value interface{}) map[string]interface{} { } func buildCall(httpRequest *HttpRequest) (request *http.Request) { - var url = "" + url := "" if len(httpRequest.Url) > 0 { url = httpRequest.Url + SdkPortalUrl } else { @@ -284,12 +287,11 @@ func buildCall(httpRequest *HttpRequest) (request *http.Request) { func prepareRequest(path string, method string, postBody interface{}, ) (httpRequest *http.Request, err error) { - var body *bytes.Buffer // Detect postBody type and post. if postBody != nil { - var contentType = detectContentType(postBody) + contentType := detectContentType(postBody) body, err = setBody(postBody, contentType) if err != nil { return nil, err diff --git a/internal/pkg/vendors/cmcc-sdk/ecloudsdkcore@v1.0.0/api_response.go b/internal/pkg/sdk3rd/cmcc/ecloudsdkcore@v1.0.0/api_response.go similarity index 99% rename from internal/pkg/vendors/cmcc-sdk/ecloudsdkcore@v1.0.0/api_response.go rename to internal/pkg/sdk3rd/cmcc/ecloudsdkcore@v1.0.0/api_response.go index 89110877..eef07f5c 100644 --- a/internal/pkg/vendors/cmcc-sdk/ecloudsdkcore@v1.0.0/api_response.go +++ b/internal/pkg/sdk3rd/cmcc/ecloudsdkcore@v1.0.0/api_response.go @@ -52,13 +52,11 @@ type APIPlatformResponseBody struct { } func NewAPIResponse(r *http.Response) *APIResponse { - response := &APIResponse{Response: r} return response } func NewAPIResponseWithError(errorMessage string) *APIResponse { - response := &APIResponse{Message: errorMessage} return response } diff --git a/internal/pkg/vendors/cmcc-sdk/ecloudsdkcore@v1.0.0/config/config.go b/internal/pkg/sdk3rd/cmcc/ecloudsdkcore@v1.0.0/config/config.go similarity index 100% rename from internal/pkg/vendors/cmcc-sdk/ecloudsdkcore@v1.0.0/config/config.go rename to internal/pkg/sdk3rd/cmcc/ecloudsdkcore@v1.0.0/config/config.go diff --git a/internal/pkg/vendors/cmcc-sdk/ecloudsdkcore@v1.0.0/configuration.go b/internal/pkg/sdk3rd/cmcc/ecloudsdkcore@v1.0.0/configuration.go similarity index 100% rename from internal/pkg/vendors/cmcc-sdk/ecloudsdkcore@v1.0.0/configuration.go rename to internal/pkg/sdk3rd/cmcc/ecloudsdkcore@v1.0.0/configuration.go diff --git a/internal/pkg/vendors/cmcc-sdk/ecloudsdkcore@v1.0.0/go.mod b/internal/pkg/sdk3rd/cmcc/ecloudsdkcore@v1.0.0/go.mod similarity index 100% rename from internal/pkg/vendors/cmcc-sdk/ecloudsdkcore@v1.0.0/go.mod rename to internal/pkg/sdk3rd/cmcc/ecloudsdkcore@v1.0.0/go.mod diff --git a/internal/pkg/vendors/cmcc-sdk/ecloudsdkcore@v1.0.0/http_request.go b/internal/pkg/sdk3rd/cmcc/ecloudsdkcore@v1.0.0/http_request.go similarity index 100% rename from internal/pkg/vendors/cmcc-sdk/ecloudsdkcore@v1.0.0/http_request.go rename to internal/pkg/sdk3rd/cmcc/ecloudsdkcore@v1.0.0/http_request.go diff --git a/internal/pkg/vendors/cmcc-sdk/ecloudsdkcore@v1.0.0/open_api_request.go b/internal/pkg/sdk3rd/cmcc/ecloudsdkcore@v1.0.0/open_api_request.go similarity index 100% rename from internal/pkg/vendors/cmcc-sdk/ecloudsdkcore@v1.0.0/open_api_request.go rename to internal/pkg/sdk3rd/cmcc/ecloudsdkcore@v1.0.0/open_api_request.go diff --git a/internal/pkg/sdk3rd/cmcc/ecloudsdkcore@v1.0.0/position/http_position.go b/internal/pkg/sdk3rd/cmcc/ecloudsdkcore@v1.0.0/position/http_position.go new file mode 100644 index 00000000..041b8e85 --- /dev/null +++ b/internal/pkg/sdk3rd/cmcc/ecloudsdkcore@v1.0.0/position/http_position.go @@ -0,0 +1,9 @@ +package position + +type Body struct{} + +type Query struct{} + +type Path struct{} + +type Header struct{} diff --git a/internal/pkg/vendors/dnsla-sdk/api.go b/internal/pkg/sdk3rd/dnsla/api.go similarity index 92% rename from internal/pkg/vendors/dnsla-sdk/api.go rename to internal/pkg/sdk3rd/dnsla/api.go index dae745c4..4b53a2ee 100644 --- a/internal/pkg/vendors/dnsla-sdk/api.go +++ b/internal/pkg/sdk3rd/dnsla/api.go @@ -31,6 +31,10 @@ func (c *Client) UpdateRecord(req *UpdateRecordRequest) (*UpdateRecordResponse, } func (c *Client) DeleteRecord(req *DeleteRecordRequest) (*DeleteRecordResponse, error) { + if req.Id == "" { + return nil, fmt.Errorf("dnsla api error: invalid parameter: Id") + } + resp := &DeleteRecordResponse{} err := c.sendRequestWithResult(http.MethodDelete, fmt.Sprintf("/record?id=%s", url.QueryEscape(req.Id)), req, resp) return resp, err diff --git a/internal/pkg/vendors/dnsla-sdk/client.go b/internal/pkg/sdk3rd/dnsla/client.go similarity index 100% rename from internal/pkg/vendors/dnsla-sdk/client.go rename to internal/pkg/sdk3rd/dnsla/client.go diff --git a/internal/pkg/vendors/dnsla-sdk/models.go b/internal/pkg/sdk3rd/dnsla/models.go similarity index 100% rename from internal/pkg/vendors/dnsla-sdk/models.go rename to internal/pkg/sdk3rd/dnsla/models.go diff --git a/internal/pkg/vendors/dogecloud-sdk/client.go b/internal/pkg/sdk3rd/dogecloud/client.go similarity index 99% rename from internal/pkg/vendors/dogecloud-sdk/client.go rename to internal/pkg/sdk3rd/dogecloud/client.go index dcca0b1d..965580c2 100644 --- a/internal/pkg/vendors/dogecloud-sdk/client.go +++ b/internal/pkg/sdk3rd/dogecloud/client.go @@ -1,4 +1,4 @@ -package dogecloudsdk +package dogecloudsdk import ( "crypto/hmac" diff --git a/internal/pkg/vendors/dogecloud-sdk/models.go b/internal/pkg/sdk3rd/dogecloud/models.go similarity index 96% rename from internal/pkg/vendors/dogecloud-sdk/models.go rename to internal/pkg/sdk3rd/dogecloud/models.go index 06507e0d..1642ad2d 100644 --- a/internal/pkg/vendors/dogecloud-sdk/models.go +++ b/internal/pkg/sdk3rd/dogecloud/models.go @@ -1,4 +1,4 @@ -package dogecloudsdk +package dogecloudsdk type BaseResponse struct { Code *int `json:"code,omitempty"` diff --git a/internal/pkg/vendors/edgio-sdk/README.md b/internal/pkg/sdk3rd/edgio/README.md similarity index 100% rename from internal/pkg/vendors/edgio-sdk/README.md rename to internal/pkg/sdk3rd/edgio/README.md diff --git a/internal/pkg/vendors/edgio-sdk/edgio-api@v0.0.0-workspace/applications/v7/dtos/cdn_configuration.go b/internal/pkg/sdk3rd/edgio/edgio-api@v0.0.0-workspace/applications/v7/dtos/cdn_configuration.go similarity index 100% rename from internal/pkg/vendors/edgio-sdk/edgio-api@v0.0.0-workspace/applications/v7/dtos/cdn_configuration.go rename to internal/pkg/sdk3rd/edgio/edgio-api@v0.0.0-workspace/applications/v7/dtos/cdn_configuration.go diff --git a/internal/pkg/vendors/edgio-sdk/edgio-api@v0.0.0-workspace/applications/v7/dtos/environment.go b/internal/pkg/sdk3rd/edgio/edgio-api@v0.0.0-workspace/applications/v7/dtos/environment.go similarity index 100% rename from internal/pkg/vendors/edgio-sdk/edgio-api@v0.0.0-workspace/applications/v7/dtos/environment.go rename to internal/pkg/sdk3rd/edgio/edgio-api@v0.0.0-workspace/applications/v7/dtos/environment.go diff --git a/internal/pkg/vendors/edgio-sdk/edgio-api@v0.0.0-workspace/applications/v7/dtos/property.go b/internal/pkg/sdk3rd/edgio/edgio-api@v0.0.0-workspace/applications/v7/dtos/property.go similarity index 100% rename from internal/pkg/vendors/edgio-sdk/edgio-api@v0.0.0-workspace/applications/v7/dtos/property.go rename to internal/pkg/sdk3rd/edgio/edgio-api@v0.0.0-workspace/applications/v7/dtos/property.go diff --git a/internal/pkg/vendors/edgio-sdk/edgio-api@v0.0.0-workspace/applications/v7/dtos/purge.go b/internal/pkg/sdk3rd/edgio/edgio-api@v0.0.0-workspace/applications/v7/dtos/purge.go similarity index 100% rename from internal/pkg/vendors/edgio-sdk/edgio-api@v0.0.0-workspace/applications/v7/dtos/purge.go rename to internal/pkg/sdk3rd/edgio/edgio-api@v0.0.0-workspace/applications/v7/dtos/purge.go diff --git a/internal/pkg/vendors/edgio-sdk/edgio-api@v0.0.0-workspace/applications/v7/dtos/tls_cert.go b/internal/pkg/sdk3rd/edgio/edgio-api@v0.0.0-workspace/applications/v7/dtos/tls_cert.go similarity index 100% rename from internal/pkg/vendors/edgio-sdk/edgio-api@v0.0.0-workspace/applications/v7/dtos/tls_cert.go rename to internal/pkg/sdk3rd/edgio/edgio-api@v0.0.0-workspace/applications/v7/dtos/tls_cert.go diff --git a/internal/pkg/vendors/edgio-sdk/edgio-api@v0.0.0-workspace/applications/v7/edgio_client.go b/internal/pkg/sdk3rd/edgio/edgio-api@v0.0.0-workspace/applications/v7/edgio_client.go similarity index 100% rename from internal/pkg/vendors/edgio-sdk/edgio-api@v0.0.0-workspace/applications/v7/edgio_client.go rename to internal/pkg/sdk3rd/edgio/edgio-api@v0.0.0-workspace/applications/v7/edgio_client.go diff --git a/internal/pkg/vendors/edgio-sdk/edgio-api@v0.0.0-workspace/applications/v7/edgio_client_interface.go b/internal/pkg/sdk3rd/edgio/edgio-api@v0.0.0-workspace/applications/v7/edgio_client_interface.go similarity index 100% rename from internal/pkg/vendors/edgio-sdk/edgio-api@v0.0.0-workspace/applications/v7/edgio_client_interface.go rename to internal/pkg/sdk3rd/edgio/edgio-api@v0.0.0-workspace/applications/v7/edgio_client_interface.go diff --git a/internal/pkg/vendors/edgio-sdk/edgio-api@v0.0.0-workspace/go.mod b/internal/pkg/sdk3rd/edgio/edgio-api@v0.0.0-workspace/go.mod similarity index 100% rename from internal/pkg/vendors/edgio-sdk/edgio-api@v0.0.0-workspace/go.mod rename to internal/pkg/sdk3rd/edgio/edgio-api@v0.0.0-workspace/go.mod diff --git a/internal/pkg/vendors/gcore-sdk/common/endpoint.go b/internal/pkg/sdk3rd/gcore/common/endpoint.go similarity index 70% rename from internal/pkg/vendors/gcore-sdk/common/endpoint.go rename to internal/pkg/sdk3rd/gcore/common/endpoint.go index d4032da3..5e027951 100644 --- a/internal/pkg/vendors/gcore-sdk/common/endpoint.go +++ b/internal/pkg/sdk3rd/gcore/common/endpoint.go @@ -1,3 +1,3 @@ -package common +package common const BASE_URL = "https://api.gcore.com" diff --git a/internal/pkg/vendors/gcore-sdk/common/signer.go b/internal/pkg/sdk3rd/gcore/common/signer.go similarity index 95% rename from internal/pkg/vendors/gcore-sdk/common/signer.go rename to internal/pkg/sdk3rd/gcore/common/signer.go index bc66ee09..b0aff7e6 100644 --- a/internal/pkg/vendors/gcore-sdk/common/signer.go +++ b/internal/pkg/sdk3rd/gcore/common/signer.go @@ -1,4 +1,4 @@ -package common +package common import ( "net/http" diff --git a/internal/pkg/vendors/gname-sdk/api.go b/internal/pkg/sdk3rd/gname/api.go similarity index 100% rename from internal/pkg/vendors/gname-sdk/api.go rename to internal/pkg/sdk3rd/gname/api.go diff --git a/internal/pkg/vendors/gname-sdk/client.go b/internal/pkg/sdk3rd/gname/client.go similarity index 100% rename from internal/pkg/vendors/gname-sdk/client.go rename to internal/pkg/sdk3rd/gname/client.go diff --git a/internal/pkg/vendors/gname-sdk/models.go b/internal/pkg/sdk3rd/gname/models.go similarity index 100% rename from internal/pkg/vendors/gname-sdk/models.go rename to internal/pkg/sdk3rd/gname/models.go diff --git a/internal/pkg/sdk3rd/goedge/api.go b/internal/pkg/sdk3rd/goedge/api.go new file mode 100644 index 00000000..67ee9194 --- /dev/null +++ b/internal/pkg/sdk3rd/goedge/api.go @@ -0,0 +1,46 @@ +package goedge + +import ( + "encoding/json" + "fmt" + "net/http" + "time" +) + +func (c *Client) getAccessToken() error { + req := &getAPIAccessTokenRequest{ + Type: c.apiUserType, + AccessKeyId: c.accessKeyId, + AccessKey: c.accessKey, + } + res, err := c.sendRequest(http.MethodPost, "/APIAccessTokenService/getAPIAccessToken", req) + if err != nil { + return err + } + + resp := &getAPIAccessTokenResponse{} + if err := json.Unmarshal(res.Body(), &resp); err != nil { + return fmt.Errorf("goedge api error: failed to parse response: %w", err) + } else if resp.GetCode() != 200 { + return fmt.Errorf("goedge get access token failed: code: %d, message: %s", resp.GetCode(), resp.GetMessage()) + } + + c.accessTokenMtx.Lock() + c.accessToken = resp.Data.Token + c.accessTokenExp = time.Unix(resp.Data.ExpiresAt, 0) + c.accessTokenMtx.Unlock() + + return nil +} + +func (c *Client) UpdateSSLCert(req *UpdateSSLCertRequest) (*UpdateSSLCertResponse, error) { + if c.accessToken == "" || c.accessTokenExp.Before(time.Now()) { + if err := c.getAccessToken(); err != nil { + return nil, err + } + } + + resp := &UpdateSSLCertResponse{} + err := c.sendRequestWithResult(http.MethodPost, "/SSLCertService/updateSSLCert", req, resp) + return resp, err +} diff --git a/internal/pkg/sdk3rd/goedge/client.go b/internal/pkg/sdk3rd/goedge/client.go new file mode 100644 index 00000000..96291fb3 --- /dev/null +++ b/internal/pkg/sdk3rd/goedge/client.go @@ -0,0 +1,103 @@ +package goedge + +import ( + "crypto/tls" + "encoding/json" + "fmt" + "net/http" + "strings" + "sync" + "time" + + "github.com/go-resty/resty/v2" +) + +type Client struct { + apiHost string + apiUserType string + accessKeyId string + accessKey string + + accessToken string + accessTokenExp time.Time + accessTokenMtx sync.Mutex + + client *resty.Client +} + +func NewClient(apiHost, apiUserType, accessKeyId, accessKey string) *Client { + client := resty.New() + + return &Client{ + apiHost: strings.TrimRight(apiHost, "/"), + apiUserType: apiUserType, + accessKeyId: accessKeyId, + accessKey: accessKey, + client: client, + } +} + +func (c *Client) WithTimeout(timeout time.Duration) *Client { + c.client.SetTimeout(timeout) + return c +} + +func (c *Client) WithTLSConfig(config *tls.Config) *Client { + c.client.SetTLSClientConfig(config) + return c +} + +func (c *Client) sendRequest(method string, path string, params interface{}) (*resty.Response, error) { + req := c.client.R().SetBasicAuth(c.accessKeyId, c.accessKey) + req.Method = method + req.URL = c.apiHost + path + if strings.EqualFold(method, http.MethodGet) { + qs := make(map[string]string) + if params != nil { + temp := make(map[string]any) + jsonb, _ := json.Marshal(params) + json.Unmarshal(jsonb, &temp) + for k, v := range temp { + if v != nil { + qs[k] = fmt.Sprintf("%v", v) + } + } + } + + req = req. + SetQueryParams(qs). + SetHeader("X-Edge-Access-Token", c.accessToken) + } else { + req = req. + SetHeader("Content-Type", "application/json"). + SetHeader("X-Edge-Access-Token", c.accessToken). + SetBody(params) + } + + resp, err := req.Send() + if err != nil { + return resp, fmt.Errorf("goedge api error: failed to send request: %w", err) + } else if resp.IsError() { + return resp, fmt.Errorf("goedge api error: unexpected status code: %d, resp: %s", resp.StatusCode(), resp.Body()) + } + + return resp, nil +} + +func (c *Client) sendRequestWithResult(method string, path string, params interface{}, result BaseResponse) error { + resp, err := c.sendRequest(method, path, params) + if err != nil { + if resp != nil { + json.Unmarshal(resp.Body(), &result) + } + return err + } + + if err := json.Unmarshal(resp.Body(), &result); err != nil { + return fmt.Errorf("goedge api error: failed to parse response: %w", err) + } else if errcode := result.GetCode(); errcode != 200 { + return fmt.Errorf("goedge api error: %d - %s", errcode, result.GetMessage()) + } + + return nil +} diff --git a/internal/pkg/sdk3rd/goedge/models.go b/internal/pkg/sdk3rd/goedge/models.go new file mode 100644 index 00000000..d19bb558 --- /dev/null +++ b/internal/pkg/sdk3rd/goedge/models.go @@ -0,0 +1,52 @@ +package goedge + +type BaseResponse interface { + GetCode() int32 + GetMessage() string +} + +type baseResponse struct { + Code int32 `json:"code"` + Message string `json:"message"` +} + +func (r *baseResponse) GetCode() int32 { + return r.Code +} + +func (r *baseResponse) GetMessage() string { + return r.Message +} + +type getAPIAccessTokenRequest struct { + Type string `json:"type"` + AccessKeyId string `json:"accessKeyId"` + AccessKey string `json:"accessKey"` +} + +type getAPIAccessTokenResponse struct { + baseResponse + Data *struct { + Token string `json:"token"` + ExpiresAt int64 `json:"expiresAt"` + } `json:"data,omitempty"` +} + +type UpdateSSLCertRequest struct { + SSLCertId int64 `json:"sslCertId"` + IsOn bool `json:"isOn"` + Name string `json:"name"` + Description string `json:"description"` + ServerName string `json:"serverName"` + IsCA bool `json:"isCA"` + CertData string `json:"certData"` + KeyData string `json:"keyData"` + TimeBeginAt int64 `json:"timeBeginAt"` + TimeEndAt int64 `json:"timeEndAt"` + DNSNames []string `json:"dnsNames"` + CommonNames []string `json:"commonNames"` +} + +type UpdateSSLCertResponse struct { + baseResponse +} diff --git a/internal/pkg/vendors/qiniu-sdk/auth.go b/internal/pkg/sdk3rd/qiniu/auth.go similarity index 100% rename from internal/pkg/vendors/qiniu-sdk/auth.go rename to internal/pkg/sdk3rd/qiniu/auth.go diff --git a/internal/pkg/vendors/qiniu-sdk/client.go b/internal/pkg/sdk3rd/qiniu/client.go similarity index 99% rename from internal/pkg/vendors/qiniu-sdk/client.go rename to internal/pkg/sdk3rd/qiniu/client.go index 8f9d10e9..ece26b9a 100644 --- a/internal/pkg/vendors/qiniu-sdk/client.go +++ b/internal/pkg/sdk3rd/qiniu/client.go @@ -1,4 +1,4 @@ -package qiniusdk +package qiniusdk import ( "context" diff --git a/internal/pkg/vendors/qiniu-sdk/models.go b/internal/pkg/sdk3rd/qiniu/models.go similarity index 98% rename from internal/pkg/vendors/qiniu-sdk/models.go rename to internal/pkg/sdk3rd/qiniu/models.go index dceca028..1f643c35 100644 --- a/internal/pkg/vendors/qiniu-sdk/models.go +++ b/internal/pkg/sdk3rd/qiniu/models.go @@ -1,4 +1,4 @@ -package qiniusdk +package qiniusdk type BaseResponse struct { Code *int `json:"code,omitempty"` diff --git a/internal/pkg/vendors/rainyun-sdk/api.go b/internal/pkg/sdk3rd/rainyun/api.go similarity index 85% rename from internal/pkg/vendors/rainyun-sdk/api.go rename to internal/pkg/sdk3rd/rainyun/api.go index 50f3279d..d4a9135e 100644 --- a/internal/pkg/vendors/rainyun-sdk/api.go +++ b/internal/pkg/sdk3rd/rainyun/api.go @@ -12,6 +12,10 @@ func (c *Client) SslCenterList(req *SslCenterListRequest) (*SslCenterListRespons } func (c *Client) SslCenterGet(id int32) (*SslCenterGetResponse, error) { + if id == 0 { + return nil, fmt.Errorf("rainyun api error: invalid parameter: id") + } + resp := &SslCenterGetResponse{} err := c.sendRequestWithResult(http.MethodGet, fmt.Sprintf("/product/sslcenter/%d", id), nil, resp) return resp, err @@ -24,6 +28,10 @@ func (c *Client) SslCenterCreate(req *SslCenterCreateRequest) (*SslCenterCreateR } func (c *Client) RcdnInstanceSslBind(id int32, req *RcdnInstanceSslBindRequest) (*RcdnInstanceSslBindResponse, error) { + if id == 0 { + return nil, fmt.Errorf("rainyun api error: invalid parameter: id") + } + resp := &RcdnInstanceSslBindResponse{} err := c.sendRequestWithResult(http.MethodPost, fmt.Sprintf("/product/rcdn/instance/%d/ssl_bind", id), req, resp) return resp, err diff --git a/internal/pkg/vendors/rainyun-sdk/client.go b/internal/pkg/sdk3rd/rainyun/client.go similarity index 100% rename from internal/pkg/vendors/rainyun-sdk/client.go rename to internal/pkg/sdk3rd/rainyun/client.go diff --git a/internal/pkg/vendors/rainyun-sdk/models.go b/internal/pkg/sdk3rd/rainyun/models.go similarity index 100% rename from internal/pkg/vendors/rainyun-sdk/models.go rename to internal/pkg/sdk3rd/rainyun/models.go diff --git a/internal/pkg/vendors/safeline-sdk/api.go b/internal/pkg/sdk3rd/safeline/api.go similarity index 100% rename from internal/pkg/vendors/safeline-sdk/api.go rename to internal/pkg/sdk3rd/safeline/api.go diff --git a/internal/pkg/vendors/safeline-sdk/client.go b/internal/pkg/sdk3rd/safeline/client.go similarity index 100% rename from internal/pkg/vendors/safeline-sdk/client.go rename to internal/pkg/sdk3rd/safeline/client.go diff --git a/internal/pkg/vendors/safeline-sdk/models.go b/internal/pkg/sdk3rd/safeline/models.go similarity index 100% rename from internal/pkg/vendors/safeline-sdk/models.go rename to internal/pkg/sdk3rd/safeline/models.go diff --git a/internal/pkg/vendors/ucloud-sdk/ufile/apis.go b/internal/pkg/sdk3rd/ucloud/ufile/apis.go similarity index 98% rename from internal/pkg/vendors/ucloud-sdk/ufile/apis.go rename to internal/pkg/sdk3rd/ucloud/ufile/apis.go index 009405fa..350b23a2 100644 --- a/internal/pkg/vendors/ucloud-sdk/ufile/apis.go +++ b/internal/pkg/sdk3rd/ucloud/ufile/apis.go @@ -1,4 +1,4 @@ -package ufile +package ufile import ( "github.com/ucloud/ucloud-sdk-go/ucloud/request" diff --git a/internal/pkg/vendors/ucloud-sdk/ufile/client.go b/internal/pkg/sdk3rd/ucloud/ufile/client.go similarity index 95% rename from internal/pkg/vendors/ucloud-sdk/ufile/client.go rename to internal/pkg/sdk3rd/ucloud/ufile/client.go index ab1f4d2e..aee06624 100644 --- a/internal/pkg/vendors/ucloud-sdk/ufile/client.go +++ b/internal/pkg/sdk3rd/ucloud/ufile/client.go @@ -1,4 +1,4 @@ -package ufile +package ufile import ( "github.com/ucloud/ucloud-sdk-go/ucloud" diff --git a/internal/pkg/vendors/ucloud-sdk/ussl/apis.go b/internal/pkg/sdk3rd/ucloud/ussl/apis.go similarity index 99% rename from internal/pkg/vendors/ucloud-sdk/ussl/apis.go rename to internal/pkg/sdk3rd/ucloud/ussl/apis.go index 5d0c6e32..d9ec7674 100644 --- a/internal/pkg/vendors/ucloud-sdk/ussl/apis.go +++ b/internal/pkg/sdk3rd/ucloud/ussl/apis.go @@ -1,4 +1,4 @@ -package ussl +package ussl import ( "github.com/ucloud/ucloud-sdk-go/ucloud/request" diff --git a/internal/pkg/vendors/ucloud-sdk/ussl/client.go b/internal/pkg/sdk3rd/ucloud/ussl/client.go similarity index 95% rename from internal/pkg/vendors/ucloud-sdk/ussl/client.go rename to internal/pkg/sdk3rd/ucloud/ussl/client.go index 6d92a204..95876543 100644 --- a/internal/pkg/vendors/ucloud-sdk/ussl/client.go +++ b/internal/pkg/sdk3rd/ucloud/ussl/client.go @@ -1,4 +1,4 @@ -package ussl +package ussl import ( "github.com/ucloud/ucloud-sdk-go/ucloud" diff --git a/internal/pkg/vendors/ucloud-sdk/ussl/models.go b/internal/pkg/sdk3rd/ucloud/ussl/models.go similarity index 98% rename from internal/pkg/vendors/ucloud-sdk/ussl/models.go rename to internal/pkg/sdk3rd/ucloud/ussl/models.go index 50343d9f..2826f2cb 100644 --- a/internal/pkg/vendors/ucloud-sdk/ussl/models.go +++ b/internal/pkg/sdk3rd/ucloud/ussl/models.go @@ -1,4 +1,4 @@ -package ussl +package ussl type CertificateListItem struct { CertificateID int diff --git a/internal/pkg/vendors/upyun-sdk/console/api.go b/internal/pkg/sdk3rd/upyun/console/api.go similarity index 100% rename from internal/pkg/vendors/upyun-sdk/console/api.go rename to internal/pkg/sdk3rd/upyun/console/api.go diff --git a/internal/pkg/vendors/upyun-sdk/console/client.go b/internal/pkg/sdk3rd/upyun/console/client.go similarity index 98% rename from internal/pkg/vendors/upyun-sdk/console/client.go rename to internal/pkg/sdk3rd/upyun/console/client.go index cf431c2c..56e7a86e 100644 --- a/internal/pkg/vendors/upyun-sdk/console/client.go +++ b/internal/pkg/sdk3rd/upyun/console/client.go @@ -11,8 +11,9 @@ import ( ) type Client struct { - username string - password string + username string + password string + loginCookie string client *resty.Client diff --git a/internal/pkg/vendors/upyun-sdk/console/models.go b/internal/pkg/sdk3rd/upyun/console/models.go similarity index 100% rename from internal/pkg/vendors/upyun-sdk/console/models.go rename to internal/pkg/sdk3rd/upyun/console/models.go diff --git a/internal/pkg/vendors/volcengine-sdk/certcenter/api_import_certificate.go b/internal/pkg/sdk3rd/volcengine/certcenter/api_import_certificate.go similarity index 99% rename from internal/pkg/vendors/volcengine-sdk/certcenter/api_import_certificate.go rename to internal/pkg/sdk3rd/volcengine/certcenter/api_import_certificate.go index ece842ed..6212508a 100644 --- a/internal/pkg/vendors/volcengine-sdk/certcenter/api_import_certificate.go +++ b/internal/pkg/sdk3rd/volcengine/certcenter/api_import_certificate.go @@ -1,4 +1,4 @@ -package certcenter +package certcenter import ( "github.com/volcengine/volcengine-go-sdk/volcengine" diff --git a/internal/pkg/vendors/volcengine-sdk/certcenter/interface.go b/internal/pkg/sdk3rd/volcengine/certcenter/interface.go similarity index 95% rename from internal/pkg/vendors/volcengine-sdk/certcenter/interface.go rename to internal/pkg/sdk3rd/volcengine/certcenter/interface.go index cebe2b73..75ba3729 100644 --- a/internal/pkg/vendors/volcengine-sdk/certcenter/interface.go +++ b/internal/pkg/sdk3rd/volcengine/certcenter/interface.go @@ -1,4 +1,4 @@ -package certcenter +package certcenter import ( "github.com/volcengine/volcengine-go-sdk/volcengine" diff --git a/internal/pkg/vendors/volcengine-sdk/certcenter/service.go b/internal/pkg/sdk3rd/volcengine/certcenter/service.go similarity index 98% rename from internal/pkg/vendors/volcengine-sdk/certcenter/service.go rename to internal/pkg/sdk3rd/volcengine/certcenter/service.go index 2feb8c28..494e2995 100644 --- a/internal/pkg/vendors/volcengine-sdk/certcenter/service.go +++ b/internal/pkg/sdk3rd/volcengine/certcenter/service.go @@ -1,4 +1,4 @@ -package certcenter +package certcenter import ( "github.com/volcengine/volcengine-go-sdk/volcengine" diff --git a/internal/pkg/vendors/wangsu-sdk/cdn/api.go b/internal/pkg/sdk3rd/wangsu/cdn/api.go similarity index 89% rename from internal/pkg/vendors/wangsu-sdk/cdn/api.go rename to internal/pkg/sdk3rd/wangsu/cdn/api.go index 92a05cfa..0da647c8 100644 --- a/internal/pkg/vendors/wangsu-sdk/cdn/api.go +++ b/internal/pkg/sdk3rd/wangsu/cdn/api.go @@ -1,4 +1,4 @@ -package cdn +package cdn import ( "fmt" @@ -23,7 +23,7 @@ func (c *Client) CreateCertificate(req *CreateCertificateRequest) (*CreateCertif func (c *Client) UpdateCertificate(certificateId string, req *UpdateCertificateRequest) (*UpdateCertificateResponse, error) { if certificateId == "" { - return nil, fmt.Errorf("invalid parameter: certificateId") + return nil, fmt.Errorf("wangsu api error: invalid parameter: certificateId") } resp := &UpdateCertificateResponse{} @@ -40,7 +40,7 @@ func (c *Client) UpdateCertificate(certificateId string, req *UpdateCertificateR func (c *Client) GetHostnameDetail(hostname string) (*GetHostnameDetailResponse, error) { if hostname == "" { - return nil, fmt.Errorf("invalid parameter: hostname") + return nil, fmt.Errorf("wangsu api error: invalid parameter: hostname") } resp := &GetHostnameDetailResponse{} @@ -61,7 +61,7 @@ func (c *Client) CreateDeploymentTask(req *CreateDeploymentTaskRequest) (*Create func (c *Client) GetDeploymentTaskDetail(deploymentTaskId string) (*GetDeploymentTaskDetailResponse, error) { if deploymentTaskId == "" { - return nil, fmt.Errorf("invalid parameter: deploymentTaskId") + return nil, fmt.Errorf("wangsu api error: invalid parameter: deploymentTaskId") } resp := &GetDeploymentTaskDetailResponse{} diff --git a/internal/pkg/vendors/wangsu-sdk/cdn/client.go b/internal/pkg/sdk3rd/wangsu/cdn/client.go similarity index 76% rename from internal/pkg/vendors/wangsu-sdk/cdn/client.go rename to internal/pkg/sdk3rd/wangsu/cdn/client.go index e1831960..ac53e171 100644 --- a/internal/pkg/vendors/wangsu-sdk/cdn/client.go +++ b/internal/pkg/sdk3rd/wangsu/cdn/client.go @@ -1,9 +1,9 @@ -package cdn +package cdn import ( "time" - "github.com/usual2970/certimate/internal/pkg/vendors/wangsu-sdk/openapi" + "github.com/usual2970/certimate/internal/pkg/sdk3rd/wangsu/openapi" ) type Client struct { diff --git a/internal/pkg/vendors/wangsu-sdk/cdn/models.go b/internal/pkg/sdk3rd/wangsu/cdn/models.go similarity index 94% rename from internal/pkg/vendors/wangsu-sdk/cdn/models.go rename to internal/pkg/sdk3rd/wangsu/cdn/models.go index 2bebced2..a9a9ec74 100644 --- a/internal/pkg/vendors/wangsu-sdk/cdn/models.go +++ b/internal/pkg/sdk3rd/wangsu/cdn/models.go @@ -1,7 +1,7 @@ package cdn import ( - "github.com/usual2970/certimate/internal/pkg/vendors/wangsu-sdk/openapi" + "github.com/usual2970/certimate/internal/pkg/sdk3rd/wangsu/openapi" ) type baseResponse struct { @@ -46,7 +46,7 @@ type CreateCertificateRequest struct { type CreateCertificateResponse struct { baseResponse - CertificateUrl string `json:"-"` + CertificateUrl string `json:"location,omitempty"` } type UpdateCertificateRequest struct { @@ -60,7 +60,7 @@ type UpdateCertificateRequest struct { type UpdateCertificateResponse struct { baseResponse - CertificateUrl string `json:"-"` + CertificateUrl string `json:"location,omitempty"` } type HostnameProperty struct { @@ -92,7 +92,7 @@ type CreateDeploymentTaskRequest struct { type CreateDeploymentTaskResponse struct { baseResponse - DeploymentTaskUrl string `json:"-"` + DeploymentTaskUrl string `json:"location,omitempty"` } type GetDeploymentTaskDetailResponse struct { diff --git a/internal/pkg/vendors/wangsu-sdk/openapi/client.go b/internal/pkg/sdk3rd/wangsu/openapi/client.go similarity index 100% rename from internal/pkg/vendors/wangsu-sdk/openapi/client.go rename to internal/pkg/sdk3rd/wangsu/openapi/client.go diff --git a/internal/pkg/utils/certutil/common.go b/internal/pkg/utils/cert/common.go similarity index 97% rename from internal/pkg/utils/certutil/common.go rename to internal/pkg/utils/cert/common.go index 409233b6..08a7cea2 100644 --- a/internal/pkg/utils/certutil/common.go +++ b/internal/pkg/utils/cert/common.go @@ -1,4 +1,4 @@ -package certutil +package certutil import ( "crypto/x509" diff --git a/internal/pkg/utils/certutil/converter.go b/internal/pkg/utils/cert/converter.go similarity index 75% rename from internal/pkg/utils/certutil/converter.go rename to internal/pkg/utils/cert/converter.go index ccbe6360..b726e86d 100644 --- a/internal/pkg/utils/certutil/converter.go +++ b/internal/pkg/utils/cert/converter.go @@ -1,12 +1,11 @@ -package certutil +package certutil import ( "crypto/ecdsa" "crypto/x509" "encoding/pem" "errors" - - xerrors "github.com/pkg/errors" + "fmt" ) // 将 x509.Certificate 对象转换为 PEM 编码的字符串。 @@ -15,9 +14,9 @@ import ( // - cert: x509.Certificate 对象。 // // 出参: -// - certPem: 证书 PEM 内容。 +// - certPEM: 证书 PEM 内容。 // - err: 错误。 -func ConvertCertificateToPEM(cert *x509.Certificate) (certPem string, err error) { +func ConvertCertificateToPEM(cert *x509.Certificate) (certPEM string, err error) { if cert == nil { return "", errors.New("`cert` is nil") } @@ -36,16 +35,16 @@ func ConvertCertificateToPEM(cert *x509.Certificate) (certPem string, err error) // - privkey: ecdsa.PrivateKey 对象。 // // 出参: -// - privkeyPem: 私钥 PEM 内容。 +// - privkeyPEM: 私钥 PEM 内容。 // - err: 错误。 -func ConvertECPrivateKeyToPEM(privkey *ecdsa.PrivateKey) (privkeyPem string, err error) { +func ConvertECPrivateKeyToPEM(privkey *ecdsa.PrivateKey) (privkeyPEM string, err error) { if privkey == nil { return "", errors.New("`privkey` is nil") } data, err := x509.MarshalECPrivateKey(privkey) if err != nil { - return "", xerrors.Wrap(err, "failed to marshal EC private key") + return "", fmt.Errorf("failed to marshal EC private key: %w", err) } block := &pem.Block{ diff --git a/internal/pkg/utils/certutil/extractor.go b/internal/pkg/utils/cert/extractor.go similarity index 53% rename from internal/pkg/utils/certutil/extractor.go rename to internal/pkg/utils/cert/extractor.go index d4e7ee6e..110f4772 100644 --- a/internal/pkg/utils/certutil/extractor.go +++ b/internal/pkg/utils/cert/extractor.go @@ -1,4 +1,4 @@ -package certutil +package certutil import ( "encoding/pem" @@ -8,15 +8,15 @@ import ( // 从 PEM 编码的证书字符串解析并提取服务器证书和中间证书。 // // 入参: -// - certPem: 证书 PEM 内容。 +// - certPEM: 证书 PEM 内容。 // // 出参: -// - serverCertPem: 服务器证书的 PEM 内容。 -// - interCertPem: 中间证书的 PEM 内容。 +// - serverCertPEM: 服务器证书的 PEM 内容。 +// - interCertPEM: 中间证书的 PEM 内容。 // - err: 错误。 -func ExtractCertificatesFromPEM(certPem string) (serverCertPem string, interCertPem string, err error) { +func ExtractCertificatesFromPEM(certPEM string) (serverCertPEM string, interCertPEM string, err error) { pemBlocks := make([]*pem.Block, 0) - pemData := []byte(certPem) + pemData := []byte(certPEM) for { block, rest := pem.Decode(pemData) if block == nil || block.Type != "CERTIFICATE" { @@ -27,22 +27,22 @@ func ExtractCertificatesFromPEM(certPem string) (serverCertPem string, interCert pemData = rest } - serverCertPem = "" - interCertPem = "" + serverCertPEM = "" + interCertPEM = "" if len(pemBlocks) == 0 { return "", "", errors.New("failed to decode PEM block") } if len(pemBlocks) > 0 { - serverCertPem = string(pem.EncodeToMemory(pemBlocks[0])) + serverCertPEM = string(pem.EncodeToMemory(pemBlocks[0])) } if len(pemBlocks) > 1 { for i := 1; i < len(pemBlocks); i++ { - interCertPem += string(pem.EncodeToMemory(pemBlocks[i])) + interCertPEM += string(pem.EncodeToMemory(pemBlocks[i])) } } - return serverCertPem, interCertPem, nil + return serverCertPEM, interCertPEM, nil } diff --git a/internal/pkg/utils/certutil/parser.go b/internal/pkg/utils/cert/parser.go similarity index 69% rename from internal/pkg/utils/certutil/parser.go rename to internal/pkg/utils/cert/parser.go index e93ce583..eb743f78 100644 --- a/internal/pkg/utils/certutil/parser.go +++ b/internal/pkg/utils/cert/parser.go @@ -1,4 +1,4 @@ -package certutil +package certutil import ( "crypto" @@ -7,22 +7,22 @@ import ( "crypto/x509" "encoding/pem" "errors" + "fmt" "github.com/go-acme/lego/v4/certcrypto" - xerrors "github.com/pkg/errors" ) // 从 PEM 编码的证书字符串解析并返回一个 x509.Certificate 对象。 // PEM 内容可能是包含多张证书的证书链,但只返回第一个证书(即服务器证书)。 // // 入参: -// - certPem: 证书 PEM 内容。 +// - certPEM: 证书 PEM 内容。 // // 出参: // - cert: x509.Certificate 对象。 // - err: 错误。 -func ParseCertificateFromPEM(certPem string) (cert *x509.Certificate, err error) { - pemData := []byte(certPem) +func ParseCertificateFromPEM(certPEM string) (cert *x509.Certificate, err error) { + pemData := []byte(certPEM) block, _ := pem.Decode(pemData) if block == nil { @@ -31,7 +31,7 @@ func ParseCertificateFromPEM(certPem string) (cert *x509.Certificate, err error) cert, err = x509.ParseCertificate(block.Bytes) if err != nil { - return nil, xerrors.Wrap(err, "failed to parse certificate") + return nil, fmt.Errorf("failed to parse certificate: %w", err) } return cert, nil @@ -40,26 +40,26 @@ func ParseCertificateFromPEM(certPem string) (cert *x509.Certificate, err error) // 从 PEM 编码的私钥字符串解析并返回一个 crypto.PrivateKey 对象。 // // 入参: -// - privkeyPem: 私钥 PEM 内容。 +// - privkeyPEM: 私钥 PEM 内容。 // // 出参: // - privkey: crypto.PrivateKey 对象,可能是 rsa.PrivateKey、ecdsa.PrivateKey 或 ed25519.PrivateKey。 // - err: 错误。 -func ParsePrivateKeyFromPEM(privkeyPem string) (privkey crypto.PrivateKey, err error) { - pemData := []byte(privkeyPem) +func ParsePrivateKeyFromPEM(privkeyPEM string) (privkey crypto.PrivateKey, err error) { + pemData := []byte(privkeyPEM) return certcrypto.ParsePEMPrivateKey(pemData) } // 从 PEM 编码的私钥字符串解析并返回一个 ecdsa.PrivateKey 对象。 // // 入参: -// - privkeyPem: 私钥 PEM 内容。 +// - privkeyPEM: 私钥 PEM 内容。 // // 出参: // - privkey: ecdsa.PrivateKey 对象。 // - err: 错误。 -func ParseECPrivateKeyFromPEM(privkeyPem string) (privkey *ecdsa.PrivateKey, err error) { - pemData := []byte(privkeyPem) +func ParseECPrivateKeyFromPEM(privkeyPEM string) (privkey *ecdsa.PrivateKey, err error) { + pemData := []byte(privkeyPEM) block, _ := pem.Decode(pemData) if block == nil { @@ -68,7 +68,7 @@ func ParseECPrivateKeyFromPEM(privkeyPem string) (privkey *ecdsa.PrivateKey, err privkey, err = x509.ParseECPrivateKey(block.Bytes) if err != nil { - return nil, xerrors.Wrap(err, "failed to parse private key") + return nil, fmt.Errorf("failed to parse private key: %w", err) } return privkey, nil @@ -77,13 +77,13 @@ func ParseECPrivateKeyFromPEM(privkeyPem string) (privkey *ecdsa.PrivateKey, err // 从 PEM 编码的私钥字符串解析并返回一个 rsa.PrivateKey 对象。 // // 入参: -// - privkeyPem: 私钥 PEM 内容。 +// - privkeyPEM: 私钥 PEM 内容。 // // 出参: // - privkey: rsa.PrivateKey 对象。 // - err: 错误。 -func ParsePKCS1PrivateKeyFromPEM(privkeyPem string) (privkey *rsa.PrivateKey, err error) { - pemData := []byte(privkeyPem) +func ParsePKCS1PrivateKeyFromPEM(privkeyPEM string) (privkey *rsa.PrivateKey, err error) { + pemData := []byte(privkeyPEM) block, _ := pem.Decode(pemData) if block == nil { @@ -92,7 +92,7 @@ func ParsePKCS1PrivateKeyFromPEM(privkeyPem string) (privkey *rsa.PrivateKey, er privkey, err = x509.ParsePKCS1PrivateKey(block.Bytes) if err != nil { - return nil, xerrors.Wrap(err, "failed to parse private key") + return nil, fmt.Errorf("failed to parse private key: %w", err) } return privkey, nil diff --git a/internal/pkg/utils/certutil/transformer.go b/internal/pkg/utils/cert/transformer.go similarity index 76% rename from internal/pkg/utils/certutil/transformer.go rename to internal/pkg/utils/cert/transformer.go index f48641ae..74690013 100644 --- a/internal/pkg/utils/certutil/transformer.go +++ b/internal/pkg/utils/cert/transformer.go @@ -1,4 +1,4 @@ -package certutil +package certutil import ( "bytes" @@ -13,20 +13,20 @@ import ( // 将 PEM 编码的证书字符串转换为 PFX 格式。 // // 入参: -// - certPem: 证书 PEM 内容。 -// - privkeyPem: 私钥 PEM 内容。 +// - certPEM: 证书 PEM 内容。 +// - privkeyPEM: 私钥 PEM 内容。 // - pfxPassword: PFX 导出密码。 // // 出参: // - data: PFX 格式的证书数据。 // - err: 错误。 -func TransformCertificateFromPEMToPFX(certPem string, privkeyPem string, pfxPassword string) ([]byte, error) { - cert, err := ParseCertificateFromPEM(certPem) +func TransformCertificateFromPEMToPFX(certPEM string, privkeyPEM string, pfxPassword string) ([]byte, error) { + cert, err := ParseCertificateFromPEM(certPEM) if err != nil { return nil, err } - privkey, err := ParsePrivateKeyFromPEM(privkeyPem) + privkey, err := ParsePrivateKeyFromPEM(privkeyPEM) if err != nil { return nil, err } @@ -42,8 +42,8 @@ func TransformCertificateFromPEMToPFX(certPem string, privkeyPem string, pfxPass // 将 PEM 编码的证书字符串转换为 JKS 格式。 // // 入参: -// - certPem: 证书 PEM 内容。 -// - privkeyPem: 私钥 PEM 内容。 +// - certPEM: 证书 PEM 内容。 +// - privkeyPEM: 私钥 PEM 内容。 // - jksAlias: JKS 别名。 // - jksKeypass: JKS 密钥密码。 // - jksStorepass: JKS 存储密码。 @@ -51,13 +51,13 @@ func TransformCertificateFromPEMToPFX(certPem string, privkeyPem string, pfxPass // 出参: // - data: JKS 格式的证书数据。 // - err: 错误。 -func TransformCertificateFromPEMToJKS(certPem string, privkeyPem string, jksAlias string, jksKeypass string, jksStorepass string) ([]byte, error) { - certBlock, _ := pem.Decode([]byte(certPem)) +func TransformCertificateFromPEMToJKS(certPEM string, privkeyPEM string, jksAlias string, jksKeypass string, jksStorepass string) ([]byte, error) { + certBlock, _ := pem.Decode([]byte(certPEM)) if certBlock == nil { return nil, errors.New("failed to decode certificate PEM") } - privkeyBlock, _ := pem.Decode([]byte(privkeyPem)) + privkeyBlock, _ := pem.Decode([]byte(privkeyPEM)) if privkeyBlock == nil { return nil, errors.New("failed to decode private key PEM") } diff --git a/internal/pkg/utils/fileutil/io.go b/internal/pkg/utils/file/io.go similarity index 80% rename from internal/pkg/utils/fileutil/io.go rename to internal/pkg/utils/file/io.go index 336f524d..58b5b970 100644 --- a/internal/pkg/utils/fileutil/io.go +++ b/internal/pkg/utils/file/io.go @@ -1,10 +1,9 @@ -package fileutil +package fileutil import ( + "fmt" "os" "path/filepath" - - xerrors "github.com/pkg/errors" ) // 与 [Write] 类似,但写入的是字符串内容。 @@ -34,18 +33,18 @@ func Write(path string, data []byte) error { err := os.MkdirAll(dir, os.ModePerm) if err != nil { - return xerrors.Wrap(err, "failed to create directory") + return fmt.Errorf("failed to create directory: %w", err) } file, err := os.Create(path) if err != nil { - return xerrors.Wrap(err, "failed to create file") + return fmt.Errorf("failed to create file: %w", err) } defer file.Close() _, err = file.Write(data) if err != nil { - return xerrors.Wrap(err, "failed to write file") + return fmt.Errorf("failed to write file: %w", err) } return nil diff --git a/internal/pkg/utils/http/parser.go b/internal/pkg/utils/http/parser.go new file mode 100644 index 00000000..872fb6b5 --- /dev/null +++ b/internal/pkg/utils/http/parser.go @@ -0,0 +1,33 @@ +package httputil + +import ( + "bufio" + "net/http" + "net/textproto" + "strings" +) + +// 从表示 HTTP 标头的字符串解析并返回一个 http.Header 对象。 +// +// 入参: +// - headers: 表示 HTTP 标头的字符串。 +// +// 出参: +// - header: http.Header 对象。 +// - err: 错误。 +func ParseHeaders(headers string) (http.Header, error) { + str := strings.TrimSpace(headers) + "\r\n\r\n" + if len(str) == 4 { + return make(http.Header), nil + } + + br := bufio.NewReader(strings.NewReader(str)) + tp := textproto.NewReader(br) + + mimeHeader, err := tp.ReadMIMEHeader() + if err != nil { + return nil, err + } + + return http.Header(mimeHeader), err +} diff --git a/internal/pkg/utils/maputil/getter.go b/internal/pkg/utils/map/getter.go similarity index 91% rename from internal/pkg/utils/maputil/getter.go rename to internal/pkg/utils/map/getter.go index c1126496..f30f6d33 100644 --- a/internal/pkg/utils/maputil/getter.go +++ b/internal/pkg/utils/map/getter.go @@ -1,4 +1,4 @@ -package maputil +package maputil import ( "strconv" @@ -199,6 +199,28 @@ func GetOrDefaultBool(dict map[string]any, key string, defaultValue bool) bool { return defaultValue } +// 以 `map[string]V` 形式从字典中获取指定键的值。 +// +// 入参: +// - dict: 字典。 +// - key: 键。 +// +// 出参: +// - 字典中键对应的 `map[string]V` 对象。 +func GetKVMap[V any](dict map[string]any, key string) map[string]V { + if dict == nil { + return make(map[string]V) + } + + if val, ok := dict[key]; ok { + if result, ok := val.(map[string]V); ok { + return result + } + } + + return make(map[string]V) +} + // 以 `map[string]any` 形式从字典中获取指定键的值。 // // 入参: @@ -207,16 +229,6 @@ func GetOrDefaultBool(dict map[string]any, key string, defaultValue bool) bool { // // 出参: // - 字典中键对应的 `map[string]any` 对象。 -func GetAnyMap(dict map[string]any, key string) map[string]any { - if dict == nil { - return make(map[string]any) - } - - if val, ok := dict[key]; ok { - if result, ok := val.(map[string]any); ok { - return result - } - } - - return make(map[string]any) +func GetKVMapAny(dict map[string]any, key string) map[string]any { + return GetKVMap[any](dict, key) } diff --git a/internal/pkg/utils/maputil/marshal.go b/internal/pkg/utils/map/marshal.go similarity index 97% rename from internal/pkg/utils/maputil/marshal.go rename to internal/pkg/utils/map/marshal.go index 64bd97e6..236b32e2 100644 --- a/internal/pkg/utils/maputil/marshal.go +++ b/internal/pkg/utils/map/marshal.go @@ -1,4 +1,4 @@ -package maputil +package maputil import ( mapstructure "github.com/go-viper/mapstructure/v2" diff --git a/internal/pkg/utils/sliceutil/slices.go b/internal/pkg/utils/slice/slice.go similarity index 98% rename from internal/pkg/utils/sliceutil/slices.go rename to internal/pkg/utils/slice/slice.go index ba63b82a..f1c7fc0f 100644 --- a/internal/pkg/utils/sliceutil/slices.go +++ b/internal/pkg/utils/slice/slice.go @@ -1,4 +1,4 @@ -package sliceutil +package sliceutil // 创建给定切片一部分的浅拷贝,其包含通过所提供函数实现的测试的所有元素。 // diff --git a/internal/pkg/utils/typeutil/types.go b/internal/pkg/utils/type/assert.go similarity index 54% rename from internal/pkg/utils/typeutil/types.go rename to internal/pkg/utils/type/assert.go index 4e5d3711..509a77cc 100644 --- a/internal/pkg/utils/typeutil/types.go +++ b/internal/pkg/utils/type/assert.go @@ -1,4 +1,4 @@ -package typeutil +package typeutil import "reflect" @@ -24,29 +24,3 @@ func IsNil(obj any) bool { return false } - -// 将对象转换为指针。 -// -// 入参: -// - 待转换的对象。 -// -// 出参: -// - 返回对象的指针。 -func ToPtr[T any](v T) (p *T) { - return &v -} - -// 将指针转换为对象。 -// -// 入参: -// - 待转换的指针。 -// -// 出参: -// - 返回指针指向的对象。如果指针为空,则返回对象的零值。 -func ToObj[T any](p *T) (v T) { - if p == nil { - return v - } - - return *p -} diff --git a/internal/pkg/utils/type/cast.go b/internal/pkg/utils/type/cast.go new file mode 100644 index 00000000..684e262e --- /dev/null +++ b/internal/pkg/utils/type/cast.go @@ -0,0 +1,27 @@ +package typeutil + +// 将对象转换为指针。 +// +// 入参: +// - 待转换的对象。 +// +// 出参: +// - 返回对象的指针。 +func ToPtr[T any](v T) (p *T) { + return &v +} + +// 将指针转换为对象。 +// +// 入参: +// - 待转换的指针。 +// +// 出参: +// - 返回指针指向的对象。如果指针为空,则返回对象的零值。 +func ToVal[T any](p *T) (v T) { + if IsNil(p) { + return v + } + + return *p +} diff --git a/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/create_record_body.go b/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/create_record_body.go deleted file mode 100644 index 1175cde9..00000000 --- a/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/create_record_body.go +++ /dev/null @@ -1,54 +0,0 @@ -// @Title Golang SDK Client -// @Description This code is auto generated -// @Author Ecloud SDK - -package model - -import ( - "gitlab.ecloud.com/ecloud/ecloudsdkcore/position" -) -type CreateRecordBodyTypeEnum string - -// List of Type -const ( - CreateRecordBodyTypeEnumA CreateRecordBodyTypeEnum = "A" - CreateRecordBodyTypeEnumAaaa CreateRecordBodyTypeEnum = "AAAA" - CreateRecordBodyTypeEnumCaa CreateRecordBodyTypeEnum = "CAA" - CreateRecordBodyTypeEnumCmauth CreateRecordBodyTypeEnum = "CMAUTH" - CreateRecordBodyTypeEnumCname CreateRecordBodyTypeEnum = "CNAME" - CreateRecordBodyTypeEnumMx CreateRecordBodyTypeEnum = "MX" - CreateRecordBodyTypeEnumNs CreateRecordBodyTypeEnum = "NS" - CreateRecordBodyTypeEnumPtr CreateRecordBodyTypeEnum = "PTR" - CreateRecordBodyTypeEnumRp CreateRecordBodyTypeEnum = "RP" - CreateRecordBodyTypeEnumSpf CreateRecordBodyTypeEnum = "SPF" - CreateRecordBodyTypeEnumSrv CreateRecordBodyTypeEnum = "SRV" - CreateRecordBodyTypeEnumTxt CreateRecordBodyTypeEnum = "TXT" - CreateRecordBodyTypeEnumUrl CreateRecordBodyTypeEnum = "URL" -) - -type CreateRecordBody struct { - position.Body - // 主机头 - Rr string `json:"rr"` - - // 域名名称 - DomainName string `json:"domainName"` - - // 备注 - Description string `json:"description,omitempty"` - - // 线路ID - LineId string `json:"lineId"` - - // MX优先级,若“记录类型”选择”MX”,则需要配置该参数,默认是5 - MxPri *int32 `json:"mxPri,omitempty"` - - // 记录类型 - Type CreateRecordBodyTypeEnum `json:"type"` - - // 缓存的生命周期,默认可配置600s - Ttl *int32 `json:"ttl,omitempty"` - - // 记录值 - Value string `json:"value"` -} diff --git a/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/modify_record_body.go b/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/modify_record_body.go deleted file mode 100644 index ab772c09..00000000 --- a/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/modify_record_body.go +++ /dev/null @@ -1,57 +0,0 @@ -// @Title Golang SDK Client -// @Description This code is auto generated -// @Author Ecloud SDK - -package model - -import ( - "gitlab.ecloud.com/ecloud/ecloudsdkcore/position" -) -type ModifyRecordBodyTypeEnum string - -// List of Type -const ( - ModifyRecordBodyTypeEnumA ModifyRecordBodyTypeEnum = "A" - ModifyRecordBodyTypeEnumAaaa ModifyRecordBodyTypeEnum = "AAAA" - ModifyRecordBodyTypeEnumCaa ModifyRecordBodyTypeEnum = "CAA" - ModifyRecordBodyTypeEnumCmauth ModifyRecordBodyTypeEnum = "CMAUTH" - ModifyRecordBodyTypeEnumCname ModifyRecordBodyTypeEnum = "CNAME" - ModifyRecordBodyTypeEnumMx ModifyRecordBodyTypeEnum = "MX" - ModifyRecordBodyTypeEnumNs ModifyRecordBodyTypeEnum = "NS" - ModifyRecordBodyTypeEnumPtr ModifyRecordBodyTypeEnum = "PTR" - ModifyRecordBodyTypeEnumRp ModifyRecordBodyTypeEnum = "RP" - ModifyRecordBodyTypeEnumSpf ModifyRecordBodyTypeEnum = "SPF" - ModifyRecordBodyTypeEnumSrv ModifyRecordBodyTypeEnum = "SRV" - ModifyRecordBodyTypeEnumTxt ModifyRecordBodyTypeEnum = "TXT" - ModifyRecordBodyTypeEnumUrl ModifyRecordBodyTypeEnum = "URL" -) - -type ModifyRecordBody struct { - position.Body - // 解析记录ID - RecordId string `json:"recordId"` - - // 主机头 - Rr string `json:"rr,omitempty"` - - // 域名名称 - DomainName string `json:"domainName"` - - // 备注 - Description string `json:"description,omitempty"` - - // 线路ID - LineId string `json:"lineId,omitempty"` - - // MX优先级 - MxPri *int32 `json:"mxPri,omitempty"` - - // 记录类型 - Type ModifyRecordBodyTypeEnum `json:"type,omitempty"` - - // 缓存的生命周期 - Ttl *int32 `json:"ttl,omitempty"` - - // 记录值 - Value string `json:"value,omitempty"` -} diff --git a/internal/pkg/vendors/cmcc-sdk/ecloudsdkcore@v1.0.0/position/http_position.go b/internal/pkg/vendors/cmcc-sdk/ecloudsdkcore@v1.0.0/position/http_position.go deleted file mode 100644 index 7c2eec1c..00000000 --- a/internal/pkg/vendors/cmcc-sdk/ecloudsdkcore@v1.0.0/position/http_position.go +++ /dev/null @@ -1,13 +0,0 @@ -package position - -type Body struct { -} - -type Query struct { -} - -type Path struct { -} - -type Header struct { -} diff --git a/internal/pkg/vendors/huaweicloud-sdk/cast.go b/internal/pkg/vendors/huaweicloud-sdk/cast.go deleted file mode 100644 index 2abb9c87..00000000 --- a/internal/pkg/vendors/huaweicloud-sdk/cast.go +++ /dev/null @@ -1,9 +0,0 @@ -package huaweicloudsdk - -func Int32Ptr(i int32) *int32 { - return &i -} - -func StringPtr(s string) *string { - return &s -} diff --git a/internal/repository/access.go b/internal/repository/access.go index d25a6366..16cc7378 100644 --- a/internal/repository/access.go +++ b/internal/repository/access.go @@ -53,6 +53,7 @@ func (r *AccessRepository) castRecordToModel(record *core.Record) (*domain.Acces Name: record.GetString("name"), Provider: record.GetString("provider"), Config: config, + Reserve: record.GetString("reserve"), } return access, nil } diff --git a/internal/workflow/dispatcher/dispatcher.go b/internal/workflow/dispatcher/dispatcher.go index d453b72f..7874b945 100644 --- a/internal/workflow/dispatcher/dispatcher.go +++ b/internal/workflow/dispatcher/dispatcher.go @@ -1,25 +1,31 @@ -package dispatcher +package dispatcher import ( "context" "errors" "fmt" "os" + "runtime" "strconv" "sync" "time" "github.com/usual2970/certimate/internal/app" "github.com/usual2970/certimate/internal/domain" - "github.com/usual2970/certimate/internal/pkg/utils/sliceutil" + sliceutil "github.com/usual2970/certimate/internal/pkg/utils/slice" ) -var maxWorkers = 16 +var maxWorkers = 1 func init() { envMaxWorkers := os.Getenv("CERTIMATE_WORKFLOW_MAX_WORKERS") if n, err := strconv.Atoi(envMaxWorkers); err != nil && n > 0 { maxWorkers = n + } else { + maxWorkers = runtime.GOMAXPROCS(0) + if maxWorkers == 0 { + maxWorkers = max(1, runtime.NumCPU()) + } } } diff --git a/internal/workflow/dispatcher/invoker.go b/internal/workflow/dispatcher/invoker.go index 5f344458..c644b26b 100644 --- a/internal/workflow/dispatcher/invoker.go +++ b/internal/workflow/dispatcher/invoker.go @@ -47,8 +47,10 @@ func (w *workflowInvoker) GetLogs() domain.WorkflowLogs { func (w *workflowInvoker) processNode(ctx context.Context, node *domain.WorkflowNode) error { current := node for current != nil { - if ctx.Err() != nil { + select { + case <-ctx.Done(): return ctx.Err() + default: } if current.Type == domain.WorkflowNodeTypeBranch || current.Type == domain.WorkflowNodeTypeExecuteResultBranch { diff --git a/internal/workflow/dispatcher/singleton.go b/internal/workflow/dispatcher/singleton.go index 20fdde97..e5a77655 100644 --- a/internal/workflow/dispatcher/singleton.go +++ b/internal/workflow/dispatcher/singleton.go @@ -1,4 +1,4 @@ -package dispatcher +package dispatcher import ( "context" diff --git a/internal/workflow/node-processor/apply_node.go b/internal/workflow/node-processor/apply_node.go index b9769f3d..97b7575d 100644 --- a/internal/workflow/node-processor/apply_node.go +++ b/internal/workflow/node-processor/apply_node.go @@ -9,7 +9,7 @@ import ( "github.com/usual2970/certimate/internal/applicant" "github.com/usual2970/certimate/internal/domain" - "github.com/usual2970/certimate/internal/pkg/utils/certutil" + certutil "github.com/usual2970/certimate/internal/pkg/utils/cert" "github.com/usual2970/certimate/internal/repository" ) @@ -41,22 +41,25 @@ func (n *applyNode) Process(ctx context.Context) error { } // 检测是否可以跳过本次执行 - if skippable, skipReason := n.checkCanSkip(ctx, lastOutput); skippable { - n.logger.Info(fmt.Sprintf("skip this application, because %s", skipReason)) + if skippable, reason := n.checkCanSkip(ctx, lastOutput); skippable { + n.logger.Info(fmt.Sprintf("skip this application, because %s", reason)) return nil - } else if skipReason != "" { - n.logger.Info(fmt.Sprintf("re-apply, because %s", skipReason)) + } else if reason != "" { + n.logger.Info(fmt.Sprintf("re-apply, because %s", reason)) } // 初始化申请器 - applicant, err := applicant.NewWithApplyNode(n.node) + applicant, err := applicant.NewWithWorkflowNode(applicant.ApplicantWithWorkflowNodeConfig{ + Node: n.node, + Logger: n.logger, + }) if err != nil { n.logger.Warn("failed to create applicant provider") return err } // 申请证书 - applyResult, err := applicant.Apply() + applyResult, err := applicant.Apply(ctx) if err != nil { n.logger.Warn("failed to apply") return err diff --git a/internal/workflow/node-processor/deploy_node.go b/internal/workflow/node-processor/deploy_node.go index edb3c53d..d60a5a7a 100644 --- a/internal/workflow/node-processor/deploy_node.go +++ b/internal/workflow/node-processor/deploy_node.go @@ -54,26 +54,27 @@ func (n *deployNode) Process(ctx context.Context) error { // 检测是否可以跳过本次执行 if lastOutput != nil && certificate.CreatedAt.Before(lastOutput.UpdatedAt) { - if skippable, skipReason := n.checkCanSkip(ctx, lastOutput); skippable { - n.logger.Info(fmt.Sprintf("skip this deployment, because %s", skipReason)) + if skippable, reason := n.checkCanSkip(ctx, lastOutput); skippable { + n.logger.Info(fmt.Sprintf("skip this deployment, because %s", reason)) return nil - } else if skipReason != "" { - n.logger.Info(fmt.Sprintf("re-deploy, because %s", skipReason)) + } else if reason != "" { + n.logger.Info(fmt.Sprintf("re-deploy, because %s", reason)) } } // 初始化部署器 - deployer, err := deployer.NewWithDeployNode(n.node, struct { - Certificate string - PrivateKey string - }{Certificate: certificate.Certificate, PrivateKey: certificate.PrivateKey}) + deployer, err := deployer.NewWithWorkflowNode(deployer.DeployerWithWorkflowNodeConfig{ + Node: n.node, + Logger: n.logger, + CertificatePEM: certificate.Certificate, + PrivateKeyPEM: certificate.PrivateKey, + }) if err != nil { n.logger.Warn("failed to create deployer provider") return err } // 部署证书 - deployer.SetLogger(n.logger) if err := deployer.Deploy(ctx); err != nil { n.logger.Warn("failed to deploy") return err diff --git a/internal/workflow/node-processor/notify_node.go b/internal/workflow/node-processor/notify_node.go index 1c2b49d8..1840938b 100644 --- a/internal/workflow/node-processor/notify_node.go +++ b/internal/workflow/node-processor/notify_node.go @@ -30,25 +30,50 @@ func (n *notifyNode) Process(ctx context.Context) error { nodeConfig := n.node.GetConfigForNotify() - // 获取通知配置 - settings, err := n.settingsRepo.GetByName(ctx, "notifyChannels") + if nodeConfig.Provider == "" { + // Deprecated: v0.4.x 将废弃 + // 兼容旧版本的通知渠道 + n.logger.Warn("WARNING! you are using the notification channel from global settings, which will be deprecated in the future") + + // 获取通知配置 + settings, err := n.settingsRepo.GetByName(ctx, "notifyChannels") + if err != nil { + return err + } + + // 获取通知渠道 + channelConfig, err := settings.GetNotifyChannelConfig(nodeConfig.Channel) + if err != nil { + return err + } + + // 发送通知 + if err := notify.SendToChannel(nodeConfig.Subject, nodeConfig.Message, nodeConfig.Channel, channelConfig); err != nil { + n.logger.Warn("failed to notify", slog.String("channel", nodeConfig.Channel)) + return err + } + + n.logger.Info("notify completed") + return nil + } + + // 初始化通知器 + deployer, err := notify.NewWithWorkflowNode(notify.NotifierWithWorkflowNodeConfig{ + Node: n.node, + Logger: n.logger, + Subject: nodeConfig.Subject, + Message: nodeConfig.Message, + }) if err != nil { + n.logger.Warn("failed to create notifier provider") return err } - // 获取通知渠道 - channelConfig, err := settings.GetNotifyChannelConfig(nodeConfig.Channel) - if err != nil { + // 推送通知 + if err := deployer.Notify(ctx); err != nil { + n.logger.Warn("failed to notify") return err } - // 发送通知 - if err := notify.SendToChannel(nodeConfig.Subject, nodeConfig.Message, nodeConfig.Channel, channelConfig); err != nil { - n.logger.Warn("failed to notify", slog.String("channel", nodeConfig.Channel)) - return err - } - - n.logger.Info("notify completed") - return nil } diff --git a/internal/workflow/node-processor/upload_node.go b/internal/workflow/node-processor/upload_node.go index 891f2978..2da19eed 100644 --- a/internal/workflow/node-processor/upload_node.go +++ b/internal/workflow/node-processor/upload_node.go @@ -39,11 +39,11 @@ func (n *uploadNode) Process(ctx context.Context) error { } // 检测是否可以跳过本次执行 - if skippable, skipReason := n.checkCanSkip(ctx, lastOutput); skippable { - n.logger.Info(fmt.Sprintf("skip this upload, because %s", skipReason)) + if skippable, reason := n.checkCanSkip(ctx, lastOutput); skippable { + n.logger.Info(fmt.Sprintf("skip this upload, because %s", reason)) return nil - } else if skipReason != "" { - n.logger.Info(fmt.Sprintf("re-upload, because %s", skipReason)) + } else if reason != "" { + n.logger.Info(fmt.Sprintf("re-upload, because %s", reason)) } // 生成证书实体 diff --git a/migrations/1739462400_collections_snapshot.go b/migrations/1739462400_collections_snapshot.go index d8ed7409..25564526 100644 --- a/migrations/1739462400_collections_snapshot.go +++ b/migrations/1739462400_collections_snapshot.go @@ -7,7 +7,7 @@ import ( "github.com/pocketbase/pocketbase/core" m "github.com/pocketbase/pocketbase/migrations" - "github.com/usual2970/certimate/internal/pkg/utils/certutil" + certutil "github.com/usual2970/certimate/internal/pkg/utils/cert" ) func init() { diff --git a/migrations/1744459000_upgrade.go b/migrations/1744459000_upgrade.go index d2f95004..4b2bbba9 100644 --- a/migrations/1744459000_upgrade.go +++ b/migrations/1744459000_upgrade.go @@ -7,91 +7,85 @@ import ( func init() { m.Register(func(app core.App) error { - // update collection `access` - { - collection, err := app.FindCollectionByNameOrId("4yzbv8urny5ja1e") - if err != nil { - return err - } - - // update field - if err := collection.Fields.AddMarshaledJSONAt(2, []byte(`{ - "hidden": false, - "id": "hwy7m03o", - "maxSelect": 1, - "name": "provider", - "presentable": false, - "required": false, - "system": false, - "type": "select", - "values": [ - "1panel", - "acmehttpreq", - "akamai", - "aliyun", - "aws", - "azure", - "baiducloud", - "baishan", - "baotapanel", - "bunny", - "byteplus", - "buypass", - "cachefly", - "cdnfly", - "cloudflare", - "cloudns", - "cmcccloud", - "ctcccloud", - "cucccloud", - "desec", - "dnsla", - "dogecloud", - "dynv6", - "edgio", - "fastly", - "gname", - "gcore", - "godaddy", - "goedge", - "googletrustservices", - "huaweicloud", - "jdcloud", - "k8s", - "letsencrypt", - "letsencryptstaging", - "local", - "namecheap", - "namedotcom", - "namesilo", - "ns1", - "porkbun", - "powerdns", - "qiniu", - "qingcloud", - "rainyun", - "safeline", - "ssh", - "sslcom", - "tencentcloud", - "ucloud", - "upyun", - "vercel", - "volcengine", - "webhook", - "westcn", - "zerossl" - ] - }`)); err != nil { - return err - } - - if err := app.Save(collection); err != nil { - return err - } + collection, err := app.FindCollectionByNameOrId("4yzbv8urny5ja1e") + if err != nil { + return err } - return nil + // update field + if err := collection.Fields.AddMarshaledJSONAt(2, []byte(`{ + "hidden": false, + "id": "hwy7m03o", + "maxSelect": 1, + "name": "provider", + "presentable": false, + "required": false, + "system": false, + "type": "select", + "values": [ + "1panel", + "acmehttpreq", + "akamai", + "aliyun", + "aws", + "azure", + "baiducloud", + "baishan", + "baotapanel", + "bunny", + "byteplus", + "buypass", + "cachefly", + "cdnfly", + "cloudflare", + "cloudns", + "cmcccloud", + "ctcccloud", + "cucccloud", + "desec", + "dnsla", + "dogecloud", + "dynv6", + "edgio", + "fastly", + "gname", + "gcore", + "godaddy", + "goedge", + "googletrustservices", + "huaweicloud", + "jdcloud", + "k8s", + "letsencrypt", + "letsencryptstaging", + "local", + "namecheap", + "namedotcom", + "namesilo", + "ns1", + "porkbun", + "powerdns", + "qiniu", + "qingcloud", + "rainyun", + "safeline", + "ssh", + "sslcom", + "tencentcloud", + "ucloud", + "upyun", + "vercel", + "volcengine", + "wangsu", + "webhook", + "westcn", + "zerossl" + ] + }`)); err != nil { + return err + } + + return app.Save(collection) }, func(app core.App) error { return nil }) diff --git a/migrations/1745308800_upgrade.go b/migrations/1745308800_upgrade.go new file mode 100644 index 00000000..989664fb --- /dev/null +++ b/migrations/1745308800_upgrade.go @@ -0,0 +1,94 @@ +package migrations + +import ( + "encoding/json" + + "github.com/pocketbase/pocketbase/core" + m "github.com/pocketbase/pocketbase/migrations" +) + +func init() { + m.Register(func(app core.App) error { + collection, err := app.FindCollectionByNameOrId("4yzbv8urny5ja1e") + if err != nil { + return err + } + + // add temp field `providerTmp` + if err := collection.Fields.AddMarshaledJSONAt(3, []byte(`{ + "autogeneratePattern": "", + "hidden": false, + "id": "text2024822322", + "max": 0, + "min": 0, + "name": "providerTmp", + "pattern": "", + "presentable": false, + "primaryKey": false, + "required": false, + "system": false, + "type": "text" + }`)); err != nil { + return err + } + if err := app.Save(collection); err != nil { + return err + } + + // copy `provider` to `providerTmp` + if _, err := app.DB().NewQuery("UPDATE access SET providerTmp = provider").Execute(); err != nil { + return err + } + + // remove old field `provider` + collection.Fields.RemoveById("hwy7m03o") + if err := json.Unmarshal([]byte(`{ + "indexes": [ + "CREATE INDEX `+"`"+`idx_wkoST0j`+"`"+` ON `+"`"+`access`+"`"+` (`+"`"+`name`+"`"+`)" + ] + }`), &collection); err != nil { + return err + } + if err := app.Save(collection); err != nil { + return err + } + + // rename field `providerTmp` to `provider` + if err := collection.Fields.AddMarshaledJSONAt(2, []byte(`{ + "autogeneratePattern": "", + "hidden": false, + "id": "text2024822322", + "max": 0, + "min": 0, + "name": "provider", + "pattern": "", + "presentable": false, + "primaryKey": false, + "required": false, + "system": false, + "type": "text" + }`)); err != nil { + return err + } + if err := app.Save(collection); err != nil { + return err + } + + // rebuild indexes + if err := json.Unmarshal([]byte(`{ + "indexes": [ + "CREATE INDEX `+"`"+`idx_wkoST0j`+"`"+` ON `+"`"+`access`+"`"+` (`+"`"+`name`+"`"+`)", + "CREATE INDEX `+"`"+`idx_frh0JT1Aqx`+"`"+` ON `+"`"+`access`+"`"+` (`+"`"+`provider`+"`"+`)" + ] + }`), &collection); err != nil { + return err + } + if err := app.Save(collection); err != nil { + return err + } + + return nil + }, func(app core.App) error { + return nil + }) +} diff --git a/migrations/1745726400_upgrade.go b/migrations/1745726400_upgrade.go new file mode 100644 index 00000000..e4449f36 --- /dev/null +++ b/migrations/1745726400_upgrade.go @@ -0,0 +1,88 @@ +package migrations + +import ( + "github.com/pocketbase/pocketbase/core" + m "github.com/pocketbase/pocketbase/migrations" +) + +func init() { + m.Register(func(app core.App) error { + // update collection `access` + { + collection, err := app.FindCollectionByNameOrId("4yzbv8urny5ja1e") + if err != nil { + return err + } + + if err := collection.Fields.AddMarshaledJSONAt(4, []byte(`{ + "autogeneratePattern": "", + "hidden": false, + "id": "text2859962647", + "max": 0, + "min": 0, + "name": "reserve", + "pattern": "", + "presentable": false, + "primaryKey": false, + "required": false, + "system": false, + "type": "text" + }`)); err != nil { + return err + } + + if err := app.Save(collection); err != nil { + return err + } + } + + // migrate data + { + accesses, err := app.FindAllRecords("access") + if err != nil { + return err + } + + for _, access := range accesses { + changed := false + + if access.GetString("provider") == "buypass" { + access.Set("reserve", "ca") + changed = true + } else if access.GetString("provider") == "googletrustservices" { + access.Set("reserve", "ca") + changed = true + } else if access.GetString("provider") == "sslcom" { + access.Set("reserve", "ca") + changed = true + } else if access.GetString("provider") == "zerossl" { + access.Set("reserve", "ca") + changed = true + } + + if access.GetString("provider") == "webhook" { + config := make(map[string]any) + if err := access.UnmarshalJSONField("config", &config); err != nil { + return err + } + + config["method"] = "POST" + config["headers"] = "Content-Type: application/json" + access.Set("config", config) + changed = true + } + + if changed { + err = app.Save(access) + if err != nil { + return err + } + } + } + } + + return nil + }, func(app core.App) error { + return nil + }) +} diff --git a/ui/package-lock.json b/ui/package-lock.json index 90a18bbf..bf44f371 100644 --- a/ui/package-lock.json +++ b/ui/package-lock.json @@ -8,57 +8,57 @@ "name": "ui", "version": "0.0.0", "dependencies": { - "@ant-design/icons": "^5.6.1", - "@ant-design/pro-components": "^2.8.6", + "@ant-design/icons": "^6.0.0", + "@ant-design/pro-components": "^2.8.7", "ahooks": "^3.8.4", - "antd": "^5.24.4", - "antd-zod": "^6.0.1", + "antd": "^5.24.8", + "antd-zod": "^6.1.0", "clsx": "^2.1.1", - "cron-parser": "^5.0.6", + "cron-parser": "^5.1.1", "file-saver": "^2.0.5", - "i18next": "^24.2.3", - "i18next-browser-languagedetector": "^8.0.4", + "i18next": "^25.0.1", + "i18next-browser-languagedetector": "^8.0.5", "immer": "^10.1.1", - "lucide-react": "^0.483.0", + "lucide-react": "^0.503.0", "nanoid": "^5.1.5", - "pocketbase": "^0.25.2", + "pocketbase": "^0.26.0", "radash": "^12.1.0", "react": "^18.3.1", "react-copy-to-clipboard": "^5.1.0", "react-dom": "^18.3.1", "react-i18next": "^15.4.1", - "react-router-dom": "^7.4.0", + "react-router-dom": "^7.5.1", "tailwind-merge": "^2.6.0", - "zod": "^3.24.2", + "zod": "^3.24.3", "zustand": "^5.0.3" }, "devDependencies": { "@types/file-saver": "^2.0.7", "@types/fs-extra": "^11.0.4", - "@types/node": "^22.13.10", + "@types/node": "^22.14.1", "@types/react": "^18.3.12", "@types/react-copy-to-clipboard": "^5.0.7", "@types/react-dom": "^18.3.1", - "@typescript-eslint/eslint-plugin": "^8.27.0", - "@typescript-eslint/parser": "^8.27.0", - "@vitejs/plugin-legacy": "^6.0.2", - "@vitejs/plugin-react": "^4.3.4", + "@typescript-eslint/eslint-plugin": "^8.31.0", + "@typescript-eslint/parser": "^8.31.0", + "@vitejs/plugin-legacy": "^6.1.0", + "@vitejs/plugin-react": "^4.4.1", "autoprefixer": "^10.4.21", "eslint": "^8.57.0", - "eslint-config-prettier": "^10.1.1", + "eslint-config-prettier": "^10.1.2", "eslint-import-resolver-typescript": "^3.8.3", "eslint-plugin-import": "^2.31.0", - "eslint-plugin-prettier": "^5.2.3", + "eslint-plugin-prettier": "^5.2.6", "eslint-plugin-react-hooks": "^5.2.0", - "eslint-plugin-react-refresh": "^0.4.19", + "eslint-plugin-react-refresh": "^0.4.20", "eslint-plugin-tailwindcss": "^3.18.0", "fs-extra": "^11.3.0", "postcss": "^8.5.3", "prettier": "^3.5.3", "tailwindcss": "^3.4.17", "tailwindcss-animate": "^1.0.7", - "typescript": "^5.8.2", - "vite": "^6.2.2" + "typescript": "^5.8.3", + "vite": "^6.3.2" } }, "node_modules/@alloc/quick-lru": { @@ -138,6 +138,64 @@ } }, "node_modules/@ant-design/icons": { + "version": "6.0.0", + "resolved": "https://registry.npmmirror.com/@ant-design/icons/-/icons-6.0.0.tgz", + "integrity": "sha512-o0aCCAlHc1o4CQcapAwWzHeaW2x9F49g7P3IDtvtNXgHowtRWYb7kiubt8sQPFvfVIVU/jLw2hzeSlNt0FU+Uw==", + "dependencies": { + "@ant-design/colors": "^8.0.0", + "@ant-design/icons-svg": "^4.4.0", + "@rc-component/util": "^1.2.1", + "classnames": "^2.2.6" + }, + "engines": { + "node": ">=8" + }, + "peerDependencies": { + "react": ">=16.0.0", + "react-dom": ">=16.0.0" + } + }, + "node_modules/@ant-design/icons-svg": { + "version": "4.4.2", + "resolved": "https://registry.npmmirror.com/@ant-design/icons-svg/-/icons-svg-4.4.2.tgz", + "integrity": "sha512-vHbT+zJEVzllwP+CM+ul7reTEfBR0vgxFe7+lREAsAA7YGsYpboiq2sQNeQeRvh09GfQgs/GyFEvZpJ9cLXpXA==" + }, + "node_modules/@ant-design/icons/node_modules/@ant-design/colors": { + "version": "8.0.0", + "resolved": "https://registry.npmmirror.com/@ant-design/colors/-/colors-8.0.0.tgz", + "integrity": "sha512-6YzkKCw30EI/E9kHOIXsQDHmMvTllT8STzjMb4K2qzit33RW2pqCJP0sk+hidBntXxE+Vz4n1+RvCTfBw6OErw==", + "dependencies": { + "@ant-design/fast-color": "^3.0.0" + } + }, + "node_modules/@ant-design/icons/node_modules/@ant-design/fast-color": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/@ant-design/fast-color/-/fast-color-3.0.0.tgz", + "integrity": "sha512-eqvpP7xEDm2S7dUzl5srEQCBTXZMmY3ekf97zI+M2DHOYyKdJGH0qua0JACHTqbkRnD/KHFQP9J1uMJ/XWVzzA==", + "engines": { + "node": ">=8.x" + } + }, + "node_modules/@ant-design/pro-card": { + "version": "2.9.7", + "resolved": "https://registry.npmmirror.com/@ant-design/pro-card/-/pro-card-2.9.7.tgz", + "integrity": "sha512-uDDYowmYH1ldRfG8Mb4QOwcEEz6ptRBQDLO1tkVADCRkdOMwz82xlZneR4uVuFyKcuNmgHzarYNncozBKhFuaA==", + "dependencies": { + "@ant-design/cssinjs": "^1.21.1", + "@ant-design/icons": "^5.0.0", + "@ant-design/pro-provider": "2.15.4", + "@ant-design/pro-utils": "2.17.0", + "@babel/runtime": "^7.18.0", + "classnames": "^2.3.2", + "rc-resize-observer": "^1.0.0", + "rc-util": "^5.4.0" + }, + "peerDependencies": { + "antd": "^4.24.15 || ^5.11.2", + "react": ">=17.0.0" + } + }, + "node_modules/@ant-design/pro-card/node_modules/@ant-design/icons": { "version": "5.6.1", "resolved": "https://registry.npmmirror.com/@ant-design/icons/-/icons-5.6.1.tgz", "integrity": "sha512-0/xS39c91WjPAZOWsvi1//zjx6kAp4kxWwctR6kuU6p133w8RU0D2dSCvZC19uQyharg/sAvYxGYWl01BbZZfg==", @@ -156,45 +214,21 @@ "react-dom": ">=16.0.0" } }, - "node_modules/@ant-design/icons-svg": { - "version": "4.4.2", - "resolved": "https://registry.npmmirror.com/@ant-design/icons-svg/-/icons-svg-4.4.2.tgz", - "integrity": "sha512-vHbT+zJEVzllwP+CM+ul7reTEfBR0vgxFe7+lREAsAA7YGsYpboiq2sQNeQeRvh09GfQgs/GyFEvZpJ9cLXpXA==" - }, - "node_modules/@ant-design/pro-card": { - "version": "2.9.6", - "resolved": "https://registry.npmmirror.com/@ant-design/pro-card/-/pro-card-2.9.6.tgz", - "integrity": "sha512-boUvowODMhc1l55ZZj/08YwnaggL50fAio2NaA7uXsgpbLduSPL2OE0RyiI24NCqFhPRZMZQHbPOmcHw4Bf3yQ==", - "dependencies": { - "@ant-design/cssinjs": "^1.21.1", - "@ant-design/icons": "^5.0.0", - "@ant-design/pro-provider": "2.15.3", - "@ant-design/pro-utils": "2.16.4", - "@babel/runtime": "^7.18.0", - "classnames": "^2.3.2", - "rc-resize-observer": "^1.0.0", - "rc-util": "^5.4.0" - }, - "peerDependencies": { - "antd": "^4.24.15 || ^5.11.2", - "react": ">=17.0.0" - } - }, "node_modules/@ant-design/pro-components": { - "version": "2.8.6", - "resolved": "https://registry.npmmirror.com/@ant-design/pro-components/-/pro-components-2.8.6.tgz", - "integrity": "sha512-iNd9kTLI0vAYGiyVrpDRflmee+h7486OLXIgIb89g3G+5YS9xSnRuCYt6UBRAEGsB1GRUPznRUGUd6Gsg33V+g==", + "version": "2.8.7", + "resolved": "https://registry.npmmirror.com/@ant-design/pro-components/-/pro-components-2.8.7.tgz", + "integrity": "sha512-QhibkPsUJryEjI1QmwUn+XCngGHidu0ekvricL6TIEvPgP+AUAca29XutN5+Mmn8Xfja1ca9HFTHTgFoV74Z7Q==", "dependencies": { - "@ant-design/pro-card": "2.9.6", - "@ant-design/pro-descriptions": "2.6.6", - "@ant-design/pro-field": "3.0.3", - "@ant-design/pro-form": "2.31.6", - "@ant-design/pro-layout": "7.22.3", - "@ant-design/pro-list": "2.6.6", - "@ant-design/pro-provider": "2.15.3", + "@ant-design/pro-card": "2.9.7", + "@ant-design/pro-descriptions": "2.6.7", + "@ant-design/pro-field": "3.0.4", + "@ant-design/pro-form": "2.31.7", + "@ant-design/pro-layout": "7.22.4", + "@ant-design/pro-list": "2.6.7", + "@ant-design/pro-provider": "2.15.4", "@ant-design/pro-skeleton": "2.2.1", - "@ant-design/pro-table": "3.18.6", - "@ant-design/pro-utils": "2.16.4", + "@ant-design/pro-table": "3.19.0", + "@ant-design/pro-utils": "2.17.0", "@babel/runtime": "^7.16.3" }, "peerDependencies": { @@ -204,15 +238,15 @@ } }, "node_modules/@ant-design/pro-descriptions": { - "version": "2.6.6", - "resolved": "https://registry.npmmirror.com/@ant-design/pro-descriptions/-/pro-descriptions-2.6.6.tgz", - "integrity": "sha512-Onwn79P5wNcFNHQmXVdTDgewXt4MCW5snEFctZuCY6T5KwpH7Y9UA8GWtFNIL2KfF5+uu83es20N0E2hg73G0w==", + "version": "2.6.7", + "resolved": "https://registry.npmmirror.com/@ant-design/pro-descriptions/-/pro-descriptions-2.6.7.tgz", + "integrity": "sha512-fgn2d0kDWUODGDWKpgziZuuqPlmIoKxQFJY9Yg4nbaRp8GDDKZeSSqgvW+OxjpYM8dxq31fiz1dZlZnOPoYKpg==", "dependencies": { - "@ant-design/pro-field": "3.0.3", - "@ant-design/pro-form": "2.31.6", - "@ant-design/pro-provider": "2.15.3", + "@ant-design/pro-field": "3.0.4", + "@ant-design/pro-form": "2.31.7", + "@ant-design/pro-provider": "2.15.4", "@ant-design/pro-skeleton": "2.2.1", - "@ant-design/pro-utils": "2.16.4", + "@ant-design/pro-utils": "2.17.0", "@babel/runtime": "^7.18.0", "rc-resize-observer": "^0.2.3", "rc-util": "^5.0.6" @@ -238,13 +272,13 @@ } }, "node_modules/@ant-design/pro-field": { - "version": "3.0.3", - "resolved": "https://registry.npmmirror.com/@ant-design/pro-field/-/pro-field-3.0.3.tgz", - "integrity": "sha512-MrDZcx1kP4vpmnSJyHuxeool2o5hDRiJ8aRFloM2M7yW+Tw9ilABMlHFkKz1FLIt4esO9Zc4vd8Iv2ndlkB4/Q==", + "version": "3.0.4", + "resolved": "https://registry.npmmirror.com/@ant-design/pro-field/-/pro-field-3.0.4.tgz", + "integrity": "sha512-nJSng/6/pPZFdiFeTtZcBQLNrHg9tIeiKFR1+zzbnQbI3qBOFP9aBZS/+LwkQZcI2G71vrRgz2x5OhHb7AX0wQ==", "dependencies": { "@ant-design/icons": "^5.0.0", - "@ant-design/pro-provider": "2.15.3", - "@ant-design/pro-utils": "2.16.4", + "@ant-design/pro-provider": "2.15.4", + "@ant-design/pro-utils": "2.17.0", "@babel/runtime": "^7.18.0", "@chenshuai2144/sketch-color": "^1.0.8", "classnames": "^2.3.2", @@ -259,15 +293,34 @@ "react": ">=17.0.0" } }, + "node_modules/@ant-design/pro-field/node_modules/@ant-design/icons": { + "version": "5.6.1", + "resolved": "https://registry.npmmirror.com/@ant-design/icons/-/icons-5.6.1.tgz", + "integrity": "sha512-0/xS39c91WjPAZOWsvi1//zjx6kAp4kxWwctR6kuU6p133w8RU0D2dSCvZC19uQyharg/sAvYxGYWl01BbZZfg==", + "dependencies": { + "@ant-design/colors": "^7.0.0", + "@ant-design/icons-svg": "^4.4.0", + "@babel/runtime": "^7.24.8", + "classnames": "^2.2.6", + "rc-util": "^5.31.1" + }, + "engines": { + "node": ">=8" + }, + "peerDependencies": { + "react": ">=16.0.0", + "react-dom": ">=16.0.0" + } + }, "node_modules/@ant-design/pro-form": { - "version": "2.31.6", - "resolved": "https://registry.npmmirror.com/@ant-design/pro-form/-/pro-form-2.31.6.tgz", - "integrity": "sha512-pDthX9AjLiryFrtPFY+Ep1z/CfEbhg++K25p7jA6tyl1gVeOIcHVkLTEFMNKmWrc9ZSCA35D/UeSz3bn102GLg==", + "version": "2.31.7", + "resolved": "https://registry.npmmirror.com/@ant-design/pro-form/-/pro-form-2.31.7.tgz", + "integrity": "sha512-0TCtIC/ynbLPoes8sLBFwFbi0tkeNmSU6the2EcyKIKDLfWHDbfkLM1OSFrzv3QD+H8OgFWMkTSOjhMOKSsOBg==", "dependencies": { "@ant-design/icons": "^5.0.0", - "@ant-design/pro-field": "3.0.3", - "@ant-design/pro-provider": "2.15.3", - "@ant-design/pro-utils": "2.16.4", + "@ant-design/pro-field": "3.0.4", + "@ant-design/pro-provider": "2.15.4", + "@ant-design/pro-utils": "2.17.0", "@babel/runtime": "^7.18.0", "@chenshuai2144/sketch-color": "^1.0.7", "@umijs/use-params": "^1.0.9", @@ -285,15 +338,34 @@ "react-dom": ">=17.0.0" } }, + "node_modules/@ant-design/pro-form/node_modules/@ant-design/icons": { + "version": "5.6.1", + "resolved": "https://registry.npmmirror.com/@ant-design/icons/-/icons-5.6.1.tgz", + "integrity": "sha512-0/xS39c91WjPAZOWsvi1//zjx6kAp4kxWwctR6kuU6p133w8RU0D2dSCvZC19uQyharg/sAvYxGYWl01BbZZfg==", + "dependencies": { + "@ant-design/colors": "^7.0.0", + "@ant-design/icons-svg": "^4.4.0", + "@babel/runtime": "^7.24.8", + "classnames": "^2.2.6", + "rc-util": "^5.31.1" + }, + "engines": { + "node": ">=8" + }, + "peerDependencies": { + "react": ">=16.0.0", + "react-dom": ">=16.0.0" + } + }, "node_modules/@ant-design/pro-layout": { - "version": "7.22.3", - "resolved": "https://registry.npmmirror.com/@ant-design/pro-layout/-/pro-layout-7.22.3.tgz", - "integrity": "sha512-di/EOMDuoMDRjBweqesYyCxEYr2LCmO82y6A4bSwmmJ6ehxN7HGC73Wx4RuBkzDR7kHLTOXt7WxI6875ENT8mg==", + "version": "7.22.4", + "resolved": "https://registry.npmmirror.com/@ant-design/pro-layout/-/pro-layout-7.22.4.tgz", + "integrity": "sha512-X2WO4L2itXemX4zhS+0NG+8kXQD5SX9sG+zjx/15BmIO3FvsUGqOHgoCg0vhd424EiyPj7WtdMZJ39G1xdgDwA==", "dependencies": { "@ant-design/cssinjs": "^1.21.1", "@ant-design/icons": "^5.0.0", - "@ant-design/pro-provider": "2.15.3", - "@ant-design/pro-utils": "2.16.4", + "@ant-design/pro-provider": "2.15.4", + "@ant-design/pro-utils": "2.17.0", "@babel/runtime": "^7.18.0", "@umijs/route-utils": "^4.0.0", "@umijs/use-params": "^1.0.9", @@ -312,17 +384,36 @@ "react-dom": ">=17.0.0" } }, + "node_modules/@ant-design/pro-layout/node_modules/@ant-design/icons": { + "version": "5.6.1", + "resolved": "https://registry.npmmirror.com/@ant-design/icons/-/icons-5.6.1.tgz", + "integrity": "sha512-0/xS39c91WjPAZOWsvi1//zjx6kAp4kxWwctR6kuU6p133w8RU0D2dSCvZC19uQyharg/sAvYxGYWl01BbZZfg==", + "dependencies": { + "@ant-design/colors": "^7.0.0", + "@ant-design/icons-svg": "^4.4.0", + "@babel/runtime": "^7.24.8", + "classnames": "^2.2.6", + "rc-util": "^5.31.1" + }, + "engines": { + "node": ">=8" + }, + "peerDependencies": { + "react": ">=16.0.0", + "react-dom": ">=16.0.0" + } + }, "node_modules/@ant-design/pro-list": { - "version": "2.6.6", - "resolved": "https://registry.npmmirror.com/@ant-design/pro-list/-/pro-list-2.6.6.tgz", - "integrity": "sha512-Yea/KDd3kjOKklz1AHs66JGvtguvPYYFSaZFXW4m4VBjABHoaF6seo7ySW9UUWgwuoegdGtiglvleYv/rQoEcw==", + "version": "2.6.7", + "resolved": "https://registry.npmmirror.com/@ant-design/pro-list/-/pro-list-2.6.7.tgz", + "integrity": "sha512-6k/En7pioMgepho/1HMf2DAnkSTZiat1lDg2ggCok2lhSgqXzir7x22ewJQRgPvEiVb6/qqaFQNd7a8dnrFj1w==", "dependencies": { "@ant-design/cssinjs": "^1.21.1", "@ant-design/icons": "^5.0.0", - "@ant-design/pro-card": "2.9.6", - "@ant-design/pro-field": "3.0.3", - "@ant-design/pro-table": "3.18.6", - "@ant-design/pro-utils": "2.16.4", + "@ant-design/pro-card": "2.9.7", + "@ant-design/pro-field": "3.0.4", + "@ant-design/pro-table": "3.19.0", + "@ant-design/pro-utils": "2.17.0", "@babel/runtime": "^7.18.0", "classnames": "^2.3.2", "dayjs": "^1.11.10", @@ -335,6 +426,38 @@ "react-dom": ">=17.0.0" } }, + "node_modules/@ant-design/pro-list/node_modules/@ant-design/icons": { + "version": "5.6.1", + "resolved": "https://registry.npmmirror.com/@ant-design/icons/-/icons-5.6.1.tgz", + "integrity": "sha512-0/xS39c91WjPAZOWsvi1//zjx6kAp4kxWwctR6kuU6p133w8RU0D2dSCvZC19uQyharg/sAvYxGYWl01BbZZfg==", + "dependencies": { + "@ant-design/colors": "^7.0.0", + "@ant-design/icons-svg": "^4.4.0", + "@babel/runtime": "^7.24.8", + "classnames": "^2.2.6", + "rc-util": "^5.31.1" + }, + "engines": { + "node": ">=8" + }, + "peerDependencies": { + "react": ">=16.0.0", + "react-dom": ">=16.0.0" + } + }, + "node_modules/@ant-design/pro-list/node_modules/@ant-design/icons/node_modules/rc-util": { + "version": "5.44.4", + "resolved": "https://registry.npmmirror.com/rc-util/-/rc-util-5.44.4.tgz", + "integrity": "sha512-resueRJzmHG9Q6rI/DfK6Kdv9/Lfls05vzMs1Sk3M2P+3cJa+MakaZyWY8IPfehVuhPJFKrIY1IK4GqbiaiY5w==", + "dependencies": { + "@babel/runtime": "^7.18.3", + "react-is": "^18.2.0" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, "node_modules/@ant-design/pro-list/node_modules/rc-util": { "version": "4.21.1", "resolved": "https://registry.npmmirror.com/rc-util/-/rc-util-4.21.1.tgz", @@ -347,15 +470,15 @@ "shallowequal": "^1.1.0" } }, - "node_modules/@ant-design/pro-list/node_modules/react-is": { + "node_modules/@ant-design/pro-list/node_modules/rc-util/node_modules/react-is": { "version": "16.13.1", "resolved": "https://registry.npmmirror.com/react-is/-/react-is-16.13.1.tgz", "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" }, "node_modules/@ant-design/pro-provider": { - "version": "2.15.3", - "resolved": "https://registry.npmmirror.com/@ant-design/pro-provider/-/pro-provider-2.15.3.tgz", - "integrity": "sha512-jUBCuRrhAXNMumSZ++704/zEg/7U1k2N3jMVBgtirvVaCAk5O9iZQKK4W3O3LRFc+D8yO16sXjsxhawvdGL4cA==", + "version": "2.15.4", + "resolved": "https://registry.npmmirror.com/@ant-design/pro-provider/-/pro-provider-2.15.4.tgz", + "integrity": "sha512-DBX0JNUNOYXAucVqd/zTdqtXckCDqr2Lo85KIku2YzWdhptDPDZRTNqL04JShjGejDl8fzwQ8yREHgVUfzn6Gg==", "dependencies": { "@ant-design/cssinjs": "^1.21.1", "@babel/runtime": "^7.18.0", @@ -384,17 +507,17 @@ } }, "node_modules/@ant-design/pro-table": { - "version": "3.18.6", - "resolved": "https://registry.npmmirror.com/@ant-design/pro-table/-/pro-table-3.18.6.tgz", - "integrity": "sha512-ABXavpJWUOGGcer/WLBpRtzWCbfwZX3T8vAwMbLUQAl1xz3TTgkYzDDTcIdwUmtVdkgJUdWc8GdHWangWW30iQ==", + "version": "3.19.0", + "resolved": "https://registry.npmmirror.com/@ant-design/pro-table/-/pro-table-3.19.0.tgz", + "integrity": "sha512-nL25734d5q5oqtmG7Apn2TNJUnJE8m9dkopXMQdoNZnv8qeRQLBH+i5cZT1yh7FIO8z6QLXleg+KnR/cI7VRRw==", "dependencies": { "@ant-design/cssinjs": "^1.21.1", "@ant-design/icons": "^5.0.0", - "@ant-design/pro-card": "2.9.6", - "@ant-design/pro-field": "3.0.3", - "@ant-design/pro-form": "2.31.6", - "@ant-design/pro-provider": "2.15.3", - "@ant-design/pro-utils": "2.16.4", + "@ant-design/pro-card": "2.9.7", + "@ant-design/pro-field": "3.0.4", + "@ant-design/pro-form": "2.31.7", + "@ant-design/pro-provider": "2.15.4", + "@ant-design/pro-utils": "2.17.0", "@babel/runtime": "^7.18.0", "@dnd-kit/core": "^6.0.8", "@dnd-kit/modifiers": "^6.0.1", @@ -414,13 +537,32 @@ "react-dom": ">=17.0.0" } }, + "node_modules/@ant-design/pro-table/node_modules/@ant-design/icons": { + "version": "5.6.1", + "resolved": "https://registry.npmmirror.com/@ant-design/icons/-/icons-5.6.1.tgz", + "integrity": "sha512-0/xS39c91WjPAZOWsvi1//zjx6kAp4kxWwctR6kuU6p133w8RU0D2dSCvZC19uQyharg/sAvYxGYWl01BbZZfg==", + "dependencies": { + "@ant-design/colors": "^7.0.0", + "@ant-design/icons-svg": "^4.4.0", + "@babel/runtime": "^7.24.8", + "classnames": "^2.2.6", + "rc-util": "^5.31.1" + }, + "engines": { + "node": ">=8" + }, + "peerDependencies": { + "react": ">=16.0.0", + "react-dom": ">=16.0.0" + } + }, "node_modules/@ant-design/pro-utils": { - "version": "2.16.4", - "resolved": "https://registry.npmmirror.com/@ant-design/pro-utils/-/pro-utils-2.16.4.tgz", - "integrity": "sha512-PFxqF0fsUsLj8ORvJSuMgVv9NDHwAxZaglzPN/u3jZX7rWYcrHD04EMJEXooZaSyT6Q4+j7SqXDx6oBsdb9zNw==", + "version": "2.17.0", + "resolved": "https://registry.npmmirror.com/@ant-design/pro-utils/-/pro-utils-2.17.0.tgz", + "integrity": "sha512-hHKUISjMEoS+E5ltJWyvNTrlEA3IimZNxtDrEhorRIbgVYAlmEN5Mj/ESSofzDM3+UlxiI5+A/Y6IHkByTfDEA==", "dependencies": { "@ant-design/icons": "^5.0.0", - "@ant-design/pro-provider": "2.15.3", + "@ant-design/pro-provider": "2.15.4", "@babel/runtime": "^7.18.0", "classnames": "^2.3.2", "dayjs": "^1.11.10", @@ -436,6 +578,25 @@ "react-dom": ">=17.0.0" } }, + "node_modules/@ant-design/pro-utils/node_modules/@ant-design/icons": { + "version": "5.6.1", + "resolved": "https://registry.npmmirror.com/@ant-design/icons/-/icons-5.6.1.tgz", + "integrity": "sha512-0/xS39c91WjPAZOWsvi1//zjx6kAp4kxWwctR6kuU6p133w8RU0D2dSCvZC19uQyharg/sAvYxGYWl01BbZZfg==", + "dependencies": { + "@ant-design/colors": "^7.0.0", + "@ant-design/icons-svg": "^4.4.0", + "@babel/runtime": "^7.24.8", + "classnames": "^2.2.6", + "rc-util": "^5.31.1" + }, + "engines": { + "node": ">=8" + }, + "peerDependencies": { + "react": ">=16.0.0", + "react-dom": ">=16.0.0" + } + }, "node_modules/@ant-design/react-slick": { "version": "1.1.2", "resolved": "https://registry.npmmirror.com/@ant-design/react-slick/-/react-slick-1.1.2.tgz", @@ -475,21 +636,21 @@ } }, "node_modules/@babel/core": { - "version": "7.26.9", - "resolved": "https://registry.npmmirror.com/@babel/core/-/core-7.26.9.tgz", - "integrity": "sha512-lWBYIrF7qK5+GjY5Uy+/hEgp8OJWOD/rpy74GplYRhEauvbHDeFB8t5hPOZxCZ0Oxf4Cc36tK51/l3ymJysrKw==", + "version": "7.26.10", + "resolved": "https://registry.npmmirror.com/@babel/core/-/core-7.26.10.tgz", + "integrity": "sha512-vMqyb7XCDMPvJFFOaT9kxtiRh42GwlZEg1/uIgtZshS5a/8OaduUfCi7kynKgc3Tw/6Uo2D+db9qBttghhmxwQ==", "dev": true, "dependencies": { "@ampproject/remapping": "^2.2.0", "@babel/code-frame": "^7.26.2", - "@babel/generator": "^7.26.9", + "@babel/generator": "^7.26.10", "@babel/helper-compilation-targets": "^7.26.5", "@babel/helper-module-transforms": "^7.26.0", - "@babel/helpers": "^7.26.9", - "@babel/parser": "^7.26.9", + "@babel/helpers": "^7.26.10", + "@babel/parser": "^7.26.10", "@babel/template": "^7.26.9", - "@babel/traverse": "^7.26.9", - "@babel/types": "^7.26.9", + "@babel/traverse": "^7.26.10", + "@babel/types": "^7.26.10", "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", @@ -514,13 +675,13 @@ } }, "node_modules/@babel/generator": { - "version": "7.26.9", - "resolved": "https://registry.npmmirror.com/@babel/generator/-/generator-7.26.9.tgz", - "integrity": "sha512-kEWdzjOAUMW4hAyrzJ0ZaTOu9OmpyDIQicIh0zg0EEcEkYXZb2TjtBhnHi2ViX7PKwZqF4xwqfAm299/QMP3lg==", + "version": "7.27.0", + "resolved": "https://registry.npmmirror.com/@babel/generator/-/generator-7.27.0.tgz", + "integrity": "sha512-VybsKvpiN1gU1sdMZIp7FcqphVVKEwcuj02x73uvcHE0PTihx1nlBcowYWhDwjpoAXRv43+gDzyggGnn1XZhVw==", "dev": true, "dependencies": { - "@babel/parser": "^7.26.9", - "@babel/types": "^7.26.9", + "@babel/parser": "^7.27.0", + "@babel/types": "^7.27.0", "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.25", "jsesc": "^3.0.2" @@ -791,25 +952,25 @@ } }, "node_modules/@babel/helpers": { - "version": "7.26.9", - "resolved": "https://registry.npmmirror.com/@babel/helpers/-/helpers-7.26.9.tgz", - "integrity": "sha512-Mz/4+y8udxBKdmzt/UjPACs4G3j5SshJJEFFKxlCGPydG4JAHXxjWjAwjd09tf6oINvl1VfMJo+nB7H2YKQ0dA==", + "version": "7.27.0", + "resolved": "https://registry.npmmirror.com/@babel/helpers/-/helpers-7.27.0.tgz", + "integrity": "sha512-U5eyP/CTFPuNE3qk+WZMxFkp/4zUzdceQlfzf7DdGdhp+Fezd7HD+i8Y24ZuTMKX3wQBld449jijbGq6OdGNQg==", "dev": true, "dependencies": { - "@babel/template": "^7.26.9", - "@babel/types": "^7.26.9" + "@babel/template": "^7.27.0", + "@babel/types": "^7.27.0" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/parser": { - "version": "7.26.9", - "resolved": "https://registry.npmmirror.com/@babel/parser/-/parser-7.26.9.tgz", - "integrity": "sha512-81NWa1njQblgZbQHxWHpxxCzNsa3ZwvFqpUg7P+NNUU6f3UU2jBEg4OlF/J6rl8+PQGh1q6/zWScd001YwcA5A==", + "version": "7.27.0", + "resolved": "https://registry.npmmirror.com/@babel/parser/-/parser-7.27.0.tgz", + "integrity": "sha512-iaepho73/2Pz7w2eMS0Q5f83+0RKI7i4xmiYeBmDzfRVbQtTOG7Ts0S4HzJVsTMGI9keU8rNfuZr8DKfSt7Yyg==", "dev": true, "dependencies": { - "@babel/types": "^7.26.9" + "@babel/types": "^7.27.0" }, "bin": { "parser": "bin/babel-parser.js" @@ -1890,30 +2051,30 @@ } }, "node_modules/@babel/template": { - "version": "7.26.9", - "resolved": "https://registry.npmmirror.com/@babel/template/-/template-7.26.9.tgz", - "integrity": "sha512-qyRplbeIpNZhmzOysF/wFMuP9sctmh2cFzRAZOn1YapxBsE1i9bJIY586R/WBLfLcmcBlM8ROBiQURnnNy+zfA==", + "version": "7.27.0", + "resolved": "https://registry.npmmirror.com/@babel/template/-/template-7.27.0.tgz", + "integrity": "sha512-2ncevenBqXI6qRMukPlXwHKHchC7RyMuu4xv5JBXRfOGVcTy1mXCD12qrp7Jsoxll1EV3+9sE4GugBVRjT2jFA==", "dev": true, "dependencies": { "@babel/code-frame": "^7.26.2", - "@babel/parser": "^7.26.9", - "@babel/types": "^7.26.9" + "@babel/parser": "^7.27.0", + "@babel/types": "^7.27.0" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/traverse": { - "version": "7.26.9", - "resolved": "https://registry.npmmirror.com/@babel/traverse/-/traverse-7.26.9.tgz", - "integrity": "sha512-ZYW7L+pL8ahU5fXmNbPF+iZFHCv5scFak7MZ9bwaRPLUhHh7QQEMjZUg0HevihoqCM5iSYHN61EyCoZvqC+bxg==", + "version": "7.27.0", + "resolved": "https://registry.npmmirror.com/@babel/traverse/-/traverse-7.27.0.tgz", + "integrity": "sha512-19lYZFzYVQkkHkl4Cy4WrAVcqBkgvV2YM2TU3xG6DIwO7O3ecbDPfW3yM3bjAGcqcQHi+CCtjMR3dIEHxsd6bA==", "dev": true, "dependencies": { "@babel/code-frame": "^7.26.2", - "@babel/generator": "^7.26.9", - "@babel/parser": "^7.26.9", - "@babel/template": "^7.26.9", - "@babel/types": "^7.26.9", + "@babel/generator": "^7.27.0", + "@babel/parser": "^7.27.0", + "@babel/template": "^7.27.0", + "@babel/types": "^7.27.0", "debug": "^4.3.1", "globals": "^11.1.0" }, @@ -1922,9 +2083,9 @@ } }, "node_modules/@babel/types": { - "version": "7.26.9", - "resolved": "https://registry.npmmirror.com/@babel/types/-/types-7.26.9.tgz", - "integrity": "sha512-Y3IR1cRnOxOCDvMmNiym7XpXQ93iGDDPHx+Zj+NM+rg0fBaShfQLkg+hKPaZCEvg5N/LeCo4+Rj/i3FuJsIQaw==", + "version": "7.27.0", + "resolved": "https://registry.npmmirror.com/@babel/types/-/types-7.27.0.tgz", + "integrity": "sha512-H45s8fVLYjbhFH62dIJ3WtmJ6RSPt/3DRO0ZcT2SUiYiQyz3BLVb9ADEnLl91m74aQPS3AzzeajZHYOalWe3bg==", "dev": true, "dependencies": { "@babel/helper-string-parser": "^7.25.9", @@ -2730,15 +2891,15 @@ } }, "node_modules/@pkgr/core": { - "version": "0.1.1", - "resolved": "https://registry.npmmirror.com/@pkgr/core/-/core-0.1.1.tgz", - "integrity": "sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA==", + "version": "0.2.4", + "resolved": "https://registry.npmmirror.com/@pkgr/core/-/core-0.2.4.tgz", + "integrity": "sha512-ROFF39F6ZrnzSUEmQQZUar0Jt4xVoP9WnDRdWwF4NNcXs3xBTLgBUDoOwW141y1jP+S8nahIbdxbFC7IShw9Iw==", "dev": true, "engines": { "node": "^12.20.0 || ^14.18.0 || >=16.0.0" }, "funding": { - "url": "https://opencollective.com/unts" + "url": "https://opencollective.com/pkgr" } }, "node_modules/@rc-component/async-validator": { @@ -2881,10 +3042,22 @@ "react-dom": ">=16.9.0" } }, + "node_modules/@rc-component/util": { + "version": "1.2.1", + "resolved": "https://registry.npmmirror.com/@rc-component/util/-/util-1.2.1.tgz", + "integrity": "sha512-AUVu6jO+lWjQnUOOECwu8iR0EdElQgWW5NBv5vP/Uf9dWbAX3udhMutRlkVXjuac2E40ghkFy+ve00mc/3Fymg==", + "dependencies": { + "react-is": "^18.2.0" + }, + "peerDependencies": { + "react": ">=18.0.0", + "react-dom": ">=18.0.0" + } + }, "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.34.6", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.34.6.tgz", - "integrity": "sha512-+GcCXtOQoWuC7hhX1P00LqjjIiS/iOouHXhMdiDSnq/1DGTox4SpUvO52Xm+div6+106r+TcvOeo/cxvyEyTgg==", + "version": "4.40.0", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.40.0.tgz", + "integrity": "sha512-+Fbls/diZ0RDerhE8kyC6hjADCXA1K4yVNlH0EYfd2XjyH0UGgzaQ8MlT0pCXAThfxv3QUAczHaL+qSv1E4/Cg==", "cpu": [ "arm" ], @@ -2895,9 +3068,9 @@ ] }, "node_modules/@rollup/rollup-android-arm64": { - "version": "4.34.6", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.34.6.tgz", - "integrity": "sha512-E8+2qCIjciYUnCa1AiVF1BkRgqIGW9KzJeesQqVfyRITGQN+dFuoivO0hnro1DjT74wXLRZ7QF8MIbz+luGaJA==", + "version": "4.40.0", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.40.0.tgz", + "integrity": "sha512-PPA6aEEsTPRz+/4xxAmaoWDqh67N7wFbgFUJGMnanCFs0TV99M0M8QhhaSCks+n6EbQoFvLQgYOGXxlMGQe/6w==", "cpu": [ "arm64" ], @@ -2908,9 +3081,9 @@ ] }, "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.34.6", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.34.6.tgz", - "integrity": "sha512-z9Ib+OzqN3DZEjX7PDQMHEhtF+t6Mi2z/ueChQPLS/qUMKY7Ybn5A2ggFoKRNRh1q1T03YTQfBTQCJZiepESAg==", + "version": "4.40.0", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.40.0.tgz", + "integrity": "sha512-GwYOcOakYHdfnjjKwqpTGgn5a6cUX7+Ra2HeNj/GdXvO2VJOOXCiYYlRFU4CubFM67EhbmzLOmACKEfvp3J1kQ==", "cpu": [ "arm64" ], @@ -2921,9 +3094,9 @@ ] }, "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.34.6", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.34.6.tgz", - "integrity": "sha512-PShKVY4u0FDAR7jskyFIYVyHEPCPnIQY8s5OcXkdU8mz3Y7eXDJPdyM/ZWjkYdR2m0izD9HHWA8sGcXn+Qrsyg==", + "version": "4.40.0", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.40.0.tgz", + "integrity": "sha512-CoLEGJ+2eheqD9KBSxmma6ld01czS52Iw0e2qMZNpPDlf7Z9mj8xmMemxEucinev4LgHalDPczMyxzbq+Q+EtA==", "cpu": [ "x64" ], @@ -2934,9 +3107,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-arm64": { - "version": "4.34.6", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.34.6.tgz", - "integrity": "sha512-YSwyOqlDAdKqs0iKuqvRHLN4SrD2TiswfoLfvYXseKbL47ht1grQpq46MSiQAx6rQEN8o8URtpXARCpqabqxGQ==", + "version": "4.40.0", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.40.0.tgz", + "integrity": "sha512-r7yGiS4HN/kibvESzmrOB/PxKMhPTlz+FcGvoUIKYoTyGd5toHp48g1uZy1o1xQvybwwpqpe010JrcGG2s5nkg==", "cpu": [ "arm64" ], @@ -2947,9 +3120,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-x64": { - "version": "4.34.6", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.34.6.tgz", - "integrity": "sha512-HEP4CgPAY1RxXwwL5sPFv6BBM3tVeLnshF03HMhJYCNc6kvSqBgTMmsEjb72RkZBAWIqiPUyF1JpEBv5XT9wKQ==", + "version": "4.40.0", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.40.0.tgz", + "integrity": "sha512-mVDxzlf0oLzV3oZOr0SMJ0lSDd3xC4CmnWJ8Val8isp9jRGl5Dq//LLDSPFrasS7pSm6m5xAcKaw3sHXhBjoRw==", "cpu": [ "x64" ], @@ -2960,9 +3133,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.34.6", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.34.6.tgz", - "integrity": "sha512-88fSzjC5xeH9S2Vg3rPgXJULkHcLYMkh8faix8DX4h4TIAL65ekwuQMA/g2CXq8W+NJC43V6fUpYZNjaX3+IIg==", + "version": "4.40.0", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.40.0.tgz", + "integrity": "sha512-y/qUMOpJxBMy8xCXD++jeu8t7kzjlOCkoxxajL58G62PJGBZVl/Gwpm7JK9+YvlB701rcQTzjUZ1JgUoPTnoQA==", "cpu": [ "arm" ], @@ -2973,9 +3146,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.34.6", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.34.6.tgz", - "integrity": "sha512-wM4ztnutBqYFyvNeR7Av+reWI/enK9tDOTKNF+6Kk2Q96k9bwhDDOlnCUNRPvromlVXo04riSliMBs/Z7RteEg==", + "version": "4.40.0", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.40.0.tgz", + "integrity": "sha512-GoCsPibtVdJFPv/BOIvBKO/XmwZLwaNWdyD8TKlXuqp0veo2sHE+A/vpMQ5iSArRUz/uaoj4h5S6Pn0+PdhRjg==", "cpu": [ "arm" ], @@ -2986,9 +3159,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.34.6", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.34.6.tgz", - "integrity": "sha512-9RyprECbRa9zEjXLtvvshhw4CMrRa3K+0wcp3KME0zmBe1ILmvcVHnypZ/aIDXpRyfhSYSuN4EPdCCj5Du8FIA==", + "version": "4.40.0", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.40.0.tgz", + "integrity": "sha512-L5ZLphTjjAD9leJzSLI7rr8fNqJMlGDKlazW2tX4IUF9P7R5TMQPElpH82Q7eNIDQnQlAyiNVfRPfP2vM5Avvg==", "cpu": [ "arm64" ], @@ -2999,9 +3172,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.34.6", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.34.6.tgz", - "integrity": "sha512-qTmklhCTyaJSB05S+iSovfo++EwnIEZxHkzv5dep4qoszUMX5Ca4WM4zAVUMbfdviLgCSQOu5oU8YoGk1s6M9Q==", + "version": "4.40.0", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.40.0.tgz", + "integrity": "sha512-ATZvCRGCDtv1Y4gpDIXsS+wfFeFuLwVxyUBSLawjgXK2tRE6fnsQEkE4csQQYWlBlsFztRzCnBvWVfcae/1qxQ==", "cpu": [ "arm64" ], @@ -3012,9 +3185,9 @@ ] }, "node_modules/@rollup/rollup-linux-loongarch64-gnu": { - "version": "4.34.6", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.34.6.tgz", - "integrity": "sha512-4Qmkaps9yqmpjY5pvpkfOerYgKNUGzQpFxV6rnS7c/JfYbDSU0y6WpbbredB5cCpLFGJEqYX40WUmxMkwhWCjw==", + "version": "4.40.0", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.40.0.tgz", + "integrity": "sha512-wG9e2XtIhd++QugU5MD9i7OnpaVb08ji3P1y/hNbxrQ3sYEelKJOq1UJ5dXczeo6Hj2rfDEL5GdtkMSVLa/AOg==", "cpu": [ "loong64" ], @@ -3025,9 +3198,9 @@ ] }, "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { - "version": "4.34.6", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.34.6.tgz", - "integrity": "sha512-Zsrtux3PuaxuBTX/zHdLaFmcofWGzaWW1scwLU3ZbW/X+hSsFbz9wDIp6XvnT7pzYRl9MezWqEqKy7ssmDEnuQ==", + "version": "4.40.0", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.40.0.tgz", + "integrity": "sha512-vgXfWmj0f3jAUvC7TZSU/m/cOE558ILWDzS7jBhiCAFpY2WEBn5jqgbqvmzlMjtp8KlLcBlXVD2mkTSEQE6Ixw==", "cpu": [ "ppc64" ], @@ -3038,9 +3211,22 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.34.6", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.34.6.tgz", - "integrity": "sha512-aK+Zp+CRM55iPrlyKiU3/zyhgzWBxLVrw2mwiQSYJRobCURb781+XstzvA8Gkjg/hbdQFuDw44aUOxVQFycrAg==", + "version": "4.40.0", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.40.0.tgz", + "integrity": "sha512-uJkYTugqtPZBS3Z136arevt/FsKTF/J9dEMTX/cwR7lsAW4bShzI2R0pJVw+hcBTWF4dxVckYh72Hk3/hWNKvA==", + "cpu": [ + "riscv64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-musl": { + "version": "4.40.0", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.40.0.tgz", + "integrity": "sha512-rKmSj6EXQRnhSkE22+WvrqOqRtk733x3p5sWpZilhmjnkHkpeCgWsFFo0dGnUGeA+OZjRl3+VYq+HyCOEuwcxQ==", "cpu": [ "riscv64" ], @@ -3051,9 +3237,9 @@ ] }, "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.34.6", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.34.6.tgz", - "integrity": "sha512-WoKLVrY9ogmaYPXwTH326+ErlCIgMmsoRSx6bO+l68YgJnlOXhygDYSZe/qbUJCSiCiZAQ+tKm88NcWuUXqOzw==", + "version": "4.40.0", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.40.0.tgz", + "integrity": "sha512-SpnYlAfKPOoVsQqmTFJ0usx0z84bzGOS9anAC0AZ3rdSo3snecihbhFTlJZ8XMwzqAcodjFU4+/SM311dqE5Sw==", "cpu": [ "s390x" ], @@ -3064,9 +3250,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.34.6", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.34.6.tgz", - "integrity": "sha512-Sht4aFvmA4ToHd2vFzwMFaQCiYm2lDFho5rPcvPBT5pCdC+GwHG6CMch4GQfmWTQ1SwRKS0dhDYb54khSrjDWw==", + "version": "4.40.0", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.40.0.tgz", + "integrity": "sha512-RcDGMtqF9EFN8i2RYN2W+64CdHruJ5rPqrlYw+cgM3uOVPSsnAQps7cpjXe9be/yDp8UC7VLoCoKC8J3Kn2FkQ==", "cpu": [ "x64" ], @@ -3077,9 +3263,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.34.6", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.34.6.tgz", - "integrity": "sha512-zmmpOQh8vXc2QITsnCiODCDGXFC8LMi64+/oPpPx5qz3pqv0s6x46ps4xoycfUiVZps5PFn1gksZzo4RGTKT+A==", + "version": "4.40.0", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.40.0.tgz", + "integrity": "sha512-HZvjpiUmSNx5zFgwtQAV1GaGazT2RWvqeDi0hV+AtC8unqqDSsaFjPxfsO6qPtKRRg25SisACWnJ37Yio8ttaw==", "cpu": [ "x64" ], @@ -3090,9 +3276,9 @@ ] }, "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.34.6", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.34.6.tgz", - "integrity": "sha512-3/q1qUsO/tLqGBaD4uXsB6coVGB3usxw3qyeVb59aArCgedSF66MPdgRStUd7vbZOsko/CgVaY5fo2vkvPLWiA==", + "version": "4.40.0", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.40.0.tgz", + "integrity": "sha512-UtZQQI5k/b8d7d3i9AZmA/t+Q4tk3hOC0tMOMSq2GlMYOfxbesxG4mJSeDp0EHs30N9bsfwUvs3zF4v/RzOeTQ==", "cpu": [ "arm64" ], @@ -3103,9 +3289,9 @@ ] }, "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.34.6", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.34.6.tgz", - "integrity": "sha512-oLHxuyywc6efdKVTxvc0135zPrRdtYVjtVD5GUm55I3ODxhU/PwkQFD97z16Xzxa1Fz0AEe4W/2hzRtd+IfpOA==", + "version": "4.40.0", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.40.0.tgz", + "integrity": "sha512-+m03kvI2f5syIqHXCZLPVYplP8pQch9JHyXKZ3AGMKlg8dCyr2PKHjwRLiW53LTrN/Nc3EqHOKxUxzoSPdKddA==", "cpu": [ "ia32" ], @@ -3116,9 +3302,9 @@ ] }, "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.34.6", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.34.6.tgz", - "integrity": "sha512-0PVwmgzZ8+TZ9oGBmdZoQVXflbvuwzN/HRclujpl4N/q3i+y0lqLw8n1bXA8ru3sApDjlmONaNAuYr38y1Kr9w==", + "version": "4.40.0", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.40.0.tgz", + "integrity": "sha512-lpPE1cLfP5oPzVjKMx10pgBmKELQnFJXHgvtHCtuJWOv8MxqdEIMNtgHgBFf7Ea2/7EuVwa9fodWUfXAlXZLZQ==", "cpu": [ "x64" ], @@ -3175,15 +3361,10 @@ "@babel/types": "^7.20.7" } }, - "node_modules/@types/cookie": { - "version": "0.6.0", - "resolved": "https://registry.npmmirror.com/@types/cookie/-/cookie-0.6.0.tgz", - "integrity": "sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA==" - }, "node_modules/@types/estree": { - "version": "1.0.6", - "resolved": "https://registry.npmmirror.com/@types/estree/-/estree-1.0.6.tgz", - "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==", + "version": "1.0.7", + "resolved": "https://registry.npmmirror.com/@types/estree/-/estree-1.0.7.tgz", + "integrity": "sha512-w28IoSUCJpidD/TGviZwwMJckNESJZXFu7NBZ5YJ4mEUnNraUn9Pm8HSZm/jDF1pDWYKspWE7oVphigUPRakIQ==", "dev": true }, "node_modules/@types/file-saver": { @@ -3218,12 +3399,12 @@ } }, "node_modules/@types/node": { - "version": "22.13.10", - "resolved": "https://registry.npmmirror.com/@types/node/-/node-22.13.10.tgz", - "integrity": "sha512-I6LPUvlRH+O6VRUqYOcMudhaIdUVWfsjnZavnsraHvpBwaEyMN29ry+0UVJhImYL16xsscu0aske3yA+uPOWfw==", + "version": "22.14.1", + "resolved": "https://registry.npmmirror.com/@types/node/-/node-22.14.1.tgz", + "integrity": "sha512-u0HuPQwe/dHrItgHHpmw3N2fYCR6x4ivMNbPHRkBVP4CvN+kiRrKHWk3i8tXiO/joPwXLMYvF9TTF0eqgHIuOw==", "dev": true, "dependencies": { - "undici-types": "~6.20.0" + "undici-types": "~6.21.0" } }, "node_modules/@types/prop-types": { @@ -3261,16 +3442,16 @@ } }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.27.0", - "resolved": "https://registry.npmmirror.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.27.0.tgz", - "integrity": "sha512-4henw4zkePi5p252c8ncBLzLce52SEUz2Ebj8faDnuUXz2UuHEONYcJ+G0oaCF+bYCWVZtrGzq3FD7YXetmnSA==", + "version": "8.31.0", + "resolved": "https://registry.npmmirror.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.31.0.tgz", + "integrity": "sha512-evaQJZ/J/S4wisevDvC1KFZkPzRetH8kYZbkgcTRyql3mcKsf+ZFDV1BVWUGTCAW5pQHoqn5gK5b8kn7ou9aFQ==", "dev": true, "dependencies": { "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "8.27.0", - "@typescript-eslint/type-utils": "8.27.0", - "@typescript-eslint/utils": "8.27.0", - "@typescript-eslint/visitor-keys": "8.27.0", + "@typescript-eslint/scope-manager": "8.31.0", + "@typescript-eslint/type-utils": "8.31.0", + "@typescript-eslint/utils": "8.31.0", + "@typescript-eslint/visitor-keys": "8.31.0", "graphemer": "^1.4.0", "ignore": "^5.3.1", "natural-compare": "^1.4.0", @@ -3290,15 +3471,15 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "8.27.0", - "resolved": "https://registry.npmmirror.com/@typescript-eslint/parser/-/parser-8.27.0.tgz", - "integrity": "sha512-XGwIabPallYipmcOk45DpsBSgLC64A0yvdAkrwEzwZ2viqGqRUJ8eEYoPz0CWnutgAFbNMPdsGGvzjSmcWVlEA==", + "version": "8.31.0", + "resolved": "https://registry.npmmirror.com/@typescript-eslint/parser/-/parser-8.31.0.tgz", + "integrity": "sha512-67kYYShjBR0jNI5vsf/c3WG4u+zDnCTHTPqVMQguffaWWFs7artgwKmfwdifl+r6XyM5LYLas/dInj2T0SgJyw==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "8.27.0", - "@typescript-eslint/types": "8.27.0", - "@typescript-eslint/typescript-estree": "8.27.0", - "@typescript-eslint/visitor-keys": "8.27.0", + "@typescript-eslint/scope-manager": "8.31.0", + "@typescript-eslint/types": "8.31.0", + "@typescript-eslint/typescript-estree": "8.31.0", + "@typescript-eslint/visitor-keys": "8.31.0", "debug": "^4.3.4" }, "engines": { @@ -3314,13 +3495,13 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "8.27.0", - "resolved": "https://registry.npmmirror.com/@typescript-eslint/scope-manager/-/scope-manager-8.27.0.tgz", - "integrity": "sha512-8oI9GwPMQmBryaaxG1tOZdxXVeMDte6NyJA4i7/TWa4fBwgnAXYlIQP+uYOeqAaLJ2JRxlG9CAyL+C+YE9Xknw==", + "version": "8.31.0", + "resolved": "https://registry.npmmirror.com/@typescript-eslint/scope-manager/-/scope-manager-8.31.0.tgz", + "integrity": "sha512-knO8UyF78Nt8O/B64i7TlGXod69ko7z6vJD9uhSlm0qkAbGeRUSudcm0+K/4CrRjrpiHfBCjMWlc08Vav1xwcw==", "dev": true, "dependencies": { - "@typescript-eslint/types": "8.27.0", - "@typescript-eslint/visitor-keys": "8.27.0" + "@typescript-eslint/types": "8.31.0", + "@typescript-eslint/visitor-keys": "8.31.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -3331,13 +3512,13 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "8.27.0", - "resolved": "https://registry.npmmirror.com/@typescript-eslint/type-utils/-/type-utils-8.27.0.tgz", - "integrity": "sha512-wVArTVcz1oJOIEJxui/nRhV0TXzD/zMSOYi/ggCfNq78EIszddXcJb7r4RCp/oBrjt8n9A0BSxRMKxHftpDxDA==", + "version": "8.31.0", + "resolved": "https://registry.npmmirror.com/@typescript-eslint/type-utils/-/type-utils-8.31.0.tgz", + "integrity": "sha512-DJ1N1GdjI7IS7uRlzJuEDCgDQix3ZVYVtgeWEyhyn4iaoitpMBX6Ndd488mXSx0xah/cONAkEaYyylDyAeHMHg==", "dev": true, "dependencies": { - "@typescript-eslint/typescript-estree": "8.27.0", - "@typescript-eslint/utils": "8.27.0", + "@typescript-eslint/typescript-estree": "8.31.0", + "@typescript-eslint/utils": "8.31.0", "debug": "^4.3.4", "ts-api-utils": "^2.0.1" }, @@ -3354,9 +3535,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "8.27.0", - "resolved": "https://registry.npmmirror.com/@typescript-eslint/types/-/types-8.27.0.tgz", - "integrity": "sha512-/6cp9yL72yUHAYq9g6DsAU+vVfvQmd1a8KyA81uvfDE21O2DwQ/qxlM4AR8TSdAu+kJLBDrEHKC5/W2/nxsY0A==", + "version": "8.31.0", + "resolved": "https://registry.npmmirror.com/@typescript-eslint/types/-/types-8.31.0.tgz", + "integrity": "sha512-Ch8oSjVyYyJxPQk8pMiP2FFGYatqXQfQIaMp+TpuuLlDachRWpUAeEu1u9B/v/8LToehUIWyiKcA/w5hUFRKuQ==", "dev": true, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -3367,13 +3548,13 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.27.0", - "resolved": "https://registry.npmmirror.com/@typescript-eslint/typescript-estree/-/typescript-estree-8.27.0.tgz", - "integrity": "sha512-BnKq8cqPVoMw71O38a1tEb6iebEgGA80icSxW7g+kndx0o6ot6696HjG7NdgfuAVmVEtwXUr3L8R9ZuVjoQL6A==", + "version": "8.31.0", + "resolved": "https://registry.npmmirror.com/@typescript-eslint/typescript-estree/-/typescript-estree-8.31.0.tgz", + "integrity": "sha512-xLmgn4Yl46xi6aDSZ9KkyfhhtnYI15/CvHbpOy/eR5NWhK/BK8wc709KKwhAR0m4ZKRP7h07bm4BWUYOCuRpQQ==", "dev": true, "dependencies": { - "@typescript-eslint/types": "8.27.0", - "@typescript-eslint/visitor-keys": "8.27.0", + "@typescript-eslint/types": "8.31.0", + "@typescript-eslint/visitor-keys": "8.31.0", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", @@ -3393,15 +3574,15 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "8.27.0", - "resolved": "https://registry.npmmirror.com/@typescript-eslint/utils/-/utils-8.27.0.tgz", - "integrity": "sha512-njkodcwH1yvmo31YWgRHNb/x1Xhhq4/m81PhtvmRngD8iHPehxffz1SNCO+kwaePhATC+kOa/ggmvPoPza5i0Q==", + "version": "8.31.0", + "resolved": "https://registry.npmmirror.com/@typescript-eslint/utils/-/utils-8.31.0.tgz", + "integrity": "sha512-qi6uPLt9cjTFxAb1zGNgTob4x9ur7xC6mHQJ8GwEzGMGE9tYniublmJaowOJ9V2jUzxrltTPfdG2nKlWsq0+Ww==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "8.27.0", - "@typescript-eslint/types": "8.27.0", - "@typescript-eslint/typescript-estree": "8.27.0" + "@typescript-eslint/scope-manager": "8.31.0", + "@typescript-eslint/types": "8.31.0", + "@typescript-eslint/typescript-estree": "8.31.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -3416,12 +3597,12 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.27.0", - "resolved": "https://registry.npmmirror.com/@typescript-eslint/visitor-keys/-/visitor-keys-8.27.0.tgz", - "integrity": "sha512-WsXQwMkILJvffP6z4U3FYJPlbf/j07HIxmDjZpbNvBJkMfvwXj5ACRkkHwBDvLBbDbtX5TdU64/rcvKJ/vuInQ==", + "version": "8.31.0", + "resolved": "https://registry.npmmirror.com/@typescript-eslint/visitor-keys/-/visitor-keys-8.31.0.tgz", + "integrity": "sha512-QcGHmlRHWOl93o64ZUMNewCdwKGU6WItOU52H0djgNmn1EOrhVudrDzXz4OycCRSCPwFCDrE2iIt5vmuUdHxuQ==", "dev": true, "dependencies": { - "@typescript-eslint/types": "8.27.0", + "@typescript-eslint/types": "8.31.0", "eslint-visitor-keys": "^4.2.0" }, "engines": { @@ -3464,16 +3645,16 @@ "dev": true }, "node_modules/@vitejs/plugin-legacy": { - "version": "6.0.2", - "resolved": "https://registry.npmmirror.com/@vitejs/plugin-legacy/-/plugin-legacy-6.0.2.tgz", - "integrity": "sha512-b/a6ARuJ1yCoIH/lSjpwPMyqo3NSCoqyxYtff7VCC6cnJfvBTzd7PthcrbomhLZnMsp/eW41b6TrbNSQvHW2lA==", + "version": "6.1.0", + "resolved": "https://registry.npmmirror.com/@vitejs/plugin-legacy/-/plugin-legacy-6.1.0.tgz", + "integrity": "sha512-D5/33NZFBDdlXvCoRbdGe3DcnSY4TZIDkQpolbMdMXBtUNgwJc03X1LHmEov4Igi4f5z2l9/lC0te74R8iHn5A==", "dev": true, "dependencies": { - "@babel/core": "^7.26.9", + "@babel/core": "^7.26.10", "@babel/preset-env": "^7.26.9", "browserslist": "^4.24.4", "browserslist-to-esbuild": "^2.1.1", - "core-js": "^3.40.0", + "core-js": "^3.41.0", "magic-string": "^0.30.17", "regenerator-runtime": "^0.14.1", "systemjs": "^6.15.1" @@ -3490,16 +3671,16 @@ } }, "node_modules/@vitejs/plugin-react": { - "version": "4.3.4", - "resolved": "https://registry.npmmirror.com/@vitejs/plugin-react/-/plugin-react-4.3.4.tgz", - "integrity": "sha512-SCCPBJtYLdE8PX/7ZQAs1QAZ8Jqwih+0VBLum1EGqmCCQal+MIUqLCzj3ZUy8ufbC0cAM4LRlSTm7IQJwWT4ug==", + "version": "4.4.1", + "resolved": "https://registry.npmmirror.com/@vitejs/plugin-react/-/plugin-react-4.4.1.tgz", + "integrity": "sha512-IpEm5ZmeXAP/osiBXVVP5KjFMzbWOonMs0NaQQl+xYnUAcq4oHUBsF2+p4MgKWG4YMmFYJU8A6sxRPuowllm6w==", "dev": true, "dependencies": { - "@babel/core": "^7.26.0", + "@babel/core": "^7.26.10", "@babel/plugin-transform-react-jsx-self": "^7.25.9", "@babel/plugin-transform-react-jsx-source": "^7.25.9", "@types/babel__core": "^7.20.5", - "react-refresh": "^0.14.2" + "react-refresh": "^0.17.0" }, "engines": { "node": "^14.18.0 || >=16.0.0" @@ -3585,9 +3766,9 @@ } }, "node_modules/antd": { - "version": "5.24.4", - "resolved": "https://registry.npmmirror.com/antd/-/antd-5.24.4.tgz", - "integrity": "sha512-s89666DcoWeekJFaIqbtz2vRlIvgPR28GuDYYGUpW1mVP08bV7HZAPBH5lFJKYNGKrN3dHbZGgRK5aNRD2iPHg==", + "version": "5.24.8", + "resolved": "https://registry.npmmirror.com/antd/-/antd-5.24.8.tgz", + "integrity": "sha512-vJcW81WSRq+ymBKTiA3NE+FddmiqTAKxdWVRZU+HnLLrRrIz896svcUxXFPa7M4mH9HqyeJ5JPOHsne4sQAC1A==", "dependencies": { "@ant-design/colors": "^7.2.0", "@ant-design/cssinjs": "^1.23.0", @@ -3611,13 +3792,13 @@ "rc-drawer": "~7.2.0", "rc-dropdown": "~4.2.1", "rc-field-form": "~2.7.0", - "rc-image": "~7.11.0", - "rc-input": "~1.7.3", - "rc-input-number": "~9.4.0", - "rc-mentions": "~2.19.1", + "rc-image": "~7.11.1", + "rc-input": "~1.8.0", + "rc-input-number": "~9.5.0", + "rc-mentions": "~2.20.0", "rc-menu": "~9.16.1", "rc-motion": "^2.9.5", - "rc-notification": "~5.6.3", + "rc-notification": "~5.6.4", "rc-pagination": "~5.1.0", "rc-picker": "~4.11.3", "rc-progress": "~4.0.0", @@ -3629,8 +3810,8 @@ "rc-steps": "~6.0.1", "rc-switch": "~4.1.0", "rc-table": "~7.50.4", - "rc-tabs": "~15.5.1", - "rc-textarea": "~1.9.0", + "rc-tabs": "~15.6.0", + "rc-textarea": "~1.10.0", "rc-tooltip": "~6.4.0", "rc-tree": "~5.13.1", "rc-tree-select": "~5.27.0", @@ -3649,9 +3830,9 @@ } }, "node_modules/antd-zod": { - "version": "6.0.1", - "resolved": "https://registry.npmmirror.com/antd-zod/-/antd-zod-6.0.1.tgz", - "integrity": "sha512-O4cEUq2p/DOwmpZYtPHbrie1CzcvhJKeN/bDOtfostjcFRz3E/HgINqALZeNaT68X+hqcXxhnxjwIHhxb+oaWw==", + "version": "6.1.0", + "resolved": "https://registry.npmmirror.com/antd-zod/-/antd-zod-6.1.0.tgz", + "integrity": "sha512-7gXf5NgZO9MRrn54dQVmSDujGuY9YgV6jmE4sOKw4MuFu+YgYPrk0oAEiRTZ9DveCyyZ1krurOwsXJJGuDJ3IQ==", "dependencies": { "lodash.merge": "^4.6.2" }, @@ -3660,6 +3841,25 @@ "zod": ">=3.0.0" } }, + "node_modules/antd/node_modules/@ant-design/icons": { + "version": "5.6.1", + "resolved": "https://registry.npmmirror.com/@ant-design/icons/-/icons-5.6.1.tgz", + "integrity": "sha512-0/xS39c91WjPAZOWsvi1//zjx6kAp4kxWwctR6kuU6p133w8RU0D2dSCvZC19uQyharg/sAvYxGYWl01BbZZfg==", + "dependencies": { + "@ant-design/colors": "^7.0.0", + "@ant-design/icons-svg": "^4.4.0", + "@babel/runtime": "^7.24.8", + "classnames": "^2.2.6", + "rc-util": "^5.31.1" + }, + "engines": { + "node": ">=8" + }, + "peerDependencies": { + "react": ">=16.0.0", + "react-dom": ">=16.0.0" + } + }, "node_modules/any-promise": { "version": "1.3.0", "resolved": "https://registry.npmmirror.com/any-promise/-/any-promise-1.3.0.tgz", @@ -4177,9 +4377,9 @@ } }, "node_modules/core-js": { - "version": "3.40.0", - "resolved": "https://registry.npmmirror.com/core-js/-/core-js-3.40.0.tgz", - "integrity": "sha512-7vsMc/Lty6AGnn7uFpYT56QesI5D2Y/UkgKounk87OP9Z2H9Z8kj6jzcSGAxFmUtDOS0ntK6lbQz+Nsa0Jj6mQ==", + "version": "3.41.0", + "resolved": "https://registry.npmmirror.com/core-js/-/core-js-3.41.0.tgz", + "integrity": "sha512-SJ4/EHwS36QMJd6h/Rg+GyR4A5xE0FSI3eZ+iBVpfqf1x0eTSg1smWLHrA+2jQThZSh97fmSgFSU8B61nxosxA==", "dev": true, "hasInstallScript": true, "funding": { @@ -4201,11 +4401,11 @@ } }, "node_modules/cron-parser": { - "version": "5.0.6", - "resolved": "https://registry.npmmirror.com/cron-parser/-/cron-parser-5.0.6.tgz", - "integrity": "sha512-KtZxEaO4XtQwQ6q2Val3gX09TxM/1Okz0BIqkm6Wwc582gAHTnjBP1rtYEgWcVOUPRIg2CeirOTiUSu7A2I+HQ==", + "version": "5.1.1", + "resolved": "https://registry.npmmirror.com/cron-parser/-/cron-parser-5.1.1.tgz", + "integrity": "sha512-xNhwjTUTJcvevF4EvOxB3xYpEKC/qOAmykR+2Qf91ARIfdbjStUwo8qpem6jjzdwFgoo4pnf3sS264xG0G858w==", "dependencies": { - "luxon": "^3.5.0" + "luxon": "^3.6.1" }, "engines": { "node": ">=18" @@ -4670,9 +4870,9 @@ } }, "node_modules/eslint-config-prettier": { - "version": "10.1.1", - "resolved": "https://registry.npmmirror.com/eslint-config-prettier/-/eslint-config-prettier-10.1.1.tgz", - "integrity": "sha512-4EQQr6wXwS+ZJSzaR5ZCrYgLxqvUjdXctaEtBqHcbkW944B1NQyO4qpdHQbXBONfwxXdkAY81HH4+LUfrg+zPw==", + "version": "10.1.2", + "resolved": "https://registry.npmmirror.com/eslint-config-prettier/-/eslint-config-prettier-10.1.2.tgz", + "integrity": "sha512-Epgp/EofAUeEpIdZkW60MHKvPyru1ruQJxPL+WIycnaPApuseK0Zpkrh/FwL9oIpQvIhJwV7ptOy0DWUjTlCiA==", "dev": true, "bin": { "eslint-config-prettier": "bin/cli.js" @@ -4847,13 +5047,13 @@ } }, "node_modules/eslint-plugin-prettier": { - "version": "5.2.3", - "resolved": "https://registry.npmmirror.com/eslint-plugin-prettier/-/eslint-plugin-prettier-5.2.3.tgz", - "integrity": "sha512-qJ+y0FfCp/mQYQ/vWQ3s7eUlFEL4PyKfAJxsnYTJ4YT73nsJBWqmEpFryxV9OeUiqmsTsYJ5Y+KDNaeP31wrRw==", + "version": "5.2.6", + "resolved": "https://registry.npmmirror.com/eslint-plugin-prettier/-/eslint-plugin-prettier-5.2.6.tgz", + "integrity": "sha512-mUcf7QG2Tjk7H055Jk0lGBjbgDnfrvqjhXh9t2xLMSCjZVcw9Rb1V6sVNXO0th3jgeO7zllWPTNRil3JW94TnQ==", "dev": true, "dependencies": { "prettier-linter-helpers": "^1.0.0", - "synckit": "^0.9.1" + "synckit": "^0.11.0" }, "engines": { "node": "^14.18.0 || >=16.0.0" @@ -4864,7 +5064,7 @@ "peerDependencies": { "@types/eslint": ">=8.0.0", "eslint": ">=8.0.0", - "eslint-config-prettier": "*", + "eslint-config-prettier": ">= 7.0.0 <10.0.0 || >=10.1.0", "prettier": ">=3.0.0" }, "peerDependenciesMeta": { @@ -4889,9 +5089,9 @@ } }, "node_modules/eslint-plugin-react-refresh": { - "version": "0.4.19", - "resolved": "https://registry.npmmirror.com/eslint-plugin-react-refresh/-/eslint-plugin-react-refresh-0.4.19.tgz", - "integrity": "sha512-eyy8pcr/YxSYjBoqIFSrlbn9i/xvxUFa8CjzAYo9cFjgGXqq1hyjihcpZvxRLalpaWmueWR81xn7vuKmAFijDQ==", + "version": "0.4.20", + "resolved": "https://registry.npmmirror.com/eslint-plugin-react-refresh/-/eslint-plugin-react-refresh-0.4.20.tgz", + "integrity": "sha512-XpbHQ2q5gUF8BGOX4dHe+71qoirYMhApEPZ7sfhF/dNnOF1UXnCMGZf79SFTBO7Bz5YEIT4TMieSlJBWhP9WBA==", "dev": true, "peerDependencies": { "eslint": ">=8.40" @@ -5608,9 +5808,9 @@ } }, "node_modules/i18next": { - "version": "24.2.3", - "resolved": "https://registry.npmmirror.com/i18next/-/i18next-24.2.3.tgz", - "integrity": "sha512-lfbf80OzkocvX7nmZtu7nSTNbrTYR52sLWxPtlXX1zAhVw8WEnFk4puUkCR4B1dNQwbSpEHHHemcZu//7EcB7A==", + "version": "25.0.1", + "resolved": "https://registry.npmmirror.com/i18next/-/i18next-25.0.1.tgz", + "integrity": "sha512-8S8PyZbrymJZn3DaN70/34JYWNhsqrU6yA4MuzcygJBv+41dgNMocEA8h+kV1P7MCc1ll03lOTOIXE7mpNCicw==", "funding": [ { "type": "individual", @@ -5638,9 +5838,9 @@ } }, "node_modules/i18next-browser-languagedetector": { - "version": "8.0.4", - "resolved": "https://registry.npmmirror.com/i18next-browser-languagedetector/-/i18next-browser-languagedetector-8.0.4.tgz", - "integrity": "sha512-f3frU3pIxD50/Tz20zx9TD9HobKYg47fmAETb117GKGPrhwcSSPJDoCposXlVycVebQ9GQohC3Efbpq7/nnJ5w==", + "version": "8.0.5", + "resolved": "https://registry.npmmirror.com/i18next-browser-languagedetector/-/i18next-browser-languagedetector-8.0.5.tgz", + "integrity": "sha512-OstebRKqKiQw8xEvQF5aRyUujsCatanj7Q9eo5iiH2gJpoXGZ7483ol3sVBwfqbobTQPNH1J+NAyJ1aCQoEC+w==", "dependencies": { "@babel/runtime": "^7.23.2" } @@ -6324,17 +6524,17 @@ } }, "node_modules/lucide-react": { - "version": "0.483.0", - "resolved": "https://registry.npmmirror.com/lucide-react/-/lucide-react-0.483.0.tgz", - "integrity": "sha512-WldsY17Qb/T3VZdMnVQ9C3DDIP7h1ViDTHVdVGnLZcvHNg30zH/MTQ04RTORjexoGmpsXroiQXZ4QyR0kBy0FA==", + "version": "0.503.0", + "resolved": "https://registry.npmmirror.com/lucide-react/-/lucide-react-0.503.0.tgz", + "integrity": "sha512-HGGkdlPWQ0vTF8jJ5TdIqhQXZi6uh3LnNgfZ8MHiuxFfX3RZeA79r2MW2tHAZKlAVfoNE8esm3p+O6VkIvpj6w==", "peerDependencies": { "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "node_modules/luxon": { - "version": "3.5.0", - "resolved": "https://registry.npmmirror.com/luxon/-/luxon-3.5.0.tgz", - "integrity": "sha512-rh+Zjr6DNfUYR3bPwJEnuwDdqMbxZW7LOQfUN4B54+Cl+0o5zaU9RJ6bcidfDtC1cWCZXQ+nvX8bf6bAji37QQ==", + "version": "3.6.1", + "resolved": "https://registry.npmmirror.com/luxon/-/luxon-3.6.1.tgz", + "integrity": "sha512-tJLxrKJhO2ukZ5z0gyjY1zPh3Rh88Ej9P7jNrZiHMUXHae1yvI2imgOZtL1TO8TW6biMMKfTtAOoEJANgtWBMQ==", "engines": { "node": ">=12" } @@ -6787,9 +6987,9 @@ } }, "node_modules/pocketbase": { - "version": "0.25.2", - "resolved": "https://registry.npmmirror.com/pocketbase/-/pocketbase-0.25.2.tgz", - "integrity": "sha512-ONZl1+qHJMnhR2uacBlBJ90lm7njtL/zy0606+1ROfK9hSL4LRBRc8r89rMcNRzPzRqCNyoFTh2Qg/lYXdEC1w==" + "version": "0.26.0", + "resolved": "https://registry.npmmirror.com/pocketbase/-/pocketbase-0.26.0.tgz", + "integrity": "sha512-WBBeOgz4Jnrd7a1KEzSBUJqpTortKKCcp16j5KoF+4tNIyQHsmynj+qRSvS56/RVacVMbAqO8Qkfj3N84fpzEw==" }, "node_modules/possible-typed-array-names": { "version": "1.0.0", @@ -7159,9 +7359,9 @@ } }, "node_modules/rc-image": { - "version": "7.11.0", - "resolved": "https://registry.npmmirror.com/rc-image/-/rc-image-7.11.0.tgz", - "integrity": "sha512-aZkTEZXqeqfPZtnSdNUnKQA0N/3MbgR7nUnZ+/4MfSFWPFHZau4p5r5ShaI0KPEMnNjv4kijSCFq/9wtJpwykw==", + "version": "7.11.1", + "resolved": "https://registry.npmmirror.com/rc-image/-/rc-image-7.11.1.tgz", + "integrity": "sha512-XuoWx4KUXg7hNy5mRTy1i8c8p3K8boWg6UajbHpDXS5AlRVucNfTi5YxTtPBTBzegxAZpvuLfh3emXFt6ybUdA==", "dependencies": { "@babel/runtime": "^7.11.2", "@rc-component/portal": "^1.0.2", @@ -7176,9 +7376,9 @@ } }, "node_modules/rc-input": { - "version": "1.7.3", - "resolved": "https://registry.npmmirror.com/rc-input/-/rc-input-1.7.3.tgz", - "integrity": "sha512-A5w4egJq8+4JzlQ55FfQjDnPvOaAbzwC3VLOAdOytyek3TboSOP9qxN+Gifup+shVXfvecBLBbWBpWxmk02SWQ==", + "version": "1.8.0", + "resolved": "https://registry.npmmirror.com/rc-input/-/rc-input-1.8.0.tgz", + "integrity": "sha512-KXvaTbX+7ha8a/k+eg6SYRVERK0NddX8QX7a7AnRvUa/rEH0CNMlpcBzBkhI0wp2C8C4HlMoYl8TImSN+fuHKA==", "dependencies": { "@babel/runtime": "^7.11.1", "classnames": "^2.2.1", @@ -7190,14 +7390,14 @@ } }, "node_modules/rc-input-number": { - "version": "9.4.0", - "resolved": "https://registry.npmmirror.com/rc-input-number/-/rc-input-number-9.4.0.tgz", - "integrity": "sha512-Tiy4DcXcFXAf9wDhN8aUAyMeCLHJUHA/VA/t7Hj8ZEx5ETvxG7MArDOSE6psbiSCo+vJPm4E3fGN710ITVn6GA==", + "version": "9.5.0", + "resolved": "https://registry.npmmirror.com/rc-input-number/-/rc-input-number-9.5.0.tgz", + "integrity": "sha512-bKaEvB5tHebUURAEXw35LDcnRZLq3x1k7GxfAqBMzmpHkDGzjAtnUL8y4y5N15rIFIg5IJgwr211jInl3cipag==", "dependencies": { "@babel/runtime": "^7.10.1", "@rc-component/mini-decimal": "^1.0.1", "classnames": "^2.2.5", - "rc-input": "~1.7.1", + "rc-input": "~1.8.0", "rc-util": "^5.40.1" }, "peerDependencies": { @@ -7206,16 +7406,16 @@ } }, "node_modules/rc-mentions": { - "version": "2.19.1", - "resolved": "https://registry.npmmirror.com/rc-mentions/-/rc-mentions-2.19.1.tgz", - "integrity": "sha512-KK3bAc/bPFI993J3necmaMXD2reZTzytZdlTvkeBbp50IGH1BDPDvxLdHDUrpQx2b2TGaVJsn+86BvYa03kGqA==", + "version": "2.20.0", + "resolved": "https://registry.npmmirror.com/rc-mentions/-/rc-mentions-2.20.0.tgz", + "integrity": "sha512-w8HCMZEh3f0nR8ZEd466ATqmXFCMGMN5UFCzEUL0bM/nGw/wOS2GgRzKBcm19K++jDyuWCOJOdgcKGXU3fXfbQ==", "dependencies": { "@babel/runtime": "^7.22.5", "@rc-component/trigger": "^2.0.0", "classnames": "^2.2.6", - "rc-input": "~1.7.1", + "rc-input": "~1.8.0", "rc-menu": "~9.16.0", - "rc-textarea": "~1.9.0", + "rc-textarea": "~1.10.0", "rc-util": "^5.34.1" }, "peerDependencies": { @@ -7255,9 +7455,9 @@ } }, "node_modules/rc-notification": { - "version": "5.6.3", - "resolved": "https://registry.npmmirror.com/rc-notification/-/rc-notification-5.6.3.tgz", - "integrity": "sha512-42szwnn8VYQoT6GnjO00i1iwqV9D1TTMvxObWsuLwgl0TsOokzhkYiufdtQBsJMFjJravS1hfDKVMHLKLcPE4g==", + "version": "5.6.4", + "resolved": "https://registry.npmmirror.com/rc-notification/-/rc-notification-5.6.4.tgz", + "integrity": "sha512-KcS4O6B4qzM3KH7lkwOB7ooLPZ4b6J+VMmQgT51VZCeEcmghdeR4IrMcFq0LG+RPdnbe/ArT086tGM8Snimgiw==", "dependencies": { "@babel/runtime": "^7.10.1", "classnames": "2.x", @@ -7490,9 +7690,9 @@ } }, "node_modules/rc-tabs": { - "version": "15.5.1", - "resolved": "https://registry.npmmirror.com/rc-tabs/-/rc-tabs-15.5.1.tgz", - "integrity": "sha512-yiWivLAjEo5d1v2xlseB2dQocsOhkoVSfo1krS8v8r+02K+TBUjSjXIf7dgyVSxp6wRIPv5pMi5hanNUlQMgUA==", + "version": "15.6.0", + "resolved": "https://registry.npmmirror.com/rc-tabs/-/rc-tabs-15.6.0.tgz", + "integrity": "sha512-SQ99Yjc9ewrJCUwoWPKq0FeGL2znWsqPhfcZgsHz1R7bkA2rMNe7CPgOiJkwppdJ98wkLhzs9vPrv21QOE1RyQ==", "dependencies": { "@babel/runtime": "^7.11.2", "classnames": "2.x", @@ -7511,13 +7711,13 @@ } }, "node_modules/rc-textarea": { - "version": "1.9.0", - "resolved": "https://registry.npmmirror.com/rc-textarea/-/rc-textarea-1.9.0.tgz", - "integrity": "sha512-dQW/Bc/MriPBTugj2Kx9PMS5eXCCGn2cxoIaichjbNvOiARlaHdI99j4DTxLl/V8+PIfW06uFy7kjfUIDDKyxQ==", + "version": "1.10.0", + "resolved": "https://registry.npmmirror.com/rc-textarea/-/rc-textarea-1.10.0.tgz", + "integrity": "sha512-ai9IkanNuyBS4x6sOL8qu/Ld40e6cEs6pgk93R+XLYg0mDSjNBGey6/ZpDs5+gNLD7urQ14po3V6Ck2dJLt9SA==", "dependencies": { "@babel/runtime": "^7.10.1", "classnames": "^2.2.1", - "rc-input": "~1.7.1", + "rc-input": "~1.8.0", "rc-resize-observer": "^1.0.0", "rc-util": "^5.27.0" }, @@ -7693,20 +7893,19 @@ "integrity": "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==" }, "node_modules/react-refresh": { - "version": "0.14.2", - "resolved": "https://registry.npmmirror.com/react-refresh/-/react-refresh-0.14.2.tgz", - "integrity": "sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA==", + "version": "0.17.0", + "resolved": "https://registry.npmmirror.com/react-refresh/-/react-refresh-0.17.0.tgz", + "integrity": "sha512-z6F7K9bV85EfseRCp2bzrpyQ0Gkw1uLoCel9XBVWPg/TjRj94SkJzUTGfOa4bs7iJvBWtQG0Wq7wnI0syw3EBQ==", "dev": true, "engines": { "node": ">=0.10.0" } }, "node_modules/react-router": { - "version": "7.4.0", - "resolved": "https://registry.npmmirror.com/react-router/-/react-router-7.4.0.tgz", - "integrity": "sha512-Y2g5ObjkvX3VFeVt+0CIPuYd9PpgqCslG7ASSIdN73LwA1nNWzcMLaoMRJfP3prZFI92svxFwbn7XkLJ+UPQ6A==", + "version": "7.5.1", + "resolved": "https://registry.npmmirror.com/react-router/-/react-router-7.5.1.tgz", + "integrity": "sha512-/jjU3fcYNd2bwz9Q0xt5TwyiyoO8XjSEFXJY4O/lMAlkGTHWuHRAbR9Etik+lSDqMC7A7mz3UlXzgYT6Vl58sA==", "dependencies": { - "@types/cookie": "^0.6.0", "cookie": "^1.0.1", "set-cookie-parser": "^2.6.0", "turbo-stream": "2.4.0" @@ -7725,11 +7924,11 @@ } }, "node_modules/react-router-dom": { - "version": "7.4.0", - "resolved": "https://registry.npmmirror.com/react-router-dom/-/react-router-dom-7.4.0.tgz", - "integrity": "sha512-VlksBPf3n2bijPvnA7nkTsXxMAKOj+bWp4R9c3i+bnwlSOFAGOkJkKhzy/OsRkWaBMICqcAl1JDzh9ZSOze9CA==", + "version": "7.5.1", + "resolved": "https://registry.npmmirror.com/react-router-dom/-/react-router-dom-7.5.1.tgz", + "integrity": "sha512-5DPSPc7ENrt2tlKPq0FtpG80ZbqA9aIKEyqX6hSNJDlol/tr6iqCK4crqdsusmOSSotq6zDsn0y3urX9TuTNmA==", "dependencies": { - "react-router": "7.4.0" + "react-router": "7.5.1" }, "engines": { "node": ">=20.0.0" @@ -7954,12 +8153,12 @@ } }, "node_modules/rollup": { - "version": "4.34.6", - "resolved": "https://registry.npmmirror.com/rollup/-/rollup-4.34.6.tgz", - "integrity": "sha512-wc2cBWqJgkU3Iz5oztRkQbfVkbxoz5EhnCGOrnJvnLnQ7O0WhQUYyv18qQI79O8L7DdHrrlJNeCHd4VGpnaXKQ==", + "version": "4.40.0", + "resolved": "https://registry.npmmirror.com/rollup/-/rollup-4.40.0.tgz", + "integrity": "sha512-Noe455xmA96nnqH5piFtLobsGbCij7Tu+tb3c1vYjNbTkfzGqXqQXG3wJaYXkRZuQ0vEYN4bhwg7QnIrqB5B+w==", "dev": true, "dependencies": { - "@types/estree": "1.0.6" + "@types/estree": "1.0.7" }, "bin": { "rollup": "dist/bin/rollup" @@ -7969,25 +8168,26 @@ "npm": ">=8.0.0" }, "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.34.6", - "@rollup/rollup-android-arm64": "4.34.6", - "@rollup/rollup-darwin-arm64": "4.34.6", - "@rollup/rollup-darwin-x64": "4.34.6", - "@rollup/rollup-freebsd-arm64": "4.34.6", - "@rollup/rollup-freebsd-x64": "4.34.6", - "@rollup/rollup-linux-arm-gnueabihf": "4.34.6", - "@rollup/rollup-linux-arm-musleabihf": "4.34.6", - "@rollup/rollup-linux-arm64-gnu": "4.34.6", - "@rollup/rollup-linux-arm64-musl": "4.34.6", - "@rollup/rollup-linux-loongarch64-gnu": "4.34.6", - "@rollup/rollup-linux-powerpc64le-gnu": "4.34.6", - "@rollup/rollup-linux-riscv64-gnu": "4.34.6", - "@rollup/rollup-linux-s390x-gnu": "4.34.6", - "@rollup/rollup-linux-x64-gnu": "4.34.6", - "@rollup/rollup-linux-x64-musl": "4.34.6", - "@rollup/rollup-win32-arm64-msvc": "4.34.6", - "@rollup/rollup-win32-ia32-msvc": "4.34.6", - "@rollup/rollup-win32-x64-msvc": "4.34.6", + "@rollup/rollup-android-arm-eabi": "4.40.0", + "@rollup/rollup-android-arm64": "4.40.0", + "@rollup/rollup-darwin-arm64": "4.40.0", + "@rollup/rollup-darwin-x64": "4.40.0", + "@rollup/rollup-freebsd-arm64": "4.40.0", + "@rollup/rollup-freebsd-x64": "4.40.0", + "@rollup/rollup-linux-arm-gnueabihf": "4.40.0", + "@rollup/rollup-linux-arm-musleabihf": "4.40.0", + "@rollup/rollup-linux-arm64-gnu": "4.40.0", + "@rollup/rollup-linux-arm64-musl": "4.40.0", + "@rollup/rollup-linux-loongarch64-gnu": "4.40.0", + "@rollup/rollup-linux-powerpc64le-gnu": "4.40.0", + "@rollup/rollup-linux-riscv64-gnu": "4.40.0", + "@rollup/rollup-linux-riscv64-musl": "4.40.0", + "@rollup/rollup-linux-s390x-gnu": "4.40.0", + "@rollup/rollup-linux-x64-gnu": "4.40.0", + "@rollup/rollup-linux-x64-musl": "4.40.0", + "@rollup/rollup-win32-arm64-msvc": "4.40.0", + "@rollup/rollup-win32-ia32-msvc": "4.40.0", + "@rollup/rollup-win32-x64-msvc": "4.40.0", "fsevents": "~2.3.2" } }, @@ -8540,9 +8740,9 @@ } }, "node_modules/swr": { - "version": "2.3.2", - "resolved": "https://registry.npmmirror.com/swr/-/swr-2.3.2.tgz", - "integrity": "sha512-RosxFpiabojs75IwQ316DGoDRmOqtiAj0tg8wCcbEu4CiLZBs/a9QNtHV7TUfDXmmlgqij/NqzKq/eLelyv9xA==", + "version": "2.3.3", + "resolved": "https://registry.npmmirror.com/swr/-/swr-2.3.3.tgz", + "integrity": "sha512-dshNvs3ExOqtZ6kJBaAsabhPdHyeY4P2cKwRCniDVifBMoG/SVI7tfLWqPXriVspf2Rg4tPzXJTnwaihIeFw2A==", "dependencies": { "dequal": "^2.0.3", "use-sync-external-store": "^1.4.0" @@ -8552,19 +8752,19 @@ } }, "node_modules/synckit": { - "version": "0.9.2", - "resolved": "https://registry.npmmirror.com/synckit/-/synckit-0.9.2.tgz", - "integrity": "sha512-vrozgXDQwYO72vHjUb/HnFbQx1exDjoKzqx23aXEg2a9VIg2TSFZ8FmeZpTjUCFMYw7mpX4BE2SFu8wI7asYsw==", + "version": "0.11.4", + "resolved": "https://registry.npmmirror.com/synckit/-/synckit-0.11.4.tgz", + "integrity": "sha512-Q/XQKRaJiLiFIBNN+mndW7S/RHxvwzuZS6ZwmRzUBqJBv/5QIKCEwkBC8GBf8EQJKYnaFs0wOZbKTXBPj8L9oQ==", "dev": true, "dependencies": { - "@pkgr/core": "^0.1.0", - "tslib": "^2.6.2" + "@pkgr/core": "^0.2.3", + "tslib": "^2.8.1" }, "engines": { "node": "^14.18.0 || >=16.0.0" }, "funding": { - "url": "https://opencollective.com/unts" + "url": "https://opencollective.com/synckit" } }, "node_modules/systemjs": { @@ -8805,9 +9005,9 @@ } }, "node_modules/tslib": { - "version": "2.6.3", - "resolved": "https://registry.npmmirror.com/tslib/-/tslib-2.6.3.tgz", - "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==" + "version": "2.8.1", + "resolved": "https://registry.npmmirror.com/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==" }, "node_modules/turbo-stream": { "version": "2.4.0", @@ -8913,9 +9113,9 @@ } }, "node_modules/typescript": { - "version": "5.8.2", - "resolved": "https://registry.npmmirror.com/typescript/-/typescript-5.8.2.tgz", - "integrity": "sha512-aJn6wq13/afZp/jT9QZmwEjDqqvSGp1VT5GVg+f/t6/oVyrgXM6BY1h9BRh/O5p3PlUPAe+WuiEZOmb/49RqoQ==", + "version": "5.8.3", + "resolved": "https://registry.npmmirror.com/typescript/-/typescript-5.8.3.tgz", + "integrity": "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==", "devOptional": true, "bin": { "tsc": "bin/tsc", @@ -8944,9 +9144,9 @@ } }, "node_modules/undici-types": { - "version": "6.20.0", - "resolved": "https://registry.npmmirror.com/undici-types/-/undici-types-6.20.0.tgz", - "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==", + "version": "6.21.0", + "resolved": "https://registry.npmmirror.com/undici-types/-/undici-types-6.21.0.tgz", + "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", "dev": true }, "node_modules/unicode-canonical-property-names-ecmascript": { @@ -9052,14 +9252,17 @@ "dev": true }, "node_modules/vite": { - "version": "6.2.2", - "resolved": "https://registry.npmmirror.com/vite/-/vite-6.2.2.tgz", - "integrity": "sha512-yW7PeMM+LkDzc7CgJuRLMW2Jz0FxMOsVJ8Lv3gpgW9WLcb9cTW+121UEr1hvmfR7w3SegR5ItvYyzVz1vxNJgQ==", + "version": "6.3.2", + "resolved": "https://registry.npmmirror.com/vite/-/vite-6.3.2.tgz", + "integrity": "sha512-ZSvGOXKGceizRQIZSz7TGJ0pS3QLlVY/9hwxVh17W3re67je1RKYzFHivZ/t0tubU78Vkyb9WnHPENSBCzbckg==", "dev": true, "dependencies": { "esbuild": "^0.25.0", + "fdir": "^6.4.3", + "picomatch": "^4.0.2", "postcss": "^8.5.3", - "rollup": "^4.30.1" + "rollup": "^4.34.9", + "tinyglobby": "^0.2.12" }, "bin": { "vite": "bin/vite.js" @@ -9122,6 +9325,32 @@ } } }, + "node_modules/vite/node_modules/fdir": { + "version": "6.4.4", + "resolved": "https://registry.npmmirror.com/fdir/-/fdir-6.4.4.tgz", + "integrity": "sha512-1NZP+GK4GfuAv3PqKvxQRDMjdSRZjnkq7KfhlNrCNNlZ0ygQFpebfrnfnq/W7fpUnAv9aGWmY1zKx7FYL3gwhg==", + "dev": true, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/vite/node_modules/picomatch": { + "version": "4.0.2", + "resolved": "https://registry.npmmirror.com/picomatch/-/picomatch-4.0.2.tgz", + "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, "node_modules/void-elements": { "version": "3.1.0", "resolved": "https://registry.npmmirror.com/void-elements/-/void-elements-3.1.0.tgz", @@ -9416,9 +9645,9 @@ } }, "node_modules/zod": { - "version": "3.24.2", - "resolved": "https://registry.npmmirror.com/zod/-/zod-3.24.2.tgz", - "integrity": "sha512-lY7CDW43ECgW9u1TcT3IoXHflywfVqDYze4waEz812jR/bZ8FHDsl7pFQoSZTz5N+2NqRXs8GBwnAwo3ZNxqhQ==", + "version": "3.24.3", + "resolved": "https://registry.npmmirror.com/zod/-/zod-3.24.3.tgz", + "integrity": "sha512-HhY1oqzWCQWuUqvBFnsyrtZRhyPeR7SUGv+C4+MsisMuVfSPx8HpwWqH8tRahSlt6M3PiFAcoeFhZAqIXTxoSg==", "funding": { "url": "https://github.com/sponsors/colinhacks" } diff --git a/ui/package.json b/ui/package.json index d11376fe..1862c30d 100644 --- a/ui/package.json +++ b/ui/package.json @@ -10,56 +10,56 @@ "preview": "vite preview" }, "dependencies": { - "@ant-design/icons": "^5.6.1", - "@ant-design/pro-components": "^2.8.6", + "@ant-design/icons": "^6.0.0", + "@ant-design/pro-components": "^2.8.7", "ahooks": "^3.8.4", - "antd": "^5.24.4", - "antd-zod": "^6.0.1", + "antd": "^5.24.8", + "antd-zod": "^6.1.0", "clsx": "^2.1.1", - "cron-parser": "^5.0.6", + "cron-parser": "^5.1.1", "file-saver": "^2.0.5", - "i18next": "^24.2.3", - "i18next-browser-languagedetector": "^8.0.4", + "i18next": "^25.0.1", + "i18next-browser-languagedetector": "^8.0.5", "immer": "^10.1.1", - "lucide-react": "^0.483.0", + "lucide-react": "^0.503.0", "nanoid": "^5.1.5", - "pocketbase": "^0.25.2", + "pocketbase": "^0.26.0", "radash": "^12.1.0", "react": "^18.3.1", "react-copy-to-clipboard": "^5.1.0", "react-dom": "^18.3.1", "react-i18next": "^15.4.1", - "react-router-dom": "^7.4.0", + "react-router-dom": "^7.5.1", "tailwind-merge": "^2.6.0", - "zod": "^3.24.2", + "zod": "^3.24.3", "zustand": "^5.0.3" }, "devDependencies": { "@types/file-saver": "^2.0.7", "@types/fs-extra": "^11.0.4", - "@types/node": "^22.13.10", + "@types/node": "^22.14.1", "@types/react": "^18.3.12", "@types/react-copy-to-clipboard": "^5.0.7", "@types/react-dom": "^18.3.1", - "@typescript-eslint/eslint-plugin": "^8.27.0", - "@typescript-eslint/parser": "^8.27.0", - "@vitejs/plugin-legacy": "^6.0.2", - "@vitejs/plugin-react": "^4.3.4", + "@typescript-eslint/eslint-plugin": "^8.31.0", + "@typescript-eslint/parser": "^8.31.0", + "@vitejs/plugin-legacy": "^6.1.0", + "@vitejs/plugin-react": "^4.4.1", "autoprefixer": "^10.4.21", "eslint": "^8.57.0", - "eslint-config-prettier": "^10.1.1", + "eslint-config-prettier": "^10.1.2", "eslint-import-resolver-typescript": "^3.8.3", "eslint-plugin-import": "^2.31.0", - "eslint-plugin-prettier": "^5.2.3", + "eslint-plugin-prettier": "^5.2.6", "eslint-plugin-react-hooks": "^5.2.0", - "eslint-plugin-react-refresh": "^0.4.19", + "eslint-plugin-react-refresh": "^0.4.20", "eslint-plugin-tailwindcss": "^3.18.0", "fs-extra": "^11.3.0", "postcss": "^8.5.3", "prettier": "^3.5.3", "tailwindcss": "^3.4.17", "tailwindcss-animate": "^1.0.7", - "typescript": "^5.8.2", - "vite": "^6.2.2" + "typescript": "^5.8.3", + "vite": "^6.3.2" } } diff --git a/ui/public/imgs/providers/dingtalk.svg b/ui/public/imgs/providers/dingtalk.svg new file mode 100644 index 00000000..24d3881a --- /dev/null +++ b/ui/public/imgs/providers/dingtalk.svg @@ -0,0 +1 @@ + diff --git a/ui/public/imgs/providers/email.svg b/ui/public/imgs/providers/email.svg new file mode 100644 index 00000000..a74f0c41 --- /dev/null +++ b/ui/public/imgs/providers/email.svg @@ -0,0 +1 @@ + diff --git a/ui/public/imgs/providers/goedge.png b/ui/public/imgs/providers/goedge.png new file mode 100644 index 00000000..760ab333 Binary files /dev/null and b/ui/public/imgs/providers/goedge.png differ diff --git a/ui/public/imgs/providers/lark.svg b/ui/public/imgs/providers/lark.svg new file mode 100644 index 00000000..ab32e57c --- /dev/null +++ b/ui/public/imgs/providers/lark.svg @@ -0,0 +1 @@ + diff --git a/ui/public/imgs/providers/mattermost.svg b/ui/public/imgs/providers/mattermost.svg new file mode 100644 index 00000000..18cc2819 --- /dev/null +++ b/ui/public/imgs/providers/mattermost.svg @@ -0,0 +1 @@ + diff --git a/ui/public/imgs/providers/proxmoxve.svg b/ui/public/imgs/providers/proxmoxve.svg new file mode 100644 index 00000000..76e497f1 --- /dev/null +++ b/ui/public/imgs/providers/proxmoxve.svg @@ -0,0 +1 @@ + diff --git a/ui/public/imgs/providers/telegram.svg b/ui/public/imgs/providers/telegram.svg new file mode 100644 index 00000000..f4cd38c1 --- /dev/null +++ b/ui/public/imgs/providers/telegram.svg @@ -0,0 +1 @@ + diff --git a/ui/public/imgs/providers/wecom.svg b/ui/public/imgs/providers/wecom.svg new file mode 100644 index 00000000..e99e59a7 --- /dev/null +++ b/ui/public/imgs/providers/wecom.svg @@ -0,0 +1 @@ + diff --git a/ui/src/components/access/AccessEditDrawer.tsx b/ui/src/components/access/AccessEditDrawer.tsx index 48002af7..7fa2f5d8 100644 --- a/ui/src/components/access/AccessEditDrawer.tsx +++ b/ui/src/components/access/AccessEditDrawer.tsx @@ -14,14 +14,14 @@ export type AccessEditDrawerProps = { data?: AccessFormProps["initialValues"]; loading?: boolean; open?: boolean; - range?: AccessFormProps["range"]; scene: AccessFormProps["scene"]; trigger?: React.ReactNode; + usage?: AccessFormProps["usage"]; onOpenChange?: (open: boolean) => void; afterSubmit?: (record: AccessModel) => void; }; -const AccessEditDrawer = ({ data, loading, trigger, scene, range, afterSubmit, ...props }: AccessEditDrawerProps) => { +const AccessEditDrawer = ({ data, loading, trigger, scene, usage, afterSubmit, ...props }: AccessEditDrawerProps) => { const { t } = useTranslation(); const [notificationApi, NotificationContextHolder] = notification.useNotification(); @@ -109,7 +109,7 @@ const AccessEditDrawer = ({ data, loading, trigger, scene, range, afterSubmit, . width={720} onClose={() => setOpen(false)} > - + ); diff --git a/ui/src/components/access/AccessEditModal.tsx b/ui/src/components/access/AccessEditModal.tsx index 0d181877..9cfb5b0f 100644 --- a/ui/src/components/access/AccessEditModal.tsx +++ b/ui/src/components/access/AccessEditModal.tsx @@ -14,14 +14,14 @@ export type AccessEditModalProps = { data?: AccessFormProps["initialValues"]; loading?: boolean; open?: boolean; - range?: AccessFormProps["range"]; + usage?: AccessFormProps["usage"]; scene: AccessFormProps["scene"]; trigger?: React.ReactNode; onOpenChange?: (open: boolean) => void; afterSubmit?: (record: AccessModel) => void; }; -const AccessEditModal = ({ data, loading, trigger, scene, range, afterSubmit, ...props }: AccessEditModalProps) => { +const AccessEditModal = ({ data, loading, trigger, scene, usage, afterSubmit, ...props }: AccessEditModalProps) => { const { t } = useTranslation(); const [notificationApi, NotificationContextHolder] = notification.useNotification(); @@ -105,7 +105,7 @@ const AccessEditModal = ({ data, loading, trigger, scene, range, afterSubmit, .. onCancel={handleCancelClick} >
- +
diff --git a/ui/src/components/access/AccessForm.tsx b/ui/src/components/access/AccessForm.tsx index a00b0f2e..5f82ad67 100644 --- a/ui/src/components/access/AccessForm.tsx +++ b/ui/src/components/access/AccessForm.tsx @@ -25,28 +25,35 @@ import AccessFormCloudflareConfig from "./AccessFormCloudflareConfig"; import AccessFormClouDNSConfig from "./AccessFormClouDNSConfig"; import AccessFormCMCCCloudConfig from "./AccessFormCMCCCloudConfig"; import AccessFormDeSECConfig from "./AccessFormDeSECConfig"; +import AccessFormDingTalkBotConfig from "./AccessFormDingTalkBotConfig"; import AccessFormDNSLAConfig from "./AccessFormDNSLAConfig"; import AccessFormDogeCloudConfig from "./AccessFormDogeCloudConfig"; import AccessFormDynv6Config from "./AccessFormDynv6Config"; import AccessFormEdgioConfig from "./AccessFormEdgioConfig"; +import AccessFormEmailConfig from "./AccessFormEmailConfig"; import AccessFormGcoreConfig from "./AccessFormGcoreConfig"; import AccessFormGnameConfig from "./AccessFormGnameConfig"; import AccessFormGoDaddyConfig from "./AccessFormGoDaddyConfig"; +import AccessFormGoEdgeConfig from "./AccessFormGoEdgeConfig"; import AccessFormGoogleTrustServicesConfig from "./AccessFormGoogleTrustServicesConfig"; import AccessFormHuaweiCloudConfig from "./AccessFormHuaweiCloudConfig"; import AccessFormJDCloudConfig from "./AccessFormJDCloudConfig"; import AccessFormKubernetesConfig from "./AccessFormKubernetesConfig"; +import AccessFormLarkBotConfig from "./AccessFormLarkBotConfig"; +import AccessFormMattermostConfig from "./AccessFormMattermostConfig"; import AccessFormNamecheapConfig from "./AccessFormNamecheapConfig"; import AccessFormNameDotComConfig from "./AccessFormNameDotComConfig"; import AccessFormNameSiloConfig from "./AccessFormNameSiloConfig"; import AccessFormNS1Config from "./AccessFormNS1Config"; import AccessFormPorkbunConfig from "./AccessFormPorkbunConfig"; import AccessFormPowerDNSConfig from "./AccessFormPowerDNSConfig"; +import AccessFormProxmoxVEConfig from "./AccessFormProxmoxVEConfig"; import AccessFormQiniuConfig from "./AccessFormQiniuConfig"; import AccessFormRainYunConfig from "./AccessFormRainYunConfig"; import AccessFormSafeLineConfig from "./AccessFormSafeLineConfig"; import AccessFormSSHConfig from "./AccessFormSSHConfig"; import AccessFormSSLComConfig from "./AccessFormSSLComConfig"; +import AccessFormTelegramConfig from "./AccessFormTelegramConfig"; import AccessFormTencentCloudConfig from "./AccessFormTencentCloudConfig"; import AccessFormUCloudConfig from "./AccessFormUCloudConfig"; import AccessFormUpyunConfig from "./AccessFormUpyunConfig"; @@ -54,20 +61,21 @@ import AccessFormVercelConfig from "./AccessFormVercelConfig"; import AccessFormVolcEngineConfig from "./AccessFormVolcEngineConfig"; import AccessFormWangsuConfig from "./AccessFormWangsuConfig"; import AccessFormWebhookConfig from "./AccessFormWebhookConfig"; +import AccessFormWeComBotConfig from "./AccessFormWeComBotConfig"; import AccessFormWestcnConfig from "./AccessFormWestcnConfig"; import AccessFormZeroSSLConfig from "./AccessFormZeroSSLConfig"; type AccessFormFieldValues = Partial>; -type AccessFormRanges = "both-dns-hosting" | "ca-only" | "notify-only"; type AccessFormScenes = "add" | "edit"; +type AccessFormUsages = "both-dns-hosting" | "ca-only" | "notification-only"; export type AccessFormProps = { className?: string; style?: React.CSSProperties; disabled?: boolean; initialValues?: AccessFormFieldValues; - range?: AccessFormRanges; scene: AccessFormScenes; + usage?: AccessFormUsages; onValuesChange?: (values: AccessFormFieldValues) => void; }; @@ -77,7 +85,7 @@ export type AccessFormInstance = { validateFields: FormInstance["validateFields"]; }; -const AccessForm = forwardRef(({ className, style, disabled, initialValues, range, scene, onValuesChange }, ref) => { +const AccessForm = forwardRef(({ className, style, disabled, initialValues, usage, scene, onValuesChange }, ref) => { const { t } = useTranslation(); const formSchema = z.object({ @@ -88,13 +96,14 @@ const AccessForm = forwardRef(({ className, .trim(), provider: z.nativeEnum(ACCESS_PROVIDERS, { message: - range === "ca-only" + usage === "ca-only" ? t("access.form.certificate_authority.placeholder") - : range === "notify-only" + : usage === "notification-only" ? t("access.form.notification_channel.placeholder") : t("access.form.provider.placeholder"), }), config: z.any(), + reserve: z.string().nullish(), }); const formRule = createSchemaFieldRule(formSchema); const { form: formInst, formProps } = useAntdForm({ @@ -102,33 +111,33 @@ const AccessForm = forwardRef(({ className, }); const providerLabel = useMemo(() => { - switch (range) { + switch (usage) { case "ca-only": return t("access.form.certificate_authority.label"); - case "notify-only": + case "notification-only": return t("access.form.notification_channel.label"); } return t("access.form.provider.label"); - }, [range]); + }, [usage]); const providerPlaceholder = useMemo(() => { - switch (range) { + switch (usage) { case "ca-only": return t("access.form.certificate_authority.placeholder"); - case "notify-only": + case "notification-only": return t("access.form.notification_channel.placeholder"); } return t("access.form.provider.placeholder"); - }, [range]); + }, [usage]); const providerTooltip = useMemo(() => { - switch (range) { + switch (usage) { case "both-dns-hosting": return ; } return undefined; - }, [range]); + }, [usage]); const fieldProvider = Form.useWatch("provider", formInst); @@ -179,6 +188,8 @@ const AccessForm = forwardRef(({ className, return ; case ACCESS_PROVIDERS.DESEC: return ; + case ACCESS_PROVIDERS.DINGTALKBOT: + return ; case ACCESS_PROVIDERS.DNSLA: return ; case ACCESS_PROVIDERS.DOGECLOUD: @@ -191,16 +202,24 @@ const AccessForm = forwardRef(({ className, return ; case ACCESS_PROVIDERS.GODADDY: return ; + case ACCESS_PROVIDERS.GOEDGE: + return ; case ACCESS_PROVIDERS.GOOGLETRUSTSERVICES: return ; case ACCESS_PROVIDERS.EDGIO: return ; + case ACCESS_PROVIDERS.EMAIL: + return ; case ACCESS_PROVIDERS.HUAWEICLOUD: return ; case ACCESS_PROVIDERS.JDCLOUD: return ; case ACCESS_PROVIDERS.KUBERNETES: return ; + case ACCESS_PROVIDERS.LARKBOT: + return ; + case ACCESS_PROVIDERS.MATTERMOST: + return ; case ACCESS_PROVIDERS.NAMECHEAP: return ; case ACCESS_PROVIDERS.NAMEDOTCOM: @@ -213,6 +232,8 @@ const AccessForm = forwardRef(({ className, return ; case ACCESS_PROVIDERS.POWERDNS: return ; + case ACCESS_PROVIDERS.PROXMOXVE: + return ; case ACCESS_PROVIDERS.QINIU: return ; case ACCESS_PROVIDERS.RAINYUN: @@ -221,6 +242,8 @@ const AccessForm = forwardRef(({ className, return ; case ACCESS_PROVIDERS.SSH: return ; + case ACCESS_PROVIDERS.TELEGRAM: + return ; case ACCESS_PROVIDERS.SSLCOM: return ; case ACCESS_PROVIDERS.TENCENTCLOUD: @@ -236,7 +259,14 @@ const AccessForm = forwardRef(({ className, case ACCESS_PROVIDERS.WANGSU: return ; case ACCESS_PROVIDERS.WEBHOOK: - return ; + return ( + + ); + case ACCESS_PROVIDERS.WECOMBOT: + return ; case ACCESS_PROVIDERS.WESTCN: return ; case ACCESS_PROVIDERS.ZEROSSL: @@ -260,6 +290,7 @@ const AccessForm = forwardRef(({ className, getFieldsValue: () => { const values = formInst.getFieldsValue(true); values.config = nestedFormInst.getFieldsValue(); + values.reserve = usage === "ca-only" ? "ca" : usage === "notification-only" ? "notification" : undefined; return values; }, resetFields: (fields) => { @@ -288,20 +319,20 @@ const AccessForm = forwardRef(({ className, { - if (range == null) return true; + if (usage == null) return true; - switch (range) { + switch (usage) { case "both-dns-hosting": return record.usages.includes(ACCESS_USAGES.DNS) || record.usages.includes(ACCESS_USAGES.HOSTING); case "ca-only": return record.usages.includes(ACCESS_USAGES.CA); - case "notify-only": + case "notification-only": return record.usages.includes(ACCESS_USAGES.NOTIFICATION); } }} disabled={scene !== "add"} placeholder={providerPlaceholder} - showOptionTags={range == null || (range === "both-dns-hosting" ? { [ACCESS_USAGES.DNS]: true, [ACCESS_USAGES.HOSTING]: true } : false)} + showOptionTags={usage == null || (usage === "both-dns-hosting" ? { [ACCESS_USAGES.DNS]: true, [ACCESS_USAGES.HOSTING]: true } : false)} showSearch={!disabled} /> diff --git a/ui/src/components/access/AccessForm1PanelConfig.tsx b/ui/src/components/access/AccessForm1PanelConfig.tsx index 1dde96b5..c0762bbd 100644 --- a/ui/src/components/access/AccessForm1PanelConfig.tsx +++ b/ui/src/components/access/AccessForm1PanelConfig.tsx @@ -49,12 +49,7 @@ const AccessForm1PanelConfig = ({ form: formInst, formName, disabled, initialVal name={formName} onValuesChange={handleFormChange} > - } - > + @@ -67,12 +62,7 @@ const AccessForm1PanelConfig = ({ form: formInst, formName, disabled, initialVal - } - > + - } - > + @@ -67,12 +62,7 @@ const AccessFormBaotaPanelConfig = ({ form: formInst, formName, disabled, initia - } - > + - } - > + @@ -80,6 +76,13 @@ const AccessFormCdnflyConfig = ({ form: formInst, formName, disabled, initialVal > + + + + ); }; diff --git a/ui/src/components/access/AccessFormDingTalkBotConfig.tsx b/ui/src/components/access/AccessFormDingTalkBotConfig.tsx new file mode 100644 index 00000000..35aebf6e --- /dev/null +++ b/ui/src/components/access/AccessFormDingTalkBotConfig.tsx @@ -0,0 +1,68 @@ +import { useTranslation } from "react-i18next"; +import { Form, type FormInstance, Input } from "antd"; +import { createSchemaFieldRule } from "antd-zod"; +import { z } from "zod"; + +import { type AccessConfigForDingTalkBot } from "@/domain/access"; + +type AccessFormDingTalkBotConfigFieldValues = Nullish; + +export type AccessFormDingTalkBotConfigProps = { + form: FormInstance; + formName: string; + disabled?: boolean; + initialValues?: AccessFormDingTalkBotConfigFieldValues; + onValuesChange?: (values: AccessFormDingTalkBotConfigFieldValues) => void; +}; + +const initFormModel = (): AccessFormDingTalkBotConfigFieldValues => { + return { + webhookUrl: "", + secret: "", + }; +}; + +const AccessFormDingTalkBotConfig = ({ form: formInst, formName, disabled, initialValues, onValuesChange }: AccessFormDingTalkBotConfigProps) => { + const { t } = useTranslation(); + + const formSchema = z.object({ + webhookUrl: z.string().url(t("common.errmsg.url_invalid")), + secret: z.string().nonempty(t("access.form.dingtalkbot_secret.placeholder")).trim(), + }); + const formRule = createSchemaFieldRule(formSchema); + + const handleFormChange = (_: unknown, values: z.infer) => { + onValuesChange?.(values); + }; + + return ( +
+ } + > + + + + } + > + + +
+ ); +}; + +export default AccessFormDingTalkBotConfig; diff --git a/ui/src/components/access/AccessFormEmailConfig.tsx b/ui/src/components/access/AccessFormEmailConfig.tsx new file mode 100644 index 00000000..ae79794a --- /dev/null +++ b/ui/src/components/access/AccessFormEmailConfig.tsx @@ -0,0 +1,125 @@ +import { useTranslation } from "react-i18next"; +import { Form, type FormInstance, Input, InputNumber, Switch } from "antd"; +import { createSchemaFieldRule } from "antd-zod"; +import { z } from "zod"; + +import { type AccessConfigForEmail } from "@/domain/access"; +import { validEmailAddress, validPortNumber } from "@/utils/validators"; + +type AccessFormEmailConfigFieldValues = Nullish; + +export type AccessFormEmailConfigProps = { + form: FormInstance; + formName: string; + disabled?: boolean; + initialValues?: AccessFormEmailConfigFieldValues; + onValuesChange?: (values: AccessFormEmailConfigFieldValues) => void; +}; + +const initFormModel = (): AccessFormEmailConfigFieldValues => { + return { + smtpHost: "", + smtpPort: 465, + smtpTls: true, + username: "", + password: "", + }; +}; + +const AccessFormEmailConfig = ({ form: formInst, formName, disabled, initialValues, onValuesChange }: AccessFormEmailConfigProps) => { + const { t } = useTranslation(); + + const formSchema = z.object({ + smtpHost: z + .string() + .min(1, t("access.form.email_smtp_host.placeholder")) + .max(256, t("common.errmsg.string_max", { max: 256 })), + smtpPort: z.preprocess( + (v) => Number(v), + z.number().refine((v) => validPortNumber(v), t("common.errmsg.port_invalid")) + ), + smtpTls: z.boolean().nullish(), + username: z + .string() + .min(1, t("access.form.email_username.placeholder")) + .max(256, t("common.errmsg.string_max", { max: 256 })), + password: z + .string() + .min(1, t("access.form.email_password.placeholder")) + .max(256, t("common.errmsg.string_max", { max: 256 })), + defaultSenderAddress: z + .string() + .nullish() + .refine((v) => { + if (!v) return true; + return validEmailAddress(v); + }, t("common.errmsg.email_invalid")), + defaultReceiverAddress: z + .string() + .nullish() + .refine((v) => { + if (!v) return true; + return validEmailAddress(v); + }, t("common.errmsg.email_invalid")), + }); + const formRule = createSchemaFieldRule(formSchema); + + const handleTlsSwitchChange = (checked: boolean) => { + const oldPort = formInst.getFieldValue("smtpPort"); + const newPort = checked && (oldPort == null || oldPort === 25) ? 465 : !checked && (oldPort == null || oldPort === 465) ? 25 : oldPort; + if (newPort !== oldPort) { + formInst.setFieldValue("smtpPort", newPort); + } + }; + + const handleFormChange = (_: unknown, values: z.infer) => { + onValuesChange?.(values); + }; + + return ( +
+
+
+ + + +
+ +
+ + + +
+
+ + + + + + + + + + + + + + + + + + + + +
+ ); +}; + +export default AccessFormEmailConfig; diff --git a/ui/src/components/access/AccessFormGoEdgeConfig.tsx b/ui/src/components/access/AccessFormGoEdgeConfig.tsx new file mode 100644 index 00000000..eb4140f4 --- /dev/null +++ b/ui/src/components/access/AccessFormGoEdgeConfig.tsx @@ -0,0 +1,90 @@ +import { useTranslation } from "react-i18next"; +import { Form, type FormInstance, Input, Switch } from "antd"; +import { createSchemaFieldRule } from "antd-zod"; +import { z } from "zod"; + +import { type AccessConfigForGoEdge } from "@/domain/access"; + +type AccessFormGoEdgeConfigFieldValues = Nullish; + +export type AccessFormGoEdgeConfigProps = { + form: FormInstance; + formName: string; + disabled?: boolean; + initialValues?: AccessFormGoEdgeConfigFieldValues; + onValuesChange?: (values: AccessFormGoEdgeConfigFieldValues) => void; +}; + +const initFormModel = (): AccessFormGoEdgeConfigFieldValues => { + return { + apiUrl: "http://:7788/", + accessKeyId: "", + accessKey: "", + }; +}; + +const AccessFormGoEdgeConfig = ({ form: formInst, formName, disabled, initialValues, onValuesChange }: AccessFormGoEdgeConfigProps) => { + const { t } = useTranslation(); + + const formSchema = z.object({ + apiUrl: z.string().url(t("common.errmsg.url_invalid")), + accessKeyId: z + .string() + .min(1, t("access.form.goedge_access_key_id.placeholder")) + .max(64, t("common.errmsg.string_max", { max: 64 })) + .trim(), + accessKey: z + .string() + .min(1, t("access.form.goedge_access_key.placeholder")) + .max(64, t("common.errmsg.string_max", { max: 64 })) + .trim(), + allowInsecureConnections: z.boolean().nullish(), + }); + const formRule = createSchemaFieldRule(formSchema); + + const handleFormChange = (_: unknown, values: z.infer) => { + onValuesChange?.(values); + }; + + return ( +
+ + + + + } + > + + + + } + > + + + + + + +
+ ); +}; + +export default AccessFormGoEdgeConfig; diff --git a/ui/src/components/access/AccessFormLarkBotConfig.tsx b/ui/src/components/access/AccessFormLarkBotConfig.tsx new file mode 100644 index 00000000..2a07505e --- /dev/null +++ b/ui/src/components/access/AccessFormLarkBotConfig.tsx @@ -0,0 +1,57 @@ +import { useTranslation } from "react-i18next"; +import { Form, type FormInstance, Input } from "antd"; +import { createSchemaFieldRule } from "antd-zod"; +import { z } from "zod"; + +import { type AccessConfigForLarkBot } from "@/domain/access"; + +type AccessFormLarkBotConfigFieldValues = Nullish; + +export type AccessFormLarkBotConfigProps = { + form: FormInstance; + formName: string; + disabled?: boolean; + initialValues?: AccessFormLarkBotConfigFieldValues; + onValuesChange?: (values: AccessFormLarkBotConfigFieldValues) => void; +}; + +const initFormModel = (): AccessFormLarkBotConfigFieldValues => { + return { + webhookUrl: "", + }; +}; + +const AccessFormLarkBotConfig = ({ form: formInst, formName, disabled, initialValues, onValuesChange }: AccessFormLarkBotConfigProps) => { + const { t } = useTranslation(); + + const formSchema = z.object({ + webhookUrl: z.string().url(t("common.errmsg.url_invalid")), + }); + const formRule = createSchemaFieldRule(formSchema); + + const handleFormChange = (_: unknown, values: z.infer) => { + onValuesChange?.(values); + }; + + return ( +
+ } + > + + +
+ ); +}; + +export default AccessFormLarkBotConfig; diff --git a/ui/src/components/access/AccessFormMattermostConfig.tsx b/ui/src/components/access/AccessFormMattermostConfig.tsx new file mode 100644 index 00000000..a583cc19 --- /dev/null +++ b/ui/src/components/access/AccessFormMattermostConfig.tsx @@ -0,0 +1,79 @@ +import { useTranslation } from "react-i18next"; +import { Form, type FormInstance, Input } from "antd"; +import { createSchemaFieldRule } from "antd-zod"; +import { z } from "zod"; + +import { type AccessConfigForMattermost } from "@/domain/access"; + +type AccessFormMattermostConfigFieldValues = Nullish; + +export type AccessFormMattermostConfigProps = { + form: FormInstance; + formName: string; + disabled?: boolean; + initialValues?: AccessFormMattermostConfigFieldValues; + onValuesChange?: (values: AccessFormMattermostConfigFieldValues) => void; +}; + +const initFormModel = (): AccessFormMattermostConfigFieldValues => { + return { + serverUrl: "http://:8065/", + username: "", + password: "", + }; +}; + +const AccessFormMattermostConfig = ({ form: formInst, formName, disabled, initialValues, onValuesChange }: AccessFormMattermostConfigProps) => { + const { t } = useTranslation(); + + const formSchema = z.object({ + serverUrl: z.string().url(t("common.errmsg.url_invalid")), + username: z.string().nonempty(t("access.form.mattermost_username.placeholder")), + password: z.string().nonempty(t("access.form.mattermost_password.placeholder")), + defaultChannelId: z.string().nullish(), + }); + const formRule = createSchemaFieldRule(formSchema); + + const handleFormChange = (_: unknown, values: z.infer) => { + onValuesChange?.(values); + }; + + return ( +
+ } + > + + + + + + + + + + + + } + > + + +
+ ); +}; + +export default AccessFormMattermostConfig; diff --git a/ui/src/components/access/AccessFormPowerDNSConfig.tsx b/ui/src/components/access/AccessFormPowerDNSConfig.tsx index cada5b61..b2bfb081 100644 --- a/ui/src/components/access/AccessFormPowerDNSConfig.tsx +++ b/ui/src/components/access/AccessFormPowerDNSConfig.tsx @@ -1,5 +1,5 @@ import { useTranslation } from "react-i18next"; -import { Form, type FormInstance, Input } from "antd"; +import { Form, type FormInstance, Input, Switch } from "antd"; import { createSchemaFieldRule } from "antd-zod"; import { z } from "zod"; @@ -32,6 +32,7 @@ const AccessFormPowerDNSConfig = ({ form: formInst, formName, disabled, initialV .min(1, t("access.form.powerdns_api_key.placeholder")) .max(64, t("common.errmsg.string_max", { max: 64 })) .trim(), + allowInsecureConnections: z.boolean().nullish(), }); const formRule = createSchemaFieldRule(formSchema); @@ -48,12 +49,7 @@ const AccessFormPowerDNSConfig = ({ form: formInst, formName, disabled, initialV name={formName} onValuesChange={handleFormChange} > - } - > + @@ -65,6 +61,13 @@ const AccessFormPowerDNSConfig = ({ form: formInst, formName, disabled, initialV > + + + + ); }; diff --git a/ui/src/components/access/AccessFormProxmoxVEConfig.tsx b/ui/src/components/access/AccessFormProxmoxVEConfig.tsx new file mode 100644 index 00000000..afdc02de --- /dev/null +++ b/ui/src/components/access/AccessFormProxmoxVEConfig.tsx @@ -0,0 +1,81 @@ +import { useTranslation } from "react-i18next"; +import { Form, type FormInstance, Input, Switch } from "antd"; +import { createSchemaFieldRule } from "antd-zod"; +import { z } from "zod"; + +import { type AccessConfigForProxmoxVE } from "@/domain/access"; + +type AccessFormProxmoxVEConfigFieldValues = Nullish; + +export type AccessFormProxmoxVEConfigProps = { + form: FormInstance; + formName: string; + disabled?: boolean; + initialValues?: AccessFormProxmoxVEConfigFieldValues; + onValuesChange?: (values: AccessFormProxmoxVEConfigFieldValues) => void; +}; + +const initFormModel = (): AccessFormProxmoxVEConfigFieldValues => { + return { + apiUrl: "http://:8006/", + apiToken: "", + }; +}; + +const AccessFormProxmoxVEConfig = ({ form: formInst, formName, disabled, initialValues, onValuesChange }: AccessFormProxmoxVEConfigProps) => { + const { t } = useTranslation(); + + const formSchema = z.object({ + apiUrl: z.string().url(t("common.errmsg.url_invalid")), + apiToken: z.string().nonempty(t("access.form.proxmoxve_api_token.placeholder")).trim(), + apiTokenSecret: z.string().nullish(), + allowInsecureConnections: z.boolean().nullish(), + }); + const formRule = createSchemaFieldRule(formSchema); + + const handleFormChange = (_: unknown, values: z.infer) => { + onValuesChange?.(values); + }; + + return ( +
+ + + + + } + > + + + + } + > + + + + + + +
+ ); +}; + +export default AccessFormProxmoxVEConfig; diff --git a/ui/src/components/access/AccessFormSSHConfig.tsx b/ui/src/components/access/AccessFormSSHConfig.tsx index 6d3615cf..ebaeba90 100644 --- a/ui/src/components/access/AccessFormSSHConfig.tsx +++ b/ui/src/components/access/AccessFormSSHConfig.tsx @@ -31,13 +31,11 @@ const AccessFormSSHConfig = ({ form: formInst, formName, disabled, initialValues const { t } = useTranslation(); const formSchema = z.object({ - host: z - .string({ message: t("access.form.ssh_host.placeholder") }) - .refine((v) => validDomainName(v) || validIPv4Address(v) || validIPv6Address(v), t("common.errmsg.host_invalid")), + host: z.string().refine((v) => validDomainName(v) || validIPv4Address(v) || validIPv6Address(v), t("common.errmsg.host_invalid")), port: z.preprocess( (v) => Number(v), z - .number({ message: t("access.form.ssh_port.placeholder") }) + .number() .int(t("access.form.ssh_port.placeholder")) .refine((v) => validPortNumber(v), t("common.errmsg.port_invalid")) ), diff --git a/ui/src/components/access/AccessFormSafeLineConfig.tsx b/ui/src/components/access/AccessFormSafeLineConfig.tsx index 5b16c508..2fde089d 100644 --- a/ui/src/components/access/AccessFormSafeLineConfig.tsx +++ b/ui/src/components/access/AccessFormSafeLineConfig.tsx @@ -49,12 +49,7 @@ const AccessFormSafeLineConfig = ({ form: formInst, formName, disabled, initialV name={formName} onValuesChange={handleFormChange} > - } - > + @@ -67,12 +62,7 @@ const AccessFormSafeLineConfig = ({ form: formInst, formName, disabled, initialV - } - > + ; + +export type AccessFormTelegramConfigProps = { + form: FormInstance; + formName: string; + disabled?: boolean; + initialValues?: AccessFormTelegramConfigFieldValues; + onValuesChange?: (values: AccessFormTelegramConfigFieldValues) => void; +}; + +const initFormModel = (): AccessFormTelegramConfigFieldValues => { + return { + botToken: "", + }; +}; + +const AccessFormTelegramConfig = ({ form: formInst, formName, disabled, initialValues, onValuesChange }: AccessFormTelegramConfigProps) => { + const { t } = useTranslation(); + + const formSchema = z.object({ + botToken: z + .string({ message: t("access.form.telegram_bot_token.placeholder") }) + .min(1, t("access.form.telegram_bot_token.placeholder")) + .max(256, t("common.errmsg.string_max", { max: 256 })), + defaultChatId: z + .preprocess( + (v) => (v == null || v === "" ? undefined : Number(v)), + z + .number() + .nullish() + .refine((v) => { + if (v == null || v + "" === "") return true; + return /^\d+$/.test(v + "") && +v! > 0; + }, t("access.form.telegram_default_chat_id.placeholder")) + ) + .nullish(), + }); + const formRule = createSchemaFieldRule(formSchema); + + const handleFormChange = (_: unknown, values: z.infer) => { + onValuesChange?.(values); + }; + + return ( +
+ } + > + + + + } + > + + +
+ ); +}; + +export default AccessFormTelegramConfig; diff --git a/ui/src/components/access/AccessFormWeComBotConfig.tsx b/ui/src/components/access/AccessFormWeComBotConfig.tsx new file mode 100644 index 00000000..16a205f5 --- /dev/null +++ b/ui/src/components/access/AccessFormWeComBotConfig.tsx @@ -0,0 +1,57 @@ +import { useTranslation } from "react-i18next"; +import { Form, type FormInstance, Input } from "antd"; +import { createSchemaFieldRule } from "antd-zod"; +import { z } from "zod"; + +import { type AccessConfigForWeComBot } from "@/domain/access"; + +type AccessFormWeComBotConfigFieldValues = Nullish; + +export type AccessFormWeComBotConfigProps = { + form: FormInstance; + formName: string; + disabled?: boolean; + initialValues?: AccessFormWeComBotConfigFieldValues; + onValuesChange?: (values: AccessFormWeComBotConfigFieldValues) => void; +}; + +const initFormModel = (): AccessFormWeComBotConfigFieldValues => { + return { + webhookUrl: "", + }; +}; + +const AccessFormWeComBotConfig = ({ form: formInst, formName, disabled, initialValues, onValuesChange }: AccessFormWeComBotConfigProps) => { + const { t } = useTranslation(); + + const formSchema = z.object({ + webhookUrl: z.string().url(t("common.errmsg.url_invalid")), + }); + const formRule = createSchemaFieldRule(formSchema); + + const handleFormChange = (_: unknown, values: z.infer) => { + onValuesChange?.(values); + }; + + return ( +
+ } + > + + +
+ ); +}; + +export default AccessFormWeComBotConfig; diff --git a/ui/src/components/access/AccessFormWebhookConfig.tsx b/ui/src/components/access/AccessFormWebhookConfig.tsx index 89280d79..4bbc6754 100644 --- a/ui/src/components/access/AccessFormWebhookConfig.tsx +++ b/ui/src/components/access/AccessFormWebhookConfig.tsx @@ -1,8 +1,10 @@ import { useTranslation } from "react-i18next"; -import { Form, type FormInstance, Input, Switch } from "antd"; +import { DownOutlined as DownOutlinedIcon } from "@ant-design/icons"; +import { Alert, Button, Dropdown, Form, type FormInstance, Input, Select, Switch } from "antd"; import { createSchemaFieldRule } from "antd-zod"; import { z } from "zod"; +import Show from "@/components/Show"; import { type AccessConfigForWebhook } from "@/domain/access"; type AccessFormWebhookConfigFieldValues = Nullish; @@ -12,24 +14,241 @@ export type AccessFormWebhookConfigProps = { formName: string; disabled?: boolean; initialValues?: AccessFormWebhookConfigFieldValues; + usage?: "deployment" | "notification" | "none"; onValuesChange?: (values: AccessFormWebhookConfigFieldValues) => void; }; const initFormModel = (): AccessFormWebhookConfigFieldValues => { return { url: "", + method: "POST", + headers: "Content-Type: application/json", + allowInsecureConnections: false, + defaultDataForDeployment: JSON.stringify( + { + name: "${DOMAINS}", + cert: "${CERTIFICATE}", + privkey: "${PRIVATE_KEY}", + }, + null, + 2 + ), + defaultDataForNotification: JSON.stringify( + { + subject: "${SUBJECT}", + message: "${MESSAGE}", + }, + null, + 2 + ), }; }; -const AccessFormWebhookConfig = ({ form: formInst, formName, disabled, initialValues, onValuesChange }: AccessFormWebhookConfigProps) => { +const AccessFormWebhookConfig = ({ form: formInst, formName, disabled, initialValues, usage, onValuesChange }: AccessFormWebhookConfigProps) => { const { t } = useTranslation(); const formSchema = z.object({ - url: z.string({ message: t("access.form.webhook_url.placeholder") }).url(t("common.errmsg.url_invalid")), + url: z.string().url(t("common.errmsg.url_invalid")), + method: z.union([z.literal("GET"), z.literal("POST"), z.literal("PUT"), z.literal("PATCH"), z.literal("DELETE")], { + message: t("access.form.webhook_method.placeholder"), + }), + headers: z + .string() + .nullish() + .refine((v) => { + if (!v) return true; + + const lines = v.split(/\r?\n/); + for (const line of lines) { + if (line.split(":").length < 2) { + return false; + } + } + return true; + }, t("access.form.webhook_headers.errmsg.invalid")), allowInsecureConnections: z.boolean().nullish(), + defaultDataForDeployment: z + .string() + .nullish() + .refine((v) => { + if (usage && usage !== "deployment") return true; + if (!v) return true; + + try { + const obj = JSON.parse(v); + return typeof obj === "object" && !Array.isArray(obj); + } catch { + return false; + } + }, t("access.form.webhook_default_data.errmsg.json_invalid")), + defaultDataForNotification: z + .string() + .nullish() + .refine((v) => { + if (usage && usage !== "notification") return true; + if (!v) return true; + + try { + const obj = JSON.parse(v); + return typeof obj === "object" && !Array.isArray(obj); + } catch { + return false; + } + }, t("access.form.webhook_default_data.errmsg.json_invalid")), }); const formRule = createSchemaFieldRule(formSchema); + const handleWebhookHeadersBlur = (e: React.FocusEvent) => { + let value = e.target.value; + value = value.trim(); + value = value.replace(/(?) => { + const value = e.target.value; + try { + const json = JSON.stringify(JSON.parse(value), null, 2); + formInst.setFieldValue("defaultDataForDeployment", json); + } catch { + return; + } + }; + + const handleWebhookDataForNotificationBlur = (e: React.FocusEvent) => { + const value = e.target.value; + try { + const json = JSON.stringify(JSON.parse(value), null, 2); + formInst.setFieldValue("defaultDataForNotification", json); + } catch { + return; + } + }; + + const handlePresetDataForDeploymentClick = () => { + formInst.setFieldValue("defaultDataForDeployment", initFormModel().defaultDataForDeployment); + }; + + const handlePresetDataForNotificationClick = (key: string) => { + switch (key) { + case "bark": + formInst.setFieldValue("url", "https://api.day.app/push"); + formInst.setFieldValue("method", "POST"); + formInst.setFieldValue("headers", "Content-Type: application/json\r\nAuthorization: Bearer "); + formInst.setFieldValue( + "defaultDataForNotification", + JSON.stringify( + { + title: "${SUBJECT}", + body: "${MESSAGE}", + group: "", + device_keys: "", + }, + null, + 2 + ) + ); + break; + + case "gotify": + formInst.setFieldValue("url", "https:///"); + formInst.setFieldValue("method", "POST"); + formInst.setFieldValue("headers", "Content-Type: application/json\r\nAuthorization: Bearer "); + formInst.setFieldValue( + "defaultDataForNotification", + JSON.stringify( + { + title: "${SUBJECT}", + message: "${MESSAGE}", + priority: 1, + }, + null, + 2 + ) + ); + break; + + case "ntfy": + formInst.setFieldValue("url", "https:///"); + formInst.setFieldValue("method", "POST"); + formInst.setFieldValue("headers", "Content-Type: application/json"); + formInst.setFieldValue( + "defaultDataForNotification", + JSON.stringify( + { + topic: "", + title: "${SUBJECT}", + message: "${MESSAGE}", + priority: 1, + }, + null, + 2 + ) + ); + break; + + case "pushover": + formInst.setFieldValue("url", "https://api.pushover.net/1/messages.json"); + formInst.setFieldValue("method", "POST"); + formInst.setFieldValue("headers", "Content-Type: application/json"); + formInst.setFieldValue( + "defaultDataForNotification", + JSON.stringify( + { + token: "", + user: "", + title: "${SUBJECT}", + message: "${MESSAGE}", + }, + null, + 2 + ) + ); + break; + + case "pushplus": + formInst.setFieldValue("url", "https://www.pushplus.plus/send"); + formInst.setFieldValue("method", "POST"); + formInst.setFieldValue("headers", "Content-Type: application/json"); + formInst.setFieldValue( + "defaultDataForNotification", + JSON.stringify( + { + token: "", + title: "${SUBJECT}", + content: "${MESSAGE}", + }, + null, + 2 + ) + ); + break; + + case "serverchan": + formInst.setFieldValue("url", "https://sctapi.ftqq.com/.send"); + formInst.setFieldValue("method", "POST"); + formInst.setFieldValue("headers", "Content-Type: application/json"); + formInst.setFieldValue( + "defaultDataForNotification", + JSON.stringify( + { + text: "${SUBJECT}", + desp: "${MESSAGE}", + }, + null, + 2 + ) + ); + break; + + default: + formInst.setFieldValue("method", "POST"); + formInst.setFieldValue("headers", "Content-Type: application/json"); + formInst.setFieldValue("defaultDataForNotification", initFormModel().defaultDataForNotification); + break; + } + }; + const handleFormChange = (_: unknown, values: z.infer) => { onValuesChange?.(values); }; @@ -47,12 +266,93 @@ const AccessFormWebhookConfig = ({ form: formInst, formName, disabled, initialVa
+ + - + - + diff --git a/ui/src/components/provider/ApplyDNSProviderPicker.tsx b/ui/src/components/provider/ACMEDns01ProviderPicker.tsx similarity index 86% rename from ui/src/components/provider/ApplyDNSProviderPicker.tsx rename to ui/src/components/provider/ACMEDns01ProviderPicker.tsx index bcf65965..7f99cf6a 100644 --- a/ui/src/components/provider/ApplyDNSProviderPicker.tsx +++ b/ui/src/components/provider/ACMEDns01ProviderPicker.tsx @@ -3,9 +3,9 @@ import { useTranslation } from "react-i18next"; import { Avatar, Card, Col, Empty, Flex, Input, type InputRef, Row, Typography } from "antd"; import Show from "@/components/Show"; -import { applyDNSProvidersMap } from "@/domain/provider"; +import { acmeDns01ProvidersMap } from "@/domain/provider"; -export type ApplyDNSProviderPickerProps = { +export type ACMEDns01ProviderPickerProps = { className?: string; style?: React.CSSProperties; autoFocus?: boolean; @@ -13,7 +13,7 @@ export type ApplyDNSProviderPickerProps = { onSelect?: (value: string) => void; }; -const ApplyDNSProviderPicker = ({ className, style, autoFocus, placeholder, onSelect }: ApplyDNSProviderPickerProps) => { +const ACMEDns01ProviderPicker = ({ className, style, autoFocus, placeholder, onSelect }: ACMEDns01ProviderPickerProps) => { const { t } = useTranslation(); const [keyword, setKeyword] = useState(); @@ -25,7 +25,7 @@ const ApplyDNSProviderPicker = ({ className, style, autoFocus, placeholder, onSe }, []); const providers = useMemo(() => { - return Array.from(applyDNSProvidersMap.values()).filter((provider) => { + return Array.from(acmeDns01ProvidersMap.values()).filter((provider) => { if (keyword) { const value = keyword.toLowerCase(); return provider.type.toLowerCase().includes(value) || t(provider.name).toLowerCase().includes(value); @@ -72,4 +72,4 @@ const ApplyDNSProviderPicker = ({ className, style, autoFocus, placeholder, onSe ); }; -export default memo(ApplyDNSProviderPicker); +export default memo(ACMEDns01ProviderPicker); diff --git a/ui/src/components/provider/DeployProviderSelect.tsx b/ui/src/components/provider/ACMEDns01ProviderSelect.tsx similarity index 77% rename from ui/src/components/provider/DeployProviderSelect.tsx rename to ui/src/components/provider/ACMEDns01ProviderSelect.tsx index 5be10cb7..b03adf7b 100644 --- a/ui/src/components/provider/DeployProviderSelect.tsx +++ b/ui/src/components/provider/ACMEDns01ProviderSelect.tsx @@ -2,21 +2,21 @@ import { memo, useEffect, useState } from "react"; import { useTranslation } from "react-i18next"; import { Avatar, Select, type SelectProps, Space, Typography } from "antd"; -import { type DeployProvider, deployProvidersMap } from "@/domain/provider"; +import { type ACMEDns01Provider, acmeDns01ProvidersMap } from "@/domain/provider"; -export type DeployProviderSelectProps = Omit< +export type ACMEDns01ProviderSelectProps = Omit< SelectProps, "filterOption" | "filterSort" | "labelRender" | "options" | "optionFilterProp" | "optionLabelProp" | "optionRender" > & { - filter?: (record: DeployProvider) => boolean; + filter?: (record: ACMEDns01Provider) => boolean; }; -const DeployProviderSelect = ({ filter, ...props }: DeployProviderSelectProps) => { +const ACMEDns01ProviderSelect = ({ filter, ...props }: ACMEDns01ProviderSelectProps) => { const { t } = useTranslation(); - const [options, setOptions] = useState>([]); + const [options, setOptions] = useState>([]); useEffect(() => { - const allItems = Array.from(deployProvidersMap.values()); + const allItems = Array.from(acmeDns01ProvidersMap.values()); const filteredItems = filter != null ? allItems.filter(filter) : allItems; setOptions( filteredItems.map((item) => ({ @@ -29,7 +29,7 @@ const DeployProviderSelect = ({ filter, ...props }: DeployProviderSelectProps) = }, [filter]); const renderOption = (key: string) => { - const provider = deployProvidersMap.get(key); + const provider = acmeDns01ProvidersMap.get(key); return ( @@ -64,4 +64,4 @@ const DeployProviderSelect = ({ filter, ...props }: DeployProviderSelectProps) = ); }; -export default memo(DeployProviderSelect); +export default memo(ACMEDns01ProviderSelect); diff --git a/ui/src/components/provider/ApplyCAProviderSelect.tsx b/ui/src/components/provider/CAProviderSelect.tsx similarity index 79% rename from ui/src/components/provider/ApplyCAProviderSelect.tsx rename to ui/src/components/provider/CAProviderSelect.tsx index fdedac9b..15d31230 100644 --- a/ui/src/components/provider/ApplyCAProviderSelect.tsx +++ b/ui/src/components/provider/CAProviderSelect.tsx @@ -2,28 +2,28 @@ import { memo, useEffect, useState } from "react"; import { useTranslation } from "react-i18next"; import { Avatar, Select, type SelectProps, Space, Typography } from "antd"; -import { type ApplyCAProvider, applyCAProvidersMap } from "@/domain/provider"; +import { type CAProvider, caProvidersMap } from "@/domain/provider"; -export type ApplyCAProviderSelectProps = Omit< +export type CAProviderSelectProps = Omit< SelectProps, "filterOption" | "filterSort" | "labelRender" | "options" | "optionFilterProp" | "optionLabelProp" | "optionRender" > & { - filter?: (record: ApplyCAProvider) => boolean; + filter?: (record: CAProvider) => boolean; }; -const ApplyCAProviderSelect = ({ filter, ...props }: ApplyCAProviderSelectProps) => { +const CAProviderSelect = ({ filter, ...props }: CAProviderSelectProps) => { const { t } = useTranslation(); - const [options, setOptions] = useState>([]); + const [options, setOptions] = useState>([]); useEffect(() => { - const allItems = Array.from(applyCAProvidersMap.values()); + const allItems = Array.from(caProvidersMap.values()); const filteredItems = filter != null ? allItems.filter(filter) : allItems; setOptions([ { key: "", value: "", - label: "provider.default_ca_provider.label", - data: {} as ApplyCAProvider, + label: t("provider.default_ca_provider.label"), + data: {} as CAProvider, }, ...filteredItems.map((item) => ({ key: item.type, @@ -45,7 +45,7 @@ const ApplyCAProviderSelect = ({ filter, ...props }: ApplyCAProviderSelectProps) ); } - const provider = applyCAProvidersMap.get(key); + const provider = caProvidersMap.get(key); return ( @@ -80,4 +80,4 @@ const ApplyCAProviderSelect = ({ filter, ...props }: ApplyCAProviderSelectProps) ); }; -export default memo(ApplyCAProviderSelect); +export default memo(CAProviderSelect); diff --git a/ui/src/components/provider/DeployProviderPicker.tsx b/ui/src/components/provider/DeploymentProviderPicker.tsx similarity index 75% rename from ui/src/components/provider/DeployProviderPicker.tsx rename to ui/src/components/provider/DeploymentProviderPicker.tsx index 10aa3e09..f1af6ecb 100644 --- a/ui/src/components/provider/DeployProviderPicker.tsx +++ b/ui/src/components/provider/DeploymentProviderPicker.tsx @@ -3,9 +3,9 @@ import { useTranslation } from "react-i18next"; import { Avatar, Card, Col, Empty, Flex, Input, type InputRef, Row, Tabs, Tooltip, Typography } from "antd"; import Show from "@/components/Show"; -import { DEPLOY_CATEGORIES, deployProvidersMap } from "@/domain/provider"; +import { DEPLOYMENT_CATEGORIES, deploymentProvidersMap } from "@/domain/provider"; -export type DeployProviderPickerProps = { +export type DeploymentProviderPickerProps = { className?: string; style?: React.CSSProperties; autoFocus?: boolean; @@ -13,10 +13,10 @@ export type DeployProviderPickerProps = { onSelect?: (value: string) => void; }; -const DeployProviderPicker = ({ className, style, autoFocus, placeholder, onSelect }: DeployProviderPickerProps) => { +const DeploymentProviderPicker = ({ className, style, autoFocus, placeholder, onSelect }: DeploymentProviderPickerProps) => { const { t } = useTranslation(); - const [category, setCategory] = useState(DEPLOY_CATEGORIES.ALL); + const [category, setCategory] = useState(DEPLOYMENT_CATEGORIES.ALL); const [keyword, setKeyword] = useState(); const keywordInputRef = useRef(null); @@ -27,9 +27,9 @@ const DeployProviderPicker = ({ className, style, autoFocus, placeholder, onSele }, []); const providers = useMemo(() => { - return Array.from(deployProvidersMap.values()) + return Array.from(deploymentProvidersMap.values()) .filter((provider) => { - if (category && category !== DEPLOY_CATEGORIES.ALL) { + if (category && category !== DEPLOYMENT_CATEGORIES.ALL) { return provider.category === category; } @@ -56,17 +56,18 @@ const DeployProviderPicker = ({ className, style, autoFocus, placeholder, onSele
({ key: key, label: t(`provider.category.${key}`), @@ -110,4 +111,4 @@ const DeployProviderPicker = ({ className, style, autoFocus, placeholder, onSele ); }; -export default memo(DeployProviderPicker); +export default memo(DeploymentProviderPicker); diff --git a/ui/src/components/provider/ApplyDNSProviderSelect.tsx b/ui/src/components/provider/DeploymentProviderSelect.tsx similarity index 77% rename from ui/src/components/provider/ApplyDNSProviderSelect.tsx rename to ui/src/components/provider/DeploymentProviderSelect.tsx index f7e3c259..0b38cedf 100644 --- a/ui/src/components/provider/ApplyDNSProviderSelect.tsx +++ b/ui/src/components/provider/DeploymentProviderSelect.tsx @@ -2,21 +2,21 @@ import { memo, useEffect, useState } from "react"; import { useTranslation } from "react-i18next"; import { Avatar, Select, type SelectProps, Space, Typography } from "antd"; -import { type ApplyDNSProvider, applyDNSProvidersMap } from "@/domain/provider"; +import { type DeploymentProvider, deploymentProvidersMap } from "@/domain/provider"; -export type ApplyDNSProviderSelectProps = Omit< +export type DeploymentProviderSelectProps = Omit< SelectProps, "filterOption" | "filterSort" | "labelRender" | "options" | "optionFilterProp" | "optionLabelProp" | "optionRender" > & { - filter?: (record: ApplyDNSProvider) => boolean; + filter?: (record: DeploymentProvider) => boolean; }; -const ApplyDNSProviderSelect = ({ filter, ...props }: ApplyDNSProviderSelectProps) => { +const DeploymentProviderSelect = ({ filter, ...props }: DeploymentProviderSelectProps) => { const { t } = useTranslation(); - const [options, setOptions] = useState>([]); + const [options, setOptions] = useState>([]); useEffect(() => { - const allItems = Array.from(applyDNSProvidersMap.values()); + const allItems = Array.from(deploymentProvidersMap.values()); const filteredItems = filter != null ? allItems.filter(filter) : allItems; setOptions( filteredItems.map((item) => ({ @@ -29,7 +29,7 @@ const ApplyDNSProviderSelect = ({ filter, ...props }: ApplyDNSProviderSelectProp }, [filter]); const renderOption = (key: string) => { - const provider = applyDNSProvidersMap.get(key); + const provider = deploymentProvidersMap.get(key); return ( @@ -64,4 +64,4 @@ const ApplyDNSProviderSelect = ({ filter, ...props }: ApplyDNSProviderSelectProp ); }; -export default memo(ApplyDNSProviderSelect); +export default memo(DeploymentProviderSelect); diff --git a/ui/src/components/provider/NotificationProviderSelect.tsx b/ui/src/components/provider/NotificationProviderSelect.tsx new file mode 100644 index 00000000..98a1005c --- /dev/null +++ b/ui/src/components/provider/NotificationProviderSelect.tsx @@ -0,0 +1,67 @@ +import { memo, useEffect, useState } from "react"; +import { useTranslation } from "react-i18next"; +import { Avatar, Select, type SelectProps, Space, Typography } from "antd"; + +import { type NotificationProvider, notificationProvidersMap } from "@/domain/provider"; + +export type NotificationProviderSelectProps = Omit< + SelectProps, + "filterOption" | "filterSort" | "labelRender" | "options" | "optionFilterProp" | "optionLabelProp" | "optionRender" +> & { + filter?: (record: NotificationProvider) => boolean; +}; + +const NotificationProviderSelect = ({ filter, ...props }: NotificationProviderSelectProps) => { + const { t } = useTranslation(); + + const [options, setOptions] = useState>([]); + useEffect(() => { + const allItems = Array.from(notificationProvidersMap.values()); + const filteredItems = filter != null ? allItems.filter(filter) : allItems; + setOptions( + filteredItems.map((item) => ({ + key: item.type, + value: item.type, + label: t(item.name), + data: item, + })) + ); + }, [filter]); + + const renderOption = (key: string) => { + const provider = notificationProvidersMap.get(key); + return ( + + + + {t(provider?.name ?? "")} + + + ); + }; + + return ( + + + {t("workflow_node.apply.form.skip_before_expiry_days.prefix")}
; + +export type ApplyNodeConfigFormAliyunESAConfigProps = { + form: FormInstance; + formName: string; + disabled?: boolean; + initialValues?: ApplyNodeConfigFormAliyunESAConfigFieldValues; + onValuesChange?: (values: ApplyNodeConfigFormAliyunESAConfigFieldValues) => void; +}; + +const initFormModel = (): ApplyNodeConfigFormAliyunESAConfigFieldValues => { + return {}; +}; + +const ApplyNodeConfigFormAliyunESAConfig = ({ form: formInst, formName, disabled, initialValues, onValuesChange }: ApplyNodeConfigFormAliyunESAConfigProps) => { + const { t } = useTranslation(); + + const formSchema = z.object({ + region: z + .string({ message: t("workflow_node.apply.form.aliyun_esa_region.placeholder") }) + .nonempty(t("workflow_node.apply.form.aliyun_esa_region.placeholder")) + .trim(), + }); + const formRule = createSchemaFieldRule(formSchema); + + const handleFormChange = (_: unknown, values: z.infer) => { + onValuesChange?.(values); + }; + + return ( +
+ } + > + + +
+ ); +}; + +export default ApplyNodeConfigFormAliyunESAConfig; diff --git a/ui/src/components/workflow/node/DeployNode.tsx b/ui/src/components/workflow/node/DeployNode.tsx index 9eca1248..92eb2890 100644 --- a/ui/src/components/workflow/node/DeployNode.tsx +++ b/ui/src/components/workflow/node/DeployNode.tsx @@ -3,7 +3,7 @@ import { useTranslation } from "react-i18next"; import { Avatar, Flex, Typography } from "antd"; import { produce } from "immer"; -import { deployProvidersMap } from "@/domain/provider"; +import { deploymentProvidersMap } from "@/domain/provider"; import { type WorkflowNodeConfigForDeploy, WorkflowNodeType } from "@/domain/workflow"; import { useZustandShallowSelector } from "@/hooks"; import { useWorkflowStore } from "@/stores/workflow"; @@ -43,7 +43,7 @@ const DeployNode = ({ node, disabled }: DeployNodeProps) => { } const config = (node.config as WorkflowNodeConfigForDeploy) ?? {}; - const provider = deployProvidersMap.get(config.provider); + const provider = deploymentProvidersMap.get(config.provider); return ( diff --git a/ui/src/components/workflow/node/DeployNodeConfigForm.tsx b/ui/src/components/workflow/node/DeployNodeConfigForm.tsx index 24d256de..fc096e80 100644 --- a/ui/src/components/workflow/node/DeployNodeConfigForm.tsx +++ b/ui/src/components/workflow/node/DeployNodeConfigForm.tsx @@ -7,10 +7,10 @@ import { z } from "zod"; import AccessEditModal from "@/components/access/AccessEditModal"; import AccessSelect from "@/components/access/AccessSelect"; -import DeployProviderPicker from "@/components/provider/DeployProviderPicker.tsx"; -import DeployProviderSelect from "@/components/provider/DeployProviderSelect.tsx"; +import DeploymentProviderPicker from "@/components/provider/DeploymentProviderPicker.tsx"; +import DeploymentProviderSelect from "@/components/provider/DeploymentProviderSelect.tsx"; import Show from "@/components/Show"; -import { ACCESS_USAGES, DEPLOY_PROVIDERS, accessProvidersMap, deployProvidersMap } from "@/domain/provider"; +import { ACCESS_USAGES, DEPLOYMENT_PROVIDERS, accessProvidersMap, deploymentProvidersMap } from "@/domain/provider"; import { type WorkflowNode, type WorkflowNodeConfigForDeploy } from "@/domain/workflow"; import { useAntdForm, useAntdFormName, useZustandShallowSelector } from "@/hooks"; import { useWorkflowStore } from "@/stores/workflow"; @@ -24,6 +24,7 @@ import DeployNodeConfigFormAliyunCASDeployConfig from "./DeployNodeConfigFormAli import DeployNodeConfigFormAliyunCDNConfig from "./DeployNodeConfigFormAliyunCDNConfig"; import DeployNodeConfigFormAliyunCLBConfig from "./DeployNodeConfigFormAliyunCLBConfig"; import DeployNodeConfigFormAliyunDCDNConfig from "./DeployNodeConfigFormAliyunDCDNConfig"; +import DeployNodeConfigFormAliyunDDoSConfig from "./DeployNodeConfigFormAliyunDDoSConfig"; import DeployNodeConfigFormAliyunESAConfig from "./DeployNodeConfigFormAliyunESAConfig"; import DeployNodeConfigFormAliyunFCConfig from "./DeployNodeConfigFormAliyunFCConfig"; import DeployNodeConfigFormAliyunLiveConfig from "./DeployNodeConfigFormAliyunLiveConfig"; @@ -46,6 +47,7 @@ import DeployNodeConfigFormCdnflyConfig from "./DeployNodeConfigFormCdnflyConfig import DeployNodeConfigFormDogeCloudCDNConfig from "./DeployNodeConfigFormDogeCloudCDNConfig"; import DeployNodeConfigFormEdgioApplicationsConfig from "./DeployNodeConfigFormEdgioApplicationsConfig"; import DeployNodeConfigFormGcoreCDNConfig from "./DeployNodeConfigFormGcoreCDNConfig"; +import DeployNodeConfigFormGoEdgeConfig from "./DeployNodeConfigFormGoEdgeConfig"; import DeployNodeConfigFormHuaweiCloudCDNConfig from "./DeployNodeConfigFormHuaweiCloudCDNConfig"; import DeployNodeConfigFormHuaweiCloudELBConfig from "./DeployNodeConfigFormHuaweiCloudELBConfig"; import DeployNodeConfigFormHuaweiCloudWAFConfig from "./DeployNodeConfigFormHuaweiCloudWAFConfig"; @@ -55,6 +57,7 @@ import DeployNodeConfigFormJDCloudLiveConfig from "./DeployNodeConfigFormJDCloud import DeployNodeConfigFormJDCloudVODConfig from "./DeployNodeConfigFormJDCloudVODConfig"; import DeployNodeConfigFormKubernetesSecretConfig from "./DeployNodeConfigFormKubernetesSecretConfig"; import DeployNodeConfigFormLocalConfig from "./DeployNodeConfigFormLocalConfig"; +import DeployNodeConfigFormProxmoxVEConfig from "./DeployNodeConfigFormProxmoxVEConfig"; import DeployNodeConfigFormQiniuCDNConfig from "./DeployNodeConfigFormQiniuCDNConfig"; import DeployNodeConfigFormQiniuKodoConfig from "./DeployNodeConfigFormQiniuKodoConfig"; import DeployNodeConfigFormQiniuPiliConfig from "./DeployNodeConfigFormQiniuPiliConfig"; @@ -133,7 +136,7 @@ const DeployNodeConfigForm = forwardRef { if (!fieldProvider) return true; - const provider = deployProvidersMap.get(fieldProvider); + const provider = deploymentProvidersMap.get(fieldProvider); return !!provider?.builtin || !!v; }, t("workflow_node.deploy.form.provider_access.placeholder")), providerConfig: z.any().nullish(), @@ -151,7 +154,7 @@ const DeployNodeConfigForm = forwardRef { // 内置的部署提供商(如本地部署)无需显示授权信息字段 if (fieldProvider) { - const provider = deployProvidersMap.get(fieldProvider); + const provider = deploymentProvidersMap.get(fieldProvider); setShowProviderAccess(!provider?.builtin); } else { setShowProviderAccess(false); @@ -173,145 +176,151 @@ const DeployNodeConfigForm = forwardRef; - case DEPLOY_PROVIDERS["1PANEL_SITE"]: + case DEPLOYMENT_PROVIDERS["1PANEL_SITE"]: return ; - case DEPLOY_PROVIDERS.ALIYUN_ALB: + case DEPLOYMENT_PROVIDERS.ALIYUN_ALB: return ; - case DEPLOY_PROVIDERS.ALIYUN_APIGW: + case DEPLOYMENT_PROVIDERS.ALIYUN_APIGW: return ; - case DEPLOY_PROVIDERS.ALIYUN_CAS: + case DEPLOYMENT_PROVIDERS.ALIYUN_CAS: return ; - case DEPLOY_PROVIDERS.ALIYUN_CAS_DEPLOY: + case DEPLOYMENT_PROVIDERS.ALIYUN_CAS_DEPLOY: return ; - case DEPLOY_PROVIDERS.ALIYUN_CLB: + case DEPLOYMENT_PROVIDERS.ALIYUN_CLB: return ; - case DEPLOY_PROVIDERS.ALIYUN_CDN: + case DEPLOYMENT_PROVIDERS.ALIYUN_CDN: return ; - case DEPLOY_PROVIDERS.ALIYUN_DCDN: + case DEPLOYMENT_PROVIDERS.ALIYUN_DCDN: return ; - case DEPLOY_PROVIDERS.ALIYUN_ESA: + case DEPLOYMENT_PROVIDERS.ALIYUN_DDOS: + return ; + case DEPLOYMENT_PROVIDERS.ALIYUN_ESA: return ; - case DEPLOY_PROVIDERS.ALIYUN_FC: + case DEPLOYMENT_PROVIDERS.ALIYUN_FC: return ; - case DEPLOY_PROVIDERS.ALIYUN_LIVE: + case DEPLOYMENT_PROVIDERS.ALIYUN_LIVE: return ; - case DEPLOY_PROVIDERS.ALIYUN_NLB: + case DEPLOYMENT_PROVIDERS.ALIYUN_NLB: return ; - case DEPLOY_PROVIDERS.ALIYUN_OSS: + case DEPLOYMENT_PROVIDERS.ALIYUN_OSS: return ; - case DEPLOY_PROVIDERS.ALIYUN_VOD: + case DEPLOYMENT_PROVIDERS.ALIYUN_VOD: return ; - case DEPLOY_PROVIDERS.ALIYUN_WAF: + case DEPLOYMENT_PROVIDERS.ALIYUN_WAF: return ; - case DEPLOY_PROVIDERS.AWS_ACM: + case DEPLOYMENT_PROVIDERS.AWS_ACM: return ; - case DEPLOY_PROVIDERS.AWS_CLOUDFRONT: + case DEPLOYMENT_PROVIDERS.AWS_CLOUDFRONT: return ; - case DEPLOY_PROVIDERS.AZURE_KEYVAULT: + case DEPLOYMENT_PROVIDERS.AZURE_KEYVAULT: return ; - case DEPLOY_PROVIDERS.BAIDUCLOUD_APPBLB: + case DEPLOYMENT_PROVIDERS.BAIDUCLOUD_APPBLB: return ; - case DEPLOY_PROVIDERS.BAIDUCLOUD_BLB: + case DEPLOYMENT_PROVIDERS.BAIDUCLOUD_BLB: return ; - case DEPLOY_PROVIDERS.BAIDUCLOUD_CDN: + case DEPLOYMENT_PROVIDERS.BAIDUCLOUD_CDN: return ; - case DEPLOY_PROVIDERS.BAISHAN_CDN: + case DEPLOYMENT_PROVIDERS.BAISHAN_CDN: return ; - case DEPLOY_PROVIDERS.BAOTAPANEL_CONSOLE: + case DEPLOYMENT_PROVIDERS.BAOTAPANEL_CONSOLE: return ; - case DEPLOY_PROVIDERS.BAOTAPANEL_SITE: + case DEPLOYMENT_PROVIDERS.BAOTAPANEL_SITE: return ; - case DEPLOY_PROVIDERS.BUNNY_CDN: + case DEPLOYMENT_PROVIDERS.BUNNY_CDN: return ; - case DEPLOY_PROVIDERS.BYTEPLUS_CDN: + case DEPLOYMENT_PROVIDERS.BYTEPLUS_CDN: return ; - case DEPLOY_PROVIDERS.CDNFLY: + case DEPLOYMENT_PROVIDERS.CDNFLY: return ; - case DEPLOY_PROVIDERS.DOGECLOUD_CDN: + case DEPLOYMENT_PROVIDERS.DOGECLOUD_CDN: return ; - case DEPLOY_PROVIDERS.EDGIO_APPLICATIONS: + case DEPLOYMENT_PROVIDERS.EDGIO_APPLICATIONS: return ; - case DEPLOY_PROVIDERS.GCORE_CDN: + case DEPLOYMENT_PROVIDERS.GCORE_CDN: return ; - case DEPLOY_PROVIDERS.HUAWEICLOUD_CDN: + case DEPLOYMENT_PROVIDERS.GOEDGE: + return ; + case DEPLOYMENT_PROVIDERS.HUAWEICLOUD_CDN: return ; - case DEPLOY_PROVIDERS.HUAWEICLOUD_ELB: + case DEPLOYMENT_PROVIDERS.HUAWEICLOUD_ELB: return ; - case DEPLOY_PROVIDERS.HUAWEICLOUD_WAF: + case DEPLOYMENT_PROVIDERS.HUAWEICLOUD_WAF: return ; - case DEPLOY_PROVIDERS.JDCLOUD_ALB: + case DEPLOYMENT_PROVIDERS.JDCLOUD_ALB: return ; - case DEPLOY_PROVIDERS.JDCLOUD_CDN: + case DEPLOYMENT_PROVIDERS.JDCLOUD_CDN: return ; - case DEPLOY_PROVIDERS.JDCLOUD_LIVE: + case DEPLOYMENT_PROVIDERS.JDCLOUD_LIVE: return ; - case DEPLOY_PROVIDERS.JDCLOUD_VOD: + case DEPLOYMENT_PROVIDERS.JDCLOUD_VOD: return ; - case DEPLOY_PROVIDERS.KUBERNETES_SECRET: + case DEPLOYMENT_PROVIDERS.KUBERNETES_SECRET: return ; - case DEPLOY_PROVIDERS.LOCAL: + case DEPLOYMENT_PROVIDERS.LOCAL: return ; - case DEPLOY_PROVIDERS.QINIU_CDN: + case DEPLOYMENT_PROVIDERS.PROXMOXVE: + return ; + case DEPLOYMENT_PROVIDERS.QINIU_CDN: return ; - case DEPLOY_PROVIDERS.QINIU_KODO: + case DEPLOYMENT_PROVIDERS.QINIU_KODO: return ; - case DEPLOY_PROVIDERS.QINIU_PILI: + case DEPLOYMENT_PROVIDERS.QINIU_PILI: return ; - case DEPLOY_PROVIDERS.RAINYUN_RCDN: + case DEPLOYMENT_PROVIDERS.RAINYUN_RCDN: return ; - case DEPLOY_PROVIDERS.SAFELINE: + case DEPLOYMENT_PROVIDERS.SAFELINE: return ; - case DEPLOY_PROVIDERS.SSH: + case DEPLOYMENT_PROVIDERS.SSH: return ; - case DEPLOY_PROVIDERS.TENCENTCLOUD_CDN: + case DEPLOYMENT_PROVIDERS.TENCENTCLOUD_CDN: return ; - case DEPLOY_PROVIDERS.TENCENTCLOUD_CLB: + case DEPLOYMENT_PROVIDERS.TENCENTCLOUD_CLB: return ; - case DEPLOY_PROVIDERS.TENCENTCLOUD_COS: + case DEPLOYMENT_PROVIDERS.TENCENTCLOUD_COS: return ; - case DEPLOY_PROVIDERS.TENCENTCLOUD_CSS: + case DEPLOYMENT_PROVIDERS.TENCENTCLOUD_CSS: return ; - case DEPLOY_PROVIDERS.TENCENTCLOUD_ECDN: + case DEPLOYMENT_PROVIDERS.TENCENTCLOUD_ECDN: return ; - case DEPLOY_PROVIDERS.TENCENTCLOUD_EO: + case DEPLOYMENT_PROVIDERS.TENCENTCLOUD_EO: return ; - case DEPLOY_PROVIDERS.TENCENTCLOUD_SCF: + case DEPLOYMENT_PROVIDERS.TENCENTCLOUD_SCF: return ; - case DEPLOY_PROVIDERS.TENCENTCLOUD_SSL_DEPLOY: + case DEPLOYMENT_PROVIDERS.TENCENTCLOUD_SSL_DEPLOY: return ; - case DEPLOY_PROVIDERS.TENCENTCLOUD_VOD: + case DEPLOYMENT_PROVIDERS.TENCENTCLOUD_VOD: return ; - case DEPLOY_PROVIDERS.TENCENTCLOUD_WAF: + case DEPLOYMENT_PROVIDERS.TENCENTCLOUD_WAF: return ; - case DEPLOY_PROVIDERS.UCLOUD_UCDN: + case DEPLOYMENT_PROVIDERS.UCLOUD_UCDN: return ; - case DEPLOY_PROVIDERS.UCLOUD_US3: + case DEPLOYMENT_PROVIDERS.UCLOUD_US3: return ; - case DEPLOY_PROVIDERS.UPYUN_CDN: + case DEPLOYMENT_PROVIDERS.UPYUN_CDN: return ; - case DEPLOY_PROVIDERS.UPYUN_FILE: + case DEPLOYMENT_PROVIDERS.UPYUN_FILE: return ; - case DEPLOY_PROVIDERS.VOLCENGINE_ALB: + case DEPLOYMENT_PROVIDERS.VOLCENGINE_ALB: return ; - case DEPLOY_PROVIDERS.VOLCENGINE_CDN: + case DEPLOYMENT_PROVIDERS.VOLCENGINE_CDN: return ; - case DEPLOY_PROVIDERS.VOLCENGINE_CERTCENTER: + case DEPLOYMENT_PROVIDERS.VOLCENGINE_CERTCENTER: return ; - case DEPLOY_PROVIDERS.VOLCENGINE_CLB: + case DEPLOYMENT_PROVIDERS.VOLCENGINE_CLB: return ; - case DEPLOY_PROVIDERS.VOLCENGINE_DCDN: + case DEPLOYMENT_PROVIDERS.VOLCENGINE_DCDN: return ; - case DEPLOY_PROVIDERS.VOLCENGINE_IMAGEX: + case DEPLOYMENT_PROVIDERS.VOLCENGINE_IMAGEX: return ; - case DEPLOY_PROVIDERS.VOLCENGINE_LIVE: + case DEPLOYMENT_PROVIDERS.VOLCENGINE_LIVE: return ; - case DEPLOY_PROVIDERS.VOLCENGINE_TOS: + case DEPLOYMENT_PROVIDERS.VOLCENGINE_TOS: return ; - case DEPLOY_PROVIDERS.WANGSU_CDNPRO: + case DEPLOYMENT_PROVIDERS.WANGSU_CDNPRO: return ; - case DEPLOY_PROVIDERS.WEBHOOK: + case DEPLOYMENT_PROVIDERS.WEBHOOK: return ; } }, [disabled, initialValues?.providerConfig, fieldProvider, nestedFormInst, nestedFormName]); @@ -322,8 +331,6 @@ const DeployNodeConfigForm = forwardRef { - if (fieldProvider === value) return; - // 切换部署目标时重置表单,避免其他部署目标的配置字段影响当前部署目标 if (initialValues?.provider === value) { formInst.resetFields(); @@ -339,7 +346,7 @@ const DeployNodeConfigForm = forwardRef } + fallback={} > -
@@ -419,6 +425,7 @@ const DeployNodeConfigForm = forwardRef } + usage="both-dns-hosting" afterSubmit={(record) => { const provider = accessProvidersMap.get(record.provider); if (provider?.usages?.includes(ACCESS_USAGES.HOSTING)) { @@ -432,9 +439,8 @@ const DeployNodeConfigForm = forwardRef { - if (fieldProvider) { - return deployProvidersMap.get(fieldProvider)?.provider === record.provider; - } + if (record.reserve) return false; + if (fieldProvider) return deploymentProvidersMap.get(fieldProvider)?.provider === record.provider; const provider = accessProvidersMap.get(record.provider); return !!provider?.usages?.includes(ACCESS_USAGES.HOSTING); @@ -444,7 +450,7 @@ const DeployNodeConfigForm = forwardRef - + ; + +export type DeployNodeConfigFormAliyunDDoSConfigProps = { + form: FormInstance; + formName: string; + disabled?: boolean; + initialValues?: DeployNodeConfigFormAliyunDDoSConfigFieldValues; + onValuesChange?: (values: DeployNodeConfigFormAliyunDDoSConfigFieldValues) => void; +}; + +const initFormModel = (): DeployNodeConfigFormAliyunDDoSConfigFieldValues => { + return {}; +}; + +const DeployNodeConfigFormAliyunDDoSConfig = ({ + form: formInst, + formName, + disabled, + initialValues, + onValuesChange, +}: DeployNodeConfigFormAliyunDDoSConfigProps) => { + const { t } = useTranslation(); + + const formSchema = z.object({ + region: z + .string({ message: t("workflow_node.deploy.form.aliyun_ddos_region.placeholder") }) + .nonempty(t("workflow_node.deploy.form.aliyun_ddos_region.placeholder")) + .trim(), + domain: z + .string({ message: t("workflow_node.deploy.form.aliyun_ddos_domain.placeholder") }) + .refine((v) => validDomainName(v, { allowWildcard: true }), t("common.errmsg.domain_invalid")), + }); + const formRule = createSchemaFieldRule(formSchema); + + const handleFormChange = (_: unknown, values: z.infer) => { + onValuesChange?.(values); + }; + + return ( +
+ } + > + + + + } + > + + +
+ ); +}; + +export default DeployNodeConfigFormAliyunDDoSConfig; diff --git a/ui/src/components/workflow/node/DeployNodeConfigFormBunnyCDNConfig.tsx b/ui/src/components/workflow/node/DeployNodeConfigFormBunnyCDNConfig.tsx index 3b68f811..340de12c 100644 --- a/ui/src/components/workflow/node/DeployNodeConfigFormBunnyCDNConfig.tsx +++ b/ui/src/components/workflow/node/DeployNodeConfigFormBunnyCDNConfig.tsx @@ -6,7 +6,7 @@ import { validDomainName } from "@/utils/validators"; type DeployNodeConfigFormBunnyCDNConfigFieldValues = Nullish<{ pullZoneId: string | number; - hostName: string; + hostname: string; }>; export type DeployNodeConfigFormBunnyCDNConfigProps = { @@ -30,11 +30,11 @@ const DeployNodeConfigFormBunnyCDNConfig = ({ form: formInst, formName, disabled .refine((v) => { return /^\d+$/.test(v + "") && +v! > 0; }, t("workflow_node.deploy.form.bunny_cdn_pull_zone_id.placeholder")), - hostName: z - .string({ message: t("workflow_node.deploy.form.bunny_cdn_host_name.placeholder") }) - .nonempty(t("workflow_node.deploy.form.bunny_cdn_host_name.placeholder")) + hostname: z + .string({ message: t("workflow_node.deploy.form.bunny_cdn_hostname.placeholder") }) + .nonempty(t("workflow_node.deploy.form.bunny_cdn_hostname.placeholder")) .refine((v) => { - return !v || validDomainName(v!, { allowWildcard: true }); + return validDomainName(v!, { allowWildcard: true }); }, t("common.errmsg.domain_invalid")), }); const formRule = createSchemaFieldRule(formSchema); @@ -62,12 +62,12 @@ const DeployNodeConfigFormBunnyCDNConfig = ({ form: formInst, formName, disabled
} + tooltip={} > - + ); diff --git a/ui/src/components/workflow/node/DeployNodeConfigFormGoEdgeConfig.tsx b/ui/src/components/workflow/node/DeployNodeConfigFormGoEdgeConfig.tsx new file mode 100644 index 00000000..89dffb5f --- /dev/null +++ b/ui/src/components/workflow/node/DeployNodeConfigFormGoEdgeConfig.tsx @@ -0,0 +1,79 @@ +import { useTranslation } from "react-i18next"; +import { Form, type FormInstance, Input, Select } from "antd"; +import { createSchemaFieldRule } from "antd-zod"; +import { z } from "zod"; + +import Show from "@/components/Show"; + +type DeployNodeConfigFormGoEdgeConfigFieldValues = Nullish<{ + resourceType: string; + certificateId?: string | number; +}>; + +export type DeployNodeConfigFormGoEdgeConfigProps = { + form: FormInstance; + formName: string; + disabled?: boolean; + initialValues?: DeployNodeConfigFormGoEdgeConfigFieldValues; + onValuesChange?: (values: DeployNodeConfigFormGoEdgeConfigFieldValues) => void; +}; + +const RESOURCE_TYPE_CERTIFICATE = "certificate" as const; + +const initFormModel = (): DeployNodeConfigFormGoEdgeConfigFieldValues => { + return { + resourceType: RESOURCE_TYPE_CERTIFICATE, + certificateId: "", + }; +}; + +const DeployNodeConfigFormGoEdgeConfig = ({ form: formInst, formName, disabled, initialValues, onValuesChange }: DeployNodeConfigFormGoEdgeConfigProps) => { + const { t } = useTranslation(); + + const formSchema = z.object({ + resourceType: z.literal(RESOURCE_TYPE_CERTIFICATE, { + message: t("workflow_node.deploy.form.goedge_resource_type.placeholder"), + }), + certificateId: z + .union([z.string(), z.number().int()]) + .nullish() + .refine((v) => { + if (fieldResourceType !== RESOURCE_TYPE_CERTIFICATE) return true; + return /^\d+$/.test(v + "") && +v! > 0; + }, t("workflow_node.deploy.form.goedge_certificate_id.placeholder")), + }); + const formRule = createSchemaFieldRule(formSchema); + + const fieldResourceType = Form.useWatch("resourceType", formInst); + + const handleFormChange = (_: unknown, values: z.infer) => { + onValuesChange?.(values); + }; + + return ( +
+ + + + + + + + + +
+ ); +}; + +export default DeployNodeConfigFormGoEdgeConfig; diff --git a/ui/src/components/workflow/node/DeployNodeConfigFormLocalConfig.tsx b/ui/src/components/workflow/node/DeployNodeConfigFormLocalConfig.tsx index afde53b3..2ebae25d 100644 --- a/ui/src/components/workflow/node/DeployNodeConfigFormLocalConfig.tsx +++ b/ui/src/components/workflow/node/DeployNodeConfigFormLocalConfig.tsx @@ -45,6 +45,108 @@ const initFormModel = (): DeployNodeConfigFormLocalConfigFieldValues => { }; }; +export const initPresetScript = ( + key: "sh_backup_files" | "ps_backup_files" | "sh_reload_nginx" | "ps_binding_iis" | "ps_binding_netsh" | "ps_binding_rdp", + params?: { + certPath?: string; + keyPath?: string; + pfxPassword?: string; + jksAlias?: string; + jksKeypass?: string; + jksStorepass?: string; + } +) => { + switch (key) { + case "sh_backup_files": + return `# 请将以下路径替换为实际值 +cp "${params?.certPath || ""}" "${params?.certPath || ""}.bak" 2>/dev/null || : +cp "${params?.keyPath || ""}" "${params?.keyPath || ""}.bak" 2>/dev/null || : + `.trim(); + + case "ps_backup_files": + return `# 请将以下路径替换为实际值 +if (Test-Path -Path "${params?.certPath || ""}" -PathType Leaf) { + Copy-Item -Path "${params?.certPath || ""}" -Destination "${params?.certPath || ""}.bak" -Force +} +if (Test-Path -Path "${params?.keyPath || ""}" -PathType Leaf) { + Copy-Item -Path "${params?.keyPath || ""}" -Destination "${params?.keyPath || ""}.bak" -Force +} + `.trim(); + + case "sh_reload_nginx": + return `sudo service nginx reload`; + + case "ps_binding_iis": + return `# 需要管理员权限 +# 请将以下变量替换为实际值 +$pfxPath = "${params?.certPath || ""}" # PFX 文件路径 +$pfxPassword = "${params?.pfxPassword || ""}" # PFX 密码 +$siteName = "" # IIS 网站名称 +$domain = "" # 域名 +$ipaddr = "" # 绑定 IP,“*”表示所有 IP 绑定 +$port = "" # 绑定端口 + + +# 导入证书到本地计算机的个人存储区 +$cert = Import-PfxCertificate -FilePath "$pfxPath" -CertStoreLocation Cert:\\LocalMachine\\My -Password (ConvertTo-SecureString -String "$pfxPassword" -AsPlainText -Force) -Exportable +# 获取 Thumbprint +$thumbprint = $cert.Thumbprint +# 导入 WebAdministration 模块 +Import-Module WebAdministration +# 检查是否已存在 HTTPS 绑定 +$existingBinding = Get-WebBinding -Name "$siteName" -Protocol "https" -Port $port -HostHeader "$domain" -ErrorAction SilentlyContinue +if (!$existingBinding) { + # 添加新的 HTTPS 绑定 + New-WebBinding -Name "$siteName" -Protocol "https" -Port $port -IPAddress "$ipaddr" -HostHeader "$domain" +} +# 获取绑定对象 +$binding = Get-WebBinding -Name "$siteName" -Protocol "https" -Port $port -IPAddress "$ipaddr" -HostHeader "$domain" +# 绑定 SSL 证书 +$binding.AddSslCertificate($thumbprint, "My") +# 删除目录下的证书文件 +Remove-Item -Path "$pfxPath" -Force + `.trim(); + + case "ps_binding_netsh": + return `# 需要管理员权限 +# 请将以下变量替换为实际值 +$pfxPath = "${params?.certPath || ""}" # PFX 文件路径 +$pfxPassword = "${params?.pfxPassword || ""}" # PFX 密码 +$ipaddr = "" # 绑定 IP,“0.0.0.0”表示所有 IP 绑定,可填入域名。 +$port = "" # 绑定端口 + +$addr = $ipaddr + ":" + $port + +# 导入证书到本地计算机的个人存储区 +$cert = Import-PfxCertificate -FilePath "$pfxPath" -CertStoreLocation Cert:\\LocalMachine\\My -Password (ConvertTo-SecureString -String "$pfxPassword" -AsPlainText -Force) -Exportable +# 获取 Thumbprint +$thumbprint = $cert.Thumbprint +# 检测端口是否绑定证书,如绑定则删除绑定 +$isExist = netsh http show sslcert ipport=$addr +if ($isExist -like "*$addr*"){ netsh http delete sslcert ipport=$addr } +# 绑定到端口 +netsh http add sslcert ipport=$addr certhash=$thumbprint +# 删除目录下的证书文件 +Remove-Item -Path "$pfxPath" -Force + `.trim(); + + case "ps_binding_rdp": + return `# 需要管理员权限 +# 请将以下变量替换为实际值 +$pfxPath = "${params?.certPath || ""}" # PFX 文件路径 +$pfxPassword = "${params?.pfxPassword || ""}" # PFX 密码 + +# 导入证书到本地计算机的个人存储区 +$cert = Import-PfxCertificate -FilePath "$pfxPath" -CertStoreLocation Cert:\\LocalMachine\\My -Password (ConvertTo-SecureString -String "$pfxPassword" -AsPlainText -Force) -Exportable +# 获取 Thumbprint +$thumbprint = $cert.Thumbprint +# 绑定到 RDP +$rdpCertPath = "HKLM:\\SYSTEM\\CurrentControlSet\\Control\\Terminal Server\\WinStations\\RDP-Tcp" +Set-ItemProperty -Path $rdpCertPath -Name "SSLCertificateSHA1Hash" -Value "$thumbprint" + `.trim(); + } +}; + const DeployNodeConfigFormLocalConfig = ({ form: formInst, formName, disabled, initialValues, onValuesChange }: DeployNodeConfigFormLocalConfigProps) => { const { t } = useTranslation(); @@ -136,16 +238,15 @@ const DeployNodeConfigFormLocalConfig = ({ form: formInst, formName, disabled, i const handlePresetPreScriptClick = (key: string) => { switch (key) { - case "backup_files": + case "sh_backup_files": + case "ps_backup_files": { + const presetScriptParams = { + certPath: formInst.getFieldValue("certPath"), + keyPath: formInst.getFieldValue("keyPath"), + }; formInst.setFieldValue("shellEnv", SHELLENV_SH); - formInst.setFieldValue( - "preCommand", - `# 请将以下路径替换为实际值 -cp "${formInst.getFieldValue("certPath")}" "${formInst.getFieldValue("certPath")}.bak" 2>/dev/null || : -cp "${formInst.getFieldValue("keyPath")}" "${formInst.getFieldValue("keyPath")}.bak" 2>/dev/null || : - `.trim() - ); + formInst.setFieldValue("preCommand", initPresetScript(key, presetScriptParams)); } break; } @@ -153,97 +254,23 @@ cp "${formInst.getFieldValue("keyPath")}" "${formInst.getFieldValue("keyPath")}. const handlePresetPostScriptClick = (key: string) => { switch (key) { - case "reload_nginx": + case "sh_reload_nginx": { formInst.setFieldValue("shellEnv", SHELLENV_SH); - formInst.setFieldValue("postCommand", "sudo service nginx reload"); + formInst.setFieldValue("postCommand", initPresetScript(key)); } break; - case "binding_iis": + case "ps_binding_iis": + case "ps_binding_netsh": + case "ps_binding_rdp": { + const presetScriptParams = { + certPath: formInst.getFieldValue("certPath"), + pfxPassword: formInst.getFieldValue("pfxPassword"), + }; formInst.setFieldValue("shellEnv", SHELLENV_POWERSHELL); - formInst.setFieldValue( - "postCommand", - `# 请将以下变量替换为实际值 -$pfxPath = "${formInst.getFieldValue("certPath")}" # PFX 文件路径 -$pfxPassword = "${formInst.getFieldValue("pfxPassword")}" # PFX 密码 -$siteName = "" # IIS 网站名称 -$domain = "" # 域名 -$ipaddr = "" # 绑定 IP,“*”表示所有 IP 绑定 -$port = "" # 绑定端口 - - -# 导入证书到本地计算机的个人存储区 -$cert = Import-PfxCertificate -FilePath "$pfxPath" -CertStoreLocation Cert:\\LocalMachine\\My -Password (ConvertTo-SecureString -String "$pfxPassword" -AsPlainText -Force) -Exportable -# 获取 Thumbprint -$thumbprint = $cert.Thumbprint -# 导入 WebAdministration 模块 -Import-Module WebAdministration -# 检查是否已存在 HTTPS 绑定 -$existingBinding = Get-WebBinding -Name "$siteName" -Protocol "https" -Port $port -HostHeader "$domain" -ErrorAction SilentlyContinue -if (!$existingBinding) { - # 添加新的 HTTPS 绑定 - New-WebBinding -Name "$siteName" -Protocol "https" -Port $port -IPAddress "$ipaddr" -HostHeader "$domain" -} -# 获取绑定对象 -$binding = Get-WebBinding -Name "$siteName" -Protocol "https" -Port $port -IPAddress "$ipaddr" -HostHeader "$domain" -# 绑定 SSL 证书 -$binding.AddSslCertificate($thumbprint, "My") -# 删除目录下的证书文件 -Remove-Item -Path "$pfxPath" -Force - `.trim() - ); - } - break; - - case "binding_netsh": - { - formInst.setFieldValue("shellEnv", SHELLENV_POWERSHELL); - formInst.setFieldValue( - "postCommand", - `# 请将以下变量替换为实际值 -$pfxPath = "${formInst.getFieldValue("certPath")}" # PFX 文件路径 -$pfxPassword = "${formInst.getFieldValue("pfxPassword")}" # PFX 密码 -$ipaddr = "" # 绑定 IP,“0.0.0.0”表示所有 IP 绑定,可填入域名。 -$port = "" # 绑定端口 - -$addr = $ipaddr + ":" + $port - -# 导入证书到本地计算机的个人存储区 -$cert = Import-PfxCertificate -FilePath "$pfxPath" -CertStoreLocation Cert:\\LocalMachine\\My -Password (ConvertTo-SecureString -String "$pfxPassword" -AsPlainText -Force) -Exportable -# 获取 Thumbprint -$thumbprint = $cert.Thumbprint -# 检测端口是否绑定证书,如绑定则删除绑定 -$isExist = netsh http show sslcert ipport=$addr -if ($isExist -like "*$addr*"){ netsh http delete sslcert ipport=$addr } -# 绑定到端口 -netsh http add sslcert ipport=$addr certhash=$thumbprint -# 删除目录下的证书文件 -Remove-Item -Path "$pfxPath" -Force - `.trim() - ); - } - break; - - case "binding_rdp": - { - formInst.setFieldValue("shellEnv", SHELLENV_POWERSHELL); - formInst.setFieldValue( - "postCommand", - `# 请将以下变量替换为实际值 -$pfxPath = "${formInst.getFieldValue("certPath")}" # PFX 文件路径 -$pfxPassword = "${formInst.getFieldValue("pfxPassword")}" # PFX 密码 - -# 导入证书到本地计算机的个人存储区 -$cert = Import-PfxCertificate -FilePath "$pfxPath" -CertStoreLocation Cert:\\LocalMachine\\My -Password (ConvertTo-SecureString -String "$pfxPassword" -AsPlainText -Force) -Exportable -# 获取 Thumbprint -$thumbprint = $cert.Thumbprint -# 绑定到 RDP -$rdpCertPath = "HKLM:\SYSTEM\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp" -Set-ItemProperty -Path $rdpCertPath -Name "SSLCertificateSHA1Hash" -Value "$thumbprint" - `.trim() - ); + formInst.setFieldValue("postCommand", initPresetScript(key, presetScriptParams)); } break; } @@ -359,13 +386,11 @@ Set-ItemProperty -Path $rdpCertPath -Name "SSLCertificateSHA1Hash" -Value "$thum
handlePresetPreScriptClick("backup_files"), - }, - ], + items: ["sh_backup_files", "ps_backup_files"].map((key) => ({ + key, + label: t(`workflow_node.deploy.form.local_preset_scripts.option.${key}.label`), + onClick: () => handlePresetPreScriptClick(key), + })), }} trigger={["click"]} > @@ -391,28 +416,11 @@ Set-ItemProperty -Path $rdpCertPath -Name "SSLCertificateSHA1Hash" -Value "$thum
handlePresetPostScriptClick("reload_nginx"), - }, - { - key: "binding_iis", - label: t("workflow_node.deploy.form.local_preset_scripts.option.binding_iis.label"), - onClick: () => handlePresetPostScriptClick("binding_iis"), - }, - { - key: "binding_netsh", - label: t("workflow_node.deploy.form.local_preset_scripts.option.binding_netsh.label"), - onClick: () => handlePresetPostScriptClick("binding_netsh"), - }, - { - key: "binding_rdp", - label: t("workflow_node.deploy.form.local_preset_scripts.option.binding_rdp.label"), - onClick: () => handlePresetPostScriptClick("binding_rdp"), - }, - ], + items: ["sh_reload_nginx", "ps_binding_iis", "ps_binding_netsh", "ps_binding_rdp"].map((key) => ({ + key, + label: t(`workflow_node.deploy.form.local_preset_scripts.option.${key}.label`), + onClick: () => handlePresetPostScriptClick(key), + })), }} trigger={["click"]} > diff --git a/ui/src/components/workflow/node/DeployNodeConfigFormProxmoxVEConfig.tsx b/ui/src/components/workflow/node/DeployNodeConfigFormProxmoxVEConfig.tsx new file mode 100644 index 00000000..444b1082 --- /dev/null +++ b/ui/src/components/workflow/node/DeployNodeConfigFormProxmoxVEConfig.tsx @@ -0,0 +1,66 @@ +import { useTranslation } from "react-i18next"; +import { Form, type FormInstance, Input, Switch } from "antd"; +import { createSchemaFieldRule } from "antd-zod"; +import { z } from "zod"; + +type DeployNodeConfigFormProxmoxVEConfigFieldValues = Nullish<{ + nodeName: string; + autoRestart?: boolean; +}>; + +export type DeployNodeConfigFormProxmoxVEConfigProps = { + form: FormInstance; + formName: string; + disabled?: boolean; + initialValues?: DeployNodeConfigFormProxmoxVEConfigFieldValues; + onValuesChange?: (values: DeployNodeConfigFormProxmoxVEConfigFieldValues) => void; +}; + +const initFormModel = (): DeployNodeConfigFormProxmoxVEConfigFieldValues => { + return { + autoRestart: true, + }; +}; + +const DeployNodeConfigFormProxmoxVEConfig = ({ + form: formInst, + formName, + disabled, + initialValues, + onValuesChange, +}: DeployNodeConfigFormProxmoxVEConfigProps) => { + const { t } = useTranslation(); + + const formSchema = z.object({ + nodeName: z + .string({ message: t("workflow_node.deploy.form.proxmoxve_node_name.placeholder") }) + .nonempty(t("workflow_node.deploy.form.proxmoxve_node_name.placeholder")), + autoRestart: z.boolean().nullish(), + }); + const formRule = createSchemaFieldRule(formSchema); + + const handleFormChange = (_: unknown, values: z.infer) => { + onValuesChange?.(values); + }; + + return ( +
+ + + + + + + +
+ ); +}; + +export default DeployNodeConfigFormProxmoxVEConfig; diff --git a/ui/src/components/workflow/node/DeployNodeConfigFormSSHConfig.tsx b/ui/src/components/workflow/node/DeployNodeConfigFormSSHConfig.tsx index c6d5db5a..21d76222 100644 --- a/ui/src/components/workflow/node/DeployNodeConfigFormSSHConfig.tsx +++ b/ui/src/components/workflow/node/DeployNodeConfigFormSSHConfig.tsx @@ -7,6 +7,8 @@ import { z } from "zod"; import Show from "@/components/Show"; import { CERTIFICATE_FORMATS } from "@/domain/certificate"; +import { initPresetScript } from "./DeployNodeConfigFormLocalConfig"; + type DeployNodeConfigFormSSHConfigFieldValues = Nullish<{ format: string; certPath: string; @@ -129,15 +131,14 @@ const DeployNodeConfigFormSSHConfig = ({ form: formInst, formName, disabled, ini const handlePresetPreScriptClick = (key: string) => { switch (key) { - case "backup_files": + case "sh_backup_files": + case "ps_backup_files": { - formInst.setFieldValue( - "preCommand", - `# 请将以下路径替换为实际值 -cp "${formInst.getFieldValue("certPath")}" "${formInst.getFieldValue("certPath")}.bak" 2>/dev/null || : -cp "${formInst.getFieldValue("keyPath")}" "${formInst.getFieldValue("keyPath")}.bak" 2>/dev/null || : - `.trim() - ); + const presetScriptParams = { + certPath: formInst.getFieldValue("certPath"), + keyPath: formInst.getFieldValue("keyPath"), + }; + formInst.setFieldValue("preCommand", initPresetScript(key, presetScriptParams)); } break; } @@ -145,9 +146,16 @@ cp "${formInst.getFieldValue("keyPath")}" "${formInst.getFieldValue("keyPath")}. const handlePresetPostScriptClick = (key: string) => { switch (key) { - case "reload_nginx": + case "sh_reload_nginx": + case "ps_binding_iis": + case "ps_binding_netsh": + case "ps_binding_rdp": { - formInst.setFieldValue("postCommand", "sudo service nginx reload"); + const presetScriptParams = { + certPath: formInst.getFieldValue("certPath"), + pfxPassword: formInst.getFieldValue("pfxPassword"), + }; + formInst.setFieldValue("postCommand", initPresetScript(key, presetScriptParams)); } break; } @@ -253,13 +261,11 @@ cp "${formInst.getFieldValue("keyPath")}" "${formInst.getFieldValue("keyPath")}.
handlePresetPreScriptClick("backup_files"), - }, - ], + items: ["sh_backup_files", "ps_backup_files"].map((key) => ({ + key, + label: t(`workflow_node.deploy.form.ssh_preset_scripts.option.${key}.label`), + onClick: () => handlePresetPreScriptClick(key), + })), }} trigger={["click"]} > @@ -285,13 +291,11 @@ cp "${formInst.getFieldValue("keyPath")}" "${formInst.getFieldValue("keyPath")}.
handlePresetPostScriptClick("reload_nginx"), - }, - ], + items: ["sh_reload_nginx", "ps_binding_iis", "ps_binding_netsh", "ps_binding_rdp"].map((key) => ({ + key, + label: t(`workflow_node.deploy.form.ssh_preset_scripts.option.${key}.label`), + onClick: () => handlePresetPostScriptClick(key), + })), }} trigger={["click"]} > diff --git a/ui/src/components/workflow/node/DeployNodeConfigFormWebhookConfig.tsx b/ui/src/components/workflow/node/DeployNodeConfigFormWebhookConfig.tsx index b916abf1..8305da8c 100644 --- a/ui/src/components/workflow/node/DeployNodeConfigFormWebhookConfig.tsx +++ b/ui/src/components/workflow/node/DeployNodeConfigFormWebhookConfig.tsx @@ -1,5 +1,5 @@ import { useTranslation } from "react-i18next"; -import { Alert, Button, Form, type FormInstance, Input } from "antd"; +import { Alert, Form, type FormInstance, Input } from "antd"; import { createSchemaFieldRule } from "antd-zod"; import { z } from "zod"; @@ -16,31 +16,26 @@ export type DeployNodeConfigFormWebhookConfigProps = { }; const initFormModel = (): DeployNodeConfigFormWebhookConfigFieldValues => { - return { - webhookData: JSON.stringify( - { - name: "${DOMAINS}", - cert: "${CERTIFICATE}", - privkey: "${PRIVATE_KEY}", - }, - null, - 2 - ), - }; + return {}; }; const DeployNodeConfigFormWebhookConfig = ({ form: formInst, formName, disabled, initialValues, onValuesChange }: DeployNodeConfigFormWebhookConfigProps) => { const { t } = useTranslation(); const formSchema = z.object({ - webhookData: z.string({ message: t("workflow_node.deploy.form.webhook_data.placeholder") }).refine((v) => { - try { - JSON.parse(v); - return true; - } catch { - return false; - } - }, t("workflow_node.deploy.form.webhook_data.errmsg.json_invalid")), + webhookData: z + .string() + .nullish() + .refine((v) => { + if (!v) return true; + + try { + const obj = JSON.parse(v); + return typeof obj === "object" && !Array.isArray(obj); + } catch { + return false; + } + }, t("workflow_node.deploy.form.webhook_data.errmsg.json_invalid")), }); const formRule = createSchemaFieldRule(formSchema); @@ -54,10 +49,6 @@ const DeployNodeConfigFormWebhookConfig = ({ form: formInst, formName, disabled, } }; - const handlePresetDataClick = () => { - formInst.setFieldValue("webhookData", initFormModel().webhookData); - }; - const handleFormChange = (_: unknown, values: z.infer) => { onValuesChange?.(values); }; @@ -71,24 +62,18 @@ const DeployNodeConfigFormWebhookConfig = ({ form: formInst, formName, disabled, name={formName} onValuesChange={handleFormChange} > - - - - - + } + > + diff --git a/ui/src/components/workflow/node/NotifyNode.tsx b/ui/src/components/workflow/node/NotifyNode.tsx index 4ac35ab5..16132539 100644 --- a/ui/src/components/workflow/node/NotifyNode.tsx +++ b/ui/src/components/workflow/node/NotifyNode.tsx @@ -1,8 +1,9 @@ import { memo, useMemo, useRef, useState } from "react"; import { useTranslation } from "react-i18next"; -import { Flex, Typography } from "antd"; +import { Avatar, Flex, Typography } from "antd"; import { produce } from "immer"; +import { notificationProvidersMap } from "@/domain/provider"; import { notifyChannelsMap } from "@/domain/settings"; import { type WorkflowNodeConfigForNotify, WorkflowNodeType } from "@/domain/workflow"; import { useZustandShallowSelector } from "@/hooks"; @@ -39,9 +40,11 @@ const NotifyNode = ({ node, disabled }: NotifyNodeProps) => { const config = (node.config as WorkflowNodeConfigForNotify) ?? {}; const channel = notifyChannelsMap.get(config.channel as string); + const provider = notificationProvidersMap.get(config.provider); return ( - {t(channel?.name ?? " ")} + + {t(channel?.name ?? provider?.name ?? " ")} {config.subject ?? ""} diff --git a/ui/src/components/workflow/node/NotifyNodeConfigForm.tsx b/ui/src/components/workflow/node/NotifyNodeConfigForm.tsx index 413a9d74..13dc1019 100644 --- a/ui/src/components/workflow/node/NotifyNodeConfigForm.tsx +++ b/ui/src/components/workflow/node/NotifyNodeConfigForm.tsx @@ -1,16 +1,27 @@ -import { forwardRef, memo, useEffect, useImperativeHandle } from "react"; +import { forwardRef, memo, useEffect, useImperativeHandle, useMemo, useState } from "react"; import { useTranslation } from "react-i18next"; import { Link } from "react-router"; -import { RightOutlined as RightOutlinedIcon } from "@ant-design/icons"; -import { Button, Form, type FormInstance, Input, Select } from "antd"; +import { PlusOutlined as PlusOutlinedIcon, RightOutlined as RightOutlinedIcon } from "@ant-design/icons"; +import { Button, Divider, Form, type FormInstance, Input, Select, Typography } from "antd"; import { createSchemaFieldRule } from "antd-zod"; import { z } from "zod"; +import AccessEditModal from "@/components/access/AccessEditModal"; +import AccessSelect from "@/components/access/AccessSelect"; +import NotificationProviderSelect from "@/components/provider/NotificationProviderSelect"; +import Show from "@/components/Show"; +import { ACCESS_USAGES, NOTIFICATION_PROVIDERS, accessProvidersMap, notificationProvidersMap } from "@/domain/provider"; import { notifyChannelsMap } from "@/domain/settings"; import { type WorkflowNodeConfigForNotify } from "@/domain/workflow"; -import { useAntdForm, useZustandShallowSelector } from "@/hooks"; +import { useAntdForm, useAntdFormName, useZustandShallowSelector } from "@/hooks"; +import { useAccessesStore } from "@/stores/access"; import { useNotifyChannelsStore } from "@/stores/notify"; +import NotifyNodeConfigFormEmailConfig from "./NotifyNodeConfigFormEmailConfig"; +import NotifyNodeConfigFormMattermostConfig from "./NotifyNodeConfigFormMattermostConfig"; +import NotifyNodeConfigFormTelegramConfig from "./NotifyNodeConfigFormTelegramConfig"; +import NotifyNodeConfigFormWebhookConfig from "./NotifyNodeConfigFormWebhookConfig"; + type NotifyNodeConfigFormFieldValues = Partial; export type NotifyNodeConfigFormProps = { @@ -35,6 +46,8 @@ const NotifyNodeConfigForm = forwardRef { const { t } = useTranslation(); + const { accesses } = useAccessesStore(useZustandShallowSelector("accesses")); + const { channels, loadedAtOnce: channelsLoadedAtOnce, @@ -53,7 +66,12 @@ const NotifyNodeConfigForm = forwardRef("provider", { form: formInst, preserve: true }); + const fieldProviderAccessId = Form.useWatch("providerAccessId", formInst); + + const [showProvider, setShowProvider] = useState(false); + useEffect(() => { + // 通常情况下每个授权信息只对应一个消息通知提供商,此时无需显示消息通知提供商字段; + // 如果对应多个,则显示。 + if (fieldProviderAccessId) { + const access = accesses.find((e) => e.id === fieldProviderAccessId); + const providers = Array.from(notificationProvidersMap.values()).filter((e) => e.provider === access?.provider); + setShowProvider(providers.length > 1); + } else { + setShowProvider(false); + } + }, [accesses, fieldProviderAccessId]); + + const [nestedFormInst] = Form.useForm(); + const nestedFormName = useAntdFormName({ form: nestedFormInst, name: "workflowNodeNotifyConfigFormProviderConfigForm" }); + const nestedFormEl = useMemo(() => { + const nestedFormProps = { + form: nestedFormInst, + formName: nestedFormName, + disabled: disabled, + initialValues: initialValues?.providerConfig, + }; + + /* + 注意:如果追加新的子组件,请保持以 ASCII 排序。 + NOTICE: If you add new child component, please keep ASCII order. + */ + switch (fieldProvider) { + case NOTIFICATION_PROVIDERS.EMAIL: + return ; + case NOTIFICATION_PROVIDERS.MATTERMOST: + return ; + case NOTIFICATION_PROVIDERS.TELEGRAM: + return ; + case NOTIFICATION_PROVIDERS.WEBHOOK: + return ; + } + }, [disabled, initialValues?.providerConfig, fieldProvider, nestedFormInst, nestedFormName]); + + const handleProviderSelect = (value: string) => { + // 切换消息通知提供商时联动授权信息 + if (initialValues?.provider === value) { + formInst.setFieldValue("providerAccessId", initialValues?.providerAccessId); + onValuesChange?.(formInst.getFieldsValue(true)); + } else { + if (notificationProvidersMap.get(fieldProvider)?.provider !== notificationProvidersMap.get(value)?.provider) { + formInst.setFieldValue("providerAccessId", undefined); + onValuesChange?.(formInst.getFieldsValue(true)); + } + } + }; + + const handleProviderAccessSelect = (value: string) => { + // 切换授权信息时联动消息通知提供商 + const access = accesses.find((access) => access.id === value); + const provider = Array.from(notificationProvidersMap.values()).find((provider) => provider.provider === access?.provider); + if (fieldProvider !== provider?.type) { + formInst.setFieldValue("provider", provider?.type); + onValuesChange?.(formInst.getFieldsValue(true)); + } + }; + const handleFormChange = (_: unknown, values: z.infer) => { onValuesChange?.(values as NotifyNodeConfigFormFieldValues); }; @@ -68,13 +151,21 @@ const NotifyNodeConfigForm = forwardRef { return { getFieldsValue: () => { - return formInst.getFieldsValue(true); + const values = formInst.getFieldsValue(true); + values.providerConfig = nestedFormInst.getFieldsValue(); + return values; }, resetFields: (fields) => { - return formInst.resetFields(fields as (keyof NotifyNodeConfigFormFieldValues)[]); + formInst.resetFields(fields); + + if (!!fields && fields.includes("providerConfig")) { + nestedFormInst.resetFields(fields); + } }, validateFields: (nameList, config) => { - return formInst.validateFields(nameList, config); + const t1 = formInst.validateFields(nameList, config); + const t2 = nestedFormInst.validateFields(undefined, config); + return Promise.all([t1, t2]).then(() => t1); }, } as NotifyNodeConfigFormInstance; }); @@ -92,7 +183,7 @@ const NotifyNodeConfigForm = forwardRef + + { + if (record.reserve !== "notification") return false; + + const provider = accessProvidersMap.get(record.provider); + return !!provider?.usages?.includes(ACCESS_USAGES.NOTIFICATION); + }} + placeholder={t("workflow_node.notify.form.provider_access.placeholder")} + onChange={handleProviderAccessSelect} + /> + + + + + + + {t("workflow_node.notify.form.params_config.label")} + + + + {nestedFormEl} + ); } diff --git a/ui/src/components/workflow/node/NotifyNodeConfigFormEmailConfig.tsx b/ui/src/components/workflow/node/NotifyNodeConfigFormEmailConfig.tsx new file mode 100644 index 00000000..b6bfed17 --- /dev/null +++ b/ui/src/components/workflow/node/NotifyNodeConfigFormEmailConfig.tsx @@ -0,0 +1,80 @@ +import { useTranslation } from "react-i18next"; +import { Form, type FormInstance, Input } from "antd"; +import { createSchemaFieldRule } from "antd-zod"; +import { z } from "zod"; + +import { validEmailAddress } from "@/utils/validators"; + +type NotifyNodeConfigFormEmailConfigFieldValues = Nullish<{ + senderAddress?: string; + receiverAddress?: string; +}>; + +export type NotifyNodeConfigFormEmailConfigProps = { + form: FormInstance; + formName: string; + disabled?: boolean; + initialValues?: NotifyNodeConfigFormEmailConfigFieldValues; + onValuesChange?: (values: NotifyNodeConfigFormEmailConfigFieldValues) => void; +}; + +const initFormModel = (): NotifyNodeConfigFormEmailConfigFieldValues => { + return {}; +}; + +const NotifyNodeConfigFormEmailConfig = ({ form: formInst, formName, disabled, initialValues, onValuesChange }: NotifyNodeConfigFormEmailConfigProps) => { + const { t } = useTranslation(); + + const formSchema = z.object({ + senderAddress: z + .string() + .nullish() + .refine((v) => { + if (!v) return true; + return validEmailAddress(v); + }, t("common.errmsg.email_invalid")), + receiverAddress: z + .string() + .nullish() + .refine((v) => { + if (!v) return true; + return validEmailAddress(v); + }, t("common.errmsg.email_invalid")), + }); + const formRule = createSchemaFieldRule(formSchema); + + const handleFormChange = (_: unknown, values: z.infer) => { + onValuesChange?.(values); + }; + + return ( +
+ } + > + + + + } + > + + +
+ ); +}; + +export default NotifyNodeConfigFormEmailConfig; diff --git a/ui/src/components/workflow/node/NotifyNodeConfigFormMattermostConfig.tsx b/ui/src/components/workflow/node/NotifyNodeConfigFormMattermostConfig.tsx new file mode 100644 index 00000000..c091298b --- /dev/null +++ b/ui/src/components/workflow/node/NotifyNodeConfigFormMattermostConfig.tsx @@ -0,0 +1,61 @@ +import { useTranslation } from "react-i18next"; +import { Form, type FormInstance, Input } from "antd"; +import { createSchemaFieldRule } from "antd-zod"; +import { z } from "zod"; + +type NotifyNodeConfigFormMattermostConfigFieldValues = Nullish<{ + channelId?: string; +}>; + +export type NotifyNodeConfigFormMattermostConfigProps = { + form: FormInstance; + formName: string; + disabled?: boolean; + initialValues?: NotifyNodeConfigFormMattermostConfigFieldValues; + onValuesChange?: (values: NotifyNodeConfigFormMattermostConfigFieldValues) => void; +}; + +const initFormModel = (): NotifyNodeConfigFormMattermostConfigFieldValues => { + return {}; +}; + +const NotifyNodeConfigFormMattermostConfig = ({ + form: formInst, + formName, + disabled, + initialValues, + onValuesChange, +}: NotifyNodeConfigFormMattermostConfigProps) => { + const { t } = useTranslation(); + + const formSchema = z.object({ + channelId: z.string().nullish(), + }); + const formRule = createSchemaFieldRule(formSchema); + + const handleFormChange = (_: unknown, values: z.infer) => { + onValuesChange?.(values); + }; + + return ( +
+ } + > + + +
+ ); +}; + +export default NotifyNodeConfigFormMattermostConfig; diff --git a/ui/src/components/workflow/node/NotifyNodeConfigFormTelegramConfig.tsx b/ui/src/components/workflow/node/NotifyNodeConfigFormTelegramConfig.tsx new file mode 100644 index 00000000..07774413 --- /dev/null +++ b/ui/src/components/workflow/node/NotifyNodeConfigFormTelegramConfig.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 NotifyNodeConfigFormTelegramConfigFieldValues = Nullish<{ + chatId?: string | number; +}>; + +export type NotifyNodeConfigFormTelegramConfigProps = { + form: FormInstance; + formName: string; + disabled?: boolean; + initialValues?: NotifyNodeConfigFormTelegramConfigFieldValues; + onValuesChange?: (values: NotifyNodeConfigFormTelegramConfigFieldValues) => void; +}; + +const initFormModel = (): NotifyNodeConfigFormTelegramConfigFieldValues => { + return {}; +}; + +const NotifyNodeConfigFormTelegramConfig = ({ form: formInst, formName, disabled, initialValues, onValuesChange }: NotifyNodeConfigFormTelegramConfigProps) => { + const { t } = useTranslation(); + + const formSchema = z.object({ + chatId: z + .preprocess( + (v) => (v == null || v === "" ? undefined : Number(v)), + z + .number() + .nullish() + .refine((v) => { + if (v == null || v + "" === "") return true; + return /^\d+$/.test(v + "") && +v! > 0; + }, t("workflow_node.notify.form.telegram_chat_id.placeholder")) + ) + .nullish(), + }); + const formRule = createSchemaFieldRule(formSchema); + + const handleFormChange = (_: unknown, values: z.infer) => { + onValuesChange?.(values); + }; + + return ( +
+ } + > + + +
+ ); +}; + +export default NotifyNodeConfigFormTelegramConfig; diff --git a/ui/src/components/workflow/node/NotifyNodeConfigFormWebhookConfig.tsx b/ui/src/components/workflow/node/NotifyNodeConfigFormWebhookConfig.tsx new file mode 100644 index 00000000..acaf00c2 --- /dev/null +++ b/ui/src/components/workflow/node/NotifyNodeConfigFormWebhookConfig.tsx @@ -0,0 +1,86 @@ +import { useTranslation } from "react-i18next"; +import { Alert, Form, type FormInstance, Input } from "antd"; +import { createSchemaFieldRule } from "antd-zod"; +import { z } from "zod"; + +type NotifyNodeConfigFormWebhookConfigFieldValues = Nullish<{ + webhookData: string; +}>; + +export type NotifyNodeConfigFormWebhookConfigProps = { + form: FormInstance; + formName: string; + disabled?: boolean; + initialValues?: NotifyNodeConfigFormWebhookConfigFieldValues; + onValuesChange?: (values: NotifyNodeConfigFormWebhookConfigFieldValues) => void; +}; + +const initFormModel = (): NotifyNodeConfigFormWebhookConfigFieldValues => { + return {}; +}; + +const NotifyNodeConfigFormWebhookConfig = ({ form: formInst, formName, disabled, initialValues, onValuesChange }: NotifyNodeConfigFormWebhookConfigProps) => { + const { t } = useTranslation(); + + const formSchema = z.object({ + webhookData: z + .string() + .nullish() + .refine((v) => { + if (!v) return true; + + try { + const obj = JSON.parse(v); + return typeof obj === "object" && !Array.isArray(obj); + } catch { + return false; + } + }, t("workflow_node.notify.form.webhook_data.errmsg.json_invalid")), + }); + const formRule = createSchemaFieldRule(formSchema); + + const handleWebhookDataBlur = (e: React.FocusEvent) => { + const value = e.target.value; + try { + const json = JSON.stringify(JSON.parse(value), null, 2); + formInst.setFieldValue("webhookData", json); + } catch { + return; + } + }; + + const handleFormChange = (_: unknown, values: z.infer) => { + onValuesChange?.(values); + }; + + return ( +
+ } + > + + + + + } /> + +
+ ); +}; + +export default NotifyNodeConfigFormWebhookConfig; diff --git a/ui/src/domain/access.ts b/ui/src/domain/access.ts index 2b217e11..1cac27ba 100644 --- a/ui/src/domain/access.ts +++ b/ui/src/domain/access.ts @@ -22,27 +22,34 @@ export interface AccessModel extends BaseModel { | AccessConfigForClouDNS | AccessConfigForCMCCCloud | AccessConfigForDeSEC + | AccessConfigForDingTalkBot | AccessConfigForDNSLA | AccessConfigForDogeCloud | AccessConfigForDynv6 | AccessConfigForEdgio + | AccessConfigForEmail | AccessConfigForGcore | AccessConfigForGname | AccessConfigForGoDaddy + | AccessConfigForGoEdge | AccessConfigForGoogleTrustServices | AccessConfigForHuaweiCloud | AccessConfigForJDCloud | AccessConfigForKubernetes + | AccessConfigForLarkBot + | AccessConfigForMattermost | AccessConfigForNamecheap | AccessConfigForNameDotCom | AccessConfigForNameSilo | AccessConfigForPorkbun | AccessConfigForPowerDNS + | AccessConfigForProxmoxVE | AccessConfigForQiniu | AccessConfigForRainYun | AccessConfigForSafeLine | AccessConfigForSSH | AccessConfigForSSLCom + | AccessConfigForTelegram | AccessConfigForTencentCloud | AccessConfigForUCloud | AccessConfigForUpyun @@ -50,9 +57,11 @@ export interface AccessModel extends BaseModel { | AccessConfigForVolcEngine | AccessConfigForWangsu | AccessConfigForWebhook + | AccessConfigForWeComBot | AccessConfigForWestcn | AccessConfigForZeroSSL ); + reserve?: "ca" | "notification"; } // #region AccessConfig @@ -118,6 +127,7 @@ export type AccessConfigForCdnfly = { apiUrl: string; apiKey: string; apiSecret: string; + allowInsecureConnections?: boolean; }; export type AccessConfigForCloudflare = { @@ -139,6 +149,11 @@ export type AccessConfigForDeSEC = { token: string; }; +export type AccessConfigForDingTalkBot = { + webhookUrl: string; + secret?: string; +}; + export type AccessConfigForDNSLA = { apiId: string; apiSecret: string; @@ -158,6 +173,16 @@ export type AccessConfigForEdgio = { clientSecret: string; }; +export type AccessConfigForEmail = { + smtpHost: string; + smtpPort: number; + smtpTls: boolean; + username: string; + password: string; + defaultSenderAddress?: string; + defaultReceiverAddress?: string; +}; + export type AccessConfigForGcore = { apiToken: string; }; @@ -172,6 +197,13 @@ export type AccessConfigForGoDaddy = { apiSecret: string; }; +export type AccessConfigForGoEdge = { + apiUrl: string; + accessKeyId: string; + accessKey: string; + allowInsecureConnections?: boolean; +}; + export type AccessConfigForGoogleTrustServices = { eabKid: string; eabHmacKey: string; @@ -191,6 +223,17 @@ export type AccessConfigForKubernetes = { kubeConfig?: string; }; +export type AccessConfigForLarkBot = { + webhookUrl: string; +}; + +export type AccessConfigForMattermost = { + serverUrl: string; + username: string; + password: string; + defaultChannelId?: string; +}; + export type AccessConfigForNamecheap = { username: string; apiKey: string; @@ -217,6 +260,14 @@ export type AccessConfigForPorkbun = { export type AccessConfigForPowerDNS = { apiUrl: string; apiKey: string; + allowInsecureConnections?: boolean; +}; + +export type AccessConfigForProxmoxVE = { + apiUrl: string; + apiToken: string; + apiTokenSecret?: string; + allowInsecureConnections?: boolean; }; export type AccessConfigForQiniu = { @@ -248,6 +299,11 @@ export type AccessConfigForSSLCom = { eabHmacKey: string; }; +export type AccessConfigForTelegram = { + botToken: string; + defaultChatId?: number; +}; + export type AccessConfigForTencentCloud = { secretId: string; secretKey: string; @@ -282,7 +338,15 @@ export type AccessConfigForWangsu = { export type AccessConfigForWebhook = { url: string; + method: string; + headers?: string; allowInsecureConnections?: boolean; + defaultDataForDeployment?: string; + defaultDataForNotification?: string; +}; + +export type AccessConfigForWeComBot = { + webhookUrl: string; }; export type AccessConfigForWestcn = { diff --git a/ui/src/domain/provider.ts b/ui/src/domain/provider.ts index a91e34cf..6fc29ad4 100644 --- a/ui/src/domain/provider.ts +++ b/ui/src/domain/provider.ts @@ -21,31 +21,38 @@ export const ACCESS_PROVIDERS = Object.freeze({ CLOUDNS: "cloudns", CMCCCLOUD: "cmcccloud", DESEC: "desec", + DINGTALKBOT: "dingtalkbot", DNSLA: "dnsla", DOGECLOUD: "dogecloud", DYNV6: "dynv6", EDGIO: "edgio", + EMAIL: "email", GCORE: "gcore", GNAME: "gname", GODADDY: "godaddy", + GOEDGE: "goedge", GOOGLETRUSTSERVICES: "googletrustservices", HUAWEICLOUD: "huaweicloud", JDCLOUD: "jdcloud", KUBERNETES: "k8s", + LARKBOT: "larkbot", LETSENCRYPT: "letsencrypt", LETSENCRYPTSTAGING: "letsencryptstaging", LOCAL: "local", + MATTERMOST: "mattermost", NAMECHEAP: "namecheap", NAMEDOTCOM: "namedotcom", NAMESILO: "namesilo", NS1: "ns1", PORKBUN: "porkbun", POWERDNS: "powerdns", + PROXMOXVE: "proxmoxve", QINIU: "qiniu", RAINYUN: "rainyun", SAFELINE: "safeline", SSH: "ssh", SSLCOM: "sslcom", + TELEGRAM: "telegram", TENCENTCLOUD: "tencentcloud", UCLOUD: "ucloud", UPYUN: "upyun", @@ -53,6 +60,7 @@ export const ACCESS_PROVIDERS = Object.freeze({ VOLCENGINE: "volcengine", WANGSU: "wangsu", WEBHOOK: "webhook", + WECOMBOT: "wecombot", WESTCN: "westcn", ZEROSSL: "zerossl", } as const); @@ -112,6 +120,8 @@ export const accessProvidersMap: Map [ e[0] as string, { @@ -150,12 +167,12 @@ export const accessProvidersMap: Map = new Map( +export const caProvidersMap: Map = new Map( /* 注意:此处的顺序决定显示在前端的顺序。 NOTICE: The following order determines the order displayed at the frontend. */ [ - [APPLY_CA_PROVIDERS.LETSENCRYPT, "builtin"], - [APPLY_CA_PROVIDERS.LETSENCRYPTSTAGING, "builtin"], - [APPLY_CA_PROVIDERS.BUYPASS], - [APPLY_CA_PROVIDERS.GOOGLETRUSTSERVICES], - [APPLY_CA_PROVIDERS.SSLCOM], - [APPLY_CA_PROVIDERS.ZEROSSL], + [CA_PROVIDERS.LETSENCRYPT, "builtin"], + [CA_PROVIDERS.LETSENCRYPTSTAGING, "builtin"], + [CA_PROVIDERS.BUYPASS], + [CA_PROVIDERS.GOOGLETRUSTSERVICES], + [CA_PROVIDERS.SSLCOM], + [CA_PROVIDERS.ZEROSSL], ].map(([type, builtin]) => [ type, { - type: type as ApplyCAProviderType, + type: type as CAProviderType, name: accessProvidersMap.get(type.split("-")[0])!.name, icon: accessProvidersMap.get(type.split("-")[0])!.icon, provider: type.split("-")[0] as AccessProviderType, @@ -199,15 +216,16 @@ export const applyCAProvidersMap: Map = new Map( +export const acmeDns01ProvidersMap: Map = new Map( /* - 注意:此处的顺序决定显示在前端的顺序。 - NOTICE: The following order determines the order displayed at the frontend. - */ + 注意:此处的顺序决定显示在前端的顺序。 + NOTICE: The following order determines the order displayed at the frontend. + */ [ - [APPLY_DNS_PROVIDERS.ALIYUN_DNS, "provider.aliyun.dns"], - [APPLY_DNS_PROVIDERS.TENCENTCLOUD_DNS, "provider.tencentcloud.dns"], - [APPLY_DNS_PROVIDERS.TENCENTCLOUD_EO, "provider.tencentcloud.eo"], - [APPLY_DNS_PROVIDERS.BAIDUCLOUD_DNS, "provider.baiducloud.dns"], - [APPLY_DNS_PROVIDERS.HUAWEICLOUD_DNS, "provider.huaweicloud.dns"], - [APPLY_DNS_PROVIDERS.VOLCENGINE_DNS, "provider.volcengine.dns"], - [APPLY_DNS_PROVIDERS.JDCLOUD_DNS, "provider.jdcloud.dns"], - [APPLY_DNS_PROVIDERS.AWS_ROUTE53, "provider.aws.route53"], - [APPLY_DNS_PROVIDERS.AZURE_DNS, "provider.azure.dns"], - [APPLY_DNS_PROVIDERS.BUNNY, "provider.bunny"], - [APPLY_DNS_PROVIDERS.CLOUDFLARE, "provider.cloudflare"], - [APPLY_DNS_PROVIDERS.CLOUDNS, "provider.cloudns"], - [APPLY_DNS_PROVIDERS.DESEC, "provider.desec"], - [APPLY_DNS_PROVIDERS.DNSLA, "provider.dnsla"], - [APPLY_DNS_PROVIDERS.DYNV6, "provider.dynv6"], - [APPLY_DNS_PROVIDERS.GCORE, "provider.gcore"], - [APPLY_DNS_PROVIDERS.GNAME, "provider.gname"], - [APPLY_DNS_PROVIDERS.GODADDY, "provider.godaddy"], - [APPLY_DNS_PROVIDERS.NAMECHEAP, "provider.namecheap"], - [APPLY_DNS_PROVIDERS.NAMEDOTCOM, "provider.namedotcom"], - [APPLY_DNS_PROVIDERS.NAMESILO, "provider.namesilo"], - [APPLY_DNS_PROVIDERS.NS1, "provider.ns1"], - [APPLY_DNS_PROVIDERS.PORKBUN, "provider.porkbun"], - [APPLY_DNS_PROVIDERS.VERCEL, "provider.vercel"], - [APPLY_DNS_PROVIDERS.CMCCCLOUD, "provider.cmcccloud"], - [APPLY_DNS_PROVIDERS.RAINYUN, "provider.rainyun"], - [APPLY_DNS_PROVIDERS.WESTCN, "provider.westcn"], - [APPLY_DNS_PROVIDERS.POWERDNS, "provider.powerdns"], - [APPLY_DNS_PROVIDERS.ACMEHTTPREQ, "provider.acmehttpreq"], + [ACME_DNS01_PROVIDERS.ALIYUN_DNS, "provider.aliyun.dns"], + [ACME_DNS01_PROVIDERS.ALIYUN_ESA, "provider.aliyun.esa"], + [ACME_DNS01_PROVIDERS.TENCENTCLOUD_DNS, "provider.tencentcloud.dns"], + [ACME_DNS01_PROVIDERS.TENCENTCLOUD_EO, "provider.tencentcloud.eo"], + [ACME_DNS01_PROVIDERS.BAIDUCLOUD_DNS, "provider.baiducloud.dns"], + [ACME_DNS01_PROVIDERS.HUAWEICLOUD_DNS, "provider.huaweicloud.dns"], + [ACME_DNS01_PROVIDERS.VOLCENGINE_DNS, "provider.volcengine.dns"], + [ACME_DNS01_PROVIDERS.JDCLOUD_DNS, "provider.jdcloud.dns"], + [ACME_DNS01_PROVIDERS.AWS_ROUTE53, "provider.aws.route53"], + [ACME_DNS01_PROVIDERS.AZURE_DNS, "provider.azure.dns"], + [ACME_DNS01_PROVIDERS.BUNNY, "provider.bunny"], + [ACME_DNS01_PROVIDERS.CLOUDFLARE, "provider.cloudflare"], + [ACME_DNS01_PROVIDERS.CLOUDNS, "provider.cloudns"], + [ACME_DNS01_PROVIDERS.DESEC, "provider.desec"], + [ACME_DNS01_PROVIDERS.DNSLA, "provider.dnsla"], + [ACME_DNS01_PROVIDERS.DYNV6, "provider.dynv6"], + [ACME_DNS01_PROVIDERS.GCORE, "provider.gcore"], + [ACME_DNS01_PROVIDERS.GNAME, "provider.gname"], + [ACME_DNS01_PROVIDERS.GODADDY, "provider.godaddy"], + [ACME_DNS01_PROVIDERS.NAMECHEAP, "provider.namecheap"], + [ACME_DNS01_PROVIDERS.NAMEDOTCOM, "provider.namedotcom"], + [ACME_DNS01_PROVIDERS.NAMESILO, "provider.namesilo"], + [ACME_DNS01_PROVIDERS.NS1, "provider.ns1"], + [ACME_DNS01_PROVIDERS.PORKBUN, "provider.porkbun"], + [ACME_DNS01_PROVIDERS.VERCEL, "provider.vercel"], + [ACME_DNS01_PROVIDERS.CMCCCLOUD, "provider.cmcccloud"], + [ACME_DNS01_PROVIDERS.RAINYUN, "provider.rainyun"], + [ACME_DNS01_PROVIDERS.WESTCN, "provider.westcn"], + [ACME_DNS01_PROVIDERS.POWERDNS, "provider.powerdns"], + [ACME_DNS01_PROVIDERS.ACMEHTTPREQ, "provider.acmehttpreq"], ].map(([type, name]) => [ type, { - type: type as ApplyDNSProviderType, + type: type as ACMEDns01ProviderType, name: name, icon: accessProvidersMap.get(type.split("-")[0])!.icon, provider: type.split("-")[0] as AccessProviderType, @@ -300,12 +319,12 @@ export const applyDNSProvidersMap: Map = new Map( +export const deploymentProvidersMap: Map = new Map( /* 注意:此处的顺序决定显示在前端的顺序。 NOTICE: The following order determines the order displayed at the frontend. */ [ - [DEPLOY_PROVIDERS.LOCAL, "provider.local", DEPLOY_CATEGORIES.OTHER, "builtin"], - [DEPLOY_PROVIDERS.SSH, "provider.ssh", DEPLOY_CATEGORIES.OTHER], - [DEPLOY_PROVIDERS.WEBHOOK, "provider.webhook", DEPLOY_CATEGORIES.OTHER], - [DEPLOY_PROVIDERS.KUBERNETES_SECRET, "provider.kubernetes.secret", DEPLOY_CATEGORIES.OTHER], - [DEPLOY_PROVIDERS.ALIYUN_OSS, "provider.aliyun.oss", DEPLOY_CATEGORIES.STORAGE], - [DEPLOY_PROVIDERS.ALIYUN_CDN, "provider.aliyun.cdn", DEPLOY_CATEGORIES.CDN], - [DEPLOY_PROVIDERS.ALIYUN_DCDN, "provider.aliyun.dcdn", DEPLOY_CATEGORIES.CDN], - [DEPLOY_PROVIDERS.ALIYUN_ESA, "provider.aliyun.esa", DEPLOY_CATEGORIES.CDN], - [DEPLOY_PROVIDERS.ALIYUN_CLB, "provider.aliyun.clb", DEPLOY_CATEGORIES.LOADBALANCE], - [DEPLOY_PROVIDERS.ALIYUN_ALB, "provider.aliyun.alb", DEPLOY_CATEGORIES.LOADBALANCE], - [DEPLOY_PROVIDERS.ALIYUN_NLB, "provider.aliyun.nlb", DEPLOY_CATEGORIES.LOADBALANCE], - [DEPLOY_PROVIDERS.ALIYUN_WAF, "provider.aliyun.waf", DEPLOY_CATEGORIES.FIREWALL], - [DEPLOY_PROVIDERS.ALIYUN_LIVE, "provider.aliyun.live", DEPLOY_CATEGORIES.AV], - [DEPLOY_PROVIDERS.ALIYUN_VOD, "provider.aliyun.vod", DEPLOY_CATEGORIES.AV], - [DEPLOY_PROVIDERS.ALIYUN_FC, "provider.aliyun.fc", DEPLOY_CATEGORIES.SERVERLESS], - [DEPLOY_PROVIDERS.ALIYUN_APIGW, "provider.aliyun.apigw", DEPLOY_CATEGORIES.OTHER], - [DEPLOY_PROVIDERS.ALIYUN_CAS, "provider.aliyun.cas_upload", DEPLOY_CATEGORIES.OTHER], - [DEPLOY_PROVIDERS.ALIYUN_CAS_DEPLOY, "provider.aliyun.cas_deploy", DEPLOY_CATEGORIES.OTHER], - [DEPLOY_PROVIDERS.TENCENTCLOUD_COS, "provider.tencentcloud.cos", DEPLOY_CATEGORIES.STORAGE], - [DEPLOY_PROVIDERS.TENCENTCLOUD_CDN, "provider.tencentcloud.cdn", DEPLOY_CATEGORIES.CDN], - [DEPLOY_PROVIDERS.TENCENTCLOUD_ECDN, "provider.tencentcloud.ecdn", DEPLOY_CATEGORIES.CDN], - [DEPLOY_PROVIDERS.TENCENTCLOUD_EO, "provider.tencentcloud.eo", DEPLOY_CATEGORIES.CDN], - [DEPLOY_PROVIDERS.TENCENTCLOUD_CLB, "provider.tencentcloud.clb", DEPLOY_CATEGORIES.LOADBALANCE], - [DEPLOY_PROVIDERS.TENCENTCLOUD_WAF, "provider.tencentcloud.waf", DEPLOY_CATEGORIES.FIREWALL], - [DEPLOY_PROVIDERS.TENCENTCLOUD_CSS, "provider.tencentcloud.css", DEPLOY_CATEGORIES.AV], - [DEPLOY_PROVIDERS.TENCENTCLOUD_VOD, "provider.tencentcloud.vod", DEPLOY_CATEGORIES.AV], - [DEPLOY_PROVIDERS.TENCENTCLOUD_SCF, "provider.tencentcloud.scf", DEPLOY_CATEGORIES.SERVERLESS], - [DEPLOY_PROVIDERS.TENCENTCLOUD_SSL, "provider.tencentcloud.ssl_upload", DEPLOY_CATEGORIES.OTHER], - [DEPLOY_PROVIDERS.TENCENTCLOUD_SSL_DEPLOY, "provider.tencentcloud.ssl_deploy", DEPLOY_CATEGORIES.OTHER], - [DEPLOY_PROVIDERS.BAIDUCLOUD_CDN, "provider.baiducloud.cdn", DEPLOY_CATEGORIES.CDN], - [DEPLOY_PROVIDERS.BAIDUCLOUD_BLB, "provider.baiducloud.blb", DEPLOY_CATEGORIES.LOADBALANCE], - [DEPLOY_PROVIDERS.BAIDUCLOUD_APPBLB, "provider.baiducloud.appblb", DEPLOY_CATEGORIES.LOADBALANCE], - [DEPLOY_PROVIDERS.BAIDUCLOUD_CERT, "provider.baiducloud.cert_upload", DEPLOY_CATEGORIES.OTHER], - [DEPLOY_PROVIDERS.HUAWEICLOUD_CDN, "provider.huaweicloud.cdn", DEPLOY_CATEGORIES.CDN], - [DEPLOY_PROVIDERS.HUAWEICLOUD_ELB, "provider.huaweicloud.elb", DEPLOY_CATEGORIES.LOADBALANCE], - [DEPLOY_PROVIDERS.HUAWEICLOUD_WAF, "provider.huaweicloud.waf", DEPLOY_CATEGORIES.FIREWALL], - [DEPLOY_PROVIDERS.HUAWEICLOUD_SCM, "provider.huaweicloud.scm_upload", DEPLOY_CATEGORIES.OTHER], - [DEPLOY_PROVIDERS.VOLCENGINE_TOS, "provider.volcengine.tos", DEPLOY_CATEGORIES.STORAGE], - [DEPLOY_PROVIDERS.VOLCENGINE_CDN, "provider.volcengine.cdn", DEPLOY_CATEGORIES.CDN], - [DEPLOY_PROVIDERS.VOLCENGINE_DCDN, "provider.volcengine.dcdn", DEPLOY_CATEGORIES.CDN], - [DEPLOY_PROVIDERS.VOLCENGINE_CLB, "provider.volcengine.clb", DEPLOY_CATEGORIES.LOADBALANCE], - [DEPLOY_PROVIDERS.VOLCENGINE_ALB, "provider.volcengine.alb", DEPLOY_CATEGORIES.LOADBALANCE], - [DEPLOY_PROVIDERS.VOLCENGINE_IMAGEX, "provider.volcengine.imagex", DEPLOY_CATEGORIES.STORAGE], - [DEPLOY_PROVIDERS.VOLCENGINE_LIVE, "provider.volcengine.live", DEPLOY_CATEGORIES.AV], - [DEPLOY_PROVIDERS.VOLCENGINE_CERTCENTER, "provider.volcengine.certcenter_upload", DEPLOY_CATEGORIES.OTHER], - [DEPLOY_PROVIDERS.JDCLOUD_ALB, "provider.jdcloud.alb", DEPLOY_CATEGORIES.LOADBALANCE], - [DEPLOY_PROVIDERS.JDCLOUD_CDN, "provider.jdcloud.cdn", DEPLOY_CATEGORIES.CDN], - [DEPLOY_PROVIDERS.JDCLOUD_LIVE, "provider.jdcloud.live", DEPLOY_CATEGORIES.AV], - [DEPLOY_PROVIDERS.JDCLOUD_VOD, "provider.jdcloud.vod", DEPLOY_CATEGORIES.AV], - [DEPLOY_PROVIDERS.QINIU_KODO, "provider.qiniu.kodo", DEPLOY_CATEGORIES.STORAGE], - [DEPLOY_PROVIDERS.QINIU_CDN, "provider.qiniu.cdn", DEPLOY_CATEGORIES.CDN], - [DEPLOY_PROVIDERS.QINIU_PILI, "provider.qiniu.pili", DEPLOY_CATEGORIES.AV], - [DEPLOY_PROVIDERS.UPYUN_FILE, "provider.upyun.file", DEPLOY_CATEGORIES.STORAGE], - [DEPLOY_PROVIDERS.UPYUN_CDN, "provider.upyun.cdn", DEPLOY_CATEGORIES.CDN], - [DEPLOY_PROVIDERS.BAISHAN_CDN, "provider.baishan.cdn", DEPLOY_CATEGORIES.CDN], - [DEPLOY_PROVIDERS.WANGSU_CDNPRO, "provider.wangsu.cdnpro", DEPLOY_CATEGORIES.CDN], - [DEPLOY_PROVIDERS.DOGECLOUD_CDN, "provider.dogecloud.cdn", DEPLOY_CATEGORIES.CDN], - [DEPLOY_PROVIDERS.BYTEPLUS_CDN, "provider.byteplus.cdn", DEPLOY_CATEGORIES.CDN], - [DEPLOY_PROVIDERS.UCLOUD_US3, "provider.ucloud.us3", DEPLOY_CATEGORIES.STORAGE], - [DEPLOY_PROVIDERS.UCLOUD_UCDN, "provider.ucloud.ucdn", DEPLOY_CATEGORIES.CDN], - [DEPLOY_PROVIDERS.RAINYUN_RCDN, "provider.rainyun.rcdn", DEPLOY_CATEGORIES.CDN], - [DEPLOY_PROVIDERS.AWS_CLOUDFRONT, "provider.aws.cloudfront", DEPLOY_CATEGORIES.CDN], - [DEPLOY_PROVIDERS.AWS_ACM, "provider.aws.acm", DEPLOY_CATEGORIES.OTHER], - [DEPLOY_PROVIDERS.AZURE_KEYVAULT, "provider.azure.keyvault", DEPLOY_CATEGORIES.OTHER], - [DEPLOY_PROVIDERS.BUNNY_CDN, "provider.bunny.cdn", DEPLOY_CATEGORIES.CDN], - [DEPLOY_PROVIDERS.CACHEFLY, "provider.cachefly", DEPLOY_CATEGORIES.CDN], - [DEPLOY_PROVIDERS.CDNFLY, "provider.cdnfly", DEPLOY_CATEGORIES.CDN], - [DEPLOY_PROVIDERS.EDGIO_APPLICATIONS, "provider.edgio.applications", DEPLOY_CATEGORIES.WEBSITE], - [DEPLOY_PROVIDERS.GCORE_CDN, "provider.gcore.cdn", DEPLOY_CATEGORIES.CDN], - [DEPLOY_PROVIDERS["1PANEL_SITE"], "provider.1panel.site", DEPLOY_CATEGORIES.WEBSITE], - [DEPLOY_PROVIDERS["1PANEL_CONSOLE"], "provider.1panel.console", DEPLOY_CATEGORIES.OTHER], - [DEPLOY_PROVIDERS.BAOTAPANEL_SITE, "provider.baotapanel.site", DEPLOY_CATEGORIES.WEBSITE], - [DEPLOY_PROVIDERS.BAOTAPANEL_CONSOLE, "provider.baotapanel.console", DEPLOY_CATEGORIES.OTHER], - [DEPLOY_PROVIDERS.SAFELINE, "provider.safeline", DEPLOY_CATEGORIES.FIREWALL], + [DEPLOYMENT_PROVIDERS.LOCAL, "provider.local", DEPLOYMENT_CATEGORIES.OTHER, "builtin"], + [DEPLOYMENT_PROVIDERS.SSH, "provider.ssh", DEPLOYMENT_CATEGORIES.OTHER], + [DEPLOYMENT_PROVIDERS.WEBHOOK, "provider.webhook", DEPLOYMENT_CATEGORIES.OTHER], + [DEPLOYMENT_PROVIDERS.KUBERNETES_SECRET, "provider.kubernetes.secret", DEPLOYMENT_CATEGORIES.OTHER], + [DEPLOYMENT_PROVIDERS.ALIYUN_OSS, "provider.aliyun.oss", DEPLOYMENT_CATEGORIES.STORAGE], + [DEPLOYMENT_PROVIDERS.ALIYUN_CDN, "provider.aliyun.cdn", DEPLOYMENT_CATEGORIES.CDN], + [DEPLOYMENT_PROVIDERS.ALIYUN_DCDN, "provider.aliyun.dcdn", DEPLOYMENT_CATEGORIES.CDN], + [DEPLOYMENT_PROVIDERS.ALIYUN_ESA, "provider.aliyun.esa", DEPLOYMENT_CATEGORIES.CDN], + [DEPLOYMENT_PROVIDERS.ALIYUN_CLB, "provider.aliyun.clb", DEPLOYMENT_CATEGORIES.LOADBALANCE], + [DEPLOYMENT_PROVIDERS.ALIYUN_ALB, "provider.aliyun.alb", DEPLOYMENT_CATEGORIES.LOADBALANCE], + [DEPLOYMENT_PROVIDERS.ALIYUN_NLB, "provider.aliyun.nlb", DEPLOYMENT_CATEGORIES.LOADBALANCE], + [DEPLOYMENT_PROVIDERS.ALIYUN_WAF, "provider.aliyun.waf", DEPLOYMENT_CATEGORIES.FIREWALL], + [DEPLOYMENT_PROVIDERS.ALIYUN_DDOS, "provider.aliyun.ddos", DEPLOYMENT_CATEGORIES.FIREWALL], + [DEPLOYMENT_PROVIDERS.ALIYUN_LIVE, "provider.aliyun.live", DEPLOYMENT_CATEGORIES.AV], + [DEPLOYMENT_PROVIDERS.ALIYUN_VOD, "provider.aliyun.vod", DEPLOYMENT_CATEGORIES.AV], + [DEPLOYMENT_PROVIDERS.ALIYUN_FC, "provider.aliyun.fc", DEPLOYMENT_CATEGORIES.SERVERLESS], + [DEPLOYMENT_PROVIDERS.ALIYUN_APIGW, "provider.aliyun.apigw", DEPLOYMENT_CATEGORIES.OTHER], + [DEPLOYMENT_PROVIDERS.ALIYUN_CAS, "provider.aliyun.cas_upload", DEPLOYMENT_CATEGORIES.OTHER], + [DEPLOYMENT_PROVIDERS.ALIYUN_CAS_DEPLOY, "provider.aliyun.cas_deploy", DEPLOYMENT_CATEGORIES.OTHER], + [DEPLOYMENT_PROVIDERS.TENCENTCLOUD_COS, "provider.tencentcloud.cos", DEPLOYMENT_CATEGORIES.STORAGE], + [DEPLOYMENT_PROVIDERS.TENCENTCLOUD_CDN, "provider.tencentcloud.cdn", DEPLOYMENT_CATEGORIES.CDN], + [DEPLOYMENT_PROVIDERS.TENCENTCLOUD_ECDN, "provider.tencentcloud.ecdn", DEPLOYMENT_CATEGORIES.CDN], + [DEPLOYMENT_PROVIDERS.TENCENTCLOUD_EO, "provider.tencentcloud.eo", DEPLOYMENT_CATEGORIES.CDN], + [DEPLOYMENT_PROVIDERS.TENCENTCLOUD_CLB, "provider.tencentcloud.clb", DEPLOYMENT_CATEGORIES.LOADBALANCE], + [DEPLOYMENT_PROVIDERS.TENCENTCLOUD_WAF, "provider.tencentcloud.waf", DEPLOYMENT_CATEGORIES.FIREWALL], + [DEPLOYMENT_PROVIDERS.TENCENTCLOUD_CSS, "provider.tencentcloud.css", DEPLOYMENT_CATEGORIES.AV], + [DEPLOYMENT_PROVIDERS.TENCENTCLOUD_VOD, "provider.tencentcloud.vod", DEPLOYMENT_CATEGORIES.AV], + [DEPLOYMENT_PROVIDERS.TENCENTCLOUD_SCF, "provider.tencentcloud.scf", DEPLOYMENT_CATEGORIES.SERVERLESS], + [DEPLOYMENT_PROVIDERS.TENCENTCLOUD_SSL, "provider.tencentcloud.ssl_upload", DEPLOYMENT_CATEGORIES.OTHER], + [DEPLOYMENT_PROVIDERS.TENCENTCLOUD_SSL_DEPLOY, "provider.tencentcloud.ssl_deploy", DEPLOYMENT_CATEGORIES.OTHER], + [DEPLOYMENT_PROVIDERS.BAIDUCLOUD_CDN, "provider.baiducloud.cdn", DEPLOYMENT_CATEGORIES.CDN], + [DEPLOYMENT_PROVIDERS.BAIDUCLOUD_BLB, "provider.baiducloud.blb", DEPLOYMENT_CATEGORIES.LOADBALANCE], + [DEPLOYMENT_PROVIDERS.BAIDUCLOUD_APPBLB, "provider.baiducloud.appblb", DEPLOYMENT_CATEGORIES.LOADBALANCE], + [DEPLOYMENT_PROVIDERS.BAIDUCLOUD_CERT, "provider.baiducloud.cert_upload", DEPLOYMENT_CATEGORIES.OTHER], + [DEPLOYMENT_PROVIDERS.HUAWEICLOUD_CDN, "provider.huaweicloud.cdn", DEPLOYMENT_CATEGORIES.CDN], + [DEPLOYMENT_PROVIDERS.HUAWEICLOUD_ELB, "provider.huaweicloud.elb", DEPLOYMENT_CATEGORIES.LOADBALANCE], + [DEPLOYMENT_PROVIDERS.HUAWEICLOUD_WAF, "provider.huaweicloud.waf", DEPLOYMENT_CATEGORIES.FIREWALL], + [DEPLOYMENT_PROVIDERS.HUAWEICLOUD_SCM, "provider.huaweicloud.scm_upload", DEPLOYMENT_CATEGORIES.OTHER], + [DEPLOYMENT_PROVIDERS.VOLCENGINE_TOS, "provider.volcengine.tos", DEPLOYMENT_CATEGORIES.STORAGE], + [DEPLOYMENT_PROVIDERS.VOLCENGINE_CDN, "provider.volcengine.cdn", DEPLOYMENT_CATEGORIES.CDN], + [DEPLOYMENT_PROVIDERS.VOLCENGINE_DCDN, "provider.volcengine.dcdn", DEPLOYMENT_CATEGORIES.CDN], + [DEPLOYMENT_PROVIDERS.VOLCENGINE_CLB, "provider.volcengine.clb", DEPLOYMENT_CATEGORIES.LOADBALANCE], + [DEPLOYMENT_PROVIDERS.VOLCENGINE_ALB, "provider.volcengine.alb", DEPLOYMENT_CATEGORIES.LOADBALANCE], + [DEPLOYMENT_PROVIDERS.VOLCENGINE_IMAGEX, "provider.volcengine.imagex", DEPLOYMENT_CATEGORIES.STORAGE], + [DEPLOYMENT_PROVIDERS.VOLCENGINE_LIVE, "provider.volcengine.live", DEPLOYMENT_CATEGORIES.AV], + [DEPLOYMENT_PROVIDERS.VOLCENGINE_CERTCENTER, "provider.volcengine.certcenter_upload", DEPLOYMENT_CATEGORIES.OTHER], + [DEPLOYMENT_PROVIDERS.JDCLOUD_ALB, "provider.jdcloud.alb", DEPLOYMENT_CATEGORIES.LOADBALANCE], + [DEPLOYMENT_PROVIDERS.JDCLOUD_CDN, "provider.jdcloud.cdn", DEPLOYMENT_CATEGORIES.CDN], + [DEPLOYMENT_PROVIDERS.JDCLOUD_LIVE, "provider.jdcloud.live", DEPLOYMENT_CATEGORIES.AV], + [DEPLOYMENT_PROVIDERS.JDCLOUD_VOD, "provider.jdcloud.vod", DEPLOYMENT_CATEGORIES.AV], + [DEPLOYMENT_PROVIDERS.QINIU_KODO, "provider.qiniu.kodo", DEPLOYMENT_CATEGORIES.STORAGE], + [DEPLOYMENT_PROVIDERS.QINIU_CDN, "provider.qiniu.cdn", DEPLOYMENT_CATEGORIES.CDN], + [DEPLOYMENT_PROVIDERS.QINIU_PILI, "provider.qiniu.pili", DEPLOYMENT_CATEGORIES.AV], + [DEPLOYMENT_PROVIDERS.UPYUN_FILE, "provider.upyun.file", DEPLOYMENT_CATEGORIES.STORAGE], + [DEPLOYMENT_PROVIDERS.UPYUN_CDN, "provider.upyun.cdn", DEPLOYMENT_CATEGORIES.CDN], + [DEPLOYMENT_PROVIDERS.BAISHAN_CDN, "provider.baishan.cdn", DEPLOYMENT_CATEGORIES.CDN], + [DEPLOYMENT_PROVIDERS.WANGSU_CDNPRO, "provider.wangsu.cdnpro", DEPLOYMENT_CATEGORIES.CDN], + [DEPLOYMENT_PROVIDERS.DOGECLOUD_CDN, "provider.dogecloud.cdn", DEPLOYMENT_CATEGORIES.CDN], + [DEPLOYMENT_PROVIDERS.BYTEPLUS_CDN, "provider.byteplus.cdn", DEPLOYMENT_CATEGORIES.CDN], + [DEPLOYMENT_PROVIDERS.UCLOUD_US3, "provider.ucloud.us3", DEPLOYMENT_CATEGORIES.STORAGE], + [DEPLOYMENT_PROVIDERS.UCLOUD_UCDN, "provider.ucloud.ucdn", DEPLOYMENT_CATEGORIES.CDN], + [DEPLOYMENT_PROVIDERS.RAINYUN_RCDN, "provider.rainyun.rcdn", DEPLOYMENT_CATEGORIES.CDN], + [DEPLOYMENT_PROVIDERS.AWS_CLOUDFRONT, "provider.aws.cloudfront", DEPLOYMENT_CATEGORIES.CDN], + [DEPLOYMENT_PROVIDERS.AWS_ACM, "provider.aws.acm", DEPLOYMENT_CATEGORIES.OTHER], + [DEPLOYMENT_PROVIDERS.AZURE_KEYVAULT, "provider.azure.keyvault", DEPLOYMENT_CATEGORIES.OTHER], + [DEPLOYMENT_PROVIDERS.BUNNY_CDN, "provider.bunny.cdn", DEPLOYMENT_CATEGORIES.CDN], + [DEPLOYMENT_PROVIDERS.CACHEFLY, "provider.cachefly", DEPLOYMENT_CATEGORIES.CDN], + [DEPLOYMENT_PROVIDERS.CDNFLY, "provider.cdnfly", DEPLOYMENT_CATEGORIES.CDN], + [DEPLOYMENT_PROVIDERS.EDGIO_APPLICATIONS, "provider.edgio.applications", DEPLOYMENT_CATEGORIES.WEBSITE], + [DEPLOYMENT_PROVIDERS.GCORE_CDN, "provider.gcore.cdn", DEPLOYMENT_CATEGORIES.CDN], + [DEPLOYMENT_PROVIDERS.GOEDGE, "provider.goedge", DEPLOYMENT_CATEGORIES.CDN], + [DEPLOYMENT_PROVIDERS["1PANEL_SITE"], "provider.1panel.site", DEPLOYMENT_CATEGORIES.WEBSITE], + [DEPLOYMENT_PROVIDERS["1PANEL_CONSOLE"], "provider.1panel.console", DEPLOYMENT_CATEGORIES.OTHER], + [DEPLOYMENT_PROVIDERS.BAOTAPANEL_SITE, "provider.baotapanel.site", DEPLOYMENT_CATEGORIES.WEBSITE], + [DEPLOYMENT_PROVIDERS.BAOTAPANEL_CONSOLE, "provider.baotapanel.console", DEPLOYMENT_CATEGORIES.OTHER], + [DEPLOYMENT_PROVIDERS.SAFELINE, "provider.safeline", DEPLOYMENT_CATEGORIES.FIREWALL], + [DEPLOYMENT_PROVIDERS.PROXMOXVE, "provider.proxmoxve", DEPLOYMENT_CATEGORIES.NAS], ].map(([type, name, category, builtin]) => [ type, { - type: type as DeployProviderType, + type: type as DeploymentProviderType, name: name, icon: accessProvidersMap.get(type.split("-")[0])!.icon, provider: type.split("-")[0] as AccessProviderType, - category: category as DeployCategoryType, + category: category as DeploymentCategoryType, builtin: builtin === "builtin", }, ]) ); // #endregion + +// #region NotificationProvider +/* + 注意:如果追加新的常量值,请保持以 ASCII 排序。 + NOTICE: If you add new constant, please keep ASCII order. + */ +export const NOTIFICATION_PROVIDERS = Object.freeze({ + DINGTALKBOT: `${ACCESS_PROVIDERS.DINGTALKBOT}`, + EMAIL: `${ACCESS_PROVIDERS.EMAIL}`, + LARKBOT: `${ACCESS_PROVIDERS.LARKBOT}`, + MATTERMOST: `${ACCESS_PROVIDERS.MATTERMOST}`, + TELEGRAM: `${ACCESS_PROVIDERS.TELEGRAM}`, + WEBHOOK: `${ACCESS_PROVIDERS.WEBHOOK}`, + WECOMBOT: `${ACCESS_PROVIDERS.WECOMBOT}`, +} as const); + +export type NotificationProviderType = (typeof CA_PROVIDERS)[keyof typeof CA_PROVIDERS]; + +export type NotificationProvider = { + type: NotificationProviderType; + name: string; + icon: string; + provider: AccessProviderType; +}; + +export const notificationProvidersMap: Map = new Map( + /* + 注意:此处的顺序决定显示在前端的顺序。 + NOTICE: The following order determines the order displayed at the frontend. + */ + [ + [NOTIFICATION_PROVIDERS.EMAIL], + [NOTIFICATION_PROVIDERS.WEBHOOK], + [NOTIFICATION_PROVIDERS.DINGTALKBOT], + [NOTIFICATION_PROVIDERS.LARKBOT], + [NOTIFICATION_PROVIDERS.WECOMBOT], + [NOTIFICATION_PROVIDERS.MATTERMOST], + [NOTIFICATION_PROVIDERS.TELEGRAM], + ].map(([type]) => [ + type, + { + type: type as CAProviderType, + name: accessProvidersMap.get(type.split("-")[0])!.name, + icon: accessProvidersMap.get(type.split("-")[0])!.icon, + provider: type.split("-")[0] as AccessProviderType, + }, + ]) +); +// #endregion diff --git a/ui/src/domain/settings.ts b/ui/src/domain/settings.ts index e789f7e3..a711f543 100644 --- a/ui/src/domain/settings.ts +++ b/ui/src/domain/settings.ts @@ -1,8 +1,11 @@ -import { type ApplyCAProviderType } from "./provider"; +import { type CAProviderType } from "./provider"; export const SETTINGS_NAMES = Object.freeze({ EMAILS: "emails", NOTIFY_TEMPLATES: "notifyTemplates", + /** + * @deprecated + */ NOTIFY_CHANNELS: "notifyChannels", SSL_PROVIDER: "sslProvider", PERSISTENCE: "persistence", @@ -38,6 +41,9 @@ export const defaultNotifyTemplate: NotifyTemplate = { // #endregion // #region Settings: NotifyChannels +/** + * @deprecated + */ export const NOTIFY_CHANNELS = Object.freeze({ BARK: "bark", DINGTALK: "dingtalk", @@ -53,8 +59,14 @@ export const NOTIFY_CHANNELS = Object.freeze({ WECOM: "wecom", } as const); +/** + * @deprecated + */ export type NotifyChannels = (typeof NOTIFY_CHANNELS)[keyof typeof NOTIFY_CHANNELS]; +/** + * @deprecated + */ export type NotifyChannelsSettingsContent = { /* 注意:如果追加新的类型,请保持以 ASCII 排序。 @@ -75,12 +87,18 @@ export type NotifyChannelsSettingsContent = { [NOTIFY_CHANNELS.WECOM]?: WeComNotifyChannelConfig; }; +/** + * @deprecated + */ export type BarkNotifyChannelConfig = { deviceKey: string; serverUrl: string; enabled?: boolean; }; +/** + * @deprecated + */ export type EmailNotifyChannelConfig = { smtpHost: string; smtpPort: number; @@ -92,12 +110,18 @@ export type EmailNotifyChannelConfig = { enabled?: boolean; }; +/** + * @deprecated + */ export type DingTalkNotifyChannelConfig = { accessToken: string; secret: string; enabled?: boolean; }; +/** + * @deprecated + */ export type GotifyNotifyChannelConfig = { url: string; token: string; @@ -105,56 +129,86 @@ export type GotifyNotifyChannelConfig = { enabled?: boolean; }; +/** + * @deprecated + */ export type LarkNotifyChannelConfig = { webhookUrl: string; enabled?: boolean; }; +/** + * @deprecated + */ export type MattermostNotifyChannelConfig = { serverUrl: string; channel: string; username: string; password: string; enabled?: boolean; -} +}; +/** + * @deprecated + */ export type PushoverNotifyChannelConfig = { token: string; user: string; enabled?: boolean; }; +/** + * @deprecated + */ export type PushPlusNotifyChannelConfig = { token: string; enabled?: boolean; }; +/** + * @deprecated + */ export type ServerChanNotifyChannelConfig = { url: string; enabled?: boolean; }; +/** + * @deprecated + */ export type TelegramNotifyChannelConfig = { apiToken: string; chatId: string; enabled?: boolean; }; +/** + * @deprecated + */ export type WebhookNotifyChannelConfig = { url: string; enabled?: boolean; }; +/** + * @deprecated + */ export type WeComNotifyChannelConfig = { webhookUrl: string; enabled?: boolean; }; +/** + * @deprecated + */ export type NotifyChannel = { type: string; name: string; }; +/** + * @deprecated + */ export const notifyChannelsMap: Map = new Map( [ [NOTIFY_CHANNELS.EMAIL, "common.notifier.email"], @@ -175,7 +229,7 @@ export const notifyChannelsMap: Map = new // #region Settings: SSLProvider export type SSLProviderSettingsContent = { - provider: ApplyCAProviderType; + provider: CAProviderType; config: { [key: string]: Record | undefined; }; diff --git a/ui/src/domain/version.ts b/ui/src/domain/version.ts index 3c1813b7..987da071 100644 --- a/ui/src/domain/version.ts +++ b/ui/src/domain/version.ts @@ -1 +1 @@ -export const version = "v0.3.9"; +export const version = "v0.3.10"; diff --git a/ui/src/domain/workflow.ts b/ui/src/domain/workflow.ts index 11ea13da..06226425 100644 --- a/ui/src/domain/workflow.ts +++ b/ui/src/domain/workflow.ts @@ -154,9 +154,15 @@ export type WorkflowNodeConfigForDeploy = { }; export type WorkflowNodeConfigForNotify = { - channel: string; subject: string; message: string; + /** + * @deprecated + */ + channel?: string; + provider: string; + providerAccessId: string; + providerConfig?: Record; }; export type WorkflowNodeConfigForBranch = never; diff --git a/ui/src/i18n/locales/en/nls.access.json b/ui/src/i18n/locales/en/nls.access.json index e1b701cd..be9a3508 100644 --- a/ui/src/i18n/locales/en/nls.access.json +++ b/ui/src/i18n/locales/en/nls.access.json @@ -18,9 +18,9 @@ "access.props.provider.usage.ca": "Certificate authority", "access.props.provider.usage.notification": "Notification channel", "access.props.provider.builtin": "Built-in", - "access.props.range.both_dns_hosting": "Provider", - "access.props.range.ca_only": "Certificate authority", - "access.props.range.notify_only": "Notification channel", + "access.props.usage.both_dns_hosting": "Provider", + "access.props.usage.ca_only": "Certificate authority", + "access.props.usage.notification_only": "Notification channel", "access.props.created_at": "Created at", "access.props.updated_at": "Updated at", @@ -28,19 +28,17 @@ "access.form.name.placeholder": "Please enter authorization name", "access.form.provider.label": "Provider", "access.form.provider.placeholder": "Please select a provider", - "access.form.provider.tooltip": "DNS provider: The provider that hosts your domain names and manages your DNS records.
Host provider: The provider that hosts your servers or cloud services for deploying certificates.

Cannot be edited after saving.", + "access.form.provider.tooltip": "DNS provider: The provider that hosts your domain names and manages your DNS records.
Hosting provider: The provider that hosts your servers or cloud services for deploying certificates.

Cannot be edited after saving.", "access.form.certificate_authority.label": "Certificate authority", "access.form.certificate_authority.placeholder": "Please select a certificate authority", "access.form.notification_channel.label": "Notification channel", "access.form.notification_channel.placeholder": "Please select a notification channel", "access.form.1panel_api_url.label": "1Panel URL", "access.form.1panel_api_url.placeholder": "Please enter 1Panel URL", - "access.form.1panel_api_url.tooltip": "For more information, see https://docs.1panel.pro/dev_manual/api_manual/", "access.form.1panel_api_key.label": "1Panel API key", "access.form.1panel_api_key.placeholder": "Please enter 1Panel API key", "access.form.1panel_api_key.tooltip": "For more information, see https://docs.1panel.pro/dev_manual/api_manual/", "access.form.1panel_allow_insecure_conns.label": "Insecure SSL/TLS connections", - "access.form.1panel_allow_insecure_conns.tooltip": "Allowing insecure connections may lead to data leak or tampering. Use this option only when under trusted networks.", "access.form.1panel_allow_insecure_conns.switch.on": "Allow", "access.form.1panel_allow_insecure_conns.switch.off": "Disallow", "access.form.acmehttpreq_endpoint.label": "Endpoint", @@ -85,7 +83,7 @@ "access.form.baiducloud_secret_access_key.label": "Baidu Cloud SecretAccessKey", "access.form.baiducloud_secret_access_key.placeholder": "Please enter Baidu Cloud SecretAccessKey", "access.form.baiducloud_secret_access_key.tooltip": "For more information, see https://intl.cloud.baidu.com/doc/Reference/s/jjwvz2e3p-en", - "access.form.bunny_api_key.label": "Bunny API Key", + "access.form.bunny_api_key.label": "Bunny API key", "access.form.bunny_api_key.placeholder": "Please enter Bunny API key", "access.form.bunny_api_key.tooltip": "For more information, see https://docs.bunny.net/reference/bunnynet-api-overview", "access.form.upyun_username.label": "UPYUN subaccount username", @@ -98,12 +96,10 @@ "access.form.baishan_api_token.placeholder": "Please enter Baishan Cloud API token", "access.form.baotapanel_api_url.label": "aaPanel URL", "access.form.baotapanel_api_url.placeholder": "Please enter aaPanel URL", - "access.form.baotapanel_api_url.tooltip": "For more information, see https://www.bt.cn/bbs/thread-20376-1-1.html", "access.form.baotapanel_api_key.label": "aaPanel API key", "access.form.baotapanel_api_key.placeholder": "Please enter aaPanel API key", "access.form.baotapanel_api_key.tooltip": "For more information, see https://www.bt.cn/bbs/thread-20376-1-1.html", "access.form.baotapanel_allow_insecure_conns.label": "Insecure SSL/TLS connections", - "access.form.baotapanel_allow_insecure_conns.tooltip": "Allowing insecure connections may lead to data leak or tampering. Use this option only when under trusted networks.", "access.form.baotapanel_allow_insecure_conns.switch.on": "Allow", "access.form.baotapanel_allow_insecure_conns.switch.off": "Disallow", "access.form.byteplus_access_key.label": "BytePlus AccessKey", @@ -117,13 +113,15 @@ "access.form.cachefly_api_token.tooltip": "For more information, see https://kb.cachefly.com/kb/guide/en/generating-tokens-and-keys-Oll9Irt5TI/Steps/2460228", "access.form.cdnfly_api_url.label": "Cdnfly API URL", "access.form.cdnfly_api_url.placeholder": "Please enter Cdnfly API URL", - "access.form.cdnfly_api_url.tooltip": "For more information, see https://doc.cdnfly.cn/anzhuangshuoming.html", "access.form.cdnfly_api_key.label": "Cdnfly user API key", "access.form.cdnfly_api_key.placeholder": "Please enter Cdnfly user API key", "access.form.cdnfly_api_key.tooltip": "For more information, see https://doc.cdnfly.cn/shiyongjieshao.html", "access.form.cdnfly_api_secret.label": "Cdnfly user API secret", "access.form.cdnfly_api_secret.placeholder": "Please enter Cdnfly user API secret", "access.form.cdnfly_api_secret.tooltip": "For more information, see https://doc.cdnfly.cn/shiyongjieshao.html", + "access.form.cdnfly_allow_insecure_conns.label": "Insecure SSL/TLS connections", + "access.form.cdnfly_allow_insecure_conns.switch.on": "Allow", + "access.form.cdnfly_allow_insecure_conns.switch.off": "Disallow", "access.form.cloudflare_dns_api_token.label": "Cloudflare DNS API token", "access.form.cloudflare_dns_api_token.placeholder": "Please enter Cloudflare DNS API token", "access.form.cloudflare_dns_api_token.tooltip": "For more information, see https://developers.cloudflare.com/fundamentals/api/get-started/create-token/", @@ -145,6 +143,12 @@ "access.form.desec_token.label": "deSEC token", "access.form.desec_token.placeholder": "Please enter deSEC token", "access.form.desec_token.tooltip": "For more information, see https://desec.readthedocs.io/en/latest/auth/tokens.html", + "access.form.dingtalkbot_webhook_url.label": "DingTalk bot Webhook URL", + "access.form.dingtalkbot_webhook_url.placeholder": "Please enter DingTalk bot Webhook URL", + "access.form.dingtalkbot_webhook_url.tooltip": "For more information, see https://open.dingtalk.com/document/orgapp/obtain-the-webhook-address-of-a-custom-robot", + "access.form.dingtalkbot_secret.label": "DingTalk bot secret", + "access.form.dingtalkbot_secret.placeholder": "Please enter DingTalk bot secret", + "access.form.dingtalkbot_secret.tooltip": "For more information, see https://open.dingtalk.com/document/orgapp/customize-robot-security-settings", "access.form.dnsla_api_id.label": "DNS.LA API ID", "access.form.dnsla_api_id.placeholder": "Please enter DNS.LA API ID", "access.form.dnsla_api_id.tooltip": "For more information, see https://www.dns.la/docs/ApiDoc", @@ -166,6 +170,19 @@ "access.form.edgio_client_secret.label": "Edgio ClientSecret", "access.form.edgio_client_secret.placeholder": "Please enter Edgio ClientSecret", "access.form.edgio_client_secret.tooltip": "For more information, see https://docs.edg.io/applications/v7/rest_api/authentication#administering-api-clients", + "access.form.email_smtp_host.label": "SMTP host", + "access.form.email_smtp_host.placeholder": "Please enter SMTP host", + "access.form.email_smtp_port.label": "SMTP port", + "access.form.email_smtp_port.placeholder": "Please enter SMTP port", + "access.form.email_smtp_tls.label": "Use SSL/TLS", + "access.form.email_username.label": "Username", + "access.form.email_username.placeholder": "please enter username", + "access.form.email_password.label": "Password", + "access.form.email_password.placeholder": "please enter password", + "access.form.email_default_sender_address.label": "Default sender email address (Optional)", + "access.form.email_default_sender_address.placeholder": "Please enter default sender email address", + "access.form.email_default_receiver_address.label": "Default receiver email address (Optional)", + "access.form.email_default_receiver_address.placeholder": "Please enter default receiver email address", "access.form.gcore_api_token.label": "Gcore API token", "access.form.gcore_api_token.placeholder": "Please enter Gcore API token", "access.form.gcore_api_token.tooltip": "For more information, see https://api.gcore.com/docs/iam#section/Authentication", @@ -181,6 +198,17 @@ "access.form.godaddy_api_secret.label": "GoDaddy API secret", "access.form.godaddy_api_secret.placeholder": "Please enter GoDaddy API secret", "access.form.godaddy_api_secret.tooltip": "For more information, see https://developer.godaddy.com/", + "access.form.goedge_api_url.label": "GoEdge API URL", + "access.form.goedge_api_url.placeholder": "Please enter GoEdge API URL", + "access.form.goedge_access_key_id.label": "GoEdge user AccessKeyId", + "access.form.goedge_access_key_id.placeholder": "Please enter GoEdge user AccessKeyId", + "access.form.goedge_access_key_id.tooltip": "For more information, see https://goedge.cloud/docs/API/Auth.md", + "access.form.goedge_access_key.label": "GoEdge user AccessKey", + "access.form.goedge_access_key.placeholder": "Please enter GoEdge user AccessKey", + "access.form.goedge_access_key.tooltip": "For more information, see https://goedge.cloud/docs/API/Auth.md", + "access.form.goedge_allow_insecure_conns.label": "Insecure SSL/TLS connections", + "access.form.goedge_allow_insecure_conns.switch.on": "Allow", + "access.form.goedge_allow_insecure_conns.switch.off": "Disallow", "access.form.googletrustservices_eab_kid.label": "ACME EAB KID", "access.form.googletrustservices_eab_kid.placeholder": "Please enter ACME EAB KID", "access.form.googletrustservices_eab_kid.tooltip": "For more information, see https://cloud.google.com/certificate-manager/docs/public-ca-tutorial", @@ -203,6 +231,18 @@ "access.form.k8s_kubeconfig.placeholder": "Please enter KubeConfig file", "access.form.k8s_kubeconfig.upload": "Choose File ...", "access.form.k8s_kubeconfig.tooltip": "For more information, see https://kubernetes.io/docs/concepts/configuration/organize-cluster-access-kubeconfig/

Leave it blank to use the Pod's ServiceAccount.", + "access.form.larkbot_webhook_url.label": "Lark bot Webhook URL", + "access.form.larkbot_webhook_url.placeholder": "Please enter Lark bot Webhook URL", + "access.form.larkbot_webhook_url.tooltip": "For more information, see https://www.feishu.cn/hc/en-US/articles/807992406756", + "access.form.mattermost_server_url.label": "Mattermost server URL", + "access.form.mattermost_server_url.placeholder": "Please enter Mattermost server URL", + "access.form.mattermost_username.label": "Mattermost username", + "access.form.mattermost_username.placeholder": "Please enter Mattermost username", + "access.form.mattermost_password.label": "Mattermost password", + "access.form.mattermost_password.placeholder": "Please enter Mattermost password", + "access.form.mattermost_default_channel_id.label": "Default Mattermost channel ID (Optional)", + "access.form.mattermost_default_channel_id.placeholder": "Please enter default Mattermost channel ID", + "access.form.mattermost_default_channel_id.tooltip": "How to get the channel ID? Select the target channel from the left sidebar, click on the channel name at the top, and choose ”Channel Details.” You can directly see the channel ID on the pop-up page.", "access.form.namecheap_username.label": "Namecheap username", "access.form.namecheap_username.placeholder": "Please enter Namecheap username", "access.form.namecheap_username.tooltip": "For more information, see https://www.namecheap.com/support/api/intro/", @@ -229,10 +269,23 @@ "access.form.porkbun_secret_api_key.tooltip": "For more information, see https://porkbun.com/api/json/v3/documentation", "access.form.powerdns_api_url.label": "PowerDNS API URL", "access.form.powerdns_api_url.placeholder": "Please enter PowerDNS API URL", - "access.form.powerdns_api_url.tooltip": "For more information, see https://doc.powerdns.com/authoritative/http-api/index.html#endpoints-and-objects-in-the-api", "access.form.powerdns_api_key.label": "PowerDNS API key", "access.form.powerdns_api_key.placeholder": "Please enter PowerDNS API key", "access.form.powerdns_api_key.tooltip": "For more information, see https://doc.powerdns.com/authoritative/http-api/index.html#enabling-the-api", + "access.form.powerdns_allow_insecure_conns.label": "Insecure SSL/TLS connections", + "access.form.powerdns_allow_insecure_conns.switch.on": "Allow", + "access.form.powerdns_allow_insecure_conns.switch.off": "Disallow", + "access.form.proxmoxve_api_url.label": "Proxmox VE URL", + "access.form.proxmoxve_api_url.placeholder": "Please enter Proxmox VE URL", + "access.form.proxmoxve_api_token.label": "Proxmox VE API token", + "access.form.proxmoxve_api_token.placeholder": "Please enter Proxmox VE API token", + "access.form.proxmoxve_api_token.tooltip": "For more information, see https://pve.proxmox.com/pve-docs/pve-admin-guide.html#pveum_tokens", + "access.form.proxmoxve_api_token_secret.label": "Proxmox VE API token secret (Optional)", + "access.form.proxmoxve_api_token_secret.placeholder": "Please enter Proxmox VE API token secret", + "access.form.proxmoxve_api_token_secret.tooltip": "For more information, see https://pve.proxmox.com/pve-docs/pve-admin-guide.html#pveum_tokens", + "access.form.proxmoxve_allow_insecure_conns.label": "Insecure SSL/TLS connections", + "access.form.proxmoxve_allow_insecure_conns.switch.on": "Allow", + "access.form.proxmoxve_allow_insecure_conns.switch.off": "Disallow", "access.form.qiniu_access_key.label": "Qiniu AccessKey", "access.form.qiniu_access_key.placeholder": "Please enter Qiniu AccessKey", "access.form.qiniu_access_key.tooltip": "For more information, see https://portal.qiniu.com/", @@ -244,12 +297,10 @@ "access.form.rainyun_api_key.tooltip": "For more information, see https://app.rainyun.com/account/settings/api-key", "access.form.safeline_api_url.label": "SafeLine URL", "access.form.safeline_api_url.placeholder": "Please enter SafeLine URL", - "access.form.safeline_api_url.tooltip": "For more information, see https://docs.waf.chaitin.com/en/tutorials/install", "access.form.safeline_api_token.label": "SafeLine API token", "access.form.safeline_api_token.placeholder": "Please enter SafeLine API token", "access.form.safeline_api_token.tooltip": "For more information, see https://docs.waf.chaitin.com/en/reference/articles/openapi", "access.form.safeline_allow_insecure_conns.label": "Insecure SSL/TLS connections", - "access.form.safeline_allow_insecure_conns.tooltip": "Allowing insecure connections may lead to data leak or tampering. Use this option only when under trusted networks.", "access.form.safeline_allow_insecure_conns.switch.on": "Allow", "access.form.safeline_allow_insecure_conns.switch.off": "Disallow", "access.form.ssh_host.label": "Server host", @@ -274,6 +325,12 @@ "access.form.sslcom_eab_hmac_key.label": "ACME EAB HMAC key", "access.form.sslcom_eab_hmac_key.placeholder": "Please enter ACME EAB HMAC key", "access.form.sslcom_eab_hmac_key.tooltip": "For more information, see https://www.ssl.com/how-to/generate-acme-credentials-for-reseller-customers/", + "access.form.telegram_bot_token.label": "Telegram bot token", + "access.form.telegram_bot_token.placeholder": "Please enter Telegram bot token", + "access.form.telegram_bot_token.tooltip": "How to get the bot token? Please refer to https://gist.github.com/nafiesl/4ad622f344cd1dc3bb1ecbe468ff9f8a", + "access.form.telegram_default_chat_id.label": "Default Telegram chat ID (Optional)", + "access.form.telegram_default_chat_id.placeholder": "Please enter default Telegram chat ID", + "access.form.telegram_default_chat_id.tooltip": "How to get the chat ID? Please refer to https://gist.github.com/nafiesl/4ad622f344cd1dc3bb1ecbe468ff9f8a", "access.form.tencentcloud_secret_id.label": "Tencent Cloud SecretId", "access.form.tencentcloud_secret_id.placeholder": "Please enter Tencent Cloud SecretId", "access.form.tencentcloud_secret_id.tooltip": "For more information, see https://cloud.tencent.com/document/product/598/40488?lang=en", @@ -312,10 +369,33 @@ "access.form.wangsu_api_key.tooltip": "For more information, see https://en.wangsu.com/document/account-manage/15776", "access.form.webhook_url.label": "Webhook URL", "access.form.webhook_url.placeholder": "Please enter Webhook URL", + "access.form.webhook_method.label": "Webhook request method", + "access.form.webhook_method.placeholder": "Please select Webhook request method", + "access.form.webhook_headers.label": "Webhook request headers (Optional)", + "access.form.webhook_headers.placeholder": "Please enter Webhook request headers", + "access.form.webhook_headers.errmsg.invalid": "Please enter a valid request headers", + "access.form.webhook_headers.tooltip": "Format:
key1: val2
key2: val2


Example:
Content-Type: application/json
User-Agent: certimate
", + "access.form.webhook_default_data.errmsg.json_invalid": "Please enter a valiod JSON string", + "access.form.webhook_default_data_for_deployment.label": "Webhook data for deployment (Optional)", + "access.form.webhook_default_data_for_deployment.placeholder": "Please enter Webhook data", + "access.form.webhook_default_data_for_deployment.guide": "Tips: The Webhook data should be in JSON format.

The values in JSON support template variables, which will be replaced by actual values when sent to the Webhook URL. Supported variables:
  1. ${DOMAIN}: The primary domain of the certificate (CommonName).
  2. ${DOMAINS}: The domain list of the certificate (SubjectAltNames).
  3. ${CERTIFICATE}: The PEM format content of the certificate file.
  4. ${PRIVATE_KEY}: The PEM format content of the private key file.

When the request method is GET, the data will be passed as query string. Otherwise, the data will be encoded in the format indicated by the Content-Type in the request headers. Supported formats:
  1. application/json (default).
  2. application/x-www-form-urlencoded: Nested data is not supported.
  3. multipart/form-data: Nested data is not supported.
  4. ", + "access.form.webhook_default_data_for_notification.label": "Webhook data for notification (Optional)", + "access.form.webhook_default_data_for_notification.placeholder": "Please enter Webhook data", + "access.form.webhook_default_data_for_notification.guide": "Tips: The Webhook data should be in JSON format.

    The values in JSON support template variables, which will be replaced by actual values when sent to the Webhook URL. Supported variables:
    1. ${SUBJECT}: The subject of notification.
    2. ${MESSAGE}: The message of notification.

    When the request method is GET, the data will be passed as query string. Otherwise, the data will be encoded in the format indicated by the Content-Type in the request headers. Supported formats:
    1. application/json (default).
    2. application/x-www-form-urlencoded: Nested data is not supported.
    3. multipart/form-data: Nested data is not supported.
    4. ", + "access.form.webhook_preset_data.button": "Use preset template", + "access.form.webhook_preset_data.option.bark.label": "Bark", + "access.form.webhook_preset_data.option.gotify.label": "Gotify", + "access.form.webhook_preset_data.option.ntfy.label": "ntfy", + "access.form.webhook_preset_data.option.pushover.label": "Pushover", + "access.form.webhook_preset_data.option.pushplus.label": "PushPlus", + "access.form.webhook_preset_data.option.serverchan.label": "ServerChan", + "access.form.webhook_preset_data.option.common.label": "General template", "access.form.webhook_allow_insecure_conns.label": "Insecure SSL/TLS connections", - "access.form.webhook_allow_insecure_conns.tooltip": "Allowing insecure connections may lead to data leak or tampering. Use this option only when under trusted networks.", "access.form.webhook_allow_insecure_conns.switch.on": "Allow", "access.form.webhook_allow_insecure_conns.switch.off": "Disallow", + "access.form.wecombot_webhook_url.label": "WeCom bot Webhook URL", + "access.form.wecombot_webhook_url.placeholder": "Please enter WeCom bot Webhook URL", + "access.form.wecombot_webhook_url.tooltip": "For more information, see https://open.work.weixin.qq.com/help2/pc/18401", "access.form.westcn_username.label": "West.cn username", "access.form.westcn_username.placeholder": "Please enter West.cn username", "access.form.westcn_username.tooltip": "For more information, see https://www.west.cn/CustomerCenter/doc/apiv2.html", diff --git a/ui/src/i18n/locales/en/nls.provider.json b/ui/src/i18n/locales/en/nls.provider.json index 1d4b9c2b..0c140684 100644 --- a/ui/src/i18n/locales/en/nls.provider.json +++ b/ui/src/i18n/locales/en/nls.provider.json @@ -11,6 +11,7 @@ "provider.aliyun.cdn": "Alibaba Cloud - CDN (Content Delivery Network)", "provider.aliyun.clb": "Alibaba Cloud - CLB (Classic Load Balancer)", "provider.aliyun.dcdn": "Alibaba Cloud - DCDN (Dynamic Route for Content Delivery Network)", + "provider.aliyun.ddos": "Alibaba Cloud - Anti-DDoS Proxy", "provider.aliyun.dns": "Alibaba Cloud - DNS (Domain Name Service)", "provider.aliyun.esa": "Alibaba Cloud - ESA (Edge Security Acceleration)", "provider.aliyun.fc": "Alibaba Cloud - FC (Function Compute)", @@ -52,19 +53,20 @@ "provider.ctcccloud": "China Telecom Cloud (State Cloud)", "provider.cucccloud": "China Unicom Cloud", "provider.desec": "deSEC", + "provider.dingtalkbot": "DingTalk Bot", "provider.dnsla": "DNS.LA", "provider.dogecloud": "Doge Cloud", "provider.dogecloud.cdn": "Doge Cloud - CDN (Content Delivery Network)", "provider.dynv6": "dynv6", "provider.edgio": "Edgio", "provider.edgio.applications": "Edgio - Applications", + "provider.email": "Email", "provider.fastly": "Fastly", "provider.gcore": "Gcore", "provider.gcore.cdn": "Gcore - CDN (Content Delivery Network)", "provider.gname": "GNAME", "provider.godaddy": "GoDaddy", "provider.goedge": "GoEdge", - "provider.goedge.cdn": "GoEdge - CDN (Content Delivery Network)", "provider.googletrustservices": "Google Trust Services", "provider.huaweicloud": "Huawei Cloud", "provider.huaweicloud.cdn": "Huawei Cloud - CDN (Content Delivery Network)", @@ -80,15 +82,18 @@ "provider.jdcloud.vod": "JD Cloud - VOD (Video on Demand)", "provider.kubernetes": "Kubernetes", "provider.kubernetes.secret": "Kubernetes - Secret", + "provider.larkbot": "Lark Bot", "provider.letsencrypt": "Let's Encrypt", "provider.letsencryptstaging": "Let's Encrypt Staging Environment", "provider.local": "Local deployment", + "provider.mattermost": "Mattermost", "provider.namecheap": "Namecheap", "provider.namedotcom": "Name.com", "provider.namesilo": "NameSilo", "provider.ns1": "NS1 (IBM NS1 Connect)", "provider.porkbun": "Porkbun", "provider.powerdns": "PowerDNS", + "provider.proxmoxve": "Proxmox VE", "provider.qiniu": "Qiniu", "provider.qiniu.cdn": "Qiniu - CDN (Content Delivery Network)", "provider.qiniu.kodo": "Qiniu - Kodo", @@ -98,6 +103,7 @@ "provider.safeline": "SafeLine", "provider.ssh": "SSH deployment", "provider.sslcom": "SSL.com", + "provider.telegram": "Telegram", "provider.tencentcloud": "Tencent Cloud", "provider.tencentcloud.cdn": "Tencent Cloud - CDN (Content Delivery Network)", "provider.tencentcloud.clb": "Tencent Cloud - CLB (Cloud Load Balancer)", @@ -131,6 +137,7 @@ "provider.wangsu": "Wangsu Cloud", "provider.wangsu.cdnpro": "Wangsu Cloud - CDN Pro", "provider.webhook": "Webhook", + "provider.wecombot": "WeCom Bot", "provider.westcn": "West.cn", "provider.zerossl": "ZeroSSL", @@ -142,6 +149,7 @@ "provider.category.av": "Audio/Video", "provider.category.serverless": "Serverless", "provider.category.website": "Website", + "provider.category.nas": "NAS", "provider.category.other": "Other", "provider.default_ca_provider.label": "(Default) Follow global settings" diff --git a/ui/src/i18n/locales/en/nls.settings.json b/ui/src/i18n/locales/en/nls.settings.json index b56113c4..ee97efd7 100644 --- a/ui/src/i18n/locales/en/nls.settings.json +++ b/ui/src/i18n/locales/en/nls.settings.json @@ -82,7 +82,6 @@ "settings.notification.channel.form.pushover_user.placeholder": "Please enter User/Group Key", "settings.notification.channel.form.pushover_user.label": "User/Group Key", "settings.notification.channel.form.pushover_user.tooltip": "For more information, see https://pushover.net/api#identifiers", - "settings.notification.channel.form.pushplus_token.placeholder": "Please enter Token", "settings.notification.channel.form.pushplus_token.label": "Token", "settings.notification.channel.form.pushplus_token.placeholder": "Please enter token", "settings.notification.channel.form.pushplus_token.tooltip": "For more information, see https://www.pushplus.plus/push1.html", diff --git a/ui/src/i18n/locales/en/nls.workflow.nodes.json b/ui/src/i18n/locales/en/nls.workflow.nodes.json index f322c3df..da776fc9 100644 --- a/ui/src/i18n/locales/en/nls.workflow.nodes.json +++ b/ui/src/i18n/locales/en/nls.workflow.nodes.json @@ -39,6 +39,9 @@ "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 challenge.", "workflow_node.apply.form.provider_access.button": "Create", + "workflow_node.apply.form.aliyun_esa_region.label": "Alibaba Cloud ESA region", + "workflow_node.apply.form.aliyun_esa_region.placeholder": "Please enter Alibaba Cloud ESA region (e.g. cn-hangzhou)", + "workflow_node.apply.form.aliyun_esa_region.tooltip": "For more information, see https://www.alibabacloud.com/help/en/edge-security-acceleration/esa/api-esa-2024-09-10-endpoint", "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", @@ -54,7 +57,7 @@ "workflow_node.apply.form.tencentcloud_eo_zone_id.label": "Tencent Cloud EdgeOne zone ID", "workflow_node.apply.form.tencentcloud_eo_zone_id.placeholder": "Please enter Tencent Cloud EdgeOne zone ID", "workflow_node.apply.form.tencentcloud_eo_zone_id.tooltip": "For more information, see https://console.tencentcloud.com/edgeone", - "workflow_node.apply.form.advanced_config.label": "Advanced settings", + "workflow_node.apply.form.certificate_config.label": "Certificate settings", "workflow_node.apply.form.ca_provider.label": "Certificate authority (Optional)", "workflow_node.apply.form.ca_provider.placeholder": "Please select a certificate authority", "workflow_node.apply.form.ca_provider.tooltip": "Used to issue SSL certificates.", @@ -64,27 +67,32 @@ "workflow_node.apply.form.ca_provider_access.button": "Create", "workflow_node.apply.form.key_algorithm.label": "Certificate key algorithm", "workflow_node.apply.form.key_algorithm.placeholder": "Please select certificate key algorithm", + "workflow_node.apply.form.advanced_config.label": "Advanced settings", "workflow_node.apply.form.nameservers.label": "DNS recursive nameservers (Optional)", "workflow_node.apply.form.nameservers.placeholder": "Please enter DNS recursive nameservers (separated by semicolons)", "workflow_node.apply.form.nameservers.tooltip": "It determines whether to custom DNS recursive nameservers during ACME DNS-01 challenge. If you don't understand this option, just keep it by default. Learn more.", "workflow_node.apply.form.nameservers.multiple_input_modal.title": "Change DNS rcursive nameservers", "workflow_node.apply.form.nameservers.multiple_input_modal.placeholder": "Please enter DNS recursive nameserver", - "workflow_node.apply.form.dns_propagation_timeout.label": "DNS propagation timeout (Optional)", - "workflow_node.apply.form.dns_propagation_timeout.placeholder": "Please enter DNS propagation timeout", + "workflow_node.apply.form.dns_propagation_wait.label": "DNS propagation waiting time (Optional)", + "workflow_node.apply.form.dns_propagation_wait.placeholder": "Please enter DNS propagation waiting time", + "workflow_node.apply.form.dns_propagation_wait.unit": "seconds", + "workflow_node.apply.form.dns_propagation_wait.tooltip": "It determines the waiting time for DNS propagation during ACME DNS-01 challenge. If you don't understand this option, just keep it by default.", + "workflow_node.apply.form.dns_propagation_timeout.label": "DNS propagation checks timeout (Optional)", + "workflow_node.apply.form.dns_propagation_timeout.placeholder": "Please enter DNS propagation checks timeout", "workflow_node.apply.form.dns_propagation_timeout.unit": "seconds", - "workflow_node.apply.form.dns_propagation_timeout.tooltip": "It determines the maximum waiting time for DNS propagation checks during ACME DNS-01 challenge. If you don't understand this option, just keep it by default.

      Leave it blank to use the default value provided by the provider.", + "workflow_node.apply.form.dns_propagation_timeout.tooltip": "It determines the timeout for DNS propagation checks during ACME DNS-01 challenge. If you don't understand this option, just keep it by default.

      Leave it blank to use the default value provided by the provider.", "workflow_node.apply.form.dns_ttl.label": "DNS TTL (Optional)", "workflow_node.apply.form.dns_ttl.placeholder": "Please enter DNS TTL", "workflow_node.apply.form.dns_ttl.unit": "seconds", - "workflow_node.apply.form.dns_ttl.tooltip": "It determines the time to live for DNS record during ACME DNS-01 challenge. If you don't understand this option, just keep it by default.

      Leave it blank to use the default value provided by the provider.", + "workflow_node.apply.form.dns_ttl.tooltip": "It determines the TTL for DNS record during ACME DNS-01 challenge. If you don't understand this option, just keep it by default.

      Leave it blank to use the default value provided by the provider.", "workflow_node.apply.form.disable_follow_cname.label": "Disable CNAME following", "workflow_node.apply.form.disable_follow_cname.tooltip": "It determines whether to disable CNAME following during ACME DNS-01 challenge. If you don't understand this option, just keep it by default. Learn more.", "workflow_node.apply.form.disable_ari.label": "Disable ARI", "workflow_node.apply.form.disable_ari.tooltip": "It determines whether to disable ARI (ACME Renewal Information). If you don't understand this option, just keep it by default. Learn more.", "workflow_node.apply.form.strategy_config.label": "Strategy settings", - "workflow_node.apply.form.skip_before_expiry_days.label": "Renewal interval", + "workflow_node.apply.form.skip_before_expiry_days.label": "Repeated application", "workflow_node.apply.form.skip_before_expiry_days.placeholder": "Please enter renewal interval", - "workflow_node.apply.form.skip_before_expiry_days.prefix": "If the certificate expiration time exceeds", + "workflow_node.apply.form.skip_before_expiry_days.prefix": "If the last certificate expiration time exceeds", "workflow_node.apply.form.skip_before_expiry_days.suffix": ", skip to re-apply.", "workflow_node.apply.form.skip_before_expiry_days.unit": "days", "workflow_node.apply.form.skip_before_expiry_days.tooltip": "Be careful not to exceed the validity period limit of the issued certificate, otherwise the certificate may never be renewed.", @@ -93,8 +101,8 @@ "workflow_node.deploy.search.provider.placeholder": "Search deploy target ...", "workflow_node.deploy.form.provider.label": "Deploy target", "workflow_node.deploy.form.provider.placeholder": "Please select deploy target", - "workflow_node.deploy.form.provider_access.label": "Host provider authorization", - "workflow_node.deploy.form.provider_access.placeholder": "Please select an authorization of host provider", + "workflow_node.deploy.form.provider_access.label": "Hosting provider authorization", + "workflow_node.deploy.form.provider_access.placeholder": "Please select an authorization of Hosting provider", "workflow_node.deploy.form.provider_access.tooltip": "Used to invoke API during deployment.", "workflow_node.deploy.form.provider_access.button": "Create", "workflow_node.deploy.form.provider_access.guide_for_local": "Tips: If you are running Certimate in Docker, the \"Local\" refers to the container rather than the host.", @@ -186,6 +194,12 @@ "workflow_node.deploy.form.aliyun_dcdn_domain.label": "Alibaba Cloud DCDN domain", "workflow_node.deploy.form.aliyun_dcdn_domain.placeholder": "Please enter Alibaba Cloud DCDN domain name", "workflow_node.deploy.form.aliyun_dcdn_domain.tooltip": "For more information, see https://dcdn.console.aliyun.com", + "workflow_node.deploy.form.aliyun_ddos_region.label": "Alibaba Cloud Anti-DDoS region", + "workflow_node.deploy.form.aliyun_ddos_region.placeholder": "Please enter Alibaba Cloud Anti-DDoS region (e.g. cn-hangzhou)", + "workflow_node.deploy.form.aliyun_ddos_region.tooltip": "For more information, see https://www.alibabacloud.com/help/en/anti-ddos/anti-ddos-pro-and-premium/developer-reference/api-ddoscoo-2020-01-01-endpoint", + "workflow_node.deploy.form.aliyun_ddos_domain.label": "Alibaba Cloud Anti-DDoS domain", + "workflow_node.deploy.form.aliyun_ddos_domain.placeholder": "Please enter Alibaba Cloud Anti-DDoS domain name", + "workflow_node.deploy.form.aliyun_ddos_domain.tooltip": "For more information, see https://yundun.console.aliyun.com/?p=ddoscoo", "workflow_node.deploy.form.aliyun_esa_region.label": "Alibaba Cloud ESA region", "workflow_node.deploy.form.aliyun_esa_region.placeholder": "Please enter Alibaba Cloud ESA region (e.g. cn-hangzhou)", "workflow_node.deploy.form.aliyun_esa_region.tooltip": "For more information, see https://www.alibabacloud.com/help/en/edge-security-acceleration/esa/api-esa-2024-09-10-endpoint", @@ -319,9 +333,9 @@ "workflow_node.deploy.form.bunny_cdn_pull_zone_id.label": "Bunny CDN pull zone ID", "workflow_node.deploy.form.bunny_cdn_pull_zone_id.placeholder": "Please enter Bunny CDN pull zone ID", "workflow_node.deploy.form.bunny_cdn_pull_zone_id.tooltip": "What is this? See https://dash.bunny.net/cdn", - "workflow_node.deploy.form.bunny_cdn_host_name.label": "Bunny CDN hostname", - "workflow_node.deploy.form.bunny_cdn_host_name.placeholder": "Please enter Bunny CDN hostname", - "workflow_node.deploy.form.bunny_cdn_host_name.tooltip": "What is this? See https://dash.bunny.net/cdn", + "workflow_node.deploy.form.bunny_cdn_hostname.label": "Bunny CDN hostname", + "workflow_node.deploy.form.bunny_cdn_hostname.placeholder": "Please enter Bunny CDN hostname", + "workflow_node.deploy.form.bunny_cdn_hostname.tooltip": "What is this? See https://dash.bunny.net/cdn", "workflow_node.deploy.form.byteplus_cdn_domain.label": "BytePlus CDN domain", "workflow_node.deploy.form.byteplus_cdn_domain.placeholder": "Please enter BytePlus CDN domain name", "workflow_node.deploy.form.byteplus_cdn_domain.tooltip": "For more information, see https://console.byteplus.com/cdn", @@ -342,6 +356,11 @@ "workflow_node.deploy.form.gcore_cdn_resource_id.label": "Gcore CDN resource ID", "workflow_node.deploy.form.gcore_cdn_resource_id.placeholder": "Please enter Gcore CDN resource ID", "workflow_node.deploy.form.gcore_cdn_resource_id.tooltip": "For more information, see https://cdn.gcore.com/resources/list", + "workflow_node.deploy.form.goedge_resource_type.label": "Resource type", + "workflow_node.deploy.form.goedge_resource_type.placeholder": "Please select resource type", + "workflow_node.deploy.form.goedge_resource_type.option.certificate.label": "Certificate", + "workflow_node.deploy.form.goedge_certificate_id.label": "GoEdge certificate ID", + "workflow_node.deploy.form.goedge_certificate_id.placeholder": "Please enter GoEdge certificate ID", "workflow_node.deploy.form.huaweicloud_cdn_region.label": "Huawei Cloud CDN region", "workflow_node.deploy.form.huaweicloud_cdn_region.placeholder": "Please enter Huawei Cloud CDN region (e.g. cn-north-1)", "workflow_node.deploy.form.huaweicloud_cdn_region.tooltip": "For more information, see https://console-intl.huaweicloud.com/apiexplorer/#/endpoint", @@ -452,11 +471,15 @@ "workflow_node.deploy.form.local_post_command.label": "Post-command (Optional)", "workflow_node.deploy.form.local_post_command.placeholder": "Please enter command to be executed after saving files", "workflow_node.deploy.form.local_preset_scripts.button": "Use preset scripts", - "workflow_node.deploy.form.local_preset_scripts.option.backup_files.label": "POSIX Bash - Backup certificate files", - "workflow_node.deploy.form.local_preset_scripts.option.reload_nginx.label": "POSIX Bash - Reload nginx", - "workflow_node.deploy.form.local_preset_scripts.option.binding_iis.label": "PowerShell - Binding IIS", - "workflow_node.deploy.form.local_preset_scripts.option.binding_netsh.label": "PowerShell - Binding netsh", - "workflow_node.deploy.form.local_preset_scripts.option.binding_rdp.label": "PowerShell - Binding RDP", + "workflow_node.deploy.form.local_preset_scripts.option.sh_backup_files.label": "POSIX Bash - Backup certificate files", + "workflow_node.deploy.form.local_preset_scripts.option.ps_backup_files.label": "PowerShell - Backup certificate files", + "workflow_node.deploy.form.local_preset_scripts.option.sh_reload_nginx.label": "POSIX Bash - Reload nginx", + "workflow_node.deploy.form.local_preset_scripts.option.ps_binding_iis.label": "PowerShell - Binding IIS", + "workflow_node.deploy.form.local_preset_scripts.option.ps_binding_netsh.label": "PowerShell - Binding netsh", + "workflow_node.deploy.form.local_preset_scripts.option.ps_.label": "PowerShell - Binding RDP", + "workflow_node.deploy.form.proxmoxve_node_name.label": "Proxmox VE cluster node name", + "workflow_node.deploy.form.proxmoxve_node_name.placeholder": "Please enter Proxmox VE cluster node name", + "workflow_node.deploy.form.proxmoxve_auto_restart.label": "Auto restart after deployment", "workflow_node.deploy.form.qiniu_cdn_domain.label": "Qiniu CDN domain", "workflow_node.deploy.form.qiniu_cdn_domain.placeholder": "Please enter Qiniu CDN domain name", "workflow_node.deploy.form.qiniu_cdn_domain.tooltip": "For more information, see https://portal.qiniu.com/cdn", @@ -510,8 +533,12 @@ "workflow_node.deploy.form.ssh_post_command.label": "Post-command (Optional)", "workflow_node.deploy.form.ssh_post_command.placeholder": "Please enter command to be executed after uploading files", "workflow_node.deploy.form.ssh_preset_scripts.button": "Use preset scripts", - "workflow_node.deploy.form.ssh_preset_scripts.option.backup_files.label": "POSIX Bash - Backup certificate files", - "workflow_node.deploy.form.ssh_preset_scripts.option.reload_nginx.label": "POSIX Bash - Reload nginx", + "workflow_node.deploy.form.ssh_preset_scripts.option.sh_backup_files.label": "POSIX Bash - Backup certificate files", + "workflow_node.deploy.form.ssh_preset_scripts.option.ps_backup_files.label": "PowerShell - Backup certificate files", + "workflow_node.deploy.form.ssh_preset_scripts.option.sh_reload_nginx.label": "POSIX Bash - Reload nginx", + "workflow_node.deploy.form.ssh_preset_scripts.option.ps_binding_iis.label": "PowerShell - Binding IIS", + "workflow_node.deploy.form.ssh_preset_scripts.option.ps_binding_netsh.label": "PowerShell - Binding netsh", + "workflow_node.deploy.form.ssh_preset_scripts.option.ps_binding_rdp.label": "PowerShell - Binding RDP", "workflow_node.deploy.form.ssh_use_scp.label": "Fallback to use SCP", "workflow_node.deploy.form.ssh_use_scp.tooltip": "If the remote server does not support SFTP, please enable this option to fallback to SCP.", "workflow_node.deploy.form.tencentcloud_cdn_domain.label": "Tencent Cloud CDN domain", @@ -685,11 +712,11 @@ "workflow_node.deploy.form.wangsu_cdnpro_webhook_id.label": "Wangsu Cloud CDN Webhook ID (Optional)", "workflow_node.deploy.form.wangsu_cdnpro_webhook_id.placeholder": "Please enter Wangsu Cloud CDN Webhook ID", "workflow_node.deploy.form.wangsu_cdnpro_webhook_id.tooltip": "For more information, see https://cdnpro.console.wangsu.com/v2/index/#/certificate", - "workflow_node.deploy.form.webhook_data.label": "Webhook data (JSON format)", - "workflow_node.deploy.form.webhook_data.placeholder": "Please enter Webhook data", - "workflow_node.deploy.form.webhook_data.guide": "Tips: The Webhook data should be a key-value pair in JSON format. The values in JSON support template variables, which will be replaced by actual values when sent to the Webhook URL.

      Supported variables:
      ${DOMAIN}: The primary domain of the certificate (CommonName).
      ${DOMAINS}: The domain list of the certificate (SubjectAltNames).
      ${CERTIFICATE}: The PEM format content of the certificate file.
      ${PRIVATE_KEY}: The PEM format content of the private key file.", + "workflow_node.deploy.form.webhook_data.label": "Webhook data (Optional)", + "workflow_node.deploy.form.webhook_data.placeholder": "Please enter Webhook data to override the default value", + "workflow_node.deploy.form.webhook_data.tooltip": "Leave it blank to use the default Webhook data provided by the authorization.", + "workflow_node.deploy.form.webhook_data.guide": "Supported variables:
      1. ${DOMAIN}: The primary domain of the certificate (CommonName).
      2. ${DOMAINS}: The domain list of the certificate (SubjectAltNames).
      3. ${CERTIFICATE}: The PEM format content of the certificate file.
      4. ${PRIVATE_KEY}: The PEM format content of the private key file.

      Please visit the authorization management page for addtional notes.", "workflow_node.deploy.form.webhook_data.errmsg.json_invalid": "Please enter a valiod JSON string", - "workflow_node.deploy.form.webhook_data_preset.button": "Use preset template", "workflow_node.deploy.form.strategy_config.label": "Strategy settings", "workflow_node.deploy.form.skip_on_last_succeeded.label": "Repeated deployment", "workflow_node.deploy.form.skip_on_last_succeeded.prefix": "If the last deployment was successful, ", @@ -712,9 +739,32 @@ "workflow_node.notify.form.subject.placeholder": "Please enter subject", "workflow_node.notify.form.message.label": "Message", "workflow_node.notify.form.message.placeholder": "Please enter message", - "workflow_node.notify.form.channel.label": "Channel", + "workflow_node.notify.form.channel.label": "Channel (Deprecated)", "workflow_node.notify.form.channel.placeholder": "Please select channel", "workflow_node.notify.form.channel.button": "Configure", + "workflow_node.notify.form.provider.label": "Notification channel", + "workflow_node.notify.form.provider.placeholder": "Please select notification channel", + "workflow_node.notify.form.provider_access.label": "Notification provider authorization", + "workflow_node.notify.form.provider_access.placeholder": "Please select an authorization of notification provider", + "workflow_node.notify.form.provider_access.button": "Create", + "workflow_node.notify.form.params_config.label": "Parameter settings", + "workflow_node.notify.form.email_sender_address.label": "Sender email address (Optional)", + "workflow_node.notify.form.email_sender_address.placeholder": "Please enter sender email address to override the default value", + "workflow_node.notify.form.email_sender_address.tooltip": "Leave it blank to use the default sender email address provided by the authorization.", + "workflow_node.notify.form.email_receiver_address.label": "Receiver email address (Optional)", + "workflow_node.notify.form.email_receiver_address.placeholder": "Please enter receiver email address to override the default value", + "workflow_node.notify.form.email_receiver_address.tooltip": "Leave it blank to use the default receiver email address provided by the selected authorization.", + "workflow_node.notify.form.mattermost_channel_id.label": "Mattermost channel ID (Optional)", + "workflow_node.notify.form.mattermost_channel_id.placeholder": "Please enter Mattermost channel ID to override the default value", + "workflow_node.notify.form.mattermost_channel_id.tooltip": "Leave it blank to use the default channel ID provided by the authorization.", + "workflow_node.notify.form.telegram_chat_id.label": "Telegram chat ID (Optional)", + "workflow_node.notify.form.telegram_chat_id.placeholder": "Please enter Telegram chat ID to override the default value", + "workflow_node.notify.form.telegram_chat_id.tooltip": "Leave it blank to use the default chat ID provided by the selected authorization.", + "workflow_node.notify.form.webhook_data.label": "Webhook data (Optional)", + "workflow_node.notify.form.webhook_data.placeholder": "Please enter Webhook data to override the default value", + "workflow_node.notify.form.webhook_data.tooltip": "Leave it blank to use the default Webhook data provided by the authorization.", + "workflow_node.notify.form.webhook_data.guide": "Supported variables:
      1. ${SUBJECT}: The subject of notification.
      2. ${MESSAGE}: The message of notification.

      Please visit the authorization management page for addtional notes.", + "workflow_node.notify.form.webhook_data.errmsg.json_invalid": "Please enter a valiod JSON string", "workflow_node.end.label": "End", diff --git a/ui/src/i18n/locales/zh/nls.access.json b/ui/src/i18n/locales/zh/nls.access.json index ce6ad588..bae29d27 100644 --- a/ui/src/i18n/locales/zh/nls.access.json +++ b/ui/src/i18n/locales/zh/nls.access.json @@ -18,9 +18,9 @@ "access.props.provider.usage.ca": "证书颁发机构", "access.props.provider.usage.notification": "通知渠道", "access.props.provider.builtin": "内置", - "access.props.range.both_dns_hosting": "提供商", - "access.props.range.ca_only": "证书颁发机构", - "access.props.range.notify_only": "通知渠道", + "access.props.usage.both_dns_hosting": "提供商", + "access.props.usage.ca_only": "证书颁发机构", + "access.props.usage.notification_only": "通知渠道", "access.props.created_at": "创建时间", "access.props.updated_at": "更新时间", @@ -35,12 +35,10 @@ "access.form.notification_channel.placeholder": "请选择通知渠道", "access.form.1panel_api_url.label": "1Panel URL", "access.form.1panel_api_url.placeholder": "请输入 1Panel URL", - "access.form.1panel_api_url.tooltip": "这是什么?请参阅 https://1panel.cn/docs/dev_manual/api_manual/", "access.form.1panel_api_key.label": "1Panel 接口密钥", "access.form.1panel_api_key.placeholder": "请输入 1Panel 接口密钥", "access.form.1panel_api_key.tooltip": "这是什么?请参阅 https://1panel.cn/docs/dev_manual/api_manual/", "access.form.1panel_allow_insecure_conns.label": "忽略 SSL/TLS 证书错误", - "access.form.1panel_allow_insecure_conns.tooltip": "忽略 SSL/TLS 证书错误可能导致数据泄露或被篡改。建议仅在可信网络下启用。", "access.form.1panel_allow_insecure_conns.switch.on": "允许", "access.form.1panel_allow_insecure_conns.switch.off": "不允许", "access.form.acmehttpreq_endpoint.label": "服务端点", @@ -89,12 +87,10 @@ "access.form.baishan_api_token.placeholder": "请输入白山云 API Token", "access.form.baotapanel_api_url.label": "宝塔面板 URL", "access.form.baotapanel_api_url.placeholder": "请输入宝塔面板 URL", - "access.form.baotapanel_api_url.tooltip": "这是什么?请参阅 https://www.bt.cn/bbs/thread-20376-1-1.html", "access.form.baotapanel_api_key.label": "宝塔面板接口密钥", "access.form.baotapanel_api_key.placeholder": "请输入宝塔面板接口密钥", "access.form.baotapanel_api_key.tooltip": "这是什么?请参阅 https://www.bt.cn/bbs/thread-113890-1-1.html", "access.form.baotapanel_allow_insecure_conns.label": "忽略 SSL/TLS 证书错误", - "access.form.baotapanel_allow_insecure_conns.tooltip": "忽略 SSL/TLS 证书错误可能导致数据泄露或被篡改。建议仅在可信网络下启用。", "access.form.baotapanel_allow_insecure_conns.switch.on": "允许", "access.form.baotapanel_allow_insecure_conns.switch.off": "不允许", "access.form.bunny_api_key.label": "Bunny API Key", @@ -111,13 +107,15 @@ "access.form.cachefly_api_token.tooltip": "这是什么?请参阅 https://kb.cachefly.com/kb/guide/en/generating-tokens-and-keys-Oll9Irt5TI/Steps/2460228", "access.form.cdnfly_api_url.label": "Cdnfly API URL", "access.form.cdnfly_api_url.placeholder": "请输入 Cdnfly API URL", - "access.form.cdnfly_api_url.tooltip": "这是什么?请参阅 https://doc.cdnfly.cn/anzhuangshuoming.html", "access.form.cdnfly_api_key.label": "Cdnfly 用户端 API Key", "access.form.cdnfly_api_key.placeholder": "请输入 Cdnfly 用户端 API Key", "access.form.cdnfly_api_key.tooltip": "这是什么?请参阅 https://doc.cdnfly.cn/shiyongjieshao.html", "access.form.cdnfly_api_secret.label": "Cdnfly 用户端 API Secret", "access.form.cdnfly_api_secret.placeholder": "请输入 Cdnfly 用户端 API Secret", "access.form.cdnfly_api_secret.tooltip": "这是什么?请参阅 https://doc.cdnfly.cn/shiyongjieshao.html", + "access.form.cdnfly_allow_insecure_conns.label": "忽略 SSL/TLS 证书错误", + "access.form.cdnfly_allow_insecure_conns.switch.on": "允许", + "access.form.cdnfly_allow_insecure_conns.switch.off": "不允许", "access.form.cloudflare_dns_api_token.label": "Cloudflare DNS API 令牌", "access.form.cloudflare_dns_api_token.placeholder": "请输入 Cloudflare DNS API 令牌", "access.form.cloudflare_dns_api_token.tooltip": "这是什么?请参阅 https://developers.cloudflare.com/fundamentals/api/get-started/create-token/", @@ -139,6 +137,12 @@ "access.form.desec_token.label": "deSEC Token", "access.form.desec_token.placeholder": "请输入 deSEC Token", "access.form.desec_token.tooltip": "这是什么?请参阅 https://desec.readthedocs.io/en/latest/auth/tokens.html", + "access.form.dingtalkbot_webhook_url.label": "钉钉群机器人 Webhook 地址", + "access.form.dingtalkbot_webhook_url.placeholder": "请输入钉钉群机器人 Webhook 地址", + "access.form.dingtalkbot_webhook_url.tooltip": "这是什么?请参阅 https://open.dingtalk.com/document/orgapp/obtain-the-webhook-address-of-a-custom-robot", + "access.form.dingtalkbot_secret.label": "钉钉群机器人加签密钥", + "access.form.dingtalkbot_secret.placeholder": "请输入钉钉群机器人加签密钥", + "access.form.dingtalkbot_secret.tooltip": "这是什么?请参阅 https://open.dingtalk.com/document/orgapp/customize-robot-security-settings", "access.form.dnsla_api_id.label": "DNS.LA API ID", "access.form.dnsla_api_id.placeholder": "请输入 DNS.LA API ID", "access.form.dnsla_api_id.tooltip": "这是什么?请参阅 https://www.dns.la/docs/ApiDoc", @@ -160,6 +164,19 @@ "access.form.edgio_client_secret.label": "Edgio 客户端密码", "access.form.edgio_client_secret.placeholder": "请输入 Edgio 客户端密码", "access.form.edgio_client_secret.tooltip": "这是什么?请参阅 https://docs.edg.io/applications/v7/rest_api/authentication#administering-api-clients", + "access.form.email_smtp_host.label": "SMTP 服务器地址", + "access.form.email_smtp_host.placeholder": "请输入 SMTP 服务器地址", + "access.form.email_smtp_port.label": "SMTP 服务器端口", + "access.form.email_smtp_port.placeholder": "请输入 SMTP 服务器端口", + "access.form.email_smtp_tls.label": "SSL/TLS 连接", + "access.form.email_username.label": "用户名", + "access.form.email_username.placeholder": "请输入用户名", + "access.form.email_password.label": "密码", + "access.form.email_password.placeholder": "请输入密码", + "access.form.email_default_sender_address.label": "默认的发送邮箱地址(可选)", + "access.form.email_default_sender_address.placeholder": "请输入默认的发送邮箱地址", + "access.form.email_default_receiver_address.label": "默认的接收邮箱地址(可选)", + "access.form.email_default_receiver_address.placeholder": "请输入默认的接收邮箱地址", "access.form.gcore_api_token.label": "Gcore API Token", "access.form.gcore_api_token.placeholder": "请输入 Gcore API Token", "access.form.gcore_api_token.tooltip": "这是什么?请参阅 https://api.gcore.com/docs/iam#section/Authentication", @@ -175,6 +192,17 @@ "access.form.godaddy_api_secret.label": "GoDaddy API Secret", "access.form.godaddy_api_secret.placeholder": "请输入 GoDaddy API Secret", "access.form.godaddy_api_secret.tooltip": "这是什么?请参阅 https://developer.godaddy.com/", + "access.form.goedge_api_url.label": "GoEdge API URL", + "access.form.goedge_api_url.placeholder": "请输入 GoEdge API URL", + "access.form.goedge_access_key_id.label": "GoEdge 用户 AccessKeyId", + "access.form.goedge_access_key_id.placeholder": "请输入 GoEdge 用户 AccessKeyId", + "access.form.goedge_access_key_id.tooltip": "这是什么?请参阅 https://goedge.cloud/docs/API/Auth.md", + "access.form.goedge_access_key.label": "GoEdge 用户 AccessKey", + "access.form.goedge_access_key.placeholder": "请输入 GoEdge 用户 AccessKey", + "access.form.goedge_access_key.tooltip": "这是什么?请参阅 https://goedge.cloud/docs/API/Auth.md", + "access.form.goedge_allow_insecure_conns.label": "忽略 SSL/TLS 证书错误", + "access.form.goedge_allow_insecure_conns.switch.on": "允许", + "access.form.goedge_allow_insecure_conns.switch.off": "不允许", "access.form.googletrustservices_eab_kid.label": "ACME EAB KID", "access.form.googletrustservices_eab_kid.placeholder": "请输入 ACME EAB KID", "access.form.googletrustservices_eab_kid.tooltip": "这是什么?请参阅 https://cloud.google.com/certificate-manager/docs/public-ca-tutorial", @@ -197,6 +225,18 @@ "access.form.k8s_kubeconfig.placeholder": "请选择 KubeConfig 文件", "access.form.k8s_kubeconfig.upload": "选择文件", "access.form.k8s_kubeconfig.tooltip": "这是什么?请参阅 https://kubernetes.io/zh-cn/docs/concepts/configuration/organize-cluster-access-kubeconfig/

      为空时,将使用 Pod 的 ServiceAccount 作为凭证。", + "access.form.larkbot_webhook_url.label": "飞书群机器人 Webhook 地址", + "access.form.larkbot_webhook_url.placeholder": "请输入飞书群机器人 Webhook 地址", + "access.form.larkbot_webhook_url.tooltip": "这是什么?请参阅 https://www.feishu.cn/hc/zh-CN/articles/807992406756", + "access.form.mattermost_server_url.label": "Mattermost 服务地址", + "access.form.mattermost_server_url.placeholder": "请输入 Mattermost 服务地址", + "access.form.mattermost_username.label": "Mattermost 用户名", + "access.form.mattermost_username.placeholder": "请输入 Mattermost 用户名", + "access.form.mattermost_password.label": "Mattermost 密码", + "access.form.mattermost_password.placeholder": "请输入 Mattermost 密码", + "access.form.mattermost_default_channel_id.label": "默认的 Mattermost 频道 ID(可选)", + "access.form.mattermost_default_channel_id.placeholder": "请输入默认的 Mattermost 频道 ID", + "access.form.mattermost_default_channel_id.tooltip": "如何获取频道 ID?从左侧边栏中选择目标频道,点击顶部的频道名称,选择“频道详情”,即可在弹出页面中直接看到频道 ID。", "access.form.namecheap_username.label": "Namecheap 用户名", "access.form.namecheap_username.placeholder": "请输入 Namecheap 用户名", "access.form.namecheap_username.tooltip": "这是什么?请参阅 https://www.namecheap.com/support/api/intro/", @@ -223,10 +263,23 @@ "access.form.porkbun_secret_api_key.tooltip": "这是什么?请参阅 https://porkbun.com/api/json/v3/documentation", "access.form.powerdns_api_url.label": "PowerDNS API URL", "access.form.powerdns_api_url.placeholder": "请输入 PowerDNS API URL", - "access.form.powerdns_api_url.tooltip": "这是什么?请参阅 https://doc.powerdns.com/authoritative/http-api/index.html#endpoints-and-objects-in-the-api", "access.form.powerdns_api_key.label": "PowerDNS API Key", "access.form.powerdns_api_key.placeholder": "请输入 PowerDNS API Key", "access.form.powerdns_api_key.tooltip": "这是什么?请参阅 https://doc.powerdns.com/authoritative/http-api/index.html#enabling-the-api", + "access.form.powerdns_allow_insecure_conns.label": "忽略 SSL/TLS 证书错误", + "access.form.powerdns_allow_insecure_conns.switch.on": "允许", + "access.form.powerdns_allow_insecure_conns.switch.off": "不允许", + "access.form.proxmoxve_api_url.label": "Proxmox VE URL", + "access.form.proxmoxve_api_url.placeholder": "请输入 Proxmox VE URL", + "access.form.proxmoxve_api_token.label": "Proxmox VE API Token", + "access.form.proxmoxve_api_token.placeholder": "请输入 Proxmox VE API Token", + "access.form.proxmoxve_api_token.tooltip": "这是什么?请参阅 https://pve.proxmox.com/pve-docs/pve-admin-guide.html#pveum_tokens", + "access.form.proxmoxve_api_token_secret.label": "Proxmox VE API Token Secret(可选)", + "access.form.proxmoxve_api_token_secret.placeholder": "请输入 Proxmox VE API Token Secret", + "access.form.proxmoxve_api_token_secret.tooltip": "这是什么?请参阅 https://pve.proxmox.com/pve-docs/pve-admin-guide.html#pveum_tokens", + "access.form.proxmoxve_allow_insecure_conns.label": "忽略 SSL/TLS 证书错误", + "access.form.proxmoxve_allow_insecure_conns.switch.on": "允许", + "access.form.proxmoxve_allow_insecure_conns.switch.off": "不允许", "access.form.qiniu_access_key.label": "七牛云 AccessKey", "access.form.qiniu_access_key.placeholder": "请输入七牛云 AccessKey", "access.form.qiniu_access_key.tooltip": "这是什么?请参阅 https://portal.qiniu.com/", @@ -238,12 +291,10 @@ "access.form.rainyun_api_key.tooltip": "这是什么?请参阅 https://app.rainyun.com/account/settings/api-key", "access.form.safeline_api_url.label": "雷池 URL", "access.form.safeline_api_url.placeholder": "请输入雷池 URL", - "access.form.safeline_api_url.tooltip": "这是什么?请参阅 https://docs.waf-ce.chaitin.cn/zh/上手指南/安装雷池", "access.form.safeline_api_token.label": "雷池 API Token", "access.form.safeline_api_token.placeholder": "请输入雷池 API Token", "access.form.safeline_api_token.tooltip": "这是什么?请参阅 https://docs.waf-ce.chaitin.cn/zh/更多技术文档/OPENAPI", "access.form.safeline_allow_insecure_conns.label": "忽略 SSL/TLS 证书错误", - "access.form.safeline_allow_insecure_conns.tooltip": "忽略 SSL/TLS 证书错误可能导致数据泄露或被篡改。建议仅在可信网络下启用。", "access.form.safeline_allow_insecure_conns.switch.on": "允许", "access.form.safeline_allow_insecure_conns.switch.off": "不允许", "access.form.ssh_host.label": "服务器地址", @@ -268,6 +319,12 @@ "access.form.sslcom_eab_hmac_key.label": "ACME EAB HMAC key", "access.form.sslcom_eab_hmac_key.placeholder": "请输入 ACME EAB HMAC key", "access.form.sslcom_eab_hmac_key.tooltip": "这是什么?请参阅 https://www.ssl.com/how-to/generate-acme-credentials-for-reseller-customers/", + "access.form.telegram_bot_token.label": "Telegram 机器人 API Token", + "access.form.telegram_bot_token.placeholder": "请输入 Telegram 机器人 API Token", + "access.form.telegram_bot_token.tooltip": "如何获取机器人 API Token?请参阅 https://gist.github.com/nafiesl/4ad622f344cd1dc3bb1ecbe468ff9f8a", + "access.form.telegram_default_chat_id.label": "默认的 Telegram 会话 ID(可选)", + "access.form.telegram_default_chat_id.placeholder": "请输入默认的 Telegram 会话 ID", + "access.form.telegram_default_chat_id.tooltip": "如何获取会话 ID?请参阅 https://gist.github.com/nafiesl/4ad622f344cd1dc3bb1ecbe468ff9f8a", "access.form.tencentcloud_secret_id.label": "腾讯云 SecretId", "access.form.tencentcloud_secret_id.placeholder": "请输入腾讯云 SecretId", "access.form.tencentcloud_secret_id.tooltip": "这是什么?请参阅 https://cloud.tencent.com/document/product/598/40488", @@ -312,10 +369,33 @@ "access.form.wangsu_api_key.tooltip": "这是什么?请参阅 https://www.wangsu.com/document/account-manage/15776", "access.form.webhook_url.label": "Webhook 回调地址", "access.form.webhook_url.placeholder": "请输入 Webhook 回调地址", + "access.form.webhook_method.label": "Webhook 请求谓词", + "access.form.webhook_method.placeholder": "请选择 Webhook 请求谓词", + "access.form.webhook_headers.label": "Webhook 请求标头(可选)", + "access.form.webhook_headers.placeholder": "请输入 Webhook 请求标头", + "access.form.webhook_headers.errmsg.invalid": "请输入有效的请求标头", + "access.form.webhook_headers.tooltip": "格式:
      key1: val2
      key2: val2


      示例:
      Content-Type: application/json
      User-Agent: certimate
      ", + "access.form.webhook_default_data.errmsg.json_invalid": "请输入有效的 JSON 格式字符串", + "access.form.webhook_default_data_for_deployment.label": "默认的 Webhook 部署证书回调数据(可选)", + "access.form.webhook_default_data_for_deployment.placeholder": "请输入默认的 Webhook 回调数据", + "access.form.webhook_default_data_for_deployment.guide": "小贴士:回调数据是一个 JSON 格式的数据。

      其中值支持模板变量,将在被发送到指定的 Webhook URL 时被替换为实际值;其他内容将保持原样。支持的变量:
      1. ${DOMAIN}:证书的主域名(即 CommonName)。
      2. ${DOMAINS}:证书的多域名列表(即 SubjectAltNames)。
      3. ${CERTIFICATE}:证书文件 PEM 格式内容。
      4. ${PRIVATE_KEY}:私钥文件 PEM 格式内容。

      当请求谓词为 GET 时,回调数据将作为查询参数;否则,回调数据将按照请求标头中 Content-Type 所指示的格式进行编码。支持的格式:
      1. application/json(默认)。
      2. application/x-www-form-urlencoded:不支持嵌套数据。
      3. multipart/form-data:不支持嵌套数据。
      4. ", + "access.form.webhook_default_data_for_notification.label": "默认的 Webhook 推送通知回调数据(可选)", + "access.form.webhook_default_data_for_notification.placeholder": "请输入默认的 Webhook 回调数据", + "access.form.webhook_default_data_for_notification.guide": "小贴士:回调数据是一个 JSON 格式的数据。

        其中值支持模板变量,将在被发送到指定的 Webhook URL 时被替换为实际值;其他内容将保持原样。支持的变量:
        1. ${DOMAIN}:证书的主域名(即 CommonName)。
        2. ${SUBJECT}:通知主题。
        3. ${MESSAGE}:通知内容。

        当请求谓词为 GET 时,回调数据将作为查询参数;否则,回调数据将按照请求标头中 Content-Type 所指示的格式进行编码。支持的格式:
        1. application/json(默认)。
        2. application/x-www-form-urlencoded:不支持嵌套数据。
        3. multipart/form-data:不支持嵌套数据。
        4. ", + "access.form.webhook_preset_data.button": "使用预设模板", + "access.form.webhook_preset_data.option.bark.label": "Bark", + "access.form.webhook_preset_data.option.gotify.label": "Gotify", + "access.form.webhook_preset_data.option.ntfy.label": "ntfy", + "access.form.webhook_preset_data.option.pushover.label": "Pushover", + "access.form.webhook_preset_data.option.pushplus.label": "PushPlus 推送加", + "access.form.webhook_preset_data.option.serverchan.label": "Server 酱", + "access.form.webhook_preset_data.option.common.label": "通用模板", "access.form.webhook_allow_insecure_conns.label": "忽略 SSL/TLS 证书错误", - "access.form.webhook_allow_insecure_conns.tooltip": "忽略 SSL/TLS 证书错误可能导致数据泄露或被篡改。建议仅在可信网络下启用。", "access.form.webhook_allow_insecure_conns.switch.on": "允许", "access.form.webhook_allow_insecure_conns.switch.off": "不允许", + "access.form.wecombot_webhook_url.label": "企业微信群机器人 Webhook 地址", + "access.form.wecombot_webhook_url.placeholder": "请输入企业微信群机器人 Webhook 地址", + "access.form.wecombot_webhook_url.tooltip": "这是什么?请参阅 https://open.work.weixin.qq.com/help2/pc/18401", "access.form.westcn_username.label": "西部数码用户名", "access.form.westcn_username.placeholder": "请输入西部数码用户名", "access.form.westcn_username.tooltip": "这是什么?请参阅 https://www.west.cn/CustomerCenter/doc/apiv2.html", diff --git a/ui/src/i18n/locales/zh/nls.provider.json b/ui/src/i18n/locales/zh/nls.provider.json index 86fd3e5b..5626426e 100644 --- a/ui/src/i18n/locales/zh/nls.provider.json +++ b/ui/src/i18n/locales/zh/nls.provider.json @@ -11,9 +11,10 @@ "provider.aliyun.cdn": "阿里云 - 内容分发网络 CDN", "provider.aliyun.clb": "阿里云 - 传统型负载均衡 CLB", "provider.aliyun.dcdn": "阿里云 - 全站加速 DCDN", + "provider.aliyun.ddos": "阿里云 - DDoS 高防", + "provider.aliyun.dns": "阿里云 - 云解析 DNS", "provider.aliyun.esa": "阿里云 - 边缘安全加速 ESA", "provider.aliyun.fc": "阿里云 - 函数计算 FC", - "provider.aliyun.dns": "阿里云 - 云解析 DNS", "provider.aliyun.live": "阿里云 - 视频直播 Live", "provider.aliyun.nlb": "阿里云 - 网络型负载均衡 NLB", "provider.aliyun.oss": "阿里云 - 对象存储 OSS", @@ -52,19 +53,20 @@ "provider.ctcccloud": "联通云", "provider.cucccloud": "天翼云", "provider.desec": "deSEC", + "provider.dingtalkbot": "钉钉群机器人", "provider.dnsla": "DNS.LA", "provider.dogecloud": "多吉云", "provider.dogecloud.cdn": "多吉云 - 内容分发网络 CDN", "provider.dynv6": "dynv6", "provider.edgio": "Edgio", "provider.edgio.applications": "Edgio - Applications", + "provider.email": "邮件", "provider.fastly": "Fastly", "provider.gcore": "Gcore", "provider.gcore.cdn": "Gcore - 内容分发网络 CDN", "provider.gname": "GNAME", "provider.godaddy": "GoDaddy", "provider.goedge": "GoEdge", - "provider.goedge.cdn": "GoEdge - 内容分发网络 CDN", "provider.googletrustservices": "Google Trust Services", "provider.huaweicloud": "华为云", "provider.huaweicloud.cdn": "华为云 - 内容分发网络 CDN", @@ -80,15 +82,18 @@ "provider.jdcloud.vod": "京东云 - 视频点播", "provider.kubernetes": "Kubernetes", "provider.kubernetes.secret": "Kubernetes - Secret", + "provider.larkbot": "飞书群机器人", "provider.letsencrypt": "Let's Encrypt", "provider.letsencryptstaging": "Let's Encrypt 测试环境", "provider.local": "本地部署", + "provider.mattermost": "Mattermost", "provider.namecheap": "Namecheap", "provider.namedotcom": "Name.com", "provider.namesilo": "NameSilo", "provider.ns1": "NS1 (IBM NS1 Connect)", "provider.porkbun": "Porkbun", "provider.powerdns": "PowerDNS", + "provider.proxmoxve": "Proxmox VE", "provider.qiniu": "七牛云", "provider.qiniu.cdn": "七牛云 - 内容分发网络 CDN", "provider.qiniu.kodo": "七牛云 - 对象存储 Kodo", @@ -98,6 +103,7 @@ "provider.safeline": "雷池", "provider.ssh": "SSH 部署", "provider.sslcom": "SSL.com", + "provider.telegram": "Telegram", "provider.tencentcloud": "腾讯云", "provider.tencentcloud.cdn": "腾讯云 - 内容分发网络 CDN", "provider.tencentcloud.clb": "腾讯云 - 负载均衡 CLB", @@ -131,6 +137,7 @@ "provider.wangsu": "网宿云", "provider.wangsu.cdnpro": "网宿云 - CDN Pro", "provider.webhook": "Webhook", + "provider.wecombot": "企业微信群机器人", "provider.westcn": "西部数码", "provider.zerossl": "ZeroSSL", @@ -142,6 +149,7 @@ "provider.category.av": "音视频", "provider.category.serverless": "Serverless", "provider.category.website": "网站托管", + "provider.category.nas": "NAS", "provider.category.other": "其他", "provider.default_ca_provider.label": "(默认)不指定,跟随全局设置" diff --git a/ui/src/i18n/locales/zh/nls.settings.json b/ui/src/i18n/locales/zh/nls.settings.json index 24342452..cde8ec0f 100644 --- a/ui/src/i18n/locales/zh/nls.settings.json +++ b/ui/src/i18n/locales/zh/nls.settings.json @@ -82,7 +82,6 @@ "settings.notification.channel.form.pushover_user.placeholder": "请输入用户/分组 Key", "settings.notification.channel.form.pushover_user.label": "用户/分组 Key", "settings.notification.channel.form.pushover_user.tooltip": "这是什么?请参阅 https://pushover.net/api#identifiers", - "settings.notification.channel.form.pushplus_token.placeholder": "请输入Token", "settings.notification.channel.form.pushplus_token.label": "Token", "settings.notification.channel.form.pushplus_token.placeholder": "请输入 Token", "settings.notification.channel.form.pushplus_token.tooltip": "这是什么?请参阅 https://www.pushplus.plus/push1.html", @@ -90,7 +89,7 @@ "settings.notification.channel.form.serverchan_url.placeholder": "请输入服务器地址(形如: https://sctapi.ftqq.com/*****.send)", "settings.notification.channel.form.serverchan_url.tooltip": "这是什么?请参阅 https://sct.ftqq.com/forward", "settings.notification.channel.form.telegram_api_token.label": "机器人 API Token", - "settings.notification.channel.form.telegram_api_token.placeholder": "请输入机器人 API token", + "settings.notification.channel.form.telegram_api_token.placeholder": "请输入机器人 API Token", "settings.notification.channel.form.telegram_api_token.tooltip": "这是什么?请参阅 https://gist.github.com/nafiesl/4ad622f344cd1dc3bb1ecbe468ff9f8a", "settings.notification.channel.form.telegram_chat_id.label": "会话 ID", "settings.notification.channel.form.telegram_chat_id.placeholder": "请输入会话 ID", diff --git a/ui/src/i18n/locales/zh/nls.workflow.nodes.json b/ui/src/i18n/locales/zh/nls.workflow.nodes.json index d3b5b494..3f38a490 100644 --- a/ui/src/i18n/locales/zh/nls.workflow.nodes.json +++ b/ui/src/i18n/locales/zh/nls.workflow.nodes.json @@ -39,6 +39,9 @@ "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.aliyun_esa_region.label": "阿里云 ESA 服务地域", + "workflow_node.apply.form.aliyun_esa_region.placeholder": "请输入阿里云 ESA 服务地域(例如:cn-hangzhou)", + "workflow_node.apply.form.aliyun_esa_region.tooltip": "这是什么?请参阅 https://help.aliyun.com/zh/edge-security-acceleration/esa/api-esa-2024-09-10-endpoint", "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", @@ -54,37 +57,42 @@ "workflow_node.apply.form.tencentcloud_eo_zone_id.label": "腾讯云 EdgeOne 站点 ID", "workflow_node.apply.form.tencentcloud_eo_zone_id.placeholder": "请输入腾讯云 EdgeOne 站点 ID", "workflow_node.apply.form.tencentcloud_eo_zone_id.tooltip": "这是什么?请参阅 https://console.cloud.tencent.com/edgeone", - "workflow_node.apply.form.advanced_config.label": "高级设置", + "workflow_node.apply.form.certificate_config.label": "证书设置", "workflow_node.apply.form.ca_provider.label": "证书颁发机构(可选)", "workflow_node.apply.form.ca_provider.placeholder": "请选择证书颁发机构", - "workflow_node.apply.form.ca_provider.button": "去配置", + "workflow_node.apply.form.ca_provider.button": "设置", "workflow_node.apply.form.ca_provider_access.label": "证书颁发机构授权", "workflow_node.apply.form.ca_provider_access.placeholder": "请选择证书颁发机构授权", "workflow_node.apply.form.ca_provider_access.button": "新建", - "workflow_node.apply.form.key_algorithm.label": "数字证书算法", - "workflow_node.apply.form.key_algorithm.placeholder": "请选择数字证书算法", + "workflow_node.apply.form.key_algorithm.label": "证书算法", + "workflow_node.apply.form.key_algorithm.placeholder": "请选择证书算法", + "workflow_node.apply.form.advanced_config.label": "高级设置", "workflow_node.apply.form.nameservers.label": "DNS 递归服务器(可选)", "workflow_node.apply.form.nameservers.placeholder": "请输入 DNS 递归服务器(多个值请用半角分号隔开)", - "workflow_node.apply.form.nameservers.tooltip": "在 ACME DNS-01 质询时使用自定义的 DNS 递归服务器。如果你不了解该选项的用途,保持默认即可。点此了解更多。", + "workflow_node.apply.form.nameservers.tooltip": "表示在 ACME DNS-01 质询时使用自定义的 DNS 递归服务器。如果你不了解该选项的用途,保持默认即可。点此了解更多。", "workflow_node.apply.form.nameservers.multiple_input_modal.title": "修改 DNS 递归服务器", "workflow_node.apply.form.nameservers.multiple_input_modal.placeholder": "请输入 DNS 递归服务器", + "workflow_node.apply.form.dns_propagation_wait.label": "DNS 传播等待时间(可选)", + "workflow_node.apply.form.dns_propagation_wait.placeholder": "请输入 DNS 传播等待时间", + "workflow_node.apply.form.dns_propagation_wait.unit": "秒", + "workflow_node.apply.form.dns_propagation_wait.tooltip": "表示在 ACME DNS-01 质询时 DNS 传播的等待时间。如果你不了解此选项的用途,保持默认即可。", "workflow_node.apply.form.dns_propagation_timeout.label": "DNS 传播检查超时时间(可选)", "workflow_node.apply.form.dns_propagation_timeout.placeholder": "请输入 DNS 传播检查超时时间", "workflow_node.apply.form.dns_propagation_timeout.unit": "秒", - "workflow_node.apply.form.dns_propagation_timeout.tooltip": "在 ACME DNS-01 质询时等待 DNS 传播检查的最长时间。如果你不了解此选项的用途,保持默认即可。

          不填写时,将使用提供商提供的默认值。", - "workflow_node.apply.form.dns_ttl.label": "DNS 解析 TTL(可选)", - "workflow_node.apply.form.dns_ttl.placeholder": "请输入 DNS 解析 TTL", + "workflow_node.apply.form.dns_propagation_timeout.tooltip": "表示在 ACME DNS-01 质询时 DNS 传播检查的超时时间。如果你不了解此选项的用途,保持默认即可。

          不填写时,将使用提供商提供的默认值。", + "workflow_node.apply.form.dns_ttl.label": "DNS 解析记录 TTL(可选)", + "workflow_node.apply.form.dns_ttl.placeholder": "请输入 DNS 解析记录 TTL", "workflow_node.apply.form.dns_ttl.unit": "秒", - "workflow_node.apply.form.dns_ttl.tooltip": "在 ACME DNS-01 质询时 DNS 解析记录的 TTL。如果你不了解此选项的用途,保持默认即可。

          不填写时,将使用提供商提供的默认值。", + "workflow_node.apply.form.dns_ttl.tooltip": "表示在 ACME DNS-01 质询时 DNS 解析记录的 TTL。如果你不了解此选项的用途,保持默认即可。

          不填写时,将使用提供商提供的默认值。", "workflow_node.apply.form.disable_follow_cname.label": "阻止 CNAME 跟随", "workflow_node.apply.form.disable_follow_cname.tooltip": "在 ACME DNS-01 质询时是否阻止 CNAME 跟随。如果你不了解该选项的用途,保持默认即可。点此了解更多。", "workflow_node.apply.form.disable_ari.label": "阻止 ARI 续期", "workflow_node.apply.form.disable_ari.tooltip": "在 ACME 证书续期时是否阻止 ARI(ACME Renewal Information)。如果你不了解该选项的用途,保持默认即可。点此了解更多。", "workflow_node.apply.form.strategy_config.label": "执行策略", - "workflow_node.apply.form.skip_before_expiry_days.label": "续期间隔", + "workflow_node.apply.form.skip_before_expiry_days.label": "重复申请", "workflow_node.apply.form.skip_before_expiry_days.placeholder": "请输入续期间隔", - "workflow_node.apply.form.skip_before_expiry_days.prefix": "当上次签发的证书有效期不足", - "workflow_node.apply.form.skip_before_expiry_days.suffix": "时,重新申请证书。", + "workflow_node.apply.form.skip_before_expiry_days.prefix": "当上次签发的证书剩余有效期大于", + "workflow_node.apply.form.skip_before_expiry_days.suffix": "时,再次执行工作流时跳过此申请节点。", "workflow_node.apply.form.skip_before_expiry_days.unit": "天", "workflow_node.apply.form.skip_before_expiry_days.tooltip": "注意不要超过颁发的证书最大有效期,否则证书可能永远不会续期。", @@ -101,7 +109,7 @@ "workflow_node.deploy.form.certificate.placeholder": "请选择待部署证书", "workflow_node.deploy.form.certificate.tooltip": "待部署证书来自之前的申请或上传节点。如果选项为空请先确保前序节点配置正确。", "workflow_node.deploy.form.params_config.label": "参数设置", - "workflow_node.deploy.form.1panel_console_auto_restart.label": "部署后自动重启面板服务", + "workflow_node.deploy.form.1panel_console_auto_restart.label": "部署后自动重启宝塔面板服务", "workflow_node.deploy.form.1panel_site_resource_type.label": "证书替换方式", "workflow_node.deploy.form.1panel_site_resource_type.placeholder": "请选择证书替换方式", "workflow_node.deploy.form.1panel_site_resource_type.option.website.label": "替换指定网站的证书", @@ -185,6 +193,12 @@ "workflow_node.deploy.form.aliyun_dcdn_domain.label": "阿里云 DCDN 加速域名", "workflow_node.deploy.form.aliyun_dcdn_domain.placeholder": "请输入阿里云 DCDN 加速域名(支持泛域名)", "workflow_node.deploy.form.aliyun_dcdn_domain.tooltip": "这是什么?请参阅 https://dcdn.console.aliyun.com", + "workflow_node.deploy.form.aliyun_ddos_region.label": "阿里云 DDoS 高防服务地域", + "workflow_node.deploy.form.aliyun_ddos_region.placeholder": "请输入阿里云 DDoS 高防服务地域(例如:cn-hangzhou)", + "workflow_node.deploy.form.aliyun_ddos_region.tooltip": "这是什么?请参阅 https://help.aliyun.com/zh/anti-ddos/anti-ddos-pro-and-premium/developer-reference/api-ddoscoo-2020-01-01-endpoint", + "workflow_node.deploy.form.aliyun_ddos_domain.label": "阿里云 DDoS 高防网站域名", + "workflow_node.deploy.form.aliyun_ddos_domain.placeholder": "请输入阿里云 DDoS 高防网站域名(支持泛域名)", + "workflow_node.deploy.form.aliyun_ddos_domain.tooltip": "这是什么?请参阅 https://yundun.console.aliyun.com/?p=ddoscoo", "workflow_node.deploy.form.aliyun_esa_region.label": "阿里云 ESA 服务地域", "workflow_node.deploy.form.aliyun_esa_region.placeholder": "请输入阿里云 ESA 服务地域(例如:cn-hangzhou)", "workflow_node.deploy.form.aliyun_esa_region.tooltip": "这是什么?请参阅 https://help.aliyun.com/zh/edge-security-acceleration/esa/api-esa-2024-09-10-endpoint", @@ -301,7 +315,7 @@ "workflow_node.deploy.form.baishan_cdn_certificate_id.label": "白山云 CDN 原证书 ID(可选)", "workflow_node.deploy.form.baishan_cdn_certificate_id.placeholder": "请输入白山云 CDN 原证书 ID", "workflow_node.deploy.form.baishan_cdn_certificate_id.tooltip": "这是什么?请参阅 https://cdnx.console.baishan.com/#/cdn/cert

          不填写时,将上传新证书;否则,将替换原证书。", - "workflow_node.deploy.form.baotapanel_console_auto_restart.label": "部署后自动重启面板服务", + "workflow_node.deploy.form.baotapanel_console_auto_restart.label": "部署后自动重启 1Panel 服务", "workflow_node.deploy.form.baotapanel_site_type.label": "宝塔面板网站类型", "workflow_node.deploy.form.baotapanel_site_type.placeholder": "请选择宝塔面板网站类型", "workflow_node.deploy.form.baotapanel_site_type.option.php.label": "PHP", @@ -318,9 +332,9 @@ "workflow_node.deploy.form.bunny_cdn_pull_zone_id.label": "Bunny CDN 拉取区域 ID", "workflow_node.deploy.form.bunny_cdn_pull_zone_id.placeholder": "请输入 Bunny CDN 拉取区域 ID", "workflow_node.deploy.form.bunny_cdn_pull_zone_id.tooltip": "这是什么?请参阅 https://dash.bunny.net/cdn", - "workflow_node.deploy.form.bunny_cdn_host_name.label": "Bunny CDN 主机名", - "workflow_node.deploy.form.bunny_cdn_host_name.placeholder": "请输入 Bunny CDN 主机名", - "workflow_node.deploy.form.bunny_cdn_host_name.tooltip": "这是什么?请参阅 https://dash.bunny.net/cdn", + "workflow_node.deploy.form.bunny_cdn_hostname.label": "Bunny CDN 主机名", + "workflow_node.deploy.form.bunny_cdn_hostname.placeholder": "请输入 Bunny CDN 主机名", + "workflow_node.deploy.form.bunny_cdn_hostname.tooltip": "这是什么?请参阅 https://dash.bunny.net/cdn", "workflow_node.deploy.form.byteplus_cdn_domain.label": "BytePlus CDN 域名", "workflow_node.deploy.form.byteplus_cdn_domain.placeholder": "请输入 BytePlus CDN 域名(支持泛域名)", "workflow_node.deploy.form.byteplus_cdn_domain.tooltip": "这是什么?请参阅 https://console.byteplus.com/cdn", @@ -341,6 +355,11 @@ "workflow_node.deploy.form.gcore_cdn_resource_id.label": "Gcore CDN 资源 ID", "workflow_node.deploy.form.gcore_cdn_resource_id.placeholder": "请输入 Gcore CDN 资源 ID", "workflow_node.deploy.form.gcore_cdn_resource_id.tooltip": "这是什么?请参阅 https://cdn.gcore.com/resources/list", + "workflow_node.deploy.form.goedge_resource_type.label": "证书替换方式", + "workflow_node.deploy.form.goedge_resource_type.placeholder": "请选择证书替换方式", + "workflow_node.deploy.form.goedge_resource_type.option.certificate.label": "替换指定证书", + "workflow_node.deploy.form.goedge_certificate_id.label": "GoEdge 证书 ID", + "workflow_node.deploy.form.goedge_certificate_id.placeholder": "请输入 GoEdge 证书 ID", "workflow_node.deploy.form.huaweicloud_cdn_region.label": "华为云 CDN 服务区域", "workflow_node.deploy.form.huaweicloud_cdn_region.placeholder": "请输入华为云 CDN 服务区域(例如:cn-north-1)", "workflow_node.deploy.form.huaweicloud_cdn_region.tooltip": "这是什么?请参阅 https://console.huaweicloud.com/apiexplorer/#/endpoint", @@ -451,11 +470,15 @@ "workflow_node.deploy.form.local_post_command.label": "后置命令(可选)", "workflow_node.deploy.form.local_post_command.placeholder": "请输入保存文件后执行的命令", "workflow_node.deploy.form.local_preset_scripts.button": "使用预设脚本", - "workflow_node.deploy.form.local_preset_scripts.option.backup_files.label": "POSIX Bash - 备份原证书文件", - "workflow_node.deploy.form.local_preset_scripts.option.reload_nginx.label": "POSIX Bash - 重启 nginx 进程", - "workflow_node.deploy.form.local_preset_scripts.option.binding_iis.label": "PowerShell - 导入并绑定到 IIS(需管理员权限)", - "workflow_node.deploy.form.local_preset_scripts.option.binding_netsh.label": "PowerShell - 导入并绑定到 netsh(需管理员权限)", - "workflow_node.deploy.form.local_preset_scripts.option.binding_rdp.label": "PowerShell - 导入并绑定到 远程桌面连接(需管理员权限)", + "workflow_node.deploy.form.local_preset_scripts.option.sh_backup_files.label": "POSIX Bash - 备份原证书文件", + "workflow_node.deploy.form.local_preset_scripts.option.ps_backup_files.label": "PowerShell - 备份原证书文件", + "workflow_node.deploy.form.local_preset_scripts.option.sh_reload_nginx.label": "POSIX Bash - 重启 nginx 进程", + "workflow_node.deploy.form.local_preset_scripts.option.ps_binding_iis.label": "PowerShell - 导入并绑定到 IIS", + "workflow_node.deploy.form.local_preset_scripts.option.ps_binding_netsh.label": "PowerShell - 导入并绑定到 netsh", + "workflow_node.deploy.form.local_preset_scripts.option.ps_binding_rdp.label": "PowerShell - 导入并绑定到 RDP", + "workflow_node.deploy.form.proxmoxve_node_name.label": "Proxmox VE 集群节点名称", + "workflow_node.deploy.form.proxmoxve_node_name.placeholder": "请输入 Proxmox VE 集群节点名称", + "workflow_node.deploy.form.proxmoxve_auto_restart.label": "部署后自动重启 Proxmox VE 服务", "workflow_node.deploy.form.qiniu_cdn_domain.label": "七牛云 CDN 加速域名", "workflow_node.deploy.form.qiniu_cdn_domain.placeholder": "请输入七牛云 CDN 加速域名(支持泛域名)", "workflow_node.deploy.form.qiniu_cdn_domain.tooltip": "这是什么?请参阅 https://portal.qiniu.com/cdn", @@ -509,8 +532,12 @@ "workflow_node.deploy.form.ssh_post_command.label": "后置命令(可选)", "workflow_node.deploy.form.ssh_post_command.placeholder": "请输入保存文件后执行的命令", "workflow_node.deploy.form.ssh_preset_scripts.button": "使用预设脚本", - "workflow_node.deploy.form.ssh_preset_scripts.option.backup_files.label": "POSIX Bash - 备份原证书文件", - "workflow_node.deploy.form.ssh_preset_scripts.option.reload_nginx.label": "POSIX Bash - 重启 nginx 进程", + "workflow_node.deploy.form.ssh_preset_scripts.option.sh_backup_files.label": "POSIX Bash - 备份原证书文件", + "workflow_node.deploy.form.ssh_preset_scripts.option.ps_backup_files.label": "PowerShell - 备份原证书文件", + "workflow_node.deploy.form.ssh_preset_scripts.option.sh_reload_nginx.label": "POSIX Bash - 重启 nginx 进程", + "workflow_node.deploy.form.ssh_preset_scripts.option.ps_binding_iis.label": "PowerShell - 导入并绑定到 IIS", + "workflow_node.deploy.form.ssh_preset_scripts.option.ps_binding_netsh.label": "PowerShell - 导入并绑定到 netsh", + "workflow_node.deploy.form.ssh_preset_scripts.option.ps_binding_rdp.label": "PowerShell - 导入并绑定到 RDP", "workflow_node.deploy.form.ssh_use_scp.label": "回退使用 SCP", "workflow_node.deploy.form.ssh_use_scp.tooltip": "如果你的远程服务器不支持 SFTP,请开启此选项回退为 SCP。", "workflow_node.deploy.form.tencentcloud_cdn_domain.label": "腾讯云 CDN 加速域名", @@ -684,15 +711,15 @@ "workflow_node.deploy.form.wangsu_cdnpro_webhook_id.label": "网宿云 CDN Pro 部署任务 Webhook ID(可选)", "workflow_node.deploy.form.wangsu_cdnpro_webhook_id.placeholder": "请输入网宿云 CDN Pro 部署任务 Webhook ID", "workflow_node.deploy.form.wangsu_cdnpro_webhook_id.tooltip": "这是什么?请参阅 https://cdnpro.console.wangsu.com/v2/index/#/certificate", - "workflow_node.deploy.form.webhook_data.label": "Webhook 回调数据(JSON 格式)", + "workflow_node.deploy.form.webhook_data.label": "Webhook 回调数据(可选)", "workflow_node.deploy.form.webhook_data.placeholder": "请输入 Webhook 回调数据", - "workflow_node.deploy.form.webhook_data.guide": "小贴士:回调数据是一个 JSON 格式的键值对。其中值支持模板变量,将在被发送到指定的 Webhook URL 时被替换为实际值;其他内容将保持原样。

          支持的变量:
          ${DOMAIN}:证书的主域名(即 CommonName
          ${DOMAINS}:证书的多域名列表(即 SubjectAltNames
          ${CERTIFICATE}:证书文件 PEM 格式内容
          ${PRIVATE_KEY}:私钥文件 PEM 格式内容", + "workflow_node.deploy.form.webhook_data.tooltip": "不填写时,将使用所选部署目标授权的默认 Webhook 回调数据。", + "workflow_node.deploy.form.webhook_data.guide": "支持的变量:
          1. ${DOMAIN}:证书的主域名(即 CommonName)。
          2. ${DOMAINS}:证书的多域名列表(即 SubjectAltNames)。
          3. ${CERTIFICATE}:证书文件 PEM 格式内容。
          4. ${PRIVATE_KEY}:私钥文件 PEM 格式内容。

          其他注意事项请前往授权管理页面查看。", "workflow_node.deploy.form.webhook_data.errmsg.json_invalid": "请输入有效的 JSON 格式字符串", - "workflow_node.deploy.form.webhook_data_preset.button": "使用预设模板", "workflow_node.deploy.form.strategy_config.label": "执行策略", "workflow_node.deploy.form.skip_on_last_succeeded.label": "重复部署", - "workflow_node.deploy.form.skip_on_last_succeeded.prefix": "当上次部署相同证书成功时,", - "workflow_node.deploy.form.skip_on_last_succeeded.suffix": "重新部署。", + "workflow_node.deploy.form.skip_on_last_succeeded.prefix": "当上次部署相同证书成功时,再次执行工作流时", + "workflow_node.deploy.form.skip_on_last_succeeded.suffix": "此部署节点。", "workflow_node.deploy.form.skip_on_last_succeeded.switch.on": "跳过", "workflow_node.deploy.form.skip_on_last_succeeded.switch.off": "不跳过", @@ -711,9 +738,32 @@ "workflow_node.notify.form.subject.placeholder": "请输入通知主题", "workflow_node.notify.form.message.label": "通知内容", "workflow_node.notify.form.message.placeholder": "请输入通知内容", - "workflow_node.notify.form.channel.label": "通知渠道", + "workflow_node.notify.form.channel.label": "通知渠道(已废弃,请使用「通知渠道授权」字段)", "workflow_node.notify.form.channel.placeholder": "请选择通知渠道", - "workflow_node.notify.form.channel.button": "去配置", + "workflow_node.notify.form.channel.button": "设置", + "workflow_node.notify.form.provider.label": "通知渠道", + "workflow_node.notify.form.provider.placeholder": "请选择通知渠道", + "workflow_node.notify.form.provider_access.label": "通知渠道授权", + "workflow_node.notify.form.provider_access.placeholder": "请选择通知渠道授权", + "workflow_node.notify.form.provider_access.button": "新建", + "workflow_node.notify.form.params_config.label": "参数设置", + "workflow_node.notify.form.email_sender_address.label": "发送邮箱地址(可选)", + "workflow_node.notify.form.email_sender_address.placeholder": "请输入发送邮箱地址以覆盖默认值", + "workflow_node.notify.form.email_sender_address.tooltip": "不填写时,将使用所选通知渠道授权的默认发送邮箱地址。", + "workflow_node.notify.form.email_receiver_address.label": "接收邮箱地址(可选)", + "workflow_node.notify.form.email_receiver_address.placeholder": "请输入接收邮箱地址以覆盖默认值", + "workflow_node.notify.form.email_receiver_address.tooltip": "不填写时,将使用所选通知渠道授权的默认接收邮箱地址。", + "workflow_node.notify.form.mattermost_channel_id.label": "Mattermost 频道 ID(可选)", + "workflow_node.notify.form.mattermost_channel_id.placeholder": "请输入 Mattermost 频道 ID 以覆盖默认值", + "workflow_node.notify.form.mattermost_channel_id.tooltip": "不填写时,将使用所选通知渠道授权的默认频道 ID。", + "workflow_node.notify.form.telegram_chat_id.label": "Telegram 会话 ID(可选)", + "workflow_node.notify.form.telegram_chat_id.placeholder": "请输入 Telegram 会话 ID 以覆盖默认值", + "workflow_node.notify.form.telegram_chat_id.tooltip": "不填写时,将使用所选通知渠道授权的默认会话 ID。", + "workflow_node.notify.form.webhook_data.label": "Webhook 回调数据(可选)", + "workflow_node.notify.form.webhook_data.placeholder": "请输入 Webhook 回调数据以覆盖默认值", + "workflow_node.notify.form.webhook_data.tooltip": "不填写时,将使用所选部署目标授权的默认 Webhook 回调数据。", + "workflow_node.notify.form.webhook_data.guide": "支持的变量:
          1. ${DOMAIN}:证书的主域名(即 CommonName)。
          2. ${DOMAINS}:证书的多域名列表(即 SubjectAltNames)。
          3. ${CERTIFICATE}:证书文件 PEM 格式内容。
          4. ${PRIVATE_KEY}:私钥文件 PEM 格式内容。

          其他注意事项请前往授权管理页面查看。", + "workflow_node.notify.form.webhook_data.errmsg.json_invalid": "请输入有效的 JSON 格式字符串", "workflow_node.end.label": "结束", diff --git a/ui/src/pages/accesses/AccessList.tsx b/ui/src/pages/accesses/AccessList.tsx index 0dd56aac..f815812e 100644 --- a/ui/src/pages/accesses/AccessList.tsx +++ b/ui/src/pages/accesses/AccessList.tsx @@ -21,7 +21,7 @@ import { useZustandShallowSelector } from "@/hooks"; import { useAccessesStore } from "@/stores/access"; import { getErrMsg } from "@/utils/error"; -type AccessRanges = AccessEditDrawerProps["range"]; +type AccessUsageProp = AccessEditDrawerProps["usage"]; const AccessList = () => { const [searchParams] = useSearchParams(); @@ -87,7 +87,7 @@ const AccessList = () => { @@ -98,7 +98,7 @@ const AccessList = () => { @@ -126,7 +126,7 @@ const AccessList = () => { const [filters, setFilters] = useState>(() => { return { - range: "both-dns-hosting" satisfies AccessRanges, + usage: "both-dns-hosting" satisfies AccessUsageProp, keyword: searchParams.get("keyword"), }; }); @@ -160,13 +160,13 @@ const AccessList = () => { }) .filter((e) => { const provider = accessProvidersMap.get(e.provider); - switch (filters["range"] as AccessRanges) { + switch (filters["usage"] as AccessUsageProp) { case "both-dns-hosting": - return provider?.usages?.includes(ACCESS_USAGES.DNS) || provider?.usages?.includes(ACCESS_USAGES.HOSTING); + return !e.reserve && (provider?.usages?.includes(ACCESS_USAGES.DNS) || provider?.usages?.includes(ACCESS_USAGES.HOSTING)); case "ca-only": - return provider?.usages?.includes(ACCESS_USAGES.CA); - case "notify-only": - return provider?.usages?.includes(ACCESS_USAGES.NOTIFICATION); + return e.reserve === "ca" && provider?.usages?.includes(ACCESS_USAGES.CA); + case "notification-only": + return e.reserve === "notification" && provider?.usages?.includes(ACCESS_USAGES.NOTIFICATION); } }); return Promise.resolve({ @@ -184,11 +184,13 @@ const AccessList = () => { ); const handleTabChange = (key: string) => { - setFilters((prev) => ({ ...prev, range: key })); + setFilters((prev) => ({ ...prev, usage: key })); + setPage(1); }; const handleSearch = (value: string) => { setFilters((prev) => ({ ...prev, keyword: value })); + setPage(1); }; const handleReloadClick = () => { @@ -224,7 +226,7 @@ const AccessList = () => { extra={[ }> @@ -245,18 +247,18 @@ const AccessList = () => { tabList={[ { key: "both-dns-hosting", - label: t("access.props.range.both_dns_hosting"), + label: t("access.props.usage.both_dns_hosting"), }, { key: "ca-only", - label: t("access.props.range.ca_only"), + label: t("access.props.usage.ca_only"), + }, + { + key: "notification-only", + label: t("access.props.usage.notification_only"), }, - // { - // key: "notify-only", - // label: t("access.props.range.notify_only"), - // }, ]} - activeTabKey={filters["range"] as string} + activeTabKey={filters["usage"] as string} onTabChange={(key) => handleTabChange(key)} /> diff --git a/ui/src/pages/certificates/CertificateList.tsx b/ui/src/pages/certificates/CertificateList.tsx index 049069a3..6e28459d 100644 --- a/ui/src/pages/certificates/CertificateList.tsx +++ b/ui/src/pages/certificates/CertificateList.tsx @@ -251,6 +251,7 @@ const CertificateList = () => { const handleSearch = (value: string) => { setFilters((prev) => ({ ...prev, keyword: value.trim() })); + setPage(1); }; const handleReloadClick = () => { diff --git a/ui/src/pages/dashboard/Dashboard.tsx b/ui/src/pages/dashboard/Dashboard.tsx index 919b53d3..9915a8a7 100644 --- a/ui/src/pages/dashboard/Dashboard.tsx +++ b/ui/src/pages/dashboard/Dashboard.tsx @@ -310,7 +310,7 @@ const StatisticCard = ({ onClick?: () => void; }) => { return ( - + {icon} { const { t } = useTranslation(); @@ -22,6 +25,7 @@ const SettingsNotification = () => { +
diff --git a/ui/src/pages/settings/SettingsSSLProvider.tsx b/ui/src/pages/settings/SettingsSSLProvider.tsx index f23c2024..2be6162f 100644 --- a/ui/src/pages/settings/SettingsSSLProvider.tsx +++ b/ui/src/pages/settings/SettingsSSLProvider.tsx @@ -7,7 +7,7 @@ import { produce } from "immer"; import { z } from "zod"; import Show from "@/components/Show"; -import { APPLY_CA_PROVIDERS, type ApplyCAProviderType } from "@/domain/provider"; +import { type CAProviderType, CA_PROVIDERS } from "@/domain/provider"; import { SETTINGS_NAMES, type SSLProviderSettingsContent, type SettingsModel } from "@/domain/settings"; import { useAntdForm } from "@/hooks"; import { get as getSettings, save as saveSettings } from "@/repository/settings"; @@ -27,14 +27,14 @@ const SSLProviderEditFormLetsEncryptConfig = () => { const { pending, settings, updateSettings } = useContext(SSLProviderContext); const { form: formInst, formProps } = useAntdForm>({ - initialValues: settings?.content?.config?.[APPLY_CA_PROVIDERS.LETSENCRYPT], + initialValues: settings?.content?.config?.[CA_PROVIDERS.LETSENCRYPT], onSubmit: async (values) => { const newSettings = produce(settings, (draft) => { draft.content ??= {} as SSLProviderSettingsContent; - draft.content.provider = APPLY_CA_PROVIDERS.LETSENCRYPT; + draft.content.provider = CA_PROVIDERS.LETSENCRYPT; draft.content.config ??= {} as SSLProviderSettingsContent["config"]; - draft.content.config[APPLY_CA_PROVIDERS.LETSENCRYPT] = values; + draft.content.config[CA_PROVIDERS.LETSENCRYPT] = values; }); await updateSettings(newSettings); @@ -44,7 +44,7 @@ const SSLProviderEditFormLetsEncryptConfig = () => { const [formChanged, setFormChanged] = useState(false); useEffect(() => { - setFormChanged(settings?.content?.provider !== APPLY_CA_PROVIDERS.LETSENCRYPT); + setFormChanged(settings?.content?.provider !== CA_PROVIDERS.LETSENCRYPT); }, [settings?.content?.provider]); const handleFormChange = () => { @@ -68,14 +68,14 @@ const SSLProviderEditFormLetsEncryptStagingConfig = () => { const { pending, settings, updateSettings } = useContext(SSLProviderContext); const { form: formInst, formProps } = useAntdForm>({ - initialValues: settings?.content?.config?.[APPLY_CA_PROVIDERS.LETSENCRYPTSTAGING], + initialValues: settings?.content?.config?.[CA_PROVIDERS.LETSENCRYPTSTAGING], onSubmit: async (values) => { const newSettings = produce(settings, (draft) => { draft.content ??= {} as SSLProviderSettingsContent; - draft.content.provider = APPLY_CA_PROVIDERS.LETSENCRYPTSTAGING; + draft.content.provider = CA_PROVIDERS.LETSENCRYPTSTAGING; draft.content.config ??= {} as SSLProviderSettingsContent["config"]; - draft.content.config[APPLY_CA_PROVIDERS.LETSENCRYPTSTAGING] = values; + draft.content.config[CA_PROVIDERS.LETSENCRYPTSTAGING] = values; }); await updateSettings(newSettings); @@ -85,7 +85,7 @@ const SSLProviderEditFormLetsEncryptStagingConfig = () => { const [formChanged, setFormChanged] = useState(false); useEffect(() => { - setFormChanged(settings?.content?.provider !== APPLY_CA_PROVIDERS.LETSENCRYPTSTAGING); + setFormChanged(settings?.content?.provider !== CA_PROVIDERS.LETSENCRYPTSTAGING); }, [settings?.content?.provider]); const handleFormChange = () => { @@ -113,14 +113,14 @@ const SSLProviderEditFormBuypassConfig = () => { const { pending, settings, updateSettings } = useContext(SSLProviderContext); const { form: formInst, formProps } = useAntdForm>({ - initialValues: settings?.content?.config?.[APPLY_CA_PROVIDERS.BUYPASS], + initialValues: settings?.content?.config?.[CA_PROVIDERS.BUYPASS], onSubmit: async (values) => { const newSettings = produce(settings, (draft) => { draft.content ??= {} as SSLProviderSettingsContent; - draft.content.provider = APPLY_CA_PROVIDERS.BUYPASS; + draft.content.provider = CA_PROVIDERS.BUYPASS; draft.content.config ??= {} as SSLProviderSettingsContent["config"]; - draft.content.config[APPLY_CA_PROVIDERS.BUYPASS] = values; + draft.content.config[CA_PROVIDERS.BUYPASS] = values; }); await updateSettings(newSettings); @@ -130,7 +130,7 @@ const SSLProviderEditFormBuypassConfig = () => { const [formChanged, setFormChanged] = useState(false); useEffect(() => { - setFormChanged(settings?.content?.provider !== APPLY_CA_PROVIDERS.LETSENCRYPTSTAGING); + setFormChanged(settings?.content?.provider !== CA_PROVIDERS.LETSENCRYPTSTAGING); }, [settings?.content?.provider]); const handleFormChange = () => { @@ -165,14 +165,14 @@ const SSLProviderEditFormGoogleTrustServicesConfig = () => { }); const formRule = createSchemaFieldRule(formSchema); const { form: formInst, formProps } = useAntdForm>({ - initialValues: settings?.content?.config?.[APPLY_CA_PROVIDERS.GOOGLETRUSTSERVICES], + initialValues: settings?.content?.config?.[CA_PROVIDERS.GOOGLETRUSTSERVICES], onSubmit: async (values) => { const newSettings = produce(settings, (draft) => { draft.content ??= {} as SSLProviderSettingsContent; - draft.content.provider = APPLY_CA_PROVIDERS.GOOGLETRUSTSERVICES; + draft.content.provider = CA_PROVIDERS.GOOGLETRUSTSERVICES; draft.content.config ??= {} as SSLProviderSettingsContent["config"]; - draft.content.config[APPLY_CA_PROVIDERS.GOOGLETRUSTSERVICES] = values; + draft.content.config[CA_PROVIDERS.GOOGLETRUSTSERVICES] = values; }); await updateSettings(newSettings); @@ -182,7 +182,7 @@ const SSLProviderEditFormGoogleTrustServicesConfig = () => { const [formChanged, setFormChanged] = useState(false); useEffect(() => { - setFormChanged(settings?.content?.provider !== APPLY_CA_PROVIDERS.GOOGLETRUSTSERVICES); + setFormChanged(settings?.content?.provider !== CA_PROVIDERS.GOOGLETRUSTSERVICES); }, [settings?.content?.provider]); const handleFormChange = () => { @@ -235,14 +235,14 @@ const SSLProviderEditFormSSLComConfig = () => { }); const formRule = createSchemaFieldRule(formSchema); const { form: formInst, formProps } = useAntdForm>({ - initialValues: settings?.content?.config?.[APPLY_CA_PROVIDERS.SSLCOM], + initialValues: settings?.content?.config?.[CA_PROVIDERS.SSLCOM], onSubmit: async (values) => { const newSettings = produce(settings, (draft) => { draft.content ??= {} as SSLProviderSettingsContent; - draft.content.provider = APPLY_CA_PROVIDERS.SSLCOM; + draft.content.provider = CA_PROVIDERS.SSLCOM; draft.content.config ??= {} as SSLProviderSettingsContent["config"]; - draft.content.config[APPLY_CA_PROVIDERS.SSLCOM] = values; + draft.content.config[CA_PROVIDERS.SSLCOM] = values; }); await updateSettings(newSettings); @@ -252,7 +252,7 @@ const SSLProviderEditFormSSLComConfig = () => { const [formChanged, setFormChanged] = useState(false); useEffect(() => { - setFormChanged(settings?.content?.provider !== APPLY_CA_PROVIDERS.SSLCOM); + setFormChanged(settings?.content?.provider !== CA_PROVIDERS.SSLCOM); }, [settings?.content?.provider]); const handleFormChange = () => { @@ -305,14 +305,14 @@ const SSLProviderEditFormZeroSSLConfig = () => { }); const formRule = createSchemaFieldRule(formSchema); const { form: formInst, formProps } = useAntdForm>({ - initialValues: settings?.content?.config?.[APPLY_CA_PROVIDERS.ZEROSSL], + initialValues: settings?.content?.config?.[CA_PROVIDERS.ZEROSSL], onSubmit: async (values) => { const newSettings = produce(settings, (draft) => { draft.content ??= {} as SSLProviderSettingsContent; - draft.content.provider = APPLY_CA_PROVIDERS.ZEROSSL; + draft.content.provider = CA_PROVIDERS.ZEROSSL; draft.content.config ??= {} as SSLProviderSettingsContent["config"]; - draft.content.config[APPLY_CA_PROVIDERS.ZEROSSL] = values; + draft.content.config[CA_PROVIDERS.ZEROSSL] = values; }); await updateSettings(newSettings); @@ -322,7 +322,7 @@ const SSLProviderEditFormZeroSSLConfig = () => { const [formChanged, setFormChanged] = useState(false); useEffect(() => { - setFormChanged(settings?.content?.provider !== APPLY_CA_PROVIDERS.ZEROSSL); + setFormChanged(settings?.content?.provider !== CA_PROVIDERS.ZEROSSL); }, [settings?.content?.provider]); const handleFormChange = () => { @@ -383,20 +383,20 @@ const SettingsSSLProvider = () => { fetchData(); }, []); - const [providerType, setProviderType] = useState(APPLY_CA_PROVIDERS.LETSENCRYPT); + const [providerType, setProviderType] = useState(CA_PROVIDERS.LETSENCRYPT); const providerFormEl = useMemo(() => { switch (providerType) { - case APPLY_CA_PROVIDERS.LETSENCRYPT: + case CA_PROVIDERS.LETSENCRYPT: return ; - case APPLY_CA_PROVIDERS.LETSENCRYPTSTAGING: + case CA_PROVIDERS.LETSENCRYPTSTAGING: return ; - case APPLY_CA_PROVIDERS.BUYPASS: + case CA_PROVIDERS.BUYPASS: return ; - case APPLY_CA_PROVIDERS.GOOGLETRUSTSERVICES: + case CA_PROVIDERS.GOOGLETRUSTSERVICES: return ; - case APPLY_CA_PROVIDERS.SSLCOM: + case CA_PROVIDERS.SSLCOM: return ; - case APPLY_CA_PROVIDERS.ZEROSSL: + case CA_PROVIDERS.ZEROSSL: return ; } }, [providerType]); @@ -431,48 +431,48 @@ const SettingsSSLProvider = () => { }>
- setProviderType(value as ApplyCAProviderType)}> + setProviderType(value as CAProviderType)}> } size="small" title={t("provider.letsencrypt")} description="letsencrypt.org" - value={APPLY_CA_PROVIDERS.LETSENCRYPT} + value={CA_PROVIDERS.LETSENCRYPT} /> } size="small" title={t("provider.letsencryptstaging")} description="letsencrypt.org" - value={APPLY_CA_PROVIDERS.LETSENCRYPTSTAGING} + value={CA_PROVIDERS.LETSENCRYPTSTAGING} /> } size="small" title={t("provider.buypass")} description="buypass.com" - value={APPLY_CA_PROVIDERS.BUYPASS} + value={CA_PROVIDERS.BUYPASS} /> } size="small" title={t("provider.googletrustservices")} description="pki.goog" - value={APPLY_CA_PROVIDERS.GOOGLETRUSTSERVICES} + value={CA_PROVIDERS.GOOGLETRUSTSERVICES} /> } size="small" title={t("provider.sslcom")} description="ssl.com" - value={APPLY_CA_PROVIDERS.SSLCOM} + value={CA_PROVIDERS.SSLCOM} /> } size="small" title={t("provider.zerossl")} description="zerossl.com" - value={APPLY_CA_PROVIDERS.ZEROSSL} + value={CA_PROVIDERS.ZEROSSL} /> diff --git a/ui/src/pages/workflows/WorkflowList.tsx b/ui/src/pages/workflows/WorkflowList.tsx index 09bca7fc..f7a350fd 100644 --- a/ui/src/pages/workflows/WorkflowList.tsx +++ b/ui/src/pages/workflows/WorkflowList.tsx @@ -281,6 +281,7 @@ const WorkflowList = () => { const handleSearch = (value: string) => { setFilters((prev) => ({ ...prev, keyword: value.trim() })); + setPage(1); }; const handleCreateClick = () => { diff --git a/ui/src/stores/notify/index.ts b/ui/src/stores/notify/index.ts index c8f0356f..d144aff4 100644 --- a/ui/src/stores/notify/index.ts +++ b/ui/src/stores/notify/index.ts @@ -4,6 +4,9 @@ import { create } from "zustand"; import { type NotifyChannelsSettingsContent, SETTINGS_NAMES, type SettingsModel } from "@/domain/settings"; import { get as getSettings, save as saveSettings } from "@/repository/settings"; +/** + * @deprecated + */ export interface NotifyChannelsState { channels: NotifyChannelsSettingsContent; loading: boolean; @@ -14,6 +17,9 @@ export interface NotifyChannelsState { setChannels: (channels: NotifyChannelsSettingsContent) => Promise; } +/** + * @deprecated + */ export const useNotifyChannelsStore = create((set, get) => { let fetcher: Promise> | null = null; // 防止多次重复请求 let settings: SettingsModel; // 记录当前设置的其他字段,保存回数据库时用