mirror of
https://github.com/usual2970/certimate.git
synced 2025-10-05 05:54:53 +00:00
feat: a new status for canceled workflow run
This commit is contained in:
@@ -22,8 +22,8 @@ const (
|
||||
)
|
||||
|
||||
type certificateRepository interface {
|
||||
GetById(ctx context.Context, id string) (*domain.Certificate, error)
|
||||
ListExpireSoon(ctx context.Context) ([]*domain.Certificate, error)
|
||||
GetById(ctx context.Context, id string) (*domain.Certificate, error)
|
||||
}
|
||||
|
||||
type CertificateService struct {
|
||||
|
@@ -1,6 +1,9 @@
|
||||
package domain
|
||||
|
||||
import "time"
|
||||
import (
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
const CollectionNameWorkflowRun = "workflow_run"
|
||||
|
||||
@@ -22,6 +25,7 @@ const (
|
||||
WorkflowRunStatusTypeRunning WorkflowRunStatusType = "running"
|
||||
WorkflowRunStatusTypeSucceeded WorkflowRunStatusType = "succeeded"
|
||||
WorkflowRunStatusTypeFailed WorkflowRunStatusType = "failed"
|
||||
WorkflowRunStatusTypeCanceled WorkflowRunStatusType = "canceled"
|
||||
)
|
||||
|
||||
type WorkflowRunLog struct {
|
||||
@@ -40,12 +44,13 @@ type WorkflowRunLogOutput struct {
|
||||
|
||||
type WorkflowRunLogs []WorkflowRunLog
|
||||
|
||||
func (r WorkflowRunLogs) FirstError() string {
|
||||
func (r WorkflowRunLogs) ErrorString() string {
|
||||
var builder strings.Builder
|
||||
for _, log := range r {
|
||||
if log.Error != "" {
|
||||
return log.Error
|
||||
builder.WriteString(log.Error)
|
||||
builder.WriteString("\n")
|
||||
}
|
||||
}
|
||||
|
||||
return ""
|
||||
return builder.String()
|
||||
}
|
||||
|
@@ -1,12 +1,14 @@
|
||||
package certs
|
||||
|
||||
import (
|
||||
"crypto"
|
||||
"crypto/ecdsa"
|
||||
"crypto/rsa"
|
||||
"crypto/x509"
|
||||
"encoding/pem"
|
||||
"errors"
|
||||
|
||||
"github.com/go-acme/lego/v4/certcrypto"
|
||||
xerrors "github.com/pkg/errors"
|
||||
)
|
||||
|
||||
@@ -34,6 +36,19 @@ func ParseCertificateFromPEM(certPem string) (cert *x509.Certificate, err error)
|
||||
return cert, nil
|
||||
}
|
||||
|
||||
// 从 PEM 编码的私钥字符串解析并返回一个 crypto.PrivateKey 对象。
|
||||
//
|
||||
// 入参:
|
||||
// - privkeyPem: 私钥 PEM 内容。
|
||||
//
|
||||
// 出参:
|
||||
// - privkey: crypto.PrivateKey 对象,可能是 rsa.PrivateKey、ecdsa.PrivateKey 或 ed25519.PrivateKey。
|
||||
// - err: 错误。
|
||||
func ParsePrivateKeyFromPEM(privkeyPem string) (privkey crypto.PrivateKey, err error) {
|
||||
pemData := []byte(privkeyPem)
|
||||
return certcrypto.ParsePEMPrivateKey(pemData)
|
||||
}
|
||||
|
||||
// 从 PEM 编码的私钥字符串解析并返回一个 ecdsa.PrivateKey 对象。
|
||||
//
|
||||
// 入参:
|
||||
|
@@ -6,7 +6,6 @@ import (
|
||||
"errors"
|
||||
"time"
|
||||
|
||||
"github.com/go-acme/lego/v4/certcrypto"
|
||||
"github.com/pavlo-v-chernykh/keystore-go/v4"
|
||||
"software.sslmate.com/src/go-pkcs12"
|
||||
)
|
||||
@@ -27,7 +26,7 @@ func TransformCertificateFromPEMToPFX(certPem string, privkeyPem string, pfxPass
|
||||
return nil, err
|
||||
}
|
||||
|
||||
privkey, err := certcrypto.ParsePEMPrivateKey([]byte(privkeyPem))
|
||||
privkey, err := ParsePrivateKeyFromPEM(privkeyPem)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@@ -134,7 +134,7 @@ func (a *applyNode) checkCanSkip(ctx context.Context, lastOutput *domain.Workflo
|
||||
renewalInterval := time.Duration(currentNodeConfig.SkipBeforeExpiryDays) * time.Hour * 24
|
||||
expirationTime := time.Until(lastCertificate.ExpireAt)
|
||||
if lastCertificate != nil && expirationTime > renewalInterval {
|
||||
return true, fmt.Sprintf("已申请过证书,且证书尚未临近过期(到期尚余 %d 天,距 %d 天时续期)", int(expirationTime.Hours()/24), currentNodeConfig.SkipBeforeExpiryDays)
|
||||
return true, fmt.Sprintf("已申请过证书,且证书尚未临近过期(到期尚余 %d 天,预计距 %d 天时续期)", int(expirationTime.Hours()/24), currentNodeConfig.SkipBeforeExpiryDays)
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -19,15 +19,15 @@ func NewWorkflowProcessor(workflow *domain.Workflow) *workflowProcessor {
|
||||
}
|
||||
}
|
||||
|
||||
func (w *workflowProcessor) Log(ctx context.Context) []domain.WorkflowRunLog {
|
||||
return w.logs
|
||||
}
|
||||
|
||||
func (w *workflowProcessor) Run(ctx context.Context) error {
|
||||
ctx = setContextWorkflowId(ctx, w.workflow.Id)
|
||||
return w.processNode(ctx, w.workflow.Content)
|
||||
}
|
||||
|
||||
func (w *workflowProcessor) GetRunLogs() []domain.WorkflowRunLog {
|
||||
return w.logs
|
||||
}
|
||||
|
||||
func (w *workflowProcessor) processNode(ctx context.Context, node *domain.WorkflowNode) error {
|
||||
current := node
|
||||
for current != nil {
|
||||
@@ -39,26 +39,26 @@ func (w *workflowProcessor) processNode(ctx context.Context, node *domain.Workfl
|
||||
}
|
||||
}
|
||||
|
||||
var runErr error
|
||||
var processor nodes.NodeProcessor
|
||||
var runErr error
|
||||
for {
|
||||
if current.Type == domain.WorkflowNodeTypeBranch || current.Type == domain.WorkflowNodeTypeExecuteResultBranch {
|
||||
break
|
||||
if current.Type != domain.WorkflowNodeTypeBranch && current.Type != domain.WorkflowNodeTypeExecuteResultBranch {
|
||||
processor, runErr = nodes.GetProcessor(current)
|
||||
if runErr != nil {
|
||||
break
|
||||
}
|
||||
|
||||
runErr = processor.Run(ctx)
|
||||
log := processor.Log(ctx)
|
||||
if log != nil {
|
||||
w.logs = append(w.logs, *log)
|
||||
}
|
||||
if runErr != nil {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
processor, runErr = nodes.GetProcessor(current)
|
||||
if runErr != nil {
|
||||
break
|
||||
}
|
||||
|
||||
runErr = processor.Run(ctx)
|
||||
log := processor.Log(ctx)
|
||||
if log != nil {
|
||||
w.logs = append(w.logs, *log)
|
||||
}
|
||||
if runErr != nil {
|
||||
break
|
||||
}
|
||||
break
|
||||
}
|
||||
|
||||
if runErr != nil && current.Next != nil && current.Next.Type != domain.WorkflowNodeTypeExecuteResultBranch {
|
||||
|
@@ -35,35 +35,20 @@ type WorkflowService struct {
|
||||
}
|
||||
|
||||
func NewWorkflowService(repo workflowRepository) *WorkflowService {
|
||||
rs := &WorkflowService{
|
||||
srv := &WorkflowService{
|
||||
repo: repo,
|
||||
ch: make(chan *workflowRunData, 1),
|
||||
}
|
||||
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
rs.cancel = cancel
|
||||
srv.cancel = cancel
|
||||
|
||||
rs.wg.Add(defaultRoutines)
|
||||
srv.wg.Add(defaultRoutines)
|
||||
for i := 0; i < defaultRoutines; i++ {
|
||||
go rs.process(ctx)
|
||||
go srv.run(ctx)
|
||||
}
|
||||
|
||||
return rs
|
||||
}
|
||||
|
||||
func (s *WorkflowService) process(ctx context.Context) {
|
||||
defer s.wg.Done()
|
||||
for {
|
||||
select {
|
||||
case data := <-s.ch:
|
||||
// 执行
|
||||
if err := s.run(ctx, data); err != nil {
|
||||
app.GetLogger().Error("failed to run workflow", "id", data.Workflow.Id, "err", err)
|
||||
}
|
||||
case <-ctx.Done():
|
||||
return
|
||||
}
|
||||
}
|
||||
return srv
|
||||
}
|
||||
|
||||
func (s *WorkflowService) InitSchedule(ctx context.Context) error {
|
||||
@@ -90,7 +75,6 @@ func (s *WorkflowService) InitSchedule(ctx context.Context) error {
|
||||
}
|
||||
|
||||
func (s *WorkflowService) Run(ctx context.Context, req *dtos.WorkflowRunReq) error {
|
||||
// 查询
|
||||
workflow, err := s.repo.GetById(ctx, req.WorkflowId)
|
||||
if err != nil {
|
||||
app.GetLogger().Error("failed to get workflow", "id", req.WorkflowId, "err", err)
|
||||
@@ -101,9 +85,8 @@ func (s *WorkflowService) Run(ctx context.Context, req *dtos.WorkflowRunReq) err
|
||||
return errors.New("workflow is running")
|
||||
}
|
||||
|
||||
// set last run
|
||||
workflow.LastRunTime = time.Now()
|
||||
workflow.LastRunStatus = domain.WorkflowRunStatusTypeRunning
|
||||
workflow.LastRunStatus = domain.WorkflowRunStatusTypePending
|
||||
workflow.LastRunId = ""
|
||||
|
||||
if err := s.repo.Save(ctx, workflow); err != nil {
|
||||
@@ -118,42 +101,56 @@ func (s *WorkflowService) Run(ctx context.Context, req *dtos.WorkflowRunReq) err
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *WorkflowService) run(ctx context.Context, runData *workflowRunData) error {
|
||||
// 执行
|
||||
func (s *WorkflowService) Stop(ctx context.Context) {
|
||||
s.cancel()
|
||||
s.wg.Wait()
|
||||
}
|
||||
|
||||
func (s *WorkflowService) run(ctx context.Context) {
|
||||
defer s.wg.Done()
|
||||
for {
|
||||
select {
|
||||
case data := <-s.ch:
|
||||
if err := s.runWithData(ctx, data); err != nil {
|
||||
app.GetLogger().Error("failed to run workflow", "id", data.Workflow.Id, "err", err)
|
||||
}
|
||||
case <-ctx.Done():
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (s *WorkflowService) runWithData(ctx context.Context, runData *workflowRunData) error {
|
||||
workflow := runData.Workflow
|
||||
|
||||
run := &domain.WorkflowRun{
|
||||
WorkflowId: workflow.Id,
|
||||
Status: domain.WorkflowRunStatusTypeRunning,
|
||||
Trigger: runData.RunTrigger,
|
||||
StartedAt: time.Now(),
|
||||
EndedAt: time.Now(),
|
||||
}
|
||||
|
||||
processor := processor.NewWorkflowProcessor(workflow)
|
||||
if err := processor.Run(ctx); err != nil {
|
||||
if runErr := processor.Run(ctx); runErr != nil {
|
||||
run.Status = domain.WorkflowRunStatusTypeFailed
|
||||
run.EndedAt = time.Now()
|
||||
run.Logs = processor.Log(ctx)
|
||||
run.Error = err.Error()
|
||||
|
||||
run.Logs = processor.GetRunLogs()
|
||||
run.Error = runErr.Error()
|
||||
if err := s.repo.SaveRun(ctx, run); err != nil {
|
||||
app.GetLogger().Error("failed to save workflow run", "err", err)
|
||||
}
|
||||
|
||||
return fmt.Errorf("failed to run workflow: %w", err)
|
||||
return fmt.Errorf("failed to run workflow: %w", runErr)
|
||||
}
|
||||
|
||||
// 保存日志
|
||||
logs := processor.Log(ctx)
|
||||
runStatus := domain.WorkflowRunStatusTypeSucceeded
|
||||
runError := domain.WorkflowRunLogs(logs).FirstError()
|
||||
if runError != "" {
|
||||
runStatus = domain.WorkflowRunStatusTypeFailed
|
||||
}
|
||||
run.Status = runStatus
|
||||
run.EndedAt = time.Now()
|
||||
run.Logs = processor.Log(ctx)
|
||||
run.Error = runError
|
||||
run.Logs = processor.GetRunLogs()
|
||||
run.Error = domain.WorkflowRunLogs(run.Logs).ErrorString()
|
||||
if run.Error == "" {
|
||||
run.Status = domain.WorkflowRunStatusTypeSucceeded
|
||||
} else {
|
||||
run.Status = domain.WorkflowRunStatusTypeFailed
|
||||
}
|
||||
if err := s.repo.SaveRun(ctx, run); err != nil {
|
||||
app.GetLogger().Error("failed to save workflow run", "err", err)
|
||||
return err
|
||||
@@ -161,8 +158,3 @@ func (s *WorkflowService) run(ctx context.Context, runData *workflowRunData) err
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *WorkflowService) Stop(ctx context.Context) {
|
||||
s.cancel()
|
||||
s.wg.Wait()
|
||||
}
|
||||
|
Reference in New Issue
Block a user