- 新增 config-contract 模块(TypeBox fragments、Ajv 契约校验、ConfigValidationIssue) - CheckerDefinition 扩展为含 configKey、schemas、validate 的完整插件接口 - HTTP/Command 各自维护 contract.ts + validate.ts,校验从 resolve 中分离 - resolve 不再承担校验,只做默认值合并和路径/单位解析 - config-loader 流程: unknown → RawProbeConfig → ValidatedProbeConfig → ResolvedConfig - 导出 probe-config.schema.json,新增 schema/schema:check 脚本 - 更新 DEVELOPMENT.md 新增 1.7 开发新 Checker 完整指引 - 同步更新 4 个 main specs(probe-config、command-checker、expect-body-checkers、checker-runner-abstraction)
142 lines
8.1 KiB
Markdown
142 lines
8.1 KiB
Markdown
## Purpose
|
||
|
||
定义 Command 类型拨测目标:通过 `type: command` 配置执行本地命令(如进程检查、脚本健康检测),捕获 exit code、stdout、stderr,按 expect 规则校验并生成 matched 判定。
|
||
|
||
## Requirements
|
||
|
||
### Requirement: command target 配置
|
||
系统 SHALL 支持 `type: command` 的 target 配置,通过 `command.exec` 和 `command.args` 描述本地命令,并使用 command 专用字段配置工作目录、环境变量和输出限制。
|
||
|
||
#### Scenario: 解析 command target
|
||
- **WHEN** YAML 中 target 配置 `type: command`、`command.exec: "pgrep"` 和 `command.args: ["nginx"]`
|
||
- **THEN** 系统 SHALL 将其解析为 command checker,并保留 exec、args、cwd、env、maxOutputBytes、interval、timeout 和 expect 配置
|
||
|
||
#### Scenario: command target 缺少 exec
|
||
- **WHEN** YAML 中 target 配置 `type: command` 但缺少 `command.exec`
|
||
- **THEN** 系统 SHALL 以配置错误退出,并提示该 target 缺少 command.exec 字段
|
||
|
||
#### Scenario: cwd 相对配置文件目录解析
|
||
- **WHEN** command target 配置 `command.cwd: "scripts"` 且配置文件位于 `/opt/checker/probes.yaml`
|
||
- **THEN** 系统 SHALL 将 cwd 解析为 `/opt/checker/scripts`
|
||
|
||
#### Scenario: command 不使用 shell
|
||
- **WHEN** command target 配置 `exec` 和 `args`
|
||
- **THEN** 系统 MUST 直接执行该程序和参数,不通过 shell 解释整段命令字符串
|
||
|
||
#### Scenario: env 默认继承并允许覆盖
|
||
- **WHEN** command target 配置 `command.env: {LANG: "C"}` 且当前进程环境包含 `PATH`
|
||
- **THEN** 系统 SHALL 继承当前进程的全部环境变量,并将 `LANG` 覆盖为 `"C"`
|
||
|
||
#### Scenario: 不支持 stdin
|
||
- **WHEN** command target 配置并执行命令
|
||
- **THEN** 系统 MUST NOT 向子进程 stdin 写入数据,避免命令因等待输入而阻塞
|
||
|
||
### Requirement: command checker 执行
|
||
系统 SHALL 按 command target 配置执行本地命令,记录执行耗时、退出码、stdout 和 stderr,并在执行失败时产生结构化错误信息。
|
||
|
||
#### Scenario: 命令正常退出
|
||
- **WHEN** command target 执行的进程正常退出且 exit code 为 0
|
||
- **THEN** 系统 SHALL 记录 `durationMs`、`statusDetail="exitCode=0"`,并进入 expect 校验
|
||
|
||
#### Scenario: 命令非零退出
|
||
- **WHEN** command target 执行的进程正常退出但 exit code 为 1
|
||
- **THEN** 系统 SHALL 记录 `statusDetail="exitCode=1"`,并由 expect.exitCode 决定 matched 结果
|
||
|
||
#### Scenario: 命令启动失败
|
||
- **WHEN** command target 的 exec 不存在或无法启动
|
||
- **THEN** 系统 SHALL 记录 `matched=false`,并在 failure 中写入 kind=`error` 和可读错误信息
|
||
|
||
#### Scenario: 命令超时
|
||
- **WHEN** command target 在 timeout 时间内未结束
|
||
- **THEN** 系统 MUST 终止该子进程,记录 `matched=false`,并在 failure 中写入命令超时信息
|
||
|
||
#### Scenario: 命令输出超限
|
||
- **WHEN** command target 的 stdout 和 stderr 合计输出超过 `maxOutputBytes`
|
||
- **THEN** 系统 MUST 停止收集输出并终止该检查,记录 `matched=false`,并在 failure 中写入输出超限信息
|
||
|
||
### Requirement: command expect 校验
|
||
系统 SHALL 支持 command 专用 expect,包括 `exitCode`、`stdout` 和 `stderr`,并按 exitCode、duration、stdout、stderr 的阶段顺序快速失败。
|
||
|
||
#### Scenario: 默认 exitCode 成功语义
|
||
- **WHEN** command target 未显式配置 `expect.exitCode`
|
||
- **THEN** 系统 SHALL 使用默认 `expect.exitCode: [0]` 进行校验
|
||
|
||
#### Scenario: 显式 exitCode 校验
|
||
- **WHEN** command target 配置 `expect.exitCode: [0, 2]` 且实际 exit code 为 2
|
||
- **THEN** 系统 SHALL 判定 exitCode 阶段通过,并继续后续 expect 阶段
|
||
|
||
#### Scenario: exitCode 不匹配快速失败
|
||
- **WHEN** command target 配置 `expect.exitCode: [0]` 且实际 exit code 为 1
|
||
- **THEN** 系统 SHALL 立即返回 `matched=false`,并在 failure 中写入 phase=`exitCode`、path=`expect.exitCode`、expected 和 actual
|
||
|
||
#### Scenario: stdout 按配置顺序校验
|
||
- **WHEN** command target 配置 `expect.stdout` 为两个规则,第一条通过且第二条失败
|
||
- **THEN** 系统 SHALL 先执行第一条 stdout 规则,再执行第二条,并将 failure.path 指向失败的 `expect.stdout[1]`
|
||
|
||
#### Scenario: stderr 校验为空
|
||
- **WHEN** command target 配置 `expect.stderr: [{empty: true}]` 且实际 stderr 为空字符串
|
||
- **THEN** 系统 SHALL 判定 stderr 阶段通过
|
||
|
||
#### Scenario: stdout 失败后不检查 stderr
|
||
- **WHEN** command target 同时配置 stdout 和 stderr 规则,且 stdout 规则失败
|
||
- **THEN** 系统 SHALL 快速失败并 MUST NOT 继续执行 stderr 规则
|
||
|
||
### Requirement: command checker 启动期配置校验
|
||
系统 SHALL 在启动期对 command checker 的配置契约和语义执行严格校验。Command target 的 `command` 分组 SHALL 只允许 `exec`、`args`、`cwd`、`env`、`maxOutputBytes` 字段;Command expect SHALL 只允许 `exitCode`、`maxDurationMs`、`stdout`、`stderr` 字段。未知字段、非法类型和不可编译正则 MUST 导致启动期配置错误。`expect.exitCode` SHALL 保留原有有限整数数组语义,不限制到特定平台范围。
|
||
|
||
#### Scenario: command args 类型非法
|
||
- **WHEN** YAML 中 command target 配置 `command.args` 不是字符串数组
|
||
- **THEN** 系统 SHALL 以配置错误退出,提示 command.args 格式错误
|
||
|
||
#### Scenario: command cwd 类型非法
|
||
- **WHEN** YAML 中 command target 配置 `command.cwd` 不是字符串
|
||
- **THEN** 系统 SHALL 以配置错误退出,提示 command.cwd 必须为字符串
|
||
|
||
#### Scenario: command env 值类型非法
|
||
- **WHEN** YAML 中 command target 配置 `command.env`,且任一环境变量值不是字符串
|
||
- **THEN** 系统 SHALL 以配置错误退出,提示 command.env 对应变量值必须为字符串
|
||
|
||
#### Scenario: command maxOutputBytes 非法
|
||
- **WHEN** YAML 中 command target 或 defaults.command 配置的 `maxOutputBytes` 不是合法 size 值
|
||
- **THEN** 系统 SHALL 以配置错误退出,提示 maxOutputBytes 格式错误
|
||
|
||
#### Scenario: command 分组未知字段失败
|
||
- **WHEN** YAML 中 command target 的 `command` 分组包含 `shell: true` 等未知字段
|
||
- **THEN** 系统 SHALL 以配置错误退出,提示 command 分组包含未知字段
|
||
|
||
#### Scenario: command expect exitCode 类型非法
|
||
- **WHEN** YAML 中 command target 配置 `expect.exitCode` 不是整数数组
|
||
- **THEN** 系统 SHALL 以配置错误退出,提示 expect.exitCode 必须为整数数组
|
||
|
||
#### Scenario: command expect exitCode 不限制平台范围
|
||
- **WHEN** YAML 中 command target 配置 `expect.exitCode` 为有限整数数组
|
||
- **THEN** 系统 SHALL 接受该数组,不额外限制为 0-255 等平台相关范围
|
||
|
||
#### Scenario: command expect maxDurationMs 非法
|
||
- **WHEN** YAML 中 command target 配置 `expect.maxDurationMs` 不是非负有限数字
|
||
- **THEN** 系统 SHALL 以配置错误退出,提示 expect.maxDurationMs 格式错误
|
||
|
||
#### Scenario: stdout 必须为规则数组
|
||
- **WHEN** YAML 中 command target 配置 `expect.stdout` 但其值不是数组
|
||
- **THEN** 系统 SHALL 以配置错误退出,提示 expect.stdout 必须为数组
|
||
|
||
#### Scenario: stderr 必须为规则数组
|
||
- **WHEN** YAML 中 command target 配置 `expect.stderr` 但其值不是数组
|
||
- **THEN** 系统 SHALL 以配置错误退出,提示 expect.stderr 必须为数组
|
||
|
||
#### Scenario: stdout text rule 空对象非法
|
||
- **WHEN** YAML 中 command target 配置 `expect.stdout: [{}]`
|
||
- **THEN** 系统 SHALL 以配置错误退出,提示 stdout 规则必须包含至少一个合法 operator
|
||
|
||
#### Scenario: stderr text rule 未知字段非法
|
||
- **WHEN** YAML 中 command target 配置 `expect.stderr: [{foo: "bar"}]`
|
||
- **THEN** 系统 SHALL 以配置错误退出,提示 stderr 规则包含未知 operator
|
||
|
||
#### Scenario: stdout match 正则非法
|
||
- **WHEN** YAML 中 command target 配置 `expect.stdout: [{match: "[invalid"}]`
|
||
- **THEN** 系统 SHALL 在启动期配置校验失败,而不是延迟到运行期抛错
|
||
|
||
#### Scenario: command expect 未知字段失败
|
||
- **WHEN** YAML 中 command target 的 expect 包含 `status: [200]` 或其他非 command expect 字段
|
||
- **THEN** 系统 SHALL 以配置错误退出,提示 expect 包含未知字段
|