Hello community,

here is the log from the commit of package salt for openSUSE:Factory checked in 
at 2016-01-26 10:14:44
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/salt (Old)
 and      /work/SRC/openSUSE:Factory/.salt.new (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "salt"

Changes:
--------
--- /work/SRC/openSUSE:Factory/salt/salt.changes        2015-12-23 
08:49:48.000000000 +0100
+++ /work/SRC/openSUSE:Factory/.salt.new/salt.changes   2016-01-26 
10:14:45.000000000 +0100
@@ -1,0 +2,26 @@
+Fri Jan 15 13:16:46 UTC 2016 - [email protected]
+
+- Fix zypper module info_available on SLE-11
+  * add salt-2015.8-zypper-info.patch
+  * https://github.com/saltstack/salt/pull/30384
+- zypper/pkg: add package attributes filtering
+  * add salt-2015.8-pkg-zypper-attr-filtering.patch
+  * https://github.com/saltstack/salt/pull/30267
+- Remove obsoleted patches and fixes:
+  * 0001-Add-rpm.minimal_info-fix-rpm.info.patch
+  * 0002-Reduce-information-returned-from-pkg.info_installed.patch
+  * Remove require on glibc-locale (bsc#959572)
+
+-------------------------------------------------------------------
+Wed Jan 13 12:03:06 UTC 2016 - [email protected]
+
+- Add missing return data to scheduled jobs
+  * add salt-2015.8-schedule-ret.patch for
+  * https://github.com/saltstack/salt/pull/30246
+
+-------------------------------------------------------------------
+Mon Dec 21 14:06:27 UTC 2015 - [email protected]
+
+- Update zypper-utf-8.patch for Python 2.6
+
+-------------------------------------------------------------------

Old:
----
  0001-Add-rpm.minimal_info-fix-rpm.info.patch
  0002-Reduce-information-returned-from-pkg.info_installed.patch

New:
----
  salt-2015.8-pkg-zypper-attr-filtering.patch
  salt-2015.8-schedule-ret.patch
  salt-2015.8-zypper-info.patch

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ salt.spec ++++++
--- /var/tmp/diff_new_pack.Bpkufl/_old  2016-01-26 10:14:46.000000000 +0100
+++ /var/tmp/diff_new_pack.Bpkufl/_new  2016-01-26 10:14:46.000000000 +0100
@@ -1,7 +1,7 @@
 #
 # spec file for package salt
 #
-# Copyright (c) 2015 SUSE LINUX GmbH, Nuernberg, Germany.
+# Copyright (c) 2016 SUSE LINUX GmbH, Nuernberg, Germany.
 #
 # All modifications and additions to the file contributed by third parties
 # remain the property of their copyright owners, unless otherwise agreed
@@ -53,11 +53,12 @@
 Patch3:         1efe484309a5c776974e723f3da0f5181f4bdb86.patch
 # PATCH-FIX-OPENSUSE detect bad UTF-8 in package header, bsc#958350
 Patch4:         zypper-utf-8.patch
-# PATCH-FIX-OPENSUSE report epoch and architecture
-Patch5:         0001-Add-rpm.minimal_info-fix-rpm.info.patch
-# PATCH-FIX-OPENSUSE use minimal_info for pkg.info_installed
-Patch6:         0002-Reduce-information-returned-from-pkg.info_installed.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
 BuildRoot:      %{_tmppath}/%{name}-%{version}-build
 BuildRequires:  logrotate
 BuildRequires:  python
@@ -105,8 +106,6 @@
 %if 0%{?suse_version}
 Requires(pre):  %fillup_prereq
 Requires(pre):  pwdutils
-# bsc#959572
-Requires:       glibc-locale
 %endif
 Requires:       logrotate
 Requires:       python
@@ -405,6 +404,7 @@
 %patch4 -p1
 %patch5 -p1
 %patch6 -p1
+%patch7 -p1
 
 %build
 python setup.py --salt-transport=both build

++++++ salt-2015.8-pkg-zypper-attr-filtering.patch ++++++
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 <package1>
         salt '*' pkg.info_installed <package1> <package2> <package3> ...
+        salt '*' pkg.info_installed <package1> attr=version,vendor
+        salt '*' pkg.info_installed <package1> <package2> <package3> ... 
attr=version,vendor
     '''
     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():
++++++ salt-2015.8-schedule-ret.patch ++++++
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
++++++ salt-2015.8-zypper-info.patch ++++++
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]
++++++ zypper-utf-8.patch ++++++
--- /var/tmp/diff_new_pack.Bpkufl/_old  2016-01-26 10:14:46.000000000 +0100
+++ /var/tmp/diff_new_pack.Bpkufl/_new  2016-01-26 10:14:46.000000000 +0100
@@ -1,15 +1,40 @@
-diff -wruN -x '*~' -x '*.o' -x '*.a' -x '*.so' -x '*.so.[0-9]' -x 
autom4te.cache -x .deps -x .libs ../orig-salt-2015.8.3/salt/modules/zypper.py 
./salt/modules/zypper.py
---- ../orig-salt-2015.8.3/salt/modules/zypper.py       2015-12-01 
22:25:13.000000000 +0100
-+++ ./salt/modules/zypper.py   2015-12-09 09:15:41.157266587 +0100
-@@ -112,6 +112,11 @@
+From 8fcc530f0473e9fcd5a7099617516a6d184b5303 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Klaus=20K=C3=A4mpf?= <[email protected]>
+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', errors='replace')
++                value = value.encode('UTF-8', 'replace')
 +            except(UnicodeDecodeError):
-+                log.error('Package ' + pkg_name + ' has bad UTF-8 code in ' + 
key + ': ' + value)
++                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
+


Reply via email to