Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
systemsmanagement:Uyuni:Master:CentOS6-Uyuni-Client-Tools
salt
list_pkgs-add-parameter-for-returned-attribute-...
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File list_pkgs-add-parameter-for-returned-attribute-selec.patch of Package salt
From da286898ffc6a7c25f9219cd31474cff84f1cf27 Mon Sep 17 00:00:00 2001 From: Silvio Moioli <smoioli@suse.de> Date: Thu, 13 Jul 2017 15:59:01 +0200 Subject: [PATCH] list_pkgs: add parameter for returned attribute selection (bsc#1052264) zypper.list_pkgs: * It adds a new optional parameter to list_pkg in the zypper module to return more data than the version (original reason is that for SUSE Manager integration we also need arch and install_date). Format is the same of existing method info_installed. yumpkg.list_pkgs: * It adds a new optional parameter to list_pkg, originally added to the the zypper module via PR #42310, to yumpkg providing the same functionality and interface to the yum package manager. --- salt/modules/pkg_resource.py | 41 +++++++ salt/modules/yumpkg.py | 101 ++++++++++++---- salt/modules/zypper.py | 105 +++++++++++------ salt/utils/pkg/rpm.py | 24 ++-- tests/unit/modules/test_yumpkg.py | 190 ++++++++++++++++++++++++++++++ tests/unit/modules/zypper_test.py | 109 +++++++++++++---- 6 files changed, 482 insertions(+), 88 deletions(-) create mode 100644 tests/unit/modules/test_yumpkg.py diff --git a/salt/modules/pkg_resource.py b/salt/modules/pkg_resource.py index 928dccae7d..248eef8505 100644 --- a/salt/modules/pkg_resource.py +++ b/salt/modules/pkg_resource.py @@ -5,6 +5,7 @@ Resources needed by pkg providers # Import python libs from __future__ import absolute_import +import copy import fnmatch import logging import os @@ -306,3 +307,43 @@ def check_extra_requirements(pkgname, pkgver): return __salt__['pkg.check_extra_requirements'](pkgname, pkgver) return True + + +def format_pkg_list(packages, versions_as_list, attr): + ''' + Formats packages according to parameters for list_pkgs. + ''' + ret = copy.deepcopy(packages) + if attr: + requested_attr = set(['epoch', 'version', 'release', 'arch', + 'install_date', 'install_date_time_t']) + + if attr != 'all': + requested_attr &= set(attr + ['version']) + + for name in ret: + versions = [] + for all_attr in ret[name]: + filtered_attr = {} + for key in requested_attr: + if all_attr[key]: + filtered_attr[key] = all_attr[key] + versions.append(filtered_attr) + ret[name] = versions + return ret + + for name in ret: + ret[name] = [format_version(d['epoch'], d['version'], d['release']) + for d in ret[name]] + if not versions_as_list: + stringify(ret) + return ret + +def format_version(epoch, version, release): + ''' + Formats a version string for list_pkgs. + ''' + full_version = '{0}:{1}'.format(epoch, version) if epoch else version + if release: + full_version += '-{0}'.format(release) + return full_version diff --git a/salt/modules/yumpkg.py b/salt/modules/yumpkg.py index 97a29fef90..20a6484c26 100644 --- a/salt/modules/yumpkg.py +++ b/salt/modules/yumpkg.py @@ -17,7 +17,6 @@ Support for YUM/DNF # Import python libs from __future__ import absolute_import import contextlib -import copy import datetime import fnmatch import itertools @@ -595,15 +594,35 @@ def version_cmp(pkg1, pkg2, ignore_epoch=False): def list_pkgs(versions_as_list=False, **kwargs): ''' - List the packages currently installed in a dict:: + List the packages currently installed as a dict. By default, the dict + contains versions as a comma separated string:: - {'<package_name>': '<version>'} + {'<package_name>': '<version>[,<version>...]'} + + versions_as_list: + If set to true, the versions are provided as a list + + {'<package_name>': ['<version>', '<version>']} + + attr: + If a list of package attributes is specified, returned value will + contain them in addition to version, eg.:: + + {'<package_name>': [{'version' : 'version', 'arch' : 'arch'}]} + + Valid attributes are: ``epoch``, ``version``, ``release``, ``arch``, + ``install_date``, ``install_date_time_t``. + + If ``all`` is specified, all valid attributes will be returned. + + .. versionadded:: Oxygen CLI Example: .. code-block:: bash salt '*' pkg.list_pkgs + salt '*' pkg.list_pkgs attr='["version", "arch"]' ''' versions_as_list = salt.utils.is_true(versions_as_list) # not yet implemented or not applicable @@ -611,17 +630,14 @@ def list_pkgs(versions_as_list=False, **kwargs): for x in ('removed', 'purge_desired')]): return {} + attr = kwargs.get("attr") if 'pkg.list_pkgs' in __context__: - if versions_as_list: - return __context__['pkg.list_pkgs'] - else: - ret = copy.deepcopy(__context__['pkg.list_pkgs']) - __salt__['pkg_resource.stringify'](ret) - return ret + cached = __context__['pkg.list_pkgs'] + return __salt__['pkg_resource.format_pkg_list'](cached, versions_as_list, attr) ret = {} cmd = ['rpm', '-qa', '--queryformat', - salt.utils.pkg.rpm.QUERYFORMAT.replace('%{REPOID}', '(none)\n')] + salt.utils.pkg.rpm.QUERYFORMAT.replace('%{REPOID}', '(none)') + '\n'] output = __salt__['cmd.run'](cmd, python_shell=False, output_loglevel='trace') @@ -631,15 +647,25 @@ def list_pkgs(versions_as_list=False, **kwargs): osarch=__grains__['osarch'] ) if pkginfo is not None: - __salt__['pkg_resource.add_pkg'](ret, - pkginfo.name, - pkginfo.version) - - __salt__['pkg_resource.sort_pkglist'](ret) - __context__['pkg.list_pkgs'] = copy.deepcopy(ret) - if not versions_as_list: - __salt__['pkg_resource.stringify'](ret) - return ret + # see rpm version string rules available at https://goo.gl/UGKPNd + pkgver = pkginfo.version + epoch = '' + release = '' + if ':' in pkgver: + epoch, pkgver = pkgver.split(":", 1) + if '-' in pkgver: + pkgver, release = pkgver.split("-", 1) + all_attr = {'epoch': epoch, 'version': pkgver, 'release': release, + 'arch': pkginfo.arch, 'install_date': pkginfo.install_date, + 'install_date_time_t': pkginfo.install_date_time_t} + __salt__['pkg_resource.add_pkg'](ret, pkginfo.name, all_attr) + + for pkgname in ret: + ret[pkgname] = sorted(ret[pkgname], key=lambda d: d['version']) + + __context__['pkg.list_pkgs'] = ret + + return __salt__['pkg_resource.format_pkg_list'](ret, versions_as_list, attr) def list_repo_pkgs(*args, **kwargs): @@ -1114,11 +1140,42 @@ def install(name=None, .. versionadded:: 2014.7.0 + diff_attr: + If a list of package attributes is specified, returned value will + contain them, eg.:: + + {'<package>': { + 'old': { + 'version': '<old-version>', + 'arch': '<old-arch>'}, + + 'new': { + 'version': '<new-version>', + 'arch': '<new-arch>'}}} + + Valid attributes are: ``epoch``, ``version``, ``release``, ``arch``, + ``install_date``, ``install_date_time_t``. + + If ``all`` is specified, all valid attributes will be returned. + + .. versionadded:: Oxygen Returns a dict containing the new package names and versions:: {'<package>': {'old': '<old-version>', 'new': '<new-version>'}} + + If an attribute list in diff_attr is specified, the dict will also contain + any specified attribute, eg.:: + + {'<package>': { + 'old': { + 'version': '<old-version>', + 'arch': '<old-arch>'}, + + 'new': { + 'version': '<new-version>', + 'arch': '<new-arch>'}}} ''' repo_arg = _get_repo_options(**kwargs) exclude_arg = _get_excludes_option(**kwargs) @@ -1148,10 +1205,10 @@ def install(name=None, log.warning('"version" parameter will be ignored for multiple ' 'package targets') - + diff_attr = kwargs.get("diff_attr") # 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) if not downloadonly else list_downloaded() + old_as_list = list_pkgs(versions_as_list=True, attr=diff_attr) if not downloadonly else list_downloaded() to_install = [] to_downgrade = [] @@ -1436,7 +1493,7 @@ def install(name=None, errors.append(out['stdout']) __context__.pop('pkg.list_pkgs', None) - new = list_pkgs(versions_as_list=False) if not downloadonly else list_downloaded() + new = list_pkgs(versions_as_list=False, attr=diff_attr) if not downloadonly else list_downloaded() ret = salt.utils.compare_dicts(old, new) diff --git a/salt/modules/zypper.py b/salt/modules/zypper.py index 7345e3deb9..fe45cee4de 100644 --- a/salt/modules/zypper.py +++ b/salt/modules/zypper.py @@ -14,7 +14,6 @@ Package support for openSUSE via the zypper package manager # Import python libs from __future__ import absolute_import -import copy import fnmatch import logging import re @@ -587,8 +586,8 @@ def version_cmp(ver1, ver2, ignore_epoch=False): def list_pkgs(versions_as_list=False, **kwargs): ''' - List the packages currently installed as a dict with versions - as a comma separated string:: + List the packages currently installed as a dict. By default, the dict + contains versions as a comma separated string:: {'<package_name>': '<version>[,<version>...]'} @@ -597,6 +596,19 @@ def list_pkgs(versions_as_list=False, **kwargs): {'<package_name>': ['<version>', '<version>']} + attr: + If a list of package attributes is specified, returned value will + contain them in addition to version, eg.:: + + {'<package_name>': [{'version' : 'version', 'arch' : 'arch'}]} + + Valid attributes are: ``epoch``, ``version``, ``release``, ``arch``, + ``install_date``, ``install_date_time_t``. + + If ``all`` is specified, all valid attributes will be returned. + + .. versionadded:: Oxygen + removed: not supported @@ -608,6 +620,7 @@ def list_pkgs(versions_as_list=False, **kwargs): .. code-block:: bash salt '*' pkg.list_pkgs + salt '*' pkg.list_pkgs attr='["version", "arch"]' ''' versions_as_list = salt.utils.is_true(versions_as_list) # not yet implemented or not applicable @@ -615,30 +628,30 @@ def list_pkgs(versions_as_list=False, **kwargs): for x in ('removed', 'purge_desired')]): return {} + attr = kwargs.get("attr") if 'pkg.list_pkgs' in __context__: - if versions_as_list: - return __context__['pkg.list_pkgs'] - else: - ret = copy.deepcopy(__context__['pkg.list_pkgs']) - __salt__['pkg_resource.stringify'](ret) - return ret + cached = __context__['pkg.list_pkgs'] + return __salt__['pkg_resource.format_pkg_list'](cached, versions_as_list, attr) - cmd = ['rpm', '-qa', '--queryformat', '%{NAME}_|-%{VERSION}_|-%{RELEASE}_|-%|EPOCH?{%{EPOCH}}:{}|\\n'] + cmd = ['rpm', '-qa', '--queryformat', ( + "%{NAME}_|-%{VERSION}_|-%{RELEASE}_|-%{ARCH}_|-" + "%|EPOCH?{%{EPOCH}}:{}|_|-%{INSTALLTIME}\\n")] ret = {} for line in __salt__['cmd.run'](cmd, output_loglevel='trace', python_shell=False).splitlines(): - name, pkgver, rel, epoch = line.split('_|-') - if epoch: - pkgver = '{0}:{1}'.format(epoch, pkgver) - if rel: - pkgver += '-{0}'.format(rel) - __salt__['pkg_resource.add_pkg'](ret, name, pkgver) - - __salt__['pkg_resource.sort_pkglist'](ret) - __context__['pkg.list_pkgs'] = copy.deepcopy(ret) - if not versions_as_list: - __salt__['pkg_resource.stringify'](ret) + name, pkgver, rel, arch, epoch, install_time = line.split('_|-') + install_date = datetime.datetime.utcfromtimestamp(int(install_time)).isoformat() + "Z" + install_date_time_t = int(install_time) - return ret + all_attr = {'epoch': epoch, 'version': pkgver, 'release': rel, 'arch': arch, + 'install_date': install_date, 'install_date_time_t': install_date_time_t} + __salt__['pkg_resource.add_pkg'](ret, name, all_attr) + + for pkgname in ret: + ret[pkgname] = sorted(ret[pkgname], key=lambda d: d['version']) + + __context__['pkg.list_pkgs'] = ret + + return __salt__['pkg_resource.format_pkg_list'](ret, versions_as_list, attr) def _get_configured_repos(): @@ -989,11 +1002,43 @@ def install(name=None, Zypper returns error code 106 if one of the repositories are not available for various reasons. In case to set strict check, this parameter needs to be set to True. Default: False. + diff_attr: + If a list of package attributes is specified, returned value will + contain them, eg.:: + + {'<package>': { + 'old': { + 'version': '<old-version>', + 'arch': '<old-arch>'}, + + 'new': { + 'version': '<new-version>', + 'arch': '<new-arch>'}}} + + Valid attributes are: ``epoch``, ``version``, ``release``, ``arch``, + ``install_date``, ``install_date_time_t``. + + If ``all`` is specified, all valid attributes will be returned. + + .. versionadded:: Oxygen + Returns a dict containing the new package names and versions:: {'<package>': {'old': '<old-version>', 'new': '<new-version>'}} + + If an attribute list is specified in ``diff_attr``, the dict will also contain + any specified attribute, eg.:: + + {'<package>': { + 'old': { + 'version': '<old-version>', + 'arch': '<old-arch>'}, + + 'new': { + 'version': '<new-version>', + 'arch': '<new-arch>'}}} ''' if refresh: refresh_db() @@ -1036,7 +1081,8 @@ def install(name=None, else: targets = pkg_params - old = list_pkgs() if not downloadonly else list_downloaded() + diff_attr = kwargs.get("diff_attr") + old = list_pkgs(attr=diff_attr) if not downloadonly else list_downloaded() downgrades = [] if fromrepo: fromrepoopt = ['--force', '--force-resolution', '--from', fromrepo] @@ -1074,13 +1120,7 @@ def install(name=None, __zypper__(no_repo_failure=ignore_repo_failure).call(*cmd) __context__.pop('pkg.list_pkgs', None) - new = list_pkgs() if not downloadonly else list_downloaded() - - # Handle packages which report multiple new versions - # (affects only kernel packages at this point) - for pkg in new: - new[pkg] = new[pkg].split(',')[-1] - + new = list_pkgs(attr=diff_attr) if not downloadonly else list_downloaded() ret = salt.utils.compare_dicts(old, new) if errors: @@ -1188,11 +1228,6 @@ def upgrade(refresh=True, __zypper__(systemd_scope=_systemd_scope()).noraise.call(*cmd_update) __context__.pop('pkg.list_pkgs', None) new = list_pkgs() - - # Handle packages which report multiple new versions - # (affects only kernel packages at this point) - for pkg in new: - new[pkg] = new[pkg].split(',')[-1] ret = salt.utils.compare_dicts(old, new) if __zypper__.exit_code not in __zypper__.SUCCESS_EXIT_CODES: diff --git a/salt/utils/pkg/rpm.py b/salt/utils/pkg/rpm.py index 7608b32969..3c4495a3fa 100644 --- a/salt/utils/pkg/rpm.py +++ b/salt/utils/pkg/rpm.py @@ -6,6 +6,7 @@ Common functions for working with RPM packages # Import python libs from __future__ import absolute_import import collections +import datetime import logging # Import salt libs @@ -36,7 +37,7 @@ ARCHES = ARCHES_64 + ARCHES_32 + ARCHES_PPC + ARCHES_S390 + \ ARCHES_ALPHA + ARCHES_ARM + ARCHES_SH # EPOCHNUM can't be used until RHEL5 is EOL as it is not present -QUERYFORMAT = '%{NAME}_|-%{EPOCH}_|-%{VERSION}_|-%{RELEASE}_|-%{ARCH}_|-%{REPOID}' +QUERYFORMAT = '%{NAME}_|-%{EPOCH}_|-%{VERSION}_|-%{RELEASE}_|-%{ARCH}_|-%{REPOID}_|-%{INSTALLTIME}' def get_osarch(): @@ -61,15 +62,17 @@ def check_32(arch, osarch=None): return all(x in ARCHES_32 for x in (osarch, arch)) -def pkginfo(name, version, arch, repoid): +def pkginfo(name, version, arch, repoid, install_date=None, install_date_time_t=None): ''' Build and return a pkginfo namedtuple ''' pkginfo_tuple = collections.namedtuple( 'PkgInfo', - ('name', 'version', 'arch', 'repoid') + ('name', 'version', 'arch', 'repoid', 'install_date', + 'install_date_time_t') ) - return pkginfo_tuple(name, version, arch, repoid) + return pkginfo_tuple(name, version, arch, repoid, install_date, + install_date_time_t) def resolve_name(name, arch, osarch=None): @@ -91,7 +94,7 @@ def parse_pkginfo(line, osarch=None): pkginfo namedtuple. ''' try: - name, epoch, version, release, arch, repoid = line.split('_|-') + name, epoch, version, release, arch, repoid, install_time = line.split('_|-') # Handle unpack errors (should never happen with the queryformat we are # using, but can't hurt to be careful). except ValueError: @@ -102,9 +105,14 @@ def parse_pkginfo(line, osarch=None): version += '-{0}'.format(release) if epoch not in ('(none)', '0'): version = ':'.join((epoch, version)) - - return pkginfo(name, version, arch, repoid) - + if install_time not in ('(none)', '0'): + install_date = datetime.datetime.utcfromtimestamp(int(install_time)).isoformat() + "Z" + install_date_time_t = int(install_time) + else: + install_date = None + install_date_time_t = None + + return pkginfo(name, version, arch, repoid, install_date, install_date_time_t) def combine_comments(comments): ''' diff --git a/tests/unit/modules/test_yumpkg.py b/tests/unit/modules/test_yumpkg.py new file mode 100644 index 0000000000..574fec1bfe --- /dev/null +++ b/tests/unit/modules/test_yumpkg.py @@ -0,0 +1,190 @@ +# -*- coding: utf-8 -*- + +# Import Python Libs +from __future__ import absolute_import +import os + +# Import Salt Testing Libs +from salttesting.unit import TestCase, skipIf +from salttesting.mock import ( + MagicMock, + patch, + NO_MOCK, + NO_MOCK_REASON +) + +# Import Salt libs +import salt.modules.yumpkg as yumpkg +import salt.modules.pkg_resource as pkg_resource + +# Globals +yumpkg.__salt__ = dict() +yumpkg.__grains__ = dict() +yumpkg.__context__ = dict() + + +@skipIf(NO_MOCK, NO_MOCK_REASON) +class YumTestCase(TestCase): + ''' + Test cases for salt.modules.yumpkg + ''' + + def test_list_pkgs(self): + ''' + Test packages listing. + + :return: + ''' + def _add_data(data, key, value): + data.setdefault(key, []).append(value) + + rpm_out = [ + 'python-urlgrabber_|-(none)_|-3.10_|-8.el7_|-noarch_|-(none)_|-1487838471', + 'alsa-lib_|-(none)_|-1.1.1_|-1.el7_|-x86_64_|-(none)_|-1487838475', + 'gnupg2_|-(none)_|-2.0.22_|-4.el7_|-x86_64_|-(none)_|-1487838477', + 'rpm-python_|-(none)_|-4.11.3_|-21.el7_|-x86_64_|-(none)_|-1487838477', + 'pygpgme_|-(none)_|-0.3_|-9.el7_|-x86_64_|-(none)_|-1487838478', + 'yum_|-(none)_|-3.4.3_|-150.el7.centos_|-noarch_|-(none)_|-1487838479', + 'lzo_|-(none)_|-2.06_|-8.el7_|-x86_64_|-(none)_|-1487838479', + 'qrencode-libs_|-(none)_|-3.4.1_|-3.el7_|-x86_64_|-(none)_|-1487838480', + 'ustr_|-(none)_|-1.0.4_|-16.el7_|-x86_64_|-(none)_|-1487838480', + 'shadow-utils_|-2_|-4.1.5.1_|-24.el7_|-x86_64_|-(none)_|-1487838481', + 'util-linux_|-(none)_|-2.23.2_|-33.el7_|-x86_64_|-(none)_|-1487838484', + 'openssh_|-(none)_|-6.6.1p1_|-33.el7_3_|-x86_64_|-(none)_|-1487838485', + 'virt-what_|-(none)_|-1.13_|-8.el7_|-x86_64_|-(none)_|-1487838486', + ] + with patch.dict(yumpkg.__grains__, {'osarch': 'x86_64'}), \ + patch.dict(yumpkg.__salt__, {'cmd.run': MagicMock(return_value=os.linesep.join(rpm_out))}), \ + patch.dict(yumpkg.__salt__, {'pkg_resource.add_pkg': _add_data}), \ + patch.dict(yumpkg.__salt__, {'pkg_resource.format_pkg_list': pkg_resource.format_pkg_list}), \ + patch.dict(yumpkg.__salt__, {'pkg_resource.stringify': MagicMock()}): + pkgs = yumpkg.list_pkgs(versions_as_list=True) + for pkg_name, pkg_version in { + 'python-urlgrabber': '3.10-8.el7', + 'alsa-lib': '1.1.1-1.el7', + 'gnupg2': '2.0.22-4.el7', + 'rpm-python': '4.11.3-21.el7', + 'pygpgme': '0.3-9.el7', + 'yum': '3.4.3-150.el7.centos', + 'lzo': '2.06-8.el7', + 'qrencode-libs': '3.4.1-3.el7', + 'ustr': '1.0.4-16.el7', + 'shadow-utils': '2:4.1.5.1-24.el7', + 'util-linux': '2.23.2-33.el7', + 'openssh': '6.6.1p1-33.el7_3', + 'virt-what': '1.13-8.el7'}.items(): + self.assertTrue(pkgs.get(pkg_name)) + self.assertEqual(pkgs[pkg_name], [pkg_version]) + + def test_list_pkgs_with_attr(self): + ''' + Test packages listing with the attr parameter + + :return: + ''' + def _add_data(data, key, value): + data.setdefault(key, []).append(value) + + rpm_out = [ + 'python-urlgrabber_|-(none)_|-3.10_|-8.el7_|-noarch_|-(none)_|-1487838471', + 'alsa-lib_|-(none)_|-1.1.1_|-1.el7_|-x86_64_|-(none)_|-1487838475', + 'gnupg2_|-(none)_|-2.0.22_|-4.el7_|-x86_64_|-(none)_|-1487838477', + 'rpm-python_|-(none)_|-4.11.3_|-21.el7_|-x86_64_|-(none)_|-1487838477', + 'pygpgme_|-(none)_|-0.3_|-9.el7_|-x86_64_|-(none)_|-1487838478', + 'yum_|-(none)_|-3.4.3_|-150.el7.centos_|-noarch_|-(none)_|-1487838479', + 'lzo_|-(none)_|-2.06_|-8.el7_|-x86_64_|-(none)_|-1487838479', + 'qrencode-libs_|-(none)_|-3.4.1_|-3.el7_|-x86_64_|-(none)_|-1487838480', + 'ustr_|-(none)_|-1.0.4_|-16.el7_|-x86_64_|-(none)_|-1487838480', + 'shadow-utils_|-2_|-4.1.5.1_|-24.el7_|-x86_64_|-(none)_|-1487838481', + 'util-linux_|-(none)_|-2.23.2_|-33.el7_|-x86_64_|-(none)_|-1487838484', + 'openssh_|-(none)_|-6.6.1p1_|-33.el7_3_|-x86_64_|-(none)_|-1487838485', + 'virt-what_|-(none)_|-1.13_|-8.el7_|-x86_64_|-(none)_|-1487838486', + ] + with patch.dict(yumpkg.__grains__, {'osarch': 'x86_64'}), \ + patch.dict(yumpkg.__salt__, {'cmd.run': MagicMock(return_value=os.linesep.join(rpm_out))}), \ + patch.dict(yumpkg.__salt__, {'pkg_resource.add_pkg': _add_data}), \ + patch.dict(yumpkg.__salt__, {'pkg_resource.format_pkg_list': pkg_resource.format_pkg_list}), \ + patch.dict(yumpkg.__salt__, {'pkg_resource.stringify': MagicMock()}): + pkgs = yumpkg.list_pkgs(attr=['epoch', 'release', 'arch', 'install_date_time_t']) + for pkg_name, pkg_attr in { + 'python-urlgrabber': { + 'version': '3.10', + 'release': '8.el7', + 'arch': 'noarch', + 'install_date_time_t': 1487838471, + }, + 'alsa-lib': { + 'version': '1.1.1', + 'release': '1.el7', + 'arch': 'x86_64', + 'install_date_time_t': 1487838475, + }, + 'gnupg2': { + 'version': '2.0.22', + 'release': '4.el7', + 'arch': 'x86_64', + 'install_date_time_t': 1487838477, + }, + 'rpm-python': { + 'version': '4.11.3', + 'release': '21.el7', + 'arch': 'x86_64', + 'install_date_time_t': 1487838477, + }, + 'pygpgme': { + 'version': '0.3', + 'release': '9.el7', + 'arch': 'x86_64', + 'install_date_time_t': 1487838478, + }, + 'yum': { + 'version': '3.4.3', + 'release': '150.el7.centos', + 'arch': 'noarch', + 'install_date_time_t': 1487838479, + }, + 'lzo': { + 'version': '2.06', + 'release': '8.el7', + 'arch': 'x86_64', + 'install_date_time_t': 1487838479, + }, + 'qrencode-libs': { + 'version': '3.4.1', + 'release': '3.el7', + 'arch': 'x86_64', + 'install_date_time_t': 1487838480, + }, + 'ustr': { + 'version': '1.0.4', + 'release': '16.el7', + 'arch': 'x86_64', + 'install_date_time_t': 1487838480, + }, + 'shadow-utils': { + 'epoch': '2', + 'version': '4.1.5.1', + 'release': '24.el7', + 'arch': 'x86_64', + 'install_date_time_t': 1487838481, + }, + 'util-linux': { + 'version': '2.23.2', + 'release': '33.el7', + 'arch': 'x86_64', + 'install_date_time_t': 1487838484, + }, + 'openssh': { + 'version': '6.6.1p1', + 'release': '33.el7_3', + 'arch': 'x86_64', + 'install_date_time_t': 1487838485, + }, + 'virt-what': { + 'version': '1.13', + 'release': '8.el7', + 'install_date_time_t': 1487838486, + 'arch': 'x86_64', + }}.items(): + self.assertTrue(pkgs.get(pkg_name)) + self.assertEqual(pkgs[pkg_name], [pkg_attr]) diff --git a/tests/unit/modules/zypper_test.py b/tests/unit/modules/zypper_test.py index 8d93aeb93b..7f6ec999d5 100644 --- a/tests/unit/modules/zypper_test.py +++ b/tests/unit/modules/zypper_test.py @@ -22,6 +22,7 @@ from salttesting.mock import ( ensure_in_syspath('../../') # Import Salt libs +import salt.modules.pkg_resource as pkg_resource from salt.exceptions import CommandExecutionError from salt.ext.six.moves import configparser import salt.ext.six as six @@ -364,7 +365,7 @@ class ZypperTestCase(TestCase): with patch('salt.modules.zypper.list_pkgs', MagicMock(side_effect=[{"vim": "1.1"}, {"vim": "1.1,1.2"}])): ret = zypper.upgrade() - self.assertDictEqual(ret, {"vim": {"old": "1.1", "new": "1.2"}}) + self.assertDictEqual(ret, {"vim": {"old": "1.1", "new": "1.1,1.2"}}) zypper_mock.assert_any_call('update', '--auto-agree-with-licenses') with patch('salt.modules.zypper.list_pkgs', MagicMock(side_effect=[{"vim": "1.1"}, {"vim": "1.2"}])): @@ -402,7 +403,7 @@ class ZypperTestCase(TestCase): with patch('salt.modules.zypper.list_pkgs', MagicMock(side_effect=[ {"kernel-default": "3.12.49-11.1"}, {"kernel-default": "3.12.49-11.1,3.12.51-60.20.2"}])): ret = zypper.install('kernel-default', '--auto-agree-with-licenses') - self.assertDictEqual(ret, {"kernel-default": {"old": "3.12.49-11.1", "new": "3.12.51-60.20.2"}}) + self.assertDictEqual(ret, {"kernel-default": {"old": "3.12.49-11.1", "new": "3.12.49-11.1,3.12.51-60.20.2"}}) @patch('salt.modules.zypper.refresh_db', MagicMock(return_value=True)) @patch('salt.modules.zypper._systemd_scope', MagicMock(return_value=False)) @@ -462,30 +463,92 @@ Repository 'DUMMY' not found by its alias, number, or URI. :return: ''' def _add_data(data, key, value): - data[key] = value + data.setdefault(key, []).append(value) + + rpm_out = [ + 'protobuf-java_|-2.6.1_|-3.1.develHead_|-noarch_|-_|-1499257756', + 'yast2-ftp-server_|-3.1.8_|-8.1_|-x86_64_|-_|-1499257798', + 'jose4j_|-0.4.4_|-2.1.develHead_|-noarch_|-_|-1499257756', + 'apache-commons-cli_|-1.2_|-1.233_|-noarch_|-_|-1498636510', + 'jakarta-commons-discovery_|-0.4_|-129.686_|-noarch_|-_|-1498636511', + 'susemanager-build-keys-web_|-12.0_|-5.1.develHead_|-noarch_|-_|-1498636510', + ] + with patch.dict(zypper.__salt__, {'cmd.run': MagicMock(return_value=os.linesep.join(rpm_out))}), \ + patch.dict(zypper.__salt__, {'pkg_resource.add_pkg': _add_data}), \ + patch.dict(zypper.__salt__, {'pkg_resource.format_pkg_list': pkg_resource.format_pkg_list}), \ + patch.dict(zypper.__salt__, {'pkg_resource.stringify': MagicMock()}): + pkgs = zypper.list_pkgs(versions_as_list=True) + for pkg_name, pkg_version in { + 'jakarta-commons-discovery': '0.4-129.686', + 'yast2-ftp-server': '3.1.8-8.1', + 'protobuf-java': '2.6.1-3.1.develHead', + 'susemanager-build-keys-web': '12.0-5.1.develHead', + 'apache-commons-cli': '1.2-1.233', + 'jose4j': '0.4.4-2.1.develHead'}.items(): + self.assertTrue(pkgs.get(pkg_name)) + self.assertEqual(pkgs[pkg_name], [pkg_version]) + + def test_list_pkgs_with_attr(self): + ''' + Test packages listing with the attr parameter + + :return: + ''' + def _add_data(data, key, value): + data.setdefault(key, []).append(value) rpm_out = [ - 'protobuf-java_|-2.6.1_|-3.1.develHead_|-', - 'yast2-ftp-server_|-3.1.8_|-8.1_|-', - 'jose4j_|-0.4.4_|-2.1.develHead_|-', - 'apache-commons-cli_|-1.2_|-1.233_|-', - 'jakarta-commons-discovery_|-0.4_|-129.686_|-', - 'susemanager-build-keys-web_|-12.0_|-5.1.develHead_|-', + 'protobuf-java_|-2.6.1_|-3.1.develHead_|-noarch_|-_|-1499257756', + 'yast2-ftp-server_|-3.1.8_|-8.1_|-x86_64_|-_|-1499257798', + 'jose4j_|-0.4.4_|-2.1.develHead_|-noarch_|-_|-1499257756', + 'apache-commons-cli_|-1.2_|-1.233_|-noarch_|-_|-1498636510', + 'jakarta-commons-discovery_|-0.4_|-129.686_|-noarch_|-_|-1498636511', + 'susemanager-build-keys-web_|-12.0_|-5.1.develHead_|-noarch_|-_|-1498636510', ] - with patch.dict(zypper.__salt__, {'cmd.run': MagicMock(return_value=os.linesep.join(rpm_out))}): - with patch.dict(zypper.__salt__, {'pkg_resource.add_pkg': _add_data}): - with patch.dict(zypper.__salt__, {'pkg_resource.sort_pkglist': MagicMock()}): - with patch.dict(zypper.__salt__, {'pkg_resource.stringify': MagicMock()}): - pkgs = zypper.list_pkgs() - for pkg_name, pkg_version in { - 'jakarta-commons-discovery': '0.4-129.686', - 'yast2-ftp-server': '3.1.8-8.1', - 'protobuf-java': '2.6.1-3.1.develHead', - 'susemanager-build-keys-web': '12.0-5.1.develHead', - 'apache-commons-cli': '1.2-1.233', - 'jose4j': '0.4.4-2.1.develHead'}.items(): - self.assertTrue(pkgs.get(pkg_name)) - self.assertEqual(pkgs[pkg_name], pkg_version) + with patch.dict(zypper.__salt__, {'cmd.run': MagicMock(return_value=os.linesep.join(rpm_out))}), \ + patch.dict(zypper.__salt__, {'pkg_resource.add_pkg': _add_data}), \ + patch.dict(zypper.__salt__, {'pkg_resource.format_pkg_list': pkg_resource.format_pkg_list}), \ + patch.dict(zypper.__salt__, {'pkg_resource.stringify': MagicMock()}): + pkgs = zypper.list_pkgs(attr=['epoch', 'release', 'arch', 'install_date_time_t']) + for pkg_name, pkg_attr in { + 'jakarta-commons-discovery': { + 'version': '0.4', + 'release': '129.686', + 'arch': 'noarch', + 'install_date_time_t': 1498636511, + }, + 'yast2-ftp-server': { + 'version': '3.1.8', + 'release': '8.1', + 'arch': 'x86_64', + 'install_date_time_t': 1499257798, + }, + 'protobuf-java': { + 'version': '2.6.1', + 'release': '3.1.develHead', + 'install_date_time_t': 1499257756, + 'arch': 'noarch', + }, + 'susemanager-build-keys-web': { + 'version': '12.0', + 'release': '5.1.develHead', + 'arch': 'noarch', + 'install_date_time_t': 1498636510, + }, + 'apache-commons-cli': { + 'version': '1.2', + 'release': '1.233', + 'arch': 'noarch', + 'install_date_time_t': 1498636510, + }, + 'jose4j': { + 'arch': 'noarch', + 'version': '0.4.4', + 'release': '2.1.develHead', + 'install_date_time_t': 1499257756, + }}.items(): + self.assertTrue(pkgs.get(pkg_name)) + self.assertEqual(pkgs[pkg_name], [pkg_attr]) def test_list_patches(self): ''' -- 2.17.1
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor