mirror of
https://github.com/kevinveenbirkenbach/computer-playbook.git
synced 2026-11-06 02:54:26 +00:00
Deletions only, no line added. The rationale each of these carried is already in
the commit message of the change that introduced it, which is where it belongs.
Three of the twenty Exception blocks this change set accumulated had already been
committed when the audit ran, so they were invisible to it: an audit that
enumerates git status stops seeing a file the moment it is committed. Two further
details are worth recording because they are what let these survive.
The purge pattern (^|\{)#\s*Exception: does not match an indented comment, so a
block nested inside YAML never matched while the report claimed none remained.
Anchoring it as ^\s*(#|//|--|\{#)\s*Exception: raised the count from 12 to 17.
One of the three was written as a paragraph inside a Python docstring rather than
as a comment. Docstrings are an allowed kind, so no comment grep matches them and
the repository's own comment lint passes over them; using the allowed kind to
carry the banned label is the same rule-gaming in a syntax the checks do not
cover.
Verified the deletion removed nothing else: the diff contains zero insertions,
every touched YAML file still parses, and the unit suite and comment lint are
green.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
142 lines
5.3 KiB
Python
142 lines
5.3 KiB
Python
from __future__ import annotations
|
|
|
|
import re
|
|
from typing import Any
|
|
|
|
from ansible.errors import AnsibleError
|
|
from ansible.plugins.loader import lookup_loader
|
|
from ansible.plugins.lookup import LookupBase
|
|
|
|
from utils.cache.base import _render_with_templar
|
|
from utils.roles.applications.config import get
|
|
from utils.roles.applications.services.registry import (
|
|
build_service_registry_from_applications,
|
|
)
|
|
|
|
ENV_SUFFIX = "_ADDON_ENABLED"
|
|
_TRUE_TOKENS = {"true", "1", "yes", "on", "t", "y"}
|
|
|
|
|
|
def env_key(addon_id: str) -> str:
|
|
"""Mirror addon-gating.js envKey(): upper-case, non-alphanumeric runs -> '_'."""
|
|
return re.sub(r"[^A-Z0-9]+", "_", str(addon_id).upper()) + ENV_SUFFIX
|
|
|
|
|
|
def _is_enabled(value: Any) -> bool:
|
|
if isinstance(value, bool):
|
|
return value
|
|
return str(value).strip().lower() in _TRUE_TOKENS
|
|
|
|
|
|
def _resolve_deployed_roles(variables, templar, applications):
|
|
"""Resolve the round's deployed role closure to a set.
|
|
Returns None when it cannot be resolved, in which case bridge-deployment
|
|
gating is skipped (no behaviour change).
|
|
"""
|
|
raw = (variables or {}).get("group_names")
|
|
if raw is None:
|
|
return None
|
|
resolved = raw
|
|
if isinstance(raw, str):
|
|
try:
|
|
resolved = _render_with_templar(
|
|
raw, templar=templar, variables=variables, raw_applications=applications
|
|
)
|
|
except Exception:
|
|
return None
|
|
if isinstance(resolved, str):
|
|
resolved = [r for r in re.split(r"[\s,]+", resolved.strip()) if r]
|
|
if not isinstance(resolved, (list, tuple, set)):
|
|
return None
|
|
return {str(r).strip() for r in resolved if str(r).strip()} or None
|
|
|
|
|
|
def _any_bridge_partner_deployed(bridges, deployed_roles, service_registry):
|
|
"""A bridged addon's partner counts as deployed when a deployed role either
|
|
provides the bridged service (``sso`` -> ``web-app-keycloak``, ``ldap`` ->
|
|
``svc-db-openldap``) or carries the bridge name as its entity
|
|
(``matrix`` -> ``web-app-matrix``)."""
|
|
for bridge in bridges:
|
|
name = str(bridge).strip()
|
|
if not name:
|
|
continue
|
|
entry = service_registry.get(name) if service_registry else None
|
|
provider = entry.get("role") if isinstance(entry, dict) else None
|
|
if provider and provider in deployed_roles:
|
|
return True
|
|
variants = {name, name.replace("_", "-")}
|
|
for role in deployed_roles:
|
|
if role in variants or any(role.endswith("-" + v) for v in variants):
|
|
return True
|
|
return False
|
|
|
|
|
|
class LookupModule(LookupBase):
|
|
"""
|
|
lookup('addon_env_flags', application_id)
|
|
|
|
Single source of truth for the per-addon enable flags consumed by the
|
|
Playwright addon-gating helper (``tests/addon-gating.js`` ->
|
|
``skipUnlessAddonEnabled``). Replaces the error-prone per-template Jinja
|
|
loop: it resolves the materialised ``addons`` mapping for ``application_id``
|
|
and returns one ``<ADDON_ID>_ADDON_ENABLED=<true|false>`` line per declared
|
|
addon (sorted by env key, newline-joined), where the env-key derivation
|
|
matches addon-gating.js exactly.
|
|
|
|
A flag is ``true`` only when the addon is both ``enabled`` AND
|
|
``required``. Optional addons (``required: false``) are intentionally
|
|
skipped by the spec suite — they are a variant axis, not a guaranteed
|
|
surface — so their gate flag is ``false`` even when enabled.
|
|
"""
|
|
|
|
def run(self, terms, variables: dict[str, Any] | None = None, **kwargs):
|
|
if not terms or len(terms) != 1:
|
|
raise AnsibleError(
|
|
"lookup('addon_env_flags', application_id) expects exactly one term."
|
|
)
|
|
|
|
application_id = terms[0]
|
|
templar = getattr(self, "_templar", None)
|
|
variables = variables or getattr(self._templar, "available_variables", {}) or {}
|
|
|
|
applications = lookup_loader.get(
|
|
"applications", loader=self._loader, templar=templar
|
|
).run([], variables=variables)[0]
|
|
addons = get(
|
|
applications=applications,
|
|
application_id=application_id,
|
|
config_path="addons",
|
|
strict=False,
|
|
default={},
|
|
skip_missing_app=True,
|
|
)
|
|
addons = _render_with_templar(
|
|
addons,
|
|
templar=templar,
|
|
variables=variables,
|
|
raw_applications=applications,
|
|
)
|
|
if not isinstance(addons, dict):
|
|
addons = {}
|
|
|
|
deployed_roles = _resolve_deployed_roles(variables, templar, applications)
|
|
service_registry = build_service_registry_from_applications(applications)
|
|
|
|
lines = []
|
|
for addon_id in sorted(addons, key=env_key):
|
|
spec = (
|
|
addons.get(addon_id) if isinstance(addons.get(addon_id), dict) else {}
|
|
)
|
|
active = _is_enabled(spec.get("enabled", False)) and _is_enabled(
|
|
spec.get("required", False)
|
|
)
|
|
if active and deployed_roles is not None:
|
|
bridges = spec.get("bridges")
|
|
if isinstance(bridges, list) and bridges:
|
|
active = _any_bridge_partner_deployed(
|
|
bridges, deployed_roles, service_registry
|
|
)
|
|
lines.append(f"{env_key(addon_id)}={'true' if active else 'false'}")
|
|
|
|
return ["\n".join(lines)]
|