Accepting request 473298 from home:bmaryniuk:branches:systemsmanagement:saltstack

Update to 2016.11.3 version, pkg deps fix

OBS-URL: https://build.opensuse.org/request/show/473298
OBS-URL: https://build.opensuse.org/package/show/systemsmanagement:saltstack/salt?expand=0&rev=87
This commit is contained in:
Klaus Kämpf 2017-03-03 14:58:24 +00:00 committed by Git OBS Bridge
parent 02cd6e0087
commit 1033bb543d
19 changed files with 457 additions and 851 deletions

View File

@ -1,48 +0,0 @@
From 409e1835e0f26295212d1d148d1e7b42cf7dc6b0 Mon Sep 17 00:00:00 2001
From: Michael Calmer <mc@suse.de>
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

View File

@ -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 <mc@suse.de>
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
-<salt.modules.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 <salt.modules.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

View File

@ -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 <malbu@suse.de>
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 <ipv6>, but scp [<ipv6]:/path
self.host = host.strip('[]')
@@ -78,6 +79,7 @@ class Shell(object):
self.mods = mods
self.identities_only = identities_only
self.remote_port_forwards = remote_port_forwards
@ -69,7 +69,7 @@ index 722ec07633..2884a52c1d 100644
def get_error(self, errstr):
'''
@@ -168,6 +170,12 @@ class Shell(object):
@@ -169,6 +171,12 @@ class Shell(object):
ret.append('-o {0} '.format(option))
return ''.join(ret)
@ -82,7 +82,7 @@ index 722ec07633..2884a52c1d 100644
def _copy_id_str_old(self):
'''
Return the string to execute ssh-copy-id
@@ -175,11 +183,12 @@ class Shell(object):
@@ -176,11 +184,12 @@ class Shell(object):
if self.passwd:
# Using single quotes prevents shell expansion and
# passwords containing '$'
@ -96,7 +96,7 @@ index 722ec07633..2884a52c1d 100644
self.user,
self.host)
return None
@@ -192,11 +201,12 @@ class Shell(object):
@@ -193,11 +202,12 @@ class Shell(object):
if self.passwd:
# Using single quotes prevents shell expansion and
# passwords containing '$'
@ -110,7 +110,7 @@ index 722ec07633..2884a52c1d 100644
self.user,
self.host)
return None
@@ -228,6 +238,9 @@ class Shell(object):
@@ -229,6 +239,9 @@ class Shell(object):
if ssh != 'scp' and self.remote_port_forwards:
command.append(' '.join(['-R {0}'.format(item)
for item in self.remote_port_forwards.split(',')]))
@ -121,10 +121,10 @@ index 722ec07633..2884a52c1d 100644
return ' '.join(command)
diff --git a/salt/utils/parsers.py b/salt/utils/parsers.py
index e8f037c3d6..d91c846168 100644
index 6330ed6596..c38506f3c5 100644
--- a/salt/utils/parsers.py
+++ b/salt/utils/parsers.py
@@ -2838,11 +2838,11 @@ class SaltSSHOptionParser(six.with_metaclass(OptionParserMeta,
@@ -2828,11 +2828,11 @@ class SaltSSHOptionParser(six.with_metaclass(OptionParserMeta,
help='Pass a JID to be used instead of generating one.'
)
@ -140,7 +140,7 @@ index e8f037c3d6..d91c846168 100644
'--remote-port-forwards',
dest='ssh_remote_port_forwards',
help='Setup remote port forwarding using the same syntax as with '
@@ -2850,7 +2850,15 @@ class SaltSSHOptionParser(six.with_metaclass(OptionParserMeta,
@@ -2840,7 +2840,15 @@ class SaltSSHOptionParser(six.with_metaclass(OptionParserMeta,
'forwarding definitions will be translated into multiple '
'-R parameters.'
)

View File

@ -1,48 +0,0 @@
From 3f950292cf9a3b6d6697e65f986e8559bc396cf2 Mon Sep 17 00:00:00 2001
From: Michael Calmer <mc@suse.de>
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
-<salt.modules.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 <salt.modules.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

View File

@ -1,32 +0,0 @@
From 64ddef78a040dde7e547518331dc9e8a98ceb42f Mon Sep 17 00:00:00 2001
From: Bo Maryniuk <bo@suse.de>
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

View File

@ -0,0 +1,26 @@
From 036be5f7300bbf6c5ef3967b5cc935fd678cd1e1 Mon Sep 17 00:00:00 2001
From: Michael Calmer <mc@suse.de>
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

View File

@ -1,26 +0,0 @@
From 7c459f38d43ef31ededce703fbfb432af1fdcee6 Mon Sep 17 00:00:00 2001
From: Michael Calmer <mc@suse.de>
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

View File

@ -1,94 +0,0 @@
From dadd20bd0db0289ac4ad9f322f03de686b24c5a7 Mon Sep 17 00:00:00 2001
From: Bo Maryniuk <bo@suse.de>
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

View File

@ -0,0 +1,196 @@
From 89fd1a83d282a10728077a08466627271a052733 Mon Sep 17 00:00:00 2001
From: Erik Johnson <palehose@gmail.com>
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

View File

@ -1,34 +0,0 @@
From f45b229c9fea4be349484d8d041c735fa78500b5 Mon Sep 17 00:00:00 2001
From: Frantisek Kobzik <fkobzik@suse.de>
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

View File

@ -1,170 +0,0 @@
From 1c22c72afce15585070829054e3460a61947e256 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Pablo=20Su=C3=A1rez=20Hern=C3=A1ndez?=
<psuarezhernandez@suse.com>
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

View File

@ -1,26 +0,0 @@
From 48a8dd97be9ddef45f249d530b9c7d1a593e5ac0 Mon Sep 17 00:00:00 2001
From: Bo Maryniuk <bo@suse.de>
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

View File

@ -1,28 +0,0 @@
From a74360a87e11bbcd65d253426c930769f83361e4 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Pablo=20Su=C3=A1rez=20Hern=C3=A1ndez?=
<psuarezhernandez@suse.com>
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

View File

@ -1,3 +0,0 @@
version https://git-lfs.github.com/spec/v1
oid sha256:f5c3d3cf4293d5b80a93790c76dec61421991c9c54222abd7327b3437ad13a43
size 9114042

3
salt-2016.11.3.tar.gz Normal file
View File

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:9d5849f38a858288ebc6ef790ced86ae724e61b06e3ee27e6cecf3f6c1ecbc51
size 9163351

View File

@ -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

View File

@ -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

View File

@ -1,275 +0,0 @@
From 678de7117211fc359c9aa7e29f6c2fecf0944b08 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Pablo=20Su=C3=A1rez=20Hern=C3=A1ndez?=
<psuarezhernandez@suse.com>
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

View File

@ -0,0 +1,91 @@
From 7313bf5574a72557a6389b9a991316d0b2c6f848 Mon Sep 17 00:00:00 2001
From: Michael Calmer <mc@suse.de>
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