From 3093fc6b020ed7eec1e225c831e647afd6bf3fbb Mon Sep 17 00:00:00 2001 From: Fu Diwei Date: Fri, 18 Oct 2024 12:16:14 +0800 Subject: [PATCH] refactor refactor refactor --- internal/applicant/aws.go | 3 +- internal/deployer/aliyun.go | 68 ---------------- internal/deployer/aliyun_cdn.go | 36 +++++---- internal/deployer/aliyun_esa.go | 36 +++++---- internal/deployer/aliyun_oss.go | 70 ++++++++++++++++ internal/deployer/deployer.go | 42 +++++----- internal/deployer/local.go | 36 ++++----- internal/deployer/{qiniu.go => qiniu_cdn.go} | 80 +++++++++---------- .../{qiniu_test.go => qiniu_cdn_test.go} | 4 +- internal/deployer/ssh.go | 56 ++++++------- internal/deployer/tencent_cdn.go | 48 +++++------ internal/deployer/webhook.go | 62 +++++++------- 12 files changed, 272 insertions(+), 269 deletions(-) delete mode 100644 internal/deployer/aliyun.go create mode 100644 internal/deployer/aliyun_oss.go rename internal/deployer/{qiniu.go => qiniu_cdn.go} (60%) rename internal/deployer/{qiniu_test.go => qiniu_cdn_test.go} (94%) diff --git a/internal/applicant/aws.go b/internal/applicant/aws.go index 154eb996..9a491d06 100644 --- a/internal/applicant/aws.go +++ b/internal/applicant/aws.go @@ -1,12 +1,13 @@ package applicant import ( - "certimate/internal/domain" "encoding/json" "fmt" "os" "github.com/go-acme/lego/v4/providers/dns/route53" + + "certimate/internal/domain" ) type aws struct { diff --git a/internal/deployer/aliyun.go b/internal/deployer/aliyun.go deleted file mode 100644 index 9c56e6df..00000000 --- a/internal/deployer/aliyun.go +++ /dev/null @@ -1,68 +0,0 @@ -package deployer - -import ( - "context" - "encoding/json" - "fmt" - - "github.com/aliyun/aliyun-oss-go-sdk/oss" - - "certimate/internal/domain" -) - -type aliyun struct { - client *oss.Client - option *DeployerOption - infos []string -} - -func NewAliyun(option *DeployerOption) (Deployer, error) { - access := &domain.AliyunAccess{} - json.Unmarshal([]byte(option.Access), access) - a := &aliyun{ - option: option, - infos: make([]string, 0), - } - client, err := a.createClient(access.AccessKeyId, access.AccessKeySecret) - if err != nil { - return nil, err - } - a.client = client - return a, nil -} - -func (a *aliyun) GetID() string { - return fmt.Sprintf("%s-%s", a.option.AceessRecord.GetString("name"), a.option.AceessRecord.Id) -} - -func (a *aliyun) GetInfo() []string { - return a.infos -} - -func (a *aliyun) Deploy(ctx context.Context) error { - err := a.client.PutBucketCnameWithCertificate(getDeployString(a.option.DeployConfig, "bucket"), oss.PutBucketCname{ - Cname: getDeployString(a.option.DeployConfig, "domain"), - CertificateConfiguration: &oss.CertificateConfiguration{ - Certificate: a.option.Certificate.Certificate, - PrivateKey: a.option.Certificate.PrivateKey, - Force: true, - }, - }) - if err != nil { - return fmt.Errorf("deploy aliyun oss error: %w", err) - } - - return nil -} - -func (a *aliyun) createClient(accessKeyId, accessKeySecret string) (*oss.Client, error) { - client, err := oss.New( - getDeployString(a.option.DeployConfig, "endpoint"), - accessKeyId, - accessKeySecret, - ) - if err != nil { - return nil, fmt.Errorf("create aliyun client error: %w", err) - } - return client, nil -} diff --git a/internal/deployer/aliyun_cdn.go b/internal/deployer/aliyun_cdn.go index 0de5959f..75ae8e6e 100644 --- a/internal/deployer/aliyun_cdn.go +++ b/internal/deployer/aliyun_cdn.go @@ -14,63 +14,65 @@ import ( "certimate/internal/utils/rand" ) -type AliyunCdn struct { +type AliyunCDNDeployer struct { client *cdn20180510.Client option *DeployerOption infos []string } -func NewAliyunCdn(option *DeployerOption) (*AliyunCdn, error) { +func NewAliyunCdnDeployer(option *DeployerOption) (*AliyunCDNDeployer, error) { access := &domain.AliyunAccess{} json.Unmarshal([]byte(option.Access), access) - a := &AliyunCdn{ + + d := &AliyunCDNDeployer{ option: option, } - client, err := a.createClient(access.AccessKeyId, access.AccessKeySecret) + + client, err := d.createClient(access.AccessKeyId, access.AccessKeySecret) if err != nil { return nil, err } - return &AliyunCdn{ + return &AliyunCDNDeployer{ client: client, option: option, infos: make([]string, 0), }, nil } -func (a *AliyunCdn) GetID() string { - return fmt.Sprintf("%s-%s", a.option.AceessRecord.GetString("name"), a.option.AceessRecord.Id) +func (d *AliyunCDNDeployer) GetID() string { + return fmt.Sprintf("%s-%s", d.option.AceessRecord.GetString("name"), d.option.AceessRecord.Id) } -func (a *AliyunCdn) GetInfo() []string { - return a.infos +func (d *AliyunCDNDeployer) GetInfo() []string { + return d.infos } -func (a *AliyunCdn) Deploy(ctx context.Context) error { - certName := fmt.Sprintf("%s-%s-%s", a.option.Domain, a.option.DomainId, rand.RandStr(6)) +func (deployer *AliyunCDNDeployer) Deploy(ctx context.Context) error { + certName := fmt.Sprintf("%s-%s-%s", deployer.option.Domain, deployer.option.DomainId, rand.RandStr(6)) setCdnDomainSSLCertificateRequest := &cdn20180510.SetCdnDomainSSLCertificateRequest{ - DomainName: tea.String(getDeployString(a.option.DeployConfig, "domain")), + DomainName: tea.String(getDeployString(deployer.option.DeployConfig, "domain")), CertName: tea.String(certName), CertType: tea.String("upload"), SSLProtocol: tea.String("on"), - SSLPub: tea.String(a.option.Certificate.Certificate), - SSLPri: tea.String(a.option.Certificate.PrivateKey), + SSLPub: tea.String(deployer.option.Certificate.Certificate), + SSLPri: tea.String(deployer.option.Certificate.PrivateKey), CertRegion: tea.String("cn-hangzhou"), } runtime := &util.RuntimeOptions{} - resp, err := a.client.SetCdnDomainSSLCertificateWithOptions(setCdnDomainSSLCertificateRequest, runtime) + resp, err := deployer.client.SetCdnDomainSSLCertificateWithOptions(setCdnDomainSSLCertificateRequest, runtime) if err != nil { return err } - a.infos = append(a.infos, toStr("cdn设置证书", resp)) + deployer.infos = append(deployer.infos, toStr("cdn设置证书", resp)) return nil } -func (a *AliyunCdn) createClient(accessKeyId, accessKeySecret string) (_result *cdn20180510.Client, _err error) { +func (d *AliyunCDNDeployer) createClient(accessKeyId, accessKeySecret string) (_result *cdn20180510.Client, _err error) { config := &openapi.Config{ AccessKeyId: tea.String(accessKeyId), AccessKeySecret: tea.String(accessKeySecret), diff --git a/internal/deployer/aliyun_esa.go b/internal/deployer/aliyun_esa.go index 2115d796..6d83c2c5 100644 --- a/internal/deployer/aliyun_esa.go +++ b/internal/deployer/aliyun_esa.go @@ -19,63 +19,65 @@ import ( "certimate/internal/utils/rand" ) -type AliyunEsa struct { +type AliyunESADeployer struct { client *dcdn20180115.Client option *DeployerOption infos []string } -func NewAliyunEsa(option *DeployerOption) (*AliyunEsa, error) { +func NewAliyunEsaDeployer(option *DeployerOption) (*AliyunESADeployer, error) { access := &domain.AliyunAccess{} json.Unmarshal([]byte(option.Access), access) - a := &AliyunEsa{ + + d := &AliyunESADeployer{ option: option, } - client, err := a.createClient(access.AccessKeyId, access.AccessKeySecret) + + client, err := d.createClient(access.AccessKeyId, access.AccessKeySecret) if err != nil { return nil, err } - return &AliyunEsa{ + return &AliyunESADeployer{ client: client, option: option, infos: make([]string, 0), }, nil } -func (a *AliyunEsa) GetID() string { - return fmt.Sprintf("%s-%s", a.option.AceessRecord.GetString("name"), a.option.AceessRecord.Id) +func (d *AliyunESADeployer) GetID() string { + return fmt.Sprintf("%s-%s", d.option.AceessRecord.GetString("name"), d.option.AceessRecord.Id) } -func (a *AliyunEsa) GetInfo() []string { - return a.infos +func (d *AliyunESADeployer) GetInfo() []string { + return d.infos } -func (a *AliyunEsa) Deploy(ctx context.Context) error { - certName := fmt.Sprintf("%s-%s-%s", a.option.Domain, a.option.DomainId, rand.RandStr(6)) +func (d *AliyunESADeployer) Deploy(ctx context.Context) error { + certName := fmt.Sprintf("%s-%s-%s", d.option.Domain, d.option.DomainId, rand.RandStr(6)) setDcdnDomainSSLCertificateRequest := &dcdn20180115.SetDcdnDomainSSLCertificateRequest{ - DomainName: tea.String(getDeployString(a.option.DeployConfig, "domain")), + DomainName: tea.String(getDeployString(d.option.DeployConfig, "domain")), CertName: tea.String(certName), CertType: tea.String("upload"), SSLProtocol: tea.String("on"), - SSLPub: tea.String(a.option.Certificate.Certificate), - SSLPri: tea.String(a.option.Certificate.PrivateKey), + SSLPub: tea.String(d.option.Certificate.Certificate), + SSLPri: tea.String(d.option.Certificate.PrivateKey), CertRegion: tea.String("cn-hangzhou"), } runtime := &util.RuntimeOptions{} - resp, err := a.client.SetDcdnDomainSSLCertificateWithOptions(setDcdnDomainSSLCertificateRequest, runtime) + resp, err := d.client.SetDcdnDomainSSLCertificateWithOptions(setDcdnDomainSSLCertificateRequest, runtime) if err != nil { return err } - a.infos = append(a.infos, toStr("dcdn设置证书", resp)) + d.infos = append(d.infos, toStr("dcdn设置证书", resp)) return nil } -func (a *AliyunEsa) createClient(accessKeyId, accessKeySecret string) (_result *dcdn20180115.Client, _err error) { +func (d *AliyunESADeployer) createClient(accessKeyId, accessKeySecret string) (_result *dcdn20180115.Client, _err error) { config := &openapi.Config{ AccessKeyId: tea.String(accessKeyId), AccessKeySecret: tea.String(accessKeySecret), diff --git a/internal/deployer/aliyun_oss.go b/internal/deployer/aliyun_oss.go new file mode 100644 index 00000000..56e3a401 --- /dev/null +++ b/internal/deployer/aliyun_oss.go @@ -0,0 +1,70 @@ +package deployer + +import ( + "context" + "encoding/json" + "fmt" + + "github.com/aliyun/aliyun-oss-go-sdk/oss" + + "certimate/internal/domain" +) + +type AliyunOSSDeployer struct { + client *oss.Client + option *DeployerOption + infos []string +} + +func NewAliyunOssDeployer(option *DeployerOption) (Deployer, error) { + access := &domain.AliyunAccess{} + json.Unmarshal([]byte(option.Access), access) + + d := &AliyunOSSDeployer{ + option: option, + infos: make([]string, 0), + } + + client, err := d.createClient(access.AccessKeyId, access.AccessKeySecret) + if err != nil { + return nil, err + } + d.client = client + + return d, nil +} + +func (d *AliyunOSSDeployer) GetID() string { + return fmt.Sprintf("%s-%s", d.option.AceessRecord.GetString("name"), d.option.AceessRecord.Id) +} + +func (d *AliyunOSSDeployer) GetInfo() []string { + return d.infos +} + +func (d *AliyunOSSDeployer) Deploy(ctx context.Context) error { + err := d.client.PutBucketCnameWithCertificate(getDeployString(d.option.DeployConfig, "bucket"), oss.PutBucketCname{ + Cname: getDeployString(d.option.DeployConfig, "domain"), + CertificateConfiguration: &oss.CertificateConfiguration{ + Certificate: d.option.Certificate.Certificate, + PrivateKey: d.option.Certificate.PrivateKey, + Force: true, + }, + }) + if err != nil { + return fmt.Errorf("deploy aliyun oss error: %w", err) + } + return nil +} + +func (d *AliyunOSSDeployer) createClient(accessKeyId, accessKeySecret string) (*oss.Client, error) { + client, err := oss.New( + getDeployString(d.option.DeployConfig, "endpoint"), + accessKeyId, + accessKeySecret, + ) + if err != nil { + return nil, fmt.Errorf("create aliyun client error: %w", err) + } + return client, nil +} diff --git a/internal/deployer/deployer.go b/internal/deployer/deployer.go index d764c37d..b6640b3f 100644 --- a/internal/deployer/deployer.go +++ b/internal/deployer/deployer.go @@ -15,14 +15,14 @@ import ( ) const ( - targetAliyunOss = "aliyun-oss" - targetAliyunCdn = "aliyun-cdn" - targetAliyunEsa = "aliyun-dcdn" - targetSSH = "ssh" - targetWebhook = "webhook" - targetTencentCdn = "tencent-cdn" + targetAliyunOSS = "aliyun-oss" + targetAliyunCDN = "aliyun-cdn" + targetAliyunESA = "aliyun-dcdn" + targetTencentCDN = "tencent-cdn" targetQiniuCdn = "qiniu-cdn" targetLocal = "local" + targetSSH = "ssh" + targetWebhook = "webhook" ) type DeployerOption struct { @@ -60,7 +60,6 @@ func Gets(record *models.Record, cert *applicant.Certificate) ([]Deployer, error } for _, deployConfig := range deployConfigs { - deployer, err := getWithDeployConfig(record, cert, deployConfig) if err != nil { return nil, err @@ -96,23 +95,22 @@ func getWithDeployConfig(record *models.Record, cert *applicant.Certificate, dep } switch deployConfig.Type { - case targetAliyunOss: - return NewAliyun(option) - case targetAliyunCdn: - return NewAliyunCdn(option) - case targetAliyunEsa: - return NewAliyunEsa(option) - case targetSSH: - return NewSSH(option) - case targetWebhook: - return NewWebhook(option) - case targetTencentCdn: - return NewTencentCdn(option) + case targetAliyunOSS: + return NewAliyunOssDeployer(option) + case targetAliyunCDN: + return NewAliyunCdnDeployer(option) + case targetAliyunESA: + return NewAliyunEsaDeployer(option) + case targetTencentCDN: + return NewTencentCDNDeployer(option) case targetQiniuCdn: - - return NewQiNiu(option) + return NewQiniuCDNDeployer(option) case targetLocal: - return NewLocal(option), nil + return NewLocalDeployer(option) + case targetSSH: + return NewSSHDeployer(option) + case targetWebhook: + return NewWebhookDeployer(option) } return nil, errors.New("not implemented") } diff --git a/internal/deployer/local.go b/internal/deployer/local.go index f358215b..bf0ec5b6 100644 --- a/internal/deployer/local.go +++ b/internal/deployer/local.go @@ -10,35 +10,35 @@ import ( "runtime" ) -type localAccess struct{} +type LocalAccess struct{} -type local struct { +type LocalDeployer struct { option *DeployerOption infos []string } -func NewLocal(option *DeployerOption) *local { - return &local{ +func NewLocalDeployer(option *DeployerOption) (Deployer, error) { + return &LocalDeployer{ option: option, infos: make([]string, 0), - } + }, nil } -func (l *local) GetID() string { - return fmt.Sprintf("%s-%s", l.option.AceessRecord.GetString("name"), l.option.AceessRecord.Id) +func (d *LocalDeployer) GetID() string { + return fmt.Sprintf("%s-%s", d.option.AceessRecord.GetString("name"), d.option.AceessRecord.Id) } -func (l *local) GetInfo() []string { +func (d *LocalDeployer) GetInfo() []string { return []string{} } -func (l *local) Deploy(ctx context.Context) error { - access := &localAccess{} - if err := json.Unmarshal([]byte(l.option.Access), access); err != nil { +func (d *LocalDeployer) Deploy(ctx context.Context) error { + access := &LocalAccess{} + if err := json.Unmarshal([]byte(d.option.Access), access); err != nil { return err } - preCommand := getDeployString(l.option.DeployConfig, "preCommand") + preCommand := getDeployString(d.option.DeployConfig, "preCommand") if preCommand != "" { if err := execCmd(preCommand); err != nil { @@ -46,18 +46,18 @@ func (l *local) Deploy(ctx context.Context) error { } } - // 复制文件 - if err := copyFile(l.option.Certificate.Certificate, getDeployString(l.option.DeployConfig, "certPath")); err != nil { + // 复制证书文件 + if err := copyFile(getDeployString(d.option.DeployConfig, "certPath"), d.option.Certificate.Certificate); err != nil { return fmt.Errorf("复制证书失败: %w", err) } - if err := copyFile(l.option.Certificate.PrivateKey, getDeployString(l.option.DeployConfig, "keyPath")); err != nil { + // 复制私钥文件 + if err := copyFile(getDeployString(d.option.DeployConfig, "keyPath"), d.option.Certificate.PrivateKey); err != nil { return fmt.Errorf("复制私钥失败: %w", err) } // 执行命令 - - if err := execCmd(getDeployString(l.option.DeployConfig, "command")); err != nil { + if err := execCmd(getDeployString(d.option.DeployConfig, "command")); err != nil { return fmt.Errorf("执行命令失败: %w", err) } @@ -85,7 +85,7 @@ func execCmd(command string) error { return nil } -func copyFile(content string, path string) error { +func copyFile(path string, content string) error { dir := filepath.Dir(path) // 如果目录不存在,创建目录 diff --git a/internal/deployer/qiniu.go b/internal/deployer/qiniu_cdn.go similarity index 60% rename from internal/deployer/qiniu.go rename to internal/deployer/qiniu_cdn.go index 46ccee10..8b345fe3 100644 --- a/internal/deployer/qiniu.go +++ b/internal/deployer/qiniu_cdn.go @@ -16,17 +16,17 @@ import ( const qiniuGateway = "http://api.qiniu.com" -type qiuniu struct { +type QiniuCDNDeployer struct { option *DeployerOption info []string credentials *auth.Credentials } -func NewQiNiu(option *DeployerOption) (*qiuniu, error) { +func NewQiniuCDNDeployer(option *DeployerOption) (*QiniuCDNDeployer, error) { access := &domain.QiniuAccess{} json.Unmarshal([]byte(option.Access), access) - return &qiuniu{ + return &QiniuCDNDeployer{ option: option, info: make([]string, 0), @@ -34,41 +34,39 @@ func NewQiNiu(option *DeployerOption) (*qiuniu, error) { }, nil } -func (a *qiuniu) GetID() string { - return fmt.Sprintf("%s-%s", a.option.AceessRecord.GetString("name"), a.option.AceessRecord.Id) +func (d *QiniuCDNDeployer) GetID() string { + return fmt.Sprintf("%s-%s", d.option.AceessRecord.GetString("name"), d.option.AceessRecord.Id) } -func (q *qiuniu) GetInfo() []string { - return q.info +func (d *QiniuCDNDeployer) GetInfo() []string { + return d.info } -func (q *qiuniu) Deploy(ctx context.Context) error { +func (d *QiniuCDNDeployer) Deploy(ctx context.Context) error { // 上传证书 - certId, err := q.uploadCert() + certId, err := d.uploadCert() if err != nil { return fmt.Errorf("uploadCert failed: %w", err) } // 获取域名信息 - domainInfo, err := q.getDomainInfo() + domainInfo, err := d.getDomainInfo() if err != nil { return fmt.Errorf("getDomainInfo failed: %w", err) } // 判断域名是否启用 https - if domainInfo.Https != nil && domainInfo.Https.CertID != "" { // 启用了 https // 修改域名证书 - err = q.modifyDomainCert(certId) + err = d.modifyDomainCert(certId) if err != nil { return fmt.Errorf("modifyDomainCert failed: %w", err) } } else { // 没启用 https // 启用 https - - err = q.enableHttps(certId) + err = d.enableHttps(certId) if err != nil { return fmt.Errorf("enableHttps failed: %w", err) } @@ -77,10 +75,10 @@ func (q *qiuniu) Deploy(ctx context.Context) error { return nil } -func (q *qiuniu) enableHttps(certId string) error { - path := fmt.Sprintf("/domain/%s/sslize", getDeployString(q.option.DeployConfig, "domain")) +func (d *QiniuCDNDeployer) enableHttps(certId string) error { + path := fmt.Sprintf("/domain/%s/sslize", getDeployString(d.option.DeployConfig, "domain")) - body := &modifyDomainCertReq{ + body := &qiniuModifyDomainCertReq{ CertID: certId, ForceHttps: true, Http2Enable: true, @@ -91,7 +89,7 @@ func (q *qiuniu) enableHttps(certId string) error { return fmt.Errorf("enable https failed: %w", err) } - _, err = q.req(qiniuGateway+path, http.MethodPut, bytes.NewReader(bodyBytes)) + _, err = d.req(qiniuGateway+path, http.MethodPut, bytes.NewReader(bodyBytes)) if err != nil { return fmt.Errorf("enable https failed: %w", err) } @@ -99,19 +97,19 @@ func (q *qiuniu) enableHttps(certId string) error { return nil } -type domainInfo struct { - Https *modifyDomainCertReq `json:"https"` +type qiniuDomainInfo struct { + Https *qiniuModifyDomainCertReq `json:"https"` } -func (q *qiuniu) getDomainInfo() (*domainInfo, error) { - path := fmt.Sprintf("/domain/%s", getDeployString(q.option.DeployConfig, "domain")) +func (d *QiniuCDNDeployer) getDomainInfo() (*qiniuDomainInfo, error) { + path := fmt.Sprintf("/domain/%s", getDeployString(d.option.DeployConfig, "domain")) - res, err := q.req(qiniuGateway+path, http.MethodGet, nil) + res, err := d.req(qiniuGateway+path, http.MethodGet, nil) if err != nil { return nil, fmt.Errorf("req failed: %w", err) } - resp := &domainInfo{} + resp := &qiniuDomainInfo{} err = json.Unmarshal(res, resp) if err != nil { return nil, fmt.Errorf("json.Unmarshal failed: %w", err) @@ -120,25 +118,25 @@ func (q *qiuniu) getDomainInfo() (*domainInfo, error) { return resp, nil } -type uploadCertReq struct { +type qiniuUploadCertReq struct { Name string `json:"name"` CommonName string `json:"common_name"` Pri string `json:"pri"` Ca string `json:"ca"` } -type uploadCertResp struct { +type qiniuUploadCertResp struct { CertID string `json:"certID"` } -func (q *qiuniu) uploadCert() (string, error) { +func (d *QiniuCDNDeployer) uploadCert() (string, error) { path := "/sslcert" - body := &uploadCertReq{ - Name: getDeployString(q.option.DeployConfig, "domain"), - CommonName: getDeployString(q.option.DeployConfig, "domain"), - Pri: q.option.Certificate.PrivateKey, - Ca: q.option.Certificate.Certificate, + body := &qiniuUploadCertReq{ + Name: getDeployString(d.option.DeployConfig, "domain"), + CommonName: getDeployString(d.option.DeployConfig, "domain"), + Pri: d.option.Certificate.PrivateKey, + Ca: d.option.Certificate.Certificate, } bodyBytes, err := json.Marshal(body) @@ -146,11 +144,11 @@ func (q *qiuniu) uploadCert() (string, error) { return "", fmt.Errorf("json.Marshal failed: %w", err) } - res, err := q.req(qiniuGateway+path, http.MethodPost, bytes.NewReader(bodyBytes)) + res, err := d.req(qiniuGateway+path, http.MethodPost, bytes.NewReader(bodyBytes)) if err != nil { return "", fmt.Errorf("req failed: %w", err) } - resp := &uploadCertResp{} + resp := &qiniuUploadCertResp{} err = json.Unmarshal(res, resp) if err != nil { return "", fmt.Errorf("json.Unmarshal failed: %w", err) @@ -159,16 +157,16 @@ func (q *qiuniu) uploadCert() (string, error) { return resp.CertID, nil } -type modifyDomainCertReq struct { +type qiniuModifyDomainCertReq struct { CertID string `json:"certId"` ForceHttps bool `json:"forceHttps"` Http2Enable bool `json:"http2Enable"` } -func (q *qiuniu) modifyDomainCert(certId string) error { - path := fmt.Sprintf("/domain/%s/httpsconf", getDeployString(q.option.DeployConfig, "domain")) +func (d *QiniuCDNDeployer) modifyDomainCert(certId string) error { + path := fmt.Sprintf("/domain/%s/httpsconf", getDeployString(d.option.DeployConfig, "domain")) - body := &modifyDomainCertReq{ + body := &qiniuModifyDomainCertReq{ CertID: certId, ForceHttps: true, Http2Enable: true, @@ -179,7 +177,7 @@ func (q *qiuniu) modifyDomainCert(certId string) error { return fmt.Errorf("json.Marshal failed: %w", err) } - _, err = q.req(qiniuGateway+path, http.MethodPut, bytes.NewReader(bodyBytes)) + _, err = d.req(qiniuGateway+path, http.MethodPut, bytes.NewReader(bodyBytes)) if err != nil { return fmt.Errorf("req failed: %w", err) } @@ -187,12 +185,12 @@ func (q *qiuniu) modifyDomainCert(certId string) error { return nil } -func (q *qiuniu) req(url, method string, body io.Reader) ([]byte, error) { +func (d *QiniuCDNDeployer) req(url, method string, body io.Reader) ([]byte, error) { req := xhttp.BuildReq(url, method, body, map[string]string{ "Content-Type": "application/json", }) - if err := q.credentials.AddToken(auth.TokenQBox, req); err != nil { + if err := d.credentials.AddToken(auth.TokenQBox, req); err != nil { return nil, fmt.Errorf("credentials.AddToken failed: %w", err) } diff --git a/internal/deployer/qiniu_test.go b/internal/deployer/qiniu_cdn_test.go similarity index 94% rename from internal/deployer/qiniu_test.go rename to internal/deployer/qiniu_cdn_test.go index 38b54960..7e625dfb 100644 --- a/internal/deployer/qiniu_test.go +++ b/internal/deployer/qiniu_cdn_test.go @@ -36,7 +36,7 @@ func Test_qiuniu_uploadCert(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - q, _ := NewQiNiu(tt.fields.option) + q, _ := NewQiniuCDNDeployer(tt.fields.option) got, err := q.uploadCert() if (err != nil) != tt.wantErr { t.Errorf("qiuniu.uploadCert() error = %v, wantErr %v", err, tt.wantErr) @@ -78,7 +78,7 @@ func Test_qiuniu_modifyDomainCert(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - q, _ := NewQiNiu(tt.fields.option) + q, _ := NewQiniuCDNDeployer(tt.fields.option) if err := q.modifyDomainCert(tt.args.certId); (err != nil) != tt.wantErr { t.Errorf("qiuniu.modifyDomainCert() error = %v, wantErr %v", err, tt.wantErr) } diff --git a/internal/deployer/ssh.go b/internal/deployer/ssh.go index 635a0639..14df1aea 100644 --- a/internal/deployer/ssh.go +++ b/internal/deployer/ssh.go @@ -12,12 +12,7 @@ import ( sshPkg "golang.org/x/crypto/ssh" ) -type ssh struct { - option *DeployerOption - infos []string -} - -type sshAccess struct { +type SSHAccess struct { Host string `json:"host"` Port string `json:"port"` Username string `json:"username"` @@ -26,71 +21,76 @@ type sshAccess struct { KeyPassphrase string `json:"keyPassphrase"` } -func NewSSH(option *DeployerOption) (Deployer, error) { - return &ssh{ +type SSHDeployer struct { + option *DeployerOption + infos []string +} + +func NewSSHDeployer(option *DeployerOption) (Deployer, error) { + return &SSHDeployer{ option: option, infos: make([]string, 0), }, nil } -func (a *ssh) GetID() string { - return fmt.Sprintf("%s-%s", a.option.AceessRecord.GetString("name"), a.option.AceessRecord.Id) +func (d *SSHDeployer) GetID() string { + return fmt.Sprintf("%s-%s", d.option.AceessRecord.GetString("name"), d.option.AceessRecord.Id) } -func (s *ssh) GetInfo() []string { - return s.infos +func (d *SSHDeployer) GetInfo() []string { + return d.infos } -func (s *ssh) Deploy(ctx context.Context) error { - access := &sshAccess{} - if err := json.Unmarshal([]byte(s.option.Access), access); err != nil { +func (d *SSHDeployer) Deploy(ctx context.Context) error { + access := &SSHAccess{} + if err := json.Unmarshal([]byte(d.option.Access), access); err != nil { return err } // 连接 - client, err := s.getClient(access) + client, err := d.createClient(access) if err != nil { return err } defer client.Close() - s.infos = append(s.infos, toStr("ssh连接成功", nil)) + d.infos = append(d.infos, toStr("ssh连接成功", nil)) // 执行前置命令 - preCommand := getDeployString(s.option.DeployConfig, "preCommand") + preCommand := getDeployString(d.option.DeployConfig, "preCommand") if preCommand != "" { - stdout, stderr, err := s.sshExecCommand(client, preCommand) + stdout, stderr, err := d.sshExecCommand(client, preCommand) if err != nil { return fmt.Errorf("failed to run pre-command: %w, stdout: %s, stderr: %s", err, stdout, stderr) } } // 上传证书 - if err := s.upload(client, s.option.Certificate.Certificate, getDeployString(s.option.DeployConfig, "certPath")); err != nil { + if err := d.upload(client, d.option.Certificate.Certificate, getDeployString(d.option.DeployConfig, "certPath")); err != nil { return fmt.Errorf("failed to upload certificate: %w", err) } - s.infos = append(s.infos, toStr("ssh上传证书成功", nil)) + d.infos = append(d.infos, toStr("ssh上传证书成功", nil)) // 上传私钥 - if err := s.upload(client, s.option.Certificate.PrivateKey, getDeployString(s.option.DeployConfig, "keyPath")); err != nil { + if err := d.upload(client, d.option.Certificate.PrivateKey, getDeployString(d.option.DeployConfig, "keyPath")); err != nil { return fmt.Errorf("failed to upload private key: %w", err) } - s.infos = append(s.infos, toStr("ssh上传私钥成功", nil)) + d.infos = append(d.infos, toStr("ssh上传私钥成功", nil)) // 执行命令 - stdout, stderr, err := s.sshExecCommand(client, getDeployString(s.option.DeployConfig, "command")) + stdout, stderr, err := d.sshExecCommand(client, getDeployString(d.option.DeployConfig, "command")) if err != nil { return fmt.Errorf("failed to run command: %w, stdout: %s, stderr: %s", err, stdout, stderr) } - s.infos = append(s.infos, toStr("ssh执行命令成功", stdout)) + d.infos = append(d.infos, toStr("ssh执行命令成功", stdout)) return nil } -func (s *ssh) sshExecCommand(client *sshPkg.Client, command string) (string, string, error) { +func (d *SSHDeployer) sshExecCommand(client *sshPkg.Client, command string) (string, string, error) { session, err := client.NewSession() if err != nil { return "", "", fmt.Errorf("failed to create ssh session: %w", err) @@ -105,7 +105,7 @@ func (s *ssh) sshExecCommand(client *sshPkg.Client, command string) (string, str return stdoutBuf.String(), stderrBuf.String(), err } -func (s *ssh) upload(client *sshPkg.Client, content, path string) error { +func (d *SSHDeployer) upload(client *sshPkg.Client, content, path string) error { sftpCli, err := sftp.NewClient(client) if err != nil { return fmt.Errorf("failed to create sftp client: %w", err) @@ -130,7 +130,7 @@ func (s *ssh) upload(client *sshPkg.Client, content, path string) error { return nil } -func (s *ssh) getClient(access *sshAccess) (*sshPkg.Client, error) { +func (d *SSHDeployer) createClient(access *SSHAccess) (*sshPkg.Client, error) { var authMethod sshPkg.AuthMethod if access.Key != "" { diff --git a/internal/deployer/tencent_cdn.go b/internal/deployer/tencent_cdn.go index 3da84775..69b3ecd3 100644 --- a/internal/deployer/tencent_cdn.go +++ b/internal/deployer/tencent_cdn.go @@ -16,13 +16,13 @@ import ( "certimate/internal/utils/rand" ) -type tencentCdn struct { +type TencentCDNDeployer struct { option *DeployerOption credential *common.Credential infos []string } -func NewTencentCdn(option *DeployerOption) (Deployer, error) { +func NewTencentCDNDeployer(option *DeployerOption) (Deployer, error) { access := &domain.TencentAccess{} if err := json.Unmarshal([]byte(option.Access), access); err != nil { return nil, fmt.Errorf("failed to unmarshal tencent access: %w", err) @@ -33,47 +33,47 @@ func NewTencentCdn(option *DeployerOption) (Deployer, error) { access.SecretKey, ) - return &tencentCdn{ + return &TencentCDNDeployer{ option: option, credential: credential, infos: make([]string, 0), }, nil } -func (a *tencentCdn) GetID() string { - return fmt.Sprintf("%s-%s", a.option.AceessRecord.GetString("name"), a.option.AceessRecord.Id) +func (d *TencentCDNDeployer) GetID() string { + return fmt.Sprintf("%s-%s", d.option.AceessRecord.GetString("name"), d.option.AceessRecord.Id) } -func (t *tencentCdn) GetInfo() []string { - return t.infos +func (d *TencentCDNDeployer) GetInfo() []string { + return d.infos } -func (t *tencentCdn) Deploy(ctx context.Context) error { +func (d *TencentCDNDeployer) Deploy(ctx context.Context) error { // 上传证书 - certId, err := t.uploadCert() + certId, err := d.uploadCert() if err != nil { return fmt.Errorf("failed to upload certificate: %w", err) } - t.infos = append(t.infos, toStr("上传证书", certId)) + d.infos = append(d.infos, toStr("上传证书", certId)) - if err := t.deploy(certId); err != nil { + if err := d.deploy(certId); err != nil { return fmt.Errorf("failed to deploy: %w", err) } return nil } -func (t *tencentCdn) uploadCert() (string, error) { +func (d *TencentCDNDeployer) uploadCert() (string, error) { cpf := profile.NewClientProfile() cpf.HttpProfile.Endpoint = "ssl.tencentcloudapi.com" - client, _ := ssl.NewClient(t.credential, "", cpf) + client, _ := ssl.NewClient(d.credential, "", cpf) request := ssl.NewUploadCertificateRequest() - request.CertificatePublicKey = common.StringPtr(t.option.Certificate.Certificate) - request.CertificatePrivateKey = common.StringPtr(t.option.Certificate.PrivateKey) - request.Alias = common.StringPtr(t.option.Domain + "_" + rand.RandStr(6)) + request.CertificatePublicKey = common.StringPtr(d.option.Certificate.Certificate) + request.CertificatePrivateKey = common.StringPtr(d.option.Certificate.PrivateKey) + request.Alias = common.StringPtr(d.option.Domain + "_" + rand.RandStr(6)) request.Repeatable = common.BoolPtr(false) response, err := client.UploadCertificate(request) @@ -84,11 +84,11 @@ func (t *tencentCdn) uploadCert() (string, error) { return *response.Response.CertificateId, nil } -func (t *tencentCdn) deploy(certId string) error { +func (d *TencentCDNDeployer) deploy(certId string) error { cpf := profile.NewClientProfile() cpf.HttpProfile.Endpoint = "ssl.tencentcloudapi.com" // 实例化要请求产品的client对象,clientProfile是可选的 - client, _ := ssl.NewClient(t.credential, "", cpf) + client, _ := ssl.NewClient(d.credential, "", cpf) // 实例化一个请求对象,每个接口都会对应一个request对象 request := ssl.NewDeployCertificateInstanceRequest() @@ -98,9 +98,9 @@ func (t *tencentCdn) deploy(certId string) error { request.Status = common.Int64Ptr(1) // 如果是泛域名就从cdn列表下获取SSL证书中的可用域名 - domain := getDeployString(t.option.DeployConfig, "domain") + domain := getDeployString(d.option.DeployConfig, "domain") if strings.Contains(domain, "*") { - list, errGetList := t.getDomainList() + list, errGetList := d.getDomainList() if errGetList != nil { return fmt.Errorf("failed to get certificate domain list: %w", errGetList) } @@ -117,18 +117,18 @@ func (t *tencentCdn) deploy(certId string) error { if err != nil { return fmt.Errorf("failed to deploy certificate: %w", err) } - t.infos = append(t.infos, toStr("部署证书", resp.Response)) + d.infos = append(d.infos, toStr("部署证书", resp.Response)) return nil } -func (t *tencentCdn) getDomainList() ([]string, error) { +func (d *TencentCDNDeployer) getDomainList() ([]string, error) { cpf := profile.NewClientProfile() cpf.HttpProfile.Endpoint = "cdn.tencentcloudapi.com" - client, _ := cdn.NewClient(t.credential, "", cpf) + client, _ := cdn.NewClient(d.credential, "", cpf) request := cdn.NewDescribeCertDomainsRequest() - cert := base64.StdEncoding.EncodeToString([]byte(t.option.Certificate.Certificate)) + cert := base64.StdEncoding.EncodeToString([]byte(d.option.Certificate.Certificate)) request.Cert = &cert response, err := client.DescribeCertDomains(request) diff --git a/internal/deployer/webhook.go b/internal/deployer/webhook.go index ce84f312..be2a5b34 100644 --- a/internal/deployer/webhook.go +++ b/internal/deployer/webhook.go @@ -10,48 +10,48 @@ import ( xhttp "certimate/internal/utils/http" ) -type webhookAccess struct { +type WebhookAccess struct { Url string `json:"url"` } -type hookData struct { +type WebhookDeployer struct { + option *DeployerOption + infos []string +} + +func NewWebhookDeployer(option *DeployerOption) (Deployer, error) { + return &WebhookDeployer{ + option: option, + infos: make([]string, 0), + }, nil +} + +func (d *WebhookDeployer) GetID() string { + return fmt.Sprintf("%s-%s", d.option.AceessRecord.GetString("name"), d.option.AceessRecord.Id) +} + +func (d *WebhookDeployer) GetInfo() []string { + return d.infos +} + +type webhookData struct { Domain string `json:"domain"` Certificate string `json:"certificate"` PrivateKey string `json:"privateKey"` Variables map[string]string `json:"variables"` } -type webhook struct { - option *DeployerOption - infos []string -} - -func NewWebhook(option *DeployerOption) (Deployer, error) { - return &webhook{ - option: option, - infos: make([]string, 0), - }, nil -} - -func (a *webhook) GetID() string { - return fmt.Sprintf("%s-%s", a.option.AceessRecord.GetString("name"), a.option.AceessRecord.Id) -} - -func (w *webhook) GetInfo() []string { - return w.infos -} - -func (w *webhook) Deploy(ctx context.Context) error { - access := &webhookAccess{} - if err := json.Unmarshal([]byte(w.option.Access), access); err != nil { +func (d *WebhookDeployer) Deploy(ctx context.Context) error { + access := &WebhookAccess{} + if err := json.Unmarshal([]byte(d.option.Access), access); err != nil { return fmt.Errorf("failed to parse hook access config: %w", err) } - data := &hookData{ - Domain: w.option.Domain, - Certificate: w.option.Certificate.Certificate, - PrivateKey: w.option.Certificate.PrivateKey, - Variables: getDeployVariables(w.option.DeployConfig), + data := &webhookData{ + Domain: d.option.Domain, + Certificate: d.option.Certificate.Certificate, + PrivateKey: d.option.Certificate.PrivateKey, + Variables: getDeployVariables(d.option.DeployConfig), } body, _ := json.Marshal(data) @@ -63,7 +63,7 @@ func (w *webhook) Deploy(ctx context.Context) error { return fmt.Errorf("failed to send hook request: %w", err) } - w.infos = append(w.infos, toStr("webhook response", string(resp))) + d.infos = append(d.infos, toStr("webhook response", string(resp))) return nil }