fix: error-pages graded healthy, unwired sensors listed apart, Maintenance failed reads 0 (#5780, #5781, #5782)
- #5780 "The error-pages service is graded on other routers' errors". The Traefik scrape reads which services an errors middleware sends to, and grades them healthy: their 4xx and 5xx are the codes of the errors they cover for, already graded on the routers that failed. - #5781 "The Maintenance failed rules sit at no data until a host has had a maintenance job". Every host with an agent reads 0 until a job fails. - #5782 "VDNT-Util01's host page lists SYSTIN at 115 °C in red". The host page lists sensors that counts_as_hottest leaves out (unwired board inputs, 0 °C or below) on one muted line, not as heat. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -341,6 +341,32 @@ async def fetch_router_domains(base: str) -> dict[str, list[str]]:
|
||||
return out
|
||||
|
||||
|
||||
async def fetch_error_page_services(base: str) -> frozenset[str]:
|
||||
"""The services Traefik's `errors` middlewares send error pages to, named
|
||||
as the metrics name them ("error-pages-service@swarm"). Such a service
|
||||
answers with the code of the error it covers for: its 4xx and 5xx are
|
||||
other routers' errors, already graded on them."""
|
||||
async with httpx.AsyncClient(timeout=10.0) as client:
|
||||
response = await client.get(f"{base}/http/middlewares", params={"per_page": 1000})
|
||||
response.raise_for_status()
|
||||
return error_page_services(response.json())
|
||||
|
||||
|
||||
def error_page_services(middlewares: list[dict]) -> frozenset[str]:
|
||||
"""fetch_error_page_services' reading of /api/http/middlewares: a service
|
||||
named without a provider belongs to its middleware's provider."""
|
||||
out = set()
|
||||
for m in middlewares:
|
||||
service = (m.get("errors") or {}).get("service")
|
||||
if not service:
|
||||
continue
|
||||
if "@" not in service:
|
||||
provider = m.get("provider") or (m.get("name", "").partition("@")[2])
|
||||
service = f"{service}@{provider}" if provider else service
|
||||
out.add(service)
|
||||
return frozenset(out)
|
||||
|
||||
|
||||
def cert_names(cn: str | None, sans: str | None) -> set[str]:
|
||||
"""Every name a certificate covers: its CN and SANs, lower-cased."""
|
||||
names = {n.strip().lower() for n in (sans or "").split(",") if n.strip()}
|
||||
|
||||
Reference in New Issue
Block a user