diff --git a/0001-Add-rpm.minimal_info-fix-rpm.info.patch b/0001-Add-rpm.minimal_info-fix-rpm.info.patch new file mode 100644 index 0000000..801ea00 --- /dev/null +++ b/0001-Add-rpm.minimal_info-fix-rpm.info.patch @@ -0,0 +1,139 @@ +From 1832daa1d247a546069f901427995f0b9f2addf3 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Klaus=20K=C3=A4mpf?= +Date: Tue, 15 Dec 2015 14:36:41 +0100 +Subject: [PATCH 1/2] Add rpm.minimal_info, fix rpm.info + +rpm.info: report epoch (if present) and architecture + +add rpm.minimal_info to just report name, epoch, version, release, +architecture, and installtime +--- + salt/modules/rpm.py | 97 +++++++++++++++++++++++++++++++++++------------------ + 1 file changed, 65 insertions(+), 32 deletions(-) + +diff --git a/salt/modules/rpm.py b/salt/modules/rpm.py +index 032f8dadc87a..9fb89c994d9b 100644 +--- a/salt/modules/rpm.py ++++ b/salt/modules/rpm.py +@@ -413,43 +413,15 @@ def _pkg_time_to_iso(pkg_time): + 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 query_rpm(queryformat, *packages): + ''' +- Return a detailed package(s) summary information. +- If no packages specified, all packages will be returned. +- +- :param packages: +- :return: +- +- CLI example: +- +- .. code-block:: bash +- +- salt '*' lowpkg.info apache2 bash ++ Internal function for info() and minimal_info() to query rpm and parse it's output + ''' + + 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'"), ++ call = __salt__['cmd.run_all'](cmd + queryformat, + output_loglevel='trace', env={'LC_ALL': 'en_US', 'TZ': 'UTC'}, clean_env=True) + if call['retcode'] != 0: + comment = '' +@@ -490,8 +462,69 @@ def info(*packages): + value = _pkg_time_to_iso(value) + if key != 'description' and value: + pkg_data[key] = value +- pkg_data['description'] = os.linesep.join(descr) ++ if len(descr) > 0: ++ pkg_data['description'] = os.linesep.join(descr) + if pkg_name: + ret[pkg_name] = pkg_data + + return ret ++ ++def info(*packages): ++ ''' ++ Return a detailed package(s) summary information. ++ If no packages specified, all packages will be returned. ++ ++ :param packages: ++ :return: ++ ++ CLI example: ++ ++ .. code-block:: bash ++ ++ salt '*' lowpkg.info apache2 bash ++ ''' ++ ++ return query_rpm(" --queryformat 'Name: %{NAME}\n" ++ "Relocations: %|PREFIXES?{[%{PREFIXES} ]}:{(not relocatable)}|\n" ++ "%|EPOCH?{Epoch: %{EPOCH}\n}|" ++ "Version: %{VERSION}\n" ++ "Vendor: %{VENDOR}\n" ++ "Release: %{RELEASE}\n" ++ "Architecture: %{ARCH}\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'", *packages) ++ ++def minimal_info(*packages): ++ ''' ++ Return a minimal package(s) information (name, epoch, version, release, arch, installtime). ++ If no packages specified, all packages will be returned. ++ ++ :param packages: ++ :return: ++ ++ CLI example: ++ ++ .. code-block:: bash ++ ++ salt '*' lowpkg.minimal_info apache2 bash ++ ''' ++ ++ return query_rpm(" --queryformat 'Name: %{NAME}\n" ++ "%|EPOCH?{Epoch: %{EPOCH}\n}|" ++ "Version: %{VERSION}\n" ++ "Release: %{RELEASE}\n" ++ "Architecture: %{ARCH}\n" ++ "Install Date: %|INSTALLTIME?{%{INSTALLTIME:date}}:{(not installed)}|\n" ++ "-----\n'", *packages) ++ +\ No newline at end of file +-- +2.6.3 + diff --git a/0002-Reduce-information-returned-from-pkg.info_installed.patch b/0002-Reduce-information-returned-from-pkg.info_installed.patch new file mode 100644 index 0000000..9faecfa --- /dev/null +++ b/0002-Reduce-information-returned-from-pkg.info_installed.patch @@ -0,0 +1,27 @@ +From e6c0629e1fbbc739a856494641330a346966ccfb Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Klaus=20K=C3=A4mpf?= +Date: Tue, 15 Dec 2015 14:37:54 +0100 +Subject: [PATCH 2/2] Reduce information returned from pkg.info_installed + +Only report name, epoch (if set), version, release, architecture, and +installtime +--- + 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 26c0580d027e..2954e8b1f06d 100644 +--- a/salt/modules/zypper.py ++++ b/salt/modules/zypper.py +@@ -111,7 +111,7 @@ def info_installed(*names): + salt '*' pkg.info_installed ... + ''' + ret = dict() +- for pkg_name, pkg_nfo in __salt__['lowpkg.info'](*names).items(): ++ for pkg_name, pkg_nfo in __salt__['lowpkg.minimal_info'](*names).items(): + t_nfo = dict() + # Translate dpkg-specific keys to a common structure + for key, value in pkg_nfo.items(): +-- +2.6.3 + diff --git a/1efe484309a5c776974e723f3da0f5181f4bdb86.patch b/1efe484309a5c776974e723f3da0f5181f4bdb86.patch new file mode 100644 index 0000000..f0f140b --- /dev/null +++ b/1efe484309a5c776974e723f3da0f5181f4bdb86.patch @@ -0,0 +1,74 @@ +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.changes b/salt.changes index 52cf3ce..415e11e 100644 --- a/salt.changes +++ b/salt.changes @@ -1,3 +1,24 @@ +------------------------------------------------------------------- +Thu Dec 17 15:53:47 UTC 2015 - kkaempf@suse.com + +- require glibc-locale (bsc#959572) + +------------------------------------------------------------------- +Tue Dec 15 13:50:17 UTC 2015 - kkaempf@suse.com + +- Report epoch and architecture of installed packages + 0001-Add-rpm.minimal_info-fix-rpm.info.patch + +- pkg.info_installed exceeds the maximum event size, reduce the + information to what's actually needed + 0002-Reduce-information-returned-from-pkg.info_installed.patch + +------------------------------------------------------------------- +Wed Dec 9 08:28:21 UTC 2015 - kkaempf@suse.com + +- Filter out bad UTF-8 strings in package data (bsc#958350) + zypper-utf-8.patch + ------------------------------------------------------------------- Tue Dec 1 22:04:14 UTC 2015 - aboe76@gmail.com @@ -8,6 +29,13 @@ Tue Dec 1 22:04:14 UTC 2015 - aboe76@gmail.com - zypper_pkgrepo.patch - more details at: https://docs.saltstack.com/en/latest/topics/releases/2015.8.3.html +------------------------------------------------------------------- +Tue Dec 1 14:40:25 UTC 2015 - bmaryniuk@suse.com + +- added 1efe484309a5c776974e723f3da0f5181f4bdb86.patch: + reimplements pkg.list_products that potentially may be broken in + a future releases of SLES. + ------------------------------------------------------------------- Mon Nov 30 17:19:06 UTC 2015 - mrueckert@suse.de diff --git a/salt.spec b/salt.spec index 3d8b27b..9e5c094 100644 --- a/salt.spec +++ b/salt.spec @@ -49,6 +49,15 @@ Source2: salt-tmpfiles.d Patch1: use-forking-daemon.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-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 + BuildRoot: %{_tmppath}/%{name}-%{version}-build BuildRequires: logrotate BuildRequires: python @@ -96,6 +105,8 @@ Requires(pre): %{_sbindir}/useradd %if 0%{?suse_version} Requires(pre): %fillup_prereq Requires(pre): pwdutils +# bsc#959572 +Requires: glibc-locale %endif Requires: logrotate Requires: python @@ -390,6 +401,10 @@ Zsh command line completion support for %{name}. cp %{S:1} . %patch1 -p1 %patch2 -p1 +%patch3 -p1 +%patch4 -p1 +%patch5 -p1 +%patch6 -p1 %build python setup.py --salt-transport=both build diff --git a/zypper-utf-8.patch b/zypper-utf-8.patch new file mode 100644 index 0000000..ffb0bcc --- /dev/null +++ b/zypper-utf-8.patch @@ -0,0 +1,15 @@ +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 @@ + 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') ++ except(UnicodeDecodeError): ++ log.error('Package ' + pkg_name + ' has bad UTF-8 code in ' + key + ': ' + value) ++ value = '*** Bad UTF-8 ***' + if key == 'source_rpm': + t_nfo['source'] = value + else: