From af60ca446dcd1f31956b56b401b591c3a4955726 Mon Sep 17 00:00:00 2001 From: Bryan Van Deusen Date: Mon, 1 Jun 2026 11:22:20 -0400 Subject: [PATCH] fix(plugins): complete steward rename across bundled plugins; clear lint debt MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The fabledscryer->steward rename had only ever reached host_agent. The other five bundled plugins (http, snmp, traefik, unifi, docker) still imported `from fabledscryer.*` (package no longer exists) and read FABLEDSCRYER_* env vars — so every one of them was broken at import since the original rebrand. CI stayed green only because none are enabled by default and migrations don't import plugin modules. Now that they version in-tree, complete the rename: - fabledscryer.* -> steward.* imports across all five plugins - FABLEDSCRYER_* -> STEWARD_* in plugin migration env.py files - author/repository/homepage + user-facing 'Fabled Scryer' strings -> Steward - snmp/scheduler.py: also drop dead `now`/datetime; record_metric from steward Adds tests/test_no_legacy_names.py — fails if 'scryer'/'roundtable' ever reappear in shipped code (the drift bit twice; this stops a third time). Also clears pre-existing ruff lint debt (unused imports, semicolon statements, mid-file import) surfaced by the new lint lane. Co-Authored-By: Claude Opus 4.8 (1M context) --- plugins/docker/migrations/env.py | 8 ++-- plugins/docker/models.py | 2 +- plugins/docker/plugin.yaml | 6 +-- plugins/docker/routes.py | 7 ++- plugins/docker/scheduler.py | 4 +- plugins/docker/scraper.py | 1 - plugins/docker/templates/docker/index.html | 2 +- plugins/http/checker.py | 1 - plugins/http/migrations/env.py | 8 ++-- plugins/http/models.py | 2 +- plugins/http/plugin.yaml | 6 +-- plugins/http/routes.py | 7 ++- plugins/http/scheduler.py | 6 +-- plugins/http/templates/http/index.html | 2 +- plugins/index.yaml | 44 +++++++++---------- plugins/snmp/plugin.yaml | 6 +-- plugins/snmp/poller.py | 4 +- plugins/snmp/routes.py | 6 +-- plugins/snmp/scheduler.py | 6 +-- plugins/snmp/templates/snmp/device.html | 2 +- plugins/snmp/templates/snmp/index.html | 2 +- plugins/traefik/migrations/env.py | 10 ++--- plugins/traefik/models.py | 2 +- plugins/traefik/plugin.yaml | 6 +-- plugins/traefik/routes.py | 6 +-- plugins/traefik/scheduler.py | 5 +-- plugins/traefik/templates/traefik/index.html | 2 +- plugins/unifi/migrations/env.py | 8 ++-- plugins/unifi/models.py | 2 +- plugins/unifi/plugin.yaml | 6 +-- plugins/unifi/routes.py | 7 ++- plugins/unifi/scheduler.py | 4 +- plugins/unifi/templates/unifi/index.html | 2 +- steward/ansible/routes.py | 7 ++- steward/auth/oidc.py | 1 - steward/core/plugin_manager.py | 1 - steward/core/reports.py | 2 - steward/migrations/env.py | 3 +- steward/settings/routes.py | 3 +- steward/templates/settings/auth.html | 4 +- steward/templates/settings/plugins.html | 2 +- tests/conftest.py | 1 - .../host_agent/test_agent_build_payload.py | 5 +-- .../host_agent/test_agent_ring_buffer.py | 7 ++- .../host_agent/test_install_template.py | 1 - tests/test_config.py | 1 - tests/test_models.py | 1 - tests/test_no_legacy_names.py | 35 +++++++++++++++ 48 files changed, 142 insertions(+), 124 deletions(-) create mode 100644 tests/test_no_legacy_names.py diff --git a/plugins/docker/migrations/env.py b/plugins/docker/migrations/env.py index 5c20755..3878d67 100644 --- a/plugins/docker/migrations/env.py +++ b/plugins/docker/migrations/env.py @@ -13,8 +13,8 @@ from alembic import context sys.path.insert(0, str(Path(__file__).parent.parent.parent.parent)) -from fabledscryer.models.base import Base -import fabledscryer.models # noqa: F401 +from steward.models.base import Base +import steward.models # noqa: F401 from plugins.docker.models import DockerContainer, DockerMetric # noqa: F401 config = context.config @@ -26,14 +26,14 @@ target_metadata = Base.metadata def _get_url() -> str: import yaml - cfg_path = os.environ.get("FABLEDSCRYER_CONFIG", "config.yaml") + cfg_path = os.environ.get("STEWARD_CONFIG", "config.yaml") try: with open(cfg_path) as f: cfg = yaml.safe_load(f) or {} url = cfg.get("database", {}).get("url", "") except FileNotFoundError: url = "" - return os.environ.get("FABLEDSCRYER_DATABASE__URL", url) + return os.environ.get("STEWARD_DATABASE__URL", url) def run_migrations_offline() -> None: diff --git a/plugins/docker/models.py b/plugins/docker/models.py index 09c1cf3..bec356b 100644 --- a/plugins/docker/models.py +++ b/plugins/docker/models.py @@ -4,7 +4,7 @@ import uuid from datetime import datetime, timezone from sqlalchemy import DateTime, Float, Integer, String, Text from sqlalchemy.orm import Mapped, mapped_column -from fabledscryer.models.base import Base +from steward.models.base import Base class DockerContainer(Base): diff --git a/plugins/docker/plugin.yaml b/plugins/docker/plugin.yaml index 8745302..9d38f24 100644 --- a/plugins/docker/plugin.yaml +++ b/plugins/docker/plugin.yaml @@ -1,11 +1,11 @@ name: docker version: "1.0.0" description: "Docker container status, resource usage, restart tracking via Docker socket" -author: "FabledScryer" +author: "Steward" license: "MIT" min_app_version: "0.1.0" -repository_url: "https://git.fabledsword.com/bvandeusen/FabledScryer-plugins" -homepage: "https://git.fabledsword.com/bvandeusen/FabledScryer-plugins/src/branch/main/docker" +repository_url: "https://git.fabledsword.com/bvandeusen/Steward-plugins" +homepage: "https://git.fabledsword.com/bvandeusen/Steward-plugins/src/branch/main/docker" tags: - containers - docker diff --git a/plugins/docker/routes.py b/plugins/docker/routes.py index 12d0383..41b123a 100644 --- a/plugins/docker/routes.py +++ b/plugins/docker/routes.py @@ -1,13 +1,12 @@ # plugins/docker/routes.py from __future__ import annotations import json -from datetime import datetime, timezone from quart import Blueprint, current_app, render_template, request from sqlalchemy import Integer, cast, func, select -from fabledscryer.auth.middleware import require_role -from fabledscryer.models.users import UserRole -from fabledscryer.core.time_range import parse_range, DEFAULT_RANGE, bucket_seconds +from steward.auth.middleware import require_role +from steward.models.users import UserRole +from steward.core.time_range import parse_range, DEFAULT_RANGE, bucket_seconds from .models import DockerContainer, DockerMetric docker_bp = Blueprint("docker", __name__, template_folder="templates") diff --git a/plugins/docker/scheduler.py b/plugins/docker/scheduler.py index eef8c61..827cf5f 100644 --- a/plugins/docker/scheduler.py +++ b/plugins/docker/scheduler.py @@ -4,8 +4,8 @@ import json import logging from datetime import datetime, timezone -from fabledscryer.core.scheduler import ScheduledTask -from fabledscryer.core.alerts import record_metric +from steward.core.scheduler import ScheduledTask +from steward.core.alerts import record_metric logger = logging.getLogger(__name__) diff --git a/plugins/docker/scraper.py b/plugins/docker/scraper.py index 96f601b..f4133ed 100644 --- a/plugins/docker/scraper.py +++ b/plugins/docker/scraper.py @@ -106,7 +106,6 @@ async def scrape_docker(socket_path: str, include_stopped: bool) -> list[dict]: ) from exc results = [] - now = datetime.now(timezone.utc) for container, stats in pairs: names = container.get("Names") or [] name = names[0].lstrip("/") if names else _short_id(container.get("Id", "")) diff --git a/plugins/docker/templates/docker/index.html b/plugins/docker/templates/docker/index.html index 42c9bb5..9b33918 100644 --- a/plugins/docker/templates/docker/index.html +++ b/plugins/docker/templates/docker/index.html @@ -1,5 +1,5 @@ {% extends "base.html" %} -{% block title %}Docker — Fabled Scryer{% endblock %} +{% block title %}Docker — Steward{% endblock %} {% block content %}

