--- - name: Apply new configuration ansible.builtin.uri: url: "http://{{ patroni_host }}:8008/config" method: PATCH body: "{{ new_config | to_json }}" body_format: json status_code: 200 headers: Content-Type: "application/json" register: apply_result changed_when: apply_result.status == 200 - name: Force wait for config to apply # noqa: no-handler ansible.builtin.wait_for: timeout: 30 delay: 5 when: apply_result is changed - name: Get verified cluster status # noqa: no-handler ansible.builtin.uri: url: "http://{{ patroni_host }}:8008/cluster" method: GET return_content: yes status_code: 200 register: verified_cluster_status delegate_to: localhost connection: local when: apply_result is changed - name: Display confirmed cluster status ansible.builtin.debug: msg: | === CONFIRMED CLUSTER STATUS === Leader: {{ (verified_cluster_status.json.members | selectattr('role', 'equalto', 'leader') | map(attribute='name') | first) | default('UNKNOWN') }} Members: {% for member in verified_cluster_status.json.members %} - {{ member.name }} [{{ member.role | upper }}] State: {{ member.state | default('UNKNOWN') }} Lag: {{ member.lag | default(0) }}MB Timeline: {{ member.timeline | default('N/A') }} Pending restart: {{ member.pending_restart | default(false) | ternary('YES', 'NO') }} {% endfor %} Config Applied: {{ apply_result is changed | ternary('YES', 'NO') }} ================================ delegate_to: localhost connection: local run_once: true - name: Refresh cluster status ansible.builtin.uri: url: "http://{{ patroni_host }}:8008/cluster" method: GET return_content: yes status_code: 200 register: refreshed_cluster_status delegate_to: localhost run_once: true when: verified_cluster_status is defined - name: Safe check for pending restarts ansible.builtin.set_fact: needs_restart: >- {{ (refreshed_cluster_status.json.members | map(attribute='pending_restart', default=false) | select('equalto', true) | list | count > 0) or (refreshed_cluster_status.json.members | map(attribute='tags.pending_restart', default=false) | select('equalto', true) | list | count > 0) }} node_names: >- {{ refreshed_cluster_status.json.members | map(attribute='name') | list }} when: - refreshed_cluster_status.json is defined - refreshed_cluster_status.json.members is defined run_once: true delegate_to: localhost - name: Show restart warning if needed ansible.builtin.debug: msg: | {% if needs_restart %} ================================== ВНИМАНИЕ: ТРЕБУЕТСЯ ПЕРЕЗАГРУЗКА ================================== Не, я конечно могу и сам ролью, но вдруг кластер в проде или еще где!!! Так что лучше выполнить следующую команду на одной из нод кластера: patronictl restart {{ node_names | join(' ') }} Затронутые ноды: {% for node in node_names %} - {{ node }} {% endfor %} {% else %} ================================== СТАТУС: Перезагрузка не требуется ================================== {% endif %} delegate_to: localhost run_once: true - name: Archive old configurations block: - name: Find old config files ansible.builtin.find: path: "{{ config_dir }}" pattern: "*-config.yaml" age: "10s" register: old_configs delegate_to: localhost connection: local - name: Remove excess configs (keep last 10) ansible.builtin.file: path: "{{ item.path }}" state: absent loop: "{{ (old_configs.files | sort(attribute='mtime'))[:-10] }}" when: - old_configs.matched > 10 - apply_result is changed delegate_to: localhost connection: local notify: Log cleanup results