diff --git a/README.md b/README.md
index 6f90fb32..0899200e 100644
--- a/README.md
+++ b/README.md
@@ -90,17 +90,23 @@ make local.run
| :----------------------------------------------------------------- | :-------------------------------------- |
| [阿里云](https://www.aliyun.com/) | |
| [腾讯云](https://cloud.tencent.com/) | |
+| [百度智能云](https://cloud.baidu.com/) | |
| [华为云](https://www.huaweicloud.com/) | |
| [火山引擎](https://www.volcengine.com/) | |
+| [京东云](https://www.jdcloud.com/) | |
| [AWS Route53](https://aws.amazon.com/route53/) | |
| [Azure](https://azure.microsoft.com/) | |
| [CloudFlare](https://www.cloudflare.com/) | |
-| [ClouDNS](https://www.cloudns.net//) | |
+| [ClouDNS](https://www.cloudns.net/) | |
+| [DNS.LA](https://www.dns.la/) | |
+| [Gcore](https://gcore.com/) | |
| [GNAME](https://www.gname.com/) | |
| [GoDaddy](https://www.godaddy.com/) | |
| [Name.com](https://www.name.com/) | |
+| [Namecheap](https://www.namecheap.com/) | |
| [NameSilo](https://www.namesilo.com/) | |
| [IBM NS1 Connect](https://www.ibm.com/cn-zh/products/ns1-connect/) | |
+| [移动云](https://ecloud.10086.cn/) | |
| [雨云](https://www.rainyun.com/) | |
| [西部数码](https://www.west.cn/) | |
| [PowerDNS](https://www.powerdns.com/) | |
@@ -116,24 +122,30 @@ make local.run
[展开查看]
-| 提供商 | 备注 |
-| :-------------------------------------- | :----------------------------------------------------------------------- |
-| 本地部署 | 可部署到本地服务器 |
-| SSH 部署 | 可部署到远程服务器(通过 SSH+SFTP/SCP) |
-| Webhook 回调 | 可部署到 Webhook |
-| [Kubernetes](https://kubernetes.io/) | 可部署到 Kubernetes Secret |
-| [阿里云](https://www.aliyun.com/) | 可部署到阿里云 OSS、CDN、DCDN、ESA、SLB(CLB/ALB/NLB)、WAF、Live 等服务 |
-| [腾讯云](https://cloud.tencent.com/) | 可部署到腾讯云 COS、CDN、ECDN、EdgeOne、CLB、CSS 等服务 |
-| [百度智能云](https://cloud.baidu.com/) | 可部署到百度智能云 CDN 等服务 |
-| [华为云](https://www.huaweicloud.com/) | 可部署到华为云 CDN、ELB 等服务 |
-| [火山引擎](https://www.volcengine.com/) | 可部署到火山引擎 TOS、CDN、DCDN、CLB、Live 等服务 |
-| [七牛云](https://www.qiniu.com/) | 可部署到七牛云 CDN、直播云等服务 |
-| [多吉云](https://www.dogecloud.com/) | 可部署到多吉云 CDN |
-| [优刻得](https://www.ucloud.cn/) | 可部署到优刻得 US3、UCDN 等服务 |
-| [宝塔面板](https://www.bt.cn/) | 可部署到宝塔面板 |
-| [AWS](https://aws.amazon.com/) | 可部署到 AWS CloudFront 等服务 |
-| [BytePlus](https://www.byteplus.com/) | 可部署到 BytePlus CDN 等服务 |
-| [Edgio](https://edg.io/) | 可部署到 Edgio Applications 等服务 |
+| 提供商 | 备注 |
+| :-------------------------------------- | :---------------------------------------------------------------------------- |
+| 本地部署 | 可部署到本地服务器 |
+| SSH 部署 | 可部署到远程服务器(通过 SSH+SFTP/SCP) |
+| Webhook 回调 | 可部署到 Webhook |
+| [Kubernetes](https://kubernetes.io/) | 可部署到 Kubernetes Secret |
+| [阿里云](https://www.aliyun.com/) | 可部署到阿里云 OSS、CDN、DCDN、ESA、SLB(CLB/ALB/NLB)、WAF、Live、VOD 等服务 |
+| [腾讯云](https://cloud.tencent.com/) | 可部署到腾讯云 COS、CDN、ECDN、EdgeOne、CLB、WAF、CSS、VOD 等服务 |
+| [百度智能云](https://cloud.baidu.com/) | 可部署到百度智能云 CDN 等服务 |
+| [华为云](https://www.huaweicloud.com/) | 可部署到华为云 CDN、ELB、WAF 等服务 |
+| [火山引擎](https://www.volcengine.com/) | 可部署到火山引擎 TOS、CDN、DCDN、CLB、ImageX、Live 等服务 |
+| [京东云](https://www.jdcloud.com/) | 可部署到京东云 CDN、ALB、视频直播、视频点播等服务 |
+| [七牛云](https://www.qiniu.com/) | 可部署到七牛云 CDN、直播云等服务 |
+| [白山云](https://www.baishan.com/) | 可部署到白山云 CDN |
+| [多吉云](https://www.dogecloud.com/) | 可部署到多吉云 CDN |
+| [优刻得](https://www.ucloud.cn/) | 可部署到优刻得 US3、UCDN 等服务 |
+| [雷池](https://waf-ce.chaitin.cn/) | 可部署到雷池 WAF |
+| [宝塔面板](https://www.bt.cn/) | 可部署到宝塔面板 |
+| [AWS](https://aws.amazon.com/) | 可部署到 AWS CloudFront |
+| [BytePlus](https://www.byteplus.com/) | 可部署到 BytePlus CDN |
+| [CacheFly](https://www.cachefly.com/) | 可部署到 CacheFly CDN |
+| [Cdnfly](https://www.cdnfly.cn/) | 可部署到 Cdnfly CDN |
+| [Edgio](https://edg.io/) | 可部署到 Edgio Applications |
+| [Gcore](https://gcore.com/) | 可部署到 Gcore CDN |
diff --git a/README_EN.md b/README_EN.md
index d5300b07..b92fc82a 100644
--- a/README_EN.md
+++ b/README_EN.md
@@ -89,17 +89,23 @@ The following DNS providers are supported:
| :----------------------------------------------------------- | :------------------------------------ |
| [Alibaba Cloud](https://www.alibabacloud.com/) | |
| [Tencent Cloud](https://www.tencentcloud.com/) | |
+| [Baidu AI Cloud](https://intl.cloud.baidu.com/) | |
| [Huawei Cloud](https://www.huaweicloud.com/) | |
| [Volcengine](https://www.volcengine.com/) | |
+| [JD Cloud](https://www.jdcloud.com/) | |
| [AWS Route53](https://aws.amazon.com/route53/) | |
| [Azure DNS](https://azure.microsoft.com/) | |
| [CloudFlare](https://www.cloudflare.com/) | |
-| [ClouDNS](https://www.cloudns.net//) | |
+| [ClouDNS](https://www.cloudns.net/) | |
+| [DNS.LA](https://www.dns.la/) | |
+| [Gcore](https://gcore.com/) | |
| [GNAME](https://www.gname.com/) | |
| [GoDaddy](https://www.godaddy.com/) | |
| [Name.com](https://www.name.com/) | |
+| [Namecheap](https://www.namecheap.com/) | |
| [NameSilo](https://www.namesilo.com/) | |
| [IBM NS1 Connect](https://www.ibm.com/products/ns1-connect/) | |
+| [CMCC Cloud](https://ecloud.10086.cn/) | |
| [Rain Yun](https://www.rainyun.com/) | |
| [West.cn](https://www.west.cn/) | |
| [PowerDNS](https://www.powerdns.com/) | |
@@ -115,24 +121,30 @@ The following hosting providers are supported:
[Fold/Unfold to view ...]
-| Provider | Remarks |
-| :---------------------------------------------- | :------------------------------------------------------------------------------- |
-| Local | Supports deployment to local servers |
-| SSH | Supports deployment to remote servers (via SSH+SFTP/SCP) |
-| Webhook | Supports deployment to Webhook |
-| [Kubernetes](https://kubernetes.io/) | Supports deployment to Kubernetes Secret |
-| [Alibaba Cloud](https://www.alibabacloud.com/) | Supports deployment to Alibaba Cloud OSS, CDN, DCDN, SLB(CLB/ALB/NLB), WAF, Live |
-| [Tencent Cloud](https://www.tencentcloud.com/) | Supports deployment to Tencent Cloud COS, CDN, ECDN, EdgeOne, CLB, CSS |
-| [Baidu AI Cloud](https://intl.cloud.baidu.com/) | Supports deployment to Baidu AI CLoud CDN |
-| [Huawei Cloud](https://www.huaweicloud.com/) | Supports deployment to Huawei Cloud CDN, ELB |
-| [Volcengine](https://www.volcengine.com/) | Supports deployment to Volcengine TOS, CDN, DCDN, CLB, Live |
-| [Qiniu Cloud](https://www.qiniu.com/) | Supports deployment to Qiniu Cloud CDN, Pili |
-| [Doge Cloud](https://www.dogecloud.com/) | Supports deployment to Doge Cloud CDN |
-| [BaoTa Panel](https://www.bt.cn/) | Supports deployment to BaoTa Panel sites |
-| [UCloud](https://www.ucloud-global.com/) | Supports deployment to UCloud US3, UCDN |
-| [AWS](https://aws.amazon.com/) | Supports deployment to AWS CloudFront |
-| [BytePlus](https://www.byteplus.com/) | Supports deployment to BytePlus CDN |
-| [Edgio](https://edg.io/) | Supports deployment to Edgio Applications |
+| Provider | Remarks |
+| :---------------------------------------------- | :------------------------------------------------------------------------------------ |
+| Local | Supports deployment to local servers |
+| SSH | Supports deployment to remote servers (via SSH+SFTP/SCP) |
+| Webhook | Supports deployment to Webhook |
+| [Kubernetes](https://kubernetes.io/) | Supports deployment to Kubernetes Secret |
+| [Alibaba Cloud](https://www.alibabacloud.com/) | Supports deployment to Alibaba Cloud OSS, CDN, DCDN, SLB(CLB/ALB/NLB), WAF, Live, VOD |
+| [Tencent Cloud](https://www.tencentcloud.com/) | Supports deployment to Tencent Cloud COS, CDN, ECDN, EdgeOne, CLB, WAF, CSS, VOD |
+| [Baidu AI Cloud](https://intl.cloud.baidu.com/) | Supports deployment to Baidu AI CLoud CDN |
+| [Huawei Cloud](https://www.huaweicloud.com/) | Supports deployment to Huawei Cloud CDN, ELB, WAF |
+| [Volcengine](https://www.volcengine.com/) | Supports deployment to Volcengine TOS, CDN, DCDN, CLB, ImageX, Live |
+| [JD Cloud](https://www.jdcloud.com/) | Supports deployment to JD Cloud CDN, ALB, Live Video, VOD |
+| [Qiniu Cloud](https://www.qiniu.com/) | Supports deployment to Qiniu Cloud CDN, Pili |
+| [Baishan Cloud](https://intl.baishancloud.com/) | Supports deployment to Baishan Cloud CDN |
+| [Doge Cloud](https://www.dogecloud.com/) | Supports deployment to Doge Cloud CDN |
+| [UCloud](https://www.ucloud-global.com/) | Supports deployment to UCloud US3, UCDN |
+| [SafeLine](https://waf.chaitin.com/) | Supports deployment to SafeLine WAF |
+| [BaoTa Panel](https://www.bt.cn/) | Supports deployment to BaoTa Panel sites |
+| [AWS](https://aws.amazon.com/) | Supports deployment to AWS CloudFront |
+| [BytePlus](https://www.byteplus.com/) | Supports deployment to BytePlus CDN |
+| [CacheFly](https://www.cachefly.com/) | Supports deployment to CacheFly CDN |
+| [Cdnfly](https://www.cdnfly.cn/) | Supports deployment to Cdnfly CDN |
+| [Edgio](https://edg.io/) | Supports deployment to Edgio Applications |
+| [Gcore](https://gcore.com/) | Supports deployment to Gcore CDN |
diff --git a/go.mod b/go.mod
index d3280f69..40efa5a4 100644
--- a/go.mod
+++ b/go.mod
@@ -19,12 +19,12 @@ require (
github.com/aliyun/aliyun-oss-go-sdk v3.0.2+incompatible
github.com/aws/aws-sdk-go-v2/service/acm v1.30.18
github.com/aws/aws-sdk-go-v2/service/cloudfront v1.44.10
- github.com/baidubce/bce-sdk-go v0.9.216
+ github.com/baidubce/bce-sdk-go v0.9.217
github.com/byteplus-sdk/byteplus-sdk-golang v1.0.41
- github.com/go-acme/lego/v4 v4.21.0
+ github.com/go-acme/lego/v4 v4.22.2
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.135
+ github.com/huaweicloud/huaweicloud-sdk-go-v3 v0.1.136
github.com/nikoksr/notify v1.3.0
github.com/pavlo-v-chernykh/keystore-go/v4 v4.5.0
github.com/pkg/sftp v1.13.7
@@ -34,13 +34,13 @@ require (
github.com/qiniu/go-sdk/v7 v7.25.2
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cdn v1.0.1096
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/clb v1.0.1096
- github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1096
+ github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1102
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/live v1.0.1096
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/ssl v1.0.1096
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/teo v1.0.1096
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.194
+ github.com/volcengine/volc-sdk-golang v1.0.195
github.com/volcengine/volcengine-go-sdk v1.0.180
golang.org/x/crypto v0.33.0
golang.org/x/exp v0.0.0-20250210185358-939b2ce775ac
@@ -57,11 +57,17 @@ require (
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.2 // indirect
+ github.com/G-Core/gcorelabscdn-go v1.0.26 // 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-rpc v1.1.3 // indirect
+ github.com/alibabacloud-go/tea-rpc-utils v1.1.0 // indirect
github.com/alibabacloud-go/tea-utils/v2 v2.0.7 // indirect
+ github.com/alibabacloud-go/vod-20170321 v1.0.1 // indirect
+ github.com/alibabacloud-go/vod-20170321/v4 v4.6.1 // 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/blinkbean/dingtalk v1.1.3 // indirect
github.com/emicklei/go-restful/v3 v3.12.1 // indirect
@@ -75,12 +81,14 @@ require (
github.com/go-playground/universal-translator v0.18.1 // indirect
github.com/go-playground/validator/v10 v10.16.0 // indirect
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/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/jdcloud-api/jdcloud-sdk-go v1.62.0 // 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
@@ -94,7 +102,11 @@ require (
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
github.com/sirupsen/logrus v1.9.3 // indirect
github.com/technoweenie/multipartstreamer v1.0.1 // indirect
+ github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/vod v1.0.1102 // indirect
+ github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/waf v1.0.1099 // indirect
github.com/x448/float16 v0.8.4 // indirect
+ gitlab.ecloud.com/ecloud/ecloudsdkclouddns v1.0.1 // indirect
+ gitlab.ecloud.com/ecloud/ecloudsdkcore v1.0.0 // indirect
go.mongodb.org/mongo-driver v1.17.2 // indirect
gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect
@@ -201,3 +213,7 @@ require (
modernc.org/memory v1.8.2 // indirect
modernc.org/sqlite v1.34.5 // indirect
)
+
+replace gitlab.ecloud.com/ecloud/ecloudsdkcore v1.0.0 => ./internal/pkg/vendors/cmcc-sdk/ecloudsdkcore@v1.0.0
+
+replace gitlab.ecloud.com/ecloud/ecloudsdkclouddns v1.0.1 => ./internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1
diff --git a/go.sum b/go.sum
index e9239294..d15c396f 100644
--- a/go.sum
+++ b/go.sum
@@ -79,6 +79,8 @@ 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/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.26 h1:22SqETUw64s+It/op1T7y3ukEOU62CJOsUcsfSkhvZs=
+github.com/G-Core/gcorelabscdn-go v1.0.26/go.mod h1:iSGXaTvZBzDHQW+rKFS918BgFVpONcyLEijwh8WsXpE=
github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.25.0 h1:3c8yed4lgqTt+oTQ+JNMDo+F4xprBf+O/il4ZC0nRLw=
github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.25.0/go.mod h1:obipzmGjfSjam60XLwGfqUkJsfiheAl+TUjG+4yzyPM=
github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.49.0 h1:o90wcURuxekmXrtxmYWTyNla0+ZEHhud6DI1ZTxd1vI=
@@ -169,6 +171,11 @@ github.com/alibabacloud-go/tea-oss-sdk v1.1.3 h1:EhAHI6edMeqgkZEqP7r4nc9iMWAUBKG
github.com/alibabacloud-go/tea-oss-sdk v1.1.3/go.mod h1:yUnodpR3Bf2rudLE7V/Gft5txjJF30Pk+hH77K/Eab0=
github.com/alibabacloud-go/tea-oss-utils v1.1.0 h1:y65crjjcZ2Pbb6UZtC2deuIZHDVTS3IaDWE7M9nVLRc=
github.com/alibabacloud-go/tea-oss-utils v1.1.0/go.mod h1:PFCF12e9yEKyBUIn7X1IrF/pNjvxgkHy0CgxX4+xRuY=
+github.com/alibabacloud-go/tea-rpc v1.1.3 h1:uuxAIT9PB6MMABQfV/EMSnREZjh629WXu+hmPNF1IAs=
+github.com/alibabacloud-go/tea-rpc v1.1.3/go.mod h1:uwhvnxPK69jcAYkVyP1WCFhTh1oVLiibUseSUpC7L8g=
+github.com/alibabacloud-go/tea-rpc-utils v1.1.0 h1:kIG7+9sMRaDzvCbXfowycEwFRdnLAglRFQ/dnc0/JNE=
+github.com/alibabacloud-go/tea-rpc-utils v1.1.0/go.mod h1:rxGY+fLbm3Fj3oJpeU0hBTmz52Ux50nm7JL01tyPv9c=
+github.com/alibabacloud-go/tea-utils v1.3.0/go.mod h1:EI/o33aBfj3hETm4RLiAxF/ThQdSngxrpF8rKUDJjPE=
github.com/alibabacloud-go/tea-utils v1.3.1/go.mod h1:EI/o33aBfj3hETm4RLiAxF/ThQdSngxrpF8rKUDJjPE=
github.com/alibabacloud-go/tea-utils v1.3.6/go.mod h1:EI/o33aBfj3hETm4RLiAxF/ThQdSngxrpF8rKUDJjPE=
github.com/alibabacloud-go/tea-utils v1.4.5 h1:h0/6Xd2f3bPE4XHTvkpjwxowIwRCJAJOqY6Eq8f3zfA=
@@ -184,12 +191,17 @@ 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 v1.0.1 h1:ZiBggVoJegu0Q3iarHZyveTOJJE0kUym6RCSLM9epoc=
+github.com/alibabacloud-go/vod-20170321 v1.0.1/go.mod h1:eKaYMCAd22pgBFMz0Ci/o2l+UJSrq24LLSF/XyaTiac=
+github.com/alibabacloud-go/vod-20170321/v4 v4.6.1 h1:6JTNq23lMo3wOui5qjpUJu2VKBgSHR4ArMgbKDOej7Q=
+github.com/alibabacloud-go/vod-20170321/v4 v4.6.1/go.mod h1:TkgLKMSLu0qZN8Qdcu8svfHREyI64kjFvrp/GhrD4VQ=
github.com/alibabacloud-go/waf-openapi-20211001/v5 v5.0.4 h1:Od0KgA73DyG9X2XFwuZZTkDv2pzA6B5mhYapyyca6QE=
github.com/alibabacloud-go/waf-openapi-20211001/v5 v5.0.4/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/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.0/go.mod h1:ZXrrxv386Mj6z8NpihLKpexQE550m7j3LlyCvYub9aE=
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=
@@ -205,6 +217,7 @@ github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgI
github.com/asaskevich/govalidator v0.0.0-20200108200545-475eaeb16496/go.mod h1:oGkLhpf+kjZl6xBf758TQhh5XrAeiJv/7FRz/2spLIg=
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 h1:DklsrG3dyBCFEj5IhUbnKptjxatkF07cF2ak3yi77so=
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw=
+github.com/avast/retry-go v3.0.0+incompatible h1:4SOWQ7Qs+oroOTQOYnAHqelpCO0biHSxpiH9JdtuBj0=
github.com/avast/retry-go v3.0.0+incompatible/go.mod h1:XtSnn+n/sHqQIpZ10K1qAevBhOOCWBLXXy3hyiqqBrY=
github.com/aws/aws-sdk-go v1.40.45/go.mod h1:585smgzpB/KqRA+K3y/NL/oYRqQvpNJYvLm+LY1U59Q=
github.com/aws/aws-sdk-go v1.55.5 h1:KKUZBfBoyqy5d3swXyiC7Q76ic40rYcbqH7qjh59kzU=
@@ -258,6 +271,8 @@ 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.216 h1:jRq4C1UGYcvHo6Gst2kuUzhWwJM6EqXCmhIsTKQvf4k=
github.com/baidubce/bce-sdk-go v0.9.216/go.mod h1:zbYJMQwE4IZuyrJiFO8tO8NbtYiKTFTbwh4eIsqjVdg=
+github.com/baidubce/bce-sdk-go v0.9.217 h1:dbMeVzpr9BGItTFHB1s2KSrpz0ayJC1y366VUMmaF0k=
+github.com/baidubce/bce-sdk-go v0.9.217/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=
@@ -361,6 +376,8 @@ github.com/ganigeorgiev/fexpr v0.4.1/go.mod h1:RyGiGqmeXhEQ6+mlGdnUleLHgtzzu/VGO
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/go-acme/lego/v4 v4.21.0 h1:arEW+8o5p7VI8Bk1kr/PDlgD1DrxtTH1gJ4b7mehL8o=
github.com/go-acme/lego/v4 v4.21.0/go.mod h1:HrSWzm3Ckj45Ie3i+p1zKVobbQoMOaGu9m4up0dUeDI=
+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-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=
@@ -422,6 +439,8 @@ 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/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=
+github.com/gofrs/uuid v4.4.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
@@ -557,6 +576,8 @@ github.com/hashicorp/serf v0.9.5/go.mod h1:UWDWwZeL5cuWDJdl0C6wrvrUwEqtQ4ZKBKKEN
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/huaweicloud/huaweicloud-sdk-go-v3 v0.1.135 h1:UbNMlPfh0GhRY3iVkvv4fXFJ+bLqXoVCwjqe6geFdPs=
github.com/huaweicloud/huaweicloud-sdk-go-v3 v0.1.135/go.mod h1:Y/+YLCFCJtS29i2MbYPTUlNNfwXvkzEsZKR0imY/2aY=
+github.com/huaweicloud/huaweicloud-sdk-go-v3 v0.1.136 h1:T785NUg5245nWpPVHLVR8lBd+zGQYR14Vi/TCX1iu3A=
+github.com/huaweicloud/huaweicloud-sdk-go-v3 v0.1.136/go.mod h1:Y/+YLCFCJtS29i2MbYPTUlNNfwXvkzEsZKR0imY/2aY=
github.com/hudl/fargo v1.4.0/go.mod h1:9Ai6uvFy5fQNq6VPKtg+Ceq1+eTY4nKUlR2JElEOcDo=
github.com/iancoleman/strcase v0.3.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho=
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
@@ -569,6 +590,8 @@ github.com/jcmturner/gofork v1.0.0/go.mod h1:MK8+TM0La+2rjBD4jE12Kj1pCCxK7d2LK/U
github.com/jcmturner/goidentity/v6 v6.0.1/go.mod h1:X1YW3bgtvwAXju7V3LCIMpY0Gbxyjn/mY9zx4tFonSg=
github.com/jcmturner/gokrb5/v8 v8.4.2/go.mod h1:sb+Xq/fTY5yktf/VxLsE3wlfPqQjp0aWNYyvBVK62bc=
github.com/jcmturner/rpc/v2 v2.0.3/go.mod h1:VUJYCIDm3PVOEHw8sgt091/20OJjskO/YJki3ELg/Hc=
+github.com/jdcloud-api/jdcloud-sdk-go v1.62.0 h1:uPfyOSY16mBrhggriDNeySFB4ZkzMMXpNac2P0fbDRw=
+github.com/jdcloud-api/jdcloud-sdk-go v1.62.0/go.mod h1:UrKjuULIWLjHFlG6aSPunArE5QX57LftMmStAZJBEX8=
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
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=
@@ -826,6 +849,10 @@ github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/clb v1.0.1096/go.mod h1
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.1096 h1:DMokC7T0UF8wMfT1kD+mX3M+hc2C06gmFvQ9gsfRPmI=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1096/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0=
+github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1099 h1:4fQ53ORk6Eayw1H2kg43PoBnUuhGR6WRG6rtec/i3oI=
+github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1099/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0=
+github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1102 h1:DxsNhw67OHyQME20IULmi8lgNY9MHuQ+qS1XH1/yTvM=
+github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1102/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.1096 h1:h9FP40Ycg45egJlZcjbLyc4IUeFoq+wSpR43sHMALtM=
@@ -834,6 +861,10 @@ github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/ssl v1.0.1096 h1:7ZmPus
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/ssl v1.0.1096/go.mod h1:aMpGcDskqqhXtfMaeo2egO61tgh/zt07L1ohSPwmjWk=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/teo v1.0.1096 h1:N62IFKL1ZRNQ7WPLNn8x9eYnwM4lOUIVY3buW6kbGtg=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/teo v1.0.1096/go.mod h1:4PZRRpZp+jvYBUbUajsoZREnk7sJXMnPAiGB4IX8IkM=
+github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/vod v1.0.1102 h1:B0mJk0ojVOFCMLrBoxLNVgrGih11EezTekRffkACCAY=
+github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/vod v1.0.1102/go.mod h1:0yyQ1r35jteb5DV4mcJZ5uh9NStWzjMYz9iSMnDMdJA=
+github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/waf v1.0.1099 h1:kD+8RKF0uJCr7VaurAUA11NNAoln0HaagMCgQV6EnUw=
+github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/waf v1.0.1099/go.mod h1:ellbjD8eHKHS4ixscLdiPJI8QoFIk0YNEgaDjxXMECM=
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=
@@ -850,6 +881,8 @@ github.com/volcengine/ve-tos-golang-sdk/v2 v2.7.9/go.mod h1:IrjK84IJJTuOZOTMv/P1
github.com/volcengine/volc-sdk-golang v1.0.23/go.mod h1:AfG/PZRUkHJ9inETvbjNifTDgut25Wbkm2QoYBTbvyU=
github.com/volcengine/volc-sdk-golang v1.0.194 h1:3o0INQzdtYJWvdGrtX02booCqPL5TsWSq2W1Ur7Bzlo=
github.com/volcengine/volc-sdk-golang v1.0.194/go.mod h1:u0VtPvlXWpXDTmc9IHkaW1q+5Jjwus4oAqRhNMDRInE=
+github.com/volcengine/volc-sdk-golang v1.0.195 h1:hKX4pBhmKcB3652BTdcAmtgizEPBnoQUpTM+j5blMA4=
+github.com/volcengine/volc-sdk-golang v1.0.195/go.mod h1:stZX+EPgv1vF4nZwOlEe8iGcriUPRBKX8zA19gXycOQ=
github.com/volcengine/volcengine-go-sdk v1.0.180 h1:lzcNlaxeGIUdXgDuVH7KJwZYZjIZzaCAYPDh91htU6U=
github.com/volcengine/volcengine-go-sdk v1.0.180/go.mod h1:gfEDc1s7SYaGoY+WH2dRrS3qiuDJMkwqyfXWCa7+7oA=
github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM=
diff --git a/internal/applicant/providers.go b/internal/applicant/providers.go
index d992e9c1..cc8a3cfd 100644
--- a/internal/applicant/providers.go
+++ b/internal/applicant/providers.go
@@ -6,23 +6,29 @@ import (
"github.com/go-acme/lego/v4/challenge"
"github.com/usual2970/certimate/internal/domain"
- providerACMEHttpReq "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/acmehttpreq"
- providerAliyun "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/aliyun"
- providerAWSRoute53 "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/aws-route53"
- providerAzureDNS "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/azure-dns"
- providerCloudflare "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/cloudflare"
- providerClouDNS "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/cloudns"
- providerGname "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/gname"
- providerGoDaddy "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/godaddy"
- providerHuaweiCloud "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/huaweicloud"
- providerNameDotCom "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/namedotcom"
- providerNameSilo "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/namesilo"
- providerNS1 "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/ns1"
- providerPowerDNS "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/powerdns"
- providerRainYun "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/rainyun"
- providerTencentCloud "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/tencentcloud"
- providerVolcEngine "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/volcengine"
- providerWestcn "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/westcn"
+ 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"
+ 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"
+ pCloudflare "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/cloudflare"
+ pClouDNS "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/cloudns"
+ pCMCCCloud "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/cmcccloud"
+ pDNSLA "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/dnsla"
+ pGcore "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/gcore"
+ pGname "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/gname"
+ pGoDaddy "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/godaddy"
+ pHuaweiCloud "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/huaweicloud"
+ pJDCloud "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/jdcloud"
+ pNamecheap "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/namecheap"
+ pNameDotCom "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/namedotcom"
+ pNameSilo "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/namesilo"
+ pNS1 "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/ns1"
+ pPowerDNS "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/powerdns"
+ pRainYun "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/rainyun"
+ pTencentCloud "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/tencentcloud"
+ 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/maps"
)
@@ -39,7 +45,7 @@ func createApplicant(options *applicantOptions) (challenge.Provider, error) {
return nil, fmt.Errorf("failed to populate provider access config: %w", err)
}
- applicant, err := providerACMEHttpReq.NewChallengeProvider(&providerACMEHttpReq.ACMEHttpReqApplicantConfig{
+ applicant, err := pACMEHttpReq.NewChallengeProvider(&pACMEHttpReq.ChallengeProviderConfig{
Endpoint: access.Endpoint,
Mode: access.Mode,
Username: access.Username,
@@ -56,7 +62,7 @@ func createApplicant(options *applicantOptions) (challenge.Provider, error) {
return nil, fmt.Errorf("failed to populate provider access config: %w", err)
}
- applicant, err := providerAliyun.NewChallengeProvider(&providerAliyun.AliyunApplicantConfig{
+ applicant, err := pAliyun.NewChallengeProvider(&pAliyun.ChallengeProviderConfig{
AccessKeyId: access.AccessKeyId,
AccessKeySecret: access.AccessKeySecret,
DnsPropagationTimeout: options.DnsPropagationTimeout,
@@ -72,7 +78,7 @@ func createApplicant(options *applicantOptions) (challenge.Provider, error) {
return nil, fmt.Errorf("failed to populate provider access config: %w", err)
}
- applicant, err := providerAWSRoute53.NewChallengeProvider(&providerAWSRoute53.AWSRoute53ApplicantConfig{
+ applicant, err := pAWSRoute53.NewChallengeProvider(&pAWSRoute53.ChallengeProviderConfig{
AccessKeyId: access.AccessKeyId,
SecretAccessKey: access.SecretAccessKey,
Region: maps.GetValueAsString(options.ProviderApplyConfig, "region"),
@@ -83,14 +89,14 @@ func createApplicant(options *applicantOptions) (challenge.Provider, error) {
return applicant, err
}
- case domain.ApplyDNSProviderTypeAzureDNS:
+ case domain.ApplyDNSProviderTypeAzure, domain.ApplyDNSProviderTypeAzureDNS:
{
access := domain.AccessConfigForAzure{}
if err := maps.Populate(options.ProviderAccessConfig, &access); err != nil {
return nil, fmt.Errorf("failed to populate provider access config: %w", err)
}
- applicant, err := providerAzureDNS.NewChallengeProvider(&providerAzureDNS.AzureDNSApplicantConfig{
+ applicant, err := pAzureDNS.NewChallengeProvider(&pAzureDNS.ChallengeProviderConfig{
TenantId: access.TenantId,
ClientId: access.ClientId,
ClientSecret: access.ClientSecret,
@@ -101,6 +107,22 @@ func createApplicant(options *applicantOptions) (challenge.Provider, error) {
return applicant, err
}
+ case domain.ApplyDNSProviderTypeBaiduCloud, domain.ApplyDNSProviderTypeBaiduCloudDNS:
+ {
+ access := domain.AccessConfigForBaiduCloud{}
+ if err := maps.Populate(options.ProviderAccessConfig, &access); err != nil {
+ return nil, fmt.Errorf("failed to populate provider access config: %w", err)
+ }
+
+ applicant, err := pBaiduCloud.NewChallengeProvider(&pBaiduCloud.ChallengeProviderConfig{
+ AccessKeyId: access.AccessKeyId,
+ SecretAccessKey: access.SecretAccessKey,
+ DnsPropagationTimeout: options.DnsPropagationTimeout,
+ DnsTTL: options.DnsTTL,
+ })
+ return applicant, err
+ }
+
case domain.ApplyDNSProviderTypeCloudflare:
{
access := domain.AccessConfigForCloudflare{}
@@ -108,7 +130,7 @@ func createApplicant(options *applicantOptions) (challenge.Provider, error) {
return nil, fmt.Errorf("failed to populate provider access config: %w", err)
}
- applicant, err := providerCloudflare.NewChallengeProvider(&providerCloudflare.CloudflareApplicantConfig{
+ applicant, err := pCloudflare.NewChallengeProvider(&pCloudflare.ChallengeProviderConfig{
DnsApiToken: access.DnsApiToken,
DnsPropagationTimeout: options.DnsPropagationTimeout,
DnsTTL: options.DnsTTL,
@@ -123,7 +145,7 @@ func createApplicant(options *applicantOptions) (challenge.Provider, error) {
return nil, fmt.Errorf("failed to populate provider access config: %w", err)
}
- applicant, err := providerClouDNS.NewChallengeProvider(&providerClouDNS.ClouDNSApplicantConfig{
+ applicant, err := pClouDNS.NewChallengeProvider(&pClouDNS.ChallengeProviderConfig{
AuthId: access.AuthId,
AuthPassword: access.AuthPassword,
DnsPropagationTimeout: options.DnsPropagationTimeout,
@@ -132,6 +154,53 @@ func createApplicant(options *applicantOptions) (challenge.Provider, error) {
return applicant, err
}
+ case domain.ApplyDNSProviderTypeCMCCCloud:
+ {
+ access := domain.AccessConfigForCMCCCloud{}
+ if err := maps.Populate(options.ProviderAccessConfig, &access); err != nil {
+ return nil, fmt.Errorf("failed to populate provider access config: %w", err)
+ }
+
+ applicant, err := pCMCCCloud.NewChallengeProvider(&pCMCCCloud.ChallengeProviderConfig{
+ AccessKeyId: access.AccessKeyId,
+ AccessKeySecret: access.AccessKeySecret,
+ DnsPropagationTimeout: options.DnsPropagationTimeout,
+ DnsTTL: options.DnsTTL,
+ })
+ return applicant, err
+ }
+
+ case domain.ApplyDNSProviderTypeDNSLA:
+ {
+ access := domain.AccessConfigForDNSLA{}
+ if err := maps.Populate(options.ProviderAccessConfig, &access); err != nil {
+ return nil, fmt.Errorf("failed to populate provider access config: %w", err)
+ }
+
+ applicant, err := pDNSLA.NewChallengeProvider(&pDNSLA.ChallengeProviderConfig{
+ ApiId: access.ApiId,
+ ApiSecret: access.ApiSecret,
+ DnsPropagationTimeout: options.DnsPropagationTimeout,
+ DnsTTL: options.DnsTTL,
+ })
+ return applicant, err
+ }
+
+ case domain.ApplyDNSProviderTypeGcore:
+ {
+ access := domain.AccessConfigForGcore{}
+ if err := maps.Populate(options.ProviderAccessConfig, &access); err != nil {
+ return nil, fmt.Errorf("failed to populate provider access config: %w", err)
+ }
+
+ applicant, err := pGcore.NewChallengeProvider(&pGcore.ChallengeProviderConfig{
+ ApiToken: access.ApiToken,
+ DnsPropagationTimeout: options.DnsPropagationTimeout,
+ DnsTTL: options.DnsTTL,
+ })
+ return applicant, err
+ }
+
case domain.ApplyDNSProviderTypeGname:
{
access := domain.AccessConfigForGname{}
@@ -139,7 +208,7 @@ func createApplicant(options *applicantOptions) (challenge.Provider, error) {
return nil, fmt.Errorf("failed to populate provider access config: %w", err)
}
- applicant, err := providerGname.NewChallengeProvider(&providerGname.GnameApplicantConfig{
+ applicant, err := pGname.NewChallengeProvider(&pGname.ChallengeProviderConfig{
AppId: access.AppId,
AppKey: access.AppKey,
DnsPropagationTimeout: options.DnsPropagationTimeout,
@@ -155,7 +224,7 @@ func createApplicant(options *applicantOptions) (challenge.Provider, error) {
return nil, fmt.Errorf("failed to populate provider access config: %w", err)
}
- applicant, err := providerGoDaddy.NewChallengeProvider(&providerGoDaddy.GoDaddyApplicantConfig{
+ applicant, err := pGoDaddy.NewChallengeProvider(&pGoDaddy.ChallengeProviderConfig{
ApiKey: access.ApiKey,
ApiSecret: access.ApiSecret,
DnsPropagationTimeout: options.DnsPropagationTimeout,
@@ -171,7 +240,7 @@ func createApplicant(options *applicantOptions) (challenge.Provider, error) {
return nil, fmt.Errorf("failed to populate provider access config: %w", err)
}
- applicant, err := providerHuaweiCloud.NewChallengeProvider(&providerHuaweiCloud.HuaweiCloudApplicantConfig{
+ applicant, err := pHuaweiCloud.NewChallengeProvider(&pHuaweiCloud.ChallengeProviderConfig{
AccessKeyId: access.AccessKeyId,
SecretAccessKey: access.SecretAccessKey,
Region: maps.GetValueAsString(options.ProviderApplyConfig, "region"),
@@ -181,6 +250,39 @@ func createApplicant(options *applicantOptions) (challenge.Provider, error) {
return applicant, err
}
+ case domain.ApplyDNSProviderTypeJDCloud, domain.ApplyDNSProviderTypeJDCloudDNS:
+ {
+ access := domain.AccessConfigForJDCloud{}
+ if err := maps.Populate(options.ProviderAccessConfig, &access); err != nil {
+ return nil, fmt.Errorf("failed to populate provider access config: %w", err)
+ }
+
+ applicant, err := pJDCloud.NewChallengeProvider(&pJDCloud.ChallengeProviderConfig{
+ AccessKeyId: access.AccessKeyId,
+ AccessKeySecret: access.AccessKeySecret,
+ RegionId: maps.GetValueAsString(options.ProviderApplyConfig, "region_id"),
+ DnsPropagationTimeout: options.DnsPropagationTimeout,
+ DnsTTL: options.DnsTTL,
+ })
+ return applicant, err
+ }
+
+ case domain.ApplyDNSProviderTypeNamecheap:
+ {
+ access := domain.AccessConfigForNamecheap{}
+ if err := maps.Populate(options.ProviderAccessConfig, &access); err != nil {
+ return nil, fmt.Errorf("failed to populate provider access config: %w", err)
+ }
+
+ applicant, err := pNamecheap.NewChallengeProvider(&pNamecheap.ChallengeProviderConfig{
+ Username: access.Username,
+ ApiKey: access.ApiKey,
+ DnsPropagationTimeout: options.DnsPropagationTimeout,
+ DnsTTL: options.DnsTTL,
+ })
+ return applicant, err
+ }
+
case domain.ApplyDNSProviderTypeNameDotCom:
{
access := domain.AccessConfigForNameDotCom{}
@@ -188,7 +290,7 @@ func createApplicant(options *applicantOptions) (challenge.Provider, error) {
return nil, fmt.Errorf("failed to populate provider access config: %w", err)
}
- applicant, err := providerNameDotCom.NewChallengeProvider(&providerNameDotCom.NameDotComApplicantConfig{
+ applicant, err := pNameDotCom.NewChallengeProvider(&pNameDotCom.ChallengeProviderConfig{
Username: access.Username,
ApiToken: access.ApiToken,
DnsPropagationTimeout: options.DnsPropagationTimeout,
@@ -204,7 +306,7 @@ func createApplicant(options *applicantOptions) (challenge.Provider, error) {
return nil, fmt.Errorf("failed to populate provider access config: %w", err)
}
- applicant, err := providerNameSilo.NewChallengeProvider(&providerNameSilo.NameSiloApplicantConfig{
+ applicant, err := pNameSilo.NewChallengeProvider(&pNameSilo.ChallengeProviderConfig{
ApiKey: access.ApiKey,
DnsPropagationTimeout: options.DnsPropagationTimeout,
DnsTTL: options.DnsTTL,
@@ -219,7 +321,7 @@ func createApplicant(options *applicantOptions) (challenge.Provider, error) {
return nil, fmt.Errorf("failed to populate provider access config: %w", err)
}
- applicant, err := providerNS1.NewChallengeProvider(&providerNS1.NS1ApplicantConfig{
+ applicant, err := pNS1.NewChallengeProvider(&pNS1.ChallengeProviderConfig{
ApiKey: access.ApiKey,
DnsPropagationTimeout: options.DnsPropagationTimeout,
DnsTTL: options.DnsTTL,
@@ -234,7 +336,7 @@ func createApplicant(options *applicantOptions) (challenge.Provider, error) {
return nil, fmt.Errorf("failed to populate provider access config: %w", err)
}
- applicant, err := providerPowerDNS.NewChallengeProvider(&providerPowerDNS.PowerDNSApplicantConfig{
+ applicant, err := pPowerDNS.NewChallengeProvider(&pPowerDNS.ChallengeProviderConfig{
ApiUrl: access.ApiUrl,
ApiKey: access.ApiKey,
DnsPropagationTimeout: options.DnsPropagationTimeout,
@@ -250,7 +352,7 @@ func createApplicant(options *applicantOptions) (challenge.Provider, error) {
return nil, fmt.Errorf("failed to populate provider access config: %w", err)
}
- applicant, err := providerRainYun.NewChallengeProvider(&providerRainYun.RainYunApplicantConfig{
+ applicant, err := pRainYun.NewChallengeProvider(&pRainYun.ChallengeProviderConfig{
ApiKey: access.ApiKey,
DnsPropagationTimeout: options.DnsPropagationTimeout,
DnsTTL: options.DnsTTL,
@@ -265,7 +367,7 @@ func createApplicant(options *applicantOptions) (challenge.Provider, error) {
return nil, fmt.Errorf("failed to populate provider access config: %w", err)
}
- applicant, err := providerTencentCloud.NewChallengeProvider(&providerTencentCloud.TencentCloudApplicantConfig{
+ applicant, err := pTencentCloud.NewChallengeProvider(&pTencentCloud.ChallengeProviderConfig{
SecretId: access.SecretId,
SecretKey: access.SecretKey,
DnsPropagationTimeout: options.DnsPropagationTimeout,
@@ -281,7 +383,7 @@ func createApplicant(options *applicantOptions) (challenge.Provider, error) {
return nil, fmt.Errorf("failed to populate provider access config: %w", err)
}
- applicant, err := providerVolcEngine.NewChallengeProvider(&providerVolcEngine.VolcEngineApplicantConfig{
+ applicant, err := pVolcEngine.NewChallengeProvider(&pVolcEngine.ChallengeProviderConfig{
AccessKeyId: access.AccessKeyId,
SecretAccessKey: access.SecretAccessKey,
DnsPropagationTimeout: options.DnsPropagationTimeout,
@@ -297,7 +399,7 @@ func createApplicant(options *applicantOptions) (challenge.Provider, error) {
return nil, fmt.Errorf("failed to populate provider access config: %w", err)
}
- applicant, err := providerWestcn.NewChallengeProvider(&providerWestcn.WestcnApplicantConfig{
+ applicant, err := pWestcn.NewChallengeProvider(&pWestcn.ChallengeProviderConfig{
Username: access.Username,
ApiPassword: access.ApiPassword,
DnsPropagationTimeout: options.DnsPropagationTimeout,
diff --git a/internal/deployer/deployer.go b/internal/deployer/deployer.go
index e64c8a88..f95442a6 100644
--- a/internal/deployer/deployer.go
+++ b/internal/deployer/deployer.go
@@ -42,7 +42,7 @@ func NewWithDeployNode(node *domain.WorkflowNode, certdata struct {
return nil, fmt.Errorf("failed to unmarshal access config: %w", err)
}
- deployer, logger, err := createDeployer(&deployerOptions{
+ deployer, err := createDeployer(&deployerOptions{
Provider: domain.DeployProviderType(nodeConfig.Provider),
ProviderAccessConfig: accessConfig,
ProviderDeployConfig: nodeConfig.ProviderConfig,
@@ -52,7 +52,7 @@ func NewWithDeployNode(node *domain.WorkflowNode, certdata struct {
}
return &proxyDeployer{
- logger: logger,
+ logger: logger.NewNilLogger(),
deployer: deployer,
deployCertificate: certdata.Certificate,
deployPrivateKey: certdata.PrivateKey,
diff --git a/internal/deployer/providers.go b/internal/deployer/providers.go
index a9878f8a..6a8a0b6c 100644
--- a/internal/deployer/providers.go
+++ b/internal/deployer/providers.go
@@ -6,162 +6,183 @@ import (
"github.com/usual2970/certimate/internal/domain"
"github.com/usual2970/certimate/internal/pkg/core/deployer"
- providerAliyunALB "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/aliyun-alb"
- providerAliyunCASDeploy "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/aliyun-cas-deploy"
- providerAliyunCDN "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/aliyun-cdn"
- providerAliyunCLB "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/aliyun-clb"
- providerAliyunDCDN "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/aliyun-dcdn"
- providerAliyunESA "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/aliyun-esa"
- providerAliyunLive "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/aliyun-live"
- providerAliyunNLB "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/aliyun-nlb"
- providerAliyunOSS "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/aliyun-oss"
- providerAliyunWAF "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/aliyun-waf"
- providerAWSCloudFront "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/aws-cloudfront"
- providerBaiduCloudCDN "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/baiducloud-cdn"
- providerBaotaPanelSite "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/baotapanel-site"
- providerBytePlusCDN "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/byteplus-cdn"
- providerDogeCDN "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/dogecloud-cdn"
- providerEdgioApplications "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/edgio-applications"
- providerHuaweiCloudCDN "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/huaweicloud-cdn"
- providerHuaweiCloudELB "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/huaweicloud-elb"
- providerK8sSecret "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/k8s-secret"
- providerLocal "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/local"
- providerQiniuCDN "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/qiniu-cdn"
- providerQiniuPili "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/qiniu-pili"
- providerSSH "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/ssh"
- providerTencentCloudCDN "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/tencentcloud-cdn"
- providerTencentCloudCLB "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/tencentcloud-clb"
- providerTencentCloudCOS "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/tencentcloud-cos"
- providerTencentCloudCSS "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/tencentcloud-css"
- providerTencentCloudECDN "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/tencentcloud-ecdn"
- providerTencentCloudEO "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/tencentcloud-eo"
- providerTencentCloudSSLDeploy "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/tencentcloud-ssl-deploy"
- providerUCloudUCDN "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/ucloud-ucdn"
- providerUCloudUS3 "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/ucloud-us3"
- providerVolcEngineCDN "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/volcengine-cdn"
- providerVolcEngineCLB "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/volcengine-clb"
- providerVolcEngineDCDN "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/volcengine-dcdn"
- providerVolcEngineLive "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/volcengine-live"
- providerVolcEngineTOS "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/volcengine-tos"
- providerWebhook "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/webhook"
- "github.com/usual2970/certimate/internal/pkg/core/logger"
+ pAliyunALB "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/aliyun-alb"
+ pAliyunCASDeploy "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/aliyun-cas-deploy"
+ 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"
+ pAliyunESA "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/aliyun-esa"
+ pAliyunLive "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/aliyun-live"
+ pAliyunNLB "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/aliyun-nlb"
+ pAliyunOSS "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/aliyun-oss"
+ pAliyunVOD "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/aliyun-vod"
+ pAliyunWAF "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/aliyun-waf"
+ pAWSCloudFront "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/aws-cloudfront"
+ pBaiduCloudCDN "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/baiducloud-cdn"
+ pBaishanCDN "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/baishan-cdn"
+ pBaotaPanelConsole "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/baotapanel-console"
+ pBaotaPanelSite "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/baotapanel-site"
+ pBytePlusCDN "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/byteplus-cdn"
+ pCacheFly "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/cachefly"
+ pCdnfly "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/cdnfly"
+ 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"
+ pHuaweiCloudCDN "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/huaweicloud-cdn"
+ pHuaweiCloudELB "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/huaweicloud-elb"
+ pHuaweiCloudWAF "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/huaweicloud-waf"
+ pJDCloudALB "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/jdcloud-alb"
+ pJDCloudCDN "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/jdcloud-cdn"
+ pJDCloudLive "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/jdcloud-live"
+ 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"
+ pQiniuCDN "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/qiniu-cdn"
+ pQiniuPili "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/qiniu-pili"
+ pSafeLine "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/safeline"
+ pSSH "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/ssh"
+ pTencentCloudCDN "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/tencentcloud-cdn"
+ pTencentCloudCLB "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/tencentcloud-clb"
+ pTencentCloudCOS "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/tencentcloud-cos"
+ pTencentCloudCSS "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/tencentcloud-css"
+ pTencentCloudECDN "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/tencentcloud-ecdn"
+ pTencentCloudEO "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/tencentcloud-eo"
+ pTencentCloudSSLDeploy "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/tencentcloud-ssl-deploy"
+ pTencentCloudVOD "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/tencentcloud-vod"
+ pTencentCloudWAF "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/tencentcloud-waf"
+ pUCloudUCDN "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/ucloud-ucdn"
+ pUCloudUS3 "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/ucloud-us3"
+ pVolcEngineCDN "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/volcengine-cdn"
+ pVolcEngineCLB "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/volcengine-clb"
+ pVolcEngineDCDN "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/volcengine-dcdn"
+ pVolcEngineImageX "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/volcengine-imagex"
+ pVolcEngineLive "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/volcengine-live"
+ pVolcEngineTOS "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/volcengine-tos"
+ pWebhook "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/webhook"
"github.com/usual2970/certimate/internal/pkg/utils/maps"
"github.com/usual2970/certimate/internal/pkg/utils/slices"
)
-func createDeployer(options *deployerOptions) (deployer.Deployer, logger.Logger, error) {
- logger := logger.NewDefaultLogger()
-
+func createDeployer(options *deployerOptions) (deployer.Deployer, error) {
/*
注意:如果追加新的常量值,请保持以 ASCII 排序。
NOTICE: If you add new constant, please keep ASCII order.
*/
switch options.Provider {
- case domain.DeployProviderTypeAliyunALB, domain.DeployProviderTypeAliyunCASDeploy, domain.DeployProviderTypeAliyunCDN, domain.DeployProviderTypeAliyunCLB, domain.DeployProviderTypeAliyunDCDN, domain.DeployProviderTypeAliyunESA, domain.DeployProviderTypeAliyunLive, domain.DeployProviderTypeAliyunNLB, domain.DeployProviderTypeAliyunOSS, domain.DeployProviderTypeAliyunWAF:
+ case domain.DeployProviderTypeAliyunALB, domain.DeployProviderTypeAliyunCASDeploy, domain.DeployProviderTypeAliyunCDN, domain.DeployProviderTypeAliyunCLB, domain.DeployProviderTypeAliyunDCDN, domain.DeployProviderTypeAliyunESA, domain.DeployProviderTypeAliyunLive, domain.DeployProviderTypeAliyunNLB, domain.DeployProviderTypeAliyunOSS, domain.DeployProviderTypeAliyunVOD, domain.DeployProviderTypeAliyunWAF:
{
access := domain.AccessConfigForAliyun{}
if err := maps.Populate(options.ProviderAccessConfig, &access); err != nil {
- return nil, nil, fmt.Errorf("failed to populate provider access config: %w", err)
+ return nil, fmt.Errorf("failed to populate provider access config: %w", err)
}
switch options.Provider {
case domain.DeployProviderTypeAliyunALB:
- deployer, err := providerAliyunALB.NewWithLogger(&providerAliyunALB.AliyunALBDeployerConfig{
+ deployer, err := pAliyunALB.NewDeployer(&pAliyunALB.DeployerConfig{
AccessKeyId: access.AccessKeyId,
AccessKeySecret: access.AccessKeySecret,
Region: maps.GetValueAsString(options.ProviderDeployConfig, "region"),
- ResourceType: providerAliyunALB.DeployResourceType(maps.GetValueAsString(options.ProviderDeployConfig, "resourceType")),
+ ResourceType: pAliyunALB.ResourceType(maps.GetValueAsString(options.ProviderDeployConfig, "resourceType")),
LoadbalancerId: maps.GetValueAsString(options.ProviderDeployConfig, "loadbalancerId"),
ListenerId: maps.GetValueAsString(options.ProviderDeployConfig, "listenerId"),
Domain: maps.GetValueAsString(options.ProviderDeployConfig, "domain"),
- }, logger)
- return deployer, logger, err
+ })
+ return deployer, err
case domain.DeployProviderTypeAliyunCASDeploy:
- deployer, err := providerAliyunCASDeploy.NewWithLogger(&providerAliyunCASDeploy.AliyunCASDeployDeployerConfig{
+ deployer, err := pAliyunCASDeploy.NewDeployer(&pAliyunCASDeploy.DeployerConfig{
AccessKeyId: access.AccessKeyId,
AccessKeySecret: access.AccessKeySecret,
Region: maps.GetValueAsString(options.ProviderDeployConfig, "region"),
ResourceIds: slices.Filter(strings.Split(maps.GetValueAsString(options.ProviderDeployConfig, "resourceIds"), ";"), func(s string) bool { return s != "" }),
ContactIds: slices.Filter(strings.Split(maps.GetValueAsString(options.ProviderDeployConfig, "contactIds"), ";"), func(s string) bool { return s != "" }),
- }, logger)
- return deployer, logger, err
+ })
+ return deployer, err
case domain.DeployProviderTypeAliyunCDN:
- deployer, err := providerAliyunCDN.NewWithLogger(&providerAliyunCDN.AliyunCDNDeployerConfig{
+ deployer, err := pAliyunCDN.NewDeployer(&pAliyunCDN.DeployerConfig{
AccessKeyId: access.AccessKeyId,
AccessKeySecret: access.AccessKeySecret,
Domain: maps.GetValueAsString(options.ProviderDeployConfig, "domain"),
- }, logger)
- return deployer, logger, err
+ })
+ return deployer, err
case domain.DeployProviderTypeAliyunCLB:
- deployer, err := providerAliyunCLB.NewWithLogger(&providerAliyunCLB.AliyunCLBDeployerConfig{
+ deployer, err := pAliyunCLB.NewDeployer(&pAliyunCLB.DeployerConfig{
AccessKeyId: access.AccessKeyId,
AccessKeySecret: access.AccessKeySecret,
Region: maps.GetValueAsString(options.ProviderDeployConfig, "region"),
- ResourceType: providerAliyunCLB.DeployResourceType(maps.GetValueAsString(options.ProviderDeployConfig, "resourceType")),
+ ResourceType: pAliyunCLB.ResourceType(maps.GetValueAsString(options.ProviderDeployConfig, "resourceType")),
LoadbalancerId: maps.GetValueAsString(options.ProviderDeployConfig, "loadbalancerId"),
ListenerPort: maps.GetValueOrDefaultAsInt32(options.ProviderDeployConfig, "listenerPort", 443),
Domain: maps.GetValueAsString(options.ProviderDeployConfig, "domain"),
- }, logger)
- return deployer, logger, err
+ })
+ return deployer, err
case domain.DeployProviderTypeAliyunDCDN:
- deployer, err := providerAliyunDCDN.NewWithLogger(&providerAliyunDCDN.AliyunDCDNDeployerConfig{
+ deployer, err := pAliyunDCDN.NewDeployer(&pAliyunDCDN.DeployerConfig{
AccessKeyId: access.AccessKeyId,
AccessKeySecret: access.AccessKeySecret,
Domain: maps.GetValueAsString(options.ProviderDeployConfig, "domain"),
- }, logger)
- return deployer, logger, err
+ })
+ return deployer, err
case domain.DeployProviderTypeAliyunESA:
- deployer, err := providerAliyunESA.NewWithLogger(&providerAliyunESA.AliyunESADeployerConfig{
+ deployer, err := pAliyunESA.NewDeployer(&pAliyunESA.DeployerConfig{
AccessKeyId: access.AccessKeyId,
AccessKeySecret: access.AccessKeySecret,
Region: maps.GetValueAsString(options.ProviderDeployConfig, "region"),
SiteId: maps.GetValueAsInt64(options.ProviderDeployConfig, "siteId"),
- }, logger)
- return deployer, logger, err
+ })
+ return deployer, err
case domain.DeployProviderTypeAliyunLive:
- deployer, err := providerAliyunLive.NewWithLogger(&providerAliyunLive.AliyunLiveDeployerConfig{
+ deployer, err := pAliyunLive.NewDeployer(&pAliyunLive.DeployerConfig{
AccessKeyId: access.AccessKeyId,
AccessKeySecret: access.AccessKeySecret,
Region: maps.GetValueAsString(options.ProviderDeployConfig, "region"),
Domain: maps.GetValueAsString(options.ProviderDeployConfig, "domain"),
- }, logger)
- return deployer, logger, err
+ })
+ return deployer, err
case domain.DeployProviderTypeAliyunNLB:
- deployer, err := providerAliyunNLB.NewWithLogger(&providerAliyunNLB.AliyunNLBDeployerConfig{
+ deployer, err := pAliyunNLB.NewDeployer(&pAliyunNLB.DeployerConfig{
AccessKeyId: access.AccessKeyId,
AccessKeySecret: access.AccessKeySecret,
Region: maps.GetValueAsString(options.ProviderDeployConfig, "region"),
- ResourceType: providerAliyunNLB.DeployResourceType(maps.GetValueAsString(options.ProviderDeployConfig, "resourceType")),
+ ResourceType: pAliyunNLB.ResourceType(maps.GetValueAsString(options.ProviderDeployConfig, "resourceType")),
LoadbalancerId: maps.GetValueAsString(options.ProviderDeployConfig, "loadbalancerId"),
ListenerId: maps.GetValueAsString(options.ProviderDeployConfig, "listenerId"),
- }, logger)
- return deployer, logger, err
+ })
+ return deployer, err
case domain.DeployProviderTypeAliyunOSS:
- deployer, err := providerAliyunOSS.NewWithLogger(&providerAliyunOSS.AliyunOSSDeployerConfig{
+ deployer, err := pAliyunOSS.NewDeployer(&pAliyunOSS.DeployerConfig{
AccessKeyId: access.AccessKeyId,
AccessKeySecret: access.AccessKeySecret,
Region: maps.GetValueAsString(options.ProviderDeployConfig, "region"),
Bucket: maps.GetValueAsString(options.ProviderDeployConfig, "bucket"),
Domain: maps.GetValueAsString(options.ProviderDeployConfig, "domain"),
- }, logger)
- return deployer, logger, err
+ })
+ return deployer, err
+
+ case domain.DeployProviderTypeAliyunVOD:
+ deployer, err := pAliyunVOD.NewDeployer(&pAliyunVOD.DeployerConfig{
+ AccessKeyId: access.AccessKeyId,
+ AccessKeySecret: access.AccessKeySecret,
+ Region: maps.GetValueAsString(options.ProviderDeployConfig, "region"),
+ Domain: maps.GetValueAsString(options.ProviderDeployConfig, "domain"),
+ })
+ return deployer, err
case domain.DeployProviderTypeAliyunWAF:
- deployer, err := providerAliyunWAF.NewWithLogger(&providerAliyunWAF.AliyunWAFDeployerConfig{
+ deployer, err := pAliyunWAF.NewDeployer(&pAliyunWAF.DeployerConfig{
AccessKeyId: access.AccessKeyId,
AccessKeySecret: access.AccessKeySecret,
Region: maps.GetValueAsString(options.ProviderDeployConfig, "region"),
InstanceId: maps.GetValueAsString(options.ProviderDeployConfig, "instanceId"),
- }, logger)
- return deployer, logger, err
+ })
+ return deployer, err
default:
break
@@ -172,18 +193,18 @@ func createDeployer(options *deployerOptions) (deployer.Deployer, logger.Logger,
{
access := domain.AccessConfigForAWS{}
if err := maps.Populate(options.ProviderAccessConfig, &access); err != nil {
- return nil, nil, fmt.Errorf("failed to populate provider access config: %w", err)
+ return nil, fmt.Errorf("failed to populate provider access config: %w", err)
}
switch options.Provider {
case domain.DeployProviderTypeAWSCloudFront:
- deployer, err := providerAWSCloudFront.NewWithLogger(&providerAWSCloudFront.AWSCloudFrontDeployerConfig{
+ deployer, err := pAWSCloudFront.NewDeployer(&pAWSCloudFront.DeployerConfig{
AccessKeyId: access.AccessKeyId,
SecretAccessKey: access.SecretAccessKey,
Region: maps.GetValueAsString(options.ProviderDeployConfig, "region"),
DistributionId: maps.GetValueAsString(options.ProviderDeployConfig, "distributionId"),
- }, logger)
- return deployer, logger, err
+ })
+ return deployer, err
default:
break
@@ -194,117 +215,263 @@ func createDeployer(options *deployerOptions) (deployer.Deployer, logger.Logger,
{
access := domain.AccessConfigForBaiduCloud{}
if err := maps.Populate(options.ProviderAccessConfig, &access); err != nil {
- return nil, nil, fmt.Errorf("failed to populate provider access config: %w", err)
+ return nil, fmt.Errorf("failed to populate provider access config: %w", err)
}
switch options.Provider {
case domain.DeployProviderTypeBaiduCloudCDN:
- deployer, err := providerBaiduCloudCDN.NewWithLogger(&providerBaiduCloudCDN.BaiduCloudCDNDeployerConfig{
+ deployer, err := pBaiduCloudCDN.NewDeployer(&pBaiduCloudCDN.DeployerConfig{
AccessKeyId: access.AccessKeyId,
SecretAccessKey: access.SecretAccessKey,
Domain: maps.GetValueAsString(options.ProviderDeployConfig, "domain"),
- }, logger)
- return deployer, logger, err
+ })
+ return deployer, err
default:
break
}
}
- case domain.DeployProviderTypeBaotaPanelSite:
+ case domain.DeployProviderTypeBaishanCDN:
+ {
+ access := domain.AccessConfigForBaishan{}
+ if err := maps.Populate(options.ProviderAccessConfig, &access); err != nil {
+ return nil, fmt.Errorf("failed to populate provider access config: %w", err)
+ }
+
+ switch options.Provider {
+ case domain.DeployProviderTypeBaishanCDN:
+ deployer, err := pBaishanCDN.NewDeployer(&pBaishanCDN.DeployerConfig{
+ ApiToken: access.ApiToken,
+ Domain: maps.GetValueAsString(options.ProviderDeployConfig, "domain"),
+ })
+ return deployer, err
+
+ default:
+ break
+ }
+ }
+
+ case domain.DeployProviderTypeBaotaPanelConsole, domain.DeployProviderTypeBaotaPanelSite:
{
access := domain.AccessConfigForBaotaPanel{}
if err := maps.Populate(options.ProviderAccessConfig, &access); err != nil {
- return nil, nil, fmt.Errorf("failed to populate provider access config: %w", err)
+ return nil, fmt.Errorf("failed to populate provider access config: %w", err)
}
- deployer, err := providerBaotaPanelSite.NewWithLogger(&providerBaotaPanelSite.BaotaPanelSiteDeployerConfig{
- ApiUrl: access.ApiUrl,
- ApiKey: access.ApiKey,
- SiteName: maps.GetValueAsString(options.ProviderDeployConfig, "siteName"),
- }, logger)
- return deployer, logger, err
+ switch options.Provider {
+ case domain.DeployProviderTypeBaotaPanelConsole:
+ deployer, err := pBaotaPanelConsole.NewDeployer(&pBaotaPanelConsole.DeployerConfig{
+ ApiUrl: access.ApiUrl,
+ ApiKey: access.ApiKey,
+ AutoRestart: maps.GetValueAsBool(options.ProviderDeployConfig, "autoRestart"),
+ })
+ return deployer, err
+
+ case domain.DeployProviderTypeBaotaPanelSite:
+ deployer, err := pBaotaPanelSite.NewDeployer(&pBaotaPanelSite.DeployerConfig{
+ ApiUrl: access.ApiUrl,
+ ApiKey: access.ApiKey,
+ SiteType: maps.GetValueOrDefaultAsString(options.ProviderDeployConfig, "siteType", "other"),
+ SiteName: maps.GetValueAsString(options.ProviderDeployConfig, "siteName"),
+ SiteNames: slices.Filter(strings.Split(maps.GetValueAsString(options.ProviderDeployConfig, "siteNames"), ";"), func(s string) bool { return s != "" }),
+ })
+ return deployer, err
+
+ default:
+ break
+ }
}
case domain.DeployProviderTypeBytePlusCDN:
{
access := domain.AccessConfigForBytePlus{}
if err := maps.Populate(options.ProviderAccessConfig, &access); err != nil {
- return nil, nil, fmt.Errorf("failed to populate provider access config: %w", err)
+ return nil, fmt.Errorf("failed to populate provider access config: %w", err)
}
switch options.Provider {
case domain.DeployProviderTypeBytePlusCDN:
- deployer, err := providerBytePlusCDN.NewWithLogger(&providerBytePlusCDN.BytePlusCDNDeployerConfig{
+ deployer, err := pBytePlusCDN.NewDeployer(&pBytePlusCDN.DeployerConfig{
AccessKey: access.AccessKey,
SecretKey: access.SecretKey,
Domain: maps.GetValueAsString(options.ProviderDeployConfig, "domain"),
- }, logger)
- return deployer, logger, err
+ })
+ return deployer, err
default:
break
}
}
+ case domain.DeployProviderTypeCacheFly:
+ {
+ access := domain.AccessConfigForCacheFly{}
+ if err := maps.Populate(options.ProviderAccessConfig, &access); err != nil {
+ return nil, fmt.Errorf("failed to populate provider access config: %w", err)
+ }
+
+ deployer, err := pCacheFly.NewDeployer(&pCacheFly.DeployerConfig{
+ ApiToken: access.ApiToken,
+ })
+ return deployer, err
+ }
+
+ case domain.DeployProviderTypeCdnfly:
+ {
+ access := domain.AccessConfigForCdnfly{}
+ if err := maps.Populate(options.ProviderAccessConfig, &access); err != nil {
+ return nil, fmt.Errorf("failed to populate provider access config: %w", err)
+ }
+
+ deployer, err := pCdnfly.NewDeployer(&pCdnfly.DeployerConfig{
+ ApiUrl: access.ApiUrl,
+ ApiKey: access.ApiKey,
+ ApiSecret: access.ApiSecret,
+ ResourceType: pCdnfly.ResourceType(maps.GetValueAsString(options.ProviderDeployConfig, "resourceType")),
+ SiteId: maps.GetValueAsString(options.ProviderDeployConfig, "siteId"),
+ CertificateId: maps.GetValueAsString(options.ProviderDeployConfig, "certificateId"),
+ })
+ return deployer, err
+ }
+
case domain.DeployProviderTypeDogeCloudCDN:
{
access := domain.AccessConfigForDogeCloud{}
if err := maps.Populate(options.ProviderAccessConfig, &access); err != nil {
- return nil, nil, fmt.Errorf("failed to populate provider access config: %w", err)
+ return nil, fmt.Errorf("failed to populate provider access config: %w", err)
}
- deployer, err := providerDogeCDN.NewWithLogger(&providerDogeCDN.DogeCloudCDNDeployerConfig{
+ deployer, err := pDogeCDN.NewDeployer(&pDogeCDN.DeployerConfig{
AccessKey: access.AccessKey,
SecretKey: access.SecretKey,
Domain: maps.GetValueAsString(options.ProviderDeployConfig, "domain"),
- }, logger)
- return deployer, logger, err
+ })
+ return deployer, err
}
case domain.DeployProviderTypeEdgioApplications:
{
access := domain.AccessConfigForEdgio{}
if err := maps.Populate(options.ProviderAccessConfig, &access); err != nil {
- return nil, nil, fmt.Errorf("failed to populate provider access config: %w", err)
+ return nil, fmt.Errorf("failed to populate provider access config: %w", err)
}
- deployer, err := providerEdgioApplications.NewWithLogger(&providerEdgioApplications.EdgioApplicationsDeployerConfig{
+ deployer, err := pEdgioApplications.NewDeployer(&pEdgioApplications.DeployerConfig{
ClientId: access.ClientId,
ClientSecret: access.ClientSecret,
EnvironmentId: maps.GetValueAsString(options.ProviderDeployConfig, "environmentId"),
- }, logger)
- return deployer, logger, err
+ })
+ return deployer, err
}
- case domain.DeployProviderTypeHuaweiCloudCDN, domain.DeployProviderTypeHuaweiCloudELB:
+ case domain.DeployProviderTypeGcoreCDN:
+ {
+ access := domain.AccessConfigForGcore{}
+ if err := maps.Populate(options.ProviderAccessConfig, &access); err != nil {
+ return nil, fmt.Errorf("failed to populate provider access config: %w", err)
+ }
+
+ switch options.Provider {
+ case domain.DeployProviderTypeGcoreCDN:
+ deployer, err := pGcoreCDN.NewDeployer(&pGcoreCDN.DeployerConfig{
+ ApiToken: access.ApiToken,
+ ResourceId: maps.GetValueAsInt64(options.ProviderDeployConfig, "resourceId"),
+ })
+ return deployer, err
+
+ default:
+ break
+ }
+ }
+
+ case domain.DeployProviderTypeHuaweiCloudCDN, domain.DeployProviderTypeHuaweiCloudELB, domain.DeployProviderTypeHuaweiCloudWAF:
{
access := domain.AccessConfigForHuaweiCloud{}
if err := maps.Populate(options.ProviderAccessConfig, &access); err != nil {
- return nil, nil, fmt.Errorf("failed to populate provider access config: %w", err)
+ return nil, fmt.Errorf("failed to populate provider access config: %w", err)
}
switch options.Provider {
case domain.DeployProviderTypeHuaweiCloudCDN:
- deployer, err := providerHuaweiCloudCDN.NewWithLogger(&providerHuaweiCloudCDN.HuaweiCloudCDNDeployerConfig{
+ deployer, err := pHuaweiCloudCDN.NewDeployer(&pHuaweiCloudCDN.DeployerConfig{
AccessKeyId: access.AccessKeyId,
SecretAccessKey: access.SecretAccessKey,
Region: maps.GetValueAsString(options.ProviderDeployConfig, "region"),
Domain: maps.GetValueAsString(options.ProviderDeployConfig, "domain"),
- }, logger)
- return deployer, logger, err
+ })
+ return deployer, err
case domain.DeployProviderTypeHuaweiCloudELB:
- deployer, err := providerHuaweiCloudELB.NewWithLogger(&providerHuaweiCloudELB.HuaweiCloudELBDeployerConfig{
+ deployer, err := pHuaweiCloudELB.NewDeployer(&pHuaweiCloudELB.DeployerConfig{
AccessKeyId: access.AccessKeyId,
SecretAccessKey: access.SecretAccessKey,
Region: maps.GetValueAsString(options.ProviderDeployConfig, "region"),
- ResourceType: providerHuaweiCloudELB.DeployResourceType(maps.GetValueAsString(options.ProviderDeployConfig, "resourceType")),
+ ResourceType: pHuaweiCloudELB.ResourceType(maps.GetValueAsString(options.ProviderDeployConfig, "resourceType")),
CertificateId: maps.GetValueAsString(options.ProviderDeployConfig, "certificateId"),
LoadbalancerId: maps.GetValueAsString(options.ProviderDeployConfig, "loadbalancerId"),
ListenerId: maps.GetValueAsString(options.ProviderDeployConfig, "listenerId"),
- }, logger)
- return deployer, logger, err
+ })
+ return deployer, err
+
+ case domain.DeployProviderTypeHuaweiCloudWAF:
+ deployer, err := pHuaweiCloudWAF.NewDeployer(&pHuaweiCloudWAF.DeployerConfig{
+ AccessKeyId: access.AccessKeyId,
+ SecretAccessKey: access.SecretAccessKey,
+ Region: maps.GetValueAsString(options.ProviderDeployConfig, "region"),
+ ResourceType: pHuaweiCloudWAF.ResourceType(maps.GetValueAsString(options.ProviderDeployConfig, "resourceType")),
+ CertificateId: maps.GetValueAsString(options.ProviderDeployConfig, "certificateId"),
+ Domain: maps.GetValueAsString(options.ProviderDeployConfig, "domain"),
+ })
+ return deployer, err
+
+ default:
+ break
+ }
+ }
+
+ case domain.DeployProviderTypeJDCloudALB, domain.DeployProviderTypeJDCloudCDN, domain.DeployProviderTypeJDCloudLive, domain.DeployProviderTypeJDCloudVOD:
+ {
+ access := domain.AccessConfigForJDCloud{}
+ if err := maps.Populate(options.ProviderAccessConfig, &access); err != nil {
+ return nil, fmt.Errorf("failed to populate provider access config: %w", err)
+ }
+
+ switch options.Provider {
+ case domain.DeployProviderTypeJDCloudALB:
+ deployer, err := pJDCloudALB.NewDeployer(&pJDCloudALB.DeployerConfig{
+ AccessKeyId: access.AccessKeyId,
+ AccessKeySecret: access.AccessKeySecret,
+ RegionId: maps.GetValueAsString(options.ProviderDeployConfig, "regionId"),
+ ResourceType: pJDCloudALB.ResourceType(maps.GetValueAsString(options.ProviderDeployConfig, "resourceType")),
+ LoadbalancerId: maps.GetValueAsString(options.ProviderDeployConfig, "loadbalancerId"),
+ ListenerId: maps.GetValueAsString(options.ProviderDeployConfig, "listenerId"),
+ })
+ return deployer, err
+
+ case domain.DeployProviderTypeJDCloudCDN:
+ deployer, err := pJDCloudCDN.NewDeployer(&pJDCloudCDN.DeployerConfig{
+ AccessKeyId: access.AccessKeyId,
+ AccessKeySecret: access.AccessKeySecret,
+ Domain: maps.GetValueAsString(options.ProviderDeployConfig, "domain"),
+ })
+ return deployer, err
+
+ case domain.DeployProviderTypeJDCloudLive:
+ deployer, err := pJDCloudLive.NewDeployer(&pJDCloudLive.DeployerConfig{
+ AccessKeyId: access.AccessKeyId,
+ AccessKeySecret: access.AccessKeySecret,
+ Domain: maps.GetValueAsString(options.ProviderDeployConfig, "domain"),
+ })
+ return deployer, err
+
+ case domain.DeployProviderTypeJDCloudVOD:
+ deployer, err := pJDCloudVOD.NewDeployer(&pJDCloudVOD.DeployerConfig{
+ AccessKeyId: access.AccessKeyId,
+ AccessKeySecret: access.AccessKeySecret,
+ Domain: maps.GetValueAsString(options.ProviderDeployConfig, "domain"),
+ })
+ return deployer, err
default:
break
@@ -313,77 +480,93 @@ func createDeployer(options *deployerOptions) (deployer.Deployer, logger.Logger,
case domain.DeployProviderTypeLocal:
{
- deployer, err := providerLocal.NewWithLogger(&providerLocal.LocalDeployerConfig{
- ShellEnv: providerLocal.ShellEnvType(maps.GetValueAsString(options.ProviderDeployConfig, "shellEnv")),
+ deployer, err := pLocal.NewDeployer(&pLocal.DeployerConfig{
+ ShellEnv: pLocal.ShellEnvType(maps.GetValueAsString(options.ProviderDeployConfig, "shellEnv")),
PreCommand: maps.GetValueAsString(options.ProviderDeployConfig, "preCommand"),
PostCommand: maps.GetValueAsString(options.ProviderDeployConfig, "postCommand"),
- OutputFormat: providerLocal.OutputFormatType(maps.GetValueOrDefaultAsString(options.ProviderDeployConfig, "format", string(providerLocal.OUTPUT_FORMAT_PEM))),
+ OutputFormat: pLocal.OutputFormatType(maps.GetValueOrDefaultAsString(options.ProviderDeployConfig, "format", string(pLocal.OUTPUT_FORMAT_PEM))),
OutputCertPath: maps.GetValueAsString(options.ProviderDeployConfig, "certPath"),
OutputKeyPath: maps.GetValueAsString(options.ProviderDeployConfig, "keyPath"),
PfxPassword: maps.GetValueAsString(options.ProviderDeployConfig, "pfxPassword"),
JksAlias: maps.GetValueAsString(options.ProviderDeployConfig, "jksAlias"),
JksKeypass: maps.GetValueAsString(options.ProviderDeployConfig, "jksKeypass"),
JksStorepass: maps.GetValueAsString(options.ProviderDeployConfig, "jksStorepass"),
- }, logger)
- return deployer, logger, err
+ })
+ return deployer, err
}
case domain.DeployProviderTypeKubernetesSecret:
{
access := domain.AccessConfigForKubernetes{}
if err := maps.Populate(options.ProviderAccessConfig, &access); err != nil {
- return nil, nil, fmt.Errorf("failed to populate provider access config: %w", err)
+ return nil, fmt.Errorf("failed to populate provider access config: %w", err)
}
- deployer, err := providerK8sSecret.NewWithLogger(&providerK8sSecret.K8sSecretDeployerConfig{
+ deployer, err := pK8sSecret.NewDeployer(&pK8sSecret.DeployerConfig{
KubeConfig: access.KubeConfig,
Namespace: maps.GetValueOrDefaultAsString(options.ProviderDeployConfig, "namespace", "default"),
SecretName: maps.GetValueAsString(options.ProviderDeployConfig, "secretName"),
SecretType: maps.GetValueOrDefaultAsString(options.ProviderDeployConfig, "secretType", "kubernetes.io/tls"),
SecretDataKeyForCrt: maps.GetValueOrDefaultAsString(options.ProviderDeployConfig, "secretDataKeyForCrt", "tls.crt"),
SecretDataKeyForKey: maps.GetValueOrDefaultAsString(options.ProviderDeployConfig, "secretDataKeyForKey", "tls.key"),
- }, logger)
- return deployer, logger, err
+ })
+ return deployer, err
}
case domain.DeployProviderTypeQiniuCDN, domain.DeployProviderTypeQiniuPili:
{
access := domain.AccessConfigForQiniu{}
if err := maps.Populate(options.ProviderAccessConfig, &access); err != nil {
- return nil, nil, fmt.Errorf("failed to populate provider access config: %w", err)
+ return nil, fmt.Errorf("failed to populate provider access config: %w", err)
}
switch options.Provider {
case domain.DeployProviderTypeQiniuCDN:
- deployer, err := providerQiniuCDN.NewWithLogger(&providerQiniuCDN.QiniuCDNDeployerConfig{
+ deployer, err := pQiniuCDN.NewDeployer(&pQiniuCDN.DeployerConfig{
AccessKey: access.AccessKey,
SecretKey: access.SecretKey,
Domain: maps.GetValueAsString(options.ProviderDeployConfig, "domain"),
- }, logger)
- return deployer, logger, err
+ })
+ return deployer, err
case domain.DeployProviderTypeQiniuPili:
- deployer, err := providerQiniuPili.NewWithLogger(&providerQiniuPili.QiniuPiliDeployerConfig{
+ deployer, err := pQiniuPili.NewDeployer(&pQiniuPili.DeployerConfig{
AccessKey: access.AccessKey,
SecretKey: access.SecretKey,
Hub: maps.GetValueAsString(options.ProviderDeployConfig, "hub"),
Domain: maps.GetValueAsString(options.ProviderDeployConfig, "domain"),
- }, logger)
- return deployer, logger, err
+ })
+ return deployer, err
default:
break
}
}
+ case domain.DeployProviderTypeSafeLine:
+ {
+ access := domain.AccessConfigForSafeLine{}
+ if err := maps.Populate(options.ProviderAccessConfig, &access); err != nil {
+ return nil, fmt.Errorf("failed to populate provider access config: %w", err)
+ }
+
+ deployer, err := pSafeLine.NewDeployer(&pSafeLine.DeployerConfig{
+ ApiUrl: access.ApiUrl,
+ ApiToken: access.ApiToken,
+ ResourceType: pSafeLine.ResourceType(maps.GetValueAsString(options.ProviderDeployConfig, "resourceType")),
+ CertificateId: maps.GetValueAsInt32(options.ProviderDeployConfig, "certificateId"),
+ })
+ return deployer, err
+ }
+
case domain.DeployProviderTypeSSH:
{
access := domain.AccessConfigForSSH{}
if err := maps.Populate(options.ProviderAccessConfig, &access); err != nil {
- return nil, nil, fmt.Errorf("failed to populate provider access config: %w", err)
+ return nil, fmt.Errorf("failed to populate provider access config: %w", err)
}
- deployer, err := providerSSH.NewWithLogger(&providerSSH.SshDeployerConfig{
+ deployer, err := pSSH.NewDeployer(&pSSH.DeployerConfig{
SshHost: access.Host,
SshPort: access.Port,
SshUsername: access.Username,
@@ -393,89 +576,108 @@ func createDeployer(options *deployerOptions) (deployer.Deployer, logger.Logger,
UseSCP: maps.GetValueAsBool(options.ProviderDeployConfig, "useSCP"),
PreCommand: maps.GetValueAsString(options.ProviderDeployConfig, "preCommand"),
PostCommand: maps.GetValueAsString(options.ProviderDeployConfig, "postCommand"),
- OutputFormat: providerSSH.OutputFormatType(maps.GetValueOrDefaultAsString(options.ProviderDeployConfig, "format", string(providerSSH.OUTPUT_FORMAT_PEM))),
+ OutputFormat: pSSH.OutputFormatType(maps.GetValueOrDefaultAsString(options.ProviderDeployConfig, "format", string(pSSH.OUTPUT_FORMAT_PEM))),
OutputCertPath: maps.GetValueAsString(options.ProviderDeployConfig, "certPath"),
OutputKeyPath: maps.GetValueAsString(options.ProviderDeployConfig, "keyPath"),
PfxPassword: maps.GetValueAsString(options.ProviderDeployConfig, "pfxPassword"),
JksAlias: maps.GetValueAsString(options.ProviderDeployConfig, "jksAlias"),
JksKeypass: maps.GetValueAsString(options.ProviderDeployConfig, "jksKeypass"),
JksStorepass: maps.GetValueAsString(options.ProviderDeployConfig, "jksStorepass"),
- }, logger)
- return deployer, logger, err
+ })
+ return deployer, err
}
- case domain.DeployProviderTypeTencentCloudCDN, domain.DeployProviderTypeTencentCloudCLB, domain.DeployProviderTypeTencentCloudCOS, domain.DeployProviderTypeTencentCloudCSS, domain.DeployProviderTypeTencentCloudECDN, domain.DeployProviderTypeTencentCloudEO, domain.DeployProviderTypeTencentCloudSSLDeploy:
+ case domain.DeployProviderTypeTencentCloudCDN, domain.DeployProviderTypeTencentCloudCLB, domain.DeployProviderTypeTencentCloudCOS, domain.DeployProviderTypeTencentCloudCSS, domain.DeployProviderTypeTencentCloudECDN, domain.DeployProviderTypeTencentCloudEO, domain.DeployProviderTypeTencentCloudSSLDeploy, domain.DeployProviderTypeTencentCloudVOD, domain.DeployProviderTypeTencentCloudWAF:
{
access := domain.AccessConfigForTencentCloud{}
if err := maps.Populate(options.ProviderAccessConfig, &access); err != nil {
- return nil, nil, fmt.Errorf("failed to populate provider access config: %w", err)
+ return nil, fmt.Errorf("failed to populate provider access config: %w", err)
}
switch options.Provider {
case domain.DeployProviderTypeTencentCloudCDN:
- deployer, err := providerTencentCloudCDN.NewWithLogger(&providerTencentCloudCDN.TencentCloudCDNDeployerConfig{
+ deployer, err := pTencentCloudCDN.NewDeployer(&pTencentCloudCDN.DeployerConfig{
SecretId: access.SecretId,
SecretKey: access.SecretKey,
Domain: maps.GetValueAsString(options.ProviderDeployConfig, "domain"),
- }, logger)
- return deployer, logger, err
+ })
+ return deployer, err
case domain.DeployProviderTypeTencentCloudCLB:
- deployer, err := providerTencentCloudCLB.NewWithLogger(&providerTencentCloudCLB.TencentCloudCLBDeployerConfig{
+ deployer, err := pTencentCloudCLB.NewDeployer(&pTencentCloudCLB.DeployerConfig{
SecretId: access.SecretId,
SecretKey: access.SecretKey,
Region: maps.GetValueAsString(options.ProviderDeployConfig, "region"),
- ResourceType: providerTencentCloudCLB.DeployResourceType(maps.GetValueAsString(options.ProviderDeployConfig, "resourceType")),
+ ResourceType: pTencentCloudCLB.ResourceType(maps.GetValueAsString(options.ProviderDeployConfig, "resourceType")),
LoadbalancerId: maps.GetValueAsString(options.ProviderDeployConfig, "loadbalancerId"),
ListenerId: maps.GetValueAsString(options.ProviderDeployConfig, "listenerId"),
Domain: maps.GetValueAsString(options.ProviderDeployConfig, "domain"),
- }, logger)
- return deployer, logger, err
+ })
+ return deployer, err
case domain.DeployProviderTypeTencentCloudCOS:
- deployer, err := providerTencentCloudCOS.NewWithLogger(&providerTencentCloudCOS.TencentCloudCOSDeployerConfig{
+ deployer, err := pTencentCloudCOS.NewDeployer(&pTencentCloudCOS.DeployerConfig{
SecretId: access.SecretId,
SecretKey: access.SecretKey,
Region: maps.GetValueAsString(options.ProviderDeployConfig, "region"),
Bucket: maps.GetValueAsString(options.ProviderDeployConfig, "bucket"),
Domain: maps.GetValueAsString(options.ProviderDeployConfig, "domain"),
- }, logger)
- return deployer, logger, err
+ })
+ return deployer, err
case domain.DeployProviderTypeTencentCloudCSS:
- deployer, err := providerTencentCloudCSS.NewWithLogger(&providerTencentCloudCSS.TencentCloudCSSDeployerConfig{
+ deployer, err := pTencentCloudCSS.NewDeployer(&pTencentCloudCSS.DeployerConfig{
SecretId: access.SecretId,
SecretKey: access.SecretKey,
Domain: maps.GetValueAsString(options.ProviderDeployConfig, "domain"),
- }, logger)
- return deployer, logger, err
+ })
+ return deployer, err
case domain.DeployProviderTypeTencentCloudECDN:
- deployer, err := providerTencentCloudECDN.NewWithLogger(&providerTencentCloudECDN.TencentCloudECDNDeployerConfig{
+ deployer, err := pTencentCloudECDN.NewDeployer(&pTencentCloudECDN.DeployerConfig{
SecretId: access.SecretId,
SecretKey: access.SecretKey,
Domain: maps.GetValueAsString(options.ProviderDeployConfig, "domain"),
- }, logger)
- return deployer, logger, err
+ })
+ return deployer, err
case domain.DeployProviderTypeTencentCloudEO:
- deployer, err := providerTencentCloudEO.NewWithLogger(&providerTencentCloudEO.TencentCloudEODeployerConfig{
+ deployer, err := pTencentCloudEO.NewDeployer(&pTencentCloudEO.DeployerConfig{
SecretId: access.SecretId,
SecretKey: access.SecretKey,
ZoneId: maps.GetValueAsString(options.ProviderDeployConfig, "zoneId"),
Domain: maps.GetValueAsString(options.ProviderDeployConfig, "domain"),
- }, logger)
- return deployer, logger, err
+ })
+ return deployer, err
case domain.DeployProviderTypeTencentCloudSSLDeploy:
- deployer, err := providerTencentCloudSSLDeploy.NewWithLogger(&providerTencentCloudSSLDeploy.TencentCloudSSLDeployDeployerConfig{
+ deployer, err := pTencentCloudSSLDeploy.NewDeployer(&pTencentCloudSSLDeploy.DeployerConfig{
SecretId: access.SecretId,
SecretKey: access.SecretKey,
Region: maps.GetValueAsString(options.ProviderDeployConfig, "region"),
ResourceType: maps.GetValueAsString(options.ProviderDeployConfig, "resourceType"),
ResourceIds: slices.Filter(strings.Split(maps.GetValueAsString(options.ProviderDeployConfig, "resourceIds"), ";"), func(s string) bool { return s != "" }),
- }, logger)
- return deployer, logger, err
+ })
+ return deployer, err
+
+ case domain.DeployProviderTypeTencentCloudVOD:
+ deployer, err := pTencentCloudVOD.NewDeployer(&pTencentCloudVOD.DeployerConfig{
+ SecretId: access.SecretId,
+ SecretKey: access.SecretKey,
+ SubAppId: maps.GetValueAsInt64(options.ProviderDeployConfig, "subAppId"),
+ Domain: maps.GetValueAsString(options.ProviderDeployConfig, "domain"),
+ })
+ return deployer, err
+
+ case domain.DeployProviderTypeTencentCloudWAF:
+ deployer, err := pTencentCloudWAF.NewDeployer(&pTencentCloudWAF.DeployerConfig{
+ SecretId: access.SecretId,
+ SecretKey: access.SecretKey,
+ Domain: maps.GetValueAsString(options.ProviderDeployConfig, "domain"),
+ DomainId: maps.GetValueAsString(options.ProviderDeployConfig, "domainId"),
+ InstanceId: maps.GetValueAsString(options.ProviderDeployConfig, "instanceId"),
+ })
+ return deployer, err
default:
break
@@ -486,86 +688,96 @@ func createDeployer(options *deployerOptions) (deployer.Deployer, logger.Logger,
{
access := domain.AccessConfigForUCloud{}
if err := maps.Populate(options.ProviderAccessConfig, &access); err != nil {
- return nil, nil, fmt.Errorf("failed to populate provider access config: %w", err)
+ return nil, fmt.Errorf("failed to populate provider access config: %w", err)
}
switch options.Provider {
case domain.DeployProviderTypeUCloudUCDN:
- deployer, err := providerUCloudUCDN.NewWithLogger(&providerUCloudUCDN.UCloudUCDNDeployerConfig{
+ deployer, err := pUCloudUCDN.NewDeployer(&pUCloudUCDN.DeployerConfig{
PrivateKey: access.PrivateKey,
PublicKey: access.PublicKey,
ProjectId: access.ProjectId,
DomainId: maps.GetValueAsString(options.ProviderDeployConfig, "domainId"),
- }, logger)
- return deployer, logger, err
+ })
+ return deployer, err
case domain.DeployProviderTypeUCloudUS3:
- deployer, err := providerUCloudUS3.NewWithLogger(&providerUCloudUS3.UCloudUS3DeployerConfig{
+ deployer, err := pUCloudUS3.NewDeployer(&pUCloudUS3.DeployerConfig{
PrivateKey: access.PrivateKey,
PublicKey: access.PublicKey,
ProjectId: access.ProjectId,
Region: maps.GetValueAsString(options.ProviderDeployConfig, "region"),
Bucket: maps.GetValueAsString(options.ProviderDeployConfig, "bucket"),
Domain: maps.GetValueAsString(options.ProviderDeployConfig, "domain"),
- }, logger)
- return deployer, logger, err
+ })
+ return deployer, err
default:
break
}
}
- case domain.DeployProviderTypeVolcEngineCDN, domain.DeployProviderTypeVolcEngineCLB, domain.DeployProviderTypeVolcEngineDCDN, domain.DeployProviderTypeVolcEngineLive, domain.DeployProviderTypeVolcEngineTOS:
+ case domain.DeployProviderTypeVolcEngineCDN, domain.DeployProviderTypeVolcEngineCLB, domain.DeployProviderTypeVolcEngineDCDN, domain.DeployProviderTypeVolcEngineImageX, domain.DeployProviderTypeVolcEngineLive, domain.DeployProviderTypeVolcEngineTOS:
{
access := domain.AccessConfigForVolcEngine{}
if err := maps.Populate(options.ProviderAccessConfig, &access); err != nil {
- return nil, nil, fmt.Errorf("failed to populate provider access config: %w", err)
+ return nil, fmt.Errorf("failed to populate provider access config: %w", err)
}
switch options.Provider {
case domain.DeployProviderTypeVolcEngineCDN:
- deployer, err := providerVolcEngineCDN.NewWithLogger(&providerVolcEngineCDN.VolcEngineCDNDeployerConfig{
+ deployer, err := pVolcEngineCDN.NewDeployer(&pVolcEngineCDN.DeployerConfig{
AccessKeyId: access.AccessKeyId,
AccessKeySecret: access.SecretAccessKey,
Domain: maps.GetValueAsString(options.ProviderDeployConfig, "domain"),
- }, logger)
- return deployer, logger, err
+ })
+ return deployer, err
case domain.DeployProviderTypeVolcEngineCLB:
- deployer, err := providerVolcEngineCLB.NewWithLogger(&providerVolcEngineCLB.VolcEngineCLBDeployerConfig{
+ deployer, err := pVolcEngineCLB.NewDeployer(&pVolcEngineCLB.DeployerConfig{
AccessKeyId: access.AccessKeyId,
AccessKeySecret: access.SecretAccessKey,
Region: maps.GetValueAsString(options.ProviderDeployConfig, "region"),
- ResourceType: providerVolcEngineCLB.DeployResourceType(maps.GetValueAsString(options.ProviderDeployConfig, "resourceType")),
+ ResourceType: pVolcEngineCLB.ResourceType(maps.GetValueAsString(options.ProviderDeployConfig, "resourceType")),
ListenerId: maps.GetValueAsString(options.ProviderDeployConfig, "listenerId"),
- }, logger)
- return deployer, logger, err
+ })
+ return deployer, err
case domain.DeployProviderTypeVolcEngineDCDN:
- deployer, err := providerVolcEngineDCDN.NewWithLogger(&providerVolcEngineDCDN.VolcEngineDCDNDeployerConfig{
+ deployer, err := pVolcEngineDCDN.NewDeployer(&pVolcEngineDCDN.DeployerConfig{
AccessKeyId: access.AccessKeyId,
AccessKeySecret: access.SecretAccessKey,
Domain: maps.GetValueAsString(options.ProviderDeployConfig, "domain"),
- }, logger)
- return deployer, logger, err
+ })
+ return deployer, err
+
+ case domain.DeployProviderTypeVolcEngineImageX:
+ deployer, err := pVolcEngineImageX.NewDeployer(&pVolcEngineImageX.DeployerConfig{
+ AccessKeyId: access.AccessKeyId,
+ AccessKeySecret: access.SecretAccessKey,
+ Region: maps.GetValueAsString(options.ProviderDeployConfig, "region"),
+ ServiceId: maps.GetValueAsString(options.ProviderDeployConfig, "serviceId"),
+ Domain: maps.GetValueAsString(options.ProviderDeployConfig, "domain"),
+ })
+ return deployer, err
case domain.DeployProviderTypeVolcEngineLive:
- deployer, err := providerVolcEngineLive.NewWithLogger(&providerVolcEngineLive.VolcEngineLiveDeployerConfig{
+ deployer, err := pVolcEngineLive.NewDeployer(&pVolcEngineLive.DeployerConfig{
AccessKeyId: access.AccessKeyId,
AccessKeySecret: access.SecretAccessKey,
Domain: maps.GetValueAsString(options.ProviderDeployConfig, "domain"),
- }, logger)
- return deployer, logger, err
+ })
+ return deployer, err
case domain.DeployProviderTypeVolcEngineTOS:
- deployer, err := providerVolcEngineTOS.NewWithLogger(&providerVolcEngineTOS.VolcEngineTOSDeployerConfig{
+ deployer, err := pVolcEngineTOS.NewDeployer(&pVolcEngineTOS.DeployerConfig{
AccessKeyId: access.AccessKeyId,
AccessKeySecret: access.SecretAccessKey,
Region: maps.GetValueAsString(options.ProviderDeployConfig, "region"),
Bucket: maps.GetValueAsString(options.ProviderDeployConfig, "bucket"),
Domain: maps.GetValueAsString(options.ProviderDeployConfig, "domain"),
- }, logger)
- return deployer, logger, err
+ })
+ return deployer, err
default:
break
@@ -576,16 +788,16 @@ func createDeployer(options *deployerOptions) (deployer.Deployer, logger.Logger,
{
access := domain.AccessConfigForWebhook{}
if err := maps.Populate(options.ProviderAccessConfig, &access); err != nil {
- return nil, nil, fmt.Errorf("failed to populate provider access config: %w", err)
+ return nil, fmt.Errorf("failed to populate provider access config: %w", err)
}
- deployer, err := providerWebhook.NewWithLogger(&providerWebhook.WebhookDeployerConfig{
+ deployer, err := pWebhook.NewDeployer(&pWebhook.DeployerConfig{
WebhookUrl: access.Url,
WebhookData: maps.GetValueAsString(options.ProviderDeployConfig, "webhookData"),
- }, logger)
- return deployer, logger, err
+ })
+ return deployer, err
}
}
- return nil, 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 e9df61d2..25df3210 100644
--- a/internal/domain/access.go
+++ b/internal/domain/access.go
@@ -53,6 +53,10 @@ type AccessConfigForBaiduCloud struct {
SecretAccessKey string `json:"secretAccessKey"`
}
+type AccessConfigForBaishan struct {
+ ApiToken string `json:"apiToken"`
+}
+
type AccessConfigForBaotaPanel struct {
ApiUrl string `json:"apiUrl"`
ApiKey string `json:"apiKey"`
@@ -63,6 +67,16 @@ type AccessConfigForBytePlus struct {
SecretKey string `json:"secretKey"`
}
+type AccessConfigForCacheFly struct {
+ ApiToken string `json:"apiToken"`
+}
+
+type AccessConfigForCdnfly struct {
+ ApiUrl string `json:"apiUrl"`
+ ApiKey string `json:"apiKey"`
+ ApiSecret string `json:"apiSecret"`
+}
+
type AccessConfigForCloudflare struct {
DnsApiToken string `json:"dnsApiToken"`
}
@@ -72,6 +86,16 @@ type AccessConfigForClouDNS struct {
AuthPassword string `json:"authPassword"`
}
+type AccessConfigForCMCCCloud struct {
+ AccessKeyId string `json:"accessKeyId"`
+ AccessKeySecret string `json:"accessKeySecret"`
+}
+
+type AccessConfigForDNSLA struct {
+ ApiId string `json:"apiId"`
+ ApiSecret string `json:"apiSecret"`
+}
+
type AccessConfigForDogeCloud struct {
AccessKey string `json:"accessKey"`
SecretKey string `json:"secretKey"`
@@ -82,6 +106,10 @@ type AccessConfigForEdgio struct {
ClientSecret string `json:"clientSecret"`
}
+type AccessConfigForGcore struct {
+ ApiToken string `json:"apiToken"`
+}
+
type AccessConfigForGname struct {
AppId string `json:"appId"`
AppKey string `json:"appKey"`
@@ -97,12 +125,22 @@ type AccessConfigForHuaweiCloud struct {
SecretAccessKey string `json:"secretAccessKey"`
}
-type AccessConfigForLocal struct{}
+type AccessConfigForJDCloud struct {
+ AccessKeyId string `json:"accessKeyId"`
+ AccessKeySecret string `json:"accessKeySecret"`
+}
type AccessConfigForKubernetes struct {
KubeConfig string `json:"kubeConfig,omitempty"`
}
+type AccessConfigForLocal struct{}
+
+type AccessConfigForNamecheap struct {
+ Username string `json:"username"`
+ ApiKey string `json:"apiKey"`
+}
+
type AccessConfigForNameDotCom struct {
Username string `json:"username"`
ApiToken string `json:"apiToken"`
@@ -130,6 +168,11 @@ type AccessConfigForRainYun struct {
ApiKey string `json:"apiKey"`
}
+type AccessConfigForSafeLine struct {
+ ApiUrl string `json:"apiUrl"`
+ ApiToken string `json:"apiToken"`
+}
+
type AccessConfigForSSH struct {
Host string `json:"host"`
Port int32 `json:"port"`
diff --git a/internal/domain/provider.go b/internal/domain/provider.go
index 350b3926..950abc08 100644
--- a/internal/domain/provider.go
+++ b/internal/domain/provider.go
@@ -16,33 +16,37 @@ const (
AccessProviderTypeAWS = AccessProviderType("aws")
AccessProviderTypeAzure = AccessProviderType("azure")
AccessProviderTypeBaiduCloud = AccessProviderType("baiducloud")
- AccessProviderTypeBaishan = AccessProviderType("baishan") // 白山云(预留)
+ AccessProviderTypeBaishan = AccessProviderType("baishan")
AccessProviderTypeBaotaPanel = AccessProviderType("baotapanel")
AccessProviderTypeBytePlus = AccessProviderType("byteplus")
- AccessProviderTypeCacheFly = AccessProviderType("cachefly") // CacheFly(预留)
- AccessProviderTypeCdnfly = AccessProviderType("cdnfly") // Cdnly(预留)
+ AccessProviderTypeCacheFly = AccessProviderType("cachefly")
+ AccessProviderTypeCdnfly = AccessProviderType("cdnfly")
AccessProviderTypeCloudflare = AccessProviderType("cloudflare")
AccessProviderTypeClouDNS = AccessProviderType("cloudns")
- AccessProviderTypeCMCCCloud = AccessProviderType("cmcccloud") // 移动云(预留)
+ AccessProviderTypeCMCCCloud = AccessProviderType("cmcccloud")
AccessProviderTypeCTCCCloud = AccessProviderType("ctcccloud") // 联通云(预留)
AccessProviderTypeCUCCCloud = AccessProviderType("cucccloud") // 天翼云(预留)
+ AccessProviderTypeDNSLA = AccessProviderType("dnsla")
AccessProviderTypeDogeCloud = AccessProviderType("dogecloud")
AccessProviderTypeEdgio = AccessProviderType("edgio")
AccessProviderTypeFastly = AccessProviderType("fastly") // Fastly(预留)
AccessProviderTypeGname = AccessProviderType("gname")
- AccessProviderTypeGcore = AccessProviderType("gcore") // Gcore(预留)
+ AccessProviderTypeGcore = AccessProviderType("gcore")
AccessProviderTypeGoDaddy = AccessProviderType("godaddy")
AccessProviderTypeGoEdge = AccessProviderType("goedge") // GoEdge(预留)
AccessProviderTypeHuaweiCloud = AccessProviderType("huaweicloud")
+ AccessProviderTypeJDCloud = AccessProviderType("jdcloud")
AccessProviderTypeKubernetes = AccessProviderType("k8s")
AccessProviderTypeLocal = AccessProviderType("local")
+ AccessProviderTypeNamecheap = AccessProviderType("namecheap")
AccessProviderTypeNameDotCom = AccessProviderType("namedotcom")
AccessProviderTypeNameSilo = AccessProviderType("namesilo")
AccessProviderTypeNS1 = AccessProviderType("ns1")
AccessProviderTypePowerDNS = AccessProviderType("powerdns")
AccessProviderTypeQiniu = AccessProviderType("qiniu")
+ AccessProviderTypeQingCloud = AccessProviderType("qingcloud") // 青云(预留)
AccessProviderTypeRainYun = AccessProviderType("rainyun")
- AccessProviderTypeSafeLine = AccessProviderType("safeline") // 雷池(预留)
+ AccessProviderTypeSafeLine = AccessProviderType("safeline")
AccessProviderTypeSSH = AccessProviderType("ssh")
AccessProviderTypeTencentCloud = AccessProviderType("tencentcloud")
AccessProviderTypeUCloud = AccessProviderType("ucloud")
@@ -66,13 +70,22 @@ const (
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")
ApplyDNSProviderTypeCloudflare = ApplyDNSProviderType("cloudflare")
ApplyDNSProviderTypeClouDNS = ApplyDNSProviderType("cloudns")
+ ApplyDNSProviderTypeCMCCCloud = ApplyDNSProviderType("cmcccloud")
+ ApplyDNSProviderTypeDNSLA = ApplyDNSProviderType("dnsla")
+ 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")
@@ -104,19 +117,31 @@ const (
DeployProviderTypeAliyunLive = DeployProviderType("aliyun-live")
DeployProviderTypeAliyunNLB = DeployProviderType("aliyun-nlb")
DeployProviderTypeAliyunOSS = DeployProviderType("aliyun-oss")
+ DeployProviderTypeAliyunVOD = DeployProviderType("aliyun-vod")
DeployProviderTypeAliyunWAF = DeployProviderType("aliyun-waf")
DeployProviderTypeAWSCloudFront = DeployProviderType("aws-cloudfront")
DeployProviderTypeBaiduCloudCDN = DeployProviderType("baiducloud-cdn")
+ DeployProviderTypeBaishanCDN = DeployProviderType("baishan-cdn")
+ DeployProviderTypeBaotaPanelConsole = DeployProviderType("baotapanel-console")
DeployProviderTypeBaotaPanelSite = DeployProviderType("baotapanel-site")
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")
+ 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")
DeployProviderTypeQiniuPili = DeployProviderType("qiniu-pili")
+ DeployProviderTypeSafeLine = DeployProviderType("safeline")
DeployProviderTypeSSH = DeployProviderType("ssh")
DeployProviderTypeTencentCloudCDN = DeployProviderType("tencentcloud-cdn")
DeployProviderTypeTencentCloudCLB = DeployProviderType("tencentcloud-clb")
@@ -125,11 +150,14 @@ const (
DeployProviderTypeTencentCloudECDN = DeployProviderType("tencentcloud-ecdn")
DeployProviderTypeTencentCloudEO = DeployProviderType("tencentcloud-eo")
DeployProviderTypeTencentCloudSSLDeploy = DeployProviderType("tencentcloud-ssldeploy")
+ DeployProviderTypeTencentCloudVOD = DeployProviderType("tencentcloud-vod")
+ DeployProviderTypeTencentCloudWAF = DeployProviderType("tencentcloud-waf")
DeployProviderTypeUCloudUCDN = DeployProviderType("ucloud-ucdn")
DeployProviderTypeUCloudUS3 = DeployProviderType("ucloud-us3")
DeployProviderTypeVolcEngineCDN = DeployProviderType("volcengine-cdn")
DeployProviderTypeVolcEngineCLB = DeployProviderType("volcengine-clb")
DeployProviderTypeVolcEngineDCDN = DeployProviderType("volcengine-dcdn")
+ DeployProviderTypeVolcEngineImageX = DeployProviderType("volcengine-imagex")
DeployProviderTypeVolcEngineLive = DeployProviderType("volcengine-live")
DeployProviderTypeVolcEngineTOS = DeployProviderType("volcengine-tos")
DeployProviderTypeWebhook = DeployProviderType("webhook")
diff --git a/internal/notify/providers.go b/internal/notify/providers.go
index 6483a7a0..6e18a84c 100644
--- a/internal/notify/providers.go
+++ b/internal/notify/providers.go
@@ -5,14 +5,14 @@ import (
"github.com/usual2970/certimate/internal/domain"
"github.com/usual2970/certimate/internal/pkg/core/notifier"
- providerBark "github.com/usual2970/certimate/internal/pkg/core/notifier/providers/bark"
- providerDingTalk "github.com/usual2970/certimate/internal/pkg/core/notifier/providers/dingtalk"
- providerEmail "github.com/usual2970/certimate/internal/pkg/core/notifier/providers/email"
- providerLark "github.com/usual2970/certimate/internal/pkg/core/notifier/providers/lark"
- providerServerChan "github.com/usual2970/certimate/internal/pkg/core/notifier/providers/serverchan"
- providerTelegram "github.com/usual2970/certimate/internal/pkg/core/notifier/providers/telegram"
- providerWebhook "github.com/usual2970/certimate/internal/pkg/core/notifier/providers/webhook"
- providerWeCom "github.com/usual2970/certimate/internal/pkg/core/notifier/providers/wecom"
+ 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"
+ pLark "github.com/usual2970/certimate/internal/pkg/core/notifier/providers/lark"
+ 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/maps"
)
@@ -23,19 +23,19 @@ func createNotifier(channel domain.NotifyChannelType, channelConfig map[string]a
*/
switch channel {
case domain.NotifyChannelTypeBark:
- return providerBark.New(&providerBark.BarkNotifierConfig{
+ return pBark.NewNotifier(&pBark.NotifierConfig{
DeviceKey: maps.GetValueAsString(channelConfig, "deviceKey"),
ServerUrl: maps.GetValueAsString(channelConfig, "serverUrl"),
})
case domain.NotifyChannelTypeDingTalk:
- return providerDingTalk.New(&providerDingTalk.DingTalkNotifierConfig{
+ return pDingTalk.NewNotifier(&pDingTalk.NotifierConfig{
AccessToken: maps.GetValueAsString(channelConfig, "accessToken"),
Secret: maps.GetValueAsString(channelConfig, "secret"),
})
case domain.NotifyChannelTypeEmail:
- return providerEmail.New(&providerEmail.EmailNotifierConfig{
+ return pEmail.NewNotifier(&pEmail.NotifierConfig{
SmtpHost: maps.GetValueAsString(channelConfig, "smtpHost"),
SmtpPort: maps.GetValueAsInt32(channelConfig, "smtpPort"),
SmtpTLS: maps.GetValueOrDefaultAsBool(channelConfig, "smtpTLS", true),
@@ -46,28 +46,28 @@ func createNotifier(channel domain.NotifyChannelType, channelConfig map[string]a
})
case domain.NotifyChannelTypeLark:
- return providerLark.New(&providerLark.LarkNotifierConfig{
+ return pLark.NewNotifier(&pLark.NotifierConfig{
WebhookUrl: maps.GetValueAsString(channelConfig, "webhookUrl"),
})
case domain.NotifyChannelTypeServerChan:
- return providerServerChan.New(&providerServerChan.ServerChanNotifierConfig{
+ return pServerChan.NewNotifier(&pServerChan.NotifierConfig{
Url: maps.GetValueAsString(channelConfig, "url"),
})
case domain.NotifyChannelTypeTelegram:
- return providerTelegram.New(&providerTelegram.TelegramNotifierConfig{
+ return pTelegram.NewNotifier(&pTelegram.NotifierConfig{
ApiToken: maps.GetValueAsString(channelConfig, "apiToken"),
ChatId: maps.GetValueAsInt64(channelConfig, "chatId"),
})
case domain.NotifyChannelTypeWebhook:
- return providerWebhook.New(&providerWebhook.WebhookNotifierConfig{
+ return pWebhook.NewNotifier(&pWebhook.NotifierConfig{
Url: maps.GetValueAsString(channelConfig, "url"),
})
case domain.NotifyChannelTypeWeCom:
- return providerWeCom.New(&providerWeCom.WeComNotifierConfig{
+ return pWeCom.NewNotifier(&pWeCom.NotifierConfig{
WebhookUrl: maps.GetValueAsString(channelConfig, "webhookUrl"),
})
}
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 a25c13bb..ab2b11a6 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,7 +1,6 @@
package acmehttpreq
import (
- "errors"
"net/url"
"time"
@@ -9,7 +8,7 @@ import (
"github.com/go-acme/lego/v4/providers/dns/httpreq"
)
-type ACMEHttpReqApplicantConfig struct {
+type ChallengeProviderConfig struct {
Endpoint string `json:"endpoint"`
Mode string `json:"mode"`
Username string `json:"username"`
@@ -17,9 +16,9 @@ type ACMEHttpReqApplicantConfig struct {
DnsPropagationTimeout int32 `json:"dnsPropagationTimeout,omitempty"`
}
-func NewChallengeProvider(config *ACMEHttpReqApplicantConfig) (challenge.Provider, error) {
+func NewChallengeProvider(config *ChallengeProviderConfig) (challenge.Provider, error) {
if config == nil {
- return nil, errors.New("config is nil")
+ panic("config is nil")
}
endpoint, _ := url.Parse(config.Endpoint)
diff --git a/internal/pkg/core/applicant/acme-dns-01/lego-providers/aliyun/aliyun.go b/internal/pkg/core/applicant/acme-dns-01/lego-providers/aliyun/aliyun.go
index 6f6d2d89..8f5cc56b 100644
--- a/internal/pkg/core/applicant/acme-dns-01/lego-providers/aliyun/aliyun.go
+++ b/internal/pkg/core/applicant/acme-dns-01/lego-providers/aliyun/aliyun.go
@@ -1,23 +1,22 @@
package aliyun
import (
- "errors"
"time"
"github.com/go-acme/lego/v4/challenge"
"github.com/go-acme/lego/v4/providers/dns/alidns"
)
-type AliyunApplicantConfig struct {
+type ChallengeProviderConfig struct {
AccessKeyId string `json:"accessKeyId"`
AccessKeySecret string `json:"accessKeySecret"`
DnsPropagationTimeout int32 `json:"dnsPropagationTimeout,omitempty"`
DnsTTL int32 `json:"dnsTTL,omitempty"`
}
-func NewChallengeProvider(config *AliyunApplicantConfig) (challenge.Provider, error) {
+func NewChallengeProvider(config *ChallengeProviderConfig) (challenge.Provider, error) {
if config == nil {
- return nil, errors.New("config is nil")
+ panic("config is nil")
}
providerConfig := alidns.NewDefaultConfig()
diff --git a/internal/pkg/core/applicant/acme-dns-01/lego-providers/aws-route53/aws-route53.go b/internal/pkg/core/applicant/acme-dns-01/lego-providers/aws-route53/aws-route53.go
index 6799885f..be1cfecf 100644
--- a/internal/pkg/core/applicant/acme-dns-01/lego-providers/aws-route53/aws-route53.go
+++ b/internal/pkg/core/applicant/acme-dns-01/lego-providers/aws-route53/aws-route53.go
@@ -1,14 +1,13 @@
package awsroute53
import (
- "errors"
"time"
"github.com/go-acme/lego/v4/challenge"
"github.com/go-acme/lego/v4/providers/dns/route53"
)
-type AWSRoute53ApplicantConfig struct {
+type ChallengeProviderConfig struct {
AccessKeyId string `json:"accessKeyId"`
SecretAccessKey string `json:"secretAccessKey"`
Region string `json:"region"`
@@ -17,9 +16,9 @@ type AWSRoute53ApplicantConfig struct {
DnsTTL int32 `json:"dnsTTL,omitempty"`
}
-func NewChallengeProvider(config *AWSRoute53ApplicantConfig) (challenge.Provider, error) {
+func NewChallengeProvider(config *ChallengeProviderConfig) (challenge.Provider, error) {
if config == nil {
- return nil, errors.New("config is nil")
+ panic("config is nil")
}
providerConfig := route53.NewDefaultConfig()
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 7cfce4a7..bf36f3fb 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
@@ -1,7 +1,6 @@
package azuredns
import (
- "errors"
"fmt"
"strings"
"time"
@@ -11,7 +10,7 @@ import (
"github.com/go-acme/lego/v4/providers/dns/azuredns"
)
-type AzureDNSApplicantConfig struct {
+type ChallengeProviderConfig struct {
TenantId string `json:"tenantId"`
ClientId string `json:"clientId"`
ClientSecret string `json:"clientSecret"`
@@ -20,9 +19,9 @@ type AzureDNSApplicantConfig struct {
DnsTTL int32 `json:"dnsTTL,omitempty"`
}
-func NewChallengeProvider(config *AzureDNSApplicantConfig) (challenge.Provider, error) {
+func NewChallengeProvider(config *ChallengeProviderConfig) (challenge.Provider, error) {
if config == nil {
- return nil, errors.New("config is nil")
+ panic("config is nil")
}
providerConfig := azuredns.NewDefaultConfig()
diff --git a/internal/pkg/core/applicant/acme-dns-01/lego-providers/baiducloud/baiducloud.go b/internal/pkg/core/applicant/acme-dns-01/lego-providers/baiducloud/baiducloud.go
new file mode 100644
index 00000000..ac63665e
--- /dev/null
+++ b/internal/pkg/core/applicant/acme-dns-01/lego-providers/baiducloud/baiducloud.go
@@ -0,0 +1,39 @@
+package baiducloud
+
+import (
+ "time"
+
+ "github.com/go-acme/lego/v4/challenge"
+
+ internal "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/baiducloud/internal"
+)
+
+type ChallengeProviderConfig struct {
+ AccessKeyId string `json:"accessKeyId"`
+ SecretAccessKey string `json:"secretAccessKey"`
+ 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.AccessKeyID = config.AccessKeyId
+ providerConfig.SecretAccessKey = config.SecretAccessKey
+ 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/baiducloud/internal/lego.go b/internal/pkg/core/applicant/acme-dns-01/lego-providers/baiducloud/internal/lego.go
new file mode 100644
index 00000000..0d3f9c66
--- /dev/null
+++ b/internal/pkg/core/applicant/acme-dns-01/lego-providers/baiducloud/internal/lego.go
@@ -0,0 +1,204 @@
+package lego_baiducloud
+
+import (
+ "errors"
+ "fmt"
+ "strings"
+ "time"
+
+ bceDns "github.com/baidubce/bce-sdk-go/services/dns"
+ "github.com/go-acme/lego/v4/challenge"
+ "github.com/go-acme/lego/v4/challenge/dns01"
+ "github.com/go-acme/lego/v4/platform/config/env"
+ "github.com/google/uuid"
+)
+
+const (
+ envNamespace = "BAIDUCLOUD_"
+
+ EnvAccessKeyID = envNamespace + "ACCESS_KEY_ID"
+ EnvSecretAccessKey = envNamespace + "SECRET_ACCESS_KEY"
+
+ EnvTTL = envNamespace + "TTL"
+ EnvPropagationTimeout = envNamespace + "PROPAGATION_TIMEOUT"
+ EnvPollingInterval = envNamespace + "POLLING_INTERVAL"
+ EnvHTTPTimeout = envNamespace + "HTTP_TIMEOUT"
+)
+
+var _ challenge.ProviderTimeout = (*DNSProvider)(nil)
+
+type Config struct {
+ AccessKeyID string
+ SecretAccessKey string
+
+ PropagationTimeout time.Duration
+ PollingInterval time.Duration
+ TTL int32
+ HTTPTimeout time.Duration
+}
+
+type DNSProvider struct {
+ client *bceDns.Client
+ config *Config
+}
+
+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(EnvAccessKeyID, EnvSecretAccessKey)
+ if err != nil {
+ return nil, fmt.Errorf("baiducloud: %w", err)
+ }
+
+ config := NewDefaultConfig()
+ config.AccessKeyID = values[EnvAccessKeyID]
+ config.SecretAccessKey = values[EnvSecretAccessKey]
+
+ return NewDNSProviderConfig(config)
+}
+
+func NewDNSProviderConfig(config *Config) (*DNSProvider, error) {
+ if config == nil {
+ return nil, errors.New("baiducloud: the configuration of the DNS provider is nil")
+ }
+
+ client, err := bceDns.NewClient(config.AccessKeyID, config.SecretAccessKey, "")
+ if err != nil {
+ return nil, err
+ } else {
+ if client.Config != nil {
+ client.Config.ConnectionTimeoutInMillis = int(config.HTTPTimeout.Milliseconds())
+ }
+ }
+
+ 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("baiducloud: %w", err)
+ }
+
+ subDomain, err := dns01.ExtractSubDomain(info.EffectiveFQDN, authZone)
+ if err != nil {
+ return fmt.Errorf("baiducloud: %w", err)
+ }
+
+ if err := d.addOrUpdateDNSRecord(dns01.UnFqdn(authZone), subDomain, info.Value); err != nil {
+ return fmt.Errorf("baiducloud: %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("baiducloud: %w", err)
+ }
+
+ subDomain, err := dns01.ExtractSubDomain(info.EffectiveFQDN, authZone)
+ if err != nil {
+ return fmt.Errorf("baiducloud: %w", err)
+ }
+
+ if err := d.removeDNSRecord(dns01.UnFqdn(authZone), subDomain); err != nil {
+ return fmt.Errorf("baiducloud: %w", err)
+ }
+
+ return nil
+}
+
+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) {
+ pageMarker := ""
+ pageSize := 1000
+ for {
+ request := &bceDns.ListRecordRequest{}
+ request.Rr = subDomain
+ request.Marker = pageMarker
+ request.MaxKeys = pageSize
+
+ response, err := d.client.ListRecord(zoneName, request)
+ if err != nil {
+ return nil, err
+ }
+
+ for _, record := range response.Records {
+ if record.Type == "TXT" && record.Rr == subDomain {
+ return &record, nil
+ }
+ }
+
+ if len(response.Records) < pageSize {
+ break
+ }
+
+ pageMarker = response.NextMarker
+ }
+
+ return nil, nil
+}
+
+func (d *DNSProvider) addOrUpdateDNSRecord(zoneName, subDomain, value string) error {
+ record, err := d.getDNSRecord(zoneName, subDomain)
+ if err != nil {
+ return err
+ }
+
+ if record == nil {
+ request := &bceDns.CreateRecordRequest{
+ Type: "TXT",
+ Rr: subDomain,
+ Value: value,
+ Ttl: &d.config.TTL,
+ }
+ err := d.client.CreateRecord(zoneName, request, d.generateClientToken())
+ return err
+ } else {
+ request := &bceDns.UpdateRecordRequest{
+ Type: "TXT",
+ Rr: subDomain,
+ Value: value,
+ Ttl: &d.config.TTL,
+ }
+ err := d.client.UpdateRecord(zoneName, record.Id, request, d.generateClientToken())
+ return err
+ }
+}
+
+func (d *DNSProvider) removeDNSRecord(zoneName, subDomain string) error {
+ record, err := d.getDNSRecord(zoneName, subDomain)
+ if err != nil {
+ return err
+ }
+
+ if record == nil {
+ return nil
+ } else {
+ err = d.client.DeleteRecord(zoneName, record.Id, d.generateClientToken())
+ return err
+ }
+}
+
+func (d *DNSProvider) generateClientToken() string {
+ return strings.ReplaceAll(uuid.New().String(), "-", "")
+}
diff --git a/internal/pkg/core/applicant/acme-dns-01/lego-providers/cloudflare/cloudflare.go b/internal/pkg/core/applicant/acme-dns-01/lego-providers/cloudflare/cloudflare.go
index cea32e94..9782b39b 100644
--- a/internal/pkg/core/applicant/acme-dns-01/lego-providers/cloudflare/cloudflare.go
+++ b/internal/pkg/core/applicant/acme-dns-01/lego-providers/cloudflare/cloudflare.go
@@ -1,22 +1,21 @@
package cloudflare
import (
- "errors"
"time"
"github.com/go-acme/lego/v4/challenge"
"github.com/go-acme/lego/v4/providers/dns/cloudflare"
)
-type CloudflareApplicantConfig struct {
+type ChallengeProviderConfig struct {
DnsApiToken string `json:"dnsApiToken"`
DnsPropagationTimeout int32 `json:"dnsPropagationTimeout,omitempty"`
DnsTTL int32 `json:"dnsTTL,omitempty"`
}
-func NewChallengeProvider(config *CloudflareApplicantConfig) (challenge.Provider, error) {
+func NewChallengeProvider(config *ChallengeProviderConfig) (challenge.Provider, error) {
if config == nil {
- return nil, errors.New("config is nil")
+ panic("config is nil")
}
providerConfig := cloudflare.NewDefaultConfig()
diff --git a/internal/pkg/core/applicant/acme-dns-01/lego-providers/cloudns/cloudns.go b/internal/pkg/core/applicant/acme-dns-01/lego-providers/cloudns/cloudns.go
index 09aac6df..dc351bd3 100644
--- a/internal/pkg/core/applicant/acme-dns-01/lego-providers/cloudns/cloudns.go
+++ b/internal/pkg/core/applicant/acme-dns-01/lego-providers/cloudns/cloudns.go
@@ -1,23 +1,22 @@
package cloudns
import (
- "errors"
"time"
"github.com/go-acme/lego/v4/challenge"
"github.com/go-acme/lego/v4/providers/dns/cloudns"
)
-type ClouDNSApplicantConfig struct {
+type ChallengeProviderConfig struct {
AuthId string `json:"authId"`
AuthPassword string `json:"authPassword"`
DnsPropagationTimeout int32 `json:"dnsPropagationTimeout,omitempty"`
DnsTTL int32 `json:"dnsTTL,omitempty"`
}
-func NewChallengeProvider(config *ClouDNSApplicantConfig) (challenge.Provider, error) {
+func NewChallengeProvider(config *ChallengeProviderConfig) (challenge.Provider, error) {
if config == nil {
- return nil, errors.New("config is nil")
+ panic("config is nil")
}
providerConfig := cloudns.NewDefaultConfig()
diff --git a/internal/pkg/core/applicant/acme-dns-01/lego-providers/cmcccloud/cmcccloud.go b/internal/pkg/core/applicant/acme-dns-01/lego-providers/cmcccloud/cmcccloud.go
new file mode 100644
index 00000000..ba0721fd
--- /dev/null
+++ b/internal/pkg/core/applicant/acme-dns-01/lego-providers/cmcccloud/cmcccloud.go
@@ -0,0 +1,40 @@
+package cmcccloud
+
+import (
+ "errors"
+ "time"
+
+ "github.com/go-acme/lego/v4/challenge"
+
+ "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/cmcccloud/internal"
+)
+
+type ChallengeProviderConfig struct {
+ AccessKeyId string `json:"accessKeyId"`
+ AccessKeySecret string `json:"accessKeySecret"`
+ DnsPropagationTimeout int32 `json:"dnsPropagationTimeout,omitempty"`
+ DnsTTL int32 `json:"dnsTTL,omitempty"`
+}
+
+func NewChallengeProvider(config *ChallengeProviderConfig) (challenge.Provider, error) {
+ if config == nil {
+ return nil, errors.New("config is nil")
+ }
+
+ providerConfig := internal.NewDefaultConfig()
+ providerConfig.AccessKey = config.AccessKeyId
+ providerConfig.SecretKey = config.AccessKeySecret
+ if config.DnsTTL != 0 {
+ providerConfig.TTL = config.DnsTTL
+ }
+ if config.DnsPropagationTimeout != 0 {
+ providerConfig.PropagationTimeout = time.Duration(config.DnsPropagationTimeout) * time.Second
+ }
+
+ 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/cmcccloud/internal/lego.go b/internal/pkg/core/applicant/acme-dns-01/lego-providers/cmcccloud/internal/lego.go
new file mode 100644
index 00000000..92ef6dfe
--- /dev/null
+++ b/internal/pkg/core/applicant/acme-dns-01/lego-providers/cmcccloud/internal/lego.go
@@ -0,0 +1,221 @@
+package internal
+
+import (
+ "encoding/json"
+ "errors"
+ "fmt"
+ "strings"
+ "time"
+
+ "github.com/go-acme/lego/v4/challenge"
+ "github.com/go-acme/lego/v4/challenge/dns01"
+ "github.com/go-acme/lego/v4/platform/config/env"
+ "gitlab.ecloud.com/ecloud/ecloudsdkclouddns"
+ "gitlab.ecloud.com/ecloud/ecloudsdkclouddns/model"
+ "gitlab.ecloud.com/ecloud/ecloudsdkcore/config"
+)
+
+const (
+ envNamespace = "CMCCCLOUD_"
+
+ EnvAccessKey = envNamespace + "ACCESS_KEY"
+ EnvSecretKey = envNamespace + "SECRET_KEY"
+ EnvTTL = envNamespace + "TTL"
+ EnvPropagationTimeout = envNamespace + "PROPAGATION_TIMEOUT"
+ EnvPollingInterval = envNamespace + "POLLING_INTERVAL"
+ EnvReadTimeOut = envNamespace + "READ_TIMEOUT"
+ EnvConnectTimeout = envNamespace + "CONNECT_TIMEOUT"
+)
+
+var _ challenge.ProviderTimeout = (*DNSProvider)(nil)
+
+type Config struct {
+ AccessKey string
+ SecretKey string
+ ReadTimeOut int
+ ConnectTimeout int
+ PropagationTimeout time.Duration
+ PollingInterval time.Duration
+ TTL int32
+}
+
+type DNSProvider struct {
+ client *ecloudsdkclouddns.Client
+ config *Config
+}
+
+func NewDefaultConfig() *Config {
+ return &Config{
+ ReadTimeOut: env.GetOrDefaultInt(EnvReadTimeOut, 30),
+ ConnectTimeout: env.GetOrDefaultInt(EnvConnectTimeout, 30),
+ TTL: int32(env.GetOrDefaultInt(EnvTTL, 600)),
+ PropagationTimeout: env.GetOrDefaultSecond(EnvPropagationTimeout, 2*time.Minute),
+ PollingInterval: env.GetOrDefaultSecond(EnvPollingInterval, dns01.DefaultPollingInterval),
+ }
+}
+
+func NewDNSProvider() (*DNSProvider, error) {
+ values, err := env.Get(EnvAccessKey, EnvSecretKey)
+ if err != nil {
+ return nil, fmt.Errorf("cmccecloud: %w", err)
+ }
+
+ cfg := NewDefaultConfig()
+ cfg.AccessKey = values[EnvAccessKey]
+ cfg.SecretKey = values[EnvSecretKey]
+
+ return NewDNSProviderConfig(cfg)
+}
+
+func NewDNSProviderConfig(cfg *Config) (*DNSProvider, error) {
+ if cfg == nil {
+ return nil, errors.New("cmccecloud: the configuration of the DNS provider is nil")
+ }
+
+ client := ecloudsdkclouddns.NewClient(&config.Config{
+ AccessKey: cfg.AccessKey,
+ SecretKey: cfg.SecretKey,
+ // 资源池常量见: https://ecloud.10086.cn/op-help-center/doc/article/54462
+ // 默认全局
+ PoolId: "CIDC-CORE-00",
+ ReadTimeOut: cfg.ReadTimeOut,
+ ConnectTimeout: cfg.ConnectTimeout,
+ })
+
+ return &DNSProvider{
+ client: client,
+ config: cfg,
+ }, nil
+}
+
+func (d *DNSProvider) Present(domain, token, keyAuth string) error {
+ info := dns01.GetChallengeInfo(domain, keyAuth)
+
+ zoneName, err := dns01.FindZoneByFqdn(info.EffectiveFQDN)
+ if err != nil {
+ return fmt.Errorf("cmccecloud: %w", err)
+ }
+
+ subDomain, err := dns01.ExtractSubDomain(info.EffectiveFQDN, 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 {
+ // add new record
+ resp, err := d.client.CreateRecordOpenapi(&model.CreateRecordOpenapiRequest{
+ CreateRecordOpenapiBody: &model.CreateRecordOpenapiBody{
+ LineId: "0", // 默认线路
+ Rr: subDomain,
+ DomainName: readDomain,
+ Description: "from certimate",
+ Type: model.CreateRecordOpenapiBodyTypeEnumTxt,
+ Value: info.Value,
+ Ttl: &d.config.TTL,
+ },
+ })
+ if err != nil {
+ return fmt.Errorf("lego: %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 nil
+ } else {
+ // update record
+ resp, err := d.client.ModifyRecordOpenapi(&model.ModifyRecordOpenapiRequest{
+ ModifyRecordOpenapiBody: &model.ModifyRecordOpenapiBody{
+ RecordId: record.RecordId,
+ Rr: subDomain,
+ DomainName: readDomain,
+ Description: "from certmate",
+ LineId: "0",
+ Type: model.ModifyRecordOpenapiBodyTypeEnumTxt,
+ Value: info.Value,
+ Ttl: &d.config.TTL,
+ },
+ })
+ if err != nil {
+ return fmt.Errorf("lego: %w", err)
+ }
+ if resp.State != model.ModifyRecordOpenapiResponseStateEnumOk {
+ return fmt.Errorf("lego: 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)
+ }
+ 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
+ }
+ 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
+}
+
+func (d *DNSProvider) Timeout() (timeout, interval time.Duration) {
+ return d.config.PropagationTimeout, d.config.PollingInterval
+}
+
+func (d *DNSProvider) getDomainRecord(domain string, rr string) (*model.ListRecordOpenapiResponseData, error) {
+ pageSize := int32(50)
+ page := int32(1)
+ for {
+ resp, err := d.client.ListRecordOpenapi(&model.ListRecordOpenapiRequest{
+ ListRecordOpenapiBody: &model.ListRecordOpenapiBody{
+ DomainName: domain,
+ },
+ ListRecordOpenapiQuery: &model.ListRecordOpenapiQuery{
+ PageSize: &pageSize,
+ Page: &page,
+ },
+ })
+ if err != nil {
+ return nil, err
+ }
+ if resp.State != model.ListRecordOpenapiResponseStateEnumOk {
+ respStr, _ := json.Marshal(resp)
+ return nil, fmt.Errorf("request error. %s", string(respStr))
+ }
+ if resp.Body.Data != nil {
+ for _, item := range *resp.Body.Data {
+ if item.Rr == rr {
+ return &item, nil
+ }
+ }
+ }
+ 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/dnsla.go b/internal/pkg/core/applicant/acme-dns-01/lego-providers/dnsla/dnsla.go
new file mode 100644
index 00000000..5b0bd977
--- /dev/null
+++ b/internal/pkg/core/applicant/acme-dns-01/lego-providers/dnsla/dnsla.go
@@ -0,0 +1,39 @@
+package dnsla
+
+import (
+ "time"
+
+ "github.com/go-acme/lego/v4/challenge"
+
+ internal "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/dnsla/internal"
+)
+
+type ChallengeProviderConfig struct {
+ ApiId string `json:"apiId"`
+ ApiSecret string `json:"apiSecret"`
+ 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.APIId = config.ApiId
+ providerConfig.APISecret = config.ApiSecret
+ if config.DnsPropagationTimeout != 0 {
+ providerConfig.PropagationTimeout = time.Duration(config.DnsPropagationTimeout) * time.Second
+ }
+ if config.DnsTTL != 0 {
+ providerConfig.TTL = int(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/dnsla/internal/lego.go b/internal/pkg/core/applicant/acme-dns-01/lego-providers/dnsla/internal/lego.go
new file mode 100644
index 00000000..1b9603bd
--- /dev/null
+++ b/internal/pkg/core/applicant/acme-dns-01/lego-providers/dnsla/internal/lego.go
@@ -0,0 +1,240 @@
+package lego_dnsla
+
+import (
+ "errors"
+ "fmt"
+ "strings"
+ "time"
+
+ "github.com/go-acme/lego/v4/challenge"
+ "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"
+)
+
+const (
+ envNamespace = "DNSLA_"
+
+ EnvAPIId = envNamespace + "API_ID"
+ EnvAPISecret = envNamespace + "API_KEY"
+
+ EnvTTL = envNamespace + "TTL"
+ EnvPropagationTimeout = envNamespace + "PROPAGATION_TIMEOUT"
+ EnvPollingInterval = envNamespace + "POLLING_INTERVAL"
+ EnvHTTPTimeout = envNamespace + "HTTP_TIMEOUT"
+)
+
+var _ challenge.ProviderTimeout = (*DNSProvider)(nil)
+
+type Config struct {
+ APIId string
+ APISecret string
+
+ PropagationTimeout time.Duration
+ PollingInterval time.Duration
+ TTL int
+ HTTPTimeout time.Duration
+}
+
+type DNSProvider struct {
+ client *dnslasdk.Client
+ config *Config
+}
+
+func NewDefaultConfig() *Config {
+ return &Config{
+ TTL: 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(EnvAPIId, EnvAPISecret)
+ if err != nil {
+ return nil, fmt.Errorf("dnsla: %w", err)
+ }
+
+ config := NewDefaultConfig()
+ config.APIId = values[EnvAPIId]
+ config.APISecret = values[EnvAPISecret]
+
+ return NewDNSProviderConfig(config)
+}
+
+func NewDNSProviderConfig(config *Config) (*DNSProvider, error) {
+ if config == nil {
+ return nil, errors.New("dnsla: the configuration of the DNS provider is nil")
+ }
+
+ client := dnslasdk.NewClient(config.APIId, config.APISecret).
+ WithTimeout(config.HTTPTimeout)
+
+ 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("dnsla: %w", err)
+ }
+
+ subDomain, err := dns01.ExtractSubDomain(info.EffectiveFQDN, authZone)
+ if err != nil {
+ return fmt.Errorf("dnsla: %w", err)
+ }
+
+ if err := d.addOrUpdateDNSRecord(dns01.UnFqdn(authZone), subDomain, info.Value); err != nil {
+ return fmt.Errorf("dnsla: %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("dnsla: %w", err)
+ }
+
+ subDomain, err := dns01.ExtractSubDomain(info.EffectiveFQDN, authZone)
+ if err != nil {
+ return fmt.Errorf("dnsla: %w", err)
+ }
+
+ if err := d.removeDNSRecord(dns01.UnFqdn(authZone), subDomain); err != nil {
+ return fmt.Errorf("dnsla: %w", err)
+ }
+
+ return nil
+}
+
+func (d *DNSProvider) Timeout() (timeout, interval time.Duration) {
+ return d.config.PropagationTimeout, d.config.PollingInterval
+}
+
+func (d *DNSProvider) getDNSZone(zoneName string) (*dnslasdk.DomainInfo, error) {
+ pageIndex := 1
+ pageSize := 100
+ for {
+ request := &dnslasdk.ListDomainsRequest{
+ PageIndex: int32(pageIndex),
+ PageSize: int32(pageSize),
+ }
+ response, err := d.client.ListDomains(request)
+ if err != nil {
+ return nil, err
+ }
+
+ if response.Data != nil {
+ for _, item := range response.Data.Results {
+ if strings.TrimRight(item.Domain, ".") == zoneName || strings.TrimRight(item.DisplayDomain, ".") == zoneName {
+ return item, nil
+ }
+ }
+ }
+
+ if response.Data == nil || len(response.Data.Results) < pageSize {
+ break
+ }
+
+ pageIndex++
+ }
+
+ return nil, fmt.Errorf("dnsla: zone %s not found", zoneName)
+}
+
+func (d *DNSProvider) getDNSZoneAndRecord(zoneName, subDomain string) (*dnslasdk.DomainInfo, *dnslasdk.RecordInfo, error) {
+ zone, err := d.getDNSZone(zoneName)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ pageIndex := 1
+ pageSize := 100
+ for {
+ request := &dnslasdk.ListRecordsRequest{
+ DomainId: zone.Id,
+ Host: &subDomain,
+ PageIndex: int32(pageIndex),
+ PageSize: int32(pageSize),
+ }
+ response, err := d.client.ListRecords(request)
+ if err != nil {
+ return zone, nil, err
+ }
+
+ if response.Data != nil {
+ for _, record := range response.Data.Results {
+ if record.Type == 16 && (record.Host == subDomain || record.DisplayHost == subDomain) {
+ return zone, record, nil
+ }
+ }
+ }
+
+ if response.Data == nil || len(response.Data.Results) < pageSize {
+ break
+ }
+
+ pageIndex++
+ }
+
+ return zone, nil, nil
+}
+
+func (d *DNSProvider) addOrUpdateDNSRecord(zoneName, subDomain, value string) error {
+ zone, record, err := d.getDNSZoneAndRecord(zoneName, subDomain)
+ if err != nil {
+ return err
+ }
+
+ if record == nil {
+ request := &dnslasdk.CreateRecordRequest{
+ DomainId: zone.Id,
+ Type: 16,
+ Host: subDomain,
+ Data: value,
+ Ttl: int32(d.config.TTL),
+ }
+ _, err := d.client.CreateRecord(request)
+ return err
+ } else {
+ reqType := int32(16)
+ reqTtl := int32(d.config.TTL)
+ request := &dnslasdk.UpdateRecordRequest{
+ Id: record.Id,
+ Type: &reqType,
+ Host: &subDomain,
+ Data: &value,
+ Ttl: &reqTtl,
+ }
+ _, err := d.client.UpdateRecord(request)
+ return err
+ }
+}
+
+func (d *DNSProvider) removeDNSRecord(zoneName, subDomain string) error {
+ _, record, err := d.getDNSZoneAndRecord(zoneName, subDomain)
+ if err != nil {
+ return err
+ }
+
+ if record == nil {
+ return nil
+ } else {
+ request := &dnslasdk.DeleteRecordRequest{
+ Id: record.Id,
+ }
+ _, err = d.client.DeleteRecord(request)
+ return err
+ }
+}
diff --git a/internal/pkg/core/applicant/acme-dns-01/lego-providers/gcore/gcore.go b/internal/pkg/core/applicant/acme-dns-01/lego-providers/gcore/gcore.go
new file mode 100644
index 00000000..ac9f7e61
--- /dev/null
+++ b/internal/pkg/core/applicant/acme-dns-01/lego-providers/gcore/gcore.go
@@ -0,0 +1,36 @@
+package gcore
+
+import (
+ "time"
+
+ "github.com/go-acme/lego/v4/challenge"
+ "github.com/go-acme/lego/v4/providers/dns/gcore"
+)
+
+type ChallengeProviderConfig struct {
+ ApiToken string `json:"apiToken"`
+ 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 := gcore.NewDefaultConfig()
+ providerConfig.APIToken = config.ApiToken
+ if config.DnsPropagationTimeout != 0 {
+ providerConfig.PropagationTimeout = time.Duration(config.DnsPropagationTimeout) * time.Second
+ }
+ if config.DnsTTL != 0 {
+ providerConfig.TTL = int(config.DnsTTL)
+ }
+
+ provider, err := gcore.NewDNSProviderConfig(providerConfig)
+ if err != nil {
+ return nil, err
+ }
+
+ return provider, nil
+}
diff --git a/internal/pkg/core/applicant/acme-dns-01/lego-providers/gname/gname.go b/internal/pkg/core/applicant/acme-dns-01/lego-providers/gname/gname.go
index 90cec017..42057149 100644
--- a/internal/pkg/core/applicant/acme-dns-01/lego-providers/gname/gname.go
+++ b/internal/pkg/core/applicant/acme-dns-01/lego-providers/gname/gname.go
@@ -1,7 +1,6 @@
package gname
import (
- "errors"
"time"
"github.com/go-acme/lego/v4/challenge"
@@ -9,16 +8,16 @@ import (
internal "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/gname/internal"
)
-type GnameApplicantConfig struct {
+type ChallengeProviderConfig struct {
AppId string `json:"appId"`
AppKey string `json:"appKey"`
DnsPropagationTimeout int32 `json:"dnsPropagationTimeout,omitempty"`
DnsTTL int32 `json:"dnsTTL,omitempty"`
}
-func NewChallengeProvider(config *GnameApplicantConfig) (challenge.Provider, error) {
+func NewChallengeProvider(config *ChallengeProviderConfig) (challenge.Provider, error) {
if config == nil {
- return nil, errors.New("config is nil")
+ panic("config is nil")
}
providerConfig := internal.NewDefaultConfig()
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 03dc633f..3d0f2e54 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
@@ -37,13 +37,13 @@ type Config struct {
}
type DNSProvider struct {
- client *gnamesdk.GnameClient
+ client *gnamesdk.Client
config *Config
}
func NewDefaultConfig() *Config {
return &Config{
- TTL: env.GetOrDefaultInt(EnvTTL, dns01.DefaultTTL),
+ TTL: env.GetOrDefaultInt(EnvTTL, 300),
PropagationTimeout: env.GetOrDefaultSecond(EnvPropagationTimeout, 2*time.Minute),
PollingInterval: env.GetOrDefaultSecond(EnvPollingInterval, dns01.DefaultPollingInterval),
HTTPTimeout: env.GetOrDefaultSecond(EnvHTTPTimeout, 30*time.Second),
@@ -68,7 +68,7 @@ func NewDNSProviderConfig(config *Config) (*DNSProvider, error) {
return nil, errors.New("gname: the configuration of the DNS provider is nil")
}
- client := gnamesdk.NewGnameClient(config.AppID, config.AppKey).
+ client := gnamesdk.NewClient(config.AppID, config.AppKey).
WithTimeout(config.HTTPTimeout)
return &DNSProvider{
@@ -80,17 +80,17 @@ func NewDNSProviderConfig(config *Config) (*DNSProvider, error) {
func (d *DNSProvider) Present(domain, token, keyAuth string) error {
info := dns01.GetChallengeInfo(domain, keyAuth)
- zoneName, err := dns01.FindZoneByFqdn(info.EffectiveFQDN)
+ authZone, err := dns01.FindZoneByFqdn(info.EffectiveFQDN)
if err != nil {
return fmt.Errorf("gname: %w", err)
}
- subDomain, err := dns01.ExtractSubDomain(info.EffectiveFQDN, zoneName)
+ subDomain, err := dns01.ExtractSubDomain(info.EffectiveFQDN, authZone)
if err != nil {
return fmt.Errorf("gname: %w", err)
}
- if err := d.addOrUpdateDNSRecord(domain, subDomain, info.Value); err != nil {
+ if err := d.addOrUpdateDNSRecord(dns01.UnFqdn(authZone), subDomain, info.Value); err != nil {
return fmt.Errorf("gname: %w", err)
}
@@ -98,10 +98,19 @@ func (d *DNSProvider) Present(domain, token, keyAuth string) error {
}
func (d *DNSProvider) CleanUp(domain, token, keyAuth string) error {
- fqdn, value := dns01.GetRecord(domain, keyAuth)
- subDomain := dns01.UnFqdn(fqdn)
+ info := dns01.GetChallengeInfo(domain, keyAuth)
- if err := d.removeDNSRecord(domain, subDomain, value); err != nil {
+ authZone, err := dns01.FindZoneByFqdn(info.EffectiveFQDN)
+ if err != nil {
+ return fmt.Errorf("gname: %w", err)
+ }
+
+ subDomain, err := dns01.ExtractSubDomain(info.EffectiveFQDN, authZone)
+ if err != nil {
+ return fmt.Errorf("gname: %w", err)
+ }
+
+ if err := d.removeDNSRecord(dns01.UnFqdn(authZone), subDomain); err != nil {
return fmt.Errorf("gname: %w", err)
}
@@ -112,12 +121,12 @@ func (d *DNSProvider) Timeout() (timeout, interval time.Duration) {
return d.config.PropagationTimeout, d.config.PollingInterval
}
-func (d *DNSProvider) getDNSRecord(domain, subDomain string) (*gnamesdk.ResolutionRecord, error) {
+func (d *DNSProvider) getDNSRecord(zoneName, subDomain string) (*gnamesdk.ResolutionRecord, error) {
page := 1
pageSize := 20
for {
request := &gnamesdk.ListDomainResolutionRequest{}
- request.ZoneName = domain
+ request.ZoneName = zoneName
request.Page = &page
request.PageSize = &pageSize
@@ -145,15 +154,15 @@ func (d *DNSProvider) getDNSRecord(domain, subDomain string) (*gnamesdk.Resoluti
return nil, nil
}
-func (d *DNSProvider) addOrUpdateDNSRecord(domain, subDomain, value string) error {
- record, err := d.getDNSRecord(domain, subDomain)
+func (d *DNSProvider) addOrUpdateDNSRecord(zoneName, subDomain, value string) error {
+ record, err := d.getDNSRecord(zoneName, subDomain)
if err != nil {
return err
}
if record == nil {
request := &gnamesdk.AddDomainResolutionRequest{
- ZoneName: domain,
+ ZoneName: zoneName,
RecordType: "TXT",
RecordName: subDomain,
RecordValue: value,
@@ -164,7 +173,7 @@ func (d *DNSProvider) addOrUpdateDNSRecord(domain, subDomain, value string) erro
} else {
request := &gnamesdk.ModifyDomainResolutionRequest{
ID: record.ID,
- ZoneName: domain,
+ ZoneName: zoneName,
RecordType: "TXT",
RecordName: subDomain,
RecordValue: value,
@@ -175,8 +184,8 @@ func (d *DNSProvider) addOrUpdateDNSRecord(domain, subDomain, value string) erro
}
}
-func (d *DNSProvider) removeDNSRecord(domain, subDomain, value string) error {
- record, err := d.getDNSRecord(domain, subDomain)
+func (d *DNSProvider) removeDNSRecord(zoneName, subDomain string) error {
+ record, err := d.getDNSRecord(zoneName, subDomain)
if err != nil {
return err
}
@@ -186,7 +195,7 @@ func (d *DNSProvider) removeDNSRecord(domain, subDomain, value string) error {
}
request := &gnamesdk.DeleteDomainResolutionRequest{
- ZoneName: domain,
+ ZoneName: zoneName,
RecordID: record.ID,
}
_, err = d.client.DeleteDomainResolution(request)
diff --git a/internal/pkg/core/applicant/acme-dns-01/lego-providers/godaddy/godaddy.go b/internal/pkg/core/applicant/acme-dns-01/lego-providers/godaddy/godaddy.go
index 3a44616b..957c9185 100644
--- a/internal/pkg/core/applicant/acme-dns-01/lego-providers/godaddy/godaddy.go
+++ b/internal/pkg/core/applicant/acme-dns-01/lego-providers/godaddy/godaddy.go
@@ -1,23 +1,22 @@
package godaddy
import (
- "errors"
"time"
"github.com/go-acme/lego/v4/challenge"
"github.com/go-acme/lego/v4/providers/dns/godaddy"
)
-type GoDaddyApplicantConfig struct {
+type ChallengeProviderConfig struct {
ApiKey string `json:"apiKey"`
ApiSecret string `json:"apiSecret"`
DnsPropagationTimeout int32 `json:"dnsPropagationTimeout,omitempty"`
DnsTTL int32 `json:"dnsTTL,omitempty"`
}
-func NewChallengeProvider(config *GoDaddyApplicantConfig) (challenge.Provider, error) {
+func NewChallengeProvider(config *ChallengeProviderConfig) (challenge.Provider, error) {
if config == nil {
- return nil, errors.New("config is nil")
+ panic("config is nil")
}
providerConfig := godaddy.NewDefaultConfig()
diff --git a/internal/pkg/core/applicant/acme-dns-01/lego-providers/huaweicloud/huaweicloud.go b/internal/pkg/core/applicant/acme-dns-01/lego-providers/huaweicloud/huaweicloud.go
index cbdf2928..08a629fc 100644
--- a/internal/pkg/core/applicant/acme-dns-01/lego-providers/huaweicloud/huaweicloud.go
+++ b/internal/pkg/core/applicant/acme-dns-01/lego-providers/huaweicloud/huaweicloud.go
@@ -1,14 +1,13 @@
package huaweicloud
import (
- "errors"
"time"
"github.com/go-acme/lego/v4/challenge"
hwc "github.com/go-acme/lego/v4/providers/dns/huaweicloud"
)
-type HuaweiCloudApplicantConfig struct {
+type ChallengeProviderConfig struct {
AccessKeyId string `json:"accessKeyId"`
SecretAccessKey string `json:"secretAccessKey"`
Region string `json:"region"`
@@ -16,9 +15,9 @@ type HuaweiCloudApplicantConfig struct {
DnsTTL int32 `json:"dnsTTL,omitempty"`
}
-func NewChallengeProvider(config *HuaweiCloudApplicantConfig) (challenge.Provider, error) {
+func NewChallengeProvider(config *ChallengeProviderConfig) (challenge.Provider, error) {
if config == nil {
- return nil, errors.New("config is nil")
+ panic("config is nil")
}
region := config.Region
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
new file mode 100644
index 00000000..68d81f7e
--- /dev/null
+++ b/internal/pkg/core/applicant/acme-dns-01/lego-providers/jdcloud/internal/lego.go
@@ -0,0 +1,238 @@
+package lego_jdcloud
+
+import (
+ "errors"
+ "fmt"
+ "time"
+
+ "github.com/go-acme/lego/v4/challenge"
+ "github.com/go-acme/lego/v4/challenge/dns01"
+ "github.com/go-acme/lego/v4/platform/config/env"
+ jdCore "github.com/jdcloud-api/jdcloud-sdk-go/core"
+ jdDnsApi "github.com/jdcloud-api/jdcloud-sdk-go/services/domainservice/apis"
+ jdDnsClient "github.com/jdcloud-api/jdcloud-sdk-go/services/domainservice/client"
+ jdDnsModel "github.com/jdcloud-api/jdcloud-sdk-go/services/domainservice/models"
+)
+
+const (
+ envNamespace = "JDCLOUD_"
+
+ EnvAccessKeyID = envNamespace + "ACCESS_KEY_ID"
+ EnvAccessKeySecret = envNamespace + "ACCESS_KEY_SECRET"
+ 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 {
+ AccessKeyID string
+ AccessKeySecret string
+ RegionId string
+
+ PropagationTimeout time.Duration
+ PollingInterval time.Duration
+ TTL int32
+ HTTPTimeout time.Duration
+}
+
+type DNSProvider struct {
+ client *jdDnsClient.DomainserviceClient
+ config *Config
+}
+
+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(EnvAccessKeyID, EnvAccessKeySecret)
+ if err != nil {
+ return nil, fmt.Errorf("jdcloud: %w", err)
+ }
+
+ config := NewDefaultConfig()
+ config.AccessKeyID = values[EnvAccessKeyID]
+ config.AccessKeySecret = values[EnvAccessKeySecret]
+ config.RegionId = values[EnvRegionId]
+
+ return NewDNSProviderConfig(config)
+}
+
+func NewDNSProviderConfig(config *Config) (*DNSProvider, error) {
+ if config == nil {
+ return nil, errors.New("jdcloud: the configuration of the DNS provider is nil")
+ }
+
+ clientCredentials := jdCore.NewCredentials(config.AccessKeyID, config.AccessKeySecret)
+ client := jdDnsClient.NewDomainserviceClient(clientCredentials)
+ clientConfig := &client.Config
+ clientConfig.SetTimeout(config.HTTPTimeout)
+ client.SetConfig(clientConfig)
+ client.SetLogger(jdCore.NewDefaultLogger(jdCore.LogWarn))
+
+ 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("jdcloud: %w", err)
+ }
+
+ subDomain, err := dns01.ExtractSubDomain(info.EffectiveFQDN, authZone)
+ if err != nil {
+ return fmt.Errorf("jdcloud: %w", err)
+ }
+
+ if err := d.addOrUpdateDNSRecord(dns01.UnFqdn(authZone), subDomain, info.Value); err != nil {
+ return fmt.Errorf("jdcloud: %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("jdcloud: %w", err)
+ }
+
+ subDomain, err := dns01.ExtractSubDomain(info.EffectiveFQDN, authZone)
+ if err != nil {
+ return fmt.Errorf("jdcloud: %w", err)
+ }
+
+ if err := d.removeDNSRecord(dns01.UnFqdn(authZone), subDomain); err != nil {
+ return fmt.Errorf("jdcloud: %w", err)
+ }
+
+ return nil
+}
+
+func (d *DNSProvider) Timeout() (timeout, interval time.Duration) {
+ return d.config.PropagationTimeout, d.config.PollingInterval
+}
+
+func (d *DNSProvider) getDNSZone(zoneName string) (*jdDnsModel.DomainInfo, error) {
+ pageNumber := 1
+ pageSize := 10
+ for {
+ request := jdDnsApi.NewDescribeDomainsRequest(d.config.RegionId, pageNumber, pageSize)
+ request.SetDomainName(zoneName)
+
+ response, err := d.client.DescribeDomains(request)
+ if err != nil {
+ return nil, err
+ }
+
+ for _, item := range response.Result.DataList {
+ if item.DomainName == zoneName {
+ return &item, nil
+ }
+ }
+
+ if len(response.Result.DataList) < pageSize {
+ break
+ }
+
+ pageNumber++
+ }
+
+ return nil, fmt.Errorf("jdcloud: zone %s not found", zoneName)
+}
+
+func (d *DNSProvider) getDNSZoneAndRecord(zoneName, subDomain string) (*jdDnsModel.DomainInfo, *jdDnsModel.RRInfo, error) {
+ zone, err := d.getDNSZone(zoneName)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ pageNumber := 1
+ pageSize := 10
+ for {
+ request := jdDnsApi.NewDescribeResourceRecordRequest(d.config.RegionId, fmt.Sprintf("%d", zone.Id))
+ request.SetSearch(subDomain)
+ request.SetPageNumber(pageNumber)
+ request.SetPageSize(pageSize)
+
+ response, err := d.client.DescribeResourceRecord(request)
+ if err != nil {
+ return zone, nil, err
+ }
+
+ for _, record := range response.Result.DataList {
+ if record.Type == "TXT" && record.HostRecord == subDomain {
+ return zone, &record, nil
+ }
+ }
+
+ if len(response.Result.DataList) < pageSize {
+ break
+ }
+
+ pageNumber++
+ }
+
+ return zone, nil, nil
+}
+
+func (d *DNSProvider) addOrUpdateDNSRecord(zoneName, subDomain, value string) error {
+ zone, record, err := d.getDNSZoneAndRecord(zoneName, subDomain)
+ if err != nil {
+ return err
+ }
+
+ if record == nil {
+ request := jdDnsApi.NewCreateResourceRecordRequest(d.config.RegionId, fmt.Sprintf("%d", zone.Id), &jdDnsModel.AddRR{
+ Type: "TXT",
+ HostRecord: subDomain,
+ HostValue: value,
+ Ttl: int(d.config.TTL),
+ ViewValue: -1,
+ })
+ _, err := d.client.CreateResourceRecord(request)
+ return err
+ } else {
+ request := jdDnsApi.NewModifyResourceRecordRequest(d.config.RegionId, fmt.Sprintf("%d", zone.Id), fmt.Sprintf("%d", record.Id), &jdDnsModel.UpdateRR{
+ Type: "TXT",
+ HostRecord: subDomain,
+ HostValue: value,
+ Ttl: int(d.config.TTL),
+ ViewValue: -1,
+ })
+ _, err := d.client.ModifyResourceRecord(request)
+ return err
+ }
+}
+
+func (d *DNSProvider) removeDNSRecord(zoneName, subDomain string) error {
+ zone, record, err := d.getDNSZoneAndRecord(zoneName, subDomain)
+ if err != nil {
+ return err
+ }
+
+ if record == nil {
+ return nil
+ } else {
+ request := jdDnsApi.NewDeleteResourceRecordRequest(d.config.RegionId, fmt.Sprintf("%d", zone.Id), fmt.Sprintf("%d", record.Id))
+ _, err = d.client.DeleteResourceRecord(request)
+ return err
+ }
+}
diff --git a/internal/pkg/core/applicant/acme-dns-01/lego-providers/jdcloud/jdcloud.go b/internal/pkg/core/applicant/acme-dns-01/lego-providers/jdcloud/jdcloud.go
new file mode 100644
index 00000000..5729d932
--- /dev/null
+++ b/internal/pkg/core/applicant/acme-dns-01/lego-providers/jdcloud/jdcloud.go
@@ -0,0 +1,47 @@
+package jdcloud
+
+import (
+ "time"
+
+ "github.com/go-acme/lego/v4/challenge"
+
+ internal "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/jdcloud/internal"
+)
+
+type ChallengeProviderConfig struct {
+ AccessKeyId string `json:"accessKeyId"`
+ AccessKeySecret string `json:"accessKeySecret"`
+ RegionId string `json:"regionId"`
+ DnsPropagationTimeout int32 `json:"dnsPropagationTimeout,omitempty"`
+ DnsTTL int32 `json:"dnsTTL,omitempty"`
+}
+
+func NewChallengeProvider(config *ChallengeProviderConfig) (challenge.Provider, error) {
+ if config == nil {
+ panic("config is nil")
+ }
+
+ regionId := config.RegionId
+ if regionId == "" {
+ // 京东云的 SDK 要求必须传一个区域,实际上 DNS-01 流程里用不到,但不传会报错
+ regionId = "cn-north-1"
+ }
+
+ providerConfig := internal.NewDefaultConfig()
+ providerConfig.AccessKeyID = config.AccessKeyId
+ providerConfig.AccessKeySecret = config.AccessKeySecret
+ providerConfig.RegionId = regionId
+ 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/namecheap/namecheap.go b/internal/pkg/core/applicant/acme-dns-01/lego-providers/namecheap/namecheap.go
new file mode 100644
index 00000000..9bf2f3c3
--- /dev/null
+++ b/internal/pkg/core/applicant/acme-dns-01/lego-providers/namecheap/namecheap.go
@@ -0,0 +1,38 @@
+package namedotcom
+
+import (
+ "time"
+
+ "github.com/go-acme/lego/v4/challenge"
+ "github.com/go-acme/lego/v4/providers/dns/namecheap"
+)
+
+type ChallengeProviderConfig struct {
+ Username string `json:"username"`
+ ApiKey string `json:"apiKey"`
+ 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 := namecheap.NewDefaultConfig()
+ providerConfig.APIUser = config.Username
+ providerConfig.APIKey = config.ApiKey
+ if config.DnsPropagationTimeout != 0 {
+ providerConfig.PropagationTimeout = time.Duration(config.DnsPropagationTimeout) * time.Second
+ }
+ if config.DnsTTL != 0 {
+ providerConfig.TTL = int(config.DnsTTL)
+ }
+
+ provider, err := namecheap.NewDNSProviderConfig(providerConfig)
+ if err != nil {
+ return nil, err
+ }
+
+ return provider, nil
+}
diff --git a/internal/pkg/core/applicant/acme-dns-01/lego-providers/namedotcom/namedotcom.go b/internal/pkg/core/applicant/acme-dns-01/lego-providers/namedotcom/namedotcom.go
index c51b1a9b..daff3612 100644
--- a/internal/pkg/core/applicant/acme-dns-01/lego-providers/namedotcom/namedotcom.go
+++ b/internal/pkg/core/applicant/acme-dns-01/lego-providers/namedotcom/namedotcom.go
@@ -1,23 +1,22 @@
package namedotcom
import (
- "errors"
"time"
"github.com/go-acme/lego/v4/challenge"
"github.com/go-acme/lego/v4/providers/dns/namedotcom"
)
-type NameDotComApplicantConfig struct {
+type ChallengeProviderConfig struct {
Username string `json:"username"`
ApiToken string `json:"apiToken"`
DnsPropagationTimeout int32 `json:"dnsPropagationTimeout,omitempty"`
DnsTTL int32 `json:"dnsTTL,omitempty"`
}
-func NewChallengeProvider(config *NameDotComApplicantConfig) (challenge.Provider, error) {
+func NewChallengeProvider(config *ChallengeProviderConfig) (challenge.Provider, error) {
if config == nil {
- return nil, errors.New("config is nil")
+ panic("config is nil")
}
providerConfig := namedotcom.NewDefaultConfig()
diff --git a/internal/pkg/core/applicant/acme-dns-01/lego-providers/namesilo/namesilo.go b/internal/pkg/core/applicant/acme-dns-01/lego-providers/namesilo/namesilo.go
index 0f1bf8ea..5656136b 100644
--- a/internal/pkg/core/applicant/acme-dns-01/lego-providers/namesilo/namesilo.go
+++ b/internal/pkg/core/applicant/acme-dns-01/lego-providers/namesilo/namesilo.go
@@ -1,22 +1,21 @@
package namesilo
import (
- "errors"
"time"
"github.com/go-acme/lego/v4/challenge"
"github.com/go-acme/lego/v4/providers/dns/namesilo"
)
-type NameSiloApplicantConfig struct {
+type ChallengeProviderConfig struct {
ApiKey string `json:"apiKey"`
DnsPropagationTimeout int32 `json:"dnsPropagationTimeout,omitempty"`
DnsTTL int32 `json:"dnsTTL,omitempty"`
}
-func NewChallengeProvider(config *NameSiloApplicantConfig) (challenge.Provider, error) {
+func NewChallengeProvider(config *ChallengeProviderConfig) (challenge.Provider, error) {
if config == nil {
- return nil, errors.New("config is nil")
+ panic("config is nil")
}
providerConfig := namesilo.NewDefaultConfig()
diff --git a/internal/pkg/core/applicant/acme-dns-01/lego-providers/ns1/ns1.go b/internal/pkg/core/applicant/acme-dns-01/lego-providers/ns1/ns1.go
index efa40076..1682e0c2 100644
--- a/internal/pkg/core/applicant/acme-dns-01/lego-providers/ns1/ns1.go
+++ b/internal/pkg/core/applicant/acme-dns-01/lego-providers/ns1/ns1.go
@@ -1,22 +1,21 @@
package ns1
import (
- "errors"
"time"
"github.com/go-acme/lego/v4/challenge"
"github.com/go-acme/lego/v4/providers/dns/ns1"
)
-type NS1ApplicantConfig struct {
+type ChallengeProviderConfig struct {
ApiKey string `json:"apiKey"`
DnsPropagationTimeout int32 `json:"dnsPropagationTimeout,omitempty"`
DnsTTL int32 `json:"dnsTTL,omitempty"`
}
-func NewChallengeProvider(config *NS1ApplicantConfig) (challenge.Provider, error) {
+func NewChallengeProvider(config *ChallengeProviderConfig) (challenge.Provider, error) {
if config == nil {
- return nil, errors.New("config is nil")
+ panic("config is nil")
}
providerConfig := ns1.NewDefaultConfig()
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 d5fa616c..3dc86d66 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,7 +1,6 @@
package namesilo
import (
- "errors"
"net/url"
"time"
@@ -9,16 +8,16 @@ import (
"github.com/go-acme/lego/v4/providers/dns/pdns"
)
-type PowerDNSApplicantConfig struct {
+type ChallengeProviderConfig struct {
ApiUrl string `json:"apiUrl"`
ApiKey string `json:"apiKey"`
DnsPropagationTimeout int32 `json:"dnsPropagationTimeout,omitempty"`
DnsTTL int32 `json:"dnsTTL,omitempty"`
}
-func NewChallengeProvider(config *PowerDNSApplicantConfig) (challenge.Provider, error) {
+func NewChallengeProvider(config *ChallengeProviderConfig) (challenge.Provider, error) {
if config == nil {
- return nil, errors.New("config is nil")
+ panic("config is nil")
}
host, _ := url.Parse(config.ApiUrl)
diff --git a/internal/pkg/core/applicant/acme-dns-01/lego-providers/rainyun/rainyun.go b/internal/pkg/core/applicant/acme-dns-01/lego-providers/rainyun/rainyun.go
index d250a279..2deda0f1 100644
--- a/internal/pkg/core/applicant/acme-dns-01/lego-providers/rainyun/rainyun.go
+++ b/internal/pkg/core/applicant/acme-dns-01/lego-providers/rainyun/rainyun.go
@@ -1,22 +1,21 @@
package rainyun
import (
- "errors"
"time"
"github.com/go-acme/lego/v4/challenge"
"github.com/go-acme/lego/v4/providers/dns/rainyun"
)
-type RainYunApplicantConfig struct {
+type ChallengeProviderConfig struct {
ApiKey string `json:"apiKey"`
DnsPropagationTimeout int32 `json:"dnsPropagationTimeout,omitempty"`
DnsTTL int32 `json:"dnsTTL,omitempty"`
}
-func NewChallengeProvider(config *RainYunApplicantConfig) (challenge.Provider, error) {
+func NewChallengeProvider(config *ChallengeProviderConfig) (challenge.Provider, error) {
if config == nil {
- return nil, errors.New("config is nil")
+ panic("config is nil")
}
providerConfig := rainyun.NewDefaultConfig()
diff --git a/internal/pkg/core/applicant/acme-dns-01/lego-providers/tencentcloud/tencentcloud.go b/internal/pkg/core/applicant/acme-dns-01/lego-providers/tencentcloud/tencentcloud.go
index f7e6bf7b..8ef3760c 100644
--- a/internal/pkg/core/applicant/acme-dns-01/lego-providers/tencentcloud/tencentcloud.go
+++ b/internal/pkg/core/applicant/acme-dns-01/lego-providers/tencentcloud/tencentcloud.go
@@ -1,23 +1,22 @@
package tencentcloud
import (
- "errors"
"time"
"github.com/go-acme/lego/v4/challenge"
"github.com/go-acme/lego/v4/providers/dns/tencentcloud"
)
-type TencentCloudApplicantConfig struct {
+type ChallengeProviderConfig struct {
SecretId string `json:"secretId"`
SecretKey string `json:"secretKey"`
DnsPropagationTimeout int32 `json:"dnsPropagationTimeout,omitempty"`
DnsTTL int32 `json:"dnsTTL,omitempty"`
}
-func NewChallengeProvider(config *TencentCloudApplicantConfig) (challenge.Provider, error) {
+func NewChallengeProvider(config *ChallengeProviderConfig) (challenge.Provider, error) {
if config == nil {
- return nil, errors.New("config is nil")
+ panic("config is nil")
}
providerConfig := tencentcloud.NewDefaultConfig()
diff --git a/internal/pkg/core/applicant/acme-dns-01/lego-providers/volcengine/volcengine.go b/internal/pkg/core/applicant/acme-dns-01/lego-providers/volcengine/volcengine.go
index a8f11ff9..e0a1ae91 100644
--- a/internal/pkg/core/applicant/acme-dns-01/lego-providers/volcengine/volcengine.go
+++ b/internal/pkg/core/applicant/acme-dns-01/lego-providers/volcengine/volcengine.go
@@ -1,23 +1,22 @@
package volcengine
import (
- "errors"
"time"
"github.com/go-acme/lego/v4/challenge"
"github.com/go-acme/lego/v4/providers/dns/volcengine"
)
-type VolcEngineApplicantConfig struct {
+type ChallengeProviderConfig struct {
AccessKeyId string `json:"accessKeyId"`
SecretAccessKey string `json:"secretAccessKey"`
DnsPropagationTimeout int32 `json:"dnsPropagationTimeout,omitempty"`
DnsTTL int32 `json:"dnsTTL,omitempty"`
}
-func NewChallengeProvider(config *VolcEngineApplicantConfig) (challenge.Provider, error) {
+func NewChallengeProvider(config *ChallengeProviderConfig) (challenge.Provider, error) {
if config == nil {
- return nil, errors.New("config is nil")
+ panic("config is nil")
}
providerConfig := volcengine.NewDefaultConfig()
diff --git a/internal/pkg/core/applicant/acme-dns-01/lego-providers/westcn/westcn.go b/internal/pkg/core/applicant/acme-dns-01/lego-providers/westcn/westcn.go
index f20b5d21..f79c5a8c 100644
--- a/internal/pkg/core/applicant/acme-dns-01/lego-providers/westcn/westcn.go
+++ b/internal/pkg/core/applicant/acme-dns-01/lego-providers/westcn/westcn.go
@@ -1,23 +1,22 @@
package westcn
import (
- "errors"
"time"
"github.com/go-acme/lego/v4/challenge"
"github.com/go-acme/lego/v4/providers/dns/westcn"
)
-type WestcnApplicantConfig struct {
+type ChallengeProviderConfig struct {
Username string `json:"username"`
ApiPassword string `json:"apiPassword"`
DnsPropagationTimeout int32 `json:"dnsPropagationTimeout,omitempty"`
DnsTTL int32 `json:"dnsTTL,omitempty"`
}
-func NewChallengeProvider(config *WestcnApplicantConfig) (challenge.Provider, error) {
+func NewChallengeProvider(config *ChallengeProviderConfig) (challenge.Provider, error) {
if config == nil {
- return nil, errors.New("config is nil")
+ panic("config is nil")
}
providerConfig := westcn.NewDefaultConfig()
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 9878b6f4..39600c7b 100644
--- a/internal/pkg/core/deployer/providers/aliyun-alb/aliyun_alb.go
+++ b/internal/pkg/core/deployer/providers/aliyun-alb/aliyun_alb.go
@@ -18,10 +18,10 @@ import (
"github.com/usual2970/certimate/internal/pkg/core/deployer"
"github.com/usual2970/certimate/internal/pkg/core/logger"
"github.com/usual2970/certimate/internal/pkg/core/uploader"
- uploaderp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/aliyun-cas"
+ uploadersp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/aliyun-cas"
)
-type AliyunALBDeployerConfig struct {
+type DeployerConfig struct {
// 阿里云 AccessKeyId。
AccessKeyId string `json:"accessKeyId"`
// 阿里云 AccessKeySecret。
@@ -29,43 +29,35 @@ type AliyunALBDeployerConfig struct {
// 阿里云地域。
Region string `json:"region"`
// 部署资源类型。
- ResourceType DeployResourceType `json:"resourceType"`
+ ResourceType ResourceType `json:"resourceType"`
// 负载均衡实例 ID。
- // 部署资源类型为 [DEPLOY_RESOURCE_LOADBALANCER] 时必填。
+ // 部署资源类型为 [RESOURCE_TYPE_LOADBALANCER] 时必填。
LoadbalancerId string `json:"loadbalancerId,omitempty"`
// 负载均衡监听 ID。
- // 部署资源类型为 [DEPLOY_RESOURCE_LISTENER] 时必填。
+ // 部署资源类型为 [RESOURCE_TYPE_LISTENER] 时必填。
ListenerId string `json:"listenerId,omitempty"`
// SNI 域名(支持泛域名)。
- // 部署资源类型为 [DEPLOY_RESOURCE_LOADBALANCER]、[DEPLOY_RESOURCE_LISTENER] 时选填。
+ // 部署资源类型为 [RESOURCE_TYPE_LOADBALANCER]、[RESOURCE_TYPE_LISTENER] 时选填。
Domain string `json:"domain,omitempty"`
}
-type AliyunALBDeployer struct {
- config *AliyunALBDeployerConfig
+type DeployerProvider struct {
+ config *DeployerConfig
logger logger.Logger
sdkClients *wSdkClients
sslUploader uploader.Uploader
}
-var _ deployer.Deployer = (*AliyunALBDeployer)(nil)
+var _ deployer.Deployer = (*DeployerProvider)(nil)
type wSdkClients struct {
alb *aliyunAlb.Client
cas *aliyunCas.Client
}
-func New(config *AliyunALBDeployerConfig) (*AliyunALBDeployer, error) {
- return NewWithLogger(config, logger.NewNilLogger())
-}
-
-func NewWithLogger(config *AliyunALBDeployerConfig, logger logger.Logger) (*AliyunALBDeployer, error) {
+func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) {
if config == nil {
- return nil, errors.New("config is nil")
- }
-
- if logger == nil {
- return nil, errors.New("logger is nil")
+ panic("config is nil")
}
clients, err := createSdkClients(config.AccessKeyId, config.AccessKeySecret, config.Region)
@@ -78,15 +70,20 @@ func NewWithLogger(config *AliyunALBDeployerConfig, logger logger.Logger) (*Aliy
return nil, xerrors.Wrap(err, "failed to create ssl uploader")
}
- return &AliyunALBDeployer{
- logger: logger,
+ return &DeployerProvider{
config: config,
+ logger: logger.NewNilLogger(),
sdkClients: clients,
sslUploader: uploader,
}, nil
}
-func (d *AliyunALBDeployer) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) {
+func (d *DeployerProvider) WithLogger(logger logger.Logger) *DeployerProvider {
+ d.logger = logger
+ return d
+}
+
+func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) {
// 上传证书到 CAS
upres, err := d.sslUploader.Upload(ctx, certPem, privkeyPem)
if err != nil {
@@ -97,12 +94,12 @@ func (d *AliyunALBDeployer) Deploy(ctx context.Context, certPem string, privkeyP
// 根据部署资源类型决定部署方式
switch d.config.ResourceType {
- case DEPLOY_RESOURCE_LOADBALANCER:
+ case RESOURCE_TYPE_LOADBALANCER:
if err := d.deployToLoadbalancer(ctx, upres.CertId); err != nil {
return nil, err
}
- case DEPLOY_RESOURCE_LISTENER:
+ case RESOURCE_TYPE_LISTENER:
if err := d.deployToListener(ctx, upres.CertId); err != nil {
return nil, err
}
@@ -114,7 +111,7 @@ func (d *AliyunALBDeployer) Deploy(ctx context.Context, certPem string, privkeyP
return &deployer.DeployResult{}, nil
}
-func (d *AliyunALBDeployer) deployToLoadbalancer(ctx context.Context, cloudCertId string) error {
+func (d *DeployerProvider) deployToLoadbalancer(ctx context.Context, cloudCertId string) error {
if d.config.LoadbalancerId == "" {
return errors.New("config `loadbalancerId` is required")
}
@@ -213,7 +210,7 @@ func (d *AliyunALBDeployer) deployToLoadbalancer(ctx context.Context, cloudCertI
return nil
}
-func (d *AliyunALBDeployer) deployToListener(ctx context.Context, cloudCertId string) error {
+func (d *DeployerProvider) deployToListener(ctx context.Context, cloudCertId string) error {
if d.config.ListenerId == "" {
return errors.New("config `listenerId` is required")
}
@@ -226,7 +223,7 @@ func (d *AliyunALBDeployer) deployToListener(ctx context.Context, cloudCertId st
return nil
}
-func (d *AliyunALBDeployer) updateListenerCertificate(ctx context.Context, cloudListenerId string, cloudCertId string) error {
+func (d *DeployerProvider) updateListenerCertificate(ctx context.Context, cloudListenerId string, cloudCertId string) error {
// 查询监听的属性
// REF: https://help.aliyun.com/zh/slb/application-load-balancer/developer-reference/api-alb-2020-06-16-getlistenerattribute
getListenerAttributeReq := &aliyunAlb.GetListenerAttributeRequest{
@@ -257,7 +254,7 @@ func (d *AliyunALBDeployer) updateListenerCertificate(ctx context.Context, cloud
d.logger.Logt("已更新 ALB 监听配置", updateListenerAttributeResp)
} else {
- // 指定 SNI,需部署到扩展域名(支持泛域名)
+ // 指定 SNI,需部署到扩展域名
// 查询监听证书列表
// REF: https://help.aliyun.com/zh/slb/application-load-balancer/developer-reference/api-alb-2020-06-16-listlistenercertificates
@@ -445,7 +442,7 @@ func createSslUploader(accessKeyId, accessKeySecret, region string) (uploader.Up
}
}
- uploader, err := uploaderp.New(&uploaderp.AliyunCASUploaderConfig{
+ uploader, err := uploadersp.NewUploader(&uploadersp.UploaderConfig{
AccessKeyId: accessKeyId,
AccessKeySecret: accessKeySecret,
Region: casRegion,
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 15e6aff2..b5ae776a 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
@@ -63,11 +63,11 @@ func TestDeploy(t *testing.T) {
fmt.Sprintf("DOMAIN: %v", fDomain),
}, "\n"))
- deployer, err := provider.New(&provider.AliyunALBDeployerConfig{
+ deployer, err := provider.NewDeployer(&provider.DeployerConfig{
AccessKeyId: fAccessKeyId,
AccessKeySecret: fAccessKeySecret,
Region: fRegion,
- ResourceType: provider.DEPLOY_RESOURCE_LOADBALANCER,
+ ResourceType: provider.RESOURCE_TYPE_LOADBALANCER,
LoadbalancerId: fLoadbalancerId,
Domain: fDomain,
})
@@ -98,11 +98,11 @@ func TestDeploy(t *testing.T) {
fmt.Sprintf("LISTENERID: %v", fListenerId),
}, "\n"))
- deployer, err := provider.New(&provider.AliyunALBDeployerConfig{
+ deployer, err := provider.NewDeployer(&provider.DeployerConfig{
AccessKeyId: fAccessKeyId,
AccessKeySecret: fAccessKeySecret,
Region: fRegion,
- ResourceType: provider.DEPLOY_RESOURCE_LISTENER,
+ ResourceType: provider.RESOURCE_TYPE_LISTENER,
ListenerId: fListenerId,
Domain: fDomain,
})
diff --git a/internal/pkg/core/deployer/providers/aliyun-alb/consts.go b/internal/pkg/core/deployer/providers/aliyun-alb/consts.go
new file mode 100644
index 00000000..a2d1aacc
--- /dev/null
+++ b/internal/pkg/core/deployer/providers/aliyun-alb/consts.go
@@ -0,0 +1,10 @@
+package aliyunalb
+
+type ResourceType string
+
+const (
+ // 资源类型:部署到指定负载均衡器。
+ RESOURCE_TYPE_LOADBALANCER = ResourceType("loadbalancer")
+ // 资源类型:部署到指定监听器。
+ RESOURCE_TYPE_LISTENER = ResourceType("listener")
+)
diff --git a/internal/pkg/core/deployer/providers/aliyun-alb/defines.go b/internal/pkg/core/deployer/providers/aliyun-alb/defines.go
deleted file mode 100644
index 927e990a..00000000
--- a/internal/pkg/core/deployer/providers/aliyun-alb/defines.go
+++ /dev/null
@@ -1,10 +0,0 @@
-package aliyunalb
-
-type DeployResourceType string
-
-const (
- // 资源类型:部署到指定负载均衡器。
- DEPLOY_RESOURCE_LOADBALANCER = DeployResourceType("loadbalancer")
- // 资源类型:部署到指定监听器。
- DEPLOY_RESOURCE_LISTENER = DeployResourceType("listener")
-)
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 31dc66b8..1cc36c6f 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
@@ -15,10 +15,10 @@ import (
"github.com/usual2970/certimate/internal/pkg/core/deployer"
"github.com/usual2970/certimate/internal/pkg/core/logger"
"github.com/usual2970/certimate/internal/pkg/core/uploader"
- uploaderp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/aliyun-cas"
+ uploadersp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/aliyun-cas"
)
-type AliyunCASDeployDeployerConfig struct {
+type DeployerConfig struct {
// 阿里云 AccessKeyId。
AccessKeyId string `json:"accessKeyId"`
// 阿里云 AccessKeySecret。
@@ -32,26 +32,18 @@ type AliyunCASDeployDeployerConfig struct {
ContactIds []string `json:"contactIds"`
}
-type AliyunCASDeployDeployer struct {
- config *AliyunCASDeployDeployerConfig
+type DeployerProvider struct {
+ config *DeployerConfig
logger logger.Logger
sdkClient *aliyunCas.Client
sslUploader uploader.Uploader
}
-var _ deployer.Deployer = (*AliyunCASDeployDeployer)(nil)
+var _ deployer.Deployer = (*DeployerProvider)(nil)
-func New(config *AliyunCASDeployDeployerConfig) (*AliyunCASDeployDeployer, error) {
- return NewWithLogger(config, logger.NewNilLogger())
-}
-
-func NewWithLogger(config *AliyunCASDeployDeployerConfig, logger logger.Logger) (*AliyunCASDeployDeployer, error) {
+func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) {
if config == nil {
- return nil, errors.New("config is nil")
- }
-
- if logger == nil {
- return nil, errors.New("logger is nil")
+ panic("config is nil")
}
client, err := createSdkClient(config.AccessKeyId, config.AccessKeySecret, config.Region)
@@ -64,15 +56,20 @@ func NewWithLogger(config *AliyunCASDeployDeployerConfig, logger logger.Logger)
return nil, xerrors.Wrap(err, "failed to create ssl uploader")
}
- return &AliyunCASDeployDeployer{
- logger: logger,
+ return &DeployerProvider{
config: config,
+ logger: logger.NewNilLogger(),
sdkClient: client,
sslUploader: uploader,
}, nil
}
-func (d *AliyunCASDeployDeployer) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) {
+func (d *DeployerProvider) WithLogger(logger logger.Logger) *DeployerProvider {
+ d.logger = logger
+ return d
+}
+
+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")
}
@@ -178,7 +175,7 @@ func createSdkClient(accessKeyId, accessKeySecret, region string) (*aliyunCas.Cl
}
func createSslUploader(accessKeyId, accessKeySecret, region string) (uploader.Uploader, error) {
- uploader, err := uploaderp.New(&uploaderp.AliyunCASUploaderConfig{
+ uploader, err := uploadersp.NewUploader(&uploadersp.UploaderConfig{
AccessKeyId: accessKeyId,
AccessKeySecret: accessKeySecret,
Region: region,
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 d2de5684..b0edd415 100644
--- a/internal/pkg/core/deployer/providers/aliyun-cdn/aliyun_cdn.go
+++ b/internal/pkg/core/deployer/providers/aliyun-cdn/aliyun_cdn.go
@@ -2,7 +2,6 @@
import (
"context"
- "errors"
"fmt"
"strings"
"time"
@@ -16,7 +15,7 @@ import (
"github.com/usual2970/certimate/internal/pkg/core/logger"
)
-type AliyunCDNDeployerConfig struct {
+type DeployerConfig struct {
// 阿里云 AccessKeyId。
AccessKeyId string `json:"accessKeyId"`
// 阿里云 AccessKeySecret。
@@ -25,25 +24,17 @@ type AliyunCDNDeployerConfig struct {
Domain string `json:"domain"`
}
-type AliyunCDNDeployer struct {
- config *AliyunCDNDeployerConfig
+type DeployerProvider struct {
+ config *DeployerConfig
logger logger.Logger
sdkClient *aliyunCdn.Client
}
-var _ deployer.Deployer = (*AliyunCDNDeployer)(nil)
+var _ deployer.Deployer = (*DeployerProvider)(nil)
-func New(config *AliyunCDNDeployerConfig) (*AliyunCDNDeployer, error) {
- return NewWithLogger(config, logger.NewNilLogger())
-}
-
-func NewWithLogger(config *AliyunCDNDeployerConfig, logger logger.Logger) (*AliyunCDNDeployer, error) {
+func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) {
if config == nil {
- return nil, errors.New("config is nil")
- }
-
- if logger == nil {
- return nil, errors.New("logger is nil")
+ panic("config is nil")
}
client, err := createSdkClient(config.AccessKeyId, config.AccessKeySecret)
@@ -51,14 +42,19 @@ func NewWithLogger(config *AliyunCDNDeployerConfig, logger logger.Logger) (*Aliy
return nil, xerrors.Wrap(err, "failed to create sdk client")
}
- return &AliyunCDNDeployer{
- logger: logger,
+ return &DeployerProvider{
config: config,
+ logger: logger.NewNilLogger(),
sdkClient: client,
}, nil
}
-func (d *AliyunCDNDeployer) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) {
+func (d *DeployerProvider) WithLogger(logger logger.Logger) *DeployerProvider {
+ d.logger = logger
+ return d
+}
+
+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, "*")
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 da4d1d74..1f92947f 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
@@ -52,7 +52,7 @@ func TestDeploy(t *testing.T) {
fmt.Sprintf("DOMAIN: %v", fDomain),
}, "\n"))
- deployer, err := provider.New(&provider.AliyunCDNDeployerConfig{
+ deployer, err := provider.NewDeployer(&provider.DeployerConfig{
AccessKeyId: fAccessKeyId,
AccessKeySecret: fAccessKeySecret,
Domain: fDomain,
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 4bd91611..21a1e471 100644
--- a/internal/pkg/core/deployer/providers/aliyun-clb/aliyun_clb.go
+++ b/internal/pkg/core/deployer/providers/aliyun-clb/aliyun_clb.go
@@ -13,10 +13,10 @@ import (
"github.com/usual2970/certimate/internal/pkg/core/deployer"
"github.com/usual2970/certimate/internal/pkg/core/logger"
"github.com/usual2970/certimate/internal/pkg/core/uploader"
- uploaderp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/aliyun-slb"
+ uploadersp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/aliyun-slb"
)
-type AliyunCLBDeployerConfig struct {
+type DeployerConfig struct {
// 阿里云 AccessKeyId。
AccessKeyId string `json:"accessKeyId"`
// 阿里云 AccessKeySecret。
@@ -24,38 +24,30 @@ type AliyunCLBDeployerConfig struct {
// 阿里云地域。
Region string `json:"region"`
// 部署资源类型。
- ResourceType DeployResourceType `json:"resourceType"`
+ ResourceType ResourceType `json:"resourceType"`
// 负载均衡实例 ID。
- // 部署资源类型为 [DEPLOY_RESOURCE_LOADBALANCER]、[DEPLOY_RESOURCE_LISTENER] 时必填。
+ // 部署资源类型为 [RESOURCE_TYPE_LOADBALANCER]、[RESOURCE_TYPE_LISTENER] 时必填。
LoadbalancerId string `json:"loadbalancerId,omitempty"`
// 负载均衡监听端口。
- // 部署资源类型为 [DEPLOY_RESOURCE_LISTENER] 时必填。
+ // 部署资源类型为 [RESOURCE_TYPE_LISTENER] 时必填。
ListenerPort int32 `json:"listenerPort,omitempty"`
// SNI 域名(支持泛域名)。
- // 部署资源类型为 [DEPLOY_RESOURCE_LOADBALANCER]、[DEPLOY_RESOURCE_LISTENER] 时选填。
+ // 部署资源类型为 [RESOURCE_TYPE_LOADBALANCER]、[RESOURCE_TYPE_LISTENER] 时选填。
Domain string `json:"domain,omitempty"`
}
-type AliyunCLBDeployer struct {
- config *AliyunCLBDeployerConfig
+type DeployerProvider struct {
+ config *DeployerConfig
logger logger.Logger
sdkClient *aliyunSlb.Client
sslUploader uploader.Uploader
}
-var _ deployer.Deployer = (*AliyunCLBDeployer)(nil)
+var _ deployer.Deployer = (*DeployerProvider)(nil)
-func New(config *AliyunCLBDeployerConfig) (*AliyunCLBDeployer, error) {
- return NewWithLogger(config, logger.NewNilLogger())
-}
-
-func NewWithLogger(config *AliyunCLBDeployerConfig, logger logger.Logger) (*AliyunCLBDeployer, error) {
+func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) {
if config == nil {
- return nil, errors.New("config is nil")
- }
-
- if logger == nil {
- return nil, errors.New("logger is nil")
+ panic("config is nil")
}
client, err := createSdkClient(config.AccessKeyId, config.AccessKeySecret, config.Region)
@@ -63,7 +55,7 @@ func NewWithLogger(config *AliyunCLBDeployerConfig, logger logger.Logger) (*Aliy
return nil, xerrors.Wrap(err, "failed to create sdk client")
}
- uploader, err := uploaderp.New(&uploaderp.AliyunSLBUploaderConfig{
+ uploader, err := uploadersp.NewUploader(&uploadersp.UploaderConfig{
AccessKeyId: config.AccessKeyId,
AccessKeySecret: config.AccessKeySecret,
Region: config.Region,
@@ -72,15 +64,20 @@ func NewWithLogger(config *AliyunCLBDeployerConfig, logger logger.Logger) (*Aliy
return nil, xerrors.Wrap(err, "failed to create ssl uploader")
}
- return &AliyunCLBDeployer{
- logger: logger,
+ return &DeployerProvider{
config: config,
+ logger: logger.NewNilLogger(),
sdkClient: client,
sslUploader: uploader,
}, nil
}
-func (d *AliyunCLBDeployer) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) {
+func (d *DeployerProvider) WithLogger(logger logger.Logger) *DeployerProvider {
+ d.logger = logger
+ return d
+}
+
+func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) {
// 上传证书到 SLB
upres, err := d.sslUploader.Upload(ctx, certPem, privkeyPem)
if err != nil {
@@ -91,12 +88,12 @@ func (d *AliyunCLBDeployer) Deploy(ctx context.Context, certPem string, privkeyP
// 根据部署资源类型决定部署方式
switch d.config.ResourceType {
- case DEPLOY_RESOURCE_LOADBALANCER:
+ case RESOURCE_TYPE_LOADBALANCER:
if err := d.deployToLoadbalancer(ctx, upres.CertId); err != nil {
return nil, err
}
- case DEPLOY_RESOURCE_LISTENER:
+ case RESOURCE_TYPE_LISTENER:
if err := d.deployToListener(ctx, upres.CertId); err != nil {
return nil, err
}
@@ -108,7 +105,7 @@ func (d *AliyunCLBDeployer) Deploy(ctx context.Context, certPem string, privkeyP
return &deployer.DeployResult{}, nil
}
-func (d *AliyunCLBDeployer) deployToLoadbalancer(ctx context.Context, cloudCertId string) error {
+func (d *DeployerProvider) deployToLoadbalancer(ctx context.Context, cloudCertId string) error {
if d.config.LoadbalancerId == "" {
return errors.New("config `loadbalancerId` is required")
}
@@ -179,7 +176,7 @@ func (d *AliyunCLBDeployer) deployToLoadbalancer(ctx context.Context, cloudCertI
return nil
}
-func (d *AliyunCLBDeployer) deployToListener(ctx context.Context, cloudCertId string) error {
+func (d *DeployerProvider) deployToListener(ctx context.Context, cloudCertId string) error {
if d.config.LoadbalancerId == "" {
return errors.New("config `loadbalancerId` is required")
}
@@ -195,7 +192,7 @@ func (d *AliyunCLBDeployer) deployToListener(ctx context.Context, cloudCertId st
return nil
}
-func (d *AliyunCLBDeployer) updateListenerCertificate(ctx context.Context, cloudLoadbalancerId string, cloudListenerPort int32, cloudCertId string) error {
+func (d *DeployerProvider) updateListenerCertificate(ctx context.Context, cloudLoadbalancerId string, cloudListenerPort int32, cloudCertId string) error {
// 查询监听配置
// REF: https://help.aliyun.com/zh/slb/classic-load-balancer/developer-reference/api-slb-2014-05-15-describeloadbalancerhttpslistenerattribute
describeLoadBalancerHTTPSListenerAttributeReq := &aliyunSlb.DescribeLoadBalancerHTTPSListenerAttributeRequest{
@@ -214,8 +211,6 @@ func (d *AliyunCLBDeployer) updateListenerCertificate(ctx context.Context, cloud
// 修改监听配置
// REF: https://help.aliyun.com/zh/slb/classic-load-balancer/developer-reference/api-slb-2014-05-15-setloadbalancerhttpslistenerattribute
- //
- // 注意修改监听配置要放在修改扩展域名之后
setLoadBalancerHTTPSListenerAttributeReq := &aliyunSlb.SetLoadBalancerHTTPSListenerAttributeRequest{
RegionId: tea.String(d.config.Region),
LoadBalancerId: tea.String(cloudLoadbalancerId),
@@ -229,7 +224,7 @@ func (d *AliyunCLBDeployer) updateListenerCertificate(ctx context.Context, cloud
d.logger.Logt("已更新 CLB HTTPS 监听配置", setLoadBalancerHTTPSListenerAttributeResp)
} else {
- // 指定 SNI,需部署到扩展域名(支持泛域名)
+ // 指定 SNI,需部署到扩展域名
// 查询扩展域名
// REF: https://help.aliyun.com/zh/slb/classic-load-balancer/developer-reference/api-slb-2014-05-15-describedomainextensions
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 0b27c5f8..a845bf86 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
@@ -63,11 +63,11 @@ func TestDeploy(t *testing.T) {
fmt.Sprintf("DOMAIN: %v", fDomain),
}, "\n"))
- deployer, err := provider.New(&provider.AliyunCLBDeployerConfig{
+ deployer, err := provider.NewDeployer(&provider.DeployerConfig{
AccessKeyId: fAccessKeyId,
AccessKeySecret: fAccessKeySecret,
Region: fRegion,
- ResourceType: provider.DEPLOY_RESOURCE_LOADBALANCER,
+ ResourceType: provider.RESOURCE_TYPE_LOADBALANCER,
LoadbalancerId: fLoadbalancerId,
Domain: fDomain,
})
@@ -99,11 +99,11 @@ func TestDeploy(t *testing.T) {
fmt.Sprintf("LISTENERPORT: %v", fListenerPort),
}, "\n"))
- deployer, err := provider.New(&provider.AliyunCLBDeployerConfig{
+ deployer, err := provider.NewDeployer(&provider.DeployerConfig{
AccessKeyId: fAccessKeyId,
AccessKeySecret: fAccessKeySecret,
Region: fRegion,
- ResourceType: provider.DEPLOY_RESOURCE_LISTENER,
+ ResourceType: provider.RESOURCE_TYPE_LISTENER,
LoadbalancerId: fLoadbalancerId,
ListenerPort: int32(fListenerPort),
Domain: fDomain,
diff --git a/internal/pkg/core/deployer/providers/aliyun-clb/consts.go b/internal/pkg/core/deployer/providers/aliyun-clb/consts.go
new file mode 100644
index 00000000..ad4fb070
--- /dev/null
+++ b/internal/pkg/core/deployer/providers/aliyun-clb/consts.go
@@ -0,0 +1,10 @@
+package aliyunclb
+
+type ResourceType string
+
+const (
+ // 资源类型:部署到指定负载均衡器。
+ RESOURCE_TYPE_LOADBALANCER = ResourceType("loadbalancer")
+ // 资源类型:部署到指定监听器。
+ RESOURCE_TYPE_LISTENER = ResourceType("listener")
+)
diff --git a/internal/pkg/core/deployer/providers/aliyun-clb/defines.go b/internal/pkg/core/deployer/providers/aliyun-clb/defines.go
deleted file mode 100644
index 4a02ab20..00000000
--- a/internal/pkg/core/deployer/providers/aliyun-clb/defines.go
+++ /dev/null
@@ -1,10 +0,0 @@
-package aliyunclb
-
-type DeployResourceType string
-
-const (
- // 资源类型:部署到指定负载均衡器。
- DEPLOY_RESOURCE_LOADBALANCER = DeployResourceType("loadbalancer")
- // 资源类型:部署到指定监听器。
- DEPLOY_RESOURCE_LISTENER = DeployResourceType("listener")
-)
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 65c9a375..bfa28e7b 100644
--- a/internal/pkg/core/deployer/providers/aliyun-dcdn/aliyun_dcdn.go
+++ b/internal/pkg/core/deployer/providers/aliyun-dcdn/aliyun_dcdn.go
@@ -2,7 +2,6 @@
import (
"context"
- "errors"
"fmt"
"strings"
"time"
@@ -16,7 +15,7 @@ import (
"github.com/usual2970/certimate/internal/pkg/core/logger"
)
-type AliyunDCDNDeployerConfig struct {
+type DeployerConfig struct {
// 阿里云 AccessKeyId。
AccessKeyId string `json:"accessKeyId"`
// 阿里云 AccessKeySecret。
@@ -25,25 +24,17 @@ type AliyunDCDNDeployerConfig struct {
Domain string `json:"domain"`
}
-type AliyunDCDNDeployer struct {
- config *AliyunDCDNDeployerConfig
+type DeployerProvider struct {
+ config *DeployerConfig
logger logger.Logger
sdkClient *aliyunDcdn.Client
}
-var _ deployer.Deployer = (*AliyunDCDNDeployer)(nil)
+var _ deployer.Deployer = (*DeployerProvider)(nil)
-func New(config *AliyunDCDNDeployerConfig) (*AliyunDCDNDeployer, error) {
- return NewWithLogger(config, logger.NewNilLogger())
-}
-
-func NewWithLogger(config *AliyunDCDNDeployerConfig, logger logger.Logger) (*AliyunDCDNDeployer, error) {
+func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) {
if config == nil {
- return nil, errors.New("config is nil")
- }
-
- if logger == nil {
- return nil, errors.New("logger is nil")
+ panic("config is nil")
}
client, err := createSdkClient(config.AccessKeyId, config.AccessKeySecret)
@@ -51,14 +42,19 @@ func NewWithLogger(config *AliyunDCDNDeployerConfig, logger logger.Logger) (*Ali
return nil, xerrors.Wrap(err, "failed to create sdk client")
}
- return &AliyunDCDNDeployer{
- logger: logger,
+ return &DeployerProvider{
config: config,
+ logger: logger.NewNilLogger(),
sdkClient: client,
}, nil
}
-func (d *AliyunDCDNDeployer) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) {
+func (d *DeployerProvider) WithLogger(logger logger.Logger) *DeployerProvider {
+ d.logger = logger
+ return d
+}
+
+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, "*")
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 ffbfcd1f..04ca4c48 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
@@ -52,7 +52,7 @@ func TestDeploy(t *testing.T) {
fmt.Sprintf("DOMAIN: %v", fDomain),
}, "\n"))
- deployer, err := provider.New(&provider.AliyunDCDNDeployerConfig{
+ deployer, err := provider.NewDeployer(&provider.DeployerConfig{
AccessKeyId: fAccessKeyId,
AccessKeySecret: fAccessKeySecret,
Domain: fDomain,
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 a09f8bbf..1ccbdae5 100644
--- a/internal/pkg/core/deployer/providers/aliyun-esa/aliyun_esa.go
+++ b/internal/pkg/core/deployer/providers/aliyun-esa/aliyun_esa.go
@@ -15,10 +15,10 @@ import (
"github.com/usual2970/certimate/internal/pkg/core/deployer"
"github.com/usual2970/certimate/internal/pkg/core/logger"
"github.com/usual2970/certimate/internal/pkg/core/uploader"
- uploaderp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/aliyun-cas"
+ uploadersp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/aliyun-cas"
)
-type AliyunESADeployerConfig struct {
+type DeployerConfig struct {
// 阿里云 AccessKeyId。
AccessKeyId string `json:"accessKeyId"`
// 阿里云 AccessKeySecret。
@@ -29,26 +29,18 @@ type AliyunESADeployerConfig struct {
SiteId int64 `json:"siteId"`
}
-type AliyunESADeployer struct {
- config *AliyunESADeployerConfig
+type DeployerProvider struct {
+ config *DeployerConfig
logger logger.Logger
sdkClient *aliyunEsa.Client
sslUploader uploader.Uploader
}
-var _ deployer.Deployer = (*AliyunESADeployer)(nil)
+var _ deployer.Deployer = (*DeployerProvider)(nil)
-func New(config *AliyunESADeployerConfig) (*AliyunESADeployer, error) {
- return NewWithLogger(config, logger.NewNilLogger())
-}
-
-func NewWithLogger(config *AliyunESADeployerConfig, logger logger.Logger) (*AliyunESADeployer, error) {
+func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) {
if config == nil {
- return nil, errors.New("config is nil")
- }
-
- if logger == nil {
- return nil, errors.New("logger is nil")
+ panic("config is nil")
}
client, err := createSdkClient(config.AccessKeyId, config.AccessKeySecret, config.Region)
@@ -61,15 +53,20 @@ func NewWithLogger(config *AliyunESADeployerConfig, logger logger.Logger) (*Aliy
return nil, xerrors.Wrap(err, "failed to create ssl uploader")
}
- return &AliyunESADeployer{
- logger: logger,
+ return &DeployerProvider{
config: config,
+ logger: logger.NewNilLogger(),
sdkClient: client,
sslUploader: uploader,
}, nil
}
-func (d *AliyunESADeployer) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) {
+func (d *DeployerProvider) WithLogger(logger logger.Logger) *DeployerProvider {
+ d.logger = logger
+ return d
+}
+
+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")
}
@@ -129,7 +126,7 @@ func createSslUploader(accessKeyId, accessKeySecret, region string) (uploader.Up
}
}
- uploader, err := uploaderp.New(&uploaderp.AliyunCASUploaderConfig{
+ uploader, err := uploadersp.NewUploader(&uploadersp.UploaderConfig{
AccessKeyId: accessKeyId,
AccessKeySecret: accessKeySecret,
Region: casRegion,
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 980dc9a0..c2d81aa3 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
@@ -56,7 +56,7 @@ func TestDeploy(t *testing.T) {
fmt.Sprintf("SITEID: %v", fSiteId),
}, "\n"))
- deployer, err := provider.New(&provider.AliyunESADeployerConfig{
+ deployer, err := provider.NewDeployer(&provider.DeployerConfig{
AccessKeyId: fAccessKeyId,
AccessKeySecret: fAccessKeySecret,
Region: fRegion,
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 2e0c46af..5735da79 100644
--- a/internal/pkg/core/deployer/providers/aliyun-live/aliyun_live.go
+++ b/internal/pkg/core/deployer/providers/aliyun-live/aliyun_live.go
@@ -2,7 +2,6 @@
import (
"context"
- "errors"
"fmt"
"strings"
"time"
@@ -16,7 +15,7 @@ import (
"github.com/usual2970/certimate/internal/pkg/core/logger"
)
-type AliyunLiveDeployerConfig struct {
+type DeployerConfig struct {
// 阿里云 AccessKeyId。
AccessKeyId string `json:"accessKeyId"`
// 阿里云 AccessKeySecret。
@@ -27,25 +26,17 @@ type AliyunLiveDeployerConfig struct {
Domain string `json:"domain"`
}
-type AliyunLiveDeployer struct {
- config *AliyunLiveDeployerConfig
+type DeployerProvider struct {
+ config *DeployerConfig
logger logger.Logger
sdkClient *aliyunLive.Client
}
-var _ deployer.Deployer = (*AliyunLiveDeployer)(nil)
+var _ deployer.Deployer = (*DeployerProvider)(nil)
-func New(config *AliyunLiveDeployerConfig) (*AliyunLiveDeployer, error) {
- return NewWithLogger(config, logger.NewNilLogger())
-}
-
-func NewWithLogger(config *AliyunLiveDeployerConfig, logger logger.Logger) (*AliyunLiveDeployer, error) {
+func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) {
if config == nil {
- return nil, errors.New("config is nil")
- }
-
- if logger == nil {
- return nil, errors.New("logger is nil")
+ panic("config is nil")
}
client, err := createSdkClient(config.AccessKeyId, config.AccessKeySecret, config.Region)
@@ -53,14 +44,19 @@ func NewWithLogger(config *AliyunLiveDeployerConfig, logger logger.Logger) (*Ali
return nil, xerrors.Wrap(err, "failed to create sdk client")
}
- return &AliyunLiveDeployer{
- logger: logger,
+ return &DeployerProvider{
config: config,
+ logger: logger.NewNilLogger(),
sdkClient: client,
}, nil
}
-func (d *AliyunLiveDeployer) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) {
+func (d *DeployerProvider) WithLogger(logger logger.Logger) *DeployerProvider {
+ d.logger = logger
+ return d
+}
+
+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, "*")
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 d66f647a..fcf01147 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
@@ -16,6 +16,7 @@ var (
fInputKeyPath string
fAccessKeyId string
fAccessKeySecret string
+ fRegion string
fDomain string
)
@@ -26,6 +27,7 @@ func init() {
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", "", "")
}
@@ -37,6 +39,7 @@ Shell command to run this test:
--CERTIMATE_DEPLOYER_ALIYUNLIVE_INPUTKEYPATH="/path/to/your-input-key.pem" \
--CERTIMATE_DEPLOYER_ALIYUNLIVE_ACCESSKEYID="your-access-key-id" \
--CERTIMATE_DEPLOYER_ALIYUNLIVE_ACCESSKEYSECRET="your-access-key-secret" \
+ --CERTIMATE_DEPLOYER_ALIYUNLIVE_REGION="cn-hangzhou" \
--CERTIMATE_DEPLOYER_ALIYUNLIVE_DOMAIN="example.com"
*/
func TestDeploy(t *testing.T) {
@@ -49,12 +52,14 @@ func TestDeploy(t *testing.T) {
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.New(&provider.AliyunLiveDeployerConfig{
+ deployer, err := provider.NewDeployer(&provider.DeployerConfig{
AccessKeyId: fAccessKeyId,
AccessKeySecret: fAccessKeySecret,
+ Region: fRegion,
Domain: fDomain,
})
if err != nil {
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 6deee907..0f1f1bca 100644
--- a/internal/pkg/core/deployer/providers/aliyun-nlb/aliyun_nlb.go
+++ b/internal/pkg/core/deployer/providers/aliyun-nlb/aliyun_nlb.go
@@ -14,10 +14,10 @@ import (
"github.com/usual2970/certimate/internal/pkg/core/deployer"
"github.com/usual2970/certimate/internal/pkg/core/logger"
"github.com/usual2970/certimate/internal/pkg/core/uploader"
- uploaderp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/aliyun-cas"
+ uploadersp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/aliyun-cas"
)
-type AliyunNLBDeployerConfig struct {
+type DeployerConfig struct {
// 阿里云 AccessKeyId。
AccessKeyId string `json:"accessKeyId"`
// 阿里云 AccessKeySecret。
@@ -25,35 +25,27 @@ type AliyunNLBDeployerConfig struct {
// 阿里云地域。
Region string `json:"region"`
// 部署资源类型。
- ResourceType DeployResourceType `json:"resourceType"`
+ ResourceType ResourceType `json:"resourceType"`
// 负载均衡实例 ID。
- // 部署资源类型为 [DEPLOY_RESOURCE_LOADBALANCER] 时必填。
+ // 部署资源类型为 [RESOURCE_TYPE_LOADBALANCER] 时必填。
LoadbalancerId string `json:"loadbalancerId,omitempty"`
// 负载均衡监听 ID。
- // 部署资源类型为 [DEPLOY_RESOURCE_LISTENER] 时必填。
+ // 部署资源类型为 [RESOURCE_TYPE_LISTENER] 时必填。
ListenerId string `json:"listenerId,omitempty"`
}
-type AliyunNLBDeployer struct {
- config *AliyunNLBDeployerConfig
+type DeployerProvider struct {
+ config *DeployerConfig
logger logger.Logger
sdkClient *aliyunNlb.Client
sslUploader uploader.Uploader
}
-var _ deployer.Deployer = (*AliyunNLBDeployer)(nil)
+var _ deployer.Deployer = (*DeployerProvider)(nil)
-func New(config *AliyunNLBDeployerConfig) (*AliyunNLBDeployer, error) {
- return NewWithLogger(config, logger.NewNilLogger())
-}
-
-func NewWithLogger(config *AliyunNLBDeployerConfig, logger logger.Logger) (*AliyunNLBDeployer, error) {
+func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) {
if config == nil {
- return nil, errors.New("config is nil")
- }
-
- if logger == nil {
- return nil, errors.New("logger is nil")
+ panic("config is nil")
}
client, err := createSdkClient(config.AccessKeyId, config.AccessKeySecret, config.Region)
@@ -66,15 +58,20 @@ func NewWithLogger(config *AliyunNLBDeployerConfig, logger logger.Logger) (*Aliy
return nil, xerrors.Wrap(err, "failed to create ssl uploader")
}
- return &AliyunNLBDeployer{
- logger: logger,
+ return &DeployerProvider{
config: config,
+ logger: logger.NewNilLogger(),
sdkClient: client,
sslUploader: uploader,
}, nil
}
-func (d *AliyunNLBDeployer) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) {
+func (d *DeployerProvider) WithLogger(logger logger.Logger) *DeployerProvider {
+ d.logger = logger
+ return d
+}
+
+func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) {
// 上传证书到 CAS
upres, err := d.sslUploader.Upload(ctx, certPem, privkeyPem)
if err != nil {
@@ -85,12 +82,12 @@ func (d *AliyunNLBDeployer) Deploy(ctx context.Context, certPem string, privkeyP
// 根据部署资源类型决定部署方式
switch d.config.ResourceType {
- case DEPLOY_RESOURCE_LOADBALANCER:
+ case RESOURCE_TYPE_LOADBALANCER:
if err := d.deployToLoadbalancer(ctx, upres.CertId); err != nil {
return nil, err
}
- case DEPLOY_RESOURCE_LISTENER:
+ case RESOURCE_TYPE_LISTENER:
if err := d.deployToListener(ctx, upres.CertId); err != nil {
return nil, err
}
@@ -102,7 +99,7 @@ func (d *AliyunNLBDeployer) Deploy(ctx context.Context, certPem string, privkeyP
return &deployer.DeployResult{}, nil
}
-func (d *AliyunNLBDeployer) deployToLoadbalancer(ctx context.Context, cloudCertId string) error {
+func (d *DeployerProvider) deployToLoadbalancer(ctx context.Context, cloudCertId string) error {
if d.config.LoadbalancerId == "" {
return errors.New("config `loadbalancerId` is required")
}
@@ -171,7 +168,7 @@ func (d *AliyunNLBDeployer) deployToLoadbalancer(ctx context.Context, cloudCertI
return nil
}
-func (d *AliyunNLBDeployer) deployToListener(ctx context.Context, cloudCertId string) error {
+func (d *DeployerProvider) deployToListener(ctx context.Context, cloudCertId string) error {
if d.config.ListenerId == "" {
return errors.New("config `listenerId` is required")
}
@@ -184,7 +181,7 @@ func (d *AliyunNLBDeployer) deployToListener(ctx context.Context, cloudCertId st
return nil
}
-func (d *AliyunNLBDeployer) updateListenerCertificate(ctx context.Context, cloudListenerId string, cloudCertId string) error {
+func (d *DeployerProvider) updateListenerCertificate(ctx context.Context, cloudListenerId string, cloudCertId string) error {
// 查询监听的属性
// REF: https://help.aliyun.com/zh/slb/network-load-balancer/developer-reference/api-nlb-2022-04-30-getlistenerattribute
getListenerAttributeReq := &aliyunNlb.GetListenerAttributeRequest{
@@ -248,7 +245,7 @@ func createSslUploader(accessKeyId, accessKeySecret, region string) (uploader.Up
}
}
- uploader, err := uploaderp.New(&uploaderp.AliyunCASUploaderConfig{
+ uploader, err := uploadersp.NewUploader(&uploadersp.UploaderConfig{
AccessKeyId: accessKeyId,
AccessKeySecret: accessKeySecret,
Region: casRegion,
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 45abd932..dfaf0916 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
@@ -59,11 +59,11 @@ func TestDeploy(t *testing.T) {
fmt.Sprintf("LOADBALANCERID: %v", fLoadbalancerId),
}, "\n"))
- deployer, err := provider.New(&provider.AliyunNLBDeployerConfig{
+ deployer, err := provider.NewDeployer(&provider.DeployerConfig{
AccessKeyId: fAccessKeyId,
AccessKeySecret: fAccessKeySecret,
Region: fRegion,
- ResourceType: provider.DEPLOY_RESOURCE_LOADBALANCER,
+ ResourceType: provider.RESOURCE_TYPE_LOADBALANCER,
LoadbalancerId: fLoadbalancerId,
})
if err != nil {
@@ -94,11 +94,11 @@ func TestDeploy(t *testing.T) {
fmt.Sprintf("LISTENERID: %v", fListenerId),
}, "\n"))
- deployer, err := provider.New(&provider.AliyunNLBDeployerConfig{
+ deployer, err := provider.NewDeployer(&provider.DeployerConfig{
AccessKeyId: fAccessKeyId,
AccessKeySecret: fAccessKeySecret,
Region: fRegion,
- ResourceType: provider.DEPLOY_RESOURCE_LISTENER,
+ ResourceType: provider.RESOURCE_TYPE_LISTENER,
ListenerId: fListenerId,
})
if err != nil {
diff --git a/internal/pkg/core/deployer/providers/aliyun-nlb/consts.go b/internal/pkg/core/deployer/providers/aliyun-nlb/consts.go
new file mode 100644
index 00000000..1fa071df
--- /dev/null
+++ b/internal/pkg/core/deployer/providers/aliyun-nlb/consts.go
@@ -0,0 +1,10 @@
+package aliyunnlb
+
+type ResourceType string
+
+const (
+ // 资源类型:部署到指定负载均衡器。
+ RESOURCE_TYPE_LOADBALANCER = ResourceType("loadbalancer")
+ // 资源类型:部署到指定监听器。
+ RESOURCE_TYPE_LISTENER = ResourceType("listener")
+)
diff --git a/internal/pkg/core/deployer/providers/aliyun-nlb/defines.go b/internal/pkg/core/deployer/providers/aliyun-nlb/defines.go
deleted file mode 100644
index 14e3c2b2..00000000
--- a/internal/pkg/core/deployer/providers/aliyun-nlb/defines.go
+++ /dev/null
@@ -1,10 +0,0 @@
-package aliyunnlb
-
-type DeployResourceType string
-
-const (
- // 资源类型:部署到指定负载均衡器。
- DEPLOY_RESOURCE_LOADBALANCER = DeployResourceType("loadbalancer")
- // 资源类型:部署到指定监听器。
- DEPLOY_RESOURCE_LISTENER = DeployResourceType("listener")
-)
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 9caf0a3b..88adbf0b 100644
--- a/internal/pkg/core/deployer/providers/aliyun-oss/aliyun_oss.go
+++ b/internal/pkg/core/deployer/providers/aliyun-oss/aliyun_oss.go
@@ -12,7 +12,7 @@ import (
"github.com/usual2970/certimate/internal/pkg/core/logger"
)
-type AliyunOSSDeployerConfig struct {
+type DeployerConfig struct {
// 阿里云 AccessKeyId。
AccessKeyId string `json:"accessKeyId"`
// 阿里云 AccessKeySecret。
@@ -25,25 +25,17 @@ type AliyunOSSDeployerConfig struct {
Domain string `json:"domain"`
}
-type AliyunOSSDeployer struct {
- config *AliyunOSSDeployerConfig
+type DeployerProvider struct {
+ config *DeployerConfig
logger logger.Logger
sdkClient *oss.Client
}
-var _ deployer.Deployer = (*AliyunOSSDeployer)(nil)
+var _ deployer.Deployer = (*DeployerProvider)(nil)
-func New(config *AliyunOSSDeployerConfig) (*AliyunOSSDeployer, error) {
- return NewWithLogger(config, logger.NewNilLogger())
-}
-
-func NewWithLogger(config *AliyunOSSDeployerConfig, logger logger.Logger) (*AliyunOSSDeployer, error) {
+func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) {
if config == nil {
- return nil, errors.New("config is nil")
- }
-
- if logger == nil {
- return nil, errors.New("logger is nil")
+ panic("config is nil")
}
client, err := createSdkClient(config.AccessKeyId, config.AccessKeySecret, config.Region)
@@ -51,14 +43,19 @@ func NewWithLogger(config *AliyunOSSDeployerConfig, logger logger.Logger) (*Aliy
return nil, xerrors.Wrap(err, "failed to create sdk client")
}
- return &AliyunOSSDeployer{
- logger: logger,
+ return &DeployerProvider{
config: config,
+ logger: logger.NewNilLogger(),
sdkClient: client,
}, nil
}
-func (d *AliyunOSSDeployer) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) {
+func (d *DeployerProvider) WithLogger(logger logger.Logger) *DeployerProvider {
+ d.logger = logger
+ return d
+}
+
+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")
}
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 e25f8156..7613a003 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
@@ -60,7 +60,7 @@ func TestDeploy(t *testing.T) {
fmt.Sprintf("DOMAIN: %v", fDomain),
}, "\n"))
- deployer, err := provider.New(&provider.AliyunOSSDeployerConfig{
+ deployer, err := provider.NewDeployer(&provider.DeployerConfig{
AccessKeyId: fAccessKeyId,
AccessKeySecret: fAccessKeySecret,
Region: fRegion,
diff --git a/internal/pkg/core/deployer/providers/aliyun-vod/aliyun_vod.go b/internal/pkg/core/deployer/providers/aliyun-vod/aliyun_vod.go
new file mode 100644
index 00000000..740fbb56
--- /dev/null
+++ b/internal/pkg/core/deployer/providers/aliyun-vod/aliyun_vod.go
@@ -0,0 +1,95 @@
+package aliyunvod
+
+import (
+ "context"
+ "fmt"
+ "time"
+
+ aliyunOpen "github.com/alibabacloud-go/darabonba-openapi/v2/client"
+ "github.com/alibabacloud-go/tea/tea"
+ aliyunVod "github.com/alibabacloud-go/vod-20170321/v4/client"
+ xerrors "github.com/pkg/errors"
+
+ "github.com/usual2970/certimate/internal/pkg/core/deployer"
+ "github.com/usual2970/certimate/internal/pkg/core/logger"
+)
+
+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 logger.Logger
+ sdkClient *aliyunVod.Client
+}
+
+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, xerrors.Wrap(err, "failed to create sdk client")
+ }
+
+ return &DeployerProvider{
+ config: config,
+ logger: logger.NewNilLogger(),
+ sdkClient: client,
+ }, nil
+}
+
+func (d *DeployerProvider) WithLogger(logger logger.Logger) *DeployerProvider {
+ d.logger = logger
+ return d
+}
+
+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 := &aliyunVod.SetVodDomainSSLCertificateRequest{
+ DomainName: tea.String(d.config.Domain),
+ 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),
+ }
+ setVodDomainSSLCertificateResp, err := d.sdkClient.SetVodDomainSSLCertificate(setVodDomainSSLCertificateReq)
+ if err != nil {
+ return nil, xerrors.Wrap(err, "failed to execute sdk request 'live.SetVodDomainSSLCertificate'")
+ } else {
+ d.logger.Logt("已设置域名证书", setVodDomainSSLCertificateResp)
+ }
+
+ return &deployer.DeployResult{}, nil
+}
+
+func createSdkClient(accessKeyId, accessKeySecret, region string) (*aliyunVod.Client, error) {
+ // 接入点一览 https://help.aliyun.com/zh/vod/developer-reference/api-vod-2017-03-21-endpoint
+ endpoint := fmt.Sprintf("vod.%s.aliyuncs.com", region)
+
+ config := &aliyunOpen.Config{
+ AccessKeyId: tea.String(accessKeyId),
+ AccessKeySecret: tea.String(accessKeySecret),
+ Endpoint: tea.String(endpoint),
+ }
+
+ client, err := aliyunVod.NewClient(config)
+ if err != nil {
+ return nil, err
+ }
+
+ return client, 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
new file mode 100644
index 00000000..552ddc0f
--- /dev/null
+++ b/internal/pkg/core/deployer/providers/aliyun-vod/aliyun_vod_test.go
@@ -0,0 +1,80 @@
+package aliyunvod_test
+
+import (
+ "context"
+ "flag"
+ "fmt"
+ "os"
+ "strings"
+ "testing"
+
+ provider "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/aliyun-vod"
+)
+
+var (
+ fInputCertPath string
+ fInputKeyPath string
+ fAccessKeyId string
+ fAccessKeySecret string
+ fRegion string
+ fDomain string
+)
+
+func init() {
+ argsPrefix := "CERTIMATE_DEPLOYER_ALIYUNVOD_"
+
+ 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_vod_test.go -args \
+ --CERTIMATE_DEPLOYER_ALIYUNVOD_INPUTCERTPATH="/path/to/your-input-cert.pem" \
+ --CERTIMATE_DEPLOYER_ALIYUNVOD_INPUTKEYPATH="/path/to/your-input-key.pem" \
+ --CERTIMATE_DEPLOYER_ALIYUNVOD_ACCESSKEYID="your-access-key-id" \
+ --CERTIMATE_DEPLOYER_ALIYUNVOD_ACCESSKEYSECRET="your-access-key-secret" \
+ --CERTIMATE_DEPLOYER_ALIYUNVOD_REGION="cn-hangzhou" \
+ --CERTIMATE_DEPLOYER_ALIYUNVOD_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-waf/aliyun_waf.go b/internal/pkg/core/deployer/providers/aliyun-waf/aliyun_waf.go
index 1cc7aecd..5747d23e 100644
--- a/internal/pkg/core/deployer/providers/aliyun-waf/aliyun_waf.go
+++ b/internal/pkg/core/deployer/providers/aliyun-waf/aliyun_waf.go
@@ -14,10 +14,10 @@ import (
"github.com/usual2970/certimate/internal/pkg/core/deployer"
"github.com/usual2970/certimate/internal/pkg/core/logger"
"github.com/usual2970/certimate/internal/pkg/core/uploader"
- uploaderp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/aliyun-cas"
+ uploadersp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/aliyun-cas"
)
-type AliyunWAFDeployerConfig struct {
+type DeployerConfig struct {
// 阿里云 AccessKeyId。
AccessKeyId string `json:"accessKeyId"`
// 阿里云 AccessKeySecret。
@@ -28,26 +28,18 @@ type AliyunWAFDeployerConfig struct {
InstanceId string `json:"instanceId"`
}
-type AliyunWAFDeployer struct {
- config *AliyunWAFDeployerConfig
+type DeployerProvider struct {
+ config *DeployerConfig
logger logger.Logger
sdkClient *aliyunWaf.Client
sslUploader uploader.Uploader
}
-var _ deployer.Deployer = (*AliyunWAFDeployer)(nil)
+var _ deployer.Deployer = (*DeployerProvider)(nil)
-func New(config *AliyunWAFDeployerConfig) (*AliyunWAFDeployer, error) {
- return NewWithLogger(config, logger.NewNilLogger())
-}
-
-func NewWithLogger(config *AliyunWAFDeployerConfig, logger logger.Logger) (*AliyunWAFDeployer, error) {
+func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) {
if config == nil {
- return nil, errors.New("config is nil")
- }
-
- if logger == nil {
- return nil, errors.New("logger is nil")
+ panic("config is nil")
}
client, err := createSdkClient(config.AccessKeyId, config.AccessKeySecret, config.Region)
@@ -60,15 +52,20 @@ func NewWithLogger(config *AliyunWAFDeployerConfig, logger logger.Logger) (*Aliy
return nil, xerrors.Wrap(err, "failed to create ssl uploader")
}
- return &AliyunWAFDeployer{
- logger: logger,
+ return &DeployerProvider{
config: config,
+ logger: logger.NewNilLogger(),
sdkClient: client,
sslUploader: uploader,
}, nil
}
-func (d *AliyunWAFDeployer) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) {
+func (d *DeployerProvider) WithLogger(logger logger.Logger) *DeployerProvider {
+ d.logger = logger
+ return d
+}
+
+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")
}
@@ -142,7 +139,7 @@ func createSslUploader(accessKeyId, accessKeySecret, region string) (uploader.Up
}
}
- uploader, err := uploaderp.New(&uploaderp.AliyunCASUploaderConfig{
+ uploader, err := uploadersp.NewUploader(&uploadersp.UploaderConfig{
AccessKeyId: accessKeyId,
AccessKeySecret: accessKeySecret,
Region: casRegion,
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 2498beca..06a76c63 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
@@ -56,7 +56,7 @@ func TestDeploy(t *testing.T) {
fmt.Sprintf("INSTANCEID: %v", fInstanceId),
}, "\n"))
- deployer, err := provider.New(&provider.AliyunWAFDeployerConfig{
+ deployer, err := provider.NewDeployer(&provider.DeployerConfig{
AccessKeyId: fAccessKeyId,
AccessKeySecret: fAccessKeySecret,
Region: fRegion,
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 086dd415..2e8e09ee 100644
--- a/internal/pkg/core/deployer/providers/aws-cloudfront/aws_cloudfront.go
+++ b/internal/pkg/core/deployer/providers/aws-cloudfront/aws_cloudfront.go
@@ -14,10 +14,10 @@ import (
"github.com/usual2970/certimate/internal/pkg/core/deployer"
"github.com/usual2970/certimate/internal/pkg/core/logger"
"github.com/usual2970/certimate/internal/pkg/core/uploader"
- uploaderp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/aws-acm"
+ uploadersp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/aws-acm"
)
-type AWSCloudFrontDeployerConfig struct {
+type DeployerConfig struct {
// AWS AccessKeyId。
AccessKeyId string `json:"accessKeyId"`
// AWS SecretAccessKey。
@@ -28,26 +28,18 @@ type AWSCloudFrontDeployerConfig struct {
DistributionId string `json:"distributionId"`
}
-type AWSCloudFrontDeployer struct {
- config *AWSCloudFrontDeployerConfig
+type DeployerProvider struct {
+ config *DeployerConfig
logger logger.Logger
sdkClient *awsCf.Client
sslUploader uploader.Uploader
}
-var _ deployer.Deployer = (*AWSCloudFrontDeployer)(nil)
+var _ deployer.Deployer = (*DeployerProvider)(nil)
-func New(config *AWSCloudFrontDeployerConfig) (*AWSCloudFrontDeployer, error) {
- return NewWithLogger(config, logger.NewNilLogger())
-}
-
-func NewWithLogger(config *AWSCloudFrontDeployerConfig, logger logger.Logger) (*AWSCloudFrontDeployer, error) {
+func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) {
if config == nil {
- return nil, errors.New("config is nil")
- }
-
- if logger == nil {
- return nil, errors.New("logger is nil")
+ panic("config is nil")
}
client, err := createSdkClient(config.AccessKeyId, config.SecretAccessKey, config.Region)
@@ -55,7 +47,7 @@ func NewWithLogger(config *AWSCloudFrontDeployerConfig, logger logger.Logger) (*
return nil, xerrors.Wrap(err, "failed to create sdk client")
}
- uploader, err := uploaderp.New(&uploaderp.AWSCertificateManagerUploaderConfig{
+ uploader, err := uploadersp.NewUploader(&uploadersp.UploaderConfig{
AccessKeyId: config.AccessKeyId,
SecretAccessKey: config.SecretAccessKey,
Region: config.Region,
@@ -64,15 +56,20 @@ func NewWithLogger(config *AWSCloudFrontDeployerConfig, logger logger.Logger) (*
return nil, xerrors.Wrap(err, "failed to create ssl uploader")
}
- return &AWSCloudFrontDeployer{
- logger: logger,
+ return &DeployerProvider{
config: config,
+ logger: logger.NewNilLogger(),
sdkClient: client,
sslUploader: uploader,
}, nil
}
-func (d *AWSCloudFrontDeployer) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) {
+func (d *DeployerProvider) WithLogger(logger logger.Logger) *DeployerProvider {
+ d.logger = logger
+ return d
+}
+
+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")
}
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 89997b37..5b4c75db 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
@@ -56,11 +56,11 @@ func TestDeploy(t *testing.T) {
fmt.Sprintf("DISTRIBUTIONID: %v", fDistribuitionId),
}, "\n"))
- deployer, err := provider.New(&provider.AWSCloudFrontDeployerConfig{
+ deployer, err := provider.NewDeployer(&provider.DeployerConfig{
AccessKeyId: fAccessKeyId,
SecretAccessKey: fSecretAccessKey,
Region: fRegion,
- DistribuitionId: fDistribuitionId,
+ DistributionId: fDistribuitionId,
})
if err != nil {
t.Errorf("err: %+v", err)
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 ab932b42..df57ea1d 100644
--- a/internal/pkg/core/deployer/providers/baiducloud-cdn/baiducloud_cdn.go
+++ b/internal/pkg/core/deployer/providers/baiducloud-cdn/baiducloud_cdn.go
@@ -2,7 +2,6 @@
import (
"context"
- "errors"
"fmt"
"time"
@@ -14,7 +13,7 @@ import (
"github.com/usual2970/certimate/internal/pkg/core/logger"
)
-type BaiduCloudCDNDeployerConfig struct {
+type DeployerConfig struct {
// 百度智能云 AccessKeyId。
AccessKeyId string `json:"accessKeyId"`
// 百度智能云 SecretAccessKey。
@@ -23,25 +22,17 @@ type BaiduCloudCDNDeployerConfig struct {
Domain string `json:"domain"`
}
-type BaiduCloudCDNDeployer struct {
- config *BaiduCloudCDNDeployerConfig
+type DeployerProvider struct {
+ config *DeployerConfig
logger logger.Logger
sdkClient *bceCdn.Client
}
-var _ deployer.Deployer = (*BaiduCloudCDNDeployer)(nil)
+var _ deployer.Deployer = (*DeployerProvider)(nil)
-func New(config *BaiduCloudCDNDeployerConfig) (*BaiduCloudCDNDeployer, error) {
- return NewWithLogger(config, logger.NewNilLogger())
-}
-
-func NewWithLogger(config *BaiduCloudCDNDeployerConfig, logger logger.Logger) (*BaiduCloudCDNDeployer, error) {
+func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) {
if config == nil {
- return nil, errors.New("config is nil")
- }
-
- if logger == nil {
- return nil, errors.New("logger is nil")
+ panic("config is nil")
}
client, err := createSdkClient(config.AccessKeyId, config.SecretAccessKey)
@@ -49,14 +40,19 @@ func NewWithLogger(config *BaiduCloudCDNDeployerConfig, logger logger.Logger) (*
return nil, xerrors.Wrap(err, "failed to create sdk client")
}
- return &BaiduCloudCDNDeployer{
- logger: logger,
+ return &DeployerProvider{
config: config,
+ logger: logger.NewNilLogger(),
sdkClient: client,
}, nil
}
-func (d *BaiduCloudCDNDeployer) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) {
+func (d *DeployerProvider) WithLogger(logger logger.Logger) *DeployerProvider {
+ d.logger = logger
+ return d
+}
+
+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(
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 817600b6..ecb9a9d4 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
@@ -52,7 +52,7 @@ func TestDeploy(t *testing.T) {
fmt.Sprintf("DOMAIN: %v", fDomain),
}, "\n"))
- deployer, err := provider.New(&provider.BaiduCloudCDNDeployerConfig{
+ deployer, err := provider.NewDeployer(&provider.DeployerConfig{
AccessKeyId: fAccessKeyId,
SecretAccessKey: fSecretAccessKey,
Domain: fDomain,
diff --git a/internal/pkg/core/deployer/providers/baishan-cdn/baishan_cdn.go b/internal/pkg/core/deployer/providers/baishan-cdn/baishan_cdn.go
new file mode 100644
index 00000000..efb3353e
--- /dev/null
+++ b/internal/pkg/core/deployer/providers/baishan-cdn/baishan_cdn.go
@@ -0,0 +1,117 @@
+package baishancdn
+
+import (
+ "context"
+ "errors"
+ "fmt"
+ "time"
+
+ xerrors "github.com/pkg/errors"
+
+ "github.com/usual2970/certimate/internal/pkg/core/deployer"
+ "github.com/usual2970/certimate/internal/pkg/core/logger"
+ bssdk "github.com/usual2970/certimate/internal/pkg/vendors/baishan-sdk"
+)
+
+type DeployerConfig struct {
+ // 白山云 API Token。
+ ApiToken string `json:"apiToken"`
+ // 加速域名(支持泛域名)。
+ Domain string `json:"domain"`
+}
+
+type DeployerProvider struct {
+ config *DeployerConfig
+ logger logger.Logger
+ sdkClient *bssdk.Client
+}
+
+var _ deployer.Deployer = (*DeployerProvider)(nil)
+
+func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) {
+ if config == nil {
+ panic("config is nil")
+ }
+
+ client, err := createSdkClient(config.ApiToken)
+ if err != nil {
+ return nil, xerrors.Wrap(err, "failed to create sdk client")
+ }
+
+ return &DeployerProvider{
+ config: config,
+ logger: logger.NewNilLogger(),
+ sdkClient: client,
+ }, nil
+}
+
+func (d *DeployerProvider) WithLogger(logger logger.Logger) *DeployerProvider {
+ d.logger = 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")
+ }
+
+ // 查询域名配置
+ // REF: https://portal.baishancloud.com/track/document/api/1/1065
+ getDomainConfigReq := &bssdk.GetDomainConfigRequest{
+ Domains: d.config.Domain,
+ Config: "https",
+ }
+ getDomainConfigResp, err := d.sdkClient.GetDomainConfig(getDomainConfigReq)
+ if err != nil {
+ return nil, xerrors.Wrap(err, "failed to execute sdk request 'baishan.GetDomainConfig'")
+ } else if len(getDomainConfigResp.Data) == 0 {
+ return nil, errors.New("domain config not found")
+ } else {
+ d.logger.Logt("已查询到域名配置", getDomainConfigResp)
+ }
+
+ // 新增证书
+ // REF: https://portal.baishancloud.com/track/document/downloadPdf/1441
+ createCertificateReq := &bssdk.CreateCertificateRequest{
+ Certificate: certPem,
+ Key: privkeyPem,
+ Name: fmt.Sprintf("certimate_%d", time.Now().UnixMilli()),
+ }
+ createCertificateResp, err := d.sdkClient.CreateCertificate(createCertificateReq)
+ if err != nil {
+ return nil, xerrors.Wrap(err, "failed to execute sdk request 'baishan.CreateCertificate'")
+ } else {
+ d.logger.Logt("已新增证书", createCertificateResp)
+ }
+
+ // 设置域名配置
+ // REF: https://portal.baishancloud.com/track/document/api/1/1045
+ setDomainConfigReq := &bssdk.SetDomainConfigRequest{
+ Domains: d.config.Domain,
+ Config: &bssdk.DomainConfig{
+ Https: &bssdk.DomainConfigHttps{
+ CertId: createCertificateResp.Data.CertId,
+ ForceHttps: getDomainConfigResp.Data[0].Config.Https.ForceHttps,
+ EnableHttp2: getDomainConfigResp.Data[0].Config.Https.EnableHttp2,
+ EnableOcsp: getDomainConfigResp.Data[0].Config.Https.EnableOcsp,
+ },
+ },
+ }
+ setDomainConfigResp, err := d.sdkClient.SetDomainConfig(setDomainConfigReq)
+ if err != nil {
+ return nil, xerrors.Wrap(err, "failed to execute sdk request 'baishan.SetDomainConfig'")
+ } else {
+ d.logger.Logt("已设置域名配置", setDomainConfigResp)
+ }
+
+ return &deployer.DeployResult{}, nil
+}
+
+func createSdkClient(apiToken string) (*bssdk.Client, error) {
+ if apiToken == "" {
+ return nil, errors.New("invalid baishan api token")
+ }
+
+ client := bssdk.NewClient(apiToken)
+ return client, nil
+}
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
new file mode 100644
index 00000000..5534a232
--- /dev/null
+++ b/internal/pkg/core/deployer/providers/baishan-cdn/baishan_cdn_test.go
@@ -0,0 +1,70 @@
+package baishancdn_test
+
+import (
+ "context"
+ "flag"
+ "fmt"
+ "os"
+ "strings"
+ "testing"
+
+ provider "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/baishan-cdn"
+)
+
+var (
+ fInputCertPath string
+ fInputKeyPath string
+ fApiToken string
+ fDomain string
+)
+
+func init() {
+ argsPrefix := "CERTIMATE_DEPLOYER_BAISHANCDN_"
+
+ flag.StringVar(&fInputCertPath, argsPrefix+"INPUTCERTPATH", "", "")
+ flag.StringVar(&fInputKeyPath, argsPrefix+"INPUTKEYPATH", "", "")
+ flag.StringVar(&fApiToken, argsPrefix+"APITOKEN", "", "")
+ flag.StringVar(&fDomain, argsPrefix+"DOMAIN", "", "")
+}
+
+/*
+Shell command to run this test:
+
+ go test -v ./baishan_cdn_test.go -args \
+ --CERTIMATE_DEPLOYER_BAISHANCDN_INPUTCERTPATH="/path/to/your-input-cert.pem" \
+ --CERTIMATE_DEPLOYER_BAISHANCDN_INPUTKEYPATH="/path/to/your-input-key.pem" \
+ --CERTIMATE_DEPLOYER_BAISHANCDN_APITOKEN="your-api-token" \
+ --CERTIMATE_DEPLOYER_BAISHANCDN_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("APITOKEN: %v", fApiToken),
+ fmt.Sprintf("DOMAIN: %v", fDomain),
+ }, "\n"))
+
+ deployer, err := provider.NewDeployer(&provider.DeployerConfig{
+ ApiToken: fApiToken,
+ 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/baotapanel-console/baotapanel_console.go b/internal/pkg/core/deployer/providers/baotapanel-console/baotapanel_console.go
new file mode 100644
index 00000000..6343acf7
--- /dev/null
+++ b/internal/pkg/core/deployer/providers/baotapanel-console/baotapanel_console.go
@@ -0,0 +1,93 @@
+package baotapanelconsole
+
+import (
+ "context"
+ "errors"
+ "net/url"
+
+ xerrors "github.com/pkg/errors"
+
+ "github.com/usual2970/certimate/internal/pkg/core/deployer"
+ "github.com/usual2970/certimate/internal/pkg/core/logger"
+ btsdk "github.com/usual2970/certimate/internal/pkg/vendors/btpanel-sdk"
+)
+
+type DeployerConfig struct {
+ // 宝塔面板地址。
+ ApiUrl string `json:"apiUrl"`
+ // 宝塔面板接口密钥。
+ ApiKey string `json:"apiKey"`
+ // 是否自动重启。
+ AutoRestart bool `json:"autoRestart"`
+}
+
+type DeployerProvider struct {
+ config *DeployerConfig
+ logger logger.Logger
+ sdkClient *btsdk.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.ApiKey)
+ if err != nil {
+ return nil, xerrors.Wrap(err, "failed to create sdk client")
+ }
+
+ return &DeployerProvider{
+ config: config,
+ logger: logger.NewNilLogger(),
+ sdkClient: client,
+ }, nil
+}
+
+func (d *DeployerProvider) WithLogger(logger logger.Logger) *DeployerProvider {
+ d.logger = logger
+ return d
+}
+
+func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) {
+ // 设置面板 SSL 证书
+ configSavePanelSSLReq := &btsdk.ConfigSavePanelSSLRequest{
+ PrivateKey: privkeyPem,
+ Certificate: certPem,
+ }
+ configSavePanelSSLResp, err := d.sdkClient.ConfigSavePanelSSL(configSavePanelSSLReq)
+ if err != nil {
+ return nil, xerrors.Wrap(err, "failed to execute sdk request 'bt.ConfigSavePanelSSL'")
+ } else {
+ d.logger.Logt("已设置面板 SSL 证书", configSavePanelSSLResp)
+ }
+
+ if d.config.AutoRestart {
+ // 重启面板
+ systemServiceAdminReq := &btsdk.SystemServiceAdminRequest{
+ Name: "nginx",
+ Type: "restart",
+ }
+ _, err := d.sdkClient.SystemServiceAdmin(systemServiceAdminReq)
+ if err != nil {
+ return nil, xerrors.Wrap(err, "failed to execute sdk request 'bt.SystemServiceAdmin'")
+ }
+ }
+
+ return &deployer.DeployResult{}, nil
+}
+
+func createSdkClient(apiUrl, apiKey string) (*btsdk.Client, error) {
+ if _, err := url.Parse(apiUrl); err != nil {
+ return nil, errors.New("invalid baota api url")
+ }
+
+ if apiKey == "" {
+ return nil, errors.New("invalid baota api key")
+ }
+
+ client := btsdk.NewClient(apiUrl, apiKey)
+ return client, nil
+}
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
new file mode 100644
index 00000000..06a2f096
--- /dev/null
+++ b/internal/pkg/core/deployer/providers/baotapanel-console/baotapanel_console_test.go
@@ -0,0 +1,70 @@
+package baotapanelconsole_test
+
+import (
+ "context"
+ "flag"
+ "fmt"
+ "os"
+ "strings"
+ "testing"
+
+ provider "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/baotapanel-console"
+)
+
+var (
+ fInputCertPath string
+ fInputKeyPath string
+ fApiUrl string
+ fApiKey string
+)
+
+func init() {
+ argsPrefix := "CERTIMATE_DEPLOYER_BAOTAPANELCONSOLE_"
+
+ flag.StringVar(&fInputCertPath, argsPrefix+"INPUTCERTPATH", "", "")
+ flag.StringVar(&fInputKeyPath, argsPrefix+"INPUTKEYPATH", "", "")
+ flag.StringVar(&fApiUrl, argsPrefix+"APIURL", "", "")
+ flag.StringVar(&fApiKey, argsPrefix+"APIKEY", "", "")
+}
+
+/*
+Shell command to run this test:
+
+ go test -v ./baotapanel_console_test.go -args \
+ --CERTIMATE_DEPLOYER_BAOTAPANELCONSOLE_INPUTCERTPATH="/path/to/your-input-cert.pem" \
+ --CERTIMATE_DEPLOYER_BAOTAPANELCONSOLE_INPUTKEYPATH="/path/to/your-input-key.pem" \
+ --CERTIMATE_DEPLOYER_BAOTAPANELCONSOLE_APIURL="http://127.0.0.1:8888" \
+ --CERTIMATE_DEPLOYER_BAOTAPANELCONSOLE_APIKEY="your-api-key"
+*/
+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("APIKEY: %v", fApiKey),
+ }, "\n"))
+
+ deployer, err := provider.NewDeployer(&provider.DeployerConfig{
+ ApiUrl: fApiUrl,
+ ApiKey: fApiKey,
+ })
+ 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/baotapanel-site/baotapanel_site.go b/internal/pkg/core/deployer/providers/baotapanel-site/baotapanel_site.go
index 336e2a5d..62cef9de 100644
--- a/internal/pkg/core/deployer/providers/baotapanel-site/baotapanel_site.go
+++ b/internal/pkg/core/deployer/providers/baotapanel-site/baotapanel_site.go
@@ -3,42 +3,41 @@
import (
"context"
"errors"
+ "fmt"
+ "net/url"
xerrors "github.com/pkg/errors"
"github.com/usual2970/certimate/internal/pkg/core/deployer"
"github.com/usual2970/certimate/internal/pkg/core/logger"
+ "github.com/usual2970/certimate/internal/pkg/utils/slices"
btsdk "github.com/usual2970/certimate/internal/pkg/vendors/btpanel-sdk"
)
-type BaotaPanelSiteDeployerConfig struct {
+type DeployerConfig struct {
// 宝塔面板地址。
ApiUrl string `json:"apiUrl"`
// 宝塔面板接口密钥。
ApiKey string `json:"apiKey"`
- // 站点名称
- SiteName string `json:"siteName"`
+ // 站点类型。
+ SiteType string `json:"siteType"`
+ // 站点名称(单个)。
+ SiteName string `json:"siteName,omitempty"`
+ // 站点名称(多个)。
+ SiteNames []string `json:"siteNames,omitempty"`
}
-type BaotaPanelSiteDeployer struct {
- config *BaotaPanelSiteDeployerConfig
+type DeployerProvider struct {
+ config *DeployerConfig
logger logger.Logger
- sdkClient *btsdk.BaoTaPanelClient
+ sdkClient *btsdk.Client
}
-var _ deployer.Deployer = (*BaotaPanelSiteDeployer)(nil)
+var _ deployer.Deployer = (*DeployerProvider)(nil)
-func New(config *BaotaPanelSiteDeployerConfig) (*BaotaPanelSiteDeployer, error) {
- return NewWithLogger(config, logger.NewNilLogger())
-}
-
-func NewWithLogger(config *BaotaPanelSiteDeployerConfig, logger logger.Logger) (*BaotaPanelSiteDeployer, error) {
+func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) {
if config == nil {
- return nil, errors.New("config is nil")
- }
-
- if logger == nil {
- return nil, errors.New("logger is nil")
+ panic("config is nil")
}
client, err := createSdkClient(config.ApiUrl, config.ApiKey)
@@ -46,36 +45,92 @@ func NewWithLogger(config *BaotaPanelSiteDeployerConfig, logger logger.Logger) (
return nil, xerrors.Wrap(err, "failed to create sdk client")
}
- return &BaotaPanelSiteDeployer{
- logger: logger,
+ return &DeployerProvider{
config: config,
+ logger: logger.NewNilLogger(),
sdkClient: client,
}, nil
}
-func (d *BaotaPanelSiteDeployer) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) {
- if d.config.SiteName == "" {
- return nil, errors.New("config `siteName` is required")
- }
+func (d *DeployerProvider) WithLogger(logger logger.Logger) *DeployerProvider {
+ d.logger = logger
+ return d
+}
- // 设置站点 SSL 证书
- setSiteSSLReq := &btsdk.SetSiteSSLRequest{
- SiteName: d.config.SiteName,
- Type: "1",
- Key: privkeyPem,
- Csr: certPem,
- }
- setSiteSSLResp, err := d.sdkClient.SetSiteSSL(setSiteSSLReq)
- if err != nil {
- return nil, xerrors.Wrap(err, "failed to execute sdk request 'bt.SetSiteSSL'")
- }
+func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) {
+ switch d.config.SiteType {
+ case "php":
+ {
+ if d.config.SiteName == "" {
+ return nil, errors.New("config `siteName` is required")
+ }
- d.logger.Logt("已设置站点 SSL 证书", setSiteSSLResp)
+ // 设置站点 SSL 证书
+ siteSetSSLReq := &btsdk.SiteSetSSLRequest{
+ SiteName: d.config.SiteName,
+ Type: "0",
+ Certificate: certPem,
+ PrivateKey: privkeyPem,
+ }
+ siteSetSSLResp, err := d.sdkClient.SiteSetSSL(siteSetSSLReq)
+ if err != nil {
+ return nil, xerrors.Wrap(err, "failed to execute sdk request 'bt.SiteSetSSL'")
+ } else {
+ d.logger.Logt("已设置站点证书", siteSetSSLResp)
+ }
+ }
+
+ case "other":
+ {
+ if len(d.config.SiteNames) == 0 {
+ return nil, errors.New("config `siteNames` is required")
+ }
+
+ // 上传证书
+ sslCertSaveCertReq := &btsdk.SSLCertSaveCertRequest{
+ Certificate: certPem,
+ PrivateKey: privkeyPem,
+ }
+ sslCertSaveCertResp, err := d.sdkClient.SSLCertSaveCert(sslCertSaveCertReq)
+ if err != nil {
+ return nil, xerrors.Wrap(err, "failed to execute sdk request 'bt.SSLCertSaveCert'")
+ } else {
+ d.logger.Logt("已上传证书", sslCertSaveCertResp)
+ }
+
+ // 设置站点证书
+ sslSetBatchCertToSiteReq := &btsdk.SSLSetBatchCertToSiteRequest{
+ BatchInfo: slices.Map(d.config.SiteNames, func(siteName string) *btsdk.SSLSetBatchCertToSiteRequestBatchInfo {
+ return &btsdk.SSLSetBatchCertToSiteRequestBatchInfo{
+ SiteName: siteName,
+ SSLHash: sslCertSaveCertResp.SSLHash,
+ }
+ }),
+ }
+ sslSetBatchCertToSiteResp, err := d.sdkClient.SSLSetBatchCertToSite(sslSetBatchCertToSiteReq)
+ if err != nil {
+ return nil, xerrors.Wrap(err, "failed to execute sdk request 'bt.SSLSetBatchCertToSite'")
+ } else {
+ d.logger.Logt("已设置站点证书", sslSetBatchCertToSiteResp)
+ }
+ }
+
+ default:
+ return nil, fmt.Errorf("unsupported site type: %s", d.config.SiteType)
+ }
return &deployer.DeployResult{}, nil
}
-func createSdkClient(apiUrl, apiKey string) (*btsdk.BaoTaPanelClient, error) {
- client := btsdk.NewBaoTaPanelClient(apiUrl, apiKey)
+func createSdkClient(apiUrl, apiKey string) (*btsdk.Client, error) {
+ if _, err := url.Parse(apiUrl); err != nil {
+ return nil, errors.New("invalid baota api url")
+ }
+
+ if apiKey == "" {
+ return nil, errors.New("invalid baota api key")
+ }
+
+ client := btsdk.NewClient(apiUrl, apiKey)
return client, nil
}
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 486e8428..4c31b021 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
@@ -16,6 +16,7 @@ var (
fInputKeyPath string
fApiUrl string
fApiKey string
+ fSiteType string
fSiteName string
)
@@ -26,6 +27,7 @@ func init() {
flag.StringVar(&fInputKeyPath, argsPrefix+"INPUTKEYPATH", "", "")
flag.StringVar(&fApiUrl, argsPrefix+"APIURL", "", "")
flag.StringVar(&fApiKey, argsPrefix+"APIKEY", "", "")
+ flag.StringVar(&fSiteType, argsPrefix+"SITETYPE", "", "")
flag.StringVar(&fSiteName, argsPrefix+"SITENAME", "", "")
}
@@ -35,9 +37,10 @@ Shell command to run this test:
go test -v ./baotapanel_site_test.go -args \
--CERTIMATE_DEPLOYER_BAOTAPANELSITE_INPUTCERTPATH="/path/to/your-input-cert.pem" \
--CERTIMATE_DEPLOYER_BAOTAPANELSITE_INPUTKEYPATH="/path/to/your-input-key.pem" \
- --CERTIMATE_DEPLOYER_BAOTAPANELSITE_APIURL="your-baota-panel-url" \
- --CERTIMATE_DEPLOYER_BAOTAPANELSITE_APIKEY="your-baota-panel-key" \
- --CERTIMATE_DEPLOYER_BAOTAPANELSITE_SITENAME="your-baota-site-name"
+ --CERTIMATE_DEPLOYER_BAOTAPANELSITE_APIURL="http://127.0.0.1:8888" \
+ --CERTIMATE_DEPLOYER_BAOTAPANELSITE_APIKEY="your-api-key" \
+ --CERTIMATE_DEPLOYER_BAOTAPANELSITE_SITETYPE="php" \
+ --CERTIMATE_DEPLOYER_BAOTAPANELSITE_SITENAME="your-site-name"
*/
func TestDeploy(t *testing.T) {
flag.Parse()
@@ -49,13 +52,16 @@ func TestDeploy(t *testing.T) {
fmt.Sprintf("INPUTKEYPATH: %v", fInputKeyPath),
fmt.Sprintf("APIURL: %v", fApiUrl),
fmt.Sprintf("APIKEY: %v", fApiKey),
+ fmt.Sprintf("SITETYPE: %v", fSiteType),
fmt.Sprintf("SITENAME: %v", fSiteName),
}, "\n"))
- deployer, err := provider.New(&provider.BaotaPanelSiteDeployerConfig{
- ApiUrl: fApiUrl,
- ApiKey: fApiKey,
- SiteName: fSiteName,
+ deployer, err := provider.NewDeployer(&provider.DeployerConfig{
+ ApiUrl: fApiUrl,
+ ApiKey: fApiKey,
+ SiteType: fSiteType,
+ SiteName: fSiteName,
+ SiteNames: []string{fSiteName},
})
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 2a695513..909a2e7d 100644
--- a/internal/pkg/core/deployer/providers/byteplus-cdn/byteplus_cdn.go
+++ b/internal/pkg/core/deployer/providers/byteplus-cdn/byteplus_cdn.go
@@ -12,10 +12,10 @@ import (
"github.com/usual2970/certimate/internal/pkg/core/deployer"
"github.com/usual2970/certimate/internal/pkg/core/logger"
"github.com/usual2970/certimate/internal/pkg/core/uploader"
- uploaderp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/byteplus-cdn"
+ uploadersp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/byteplus-cdn"
)
-type BytePlusCDNDeployerConfig struct {
+type DeployerConfig struct {
// BytePlus AccessKey。
AccessKey string `json:"accessKey"`
// BytePlus SecretKey。
@@ -24,33 +24,25 @@ type BytePlusCDNDeployerConfig struct {
Domain string `json:"domain"`
}
-type BytePlusCDNDeployer struct {
- config *BytePlusCDNDeployerConfig
+type DeployerProvider struct {
+ config *DeployerConfig
logger logger.Logger
sdkClient *bpCdn.CDN
sslUploader uploader.Uploader
}
-var _ deployer.Deployer = (*BytePlusCDNDeployer)(nil)
+var _ deployer.Deployer = (*DeployerProvider)(nil)
-func New(config *BytePlusCDNDeployerConfig) (*BytePlusCDNDeployer, error) {
- return NewWithLogger(config, logger.NewNilLogger())
-}
-
-func NewWithLogger(config *BytePlusCDNDeployerConfig, logger logger.Logger) (*BytePlusCDNDeployer, error) {
+func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) {
if config == nil {
- return nil, errors.New("config is nil")
- }
-
- if logger == nil {
- return nil, errors.New("logger is nil")
+ panic("config is nil")
}
client := bpCdn.NewInstance()
client.Client.SetAccessKey(config.AccessKey)
client.Client.SetSecretKey(config.SecretKey)
- uploader, err := uploaderp.New(&uploaderp.ByteplusCDNUploaderConfig{
+ uploader, err := uploadersp.NewUploader(&uploadersp.UploaderConfig{
AccessKey: config.AccessKey,
SecretKey: config.SecretKey,
})
@@ -58,15 +50,20 @@ func NewWithLogger(config *BytePlusCDNDeployerConfig, logger logger.Logger) (*By
return nil, xerrors.Wrap(err, "failed to create ssl uploader")
}
- return &BytePlusCDNDeployer{
- logger: logger,
+ return &DeployerProvider{
config: config,
+ logger: logger.NewNilLogger(),
sdkClient: client,
sslUploader: uploader,
}, nil
}
-func (d *BytePlusCDNDeployer) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) {
+func (d *DeployerProvider) WithLogger(logger logger.Logger) *DeployerProvider {
+ d.logger = logger
+ return d
+}
+
+func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) {
// 上传证书到 CDN
upres, err := d.sslUploader.Upload(ctx, certPem, privkeyPem)
if err != nil {
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 9de97be6..ee09e8ee 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
@@ -52,7 +52,7 @@ func TestDeploy(t *testing.T) {
fmt.Sprintf("DOMAIN: %v", fDomain),
}, "\n"))
- deployer, err := provider.New(&provider.BytePlusCDNDeployerConfig{
+ deployer, err := provider.NewDeployer(&provider.DeployerConfig{
AccessKey: fAccessKey,
SecretKey: fSecretKey,
Domain: fDomain,
diff --git a/internal/pkg/core/deployer/providers/cachefly/cachefly.go b/internal/pkg/core/deployer/providers/cachefly/cachefly.go
new file mode 100644
index 00000000..8c6f129d
--- /dev/null
+++ b/internal/pkg/core/deployer/providers/cachefly/cachefly.go
@@ -0,0 +1,72 @@
+package cachefly
+
+import (
+ "context"
+ "errors"
+
+ xerrors "github.com/pkg/errors"
+
+ "github.com/usual2970/certimate/internal/pkg/core/deployer"
+ "github.com/usual2970/certimate/internal/pkg/core/logger"
+ cfsdk "github.com/usual2970/certimate/internal/pkg/vendors/cachefly-sdk"
+)
+
+type DeployerConfig struct {
+ // CacheFly API Token。
+ ApiToken string `json:"apiToken"`
+}
+
+type DeployerProvider struct {
+ config *DeployerConfig
+ logger logger.Logger
+ sdkClient *cfsdk.Client
+}
+
+var _ deployer.Deployer = (*DeployerProvider)(nil)
+
+func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) {
+ if config == nil {
+ panic("config is nil")
+ }
+
+ client, err := createSdkClient(config.ApiToken)
+ if err != nil {
+ return nil, xerrors.Wrap(err, "failed to create sdk client")
+ }
+
+ return &DeployerProvider{
+ config: config,
+ logger: logger.NewNilLogger(),
+ sdkClient: client,
+ }, nil
+}
+
+func (d *DeployerProvider) WithLogger(logger logger.Logger) *DeployerProvider {
+ d.logger = logger
+ return d
+}
+
+func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) {
+ // 上传证书
+ createCertificateReq := &cfsdk.CreateCertificateRequest{
+ Certificate: certPem,
+ CertificateKey: privkeyPem,
+ }
+ createCertificateResp, err := d.sdkClient.CreateCertificate(createCertificateReq)
+ if err != nil {
+ return nil, xerrors.Wrap(err, "failed to execute sdk request 'cachefly.CreateCertificate'")
+ } else {
+ d.logger.Logt("已上传证书", createCertificateResp)
+ }
+
+ return &deployer.DeployResult{}, nil
+}
+
+func createSdkClient(apiToken string) (*cfsdk.Client, error) {
+ if apiToken == "" {
+ return nil, errors.New("invalid cachefly api token")
+ }
+
+ client := cfsdk.NewClient(apiToken)
+ return client, nil
+}
diff --git a/internal/pkg/core/deployer/providers/cachefly/cachefly_test.go b/internal/pkg/core/deployer/providers/cachefly/cachefly_test.go
new file mode 100644
index 00000000..1de6047e
--- /dev/null
+++ b/internal/pkg/core/deployer/providers/cachefly/cachefly_test.go
@@ -0,0 +1,65 @@
+package cachefly_test
+
+import (
+ "context"
+ "flag"
+ "fmt"
+ "os"
+ "strings"
+ "testing"
+
+ provider "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/cachefly"
+)
+
+var (
+ fInputCertPath string
+ fInputKeyPath string
+ fApiToken string
+)
+
+func init() {
+ argsPrefix := "CERTIMATE_DEPLOYER_CACHEFLY_"
+
+ flag.StringVar(&fInputCertPath, argsPrefix+"INPUTCERTPATH", "", "")
+ flag.StringVar(&fInputKeyPath, argsPrefix+"INPUTKEYPATH", "", "")
+ flag.StringVar(&fApiToken, argsPrefix+"APITOKEN", "", "")
+}
+
+/*
+Shell command to run this test:
+
+ go test -v ./cachefly_test.go -args \
+ --CERTIMATE_DEPLOYER_CACHEFLY_INPUTCERTPATH="/path/to/your-input-cert.pem" \
+ --CERTIMATE_DEPLOYER_CACHEFLY_INPUTKEYPATH="/path/to/your-input-key.pem" \
+ --CERTIMATE_DEPLOYER_CACHEFLY_APITOKEN="your-api-token"
+*/
+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("APITOKEN: %v", fApiToken),
+ }, "\n"))
+
+ deployer, err := provider.NewDeployer(&provider.DeployerConfig{
+ ApiToken: fApiToken,
+ })
+ 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/cdnfly/cdnfly.go b/internal/pkg/core/deployer/providers/cdnfly/cdnfly.go
new file mode 100644
index 00000000..c98d9ae4
--- /dev/null
+++ b/internal/pkg/core/deployer/providers/cdnfly/cdnfly.go
@@ -0,0 +1,177 @@
+package cdnfly
+
+import (
+ "context"
+ "encoding/json"
+ "errors"
+ "fmt"
+ "net/url"
+ "time"
+
+ xerrors "github.com/pkg/errors"
+
+ "github.com/usual2970/certimate/internal/pkg/core/deployer"
+ "github.com/usual2970/certimate/internal/pkg/core/logger"
+ cfsdk "github.com/usual2970/certimate/internal/pkg/vendors/cdnfly-sdk"
+)
+
+type DeployerConfig struct {
+ // Cdnfly 地址。
+ ApiUrl string `json:"apiUrl"`
+ // Cdnfly 用户端 API Key。
+ ApiKey string `json:"apiKey"`
+ // Cdnfly 用户端 API Secret。
+ ApiSecret string `json:"apiSecret"`
+ // 部署资源类型。
+ ResourceType ResourceType `json:"resourceType"`
+ // 网站 ID。
+ // 部署资源类型为 [RESOURCE_TYPE_SITE] 时必填。
+ SiteId string `json:"siteId,omitempty"`
+ // 证书 ID。
+ // 部署资源类型为 [RESOURCE_TYPE_CERTIFICATE] 时必填。
+ CertificateId string `json:"certificateId,omitempty"`
+}
+
+type DeployerProvider struct {
+ config *DeployerConfig
+ logger logger.Logger
+ sdkClient *cfsdk.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.ApiKey, config.ApiSecret)
+ if err != nil {
+ return nil, xerrors.Wrap(err, "failed to create sdk client")
+ }
+
+ return &DeployerProvider{
+ config: config,
+ logger: logger.NewNilLogger(),
+ sdkClient: client,
+ }, nil
+}
+
+func (d *DeployerProvider) WithLogger(logger logger.Logger) *DeployerProvider {
+ 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_SITE:
+ 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 {
+ return nil, err
+ }
+
+ default:
+ 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 {
+ if d.config.SiteId == "" {
+ return errors.New("config `siteId` is required")
+ }
+
+ // 获取单个网站详情
+ // REF: https://doc.cdnfly.cn/wangzhanguanli-v1-sites.html#%E8%8E%B7%E5%8F%96%E5%8D%95%E4%B8%AA%E7%BD%91%E7%AB%99%E8%AF%A6%E6%83%85
+ getSiteReq := &cfsdk.GetSiteRequest{
+ Id: d.config.SiteId,
+ }
+ getSiteResp, err := d.sdkClient.GetSite(getSiteReq)
+ if err != nil {
+ return xerrors.Wrap(err, "failed to execute sdk request 'cdnfly.GetSite'")
+ } else {
+ d.logger.Logt("已获取网站详情", getSiteResp)
+ }
+
+ // 添加单个证书
+ // REF: https://doc.cdnfly.cn/wangzhanzhengshu-v1-certs.html#%E6%B7%BB%E5%8A%A0%E5%8D%95%E4%B8%AA%E6%88%96%E5%A4%9A%E4%B8%AA%E8%AF%81%E4%B9%A6-%E5%A4%9A%E4%B8%AA%E8%AF%81%E4%B9%A6%E6%97%B6%E6%95%B0%E6%8D%AE%E6%A0%BC%E5%BC%8F%E4%B8%BA%E6%95%B0%E7%BB%84
+ createCertificateReq := &cfsdk.CreateCertificateRequest{
+ Name: fmt.Sprintf("certimate-%d", time.Now().UnixMilli()),
+ Type: "custom",
+ Cert: certPem,
+ Key: privkeyPem,
+ }
+ createCertificateResp, err := d.sdkClient.CreateCertificate(createCertificateReq)
+ if err != nil {
+ return xerrors.Wrap(err, "failed to execute sdk request 'cdnfly.CreateCertificate'")
+ } else {
+ d.logger.Logt("已添加证书", createCertificateResp)
+ }
+
+ // 修改单个网站
+ // REF: https://doc.cdnfly.cn/wangzhanguanli-v1-sites.html#%E4%BF%AE%E6%94%B9%E5%8D%95%E4%B8%AA%E7%BD%91%E7%AB%99
+ updateSiteHttpsListenMap := make(map[string]any)
+ _ = json.Unmarshal([]byte(getSiteResp.Data.HttpsListen), &updateSiteHttpsListenMap)
+ updateSiteHttpsListenMap["cert"] = createCertificateResp.Data
+ updateSiteHttpsListenData, _ := json.Marshal(updateSiteHttpsListenMap)
+ updateSiteHttpsListen := string(updateSiteHttpsListenData)
+ updateSiteReq := &cfsdk.UpdateSiteRequest{
+ Id: d.config.SiteId,
+ HttpsListen: &updateSiteHttpsListen,
+ }
+ updateSiteResp, err := d.sdkClient.UpdateSite(updateSiteReq)
+ if err != nil {
+ return xerrors.Wrap(err, "failed to execute sdk request 'cdnfly.UpdateSite'")
+ } else {
+ d.logger.Logt("已修改网站", updateSiteResp)
+ }
+
+ return nil
+}
+
+func (d *DeployerProvider) deployToCertificate(ctx context.Context, certPem string, privkeyPem string) error {
+ if d.config.CertificateId == "" {
+ return errors.New("config `certificateId` is required")
+ }
+
+ // 修改单个证书
+ // REF: https://doc.cdnfly.cn/wangzhanzhengshu-v1-certs.html#%E4%BF%AE%E6%94%B9%E5%8D%95%E4%B8%AA%E8%AF%81%E4%B9%A6
+ updateCertificateType := "custom"
+ updateCertificateReq := &cfsdk.UpdateCertificateRequest{
+ Id: d.config.CertificateId,
+ Type: &updateCertificateType,
+ Cert: &certPem,
+ Key: &privkeyPem,
+ }
+ updateCertificateResp, err := d.sdkClient.UpdateCertificate(updateCertificateReq)
+ if err != nil {
+ return xerrors.Wrap(err, "failed to execute sdk request 'cdnfly.UpdateCertificate'")
+ } else {
+ d.logger.Logt("已修改证书", updateCertificateResp)
+ }
+
+ return nil
+}
+
+func createSdkClient(apiUrl, apiKey, apiSecret string) (*cfsdk.Client, error) {
+ if _, err := url.Parse(apiUrl); err != nil {
+ return nil, errors.New("invalid cachefly api url")
+ }
+
+ if apiKey == "" {
+ return nil, errors.New("invalid cachefly api key")
+ }
+
+ if apiSecret == "" {
+ return nil, errors.New("invalid cachefly api secret")
+ }
+
+ client := cfsdk.NewClient(apiUrl, apiKey, apiSecret)
+ 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
new file mode 100644
index 00000000..fd17df9c
--- /dev/null
+++ b/internal/pkg/core/deployer/providers/cdnfly/cdnfly_test.go
@@ -0,0 +1,81 @@
+package cdnfly_test
+
+import (
+ "context"
+ "flag"
+ "fmt"
+ "os"
+ "strings"
+ "testing"
+
+ provider "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/cdnfly"
+)
+
+var (
+ fInputCertPath string
+ fInputKeyPath string
+ fApiUrl string
+ fApiKey string
+ fApiSecret string
+ fCertificateId string
+)
+
+func init() {
+ argsPrefix := "CERTIMATE_DEPLOYER_CDNFLY_"
+
+ flag.StringVar(&fInputCertPath, argsPrefix+"INPUTCERTPATH", "", "")
+ flag.StringVar(&fInputKeyPath, argsPrefix+"INPUTKEYPATH", "", "")
+ flag.StringVar(&fApiUrl, argsPrefix+"APIURL", "", "")
+ flag.StringVar(&fApiKey, argsPrefix+"APIKEY", "", "")
+ flag.StringVar(&fApiSecret, argsPrefix+"APISECRET", "", "")
+ flag.StringVar(&fCertificateId, argsPrefix+"CERTIFICATEID", "", "")
+}
+
+/*
+Shell command to run this test:
+
+ go test -v ./cdnfly_test.go -args \
+ --CERTIMATE_DEPLOYER_CDNFLY_INPUTCERTPATH="/path/to/your-input-cert.pem" \
+ --CERTIMATE_DEPLOYER_CDNFLY_INPUTKEYPATH="/path/to/your-input-key.pem" \
+ --CERTIMATE_DEPLOYER_CDNFLY_APIURL="http://127.0.0.1:88" \
+ --CERTIMATE_DEPLOYER_CDNFLY_APIKEY="your-api-key" \
+ --CERTIMATE_DEPLOYER_CDNFLY_APISECRET="your-api-secret" \
+ --CERTIMATE_DEPLOYER_CDNFLY_CERTIFICATEID="your-cert-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("APIKEY: %v", fApiKey),
+ fmt.Sprintf("APISECRET: %v", fApiSecret),
+ fmt.Sprintf("CERTIFICATEID: %v", fCertificateId),
+ }, "\n"))
+
+ deployer, err := provider.NewDeployer(&provider.DeployerConfig{
+ ApiUrl: fApiUrl,
+ ApiKey: fApiKey,
+ ApiSecret: fApiSecret,
+ ResourceType: provider.RESOURCE_TYPE_CERTIFICATE,
+ CertificateId: 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/cdnfly/consts.go b/internal/pkg/core/deployer/providers/cdnfly/consts.go
new file mode 100644
index 00000000..3f6c6db0
--- /dev/null
+++ b/internal/pkg/core/deployer/providers/cdnfly/consts.go
@@ -0,0 +1,10 @@
+package cdnfly
+
+type ResourceType string
+
+const (
+ // 资源类型:替换指定网站的证书。
+ RESOURCE_TYPE_SITE = ResourceType("site")
+ // 资源类型:替换指定证书。
+ RESOURCE_TYPE_CERTIFICATE = ResourceType("certificate")
+)
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 283d9907..325a5319 100644
--- a/internal/pkg/core/deployer/providers/dogecloud-cdn/dogecloud_cdn.go
+++ b/internal/pkg/core/deployer/providers/dogecloud-cdn/dogecloud_cdn.go
@@ -2,7 +2,6 @@
import (
"context"
- "errors"
"strconv"
xerrors "github.com/pkg/errors"
@@ -10,11 +9,11 @@ import (
"github.com/usual2970/certimate/internal/pkg/core/deployer"
"github.com/usual2970/certimate/internal/pkg/core/logger"
"github.com/usual2970/certimate/internal/pkg/core/uploader"
- uploaderp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/dogecloud"
+ uploadersp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/dogecloud"
dogesdk "github.com/usual2970/certimate/internal/pkg/vendors/dogecloud-sdk"
)
-type DogeCloudCDNDeployerConfig struct {
+type DeployerConfig struct {
// 多吉云 AccessKey。
AccessKey string `json:"accessKey"`
// 多吉云 SecretKey。
@@ -23,31 +22,23 @@ type DogeCloudCDNDeployerConfig struct {
Domain string `json:"domain"`
}
-type DogeCloudCDNDeployer struct {
- config *DogeCloudCDNDeployerConfig
+type DeployerProvider struct {
+ config *DeployerConfig
logger logger.Logger
sdkClient *dogesdk.Client
sslUploader uploader.Uploader
}
-var _ deployer.Deployer = (*DogeCloudCDNDeployer)(nil)
+var _ deployer.Deployer = (*DeployerProvider)(nil)
-func New(config *DogeCloudCDNDeployerConfig) (*DogeCloudCDNDeployer, error) {
- return NewWithLogger(config, logger.NewNilLogger())
-}
-
-func NewWithLogger(config *DogeCloudCDNDeployerConfig, logger logger.Logger) (*DogeCloudCDNDeployer, error) {
+func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) {
if config == nil {
- return nil, errors.New("config is nil")
- }
-
- if logger == nil {
- return nil, errors.New("logger is nil")
+ panic("config is nil")
}
client := dogesdk.NewClient(config.AccessKey, config.SecretKey)
- uploader, err := uploaderp.New(&uploaderp.DogeCloudUploaderConfig{
+ uploader, err := uploadersp.NewUploader(&uploadersp.UploaderConfig{
AccessKey: config.AccessKey,
SecretKey: config.SecretKey,
})
@@ -55,15 +46,19 @@ func NewWithLogger(config *DogeCloudCDNDeployerConfig, logger logger.Logger) (*D
return nil, xerrors.Wrap(err, "failed to create ssl uploader")
}
- return &DogeCloudCDNDeployer{
- logger: logger,
- config: config,
+ return &DeployerProvider{
+ logger: logger.NewNilLogger(),
sdkClient: client,
sslUploader: uploader,
}, nil
}
-func (d *DogeCloudCDNDeployer) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) {
+func (d *DeployerProvider) WithLogger(logger logger.Logger) *DeployerProvider {
+ d.logger = logger
+ return d
+}
+
+func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) {
// 上传证书到 CDN
upres, err := d.sslUploader.Upload(ctx, certPem, privkeyPem)
if err != 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 8d066484..f9c1e7c9 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
@@ -52,7 +52,7 @@ func TestDeploy(t *testing.T) {
fmt.Sprintf("DOMAIN: %v", fDomain),
}, "\n"))
- deployer, err := provider.New(&provider.DogeCloudCDNDeployerConfig{
+ deployer, err := provider.NewDeployer(&provider.DeployerConfig{
AccessKey: fAccessKey,
SecretKey: fSecretKey,
Domain: fDomain,
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 5a6d4bf2..890cfdf3 100644
--- a/internal/pkg/core/deployer/providers/edgio-applications/edgio_applications.go
+++ b/internal/pkg/core/deployer/providers/edgio-applications/edgio_applications.go
@@ -2,7 +2,6 @@
import (
"context"
- "errors"
xerrors "github.com/pkg/errors"
@@ -13,7 +12,7 @@ import (
edgsdkDtos "github.com/usual2970/certimate/internal/pkg/vendors/edgio-sdk/applications/v7/dtos"
)
-type EdgioApplicationsDeployerConfig struct {
+type DeployerConfig struct {
// Edgio ClientId。
ClientId string `json:"clientId"`
// Edgio ClientSecret。
@@ -22,25 +21,17 @@ type EdgioApplicationsDeployerConfig struct {
EnvironmentId string `json:"environmentId"`
}
-type EdgioApplicationsDeployer struct {
- config *EdgioApplicationsDeployerConfig
+type DeployerProvider struct {
+ config *DeployerConfig
logger logger.Logger
sdkClient *edgsdk.EdgioClient
}
-var _ deployer.Deployer = (*EdgioApplicationsDeployer)(nil)
+var _ deployer.Deployer = (*DeployerProvider)(nil)
-func New(config *EdgioApplicationsDeployerConfig) (*EdgioApplicationsDeployer, error) {
- return NewWithLogger(config, logger.NewNilLogger())
-}
-
-func NewWithLogger(config *EdgioApplicationsDeployerConfig, logger logger.Logger) (*EdgioApplicationsDeployer, error) {
+func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) {
if config == nil {
- return nil, errors.New("config is nil")
- }
-
- if logger == nil {
- return nil, errors.New("logger is nil")
+ panic("config is nil")
}
client, err := createSdkClient(config.ClientId, config.ClientSecret)
@@ -48,14 +39,19 @@ func NewWithLogger(config *EdgioApplicationsDeployerConfig, logger logger.Logger
return nil, xerrors.Wrap(err, "failed to create sdk client")
}
- return &EdgioApplicationsDeployer{
- logger: logger,
+ return &DeployerProvider{
config: config,
+ logger: logger.NewNilLogger(),
sdkClient: client,
}, nil
}
-func (d *EdgioApplicationsDeployer) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) {
+func (d *DeployerProvider) WithLogger(logger logger.Logger) *DeployerProvider {
+ d.logger = logger
+ return d
+}
+
+func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) {
// 提取 Edgio 所需的服务端证书和中间证书内容
privateCertPem, intermediateCertPem, err := certs.ExtractCertificatesFromPEM(certPem)
if err != 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 04f7a4cb..bd05b16c 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
@@ -52,7 +52,7 @@ func TestDeploy(t *testing.T) {
fmt.Sprintf("ENVIRONMENTID: %v", fEnvironmentId),
}, "\n"))
- deployer, err := provider.New(&provider.EdgioApplicationsDeployerConfig{
+ deployer, err := provider.NewDeployer(&provider.DeployerConfig{
ClientId: fClientId,
ClientSecret: fClientSecret,
EnvironmentId: fEnvironmentId,
diff --git a/internal/pkg/core/deployer/providers/gcore-cdn/gcore_cdn.go b/internal/pkg/core/deployer/providers/gcore-cdn/gcore_cdn.go
new file mode 100644
index 00000000..e1598a5d
--- /dev/null
+++ b/internal/pkg/core/deployer/providers/gcore-cdn/gcore_cdn.go
@@ -0,0 +1,124 @@
+package gcorecdn
+
+import (
+ "context"
+ "errors"
+ "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/logger"
+ "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"
+)
+
+type DeployerConfig struct {
+ // Gcore API Token。
+ ApiToken string `json:"apiToken"`
+ // CDN 资源 ID。
+ ResourceId int64 `json:"resourceId"`
+}
+
+type DeployerProvider struct {
+ config *DeployerConfig
+ logger logger.Logger
+ sdkClient *gresources.Service
+ 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.ApiToken)
+ if err != nil {
+ return nil, xerrors.Wrap(err, "failed to create sdk client")
+ }
+
+ uploader, err := uploadersp.NewUploader(&uploadersp.UploaderConfig{
+ ApiToken: config.ApiToken,
+ })
+ if err != nil {
+ return nil, xerrors.Wrap(err, "failed to create ssl uploader")
+ }
+
+ return &DeployerProvider{
+ config: config,
+ logger: logger.NewNilLogger(),
+ sdkClient: client,
+ sslUploader: uploader,
+ }, nil
+}
+
+func (d *DeployerProvider) WithLogger(logger logger.Logger) *DeployerProvider {
+ d.logger = logger
+ return d
+}
+
+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)
+ if err != nil {
+ return nil, xerrors.Wrap(err, "failed to upload certificate file")
+ } else {
+ d.logger.Logt("certificate file uploaded", upres)
+ }
+
+ // 获取 CDN 资源详情
+ // REF: https://api.gcore.com/docs/cdn#tag/CDN-resources/paths/~1cdn~1resources~1%7Bresource_id%7D/get
+ getResourceResp, err := d.sdkClient.Get(context.TODO(), d.config.ResourceId)
+ if err != nil {
+ return nil, xerrors.Wrap(err, "failed to execute sdk request 'resources.Get'")
+ } else {
+ d.logger.Logt("已获取 CDN 资源详情", getResourceResp)
+ }
+
+ // 更新 CDN 资源详情
+ // REF: https://api.gcore.com/docs/cdn#tag/CDN-resources/operation/change_cdn_resource
+ updateResourceCertId, _ := strconv.ParseInt(upres.CertId, 10, 64)
+ updateResourceReq := &gresources.UpdateRequest{
+ Description: getResourceResp.Description,
+ Active: getResourceResp.Active,
+ OriginGroup: int(getResourceResp.OriginGroup),
+ OriginProtocol: getResourceResp.OriginProtocol,
+ SecondaryHostnames: getResourceResp.SecondaryHostnames,
+ SSlEnabled: true,
+ SSLData: int(updateResourceCertId),
+ ProxySSLEnabled: getResourceResp.ProxySSLEnabled,
+ ProxySSLCA: &getResourceResp.ProxySSLCA,
+ ProxySSLData: &getResourceResp.ProxySSLData,
+ Options: getResourceResp.Options,
+ }
+ updateResourceResp, err := d.sdkClient.Update(context.TODO(), d.config.ResourceId, updateResourceReq)
+ if err != nil {
+ return nil, xerrors.Wrap(err, "failed to execute sdk request 'resources.Update'")
+ } else {
+ d.logger.Logt("已更新 CDN 资源详情", updateResourceResp)
+ }
+
+ return &deployer.DeployResult{}, nil
+}
+
+func createSdkClient(apiToken string) (*gresources.Service, error) {
+ if apiToken == "" {
+ return nil, errors.New("invalid gcore api token")
+ }
+
+ requester := gprovider.NewClient(
+ gcoresdk.BASE_URL,
+ gprovider.WithSigner(gcoresdk.NewAuthRequestSigner(apiToken)),
+ )
+ service := gresources.NewService(requester)
+ return service, 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
new file mode 100644
index 00000000..34d4a9d6
--- /dev/null
+++ b/internal/pkg/core/deployer/providers/gcore-cdn/gcore_cdn_test.go
@@ -0,0 +1,70 @@
+package gcorecdn_test
+
+import (
+ "context"
+ "flag"
+ "fmt"
+ "os"
+ "strings"
+ "testing"
+
+ provider "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/gcore-cdn"
+)
+
+var (
+ fInputCertPath string
+ fInputKeyPath string
+ fApiToken string
+ fResourceId int64
+)
+
+func init() {
+ argsPrefix := "CERTIMATE_DEPLOYER_GCORECDN_"
+
+ flag.StringVar(&fInputCertPath, argsPrefix+"INPUTCERTPATH", "", "")
+ flag.StringVar(&fInputKeyPath, argsPrefix+"INPUTKEYPATH", "", "")
+ flag.StringVar(&fApiToken, argsPrefix+"APITOKEN", "", "")
+ flag.Int64Var(&fResourceId, argsPrefix+"RESOURCEID", 0, "")
+}
+
+/*
+Shell command to run this test:
+
+ go test -v ./gcore_cdn_test.go -args \
+ --CERTIMATE_DEPLOYER_GCORECDN_INPUTCERTPATH="/path/to/your-input-cert.pem" \
+ --CERTIMATE_DEPLOYER_GCORECDN_INPUTKEYPATH="/path/to/your-input-key.pem" \
+ --CERTIMATE_DEPLOYER_GCORECDN_APITOKEN="your-api-token" \
+ --CERTIMATE_DEPLOYER_GCORECDN_RESOURCEID="your-cdn-resource-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("APITOKEN: %v", fApiToken),
+ fmt.Sprintf("RESOURCEID: %v", fResourceId),
+ }, "\n"))
+
+ deployer, err := provider.NewDeployer(&provider.DeployerConfig{
+ ApiToken: fApiToken,
+ ResourceId: fResourceId,
+ })
+ 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 31782af3..4a40fbc1 100644
--- a/internal/pkg/core/deployer/providers/huaweicloud-cdn/huaweicloud_cdn.go
+++ b/internal/pkg/core/deployer/providers/huaweicloud-cdn/huaweicloud_cdn.go
@@ -2,7 +2,6 @@
import (
"context"
- "errors"
"github.com/huaweicloud/huaweicloud-sdk-go-v3/core/auth/global"
hcCdn "github.com/huaweicloud/huaweicloud-sdk-go-v3/services/cdn/v2"
@@ -13,11 +12,11 @@ import (
"github.com/usual2970/certimate/internal/pkg/core/deployer"
"github.com/usual2970/certimate/internal/pkg/core/logger"
"github.com/usual2970/certimate/internal/pkg/core/uploader"
- uploaderp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/huaweicloud-scm"
+ uploadersp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/huaweicloud-scm"
hwsdk "github.com/usual2970/certimate/internal/pkg/vendors/huaweicloud-sdk"
)
-type HuaweiCloudCDNDeployerConfig struct {
+type DeployerConfig struct {
// 华为云 AccessKeyId。
AccessKeyId string `json:"accessKeyId"`
// 华为云 SecretAccessKey。
@@ -28,26 +27,18 @@ type HuaweiCloudCDNDeployerConfig struct {
Domain string `json:"domain"`
}
-type HuaweiCloudCDNDeployer struct {
- config *HuaweiCloudCDNDeployerConfig
+type DeployerProvider struct {
+ config *DeployerConfig
logger logger.Logger
sdkClient *hcCdn.CdnClient
sslUploader uploader.Uploader
}
-var _ deployer.Deployer = (*HuaweiCloudCDNDeployer)(nil)
+var _ deployer.Deployer = (*DeployerProvider)(nil)
-func New(config *HuaweiCloudCDNDeployerConfig) (*HuaweiCloudCDNDeployer, error) {
- return NewWithLogger(config, logger.NewNilLogger())
-}
-
-func NewWithLogger(config *HuaweiCloudCDNDeployerConfig, logger logger.Logger) (*HuaweiCloudCDNDeployer, error) {
+func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) {
if config == nil {
- return nil, errors.New("config is nil")
- }
-
- if logger == nil {
- return nil, errors.New("logger is nil")
+ panic("config is nil")
}
client, err := createSdkClient(
@@ -59,7 +50,7 @@ func NewWithLogger(config *HuaweiCloudCDNDeployerConfig, logger logger.Logger) (
return nil, xerrors.Wrap(err, "failed to create sdk client")
}
- uploader, err := uploaderp.New(&uploaderp.HuaweiCloudSCMUploaderConfig{
+ uploader, err := uploadersp.NewUploader(&uploadersp.UploaderConfig{
AccessKeyId: config.AccessKeyId,
SecretAccessKey: config.SecretAccessKey,
})
@@ -67,15 +58,20 @@ func NewWithLogger(config *HuaweiCloudCDNDeployerConfig, logger logger.Logger) (
return nil, xerrors.Wrap(err, "failed to create ssl uploader")
}
- return &HuaweiCloudCDNDeployer{
- logger: logger,
+ return &DeployerProvider{
config: config,
+ logger: logger.NewNilLogger(),
sdkClient: client,
sslUploader: uploader,
}, nil
}
-func (d *HuaweiCloudCDNDeployer) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) {
+func (d *DeployerProvider) WithLogger(logger logger.Logger) *DeployerProvider {
+ d.logger = logger
+ return d
+}
+
+func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) {
// 上传证书到 SCM
upres, err := d.sslUploader.Upload(ctx, certPem, privkeyPem)
if err != nil {
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 d31b2a68..aaf8d6c7 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
@@ -56,7 +56,7 @@ func TestDeploy(t *testing.T) {
fmt.Sprintf("DOMAIN: %v", fDomain),
}, "\n"))
- deployer, err := provider.New(&provider.HuaweiCloudCDNDeployerConfig{
+ deployer, err := provider.NewDeployer(&provider.DeployerConfig{
AccessKeyId: fAccessKeyId,
SecretAccessKey: fSecretAccessKey,
Region: fRegion,
diff --git a/internal/pkg/core/deployer/providers/huaweicloud-elb/consts.go b/internal/pkg/core/deployer/providers/huaweicloud-elb/consts.go
new file mode 100644
index 00000000..b097a958
--- /dev/null
+++ b/internal/pkg/core/deployer/providers/huaweicloud-elb/consts.go
@@ -0,0 +1,12 @@
+package huaweicloudelb
+
+type ResourceType string
+
+const (
+ // 资源类型:替换指定证书。
+ RESOURCE_TYPE_CERTIFICATE = ResourceType("certificate")
+ // 资源类型:部署到指定负载均衡器。
+ RESOURCE_TYPE_LOADBALANCER = ResourceType("loadbalancer")
+ // 资源类型:部署到指定监听器。
+ RESOURCE_TYPE_LISTENER = ResourceType("listener")
+)
diff --git a/internal/pkg/core/deployer/providers/huaweicloud-elb/defines.go b/internal/pkg/core/deployer/providers/huaweicloud-elb/defines.go
deleted file mode 100644
index 093ab829..00000000
--- a/internal/pkg/core/deployer/providers/huaweicloud-elb/defines.go
+++ /dev/null
@@ -1,12 +0,0 @@
-package huaweicloudelb
-
-type DeployResourceType string
-
-const (
- // 资源类型:替换指定证书。
- DEPLOY_RESOURCE_CERTIFICATE = DeployResourceType("certificate")
- // 资源类型:部署到指定负载均衡器。
- DEPLOY_RESOURCE_LOADBALANCER = DeployResourceType("loadbalancer")
- // 资源类型:部署到指定监听器。
- DEPLOY_RESOURCE_LISTENER = DeployResourceType("listener")
-)
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 3fa17a70..17bc178b 100644
--- a/internal/pkg/core/deployer/providers/huaweicloud-elb/huaweicloud_elb.go
+++ b/internal/pkg/core/deployer/providers/huaweicloud-elb/huaweicloud_elb.go
@@ -19,11 +19,11 @@ import (
"github.com/usual2970/certimate/internal/pkg/core/deployer"
"github.com/usual2970/certimate/internal/pkg/core/logger"
"github.com/usual2970/certimate/internal/pkg/core/uploader"
- uploaderp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/huaweicloud-elb"
+ uploadersp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/huaweicloud-elb"
hwsdk "github.com/usual2970/certimate/internal/pkg/vendors/huaweicloud-sdk"
)
-type HuaweiCloudELBDeployerConfig struct {
+type DeployerConfig struct {
// 华为云 AccessKeyId。
AccessKeyId string `json:"accessKeyId"`
// 华为云 SecretAccessKey。
@@ -31,38 +31,30 @@ type HuaweiCloudELBDeployerConfig struct {
// 华为云区域。
Region string `json:"region"`
// 部署资源类型。
- ResourceType DeployResourceType `json:"resourceType"`
+ ResourceType ResourceType `json:"resourceType"`
// 证书 ID。
- // 部署资源类型为 [DEPLOY_RESOURCE_CERTIFICATE] 时必填。
+ // 部署资源类型为 [RESOURCE_TYPE_CERTIFICATE] 时必填。
CertificateId string `json:"certificateId,omitempty"`
// 负载均衡器 ID。
- // 部署资源类型为 [DEPLOY_RESOURCE_LOADBALANCER] 时必填。
+ // 部署资源类型为 [RESOURCE_TYPE_LOADBALANCER] 时必填。
LoadbalancerId string `json:"loadbalancerId,omitempty"`
// 负载均衡监听 ID。
- // 部署资源类型为 [DEPLOY_RESOURCE_LISTENER] 时必填。
+ // 部署资源类型为 [RESOURCE_TYPE_LISTENER] 时必填。
ListenerId string `json:"listenerId,omitempty"`
}
-type HuaweiCloudELBDeployer struct {
- config *HuaweiCloudELBDeployerConfig
+type DeployerProvider struct {
+ config *DeployerConfig
logger logger.Logger
sdkClient *hcElb.ElbClient
sslUploader uploader.Uploader
}
-var _ deployer.Deployer = (*HuaweiCloudELBDeployer)(nil)
+var _ deployer.Deployer = (*DeployerProvider)(nil)
-func New(config *HuaweiCloudELBDeployerConfig) (*HuaweiCloudELBDeployer, error) {
- return NewWithLogger(config, logger.NewNilLogger())
-}
-
-func NewWithLogger(config *HuaweiCloudELBDeployerConfig, logger logger.Logger) (*HuaweiCloudELBDeployer, error) {
+func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) {
if config == nil {
- return nil, errors.New("config is nil")
- }
-
- if logger == nil {
- return nil, errors.New("logger is nil")
+ panic("config is nil")
}
client, err := createSdkClient(config.AccessKeyId, config.SecretAccessKey, config.Region)
@@ -70,7 +62,7 @@ func NewWithLogger(config *HuaweiCloudELBDeployerConfig, logger logger.Logger) (
return nil, xerrors.Wrap(err, "failed to create sdk client")
}
- uploader, err := uploaderp.New(&uploaderp.HuaweiCloudELBUploaderConfig{
+ uploader, err := uploadersp.NewUploader(&uploadersp.UploaderConfig{
AccessKeyId: config.AccessKeyId,
SecretAccessKey: config.SecretAccessKey,
Region: config.Region,
@@ -79,15 +71,20 @@ func NewWithLogger(config *HuaweiCloudELBDeployerConfig, logger logger.Logger) (
return nil, xerrors.Wrap(err, "failed to create ssl uploader")
}
- return &HuaweiCloudELBDeployer{
- logger: logger,
+ return &DeployerProvider{
config: config,
+ logger: logger.NewNilLogger(),
sdkClient: client,
sslUploader: uploader,
}, nil
}
-func (d *HuaweiCloudELBDeployer) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) {
+func (d *DeployerProvider) WithLogger(logger logger.Logger) *DeployerProvider {
+ d.logger = logger
+ return d
+}
+
+func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) {
// 上传证书到 SCM
upres, err := d.sslUploader.Upload(ctx, certPem, privkeyPem)
if err != nil {
@@ -98,17 +95,17 @@ func (d *HuaweiCloudELBDeployer) Deploy(ctx context.Context, certPem string, pri
// 根据部署资源类型决定部署方式
switch d.config.ResourceType {
- case DEPLOY_RESOURCE_CERTIFICATE:
+ case RESOURCE_TYPE_CERTIFICATE:
if err := d.deployToCertificate(ctx, certPem, privkeyPem); err != nil {
return nil, err
}
- case DEPLOY_RESOURCE_LOADBALANCER:
+ case RESOURCE_TYPE_LOADBALANCER:
if err := d.deployToLoadbalancer(ctx, certPem, privkeyPem); err != nil {
return nil, err
}
- case DEPLOY_RESOURCE_LISTENER:
+ case RESOURCE_TYPE_LISTENER:
if err := d.deployToListener(ctx, certPem, privkeyPem); err != nil {
return nil, err
}
@@ -120,7 +117,7 @@ func (d *HuaweiCloudELBDeployer) Deploy(ctx context.Context, certPem string, pri
return &deployer.DeployResult{}, nil
}
-func (d *HuaweiCloudELBDeployer) 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")
}
@@ -146,7 +143,7 @@ func (d *HuaweiCloudELBDeployer) deployToCertificate(ctx context.Context, certPe
return nil
}
-func (d *HuaweiCloudELBDeployer) 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")
}
@@ -223,7 +220,7 @@ func (d *HuaweiCloudELBDeployer) deployToLoadbalancer(ctx context.Context, certP
return nil
}
-func (d *HuaweiCloudELBDeployer) 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")
}
@@ -244,7 +241,7 @@ func (d *HuaweiCloudELBDeployer) deployToListener(ctx context.Context, certPem s
return nil
}
-func (d *HuaweiCloudELBDeployer) modifyListenerCertificate(ctx context.Context, cloudListenerId string, cloudCertId string) error {
+func (d *DeployerProvider) modifyListenerCertificate(ctx context.Context, cloudListenerId string, cloudCertId string) error {
// 查询监听器详情
// REF: https://support.huaweicloud.com/api-elb/ShowListener.html
showListenerReq := &hcElbModel.ShowListenerRequest{
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 32582800..4325ba40 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
@@ -62,11 +62,11 @@ func TestDeploy(t *testing.T) {
fmt.Sprintf("CERTIFICATEID: %v", fCertificateId),
}, "\n"))
- deployer, err := provider.New(&provider.HuaweiCloudELBDeployerConfig{
+ deployer, err := provider.NewDeployer(&provider.DeployerConfig{
AccessKeyId: fAccessKeyId,
SecretAccessKey: fSecretAccessKey,
Region: fRegion,
- ResourceType: provider.DEPLOY_RESOURCE_CERTIFICATE,
+ ResourceType: provider.RESOURCE_TYPE_CERTIFICATE,
CertificateId: fCertificateId,
})
if err != nil {
@@ -96,11 +96,11 @@ func TestDeploy(t *testing.T) {
fmt.Sprintf("LOADBALANCERID: %v", fLoadbalancerId),
}, "\n"))
- deployer, err := provider.New(&provider.HuaweiCloudELBDeployerConfig{
+ deployer, err := provider.NewDeployer(&provider.DeployerConfig{
AccessKeyId: fAccessKeyId,
SecretAccessKey: fSecretAccessKey,
Region: fRegion,
- ResourceType: provider.DEPLOY_RESOURCE_LOADBALANCER,
+ ResourceType: provider.RESOURCE_TYPE_LOADBALANCER,
LoadbalancerId: fLoadbalancerId,
})
if err != nil {
@@ -130,11 +130,11 @@ func TestDeploy(t *testing.T) {
fmt.Sprintf("LISTENERID: %v", fListenerId),
}, "\n"))
- deployer, err := provider.New(&provider.HuaweiCloudELBDeployerConfig{
+ deployer, err := provider.NewDeployer(&provider.DeployerConfig{
AccessKeyId: fAccessKeyId,
SecretAccessKey: fSecretAccessKey,
Region: fRegion,
- ResourceType: provider.DEPLOY_RESOURCE_LISTENER,
+ ResourceType: provider.RESOURCE_TYPE_LISTENER,
ListenerId: fListenerId,
})
if err != nil {
diff --git a/internal/pkg/core/deployer/providers/huaweicloud-waf/consts.go b/internal/pkg/core/deployer/providers/huaweicloud-waf/consts.go
new file mode 100644
index 00000000..fc574c32
--- /dev/null
+++ b/internal/pkg/core/deployer/providers/huaweicloud-waf/consts.go
@@ -0,0 +1,12 @@
+package huaweicloudwaf
+
+type ResourceType string
+
+const (
+ // 资源类型:替换指定证书。
+ RESOURCE_TYPE_CERTIFICATE = ResourceType("certificate")
+ // 资源类型:部署到云模式防护网站。
+ RESOURCE_TYPE_CLOUDSERVER = ResourceType("cloudserver")
+ // 资源类型:部署到独享模式防护网站。
+ RESOURCE_TYPE_PREMIUMHOST = ResourceType("premiumhost")
+)
diff --git a/internal/pkg/core/deployer/providers/huaweicloud-waf/huaweicloud_waf.go b/internal/pkg/core/deployer/providers/huaweicloud-waf/huaweicloud_waf.go
new file mode 100644
index 00000000..2342edfa
--- /dev/null
+++ b/internal/pkg/core/deployer/providers/huaweicloud-waf/huaweicloud_waf.go
@@ -0,0 +1,355 @@
+package huaweicloudwaf
+
+import (
+ "context"
+ "errors"
+ "fmt"
+ "strings"
+
+ "github.com/huaweicloud/huaweicloud-sdk-go-v3/core/auth/basic"
+ "github.com/huaweicloud/huaweicloud-sdk-go-v3/core/auth/global"
+ 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"
+ 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/logger"
+ "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"
+)
+
+type DeployerConfig struct {
+ // 华为云 AccessKeyId。
+ AccessKeyId string `json:"accessKeyId"`
+ // 华为云 SecretAccessKey。
+ SecretAccessKey string `json:"secretAccessKey"`
+ // 华为云区域。
+ Region string `json:"region"`
+ // 部署资源类型。
+ ResourceType ResourceType `json:"resourceType"`
+ // 证书 ID。
+ // 部署资源类型为 [RESOURCE_TYPE_CERTIFICATE] 时必填。
+ CertificateId string `json:"certificateId,omitempty"`
+ // 防护域名(支持泛域名)。
+ // 部署资源类型为 [RESOURCE_TYPE_CLOUDSERVER]、[RESOURCE_TYPE_PREMIUMHOST] 时必填。
+ Domain string `json:"domain,omitempty"`
+}
+
+type DeployerProvider struct {
+ config *DeployerConfig
+ logger logger.Logger
+ sdkClient *hcWaf.WafClient
+ 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.SecretAccessKey, config.Region)
+ if err != nil {
+ return nil, xerrors.Wrap(err, "failed to create sdk client")
+ }
+
+ uploader, err := uploadersp.NewUploader(&uploadersp.UploaderConfig{
+ AccessKeyId: config.AccessKeyId,
+ SecretAccessKey: config.SecretAccessKey,
+ Region: config.Region,
+ })
+ if err != nil {
+ return nil, xerrors.Wrap(err, "failed to create ssl uploader")
+ }
+
+ return &DeployerProvider{
+ config: config,
+ logger: logger.NewNilLogger(),
+ sdkClient: client,
+ sslUploader: uploader,
+ }, nil
+}
+
+func (d *DeployerProvider) WithLogger(logger logger.Logger) *DeployerProvider {
+ d.logger = logger
+ return d
+}
+
+func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) {
+ // 上传证书到 WAF
+ upres, err := d.sslUploader.Upload(ctx, certPem, privkeyPem)
+ if err != nil {
+ return nil, xerrors.Wrap(err, "failed to upload certificate file")
+ } else {
+ d.logger.Logt("certificate file uploaded", upres)
+ }
+
+ // 根据部署资源类型决定部署方式
+ switch d.config.ResourceType {
+ case RESOURCE_TYPE_CERTIFICATE:
+ 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 {
+ return nil, err
+ }
+
+ case RESOURCE_TYPE_PREMIUMHOST:
+ 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 &deployer.DeployResult{}, nil
+}
+
+func (d *DeployerProvider) deployToCertificate(ctx context.Context, certPem string, privkeyPem string) error {
+ if d.config.CertificateId == "" {
+ return errors.New("config `certificateId` is required")
+ }
+
+ // 查询证书
+ // REF: https://support.huaweicloud.com/api-waf/ShowCertificate.html
+ showCertificateReq := &hcWafModel.ShowCertificateRequest{
+ CertificateId: d.config.CertificateId,
+ }
+ showCertificateResp, err := d.sdkClient.ShowCertificate(showCertificateReq)
+ if err != nil {
+ return xerrors.Wrap(err, "failed to execute sdk request 'waf.ShowCertificate'")
+ } else {
+ d.logger.Logt("已获取 WAF 证书", showCertificateResp)
+ }
+
+ // 更新证书
+ // REF: https://support.huaweicloud.com/api-waf/UpdateCertificate.html
+ updateCertificateReq := &hcWafModel.UpdateCertificateRequest{
+ CertificateId: d.config.CertificateId,
+ Body: &hcWafModel.UpdateCertificateRequestBody{
+ Name: *showCertificateResp.Name,
+ Content: hwsdk.StringPtr(certPem),
+ Key: hwsdk.StringPtr(privkeyPem),
+ },
+ }
+ updateCertificateResp, err := d.sdkClient.UpdateCertificate(updateCertificateReq)
+ if err != nil {
+ return xerrors.Wrap(err, "failed to execute sdk request 'waf.UpdateCertificate'")
+ } else {
+ d.logger.Logt("已更新 WAF 证书", updateCertificateResp)
+ }
+
+ return nil
+}
+
+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)
+ if err != nil {
+ return xerrors.Wrap(err, "failed to upload certificate file")
+ } else {
+ d.logger.Logt("certificate file uploaded", upres)
+ }
+
+ // 遍历查询云模式防护域名列表,获取防护域名 ID
+ // REF: https://support.huaweicloud.com/api-waf/ListHost.html
+ hostId := ""
+ listHostPage := int32(1)
+ listHostPageSize := int32(100)
+ for {
+ listHostReq := &hcWafModel.ListHostRequest{
+ Hostname: hwsdk.StringPtr(strings.TrimPrefix(d.config.Domain, "*")),
+ Page: hwsdk.Int32Ptr(listHostPage),
+ Pagesize: hwsdk.Int32Ptr(listHostPageSize),
+ }
+ listHostResp, err := d.sdkClient.ListHost(listHostReq)
+ if err != nil {
+ return xerrors.Wrap(err, "failed to execute sdk request 'waf.ListHost'")
+ }
+
+ if listHostResp.Items != nil {
+ for _, hostItem := range *listHostResp.Items {
+ if strings.TrimPrefix(d.config.Domain, "*") == *hostItem.Hostname {
+ hostId = *hostItem.Id
+ break
+ }
+ }
+ }
+
+ if listHostResp.Items == nil || len(*listHostResp.Items) < int(listHostPageSize) {
+ break
+ } else {
+ listHostPage++
+ }
+ }
+ if hostId == "" {
+ return errors.New("host not found")
+ }
+
+ // 更新云模式防护域名的配置
+ // REF: https://support.huaweicloud.com/api-waf/UpdateHost.html
+ updateHostReq := &hcWafModel.UpdateHostRequest{
+ InstanceId: hostId,
+ Body: &hcWafModel.UpdateHostRequestBody{
+ Certificateid: hwsdk.StringPtr(upres.CertId),
+ Certificatename: hwsdk.StringPtr(upres.CertName),
+ },
+ }
+ updateHostResp, err := d.sdkClient.UpdateHost(updateHostReq)
+ if err != nil {
+ return xerrors.Wrap(err, "failed to execute sdk request 'waf.UpdateHost'")
+ } else {
+ d.logger.Logt("已更新云模式防护域名的配置", updateHostResp)
+ }
+
+ return nil
+}
+
+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)
+ if err != nil {
+ return xerrors.Wrap(err, "failed to upload certificate file")
+ } else {
+ d.logger.Logt("certificate file uploaded", upres)
+ }
+
+ // 遍历查询独享模式域名列表,获取防护域名 ID
+ // REF: https://support.huaweicloud.com/api-waf/ListPremiumHost.html
+ hostId := ""
+ listPremiumHostPage := int32(1)
+ listPremiumHostPageSize := int32(100)
+ for {
+ 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)),
+ }
+ listPremiumHostResp, err := d.sdkClient.ListPremiumHost(listPremiumHostReq)
+ if err != nil {
+ return xerrors.Wrap(err, "failed to execute sdk request 'waf.ListPremiumHost'")
+ }
+
+ if listPremiumHostResp.Items != nil {
+ for _, hostItem := range *listPremiumHostResp.Items {
+ if strings.TrimPrefix(d.config.Domain, "*") == *hostItem.Hostname {
+ hostId = *hostItem.Id
+ break
+ }
+ }
+ }
+
+ if listPremiumHostResp.Items == nil || len(*listPremiumHostResp.Items) < int(listPremiumHostPageSize) {
+ break
+ } else {
+ listPremiumHostPage++
+ }
+ }
+ if hostId == "" {
+ return errors.New("host not found")
+ }
+
+ // 修改独享模式域名配置
+ // REF: https://support.huaweicloud.com/api-waf/UpdatePremiumHost.html
+ updatePremiumHostReq := &hcWafModel.UpdatePremiumHostRequest{
+ HostId: hostId,
+ Body: &hcWafModel.UpdatePremiumHostRequestBody{
+ Certificateid: hwsdk.StringPtr(upres.CertId),
+ Certificatename: hwsdk.StringPtr(upres.CertName),
+ },
+ }
+ updatePremiumHostResp, err := d.sdkClient.UpdatePremiumHost(updatePremiumHostReq)
+ if err != nil {
+ return xerrors.Wrap(err, "failed to execute sdk request 'waf.UpdatePremiumHost'")
+ } else {
+ d.logger.Logt("已修改独享模式域名配置", updatePremiumHostResp)
+ }
+
+ return nil
+}
+
+func createSdkClient(accessKeyId, secretAccessKey, region string) (*hcWaf.WafClient, error) {
+ projectId, err := getSdkProjectId(accessKeyId, secretAccessKey, region)
+ if err != nil {
+ return nil, err
+ }
+
+ auth, err := basic.NewCredentialsBuilder().
+ WithAk(accessKeyId).
+ WithSk(secretAccessKey).
+ WithProjectId(projectId).
+ SafeBuild()
+ if err != nil {
+ return nil, err
+ }
+
+ hcRegion, err := hcWafRegion.SafeValueOf(region)
+ if err != nil {
+ return nil, err
+ }
+
+ hcClient, err := hcWaf.WafClientBuilder().
+ WithRegion(hcRegion).
+ WithCredential(auth).
+ SafeBuild()
+ if err != nil {
+ return nil, err
+ }
+
+ client := hcWaf.NewWafClient(hcClient)
+ return client, nil
+}
+
+func getSdkProjectId(accessKeyId, secretAccessKey, region string) (string, error) {
+ auth, err := global.NewCredentialsBuilder().
+ WithAk(accessKeyId).
+ WithSk(secretAccessKey).
+ SafeBuild()
+ if err != nil {
+ return "", err
+ }
+
+ hcRegion, err := hcIamRegion.SafeValueOf(region)
+ if err != nil {
+ return "", err
+ }
+
+ hcClient, err := hcIam.IamClientBuilder().
+ WithRegion(hcRegion).
+ WithCredential(auth).
+ SafeBuild()
+ if err != nil {
+ return "", err
+ }
+
+ client := hcIam.NewIamClient(hcClient)
+
+ request := &hcIamModel.KeystoneListProjectsRequest{
+ Name: ®ion,
+ }
+ response, err := client.KeystoneListProjects(request)
+ if err != nil {
+ return "", err
+ } else if response.Projects == nil || len(*response.Projects) == 0 {
+ return "", errors.New("no project found")
+ }
+
+ return (*response.Projects)[0].Id, 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
new file mode 100644
index 00000000..83142325
--- /dev/null
+++ b/internal/pkg/core/deployer/providers/huaweicloud-waf/huaweicloud_waf_test.go
@@ -0,0 +1,84 @@
+package huaweicloudwaf_test
+
+import (
+ "context"
+ "flag"
+ "fmt"
+ "os"
+ "strings"
+ "testing"
+
+ provider "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/huaweicloud-waf"
+)
+
+var (
+ fInputCertPath string
+ fInputKeyPath string
+ fAccessKeyId string
+ fSecretAccessKey string
+ fRegion string
+ fResourceType string
+ fDomain string
+)
+
+func init() {
+ argsPrefix := "CERTIMATE_DEPLOYER_HUAWEICLOUDWAF_"
+
+ flag.StringVar(&fInputCertPath, argsPrefix+"INPUTCERTPATH", "", "")
+ flag.StringVar(&fInputKeyPath, argsPrefix+"INPUTKEYPATH", "", "")
+ flag.StringVar(&fAccessKeyId, argsPrefix+"ACCESSKEYID", "", "")
+ flag.StringVar(&fSecretAccessKey, argsPrefix+"SECRETACCESSKEY", "", "")
+ flag.StringVar(&fRegion, argsPrefix+"REGION", "", "")
+ flag.StringVar(&fResourceType, argsPrefix+"RESOURCETYPE", "", "")
+ flag.StringVar(&fDomain, argsPrefix+"DOMAIN", "", "")
+}
+
+/*
+Shell command to run this test:
+
+ go test -v ./huaweicloud_waf_test.go -args \
+ --CERTIMATE_DEPLOYER_HUAWEICLOUDWAF_INPUTCERTPATH="/path/to/your-input-cert.pem" \
+ --CERTIMATE_DEPLOYER_HUAWEICLOUDWAF_INPUTKEYPATH="/path/to/your-input-key.pem" \
+ --CERTIMATE_DEPLOYER_HUAWEICLOUDWAF_ACCESSKEYID="your-access-key-id" \
+ --CERTIMATE_DEPLOYER_HUAWEICLOUDWAF_SECRETACCESSKEY="your-secret-access-key" \
+ --CERTIMATE_DEPLOYER_HUAWEICLOUDWAF_REGION="cn-north-1" \
+ --CERTIMATE_DEPLOYER_HUAWEICLOUDWAF_RESOURCETYPE="premium" \
+ --CERTIMATE_DEPLOYER_HUAWEICLOUDWAF_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("SECRETACCESSKEY: %v", fSecretAccessKey),
+ fmt.Sprintf("REGION: %v", fRegion),
+ fmt.Sprintf("RESOURCETYPE: %v", fResourceType),
+ }, "\n"))
+
+ deployer, err := provider.NewDeployer(&provider.DeployerConfig{
+ AccessKeyId: fAccessKeyId,
+ SecretAccessKey: fSecretAccessKey,
+ Region: fRegion,
+ ResourceType: provider.ResourceType(fResourceType),
+ 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/jdcloud-alb/consts.go b/internal/pkg/core/deployer/providers/jdcloud-alb/consts.go
new file mode 100644
index 00000000..13525c20
--- /dev/null
+++ b/internal/pkg/core/deployer/providers/jdcloud-alb/consts.go
@@ -0,0 +1,10 @@
+package jdcloudalb
+
+type ResourceType string
+
+const (
+ // 资源类型:部署到指定负载均衡器。
+ RESOURCE_TYPE_LOADBALANCER = ResourceType("loadbalancer")
+ // 资源类型:部署到指定监听器。
+ RESOURCE_TYPE_LISTENER = ResourceType("listener")
+)
diff --git a/internal/pkg/core/deployer/providers/jdcloud-alb/jdcloud_alb.go b/internal/pkg/core/deployer/providers/jdcloud-alb/jdcloud_alb.go
new file mode 100644
index 00000000..41625b64
--- /dev/null
+++ b/internal/pkg/core/deployer/providers/jdcloud-alb/jdcloud_alb.go
@@ -0,0 +1,252 @@
+package jdcloudalb
+
+import (
+ "context"
+ "errors"
+ "fmt"
+ "strings"
+
+ jdCore "github.com/jdcloud-api/jdcloud-sdk-go/core"
+ jdCommon "github.com/jdcloud-api/jdcloud-sdk-go/services/common/models"
+ 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/logger"
+ "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/slices"
+)
+
+type DeployerConfig struct {
+ // 京东云 AccessKeyId。
+ AccessKeyId string `json:"accessKeyId"`
+ // 京东云 AccessKeySecret。
+ AccessKeySecret string `json:"accessKeySecret"`
+ // 京东云地域 ID。
+ RegionId string `json:"regionId"`
+ // 部署资源类型。
+ ResourceType ResourceType `json:"resourceType"`
+ // 负载均衡器 ID。
+ // 部署资源类型为 [RESOURCE_TYPE_LOADBALANCER] 时必填。
+ LoadbalancerId string `json:"loadbalancerId,omitempty"`
+ // 监听器 ID。
+ // 部署资源类型为 [RESOURCE_TYPE_LISTENER] 时必填。
+ ListenerId string `json:"listenerId,omitempty"`
+ // SNI 域名(支持泛域名)。
+ // 部署资源类型为 [RESOURCE_TYPE_LOADBALANCER]、[RESOURCE_TYPE_LISTENER] 时选填。
+ Domain string `json:"domain,omitempty"`
+}
+
+type DeployerProvider struct {
+ config *DeployerConfig
+ logger logger.Logger
+ sdkClient *jdLbClient.LbClient
+ 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)
+ if err != nil {
+ return nil, xerrors.Wrap(err, "failed to create sdk client")
+ }
+
+ uploader, err := uploadersp.NewUploader(&uploadersp.UploaderConfig{
+ AccessKeyId: config.AccessKeyId,
+ AccessKeySecret: config.AccessKeySecret,
+ })
+ if err != nil {
+ return nil, xerrors.Wrap(err, "failed to create ssl uploader")
+ }
+
+ return &DeployerProvider{
+ config: config,
+ logger: logger.NewNilLogger(),
+ sdkClient: client,
+ sslUploader: uploader,
+ }, nil
+}
+
+func (d *DeployerProvider) WithLogger(logger logger.Logger) *DeployerProvider {
+ d.logger = logger
+ return d
+}
+
+func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) {
+ // 上传证书到 SSL
+ upres, err := d.sslUploader.Upload(ctx, certPem, privkeyPem)
+ if err != nil {
+ return nil, xerrors.Wrap(err, "failed to upload certificate file")
+ } else {
+ d.logger.Logt("certificate file uploaded", upres)
+ }
+
+ // 根据部署资源类型决定部署方式
+ switch d.config.ResourceType {
+ case RESOURCE_TYPE_LOADBALANCER:
+ if err := d.deployToLoadbalancer(ctx, upres.CertId); err != nil {
+ return nil, err
+ }
+
+ case RESOURCE_TYPE_LISTENER:
+ if err := d.deployToListener(ctx, upres.CertId); err != nil {
+ return nil, err
+ }
+
+ default:
+ return nil, fmt.Errorf("unsupported resource type: %s", d.config.ResourceType)
+ }
+
+ return &deployer.DeployResult{}, nil
+}
+
+func (d *DeployerProvider) deployToLoadbalancer(ctx context.Context, cloudCertId string) error {
+ if d.config.LoadbalancerId == "" {
+ return errors.New("config `loadbalancerId` is required")
+ }
+
+ // 查询负载均衡器详情
+ // REF: https://docs.jdcloud.com/cn/load-balancer/api/describeloadbalancer
+ describeLoadBalancerReq := jdLbApi.NewDescribeLoadBalancerRequest(d.config.RegionId, d.config.LoadbalancerId)
+ describeLoadBalancerResp, err := d.sdkClient.DescribeLoadBalancer(describeLoadBalancerReq)
+ if err != nil {
+ return xerrors.Wrap(err, "failed to execute sdk request 'lb.DescribeLoadBalancer'")
+ } else {
+ d.logger.Logt("已查询到负载均衡器详情", describeLoadBalancerResp)
+ }
+
+ // 查询监听器列表
+ // REF: https://docs.jdcloud.com/cn/load-balancer/api/describelisteners
+ listenerIds := make([]string, 0)
+ describeListenersPageNumber := 1
+ describeListenersPageSize := 100
+ for {
+ describeListenersReq := jdLbApi.NewDescribeListenersRequest(d.config.RegionId)
+ describeListenersReq.SetFilters([]jdCommon.Filter{{Name: "loadBalancerId", Values: []string{d.config.LoadbalancerId}}})
+ describeListenersReq.SetPageSize(describeListenersPageNumber)
+ describeListenersReq.SetPageSize(describeListenersPageSize)
+ describeListenersResp, err := d.sdkClient.DescribeListeners(describeListenersReq)
+ if err != nil {
+ return xerrors.Wrap(err, "failed to execute sdk request 'lb.DescribeListeners'")
+ }
+
+ for _, listener := range describeListenersResp.Result.Listeners {
+ if strings.EqualFold(listener.Protocol, "https") || strings.EqualFold(listener.Protocol, "tls") {
+ listenerIds = append(listenerIds, listener.ListenerId)
+ }
+ }
+
+ if len(describeListenersResp.Result.Listeners) < int(describeListenersPageSize) {
+ break
+ } else {
+ describeListenersPageNumber++
+ }
+ }
+
+ // 遍历更新监听器证书
+ if len(listenerIds) == 0 {
+ return errors.New("listener not found")
+ } else {
+ d.logger.Logt("已查询到负载均衡器下的全部 HTTPS/TLS 监听器", listenerIds)
+
+ var errs []error
+
+ for _, listenerId := range listenerIds {
+ if err := d.updateListenerCertificate(ctx, listenerId, cloudCertId); err != nil {
+ errs = append(errs, err)
+ }
+ }
+
+ if len(errs) > 0 {
+ return errors.Join(errs...)
+ }
+ }
+
+ return nil
+}
+
+func (d *DeployerProvider) deployToListener(ctx context.Context, cloudCertId string) error {
+ if d.config.ListenerId == "" {
+ return errors.New("config `listenerId` is required")
+ }
+
+ // 更新监听器证书
+ if err := d.updateListenerCertificate(ctx, d.config.ListenerId, cloudCertId); err != nil {
+ return err
+ }
+
+ return nil
+}
+
+func (d *DeployerProvider) updateListenerCertificate(ctx context.Context, cloudListenerId string, cloudCertId string) error {
+ // 查询监听器详情
+ // REF: https://docs.jdcloud.com/cn/load-balancer/api/describelistener
+ describeListenerReq := jdLbApi.NewDescribeListenerRequest(d.config.RegionId, cloudListenerId)
+ describeListenerResp, err := d.sdkClient.DescribeListener(describeListenerReq)
+ if err != nil {
+ return xerrors.Wrap(err, "failed to execute sdk request 'lb.DescribeListener'")
+ } else {
+ d.logger.Logt("已查询到监听器详情", describeListenerResp)
+ }
+
+ if d.config.Domain == "" {
+ // 未指定 SNI,只需部署到监听器
+
+ // 修改监听器信息
+ // REF: https://docs.jdcloud.com/cn/load-balancer/api/updatelistener
+ updateListenerReq := jdLbApi.NewUpdateListenerRequest(d.config.RegionId, cloudListenerId)
+ updateListenerReq.SetCertificateSpecs([]jdLbModel.CertificateSpec{{CertificateId: cloudCertId}})
+ updateListenerResp, err := d.sdkClient.UpdateListener(updateListenerReq)
+ if err != nil {
+ return xerrors.Wrap(err, "failed to execute sdk request 'lb.UpdateListener'")
+ } else {
+ d.logger.Logt("已修改监听器信息", updateListenerResp)
+ }
+ } else {
+ // 指定 SNI,需部署到扩展证书
+
+ extCertSpecs := slices.Filter(describeListenerResp.Result.Listener.ExtensionCertificateSpecs, func(extCertSpec jdLbModel.ExtensionCertificateSpec) bool {
+ return extCertSpec.Domain == d.config.Domain
+ })
+ if len(extCertSpecs) == 0 {
+ return errors.New("extension certificate spec not found")
+ }
+
+ // 批量修改扩展证书
+ // REF: https://docs.jdcloud.com/cn/load-balancer/api/updatelistenercertificates
+ updateListenerCertificatesReq := jdLbApi.NewUpdateListenerCertificatesRequest(
+ d.config.RegionId,
+ cloudListenerId,
+ slices.Map(extCertSpecs, func(extCertSpec jdLbModel.ExtensionCertificateSpec) jdLbModel.ExtCertificateUpdateSpec {
+ return jdLbModel.ExtCertificateUpdateSpec{
+ CertificateBindId: extCertSpec.CertificateBindId,
+ CertificateId: &cloudCertId,
+ Domain: &extCertSpec.Domain,
+ }
+ }),
+ )
+ updateListenerCertificatesResp, err := d.sdkClient.UpdateListenerCertificates(updateListenerCertificatesReq)
+ if err != nil {
+ return xerrors.Wrap(err, "failed to execute sdk request 'lb.UpdateListenerCertificates'")
+ } else {
+ d.logger.Logt("已批量修改扩展证书", updateListenerCertificatesResp)
+ }
+ }
+
+ return nil
+}
+
+func createSdkClient(accessKeyId, accessKeySecret string) (*jdLbClient.LbClient, error) {
+ clientCredentials := jdCore.NewCredentials(accessKeyId, accessKeySecret)
+ client := jdLbClient.NewLbClient(clientCredentials)
+ client.SetLogger(jdCore.NewDefaultLogger(jdCore.LogWarn))
+ return client, nil
+}
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
new file mode 100644
index 00000000..9c9cc9cc
--- /dev/null
+++ b/internal/pkg/core/deployer/providers/jdcloud-alb/jdcloud_alb_test.go
@@ -0,0 +1,118 @@
+package jdcloudalb_test
+
+import (
+ "context"
+ "flag"
+ "fmt"
+ "os"
+ "strings"
+ "testing"
+
+ provider "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/jdcloud-alb"
+)
+
+var (
+ fInputCertPath string
+ fInputKeyPath string
+ fAccessKeyId string
+ fAccessKeySecret string
+ fRegionId string
+ fLoadbalancerId string
+ fListenerId string
+)
+
+func init() {
+ argsPrefix := "CERTIMATE_DEPLOYER_JDCLOUDALB_"
+
+ flag.StringVar(&fInputCertPath, argsPrefix+"INPUTCERTPATH", "", "")
+ flag.StringVar(&fInputKeyPath, argsPrefix+"INPUTKEYPATH", "", "")
+ flag.StringVar(&fAccessKeyId, argsPrefix+"ACCESSKEYID", "", "")
+ flag.StringVar(&fAccessKeySecret, argsPrefix+"ACCESSKEYSECRET", "", "")
+ flag.StringVar(&fRegionId, argsPrefix+"REGIONID", "", "")
+ flag.StringVar(&fLoadbalancerId, argsPrefix+"LOADBALANCERID", "", "")
+ flag.StringVar(&fListenerId, argsPrefix+"LISTENERID", "", "")
+}
+
+/*
+Shell command to run this test:
+
+ go test -v ./jdcloud_alb_test.go -args \
+ --CERTIMATE_DEPLOYER_JDCLOUDALB_INPUTCERTPATH="/path/to/your-input-cert.pem" \
+ --CERTIMATE_DEPLOYER_JDCLOUDALB_INPUTKEYPATH="/path/to/your-input-key.pem" \
+ --CERTIMATE_DEPLOYER_JDCLOUDALB_ACCESSKEYID="your-access-key-id" \
+ --CERTIMATE_DEPLOYER_JDCLOUDALB_ACCESSKEYSECRET="your-secret-access-key" \
+ --CERTIMATE_DEPLOYER_JDCLOUDALB_REGION_ID="cn-north-1" \
+ --CERTIMATE_DEPLOYER_JDCLOUDALB_LOADBALANCERID="your-alb-loadbalancer-id" \
+ --CERTIMATE_DEPLOYER_JDCLOUDALB_LISTENERID="your-alb-listener-id"
+*/
+func TestDeploy(t *testing.T) {
+ flag.Parse()
+
+ t.Run("Deploy_ToLoadbalancer", 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("REGIONID: %v", fRegionId),
+ fmt.Sprintf("LOADBALANCERID: %v", fLoadbalancerId),
+ }, "\n"))
+
+ deployer, err := provider.NewDeployer(&provider.DeployerConfig{
+ AccessKeyId: fAccessKeyId,
+ AccessKeySecret: fAccessKeySecret,
+ RegionId: fRegionId,
+ ResourceType: provider.RESOURCE_TYPE_LOADBALANCER,
+ LoadbalancerId: fLoadbalancerId,
+ })
+ 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)
+ })
+
+ t.Run("Deploy_ToListener", 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("REGIONID: %v", fRegionId),
+ fmt.Sprintf("LISTENERID: %v", fListenerId),
+ }, "\n"))
+
+ deployer, err := provider.NewDeployer(&provider.DeployerConfig{
+ AccessKeyId: fAccessKeyId,
+ AccessKeySecret: fAccessKeySecret,
+ RegionId: fRegionId,
+ ResourceType: provider.RESOURCE_TYPE_LISTENER,
+ ListenerId: fListenerId,
+ })
+ 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/jdcloud-cdn/jdcloud_cdn.go b/internal/pkg/core/deployer/providers/jdcloud-cdn/jdcloud_cdn.go
new file mode 100644
index 00000000..d5bdae4f
--- /dev/null
+++ b/internal/pkg/core/deployer/providers/jdcloud-cdn/jdcloud_cdn.go
@@ -0,0 +1,109 @@
+package jdcloudcdn
+
+import (
+ "context"
+
+ 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/logger"
+ "github.com/usual2970/certimate/internal/pkg/core/uploader"
+ uploadersp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/jdcloud-ssl"
+)
+
+type DeployerConfig struct {
+ // 京东云 AccessKeyId。
+ AccessKeyId string `json:"accessKeyId"`
+ // 京东云 AccessKeySecret。
+ AccessKeySecret string `json:"accessKeySecret"`
+ // 加速域名(支持泛域名)。
+ Domain string `json:"domain"`
+}
+
+type DeployerProvider struct {
+ config *DeployerConfig
+ logger logger.Logger
+ sdkClient *jdCdnClient.CdnClient
+ 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)
+ if err != nil {
+ return nil, xerrors.Wrap(err, "failed to create sdk client")
+ }
+
+ uploader, err := uploadersp.NewUploader(&uploadersp.UploaderConfig{
+ AccessKeyId: config.AccessKeyId,
+ AccessKeySecret: config.AccessKeySecret,
+ })
+ if err != nil {
+ return nil, xerrors.Wrap(err, "failed to create ssl uploader")
+ }
+
+ return &DeployerProvider{
+ config: config,
+ logger: logger.NewNilLogger(),
+ sdkClient: client,
+ sslUploader: uploader,
+ }, nil
+}
+
+func (d *DeployerProvider) WithLogger(logger logger.Logger) *DeployerProvider {
+ d.logger = logger
+ return d
+}
+
+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)
+ if err != nil {
+ return nil, xerrors.Wrap(err, "failed to execute sdk request 'cdn.QueryDomainConfig'")
+ } else {
+ d.logger.Logt("已查询到域名配置信息", queryDomainConfigResp)
+ }
+
+ // 上传证书到 SSL
+ upres, err := d.sslUploader.Upload(ctx, certPem, privkeyPem)
+ if err != nil {
+ return nil, xerrors.Wrap(err, "failed to upload certificate file")
+ } else {
+ d.logger.Logt("certificate file uploaded", upres)
+ }
+
+ // 设置通讯协议
+ // 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.SetCertFrom("ssl")
+ setHttpTypeReq.SetSslCertId(upres.CertId)
+ setHttpTypeReq.SetJumpType(queryDomainConfigResp.Result.HttpsJumpType)
+ setHttpTypeResp, err := d.sdkClient.SetHttpType(setHttpTypeReq)
+ if err != nil {
+ return nil, xerrors.Wrap(err, "failed to execute sdk request 'cdn.SetHttpType'")
+ } else {
+ d.logger.Logt("已设置通讯协议", setHttpTypeResp)
+ }
+
+ return &deployer.DeployResult{}, nil
+}
+
+func createSdkClient(accessKeyId, accessKeySecret string) (*jdCdnClient.CdnClient, error) {
+ clientCredentials := jdCore.NewCredentials(accessKeyId, accessKeySecret)
+ client := jdCdnClient.NewCdnClient(clientCredentials)
+ client.SetLogger(jdCore.NewDefaultLogger(jdCore.LogWarn))
+ return client, 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
new file mode 100644
index 00000000..2d2f7ed0
--- /dev/null
+++ b/internal/pkg/core/deployer/providers/jdcloud-cdn/jdcloud_cdn_test.go
@@ -0,0 +1,75 @@
+package jdcloudcdn_test
+
+import (
+ "context"
+ "flag"
+ "fmt"
+ "os"
+ "strings"
+ "testing"
+
+ provider "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/jdcloud-cdn"
+)
+
+var (
+ fInputCertPath string
+ fInputKeyPath string
+ fAccessKeyId string
+ fAccessKeySecret string
+ fDomain string
+)
+
+func init() {
+ argsPrefix := "CERTIMATE_DEPLOYER_JDCLOUDCDN_"
+
+ flag.StringVar(&fInputCertPath, argsPrefix+"INPUTCERTPATH", "", "")
+ flag.StringVar(&fInputKeyPath, argsPrefix+"INPUTKEYPATH", "", "")
+ flag.StringVar(&fAccessKeyId, argsPrefix+"ACCESSKEYID", "", "")
+ flag.StringVar(&fAccessKeySecret, argsPrefix+"ACCESSKEYSECRET", "", "")
+ flag.StringVar(&fDomain, argsPrefix+"DOMAIN", "", "")
+}
+
+/*
+Shell command to run this test:
+
+ go test -v ./jdcloud_cdn_test.go -args \
+ --CERTIMATE_DEPLOYER_JDCLOUDCDN_INPUTCERTPATH="/path/to/your-input-cert.pem" \
+ --CERTIMATE_DEPLOYER_JDCLOUDCDN_INPUTKEYPATH="/path/to/your-input-key.pem" \
+ --CERTIMATE_DEPLOYER_JDCLOUDCDN_ACCESSKEYID="your-access-key-id" \
+ --CERTIMATE_DEPLOYER_JDCLOUDCDN_ACCESSKEYSECRET="your-secret-access-key" \
+ --CERTIMATE_DEPLOYER_JDCLOUDCDN_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("DOMAIN: %v", fDomain),
+ }, "\n"))
+
+ deployer, err := provider.NewDeployer(&provider.DeployerConfig{
+ AccessKeyId: fAccessKeyId,
+ AccessKeySecret: fAccessKeySecret,
+ 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/jdcloud-live/jdcloud_live.go b/internal/pkg/core/deployer/providers/jdcloud-live/jdcloud_live.go
new file mode 100644
index 00000000..7998fb16
--- /dev/null
+++ b/internal/pkg/core/deployer/providers/jdcloud-live/jdcloud_live.go
@@ -0,0 +1,75 @@
+package jdcloudlive
+
+import (
+ "context"
+
+ 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"
+ "github.com/usual2970/certimate/internal/pkg/core/logger"
+)
+
+type DeployerConfig struct {
+ // 京东云 AccessKeyId。
+ AccessKeyId string `json:"accessKeyId"`
+ // 京东云 AccessKeySecret。
+ AccessKeySecret string `json:"accessKeySecret"`
+ // 直播播放域名(不支持泛域名)。
+ Domain string `json:"domain"`
+}
+
+type DeployerProvider struct {
+ config *DeployerConfig
+ logger logger.Logger
+ sdkClient *jdLiveClient.LiveClient
+}
+
+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)
+ if err != nil {
+ return nil, xerrors.Wrap(err, "failed to create sdk client")
+ }
+
+ return &DeployerProvider{
+ config: config,
+ logger: logger.NewNilLogger(),
+ sdkClient: client,
+ }, nil
+}
+
+func (d *DeployerProvider) WithLogger(logger logger.Logger) *DeployerProvider {
+ d.logger = logger
+ return d
+}
+
+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)
+ setLiveDomainCertificateResp, err := d.sdkClient.SetLiveDomainCertificate(setLiveDomainCertificateReq)
+ if err != nil {
+ return nil, xerrors.Wrap(err, "failed to execute sdk request 'live.SetLiveDomainCertificate'")
+ } else {
+ d.logger.Logt("已设置直播证书", setLiveDomainCertificateResp)
+ }
+
+ return &deployer.DeployResult{}, nil
+}
+
+func createSdkClient(accessKeyId, accessKeySecret string) (*jdLiveClient.LiveClient, error) {
+ clientCredentials := jdCore.NewCredentials(accessKeyId, accessKeySecret)
+ client := jdLiveClient.NewLiveClient(clientCredentials)
+ client.SetLogger(jdCore.NewDefaultLogger(jdCore.LogWarn))
+ return client, 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
new file mode 100644
index 00000000..076202b5
--- /dev/null
+++ b/internal/pkg/core/deployer/providers/jdcloud-live/jdcloud_live_test.go
@@ -0,0 +1,75 @@
+package jdcloudlive_test
+
+import (
+ "context"
+ "flag"
+ "fmt"
+ "os"
+ "strings"
+ "testing"
+
+ provider "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/jdcloud-live"
+)
+
+var (
+ fInputCertPath string
+ fInputKeyPath string
+ fAccessKeyId string
+ fAccessKeySecret string
+ fDomain string
+)
+
+func init() {
+ argsPrefix := "CERTIMATE_DEPLOYER_JDCLOUDLIVE_"
+
+ flag.StringVar(&fInputCertPath, argsPrefix+"INPUTCERTPATH", "", "")
+ flag.StringVar(&fInputKeyPath, argsPrefix+"INPUTKEYPATH", "", "")
+ flag.StringVar(&fAccessKeyId, argsPrefix+"ACCESSKEYID", "", "")
+ flag.StringVar(&fAccessKeySecret, argsPrefix+"ACCESSKEYSECRET", "", "")
+ flag.StringVar(&fDomain, argsPrefix+"DOMAIN", "", "")
+}
+
+/*
+Shell command to run this test:
+
+ go test -v ./jdcloud_live_test.go -args \
+ --CERTIMATE_DEPLOYER_JDCLOUDLIVE_INPUTCERTPATH="/path/to/your-input-cert.pem" \
+ --CERTIMATE_DEPLOYER_JDCLOUDLIVE_INPUTKEYPATH="/path/to/your-input-key.pem" \
+ --CERTIMATE_DEPLOYER_JDCLOUDLIVE_ACCESSKEYID="your-access-key-id" \
+ --CERTIMATE_DEPLOYER_JDCLOUDLIVE_ACCESSKEYSECRET="your-secret-access-key" \
+ --CERTIMATE_DEPLOYER_JDCLOUDLIVE_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("DOMAIN: %v", fDomain),
+ }, "\n"))
+
+ deployer, err := provider.NewDeployer(&provider.DeployerConfig{
+ AccessKeyId: fAccessKeyId,
+ AccessKeySecret: fAccessKeySecret,
+ 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/jdcloud-vod/jdcloud_vod.go b/internal/pkg/core/deployer/providers/jdcloud-vod/jdcloud_vod.go
new file mode 100644
index 00000000..b83fd430
--- /dev/null
+++ b/internal/pkg/core/deployer/providers/jdcloud-vod/jdcloud_vod.go
@@ -0,0 +1,123 @@
+package jdcloudvod
+
+import (
+ "context"
+ "fmt"
+ "strconv"
+ "time"
+
+ 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"
+ "github.com/usual2970/certimate/internal/pkg/core/logger"
+)
+
+type DeployerConfig struct {
+ // 京东云 AccessKeyId。
+ AccessKeyId string `json:"accessKeyId"`
+ // 京东云 AccessKeySecret。
+ AccessKeySecret string `json:"accessKeySecret"`
+ // 点播加速域名(不支持泛域名)。
+ Domain string `json:"domain"`
+}
+
+type DeployerProvider struct {
+ config *DeployerConfig
+ logger logger.Logger
+ sdkClient *jdVodClient.VodClient
+}
+
+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)
+ if err != nil {
+ return nil, xerrors.Wrap(err, "failed to create sdk client")
+ }
+
+ return &DeployerProvider{
+ config: config,
+ logger: logger.NewNilLogger(),
+ sdkClient: client,
+ }, nil
+}
+
+func (d *DeployerProvider) WithLogger(logger logger.Logger) *DeployerProvider {
+ d.logger = logger
+ return d
+}
+
+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 {
+ listDomainsReq := jdVodApi.NewListDomainsRequest()
+ listDomainsReq.SetPageNumber(1)
+ listDomainsReq.SetPageSize(100)
+ listDomainsResp, err := d.sdkClient.ListDomains(listDomainsReq)
+ if err != nil {
+ return nil, xerrors.Wrap(err, "failed to execute sdk request 'vod.ListDomains'")
+ }
+
+ for _, domain := range listDomainsResp.Result.Content {
+ if domain.Name == d.config.Domain {
+ domainId, _ = strconv.Atoi(domain.Id)
+ break
+ }
+ }
+
+ if len(listDomainsResp.Result.Content) < listDomainsPageSize {
+ break
+ } else {
+ listDomainsPageNumber++
+ }
+ }
+ if domainId == 0 {
+ return nil, xerrors.New("domain not found")
+ }
+
+ // 查询域名 SSL 配置
+ // REF: https://docs.jdcloud.com/cn/video-on-demand/api/gethttpssl
+ getHttpSslReq := jdVodApi.NewGetHttpSslRequest(domainId)
+ getHttpSslResp, err := d.sdkClient.GetHttpSsl(getHttpSslReq)
+ if err != nil {
+ return nil, xerrors.Wrap(err, "failed to execute sdk request 'vod.GetHttpSsl'")
+ } else {
+ d.logger.Logt("已查询到域名 SSL 配置", getHttpSslResp)
+ }
+
+ // 设置域名 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.SetSource("default")
+ setHttpSslReq.SetJumpType(getHttpSslResp.Result.JumpType)
+ setHttpSslReq.SetEnabled(true)
+ setHttpSslResp, err := d.sdkClient.SetHttpSsl(setHttpSslReq)
+ if err != nil {
+ return nil, xerrors.Wrap(err, "failed to execute sdk request 'vod.SetHttpSsl'")
+ } else {
+ d.logger.Logt("已设置域名 SSL 配置", setHttpSslResp)
+ }
+
+ return &deployer.DeployResult{}, nil
+}
+
+func createSdkClient(accessKeyId, accessKeySecret string) (*jdVodClient.VodClient, error) {
+ clientCredentials := jdCore.NewCredentials(accessKeyId, accessKeySecret)
+ client := jdVodClient.NewVodClient(clientCredentials)
+ client.SetLogger(jdCore.NewDefaultLogger(jdCore.LogWarn))
+ return client, 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
new file mode 100644
index 00000000..6046982b
--- /dev/null
+++ b/internal/pkg/core/deployer/providers/jdcloud-vod/jdcloud_vod_test.go
@@ -0,0 +1,75 @@
+package jdcloudvod_test
+
+import (
+ "context"
+ "flag"
+ "fmt"
+ "os"
+ "strings"
+ "testing"
+
+ provider "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/jdcloud-vod"
+)
+
+var (
+ fInputCertPath string
+ fInputKeyPath string
+ fAccessKeyId string
+ fAccessKeySecret string
+ fDomain string
+)
+
+func init() {
+ argsPrefix := "CERTIMATE_DEPLOYER_JDCLOUDVOD_"
+
+ flag.StringVar(&fInputCertPath, argsPrefix+"INPUTCERTPATH", "", "")
+ flag.StringVar(&fInputKeyPath, argsPrefix+"INPUTKEYPATH", "", "")
+ flag.StringVar(&fAccessKeyId, argsPrefix+"ACCESSKEYID", "", "")
+ flag.StringVar(&fAccessKeySecret, argsPrefix+"ACCESSKEYSECRET", "", "")
+ flag.StringVar(&fDomain, argsPrefix+"DOMAIN", "", "")
+}
+
+/*
+Shell command to run this test:
+
+ go test -v ./jdcloud_vod_test.go -args \
+ --CERTIMATE_DEPLOYER_JDCLOUDVOD_INPUTCERTPATH="/path/to/your-input-cert.pem" \
+ --CERTIMATE_DEPLOYER_JDCLOUDVOD_INPUTKEYPATH="/path/to/your-input-key.pem" \
+ --CERTIMATE_DEPLOYER_JDCLOUDVOD_ACCESSKEYID="your-access-key-id" \
+ --CERTIMATE_DEPLOYER_JDCLOUDVOD_ACCESSKEYSECRET="your-secret-access-key" \
+ --CERTIMATE_DEPLOYER_JDCLOUDVOD_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("DOMAIN: %v", fDomain),
+ }, "\n"))
+
+ deployer, err := provider.NewDeployer(&provider.DeployerConfig{
+ AccessKeyId: fAccessKeyId,
+ AccessKeySecret: fAccessKeySecret,
+ 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/k8s-secret/k8s_secret.go b/internal/pkg/core/deployer/providers/k8s-secret/k8s_secret.go
index 2b7ab8fd..c97e4386 100644
--- a/internal/pkg/core/deployer/providers/k8s-secret/k8s_secret.go
+++ b/internal/pkg/core/deployer/providers/k8s-secret/k8s_secret.go
@@ -17,7 +17,7 @@ import (
"github.com/usual2970/certimate/internal/pkg/utils/certs"
)
-type K8sSecretDeployerConfig struct {
+type DeployerConfig struct {
// kubeconfig 文件内容。
KubeConfig string `json:"kubeConfig,omitempty"`
// Kubernetes 命名空间。
@@ -32,33 +32,30 @@ type K8sSecretDeployerConfig struct {
SecretDataKeyForKey string `json:"secretDataKeyForKey,omitempty"`
}
-type K8sSecretDeployer struct {
- config *K8sSecretDeployerConfig
+type DeployerProvider struct {
+ config *DeployerConfig
logger logger.Logger
}
-var _ deployer.Deployer = (*K8sSecretDeployer)(nil)
+var _ deployer.Deployer = (*DeployerProvider)(nil)
-func New(config *K8sSecretDeployerConfig) (*K8sSecretDeployer, error) {
- return NewWithLogger(config, logger.NewNilLogger())
-}
-
-func NewWithLogger(config *K8sSecretDeployerConfig, logger logger.Logger) (*K8sSecretDeployer, error) {
+func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) {
if config == nil {
- return nil, errors.New("config is nil")
+ panic("config is nil")
}
- if logger == nil {
- return nil, errors.New("logger is nil")
- }
-
- return &K8sSecretDeployer{
- logger: logger,
+ return &DeployerProvider{
+ logger: logger.NewNilLogger(),
config: config,
}, nil
}
-func (d *K8sSecretDeployer) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) {
+func (d *DeployerProvider) WithLogger(logger logger.Logger) *DeployerProvider {
+ d.logger = logger
+ return d
+}
+
+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")
}
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 913099ec..75f15502 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
@@ -56,7 +56,7 @@ func TestDeploy(t *testing.T) {
fmt.Sprintf("SECRETDATAKEYFORKEY: %v", fSecretDataKeyForKey),
}, "\n"))
- deployer, err := provider.New(&provider.K8sSecretDeployerConfig{
+ deployer, err := provider.NewDeployer(&provider.DeployerConfig{
Namespace: fNamespace,
SecretName: fSecretName,
SecretDataKeyForCrt: fSecretDataKeyForCrt,
diff --git a/internal/pkg/core/deployer/providers/local/local.go b/internal/pkg/core/deployer/providers/local/local.go
index e254caf9..7952f63c 100644
--- a/internal/pkg/core/deployer/providers/local/local.go
+++ b/internal/pkg/core/deployer/providers/local/local.go
@@ -3,7 +3,6 @@ package local
import (
"bytes"
"context"
- "errors"
"fmt"
"os/exec"
"runtime"
@@ -16,7 +15,7 @@ import (
"github.com/usual2970/certimate/internal/pkg/utils/files"
)
-type LocalDeployerConfig struct {
+type DeployerConfig struct {
// Shell 执行环境。
// 零值时默认根据操作系统决定。
ShellEnv ShellEnvType `json:"shellEnv,omitempty"`
@@ -44,33 +43,30 @@ type LocalDeployerConfig struct {
JksStorepass string `json:"jksStorepass,omitempty"`
}
-type LocalDeployer struct {
- config *LocalDeployerConfig
+type DeployerProvider struct {
+ config *DeployerConfig
logger logger.Logger
}
-var _ deployer.Deployer = (*LocalDeployer)(nil)
+var _ deployer.Deployer = (*DeployerProvider)(nil)
-func New(config *LocalDeployerConfig) (*LocalDeployer, error) {
- return NewWithLogger(config, logger.NewNilLogger())
-}
-
-func NewWithLogger(config *LocalDeployerConfig, logger logger.Logger) (*LocalDeployer, error) {
+func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) {
if config == nil {
- return nil, errors.New("config is nil")
+ panic("config is nil")
}
- if logger == nil {
- return nil, errors.New("logger is nil")
- }
-
- return &LocalDeployer{
- logger: logger,
+ return &DeployerProvider{
config: config,
+ logger: logger.NewNilLogger(),
}, nil
}
-func (d *LocalDeployer) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) {
+func (d *DeployerProvider) WithLogger(logger logger.Logger) *DeployerProvider {
+ d.logger = logger
+ return d
+}
+
+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)
diff --git a/internal/pkg/core/deployer/providers/local/local_test.go b/internal/pkg/core/deployer/providers/local/local_test.go
index 723ddf58..e86ba7e0 100644
--- a/internal/pkg/core/deployer/providers/local/local_test.go
+++ b/internal/pkg/core/deployer/providers/local/local_test.go
@@ -72,7 +72,7 @@ func TestDeploy(t *testing.T) {
fmt.Sprintf("POSTCOMMAND: %v", fPostCommand),
}, "\n"))
- deployer, err := provider.New(&provider.LocalDeployerConfig{
+ deployer, err := provider.NewDeployer(&provider.DeployerConfig{
OutputFormat: provider.OUTPUT_FORMAT_PEM,
OutputCertPath: fOutputCertPath + ".pem",
OutputKeyPath: fOutputKeyPath + ".pem",
@@ -123,7 +123,7 @@ func TestDeploy(t *testing.T) {
fmt.Sprintf("PFXPASSWORD: %v", fPfxPassword),
}, "\n"))
- deployer, err := provider.New(&provider.LocalDeployerConfig{
+ deployer, err := provider.NewDeployer(&provider.DeployerConfig{
OutputFormat: provider.OUTPUT_FORMAT_PFX,
OutputCertPath: fOutputCertPath + ".pfx",
PfxPassword: fPfxPassword,
@@ -164,7 +164,7 @@ func TestDeploy(t *testing.T) {
fmt.Sprintf("JKSSTOREPASS: %v", fJksStorepass),
}, "\n"))
- deployer, err := provider.New(&provider.LocalDeployerConfig{
+ deployer, err := provider.NewDeployer(&provider.DeployerConfig{
OutputFormat: provider.OUTPUT_FORMAT_JKS,
OutputCertPath: fOutputCertPath + ".jks",
JksAlias: fJksAlias,
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 8fac6459..cdb62b8c 100644
--- a/internal/pkg/core/deployer/providers/qiniu-cdn/qiniu_cdn.go
+++ b/internal/pkg/core/deployer/providers/qiniu-cdn/qiniu_cdn.go
@@ -2,7 +2,6 @@
import (
"context"
- "errors"
"strings"
xerrors "github.com/pkg/errors"
@@ -11,11 +10,11 @@ import (
"github.com/usual2970/certimate/internal/pkg/core/deployer"
"github.com/usual2970/certimate/internal/pkg/core/logger"
"github.com/usual2970/certimate/internal/pkg/core/uploader"
- uploaderp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/qiniu-sslcert"
+ uploadersp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/qiniu-sslcert"
qiniusdk "github.com/usual2970/certimate/internal/pkg/vendors/qiniu-sdk"
)
-type QiniuCDNDeployerConfig struct {
+type DeployerConfig struct {
// 七牛云 AccessKey。
AccessKey string `json:"accessKey"`
// 七牛云 SecretKey。
@@ -24,31 +23,23 @@ type QiniuCDNDeployerConfig struct {
Domain string `json:"domain"`
}
-type QiniuCDNDeployer struct {
- config *QiniuCDNDeployerConfig
+type DeployerProvider struct {
+ config *DeployerConfig
logger logger.Logger
sdkClient *qiniusdk.Client
sslUploader uploader.Uploader
}
-var _ deployer.Deployer = (*QiniuCDNDeployer)(nil)
+var _ deployer.Deployer = (*DeployerProvider)(nil)
-func New(config *QiniuCDNDeployerConfig) (*QiniuCDNDeployer, error) {
- return NewWithLogger(config, logger.NewNilLogger())
-}
-
-func NewWithLogger(config *QiniuCDNDeployerConfig, logger logger.Logger) (*QiniuCDNDeployer, error) {
+func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) {
if config == nil {
- return nil, errors.New("config is nil")
- }
-
- if logger == nil {
- return nil, errors.New("logger is nil")
+ panic("config is nil")
}
client := qiniusdk.NewClient(auth.New(config.AccessKey, config.SecretKey))
- uploader, err := uploaderp.New(&uploaderp.QiniuSSLCertUploaderConfig{
+ uploader, err := uploadersp.NewUploader(&uploadersp.UploaderConfig{
AccessKey: config.AccessKey,
SecretKey: config.SecretKey,
})
@@ -56,15 +47,20 @@ func NewWithLogger(config *QiniuCDNDeployerConfig, logger logger.Logger) (*Qiniu
return nil, xerrors.Wrap(err, "failed to create ssl uploader")
}
- return &QiniuCDNDeployer{
- logger: logger,
+ return &DeployerProvider{
config: config,
+ logger: logger.NewNilLogger(),
sdkClient: client,
sslUploader: uploader,
}, nil
}
-func (d *QiniuCDNDeployer) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) {
+func (d *DeployerProvider) WithLogger(logger logger.Logger) *DeployerProvider {
+ d.logger = logger
+ return d
+}
+
+func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) {
// 上传证书到 CDN
upres, err := d.sslUploader.Upload(ctx, certPem, privkeyPem)
if err != nil {
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 85ca8316..eff0ab48 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
@@ -52,7 +52,7 @@ func TestDeploy(t *testing.T) {
fmt.Sprintf("DOMAIN: %v", fDomain),
}, "\n"))
- deployer, err := provider.New(&provider.QiniuCDNDeployerConfig{
+ deployer, err := provider.NewDeployer(&provider.DeployerConfig{
AccessKey: fAccessKey,
SecretKey: fSecretKey,
Domain: fDomain,
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 4530071c..b9121694 100644
--- a/internal/pkg/core/deployer/providers/qiniu-pili/qiniu_pili.go
+++ b/internal/pkg/core/deployer/providers/qiniu-pili/qiniu_pili.go
@@ -2,7 +2,6 @@
import (
"context"
- "errors"
xerrors "github.com/pkg/errors"
"github.com/qiniu/go-sdk/v7/pili"
@@ -10,10 +9,10 @@ import (
"github.com/usual2970/certimate/internal/pkg/core/deployer"
"github.com/usual2970/certimate/internal/pkg/core/logger"
"github.com/usual2970/certimate/internal/pkg/core/uploader"
- uploaderp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/qiniu-sslcert"
+ uploadersp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/qiniu-sslcert"
)
-type QiniuPiliDeployerConfig struct {
+type DeployerConfig struct {
// 七牛云 AccessKey。
AccessKey string `json:"accessKey"`
// 七牛云 SecretKey。
@@ -24,31 +23,23 @@ type QiniuPiliDeployerConfig struct {
Domain string `json:"domain"`
}
-type QiniuPiliDeployer struct {
- config *QiniuPiliDeployerConfig
+type DeployerProvider struct {
+ config *DeployerConfig
logger logger.Logger
sdkClient *pili.Manager
sslUploader uploader.Uploader
}
-var _ deployer.Deployer = (*QiniuPiliDeployer)(nil)
+var _ deployer.Deployer = (*DeployerProvider)(nil)
-func New(config *QiniuPiliDeployerConfig) (*QiniuPiliDeployer, error) {
- return NewWithLogger(config, logger.NewNilLogger())
-}
-
-func NewWithLogger(config *QiniuPiliDeployerConfig, logger logger.Logger) (*QiniuPiliDeployer, error) {
+func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) {
if config == nil {
- return nil, errors.New("config is nil")
- }
-
- if logger == nil {
- return nil, errors.New("logger is nil")
+ panic("config is nil")
}
manager := pili.NewManager(pili.ManagerConfig{AccessKey: config.AccessKey, SecretKey: config.SecretKey})
- uploader, err := uploaderp.New(&uploaderp.QiniuSSLCertUploaderConfig{
+ uploader, err := uploadersp.NewUploader(&uploadersp.UploaderConfig{
AccessKey: config.AccessKey,
SecretKey: config.SecretKey,
})
@@ -56,15 +47,20 @@ func NewWithLogger(config *QiniuPiliDeployerConfig, logger logger.Logger) (*Qini
return nil, xerrors.Wrap(err, "failed to create ssl uploader")
}
- return &QiniuPiliDeployer{
- logger: logger,
+ return &DeployerProvider{
config: config,
+ logger: logger.NewNilLogger(),
sdkClient: manager,
sslUploader: uploader,
}, nil
}
-func (d *QiniuPiliDeployer) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) {
+func (d *DeployerProvider) WithLogger(logger logger.Logger) *DeployerProvider {
+ d.logger = logger
+ return d
+}
+
+func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) {
// 上传证书到 CDN
upres, err := d.sslUploader.Upload(ctx, certPem, privkeyPem)
if err != 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 06ef47e4..1d307dda 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
@@ -56,7 +56,7 @@ func TestDeploy(t *testing.T) {
fmt.Sprintf("DOMAIN: %v", fDomain),
}, "\n"))
- deployer, err := provider.New(&provider.QiniuPiliDeployerConfig{
+ deployer, err := provider.NewDeployer(&provider.DeployerConfig{
AccessKey: fAccessKey,
SecretKey: fSecretKey,
Domain: fDomain,
diff --git a/internal/pkg/core/deployer/providers/safeline/consts.go b/internal/pkg/core/deployer/providers/safeline/consts.go
new file mode 100644
index 00000000..a19e3866
--- /dev/null
+++ b/internal/pkg/core/deployer/providers/safeline/consts.go
@@ -0,0 +1,8 @@
+package safeline
+
+type ResourceType string
+
+const (
+ // 资源类型:替换指定证书。
+ RESOURCE_TYPE_CERTIFICATE = ResourceType("certificate")
+)
diff --git a/internal/pkg/core/deployer/providers/safeline/safeline.go b/internal/pkg/core/deployer/providers/safeline/safeline.go
new file mode 100644
index 00000000..3b4006c4
--- /dev/null
+++ b/internal/pkg/core/deployer/providers/safeline/safeline.go
@@ -0,0 +1,108 @@
+package safeline
+
+import (
+ "context"
+ "errors"
+ "fmt"
+ "net/url"
+
+ xerrors "github.com/pkg/errors"
+
+ "github.com/usual2970/certimate/internal/pkg/core/deployer"
+ "github.com/usual2970/certimate/internal/pkg/core/logger"
+ safelinesdk "github.com/usual2970/certimate/internal/pkg/vendors/safeline-sdk"
+)
+
+type DeployerConfig struct {
+ // 雷池 URL。
+ ApiUrl string `json:"apiUrl"`
+ // 雷池 API Token。
+ ApiToken string `json:"apiToken"`
+ // 部署资源类型。
+ ResourceType ResourceType `json:"resourceType"`
+ // 证书 ID。
+ // 部署资源类型为 [RESOURCE_TYPE_CERTIFICATE] 时必填。
+ CertificateId int32 `json:"certificateId,omitempty"`
+}
+
+type DeployerProvider struct {
+ config *DeployerConfig
+ logger logger.Logger
+ sdkClient *safelinesdk.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)
+ if err != nil {
+ return nil, xerrors.Wrap(err, "failed to create sdk clients")
+ }
+
+ return &DeployerProvider{
+ config: config,
+ logger: logger.NewNilLogger(),
+ sdkClient: client,
+ }, nil
+}
+
+func (d *DeployerProvider) WithLogger(logger logger.Logger) *DeployerProvider {
+ 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")
+ }
+
+ // 更新证书
+ updateCertificateReq := &safelinesdk.UpdateCertificateRequest{
+ Id: d.config.CertificateId,
+ Type: 2,
+ Manual: &safelinesdk.UpdateCertificateRequestBodyManul{
+ Crt: certPem,
+ Key: privkeyPem,
+ },
+ }
+ updateCertificateResp, err := d.sdkClient.UpdateCertificate(updateCertificateReq)
+ if err != nil {
+ return xerrors.Wrap(err, "failed to execute sdk request 'safeline.UpdateCertificate'")
+ } else {
+ d.logger.Logt("已更新证书", updateCertificateResp)
+ }
+
+ return nil
+}
+
+func createSdkClient(apiUrl, apiToken string) (*safelinesdk.Client, error) {
+ if _, err := url.Parse(apiUrl); err != nil {
+ return nil, errors.New("invalid safeline api url")
+ }
+
+ if apiToken == "" {
+ return nil, errors.New("invalid safeline api token")
+ }
+
+ client := safelinesdk.NewClient(apiUrl, apiToken)
+ return client, nil
+}
diff --git a/internal/pkg/core/deployer/providers/safeline/safeline_test.go b/internal/pkg/core/deployer/providers/safeline/safeline_test.go
new file mode 100644
index 00000000..0d7f2223
--- /dev/null
+++ b/internal/pkg/core/deployer/providers/safeline/safeline_test.go
@@ -0,0 +1,76 @@
+package safeline_test
+
+import (
+ "context"
+ "flag"
+ "fmt"
+ "os"
+ "strings"
+ "testing"
+
+ provider "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/safeline"
+)
+
+var (
+ fInputCertPath string
+ fInputKeyPath string
+ fApiUrl string
+ fApiToken string
+ fCertificateId int
+)
+
+func init() {
+ argsPrefix := "CERTIMATE_DEPLOYER_SAFELINE_"
+
+ flag.StringVar(&fInputCertPath, argsPrefix+"INPUTCERTPATH", "", "")
+ flag.StringVar(&fInputKeyPath, argsPrefix+"INPUTKEYPATH", "", "")
+ flag.StringVar(&fApiUrl, argsPrefix+"APIURL", "", "")
+ flag.StringVar(&fApiToken, argsPrefix+"APITOKEN", "", "")
+ flag.IntVar(&fCertificateId, argsPrefix+"CERTIFICATEID", 0, "")
+}
+
+/*
+Shell command to run this test:
+
+ go test -v ./safeline_test.go -args \
+ --CERTIMATE_DEPLOYER_SAFELINE_INPUTCERTPATH="/path/to/your-input-cert.pem" \
+ --CERTIMATE_DEPLOYER_SAFELINE_INPUTKEYPATH="/path/to/your-input-key.pem" \
+ --CERTIMATE_DEPLOYER_SAFELINE_APIURL="http://127.0.0.1:9443" \
+ --CERTIMATE_DEPLOYER_SAFELINE_APITOKEN="your-api-token" \
+ --CERTIMATE_DEPLOYER_SAFELINE_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("APITOKEN: %v", fApiToken),
+ fmt.Sprintf("CERTIFICATEID: %v", fCertificateId),
+ }, "\n"))
+
+ deployer, err := provider.NewDeployer(&provider.DeployerConfig{
+ ApiUrl: fApiUrl,
+ ApiToken: fApiToken,
+ ResourceType: provider.ResourceType("certificate"),
+ CertificateId: 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/ssh/ssh.go b/internal/pkg/core/deployer/providers/ssh/ssh.go
index 20ea348a..a1617327 100644
--- a/internal/pkg/core/deployer/providers/ssh/ssh.go
+++ b/internal/pkg/core/deployer/providers/ssh/ssh.go
@@ -3,7 +3,6 @@ package ssh
import (
"bytes"
"context"
- "errors"
"fmt"
"os"
"path/filepath"
@@ -18,7 +17,7 @@ import (
"github.com/usual2970/certimate/internal/pkg/utils/certs"
)
-type SshDeployerConfig struct {
+type DeployerConfig struct {
// SSH 主机。
// 零值时默认为 "localhost"。
SshHost string `json:"sshHost,omitempty"`
@@ -59,33 +58,30 @@ type SshDeployerConfig struct {
JksStorepass string `json:"jksStorepass,omitempty"`
}
-type SshDeployer struct {
- config *SshDeployerConfig
+type DeployerProvider struct {
+ config *DeployerConfig
logger logger.Logger
}
-var _ deployer.Deployer = (*SshDeployer)(nil)
+var _ deployer.Deployer = (*DeployerProvider)(nil)
-func New(config *SshDeployerConfig) (*SshDeployer, error) {
- return NewWithLogger(config, logger.NewNilLogger())
-}
-
-func NewWithLogger(config *SshDeployerConfig, logger logger.Logger) (*SshDeployer, error) {
+func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) {
if config == nil {
- return nil, errors.New("config is nil")
+ panic("config is nil")
}
- if logger == nil {
- return nil, errors.New("logger is nil")
- }
-
- return &SshDeployer{
- logger: logger,
+ return &DeployerProvider{
config: config,
+ logger: logger.NewNilLogger(),
}, nil
}
-func (d *SshDeployer) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) {
+func (d *DeployerProvider) WithLogger(logger logger.Logger) *DeployerProvider {
+ d.logger = logger
+ return d
+}
+
+func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) {
// 连接
client, err := createSshClient(
d.config.SshHost,
diff --git a/internal/pkg/core/deployer/providers/ssh/ssh_test.go b/internal/pkg/core/deployer/providers/ssh/ssh_test.go
index 4221378e..8312d680 100644
--- a/internal/pkg/core/deployer/providers/ssh/ssh_test.go
+++ b/internal/pkg/core/deployer/providers/ssh/ssh_test.go
@@ -64,7 +64,7 @@ func TestDeploy(t *testing.T) {
fmt.Sprintf("OUTPUTKEYPATH: %v", fOutputKeyPath),
}, "\n"))
- deployer, err := provider.New(&provider.SshDeployerConfig{
+ deployer, err := provider.NewDeployer(&provider.DeployerConfig{
SshHost: fSshHost,
SshPort: int32(fSshPort),
SshUsername: fSshUsername,
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 61418845..1784354d 100644
--- a/internal/pkg/core/deployer/providers/tencentcloud-cdn/tencentcloud_cdn.go
+++ b/internal/pkg/core/deployer/providers/tencentcloud-cdn/tencentcloud_cdn.go
@@ -2,7 +2,6 @@
import (
"context"
- "errors"
"strings"
xerrors "github.com/pkg/errors"
@@ -15,10 +14,10 @@ import (
"github.com/usual2970/certimate/internal/pkg/core/deployer"
"github.com/usual2970/certimate/internal/pkg/core/logger"
"github.com/usual2970/certimate/internal/pkg/core/uploader"
- uploaderp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/tencentcloud-ssl"
+ uploadersp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/tencentcloud-ssl"
)
-type TencentCloudCDNDeployerConfig struct {
+type DeployerConfig struct {
// 腾讯云 SecretId。
SecretId string `json:"secretId"`
// 腾讯云 SecretKey。
@@ -27,31 +26,23 @@ type TencentCloudCDNDeployerConfig struct {
Domain string `json:"domain"`
}
-type TencentCloudCDNDeployer struct {
- config *TencentCloudCDNDeployerConfig
+type DeployerProvider struct {
+ config *DeployerConfig
logger logger.Logger
sdkClients *wSdkClients
sslUploader uploader.Uploader
}
-var _ deployer.Deployer = (*TencentCloudCDNDeployer)(nil)
+var _ deployer.Deployer = (*DeployerProvider)(nil)
type wSdkClients struct {
ssl *tcSsl.Client
cdn *tcCdn.Client
}
-func New(config *TencentCloudCDNDeployerConfig) (*TencentCloudCDNDeployer, error) {
- return NewWithLogger(config, logger.NewNilLogger())
-}
-
-func NewWithLogger(config *TencentCloudCDNDeployerConfig, logger logger.Logger) (*TencentCloudCDNDeployer, error) {
+func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) {
if config == nil {
- return nil, errors.New("config is nil")
- }
-
- if logger == nil {
- return nil, errors.New("logger is nil")
+ panic("config is nil")
}
clients, err := createSdkClients(config.SecretId, config.SecretKey)
@@ -59,7 +50,7 @@ func NewWithLogger(config *TencentCloudCDNDeployerConfig, logger logger.Logger)
return nil, xerrors.Wrap(err, "failed to create sdk clients")
}
- uploader, err := uploaderp.New(&uploaderp.TencentCloudSSLUploaderConfig{
+ uploader, err := uploadersp.NewUploader(&uploadersp.UploaderConfig{
SecretId: config.SecretId,
SecretKey: config.SecretKey,
})
@@ -67,15 +58,20 @@ func NewWithLogger(config *TencentCloudCDNDeployerConfig, logger logger.Logger)
return nil, xerrors.Wrap(err, "failed to create ssl uploader")
}
- return &TencentCloudCDNDeployer{
- logger: logger,
+ return &DeployerProvider{
config: config,
+ logger: logger.NewNilLogger(),
sdkClients: clients,
sslUploader: uploader,
}, nil
}
-func (d *TencentCloudCDNDeployer) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) {
+func (d *DeployerProvider) WithLogger(logger logger.Logger) *DeployerProvider {
+ d.logger = logger
+ return d
+}
+
+func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) {
// 上传证书到 SSL
upres, err := d.sslUploader.Upload(ctx, certPem, privkeyPem)
if err != nil {
@@ -135,7 +131,7 @@ func (d *TencentCloudCDNDeployer) Deploy(ctx context.Context, certPem string, pr
return &deployer.DeployResult{}, nil
}
-func (d *TencentCloudCDNDeployer) getDomainsByCertificateId(cloudCertId string) ([]string, error) {
+func (d *DeployerProvider) getDomainsByCertificateId(cloudCertId string) ([]string, error) {
// 获取证书中的可用域名
// REF: https://cloud.tencent.com/document/product/228/42491
describeCertDomainsReq := tcCdn.NewDescribeCertDomainsRequest()
@@ -156,7 +152,7 @@ func (d *TencentCloudCDNDeployer) getDomainsByCertificateId(cloudCertId string)
return domains, nil
}
-func (d *TencentCloudCDNDeployer) getDeployedDomainsByCertificateId(cloudCertId string) ([]string, error) {
+func (d *DeployerProvider) getDeployedDomainsByCertificateId(cloudCertId string) ([]string, error) {
// 根据证书查询关联 CDN 域名
// REF: https://cloud.tencent.com/document/product/400/62674
describeDeployedResourcesReq := tcSsl.NewDescribeDeployedResourcesRequest()
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 088251b1..0361e17b 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
@@ -52,7 +52,7 @@ func TestDeploy(t *testing.T) {
fmt.Sprintf("DOMAIN: %v", fDomain),
}, "\n"))
- deployer, err := provider.New(&provider.TencentCloudCDNDeployerConfig{
+ deployer, err := provider.NewDeployer(&provider.DeployerConfig{
SecretId: fSecretId,
SecretKey: fSecretKey,
Domain: fDomain,
diff --git a/internal/pkg/core/deployer/providers/tencentcloud-clb/consts.go b/internal/pkg/core/deployer/providers/tencentcloud-clb/consts.go
new file mode 100644
index 00000000..7d72d5d3
--- /dev/null
+++ b/internal/pkg/core/deployer/providers/tencentcloud-clb/consts.go
@@ -0,0 +1,14 @@
+package tencentcloudclb
+
+type ResourceType string
+
+const (
+ // 资源类型:通过 SSL 服务部署到云资源实例。
+ RESOURCE_TYPE_VIA_SSLDEPLOY = ResourceType("ssl-deploy")
+ // 资源类型:部署到指定负载均衡器。
+ RESOURCE_TYPE_LOADBALANCER = ResourceType("loadbalancer")
+ // 资源类型:部署到指定监听器。
+ RESOURCE_TYPE_LISTENER = ResourceType("listener")
+ // 资源类型:部署到指定转发规则域名。
+ RESOURCE_TYPE_RULEDOMAIN = ResourceType("ruledomain")
+)
diff --git a/internal/pkg/core/deployer/providers/tencentcloud-clb/defines.go b/internal/pkg/core/deployer/providers/tencentcloud-clb/defines.go
deleted file mode 100644
index 7e7eace9..00000000
--- a/internal/pkg/core/deployer/providers/tencentcloud-clb/defines.go
+++ /dev/null
@@ -1,14 +0,0 @@
-package tencentcloudclb
-
-type DeployResourceType string
-
-const (
- // 资源类型:通过 SSL 服务部署到云资源实例。
- DEPLOY_RESOURCE_VIA_SSLDEPLOY = DeployResourceType("ssl-deploy")
- // 资源类型:部署到指定负载均衡器。
- DEPLOY_RESOURCE_LOADBALANCER = DeployResourceType("loadbalancer")
- // 资源类型:部署到指定监听器。
- DEPLOY_RESOURCE_LISTENER = DeployResourceType("listener")
- // 资源类型:部署到指定转发规则域名。
- DEPLOY_RESOURCE_RULEDOMAIN = DeployResourceType("ruledomain")
-)
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 e6982817..521f3e34 100644
--- a/internal/pkg/core/deployer/providers/tencentcloud-clb/tencentcloud_clb.go
+++ b/internal/pkg/core/deployer/providers/tencentcloud-clb/tencentcloud_clb.go
@@ -14,10 +14,10 @@ import (
"github.com/usual2970/certimate/internal/pkg/core/deployer"
"github.com/usual2970/certimate/internal/pkg/core/logger"
"github.com/usual2970/certimate/internal/pkg/core/uploader"
- uploaderp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/tencentcloud-ssl"
+ uploadersp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/tencentcloud-ssl"
)
-type TencentCloudCLBDeployerConfig struct {
+type DeployerConfig struct {
// 腾讯云 SecretId。
SecretId string `json:"secretId"`
// 腾讯云 SecretKey。
@@ -25,43 +25,35 @@ type TencentCloudCLBDeployerConfig struct {
// 腾讯云地域。
Region string `json:"region"`
// 部署资源类型。
- ResourceType DeployResourceType `json:"resourceType"`
+ ResourceType ResourceType `json:"resourceType"`
// 负载均衡器 ID。
- // 部署资源类型为 [DEPLOY_RESOURCE_SSLDEPLOY]、[DEPLOY_RESOURCE_LOADBALANCER]、[DEPLOY_RESOURCE_RULEDOMAIN] 时必填。
+ // 部署资源类型为 [RESOURCE_TYPE_SSLDEPLOY]、[RESOURCE_TYPE_LOADBALANCER]、[RESOURCE_TYPE_RULEDOMAIN] 时必填。
LoadbalancerId string `json:"loadbalancerId,omitempty"`
// 负载均衡监听 ID。
- // 部署资源类型为 [DEPLOY_RESOURCE_SSLDEPLOY]、[DEPLOY_RESOURCE_LOADBALANCER]、[DEPLOY_RESOURCE_LISTENER]、[DEPLOY_RESOURCE_RULEDOMAIN] 时必填。
+ // 部署资源类型为 [RESOURCE_TYPE_SSLDEPLOY]、[RESOURCE_TYPE_LOADBALANCER]、[RESOURCE_TYPE_LISTENER]、[RESOURCE_TYPE_RULEDOMAIN] 时必填。
ListenerId string `json:"listenerId,omitempty"`
// SNI 域名或七层转发规则域名(支持泛域名)。
- // 部署资源类型为 [DEPLOY_RESOURCE_SSLDEPLOY] 时选填;部署资源类型为 [DEPLOY_RESOURCE_RULEDOMAIN] 时必填。
+ // 部署资源类型为 [RESOURCE_TYPE_SSLDEPLOY] 时选填;部署资源类型为 [RESOURCE_TYPE_RULEDOMAIN] 时必填。
Domain string `json:"domain,omitempty"`
}
-type TencentCloudCLBDeployer struct {
- config *TencentCloudCLBDeployerConfig
+type DeployerProvider struct {
+ config *DeployerConfig
logger logger.Logger
sdkClients *wSdkClients
sslUploader uploader.Uploader
}
-var _ deployer.Deployer = (*TencentCloudCLBDeployer)(nil)
+var _ deployer.Deployer = (*DeployerProvider)(nil)
type wSdkClients struct {
ssl *tcSsl.Client
clb *tcClb.Client
}
-func New(config *TencentCloudCLBDeployerConfig) (*TencentCloudCLBDeployer, error) {
- return NewWithLogger(config, logger.NewNilLogger())
-}
-
-func NewWithLogger(config *TencentCloudCLBDeployerConfig, logger logger.Logger) (*TencentCloudCLBDeployer, error) {
+func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) {
if config == nil {
- return nil, errors.New("config is nil")
- }
-
- if logger == nil {
- return nil, errors.New("logger is nil")
+ panic("config is nil")
}
clients, err := createSdkClients(config.SecretId, config.SecretKey, config.Region)
@@ -69,7 +61,7 @@ func NewWithLogger(config *TencentCloudCLBDeployerConfig, logger logger.Logger)
return nil, xerrors.Wrap(err, "failed to create sdk clients")
}
- uploader, err := uploaderp.New(&uploaderp.TencentCloudSSLUploaderConfig{
+ uploader, err := uploadersp.NewUploader(&uploadersp.UploaderConfig{
SecretId: config.SecretId,
SecretKey: config.SecretKey,
})
@@ -77,15 +69,20 @@ func NewWithLogger(config *TencentCloudCLBDeployerConfig, logger logger.Logger)
return nil, xerrors.Wrap(err, "failed to create ssl uploader")
}
- return &TencentCloudCLBDeployer{
- logger: logger,
+ return &DeployerProvider{
config: config,
+ logger: logger.NewNilLogger(),
sdkClients: clients,
sslUploader: uploader,
}, nil
}
-func (d *TencentCloudCLBDeployer) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) {
+func (d *DeployerProvider) WithLogger(logger logger.Logger) *DeployerProvider {
+ d.logger = logger
+ return d
+}
+
+func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) {
// 上传证书到 SSL
upres, err := d.sslUploader.Upload(ctx, certPem, privkeyPem)
if err != nil {
@@ -96,22 +93,22 @@ func (d *TencentCloudCLBDeployer) Deploy(ctx context.Context, certPem string, pr
// 根据部署资源类型决定部署方式
switch d.config.ResourceType {
- case DEPLOY_RESOURCE_VIA_SSLDEPLOY:
+ case RESOURCE_TYPE_VIA_SSLDEPLOY:
if err := d.deployViaSslService(ctx, upres.CertId); err != nil {
return nil, err
}
- case DEPLOY_RESOURCE_LOADBALANCER:
+ case RESOURCE_TYPE_LOADBALANCER:
if err := d.deployToLoadbalancer(ctx, upres.CertId); err != nil {
return nil, err
}
- case DEPLOY_RESOURCE_LISTENER:
+ case RESOURCE_TYPE_LISTENER:
if err := d.deployToListener(ctx, upres.CertId); err != nil {
return nil, err
}
- case DEPLOY_RESOURCE_RULEDOMAIN:
+ case RESOURCE_TYPE_RULEDOMAIN:
if err := d.deployToRuleDomain(ctx, upres.CertId); err != nil {
return nil, err
}
@@ -123,7 +120,7 @@ func (d *TencentCloudCLBDeployer) Deploy(ctx context.Context, certPem string, pr
return &deployer.DeployResult{}, nil
}
-func (d *TencentCloudCLBDeployer) deployViaSslService(ctx context.Context, cloudCertId string) error {
+func (d *DeployerProvider) deployViaSslService(ctx context.Context, cloudCertId string) error {
if d.config.LoadbalancerId == "" {
return errors.New("config `loadbalancerId` is required")
}
@@ -141,7 +138,7 @@ func (d *TencentCloudCLBDeployer) deployViaSslService(ctx context.Context, cloud
// 未指定 SNI,只需部署到监听器
deployCertificateInstanceReq.InstanceIdList = common.StringPtrs([]string{fmt.Sprintf("%s|%s", d.config.LoadbalancerId, d.config.ListenerId)})
} else {
- // 指定 SNI,需部署到域名(支持泛域名)
+ // 指定 SNI,需部署到域名
deployCertificateInstanceReq.InstanceIdList = common.StringPtrs([]string{fmt.Sprintf("%s|%s|%s", d.config.LoadbalancerId, d.config.ListenerId, d.config.Domain)})
}
deployCertificateInstanceResp, err := d.sdkClients.ssl.DeployCertificateInstance(deployCertificateInstanceReq)
@@ -154,7 +151,7 @@ func (d *TencentCloudCLBDeployer) deployViaSslService(ctx context.Context, cloud
return nil
}
-func (d *TencentCloudCLBDeployer) deployToLoadbalancer(ctx context.Context, cloudCertId string) error {
+func (d *DeployerProvider) deployToLoadbalancer(ctx context.Context, cloudCertId string) error {
if d.config.LoadbalancerId == "" {
return errors.New("config `loadbalancerId` is required")
}
@@ -201,7 +198,7 @@ func (d *TencentCloudCLBDeployer) deployToLoadbalancer(ctx context.Context, clou
return nil
}
-func (d *TencentCloudCLBDeployer) deployToListener(ctx context.Context, cloudCertId string) error {
+func (d *DeployerProvider) deployToListener(ctx context.Context, cloudCertId string) error {
if d.config.LoadbalancerId == "" {
return errors.New("config `loadbalancerId` is required")
}
@@ -217,7 +214,7 @@ func (d *TencentCloudCLBDeployer) deployToListener(ctx context.Context, cloudCer
return nil
}
-func (d *TencentCloudCLBDeployer) deployToRuleDomain(ctx context.Context, cloudCertId string) error {
+func (d *DeployerProvider) deployToRuleDomain(ctx context.Context, cloudCertId string) error {
if d.config.LoadbalancerId == "" {
return errors.New("config `loadbalancerId` is required")
}
@@ -248,7 +245,7 @@ func (d *TencentCloudCLBDeployer) deployToRuleDomain(ctx context.Context, cloudC
return nil
}
-func (d *TencentCloudCLBDeployer) modifyListenerCertificate(ctx context.Context, cloudLoadbalancerId, cloudListenerId, cloudCertId string) error {
+func (d *DeployerProvider) modifyListenerCertificate(ctx context.Context, cloudLoadbalancerId, cloudListenerId, cloudCertId string) error {
// 查询监听器列表
// REF: https://cloud.tencent.com/document/api/214/30686
describeListenersReq := tcClb.NewDescribeListenersRequest()
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 74a1e23e..0aeb1e7c 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
@@ -64,11 +64,11 @@ func TestDeploy(t *testing.T) {
fmt.Sprintf("DOMAIN: %v", fDomain),
}, "\n"))
- deployer, err := provider.New(&provider.TencentCloudCLBDeployerConfig{
+ deployer, err := provider.NewDeployer(&provider.DeployerConfig{
SecretId: fSecretId,
SecretKey: fSecretKey,
Region: fRegion,
- ResourceType: provider.DEPLOY_RESOURCE_VIA_SSLDEPLOY,
+ ResourceType: provider.RESOURCE_TYPE_VIA_SSLDEPLOY,
LoadbalancerId: fLoadbalancerId,
ListenerId: fListenerId,
Domain: fDomain,
@@ -100,11 +100,11 @@ func TestDeploy(t *testing.T) {
fmt.Sprintf("LOADBALANCERID: %v", fLoadbalancerId),
}, "\n"))
- deployer, err := provider.New(&provider.TencentCloudCLBDeployerConfig{
+ deployer, err := provider.NewDeployer(&provider.DeployerConfig{
SecretId: fSecretId,
SecretKey: fSecretKey,
Region: fRegion,
- ResourceType: provider.DEPLOY_RESOURCE_LOADBALANCER,
+ ResourceType: provider.RESOURCE_TYPE_LOADBALANCER,
LoadbalancerId: fLoadbalancerId,
})
if err != nil {
@@ -135,11 +135,11 @@ func TestDeploy(t *testing.T) {
fmt.Sprintf("LISTENERID: %v", fListenerId),
}, "\n"))
- deployer, err := provider.New(&provider.TencentCloudCLBDeployerConfig{
+ deployer, err := provider.NewDeployer(&provider.DeployerConfig{
SecretId: fSecretId,
SecretKey: fSecretKey,
Region: fRegion,
- ResourceType: provider.DEPLOY_RESOURCE_LISTENER,
+ ResourceType: provider.RESOURCE_TYPE_LISTENER,
LoadbalancerId: fLoadbalancerId,
ListenerId: fListenerId,
})
@@ -172,11 +172,11 @@ func TestDeploy(t *testing.T) {
fmt.Sprintf("DOMAIN: %v", fDomain),
}, "\n"))
- deployer, err := provider.New(&provider.TencentCloudCLBDeployerConfig{
+ deployer, err := provider.NewDeployer(&provider.DeployerConfig{
SecretId: fSecretId,
SecretKey: fSecretKey,
Region: fRegion,
- ResourceType: provider.DEPLOY_RESOURCE_RULEDOMAIN,
+ ResourceType: provider.RESOURCE_TYPE_RULEDOMAIN,
LoadbalancerId: fLoadbalancerId,
ListenerId: fListenerId,
Domain: fDomain,
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 c2af84fb..d3b3f881 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 tencentcloudcdn
+package tencentcloudcos
import (
"context"
@@ -13,10 +13,10 @@ import (
"github.com/usual2970/certimate/internal/pkg/core/deployer"
"github.com/usual2970/certimate/internal/pkg/core/logger"
"github.com/usual2970/certimate/internal/pkg/core/uploader"
- uploaderp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/tencentcloud-ssl"
+ uploadersp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/tencentcloud-ssl"
)
-type TencentCloudCOSDeployerConfig struct {
+type DeployerConfig struct {
// 腾讯云 SecretId。
SecretId string `json:"secretId"`
// 腾讯云 SecretKey。
@@ -29,26 +29,18 @@ type TencentCloudCOSDeployerConfig struct {
Domain string `json:"domain"`
}
-type TencentCloudCOSDeployer struct {
- config *TencentCloudCOSDeployerConfig
+type DeployerProvider struct {
+ config *DeployerConfig
logger logger.Logger
sdkClient *tcSsl.Client
sslUploader uploader.Uploader
}
-var _ deployer.Deployer = (*TencentCloudCOSDeployer)(nil)
+var _ deployer.Deployer = (*DeployerProvider)(nil)
-func New(config *TencentCloudCOSDeployerConfig) (*TencentCloudCOSDeployer, error) {
- return NewWithLogger(config, logger.NewNilLogger())
-}
-
-func NewWithLogger(config *TencentCloudCOSDeployerConfig, logger logger.Logger) (*TencentCloudCOSDeployer, error) {
+func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) {
if config == nil {
- return nil, errors.New("config is nil")
- }
-
- if logger == nil {
- return nil, errors.New("logger is nil")
+ panic("config is nil")
}
client, err := createSdkClient(config.SecretId, config.SecretKey, config.Region)
@@ -56,7 +48,7 @@ func NewWithLogger(config *TencentCloudCOSDeployerConfig, logger logger.Logger)
return nil, xerrors.Wrap(err, "failed to create sdk clients")
}
- uploader, err := uploaderp.New(&uploaderp.TencentCloudSSLUploaderConfig{
+ uploader, err := uploadersp.NewUploader(&uploadersp.UploaderConfig{
SecretId: config.SecretId,
SecretKey: config.SecretKey,
})
@@ -64,15 +56,20 @@ func NewWithLogger(config *TencentCloudCOSDeployerConfig, logger logger.Logger)
return nil, xerrors.Wrap(err, "failed to create ssl uploader")
}
- return &TencentCloudCOSDeployer{
- logger: logger,
+ return &DeployerProvider{
config: config,
+ logger: logger.NewNilLogger(),
sdkClient: client,
sslUploader: uploader,
}, nil
}
-func (d *TencentCloudCOSDeployer) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) {
+func (d *DeployerProvider) WithLogger(logger logger.Logger) *DeployerProvider {
+ d.logger = logger
+ return d
+}
+
+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")
}
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 d58e4f50..ab29a893 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 tencentcloudcdn_test
+package tencentcloudcos_test
import (
"context"
@@ -60,7 +60,7 @@ func TestDeploy(t *testing.T) {
fmt.Sprintf("DOMAIN: %v", fDomain),
}, "\n"))
- deployer, err := provider.New(&provider.TencentCloudCOSDeployerConfig{
+ deployer, err := provider.NewDeployer(&provider.DeployerConfig{
SecretId: fSecretId,
SecretKey: fSecretKey,
Region: fRegion,
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 31057017..ad5dbed5 100644
--- a/internal/pkg/core/deployer/providers/tencentcloud-css/tencentcloud_css.go
+++ b/internal/pkg/core/deployer/providers/tencentcloud-css/tencentcloud_css.go
@@ -2,7 +2,6 @@
import (
"context"
- "errors"
xerrors "github.com/pkg/errors"
"github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common"
@@ -12,10 +11,10 @@ import (
"github.com/usual2970/certimate/internal/pkg/core/deployer"
"github.com/usual2970/certimate/internal/pkg/core/logger"
"github.com/usual2970/certimate/internal/pkg/core/uploader"
- uploaderp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/tencentcloud-ssl"
+ uploadersp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/tencentcloud-ssl"
)
-type TencentCloudCSSDeployerConfig struct {
+type DeployerConfig struct {
// 腾讯云 SecretId。
SecretId string `json:"secretId"`
// 腾讯云 SecretKey。
@@ -24,26 +23,18 @@ type TencentCloudCSSDeployerConfig struct {
Domain string `json:"domain"`
}
-type TencentCloudCSSDeployer struct {
- config *TencentCloudCSSDeployerConfig
+type DeployerProvider struct {
+ config *DeployerConfig
logger logger.Logger
sdkClient *tcLive.Client
sslUploader uploader.Uploader
}
-var _ deployer.Deployer = (*TencentCloudCSSDeployer)(nil)
+var _ deployer.Deployer = (*DeployerProvider)(nil)
-func New(config *TencentCloudCSSDeployerConfig) (*TencentCloudCSSDeployer, error) {
- return NewWithLogger(config, logger.NewNilLogger())
-}
-
-func NewWithLogger(config *TencentCloudCSSDeployerConfig, logger logger.Logger) (*TencentCloudCSSDeployer, error) {
+func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) {
if config == nil {
- return nil, errors.New("config is nil")
- }
-
- if logger == nil {
- return nil, errors.New("logger is nil")
+ panic("config is nil")
}
client, err := createSdkClient(config.SecretId, config.SecretKey)
@@ -51,7 +42,7 @@ func NewWithLogger(config *TencentCloudCSSDeployerConfig, logger logger.Logger)
return nil, xerrors.Wrap(err, "failed to create sdk client")
}
- uploader, err := uploaderp.New(&uploaderp.TencentCloudSSLUploaderConfig{
+ uploader, err := uploadersp.NewUploader(&uploadersp.UploaderConfig{
SecretId: config.SecretId,
SecretKey: config.SecretKey,
})
@@ -59,15 +50,20 @@ func NewWithLogger(config *TencentCloudCSSDeployerConfig, logger logger.Logger)
return nil, xerrors.Wrap(err, "failed to create ssl uploader")
}
- return &TencentCloudCSSDeployer{
- logger: logger,
+ return &DeployerProvider{
config: config,
+ logger: logger.NewNilLogger(),
sdkClient: client,
sslUploader: uploader,
}, nil
}
-func (d *TencentCloudCSSDeployer) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) {
+func (d *DeployerProvider) WithLogger(logger logger.Logger) *DeployerProvider {
+ d.logger = logger
+ return d
+}
+
+func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) {
// 上传证书到 SSL
upres, err := d.sslUploader.Upload(ctx, certPem, privkeyPem)
if err != 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 4efe7bba..92127b3b 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
@@ -52,7 +52,7 @@ func TestDeploy(t *testing.T) {
fmt.Sprintf("DOMAIN: %v", fDomain),
}, "\n"))
- deployer, err := provider.New(&provider.TencentCloudCSSDeployerConfig{
+ deployer, err := provider.NewDeployer(&provider.DeployerConfig{
SecretId: fSecretId,
SecretKey: fSecretKey,
Domain: fDomain,
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 4cddbc59..e9438898 100644
--- a/internal/pkg/core/deployer/providers/tencentcloud-ecdn/tencentcloud_ecdn.go
+++ b/internal/pkg/core/deployer/providers/tencentcloud-ecdn/tencentcloud_ecdn.go
@@ -2,7 +2,6 @@
import (
"context"
- "errors"
"strings"
xerrors "github.com/pkg/errors"
@@ -14,10 +13,10 @@ import (
"github.com/usual2970/certimate/internal/pkg/core/deployer"
"github.com/usual2970/certimate/internal/pkg/core/logger"
"github.com/usual2970/certimate/internal/pkg/core/uploader"
- uploaderp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/tencentcloud-ssl"
+ uploadersp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/tencentcloud-ssl"
)
-type TencentCloudECDNDeployerConfig struct {
+type DeployerConfig struct {
// 腾讯云 SecretId。
SecretId string `json:"secretId"`
// 腾讯云 SecretKey。
@@ -26,31 +25,23 @@ type TencentCloudECDNDeployerConfig struct {
Domain string `json:"domain"`
}
-type TencentCloudECDNDeployer struct {
- config *TencentCloudECDNDeployerConfig
+type DeployerProvider struct {
+ config *DeployerConfig
logger logger.Logger
sdkClients *wSdkClients
sslUploader uploader.Uploader
}
-var _ deployer.Deployer = (*TencentCloudECDNDeployer)(nil)
+var _ deployer.Deployer = (*DeployerProvider)(nil)
type wSdkClients struct {
ssl *tcSsl.Client
cdn *tcCdn.Client
}
-func New(config *TencentCloudECDNDeployerConfig) (*TencentCloudECDNDeployer, error) {
- return NewWithLogger(config, logger.NewNilLogger())
-}
-
-func NewWithLogger(config *TencentCloudECDNDeployerConfig, logger logger.Logger) (*TencentCloudECDNDeployer, error) {
+func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) {
if config == nil {
- return nil, errors.New("config is nil")
- }
-
- if logger == nil {
- return nil, errors.New("logger is nil")
+ panic("config is nil")
}
clients, err := createSdkClients(config.SecretId, config.SecretKey)
@@ -58,7 +49,7 @@ func NewWithLogger(config *TencentCloudECDNDeployerConfig, logger logger.Logger)
return nil, xerrors.Wrap(err, "failed to create sdk clients")
}
- uploader, err := uploaderp.New(&uploaderp.TencentCloudSSLUploaderConfig{
+ uploader, err := uploadersp.NewUploader(&uploadersp.UploaderConfig{
SecretId: config.SecretId,
SecretKey: config.SecretKey,
})
@@ -66,15 +57,20 @@ func NewWithLogger(config *TencentCloudECDNDeployerConfig, logger logger.Logger)
return nil, xerrors.Wrap(err, "failed to create ssl uploader")
}
- return &TencentCloudECDNDeployer{
- logger: logger,
+ return &DeployerProvider{
config: config,
+ logger: logger.NewNilLogger(),
sdkClients: clients,
sslUploader: uploader,
}, nil
}
-func (d *TencentCloudECDNDeployer) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) {
+func (d *DeployerProvider) WithLogger(logger logger.Logger) *DeployerProvider {
+ d.logger = logger
+ return d
+}
+
+func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) {
// 上传证书到 SSL
upres, err := d.sslUploader.Upload(ctx, certPem, privkeyPem)
if err != nil {
@@ -118,7 +114,7 @@ func (d *TencentCloudECDNDeployer) Deploy(ctx context.Context, certPem string, p
return &deployer.DeployResult{}, nil
}
-func (d *TencentCloudECDNDeployer) getDomainsByCertificateId(cloudCertId string) ([]string, error) {
+func (d *DeployerProvider) getDomainsByCertificateId(cloudCertId string) ([]string, error) {
// 获取证书中的可用域名
// REF: https://cloud.tencent.com/document/product/228/42491
describeCertDomainsReq := tcCdn.NewDescribeCertDomainsRequest()
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 764aa5fb..da03a7ab 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
@@ -52,7 +52,7 @@ func TestDeploy(t *testing.T) {
fmt.Sprintf("DOMAIN: %v", fDomain),
}, "\n"))
- deployer, err := provider.New(&provider.TencentCloudECDNDeployerConfig{
+ deployer, err := provider.NewDeployer(&provider.DeployerConfig{
SecretId: fSecretId,
SecretKey: fSecretKey,
Domain: fDomain,
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 2de4dcc5..99669038 100644
--- a/internal/pkg/core/deployer/providers/tencentcloud-eo/tencentcloud_eo.go
+++ b/internal/pkg/core/deployer/providers/tencentcloud-eo/tencentcloud_eo.go
@@ -1,4 +1,4 @@
-package tencentcloudeteo
+package tencentcloudeo
import (
"context"
@@ -13,10 +13,10 @@ import (
"github.com/usual2970/certimate/internal/pkg/core/deployer"
"github.com/usual2970/certimate/internal/pkg/core/logger"
"github.com/usual2970/certimate/internal/pkg/core/uploader"
- uploaderp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/tencentcloud-ssl"
+ uploadersp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/tencentcloud-ssl"
)
-type TencentCloudEODeployerConfig struct {
+type DeployerConfig struct {
// 腾讯云 SecretId。
SecretId string `json:"secretId"`
// 腾讯云 SecretKey。
@@ -27,31 +27,23 @@ type TencentCloudEODeployerConfig struct {
Domain string `json:"domain"`
}
-type TencentCloudEODeployer struct {
- config *TencentCloudEODeployerConfig
+type DeployerProvider struct {
+ config *DeployerConfig
logger logger.Logger
sdkClients *wSdkClients
sslUploader uploader.Uploader
}
-var _ deployer.Deployer = (*TencentCloudEODeployer)(nil)
+var _ deployer.Deployer = (*DeployerProvider)(nil)
type wSdkClients struct {
ssl *tcSsl.Client
teo *tcTeo.Client
}
-func New(config *TencentCloudEODeployerConfig) (*TencentCloudEODeployer, error) {
- return NewWithLogger(config, logger.NewNilLogger())
-}
-
-func NewWithLogger(config *TencentCloudEODeployerConfig, logger logger.Logger) (*TencentCloudEODeployer, error) {
+func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) {
if config == nil {
- return nil, errors.New("config is nil")
- }
-
- if logger == nil {
- return nil, errors.New("logger is nil")
+ panic("config is nil")
}
clients, err := createSdkClients(config.SecretId, config.SecretKey)
@@ -59,7 +51,7 @@ func NewWithLogger(config *TencentCloudEODeployerConfig, logger logger.Logger) (
return nil, xerrors.Wrap(err, "failed to create sdk clients")
}
- uploader, err := uploaderp.New(&uploaderp.TencentCloudSSLUploaderConfig{
+ uploader, err := uploadersp.NewUploader(&uploadersp.UploaderConfig{
SecretId: config.SecretId,
SecretKey: config.SecretKey,
})
@@ -67,15 +59,20 @@ func NewWithLogger(config *TencentCloudEODeployerConfig, logger logger.Logger) (
return nil, xerrors.Wrap(err, "failed to create ssl uploader")
}
- return &TencentCloudEODeployer{
- logger: logger,
+ return &DeployerProvider{
config: config,
+ logger: logger.NewNilLogger(),
sdkClients: clients,
sslUploader: uploader,
}, nil
}
-func (d *TencentCloudEODeployer) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) {
+func (d *DeployerProvider) WithLogger(logger logger.Logger) *DeployerProvider {
+ d.logger = logger
+ return d
+}
+
+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")
}
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 bc5280f7..8e5b70fe 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 tencentcloudeteo_test
+package tencentcloudeo_test
import (
"context"
@@ -56,7 +56,7 @@ func TestDeploy(t *testing.T) {
fmt.Sprintf("DOMAIN: %v", fDomain),
}, "\n"))
- deployer, err := provider.New(&provider.TencentCloudEODeployerConfig{
+ deployer, err := provider.NewDeployer(&provider.DeployerConfig{
SecretId: fSecretId,
SecretKey: fSecretKey,
ZoneId: fZoneId,
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 37c00ea4..f943ad6e 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
@@ -14,10 +14,10 @@ import (
"github.com/usual2970/certimate/internal/pkg/core/deployer"
"github.com/usual2970/certimate/internal/pkg/core/logger"
"github.com/usual2970/certimate/internal/pkg/core/uploader"
- uploaderp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/tencentcloud-ssl"
+ uploadersp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/tencentcloud-ssl"
)
-type TencentCloudSSLDeployDeployerConfig struct {
+type DeployerConfig struct {
// 腾讯云 SecretId。
SecretId string `json:"secretId"`
// 腾讯云 SecretKey。
@@ -30,26 +30,18 @@ type TencentCloudSSLDeployDeployerConfig struct {
ResourceIds []string `json:"resourceIds"`
}
-type TencentCloudSSLDeployDeployer struct {
- config *TencentCloudSSLDeployDeployerConfig
+type DeployerProvider struct {
+ config *DeployerConfig
logger logger.Logger
sdkClient *tcSsl.Client
sslUploader uploader.Uploader
}
-var _ deployer.Deployer = (*TencentCloudSSLDeployDeployer)(nil)
+var _ deployer.Deployer = (*DeployerProvider)(nil)
-func New(config *TencentCloudSSLDeployDeployerConfig) (*TencentCloudSSLDeployDeployer, error) {
- return NewWithLogger(config, logger.NewNilLogger())
-}
-
-func NewWithLogger(config *TencentCloudSSLDeployDeployerConfig, logger logger.Logger) (*TencentCloudSSLDeployDeployer, error) {
+func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) {
if config == nil {
- return nil, errors.New("config is nil")
- }
-
- if logger == nil {
- return nil, errors.New("logger is nil")
+ panic("config is nil")
}
client, err := createSdkClient(config.SecretId, config.SecretKey, config.Region)
@@ -57,7 +49,7 @@ func NewWithLogger(config *TencentCloudSSLDeployDeployerConfig, logger logger.Lo
return nil, xerrors.Wrap(err, "failed to create sdk client")
}
- uploader, err := uploaderp.New(&uploaderp.TencentCloudSSLUploaderConfig{
+ uploader, err := uploadersp.NewUploader(&uploadersp.UploaderConfig{
SecretId: config.SecretId,
SecretKey: config.SecretKey,
})
@@ -65,15 +57,20 @@ func NewWithLogger(config *TencentCloudSSLDeployDeployerConfig, logger logger.Lo
return nil, xerrors.Wrap(err, "failed to create ssl uploader")
}
- return &TencentCloudSSLDeployDeployer{
- logger: logger,
+ return &DeployerProvider{
config: config,
+ logger: logger.NewNilLogger(),
sdkClient: client,
sslUploader: uploader,
}, nil
}
-func (d *TencentCloudSSLDeployDeployer) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) {
+func (d *DeployerProvider) WithLogger(logger logger.Logger) *DeployerProvider {
+ d.logger = logger
+ return d
+}
+
+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")
}
diff --git a/internal/pkg/core/deployer/providers/tencentcloud-vod/tencentcloud_vod.go b/internal/pkg/core/deployer/providers/tencentcloud-vod/tencentcloud_vod.go
new file mode 100644
index 00000000..fbce8d6f
--- /dev/null
+++ b/internal/pkg/core/deployer/providers/tencentcloud-vod/tencentcloud_vod.go
@@ -0,0 +1,104 @@
+package tencentcloudvod
+
+import (
+ "context"
+
+ 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"
+
+ "github.com/usual2970/certimate/internal/pkg/core/deployer"
+ "github.com/usual2970/certimate/internal/pkg/core/logger"
+ "github.com/usual2970/certimate/internal/pkg/core/uploader"
+ uploadersp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/tencentcloud-ssl"
+)
+
+type DeployerConfig struct {
+ // 腾讯云 SecretId。
+ SecretId string `json:"secretId"`
+ // 腾讯云 SecretKey。
+ SecretKey string `json:"secretKey"`
+ // 点播应用 ID。
+ SubAppId int64 `json:"subAppId"`
+ // 点播加速域名(不支持泛域名)。
+ Domain string `json:"domain"`
+}
+
+type DeployerProvider struct {
+ config *DeployerConfig
+ logger logger.Logger
+ sdkClient *tcVod.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.SecretId, config.SecretKey)
+ if err != nil {
+ return nil, xerrors.Wrap(err, "failed to create sdk clients")
+ }
+
+ uploader, err := uploadersp.NewUploader(&uploadersp.UploaderConfig{
+ SecretId: config.SecretId,
+ SecretKey: config.SecretKey,
+ })
+ if err != nil {
+ return nil, xerrors.Wrap(err, "failed to create ssl uploader")
+ }
+
+ return &DeployerProvider{
+ config: config,
+ logger: logger.NewNilLogger(),
+ sdkClient: client,
+ sslUploader: uploader,
+ }, nil
+}
+
+func (d *DeployerProvider) WithLogger(logger logger.Logger) *DeployerProvider {
+ d.logger = logger
+ return d
+}
+
+func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) {
+ // 上传证书到 SSL
+ upres, err := d.sslUploader.Upload(ctx, certPem, privkeyPem)
+ if err != nil {
+ return nil, xerrors.Wrap(err, "failed to upload certificate file")
+ } else {
+ d.logger.Logt("certificate file uploaded", upres)
+ }
+
+ // 设置点播域名 HTTPS 证书
+ // REF: https://cloud.tencent.com/document/api/266/102015
+ setVodDomainCertificateReq := tcVod.NewSetVodDomainCertificateRequest()
+ setVodDomainCertificateReq.Domain = common.StringPtr(d.config.Domain)
+ setVodDomainCertificateReq.Operation = common.StringPtr("Set")
+ setVodDomainCertificateReq.CertID = common.StringPtr(upres.CertId)
+ if d.config.SubAppId != 0 {
+ setVodDomainCertificateReq.SubAppId = common.Uint64Ptr(uint64(d.config.SubAppId))
+ }
+ setVodDomainCertificateResp, err := d.sdkClient.SetVodDomainCertificate(setVodDomainCertificateReq)
+ if err != nil {
+ return nil, xerrors.Wrap(err, "failed to execute sdk request 'vod.SetVodDomainCertificate'")
+ } else {
+ d.logger.Logt("已设置点播域名 HTTPS 证书", setVodDomainCertificateResp.Response)
+ }
+
+ return &deployer.DeployResult{}, nil
+}
+
+func createSdkClient(secretId, secretKey string) (*tcVod.Client, error) {
+ credential := common.NewCredential(secretId, secretKey)
+ client, err := tcVod.NewClient(credential, "", profile.NewClientProfile())
+ if err != nil {
+ return nil, err
+ }
+
+ return client, 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
new file mode 100644
index 00000000..60871a31
--- /dev/null
+++ b/internal/pkg/core/deployer/providers/tencentcloud-vod/tencentcloud_vod_test.go
@@ -0,0 +1,87 @@
+package tencentcloudvod_test
+
+import (
+ "context"
+ "flag"
+ "fmt"
+ "os"
+ "strings"
+ "testing"
+
+ provider "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/tencentcloud-vod"
+)
+
+var (
+ fInputCertPath string
+ fInputKeyPath string
+ fSecretId string
+ fSecretKey string
+ fRegion string
+ fDomain string
+ fSubAppId int64
+ fInstanceId string
+)
+
+func init() {
+ argsPrefix := "CERTIMATE_DEPLOYER_TENCENTCLOUDVOD_"
+
+ flag.StringVar(&fInputCertPath, argsPrefix+"INPUTCERTPATH", "", "")
+ flag.StringVar(&fInputKeyPath, argsPrefix+"INPUTKEYPATH", "", "")
+ flag.StringVar(&fSecretId, argsPrefix+"SECRETID", "", "")
+ flag.StringVar(&fSecretKey, argsPrefix+"SECRETKEY", "", "")
+ flag.StringVar(&fRegion, argsPrefix+"REGION", "", "")
+ flag.StringVar(&fDomain, argsPrefix+"DOMAIN", "", "")
+ flag.Int64Var(&fSubAppId, argsPrefix+"SUBAPPID", 0, "")
+ flag.StringVar(&fInstanceId, argsPrefix+"INSTANCEID", "", "")
+}
+
+/*
+Shell command to run this test:
+
+ go test -v ./tencentcloud_vod_test.go -args \
+ --CERTIMATE_DEPLOYER_TENCENTCLOUDVOD_INPUTCERTPATH="/path/to/your-input-cert.pem" \
+ --CERTIMATE_DEPLOYER_TENCENTCLOUDVOD_INPUTKEYPATH="/path/to/your-input-key.pem" \
+ --CERTIMATE_DEPLOYER_TENCENTCLOUDVOD_SECRETID="your-secret-id" \
+ --CERTIMATE_DEPLOYER_TENCENTCLOUDVOD_SECRETKEY="your-secret-key" \
+ --CERTIMATE_DEPLOYER_TENCENTCLOUDVOD_REGION="ap-guangzhou" \
+ --CERTIMATE_DEPLOYER_TENCENTCLOUDVOD_SUBAPPID="your-app-id" \
+ --CERTIMATE_DEPLOYER_TENCENTCLOUDVOD_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("SECRETID: %v", fSecretId),
+ fmt.Sprintf("SECRETKEY: %v", fSecretKey),
+ fmt.Sprintf("REGION: %v", fRegion),
+ fmt.Sprintf("DOMAIN: %v", fDomain),
+ fmt.Sprintf("INSTANCEID: %v", fInstanceId),
+ }, "\n"))
+
+ deployer, err := provider.NewDeployer(&provider.DeployerConfig{
+ SecretId: fSecretId,
+ SecretKey: fSecretKey,
+ Region: fRegion,
+ SubAppId: fSubAppId,
+ 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/tencentcloud-waf/tencentcloud_waf.go b/internal/pkg/core/deployer/providers/tencentcloud-waf/tencentcloud_waf.go
new file mode 100644
index 00000000..7919516c
--- /dev/null
+++ b/internal/pkg/core/deployer/providers/tencentcloud-waf/tencentcloud_waf.go
@@ -0,0 +1,131 @@
+package tencentcloudwaf
+
+import (
+ "context"
+ "errors"
+
+ 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"
+
+ "github.com/usual2970/certimate/internal/pkg/core/deployer"
+ "github.com/usual2970/certimate/internal/pkg/core/logger"
+ "github.com/usual2970/certimate/internal/pkg/core/uploader"
+ uploadersp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/tencentcloud-ssl"
+)
+
+type DeployerConfig struct {
+ // 腾讯云 SecretId。
+ SecretId string `json:"secretId"`
+ // 腾讯云 SecretKey。
+ SecretKey string `json:"secretKey"`
+ // 腾讯云地域。
+ Region string `json:"region"`
+ // 防护域名(不支持泛域名)。
+ Domain string `json:"domain"`
+ // 防护域名 ID。
+ DomainId string `json:"domainId"`
+ // 防护域名所属实例 ID。
+ InstanceId string `json:"instanceId"`
+}
+
+type DeployerProvider struct {
+ config *DeployerConfig
+ logger logger.Logger
+ sdkClient *tcWaf.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.SecretId, config.SecretKey, config.Region)
+ if err != nil {
+ return nil, xerrors.Wrap(err, "failed to create sdk clients")
+ }
+
+ uploader, err := uploadersp.NewUploader(&uploadersp.UploaderConfig{
+ SecretId: config.SecretId,
+ SecretKey: config.SecretKey,
+ })
+ if err != nil {
+ return nil, xerrors.Wrap(err, "failed to create ssl uploader")
+ }
+
+ return &DeployerProvider{
+ config: config,
+ logger: logger.NewNilLogger(),
+ sdkClient: client,
+ sslUploader: uploader,
+ }, nil
+}
+
+func (d *DeployerProvider) WithLogger(logger logger.Logger) *DeployerProvider {
+ d.logger = 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")
+ }
+ if d.config.DomainId == "" {
+ return nil, errors.New("config `domainId` is required")
+ }
+ if d.config.InstanceId == "" {
+ return nil, errors.New("config `instanceId` is required")
+ }
+
+ // 上传证书到 SSL
+ upres, err := d.sslUploader.Upload(ctx, certPem, privkeyPem)
+ if err != nil {
+ return nil, xerrors.Wrap(err, "failed to upload certificate file")
+ } else {
+ d.logger.Logt("certificate file uploaded", upres)
+ }
+
+ // 查询单个 SaaS 型 WAF 域名详情
+ // REF: https://cloud.tencent.com/document/api/627/82938
+ describeDomainDetailsSaasReq := tcWaf.NewDescribeDomainDetailsSaasRequest()
+ describeDomainDetailsSaasReq.Domain = common.StringPtr(d.config.Domain)
+ describeDomainDetailsSaasReq.DomainId = common.StringPtr(d.config.DomainId)
+ describeDomainDetailsSaasReq.InstanceId = common.StringPtr(d.config.InstanceId)
+ describeDomainDetailsSaasResp, err := d.sdkClient.DescribeDomainDetailsSaas(describeDomainDetailsSaasReq)
+ if err != nil {
+ return nil, xerrors.Wrap(err, "failed to execute sdk request 'waf.DescribeDomainDetailsSaas'")
+ } else {
+ d.logger.Logt("已查询到 SaaS 型 WAF 域名详情", describeDomainDetailsSaasResp.Response)
+ }
+
+ // 编辑 SaaS 型 WAF 域名
+ // REF: https://cloud.tencent.com/document/api/627/94309
+ modifySpartaProtectionReq := tcWaf.NewModifySpartaProtectionRequest()
+ modifySpartaProtectionReq.Domain = common.StringPtr(d.config.Domain)
+ modifySpartaProtectionReq.DomainId = common.StringPtr(d.config.DomainId)
+ modifySpartaProtectionReq.InstanceID = common.StringPtr(d.config.InstanceId)
+ modifySpartaProtectionReq.CertType = common.Int64Ptr(2)
+ modifySpartaProtectionReq.SSLId = common.StringPtr(upres.CertId)
+ modifySpartaProtectionResp, err := d.sdkClient.ModifySpartaProtection(modifySpartaProtectionReq)
+ if err != nil {
+ return nil, xerrors.Wrap(err, "failed to execute sdk request 'waf.ModifySpartaProtection'")
+ } else {
+ d.logger.Logt("已编辑 SaaS 型 WAF 域名", modifySpartaProtectionResp.Response)
+ }
+
+ return &deployer.DeployResult{}, nil
+}
+
+func createSdkClient(secretId, secretKey, region string) (*tcWaf.Client, error) {
+ credential := common.NewCredential(secretId, secretKey)
+ client, err := tcWaf.NewClient(credential, region, profile.NewClientProfile())
+ if err != nil {
+ return nil, err
+ }
+
+ return client, 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
new file mode 100644
index 00000000..42ba1ffe
--- /dev/null
+++ b/internal/pkg/core/deployer/providers/tencentcloud-waf/tencentcloud_waf_test.go
@@ -0,0 +1,89 @@
+package tencentcloudwaf_test
+
+import (
+ "context"
+ "flag"
+ "fmt"
+ "os"
+ "strings"
+ "testing"
+
+ provider "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/tencentcloud-waf"
+)
+
+var (
+ fInputCertPath string
+ fInputKeyPath string
+ fSecretId string
+ fSecretKey string
+ fRegion string
+ fDomain string
+ fDomainId string
+ fInstanceId string
+)
+
+func init() {
+ argsPrefix := "CERTIMATE_DEPLOYER_TENCENTCLOUDWAF_"
+
+ flag.StringVar(&fInputCertPath, argsPrefix+"INPUTCERTPATH", "", "")
+ flag.StringVar(&fInputKeyPath, argsPrefix+"INPUTKEYPATH", "", "")
+ flag.StringVar(&fSecretId, argsPrefix+"SECRETID", "", "")
+ flag.StringVar(&fSecretKey, argsPrefix+"SECRETKEY", "", "")
+ flag.StringVar(&fRegion, argsPrefix+"REGION", "", "")
+ flag.StringVar(&fDomain, argsPrefix+"DOMAIN", "", "")
+ flag.StringVar(&fDomainId, argsPrefix+"DOMAINID", "", "")
+ flag.StringVar(&fInstanceId, argsPrefix+"INSTANCEID", "", "")
+}
+
+/*
+Shell command to run this test:
+
+ go test -v ./tencentcloud_waf_test.go -args \
+ --CERTIMATE_DEPLOYER_TENCENTCLOUDWAF_INPUTCERTPATH="/path/to/your-input-cert.pem" \
+ --CERTIMATE_DEPLOYER_TENCENTCLOUDWAF_INPUTKEYPATH="/path/to/your-input-key.pem" \
+ --CERTIMATE_DEPLOYER_TENCENTCLOUDWAF_SECRETID="your-secret-id" \
+ --CERTIMATE_DEPLOYER_TENCENTCLOUDWAF_SECRETKEY="your-secret-key" \
+ --CERTIMATE_DEPLOYER_TENCENTCLOUDWAF_REGION="ap-guangzhou" \
+ --CERTIMATE_DEPLOYER_TENCENTCLOUDWAF_DOMAIN="example.com" \
+ --CERTIMATE_DEPLOYER_TENCENTCLOUDWAF_DOMAINID="your-domain-id" \
+ --CERTIMATE_DEPLOYER_TENCENTCLOUDWAF_INSTANCEID="your-instance-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("SECRETID: %v", fSecretId),
+ fmt.Sprintf("SECRETKEY: %v", fSecretKey),
+ fmt.Sprintf("REGION: %v", fRegion),
+ fmt.Sprintf("DOMAIN: %v", fDomain),
+ fmt.Sprintf("INSTANCEID: %v", fInstanceId),
+ }, "\n"))
+
+ deployer, err := provider.NewDeployer(&provider.DeployerConfig{
+ SecretId: fSecretId,
+ SecretKey: fSecretKey,
+ Region: fRegion,
+ Domain: fDomain,
+ DomainId: fDomainId,
+ InstanceId: fInstanceId,
+ })
+ 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/ucloud-ucdn/ucloud_ucdn.go b/internal/pkg/core/deployer/providers/ucloud-ucdn/ucloud_ucdn.go
index fa104ba3..8c19621b 100644
--- a/internal/pkg/core/deployer/providers/ucloud-ucdn/ucloud_ucdn.go
+++ b/internal/pkg/core/deployer/providers/ucloud-ucdn/ucloud_ucdn.go
@@ -13,10 +13,10 @@ import (
"github.com/usual2970/certimate/internal/pkg/core/deployer"
"github.com/usual2970/certimate/internal/pkg/core/logger"
"github.com/usual2970/certimate/internal/pkg/core/uploader"
- uploaderp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/ucloud-ussl"
+ uploadersp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/ucloud-ussl"
)
-type UCloudUCDNDeployerConfig struct {
+type DeployerConfig struct {
// 优刻得 API 私钥。
PrivateKey string `json:"privateKey"`
// 优刻得 API 公钥。
@@ -27,26 +27,18 @@ type UCloudUCDNDeployerConfig struct {
DomainId string `json:"domainId"`
}
-type UCloudUCDNDeployer struct {
- config *UCloudUCDNDeployerConfig
+type DeployerProvider struct {
+ config *DeployerConfig
logger logger.Logger
sdkClient *uCdn.UCDNClient
sslUploader uploader.Uploader
}
-var _ deployer.Deployer = (*UCloudUCDNDeployer)(nil)
+var _ deployer.Deployer = (*DeployerProvider)(nil)
-func New(config *UCloudUCDNDeployerConfig) (*UCloudUCDNDeployer, error) {
- return NewWithLogger(config, logger.NewNilLogger())
-}
-
-func NewWithLogger(config *UCloudUCDNDeployerConfig, logger logger.Logger) (*UCloudUCDNDeployer, error) {
+func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) {
if config == nil {
- return nil, errors.New("config is nil")
- }
-
- if logger == nil {
- return nil, errors.New("logger is nil")
+ panic("config is nil")
}
client, err := createSdkClient(config.PrivateKey, config.PublicKey)
@@ -54,7 +46,7 @@ func NewWithLogger(config *UCloudUCDNDeployerConfig, logger logger.Logger) (*UCl
return nil, xerrors.Wrap(err, "failed to create sdk client")
}
- uploader, err := uploaderp.New(&uploaderp.UCloudUSSLUploaderConfig{
+ uploader, err := uploadersp.NewUploader(&uploadersp.UploaderConfig{
PrivateKey: config.PrivateKey,
PublicKey: config.PublicKey,
ProjectId: config.ProjectId,
@@ -63,15 +55,20 @@ func NewWithLogger(config *UCloudUCDNDeployerConfig, logger logger.Logger) (*UCl
return nil, xerrors.Wrap(err, "failed to create ssl uploader")
}
- return &UCloudUCDNDeployer{
- logger: logger,
+ return &DeployerProvider{
config: config,
+ logger: logger.NewNilLogger(),
sdkClient: client,
sslUploader: uploader,
}, nil
}
-func (d *UCloudUCDNDeployer) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) {
+func (d *DeployerProvider) WithLogger(logger logger.Logger) *DeployerProvider {
+ d.logger = logger
+ return d
+}
+
+func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) {
// 上传证书到 USSL
upres, err := d.sslUploader.Upload(ctx, certPem, privkeyPem)
if err != 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 d8b703b5..fc952da1 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
@@ -52,7 +52,7 @@ func TestDeploy(t *testing.T) {
fmt.Sprintf("DOMAIN: %v", fDomainId),
}, "\n"))
- deployer, err := provider.New(&provider.UCloudUCDNDeployerConfig{
+ deployer, err := provider.NewDeployer(&provider.DeployerConfig{
PrivateKey: fPrivateKey,
PublicKey: fPublicKey,
DomainId: fDomainId,
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 ccf03224..592a1cf6 100644
--- a/internal/pkg/core/deployer/providers/ucloud-us3/ucloud_us3.go
+++ b/internal/pkg/core/deployer/providers/ucloud-us3/ucloud_us3.go
@@ -2,7 +2,6 @@
import (
"context"
- "errors"
xerrors "github.com/pkg/errors"
usdk "github.com/ucloud/ucloud-sdk-go/ucloud"
@@ -11,11 +10,11 @@ import (
"github.com/usual2970/certimate/internal/pkg/core/deployer"
"github.com/usual2970/certimate/internal/pkg/core/logger"
"github.com/usual2970/certimate/internal/pkg/core/uploader"
- uploaderp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/ucloud-ussl"
+ uploadersp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/ucloud-ussl"
usdkFile "github.com/usual2970/certimate/internal/pkg/vendors/ucloud-sdk/ufile"
)
-type UCloudUS3DeployerConfig struct {
+type DeployerConfig struct {
// 优刻得 API 私钥。
PrivateKey string `json:"privateKey"`
// 优刻得 API 公钥。
@@ -30,26 +29,18 @@ type UCloudUS3DeployerConfig struct {
Domain string `json:"domain"`
}
-type UCloudUS3Deployer struct {
- config *UCloudUS3DeployerConfig
+type DeployerProvider struct {
+ config *DeployerConfig
logger logger.Logger
sdkClient *usdkFile.UFileClient
sslUploader uploader.Uploader
}
-var _ deployer.Deployer = (*UCloudUS3Deployer)(nil)
+var _ deployer.Deployer = (*DeployerProvider)(nil)
-func New(config *UCloudUS3DeployerConfig) (*UCloudUS3Deployer, error) {
- return NewWithLogger(config, logger.NewNilLogger())
-}
-
-func NewWithLogger(config *UCloudUS3DeployerConfig, logger logger.Logger) (*UCloudUS3Deployer, error) {
+func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) {
if config == nil {
- return nil, errors.New("config is nil")
- }
-
- if logger == nil {
- return nil, errors.New("logger is nil")
+ panic("config is nil")
}
client, err := createSdkClient(config.PrivateKey, config.PublicKey, config.Region)
@@ -57,7 +48,7 @@ func NewWithLogger(config *UCloudUS3DeployerConfig, logger logger.Logger) (*UClo
return nil, xerrors.Wrap(err, "failed to create sdk client")
}
- uploader, err := uploaderp.New(&uploaderp.UCloudUSSLUploaderConfig{
+ uploader, err := uploadersp.NewUploader(&uploadersp.UploaderConfig{
PrivateKey: config.PrivateKey,
PublicKey: config.PublicKey,
ProjectId: config.ProjectId,
@@ -66,15 +57,20 @@ func NewWithLogger(config *UCloudUS3DeployerConfig, logger logger.Logger) (*UClo
return nil, xerrors.Wrap(err, "failed to create ssl uploader")
}
- return &UCloudUS3Deployer{
- logger: logger,
+ return &DeployerProvider{
config: config,
+ logger: logger.NewNilLogger(),
sdkClient: client,
sslUploader: uploader,
}, nil
}
-func (d *UCloudUS3Deployer) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) {
+func (d *DeployerProvider) WithLogger(logger logger.Logger) *DeployerProvider {
+ d.logger = logger
+ return d
+}
+
+func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) {
// 上传证书到 USSL
upres, err := d.sslUploader.Upload(ctx, certPem, privkeyPem)
if err != 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 e4175bfc..52f78664 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
@@ -60,7 +60,7 @@ func TestDeploy(t *testing.T) {
fmt.Sprintf("DOMAIN: %v", fDomain),
}, "\n"))
- deployer, err := provider.New(&provider.UCloudUS3DeployerConfig{
+ deployer, err := provider.NewDeployer(&provider.DeployerConfig{
PrivateKey: fPrivateKey,
PublicKey: fPublicKey,
Region: fRegion,
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 de3e76e4..229c3c01 100644
--- a/internal/pkg/core/deployer/providers/volcengine-cdn/volcengine_cdn.go
+++ b/internal/pkg/core/deployer/providers/volcengine-cdn/volcengine_cdn.go
@@ -12,10 +12,10 @@ import (
"github.com/usual2970/certimate/internal/pkg/core/deployer"
"github.com/usual2970/certimate/internal/pkg/core/logger"
"github.com/usual2970/certimate/internal/pkg/core/uploader"
- uploaderp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/volcengine-cdn"
+ uploadersp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/volcengine-cdn"
)
-type VolcEngineCDNDeployerConfig struct {
+type DeployerConfig struct {
// 火山引擎 AccessKeyId。
AccessKeyId string `json:"accessKeyId"`
// 火山引擎 AccessKeySecret。
@@ -24,33 +24,25 @@ type VolcEngineCDNDeployerConfig struct {
Domain string `json:"domain"`
}
-type VolcEngineCDNDeployer struct {
- config *VolcEngineCDNDeployerConfig
+type DeployerProvider struct {
+ config *DeployerConfig
logger logger.Logger
sdkClient *veCdn.CDN
sslUploader uploader.Uploader
}
-var _ deployer.Deployer = (*VolcEngineCDNDeployer)(nil)
+var _ deployer.Deployer = (*DeployerProvider)(nil)
-func New(config *VolcEngineCDNDeployerConfig) (*VolcEngineCDNDeployer, error) {
- return NewWithLogger(config, logger.NewNilLogger())
-}
-
-func NewWithLogger(config *VolcEngineCDNDeployerConfig, logger logger.Logger) (*VolcEngineCDNDeployer, error) {
+func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) {
if config == nil {
- return nil, errors.New("config is nil")
- }
-
- if logger == nil {
- return nil, errors.New("logger is nil")
+ panic("config is nil")
}
client := veCdn.NewInstance()
client.Client.SetAccessKey(config.AccessKeyId)
client.Client.SetSecretKey(config.AccessKeySecret)
- uploader, err := uploaderp.New(&uploaderp.VolcEngineCDNUploaderConfig{
+ uploader, err := uploadersp.NewUploader(&uploadersp.UploaderConfig{
AccessKeyId: config.AccessKeyId,
AccessKeySecret: config.AccessKeySecret,
})
@@ -58,15 +50,20 @@ func NewWithLogger(config *VolcEngineCDNDeployerConfig, logger logger.Logger) (*
return nil, xerrors.Wrap(err, "failed to create ssl uploader")
}
- return &VolcEngineCDNDeployer{
- logger: logger,
+ return &DeployerProvider{
config: config,
+ logger: logger.NewNilLogger(),
sdkClient: client,
sslUploader: uploader,
}, nil
}
-func (d *VolcEngineCDNDeployer) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) {
+func (d *DeployerProvider) WithLogger(logger logger.Logger) *DeployerProvider {
+ d.logger = logger
+ return d
+}
+
+func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) {
// 上传证书到 CDN
upres, err := d.sslUploader.Upload(ctx, certPem, privkeyPem)
if err != nil {
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 3a3ff62d..c94b9828 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
@@ -52,7 +52,7 @@ func TestDeploy(t *testing.T) {
fmt.Sprintf("DOMAIN: %v", fDomain),
}, "\n"))
- deployer, err := provider.New(&provider.VolcEngineCDNDeployerConfig{
+ deployer, err := provider.NewDeployer(&provider.DeployerConfig{
AccessKeyId: fAccessKeyId,
AccessKeySecret: fAccessKeySecret,
Domain: fDomain,
diff --git a/internal/pkg/core/deployer/providers/volcengine-clb/consts.go b/internal/pkg/core/deployer/providers/volcengine-clb/consts.go
new file mode 100644
index 00000000..dc1e992b
--- /dev/null
+++ b/internal/pkg/core/deployer/providers/volcengine-clb/consts.go
@@ -0,0 +1,8 @@
+package volcengineclb
+
+type ResourceType string
+
+const (
+ // 资源类型:部署到指定监听器。
+ RESOURCE_TYPE_LISTENER = ResourceType("listener")
+)
diff --git a/internal/pkg/core/deployer/providers/volcengine-clb/defines.go b/internal/pkg/core/deployer/providers/volcengine-clb/defines.go
deleted file mode 100644
index ec211199..00000000
--- a/internal/pkg/core/deployer/providers/volcengine-clb/defines.go
+++ /dev/null
@@ -1,8 +0,0 @@
-package volcengineclb
-
-type DeployResourceType string
-
-const (
- // 资源类型:部署到指定监听器。
- DEPLOY_RESOURCE_LISTENER = DeployResourceType("listener")
-)
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 08c096fd..73372781 100644
--- a/internal/pkg/core/deployer/providers/volcengine-clb/volcengine_clb.go
+++ b/internal/pkg/core/deployer/providers/volcengine-clb/volcengine_clb.go
@@ -13,10 +13,10 @@ import (
"github.com/usual2970/certimate/internal/pkg/core/deployer"
"github.com/usual2970/certimate/internal/pkg/core/logger"
"github.com/usual2970/certimate/internal/pkg/core/uploader"
- uploaderp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/volcengine-certcenter"
+ uploadersp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/volcengine-certcenter"
)
-type VolcEngineCLBDeployerConfig struct {
+type DeployerConfig struct {
// 火山引擎 AccessKeyId。
AccessKeyId string `json:"accessKeyId"`
// 火山引擎 AccessKeySecret。
@@ -24,32 +24,24 @@ type VolcEngineCLBDeployerConfig struct {
// 火山引擎地域。
Region string `json:"region"`
// 部署资源类型。
- ResourceType DeployResourceType `json:"resourceType"`
+ ResourceType ResourceType `json:"resourceType"`
// 负载均衡监听器 ID。
- // 部署资源类型为 [DEPLOY_RESOURCE_LISTENER] 时必填。
+ // 部署资源类型为 [RESOURCE_TYPE_LISTENER] 时必填。
ListenerId string `json:"listenerId,omitempty"`
}
-type VolcEngineCLBDeployer struct {
- config *VolcEngineCLBDeployerConfig
+type DeployerProvider struct {
+ config *DeployerConfig
logger logger.Logger
sdkClient *veClb.CLB
sslUploader uploader.Uploader
}
-var _ deployer.Deployer = (*VolcEngineCLBDeployer)(nil)
+var _ deployer.Deployer = (*DeployerProvider)(nil)
-func New(config *VolcEngineCLBDeployerConfig) (*VolcEngineCLBDeployer, error) {
- return NewWithLogger(config, logger.NewNilLogger())
-}
-
-func NewWithLogger(config *VolcEngineCLBDeployerConfig, logger logger.Logger) (*VolcEngineCLBDeployer, error) {
+func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) {
if config == nil {
- return nil, errors.New("config is nil")
- }
-
- if logger == nil {
- return nil, errors.New("logger is nil")
+ panic("config is nil")
}
client, err := createSdkClient(config.AccessKeyId, config.AccessKeySecret, config.Region)
@@ -57,7 +49,7 @@ func NewWithLogger(config *VolcEngineCLBDeployerConfig, logger logger.Logger) (*
return nil, xerrors.Wrap(err, "failed to create sdk client")
}
- uploader, err := uploaderp.New(&uploaderp.VolcEngineCertCenterUploaderConfig{
+ uploader, err := uploadersp.NewUploader(&uploadersp.UploaderConfig{
AccessKeyId: config.AccessKeyId,
AccessKeySecret: config.AccessKeySecret,
Region: config.Region,
@@ -66,15 +58,19 @@ func NewWithLogger(config *VolcEngineCLBDeployerConfig, logger logger.Logger) (*
return nil, xerrors.Wrap(err, "failed to create ssl uploader")
}
- return &VolcEngineCLBDeployer{
- logger: logger,
+ return &DeployerProvider{
config: config,
sdkClient: client,
sslUploader: uploader,
}, nil
}
-func (d *VolcEngineCLBDeployer) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) {
+func (d *DeployerProvider) WithLogger(logger logger.Logger) *DeployerProvider {
+ d.logger = logger
+ return d
+}
+
+func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) {
// 上传证书到证书中心
upres, err := d.sslUploader.Upload(ctx, certPem, privkeyPem)
if err != nil {
@@ -85,7 +81,7 @@ func (d *VolcEngineCLBDeployer) Deploy(ctx context.Context, certPem string, priv
// 根据部署资源类型决定部署方式
switch d.config.ResourceType {
- case DEPLOY_RESOURCE_LISTENER:
+ case RESOURCE_TYPE_LISTENER:
if err := d.deployToListener(ctx, upres.CertId); err != nil {
return nil, err
}
@@ -97,7 +93,7 @@ func (d *VolcEngineCLBDeployer) Deploy(ctx context.Context, certPem string, priv
return &deployer.DeployResult{}, nil
}
-func (d *VolcEngineCLBDeployer) deployToListener(ctx context.Context, cloudCertId string) error {
+func (d *DeployerProvider) deployToListener(ctx context.Context, cloudCertId string) error {
if d.config.ListenerId == "" {
return errors.New("config `listenerId` is required")
}
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 45d79f44..0b589f88 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
@@ -56,11 +56,11 @@ func TestDeploy(t *testing.T) {
fmt.Sprintf("LISTENERID: %v", fListenerId),
}, "\n"))
- deployer, err := provider.New(&provider.VolcEngineCLBDeployerConfig{
+ deployer, err := provider.NewDeployer(&provider.DeployerConfig{
AccessKeyId: fAccessKeyId,
AccessKeySecret: fAccessKeySecret,
Region: fRegion,
- ResourceType: provider.DEPLOY_RESOURCE_LISTENER,
+ ResourceType: provider.RESOURCE_TYPE_LISTENER,
ListenerId: fListenerId,
})
if err != nil {
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 0f9f8e51..835eae4b 100644
--- a/internal/pkg/core/deployer/providers/volcengine-dcdn/volcengine_dcdn.go
+++ b/internal/pkg/core/deployer/providers/volcengine-dcdn/volcengine_dcdn.go
@@ -2,7 +2,6 @@
import (
"context"
- "errors"
"strings"
xerrors "github.com/pkg/errors"
@@ -13,10 +12,10 @@ import (
"github.com/usual2970/certimate/internal/pkg/core/deployer"
"github.com/usual2970/certimate/internal/pkg/core/logger"
"github.com/usual2970/certimate/internal/pkg/core/uploader"
- uploaderp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/volcengine-certcenter"
+ uploadersp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/volcengine-certcenter"
)
-type VolcEngineDCDNDeployerConfig struct {
+type DeployerConfig struct {
// 火山引擎 AccessKeyId。
AccessKeyId string `json:"accessKeyId"`
// 火山引擎 AccessKeySecret。
@@ -27,26 +26,18 @@ type VolcEngineDCDNDeployerConfig struct {
Domain string `json:"domain"`
}
-type VolcEngineDCDNDeployer struct {
- config *VolcEngineDCDNDeployerConfig
+type DeployerProvider struct {
+ config *DeployerConfig
logger logger.Logger
sdkClient *veDcdn.DCDN
sslUploader uploader.Uploader
}
-var _ deployer.Deployer = (*VolcEngineDCDNDeployer)(nil)
+var _ deployer.Deployer = (*DeployerProvider)(nil)
-func New(config *VolcEngineDCDNDeployerConfig) (*VolcEngineDCDNDeployer, error) {
- return NewWithLogger(config, logger.NewNilLogger())
-}
-
-func NewWithLogger(config *VolcEngineDCDNDeployerConfig, logger logger.Logger) (*VolcEngineDCDNDeployer, error) {
+func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) {
if config == nil {
- return nil, errors.New("config is nil")
- }
-
- if logger == nil {
- return nil, errors.New("logger is nil")
+ panic("config is nil")
}
client, err := createSdkClient(config.AccessKeyId, config.AccessKeySecret, config.Region)
@@ -54,7 +45,7 @@ func NewWithLogger(config *VolcEngineDCDNDeployerConfig, logger logger.Logger) (
return nil, xerrors.Wrap(err, "failed to create sdk client")
}
- uploader, err := uploaderp.New(&uploaderp.VolcEngineCertCenterUploaderConfig{
+ uploader, err := uploadersp.NewUploader(&uploadersp.UploaderConfig{
AccessKeyId: config.AccessKeyId,
AccessKeySecret: config.AccessKeySecret,
Region: config.Region,
@@ -63,15 +54,20 @@ func NewWithLogger(config *VolcEngineDCDNDeployerConfig, logger logger.Logger) (
return nil, xerrors.Wrap(err, "failed to create ssl uploader")
}
- return &VolcEngineDCDNDeployer{
- logger: logger,
+ return &DeployerProvider{
config: config,
+ logger: logger.NewNilLogger(),
sdkClient: client,
sslUploader: uploader,
}, nil
}
-func (d *VolcEngineDCDNDeployer) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) {
+func (d *DeployerProvider) WithLogger(logger logger.Logger) *DeployerProvider {
+ d.logger = logger
+ return d
+}
+
+func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) {
// 上传证书到证书中心
upres, err := d.sslUploader.Upload(ctx, certPem, privkeyPem)
if err != 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 2236b1e1..1d34a295 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
@@ -52,7 +52,7 @@ func TestDeploy(t *testing.T) {
fmt.Sprintf("DOMAIN: %v", fDomain),
}, "\n"))
- deployer, err := provider.New(&provider.VolcEngineDCDNDeployerConfig{
+ deployer, err := provider.NewDeployer(&provider.DeployerConfig{
AccessKeyId: fAccessKeyId,
AccessKeySecret: fAccessKeySecret,
Domain: fDomain,
diff --git a/internal/pkg/core/deployer/providers/volcengine-imagex/volcengine_imagex.go b/internal/pkg/core/deployer/providers/volcengine-imagex/volcengine_imagex.go
new file mode 100644
index 00000000..57d133ec
--- /dev/null
+++ b/internal/pkg/core/deployer/providers/volcengine-imagex/volcengine_imagex.go
@@ -0,0 +1,144 @@
+package volcengineimagex
+
+import (
+ "context"
+ "errors"
+
+ xerrors "github.com/pkg/errors"
+ veBase "github.com/volcengine/volc-sdk-golang/base"
+ veImageX "github.com/volcengine/volc-sdk-golang/service/imagex/v2"
+
+ "github.com/usual2970/certimate/internal/pkg/core/deployer"
+ "github.com/usual2970/certimate/internal/pkg/core/logger"
+ "github.com/usual2970/certimate/internal/pkg/core/uploader"
+ uploadersp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/volcengine-certcenter"
+)
+
+type DeployerConfig struct {
+ // 火山引擎 AccessKeyId。
+ AccessKeyId string `json:"accessKeyId"`
+ // 火山引擎 AccessKeySecret。
+ AccessKeySecret string `json:"accessKeySecret"`
+ // 火山引擎地域。
+ Region string `json:"region"`
+ // 服务 ID。
+ ServiceId string `json:"serviceId"`
+ // 自定义域名(不支持泛域名)。
+ Domain string `json:"domain"`
+}
+
+type DeployerProvider struct {
+ config *DeployerConfig
+ logger logger.Logger
+ sdkClient *veImageX.Imagex
+ 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, xerrors.Wrap(err, "failed to create sdk client")
+ }
+
+ uploader, err := uploadersp.NewUploader(&uploadersp.UploaderConfig{
+ AccessKeyId: config.AccessKeyId,
+ AccessKeySecret: config.AccessKeySecret,
+ Region: config.Region,
+ })
+ if err != nil {
+ return nil, xerrors.Wrap(err, "failed to create ssl uploader")
+ }
+
+ return &DeployerProvider{
+ config: config,
+ logger: logger.NewNilLogger(),
+ sdkClient: client,
+ sslUploader: uploader,
+ }, nil
+}
+
+func (d *DeployerProvider) WithLogger(logger logger.Logger) *DeployerProvider {
+ d.logger = logger
+ return d
+}
+
+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")
+ }
+ if d.config.Domain == "" {
+ return nil, errors.New("config `domain` is required")
+ }
+
+ // 上传证书到证书中心
+ upres, err := d.sslUploader.Upload(ctx, certPem, privkeyPem)
+ if err != nil {
+ return nil, xerrors.Wrap(err, "failed to upload certificate file")
+ } else {
+ d.logger.Logt("certificate file uploaded", upres)
+ }
+
+ // 获取域名配置
+ // REF: https://www.volcengine.com/docs/508/9366
+ getDomainConfigReq := &veImageX.GetDomainConfigQuery{
+ ServiceID: d.config.ServiceId,
+ DomainName: d.config.Domain,
+ }
+ getDomainConfigResp, err := d.sdkClient.GetDomainConfig(context.TODO(), getDomainConfigReq)
+ if err != nil {
+ return nil, xerrors.Wrap(err, "failed to execute sdk request 'imagex.GetDomainConfig'")
+ } else {
+ d.logger.Logt("已获取域名配置", getDomainConfigResp)
+ }
+
+ // 更新 HTTPS 配置
+ // REF: https://www.volcengine.com/docs/508/66012
+ updateHttpsReq := &veImageX.UpdateHTTPSReq{
+ UpdateHTTPSQuery: &veImageX.UpdateHTTPSQuery{
+ ServiceID: d.config.ServiceId,
+ },
+ UpdateHTTPSBody: &veImageX.UpdateHTTPSBody{
+ Domain: getDomainConfigResp.Result.Domain,
+ HTTPS: &veImageX.UpdateHTTPSBodyHTTPS{
+ CertID: upres.CertId,
+ EnableHTTP2: getDomainConfigResp.Result.HTTPSConfig.EnableHTTP2,
+ EnableHTTPS: getDomainConfigResp.Result.HTTPSConfig.EnableHTTPS,
+ EnableOcsp: getDomainConfigResp.Result.HTTPSConfig.EnableOcsp,
+ TLSVersions: getDomainConfigResp.Result.HTTPSConfig.TLSVersions,
+ EnableForceRedirect: getDomainConfigResp.Result.HTTPSConfig.EnableForceRedirect,
+ ForceRedirectType: getDomainConfigResp.Result.HTTPSConfig.ForceRedirectType,
+ ForceRedirectCode: getDomainConfigResp.Result.HTTPSConfig.ForceRedirectCode,
+ },
+ },
+ }
+ updateHttpsResp, err := d.sdkClient.UpdateHTTPS(context.TODO(), updateHttpsReq)
+ if err != nil {
+ return nil, xerrors.Wrap(err, "failed to execute sdk request 'imagex.UpdateHttps'")
+ } else {
+ d.logger.Logt("已更新 HTTPS 配置", updateHttpsResp)
+ }
+
+ return &deployer.DeployResult{}, nil
+}
+
+func createSdkClient(accessKeyId, accessKeySecret, region string) (*veImageX.Imagex, error) {
+ var instance *veImageX.Imagex
+ if region == "" {
+ instance = veImageX.NewInstance()
+ } else {
+ instance = veImageX.NewInstanceWithRegion(region)
+ }
+
+ instance.SetCredential(veBase.Credentials{
+ AccessKeyID: accessKeyId,
+ SecretAccessKey: accessKeySecret,
+ })
+
+ return instance, 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
new file mode 100644
index 00000000..f2acb8f2
--- /dev/null
+++ b/internal/pkg/core/deployer/providers/volcengine-imagex/volcengine_imagex_test.go
@@ -0,0 +1,85 @@
+package volcengineimagex_test
+
+import (
+ "context"
+ "flag"
+ "fmt"
+ "os"
+ "strings"
+ "testing"
+
+ provider "github.com/usual2970/certimate/internal/pkg/core/deployer/providers/volcengine-imagex"
+)
+
+var (
+ fInputCertPath string
+ fInputKeyPath string
+ fAccessKeyId string
+ fAccessKeySecret string
+ fRegion string
+ fServiceId string
+ fDomain string
+)
+
+func init() {
+ argsPrefix := "CERTIMATE_DEPLOYER_VOLCENGINEIMAGEX_"
+
+ 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(&fServiceId, argsPrefix+"SERVICEID", "", "")
+ flag.StringVar(&fDomain, argsPrefix+"DOMAIN", "", "")
+}
+
+/*
+Shell command to run this test:
+
+ go test -v ./volcengine_imagex_test.go -args \
+ --CERTIMATE_DEPLOYER_VOLCENGINEIMAGEX_INPUTCERTPATH="/path/to/your-input-cert.pem" \
+ --CERTIMATE_DEPLOYER_VOLCENGINEIMAGEX_INPUTKEYPATH="/path/to/your-input-key.pem" \
+ --CERTIMATE_DEPLOYER_VOLCENGINEIMAGEX_ACCESSKEYID="your-access-key-id" \
+ --CERTIMATE_DEPLOYER_VOLCENGINEIMAGEX_ACCESSKEYSECRET="your-access-key-secret" \
+ --CERTIMATE_DEPLOYER_VOLCENGINEIMAGEX_REGION="cn-north-1" \
+ --CERTIMATE_DEPLOYER_VOLCENGINEIMAGEX_SERVICEID="your-service-id" \
+ --CERTIMATE_DEPLOYER_VOLCENGINEIMAGEX_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("SERVICEID: %v", fServiceId),
+ fmt.Sprintf("DOMAIN: %v", fDomain),
+ }, "\n"))
+
+ deployer, err := provider.NewDeployer(&provider.DeployerConfig{
+ AccessKeyId: fAccessKeyId,
+ AccessKeySecret: fAccessKeySecret,
+ Region: fRegion,
+ ServiceId: fServiceId,
+ 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/volcengine-live/volcengine_live.go b/internal/pkg/core/deployer/providers/volcengine-live/volcengine_live.go
index b23f4c6c..240e5c9c 100644
--- a/internal/pkg/core/deployer/providers/volcengine-live/volcengine_live.go
+++ b/internal/pkg/core/deployer/providers/volcengine-live/volcengine_live.go
@@ -13,10 +13,10 @@ import (
"github.com/usual2970/certimate/internal/pkg/core/deployer"
"github.com/usual2970/certimate/internal/pkg/core/logger"
"github.com/usual2970/certimate/internal/pkg/core/uploader"
- uploaderp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/volcengine-live"
+ uploadersp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/volcengine-live"
)
-type VolcEngineLiveDeployerConfig struct {
+type DeployerConfig struct {
// 火山引擎 AccessKeyId。
AccessKeyId string `json:"accessKeyId"`
// 火山引擎 AccessKeySecret。
@@ -25,33 +25,25 @@ type VolcEngineLiveDeployerConfig struct {
Domain string `json:"domain"`
}
-type VolcEngineLiveDeployer struct {
- config *VolcEngineLiveDeployerConfig
+type DeployerProvider struct {
+ config *DeployerConfig
logger logger.Logger
sdkClient *veLive.Live
sslUploader uploader.Uploader
}
-var _ deployer.Deployer = (*VolcEngineLiveDeployer)(nil)
+var _ deployer.Deployer = (*DeployerProvider)(nil)
-func New(config *VolcEngineLiveDeployerConfig) (*VolcEngineLiveDeployer, error) {
- return NewWithLogger(config, logger.NewNilLogger())
-}
-
-func NewWithLogger(config *VolcEngineLiveDeployerConfig, logger logger.Logger) (*VolcEngineLiveDeployer, error) {
+func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) {
if config == nil {
- return nil, errors.New("config is nil")
- }
-
- if logger == nil {
- return nil, errors.New("logger is nil")
+ panic("config is nil")
}
client := veLive.NewInstance()
client.SetAccessKey(config.AccessKeyId)
client.SetSecretKey(config.AccessKeySecret)
- uploader, err := uploaderp.New(&uploaderp.VolcEngineLiveUploaderConfig{
+ uploader, err := uploadersp.NewUploader(&uploadersp.UploaderConfig{
AccessKeyId: config.AccessKeyId,
AccessKeySecret: config.AccessKeySecret,
})
@@ -59,15 +51,20 @@ func NewWithLogger(config *VolcEngineLiveDeployerConfig, logger logger.Logger) (
return nil, xerrors.Wrap(err, "failed to create ssl uploader")
}
- return &VolcEngineLiveDeployer{
- logger: logger,
+ return &DeployerProvider{
config: config,
+ logger: logger.NewNilLogger(),
sdkClient: client,
sslUploader: uploader,
}, nil
}
-func (d *VolcEngineLiveDeployer) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) {
+func (d *DeployerProvider) WithLogger(logger logger.Logger) *DeployerProvider {
+ d.logger = logger
+ return d
+}
+
+func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) {
// 上传证书到 Live
upres, err := d.sslUploader.Upload(ctx, certPem, privkeyPem)
if err != nil {
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 28097c75..2222e7b9 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
@@ -52,7 +52,7 @@ func TestDeploy(t *testing.T) {
fmt.Sprintf("DOMAIN: %v", fDomain),
}, "\n"))
- deployer, err := provider.New(&provider.VolcEngineLiveDeployerConfig{
+ deployer, err := provider.NewDeployer(&provider.DeployerConfig{
AccessKeyId: fAccessKeyId,
AccessKeySecret: fAccessKeySecret,
Domain: fDomain,
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 9a238f27..142a8b9f 100644
--- a/internal/pkg/core/deployer/providers/volcengine-tos/volcengine_tos.go
+++ b/internal/pkg/core/deployer/providers/volcengine-tos/volcengine_tos.go
@@ -11,10 +11,10 @@ import (
"github.com/usual2970/certimate/internal/pkg/core/deployer"
"github.com/usual2970/certimate/internal/pkg/core/logger"
"github.com/usual2970/certimate/internal/pkg/core/uploader"
- uploaderp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/volcengine-certcenter"
+ uploadersp "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/volcengine-certcenter"
)
-type VolcEngineTOSDeployerConfig struct {
+type DeployerConfig struct {
// 火山引擎 AccessKeyId。
AccessKeyId string `json:"accessKeyId"`
// 火山引擎 AccessKeySecret。
@@ -27,26 +27,18 @@ type VolcEngineTOSDeployerConfig struct {
Domain string `json:"domain"`
}
-type VolcEngineTOSDeployer struct {
- config *VolcEngineTOSDeployerConfig
+type DeployerProvider struct {
+ config *DeployerConfig
logger logger.Logger
sdkClient *veTos.ClientV2
sslUploader uploader.Uploader
}
-var _ deployer.Deployer = (*VolcEngineTOSDeployer)(nil)
+var _ deployer.Deployer = (*DeployerProvider)(nil)
-func New(config *VolcEngineTOSDeployerConfig) (*VolcEngineTOSDeployer, error) {
- return NewWithLogger(config, logger.NewNilLogger())
-}
-
-func NewWithLogger(config *VolcEngineTOSDeployerConfig, logger logger.Logger) (*VolcEngineTOSDeployer, error) {
+func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) {
if config == nil {
- return nil, errors.New("config is nil")
- }
-
- if logger == nil {
- return nil, errors.New("logger is nil")
+ panic("config is nil")
}
client, err := createSdkClient(config.AccessKeyId, config.AccessKeySecret, config.Region)
@@ -54,7 +46,7 @@ func NewWithLogger(config *VolcEngineTOSDeployerConfig, logger logger.Logger) (*
return nil, xerrors.Wrap(err, "failed to create sdk client")
}
- uploader, err := uploaderp.New(&uploaderp.VolcEngineCertCenterUploaderConfig{
+ uploader, err := uploadersp.NewUploader(&uploadersp.UploaderConfig{
AccessKeyId: config.AccessKeyId,
AccessKeySecret: config.AccessKeySecret,
Region: config.Region,
@@ -63,15 +55,20 @@ func NewWithLogger(config *VolcEngineTOSDeployerConfig, logger logger.Logger) (*
return nil, xerrors.Wrap(err, "failed to create ssl uploader")
}
- return &VolcEngineTOSDeployer{
- logger: logger,
+ return &DeployerProvider{
config: config,
+ logger: logger.NewNilLogger(),
sdkClient: client,
sslUploader: uploader,
}, nil
}
-func (d *VolcEngineTOSDeployer) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) {
+func (d *DeployerProvider) WithLogger(logger logger.Logger) *DeployerProvider {
+ d.logger = logger
+ return d
+}
+
+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")
}
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 b70130c4..0c9b398a 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
@@ -60,9 +60,11 @@ func TestDeploy(t *testing.T) {
fmt.Sprintf("DOMAIN: %v", fDomain),
}, "\n"))
- deployer, err := provider.New(&provider.VolcEngineTOSDeployerConfig{
+ deployer, err := provider.NewDeployer(&provider.DeployerConfig{
AccessKeyId: fAccessKeyId,
AccessKeySecret: fAccessKeySecret,
+ Region: fRegion,
+ Bucket: fBucket,
Domain: fDomain,
})
if err != nil {
diff --git a/internal/pkg/core/deployer/providers/webhook/webhook.go b/internal/pkg/core/deployer/providers/webhook/webhook.go
index 694befc5..7a9edfda 100644
--- a/internal/pkg/core/deployer/providers/webhook/webhook.go
+++ b/internal/pkg/core/deployer/providers/webhook/webhook.go
@@ -3,7 +3,6 @@ package webhook
import (
"context"
"encoding/json"
- "errors"
"strings"
"time"
@@ -15,32 +14,24 @@ import (
"github.com/usual2970/certimate/internal/pkg/utils/certs"
)
-type WebhookDeployerConfig struct {
+type DeployerConfig struct {
// Webhook URL。
WebhookUrl string `json:"webhookUrl"`
// Webhook 回调数据(JSON 格式)。
WebhookData string `json:"webhookData,omitempty"`
}
-type WebhookDeployer struct {
- config *WebhookDeployerConfig
+type DeployerProvider struct {
+ config *DeployerConfig
logger logger.Logger
httpClient *resty.Client
}
-var _ deployer.Deployer = (*WebhookDeployer)(nil)
+var _ deployer.Deployer = (*DeployerProvider)(nil)
-func New(config *WebhookDeployerConfig) (*WebhookDeployer, error) {
- return NewWithLogger(config, logger.NewNilLogger())
-}
-
-func NewWithLogger(config *WebhookDeployerConfig, logger logger.Logger) (*WebhookDeployer, error) {
+func NewDeployer(config *DeployerConfig) (*DeployerProvider, error) {
if config == nil {
- return nil, errors.New("config is nil")
- }
-
- if logger == nil {
- return nil, errors.New("logger is nil")
+ panic("config is nil")
}
client := resty.New().
@@ -48,14 +39,19 @@ func NewWithLogger(config *WebhookDeployerConfig, logger logger.Logger) (*Webhoo
SetRetryCount(3).
SetRetryWaitTime(5 * time.Second)
- return &WebhookDeployer{
+ return &DeployerProvider{
config: config,
- logger: logger,
+ logger: logger.NewNilLogger(),
httpClient: client,
}, nil
}
-func (d *WebhookDeployer) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) {
+func (d *DeployerProvider) WithLogger(logger logger.Logger) *DeployerProvider {
+ d.logger = logger
+ return d
+}
+
+func (d *DeployerProvider) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) {
certX509, err := certs.ParseCertificateFromPEM(certPem)
if err != nil {
return nil, xerrors.Wrap(err, "failed to parse x509")
diff --git a/internal/pkg/core/deployer/providers/webhook/webhook_test.go b/internal/pkg/core/deployer/providers/webhook/webhook_test.go
index 92b57e56..7dd6f24a 100644
--- a/internal/pkg/core/deployer/providers/webhook/webhook_test.go
+++ b/internal/pkg/core/deployer/providers/webhook/webhook_test.go
@@ -48,7 +48,7 @@ func TestDeploy(t *testing.T) {
fmt.Sprintf("WEBHOOKDATA: %v", fWebhookData),
}, "\n"))
- deployer, err := provider.New(&provider.WebhookDeployerConfig{
+ deployer, err := provider.NewDeployer(&provider.DeployerConfig{
WebhookUrl: fWebhookUrl,
WebhookData: fWebhookData,
})
diff --git a/internal/pkg/core/logger/builtin.go b/internal/pkg/core/logger/builtin.go
index 9787817d..fa8932dc 100644
--- a/internal/pkg/core/logger/builtin.go
+++ b/internal/pkg/core/logger/builtin.go
@@ -35,8 +35,8 @@ func (l *DefaultLogger) Logt(tag string, data ...any) {
reflect.Float32, reflect.Float64:
s = fmt.Sprintf("%v", v)
default:
- jsonData, _ := json.Marshal(v)
- s = string(jsonData)
+ jbytes, _ := json.Marshal(v)
+ s = string(jbytes)
}
}
diff --git a/internal/pkg/core/notifier/providers/bark/bark.go b/internal/pkg/core/notifier/providers/bark/bark.go
index 74683f82..f9589096 100644
--- a/internal/pkg/core/notifier/providers/bark/bark.go
+++ b/internal/pkg/core/notifier/providers/bark/bark.go
@@ -2,7 +2,6 @@
import (
"context"
- "errors"
"github.com/nikoksr/notify"
"github.com/nikoksr/notify/service/bark"
@@ -10,7 +9,7 @@ import (
"github.com/usual2970/certimate/internal/pkg/core/notifier"
)
-type BarkNotifierConfig struct {
+type NotifierConfig struct {
// Bark 服务地址。
// 零值时默认使用官方服务器。
ServerUrl string `json:"serverUrl"`
@@ -18,23 +17,23 @@ type BarkNotifierConfig struct {
DeviceKey string `json:"deviceKey"`
}
-type BarkNotifier struct {
- config *BarkNotifierConfig
+type NotifierProvider struct {
+ config *NotifierConfig
}
-var _ notifier.Notifier = (*BarkNotifier)(nil)
+var _ notifier.Notifier = (*NotifierProvider)(nil)
-func New(config *BarkNotifierConfig) (*BarkNotifier, error) {
+func NewNotifier(config *NotifierConfig) (*NotifierProvider, error) {
if config == nil {
- return nil, errors.New("config is nil")
+ panic("config is nil")
}
- return &BarkNotifier{
+ return &NotifierProvider{
config: config,
}, nil
}
-func (n *BarkNotifier) Notify(ctx context.Context, subject string, message string) (res *notifier.NotifyResult, err error) {
+func (n *NotifierProvider) Notify(ctx context.Context, subject string, message string) (res *notifier.NotifyResult, err error) {
var srv notify.Notifier
if n.config.ServerUrl == "" {
srv = bark.New(n.config.DeviceKey)
diff --git a/internal/pkg/core/notifier/providers/bark/bark_test.go b/internal/pkg/core/notifier/providers/bark/bark_test.go
index e3045cae..bd0441b4 100644
--- a/internal/pkg/core/notifier/providers/bark/bark_test.go
+++ b/internal/pkg/core/notifier/providers/bark/bark_test.go
@@ -44,7 +44,7 @@ func TestNotify(t *testing.T) {
fmt.Sprintf("DEVICEKEY: %v", fDeviceKey),
}, "\n"))
- notifier, err := provider.New(&provider.BarkNotifierConfig{
+ notifier, err := provider.NewNotifier(&provider.NotifierConfig{
ServerUrl: fServerUrl,
DeviceKey: fDeviceKey,
})
diff --git a/internal/pkg/core/notifier/providers/dingtalk/dingtalk.go b/internal/pkg/core/notifier/providers/dingtalk/dingtalk.go
index 52fe5f27..f8eba8a7 100644
--- a/internal/pkg/core/notifier/providers/dingtalk/dingtalk.go
+++ b/internal/pkg/core/notifier/providers/dingtalk/dingtalk.go
@@ -2,37 +2,36 @@
import (
"context"
- "errors"
"github.com/nikoksr/notify/service/dingding"
"github.com/usual2970/certimate/internal/pkg/core/notifier"
)
-type DingTalkNotifierConfig struct {
+type NotifierConfig struct {
// 钉钉机器人的 Token。
AccessToken string `json:"accessToken"`
// 钉钉机器人的 Secret。
Secret string `json:"secret"`
}
-type DingTalkNotifier struct {
- config *DingTalkNotifierConfig
+type NotifierProvider struct {
+ config *NotifierConfig
}
-var _ notifier.Notifier = (*DingTalkNotifier)(nil)
+var _ notifier.Notifier = (*NotifierProvider)(nil)
-func New(config *DingTalkNotifierConfig) (*DingTalkNotifier, error) {
+func NewNotifier(config *NotifierConfig) (*NotifierProvider, error) {
if config == nil {
- return nil, errors.New("config is nil")
+ panic("config is nil")
}
- return &DingTalkNotifier{
+ return &NotifierProvider{
config: config,
}, nil
}
-func (n *DingTalkNotifier) Notify(ctx context.Context, subject string, message string) (res *notifier.NotifyResult, err error) {
+func (n *NotifierProvider) Notify(ctx context.Context, subject string, message string) (res *notifier.NotifyResult, err error) {
srv := dingding.New(&dingding.Config{
Token: n.config.AccessToken,
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 621a57ca..836cf498 100644
--- a/internal/pkg/core/notifier/providers/dingtalk/dingtalk_test.go
+++ b/internal/pkg/core/notifier/providers/dingtalk/dingtalk_test.go
@@ -43,7 +43,7 @@ func TestNotify(t *testing.T) {
fmt.Sprintf("SECRET: %v", fSecret),
}, "\n"))
- notifier, err := provider.New(&provider.DingTalkNotifierConfig{
+ notifier, err := provider.NewNotifier(&provider.NotifierConfig{
AccessToken: fAccessToken,
Secret: fSecret,
})
diff --git a/internal/pkg/core/notifier/providers/email/email.go b/internal/pkg/core/notifier/providers/email/email.go
index 127c5528..4a69d50a 100644
--- a/internal/pkg/core/notifier/providers/email/email.go
+++ b/internal/pkg/core/notifier/providers/email/email.go
@@ -3,7 +3,6 @@
import (
"context"
"crypto/tls"
- "errors"
"fmt"
"net/smtp"
@@ -12,7 +11,7 @@ import (
"github.com/usual2970/certimate/internal/pkg/core/notifier"
)
-type EmailNotifierConfig struct {
+type NotifierConfig struct {
// SMTP 服务器地址。
SmtpHost string `json:"smtpHost"`
// SMTP 服务器端口。
@@ -30,23 +29,23 @@ type EmailNotifierConfig struct {
ReceiverAddress string `json:"receiverAddress"`
}
-type EmailNotifier struct {
- config *EmailNotifierConfig
+type NotifierProvider struct {
+ config *NotifierConfig
}
-var _ notifier.Notifier = (*EmailNotifier)(nil)
+var _ notifier.Notifier = (*NotifierProvider)(nil)
-func New(config *EmailNotifierConfig) (*EmailNotifier, error) {
+func NewNotifier(config *NotifierConfig) (*NotifierProvider, error) {
if config == nil {
- return nil, errors.New("config is nil")
+ panic("config is nil")
}
- return &EmailNotifier{
+ return &NotifierProvider{
config: config,
}, nil
}
-func (n *EmailNotifier) Notify(ctx context.Context, subject string, message string) (res *notifier.NotifyResult, err error) {
+func (n *NotifierProvider) Notify(ctx context.Context, subject string, message string) (res *notifier.NotifyResult, err error) {
var smtpAuth smtp.Auth
if n.config.Username != "" || n.config.Password != "" {
smtpAuth = smtp.PlainAuth("", n.config.Username, n.config.Password, n.config.SmtpHost)
diff --git a/internal/pkg/core/notifier/providers/email/email_test.go b/internal/pkg/core/notifier/providers/email/email_test.go
index 1c52d4de..df006c24 100644
--- a/internal/pkg/core/notifier/providers/email/email_test.go
+++ b/internal/pkg/core/notifier/providers/email/email_test.go
@@ -64,7 +64,7 @@ func TestNotify(t *testing.T) {
fmt.Sprintf("RECEIVERADDRESS: %v", fReceiverAddress),
}, "\n"))
- notifier, err := provider.New(&provider.EmailNotifierConfig{
+ notifier, err := provider.NewNotifier(&provider.NotifierConfig{
SmtpHost: fSmtpHost,
SmtpPort: int32(fSmtpPort),
SmtpTLS: fSmtpTLS,
diff --git a/internal/pkg/core/notifier/providers/lark/lark.go b/internal/pkg/core/notifier/providers/lark/lark.go
index 4714e280..9c92691a 100644
--- a/internal/pkg/core/notifier/providers/lark/lark.go
+++ b/internal/pkg/core/notifier/providers/lark/lark.go
@@ -2,35 +2,34 @@
import (
"context"
- "errors"
"github.com/nikoksr/notify/service/lark"
"github.com/usual2970/certimate/internal/pkg/core/notifier"
)
-type LarkNotifierConfig struct {
+type NotifierConfig struct {
// 飞书机器人 Webhook 地址。
WebhookUrl string `json:"webhookUrl"`
}
-type LarkNotifier struct {
- config *LarkNotifierConfig
+type NotifierProvider struct {
+ config *NotifierConfig
}
-var _ notifier.Notifier = (*LarkNotifier)(nil)
+var _ notifier.Notifier = (*NotifierProvider)(nil)
-func New(config *LarkNotifierConfig) (*LarkNotifier, error) {
+func NewNotifier(config *NotifierConfig) (*NotifierProvider, error) {
if config == nil {
- return nil, errors.New("config is nil")
+ panic("config is nil")
}
- return &LarkNotifier{
+ return &NotifierProvider{
config: config,
}, nil
}
-func (n *LarkNotifier) Notify(ctx context.Context, subject string, message string) (res *notifier.NotifyResult, err error) {
+func (n *NotifierProvider) Notify(ctx context.Context, subject string, message string) (res *notifier.NotifyResult, err error) {
srv := lark.NewWebhookService(n.config.WebhookUrl)
err = srv.Send(ctx, subject, message)
diff --git a/internal/pkg/core/notifier/providers/lark/lark_test.go b/internal/pkg/core/notifier/providers/lark/lark_test.go
index 0b91ebd7..2b04a7a6 100644
--- a/internal/pkg/core/notifier/providers/lark/lark_test.go
+++ b/internal/pkg/core/notifier/providers/lark/lark_test.go
@@ -38,7 +38,7 @@ func TestNotify(t *testing.T) {
fmt.Sprintf("WEBHOOKURL: %v", fWebhookUrl),
}, "\n"))
- notifier, err := provider.New(&provider.LarkNotifierConfig{
+ notifier, err := provider.NewNotifier(&provider.NotifierConfig{
WebhookUrl: fWebhookUrl,
})
if err != nil {
diff --git a/internal/pkg/core/notifier/providers/serverchan/serverchan.go b/internal/pkg/core/notifier/providers/serverchan/serverchan.go
index 7b5a6de0..51df0893 100644
--- a/internal/pkg/core/notifier/providers/serverchan/serverchan.go
+++ b/internal/pkg/core/notifier/providers/serverchan/serverchan.go
@@ -2,7 +2,6 @@
import (
"context"
- "errors"
"net/http"
notifyHttp "github.com/nikoksr/notify/service/http"
@@ -10,28 +9,28 @@ import (
"github.com/usual2970/certimate/internal/pkg/core/notifier"
)
-type ServerChanNotifierConfig struct {
+type NotifierConfig struct {
// ServerChan 服务地址。
Url string `json:"url"`
}
-type ServerChanNotifier struct {
- config *ServerChanNotifierConfig
+type NotifierProvider struct {
+ config *NotifierConfig
}
-var _ notifier.Notifier = (*ServerChanNotifier)(nil)
+var _ notifier.Notifier = (*NotifierProvider)(nil)
-func New(config *ServerChanNotifierConfig) (*ServerChanNotifier, error) {
+func NewNotifier(config *NotifierConfig) (*NotifierProvider, error) {
if config == nil {
- return nil, errors.New("config is nil")
+ panic("config is nil")
}
- return &ServerChanNotifier{
+ return &NotifierProvider{
config: config,
}, nil
}
-func (n *ServerChanNotifier) Notify(ctx context.Context, subject string, message string) (res *notifier.NotifyResult, err error) {
+func (n *NotifierProvider) Notify(ctx context.Context, subject string, message string) (res *notifier.NotifyResult, err error) {
srv := notifyHttp.New()
srv.AddReceivers(¬ifyHttp.Webhook{
diff --git a/internal/pkg/core/notifier/providers/serverchan/serverchan_test.go b/internal/pkg/core/notifier/providers/serverchan/serverchan_test.go
index db2a4946..6f9c61a3 100644
--- a/internal/pkg/core/notifier/providers/serverchan/serverchan_test.go
+++ b/internal/pkg/core/notifier/providers/serverchan/serverchan_test.go
@@ -38,7 +38,7 @@ func TestNotify(t *testing.T) {
fmt.Sprintf("URL: %v", fUrl),
}, "\n"))
- notifier, err := provider.New(&provider.ServerChanNotifierConfig{
+ notifier, err := provider.NewNotifier(&provider.NotifierConfig{
Url: fUrl,
})
if err != nil {
diff --git a/internal/pkg/core/notifier/providers/telegram/telegram.go b/internal/pkg/core/notifier/providers/telegram/telegram.go
index d1dcc45f..6a1889b3 100644
--- a/internal/pkg/core/notifier/providers/telegram/telegram.go
+++ b/internal/pkg/core/notifier/providers/telegram/telegram.go
@@ -2,37 +2,36 @@
import (
"context"
- "errors"
"github.com/nikoksr/notify/service/telegram"
"github.com/usual2970/certimate/internal/pkg/core/notifier"
)
-type TelegramNotifierConfig struct {
+type NotifierConfig struct {
// Telegram API Token。
ApiToken string `json:"apiToken"`
// Telegram Chat ID。
ChatId int64 `json:"chatId"`
}
-type TelegramNotifier struct {
- config *TelegramNotifierConfig
+type NotifierProvider struct {
+ config *NotifierConfig
}
-var _ notifier.Notifier = (*TelegramNotifier)(nil)
+var _ notifier.Notifier = (*NotifierProvider)(nil)
-func New(config *TelegramNotifierConfig) (*TelegramNotifier, error) {
+func NewNotifier(config *NotifierConfig) (*NotifierProvider, error) {
if config == nil {
- return nil, errors.New("config is nil")
+ panic("config is nil")
}
- return &TelegramNotifier{
+ return &NotifierProvider{
config: config,
}, nil
}
-func (n *TelegramNotifier) Notify(ctx context.Context, subject string, message string) (res *notifier.NotifyResult, err error) {
+func (n *NotifierProvider) Notify(ctx context.Context, subject string, message string) (res *notifier.NotifyResult, err error) {
srv, err := telegram.New(n.config.ApiToken)
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 fca71e8a..10e93547 100644
--- a/internal/pkg/core/notifier/providers/telegram/telegram_test.go
+++ b/internal/pkg/core/notifier/providers/telegram/telegram_test.go
@@ -44,7 +44,7 @@ func TestNotify(t *testing.T) {
fmt.Sprintf("CHATID: %v", fChartId),
}, "\n"))
- notifier, err := provider.New(&provider.TelegramNotifierConfig{
+ notifier, err := provider.NewNotifier(&provider.NotifierConfig{
ApiToken: fApiToken,
ChatId: fChartId,
})
diff --git a/internal/pkg/core/notifier/providers/webhook/webhook.go b/internal/pkg/core/notifier/providers/webhook/webhook.go
index 3c2bc05f..55c0e668 100644
--- a/internal/pkg/core/notifier/providers/webhook/webhook.go
+++ b/internal/pkg/core/notifier/providers/webhook/webhook.go
@@ -2,35 +2,34 @@
import (
"context"
- "errors"
"github.com/nikoksr/notify/service/http"
"github.com/usual2970/certimate/internal/pkg/core/notifier"
)
-type WebhookNotifierConfig struct {
+type NotifierConfig struct {
// Webhook URL。
Url string `json:"url"`
}
-type WebhookNotifier struct {
- config *WebhookNotifierConfig
+type NotifierProvider struct {
+ config *NotifierConfig
}
-var _ notifier.Notifier = (*WebhookNotifier)(nil)
+var _ notifier.Notifier = (*NotifierProvider)(nil)
-func New(config *WebhookNotifierConfig) (*WebhookNotifier, error) {
+func NewNotifier(config *NotifierConfig) (*NotifierProvider, error) {
if config == nil {
- return nil, errors.New("config is nil")
+ panic("config is nil")
}
- return &WebhookNotifier{
+ return &NotifierProvider{
config: config,
}, nil
}
-func (n *WebhookNotifier) Notify(ctx context.Context, subject string, message string) (res *notifier.NotifyResult, err error) {
+func (n *NotifierProvider) Notify(ctx context.Context, subject string, message string) (res *notifier.NotifyResult, err error) {
srv := http.New()
srv.AddReceiversURLs(n.config.Url)
diff --git a/internal/pkg/core/notifier/providers/webhook/webhook_test.go b/internal/pkg/core/notifier/providers/webhook/webhook_test.go
index 14e2adf6..7afe6be4 100644
--- a/internal/pkg/core/notifier/providers/webhook/webhook_test.go
+++ b/internal/pkg/core/notifier/providers/webhook/webhook_test.go
@@ -38,7 +38,7 @@ func TestNotify(t *testing.T) {
fmt.Sprintf("URL: %v", fUrl),
}, "\n"))
- notifier, err := provider.New(&provider.WebhookNotifierConfig{
+ notifier, err := provider.NewNotifier(&provider.NotifierConfig{
Url: fUrl,
})
if err != nil {
diff --git a/internal/pkg/core/notifier/providers/wecom/wecom.go b/internal/pkg/core/notifier/providers/wecom/wecom.go
index 20938009..63342cb5 100644
--- a/internal/pkg/core/notifier/providers/wecom/wecom.go
+++ b/internal/pkg/core/notifier/providers/wecom/wecom.go
@@ -2,7 +2,6 @@
import (
"context"
- "errors"
"net/http"
notifyHttp "github.com/nikoksr/notify/service/http"
@@ -10,28 +9,28 @@ import (
"github.com/usual2970/certimate/internal/pkg/core/notifier"
)
-type WeComNotifierConfig struct {
+type NotifierConfig struct {
// 企业微信机器人 Webhook 地址。
WebhookUrl string `json:"webhookUrl"`
}
-type WeComNotifier struct {
- config *WeComNotifierConfig
+type NotifierProvider struct {
+ config *NotifierConfig
}
-var _ notifier.Notifier = (*WeComNotifier)(nil)
+var _ notifier.Notifier = (*NotifierProvider)(nil)
-func New(config *WeComNotifierConfig) (*WeComNotifier, error) {
+func NewNotifier(config *NotifierConfig) (*NotifierProvider, error) {
if config == nil {
- return nil, errors.New("config is nil")
+ panic("config is nil")
}
- return &WeComNotifier{
+ return &NotifierProvider{
config: config,
}, nil
}
-func (n *WeComNotifier) Notify(ctx context.Context, subject string, message string) (res *notifier.NotifyResult, err error) {
+func (n *NotifierProvider) Notify(ctx context.Context, subject string, message string) (res *notifier.NotifyResult, err error) {
srv := notifyHttp.New()
srv.AddReceivers(¬ifyHttp.Webhook{
diff --git a/internal/pkg/core/notifier/providers/wecom/wecom_test.go b/internal/pkg/core/notifier/providers/wecom/wecom_test.go
index e1378849..b823adea 100644
--- a/internal/pkg/core/notifier/providers/wecom/wecom_test.go
+++ b/internal/pkg/core/notifier/providers/wecom/wecom_test.go
@@ -38,7 +38,7 @@ func TestNotify(t *testing.T) {
fmt.Sprintf("WEBHOOKURL: %v", fWebhookUrl),
}, "\n"))
- notifier, err := provider.New(&provider.WeComNotifierConfig{
+ notifier, err := provider.NewNotifier(&provider.NotifierConfig{
WebhookUrl: fWebhookUrl,
})
if err != nil {
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 ac71202e..202339c4 100644
--- a/internal/pkg/core/uploader/providers/aliyun-cas/aliyun_cas.go
+++ b/internal/pkg/core/uploader/providers/aliyun-cas/aliyun_cas.go
@@ -2,7 +2,6 @@
import (
"context"
- "errors"
"fmt"
"strings"
"time"
@@ -16,7 +15,7 @@ import (
"github.com/usual2970/certimate/internal/pkg/utils/certs"
)
-type AliyunCASUploaderConfig struct {
+type UploaderConfig struct {
// 阿里云 AccessKeyId。
AccessKeyId string `json:"accessKeyId"`
// 阿里云 AccessKeySecret。
@@ -25,16 +24,16 @@ type AliyunCASUploaderConfig struct {
Region string `json:"region"`
}
-type AliyunCASUploader struct {
- config *AliyunCASUploaderConfig
+type UploaderProvider struct {
+ config *UploaderConfig
sdkClient *aliyunCas.Client
}
-var _ uploader.Uploader = (*AliyunCASUploader)(nil)
+var _ uploader.Uploader = (*UploaderProvider)(nil)
-func New(config *AliyunCASUploaderConfig) (*AliyunCASUploader, error) {
+func NewUploader(config *UploaderConfig) (*UploaderProvider, error) {
if config == nil {
- return nil, errors.New("config is nil")
+ panic("config is nil")
}
client, err := createSdkClient(
@@ -46,13 +45,13 @@ func New(config *AliyunCASUploaderConfig) (*AliyunCASUploader, error) {
return nil, xerrors.Wrap(err, "failed to create sdk client")
}
- return &AliyunCASUploader{
+ return &UploaderProvider{
config: config,
sdkClient: client,
}, nil
}
-func (u *AliyunCASUploader) 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 := certs.ParseCertificateFromPEM(certPem)
if err != nil {
@@ -112,7 +111,7 @@ func (u *AliyunCASUploader) Upload(ctx context.Context, certPem string, privkeyP
if listUserCertificateOrderResp.Body.CertificateOrderList == nil || len(listUserCertificateOrderResp.Body.CertificateOrderList) < int(listUserCertificateOrderLimit) {
break
} else {
- listUserCertificateOrderPage += 1
+ listUserCertificateOrderPage++
}
}
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 63779b48..c53eced2 100644
--- a/internal/pkg/core/uploader/providers/aliyun-slb/aliyun_slb.go
+++ b/internal/pkg/core/uploader/providers/aliyun-slb/aliyun_slb.go
@@ -4,7 +4,6 @@ import (
"context"
"crypto/sha256"
"encoding/hex"
- "errors"
"fmt"
"regexp"
"strings"
@@ -19,7 +18,7 @@ import (
"github.com/usual2970/certimate/internal/pkg/utils/certs"
)
-type AliyunSLBUploaderConfig struct {
+type UploaderConfig struct {
// 阿里云 AccessKeyId。
AccessKeyId string `json:"accessKeyId"`
// 阿里云 AccessKeySecret。
@@ -28,16 +27,16 @@ type AliyunSLBUploaderConfig struct {
Region string `json:"region"`
}
-type AliyunSLBUploader struct {
- config *AliyunSLBUploaderConfig
+type UploaderProvider struct {
+ config *UploaderConfig
sdkClient *aliyunSlb.Client
}
-var _ uploader.Uploader = (*AliyunSLBUploader)(nil)
+var _ uploader.Uploader = (*UploaderProvider)(nil)
-func New(config *AliyunSLBUploaderConfig) (*AliyunSLBUploader, error) {
+func NewUploader(config *UploaderConfig) (*UploaderProvider, error) {
if config == nil {
- return nil, errors.New("config is nil")
+ panic("config is nil")
}
client, err := createSdkClient(
@@ -49,13 +48,13 @@ func New(config *AliyunSLBUploaderConfig) (*AliyunSLBUploader, error) {
return nil, xerrors.Wrap(err, "failed to create sdk client")
}
- return &AliyunSLBUploader{
+ return &UploaderProvider{
config: config,
sdkClient: client,
}, nil
}
-func (u *AliyunSLBUploader) 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 := certs.ParseCertificateFromPEM(certPem)
if err != nil {
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 cac4d833..18ffd3aa 100644
--- a/internal/pkg/core/uploader/providers/aws-acm/aws_acm.go
+++ b/internal/pkg/core/uploader/providers/aws-acm/aws_acm.go
@@ -2,7 +2,6 @@
import (
"context"
- "errors"
"fmt"
"time"
@@ -16,7 +15,7 @@ import (
"github.com/usual2970/certimate/internal/pkg/utils/certs"
)
-type AWSCertificateManagerUploaderConfig struct {
+type UploaderConfig struct {
// AWS AccessKeyId。
AccessKeyId string `json:"accessKeyId"`
// AWS SecretAccessKey。
@@ -25,16 +24,16 @@ type AWSCertificateManagerUploaderConfig struct {
Region string `json:"region"`
}
-type AWSCertificateManagerUploader struct {
- config *AWSCertificateManagerUploaderConfig
+type UploaderProvider struct {
+ config *UploaderConfig
sdkClient *awsAcm.Client
}
-var _ uploader.Uploader = (*AWSCertificateManagerUploader)(nil)
+var _ uploader.Uploader = (*UploaderProvider)(nil)
-func New(config *AWSCertificateManagerUploaderConfig) (*AWSCertificateManagerUploader, error) {
+func NewUploader(config *UploaderConfig) (*UploaderProvider, error) {
if config == nil {
- return nil, errors.New("config is nil")
+ panic("config is nil")
}
client, err := createSdkClient(config.AccessKeyId, config.SecretAccessKey, config.Region)
@@ -42,13 +41,13 @@ func New(config *AWSCertificateManagerUploaderConfig) (*AWSCertificateManagerUpl
return nil, xerrors.Wrap(err, "failed to create sdk client")
}
- return &AWSCertificateManagerUploader{
+ return &UploaderProvider{
config: config,
sdkClient: client,
}, nil
}
-func (u *AWSCertificateManagerUploader) 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 := certs.ParseCertificateFromPEM(certPem)
if err != nil {
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 f1bf2b46..04116e31 100644
--- a/internal/pkg/core/uploader/providers/byteplus-cdn/byteplus_cdn.go
+++ b/internal/pkg/core/uploader/providers/byteplus-cdn/byteplus_cdn.go
@@ -5,7 +5,6 @@ import (
"crypto/sha1"
"crypto/sha256"
"encoding/hex"
- "errors"
"fmt"
"strings"
"time"
@@ -17,36 +16,36 @@ import (
"github.com/usual2970/certimate/internal/pkg/utils/certs"
)
-type ByteplusCDNUploaderConfig struct {
+type UploaderConfig struct {
// BytePlus AccessKey。
AccessKey string `json:"accessKey"`
// BytePlus SecretKey。
SecretKey string `json:"secretKey"`
}
-type ByteplusCDNUploader struct {
- config *ByteplusCDNUploaderConfig
+type UploaderProvider struct {
+ config *UploaderConfig
sdkClient *bpCdn.CDN
}
-var _ uploader.Uploader = (*ByteplusCDNUploader)(nil)
+var _ uploader.Uploader = (*UploaderProvider)(nil)
-func New(config *ByteplusCDNUploaderConfig) (*ByteplusCDNUploader, error) {
+func NewUploader(config *UploaderConfig) (*UploaderProvider, error) {
if config == nil {
- return nil, errors.New("config is nil")
+ panic("config is nil")
}
client := bpCdn.NewInstance()
client.Client.SetAccessKey(config.AccessKey)
client.Client.SetSecretKey(config.SecretKey)
- return &ByteplusCDNUploader{
+ return &UploaderProvider{
config: config,
sdkClient: client,
}, nil
}
-func (u *ByteplusCDNUploader) 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 := certs.ParseCertificateFromPEM(certPem)
if err != nil {
diff --git a/internal/pkg/core/uploader/providers/dogecloud/dogecloud.go b/internal/pkg/core/uploader/providers/dogecloud/dogecloud.go
index a38e832c..82856b6e 100644
--- a/internal/pkg/core/uploader/providers/dogecloud/dogecloud.go
+++ b/internal/pkg/core/uploader/providers/dogecloud/dogecloud.go
@@ -2,7 +2,6 @@
import (
"context"
- "errors"
"fmt"
"time"
@@ -12,23 +11,23 @@ import (
doge "github.com/usual2970/certimate/internal/pkg/vendors/dogecloud-sdk"
)
-type DogeCloudUploaderConfig struct {
+type UploaderConfig struct {
// 多吉云 AccessKey。
AccessKey string `json:"accessKey"`
// 多吉云 SecretKey。
SecretKey string `json:"secretKey"`
}
-type DogeCloudUploader struct {
- config *DogeCloudUploaderConfig
+type UploaderProvider struct {
+ config *UploaderConfig
sdkClient *doge.Client
}
-var _ uploader.Uploader = (*DogeCloudUploader)(nil)
+var _ uploader.Uploader = (*UploaderProvider)(nil)
-func New(config *DogeCloudUploaderConfig) (*DogeCloudUploader, error) {
+func NewUploader(config *UploaderConfig) (*UploaderProvider, error) {
if config == nil {
- return nil, errors.New("config is nil")
+ panic("config is nil")
}
client, err := createSdkClient(
@@ -39,13 +38,13 @@ func New(config *DogeCloudUploaderConfig) (*DogeCloudUploader, error) {
return nil, xerrors.Wrap(err, "failed to create sdk client")
}
- return &DogeCloudUploader{
+ return &UploaderProvider{
config: config,
sdkClient: client,
}, nil
}
-func (u *DogeCloudUploader) 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())
diff --git a/internal/pkg/core/uploader/providers/gcore-cdn/gcore_cdn.go b/internal/pkg/core/uploader/providers/gcore-cdn/gcore_cdn.go
new file mode 100644
index 00000000..b990c694
--- /dev/null
+++ b/internal/pkg/core/uploader/providers/gcore-cdn/gcore_cdn.go
@@ -0,0 +1,83 @@
+package gcorecdn
+
+import (
+ "context"
+ "errors"
+ "fmt"
+ "time"
+
+ 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"
+)
+
+type UploaderConfig struct {
+ // Gcore API Token。
+ ApiToken string `json:"apiToken"`
+}
+
+type UploaderProvider struct {
+ config *UploaderConfig
+ sdkClient *gsslcerts.Service
+}
+
+var _ uploader.Uploader = (*UploaderProvider)(nil)
+
+func NewUploader(config *UploaderConfig) (*UploaderProvider, error) {
+ if config == nil {
+ panic("config is nil")
+ }
+
+ client, err := createSdkClient(config.ApiToken)
+ if err != nil {
+ return nil, xerrors.Wrap(err, "failed to create sdk client")
+ }
+
+ return &UploaderProvider{
+ config: config,
+ sdkClient: client,
+ }, nil
+}
+
+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())
+
+ // 新增证书
+ // REF: https://api.gcore.com/docs/cdn#tag/CA-certificates/operation/ca_certificates-add
+ createCertificateReq := &gsslcerts.CreateRequest{
+ Name: certName,
+ Cert: certPem,
+ PrivateKey: privkeyPem,
+ Automated: false,
+ ValidateRootCA: false,
+ }
+ createCertificateResp, err := u.sdkClient.Create(context.TODO(), createCertificateReq)
+ if err != nil {
+ return nil, xerrors.Wrap(err, "failed to execute sdk request 'sslcerts.Create'")
+ }
+
+ certId = fmt.Sprintf("%d", createCertificateResp.ID)
+ certName = createCertificateResp.Name
+ return &uploader.UploadResult{
+ CertId: certId,
+ CertName: certName,
+ }, nil
+}
+
+func createSdkClient(apiToken string) (*gsslcerts.Service, error) {
+ if apiToken == "" {
+ return nil, errors.New("invalid gcore api token")
+ }
+
+ requester := gprovider.NewClient(
+ gcoresdk.BASE_URL,
+ gprovider.WithSigner(gcoresdk.NewAuthRequestSigner(apiToken)),
+ )
+ service := gsslcerts.NewService(requester)
+ return service, nil
+}
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 2ea7d031..96a1ff7b 100644
--- a/internal/pkg/core/uploader/providers/huaweicloud-elb/huaweicloud_elb.go
+++ b/internal/pkg/core/uploader/providers/huaweicloud-elb/huaweicloud_elb.go
@@ -21,7 +21,7 @@ import (
hwsdk "github.com/usual2970/certimate/internal/pkg/vendors/huaweicloud-sdk"
)
-type HuaweiCloudELBUploaderConfig struct {
+type UploaderConfig struct {
// 华为云 AccessKeyId。
AccessKeyId string `json:"accessKeyId"`
// 华为云 SecretAccessKey。
@@ -30,16 +30,16 @@ type HuaweiCloudELBUploaderConfig struct {
Region string `json:"region"`
}
-type HuaweiCloudELBUploader struct {
- config *HuaweiCloudELBUploaderConfig
+type UploaderProvider struct {
+ config *UploaderConfig
sdkClient *hcElb.ElbClient
}
-var _ uploader.Uploader = (*HuaweiCloudELBUploader)(nil)
+var _ uploader.Uploader = (*UploaderProvider)(nil)
-func New(config *HuaweiCloudELBUploaderConfig) (*HuaweiCloudELBUploader, error) {
+func NewUploader(config *UploaderConfig) (*UploaderProvider, error) {
if config == nil {
- return nil, errors.New("config is nil")
+ panic("config is nil")
}
client, err := createSdkClient(
@@ -51,13 +51,13 @@ func New(config *HuaweiCloudELBUploaderConfig) (*HuaweiCloudELBUploader, error)
return nil, xerrors.Wrap(err, "failed to create sdk client")
}
- return &HuaweiCloudELBUploader{
+ return &UploaderProvider{
config: config,
sdkClient: client,
}, nil
}
-func (u *HuaweiCloudELBUploader) 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 := certs.ParseCertificateFromPEM(certPem)
if err != nil {
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 c0618da0..9406c55d 100644
--- a/internal/pkg/core/uploader/providers/huaweicloud-scm/huaweicloud_scm.go
+++ b/internal/pkg/core/uploader/providers/huaweicloud-scm/huaweicloud_scm.go
@@ -2,7 +2,6 @@
import (
"context"
- "errors"
"fmt"
"time"
@@ -17,7 +16,7 @@ import (
hwsdk "github.com/usual2970/certimate/internal/pkg/vendors/huaweicloud-sdk"
)
-type HuaweiCloudSCMUploaderConfig struct {
+type UploaderConfig struct {
// 华为云 AccessKeyId。
AccessKeyId string `json:"accessKeyId"`
// 华为云 SecretAccessKey。
@@ -26,16 +25,16 @@ type HuaweiCloudSCMUploaderConfig struct {
Region string `json:"region"`
}
-type HuaweiCloudSCMUploader struct {
- config *HuaweiCloudSCMUploaderConfig
+type UploaderProvider struct {
+ config *UploaderConfig
sdkClient *hcScm.ScmClient
}
-var _ uploader.Uploader = (*HuaweiCloudSCMUploader)(nil)
+var _ uploader.Uploader = (*UploaderProvider)(nil)
-func New(config *HuaweiCloudSCMUploaderConfig) (*HuaweiCloudSCMUploader, error) {
+func NewUploader(config *UploaderConfig) (*UploaderProvider, error) {
if config == nil {
- return nil, errors.New("config is nil")
+ panic("config is nil")
}
client, err := createSdkClient(
@@ -47,13 +46,13 @@ func New(config *HuaweiCloudSCMUploaderConfig) (*HuaweiCloudSCMUploader, error)
return nil, xerrors.Wrap(err, "failed to create sdk client")
}
- return &HuaweiCloudSCMUploader{
+ return &UploaderProvider{
config: config,
sdkClient: client,
}, nil
}
-func (u *HuaweiCloudSCMUploader) 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 := certs.ParseCertificateFromPEM(certPem)
if err != nil {
diff --git a/internal/pkg/core/uploader/providers/huaweicloud-waf/huaweicloud_waf.go b/internal/pkg/core/uploader/providers/huaweicloud-waf/huaweicloud_waf.go
new file mode 100644
index 00000000..19e7cea7
--- /dev/null
+++ b/internal/pkg/core/uploader/providers/huaweicloud-waf/huaweicloud_waf.go
@@ -0,0 +1,214 @@
+package huaweicloudwaf
+
+import (
+ "context"
+ "errors"
+ "fmt"
+ "time"
+
+ "github.com/huaweicloud/huaweicloud-sdk-go-v3/core/auth/basic"
+ "github.com/huaweicloud/huaweicloud-sdk-go-v3/core/auth/global"
+ 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"
+ 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/certs"
+ hwsdk "github.com/usual2970/certimate/internal/pkg/vendors/huaweicloud-sdk"
+)
+
+type UploaderConfig struct {
+ // 华为云 AccessKeyId。
+ AccessKeyId string `json:"accessKeyId"`
+ // 华为云 SecretAccessKey。
+ SecretAccessKey string `json:"secretAccessKey"`
+ // 华为云区域。
+ Region string `json:"region"`
+}
+
+type UploaderProvider struct {
+ config *UploaderConfig
+ sdkClient *hcWaf.WafClient
+}
+
+var _ uploader.Uploader = (*UploaderProvider)(nil)
+
+func NewUploader(config *UploaderConfig) (*UploaderProvider, error) {
+ if config == nil {
+ panic("config is nil")
+ }
+
+ client, err := createSdkClient(
+ config.AccessKeyId,
+ config.SecretAccessKey,
+ config.Region,
+ )
+ if err != nil {
+ return nil, xerrors.Wrap(err, "failed to create sdk client")
+ }
+
+ return &UploaderProvider{
+ config: config,
+ sdkClient: client,
+ }, nil
+}
+
+func (u *UploaderProvider) Upload(ctx context.Context, certPem string, privkeyPem string) (res *uploader.UploadResult, err error) {
+ // 解析证书内容
+ certX509, err := certs.ParseCertificateFromPEM(certPem)
+ if err != nil {
+ return nil, err
+ }
+
+ // 遍历查询已有证书,避免重复上传
+ // REF: https://support.huaweicloud.com/api-waf/ListCertificates.html
+ // REF: https://support.huaweicloud.com/api-waf/ShowCertificate.html
+ listCertificatesPage := int32(1)
+ listCertificatesPageSize := int32(100)
+ for {
+ listCertificatesReq := &hcWafModel.ListCertificatesRequest{
+ Page: hwsdk.Int32Ptr(listCertificatesPage),
+ Pagesize: hwsdk.Int32Ptr(listCertificatesPageSize),
+ }
+ listCertificatesResp, err := u.sdkClient.ListCertificates(listCertificatesReq)
+ if err != nil {
+ return nil, xerrors.Wrap(err, "failed to execute sdk request 'waf.ListCertificates'")
+ }
+
+ if listCertificatesResp.Items != nil {
+ for _, certItem := range *listCertificatesResp.Items {
+ showCertificateReq := &hcWafModel.ShowCertificateRequest{
+ CertificateId: certItem.Id,
+ }
+ showCertificateResp, err := u.sdkClient.ShowCertificate(showCertificateReq)
+ if err != nil {
+ return nil, xerrors.Wrap(err, "failed to execute sdk request 'waf.ShowCertificate'")
+ }
+
+ var isSameCert bool
+ if *showCertificateResp.Content == certPem {
+ isSameCert = true
+ } else {
+ oldCertX509, err := certs.ParseCertificateFromPEM(*showCertificateResp.Content)
+ if err != nil {
+ continue
+ }
+
+ isSameCert = certs.EqualCertificate(certX509, oldCertX509)
+ }
+
+ // 如果已存在相同证书,直接返回已有的证书信息
+ if isSameCert {
+ return &uploader.UploadResult{
+ CertId: certItem.Id,
+ CertName: certItem.Name,
+ }, nil
+ }
+ }
+ }
+
+ if listCertificatesResp.Items == nil || len(*listCertificatesResp.Items) < int(listCertificatesPageSize) {
+ break
+ } else {
+ listCertificatesPage++
+ }
+ }
+
+ // 生成新证书名(需符合华为云命名规则)
+ var certId, certName string
+ certName = fmt.Sprintf("certimate-%d", time.Now().UnixMilli())
+
+ // 创建证书
+ // REF: https://support.huaweicloud.com/api-waf/CreateCertificate.html
+ createCertificateReq := &hcWafModel.CreateCertificateRequest{
+ Body: &hcWafModel.CreateCertificateRequestBody{
+ Name: certName,
+ Content: certPem,
+ Key: privkeyPem,
+ },
+ }
+ createCertificateResp, err := u.sdkClient.CreateCertificate(createCertificateReq)
+ if err != nil {
+ return nil, xerrors.Wrap(err, "failed to execute sdk request 'waf.CreateCertificate'")
+ }
+
+ certId = *createCertificateResp.Id
+ certName = *createCertificateResp.Name
+ return &uploader.UploadResult{
+ CertId: certId,
+ CertName: certName,
+ }, nil
+}
+
+func createSdkClient(accessKeyId, secretAccessKey, region string) (*hcWaf.WafClient, error) {
+ projectId, err := getSdkProjectId(accessKeyId, secretAccessKey, region)
+ if err != nil {
+ return nil, err
+ }
+
+ auth, err := basic.NewCredentialsBuilder().
+ WithAk(accessKeyId).
+ WithSk(secretAccessKey).
+ WithProjectId(projectId).
+ SafeBuild()
+ if err != nil {
+ return nil, err
+ }
+
+ hcRegion, err := hcWafRegion.SafeValueOf(region)
+ if err != nil {
+ return nil, err
+ }
+
+ hcClient, err := hcWaf.WafClientBuilder().
+ WithRegion(hcRegion).
+ WithCredential(auth).
+ SafeBuild()
+ if err != nil {
+ return nil, err
+ }
+
+ client := hcWaf.NewWafClient(hcClient)
+ return client, nil
+}
+
+func getSdkProjectId(accessKeyId, secretAccessKey, region string) (string, error) {
+ auth, err := global.NewCredentialsBuilder().
+ WithAk(accessKeyId).
+ WithSk(secretAccessKey).
+ SafeBuild()
+ if err != nil {
+ return "", err
+ }
+
+ hcRegion, err := hcIamRegion.SafeValueOf(region)
+ if err != nil {
+ return "", err
+ }
+
+ hcClient, err := hcIam.IamClientBuilder().
+ WithRegion(hcRegion).
+ WithCredential(auth).
+ SafeBuild()
+ if err != nil {
+ return "", err
+ }
+
+ client := hcIam.NewIamClient(hcClient)
+
+ request := &hcIamModel.KeystoneListProjectsRequest{
+ Name: ®ion,
+ }
+ response, err := client.KeystoneListProjects(request)
+ if err != nil {
+ return "", err
+ } else if response.Projects == nil || len(*response.Projects) == 0 {
+ return "", errors.New("no project found")
+ }
+
+ return (*response.Projects)[0].Id, nil
+}
diff --git a/internal/pkg/core/uploader/providers/jdcloud-ssl/jdcloud_ssl.go b/internal/pkg/core/uploader/providers/jdcloud-ssl/jdcloud_ssl.go
new file mode 100644
index 00000000..afbbf3e1
--- /dev/null
+++ b/internal/pkg/core/uploader/providers/jdcloud-ssl/jdcloud_ssl.go
@@ -0,0 +1,139 @@
+package jdcloudssl
+
+import (
+ "context"
+ "crypto/sha256"
+ "encoding/hex"
+ "fmt"
+ "strings"
+ "time"
+
+ 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/certs"
+)
+
+type UploaderConfig struct {
+ // 京东云 AccessKeyId。
+ AccessKeyId string `json:"accessKeyId"`
+ // 京东云 AccessKeySecret。
+ AccessKeySecret string `json:"accessKeySecret"`
+}
+
+type UploaderProvider struct {
+ config *UploaderConfig
+ sdkClient *jdSslClient.SslClient
+}
+
+var _ uploader.Uploader = (*UploaderProvider)(nil)
+
+func NewUploader(config *UploaderConfig) (*UploaderProvider, error) {
+ if config == nil {
+ panic("config is nil")
+ }
+
+ client, err := createSdkClient(config.AccessKeyId, config.AccessKeySecret)
+ if err != nil {
+ return nil, xerrors.Wrap(err, "failed to create sdk client")
+ }
+
+ return &UploaderProvider{
+ config: config,
+ sdkClient: client,
+ }, nil
+}
+
+func (u *UploaderProvider) Upload(ctx context.Context, certPem string, privkeyPem string) (res *uploader.UploadResult, err error) {
+ // 解析证书内容
+ certX509, err := certs.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"
+
+ // 遍历查看证书列表,避免重复上传
+ // REF: https://docs.jdcloud.com/cn/ssl-certificate/api/describecerts
+ describeCertsPageNumber := 1
+ describeCertsPageSize := 10
+ for {
+ describeCertsReq := jdSslApi.NewDescribeCertsRequest()
+ describeCertsReq.SetDomainName(certX509.Subject.CommonName)
+ describeCertsReq.SetPageNumber(describeCertsPageNumber)
+ describeCertsReq.SetPageSize(describeCertsPageSize)
+ describeCertsResp, err := u.sdkClient.DescribeCerts(describeCertsReq)
+ if err != nil {
+ return nil, xerrors.Wrap(err, "failed to execute sdk request 'ssl.DescribeCerts'")
+ }
+
+ for _, certDetail := range describeCertsResp.Result.CertListDetails {
+ // 先尝试匹配 CN
+ if !strings.EqualFold(certX509.Subject.CommonName, certDetail.CommonName) {
+ continue
+ }
+
+ // 再尝试匹配 SAN
+ if !slices.Equal(certX509.DNSNames, certDetail.DnsNames) {
+ continue
+ }
+
+ // 再尝试匹配证书有效期
+ oldCertNotBefore, _ := time.Parse(time.RFC3339, certDetail.StartTime)
+ oldCertNotAfter, _ := time.Parse(time.RFC3339, certDetail.EndTime)
+ if !certX509.NotBefore.Equal(oldCertNotBefore) || !certX509.NotAfter.Equal(oldCertNotAfter) {
+ continue
+ }
+
+ // 最后尝试匹配私钥摘要
+ newKeyDigest := sha256.Sum256([]byte(privkeyPem))
+ newKeyDigestHex := hex.EncodeToString(newKeyDigest[:])
+ if !strings.EqualFold(newKeyDigestHex, certDetail.Digest) {
+ continue
+ }
+
+ // 如果以上都匹配,则视为已存在相同证书,直接返回已有的证书信息
+ return &uploader.UploadResult{
+ CertId: certDetail.CertId,
+ CertName: certDetail.CertName,
+ }, nil
+ }
+
+ if len(describeCertsResp.Result.CertListDetails) < int(describeCertsPageSize) {
+ break
+ } else {
+ describeCertsPageNumber++
+ }
+ }
+
+ // 生成新证书名(需符合京东云命名规则)
+ certName := fmt.Sprintf("certimate-%d", time.Now().UnixMilli())
+
+ // 上传证书
+ // REF: https://docs.jdcloud.com/cn/ssl-certificate/api/uploadcert
+ uploadCertReq := jdSslApi.NewUploadCertRequest(certName, privkeyPem, certPem)
+ uploadCertResp, err := u.sdkClient.UploadCert(uploadCertReq)
+ if err != nil {
+ return nil, xerrors.Wrap(err, "failed to execute sdk request 'ssl.UploadCertificate'")
+ }
+
+ return &uploader.UploadResult{
+ CertId: uploadCertResp.Result.CertId,
+ CertName: certName,
+ }, nil
+}
+
+func createSdkClient(accessKeyId, accessKeySecret string) (*jdSslClient.SslClient, error) {
+ clientCredentials := jdCore.NewCredentials(accessKeyId, accessKeySecret)
+ client := jdSslClient.NewSslClient(clientCredentials)
+ client.SetLogger(jdCore.NewDefaultLogger(jdCore.LogWarn))
+ return client, nil
+}
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
new file mode 100644
index 00000000..ec02ce49
--- /dev/null
+++ b/internal/pkg/core/uploader/providers/jdcloud-ssl/jdcloud_ssl_test.go
@@ -0,0 +1,72 @@
+package jdcloudssl_test
+
+import (
+ "context"
+ "encoding/json"
+ "flag"
+ "fmt"
+ "os"
+ "strings"
+ "testing"
+
+ provider "github.com/usual2970/certimate/internal/pkg/core/uploader/providers/jdcloud-ssl"
+)
+
+var (
+ fInputCertPath string
+ fInputKeyPath string
+ fAccessKeyId string
+ fAccessKeySecret string
+)
+
+func init() {
+ argsPrefix := "CERTIMATE_UPLOADER_JDCLOUDSSL_"
+
+ flag.StringVar(&fInputCertPath, argsPrefix+"INPUTCERTPATH", "", "")
+ flag.StringVar(&fInputKeyPath, argsPrefix+"INPUTKEYPATH", "", "")
+ flag.StringVar(&fAccessKeyId, argsPrefix+"ACCESSKEYID", "", "")
+ flag.StringVar(&fAccessKeySecret, argsPrefix+"ACCESSKEYSECRET", "", "")
+}
+
+/*
+Shell command to run this test:
+
+ go test -v ./jdcloud_ssl_test.go -args \
+ --CERTIMATE_UPLOADER_JDCLOUDSSL_INPUTCERTPATH="/path/to/your-input-cert.pem" \
+ --CERTIMATE_UPLOADER_JDCLOUDSSL_INPUTKEYPATH="/path/to/your-input-key.pem" \
+ --CERTIMATE_UPLOADER_JDCLOUDSSL_ACCESSKEYID="your-access-key-id" \
+ --CERTIMATE_UPLOADER_JDCLOUDSSL_ACCESSKEYSECRET="your-access-key-secret"
+*/
+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),
+ }, "\n"))
+
+ uploader, err := provider.NewUploader(&provider.UploaderConfig{
+ AccessKeyId: fAccessKeyId,
+ AccessKeySecret: fAccessKeySecret,
+ })
+ if err != nil {
+ t.Errorf("err: %+v", err)
+ return
+ }
+
+ fInputCertData, _ := os.ReadFile(fInputCertPath)
+ fInputKeyData, _ := os.ReadFile(fInputKeyPath)
+ res, err := uploader.Upload(context.Background(), string(fInputCertData), string(fInputKeyData))
+ if err != nil {
+ t.Errorf("err: %+v", err)
+ return
+ }
+
+ sres, _ := json.Marshal(res)
+ t.Logf("ok: %s", string(sres))
+ })
+}
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 851cbf01..05c57be8 100644
--- a/internal/pkg/core/uploader/providers/qiniu-sslcert/qiniu_sslcert.go
+++ b/internal/pkg/core/uploader/providers/qiniu-sslcert/qiniu_sslcert.go
@@ -2,7 +2,6 @@
import (
"context"
- "errors"
"fmt"
"time"
@@ -14,23 +13,23 @@ import (
qiniuEx "github.com/usual2970/certimate/internal/pkg/vendors/qiniu-sdk"
)
-type QiniuSSLCertUploaderConfig struct {
+type UploaderConfig struct {
// 七牛云 AccessKey。
AccessKey string `json:"accessKey"`
// 七牛云 SecretKey。
SecretKey string `json:"secretKey"`
}
-type QiniuSSLCertUploader struct {
- config *QiniuSSLCertUploaderConfig
+type UploaderProvider struct {
+ config *UploaderConfig
sdkClient *qiniuEx.Client
}
-var _ uploader.Uploader = (*QiniuSSLCertUploader)(nil)
+var _ uploader.Uploader = (*UploaderProvider)(nil)
-func New(config *QiniuSSLCertUploaderConfig) (*QiniuSSLCertUploader, error) {
+func NewUploader(config *UploaderConfig) (*UploaderProvider, error) {
if config == nil {
- return nil, errors.New("config is nil")
+ panic("config is nil")
}
client, err := createSdkClient(
@@ -41,13 +40,13 @@ func New(config *QiniuSSLCertUploaderConfig) (*QiniuSSLCertUploader, error) {
return nil, xerrors.Wrap(err, "failed to create sdk client")
}
- return &QiniuSSLCertUploader{
+ return &UploaderProvider{
config: config,
sdkClient: client,
}, nil
}
-func (u *QiniuSSLCertUploader) 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 := certs.ParseCertificateFromPEM(certPem)
if err != nil {
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 a94af000..a76bf2a0 100644
--- a/internal/pkg/core/uploader/providers/tencentcloud-ssl/tencentcloud_ssl.go
+++ b/internal/pkg/core/uploader/providers/tencentcloud-ssl/tencentcloud_ssl.go
@@ -2,7 +2,6 @@
import (
"context"
- "errors"
xerrors "github.com/pkg/errors"
"github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common"
@@ -12,23 +11,23 @@ import (
"github.com/usual2970/certimate/internal/pkg/core/uploader"
)
-type TencentCloudSSLUploaderConfig struct {
+type UploaderConfig struct {
// 腾讯云 SecretId。
SecretId string `json:"secretId"`
// 腾讯云 SecretKey。
SecretKey string `json:"secretKey"`
}
-type TencentCloudSSLUploader struct {
- config *TencentCloudSSLUploaderConfig
+type UploaderProvider struct {
+ config *UploaderConfig
sdkClient *tcSsl.Client
}
-var _ uploader.Uploader = (*TencentCloudSSLUploader)(nil)
+var _ uploader.Uploader = (*UploaderProvider)(nil)
-func New(config *TencentCloudSSLUploaderConfig) (*TencentCloudSSLUploader, error) {
+func NewUploader(config *UploaderConfig) (*UploaderProvider, error) {
if config == nil {
- return nil, errors.New("config is nil")
+ panic("config is nil")
}
client, err := createSdkClient(
@@ -39,13 +38,13 @@ func New(config *TencentCloudSSLUploaderConfig) (*TencentCloudSSLUploader, error
return nil, xerrors.Wrap(err, "failed to create sdk client")
}
- return &TencentCloudSSLUploader{
+ return &UploaderProvider{
config: config,
sdkClient: client,
}, nil
}
-func (u *TencentCloudSSLUploader) 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()
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 9c5fa2b3..aaa03999 100644
--- a/internal/pkg/core/uploader/providers/ucloud-ussl/ucloud_ussl.go
+++ b/internal/pkg/core/uploader/providers/ucloud-ussl/ucloud_ussl.go
@@ -20,7 +20,7 @@ import (
usdkSsl "github.com/usual2970/certimate/internal/pkg/vendors/ucloud-sdk/ussl"
)
-type UCloudUSSLUploaderConfig struct {
+type UploaderConfig struct {
// 优刻得 API 私钥。
PrivateKey string `json:"privateKey"`
// 优刻得 API 公钥。
@@ -29,16 +29,16 @@ type UCloudUSSLUploaderConfig struct {
ProjectId string `json:"projectId,omitempty"`
}
-type UCloudUSSLUploader struct {
- config *UCloudUSSLUploaderConfig
+type UploaderProvider struct {
+ config *UploaderConfig
sdkClient *usdkSsl.USSLClient
}
-var _ uploader.Uploader = (*UCloudUSSLUploader)(nil)
+var _ uploader.Uploader = (*UploaderProvider)(nil)
-func New(config *UCloudUSSLUploaderConfig) (*UCloudUSSLUploader, error) {
+func NewUploader(config *UploaderConfig) (*UploaderProvider, error) {
if config == nil {
- return nil, errors.New("config is nil")
+ panic("config is nil")
}
client, err := createSdkClient(config.PrivateKey, config.PublicKey)
@@ -46,13 +46,13 @@ func New(config *UCloudUSSLUploaderConfig) (*UCloudUSSLUploader, error) {
return nil, xerrors.Wrap(err, "failed to create sdk client")
}
- return &UCloudUSSLUploader{
+ return &UploaderProvider{
config: config,
sdkClient: client,
}, nil
}
-func (u *UCloudUSSLUploader) 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())
@@ -92,7 +92,7 @@ func (u *UCloudUSSLUploader) Upload(ctx context.Context, certPem string, privkey
}, nil
}
-func (u *UCloudUSSLUploader) getExistCert(ctx context.Context, certPem string) (res *uploader.UploadResult, err error) {
+func (u *UploaderProvider) getExistCert(ctx context.Context, certPem string) (res *uploader.UploadResult, err error) {
// 解析证书内容
certX509, err := certs.ParseCertificateFromPEM(certPem)
if err != nil {
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 c0a0f719..b6324fd5 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
@@ -49,7 +49,7 @@ func TestDeploy(t *testing.T) {
fmt.Sprintf("PUBLICKEY: %v", fPublicKey),
}, "\n"))
- uploader, err := provider.New(&provider.UCloudUSSLUploaderConfig{
+ uploader, err := provider.NewUploader(&provider.UploaderConfig{
PrivateKey: fPrivateKey,
PublicKey: fPublicKey,
})
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 23f05281..9b5c9b56 100644
--- a/internal/pkg/core/uploader/providers/volcengine-cdn/volcengine_cdn.go
+++ b/internal/pkg/core/uploader/providers/volcengine-cdn/volcengine_cdn.go
@@ -5,7 +5,6 @@ import (
"crypto/sha1"
"crypto/sha256"
"encoding/hex"
- "errors"
"fmt"
"strings"
"time"
@@ -18,36 +17,36 @@ import (
"github.com/usual2970/certimate/internal/pkg/utils/certs"
)
-type VolcEngineCDNUploaderConfig struct {
+type UploaderConfig struct {
// 火山引擎 AccessKeyId。
AccessKeyId string `json:"accessKeyId"`
// 火山引擎 AccessKeySecret。
AccessKeySecret string `json:"accessKeySecret"`
}
-type VolcEngineCDNUploader struct {
- config *VolcEngineCDNUploaderConfig
+type UploaderProvider struct {
+ config *UploaderConfig
sdkClient *veCdn.CDN
}
-var _ uploader.Uploader = (*VolcEngineCDNUploader)(nil)
+var _ uploader.Uploader = (*UploaderProvider)(nil)
-func New(config *VolcEngineCDNUploaderConfig) (*VolcEngineCDNUploader, error) {
+func NewUploader(config *UploaderConfig) (*UploaderProvider, error) {
if config == nil {
- return nil, errors.New("config is nil")
+ panic("config is nil")
}
client := veCdn.NewInstance()
client.Client.SetAccessKey(config.AccessKeyId)
client.Client.SetSecretKey(config.AccessKeySecret)
- return &VolcEngineCDNUploader{
+ return &UploaderProvider{
config: config,
sdkClient: client,
}, nil
}
-func (u *VolcEngineCDNUploader) 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 := certs.ParseCertificateFromPEM(certPem)
if err != nil {
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 5e301ebd..1ff133e5 100644
--- a/internal/pkg/core/uploader/providers/volcengine-certcenter/volcengine_certcenter.go
+++ b/internal/pkg/core/uploader/providers/volcengine-certcenter/volcengine_certcenter.go
@@ -2,7 +2,6 @@ package volcenginecertcenter
import (
"context"
- "errors"
xerrors "github.com/pkg/errors"
ve "github.com/volcengine/volcengine-go-sdk/volcengine"
@@ -12,7 +11,7 @@ import (
vesdkCc "github.com/usual2970/certimate/internal/pkg/vendors/volcengine-sdk/certcenter"
)
-type VolcEngineCertCenterUploaderConfig struct {
+type UploaderConfig struct {
// 火山引擎 AccessKeyId。
AccessKeyId string `json:"accessKeyId"`
// 火山引擎 AccessKeySecret。
@@ -21,16 +20,16 @@ type VolcEngineCertCenterUploaderConfig struct {
Region string `json:"region"`
}
-type VolcEngineCertCenterUploader struct {
- config *VolcEngineCertCenterUploaderConfig
+type UploaderProvider struct {
+ config *UploaderConfig
sdkClient *vesdkCc.CertCenter
}
-var _ uploader.Uploader = (*VolcEngineCertCenterUploader)(nil)
+var _ uploader.Uploader = (*UploaderProvider)(nil)
-func New(config *VolcEngineCertCenterUploaderConfig) (*VolcEngineCertCenterUploader, error) {
+func NewUploader(config *UploaderConfig) (*UploaderProvider, error) {
if config == nil {
- return nil, errors.New("config is nil")
+ panic("config is nil")
}
client, err := createSdkClient(config.AccessKeyId, config.AccessKeySecret, config.Region)
@@ -38,13 +37,13 @@ func New(config *VolcEngineCertCenterUploaderConfig) (*VolcEngineCertCenterUploa
return nil, xerrors.Wrap(err, "failed to create sdk client")
}
- return &VolcEngineCertCenterUploader{
+ return &UploaderProvider{
config: config,
sdkClient: client,
}, nil
}
-func (u *VolcEngineCertCenterUploader) 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 := &vesdkCc.ImportCertificateInput{
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 5f15c44f..5c312707 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
@@ -49,7 +49,7 @@ func TestDeploy(t *testing.T) {
fmt.Sprintf("ACCESSKEYSECRET: %v", fAccessKeySecret),
}, "\n"))
- uploader, err := provider.New(&provider.VolcEngineCertCenterUploaderConfig{
+ uploader, err := provider.NewUploader(&provider.UploaderConfig{
AccessKeyId: fAccessKeyId,
AccessKeySecret: fAccessKeySecret,
})
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 c7861cb6..3a7a39eb 100644
--- a/internal/pkg/core/uploader/providers/volcengine-live/volcengine_live.go
+++ b/internal/pkg/core/uploader/providers/volcengine-live/volcengine_live.go
@@ -2,7 +2,6 @@ package volcenginelive
import (
"context"
- "errors"
"fmt"
"strings"
"time"
@@ -15,36 +14,36 @@ import (
"github.com/usual2970/certimate/internal/pkg/utils/certs"
)
-type VolcEngineLiveUploaderConfig struct {
+type UploaderConfig struct {
// 火山引擎 AccessKeyId。
AccessKeyId string `json:"accessKeyId"`
// 火山引擎 AccessKeySecret。
AccessKeySecret string `json:"accessKeySecret"`
}
-type VolcEngineLiveUploader struct {
- config *VolcEngineLiveUploaderConfig
+type UploaderProvider struct {
+ config *UploaderConfig
sdkClient *veLive.Live
}
-var _ uploader.Uploader = (*VolcEngineLiveUploader)(nil)
+var _ uploader.Uploader = (*UploaderProvider)(nil)
-func New(config *VolcEngineLiveUploaderConfig) (*VolcEngineLiveUploader, error) {
+func NewUploader(config *UploaderConfig) (*UploaderProvider, error) {
if config == nil {
- return nil, errors.New("config is nil")
+ panic("config is nil")
}
client := veLive.NewInstance()
client.SetAccessKey(config.AccessKeyId)
client.SetSecretKey(config.AccessKeySecret)
- return &VolcEngineLiveUploader{
+ return &UploaderProvider{
config: config,
sdkClient: client,
}, nil
}
-func (u *VolcEngineLiveUploader) 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 := certs.ParseCertificateFromPEM(certPem)
if err != nil {
diff --git a/internal/pkg/utils/maps/maps.go b/internal/pkg/utils/maps/maps.go
index a88b6629..4a4417d0 100644
--- a/internal/pkg/utils/maps/maps.go
+++ b/internal/pkg/utils/maps/maps.go
@@ -207,8 +207,3 @@ func Populate(dict map[string]any, output any) error {
return decoder.Decode(dict)
}
-
-// Deprecated: Use [Populate] instead.
-func Decode(dict map[string]any, output any) error {
- return Populate(dict, output)
-}
diff --git a/internal/pkg/vendors/baishan-sdk/api.go b/internal/pkg/vendors/baishan-sdk/api.go
new file mode 100644
index 00000000..c2f76adc
--- /dev/null
+++ b/internal/pkg/vendors/baishan-sdk/api.go
@@ -0,0 +1,32 @@
+package baishansdk
+
+import (
+ "net/http"
+)
+
+func (c *Client) CreateCertificate(req *CreateCertificateRequest) (*CreateCertificateResponse, error) {
+ resp := CreateCertificateResponse{}
+ err := c.sendRequestWithResult(http.MethodPost, "/v2/domain/certificate", req, &resp)
+ if err != nil {
+ return nil, err
+ }
+ return &resp, nil
+}
+
+func (c *Client) GetDomainConfig(req *GetDomainConfigRequest) (*GetDomainConfigResponse, error) {
+ resp := GetDomainConfigResponse{}
+ err := c.sendRequestWithResult(http.MethodGet, "/v2/domain/config", req, &resp)
+ if err != nil {
+ return nil, err
+ }
+ return &resp, nil
+}
+
+func (c *Client) SetDomainConfig(req *SetDomainConfigRequest) (*SetDomainConfigResponse, error) {
+ resp := SetDomainConfigResponse{}
+ err := c.sendRequestWithResult(http.MethodPost, "/v2/domain/config", req, &resp)
+ if err != nil {
+ return nil, err
+ }
+ return &resp, nil
+}
diff --git a/internal/pkg/vendors/baishan-sdk/client.go b/internal/pkg/vendors/baishan-sdk/client.go
new file mode 100644
index 00000000..44015b62
--- /dev/null
+++ b/internal/pkg/vendors/baishan-sdk/client.go
@@ -0,0 +1,83 @@
+package baishansdk
+
+import (
+ "encoding/json"
+ "fmt"
+ "net/http"
+ "strings"
+ "time"
+
+ "github.com/go-resty/resty/v2"
+)
+
+type Client struct {
+ apiToken string
+
+ client *resty.Client
+}
+
+func NewClient(apiToken string) *Client {
+ client := resty.New()
+
+ return &Client{
+ apiToken: apiToken,
+ client: client,
+ }
+}
+
+func (c *Client) WithTimeout(timeout time.Duration) *Client {
+ c.client.SetTimeout(timeout)
+ return c
+}
+
+func (c *Client) sendRequest(method string, path string, params interface{}) (*resty.Response, error) {
+ req := c.client.R()
+ req.Method = method
+ req.URL = "https://cdn.api.baishan.com" + 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).
+ SetQueryParam("token", c.apiToken)
+ } else {
+ req = req.
+ SetHeader("Content-Type", "application/json").
+ SetQueryParam("token", c.apiToken).
+ SetBody(params)
+ }
+
+ resp, err := req.Send()
+ if err != nil {
+ return nil, fmt.Errorf("baishan api error: failed to send request: %w", err)
+ } else if resp.IsError() {
+ return nil, fmt.Errorf("baishan api error: unexpected status code: %d, %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 {
+ return err
+ }
+
+ if err := json.Unmarshal(resp.Body(), &result); err != nil {
+ return fmt.Errorf("baishan api error: failed to parse response: %w", err)
+ } else if errcode := result.GetCode(); errcode != 0 {
+ return fmt.Errorf("baishan api error: %d - %s", errcode, result.GetMessage())
+ }
+
+ return nil
+}
diff --git a/internal/pkg/vendors/baishan-sdk/models.go b/internal/pkg/vendors/baishan-sdk/models.go
new file mode 100644
index 00000000..78685571
--- /dev/null
+++ b/internal/pkg/vendors/baishan-sdk/models.go
@@ -0,0 +1,73 @@
+package baishansdk
+
+type BaseResponse interface {
+ GetCode() int
+ GetMessage() string
+}
+
+type baseResponse struct {
+ Code int `json:"code"`
+ Message string `json:"message"`
+}
+
+func (r *baseResponse) GetCode() int {
+ return r.Code
+}
+
+func (r *baseResponse) GetMessage() string {
+ return r.Message
+}
+
+type CreateCertificateRequest struct {
+ Certificate string `json:"certificate"`
+ Key string `json:"key"`
+ Name string `json:"name"`
+}
+
+type CreateCertificateResponse struct {
+ baseResponse
+ Data *DomainCertificate `json:"data"`
+}
+
+type GetDomainConfigRequest struct {
+ Domains string `json:"domains"`
+ Config string `json:"config"`
+}
+
+type GetDomainConfigResponse struct {
+ baseResponse
+ Data []*struct {
+ Domain string `json:"domain"`
+ Config *DomainConfig `json:"config"`
+ } `json:"data"`
+}
+
+type SetDomainConfigRequest struct {
+ Domains string `json:"domains"`
+ Config *DomainConfig `json:"config"`
+}
+
+type SetDomainConfigResponse struct {
+ baseResponse
+ Data *struct {
+ Config *DomainConfig `json:"config"`
+ } `json:"data"`
+}
+
+type DomainCertificate struct {
+ CertId int64 `json:"cert_id"`
+ Name string `json:"name"`
+ CertStartTime string `json:"cert_start_time"`
+ CertExpireTime string `json:"cert_expire_time"`
+}
+
+type DomainConfig struct {
+ Https *DomainConfigHttps `json:"https"`
+}
+
+type DomainConfigHttps struct {
+ CertId int64 `json:"cert_id"`
+ ForceHttps *string `json:"force_https,omitempty"`
+ EnableHttp2 *string `json:"http2,omitempty"`
+ EnableOcsp *string `json:"ocsp,omitempty"`
+}
diff --git a/internal/pkg/vendors/btpanel-sdk/api.go b/internal/pkg/vendors/btpanel-sdk/api.go
index 5c58e3df..434e7f6e 100644
--- a/internal/pkg/vendors/btpanel-sdk/api.go
+++ b/internal/pkg/vendors/btpanel-sdk/api.go
@@ -1,26 +1,46 @@
package btpanelsdk
-type BaseResponse interface {
- GetStatus() *bool
- GetMsg() *string
+func (c *Client) ConfigSavePanelSSL(req *ConfigSavePanelSSLRequest) (*ConfigSavePanelSSLResponse, error) {
+ resp := ConfigSavePanelSSLResponse{}
+ err := c.sendRequestWithResult("/config?action=SavePanelSSL", req, &resp)
+ if err != nil {
+ return nil, err
+ }
+ return &resp, nil
}
-type SetSiteSSLRequest struct {
- Type string `json:"type"`
- SiteName string `json:"siteName"`
- Key string `json:"key"`
- Csr string `json:"csr"`
+func (c *Client) SiteSetSSL(req *SiteSetSSLRequest) (*SiteSetSSLResponse, error) {
+ resp := SiteSetSSLResponse{}
+ err := c.sendRequestWithResult("/site?action=SetSSL", req, &resp)
+ if err != nil {
+ return nil, err
+ }
+ return &resp, nil
}
-type SetSiteSSLResponse struct {
- Status *bool `json:"status,omitempty"`
- Msg *string `json:"msg,omitempty"`
+func (c *Client) SystemServiceAdmin(req *SystemServiceAdminRequest) (*SystemServiceAdminResponse, error) {
+ resp := SystemServiceAdminResponse{}
+ err := c.sendRequestWithResult("/system?action=ServiceAdmin", req, &resp)
+ if err != nil {
+ return nil, err
+ }
+ return &resp, nil
}
-func (r *SetSiteSSLResponse) GetStatus() *bool {
- return r.Status
+func (c *Client) SSLCertSaveCert(req *SSLCertSaveCertRequest) (*SSLCertSaveCertResponse, error) {
+ resp := SSLCertSaveCertResponse{}
+ err := c.sendRequestWithResult("/ssl/cert/save_cert", req, &resp)
+ if err != nil {
+ return nil, err
+ }
+ return &resp, nil
}
-func (r *SetSiteSSLResponse) GetMsg() *string {
- return r.Msg
+func (c *Client) SSLSetBatchCertToSite(req *SSLSetBatchCertToSiteRequest) (*SSLSetBatchCertToSiteResponse, error) {
+ resp := SSLSetBatchCertToSiteResponse{}
+ err := c.sendRequestWithResult("/ssl?action=SetBatchCertToSite", req, &resp)
+ if err != nil {
+ return nil, err
+ }
+ return &resp, nil
}
diff --git a/internal/pkg/vendors/btpanel-sdk/client.go b/internal/pkg/vendors/btpanel-sdk/client.go
index 9557612a..67e9fdb1 100644
--- a/internal/pkg/vendors/btpanel-sdk/client.go
+++ b/internal/pkg/vendors/btpanel-sdk/client.go
@@ -9,45 +9,31 @@ import (
"time"
"github.com/go-resty/resty/v2"
-
- "github.com/usual2970/certimate/internal/pkg/utils/maps"
)
-type BaoTaPanelClient struct {
+type Client struct {
apiHost string
apiKey string
- client *resty.Client
+
+ client *resty.Client
}
-func NewBaoTaPanelClient(apiHost, apiKey string) *BaoTaPanelClient {
+func NewClient(apiHost, apiKey string) *Client {
client := resty.New()
- return &BaoTaPanelClient{
- apiHost: apiHost,
+ return &Client{
+ apiHost: strings.TrimRight(apiHost, "/"),
apiKey: apiKey,
client: client,
}
}
-func (c *BaoTaPanelClient) WithTimeout(timeout time.Duration) *BaoTaPanelClient {
+func (c *Client) WithTimeout(timeout time.Duration) *Client {
c.client.SetTimeout(timeout)
return c
}
-func (c *BaoTaPanelClient) SetSiteSSL(req *SetSiteSSLRequest) (*SetSiteSSLResponse, error) {
- params := make(map[string]any)
- jsonData, _ := json.Marshal(req)
- json.Unmarshal(jsonData, ¶ms)
-
- result := SetSiteSSLResponse{}
- err := c.sendRequestWithResult("/site?action=SetSSL", params, &result)
- if err != nil {
- return nil, err
- }
- return &result, nil
-}
-
-func (c *BaoTaPanelClient) generateSignature(timestamp string) string {
+func (c *Client) generateSignature(timestamp string) string {
keyMd5 := md5.Sum([]byte(c.apiKey))
keyMd5Hex := strings.ToLower(hex.EncodeToString(keyMd5[:]))
@@ -56,50 +42,50 @@ func (c *BaoTaPanelClient) generateSignature(timestamp string) string {
return signMd5Hex
}
-func (c *BaoTaPanelClient) sendRequest(path string, params map[string]any) (*resty.Response, error) {
- if params == nil {
- params = make(map[string]any)
- }
-
+func (c *Client) sendRequest(path string, params interface{}) (*resty.Response, error) {
timestamp := time.Now().Unix()
- params["request_time"] = timestamp
- params["request_token"] = c.generateSignature(fmt.Sprintf("%d", timestamp))
- url := strings.TrimRight(c.apiHost, "/") + path
+ data := make(map[string]any)
+ if params != nil {
+ temp := make(map[string]any)
+ jsonb, _ := json.Marshal(params)
+ json.Unmarshal(jsonb, &temp)
+ for k, v := range temp {
+ if v != nil {
+ data[k] = v
+ }
+ }
+ }
+ data["request_time"] = timestamp
+ data["request_token"] = c.generateSignature(fmt.Sprintf("%d", timestamp))
+
+ url := c.apiHost + path
req := c.client.R().
SetHeader("Content-Type", "application/json").
- SetBody(params)
+ SetBody(data)
resp, err := req.Post(url)
if err != nil {
- return nil, fmt.Errorf("baota: failed to send request: %w", err)
- }
-
- if resp.IsError() {
- return nil, fmt.Errorf("baota: unexpected status code: %d, %s", resp.StatusCode(), resp.Body())
+ return nil, fmt.Errorf("baota api error: failed to send request: %w", err)
+ } else if resp.IsError() {
+ return nil, fmt.Errorf("baota api error: unexpected status code: %d, %s", resp.StatusCode(), resp.Body())
}
return resp, nil
}
-func (c *BaoTaPanelClient) sendRequestWithResult(path string, params map[string]any, result BaseResponse) error {
+func (c *Client) sendRequestWithResult(path string, params interface{}, result BaseResponse) error {
resp, err := c.sendRequest(path, params)
if err != nil {
return err
}
- jsonResp := make(map[string]any)
- if err := json.Unmarshal(resp.Body(), &jsonResp); err != nil {
- return fmt.Errorf("baota: failed to parse response: %w", err)
- }
- if err := maps.Populate(jsonResp, &result); err != nil {
- return fmt.Errorf("baota: failed to parse response: %w", err)
- }
-
- if result.GetStatus() != nil && !*result.GetStatus() {
- if result.GetMsg() == nil {
+ if err := json.Unmarshal(resp.Body(), &result); err != nil {
+ return fmt.Errorf("baota api error: failed to parse response: %w", err)
+ } else if errstatus := result.GetStatus(); errstatus != nil && !*errstatus {
+ if result.GetMessage() == nil {
return fmt.Errorf("baota api error: unknown error")
} else {
- return fmt.Errorf("baota api error: %s", *result.GetMsg())
+ return fmt.Errorf("baota api error: %s", *result.GetMessage())
}
}
diff --git a/internal/pkg/vendors/btpanel-sdk/models.go b/internal/pkg/vendors/btpanel-sdk/models.go
new file mode 100644
index 00000000..8625e539
--- /dev/null
+++ b/internal/pkg/vendors/btpanel-sdk/models.go
@@ -0,0 +1,75 @@
+package btpanelsdk
+
+type BaseResponse interface {
+ GetStatus() *bool
+ GetMessage() *string
+}
+
+type baseResponse struct {
+ Status *bool `json:"status,omitempty"`
+ Message *string `json:"msg,omitempty"`
+}
+
+func (r *baseResponse) GetStatus() *bool {
+ return r.Status
+}
+
+func (r *baseResponse) GetMessage() *string {
+ return r.Message
+}
+
+type ConfigSavePanelSSLRequest struct {
+ PrivateKey string `json:"privateKey"`
+ Certificate string `json:"certPem"`
+}
+
+type ConfigSavePanelSSLResponse struct {
+ baseResponse
+}
+
+type SiteSetSSLRequest struct {
+ Type string `json:"type"`
+ SiteName string `json:"siteName"`
+ PrivateKey string `json:"key"`
+ Certificate string `json:"csr"`
+}
+
+type SiteSetSSLResponse struct {
+ baseResponse
+}
+
+type SystemServiceAdminRequest struct {
+ Name string `json:"name"`
+ Type string `json:"type"`
+}
+
+type SystemServiceAdminResponse struct {
+ baseResponse
+}
+
+type SSLCertSaveCertRequest struct {
+ PrivateKey string `json:"key"`
+ Certificate string `json:"csr"`
+}
+
+type SSLCertSaveCertResponse struct {
+ baseResponse
+ SSLHash string `json:"ssl_hash"`
+}
+
+type SSLSetBatchCertToSiteRequest struct {
+ BatchInfo []*SSLSetBatchCertToSiteRequestBatchInfo `json:"BatchInfo"`
+}
+
+type SSLSetBatchCertToSiteRequestBatchInfo struct {
+ SSLHash string `json:"ssl_hash"`
+ SiteName string `json:"siteName"`
+ CertName string `json:"certName"`
+}
+
+type SSLSetBatchCertToSiteResponse struct {
+ baseResponse
+ TotalCount int32 `json:"total"`
+ SuccessCount int32 `json:"success"`
+ FailedCount int32 `json:"faild"`
+}
diff --git a/internal/pkg/vendors/cachefly-sdk/api.go b/internal/pkg/vendors/cachefly-sdk/api.go
new file mode 100644
index 00000000..ad6e3b8d
--- /dev/null
+++ b/internal/pkg/vendors/cachefly-sdk/api.go
@@ -0,0 +1,14 @@
+package cacheflysdk
+
+import (
+ "net/http"
+)
+
+func (c *Client) CreateCertificate(req *CreateCertificateRequest) (*CreateCertificateResponse, error) {
+ resp := CreateCertificateResponse{}
+ err := c.sendRequestWithResult(http.MethodPost, "/certificates", req, &resp)
+ if err != nil {
+ return nil, err
+ }
+ return &resp, nil
+}
diff --git a/internal/pkg/vendors/cachefly-sdk/client.go b/internal/pkg/vendors/cachefly-sdk/client.go
new file mode 100644
index 00000000..505aafaf
--- /dev/null
+++ b/internal/pkg/vendors/cachefly-sdk/client.go
@@ -0,0 +1,79 @@
+package cacheflysdk
+
+import (
+ "encoding/json"
+ "fmt"
+ "net/http"
+ "strings"
+ "time"
+
+ "github.com/go-resty/resty/v2"
+)
+
+type Client struct {
+ apiToken string
+
+ client *resty.Client
+}
+
+func NewClient(apiToken string) *Client {
+ client := resty.New()
+
+ return &Client{
+ apiToken: apiToken,
+ client: client,
+ }
+}
+
+func (c *Client) WithTimeout(timeout time.Duration) *Client {
+ c.client.SetTimeout(timeout)
+ return c
+}
+
+func (c *Client) sendRequest(method string, path string, params interface{}) (*resty.Response, error) {
+ req := c.client.R()
+ req.Method = method
+ req.URL = "https://api.cachefly.com/api/2.5" + path
+ req = req.SetHeader("x-cf-authorization", "Bearer "+c.apiToken)
+ 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)
+ } else {
+ req = req.
+ SetHeader("Content-Type", "application/json").
+ SetBody(params)
+ }
+
+ resp, err := req.Send()
+ if err != nil {
+ return nil, fmt.Errorf("cachefly api error: failed to send request: %w", err)
+ } else if resp.IsError() {
+ return nil, fmt.Errorf("cachefly api error: unexpected status code: %d, %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 {
+ return err
+ }
+
+ if err := json.Unmarshal(resp.Body(), &result); err != nil {
+ return fmt.Errorf("cachefly api error: failed to parse response: %w", err)
+ }
+
+ return nil
+}
diff --git a/internal/pkg/vendors/cachefly-sdk/models.go b/internal/pkg/vendors/cachefly-sdk/models.go
new file mode 100644
index 00000000..aaca7723
--- /dev/null
+++ b/internal/pkg/vendors/cachefly-sdk/models.go
@@ -0,0 +1,35 @@
+package cacheflysdk
+
+type BaseResponse interface {
+ GetMessage() *string
+}
+
+type baseResponse struct {
+ Message *string `json:"message,omitempty"`
+}
+
+func (r *baseResponse) GetMessage() *string {
+ return r.Message
+}
+
+type CreateCertificateRequest struct {
+ Certificate string `json:"certificate"`
+ CertificateKey string `json:"certificateKey"`
+ Password *string `json:"password"`
+}
+
+type CreateCertificateResponse struct {
+ baseResponse
+ Id string `json:"_id"`
+ SubjectCommonName string `json:"subjectCommonName"`
+ SubjectNames []string `json:"subjectNames"`
+ Expired bool `json:"expired"`
+ Expiring bool `json:"expiring"`
+ InUse bool `json:"inUse"`
+ Managed bool `json:"managed"`
+ Services []string `json:"services"`
+ Domains []string `json:"domains"`
+ NotBefore string `json:"notBefore"`
+ NotAfter string `json:"notAfter"`
+ CreatedAt string `json:"createdAt"`
+}
diff --git a/internal/pkg/vendors/cdnfly-sdk/api.go b/internal/pkg/vendors/cdnfly-sdk/api.go
new file mode 100644
index 00000000..211baa33
--- /dev/null
+++ b/internal/pkg/vendors/cdnfly-sdk/api.go
@@ -0,0 +1,42 @@
+package cdnflysdk
+
+import (
+ "fmt"
+ "net/http"
+)
+
+func (c *Client) GetSite(req *GetSiteRequest) (*GetSiteResponse, error) {
+ resp := GetSiteResponse{}
+ err := c.sendRequestWithResult(http.MethodGet, fmt.Sprintf("/v1/sites/%s", req.Id), req, &resp)
+ if err != nil {
+ return nil, err
+ }
+ return &resp, nil
+}
+
+func (c *Client) UpdateSite(req *UpdateSiteRequest) (*UpdateSiteResponse, error) {
+ resp := UpdateSiteResponse{}
+ err := c.sendRequestWithResult(http.MethodPut, fmt.Sprintf("/v1/sites/%s", req.Id), req, &resp)
+ if err != nil {
+ return nil, err
+ }
+ return &resp, nil
+}
+
+func (c *Client) CreateCertificate(req *CreateCertificateRequest) (*CreateCertificateResponse, error) {
+ resp := CreateCertificateResponse{}
+ err := c.sendRequestWithResult(http.MethodPost, "/v1/certs", req, &resp)
+ if err != nil {
+ return nil, err
+ }
+ return &resp, nil
+}
+
+func (c *Client) UpdateCertificate(req *UpdateCertificateRequest) (*UpdateCertificateResponse, error) {
+ resp := UpdateCertificateResponse{}
+ err := c.sendRequestWithResult(http.MethodPut, fmt.Sprintf("/v1/certs/%s", req.Id), req, &resp)
+ if err != nil {
+ return nil, err
+ }
+ return &resp, nil
+}
diff --git a/internal/pkg/vendors/cdnfly-sdk/client.go b/internal/pkg/vendors/cdnfly-sdk/client.go
new file mode 100644
index 00000000..7e2e93f4
--- /dev/null
+++ b/internal/pkg/vendors/cdnfly-sdk/client.go
@@ -0,0 +1,87 @@
+package cdnflysdk
+
+import (
+ "encoding/json"
+ "fmt"
+ "net/http"
+ "strings"
+ "time"
+
+ "github.com/go-resty/resty/v2"
+)
+
+type Client struct {
+ apiHost string
+ apiKey string
+ apiSecret string
+
+ client *resty.Client
+}
+
+func NewClient(apiHost, apiKey, apiSecret string) *Client {
+ client := resty.New()
+
+ return &Client{
+ apiHost: strings.TrimRight(apiHost, "/"),
+ apiKey: apiKey,
+ apiSecret: apiSecret,
+ client: client,
+ }
+}
+
+func (c *Client) WithTimeout(timeout time.Duration) *Client {
+ c.client.SetTimeout(timeout)
+ return c
+}
+
+func (c *Client) sendRequest(method string, path string, params interface{}) (*resty.Response, error) {
+ req := c.client.R()
+ req.Method = method
+ req.URL = c.apiHost + path
+ req = req.
+ SetHeader("api-key", c.apiKey).
+ SetHeader("api-secret", c.apiSecret)
+ 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)
+ } else {
+ req = req.
+ SetHeader("Content-Type", "application/json").
+ SetBody(params)
+ }
+
+ resp, err := req.Send()
+ if err != nil {
+ return nil, fmt.Errorf("cdnfly api error: failed to send request: %w", err)
+ } else if resp.IsError() {
+ return nil, fmt.Errorf("cdnfly api error: unexpected status code: %d, %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 {
+ return err
+ }
+
+ if err := json.Unmarshal(resp.Body(), &result); err != nil {
+ return fmt.Errorf("cdnfly api error: failed to parse response: %w", err)
+ } else if errcode := result.GetCode(); errcode != "" && errcode != "0" {
+ return fmt.Errorf("cdnfly api error: %s - %s", errcode, result.GetMessage())
+ }
+
+ return nil
+}
diff --git a/internal/pkg/vendors/cdnfly-sdk/models.go b/internal/pkg/vendors/cdnfly-sdk/models.go
new file mode 100644
index 00000000..873b80b0
--- /dev/null
+++ b/internal/pkg/vendors/cdnfly-sdk/models.go
@@ -0,0 +1,70 @@
+package cdnflysdk
+
+type BaseResponse interface {
+ GetCode() string
+ GetMessage() string
+}
+
+type baseResponse struct {
+ Code string `json:"code"`
+ Message string `json:"msg"`
+}
+
+func (r *baseResponse) GetCode() string {
+ return r.Code
+}
+
+func (r *baseResponse) GetMessage() string {
+ return r.Message
+}
+
+type GetSiteRequest struct {
+ Id string `json:"-"`
+}
+
+type GetSiteResponse struct {
+ baseResponse
+ Data *struct {
+ Id string `json:"id"`
+ Name string `json:"name"`
+ Domain string `json:"domain"`
+ HttpsListen string `json:"https_listen"`
+ } `json:"data"`
+}
+
+type UpdateSiteRequest struct {
+ Id string `json:"-"`
+ HttpsListen *string `json:"https_listen,omitempty"`
+ Enable *bool `json:"enable,omitempty"`
+}
+
+type UpdateSiteResponse struct {
+ baseResponse
+}
+
+type CreateCertificateRequest struct {
+ Name string `json:"name"`
+ Description *string `json:"des,omitempty"`
+ Type string `json:"type"`
+ Cert string `json:"cert"`
+ Key string `json:"key"`
+}
+
+type CreateCertificateResponse struct {
+ baseResponse
+ Data string `json:"data"`
+}
+
+type UpdateCertificateRequest struct {
+ Id string `json:"-"`
+ Name *string `json:"name,omitempty"`
+ Description *string `json:"des,omitempty"`
+ Type *string `json:"type,omitempty"`
+ Cert *string `json:"cert,omitempty"`
+ Key *string `json:"key,omitempty"`
+ Enable *bool `json:"enable,omitempty"`
+}
+
+type UpdateCertificateResponse struct {
+ baseResponse
+}
diff --git a/internal/pkg/vendors/cmcc-sdk/README.md b/internal/pkg/vendors/cmcc-sdk/README.md
new file mode 100644
index 00000000..c64eebe8
--- /dev/null
+++ b/internal/pkg/vendors/cmcc-sdk/README.md
@@ -0,0 +1,14 @@
+移动云 Go SDK 文档: [https://ecloud.10086.cn/op-help-center/doc/article/53799](https://ecloud.10086.cn/op-help-center/doc/article/53799)
+
+移动云 Go SDK 下载地址: [https://ecloud.10086.cn/api/query/developer/nexus/service/rest/repository/browse/go-sdk/gitlab.ecloud.com/ecloud/](https://ecloud.10086.cn/api/query/developer/nexus/service/rest/repository/browse/go-sdk/gitlab.ecloud.com/ecloud/)
+
+---
+
+将其引入本地目录的原因是:
+
+1. 原始包必须通过移动云私有仓库获取, 为构建带来不便。
+2. 原始包存在部分内容错误, 需要自行修改, 如:
+
+ - 存在一些编译错误;
+ - 返回错误的时候, 未返回错误信息;
+ - 解析响应体错误。
diff --git a/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/client.go b/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/client.go
new file mode 100644
index 00000000..d2c2ccde
--- /dev/null
+++ b/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/client.go
@@ -0,0 +1,144 @@
+// @Title Golang SDK Client
+// @Description This code is auto generated
+// @Author Ecloud SDK
+
+package ecloudsdkclouddns
+
+import (
+ "gitlab.ecloud.com/ecloud/ecloudsdkclouddns/model"
+ "gitlab.ecloud.com/ecloud/ecloudsdkcore"
+ "gitlab.ecloud.com/ecloud/ecloudsdkcore/config"
+)
+
+type Client struct {
+ APIClient *ecloudsdkcore.APIClient
+ config *config.Config
+ httpRequest *ecloudsdkcore.HttpRequest
+}
+
+func NewClient(config *config.Config) *Client {
+ client := &Client{}
+ client.config = config
+ apiClient := ecloudsdkcore.NewAPIClient()
+ httpRequest := ecloudsdkcore.NewDefaultHttpRequest()
+ httpRequest.Product = product
+ httpRequest.Version = version
+ httpRequest.SdkVersion = sdkVersion
+ client.httpRequest = httpRequest
+ client.APIClient = apiClient
+ return client
+}
+
+func NewClientByCustomized(config *config.Config, httpRequest *ecloudsdkcore.HttpRequest) *Client {
+ client := &Client{}
+ client.config = config
+ apiClient := ecloudsdkcore.NewAPIClient()
+ httpRequest.Product = product
+ httpRequest.Version = version
+ httpRequest.SdkVersion = sdkVersion
+ client.httpRequest = httpRequest
+ client.APIClient = apiClient
+ return client
+}
+
+const (
+ product string = "clouddns"
+ version string = "v1"
+ sdkVersion string = "1.0.1"
+)
+
+// CreateRecord 新增解析记录
+func (c *Client) CreateRecord(request *model.CreateRecordRequest) (*model.CreateRecordResponse, error) {
+ c.httpRequest.Action = "createRecord"
+ c.httpRequest.Body = request
+ returnValue := &model.CreateRecordResponse{}
+ if _, err := c.APIClient.Excute(c.httpRequest, c.config, returnValue); err != nil {
+ return nil, err
+ } else {
+ return returnValue, nil
+ }
+}
+
+// CreateRecordOpenapi 新增解析记录Openapi
+func (c *Client) CreateRecordOpenapi(request *model.CreateRecordOpenapiRequest) (*model.CreateRecordOpenapiResponse, error) {
+ c.httpRequest.Action = "createRecordOpenapi"
+ c.httpRequest.Body = request
+ returnValue := &model.CreateRecordOpenapiResponse{}
+ if _, err := c.APIClient.Excute(c.httpRequest, c.config, returnValue); err != nil {
+ return nil, err
+ } else {
+ return returnValue, nil
+ }
+}
+
+// DeleteRecord 删除解析记录
+func (c *Client) DeleteRecord(request *model.DeleteRecordRequest) (*model.DeleteRecordResponse, error) {
+ c.httpRequest.Action = "deleteRecord"
+ c.httpRequest.Body = request
+ returnValue := &model.DeleteRecordResponse{}
+ if _, err := c.APIClient.Excute(c.httpRequest, c.config, returnValue); err != nil {
+ return nil, err
+ } else {
+ return returnValue, nil
+ }
+}
+
+// DeleteRecordOpenapi 删除解析记录Openapi
+func (c *Client) DeleteRecordOpenapi(request *model.DeleteRecordOpenapiRequest) (*model.DeleteRecordOpenapiResponse, error) {
+ c.httpRequest.Action = "deleteRecordOpenapi"
+ c.httpRequest.Body = request
+ returnValue := &model.DeleteRecordOpenapiResponse{}
+ if _, err := c.APIClient.Excute(c.httpRequest, c.config, returnValue); err != nil {
+ return nil, err
+ } else {
+ return returnValue, nil
+ }
+}
+
+// ListRecord 查询解析记录
+func (c *Client) ListRecord(request *model.ListRecordRequest) (*model.ListRecordResponse, error) {
+ c.httpRequest.Action = "listRecord"
+ c.httpRequest.Body = request
+ returnValue := &model.ListRecordResponse{}
+ if _, err := c.APIClient.Excute(c.httpRequest, c.config, returnValue); err != nil {
+ return nil, err
+ } else {
+ return returnValue, nil
+ }
+}
+
+// ListRecordOpenapi 查询解析记录Openapi
+func (c *Client) ListRecordOpenapi(request *model.ListRecordOpenapiRequest) (*model.ListRecordOpenapiResponse, error) {
+ c.httpRequest.Action = "listRecordOpenapi"
+ c.httpRequest.Body = request
+ returnValue := &model.ListRecordOpenapiResponse{}
+ if _, err := c.APIClient.Excute(c.httpRequest, c.config, returnValue); err != nil {
+ return nil, err
+ } else {
+ return returnValue, nil
+ }
+}
+
+// ModifyRecord 修改解析记录
+func (c *Client) ModifyRecord(request *model.ModifyRecordRequest) (*model.ModifyRecordResponse, error) {
+ c.httpRequest.Action = "modifyRecord"
+ c.httpRequest.Body = request
+ returnValue := &model.ModifyRecordResponse{}
+ if _, err := c.APIClient.Excute(c.httpRequest, c.config, returnValue); err != nil {
+ return nil, err
+ } else {
+ return returnValue, nil
+ }
+}
+
+// ModifyRecordOpenapi 修改解析记录Openapi
+func (c *Client) ModifyRecordOpenapi(request *model.ModifyRecordOpenapiRequest) (*model.ModifyRecordOpenapiResponse, error) {
+ c.httpRequest.Action = "modifyRecordOpenapi"
+ c.httpRequest.Body = request
+ returnValue := &model.ModifyRecordOpenapiResponse{}
+ if _, err := c.APIClient.Excute(c.httpRequest, c.config, returnValue); err != nil {
+ return nil, err
+ } else {
+ return returnValue, nil
+ }
+}
diff --git a/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/go.mod b/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/go.mod
new file mode 100644
index 00000000..39812459
--- /dev/null
+++ b/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/go.mod
@@ -0,0 +1,7 @@
+module gitlab.ecloud.com/ecloud/ecloudsdkclouddns
+
+go 1.23.0
+
+require gitlab.ecloud.com/ecloud/ecloudsdkcore v1.0.0
+
+replace gitlab.ecloud.com/ecloud/ecloudsdkcore v1.0.0 => ../ecloudsdkcore@v1.0.0
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
new file mode 100644
index 00000000..1175cde9
--- /dev/null
+++ b/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/create_record_body.go
@@ -0,0 +1,54 @@
+// @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/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/create_record_openapi_body.go
new file mode 100644
index 00000000..3db9f0f7
--- /dev/null
+++ b/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/create_record_openapi_body.go
@@ -0,0 +1,51 @@
+// @Title Golang SDK Client
+// @Description This code is auto generated
+// @Author Ecloud SDK
+
+package model
+
+import (
+ "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"
+)
+
+type CreateRecordOpenapiBody 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 CreateRecordOpenapiBodyTypeEnum `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_request.go b/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/create_record_openapi_request.go
new file mode 100644
index 00000000..d43fded1
--- /dev/null
+++ b/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/create_record_openapi_request.go
@@ -0,0 +1,12 @@
+// @Title Golang SDK Client
+// @Description This code is auto generated
+// @Author Ecloud SDK
+
+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/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/create_record_openapi_response.go
new file mode 100644
index 00000000..a33b47c7
--- /dev/null
+++ b/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/create_record_openapi_response.go
@@ -0,0 +1,29 @@
+// @Title Golang SDK Client
+// @Description This code is auto generated
+// @Author Ecloud SDK
+
+package model
+
+
+type CreateRecordOpenapiResponseStateEnum string
+
+// List of State
+const (
+ 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"`
+
+ ErrorCode string `json:"errorCode,omitempty"`
+
+ State CreateRecordOpenapiResponseStateEnum `json:"state,omitempty"`
+
+ Body *CreateRecordOpenapiResponseBody `json:"body,omitempty"`
+}
diff --git a/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/create_record_openapi_response_body.go b/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/create_record_openapi_response_body.go
new file mode 100644
index 00000000..e7c62769
--- /dev/null
+++ b/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/create_record_openapi_response_body.go
@@ -0,0 +1,80 @@
+// @Title Golang SDK Client
+// @Description This code is auto generated
+// @Author Ecloud SDK
+
+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"
+)
+type CreateRecordOpenapiResponseBodyStateEnum string
+
+// List of State
+const (
+ CreateRecordOpenapiResponseBodyStateEnumDisabled CreateRecordOpenapiResponseBodyStateEnum = "DISABLED"
+ CreateRecordOpenapiResponseBodyStateEnumEnabled CreateRecordOpenapiResponseBodyStateEnum = "ENABLED"
+)
+
+type CreateRecordOpenapiResponseBody struct {
+
+ // 主机头
+ Rr string `json:"rr,omitempty"`
+
+ // 修改时间
+ ModifiedTime string `json:"modifiedTime,omitempty"`
+
+ // 线路中文名
+ LineZh string `json:"lineZh,omitempty"`
+
+ // 备注
+ Description string `json:"description,omitempty"`
+
+ // 线路ID
+ LineId string `json:"lineId,omitempty"`
+
+ // 权重值
+ Weight *int32 `json:"weight,omitempty"`
+
+ // MX优先级
+ MxPri *int32 `json:"mxPri,omitempty"`
+
+ // 记录类型
+ Type CreateRecordOpenapiResponseBodyTypeEnum `json:"type,omitempty"`
+
+ // 缓存的生命周期
+ Ttl *int32 `json:"ttl,omitempty"`
+
+ // 标签
+ Tags *[]CreateRecordOpenapiResponseTags `json:"tags,omitempty"`
+
+ // 解析记录ID
+ RecordId string `json:"recordId,omitempty"`
+
+ // 域名名称
+ DomainName string `json:"domainName,omitempty"`
+
+ // 线路英文名
+ LineEn string `json:"lineEn,omitempty"`
+
+ // 状态
+ State CreateRecordOpenapiResponseBodyStateEnum `json:"state,omitempty"`
+
+ // 记录值
+ Value string `json:"value,omitempty"`
+
+ // 定时发布时间
+ Pubdate string `json:"pubdate,omitempty"`
+}
diff --git a/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/create_record_openapi_response_tags.go b/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/create_record_openapi_response_tags.go
new file mode 100644
index 00000000..a4bda62c
--- /dev/null
+++ b/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/create_record_openapi_response_tags.go
@@ -0,0 +1,16 @@
+// @Title Golang SDK Client
+// @Description This code is auto generated
+// @Author Ecloud SDK
+
+package model
+
+
+
+type CreateRecordOpenapiResponseTags struct {
+
+ // 标签ID
+ TagId string `json:"tagId,omitempty"`
+
+ // 标签名称
+ Value string `json:"value,omitempty"`
+}
diff --git a/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/create_record_request.go b/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/create_record_request.go
new file mode 100644
index 00000000..715f03ff
--- /dev/null
+++ b/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/create_record_request.go
@@ -0,0 +1,12 @@
+// @Title Golang SDK Client
+// @Description This code is auto generated
+// @Author Ecloud SDK
+
+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/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/create_record_response.go
new file mode 100644
index 00000000..bd277c0c
--- /dev/null
+++ b/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/create_record_response.go
@@ -0,0 +1,29 @@
+// @Title Golang SDK Client
+// @Description This code is auto generated
+// @Author Ecloud SDK
+
+package model
+
+
+type CreateRecordResponseStateEnum string
+
+// List of State
+const (
+ 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"`
+
+ ErrorCode string `json:"errorCode,omitempty"`
+
+ State CreateRecordResponseStateEnum `json:"state,omitempty"`
+
+ Body *CreateRecordResponseBody `json:"body,omitempty"`
+}
diff --git a/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/create_record_response_body.go b/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/create_record_response_body.go
new file mode 100644
index 00000000..64660b91
--- /dev/null
+++ b/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/create_record_response_body.go
@@ -0,0 +1,94 @@
+// @Title Golang SDK Client
+// @Description This code is auto generated
+// @Author Ecloud SDK
+
+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"
+)
+type CreateRecordResponseBodyTimedStatusEnum string
+
+// List of TimedStatus
+const (
+ CreateRecordResponseBodyTimedStatusEnumDisabled CreateRecordResponseBodyTimedStatusEnum = "DISABLED"
+ CreateRecordResponseBodyTimedStatusEnumEnabled CreateRecordResponseBodyTimedStatusEnum = "ENABLED"
+ CreateRecordResponseBodyTimedStatusEnumTimed CreateRecordResponseBodyTimedStatusEnum = "TIMED"
+)
+type CreateRecordResponseBodyStateEnum string
+
+// List of State
+const (
+ CreateRecordResponseBodyStateEnumDisabled CreateRecordResponseBodyStateEnum = "DISABLED"
+ CreateRecordResponseBodyStateEnumEnabled CreateRecordResponseBodyStateEnum = "ENABLED"
+)
+
+type CreateRecordResponseBody struct {
+
+ // 主机头
+ Rr string `json:"rr,omitempty"`
+
+ // 修改时间
+ ModifiedTime string `json:"modifiedTime,omitempty"`
+
+ // 线路中文名
+ LineZh string `json:"lineZh,omitempty"`
+
+ // 备注
+ Description string `json:"description,omitempty"`
+
+ // 线路ID
+ LineId string `json:"lineId,omitempty"`
+
+ // 权重值
+ Weight *int32 `json:"weight,omitempty"`
+
+ // MX优先级
+ MxPri *int32 `json:"mxPri,omitempty"`
+
+ // 记录类型
+ Type CreateRecordResponseBodyTypeEnum `json:"type,omitempty"`
+
+ // 缓存的生命周期
+ Ttl *int32 `json:"ttl,omitempty"`
+
+ // 标签
+ Tags *[]CreateRecordResponseTags `json:"tags,omitempty"`
+
+ // 解析记录ID
+ RecordId string `json:"recordId,omitempty"`
+
+ // 定时状态
+ TimedStatus CreateRecordResponseBodyTimedStatusEnum `json:"timedStatus,omitempty"`
+
+ // 域名名称
+ DomainName string `json:"domainName,omitempty"`
+
+ // 线路英文名
+ LineEn string `json:"lineEn,omitempty"`
+
+ // 状态
+ State CreateRecordResponseBodyStateEnum `json:"state,omitempty"`
+
+ // 记录值
+ Value string `json:"value,omitempty"`
+
+ // 定时发布时间
+ Pubdate string `json:"pubdate,omitempty"`
+}
diff --git a/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/create_record_response_tags.go b/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/create_record_response_tags.go
new file mode 100644
index 00000000..003680d5
--- /dev/null
+++ b/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/create_record_response_tags.go
@@ -0,0 +1,16 @@
+// @Title Golang SDK Client
+// @Description This code is auto generated
+// @Author Ecloud SDK
+
+package model
+
+
+
+type CreateRecordResponseTags struct {
+
+ // 标签ID
+ TagId string `json:"tagId,omitempty"`
+
+ // 标签名称
+ Value string `json:"value,omitempty"`
+}
diff --git a/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/delete_record_body.go b/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/delete_record_body.go
new file mode 100644
index 00000000..326b9abb
--- /dev/null
+++ b/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/delete_record_body.go
@@ -0,0 +1,15 @@
+// @Title Golang SDK Client
+// @Description This code is auto generated
+// @Author Ecloud SDK
+
+package model
+
+import (
+ "gitlab.ecloud.com/ecloud/ecloudsdkcore/position"
+)
+
+type DeleteRecordBody struct {
+ 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/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/delete_record_openapi_body.go
new file mode 100644
index 00000000..e5614ac5
--- /dev/null
+++ b/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/delete_record_openapi_body.go
@@ -0,0 +1,15 @@
+// @Title Golang SDK Client
+// @Description This code is auto generated
+// @Author Ecloud SDK
+
+package model
+
+import (
+ "gitlab.ecloud.com/ecloud/ecloudsdkcore/position"
+)
+
+type DeleteRecordOpenapiBody struct {
+ 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/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/delete_record_openapi_request.go
new file mode 100644
index 00000000..1cb684d6
--- /dev/null
+++ b/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/delete_record_openapi_request.go
@@ -0,0 +1,12 @@
+// @Title Golang SDK Client
+// @Description This code is auto generated
+// @Author Ecloud SDK
+
+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/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/delete_record_openapi_response.go
new file mode 100644
index 00000000..ca528148
--- /dev/null
+++ b/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/delete_record_openapi_response.go
@@ -0,0 +1,29 @@
+// @Title Golang SDK Client
+// @Description This code is auto generated
+// @Author Ecloud SDK
+
+package model
+
+
+type DeleteRecordOpenapiResponseStateEnum string
+
+// List of State
+const (
+ 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"`
+
+ ErrorCode string `json:"errorCode,omitempty"`
+
+ State DeleteRecordOpenapiResponseStateEnum `json:"state,omitempty"`
+
+ Body *[]DeleteRecordOpenapiResponseBody `json:"body,omitempty"`
+}
diff --git a/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/delete_record_openapi_response_body.go b/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/delete_record_openapi_response_body.go
new file mode 100644
index 00000000..67da3ab7
--- /dev/null
+++ b/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/delete_record_openapi_response_body.go
@@ -0,0 +1,29 @@
+// @Title Golang SDK Client
+// @Description This code is auto generated
+// @Author Ecloud SDK
+
+package model
+
+
+type DeleteRecordOpenapiResponseBodyCodeEnum string
+
+// List of Code
+const (
+ DeleteRecordOpenapiResponseBodyCodeEnumError DeleteRecordOpenapiResponseBodyCodeEnum = "ERROR"
+ DeleteRecordOpenapiResponseBodyCodeEnumSuccess DeleteRecordOpenapiResponseBodyCodeEnum = "SUCCESS"
+)
+
+type DeleteRecordOpenapiResponseBody struct {
+
+ // 结果说明
+ Msg string `json:"msg,omitempty"`
+
+ // 解析记录ID
+ RecordId string `json:"recordId,omitempty"`
+
+ // 结果码
+ Code DeleteRecordOpenapiResponseBodyCodeEnum `json:"code,omitempty"`
+
+ // 域名
+ DomainName string `json:"domainName,omitempty"`
+}
diff --git a/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/delete_record_request.go b/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/delete_record_request.go
new file mode 100644
index 00000000..678fd8ef
--- /dev/null
+++ b/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/delete_record_request.go
@@ -0,0 +1,12 @@
+// @Title Golang SDK Client
+// @Description This code is auto generated
+// @Author Ecloud SDK
+
+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/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/delete_record_response.go
new file mode 100644
index 00000000..051d7105
--- /dev/null
+++ b/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/delete_record_response.go
@@ -0,0 +1,29 @@
+// @Title Golang SDK Client
+// @Description This code is auto generated
+// @Author Ecloud SDK
+
+package model
+
+
+type DeleteRecordResponseStateEnum string
+
+// List of State
+const (
+ 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"`
+
+ ErrorCode string `json:"errorCode,omitempty"`
+
+ State DeleteRecordResponseStateEnum `json:"state,omitempty"`
+
+ Body *[]DeleteRecordResponseBody `json:"body,omitempty"`
+}
diff --git a/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/delete_record_response_body.go b/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/delete_record_response_body.go
new file mode 100644
index 00000000..45320290
--- /dev/null
+++ b/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/delete_record_response_body.go
@@ -0,0 +1,29 @@
+// @Title Golang SDK Client
+// @Description This code is auto generated
+// @Author Ecloud SDK
+
+package model
+
+
+type DeleteRecordResponseBodyCodeEnum string
+
+// List of Code
+const (
+ DeleteRecordResponseBodyCodeEnumError DeleteRecordResponseBodyCodeEnum = "ERROR"
+ DeleteRecordResponseBodyCodeEnumSuccess DeleteRecordResponseBodyCodeEnum = "SUCCESS"
+)
+
+type DeleteRecordResponseBody struct {
+
+ // 结果说明
+ Msg string `json:"msg,omitempty"`
+
+ // 解析记录ID
+ RecordId string `json:"recordId,omitempty"`
+
+ // 结果码
+ Code DeleteRecordResponseBodyCodeEnum `json:"code,omitempty"`
+
+ // 域名
+ DomainName string `json:"domainName,omitempty"`
+}
diff --git a/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/list_record_body.go b/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/list_record_body.go
new file mode 100644
index 00000000..5eadce7a
--- /dev/null
+++ b/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/list_record_body.go
@@ -0,0 +1,18 @@
+// @Title Golang SDK Client
+// @Description This code is auto generated
+// @Author Ecloud SDK
+
+package model
+
+import (
+ "gitlab.ecloud.com/ecloud/ecloudsdkcore/position"
+)
+
+type ListRecordBody struct {
+ position.Body
+ // 域名
+ DomainName string `json:"domainName"`
+
+ // 可以匹配主机头rr、记录值value、备注description,并且是模糊搜索
+ DataLike string `json:"dataLike,omitempty"`
+}
diff --git a/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/list_record_openapi_body.go b/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/list_record_openapi_body.go
new file mode 100644
index 00000000..63f5e13a
--- /dev/null
+++ b/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/list_record_openapi_body.go
@@ -0,0 +1,15 @@
+// @Title Golang SDK Client
+// @Description This code is auto generated
+// @Author Ecloud SDK
+
+package model
+
+import (
+ "gitlab.ecloud.com/ecloud/ecloudsdkcore/position"
+)
+
+type ListRecordOpenapiBody struct {
+ 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/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/list_record_openapi_query.go
new file mode 100644
index 00000000..ee89a7f5
--- /dev/null
+++ b/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/list_record_openapi_query.go
@@ -0,0 +1,18 @@
+// @Title Golang SDK Client
+// @Description This code is auto generated
+// @Author Ecloud SDK
+
+package model
+
+import (
+ "gitlab.ecloud.com/ecloud/ecloudsdkcore/position"
+)
+
+type ListRecordOpenapiQuery struct {
+ position.Query
+ // 页大小
+ PageSize *int32 `json:"pageSize,omitempty"`
+
+ // 当前页
+ Page *int32 `json:"page,omitempty"`
+}
diff --git a/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/list_record_openapi_request.go b/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/list_record_openapi_request.go
new file mode 100644
index 00000000..34540481
--- /dev/null
+++ b/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/list_record_openapi_request.go
@@ -0,0 +1,14 @@
+// @Title Golang SDK Client
+// @Description This code is auto generated
+// @Author Ecloud SDK
+
+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/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/list_record_openapi_response.go
new file mode 100644
index 00000000..36646938
--- /dev/null
+++ b/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/list_record_openapi_response.go
@@ -0,0 +1,29 @@
+// @Title Golang SDK Client
+// @Description This code is auto generated
+// @Author Ecloud SDK
+
+package model
+
+
+type ListRecordOpenapiResponseStateEnum string
+
+// List of State
+const (
+ 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"`
+
+ ErrorCode string `json:"errorCode,omitempty"`
+
+ State ListRecordOpenapiResponseStateEnum `json:"state,omitempty"`
+
+ Body *ListRecordOpenapiResponseBody `json:"body,omitempty"`
+}
diff --git a/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/list_record_openapi_response_body.go b/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/list_record_openapi_response_body.go
new file mode 100644
index 00000000..8c6f7302
--- /dev/null
+++ b/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/list_record_openapi_response_body.go
@@ -0,0 +1,25 @@
+// @Title Golang SDK Client
+// @Description This code is auto generated
+// @Author Ecloud SDK
+
+package model
+
+
+
+type ListRecordOpenapiResponseBody struct {
+
+ // 当前页的具体数据列表
+ Data *[]ListRecordOpenapiResponseData `json:"data,omitempty"`
+
+ // 总数据量
+ TotalNum *int32 `json:"totalNum,omitempty"`
+
+ // 总页数
+ TotalPages *int32 `json:"totalPages,omitempty"`
+
+ // 页大小
+ PageSize *int32 `json:"pageSize,omitempty"`
+
+ // 当前页码,从0开始,0表示第一页
+ Page *int32 `json:"page,omitempty"`
+}
diff --git a/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/list_record_openapi_response_data.go b/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/list_record_openapi_response_data.go
new file mode 100644
index 00000000..19981aa9
--- /dev/null
+++ b/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/list_record_openapi_response_data.go
@@ -0,0 +1,91 @@
+// @Title Golang SDK Client
+// @Description This code is auto generated
+// @Author Ecloud SDK
+
+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"
+)
+type ListRecordOpenapiResponseDataTimedStatusEnum string
+
+// List of TimedStatus
+const (
+ ListRecordOpenapiResponseDataTimedStatusEnumDisabled ListRecordOpenapiResponseDataTimedStatusEnum = "DISABLED"
+ ListRecordOpenapiResponseDataTimedStatusEnumEnabled ListRecordOpenapiResponseDataTimedStatusEnum = "ENABLED"
+ ListRecordOpenapiResponseDataTimedStatusEnumTimed ListRecordOpenapiResponseDataTimedStatusEnum = "TIMED"
+)
+type ListRecordOpenapiResponseDataStateEnum string
+
+// List of State
+const (
+ ListRecordOpenapiResponseDataStateEnumDisabled ListRecordOpenapiResponseDataStateEnum = "DISABLED"
+ ListRecordOpenapiResponseDataStateEnumEnabled ListRecordOpenapiResponseDataStateEnum = "ENABLED"
+)
+
+type ListRecordOpenapiResponseData struct {
+
+ // 主机头
+ Rr string `json:"rr,omitempty"`
+
+ // 修改时间
+ ModifiedTime string `json:"modifiedTime,omitempty"`
+
+ // 线路中文名
+ LineZh string `json:"lineZh,omitempty"`
+
+ // 备注
+ Description string `json:"description,omitempty"`
+
+ // 线路ID
+ LineId string `json:"lineId,omitempty"`
+
+ // 权重值
+ Weight *int32 `json:"weight,omitempty"`
+
+ // MX优先级
+ MxPri *int32 `json:"mxPri,omitempty"`
+
+ // 记录类型
+ Type ListRecordOpenapiResponseDataTypeEnum `json:"type,omitempty"`
+
+ // 缓存的生命周期
+ Ttl *int32 `json:"ttl,omitempty"`
+
+ // 标签
+ Tags *[]ListRecordOpenapiResponseTags `json:"tags,omitempty"`
+
+ // 解析记录ID
+ RecordId string `json:"recordId,omitempty"`
+
+ // 定时状态
+ TimedStatus ListRecordOpenapiResponseDataTimedStatusEnum `json:"timedStatus,omitempty"`
+
+ // 域名名称
+ DomainName string `json:"domainName,omitempty"`
+
+ // 线路英文名
+ LineEn string `json:"lineEn,omitempty"`
+
+ // 状态
+ State ListRecordOpenapiResponseDataStateEnum `json:"state,omitempty"`
+
+ // 记录值
+ Value string `json:"value,omitempty"`
+
+ // 定时发布时间
+ Pubdate string `json:"pubdate,omitempty"`
+}
diff --git a/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/list_record_openapi_response_tags.go b/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/list_record_openapi_response_tags.go
new file mode 100644
index 00000000..867f667f
--- /dev/null
+++ b/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/list_record_openapi_response_tags.go
@@ -0,0 +1,16 @@
+// @Title Golang SDK Client
+// @Description This code is auto generated
+// @Author Ecloud SDK
+
+package model
+
+
+
+type ListRecordOpenapiResponseTags struct {
+
+ // 标签ID
+ TagId string `json:"tagId,omitempty"`
+
+ // 标签名称
+ Value string `json:"value,omitempty"`
+}
diff --git a/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/list_record_query.go b/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/list_record_query.go
new file mode 100644
index 00000000..df871a76
--- /dev/null
+++ b/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/list_record_query.go
@@ -0,0 +1,18 @@
+// @Title Golang SDK Client
+// @Description This code is auto generated
+// @Author Ecloud SDK
+
+package model
+
+import (
+ "gitlab.ecloud.com/ecloud/ecloudsdkcore/position"
+)
+
+type ListRecordQuery struct {
+ position.Query
+ // 页大小
+ PageSize *int32 `json:"pageSize,omitempty"`
+
+ // 当前页
+ CurrentPage *int32 `json:"currentPage,omitempty"`
+}
diff --git a/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/list_record_request.go b/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/list_record_request.go
new file mode 100644
index 00000000..5ff9df08
--- /dev/null
+++ b/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/list_record_request.go
@@ -0,0 +1,14 @@
+// @Title Golang SDK Client
+// @Description This code is auto generated
+// @Author Ecloud SDK
+
+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/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/list_record_response.go
new file mode 100644
index 00000000..b11f3d21
--- /dev/null
+++ b/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/list_record_response.go
@@ -0,0 +1,29 @@
+// @Title Golang SDK Client
+// @Description This code is auto generated
+// @Author Ecloud SDK
+
+package model
+
+
+type ListRecordResponseStateEnum string
+
+// List of State
+const (
+ 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"`
+
+ ErrorCode string `json:"errorCode,omitempty"`
+
+ State ListRecordResponseStateEnum `json:"state,omitempty"`
+
+ Body *ListRecordResponseBody `json:"body,omitempty"`
+}
diff --git a/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/list_record_response_body.go b/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/list_record_response_body.go
new file mode 100644
index 00000000..0acf543d
--- /dev/null
+++ b/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/list_record_response_body.go
@@ -0,0 +1,22 @@
+// @Title Golang SDK Client
+// @Description This code is auto generated
+// @Author Ecloud SDK
+
+package model
+
+
+
+type ListRecordResponseBody struct {
+
+ // 总页数
+ TotalPages *int32 `json:"totalPages,omitempty"`
+
+ // 当前页码,从0开始,0表示第一页
+ CurrentPage *int32 `json:"currentPage,omitempty"`
+
+ // 当前页的具体数据列表
+ Results *[]ListRecordResponseResults `json:"results,omitempty"`
+
+ // 总数据量
+ TotalElements *int64 `json:"totalElements,omitempty"`
+}
diff --git a/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/list_record_response_results.go b/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/list_record_response_results.go
new file mode 100644
index 00000000..7498fca3
--- /dev/null
+++ b/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/list_record_response_results.go
@@ -0,0 +1,91 @@
+// @Title Golang SDK Client
+// @Description This code is auto generated
+// @Author Ecloud SDK
+
+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"
+)
+type ListRecordResponseResultsTimedStatusEnum string
+
+// List of TimedStatus
+const (
+ ListRecordResponseResultsTimedStatusEnumDisabled ListRecordResponseResultsTimedStatusEnum = "DISABLED"
+ ListRecordResponseResultsTimedStatusEnumEnabled ListRecordResponseResultsTimedStatusEnum = "ENABLED"
+ ListRecordResponseResultsTimedStatusEnumTimed ListRecordResponseResultsTimedStatusEnum = "TIMED"
+)
+type ListRecordResponseResultsStateEnum string
+
+// List of State
+const (
+ ListRecordResponseResultsStateEnumDisabled ListRecordResponseResultsStateEnum = "DISABLED"
+ ListRecordResponseResultsStateEnumEnabled ListRecordResponseResultsStateEnum = "ENABLED"
+)
+
+type ListRecordResponseResults struct {
+
+ // 主机头
+ Rr string `json:"rr,omitempty"`
+
+ // 修改时间
+ ModifiedTime string `json:"modifiedTime,omitempty"`
+
+ // 线路中文名
+ LineZh string `json:"lineZh,omitempty"`
+
+ // 备注
+ Description string `json:"description,omitempty"`
+
+ // 线路ID
+ LineId string `json:"lineId,omitempty"`
+
+ // 权重值
+ Weight *int32 `json:"weight,omitempty"`
+
+ // MX优先级
+ MxPri *int32 `json:"mxPri,omitempty"`
+
+ // 记录类型
+ Type ListRecordResponseResultsTypeEnum `json:"type,omitempty"`
+
+ // 缓存的生命周期
+ Ttl *int32 `json:"ttl,omitempty"`
+
+ // 解析记录ID
+ RecordId string `json:"recordId,omitempty"`
+
+ // 定时状态
+ TimedStatus ListRecordResponseResultsTimedStatusEnum `json:"timedStatus,omitempty"`
+
+ // 域名名称
+ DomainName string `json:"domainName,omitempty"`
+
+ // 线路英文名
+ LineEn string `json:"lineEn,omitempty"`
+
+ // 状态
+ State ListRecordResponseResultsStateEnum `json:"state,omitempty"`
+
+ // 记录值
+ Value string `json:"value,omitempty"`
+
+ // 定时发布时间
+ Pubdate string `json:"pubdate,omitempty"`
+}
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
new file mode 100644
index 00000000..ab772c09
--- /dev/null
+++ b/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/modify_record_body.go
@@ -0,0 +1,57 @@
+// @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/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/modify_record_openapi_body.go
new file mode 100644
index 00000000..3bde8919
--- /dev/null
+++ b/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/modify_record_openapi_body.go
@@ -0,0 +1,54 @@
+// @Title Golang SDK Client
+// @Description This code is auto generated
+// @Author Ecloud SDK
+
+package model
+
+import (
+ "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"
+)
+
+type ModifyRecordOpenapiBody 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 ModifyRecordOpenapiBodyTypeEnum `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_request.go b/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/modify_record_openapi_request.go
new file mode 100644
index 00000000..fd1ffe00
--- /dev/null
+++ b/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/modify_record_openapi_request.go
@@ -0,0 +1,12 @@
+// @Title Golang SDK Client
+// @Description This code is auto generated
+// @Author Ecloud SDK
+
+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/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/modify_record_openapi_response.go
new file mode 100644
index 00000000..97d7552f
--- /dev/null
+++ b/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/modify_record_openapi_response.go
@@ -0,0 +1,29 @@
+// @Title Golang SDK Client
+// @Description This code is auto generated
+// @Author Ecloud SDK
+
+package model
+
+
+type ModifyRecordOpenapiResponseStateEnum string
+
+// List of State
+const (
+ 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"`
+
+ ErrorCode string `json:"errorCode,omitempty"`
+
+ State ModifyRecordOpenapiResponseStateEnum `json:"state,omitempty"`
+
+ Body *ModifyRecordOpenapiResponseBody `json:"body,omitempty"`
+}
diff --git a/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/modify_record_openapi_response_body.go b/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/modify_record_openapi_response_body.go
new file mode 100644
index 00000000..6dfcec71
--- /dev/null
+++ b/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/modify_record_openapi_response_body.go
@@ -0,0 +1,91 @@
+// @Title Golang SDK Client
+// @Description This code is auto generated
+// @Author Ecloud SDK
+
+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"
+)
+type ModifyRecordOpenapiResponseBodyTimedStatusEnum string
+
+// List of TimedStatus
+const (
+ ModifyRecordOpenapiResponseBodyTimedStatusEnumDisabled ModifyRecordOpenapiResponseBodyTimedStatusEnum = "DISABLED"
+ ModifyRecordOpenapiResponseBodyTimedStatusEnumEnabled ModifyRecordOpenapiResponseBodyTimedStatusEnum = "ENABLED"
+ ModifyRecordOpenapiResponseBodyTimedStatusEnumTimed ModifyRecordOpenapiResponseBodyTimedStatusEnum = "TIMED"
+)
+type ModifyRecordOpenapiResponseBodyStateEnum string
+
+// List of State
+const (
+ ModifyRecordOpenapiResponseBodyStateEnumDisabled ModifyRecordOpenapiResponseBodyStateEnum = "DISABLED"
+ ModifyRecordOpenapiResponseBodyStateEnumEnabled ModifyRecordOpenapiResponseBodyStateEnum = "ENABLED"
+)
+
+type ModifyRecordOpenapiResponseBody struct {
+
+ // 主机头
+ Rr string `json:"rr,omitempty"`
+
+ // 修改时间
+ ModifiedTime string `json:"modifiedTime,omitempty"`
+
+ // 线路中文名
+ LineZh string `json:"lineZh,omitempty"`
+
+ // 备注
+ Description string `json:"description,omitempty"`
+
+ // 线路ID
+ LineId string `json:"lineId,omitempty"`
+
+ // 权重值
+ Weight *int32 `json:"weight,omitempty"`
+
+ // MX优先级
+ MxPri *int32 `json:"mxPri,omitempty"`
+
+ // 记录类型
+ Type ModifyRecordOpenapiResponseBodyTypeEnum `json:"type,omitempty"`
+
+ // 缓存的生命周期
+ Ttl *int32 `json:"ttl,omitempty"`
+
+ // 标签
+ Tags *[]ModifyRecordOpenapiResponseTags `json:"tags,omitempty"`
+
+ // 解析记录ID
+ RecordId string `json:"recordId,omitempty"`
+
+ // 定时状态
+ TimedStatus ModifyRecordOpenapiResponseBodyTimedStatusEnum `json:"timedStatus,omitempty"`
+
+ // 域名名称
+ DomainName string `json:"domainName,omitempty"`
+
+ // 线路英文名
+ LineEn string `json:"lineEn,omitempty"`
+
+ // 状态
+ State ModifyRecordOpenapiResponseBodyStateEnum `json:"state,omitempty"`
+
+ // 记录值
+ Value string `json:"value,omitempty"`
+
+ // 定时发布时间
+ Pubdate string `json:"pubdate,omitempty"`
+}
diff --git a/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/modify_record_openapi_response_tags.go b/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/modify_record_openapi_response_tags.go
new file mode 100644
index 00000000..62c2e780
--- /dev/null
+++ b/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/modify_record_openapi_response_tags.go
@@ -0,0 +1,16 @@
+// @Title Golang SDK Client
+// @Description This code is auto generated
+// @Author Ecloud SDK
+
+package model
+
+
+
+type ModifyRecordOpenapiResponseTags struct {
+
+ // 标签ID
+ TagId string `json:"tagId,omitempty"`
+
+ // 标签名称
+ Value string `json:"value,omitempty"`
+}
diff --git a/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/modify_record_request.go b/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/modify_record_request.go
new file mode 100644
index 00000000..d92abb44
--- /dev/null
+++ b/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/modify_record_request.go
@@ -0,0 +1,12 @@
+// @Title Golang SDK Client
+// @Description This code is auto generated
+// @Author Ecloud SDK
+
+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/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/modify_record_response.go
new file mode 100644
index 00000000..45b1ae0f
--- /dev/null
+++ b/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/modify_record_response.go
@@ -0,0 +1,29 @@
+// @Title Golang SDK Client
+// @Description This code is auto generated
+// @Author Ecloud SDK
+
+package model
+
+
+type ModifyRecordResponseStateEnum string
+
+// List of State
+const (
+ 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"`
+
+ ErrorCode string `json:"errorCode,omitempty"`
+
+ State ModifyRecordResponseStateEnum `json:"state,omitempty"`
+
+ Body *ModifyRecordResponseBody `json:"body,omitempty"`
+}
diff --git a/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/modify_record_response_body.go b/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/modify_record_response_body.go
new file mode 100644
index 00000000..3df09342
--- /dev/null
+++ b/internal/pkg/vendors/cmcc-sdk/ecloudsdkclouddns@v1.0.1/model/modify_record_response_body.go
@@ -0,0 +1,77 @@
+// @Title Golang SDK Client
+// @Description This code is auto generated
+// @Author Ecloud SDK
+
+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"
+)
+type ModifyRecordResponseBodyStateEnum string
+
+// List of State
+const (
+ ModifyRecordResponseBodyStateEnumDisabled ModifyRecordResponseBodyStateEnum = "DISABLED"
+ ModifyRecordResponseBodyStateEnumEnabled ModifyRecordResponseBodyStateEnum = "ENABLED"
+)
+
+type ModifyRecordResponseBody struct {
+
+ // 主机头
+ Rr string `json:"rr,omitempty"`
+
+ // 修改时间
+ ModifiedTime string `json:"modifiedTime,omitempty"`
+
+ // 线路中文名
+ LineZh string `json:"lineZh,omitempty"`
+
+ // 备注
+ Description string `json:"description,omitempty"`
+
+ // 线路ID
+ LineId string `json:"lineId,omitempty"`
+
+ // 权重值
+ Weight *int32 `json:"weight,omitempty"`
+
+ // MX优先级
+ MxPri *int32 `json:"mxPri,omitempty"`
+
+ // 记录类型
+ Type ModifyRecordResponseBodyTypeEnum `json:"type,omitempty"`
+
+ // 缓存的生命周期
+ Ttl *int32 `json:"ttl,omitempty"`
+
+ // 解析记录ID
+ RecordId string `json:"recordId,omitempty"`
+
+ // 域名名称
+ DomainName string `json:"domainName,omitempty"`
+
+ // 线路英文名
+ LineEn string `json:"lineEn,omitempty"`
+
+ // 状态
+ State ModifyRecordResponseBodyStateEnum `json:"state,omitempty"`
+
+ // 记录值
+ Value string `json:"value,omitempty"`
+}
diff --git a/internal/pkg/vendors/cmcc-sdk/ecloudsdkcore@v1.0.0/api_client.go b/internal/pkg/vendors/cmcc-sdk/ecloudsdkcore@v1.0.0/api_client.go
new file mode 100644
index 00000000..8f73b499
--- /dev/null
+++ b/internal/pkg/vendors/cmcc-sdk/ecloudsdkcore@v1.0.0/api_client.go
@@ -0,0 +1,507 @@
+package ecloudsdkcore
+
+import (
+ "bytes"
+ "encoding/json"
+ "encoding/xml"
+ "errors"
+ "fmt"
+ "gitlab.ecloud.com/ecloud/ecloudsdkcore/config"
+ "io"
+ "io/ioutil"
+ "mime/multipart"
+ "net/http"
+ "net/url"
+ "os"
+ "path/filepath"
+ "reflect"
+ "regexp"
+ "strconv"
+ "strings"
+ "time"
+ "unicode/utf8"
+)
+
+var (
+ jsonCheck = regexp.MustCompile("(?i:(?:application|text)/json)")
+ xmlCheck = regexp.MustCompile("(?i:(?:application|text)/xml)")
+)
+
+// APIClient manages communication
+// In most cases there should be only one, shared, APIClient.
+type APIClient struct {
+ cfg *Configuration
+ common service
+}
+
+type service struct {
+ client *APIClient
+}
+
+type HttpRequestPosition string
+
+const (
+ BODY HttpRequestPosition = "Body"
+ QUERY HttpRequestPosition = "Query"
+ PATH HttpRequestPosition = "Path"
+ HEADER HttpRequestPosition = "Header"
+)
+
+const SdkPortalUrl = "/op-apim-portal/apim/request/sdk"
+const SdkPortalGatewayUrl = "/api/query/openapi/apim/request/sdk"
+
+// NewAPIClient creates a new API client.
+func NewAPIClient() *APIClient {
+ cfg := NewConfiguration()
+ if cfg.HTTPClient == nil {
+ cfg.HTTPClient = http.DefaultClient
+ }
+ c := &APIClient{}
+ c.cfg = cfg
+ c.common.client = c
+ return c
+}
+
+// atoi string to int
+func atoi(in string) (int, error) {
+ return strconv.Atoi(in)
+}
+
+// selectHeaderContentType select a content type from the available list.
+func selectHeaderContentType(contentTypes []string) string {
+ if len(contentTypes) == 0 {
+ return ""
+ }
+ if contains(contentTypes, "application/json") {
+ return "application/json"
+ }
+ return contentTypes[0]
+}
+
+// selectHeaderAccept join all accept types and return
+func selectHeaderAccept(accepts []string) string {
+ if len(accepts) == 0 {
+ return ""
+ }
+
+ if contains(accepts, "application/json") {
+ return "application/json"
+ }
+
+ return strings.Join(accepts, ",")
+}
+
+// contains is a case insenstive match, finding needle in a haystack
+func contains(haystack []string, needle string) bool {
+ for _, a := range haystack {
+ if strings.ToLower(a) == strings.ToLower(needle) {
+ return true
+ }
+ }
+ return false
+}
+
+// Verify optional parameters are of the correct type.
+func typeCheckParameter(obj interface{}, expected string, name string) error {
+ if obj == nil {
+ return nil
+ }
+ if reflect.TypeOf(obj).String() != expected {
+ return fmt.Errorf("Expected %s to be of type %s but received %s.", name, expected, reflect.TypeOf(obj).String())
+ }
+ return nil
+}
+
+// parameterToString convert interface{} parameters to string, using a delimiter if format is provided.
+func parameterToString(obj interface{}, collectionFormat string, request HttpRequest) (*http.Request, string) {
+ var delimiter string
+
+ switch collectionFormat {
+ case "pipes":
+ delimiter = "|"
+ case "ssv":
+ delimiter = " "
+ case "tsv":
+ delimiter = "\t"
+ case "csv":
+ delimiter = ","
+ }
+
+ if reflect.TypeOf(obj).Kind() == reflect.Slice {
+ return nil, strings.Trim(strings.Replace(fmt.Sprint(obj), " ", delimiter, -1), "[]")
+ }
+
+ return nil, fmt.Sprintf("%v", obj)
+}
+
+// Excute entry for http call
+func (c *APIClient) Excute(httpRequest *HttpRequest, config *config.Config, returnType interface{}) (*http.Response, error) {
+ httpRequest = buildHttpRequest(httpRequest, config)
+ request := buildCall(httpRequest)
+ httpResponse, err := c.callAPI(request)
+ if err != nil || httpResponse == nil {
+ return nil, err
+ }
+
+ responseBody, err := ioutil.ReadAll(httpResponse.Body)
+ httpResponse.Body.Close()
+ if err != nil {
+ return httpResponse, err
+ }
+
+ if httpResponse.StatusCode < 300 {
+ // If we succeed, return the data, otherwise pass on to decode error.
+ err = c.decode(&returnType, responseBody, httpResponse.Header.Get("Content-Type"))
+ if err != nil {
+ return httpResponse, fmt.Errorf("%w, response body is: %s", err, string(responseBody))
+ }
+ return httpResponse, nil
+ }
+
+ if httpResponse.StatusCode >= 300 {
+ newErr := GenericResponseError{
+ body: responseBody,
+ error: httpResponse.Status,
+ }
+ return httpResponse, newErr
+ }
+ return httpResponse, err
+}
+
+// callAPI do the request.
+func (c *APIClient) callAPI(request *http.Request) (*http.Response, error) {
+ return c.cfg.HTTPClient.Do(request)
+}
+
+// ChangeBasePath Change base path to allow switching to mocks
+func (c *APIClient) ChangeBasePath(path string) {
+ c.cfg.BasePath = path
+}
+
+// buildHttpRequest build the request
+func buildHttpRequest(httpRequest *HttpRequest, config *config.Config) *HttpRequest {
+ openApiRequest := &OpenApiRequest{
+ AccessKey: config.AccessKey,
+ SecretKey: config.SecretKey,
+ PoolId: config.PoolId,
+ Api: httpRequest.Action,
+ Product: httpRequest.Product,
+ Version: httpRequest.Version,
+ SdkVersion: httpRequest.SdkVersion,
+ Language: "Golang",
+ }
+ if httpRequest.Body != nil {
+ reqType := reflect.TypeOf(httpRequest.Body)
+ if reqType.Kind() == reflect.Ptr {
+ reqType = reqType.Elem()
+ }
+ v := reflect.ValueOf(httpRequest.Body)
+ if v.Kind() == reflect.Ptr {
+ v = v.Elem()
+ }
+ var flag = false
+ for i := 0; i < reqType.NumField(); i++ {
+ fieldType := reqType.Field(i)
+ value := v.FieldByName(fieldType.Name)
+ if value.Kind() == reflect.Ptr {
+ if value.IsNil() {
+ continue
+ }
+ value = value.Elem()
+
+ }
+ propertyType := fieldType.Type
+ if propertyType.Kind() == reflect.Ptr {
+ propertyType = propertyType.Elem()
+ }
+
+ _, flag = propertyType.FieldByName(string(BODY))
+ if flag {
+ openApiRequest.BodyParameter = value.Interface()
+ continue
+ }
+ _, flag = propertyType.FieldByName(string(HEADER))
+ if flag {
+ openApiRequest.HeaderParameter = structToMap(value.Interface())
+ continue
+ }
+ _, flag = propertyType.FieldByName(string(QUERY))
+ if flag {
+ openApiRequest.QueryParameter = structToMap(value.Interface())
+ continue
+ }
+ _, flag = propertyType.FieldByName(string(PATH))
+ if flag {
+ openApiRequest.PathParameter = structToMap(value.Interface())
+ continue
+ }
+ }
+ }
+ headers := make(map[string]interface{})
+ if httpRequest.HeaderParams != nil {
+ if openApiRequest.HeaderParameter == nil {
+ headers = httpRequest.HeaderParams
+ } else {
+ headers = mergeMap(openApiRequest.HeaderParameter, httpRequest.HeaderParams)
+ }
+ openApiRequest.HeaderParameter = headers
+ }
+ httpRequest.Body = openApiRequest
+ return httpRequest
+}
+
+// mergeMap merge the two map results
+func mergeMap(mObj ...map[string]interface{}) map[string]interface{} {
+ newMap := map[string]interface{}{}
+ for _, m := range mObj {
+ for k, v := range m {
+ newMap[k] = v
+ }
+ }
+ return newMap
+}
+
+// structToMap struct convert to map
+func structToMap(value interface{}) map[string]interface{} {
+ data, _ := json.Marshal(value)
+ result := make(map[string]interface{})
+ json.Unmarshal(data, &result)
+ return result
+}
+
+func buildCall(httpRequest *HttpRequest) (request *http.Request) {
+ var url = ""
+ if len(httpRequest.Url) > 0 {
+ url = httpRequest.Url + SdkPortalUrl
+ } else {
+ url = httpRequest.DefaultUrl + SdkPortalGatewayUrl
+ }
+ request, _ = prepareRequest(url, "POST", httpRequest.Body)
+ return request
+}
+
+// prepareRequest build the 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)
+ body, err = setBody(postBody, contentType)
+ if err != nil {
+ return nil, err
+ }
+ }
+
+ // Setup path and query parameters
+ url, err := url.Parse(path)
+ if err != nil {
+ return nil, err
+ }
+
+ // Generate a new request
+ if body != nil {
+ httpRequest, err = http.NewRequest(method, url.String(), body)
+ } else {
+ httpRequest, err = http.NewRequest(method, url.String(), nil)
+ }
+ if err != nil {
+ return nil, err
+ }
+
+ // add default header parameters
+ httpRequest.Header.Add("Content-Type", "application/json")
+ return httpRequest, nil
+}
+
+func (c *APIClient) decode(v interface{}, b []byte, contentType string) (err error) {
+ if strings.Contains(contentType, "application/xml") {
+ if err = xml.Unmarshal(b, v); err != nil {
+ return err
+ }
+ return nil
+ } else if strings.Contains(contentType, "application/json") {
+ platformResponse := &APIPlatformResponse{}
+ if err = json.Unmarshal(b, platformResponse); err != nil {
+ newErr := GenericResponseError{
+ body: b,
+ error: err.Error(),
+ }
+ return newErr
+ }
+ platformResponseBodyBytes, _ := json.Marshal(platformResponse.Body)
+ platformResponseBody := &APIPlatformResponseBody{}
+ if err = json.Unmarshal(platformResponseBodyBytes, platformResponseBody); err != nil {
+ return err
+ }
+ /*
+ 找到两层指针指向的元素
+ */
+ value := reflect.ValueOf(v).Elem().Elem()
+
+ if !value.IsNil() {
+ structValue := value.Elem()
+ if structValue.NumField() == 1 && structValue.Field(0).Kind() == reflect.String {
+ n := len(platformResponseBody.ResponseBody)
+ structValue.Field(0).SetString(platformResponseBody.ResponseBody[1 : n-1])
+ return nil
+ }
+ }
+
+ if err = json.Unmarshal([]byte(platformResponseBody.ResponseBody), v); err != nil {
+ return err
+ }
+ return nil
+ }
+ return errors.New("undefined response type")
+}
+
+// Add a file to the multipart request
+func addFile(w *multipart.Writer, fieldName, path string) error {
+ file, err := os.Open(path)
+ if err != nil {
+ return err
+ }
+ defer file.Close()
+
+ part, err := w.CreateFormFile(fieldName, filepath.Base(path))
+ if err != nil {
+ return err
+ }
+ _, err = io.Copy(part, file)
+
+ return err
+}
+
+// Prevent trying to import "fmt"
+func reportError(format string, a ...interface{}) error {
+ return fmt.Errorf(format, a...)
+}
+
+// Set request body from an interface{}
+func setBody(body interface{}, contentType string) (bodyBuf *bytes.Buffer, err error) {
+ if bodyBuf == nil {
+ bodyBuf = &bytes.Buffer{}
+ }
+ if reader, ok := body.(io.Reader); ok {
+ _, err = bodyBuf.ReadFrom(reader)
+ } else if b, ok := body.([]byte); ok {
+ _, err = bodyBuf.Write(b)
+ } else if s, ok := body.(string); ok {
+ _, err = bodyBuf.WriteString(s)
+ } else if s, ok := body.(*string); ok {
+ _, err = bodyBuf.WriteString(*s)
+ } else if jsonCheck.MatchString(contentType) {
+ err = json.NewEncoder(bodyBuf).Encode(body)
+ } else if xmlCheck.MatchString(contentType) {
+ xml.NewEncoder(bodyBuf).Encode(body)
+ }
+
+ if err != nil {
+ return nil, err
+ }
+
+ if bodyBuf.Len() == 0 {
+ err = fmt.Errorf("Invalid body type %s\n", contentType)
+ return nil, err
+ }
+ return bodyBuf, nil
+}
+
+// detectContentType method is used to figure out `Request.Body` content type for request header
+func detectContentType(body interface{}) string {
+ contentType := "text/plain; charset=utf-8"
+ kind := reflect.TypeOf(body).Kind()
+
+ switch kind {
+ case reflect.Struct, reflect.Map, reflect.Ptr:
+ contentType = "application/json; charset=utf-8"
+ case reflect.String:
+ contentType = "text/plain; charset=utf-8"
+ default:
+ if b, ok := body.([]byte); ok {
+ contentType = http.DetectContentType(b)
+ } else if kind == reflect.Slice {
+ contentType = "application/json; charset=utf-8"
+ }
+ }
+
+ return contentType
+}
+
+type cacheControl map[string]string
+
+func parseCacheControl(headers http.Header) cacheControl {
+ cc := cacheControl{}
+ ccHeader := headers.Get("Cache-Control")
+ for _, part := range strings.Split(ccHeader, ",") {
+ part = strings.Trim(part, " ")
+ if part == "" {
+ continue
+ }
+ if strings.ContainsRune(part, '=') {
+ keyval := strings.Split(part, "=")
+ cc[strings.Trim(keyval[0], " ")] = strings.Trim(keyval[1], ",")
+ } else {
+ cc[part] = ""
+ }
+ }
+ return cc
+}
+
+// CacheExpires helper function to determine remaining time before repeating a request.
+func CacheExpires(r *http.Response) time.Time {
+ // Figure out when the cache expires.
+ var expires time.Time
+ now, err := time.Parse(time.RFC1123, r.Header.Get("date"))
+ if err != nil {
+ return time.Now()
+ }
+ respCacheControl := parseCacheControl(r.Header)
+
+ if maxAge, ok := respCacheControl["max-age"]; ok {
+ lifetime, err := time.ParseDuration(maxAge + "s")
+ if err != nil {
+ expires = now
+ }
+ expires = now.Add(lifetime)
+ } else {
+ expiresHeader := r.Header.Get("Expires")
+ if expiresHeader != "" {
+ expires, err = time.Parse(time.RFC1123, expiresHeader)
+ if err != nil {
+ expires = now
+ }
+ }
+ }
+ return expires
+}
+
+func strlen(s string) int {
+ return utf8.RuneCountInString(s)
+}
+
+// GenericResponseError Provides access to the body, error and model on returned errors.
+type GenericResponseError struct {
+ body []byte
+ error string
+ model interface{}
+}
+
+// Error returns non-empty string if there was an error.
+func (e GenericResponseError) Error() string {
+ return e.error
+}
+
+// Body returns the raw bytes of the response
+func (e GenericResponseError) Body() []byte {
+ return e.body
+}
+
+// Model returns the unpacked model of the error
+func (e GenericResponseError) Model() interface{} {
+ return e.model
+}
diff --git a/internal/pkg/vendors/cmcc-sdk/ecloudsdkcore@v1.0.0/api_response.go b/internal/pkg/vendors/cmcc-sdk/ecloudsdkcore@v1.0.0/api_response.go
new file mode 100644
index 00000000..89110877
--- /dev/null
+++ b/internal/pkg/vendors/cmcc-sdk/ecloudsdkcore@v1.0.0/api_response.go
@@ -0,0 +1,64 @@
+package ecloudsdkcore
+
+import (
+ "net/http"
+)
+
+type ReturnState string
+
+const (
+ OK ReturnState = "OK"
+ ERROR ReturnState = "ERROR"
+ EXCEPTION ReturnState = "EXCEPTION"
+ ALARM ReturnState = "ALARM"
+ FORBIDDEN ReturnState = "FORBIDDEN"
+)
+
+type APIResponse struct {
+ *http.Response `json:"-"`
+ Message string `json:"message,omitempty"`
+ // Operation is the name of the swagger operation.
+ Operation string `json:"operation,omitempty"`
+ // RequestURL is the request URL. This value is always available, even if the
+ // embedded *http.Response is nil.
+ RequestURL string `json:"url,omitempty"`
+ // Method is the HTTP method used for the request. This value is always
+ // available, even if the embedded *http.Response is nil.
+ Method string `json:"method,omitempty"`
+ // Payload holds the contents of the response body (which may be nil or empty).
+ // This is provided here as the raw response.Body() reader will have already
+ // been drained.
+ Payload []byte `json:"-"`
+}
+
+type APIPlatformResponse struct {
+ RequestId string `json:"requestId,omitempty"`
+ State ReturnState `json:"state,omitempty"`
+ Body interface{} `json:"body,omitempty"`
+ ErrorCode string `json:"errorCode,omitempty"`
+ ErrorParams []string `json:"errorParams,omitempty"`
+ ErrorMessage string `json:"errorMessage,omitempty"`
+}
+
+type APIPlatformResponseBody struct {
+ // TimeConsuming int64 `json:"timeConsuming,omitempty"`
+ ResponseBody string `json:"responseBody,omitempty"`
+ RequestHeader map[string]interface{} `json:"requestHeader,omitempty"`
+ ResponseHeader map[string]interface{} `json:"responseHeader,omitempty"`
+ ResponseMessage string `json:"responseMessage,omitempty"`
+ StatusCode int `json:"statusCode,omitempty"`
+ HttpMethod string `json:"httpMethod,omitempty"`
+ RequestUrl string `json:"requestUrl,omitempty"`
+}
+
+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/vendors/cmcc-sdk/ecloudsdkcore@v1.0.0/config/config.go
new file mode 100644
index 00000000..08ba59e3
--- /dev/null
+++ b/internal/pkg/vendors/cmcc-sdk/ecloudsdkcore@v1.0.0/config/config.go
@@ -0,0 +1,9 @@
+package config
+
+type Config struct {
+ AccessKey string `json:"accessKey,string"`
+ SecretKey string `json:"secretKey,string"`
+ PoolId string `json:"poolId,string"`
+ ReadTimeOut int `json:"readTimeOut,int"`
+ ConnectTimeout int `json:"connectTimeout,int"`
+}
diff --git a/internal/pkg/vendors/cmcc-sdk/ecloudsdkcore@v1.0.0/configuration.go b/internal/pkg/vendors/cmcc-sdk/ecloudsdkcore@v1.0.0/configuration.go
new file mode 100644
index 00000000..8eeb5df0
--- /dev/null
+++ b/internal/pkg/vendors/cmcc-sdk/ecloudsdkcore@v1.0.0/configuration.go
@@ -0,0 +1,32 @@
+package ecloudsdkcore
+
+import (
+ "net/http"
+)
+
+type APIKey struct {
+ Key string
+ Prefix string
+}
+
+type Configuration struct {
+ BasePath string `json:"basePath,omitempty"`
+ Host string `json:"host,omitempty"`
+ Scheme string `json:"scheme,omitempty"`
+ DefaultHeader map[string]string `json:"defaultHeader,omitempty"`
+ UserAgent string `json:"userAgent,omitempty"`
+ HTTPClient *http.Client
+}
+
+func NewConfiguration() *Configuration {
+ cfg := &Configuration{
+ BasePath: "https://ecloud.10086.cn/",
+ DefaultHeader: make(map[string]string),
+ UserAgent: "Ecloud-SDK/1.0.0/go",
+ }
+ return cfg
+}
+
+func (c *Configuration) AddDefaultHeader(key string, value string) {
+ c.DefaultHeader[key] = value
+}
diff --git a/internal/pkg/vendors/cmcc-sdk/ecloudsdkcore@v1.0.0/go.mod b/internal/pkg/vendors/cmcc-sdk/ecloudsdkcore@v1.0.0/go.mod
new file mode 100644
index 00000000..141fa34e
--- /dev/null
+++ b/internal/pkg/vendors/cmcc-sdk/ecloudsdkcore@v1.0.0/go.mod
@@ -0,0 +1,3 @@
+module gitlab.ecloud.com/ecloud/ecloudsdkcore
+
+go 1.23.0
diff --git a/internal/pkg/vendors/cmcc-sdk/ecloudsdkcore@v1.0.0/http_request.go b/internal/pkg/vendors/cmcc-sdk/ecloudsdkcore@v1.0.0/http_request.go
new file mode 100644
index 00000000..e498463d
--- /dev/null
+++ b/internal/pkg/vendors/cmcc-sdk/ecloudsdkcore@v1.0.0/http_request.go
@@ -0,0 +1,22 @@
+package ecloudsdkcore
+
+type HttpRequest struct {
+ Url string `json:"url,omitempty"`
+ DefaultUrl string `json:"defaultUrl,omitempty"`
+ Method string `json:"method,omitempty"`
+ Action string `json:"action,omitempty"`
+ Product string `json:"product,omitempty"`
+ Version string `json:"version,omitempty"`
+ SdkVersion string `json:"sdkVersion,omitempty"`
+ Body interface{} `json:"body,omitempty"`
+ PathParams map[string]interface{} `json:"pathParams,omitempty"`
+ QueryParams map[string]interface{} `json:"queryParams,omitempty"`
+ HeaderParams map[string]interface{} `json:"headerParams,omitempty"`
+}
+
+func NewDefaultHttpRequest() *HttpRequest {
+ return &HttpRequest{
+ DefaultUrl: "https://ecloud.10086.cn",
+ Method: "POST",
+ }
+}
diff --git a/internal/pkg/vendors/cmcc-sdk/ecloudsdkcore@v1.0.0/open_api_request.go b/internal/pkg/vendors/cmcc-sdk/ecloudsdkcore@v1.0.0/open_api_request.go
new file mode 100644
index 00000000..a7cb4c0b
--- /dev/null
+++ b/internal/pkg/vendors/cmcc-sdk/ecloudsdkcore@v1.0.0/open_api_request.go
@@ -0,0 +1,16 @@
+package ecloudsdkcore
+
+type OpenApiRequest struct {
+ Product string `json:"product,omitempty"`
+ Version string `json:"version,omitempty"`
+ SdkVersion string `json:"sdkVersion,omitempty"`
+ Language string `json:"language,omitempty"`
+ Api string `json:"api,omitempty"`
+ PoolId string `json:"poolId,omitempty"`
+ HeaderParameter map[string]interface{} `json:"headerParameter,omitempty"`
+ PathParameter map[string]interface{} `json:"pathParameter,omitempty"`
+ QueryParameter map[string]interface{} `json:"queryParameter,omitempty"`
+ BodyParameter interface{} `json:"bodyParameter,omitempty"`
+ AccessKey string `json:"accessKey,omitempty"`
+ SecretKey string `json:"secretKey,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
new file mode 100644
index 00000000..7c2eec1c
--- /dev/null
+++ b/internal/pkg/vendors/cmcc-sdk/ecloudsdkcore@v1.0.0/position/http_position.go
@@ -0,0 +1,13 @@
+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/vendors/dnsla-sdk/api.go
new file mode 100644
index 00000000..df8e6026
--- /dev/null
+++ b/internal/pkg/vendors/dnsla-sdk/api.go
@@ -0,0 +1,52 @@
+package dnslasdk
+
+import (
+ "fmt"
+ "net/http"
+ "net/url"
+)
+
+func (c *Client) ListDomains(req *ListDomainsRequest) (*ListDomainsResponse, error) {
+ resp := ListDomainsResponse{}
+ err := c.sendRequestWithResult(http.MethodGet, "/domainList", req, &resp)
+ if err != nil {
+ return nil, err
+ }
+ return &resp, nil
+}
+
+func (c *Client) ListRecords(req *ListRecordsRequest) (*ListRecordsResponse, error) {
+ resp := ListRecordsResponse{}
+ err := c.sendRequestWithResult(http.MethodGet, "/recordList", req, &resp)
+ if err != nil {
+ return nil, err
+ }
+ return &resp, nil
+}
+
+func (c *Client) CreateRecord(req *CreateRecordRequest) (*CreateRecordResponse, error) {
+ resp := CreateRecordResponse{}
+ err := c.sendRequestWithResult(http.MethodPost, "/record", req, &resp)
+ if err != nil {
+ return nil, err
+ }
+ return &resp, nil
+}
+
+func (c *Client) UpdateRecord(req *UpdateRecordRequest) (*UpdateRecordResponse, error) {
+ resp := UpdateRecordResponse{}
+ err := c.sendRequestWithResult(http.MethodPut, "/record", req, &resp)
+ if err != nil {
+ return nil, err
+ }
+ return &resp, nil
+}
+
+func (c *Client) DeleteRecord(req *DeleteRecordRequest) (*DeleteRecordResponse, error) {
+ resp := DeleteRecordResponse{}
+ err := c.sendRequestWithResult(http.MethodDelete, fmt.Sprintf("/record?id=%s", url.QueryEscape(req.Id)), req, &resp)
+ if err != nil {
+ return nil, err
+ }
+ return &resp, nil
+}
diff --git a/internal/pkg/vendors/dnsla-sdk/client.go b/internal/pkg/vendors/dnsla-sdk/client.go
new file mode 100644
index 00000000..60430fa1
--- /dev/null
+++ b/internal/pkg/vendors/dnsla-sdk/client.go
@@ -0,0 +1,82 @@
+package dnslasdk
+
+import (
+ "encoding/json"
+ "fmt"
+ "net/http"
+ "strings"
+ "time"
+
+ "github.com/go-resty/resty/v2"
+)
+
+type Client struct {
+ apiId string
+ apiSecret string
+
+ client *resty.Client
+}
+
+func NewClient(apiId, apiSecret string) *Client {
+ client := resty.New()
+
+ return &Client{
+ apiId: apiId,
+ apiSecret: apiSecret,
+ client: client,
+ }
+}
+
+func (c *Client) WithTimeout(timeout time.Duration) *Client {
+ c.client.SetTimeout(timeout)
+ return c
+}
+
+func (c *Client) sendRequest(method string, path string, params interface{}) (*resty.Response, error) {
+ req := c.client.R().SetBasicAuth(c.apiId, c.apiSecret)
+ req.Method = method
+ req.URL = "https://api.dns.la/api" + 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)
+ } else {
+ req = req.
+ SetHeader("Content-Type", "application/json").
+ SetBody(params)
+ }
+
+ resp, err := req.Send()
+ if err != nil {
+ return nil, fmt.Errorf("dnsla api error: failed to send request: %w", err)
+ } else if resp.IsError() {
+ return nil, fmt.Errorf("dnsla api error: unexpected status code: %d, %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 {
+ return err
+ }
+
+ if err := json.Unmarshal(resp.Body(), &result); err != nil {
+ return fmt.Errorf("dnsla api error: failed to parse response: %w", err)
+ } else if errcode := result.GetCode(); errcode/100 != 2 {
+ return fmt.Errorf("dnsla api error: %d - %s", errcode, result.GetMessage())
+ }
+
+ return nil
+}
diff --git a/internal/pkg/vendors/dnsla-sdk/models.go b/internal/pkg/vendors/dnsla-sdk/models.go
new file mode 100644
index 00000000..85fe7978
--- /dev/null
+++ b/internal/pkg/vendors/dnsla-sdk/models.go
@@ -0,0 +1,125 @@
+package dnslasdk
+
+type BaseResponse interface {
+ GetCode() int
+ GetMessage() string
+}
+
+type baseResponse struct {
+ Code int `json:"code"`
+ Message string `json:"message"`
+}
+
+func (r *baseResponse) GetCode() int {
+ return r.Code
+}
+
+func (r *baseResponse) GetMessage() string {
+ return r.Message
+}
+
+type DomainInfo struct {
+ Id string `json:"id"`
+ GroupId string `json:"groupId"`
+ GroupName string `json:"groupName"`
+ Domain string `json:"domain"`
+ DisplayDomain string `json:"displayDomain"`
+ CreatedAt int64 `json:"createdAt"`
+ UpdatedAt int64 `json:"updatedAt"`
+}
+
+type RecordInfo struct {
+ Id string `json:"id"`
+ DomainId string `json:"domainId"`
+ GroupId string `json:"groupId"`
+ GroupName string `json:"groupName"`
+ LineId string `json:"lineId"`
+ LineCode string `json:"lineCode"`
+ LineName string `json:"lineName"`
+ Type int32 `json:"type"`
+ Host string `json:"host"`
+ DisplayHost string `json:"displayHost"`
+ Data string `json:"data"`
+ DisplayData string `json:"displayData"`
+ Ttl int32 `json:"ttl"`
+ Weight int32 `json:"weight"`
+ Preference int32 `json:"preference"`
+ CreatedAt int64 `json:"createdAt"`
+ UpdatedAt int64 `json:"updatedAt"`
+}
+
+type ListDomainsRequest struct {
+ PageIndex int32 `json:"pageIndex"`
+ PageSize int32 `json:"pageSize"`
+ GroupId *string `json:"groupId,omitempty"`
+}
+
+type ListDomainsResponse struct {
+ baseResponse
+ Data *struct {
+ Total int32 `json:"total"`
+ Results []*DomainInfo `json:"results"`
+ } `json:"data,omitempty"`
+}
+
+type ListRecordsRequest struct {
+ PageIndex int32 `json:"pageIndex"`
+ PageSize int32 `json:"pageSize"`
+ DomainId string `json:"domainId"`
+ GroupId *string `json:"groupId,omitempty"`
+ LineId *string `json:"lineId,omitempty"`
+ Type *int32 `json:"type,omitempty"`
+ Host *string `json:"host,omitempty"`
+ Data *string `json:"data,omitempty"`
+}
+
+type ListRecordsResponse struct {
+ baseResponse
+ Data *struct {
+ Total int32 `json:"total"`
+ Results []*RecordInfo `json:"results"`
+ } `json:"data,omitempty"`
+}
+
+type CreateRecordRequest struct {
+ DomainId string `json:"domainId"`
+ GroupId *string `json:"groupId,omitempty"`
+ LineId *string `json:"lineId,omitempty"`
+ Type int32 `json:"type"`
+ Host string `json:"host"`
+ Data string `json:"data"`
+ Ttl int32 `json:"ttl"`
+ Weight *int32 `json:"weight,omitempty"`
+ Preference *int32 `json:"preference,omitempty"`
+}
+
+type CreateRecordResponse struct {
+ baseResponse
+ Data *struct {
+ Id string `json:"id"`
+ } `json:"data,omitempty"`
+}
+
+type UpdateRecordRequest struct {
+ Id string `json:"id"`
+ GroupId *string `json:"groupId,omitempty"`
+ LineId *string `json:"lineId,omitempty"`
+ Type *int32 `json:"type,omitempty"`
+ Host *string `json:"host,omitempty"`
+ Data *string `json:"data,omitempty"`
+ Ttl *int32 `json:"ttl,omitempty"`
+ Weight *int32 `json:"weight,omitempty"`
+ Preference *int32 `json:"preference,omitempty"`
+}
+
+type UpdateRecordResponse struct {
+ baseResponse
+}
+
+type DeleteRecordRequest struct {
+ Id string `json:"-"`
+}
+
+type DeleteRecordResponse struct {
+ baseResponse
+}
diff --git a/internal/pkg/vendors/edgio-sdk/applications/README.md b/internal/pkg/vendors/edgio-sdk/applications/README.md
new file mode 100644
index 00000000..703b245a
--- /dev/null
+++ b/internal/pkg/vendors/edgio-sdk/applications/README.md
@@ -0,0 +1 @@
+From https://github.com/Edgio/terraform-provider-edgio.git
diff --git a/internal/pkg/vendors/edgio-sdk/applications/v7/README.md b/internal/pkg/vendors/edgio-sdk/applications/v7/README.md
deleted file mode 100644
index fae60236..00000000
--- a/internal/pkg/vendors/edgio-sdk/applications/v7/README.md
+++ /dev/null
@@ -1,3 +0,0 @@
-```shell
-git clone https://github.com/Edgio/terraform-provider-edgio.git
-```
diff --git a/internal/pkg/vendors/gcore-sdk/common/endpoint.go b/internal/pkg/vendors/gcore-sdk/common/endpoint.go
new file mode 100644
index 00000000..d4032da3
--- /dev/null
+++ b/internal/pkg/vendors/gcore-sdk/common/endpoint.go
@@ -0,0 +1,3 @@
+package common
+
+const BASE_URL = "https://api.gcore.com"
diff --git a/internal/pkg/vendors/gcore-sdk/common/signer.go b/internal/pkg/vendors/gcore-sdk/common/signer.go
new file mode 100644
index 00000000..bc66ee09
--- /dev/null
+++ b/internal/pkg/vendors/gcore-sdk/common/signer.go
@@ -0,0 +1,24 @@
+package common
+
+import (
+ "net/http"
+
+ "github.com/G-Core/gcorelabscdn-go/gcore"
+)
+
+type AuthRequestSigner struct {
+ apiToken string
+}
+
+var _ gcore.RequestSigner = (*AuthRequestSigner)(nil)
+
+func NewAuthRequestSigner(apiToken string) *AuthRequestSigner {
+ return &AuthRequestSigner{
+ apiToken: apiToken,
+ }
+}
+
+func (s *AuthRequestSigner) Sign(req *http.Request) error {
+ req.Header.Set("Authorization", "APIKey "+s.apiToken)
+ return nil
+}
diff --git a/internal/pkg/vendors/gname-sdk/api.go b/internal/pkg/vendors/gname-sdk/api.go
index 33972adc..d01574c7 100644
--- a/internal/pkg/vendors/gname-sdk/api.go
+++ b/internal/pkg/vendors/gname-sdk/api.go
@@ -1,102 +1,37 @@
package gnamesdk
-type BaseResponse interface {
- GetCode() int
- GetMsg() string
+func (c *Client) AddDomainResolution(req *AddDomainResolutionRequest) (*AddDomainResolutionResponse, error) {
+ result := AddDomainResolutionResponse{}
+ err := c.sendRequestWithResult("/api/resolution/add", req, &result)
+ if err != nil {
+ return nil, err
+ }
+ return &result, nil
}
-type AddDomainResolutionRequest struct {
- ZoneName string `json:"ym"`
- RecordType string `json:"lx"`
- RecordName string `json:"zj"`
- RecordValue string `json:"jlz"`
- MX int `json:"mx"`
- TTL int `json:"ttl"`
+func (c *Client) ModifyDomainResolution(req *ModifyDomainResolutionRequest) (*ModifyDomainResolutionResponse, error) {
+ resp := ModifyDomainResolutionResponse{}
+ err := c.sendRequestWithResult("/api/resolution/edit", req, &resp)
+ if err != nil {
+ return nil, err
+ }
+ return &resp, nil
}
-type AddDomainResolutionResponse struct {
- Code int `json:"code"`
- Msg string `json:"msg"`
- Data int `json:"data"`
+func (c *Client) DeleteDomainResolution(req *DeleteDomainResolutionRequest) (*DeleteDomainResolutionResponse, error) {
+ resp := DeleteDomainResolutionResponse{}
+ err := c.sendRequestWithResult("/api/resolution/delete", req, &resp)
+ if err != nil {
+ return nil, err
+ }
+ return &resp, nil
}
-func (r *AddDomainResolutionResponse) GetCode() int {
- return r.Code
-}
-
-func (r *AddDomainResolutionResponse) GetMsg() string {
- return r.Msg
-}
-
-type ModifyDomainResolutionRequest struct {
- ID string `json:"jxid"`
- ZoneName string `json:"ym"`
- RecordType string `json:"lx"`
- RecordName string `json:"zj"`
- RecordValue string `json:"jlz"`
- MX int `json:"mx"`
- TTL int `json:"ttl"`
-}
-
-type ModifyDomainResolutionResponse struct {
- Code int `json:"code"`
- Msg string `json:"msg"`
-}
-
-func (r *ModifyDomainResolutionResponse) GetCode() int {
- return r.Code
-}
-
-func (r *ModifyDomainResolutionResponse) GetMsg() string {
- return r.Msg
-}
-
-type DeleteDomainResolutionRequest struct {
- ZoneName string `json:"ym"`
- RecordID string `json:"jxid"`
-}
-
-type DeleteDomainResolutionResponse struct {
- Code int `json:"code"`
- Msg string `json:"msg"`
-}
-
-func (r *DeleteDomainResolutionResponse) GetCode() int {
- return r.Code
-}
-
-func (r *DeleteDomainResolutionResponse) GetMsg() string {
- return r.Msg
-}
-
-type ListDomainResolutionRequest struct {
- ZoneName string `json:"ym"`
- Page *int `json:"page,omitempty"`
- PageSize *int `json:"limit,omitempty"`
-}
-
-type ListDomainResolutionResponse struct {
- Code int `json:"code"`
- Msg string `json:"msg"`
- Count int `json:"count"`
- Data []*ResolutionRecord `json:"data"`
- Page int `json:"page"`
- PageSize int `json:"pagesize"`
-}
-
-type ResolutionRecord struct {
- ID string `json:"id"`
- ZoneName string `json:"ym"`
- RecordType string `json:"lx"`
- RecordName string `json:"zjt"`
- RecordValue string `json:"jxz"`
- MX int `json:"mx"`
-}
-
-func (r *ListDomainResolutionResponse) GetCode() int {
- return r.Code
-}
-
-func (r *ListDomainResolutionResponse) GetMsg() string {
- return r.Msg
+func (c *Client) ListDomainResolution(req *ListDomainResolutionRequest) (*ListDomainResolutionResponse, error) {
+ resp := ListDomainResolutionResponse{}
+ err := c.sendRequestWithResult("/api/resolution/list", req, &resp)
+ if err != nil {
+ return nil, err
+ }
+ return &resp, nil
}
diff --git a/internal/pkg/vendors/gname-sdk/client.go b/internal/pkg/vendors/gname-sdk/client.go
index 64baab95..8e2a2ba9 100644
--- a/internal/pkg/vendors/gname-sdk/client.go
+++ b/internal/pkg/vendors/gname-sdk/client.go
@@ -10,84 +10,31 @@ import (
"time"
"github.com/go-resty/resty/v2"
-
- "github.com/usual2970/certimate/internal/pkg/utils/maps"
)
-type GnameClient struct {
+type Client struct {
appId string
appKey string
+
client *resty.Client
}
-func NewGnameClient(appId, appKey string) *GnameClient {
+func NewClient(appId, appKey string) *Client {
client := resty.New()
- return &GnameClient{
+ return &Client{
appId: appId,
appKey: appKey,
client: client,
}
}
-func (c *GnameClient) WithTimeout(timeout time.Duration) *GnameClient {
+func (c *Client) WithTimeout(timeout time.Duration) *Client {
c.client.SetTimeout(timeout)
return c
}
-func (c *GnameClient) AddDomainResolution(req *AddDomainResolutionRequest) (*AddDomainResolutionResponse, error) {
- params := make(map[string]any)
- jsonData, _ := json.Marshal(req)
- json.Unmarshal(jsonData, ¶ms)
-
- result := AddDomainResolutionResponse{}
- err := c.sendRequestWithResult("/api/resolution/add", params, &result)
- if err != nil {
- return nil, err
- }
- return &result, nil
-}
-
-func (c *GnameClient) ModifyDomainResolution(req *ModifyDomainResolutionRequest) (*ModifyDomainResolutionResponse, error) {
- params := make(map[string]any)
- jsonData, _ := json.Marshal(req)
- json.Unmarshal(jsonData, ¶ms)
-
- result := ModifyDomainResolutionResponse{}
- err := c.sendRequestWithResult("/api/resolution/edit", params, &result)
- if err != nil {
- return nil, err
- }
- return &result, nil
-}
-
-func (c *GnameClient) DeleteDomainResolution(req *DeleteDomainResolutionRequest) (*DeleteDomainResolutionResponse, error) {
- params := make(map[string]any)
- jsonData, _ := json.Marshal(req)
- json.Unmarshal(jsonData, ¶ms)
-
- result := DeleteDomainResolutionResponse{}
- err := c.sendRequestWithResult("/api/resolution/delete", params, &result)
- if err != nil {
- return nil, err
- }
- return &result, nil
-}
-
-func (c *GnameClient) ListDomainResolution(req *ListDomainResolutionRequest) (*ListDomainResolutionResponse, error) {
- params := make(map[string]any)
- jsonData, _ := json.Marshal(req)
- json.Unmarshal(jsonData, ¶ms)
-
- result := ListDomainResolutionResponse{}
- err := c.sendRequestWithResult("/api/resolution/list", params, &result)
- if err != nil {
- return nil, err
- }
- return &result, nil
-}
-
-func (c *GnameClient) generateSignature(params map[string]string) string {
+func (c *Client) generateSignature(params map[string]string) string {
// Step 1: Sort parameters by ASCII order
var keys []string
for k := range params {
@@ -111,14 +58,17 @@ func (c *GnameClient) generateSignature(params map[string]string) string {
return strings.ToUpper(fmt.Sprintf("%x", hash))
}
-func (c *GnameClient) sendRequest(path string, params map[string]any) (*resty.Response, error) {
- if params == nil {
- params = make(map[string]any)
- }
-
+func (c *Client) sendRequest(path string, params interface{}) (*resty.Response, error) {
data := make(map[string]string)
- for k, v := range params {
- data[k] = fmt.Sprintf("%v", v)
+ if params != nil {
+ temp := make(map[string]any)
+ jsonb, _ := json.Marshal(params)
+ json.Unmarshal(jsonb, &temp)
+ for k, v := range temp {
+ if v != nil {
+ data[k] = fmt.Sprintf("%v", v)
+ }
+ }
}
data["appid"] = c.appId
data["gntime"] = fmt.Sprintf("%d", time.Now().Unix())
@@ -130,32 +80,24 @@ func (c *GnameClient) sendRequest(path string, params map[string]any) (*resty.Re
SetFormData(data)
resp, err := req.Post(url)
if err != nil {
- return nil, fmt.Errorf("gname: failed to send request: %w", err)
- }
-
- if resp.IsError() {
- return nil, fmt.Errorf("gname: unexpected status code: %d, %s", resp.StatusCode(), resp.Body())
+ return nil, fmt.Errorf("gname api error: failed to send request: %w", err)
+ } else if resp.IsError() {
+ return nil, fmt.Errorf("gname api error: unexpected status code: %d, %s", resp.StatusCode(), resp.Body())
}
return resp, nil
}
-func (c *GnameClient) sendRequestWithResult(path string, params map[string]any, result BaseResponse) error {
+func (c *Client) sendRequestWithResult(path string, params interface{}, result BaseResponse) error {
resp, err := c.sendRequest(path, params)
if err != nil {
return err
}
- jsonResp := make(map[string]any)
- if err := json.Unmarshal(resp.Body(), &jsonResp); err != nil {
- return fmt.Errorf("gname: failed to parse response: %w", err)
- }
- if err := maps.Populate(jsonResp, &result); err != nil {
- return fmt.Errorf("gname: failed to parse response: %w", err)
- }
-
- if result.GetCode() != 1 {
- return fmt.Errorf("gname api error: %s", result.GetMsg())
+ if err := json.Unmarshal(resp.Body(), &result); err != nil {
+ return fmt.Errorf("gname api error: failed to parse response: %w", err)
+ } else if errcode := result.GetCode(); errcode != 1 {
+ return fmt.Errorf("gname api error: %d - %s", errcode, result.GetMessage())
}
return nil
diff --git a/internal/pkg/vendors/gname-sdk/models.go b/internal/pkg/vendors/gname-sdk/models.go
new file mode 100644
index 00000000..997fb2c4
--- /dev/null
+++ b/internal/pkg/vendors/gname-sdk/models.go
@@ -0,0 +1,79 @@
+package gnamesdk
+
+type BaseResponse interface {
+ GetCode() int
+ GetMessage() string
+}
+
+type baseResponse struct {
+ Code int `json:"code"`
+ Message string `json:"msg"`
+}
+
+func (r *baseResponse) GetCode() int {
+ return r.Code
+}
+
+func (r *baseResponse) GetMessage() string {
+ return r.Message
+}
+
+type AddDomainResolutionRequest struct {
+ ZoneName string `json:"ym"`
+ RecordType string `json:"lx"`
+ RecordName string `json:"zj"`
+ RecordValue string `json:"jlz"`
+ MX int `json:"mx"`
+ TTL int `json:"ttl"`
+}
+
+type AddDomainResolutionResponse struct {
+ baseResponse
+ Data string `json:"data"`
+}
+
+type ModifyDomainResolutionRequest struct {
+ ID string `json:"jxid"`
+ ZoneName string `json:"ym"`
+ RecordType string `json:"lx"`
+ RecordName string `json:"zj"`
+ RecordValue string `json:"jlz"`
+ MX int `json:"mx"`
+ TTL int `json:"ttl"`
+}
+
+type ModifyDomainResolutionResponse struct {
+ baseResponse
+}
+
+type DeleteDomainResolutionRequest struct {
+ ZoneName string `json:"ym"`
+ RecordID string `json:"jxid"`
+}
+
+type DeleteDomainResolutionResponse struct {
+ baseResponse
+}
+
+type ListDomainResolutionRequest struct {
+ ZoneName string `json:"ym"`
+ Page *int `json:"page,omitempty"`
+ PageSize *int `json:"limit,omitempty"`
+}
+
+type ListDomainResolutionResponse struct {
+ baseResponse
+ Count int `json:"count"`
+ Data []*ResolutionRecord `json:"data"`
+ Page int `json:"page"`
+ PageSize int `json:"pagesize"`
+}
+
+type ResolutionRecord struct {
+ ID string `json:"id"`
+ ZoneName string `json:"ym"`
+ RecordType string `json:"lx"`
+ RecordName string `json:"zjt"`
+ RecordValue string `json:"jxz"`
+ MX int `json:"mx"`
+}
diff --git a/internal/pkg/vendors/safeline-sdk/api.go b/internal/pkg/vendors/safeline-sdk/api.go
new file mode 100644
index 00000000..17af6c83
--- /dev/null
+++ b/internal/pkg/vendors/safeline-sdk/api.go
@@ -0,0 +1,10 @@
+package safelinesdk
+
+func (c *Client) UpdateCertificate(req *UpdateCertificateRequest) (*UpdateCertificateResponse, error) {
+ resp := UpdateCertificateResponse{}
+ err := c.sendRequestWithResult("/api/open/cert", req, &resp)
+ if err != nil {
+ return nil, err
+ }
+ return &resp, nil
+}
diff --git a/internal/pkg/vendors/safeline-sdk/client.go b/internal/pkg/vendors/safeline-sdk/client.go
new file mode 100644
index 00000000..c6e6caf1
--- /dev/null
+++ b/internal/pkg/vendors/safeline-sdk/client.go
@@ -0,0 +1,67 @@
+package safelinesdk
+
+import (
+ "encoding/json"
+ "fmt"
+ "strings"
+ "time"
+
+ "github.com/go-resty/resty/v2"
+)
+
+type Client struct {
+ apiHost string
+ apiToken string
+
+ client *resty.Client
+}
+
+func NewClient(apiHost, apiToken string) *Client {
+ client := resty.New()
+
+ return &Client{
+ apiHost: strings.TrimRight(apiHost, "/"),
+ apiToken: apiToken,
+ client: client,
+ }
+}
+
+func (c *Client) WithTimeout(timeout time.Duration) *Client {
+ c.client.SetTimeout(timeout)
+ return c
+}
+
+func (c *Client) sendRequest(path string, params interface{}) (*resty.Response, error) {
+ url := c.apiHost + path
+ req := c.client.R().
+ SetHeader("Content-Type", "application/json").
+ SetHeader("X-SLCE-API-TOKEN", c.apiToken).
+ SetBody(params)
+ resp, err := req.Post(url)
+ if err != nil {
+ return nil, fmt.Errorf("safeline api error: failed to send request: %w", err)
+ } else if resp.IsError() {
+ return nil, fmt.Errorf("safeline api error: unexpected status code: %d, %s", resp.StatusCode(), resp.Body())
+ }
+
+ return resp, nil
+}
+
+func (c *Client) sendRequestWithResult(path string, params interface{}, result BaseResponse) error {
+ resp, err := c.sendRequest(path, params)
+ if err != nil {
+ return err
+ }
+
+ if err := json.Unmarshal(resp.Body(), &result); err != nil {
+ return fmt.Errorf("safeline api error: failed to parse response: %w", err)
+ } else if errcode := result.GetErrCode(); errcode != nil && *errcode != "" {
+ if result.GetErrMsg() == nil {
+ return fmt.Errorf("safeline api error: %s", *errcode)
+ } else {
+ return fmt.Errorf("safeline api error: %s - %s", *errcode, *result.GetErrMsg())
+ }
+ }
+
+ return nil
+}
diff --git a/internal/pkg/vendors/safeline-sdk/models.go b/internal/pkg/vendors/safeline-sdk/models.go
new file mode 100644
index 00000000..9fbfb7c9
--- /dev/null
+++ b/internal/pkg/vendors/safeline-sdk/models.go
@@ -0,0 +1,34 @@
+package safelinesdk
+
+type BaseResponse interface {
+ GetErrCode() *string
+ GetErrMsg() *string
+}
+
+type baseResponse struct {
+ ErrCode *string `json:"err,omitempty"`
+ ErrMsg *string `json:"msg,omitempty"`
+}
+
+func (r *baseResponse) GetErrCode() *string {
+ return r.ErrCode
+}
+
+func (r *baseResponse) GetErrMsg() *string {
+ return r.ErrMsg
+}
+
+type UpdateCertificateRequest struct {
+ Id int32 `json:"id"`
+ Type int32 `json:"type"`
+ Manual *UpdateCertificateRequestBodyManul `json:"manual"`
+}
+
+type UpdateCertificateRequestBodyManul struct {
+ Crt string `json:"crt"`
+ Key string `json:"key"`
+}
+
+type UpdateCertificateResponse struct {
+ baseResponse
+}
diff --git a/main.go b/main.go
index 73d1a2a9..76f7f1c0 100644
--- a/main.go
+++ b/main.go
@@ -29,6 +29,11 @@ func main() {
var flagDir string
flag.StringVar(&flagHttp, "http", "127.0.0.1:8090", "HTTP server address")
flag.StringVar(&flagDir, "dir", "/pb_data/database", "Pocketbase data directory")
+ if len(os.Args) < 2 {
+ slog.Error("[CERTIMATE] missing exec args")
+ os.Exit(1)
+ return
+ }
_ = flag.CommandLine.Parse(os.Args[2:]) // skip the first two arguments: "main.go serve"
migratecmd.MustRegister(app, app.RootCmd, migratecmd.Config{
diff --git a/migrations/1739462400_collections_snapshot.go b/migrations/1739462400_collections_snapshot.go
index 523792c7..67453954 100644
--- a/migrations/1739462400_collections_snapshot.go
+++ b/migrations/1739462400_collections_snapshot.go
@@ -65,6 +65,7 @@ func init() {
"cmcccloud",
"ctcccloud",
"cucccloud",
+ "dnsla",
"dogecloud",
"edgio",
"fastly",
@@ -73,13 +74,16 @@ func init() {
"godaddy",
"goedge",
"huaweicloud",
+ "jdcloud",
"k8s",
"local",
+ "namecheap",
"namedotcom",
"namesilo",
"ns1",
"powerdns",
"qiniu",
+ "qingcloud",
"rainyun",
"safeline",
"ssh",
@@ -171,6 +175,7 @@ func init() {
"cmcccloud",
"ctcccloud",
"cucccloud",
+ "dnsla",
"dogecloud",
"edgio",
"fastly",
@@ -179,13 +184,16 @@ func init() {
"godaddy",
"goedge",
"huaweicloud",
+ "jdcloud",
"k8s",
"local",
+ "namecheap",
"namedotcom",
"namesilo",
"ns1",
"powerdns",
"qiniu",
+ "qingcloud",
"rainyun",
"safeline",
"ssh",
diff --git a/ui/public/imgs/acme/letsencrypt.svg b/ui/public/imgs/acme/letsencrypt.svg
index 3a6c2312..b13df853 100644
--- a/ui/public/imgs/acme/letsencrypt.svg
+++ b/ui/public/imgs/acme/letsencrypt.svg
@@ -1 +1 @@
-
+
diff --git a/ui/public/imgs/providers/acmehttpreq.svg b/ui/public/imgs/providers/acmehttpreq.svg
index 88f2d6b2..936ca077 100644
--- a/ui/public/imgs/providers/acmehttpreq.svg
+++ b/ui/public/imgs/providers/acmehttpreq.svg
@@ -1,2 +1,2 @@
-