Files
computer-playbook/plugins/lookup/package_batch.py
T
kevinveenbirkenbachandClaude Opus 5.5 18ea75049e perf(packages): install every role's packages per host in one run at deploy start
A constructor task after the update role and the swarm auto-placement installs,
in one package-manager call, every package id of every role the host's groups
may run: meta dependencies, service edges and every role invocation readable
from tasks and handlers, conditions ignored. Ids that must stay with their role
(a conditional install, a repository added first, a need before update) carry
batch: false in meta/packages.yml and keep their task; roles reference shared
root ids with shared: true. 42 per-role install tasks go, and a lint keeps the
split: no batched id in a role task, none in a role run ahead of the batch.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-28 22:54:36 +01:00

59 lines
2.1 KiB
Python

"""Lookup ``package_batch``: the package ids a host installs in one run at
deploy start.
{{ lookup('package_batch', group_names) }}
The terms are every group of the host, after the swarm auto-placement, so a
role the service loader reaches on this host through any whitelist is covered. They are widened to
every role the deploy may run on the host
(:func:`utils.roles.invocations.deploy_closure`), and the sorted ids the
batch installs for those roles (:func:`utils.packages.batch.batch_ids`) are
returned.
"""
from __future__ import annotations
from typing import Any
from ansible.errors import AnsibleError
from ansible.plugins.loader import lookup_loader
from ansible.plugins.lookup import LookupBase
from utils import PROJECT_ROOT
from utils.packages.batch import batch_ids
from utils.packages.schema import PackagesShapeError
from utils.roles.invocations import deploy_closure
from utils.roles.validation.invokable import types_from_group_names
class LookupModule(LookupBase):
def run(
self,
terms: list[Any] | None,
variables: dict[str, Any] | None = None,
**kwargs: Any,
) -> list[list[str]]:
seeds: list[str] = []
for term in terms or []:
if isinstance(term, (list, tuple, set)):
seeds.extend(str(entry) for entry in term)
elif term:
seeds.append(str(term))
vars_ = variables or getattr(self._templar, "available_variables", {}) or {}
group_names = [str(group) for group in vars_["group_names"]]
applications = lookup_loader.get(
"applications", loader=self._loader, templar=getattr(self, "_templar", None)
).run([], variables=vars_)[0]
try:
roles = deploy_closure(
applications,
seeds,
project_root=PROJECT_ROOT,
host_types=types_from_group_names(group_names),
group_names=group_names,
)
return [batch_ids(roles, PROJECT_ROOT)]
except (PackagesShapeError, TypeError, ValueError) as exc:
raise AnsibleError(f"package_batch: {exc}") from exc