I have this ansible playbook:
---
- name: Portal Quality Checks - IC
become: yes
hosts: all
tasks:
- name: Verify software version on Interconnect(s)
shell: |
dpkg -l | grep network-controller | awk '{print $3}'
register: cv_raw
when: inventory_hostname in groups.IC
tags: ['ic', 'software']
- debug:
msg: "{{ (cv_raw.stdout_lines | last) }}"
failed_when: ( hostvars[groups['IC'][0]].cv_raw.stdout_lines != hostvars[groups['IC'][1]].cv_raw.stdout_lines )
ignore_errors: true
tags: ['ic', 'software']
The output is something like:
TASK [debug] ****************************************************************************************************************************************************************************************************************************************************************************************************************
ok: [10.241.55.6] => {
"msg": "5.0.0.0600-1"
}
ok: [10.241.55.8] => {
"msg": "4.2.0.819477-1"
}
The ideea is that I'm trying to compare the version from the ouput (that's in the 2nd task in the playlist). Right now there are only 2 hosts in the inventory and it works just fine.
My question is how do I do this if I have let's say 10 hosts in the inventory and all should be running the same version? There should be an easier way to compare the resulted version for each of the hostname than how I'm doing it now hostvars[groups['IC'][0]].cv_raw.stdout_lines
for host1 and hostvars[groups['IC'][0]].cv_raw.stdout_lines
for host2 because it will really a lot of manual work to do this for each of the 10 hosts or even more complicated if let's say there are 50 hosts in the inventory.
Also I would be interested in displaying a message on the screen like:
Network Controller version:
host1 - version
host2 - version
host3 - version
...
Also if there is a version mismatch, then to display a message like:
Network Controller version missmatch:
host1 version different than host2 version etc...
Based on your suggestion, here's the output for 3 hosts, 2 of them running the same controller version and one of them running a different version:
TASK [debug]
ok: [10.241.55.6] => {
"sw_versions": [
{
"host": "ro151",
"version": "5.0.0.0600-1"
},
{
"host": "PrimaryIC-Stack5",
"version": "4.2.2.600111061-1"
},
{
"host": "SecondaryIC-Stack5",
"version": "4.2.2.600111061-1"
}
]
}
So how do I compare those versions and display an error message if there's a version mismatch?
UPDATE:
So in addition to your playbook I've added this:
- set_fact:
compare_versions: "{{ groups.IC | map('extract', hostvars) | list | json_query('[].sw_version') }}"
- debug:
var: compare_versions
run_once: true
Which results into a debug message of:
TASK [debug]
ok: [10.241.55.6] => {
"compare_versions": [
"5.0.0.0600-1",
"4.2.2.600111061-1",
"4.2.2.600111061-1"
]
}
So how do I compare those versions?!
Q: "Display a message on the screen like host1 - version ..."
A: The tasks below do the job. For each host put the version into the variable sw_version
. In the next task extract hostvars
of the hosts from the group IC
and create the list of the host-version dictionaries
- set_fact:
sw_version: "{{ cv_raw.stdout_lines|last }}"
- set_fact:
sw_versions: "{{ groups.IC|
map('extract', hostvars)|
list|
json_query('[].{host: ansible_hostname,
version: sw_version}') }}"
run_once: true
For example, given the inventory below and the list of the versions from the question
shell> cat hosts
[IC]
10.241.55.6 ansible_hostname=ro151
10.241.55.8 ansible_hostname=PrimaryIC-Stack5
10.241.55.9 ansible_hostname=SecondaryIC-Stack5
the result would be
sw_versions:
- {host: ro151, version: 5.0.0.0600-1}
- {host: PrimaryIC-Stack5, version: 4.2.2.600111061-1}
- {host: SecondaryIC-Stack5, version: 4.2.2.600111061-1}
Q: "How do I compare those versions and display an error message if there's a version mismatch?"
A: Use Version Comparison tests to analyze the data. For example
- debug:
msg: "{{ item.host }} version is {{ item.version }}.
Upgrade to {{ install_version }}."
loop: "{{ sw_versions }}"
when: item.version is version( install_version, '<')
vars:
install_version: 5.0.0.0600-1
run_once: true
gives
msg: PrimaryIC-Stack5 version is 4.2.2.600111061-1. Upgrade to 5.0.0.0600-1
msg: SecondaryIC-Stack5 version is 4.2.2.600111061-1. Upgrade to 5.0.0.0600-1
Q: "Let's say host1: 4.2.2.6, host2: 4.2.2.6, host3: 5.5.0. I want to display a message: Version mismatch between hosts: host1,host2, and host3. If all hosts are running the same version then say: All your hosts are running the same version."
A: For example
- block:
- debug:
msg: "All your hosts are running the same version."
when: sw_versions|json_query('[].version')|unique|length == 1
- debug:
msg: |-
Version mismatch among hosts:
{{ my_hosts|to_nice_yaml }}
when: sw_versions|json_query('[].version')|unique|length > 1
vars:
my_hosts: "{{ sw_versions|json_query('[].host') }}"
run_once: true
gives
msg:
Version mismatch among hosts:
- ro151
- PrimaryIC-Stack5
- SecondaryIC-Stack5
If all versions are the same the result will be
msg: All your hosts are running the same version.
Notes
- set_fact:
versions_hosts: "{{ dict(_keys|zip(_vals)) }}"
vars:
_groupby: "{{ sw_versions|groupby('version') }}"
_keys: "{{ _groupby|map('first')|list }}"
_vals: "{{ _groupby|map('last')|map('map', attribute='host')|list }}"
run_once: true
gives
versions_hosts:
4.2.2.600111061-1: [PrimaryIC-Stack5, SecondaryIC-Stack5]
5.0.0.0600-1: [ro151]