Files
kevinveenbirkenbachandClaude Fable 5 92c73b5257 fix(web-app-keycloak): harden update recovery
Reset the cross-node recovery budget after a successful update pass so
later updates.yml invocations in the same deploy start with 5 fresh
attempts, and make resolve_root_group_id.sh exit non-zero when the
kcadm groups listing cannot be fetched instead of feeding a silent
empty string to the root-group assert (both surfaced by CI run
32119014832: swarm healthcheck kill mid-update).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-18 23:28:18 +02:00

48 lines
2.4 KiB
YAML

---
- name: "📌 Keycloak | Apply object updates, recovering from cross-node reschedules"
vars:
kc_update_max_attempts: 5
block:
- name: "🔍 Keycloak updates | Resolve live hosting node (swarm may reschedule)"
ansible.builtin.include_tasks: "{{ lookup('path_absolute', 'roles/sys-svc-compose/tasks/utils/swarm/resolve_host_cid.yml') }}"
vars:
resolve_service_key: "{{ entity_name }}"
resolve_output_prefix: KEYCLOAK
resolve_compose_cid: "{{ lookup('container_address', application_id, entity_name) }}"
when: DEPLOYMENT_MODE == 'swarm'
- name: "📂 Run Keycloak object-update routines on the freshly resolved node"
ansible.builtin.include_tasks:
file: update_routines.yml
apply:
delegate_to: "{{ KEYCLOAK_HOST_NODE }}"
- name: "🔢 Keycloak updates | Reset cross-node recovery attempt counter"
ansible.builtin.set_fact:
kc_update_attempt: 0
rescue:
- name: "🔢 Keycloak updates | Advance cross-node recovery attempt counter" # nocheck: rescue-recovery a cross-node reschedule needs a swarm-wide node re-resolve plus a change of delegate_to, which Ansible can only do by catching the failure and retrying; a diagnostics-only rescue cannot re-target the delegate, so this block recovers and only captures diagnostics once recovery is exhausted
ansible.builtin.set_fact:
kc_update_attempt: "{{ (kc_update_attempt | default(0) | int) + 1 }}"
- name: "🐳 Keycloak updates | Re-raise failure unchanged in compose (no swarm recovery)"
ansible.builtin.fail:
msg: "{{ ansible_failed_result.msg | default('Keycloak object update failed') }}"
when: DEPLOYMENT_MODE == 'compose'
- name: "🛑 Keycloak updates | Fail after exhausting cross-node recovery retries"
ansible.builtin.fail:
msg: >-
Keycloak object updates failed after {{ kc_update_max_attempts }}
cross-node recovery attempts: {{ ansible_failed_result.msg | default('see above') }}
when: (kc_update_attempt | int) >= (kc_update_max_attempts | int)
- name: "🔑 Keycloak updates | Re-resolve node + re-login on fresh container (recovery)"
ansible.builtin.include_tasks: "{{ role_path }}/tasks/utils/login.yml"
- name: "🔁 Keycloak updates | Retry object updates on the freshly resolved node"
ansible.builtin.include_tasks:
file: updates.yml
apply:
delegate_to: "{{ KEYCLOAK_HOST_NODE }}"