Files
computer-playbook/roles/web-app-wordpress/tasks/addons/wp-discourse.yml
kevinveenbirkenbachandClaude Opus 5 972c8764fe fix(integrations): probe the node-local port, not the public domain
Four readiness probes waited on lookup('domain', <app>) port 80 -- a
publication identity used as a machine address. With svc-net-tor deployed
that name is onion-only, because exclusive: true replaces the clearnet
domain rather than adding to it (utils/cache/domains.py).

Nextcloud 5 then burned its full 600s on zammad.helpdesk.<onion>:80. The task
carries no delegate_to but inherits apply: delegate_to: NEXTCLOUD_HOST_NODE
from 02_manager_ops.yml:46-50, which propagates through nested includes, so it
ran on a worker. svc-net-tor is placement: manager, so that worker had no
.onion split-DNS, no TransPort redirect and no :80 listener. wait_for swallows
socket.gaierror in a bare except and retries, so an unresolvable name is
indistinguishable from a slow service -- it just burns the timeout.

Point the probes at DOCKER_REACH_HOST and the service's own
ports.local.http instead. No name resolution, so the onion replacement cannot
reach it; node-local, so the inherited delegation stops mattering; and it hits
the service's own listener rather than the shared front proxy, which is what
the probe was supposed to measure in the first place.

Verified on the failing run's artifacts that this is node-independent in
swarm: zammad_railsserver.1 ran only on mgr-01, yet dockerd listens on *:8077
on all three nodes -- the ingress mesh. Only svc-prx-openresty and svc-net-tor
publish with mode: host; every other role, these four included, goes through
ingress.

Same swap for openproject, suitecrm and wordpress->discourse, which had the
identical construct.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-10 13:39:05 +02:00

60 lines
1.9 KiB
YAML

---
- name: ⏳ Wait for Discourse API
wait_for:
host: "{{ DOCKER_REACH_HOST }}"
port: "{{ lookup('config', 'web-app-discourse', 'services.discourse.ports.local.http') }}"
delay: 5
timeout: "{{ lookup('timeout', 600) | int }}"
- name: "🖥️ WP Discourse: stack-host container ops against Discourse"
include_tasks: wp-discourse-stack-host.yml
when: IS_STACK_HOST | bool
# Exception: include_vars (not lookup('file')|from_yaml) so values lazy-render and the deploy-time vault_discourse_api_key resolves in this scope.
- name: "📄 Load WP Discourse addon spec from meta/addons/wp-discourse.yml"
ansible.builtin.include_vars:
file: "{{ [role_path, 'meta/addons', 'wp-discourse.yml'] | path_join }}"
name: wp_discourse_addon
- name: "🔍 Resolve WP Discourse settings"
set_fact:
discourse_settings: "{{ wp_discourse_addon.config.discourse_settings | default([]) }}"
changed_when: false
- name: "📦 Install WP Discourse plugin"
ansible.builtin.include_tasks: ../utils/install/plugin.yml
vars:
plugin_name: wp-discourse
when: IS_STACK_HOST | bool
- name: "🔧 Configure WP Discourse settings"
loop: "{{ discourse_settings | map(attribute='name') | unique | list }}"
loop_control:
label: "{{ item }}"
vars:
option_name: "{{ item }}"
option_items: >-
{{ discourse_settings
| selectattr('name', 'equalto', option_name)
| list
}}
option_kv: >-
{{ dict(
option_items | map(attribute='key')
| zip(option_items | map(attribute='value'))
) }}
option_json_b64: "{{ option_kv | to_json | b64encode }}"
ansible.builtin.shell: >
container exec -u {{ WORDPRESS_USER }} {{ WORDPRESS_CONTAINER_ADDRESS }} bash -lc
"wp eval \"update_option(
'{{ option_name }}',
json_decode(
base64_decode('{{ option_json_b64 }}'),
true
)
);\" --path={{ WORDPRESS_DOCKER_HTML_PATH }}"
when: IS_STACK_HOST | bool