Files
FabledSteward/tests/plugins/prometheus/test_archives_template.py
T
bvandeusenandClaude Opus 5.5 41d9d00216
CI / lint (push) Successful in 2s
CI / integration (push) Failing after 1m17s
CI / unit (push) Successful in 1m30s
CI / publish (push) Skipped
feat(prometheus): Fabled Archives template v2 against the live series; a state past its deadline is overdue (#5693)
Read from what Steward stored for Archives on 2026-10-14: the nightly
Restic replication job had said "running" since the first scrape two days
earlier, with no good copy yet and past both its late and missing times.
Archives ranks "running" above lateness, so the widget called it healthy.

- states blocks take warn_past / crit_past: a deadline metric per row (a
  *_timestamp_seconds). Once it has passed, a healthy row reads as a
  warning or a problem: "FullNightly-Restic is running, 11h 53m overdue".
  Quiet and already-failing rows keep their own reading.
- The Archives template (version 2) uses the job's late_at / missing_at
  deadlines and shows its last good copy beside the next run. It says why
  section_up, the queue and the HTTP/audit counters are left out.
- tests/plugins/prometheus/archives_live.py is the series as captured
  live, and test_archives_template.py renders the template over them.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 09:43:38 -04:00

48 lines
2.6 KiB
Python

"""The bundled Fabled Archives template (#5693) over the series Archives
actually reported (archives_live.py): what the widget said about it."""
from plugins.prometheus import library
from plugins.prometheus.template_view import render
from tests.plugins.prometheus.archives_live import AT, SERIES, TARGET, latest
ARCHIVES = library.bundled()[0].template
def _rows(view, title):
return {r.name: r for b in view.blocks if b.title == title for r in b.rows}
def test_a_replication_that_never_finishes_reads_as_overdue_not_running():
view = render(ARCHIVES, TARGET, latest(), AT)
assert view.tone == "crit" and view.note == ""
assert view.verdict == "2 need a look. Replication: FullNightly-Restic is running, 11h 53m overdue."
job = _rows(view, "Replication")["FullNightly-Restic"]
assert (job.tone, job.text) == ("crit", "running")
last_good, next_run = job.cells
assert last_good["text"] == "—" and next_run["moment"] is not None # no good copy yet
assert _rows(view, "Storage and integrity")["Malware held"].why == "above 0"
def test_everything_else_archives_reported_reads_as_well():
view = render(ARCHIVES, TARGET, latest(), AT)
assert all(not b.note for b in view.blocks), [b.note for b in view.blocks]
steward = _rows(view, "Backup targets")["Steward"]
assert (steward.tone, steward.text) == ("ok", "fresh") and steward.cells[0]["moment"] is not None
storage = _rows(view, "Storage and integrity")
assert storage["Disk free"].tone == "ok" and "of" in storage["Disk free"].text
assert (storage["Files checked"].text, storage["Files checked"].tone) == ("100,462 of 100,462", "ok")
assert storage["Notification channels failing"].tone == "ok"
assert list(_rows(view, "Stored per person")) == ["Bryan Van Deusen"]
assert list(_rows(view, "Running")) == ["version 2026.10.12.1717 · channel dev · commit 3605d0a"]
def test_a_finished_copy_clears_it():
"""The next night's run succeeds: Archives reports ok with a last good
copy and deadlines a day out, and the widget says so."""
later = AT.timestamp() + 86400
done = [(labels, metric, (float(labels.endswith("state=ok")) if metric.endswith("job_state") else value))
for labels, metric, value in SERIES]
done = [(lb, m, later + 30 * 3600 if m.endswith(("late_at_timestamp_seconds", "missing_at_timestamp_seconds"))
and lb.startswith("job=") else v) for lb, m, v in done]
job = _rows(render(ARCHIVES, TARGET, latest(done), AT), "Replication")["FullNightly-Restic"]
assert (job.tone, job.text, job.why) == ("ok", "ok", "")