From d24fabaec3587c86bc890c3fd704fcaad8ea3237 Mon Sep 17 00:00:00 2001 From: Bo Maryniuk Date: Tue, 17 Mar 2015 19:56:32 +0100 Subject: [PATCH 01/11] PEP8: closing bracked matching --- salt/modules/zypper.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/salt/modules/zypper.py b/salt/modules/zypper.py index 194f5a74f45c..79a9e246cc68 100644 --- a/salt/modules/zypper.py +++ b/salt/modules/zypper.py @@ -332,7 +332,7 @@ def del_repo(repo): return { repo: True, 'message': msg[0].childNodes[0].nodeValue, - } + } raise CommandExecutionError('Repository \'{0}\' not found.'.format(repo)) @@ -686,7 +686,7 @@ def upgrade(refresh=True): ret = {'changes': {}, 'result': True, 'comment': '', - } + } if salt.utils.is_true(refresh): refresh_db() From 4b484e22faac25fe0f6daa497fe83ed17587e680 Mon Sep 17 00:00:00 2001 From: Bo Maryniuk Date: Tue, 17 Mar 2015 19:57:05 +0100 Subject: [PATCH 02/11] Identation fixes --- salt/modules/zypper.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/salt/modules/zypper.py b/salt/modules/zypper.py index 79a9e246cc68..d085f1fef990 100644 --- a/salt/modules/zypper.py +++ b/salt/modules/zypper.py @@ -398,11 +398,11 @@ def mod_repo(repo, **kwargs): new_url = _urlparse(url) if not new_url.path: new_url = _urlparse.ParseResult(scheme=new_url.scheme, # pylint: disable=E1123 - netloc=new_url.netloc, - path='/', - params=new_url.params, - query=new_url.query, - fragment=new_url.fragment) + netloc=new_url.netloc, + path='/', + params=new_url.params, + query=new_url.query, + fragment=new_url.fragment) base_url = _urlparse(repo_meta['baseurl']) if new_url == base_url: @@ -460,7 +460,7 @@ def mod_repo(repo, **kwargs): # If repo nor added neither modified, error should be thrown if not added and not cmd_opt: raise CommandExecutionError( - 'Modification of the repository \'{0}\' was not specified.'.format(repo)) + 'Modification of the repository \'{0}\' was not specified.'.format(repo)) return get_repo(repo) @@ -1045,7 +1045,7 @@ def search(criteria): out = {} for solvable in [s for s in solvables if s.getAttribute('status') == 'not-installed' and - s.getAttribute('kind') == 'package']: + s.getAttribute('kind') == 'package']: out[solvable.getAttribute('name')] = { 'summary': solvable.getAttribute('summary') } From 3e6d790b97d145ffb6156e40345c43dd27347a27 Mon Sep 17 00:00:00 2001 From: Bo Maryniuk Date: Tue, 17 Mar 2015 19:57:25 +0100 Subject: [PATCH 03/11] Added package download to the local disk --- salt/modules/zypper.py | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/salt/modules/zypper.py b/salt/modules/zypper.py index d085f1fef990..582b80333467 100644 --- a/salt/modules/zypper.py +++ b/salt/modules/zypper.py @@ -1114,3 +1114,36 @@ def list_products(): ret[product.pop('name')] = product return ret + + +def download(*packages): + """ + Download packages to the local disk. + + CLI Examples: + + .. code-block:: bash + + salt '*' pkg.download httpd + salt '*' pkg.download httpd postfix + """ + if not packages: + raise CommandExecutionError("No packages has been specified.") + + doc = dom.parseString(__salt__['cmd.run']( + ('zypper -x --non-interactive download {0}'.format(' '.join(package))), + output_loglevel='trace')) + packages = {} + for dld_result in doc.getElementsByTagName("download-result"): + repo = dld_result.getElementsByTagName("repository")[0] + pkg_info = { + 'repository-name': repo.getAttribute("name"), + 'repository-alias': repo.getAttribute("alias"), + 'path': dld_result.getElementsByTagName("localfile")[0].getAttribute("path"), + } + packages[_get_first_aggregate_text(dld_result.getElementsByTagName("name"))] = pkg_info + + if packages: + return packages + + raise CommandExecutionError("Unable to download package {0}.".format(package)) From e2fa6631da057522a114d279ef145bb792c870e1 Mon Sep 17 00:00:00 2001 From: Bo Maryniuk Date: Wed, 18 Mar 2015 15:58:25 +0100 Subject: [PATCH 04/11] Added diff between installed and originally packaged file. --- salt/modules/rpm.py | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/salt/modules/rpm.py b/salt/modules/rpm.py index 2408c1422b4f..3fa57ee2c8ae 100644 --- a/salt/modules/rpm.py +++ b/salt/modules/rpm.py @@ -9,6 +9,7 @@ # Import Salt libs import salt.utils +import salt.utils.decorators as decorators log = logging.getLogger(__name__) @@ -222,3 +223,27 @@ def owner(*paths): if len(ret) == 1: return list(ret.values())[0] return ret + + +@decorators.which('rpm2cpio') +@decorators.which('cpio') +@decorators.which('diff') +def diff(package, path): + ''' + Return a formatted diff between current file and original in a package. + NOTE: this function includes all files (configuration and not), but does + not work on binary content. + + :param package: The name of the package + :param path: Full path to the installed file + :return: Difference string or raises and exception if examined file is binary. + ''' + + cmd = "rpm2cpio {0} " \ + "| cpio -i --quiet --to-stdout .{1} " \ + "| diff -u --label 'A {1}' --from-file=- --label 'B {1}' {1}" + res = __salt__['cmd.shell'](cmd.format(package, path), output_loglevel='trace') + if res and res.startswith('Binary file'): + return 'File "{0}" is binary and its content has been modified.'.format(path) + + return res From 6d5930bf56aa4e7c0d88a592f6109ef2697c3a31 Mon Sep 17 00:00:00 2001 From: Bo Maryniuk Date: Wed, 18 Mar 2015 15:58:56 +0100 Subject: [PATCH 05/11] Bugfix: Typo. --- 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 582b80333467..871ca3a7a5d9 100644 --- a/salt/modules/zypper.py +++ b/salt/modules/zypper.py @@ -1131,7 +1131,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(package))), + ('zypper -x --non-interactive download {0}'.format(' '.join(packages))), output_loglevel='trace')) packages = {} for dld_result in doc.getElementsByTagName("download-result"): From aa893a7c0365f6dc0e20da65b077901790df7098 Mon Sep 17 00:00:00 2001 From: Bo Maryniuk Date: Wed, 18 Mar 2015 16:00:57 +0100 Subject: [PATCH 06/11] Multipackages support. --- salt/modules/zypper.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/salt/modules/zypper.py b/salt/modules/zypper.py index 871ca3a7a5d9..981667782a4c 100644 --- a/salt/modules/zypper.py +++ b/salt/modules/zypper.py @@ -1133,7 +1133,7 @@ def download(*packages): doc = dom.parseString(__salt__['cmd.run']( ('zypper -x --non-interactive download {0}'.format(' '.join(packages))), output_loglevel='trace')) - packages = {} + pkg_ret = {} for dld_result in doc.getElementsByTagName("download-result"): repo = dld_result.getElementsByTagName("repository")[0] pkg_info = { @@ -1141,9 +1141,9 @@ def download(*packages): 'repository-alias': repo.getAttribute("alias"), 'path': dld_result.getElementsByTagName("localfile")[0].getAttribute("path"), } - packages[_get_first_aggregate_text(dld_result.getElementsByTagName("name"))] = pkg_info + pkg_ret[_get_first_aggregate_text(dld_result.getElementsByTagName("name"))] = pkg_info - if packages: - return packages + if pkg_ret: + return pkg_ret - raise CommandExecutionError("Unable to download package {0}.".format(package)) + raise CommandExecutionError("Unable to download packages: {0}.".format(', '.join(packages))) From b273960ef8bb5729795d7071aef9d0ce32e923e7 Mon Sep 17 00:00:00 2001 From: Bo Maryniuk Date: Wed, 18 Mar 2015 16:02:09 +0100 Subject: [PATCH 07/11] Added diff support between current and vendor file. --- salt/modules/zypper.py | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/salt/modules/zypper.py b/salt/modules/zypper.py index 981667782a4c..eea248527114 100644 --- a/salt/modules/zypper.py +++ b/salt/modules/zypper.py @@ -1147,3 +1147,36 @@ def download(*packages): return pkg_ret raise CommandExecutionError("Unable to download packages: {0}.".format(', '.join(packages))) + + +def diff(*paths): + ''' + Return a formatted diff between current files and original in a package. + NOTE: this function includes all files (configuration and not), but does + not work on binary content. + + :param path: Full path to the installed file + :return: Difference string or raises and exception if examined file is binary. + + .. code-block:: bash + + salt '*' pkg.diff httpd /etc/apache2/httpd.conf + ''' + ret = {} + + pkg_to_paths = {} + for pth in paths: + pth_pkg = __salt__['lowpkg.owner'](pth) + if not pth_pkg: + ret[pth] = os.path.exists(pth) and 'Not managed' or 'N/A' + else: + if pkg_to_paths.get(pth_pkg) is None: + pkg_to_paths[pth_pkg] = [] + pkg_to_paths[pth_pkg].append(pth) + + local_pkgs = __salt__['pkg.download'](*pkg_to_paths.keys()) + for pkg, files in pkg_to_paths.items(): + for path in files: + ret[path] = __salt__['lowpkg.diff'](local_pkgs[pkg]['path'], path) or 'Unchanged' + + return ret From 84c1eca3c5447f9755608b9101bd18a047177019 Mon Sep 17 00:00:00 2001 From: Bo Maryniuk Date: Wed, 18 Mar 2015 16:57:57 +0100 Subject: [PATCH 08/11] Doc adjustment. --- salt/modules/rpm.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/salt/modules/rpm.py b/salt/modules/rpm.py index 3fa57ee2c8ae..79d1376f641c 100644 --- a/salt/modules/rpm.py +++ b/salt/modules/rpm.py @@ -236,7 +236,7 @@ def diff(package, path): :param package: The name of the package :param path: Full path to the installed file - :return: Difference string or raises and exception if examined file is binary. + :return: Difference or empty string. For binary files only a notification. ''' cmd = "rpm2cpio {0} " \ From 7128dad16e7ab474f98bccb24ca42acf302cc458 Mon Sep 17 00:00:00 2001 From: Bo Maryniuk Date: Wed, 18 Mar 2015 17:21:27 +0100 Subject: [PATCH 09/11] Typo fix. --- 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 eea248527114..809de5ef811e 100644 --- a/salt/modules/zypper.py +++ b/salt/modules/zypper.py @@ -1120,7 +1120,7 @@ def download(*packages): """ Download packages to the local disk. - CLI Examples: + CLI example: .. code-block:: bash From 7f68fc744f6988169a26cd140e30eed13de84e20 Mon Sep 17 00:00:00 2001 From: Bo Maryniuk Date: Wed, 18 Mar 2015 17:21:41 +0100 Subject: [PATCH 10/11] Added CLI example. --- salt/modules/zypper.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/salt/modules/zypper.py b/salt/modules/zypper.py index 809de5ef811e..0b0d8d6b95ae 100644 --- a/salt/modules/zypper.py +++ b/salt/modules/zypper.py @@ -1158,9 +1158,11 @@ def diff(*paths): :param path: Full path to the installed file :return: Difference string or raises and exception if examined file is binary. + CLI example: + .. code-block:: bash - salt '*' pkg.diff httpd /etc/apache2/httpd.conf + salt '*' pkg.diff /etc/apache2/httpd.conf /etc/sudoers ''' ret = {} From e6d3c9c705c2a03e387a4f82f742351ccdf38560 Mon Sep 17 00:00:00 2001 From: Bo Maryniuk Date: Wed, 18 Mar 2015 17:21:54 +0100 Subject: [PATCH 11/11] Added CLI example. --- salt/modules/rpm.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/salt/modules/rpm.py b/salt/modules/rpm.py index 79d1376f641c..25d748473034 100644 --- a/salt/modules/rpm.py +++ b/salt/modules/rpm.py @@ -237,6 +237,12 @@ def diff(package, path): :param package: The name of the package :param path: Full path to the installed file :return: Difference or empty string. For binary files only a notification. + + CLI example: + + .. code-block:: bash + + salt '*' lowpkg.diff apache2 /etc/apache2/httpd.conf ''' cmd = "rpm2cpio {0} " \