feat(sre): enforce typed host ansible handoffs

This commit is contained in:
Your Name
2026-07-18 23:11:04 +08:00
parent 83fe799f50
commit 5b2547e4ec
24 changed files with 2255 additions and 58 deletions

View File

@@ -278,6 +278,67 @@ async def dispatch_action(
user_id=user_id, result_text=result_text, duration_ms=duration,
)
# Host/systemd writes never dispatch the legacy SSH MCP tool. The
# callback only records one incident-bound candidate for the existing
# single-writer Ansible check/apply/verifier worker.
if (
spec.mcp_provider == "controlled"
and spec.mcp_tool == "host_ansible_reconcile"
):
from src.services.host_ansible_controlled_executor import (
queue_host_ansible_controlled_action_for_incident_id,
)
requested_host = str(resolved_params.get("host") or "")
requested_service = str(resolved_params.get("service") or "")
handoff = await queue_host_ansible_controlled_action_for_incident_id(
incident_id=incident_id,
requested_action=(
f"reconcile host service {requested_service}"
if requested_service and "{" not in requested_service
else "reconcile typed host service"
),
risk_level=spec.risk,
source="telegram_callback_host_systemd",
requested_host=(
requested_host
if requested_host and "{" not in requested_host
else None
),
)
duration = (time.perf_counter() - start) * 1000
if handoff.get("queued") is True:
run_id = str(handoff.get("automation_run_id") or "--")
return DispatchResult(
success=True,
action=action_name,
incident_id=incident_id,
user_id=user_id,
result_text=(
f"{spec.emoji} <b>{spec.label}</b> 已排入 Ansible check-mode\n"
"├ 目前:尚未執行修復、尚未完成驗證\n"
"├ Executor<code>host_ansible_executor</code>\n"
"├ Verifier<code>independent pending</code>\n"
f"└ Run<code>{run_id}</code>"
),
duration_ms=duration,
)
reason = str(
handoff.get("status") or "controlled_executor_queue_failed"
)
return DispatchResult(
success=False,
action=action_name,
incident_id=incident_id,
user_id=user_id,
result_text=(
f"{spec.emoji} <b>{spec.label}</b> 已由 typed gate 阻擋\n"
f"└ 原因:<code>{reason}</code>"
),
error=f"host_ansible_controlled_executor:{reason}",
duration_ms=duration,
)
# MCP registry dispatch
from src.plugins.mcp.registry import get_provider
from src.services.mcp_audit_context import with_mcp_audit_context