Merge branch 'feature/updater' into feature/store-i18n

svc-db-postgres/tasks/01_init.yml: the updater moved the TCP-auth wait
into 01_init/ready.yml, run once per container; that structure wins,
and ready.yml keeps store-i18n's PGPASSWORD passed by name through
environment instead of on the exec argv, which
test_exec_env_passes_no_value requires.

web-app-gitea/tasks/01_manager_ops.yml: store-i18n's administrator
password realignment stays; the OIDC/LDAP-only readiness wait goes, as
the updater's /api/v1/version wait at the top already covers it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
kevinveenbirkenbachandClaude Opus 5.5 committed 2026-10-25 20:40:19 +01:00
commit c887b8e04e
5 files changed
+72 -74

No files matched your search

+1
View File
@@ -1,3 +1,4 @@
---
database_init: false # When true a database is initialized
database_consumer_id: "svc-db-postgres" # Self consumer
postgres_verified_target: ""
+6
View File
@@ -0,0 +1,6 @@
---
- name: 🧊 Forget the Postgres container whose TCP auth was verified
ansible.builtin.set_fact:
postgres_verified_target: ""
changed_when: false
listen: container-manager-restart
+11 -37
View File
@@ -12,44 +12,18 @@
changed_when: false
no_log: "{{ MASK_CREDENTIALS_IN_LOGS | bool }}"
- name: "🔍 Postgres | Resolve hosting node + container id"
ansible.builtin.include_tasks: "{{ lookup('path_absolute', 'roles/sys-svc-compose/tasks/utils/swarm/resolve_host_cid.yml') }}"
- name: "🔍 Postgres | Resolve the container and wait for TCP auth once per container"
ansible.builtin.include_tasks: 01_init/ready.yml
when: postgres_verified_target != postgres_target
vars:
resolve_service_key: "{{ entity_name }}"
resolve_service_name: "{{ lookup('database', database_consumer_id, 'service_name') }}"
resolve_output_prefix: POSTGRES
resolve_compose_cid: "{{ lookup('database', database_consumer_id, 'container') }}"
- name: ⏳ Wait until postgres TCP auth works
block:
- name: ⏳ Wait for Postgres TCP auth
no_log: "{{ MASK_CREDENTIALS_IN_LOGS | bool }}"
ansible.builtin.shell: > # nocheck: container-exec-resolver POSTGRES_LOCAL_CID resolved at delegate_to runtime
container exec -e PGPASSWORD {{ POSTGRES_LOCAL_CID | quote }} sh -lc
'psql -h "{{ POSTGRES_LOCAL_HOST }}" -p "{{ POSTGRES_PORT }}"
-U postgres -d postgres -c "SELECT 1"'
environment:
PGPASSWORD: "{{ POSTGRES_PASSWORD }}"
delegate_to: "{{ POSTGRES_HOST_NODE }}"
register: pg_ready
until: pg_ready.rc == 0
retries: 30
delay: 5
changed_when: false
rescue:
- name: "💾 Postgres | Dump pg_hba.conf into the diagnostics folder" # nocheck: rescue-extra-diagnostics pg_hba.conf is postgres-specific auth config the generic rescue script cannot capture, and it is what a failed TCP-auth wait needs
ansible.builtin.script: "{{ lookup('path_absolute', 'roles/svc-db-postgres/files/shell/dump_pg_hba.sh') }}"
environment:
POSTGRES_CONTAINER_ADDRESS: "{{ POSTGRES_LOCAL_CID }}"
PGPASSWORD: "{{ POSTGRES_PASSWORD }}"
delegate_to: "{{ POSTGRES_HOST_NODE }}"
changed_when: false
failed_when: false
no_log: "{{ MASK_CREDENTIALS_IN_LOGS | bool }}"
- name: "🛑 Postgres | fail after pg_hba dump"
ansible.builtin.fail:
msg: "Postgres TCP auth never became ready; pg_hba.conf was dumped into the diagnostics folder (the workflow-level rescue capture collects the full snapshot)"
postgres_target: >-
{{
[
lookup('database', database_consumer_id, 'service_name'),
lookup('database', database_consumer_id, 'container'),
POSTGRES_PORT
] | join('|')
}}
- name: "📁 Create database: {{ database_name }}"
community.postgresql.postgresql_db:
@@ -0,0 +1,44 @@
---
- name: "🔍 Postgres | Resolve hosting node + container id"
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_service_name: "{{ lookup('database', database_consumer_id, 'service_name') }}"
resolve_output_prefix: POSTGRES
resolve_compose_cid: "{{ lookup('database', database_consumer_id, 'container') }}"
- name: ⏳ Wait until postgres TCP auth works
block:
- name: ⏳ Wait for Postgres TCP auth
no_log: "{{ MASK_CREDENTIALS_IN_LOGS | bool }}"
ansible.builtin.shell: > # nocheck: container-exec-resolver POSTGRES_LOCAL_CID resolved at delegate_to runtime
container exec -e PGPASSWORD {{ POSTGRES_LOCAL_CID | quote }} sh -lc
'psql -h "{{ POSTGRES_LOCAL_HOST }}" -p "{{ POSTGRES_PORT }}"
-U postgres -d postgres -c "SELECT 1"'
environment:
PGPASSWORD: "{{ POSTGRES_PASSWORD }}"
delegate_to: "{{ POSTGRES_HOST_NODE }}"
register: pg_ready
until: pg_ready.rc == 0
retries: 30
delay: 5
changed_when: false
rescue:
- name: "💾 Postgres | Dump pg_hba.conf into the diagnostics folder" # nocheck: rescue-extra-diagnostics pg_hba.conf is postgres-specific auth config the generic rescue script cannot capture, and it is what a failed TCP-auth wait needs
ansible.builtin.script: "{{ lookup('path_absolute', 'roles/svc-db-postgres/files/shell/dump_pg_hba.sh') }}"
environment:
POSTGRES_CONTAINER_ADDRESS: "{{ POSTGRES_LOCAL_CID }}"
PGPASSWORD: "{{ POSTGRES_PASSWORD }}"
delegate_to: "{{ POSTGRES_HOST_NODE }}"
changed_when: false
failed_when: false
no_log: "{{ MASK_CREDENTIALS_IN_LOGS | bool }}"
- name: "🛑 Postgres | fail after pg_hba dump"
ansible.builtin.fail:
msg: "Postgres TCP auth never became ready; pg_hba.conf was dumped into the diagnostics folder (the workflow-level rescue capture collects the full snapshot)"
- name: "🧊 Postgres | Remember the container whose TCP auth works"
ansible.builtin.set_fact:
postgres_verified_target: "{{ postgres_target }}"
changed_when: false
+10 -37
View File
@@ -1,10 +1,14 @@
---
- name: ⏳ Wait for Gitea HTTP endpoint
wait_for:
host: "{{ DOCKER_REACH_HOST }}"
port: "{{ lookup('config', application_id, 'services.gitea.ports.local.http') }}"
delay: 5
timeout: "{{ lookup('timeout', 300) | int }}"
- name: "⏳ Wait until Gitea has migrated its database and serves the API"
uri_retry:
url: "http://{{ DOCKER_REACH_HOST }}:{{ lookup('config', application_id, 'services.gitea.ports.local.http') }}/api/v1/version"
method: GET
status_code: 200
return_content: false
register: gitea_ready
until: gitea_ready.status == 200
retries: 120
delay: 5
- name: "🔍 Resolve {{ application_id }} hosting node + container id"
ansible.builtin.include_tasks: "{{ lookup('path_absolute', 'roles/sys-svc-compose/tasks/utils/swarm/resolve_host_cid.yml') }}"
@@ -13,25 +17,6 @@
resolve_output_prefix: GITEA
resolve_compose_cid: "{{ GITEA_CONTAINER_ADDRESS }}"
- name: "⏳ Wait for Gitea app.ini to be present after redeploy"
shell: | # nocheck: container-exec-resolver runtime-resolved CID, delegated to the hosting node
container exec -i --user {{ GITEA_USER }} {{ GITEA_LOCAL_CID | quote }} \
test -f {{ GITEA_CONFIG }}
delegate_to: "{{ GITEA_HOST_NODE }}"
register: gitea_config_ready
changed_when: false
retries: 30
delay: 2
until: gitea_config_ready.rc == 0
- name: "▶️ Run DB migrations inside Gitea container"
shell: | # nocheck: container-exec-resolver runtime-resolved CID, delegated to the hosting node
container exec -i --user {{ GITEA_USER }} {{ GITEA_LOCAL_CID | quote }} \
/app/gitea/gitea migrate -c {{ GITEA_CONFIG }}
delegate_to: "{{ GITEA_HOST_NODE }}"
register: migrate
changed_when: "'migrations completed' in migrate.stdout"
- name: "📁 Create initial admin user"
no_log: "{{ MASK_CREDENTIALS_IN_LOGS | bool }}"
shell: | # nocheck: container-exec-resolver runtime-resolved CID, delegated to the hosting node
@@ -66,18 +51,6 @@
delegate_to: "{{ GITEA_HOST_NODE }}"
changed_when: true
- name: "⏳ Wait until Gitea setup and migrations are ready"
uri_retry:
url: "http://{{ DOCKER_REACH_HOST }}:{{ lookup('config', application_id, 'services.gitea.ports.local.http') }}/api/v1/version"
method: GET
status_code: 200
return_content: false
register: gitea_ready
until: gitea_ready.status == 200
retries: 20
delay: 5
when: (GITEA_OIDC_ENABLED | bool) or (GITEA_LDAP_ENABLED | bool)
- name: ▶️ Execute Setup Routines
include_tasks: 02_setup.yml