diff --git a/add-buildargs-option-to-dockerng.build.patch b/add-buildargs-option-to-dockerng.build.patch deleted file mode 100644 index 8b76c26..0000000 --- a/add-buildargs-option-to-dockerng.build.patch +++ /dev/null @@ -1,48 +0,0 @@ -From 409e1835e0f26295212d1d148d1e7b42cf7dc6b0 Mon Sep 17 00:00:00 2001 -From: Michael Calmer -Date: Thu, 19 Jan 2017 15:39:10 +0100 -Subject: [PATCH] add buildargs option to dockerng.build - ---- - salt/modules/dockerng.py | 10 ++++++++-- - 1 file changed, 8 insertions(+), 2 deletions(-) - -diff --git a/salt/modules/dockerng.py b/salt/modules/dockerng.py -index 6c31c18289..87000e3846 100644 ---- a/salt/modules/dockerng.py -+++ b/salt/modules/dockerng.py -@@ -3553,7 +3553,8 @@ def build(path=None, - rm=True, - api_response=False, - fileobj=None, -- dockerfile=None): -+ dockerfile=None, -+ buildargs=None): - ''' - Builds a docker image from a Dockerfile or a URL - -@@ -3587,6 +3588,10 @@ def build(path=None, - - .. versionadded:: develop - -+ buildargs -+ A dictionary of build arguments provided to the docker build process. -+ -+ - **RETURN DATA** - - A dictionary containing one or more of the following keys: -@@ -3633,7 +3638,8 @@ def build(path=None, - fileobj=fileobj, - rm=rm, - nocache=not cache, -- dockerfile=dockerfile) -+ dockerfile=dockerfile, -+ buildargs=buildargs) - ret = {'Time_Elapsed': time.time() - time_started} - _clear_context() - --- -2.11.0 - - diff --git a/support-dryrun-for-dockerng.sls_build.patch b/add-options-for-dockerng.patch similarity index 71% rename from support-dryrun-for-dockerng.sls_build.patch rename to add-options-for-dockerng.patch index 9de2a0e..02bd0c8 100644 --- a/support-dryrun-for-dockerng.sls_build.patch +++ b/add-options-for-dockerng.patch @@ -1,21 +1,86 @@ -From ec727bbd931c8536b4f3cb1bf3f599432c063b3e Mon Sep 17 00:00:00 2001 +From 95d547d3e6c98f927eaad77346b84b2ccef95627 Mon Sep 17 00:00:00 2001 From: Michael Calmer -Date: Thu, 9 Feb 2017 12:44:43 +0100 -Subject: [PATCH] support dryrun for dockerng.sls_build +Date: Thu, 19 Jan 2017 15:39:10 +0100 +Subject: [PATCH] add options for dockerng + +* add buildargs option to dockerng.build +* docker buildargs require minimal dockerpy 1.6.0 and docker version 1.9.0 +* update version in the docs +* support dryrun for dockerng.sls_build provide the possibility to put extra modules into the thin added unit test for dockerng.sls_build dryrun option --- - salt/modules/dockerng.py | 29 +++++++++++-- + salt/modules/dockerng.py | 51 ++++++++++++++++++----- tests/unit/modules/dockerng_test.py | 82 +++++++++++++++++++++++++++++++++++++ - 2 files changed, 108 insertions(+), 3 deletions(-) + 2 files changed, 122 insertions(+), 11 deletions(-) diff --git a/salt/modules/dockerng.py b/salt/modules/dockerng.py -index cbf2a6b397..bd0a208cac 100644 +index 29af703ffa..c199fede1e 100644 --- a/salt/modules/dockerng.py +++ b/salt/modules/dockerng.py -@@ -5757,7 +5757,9 @@ def call(name, function, *args, **kwargs): +@@ -28,13 +28,13 @@ to replace references to ``dockerng`` with ``docker``. + Installation Prerequisites + -------------------------- + +-This execution module requires at least version 1.4.0 of both docker-py_ and +-Docker_. docker-py can easily be installed using :py:func:`pip.install +-`: ++This execution module requires at least version 1.6.0 of docker-py_ and ++version 1.9.0 of Docker_. docker-py can easily be installed using ++:py:func:`pip.install `: + + .. code-block:: bash + +- salt myminion pip.install docker-py>=1.4.0 ++ salt myminion pip.install docker-py>=1.6.0 + + .. _docker-py: https://pypi.python.org/pypi/docker-py + .. _Docker: https://www.docker.com/ +@@ -332,8 +332,8 @@ __func_alias__ = { + } + + # Minimum supported versions +-MIN_DOCKER = (1, 6, 0) +-MIN_DOCKER_PY = (1, 4, 0) ++MIN_DOCKER = (1, 9, 0) ++MIN_DOCKER_PY = (1, 6, 0) + + VERSION_RE = r'([\d.]+)' + +@@ -3557,7 +3557,8 @@ def build(path=None, + rm=True, + api_response=False, + fileobj=None, +- dockerfile=None): ++ dockerfile=None, ++ buildargs=None): + ''' + Builds a docker image from a Dockerfile or a URL + +@@ -3591,6 +3592,10 @@ def build(path=None, + + .. versionadded:: develop + ++ buildargs ++ A dictionary of build arguments provided to the docker build process. ++ ++ + **RETURN DATA** + + A dictionary containing one or more of the following keys: +@@ -3637,7 +3642,8 @@ def build(path=None, + fileobj=fileobj, + rm=rm, + nocache=not cache, +- dockerfile=dockerfile) ++ dockerfile=dockerfile, ++ buildargs=buildargs) + ret = {'Time_Elapsed': time.time() - time_started} + _clear_context() + +@@ -5755,7 +5761,9 @@ def call(name, function, *args, **kwargs): raise CommandExecutionError('Missing function parameter') # move salt into the container @@ -26,7 +91,7 @@ index cbf2a6b397..bd0a208cac 100644 with io.open(thin_path, 'rb') as file: _client_wrapper('put_archive', name, thin_dest_path, file) try: -@@ -5867,7 +5869,7 @@ def sls(name, mods=None, saltenv='base', **kwargs): +@@ -5865,7 +5873,7 @@ def sls(name, mods=None, saltenv='base', **kwargs): def sls_build(name, base='opensuse/python', mods=None, saltenv='base', @@ -35,7 +100,7 @@ index cbf2a6b397..bd0a208cac 100644 ''' Build a docker image using the specified sls modules and base image. -@@ -5875,6 +5877,24 @@ def sls_build(name, base='opensuse/python', mods=None, saltenv='base', +@@ -5873,6 +5881,24 @@ def sls_build(name, base='opensuse/python', mods=None, saltenv='base', can build a docker image inside myminion that results of applying those states by doing: @@ -60,7 +125,7 @@ index cbf2a6b397..bd0a208cac 100644 CLI Example: .. code-block:: bash -@@ -5907,9 +5927,12 @@ def sls_build(name, base='opensuse/python', mods=None, saltenv='base', +@@ -5905,9 +5931,12 @@ def sls_build(name, base='opensuse/python', mods=None, saltenv='base', # Now execute the state into the container ret = __salt__['dockerng.sls'](id_, mods, saltenv, **kwargs) # fail if the state was not successful diff --git a/add-ssh-option-to-salt-ssh.patch b/add-ssh-option-to-salt-ssh.patch index ec495d7..5b9e3fb 100644 --- a/add-ssh-option-to-salt-ssh.patch +++ b/add-ssh-option-to-salt-ssh.patch @@ -1,4 +1,4 @@ -From 949591bc0a4c0e768c08a2f61c040a1c4f0190ed Mon Sep 17 00:00:00 2001 +From c4c6610bf7314cc4c6ecf656bef341e2d1ca1587 Mon Sep 17 00:00:00 2001 From: Matei Albu Date: Mon, 19 Dec 2016 16:54:52 +0100 Subject: [PATCH] Add --ssh-option to salt-ssh @@ -16,7 +16,7 @@ Fix salt-ssh err when -ssh-option is missing 3 files changed, 35 insertions(+), 9 deletions(-) diff --git a/salt/client/ssh/__init__.py b/salt/client/ssh/__init__.py -index f0b7a282c0..9ed6be2b75 100644 +index 23ec948fe0..bbef9d8de1 100644 --- a/salt/client/ssh/__init__.py +++ b/salt/client/ssh/__init__.py @@ -295,6 +295,9 @@ class SSH(object): @@ -29,7 +29,7 @@ index f0b7a282c0..9ed6be2b75 100644 } if self.opts.get('rand_thin_dir'): self.defaults['thin_dir'] = os.path.join( -@@ -690,6 +693,7 @@ class Single(object): +@@ -693,6 +696,7 @@ class Single(object): identities_only=False, sudo_user=None, remote_port_forwards=None, @@ -37,7 +37,7 @@ index f0b7a282c0..9ed6be2b75 100644 **kwargs): # Get mine setting and mine_functions if defined in kwargs (from roster) self.mine = mine -@@ -746,7 +750,8 @@ class Single(object): +@@ -749,7 +753,8 @@ class Single(object): 'mods': self.mods, 'identities_only': identities_only, 'sudo_user': sudo_user, @@ -48,7 +48,7 @@ index f0b7a282c0..9ed6be2b75 100644 self.minion_opts = { 'grains_cache': True, diff --git a/salt/client/ssh/shell.py b/salt/client/ssh/shell.py -index 722ec07633..2884a52c1d 100644 +index f78cb623e1..613660fe34 100644 --- a/salt/client/ssh/shell.py +++ b/salt/client/ssh/shell.py @@ -64,7 +64,8 @@ class Shell(object): @@ -59,9 +59,9 @@ index 722ec07633..2884a52c1d 100644 + remote_port_forwards=None, + ssh_options=None): self.opts = opts - self.host = host - self.user = user -@@ -77,6 +78,7 @@ class Shell(object): + # ssh , but scp [ -Date: Wed, 1 Feb 2017 16:57:13 +0100 -Subject: [PATCH] docker buildargs require minimal dockerpy 1.6.0 and - docker version 1.9.0 - -update version in the docs ---- - salt/modules/dockerng.py | 12 ++++++------ - 1 file changed, 6 insertions(+), 6 deletions(-) - -diff --git a/salt/modules/dockerng.py b/salt/modules/dockerng.py -index 87000e3846..f29108f1ba 100644 ---- a/salt/modules/dockerng.py -+++ b/salt/modules/dockerng.py -@@ -28,13 +28,13 @@ to replace references to ``dockerng`` with ``docker``. - Installation Prerequisites - -------------------------- - --This execution module requires at least version 1.4.0 of both docker-py_ and --Docker_. docker-py can easily be installed using :py:func:`pip.install --`: -+This execution module requires at least version 1.6.0 of docker-py_ and -+version 1.9.0 of Docker_. docker-py can easily be installed using -+:py:func:`pip.install `: - - .. code-block:: bash - -- salt myminion pip.install docker-py>=1.4.0 -+ salt myminion pip.install docker-py>=1.6.0 - - .. _docker-py: https://pypi.python.org/pypi/docker-py - .. _Docker: https://www.docker.com/ -@@ -332,8 +332,8 @@ __func_alias__ = { - } - - # Minimum supported versions --MIN_DOCKER = (1, 6, 0) --MIN_DOCKER_PY = (1, 4, 0) -+MIN_DOCKER = (1, 9, 0) -+MIN_DOCKER_PY = (1, 6, 0) - - VERSION_RE = r'([\d.]+)' - --- -2.11.0 - - diff --git a/fix-a-typo-for-master-comments.patch b/fix-a-typo-for-master-comments.patch deleted file mode 100644 index 9789cc2..0000000 --- a/fix-a-typo-for-master-comments.patch +++ /dev/null @@ -1,32 +0,0 @@ -From 64ddef78a040dde7e547518331dc9e8a98ceb42f Mon Sep 17 00:00:00 2001 -From: Bo Maryniuk -Date: Thu, 5 Jan 2017 19:09:17 +0100 -Subject: [PATCH] Fix a typo for master comments - -* Disable custom rosters in API -* Pick up a specified roster file from the configured locations -* Explain what it is about and how to configure that -* Add docstring -* Add explanation comment -* Lintfix ---- - conf/master | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/conf/master b/conf/master -index f58eb496bf..3cfdae0a47 100644 ---- a/conf/master -+++ b/conf/master -@@ -405,7 +405,7 @@ syndic_user: salt - # Pass in an alternative location for the salt-ssh roster file - #roster_file: /etc/salt/roster - --# Define a location for roster files so they can be chosen when using Salt API. -+# Define a locations for roster files so they can be chosen when using Salt API. - # An administrator can place roster files into these locations. Then when - # calling Salt API, parameter 'roster_file' should contain a relative path to - # these locations. That is, "roster_file=/foo/roster" will be resolved as --- -2.11.0 - - diff --git a/fix-case-in-os_family-for-suse.patch b/fix-case-in-os_family-for-suse.patch new file mode 100644 index 0000000..bced534 --- /dev/null +++ b/fix-case-in-os_family-for-suse.patch @@ -0,0 +1,26 @@ +From 036be5f7300bbf6c5ef3967b5cc935fd678cd1e1 Mon Sep 17 00:00:00 2001 +From: Michael Calmer +Date: Thu, 23 Feb 2017 12:01:05 +0100 +Subject: [PATCH] fix case in os_family for Suse + +--- + salt/modules/service.py | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/salt/modules/service.py b/salt/modules/service.py +index bb7133ee99..49186e4c9d 100644 +--- a/salt/modules/service.py ++++ b/salt/modules/service.py +@@ -53,7 +53,7 @@ def __virtual__(): + if __grains__['kernel'] != 'Linux': + return (False, 'Non Linux OSes are not supported') + # SUSE >=12.0 uses systemd +- if __grains__.get('os_family', '') == 'SUSE': ++ if __grains__.get('os_family', '') == 'Suse': + try: + # osrelease might be in decimal format (e.g. "12.1"), or for + # SLES might include service pack (e.g. "11 SP3"), so split on +-- +2.11.0 + + diff --git a/fix-error-parsing.patch b/fix-error-parsing.patch deleted file mode 100644 index 1bb6bdf..0000000 --- a/fix-error-parsing.patch +++ /dev/null @@ -1,26 +0,0 @@ -From 7c459f38d43ef31ededce703fbfb432af1fdcee6 Mon Sep 17 00:00:00 2001 -From: Michael Calmer -Date: Sat, 4 Feb 2017 16:05:45 +0100 -Subject: [PATCH] fix error parsing - ---- - salt/modules/dockerng.py | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/salt/modules/dockerng.py b/salt/modules/dockerng.py -index f29108f1ba..cbf2a6b397 100644 ---- a/salt/modules/dockerng.py -+++ b/salt/modules/dockerng.py -@@ -1204,7 +1204,7 @@ def _error_detail(data, item): - ''' - err = item['errorDetail'] - if 'code' in err: -- msg = '{1}: {2}'.format( -+ msg = '{0}: {1}'.format( - item['errorDetail']['code'], - item['errorDetail']['message'], - ) --- -2.11.0 - - diff --git a/fix-leading-dots-on-sanitized-hostname.patch b/fix-leading-dots-on-sanitized-hostname.patch deleted file mode 100644 index af77429..0000000 --- a/fix-leading-dots-on-sanitized-hostname.patch +++ /dev/null @@ -1,94 +0,0 @@ -From dadd20bd0db0289ac4ad9f322f03de686b24c5a7 Mon Sep 17 00:00:00 2001 -From: Bo Maryniuk -Date: Wed, 25 Jan 2017 15:42:08 +0100 -Subject: [PATCH] Fix leading dots on sanitized hostname - -Add unit test - -Fix typo ---- - salt/utils/sanitizers.py | 2 +- - tests/unit/utils/sanitizers_test.py | 57 +++++++++++++++++++++++++++++++++++++ - 2 files changed, 58 insertions(+), 1 deletion(-) - create mode 100644 tests/unit/utils/sanitizers_test.py - -diff --git a/salt/utils/sanitizers.py b/salt/utils/sanitizers.py -index d05d39955d..83f621151a 100644 ---- a/salt/utils/sanitizers.py -+++ b/salt/utils/sanitizers.py -@@ -56,7 +56,7 @@ class InputSanitizer(object): - :param value: - :return: - ''' -- return re.sub(r'[^a-zA-Z0-9.-]', '', InputSanitizer.trim(value)) -+ return re.sub(r'[^a-zA-Z0-9.-]', '', InputSanitizer.trim(value)).strip('.') - - id = hostname - -diff --git a/tests/unit/utils/sanitizers_test.py b/tests/unit/utils/sanitizers_test.py -new file mode 100644 -index 0000000000..e9c333149c ---- /dev/null -+++ b/tests/unit/utils/sanitizers_test.py -@@ -0,0 +1,57 @@ -+# -*- coding: utf-8 -*- -+ -+# Import python libs -+from __future__ import absolute_import -+from salt.ext.six import text_type as text -+ -+# Import Salt Libs -+from salt.utils.sanitizers import clean -+ -+# Import Salt Testing Libs -+from salttesting import TestCase, skipIf -+from salttesting.mock import NO_MOCK, NO_MOCK_REASON -+from salttesting.helpers import ensure_in_syspath -+ -+ensure_in_syspath('../../') -+ -+ -+@skipIf(NO_MOCK, NO_MOCK_REASON) -+class SanitizersTestCase(TestCase): -+ ''' -+ TestCase for sanitizers -+ ''' -+ def test_sanitized_trim(self): -+ ''' -+ Test sanitized input for trimming -+ ''' -+ value = u' sample ' -+ response = clean.trim(value) -+ assert response == 'sample' -+ assert type(response) == text -+ -+ def test_sanitized_filename(self): -+ ''' -+ Test sanitized input for filename -+ ''' -+ value = '/absolute/path/to/the/file.txt' -+ response = clean.filename(value) -+ assert response == 'file.txt' -+ -+ value = '../relative/path/to/the/file.txt' -+ response = clean.filename(value) -+ assert response == 'file.txt' -+ -+ def test_sanitized_hostname(self): -+ ''' -+ Test sanitized input for hostname (id) -+ ''' -+ value = ' ../ ../some/dubious/hostname ' -+ response = clean.hostname(value) -+ assert response == 'somedubioushostname' -+ -+ test_sanitized_id = test_sanitized_hostname -+ -+ -+if __name__ == '__main__': -+ from integration import run_tests -+ run_tests(SanitizersTestCase, needs_daemon=False) --- -2.11.0 - - diff --git a/fix-regression-in-file.get_managed-add-unit-tests.patch b/fix-regression-in-file.get_managed-add-unit-tests.patch new file mode 100644 index 0000000..1764a68 --- /dev/null +++ b/fix-regression-in-file.get_managed-add-unit-tests.patch @@ -0,0 +1,196 @@ +From 89fd1a83d282a10728077a08466627271a052733 Mon Sep 17 00:00:00 2001 +From: Erik Johnson +Date: Wed, 1 Mar 2017 10:19:33 -0600 +Subject: [PATCH] Fix regression in file.get_managed, add unit tests + +This is no longer needed since we're invoking the state module directly +and not via the state compiler. + +* Fix regression in file.get_managed when skip_verify=True +* Add integration tests for remote file sources +* Remove next(iter()) extraction +--- + salt/modules/file.py | 6 +-- + salt/states/archive.py | 11 ---- + tests/integration/states/file.py | 105 +++++++++++++++++++++++++++++++++++++++ + 3 files changed, 108 insertions(+), 14 deletions(-) + +diff --git a/salt/modules/file.py b/salt/modules/file.py +index 8f0c6914b6..381800bc1a 100644 +--- a/salt/modules/file.py ++++ b/salt/modules/file.py +@@ -3745,13 +3745,13 @@ def get_managed( + if cached_dest and (source_hash or skip_verify): + htype = source_sum.get('hash_type', 'sha256') + cached_sum = get_hash(cached_dest, form=htype) +- if cached_sum != source_sum['hsum']: +- cache_refetch = True +- elif skip_verify: ++ if skip_verify: + # prev: if skip_verify or cached_sum == source_sum['hsum']: + # but `cached_sum == source_sum['hsum']` is elliptical as prev if + sfn = cached_dest + source_sum = {'hsum': cached_sum, 'hash_type': htype} ++ elif cached_sum != source_sum['hsum']: ++ cache_refetch = True + + # If we didn't have the template or remote file, let's get it + # Similarly when the file has been updated and the cache has to be refreshed +diff --git a/salt/states/archive.py b/salt/states/archive.py +index c5df213620..46146e971e 100644 +--- a/salt/states/archive.py ++++ b/salt/states/archive.py +@@ -897,17 +897,6 @@ def extracted(name, + ret['comment'] = '\n'.join([str(x) for x in file_result]) + return ret + +- # Get actual state result. The state.single return is a single-element +- # dictionary with the state's unique ID at the top level, and its value +- # being the state's return dictionary. next(iter(dict_name)) will give +- # us the value of the first key, so +- # file_result[next(iter(file_result))] will give us the results of the +- # state.single we just ran. +- try: +- file_result = file_result[next(iter(file_result))] +- except AttributeError: +- pass +- + try: + if not file_result['result']: + log.debug('failed to download {0}'.format(source_match)) +diff --git a/tests/integration/states/file.py b/tests/integration/states/file.py +index d63f318064..faa83d00e8 100644 +--- a/tests/integration/states/file.py ++++ b/tests/integration/states/file.py +@@ -9,15 +9,22 @@ from __future__ import absolute_import + from distutils.version import LooseVersion + import errno + import glob ++import logging + import os + import re + import sys + import shutil ++import socket + import stat + import tempfile + import textwrap ++import threading ++import tornado.ioloop ++import tornado.web + import filecmp + ++log = logging.getLogger(__name__) ++ + # Import 3rd-party libs + from salt.ext.six.moves import range # pylint: disable=import-error,redefined-builtin + +@@ -2392,6 +2399,104 @@ class FileTest(integration.ModuleCase, integration.SaltReturnAssertsMixIn): + if check_file: + self.run_function('file.remove', [file]) + ++ ++PORT = 9999 ++FILE_SOURCE = 'http://localhost:{0}/grail/scene33'.format(PORT) ++FILE_HASH = 'd2feb3beb323c79fc7a0f44f1408b4a3' ++STATE_DIR = os.path.join(integration.FILES, 'file', 'base') ++ ++ ++class RemoteFileTest(integration.ModuleCase, integration.SaltReturnAssertsMixIn): ++ ''' ++ Uses a local tornado webserver to test http(s) file.managed states with and ++ without skip_verify ++ ''' ++ @classmethod ++ def webserver(cls): ++ ''' ++ method to start tornado static web app ++ ''' ++ application = tornado.web.Application([ ++ (r'/(.*)', tornado.web.StaticFileHandler, {'path': STATE_DIR}) ++ ]) ++ application.listen(PORT) ++ tornado.ioloop.IOLoop.instance().start() ++ ++ @classmethod ++ def setUpClass(cls): ++ ''' ++ start tornado app on thread and wait until it is running ++ ''' ++ cls.server_thread = threading.Thread(target=cls.webserver) ++ cls.server_thread.daemon = True ++ cls.server_thread.start() ++ # check if tornado app is up ++ port_closed = True ++ while port_closed: ++ sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) ++ result = sock.connect_ex(('127.0.0.1', PORT)) ++ if result == 0: ++ port_closed = False ++ ++ @classmethod ++ def tearDownClass(cls): ++ tornado.ioloop.IOLoop.instance().stop() ++ cls.server_thread.join() ++ ++ def setUp(self): ++ fd_, self.name = tempfile.mkstemp(dir=integration.TMP) ++ try: ++ os.close(fd_) ++ except OSError as exc: ++ if exc.errno != errno.EBADF: ++ raise exc ++ # Remove the file that mkstemp just created so that the states can test ++ # creating a new file instead of a diff from a zero-length file. ++ self.tearDown() ++ ++ def tearDown(self): ++ try: ++ os.remove(self.name) ++ except OSError as exc: ++ if exc.errno != errno.ENOENT: ++ raise exc ++ ++ def test_file_managed_http_source_no_hash(self): ++ ''' ++ Test a remote file with no hash ++ ''' ++ ret = self.run_state('file.managed', ++ name=self.name, ++ source=FILE_SOURCE, ++ skip_verify=False) ++ log.debug('ret = %s', ret) ++ # This should fail because no hash was provided ++ self.assertSaltFalseReturn(ret) ++ ++ def test_file_managed_http_source(self): ++ ''' ++ Test a remote file with no hash ++ ''' ++ ret = self.run_state('file.managed', ++ name=self.name, ++ source=FILE_SOURCE, ++ source_hash=FILE_HASH, ++ skip_verify=False) ++ log.debug('ret = %s', ret) ++ self.assertSaltTrueReturn(ret) ++ ++ def test_file_managed_http_source_skip_verify(self): ++ ''' ++ Test a remote file using skip_verify ++ ''' ++ ret = self.run_state('file.managed', ++ name=self.name, ++ source=FILE_SOURCE, ++ skip_verify=True) ++ log.debug('ret = %s', ret) ++ self.assertSaltTrueReturn(ret) ++ ++ + if __name__ == '__main__': + from integration import run_tests + run_tests(FileTest) +-- +2.11.0 + + diff --git a/fix-timezone-handling-for-rpm-installtime-bsc-101707.patch b/fix-timezone-handling-for-rpm-installtime-bsc-101707.patch deleted file mode 100644 index c5ad91d..0000000 --- a/fix-timezone-handling-for-rpm-installtime-bsc-101707.patch +++ /dev/null @@ -1,34 +0,0 @@ -From f45b229c9fea4be349484d8d041c735fa78500b5 Mon Sep 17 00:00:00 2001 -From: Frantisek Kobzik -Date: Thu, 12 Jan 2017 16:02:47 +0100 -Subject: [PATCH] Fix timezone handling for rpm installtime (bsc#1017078) - -Previously datetime.fromtimestamp was used. If used without additional -parameters, this method returns date in the local timezone. - -Our code took the result of fromtimestamp, appended 'Z' and returned -this string. This is wrong as 'Z' means UTC (the client code parses this -value as UTC, but it's in fact local time). - -Fixed by using utcfromtimestamp. ---- - 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 68268dea1d..9dace3cb6f 100644 ---- a/salt/modules/rpm.py -+++ b/salt/modules/rpm.py -@@ -575,7 +575,7 @@ def info(*packages, **attr): - # Convert Unix ticks into ISO time format - if key in ['build_date', 'install_date']: - try: -- pkg_data[key] = datetime.datetime.fromtimestamp(int(value)).isoformat() + "Z" -+ pkg_data[key] = datetime.datetime.utcfromtimestamp(int(value)).isoformat() + "Z" - except ValueError: - log.warning('Could not convert "{0}" into Unix time'.format(value)) - continue --- -2.11.0 - - diff --git a/increasing-timeouts-for-running-integrations-tests.patch b/increasing-timeouts-for-running-integrations-tests.patch deleted file mode 100644 index 9d2da84..0000000 --- a/increasing-timeouts-for-running-integrations-tests.patch +++ /dev/null @@ -1,170 +0,0 @@ -From 1c22c72afce15585070829054e3460a61947e256 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Pablo=20Su=C3=A1rez=20Hern=C3=A1ndez?= - -Date: Mon, 23 Jan 2017 12:10:22 +0000 -Subject: [PATCH] Increasing timeouts for running integrations tests - ---- - tests/integration/__init__.py | 16 ++++++++-------- - tests/integration/runners/state.py | 2 +- - tests/integration/shell/call.py | 6 +++--- - tests/integration/shell/key.py | 2 +- - tests/integration/shell/matcher.py | 2 +- - tests/integration/shell/runner.py | 2 +- - 6 files changed, 15 insertions(+), 15 deletions(-) - -diff --git a/tests/integration/__init__.py b/tests/integration/__init__.py -index a37ad61d2e..104566363a 100644 ---- a/tests/integration/__init__.py -+++ b/tests/integration/__init__.py -@@ -801,7 +801,7 @@ class TestDaemon(object): - ) - sys.stdout.flush() - process.start() -- process.wait_until_running(timeout=15) -+ process.wait_until_running(timeout=60) - sys.stdout.write( - '\r{0}\r'.format( - ' ' * getattr(self.parser.options, 'output_columns', PNUM) -@@ -1863,14 +1863,14 @@ class ShellCase(AdaptedConfigurationTestCaseMixIn, ShellTestCase, ScriptPathMixi - except OSError: - os.chdir(INTEGRATION_TEST_DIR) - -- def run_salt(self, arg_str, with_retcode=False, catch_stderr=False, timeout=30): # pylint: disable=W0221 -+ def run_salt(self, arg_str, with_retcode=False, catch_stderr=False, timeout=60): # pylint: disable=W0221 - ''' - Execute salt - ''' - arg_str = '-c {0} {1}'.format(self.get_config_dir(), arg_str) - return self.run_script('salt', arg_str, with_retcode=with_retcode, catch_stderr=catch_stderr, timeout=timeout) - -- def run_ssh(self, arg_str, with_retcode=False, catch_stderr=False, timeout=25): # pylint: disable=W0221 -+ def run_ssh(self, arg_str, with_retcode=False, catch_stderr=False, timeout=60): # pylint: disable=W0221 - ''' - Execute salt-ssh - ''' -@@ -1885,7 +1885,7 @@ class ShellCase(AdaptedConfigurationTestCaseMixIn, ShellTestCase, ScriptPathMixi - arg_str, - timeout=timeout, - async_flag=' --async' if async else '') -- return self.run_script('salt-run', arg_str, with_retcode=with_retcode, catch_stderr=catch_stderr, timeout=30) -+ return self.run_script('salt-run', arg_str, with_retcode=with_retcode, catch_stderr=catch_stderr, timeout=60) - - def run_run_plus(self, fun, *arg, **kwargs): - ''' -@@ -1932,7 +1932,7 @@ class ShellCase(AdaptedConfigurationTestCaseMixIn, ShellTestCase, ScriptPathMixi - arg_str, - catch_stderr=catch_stderr, - with_retcode=with_retcode, -- timeout=30 -+ timeout=60 - ) - - def run_cp(self, arg_str, with_retcode=False, catch_stderr=False): -@@ -1940,16 +1940,16 @@ class ShellCase(AdaptedConfigurationTestCaseMixIn, ShellTestCase, ScriptPathMixi - Execute salt-cp - ''' - arg_str = '--config-dir {0} {1}'.format(self.get_config_dir(), arg_str) -- return self.run_script('salt-cp', arg_str, with_retcode=with_retcode, catch_stderr=catch_stderr, timeout=30) -+ return self.run_script('salt-cp', arg_str, with_retcode=with_retcode, catch_stderr=catch_stderr, timeout=60) - - def run_call(self, arg_str, with_retcode=False, catch_stderr=False): - ''' - Execute salt-call. - ''' - arg_str = '--config-dir {0} {1}'.format(self.get_config_dir(), arg_str) -- return self.run_script('salt-call', arg_str, with_retcode=with_retcode, catch_stderr=catch_stderr, timeout=30) -+ return self.run_script('salt-call', arg_str, with_retcode=with_retcode, catch_stderr=catch_stderr, timeout=60) - -- def run_cloud(self, arg_str, catch_stderr=False, timeout=15): -+ def run_cloud(self, arg_str, catch_stderr=False, timeout=30): - ''' - Execute salt-cloud - ''' -diff --git a/tests/integration/runners/state.py b/tests/integration/runners/state.py -index 07cfe15fe0..3ca74e915b 100644 ---- a/tests/integration/runners/state.py -+++ b/tests/integration/runners/state.py -@@ -109,7 +109,7 @@ class OrchEventTest(integration.ShellCase): - Tests for orchestration events - ''' - def setUp(self): -- self.timeout = 15 -+ self.timeout = 60 - self.master_d_dir = os.path.join(self.get_config_dir(), 'master.d') - try: - os.makedirs(self.master_d_dir) -diff --git a/tests/integration/shell/call.py b/tests/integration/shell/call.py -index 275878f7ca..e444743720 100644 ---- a/tests/integration/shell/call.py -+++ b/tests/integration/shell/call.py -@@ -272,7 +272,7 @@ class CallTest(integration.ShellCase, testprogram.TestProgramCase, integration.S - '--config-dir {0} --local cmd.run "echo foo"'.format( - config_dir - ), -- timeout=15 -+ timeout=60 - ) - try: - self.assertIn('local:', ret) -@@ -295,7 +295,7 @@ class CallTest(integration.ShellCase, testprogram.TestProgramCase, integration.S - '--config-dir {0} cmd.run "echo foo"'.format( - config_dir - ), -- timeout=15 -+ timeout=60 - ) - self.assertIn('local:', ret) - finally: -@@ -325,7 +325,7 @@ class CallTest(integration.ShellCase, testprogram.TestProgramCase, integration.S - '--config-dir {0} cmd.run "echo foo"'.format( - config_dir - ), -- timeout=15, -+ timeout=60, - catch_stderr=True, - with_retcode=True - ) -diff --git a/tests/integration/shell/key.py b/tests/integration/shell/key.py -index bf13fff9a3..aeba671829 100644 ---- a/tests/integration/shell/key.py -+++ b/tests/integration/shell/key.py -@@ -265,7 +265,7 @@ class KeyTest(integration.ShellCase, integration.ShellCaseCommonTestsMixIn): - '--config-dir {0} -L'.format( - config_dir - ), -- timeout=15 -+ timeout=60 - ) - try: - self.assertIn('minion', '\n'.join(ret)) -diff --git a/tests/integration/shell/matcher.py b/tests/integration/shell/matcher.py -index e1623ae1b2..2bc8e61220 100644 ---- a/tests/integration/shell/matcher.py -+++ b/tests/integration/shell/matcher.py -@@ -353,7 +353,7 @@ class MatchTest(integration.ShellCase, integration.ShellCaseCommonTestsMixIn): - '--config-dir {0} minion test.ping'.format( - config_dir - ), -- timeout=15, -+ timeout=60, - catch_stderr=True, - with_retcode=True - ) -diff --git a/tests/integration/shell/runner.py b/tests/integration/shell/runner.py -index 6d65d537b5..cf7257b93d 100644 ---- a/tests/integration/shell/runner.py -+++ b/tests/integration/shell/runner.py -@@ -109,7 +109,7 @@ class RunTest(integration.ShellCase, testprogram.TestProgramCase, integration.Sh - '--config-dir {0} -d'.format( - config_dir - ), -- timeout=15, -+ timeout=60, - catch_stderr=True, - with_retcode=True - ) --- -2.11.0 - - diff --git a/prevent-crash-on-unknown-to-the-repo-package.patch b/prevent-crash-on-unknown-to-the-repo-package.patch deleted file mode 100644 index 5fa33ed..0000000 --- a/prevent-crash-on-unknown-to-the-repo-package.patch +++ /dev/null @@ -1,26 +0,0 @@ -From 48a8dd97be9ddef45f249d530b9c7d1a593e5ac0 Mon Sep 17 00:00:00 2001 -From: Bo Maryniuk -Date: Fri, 27 Jan 2017 14:31:50 +0100 -Subject: [PATCH] Prevent crash on unknown to the repo package - ---- - salt/states/pkg.py | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/salt/states/pkg.py b/salt/states/pkg.py -index d81f0c00c7..7c3b27b9ac 100644 ---- a/salt/states/pkg.py -+++ b/salt/states/pkg.py -@@ -1909,7 +1909,7 @@ def latest( - for pkg in desired_pkgs: - if not avail.get(pkg): - # Package either a) is up-to-date, or b) does not exist -- if not cur[pkg]: -+ if not cur.get(pkg): - # Package does not exist - msg = 'No information found for \'{0}\'.'.format(pkg) - log.error(msg) --- -2.11.0 - - diff --git a/prevents-oserror-exception-in-case-path-doesn-t-exis.patch b/prevents-oserror-exception-in-case-path-doesn-t-exis.patch deleted file mode 100644 index a0248b7..0000000 --- a/prevents-oserror-exception-in-case-path-doesn-t-exis.patch +++ /dev/null @@ -1,28 +0,0 @@ -From a74360a87e11bbcd65d253426c930769f83361e4 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Pablo=20Su=C3=A1rez=20Hern=C3=A1ndez?= - -Date: Tue, 14 Feb 2017 16:13:32 +0000 -Subject: [PATCH] Prevents 'OSError' exception in case path doesn't exist - ---- - salt/returners/local_cache.py | 3 +++ - 1 file changed, 3 insertions(+) - -diff --git a/salt/returners/local_cache.py b/salt/returners/local_cache.py -index e2d2979241..d46cb1e70c 100644 ---- a/salt/returners/local_cache.py -+++ b/salt/returners/local_cache.py -@@ -60,6 +60,9 @@ def _walk_through(job_dir): - for top in os.listdir(job_dir): - t_path = os.path.join(job_dir, top) - -+ if not os.path.exists(t_path): -+ continue -+ - for final in os.listdir(t_path): - load_path = os.path.join(t_path, final, LOAD_P) - --- -2.11.0 - - diff --git a/salt-2016.11.2.tar.gz b/salt-2016.11.2.tar.gz deleted file mode 100644 index 2182004..0000000 --- a/salt-2016.11.2.tar.gz +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:f5c3d3cf4293d5b80a93790c76dec61421991c9c54222abd7327b3437ad13a43 -size 9114042 diff --git a/salt-2016.11.3.tar.gz b/salt-2016.11.3.tar.gz new file mode 100644 index 0000000..32c9ee7 --- /dev/null +++ b/salt-2016.11.3.tar.gz @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9d5849f38a858288ebc6ef790ced86ae724e61b06e3ee27e6cecf3f6c1ecbc51 +size 9163351 diff --git a/salt.changes b/salt.changes index c6aa374..2ba91c5 100644 --- a/salt.changes +++ b/salt.changes @@ -1,3 +1,34 @@ +------------------------------------------------------------------- +Fri Mar 3 09:36:17 UTC 2017 - bmaryniuk@suse.com + +- Update to 2016.11.3 + See https://docs.saltstack.com/en/develop/topics/releases/2016.11.3.html + for full changelog + +- Use correct package names for PyYAML and MarkupSafe (tbechtold@suse.com) + +- Changed: + * add-ssh-option-to-salt-ssh.patch + +- Added: + * add-options-for-dockerng.patch + * fix-case-in-os_family-for-suse.patch + * fix-regression-in-file.get_managed-add-unit-tests.patch + * translate-variable-arguments-if-they-contain-hidden-.patch + +- Removed: + * add-buildargs-option-to-dockerng.build.patch + * docker-buildargs-require-minimal-dockerpy-1.6.0-and-.patch + * fix-a-typo-for-master-comments.patch + * fix-error-parsing.patch + * fix-leading-dots-on-sanitized-hostname.patch + * fix-timezone-handling-for-rpm-installtime-bsc-101707.patch + * increasing-timeouts-for-running-integrations-tests.patch + * prevent-crash-on-unknown-to-the-repo-package.patch + * prevents-oserror-exception-in-case-path-doesn-t-exis.patch + * snapper-module-improvements.patch + * support-dryrun-for-dockerng.sls_build.patch + ------------------------------------------------------------------- Thu Feb 16 14:41:48 UTC 2017 - bmaryniuk@suse.com diff --git a/salt.spec b/salt.spec index ef8102b..d0d9c71 100644 --- a/salt.spec +++ b/salt.spec @@ -37,7 +37,7 @@ %bcond_with builddocs Name: salt -Version: 2016.11.2 +Version: 2016.11.3 Release: 0 Summary: A parallel remote execution system License: Apache-2.0 @@ -51,22 +51,21 @@ Source3: html.tar.bz2 Source4: update-documentation.sh Source5: travis.yml -# We do not upstream this patch because this is something that we have to fix on our side # PATCH-FIX-OPENSUSE use-forking-daemon.patch tserong@suse.com -- We don't have python-systemd, so notify can't work +# We do not upstream this patch because this is something that we have to fix on our side Patch1: tserong-suse.com-we-don-t-have-python-systemd-so-not.patch -# We do not upstream this patch because this is suse custom configuration # PATCH-FIX-OPENSUSE use-salt-user-for-master.patch -- Run salt master as dedicated salt user +# We do not upstream this patch because this is suse custom configuration Patch2: run-salt-master-as-dedicated-salt-user.patch -# (see: https://trello.com/c/wh96lCD4/1528-get-rid-of-0003-check-if-byte-strings-are-properly-encoded-in-utf-8-patch-in-the-salt-package) -# We do not upstream this patch because it has been fixed upstream # PATCH-FIX-OPENSUSE https://github.com/saltstack/salt/pull/30424 +# We do not upstream this patch because it has been fixed upstream +# (see: https://trello.com/c/wh96lCD4/1528-get-rid-of-0003-check-if-byte-strings-are-properly-encoded-in-utf-8-patch-in-the-salt-package) Patch3: check-if-byte-strings-are-properly-encoded-in-utf-8.patch -# We do not upstream this patch because the issue is on our side # PATCH-FIX-OPENSUSE prevent rebuilds in OBS +# We do not upstream this patch because the issue is on our side Patch4: do-not-generate-a-date-in-a-comment-to-prevent-rebui.patch -# We do not upstream this because this is for SUSE only (15.08.2016) # PATCH-FIX-OPENSUSE Generate events from the Salt minion, -# if Zypper has been used outside the Salt infrastructure +# We do not upstream this because this is for SUSE only (15.08.2016) if Zypper has been used outside the Salt infrastructure Patch5: add-zypp-notify-plugin.patch # PATCH-FIX_OPENSUSE Patch6: run-salt-api-as-user-salt-bsc-990029.patch @@ -82,30 +81,16 @@ Patch10: avoid-failures-on-sles-12-sp2-because-of-new-systemd.patch Patch11: add-yum-plugin.patch # PATCH-FIX_OPENSUSE Patch12: add-ssh-option-to-salt-ssh.patch -# PATCH-FIX_UPSTREAM https://github.com/saltstack/salt/pull/38639/commits -Patch13: fix-a-typo-for-master-comments.patch # PATCH-FIX_UPSTREAM https://github.com/saltstack/salt/pull/38806 -Patch14: add-a-salt-minion-service-control-file.patch -# PATCH-FIX_UPSTREAM https://github.com/saltstack/salt/pull/38824 -Patch15: add-buildargs-option-to-dockerng.build.patch -# PATCH-FIX_UPSTREAM https://github.com/saltstack/salt/pull/38885 -Patch16: increasing-timeouts-for-running-integrations-tests.patch -# PATCH-FIX_UPSTREAM https://github.com/saltstack/salt/pull/38957 -Patch17: fix-timezone-handling-for-rpm-installtime-bsc-101707.patch -# PATCH-FIX_UPSTREAM https://github.com/saltstack/salt/pull/38940/commits -Patch18: fix-leading-dots-on-sanitized-hostname.patch -# PATCH-FIX_UPSTREAM https://github.com/saltstack/salt/pull/38991 -Patch19: prevent-crash-on-unknown-to-the-repo-package.patch -# PATCH-FIX_UPSTREAM https://github.com/saltstack/salt/pull/39111 -Patch20: docker-buildargs-require-minimal-dockerpy-1.6.0-and-.patch -# PATCH-FIX_UPSTREAM https://github.com/saltstack/salt/pull/39179 -Patch21: fix-error-parsing.patch -# PATCH-FIX_UPSTREAM https://github.com/saltstack/salt/pull/39162 -Patch22: snapper-module-improvements.patch -# PATCH-FIX_UPSTREAM https://github.com/saltstack/salt/pull/39278 -Patch23: support-dryrun-for-dockerng.sls_build.patch -# PATCH-FIX_UPSTREAM https://github.com/saltstack/salt/pull/39400 -Patch24: prevents-oserror-exception-in-case-path-doesn-t-exis.patch +Patch13: add-a-salt-minion-service-control-file.patch +# PATCH-FIX-OPENSUSE +Patch14: add-options-for-dockerng.patch +# PATCH-FIX_UPSTREAM https://github.com/saltstack/salt/pull/39591 +Patch15: fix-case-in-os_family-for-suse.patch +# PATCH-FIX_OPENSUSE +Patch16: translate-variable-arguments-if-they-contain-hidden-.patch +# PATCH-FIX_UPSTREAM https://github.com/saltstack/salt/pull/39762 +Patch17: fix-regression-in-file.get_managed-add-unit-tests.patch BuildRoot: %{_tmppath}/%{name}-%{version}-build BuildRequires: logrotate @@ -117,13 +102,13 @@ BuildRequires: python-jinja2 %else BuildRequires: python-Jinja2 %endif +BuildRequires: python-MarkupSafe +BuildRequires: python-PyYAML BuildRequires: python-futures >= 2.0 -BuildRequires: python-markupsafe BuildRequires: python-msgpack-python > 0.3 BuildRequires: python-psutil BuildRequires: python-requests >= 1.0.0 BuildRequires: python-tornado >= 4.2.1 -BuildRequires: python-yaml # requirements/opt.txt (not all) # BuildRequires: python-MySQL-python # BuildRequires: python-timelib @@ -182,13 +167,13 @@ Requires: yum %else Requires: python-Jinja2 %endif +Requires: python-MarkupSafe +Requires: python-PyYAML Requires: python-futures >= 2.0 -Requires: python-markupsafe Requires: python-msgpack-python > 0.3 Requires: python-psutil 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 @@ -497,13 +482,6 @@ cp %{S:5} ./.travis.yml %patch15 -p1 %patch16 -p1 %patch17 -p1 -%patch18 -p1 -%patch19 -p1 -%patch20 -p1 -%patch21 -p1 -%patch22 -p1 -%patch23 -p1 -%patch24 -p1 %build %{__python} setup.py --salt-transport=both build diff --git a/snapper-module-improvements.patch b/snapper-module-improvements.patch deleted file mode 100644 index f0f6964..0000000 --- a/snapper-module-improvements.patch +++ /dev/null @@ -1,275 +0,0 @@ -From 678de7117211fc359c9aa7e29f6c2fecf0944b08 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Pablo=20Su=C3=A1rez=20Hern=C3=A1ndez?= - -Date: Fri, 27 Jan 2017 17:07:25 +0000 -Subject: [PATCH] Snapper module improvements - -* Snapper: Adding support for deleting snapshots -* Snapper: Adding support for snapshot metadata modification -* Snapper: Adding support for creating configurations -* Adds 'snapper.delete_snapshots' unit tests -* Adds 'snapper.modify_snapshots' unit tests -* Adds 'snapper.create_config' unit tests -* Removing extra spaces -* pylint fixes ---- - salt/modules/snapper.py | 159 +++++++++++++++++++++++++++++++++++-- - tests/unit/modules/snapper_test.py | 50 ++++++++++++ - 2 files changed, 201 insertions(+), 8 deletions(-) - -diff --git a/salt/modules/snapper.py b/salt/modules/snapper.py -index 318ce9b99d..d5f1181743 100644 ---- a/salt/modules/snapper.py -+++ b/salt/modules/snapper.py -@@ -290,6 +290,60 @@ def get_config(name='root'): - ) - - -+def create_config(name=None, -+ subvolume=None, -+ fstype=None, -+ template=None, -+ extra_opts=None): -+ ''' -+ Creates a new Snapper configuration -+ -+ name -+ Name of the new Snapper configuration. -+ subvolume -+ Path to the related subvolume. -+ fstype -+ Filesystem type of the subvolume. -+ template -+ Configuration template to use. (Default: default) -+ extra_opts -+ Extra Snapper configuration opts dictionary. It will override the values provided -+ by the given template (if any). -+ -+ CLI example: -+ -+ .. code-block:: bash -+ -+ salt '*' snapper.create_config name=myconfig subvolume=/foo/bar/ fstype=btrfs -+ salt '*' snapper.create_config name=myconfig subvolume=/foo/bar/ fstype=btrfs template="default" -+ salt '*' snapper.create_config name=myconfig subvolume=/foo/bar/ fstype=btrfs extra_opts='{"NUMBER_CLEANUP": False}' -+ ''' -+ def raise_arg_error(argname): -+ raise CommandExecutionError( -+ 'You must provide a "{0}" for the new configuration'.format(argname) -+ ) -+ -+ if not name: -+ raise_arg_error("name") -+ if not subvolume: -+ raise_arg_error("subvolume") -+ if not fstype: -+ raise_arg_error("fstype") -+ if not template: -+ template = "" -+ -+ try: -+ snapper.CreateConfig(name, subvolume, fstype, template) -+ if extra_opts: -+ set_config(name, **extra_opts) -+ return get_config(name) -+ except dbus.DBusException as exc: -+ raise CommandExecutionError( -+ 'Error encountered while creating the new configuration: {0}' -+ .format(_dbus_exception_to_reason(exc, locals())) -+ ) -+ -+ - def create_snapshot(config='root', snapshot_type='single', pre_number=None, - description=None, cleanup_algorithm='number', userdata=None, - **kwargs): -@@ -309,14 +363,14 @@ def create_snapshot(config='root', snapshot_type='single', pre_number=None, - cleanup_algorithm - Set the cleanup algorithm for the snapshot. - -- number -- Deletes old snapshots when a certain number of snapshots -- is reached. -- timeline -- Deletes old snapshots but keeps a number of hourly, -- daily, weekly, monthly and yearly snapshots. -- empty-pre-post -- Deletes pre/post snapshot pairs with empty diffs. -+ number -+ Deletes old snapshots when a certain number of snapshots -+ is reached. -+ timeline -+ Deletes old snapshots but keeps a number of hourly, -+ daily, weekly, monthly and yearly snapshots. -+ empty-pre-post -+ Deletes pre/post snapshot pairs with empty diffs. - userdata - Set userdata for the snapshot (key-value pairs). - -@@ -364,6 +418,95 @@ def create_snapshot(config='root', snapshot_type='single', pre_number=None, - return new_nr - - -+def delete_snapshot(snapshots_ids=None, config="root"): -+ ''' -+ Deletes an snapshot -+ -+ config -+ Configuration name. (Default: root) -+ -+ snapshots_ids -+ List of the snapshots IDs to be deleted. -+ -+ CLI example: -+ -+ .. code-block:: bash -+ -+ salt '*' snapper.delete_snapshot 54 -+ salt '*' snapper.delete_snapshot config=root 54 -+ salt '*' snapper.delete_snapshot config=root snapshots_ids=[54,55,56] -+ ''' -+ if not snapshots_ids: -+ raise CommandExecutionError('Error: No snapshot ID has been provided') -+ try: -+ current_snapshots_ids = [x['id'] for x in list_snapshots(config)] -+ if not isinstance(snapshots_ids, list): -+ snapshots_ids = [snapshots_ids] -+ if not set(snapshots_ids).issubset(set(current_snapshots_ids)): -+ raise CommandExecutionError( -+ "Error: Snapshots '{0}' not found".format(", ".join( -+ [str(x) for x in set(snapshots_ids).difference( -+ set(current_snapshots_ids))])) -+ ) -+ snapper.DeleteSnapshots(config, snapshots_ids) -+ return {config: {"ids": snapshots_ids, "status": "deleted"}} -+ except dbus.DBusException as exc: -+ raise CommandExecutionError(_dbus_exception_to_reason(exc, locals())) -+ -+ -+def modify_snapshot(snapshot_id=None, -+ description=None, -+ userdata=None, -+ cleanup=None, -+ config="root"): -+ ''' -+ Modify attributes of an existing snapshot. -+ -+ config -+ Configuration name. (Default: root) -+ -+ snapshot_id -+ ID of the snapshot to be modified. -+ -+ cleanup -+ Change the cleanup method of the snapshot. (str) -+ -+ description -+ Change the description of the snapshot. (str) -+ -+ userdata -+ Change the userdata dictionary of the snapshot. (dict) -+ -+ CLI example: -+ -+ .. code-block:: bash -+ -+ salt '*' snapper.modify_snapshot 54 description="my snapshot description" -+ salt '*' snapper.modify_snapshot 54 description="my snapshot description" -+ salt '*' snapper.modify_snapshot 54 userdata='{"foo": "bar"}' -+ salt '*' snapper.modify_snapshot snapshot_id=54 cleanup="number" -+ ''' -+ if not snapshot_id: -+ raise CommandExecutionError('Error: No snapshot ID has been provided') -+ -+ snapshot = get_snapshot(config=config, number=snapshot_id) -+ try: -+ # Updating only the explicitely provided attributes by the user -+ updated_opts = { -+ 'description': description if description is not None else snapshot['description'], -+ 'cleanup': cleanup if cleanup is not None else snapshot['cleanup'], -+ 'userdata': userdata if userdata is not None else snapshot['userdata'], -+ } -+ snapper.SetSnapshot(config, -+ snapshot_id, -+ updated_opts['description'], -+ updated_opts['cleanup'], -+ updated_opts['userdata']) -+ return get_snapshot(config=config, number=snapshot_id) -+ except dbus.DBusException as exc: -+ raise CommandExecutionError(_dbus_exception_to_reason(exc, locals())) -+ -+ - def _get_num_interval(config, num_pre, num_post): - ''' - Returns numerical interval based on optionals num_pre, num_post values -diff --git a/tests/unit/modules/snapper_test.py b/tests/unit/modules/snapper_test.py -index ca985cfd05..a5d9b7686e 100644 ---- a/tests/unit/modules/snapper_test.py -+++ b/tests/unit/modules/snapper_test.py -@@ -202,6 +202,26 @@ class SnapperTestCase(TestCase): - self.assertEqual(snapper.status_to_string(128), ["extended attributes changed"]) - self.assertEqual(snapper.status_to_string(256), ["ACL info changed"]) - -+ @patch('salt.modules.snapper.snapper.CreateConfig', MagicMock()) -+ @patch('salt.modules.snapper.snapper.GetConfig', MagicMock(return_value=DBUS_RET['ListConfigs'][0])) -+ def test_create_config(self): -+ opts = { -+ 'name': 'testconfig', -+ 'subvolume': '/foo/bar/', -+ 'fstype': 'btrfs', -+ 'template': 'mytemplate', -+ 'extra_opts': {"NUMBER_CLEANUP": False}, -+ } -+ with patch('salt.modules.snapper.set_config', MagicMock()) as set_config_mock: -+ self.assertEqual(snapper.create_config(**opts), DBUS_RET['ListConfigs'][0]) -+ set_config_mock.assert_called_with("testconfig", **opts['extra_opts']) -+ -+ with patch('salt.modules.snapper.set_config', MagicMock()) as set_config_mock: -+ del opts['extra_opts'] -+ self.assertEqual(snapper.create_config(**opts), DBUS_RET['ListConfigs'][0]) -+ assert not set_config_mock.called -+ self.assertRaises(CommandExecutionError, snapper.create_config) -+ - @patch('salt.modules.snapper.snapper.CreateSingleSnapshot', MagicMock(return_value=1234)) - @patch('salt.modules.snapper.snapper.CreatePreSnapshot', MagicMock(return_value=1234)) - @patch('salt.modules.snapper.snapper.CreatePostSnapshot', MagicMock(return_value=1234)) -@@ -216,6 +236,36 @@ class SnapperTestCase(TestCase): - } - self.assertEqual(snapper.create_snapshot(**opts), 1234) - -+ @patch('salt.modules.snapper.snapper.DeleteSnapshots', MagicMock()) -+ @patch('salt.modules.snapper.snapper.ListSnapshots', MagicMock(return_value=DBUS_RET['ListSnapshots'])) -+ def test_delete_snapshot_id_success(self): -+ self.assertEqual(snapper.delete_snapshot(snapshots_ids=43), {"root": {"ids": [43], "status": "deleted"}}) -+ self.assertEqual(snapper.delete_snapshot(snapshots_ids=[42, 43]), {"root": {"ids": [42, 43], "status": "deleted"}}) -+ -+ @patch('salt.modules.snapper.snapper.DeleteSnapshots', MagicMock()) -+ @patch('salt.modules.snapper.snapper.ListSnapshots', MagicMock(return_value=DBUS_RET['ListSnapshots'])) -+ def test_delete_snapshot_id_fail(self): -+ self.assertRaises(CommandExecutionError, snapper.delete_snapshot) -+ self.assertRaises(CommandExecutionError, snapper.delete_snapshot, snapshots_ids=1) -+ self.assertRaises(CommandExecutionError, snapper.delete_snapshot, snapshots_ids=[1, 2]) -+ -+ @patch('salt.modules.snapper.snapper.SetSnapshot', MagicMock()) -+ def test_modify_snapshot(self): -+ _ret = { -+ 'userdata': {'userdata2': 'uservalue2'}, -+ 'description': 'UPDATED DESCRIPTION', 'timestamp': 1457006571, -+ 'cleanup': 'number', 'user': 'root', 'type': 'pre', 'id': 42 -+ } -+ _opts = { -+ 'config': 'root', -+ 'snapshot_id': 42, -+ 'cleanup': 'number', -+ 'description': 'UPDATED DESCRIPTION', -+ 'userdata': {'userdata2': 'uservalue2'}, -+ } -+ with patch('salt.modules.snapper.get_snapshot', MagicMock(side_effect=[DBUS_RET['ListSnapshots'][0], _ret])): -+ self.assertDictEqual(snapper.modify_snapshot(**_opts), _ret) -+ - @patch('salt.modules.snapper._get_last_snapshot', MagicMock(return_value={'id': 42})) - def test__get_num_interval(self): - self.assertEqual(snapper._get_num_interval(config=None, num_pre=None, num_post=None), (42, 0)) # pylint: disable=protected-access --- -2.11.0 - - diff --git a/translate-variable-arguments-if-they-contain-hidden-.patch b/translate-variable-arguments-if-they-contain-hidden-.patch new file mode 100644 index 0000000..6a723e6 --- /dev/null +++ b/translate-variable-arguments-if-they-contain-hidden-.patch @@ -0,0 +1,91 @@ +From 7313bf5574a72557a6389b9a991316d0b2c6f848 Mon Sep 17 00:00:00 2001 +From: Michael Calmer +Date: Wed, 1 Mar 2017 15:37:04 +0100 +Subject: [PATCH] translate variable arguments if they contain hidden + keywords (bsc#1025896) + +- includes a test +--- + salt/states/module.py | 30 ++++++++++++++++++++++-------- + tests/unit/states/module_test.py | 14 ++++++++++++++ + 2 files changed, 36 insertions(+), 8 deletions(-) + +diff --git a/salt/states/module.py b/salt/states/module.py +index 686546832f..adc6e12c9d 100644 +--- a/salt/states/module.py ++++ b/salt/states/module.py +@@ -218,16 +218,30 @@ def run(name, **kwargs): + ret['result'] = False + return ret + +- if aspec.varargs and aspec.varargs in kwargs: +- varargs = kwargs.pop(aspec.varargs) ++ if aspec.varargs: ++ if aspec.varargs == 'name': ++ rarg = 'm_name' ++ elif aspec.varargs == 'fun': ++ rarg = 'm_fun' ++ elif aspec.varargs == 'names': ++ rarg = 'm_names' ++ elif aspec.varargs == 'state': ++ rarg = 'm_state' ++ elif aspec.varargs == 'saltenv': ++ rarg = 'm_saltenv' ++ else: ++ rarg = aspec.varargs + +- if not isinstance(varargs, list): +- msg = "'{0}' must be a list." +- ret['comment'] = msg.format(aspec.varargs) +- ret['result'] = False +- return ret ++ if rarg in kwargs: ++ varargs = kwargs.pop(rarg) ++ ++ if not isinstance(varargs, list): ++ msg = "'{0}' must be a list." ++ ret['comment'] = msg.format(aspec.varargs) ++ ret['result'] = False ++ return ret + +- args.extend(varargs) ++ args.extend(varargs) + + nkwargs = {} + if aspec.keywords and aspec.keywords in kwargs: +diff --git a/tests/unit/states/module_test.py b/tests/unit/states/module_test.py +index 0c025e3861..20dda73938 100644 +--- a/tests/unit/states/module_test.py ++++ b/tests/unit/states/module_test.py +@@ -38,6 +38,10 @@ class ModuleStateTest(TestCase): + varargs=None, + keywords=None, + defaults=False) ++ bspec = ArgSpec(args=[], ++ varargs='names', ++ keywords='kwargs', ++ defaults=None) + + def test_module_run_module_not_available(self): + ''' +@@ -69,6 +73,16 @@ class ModuleStateTest(TestCase): + comment = 'The following arguments are missing: world hello' + self.assertEqual(ret['comment'], comment) + ++ @patch('salt.utils.args.get_function_argspec', MagicMock(return_value=bspec)) ++ def test_module_run_hidden_varargs(self): ++ ''' ++ Tests the return of module.run state when hidden varargs are used with ++ wrong type. ++ ''' ++ ret = module.run(CMD, m_names = 'anyname') ++ comment = "'names' must be a list." ++ self.assertEqual(ret['comment'], comment) ++ + + if __name__ == '__main__': + from integration import run_tests +-- +2.11.0 + +