diff options
author | Sloane Hertel <19572925+s-hertel@users.noreply.github.com> | 2021-08-06 16:56:41 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-08-06 13:56:41 -0700 |
commit | 081a93caa36df4b353d14395276c07a17061f8e5 (patch) | |
tree | 8bf1c5853e2e42d1b4874f381839bccfbd22a7c7 | |
parent | e9bc4742084879ed11d955b7ae4eca6fa34febe3 (diff) | |
download | ansible-081a93caa36df4b353d14395276c07a17061f8e5.tar.gz |
[2.9] Fix dnf package matching (#75411) (#75416)
* Fix dnf package matching (#75411)
* Fix a bug with the dnf module not using all components of a package name when filtering to determine if it's installed
* changelog
* Simplify splitting on the last '.'
* Update lib/ansible/modules/dnf.py
(cherry picked from commit b541a148d51e75b298e71161c022b12cd8ebba7c)
* Fix dnf test assertion
(cherry picked from commit 91a26ddcefb393e48ac93d442b3922bf2fde0de7)
-rw-r--r-- | changelogs/fragments/fix-dnf-filtering-for-installed-package-name.yml | 2 | ||||
-rw-r--r-- | lib/ansible/modules/packaging/os/dnf.py | 48 | ||||
-rw-r--r-- | test/integration/targets/dnf/tasks/filters.yml | 28 |
3 files changed, 62 insertions, 16 deletions
diff --git a/changelogs/fragments/fix-dnf-filtering-for-installed-package-name.yml b/changelogs/fragments/fix-dnf-filtering-for-installed-package-name.yml new file mode 100644 index 0000000000..f8a788a992 --- /dev/null +++ b/changelogs/fragments/fix-dnf-filtering-for-installed-package-name.yml @@ -0,0 +1,2 @@ +bugfixes: + - dnf module - Use all components of a package name to determine if it's installed (https://github.com/ansible/ansible/issues/75311). diff --git a/lib/ansible/modules/packaging/os/dnf.py b/lib/ansible/modules/packaging/os/dnf.py index 1829f36712..cc75ad0637 100644 --- a/lib/ansible/modules/packaging/os/dnf.py +++ b/lib/ansible/modules/packaging/os/dnf.py @@ -390,15 +390,7 @@ class DnfModule(YumDnf): return result - def _packagename_dict(self, packagename): - """ - Return a dictionary of information for a package name string or None - if the package name doesn't contain at least all NVR elements - """ - - if packagename[-4:] == '.rpm': - packagename = packagename[:-4] - + def _split_package_arch(self, packagename): # This list was auto generated on a Fedora 28 system with the following one-liner # printf '[ '; for arch in $(ls /usr/lib/rpm/platform); do printf '"%s", ' ${arch%-linux}; done; printf ']\n' redhat_rpm_arches = [ @@ -413,15 +405,26 @@ class DnfModule(YumDnf): "sparc", "sparcv8", "sparcv9", "sparcv9v", "x86_64" ] - rpm_arch_re = re.compile(r'(.*)\.(.*)') + name, delimiter, arch = packagename.rpartition('.') + if name and arch and arch in redhat_rpm_arches: + return name, arch + return packagename, None + + def _packagename_dict(self, packagename): + """ + Return a dictionary of information for a package name string or None + if the package name doesn't contain at least all NVR elements + """ + + if packagename[-4:] == '.rpm': + packagename = packagename[:-4] + rpm_nevr_re = re.compile(r'(\S+)-(?:(\d*):)?(.*)-(~?\w+[\w.+]*)') try: arch = None - rpm_arch_match = rpm_arch_re.match(packagename) - if rpm_arch_match: - nevr, arch = rpm_arch_match.groups() - if arch in redhat_rpm_arches: - packagename = nevr + nevr, arch = self._split_package_arch(packagename) + if arch: + packagename = nevr rpm_nevr_match = rpm_nevr_re.match(packagename) if rpm_nevr_match: name, epoch, version, release = rpm_nevr_re.match(packagename).groups() @@ -709,7 +712,20 @@ class DnfModule(YumDnf): def _is_installed(self, pkg): installed = self.base.sack.query().installed() - if installed.filter(name=pkg): + + package_spec = {} + name, arch = self._split_package_arch(pkg) + if arch: + package_spec['arch'] = arch + + package_details = self._packagename_dict(pkg) + if package_details: + package_details['epoch'] = int(package_details['epoch']) + package_spec.update(package_details) + else: + package_spec['name'] = name + + if installed.filter(**package_spec): return True else: return False diff --git a/test/integration/targets/dnf/tasks/filters.yml b/test/integration/targets/dnf/tasks/filters.yml index d5e9ee906b..2bff25bcd3 100644 --- a/test/integration/targets/dnf/tasks/filters.yml +++ b/test/integration/targets/dnf/tasks/filters.yml @@ -98,6 +98,19 @@ allow_downgrade: true disable_gpg_check: true + - name: Verify toaster is not upgraded with state=installed + dnf: + name: "{{ item }}" + state: installed + register: installed + loop: + - toaster + - toaster.noarch + - toaster-1.2.3.4-1.el8.noarch + + - assert: + that: "installed.results | map(attribute='changed') is not any" + - name: Ask for pending updates with bugfix=true and security=true dnf: name: '*' @@ -118,6 +131,21 @@ - '"Installed: oven-1.2.3.5-1.el8.noarch" in update_bugfix.results' - '"Removed: oven-1.2.3.4-1.el8.noarch" in update_bugfix.results' + - name: Install old version of toaster again + dnf: + name: "{{ updateinfo_repo }}/toaster-1.2.3.4-1.el8.noarch.rpm" + allow_downgrade: true + disable_gpg_check: true + + - name: Verify toaster is upgraded with state=latest + dnf: + name: toaster.noarch + state: latest + register: result + + - assert: + that: result.changed + always: - name: Remove installed packages dnf: |