Docker

diff --git a/plugins/http/checker.py b/plugins/http/checker.py index 7eec743..c898ad6 100644 --- a/plugins/http/checker.py +++ b/plugins/http/checker.py @@ -2,7 +2,6 @@ """Core HTTP check logic — runs a single monitor check and returns a result dict.""" from __future__ import annotations import asyncio -import json import logging import ssl import time diff --git a/plugins/http/migrations/env.py b/plugins/http/migrations/env.py index fd308a2..02082a7 100644 --- a/plugins/http/migrations/env.py +++ b/plugins/http/migrations/env.py @@ -13,8 +13,8 @@ from alembic import context sys.path.insert(0, str(Path(__file__).parent.parent.parent.parent)) -from fabledscryer.models.base import Base -import fabledscryer.models # noqa: F401 +from steward.models.base import Base +import steward.models # noqa: F401 from plugins.http.models import HttpMonitor, HttpResult # noqa: F401 config = context.config @@ -26,14 +26,14 @@ target_metadata = Base.metadata def _get_url() -> str: import yaml - cfg_path = os.environ.get("FABLEDSCRYER_CONFIG", "config.yaml") + cfg_path = os.environ.get("STEWARD_CONFIG", "config.yaml") try: with open(cfg_path) as f: cfg = yaml.safe_load(f) or {} url = cfg.get("database", {}).get("url", "") except FileNotFoundError: url = "" - return os.environ.get("FABLEDSCRYER_DATABASE__URL", url) + return os.environ.get("STEWARD_DATABASE__URL", url) def run_migrations_offline() -> None: diff --git a/plugins/http/models.py b/plugins/http/models.py index 180effd..d11cb0c 100644 --- a/plugins/http/models.py +++ b/plugins/http/models.py @@ -4,7 +4,7 @@ import uuid from datetime import datetime, timezone from sqlalchemy import Boolean, DateTime, Float, Integer, String, Text from sqlalchemy.orm import Mapped, mapped_column -from fabledscryer.models.base import Base +from steward.models.base import Base class HttpMonitor(Base): diff --git a/plugins/http/plugin.yaml b/plugins/http/plugin.yaml index 9aa1475..a232c4d 100644 --- a/plugins/http/plugin.yaml +++ b/plugins/http/plugin.yaml @@ -1,11 +1,11 @@ name: http version: "1.0.0" description: "Synthetic HTTP endpoint monitoring — status code, response time, content match, TLS expiry" -author: "FabledScryer" +author: "Steward" license: "MIT" min_app_version: "0.1.0" -repository_url: "https://git.fabledsword.com/bvandeusen/FabledScryer-plugins" -homepage: "https://git.fabledsword.com/bvandeusen/FabledScryer-plugins/src/branch/main/http" +repository_url: "https://git.fabledsword.com/bvandeusen/Steward-plugins" +homepage: "https://git.fabledsword.com/bvandeusen/Steward-plugins/src/branch/main/http" tags: - monitoring - http diff --git a/plugins/http/routes.py b/plugins/http/routes.py index eea5ce7..24bede7 100644 --- a/plugins/http/routes.py +++ b/plugins/http/routes.py @@ -1,14 +1,13 @@ # plugins/http/routes.py from __future__ import annotations -import json import uuid from datetime import datetime, timezone from quart import Blueprint, current_app, render_template, request, redirect, url_for from sqlalchemy import Integer, cast, func, select -from fabledscryer.auth.middleware import require_role -from fabledscryer.models.users import UserRole -from fabledscryer.core.time_range import parse_range, DEFAULT_RANGE, bucket_seconds +from steward.auth.middleware import require_role +from steward.models.users import UserRole +from steward.core.time_range import parse_range, DEFAULT_RANGE, bucket_seconds from .models import HttpMonitor, HttpResult http_bp = Blueprint("http", __name__, template_folder="templates") diff --git a/plugins/http/scheduler.py b/plugins/http/scheduler.py index f9edd67..424836c 100644 --- a/plugins/http/scheduler.py +++ b/plugins/http/scheduler.py @@ -3,10 +3,10 @@ from __future__ import annotations import asyncio import json import logging -from datetime import datetime, timezone, timedelta +from datetime import datetime, timezone -from fabledscryer.core.scheduler import ScheduledTask -from fabledscryer.core.alerts import record_metric +from steward.core.scheduler import ScheduledTask +from steward.core.alerts import record_metric logger = logging.getLogger(__name__) diff --git a/plugins/http/templates/http/index.html b/plugins/http/templates/http/index.html index 6d1ffd0..a2c7771 100644 --- a/plugins/http/templates/http/index.html +++ b/plugins/http/templates/http/index.html @@ -1,5 +1,5 @@ {% extends "base.html" %} -{% block title %}HTTP Monitors — Fabled Scryer{% endblock %} +{% block title %}HTTP Monitors — Steward{% endblock %} {% block content %}

