Files
computer-playbook/utils/roles/entity/apps.py
T
kevinveenbirkenbachandClaude Opus 5 a05071fe78 refactor(roles): let a role declare its entity name and drop the get_ prefix
The entity name keys a role's instance directory, its compose project and its container name, and was derived only by stripping the longest matching category prefix. Two roles under different categories whose names share a suffix therefore collapse onto one entity and overwrite each other's rendered stack, which no provides: can repair.

A literal entity_name in vars/main.yml now wins over the derivation. web-app-seaweedfs-console takes its shorter name back and declares the entity seaweedfs-console, which frees the seaweedfs key in its own services map for the engine consumer and removes the provides:, covers: and alias entries that stood in for it. A new lint pairs the declaration with the primary key it has to match, because a drift between them would drop the role from the provider set in silence.

Compared across all 288 roles, exactly one entity changes, and it restores what main already keeps on disk, so no instance directory moves.

The function and the filter lose their get_ prefix. Two lints read that prefix as the discriminator between the variable and the filter that fills it; both discriminate on the pipe now. Ansible's templar resolves a filter and a same-named variable independently, verified against ansible-core 2.20.2.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-10-03 19:40:53 +02:00

60 lines
2.0 KiB
Python

"""Reverse entity -> application_id resolver.
`utils.roles.entity.name.entity_name` maps a role / application_id to
its compose entity name (the longest matching category prefix stripped).
The purge orchestrators need the inverse: given an entity name, which
application_ids belong to it? This helper walks the roles directory and
returns that mapping.
Used by `utils.cleanup.nginx_vhosts` so an entity-keyed purge can
enumerate the per-app domains whose nginx vhost files belong to the
stack being torn down.
"""
from __future__ import annotations
from typing import TYPE_CHECKING
from utils.cache.yaml import load_yaml_any
from utils.roles.entity.name import entity_name
from utils.roles.mapping import ROLE_FILE_VARS_MAIN
if TYPE_CHECKING:
from pathlib import Path
def _role_app_id(role_dir: Path) -> str:
"""Return the role's application_id (vars/main.yml.application_id),
falling back to the directory name when the field is missing or the
file does not exist. Mirrors `utils.roles.validation.invokable._role_to_app_id`.
"""
vars_file = role_dir / ROLE_FILE_VARS_MAIN
if not vars_file.is_file():
return role_dir.name
data = load_yaml_any(str(vars_file), default_if_missing={}) or {}
if not isinstance(data, dict):
return role_dir.name
app_id = data.get("application_id")
return str(app_id) if app_id else role_dir.name
def apps_for_entity(entity: str, *, roles_dir: Path) -> list[str]:
"""Return sorted, deduplicated application_ids whose role belongs to
*entity* under `entity_name`.
Returns an empty list when *entity* is blank, *roles_dir* is not a
directory, or no role matches.
"""
target = entity.strip()
if not target or not roles_dir.is_dir():
return []
out: set[str] = set()
for role_dir in sorted(p for p in roles_dir.iterdir() if p.is_dir()):
app_id = _role_app_id(role_dir)
if not app_id:
continue
if entity_name(app_id) == target:
out.add(app_id)
return sorted(out)