Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Switch to middleware_automation.common for rh-sso patching #64

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 52 additions & 0 deletions plugins/filter/version_sort.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# -*- coding: utf-8 -*-
# Copyright (C) 2021 Eric Lavarde <[email protected]>
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
# SPDX-License-Identifier: GPL-3.0-or-later

from __future__ import (absolute_import, division, print_function)
__metaclass__ = type

DOCUMENTATION = '''
name: version_sort
short_description: Sort a list according to version order instead of pure alphabetical one
version_added: 2.2.0
author: Eric L. (@ericzolf)
description:
- Sort a list according to version order instead of pure alphabetical one.
options:
_input:
description: A list of strings to sort.
type: list
elements: string
required: true
'''

EXAMPLES = '''
- name: Convert list of tuples into dictionary
ansible.builtin.set_fact:
dictionary: "{{ ['2.1', '2.10', '2.9'] | middleware_automation.keycloak.version_sort }}"
# Result is ['2.1', '2.9', '2.10']
'''

RETURN = '''
_value:
description: The list of strings sorted by version.
type: list
elements: string
'''

from ansible_collections.middleware_automation.keycloak.plugins.module_utils.version import LooseVersion


def version_sort(value, reverse=False):
'''Sort a list according to loose versions so that e.g. 2.9 is smaller than 2.10'''
return sorted(value, key=LooseVersion, reverse=reverse)


class FilterModule(object):
''' Version sort filter '''

def filters(self):
return {
'version_sort': version_sort
}
22 changes: 22 additions & 0 deletions plugins/module_utils/version.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# -*- coding: utf-8 -*-

# Copyright (c) 2021, Felix Fontein <[email protected]>
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
# SPDX-License-Identifier: GPL-3.0-or-later

"""Provide version object to compare version numbers."""

from __future__ import absolute_import, division, print_function
__metaclass__ = type


from ansible.module_utils.six import raise_from

try:
from ansible.module_utils.compat.version import LooseVersion # noqa: F401, pylint: disable=unused-import
except ImportError:
try:
from distutils.version import LooseVersion # noqa: F401, pylint: disable=unused-import
except ImportError as exc:
msg = 'To use this plugin or module with ansible-core 2.11, you need to use Python < 3.12 with distutils.version present'
raise_from(ImportError(msg), exc)
2 changes: 1 addition & 1 deletion roles/keycloak/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ Role Defaults
|`keycloak_archive` | keycloak install archive filename | `keycloak-legacy-{{ keycloak_version }}.zip` |
|`keycloak_download_url_9x` | Download URL for keycloak (deprecated) | `https://downloads.jboss.org/keycloak/{{ keycloak_version }}/{{ keycloak_archive }}` |
|`keycloak_installdir` | Installation path | `{{ keycloak_dest }}/keycloak-{{ keycloak_version }}` |
|`keycloak_jboss_home` | Installation work directory | `{{ keycloak_rhsso_installdir if keycloak_rhsso_enable else keycloak_installdir }}` |
|`keycloak_jboss_home` | Installation work directory | `{{ keycloak_rhsso_installdir }}` |
|`keycloak_config_dir` | Path for configuration | `{{ keycloak_jboss_home }}/standalone/configuration` |
|`keycloak_config_path_to_standalone_xml` | Custom path for configuration | `{{ keycloak_jboss_home }}/standalone/configuration/{{ keycloak_config_standalone_xml }}` |
|`keycloak_config_override_template` | Path to custom template for standalone.xml configuration | `''` |
Expand Down
4 changes: 2 additions & 2 deletions roles/keycloak/meta/argument_specs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -334,10 +334,10 @@ argument_specs:
type: "str"
sso_patch_version:
required: False
description: "Red Hat Single Sign-On latest cumulative patch version to apply; default to latest version when sso_apply_patches is True"
description: "Red Hat Single Sign-On latest cumulative patch version to apply; defaults to latest version when sso_apply_patches is True"
type: "str"
sso_patch_bundle:
default: "rh-sso-{{ sso_patch_version | default('') }}-patch.zip"
default: "rh-sso-{{ sso_patch_version | default('[0-9]+[.][0-9]+[.][0-9]+') }}-patch.zip"
description: "Red Hat SSO patch archive filename"
type: "str"
sso_product_category:
Expand Down
77 changes: 65 additions & 12 deletions roles/keycloak/tasks/rhsso_patch.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,25 +9,78 @@
path: "{{ patch_archive }}"
register: patch_archive_path