HTTP Monitors

diff --git a/plugins/index.yaml b/plugins/index.yaml index 0192afe..276306d 100644 --- a/plugins/index.yaml +++ b/plugins/index.yaml @@ -1,6 +1,6 @@ -# fabledscryer-plugins / index.yaml +# steward-plugins / index.yaml # -# Plugin catalog for Fabled Scryer. +# Plugin catalog for Steward. # Fetched by the app at: Settings → Plugins → Plugin Catalog # # After updating an entry, commit and push — changes are live within 5 minutes @@ -16,12 +16,12 @@ plugins: - name: http version: "1.0.0" description: "Synthetic HTTP endpoint monitoring — status code, response time, content match, TLS expiry" - author: "FabledScryer" + author: "Steward" license: "MIT" min_app_version: "0.1.0" - repository_url: "https://git.fabledsword.com/bvandeusen/FabledScryer-plugins" - homepage: "https://git.fabledsword.com/bvandeusen/FabledScryer-plugins/src/branch/main/http" - download_url: "https://git.fabledsword.com/bvandeusen/FabledScryer-plugins/releases/download/http-v1.0.0/http.zip" + repository_url: "https://git.fabledsword.com/bvandeusen/Steward-plugins" + homepage: "https://git.fabledsword.com/bvandeusen/Steward-plugins/src/branch/main/http" + download_url: "https://git.fabledsword.com/bvandeusen/Steward-plugins/releases/download/http-v1.0.0/http.zip" checksum_sha256: "" tags: - monitoring @@ -32,12 +32,12 @@ plugins: - name: docker version: "1.0.0" description: "Docker container status, resource usage, and restart tracking via Docker socket" - author: "FabledScryer" + author: "Steward" license: "MIT" min_app_version: "0.1.0" - repository_url: "https://git.fabledsword.com/bvandeusen/FabledScryer-plugins" - homepage: "https://git.fabledsword.com/bvandeusen/FabledScryer-plugins/src/branch/main/docker" - download_url: "https://git.fabledsword.com/bvandeusen/FabledScryer-plugins/releases/download/docker-v1.0.0/docker.zip" + repository_url: "https://git.fabledsword.com/bvandeusen/Steward-plugins" + homepage: "https://git.fabledsword.com/bvandeusen/Steward-plugins/src/branch/main/docker" + download_url: "https://git.fabledsword.com/bvandeusen/Steward-plugins/releases/download/docker-v1.0.0/docker.zip" checksum_sha256: "" tags: - containers @@ -47,12 +47,12 @@ plugins: - name: traefik version: "1.0.0" description: "Traefik reverse proxy metrics and access log integration" - author: "FabledScryer" + author: "Steward" license: "MIT" min_app_version: "0.1.0" - repository_url: "https://git.fabledsword.com/bvandeusen/FabledScryer-plugins" - homepage: "https://git.fabledsword.com/bvandeusen/FabledScryer-plugins/src/branch/main/traefik" - download_url: "https://git.fabledsword.com/bvandeusen/FabledScryer-plugins/releases/download/traefik-v1.0.0/traefik.zip" + repository_url: "https://git.fabledsword.com/bvandeusen/Steward-plugins" + homepage: "https://git.fabledsword.com/bvandeusen/Steward-plugins/src/branch/main/traefik" + download_url: "https://git.fabledsword.com/bvandeusen/Steward-plugins/releases/download/traefik-v1.0.0/traefik.zip" checksum_sha256: "" tags: - proxy @@ -62,12 +62,12 @@ plugins: - name: unifi version: "1.0.0" description: "UniFi Network controller integration — WAN health, devices, clients, DPI" - author: "FabledScryer" + author: "Steward" license: "MIT" min_app_version: "0.1.0" - repository_url: "https://git.fabledsword.com/bvandeusen/FabledScryer-plugins" - homepage: "https://git.fabledsword.com/bvandeusen/FabledScryer-plugins/src/branch/main/unifi" - download_url: "https://git.fabledsword.com/bvandeusen/FabledScryer-plugins/releases/download/unifi-v1.0.0/unifi.zip" + repository_url: "https://git.fabledsword.com/bvandeusen/Steward-plugins" + homepage: "https://git.fabledsword.com/bvandeusen/Steward-plugins/src/branch/main/unifi" + download_url: "https://git.fabledsword.com/bvandeusen/Steward-plugins/releases/download/unifi-v1.0.0/unifi.zip" checksum_sha256: "" tags: - network @@ -77,12 +77,12 @@ plugins: - name: ups version: "1.0.0" description: "UPS monitoring via NUT (Network UPS Tools) with Ansible shutdown automation" - author: "FabledScryer" + author: "Steward" license: "MIT" min_app_version: "0.1.0" - repository_url: "https://git.fabledsword.com/bvandeusen/FabledScryer-plugins" - homepage: "https://git.fabledsword.com/bvandeusen/FabledScryer-plugins/src/branch/main/ups" - download_url: "https://git.fabledsword.com/bvandeusen/FabledScryer-plugins/releases/download/ups-v1.0.0/ups.zip" + repository_url: "https://git.fabledsword.com/bvandeusen/Steward-plugins" + homepage: "https://git.fabledsword.com/bvandeusen/Steward-plugins/src/branch/main/ups" + download_url: "https://git.fabledsword.com/bvandeusen/Steward-plugins/releases/download/ups-v1.0.0/ups.zip" checksum_sha256: "" tags: - ups diff --git a/plugins/snmp/plugin.yaml b/plugins/snmp/plugin.yaml index 5e98fce..ba8d8a6 100644 --- a/plugins/snmp/plugin.yaml +++ b/plugins/snmp/plugin.yaml @@ -2,11 +2,11 @@ name: snmp version: "1.0.0" description: "SNMP polling for network devices — switches, routers, printers, UPSes, etc." -author: "FabledScryer" +author: "Steward" license: "MIT" min_app_version: "0.1.0" -repository_url: "https://git.fabledsword.com/bvandeusen/FabledScryer-plugins" -homepage: "https://git.fabledsword.com/bvandeusen/FabledScryer-plugins/src/branch/main/snmp" +repository_url: "https://git.fabledsword.com/bvandeusen/Steward-plugins" +homepage: "https://git.fabledsword.com/bvandeusen/Steward-plugins/src/branch/main/snmp" tags: - snmp - network diff --git a/plugins/snmp/poller.py b/plugins/snmp/poller.py index 2f7e86f..6a837f6 100644 --- a/plugins/snmp/poller.py +++ b/plugins/snmp/poller.py @@ -3,7 +3,7 @@ Synchronous SNMP GET helper, run via executor. Requires pysnmp-lextudio (maintained pysnmp fork): - pip install 'fabledscryer[snmp]' + pip install 'steward[snmp]' If pysnmp is not installed, poll_device() returns an empty dict and logs a warning. """ @@ -40,7 +40,7 @@ def poll_device_sync( """ if not _pysnmp_available(): logger.warning("pysnmp not installed — SNMP polling disabled. " - "Install with: pip install 'fabledscryer[snmp]'") + "Install with: pip install 'steward[snmp]'") return {} from pysnmp.hlapi import ( diff --git a/plugins/snmp/routes.py b/plugins/snmp/routes.py index cca9697..94bffbc 100644 --- a/plugins/snmp/routes.py +++ b/plugins/snmp/routes.py @@ -5,9 +5,9 @@ from datetime import datetime, timedelta, timezone from quart import Blueprint, current_app, render_template, request from sqlalchemy import func, select -from fabledscryer.auth.middleware import require_role -from fabledscryer.models.users import UserRole -from fabledscryer.models.metrics import PluginMetric +from steward.auth.middleware import require_role +from steward.models.users import UserRole +from steward.models.metrics import PluginMetric snmp_bp = Blueprint("snmp", __name__, template_folder="templates") diff --git a/plugins/snmp/scheduler.py b/plugins/snmp/scheduler.py index b8809c3..d1a1d85 100644 --- a/plugins/snmp/scheduler.py +++ b/plugins/snmp/scheduler.py @@ -7,7 +7,7 @@ from typing import TYPE_CHECKING if TYPE_CHECKING: from quart import Quart -from fabledscryer.core.scheduler import ScheduledTask +from steward.core.scheduler import ScheduledTask logger = logging.getLogger(__name__) @@ -27,16 +27,14 @@ def make_poll_task(app: "Quart") -> ScheduledTask: async def _do_poll(app: "Quart") -> None: - from datetime import datetime, timezone from .poller import poll_device_sync - from fabledscryer.core.alerts import record_metric + from steward.core.alerts import record_metric devices: list[dict] = app.config["PLUGINS"]["snmp"].get("devices", []) if not devices: return loop = asyncio.get_event_loop() - now = datetime.now(timezone.utc) async with app.db_sessionmaker() as session: async with session.begin(): diff --git a/plugins/snmp/templates/snmp/device.html b/plugins/snmp/templates/snmp/device.html index 82022a9..b8fe625 100644 --- a/plugins/snmp/templates/snmp/device.html +++ b/plugins/snmp/templates/snmp/device.html @@ -1,6 +1,6 @@ {# plugins/snmp/templates/snmp/device.html #} {% extends "base.html" %} -{% block title %}SNMP — {{ device_name }} — Fabled Scryer{% endblock %} +{% block title %}SNMP — {{ device_name }} — Steward{% endblock %} {% block content %}
← SNMP diff --git a/plugins/snmp/templates/snmp/index.html b/plugins/snmp/templates/snmp/index.html index 86a1485..ef5979c 100644 --- a/plugins/snmp/templates/snmp/index.html +++ b/plugins/snmp/templates/snmp/index.html @@ -1,6 +1,6 @@ {# plugins/snmp/templates/snmp/index.html #} {% extends "base.html" %} -{% block title %}SNMP — Fabled Scryer{% endblock %} +{% block title %}SNMP — Steward{% endblock %} {% block content %}

SNMP Devices

diff --git a/plugins/traefik/migrations/env.py b/plugins/traefik/migrations/env.py index 1919fec..a523e27 100644 --- a/plugins/traefik/migrations/env.py +++ b/plugins/traefik/migrations/env.py @@ -15,11 +15,11 @@ from sqlalchemy.engine import Connection from sqlalchemy.ext.asyncio import async_engine_from_config from alembic import context -# Make fabledscryer importable +# Make steward importable sys.path.insert(0, str(Path(__file__).parent.parent.parent.parent)) -from fabledscryer.models.base import Base -import fabledscryer.models # noqa: F401 — core models +from steward.models.base import Base +import steward.models # noqa: F401 — core models from plugins.traefik.models import TraefikMetric # noqa: F401 — plugin model config = context.config @@ -31,14 +31,14 @@ target_metadata = Base.metadata def _get_url() -> str: import yaml - cfg_path = os.environ.get("FABLEDSCRYER_CONFIG", "config.yaml") + cfg_path = os.environ.get("STEWARD_CONFIG", "config.yaml") try: with open(cfg_path) as f: cfg = yaml.safe_load(f) or {} url = cfg.get("database", {}).get("url", "") except FileNotFoundError: url = "" - return os.environ.get("FABLEDSCRYER_DATABASE__URL", url) + return os.environ.get("STEWARD_DATABASE__URL", url) def run_migrations_offline() -> None: diff --git a/plugins/traefik/models.py b/plugins/traefik/models.py index 1ba9e50..d177d10 100644 --- a/plugins/traefik/models.py +++ b/plugins/traefik/models.py @@ -4,7 +4,7 @@ import uuid from datetime import datetime, timezone from sqlalchemy import DateTime, Float, Integer, String, Text from sqlalchemy.orm import Mapped, mapped_column -from fabledscryer.models.base import Base +from steward.models.base import Base class TraefikMetric(Base): diff --git a/plugins/traefik/plugin.yaml b/plugins/traefik/plugin.yaml index 392713b..3f09ff4 100644 --- a/plugins/traefik/plugin.yaml +++ b/plugins/traefik/plugin.yaml @@ -2,11 +2,11 @@ name: traefik version: "1.0.0" description: "Traefik reverse proxy metrics and access log integration" -author: "FabledScryer" +author: "Steward" license: "MIT" min_app_version: "0.1.0" -repository_url: "https://git.fabledsword.com/bvandeusen/FabledScryer-plugins" -homepage: "https://git.fabledsword.com/bvandeusen/FabledScryer-plugins/src/branch/main/traefik" +repository_url: "https://git.fabledsword.com/bvandeusen/Steward-plugins" +homepage: "https://git.fabledsword.com/bvandeusen/Steward-plugins/src/branch/main/traefik" tags: - proxy - metrics diff --git a/plugins/traefik/routes.py b/plugins/traefik/routes.py index f7fe3ce..80e6c93 100644 --- a/plugins/traefik/routes.py +++ b/plugins/traefik/routes.py @@ -6,9 +6,9 @@ from quart import Blueprint, current_app, render_template, request from sqlalchemy import Integer, cast, func, select import json -from fabledscryer.auth.middleware import require_role -from fabledscryer.models.users import UserRole -from fabledscryer.core.time_range import parse_range, DEFAULT_RANGE, bucket_seconds, subsample +from steward.auth.middleware import require_role +from steward.models.users import UserRole +from steward.core.time_range import parse_range, DEFAULT_RANGE, bucket_seconds, subsample from .models import TraefikAccessSummary, TraefikCert, TraefikGlobalStat, TraefikMetric traefik_bp = Blueprint("traefik", __name__, template_folder="templates") diff --git a/plugins/traefik/scheduler.py b/plugins/traefik/scheduler.py index b7eb050..678e788 100644 --- a/plugins/traefik/scheduler.py +++ b/plugins/traefik/scheduler.py @@ -5,7 +5,7 @@ import time from typing import TYPE_CHECKING from datetime import datetime -from fabledscryer.core.scheduler import ScheduledTask +from steward.core.scheduler import ScheduledTask if TYPE_CHECKING: from quart import Quart @@ -41,7 +41,6 @@ async def _do_scrape(app: "Quart") -> None: global _prev_metrics, _prev_time from datetime import datetime, timezone - from sqlalchemy import select from .models import TraefikCert, TraefikGlobalStat, TraefikMetric from .scraper import ( compute_global_stats, @@ -49,7 +48,7 @@ async def _do_scrape(app: "Quart") -> None: extract_certs, fetch_metrics, ) - from fabledscryer.core.alerts import record_metric + from steward.core.alerts import record_metric metrics_url: str = app.config["PLUGINS"]["traefik"]["metrics_url"] diff --git a/plugins/traefik/templates/traefik/index.html b/plugins/traefik/templates/traefik/index.html index da66fc7..18f50f0 100644 --- a/plugins/traefik/templates/traefik/index.html +++ b/plugins/traefik/templates/traefik/index.html @@ -1,6 +1,6 @@ {# plugins/traefik/templates/traefik/index.html #} {% extends "base.html" %} -{% block title %}Traefik — Fabled Scryer{% endblock %} +{% block title %}Traefik — Steward{% endblock %} {% block content %}
diff --git a/plugins/unifi/migrations/env.py b/plugins/unifi/migrations/env.py index 56f15d5..7fa8252 100644 --- a/plugins/unifi/migrations/env.py +++ b/plugins/unifi/migrations/env.py @@ -15,8 +15,8 @@ from alembic import context sys.path.insert(0, str(Path(__file__).parent.parent.parent.parent)) -from fabledscryer.models.base import Base -import fabledscryer.models # noqa: F401 +from steward.models.base import Base +import steward.models # noqa: F401 from plugins.unifi.models import UnifiWanStat, UnifiClientSnapshot, UnifiDevice # noqa: F401 config = context.config @@ -28,14 +28,14 @@ target_metadata = Base.metadata def _get_url() -> str: import yaml - cfg_path = os.environ.get("FABLEDSCRYER_CONFIG", "config.yaml") + cfg_path = os.environ.get("STEWARD_CONFIG", "config.yaml") try: with open(cfg_path) as f: cfg = yaml.safe_load(f) or {} url = cfg.get("database", {}).get("url", "") except FileNotFoundError: url = "" - return os.environ.get("FABLEDSCRYER_DATABASE__URL", url) + return os.environ.get("STEWARD_DATABASE__URL", url) def run_migrations_offline() -> None: diff --git a/plugins/unifi/models.py b/plugins/unifi/models.py index 2ad90e9..bb36410 100644 --- a/plugins/unifi/models.py +++ b/plugins/unifi/models.py @@ -4,7 +4,7 @@ import uuid from datetime import datetime, timezone from sqlalchemy import Boolean, DateTime, Float, Integer, String, Text from sqlalchemy.orm import Mapped, mapped_column -from fabledscryer.models.base import Base +from steward.models.base import Base # ── Time-series (one row per scrape) ────────────────────────────────────────── diff --git a/plugins/unifi/plugin.yaml b/plugins/unifi/plugin.yaml index 208ace5..76b64ed 100644 --- a/plugins/unifi/plugin.yaml +++ b/plugins/unifi/plugin.yaml @@ -1,11 +1,11 @@ name: unifi version: "1.0.0" description: "UniFi Network controller integration — WAN health, devices, clients, DPI" -author: "FabledScryer" +author: "Steward" license: "MIT" min_app_version: "0.1.0" -repository_url: "https://git.fabledsword.com/bvandeusen/FabledScryer-plugins" -homepage: "https://git.fabledsword.com/bvandeusen/FabledScryer-plugins/src/branch/main/unifi" +repository_url: "https://git.fabledsword.com/bvandeusen/Steward-plugins" +homepage: "https://git.fabledsword.com/bvandeusen/Steward-plugins/src/branch/main/unifi" tags: - network - unifi diff --git a/plugins/unifi/routes.py b/plugins/unifi/routes.py index 2a57330..e5e00a6 100644 --- a/plugins/unifi/routes.py +++ b/plugins/unifi/routes.py @@ -1,13 +1,12 @@ # plugins/unifi/routes.py from __future__ import annotations import json -from datetime import datetime, timezone from quart import Blueprint, current_app, render_template, request from sqlalchemy import Integer, cast, func, select -from fabledscryer.auth.middleware import require_role -from fabledscryer.models.users import UserRole -from fabledscryer.core.time_range import parse_range, DEFAULT_RANGE, bucket_seconds, subsample +from steward.auth.middleware import require_role +from steward.models.users import UserRole +from steward.core.time_range import parse_range, DEFAULT_RANGE, bucket_seconds from .models import ( UnifiAlarm, UnifiClientSnapshot, UnifiDevice, UnifiDpiSnapshot, UnifiEvent, UnifiFwRule, UnifiKnownClient, UnifiNetwork, diff --git a/plugins/unifi/scheduler.py b/plugins/unifi/scheduler.py index 2a6345d..e050c40 100644 --- a/plugins/unifi/scheduler.py +++ b/plugins/unifi/scheduler.py @@ -5,7 +5,7 @@ import logging from datetime import datetime, timezone from typing import TYPE_CHECKING -from fabledscryer.core.scheduler import ScheduledTask +from steward.core.scheduler import ScheduledTask if TYPE_CHECKING: from quart import Quart @@ -35,7 +35,7 @@ async def _do_poll(app: "Quart") -> None: from .client import UnifiClient from .models import UnifiClientSnapshot, UnifiDevice, UnifiWanStat - from fabledscryer.core.alerts import record_metric + from steward.core.alerts import record_metric cfg = app.config["PLUGINS"]["unifi"] diff --git a/plugins/unifi/templates/unifi/index.html b/plugins/unifi/templates/unifi/index.html index b2113b6..517c030 100644 --- a/plugins/unifi/templates/unifi/index.html +++ b/plugins/unifi/templates/unifi/index.html @@ -1,6 +1,6 @@ {# plugins/unifi/templates/unifi/index.html #} {% extends "base.html" %} -{% block title %}UniFi — Fabled Scryer{% endblock %} +{% block title %}UniFi — Steward{% endblock %} {% block content %}
diff --git a/steward/ansible/routes.py b/steward/ansible/routes.py index d01f860..1dceb26 100644 --- a/steward/ansible/routes.py +++ b/steward/ansible/routes.py @@ -3,13 +3,12 @@ from __future__ import annotations import asyncio import uuid from datetime import datetime, timezone -from pathlib import Path from quart import ( - Blueprint, Response, current_app, redirect, render_template, - request, session, url_for, + Blueprint, Response, current_app, render_template, + request, session, ) -from sqlalchemy import select, update +from sqlalchemy import select from steward.ansible import executor, sources as src_module from steward.auth.middleware import require_role diff --git a/steward/auth/oidc.py b/steward/auth/oidc.py index 934e3a8..9f8697e 100644 --- a/steward/auth/oidc.py +++ b/steward/auth/oidc.py @@ -8,7 +8,6 @@ we trust the HTTPS connection to the discovery-documented token/userinfo endpoin """ from __future__ import annotations import base64 -import hashlib import json import logging import os diff --git a/steward/core/plugin_manager.py b/steward/core/plugin_manager.py index b0c6e6d..680235c 100644 --- a/steward/core/plugin_manager.py +++ b/steward/core/plugin_manager.py @@ -1,7 +1,6 @@ # steward/core/plugin_manager.py from __future__ import annotations import hashlib -import importlib import logging import os import sys diff --git a/steward/core/reports.py b/steward/core/reports.py index 39f0d7a..7c376d0 100644 --- a/steward/core/reports.py +++ b/steward/core/reports.py @@ -6,8 +6,6 @@ Called by the scheduler (hourly check) or triggered manually from Settings. from __future__ import annotations import asyncio import logging -import smtplib -import ssl from datetime import datetime, timedelta, timezone from email.message import EmailMessage diff --git a/steward/migrations/env.py b/steward/migrations/env.py index 3da677f..0c35e5e 100644 --- a/steward/migrations/env.py +++ b/steward/migrations/env.py @@ -15,7 +15,8 @@ target_metadata = Base.metadata def get_url() -> str: - import os, yaml + import os + import yaml def _env(suffix: str) -> str | None: return os.environ.get(f"STEWARD_{suffix}") diff --git a/steward/settings/routes.py b/steward/settings/routes.py index 8434b70..f2740a4 100644 --- a/steward/settings/routes.py +++ b/steward/settings/routes.py @@ -1,6 +1,5 @@ # steward/settings/routes.py from __future__ import annotations -import json import logging from pathlib import Path from quart import Blueprint, current_app, render_template, request, redirect, url_for, session @@ -9,7 +8,7 @@ from steward.auth.middleware import require_role from steward.core.audit import log_audit from steward.models.users import UserRole from steward.core.settings import ( - DEFAULTS, get_all_settings, set_setting, + get_all_settings, set_setting, to_smtp_cfg, to_webhook_cfg, to_ansible_cfg, to_plugins_cfg, to_oidc_cfg, to_ldap_cfg, ) diff --git a/steward/templates/settings/auth.html b/steward/templates/settings/auth.html index 655fd08..41b69c4 100644 --- a/steward/templates/settings/auth.html +++ b/steward/templates/settings/auth.html @@ -144,12 +144,12 @@
+ placeholder="cn=steward-admins,ou=groups,dc=example,dc=com">
+ placeholder="cn=steward-operators,ou=groups,dc=example,dc=com">
diff --git a/steward/templates/settings/plugins.html b/steward/templates/settings/plugins.html index 31d1a7c..2b2a5c6 100644 --- a/steward/templates/settings/plugins.html +++ b/steward/templates/settings/plugins.html @@ -81,7 +81,7 @@
Plugin Repositories

- Repositories are remote index.yaml files that Scryer checks for available + Repositories are remote index.yaml files that Steward checks for available and updated plugins. Add repos from other developers to expand the plugin catalog.

{% include "settings/_plugin_repos.html" %} diff --git a/tests/conftest.py b/tests/conftest.py index 1031522..8b4edc0 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,6 +1,5 @@ import pytest import pytest_asyncio -from pathlib import Path import textwrap from steward.app import create_app diff --git a/tests/plugins/host_agent/test_agent_build_payload.py b/tests/plugins/host_agent/test_agent_build_payload.py index f38f567..2d7f26a 100644 --- a/tests/plugins/host_agent/test_agent_build_payload.py +++ b/tests/plugins/host_agent/test_agent_build_payload.py @@ -1,3 +1,4 @@ +import urllib.error from unittest.mock import patch from plugins.host_agent import agent as a @@ -55,10 +56,6 @@ def test_build_payload_wraps_samples(): assert payload["samples"][0]["cpu_pct"] == 5.0 -import urllib.error -from unittest.mock import MagicMock, patch - - def test_post_payload_success(): from plugins.host_agent import agent as a captured = {} diff --git a/tests/plugins/host_agent/test_agent_ring_buffer.py b/tests/plugins/host_agent/test_agent_ring_buffer.py index f0d7a46..2482e6d 100644 --- a/tests/plugins/host_agent/test_agent_ring_buffer.py +++ b/tests/plugins/host_agent/test_agent_ring_buffer.py @@ -3,7 +3,9 @@ from plugins.host_agent.agent import RingBuffer def test_ring_buffer_preserves_order(): rb = RingBuffer(maxlen=3) - rb.push(1); rb.push(2); rb.push(3) + rb.push(1) + rb.push(2) + rb.push(3) assert list(rb.drain()) == [1, 2, 3] assert len(rb) == 0 @@ -17,7 +19,8 @@ def test_ring_buffer_drops_oldest_when_full(): def test_ring_buffer_drain_clears_and_is_atomic(): rb = RingBuffer(maxlen=5) - rb.push("a"); rb.push("b") + rb.push("a") + rb.push("b") out = list(rb.drain()) rb.push("c") assert out == ["a", "b"] diff --git a/tests/plugins/host_agent/test_install_template.py b/tests/plugins/host_agent/test_install_template.py index dc3f928..efaed79 100644 --- a/tests/plugins/host_agent/test_install_template.py +++ b/tests/plugins/host_agent/test_install_template.py @@ -2,7 +2,6 @@ import subprocess from pathlib import Path -import pytest from jinja2 import Environment, FileSystemLoader from plugins.host_agent.routes import _agent_version, AGENT_SOURCE_PATH diff --git a/tests/test_config.py b/tests/test_config.py index d4151bd..40e9203 100644 --- a/tests/test_config.py +++ b/tests/test_config.py @@ -1,4 +1,3 @@ -import os import textwrap import pytest from steward.config import load_bootstrap diff --git a/tests/test_models.py b/tests/test_models.py index 2bce1c7..50a074b 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -1,4 +1,3 @@ -import pytest from steward.models.users import User, UserRole diff --git a/tests/test_no_legacy_names.py b/tests/test_no_legacy_names.py new file mode 100644 index 0000000..0e75198 --- /dev/null +++ b/tests/test_no_legacy_names.py @@ -0,0 +1,35 @@ +"""Regression guard: shipped code must not reference old project names. + +The FabledScryer -> Roundtable -> Steward renames repeatedly left stale package +imports behind in the (then separate) plugins (e.g. `from fabledscryer.models...`), +silently breaking every non-host_agent plugin. Now that plugins are folded in-tree +and version with core, this test fails loudly if either legacy name reappears in +the shipped Python / templates / plugin manifests. +""" +from __future__ import annotations + +from pathlib import Path + +import pytest + +_ROOT = Path(__file__).resolve().parent.parent +_TREES = [_ROOT / "steward", _ROOT / "plugins"] +_EXTENSIONS = {".py", ".yaml", ".yml", ".html", ".j2"} +_FORBIDDEN = ("scryer", "roundtable") # case-insensitive; old project names + + +def _shipped_files(): + for tree in _TREES: + for path in tree.rglob("*"): + if path.suffix in _EXTENSIONS and "__pycache__" not in path.parts: + yield path + + +@pytest.mark.parametrize("name", _FORBIDDEN) +def test_no_legacy_project_name(name): + offenders = [ + str(p.relative_to(_ROOT)) + for p in _shipped_files() + if name in p.read_text(encoding="utf-8", errors="ignore").lower() + ] + assert not offenders, f"legacy name {name!r} found in shipped code: {offenders}"