56c946e70f
- Prevent crash if pygit2 package requests recompilation. Add: * 0013-Prevent-crash-if-pygit2-package-is-requesting-re-com.patch - Align OS grains from older SLES with the current one (bsc#975757) Add: * 0014-align-OS-grains-from-older-SLES-with-current-one-326.patch - remove patches which produce duplicate functions: Remove: * 0004-implement-version_cmp-for-zypper.patch * 0005-pylint-changes.patch * 0006-Check-if-rpm-python-can-be-imported.patch - remove patches which add and revert the same file Remove: * 0007-Initial-Zypper-Unit-Tests-and-bugfixes.patch * 0009-Bugfix-on-SLE11-series-base-product-reported-as-addi.patch - rename patches: 0008-do-not-generate-a-date-in-a-comment-to-prevent-rebui.patch to 0004-do-not-generate-a-date-in-a-comment-to-prevent-rebui.patch 0010-Use-SHA256-hash-type-by-default.patch to 0005-Use-SHA256-hash-type-by-default.patch 0011-Update-to-2015.8.8.2.patch to 0006-Update-to-2015.8.8.2.patch 0012-Force-sort-the-RPM-output-to-ensure-latest-version-o.patch to 0007-Force-sort-the-RPM-output-to-ensure-latest-version-o.patch 0013-Cleaner-deprecation-process-with-decorators.patch to 0008-Cleaner-deprecation-process-with-decorators.patch - fix sorting by latest package Add: * 0009-fix-sorting-by-latest-version-when-called-with-an-at.patch - Prevent metadata download when getting installed products Add: * 0010-Prevent-metadata-download-when-getting-installed-pro.patch - Check if EOL is available in a particular product (bsc#975093) Add: * 0011-Check-if-EOL-is-available-in-a-particular-product-bs.patch - Bugfix: salt-key crashes if tries to generate keys to the directory w/o write access (bsc#969320) Add: * 0012-Bugfix-salt-key-crashes-if-tries-to-generate-keys-to.patch - Deprecation process using decorators and re-implementation of status.update function. Add: * 0013-Cleaner-deprecation-process-with-decorators.patch - Reverted the fake 2015.8.8.2 patch, with the right one, - this patch only contains: - https://github.com/saltstack/salt/pull/32135 - https://github.com/saltstack/salt/pull/32023 - https://github.com/saltstack/salt/pull/32117 - Ensure that in case of multi-packages installed on the system, the latest is reported by pkg.info_installed (bsc#972490) Add: * 0012-Force-sort-the-RPM-output-to-ensure-latest-version-o.patch - Update to the fake 2015.8.8.2 release upstream released a bunch of fixes on top of 2015.8.8, without creating a new tag and proper release. This commit includes all the changes between tag v2015.8.8 and commit ID 596444e2b447b7378dbcdfeb9fc9610b90057745 which introduces the fake 2015.8.8.2 release. see https://docs.saltstack.com/en/latest/topics/releases/2015.8.8.html#salt-2015-8-8-2 - Update to 2015.8.8 see https://docs.saltstack.com/en/latest/topics/releases/2015.8.8.html Patches renamed: * 0004-implement-version_cmp-for-zypper.patch * 0005-pylint-changes.patch * 0006-Check-if-rpm-python-can-be-imported.patch * 0007-Initial-Zypper-Unit-Tests-and-bugfixes.patch * 0008-do-not-generate-a-date-in-a-comment-to-prevent-rebui.patch * 0009-Bugfix-on-SLE11-series-base-product-reported-as-addi.patch * 0010-Use-SHA256-hash-type-by-default.patch Patches removed: * 0004-Fix-pkg.latest-prevent-crash-on-multiple-package-ins.patch * 0005-Fix-package-status-filtering-on-latest-version-and-i.patch * 0006-add_key-reject_key-do-not-crash-w-Permission-denied-.patch * 0007-Force-kill-websocket-s-child-processes-faster-than-d.patch * 0008-Fix-types-in-the-output-data-and-return-just-a-list-.patch * 0009-The-functions-in-the-state-module-that-return-a-retc.patch * 0010-add-handling-for-OEM-products.patch * 0011-improve-doc-for-list_pkgs.patch * 0012-implement-version_cmp-for-zypper.patch * 0013-pylint-changes.patch * 0014-Check-if-rpm-python-can-be-imported.patch * 0015-call-zypper-with-option-non-interactive-everywhere.patch * 0016-write-a-zypper-command-builder-function.patch * 0017-Fix-crash-with-scheduler-and-runners-31106.patch * 0018-unify-behavior-of-refresh.patch * 0019-add-refresh-option-to-more-functions.patch * 0020-simplify-checking-the-refresh-paramater.patch * 0021-do-not-change-kwargs-in-refresh-while-checking-a-val.patch * 0022-fix-argument-handling-for-pkg.download.patch * 0023-Initial-Zypper-Unit-Tests-and-bugfixes.patch * 0024-proper-checking-if-zypper-exit-codes-and-handling-of.patch * 0025-adapt-tests-to-new-zypper_check_result-output.patch * 0026-do-not-generate-a-date-in-a-comment-to-prevent-rebui.patch * 0027-make-suse-check-consistent-with-rh_service.patch * 0028-fix-numerical-check-of-osrelease.patch * 0029-Make-use-of-checksum-configurable-defaults-to-MD5-SH.patch * 0030-Bugfix-on-SLE11-series-base-product-reported-as-addi.patch * 0031-Only-use-LONGSIZE-in-rpm.info-if-available.-Otherwis.patch * 0032-Add-error-check-when-retcode-is-0-but-stderr-is-pres.patch * 0033-fixing-init-system-dectection-on-sles-11-refs-31617.patch * 0034-Fix-git_pillar-race-condition.patch * 0035-Fix-the-always-false-behavior-on-checking-state.patch * 0036-Use-SHA256-hash-type-by-default.patch OBS-URL: https://build.opensuse.org/request/show/391560 OBS-URL: https://build.opensuse.org/package/show/systemsmanagement:saltstack/salt?expand=0&rev=66
351 lines
12 KiB
Diff
351 lines
12 KiB
Diff
From e3a599712daafb88b6b77ebf6c7684fdd10ffedf Mon Sep 17 00:00:00 2001
|
|
From: Bo Maryniuk <bo@suse.de>
|
|
Date: Wed, 30 Mar 2016 12:14:21 +0200
|
|
Subject: [PATCH 07/12] Force-sort the RPM output to ensure latest version of
|
|
the multi-package on top of the list.
|
|
|
|
- Remove version_cmp from the yumpkg and use just a lowpkg alias
|
|
- Remove version_cmp from Zypper module and use just lowpkg alias
|
|
- Merge yumpkg's and zypper's version_cmp for a common use
|
|
- Sort installed pkgs data by version_cmp
|
|
- Move "string to EVR" function to the utilities
|
|
- Remove suse/redhat checks, refactor code.
|
|
- Fix condition from returning None on 0
|
|
- Remove tests from the zypper_test that belongs to rpm_test
|
|
- Add lowpkg tests for version comparison
|
|
- Fix lint
|
|
- Fix the documentation
|
|
---
|
|
salt/modules/rpm.py | 60 +++++++++++++++++++++++++++++++++++++--
|
|
salt/modules/yumpkg.py | 28 ++----------------
|
|
salt/modules/zypper.py | 58 +------------------------------------
|
|
salt/utils/__init__.py | 35 +++++++++++++++++++++++
|
|
tests/unit/modules/rpm_test.py | 21 ++++++++++++++
|
|
tests/unit/modules/zypper_test.py | 22 --------------
|
|
6 files changed, 117 insertions(+), 107 deletions(-)
|
|
|
|
diff --git a/salt/modules/rpm.py b/salt/modules/rpm.py
|
|
index 5d60dd2..6026f18 100644
|
|
--- a/salt/modules/rpm.py
|
|
+++ b/salt/modules/rpm.py
|
|
@@ -17,6 +17,19 @@ import salt.utils.pkg.rpm
|
|
# pylint: disable=import-error,redefined-builtin
|
|
from salt.ext.six.moves import shlex_quote as _cmd_quote
|
|
from salt.ext.six.moves import zip
|
|
+
|
|
+try:
|
|
+ import rpm
|
|
+ HAS_RPM = True
|
|
+except ImportError:
|
|
+ HAS_RPM = False
|
|
+
|
|
+try:
|
|
+ import rpmUtils.miscutils
|
|
+ HAS_RPMUTILS = True
|
|
+except ImportError:
|
|
+ HAS_RPMUTILS = False
|
|
+
|
|
# pylint: enable=import-error,redefined-builtin
|
|
from salt.exceptions import CommandExecutionError, SaltInvocationError
|
|
|
|
@@ -491,7 +504,7 @@ def info(*packages, **attr):
|
|
else:
|
|
out = call['stdout']
|
|
|
|
- ret = dict()
|
|
+ _ret = list()
|
|
for pkg_info in re.split(r"----*", out):
|
|
pkg_info = pkg_info.strip()
|
|
if not pkg_info:
|
|
@@ -538,6 +551,49 @@ def info(*packages, **attr):
|
|
if attr and 'description' in attr or not attr:
|
|
pkg_data['description'] = os.linesep.join(descr)
|
|
if pkg_name:
|
|
- ret[pkg_name] = pkg_data
|
|
+ pkg_data['name'] = pkg_name
|
|
+ _ret.append(pkg_data)
|
|
+
|
|
+ # Force-sort package data by version,
|
|
+ # pick only latest versions
|
|
+ # (in case multiple packages installed, e.g. kernel)
|
|
+ ret = dict()
|
|
+ for pkg_data in reversed(sorted(_ret, cmp=lambda a_vrs, b_vrs: version_cmp(a_vrs['version'], b_vrs['version']))):
|
|
+ pkg_name = pkg_data.pop('name')
|
|
+ if pkg_name not in ret:
|
|
+ ret[pkg_name] = pkg_data.copy()
|
|
|
|
return ret
|
|
+
|
|
+
|
|
+def version_cmp(ver1, ver2):
|
|
+ '''
|
|
+ .. versionadded:: 2015.8.9
|
|
+
|
|
+ Do a cmp-style comparison on two packages. Return -1 if ver1 < ver2, 0 if
|
|
+ ver1 == ver2, and 1 if ver1 > ver2. Return None if there was a problem
|
|
+ making the comparison.
|
|
+
|
|
+ CLI Example:
|
|
+
|
|
+ .. code-block:: bash
|
|
+
|
|
+ salt '*' pkg.version_cmp '0.2-001' '0.2.0.1-002'
|
|
+ '''
|
|
+ try:
|
|
+ if HAS_RPM:
|
|
+ cmp_func = rpm.labelCompare
|
|
+ elif HAS_RPMUTILS:
|
|
+ cmp_func = rpmUtils.miscutils.compareEVR
|
|
+ else:
|
|
+ cmp_func = None
|
|
+ cmp_result = cmp_func is None and 2 or cmp_func(salt.utils.str_version_to_evr(ver1),
|
|
+ salt.utils.str_version_to_evr(ver2))
|
|
+ if cmp_result not in (-1, 0, 1):
|
|
+ raise Exception("Comparison result '{0}' is invalid".format(cmp_result))
|
|
+
|
|
+ return cmp_result
|
|
+ except Exception as exc:
|
|
+ log.warning("Failed to compare version '{0}' to '{1}' using RPM: {2}".format(ver1, ver2, exc))
|
|
+
|
|
+ return salt.utils.version_cmp(ver1, ver2)
|
|
diff --git a/salt/modules/yumpkg.py b/salt/modules/yumpkg.py
|
|
index 1bfc38d..1cde676 100644
|
|
--- a/salt/modules/yumpkg.py
|
|
+++ b/salt/modules/yumpkg.py
|
|
@@ -40,12 +40,6 @@ try:
|
|
except ImportError:
|
|
from salt.ext.six.moves import configparser
|
|
HAS_YUM = False
|
|
-
|
|
-try:
|
|
- import rpmUtils.miscutils
|
|
- HAS_RPMUTILS = True
|
|
-except ImportError:
|
|
- HAS_RPMUTILS = False
|
|
# pylint: enable=import-error,redefined-builtin
|
|
|
|
# Import salt libs
|
|
@@ -665,26 +659,8 @@ def version_cmp(pkg1, pkg2):
|
|
|
|
salt '*' pkg.version_cmp '0.2-001' '0.2.0.1-002'
|
|
'''
|
|
- if HAS_RPMUTILS:
|
|
- try:
|
|
- cmp_result = rpmUtils.miscutils.compareEVR(
|
|
- rpmUtils.miscutils.stringToVersion(pkg1),
|
|
- rpmUtils.miscutils.stringToVersion(pkg2)
|
|
- )
|
|
- if cmp_result not in (-1, 0, 1):
|
|
- raise Exception(
|
|
- 'cmp result \'{0}\' is invalid'.format(cmp_result)
|
|
- )
|
|
- return cmp_result
|
|
- except Exception as exc:
|
|
- log.warning(
|
|
- 'Failed to compare version \'%s\' to \'%s\' using '
|
|
- 'rpmUtils: %s', pkg1, pkg2, exc
|
|
- )
|
|
- # Fall back to distutils.version.LooseVersion (should only need to do
|
|
- # this for RHEL5, or if an exception is raised when attempting to compare
|
|
- # using rpmUtils)
|
|
- return salt.utils.version_cmp(pkg1, pkg2)
|
|
+
|
|
+ return __salt__['lowpkg.version_cmp'](pkg1, pkg2)
|
|
|
|
|
|
def list_pkgs(versions_as_list=False, **kwargs):
|
|
diff --git a/salt/modules/zypper.py b/salt/modules/zypper.py
|
|
index 27b00d5..63c473c 100644
|
|
--- a/salt/modules/zypper.py
|
|
+++ b/salt/modules/zypper.py
|
|
@@ -17,12 +17,6 @@ import os
|
|
import salt.ext.six as six
|
|
from salt.ext.six.moves import configparser
|
|
from salt.ext.six.moves.urllib.parse import urlparse as _urlparse
|
|
-
|
|
-try:
|
|
- import rpm
|
|
- HAS_RPM = True
|
|
-except ImportError:
|
|
- HAS_RPM = False
|
|
# pylint: enable=import-error,redefined-builtin,no-name-in-module
|
|
|
|
from xml.dom import minidom as dom
|
|
@@ -347,40 +341,6 @@ def version(*names, **kwargs):
|
|
return __salt__['pkg_resource.version'](*names, **kwargs) or {}
|
|
|
|
|
|
-def _string_to_evr(verstring):
|
|
- '''
|
|
- Split the version string into epoch, version and release and
|
|
- return this as tuple.
|
|
-
|
|
- epoch is always not empty.
|
|
- version and release can be an empty string if such a component
|
|
- could not be found in the version string.
|
|
-
|
|
- "2:1.0-1.2" => ('2', '1.0', '1.2)
|
|
- "1.0" => ('0', '1.0', '')
|
|
- "" => ('0', '', '')
|
|
- '''
|
|
- if verstring in [None, '']:
|
|
- return ('0', '', '')
|
|
- idx_e = verstring.find(':')
|
|
- if idx_e != -1:
|
|
- try:
|
|
- epoch = str(int(verstring[:idx_e]))
|
|
- except ValueError:
|
|
- # look, garbage in the epoch field, how fun, kill it
|
|
- epoch = '0' # this is our fallback, deal
|
|
- else:
|
|
- epoch = '0'
|
|
- idx_r = verstring.find('-')
|
|
- if idx_r != -1:
|
|
- version = verstring[idx_e + 1:idx_r]
|
|
- release = verstring[idx_r + 1:]
|
|
- else:
|
|
- version = verstring[idx_e + 1:]
|
|
- release = ''
|
|
- return (epoch, version, release)
|
|
-
|
|
-
|
|
def version_cmp(ver1, ver2):
|
|
'''
|
|
.. versionadded:: 2015.5.4
|
|
@@ -395,23 +355,7 @@ def version_cmp(ver1, ver2):
|
|
|
|
salt '*' pkg.version_cmp '0.2-001' '0.2.0.1-002'
|
|
'''
|
|
- if HAS_RPM:
|
|
- try:
|
|
- cmp_result = rpm.labelCompare(
|
|
- _string_to_evr(ver1),
|
|
- _string_to_evr(ver2)
|
|
- )
|
|
- if cmp_result not in (-1, 0, 1):
|
|
- raise Exception(
|
|
- 'cmp result \'{0}\' is invalid'.format(cmp_result)
|
|
- )
|
|
- return cmp_result
|
|
- except Exception as exc:
|
|
- log.warning(
|
|
- 'Failed to compare version \'{0}\' to \'{1}\' using '
|
|
- 'rpmUtils: {2}'.format(ver1, ver2, exc)
|
|
- )
|
|
- return salt.utils.version_cmp(ver1, ver2)
|
|
+ return __salt__['lowpkg.version_cmp'](ver1, ver2)
|
|
|
|
|
|
def list_pkgs(versions_as_list=False, **kwargs):
|
|
diff --git a/salt/utils/__init__.py b/salt/utils/__init__.py
|
|
index f83a677..8956a15 100644
|
|
--- a/salt/utils/__init__.py
|
|
+++ b/salt/utils/__init__.py
|
|
@@ -2881,3 +2881,38 @@ def split_input(val):
|
|
return [x.strip() for x in val.split(',')]
|
|
except AttributeError:
|
|
return [x.strip() for x in str(val).split(',')]
|
|
+
|
|
+
|
|
+def str_version_to_evr(verstring):
|
|
+ '''
|
|
+ Split the package version string into epoch, version and release.
|
|
+ Return this as tuple.
|
|
+
|
|
+ The epoch is always not empty. The version and the release can be an empty
|
|
+ string if such a component could not be found in the version string.
|
|
+
|
|
+ "2:1.0-1.2" => ('2', '1.0', '1.2)
|
|
+ "1.0" => ('0', '1.0', '')
|
|
+ "" => ('0', '', '')
|
|
+ '''
|
|
+ if verstring in [None, '']:
|
|
+ return '0', '', ''
|
|
+
|
|
+ idx_e = verstring.find(':')
|
|
+ if idx_e != -1:
|
|
+ try:
|
|
+ epoch = str(int(verstring[:idx_e]))
|
|
+ except ValueError:
|
|
+ # look, garbage in the epoch field, how fun, kill it
|
|
+ epoch = '0' # this is our fallback, deal
|
|
+ else:
|
|
+ epoch = '0'
|
|
+ idx_r = verstring.find('-')
|
|
+ if idx_r != -1:
|
|
+ version = verstring[idx_e + 1:idx_r]
|
|
+ release = verstring[idx_r + 1:]
|
|
+ else:
|
|
+ version = verstring[idx_e + 1:]
|
|
+ release = ''
|
|
+
|
|
+ return epoch, version, release
|
|
diff --git a/tests/unit/modules/rpm_test.py b/tests/unit/modules/rpm_test.py
|
|
index 8bfce9b..f180736 100644
|
|
--- a/tests/unit/modules/rpm_test.py
|
|
+++ b/tests/unit/modules/rpm_test.py
|
|
@@ -95,6 +95,27 @@ class RpmTestCase(TestCase):
|
|
self.assertDictEqual(rpm.owner('/usr/bin/python', '/usr/bin/vim'),
|
|
ret)
|
|
|
|
+ @patch('salt.modules.rpm.HAS_RPM', True)
|
|
+ def test_version_cmp_rpm(self):
|
|
+ '''
|
|
+ Test package version is called RPM version if RPM-Python is installed
|
|
+
|
|
+ :return:
|
|
+ '''
|
|
+ rpm.rpm = MagicMock(return_value=MagicMock)
|
|
+ with patch('salt.modules.rpm.rpm.labelCompare', MagicMock(return_value=0)):
|
|
+ self.assertEqual(0, rpm.version_cmp('1', '2')) # mock returns 0, which means RPM was called
|
|
+
|
|
+ @patch('salt.modules.rpm.HAS_RPM', False)
|
|
+ def test_version_cmp_fallback(self):
|
|
+ '''
|
|
+ Test package version is called RPM version if RPM-Python is installed
|
|
+
|
|
+ :return:
|
|
+ '''
|
|
+ rpm.rpm = MagicMock(return_value=MagicMock)
|
|
+ with patch('salt.modules.rpm.rpm.labelCompare', MagicMock(return_value=0)):
|
|
+ self.assertEqual(-1, rpm.version_cmp('1', '2')) # mock returns -1, a python implementation was called
|
|
|
|
if __name__ == '__main__':
|
|
from integration import run_tests
|
|
diff --git a/tests/unit/modules/zypper_test.py b/tests/unit/modules/zypper_test.py
|
|
index 5c4eb67..67cf52a 100644
|
|
--- a/tests/unit/modules/zypper_test.py
|
|
+++ b/tests/unit/modules/zypper_test.py
|
|
@@ -301,28 +301,6 @@ class ZypperTestCase(TestCase):
|
|
self.assertFalse(zypper.upgrade_available(pkg_name))
|
|
self.assertTrue(zypper.upgrade_available('vim'))
|
|
|
|
- @patch('salt.modules.zypper.HAS_RPM', True)
|
|
- def test_version_cmp_rpm(self):
|
|
- '''
|
|
- Test package version is called RPM version if RPM-Python is installed
|
|
-
|
|
- :return:
|
|
- '''
|
|
- with patch('salt.modules.zypper.rpm', MagicMock(return_value=MagicMock)):
|
|
- with patch('salt.modules.zypper.rpm.labelCompare', MagicMock(return_value=0)):
|
|
- self.assertEqual(0, zypper.version_cmp('1', '2')) # mock returns 0, which means RPM was called
|
|
-
|
|
- @patch('salt.modules.zypper.HAS_RPM', False)
|
|
- def test_version_cmp_fallback(self):
|
|
- '''
|
|
- Test package version is called RPM version if RPM-Python is installed
|
|
-
|
|
- :return:
|
|
- '''
|
|
- with patch('salt.modules.zypper.rpm', MagicMock(return_value=MagicMock)):
|
|
- with patch('salt.modules.zypper.rpm.labelCompare', MagicMock(return_value=0)):
|
|
- self.assertEqual(-1, zypper.version_cmp('1', '2')) # mock returns -1, a python implementation was called
|
|
-
|
|
def test_list_pkgs(self):
|
|
'''
|
|
Test packages listing.
|
|
--
|
|
2.1.4
|
|
|