From 63f22bb1f99f6012a68e926e7c1630d1dd1a891a Mon Sep 17 00:00:00 2001 From: Bertrand Lanson Date: Sun, 10 Nov 2024 13:32:45 +0100 Subject: [PATCH] feat: add automatic reload of nomad service for certificate reloading This feature adds logic to automatically reload the nomad service if tls is enbabled and the certificates have changed. This only tracks certificates copied by the extra_files logic. --- roles/nomad/tasks/configure.yml | 66 +++++++++++++++++++++++++++++++++ roles/nomad/tasks/install.yml | 2 +- roles/nomad/tasks/main.yml | 17 ++++++++- roles/nomad/vars/main.yml | 12 ++++++ 4 files changed, 94 insertions(+), 3 deletions(-) diff --git a/roles/nomad/tasks/configure.yml b/roles/nomad/tasks/configure.yml index 0af74b2..769f5e0 100644 --- a/roles/nomad/tasks/configure.yml +++ b/roles/nomad/tasks/configure.yml @@ -24,6 +24,31 @@ when: _nomad_env_file.changed or _nomad_config_file.changed +- name: "Nomad | Gather initial checksums for certificate files" + ansible.builtin.stat: + path: "{{ item }}" + checksum_algorithm: sha1 + loop: "{{ nomad_certificates_reload_watchlist }}" + when: nomad_enable_tls + register: _nomad_initial_cert_checksums + +- name: "Nomad | 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. + _nomad_initial_checksums_normalized: >- + {% filter trim %} + {% set checksums = [] %} + {% for item in _nomad_initial_cert_checksums.results %} + {% set _ = checksums.append({ + 'item': item.item, + 'initial_checksum': (item.stat.checksum | default('absent')) + }) %} + {% endfor %} + {{ checksums }} + {% endfilter %} + when: nomad_enable_tls + - name: "Nomad | Copy extra configuration files" when: nomad_extra_files block: @@ -72,3 +97,44 @@ loop_control: loop_var: dir_source_item when: _nomad_dir_sources is defined + +- name: "Nomad | Gather final checksums for certificate files" + ansible.builtin.stat: + path: "{{ item }}" + checksum_algorithm: sha1 + loop: "{{ nomad_certificates_reload_watchlist }}" + when: nomad_enable_tls + register: _nomad_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. + _nomad_final_checksums_normalized: >- + {% filter trim %} + {% set checksums = [] %} + {% for item in _nomad_final_cert_checksums.results %} + {% set _ = checksums.append({ + 'item': item.item, + 'final_checksum': (item.stat.checksum | default('absent')) + }) %} + {% endfor %} + {{ checksums }} + {% endfilter %} + when: nomad_enable_tls + +- name: "Consul | Merge initial and final checksum lists" + ansible.builtin.set_fact: + _nomad_checksums_list: >- + {{ + _nomad_initial_checksums_normalized | + community.general.lists_mergeby(_nomad_final_checksums_normalized, 'item') + }} + when: nomad_enable_tls + +- name: "Consul | Determine if certificates have changed or were newly added" + ansible.builtin.set_fact: + _nomad_service_need_reload: true + when: + - nomad_enable_tls + - _nomad_checksums_list | json_query('[?initial_checksum!=final_checksum]') | list| length > 0 diff --git a/roles/nomad/tasks/install.yml b/roles/nomad/tasks/install.yml index 200bcb4..52791a5 100644 --- a/roles/nomad/tasks/install.yml +++ b/roles/nomad/tasks/install.yml @@ -136,6 +136,6 @@ - name: "Nomad | Set reload-check & restart-check variable" ansible.builtin.set_fact: - _nomad_service_need_reload: true + _nomad_service_need_daemon_reload: true _nomad_service_need_restart: true when: _nomad_unit_file.changed # noqa: no-handler diff --git a/roles/nomad/tasks/main.yml b/roles/nomad/tasks/main.yml index 959a953..7e07a82 100644 --- a/roles/nomad/tasks/main.yml +++ b/roles/nomad/tasks/main.yml @@ -2,6 +2,7 @@ # task/main file for nomad - name: "Nomad | Set reload-check & restart-check variable" ansible.builtin.set_fact: + _nomad_service_need_daemon_reload: false _nomad_service_need_reload: false _nomad_service_need_restart: false @@ -33,11 +34,23 @@ - name: "Nomad | Reload systemd daemon" ansible.builtin.systemd: daemon_reload: true - when: _nomad_service_need_reload + when: _nomad_service_need_daemon_reload - name: "Nomad | Start service: {{ nomad_service_name }}" ansible.builtin.service: name: "{{ nomad_service_name }}" state: restarted throttle: 1 - when: _nomad_service_need_restart + when: + - nomad_start_service + - _nomad_service_need_restart + +- name: "Nomad | Reload service: {{ nomad_service_name }}" + ansible.builtin.service: + name: "{{ nomad_service_name }}" + state: reloaded + throttle: 1 + when: + - nomad_start_service + - _nomad_service_need_reload + - not _nomad_service_need_restart diff --git a/roles/nomad/vars/main.yml b/roles/nomad/vars/main.yml index c21ccb5..0674409 100644 --- a/roles/nomad/vars/main.yml +++ b/roles/nomad/vars/main.yml @@ -15,6 +15,18 @@ nomad_github_project: hashicorp/nomad nomad_github_url: https://github.com nomad_repository_url: https://releases.hashicorp.com/nomad +nomad_certificates_reload_watchlist: | + {% filter trim %} + {% set watchlist = [] %} + {% set config = nomad_configuration.get('tls', {}) %} + {% for key in ['ca_file', 'cert_file', 'key_file'] %} + {% if config.get(key) %} + {{ watchlist.append(config[key]) }} + {% endif %} + {% endfor %} + {{ watchlist | unique }} + {% endfilter %} + nomad_configuration: datacenter: "{{ nomad_datacenter }}" region: "{{ nomad_region }}"