We are doing an In-Place Upgrade from RHEL 7 to RHEL 8 in my organization and we've come to find out that not all RHEL 7 packages are removed after an OS Upgrade. I've been asked to report on all RHEL 7 packages leftover on the device. To start I've looked into Ansible Package facts which has a variable that looks something like:
'ansible_facts.packages:{
zlib: [
{
"arch": "x86_64",
"epoch": null,
"release": "11.el7",
"source": "rpm",
"version": "1.2.7"
},
{
"arch": "x86_64",
"epoch": null,
"release": "10.el7",
"source": "rpm",
"version": "1.2.6"
},
{
"arch": "x86_64",
"epoch": null,
"release": "10.el8",
"source": "rpm",
"version": "1.2.7"
}
]
}
This occurs for a handful of packages, what I would like to do is to run a json_query against the entire dictionary of package_facts and determine what "el7" packages live on the host. That can tell me what I want to remove. Are there any suggestions on the json_query to run in order to find all packages that have an 'el7' in the release key?
Here's what I've tried so far:
vars:
example_query1: "[?contains(release, 'el7')]"
example_query2: "[?release == '*el7*']"
tasks:
new_package_list: "{{ ansible_facts.packages | json_query(example_query) | list }}"
A quick (and dirty) variant with Ansible and Jinja2 filter techniques is as follows:
- name: Grab all packages with el7 releases
set_fact:
el7_packages: "{{ el7_packages | default({}) | combine(new_item | items2dict) }}"
with_dict: "{{ ansible_facts.packages }}"
loop_control:
label: "{{ item.key }}"
vars:
el7_releases: "{{ item.value | map(attribute='release') | select('search', 'el7') }}"
new_item:
- key: "{{ item.key }}"
value: "{{ el7_releases }}"
when: el7_releases | list | length
- name: Print found el7 packages
debug:
var: el7_packages
you iterate over each entry of the dict
with_dict: "{{ ansible_facts.packages }}"
you reduce the list of dicts to the release
value and then filter the list by el7
el7_releases: "{{ item.value | map(attribute='release') | select('search', 'el7') }}"
only if a release with el7
exists, the package with its el7
releases is saved in the target dict el7_packages
el7
release exists)when: el7_releases | list | length
set_fact
with el7_packages: "{{ el7_packages | default({}) | combine(new_item | items2dict) }}"
the result is a dict, the keys are the package names, the values are lists of release strings containing el7
Notes:
loop_control
with label
is only for cosmetics in the terminalnew_item
) is prepared as an array and converted into a dict via items2dict
before combiningResult:
TASK [Grab all packages with el7 releases] *********************
ok: [localhost] => (item=zlib)
ok: [localhost] => (item=other_pkg)
skipping: [localhost] => (item=an_other_tool)
TASK [Print found el7 packages] ********************************
ok: [localhost] => {
"el7_packages": {
"other_pkg": [
"11.el7"
],
"zlib": [
"11.el7",
"10.el7"
]
}
}
Edit:
To get the whole dict as a result, instead of just the release
string, only a minimal change of the variable assignment for el7_releases
is required:
el7_releases: "{{ item.value | selectattr('release', 'search', 'el7') }}"
Code:
- name: Grab all packages with el7 releases
set_fact:
el7_packages: "{{ el7_packages | default({}) | combine(new_item | items2dict) }}"
with_dict: "{{ ansible_facts.packages }}"
loop_control:
label: "{{ item.key }}"
vars:
el7_releases: "{{ item.value | selectattr('release', 'search', 'el7') }}"
new_item:
- key: "{{ item.key }}"
value: "{{ el7_releases }}"
when: el7_releases | list | length
- name: Print found el7 packages
debug:
var: el7_packages
Reslut:
TASK [Grab all packages with el7 releases] ****************************
ok: [localhost] => (item=zlib)
ok: [localhost] => (item=other_pkg)
skipping: [localhost] => (item=an_other_tool)
TASK [Print found el7 packages] ***************************************
ok: [localhost] => {
"el7_packages": {
"other_pkg": [
{
"arch": "x86_64",
"epoch": null,
"release": "11.el7",
"source": "rpm",
"version": "1.2.7"
}
],
"zlib": [
{
"arch": "x86_64",
"epoch": null,
"release": "11.el7",
"source": "rpm",
"version": "1.2.7"
},
{
"arch": "x86_64",
"epoch": null,
"release": "10.el7",
"source": "rpm",
"version": "1.2.6"
}
]
}
}
example input data:
packages:
zlib:
- arch: "x86_64"
epoch: null
release: "11.el7"
source: "rpm"
version: "1.2.7"
- arch: "x86_64"
epoch: null
release: "10.el7"
source: "rpm"
version: "1.2.6"
- arch: "x86_64"
epoch: null
release: "10.el8"
source: "rpm"
version: "1.2.7"
other_pkg:
- arch: "x86_64"
epoch: null
release: "11.el7"
source: "rpm"
version: "1.2.7"
- arch: "x86_64"
epoch: null
release: "10.el8"
source: "rpm"
version: "1.2.7"
an_other_tool:
- arch: "x86_64"
epoch: null
release: "10.el8"
source: "rpm"
version: "1.2.7"