From 2d573c2b626e348130b921ad827ed3a222daee75 Mon Sep 17 00:00:00 2001 From: Guido Grazioli Date: Wed, 15 May 2024 13:34:29 +0200 Subject: [PATCH] Add restart strategies, and allow custom task include Co-authored-by: Helmut Wolf Co-authored-by: Guido Grazioli --- roles/keycloak_quarkus/defaults/main.yml | 5 ++ roles/keycloak_quarkus/handlers/main.yml | 3 +- .../keycloak_quarkus/meta/argument_specs.yml | 22 +++++++- roles/keycloak_quarkus/tasks/install.yml | 4 +- roles/keycloak_quarkus/tasks/prereqs.yml | 18 +++++-- roles/keycloak_quarkus/tasks/restart.yml | 51 ++++++------------- roles/keycloak_quarkus/tasks/restart/none.yml | 4 ++ .../keycloak_quarkus/tasks/restart/serial.yml | 8 +++ .../tasks/restart/verify_first.yml | 34 +++++++++++++ 9 files changed, 104 insertions(+), 45 deletions(-) create mode 100644 roles/keycloak_quarkus/tasks/restart/none.yml create mode 100644 roles/keycloak_quarkus/tasks/restart/serial.yml create mode 100644 roles/keycloak_quarkus/tasks/restart/verify_first.yml diff --git a/roles/keycloak_quarkus/defaults/main.yml b/roles/keycloak_quarkus/defaults/main.yml index d61cfff6..0dde230b 100644 --- a/roles/keycloak_quarkus/defaults/main.yml +++ b/roles/keycloak_quarkus/defaults/main.yml @@ -153,3 +153,8 @@ keycloak_quarkus_ks_vault_pass: keycloak_quarkus_providers: [] keycloak_quarkus_policies: [] keycloak_quarkus_supported_policy_types: ['password-blacklists'] + +# files in restart directory (one of [ 'serial', 'none', 'verify_first' ]), or path to file when providing custom strategy +keycloak_quarkus_restart_strategy: restart/serial.yml +keycloak_quarkus_restart_health_check: "{{ keycloak_quarkus_ha_enabled }}" +keycloak_quarkus_restart_pause: 15 diff --git a/roles/keycloak_quarkus/handlers/main.yml b/roles/keycloak_quarkus/handlers/main.yml index b95d5c39..5851a719 100644 --- a/roles/keycloak_quarkus/handlers/main.yml +++ b/roles/keycloak_quarkus/handlers/main.yml @@ -7,7 +7,8 @@ ansible.builtin.include_tasks: bootstrapped.yml listen: bootstrapped - name: "Restart {{ keycloak.service_name }}" - ansible.builtin.include_tasks: restart.yml + ansible.builtin.include_tasks: + file: "{{ keycloak_quarkus_restart_strategy if keycloak_quarkus_ha_enabled else 'restart.yml' }}" listen: "restart keycloak" - name: "Print deprecation warning" ansible.builtin.fail: diff --git a/roles/keycloak_quarkus/meta/argument_specs.yml b/roles/keycloak_quarkus/meta/argument_specs.yml index 6936fa21..01dbfb99 100644 --- a/roles/keycloak_quarkus/meta/argument_specs.yml +++ b/roles/keycloak_quarkus/meta/argument_specs.yml @@ -399,7 +399,13 @@ argument_specs: default: 10 type: 'int' keycloak_quarkus_providers: - description: "List of provider definition dicts: { 'id': str, 'spi': str, 'url': str, 'local_path': str, 'maven': { 'repository_url': str, 'group_id': str, 'artifact_id': str, 'version': str, 'username': str, optional, 'password': str, optional }, 'default': bool, 'properties': list of key/value }" + description: > + List of provider definition dicts: { 'id': str, 'spi': str, 'url': str, 'local_path': str, + 'maven': { + 'repository_url': str, 'group_id': str, 'artifact_id': str, 'version': str, 'username': str, optional, 'password': str, optional + }, + 'default': bool, + 'properties': list of key/value } default: [] type: "list" keycloak_quarkus_supported_policy_types: @@ -425,6 +431,20 @@ argument_specs: default: true description: "Allow the option to ignore invalid certificates when downloading JDBC drivers from a custom URL" type: "bool" + keycloak_quarkus_restart_health_check: + default: "{{ keycloak_quarkus_ha_enabled }}" + description: "Whether to wait on successful health check after restart" + type: "bool" + keycloak_quarkus_restart_strategy: + description: > + Strategy task file for restarting in HA, one of [ 'serial', 'none', 'verify_first' ] below, or path to + file when providing custom strategy + default: "restart/serial.yml" + type: "str" + keycloak_quarkus_restart_pause: + description: "Seconds to wait between restarts in HA strategy" + default: 15 + type: int downstream: options: rhbk_version: diff --git a/roles/keycloak_quarkus/tasks/install.yml b/roles/keycloak_quarkus/tasks/install.yml index ced4191a..7745031b 100644 --- a/roles/keycloak_quarkus/tasks/install.yml +++ b/roles/keycloak_quarkus/tasks/install.yml @@ -258,7 +258,7 @@ - name: "Upload local providers" ansible.builtin.copy: - src: "{{ item.local_path}}" + src: "{{ item.local_path }}" dest: "{{ keycloak.home }}/providers/{{ item.id }}.jar" owner: "{{ keycloak.service_user }}" group: "{{ keycloak.service_group }}" @@ -280,7 +280,7 @@ - name: "Install custom policies" ansible.builtin.get_url: url: "{{ item.url }}" - dest: "{{ keycloak.home }}/data/{{ item.type|default(keycloak_quarkus_supported_policy_types | first) | lower }}/{{ item.name }}" + dest: "{{ keycloak.home }}/data/{{ item.type | default(keycloak_quarkus_supported_policy_types | first) | lower }}/{{ item.name }}" owner: "{{ keycloak.service_user }}" group: "{{ keycloak.service_group }}" mode: '0640' diff --git a/roles/keycloak_quarkus/tasks/prereqs.yml b/roles/keycloak_quarkus/tasks/prereqs.yml index d901c718..220f65b5 100644 --- a/roles/keycloak_quarkus/tasks/prereqs.yml +++ b/roles/keycloak_quarkus/tasks/prereqs.yml @@ -59,11 +59,18 @@ - name: "Validate providers" ansible.builtin.assert: - that: - - item.id is defined and item.id | length > 0 - - (item.spi is defined and item.spi | length > 0) or (item.url is defined and item.url | length > 0) or (item.maven is defined and item.maven.repository_url is defined and item.maven.repository_url | length > 0 and item.maven.group_id is defined and item.maven.group_id | length > 0 and item.maven.artifact_id is defined and item.maven.artifact_id | length > 0) or (item.local_path is defined and item.local_path | length > 0) + that: > + item.id is defined and item.id | length > 0 and + ( (item.spi is defined and item.spi | length > 0) or + (item.url is defined and item.url | length > 0) or + ( item.maven is defined and item.maven.repository_url is defined and item.maven.repository_url | length > 0 and + item.maven.group_id is defined and item.maven.group_id | length > 0 and + item.maven.artifact_id is defined and item.maven.artifact_id | length > 0) or + (item.local_path is defined and item.local_path | length > 0) + ) quiet: true - fail_msg: "Providers definition is incorrect; `id` and one of `spi`, `url`, `local_path`, or `maven` are mandatory. `key` and `value` are mandatory for each property" + fail_msg: > + Providers definition incorrect; `id` and one of `spi`, `url`, `local_path`, or `maven` are mandatory. `key` and `value` are mandatory for each property loop: "{{ keycloak_quarkus_providers }}" - name: "Validate policies" @@ -73,7 +80,8 @@ - item.url is defined and item.url | length > 0 - item.type is not defined or item.type | lower in keycloak_quarkus_supported_policy_types quiet: true - fail_msg: "Policy definition is incorrect: `name` and one of `url` are mandatory, `type` needs to be left empty or one of {{ keycloak_quarkus_supported_policy_types }}." + fail_msg: > + Policy definition is incorrect: `name` and one of `url` are mandatory, `type` needs to be left empty or one of {{ keycloak_quarkus_supported_policy_types }}. loop: "{{ keycloak_quarkus_policies }}" - name: "Validate additional env variables" diff --git a/roles/keycloak_quarkus/tasks/restart.yml b/roles/keycloak_quarkus/tasks/restart.yml index 4d551892..9255114f 100644 --- a/roles/keycloak_quarkus/tasks/restart.yml +++ b/roles/keycloak_quarkus/tasks/restart.yml @@ -1,38 +1,17 @@ --- -- name: Ensure only one service at a time gets rebooted, to ensure replication of distributed ispn caches - throttle: 1 - block: - - name: "Restart and enable {{ keycloak.service_name }} service on first host" - ansible.builtin.systemd: - name: "{{ keycloak.service_name }}" - enabled: true - state: restarted - daemon_reload: true - become: true - delegate_to: "{{ ansible_play_hosts | first }}" - run_once: true +- name: "Restart and enable {{ keycloak.service_name }} service" + ansible.builtin.systemd: + name: "{{ keycloak.service_name }}" + enabled: true + state: restarted + daemon_reload: true + become: true - - name: "Wait until {{ keycloak.service_name }} service becomes active {{ keycloak.health_url }}" - ansible.builtin.uri: - url: "{{ keycloak.health_url }}" - register: keycloak_status - until: keycloak_status.status == 200 - retries: 25 - delay: 10 - delegate_to: "{{ ansible_play_hosts | first }}" - run_once: true - - - name: Pause to give distributed ispn caches time to (re-)replicate back onto first host - ansible.builtin.pause: - seconds: 15 - when: - - keycloak_quarkus_ha_enabled - - - name: "Restart and enable {{ keycloak.service_name }} service on all other hosts" - ansible.builtin.systemd: - name: "{{ keycloak.service_name }}" - enabled: true - state: restarted - daemon_reload: true - become: true - when: inventory_hostname != ansible_play_hosts | first +- name: "Wait until {{ keycloak.service_name }} service becomes active {{ keycloak.health_url }}" + ansible.builtin.uri: + url: "{{ keycloak.health_url }}" + register: keycloak_status + until: keycloak_status.status == 200 + retries: 25 + delay: 10 + when: keycloak_quarkus_restart_health_check diff --git a/roles/keycloak_quarkus/tasks/restart/none.yml b/roles/keycloak_quarkus/tasks/restart/none.yml new file mode 100644 index 00000000..d0489591 --- /dev/null +++ b/roles/keycloak_quarkus/tasks/restart/none.yml @@ -0,0 +1,4 @@ +--- +- name: "Display message" + ansible.builtin.debug: + msg: "keycloak_quarkus_restart_strategy is none, skipping restart" diff --git a/roles/keycloak_quarkus/tasks/restart/serial.yml b/roles/keycloak_quarkus/tasks/restart/serial.yml new file mode 100644 index 00000000..74e8e3be --- /dev/null +++ b/roles/keycloak_quarkus/tasks/restart/serial.yml @@ -0,0 +1,8 @@ +--- +- name: "Restart services in serial, with optional healtch check (keycloak_quarkus_restart_health_check)" + throttle: 1 + loop: "{{ ansible_play_hosts }}" + block: + - name: "Restart and enable {{ keycloak.service_name }} service on first host" + ansible.builtin.include_tasks: ../restart.yml + delegate_to: "{{ item }}" diff --git a/roles/keycloak_quarkus/tasks/restart/verify_first.yml b/roles/keycloak_quarkus/tasks/restart/verify_first.yml new file mode 100644 index 00000000..64e2f536 --- /dev/null +++ b/roles/keycloak_quarkus/tasks/restart/verify_first.yml @@ -0,0 +1,34 @@ +--- +- name: Verify first restarted service with health URL, then rest in parallel + block: + - name: "Restart and enable {{ keycloak.service_name }} service on first host" + ansible.builtin.systemd: + name: "{{ keycloak.service_name }}" + enabled: true + state: restarted + daemon_reload: true + become: true + delegate_to: "{{ ansible_play_hosts | first }}" + run_once: true + + - name: "Wait until {{ keycloak.service_name }} service becomes active {{ keycloak.health_url }}" + ansible.builtin.uri: + url: "{{ keycloak.health_url }}" + register: keycloak_status + until: keycloak_status.status == 200 + retries: 25 + delay: 10 + delegate_to: "{{ ansible_play_hosts | first }}" + run_once: true + + - name: Pause to give distributed ispn caches time to (re-)replicate back onto first host + ansible.builtin.pause: + seconds: "{{ keycloak_quarkus_restart_pause }}" + when: + - keycloak_quarkus_ha_enabled + + - name: "Restart and enable {{ keycloak.service_name }} service on other hosts" + ansible.builtin.include_tasks: ../restart.yml + delegate_to: "{{ item }}" + loop: "{{ ansible_play_hosts }}" + when: inventory_hostname != ansible_play_hosts | first