- name: Perform download from RHN
middleware_automation.redhat_csp_download.redhat_csp_download:
url: "{{ keycloak_rhn_url }}{{ sso_patch_rhn_id }}"
dest: "{{ local_path.stat.path }}/{{ sso_patch_bundle }}"
username: "{{ rhn_username }}"
password: "{{ rhn_password }}"
no_log: "{{ omit_rhn_output | default(true) }}"
- name: Perform patch download from RHN via JBossNetwork API
delegate_to: localhost
run_once: yes
when:
- patch_archive_path is defined
- patch_archive_path.stat is defined
- not patch_archive_path.stat.exists
- sso_enable is defined and sso_enable
- not keycloak_offline_install
block:
- name: Retrieve product download using JBossNetwork API
middleware_automation.common.product_search:
client_id: "{{ rhn_username }}"
client_secret: "{{ rhn_password }}"
product_type: BUGFIX
product_version: "{{ sso_version }}"
product_category: "{{ sso_product_category }}"
register: rhn_products
no_log: "{{ omit_rhn_output | default(true) }}"
delegate_to: localhost
run_once: yes

- name: Determine patch versions list
set_fact:
filtered_versions: "{{ rhn_products.results | map(attribute='file_path') | select('match', '^[^/]*/rh-sso-.*[0-9]*[.][0-9]*[.][0-9]*.*$') | map('regex_replace','[^/]*/rh-sso-([0-9]*[.][0-9]*[.][0-9]*)-.*','\\1' ) | list | unique }}"
when: sso_patch_version is not defined or sso_patch_version | length == 0
delegate_to: localhost
run_once: yes

- name: Determine latest version
set_fact:
sso_latest_version: "{{ filtered_versions | middleware_automation.keycloak.version_sort | last }}"
when: sso_patch_version is not defined or sso_patch_version | length == 0
delegate_to: localhost
run_once: yes

- name: Determine install zipfile from search results
ansible.builtin.set_fact:
rhn_filtered_products: "{{ rhn_products.results | selectattr('file_path', 'match', '[^/]*/rh-sso-' + sso_latest_version + '-patch.zip$') }}"
patch_bundle: "rh-sso-{{ sso_latest_version }}-patch.zip"
patch_version: "{{ sso_latest_version }}"
when: sso_patch_version is not defined or sso_patch_version | length == 0
delegate_to: localhost
run_once: yes

- name: "Determine selected patch from supplied version: {{ sso_patch_version }}"
set_fact:
rhn_filtered_products: "{{ rhn_products.results | selectattr('file_path', 'match', '[^/]*/' + sso_patch_bundle + '$') }}"
patch_bundle: "{{ sso_patch_bundle }}"
patch_version: "{{ sso_patch_version }}"
when: sso_patch_version is defined
delegate_to: localhost
run_once: yes

- 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: "{{ (rhn_filtered_products | first).id }}"
dest: "{{ local_path.stat.path }}/{{ patch_bundle }}"
no_log: "{{ omit_rhn_output | default(true) }}"
delegate_to: localhost
run_once: yes

- name: Set download patch archive path
ansible.builtin.set_fact:
patch_archive: "{{ keycloak_dest }}/{{ patch_bundle }}"

## copy and unpack
- name: Copy patch archive to target nodes
ansible.builtin.copy:
src: "{{ local_path.stat.path }}/{{ sso_patch_bundle }}"
src: "{{ local_path.stat.path }}/{{ patch_bundle }}"
dest: "{{ patch_archive }}"
owner: "{{ keycloak_service_user }}"
group: "{{ keycloak_service_group }}"
Expand All @@ -48,9 +101,9 @@
when:
- cli_result is defined
- cli_result.stdout is defined
- sso_patch_version not in cli_result.stdout
- patch_version not in cli_result.stdout
block:
- name: "Apply patch {{ sso_patch_version }} to server"
- name: "Apply patch {{ patch_version }} to server"
ansible.builtin.include_tasks: rhsso_cli.yml
vars:
query: "patch apply {{ patch_archive }}"
Expand Down Expand Up @@ -78,10 +131,10 @@
- name: "Verify installed patch version"
ansible.builtin.assert:
that:
- sso_patch_version not in cli_result.stdout
- patch_version not in cli_result.stdout
fail_msg: "Patch installation failed"
success_msg: "Patch installation successful"

- name: "Skipping patch"
ansible.builtin.debug:
msg: "Latest cumulative patch {{ sso_patch_version }} already installed, skipping patch installation."
msg: "Cumulative patch {{ patch_version }} already installed, skipping patch installation."