How to compare kernel (or other) version numbers in Ansible - ansible

For a role I'm developing I need to verify that the kernel version is greater than a particular version.
I've found the ansible_kernel fact, but is there an easy way to compare this to other versions? I thought I might manually explode the version string on the .'s and compare the numbers, but I can't even find a friendly filter to explode the version string out, so I'm at a loss.

There is a test for it:
{{ ansible_distribution_version is version('12.04', '>=') }}
{{ sample_version_var is version('1.0', operator='lt', strict=True) }}

To Print the host IP address if the kernel version is less than 3
Ansible Version : 2.0.0.2
---
- hosts: all
vars:
kernel_version: "{{ ansible_kernel }}"
tasks:
- name: 'kernel version from facts'
debug:
msg: '{{ansible_all_ipv4_addresses}} {{ansible_kernel}}'
when: ansible_kernel | version_compare('3','<')
**
In 2.5 version_compare was renamed to version
**

For ansible>=2.9 this won't work, as the test syntax is now strictly separated from filters.
https://docs.ansible.com/ansible/latest/user_guide/playbooks_tests.html
The working solution would be:
{{ sample_version_var is version('1.0', operator='lt', strict=True) }}
...

To compare a version number, such as checking if the ansible_facts['distribution_version'] version is greater than or equal to ‘12.04’, you can use the version test.
{{ ansible_facts['distribution_version'] is version('12.04', '>=') }}
When using version in a playbook or role, don’t use {{ }} as described in the FAQ
vars:
my_version: 1.2.3
tasks:
- debug:
msg: "my_version is higher than 1.0.0"
when: my_version is version('1.0.0', '>')
Check Ansible Doc for more info

Have you thought of using shell module instead? for example:
- name: Get Kernel version
shell: uname -r | egrep '^[0-9]*\.[0-9]*' -o
register: kernel_shell_output
- debug: msg="{{ kernel_shell_output.stdout}}"
- name: Add cstate and reboot bios if kernel is 4.8
shell: echo "do what yo need to do"
when: kernel_shell_output.stdout == "4.8"

Related

How to compare version numbers of software using Ansible?

Hey I am trying to check the version on installed software on my VMs with Ansible.
Unfortunately I cant get the conditionals right.
Via the ansible_facts.packages I get the version of the software but I am not sure about the comparing.
- hosts:
- os_linux
vars:
softwareVersion: "4.8.0-49"
tasks:
- name: Gather the package facts
ansible.builtin.package_facts:
manager: auto
- name: Check version of SoftwareX
ansible.builtin.debug:
msg: "OLD SoftwareX version: {{ ansible_facts.packages['SoftwareX'][0]['version'] }} found"
when: "ansible_facts.packages['SoftwareX'][0]['version'] <= {{ softwareVersion }}"
I am not sure about the comparing.
when: "ansible_facts.packages['SoftwareX'][0]['version'] <= {{ softwareVersion }}"
Since according When should I use {{ }}?
when:... are always templated and you should avoid adding {{ }}.
you'll need to remove first the curly brackets from softwareVersion.
Then, since you are comparing strings which contains a version number in order, you need to address this in a different way. Means, you can't use plain a mathematical operation but instead a specific filter for.
A minimal test playbook
---
- hosts: localhost
become: false
gather_facts: false
vars:
installedVersion: "4.7.0-48"
softwareVersion: "4.8.0-49"
tasks:
- name: Show hint
debug:
msg: "OLD"
when: installedVersion is version(softwareVersion, '<=')
will result into an output of
TASK [Show hint] ******
ok: [localhost] =>
msg: OLD
Further Documentaion
Comparing versions
Note: In 2.5 version_compare was renamed to version
To compare a version number, such as checking if the ansible_facts['distribution_version'] version is greater than or equal to ‘12.04’, you can use the version test.
Similar Q&A
Compare version numbers using Jinja2
How to compare kernel (or other) version numbers in Ansible?

Anisble conditionals if package version [duplicate]

For a role I'm developing I need to verify that the kernel version is greater than a particular version.
I've found the ansible_kernel fact, but is there an easy way to compare this to other versions? I thought I might manually explode the version string on the .'s and compare the numbers, but I can't even find a friendly filter to explode the version string out, so I'm at a loss.
There is a test for it:
{{ ansible_distribution_version is version('12.04', '>=') }}
{{ sample_version_var is version('1.0', operator='lt', strict=True) }}
To Print the host IP address if the kernel version is less than 3
Ansible Version : 2.0.0.2
---
- hosts: all
vars:
kernel_version: "{{ ansible_kernel }}"
tasks:
- name: 'kernel version from facts'
debug:
msg: '{{ansible_all_ipv4_addresses}} {{ansible_kernel}}'
when: ansible_kernel | version_compare('3','<')
**
In 2.5 version_compare was renamed to version
**
For ansible>=2.9 this won't work, as the test syntax is now strictly separated from filters.
https://docs.ansible.com/ansible/latest/user_guide/playbooks_tests.html
The working solution would be:
{{ sample_version_var is version('1.0', operator='lt', strict=True) }}
...
To compare a version number, such as checking if the ansible_facts['distribution_version'] version is greater than or equal to ‘12.04’, you can use the version test.
{{ ansible_facts['distribution_version'] is version('12.04', '>=') }}
When using version in a playbook or role, don’t use {{ }} as described in the FAQ
vars:
my_version: 1.2.3
tasks:
- debug:
msg: "my_version is higher than 1.0.0"
when: my_version is version('1.0.0', '>')
Check Ansible Doc for more info
Have you thought of using shell module instead? for example:
- name: Get Kernel version
shell: uname -r | egrep '^[0-9]*\.[0-9]*' -o
register: kernel_shell_output
- debug: msg="{{ kernel_shell_output.stdout}}"
- name: Add cstate and reboot bios if kernel is 4.8
shell: echo "do what yo need to do"
when: kernel_shell_output.stdout == "4.8"

