SHA256
1
0
forked from pool/salt
salt/add-all_versions-parameter-to-include-all-installed-.patch

451 lines
20 KiB
Diff
Raw Normal View History

Accepting request 626472 from home:mdinca:branches:systemsmanagement:saltstack - Update to 2018.3.2 See https://docs.saltstack.com/en/latest/topics/releases/2018.3.2.html for full changelog - Added: * accounting-for-when-files-in-an-archive-contain-non-.patch * add-all_versions-parameter-to-include-all-installed-.patch * add-custom-suse-capabilities-as-grains.patch * add-engine-relaying-libvirt-events.patch * add-environment-variable-to-know-if-yum-is-invoked-f.patch * add-other-attribute-to-gecos-fields-to-avoid-inconsi.patch * align-suse-salt-master.service-limitnofiles-limit-wi.patch * avoid-incomprehensive-message-if-crashes.patch * fix-deprecation-warning-bsc-1095507.patch * fix-diffing-binary-files-in-file.get_diff-bsc-109839.patch * fix-unboundlocalerror-in-file.get_diff.patch * fix-zypper.list_pkgs-to-be-aligned-with-pkg-state.patch * prevent-zypper-from-parsing-repo-configuration-from-.patch * remove-old-hack-when-reporting-multiversion-packages.patch * show-recommendations-for-salt-ssh-cross-version-pyth.patch - Modified: * activate-all-beacons-sources-config-pillar-grains.patch * add-saltssh-multi-version-support-across-python-inte.patch * avoid-excessive-syslogging-by-watchdog-cronjob-58.patch * do-not-override-jid-on-returners-only-sending-back-t.patch * enable-passing-a-unix_socket-for-mysql-returners-bsc.patch * fall-back-to-pymysql.patch * feat-add-grain-for-all-fqdns.patch * fix-bsc-1065792.patch * fix-decrease-loglevel-when-unable-to-resolve-addr.patch * fix-for-ec2-rate-limit-failures.patch OBS-URL: https://build.opensuse.org/request/show/626472 OBS-URL: https://build.opensuse.org/package/show/systemsmanagement:saltstack/salt?expand=0&rev=127
2018-07-30 13:52:13 +02:00
From 9de54cf6f7d8d6da4212842fef8c4c658a2a9b9c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Pablo=20Su=C3=A1rez=20Hern=C3=A1ndez?=
<psuarezhernandez@suse.com>
Date: Mon, 14 May 2018 11:33:13 +0100
Subject: [PATCH] Add "all_versions" parameter to include all installed
version on rpm.info
Enable "all_versions" parameter for zypper.info_installed
Enable "all_versions" parameter for yumpkg.info_installed
Prevent adding failed packages when pkg name contains the arch (on SUSE)
Add 'all_versions' documentation for info_installed on yum/zypper modules
Add unit tests for info_installed with all_versions
Refactor: use dict.setdefault instead if-else statement
Allow removing only specific package versions with zypper and yum
---
salt/modules/rpm.py | 18 ++++++++---
salt/modules/yumpkg.py | 49 ++++++++++++++++++++++--------
salt/modules/zypper.py | 64 ++++++++++++++++++++++++++++++++-------
salt/states/pkg.py | 33 +++++++++++++++++++-
tests/unit/modules/test_yumpkg.py | 50 ++++++++++++++++++++++++++++++
tests/unit/modules/test_zypper.py | 50 ++++++++++++++++++++++++++++++
6 files changed, 236 insertions(+), 28 deletions(-)
diff --git a/salt/modules/rpm.py b/salt/modules/rpm.py
index d065f1e2d9..3683234f59 100644
--- a/salt/modules/rpm.py
+++ b/salt/modules/rpm.py
@@ -453,7 +453,7 @@ def diff(package, path):
return res
-def info(*packages, **attr):
+def info(*packages, **kwargs):
'''
Return a detailed package(s) summary information.
If no packages specified, all packages will be returned.
@@ -467,6 +467,9 @@ def info(*packages, **attr):
version, vendor, release, build_date, build_date_time_t, install_date, install_date_time_t,
build_host, group, source_rpm, arch, epoch, size, license, signature, packager, url, summary, description.
+ :param all_versions:
+ Return information for all installed versions of the packages
+
:return:
CLI example:
@@ -476,7 +479,9 @@ def info(*packages, **attr):
salt '*' lowpkg.info apache2 bash
salt '*' lowpkg.info apache2 bash attr=version
salt '*' lowpkg.info apache2 bash attr=version,build_date_iso,size
+ salt '*' lowpkg.info apache2 bash attr=version,build_date_iso,size all_versions=True
'''
+ all_versions = kwargs.get('all_versions', False)
# LONGSIZE is not a valid tag for all versions of rpm. If LONGSIZE isn't
# available, then we can just use SIZE for older versions. See Issue #31366.
rpm_tags = __salt__['cmd.run_stdout'](
@@ -516,7 +521,7 @@ def info(*packages, **attr):
"edition": "edition: %|EPOCH?{%{EPOCH}:}|%{VERSION}-%{RELEASE}\\n",
}
- attr = attr.get('attr', None) and attr['attr'].split(",") or None
+ attr = kwargs.get('attr', None) and kwargs['attr'].split(",") or None
query = list()
if attr:
for attr_k in attr:
@@ -610,8 +615,13 @@ def info(*packages, **attr):
if pkg_name.startswith('gpg-pubkey'):
continue
if pkg_name not in ret:
- ret[pkg_name] = pkg_data.copy()
- del ret[pkg_name]['edition']
+ if all_versions:
+ ret[pkg_name] = [pkg_data.copy()]
+ else:
+ ret[pkg_name] = pkg_data.copy()
+ del ret[pkg_name]['edition']
+ elif all_versions:
+ ret[pkg_name].append(pkg_data.copy())
return ret
diff --git a/salt/modules/yumpkg.py b/salt/modules/yumpkg.py
index 747142264d..9ce4926790 100644
--- a/salt/modules/yumpkg.py
+++ b/salt/modules/yumpkg.py
@@ -994,31 +994,39 @@ def list_downloaded():
return ret
-def info_installed(*names):
+def info_installed(*names, **kwargs):
'''
.. versionadded:: 2015.8.1
Return the information of the named package(s), installed on the system.
+ :param all_versions:
+ Include information for all versions of the packages installed on the minion.
+
CLI example:
.. code-block:: bash
salt '*' pkg.info_installed <package1>
salt '*' pkg.info_installed <package1> <package2> <package3> ...
+ salt '*' pkg.info_installed <package1> <package2> <package3> all_versions=True
'''
+ all_versions = kwargs.get('all_versions', False)
ret = dict()
- for pkg_name, pkg_nfo in __salt__['lowpkg.info'](*names).items():
- t_nfo = dict()
- # Translate dpkg-specific keys to a common structure
- for key, value in pkg_nfo.items():
- if key == 'source_rpm':
- t_nfo['source'] = value
+ for pkg_name, pkgs_nfo in __salt__['lowpkg.info'](*names, **kwargs).items():
+ pkg_nfo = pkgs_nfo if all_versions else [pkgs_nfo]
+ for _nfo in pkg_nfo:
+ t_nfo = dict()
+ # Translate dpkg-specific keys to a common structure
+ for key, value in _nfo.items():
+ if key == 'source_rpm':
+ t_nfo['source'] = value
+ else:
+ t_nfo[key] = value
+ if not all_versions:
+ ret[pkg_name] = t_nfo
else:
- t_nfo[key] = value
-
- ret[pkg_name] = t_nfo
-
+ ret.setdefault(pkg_name, []).append(t_nfo)
return ret
@@ -1919,7 +1927,24 @@ def remove(name=None, pkgs=None, **kwargs): # pylint: disable=W0613
raise CommandExecutionError(exc)
old = list_pkgs()
- targets = [x for x in pkg_params if x in old]
+ targets = []
+ for target in pkg_params:
+ # Check if package version set to be removed is actually installed:
+ # old[target] contains a comma-separated list of installed versions
+ if target in old and not pkg_params[target]:
+ targets.append(target)
+ elif target in old and pkg_params[target] in old[target].split(','):
+ arch = ''
+ pkgname = target
+ try:
+ namepart, archpart = target.rsplit('.', 1)
+ except ValueError:
+ pass
+ else:
+ if archpart in salt.utils.pkg.rpm.ARCHES:
+ arch = '.' + archpart
+ pkgname = namepart
+ targets.append('{0}-{1}{2}'.format(pkgname, pkg_params[target], arch))
if not targets:
return {}
diff --git a/salt/modules/zypper.py b/salt/modules/zypper.py
index 668143bdd9..06f8335c18 100644
--- a/salt/modules/zypper.py
+++ b/salt/modules/zypper.py
@@ -470,28 +470,37 @@ def info_installed(*names, **kwargs):
Valid attributes are:
ignore, report
+ :param all_versions:
+ Include information for all versions of the packages installed on the minion.
+
CLI example:
.. code-block:: bash
salt '*' pkg.info_installed <package1>
salt '*' pkg.info_installed <package1> <package2> <package3> ...
- salt '*' pkg.info_installed <package1> attr=version,vendor
+ salt '*' pkg.info_installed <package1> <package2> <package3> all_versions=True
+ salt '*' pkg.info_installed <package1> attr=version,vendor all_versions=True
salt '*' pkg.info_installed <package1> <package2> <package3> ... attr=version,vendor
salt '*' pkg.info_installed <package1> <package2> <package3> ... attr=version,vendor errors=ignore
salt '*' pkg.info_installed <package1> <package2> <package3> ... attr=version,vendor errors=report
'''
+ all_versions = kwargs.get('all_versions', False)
ret = dict()
- for pkg_name, pkg_nfo in __salt__['lowpkg.info'](*names, **kwargs).items():
- t_nfo = dict()
- # Translate dpkg-specific keys to a common structure
- for key, value in six.iteritems(pkg_nfo):
- if key == 'source_rpm':
- t_nfo['source'] = value
+ for pkg_name, pkgs_nfo in __salt__['lowpkg.info'](*names, **kwargs).items():
+ pkg_nfo = pkgs_nfo if all_versions else [pkgs_nfo]
+ for _nfo in pkg_nfo:
+ t_nfo = dict()
+ # Translate dpkg-specific keys to a common structure
+ for key, value in six.iteritems(_nfo):
+ if key == 'source_rpm':
+ t_nfo['source'] = value
+ else:
+ t_nfo[key] = value
+ if not all_versions:
+ ret[pkg_name] = t_nfo
else:
- t_nfo[key] = value
- ret[pkg_name] = t_nfo
-
+ ret.setdefault(pkg_name, []).append(t_nfo)
return ret
@@ -1494,7 +1503,14 @@ def _uninstall(name=None, pkgs=None):
raise CommandExecutionError(exc)
old = list_pkgs()
- targets = [target for target in pkg_params if target in old]
+ targets = []
+ for target in pkg_params:
+ # Check if package version set to be removed is actually installed:
+ # old[target] contains a comma-separated list of installed versions
+ if target in old and pkg_params[target] in old[target].split(','):
+ targets.append(target + "-" + pkg_params[target])
+ elif target in old and not pkg_params[target]:
+ targets.append(target)
if not targets:
return {}
@@ -1517,6 +1533,32 @@ def _uninstall(name=None, pkgs=None):
return ret
+def normalize_name(name):
+ '''
+ Strips the architecture from the specified package name, if necessary.
+ Circumstances where this would be done include:
+
+ * If the arch is 32 bit and the package name ends in a 32-bit arch.
+ * If the arch matches the OS arch, or is ``noarch``.
+
+ CLI Example:
+
+ .. code-block:: bash
+
+ salt '*' pkg.normalize_name zsh.x86_64
+ '''
+ try:
+ arch = name.rsplit('.', 1)[-1]
+ if arch not in salt.utils.pkg.rpm.ARCHES + ('noarch',):
+ return name
+ except ValueError:
+ return name
+ if arch in (__grains__['osarch'], 'noarch') \
+ or salt.utils.pkg.rpm.check_32(arch, osarch=__grains__['osarch']):
+ return name[:-(len(arch) + 1)]
+ return name
+
+
def remove(name=None, pkgs=None, **kwargs): # pylint: disable=unused-argument
'''
.. versionchanged:: 2015.8.12,2016.3.3,2016.11.0
diff --git a/salt/states/pkg.py b/salt/states/pkg.py
index 2682ee17f9..ed405cb6b5 100644
--- a/salt/states/pkg.py
+++ b/salt/states/pkg.py
@@ -415,6 +415,16 @@ def _find_remove_targets(name=None,
if __grains__['os'] == 'FreeBSD' and origin:
cver = [k for k, v in six.iteritems(cur_pkgs) if v['origin'] == pkgname]
+ elif __grains__['os_family'] == 'Suse':
+ # On SUSE systems. Zypper returns packages without "arch" in name
+ try:
+ namepart, archpart = pkgname.rsplit('.', 1)
+ except ValueError:
+ cver = cur_pkgs.get(pkgname, [])
+ else:
+ if archpart in salt.utils.pkg.rpm.ARCHES + ("noarch",):
+ pkgname = namepart
+ cver = cur_pkgs.get(pkgname, [])
else:
cver = cur_pkgs.get(pkgname, [])
@@ -844,6 +854,17 @@ def _verify_install(desired, new_pkgs, ignore_epoch=False, new_caps=None):
cver = new_pkgs.get(pkgname.split('%')[0])
elif __grains__['os_family'] == 'Debian':
cver = new_pkgs.get(pkgname.split('=')[0])
+ elif __grains__['os_family'] == 'Suse':
+ # On SUSE systems. Zypper returns packages without "arch" in name
+ try:
+ namepart, archpart = pkgname.rsplit('.', 1)
+ except ValueError:
+ cver = new_pkgs.get(pkgname)
+ else:
+ if archpart in salt.utils.pkg.rpm.ARCHES + ("noarch",):
+ cver = new_pkgs.get(namepart)
+ else:
+ cver = new_pkgs.get(pkgname)
else:
cver = new_pkgs.get(pkgname)
if not cver and pkgname in new_caps:
@@ -2674,7 +2695,17 @@ def _uninstall(
changes = __salt__['pkg.{0}'.format(action)](name, pkgs=pkgs, version=version, **kwargs)
new = __salt__['pkg.list_pkgs'](versions_as_list=True, **kwargs)
- failed = [x for x in pkg_params if x in new]
+ failed = []
+ for x in pkg_params:
+ if __grains__['os_family'] in ['Suse', 'RedHat']:
+ # Check if the package version set to be removed is actually removed:
+ if x in new and not pkg_params[x]:
+ failed.append(x)
+ elif x in new and pkg_params[x] in new[x]:
+ failed.append(x + "-" + pkg_params[x])
+ elif x in new:
+ failed.append(x)
+
if action == 'purge':
new_removed = __salt__['pkg.list_pkgs'](versions_as_list=True,
removed=True,
diff --git a/tests/unit/modules/test_yumpkg.py b/tests/unit/modules/test_yumpkg.py
index 28b6e1294c..c73f2582b9 100644
--- a/tests/unit/modules/test_yumpkg.py
+++ b/tests/unit/modules/test_yumpkg.py
@@ -601,3 +601,53 @@ class YumTestCase(TestCase, LoaderModuleMockMixin):
'--branch=foo', '--exclude=kernel*', 'upgrade'],
output_loglevel='trace',
python_shell=False)
+
+ def test_info_installed_with_all_versions(self):
+ '''
+ Test the return information of all versions for the named package(s), installed on the system.
+
+ :return:
+ '''
+ run_out = {
+ 'virgo-dummy': [
+ {'build_date': '2015-07-09T10:55:19Z',
+ 'vendor': 'openSUSE Build Service',
+ 'description': 'This is the Virgo dummy package used for testing SUSE Manager',
+ 'license': 'GPL-2.0', 'build_host': 'sheep05', 'url': 'http://www.suse.com',
+ 'build_date_time_t': 1436432119, 'relocations': '(not relocatable)',
+ 'source_rpm': 'virgo-dummy-1.0-1.1.src.rpm', 'install_date': '2016-02-23T16:31:57Z',
+ 'install_date_time_t': 1456241517, 'summary': 'Virgo dummy package', 'version': '1.0',
+ 'signature': 'DSA/SHA1, Thu Jul 9 08:55:33 2015, Key ID 27fa41bd8a7c64f9',
+ 'release': '1.1', 'group': 'Applications/System', 'arch': 'i686', 'size': '17992'},
+ {'build_date': '2015-07-09T10:15:19Z',
+ 'vendor': 'openSUSE Build Service',
+ 'description': 'This is the Virgo dummy package used for testing SUSE Manager',
+ 'license': 'GPL-2.0', 'build_host': 'sheep05', 'url': 'http://www.suse.com',
+ 'build_date_time_t': 1436432119, 'relocations': '(not relocatable)',
+ 'source_rpm': 'virgo-dummy-1.0-1.1.src.rpm', 'install_date': '2016-02-23T16:31:57Z',
+ 'install_date_time_t': 14562415127, 'summary': 'Virgo dummy package', 'version': '1.0',
+ 'signature': 'DSA/SHA1, Thu Jul 9 08:55:33 2015, Key ID 27fa41bd8a7c64f9',
+ 'release': '1.1', 'group': 'Applications/System', 'arch': 'x86_64', 'size': '13124'}
+ ],
+ 'libopenssl1_0_0': [
+ {'build_date': '2015-11-04T23:20:34Z', 'vendor': 'SUSE LLC <https://www.suse.com/>',
+ 'description': 'The OpenSSL Project is a collaborative effort.',
+ 'license': 'OpenSSL', 'build_host': 'sheep11', 'url': 'https://www.openssl.org/',
+ 'build_date_time_t': 1446675634, 'relocations': '(not relocatable)',
+ 'source_rpm': 'openssl-1.0.1i-34.1.src.rpm', 'install_date': '2016-02-23T16:31:35Z',
+ 'install_date_time_t': 1456241495, 'summary': 'Secure Sockets and Transport Layer Security',
+ 'version': '1.0.1i', 'signature': 'RSA/SHA256, Wed Nov 4 22:21:34 2015, Key ID 70af9e8139db7c82',
+ 'release': '34.1', 'group': 'Productivity/Networking/Security', 'packager': 'https://www.suse.com/',
+ 'arch': 'x86_64', 'size': '2576912'}
+ ]
+ }
+ with patch.dict(yumpkg.__salt__, {'lowpkg.info': MagicMock(return_value=run_out)}):
+ installed = yumpkg.info_installed(all_versions=True)
+ # Test overall products length
+ self.assertEqual(len(installed), 2)
+
+ # Test multiple versions for the same package
+ for pkg_name, pkg_info_list in installed.items():
+ self.assertEqual(len(pkg_info_list), 2 if pkg_name == "virgo-dummy" else 1)
+ for info in pkg_info_list:
+ self.assertTrue(info['arch'] in ('x86_64', 'i686'))
diff --git a/tests/unit/modules/test_zypper.py b/tests/unit/modules/test_zypper.py
index 539a950252..6eccee568b 100644
--- a/tests/unit/modules/test_zypper.py
+++ b/tests/unit/modules/test_zypper.py
@@ -327,6 +327,56 @@ class ZypperTestCase(TestCase, LoaderModuleMockMixin):
installed = zypper.info_installed()
self.assertEqual(installed['vīrgô']['description'], 'vīrgô d€šçripţiǫñ')
+ def test_info_installed_with_all_versions(self):
+ '''
+ Test the return information of all versions for the named package(s), installed on the system.
+
+ :return:
+ '''
+ run_out = {
+ 'virgo-dummy': [
+ {'build_date': '2015-07-09T10:55:19Z',
+ 'vendor': 'openSUSE Build Service',
+ 'description': 'This is the Virgo dummy package used for testing SUSE Manager',
+ 'license': 'GPL-2.0', 'build_host': 'sheep05', 'url': 'http://www.suse.com',
+ 'build_date_time_t': 1436432119, 'relocations': '(not relocatable)',
+ 'source_rpm': 'virgo-dummy-1.0-1.1.src.rpm', 'install_date': '2016-02-23T16:31:57Z',
+ 'install_date_time_t': 1456241517, 'summary': 'Virgo dummy package', 'version': '1.0',
+ 'signature': 'DSA/SHA1, Thu Jul 9 08:55:33 2015, Key ID 27fa41bd8a7c64f9',
+ 'release': '1.1', 'group': 'Applications/System', 'arch': 'i686', 'size': '17992'},
+ {'build_date': '2015-07-09T10:15:19Z',
+ 'vendor': 'openSUSE Build Service',
+ 'description': 'This is the Virgo dummy package used for testing SUSE Manager',
+ 'license': 'GPL-2.0', 'build_host': 'sheep05', 'url': 'http://www.suse.com',
+ 'build_date_time_t': 1436432119, 'relocations': '(not relocatable)',
+ 'source_rpm': 'virgo-dummy-1.0-1.1.src.rpm', 'install_date': '2016-02-23T16:31:57Z',
+ 'install_date_time_t': 14562415127, 'summary': 'Virgo dummy package', 'version': '1.0',
+ 'signature': 'DSA/SHA1, Thu Jul 9 08:55:33 2015, Key ID 27fa41bd8a7c64f9',
+ 'release': '1.1', 'group': 'Applications/System', 'arch': 'x86_64', 'size': '13124'}
+ ],
+ 'libopenssl1_0_0': [
+ {'build_date': '2015-11-04T23:20:34Z', 'vendor': 'SUSE LLC <https://www.suse.com/>',
+ 'description': 'The OpenSSL Project is a collaborative effort.',
+ 'license': 'OpenSSL', 'build_host': 'sheep11', 'url': 'https://www.openssl.org/',
+ 'build_date_time_t': 1446675634, 'relocations': '(not relocatable)',
+ 'source_rpm': 'openssl-1.0.1i-34.1.src.rpm', 'install_date': '2016-02-23T16:31:35Z',
+ 'install_date_time_t': 1456241495, 'summary': 'Secure Sockets and Transport Layer Security',
+ 'version': '1.0.1i', 'signature': 'RSA/SHA256, Wed Nov 4 22:21:34 2015, Key ID 70af9e8139db7c82',
+ 'release': '34.1', 'group': 'Productivity/Networking/Security', 'packager': 'https://www.suse.com/',
+ 'arch': 'x86_64', 'size': '2576912'}
+ ]
+ }
+ with patch.dict(zypper.__salt__, {'lowpkg.info': MagicMock(return_value=run_out)}):
+ installed = zypper.info_installed(all_versions=True)
+ # Test overall products length
+ self.assertEqual(len(installed), 2)
+
+ # Test multiple versions for the same package
+ for pkg_name, pkg_info_list in installed.items():
+ self.assertEqual(len(pkg_info_list), 2 if pkg_name == "virgo-dummy" else 1)
+ for info in pkg_info_list:
+ self.assertTrue(info['arch'] in ('x86_64', 'i686'))
+
def test_info_available(self):
'''
Test return the information of the named package available for the system.
--
2.13.7