Files
getDomain/docs/schemas/ops_playbook_contract.md
2026-04-18 23:52:51 +08:00

12 KiB
Raw Permalink Blame History

domainCheck Ops Playbook Contract

1. 目标

这份文档用于冻结 playbook catalog / preview / run / events 的正式 contract。

这层的定位不是“页面里的一个弹窗”,而是:

  • 控制面的正式编排对象
  • 海外 Codex 驾驶员可消费的标准作业对象
  • Driver / Runbook / Release / Inspection 之间的统一中间层

核心原则:

  • 一次标准编排 = 一次 playbook run
  • 页面、CLI、Codex 必须共用同一份 playbook / playbook run 结构
  • playbook run 只负责创建与聚合正式 ops job
  • 不允许前端再把“标准巡检 / 接管验收 / 现场日志”退回成零散按钮逻辑

建议与 ops_job_contract.md 配套阅读。


2. 当前接口面

当前已落地的主入口:

  • GET /api/v1/ops/playbooks
  • POST /api/v1/ops/playbooks/preview
  • POST /api/v1/ops/playbooks/execute
  • GET /api/v1/ops/playbook-runs
  • GET /api/v1/ops/playbook-runs/{run_code}
  • GET /api/v1/ops/playbook-runs/{run_code}/events
  • POST /api/v1/ops/playbook-runs/{run_code}/rerun
  • POST /api/v1/ops/playbook-runs/{run_code}/cancel

并且这层已经被以下入口复用:

  • driver action -> open_playbook_dialog
  • runbook sequence -> secondary_resolution
  • inspection
  • activity-stream

所以后续不应再新造第四套“标准作业对象”。


3. Playbook Catalog Object

来源:

  • GET /api/v1/ops/playbooks
  • preview / execute 返回体中的 playbook

最小字段:

{
  "key": "inspection.standard",
  "group_key": "diagnostics",
  "group_title": "标准巡检",
  "title": "标准巡检",
  "description": "按 健康快照 -> Worker 日志 -> 诊断包 的顺序,对目标节点做一次标准联调巡检。",
  "target_scope": "node-set",
  "default_execution_mode": "remote-agent",
  "default_execution_mode_label": "Node Agent",
  "execution_modes": [
    "remote-agent",
    "ssh"
  ],
  "execution_mode_options": [
    {
      "value": "remote-agent",
      "label": "Node Agent",
      "is_default": true
    },
    {
      "value": "ssh",
      "label": "SSH",
      "is_default": false
    }
  ],
  "default_auto_approve": true,
  "stop_on_failure": true,
  "steps": [
    {
      "step_key": "health",
      "title": "采集健康快照",
      "template_key": "health.snapshot",
      "payload": {}
    }
  ]
}

正式约束:

  • key
    • 是 Playbook 的稳定主键
  • group_key
    • 用于页面、CLI、Codex 做标准分组,不应用 title
  • execution_modes
    • 是能力白名单,不是建议文案
  • stop_on_failure
    • 是编排级行为,不是某一步骤的临时说明

4. Playbook Preview Contract

来源:

  • POST /api/v1/ops/playbooks/preview

最小请求体:

{
  "playbook_key": "inspection.standard",
  "node_codes": [
    "mainland-worker-01"
  ],
  "execution_mode": "remote-agent",
  "auto_approve": true,
  "requested_by": "web-ui"
}

最小返回体:

{
  "playbook": {},
  "requested_by": "web-ui",
  "execution_mode": "remote-agent",
  "execution_mode_label": "Node Agent",
  "auto_approve": true,
  "target_nodes_total": 1,
  "target_node_codes": [
    "mainland-worker-01"
  ],
  "step_count": 3,
  "expected_jobs_total": 3,
  "template_keys": [
    "health.snapshot",
    "logs.collect",
    "diagnostics.collect"
  ],
  "steps": [
    {
      "order": 1,
      "step_key": "health",
      "title": "采集健康快照",
      "template_key": "health.snapshot",
      "action": "health.snapshot",
      "payload": {},
      "execution_mode": "remote-agent",
      "execution_mode_label": "Node Agent",
      "auto_approve": true,
      "target_nodes_total": 1,
      "expected_jobs": 1
    }
  ]
}

预览阶段必须回答:

  • 最终执行方式是什么
  • 总共会展开多少步
  • 每步会展开成什么模板
  • 总共会生成多少个 ops job

这样页面、CLI、Codex 才能在执行前看见“这次会做什么”。


5. Playbook Run Object

