From 365a23dabb8fcd07a44654660847d37824e33a51 Mon Sep 17 00:00:00 2001 From: Vlad Zolotarov Date: Tue, 28 Jun 2022 14:12:06 -0400 Subject: [PATCH] ansible-scylla-node: fix specific version installation on Debian This patch fixes for the 'installation' and the 'upgrade' paths. The corresponding code is moved into a separate tasks file: Debian_install.yml; and used from both locations. Fixes #102 Signed-off-by: Vlad Zolotarov --- ansible-scylla-node/README.md | 16 ++++ ansible-scylla-node/tasks/Debian.yml | 27 ++---- ansible-scylla-node/tasks/Debian_install.yml | 84 +++++++++++++++++++ .../tasks/upgrade/pre_upgrade.yml | 4 +- .../tasks/upgrade/upgrade_debian.yml | 15 ++-- .../tasks/upgrade/upgrade_ubuntu.yml | 15 ++-- ansible-scylla-node/templates/apt-pin-file.j2 | 3 + 7 files changed, 122 insertions(+), 42 deletions(-) create mode 100644 ansible-scylla-node/tasks/Debian_install.yml create mode 100644 ansible-scylla-node/templates/apt-pin-file.j2 diff --git a/ansible-scylla-node/README.md b/ansible-scylla-node/README.md index ec86de30..aa648359 100644 --- a/ansible-scylla-node/README.md +++ b/ansible-scylla-node/README.md @@ -86,6 +86,22 @@ Example Playbook - ../ansible-scylla-node ``` +### `scylla_version` format +`scylla-version` can be either a string 'latest' or an explicit version that needs to be installed. +If 'latest' is requested a corresponding (OSS or Enterprise) most recent official version is going to be +installed. + +An explicit version string can be either a full version string, like `2021.1.1-0.20210530.ddf65ffc2-1` +or any prefix of it that ends with a non-digit character, e.g. `2021.1.1`, `2021.1.1-0.20210530.ddf65ffc2`, +`2021.1.1-0.20210530`, etc. + +If a give string matches zero or more than an exactly one existing version it is going to trigger +a play failure with a corresponding error message: + +```commandline +TASK [Error out, wrong Scylla version was passed (more than a single or none version matches), please fix it!] ************************************************************************************************************************* +fatal: [localhost]: FAILED! => {"changed": false, "msg": "Too many/few choices for a requested version '2021.1': ['2021.1.0-0.20210511.9e8e7d58b-1', '2021.1.1-0.20210530.ddf65ffc2-1', '2021.1.10-0.20220410.e8e681dee-1', '2021.1.11-0.20220516.8e6c9917c-1', '2021.1.12-0.20220620.e23889f17-1', '2021.1.2-0.20210620.7bb9428ae-1', '2021.1.3-0.20210708.aec1c25d7-1', '2021.1.4-0.20210721.6cb3fc153-1', '2021.1.5-0.20210818.fc817c0cd-1', '2021.1.6-0.20211006.5eee352bf-1', '2021.1.7-0.20211108.3c0706646-1', '2021.1.8-0.20220106.fcdf103fd-1', '2021.1.9-0.20220208.86e3ea4df-1', '2021.1~rc2-0.20210502.f3e5e1f12-1']. Bailing out!"} +``` License ------- diff --git a/ansible-scylla-node/tasks/Debian.yml b/ansible-scylla-node/tasks/Debian.yml index 8a7bcd22..09f7e226 100644 --- a/ansible-scylla-node/tasks/Debian.yml +++ b/ansible-scylla-node/tasks/Debian.yml @@ -58,29 +58,12 @@ name: java path: /usr/lib/jvm/java-8-openjdk-amd64/jre/bin/java - - name: Install latest OSS Scylla - apt: - name: scylla - state: latest - when: scylla_version == 'latest' and scylla_edition == 'oss' - - - name: Install latest Enterprise Scylla - apt: - name: scylla-enterprise - state: latest - when: scylla_version == 'latest' and scylla_edition == 'enterprise' - - - name: Install specified OSS Scylla - apt: - name: "scylla={{ scylla_version }}*" - state: present - when: scylla_version != 'latest' and scylla_edition == 'oss' + - name: "Going to install {{ scylla_version }}" + set_fact: + scylla_version_to_install: "{{ scylla_version }}" - - name: Install specified Enterprise Scylla - apt: - name: "scylla-enterprise={{ scylla_version }}*" - state: present - when: scylla_version != 'latest' and scylla_edition == 'enterprise' + - name: Install Scylla packages + include_tasks: Debian_install.yml become: true # TODO: Implement this for the debian based distros diff --git a/ansible-scylla-node/tasks/Debian_install.yml b/ansible-scylla-node/tasks/Debian_install.yml new file mode 100644 index 00000000..b3da4dd9 --- /dev/null +++ b/ansible-scylla-node/tasks/Debian_install.yml @@ -0,0 +1,84 @@ +--- +# Requires a 'scylla_version_to_install' fact to be set to a version string we want to install +- name: Install Scylla + block: + - name: Install 'latest' Scylla + block: + - block: + - name: Nuke an OSS pin file if exists + file: + state: absent + path: /etc/apt/preferences.d/99-scylla + + - name: Install latest OSS Scylla + apt: + name: scylla + state: latest + when: scylla_edition == 'oss' + + - block: + - name: Nuke an Enterprise pin file if exists + file: + state: absent + path: /etc/apt/preferences.d/99-scylla-enterprise + + - name: Install latest Enterprise Scylla + apt: + name: scylla-enterprise + state: latest + when: scylla_edition == 'enterprise' + when: scylla_version_to_install == 'latest' + +### Handle non-latest version installation + - name: Install explicitly specified Scylla version + block: + - name: Set Scylla package prefix as OSS + set_fact: + scylla_package_prefix: "scylla" + when: scylla_edition == 'oss' + + - name: Set Scylla package prefix as Enterprise + set_fact: + scylla_package_prefix: "scylla-enterprise" + when: scylla_edition == 'enterprise' + + - name: Get versions of {{ scylla_edition }} package + # 'apt list -a' output has a package version as a second column and an arch as a third one. + # Let's filter by the arch first and then cut the version column. + # Then we will filter out all rows that start with a requested version string followed by a digit to filter out version like 2021.1.11 when 2021.1.1 was requested. + # And finally, we are going to get rid of duplications. + shell: apt list -a {{ scylla_package_prefix }} 2>/dev/null | grep `dpkg --print-architecture` | awk '{split($0,a," "); print a[2]}' | egrep -v "^{{ scylla_version_escaped }}[0123456789]+" | egrep "^{{ scylla_version_escaped }}" | sort | uniq + register: aptversions + vars: + scylla_version_escaped: "{{ scylla_version_to_install | regex_escape }}" + + # - debug: + # msg: "{{ aptversions.stdout_line }}" + + - name: "Validate scylla version correctness" + ansible.builtin.fail: + msg: "Too many/few choices for a requested version '{{ scylla_version_to_install }}': {{ aptversions.stdout_lines }}. Bailing out!" + when: aptversions.stdout_lines | length != 1 + + - name: Fetch version parts of Scylla package + set_fact: + scylla_version_split: "{{ aptversions.stdout | regex_findall(regexp, ignorecase=True) }}" + vars: + # All we know that the version is a string comprised of 3 parts separated by '-' + regexp: '^([^\-]+)-([^\-]+)-([^\-]+)$' + + - name: Create package version pin file + template: + src: templates/apt-pin-file.j2 + dest: "/etc/apt/preferences.d/99-{{ scylla_package_prefix }}" + owner: root + group: root + mode: '0644' + + - name: "Install {{ aptversions.stdout }}" + apt: + name: "{{ scylla_package_prefix }}={{ aptversions.stdout }}" + state: present + allow_downgrade: yes + when: scylla_version_to_install != 'latest' + become: true \ No newline at end of file diff --git a/ansible-scylla-node/tasks/upgrade/pre_upgrade.yml b/ansible-scylla-node/tasks/upgrade/pre_upgrade.yml index dec724b8..4f1d5d3e 100644 --- a/ansible-scylla-node/tasks/upgrade/pre_upgrade.yml +++ b/ansible-scylla-node/tasks/upgrade/pre_upgrade.yml @@ -144,12 +144,12 @@ become: true -# Determine the folder name for 'sysconfig/defaults' files +# Determine the folder name for 'sysconfig/default' files - name: Determine the folder name for distribution-specific files vars: is_etc_defaults: "{{ true if ansible_facts['distribution'] |lower == 'debian' or ansible_facts['distribution'] |lower == 'ubuntu' else false }}" ansible.builtin.set_fact: - system_config_folder: "{{ 'defaults' if is_etc_defaults else 'sysconfig' }}" + system_config_folder: "{{ 'default' if is_etc_defaults else 'sysconfig' }}" # Prepare and create backup diff --git a/ansible-scylla-node/tasks/upgrade/upgrade_debian.yml b/ansible-scylla-node/tasks/upgrade/upgrade_debian.yml index 68e5ec6d..7c439696 100644 --- a/ansible-scylla-node/tasks/upgrade/upgrade_debian.yml +++ b/ansible-scylla-node/tasks/upgrade/upgrade_debian.yml @@ -41,12 +41,9 @@ # Upgrade Scylla -- name: Upgrade Scylla to {{ scylla_upgrade['version'] }} - ansible.builtin.apt: - name: "{{ scylla_detected['package_name'] }}*={{ scylla_upgrade['version'] }}*" - state: present - update_cache: yes - become: true - register: apt_action - retries: 300 - until: apt_action is success or ('Failed to lock apt for exclusive operation' not in apt_action.msg and '/var/lib/dpkg/lock' not in apt_action.msg) \ No newline at end of file +- name: "Upgrade Scylla to {{ scylla_upgrade['version'] }}" + set_fact: + scylla_version_to_install: "{{ scylla_upgrade['version'] }}" + +- name: Install Scylla packages + include_tasks: ../Debian_install.yml \ No newline at end of file diff --git a/ansible-scylla-node/tasks/upgrade/upgrade_ubuntu.yml b/ansible-scylla-node/tasks/upgrade/upgrade_ubuntu.yml index c43c0516..5a38c404 100644 --- a/ansible-scylla-node/tasks/upgrade/upgrade_ubuntu.yml +++ b/ansible-scylla-node/tasks/upgrade/upgrade_ubuntu.yml @@ -41,12 +41,9 @@ # Upgrade Scylla -- name: Upgrade Scylla to {{ scylla_upgrade['version'] }} - ansible.builtin.apt: - name: "{{ scylla_detected['package_name'] }}*={{ scylla_upgrade['version'] }}*" - state: present - update_cache: yes - become: true - register: apt_action - retries: 300 - until: apt_action is success or ('Failed to lock apt for exclusive operation' not in apt_action.msg and '/var/lib/dpkg/lock' not in apt_action.msg) +- name: "Upgrade Scylla to {{ scylla_upgrade['version'] }}" + set_fact: + scylla_version_to_install: "{{ scylla_upgrade['version'] }}" + +- name: Install Scylla packages + include_tasks: ../Debian_install.yml \ No newline at end of file diff --git a/ansible-scylla-node/templates/apt-pin-file.j2 b/ansible-scylla-node/templates/apt-pin-file.j2 new file mode 100644 index 00000000..0ecb8818 --- /dev/null +++ b/ansible-scylla-node/templates/apt-pin-file.j2 @@ -0,0 +1,3 @@ +Package: {{ scylla_package_prefix }}* +Pin: version {{ scylla_version_split[0][0] }}-{{ scylla_version_split[0][1] }}-{{ scylla_version_split[0][2] }} +Pin-Priority: 1001 \ No newline at end of file