Files
membank/auto-check/pkg/workflow/workflow.go
张威33321 19f6050147 新增 auto-check 工具:网段扫描+SSH登录+压力测试永久循环工作流
- pkg/discovery: TCP端口探测存活主机,ARP表解析MAC作为设备唯一标识
- pkg/sshclient: SSH连接(密码/密钥认证)与远程命令执行
- pkg/stress: stress-ng/stressapptest 压测(cpu/memory/disk/memnative/full)+温度与dmesg监控
- pkg/report: 检测报告生成(文本/JSON)
- pkg/workflow: 永久循环工作流(间隔可配),MAC唯一标识设备,增量测试+状态变化打印
- pkg/config: YAML分类配置(scan/ssh/stress/report/workflow)
- cmd: cobra入口,仅 --config 指定配置文件
2026-08-10 20:30:23 +08:00

167 lines
3.8 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package workflow
import (
"context"
"fmt"
"time"
"auto-check/pkg/config"
"auto-check/pkg/stress"
)
// ============================
// Context — 阶段间共享数据
// ============================
// Context 工作流上下文,保存阶段间传递的数据
type Context struct {
base context.Context // 可取消上下文
// 配置(由入口设置)
Config config.Config
// 循环模式下的状态数据key 均为设备 MAC
Devices map[string]*Device // 设备列表MAC → 设备)
Results map[string]*stress.Report // 测试结果nil/失败=需测试)
Printed map[string]string // 上次打印的测试状态
}
// NewContext 创建上下文
func NewContext() *Context {
return &Context{
base: context.Background(),
Devices: make(map[string]*Device),
Results: make(map[string]*stress.Report),
Printed: make(map[string]string),
}
}
// WithCancel 支持取消
func (c *Context) WithCancel() (context.CancelFunc, error) {
ctx, cancel := context.WithCancel(c.base)
c.base = ctx
return cancel, nil
}
// Done 返回取消信号
func (c *Context) Done() <-chan struct{} {
return c.base.Done()
}
// Err 返回取消原因
func (c *Context) Err() error {
return c.base.Err()
}
// ============================
// Stage — 阶段接口
// ============================
// Stage 工作流阶段
type Stage interface {
Name() string
Execute(ctx *Context) error
}
// ============================
// Workflow — 流水线调度器
// ============================
// OnStageError 阶段失败处理策略
type OnStageError int
const (
// StopOnError 失败即中断整个工作流
StopOnError OnStageError = iota
// ContinueOnError 失败继续执行后续阶段
ContinueOnError
)
// StageResult 阶段执行结果
type StageResult struct {
Stage string
Start time.Time
End time.Time
Duration time.Duration
Err error
}
// Workflow Pipeline 工作流
type Workflow struct {
stages []Stage
onError OnStageError
results []StageResult
startTime time.Time
}
// New 创建空工作流
func New() *Workflow {
return &Workflow{
onError: StopOnError,
}
}
// SetOnError 设置失败策略
func (w *Workflow) SetOnError(policy OnStageError) *Workflow {
w.onError = policy
return w
}
// AddStage 追加阶段(串行)
func (w *Workflow) AddStage(stage Stage) *Workflow {
w.stages = append(w.stages, stage)
return w
}
// Run 依次执行所有阶段
func (w *Workflow) Run(ctx *Context) error {
w.startTime = time.Now()
fmt.Printf("══ 工作流启动 (%d 个阶段) ══\n\n", len(w.stages))
for i, stage := range w.stages {
// 检查是否被取消
select {
case <-ctx.Done():
fmt.Printf(" [!] 工作流已取消,停止于阶段 %d/%d\n", i+1, len(w.stages))
return ctx.Err()
default:
}
fmt.Printf("════ 阶段 %d/%d: %s ════\n", i+1, len(w.stages), stage.Name())
start := time.Now()
err := stage.Execute(ctx)
duration := time.Since(start)
result := StageResult{
Stage: stage.Name(),
Start: start,
End: time.Now(),
Duration: duration,
Err: err,
}
w.results = append(w.results, result)
if err != nil {
fmt.Printf(" [✗] 阶段失败: %v\n", err)
switch w.onError {
case StopOnError:
fmt.Printf("══ 工作流中止(策略: 失败即停止)══\n")
return err
case ContinueOnError:
fmt.Printf(" [!] 继续执行后续阶段(策略: 失败继续)\n\n")
continue
}
} else {
fmt.Printf(" [✓] 阶段完成 (%v)\n\n", duration.Round(time.Millisecond))
}
}
fmt.Printf("══ 工作流完成,总耗时 %v ══\n", time.Since(w.startTime).Round(time.Millisecond))
return nil
}
// Results 阶段执行结果列表
func (w *Workflow) Results() []StageResult {
return w.results
}