Compare two version numbers with version in ansible

I am writing a playbook that only should run when a new package version of a software is available.
Both version numbers are custom facts I set with "set_fact"
Ansible let's you compare version numbers, so I tried it like this:
- name: compare versions
debug:
msg: "The version {{ new_version }} is newer than the old version {{ old_version }}"
when: "{{ new_version is version('{{ old_version }}', '>', strict=True }}"
Ansible throws an error that the version number is invalid. When I set "old_version" to a fixed version number it works as expected.
Is it possible to compare two facts with "version"?
I already tried different approaches with double-quotes etc which leads to syntax errors in ansible.
Any ideas?
Thanks
It could be use of Jinja delimiters {{ in a conditional. In a when: condition you don't need these delimiters to interpolate.
Example below works:
vars:
new_version: 14
old_version: 12
tasks:
- debug:
msg: 'The version {{ new_version }} is newer than the old version {{ old_version }}'
when: "new_version is version(old_version, '>')"

How to show all the host names of hosts within a specific OS in Ansible

Is there any command in Ansible to collect the hostnames of hosts with OS Debain?
The file hosts contains no groups!
So a simple command to see the hostnames of hosts containing Debain.
The setup module, which is implicitly called in any playbook via the gather_facts mechanism, contains some output that you could use.
Look for example for the ansible_distribution fact, which should contain Debian on the hosts you are looking for.
If all you want is that list once, you could invoke the module directly, using the ansible command and grep:
ansible all -m setup -a 'filter=ansible_distribution' | grep Debian
If you want to use that information dynamically in a playbook, you could use this pattern:
---
- hosts: all
tasks:
- name: Do something on Debian
debug:
msg: I'm a Debian host
when: ansible_distribution == 'Debian'
I would add that if you want to target distribution and minimum version (often the case), you could do that with a dictionary. I often use this snippet:
---
- hosts: localhost
vars:
minimum_required_version:
CentOS: 7
Debian: 11
Fedora: 31
RHEL7: 7
Ubuntu: 21.10
- name: set boolean fact has_minimum_required_version
set_fact:
has_minimum_required_version: "{{ ansible_distribution_version is version(minimum_required_version[ansible_distribution], '>=') | bool }}"
tasks:
- name: run task when host has minimum version required
debug:
msg: "{{ ansible_distribution }} {{ ansible_distribution_version }} >= {{ minimum_required_version[ansible_distribution] }}"
when: has_minimum_required_version
You could also dynamically include a playbook fragment that targets specific distributions or versions like so:
- name: Include task list in play for specific distros
include_tasks: "{{ ansible_distribution }}.yaml"
Which assumes you'd have Debian.yaml, Ubuntu.yaml, etc. defined for each distro you want to support.

Combine with_fileglob with another list in Ansible Playbooks

So I have an Ansible playbook and I'm trying to call a command for each item in a list, but also run that command over a fileglob. There is a "with_nested" in Ansible, and it can take variable names, but if I add a "with_fileglob," it just inserts "with_fileglob" as the filename instead of actually doing a glob.
vars:
repo_versions:
- version: trusty
distribution: Ubuntu
- version: wheezy
distribution: Debian
...
- command: reprepro -b /var/www/html includedeb {{ item[0].version }} {{ item[1] }}
with_nested:
- repo_versions
with_fileglob: /home/repoman/debs/*.deb
when: debs_available.stat.exists == True
I've tried a couple of different combinations and I can't seem to get it to process the command in a double for loop (for each .version, for each .deb file)
This should be what you are trying to accomplish.
I used the shell module to register the output of the fileglob, and then the stdout_lines property of the registerd variable in the loop. I have converted the task from my test to your actual commands and paths, so you might need to double check:
vars:
repo_versions:
- version: trusty
distribution: Ubuntu
- version: wheezy
distribution: Debian
tasks:
- shell: ls -1 /home/repoman/debs/*.deb
register: repo_list
- command: reprepro -b /var/www/html includedeb {{ item[0].version }} {{ item[1] }}
with_nested:
- repo_versions
- repo_list.stdout_lines

Resources