mirror of
https://github.com/norandom/OpenUltraSAST.git
synced 2026-10-16 03:49:26 +00:00
fix(plane): doctor no longer reads "No resources found" as a ready pod
kubectl prints the sentence as one whitespace-split row, which passed the ready check and reported an absent ax controller as "1 pods ready". Rows must carry a READY column; an empty namespace fails. Regression test added. Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01EmM1j46qgKMh3zqD1QMwEo
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
ea9d7c7b7d
commit
e6d5124ffc
@@ -469,8 +469,10 @@ def _pods_ready(namespace: str, context: str) -> tuple[bool, str]:
|
|||||||
ok, out = _sh("kubectl", "--context", context, "-n", namespace, "get", "pods", "--no-headers")
|
ok, out = _sh("kubectl", "--context", context, "-n", namespace, "get", "pods", "--no-headers")
|
||||||
if not ok or not out:
|
if not ok or not out:
|
||||||
return False, out or "no pods"
|
return False, out or "no pods"
|
||||||
rows = [line.split() for line in out.splitlines()]
|
rows = [r for r in (line.split() for line in out.splitlines()) if len(r) > 2 and re.fullmatch(r"\d+/\d+", r[1])]
|
||||||
bad = [r[0] for r in rows if len(r) > 2 and r[2] not in ("Completed", "Succeeded") and r[1].split("/")[0] != r[1].split("/")[-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"
|
return not bad, f"not ready: {', '.join(bad)}" if bad else f"{len(rows)} pods ready"
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -483,3 +483,16 @@ def test_elapsed_polling_is_paced(fake: Fake, tmp_path: Path, monkeypatch: pytes
|
|||||||
started = time.monotonic()
|
started = time.monotonic()
|
||||||
assert reconciler.run(write_run(tmp_path, "paced", PAIR.replace("{serialize}", "")), ax=str(fake.ax)) == "done"
|
assert reconciler.run(write_run(tmp_path, "paced", PAIR.replace("{serialize}", "")), ax=str(fake.ax)) == "done"
|
||||||
assert time.monotonic() - started >= 0.4, "three polls of x plus one of y at 0.1s each"
|
assert time.monotonic() - started >= 0.4, "three polls of x plus one of y at 0.1s each"
|
||||||
|
|
||||||
|
|
||||||
|
def test_doctor_treats_an_empty_namespace_as_not_ready(monkeypatch: pytest.MonkeyPatch) -> None:
|
||||||
|
"""kubectl's "No resources found" must not read as one ready pod (a plausible-zero instrument failure)."""
|
||||||
|
from openultrasast.plane import reconciler
|
||||||
|
|
||||||
|
monkeypatch.setattr(reconciler, "_sh", lambda *a: (True, "No resources found in ax-system namespace."))
|
||||||
|
ok, text = reconciler._pods_ready("ax-system", "kind-ousast")
|
||||||
|
assert not ok and "no pods" in text
|
||||||
|
monkeypatch.setattr(reconciler, "_sh", lambda *a: (True, "a-1 1/1 Running 0 1m\nb-2 0/1 Completed 0 1m"))
|
||||||
|
assert reconciler._pods_ready("ns", "ctx") == (True, "2 pods ready")
|
||||||
|
monkeypatch.setattr(reconciler, "_sh", lambda *a: (True, "a-1 0/1 Running 0 1m"))
|
||||||
|
assert reconciler._pods_ready("ns", "ctx")[0] is False
|
||||||
|
|||||||
Reference in New Issue
Block a user