Commit Graph
10 Commits
Author SHA1 Message Date
kevinveenbirkenbachandClaude Opus 5 a46348b6cf refactor(handlers): bind notify to a listen topic, not to a name
A handler name was doing two jobs at once: the line an operator reads in the
play output, and the identifier a `notify:` binds to. The two pull in opposite
directions -- the log wants "restart the SSH service, with diagnostics", the
binding wants a token that survives quoting, YAML flow style and a shell
round-trip -- and a name that changes for readability silently changes which
handler runs.

Every handler that a notify reached by name now carries a `listen:` with that
exact wording, so the binding is explicit before anything is renamed. The
topics themselves become identifiers: `compose up` reads `compose-up`,
`Restart NFS ganesha` reads `restart-nfs-ganesha`, 22 of them across both
sides of every notify. Where the topic is assembled at runtime, both branches
moved together: the conditional in sys-service carries two literals, and the
LDAP renderer interpolates `import-{{ folder }}-ldif-files`, which is what
makes those handlers reachable at all.

Freed from the binding, the names take the emoji prefix every other task line
already has.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-16 03:38:42 +02:00
kevinveenbirkenbachandClaude Opus 4.8 6fb4cf462c refactor(sys-svc-compose): delegate manager-only queries to the STACK_HOST SPOT
resolve_host_cid/wait_converged/guard_instance_dir took a run_host parameter every caller had to pass; STACK_HOST already encodes the correct host in both modes (first swarm manager, degrading to inventory_hostname in compose), so the manager-only queries now delegate to it directly and the parameter plus all caller declarations are gone. Also repairs the swarm guard include: apply/delegate_to are invalid on a HandlerTaskInclude and the previous commit carried duplicate run_once/delegate_to keys, which failed the ansible syntax-check. The keycloak handler drops its masking default; the 02b conditional collapses into the SPOT.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-03 22:18:20 +02:00
kevinveenbirkenbachandClaude Opus 4.7 74e3a64a4d refactor(web-app-keycloak): swarm-aware host discovery + realm-import dispatch
Restructures the keycloak role so manager-side operations run on the
hosting node under both deployment models without per-task delegation
noise:

- tasks/02_manager_ops.yml: extracts the manager-side body into
  02a_manager_ops_on_host.yml and includes it once with
  `apply: delegate_to: KEYCLOAK_HOST_NODE`. Ansible's `apply:` keyword
  propagates the delegate to every task in the included file so each
  step (kcadm login, client / mail / RBAC / LDAP updates) runs on the
  stack host without the inner files needing to know about it.
- tasks/04_login.yml: dual-path discovery. Swarm waits for the
  keycloak service to converge via `container service ps`, resolves
  the hosting node, and sets KEYCLOAK_HOST_NODE; compose sets it to
  inventory_hostname (single-host model). Subsequent LOCAL_CID
  resolution is now gated `when: DEPLOYMENT_MODE == 'swarm'` and
  scoped to a single block; compose leaves KEYCLOAK_LOCAL_CID unset
  and relies on vars/main.yml's
  `KEYCLOAK_EXEC_CONTAINER: container exec -i {{ KEYCLOAK_LOCAL_CID
  | default(KEYCLOAK_CONTAINER_ADDRESS) }}` fallback. Removes the
  brittle inline shell-template else-branch that previously echoed
  KEYCLOAK_CONTAINER for compose.
- tasks/05a_realm_import_run.yml: compose path runs the import
  in-place via `compose down/up/run`; swarm path dispatches to a new
  05b_realm_import_swarm.yml that scales the import service via
  `container service update`, tails its logs, and rescales to 0. The
  3 mode-gated tasks share a single `when:` wrapper to satisfy the
  ansible-repeated-when-run lint.
- tasks/update/05_ldap_shared.yml (new): extracted from the previous
  inline LDAP-shared block in the manager-ops handler so the
  surrounding block stays under the >3-children limit. Combined
  when-guard (KEYCLOAK_LDAP_ENABLED AND KEYCLOAK_LDAP_SHARED) lives
  on the include.
- tasks/assert/05_ldap.yml: read-only assertion path; uses
  KEYCLOAK_EXEC_KCADM (mode-agnostic).
- handlers/main.yml: drops the comment block that restated
  `ignore_errors: true` on the sync-ldap-groups handler. The
  ignore_errors + delegate_to + transient-failure semantics remain
  intact; the prose was restating the directive, not naming a
  trip-wire.

