"""The Syslog page (#5999): whether the listener is open or why not, the sources kept, and the senders offered to an admin to add or ignore.""" from datetime import datetime, timedelta, timezone from types import SimpleNamespace as NS from tests._templates import render_plugin_template from tests.test_style_tokens import hex_colours def _listener(**over): base = {"port": 5514, "protocols": ["UDP", "TCP"], "listening": True, "error": None, "bound_at": datetime.now(timezone.utc) - timedelta(hours=2), "received": 1204, "dropped": 0, "unoffered": 0, "connections": 1, "senders_full": False, "max_senders": 200} return {**base, **over} def _source(name, state, level=6, line="nfsd: server not responding", host=None): now = datetime.now(timezone.utc) return {"id": f"id-{name}", "address": "192.168.0.7", "state": state, "name": name, "hostname_seen": "synnas", "host": host, "first_seen_at": now - timedelta(days=1), "last_seen_at": now - timedelta(minutes=3), "lines_total": 1204, "severity": "err" if level == 3 else "info", "level": level, "last_line": line, "suggested_host": "h1", "rate": 12 if state == "accepted" else None} async def _render(app, role, **ctx): from quart import session ctx = {"listener": _listener(), "sources": [], "offered": [], "ignored": [], "hosts": [NS(id="h1", name="SynNAS", address="192.168.0.7")], "now": datetime.now(timezone.utc), **ctx} async with app.test_request_context("/plugins/syslog/"): session["user_role"] = role page = await render_plugin_template(app, "syslog", "syslog/index.html", **ctx) return " ".join(page.split()) async def test_an_offered_sender_can_be_added_or_ignored_by_an_admin(app): page = await _render(app, "admin", offered=[_source("synnas", "offered", level=3)]) assert "Sending, not added" in page and "calls itself synnas" in page assert 'action="/plugins/syslog/sources/id-synnas/add"' in page assert 'action="/plugins/syslog/sources/id-synnas/ignore"' in page assert '' in page # the host at its address assert 'class="tone-crit">err nfsd: server not responding' in page assert "UDP and TCP port 5514" in page and "1,204 lines received" in page main = page[page.index("Syslog' in page assert 'action="/plugins/syslog/sources/s1/delete"' in page and "data-confirm=" in page def _line(i, level=6, app="kernel", message="nfsd: server not responding", minutes=1): now = datetime.now(timezone.utc) return {"id": f"l{i}", "received_at": now - timedelta(minutes=minutes), "sent_at": None, "level": level, "severity": {3: "err", 4: "warning"}.get(level, "info"), "facility": "kern", "hostname": "synnas", "app": app, "message": message, "group": "Today", "opens_group": i == 0} async def test_a_source_page_filters_its_lines_and_scrolls_on(app): from quart import session from plugins.syslog.service import SEVERITY_CHOICES, LineFilter src = {**_source("SynNAS", "accepted"), "rate": 42} async with app.test_request_context("/plugins/syslog/sources/id-SynNAS"): session["user_role"] = "viewer" page = await render_plugin_template( app, "syslog", "syslog/source.html", source=src, f=LineFilter(severity=3), filtered=True, lines=[_line(0, level=3), _line(1, app="", message="a tag")], more_url="/plugins/syslog/sources/id-SynNAS?severity=3&before=x", severities=SEVERITY_CHOICES, apps=["kernel", "nfsd"], ranges=["1h", "24h"]) page = " ".join(page.split()) assert 'href="/plugins/syslog/">Syslog' in page # its trail assert "42 lines in the last hour" in page assert '' in page assert 'Today' in page assert 'err' in page and "a <b> tag" in page assert 'hx-get="/plugins/syslog/sources/id-SynNAS?severity=3&before=x"' in page assert "/edit" not in page # a viewer main = page[page.index("Source" not in one and 'warning' in one assert "Source" in two and 'href="/plugins/syslog/sources/s2">router' in two assert "No lines in the last day." in none