From 5e7edfccfaf4d20f7463dd1e377e8dd0f36e791f Mon Sep 17 00:00:00 2001 From: Erik Johnson Date: Mon, 18 Apr 2016 10:03:06 -0500 Subject: [PATCH] yumpkg: Ignore epoch in version comparison for explict versions without an epoch (#32563) * yumpkg: Ignore epoch in version comparison for explict versions without an epoch Also properly handle comparisions for packages with multiple versions. Resolves #32229 * Don't attempt downgrade for kernel and its subpackages Multiple versions are supported since their paths do not conflict. --- salt/modules/yumpkg.py | 67 ++++++++++++++++++++++++++++++++---------- 1 file changed, 52 insertions(+), 15 deletions(-) diff --git a/salt/modules/yumpkg.py b/salt/modules/yumpkg.py index 3d84e41a7f..369aead9bf 100644 --- a/salt/modules/yumpkg.py +++ b/salt/modules/yumpkg.py @@ -1229,7 +1229,10 @@ def install(name=None, log.warning('"version" parameter will be ignored for multiple ' 'package targets') - old = list_pkgs() + old = list_pkgs(versions_as_list=False) + # Use of __context__ means no duplicate work here, just accessing + # information already in __context__ from the previous call to list_pkgs() + old_as_list = list_pkgs(versions_as_list=True) targets = [] downgrade = [] to_reinstall = {} @@ -1301,20 +1304,54 @@ def install(name=None, else: pkgstr = pkgpath - cver = old.get(pkgname, '') - if reinstall and cver \ - and salt.utils.compare_versions(ver1=version_num, - oper='==', - ver2=cver, - cmp_func=version_cmp): - to_reinstall[pkgname] = pkgstr - elif not cver or salt.utils.compare_versions(ver1=version_num, - oper='>=', - ver2=cver, - cmp_func=version_cmp): - targets.append(pkgstr) + # Lambda to trim the epoch from the currently-installed version if + # no epoch is specified in the specified version + norm_epoch = lambda x, y: x.split(':', 1)[-1] \ + if ':' not in y \ + else x + cver = old_as_list.get(pkgname, []) + if reinstall and cver: + for ver in cver: + ver = norm_epoch(ver, version_num) + if salt.utils.compare_versions(ver1=version_num, + oper='==', + ver2=ver, + cmp_func=version_cmp): + # This version is already installed, so we need to + # reinstall. + to_reinstall[pkgname] = pkgstr + break else: - downgrade.append(pkgstr) + if not cver: + targets.append(pkgstr) + else: + for ver in cver: + ver = norm_epoch(ver, version_num) + if salt.utils.compare_versions(ver1=version_num, + oper='>=', + ver2=ver, + cmp_func=version_cmp): + targets.append(pkgstr) + break + else: + if re.match('kernel(-.+)?', name): + # kernel and its subpackages support multiple + # installs as their paths do not conflict. + # Performing a yum/dnf downgrade will be a no-op + # so just do an install instead. It will fail if + # there are other interdependencies that have + # conflicts, and that's OK. We don't want to force + # anything, we just want to properly handle it if + # someone tries to install a kernel/kernel-devel of + # a lower version than the currently-installed one. + # TODO: find a better way to determine if a package + # supports multiple installs. + targets.append(pkgstr) + else: + # None of the currently-installed versions are + # greater than the specified version, so this is a + # downgrade. + downgrade.append(pkgstr) def _add_common_args(cmd): ''' @@ -1365,7 +1402,7 @@ def install(name=None, ) __context__.pop('pkg.list_pkgs', None) - new = list_pkgs() + new = list_pkgs(versions_as_list=False) ret = salt.utils.compare_dicts(old, new)