phase: 32_gateway_resolved_target_liveness

Fixture and live stream.conf are byte-identical (modulo header comment). Let me test the parser directly:
This commit is contained in:
2026-10-26 14:03:42 -04:00
parent 25fd74b7c5
commit 51772ffef2
58 changed files with 5272 additions and 478 deletions
+34
View File
@@ -24,6 +24,7 @@ import inspect
from typing import Any
from dashboards import alerts, severity
from dashboards.collectors import ADDON_ERROR_PREFIXES
from dashboards.config import Settings
from dashboards.sources import nut
from dashboards.sources.nut_sim import NutSimulator
@@ -351,6 +352,39 @@ def test_a_degraded_agent_warns_and_names_the_sections_that_failed(
assert "disk_io" in out[0]["message"]
def test_an_addon_absence_line_raises_no_row_and_a_section_that_failed_raises_one(
host_scrape: Any, agent_snapshot: dict[str, Any]) -> None:
"""Invariant 3's last link, `resolver:` included: filtered out means no row, unfiltered means one.
`collectors.ADDON_ERROR_PREFIXES` is what keeps an agent's add-on lines out of `degraded`
(`tests/test_collectors.py` pins that), and `degraded` is what this module turns into the
overview row pinned just above. So: a host whose agent said it runs no haproxy, no nginx, no
smartmontools and had **nothing to resolve** is all-clear on every panel — the phase-32 pair of
lines (`nothing to resolve`, `pass budget … exhausted`) included, because a truncated lookup is
one route without a count and not a broken box. And a line that *did* reach `degraded` — which
is what dropping a prefix from that list would do — does raise exactly one row, naming it.
"""
addon_lines = (
"resolver: nothing to resolve — haproxy not found and nginx not found; --no-resolve opts out",
"resolver: pass budget 3.0s exhausted, 41 of 58 targets looked up",
"haproxy: /etc/haproxy/haproxy.cfg not found — haproxy is not installed here",
"smart: smartctl 7.5 not found",
)
assert all(line.lower().startswith(ADDON_ERROR_PREFIXES) for line in addon_lines), (
"a prefix dropped from collectors' list would put this fleet's non-gateway hosts on warn")
clean = host_scrape(agent_snapshot, cpu_busy=10.0)
clean["agent"]["errors"] = list(addon_lines)
assert "degraded" not in clean, "the collector filtered them, so there is nothing to grade"
assert alerts.build(SETTINGS, [state()], [clean]) == []
for line in addon_lines:
broken = host_scrape(agent_snapshot, cpu_busy=10.0)
broken["degraded"] = [line]
out = alerts.build(SETTINGS, [state()], [broken])
assert [row["id"] for row in out] == ["driveripper:agent.sections"], line
def test_a_degraded_list_from_an_older_agent_is_readable_too(
host_scrape: Any, agent_snapshot: dict[str, Any]) -> None:
payload = host_scrape(agent_snapshot, cpu_busy=10.0)