refactor

refactor
main
Fu Diwei 2024-10-18 12:16:14 +08:00
parent 3c4b7d251a
commit 3093fc6b02
12 changed files with 272 additions and 269 deletions

View File

@ -1,12 +1,13 @@
package applicant package applicant
import ( import (
"certimate/internal/domain"
"encoding/json" "encoding/json"
"fmt" "fmt"
"os" "os"
"github.com/go-acme/lego/v4/providers/dns/route53" "github.com/go-acme/lego/v4/providers/dns/route53"
"certimate/internal/domain"
) )
type aws struct { type aws struct {

View File

@ -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
}

View File

@ -14,63 +14,65 @@ import (
"certimate/internal/utils/rand" "certimate/internal/utils/rand"
) )
type AliyunCdn struct { type AliyunCDNDeployer struct {
client *cdn20180510.Client client *cdn20180510.Client
option *DeployerOption option *DeployerOption
infos []string infos []string
} }
func NewAliyunCdn(option *DeployerOption) (*AliyunCdn, error) { func NewAliyunCdnDeployer(option *DeployerOption) (*AliyunCDNDeployer, error) {
access := &domain.AliyunAccess{} access := &domain.AliyunAccess{}
json.Unmarshal([]byte(option.Access), access) json.Unmarshal([]byte(option.Access), access)
a := &AliyunCdn{
d := &AliyunCDNDeployer{
option: option, option: option,
} }
client, err := a.createClient(access.AccessKeyId, access.AccessKeySecret)
client, err := d.createClient(access.AccessKeyId, access.AccessKeySecret)
if err != nil { if err != nil {
return nil, err return nil, err
} }
return &AliyunCdn{ return &AliyunCDNDeployer{
client: client, client: client,
option: option, option: option,
infos: make([]string, 0), infos: make([]string, 0),
}, nil }, nil
} }
func (a *AliyunCdn) GetID() string { func (d *AliyunCDNDeployer) GetID() string {
return fmt.Sprintf("%s-%s", a.option.AceessRecord.GetString("name"), a.option.AceessRecord.Id) return fmt.Sprintf("%s-%s", d.option.AceessRecord.GetString("name"), d.option.AceessRecord.Id)
} }
func (a *AliyunCdn) GetInfo() []string { func (d *AliyunCDNDeployer) GetInfo() []string {
return a.infos return d.infos
} }
func (a *AliyunCdn) Deploy(ctx context.Context) error { func (deployer *AliyunCDNDeployer) Deploy(ctx context.Context) error {
certName := fmt.Sprintf("%s-%s-%s", a.option.Domain, a.option.DomainId, rand.RandStr(6)) certName := fmt.Sprintf("%s-%s-%s", deployer.option.Domain, deployer.option.DomainId, rand.RandStr(6))
setCdnDomainSSLCertificateRequest := &cdn20180510.SetCdnDomainSSLCertificateRequest{ setCdnDomainSSLCertificateRequest := &cdn20180510.SetCdnDomainSSLCertificateRequest{
DomainName: tea.String(getDeployString(a.option.DeployConfig, "domain")), DomainName: tea.String(getDeployString(deployer.option.DeployConfig, "domain")),
CertName: tea.String(certName), CertName: tea.String(certName),
CertType: tea.String("upload"), CertType: tea.String("upload"),
SSLProtocol: tea.String("on"), SSLProtocol: tea.String("on"),
SSLPub: tea.String(a.option.Certificate.Certificate), SSLPub: tea.String(deployer.option.Certificate.Certificate),
SSLPri: tea.String(a.option.Certificate.PrivateKey), SSLPri: tea.String(deployer.option.Certificate.PrivateKey),
CertRegion: tea.String("cn-hangzhou"), CertRegion: tea.String("cn-hangzhou"),
} }
runtime := &util.RuntimeOptions{} runtime := &util.RuntimeOptions{}
resp, err := a.client.SetCdnDomainSSLCertificateWithOptions(setCdnDomainSSLCertificateRequest, runtime) resp, err := deployer.client.SetCdnDomainSSLCertificateWithOptions(setCdnDomainSSLCertificateRequest, runtime)
if err != nil { if err != nil {
return err return err
} }
a.infos = append(a.infos, toStr("cdn设置证书", resp)) deployer.infos = append(deployer.infos, toStr("cdn设置证书", resp))
return nil 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{ config := &openapi.Config{
AccessKeyId: tea.String(accessKeyId), AccessKeyId: tea.String(accessKeyId),
AccessKeySecret: tea.String(accessKeySecret), AccessKeySecret: tea.String(accessKeySecret),

View File

@ -19,63 +19,65 @@ import (
"certimate/internal/utils/rand" "certimate/internal/utils/rand"
) )
type AliyunEsa struct { type AliyunESADeployer struct {
client *dcdn20180115.Client client *dcdn20180115.Client
option *DeployerOption option *DeployerOption
infos []string infos []string
} }
func NewAliyunEsa(option *DeployerOption) (*AliyunEsa, error) { func NewAliyunEsaDeployer(option *DeployerOption) (*AliyunESADeployer, error) {
access := &domain.AliyunAccess{} access := &domain.AliyunAccess{}
json.Unmarshal([]byte(option.Access), access) json.Unmarshal([]byte(option.Access), access)
a := &AliyunEsa{
d := &AliyunESADeployer{
option: option, option: option,
} }
client, err := a.createClient(access.AccessKeyId, access.AccessKeySecret)
client, err := d.createClient(access.AccessKeyId, access.AccessKeySecret)
if err != nil { if err != nil {
return nil, err return nil, err
} }
return &AliyunEsa{ return &AliyunESADeployer{
client: client, client: client,
option: option, option: option,
infos: make([]string, 0), infos: make([]string, 0),
}, nil }, nil
} }
func (a *AliyunEsa) GetID() string { func (d *AliyunESADeployer) GetID() string {
return fmt.Sprintf("%s-%s", a.option.AceessRecord.GetString("name"), a.option.AceessRecord.Id) return fmt.Sprintf("%s-%s", d.option.AceessRecord.GetString("name"), d.option.AceessRecord.Id)
} }
func (a *AliyunEsa) GetInfo() []string { func (d *AliyunESADeployer) GetInfo() []string {
return a.infos return d.infos
} }
func (a *AliyunEsa) Deploy(ctx context.Context) error { func (d *AliyunESADeployer) Deploy(ctx context.Context) error {
certName := fmt.Sprintf("%s-%s-%s", a.option.Domain, a.option.DomainId, rand.RandStr(6)) certName := fmt.Sprintf("%s-%s-%s", d.option.Domain, d.option.DomainId, rand.RandStr(6))
setDcdnDomainSSLCertificateRequest := &dcdn20180115.SetDcdnDomainSSLCertificateRequest{ setDcdnDomainSSLCertificateRequest := &dcdn20180115.SetDcdnDomainSSLCertificateRequest{
DomainName: tea.String(getDeployString(a.option.DeployConfig, "domain")), DomainName: tea.String(getDeployString(d.option.DeployConfig, "domain")),
CertName: tea.String(certName), CertName: tea.String(certName),
CertType: tea.String("upload"), CertType: tea.String("upload"),
SSLProtocol: tea.String("on"), SSLProtocol: tea.String("on"),
SSLPub: tea.String(a.option.Certificate.Certificate), SSLPub: tea.String(d.option.Certificate.Certificate),
SSLPri: tea.String(a.option.Certificate.PrivateKey), SSLPri: tea.String(d.option.Certificate.PrivateKey),
CertRegion: tea.String("cn-hangzhou"), CertRegion: tea.String("cn-hangzhou"),
} }
runtime := &util.RuntimeOptions{} runtime := &util.RuntimeOptions{}
resp, err := a.client.SetDcdnDomainSSLCertificateWithOptions(setDcdnDomainSSLCertificateRequest, runtime) resp, err := d.client.SetDcdnDomainSSLCertificateWithOptions(setDcdnDomainSSLCertificateRequest, runtime)
if err != nil { if err != nil {
return err return err
} }
a.infos = append(a.infos, toStr("dcdn设置证书", resp)) d.infos = append(d.infos, toStr("dcdn设置证书", resp))
return nil 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{ config := &openapi.Config{
AccessKeyId: tea.String(accessKeyId), AccessKeyId: tea.String(accessKeyId),
AccessKeySecret: tea.String(accessKeySecret), AccessKeySecret: tea.String(accessKeySecret),

View File

@ -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
}

View File

@ -15,14 +15,14 @@ import (
) )
const ( const (
targetAliyunOss = "aliyun-oss" targetAliyunOSS = "aliyun-oss"
targetAliyunCdn = "aliyun-cdn" targetAliyunCDN = "aliyun-cdn"
targetAliyunEsa = "aliyun-dcdn" targetAliyunESA = "aliyun-dcdn"
targetSSH = "ssh" targetTencentCDN = "tencent-cdn"
targetWebhook = "webhook"
targetTencentCdn = "tencent-cdn"
targetQiniuCdn = "qiniu-cdn" targetQiniuCdn = "qiniu-cdn"
targetLocal = "local" targetLocal = "local"
targetSSH = "ssh"
targetWebhook = "webhook"
) )
type DeployerOption struct { type DeployerOption struct {
@ -60,7 +60,6 @@ func Gets(record *models.Record, cert *applicant.Certificate) ([]Deployer, error
} }
for _, deployConfig := range deployConfigs { for _, deployConfig := range deployConfigs {
deployer, err := getWithDeployConfig(record, cert, deployConfig) deployer, err := getWithDeployConfig(record, cert, deployConfig)
if err != nil { if err != nil {
return nil, err return nil, err
@ -96,23 +95,22 @@ func getWithDeployConfig(record *models.Record, cert *applicant.Certificate, dep
} }
switch deployConfig.Type { switch deployConfig.Type {
case targetAliyunOss: case targetAliyunOSS:
return NewAliyun(option) return NewAliyunOssDeployer(option)
case targetAliyunCdn: case targetAliyunCDN:
return NewAliyunCdn(option) return NewAliyunCdnDeployer(option)
case targetAliyunEsa: case targetAliyunESA:
return NewAliyunEsa(option) return NewAliyunEsaDeployer(option)
case targetSSH: case targetTencentCDN:
return NewSSH(option) return NewTencentCDNDeployer(option)
case targetWebhook:
return NewWebhook(option)
case targetTencentCdn:
return NewTencentCdn(option)
case targetQiniuCdn: case targetQiniuCdn:
return NewQiniuCDNDeployer(option)
return NewQiNiu(option)
case targetLocal: 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") return nil, errors.New("not implemented")
} }

View File

@ -10,35 +10,35 @@ import (
"runtime" "runtime"
) )
type localAccess struct{} type LocalAccess struct{}
type local struct { type LocalDeployer struct {
option *DeployerOption option *DeployerOption
infos []string infos []string
} }
func NewLocal(option *DeployerOption) *local { func NewLocalDeployer(option *DeployerOption) (Deployer, error) {
return &local{ return &LocalDeployer{
option: option, option: option,
infos: make([]string, 0), infos: make([]string, 0),
} }, nil
} }
func (l *local) GetID() string { func (d *LocalDeployer) GetID() string {
return fmt.Sprintf("%s-%s", l.option.AceessRecord.GetString("name"), l.option.AceessRecord.Id) 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{} return []string{}
} }
func (l *local) Deploy(ctx context.Context) error { func (d *LocalDeployer) Deploy(ctx context.Context) error {
access := &localAccess{} access := &LocalAccess{}
if err := json.Unmarshal([]byte(l.option.Access), access); err != nil { if err := json.Unmarshal([]byte(d.option.Access), access); err != nil {
return err return err
} }
preCommand := getDeployString(l.option.DeployConfig, "preCommand") preCommand := getDeployString(d.option.DeployConfig, "preCommand")
if preCommand != "" { if preCommand != "" {
if err := execCmd(preCommand); err != nil { 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) 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) return fmt.Errorf("复制私钥失败: %w", err)
} }
// 执行命令 // 执行命令
if err := execCmd(getDeployString(d.option.DeployConfig, "command")); err != nil {
if err := execCmd(getDeployString(l.option.DeployConfig, "command")); err != nil {
return fmt.Errorf("执行命令失败: %w", err) return fmt.Errorf("执行命令失败: %w", err)
} }
@ -85,7 +85,7 @@ func execCmd(command string) error {
return nil return nil
} }
func copyFile(content string, path string) error { func copyFile(path string, content string) error {
dir := filepath.Dir(path) dir := filepath.Dir(path)
// 如果目录不存在,创建目录 // 如果目录不存在,创建目录

View File

@ -16,17 +16,17 @@ import (
const qiniuGateway = "http://api.qiniu.com" const qiniuGateway = "http://api.qiniu.com"
type qiuniu struct { type QiniuCDNDeployer struct {
option *DeployerOption option *DeployerOption
info []string info []string
credentials *auth.Credentials credentials *auth.Credentials
} }
func NewQiNiu(option *DeployerOption) (*qiuniu, error) { func NewQiniuCDNDeployer(option *DeployerOption) (*QiniuCDNDeployer, error) {
access := &domain.QiniuAccess{} access := &domain.QiniuAccess{}
json.Unmarshal([]byte(option.Access), access) json.Unmarshal([]byte(option.Access), access)
return &qiuniu{ return &QiniuCDNDeployer{
option: option, option: option,
info: make([]string, 0), info: make([]string, 0),
@ -34,41 +34,39 @@ func NewQiNiu(option *DeployerOption) (*qiuniu, error) {
}, nil }, nil
} }
func (a *qiuniu) GetID() string { func (d *QiniuCDNDeployer) GetID() string {
return fmt.Sprintf("%s-%s", a.option.AceessRecord.GetString("name"), a.option.AceessRecord.Id) return fmt.Sprintf("%s-%s", d.option.AceessRecord.GetString("name"), d.option.AceessRecord.Id)
} }
func (q *qiuniu) GetInfo() []string { func (d *QiniuCDNDeployer) GetInfo() []string {
return q.info 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 { if err != nil {
return fmt.Errorf("uploadCert failed: %w", err) return fmt.Errorf("uploadCert failed: %w", err)
} }
// 获取域名信息 // 获取域名信息
domainInfo, err := q.getDomainInfo() domainInfo, err := d.getDomainInfo()
if err != nil { if err != nil {
return fmt.Errorf("getDomainInfo failed: %w", err) return fmt.Errorf("getDomainInfo failed: %w", err)
} }
// 判断域名是否启用 https // 判断域名是否启用 https
if domainInfo.Https != nil && domainInfo.Https.CertID != "" { if domainInfo.Https != nil && domainInfo.Https.CertID != "" {
// 启用了 https // 启用了 https
// 修改域名证书 // 修改域名证书
err = q.modifyDomainCert(certId) err = d.modifyDomainCert(certId)
if err != nil { if err != nil {
return fmt.Errorf("modifyDomainCert failed: %w", err) return fmt.Errorf("modifyDomainCert failed: %w", err)
} }
} else { } else {
// 没启用 https // 没启用 https
// 启用 https // 启用 https
err = d.enableHttps(certId)
err = q.enableHttps(certId)
if err != nil { if err != nil {
return fmt.Errorf("enableHttps failed: %w", err) return fmt.Errorf("enableHttps failed: %w", err)
} }
@ -77,10 +75,10 @@ func (q *qiuniu) Deploy(ctx context.Context) error {
return nil return nil
} }
func (q *qiuniu) enableHttps(certId string) error { func (d *QiniuCDNDeployer) enableHttps(certId string) error {
path := fmt.Sprintf("/domain/%s/sslize", getDeployString(q.option.DeployConfig, "domain")) path := fmt.Sprintf("/domain/%s/sslize", getDeployString(d.option.DeployConfig, "domain"))
body := &modifyDomainCertReq{ body := &qiniuModifyDomainCertReq{
CertID: certId, CertID: certId,
ForceHttps: true, ForceHttps: true,
Http2Enable: true, Http2Enable: true,
@ -91,7 +89,7 @@ func (q *qiuniu) enableHttps(certId string) error {
return fmt.Errorf("enable https failed: %w", err) 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 { if err != nil {
return fmt.Errorf("enable https failed: %w", err) return fmt.Errorf("enable https failed: %w", err)
} }
@ -99,19 +97,19 @@ func (q *qiuniu) enableHttps(certId string) error {
return nil return nil
} }
type domainInfo struct { type qiniuDomainInfo struct {
Https *modifyDomainCertReq `json:"https"` Https *qiniuModifyDomainCertReq `json:"https"`
} }
func (q *qiuniu) getDomainInfo() (*domainInfo, error) { func (d *QiniuCDNDeployer) getDomainInfo() (*qiniuDomainInfo, error) {
path := fmt.Sprintf("/domain/%s", getDeployString(q.option.DeployConfig, "domain")) 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 { if err != nil {
return nil, fmt.Errorf("req failed: %w", err) return nil, fmt.Errorf("req failed: %w", err)
} }
resp := &domainInfo{} resp := &qiniuDomainInfo{}
err = json.Unmarshal(res, resp) err = json.Unmarshal(res, resp)
if err != nil { if err != nil {
return nil, fmt.Errorf("json.Unmarshal failed: %w", err) return nil, fmt.Errorf("json.Unmarshal failed: %w", err)
@ -120,25 +118,25 @@ func (q *qiuniu) getDomainInfo() (*domainInfo, error) {
return resp, nil return resp, nil
} }
type uploadCertReq struct { type qiniuUploadCertReq struct {
Name string `json:"name"` Name string `json:"name"`
CommonName string `json:"common_name"` CommonName string `json:"common_name"`
Pri string `json:"pri"` Pri string `json:"pri"`
Ca string `json:"ca"` Ca string `json:"ca"`
} }
type uploadCertResp struct { type qiniuUploadCertResp struct {
CertID string `json:"certID"` CertID string `json:"certID"`
} }
func (q *qiuniu) uploadCert() (string, error) { func (d *QiniuCDNDeployer) uploadCert() (string, error) {
path := "/sslcert" path := "/sslcert"
body := &uploadCertReq{ body := &qiniuUploadCertReq{
Name: getDeployString(q.option.DeployConfig, "domain"), Name: getDeployString(d.option.DeployConfig, "domain"),
CommonName: getDeployString(q.option.DeployConfig, "domain"), CommonName: getDeployString(d.option.DeployConfig, "domain"),
Pri: q.option.Certificate.PrivateKey, Pri: d.option.Certificate.PrivateKey,
Ca: q.option.Certificate.Certificate, Ca: d.option.Certificate.Certificate,
} }
bodyBytes, err := json.Marshal(body) bodyBytes, err := json.Marshal(body)
@ -146,11 +144,11 @@ func (q *qiuniu) uploadCert() (string, error) {
return "", fmt.Errorf("json.Marshal failed: %w", err) 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 { if err != nil {
return "", fmt.Errorf("req failed: %w", err) return "", fmt.Errorf("req failed: %w", err)
} }
resp := &uploadCertResp{} resp := &qiniuUploadCertResp{}
err = json.Unmarshal(res, resp) err = json.Unmarshal(res, resp)
if err != nil { if err != nil {
return "", fmt.Errorf("json.Unmarshal failed: %w", err) return "", fmt.Errorf("json.Unmarshal failed: %w", err)
@ -159,16 +157,16 @@ func (q *qiuniu) uploadCert() (string, error) {
return resp.CertID, nil return resp.CertID, nil
} }
type modifyDomainCertReq struct { type qiniuModifyDomainCertReq struct {
CertID string `json:"certId"` CertID string `json:"certId"`
ForceHttps bool `json:"forceHttps"` ForceHttps bool `json:"forceHttps"`
Http2Enable bool `json:"http2Enable"` Http2Enable bool `json:"http2Enable"`
} }
func (q *qiuniu) modifyDomainCert(certId string) error { func (d *QiniuCDNDeployer) modifyDomainCert(certId string) error {
path := fmt.Sprintf("/domain/%s/httpsconf", getDeployString(q.option.DeployConfig, "domain")) path := fmt.Sprintf("/domain/%s/httpsconf", getDeployString(d.option.DeployConfig, "domain"))
body := &modifyDomainCertReq{ body := &qiniuModifyDomainCertReq{
CertID: certId, CertID: certId,
ForceHttps: true, ForceHttps: true,
Http2Enable: true, Http2Enable: true,
@ -179,7 +177,7 @@ func (q *qiuniu) modifyDomainCert(certId string) error {
return fmt.Errorf("json.Marshal failed: %w", err) 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 { if err != nil {
return fmt.Errorf("req failed: %w", err) return fmt.Errorf("req failed: %w", err)
} }
@ -187,12 +185,12 @@ func (q *qiuniu) modifyDomainCert(certId string) error {
return nil 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{ req := xhttp.BuildReq(url, method, body, map[string]string{
"Content-Type": "application/json", "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) return nil, fmt.Errorf("credentials.AddToken failed: %w", err)
} }

View File

@ -36,7 +36,7 @@ func Test_qiuniu_uploadCert(t *testing.T) {
} }
for _, tt := range tests { for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) { t.Run(tt.name, func(t *testing.T) {
q, _ := NewQiNiu(tt.fields.option) q, _ := NewQiniuCDNDeployer(tt.fields.option)
got, err := q.uploadCert() got, err := q.uploadCert()
if (err != nil) != tt.wantErr { if (err != nil) != tt.wantErr {
t.Errorf("qiuniu.uploadCert() error = %v, wantErr %v", err, 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 { for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) { 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 { if err := q.modifyDomainCert(tt.args.certId); (err != nil) != tt.wantErr {
t.Errorf("qiuniu.modifyDomainCert() error = %v, wantErr %v", err, tt.wantErr) t.Errorf("qiuniu.modifyDomainCert() error = %v, wantErr %v", err, tt.wantErr)
} }

View File

@ -12,12 +12,7 @@ import (
sshPkg "golang.org/x/crypto/ssh" sshPkg "golang.org/x/crypto/ssh"
) )
type ssh struct { type SSHAccess struct {
option *DeployerOption
infos []string
}
type sshAccess struct {
Host string `json:"host"` Host string `json:"host"`
Port string `json:"port"` Port string `json:"port"`
Username string `json:"username"` Username string `json:"username"`
@ -26,71 +21,76 @@ type sshAccess struct {
KeyPassphrase string `json:"keyPassphrase"` KeyPassphrase string `json:"keyPassphrase"`
} }
func NewSSH(option *DeployerOption) (Deployer, error) { type SSHDeployer struct {
return &ssh{ option *DeployerOption
infos []string
}
func NewSSHDeployer(option *DeployerOption) (Deployer, error) {
return &SSHDeployer{
option: option, option: option,
infos: make([]string, 0), infos: make([]string, 0),
}, nil }, nil
} }
func (a *ssh) GetID() string { func (d *SSHDeployer) GetID() string {
return fmt.Sprintf("%s-%s", a.option.AceessRecord.GetString("name"), a.option.AceessRecord.Id) return fmt.Sprintf("%s-%s", d.option.AceessRecord.GetString("name"), d.option.AceessRecord.Id)
} }
func (s *ssh) GetInfo() []string { func (d *SSHDeployer) GetInfo() []string {
return s.infos return d.infos
} }
func (s *ssh) Deploy(ctx context.Context) error { func (d *SSHDeployer) Deploy(ctx context.Context) error {
access := &sshAccess{} access := &SSHAccess{}
if err := json.Unmarshal([]byte(s.option.Access), access); err != nil { if err := json.Unmarshal([]byte(d.option.Access), access); err != nil {
return err return err
} }
// 连接 // 连接
client, err := s.getClient(access) client, err := d.createClient(access)
if err != nil { if err != nil {
return err return err
} }
defer client.Close() 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 != "" { if preCommand != "" {
stdout, stderr, err := s.sshExecCommand(client, preCommand) stdout, stderr, err := d.sshExecCommand(client, preCommand)
if err != nil { if err != nil {
return fmt.Errorf("failed to run pre-command: %w, stdout: %s, stderr: %s", err, stdout, stderr) 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) 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) 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 { if err != nil {
return fmt.Errorf("failed to run command: %w, stdout: %s, stderr: %s", err, stdout, stderr) 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 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() session, err := client.NewSession()
if err != nil { if err != nil {
return "", "", fmt.Errorf("failed to create ssh session: %w", err) 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 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) sftpCli, err := sftp.NewClient(client)
if err != nil { if err != nil {
return fmt.Errorf("failed to create sftp client: %w", err) 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 return nil
} }
func (s *ssh) getClient(access *sshAccess) (*sshPkg.Client, error) { func (d *SSHDeployer) createClient(access *SSHAccess) (*sshPkg.Client, error) {
var authMethod sshPkg.AuthMethod var authMethod sshPkg.AuthMethod
if access.Key != "" { if access.Key != "" {

View File

@ -16,13 +16,13 @@ import (
"certimate/internal/utils/rand" "certimate/internal/utils/rand"
) )
type tencentCdn struct { type TencentCDNDeployer struct {
option *DeployerOption option *DeployerOption
credential *common.Credential credential *common.Credential
infos []string infos []string
} }
func NewTencentCdn(option *DeployerOption) (Deployer, error) { func NewTencentCDNDeployer(option *DeployerOption) (Deployer, error) {
access := &domain.TencentAccess{} access := &domain.TencentAccess{}
if err := json.Unmarshal([]byte(option.Access), access); err != nil { if err := json.Unmarshal([]byte(option.Access), access); err != nil {
return nil, fmt.Errorf("failed to unmarshal tencent access: %w", err) return nil, fmt.Errorf("failed to unmarshal tencent access: %w", err)
@ -33,47 +33,47 @@ func NewTencentCdn(option *DeployerOption) (Deployer, error) {
access.SecretKey, access.SecretKey,
) )
return &tencentCdn{ return &TencentCDNDeployer{
option: option, option: option,
credential: credential, credential: credential,
infos: make([]string, 0), infos: make([]string, 0),
}, nil }, nil
} }
func (a *tencentCdn) GetID() string { func (d *TencentCDNDeployer) GetID() string {
return fmt.Sprintf("%s-%s", a.option.AceessRecord.GetString("name"), a.option.AceessRecord.Id) return fmt.Sprintf("%s-%s", d.option.AceessRecord.GetString("name"), d.option.AceessRecord.Id)
} }
func (t *tencentCdn) GetInfo() []string { func (d *TencentCDNDeployer) GetInfo() []string {
return t.infos 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 { if err != nil {
return fmt.Errorf("failed to upload certificate: %w", err) 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 fmt.Errorf("failed to deploy: %w", err)
} }
return nil return nil
} }
func (t *tencentCdn) uploadCert() (string, error) { func (d *TencentCDNDeployer) uploadCert() (string, error) {
cpf := profile.NewClientProfile() cpf := profile.NewClientProfile()
cpf.HttpProfile.Endpoint = "ssl.tencentcloudapi.com" cpf.HttpProfile.Endpoint = "ssl.tencentcloudapi.com"
client, _ := ssl.NewClient(t.credential, "", cpf) client, _ := ssl.NewClient(d.credential, "", cpf)
request := ssl.NewUploadCertificateRequest() request := ssl.NewUploadCertificateRequest()
request.CertificatePublicKey = common.StringPtr(t.option.Certificate.Certificate) request.CertificatePublicKey = common.StringPtr(d.option.Certificate.Certificate)
request.CertificatePrivateKey = common.StringPtr(t.option.Certificate.PrivateKey) request.CertificatePrivateKey = common.StringPtr(d.option.Certificate.PrivateKey)
request.Alias = common.StringPtr(t.option.Domain + "_" + rand.RandStr(6)) request.Alias = common.StringPtr(d.option.Domain + "_" + rand.RandStr(6))
request.Repeatable = common.BoolPtr(false) request.Repeatable = common.BoolPtr(false)
response, err := client.UploadCertificate(request) response, err := client.UploadCertificate(request)
@ -84,11 +84,11 @@ func (t *tencentCdn) uploadCert() (string, error) {
return *response.Response.CertificateId, nil return *response.Response.CertificateId, nil
} }
func (t *tencentCdn) deploy(certId string) error { func (d *TencentCDNDeployer) deploy(certId string) error {
cpf := profile.NewClientProfile() cpf := profile.NewClientProfile()
cpf.HttpProfile.Endpoint = "ssl.tencentcloudapi.com" cpf.HttpProfile.Endpoint = "ssl.tencentcloudapi.com"
// 实例化要请求产品的client对象,clientProfile是可选的 // 实例化要请求产品的client对象,clientProfile是可选的
client, _ := ssl.NewClient(t.credential, "", cpf) client, _ := ssl.NewClient(d.credential, "", cpf)
// 实例化一个请求对象,每个接口都会对应一个request对象 // 实例化一个请求对象,每个接口都会对应一个request对象
request := ssl.NewDeployCertificateInstanceRequest() request := ssl.NewDeployCertificateInstanceRequest()
@ -98,9 +98,9 @@ func (t *tencentCdn) deploy(certId string) error {
request.Status = common.Int64Ptr(1) request.Status = common.Int64Ptr(1)
// 如果是泛域名就从cdn列表下获取SSL证书中的可用域名 // 如果是泛域名就从cdn列表下获取SSL证书中的可用域名
domain := getDeployString(t.option.DeployConfig, "domain") domain := getDeployString(d.option.DeployConfig, "domain")
if strings.Contains(domain, "*") { if strings.Contains(domain, "*") {
list, errGetList := t.getDomainList() list, errGetList := d.getDomainList()
if errGetList != nil { if errGetList != nil {
return fmt.Errorf("failed to get certificate domain list: %w", errGetList) 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 { if err != nil {
return fmt.Errorf("failed to deploy certificate: %w", err) 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 return nil
} }
func (t *tencentCdn) getDomainList() ([]string, error) { func (d *TencentCDNDeployer) getDomainList() ([]string, error) {
cpf := profile.NewClientProfile() cpf := profile.NewClientProfile()
cpf.HttpProfile.Endpoint = "cdn.tencentcloudapi.com" cpf.HttpProfile.Endpoint = "cdn.tencentcloudapi.com"
client, _ := cdn.NewClient(t.credential, "", cpf) client, _ := cdn.NewClient(d.credential, "", cpf)
request := cdn.NewDescribeCertDomainsRequest() request := cdn.NewDescribeCertDomainsRequest()
cert := base64.StdEncoding.EncodeToString([]byte(t.option.Certificate.Certificate)) cert := base64.StdEncoding.EncodeToString([]byte(d.option.Certificate.Certificate))
request.Cert = &cert request.Cert = &cert
response, err := client.DescribeCertDomains(request) response, err := client.DescribeCertDomains(request)

View File

@ -10,48 +10,48 @@ import (
xhttp "certimate/internal/utils/http" xhttp "certimate/internal/utils/http"
) )
type webhookAccess struct { type WebhookAccess struct {
Url string `json:"url"` 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"` Domain string `json:"domain"`
Certificate string `json:"certificate"` Certificate string `json:"certificate"`
PrivateKey string `json:"privateKey"` PrivateKey string `json:"privateKey"`
Variables map[string]string `json:"variables"` Variables map[string]string `json:"variables"`
} }
type webhook struct { func (d *WebhookDeployer) Deploy(ctx context.Context) error {
option *DeployerOption access := &WebhookAccess{}
infos []string if err := json.Unmarshal([]byte(d.option.Access), access); err != nil {
}
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 {
return fmt.Errorf("failed to parse hook access config: %w", err) return fmt.Errorf("failed to parse hook access config: %w", err)
} }
data := &hookData{ data := &webhookData{
Domain: w.option.Domain, Domain: d.option.Domain,
Certificate: w.option.Certificate.Certificate, Certificate: d.option.Certificate.Certificate,
PrivateKey: w.option.Certificate.PrivateKey, PrivateKey: d.option.Certificate.PrivateKey,
Variables: getDeployVariables(w.option.DeployConfig), Variables: getDeployVariables(d.option.DeployConfig),
} }
body, _ := json.Marshal(data) 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) 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 return nil
} }