来源:

  • GET /api/v1/ops/playbook-runs
  • GET /api/v1/ops/playbook-runs/{run_code}
  • POST /api/v1/ops/playbooks/execute

最小字段:

{
  "run_code": "playbook-20260418-001",
  "playbook_key": "inspection.standard",
  "playbook_title": "标准巡检",
  "group_key": "diagnostics",
  "group_title": "标准巡检",
  "requested_by": "web-ui",
  "execution_mode": "remote-agent",
  "execution_mode_label": "Node Agent",
  "stop_on_failure": true,
  "step_count": 3,
  "expected_jobs_total": 3,
  "target_nodes_total": 1,
  "target_node_codes": [
    "mainland-worker-01"
  ],
  "created_at": "2026-04-18 06:30:00",
  "updated_at": "2026-04-18 06:31:10",
  "status": "running",
  "status_label": "收口中",
  "status_counts": {
    "queued": 1,
    "running": 1,
    "success": 1
  },
  "jobs_total": 3,
  "success_jobs_total": 1,
  "terminal_jobs_total": 1,
  "completion_percent": 33.3,
  "steps_total": 3,
  "steps_success": 1,
  "steps_running": 1,
  "steps_problem": 0,
  "steps_terminal": 1,
  "focus_level": "warning",
  "focus_step_key": "worker_logs",
  "focus_step_title": "收集 Worker 日志",
  "focus_summary": "收集 Worker 日志 当前仍在执行,先等待回执或检查对应节点事件流。",
  "summary": "收集 Worker 日志 当前仍在执行,先等待回执或检查对应节点事件流。",
  "summary_text": "收集 Worker 日志 当前仍在执行,先等待回执或检查对应节点事件流。",
  "focus_ref": {
    "kind": "playbook_run",
    "run_code": "playbook-20260418-001",
    "playbook_key": "inspection.standard",
    "group_key": "diagnostics",
    "focus_step_key": "worker_logs",
    "focus_step_title": "收集 Worker 日志",
    "event_key": "",
    "node_code": ""
  },
  "problem_steps": [],
  "active_steps": [],
  "latest_job": {},
  "steps": []
}

正式定义:

playbook run 是一轮标准编排在控制面的聚合对象,不是某一条单独任务。

也就是说:

  • ops job 是执行颗粒度
  • playbook run 是观察、重跑、取消、钻取的编排颗粒度

6. Playbook Step Object

playbook run.steps[] 的最小结构:

{
  "step_key": "worker_logs",
  "title": "收集 Worker 日志",
  "template_key": "logs.collect",
  "order": 2,
  "jobs_total": 1,
  "nodes_total": 1,
  "target_node_codes": [
    "mainland-worker-01"
  ],
  "status_counts": {
    "running": 1
  },
  "terminal_jobs_total": 0,
  "success_jobs_total": 0,
  "status": "running",
  "status_label": "收口中",
  "completion_percent": 0.0,
  "summary": "收集 Worker 日志 当前处于执行中,可继续观察该步骤事件。",
  "summary_text": "收集 Worker 日志 当前处于执行中,可继续观察该步骤事件。",
  "focus_ref": {
    "kind": "playbook_run",
    "run_code": "playbook-20260418-001",
    "playbook_key": "inspection.standard",
    "group_key": "diagnostics",
    "focus_step_key": "worker_logs",
    "focus_step_title": "收集 Worker 日志",
    "event_key": "",
    "node_code": ""
  },
  "latest_job": {}
}

推荐 step 状态:

  • queued
  • running
  • success
  • attention

规则:

  • 只要该步骤出现失败、阻断、取消等终态问题,应收口为 attention
  • 页面与 Codex 都应优先盯 problem_steps / active_steps,而不是自己遍历所有子任务推断

7. Playbook Event Stream

来源:

  • GET /api/v1/ops/playbook-runs/{run_code}/events

最小返回体:

