commit b762722b614360d61a964bf6020d0feb51ef9628
parent 6c0f65e7e2cd57c810fee186c002bdcdf285ebb9
Author: Florian Dold <dold@taler.net>
Date: Mon, 10 Aug 2026 12:05:18 +0200
Add post-deployment sanity checks
Diffstat:
3 files changed, 150 insertions(+), 0 deletions(-)
diff --git a/playbooks/setup.yml b/playbooks/setup.yml
@@ -87,3 +87,8 @@
when: deploy_monitoring | bool
- role: devtesting
when: dangerously_enable_devtesting | bool
+
+ post_tasks:
+ - name: Run post-deployment sanity checks
+ ansible.builtin.include_role:
+ name: post_deployment_checks
diff --git a/roles/post_deployment_checks/defaults/main.yml b/roles/post_deployment_checks/defaults/main.yml
@@ -0,0 +1,76 @@
+---
+post_deployment_check_retries: 10
+post_deployment_check_delay: 1
+post_deployment_http_timeout: 5
+
+post_deployment_systemd_checks:
+ # Exchange
+ - unit: taler-exchange.target
+ enabled: true
+ - unit: taler-exchange-httpd.service
+ enabled: true
+ - unit: taler-exchange-wirewatch.service
+ enabled: true
+ - unit: taler-exchange-aggregator.service
+ enabled: true
+ - unit: taler-exchange-closer.service
+ enabled: true
+ - unit: taler-exchange-expire.service
+ enabled: true
+ - unit: taler-exchange-transfer.service
+ enabled: true
+ - unit: taler-exchange-secmod-cs.service
+ enabled: true
+ - unit: taler-exchange-secmod-eddsa.service
+ enabled: true
+ - unit: taler-exchange-secmod-rsa.service
+ enabled: true
+ - unit: taler-exchange-sanctionscheck.service
+ enabled: >-
+ {{
+ sanction_list is defined
+ and 'taler-exchange-sanctionscheck.service' in ansible_facts.services
+ }}
+
+ # LibEuFin Nexus
+ - unit: libeufin-nexus-httpd.service
+ enabled: true
+ - unit: libeufin-nexus.target
+ enabled: "{{ use_ebics | bool }}"
+ - unit: libeufin-nexus-ebics-fetch.service
+ enabled: "{{ use_ebics | bool }}"
+ - unit: libeufin-nexus-ebics-submit.service
+ enabled: "{{ use_ebics | bool }}"
+
+ # Challengers
+ - unit: sms-challenger-httpd.service
+ enabled: "{{ deploy_challenger | bool }}"
+ - unit: email-challenger-httpd.service
+ enabled: "{{ deploy_challenger | bool }}"
+ - unit: postal-challenger-httpd.service
+ enabled: "{{ deploy_challenger | bool }}"
+
+post_deployment_http_checks:
+ - name: Taler exchange /config
+ url: http://localhost/config
+ unix_socket: /var/run/taler-exchange/httpd/exchange-http.sock
+ enabled: true
+
+ - name: LibEuFin Nexus /taler-prepared-transfer/config
+ url: "http://127.0.0.1:{{ libeufin_port }}/taler-prepared-transfer/config"
+ enabled: true
+
+ - name: SMS Challenger /config
+ url: http://localhost/config
+ unix_socket: /run/challenger-sms/challenger-http.sock
+ enabled: "{{ deploy_challenger | bool }}"
+
+ - name: email Challenger /config
+ url: http://localhost/config
+ unix_socket: /run/challenger-email/challenger-http.sock
+ enabled: "{{ deploy_challenger | bool }}"
+
+ - name: postal Challenger /config
+ url: http://localhost/config
+ unix_socket: /run/challenger-postal/challenger-http.sock
+ enabled: "{{ deploy_challenger | bool }}"
diff --git a/roles/post_deployment_checks/tasks/main.yml b/roles/post_deployment_checks/tasks/main.yml
@@ -0,0 +1,69 @@
+---
+- name: Gather service facts for optional post-deployment checks
+ ansible.builtin.service_facts:
+
+- name: Check that required systemd units are active
+ ansible.builtin.command:
+ argv:
+ - systemctl
+ - is-active
+ - --quiet
+ - "{{ item.unit }}"
+ loop: "{{ post_deployment_systemd_checks }}"
+ loop_control:
+ label: "{{ item.unit }}"
+ register: post_deployment_systemd_check
+ changed_when: false
+ failed_when: false
+ retries: "{{ post_deployment_check_retries }}"
+ delay: "{{ post_deployment_check_delay }}"
+ until: post_deployment_systemd_check.rc == 0
+ when: item.enabled | bool
+
+- name: Check that required HTTP endpoints respond
+ ansible.builtin.uri:
+ url: "{{ item.url }}"
+ unix_socket: "{{ item.unix_socket | default(omit) }}"
+ status_code: 200
+ timeout: "{{ post_deployment_http_timeout }}"
+ use_proxy: false
+ loop: "{{ post_deployment_http_checks }}"
+ loop_control:
+ label: "{{ item.name }}"
+ register: post_deployment_http_check
+ changed_when: false
+ failed_when: false
+ retries: "{{ post_deployment_check_retries }}"
+ delay: "{{ post_deployment_check_delay }}"
+ until: post_deployment_http_check.status | default(-1) == 200
+ when: item.enabled | bool
+
+- name: Collect failed post-deployment checks
+ ansible.builtin.set_fact:
+ post_deployment_failed_systemd_units: >-
+ {{
+ post_deployment_systemd_check.results
+ | rejectattr('skipped', 'defined')
+ | rejectattr('rc', 'equalto', 0)
+ | map(attribute='item.unit')
+ | list
+ }}
+ post_deployment_failed_http_endpoints: >-
+ {{
+ post_deployment_http_check.results
+ | rejectattr('skipped', 'defined')
+ | rejectattr('status', 'equalto', 200)
+ | map(attribute='item.name')
+ | list
+ }}
+
+- name: Report post-deployment sanity check failures
+ ansible.builtin.assert:
+ that:
+ - post_deployment_failed_systemd_units | length == 0
+ - post_deployment_failed_http_endpoints | length == 0
+ fail_msg: |-
+ Post-deployment sanity checks failed.
+ Inactive systemd units: {{ post_deployment_failed_systemd_units | join(', ') or 'none' }}
+ Unavailable HTTP endpoints: {{ post_deployment_failed_http_endpoints | join(', ') or 'none' }}
+ success_msg: All post-deployment sanity checks passed.