--- ## check remote patch archive - name: Set download patch archive path ansible.builtin.set_fact: keycloak_patch_archive: "{{ keycloak_dest }}/{{ sso_patch_bundle }}" keycloak_patch_bundle: "{{ sso_patch_bundle }}" keycloak_patch_version: "{{ sso_patch_version }}" when: sso_patch_version is defined - name: Check download patch archive path ansible.builtin.stat: path: "{{ keycloak_patch_archive }}" register: keycloak_patch_archive_path when: sso_patch_version is defined become: "{{ keycloak_rhsso_patch_require_privilege_escalation | default(true) }}" - name: Perform patch download from RHN via Unified Downloads API delegate_to: localhost run_once: true when: - sso_enable is defined and sso_enable - not keycloak_offline_install - sso_apply_patches block: - name: Retrieve product download using Unified Downloads API middleware_automation.common.product_search: client_id: "{{ rhn_username }}" client_secret: "{{ rhn_password }}" product_type: BUGFIX product_version: "{{ sso_version.split('.')[:2] | join('.') }}" product_category: "{{ sso_product_category }}" validate_certs: false register: keycloak_rhn_products no_log: "{{ omit_rhn_output | default(true) }}" delegate_to: localhost run_once: true - name: Determine patch versions list ansible.builtin.set_fact: keycloak_filtered_versions: "{{ keycloak_rhn_products.results | map(attribute='file_name') | \ select('match', '^[^/]*/rh-sso-.*[0-9]*[.][0-9]*[.][0-9]*.*$') | \ map('regex_replace', '[^/]*/rh-sso-([0-9]*[.][0-9]*[.][0-9]*(-[0-9])?)-.*', '\\1') | list | unique }}" when: (sso_patch_version | default('', true)) | length == 0 delegate_to: localhost run_once: true - name: Determine latest version ansible.builtin.set_fact: keycloak_sso_latest_version: "{{ keycloak_filtered_versions | middleware_automation.common.version_sort | last }}" when: (sso_patch_version | default('', true)) | length == 0 delegate_to: localhost run_once: true - name: Determine install zipfile from search results ansible.builtin.set_fact: keycloak_rhn_filtered_products: "{{ keycloak_rhn_products.results | selectattr('file_name', 'match', '[^/]*/rh-sso-' + keycloak_sso_latest_version + '-patch.zip$') }}" keycloak_patch_bundle: "rh-sso-{{ keycloak_sso_latest_version }}-patch.zip" keycloak_patch_version: "{{ keycloak_sso_latest_version }}" when: (sso_patch_version | default('', true)) | length == 0 delegate_to: localhost run_once: true - name: "Determine selected patch from supplied version: {{ sso_patch_version }}" ansible.builtin.set_fact: keycloak_rhn_filtered_products: "{{ keycloak_rhn_products.results | selectattr('file_name', 'match', '[^/]*/' + sso_patch_bundle + '$') }}" keycloak_patch_bundle: "{{ sso_patch_bundle }}" keycloak_patch_version: "{{ sso_patch_version }}" when: sso_patch_version is defined delegate_to: localhost run_once: true - name: Download Red Hat Single Sign-On patch middleware_automation.common.product_download: # noqa risky-file-permissions delegated, uses controller host user client_id: "{{ rhn_username }}" client_secret: "{{ rhn_password }}" product_id: "{{ (keycloak_rhn_filtered_products | sort | last).id }}" dest: "{{ keycloak_local_path.stat.path }}/{{ keycloak_patch_bundle }}" validate_certs: false no_log: "{{ omit_rhn_output | default(true) }}" delegate_to: localhost run_once: true - name: Set download patch archive path ansible.builtin.set_fact: keycloak_patch_archive: "{{ keycloak_dest }}/{{ keycloak_patch_bundle }}" - name: Check download patch archive path ansible.builtin.stat: path: "{{ keycloak_patch_archive }}" register: keycloak_patch_archive_path become: "{{ keycloak_rhsso_patch_require_privilege_escalation | default(true) }}" ## copy and unpack - name: Copy patch archive to target nodes ansible.builtin.copy: src: "{{ keycloak_local_path.stat.path }}/{{ keycloak_patch_bundle }}" dest: "{{ keycloak_patch_archive }}" owner: "{{ keycloak_service_user }}" group: "{{ keycloak_service_group }}" mode: '0640' register: keycloak_new_version_downloaded when: - not keycloak_patch_archive_path.stat.exists - keycloak_local_archive_path.stat is defined - keycloak_local_archive_path.stat.exists become: "{{ keycloak_rhsso_patch_require_privilege_escalation | default(true) }}" - name: "Check installed patches" ansible.builtin.include_tasks: rhsso_cli.yml vars: cli_query: "patch info" args: apply: become: "{{ keycloak_rhsso_patch_require_privilege_escalation | default(true) }}" become_user: "{{ keycloak_service_user }}" - name: "Perform patching" when: - keycloak_cli_result is defined - keycloak_cli_result.stdout is defined - keycloak_patch_version | regex_replace('-[0-9]$', '') not in keycloak_cli_result.stdout block: - name: "Apply patch to server: {{ keycloak_patch_version }}" ansible.builtin.include_tasks: rhsso_cli.yml vars: cli_query: "patch apply {{ keycloak_patch_archive }}" args: apply: become: "{{ keycloak_rhsso_patch_require_privilege_escalation | default(true) }}" become_user: "{{ keycloak_service_user }}" - name: "Restart server to ensure patch content is running" ansible.builtin.include_tasks: rhsso_cli.yml vars: cli_query: "shutdown --restart" when: - keycloak_cli_result.rc == 0 args: apply: become: "{{ keycloak_rhsso_patch_require_privilege_escalation | default(true) }}" become_user: "{{ keycloak_service_user }}" - name: "Wait until service becomes active: {{ keycloak_config.service_name }}" ansible.builtin.uri: url: "{{ keycloak_config.health_url }}" register: keycloak_status until: keycloak_status.status == 200 retries: 25 delay: 10 - name: "Query installed patch after restart" ansible.builtin.include_tasks: rhsso_cli.yml vars: cli_query: "patch info" args: apply: become: "{{ keycloak_rhsso_patch_require_privilege_escalation | default(true) }}" become_user: "{{ keycloak_service_user }}" - name: "Verify installed patch version" ansible.builtin.assert: that: - keycloak_patch_version not in keycloak_cli_result.stdout fail_msg: "Patch installation failed" success_msg: "Patch installation successful" - name: "Skipping patch" ansible.builtin.debug: msg: "Cumulative patch {{ keycloak_patch_version }} already installed, skipping patch installation." when: - keycloak_cli_result is defined - keycloak_cli_result.stdout is defined - keycloak_patch_version in keycloak_cli_result.stdout