Files
getDomain/domain-api/tests/test_ops_service_driver_feed.py
2026-04-18 23:52:51 +08:00

359 lines
20 KiB
Python
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.
import unittest
from unittest.mock import patch
from app.services.ops_service import get_ops_driver_feed
class OpsServiceDriverFeedTests(unittest.TestCase):
@patch("app.services.ops_service.get_ops_go_live_summary")
@patch("app.services.ops_service.get_ops_runbook")
@patch("app.services.ops_service.get_ops_overview")
def test_driver_feed_merges_priority_recommendation_driver_cards_and_runbook_sequences(
self,
mock_get_ops_overview,
mock_get_ops_runbook,
mock_get_ops_go_live_summary,
) -> None:
mock_get_ops_go_live_summary.return_value = {
"go_live_status": "blocked",
"publish_ready": False,
"publish_status": "blocked",
"publish_status_label": "暂不可发布",
"publish_summary": "当前仍有硬阻断项,不能直接进入正式发版。",
"operator_title": "先补接管缺口",
"next_step_action_code": "handover_first_gap",
"launchpad_recommended_target_node_code": "mainland-controller-01",
"launchpad_recommended_recovery_label": "签发接入工单",
"launchpad_recommended_recovery_summary": "当前节点仍处于接入阶段,建议先签发 onboarding.bootstrap。",
"launchpad_onboarding_bootstrap_pending_nodes": 1,
"launchpad_onboarding_acceptance_ready_nodes": 1,
"blocking_reasons": ["remote_agent_ready=0"],
"warnings": ["log_sync_waiting_sample=0/2"],
}
mock_get_ops_overview.return_value = {
"execution_scene": {
"participation_summary": {
"participating_nodes": 2,
"dispatch_active_node_codes": ["mainland-worker-01", "mainland-controller-01"],
},
"participating_nodes": [
{"node_code": "mainland-worker-01"},
{"node_code": "mainland-controller-01"},
],
"log_sync": {
"enabled": False,
"mode": "key",
"line_count": 0,
"source_node_count": 0,
"participating_node_count": 2,
"covered_participating_node_count": 0,
"missing_participating_nodes": ["mainland-worker-01", "mainland-controller-01"],
},
},
"recommendation": {
"key": "fix-handover-gap",
"priority": "先补接管缺口",
"title": "先补接管缺口",
"summary": "当前应该先把接管链路补齐。",
"reason": "否则后续批量动作无法稳定下发。",
"level_label": "最高优先",
"tag_type": "danger",
"primary_label": "纳管首台节点",
"secondary_label": "查看目标节点",
"primary_action_code": "handover_first_gap",
"secondary_action_code": "view_first_gap",
"node_codes": ["mainland-worker-02"],
"primary_node_codes": ["mainland-worker-02"],
"secondary_node_codes": ["mainland-worker-02"],
"primary_action_payload": {"requested_by": "test"},
"secondary_action_payload": {},
"reasons": ["当前存在接管缺口。"],
},
"activity_stream": {
"items": [
{
"kind": "ops_job",
"activity_key": "ops-job:501",
"title": "logs.collect",
"subtitle": "ops-logs-501",
"summary_text": "远端 Agent 已回传 120 行 Worker 日志,可直接继续分析。",
"summary": "远端 Agent 已回传 120 行 Worker 日志,可直接继续分析。",
"status": "running",
"status_label": "执行中",
"meta_text": "ops-logs-501 / 执行 远端 Agent",
"occurred_at": "2026-04-18 09:18:00",
"target_node_codes": ["mainland-worker-01"],
"focus_ref": {
"kind": "ops_job",
"job_id": 501,
"job_code": "ops-logs-501",
"action": "logs.collect",
"target_node_code": "mainland-worker-01",
},
"source_focus_ref": {
"kind": "ops_job_event",
"job_id": 501,
"event_key": "job-event:501",
},
"ui_intent": {
"kind": "job_events",
"job_id": 501,
"job_code": "ops-logs-501",
"action": "logs.collect",
"target_node_code": "mainland-worker-01",
},
}
]
},
"driver_recommendations": [
{
"key": "fix-handover-gap",
"title": "先补接管缺口",
"summary": "重复建议,不应再次进入 feed。",
"reason": "duplicate",
"level_label": "最高优先",
"tag_type": "danger",
"primary_label": "纳管首台节点",
"primary_action_code": "handover_first_gap",
},
{
"key": "inspect-scene-log-gap",
"title": "排查现场日志样本缺口",
"summary": "现场日志样本还没有形成。",
"reason": "先看 Worker 日志。",
"meta_text": "参与节点 2 台 / 已回传来源 0 台",
"level_label": "推荐",
"tag_type": "warning",
"primary_label": "看 Worker 日志",
"secondary_label": "执行标准巡检",
"primary_action_code": "open_worker_logs",
"secondary_action_code": "run_standard_inspection",
"node_codes": ["mainland-worker-01", "mainland-controller-01"],
"primary_node_codes": ["mainland-worker-01", "mainland-controller-01"],
"secondary_node_codes": ["mainland-worker-01", "mainland-controller-01"],
"primary_action_payload": {"lines": 120},
"secondary_action_payload": {},
},
],
}
mock_get_ops_runbook.return_value = {
"control_sequences": [
{
"key": "release_progression",
"title": "版本发布与放量",
"summary": "当前可进入发布路径。",
"reason": "正式运维时应统一落回 Release / Rollout。",
"status": "warning",
"status_label": "待处理",
"tag_type": "warning",
"target_scope_label": "Release / Rollout",
"target_node_codes": ["mainland-controller-01"],
"focus_ref": {
"kind": "release_hub",
"release_id": 7,
"section": "release_launchpad",
},
"primary_label": "补执行面接管",
"secondary_label": "查看版本区",
"primary_action_code": "fix_managed_nodes",
"secondary_action_code": "focus_release_hub",
"primary_focus_ref": {
"kind": "release_hub",
"release_id": 7,
"section": "default_rollout_gate",
},
"secondary_focus_ref": {
"kind": "release_hub",
"release_id": 7,
"section": "release_detail",
},
"step_titles": ["同步集群节点", "纳管首台缺口", "补齐 Agent 接入"],
"primary_resolution": {
"ok": True,
"driver_action_code": "fix_managed_nodes",
"driver_action_label": "补执行面接管",
"driver_node_codes": ["mainland-controller-01"],
"driver_action_payload": {"channel": "stable"},
"resolved_at": "2026-04-18T03:00:00",
},
"secondary_resolution": {
"ok": True,
"driver_action_code": "focus_release_hub",
"driver_action_label": "查看版本区",
"driver_node_codes": [],
"driver_action_payload": {"release_id": 7},
},
}
]
}
payload = get_ops_driver_feed()
self.assertEqual(3, payload["summary"]["total"])
self.assertEqual("blocked", payload["go_live_summary"]["go_live_status"])
self.assertEqual("blocked", payload["summary"]["go_live_status"])
self.assertEqual("先补接管缺口", payload["summary"]["operator_title"])
self.assertEqual("blocked", payload["summary"]["publish_status"])
self.assertFalse(payload["summary"]["publish_ready"])
self.assertEqual("暂不可发布", payload["summary"]["publish_status_label"])
self.assertIn("发布闸门:暂不可发布", payload["headline"])
self.assertIn("接入缺口签发接入工单mainland-controller-01", payload["headline"])
self.assertEqual("handover_first_gap", payload["go_live_summary"]["next_step_action_code"])
self.assertEqual("mainland-controller-01", payload["summary"]["launchpad_recommended_target_node_code"])
self.assertEqual("签发接入工单", payload["summary"]["launchpad_recommended_recovery_label"])
self.assertEqual(
"当前节点仍处于接入阶段,建议先签发 onboarding.bootstrap。",
payload["summary"]["launchpad_recommended_recovery_summary"],
)
self.assertEqual(1, payload["summary"]["launchpad_onboarding_bootstrap_pending_nodes"])
self.assertEqual(1, payload["summary"]["launchpad_onboarding_acceptance_ready_nodes"])
self.assertEqual(2, payload["summary"]["do_now_total"])
self.assertEqual(1, payload["summary"]["standard_path_total"])
self.assertEqual("ops_driver_contract", payload["contract_navigation"]["primary_contract_key"])
self.assertIn("ops_playbook_contract", payload["contract_navigation"]["contract_keys"])
self.assertIn("ops_observability_contract", payload["contract_navigation"]["contract_keys"])
self.assertEqual("priority:fix-handover-gap", payload["top_recommendation"]["key"])
self.assertEqual("ops_driver_contract", payload["top_recommendation"]["contract_navigation"]["primary_contract_key"])
self.assertEqual(2, len(payload["driver_recommendations"]))
self.assertEqual(1, len(payload["runbook_sequences"]))
self.assertEqual(1, len(payload["activity_focus"]))
self.assertEqual(
["priority_recommendation", "driver_recommendation", "runbook_sequence"],
[item["kind"] for item in payload["entries"]],
)
self.assertEqual(1, payload["summary"]["activity_focus_total"])
self.assertEqual("disabled", payload["summary"]["scene_log_status"])
self.assertEqual("blocked", payload["summary"]["launch_status"])
self.assertFalse(payload["summary"]["launch_ready"])
self.assertEqual(2, payload["summary"]["preview_only_total"])
self.assertEqual(3, payload["summary"]["backend_handled_total"])
self.assertEqual("blocked", payload["automation_coverage"]["launch_status"])
self.assertEqual(2, payload["automation_coverage"]["safe_auto_total"])
self.assertEqual(0, payload["automation_coverage"]["guarded_auto_total"])
self.assertEqual(2, payload["automation_coverage"]["auto_execute_total"])
self.assertEqual(1, payload["automation_coverage"]["resolve_first_total"])
self.assertEqual(2, payload["automation_coverage"]["preview_only_total"])
self.assertEqual(3, payload["automation_coverage"]["backend_handled_total"])
self.assertEqual(1, payload["automation_coverage"]["human_dependency_total"])
self.assertFalse(payload["automation_coverage"]["launch_ready"])
priority_entry = payload["entries"][0]
self.assertEqual("do_now", priority_entry["lane"])
self.assertEqual("driver_action", priority_entry["executor_kind"])
self.assertEqual("handover_first_gap", priority_entry["primary_action_code"])
self.assertEqual("ops_driver_contract", priority_entry["contract_navigation"]["primary_contract_key"])
activity_focus = payload["activity_focus"][0]
self.assertEqual("ops_job", activity_focus["activity_kind"])
self.assertEqual("远端 Agent 已回传 120 行 Worker 日志,可直接继续分析。", activity_focus["summary"])
self.assertEqual("focus_latest_job_events", activity_focus["focus_action_code"])
self.assertEqual("job_events", activity_focus["ui_intent_kind"])
self.assertEqual("ops_job_event", activity_focus["source_focus_ref"]["kind"])
self.assertTrue(activity_focus["observation_only"])
self.assertEqual("ops_observability_contract", activity_focus["contract_navigation"]["primary_contract_key"])
self.assertIn("ops_stack_diagnosis_contract", activity_focus["contract_navigation"]["contract_keys"])
scene_log_observation = payload["scene_log_observation"]
self.assertEqual("disabled", scene_log_observation["status"])
self.assertEqual("mainland-worker-01", scene_log_observation["target_node_code"])
self.assertEqual("node_scene_log", scene_log_observation["focus_ref"]["kind"])
self.assertEqual(
"ops_observability_contract",
scene_log_observation["contract_navigation"]["primary_contract_key"],
)
runbook_entry = payload["entries"][2]
self.assertEqual("runbook_sequence", runbook_entry["kind"])
self.assertEqual("standard_path", runbook_entry["lane"])
self.assertEqual("runbook_sequence", runbook_entry["executor_kind"])
self.assertEqual("release_progression", runbook_entry["sequence_key"])
self.assertEqual("fix_managed_nodes", runbook_entry["primary_action_code"])
self.assertEqual("focus_release_hub", runbook_entry["secondary_action_code"])
self.assertIn("当前解析:补执行面接管", runbook_entry["detail_lines"][0])
self.assertEqual("release_hub", runbook_entry["focus_ref"]["kind"])
self.assertEqual("release_launchpad", runbook_entry["focus_ref"]["section"])
self.assertEqual("default_rollout_gate", runbook_entry["primary_focus_ref"]["section"])
self.assertEqual("release_detail", runbook_entry["secondary_focus_ref"]["section"])
self.assertEqual("default_rollout_gate", runbook_entry["primary_action_payload"]["focus_ref"]["section"])
self.assertEqual("release_detail", runbook_entry["secondary_action_payload"]["focus_ref"]["section"])
self.assertEqual("ops_driver_contract", runbook_entry["contract_navigation"]["primary_contract_key"])
self.assertIn("ops_playbook_contract", runbook_entry["contract_navigation"]["contract_keys"])
self.assertIn("release_hub_contract", runbook_entry["contract_navigation"]["contract_keys"])
@patch("app.services.ops_service.get_ops_go_live_summary")
@patch("app.services.ops_service.get_ops_runbook")
@patch("app.services.ops_service.get_ops_overview")
def test_driver_feed_preserves_bootstrap_run_as_top_recommendation(
self,
mock_get_ops_overview,
mock_get_ops_runbook,
mock_get_ops_go_live_summary,
) -> None:
mock_get_ops_go_live_summary.return_value = {
"go_live_status": "attention",
"publish_ready": False,
"publish_status": "attention",
"publish_status_label": "可发布但建议先复核",
"publish_summary": "当前没有硬阻断,但仍有上线前关注项,建议先完成复核再正式发版。",
"operator_title": "先跑接入收口",
"next_step_action_code": "bootstrap_run",
"launchpad_recommended_target_node_code": "mainland-worker-01",
"launchpad_recommended_recovery_label": "跑接入收口",
"launchpad_recommended_recovery_summary": "mainland-worker-01 还缺接入收口,先执行 bootstrap。",
"launchpad_onboarding_bootstrap_pending_nodes": 1,
"launchpad_onboarding_acceptance_ready_nodes": 0,
"blocking_reasons": [],
"warnings": ["remote_agent_ready=1/2"],
}
mock_get_ops_overview.return_value = {
"recommendation": {
"key": "handover-gap-bootstrap_run",
"priority": "先补接管缺口",
"title": "先补接管缺口",
"summary": "Launchpad 已明确收敛到首台节点接入收口。",
"reason": "mainland-worker-01 还缺接入收口,先执行 bootstrap。",
"level_label": "最高优先",
"tag_type": "warning",
"primary_label": "跑接入收口",
"secondary_label": "查看目标节点",
"primary_action_code": "bootstrap_run",
"secondary_action_code": "view_first_gap",
"node_codes": ["mainland-worker-01"],
"primary_node_codes": ["mainland-worker-01"],
"secondary_node_codes": ["mainland-worker-01"],
"primary_action_payload": {"node_code": "mainland-worker-01"},
"secondary_action_payload": {},
"focus_ref": {"kind": "managed_node", "node_code": "mainland-worker-01"},
"primary_focus_ref": {"kind": "managed_node", "node_code": "mainland-worker-01"},
"secondary_focus_ref": {"kind": "managed_node", "node_code": "mainland-worker-01"},
},
"driver_recommendations": [],
"activity_stream": {"items": []},
"execution_scene": {},
}
mock_get_ops_runbook.return_value = {"control_sequences": []}
payload = get_ops_driver_feed()
self.assertEqual("priority:handover-gap-bootstrap_run", payload["top_recommendation"]["key"])
self.assertEqual("attention", payload["summary"]["publish_status"])
self.assertEqual("可发布但建议先复核", payload["summary"]["publish_status_label"])
self.assertEqual("mainland-worker-01", payload["summary"]["launchpad_recommended_target_node_code"])
self.assertEqual("跑接入收口", payload["summary"]["launchpad_recommended_recovery_label"])
self.assertEqual(1, payload["summary"]["launchpad_onboarding_bootstrap_pending_nodes"])
self.assertEqual(0, payload["summary"]["launchpad_onboarding_acceptance_ready_nodes"])
self.assertEqual("attention", payload["summary"]["launch_status"])
self.assertFalse(payload["summary"]["launch_ready"])
self.assertEqual("bootstrap_run", payload["top_recommendation"]["primary_action_code"])
self.assertEqual("mainland-worker-01", payload["top_recommendation"]["primary_node_codes"][0])
self.assertIn("ops_agent_protocol", payload["top_recommendation"]["contract_navigation"]["contract_keys"])
self.assertEqual("ops_driver_contract", payload["top_recommendation"]["contract_navigation"]["primary_contract_key"])
self.assertEqual(0, payload["automation_coverage"]["safe_auto_total"])
self.assertEqual(1, payload["automation_coverage"]["mixed_total"])
self.assertEqual(0, payload["automation_coverage"]["preview_only_total"])
self.assertEqual(1, payload["automation_coverage"]["backend_handled_total"])
if __name__ == "__main__":
unittest.main()