mirror of
https://github.com/norandom/OpenUltraSAST.git
synced 2026-10-19 13:10:03 +00:00
53 lines
2.3 KiB
Python
53 lines
2.3 KiB
Python
"""``ousast plane doctor``: four checks of this host's ax before a Run is submitted (ai-service-plane Req 3.5).
|
|||
|
|
|
||
|
|
A sibling of ``reconciler.py`` (tasks.md task 0 allows either), which re-exports :func:`doctor`.
|
||
|
|
"""
|
||
|
|
|
||
|
|
from __future__ import annotations
|
||
|
|
|
||
|
|
import os
|
||
|
|
import re
|
||
|
|
import subprocess
|
||
|
|
|
||
|
|
UP = "ops/ax/up.sh brings it up"
|
||
|
|
|
||
|
|
|
||
|
|
# --- checks ----------------------------------------------------------------------------------------------
|
||
|
|
|
||
|
|
|
||
|
|
def _sh(*args: str) -> tuple[bool, str]:
|
||
|
|
try:
|
||
|
|
proc = subprocess.run(args, capture_output=True, text=True, timeout=60, check=False)
|
||
|
|
except (OSError, subprocess.TimeoutExpired) as exc:
|
||
|
|
return False, str(exc)
|
||
|
|
return proc.returncode == 0, (proc.stdout + proc.stderr).strip()
|
||
|
|
|
||
|
|
|
||
|
|
def _pods_ready(namespace: str, context: str) -> tuple[bool, str]:
|
||
|
|
ok, out = _sh("kubectl", "--context", context, "-n", namespace, "get", "pods", "--no-headers")
|
||
|
|
if not ok or not out:
|
||
|
|
return False, out or "no pods"
|
||
|
|
rows = [r for r in (line.split() for line in out.splitlines()) if len(r) > 2 and re.fullmatch(r"\d+/\d+", r[1])]
|
||
|
|
if not rows: # "No resources found" is not a ready namespace
|
||
|
|
return False, f"no pods in {namespace}"
|
||
|
|
bad = [r[0] for r in rows if r[2] not in ("Completed", "Succeeded") and r[1].split("/")[0] != r[1].split("/")[1]]
|
||
|
|
return not bad, f"not ready: {', '.join(bad)}" if bad else f"{len(rows)} pods ready"
|
||
|
|
|
||
|
|
|
||
|
|
def doctor() -> list[tuple[str, bool, str]]:
|
||
|
|
"""Four checks of the host's ax: kind, Agent Substrate, the ax controller, the runner image (Req 3.5)."""
|
||
|
|
context = "kind-" + (os.environ.get("KIND_CLUSTER_NAME") or "ousast")
|
||
|
|
ok, out = _sh("kubectl", "--context", context, "cluster-info")
|
||
|
|
checks = [("kind cluster", ok, "reachable" if ok else f"context {context} unreachable ({out[:80]}); {UP}")]
|
||
|
|
for label, ns in (("agent substrate (ate-system)", "ate-system"), ("ax controller (ax-system)", "ax-system")):
|
||
|
|
ok, out = _pods_ready(ns, context)
|
||
|
|
checks.append((label, ok, out if ok else f"{out}; {UP}"))
|
||
|
|
ok, out = _sh("curl", "-s", "localhost:5001/v2/_catalog")
|
||
|
|
present = ok and "ousast-runner" in out
|
||
|
|
text = "ousast-runner present" if present else f"missing from localhost:5001 ({out[:80]}); {UP} and loads it"
|
||
|
|
checks.append(("runner image in kind registry", present, text))
|
||
|
|
return checks
|
||
|
|
|
||
|
|
|
||
|
|
__all__ = ["doctor"]
|