mirror of
https://github.com/usual2970/certimate.git
synced 2025-10-04 21:44:54 +00:00
Save and display execution records
This commit is contained in:
@@ -2,6 +2,8 @@ package domain
|
||||
|
||||
import "time"
|
||||
|
||||
var ValidityDuration = time.Hour * 24 * 10
|
||||
|
||||
type Certificate struct {
|
||||
Meta
|
||||
SAN string `json:"san"`
|
||||
|
22
internal/domain/workflow_run_log.go
Normal file
22
internal/domain/workflow_run_log.go
Normal file
@@ -0,0 +1,22 @@
|
||||
package domain
|
||||
|
||||
type RunLogOutput struct {
|
||||
Time string `json:"time"`
|
||||
Title string `json:"title"`
|
||||
Content string `json:"content"`
|
||||
Error string `json:"error"`
|
||||
}
|
||||
|
||||
type RunLog struct {
|
||||
NodeName string `json:"nodeName"`
|
||||
Error string `json:"error"`
|
||||
Outputs []RunLogOutput `json:"outputs"`
|
||||
}
|
||||
|
||||
type WorkflowRunLog struct {
|
||||
Meta
|
||||
Workflow string `json:"workflow"`
|
||||
Log []RunLog `json:"log"`
|
||||
Succeed bool `json:"succeed"`
|
||||
Error string `json:"error"`
|
||||
}
|
@@ -5,6 +5,7 @@ import (
|
||||
"database/sql"
|
||||
"errors"
|
||||
|
||||
"github.com/pocketbase/pocketbase/models"
|
||||
"github.com/usual2970/certimate/internal/domain"
|
||||
"github.com/usual2970/certimate/internal/utils/app"
|
||||
)
|
||||
@@ -15,6 +16,21 @@ func NewWorkflowRepository() *WorkflowRepository {
|
||||
return &WorkflowRepository{}
|
||||
}
|
||||
|
||||
func (w *WorkflowRepository) SaveRunLog(ctx context.Context, log *domain.WorkflowRunLog) error {
|
||||
collection, err := app.GetApp().Dao().FindCollectionByNameOrId("workflow_run_log")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
record := models.NewRecord(collection)
|
||||
|
||||
record.Set("workflow", log.Workflow)
|
||||
record.Set("log", log.Log)
|
||||
record.Set("succeed", log.Succeed)
|
||||
record.Set("error", log.Error)
|
||||
|
||||
return app.GetApp().Dao().SaveRecord(record)
|
||||
}
|
||||
|
||||
func (w *WorkflowRepository) Get(ctx context.Context, id string) (*domain.Workflow, error) {
|
||||
record, err := app.GetApp().Dao().FindRecordById("workflow", id)
|
||||
if err != nil {
|
||||
|
@@ -43,8 +43,8 @@ func (w *WorkflowOutputRepository) Get(ctx context.Context, nodeId string) (*dom
|
||||
rs := &domain.WorkflowOutput{
|
||||
Meta: domain.Meta{
|
||||
Id: record.GetId(),
|
||||
Created: record.GetTime("created"),
|
||||
Updated: record.GetTime("updated"),
|
||||
Created: record.GetCreated().Time(),
|
||||
Updated: record.GetUpdated().Time(),
|
||||
},
|
||||
Workflow: record.GetString("workflow"),
|
||||
NodeId: record.GetString("nodeId"),
|
||||
@@ -73,15 +73,15 @@ func (w *WorkflowOutputRepository) GetCertificate(ctx context.Context, nodeId st
|
||||
rs := &domain.Certificate{
|
||||
Meta: domain.Meta{
|
||||
Id: record.GetId(),
|
||||
Created: record.GetTime("created"),
|
||||
Updated: record.GetTime("updated"),
|
||||
Created: record.GetDateTime("created").Time(),
|
||||
Updated: record.GetDateTime("updated").Time(),
|
||||
},
|
||||
Certificate: record.GetString("certificate"),
|
||||
PrivateKey: record.GetString("privateKey"),
|
||||
IssuerCertificate: record.GetString("issuerCertificate"),
|
||||
SAN: record.GetString("san"),
|
||||
Output: record.GetString("output"),
|
||||
ExpireAt: record.GetTime("expireAt"),
|
||||
ExpireAt: record.GetDateTime("expireAt").Time(),
|
||||
CertUrl: record.GetString("certUrl"),
|
||||
CertStableUrl: record.GetString("certStableUrl"),
|
||||
Workflow: record.GetString("workflow"),
|
||||
|
@@ -2,6 +2,7 @@ package nodeprocessor
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"github.com/usual2970/certimate/internal/applicant"
|
||||
"github.com/usual2970/certimate/internal/domain"
|
||||
@@ -45,8 +46,16 @@ func (a *applyNode) Run(ctx context.Context) error {
|
||||
}
|
||||
|
||||
if output != nil && output.Succeed {
|
||||
a.AddOutput(ctx, a.node.Name, "已申请过")
|
||||
return nil
|
||||
cert, err := a.outputRepo.GetCertificate(ctx, a.node.Id)
|
||||
if err != nil {
|
||||
a.AddOutput(ctx, a.node.Name, "获取证书失败", err.Error())
|
||||
return err
|
||||
}
|
||||
|
||||
if time.Until(cert.ExpireAt) > domain.ValidityDuration {
|
||||
a.AddOutput(ctx, a.node.Name, "已申请过证书,且证书在有效期内")
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// 获取Applicant
|
||||
@@ -65,12 +74,18 @@ func (a *applyNode) Run(ctx context.Context) error {
|
||||
a.AddOutput(ctx, a.node.Name, "申请成功")
|
||||
|
||||
// 记录申请结果
|
||||
// 保持一个节点只有一个输出
|
||||
outputId := ""
|
||||
if output != nil {
|
||||
outputId = output.Id
|
||||
}
|
||||
output = &domain.WorkflowOutput{
|
||||
Workflow: GetWorkflowId(ctx),
|
||||
NodeId: a.node.Id,
|
||||
Node: a.node,
|
||||
Succeed: true,
|
||||
Output: a.node.Output,
|
||||
Meta: domain.Meta{Id: outputId},
|
||||
}
|
||||
|
||||
cert, err := x509.ParseCertificateFromPEM(certificate.Certificate)
|
||||
|
@@ -4,7 +4,6 @@ import (
|
||||
"context"
|
||||
|
||||
"github.com/usual2970/certimate/internal/domain"
|
||||
"github.com/usual2970/certimate/internal/utils/xtime"
|
||||
)
|
||||
|
||||
type conditionNode struct {
|
||||
@@ -21,7 +20,7 @@ func NewConditionNode(node *domain.WorkflowNode) *conditionNode {
|
||||
|
||||
// 条件节点没有任何操作
|
||||
func (c *conditionNode) Run(ctx context.Context) error {
|
||||
c.AddOutput(ctx, xtime.BeijingTimeStr(),
|
||||
c.AddOutput(ctx,
|
||||
c.node.Name,
|
||||
"完成",
|
||||
)
|
||||
|
@@ -32,10 +32,6 @@ func (d *deployNode) Run(ctx context.Context) error {
|
||||
d.AddOutput(ctx, d.node.Name, "查询部署记录失败", err.Error())
|
||||
return err
|
||||
}
|
||||
if output != nil && output.Succeed {
|
||||
d.AddOutput(ctx, d.node.Name, "已部署过")
|
||||
return nil
|
||||
}
|
||||
// 获取部署对象
|
||||
// 获取证书
|
||||
certSource := d.node.GetConfigString("certificate")
|
||||
@@ -52,6 +48,15 @@ func (d *deployNode) Run(ctx context.Context) error {
|
||||
return err
|
||||
}
|
||||
|
||||
// 未部署过,开始部署
|
||||
// 部署过但是证书更新了,重新部署
|
||||
// 部署过且证书未更新,直接返回
|
||||
|
||||
if d.deployed(output) && cert.Created.Before(output.Updated) {
|
||||
d.AddOutput(ctx, d.node.Name, "已部署过且证书未更新")
|
||||
return nil
|
||||
}
|
||||
|
||||
accessRepo := repository.NewAccessRepository()
|
||||
access, err := accessRepo.GetById(context.Background(), d.node.GetConfigString("access"))
|
||||
if err != nil {
|
||||
@@ -86,11 +91,16 @@ func (d *deployNode) Run(ctx context.Context) error {
|
||||
d.AddOutput(ctx, d.node.Name, "部署成功")
|
||||
|
||||
// 记录部署结果
|
||||
outputId := ""
|
||||
if output != nil {
|
||||
outputId = output.Id
|
||||
}
|
||||
output = &domain.WorkflowOutput{
|
||||
Workflow: GetWorkflowId(ctx),
|
||||
NodeId: d.node.Id,
|
||||
Node: d.node,
|
||||
Succeed: true,
|
||||
Meta: domain.Meta{Id: outputId},
|
||||
}
|
||||
|
||||
if err := d.outputRepo.Save(ctx, output, nil, nil); err != nil {
|
||||
@@ -102,3 +112,7 @@ func (d *deployNode) Run(ctx context.Context) error {
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *deployNode) deployed(output *domain.WorkflowOutput) bool {
|
||||
return output != nil && output.Succeed
|
||||
}
|
||||
|
@@ -8,51 +8,38 @@ import (
|
||||
"github.com/usual2970/certimate/internal/utils/xtime"
|
||||
)
|
||||
|
||||
type RunLog struct {
|
||||
NodeName string `json:"node_name"`
|
||||
Err string `json:"err"`
|
||||
Outputs []RunLogOutput `json:"outputs"`
|
||||
}
|
||||
|
||||
type RunLogOutput struct {
|
||||
Time string `json:"time"`
|
||||
Title string `json:"title"`
|
||||
Content string `json:"content"`
|
||||
Error string `json:"error"`
|
||||
}
|
||||
|
||||
type NodeProcessor interface {
|
||||
Run(ctx context.Context) error
|
||||
Log(ctx context.Context) *RunLog
|
||||
Log(ctx context.Context) *domain.RunLog
|
||||
AddOutput(ctx context.Context, title, content string, err ...string)
|
||||
}
|
||||
|
||||
type Logger struct {
|
||||
log *RunLog
|
||||
log *domain.RunLog
|
||||
}
|
||||
|
||||
func NewLogger(node *domain.WorkflowNode) *Logger {
|
||||
return &Logger{
|
||||
log: &RunLog{
|
||||
log: &domain.RunLog{
|
||||
NodeName: node.Name,
|
||||
Outputs: make([]RunLogOutput, 0),
|
||||
Outputs: make([]domain.RunLogOutput, 0),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (l *Logger) Log(ctx context.Context) *RunLog {
|
||||
func (l *Logger) Log(ctx context.Context) *domain.RunLog {
|
||||
return l.log
|
||||
}
|
||||
|
||||
func (l *Logger) AddOutput(ctx context.Context, title, content string, err ...string) {
|
||||
output := RunLogOutput{
|
||||
output := domain.RunLogOutput{
|
||||
Time: xtime.BeijingTimeStr(),
|
||||
Title: title,
|
||||
Content: content,
|
||||
}
|
||||
if len(err) > 0 {
|
||||
output.Error = err[0]
|
||||
l.log.Err = err[0]
|
||||
l.log.Error = err[0]
|
||||
}
|
||||
l.log.Outputs = append(l.log.Outputs, output)
|
||||
}
|
||||
|
@@ -4,7 +4,6 @@ import (
|
||||
"context"
|
||||
|
||||
"github.com/usual2970/certimate/internal/domain"
|
||||
"github.com/usual2970/certimate/internal/utils/xtime"
|
||||
)
|
||||
|
||||
type startNode struct {
|
||||
@@ -21,7 +20,7 @@ func NewStartNode(node *domain.WorkflowNode) *startNode {
|
||||
|
||||
// 开始节点没有任何操作
|
||||
func (s *startNode) Run(ctx context.Context) error {
|
||||
s.AddOutput(ctx, xtime.BeijingTimeStr(),
|
||||
s.AddOutput(ctx,
|
||||
s.node.Name,
|
||||
"完成",
|
||||
)
|
||||
|
@@ -8,15 +8,20 @@ import (
|
||||
|
||||
type workflowProcessor struct {
|
||||
workflow *domain.Workflow
|
||||
logs []RunLog
|
||||
logs []domain.RunLog
|
||||
}
|
||||
|
||||
func NewWorkflowProcessor(workflow *domain.Workflow) *workflowProcessor {
|
||||
return &workflowProcessor{
|
||||
workflow: workflow,
|
||||
logs: make([]domain.RunLog, 0),
|
||||
}
|
||||
}
|
||||
|
||||
func (w *workflowProcessor) Log(ctx context.Context) []domain.RunLog {
|
||||
return w.logs
|
||||
}
|
||||
|
||||
func (w *workflowProcessor) Run(ctx context.Context) error {
|
||||
ctx = WithWorkflowId(ctx, w.workflow.Id)
|
||||
return w.runNode(ctx, w.workflow.Content)
|
||||
|
@@ -11,6 +11,7 @@ import (
|
||||
|
||||
type WorkflowRepository interface {
|
||||
Get(ctx context.Context, id string) (*domain.Workflow, error)
|
||||
SaveRunLog(ctx context.Context, log *domain.WorkflowRunLog) error
|
||||
}
|
||||
|
||||
type WorkflowService struct {
|
||||
@@ -43,11 +44,29 @@ func (s *WorkflowService) Run(ctx context.Context, req *domain.WorkflowRunReq) e
|
||||
|
||||
processor := nodeprocessor.NewWorkflowProcessor(workflow)
|
||||
if err := processor.Run(ctx); err != nil {
|
||||
log := &domain.WorkflowRunLog{
|
||||
Workflow: workflow.Id,
|
||||
Log: processor.Log(ctx),
|
||||
Succeed: false,
|
||||
Error: err.Error(),
|
||||
}
|
||||
if err := s.repo.SaveRunLog(ctx, log); err != nil {
|
||||
app.GetApp().Logger().Error("failed to save run log", "err", err)
|
||||
}
|
||||
return fmt.Errorf("failed to run workflow: %w", err)
|
||||
}
|
||||
|
||||
// 保存执行日志
|
||||
|
||||
|
||||
log := &domain.WorkflowRunLog{
|
||||
Workflow: workflow.Id,
|
||||
Log: processor.Log(ctx),
|
||||
Succeed: true,
|
||||
}
|
||||
if err := s.repo.SaveRunLog(ctx, log); err != nil {
|
||||
app.GetApp().Logger().Error("failed to save run log", "err", err)
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
Reference in New Issue
Block a user