fix(api): normalize ssh mcp evidence inputs
All checks were successful
CD Pipeline / tests (push) Successful in 1m29s
Code Review / ai-code-review (push) Successful in 12s
CD Pipeline / build-and-deploy (push) Successful in 4m31s
CD Pipeline / post-deploy-checks (push) Successful in 1m40s

This commit is contained in:
Your Name
2026-06-01 01:11:10 +08:00
parent b83f9c5a52
commit 87378b452d
5 changed files with 39 additions and 2 deletions

View File

@@ -70,6 +70,7 @@ SHORT_HOST_MAP = {
"120": "192.168.0.120", "120": "192.168.0.120",
"121": "192.168.0.121", "121": "192.168.0.121",
"188": "192.168.0.188", "188": "192.168.0.188",
"wooo": "192.168.0.110",
} }
DIAG_TIMEOUT = 10 # 診斷類超時(秒) DIAG_TIMEOUT = 10 # 診斷類超時(秒)
OP_TIMEOUT = 60 # 操作類超時(秒) OP_TIMEOUT = 60 # 操作類超時(秒)
@@ -587,7 +588,10 @@ class SSHProvider(MCPToolProvider):
return f"docker logs {name} --tail {tail} 2>&1" return f"docker logs {name} --tail {tail} 2>&1"
if tool_name == "ssh_get_container_status": if tool_name == "ssh_get_container_status":
name = _validate_param("filter_name", params["filter_name"]) raw_name = params.get("filter_name") or params.get("container_name") or params.get("name")
if not raw_name:
raise ValueError("Missing filter_name for ssh_get_container_status")
name = _validate_param("filter_name", str(raw_name))
return f"docker ps -a --filter name={name}" return f"docker ps -a --filter name={name}"
if tool_name == "ssh_get_service_status": if tool_name == "ssh_get_service_status":

View File

@@ -2661,7 +2661,7 @@ class DecisionManager:
ssh.execute( ssh.execute(
tool_name="ssh_get_container_status", tool_name="ssh_get_container_status",
# P0.4 fix 2026-04-24 ogt + Claude Sonnet 4.6: params= → parameters=(符合 MCPToolProvider.execute 簽名) # P0.4 fix 2026-04-24 ogt + Claude Sonnet 4.6: params= → parameters=(符合 MCPToolProvider.execute 簽名)
parameters={"host": host, "container_name": container}, parameters={"host": host, "filter_name": container, "container_name": container},
), ),
timeout=_MCP_TIMEOUT, timeout=_MCP_TIMEOUT,
) )

View File

@@ -552,6 +552,7 @@ _SHORT_HOST_MAP: dict[str, str] = {
"188": "192.168.0.188", "188": "192.168.0.188",
"ollama": "192.168.0.188", "ollama": "192.168.0.188",
"ai-web": "192.168.0.188", "ai-web": "192.168.0.188",
"wooo": "192.168.0.110",
"harbor": "192.168.0.110", "harbor": "192.168.0.110",
"gitea": "192.168.0.110", "gitea": "192.168.0.110",
} }

View File

@@ -173,6 +173,25 @@ def test_build_tool_params_uses_host_alias_and_service_from_affected_service() -
assert params["time_window_minutes"] == 30 assert params["time_window_minutes"] == 30
def test_build_tool_params_maps_wooo_alias_to_allowed_ssh_host() -> None:
class _Signal:
alert_name = "HostHighCpuLoad"
labels = {
"alertname": "HostHighCpuLoad",
"instance": "wooo:9100",
}
class _Incident:
incident_id = "INC-WOOO"
signals = [_Signal()]
affected_services = ["gitea"]
params = _build_tool_params(_Incident())
assert params["host"] == "192.168.0.110"
assert params["filter_name"] == "gitea"
# ───────────────────────────────────────────────────────────────────────────── # ─────────────────────────────────────────────────────────────────────────────
# _compute_fingerprint # _compute_fingerprint
# ───────────────────────────────────────────────────────────────────────────── # ─────────────────────────────────────────────────────────────────────────────

View File

@@ -45,6 +45,8 @@ def test_ssh_provider_uses_ollama_user_for_188():
[ [
("192.168.0.110:9100", "192.168.0.110"), ("192.168.0.110:9100", "192.168.0.110"),
("110:9100", "192.168.0.110"), ("110:9100", "192.168.0.110"),
("wooo", "192.168.0.110"),
("wooo:9100", "192.168.0.110"),
("188", "192.168.0.188"), ("188", "192.168.0.188"),
("wooo@192.168.0.110", "192.168.0.110"), ("wooo@192.168.0.110", "192.168.0.110"),
("ssh://wooo@192.168.0.110:22", "192.168.0.110"), ("ssh://wooo@192.168.0.110:22", "192.168.0.110"),
@@ -90,3 +92,14 @@ async def test_ssh_execute_normalizes_host_before_allowed_check(monkeypatch):
assert result.success is True assert result.success is True
assert captured["host"] == "192.168.0.110" assert captured["host"] == "192.168.0.110"
assert isinstance(captured["timeout"], int) assert isinstance(captured["timeout"], int)
def test_ssh_container_status_accepts_legacy_container_name_alias():
provider = SSHProvider()
command = provider._build_command(
"ssh_get_container_status",
{"container_name": "awoooi-api"},
)
assert command == "docker ps -a --filter name=awoooi-api"