Verified internally coherent + compose-mode-safe via static audit:
include chain main -> 01_core -> 02_manager_ops -> 02a -> {04_login,
05_realm_import -> 05a (compose-branch) | 05b (swarm-branch),
update/{01_client, 02_mail_realm, 03_mail_master,
04_rbac_client_scope, 05_ldap_shared}, assert/05_ldap}. All
include_tasks targets resolve, all KEYCLOAK_* vars are set before
consumption, all kcadm/update/assert tasks are mode-agnostic.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-14 19:08:47 +02:00
kevinveenbirkenbachandClaude Opus 4.7 c52e4269bf chore(tooling): integrate mbake (Makefile linter/formatter) + working-tree drift sync
Makefile lint integration:
* scripts/install/lint.sh: replace the prior checkmake binary install with
  ensure_mbake (mbake is pip-installable, parses our Makefile correctly
  whereas checkmake bailed on .ONESHELL: / .SHELLFLAGS: / ifneq).
* scripts/lint/makefile.sh: new runner — `mbake format --check Makefile`
  reports formatting drift and missing .PHONY declarations.
* scripts/lint/autoformat.sh: add a two-pass `mbake format Makefile`
  (mbake's formatter is not strictly idempotent on the first pass).
* Makefile: split the multi-line `.PHONY:` block into 18 single-line
  `.PHONY:` declarations so mbake's parser can validate it; add the
  previously-missing `install-python-dev` and `build-dependency` PHONY
  targets; add `lint-makefile` aggregate-and-direct target.
* .pre-commit-config.yaml: new make-lint-makefile hook scoped to
  `^Makefile$`.
* .github/workflows/lint-makefile.yml: new CI workflow (pip-install mbake
  + make lint-makefile).
* .github/workflows/ci-orchestrator.yml: wire lint-makefile into
  lint-gate.needs.

Misc:
* .gitignore: add roles/importer_result.json (tooling artefact written by
  galaxy-importer when it runs in roles/).

Plus working-tree drift across roles/, group_vars/, inventories/, and
tasks/ that accumulated from the make-test setup phase regenerating
generated artefacts during recent test runs.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-09 00:32:44 +02:00
kevinveenbirkenbach a1b2fd54e5 fix: use resolved ldap component id 2026-03-28 01:37:46 +01:00
kevinveenbirkenbach 3889fd30dc Ignore errors in handler 2026-01-19 09:00:33 +01:00
kevinveenbirkenbach 385c563b4f fix(web-app-keycloak): make LDAP group sync handler idempotent by enforcing admin login
Ensure kcadm is always authenticated before triggering LDAP group sync.
Refactor login logic into reusable KEYCLOAK_COMMAND_PERMANENT_ADMIN_LOGIN
and reuse it in login tasks and sync handler.

https://chatgpt.com/share/696d76ba-50f0-800f-8ec3-2ca9e27adcc8
2026-01-19 01:11:32 +01:00
kevinveenbirkenbach 660596bb75 web-app-keycloak: fix ldap group sync handler by removing async
The ldap group sync handler relies on rc-based retries with `until`.
Using async/poll breaks this logic because async results do not expose `rc`
unless fully polled.

This change removes async execution to ensure reliable retry and error
handling during ldap group synchronization.

https://chatgpt.com/share/696d63e9-0e3c-800f-8107-adf747e4ffe5
2026-01-18 23:51:11 +01:00
kevinveenbirkenbach 29f5f4ab63 fix(keycloak): add retry logic to LDAP group sync handler
Retry LDAP roles mapper sync up to 6 times with 20s delay to
avoid race conditions during Keycloak/LDAP startup.

https://chatgpt.com/share/696d500b-18c8-800f-8b0f-c68420a8c418
2026-01-18 22:24:12 +01:00
kevinveenbirkenbach 48d5390264 keycloak: fix ldap group mapper parent and sync groups via handler
Ensure the ldap-roles group mapper always uses the correct parent group id
by injecting groups.path.group based on the actual Keycloak group.

Trigger LDAP → Keycloak group synchronization via a handler whenever the
mapper configuration changes, ensuring deterministic and reproducible
group imports under /roles.

https://chatgpt.com/share/696d02b4-1418-800f-8fe5-864f4e7494e8
2026-01-18 16:56:26 +01:00