{
  "run_code": "playbook-20260418-001",
  "playbook_run": {},
  "events": [
    {
      "job_id": 123,
      "job_code": "ops-20260418-123",
      "run_code": "playbook-20260418-001",
      "job_status": "running",
      "job_status_label": "收口中",
      "action": "logs.collect",
      "target_node_code": "mainland-worker-01",
      "step_key": "worker_logs",
      "step_title": "收集 Worker 日志",
      "event_type": "job_running",
      "level": "info",
      "level_label": "信息",
      "message": "开始收集 Worker 日志",
      "summary": "开始收集 Worker 日志",
      "summary_text": "开始收集 Worker 日志",
      "payload": {},
      "event_key": "job-event:1001",
      "occurred_at": "2026-04-18 06:31:00",
      "focus_ref": {
        "kind": "playbook_run",
        "run_code": "playbook-20260418-001",
        "playbook_key": "inspection.standard",
        "group_key": "diagnostics",
        "focus_step_key": "worker_logs",
        "focus_step_title": "收集 Worker 日志",
        "event_key": "job-event:1001",
        "node_code": "mainland-worker-01"
      },
      "created_at": "2026-04-18 06:31:00"
    }
  ],
  "summary": {
    "total": 1,
    "returned_total": 1,
    "available_step_counts": {
      "worker_logs": 1
    },
    "available_node_counts": {
      "mainland-worker-01": 1
    },
    "level_counts": {
      "info": 1
    },
    "event_type_counts": {
      "job_running": 1
    },
    "job_status_counts": {
      "running": 1
    },
    "latest_at": "2026-04-18 06:31:00",
    "filters": {
      "step_key": "",
      "node_code": "",
      "limit": 80
    }
  }
}

这层必须支持:

  • step_key 过滤
  • node_code 过滤
  • 快速看到最近活动时间

否则 playbook run 只能看总览,不能真正钻取。


8. 正式 Playbook Key 语义

当前最值得冻结成正式对象的 key

8.1 onboarding.bootstrap

定位:

  • 生成节点接入工单

执行方式:

  • control-plane

正式语义:

  • 不直接接管节点
  • 只创建标准接入方案对象

8.2 onboarding.acceptance

定位:

  • 新节点接管后标准验收

当前标准步骤:

  1. health.snapshot
  2. service.status(node-agent)
  3. logs.collect(node-agent)
  4. service.status(worker)
  5. logs.collect(worker)

8.3 inspection.standard

定位:

  • 标准巡检

当前标准步骤:

  1. health.snapshot
  2. logs.collect(worker)
  3. diagnostics.collect

正式要求:

  • 这是 release / rollout 之前最核心的健康观察面

8.4 scene.logs.key

定位:

  • 关键现场日志样本

正式要求:

  • 默认比 scene.logs.full 更轻
  • 适合先看现场,再决定是否升级取证

8.5 scene.logs.full

定位:

  • 全量现场取证

正式要求:

  • 应明确比 scene.logs.key 更重
  • 默认应同时补诊断包

8.6 scene.diagnostics

定位:

  • 轻量诊断包

正式要求:

  • 适合作为参与节点的常规取证动作

9. 执行模式 Contract

推荐模式:

  • remote-agent
  • ssh
  • control-plane

正式约束:

  • remote-agent
    • 正式日常运维默认模式
  • ssh
    • 仅用于首发接管与应急救援
  • control-plane
    • 只适合控制面本地对象生成或极少量控制面动作

页面、CLI、Codex 不能自己发明第四种临时模式。


10. Playbook Run 状态机

推荐状态:

  • queued
  • running
  • success
  • attention

含义:

  • queued
    • 子任务刚创建,尚未出现有效执行推进
  • running
    • 已有子任务进入 dispatching / running / awaiting_approval
  • success
    • 全部子任务收口成功
  • attention
    • 任一步骤出现失败、阻断、取消或部分成功,需要人工关注

正式规则:

  • 页面上的“标准巡检状态”
  • activity-stream 中的 playbook run 摘要
  • Driver / Codex 的推荐动作

都必须共用这一套状态语义。


11. 与 Driver / Runbook / Release 的关系

正式收口规则:

  • Driver 不直接“模拟巡检”
    • 应优先跳转或创建 playbook run
  • Runbook Sequence 不直接展开 shell
    • 应优先收口到 driver actionplaybook
  • Release / Rollout 不自己维护另一套巡检摘要
    • 应优先消费 inspection.standard 的最近结果

也就是说:

  • scene 是现场观察对象
  • inspection 是标准健康对象
  • release / rollout 是发布对象

三者不能再各自维护不同的“日志 / 诊断 / 巡检”定义。


12. 正式要求

后续继续演进时,必须保持:

  1. playbook catalog
    • 是稳定 contract而不是页面枚举
  2. playbook preview
    • 是执行前的唯一结构化预览面
  3. playbook run
    • 是页面、CLI、Codex 共同观察的一轮编排对象
  4. playbook events
    • 是整轮编排的钻取视角
  5. 接管验收、标准巡检、现场观察
    • 优先都收进 playbook

这样这套编排才能成为真正的正式平台能力,而不是一组“看起来像流程”的按钮。