mirror of
https://github.com/saltstack/salt.git
synced 2025-04-17 10:10:20 +00:00
Merge pull request #32243 from isbm/isbm-zypper-list-installed-ensure-latest
Ensure latest pkg.info_installed ensure latest
This commit is contained in:
commit
3e374e7ec6
6 changed files with 117 additions and 107 deletions
|
@ -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)
|
||||
|
|
|
@ -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):
|
||||
|
|
|
@ -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
|
||||
|
@ -346,40 +340,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
|
||||
|
@ -394,23 +354,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):
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
Loading…
Add table
Reference in a new issue