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 }}"
3
Answers
A quick (and dirty) variant with Ansible and Jinja2 filter techniques is as follows:
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 byel7
el7_releases: "{{ item.value | map(attribute='release') | select('search', 'el7') }}"
only if a release with
el7
exists, the package with itsel7
releases is saved in the target dictel7_packages
el7
release exists)when: el7_releases | list | length
set_fact
withel7_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
withlabel
is only for cosmetics in the terminalnew_item
) is prepared as an array and converted into a dict viaitems2dict
before combiningMy example input data:
Result:
Q: "Instead of just the package release information, what if I wanted the entire package information? Like the
name
,version
,release
,arch
, etc. would something like that be possible for the RHEL 7 packages once they’re found? … As in the filter is theel7
in therelease
, but the capture I want is the entire package information."Based on the already given good answer, a only slightly changed minimal example playbook
will output all 9.2 packages on a 9.5 system
In order to gain more performance one could focus next on combining these two
into one, generate a list before and instead of test when on list elements.
Get the keys, select the matching items in the lists, and create the dictionary
gives
Example of a complete playbook for testing