Files
computer-playbook/tests/integration/roles/dashboard/test_integration_scope.py
kevinveenbirkenbachandClaude Opus 4.7 d1410c0be3 refactor(web-opt-rdr-www): rename canonical to w3redirect + lookup-based redirect mappings
- web-opt-rdr-www canonical: rdr-www.{DOMAIN_PRIMARY} -> w3redirect.{DOMAIN_PRIMARY}.
- New lookup `www_redirect_domains` (role-scoped): returns full {source, target}
  mapping list, resolves DOMAIN_HOMEPAGE target for the role's own canonical via
  lookup('domain', 'web-opt-rdr-www'). REDIRECT_WWW_DOMAINS now carries dicts;
  tasks/main.yml and _01_cloudflare_edge_redirect.yml updated to consume dicts.
- New lookup `current_play_redirect_domains`: replaces the two inline
  set_fact merges in tasks/stages/01_constructor.yml. Merges user-supplied
  redirect_domain_mappings, primary-redirect (conditional on web-opt-rdr-domains
  in deployed), and per-app domain mappings (inlined from the now-removed
  domain_mappings filter).
- domain_redirect_mappings filter removed; web-app-keycloak RedirectUrisTest
  pollution of utils.roles.applications.config in sys.modules fixed via
  tearDownClass cleanup.
- csp_skip_domains lookup: csp.health.skip opt-out path removed (architecture
  no longer needs it).
- Lint test_only_web_app_roles_integrate_dashboard expanded from web-app-* to
  web-*; test_role_and_group_vars_used now scans .py files too so vars consumed
  only inside plugins (DOMAIN_HOMEPAGE, AUTO_BUILD_ALIASES) are seen.
- New role-scoped variants.yml on web-opt-rdr-www with dashboard on/off.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-26 04:02:55 +02:00

114 lines
4.2 KiB
Python

"""Guard: only ``web-*`` roles may integrate the dashboard.
A role "integrates" the dashboard when its ``meta/services.yml`` (or
any entry in ``meta/variants.yml``) declares a ``dashboard:`` block
whose ``enabled`` or ``shared`` flag is truthy according to the
canonical helper :func:`utils.roles.applications.services.registry.is_explicit_truth`.
Truthy means either the literal Python ``True`` *or* the dynamic Jinja
form ``"{{ '<role>' in group_names }}"``. Both produce a runtime tile
in the dashboard grid, so both are forbidden for non-``web-*`` roles.
Why
---
The dashboard is the user-facing tile grid. Only web-facing surfaces
belong in it. A system role (``sys-*``), desktop role (``desk-*``),
service role (``svc-*``), or driver role (``drv-*``) embedding the
dashboard would spam the tile grid with non-clickable infrastructure
entries.
A non-``web-*`` role MAY still ship a ``dashboard:`` block with
*explicitly disabled* flags (``enabled: false`` / ``shared: false``)
- that's a static "we know this service exists in the registry but
this role does not contribute a tile" declaration and is fine.
"""
from __future__ import annotations
import unittest
from typing import TYPE_CHECKING, Any
from utils.cache.yaml import load_yaml_any
from utils.roles.applications.services.registry import is_explicit_truth
from utils.roles.mapping import ROLE_FILE_META_SERVICES, ROLE_FILE_META_VARIANTS
from . import PROJECT_ROOT
if TYPE_CHECKING:
from pathlib import Path
ROLES_DIR = PROJECT_ROOT / "roles"
DASHBOARD_KEY = "dashboard"
def _load_yaml(path: Path) -> Any:
if not path.is_file():
return None
return load_yaml_any(str(path), default_if_missing=None)
def _dashboard_block_violates(block: Any) -> bool:
"""Return True iff the ``dashboard:`` mapping has a truthy
``enabled`` or ``shared`` flag."""
if not isinstance(block, dict):
return False
return is_explicit_truth(block.get("enabled")) or is_explicit_truth(
block.get("shared")
)
def _find_services_violation(role_dir: Path) -> str | None:
services_yaml = _load_yaml(role_dir / ROLE_FILE_META_SERVICES)
if not isinstance(services_yaml, dict):
return None
if _dashboard_block_violates(services_yaml.get(DASHBOARD_KEY)):
return f"{role_dir.name}: meta/services.yml declares `dashboard:` with a truthy enabled/shared flag"
return None
def _find_variants_violations(role_dir: Path) -> list[str]:
variants_yaml = _load_yaml(role_dir / ROLE_FILE_META_VARIANTS)
if not isinstance(variants_yaml, list):
return []
offenders: list[str] = []
for index, entry in enumerate(variants_yaml):
if not isinstance(entry, dict):
continue
services_override = entry.get("services")
if not isinstance(services_override, dict):
continue
if _dashboard_block_violates(services_override.get(DASHBOARD_KEY)):
offenders.append(
f"{role_dir.name}: meta/variants.yml[{index}].services.dashboard "
f"has a truthy enabled/shared flag"
)
return offenders
class TestDashboardIntegrationScope(unittest.TestCase):
def test_only_web_roles_integrate_dashboard(self) -> None:
offenders: list[str] = []
for role_dir in sorted(p for p in ROLES_DIR.iterdir() if p.is_dir()):
if role_dir.name.startswith("web-"):
continue
services_violation = _find_services_violation(role_dir)
if services_violation is not None:
offenders.append(services_violation)
offenders.extend(_find_variants_violations(role_dir))
if offenders:
self.fail(
"Non-web roles MUST NOT integrate the dashboard via a "
"truthy `enabled`/`shared` flag (literal `true` or the "
"`'<role>' in group_names` Jinja form). The dashboard tile "
"grid is reserved for web-facing surfaces. "
"Either drop the `dashboard:` block, or set both flags to "
"`false` if the registry declaration is intentional:\n"
+ "\n".join(f" - {o}" for o in offenders)
)
if __name__ == "__main__": # pragma: no cover
unittest.main()