Skip to content

Commit

Permalink
Merge pull request #30 from usual2970/feat/deploy_group
Browse files Browse the repository at this point in the history
添加部署变量、部署授权组的支持
  • Loading branch information
usual2970 authored Sep 14, 2024
2 parents 505cfc5 + 6c1b1fb commit f501df2
Show file tree
Hide file tree
Showing 29 changed files with 2,173 additions and 575 deletions.
4 changes: 4 additions & 0 deletions internal/deployer/aliyun.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,10 @@ func NewAliyun(option *DeployerOption) (Deployer, error) {

}

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
}
Expand Down
4 changes: 4 additions & 0 deletions internal/deployer/aliyun_cdn.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,10 @@ func NewAliyunCdn(option *DeployerOption) (*AliyunCdn, error) {
}, nil
}

func (a *AliyunCdn) GetID() string {
return fmt.Sprintf("%s-%s", a.option.AceessRecord.GetString("name"), a.option.AceessRecord.Id)
}

func (a *AliyunCdn) GetInfo() []string {
return a.infos
}
Expand Down
92 changes: 81 additions & 11 deletions internal/deployer/deployer.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,12 @@ package deployer

import (
"certimate/internal/applicant"
"certimate/internal/utils/app"
"certimate/internal/utils/variables"
"context"
"encoding/json"
"errors"
"fmt"
"strings"

"github.com/pocketbase/pocketbase/models"
Expand All @@ -20,25 +23,85 @@ const (
)

type DeployerOption struct {
DomainId string `json:"domainId"`
Domain string `json:"domain"`
Product string `json:"product"`
Access string `json:"access"`
Certificate applicant.Certificate `json:"certificate"`
DomainId string `json:"domainId"`
Domain string `json:"domain"`
Product string `json:"product"`
Access string `json:"access"`
AceessRecord *models.Record `json:"-"`
Certificate applicant.Certificate `json:"certificate"`
Variables map[string]string `json:"variables"`
}

type Deployer interface {
Deploy(ctx context.Context) error
GetInfo() []string
GetID() string
}

func Get(record *models.Record, cert *applicant.Certificate) (Deployer, error) {
access := record.ExpandedOne("targetAccess")
func Gets(record *models.Record, cert *applicant.Certificate) ([]Deployer, error) {
rs := make([]Deployer, 0)

if record.GetString("targetAccess") != "" {
singleDeployer, err := Get(record, cert)
if err != nil {
return nil, err
}
rs = append(rs, singleDeployer)
}

if record.GetString("group") != "" {
group := record.ExpandedOne("group")

if errs := app.GetApp().Dao().ExpandRecord(group, []string{"access"}, nil); len(errs) > 0 {

errList := make([]error, 0)
for name, err := range errs {
errList = append(errList, fmt.Errorf("展开记录失败,%s: %w", name, err))
}
err := errors.Join(errList...)
return nil, err
}

records := group.ExpandedAll("access")

deployers, err := getByGroup(record, cert, records...)
if err != nil {
return nil, err
}

rs = append(rs, deployers...)

}

return rs, nil

}

func getByGroup(record *models.Record, cert *applicant.Certificate, accesses ...*models.Record) ([]Deployer, error) {

rs := make([]Deployer, 0)

for _, access := range accesses {
deployer, err := getWithAccess(record, cert, access)
if err != nil {
return nil, err
}
rs = append(rs, deployer)
}

return rs, nil

}

func getWithAccess(record *models.Record, cert *applicant.Certificate, access *models.Record) (Deployer, error) {

option := &DeployerOption{
DomainId: record.Id,
Domain: record.GetString("domain"),
Product: getProduct(record),
Access: access.GetString("config"),
DomainId: record.Id,
Domain: record.GetString("domain"),
Product: getProduct(record),
Access: access.GetString("config"),
AceessRecord: access,
Variables: variables.Parse2Map(record.GetString("variables")),
}
if cert != nil {
option.Certificate = *cert
Expand Down Expand Up @@ -66,6 +129,13 @@ func Get(record *models.Record, cert *applicant.Certificate) (Deployer, error) {
return nil, errors.New("not implemented")
}

func Get(record *models.Record, cert *applicant.Certificate) (Deployer, error) {

access := record.ExpandedOne("targetAccess")

return getWithAccess(record, cert, access)
}

func getProduct(record *models.Record) string {
targetType := record.GetString("targetType")
rs := strings.Split(targetType, "-")
Expand Down
4 changes: 4 additions & 0 deletions internal/deployer/qiniu.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,10 @@ 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 (q *qiuniu) GetInfo() []string {
return q.info
}
Expand Down
14 changes: 14 additions & 0 deletions internal/deployer/ssh.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"fmt"
"os"
xpath "path"
"strings"

"github.com/pkg/sftp"
sshPkg "golang.org/x/crypto/ssh"
Expand Down Expand Up @@ -35,6 +36,10 @@ func NewSSH(option *DeployerOption) (Deployer, error) {
}, nil
}

func (a *ssh) GetID() string {
return fmt.Sprintf("%s-%s", a.option.AceessRecord.GetString("name"), a.option.AceessRecord.Id)
}

func (s *ssh) GetInfo() []string {
return s.infos
}
Expand All @@ -44,6 +49,15 @@ func (s *ssh) Deploy(ctx context.Context) error {
if err := json.Unmarshal([]byte(s.option.Access), access); err != nil {
return err
}

// 将证书路径和命令中的变量替换为实际值
for k, v := range s.option.Variables {
key := fmt.Sprintf("${%s}", k)
access.CertPath = strings.ReplaceAll(access.CertPath, key, v)
access.KeyPath = strings.ReplaceAll(access.KeyPath, key, v)
access.Command = strings.ReplaceAll(access.Command, key, v)
}

// 连接
client, err := s.getClient(access)
if err != nil {
Expand Down
4 changes: 4 additions & 0 deletions internal/deployer/tencent_cdn.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,10 @@ func NewTencentCdn(option *DeployerOption) (Deployer, error) {
}, nil
}

func (a *tencentCdn) GetID() string {
return fmt.Sprintf("%s-%s", a.option.AceessRecord.GetString("name"), a.option.AceessRecord.Id)
}

func (t *tencentCdn) GetInfo() []string {
return t.infos
}
Expand Down
4 changes: 4 additions & 0 deletions internal/deployer/webhook.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,10 @@ func NewWebhook(option *DeployerOption) (Deployer, error) {
}, 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
}
Expand Down
22 changes: 13 additions & 9 deletions internal/domains/deploy.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ func deploy(ctx context.Context, record *models.Record) error {
return err
}
history.record(checkPhase, "获取记录成功", nil)
if errs := app.GetApp().Dao().ExpandRecord(currRecord, []string{"access", "targetAccess"}, nil); len(errs) > 0 {
if errs := app.GetApp().Dao().ExpandRecord(currRecord, []string{"access", "targetAccess", "group"}, nil); len(errs) > 0 {

errList := make([]error, 0)
for name, err := range errs {
Expand Down Expand Up @@ -96,24 +96,28 @@ func deploy(ctx context.Context, record *models.Record) error {

// ############3.部署证书
history.record(deployPhase, "开始部署", nil, false)
deployer, err := deployer.Get(currRecord, certificate)
deployers, err := deployer.Gets(currRecord, certificate)
if err != nil {
history.record(deployPhase, "获取deployer失败", &RecordInfo{Err: err})
app.GetApp().Logger().Error("获取deployer失败", "err", err)
return err
}

if err = deployer.Deploy(ctx); err != nil {
for _, deployer := range deployers {
if err = deployer.Deploy(ctx); err != nil {

app.GetApp().Logger().Error("部署失败", "err", err)
history.record(deployPhase, "部署失败", &RecordInfo{Err: err, Info: deployer.GetInfo()})
return err
}
history.record(deployPhase, fmt.Sprintf("[%s]-部署成功", deployer.GetID()), &RecordInfo{
Info: deployer.GetInfo(),
}, false)

app.GetApp().Logger().Error("部署失败", "err", err)
history.record(deployPhase, "部署失败", &RecordInfo{Err: err, Info: deployer.GetInfo()})
return err
}

app.GetApp().Logger().Info("部署成功")
history.record(deployPhase, "部署成功", &RecordInfo{
Info: deployer.GetInfo(),
}, true)
history.record(deployPhase, "部署成功", nil, true)

return nil
}
30 changes: 30 additions & 0 deletions internal/utils/variables/variables.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package variables

import "strings"

// Parse2Map 将变量赋值字符串解析为map
func Parse2Map(str string) map[string]string {

m := make(map[string]string)

lines := strings.Split(str, ";")

for _, line := range lines {

line = strings.TrimSpace(line)

if line == "" {
continue
}

kv := strings.Split(line, "=")

if len(kv) != 2 {
continue
}

m[kv[0]] = kv[1]
}

return m
}
56 changes: 56 additions & 0 deletions internal/utils/variables/variables_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package variables

import (
"reflect"
"testing"
)

func TestParse2Map(t *testing.T) {
type args struct {
str string
}
tests := []struct {
name string
args args
want map[string]string
}{
{
name: "test1",
args: args{
str: "a=1;b=2;c=3",
},
want: map[string]string{
"a": "1",
"b": "2",
"c": "3",
},
},
{
name: "test2",
args: args{
str: `a=1;
b=2;
c=`,
},
want: map[string]string{
"a": "1",
"b": "2",
"c": "",
},
},
{
name: "test3",
args: args{
str: "1",
},
want: map[string]string{},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := Parse2Map(tt.args.str); !reflect.DeepEqual(got, tt.want) {
t.Errorf("Parse2Map() = %v, want %v", got, tt.want)
}
})
}
}
Loading

0 comments on commit f501df2

Please sign in to comment.