From cca2a806c999cbf4ad299c137ae5e728e0b45dd5 Mon Sep 17 00:00:00 2001 From: zer0def Date: Mon, 16 Apr 2018 21:41:35 +0200 Subject: [PATCH 01/50] Made interaction with [DEFAULT] section in ConfigParser as sane as upstream permits. --- salt/serializers/configparser.py | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/salt/serializers/configparser.py b/salt/serializers/configparser.py index 3df65e93f1..14be3fdc1e 100644 --- a/salt/serializers/configparser.py +++ b/salt/serializers/configparser.py @@ -85,15 +85,28 @@ def serialize(obj, **options): raise SerializationError(error) -def _read_dict(configparser, dictionary): +def _is_defaultsect(section_name): + if six.PY3: + return section_name == configparser.DEFAULTSECT + else: # in py2 the check is done against lowercased section name + return section_name.upper() == configparser.DEFAULTSECT + + +def _read_dict(cp, dictionary): ''' Cribbed from python3's ConfigParser.read_dict function. ''' for section, keys in dictionary.items(): section = str(section) - configparser.add_section(section) + + if _is_defaultsect(section): + if six.PY2: + section = configparser.DEFAULTSECT + else: + cp.add_section(section) + for key, value in keys.items(): - key = configparser.optionxform(str(key)) + key = cp.optionxform(str(key)) if value is not None: value = str(value) - configparser.set(section, key, value) + cp.set(section, key, value) From 10bd63a9769c4ba3a1bf471e35b88c0974ba009d Mon Sep 17 00:00:00 2001 From: Ch3LL Date: Mon, 30 Apr 2018 14:44:34 -0400 Subject: [PATCH 02/50] Skip status.diskusage integration tests on macsox --- tests/integration/modules/test_status.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/integration/modules/test_status.py b/tests/integration/modules/test_status.py index 10eb5008a0..87afcfe220 100644 --- a/tests/integration/modules/test_status.py +++ b/tests/integration/modules/test_status.py @@ -44,6 +44,7 @@ class StatusModuleTest(ModuleCase): ret = self.run_function('status.saltmem') self.assertTrue(isinstance(ret, int)) + @skipIf(salt.utils.is_darwin(), 'status.diskusage not currently supported on macosx') def test_status_diskusage(self): ''' status.diskusage From 1a7ffb4e0d581315911ccb2161b1ce07de8487c5 Mon Sep 17 00:00:00 2001 From: Ch3LL Date: Tue, 1 May 2018 13:11:23 -0400 Subject: [PATCH 03/50] return error if diskusage not available --- salt/modules/status.py | 2 +- tests/integration/modules/test_status.py | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/salt/modules/status.py b/salt/modules/status.py index b5ece1d7d2..6e8aae1052 100644 --- a/salt/modules/status.py +++ b/salt/modules/status.py @@ -939,7 +939,7 @@ def diskusage(*args): elif __grains__['kernel'] in ('FreeBSD', 'SunOS'): ifile = __salt__['cmd.run']('mount -p').splitlines() else: - ifile = [] + raise CommandExecutionError('status.diskusage not yet supported on this platform') for line in ifile: comps = line.split() diff --git a/tests/integration/modules/test_status.py b/tests/integration/modules/test_status.py index 87afcfe220..59f1a4ba78 100644 --- a/tests/integration/modules/test_status.py +++ b/tests/integration/modules/test_status.py @@ -44,13 +44,14 @@ class StatusModuleTest(ModuleCase): ret = self.run_function('status.saltmem') self.assertTrue(isinstance(ret, int)) - @skipIf(salt.utils.is_darwin(), 'status.diskusage not currently supported on macosx') def test_status_diskusage(self): ''' status.diskusage ''' ret = self.run_function('status.diskusage') - if salt.utils.is_windows(): + if salt.utils.is_darwin(): + self.assertIn('not yet supported on this platform', ret) + elif salt.utils.is_windows(): self.assertTrue(isinstance(ret['percent'], float)) else: self.assertIn('total', str(ret)) From a1e9fe00fd59f47ae021bb346940b98873cea4e8 Mon Sep 17 00:00:00 2001 From: Erik Johnson Date: Wed, 2 May 2018 20:28:45 -0500 Subject: [PATCH 04/50] Skip trying to render a template for a nonexistant SLS file This skips an unnecssary call to compile_template, and also prevents a confusing error message: "Template was specified incorrectly: False", for cases when an SLS target specified in a top file does not exist. --- salt/state.py | 64 ++++++++++++++++++++++++++------------------------- 1 file changed, 33 insertions(+), 31 deletions(-) diff --git a/salt/state.py b/salt/state.py index c66ee4e462..b9f176aa46 100644 --- a/salt/state.py +++ b/salt/state.py @@ -3255,43 +3255,45 @@ class BaseHighState(object): 'Specified SLS {0} on local filesystem cannot ' 'be found.'.format(sls) ) + state = None if not fn_: errors.append( 'Specified SLS {0} in saltenv {1} is not ' 'available on the salt master or through a configured ' 'fileserver'.format(sls, saltenv) ) - state = None - try: - state = compile_template(fn_, - self.state.rend, - self.state.opts['renderer'], - self.state.opts['renderer_blacklist'], - self.state.opts['renderer_whitelist'], - saltenv, - sls, - rendered_sls=mods - ) - except SaltRenderError as exc: - msg = 'Rendering SLS \'{0}:{1}\' failed: {2}'.format( - saltenv, sls, exc - ) - log.critical(msg) - errors.append(msg) - except Exception as exc: - msg = 'Rendering SLS {0} failed, render error: {1}'.format( - sls, exc - ) - log.critical( - msg, - # Show the traceback if the debug logging level is enabled - exc_info_on_loglevel=logging.DEBUG - ) - errors.append('{0}\n{1}'.format(msg, traceback.format_exc())) - try: - mods.add('{0}:{1}'.format(saltenv, sls)) - except AttributeError: - pass + else: + try: + state = compile_template(fn_, + self.state.rend, + self.state.opts['renderer'], + self.state.opts['renderer_blacklist'], + self.state.opts['renderer_whitelist'], + saltenv, + sls, + rendered_sls=mods + ) + except SaltRenderError as exc: + msg = 'Rendering SLS \'{0}:{1}\' failed: {2}'.format( + saltenv, sls, exc + ) + log.critical(msg) + errors.append(msg) + except Exception as exc: + msg = 'Rendering SLS {0} failed, render error: {1}'.format( + sls, exc + ) + log.critical( + msg, + # Show the traceback if the debug logging level is enabled + exc_info_on_loglevel=logging.DEBUG + ) + errors.append('{0}\n{1}'.format(msg, traceback.format_exc())) + try: + mods.add('{0}:{1}'.format(saltenv, sls)) + except AttributeError: + pass + if state: if not isinstance(state, dict): errors.append( From d74057224dbc720393d31980ba46458fb683054e Mon Sep 17 00:00:00 2001 From: Alex Austin Date: Sun, 29 Apr 2018 23:06:59 -0500 Subject: [PATCH 05/50] Un-normalize os_family in pkgrepo state The __grains__['os'].lower() code was added in e7fb3095ceeecc1e5507754515a34e2d498a6e75, but I don't know why. I hope this "fix" doesn't break anything. --- salt/states/pkgrepo.py | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/salt/states/pkgrepo.py b/salt/states/pkgrepo.py index e38d44dd30..17398ba1b8 100644 --- a/salt/states/pkgrepo.py +++ b/salt/states/pkgrepo.py @@ -319,7 +319,6 @@ def managed(name, ppa=None, **kwargs): enabled = True repo = name - os_family = __grains__['os_family'].lower() if __grains__['os'] in ('Ubuntu', 'Mint'): if ppa is not None: # overload the name/repo value for PPAs cleanly @@ -333,7 +332,7 @@ def managed(name, ppa=None, **kwargs): if enabled is not None \ else salt.utils.is_true(disabled) - elif os_family in ('redhat', 'suse'): + elif __grains__['os_family'] in ('RedHat', 'Suse'): if 'humanname' in kwargs: kwargs['name'] = kwargs.pop('humanname') if 'name' not in kwargs: @@ -344,7 +343,7 @@ def managed(name, ppa=None, **kwargs): if disabled is not None \ else salt.utils.is_true(enabled) - elif os_family == 'nilinuxrt': + elif __grains__['os_family'] in ('NILinuxRT',): # opkg is the pkg virtual kwargs['enabled'] = not salt.utils.is_true(disabled) \ if disabled is not None \ @@ -373,7 +372,7 @@ def managed(name, ppa=None, **kwargs): else: sanitizedkwargs = kwargs - if os_family == 'debian': + if __grains__['os_family'] == 'Debian': repo = salt.utils.pkg.deb.strip_uri(repo) if pre: @@ -387,7 +386,7 @@ def managed(name, ppa=None, **kwargs): # not explicitly set, so we don't need to update the repo # if it's desired to be enabled and the 'enabled' key is # missing from the repo definition - if os_family == 'redhat': + if __grains__['os_family'] == 'RedHat': if not salt.utils.is_true(sanitizedkwargs[kwarg]): break else: @@ -397,7 +396,7 @@ def managed(name, ppa=None, **kwargs): elif kwarg == 'comps': if sorted(sanitizedkwargs[kwarg]) != sorted(pre[kwarg]): break - elif kwarg == 'line' and os_family == 'debian': + elif kwarg == 'line' and __grains__['os_family'] == 'Debian': # split the line and sort everything after the URL sanitizedsplit = sanitizedkwargs[kwarg].split() sanitizedsplit[3:] = sorted(sanitizedsplit[3:]) @@ -412,14 +411,14 @@ def managed(name, ppa=None, **kwargs): salt.utils.pkg.deb.combine_comments(kwargs['comments']) if pre_comments != post_comments: break - elif kwarg == 'comments' and os_family == 'redhat': + elif kwarg == 'comments' and __grains__['os_family'] == 'RedHat': precomments = salt.utils.pkg.rpm.combine_comments(pre[kwarg]) kwargcomments = salt.utils.pkg.rpm.combine_comments( sanitizedkwargs[kwarg]) if precomments != kwargcomments: break else: - if os_family in ('redhat', 'suse') \ + if __grains__['os_family'] in ('RedHat', 'Suse') \ and any(isinstance(x, bool) for x in (sanitizedkwargs[kwarg], pre[kwarg])): # This check disambiguates 1/0 from True/False @@ -450,7 +449,7 @@ def managed(name, ppa=None, **kwargs): pass try: - if os_family == 'debian': + if __grains__['os_family'] == 'Debian': __salt__['pkg.mod_repo'](repo, saltenv=__env__, **kwargs) else: __salt__['pkg.mod_repo'](repo, **kwargs) From 139360c55fa16e71655f46a6e288297894dd0557 Mon Sep 17 00:00:00 2001 From: Alex Austin Date: Wed, 25 Apr 2018 15:24:52 -0500 Subject: [PATCH 06/50] Add Poky to OS Information Grains --- salt/grains/core.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/salt/grains/core.py b/salt/grains/core.py index da4ce355c5..14b637a0b7 100644 --- a/salt/grains/core.py +++ b/salt/grains/core.py @@ -1106,6 +1106,7 @@ _OS_NAME_MAP = { 'synology': 'Synology', 'nilrt': 'NILinuxRT', 'nilrt-xfce': 'NILinuxRT-XFCE', + 'poky': 'Poky', 'manjaro': 'Manjaro', 'manjarolin': 'Manjaro', 'antergos': 'Antergos', @@ -1647,7 +1648,7 @@ def os_data(): osarch = __salt__['cmd.run']('dpkg --print-architecture').strip() elif grains.get('os_family') == 'RedHat': osarch = __salt__['cmd.run']('rpm --eval %{_host_cpu}').strip() - elif grains.get('os_family') == 'NILinuxRT': + elif grains.get('os_family') in ('NILinuxRT', 'Poky'): archinfo = {} for line in __salt__['cmd.run']('opkg print-architecture').splitlines(): if line.startswith('arch'): From 7a58fd157eb6ddeb4627ff719cb082550dbadf80 Mon Sep 17 00:00:00 2001 From: Alex Austin Date: Wed, 25 Apr 2018 15:27:25 -0500 Subject: [PATCH 07/50] Enable opkg on non-NILinuxRT systems --- salt/modules/opkg.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/salt/modules/opkg.py b/salt/modules/opkg.py index b3c9103bc0..7223c7778e 100644 --- a/salt/modules/opkg.py +++ b/salt/modules/opkg.py @@ -56,9 +56,9 @@ def __virtual__(): ''' Confirm this module is on a nilrt based system ''' - if __grains__.get('os_family', False) == 'NILinuxRT': + if os.path.isdir(OPKG_CONFDIR): return __virtualname__ - return (False, "Module opkg only works on nilrt based systems") + return False, "Module opkg only works on OpenEmbedded based systems" def latest_version(*names, **kwargs): From cb674fb1cb5d861582baa89b230e6e31dab11be3 Mon Sep 17 00:00:00 2001 From: Alex Austin Date: Wed, 25 Apr 2018 15:29:01 -0500 Subject: [PATCH 08/50] Enable opkg as pkgrepo handler on Poky --- salt/states/pkgrepo.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/salt/states/pkgrepo.py b/salt/states/pkgrepo.py index 17398ba1b8..5e5c3b257e 100644 --- a/salt/states/pkgrepo.py +++ b/salt/states/pkgrepo.py @@ -343,7 +343,7 @@ def managed(name, ppa=None, **kwargs): if disabled is not None \ else salt.utils.is_true(enabled) - elif __grains__['os_family'] in ('NILinuxRT',): + elif __grains__['os_family'] in ('NILinuxRT', 'Poky'): # opkg is the pkg virtual kwargs['enabled'] = not salt.utils.is_true(disabled) \ if disabled is not None \ From 9f7a9ebebd1237ebbabd4df42f29e7f9706b5272 Mon Sep 17 00:00:00 2001 From: Erik Johnson Date: Fri, 4 May 2018 14:57:41 -0500 Subject: [PATCH 09/50] Rename pip state test modules to match naming convention This makes the naming match the naming convention used throughout the test suite and will make the changes in https://github.com/saltstack/salt/pull/47337 work better. --- tests/integration/states/{test_pip.py => test_pip_state.py} | 0 tests/unit/states/{test_pip.py => test_pip_state.py} | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename tests/integration/states/{test_pip.py => test_pip_state.py} (100%) rename tests/unit/states/{test_pip.py => test_pip_state.py} (100%) diff --git a/tests/integration/states/test_pip.py b/tests/integration/states/test_pip_state.py similarity index 100% rename from tests/integration/states/test_pip.py rename to tests/integration/states/test_pip_state.py diff --git a/tests/unit/states/test_pip.py b/tests/unit/states/test_pip_state.py similarity index 100% rename from tests/unit/states/test_pip.py rename to tests/unit/states/test_pip_state.py From d22ed7dffadeee1c499c3cef9672a5231367957a Mon Sep 17 00:00:00 2001 From: Banio Carpenter Date: Fri, 4 May 2018 15:11:56 -0500 Subject: [PATCH 10/50] added handling for the aws error ConflictingDomainExists --- salt/modules/boto3_route53.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/salt/modules/boto3_route53.py b/salt/modules/boto3_route53.py index db194c1aae..0f4e5cb554 100644 --- a/salt/modules/boto3_route53.py +++ b/salt/modules/boto3_route53.py @@ -544,6 +544,10 @@ def associate_vpc_with_hosted_zone(HostedZoneId=None, Name=None, VPCId=None, r = conn.associate_vpc_with_hosted_zone(**args) return _wait_for_sync(r['ChangeInfo']['Id'], conn) except ClientError as e: + if e.response.get('Error', {}).get('Code') == 'ConflictingDomainExists': + log.debug('VPC Association already exists.') + # return True since the current state is the desired one + return True if tries and e.response.get('Error', {}).get('Code') == 'Throttling': log.debug('Throttled by AWS API.') time.sleep(3) From fec1233dc43282e9fc62acb288626df2e32b60ea Mon Sep 17 00:00:00 2001 From: Daniel A Wozniak Date: Sat, 5 May 2018 21:00:55 +0000 Subject: [PATCH 11/50] Add support for windows timeout to run_salt The run_salt function needs to support timeout on windows for the full test suite to run. --- tests/support/case.py | 39 ++++++++++++++++++++++++++++++++++----- 1 file changed, 34 insertions(+), 5 deletions(-) diff --git a/tests/support/case.py b/tests/support/case.py index b809571441..bdbced2e10 100644 --- a/tests/support/case.py +++ b/tests/support/case.py @@ -36,6 +36,8 @@ from tests.support.mixins import AdaptedConfigurationTestCaseMixin, SaltClientTe from tests.support.paths import ScriptPathMixin, INTEGRATION_TEST_DIR, CODE_DIR, PYEXEC, SCRIPT_DIR # Import 3rd-party libs +import psutil +import salt.utils import salt.ext.six as six from salt.ext.six.moves import cStringIO # pylint: disable=import-error @@ -67,6 +69,26 @@ SCRIPT_TEMPLATES = { log = logging.getLogger(__name__) +def kill_process_tree(pid, sig=signal.SIGTERM, include_parent=True, timeout=None, + on_terminate=None): + ''' + Kill a process tree (including grandchildren) with signal "sig" and return + a (gone, still_alive) tuple. "on_terminate", if specified, is a callabck + function which is called as soon as a child terminates. + ''' + if pid == os.getpid(): + raise RuntimeError("I refuse to kill myself") + parent = psutil.Process(pid) + children = parent.children(recursive=True) + if include_parent: + children.append(parent) + for p in children: + p.send_signal(sig) + gone, alive = psutil.wait_procs(children, timeout=timeout, + callback=on_terminate) + return (gone, alive) + + class ShellTestCase(TestCase, AdaptedConfigurationTestCaseMixin): ''' Execute a test for a shell command @@ -276,9 +298,6 @@ class ShellTestCase(TestCase, AdaptedConfigurationTestCaseMixin): popen_kwargs['preexec_fn'] = detach_from_parent_group - elif sys.platform.lower().startswith('win') and timeout is not None: - raise RuntimeError('Timeout is not supported under windows') - process = subprocess.Popen(cmd, **popen_kwargs) if timeout is not None: @@ -292,13 +311,23 @@ class ShellTestCase(TestCase, AdaptedConfigurationTestCaseMixin): # Kill the process group since sending the term signal # would only terminate the shell, not the command # executed in the shell - os.killpg(os.getpgid(process.pid), signal.SIGINT) + if salt.utils.is_windows(): + _, alive = kill_process_tree(process.pid) + if alive: + log.error("Child processes still alive: %s", alive) + else: + os.killpg(os.getpgid(process.pid), signal.SIGINT) term_sent = True continue try: # As a last resort, kill the process group - os.killpg(os.getpgid(process.pid), signal.SIGKILL) + if salt.utils.is_windows(): + _, alive = kill_process_tree(process.pid) + if alive: + log.error("Child processes still alive: %s", alive) + else: + os.killpg(os.getpgid(process.pid), signal.SIGINT) except OSError as exc: if exc.errno != errno.ESRCH: # If errno is not "no such process", raise From c6697b9f16b06b5f3a1b6f36f93275965ecec444 Mon Sep 17 00:00:00 2001 From: Daniel A Wozniak Date: Sun, 6 May 2018 16:43:21 +0000 Subject: [PATCH 12/50] Move kill process tree and re-use it --- tests/integration/utils/testprogram.py | 30 ++++++++++++++++---------- tests/support/case.py | 29 +++++-------------------- tests/support/helpers.py | 20 +++++++++++++++++ 3 files changed, 44 insertions(+), 35 deletions(-) diff --git a/tests/integration/utils/testprogram.py b/tests/integration/utils/testprogram.py index ee761ad27e..e00772c8f8 100644 --- a/tests/integration/utils/testprogram.py +++ b/tests/integration/utils/testprogram.py @@ -29,6 +29,7 @@ import salt.ext.six as six from salt.ext.six.moves import range # pylint: disable=import-error,redefined-builtin from tests.support.unit import TestCase +from tests.support.helpers import win32_kill_process_tree from tests.support.paths import CODE_DIR from tests.support.processes import terminate_process, terminate_process_list @@ -414,9 +415,6 @@ class TestProgram(six.with_metaclass(TestProgramMeta, object)): popen_kwargs['preexec_fn'] = detach_from_parent_group - elif sys.platform.lower().startswith('win') and timeout is not None: - raise RuntimeError('Timeout is not supported under windows') - self.argv = [self.program] self.argv.extend(args) log.debug('TestProgram.run: %s Environment %s', self.argv, env_delta) @@ -431,16 +429,26 @@ class TestProgram(six.with_metaclass(TestProgramMeta, object)): if datetime.now() > stop_at: if term_sent is False: - # Kill the process group since sending the term signal - # would only terminate the shell, not the command - # executed in the shell - os.killpg(os.getpgid(process.pid), signal.SIGINT) - term_sent = True - continue + if salt.utils.is_windows(): + _, alive = win32_kill_process_tree(process.pid) + if alive: + log.error("Child processes still alive: %s", alive) + else: + # Kill the process group since sending the term signal + # would only terminate the shell, not the command + # executed in the shell + os.killpg(os.getpgid(process.pid), signal.SIGINT) + term_sent = True + continue try: - # As a last resort, kill the process group - os.killpg(os.getpgid(process.pid), signal.SIGKILL) + if salt.utils.is_windows(): + _, alive = win32_kill_process_tree(process.pid) + if alive: + log.error("Child processes still alive: %s", alive) + else: + # As a last resort, kill the process group + os.killpg(os.getpgid(process.pid), signal.SIGKILL) process.wait() except OSError as exc: if exc.errno != errno.ESRCH: diff --git a/tests/support/case.py b/tests/support/case.py index bdbced2e10..376842f2fc 100644 --- a/tests/support/case.py +++ b/tests/support/case.py @@ -30,13 +30,14 @@ from datetime import datetime, timedelta # Import salt testing libs from tests.support.unit import TestCase -from tests.support.helpers import RedirectStdStreams, requires_sshd_server +from tests.support.helpers import ( + RedirectStdStreams, requires_sshd_server, win32_kill_process_tree +) from tests.support.runtests import RUNTIME_VARS from tests.support.mixins import AdaptedConfigurationTestCaseMixin, SaltClientTestCaseMixin from tests.support.paths import ScriptPathMixin, INTEGRATION_TEST_DIR, CODE_DIR, PYEXEC, SCRIPT_DIR # Import 3rd-party libs -import psutil import salt.utils import salt.ext.six as six from salt.ext.six.moves import cStringIO # pylint: disable=import-error @@ -69,26 +70,6 @@ SCRIPT_TEMPLATES = { log = logging.getLogger(__name__) -def kill_process_tree(pid, sig=signal.SIGTERM, include_parent=True, timeout=None, - on_terminate=None): - ''' - Kill a process tree (including grandchildren) with signal "sig" and return - a (gone, still_alive) tuple. "on_terminate", if specified, is a callabck - function which is called as soon as a child terminates. - ''' - if pid == os.getpid(): - raise RuntimeError("I refuse to kill myself") - parent = psutil.Process(pid) - children = parent.children(recursive=True) - if include_parent: - children.append(parent) - for p in children: - p.send_signal(sig) - gone, alive = psutil.wait_procs(children, timeout=timeout, - callback=on_terminate) - return (gone, alive) - - class ShellTestCase(TestCase, AdaptedConfigurationTestCaseMixin): ''' Execute a test for a shell command @@ -312,7 +293,7 @@ class ShellTestCase(TestCase, AdaptedConfigurationTestCaseMixin): # would only terminate the shell, not the command # executed in the shell if salt.utils.is_windows(): - _, alive = kill_process_tree(process.pid) + _, alive = win32_kill_process_tree(process.pid) if alive: log.error("Child processes still alive: %s", alive) else: @@ -323,7 +304,7 @@ class ShellTestCase(TestCase, AdaptedConfigurationTestCaseMixin): try: # As a last resort, kill the process group if salt.utils.is_windows(): - _, alive = kill_process_tree(process.pid) + _, alive = win32_kill_process_tree(process.pid) if alive: log.error("Child processes still alive: %s", alive) else: diff --git a/tests/support/helpers.py b/tests/support/helpers.py index f97d9390a1..6866c99730 100644 --- a/tests/support/helpers.py +++ b/tests/support/helpers.py @@ -1532,3 +1532,23 @@ class Webserver(object): ''' self.ioloop.add_callback(self.ioloop.stop) self.server_thread.join() + + +def win32_kill_process_tree(pid, sig=signal.SIGTERM, include_parent=True, + timeout=None, on_terminate=None): + ''' + Kill a process tree (including grandchildren) with signal "sig" and return + a (gone, still_alive) tuple. "on_terminate", if specified, is a callabck + function which is called as soon as a child terminates. + ''' + if pid == os.getpid(): + raise RuntimeError("I refuse to kill myself") + parent = psutil.Process(pid) + children = parent.children(recursive=True) + if include_parent: + children.append(parent) + for p in children: + p.send_signal(sig) + gone, alive = psutil.wait_procs(children, timeout=timeout, + callback=on_terminate) + return (gone, alive) From d1fcb40d1c7792e7610dfc14c80e22ae48bc5b9f Mon Sep 17 00:00:00 2001 From: "Daniel A. Wozniak" Date: Sun, 6 May 2018 14:45:04 -0700 Subject: [PATCH 13/50] Raise proper invocation errors --- salt/modules/win_dsc.py | 34 +++++++++++++++++++--------------- 1 file changed, 19 insertions(+), 15 deletions(-) diff --git a/salt/modules/win_dsc.py b/salt/modules/win_dsc.py index eec2eed952..f137053650 100644 --- a/salt/modules/win_dsc.py +++ b/salt/modules/win_dsc.py @@ -718,23 +718,24 @@ def set_lcm_config(config_mode=None, 'ApplyAndAutoCorrect'): error = 'config_mode must be one of ApplyOnly, ApplyAndMonitor, ' \ 'or ApplyAndAutoCorrect. Passed {0}'.format(config_mode) - SaltInvocationError(error) - return error + raise SaltInvocationError(error) cmd += ' ConfigurationMode = "{0}";'.format(config_mode) if config_mode_freq: if not isinstance(config_mode_freq, int): - SaltInvocationError('config_mode_freq must be an integer') - return 'config_mode_freq must be an integer. Passed {0}'.\ - format(config_mode_freq) + error = 'config_mode_freq must be an integer. Passed {0}'.format( + config_mode_freq + ) + raise SaltInvocationError(error) cmd += ' ConfigurationModeFrequencyMins = {0};'.format(config_mode_freq) if refresh_mode: if refresh_mode not in ('Disabled', 'Push', 'Pull'): - SaltInvocationError('refresh_mode must be one of Disabled, Push, ' - 'or Pull') + raise SaltInvocationError( + 'refresh_mode must be one of Disabled, Push, or Pull' + ) cmd += ' RefreshMode = "{0}";'.format(refresh_mode) if refresh_freq: if not isinstance(refresh_freq, int): - SaltInvocationError('refresh_freq must be an integer') + raise SaltInvocationError('refresh_freq must be an integer') cmd += ' RefreshFrequencyMins = {0};'.format(refresh_freq) if reboot_if_needed is not None: if not isinstance(reboot_if_needed, bool): @@ -747,8 +748,10 @@ def set_lcm_config(config_mode=None, if action_after_reboot: if action_after_reboot not in ('ContinueConfiguration', 'StopConfiguration'): - SaltInvocationError('action_after_reboot must be one of ' - 'ContinueConfiguration or StopConfiguration') + raise SaltInvocationError( + 'action_after_reboot must be one of ' + 'ContinueConfiguration or StopConfiguration' + ) cmd += ' ActionAfterReboot = "{0}"'.format(action_after_reboot) if certificate_id is not None: if certificate_id == '': @@ -760,7 +763,7 @@ def set_lcm_config(config_mode=None, cmd += ' ConfigurationID = "{0}";'.format(configuration_id) if allow_module_overwrite is not None: if not isinstance(allow_module_overwrite, bool): - SaltInvocationError('allow_module_overwrite must be a boolean value') + raise SaltInvocationError('allow_module_overwrite must be a boolean value') if allow_module_overwrite: allow_module_overwrite = '$true' else: @@ -770,13 +773,14 @@ def set_lcm_config(config_mode=None, if debug_mode is None: debug_mode = 'None' if debug_mode not in ('None', 'ForceModuleImport', 'All'): - SaltInvocationError('debug_mode must be one of None, ' - 'ForceModuleImport, ResourceScriptBreakAll, or ' - 'All') + raise SaltInvocationError( + 'debug_mode must be one of None, ForceModuleImport, ' + 'ResourceScriptBreakAll, or All' + ) cmd += ' DebugMode = "{0}";'.format(debug_mode) if status_retention_days: if not isinstance(status_retention_days, int): - SaltInvocationError('status_retention_days must be an integer') + raise SaltInvocationError('status_retention_days must be an integer') cmd += ' StatusRetentionTimeInDays = {0};'.format(status_retention_days) cmd += ' }}};' cmd += r'SaltConfig -OutputPath "{0}\SaltConfig"'.format(temp_dir) From 1a87e7455f860e5515d82d383442b1c047381c74 Mon Sep 17 00:00:00 2001 From: Daniel Wallace Date: Mon, 7 May 2018 08:31:54 -0500 Subject: [PATCH 14/50] allow pulling the mysql_query.run_file to pull from the fileserver --- salt/states/mysql_query.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/salt/states/mysql_query.py b/salt/states/mysql_query.py index b2ea6c1c3c..a558b7c46e 100644 --- a/salt/states/mysql_query.py +++ b/salt/states/mysql_query.py @@ -56,10 +56,13 @@ def run_file(name, grain=None, key=None, overwrite=True, + saltenv=None, **connection_args): ''' Execute an arbitrary query on the specified database + .. versionadded:: 2017.7.0 + name Used only as an ID @@ -84,13 +87,17 @@ def run_file(name, overwrite: The file or grain will be overwritten if it already exists (default) - .. versionadded:: 2017.7.0 + saltenv: + The saltenv to pull the query_file from ''' ret = {'name': name, 'changes': {}, 'result': True, 'comment': 'Database {0} is already present'.format(database)} + if any([query_file.startswith(proto) for proto in ['http://', 'https://', 'salt://', 's3://', 'swift://']]): + query_file = __salt__['cp.cache_file'](query_file, saltenv=saltenv or __env__) + if not os.path.exists(query_file): ret['comment'] = 'File {0} does not exist'.format(query_file) ret['result'] = False From 2605ff8712605dbd1576578099facb7a93f23443 Mon Sep 17 00:00:00 2001 From: "Daniel A. Wozniak" Date: Mon, 7 May 2018 13:32:56 -0700 Subject: [PATCH 15/50] Gracefully handle blank lines in whitelist.txt --- tests/runtests.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/runtests.py b/tests/runtests.py index a609f796bb..dcc2e57828 100755 --- a/tests/runtests.py +++ b/tests/runtests.py @@ -698,6 +698,9 @@ class SaltTestsuiteParser(SaltCoverageTestingParser): with TestDaemon(self): if self.options.name: for name in self.options.name: + name = name.strip() + if not name: + continue if os.path.isfile(name): if not name.endswith('.py'): continue From b3289e5a1c8a6ea480794cb7025049915c0988ce Mon Sep 17 00:00:00 2001 From: "Daniel A. Wozniak" Date: Mon, 7 May 2018 14:40:15 -0700 Subject: [PATCH 16/50] Fix test file name --- tests/whitelist.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/whitelist.txt b/tests/whitelist.txt index 18395bad2a..b7cb036881 100644 --- a/tests/whitelist.txt +++ b/tests/whitelist.txt @@ -37,7 +37,7 @@ integration.runners.test_jobs integration.runners.test_salt integration.sdb.test_env integration.states.test_host -integration.states.test_pip +integration.states.test_pip_state integration.states.test_renderers integration.utils.testprogram integration.wheel.test_client From 4aea7ca571af4797e27df4ea83c7739157768fd8 Mon Sep 17 00:00:00 2001 From: "Daniel A. Wozniak" Date: Mon, 7 May 2018 14:41:20 -0700 Subject: [PATCH 17/50] Update doc string --- tests/integration/states/test_pip_state.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/integration/states/test_pip_state.py b/tests/integration/states/test_pip_state.py index 5c5422c196..24d286cfd6 100644 --- a/tests/integration/states/test_pip_state.py +++ b/tests/integration/states/test_pip_state.py @@ -3,7 +3,7 @@ :codeauthor: :email:`Pedro Algarvio (pedro@algarvio.me)` - tests.integration.states.pip + tests.integration.states.pip_state ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ''' From 98e8ffeba48661b19c2941c245e4f8e82bf64759 Mon Sep 17 00:00:00 2001 From: Erik Johnson Date: Tue, 8 May 2018 08:13:25 -0500 Subject: [PATCH 18/50] Fix/clarify some of the pip module documentation --- salt/modules/pip.py | 97 ++++++++++++++++++++------------------------- 1 file changed, 43 insertions(+), 54 deletions(-) diff --git a/salt/modules/pip.py b/salt/modules/pip.py index 3be06d0fbe..b9661bda41 100644 --- a/salt/modules/pip.py +++ b/salt/modules/pip.py @@ -452,13 +452,10 @@ def install(pkgs=None, # pylint: disable=R0912,R0913,R0914 Path to requirements bin_env - Path to pip bin or path to virtualenv. If doing a system install, - and want to use a specific pip bin (pip-2.7, pip-2.6, etc..) just - specify the pip bin you want. - - .. note:: - If installing into a virtualenv, just use the path to the - virtualenv (e.g. ``/home/code/path/to/virtualenv/``) + Path to pip (or to a virtualenv). This can be used to specify the path + to the pip to use when more than one Python release is installed (e.g. + ``/usr/bin/pip-2.7`` or ``/usr/bin/pip-2.6``. If a directory path is + specified, it is assumed to be a virtualenv. use_wheel Prefer wheel archives (requires pip>=1.4) @@ -561,7 +558,7 @@ def install(pkgs=None, # pylint: disable=R0912,R0913,R0914 The user under which to run pip cwd - Current working directory to run pip from + Directory from which to run pip pre_releases Include pre-releases in the available versions @@ -931,36 +928,38 @@ def uninstall(pkgs=None, saltenv='base', use_vt=False): ''' - Uninstall packages with pip - - Uninstall packages individually or from a pip requirements file. Uninstall - packages globally or from a virtualenv. + Uninstall packages individually or from a pip requirements file pkgs comma separated list of packages to install + requirements - path to requirements. + Path to requirements file + bin_env - path to pip bin or path to virtualenv. If doing an uninstall from - the system python and want to use a specific pip bin (pip-2.7, - pip-2.6, etc..) just specify the pip bin you want. - If uninstalling from a virtualenv, just use the path to the virtualenv - (/home/code/path/to/virtualenv/) + Path to pip (or to a virtualenv). This can be used to specify the path + to the pip to use when more than one Python release is installed (e.g. + ``/usr/bin/pip-2.7`` or ``/usr/bin/pip-2.6``. If a directory path is + specified, it is assumed to be a virtualenv. + log Log file where a complete (maximum verbosity) record will be kept + proxy - Specify a proxy in the form - user:passwd@proxy.server:port. Note that the - user:password@ is optional and required only if you - are behind an authenticated proxy. If you provide - user@proxy.server:port then you will be prompted for a - password. + Specify a proxy in the format ``user:passwd@proxy.server:port``. Note + that the ``user:password@`` is optional and required only if you are + behind an authenticated proxy. If you provide + ``user@proxy.server:port`` then you will be prompted for a password. + timeout Set the socket timeout (default 15 seconds) + user The user under which to run pip + cwd - Current working directory to run pip from + Directory from which to run pip + use_vt Use VT terminal emulation (see output while installing) @@ -972,7 +971,6 @@ def uninstall(pkgs=None, salt '*' pip.uninstall requirements=/path/to/requirements.txt salt '*' pip.uninstall bin_env=/path/to/virtualenv salt '*' pip.uninstall bin_env=/path/to/pip_bin - ''' cmd = _get_pip_bin(bin_env) cmd.extend(['uninstall', '-y']) @@ -1054,32 +1052,27 @@ def freeze(bin_env=None, virtualenv bin_env - path to pip bin or path to virtualenv. If doing an uninstall from - the system python and want to use a specific pip bin (pip-2.7, - pip-2.6, etc..) just specify the pip bin you want. - If uninstalling from a virtualenv, just use the path to the virtualenv - (/home/code/path/to/virtualenv/) + Path to pip (or to a virtualenv). This can be used to specify the path + to the pip to use when more than one Python release is installed (e.g. + ``/usr/bin/pip-2.7`` or ``/usr/bin/pip-2.6``. If a directory path is + specified, it is assumed to be a virtualenv. + user The user under which to run pip + cwd - Current working directory to run pip from + Directory from which to run pip .. note:: - If the version of pip available is older than 8.0.3, the list will not - include the packages pip, wheel, setuptools, or distribute even if they - are installed. + include the packages ``pip``, ``wheel``, ``setuptools``, or + ``distribute`` even if they are installed. CLI Example: .. code-block:: bash - salt '*' pip.freeze /home/code/path/to/virtualenv/ - - .. versionchanged:: 2016.11.2 - - The packages pip, wheel, setuptools, and distribute are included if the - installed pip is new enough. + salt '*' pip.freeze bin_env=/home/code/path/to/virtualenv ''' cmd = _get_pip_bin(bin_env) cmd.append('freeze') @@ -1124,21 +1117,16 @@ def list_(prefix=None, .. note:: If the version of pip available is older than 8.0.3, the packages - wheel, setuptools, and distribute will not be reported by this function - even if they are installed. Unlike - :py:func:`pip.freeze `, this function always - reports the version of pip which is installed. + ``wheel``, ``setuptools``, and ``distribute`` will not be reported by + this function even if they are installed. Unlike :py:func:`pip.freeze + `, this function always reports the version of + pip which is installed. CLI Example: .. code-block:: bash salt '*' pip.list salt - - .. versionchanged:: 2016.11.2 - - The packages wheel, setuptools, and distribute are included if the - installed pip is new enough. ''' packages = {} @@ -1392,9 +1380,10 @@ def list_all_versions(pkg, The package to check bin_env - Path to pip bin or path to virtualenv. If doing a system install, - and want to use a specific pip bin (pip-2.7, pip-2.6, etc..) just - specify the pip bin you want. + Path to pip (or to a virtualenv). This can be used to specify the path + to the pip to use when more than one Python release is installed (e.g. + ``/usr/bin/pip-2.7`` or ``/usr/bin/pip-2.6``. If a directory path is + specified, it is assumed to be a virtualenv. include_alpha Include alpha versions in the list @@ -1409,7 +1398,7 @@ def list_all_versions(pkg, The user under which to run pip cwd - Current working directory to run pip from + Directory from which to run pip CLI Example: From e4b277f82e9e4100894c2f33041b2f95e1273761 Mon Sep 17 00:00:00 2001 From: Erik Johnson Date: Tue, 8 May 2018 08:22:04 -0500 Subject: [PATCH 19/50] Fix corner case where runas user's HOME env value is incorrect In the test suite, two of the failing `pip.installed` tests were failing because when we shelled out to get the user's environment, the `HOME` environment variable's value was incorrectly showing the root user's home dir. This change ensures that we use the correct value for the HOME environment variable when running a command as another user. --- salt/modules/cmdmod.py | 8 ++++++++ tests/integration/states/test_pip_state.py | 8 ++++---- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/salt/modules/cmdmod.py b/salt/modules/cmdmod.py index 93a385dd21..c1a07466e4 100644 --- a/salt/modules/cmdmod.py +++ b/salt/modules/cmdmod.py @@ -478,10 +478,18 @@ def _run(cmd, env_runas = dict((sdecode(k), sdecode(v)) for k, v in six.iteritems(env_runas)) env_runas.update(env) + # Fix platforms like Solaris that don't set a USER env var in the # user's default environment as obtained above. if env_runas.get('USER') != runas: env_runas['USER'] = runas + + # Fix some corner cases where shelling out to get the user's + # environment returns the wrong home directory. + runas_home = os.path.expanduser('~{0}'.format(runas)) + if env_runas.get('HOME') != runas_home: + env_runas['HOME'] = runas_home + env = env_runas # Encode unicode kwargs to filesystem encoding to avoid a # UnicodeEncodeError when the subprocess is invoked. diff --git a/tests/integration/states/test_pip_state.py b/tests/integration/states/test_pip_state.py index 24d286cfd6..051c692f3e 100644 --- a/tests/integration/states/test_pip_state.py +++ b/tests/integration/states/test_pip_state.py @@ -296,7 +296,7 @@ class PipStateTest(ModuleCase, SaltReturnAssertsMixin): # pip install passing the package name in `name` ret = self.run_state( 'pip.installed', name='pep8', user=username, bin_env=venv_dir, - no_cache_dir=True, password='PassWord1!') + password='PassWord1!') self.assertSaltTrueReturn(ret) if HAS_PWD: @@ -340,12 +340,12 @@ class PipStateTest(ModuleCase, SaltReturnAssertsMixin): req_filename = os.path.join( RUNTIME_VARS.TMP_STATE_TREE, 'issue-6912-requirements.txt') with salt.utils.fopen(req_filename, 'wb') as reqf: - reqf.write(six.b('pep8')) + reqf.write(b'pep8') ret = self.run_state( 'pip.installed', name='', user=username, bin_env=venv_dir, requirements='salt://issue-6912-requirements.txt', - no_cache_dir=True, password='PassWord1!') + password='PassWord1!') self.assertSaltTrueReturn(ret) if HAS_PWD: @@ -430,7 +430,7 @@ class PipStateTest(ModuleCase, SaltReturnAssertsMixin): RUNTIME_VARS.TMP_PRODENV_STATE_TREE, 'prod-env-requirements.txt' ) with salt.utils.fopen(requirements_file, 'wb') as reqf: - reqf.write(six.b('pep8\n')) + reqf.write(b'pep8\n') try: self.run_function('virtualenv.create', [venv_dir]) From 806ffb298aff17658595391336e0da607e7dd72f Mon Sep 17 00:00:00 2001 From: Erik Johnson Date: Tue, 8 May 2018 13:46:47 -0500 Subject: [PATCH 20/50] Add masterless mode docs to gitfs tutorial --- doc/topics/tutorials/gitfs.rst | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/doc/topics/tutorials/gitfs.rst b/doc/topics/tutorials/gitfs.rst index 0349509d21..c5e97f72e1 100644 --- a/doc/topics/tutorials/gitfs.rst +++ b/doc/topics/tutorials/gitfs.rst @@ -600,15 +600,24 @@ repository to be served up from the Salt fileserver path Mountpoints can also be configured on a :ref:`per-remote basis `. + +Using gitfs in Masterless Mode +============================== + +Since 2014.7.0, gitfs can be used in masterless mode. To do so, simply add the +gitfs configuration parameters (and set :conf_master:`fileserver_backend`) in +the _minion_ config file instead of the master config file. + + Using gitfs Alongside Other Backends ==================================== Sometimes it may make sense to use multiple backends; for instance, if ``sls`` files are stored in git but larger files are stored directly on the master. -The cascading lookup logic used for multiple remotes is also used with -multiple backends. If the ``fileserver_backend`` option contains -multiple backends: +The cascading lookup logic used for multiple remotes is also used with multiple +backends. If the :conf_master:`fileserver_backend` option contains multiple +backends: .. code-block:: yaml @@ -620,7 +629,6 @@ Then the ``roots`` backend (the default backend of files in ``/srv/salt``) will be searched first for the requested file; then, if it is not found on the master, each configured git remote will be searched. - Branches, Environments, and Top Files ===================================== From a020352a0355b16c9d8702e26ae64b810df667f6 Mon Sep 17 00:00:00 2001 From: Ch3LL Date: Tue, 8 May 2018 15:12:35 -0400 Subject: [PATCH 21/50] Catch Sysloghandler errors when log file does not exist --- salt/log/handlers/__init__.py | 15 ++++++++++ tests/integration/shell/test_call.py | 42 ++++++++++++++++++++++++++++ 2 files changed, 57 insertions(+) diff --git a/salt/log/handlers/__init__.py b/salt/log/handlers/__init__.py index cb498b1bae..541f3200cb 100644 --- a/salt/log/handlers/__init__.py +++ b/salt/log/handlers/__init__.py @@ -17,6 +17,7 @@ import logging.handlers # Import salt libs from salt.log.mixins import NewStyleClassMixIn, ExcInfoOnLogLevelFormatMixIn +from salt.ext import six from salt.ext.six.moves import queue log = logging.getLogger(__name__) @@ -103,6 +104,20 @@ class SysLogHandler(ExcInfoOnLogLevelFormatMixIn, logging.handlers.SysLogHandler ''' Syslog handler which properly handles exc_info on a per handler basis ''' + def handleError(self, record): + ''' + Override the default error handling mechanism for py3 + Deal with syslog os errors when the log file does not exist + ''' + handled = False + if sys.stderr and six.PY3: + t, v, tb = sys.exc_info() + if t.__name__ in 'FileNotFoundError': + sys.stderr.write('[WARNING ] The log_file does not exist. Logging not setup correctly or syslog service not started.\n') + handled = True + + if not handled: + super(SysLogHandler, self).handleError(record) class RotatingFileHandler(ExcInfoOnLogLevelFormatMixIn, logging.handlers.RotatingFileHandler, NewStyleClassMixIn): diff --git a/tests/integration/shell/test_call.py b/tests/integration/shell/test_call.py index b8200cbca5..846ec70987 100644 --- a/tests/integration/shell/test_call.py +++ b/tests/integration/shell/test_call.py @@ -340,6 +340,48 @@ class CallTest(ShellCase, testprogram.TestProgramCase, ShellCaseCommonTestsMixin if os.path.isdir(config_dir): shutil.rmtree(config_dir) + def test_syslog_file_not_found(self): + ''' + test when log_file is set to a syslog file that does not exist + ''' + old_cwd = os.getcwd() + config_dir = os.path.join(TMP, 'log_file_incorrect') + if not os.path.isdir(config_dir): + os.makedirs(config_dir) + + os.chdir(config_dir) + + with salt.utils.fopen(self.get_config_file_path('minion'), 'r') as fh_: + minion_config = yaml.load(fh_.read()) + minion_config['log_file'] = 'file:///dev/doesnotexist' + with salt.utils.fopen(os.path.join(config_dir, 'minion'), 'w') as fh_: + fh_.write( + yaml.dump(minion_config, default_flow_style=False) + ) + ret = self.run_script( + 'salt-call', + '--config-dir {0} cmd.run "echo foo"'.format( + config_dir + ), + timeout=60, + catch_stderr=True, + with_retcode=True + ) + try: + if six.PY3: + self.assertIn('local:', ret[0]) + self.assertIn('[WARNING ] The log_file does not exist. Logging not setup correctly or syslog service not started.', ret[1]) + self.assertEqual(ret[2], 0) + else: + self.assertIn( + 'Failed to setup the Syslog logging handler', '\n'.join(ret[1]) + ) + self.assertEqual(ret[2], 2) + finally: + self.chdir(old_cwd) + if os.path.isdir(config_dir): + shutil.rmtree(config_dir) + def test_issue_15074_output_file_append(self): output_file_append = os.path.join(TMP, 'issue-15074') try: From 357bc084b3c7657149fc57a9e2d5212dd6cade9b Mon Sep 17 00:00:00 2001 From: Frankie Hui Date: Tue, 8 May 2018 00:59:01 +0800 Subject: [PATCH 22/50] fix #46546 --- salt/grains/napalm.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/salt/grains/napalm.py b/salt/grains/napalm.py index f15c970d4a..285a85aa0c 100644 --- a/salt/grains/napalm.py +++ b/salt/grains/napalm.py @@ -91,7 +91,7 @@ def _retrieve_device_cache(proxy=None): DEVICE_CACHE = proxy['napalm.get_device']() elif not proxy and salt.utils.napalm.is_minion(__opts__): # if proxy var not passed and is running in a straight minion - DEVICE_CACHE = salt.utils.napalm.get_device_opts(__opts__) + DEVICE_CACHE = salt.utils.napalm.get_device(__opts__) return DEVICE_CACHE From f0799395004f716fb8aac655178960fa6839826a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pablo=20Su=C3=A1rez=20Hern=C3=A1ndez?= Date: Fri, 4 May 2018 09:34:13 +0100 Subject: [PATCH 23/50] Do not override jid on returners, only sending back to master --- salt/utils/schedule.py | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/salt/utils/schedule.py b/salt/utils/schedule.py index 33e1359304..6f09b0b654 100644 --- a/salt/utils/schedule.py +++ b/salt/utils/schedule.py @@ -941,11 +941,13 @@ class Schedule(object): else: # Send back to master so the job is included in the job list mret = ret.copy() - mret['jid'] = 'req' - if data.get('return_job') == 'nocache': - # overwrite 'req' to signal to master that - # this job shouldn't be stored - mret['jid'] = 'nocache' + # No returners defined, so we're only sending back to the master + if not data_returner and not self.schedule_returner: + mret['jid'] = 'req' + if data.get('return_job') == 'nocache': + # overwrite 'req' to signal to master that + # this job shouldn't be stored + mret['jid'] = 'nocache' load = {'cmd': '_return', 'id': self.opts['id']} for key, value in six.iteritems(mret): load[key] = value From 502c5bdff5808e30523fa86ae438f3c929cfcdf5 Mon Sep 17 00:00:00 2001 From: Ch3LL Date: Wed, 9 May 2018 17:12:50 -0400 Subject: [PATCH 24/50] Ensure mac_service.disabled is correctly querying services --- salt/modules/mac_service.py | 22 ++++++- tests/integration/modules/test_service.py | 20 +++++- tests/unit/modules/test_mac_service.py | 79 +++++++++++++++++++++++ 3 files changed, 117 insertions(+), 4 deletions(-) create mode 100644 tests/unit/modules/test_mac_service.py diff --git a/salt/modules/mac_service.py b/salt/modules/mac_service.py index 9f5b60596c..639d66380a 100644 --- a/salt/modules/mac_service.py +++ b/salt/modules/mac_service.py @@ -496,7 +496,7 @@ def enabled(name, runas=None): return False -def disabled(name, runas=None): +def disabled(name, runas=None, domain='system'): ''' Check if the specified service is not enabled. This is the opposite of ``service.enabled`` @@ -505,6 +505,8 @@ def disabled(name, runas=None): :param str runas: User to run launchctl commands + :param str domain: domain to check for disabled services. Default is system. + :return: True if the specified service is NOT enabled, otherwise False :rtype: bool @@ -514,8 +516,22 @@ def disabled(name, runas=None): salt '*' service.disabled org.cups.cupsd ''' - # A service is disabled if it is not enabled - return not enabled(name, runas=runas) + ret = False + disabled = launchctl('print-disabled', + domain, + return_stdout=True, + output_loglevel='trace', + runas=runas) + for service in disabled.split("\n"): + if name in service: + srv_name = service.split("=>")[0].split("\"")[1] + status = service.split("=>")[1] + if name != srv_name: + pass + else: + return True if 'true' in status.lower() else False + + return False def get_all(runas=None): diff --git a/tests/integration/modules/test_service.py b/tests/integration/modules/test_service.py index a1bd78f3de..60ce7b5529 100644 --- a/tests/integration/modules/test_service.py +++ b/tests/integration/modules/test_service.py @@ -101,7 +101,25 @@ class ServiceModuleTest(ModuleCase): self.assertTrue(self.run_function('service.enable', [self.service_name])) self.assertTrue(self.run_function('service.disable', [self.service_name])) - self.assertIn(self.service_name, self.run_function('service.get_disabled')) + if salt.utils.is_darwin(): + self.assertTrue(self.run_function('service.disabled', [self.service_name])) + else: + self.assertIn(self.service_name, self.run_function('service.get_disabled')) + + def test_service_disable_doesnot_exist(self): + ''' + test service.get_disabled and service.disable module + when service name does not exist + ''' + # enable service before test + srv_name = 'doesnotexist' + self.assertFalse(self.run_function('service.enable', [srv_name])) + + self.assertFalse(self.run_function('service.disable', [srv_name])) + if salt.utils.is_darwin(): + self.assertFalse(self.run_function('service.disabled', [srv_name])) + else: + self.assertNotIn(self.service_name, self.run_function('service.get_disabled')) @skipIf(not salt.utils.is_windows(), 'Windows Only Test') def test_service_get_service_name(self): diff --git a/tests/unit/modules/test_mac_service.py b/tests/unit/modules/test_mac_service.py new file mode 100644 index 0000000000..511877a447 --- /dev/null +++ b/tests/unit/modules/test_mac_service.py @@ -0,0 +1,79 @@ +# -*- coding: utf-8 -*- +''' + :codeauthor: :email:`Nicole Thomas ` +''' + +# Import Python libs +from __future__ import absolute_import + +# Import Salt Libs +import salt.modules.mac_service as mac_service + +# Import Salt Testing Libs +from tests.support.mixins import LoaderModuleMockMixin +from tests.support.unit import skipIf, TestCase +from tests.support.mock import ( + MagicMock, + patch, + NO_MOCK, + NO_MOCK_REASON +) + + +@skipIf(NO_MOCK, NO_MOCK_REASON) +class DarwinSysctlTestCase(TestCase, LoaderModuleMockMixin): + ''' + TestCase for salt.modules.mac_service module + ''' + def setup_loader_modules(self): + return {mac_service: {}} + + def test_service_disabled_when_enabled(self): + ''' + test service.disabled when service is enabled + ''' + srv_name = 'com.apple.atrun' + cmd = 'disabled services = {\n\t"com.saltstack.salt.minion" => false\n\t"com.apple.atrun" => false\n{' + + with patch.object(mac_service, 'launchctl', MagicMock(return_value=cmd)): + self.assertFalse(mac_service.disabled(srv_name)) + + def test_service_disabled_when_disabled(self): + ''' + test service.disabled when service is disabled + ''' + srv_name = 'com.apple.atrun' + cmd = 'disabled services = {\n\t"com.saltstack.salt.minion" => false\n\t"com.apple.atrun" => true\n{' + + with patch.object(mac_service, 'launchctl', MagicMock(return_value=cmd)): + self.assertTrue(mac_service.disabled(srv_name)) + + def test_service_disabled_srvname_wrong(self): + ''' + test service.disabled when service is just slightly wrong + ''' + srv_names = ['com.apple.atru', 'com', 'apple'] + cmd = 'disabled services = {\n\t"com.saltstack.salt.minion" => false\n\t"com.apple.atrun" => true\n}' + for name in srv_names: + with patch.object(mac_service, 'launchctl', MagicMock(return_value=cmd)): + self.assertFalse(mac_service.disabled(name)) + + def test_service_disabled_short_name(self): + ''' + test service.disabled when service name is less characters + ''' + srv_name = 'com' + cmd = 'disabled services = {\n\t"com.saltstack.salt.minion" => false\n\t"com.apple.atrun" => true\n{' + + with patch.object(mac_service, 'launchctl', MagicMock(return_value=cmd)): + self.assertFalse(mac_service.disabled(srv_name)) + + def test_service_disabled_status_upper_case(self): + ''' + test service.disabled when disabled status is uppercase + ''' + srv_name = 'com.apple.atrun' + cmd = 'disabled services = {\n\t"com.saltstack.salt.minion" => false\n\t"com.apple.atrun" => True\n{' + + with patch.object(mac_service, 'launchctl', MagicMock(return_value=cmd)): + self.assertTrue(mac_service.disabled(srv_name)) From 14896f9743377a26177781eee718f20eff37b18f Mon Sep 17 00:00:00 2001 From: Ch3LL Date: Wed, 9 May 2018 17:48:59 -0400 Subject: [PATCH 25/50] change codeauthor and class name --- tests/unit/modules/test_mac_service.py | 24 +++++++----------------- 1 file changed, 7 insertions(+), 17 deletions(-) diff --git a/tests/unit/modules/test_mac_service.py b/tests/unit/modules/test_mac_service.py index 511877a447..404471a5fe 100644 --- a/tests/unit/modules/test_mac_service.py +++ b/tests/unit/modules/test_mac_service.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- ''' - :codeauthor: :email:`Nicole Thomas ` + :codeauthor: :email:`Megan Wilhite` ''' # Import Python libs @@ -21,7 +21,7 @@ from tests.support.mock import ( @skipIf(NO_MOCK, NO_MOCK_REASON) -class DarwinSysctlTestCase(TestCase, LoaderModuleMockMixin): +class MacServiceTestCase(TestCase, LoaderModuleMockMixin): ''' TestCase for salt.modules.mac_service module ''' @@ -58,22 +58,12 @@ class DarwinSysctlTestCase(TestCase, LoaderModuleMockMixin): with patch.object(mac_service, 'launchctl', MagicMock(return_value=cmd)): self.assertFalse(mac_service.disabled(name)) - def test_service_disabled_short_name(self): + def test_service_disabled_status_upper_case(self): ''' - test service.disabled when service name is less characters + test service.disabled when disabled status is uppercase ''' - srv_name = 'com' - cmd = 'disabled services = {\n\t"com.saltstack.salt.minion" => false\n\t"com.apple.atrun" => true\n{' + srv_name = 'com.apple.atrun' + cmd = 'disabled services = {\n\t"com.saltstack.salt.minion" => false\n\t"com.apple.atrun" => True\n{' with patch.object(mac_service, 'launchctl', MagicMock(return_value=cmd)): - self.assertFalse(mac_service.disabled(srv_name)) - - def test_service_disabled_status_upper_case(self): - ''' - test service.disabled when disabled status is uppercase - ''' - srv_name = 'com.apple.atrun' - cmd = 'disabled services = {\n\t"com.saltstack.salt.minion" => false\n\t"com.apple.atrun" => True\n{' - - with patch.object(mac_service, 'launchctl', MagicMock(return_value=cmd)): - self.assertTrue(mac_service.disabled(srv_name)) + self.assertTrue(mac_service.disabled(srv_name)) From c62c855f9cd0583d8b58b017da0a1d31d7cfd891 Mon Sep 17 00:00:00 2001 From: Erik Johnson Date: Wed, 9 May 2018 10:13:05 -0500 Subject: [PATCH 26/50] salt.serializers.yaml/yamlex: remove invalid multi_constructor The first argument to add_multi_constructor must be a YAML tag. This is because when PyYAML looks for a constructor to match the tag (in order to get the function to use for deserialization) it matches the tag using `.startswith()`. Thus, when this is attempted using a constructor with a tag value of `None`, an error is raised. The ordering of the list of multi_constructors in the Loader object appears to differ from platform to platform, which explains why this only caused the unit tests to fail on one or two platforms. If a tag match is found, then PyYAML stops iterating through the list of multi_constructors, so this invalid one has been able to stay in Salt without causing any noticeable trouble until now. --- salt/serializers/yaml.py | 1 - salt/serializers/yamlex.py | 1 - 2 files changed, 2 deletions(-) diff --git a/salt/serializers/yaml.py b/salt/serializers/yaml.py index 5ebc94bfc0..debbd39caf 100644 --- a/salt/serializers/yaml.py +++ b/salt/serializers/yaml.py @@ -93,7 +93,6 @@ Loader.add_multi_constructor('tag:yaml.org,2002:set', Loader.construct_yaml_set) Loader.add_multi_constructor('tag:yaml.org,2002:str', Loader.construct_yaml_str) Loader.add_multi_constructor('tag:yaml.org,2002:seq', Loader.construct_yaml_seq) Loader.add_multi_constructor('tag:yaml.org,2002:map', Loader.construct_yaml_map) -Loader.add_multi_constructor(None, Loader.construct_undefined) class Dumper(BaseDumper): # pylint: disable=W0232 diff --git a/salt/serializers/yamlex.py b/salt/serializers/yamlex.py index 65fbf58e48..0a648bb7e3 100644 --- a/salt/serializers/yamlex.py +++ b/salt/serializers/yamlex.py @@ -322,7 +322,6 @@ Loader.add_multi_constructor('tag:yaml.org,2002:pairs', Loader.construct_yaml_pa Loader.add_multi_constructor('tag:yaml.org,2002:set', Loader.construct_yaml_set) Loader.add_multi_constructor('tag:yaml.org,2002:seq', Loader.construct_yaml_seq) Loader.add_multi_constructor('tag:yaml.org,2002:map', Loader.construct_yaml_map) -Loader.add_multi_constructor(None, Loader.construct_undefined) class SLSMap(OrderedDict): From 09458c65cf004063baf5f31ab8de1a15557c96fb Mon Sep 17 00:00:00 2001 From: Erik Johnson Date: Wed, 9 May 2018 10:54:18 -0500 Subject: [PATCH 27/50] Add exception logging on serialize/deserialize exceptions Since we are reraising an error using our own exception classes, we lose the traceback. This adds exception logging to provide useful information to troubleshoot errors encountered while serializing/deserializing. --- salt/serializers/yaml.py | 7 +++++++ salt/serializers/yamlex.py | 4 ++++ 2 files changed, 11 insertions(+) diff --git a/salt/serializers/yaml.py b/salt/serializers/yaml.py index debbd39caf..7636d7dfa1 100644 --- a/salt/serializers/yaml.py +++ b/salt/serializers/yaml.py @@ -11,6 +11,7 @@ from __future__ import absolute_import import datetime +import logging import yaml from yaml.constructor import ConstructorError @@ -22,6 +23,8 @@ from salt.utils.odict import OrderedDict __all__ = ['deserialize', 'serialize', 'available'] +log = logging.getLogger(__name__) + available = True # prefer C bindings over python when available @@ -46,14 +49,17 @@ def deserialize(stream_or_string, **options): try: return yaml.load(stream_or_string, **options) except ScannerError as error: + log.exception('Error encountered while deserializing') err_type = ERROR_MAP.get(error.problem, 'Unknown yaml render error') line_num = error.problem_mark.line + 1 raise DeserializationError(err_type, line_num, error.problem_mark.buffer) except ConstructorError as error: + log.exception('Error encountered while deserializing') raise DeserializationError(error) except Exception as error: + log.exception('Error encountered while deserializing') raise DeserializationError(error) @@ -74,6 +80,7 @@ def serialize(obj, **options): return response[:-1] return response except Exception as error: + log.exception('Error encountered while serializing') raise SerializationError(error) diff --git a/salt/serializers/yamlex.py b/salt/serializers/yamlex.py index 0a648bb7e3..ac8a21d595 100644 --- a/salt/serializers/yamlex.py +++ b/salt/serializers/yamlex.py @@ -150,14 +150,17 @@ def deserialize(stream_or_string, **options): try: return yaml.load(stream_or_string, **options) except ScannerError as error: + log.exception('Error encountered while deserializing') err_type = ERROR_MAP.get(error.problem, 'Unknown yaml render error') line_num = error.problem_mark.line + 1 raise DeserializationError(err_type, line_num, error.problem_mark.buffer) except ConstructorError as error: + log.exception('Error encountered while deserializing') raise DeserializationError(error) except Exception as error: + log.exception('Error encountered while deserializing') raise DeserializationError(error) @@ -178,6 +181,7 @@ def serialize(obj, **options): return response[:-1] return response except Exception as error: + log.exception('Error encountered while serializing') raise SerializationError(error) From 31f13a4197ef02ed4892e000f0dcb064ced6b1c7 Mon Sep 17 00:00:00 2001 From: Ch3LL Date: Thu, 10 May 2018 14:12:15 -0400 Subject: [PATCH 28/50] sysloghander: check for 3.5.4 python version --- salt/log/handlers/__init__.py | 3 +-- tests/integration/shell/test_call.py | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/salt/log/handlers/__init__.py b/salt/log/handlers/__init__.py index 541f3200cb..3a7e5ca7e5 100644 --- a/salt/log/handlers/__init__.py +++ b/salt/log/handlers/__init__.py @@ -17,7 +17,6 @@ import logging.handlers # Import salt libs from salt.log.mixins import NewStyleClassMixIn, ExcInfoOnLogLevelFormatMixIn -from salt.ext import six from salt.ext.six.moves import queue log = logging.getLogger(__name__) @@ -110,7 +109,7 @@ class SysLogHandler(ExcInfoOnLogLevelFormatMixIn, logging.handlers.SysLogHandler Deal with syslog os errors when the log file does not exist ''' handled = False - if sys.stderr and six.PY3: + if sys.stderr and sys.version_info >= (3, 5, 4): t, v, tb = sys.exc_info() if t.__name__ in 'FileNotFoundError': sys.stderr.write('[WARNING ] The log_file does not exist. Logging not setup correctly or syslog service not started.\n') diff --git a/tests/integration/shell/test_call.py b/tests/integration/shell/test_call.py index 846ec70987..431149e7c7 100644 --- a/tests/integration/shell/test_call.py +++ b/tests/integration/shell/test_call.py @@ -368,7 +368,7 @@ class CallTest(ShellCase, testprogram.TestProgramCase, ShellCaseCommonTestsMixin with_retcode=True ) try: - if six.PY3: + if sys.version_info >= (3, 5, 4): self.assertIn('local:', ret[0]) self.assertIn('[WARNING ] The log_file does not exist. Logging not setup correctly or syslog service not started.', ret[1]) self.assertEqual(ret[2], 0) From a48ac26573935eddea1d54e43f9eaa136f5dca19 Mon Sep 17 00:00:00 2001 From: "Daniel A. Wozniak" Date: Thu, 10 May 2018 12:03:31 -0700 Subject: [PATCH 29/50] Skip tests when we can not use runas --- tests/integration/states/test_pip_state.py | 23 ++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/tests/integration/states/test_pip_state.py b/tests/integration/states/test_pip_state.py index 051c692f3e..76d291eefd 100644 --- a/tests/integration/states/test_pip_state.py +++ b/tests/integration/states/test_pip_state.py @@ -37,6 +37,7 @@ from tests.support.case import ModuleCase import salt.utils import salt.utils.win_dacl import salt.utils.win_functions +import salt.utils.win_runas from salt.modules.virtualenv_mod import KNOWN_BINARY_NAMES from salt.exceptions import CommandExecutionError @@ -44,6 +45,26 @@ from salt.exceptions import CommandExecutionError import salt.ext.six as six +def can_runas(): + ''' + Detect if we are running in a limited shell (winrm) and are un-able to use + the runas + ''' + if salt.utils.is_windows(): + try: + salt.utils.win_runas.run_as( + 'cmd.exe /c echo 1', 'noexistuser', 'n0existp4ss', + ) + except WindowsError as exc: + if exc.winerror == 5: + # Access Denied + return False + return True + + +CAN_RUNAS = can_runas() + + class VirtualEnv(object): def __init__(self, test, venv_dir): self.venv_dir = venv_dir @@ -270,6 +291,7 @@ class PipStateTest(ModuleCase, SaltReturnAssertsMixin): @destructiveTest @skip_if_not_root + @skipIf(not CAN_RUNAS, 'Runas support required') @with_system_user('issue-6912', on_existing='delete', delete=True, password='PassWord1!') @with_tempdir() @@ -313,6 +335,7 @@ class PipStateTest(ModuleCase, SaltReturnAssertsMixin): @destructiveTest @skip_if_not_root + @skipIf(not CAN_RUNAS, 'Runas support required') @with_system_user('issue-6912', on_existing='delete', delete=True, password='PassWord1!') @with_tempdir() From 17987d3c5a44051f2036407579c09808aa84753d Mon Sep 17 00:00:00 2001 From: "Daniel A. Wozniak" Date: Thu, 10 May 2018 12:11:45 -0700 Subject: [PATCH 30/50] Better doc string --- tests/integration/states/test_pip_state.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/integration/states/test_pip_state.py b/tests/integration/states/test_pip_state.py index 76d291eefd..bdb410de27 100644 --- a/tests/integration/states/test_pip_state.py +++ b/tests/integration/states/test_pip_state.py @@ -48,7 +48,7 @@ import salt.ext.six as six def can_runas(): ''' Detect if we are running in a limited shell (winrm) and are un-able to use - the runas + the runas utility method. ''' if salt.utils.is_windows(): try: From 33b4cfbc5b73a956d8f44b00ec33bc84d6458695 Mon Sep 17 00:00:00 2001 From: Ch3LL Date: Thu, 10 May 2018 16:16:39 -0400 Subject: [PATCH 31/50] Change service assertion check for systemd platforms --- tests/integration/modules/test_service.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/tests/integration/modules/test_service.py b/tests/integration/modules/test_service.py index 60ce7b5529..7141ef6807 100644 --- a/tests/integration/modules/test_service.py +++ b/tests/integration/modules/test_service.py @@ -10,6 +10,7 @@ from tests.support.unit import skipIf # Import Salt libs import salt.utils +import salt.utils.systemd @destructiveTest @@ -113,13 +114,17 @@ class ServiceModuleTest(ModuleCase): ''' # enable service before test srv_name = 'doesnotexist' - self.assertFalse(self.run_function('service.enable', [srv_name])) + enable = self.run_function('service.enable', [srv_name]) + if salt.utils.systemd.booted(): + self.assertIn('ERROR', enable) + else: + self.assertFalse(enable) self.assertFalse(self.run_function('service.disable', [srv_name])) if salt.utils.is_darwin(): self.assertFalse(self.run_function('service.disabled', [srv_name])) else: - self.assertNotIn(self.service_name, self.run_function('service.get_disabled')) + self.assertNotIn(srv_name, self.run_function('service.get_disabled')) @skipIf(not salt.utils.is_windows(), 'Windows Only Test') def test_service_get_service_name(self): From 58911d510ae666b6887adb7d0fc36dc39e0b4998 Mon Sep 17 00:00:00 2001 From: "Daniel A. Wozniak" Date: Fri, 11 May 2018 01:37:12 -0700 Subject: [PATCH 32/50] Ignore pylint WindowsError --- tests/integration/states/test_pip_state.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/integration/states/test_pip_state.py b/tests/integration/states/test_pip_state.py index bdb410de27..5856abc282 100644 --- a/tests/integration/states/test_pip_state.py +++ b/tests/integration/states/test_pip_state.py @@ -55,7 +55,7 @@ def can_runas(): salt.utils.win_runas.run_as( 'cmd.exe /c echo 1', 'noexistuser', 'n0existp4ss', ) - except WindowsError as exc: + except WindowsError as exc: # pylint: disable=E060 if exc.winerror == 5: # Access Denied return False From 138847c9c49b77d3e7015829c920143786a60342 Mon Sep 17 00:00:00 2001 From: Ch3LL Date: Fri, 11 May 2018 09:51:50 -0400 Subject: [PATCH 33/50] Update debian install docs to reflect new latest debian releases --- doc/topics/installation/debian.rst | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/doc/topics/installation/debian.rst b/doc/topics/installation/debian.rst index 369991ebaa..885a57fd36 100644 --- a/doc/topics/installation/debian.rst +++ b/doc/topics/installation/debian.rst @@ -6,7 +6,7 @@ Debian GNU/Linux / Raspbian Debian GNU/Linux distribution and some derivatives such as Raspbian already have included Salt packages to their repositories. However, current stable -release codenamed "Jessie" contains old outdated Salt release. It is +debian release contains old outdated Salt releases. It is recommended to use SaltStack repository for Debian as described :ref:`below `. @@ -33,11 +33,13 @@ Instructions are at https://repo.saltstack.com/#debian. Installation from the Debian / Raspbian Official Repository =========================================================== -Stretch (Testing) and Sid (Unstable) distributions are already contain mostly -up-to-date Salt packages built by Debian Salt Team. You can install Salt -components directly from Debian. +The debian distributions contain mostly old Salt packages +built by the Debian Salt Team. You can install Salt +components directly from Debian but it is recommended to +use the instructions above for the packages from the official +saltstack repository. -On Jessie (Stable) there is an option to install Salt minion from Stretch with +On Jessie there is an option to install Salt minion from Stretch with `python-tornado` dependency from `jessie-backports` repositories. To install fresh release of Salt minion on Jessie: @@ -79,7 +81,7 @@ To install fresh release of Salt minion on Jessie: apt-get update apt-get install python-zmq python-tornado/stretch salt-common/stretch -#. Install Salt minion package from Stretch: +#. Install Salt minion package from Latest Debian Release: .. code-block:: bash From 2d5ff012613e6fbdde0088dd8b4f909b85d2b635 Mon Sep 17 00:00:00 2001 From: Mike Place Date: Fri, 11 May 2018 09:18:55 -0500 Subject: [PATCH 34/50] Grammar fix --- doc/topics/installation/debian.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/topics/installation/debian.rst b/doc/topics/installation/debian.rst index 885a57fd36..a8cff3f494 100644 --- a/doc/topics/installation/debian.rst +++ b/doc/topics/installation/debian.rst @@ -33,11 +33,11 @@ Instructions are at https://repo.saltstack.com/#debian. Installation from the Debian / Raspbian Official Repository =========================================================== -The debian distributions contain mostly old Salt packages +The Debian distributions contain mostly old Salt packages built by the Debian Salt Team. You can install Salt components directly from Debian but it is recommended to use the instructions above for the packages from the official -saltstack repository. +Salt repository. On Jessie there is an option to install Salt minion from Stretch with `python-tornado` dependency from `jessie-backports` repositories. From 6d2ddd050f3632937465d3072ed39fcb50970705 Mon Sep 17 00:00:00 2001 From: Mike Place Date: Fri, 11 May 2018 11:32:33 -0500 Subject: [PATCH 35/50] One more grammar fixup --- doc/topics/installation/debian.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/topics/installation/debian.rst b/doc/topics/installation/debian.rst index a8cff3f494..893d042da4 100644 --- a/doc/topics/installation/debian.rst +++ b/doc/topics/installation/debian.rst @@ -6,7 +6,7 @@ Debian GNU/Linux / Raspbian Debian GNU/Linux distribution and some derivatives such as Raspbian already have included Salt packages to their repositories. However, current stable -debian release contains old outdated Salt releases. It is +Debian release contains old outdated Salt releases. It is recommended to use SaltStack repository for Debian as described :ref:`below `. From f78b81db94b7a591d84159414319358a43322d80 Mon Sep 17 00:00:00 2001 From: Daniel Wallace Date: Sat, 12 May 2018 21:20:47 -0400 Subject: [PATCH 36/50] simplify dev and base.txt to single files Instead of having different files for different python versions, just have one, and use the built in `python_version` to handle which dependencies to install. --- requirements/base-py2.txt | 4 ---- requirements/base-py3.txt | 1 - requirements/base.txt | 2 +- requirements/dev.txt | 16 ++++++++++++++++ requirements/dev_python27.txt | 13 ++----------- requirements/dev_python34.txt | 17 ++--------------- 6 files changed, 21 insertions(+), 32 deletions(-) delete mode 100644 requirements/base-py2.txt delete mode 100644 requirements/base-py3.txt create mode 100644 requirements/dev.txt diff --git a/requirements/base-py2.txt b/requirements/base-py2.txt deleted file mode 100644 index 57090fa637..0000000000 --- a/requirements/base-py2.txt +++ /dev/null @@ -1,4 +0,0 @@ --r base.txt - -# Required by Tornado to handle threads stuff. -futures>=2.0 diff --git a/requirements/base-py3.txt b/requirements/base-py3.txt deleted file mode 100644 index a3e81b8dcf..0000000000 --- a/requirements/base-py3.txt +++ /dev/null @@ -1 +0,0 @@ --r base.txt diff --git a/requirements/base.txt b/requirements/base.txt index de490ed07f..3d0cf758b0 100644 --- a/requirements/base.txt +++ b/requirements/base.txt @@ -5,4 +5,4 @@ MarkupSafe requests>=1.0.0 tornado>=4.2.1,<5.0 # Required by Tornado to handle threads stuff. -futures>=2.0 +futures>=2.0; python_version < '3.0' diff --git a/requirements/dev.txt b/requirements/dev.txt new file mode 100644 index 0000000000..ca057a62a3 --- /dev/null +++ b/requirements/dev.txt @@ -0,0 +1,16 @@ +-r base.txt + +mock>=2.0.0 +apache-libcloud>=0.14.0 +boto>=2.32.1 +boto3>=1.2.1 +moto>=0.3.6 +SaltPyLint>=v2017.3.6 +pytest>=3.5.0 +git+https://github.com/saltstack/pytest-salt.git@master#egg=pytest-salt + +# httpretty Needs to be here for now even though it's a dependency of boto. +# A pip install on a fresh system will decide to target httpretty 0.8.10 to +# satisfy other requirements, and httpretty 0.8.10 has bugs in setup.py that +# prevent it from being successfully installed (at least on Python 3.4). +httpretty; python_version >= '3.4' diff --git a/requirements/dev_python27.txt b/requirements/dev_python27.txt index 3e29513b1b..ae5d41379b 100644 --- a/requirements/dev_python27.txt +++ b/requirements/dev_python27.txt @@ -1,11 +1,2 @@ --r base-py2.txt - -mock>=2.0.0 -apache-libcloud>=0.14.0 -boto>=2.32.1 -boto3>=1.2.1 -moto>=0.3.6 -SaltPyLint>=v2017.3.6 -pytest>=3.5.0 -git+https://github.com/eisensheng/pytest-catchlog.git@develop#egg=Pytest-catchlog -git+https://github.com/saltstack/pytest-salt.git@master#egg=pytest-salt +# This is for legacy purposes +-r dev.txt diff --git a/requirements/dev_python34.txt b/requirements/dev_python34.txt index 2cc9bee125..d602a71ed3 100644 --- a/requirements/dev_python34.txt +++ b/requirements/dev_python34.txt @@ -1,15 +1,2 @@ --r base-py3.txt - -mock>=2.0.0 -apache-libcloud>=0.14.0 -boto>=2.32.1 -boto3>=1.2.1 -moto>=0.3.6 -# httpretty Needs to be here for now even though it's a dependency of boto. -# A pip install on a fresh system will decide to target httpretty 0.8.10 to -# satisfy other requirements, and httpretty 0.8.10 has bugs in setup.py that -# prevent it from being successfully installed (at least on Python 3.4). -httpretty -SaltPyLint>=v2017.2.29 -pytest>=3.5.0 -git+https://github.com/saltstack/pytest-salt.git@master#egg=pytest-salt +# This is a legacy file, use dev.txt +-r dev.txt From 0a621dd0ec476c069767cf8ad47543c23bced67b Mon Sep 17 00:00:00 2001 From: Daniel Wallace Date: Sat, 12 May 2018 21:39:49 -0400 Subject: [PATCH 37/50] add Pipfile for managing dependencies in salt --- Pipfile | 31 +++ Pipfile.lock | 605 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 636 insertions(+) create mode 100644 Pipfile create mode 100644 Pipfile.lock diff --git a/Pipfile b/Pipfile new file mode 100644 index 0000000000..8b947da3be --- /dev/null +++ b/Pipfile @@ -0,0 +1,31 @@ +[[source]] +url = "https://pypi.org/simple" +verify_ssl = true +name = "pypi" + +[packages] +Jinja2 = "*" +msgpack-python = ">0.3,!=0.5.5" +PyYAML = "*" +MarkupSafe = "*" +requests = ">=1.0.0" +tornado = ">=4.2.1,<5.0" +# Required by Tornado to handle threads stuff. +futures = {version = ">=2.0", markers = "python_version < '3.0'"} +pycrypto = ">=2.6.1" +pyzmq = ">=2.2.0" + +[dev-packages] +mock = ">=2.0.0" +apache-libcloud = ">=0.14.0" +boto = ">=2.32.1" +boto3 = ">=1.2.1" +moto = ">=0.3.6" +SaltPyLint = ">=v2017.3.6" +pytest = ">=3.5.0" +pytest-salt = {git = "git://github.com/saltstack/pytest-salt.git", ref = "master"} +# httpretty Needs to be here for now even though it's a dependency of boto. +# A pip install on a fresh system will decide to target httpretty 0.8.10 to +# satisfy other requirements, and httpretty 0.8.10 has bugs in setup.py that +# prevent it from being successfully installed (at least on Python 3.4). +httpretty = {version = "*", markers = "python_version >= '3.4'"} diff --git a/Pipfile.lock b/Pipfile.lock new file mode 100644 index 0000000000..585947a7ed --- /dev/null +++ b/Pipfile.lock @@ -0,0 +1,605 @@ +{ + "_meta": { + "hash": { + "sha256": "8f02988135a2598a4329ea2add290045f897d3bcc292cb859a0965de51ae18bb" + }, + "pipfile-spec": 6, + "requires": {}, + "sources": [ + { + "name": "pypi", + "url": "https://pypi.org/simple", + "verify_ssl": true + } + ] + }, + "default": { + "certifi": { + "hashes": [ + "sha256:13e698f54293db9f89122b0581843a782ad0934a4fe0172d2a980ba77fc61bb7", + "sha256:9fa520c1bacfb634fa7af20a76bcbd3d5fb390481724c597da32c719a7dca4b0" + ], + "version": "==2018.4.16" + }, + "chardet": { + "hashes": [ + "sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae", + "sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691" + ], + "version": "==3.0.4" + }, + "futures": { + "hashes": [ + "sha256:9ec02aa7d674acb8618afb127e27fde7fc68994c0437ad759fa094a574adb265", + "sha256:ec0a6cb848cc212002b9828c3e34c675e0c9ff6741dc445cab6fdd4e1085d1f1" + ], + "index": "pypi", + "markers": "python_version < '3.0'", + "version": "==3.2.0" + }, + "idna": { + "hashes": [ + "sha256:2c6a5de3089009e3da7c5dde64a141dbc8551d5b7f6cf4ed7c2568d0cc520a8f", + "sha256:8c7309c718f94b3a625cb648ace320157ad16ff131ae0af362c9f21b80ef6ec4" + ], + "version": "==2.6" + }, + "jinja2": { + "hashes": [ + "sha256:74c935a1b8bb9a3947c50a54766a969d4846290e1e788ea44c1392163723c3bd", + "sha256:f84be1bb0040caca4cea721fcbbbbd61f9be9464ca236387158b0feea01914a4" + ], + "index": "pypi", + "version": "==2.10" + }, + "markupsafe": { + "hashes": [ + "sha256:a6be69091dac236ea9c6bc7d012beab42010fa914c459791d627dad4910eb665" + ], + "index": "pypi", + "version": "==1.0" + }, + "msgpack-python": { + "hashes": [ + "sha256:378cc8a6d3545b532dfd149da715abae4fda2a3adb6d74e525d0d5e51f46909b" + ], + "index": "pypi", + "version": "==0.5.6" + }, + "pycrypto": { + "hashes": [ + "sha256:f2ce1e989b272cfcb677616763e0a2e7ec659effa67a88aa92b3a65528f60a3c" + ], + "index": "pypi", + "version": "==2.6.1" + }, + "pyyaml": { + "hashes": [ + "sha256:0c507b7f74b3d2dd4d1322ec8a94794927305ab4cebbe89cc47fe5e81541e6e8", + "sha256:16b20e970597e051997d90dc2cddc713a2876c47e3d92d59ee198700c5427736", + "sha256:3262c96a1ca437e7e4763e2843746588a965426550f3797a79fca9c6199c431f", + "sha256:326420cbb492172dec84b0f65c80942de6cedb5233c413dd824483989c000608", + "sha256:4474f8ea030b5127225b8894d626bb66c01cda098d47a2b0d3429b6700af9fd8", + "sha256:592766c6303207a20efc445587778322d7f73b161bd994f227adaa341ba212ab", + "sha256:5ac82e411044fb129bae5cfbeb3ba626acb2af31a8d17d175004b70862a741a7", + "sha256:5f84523c076ad14ff5e6c037fe1c89a7f73a3e04cf0377cb4d017014976433f3", + "sha256:827dc04b8fa7d07c44de11fabbc888e627fa8293b695e0f99cb544fdfa1bf0d1", + "sha256:b4c423ab23291d3945ac61346feeb9a0dc4184999ede5e7c43e1ffb975130ae6", + "sha256:bc6bced57f826ca7cb5125a10b23fd0f2fff3b7c4701d64c439a300ce665fff8", + "sha256:c01b880ec30b5a6e6aa67b09a2fe3fb30473008c85cd6a67359a1b15ed6d83a4", + "sha256:ca233c64c6e40eaa6c66ef97058cdc80e8d0157a443655baa1b2966e812807ca", + "sha256:e863072cdf4c72eebf179342c94e6989c67185842d9997960b3e69290b2fa269" + ], + "index": "pypi", + "version": "==3.12" + }, + "pyzmq": { + "hashes": [ + "sha256:0145ae59139b41f65e047a3a9ed11bbc36e37d5e96c64382fcdff911c4d8c3f0", + "sha256:18de8a02768b1c0b3495ac635b24bd902fafc08befb70a6e68c4d343ccbd6cbd", + "sha256:2fb4d745ffe0a65ebf8fd29df093bb5c0ac96a506cb05b9a7b7c94b2524ae7f6", + "sha256:4193cc666591495ab7fe8d24fa8374a35f9775f16dc7c46e03615559e1fc1855", + "sha256:445fed4d71ac48da258ba38f2e29c88c5091124212a4004a0a6a42e6586a7de1", + "sha256:538dfdd9542cf9ff37cd958da03b58d56b53b90800159ea07adc51a8ec7ffcb8", + "sha256:613ac1fc4591b1c6a0a52ce3ed17dbffd6a17e985df504e8b4cdb987f97285b1", + "sha256:630fb21f7474eb9e409a1ad476bf1ec489a69eb021172d422f2485cc3a44cd79", + "sha256:6c3632d2c17cf03ce728ffaa328d45bb053623b3a0aa9747adcde81778d5a4d5", + "sha256:767e1d0b1f7fff1950127abc08c5a5af2754987bc6480c6d641bed6971278a7a", + "sha256:863ec1bfa52da6eaa5c4aa59143eeaeb4ef7a076862407a548ec645f25e6d6df", + "sha256:a0ecf4c3eccd92f030a4e3e334b9da6fa3ee86be00249343c74e476d70567d0f", + "sha256:ad5a8b19b6671b52d30ccfc3a0f4c600e49c4e2dcc88caf4106ed5958dec8d5e", + "sha256:b31f2b50ad2920f21b904f5edf66bee324e42bb978df1407ecf381b210d4678e", + "sha256:b328c538061757f627d32f7f8885c16f1d2f59f5374e057822f3c8e6cd94c41b", + "sha256:b89268020a843d4c3cc04180577ec061fe96d35f267b0b672cb006e4d70560da", + "sha256:ba0b43aebf856e5e249250d74c1232d6600b6859328920d12e2ba72a565ab1b1", + "sha256:bdb12b485b3440b5193cd337d27cc126cdfc54ea9f38df237e1ead6216435cbe", + "sha256:c30d27c9b35285597b8ef3019f97b9b98457b053f65dcc87a90dfdd4db09ca78", + "sha256:d51eb3902d27d691483243707bfa67972167a70269bbbc172b74eeac4f780a1d", + "sha256:e5578ae84bb94e97adadfcb00106a1cb161cb8017f89b01f6c3737f356257811", + "sha256:f35b4cdeffff79357a9d929daa2a8620fb362b2cbeebdc5dd2cf9fcd27c44821", + "sha256:fb983aec4bddee3680a0b7395f99e4595d70d81841370da736c5dc642bad4cd2" + ], + "index": "pypi", + "version": "==17.0.0" + }, + "requests": { + "hashes": [ + "sha256:6a1b267aa90cac58ac3a765d067950e7dbbf75b1da07e895d1f594193a40a38b", + "sha256:9c443e7324ba5b85070c4a818ade28bfabedf16ea10206da1132edaa6dda237e" + ], + "index": "pypi", + "version": "==2.18.4" + }, + "tornado": { + "hashes": [ + "sha256:5ef073ac6180038ccf99411fe05ae9aafb675952a2c8db60592d5daf8401f803", + "sha256:6d14e47eab0e15799cf3cdcc86b0b98279da68522caace2bd7ce644287685f0a", + "sha256:92b7ca81e18ba9ec3031a7ee73d4577ac21d41a0c9b775a9182f43301c3b5f8e", + "sha256:ab587996fe6fb9ce65abfda440f9b61e4f9f2cf921967723540679176915e4c3", + "sha256:b36298e9f63f18cad97378db2222c0e0ca6a55f6304e605515e05a25483ed51a" + ], + "index": "pypi", + "version": "==4.5.3" + }, + "urllib3": { + "hashes": [ + "sha256:06330f386d6e4b195fbfc736b297f58c5a892e4440e54d294d7004e3a9bbea1b", + "sha256:cc44da8e1145637334317feebd728bd869a35285b93cbb4cca2577da7e62db4f" + ], + "version": "==1.22" + } + }, + "develop": { + "apache-libcloud": { + "hashes": [ + "sha256:0e2eee3802163bd0605975ed1e284cafc23203919bfa80c0cc5d3cd2543aaf97", + "sha256:48d5d64790a5112cace1a8e28d228c3f1c5bd3ddbd986a5453172d2da19f47d5" + ], + "index": "pypi", + "version": "==2.3.0" + }, + "asn1crypto": { + "hashes": [ + "sha256:2f1adbb7546ed199e3c90ef23ec95c5cf3585bac7d11fb7eb562a3fe89c64e87", + "sha256:9d5c20441baf0cb60a4ac34cc447c6c189024b6b4c6cd7877034f4965c464e49" + ], + "version": "==0.24.0" + }, + "astroid": { + "hashes": [ + "sha256:35cfae47aac19c7b407b7095410e895e836f2285ccf1220336afba744cc4c5f2", + "sha256:38186e481b65877fd8b1f9acc33e922109e983eb7b6e487bd4c71002134ad331" + ], + "version": "==1.6.3" + }, + "attrs": { + "hashes": [ + "sha256:4b90b09eeeb9b88c35bc642cbac057e45a5fd85367b985bd2809c62b7b939265", + "sha256:e0d0eb91441a3b53dab4d9b743eafc1ac44476296a2053b6ca3af0b139faf87b" + ], + "version": "==18.1.0" + }, + "aws-xray-sdk": { + "hashes": [ + "sha256:72791618feb22eaff2e628462b0d58f398ce8c1bacfa989b7679817ab1fad60c", + "sha256:9e7ba8dd08fd2939376c21423376206bff01d0deaea7d7721c6b35921fed1943" + ], + "version": "==0.95" + }, + "boto": { + "hashes": [ + "sha256:13be844158d1bd80a94c972c806ec8381b9ea72035aa06123c5db6bc6a6f3ead", + "sha256:deb8925b734b109679e3de65856018996338758f4b916ff4fe7bb62b6d7000d1" + ], + "index": "pypi", + "version": "==2.48.0" + }, + "boto3": { + "hashes": [ + "sha256:3bf4cb951faa6908134bc7f9faa300628e58961d329cba9810c65ef5fd99b54e", + "sha256:b4fadc62eca3bb2c4f894f807d087058fdf93f074472f8b7db385ed66f1c0136" + ], + "index": "pypi", + "version": "==1.7.19" + }, + "botocore": { + "hashes": [ + "sha256:184e600f78ddcc4eb508858cc82939ea4fa2b2ab9cc09c9f8642e8734c9528b4", + "sha256:e05534810847803e30a86583702eaee0c7f4f390a7af31cca8ee7e08c39ce47c" + ], + "version": "==1.10.19" + }, + "certifi": { + "hashes": [ + "sha256:13e698f54293db9f89122b0581843a782ad0934a4fe0172d2a980ba77fc61bb7", + "sha256:9fa520c1bacfb634fa7af20a76bcbd3d5fb390481724c597da32c719a7dca4b0" + ], + "version": "==2018.4.16" + }, + "cffi": { + "hashes": [ + "sha256:151b7eefd035c56b2b2e1eb9963c90c6302dc15fbd8c1c0a83a163ff2c7d7743", + "sha256:1553d1e99f035ace1c0544050622b7bc963374a00c467edafac50ad7bd276aef", + "sha256:1b0493c091a1898f1136e3f4f991a784437fac3673780ff9de3bcf46c80b6b50", + "sha256:2ba8a45822b7aee805ab49abfe7eec16b90587f7f26df20c71dd89e45a97076f", + "sha256:3c85641778460581c42924384f5e68076d724ceac0f267d66c757f7535069c93", + "sha256:3eb6434197633b7748cea30bf0ba9f66727cdce45117a712b29a443943733257", + "sha256:4c91af6e967c2015729d3e69c2e51d92f9898c330d6a851bf8f121236f3defd3", + "sha256:770f3782b31f50b68627e22f91cb182c48c47c02eb405fd689472aa7b7aa16dc", + "sha256:79f9b6f7c46ae1f8ded75f68cf8ad50e5729ed4d590c74840471fc2823457d04", + "sha256:7a33145e04d44ce95bcd71e522b478d282ad0eafaf34fe1ec5bbd73e662f22b6", + "sha256:857959354ae3a6fa3da6651b966d13b0a8bed6bbc87a0de7b38a549db1d2a359", + "sha256:87f37fe5130574ff76c17cab61e7d2538a16f843bb7bca8ebbc4b12de3078596", + "sha256:95d5251e4b5ca00061f9d9f3d6fe537247e145a8524ae9fd30a2f8fbce993b5b", + "sha256:9d1d3e63a4afdc29bd76ce6aa9d58c771cd1599fbba8cf5057e7860b203710dd", + "sha256:a36c5c154f9d42ec176e6e620cb0dd275744aa1d804786a71ac37dc3661a5e95", + "sha256:ae5e35a2c189d397b91034642cb0eab0e346f776ec2eb44a49a459e6615d6e2e", + "sha256:b0f7d4a3df8f06cf49f9f121bead236e328074de6449866515cea4907bbc63d6", + "sha256:b75110fb114fa366b29a027d0c9be3709579602ae111ff61674d28c93606acca", + "sha256:ba5e697569f84b13640c9e193170e89c13c6244c24400fc57e88724ef610cd31", + "sha256:be2a9b390f77fd7676d80bc3cdc4f8edb940d8c198ed2d8c0be1319018c778e1", + "sha256:d5d8555d9bfc3f02385c1c37e9f998e2011f0db4f90e250e5bc0c0a85a813085", + "sha256:e55e22ac0a30023426564b1059b035973ec82186ddddbac867078435801c7801", + "sha256:e90f17980e6ab0f3c2f3730e56d1fe9bcba1891eeea58966e89d352492cc74f4", + "sha256:ecbb7b01409e9b782df5ded849c178a0aa7c906cf8c5a67368047daab282b184", + "sha256:ed01918d545a38998bfa5902c7c00e0fee90e957ce036a4000a88e3fe2264917", + "sha256:edabd457cd23a02965166026fd9bfd196f4324fe6032e866d0f3bd0301cd486f", + "sha256:fdf1c1dc5bafc32bc5d08b054f94d659422b05aba244d6be4ddc1c72d9aa70fb" + ], + "markers": "platform_python_implementation != 'pypy'", + "version": "==1.11.5" + }, + "chardet": { + "hashes": [ + "sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae", + "sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691" + ], + "version": "==3.0.4" + }, + "cookies": { + "hashes": [ + "sha256:15bee753002dff684987b8df8c235288eb8d45f8191ae056254812dfd42c81d3", + "sha256:d6b698788cae4cfa4e62ef8643a9ca332b79bd96cb314294b864ae8d7eb3ee8e" + ], + "version": "==2.2.1" + }, + "cryptography": { + "hashes": [ + "sha256:3f3b65d5a16e6b52fba63dc860b62ca9832f51f1a2ae5083c78b6840275f12dd", + "sha256:551a3abfe0c8c6833df4192a63371aa2ff43afd8f570ed345d31f251d78e7e04", + "sha256:5cb990056b7cadcca26813311187ad751ea644712022a3976443691168781b6f", + "sha256:60bda7f12ecb828358be53095fc9c6edda7de8f1ef571f96c00b2363643fa3cd", + "sha256:6fef51ec447fe9f8351894024e94736862900d3a9aa2961528e602eb65c92bdb", + "sha256:77d0ad229d47a6e0272d00f6bf8ac06ce14715a9fd02c9a97f5a2869aab3ccb2", + "sha256:808fe471b1a6b777f026f7dc7bd9a4959da4bfab64972f2bbe91e22527c1c037", + "sha256:9b62fb4d18529c84b961efd9187fecbb48e89aa1a0f9f4161c61b7fc42a101bd", + "sha256:9e5bed45ec6b4f828866ac6a6bedf08388ffcfa68abe9e94b34bb40977aba531", + "sha256:9fc295bf69130a342e7a19a39d7bbeb15c0bcaabc7382ec33ef3b2b7d18d2f63", + "sha256:abd070b5849ed64e6d349199bef955ee0ad99aefbad792f0c587f8effa681a5e", + "sha256:ba6a774749b6e510cffc2fb98535f717e0e5fd91c7c99a61d223293df79ab351", + "sha256:c332118647f084c983c6a3e1dba0f3bcb051f69d12baccac68db8d62d177eb8a", + "sha256:d6f46e862ee36df81e6342c2177ba84e70f722d9dc9c6c394f9f1f434c4a5563", + "sha256:db6013746f73bf8edd9c3d1d3f94db635b9422f503db3fc5ef105233d4c011ab", + "sha256:f57008eaff597c69cf692c3518f6d4800f0309253bb138b526a37fe9ef0c7471", + "sha256:f6c821ac253c19f2ad4c8691633ae1d1a17f120d5b01ea1d256d7b602bc59887" + ], + "version": "==2.2.2" + }, + "docker": { + "hashes": [ + "sha256:43b45b92bed372161a5d4f3c7137e16b30d93845e99a00bc727938e52850694e", + "sha256:dc5cc0971a0d36fe94c5ce89bd4adb6c892713500af7b0818708229c3199911a" + ], + "version": "==3.3.0" + }, + "docker-pycreds": { + "hashes": [ + "sha256:764a7ea2f6484bc5de5bf0c060f08b41a1118cf1acb987626b3ff45f3cc40dac", + "sha256:e3732a03610a00461a716997670c7010bf1c214a3edc440f7d6a2a3a830ecd9d" + ], + "version": "==0.2.3" + }, + "docutils": { + "hashes": [ + "sha256:02aec4bd92ab067f6ff27a38a38a41173bf01bed8f89157768c1573f53e474a6", + "sha256:51e64ef2ebfb29cae1faa133b3710143496eca21c530f3f71424d77687764274", + "sha256:7a4bd47eaf6596e1295ecb11361139febe29b084a87bf005bf899f9a42edc3c6" + ], + "version": "==0.14" + }, + "httpretty": { + "hashes": [ + "sha256:69259e22addf5ab5f25bd00c6568e16fc2e54efdd4da69eb0950718dba3b2dab" + ], + "index": "pypi", + "markers": "python_version >= '3.4'", + "version": "==0.9.4" + }, + "idna": { + "hashes": [ + "sha256:2c6a5de3089009e3da7c5dde64a141dbc8551d5b7f6cf4ed7c2568d0cc520a8f", + "sha256:8c7309c718f94b3a625cb648ace320157ad16ff131ae0af362c9f21b80ef6ec4" + ], + "version": "==2.6" + }, + "isort": { + "hashes": [ + "sha256:1153601da39a25b14ddc54955dbbacbb6b2d19135386699e2ad58517953b34af", + "sha256:b9c40e9750f3d77e6e4d441d8b0266cf555e7cdabdcff33c4fd06366ca761ef8", + "sha256:ec9ef8f4a9bc6f71eec99e1806bfa2de401650d996c59330782b89a5555c1497" + ], + "version": "==4.3.4" + }, + "jinja2": { + "hashes": [ + "sha256:74c935a1b8bb9a3947c50a54766a969d4846290e1e788ea44c1392163723c3bd", + "sha256:f84be1bb0040caca4cea721fcbbbbd61f9be9464ca236387158b0feea01914a4" + ], + "index": "pypi", + "version": "==2.10" + }, + "jmespath": { + "hashes": [ + "sha256:6a81d4c9aa62caf061cb517b4d9ad1dd300374cd4706997aff9cd6aedd61fc64", + "sha256:f11b4461f425740a1d908e9a3f7365c3d2e569f6ca68a2ff8bc5bcd9676edd63" + ], + "version": "==0.9.3" + }, + "jsondiff": { + "hashes": [ + "sha256:2d0437782de9418efa34e694aa59f43d7adb1899bd9a793f063867ddba8f7893" + ], + "version": "==1.1.1" + }, + "jsonpickle": { + "hashes": [ + "sha256:545b3bee0d65e1abb4baa1818edcc9ec239aa9f2ffbfde8084d71c056180054f" + ], + "version": "==0.9.6" + }, + "lazy-object-proxy": { + "hashes": [ + "sha256:0ce34342b419bd8f018e6666bfef729aec3edf62345a53b537a4dcc115746a33", + "sha256:1b668120716eb7ee21d8a38815e5eb3bb8211117d9a90b0f8e21722c0758cc39", + "sha256:209615b0fe4624d79e50220ce3310ca1a9445fd8e6d3572a896e7f9146bbf019", + "sha256:27bf62cb2b1a2068d443ff7097ee33393f8483b570b475db8ebf7e1cba64f088", + "sha256:27ea6fd1c02dcc78172a82fc37fcc0992a94e4cecf53cb6d73f11749825bd98b", + "sha256:2c1b21b44ac9beb0fc848d3993924147ba45c4ebc24be19825e57aabbe74a99e", + "sha256:2df72ab12046a3496a92476020a1a0abf78b2a7db9ff4dc2036b8dd980203ae6", + "sha256:320ffd3de9699d3892048baee45ebfbbf9388a7d65d832d7e580243ade426d2b", + "sha256:50e3b9a464d5d08cc5227413db0d1c4707b6172e4d4d915c1c70e4de0bbff1f5", + "sha256:5276db7ff62bb7b52f77f1f51ed58850e315154249aceb42e7f4c611f0f847ff", + "sha256:61a6cf00dcb1a7f0c773ed4acc509cb636af2d6337a08f362413c76b2b47a8dd", + "sha256:6ae6c4cb59f199d8827c5a07546b2ab7e85d262acaccaacd49b62f53f7c456f7", + "sha256:7661d401d60d8bf15bb5da39e4dd72f5d764c5aff5a86ef52a042506e3e970ff", + "sha256:7bd527f36a605c914efca5d3d014170b2cb184723e423d26b1fb2fd9108e264d", + "sha256:7cb54db3535c8686ea12e9535eb087d32421184eacc6939ef15ef50f83a5e7e2", + "sha256:7f3a2d740291f7f2c111d86a1c4851b70fb000a6c8883a59660d95ad57b9df35", + "sha256:81304b7d8e9c824d058087dcb89144842c8e0dea6d281c031f59f0acf66963d4", + "sha256:933947e8b4fbe617a51528b09851685138b49d511af0b6c0da2539115d6d4514", + "sha256:94223d7f060301b3a8c09c9b3bc3294b56b2188e7d8179c762a1cda72c979252", + "sha256:ab3ca49afcb47058393b0122428358d2fbe0408cf99f1b58b295cfeb4ed39109", + "sha256:bd6292f565ca46dee4e737ebcc20742e3b5be2b01556dafe169f6c65d088875f", + "sha256:cb924aa3e4a3fb644d0c463cad5bc2572649a6a3f68a7f8e4fbe44aaa6d77e4c", + "sha256:d0fc7a286feac9077ec52a927fc9fe8fe2fabab95426722be4c953c9a8bede92", + "sha256:ddc34786490a6e4ec0a855d401034cbd1242ef186c20d79d2166d6a4bd449577", + "sha256:e34b155e36fa9da7e1b7c738ed7767fc9491a62ec6af70fe9da4a057759edc2d", + "sha256:e5b9e8f6bda48460b7b143c3821b21b452cb3a835e6bbd5dd33aa0c8d3f5137d", + "sha256:e81ebf6c5ee9684be8f2c87563880f93eedd56dd2b6146d8a725b50b7e5adb0f", + "sha256:eb91be369f945f10d3a49f5f9be8b3d0b93a4c2be8f8a5b83b0571b8123e0a7a", + "sha256:f460d1ceb0e4a5dcb2a652db0904224f367c9b3c1470d5a7683c0480e582468b" + ], + "version": "==1.3.1" + }, + "markupsafe": { + "hashes": [ + "sha256:a6be69091dac236ea9c6bc7d012beab42010fa914c459791d627dad4910eb665" + ], + "index": "pypi", + "version": "==1.0" + }, + "mccabe": { + "hashes": [ + "sha256:ab8a6258860da4b6677da4bd2fe5dc2c659cff31b3ee4f7f5d64e79735b80d42", + "sha256:dd8d182285a0fe56bace7f45b5e7d1a6ebcbf524e8f3bd87eb0f125271b8831f" + ], + "version": "==0.6.1" + }, + "mock": { + "hashes": [ + "sha256:5ce3c71c5545b472da17b72268978914d0252980348636840bd34a00b5cc96c1", + "sha256:b158b6df76edd239b8208d481dc46b6afd45a846b7812ff0ce58971cf5bc8bba" + ], + "index": "pypi", + "version": "==2.0.0" + }, + "modernize": { + "hashes": [ + "sha256:358dbb35baec7619d9b7cd5efed532c9f4a2e4e4a80f70c4d03f7aa30f76905d" + ], + "version": "==0.5" + }, + "more-itertools": { + "hashes": [ + "sha256:0dd8f72eeab0d2c3bd489025bb2f6a1b8342f9b198f6fc37b52d15cfa4531fea", + "sha256:11a625025954c20145b37ff6309cd54e39ca94f72f6bb9576d1195db6fa2442e", + "sha256:c9ce7eccdcb901a2c75d326ea134e0886abfbea5f93e91cc95de9507c0816c44" + ], + "version": "==4.1.0" + }, + "moto": { + "hashes": [ + "sha256:45d14aca2b06b0083d5e82cfd770ebca0ba77b5070aec6928670240939a78681", + "sha256:ee71b515ba34d64c5f625950fc995594040f793a4a106614ff108ae02c1a2896" + ], + "index": "pypi", + "version": "==1.3.3" + }, + "pbr": { + "hashes": [ + "sha256:4e8a0ed6a8705a26768f4c3da26026013b157821fe5f95881599556ea9d91c19", + "sha256:dae4aaa78eafcad10ce2581fc34d694faa616727837fd8e55c1a00951ad6744f" + ], + "version": "==4.0.2" + }, + "pep8": { + "hashes": [ + "sha256:4aa129df8d9007b192bf82013f415533994652d7caa930d002687eb42a6c2a41", + "sha256:b8b7e35630b5539e26a197dfc6005be9e1e9a135496b377723a8ebc01b9bcbff" + ], + "version": "==1.6.2" + }, + "pluggy": { + "hashes": [ + "sha256:7f8ae7f5bdf75671a718d2daf0a64b7885f74510bcd98b1a0bb420eb9a9d0cff", + "sha256:d345c8fe681115900d6da8d048ba67c25df42973bda370783cd58826442dcd7c", + "sha256:e160a7fcf25762bb60efc7e171d4497ff1d8d2d75a3d0df7a21b76821ecbf5c5" + ], + "version": "==0.6.0" + }, + "py": { + "hashes": [ + "sha256:29c9fab495d7528e80ba1e343b958684f4ace687327e6f789a94bf3d1915f881", + "sha256:983f77f3331356039fdd792e9220b7b8ee1aa6bd2b25f567a963ff1de5a64f6a" + ], + "version": "==1.5.3" + }, + "pyaml": { + "hashes": [ + "sha256:66623c52f34d83a2c0fc963e08e8b9d0c13d88404e3b43b1852ef71eda19afa3", + "sha256:f83fc302c52c6b83a15345792693ae0b5bc07ad19f59e318b7617d7123d62990" + ], + "version": "==17.12.1" + }, + "pycparser": { + "hashes": [ + "sha256:99a8ca03e29851d96616ad0404b4aad7d9ee16f25c9f9708a11faf2810f7b226" + ], + "version": "==2.18" + }, + "pylint": { + "hashes": [ + "sha256:0b7e6b5d9f1d4e0b554b5d948f14ed7969e8cdf9a0120853e6e5af60813b18ab", + "sha256:34738a82ab33cbd3bb6cd4cef823dbcabdd2b6b48a4e3a3054a2bbbf0c712be9" + ], + "version": "==1.8.4" + }, + "pytest": { + "hashes": [ + "sha256:54713b26c97538db6ff0703a12b19aeaeb60b5e599de542e7fca0ec83b9038e8", + "sha256:829230122facf05a5f81a6d4dfe6454a04978ea3746853b2b84567ecf8e5c526" + ], + "index": "pypi", + "version": "==3.5.1" + }, + "pytest-salt": { + "git": "git://github.com/saltstack/pytest-salt.git", + "ref": "master" + }, + "python-dateutil": { + "hashes": [ + "sha256:891c38b2a02f5bb1be3e4793866c8df49c7d19baabf9c1bad62547e0b4866aca", + "sha256:95511bae634d69bc7329ba55e646499a842bc4ec342ad54a8cdb65645a0aad3c" + ], + "version": "==2.6.1" + }, + "pytz": { + "hashes": [ + "sha256:65ae0c8101309c45772196b21b74c46b2e5d11b6275c45d251b150d5da334555", + "sha256:c06425302f2cf668f1bba7a0a03f3c1d34d4ebeef2c72003da308b3947c7f749" + ], + "version": "==2018.4" + }, + "pyyaml": { + "hashes": [ + "sha256:0c507b7f74b3d2dd4d1322ec8a94794927305ab4cebbe89cc47fe5e81541e6e8", + "sha256:16b20e970597e051997d90dc2cddc713a2876c47e3d92d59ee198700c5427736", + "sha256:3262c96a1ca437e7e4763e2843746588a965426550f3797a79fca9c6199c431f", + "sha256:326420cbb492172dec84b0f65c80942de6cedb5233c413dd824483989c000608", + "sha256:4474f8ea030b5127225b8894d626bb66c01cda098d47a2b0d3429b6700af9fd8", + "sha256:592766c6303207a20efc445587778322d7f73b161bd994f227adaa341ba212ab", + "sha256:5ac82e411044fb129bae5cfbeb3ba626acb2af31a8d17d175004b70862a741a7", + "sha256:5f84523c076ad14ff5e6c037fe1c89a7f73a3e04cf0377cb4d017014976433f3", + "sha256:827dc04b8fa7d07c44de11fabbc888e627fa8293b695e0f99cb544fdfa1bf0d1", + "sha256:b4c423ab23291d3945ac61346feeb9a0dc4184999ede5e7c43e1ffb975130ae6", + "sha256:bc6bced57f826ca7cb5125a10b23fd0f2fff3b7c4701d64c439a300ce665fff8", + "sha256:c01b880ec30b5a6e6aa67b09a2fe3fb30473008c85cd6a67359a1b15ed6d83a4", + "sha256:ca233c64c6e40eaa6c66ef97058cdc80e8d0157a443655baa1b2966e812807ca", + "sha256:e863072cdf4c72eebf179342c94e6989c67185842d9997960b3e69290b2fa269" + ], + "index": "pypi", + "version": "==3.12" + }, + "requests": { + "hashes": [ + "sha256:6a1b267aa90cac58ac3a765d067950e7dbbf75b1da07e895d1f594193a40a38b", + "sha256:9c443e7324ba5b85070c4a818ade28bfabedf16ea10206da1132edaa6dda237e" + ], + "index": "pypi", + "version": "==2.18.4" + }, + "responses": { + "hashes": [ + "sha256:c6082710f4abfb60793899ca5f21e7ceb25aabf321560cc0726f8b59006811c9", + "sha256:f23a29dca18b815d9d64a516b4a0abb1fbdccff6141d988ad8100facb81cf7b3" + ], + "version": "==0.9.0" + }, + "s3transfer": { + "hashes": [ + "sha256:90dc18e028989c609146e241ea153250be451e05ecc0c2832565231dacdf59c1", + "sha256:c7a9ec356982d5e9ab2d4b46391a7d6a950e2b04c472419f5fdec70cc0ada72f" + ], + "version": "==0.1.13" + }, + "saltpylint": { + "hashes": [ + "sha256:0eff47f258c9232d6e6ff03861c93443da182d3cddee1b5aa5b1aa6708dda660", + "sha256:5ff2012dcd0caf18400b94f13d2f30e2228310de06249190566796bbf15f64b5" + ], + "index": "pypi", + "version": "==2017.12.15" + }, + "six": { + "hashes": [ + "sha256:70e8a77beed4562e7f14fe23a786b54f6296e34344c23bc42f07b15018ff98e9", + "sha256:832dc0e10feb1aa2c68dcc57dbb658f1c7e65b9b61af69048abc87a2db00a0eb" + ], + "version": "==1.11.0" + }, + "urllib3": { + "hashes": [ + "sha256:06330f386d6e4b195fbfc736b297f58c5a892e4440e54d294d7004e3a9bbea1b", + "sha256:cc44da8e1145637334317feebd728bd869a35285b93cbb4cca2577da7e62db4f" + ], + "version": "==1.22" + }, + "websocket-client": { + "hashes": [ + "sha256:188b68b14fdb2d8eb1a111f21b9ffd2dbf1dbc4e4c1d28cf2c37cdbf1dd1cae6", + "sha256:a453dc4dfa6e0db3d8fd7738a308a88effe6240c59f3226eb93e8f020c216149" + ], + "version": "==0.47.0" + }, + "werkzeug": { + "hashes": [ + "sha256:c3fd7a7d41976d9f44db327260e263132466836cef6f91512889ed60ad26557c", + "sha256:d5da73735293558eb1651ee2fddc4d0dedcfa06538b8813a2e20011583c9e49b" + ], + "version": "==0.14.1" + }, + "wrapt": { + "hashes": [ + "sha256:d4d560d479f2c21e1b5443bbd15fe7ec4b37fe7e53d335d3b9b0a7b1226fe3c6" + ], + "version": "==1.10.11" + }, + "xmltodict": { + "hashes": [ + "sha256:8f8d7d40aa28d83f4109a7e8aa86e67a4df202d9538be40c0cb1d70da527b0df", + "sha256:add07d92089ff611badec526912747cf87afd4f9447af6661aca074eeaf32615" + ], + "version": "==0.11.0" + } + } +} From e0f7cc1447f9746953ad86e212ce3bd7284ed30c Mon Sep 17 00:00:00 2001 From: Daniel Wallace Date: Sun, 13 May 2018 08:35:06 -0400 Subject: [PATCH 38/50] add proxy tests decorator to pytest conftest --- .gitignore | 1 + tests/conftest.py | 11 ++++++++++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index c015ea2c31..925ec8de7f 100644 --- a/.gitignore +++ b/.gitignore @@ -11,6 +11,7 @@ MANIFEST *.wpr *.wpu *.DS_Store +.pytest_cache # virtualenv # - ignores directories of a virtualenv when you create it right on diff --git a/tests/conftest.py b/tests/conftest.py index 7f8bd54533..6c45881774 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -102,6 +102,14 @@ def pytest_addoption(parser): 'SSH server on your machine. In certain environments, this ' 'may be insecure! Default: False' ) + test_selection_group.addoption( + '--proxy', + '--proxy-tests', + dest='ssh', + action='store_true', + default=False, + help='Run proxy tests' + ) test_selection_group.addoption( '--run-destructive', action='store_true', @@ -640,7 +648,8 @@ def test_daemon(request): ('sysinfo', request.config.getoption('--sysinfo')), ('no_colors', request.config.getoption('--no-colors')), ('output_columns', request.config.getoption('--output-columns')), - ('ssh', request.config.getoption('--ssh'))) + ('ssh', request.config.getoption('--ssh')), + ('proxy', request.config.getoption('--proxy'))) options = namedtuple('options', [n for n, v in values])(*[v for n, v in values]) fake_parser = namedtuple('parser', 'options')(options) From 493ed7f93d529268adcc042b10602705257a3860 Mon Sep 17 00:00:00 2001 From: Daniel Wallace Date: Sun, 13 May 2018 14:35:23 -0400 Subject: [PATCH 39/50] use the toml dict format --- Pipfile | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/Pipfile b/Pipfile index 8b947da3be..22ca7ca4cc 100644 --- a/Pipfile +++ b/Pipfile @@ -10,8 +10,6 @@ PyYAML = "*" MarkupSafe = "*" requests = ">=1.0.0" tornado = ">=4.2.1,<5.0" -# Required by Tornado to handle threads stuff. -futures = {version = ">=2.0", markers = "python_version < '3.0'"} pycrypto = ">=2.6.1" pyzmq = ">=2.2.0" @@ -23,9 +21,20 @@ boto3 = ">=1.2.1" moto = ">=0.3.6" SaltPyLint = ">=v2017.3.6" pytest = ">=3.5.0" -pytest-salt = {git = "git://github.com/saltstack/pytest-salt.git", ref = "master"} + +[packages.futures] +# Required by Tornado to handle threads stuff. +version = ">=2.0" +markers = "python_version < '3.0'" + +[dev-packages.pytest-salt] +git = "git://github.com/saltstack/pytest-salt.git" +ref = "master" + +[dev-packages.httpretty] # httpretty Needs to be here for now even though it's a dependency of boto. # A pip install on a fresh system will decide to target httpretty 0.8.10 to # satisfy other requirements, and httpretty 0.8.10 has bugs in setup.py that # prevent it from being successfully installed (at least on Python 3.4). -httpretty = {version = "*", markers = "python_version >= '3.4'"} +version = "*" +markers = "python_version >= '3.4'" From d53b44d10fefba152f59a8080760b619cbada024 Mon Sep 17 00:00:00 2001 From: Daniel Wallace Date: Sun, 13 May 2018 14:35:50 -0400 Subject: [PATCH 40/50] remove lock file --- .gitignore | 1 + Pipfile.lock | 605 --------------------------------------------------- 2 files changed, 1 insertion(+), 605 deletions(-) delete mode 100644 Pipfile.lock diff --git a/.gitignore b/.gitignore index 925ec8de7f..761ef65644 100644 --- a/.gitignore +++ b/.gitignore @@ -12,6 +12,7 @@ MANIFEST *.wpu *.DS_Store .pytest_cache +Pipfile.lock # virtualenv # - ignores directories of a virtualenv when you create it right on diff --git a/Pipfile.lock b/Pipfile.lock deleted file mode 100644 index 585947a7ed..0000000000 --- a/Pipfile.lock +++ /dev/null @@ -1,605 +0,0 @@ -{ - "_meta": { - "hash": { - "sha256": "8f02988135a2598a4329ea2add290045f897d3bcc292cb859a0965de51ae18bb" - }, - "pipfile-spec": 6, - "requires": {}, - "sources": [ - { - "name": "pypi", - "url": "https://pypi.org/simple", - "verify_ssl": true - } - ] - }, - "default": { - "certifi": { - "hashes": [ - "sha256:13e698f54293db9f89122b0581843a782ad0934a4fe0172d2a980ba77fc61bb7", - "sha256:9fa520c1bacfb634fa7af20a76bcbd3d5fb390481724c597da32c719a7dca4b0" - ], - "version": "==2018.4.16" - }, - "chardet": { - "hashes": [ - "sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae", - "sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691" - ], - "version": "==3.0.4" - }, - "futures": { - "hashes": [ - "sha256:9ec02aa7d674acb8618afb127e27fde7fc68994c0437ad759fa094a574adb265", - "sha256:ec0a6cb848cc212002b9828c3e34c675e0c9ff6741dc445cab6fdd4e1085d1f1" - ], - "index": "pypi", - "markers": "python_version < '3.0'", - "version": "==3.2.0" - }, - "idna": { - "hashes": [ - "sha256:2c6a5de3089009e3da7c5dde64a141dbc8551d5b7f6cf4ed7c2568d0cc520a8f", - "sha256:8c7309c718f94b3a625cb648ace320157ad16ff131ae0af362c9f21b80ef6ec4" - ], - "version": "==2.6" - }, - "jinja2": { - "hashes": [ - "sha256:74c935a1b8bb9a3947c50a54766a969d4846290e1e788ea44c1392163723c3bd", - "sha256:f84be1bb0040caca4cea721fcbbbbd61f9be9464ca236387158b0feea01914a4" - ], - "index": "pypi", - "version": "==2.10" - }, - "markupsafe": { - "hashes": [ - "sha256:a6be69091dac236ea9c6bc7d012beab42010fa914c459791d627dad4910eb665" - ], - "index": "pypi", - "version": "==1.0" - }, - "msgpack-python": { - "hashes": [ - "sha256:378cc8a6d3545b532dfd149da715abae4fda2a3adb6d74e525d0d5e51f46909b" - ], - "index": "pypi", - "version": "==0.5.6" - }, - "pycrypto": { - "hashes": [ - "sha256:f2ce1e989b272cfcb677616763e0a2e7ec659effa67a88aa92b3a65528f60a3c" - ], - "index": "pypi", - "version": "==2.6.1" - }, - "pyyaml": { - "hashes": [ - "sha256:0c507b7f74b3d2dd4d1322ec8a94794927305ab4cebbe89cc47fe5e81541e6e8", - "sha256:16b20e970597e051997d90dc2cddc713a2876c47e3d92d59ee198700c5427736", - "sha256:3262c96a1ca437e7e4763e2843746588a965426550f3797a79fca9c6199c431f", - "sha256:326420cbb492172dec84b0f65c80942de6cedb5233c413dd824483989c000608", - "sha256:4474f8ea030b5127225b8894d626bb66c01cda098d47a2b0d3429b6700af9fd8", - "sha256:592766c6303207a20efc445587778322d7f73b161bd994f227adaa341ba212ab", - "sha256:5ac82e411044fb129bae5cfbeb3ba626acb2af31a8d17d175004b70862a741a7", - "sha256:5f84523c076ad14ff5e6c037fe1c89a7f73a3e04cf0377cb4d017014976433f3", - "sha256:827dc04b8fa7d07c44de11fabbc888e627fa8293b695e0f99cb544fdfa1bf0d1", - "sha256:b4c423ab23291d3945ac61346feeb9a0dc4184999ede5e7c43e1ffb975130ae6", - "sha256:bc6bced57f826ca7cb5125a10b23fd0f2fff3b7c4701d64c439a300ce665fff8", - "sha256:c01b880ec30b5a6e6aa67b09a2fe3fb30473008c85cd6a67359a1b15ed6d83a4", - "sha256:ca233c64c6e40eaa6c66ef97058cdc80e8d0157a443655baa1b2966e812807ca", - "sha256:e863072cdf4c72eebf179342c94e6989c67185842d9997960b3e69290b2fa269" - ], - "index": "pypi", - "version": "==3.12" - }, - "pyzmq": { - "hashes": [ - "sha256:0145ae59139b41f65e047a3a9ed11bbc36e37d5e96c64382fcdff911c4d8c3f0", - "sha256:18de8a02768b1c0b3495ac635b24bd902fafc08befb70a6e68c4d343ccbd6cbd", - "sha256:2fb4d745ffe0a65ebf8fd29df093bb5c0ac96a506cb05b9a7b7c94b2524ae7f6", - "sha256:4193cc666591495ab7fe8d24fa8374a35f9775f16dc7c46e03615559e1fc1855", - "sha256:445fed4d71ac48da258ba38f2e29c88c5091124212a4004a0a6a42e6586a7de1", - "sha256:538dfdd9542cf9ff37cd958da03b58d56b53b90800159ea07adc51a8ec7ffcb8", - "sha256:613ac1fc4591b1c6a0a52ce3ed17dbffd6a17e985df504e8b4cdb987f97285b1", - "sha256:630fb21f7474eb9e409a1ad476bf1ec489a69eb021172d422f2485cc3a44cd79", - "sha256:6c3632d2c17cf03ce728ffaa328d45bb053623b3a0aa9747adcde81778d5a4d5", - "sha256:767e1d0b1f7fff1950127abc08c5a5af2754987bc6480c6d641bed6971278a7a", - "sha256:863ec1bfa52da6eaa5c4aa59143eeaeb4ef7a076862407a548ec645f25e6d6df", - "sha256:a0ecf4c3eccd92f030a4e3e334b9da6fa3ee86be00249343c74e476d70567d0f", - "sha256:ad5a8b19b6671b52d30ccfc3a0f4c600e49c4e2dcc88caf4106ed5958dec8d5e", - "sha256:b31f2b50ad2920f21b904f5edf66bee324e42bb978df1407ecf381b210d4678e", - "sha256:b328c538061757f627d32f7f8885c16f1d2f59f5374e057822f3c8e6cd94c41b", - "sha256:b89268020a843d4c3cc04180577ec061fe96d35f267b0b672cb006e4d70560da", - "sha256:ba0b43aebf856e5e249250d74c1232d6600b6859328920d12e2ba72a565ab1b1", - "sha256:bdb12b485b3440b5193cd337d27cc126cdfc54ea9f38df237e1ead6216435cbe", - "sha256:c30d27c9b35285597b8ef3019f97b9b98457b053f65dcc87a90dfdd4db09ca78", - "sha256:d51eb3902d27d691483243707bfa67972167a70269bbbc172b74eeac4f780a1d", - "sha256:e5578ae84bb94e97adadfcb00106a1cb161cb8017f89b01f6c3737f356257811", - "sha256:f35b4cdeffff79357a9d929daa2a8620fb362b2cbeebdc5dd2cf9fcd27c44821", - "sha256:fb983aec4bddee3680a0b7395f99e4595d70d81841370da736c5dc642bad4cd2" - ], - "index": "pypi", - "version": "==17.0.0" - }, - "requests": { - "hashes": [ - "sha256:6a1b267aa90cac58ac3a765d067950e7dbbf75b1da07e895d1f594193a40a38b", - "sha256:9c443e7324ba5b85070c4a818ade28bfabedf16ea10206da1132edaa6dda237e" - ], - "index": "pypi", - "version": "==2.18.4" - }, - "tornado": { - "hashes": [ - "sha256:5ef073ac6180038ccf99411fe05ae9aafb675952a2c8db60592d5daf8401f803", - "sha256:6d14e47eab0e15799cf3cdcc86b0b98279da68522caace2bd7ce644287685f0a", - "sha256:92b7ca81e18ba9ec3031a7ee73d4577ac21d41a0c9b775a9182f43301c3b5f8e", - "sha256:ab587996fe6fb9ce65abfda440f9b61e4f9f2cf921967723540679176915e4c3", - "sha256:b36298e9f63f18cad97378db2222c0e0ca6a55f6304e605515e05a25483ed51a" - ], - "index": "pypi", - "version": "==4.5.3" - }, - "urllib3": { - "hashes": [ - "sha256:06330f386d6e4b195fbfc736b297f58c5a892e4440e54d294d7004e3a9bbea1b", - "sha256:cc44da8e1145637334317feebd728bd869a35285b93cbb4cca2577da7e62db4f" - ], - "version": "==1.22" - } - }, - "develop": { - "apache-libcloud": { - "hashes": [ - "sha256:0e2eee3802163bd0605975ed1e284cafc23203919bfa80c0cc5d3cd2543aaf97", - "sha256:48d5d64790a5112cace1a8e28d228c3f1c5bd3ddbd986a5453172d2da19f47d5" - ], - "index": "pypi", - "version": "==2.3.0" - }, - "asn1crypto": { - "hashes": [ - "sha256:2f1adbb7546ed199e3c90ef23ec95c5cf3585bac7d11fb7eb562a3fe89c64e87", - "sha256:9d5c20441baf0cb60a4ac34cc447c6c189024b6b4c6cd7877034f4965c464e49" - ], - "version": "==0.24.0" - }, - "astroid": { - "hashes": [ - "sha256:35cfae47aac19c7b407b7095410e895e836f2285ccf1220336afba744cc4c5f2", - "sha256:38186e481b65877fd8b1f9acc33e922109e983eb7b6e487bd4c71002134ad331" - ], - "version": "==1.6.3" - }, - "attrs": { - "hashes": [ - "sha256:4b90b09eeeb9b88c35bc642cbac057e45a5fd85367b985bd2809c62b7b939265", - "sha256:e0d0eb91441a3b53dab4d9b743eafc1ac44476296a2053b6ca3af0b139faf87b" - ], - "version": "==18.1.0" - }, - "aws-xray-sdk": { - "hashes": [ - "sha256:72791618feb22eaff2e628462b0d58f398ce8c1bacfa989b7679817ab1fad60c", - "sha256:9e7ba8dd08fd2939376c21423376206bff01d0deaea7d7721c6b35921fed1943" - ], - "version": "==0.95" - }, - "boto": { - "hashes": [ - "sha256:13be844158d1bd80a94c972c806ec8381b9ea72035aa06123c5db6bc6a6f3ead", - "sha256:deb8925b734b109679e3de65856018996338758f4b916ff4fe7bb62b6d7000d1" - ], - "index": "pypi", - "version": "==2.48.0" - }, - "boto3": { - "hashes": [ - "sha256:3bf4cb951faa6908134bc7f9faa300628e58961d329cba9810c65ef5fd99b54e", - "sha256:b4fadc62eca3bb2c4f894f807d087058fdf93f074472f8b7db385ed66f1c0136" - ], - "index": "pypi", - "version": "==1.7.19" - }, - "botocore": { - "hashes": [ - "sha256:184e600f78ddcc4eb508858cc82939ea4fa2b2ab9cc09c9f8642e8734c9528b4", - "sha256:e05534810847803e30a86583702eaee0c7f4f390a7af31cca8ee7e08c39ce47c" - ], - "version": "==1.10.19" - }, - "certifi": { - "hashes": [ - "sha256:13e698f54293db9f89122b0581843a782ad0934a4fe0172d2a980ba77fc61bb7", - "sha256:9fa520c1bacfb634fa7af20a76bcbd3d5fb390481724c597da32c719a7dca4b0" - ], - "version": "==2018.4.16" - }, - "cffi": { - "hashes": [ - "sha256:151b7eefd035c56b2b2e1eb9963c90c6302dc15fbd8c1c0a83a163ff2c7d7743", - "sha256:1553d1e99f035ace1c0544050622b7bc963374a00c467edafac50ad7bd276aef", - "sha256:1b0493c091a1898f1136e3f4f991a784437fac3673780ff9de3bcf46c80b6b50", - "sha256:2ba8a45822b7aee805ab49abfe7eec16b90587f7f26df20c71dd89e45a97076f", - "sha256:3c85641778460581c42924384f5e68076d724ceac0f267d66c757f7535069c93", - "sha256:3eb6434197633b7748cea30bf0ba9f66727cdce45117a712b29a443943733257", - "sha256:4c91af6e967c2015729d3e69c2e51d92f9898c330d6a851bf8f121236f3defd3", - "sha256:770f3782b31f50b68627e22f91cb182c48c47c02eb405fd689472aa7b7aa16dc", - "sha256:79f9b6f7c46ae1f8ded75f68cf8ad50e5729ed4d590c74840471fc2823457d04", - "sha256:7a33145e04d44ce95bcd71e522b478d282ad0eafaf34fe1ec5bbd73e662f22b6", - "sha256:857959354ae3a6fa3da6651b966d13b0a8bed6bbc87a0de7b38a549db1d2a359", - "sha256:87f37fe5130574ff76c17cab61e7d2538a16f843bb7bca8ebbc4b12de3078596", - "sha256:95d5251e4b5ca00061f9d9f3d6fe537247e145a8524ae9fd30a2f8fbce993b5b", - "sha256:9d1d3e63a4afdc29bd76ce6aa9d58c771cd1599fbba8cf5057e7860b203710dd", - "sha256:a36c5c154f9d42ec176e6e620cb0dd275744aa1d804786a71ac37dc3661a5e95", - "sha256:ae5e35a2c189d397b91034642cb0eab0e346f776ec2eb44a49a459e6615d6e2e", - "sha256:b0f7d4a3df8f06cf49f9f121bead236e328074de6449866515cea4907bbc63d6", - "sha256:b75110fb114fa366b29a027d0c9be3709579602ae111ff61674d28c93606acca", - "sha256:ba5e697569f84b13640c9e193170e89c13c6244c24400fc57e88724ef610cd31", - "sha256:be2a9b390f77fd7676d80bc3cdc4f8edb940d8c198ed2d8c0be1319018c778e1", - "sha256:d5d8555d9bfc3f02385c1c37e9f998e2011f0db4f90e250e5bc0c0a85a813085", - "sha256:e55e22ac0a30023426564b1059b035973ec82186ddddbac867078435801c7801", - "sha256:e90f17980e6ab0f3c2f3730e56d1fe9bcba1891eeea58966e89d352492cc74f4", - "sha256:ecbb7b01409e9b782df5ded849c178a0aa7c906cf8c5a67368047daab282b184", - "sha256:ed01918d545a38998bfa5902c7c00e0fee90e957ce036a4000a88e3fe2264917", - "sha256:edabd457cd23a02965166026fd9bfd196f4324fe6032e866d0f3bd0301cd486f", - "sha256:fdf1c1dc5bafc32bc5d08b054f94d659422b05aba244d6be4ddc1c72d9aa70fb" - ], - "markers": "platform_python_implementation != 'pypy'", - "version": "==1.11.5" - }, - "chardet": { - "hashes": [ - "sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae", - "sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691" - ], - "version": "==3.0.4" - }, - "cookies": { - "hashes": [ - "sha256:15bee753002dff684987b8df8c235288eb8d45f8191ae056254812dfd42c81d3", - "sha256:d6b698788cae4cfa4e62ef8643a9ca332b79bd96cb314294b864ae8d7eb3ee8e" - ], - "version": "==2.2.1" - }, - "cryptography": { - "hashes": [ - "sha256:3f3b65d5a16e6b52fba63dc860b62ca9832f51f1a2ae5083c78b6840275f12dd", - "sha256:551a3abfe0c8c6833df4192a63371aa2ff43afd8f570ed345d31f251d78e7e04", - "sha256:5cb990056b7cadcca26813311187ad751ea644712022a3976443691168781b6f", - "sha256:60bda7f12ecb828358be53095fc9c6edda7de8f1ef571f96c00b2363643fa3cd", - "sha256:6fef51ec447fe9f8351894024e94736862900d3a9aa2961528e602eb65c92bdb", - "sha256:77d0ad229d47a6e0272d00f6bf8ac06ce14715a9fd02c9a97f5a2869aab3ccb2", - "sha256:808fe471b1a6b777f026f7dc7bd9a4959da4bfab64972f2bbe91e22527c1c037", - "sha256:9b62fb4d18529c84b961efd9187fecbb48e89aa1a0f9f4161c61b7fc42a101bd", - "sha256:9e5bed45ec6b4f828866ac6a6bedf08388ffcfa68abe9e94b34bb40977aba531", - "sha256:9fc295bf69130a342e7a19a39d7bbeb15c0bcaabc7382ec33ef3b2b7d18d2f63", - "sha256:abd070b5849ed64e6d349199bef955ee0ad99aefbad792f0c587f8effa681a5e", - "sha256:ba6a774749b6e510cffc2fb98535f717e0e5fd91c7c99a61d223293df79ab351", - "sha256:c332118647f084c983c6a3e1dba0f3bcb051f69d12baccac68db8d62d177eb8a", - "sha256:d6f46e862ee36df81e6342c2177ba84e70f722d9dc9c6c394f9f1f434c4a5563", - "sha256:db6013746f73bf8edd9c3d1d3f94db635b9422f503db3fc5ef105233d4c011ab", - "sha256:f57008eaff597c69cf692c3518f6d4800f0309253bb138b526a37fe9ef0c7471", - "sha256:f6c821ac253c19f2ad4c8691633ae1d1a17f120d5b01ea1d256d7b602bc59887" - ], - "version": "==2.2.2" - }, - "docker": { - "hashes": [ - "sha256:43b45b92bed372161a5d4f3c7137e16b30d93845e99a00bc727938e52850694e", - "sha256:dc5cc0971a0d36fe94c5ce89bd4adb6c892713500af7b0818708229c3199911a" - ], - "version": "==3.3.0" - }, - "docker-pycreds": { - "hashes": [ - "sha256:764a7ea2f6484bc5de5bf0c060f08b41a1118cf1acb987626b3ff45f3cc40dac", - "sha256:e3732a03610a00461a716997670c7010bf1c214a3edc440f7d6a2a3a830ecd9d" - ], - "version": "==0.2.3" - }, - "docutils": { - "hashes": [ - "sha256:02aec4bd92ab067f6ff27a38a38a41173bf01bed8f89157768c1573f53e474a6", - "sha256:51e64ef2ebfb29cae1faa133b3710143496eca21c530f3f71424d77687764274", - "sha256:7a4bd47eaf6596e1295ecb11361139febe29b084a87bf005bf899f9a42edc3c6" - ], - "version": "==0.14" - }, - "httpretty": { - "hashes": [ - "sha256:69259e22addf5ab5f25bd00c6568e16fc2e54efdd4da69eb0950718dba3b2dab" - ], - "index": "pypi", - "markers": "python_version >= '3.4'", - "version": "==0.9.4" - }, - "idna": { - "hashes": [ - "sha256:2c6a5de3089009e3da7c5dde64a141dbc8551d5b7f6cf4ed7c2568d0cc520a8f", - "sha256:8c7309c718f94b3a625cb648ace320157ad16ff131ae0af362c9f21b80ef6ec4" - ], - "version": "==2.6" - }, - "isort": { - "hashes": [ - "sha256:1153601da39a25b14ddc54955dbbacbb6b2d19135386699e2ad58517953b34af", - "sha256:b9c40e9750f3d77e6e4d441d8b0266cf555e7cdabdcff33c4fd06366ca761ef8", - "sha256:ec9ef8f4a9bc6f71eec99e1806bfa2de401650d996c59330782b89a5555c1497" - ], - "version": "==4.3.4" - }, - "jinja2": { - "hashes": [ - "sha256:74c935a1b8bb9a3947c50a54766a969d4846290e1e788ea44c1392163723c3bd", - "sha256:f84be1bb0040caca4cea721fcbbbbd61f9be9464ca236387158b0feea01914a4" - ], - "index": "pypi", - "version": "==2.10" - }, - "jmespath": { - "hashes": [ - "sha256:6a81d4c9aa62caf061cb517b4d9ad1dd300374cd4706997aff9cd6aedd61fc64", - "sha256:f11b4461f425740a1d908e9a3f7365c3d2e569f6ca68a2ff8bc5bcd9676edd63" - ], - "version": "==0.9.3" - }, - "jsondiff": { - "hashes": [ - "sha256:2d0437782de9418efa34e694aa59f43d7adb1899bd9a793f063867ddba8f7893" - ], - "version": "==1.1.1" - }, - "jsonpickle": { - "hashes": [ - "sha256:545b3bee0d65e1abb4baa1818edcc9ec239aa9f2ffbfde8084d71c056180054f" - ], - "version": "==0.9.6" - }, - "lazy-object-proxy": { - "hashes": [ - "sha256:0ce34342b419bd8f018e6666bfef729aec3edf62345a53b537a4dcc115746a33", - "sha256:1b668120716eb7ee21d8a38815e5eb3bb8211117d9a90b0f8e21722c0758cc39", - "sha256:209615b0fe4624d79e50220ce3310ca1a9445fd8e6d3572a896e7f9146bbf019", - "sha256:27bf62cb2b1a2068d443ff7097ee33393f8483b570b475db8ebf7e1cba64f088", - "sha256:27ea6fd1c02dcc78172a82fc37fcc0992a94e4cecf53cb6d73f11749825bd98b", - "sha256:2c1b21b44ac9beb0fc848d3993924147ba45c4ebc24be19825e57aabbe74a99e", - "sha256:2df72ab12046a3496a92476020a1a0abf78b2a7db9ff4dc2036b8dd980203ae6", - "sha256:320ffd3de9699d3892048baee45ebfbbf9388a7d65d832d7e580243ade426d2b", - "sha256:50e3b9a464d5d08cc5227413db0d1c4707b6172e4d4d915c1c70e4de0bbff1f5", - "sha256:5276db7ff62bb7b52f77f1f51ed58850e315154249aceb42e7f4c611f0f847ff", - "sha256:61a6cf00dcb1a7f0c773ed4acc509cb636af2d6337a08f362413c76b2b47a8dd", - "sha256:6ae6c4cb59f199d8827c5a07546b2ab7e85d262acaccaacd49b62f53f7c456f7", - "sha256:7661d401d60d8bf15bb5da39e4dd72f5d764c5aff5a86ef52a042506e3e970ff", - "sha256:7bd527f36a605c914efca5d3d014170b2cb184723e423d26b1fb2fd9108e264d", - "sha256:7cb54db3535c8686ea12e9535eb087d32421184eacc6939ef15ef50f83a5e7e2", - "sha256:7f3a2d740291f7f2c111d86a1c4851b70fb000a6c8883a59660d95ad57b9df35", - "sha256:81304b7d8e9c824d058087dcb89144842c8e0dea6d281c031f59f0acf66963d4", - "sha256:933947e8b4fbe617a51528b09851685138b49d511af0b6c0da2539115d6d4514", - "sha256:94223d7f060301b3a8c09c9b3bc3294b56b2188e7d8179c762a1cda72c979252", - "sha256:ab3ca49afcb47058393b0122428358d2fbe0408cf99f1b58b295cfeb4ed39109", - "sha256:bd6292f565ca46dee4e737ebcc20742e3b5be2b01556dafe169f6c65d088875f", - "sha256:cb924aa3e4a3fb644d0c463cad5bc2572649a6a3f68a7f8e4fbe44aaa6d77e4c", - "sha256:d0fc7a286feac9077ec52a927fc9fe8fe2fabab95426722be4c953c9a8bede92", - "sha256:ddc34786490a6e4ec0a855d401034cbd1242ef186c20d79d2166d6a4bd449577", - "sha256:e34b155e36fa9da7e1b7c738ed7767fc9491a62ec6af70fe9da4a057759edc2d", - "sha256:e5b9e8f6bda48460b7b143c3821b21b452cb3a835e6bbd5dd33aa0c8d3f5137d", - "sha256:e81ebf6c5ee9684be8f2c87563880f93eedd56dd2b6146d8a725b50b7e5adb0f", - "sha256:eb91be369f945f10d3a49f5f9be8b3d0b93a4c2be8f8a5b83b0571b8123e0a7a", - "sha256:f460d1ceb0e4a5dcb2a652db0904224f367c9b3c1470d5a7683c0480e582468b" - ], - "version": "==1.3.1" - }, - "markupsafe": { - "hashes": [ - "sha256:a6be69091dac236ea9c6bc7d012beab42010fa914c459791d627dad4910eb665" - ], - "index": "pypi", - "version": "==1.0" - }, - "mccabe": { - "hashes": [ - "sha256:ab8a6258860da4b6677da4bd2fe5dc2c659cff31b3ee4f7f5d64e79735b80d42", - "sha256:dd8d182285a0fe56bace7f45b5e7d1a6ebcbf524e8f3bd87eb0f125271b8831f" - ], - "version": "==0.6.1" - }, - "mock": { - "hashes": [ - "sha256:5ce3c71c5545b472da17b72268978914d0252980348636840bd34a00b5cc96c1", - "sha256:b158b6df76edd239b8208d481dc46b6afd45a846b7812ff0ce58971cf5bc8bba" - ], - "index": "pypi", - "version": "==2.0.0" - }, - "modernize": { - "hashes": [ - "sha256:358dbb35baec7619d9b7cd5efed532c9f4a2e4e4a80f70c4d03f7aa30f76905d" - ], - "version": "==0.5" - }, - "more-itertools": { - "hashes": [ - "sha256:0dd8f72eeab0d2c3bd489025bb2f6a1b8342f9b198f6fc37b52d15cfa4531fea", - "sha256:11a625025954c20145b37ff6309cd54e39ca94f72f6bb9576d1195db6fa2442e", - "sha256:c9ce7eccdcb901a2c75d326ea134e0886abfbea5f93e91cc95de9507c0816c44" - ], - "version": "==4.1.0" - }, - "moto": { - "hashes": [ - "sha256:45d14aca2b06b0083d5e82cfd770ebca0ba77b5070aec6928670240939a78681", - "sha256:ee71b515ba34d64c5f625950fc995594040f793a4a106614ff108ae02c1a2896" - ], - "index": "pypi", - "version": "==1.3.3" - }, - "pbr": { - "hashes": [ - "sha256:4e8a0ed6a8705a26768f4c3da26026013b157821fe5f95881599556ea9d91c19", - "sha256:dae4aaa78eafcad10ce2581fc34d694faa616727837fd8e55c1a00951ad6744f" - ], - "version": "==4.0.2" - }, - "pep8": { - "hashes": [ - "sha256:4aa129df8d9007b192bf82013f415533994652d7caa930d002687eb42a6c2a41", - "sha256:b8b7e35630b5539e26a197dfc6005be9e1e9a135496b377723a8ebc01b9bcbff" - ], - "version": "==1.6.2" - }, - "pluggy": { - "hashes": [ - "sha256:7f8ae7f5bdf75671a718d2daf0a64b7885f74510bcd98b1a0bb420eb9a9d0cff", - "sha256:d345c8fe681115900d6da8d048ba67c25df42973bda370783cd58826442dcd7c", - "sha256:e160a7fcf25762bb60efc7e171d4497ff1d8d2d75a3d0df7a21b76821ecbf5c5" - ], - "version": "==0.6.0" - }, - "py": { - "hashes": [ - "sha256:29c9fab495d7528e80ba1e343b958684f4ace687327e6f789a94bf3d1915f881", - "sha256:983f77f3331356039fdd792e9220b7b8ee1aa6bd2b25f567a963ff1de5a64f6a" - ], - "version": "==1.5.3" - }, - "pyaml": { - "hashes": [ - "sha256:66623c52f34d83a2c0fc963e08e8b9d0c13d88404e3b43b1852ef71eda19afa3", - "sha256:f83fc302c52c6b83a15345792693ae0b5bc07ad19f59e318b7617d7123d62990" - ], - "version": "==17.12.1" - }, - "pycparser": { - "hashes": [ - "sha256:99a8ca03e29851d96616ad0404b4aad7d9ee16f25c9f9708a11faf2810f7b226" - ], - "version": "==2.18" - }, - "pylint": { - "hashes": [ - "sha256:0b7e6b5d9f1d4e0b554b5d948f14ed7969e8cdf9a0120853e6e5af60813b18ab", - "sha256:34738a82ab33cbd3bb6cd4cef823dbcabdd2b6b48a4e3a3054a2bbbf0c712be9" - ], - "version": "==1.8.4" - }, - "pytest": { - "hashes": [ - "sha256:54713b26c97538db6ff0703a12b19aeaeb60b5e599de542e7fca0ec83b9038e8", - "sha256:829230122facf05a5f81a6d4dfe6454a04978ea3746853b2b84567ecf8e5c526" - ], - "index": "pypi", - "version": "==3.5.1" - }, - "pytest-salt": { - "git": "git://github.com/saltstack/pytest-salt.git", - "ref": "master" - }, - "python-dateutil": { - "hashes": [ - "sha256:891c38b2a02f5bb1be3e4793866c8df49c7d19baabf9c1bad62547e0b4866aca", - "sha256:95511bae634d69bc7329ba55e646499a842bc4ec342ad54a8cdb65645a0aad3c" - ], - "version": "==2.6.1" - }, - "pytz": { - "hashes": [ - "sha256:65ae0c8101309c45772196b21b74c46b2e5d11b6275c45d251b150d5da334555", - "sha256:c06425302f2cf668f1bba7a0a03f3c1d34d4ebeef2c72003da308b3947c7f749" - ], - "version": "==2018.4" - }, - "pyyaml": { - "hashes": [ - "sha256:0c507b7f74b3d2dd4d1322ec8a94794927305ab4cebbe89cc47fe5e81541e6e8", - "sha256:16b20e970597e051997d90dc2cddc713a2876c47e3d92d59ee198700c5427736", - "sha256:3262c96a1ca437e7e4763e2843746588a965426550f3797a79fca9c6199c431f", - "sha256:326420cbb492172dec84b0f65c80942de6cedb5233c413dd824483989c000608", - "sha256:4474f8ea030b5127225b8894d626bb66c01cda098d47a2b0d3429b6700af9fd8", - "sha256:592766c6303207a20efc445587778322d7f73b161bd994f227adaa341ba212ab", - "sha256:5ac82e411044fb129bae5cfbeb3ba626acb2af31a8d17d175004b70862a741a7", - "sha256:5f84523c076ad14ff5e6c037fe1c89a7f73a3e04cf0377cb4d017014976433f3", - "sha256:827dc04b8fa7d07c44de11fabbc888e627fa8293b695e0f99cb544fdfa1bf0d1", - "sha256:b4c423ab23291d3945ac61346feeb9a0dc4184999ede5e7c43e1ffb975130ae6", - "sha256:bc6bced57f826ca7cb5125a10b23fd0f2fff3b7c4701d64c439a300ce665fff8", - "sha256:c01b880ec30b5a6e6aa67b09a2fe3fb30473008c85cd6a67359a1b15ed6d83a4", - "sha256:ca233c64c6e40eaa6c66ef97058cdc80e8d0157a443655baa1b2966e812807ca", - "sha256:e863072cdf4c72eebf179342c94e6989c67185842d9997960b3e69290b2fa269" - ], - "index": "pypi", - "version": "==3.12" - }, - "requests": { - "hashes": [ - "sha256:6a1b267aa90cac58ac3a765d067950e7dbbf75b1da07e895d1f594193a40a38b", - "sha256:9c443e7324ba5b85070c4a818ade28bfabedf16ea10206da1132edaa6dda237e" - ], - "index": "pypi", - "version": "==2.18.4" - }, - "responses": { - "hashes": [ - "sha256:c6082710f4abfb60793899ca5f21e7ceb25aabf321560cc0726f8b59006811c9", - "sha256:f23a29dca18b815d9d64a516b4a0abb1fbdccff6141d988ad8100facb81cf7b3" - ], - "version": "==0.9.0" - }, - "s3transfer": { - "hashes": [ - "sha256:90dc18e028989c609146e241ea153250be451e05ecc0c2832565231dacdf59c1", - "sha256:c7a9ec356982d5e9ab2d4b46391a7d6a950e2b04c472419f5fdec70cc0ada72f" - ], - "version": "==0.1.13" - }, - "saltpylint": { - "hashes": [ - "sha256:0eff47f258c9232d6e6ff03861c93443da182d3cddee1b5aa5b1aa6708dda660", - "sha256:5ff2012dcd0caf18400b94f13d2f30e2228310de06249190566796bbf15f64b5" - ], - "index": "pypi", - "version": "==2017.12.15" - }, - "six": { - "hashes": [ - "sha256:70e8a77beed4562e7f14fe23a786b54f6296e34344c23bc42f07b15018ff98e9", - "sha256:832dc0e10feb1aa2c68dcc57dbb658f1c7e65b9b61af69048abc87a2db00a0eb" - ], - "version": "==1.11.0" - }, - "urllib3": { - "hashes": [ - "sha256:06330f386d6e4b195fbfc736b297f58c5a892e4440e54d294d7004e3a9bbea1b", - "sha256:cc44da8e1145637334317feebd728bd869a35285b93cbb4cca2577da7e62db4f" - ], - "version": "==1.22" - }, - "websocket-client": { - "hashes": [ - "sha256:188b68b14fdb2d8eb1a111f21b9ffd2dbf1dbc4e4c1d28cf2c37cdbf1dd1cae6", - "sha256:a453dc4dfa6e0db3d8fd7738a308a88effe6240c59f3226eb93e8f020c216149" - ], - "version": "==0.47.0" - }, - "werkzeug": { - "hashes": [ - "sha256:c3fd7a7d41976d9f44db327260e263132466836cef6f91512889ed60ad26557c", - "sha256:d5da73735293558eb1651ee2fddc4d0dedcfa06538b8813a2e20011583c9e49b" - ], - "version": "==0.14.1" - }, - "wrapt": { - "hashes": [ - "sha256:d4d560d479f2c21e1b5443bbd15fe7ec4b37fe7e53d335d3b9b0a7b1226fe3c6" - ], - "version": "==1.10.11" - }, - "xmltodict": { - "hashes": [ - "sha256:8f8d7d40aa28d83f4109a7e8aa86e67a4df202d9538be40c0cb1d70da527b0df", - "sha256:add07d92089ff611badec526912747cf87afd4f9447af6661aca074eeaf32615" - ], - "version": "==0.11.0" - } - } -} From 3235ac08cbf65988bc15490bfb65534169d88e6f Mon Sep 17 00:00:00 2001 From: "Daniel A. Wozniak" Date: Mon, 14 May 2018 08:26:01 -0700 Subject: [PATCH 41/50] use ignore-undefined-variable --- test | 4 ++++ tests/integration/states/test_pip_state.py | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) create mode 100644 test diff --git a/test b/test new file mode 100644 index 0000000000..68abad7d93 --- /dev/null +++ b/test @@ -0,0 +1,4 @@ +a +b +c + diff --git a/tests/integration/states/test_pip_state.py b/tests/integration/states/test_pip_state.py index 5856abc282..60b1f17e2e 100644 --- a/tests/integration/states/test_pip_state.py +++ b/tests/integration/states/test_pip_state.py @@ -55,7 +55,7 @@ def can_runas(): salt.utils.win_runas.run_as( 'cmd.exe /c echo 1', 'noexistuser', 'n0existp4ss', ) - except WindowsError as exc: # pylint: disable=E060 + except WindowsError as exc: # pylint: disable=undefined-variable if exc.winerror == 5: # Access Denied return False From 69bc88f1c6e963a7bcd14b20c44fed6fc08cb8c2 Mon Sep 17 00:00:00 2001 From: "Daniel A. Wozniak" Date: Mon, 14 May 2018 09:48:31 -0700 Subject: [PATCH 42/50] Remove unwanted file --- test | 4 ---- 1 file changed, 4 deletions(-) delete mode 100644 test diff --git a/test b/test deleted file mode 100644 index 68abad7d93..0000000000 --- a/test +++ /dev/null @@ -1,4 +0,0 @@ -a -b -c - From 8c5e54b8b3c4be967de5624e117788a1bbc5a4c6 Mon Sep 17 00:00:00 2001 From: "Daniel A. Wozniak" Date: Mon, 14 May 2018 10:30:04 -0700 Subject: [PATCH 43/50] Fix typo --- tests/integration/states/test_pip_state.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/integration/states/test_pip_state.py b/tests/integration/states/test_pip_state.py index 60b1f17e2e..4382ae585a 100644 --- a/tests/integration/states/test_pip_state.py +++ b/tests/integration/states/test_pip_state.py @@ -52,7 +52,7 @@ def can_runas(): ''' if salt.utils.is_windows(): try: - salt.utils.win_runas.run_as( + salt.utils.win_runas.runas( 'cmd.exe /c echo 1', 'noexistuser', 'n0existp4ss', ) except WindowsError as exc: # pylint: disable=undefined-variable From 6032a01f5599d5a4d1f9beea3d3ccebce9cdf84c Mon Sep 17 00:00:00 2001 From: Ch3LL Date: Tue, 15 May 2018 12:07:27 -0400 Subject: [PATCH 44/50] change disable check for upstart service on ubuntu14 --- tests/integration/modules/test_service.py | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/tests/integration/modules/test_service.py b/tests/integration/modules/test_service.py index 7141ef6807..77a41e4bc6 100644 --- a/tests/integration/modules/test_service.py +++ b/tests/integration/modules/test_service.py @@ -115,12 +115,21 @@ class ServiceModuleTest(ModuleCase): # enable service before test srv_name = 'doesnotexist' enable = self.run_function('service.enable', [srv_name]) - if salt.utils.systemd.booted(): + systemd = salt.utils.systemd.booted() + + # check service was not enabled + if systemd: self.assertIn('ERROR', enable) else: self.assertFalse(enable) - self.assertFalse(self.run_function('service.disable', [srv_name])) + # check service was not disabled + if tuple(self.run_function('grains.item', ['osrelease_info'])['osrelease_info']) == (14, 0o4) and not systemd: + # currently upstart does not have a mechanism to report if disabling a service fails if does not exist + self.assertTrue(self.run_function('service.disable', [srv_name])) + else: + self.assertFalse(self.run_function('service.disable', [srv_name])) + if salt.utils.is_darwin(): self.assertFalse(self.run_function('service.disabled', [srv_name])) else: From 418364a533770722b612b439ad19fa0c9712ec1a Mon Sep 17 00:00:00 2001 From: Daniel Wallace Date: Tue, 15 May 2018 12:29:52 -0500 Subject: [PATCH 45/50] make dev_python27.txt have the same message as dev_python34.txt --- requirements/dev_python27.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements/dev_python27.txt b/requirements/dev_python27.txt index ae5d41379b..d602a71ed3 100644 --- a/requirements/dev_python27.txt +++ b/requirements/dev_python27.txt @@ -1,2 +1,2 @@ -# This is for legacy purposes +# This is a legacy file, use dev.txt -r dev.txt From fd8a02decb23272066798a6e5109cc05cceeb78d Mon Sep 17 00:00:00 2001 From: Daniel Wallace Date: Tue, 15 May 2018 12:35:48 -0500 Subject: [PATCH 46/50] use dictupdate to update the providers dictionary and merge lists --- salt/cloud/__init__.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/salt/cloud/__init__.py b/salt/cloud/__init__.py index 566b75a5fa..745e4e87ee 100644 --- a/salt/cloud/__init__.py +++ b/salt/cloud/__init__.py @@ -1910,7 +1910,7 @@ class Map(Cloud): pmap = self.map_providers_parallel(cached=cached) exist = set() defined = set() - for profile_name, nodes in six.iteritems(self.rendered_map): + for profile_name, nodes in six.iteritems(copy.deepcopy(self.rendered_map)): if profile_name not in self.opts['profiles']: msg = ( 'The required profile, \'{0}\', defined in the map ' @@ -1931,13 +1931,13 @@ class Map(Cloud): # Get associated provider data, in case something like size # or image is specified in the provider file. See issue #32510. alias, driver = profile_data.get('provider').split(':') - provider_details = self.opts['providers'][alias][driver].copy() + provider_details = copy.deepcopy(self.opts['providers'][alias][driver]) del provider_details['profiles'] # Update the provider details information with profile data # Profile data should override provider data, if defined. # This keeps map file data definitions consistent with -p usage. - provider_details.update(profile_data) + salt.utils.dictupdate.update(provider_details, profile_data) profile_data = provider_details for nodename, overrides in six.iteritems(nodes): From dfd5a8715f50368f9e41f739407dee4646d1c659 Mon Sep 17 00:00:00 2001 From: Daniel Wallace Date: Tue, 15 May 2018 20:55:18 -0500 Subject: [PATCH 47/50] add a pytest.ini and update a dependency for kitchen --- Gemfile | 2 +- pytest.ini | 4 ++++ tests/conftest.py | 2 +- 3 files changed, 6 insertions(+), 2 deletions(-) create mode 100644 pytest.ini diff --git a/Gemfile b/Gemfile index fde8b3691c..8e527b42dc 100644 --- a/Gemfile +++ b/Gemfile @@ -2,7 +2,7 @@ source 'https://rubygems.org' -gem 'test-kitchen', :git => 'https://github.com/gtmanfred/test-kitchen.git' +gem 'test-kitchen', '>=1.21.0' gem 'kitchen-salt', :git => 'https://github.com/saltstack/kitchen-salt.git' gem 'kitchen-sync' gem 'git' diff --git a/pytest.ini b/pytest.ini new file mode 100644 index 0000000000..de3a013904 --- /dev/null +++ b/pytest.ini @@ -0,0 +1,4 @@ +[pytest] +addopts = --ssh-tests -ra -sv +testpaths = tests +norecursedirs = tests/kitchen diff --git a/tests/conftest.py b/tests/conftest.py index 6c45881774..1b189e5907 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -105,7 +105,7 @@ def pytest_addoption(parser): test_selection_group.addoption( '--proxy', '--proxy-tests', - dest='ssh', + dest='proxy', action='store_true', default=False, help='Run proxy tests' From 454291ad62e3e5bcb090cd5a79336407c3e421da Mon Sep 17 00:00:00 2001 From: andrei Date: Wed, 31 Jan 2018 10:35:52 -0800 Subject: [PATCH 48/50] Fix errors when attempting to cache files with long names or URLs --- salt/fileclient.py | 4 ++++ tests/unit/test_fileclient.py | 11 +++++++++++ 2 files changed, 15 insertions(+) diff --git a/salt/fileclient.py b/salt/fileclient.py index b6cc308107..f26f6d158a 100644 --- a/salt/fileclient.py +++ b/salt/fileclient.py @@ -41,6 +41,7 @@ from salt.ext.six.moves.urllib.parse import urlparse, urlunparse # pylint: enable=no-name-in-module,import-error log = logging.getLogger(__name__) +MAX_FILENAME_LENGTH = 255 def get_file_client(opts, pillar=False): @@ -799,6 +800,9 @@ class Client(object): else: file_name = url_data.path + if len(file_name) > MAX_FILENAME_LENGTH: + file_name = salt.utils.hashutils.sha256_digest(file_name) + return salt.utils.path_join( cachedir, 'extrn_files', diff --git a/tests/unit/test_fileclient.py b/tests/unit/test_fileclient.py index b6bd2207e0..714a7c5696 100644 --- a/tests/unit/test_fileclient.py +++ b/tests/unit/test_fileclient.py @@ -50,3 +50,14 @@ class FileclientTestCase(TestCase): with self.assertRaises(OSError): with Client(self.opts)._cache_loc('testfile') as c_ref_itr: assert c_ref_itr == '/__test__/files/base/testfile' + + def test_extrn_path_with_long_filename(self): + safe_file_name = os.path.split(Client(self.opts)._extrn_path('https://test.com/' + ('A' * 254), 'base'))[-1] + assert safe_file_name == 'A' * 254 + + oversized_file_name = os.path.split(Client(self.opts)._extrn_path('https://test.com/' + ('A' * 255), 'base'))[-1] + assert len(oversized_file_name) < 256 + assert oversized_file_name != 'A' * 255 + + oversized_file_with_query_params = os.path.split(Client(self.opts)._extrn_path('https://test.com/file?' + ('A' * 255), 'base'))[-1] + assert len(oversized_file_with_query_params) < 256 From 5a1b25b9c7b45c64a908783753d67d8da9129bb2 Mon Sep 17 00:00:00 2001 From: Ch3LL Date: Wed, 16 May 2018 13:54:19 -0400 Subject: [PATCH 49/50] Remove unnecessary setUp in states.test_user test for mac --- tests/integration/states/test_user.py | 6 ------ 1 file changed, 6 deletions(-) diff --git a/tests/integration/states/test_user.py b/tests/integration/states/test_user.py index ae9774a241..be46cbf7be 100644 --- a/tests/integration/states/test_user.py +++ b/tests/integration/states/test_user.py @@ -44,12 +44,6 @@ class UserTest(ModuleCase, SaltReturnAssertsMixin): user_name = 'salt_test' user_home = '/var/lib/salt_test' - def setUp(self): - if salt.utils.is_darwin(): - #on mac we need to add user, because there is - #no creationtime for nobody user. - add_user = self.run_function('user.add', [USER], gid=GID) - def test_user_absent(self): ret = self.run_state('user.absent', name='unpossible') self.assertSaltTrueReturn(ret) From 20b6070d54acb02671916ecdd083058384b5cf79 Mon Sep 17 00:00:00 2001 From: "Daniel A. Wozniak" Date: Wed, 16 May 2018 14:37:07 -0700 Subject: [PATCH 50/50] Default windows to m1.small for ec2-classic --- tests/integration/files/conf/cloud.profiles.d/ec2.conf | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/integration/files/conf/cloud.profiles.d/ec2.conf b/tests/integration/files/conf/cloud.profiles.d/ec2.conf index cd8aba1364..5a119df2cd 100644 --- a/tests/integration/files/conf/cloud.profiles.d/ec2.conf +++ b/tests/integration/files/conf/cloud.profiles.d/ec2.conf @@ -6,7 +6,7 @@ ec2-test: script_args: '-P -Z' ec2-win2012r2-test: provider: ec2-config - size: t2.micro + size: m1.small image: ami-eb1ecd96 smb_port: 445 win_installer: '' @@ -20,7 +20,7 @@ ec2-win2012r2-test: deploy: True ec2-win2016-test: provider: ec2-config - size: t2.micro + size: m1.small image: ami-ed14c790 smb_port: 445 win_installer: ''