fix(prometheus, syslog): a target or pattern pauses with a Pause/Resume button, not an "on" tick box in its form (#6419)
CI / lint (push) Successful in 2s
CI / unit (push) Failing after 1m42s
CI / integration (push) Successful in 1m45s
CI / publish (push) Skipped

Monitors, schedules and maintenance plans already pause with a
Pause/Resume button and say "Paused" where they're listed. Prometheus
targets and syslog patterns only had a tick box inside the edit form,
so a target refused by its endpoint couldn't be stopped from its page.

- Both get a Pause/Resume button (target page and list; patterns list)
  posting to /toggle, recorded in the audit log, and a Paused badge.
- The forms lose the tick box. A new one starts running; an edit keeps
  whether it is paused.
- A target's "off" state is now "paused", in its pages and MCP tools.
  A resumed target reads "not scraped yet" until its next scrape, and its
  counter rates start over.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-25 17:48:31 -04:00
co-authored by Claude Opus 5.5
parent 0b787a0676
commit d20d78498e
15 changed files with 104 additions and 51 deletions
+5 -5
View File
@@ -128,13 +128,13 @@ class _Form(dict):
def test_the_form_checks_what_it_stores_and_keeps_a_blank_token():
values = parse_form(_Form(name="Archives", url="http://archives:8081/metrics", token="s3cret",
interval_seconds="30", series_cap="500", keep="fabledarchives_*",
enabled="on", verify_tls="on"))
verify_tls="on"))
assert values["token"].startswith("enc:") or values["token"] == "s3cret"
assert (values["interval_seconds"], values["series_cap"], values["keep"], values["enabled"]) == (
30, 500, ["fabledarchives_*"], True)
assert (values["interval_seconds"], values["series_cap"], values["keep"]) == (30, 500, ["fabledarchives_*"])
assert "enabled" not in values # Pause/Resume sets it, not the form (#6419)
existing = PrometheusTarget(name="Archives", url="http://a/metrics", token="enc:v1:kept")
again = parse_form(_Form(name="Archives", url="http://a/metrics"), existing)
assert again["token"] == "enc:v1:kept" and again["enabled"] is False
assert again["token"] == "enc:v1:kept" and "enabled" not in again
cleared = parse_form(_Form(name="Archives", url="http://a/metrics", clear_token="on"), existing)
assert cleared["token"] == ""
for bad in (dict(name="", url="http://a"), dict(name="a:b", url="http://a"),
@@ -158,7 +158,7 @@ def test_state_and_due():
t.last_scraped_at = now - timedelta(minutes=10)
assert target_state(t, now).reach == "stale"
t.enabled = False
assert target_state(t, now).reach == "off" and not is_due(t, now)
assert target_state(t, now).reach == "paused" and not is_due(t, now)
@pytest.mark.asyncio