Hello community, here is the log from the commit of package salt for openSUSE:Factory checked in at 2016-02-24 18:43:06 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/salt (Old) and /work/SRC/openSUSE:Factory/.salt.new (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "salt" Changes: -------- --- /work/SRC/openSUSE:Factory/salt/salt.changes 2016-01-26 10:14:45.000000000 +0100 +++ /work/SRC/openSUSE:Factory/.salt.new/salt.changes 2016-02-24 18:43:08.000000000 +0100 @@ -1,0 +2,165 @@ +Tue Feb 23 11:58:00 CET 2016 - [email protected] + +- fix argument handling of pkg.download + Add: 0022-fix-argument-handling-for-pkg.download.patch + +------------------------------------------------------------------- +Mon Feb 22 16:12:43 CET 2016 - [email protected] + +- unify behavior of zypper refresh in salt + Add: 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 + +------------------------------------------------------------------- +Sat Feb 20 11:41:45 CET 2016 - [email protected] + +- Fix crash with scheduler and runners + Add: 0017-Fix-crash-with-scheduler-and-runners-31106.patch + +------------------------------------------------------------------- +Fri Feb 19 15:01:38 CET 2016 - [email protected] + +- Call zypper always with --non-interactive + Add: + * 0015-call-zypper-with-option-non-interactive-everywhere.patch + * 0016-write-a-zypper-command-builder-function.patch + +------------------------------------------------------------------- +Fri Feb 19 13:00:52 CET 2016 - [email protected] + +- require rpm-python on SUSE for zypper support + +------------------------------------------------------------------- +Thu Feb 18 11:01:21 CET 2016 - [email protected] + +- fix state return code + Add: 0009-The-functions-in-the-state-module-that-return-a-retc.patch +- add handling of OEM products to pkg.list_products + Add: 0010-add-handling-for-OEM-products.patch +- improve doc for list_pkgs + Add: 0011-improve-doc-for-list_pkgs.patch +- implement pkg.version_cmp in zypper.py + Add: + * 0012-implement-version_cmp-for-zypper.patch + * 0013-pylint-changes.patch + * 0014-Check-if-rpm-python-can-be-imported.patch + +------------------------------------------------------------------- +Wed Feb 17 17:57:57 UTC 2016 - [email protected] + +- Update to 2015.8.7 + this is a small update to fix some regressions + see https://docs.saltstack.com/en/latest/topics/releases/2015.8.7.html + +------------------------------------------------------------------- +Thu Feb 11 17:42:38 UTC 2016 - [email protected] + +- Booleans should not be strings from XML, add Unix ticks time and + format result in a list of maps. + Add: + * 0008-Fix-types-in-the-output-data-and-return-just-a-list-.patch + +------------------------------------------------------------------- +Thu Feb 11 16:27:33 UTC 2016 - [email protected] + +- Stop salt-api daemon faster (bsc#963322) + Add: + * 0007-Force-kill-websocket-s-child-processes-faster-than-d.patch + +------------------------------------------------------------------- +Wed Feb 10 08:30:45 UTC 2016 - [email protected] + +- Do not crash on salt-key reject/delete consecutive calls. + Add: + * 0006-add_key-reject_key-do-not-crash-w-Permission-denied-.patch + +------------------------------------------------------------------- +Mon Feb 8 16:15:56 UTC 2016 - [email protected] + +- Update to 2015.8.5 + See https://docs.saltstack.com/en/latest/topics/releases/2015.8.5.html + Dropped patches (all upstream): + * 0003-List-products-consistently-across-all-SLES-systems.patch + * 0004-Add-missing-return-data-to-scheduled-jobs.patch + * 0005-Fix-RPM-issues-with-the-date-time-and-add-package-at.patch + * 0006-Bugfix-info_available-does-not-work-correctly-on-SLE.patch + Renamed patches: + * 0007-Check-if-byte-strings-are-properly-encoded-in-UTF-8.patch + -> 0003-Check-if-byte-strings-are-properly-encoded-in-UTF-8.patch + * 0008-Fix-pkg.latest-prevent-crash-on-multiple-package-ins.patch + -> 0004-Fix-pkg.latest-prevent-crash-on-multiple-package-ins.patch + * 0009-Fix-package-status-filtering-on-latest-version-and-i.patch + -> 0005-Fix-package-status-filtering-on-latest-version-and-i.patch + +- Update to 2015.8.4 + See https://docs.saltstack.com/en/latest/topics/releases/2015.8.4.html + +------------------------------------------------------------------- +Wed Jan 27 13:09:53 UTC 2016 - [email protected] + +- Fix latest version available comparison and implement epoch + support in Zypper module. + Add: + * 0009-Fix-package-status-filtering-on-latest-version-and-i.patch + +------------------------------------------------------------------- +Wed Jan 27 09:25:15 UTC 2016 - [email protected] + +- Update patch from opensuse to upstream version. + Update: + * 0008-Fix-pkg.latest-prevent-crash-on-multiple-package-ins.patch + +------------------------------------------------------------------- +Tue Jan 26 09:42:57 UTC 2016 - [email protected] + +- Fix dependencies to Salt subpackages requiring release along the + version. + +------------------------------------------------------------------- +Mon Jan 25 16:24:55 UTC 2016 - [email protected] + +- Fix pkg.latest crash. +- Fix pkg.latest SLS ID bug, when pkgs empty list is passed, + but SLS ID still treated as a package name. + + Add: + * 0008-Fix-pkg.latest-prevent-crash-on-multiple-package-ins.patch + +------------------------------------------------------------------- +Wed Jan 20 15:10:04 UTC 2016 - [email protected] + +- Drop: + * -0004-zypper-check-package-header-content-for-valid-utf-8.patch +- Rename: + * -0004-zypper-check-package-header-content-for-valid-utf-8.patch + +0004-Add-missing-return-data-to-scheduled-jobs.patch + * -0005-Add-missing-return-data-to-scheduled-jobs.patch + +0004-Add-missing-return-data-to-scheduled-jobs.patch + * -0006-Fix-RPM-issues-with-the-date-time-and-add-package-at.patch + +0005-Fix-RPM-issues-with-the-date-time-and-add-package-at.patch + * -0007-Bugfix-info_available-does-not-work-correctly-on-SLE.patch + +0006-Bugfix-info_available-does-not-work-correctly-on-SLE.patch +- Add: + * 0007-Check-if-byte-strings-are-properly-encoded-in-UTF-8.patch + +------------------------------------------------------------------- +Wed Jan 20 10:19:07 UTC 2016 - [email protected] + +- Rename use-forking-daemon.patch to + 0001-tserong-suse.com-We-don-t-have-python-systemd-so-not.patch +- Rename use-salt-user-for-master.patch to + 0002-Run-salt-master-as-dedicated-salt-user.patch +- Rename 1efe484309a5c776974e723f3da0f5181f4bdb86.patch to + 0003-List-products-consistently-across-all-SLES-systems.patch +- Rename zypper-utf-8.patch to + 0004-zypper-check-package-header-content-for-valid-utf-8.patch +- Rename salt-2015.8-schedule-ret.patch to + 0005-Add-missing-return-data-to-scheduled-jobs.patch +- Rename salt-2015.8-pkg-zypper-attr-filtering.patch to + 0006-Fix-RPM-issues-with-the-date-time-and-add-package-at.patch +- Rename salt-2015.8-zypper-info.patch to + 0007-Bugfix-info_available-does-not-work-correctly-on-SLE.patch + +------------------------------------------------------------------- Old: ---- 1efe484309a5c776974e723f3da0f5181f4bdb86.patch salt-2015.8-pkg-zypper-attr-filtering.patch salt-2015.8-schedule-ret.patch salt-2015.8-zypper-info.patch salt-2015.8.3.tar.gz use-forking-daemon.patch use-salt-user-for-master.patch zypper-utf-8.patch New: ---- 0001-tserong-suse.com-We-don-t-have-python-systemd-so-not.patch 0002-Run-salt-master-as-dedicated-salt-user.patch 0003-Check-if-byte-strings-are-properly-encoded-in-UTF-8.patch 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 salt-2015.8.7.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ salt.spec ++++++ --- /var/tmp/diff_new_pack.jfoIOI/_old 2016-02-24 18:43:09.000000000 +0100 +++ /var/tmp/diff_new_pack.jfoIOI/_new 2016-02-24 18:43:09.000000000 +0100 @@ -36,29 +36,56 @@ %bcond_without docs Name: salt -Version: 2015.8.3 +Version: 2015.8.7 Release: 0 Summary: A parallel remote execution system License: Apache-2.0 Group: System/Monitoring Url: http://saltstack.org/ +# Git: https://github.com/openSUSE/salt.git Source0: http://pypi.python.org/packages/source/s/%{name}/%{name}-%{version}.tar.gz Source1: README.SUSE Source2: salt-tmpfiles.d + # PATCH-FIX-OPENSUSE use-forking-daemon.patch [email protected] -- We don't have python-systemd, so notify can't work -Patch1: use-forking-daemon.patch +Patch1: 0001-tserong-suse.com-We-don-t-have-python-systemd-so-not.patch # PATCH-FIX-OPENSUSE use-salt-user-for-master.patch -- Run salt master as dedicated salt user -Patch2: use-salt-user-for-master.patch -# PATCH-FIX-UPSTREAM https://github.com/saltstack/salt/pull/29244 -Patch3: 1efe484309a5c776974e723f3da0f5181f4bdb86.patch -# PATCH-FIX-OPENSUSE detect bad UTF-8 in package header, bsc#958350 -Patch4: zypper-utf-8.patch -# PATCH-FIX-UPSTREAM https://github.com/saltstack/salt/pull/30246 -Patch5: salt-2015.8-schedule-ret.patch -# PATCH-FIX-UPSTREAM https://github.com/saltstack/salt/pull/30267 -Patch6: salt-2015.8-pkg-zypper-attr-filtering.patch -# PATCH-FIX-UPSTREAM https://github.com/saltstack/salt/pull/30384 -Patch7: salt-2015.8-zypper-info.patch +Patch2: 0002-Run-salt-master-as-dedicated-salt-user.patch +# PATCH-FIX-OPENSUSE https://github.com/saltstack/salt/pull/30424 +Patch3: 0003-Check-if-byte-strings-are-properly-encoded-in-UTF-8.patch +# PATCH-FIX-OPENSUSE https://github.com/saltstack/salt/pull/30611 +Patch4: 0004-Fix-pkg.latest-prevent-crash-on-multiple-package-ins.patch +# PATCH-FIX-OPENSUSE https://github.com/saltstack/salt/pull/30663 +Patch5: 0005-Fix-package-status-filtering-on-latest-version-and-i.patch +# PATCH-FIX-UPSTREAM https://github.com/saltstack/salt/pull/30998 +Patch6: 0006-add_key-reject_key-do-not-crash-w-Permission-denied-.patch +# PATCH-FIX-UPSTREAM https://github.com/saltstack/salt/pull/31125 +Patch7: 0007-Force-kill-websocket-s-child-processes-faster-than-d.patch +# PATCH-FIX-UPSTREAM https://github.com/saltstack/salt/pull/31134 +Patch8: 0008-Fix-types-in-the-output-data-and-return-just-a-list-.patch +# PATCH-FIX-UPSTREAM +Patch9: 0009-The-functions-in-the-state-module-that-return-a-retc.patch +# PATCH-FIX-UPSTREAM https://github.com/saltstack/salt/pull/31237 +Patch10: 0010-add-handling-for-OEM-products.patch +# PATCH-FIX-UPSTREAM https://github.com/saltstack/salt/pull/31234 +Patch11: 0011-improve-doc-for-list_pkgs.patch +# PATCH-FIX-UPSTREAM https://github.com/saltstack/salt/pull/31233 +Patch12: 0012-implement-version_cmp-for-zypper.patch +Patch13: 0013-pylint-changes.patch +Patch14: 0014-Check-if-rpm-python-can-be-imported.patch +# PATCH-FIX-UPSTREAM https://github.com/saltstack/salt/pull/31305 +Patch15: 0015-call-zypper-with-option-non-interactive-everywhere.patch +Patch16: 0016-write-a-zypper-command-builder-function.patch +# PATCH-FIX-UPSTREAM https://github.com/saltstack/salt/pull/31189 +Patch17: 0017-Fix-crash-with-scheduler-and-runners-31106.patch +# PATCH-FIX-UPSTREAM https://github.com/saltstack/salt/pull/31378 +Patch18: 0018-unify-behavior-of-refresh.patch +Patch19: 0019-add-refresh-option-to-more-functions.patch +Patch20: 0020-simplify-checking-the-refresh-paramater.patch +Patch21: 0021-do-not-change-kwargs-in-refresh-while-checking-a-val.patch +# PATCH-FIX-UPSTREAM https://github.com/saltstack/salt/pull/31429 +Patch22: 0022-fix-argument-handling-for-pkg.download.patch + BuildRoot: %{_tmppath}/%{name}-%{version}-build BuildRequires: logrotate BuildRequires: python @@ -123,6 +150,8 @@ Requires: python-tornado >= 4.2.1 Requires: python-yaml %if 0%{?suse_version} +# required for zypper.py +Requires: rpm-python # requirements/opt.txt (not all) Recommends: python-MySQL-python Recommends: python-timelib @@ -178,8 +207,8 @@ %package api Summary: The api for Salt a parallel remote execution system Group: System/Monitoring -Requires: %{name} = %{version} -Requires: %{name}-master = %{version} +Requires: %{name} = %{version}-%{release} +Requires: %{name}-master = %{version}-%{release} Requires: python-CherryPy >= 3.2.2 %description api @@ -188,8 +217,8 @@ %package cloud Summary: Generic cloud provisioning tool for Saltstack Group: System/Monitoring -Requires: %{name} = %{version} -Requires: %{name}-master = %{version} +Requires: %{name} = %{version}-%{release} +Requires: %{name}-master = %{version}-%{release} Requires: python-apache-libcloud %if 0%{?suse_version} Recommends: python-botocore @@ -214,7 +243,7 @@ %package master Summary: The management component of Saltstack both protocols zmq and raet supported Group: System/Monitoring -Requires: %{name} = %{version} +Requires: %{name} = %{version}-%{release} %if 0%{?suse_version} Recommends: python-pygit2 >= 0.20.3 %endif @@ -246,7 +275,7 @@ %package minion Summary: The client component for Saltstack Group: System/Monitoring -Requires: %{name} = %{version} +Requires: %{name} = %{version}-%{release} %if %{with systemd} %{?systemd_requires} %else @@ -265,7 +294,7 @@ %package raet Summary: Raet Support for Saltstack Group: System/Monitoring -Requires: %{name} = %{version} +Requires: %{name} = %{version}-%{release} Requires: python-enum34 Requires: python-ioflo >= 1.1.7 Requires: python-libnacl >= 1.0.0 @@ -287,7 +316,7 @@ %package proxy Summary: Component for salt that enables controlling arbitrary devices Group: System/Monitoring -Requires: %{name} = %{version} +Requires: %{name} = %{version}-%{release} %if %{with systemd} %{?systemd_requires} %else @@ -310,8 +339,8 @@ %package syndic Summary: The syndic component for saltstack Group: System/Monitoring -Requires: %{name} = %{version} -Requires: %{name}-master = %{version} +Requires: %{name} = %{version}-%{release} +Requires: %{name}-master = %{version}-%{release} %if %{with systemd} %{?systemd_requires} %else @@ -331,8 +360,8 @@ %package ssh Summary: Management component for Saltstack with ssh protocol Group: System/Monitoring -Requires: %{name} = %{version} -Requires: %{name}-master = %{version} +Requires: %{name} = %{version}-%{release} +Requires: %{name}-master = %{version}-%{release} %if 0%{?suse_version} Recommends: sshpass %endif @@ -355,7 +384,7 @@ %package bash-completion Summary: Bash Completion for %{name} Group: System/Management -Requires: %{name} = %{version} +Requires: %{name} = %{version}-%{release} Requires: bash-completion %if 0%{?suse_version} > 1110 BuildArch: noarch @@ -370,7 +399,7 @@ %package fish-completion Summary: Fish Completion for %{name} Group: System/Management -Requires: %{name} = %{version} +Requires: %{name} = %{version}-%{release} %if 0%{?suse_version} > 1110 BuildArch: noarch @@ -384,7 +413,7 @@ %package zsh-completion Summary: Zsh Completion for %{name} Group: System/Management -Requires: %{name} = %{version} +Requires: %{name} = %{version}-%{release} Requires: zsh %if 0%{?suse_version} > 1110 BuildArch: noarch @@ -405,6 +434,21 @@ %patch5 -p1 %patch6 -p1 %patch7 -p1 +%patch8 -p1 +%patch9 -p1 +%patch10 -p1 +%patch11 -p1 +%patch12 -p1 +%patch13 -p1 +%patch14 -p1 +%patch15 -p1 +%patch16 -p1 +%patch17 -p1 +%patch18 -p1 +%patch19 -p1 +%patch20 -p1 +%patch21 -p1 +%patch22 -p1 %build python setup.py --salt-transport=both build ++++++ 0001-tserong-suse.com-We-don-t-have-python-systemd-so-not.patch ++++++ >From f6534519ed6dcd443e9b5b8f7dc6dfe1fb508ab3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Klaus=20K=C3=A4mpf?= <[email protected]> Date: Wed, 20 Jan 2016 11:00:15 +0100 Subject: [PATCH 01/22] [email protected] -- We don't have python-systemd, so notify can't work --- pkg/salt-master.service | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/pkg/salt-master.service b/pkg/salt-master.service index 0eadf88..2b0f326 100644 --- a/pkg/salt-master.service +++ b/pkg/salt-master.service @@ -4,8 +4,7 @@ After=network.target [Service] LimitNOFILE=16384 -Type=notify -NotifyAccess=all +Type=simple ExecStart=/usr/bin/salt-master KillMode=process -- 2.1.4 ++++++ 0002-Run-salt-master-as-dedicated-salt-user.patch ++++++ >From cd60b85c9e6bfd8ebf3505e5ff05e7fdec6211d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Klaus=20K=C3=A4mpf?= <[email protected]> Date: Wed, 20 Jan 2016 11:01:06 +0100 Subject: [PATCH 02/22] Run salt master as dedicated salt user --- conf/master | 3 ++- pkg/salt-common.logrotate | 3 +++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/conf/master b/conf/master index 643b5f4..36657e8 100644 --- a/conf/master +++ b/conf/master @@ -25,7 +25,8 @@ # permissions to allow the specified user to run the master. The exception is # the job cache, which must be deleted if this user is changed. If the # modified files cause conflicts, set verify_env to False. -#user: root +user: salt +syndic_user: salt # The port used by the communication interface. The ret (return) port is the # interface used for the file server, authentication, job returns, etc. diff --git a/pkg/salt-common.logrotate b/pkg/salt-common.logrotate index 3cd0023..8d970c0 100644 --- a/pkg/salt-common.logrotate +++ b/pkg/salt-common.logrotate @@ -1,4 +1,5 @@ /var/log/salt/master { + su salt salt weekly missingok rotate 7 @@ -7,6 +8,7 @@ } /var/log/salt/minion { + su salt salt weekly missingok rotate 7 @@ -15,6 +17,7 @@ } /var/log/salt/key { + su salt salt weekly missingok rotate 7 -- 2.1.4 ++++++ 0003-Check-if-byte-strings-are-properly-encoded-in-UTF-8.patch ++++++ >From 9dc25e7dfb08a7cd583215d0206f18b15a44ccb1 Mon Sep 17 00:00:00 2001 From: Bo Maryniuk <[email protected]> Date: Mon, 18 Jan 2016 16:28:48 +0100 Subject: [PATCH 03/22] Check if byte strings are properly encoded in UTF-8 Rename keywords arguments variable to a default name. --- salt/modules/zypper.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/salt/modules/zypper.py b/salt/modules/zypper.py index 0d62c68..dddcc2f 100644 --- a/salt/modules/zypper.py +++ b/salt/modules/zypper.py @@ -112,9 +112,9 @@ def info_installed(*names, **kwargs): summary, description. :param errors: - Handle RPM field errors (true|false). By default, various mistakes in the textual fields are simply ignored and - omitted from the data. Otherwise a field with a mistake is not returned, instead a 'N/A (bad UTF-8)' - (not available, broken) text is returned. + Handle RPM field errors. If 'ignore' is chosen, then various mistakes are simply ignored and omitted + from the texts or strings. If 'report' is chonen, then a field with a mistake is not returned, instead + a 'N/A (broken)' (not available, broken) text is placed. Valid attributes are: ignore, report @@ -127,7 +127,8 @@ def info_installed(*names, **kwargs): salt '*' pkg.info_installed <package1> <package2> <package3> ... salt '*' pkg.info_installed <package1> attr=version,vendor salt '*' pkg.info_installed <package1> <package2> <package3> ... attr=version,vendor - salt '*' pkg.info_installed <package1> <package2> <package3> ... attr=version,vendor errors=true + salt '*' pkg.info_installed <package1> <package2> <package3> ... attr=version,vendor errors=ignore + salt '*' pkg.info_installed <package1> <package2> <package3> ... attr=version,vendor errors=report ''' ret = dict() for pkg_name, pkg_nfo in __salt__['lowpkg.info'](*names, **kwargs).items(): @@ -138,7 +139,7 @@ def info_installed(*names, **kwargs): # Check, if string is encoded in a proper UTF-8 value_ = value.decode('UTF-8', 'ignore').encode('UTF-8', 'ignore') if value != value_: - value = kwargs.get('errors') and value_ or 'N/A (invalid UTF-8)' + value = kwargs.get('errors', 'ignore') == 'ignore' and value_ or 'N/A (invalid UTF-8)' log.error('Package {0} has bad UTF-8 code in {1}: {2}'.format(pkg_name, key, value)) if key == 'source_rpm': t_nfo['source'] = value -- 2.1.4 ++++++ 0004-Fix-pkg.latest-prevent-crash-on-multiple-package-ins.patch ++++++ >From e21ddab93f22d1b2e1ad94368527f41102b69f16 Mon Sep 17 00:00:00 2001 From: Bo Maryniuk <[email protected]> Date: Fri, 22 Jan 2016 18:37:12 +0100 Subject: [PATCH 04/22] Fix pkg.latest - prevent crash on multiple package installation Fix PEP8: line continuation Replace old fashion string memcopy with the list Fix PEP8: line continuation Bugfix: crash on "key not found" error Fix formatting Check the version of the package, instead of the package name Get version as an explicit parameter Use regexp type for the string. Avoid backslashes where they are not needed Remove unnecessary complexity and string increment Add a new line before the last return Add error handling Cleanup formatting Bugfix: do not treat SLS id as a package name if an empty 'pkgs' list specified. Put 'kwargs' on its own line according to the common pattern --- salt/modules/zypper.py | 43 +++++++++++++--------------------- salt/states/pkg.py | 62 ++++++++++++++++++++++++-------------------------- 2 files changed, 46 insertions(+), 59 deletions(-) diff --git a/salt/modules/zypper.py b/salt/modules/zypper.py index dddcc2f..63b38af 100644 --- a/salt/modules/zypper.py +++ b/salt/modules/zypper.py @@ -598,6 +598,7 @@ def install(name=None, pkgs=None, sources=None, downloadonly=None, + version=None, **kwargs): ''' Install the passed package(s), add refresh=True to run 'zypper refresh' @@ -666,23 +667,20 @@ def install(name=None, 'new': '<new-version>'}} ''' try: - pkg_params, pkg_type = __salt__['pkg_resource.parse_targets']( - name, pkgs, sources, **kwargs - ) + pkg_params, pkg_type = __salt__['pkg_resource.parse_targets'](name, pkgs, sources, **kwargs) except MinionError as exc: raise CommandExecutionError(exc) if pkg_params is None or len(pkg_params) == 0: return {} - version_num = kwargs.get('version') + version_num = version if version_num: if pkgs is None and sources is None: # Allow "version" to work for single package target pkg_params = {name: version_num} else: - log.warning('\'version\' parameter will be ignored for multiple ' - 'package targets') + log.warning("'version' parameter will be ignored for multiple package targets") if pkg_type == 'repository': targets = [] @@ -691,18 +689,13 @@ def install(name=None, if version_num is None: targets.append(param) else: - match = re.match('^([<>])?(=)?([^<>=]+)$', version_num) + match = re.match(r'^([<>])?(=)?([^<>=]+)$', version_num) if match: gt_lt, equal, verstr = match.groups() - prefix = gt_lt or '' - prefix += equal or '' - # If no prefix characters were supplied, use '=' - prefix = prefix or '=' - targets.append('{0}{1}{2}'.format(param, prefix, verstr)) + targets.append('{0}{1}{2}'.format(param, ((gt_lt or '') + (equal or '')) or '=', verstr)) log.debug(targets) else: - msg = ('Invalid version string {0!r} for package ' - '{1!r}'.format(version_num, name)) + msg = ('Invalid version string {0!r} for package {1!r}'.format(version_num, name)) problems.append(msg) if problems: for problem in problems: @@ -731,19 +724,14 @@ def install(name=None, while targets: cmd = cmd_install + targets[:500] targets = targets[500:] - - out = __salt__['cmd.run']( - cmd, - output_loglevel='trace', - python_shell=False - ) - for line in out.splitlines(): - match = re.match( - "^The selected package '([^']+)'.+has lower version", - line - ) - if match: - downgrades.append(match.group(1)) + call = __salt__['cmd.run_all'](cmd, output_loglevel='trace', python_shell=False) + if call['retcode'] != 0: + raise CommandExecutionError(call['stderr']) # Fixme: This needs a proper report mechanism. + else: + for line in call['stdout'].splitlines(): + match = re.match(r"^The selected package '([^']+)'.+has lower version", line) + if match: + downgrades.append(match.group(1)) while downgrades: cmd = cmd_install + ['--force'] + downgrades[:500] @@ -752,6 +740,7 @@ def install(name=None, __salt__['cmd.run'](cmd, output_loglevel='trace', python_shell=False) __context__.pop('pkg.list_pkgs', None) new = list_pkgs() + return salt.utils.compare_dicts(old, new) diff --git a/salt/states/pkg.py b/salt/states/pkg.py index 65ba779..d7c4503 100644 --- a/salt/states/pkg.py +++ b/salt/states/pkg.py @@ -1373,8 +1373,7 @@ def latest( ''' rtag = __gen_rtag() refresh = bool( - salt.utils.is_true(refresh) - or (os.path.isfile(rtag) and refresh is not False) + salt.utils.is_true(refresh) or (os.path.isfile(rtag) and refresh is not False) ) if kwargs.get('sources'): @@ -1392,7 +1391,15 @@ def latest( 'comment': 'Invalidly formatted "pkgs" parameter. See ' 'minion log.'} else: - desired_pkgs = [name] + if isinstance(pkgs, list) and len(pkgs) == 0: + return { + 'name': name, + 'changes': {}, + 'result': True, + 'comment': 'No packages to install provided' + } + else: + desired_pkgs = [name] cur = __salt__['pkg.version'](*desired_pkgs, **kwargs) try: @@ -1431,33 +1438,29 @@ def latest( log.error(msg) problems.append(msg) else: - if salt.utils.compare_versions(ver1=cur[pkg], - oper='!=', - ver2=avail[pkg], - cmp_func=cmp_func): + if salt.utils.compare_versions(ver1=cur[pkg], oper='!=', ver2=avail[pkg], cmp_func=cmp_func): targets[pkg] = avail[pkg] else: if not cur[pkg] or __salt__['portage_config.is_changed_uses'](pkg): targets[pkg] = avail[pkg] else: for pkg in desired_pkgs: - if not avail[pkg]: - if not cur[pkg]: + if pkg not in avail: + if not cur.get(pkg): msg = 'No information found for \'{0}\'.'.format(pkg) log.error(msg) problems.append(msg) - elif not cur[pkg] \ - or salt.utils.compare_versions(ver1=cur[pkg], - oper='<', - ver2=avail[pkg], - cmp_func=cmp_func): + elif not cur.get(pkg) \ + or salt.utils.compare_versions(ver1=cur[pkg], oper='<', ver2=avail[pkg], cmp_func=cmp_func): targets[pkg] = avail[pkg] if problems: - return {'name': name, - 'changes': {}, - 'result': False, - 'comment': ' '.join(problems)} + return { + 'name': name, + 'changes': {}, + 'result': False, + 'comment': ' '.join(problems) + } if targets: # Find up-to-date packages @@ -1471,9 +1474,7 @@ def latest( if __opts__['test']: to_be_upgraded = ', '.join(sorted(targets)) - comment = 'The following packages are set to be ' \ - 'installed/upgraded: ' \ - '{0}'.format(to_be_upgraded) + comment = ['The following packages are set to be installed/upgraded: {0}'.format(to_be_upgraded)] if up_to_date: up_to_date_nb = len(up_to_date) if up_to_date_nb <= 10: @@ -1482,19 +1483,16 @@ def latest( '{0} ({1})'.format(name, cur[name]) for name in up_to_date_sorted ) - comment += ( - ' The following packages are already ' - 'up-to-date: {0}' - ).format(up_to_date_details) + comment.append('The following packages are already up-to-date: {0}'.format(up_to_date_details)) else: - comment += ' {0} packages are already up-to-date'.format( - up_to_date_nb - ) + comment.append('{0} packages are already up-to-date'.format(up_to_date_nb)) - return {'name': name, - 'changes': {}, - 'result': None, - 'comment': comment} + return { + 'name': name, + 'changes': {}, + 'result': None, + 'comment': ' '.join(comment) + } # Build updated list of pkgs to exclude non-targeted ones targeted_pkgs = list(targets.keys()) if pkgs else None -- 2.1.4 ++++++ 0005-Fix-package-status-filtering-on-latest-version-and-i.patch ++++++ >From 2747b83d8009fb7386986ada1640456de2fe5304 Mon Sep 17 00:00:00 2001 From: Bo Maryniuk <[email protected]> Date: Wed, 27 Jan 2016 12:37:06 +0100 Subject: [PATCH 05/22] Fix package status filtering on latest version and implement epoch support --- salt/modules/zypper.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/salt/modules/zypper.py b/salt/modules/zypper.py index 63b38af..4699904 100644 --- a/salt/modules/zypper.py +++ b/salt/modules/zypper.py @@ -245,7 +245,8 @@ def latest_version(*names, **kwargs): package_info = info_available(*names) for name in names: pkg_info = package_info.get(name, {}) - if pkg_info.get('status', '').lower() in ['not installed', 'out-of-date']: + status = pkg_info.get('status', '').lower() + if status.find('not installed') > -1 or status.find('out-of-date') > -1: ret[name] = pkg_info.get('version') # Return a string if only one package name passed @@ -314,7 +315,7 @@ def list_pkgs(versions_as_list=False, **kwargs): __salt__['pkg_resource.stringify'](ret) return ret - cmd = ['rpm', '-qa', '--queryformat', '%{NAME}_|-%{VERSION}_|-%{RELEASE}\\n'] + cmd = ['rpm', '-qa', '--queryformat', '%{NAME}_|-%{VERSION}_|-%{RELEASE}_|-%|EPOCH?{%{EPOCH}}:{}|\\n'] ret = {} out = __salt__['cmd.run']( cmd, @@ -322,7 +323,9 @@ def list_pkgs(versions_as_list=False, **kwargs): python_shell=False ) for line in out.splitlines(): - name, pkgver, rel = line.split('_|-') + 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) -- 2.1.4 ++++++ 0006-add_key-reject_key-do-not-crash-w-Permission-denied-.patch ++++++ >From 697e42284fdd1e18fef1d1747f64cb75be1e0bef Mon Sep 17 00:00:00 2001 From: Duncan Mac-Vicar P <[email protected]> Date: Wed, 10 Feb 2016 09:24:57 +0100 Subject: [PATCH 06/22] add_key/reject_key: do not crash w/Permission denied: '/var/cache/salt/master/.dfn' (#27796) already upstream https://github.com/saltstack/salt/pull/30998 --- salt/crypt.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/salt/crypt.py b/salt/crypt.py index ce27d9f..907ec0c 100644 --- a/salt/crypt.py +++ b/salt/crypt.py @@ -55,6 +55,9 @@ def dropfile(cachedir, user=None): mask = os.umask(191) try: log.info('Rotating AES key') + if os.path.isfile(dfn): + log.info('AES key rotation already requested') + return with salt.utils.fopen(dfn, 'wb+') as fp_: fp_.write('') -- 2.1.4 ++++++ 0007-Force-kill-websocket-s-child-processes-faster-than-d.patch ++++++ >From a1782a9c76f0af20e88fa913dd2ac6dcb20c9c37 Mon Sep 17 00:00:00 2001 From: Bo Maryniuk <[email protected]> Date: Thu, 11 Feb 2016 15:16:43 +0100 Subject: [PATCH 07/22] Force-kill websocket's child processes faster than default two minutes. --- pkg/salt-api.service | 1 + 1 file changed, 1 insertion(+) diff --git a/pkg/salt-api.service b/pkg/salt-api.service index ccf3d34..72379ba 100644 --- a/pkg/salt-api.service +++ b/pkg/salt-api.service @@ -6,6 +6,7 @@ After=network.target Type=simple LimitNOFILE=8192 ExecStart=/usr/bin/salt-api +TimeoutStopSec=3 [Install] WantedBy=multi-user.target -- 2.1.4 ++++++ 0008-Fix-types-in-the-output-data-and-return-just-a-list-.patch ++++++ >From 1f6af694ef7296f4a32d4adcb658f66865a4c38a Mon Sep 17 00:00:00 2001 From: Bo Maryniuk <[email protected]> Date: Thu, 11 Feb 2016 18:26:51 +0100 Subject: [PATCH 08/22] Fix types in the output data and return just a list of products --- salt/modules/zypper.py | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/salt/modules/zypper.py b/salt/modules/zypper.py index 4699904..76170e6 100644 --- a/salt/modules/zypper.py +++ b/salt/modules/zypper.py @@ -1216,14 +1216,18 @@ def list_products(all=False): doc = dom.parseString(__salt__['cmd.run'](("zypper -x products{0}".format(not all and ' -i' or '')), output_loglevel='trace')) for prd in doc.getElementsByTagName('product-list')[0].getElementsByTagName('product'): - p_data = dict() - p_nfo = dict(prd.attributes.items()) - p_name = p_nfo.pop('name') - p_data[p_name] = p_nfo - p_data[p_name]['eol'] = prd.getElementsByTagName('endoflife')[0].getAttribute('text') - descr = _get_first_aggregate_text(prd.getElementsByTagName('description')) - p_data[p_name]['description'] = " ".join([line.strip() for line in descr.split(os.linesep)]) - ret.append(p_data) + p_nfo = dict() + for k_p_nfo, v_p_nfo in prd.attributes.items(): + p_nfo[k_p_nfo] = k_p_nfo not in ['isbase', 'installed'] and v_p_nfo or v_p_nfo == 'true' + p_nfo['eol'] = prd.getElementsByTagName('endoflife')[0].getAttribute('text') + p_nfo['eol_t'] = int(prd.getElementsByTagName('endoflife')[0].getAttribute('time_t')) + p_nfo['description'] = " ".join( + [line.strip() for line in _get_first_aggregate_text( + prd.getElementsByTagName('description') + ).split(os.linesep)] + ) + + ret.append(p_nfo) return ret -- 2.1.4 ++++++ 0009-The-functions-in-the-state-module-that-return-a-retc.patch ++++++ >From 8d77e22c0c570a0a725216f70c41d4fe00a184ca Mon Sep 17 00:00:00 2001 From: "Gareth J. Greenaway" <[email protected]> Date: Sat, 6 Feb 2016 15:52:17 -0800 Subject: [PATCH 09/22] The functions in the state module that return a retcode when something goes wrong, eg. a 1 or a 2, do not return a 0 when things go the way they're supposed to go. With the recent changes to the scheduler to ensure that the retcode is returned this is problematic and results in exceptions when a state function is run from the schedule. This simple fix ensures a default retcode of 0 exists, it is then override in the _set_retcode function if there is an issue with the run --- salt/modules/state.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/salt/modules/state.py b/salt/modules/state.py index 9cb195b..27e588c 100644 --- a/salt/modules/state.py +++ b/salt/modules/state.py @@ -70,6 +70,10 @@ def _set_retcode(ret): ''' Set the return code based on the data back from the state system ''' + + # Set default retcode to 0 + __context__['retcode'] = 0 + if isinstance(ret, list): __context__['retcode'] = 1 return @@ -576,7 +580,6 @@ def highstate(test=None, serial = salt.payload.Serial(__opts__) cache_file = os.path.join(__opts__['cachedir'], 'highstate.p') - _set_retcode(ret) # Work around Windows multiprocessing bug, set __opts__['test'] back to # value from before this function was run. @@ -770,7 +773,6 @@ def sls(mods, except (IOError, OSError): msg = 'Unable to write to SLS cache file {0}. Check permission.' log.error(msg.format(cache_file)) - _set_retcode(ret) # Work around Windows multiprocessing bug, set __opts__['test'] back to # value from before this function was run. @@ -876,8 +878,7 @@ def show_highstate(queue=False, **kwargs): ret = st_.compile_highstate() finally: st_.pop_active() - if isinstance(ret, list): - __context__['retcode'] = 1 + _set_retcode(ret) return ret -- 2.1.4 ++++++ 0010-add-handling-for-OEM-products.patch ++++++ >From a7a0b80b0ca22a0a898ac4a4f671c08337f8f996 Mon Sep 17 00:00:00 2001 From: Michael Calmer <[email protected]> Date: Tue, 16 Feb 2016 12:56:24 +0100 Subject: [PATCH 10/22] add handling for OEM products --- salt/modules/zypper.py | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/salt/modules/zypper.py b/salt/modules/zypper.py index 76170e6..6930f1a 100644 --- a/salt/modules/zypper.py +++ b/salt/modules/zypper.py @@ -1205,6 +1205,9 @@ def list_products(all=False): all List all products available or only installed. Default is False. + Includes handling for OEM products, which read the OEM productline file + and overwrite the release value. + CLI Examples: .. code-block:: bash @@ -1213,6 +1216,7 @@ def list_products(all=False): salt '*' pkg.list_products all=True ''' ret = list() + OEM_PATH = "/var/lib/suseRegister/OEM" doc = dom.parseString(__salt__['cmd.run'](("zypper -x products{0}".format(not all and ' -i' or '')), output_loglevel='trace')) for prd in doc.getElementsByTagName('product-list')[0].getElementsByTagName('product'): @@ -1226,7 +1230,13 @@ def list_products(all=False): prd.getElementsByTagName('description') ).split(os.linesep)] ) - + if 'productline' in p_nfo and p_nfo['productline']: + oem_file = os.path.join(OEM_PATH, p_nfo['productline']) + if os.path.isfile(oem_file): + with salt.utils.fopen(oem_file, 'r') as rfile: + oem_release = rfile.readline().strip() + if oem_release: + p_nfo['release'] = oem_release ret.append(p_nfo) return ret -- 2.1.4 ++++++ 0011-improve-doc-for-list_pkgs.patch ++++++ >From 13fd4a3becab7fd991ae2c6a8ca1c52a51048cef Mon Sep 17 00:00:00 2001 From: Michael Calmer <[email protected]> Date: Wed, 10 Feb 2016 14:20:34 +0100 Subject: [PATCH 11/22] improve doc for list_pkgs --- salt/modules/zypper.py | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/salt/modules/zypper.py b/salt/modules/zypper.py index 6930f1a..56d9ffb 100644 --- a/salt/modules/zypper.py +++ b/salt/modules/zypper.py @@ -291,9 +291,21 @@ def version(*names, **kwargs): def list_pkgs(versions_as_list=False, **kwargs): ''' - List the packages currently installed as a dict:: + List the packages currently installed as a dict with 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>']} + + removed: + not supported + + purge_desired: + not supported CLI Example: -- 2.1.4 ++++++ 0012-implement-version_cmp-for-zypper.patch ++++++ >From 82a9f07f27cf95a7dcff32c8434af9b5d7cf55ad Mon Sep 17 00:00:00 2001 From: Michael Calmer <[email protected]> Date: Wed, 10 Feb 2016 11:47:12 +0100 Subject: [PATCH 12/22] implement version_cmp for zypper --- salt/modules/zypper.py | 65 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) diff --git a/salt/modules/zypper.py b/salt/modules/zypper.py index 56d9ffb..bd9c30a 100644 --- a/salt/modules/zypper.py +++ b/salt/modules/zypper.py @@ -11,6 +11,7 @@ import copy import logging import re import os +import rpm # Import 3rd-party libs # pylint: disable=import-error,redefined-builtin,no-name-in-module @@ -288,6 +289,70 @@ def version(*names, **kwargs): ''' return __salt__['pkg_resource.version'](*names, **kwargs) or {} +def _stringToEVR(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', '', '') + i = verstring.find(':') + if i != -1: + try: + epoch = str(long(verstring[:i])) + except ValueError: + # look, garbage in the epoch field, how fun, kill it + epoch = '0' # this is our fallback, deal + else: + epoch = '0' + j = verstring.find('-') + if j != -1: + version = verstring[i + 1:j] + release = verstring[j + 1:] + else: + version = verstring[i + 1:] + release = '' + return (epoch, version, release) + +def version_cmp(ver1, ver2): + ''' + .. versionadded:: 2015.5.4 + + 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: + cmp_result = rpm.labelCompare( + _stringToEVR(ver1), + _stringToEVR(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) + def list_pkgs(versions_as_list=False, **kwargs): ''' -- 2.1.4 ++++++ 0013-pylint-changes.patch ++++++ >From c26d1b6987a06e972749a10af1c54befae14c6e6 Mon Sep 17 00:00:00 2001 From: Michael Calmer <[email protected]> Date: Tue, 16 Feb 2016 13:48:50 +0100 Subject: [PATCH 13/22] pylint changes --- salt/modules/zypper.py | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/salt/modules/zypper.py b/salt/modules/zypper.py index bd9c30a..7448f8b 100644 --- a/salt/modules/zypper.py +++ b/salt/modules/zypper.py @@ -2,7 +2,7 @@ ''' Package support for openSUSE via the zypper package manager -:depends: - ``zypp`` Python module. Install with ``zypper install python-zypp`` +:depends: - ``rpm`` Python module. Install with ``zypper install rpm-python`` ''' # Import python libs @@ -11,10 +11,10 @@ import copy import logging import re import os -import rpm # Import 3rd-party libs # pylint: disable=import-error,redefined-builtin,no-name-in-module +import rpm import salt.ext.six as six from salt.ext.six.moves import configparser from salt.ext.six.moves.urllib.parse import urlparse as _urlparse @@ -289,7 +289,8 @@ def version(*names, **kwargs): ''' return __salt__['pkg_resource.version'](*names, **kwargs) or {} -def _stringToEVR(verstring): + +def _string_to_evr(verstring): ''' Split the version string into epoch, version and release and return this as tuple. @@ -304,24 +305,25 @@ def _stringToEVR(verstring): ''' if verstring in [None, '']: return ('0', '', '') - i = verstring.find(':') - if i != -1: + idx_e = verstring.find(':') + if idx_e != -1: try: - epoch = str(long(verstring[:i])) + 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 + epoch = '0' # this is our fallback, deal else: epoch = '0' - j = verstring.find('-') - if j != -1: - version = verstring[i + 1:j] - release = verstring[j + 1:] + idx_r = verstring.find('-') + if idx_r != -1: + version = verstring[idx_e + 1:idx_r] + release = verstring[idx_r + 1:] else: - version = verstring[i + 1:] + version = verstring[idx_e + 1:] release = '' return (epoch, version, release) + def version_cmp(ver1, ver2): ''' .. versionadded:: 2015.5.4 @@ -338,8 +340,8 @@ def version_cmp(ver1, ver2): ''' try: cmp_result = rpm.labelCompare( - _stringToEVR(ver1), - _stringToEVR(ver2) + _string_to_evr(ver1), + _string_to_evr(ver2) ) if cmp_result not in (-1, 0, 1): raise Exception( -- 2.1.4 ++++++ 0014-Check-if-rpm-python-can-be-imported.patch ++++++ >From 4accc710ab2f92118f4777d13bc585d26e8e939e Mon Sep 17 00:00:00 2001 From: Michael Calmer <[email protected]> Date: Wed, 17 Feb 2016 08:49:15 +0100 Subject: [PATCH 14/22] Check if rpm-python can be imported --- salt/modules/zypper.py | 36 +++++++++++++++++++++--------------- 1 file changed, 21 insertions(+), 15 deletions(-) diff --git a/salt/modules/zypper.py b/salt/modules/zypper.py index 7448f8b..d44ad6a 100644 --- a/salt/modules/zypper.py +++ b/salt/modules/zypper.py @@ -14,10 +14,15 @@ import os # Import 3rd-party libs # pylint: disable=import-error,redefined-builtin,no-name-in-module -import rpm 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 @@ -338,21 +343,22 @@ def version_cmp(ver1, ver2): salt '*' pkg.version_cmp '0.2-001' '0.2.0.1-002' ''' - 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) + 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 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) -- 2.1.4 ++++++ 0015-call-zypper-with-option-non-interactive-everywhere.patch ++++++ >From 5009e290b5a318b168fd03095ced7043203fe34c Mon Sep 17 00:00:00 2001 From: Michael Calmer <[email protected]> Date: Thu, 18 Feb 2016 10:12:55 +0100 Subject: [PATCH 15/22] call zypper with option --non-interactive everywhere --- salt/modules/zypper.py | 49 ++++++++++++++++++++++++++++++++----------------- 1 file changed, 32 insertions(+), 17 deletions(-) diff --git a/salt/modules/zypper.py b/salt/modules/zypper.py index d44ad6a..cb26b51 100644 --- a/salt/modules/zypper.py +++ b/salt/modules/zypper.py @@ -56,6 +56,21 @@ def __virtual__(): return __virtualname__ +def _zypper(as_list=False): + ''' + Return zypper command with default options as a string. + + CMD: zypper --non-interactive + + as_list: + if set to True, the command and the default options + are returned as a list + ''' + if as_list: + return ['zypper', '--non-interactive'] + return "zypper --non-interactive " + + def list_upgrades(refresh=True): ''' List all available package upgrades on this system @@ -70,7 +85,7 @@ def list_upgrades(refresh=True): refresh_db() ret = {} call = __salt__['cmd.run_all']( - 'zypper list-updates', output_loglevel='trace' + _zypper() + 'list-updates', output_loglevel='trace' ) if call['retcode'] != 0: comment = '' @@ -185,7 +200,7 @@ def info_available(*names, **kwargs): # Run in batches while batch: - cmd = 'zypper info -t package {0}'.format(' '.join(batch[:batch_size])) + cmd = '{0} info -t package {1}'.format(_zypper(), ' '.join(batch[:batch_size])) pkg_info.extend(re.split(r"Information for package*", __salt__['cmd.run_stdout'](cmd, output_loglevel='trace'))) batch = batch[batch_size:] @@ -494,7 +509,7 @@ def del_repo(repo): repos_cfg = _get_configured_repos() for alias in repos_cfg.sections(): if alias == repo: - cmd = ('zypper -x --non-interactive rr --loose-auth --loose-query {0}'.format(alias)) + cmd = ('{0} -x rr --loose-auth --loose-query {1}'.format(_zypper(), alias)) doc = dom.parseString(__salt__['cmd.run'](cmd, output_loglevel='trace')) msg = doc.getElementsByTagName('message') if doc.getElementsByTagName('progress') and msg: @@ -583,7 +598,7 @@ def mod_repo(repo, **kwargs): try: # Try to parse the output and find the error, # but this not always working (depends on Zypper version) - doc = dom.parseString(__salt__['cmd.run'](('zypper -x ar {0} \'{1}\''.format(url, repo)), + doc = dom.parseString(__salt__['cmd.run'](('{0} -x ar {1} \'{2}\''.format(_zypper(), url, repo)), output_loglevel='trace')) except Exception: # No XML out available, but it is still unknown the state of the result. @@ -629,7 +644,7 @@ def mod_repo(repo, **kwargs): cmd_opt.append("--name='{0}'".format(kwargs.get('humanname'))) if cmd_opt: - __salt__['cmd.run'](('zypper -x mr {0} \'{1}\''.format(' '.join(cmd_opt), repo)), + __salt__['cmd.run'](('{0} -x mr {1} \'{2}\''.format(_zypper(), ' '.join(cmd_opt), repo)), output_loglevel='trace') # If repo nor added neither modified, error should be thrown @@ -652,7 +667,7 @@ def refresh_db(): salt '*' pkg.refresh_db ''' - cmd = 'zypper refresh' + cmd = _zypper() + 'refresh' ret = {} call = __salt__['cmd.run_all'](cmd, output_loglevel='trace') if call['retcode'] != 0: @@ -799,7 +814,7 @@ def install(name=None, log.info('Targeting repo {0!r}'.format(fromrepo)) else: fromrepoopt = '' - cmd_install = ['zypper', '--non-interactive'] + cmd_install = _zypper(as_list=True) if not refresh: cmd_install.append('--no-refresh') cmd_install += ['install', '--name', '--auto-agree-with-licenses'] @@ -855,7 +870,7 @@ def upgrade(refresh=True): if salt.utils.is_true(refresh): refresh_db() old = list_pkgs() - cmd = 'zypper --non-interactive update --auto-agree-with-licenses' + cmd = _zypper() + 'update --auto-agree-with-licenses' call = __salt__['cmd.run_all'](cmd, output_loglevel='trace') if call['retcode'] != 0: ret['result'] = False @@ -887,8 +902,8 @@ def _uninstall(action='remove', name=None, pkgs=None): return {} while targets: cmd = ( - 'zypper --non-interactive remove {0} {1}' - .format(purge_arg, ' '.join(targets[:500])) + '{0} remove {1} {2}' + .format(_zypper(), purge_arg, ' '.join(targets[:500])) ) __salt__['cmd.run'](cmd, output_loglevel='trace') targets = targets[500:] @@ -1003,7 +1018,7 @@ def clean_locks(): if not os.path.exists("/etc/zypp/locks"): return out - doc = dom.parseString(__salt__['cmd.run']('zypper --non-interactive -x cl', output_loglevel='trace')) + doc = dom.parseString(__salt__['cmd.run'](_zypper() + '-x cl', output_loglevel='trace')) for node in doc.getElementsByTagName("message"): text = node.childNodes[0].nodeValue.lower() if text.startswith(LCK): @@ -1041,7 +1056,7 @@ def remove_lock(packages, **kwargs): # pylint: disable=unused-argument missing.append(pkg) if removed: - __salt__['cmd.run'](('zypper --non-interactive rl {0}'.format(' '.join(removed))), + __salt__['cmd.run'](('{0} rl {1}'.format(_zypper(), ' '.join(removed))), output_loglevel='trace') return {'removed': len(removed), 'not_found': missing} @@ -1071,7 +1086,7 @@ def add_lock(packages, **kwargs): # pylint: disable=unused-argument added.append(pkg) if added: - __salt__['cmd.run'](('zypper --non-interactive al {0}'.format(' '.join(added))), + __salt__['cmd.run'](('{0} al {1}'.format(_zypper(), ' '.join(added))), output_loglevel='trace') return {'added': len(added), 'packages': added} @@ -1204,7 +1219,7 @@ def _get_patterns(installed_only=None): List all known patterns in repos. ''' patterns = {} - doc = dom.parseString(__salt__['cmd.run'](('zypper --xmlout se -t pattern'), + doc = dom.parseString(__salt__['cmd.run']((_zypper() + '--xmlout se -t pattern'), output_loglevel='trace')) for element in doc.getElementsByTagName('solvable'): installed = element.getAttribute('status') == 'installed' @@ -1253,7 +1268,7 @@ def search(criteria): salt '*' pkg.search <criteria> ''' - doc = dom.parseString(__salt__['cmd.run'](('zypper --xmlout se {0}'.format(criteria)), + doc = dom.parseString(__salt__['cmd.run'](('{0} --xmlout se {1}'.format(_zypper(), criteria)), output_loglevel='trace')) solvables = doc.getElementsByTagName('solvable') if not solvables: @@ -1302,7 +1317,7 @@ def list_products(all=False): ''' ret = list() OEM_PATH = "/var/lib/suseRegister/OEM" - doc = dom.parseString(__salt__['cmd.run'](("zypper -x products{0}".format(not all and ' -i' or '')), + doc = dom.parseString(__salt__['cmd.run'](("{0} -x products{1}".format(_zypper(), not all and ' -i' or '')), output_loglevel='trace')) for prd in doc.getElementsByTagName('product-list')[0].getElementsByTagName('product'): p_nfo = dict() @@ -1342,7 +1357,7 @@ def download(*packages): raise CommandExecutionError("No packages has been specified.") doc = dom.parseString(__salt__['cmd.run']( - ('zypper -x --non-interactive download {0}'.format(' '.join(packages))), + ('{0} -x download {1}'.format(_zypper(), ' '.join(packages))), output_loglevel='trace')) pkg_ret = {} for dld_result in doc.getElementsByTagName("download-result"): -- 2.1.4 ++++++ 0016-write-a-zypper-command-builder-function.patch ++++++ >From 8d25c4c8906581fa44380f72f0f754b56f5e30c3 Mon Sep 17 00:00:00 2001 From: Michael Calmer <[email protected]> Date: Fri, 19 Feb 2016 11:50:31 +0100 Subject: [PATCH 16/22] write a zypper command builder function --- salt/modules/zypper.py | 62 +++++++++++++++++++++++--------------------------- 1 file changed, 29 insertions(+), 33 deletions(-) diff --git a/salt/modules/zypper.py b/salt/modules/zypper.py index cb26b51..f878c95 100644 --- a/salt/modules/zypper.py +++ b/salt/modules/zypper.py @@ -56,19 +56,18 @@ def __virtual__(): return __virtualname__ -def _zypper(as_list=False): +def _zypper(*opts): ''' - Return zypper command with default options as a string. + Return zypper command with default options as a list. - CMD: zypper --non-interactive + opts + additional options for zypper command - as_list: - if set to True, the command and the default options - are returned as a list ''' - if as_list: - return ['zypper', '--non-interactive'] - return "zypper --non-interactive " + cmd = ['zypper', '--non-interactive'] + cmd.extend(opts) + + return cmd def list_upgrades(refresh=True): @@ -85,7 +84,7 @@ def list_upgrades(refresh=True): refresh_db() ret = {} call = __salt__['cmd.run_all']( - _zypper() + 'list-updates', output_loglevel='trace' + _zypper('list-updates'), output_loglevel='trace' ) if call['retcode'] != 0: comment = '' @@ -200,7 +199,7 @@ def info_available(*names, **kwargs): # Run in batches while batch: - cmd = '{0} info -t package {1}'.format(_zypper(), ' '.join(batch[:batch_size])) + cmd = _zypper('info', '-t', 'package', *batch[:batch_size]) pkg_info.extend(re.split(r"Information for package*", __salt__['cmd.run_stdout'](cmd, output_loglevel='trace'))) batch = batch[batch_size:] @@ -509,7 +508,7 @@ def del_repo(repo): repos_cfg = _get_configured_repos() for alias in repos_cfg.sections(): if alias == repo: - cmd = ('{0} -x rr --loose-auth --loose-query {1}'.format(_zypper(), alias)) + cmd = _zypper('-x', 'rr', '--loose-auth', '--loose-query', alias) doc = dom.parseString(__salt__['cmd.run'](cmd, output_loglevel='trace')) msg = doc.getElementsByTagName('message') if doc.getElementsByTagName('progress') and msg: @@ -598,8 +597,8 @@ def mod_repo(repo, **kwargs): try: # Try to parse the output and find the error, # but this not always working (depends on Zypper version) - doc = dom.parseString(__salt__['cmd.run'](('{0} -x ar {1} \'{2}\''.format(_zypper(), url, repo)), - output_loglevel='trace')) + doc = dom.parseString(__salt__['cmd.run']( + _zypper('-x', 'ar', url, repo), output_loglevel='trace')) except Exception: # No XML out available, but it is still unknown the state of the result. pass @@ -644,7 +643,8 @@ def mod_repo(repo, **kwargs): cmd_opt.append("--name='{0}'".format(kwargs.get('humanname'))) if cmd_opt: - __salt__['cmd.run'](('{0} -x mr {1} \'{2}\''.format(_zypper(), ' '.join(cmd_opt), repo)), + cmd_opt.append(repo) + __salt__['cmd.run'](_zypper('-x', 'mr', *cmd_opt), output_loglevel='trace') # If repo nor added neither modified, error should be thrown @@ -667,7 +667,7 @@ def refresh_db(): salt '*' pkg.refresh_db ''' - cmd = _zypper() + 'refresh' + cmd = _zypper('refresh') ret = {} call = __salt__['cmd.run_all'](cmd, output_loglevel='trace') if call['retcode'] != 0: @@ -814,7 +814,7 @@ def install(name=None, log.info('Targeting repo {0!r}'.format(fromrepo)) else: fromrepoopt = '' - cmd_install = _zypper(as_list=True) + cmd_install = _zypper() if not refresh: cmd_install.append('--no-refresh') cmd_install += ['install', '--name', '--auto-agree-with-licenses'] @@ -870,7 +870,7 @@ def upgrade(refresh=True): if salt.utils.is_true(refresh): refresh_db() old = list_pkgs() - cmd = _zypper() + 'update --auto-agree-with-licenses' + cmd = _zypper('update', '--auto-agree-with-licenses') call = __salt__['cmd.run_all'](cmd, output_loglevel='trace') if call['retcode'] != 0: ret['result'] = False @@ -901,10 +901,7 @@ def _uninstall(action='remove', name=None, pkgs=None): if not targets: return {} while targets: - cmd = ( - '{0} remove {1} {2}' - .format(_zypper(), purge_arg, ' '.join(targets[:500])) - ) + cmd = _zypper('remove', purge_arg, *targets[:500]) __salt__['cmd.run'](cmd, output_loglevel='trace') targets = targets[500:] __context__.pop('pkg.list_pkgs', None) @@ -1018,7 +1015,7 @@ def clean_locks(): if not os.path.exists("/etc/zypp/locks"): return out - doc = dom.parseString(__salt__['cmd.run'](_zypper() + '-x cl', output_loglevel='trace')) + doc = dom.parseString(__salt__['cmd.run'](_zypper('-x', 'cl'), output_loglevel='trace')) for node in doc.getElementsByTagName("message"): text = node.childNodes[0].nodeValue.lower() if text.startswith(LCK): @@ -1056,8 +1053,7 @@ def remove_lock(packages, **kwargs): # pylint: disable=unused-argument missing.append(pkg) if removed: - __salt__['cmd.run'](('{0} rl {1}'.format(_zypper(), ' '.join(removed))), - output_loglevel='trace') + __salt__['cmd.run'](_zypper('rl', *removed), output_loglevel='trace') return {'removed': len(removed), 'not_found': missing} @@ -1086,8 +1082,7 @@ def add_lock(packages, **kwargs): # pylint: disable=unused-argument added.append(pkg) if added: - __salt__['cmd.run'](('{0} al {1}'.format(_zypper(), ' '.join(added))), - output_loglevel='trace') + __salt__['cmd.run'](_zypper('al', *added), output_loglevel='trace') return {'added': len(added), 'packages': added} @@ -1219,7 +1214,7 @@ def _get_patterns(installed_only=None): List all known patterns in repos. ''' patterns = {} - doc = dom.parseString(__salt__['cmd.run']((_zypper() + '--xmlout se -t pattern'), + doc = dom.parseString(__salt__['cmd.run'](_zypper('--xmlout', 'se', '-t', 'pattern'), output_loglevel='trace')) for element in doc.getElementsByTagName('solvable'): installed = element.getAttribute('status') == 'installed' @@ -1268,7 +1263,7 @@ def search(criteria): salt '*' pkg.search <criteria> ''' - doc = dom.parseString(__salt__['cmd.run'](('{0} --xmlout se {1}'.format(_zypper(), criteria)), + doc = dom.parseString(__salt__['cmd.run'](_zypper('--xmlout', 'se', criteria), output_loglevel='trace')) solvables = doc.getElementsByTagName('solvable') if not solvables: @@ -1317,8 +1312,10 @@ def list_products(all=False): ''' ret = list() OEM_PATH = "/var/lib/suseRegister/OEM" - doc = dom.parseString(__salt__['cmd.run'](("{0} -x products{1}".format(_zypper(), not all and ' -i' or '')), - output_loglevel='trace')) + cmd = _zypper('-x', 'products') + if not all: + cmd.append('-i') + doc = dom.parseString(__salt__['cmd.run'](cmd, output_loglevel='trace')) for prd in doc.getElementsByTagName('product-list')[0].getElementsByTagName('product'): p_nfo = dict() for k_p_nfo, v_p_nfo in prd.attributes.items(): @@ -1357,8 +1354,7 @@ def download(*packages): raise CommandExecutionError("No packages has been specified.") doc = dom.parseString(__salt__['cmd.run']( - ('{0} -x download {1}'.format(_zypper(), ' '.join(packages))), - output_loglevel='trace')) + _zypper('-x', 'download', *packages), output_loglevel='trace')) pkg_ret = {} for dld_result in doc.getElementsByTagName("download-result"): repo = dld_result.getElementsByTagName("repository")[0] -- 2.1.4 ++++++ 0017-Fix-crash-with-scheduler-and-runners-31106.patch ++++++ >From 978afba658cff38ebc1d6a7aecee4813796db528 Mon Sep 17 00:00:00 2001 From: Duncan Mac-Vicar P <[email protected]> Date: Sat, 13 Feb 2016 00:23:30 +0100 Subject: [PATCH 17/22] Fix crash with scheduler and runners (#31106) * runner wrapper ClientFuncsDict do not provide access to 'pack' attribute * runners do not provide retcode, therefore ignore it in the schedule if it is not provided by __context__ --- salt/client/mixins.py | 6 ++++++ salt/utils/schedule.py | 5 ++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/salt/client/mixins.py b/salt/client/mixins.py index cdb1d0c..6fa3e6f 100644 --- a/salt/client/mixins.py +++ b/salt/client/mixins.py @@ -53,6 +53,12 @@ class ClientFuncsDict(collections.MutableMapping): def __init__(self, client): self.client = client + def __getattr__(self, attr): + ''' + Provide access eg. to 'pack' + ''' + return getattr(self.client.functions, attr) + def __setitem__(self, key, val): raise NotImplementedError() diff --git a/salt/utils/schedule.py b/salt/utils/schedule.py index cae5fcf..5ed49f7 100644 --- a/salt/utils/schedule.py +++ b/salt/utils/schedule.py @@ -700,7 +700,10 @@ class Schedule(object): ) ) - ret['retcode'] = self.functions.pack['__context__']['retcode'] + # runners do not provide retcode + if 'retcode' in self.functions.pack['__context__']: + ret['retcode'] = self.functions.pack['__context__']['retcode'] + ret['success'] = True except Exception: log.exception("Unhandled exception running {0}".format(ret['fun'])) -- 2.1.4 ++++++ 0018-unify-behavior-of-refresh.patch ++++++ >From 29ab56413c60c958d5d62b1acdea5a97ce80fdb9 Mon Sep 17 00:00:00 2001 From: Michael Calmer <[email protected]> Date: Thu, 18 Feb 2016 12:30:19 +0100 Subject: [PATCH 18/22] unify behavior of refresh --- salt/modules/zypper.py | 30 ++++++++++++++++++++++++------ 1 file changed, 24 insertions(+), 6 deletions(-) diff --git a/salt/modules/zypper.py b/salt/modules/zypper.py index f878c95..f5b09c0 100644 --- a/salt/modules/zypper.py +++ b/salt/modules/zypper.py @@ -74,6 +74,11 @@ def list_upgrades(refresh=True): ''' List all available package upgrades on this system + refresh + force a refresh if set to True (default). + If set to False it depends on zypper if a refresh is + executed. + CLI Example: .. code-block:: bash @@ -175,6 +180,11 @@ def info_available(*names, **kwargs): ''' Return the information of the named package available for the system. + refresh + force a refresh if set to True (default). + If set to False it depends on zypper if a refresh is + executed or not. + CLI example: .. code-block:: bash @@ -657,7 +667,7 @@ def mod_repo(repo, **kwargs): def refresh_db(): ''' - Just run a ``zypper refresh``, return a dict:: + Force a repository refresh by calling ``zypper refresh --force``, return a dict:: {'<database name>': Bool} @@ -667,7 +677,7 @@ def refresh_db(): salt '*' pkg.refresh_db ''' - cmd = _zypper('refresh') + cmd = _zypper('refresh', '--force') ret = {} call = __salt__['cmd.run_all'](cmd, output_loglevel='trace') if call['retcode'] != 0: @@ -704,7 +714,7 @@ def install(name=None, version=None, **kwargs): ''' - Install the passed package(s), add refresh=True to run 'zypper refresh' + Install the passed package(s), add refresh=True to force a 'zypper refresh' before package is installed. name @@ -721,7 +731,9 @@ def install(name=None, salt '*' pkg.install <package name> refresh - Whether or not to refresh the package database before installing. + force a refresh if set to True. + If set to False (default) it depends on zypper if a refresh is + executed. fromrepo Specify a package repository to install from. @@ -769,6 +781,9 @@ def install(name=None, {'<package>': {'old': '<old-version>', 'new': '<new-version>'}} ''' + if salt.utils.is_true(refresh): + refresh_db() + try: pkg_params, pkg_type = __salt__['pkg_resource.parse_targets'](name, pkgs, sources, **kwargs) except MinionError as exc: @@ -815,8 +830,6 @@ def install(name=None, else: fromrepoopt = '' cmd_install = _zypper() - if not refresh: - cmd_install.append('--no-refresh') cmd_install += ['install', '--name', '--auto-agree-with-licenses'] if downloadonly: cmd_install.append('--download-only') @@ -851,6 +864,11 @@ def upgrade(refresh=True): ''' Run a full system upgrade, a zypper upgrade + refresh + force a refresh if set to True (default). + If set to False it depends on zypper if a refresh is + executed. + Return a dict containing the new package names and versions:: {'<package>': {'old': '<old-version>', -- 2.1.4 ++++++ 0019-add-refresh-option-to-more-functions.patch ++++++ >From 478871aebfcb2ddf1b1c2a47b4fccb820180c9ed Mon Sep 17 00:00:00 2001 From: Michael Calmer <[email protected]> Date: Thu, 18 Feb 2016 12:39:52 +0100 Subject: [PATCH 19/22] add refresh option to more functions --- salt/modules/zypper.py | 40 ++++++++++++++++++++++++++++++++++++---- 1 file changed, 36 insertions(+), 4 deletions(-) diff --git a/salt/modules/zypper.py b/salt/modules/zypper.py index f5b09c0..9afdeef 100644 --- a/salt/modules/zypper.py +++ b/salt/modules/zypper.py @@ -1245,16 +1245,24 @@ def _get_patterns(installed_only=None): return patterns -def list_patterns(): +def list_patterns(refresh=False): ''' List all known patterns from available repos. + refresh + force a refresh if set to True. + If set to False (default) it depends on zypper if a refresh is + executed. + CLI Examples: .. code-block:: bash salt '*' pkg.list_patterns ''' + if salt.utils.is_true(refresh): + refresh_db() + return _get_patterns() @@ -1271,16 +1279,24 @@ def list_installed_patterns(): return _get_patterns(installed_only=True) -def search(criteria): +def search(criteria, refresh=False): ''' List known packags, available to the system. + refresh + force a refresh if set to True. + If set to False (default) it depends on zypper if a refresh is + executed. + CLI Examples: .. code-block:: bash salt '*' pkg.search <criteria> ''' + if salt.utils.is_true(refresh): + refresh_db() + doc = dom.parseString(__salt__['cmd.run'](_zypper('--xmlout', 'se', criteria), output_loglevel='trace')) solvables = doc.getElementsByTagName('solvable') @@ -1311,13 +1327,18 @@ def _get_first_aggregate_text(node_list): return '\n'.join(out) -def list_products(all=False): +def list_products(all=False, refresh=False): ''' List all available or installed SUSE products. all List all products available or only installed. Default is False. + refresh + force a refresh if set to True. + If set to False (default) it depends on zypper if a refresh is + executed. + Includes handling for OEM products, which read the OEM productline file and overwrite the release value. @@ -1328,6 +1349,9 @@ def list_products(all=False): salt '*' pkg.list_products salt '*' pkg.list_products all=True ''' + if salt.utils.is_true(refresh): + refresh_db() + ret = list() OEM_PATH = "/var/lib/suseRegister/OEM" cmd = _zypper('-x', 'products') @@ -1357,10 +1381,15 @@ def list_products(all=False): return ret -def download(*packages): +def download(refresh=False, *packages): """ Download packages to the local disk. + refresh + force a refresh if set to True. + If set to False (default) it depends on zypper if a refresh is + executed. + CLI example: .. code-block:: bash @@ -1371,6 +1400,9 @@ def download(*packages): if not packages: raise CommandExecutionError("No packages has been specified.") + if salt.utils.is_true(refresh): + refresh_db() + doc = dom.parseString(__salt__['cmd.run']( _zypper('-x', 'download', *packages), output_loglevel='trace')) pkg_ret = {} -- 2.1.4 ++++++ 0020-simplify-checking-the-refresh-paramater.patch ++++++ >From 0a09ae513698029eb1e05cd8b6e6b45d2830a0cb Mon Sep 17 00:00:00 2001 From: Michael Calmer <[email protected]> Date: Sun, 21 Feb 2016 11:26:51 +0100 Subject: [PATCH 20/22] simplify checking the refresh paramater --- salt/modules/zypper.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/salt/modules/zypper.py b/salt/modules/zypper.py index 9afdeef..e2cd5f9 100644 --- a/salt/modules/zypper.py +++ b/salt/modules/zypper.py @@ -85,7 +85,7 @@ def list_upgrades(refresh=True): salt '*' pkg.list_upgrades ''' - if salt.utils.is_true(refresh): + if refresh: refresh_db() ret = {} call = __salt__['cmd.run_all']( @@ -200,7 +200,7 @@ def info_available(*names, **kwargs): names = sorted(list(set(names))) # Refresh db before extracting the latest package - if salt.utils.is_true(kwargs.pop('refresh', True)): + if kwargs.pop('refresh', True): refresh_db() pkg_info = [] @@ -781,7 +781,7 @@ def install(name=None, {'<package>': {'old': '<old-version>', 'new': '<new-version>'}} ''' - if salt.utils.is_true(refresh): + if refresh: refresh_db() try: @@ -885,7 +885,7 @@ def upgrade(refresh=True): 'comment': '', } - if salt.utils.is_true(refresh): + if refresh: refresh_db() old = list_pkgs() cmd = _zypper('update', '--auto-agree-with-licenses') @@ -1260,7 +1260,7 @@ def list_patterns(refresh=False): salt '*' pkg.list_patterns ''' - if salt.utils.is_true(refresh): + if refresh: refresh_db() return _get_patterns() @@ -1294,7 +1294,7 @@ def search(criteria, refresh=False): salt '*' pkg.search <criteria> ''' - if salt.utils.is_true(refresh): + if refresh: refresh_db() doc = dom.parseString(__salt__['cmd.run'](_zypper('--xmlout', 'se', criteria), @@ -1349,7 +1349,7 @@ def list_products(all=False, refresh=False): salt '*' pkg.list_products salt '*' pkg.list_products all=True ''' - if salt.utils.is_true(refresh): + if refresh: refresh_db() ret = list() @@ -1400,7 +1400,7 @@ def download(refresh=False, *packages): if not packages: raise CommandExecutionError("No packages has been specified.") - if salt.utils.is_true(refresh): + if refresh: refresh_db() doc = dom.parseString(__salt__['cmd.run']( -- 2.1.4 ++++++ 0021-do-not-change-kwargs-in-refresh-while-checking-a-val.patch ++++++ >From ea6898f82ddc21c73f3ea369e6af241753a2ceda Mon Sep 17 00:00:00 2001 From: Michael Calmer <[email protected]> Date: Mon, 22 Feb 2016 09:51:01 +0100 Subject: [PATCH 21/22] do not change kwargs in refresh while checking a value --- salt/modules/zypper.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/salt/modules/zypper.py b/salt/modules/zypper.py index e2cd5f9..1499b27 100644 --- a/salt/modules/zypper.py +++ b/salt/modules/zypper.py @@ -200,7 +200,7 @@ def info_available(*names, **kwargs): names = sorted(list(set(names))) # Refresh db before extracting the latest package - if kwargs.pop('refresh', True): + if kwargs.get('refresh', True): refresh_db() pkg_info = [] -- 2.1.4 ++++++ 0022-fix-argument-handling-for-pkg.download.patch ++++++ >From c9bab6bb32f9ca2e65b6e0c24283146b66bf91be Mon Sep 17 00:00:00 2001 From: Michael Calmer <[email protected]> Date: Tue, 23 Feb 2016 11:46:09 +0100 Subject: [PATCH 22/22] fix argument handling for pkg.download --- salt/modules/zypper.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/salt/modules/zypper.py b/salt/modules/zypper.py index 1499b27..33e5da9 100644 --- a/salt/modules/zypper.py +++ b/salt/modules/zypper.py @@ -1381,7 +1381,7 @@ def list_products(all=False, refresh=False): return ret -def download(refresh=False, *packages): +def download(*packages, **kwargs): """ Download packages to the local disk. @@ -1397,6 +1397,7 @@ def download(refresh=False, *packages): salt '*' pkg.download httpd salt '*' pkg.download httpd postfix """ + refresh = kwargs.get('refresh', False) if not packages: raise CommandExecutionError("No packages has been specified.") -- 2.1.4 ++++++ salt-2015.8.3.tar.gz -> salt-2015.8.7.tar.gz ++++++ /work/SRC/openSUSE:Factory/salt/salt-2015.8.3.tar.gz /work/SRC/openSUSE:Factory/.salt.new/salt-2015.8.7.tar.gz differ: char 5, line 1
