From 1592ccc37e4630d69eb90372fa5ff140a0f406dc8dd58d0874207120ea4207f1 Mon Sep 17 00:00:00 2001 From: Dominique Leuenberger Date: Wed, 24 Feb 2016 17:43:06 +0000 Subject: [PATCH] Accepting request 361294 from systemsmanagement:saltstack - fix argument handling of pkg.download Add: 0022-fix-argument-handling-for-pkg.download.patch - 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 - Fix crash with scheduler and runners Add: 0017-Fix-crash-with-scheduler-and-runners-31106.patch - Call zypper always with --non-interactive Add: * 0015-call-zypper-with-option-non-interactive-everywhere.patch * 0016-write-a-zypper-command-builder-function.patch - require rpm-python on SUSE for zypper support - 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 - 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 - 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 - Stop salt-api daemon faster (bsc#963322) Add: * 0007-Force-kill-websocket-s-child-processes-faster-than-d.patch - Do not crash on salt-key reject/delete consecutive calls. Add: * 0006-add_key-reject_key-do-not-crash-w-Permission-denied-.patch - 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 - Fix latest version available comparison and implement epoch support in Zypper module. Add: * 0009-Fix-package-status-filtering-on-latest-version-and-i.patch - Update patch from opensuse to upstream version. Update: * 0008-Fix-pkg.latest-prevent-crash-on-multiple-package-ins.patch - Fix dependencies to Salt subpackages requiring release along the version. - 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 - 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 - 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 OBS-URL: https://build.opensuse.org/request/show/361294 OBS-URL: https://build.opensuse.org/package/show/openSUSE:Factory/salt?expand=0&rev=55 --- ...-We-don-t-have-python-systemd-so-not.patch | 27 ++ ...n-salt-master-as-dedicated-salt-user.patch | 53 ++++ ...trings-are-properly-encoded-in-UTF-8.patch | 49 ++++ ...revent-crash-on-multiple-package-ins.patch | 255 ++++++++++++++++++ ...us-filtering-on-latest-version-and-i.patch | 47 ++++ ...ey-do-not-crash-w-Permission-denied-.patch | 29 ++ ...cket-s-child-processes-faster-than-d.patch | 25 ++ ...-output-data-and-return-just-a-list-.patch | 44 +++ ...-the-state-module-that-return-a-retc.patch | 59 ++++ 0010-add-handling-for-OEM-products.patch | 49 ++++ 0011-improve-doc-for-list_pkgs.patch | 40 +++ 0012-implement-version_cmp-for-zypper.patch | 95 +++++++ 0013-pylint-changes.patch | 93 +++++++ ...-Check-if-rpm-python-can-be-imported.patch | 70 +++++ ...th-option-non-interactive-everywhere.patch | 184 +++++++++++++ ...te-a-zypper-command-builder-function.patch | 201 ++++++++++++++ ...ash-with-scheduler-and-runners-31106.patch | 49 ++++ 0018-unify-behavior-of-refresh.patch | 109 ++++++++ ...add-refresh-option-to-more-functions.patch | 125 +++++++++ ...plify-checking-the-refresh-paramater.patch | 88 ++++++ ...args-in-refresh-while-checking-a-val.patch | 25 ++ ...x-argument-handling-for-pkg.download.patch | 33 +++ ...484309a5c776974e723f3da0f5181f4bdb86.patch | 74 ----- salt-2015.8-pkg-zypper-attr-filtering.patch | 201 -------------- salt-2015.8-schedule-ret.patch | 170 ------------ salt-2015.8-zypper-info.patch | 20 -- salt-2015.8.3.tar.gz | 3 - salt-2015.8.7.tar.gz | 3 + salt.changes | 165 ++++++++++++ salt.spec | 100 +++++-- use-forking-daemon.patch | 13 - use-salt-user-for-master.patch | 40 --- zypper-utf-8.patch | 40 --- 33 files changed, 1989 insertions(+), 589 deletions(-) create mode 100644 0001-tserong-suse.com-We-don-t-have-python-systemd-so-not.patch create mode 100644 0002-Run-salt-master-as-dedicated-salt-user.patch create mode 100644 0003-Check-if-byte-strings-are-properly-encoded-in-UTF-8.patch create mode 100644 0004-Fix-pkg.latest-prevent-crash-on-multiple-package-ins.patch create mode 100644 0005-Fix-package-status-filtering-on-latest-version-and-i.patch create mode 100644 0006-add_key-reject_key-do-not-crash-w-Permission-denied-.patch create mode 100644 0007-Force-kill-websocket-s-child-processes-faster-than-d.patch create mode 100644 0008-Fix-types-in-the-output-data-and-return-just-a-list-.patch create mode 100644 0009-The-functions-in-the-state-module-that-return-a-retc.patch create mode 100644 0010-add-handling-for-OEM-products.patch create mode 100644 0011-improve-doc-for-list_pkgs.patch create mode 100644 0012-implement-version_cmp-for-zypper.patch create mode 100644 0013-pylint-changes.patch create mode 100644 0014-Check-if-rpm-python-can-be-imported.patch create mode 100644 0015-call-zypper-with-option-non-interactive-everywhere.patch create mode 100644 0016-write-a-zypper-command-builder-function.patch create mode 100644 0017-Fix-crash-with-scheduler-and-runners-31106.patch create mode 100644 0018-unify-behavior-of-refresh.patch create mode 100644 0019-add-refresh-option-to-more-functions.patch create mode 100644 0020-simplify-checking-the-refresh-paramater.patch create mode 100644 0021-do-not-change-kwargs-in-refresh-while-checking-a-val.patch create mode 100644 0022-fix-argument-handling-for-pkg.download.patch delete mode 100644 1efe484309a5c776974e723f3da0f5181f4bdb86.patch delete mode 100644 salt-2015.8-pkg-zypper-attr-filtering.patch delete mode 100644 salt-2015.8-schedule-ret.patch delete mode 100644 salt-2015.8-zypper-info.patch delete mode 100644 salt-2015.8.3.tar.gz create mode 100644 salt-2015.8.7.tar.gz delete mode 100644 use-forking-daemon.patch delete mode 100644 use-salt-user-for-master.patch delete mode 100644 zypper-utf-8.patch diff --git a/0001-tserong-suse.com-We-don-t-have-python-systemd-so-not.patch b/0001-tserong-suse.com-We-don-t-have-python-systemd-so-not.patch new file mode 100644 index 0000000..c87acdc --- /dev/null +++ b/0001-tserong-suse.com-We-don-t-have-python-systemd-so-not.patch @@ -0,0 +1,27 @@ +From f6534519ed6dcd443e9b5b8f7dc6dfe1fb508ab3 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Klaus=20K=C3=A4mpf?= +Date: Wed, 20 Jan 2016 11:00:15 +0100 +Subject: [PATCH 01/22] tserong@suse.com -- 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 + diff --git a/0002-Run-salt-master-as-dedicated-salt-user.patch b/0002-Run-salt-master-as-dedicated-salt-user.patch new file mode 100644 index 0000000..9cb360c --- /dev/null +++ b/0002-Run-salt-master-as-dedicated-salt-user.patch @@ -0,0 +1,53 @@ +From cd60b85c9e6bfd8ebf3505e5ff05e7fdec6211d6 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Klaus=20K=C3=A4mpf?= +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 + diff --git a/0003-Check-if-byte-strings-are-properly-encoded-in-UTF-8.patch b/0003-Check-if-byte-strings-are-properly-encoded-in-UTF-8.patch new file mode 100644 index 0000000..f48ad81 --- /dev/null +++ b/0003-Check-if-byte-strings-are-properly-encoded-in-UTF-8.patch @@ -0,0 +1,49 @@ +From 9dc25e7dfb08a7cd583215d0206f18b15a44ccb1 Mon Sep 17 00:00:00 2001 +From: Bo Maryniuk +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 ... + salt '*' pkg.info_installed attr=version,vendor + salt '*' pkg.info_installed ... attr=version,vendor +- salt '*' pkg.info_installed ... attr=version,vendor errors=true ++ salt '*' pkg.info_installed ... attr=version,vendor errors=ignore ++ salt '*' pkg.info_installed ... 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 + diff --git a/0004-Fix-pkg.latest-prevent-crash-on-multiple-package-ins.patch b/0004-Fix-pkg.latest-prevent-crash-on-multiple-package-ins.patch new file mode 100644 index 0000000..d0e2d03 --- /dev/null +++ b/0004-Fix-pkg.latest-prevent-crash-on-multiple-package-ins.patch @@ -0,0 +1,255 @@ +From e21ddab93f22d1b2e1ad94368527f41102b69f16 Mon Sep 17 00:00:00 2001 +From: Bo Maryniuk +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': ''}} + ''' + 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 + diff --git a/0005-Fix-package-status-filtering-on-latest-version-and-i.patch b/0005-Fix-package-status-filtering-on-latest-version-and-i.patch new file mode 100644 index 0000000..de31b25 --- /dev/null +++ b/0005-Fix-package-status-filtering-on-latest-version-and-i.patch @@ -0,0 +1,47 @@ +From 2747b83d8009fb7386986ada1640456de2fe5304 Mon Sep 17 00:00:00 2001 +From: Bo Maryniuk +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 + diff --git a/0006-add_key-reject_key-do-not-crash-w-Permission-denied-.patch b/0006-add_key-reject_key-do-not-crash-w-Permission-denied-.patch new file mode 100644 index 0000000..c42f167 --- /dev/null +++ b/0006-add_key-reject_key-do-not-crash-w-Permission-denied-.patch @@ -0,0 +1,29 @@ +From 697e42284fdd1e18fef1d1747f64cb75be1e0bef Mon Sep 17 00:00:00 2001 +From: Duncan Mac-Vicar P +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 + diff --git a/0007-Force-kill-websocket-s-child-processes-faster-than-d.patch b/0007-Force-kill-websocket-s-child-processes-faster-than-d.patch new file mode 100644 index 0000000..9ab83e1 --- /dev/null +++ b/0007-Force-kill-websocket-s-child-processes-faster-than-d.patch @@ -0,0 +1,25 @@ +From a1782a9c76f0af20e88fa913dd2ac6dcb20c9c37 Mon Sep 17 00:00:00 2001 +From: Bo Maryniuk +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 + diff --git a/0008-Fix-types-in-the-output-data-and-return-just-a-list-.patch b/0008-Fix-types-in-the-output-data-and-return-just-a-list-.patch new file mode 100644 index 0000000..b6e373c --- /dev/null +++ b/0008-Fix-types-in-the-output-data-and-return-just-a-list-.patch @@ -0,0 +1,44 @@ +From 1f6af694ef7296f4a32d4adcb658f66865a4c38a Mon Sep 17 00:00:00 2001 +From: Bo Maryniuk +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 + diff --git a/0009-The-functions-in-the-state-module-that-return-a-retc.patch b/0009-The-functions-in-the-state-module-that-return-a-retc.patch new file mode 100644 index 0000000..fdeae2a --- /dev/null +++ b/0009-The-functions-in-the-state-module-that-return-a-retc.patch @@ -0,0 +1,59 @@ +From 8d77e22c0c570a0a725216f70c41d4fe00a184ca Mon Sep 17 00:00:00 2001 +From: "Gareth J. Greenaway" +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 + diff --git a/0010-add-handling-for-OEM-products.patch b/0010-add-handling-for-OEM-products.patch new file mode 100644 index 0000000..c9f40c1 --- /dev/null +++ b/0010-add-handling-for-OEM-products.patch @@ -0,0 +1,49 @@ +From a7a0b80b0ca22a0a898ac4a4f671c08337f8f996 Mon Sep 17 00:00:00 2001 +From: Michael Calmer +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 + diff --git a/0011-improve-doc-for-list_pkgs.patch b/0011-improve-doc-for-list_pkgs.patch new file mode 100644 index 0000000..2b05912 --- /dev/null +++ b/0011-improve-doc-for-list_pkgs.patch @@ -0,0 +1,40 @@ +From 13fd4a3becab7fd991ae2c6a8ca1c52a51048cef Mon Sep 17 00:00:00 2001 +From: Michael Calmer +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:: + +- {'': ''} ++ {'': '[,...]'} ++ ++ versions_as_list: ++ If set to true, the versions are provided as a list ++ ++ {'': ['', '']} ++ ++ removed: ++ not supported ++ ++ purge_desired: ++ not supported + + CLI Example: + +-- +2.1.4 + diff --git a/0012-implement-version_cmp-for-zypper.patch b/0012-implement-version_cmp-for-zypper.patch new file mode 100644 index 0000000..c84c4ff --- /dev/null +++ b/0012-implement-version_cmp-for-zypper.patch @@ -0,0 +1,95 @@ +From 82a9f07f27cf95a7dcff32c8434af9b5d7cf55ad Mon Sep 17 00:00:00 2001 +From: Michael Calmer +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 + diff --git a/0013-pylint-changes.patch b/0013-pylint-changes.patch new file mode 100644 index 0000000..ee02a00 --- /dev/null +++ b/0013-pylint-changes.patch @@ -0,0 +1,93 @@ +From c26d1b6987a06e972749a10af1c54befae14c6e6 Mon Sep 17 00:00:00 2001 +From: Michael Calmer +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 + diff --git a/0014-Check-if-rpm-python-can-be-imported.patch b/0014-Check-if-rpm-python-can-be-imported.patch new file mode 100644 index 0000000..00088ce --- /dev/null +++ b/0014-Check-if-rpm-python-can-be-imported.patch @@ -0,0 +1,70 @@ +From 4accc710ab2f92118f4777d13bc585d26e8e939e Mon Sep 17 00:00:00 2001 +From: Michael Calmer +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 + diff --git a/0015-call-zypper-with-option-non-interactive-everywhere.patch b/0015-call-zypper-with-option-non-interactive-everywhere.patch new file mode 100644 index 0000000..33293eb --- /dev/null +++ b/0015-call-zypper-with-option-non-interactive-everywhere.patch @@ -0,0 +1,184 @@ +From 5009e290b5a318b168fd03095ced7043203fe34c Mon Sep 17 00:00:00 2001 +From: Michael Calmer +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 + ''' +- 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 + diff --git a/0016-write-a-zypper-command-builder-function.patch b/0016-write-a-zypper-command-builder-function.patch new file mode 100644 index 0000000..f5754c3 --- /dev/null +++ b/0016-write-a-zypper-command-builder-function.patch @@ -0,0 +1,201 @@ +From 8d25c4c8906581fa44380f72f0f754b56f5e30c3 Mon Sep 17 00:00:00 2001 +From: Michael Calmer +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 + ''' +- 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 + diff --git a/0017-Fix-crash-with-scheduler-and-runners-31106.patch b/0017-Fix-crash-with-scheduler-and-runners-31106.patch new file mode 100644 index 0000000..17658e0 --- /dev/null +++ b/0017-Fix-crash-with-scheduler-and-runners-31106.patch @@ -0,0 +1,49 @@ +From 978afba658cff38ebc1d6a7aecee4813796db528 Mon Sep 17 00:00:00 2001 +From: Duncan Mac-Vicar P +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 + diff --git a/0018-unify-behavior-of-refresh.patch b/0018-unify-behavior-of-refresh.patch new file mode 100644 index 0000000..0f1f315 --- /dev/null +++ b/0018-unify-behavior-of-refresh.patch @@ -0,0 +1,109 @@ +From 29ab56413c60c958d5d62b1acdea5a97ce80fdb9 Mon Sep 17 00:00:00 2001 +From: Michael Calmer +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:: + + {'': 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 + + 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, + {'': {'old': '', + 'new': ''}} + ''' ++ 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:: + + {'': {'old': '', +-- +2.1.4 + diff --git a/0019-add-refresh-option-to-more-functions.patch b/0019-add-refresh-option-to-more-functions.patch new file mode 100644 index 0000000..baa38c8 --- /dev/null +++ b/0019-add-refresh-option-to-more-functions.patch @@ -0,0 +1,125 @@ +From 478871aebfcb2ddf1b1c2a47b4fccb820180c9ed Mon Sep 17 00:00:00 2001 +From: Michael Calmer +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 + ''' ++ 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 + diff --git a/0020-simplify-checking-the-refresh-paramater.patch b/0020-simplify-checking-the-refresh-paramater.patch new file mode 100644 index 0000000..56c301a --- /dev/null +++ b/0020-simplify-checking-the-refresh-paramater.patch @@ -0,0 +1,88 @@ +From 0a09ae513698029eb1e05cd8b6e6b45d2830a0cb Mon Sep 17 00:00:00 2001 +From: Michael Calmer +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, + {'': {'old': '', + 'new': ''}} + ''' +- 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 + ''' +- 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 + diff --git a/0021-do-not-change-kwargs-in-refresh-while-checking-a-val.patch b/0021-do-not-change-kwargs-in-refresh-while-checking-a-val.patch new file mode 100644 index 0000000..c3c5810 --- /dev/null +++ b/0021-do-not-change-kwargs-in-refresh-while-checking-a-val.patch @@ -0,0 +1,25 @@ +From ea6898f82ddc21c73f3ea369e6af241753a2ceda Mon Sep 17 00:00:00 2001 +From: Michael Calmer +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 + diff --git a/0022-fix-argument-handling-for-pkg.download.patch b/0022-fix-argument-handling-for-pkg.download.patch new file mode 100644 index 0000000..59f4546 --- /dev/null +++ b/0022-fix-argument-handling-for-pkg.download.patch @@ -0,0 +1,33 @@ +From c9bab6bb32f9ca2e65b6e0c24283146b66bf91be Mon Sep 17 00:00:00 2001 +From: Michael Calmer +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 + diff --git a/1efe484309a5c776974e723f3da0f5181f4bdb86.patch b/1efe484309a5c776974e723f3da0f5181f4bdb86.patch deleted file mode 100644 index f0f140b..0000000 --- a/1efe484309a5c776974e723f3da0f5181f4bdb86.patch +++ /dev/null @@ -1,74 +0,0 @@ -Index: salt-2015.8.2/salt/modules/zypper.py -=================================================================== ---- salt-2015.8.2.orig/salt/modules/zypper.py -+++ salt-2015.8.2/salt/modules/zypper.py -@@ -1175,52 +1175,32 @@ def _get_first_aggregate_text(node_list) - return '\n'.join(out) - - --def _parse_suse_product(path, *info): -+def list_products(all=False): - ''' -- Parse SUSE LLC product. -- ''' -- doc = dom.parse(path) -- product = {} -- for nfo in info: -- product.update( -- {nfo: _get_first_aggregate_text( -- doc.getElementsByTagName(nfo) -- )} -- ) -- -- return product -+ List all available or installed SUSE products. - -- --def list_products(): -- ''' -- List all installed SUSE products. -+ all -+ List all products available or only installed. Default is False. - - CLI Examples: - - .. code-block:: bash - - salt '*' pkg.list_products -+ salt '*' pkg.list_products all=True - ''' -- products_dir = '/etc/products.d' -- if not os.path.exists(products_dir): -- raise CommandExecutionError('Directory {0} does not exists.'.format(products_dir)) -- -- p_data = {} -- for fname in os.listdir(products_dir): -- pth_name = os.path.join(products_dir, fname) -- r_pth_name = os.path.realpath(pth_name) -- p_data[r_pth_name] = r_pth_name != pth_name and 'baseproduct' or None -- -- info = ['vendor', 'name', 'version', 'baseversion', 'patchlevel', -- 'predecessor', 'release', 'endoflife', 'arch', 'cpeid', -- 'productline', 'updaterepokey', 'summary', 'shortsummary', -- 'description'] -- -- ret = {} -- for prod_meta, is_base_product in six.iteritems(p_data): -- product = _parse_suse_product(prod_meta, *info) -- product['baseproduct'] = is_base_product is not None -- ret[product.pop('name')] = product -+ ret = list() -+ 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) - - return ret - diff --git a/salt-2015.8-pkg-zypper-attr-filtering.patch b/salt-2015.8-pkg-zypper-attr-filtering.patch deleted file mode 100644 index be0bc80..0000000 --- a/salt-2015.8-pkg-zypper-attr-filtering.patch +++ /dev/null @@ -1,201 +0,0 @@ -diff --git a/salt/modules/rpm.py b/salt/modules/rpm.py -index 7810e22..51c72c9 100644 ---- a/salt/modules/rpm.py -+++ b/salt/modules/rpm.py -@@ -8,7 +8,6 @@ from __future__ import absolute_import - import logging - import os - import re --import time - import datetime - - # Import Salt libs -@@ -399,24 +398,20 @@ def diff(package, path): - return res - - --def _pkg_time_to_iso(pkg_time): -- ''' -- Convert package time to ISO 8601. -- -- :param pkg_time: -- :return: -- ''' -- ptime = time.strptime(pkg_time, '%a %d %b %Y %H:%M:%S %p %Z') -- return datetime.datetime(ptime.tm_year, ptime.tm_mon, ptime.tm_mday, -- ptime.tm_hour, ptime.tm_min, ptime.tm_sec).isoformat() + "Z" -- -- --def info(*packages): -+def info(*packages, **attr): - ''' - Return a detailed package(s) summary information. - If no packages specified, all packages will be returned. - - :param packages: -+ -+ :param attr: -+ Comma-separated package attributes. If no 'attr' is specified, all available attributes returned. -+ -+ Valid attributes are: -+ 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. -+ - :return: - - CLI example: -@@ -424,30 +419,59 @@ def info(*packages): - .. code-block:: bash - - salt '*' lowpkg.info apache2 bash -+ salt '*' lowpkg.info apache2 bash attr=version -+ salt '*' lowpkg.info apache2 bash attr=version,build_date_iso,size - ''' - - cmd = packages and "rpm -q {0}".format(' '.join(packages)) or "rpm -qa" - -- # Locale needs to be en_US instead of C, because RPM otherwise will yank the timezone from the timestamps -- call = __salt__['cmd.run_all'](cmd + (" --queryformat 'Name: %{NAME}\n" -- "Relocations: %|PREFIXES?{[%{PREFIXES} ]}:{(not relocatable)}|\n" -- "Version: %{VERSION}\n" -- "Vendor: %{VENDOR}\n" -- "Release: %{RELEASE}\n" -- "Build Date: %{BUILDTIME:date}\n" -- "Install Date: %|INSTALLTIME?{%{INSTALLTIME:date}}:{(not installed)}|\n" -- "Build Host: %{BUILDHOST}\n" -- "Group: %{GROUP}\n" -- "Source RPM: %{SOURCERPM}\n" -- "Size: %{LONGSIZE}\n" -- "%|LICENSE?{License: %{LICENSE}\n}|" -- "Signature: %|DSAHEADER?{%{DSAHEADER:pgpsig}}:{%|RSAHEADER?{%{RSAHEADER:pgpsig}}:{%|SIGGPG?{%{SIGGPG:pgpsig}}:{%|SIGPGP?{%{SIGPGP:pgpsig}}:{(none)}|}|}|}|\n" -- "%|PACKAGER?{Packager: %{PACKAGER}\n}|" -- "%|URL?{URL: %{URL}\n}|" -- "Summary: %{SUMMARY}\n" -- "Description:\n%{DESCRIPTION}\n" -- "-----\n'"), -- output_loglevel='trace', env={'LC_ALL': 'en_US', 'TZ': 'UTC'}, clean_env=True) -+ # Construct query format -+ attr_map = { -+ "name": "name: %{NAME}\\n", -+ "relocations": "relocations: %|PREFIXES?{[%{PREFIXES} ]}:{(not relocatable)}|\\n", -+ "version": "version: %{VERSION}\\n", -+ "vendor": "vendor: %{VENDOR}\\n", -+ "release": "release: %{RELEASE}\\n", -+ "epoch": "%|EPOCH?{epoch: %{EPOCH}\\n}|", -+ "build_date_time_t": "build_date_time_t: %{BUILDTIME}\\n", -+ "build_date": "build_date: %{BUILDTIME}\\n", -+ "install_date_time_t": "install_date_time_t: %|INSTALLTIME?{%{INSTALLTIME}}:{(not installed)}|\\n", -+ "install_date": "install_date: %|INSTALLTIME?{%{INSTALLTIME}}:{(not installed)}|\\n", -+ "build_host": "build_host: %{BUILDHOST}\\n", -+ "group": "group: %{GROUP}\\n", -+ "source_rpm": "source_rpm: %{SOURCERPM}\\n", -+ "size": "size: %{LONGSIZE}\\n", -+ "arch": "arch: %{ARCH}\\n", -+ "license": "%|LICENSE?{license: %{LICENSE}\\n}|", -+ "signature": "signature: %|DSAHEADER?{%{DSAHEADER:pgpsig}}:{%|RSAHEADER?{%{RSAHEADER:pgpsig}}:" -+ "{%|SIGGPG?{%{SIGGPG:pgpsig}}:{%|SIGPGP?{%{SIGPGP:pgpsig}}:{(none)}|}|}|}|\\n", -+ "packager": "%|PACKAGER?{packager: %{PACKAGER}\\n}|", -+ "url": "%|URL?{url: %{URL}\\n}|", -+ "summary": "summary: %{SUMMARY}\\n", -+ "description": "description:\\n%{DESCRIPTION}\\n", -+ } -+ -+ attr = attr.get('attr', None) and attr['attr'].split(",") or None -+ query = list() -+ if attr: -+ for attr_k in attr: -+ if attr_k in attr_map and attr_k != 'description': -+ query.append(attr_map[attr_k]) -+ if not query: -+ raise CommandExecutionError('No valid attributes found.') -+ if 'name' not in attr: -+ attr.append('name') -+ query.append(attr_map['name']) -+ else: -+ for attr_k, attr_v in attr_map.iteritems(): -+ if attr_k != 'description': -+ query.append(attr_v) -+ if attr and 'description' in attr or not attr: -+ query.append(attr_map['description']) -+ query.append("-----\\n") -+ -+ call = __salt__['cmd.run_all'](cmd + (" --queryformat '{0}'".format(''.join(query))), -+ output_loglevel='trace', env={'TZ': 'UTC'}, clean_env=True) - if call['retcode'] != 0: - comment = '' - if 'stderr' in call: -@@ -477,17 +501,31 @@ def info(*packages): - if len(line) != 2: - continue - key, value = line -- key = key.replace(' ', '_').lower() - if key == 'description': - descr_marker = True - continue - if key == 'name': - pkg_name = value -+ -+ # Convert Unix ticks into ISO time format - if key in ['build_date', 'install_date']: -- value = _pkg_time_to_iso(value) -- if key != 'description' and value: -+ try: -+ pkg_data[key] = datetime.datetime.fromtimestamp(int(value)).isoformat() + "Z" -+ except ValueError: -+ log.warning('Could not convert "{0}" into Unix time'.format(value)) -+ continue -+ -+ # Convert Unix ticks into an Integer -+ if key in ['build_date_time_t', 'install_date_time_t']: -+ try: -+ pkg_data[key] = int(value) -+ except ValueError: -+ log.warning('Could not convert "{0}" into Unix time'.format(value)) -+ continue -+ if key not in ['description', 'name'] and value: - pkg_data[key] = value -- pkg_data['description'] = os.linesep.join(descr) -+ if attr and 'description' in attr or not attr: -+ pkg_data['description'] = os.linesep.join(descr) - if pkg_name: - ret[pkg_name] = pkg_data - -diff --git a/salt/modules/zypper.py b/salt/modules/zypper.py -index 84b5d51..ccba713 100644 ---- a/salt/modules/zypper.py -+++ b/salt/modules/zypper.py -@@ -96,19 +96,32 @@ def list_upgrades(refresh=True): - list_updates = salt.utils.alias_function(list_upgrades, 'list_updates') - - --def info_installed(*names): -+def info_installed(*names, **attr): - ''' - Return the information of the named package(s), installed on the system. - -+ :param names: -+ Names of the packages to get information about. -+ -+ :param attr: -+ Comma-separated package attributes. If no 'attr' is specified, all available attributes returned. -+ -+ Valid attributes are: -+ 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. -+ - CLI example: - - .. code-block:: bash - - salt '*' pkg.info_installed - salt '*' pkg.info_installed ... -+ salt '*' pkg.info_installed attr=version,vendor -+ salt '*' pkg.info_installed ... attr=version,vendor - ''' - ret = dict() -- for pkg_name, pkg_nfo in __salt__['lowpkg.info'](*names).items(): -+ for pkg_name, pkg_nfo in __salt__['lowpkg.info'](*names, **attr).items(): - t_nfo = dict() - # Translate dpkg-specific keys to a common structure - for key, value in pkg_nfo.items(): diff --git a/salt-2015.8-schedule-ret.patch b/salt-2015.8-schedule-ret.patch deleted file mode 100644 index 4869297..0000000 --- a/salt-2015.8-schedule-ret.patch +++ /dev/null @@ -1,170 +0,0 @@ -diff --git a/salt/utils/schedule.py b/salt/utils/schedule.py -index 4458202..cae5fcf 100644 ---- a/salt/utils/schedule.py -+++ b/salt/utils/schedule.py -@@ -482,24 +482,24 @@ class Schedule(object): - func = None - if func not in self.functions: - log.info( -- 'Invalid function: {0} in job {1}. Ignoring.'.format( -+ 'Invalid function: {0} in scheduled job {1}.'.format( - func, name - ) - ) -+ -+ if 'name' not in data: -+ data['name'] = name -+ log.info( -+ 'Running Job: {0}.'.format(name) -+ ) -+ if self.opts.get('multiprocessing', True): -+ thread_cls = multiprocessing.Process - else: -- if 'name' not in data: -- data['name'] = name -- log.info( -- 'Running Job: {0}.'.format(name) -- ) -- if self.opts.get('multiprocessing', True): -- thread_cls = multiprocessing.Process -- else: -- thread_cls = threading.Thread -- proc = thread_cls(target=self.handle_func, args=(func, data)) -- proc.start() -- if self.opts.get('multiprocessing', True): -- proc.join() -+ thread_cls = threading.Thread -+ proc = thread_cls(target=self.handle_func, args=(func, data)) -+ proc.start() -+ if self.opts.get('multiprocessing', True): -+ proc.join() - - def enable_schedule(self): - ''' -@@ -642,33 +642,39 @@ class Schedule(object): - except OSError: - log.info('Unable to remove file: {0}.'.format(fn_)) - -- salt.utils.daemonize_if(self.opts) -+ try: -+ salt.utils.daemonize_if(self.opts) - -- ret['pid'] = os.getpid() -+ ret['pid'] = os.getpid() - -- if 'jid_include' not in data or data['jid_include']: -- log.debug('schedule.handle_func: adding this job to the jobcache ' -- 'with data {0}'.format(ret)) -- # write this to /var/cache/salt/minion/proc -- with salt.utils.fopen(proc_fn, 'w+b') as fp_: -- fp_.write(salt.payload.Serial(self.opts).dumps(ret)) -- -- args = tuple() -- if 'args' in data: -- args = data['args'] -- -- kwargs = {} -- if 'kwargs' in data: -- kwargs = data['kwargs'] -- # if the func support **kwargs, lets pack in the pub data we have -- # TODO: pack the *same* pub data as a minion? -- argspec = salt.utils.args.get_function_argspec(self.functions[func]) -- if argspec.keywords: -- # this function accepts **kwargs, pack in the publish data -- for key, val in six.iteritems(ret): -- kwargs['__pub_{0}'.format(key)] = val -+ if 'jid_include' not in data or data['jid_include']: -+ log.debug('schedule.handle_func: adding this job to the jobcache ' -+ 'with data {0}'.format(ret)) -+ # write this to /var/cache/salt/minion/proc -+ with salt.utils.fopen(proc_fn, 'w+b') as fp_: -+ fp_.write(salt.payload.Serial(self.opts).dumps(ret)) -+ -+ args = tuple() -+ if 'args' in data: -+ args = data['args'] -+ -+ kwargs = {} -+ if 'kwargs' in data: -+ kwargs = data['kwargs'] -+ -+ if func not in self.functions: -+ ret['return'] = self.functions.missing_fun_string(func) -+ salt.utils.error.raise_error( -+ message=self.functions.missing_fun_string(func)) -+ -+ # if the func support **kwargs, lets pack in the pub data we have -+ # TODO: pack the *same* pub data as a minion? -+ argspec = salt.utils.args.get_function_argspec(self.functions[func]) -+ if argspec.keywords: -+ # this function accepts **kwargs, pack in the publish data -+ for key, val in six.iteritems(ret): -+ kwargs['__pub_{0}'.format(key)] = val - -- try: - ret['return'] = self.functions[func](*args, **kwargs) - - data_returner = data.get('returner', None) -@@ -694,28 +700,34 @@ class Schedule(object): - ) - ) - -- # Only attempt to return data to the master -- # if the scheduled job is running on a minion. -- if '__role' in self.opts and self.opts['__role'] == 'minion': -- if 'return_job' in data and not data['return_job']: -- pass -- else: -- # Send back to master so the job is included in the job list -- mret = ret.copy() -- mret['jid'] = 'req' -- channel = salt.transport.Channel.factory(self.opts, usage='salt_schedule') -- load = {'cmd': '_return', 'id': self.opts['id']} -- for key, value in six.iteritems(mret): -- load[key] = value -- channel.send(load) -- -+ ret['retcode'] = self.functions.pack['__context__']['retcode'] -+ ret['success'] = True - except Exception: - log.exception("Unhandled exception running {0}".format(ret['fun'])) - # Although catch-all exception handlers are bad, the exception here - # is to let the exception bubble up to the top of the thread context, - # where the thread will die silently, which is worse. -+ if 'return' not in ret: -+ ret['return'] = "Unhandled exception running {0}".format(ret['fun']) -+ ret['success'] = False -+ ret['retcode'] = 254 - finally: - try: -+ # Only attempt to return data to the master -+ # if the scheduled job is running on a minion. -+ if '__role' in self.opts and self.opts['__role'] == 'minion': -+ if 'return_job' in data and not data['return_job']: -+ pass -+ else: -+ # Send back to master so the job is included in the job list -+ mret = ret.copy() -+ mret['jid'] = 'req' -+ channel = salt.transport.Channel.factory(self.opts, usage='salt_schedule') -+ load = {'cmd': '_return', 'id': self.opts['id']} -+ for key, value in six.iteritems(mret): -+ load[key] = value -+ channel.send(load) -+ - log.debug('schedule.handle_func: Removing {0}'.format(proc_fn)) - os.unlink(proc_fn) - except OSError as exc: -@@ -757,11 +769,10 @@ class Schedule(object): - func = None - if func not in self.functions: - log.info( -- 'Invalid function: {0} in job {1}. Ignoring.'.format( -+ 'Invalid function: {0} in scheduled job {1}.'.format( - func, job - ) - ) -- continue - if 'name' not in data: - data['name'] = job - # Add up how many seconds between now and then diff --git a/salt-2015.8-zypper-info.patch b/salt-2015.8-zypper-info.patch deleted file mode 100644 index ff2b655..0000000 --- a/salt-2015.8-zypper-info.patch +++ /dev/null @@ -1,20 +0,0 @@ -diff --git a/salt/modules/zypper.py b/salt/modules/zypper.py -index ccba713..9d654a2 100644 ---- a/salt/modules/zypper.py -+++ b/salt/modules/zypper.py -@@ -164,12 +164,14 @@ def info_available(*names, **kwargs): - # Run in batches - while batch: - cmd = 'zypper info -t package {0}'.format(' '.join(batch[:batch_size])) -- pkg_info.extend(re.split(r"----*", __salt__['cmd.run_stdout'](cmd, output_loglevel='trace'))) -+ pkg_info.extend(re.split(r"Information for package*", __salt__['cmd.run_stdout'](cmd, output_loglevel='trace'))) - batch = batch[batch_size:] - - for pkg_data in pkg_info: - nfo = {} - for line in [data for data in pkg_data.split("\n") if ":" in data]: -+ if line.startswith("-----"): -+ continue - kw = [data.strip() for data in line.split(":", 1)] - if len(kw) == 2 and kw[1]: - nfo[kw[0].lower()] = kw[1] diff --git a/salt-2015.8.3.tar.gz b/salt-2015.8.3.tar.gz deleted file mode 100644 index 6c8691f..0000000 --- a/salt-2015.8.3.tar.gz +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:2e9a262789b018f3443513105c0c6ae98934c9bc105a04cf9e5c073ef706218a -size 6757678 diff --git a/salt-2015.8.7.tar.gz b/salt-2015.8.7.tar.gz new file mode 100644 index 0000000..9aea50a --- /dev/null +++ b/salt-2015.8.7.tar.gz @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:61a2f9cff77dd11fc6bf7630d82d1955238818dfa7eedb53e6bf3edbbc9d6029 +size 6877927 diff --git a/salt.changes b/salt.changes index 4aaac86..8219e9a 100644 --- a/salt.changes +++ b/salt.changes @@ -1,3 +1,168 @@ +------------------------------------------------------------------- +Tue Feb 23 11:58:00 CET 2016 - mc@suse.de + +- fix argument handling of pkg.download + Add: 0022-fix-argument-handling-for-pkg.download.patch + +------------------------------------------------------------------- +Mon Feb 22 16:12:43 CET 2016 - mc@suse.de + +- 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 - mc@suse.de + +- Fix crash with scheduler and runners + Add: 0017-Fix-crash-with-scheduler-and-runners-31106.patch + +------------------------------------------------------------------- +Fri Feb 19 15:01:38 CET 2016 - mc@suse.de + +- 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 - mc@suse.de + +- require rpm-python on SUSE for zypper support + +------------------------------------------------------------------- +Thu Feb 18 11:01:21 CET 2016 - mc@suse.de + +- 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 - aboe76@gmail.com + +- 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 - bmaryniuk@suse.com + +- 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 - bmaryniuk@suse.com + +- 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 - dmacvicar@suse.de + +- 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 - kkaempf@suse.com + +- 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 - bmaryniuk@suse.com + +- 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 - bmaryniuk@suse.com + +- 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 - bmaryniuk@suse.com + +- Fix dependencies to Salt subpackages requiring release along the + version. + +------------------------------------------------------------------- +Mon Jan 25 16:24:55 UTC 2016 - bmaryniuk@suse.com + +- 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 - bmaryniuk@suse.com + +- 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 - kkaempf@suse.com + +- 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 + ------------------------------------------------------------------- Fri Jan 15 13:16:46 UTC 2016 - dmacvicar@suse.de diff --git a/salt.spec b/salt.spec index 26f3fe7..f24657c 100644 --- a/salt.spec +++ b/salt.spec @@ -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 tserong@suse.com -- 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-requests >= 1.0.0 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 @@ servers, handle them quickly and through a simple and manageable interface. %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 @@ salt-api is a modular interface on top of Salt that can provide a variety of ent %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 @@ This contains the documentation of salt, it is an offline version of http://docs %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 @@ than serially. %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 @@ Listens to the salt master and execute the commands. %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 @@ for trust to be established. %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 @@ security reasons, will not. %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 @@ the management of multiple masters at a time.. %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 @@ it enables the management of minions over a ssh connection. %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 @@ Bash command line completion support for %{name}. %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 @@ Fish command line completion support for %{name}. %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 @@ cp %{S:1} . %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 diff --git a/use-forking-daemon.patch b/use-forking-daemon.patch deleted file mode 100644 index 8198eca..0000000 --- a/use-forking-daemon.patch +++ /dev/null @@ -1,13 +0,0 @@ -Index: salt-2015.8.0/pkg/salt-master.service -=================================================================== ---- salt-2015.8.0.orig/pkg/salt-master.service -+++ salt-2015.8.0/pkg/salt-master.service -@@ -4,7 +4,7 @@ After=syslog.target network.target - - [Service] - LimitNOFILE=16384 --Type=notify -+Type=simple - ExecStart=/usr/bin/salt-master - - [Install] diff --git a/use-salt-user-for-master.patch b/use-salt-user-for-master.patch deleted file mode 100644 index 988d390..0000000 --- a/use-salt-user-for-master.patch +++ /dev/null @@ -1,40 +0,0 @@ -Index: salt-2015.8.2/conf/master -=================================================================== ---- salt-2015.8.2.orig/conf/master -+++ salt-2015.8.2/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 - - # Max open files - # -Index: salt-2015.8.2/pkg/salt-common.logrotate -=================================================================== ---- salt-2015.8.2.orig/pkg/salt-common.logrotate -+++ salt-2015.8.2/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 diff --git a/zypper-utf-8.patch b/zypper-utf-8.patch deleted file mode 100644 index ebc20fb..0000000 --- a/zypper-utf-8.patch +++ /dev/null @@ -1,40 +0,0 @@ -From 8fcc530f0473e9fcd5a7099617516a6d184b5303 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Klaus=20K=C3=A4mpf?= -Date: Thu, 10 Dec 2015 13:21:41 +0100 -Subject: [PATCH] zypper: check package header content for valid utf-8 - -"salt 'system.domain.tld' pkg.info_installed --out json" can crash with - - [ERROR ] An un-handled exception was caught by salt's global exception handler: - UnicodeDecodeError: 'utf8' codec can't decode byte ... - -if a package name, summary, or description contains invalid UTF-8. - -This patch detects such rpm header values, logs them as errors, and -replaces them with "*** Bad UTF-8 ***". - -Update: drop the 'errors=' named parameter from the encode() call as it -is incompatible with Python 2.6 as used in SLE 11. ---- - salt/modules/zypper.py | 5 +++++ - 1 file changed, 5 insertions(+) - -diff --git a/salt/modules/zypper.py b/salt/modules/zypper.py -index be28311ae1bd..483d63e08edc 100644 ---- a/salt/modules/zypper.py -+++ b/salt/modules/zypper.py -@@ -115,6 +115,11 @@ def info_installed(*names): - t_nfo = dict() - # Translate dpkg-specific keys to a common structure - for key, value in pkg_nfo.items(): -+ try: -+ value = value.encode('UTF-8', 'replace') -+ except(UnicodeDecodeError): -+ log.error('Package {0} has bad UTF-8 code in {1}: {2}'.format(pkg_name, key, value)) -+ value = '*** Bad UTF-8 ***' - if key == 'source_rpm': - t_nfo['source'] = value - else: --- -2.6.3 -