from __future__ import annotations from quart import Blueprint, current_app, render_template from sqlalchemy import select, func from steward.auth.middleware import require_role from steward.models.users import UserRole from steward.models.hosts import Host from steward.models.monitors import DnsResult dns_bp = Blueprint("dns", __name__, url_prefix="/dns") async def _latest_dns(db, host_ids: list[str]) -> dict: if not host_ids: return {} subq = ( select(DnsResult.host_id, func.max(DnsResult.resolved_at).label("max_at")) .where(DnsResult.host_id.in_(host_ids)) .group_by(DnsResult.host_id) .subquery() ) pr = await db.execute( select(DnsResult).join( subq, (DnsResult.host_id == subq.c.host_id) & (DnsResult.resolved_at == subq.c.max_at), ) ) return {r.host_id: r for r in pr.scalars()} @dns_bp.get("/") @require_role(UserRole.viewer) async def index(): async with current_app.db_sessionmaker() as db: result = await db.execute( select(Host).where(Host.dns_enabled.is_(True)).order_by(Host.name) ) hosts = result.scalars().all() latest = await _latest_dns(db, [h.id for h in hosts]) poll_interval = current_app.config.get("MONITORS_POLL_INTERVAL", 60) return await render_template("dns/index.html", hosts=hosts, latest=latest, poll_interval=poll_interval) @dns_bp.get("/rows") @require_role(UserRole.viewer) async def rows(): async with current_app.db_sessionmaker() as db: result = await db.execute( select(Host).where(Host.dns_enabled.is_(True)).order_by(Host.name) ) hosts = result.scalars().all() latest = await _latest_dns(db, [h.id for h in hosts]) return await render_template("dns/rows.html", hosts=hosts, latest=latest)