Files
computer-playbook/utils/distros.py
T
kevinveenbirkenbachandClaude Opus 5 e409674718 refactor(meta): centralize category/distro SPOTs
categories.yml moves from roles/ to the repository-root meta/, joining packages.yml. utils/roles/categories.py owns its location plus the tree-walking helpers that were stranded in entity/name.py, so no caller spells the path or duplicates the lookup.

meta/distros.yml becomes the SPOT for every distribution: os_family, Galaxy platform name, dev-environment base image, and the pkgmgr/pkgmgr-virgin/environment reference templates. It replaces seven scattered copies (DISTRO_FAMILY, VALID_DISTROS, _DISTROS, _CANONICAL_PLATFORMS, two shell arrays, a Makefile literal). INFINITO_DISTROS is no longer a static default but generated by utils/env/handlers/infinito/distros.py; the shell consumers read it through the env layer.

Drops dead CLI surface found along the way: --categories-file and --roles-dir on the provision CLI plus three unused parameters of generate_dynamic_inventory, and the positional roles_file of the invokable categories command.

tests/lint/repository/test_distros_spot.py pins the copies that cannot call the SPOT (workflow literals, docs table) and forbids composing a pkgmgr reference outside it.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-28 11:19:30 +02:00

118 lines
4.0 KiB
Python

"""Distribution SPOT.
``meta/distros.yml`` declares every distribution the project builds, tests
and deploys on: the id used as ``INFINITO_DISTRO``, the ``os_family``
ansible reports for it, the Galaxy platform name, the upstream base image
the development-environment matrix boots it from, and the templates the
pkgmgr base image and the environment image references are rendered from.
Consumers MUST read the distro set through this module. A local tuple of
distro names or an f-string spelling out ``ghcr.io/.../pkgmgr-...`` is a
second source of truth and drifts; ``tests/lint/repository/test_distros_spot.py``
guards against reintroducing one.
Registry owner, repository and tag are *not* declared here — they stay in
``default.env``, which is their SPOT. This module only renders them into
the templates.
Keep this module free of Ansible imports and cheap to import: it is pulled
in by the env layer and by ``utils.packages.schema``, which reach contexts
where Ansible is not installed.
"""
from __future__ import annotations
from utils.cache import PROJECT_ROOT
from utils.cache.yaml import load_yaml
FILE_META_DISTROS: str = "meta/distros.yml"
IMAGE_PKGMGR = "pkgmgr"
IMAGE_PKGMGR_VIRGIN = "pkgmgr_virgin"
IMAGE_ENVIRONMENT = "environment"
class UnknownDistroError(ValueError):
"""Raised for a distro id that ``meta/distros.yml`` does not declare."""
def _doc() -> dict:
return load_yaml(str(PROJECT_ROOT / FILE_META_DISTROS))
def _specs() -> dict[str, dict]:
return _doc()["distros"]
def _spec(distro: str) -> dict:
try:
return _specs()[distro]
except KeyError:
raise UnknownDistroError(
f"{distro!r} is not declared in {FILE_META_DISTROS}. "
f"Declared: {', '.join(distro_names())}."
) from None
def distro_names() -> tuple[str, ...]:
"""Every declared distro id, in declaration order."""
return tuple(_specs())
def distro_family() -> dict[str, str]:
"""Map each distro id onto the ``os_family`` ansible reports for it."""
return {name: spec["family"] for name, spec in _specs().items()}
def galaxy_platforms() -> list[dict[str, object]]:
"""Canonical ``galaxy_info.platforms`` block for every role's meta/main.yml.
Sorted by platform name, which is the order the role files carry and
which the schema lint compares against verbatim.
"""
versions = list(_doc()["galaxy_platform_versions"])
return [
{"name": name, "versions": list(versions)}
for name in sorted(spec["galaxy_platform"] for spec in _specs().values())
]
def dev_runtime_images() -> tuple[str, ...]:
"""Upstream base images of the development-environment test matrix."""
return tuple(spec["dev_runtime_image"] for spec in _specs().values())
def dev_runtime_image(distro: str) -> str:
"""Upstream base image the development environment boots a distro from."""
return _spec(distro)["dev_runtime_image"]
def image_template(kind: str) -> str:
"""Raw reference template, for callers rendering a non-distro slug.
The shell-side installer scripts loop over distros with their own
variable, so they render ``{slug}`` themselves rather than per distro.
"""
return _doc()["images"][kind]
def _render(kind: str, distro: str, **fields: str) -> str:
return image_template(kind).format(slug=_spec(distro)["slug"], **fields)
def pkgmgr_image(distro: str, owner: str, tag: str) -> str:
"""Reference of the pkgmgr base image a distro's container builds FROM."""
return _render(IMAGE_PKGMGR, distro, owner=owner, tag=tag)
def pkgmgr_virgin_image(distro: str, owner: str, tag: str) -> str:
"""Reference of the untouched pkgmgr image the install tests boot."""
return _render(IMAGE_PKGMGR_VIRGIN, distro, owner=owner, tag=tag)
def environment_image(distro: str, owner: str, repository: str, tag: str) -> str:
"""Reference of the environment image built for a distro."""
return _render(
IMAGE_ENVIRONMENT, distro, owner=owner, repository=repository, tag=tag
)