summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSloane Hertel <19572925+s-hertel@users.noreply.github.com>2021-08-06 16:56:41 -0400
committerGitHub <noreply@github.com>2021-08-06 13:56:41 -0700
commit081a93caa36df4b353d14395276c07a17061f8e5 (patch)
tree8bf1c5853e2e42d1b4874f381839bccfbd22a7c7
parente9bc4742084879ed11d955b7ae4eca6fa34febe3 (diff)
downloadansible-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.yml2
-rw-r--r--lib/ansible/modules/packaging/os/dnf.py48
-rw-r--r--test/integration/targets/dnf/tasks/filters.yml28
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: