Files
FabledSteward/tests/integration/test_alert_rule_form.py
T
bvandeusenandClaude Opus 5.5 d19df51ffb
CI / lint (push) Successful in 2s
CI / integration (push) Successful in 1m8s
CI / unit (push) Failing after 1m29s
CI / publish (push) Skipped
feat(alerts): pick the host, then its part, and see what the metric reads (#5475)
#5475 "Rule form: pick the host, then its part; metrics that part reports;
a link to groups; a preview of the metric", from the operator's review of
the New rule page: hosts and their parts shared one long picker.

- Host agent rules pick a Host, then a Part: "The whole host", then its
  mounts, CPU cores, disks, interfaces and sensors under a heading each,
  cores in number order. A part that reports nothing a rule can watch
  (an interface's traffic) isn't offered.
- The Metric list holds what the picked resource reports, in catalog order.
- Under it, a preview: the reading now, and the last 24 h low to high with
  an hourly sparkline drawn from zero (UI ruling 8), read from one series.
- The group picker links to Ansible > Inventory to make a group, in a new
  tab, and re-reads the groups when the tab comes back into view.
- Picking a host or part swaps the pickers alone (/alerts/api/rule_target);
  picking a metric swaps the preview (/alerts/api/metric_preview).
- A rule's own resource and metric stay on offer after they go quiet.

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

68 lines
2.9 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""Integration: the rule form's host and part pickers and the metric preview
(#5475), through their routes against Postgres. A host's parts come grouped
under it, and a picked metric shows what it reads now and over the last day."""
from __future__ import annotations
import asyncio
import os
import time
import uuid
from datetime import datetime, timedelta, timezone
import pytest
pytestmark = pytest.mark.integration
@pytest.fixture
def app():
if not os.environ.get("STEWARD_DATABASE_URL"):
pytest.skip("needs Postgres")
from steward.app import create_app
return create_app(testing=False)
def test_the_pickers_and_the_preview_read_what_the_host_reports(app):
from steward.core.alerts import record_metrics
from steward.models.metrics import PluginMetric
from steward.models.users import User, UserRole
async def _go():
tag = uuid.uuid4().hex[:8]
host = f"rf-{tag}"
now = datetime.now(timezone.utc)
async with app.db_sessionmaker() as s:
async with s.begin():
user = User(username=f"rf-{tag}", email=f"rf-{tag}@test", password_hash="x",
role=UserRole.operator, is_active=True)
s.add(user)
# Disk use climbing over the last few hours, then cpu and a mount.
await record_metrics(s, [
PluginMetric(source_module="host_agent", resource_name=f"{host}:/data",
metric_name="disk_used_pct", value=v, recorded_at=now - timedelta(hours=h))
for h, v in ((5, 61.0), (3, 70.0), (1, 82.0))])
await record_metrics(s, [
PluginMetric(source_module="host_agent", resource_name=host,
metric_name="cpu_pct", value=12.0, recorded_at=now)])
uid = user.id
client = app.test_client()
async with client.session_transaction() as sess:
sess.update(user_id=uid, user_role="operator", username=f"rf-{tag}",
_csrf="test-token", login_at=time.time())
resp = await client.get("/alerts/api/rule_target", query_string={
"source_module": "host_agent", "pick_host": host})
page = " ".join((await resp.get_data(as_text=True)).split())
assert resp.status_code == 200
assert f'<option value="{host}" selected>The whole host</option>' in page
assert f'<optgroup label="Mounts"> <option value="{host}:/data" >/data</option>' in page
resp = await client.get("/alerts/api/metric_preview", query_string={
"source_module": "host_agent", "pick_host": host, "resource_name": f"{host}:/data",
"metric_name": "disk_used_pct"})
page = " ".join((await resp.get_data(as_text=True)).split())
assert "Now <strong>82%</strong>" in page
assert "last 24 h</span> 61% – 82%" in page and "<polyline" in page
asyncio.run(_go())