mirror of
https://github.com/saltstack/salt.git
synced 2025-04-17 10:10:20 +00:00
Add more insight into failures
This commit is contained in:
parent
7721f5ca57
commit
86a86e6b58
2 changed files with 80 additions and 77 deletions
|
@ -1,4 +1,3 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
:copyright: Copyright 2013-2017 by the SaltStack Team, see AUTHORS for more details.
|
||||
:license: Apache 2.0, see LICENSE for more details.
|
||||
|
@ -9,7 +8,6 @@
|
|||
|
||||
Test support helpers
|
||||
"""
|
||||
from __future__ import absolute_import, print_function, unicode_literals
|
||||
|
||||
import base64
|
||||
import errno
|
||||
|
@ -40,7 +38,8 @@ import salt.utils.pycrypto
|
|||
import salt.utils.stringutils
|
||||
import salt.utils.versions
|
||||
from salt.ext import six
|
||||
from salt.ext.six.moves import builtins, range
|
||||
from salt.ext.six.moves import builtins
|
||||
from saltfactories.exceptions import ProcessFailed
|
||||
from saltfactories.utils.ports import get_unused_localhost_port
|
||||
from saltfactories.utils.processes.bases import ProcessResult
|
||||
from tests.support.mock import patch
|
||||
|
@ -306,7 +305,7 @@ def requires_sshd_server(caller):
|
|||
return wrap
|
||||
|
||||
|
||||
class RedirectStdStreams(object):
|
||||
class RedirectStdStreams:
|
||||
"""
|
||||
Temporarily redirect system output to file like objects.
|
||||
Default is to redirect to `os.devnull`, which just mutes output, `stdout`
|
||||
|
@ -375,7 +374,7 @@ class RedirectStdStreams(object):
|
|||
pass
|
||||
|
||||
|
||||
class TstSuiteLoggingHandler(object):
|
||||
class TstSuiteLoggingHandler:
|
||||
"""
|
||||
Simple logging handler which can be used to test if certain logging
|
||||
messages get emitted or not:
|
||||
|
@ -459,7 +458,7 @@ class TstSuiteLoggingHandler(object):
|
|||
return self.handler.release()
|
||||
|
||||
|
||||
class ForceImportErrorOn(object):
|
||||
class ForceImportErrorOn:
|
||||
"""
|
||||
This class is meant to be used in mock'ed test cases which require an
|
||||
``ImportError`` to be raised.
|
||||
|
@ -530,22 +529,19 @@ class ForceImportErrorOn(object):
|
|||
locals_ = {}
|
||||
|
||||
if level is None:
|
||||
if six.PY2:
|
||||
level = -1
|
||||
else:
|
||||
level = 0
|
||||
level = 0
|
||||
if fromlist is None:
|
||||
fromlist = []
|
||||
|
||||
if name in self.__module_names:
|
||||
importerror_fromlist = self.__module_names.get(name)
|
||||
if importerror_fromlist is None:
|
||||
raise ImportError("Forced ImportError raised for {0!r}".format(name))
|
||||
raise ImportError("Forced ImportError raised for {!r}".format(name))
|
||||
|
||||
if importerror_fromlist.intersection(set(fromlist)):
|
||||
raise ImportError(
|
||||
"Forced ImportError raised for {0!r}".format(
|
||||
"from {0} import {1}".format(name, ", ".join(fromlist))
|
||||
"Forced ImportError raised for {!r}".format(
|
||||
"from {} import {}".format(name, ", ".join(fromlist))
|
||||
)
|
||||
)
|
||||
return self.__original_import(name, globals_, locals_, fromlist, level)
|
||||
|
@ -558,7 +554,7 @@ class ForceImportErrorOn(object):
|
|||
self.restore_import_funtion()
|
||||
|
||||
|
||||
class MockWraps(object):
|
||||
class MockWraps:
|
||||
"""
|
||||
Helper class to be used with the mock library.
|
||||
To be used in the ``wraps`` keyword of ``Mock`` or ``MagicMock`` where you
|
||||
|
@ -623,7 +619,7 @@ def requires_network(only_local_network=False):
|
|||
retsock.bind(("", 18001))
|
||||
retsock.close()
|
||||
has_local_network = True
|
||||
except socket.error:
|
||||
except OSError:
|
||||
# I wonder if we just have IPV6 support?
|
||||
try:
|
||||
pubsock = socket.socket(socket.AF_INET6, socket.SOCK_STREAM)
|
||||
|
@ -635,7 +631,7 @@ def requires_network(only_local_network=False):
|
|||
retsock.bind(("", 18001))
|
||||
retsock.close()
|
||||
has_local_network = True
|
||||
except socket.error:
|
||||
except OSError:
|
||||
# Let's continue
|
||||
pass
|
||||
|
||||
|
@ -670,7 +666,7 @@ def requires_network(only_local_network=False):
|
|||
sock.connect((addr, 80))
|
||||
# We connected? Stop the loop
|
||||
break
|
||||
except socket.error:
|
||||
except OSError:
|
||||
# Let's check the next IP
|
||||
continue
|
||||
else:
|
||||
|
@ -715,7 +711,7 @@ def with_system_user(
|
|||
def wrap(cls):
|
||||
|
||||
# Let's add the user to the system.
|
||||
log.debug("Creating system user {0!r}".format(username))
|
||||
log.debug("Creating system user {!r}".format(username))
|
||||
kwargs = {"timeout": 60, "groups": groups}
|
||||
if salt.utils.platform.is_windows():
|
||||
kwargs.update({"password": password})
|
||||
|
@ -724,25 +720,25 @@ def with_system_user(
|
|||
log.debug("Failed to create system user")
|
||||
# The user was not created
|
||||
if on_existing == "skip":
|
||||
cls.skipTest("Failed to create system user {0!r}".format(username))
|
||||
cls.skipTest("Failed to create system user {!r}".format(username))
|
||||
|
||||
if on_existing == "delete":
|
||||
log.debug("Deleting the system user {0!r}".format(username))
|
||||
log.debug("Deleting the system user {!r}".format(username))
|
||||
delete_user = cls.run_function(
|
||||
"user.delete", [username, True, True]
|
||||
)
|
||||
if not delete_user:
|
||||
cls.skipTest(
|
||||
"A user named {0!r} already existed on the "
|
||||
"A user named {!r} already existed on the "
|
||||
"system and re-creating it was not possible".format(
|
||||
username
|
||||
)
|
||||
)
|
||||
log.debug("Second time creating system user {0!r}".format(username))
|
||||
log.debug("Second time creating system user {!r}".format(username))
|
||||
create_user = cls.run_function("user.add", [username], **kwargs)
|
||||
if not create_user:
|
||||
cls.skipTest(
|
||||
"A user named {0!r} already existed, was deleted "
|
||||
"A user named {!r} already existed, was deleted "
|
||||
"as requested, but re-creating it was not possible".format(
|
||||
username
|
||||
)
|
||||
|
@ -752,7 +748,7 @@ def with_system_user(
|
|||
hashed_password = password
|
||||
else:
|
||||
hashed_password = salt.utils.pycrypto.gen_hash(password=password)
|
||||
hashed_password = "'{0}'".format(hashed_password)
|
||||
hashed_password = "'{}'".format(hashed_password)
|
||||
add_pwd = cls.run_function(
|
||||
"shadow.set_password", [username, hashed_password]
|
||||
)
|
||||
|
@ -763,7 +759,7 @@ def with_system_user(
|
|||
return func(cls, username)
|
||||
except Exception as exc: # pylint: disable=W0703
|
||||
log.error(
|
||||
"Running {0!r} raised an exception: {1}".format(func, exc),
|
||||
"Running {!r} raised an exception: {}".format(func, exc),
|
||||
exc_info=True,
|
||||
)
|
||||
# Store the original exception details which will be raised
|
||||
|
@ -778,17 +774,17 @@ def with_system_user(
|
|||
if failure is None:
|
||||
log.warning(
|
||||
"Although the actual test-case did not fail, "
|
||||
"deleting the created system user {0!r} "
|
||||
"deleting the created system user {!r} "
|
||||
"afterwards did.".format(username)
|
||||
)
|
||||
else:
|
||||
log.warning(
|
||||
"The test-case failed and also did the removal"
|
||||
" of the system user {0!r}".format(username)
|
||||
" of the system user {!r}".format(username)
|
||||
)
|
||||
if failure is not None:
|
||||
# If an exception was thrown, raise it
|
||||
six.reraise(failure[0], failure[1], failure[2])
|
||||
raise failure[1].with_traceback(failure[2])
|
||||
|
||||
return wrap
|
||||
|
||||
|
@ -824,27 +820,27 @@ def with_system_group(group, on_existing="delete", delete=True):
|
|||
def wrap(cls):
|
||||
|
||||
# Let's add the user to the system.
|
||||
log.debug("Creating system group {0!r}".format(group))
|
||||
log.debug("Creating system group {!r}".format(group))
|
||||
create_group = cls.run_function("group.add", [group])
|
||||
if not create_group:
|
||||
log.debug("Failed to create system group")
|
||||
# The group was not created
|
||||
if on_existing == "skip":
|
||||
cls.skipTest("Failed to create system group {0!r}".format(group))
|
||||
cls.skipTest("Failed to create system group {!r}".format(group))
|
||||
|
||||
if on_existing == "delete":
|
||||
log.debug("Deleting the system group {0!r}".format(group))
|
||||
log.debug("Deleting the system group {!r}".format(group))
|
||||
delete_group = cls.run_function("group.delete", [group])
|
||||
if not delete_group:
|
||||
cls.skipTest(
|
||||
"A group named {0!r} already existed on the "
|
||||
"A group named {!r} already existed on the "
|
||||
"system and re-creating it was not possible".format(group)
|
||||
)
|
||||
log.debug("Second time creating system group {0!r}".format(group))
|
||||
log.debug("Second time creating system group {!r}".format(group))
|
||||
create_group = cls.run_function("group.add", [group])
|
||||
if not create_group:
|
||||
cls.skipTest(
|
||||
"A group named {0!r} already existed, was deleted "
|
||||
"A group named {!r} already existed, was deleted "
|
||||
"as requested, but re-creating it was not possible".format(
|
||||
group
|
||||
)
|
||||
|
@ -856,7 +852,7 @@ def with_system_group(group, on_existing="delete", delete=True):
|
|||
return func(cls, group)
|
||||
except Exception as exc: # pylint: disable=W0703
|
||||
log.error(
|
||||
"Running {0!r} raised an exception: {1}".format(func, exc),
|
||||
"Running {!r} raised an exception: {}".format(func, exc),
|
||||
exc_info=True,
|
||||
)
|
||||
# Store the original exception details which will be raised
|
||||
|
@ -869,17 +865,17 @@ def with_system_group(group, on_existing="delete", delete=True):
|
|||
if failure is None:
|
||||
log.warning(
|
||||
"Although the actual test-case did not fail, "
|
||||
"deleting the created system group {0!r} "
|
||||
"deleting the created system group {!r} "
|
||||
"afterwards did.".format(group)
|
||||
)
|
||||
else:
|
||||
log.warning(
|
||||
"The test-case failed and also did the removal"
|
||||
" of the system group {0!r}".format(group)
|
||||
" of the system group {!r}".format(group)
|
||||
)
|
||||
if failure is not None:
|
||||
# If an exception was thrown, raise it
|
||||
six.reraise(failure[0], failure[1], failure[2])
|
||||
raise failure[1].with_traceback(failure[2])
|
||||
|
||||
return wrap
|
||||
|
||||
|
@ -918,33 +914,33 @@ def with_system_user_and_group(username, group, on_existing="delete", delete=Tru
|
|||
def wrap(cls):
|
||||
|
||||
# Let's add the user to the system.
|
||||
log.debug("Creating system user {0!r}".format(username))
|
||||
log.debug("Creating system user {!r}".format(username))
|
||||
create_user = cls.run_function("user.add", [username])
|
||||
log.debug("Creating system group {0!r}".format(group))
|
||||
log.debug("Creating system group {!r}".format(group))
|
||||
create_group = cls.run_function("group.add", [group])
|
||||
if not create_user:
|
||||
log.debug("Failed to create system user")
|
||||
# The user was not created
|
||||
if on_existing == "skip":
|
||||
cls.skipTest("Failed to create system user {0!r}".format(username))
|
||||
cls.skipTest("Failed to create system user {!r}".format(username))
|
||||
|
||||
if on_existing == "delete":
|
||||
log.debug("Deleting the system user {0!r}".format(username))
|
||||
log.debug("Deleting the system user {!r}".format(username))
|
||||
delete_user = cls.run_function(
|
||||
"user.delete", [username, True, True]
|
||||
)
|
||||
if not delete_user:
|
||||
cls.skipTest(
|
||||
"A user named {0!r} already existed on the "
|
||||
"A user named {!r} already existed on the "
|
||||
"system and re-creating it was not possible".format(
|
||||
username
|
||||
)
|
||||
)
|
||||
log.debug("Second time creating system user {0!r}".format(username))
|
||||
log.debug("Second time creating system user {!r}".format(username))
|
||||
create_user = cls.run_function("user.add", [username])
|
||||
if not create_user:
|
||||
cls.skipTest(
|
||||
"A user named {0!r} already existed, was deleted "
|
||||
"A user named {!r} already existed, was deleted "
|
||||
"as requested, but re-creating it was not possible".format(
|
||||
username
|
||||
)
|
||||
|
@ -953,21 +949,21 @@ def with_system_user_and_group(username, group, on_existing="delete", delete=Tru
|
|||
log.debug("Failed to create system group")
|
||||
# The group was not created
|
||||
if on_existing == "skip":
|
||||
cls.skipTest("Failed to create system group {0!r}".format(group))
|
||||
cls.skipTest("Failed to create system group {!r}".format(group))
|
||||
|
||||
if on_existing == "delete":
|
||||
log.debug("Deleting the system group {0!r}".format(group))
|
||||
log.debug("Deleting the system group {!r}".format(group))
|
||||
delete_group = cls.run_function("group.delete", [group])
|
||||
if not delete_group:
|
||||
cls.skipTest(
|
||||
"A group named {0!r} already existed on the "
|
||||
"A group named {!r} already existed on the "
|
||||
"system and re-creating it was not possible".format(group)
|
||||
)
|
||||
log.debug("Second time creating system group {0!r}".format(group))
|
||||
log.debug("Second time creating system group {!r}".format(group))
|
||||
create_group = cls.run_function("group.add", [group])
|
||||
if not create_group:
|
||||
cls.skipTest(
|
||||
"A group named {0!r} already existed, was deleted "
|
||||
"A group named {!r} already existed, was deleted "
|
||||
"as requested, but re-creating it was not possible".format(
|
||||
group
|
||||
)
|
||||
|
@ -979,7 +975,7 @@ def with_system_user_and_group(username, group, on_existing="delete", delete=Tru
|
|||
return func(cls, username, group)
|
||||
except Exception as exc: # pylint: disable=W0703
|
||||
log.error(
|
||||
"Running {0!r} raised an exception: {1}".format(func, exc),
|
||||
"Running {!r} raised an exception: {}".format(func, exc),
|
||||
exc_info=True,
|
||||
)
|
||||
# Store the original exception details which will be raised
|
||||
|
@ -995,36 +991,36 @@ def with_system_user_and_group(username, group, on_existing="delete", delete=Tru
|
|||
if failure is None:
|
||||
log.warning(
|
||||
"Although the actual test-case did not fail, "
|
||||
"deleting the created system user {0!r} "
|
||||
"deleting the created system user {!r} "
|
||||
"afterwards did.".format(username)
|
||||
)
|
||||
else:
|
||||
log.warning(
|
||||
"The test-case failed and also did the removal"
|
||||
" of the system user {0!r}".format(username)
|
||||
" of the system user {!r}".format(username)
|
||||
)
|
||||
if not delete_group:
|
||||
if failure is None:
|
||||
log.warning(
|
||||
"Although the actual test-case did not fail, "
|
||||
"deleting the created system group {0!r} "
|
||||
"deleting the created system group {!r} "
|
||||
"afterwards did.".format(group)
|
||||
)
|
||||
else:
|
||||
log.warning(
|
||||
"The test-case failed and also did the removal"
|
||||
" of the system group {0!r}".format(group)
|
||||
" of the system group {!r}".format(group)
|
||||
)
|
||||
if failure is not None:
|
||||
# If an exception was thrown, raise it
|
||||
six.reraise(failure[0], failure[1], failure[2])
|
||||
raise failure[1].with_traceback(failure[2])
|
||||
|
||||
return wrap
|
||||
|
||||
return decorator
|
||||
|
||||
|
||||
class WithTempfile(object):
|
||||
class WithTempfile:
|
||||
def __init__(self, **kwargs):
|
||||
self.create = kwargs.pop("create", True)
|
||||
if "dir" not in kwargs:
|
||||
|
@ -1057,7 +1053,7 @@ class WithTempfile(object):
|
|||
with_tempfile = WithTempfile
|
||||
|
||||
|
||||
class WithTempdir(object):
|
||||
class WithTempdir:
|
||||
def __init__(self, **kwargs):
|
||||
self.create = kwargs.pop("create", True)
|
||||
if "dir" not in kwargs:
|
||||
|
@ -1227,20 +1223,20 @@ def skip_if_binaries_missing(*binaries, **kwargs):
|
|||
if kwargs:
|
||||
raise RuntimeError(
|
||||
"The only supported keyword argument is 'check_all' and "
|
||||
"'message'. Invalid keyword arguments: {0}".format(", ".join(kwargs.keys()))
|
||||
"'message'. Invalid keyword arguments: {}".format(", ".join(kwargs.keys()))
|
||||
)
|
||||
if check_all:
|
||||
for binary in binaries:
|
||||
if salt.utils.path.which(binary) is None:
|
||||
return skip(
|
||||
"{0}The {1!r} binary was not found".format(
|
||||
message and "{0}. ".format(message) or "", binary
|
||||
"{}The {!r} binary was not found".format(
|
||||
message and "{}. ".format(message) or "", binary
|
||||
)
|
||||
)
|
||||
elif salt.utils.path.which_bin(binaries) is None:
|
||||
return skip(
|
||||
"{0}None of the following binaries was found: {1}".format(
|
||||
message and "{0}. ".format(message) or "", ", ".join(binaries)
|
||||
"{}None of the following binaries was found: {}".format(
|
||||
message and "{}. ".format(message) or "", ", ".join(binaries)
|
||||
)
|
||||
)
|
||||
return _id
|
||||
|
@ -1424,7 +1420,7 @@ def random_string(prefix, size=6, uppercase=True, lowercase=True, digits=True):
|
|||
return prefix + "".join(random.choice(choices) for _ in range(size))
|
||||
|
||||
|
||||
class Webserver(object):
|
||||
class Webserver:
|
||||
"""
|
||||
Starts a tornado webserver on 127.0.0.1 on a random available port
|
||||
|
||||
|
@ -1459,7 +1455,7 @@ class Webserver(object):
|
|||
such as when enforcing authentication with the http_basic_auth
|
||||
decorator.
|
||||
"""
|
||||
if port is not None and not isinstance(port, six.integer_types):
|
||||
if port is not None and not isinstance(port, int):
|
||||
raise ValueError("port must be an integer")
|
||||
|
||||
if root is None:
|
||||
|
@ -1510,7 +1506,7 @@ class Webserver(object):
|
|||
raise RuntimeError("Webserver instance has not been started")
|
||||
err_msg = (
|
||||
"invalid path, must be either a relative path or a path "
|
||||
"within {0}".format(self.root)
|
||||
"within {}".format(self.root)
|
||||
)
|
||||
try:
|
||||
relpath = (
|
||||
|
@ -1529,7 +1525,7 @@ class Webserver(object):
|
|||
if self.port is None:
|
||||
self.port = get_unused_localhost_port()
|
||||
|
||||
self.web_root = "http://127.0.0.1:{0}".format(self.port)
|
||||
self.web_root = "http://127.0.0.1:{}".format(self.port)
|
||||
|
||||
self.server_thread = threading.Thread(target=self.target)
|
||||
self.server_thread.daemon = True
|
||||
|
@ -1542,8 +1538,8 @@ class Webserver(object):
|
|||
time.sleep(1)
|
||||
else:
|
||||
raise Exception(
|
||||
"Failed to start tornado webserver on 127.0.0.1:{0} within "
|
||||
"{1} seconds".format(self.port, self.wait)
|
||||
"Failed to start tornado webserver on 127.0.0.1:{} within "
|
||||
"{} seconds".format(self.port, self.wait)
|
||||
)
|
||||
|
||||
def stop(self):
|
||||
|
@ -1603,12 +1599,12 @@ def dedent(text, linesep=os.linesep):
|
|||
clean_text = linesep.join(unicode_text.splitlines())
|
||||
if unicode_text.endswith("\n"):
|
||||
clean_text += linesep
|
||||
if not isinstance(text, six.text_type):
|
||||
if not isinstance(text, str):
|
||||
return salt.utils.stringutils.to_bytes(clean_text)
|
||||
return clean_text
|
||||
|
||||
|
||||
class PatchedEnviron(object):
|
||||
class PatchedEnviron:
|
||||
def __init__(self, **kwargs):
|
||||
self.cleanup_keys = kwargs.pop("__cleanup__", ())
|
||||
self.kwargs = kwargs
|
||||
|
@ -1627,9 +1623,9 @@ class PatchedEnviron(object):
|
|||
clean_kwargs = {}
|
||||
for k in self.kwargs:
|
||||
key = k
|
||||
if isinstance(key, six.text_type):
|
||||
if isinstance(key, str):
|
||||
key = key.encode("utf-8")
|
||||
if isinstance(self.kwargs[k], six.text_type):
|
||||
if isinstance(self.kwargs[k], str):
|
||||
kwargs[k] = kwargs[k].encode("utf-8")
|
||||
clean_kwargs[key] = kwargs[k]
|
||||
self.kwargs = clean_kwargs
|
||||
|
@ -1645,7 +1641,7 @@ class PatchedEnviron(object):
|
|||
patched_environ = PatchedEnviron
|
||||
|
||||
|
||||
class VirtualEnv(object):
|
||||
class VirtualEnv:
|
||||
def __init__(self, venv_dir=None):
|
||||
self.venv_dir = venv_dir or tempfile.mkdtemp(dir=RUNTIME_VARS.TMP)
|
||||
if salt.utils.platform.is_windows():
|
||||
|
@ -1677,7 +1673,16 @@ class VirtualEnv(object):
|
|||
ret = ProcessResult(proc.returncode, proc.stdout, proc.stderr, proc.args)
|
||||
log.debug(ret)
|
||||
if check is True:
|
||||
proc.check_returncode()
|
||||
try:
|
||||
proc.check_returncode()
|
||||
except subprocess.CalledProcessError:
|
||||
raise ProcessFailed(
|
||||
"Command failed return code check",
|
||||
cmdline=proc.args,
|
||||
stdout=proc.stdout,
|
||||
stderr=proc.stderr,
|
||||
exitcode=proc.returncode,
|
||||
)
|
||||
return ret
|
||||
|
||||
def _get_real_python(self):
|
||||
|
|
|
@ -1,9 +1,7 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
tests.unit.setup.test_install
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
"""
|
||||
from __future__ import absolute_import, print_function, unicode_literals
|
||||
|
||||
import json
|
||||
import logging
|
||||
|
|
Loading…
Add table
Reference in a new issue