Files
computer-playbook/utils/roles
kevinveenbirkenbachandClaude Opus 4.7 99e5bef885 fix(inventory): treat multi-DB roles as non-single-consumer
`_apply_one_role_special_rules()` in utils/manager/inventory.py used
`bool(resolve_database_service_key(...))` to decide whether to
auto-generate a `database_password` credential for a role. The
resolver raises when multiple RDBMS keys are enabled — which is the
correct contract for compose_volumes / container_depends_on /
plugins.lookup.database (they need an unambiguous single key) but the
wrong contract for inventory's credential-generation pass: variant 1
of svc-bkp-container-2-local intentionally enables both mariadb and
postgres to exercise the engine-side dump path against both engines
at once, and the deploy aborted with `ValueError: multiple direct
database services are enabled: mariadb, postgres` during inventory
generation (job 77602095377 on run 26362676803).

Add a non-raising sibling helper `has_single_database_service()` that
returns True iff exactly one RDBMS service is enabled, and switch
inventory's call site to it. Multi-DB roles now skip the auto-
generated `database_password` (which was a phantom credential for
svc-bkp anyway — no schema.yml, no cross-role lookup; the role's own
`04_seed-database-to-backup.yml` receives `database_password` as a
caller-passed task var, not as a self-credential lookup).

`resolve_database_service_key` keeps its strict raise semantics for
the compose_volumes / container_depends_on / database-lookup callers,
which still need a single unambiguous key.

Add unit coverage for both functions (3 + 4 tests) in
tests/unit/utils/roles/applications/services/test_database.py.

Static check only (per operator request).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-25 15:55:46 +02:00
..
…
…

Role Utilities 🧩

Helpers under utils/roles/ operate on Ansible role artefacts and the dictionaries that mirror them at runtime.

Scope 📋

Modules in utils/roles/ MUST stay focused on data that originates from roles/<role>/ (meta/services.yml, meta/main.yml, vars/, defaults/) or the runtime dictionary that mirrors those files (applications).

Modules in utils/roles/ MUST NOT depend on Ansible plugin loader internals at import time so the same code can be imported from filter plugins, lookup plugins, library modules, the CLI, and tests.

Subpackages 📦

  • applications/ helpers around the central applications dict and the role config that feeds it.