补齐证书任务入口校验与回归

增加证书导入、恢复、校验任务入口的任务中心回归覆盖,并在任务创建前拒绝无效执行配置,避免异常任务落库。
This commit is contained in:
xuans 2026-09-30 05:37:09 +08:00
parent 88d1717656
commit 9741721b1b
2 changed files with 98 additions and 1 deletions

View File

@ -5,6 +5,7 @@ import (
"database/sql"
"errors"
"fmt"
"strings"
"time"
"git.pcux.cn/xuans/Scert/backend/internal/certificate"
@ -60,9 +61,21 @@ func (w *certificateTaskWorkflow) Validate(ctx context.Context, domainID string)
}
func (w *certificateTaskWorkflow) run(ctx context.Context, id, taskType, stage string, attempts int, interval time.Duration, execute func(context.Context, string) (CertificateWorkflowResult, error)) (result CertificateWorkflowResult, resultErr error) {
if w.tasks == nil || w.audit == nil {
if w == nil || w.tasks == nil || w.audit == nil {
return result, errors.New("证书任务记录服务未初始化")
}
if strings.TrimSpace(id) == "" {
return result, errors.New("证书任务域名 ID 不能为空")
}
if strings.TrimSpace(taskType) == "" || strings.TrimSpace(stage) == "" {
return result, errors.New("证书任务类型和阶段不能为空")
}
if attempts < 1 {
return result, errors.New("证书任务至少执行一次")
}
if execute == nil {
return result, errors.New("证书任务执行器未配置")
}
if active, err := w.tasks.FindActiveTaskByDomain(ctx, id, taskType); err == nil {
return result, fmt.Errorf("%w:%s", repository.ErrTaskAlreadyRunning, active.ID)
} else if !errors.Is(err, sql.ErrNoRows) {

View File

@ -218,6 +218,90 @@ func TestCertificateTaskEntryPointsRecordRenewalAndDeployment(t *testing.T) {
}
}
type restoringWorkflowCertificateService struct {
workflowCertificateService
restored certificate.IssueResult
}
func (s *restoringWorkflowCertificateService) RestoreVersion(context.Context, string, string) (certificate.IssueResult, error) {
s.called = true
return s.restored, nil
}
func TestCertificateTaskEntryPointsRecordImportRestoreAndValidate(t *testing.T) {
t.Run("import", func(t *testing.T) {
w, a := newCertificateTaskFixture(t)
service := &workflowCertificateService{result: certificate.IssueResult{
DomainID: "task-domain",
Domains: []string{"task.example.test"},
Saved: certificate.SavedResource{CertificatePath: "cert.pem"},
}}
w.workflow = &CertificateWorkflow{
Certificates: service,
Domains: &workflowDomainState{},
Servers: workflowServerLister{servers: []deployment.Server{{ID: "server"}}},
Deployment: &workflowDeployer{report: deployment.Report{Total: 1, Success: 1, Status: "success"}},
}
_, err := w.Import(t.Context(), certificate.ImportRequest{DomainID: "task-domain", Certificate: "cert.pem", PrivateKey: "key.pem"})
if err != nil || !service.called {
t.Fatalf("证书导入任务入口执行错误:%v", err)
}
item := assertCertificateTask(t, a, "success", "success")
if item.TaskType != "certificate_import" {
t.Fatalf("证书导入任务类型错误:%+v", item)
}
})
t.Run("restore", func(t *testing.T) {
w, a := newCertificateTaskFixture(t)
service := &restoringWorkflowCertificateService{workflowCertificateService: workflowCertificateService{
result: certificate.IssueResult{DomainID: "task-domain"},
}, restored: certificate.IssueResult{DomainID: "task-domain"}}
w.workflow = &CertificateWorkflow{Certificates: service}
_, err := w.Restore(t.Context(), "task-domain", "version-1")
if err != nil || !service.called {
t.Fatalf("证书恢复任务入口执行错误:%v", err)
}
item := assertCertificateTask(t, a, "success", "success")
if item.TaskType != "certificate_restore" {
t.Fatalf("证书恢复任务类型错误:%+v", item)
}
})
t.Run("validate", func(t *testing.T) {
w, a := newCertificateTaskFixture(t)
service := &workflowCertificateService{}
w.workflow = &CertificateWorkflow{
CurrentCertificate: func(context.Context, string) (certificate.IssueResult, error) {
service.called = true
return certificate.IssueResult{DomainID: "task-domain"}, nil
},
}
_, _, err := w.Validate(t.Context(), "task-domain")
if err == nil || !service.called {
t.Fatal("证书校验任务入口未返回预期失败")
}
item := assertCertificateTask(t, a, "failed", "failed")
if item.TaskType != "certificate_validate" {
t.Fatalf("证书校验任务类型错误:%+v", item)
}
})
}
func TestCertificateTaskRejectsInvalidExecutionConfiguration(t *testing.T) {
w, a := newCertificateTaskFixture(t)
_, err := w.run(t.Context(), "task-domain", "certificate_validate", "certificate_validate", 0, 0, func(context.Context, string) (CertificateWorkflowResult, error) {
return CertificateWorkflowResult{}, nil
})
if err == nil || !strings.Contains(err.Error(), "至少执行一次") {
t.Fatalf("无效执行次数未被拒绝:%v", err)
}
items, listErr := a.Tasks.ListTasks(t.Context(), "task-domain", 10)
if listErr != nil || len(items) != 0 {
t.Fatalf("无效任务配置不应创建任务:%+v,%v", items, listErr)
}
}
type failingCertificateAudit struct {
repository.AuditRepository
failStatus string