feat: add automatic reload of consul service for certificate reloading

This feature adds logic to automatically reload the consul service if tls is
enbabled and the certificates have changed. This only tracks certificates copied
by the extra_files logic.
This commit is contained in:
Bertrand Lanson 2024-11-10 13:31:35 +01:00
parent 675753a2d8
commit bcbfd39285
Signed by: lanson
SSH Key Fingerprint: SHA256:/nqc6HGqld/PS208F6FUOvZlUzTS0rGpNNwR5O2bQBw
4 changed files with 94 additions and 3 deletions

View File

@ -24,6 +24,31 @@
when: _consul_env_file.changed or when: _consul_env_file.changed or
_consul_config_file.changed _consul_config_file.changed
- name: "Consul | Gather initial checksums for certificate files"
ansible.builtin.stat:
path: "{{ item }}"
checksum_algorithm: sha1
loop: "{{ consul_certificates_reload_watchlist }}"
when: consul_enable_tls
register: _consul_initial_cert_checksums
- name: "Consul | Normalize initial checksums"
ansible.builtin.set_fact:
# This needs to be optimized, but I have spent so much time on it not
# working that I will keep it as is for now, and we'll see later.
_consul_initial_checksums_normalized: >-
{% filter trim %}
{% set checksums = [] %}
{% for item in _consul_initial_cert_checksums.results %}
{% set _ = checksums.append({
'item': item.item,
'initial_checksum': (item.stat.checksum | default('absent'))
}) %}
{% endfor %}
{{ checksums }}
{% endfilter %}
when: consul_enable_tls
- name: "Consul | Copy extra configuration files" - name: "Consul | Copy extra configuration files"
when: consul_extra_files when: consul_extra_files
block: block:
@ -72,3 +97,44 @@
loop_control: loop_control:
loop_var: dir_source_item loop_var: dir_source_item
when: _consul_dir_sources is defined when: _consul_dir_sources is defined
- name: "Consul | Gather final checksums for certificate files"
ansible.builtin.stat:
path: "{{ item }}"
checksum_algorithm: sha1
loop: "{{ consul_certificates_reload_watchlist }}"
when: consul_enable_tls
register: _consul_final_cert_checksums
- name: "Consul | Normalize final checksums"
ansible.builtin.set_fact:
# This needs to be optimized, but I have spent so much time on it not
# working that I will keep it as is for now, and we'll see later.
_consul_final_checksums_normalized: >-
{% filter trim %}
{% set checksums = [] %}
{% for item in _consul_final_cert_checksums.results %}
{% set _ = checksums.append({
'item': item.item,
'final_checksum': (item.stat.checksum | default('absent'))
}) %}
{% endfor %}
{{ checksums }}
{% endfilter %}
when: consul_enable_tls
- name: "Consul | Merge initial and final checksum lists"
ansible.builtin.set_fact:
_consul_checksums_list: >-
{{
_consul_initial_checksums_normalized |
community.general.lists_mergeby(_consul_final_checksums_normalized, 'item')
}}
when: consul_enable_tls
- name: "Consul | Determine if certificates have changed or were newly added"
ansible.builtin.set_fact:
_consul_service_need_reload: true
when:
- consul_enable_tls
- _consul_checksums_list | json_query('[?initial_checksum!=final_checksum]') | list| length > 0

View File

@ -136,6 +136,6 @@
- name: "Consul | Set reload-check & restart-check variable" - name: "Consul | Set reload-check & restart-check variable"
ansible.builtin.set_fact: ansible.builtin.set_fact:
_consul_service_need_reload: true _consul_service_need_daemon_reload: true
_consul_service_need_restart: true _consul_service_need_restart: true
when: _consul_unit_file.changed # noqa: no-handler when: _consul_unit_file.changed # noqa: no-handler

View File

@ -2,6 +2,7 @@
# task/main file for consul # task/main file for consul
- name: "Consul | Set reload-check & restart-check variable" - name: "Consul | Set reload-check & restart-check variable"
ansible.builtin.set_fact: ansible.builtin.set_fact:
_consul_service_need_daemon_reload: false
_consul_service_need_reload: false _consul_service_need_reload: false
_consul_service_need_restart: false _consul_service_need_restart: false
@ -37,11 +38,22 @@
- name: "Consul | Reload systemd daemon" - name: "Consul | Reload systemd daemon"
ansible.builtin.systemd: ansible.builtin.systemd:
daemon_reload: true daemon_reload: true
when: _consul_service_need_reload when: _consul_service_need_daemon_reload
- name: "Consul | Start service: {{ consul_service_name }}" - name: "Consul | Start service: {{ consul_service_name }}"
ansible.builtin.service: ansible.builtin.service:
name: "{{ consul_service_name }}" name: "{{ consul_service_name }}"
state: restarted state: restarted
throttle: 1 throttle: 1
when: _consul_service_need_restart when:
- consul_start_service
- _consul_service_need_restart
- name: "Consul | Reload service: {{ consul_service_name }}"
ansible.builtin.service:
name: "{{ consul_service_name }}"
state: reloaded
throttle: 1
when:
- _consul_service_need_reload
- not _consul_service_need_restart

View File

@ -21,6 +21,19 @@ consul_github_project: hashicorp/consul
consul_github_url: https://github.com consul_github_url: https://github.com
consul_repository_url: https://releases.hashicorp.com/consul consul_repository_url: https://releases.hashicorp.com/consul
consul_certificates_reload_watchlist: |
{% filter trim %}
{% set watchlist = [] %}
{% for block, config in (consul_configuration.tls | default({})).items() %}
{% for key in ['ca_file', 'cert_file', 'key_file'] %}
{% if config.get(key) %}
{{ watchlist.append(config[key]) }}
{% endif %}
{% endfor %}
{% endfor %}
{{ watchlist | unique }}
{% endfilter %}
consul_configuration: consul_configuration:
domain: "{{ consul_domain }}" domain: "{{ consul_domain }}"
datacenter: "{{ consul_datacenter }}" datacenter: "{{ consul_datacenter }}"