cli.meta.roles.services.called package¶
Module contents¶
Verify that every role declaring required_by in its meta/services.yml actually ran in an Ansible run log.
A role’s meta/services.yml MAY contain (per-service-entity):
- <entity>:
- required_by:
categories: [web, web.app, …] # category handles (cf. meta/categories.yml) roles: [web-app-yourls, …] # full role names incl. category prefix
A required_by block MAY instead nest compose: / swarm: sub-blocks to scope the requirement to one deploy mode (a flat block applies in every mode); the deploy mode is inferred from the role set (swarm pulls in svc-swarm-node):
- <entity>:
- required_by:
compose: { categories: [web] } # required only in compose deploys
Semantics: when the current deploy contains any role whose id matches a listed roles entry, OR whose category set (top-level + first sub-level) intersects the listed categories, the role owning the services.yml entry MUST have executed (at least one of its TASK blocks must end with a non-skip status) in the run log slice that this verifier scans.
A missing event indicates a coverage regression in the deploy chain (typically: a once-flag swallowed an include before the role could run).
Two log-parsing trip-wires shape the regexes below. The non-skip status match is anchored to line start (after optional indent) so a substring in arbitrary task output cannot fake a status. And Ansible’s log_path file (ANSIBLE_LOG_PATH, what the swarm/compose deploy feeds this verifier) prefixes every line with <ts> p=<pid> u=<user> n=<name> <LVL>| `; left unstripped that prefix defeats both the line anchor and the `nTASK [ block split, so every required role would false-positive as “did not execute”.
CLI: python -m cli.meta.roles.services.called –help
- cli.meta.roles.services.called.categories_of(role_id: str) set[str]¶
Top-level + first-sub-level categories for the given role id.
Examples
web-app-yourls -> {“web”, “web-app”} svc-db-postgres -> {“svc”, “svc-db”} sys-ctl-hlth-csp -> {“sys”, “sys-ctl”}
- cli.meta.roles.services.called.container_log_size(*, container: str, log_path: str) int¶
Return the byte size of log_path inside container, or 0 if absent.
- cli.meta.roles.services.called.required_role_ids(*, roles_dir: Path, deployed_role_ids: list[str]) set[str]¶
Return role ids whose required_by matches the current deploy.
- cli.meta.roles.services.called.verify(*, roles_dir: Path, log_path: str, deployed_role_ids: list[str], container: str | None = None, log_byte_offset: int = 0) tuple[bool, list[str]]¶
Returns (ok, missing_role_ids).
When container is given, log_path is interpreted as a path INSIDE that container and read via docker exec tail. When container is None, log_path is read directly from the host filesystem.
Reads from log_byte_offset to end and asserts that every required role’s body actually executed in that slice (i.e. at least one TASK block for the role ended with a non-skip status).
An unreadable log proves coverage neither way and is reported as “missing” for every required role, so the operator notices.