mirror of
https://github.com/saltstack/salt.git
synced 2025-04-16 09:40:20 +00:00
Bump pytest-salt-factories to 0.92.x
This commit is contained in:
parent
3ab6b9dca2
commit
0aba49c7d3
47 changed files with 2067 additions and 2752 deletions
|
@ -681,6 +681,7 @@ allowed-3rd-party-modules=msgpack,
|
|||
libcloud,
|
||||
zmq,
|
||||
pytest,
|
||||
attr,
|
||||
setuptools,
|
||||
pytestsalt,
|
||||
saltfactories,
|
||||
|
|
10
noxfile.py
10
noxfile.py
|
@ -932,7 +932,15 @@ def _pytest(session, coverage, cmd_args):
|
|||
try:
|
||||
if coverage is True:
|
||||
_run_with_coverage(
|
||||
session, "python", "-m", "coverage", "run", "-m", "pytest", *cmd_args
|
||||
session,
|
||||
"python",
|
||||
"-m",
|
||||
"coverage",
|
||||
"run",
|
||||
"-m",
|
||||
"pytest",
|
||||
"--showlocals",
|
||||
*cmd_args
|
||||
)
|
||||
else:
|
||||
session.run("python", "-m", "pytest", *cmd_args, env=env)
|
||||
|
|
|
@ -2,6 +2,6 @@ mock >= 3.0.0
|
|||
# PyTest
|
||||
pytest >= 6.0.1
|
||||
pytest-salt
|
||||
pytest-salt-factories >= 0.11.4
|
||||
pytest-salt-factories >= 0.92.0
|
||||
pytest-tempdir >= 2019.10.12
|
||||
pytest-helpers-namespace >= 2019.1.8
|
||||
|
|
|
@ -90,7 +90,7 @@ pyopenssl==19.0.0
|
|||
pyparsing==2.4.5 # via junos-eznc, packaging
|
||||
pyserial==3.4 # via junos-eznc
|
||||
pytest-helpers-namespace==2019.1.8
|
||||
pytest-salt-factories==0.11.4
|
||||
pytest-salt-factories==0.92.0
|
||||
pytest-salt==2020.1.27
|
||||
pytest-tempdir==2019.10.12
|
||||
pytest==6.0.1
|
||||
|
|
|
@ -90,7 +90,7 @@ pyopenssl==19.0.0
|
|||
pyparsing==2.4.5 # via junos-eznc, packaging
|
||||
pyserial==3.4 # via junos-eznc
|
||||
pytest-helpers-namespace==2019.1.8
|
||||
pytest-salt-factories==0.11.4
|
||||
pytest-salt-factories==0.92.0
|
||||
pytest-salt==2020.1.27
|
||||
pytest-tempdir==2019.10.12
|
||||
pytest==6.0.1
|
||||
|
|
|
@ -181,7 +181,7 @@ pyopenssl==19.0.0
|
|||
pyparsing==2.4.5 # via junos-eznc, packaging
|
||||
pyserial==3.4 # via junos-eznc
|
||||
pytest-helpers-namespace==2019.1.8
|
||||
pytest-salt-factories==0.11.4
|
||||
pytest-salt-factories==0.92.0
|
||||
pytest-salt==2020.1.27
|
||||
pytest-tempdir==2019.10.12
|
||||
pytest==6.0.1
|
||||
|
|
|
@ -83,7 +83,7 @@ pymysql==0.9.3
|
|||
pyopenssl==19.0.0
|
||||
pyparsing==2.4.5 # via packaging
|
||||
pytest-helpers-namespace==2019.1.8
|
||||
pytest-salt-factories==0.11.4
|
||||
pytest-salt-factories==0.92.0
|
||||
pytest-salt==2020.1.27
|
||||
pytest-tempdir==2019.10.12
|
||||
pytest==6.0.1
|
||||
|
|
|
@ -95,7 +95,7 @@ pyopenssl==19.0.0
|
|||
pyparsing==2.4.5 # via junos-eznc, packaging
|
||||
pyserial==3.4 # via junos-eznc, netmiko
|
||||
pytest-helpers-namespace==2019.1.8
|
||||
pytest-salt-factories==0.11.4
|
||||
pytest-salt-factories==0.92.0
|
||||
pytest-salt==2020.1.27
|
||||
pytest-tempdir==2019.10.12
|
||||
pytest==6.0.1
|
||||
|
|
|
@ -95,7 +95,7 @@ pyopenssl==19.0.0
|
|||
pyparsing==2.4.5 # via junos-eznc, packaging
|
||||
pyserial==3.4 # via junos-eznc, netmiko
|
||||
pytest-helpers-namespace==2019.1.8
|
||||
pytest-salt-factories==0.11.4
|
||||
pytest-salt-factories==0.92.0
|
||||
pytest-salt==2020.1.27
|
||||
pytest-tempdir==2019.10.12
|
||||
pytest==6.0.1
|
||||
|
|
|
@ -185,7 +185,7 @@ pyopenssl==19.0.0
|
|||
pyparsing==2.4.5 # via junos-eznc, packaging
|
||||
pyserial==3.4 # via junos-eznc, netmiko
|
||||
pytest-helpers-namespace==2019.1.8
|
||||
pytest-salt-factories==0.11.4
|
||||
pytest-salt-factories==0.92.0
|
||||
pytest-salt==2020.1.27
|
||||
pytest-tempdir==2019.10.12
|
||||
pytest==6.0.1
|
||||
|
|
|
@ -82,7 +82,7 @@ pymysql==0.9.3
|
|||
pyopenssl==19.0.0
|
||||
pyparsing==2.4.5 # via packaging
|
||||
pytest-helpers-namespace==2019.1.8
|
||||
pytest-salt-factories==0.11.4
|
||||
pytest-salt-factories==0.92.0
|
||||
pytest-salt==2020.1.27
|
||||
pytest-tempdir==2019.10.12
|
||||
pytest==6.0.1
|
||||
|
|
|
@ -93,7 +93,7 @@ pyopenssl==19.0.0
|
|||
pyparsing==2.4.5 # via junos-eznc, packaging
|
||||
pyserial==3.4 # via junos-eznc, netmiko
|
||||
pytest-helpers-namespace==2019.1.8
|
||||
pytest-salt-factories==0.11.4
|
||||
pytest-salt-factories==0.92.0
|
||||
pytest-salt==2020.1.27
|
||||
pytest-tempdir==2019.10.12
|
||||
pytest==6.0.1
|
||||
|
|
|
@ -94,7 +94,7 @@ pyopenssl==19.0.0
|
|||
pyparsing==2.4.5 # via junos-eznc, packaging
|
||||
pyserial==3.4 # via junos-eznc, netmiko
|
||||
pytest-helpers-namespace==2019.1.8
|
||||
pytest-salt-factories==0.11.4
|
||||
pytest-salt-factories==0.92.0
|
||||
pytest-salt==2020.1.27
|
||||
pytest-tempdir==2019.10.12
|
||||
pytest==6.0.1
|
||||
|
|
|
@ -184,7 +184,7 @@ pyopenssl==19.0.0
|
|||
pyparsing==2.4.5 # via junos-eznc, packaging
|
||||
pyserial==3.4 # via junos-eznc, netmiko
|
||||
pytest-helpers-namespace==2019.1.8
|
||||
pytest-salt-factories==0.11.4
|
||||
pytest-salt-factories==0.92.0
|
||||
pytest-salt==2020.1.27
|
||||
pytest-tempdir==2019.10.12
|
||||
pytest==6.0.1
|
||||
|
|
|
@ -80,7 +80,7 @@ pymysql==0.9.3
|
|||
pyopenssl==19.0.0
|
||||
pyparsing==2.4.5 # via packaging
|
||||
pytest-helpers-namespace==2019.1.8
|
||||
pytest-salt-factories==0.11.4
|
||||
pytest-salt-factories==0.92.0
|
||||
pytest-salt==2020.1.27
|
||||
pytest-tempdir==2019.10.12
|
||||
pytest==6.0.1
|
||||
|
|
|
@ -92,7 +92,7 @@ pyopenssl==19.0.0
|
|||
pyparsing==2.4.5 # via junos-eznc, packaging
|
||||
pyserial==3.4 # via junos-eznc, netmiko
|
||||
pytest-helpers-namespace==2019.1.8
|
||||
pytest-salt-factories==0.11.4
|
||||
pytest-salt-factories==0.92.0
|
||||
pytest-salt==2020.1.27
|
||||
pytest-tempdir==2019.10.12
|
||||
pytest==6.0.1
|
||||
|
|
|
@ -93,7 +93,7 @@ pyopenssl==19.0.0
|
|||
pyparsing==2.4.5 # via junos-eznc, packaging
|
||||
pyserial==3.4 # via junos-eznc, netmiko
|
||||
pytest-helpers-namespace==2019.1.8
|
||||
pytest-salt-factories==0.11.4
|
||||
pytest-salt-factories==0.92.0
|
||||
pytest-salt==2020.1.27
|
||||
pytest-tempdir==2019.10.12
|
||||
pytest==6.0.1
|
||||
|
|
|
@ -184,7 +184,7 @@ pyopenssl==19.0.0
|
|||
pyparsing==2.4.5 # via junos-eznc, packaging
|
||||
pyserial==3.4 # via junos-eznc, netmiko
|
||||
pytest-helpers-namespace==2019.1.8
|
||||
pytest-salt-factories==0.11.4
|
||||
pytest-salt-factories==0.92.0
|
||||
pytest-salt==2020.1.27
|
||||
pytest-tempdir==2019.10.12
|
||||
pytest==6.0.1
|
||||
|
|
|
@ -92,7 +92,7 @@ pyopenssl==19.0.0
|
|||
pyparsing==2.4.5 # via junos-eznc, packaging
|
||||
pyserial==3.4 # via junos-eznc, netmiko
|
||||
pytest-helpers-namespace==2019.1.8
|
||||
pytest-salt-factories==0.11.4
|
||||
pytest-salt-factories==0.92.0
|
||||
pytest-salt==2020.1.27
|
||||
pytest-tempdir==2019.10.12
|
||||
pytest==6.0.1
|
||||
|
|
|
@ -93,7 +93,7 @@ pyopenssl==19.0.0
|
|||
pyparsing==2.4.5 # via junos-eznc, packaging
|
||||
pyserial==3.4 # via junos-eznc, netmiko
|
||||
pytest-helpers-namespace==2019.1.8
|
||||
pytest-salt-factories==0.11.4
|
||||
pytest-salt-factories==0.92.0
|
||||
pytest-salt==2020.1.27
|
||||
pytest-tempdir==2019.10.12
|
||||
pytest==6.0.1
|
||||
|
|
|
@ -184,7 +184,7 @@ pyopenssl==19.0.0
|
|||
pyparsing==2.4.5 # via junos-eznc, packaging
|
||||
pyserial==3.4 # via junos-eznc, netmiko
|
||||
pytest-helpers-namespace==2019.1.8
|
||||
pytest-salt-factories==0.11.4
|
||||
pytest-salt-factories==0.92.0
|
||||
pytest-salt==2020.1.27
|
||||
pytest-tempdir==2019.10.12
|
||||
pytest==6.0.1
|
||||
|
|
|
@ -15,7 +15,10 @@ import os
|
|||
import pathlib
|
||||
import pprint
|
||||
import re
|
||||
import shutil
|
||||
import stat
|
||||
import sys
|
||||
import textwrap
|
||||
from functools import partial, wraps
|
||||
from unittest import TestCase # pylint: disable=blacklisted-module
|
||||
|
||||
|
@ -33,11 +36,14 @@ import salt.utils.platform
|
|||
import salt.utils.win_functions
|
||||
import saltfactories.utils.compat
|
||||
from salt.serializers import yaml
|
||||
from tests.support.helpers import PRE_PYTEST_SKIP_OR_NOT, PRE_PYTEST_SKIP_REASON
|
||||
from tests.support.pytest.fixtures import * # pylint: disable=unused-wildcard-import
|
||||
from salt.utils.immutabletypes import freeze
|
||||
from tests.support.helpers import (
|
||||
PRE_PYTEST_SKIP_OR_NOT,
|
||||
PRE_PYTEST_SKIP_REASON,
|
||||
get_virtualenv_binary_path,
|
||||
)
|
||||
from tests.support.pytest.helpers import * # pylint: disable=unused-wildcard-import
|
||||
from tests.support.runtests import RUNTIME_VARS
|
||||
from tests.support.saltfactories_compat import LogServer
|
||||
from tests.support.sminion import check_required_sminion_attributes, create_sminion
|
||||
|
||||
TESTS_DIR = pathlib.Path(__file__).resolve().parent
|
||||
|
@ -232,39 +238,15 @@ def pytest_configure(config):
|
|||
config.addinivalue_line(
|
||||
"markers", "windows_whitelisted: Mark test as whitelisted to run under Windows"
|
||||
)
|
||||
config.addinivalue_line(
|
||||
"markers", "requires_sshd_server: Mark test that require an SSH server running"
|
||||
)
|
||||
# Make sure the test suite "knows" this is a pytest test run
|
||||
RUNTIME_VARS.PYTEST_SESSION = True
|
||||
|
||||
# "Flag" the slotTest decorator if we're skipping slow tests or not
|
||||
os.environ["SLOW_TESTS"] = str(config.getoption("--run-slow"))
|
||||
|
||||
# If PyTest has no logging configured, default to ERROR level
|
||||
levels = [logging.ERROR]
|
||||
logging_plugin = config.pluginmanager.get_plugin("logging-plugin")
|
||||
try:
|
||||
level = logging_plugin.log_cli_handler.level
|
||||
if level is not None:
|
||||
levels.append(level)
|
||||
except AttributeError:
|
||||
# PyTest CLI logging not configured
|
||||
pass
|
||||
try:
|
||||
level = logging_plugin.log_file_level
|
||||
if level is not None:
|
||||
levels.append(level)
|
||||
except AttributeError:
|
||||
# PyTest Log File logging not configured
|
||||
pass
|
||||
|
||||
if logging.NOTSET in levels:
|
||||
# We don't want the NOTSET level on the levels
|
||||
levels.pop(levels.index(logging.NOTSET))
|
||||
|
||||
log_level = logging.getLevelName(min(levels))
|
||||
|
||||
log_server = LogServer(log_level=log_level)
|
||||
config.pluginmanager.register(log_server, "salt-saltfactories-log-server")
|
||||
|
||||
|
||||
# <---- Register Markers ---------------------------------------------------------------------------------------------
|
||||
|
||||
|
@ -464,29 +446,6 @@ def pytest_runtest_protocol(item, nextitem):
|
|||
del used_fixture_defs
|
||||
|
||||
|
||||
@pytest.hookimpl(tryfirst=True)
|
||||
def pytest_sessionstart(session):
|
||||
log_server = session.config.pluginmanager.get_plugin(
|
||||
"salt-saltfactories-log-server"
|
||||
)
|
||||
log_server.start()
|
||||
|
||||
|
||||
@pytest.hookimpl(trylast=True)
|
||||
def pytest_sessionfinish(session):
|
||||
log_server = session.config.pluginmanager.get_plugin(
|
||||
"salt-saltfactories-log-server"
|
||||
)
|
||||
log_server.stop()
|
||||
|
||||
|
||||
@pytest.fixture(scope="session")
|
||||
def log_server():
|
||||
"""
|
||||
Just overriding the fixture
|
||||
"""
|
||||
|
||||
|
||||
# <---- PyTest Tweaks ------------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
|
@ -509,6 +468,13 @@ def pytest_runtest_setup(item):
|
|||
item._skipped_by_mark = True
|
||||
pytest.skip("Slow tests are disabled!")
|
||||
|
||||
requires_sshd_server_marker = item.get_closest_marker("requires_sshd_server")
|
||||
if requires_sshd_server_marker is not None:
|
||||
if not item.config.getoption("--ssh-tests"):
|
||||
item._skipped_by_mark = True
|
||||
pytest.skip("SSH tests are disabled, pass '--ssh-tests' to enable them.")
|
||||
item.fixturenames.append("sshd_server")
|
||||
|
||||
requires_salt_modules_marker = item.get_closest_marker("requires_salt_modules")
|
||||
if requires_salt_modules_marker is not None:
|
||||
required_salt_modules = requires_salt_modules_marker.args
|
||||
|
@ -630,29 +596,561 @@ def groups_collection_modifyitems(config, items):
|
|||
|
||||
# ----- Fixtures Overrides ------------------------------------------------------------------------------------------>
|
||||
@pytest.fixture(scope="session")
|
||||
def salt_factories_config(request):
|
||||
def salt_factories_config():
|
||||
"""
|
||||
Return a dictionary with the keyworkd arguments for SaltFactoriesManager
|
||||
Return a dictionary with the keyworkd arguments for FactoriesManager
|
||||
"""
|
||||
log_server = request.config.pluginmanager.get_plugin(
|
||||
"salt-saltfactories-log-server"
|
||||
)
|
||||
return {
|
||||
"executable": sys.executable,
|
||||
"code_dir": str(CODE_DIR),
|
||||
"inject_coverage": MAYBE_RUN_COVERAGE,
|
||||
"inject_sitecustomize": MAYBE_RUN_COVERAGE,
|
||||
"start_timeout": 120
|
||||
if (os.environ.get("JENKINS_URL") or os.environ.get("CI"))
|
||||
else 60,
|
||||
"log_server_host": log_server.log_host,
|
||||
"log_server_port": log_server.log_port,
|
||||
"log_server_level": log_server.log_level,
|
||||
}
|
||||
|
||||
|
||||
# <---- Pytest Helpers -----------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
# ----- Salt Factories ---------------------------------------------------------------------------------------------->
|
||||
@pytest.fixture(scope="session")
|
||||
def integration_files_dir(salt_factories):
|
||||
"""
|
||||
Fixture which returns the salt integration files directory path.
|
||||
Creates the directory if it does not yet exist.
|
||||
"""
|
||||
dirname = salt_factories.root_dir / "integration-files"
|
||||
dirname.mkdir(exist_ok=True)
|
||||
return dirname
|
||||
|
||||
|
||||
@pytest.fixture(scope="session")
|
||||
def state_tree_root_dir(integration_files_dir):
|
||||
"""
|
||||
Fixture which returns the salt state tree root directory path.
|
||||
Creates the directory if it does not yet exist.
|
||||
"""
|
||||
dirname = integration_files_dir / "state-tree"
|
||||
dirname.mkdir(exist_ok=True)
|
||||
return dirname
|
||||
|
||||
|
||||
@pytest.fixture(scope="session")
|
||||
def pillar_tree_root_dir(integration_files_dir):
|
||||
"""
|
||||
Fixture which returns the salt pillar tree root directory path.
|
||||
Creates the directory if it does not yet exist.
|
||||
"""
|
||||
dirname = integration_files_dir / "pillar-tree"
|
||||
dirname.mkdir(exist_ok=True)
|
||||
return dirname
|
||||
|
||||
|
||||
@pytest.fixture(scope="session")
|
||||
def base_env_state_tree_root_dir(state_tree_root_dir):
|
||||
"""
|
||||
Fixture which returns the salt base environment state tree directory path.
|
||||
Creates the directory if it does not yet exist.
|
||||
"""
|
||||
dirname = state_tree_root_dir / "base"
|
||||
dirname.mkdir(exist_ok=True)
|
||||
RUNTIME_VARS.TMP_STATE_TREE = str(dirname.resolve())
|
||||
RUNTIME_VARS.TMP_BASEENV_STATE_TREE = RUNTIME_VARS.TMP_STATE_TREE
|
||||
return dirname
|
||||
|
||||
|
||||
@pytest.fixture(scope="session")
|
||||
def prod_env_state_tree_root_dir(state_tree_root_dir):
|
||||
"""
|
||||
Fixture which returns the salt prod environment state tree directory path.
|
||||
Creates the directory if it does not yet exist.
|
||||
"""
|
||||
dirname = state_tree_root_dir / "prod"
|
||||
dirname.mkdir(exist_ok=True)
|
||||
RUNTIME_VARS.TMP_PRODENV_STATE_TREE = str(dirname.resolve())
|
||||
return dirname
|
||||
|
||||
|
||||
@pytest.fixture(scope="session")
|
||||
def base_env_pillar_tree_root_dir(pillar_tree_root_dir):
|
||||
"""
|
||||
Fixture which returns the salt base environment pillar tree directory path.
|
||||
Creates the directory if it does not yet exist.
|
||||
"""
|
||||
dirname = pillar_tree_root_dir / "base"
|
||||
dirname.mkdir(exist_ok=True)
|
||||
RUNTIME_VARS.TMP_PILLAR_TREE = str(dirname.resolve())
|
||||
RUNTIME_VARS.TMP_BASEENV_PILLAR_TREE = RUNTIME_VARS.TMP_PILLAR_TREE
|
||||
return dirname
|
||||
|
||||
|
||||
@pytest.fixture(scope="session")
|
||||
def prod_env_pillar_tree_root_dir(pillar_tree_root_dir):
|
||||
"""
|
||||
Fixture which returns the salt prod environment pillar tree directory path.
|
||||
Creates the directory if it does not yet exist.
|
||||
"""
|
||||
dirname = pillar_tree_root_dir / "prod"
|
||||
dirname.mkdir(exist_ok=True)
|
||||
RUNTIME_VARS.TMP_PRODENV_PILLAR_TREE = str(dirname.resolve())
|
||||
return dirname
|
||||
|
||||
|
||||
@pytest.fixture(scope="session")
|
||||
def salt_syndic_master_factory(
|
||||
request,
|
||||
salt_factories,
|
||||
base_env_state_tree_root_dir,
|
||||
base_env_pillar_tree_root_dir,
|
||||
prod_env_state_tree_root_dir,
|
||||
prod_env_pillar_tree_root_dir,
|
||||
):
|
||||
root_dir = salt_factories.get_root_dir_for_daemon("syndic_master")
|
||||
conf_dir = root_dir / "conf"
|
||||
conf_dir.mkdir(exist_ok=True)
|
||||
|
||||
with salt.utils.files.fopen(
|
||||
os.path.join(RUNTIME_VARS.CONF_DIR, "syndic_master")
|
||||
) as rfh:
|
||||
config_defaults = yaml.deserialize(rfh.read())
|
||||
|
||||
tests_known_hosts_file = str(root_dir / "salt_ssh_known_hosts")
|
||||
with salt.utils.files.fopen(tests_known_hosts_file, "w") as known_hosts:
|
||||
known_hosts.write("")
|
||||
|
||||
config_defaults["root_dir"] = str(root_dir)
|
||||
config_defaults["known_hosts_file"] = tests_known_hosts_file
|
||||
config_defaults["syndic_master"] = "localhost"
|
||||
config_defaults["transport"] = request.config.getoption("--transport")
|
||||
|
||||
config_overrides = {}
|
||||
ext_pillar = []
|
||||
if salt.utils.platform.is_windows():
|
||||
ext_pillar.append(
|
||||
{"cmd_yaml": "type {}".format(os.path.join(RUNTIME_VARS.FILES, "ext.yaml"))}
|
||||
)
|
||||
else:
|
||||
ext_pillar.append(
|
||||
{"cmd_yaml": "cat {}".format(os.path.join(RUNTIME_VARS.FILES, "ext.yaml"))}
|
||||
)
|
||||
|
||||
# We need to copy the extension modules into the new master root_dir or
|
||||
# it will be prefixed by it
|
||||
extension_modules_path = str(root_dir / "extension_modules")
|
||||
if not os.path.exists(extension_modules_path):
|
||||
shutil.copytree(
|
||||
os.path.join(RUNTIME_VARS.FILES, "extension_modules"),
|
||||
extension_modules_path,
|
||||
)
|
||||
|
||||
# Copy the autosign_file to the new master root_dir
|
||||
autosign_file_path = str(root_dir / "autosign_file")
|
||||
shutil.copyfile(
|
||||
os.path.join(RUNTIME_VARS.FILES, "autosign_file"), autosign_file_path
|
||||
)
|
||||
# all read, only owner write
|
||||
autosign_file_permissions = (
|
||||
stat.S_IRUSR | stat.S_IRGRP | stat.S_IROTH | stat.S_IWUSR
|
||||
)
|
||||
os.chmod(autosign_file_path, autosign_file_permissions)
|
||||
|
||||
config_overrides.update(
|
||||
{
|
||||
"ext_pillar": ext_pillar,
|
||||
"extension_modules": extension_modules_path,
|
||||
"file_roots": {
|
||||
"base": [
|
||||
str(base_env_state_tree_root_dir),
|
||||
os.path.join(RUNTIME_VARS.FILES, "file", "base"),
|
||||
],
|
||||
# Alternate root to test __env__ choices
|
||||
"prod": [
|
||||
str(prod_env_state_tree_root_dir),
|
||||
os.path.join(RUNTIME_VARS.FILES, "file", "prod"),
|
||||
],
|
||||
},
|
||||
"pillar_roots": {
|
||||
"base": [
|
||||
str(base_env_pillar_tree_root_dir),
|
||||
os.path.join(RUNTIME_VARS.FILES, "pillar", "base"),
|
||||
],
|
||||
"prod": [str(prod_env_pillar_tree_root_dir)],
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
factory = salt_factories.get_salt_master_daemon(
|
||||
"syndic_master",
|
||||
order_masters=True,
|
||||
config_defaults=config_defaults,
|
||||
config_overrides=config_overrides,
|
||||
extra_cli_arguments_after_first_start_failure=["--log-level=debug"],
|
||||
)
|
||||
return factory
|
||||
|
||||
|
||||
@pytest.fixture(scope="session")
|
||||
def salt_syndic_factory(salt_factories, salt_syndic_master_factory):
|
||||
config_defaults = {"master": None, "minion": None, "syndic": None}
|
||||
with salt.utils.files.fopen(os.path.join(RUNTIME_VARS.CONF_DIR, "syndic")) as rfh:
|
||||
opts = yaml.deserialize(rfh.read())
|
||||
|
||||
opts["hosts.file"] = os.path.join(RUNTIME_VARS.TMP, "hosts")
|
||||
opts["aliases.file"] = os.path.join(RUNTIME_VARS.TMP, "aliases")
|
||||
opts["transport"] = salt_syndic_master_factory.config["transport"]
|
||||
config_defaults["syndic"] = opts
|
||||
factory = salt_syndic_master_factory.get_salt_syndic_daemon(
|
||||
"syndic",
|
||||
config_defaults=config_defaults,
|
||||
extra_cli_arguments_after_first_start_failure=["--log-level=debug"],
|
||||
)
|
||||
return factory
|
||||
|
||||
|
||||
@pytest.fixture(scope="session")
|
||||
def salt_master_factory(
|
||||
salt_factories,
|
||||
salt_syndic_master_factory,
|
||||
base_env_state_tree_root_dir,
|
||||
base_env_pillar_tree_root_dir,
|
||||
prod_env_state_tree_root_dir,
|
||||
prod_env_pillar_tree_root_dir,
|
||||
):
|
||||
root_dir = salt_factories.get_root_dir_for_daemon("master")
|
||||
conf_dir = root_dir / "conf"
|
||||
conf_dir.mkdir(exist_ok=True)
|
||||
|
||||
with salt.utils.files.fopen(os.path.join(RUNTIME_VARS.CONF_DIR, "master")) as rfh:
|
||||
config_defaults = yaml.deserialize(rfh.read())
|
||||
|
||||
tests_known_hosts_file = str(root_dir / "salt_ssh_known_hosts")
|
||||
with salt.utils.files.fopen(tests_known_hosts_file, "w") as known_hosts:
|
||||
known_hosts.write("")
|
||||
|
||||
config_defaults["root_dir"] = str(root_dir)
|
||||
config_defaults["known_hosts_file"] = tests_known_hosts_file
|
||||
config_defaults["syndic_master"] = "localhost"
|
||||
config_defaults["transport"] = salt_syndic_master_factory.config["transport"]
|
||||
config_defaults["reactor"] = [
|
||||
{"salt/test/reactor": [os.path.join(RUNTIME_VARS.FILES, "reactor-test.sls")]}
|
||||
]
|
||||
|
||||
config_overrides = {}
|
||||
ext_pillar = []
|
||||
if salt.utils.platform.is_windows():
|
||||
ext_pillar.append(
|
||||
{"cmd_yaml": "type {}".format(os.path.join(RUNTIME_VARS.FILES, "ext.yaml"))}
|
||||
)
|
||||
else:
|
||||
ext_pillar.append(
|
||||
{"cmd_yaml": "cat {}".format(os.path.join(RUNTIME_VARS.FILES, "ext.yaml"))}
|
||||
)
|
||||
ext_pillar.append(
|
||||
{
|
||||
"file_tree": {
|
||||
"root_dir": os.path.join(RUNTIME_VARS.PILLAR_DIR, "base", "file_tree"),
|
||||
"follow_dir_links": False,
|
||||
"keep_newline": True,
|
||||
}
|
||||
}
|
||||
)
|
||||
config_overrides["pillar_opts"] = True
|
||||
|
||||
# We need to copy the extension modules into the new master root_dir or
|
||||
# it will be prefixed by it
|
||||
extension_modules_path = str(root_dir / "extension_modules")
|
||||
if not os.path.exists(extension_modules_path):
|
||||
shutil.copytree(
|
||||
os.path.join(RUNTIME_VARS.FILES, "extension_modules"),
|
||||
extension_modules_path,
|
||||
)
|
||||
|
||||
# Copy the autosign_file to the new master root_dir
|
||||
autosign_file_path = str(root_dir / "autosign_file")
|
||||
shutil.copyfile(
|
||||
os.path.join(RUNTIME_VARS.FILES, "autosign_file"), autosign_file_path
|
||||
)
|
||||
# all read, only owner write
|
||||
autosign_file_permissions = (
|
||||
stat.S_IRUSR | stat.S_IRGRP | stat.S_IROTH | stat.S_IWUSR
|
||||
)
|
||||
os.chmod(autosign_file_path, autosign_file_permissions)
|
||||
|
||||
config_overrides.update(
|
||||
{
|
||||
"ext_pillar": ext_pillar,
|
||||
"extension_modules": extension_modules_path,
|
||||
"file_roots": {
|
||||
"base": [
|
||||
str(base_env_state_tree_root_dir),
|
||||
os.path.join(RUNTIME_VARS.FILES, "file", "base"),
|
||||
],
|
||||
# Alternate root to test __env__ choices
|
||||
"prod": [
|
||||
str(prod_env_state_tree_root_dir),
|
||||
os.path.join(RUNTIME_VARS.FILES, "file", "prod"),
|
||||
],
|
||||
},
|
||||
"pillar_roots": {
|
||||
"base": [
|
||||
str(base_env_pillar_tree_root_dir),
|
||||
os.path.join(RUNTIME_VARS.FILES, "pillar", "base"),
|
||||
],
|
||||
"prod": [str(prod_env_pillar_tree_root_dir)],
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
# Let's copy over the test cloud config files and directories into the running master config directory
|
||||
for entry in os.listdir(RUNTIME_VARS.CONF_DIR):
|
||||
if not entry.startswith("cloud"):
|
||||
continue
|
||||
source = os.path.join(RUNTIME_VARS.CONF_DIR, entry)
|
||||
dest = str(conf_dir / entry)
|
||||
if os.path.isdir(source):
|
||||
shutil.copytree(source, dest)
|
||||
else:
|
||||
shutil.copyfile(source, dest)
|
||||
|
||||
factory = salt_syndic_master_factory.get_salt_master_daemon(
|
||||
"master",
|
||||
config_defaults=config_defaults,
|
||||
config_overrides=config_overrides,
|
||||
extra_cli_arguments_after_first_start_failure=["--log-level=debug"],
|
||||
)
|
||||
return factory
|
||||
|
||||
|
||||
@pytest.fixture(scope="session")
|
||||
def salt_minion_factory(salt_master_factory):
|
||||
with salt.utils.files.fopen(os.path.join(RUNTIME_VARS.CONF_DIR, "minion")) as rfh:
|
||||
config_defaults = yaml.deserialize(rfh.read())
|
||||
config_defaults["hosts.file"] = os.path.join(RUNTIME_VARS.TMP, "hosts")
|
||||
config_defaults["aliases.file"] = os.path.join(RUNTIME_VARS.TMP, "aliases")
|
||||
config_defaults["transport"] = salt_master_factory.config["transport"]
|
||||
|
||||
config_overrides = {
|
||||
"file_roots": salt_master_factory.config["file_roots"].copy(),
|
||||
"pillar_roots": salt_master_factory.config["pillar_roots"].copy(),
|
||||
}
|
||||
|
||||
virtualenv_binary = get_virtualenv_binary_path()
|
||||
if virtualenv_binary:
|
||||
config_overrides["venv_bin"] = virtualenv_binary
|
||||
factory = salt_master_factory.get_salt_minion_daemon(
|
||||
"minion",
|
||||
config_defaults=config_defaults,
|
||||
config_overrides=config_overrides,
|
||||
extra_cli_arguments_after_first_start_failure=["--log-level=debug"],
|
||||
)
|
||||
factory.register_after_terminate_callback(
|
||||
pytest.helpers.remove_stale_minion_key, salt_master_factory, factory.id
|
||||
)
|
||||
return factory
|
||||
|
||||
|
||||
@pytest.fixture(scope="session")
|
||||
def salt_sub_minion_factory(salt_master_factory):
|
||||
with salt.utils.files.fopen(
|
||||
os.path.join(RUNTIME_VARS.CONF_DIR, "sub_minion")
|
||||
) as rfh:
|
||||
config_defaults = yaml.deserialize(rfh.read())
|
||||
config_defaults["hosts.file"] = os.path.join(RUNTIME_VARS.TMP, "hosts")
|
||||
config_defaults["aliases.file"] = os.path.join(RUNTIME_VARS.TMP, "aliases")
|
||||
config_defaults["transport"] = salt_master_factory.config["transport"]
|
||||
|
||||
config_overrides = {
|
||||
"file_roots": salt_master_factory.config["file_roots"].copy(),
|
||||
"pillar_roots": salt_master_factory.config["pillar_roots"].copy(),
|
||||
}
|
||||
|
||||
virtualenv_binary = get_virtualenv_binary_path()
|
||||
if virtualenv_binary:
|
||||
config_overrides["venv_bin"] = virtualenv_binary
|
||||
factory = salt_master_factory.get_salt_minion_daemon(
|
||||
"sub_minion",
|
||||
config_defaults=config_defaults,
|
||||
config_overrides=config_overrides,
|
||||
extra_cli_arguments_after_first_start_failure=["--log-level=debug"],
|
||||
)
|
||||
factory.register_after_terminate_callback(
|
||||
pytest.helpers.remove_stale_minion_key, salt_master_factory, factory.id
|
||||
)
|
||||
return factory
|
||||
|
||||
|
||||
@pytest.fixture(scope="session")
|
||||
def salt_proxy_factory(salt_factories, salt_master_factory):
|
||||
proxy_minion_id = "proxytest"
|
||||
root_dir = salt_factories.get_root_dir_for_daemon(proxy_minion_id)
|
||||
conf_dir = root_dir / "conf"
|
||||
conf_dir.mkdir(parents=True, exist_ok=True)
|
||||
RUNTIME_VARS.TMP_PROXY_CONF_DIR = str(conf_dir)
|
||||
|
||||
with salt.utils.files.fopen(os.path.join(RUNTIME_VARS.CONF_DIR, "proxy")) as rfh:
|
||||
config_defaults = yaml.deserialize(rfh.read())
|
||||
|
||||
config_defaults["root_dir"] = str(root_dir)
|
||||
config_defaults["hosts.file"] = os.path.join(RUNTIME_VARS.TMP, "hosts")
|
||||
config_defaults["aliases.file"] = os.path.join(RUNTIME_VARS.TMP, "aliases")
|
||||
config_defaults["transport"] = salt_master_factory.config["transport"]
|
||||
|
||||
factory = salt_master_factory.get_salt_proxy_minion_daemon(
|
||||
proxy_minion_id,
|
||||
config_defaults=config_defaults,
|
||||
extra_cli_arguments_after_first_start_failure=["--log-level=debug"],
|
||||
)
|
||||
factory.register_after_terminate_callback(
|
||||
pytest.helpers.remove_stale_minion_key, salt_master_factory, factory.id
|
||||
)
|
||||
return factory
|
||||
|
||||
|
||||
@pytest.fixture(scope="session")
|
||||
def salt_cli(salt_master_factory):
|
||||
return salt_master_factory.get_salt_cli()
|
||||
|
||||
|
||||
@pytest.fixture(scope="session")
|
||||
def salt_cp_cli(salt_master_factory):
|
||||
return salt_master_factory.get_salt_cp_cli()
|
||||
|
||||
|
||||
@pytest.fixture(scope="session")
|
||||
def salt_key_cli(salt_master_factory):
|
||||
return salt_master_factory.get_salt_key_cli()
|
||||
|
||||
|
||||
@pytest.fixture(scope="session")
|
||||
def salt_run_cli(salt_master_factory):
|
||||
return salt_master_factory.get_salt_run_cli()
|
||||
|
||||
|
||||
@pytest.fixture(scope="session")
|
||||
def salt_ssh_cli(salt_master_factory):
|
||||
return salt_master_factory.get_salt_ssh_cli()
|
||||
|
||||
|
||||
@pytest.fixture(scope="session")
|
||||
def salt_call_cli(salt_minion_factory):
|
||||
return salt_minion_factory.get_salt_call_cli()
|
||||
|
||||
|
||||
@pytest.fixture(scope="session", autouse=True)
|
||||
def bridge_pytest_and_runtests(
|
||||
reap_stray_processes,
|
||||
salt_factories,
|
||||
salt_syndic_master_factory,
|
||||
salt_syndic_factory,
|
||||
salt_master_factory,
|
||||
salt_minion_factory,
|
||||
salt_sub_minion_factory,
|
||||
sshd_config_dir,
|
||||
):
|
||||
# Make sure unittest2 uses the pytest generated configuration
|
||||
RUNTIME_VARS.RUNTIME_CONFIGS["master"] = freeze(salt_master_factory.config)
|
||||
RUNTIME_VARS.RUNTIME_CONFIGS["minion"] = freeze(salt_minion_factory.config)
|
||||
RUNTIME_VARS.RUNTIME_CONFIGS["sub_minion"] = freeze(salt_sub_minion_factory.config)
|
||||
RUNTIME_VARS.RUNTIME_CONFIGS["syndic_master"] = freeze(
|
||||
salt_syndic_master_factory.config
|
||||
)
|
||||
RUNTIME_VARS.RUNTIME_CONFIGS["syndic"] = freeze(salt_syndic_factory.config)
|
||||
RUNTIME_VARS.RUNTIME_CONFIGS["client_config"] = freeze(
|
||||
salt.config.client_config(salt_master_factory.config["conf_file"])
|
||||
)
|
||||
|
||||
# Make sure unittest2 classes know their paths
|
||||
RUNTIME_VARS.TMP_ROOT_DIR = str(salt_factories.root_dir.resolve())
|
||||
RUNTIME_VARS.TMP_CONF_DIR = os.path.dirname(salt_master_factory.config["conf_file"])
|
||||
RUNTIME_VARS.TMP_MINION_CONF_DIR = os.path.dirname(
|
||||
salt_minion_factory.config["conf_file"]
|
||||
)
|
||||
RUNTIME_VARS.TMP_SUB_MINION_CONF_DIR = os.path.dirname(
|
||||
salt_sub_minion_factory.config["conf_file"]
|
||||
)
|
||||
RUNTIME_VARS.TMP_SYNDIC_MASTER_CONF_DIR = os.path.dirname(
|
||||
salt_syndic_master_factory.config["conf_file"]
|
||||
)
|
||||
RUNTIME_VARS.TMP_SYNDIC_MINION_CONF_DIR = os.path.dirname(
|
||||
salt_syndic_factory.config["conf_file"]
|
||||
)
|
||||
RUNTIME_VARS.TMP_SSH_CONF_DIR = str(sshd_config_dir)
|
||||
|
||||
|
||||
@pytest.fixture(scope="session")
|
||||
def sshd_config_dir(salt_factories):
|
||||
config_dir = salt_factories.get_root_dir_for_daemon("sshd")
|
||||
yield config_dir
|
||||
shutil.rmtree(str(config_dir), ignore_errors=True)
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def sshd_server(salt_factories, sshd_config_dir, salt_master):
|
||||
sshd_config_dict = {
|
||||
"Protocol": "2",
|
||||
# Turn strict modes off so that we can operate in /tmp
|
||||
"StrictModes": "no",
|
||||
# Logging
|
||||
"SyslogFacility": "AUTH",
|
||||
"LogLevel": "INFO",
|
||||
# Authentication:
|
||||
"LoginGraceTime": "120",
|
||||
"PermitRootLogin": "without-password",
|
||||
"PubkeyAuthentication": "yes",
|
||||
# Don't read the user's ~/.rhosts and ~/.shosts files
|
||||
"IgnoreRhosts": "yes",
|
||||
"HostbasedAuthentication": "no",
|
||||
# To enable empty passwords, change to yes (NOT RECOMMENDED)
|
||||
"PermitEmptyPasswords": "no",
|
||||
# Change to yes to enable challenge-response passwords (beware issues with
|
||||
# some PAM modules and threads)
|
||||
"ChallengeResponseAuthentication": "no",
|
||||
# Change to no to disable tunnelled clear text passwords
|
||||
"PasswordAuthentication": "no",
|
||||
"X11Forwarding": "no",
|
||||
"X11DisplayOffset": "10",
|
||||
"PrintMotd": "no",
|
||||
"PrintLastLog": "yes",
|
||||
"TCPKeepAlive": "yes",
|
||||
"AcceptEnv": "LANG LC_*",
|
||||
"Subsystem": "sftp /usr/lib/openssh/sftp-server",
|
||||
"UsePAM": "yes",
|
||||
}
|
||||
factory = salt_factories.get_sshd_daemon(
|
||||
sshd_config_dict=sshd_config_dict, config_dir=sshd_config_dir,
|
||||
)
|
||||
# We also need a salt-ssh roster config file
|
||||
roster_path = pathlib.Path(salt_master.config_dir) / "roster"
|
||||
roster_contents = textwrap.dedent(
|
||||
"""\
|
||||
localhost:
|
||||
host: 127.0.0.1
|
||||
port: {}
|
||||
user: {}
|
||||
mine_functions:
|
||||
test.arg: ['itworked']
|
||||
""".format(
|
||||
factory.listen_port, RUNTIME_VARS.RUNNING_TESTS_USER
|
||||
)
|
||||
)
|
||||
log.debug(
|
||||
"Writing to configuration file %s. Configuration:\n%s",
|
||||
roster_path,
|
||||
roster_contents,
|
||||
)
|
||||
with salt.utils.files.fopen(str(roster_path), "w") as wfh:
|
||||
wfh.write(roster_contents)
|
||||
|
||||
with factory.started():
|
||||
yield factory
|
||||
if roster_path.exists():
|
||||
roster_path.unlink()
|
||||
|
||||
|
||||
# <---- Salt Factories -----------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
# ----- From Filenames Test Selection ------------------------------------------------------------------------------->
|
||||
def _match_to_test_file(match):
|
||||
parts = match.split(".")
|
||||
|
|
|
@ -4,9 +4,6 @@
|
|||
|
||||
Integration tests PyTest configuration/fixtures
|
||||
"""
|
||||
# pylint: disable=unused-argument,redefined-outer-name
|
||||
|
||||
|
||||
import logging
|
||||
|
||||
import pytest
|
||||
|
@ -14,79 +11,36 @@ import pytest
|
|||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
# @pytest.fixture(scope='package')
|
||||
# def salt_syndic_master(request, salt_factories):
|
||||
# return salt_factories.spawn_master(request, 'syndic_master', order_masters=True)
|
||||
|
||||
|
||||
# @pytest.fixture(scope='package')
|
||||
# def salt_syndic(request, salt_factories, salt_syndic_master):
|
||||
# return salt_factories.spawn_syndic(request, 'syndic', master_of_masters_id='syndic_master')
|
||||
|
||||
|
||||
# @pytest.fixture(scope='package')
|
||||
# def salt_master(request, salt_factories, salt_syndic_master):
|
||||
# return salt_factories.spawn_master(request, 'master', master_of_masters_id='syndic_master')
|
||||
|
||||
|
||||
@pytest.fixture(scope="package")
|
||||
def salt_master(request, salt_factories, salt_master_config):
|
||||
return salt_factories.spawn_master(request, "master")
|
||||
|
||||
|
||||
@pytest.fixture(scope="package")
|
||||
def salt_minion(request, salt_factories, salt_master, salt_minion_config):
|
||||
proc = salt_factories.spawn_minion(request, "minion", master_id="master")
|
||||
# Sync All
|
||||
salt_call_cli = salt_factories.get_salt_call_cli("minion")
|
||||
ret = salt_call_cli.run("saltutil.sync_all", _timeout=120)
|
||||
assert ret.exitcode == 0, ret
|
||||
return proc
|
||||
|
||||
|
||||
@pytest.fixture(scope="package")
|
||||
def salt_sub_minion(request, salt_factories, salt_master, salt_sub_minion_config):
|
||||
proc = salt_factories.spawn_minion(request, "sub_minion", master_id="master")
|
||||
# Sync All
|
||||
salt_call_cli = salt_factories.get_salt_call_cli("sub_minion")
|
||||
ret = salt_call_cli.run("saltutil.sync_all", _timeout=120)
|
||||
assert ret.exitcode == 0, ret
|
||||
return proc
|
||||
@pytest.fixture(scope="package", autouse=True)
|
||||
def salt_master(salt_master_factory):
|
||||
"""
|
||||
A running salt-master fixture
|
||||
"""
|
||||
with salt_master_factory.started():
|
||||
yield salt_master_factory
|
||||
|
||||
|
||||
@pytest.fixture(scope="package", autouse=True)
|
||||
def bridge_pytest_and_runtests_integration(
|
||||
bridge_pytest_and_runtests,
|
||||
salt_factories,
|
||||
# salt_syndic_master,
|
||||
# salt_syndic,
|
||||
salt_master,
|
||||
salt_minion,
|
||||
):
|
||||
|
||||
yield
|
||||
def salt_minion(salt_minion_factory):
|
||||
"""
|
||||
A running salt-minion fixture
|
||||
"""
|
||||
with salt_minion_factory.started():
|
||||
# Sync All
|
||||
salt_call_cli = salt_minion_factory.get_salt_call_cli()
|
||||
ret = salt_call_cli.run("saltutil.sync_all", _timeout=120)
|
||||
assert ret.exitcode == 0, ret
|
||||
yield salt_minion_factory
|
||||
|
||||
|
||||
@pytest.fixture(scope="package")
|
||||
def salt_cli(salt_factories, salt_minion, salt_master):
|
||||
return salt_factories.get_salt_cli(salt_master.config["id"])
|
||||
|
||||
|
||||
@pytest.fixture(scope="package")
|
||||
def salt_cp_cli(salt_factories, salt_minion, salt_master):
|
||||
return salt_factories.get_salt_cp_cli(salt_master.config["id"])
|
||||
|
||||
|
||||
@pytest.fixture(scope="package")
|
||||
def salt_key_cli(salt_factories, salt_minion, salt_master):
|
||||
return salt_factories.get_salt_key_cli(salt_master.config["id"])
|
||||
|
||||
|
||||
@pytest.fixture(scope="package")
|
||||
def salt_run_cli(salt_factories, salt_minion, salt_master):
|
||||
return salt_factories.get_salt_run_cli(salt_master.config["id"])
|
||||
|
||||
|
||||
@pytest.fixture(scope="package")
|
||||
def salt_call_cli(salt_factories, salt_minion, salt_master):
|
||||
return salt_factories.get_salt_call_cli(salt_minion.config["id"])
|
||||
@pytest.fixture(scope="module")
|
||||
def salt_sub_minion(salt_sub_minion_factory):
|
||||
"""
|
||||
A second running salt-minion fixture
|
||||
"""
|
||||
with salt_sub_minion_factory.started():
|
||||
# Sync All
|
||||
salt_call_cli = salt_sub_minion_factory.get_salt_call_cli()
|
||||
ret = salt_call_cli.run("saltutil.sync_all", _timeout=120)
|
||||
assert ret.exitcode == 0, ret
|
||||
yield salt_sub_minion_factory
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
tests.integration.master.test_event_return
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
@ -7,18 +6,17 @@ tests.integration.master.test_event_return
|
|||
|
||||
https://github.com/saltstack/salt/pull/54731
|
||||
"""
|
||||
from __future__ import absolute_import, print_function, unicode_literals
|
||||
|
||||
import logging
|
||||
import os
|
||||
import shutil
|
||||
import subprocess
|
||||
import sys
|
||||
import time
|
||||
|
||||
import salt.ext.six as six
|
||||
from salt.utils.nb_popen import NonBlockingPopen
|
||||
from saltfactories.utils.ports import get_unused_localhost_port
|
||||
from saltfactories.utils.processes.helpers import terminate_process
|
||||
from saltfactories.utils.processes import terminate_process
|
||||
from tests.support.cli_scripts import ScriptPathMixin
|
||||
from tests.support.mixins import AdaptedConfigurationTestCaseMixin
|
||||
from tests.support.runtests import RUNTIME_VARS
|
||||
|
@ -57,6 +55,7 @@ class TestEventReturn(AdaptedConfigurationTestCaseMixin, ScriptPathMixin, TestCa
|
|||
def test_master_startup(self):
|
||||
proc = NonBlockingPopen(
|
||||
[
|
||||
sys.executable,
|
||||
self.get_script_path("master"),
|
||||
"-c",
|
||||
RUNTIME_VARS.TMP_CONF_DIR,
|
||||
|
@ -66,8 +65,8 @@ class TestEventReturn(AdaptedConfigurationTestCaseMixin, ScriptPathMixin, TestCa
|
|||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.STDOUT,
|
||||
)
|
||||
out = six.b("")
|
||||
err = six.b("")
|
||||
out = b""
|
||||
err = b""
|
||||
|
||||
# Testing this should never be longer than 1 minute
|
||||
max_time = time.time() + 60
|
||||
|
@ -83,17 +82,17 @@ class TestEventReturn(AdaptedConfigurationTestCaseMixin, ScriptPathMixin, TestCa
|
|||
if _err:
|
||||
err += _err
|
||||
|
||||
if six.b("DeprecationWarning: object() takes no parameters") in out:
|
||||
if b"DeprecationWarning: object() takes no parameters" in out:
|
||||
self.fail(
|
||||
"'DeprecationWarning: object() takes no parameters' was seen in output"
|
||||
)
|
||||
|
||||
if six.b("TypeError: object() takes no parameters") in out:
|
||||
if b"TypeError: object() takes no parameters" in out:
|
||||
self.fail(
|
||||
"'TypeError: object() takes no parameters' was seen in output"
|
||||
)
|
||||
|
||||
if six.b("Setting up the master communication server") in out:
|
||||
if b"Setting up the master communication server" in out:
|
||||
# We got past the place we need, stop the process
|
||||
break
|
||||
|
||||
|
|
|
@ -1,6 +1,3 @@
|
|||
# encoding: utf-8
|
||||
from __future__ import absolute_import, print_function, unicode_literals
|
||||
|
||||
import logging
|
||||
import os
|
||||
import time
|
||||
|
@ -11,20 +8,20 @@ import salt.netapi
|
|||
from salt.exceptions import EauthAuthenticationError
|
||||
from tests.support.case import SSHCase
|
||||
from tests.support.helpers import (
|
||||
SKIP_IF_NOT_RUNNING_PYTEST,
|
||||
SaveRequestsPostHandler,
|
||||
Webserver,
|
||||
requires_sshd_server,
|
||||
slowTest,
|
||||
)
|
||||
from tests.support.mixins import AdaptedConfigurationTestCaseMixin
|
||||
from tests.support.mock import patch
|
||||
from tests.support.paths import TMP, TMP_CONF_DIR
|
||||
from tests.support.runtests import RUNTIME_VARS
|
||||
from tests.support.unit import TestCase, skipIf
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("salt_sub_minion")
|
||||
@pytest.mark.usefixtures("salt_master", "salt_sub_minion")
|
||||
class NetapiClientTest(TestCase):
|
||||
eauth_creds = {
|
||||
"username": "saltdev_auto",
|
||||
|
@ -36,9 +33,7 @@ class NetapiClientTest(TestCase):
|
|||
"""
|
||||
Set up a NetapiClient instance
|
||||
"""
|
||||
opts = salt.config.client_config(
|
||||
os.path.join(RUNTIME_VARS.TMP_CONF_DIR, "master")
|
||||
)
|
||||
opts = AdaptedConfigurationTestCaseMixin.get_config("client_config").copy()
|
||||
self.netapi = salt.netapi.NetapiClient(opts)
|
||||
|
||||
def tearDown(self):
|
||||
|
@ -118,9 +113,7 @@ class NetapiClientTest(TestCase):
|
|||
|
||||
self.maxDiff = None
|
||||
self.assertTrue(
|
||||
set(["master.pem", "master.pub"]).issubset(
|
||||
set(ret["data"]["return"]["local"])
|
||||
)
|
||||
{"master.pem", "master.pub"}.issubset(set(ret["data"]["return"]["local"]))
|
||||
)
|
||||
|
||||
@slowTest
|
||||
|
@ -166,7 +159,8 @@ class NetapiClientTest(TestCase):
|
|||
ret = self.netapi.run(low)
|
||||
|
||||
|
||||
@requires_sshd_server
|
||||
@SKIP_IF_NOT_RUNNING_PYTEST
|
||||
@pytest.mark.requires_sshd_server
|
||||
class NetapiSSHClientTest(SSHCase):
|
||||
eauth_creds = {
|
||||
"username": "saltdev_auto",
|
||||
|
@ -178,10 +172,10 @@ class NetapiSSHClientTest(SSHCase):
|
|||
"""
|
||||
Set up a NetapiClient instance
|
||||
"""
|
||||
opts = salt.config.client_config(os.path.join(TMP_CONF_DIR, "master"))
|
||||
opts = AdaptedConfigurationTestCaseMixin.get_config("client_config").copy()
|
||||
self.netapi = salt.netapi.NetapiClient(opts)
|
||||
|
||||
self.priv_file = os.path.join(RUNTIME_VARS.TMP_CONF_DIR, "key_test")
|
||||
self.priv_file = os.path.join(RUNTIME_VARS.TMP_SSH_CONF_DIR, "client_key")
|
||||
self.rosters = os.path.join(RUNTIME_VARS.TMP_CONF_DIR)
|
||||
|
||||
# Initialize salt-ssh
|
||||
|
@ -234,7 +228,7 @@ class NetapiSSHClientTest(SSHCase):
|
|||
@slowTest
|
||||
def test_ssh_unauthenticated_raw_shell_curl(self):
|
||||
|
||||
fun = "-o ProxyCommand curl {0}".format(self.post_web_root)
|
||||
fun = "-o ProxyCommand curl {}".format(self.post_web_root)
|
||||
low = {"client": "ssh", "tgt": "localhost", "fun": fun, "raw_shell": True}
|
||||
|
||||
ret = None
|
||||
|
@ -247,8 +241,8 @@ class NetapiSSHClientTest(SSHCase):
|
|||
@slowTest
|
||||
def test_ssh_unauthenticated_raw_shell_touch(self):
|
||||
|
||||
badfile = os.path.join(TMP, "badfile.txt")
|
||||
fun = "-o ProxyCommand touch {0}".format(badfile)
|
||||
badfile = os.path.join(RUNTIME_VARS.TMP, "badfile.txt")
|
||||
fun = "-o ProxyCommand touch {}".format(badfile)
|
||||
low = {"client": "ssh", "tgt": "localhost", "fun": fun, "raw_shell": True}
|
||||
|
||||
ret = None
|
||||
|
@ -261,8 +255,8 @@ class NetapiSSHClientTest(SSHCase):
|
|||
@slowTest
|
||||
def test_ssh_authenticated_raw_shell_disabled(self):
|
||||
|
||||
badfile = os.path.join(TMP, "badfile.txt")
|
||||
fun = "-o ProxyCommand touch {0}".format(badfile)
|
||||
badfile = os.path.join(RUNTIME_VARS.TMP, "badfile.txt")
|
||||
fun = "-o ProxyCommand touch {}".format(badfile)
|
||||
low = {"client": "ssh", "tgt": "localhost", "fun": fun, "raw_shell": True}
|
||||
|
||||
low.update(self.eauth_creds)
|
||||
|
|
|
@ -1,46 +1,17 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
tests.integration.proxy.conftest
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Proxy related fixtures
|
||||
"""
|
||||
from __future__ import absolute_import, unicode_literals
|
||||
|
||||
import logging
|
||||
import os
|
||||
|
||||
import pytest
|
||||
import salt.utils.files
|
||||
from salt.serializers import yaml
|
||||
from tests.support.runtests import RUNTIME_VARS
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@pytest.fixture(scope="package", autouse=True)
|
||||
def salt_proxy(request, salt_factories, salt_master):
|
||||
proxy_minion_id = "proxytest"
|
||||
root_dir = salt_factories._get_root_dir_for_daemon(proxy_minion_id)
|
||||
conf_dir = root_dir.join("conf").ensure(dir=True)
|
||||
RUNTIME_VARS.TMP_PROXY_CONF_DIR = conf_dir.strpath
|
||||
|
||||
with salt.utils.files.fopen(os.path.join(RUNTIME_VARS.CONF_DIR, "proxy")) as rfh:
|
||||
config_defaults = yaml.deserialize(rfh.read())
|
||||
|
||||
config_defaults["hosts.file"] = os.path.join(RUNTIME_VARS.TMP, "hosts")
|
||||
config_defaults["aliases.file"] = os.path.join(RUNTIME_VARS.TMP, "aliases")
|
||||
config_defaults["transport"] = request.config.getoption("--transport")
|
||||
config_defaults["root_dir"] = root_dir
|
||||
yield salt_factories.spawn_proxy_minion(
|
||||
request, proxy_minion_id, master_id="master", config_defaults=config_defaults
|
||||
)
|
||||
|
||||
proxy_key_file = os.path.join(
|
||||
salt_master.config["pki_dir"], "minions", proxy_minion_id
|
||||
)
|
||||
log.debug("Proxy minion %r KEY FILE: %s", proxy_minion_id, proxy_key_file)
|
||||
if os.path.exists(proxy_key_file):
|
||||
os.unlink(proxy_key_file)
|
||||
else:
|
||||
log.warning("The proxy minion key was not found at %s", proxy_key_file)
|
||||
def salt_proxy(salt_proxy):
|
||||
return salt_proxy
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
salt-ssh testing
|
||||
"""
|
||||
from __future__ import absolute_import, print_function, unicode_literals
|
||||
|
||||
import os
|
||||
import shutil
|
||||
|
@ -17,6 +15,10 @@ class SSHTest(SSHCase):
|
|||
Test general salt-ssh functionality
|
||||
"""
|
||||
|
||||
def setUp(self):
|
||||
thin_dir = self.run_function("config.get", ["thin_dir"], wipe=False)
|
||||
self.addCleanup(shutil.rmtree, thin_dir, ignore_errors=True)
|
||||
|
||||
@slowTest
|
||||
def test_ping(self):
|
||||
"""
|
||||
|
@ -43,15 +45,7 @@ class SSHTest(SSHCase):
|
|||
path = "/pathdoesnotexist/"
|
||||
roster = os.path.join(RUNTIME_VARS.TMP, "roster-set-path")
|
||||
self.custom_roster(
|
||||
roster, data={"set_path": "$PATH:/usr/local/bin/:{0}".format(path)}
|
||||
roster, data={"set_path": "$PATH:/usr/local/bin/:{}".format(path)}
|
||||
)
|
||||
ret = self.run_function("environ.get", ["PATH"], roster_file=roster)
|
||||
assert path in ret
|
||||
|
||||
def tearDown(self):
|
||||
"""
|
||||
make sure to clean up any old ssh directories
|
||||
"""
|
||||
salt_dir = self.run_function("config.get", ["thin_dir"], wipe=False)
|
||||
if os.path.exists(salt_dir):
|
||||
shutil.rmtree(salt_dir)
|
||||
|
|
|
@ -1,25 +1,20 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
Test AnsibleGate State Module
|
||||
"""
|
||||
from __future__ import absolute_import, print_function, unicode_literals
|
||||
|
||||
# Import python libraries
|
||||
import os
|
||||
import shutil
|
||||
import tempfile
|
||||
|
||||
# Import salt libraries
|
||||
import pytest
|
||||
import salt.utils.files
|
||||
import salt.utils.path
|
||||
import yaml
|
||||
|
||||
# Import testing libraries
|
||||
from tests.support.case import ModuleCase
|
||||
from tests.support.helpers import (
|
||||
SKIP_IF_NOT_RUNNING_PYTEST,
|
||||
destructiveTest,
|
||||
flaky,
|
||||
requires_sshd_server,
|
||||
requires_system_grains,
|
||||
)
|
||||
from tests.support.mixins import SaltReturnAssertsMixin
|
||||
|
@ -27,8 +22,9 @@ from tests.support.runtests import RUNTIME_VARS
|
|||
from tests.support.unit import SkipTest, skipIf
|
||||
|
||||
|
||||
@SKIP_IF_NOT_RUNNING_PYTEST
|
||||
@destructiveTest
|
||||
@requires_sshd_server
|
||||
@pytest.mark.requires_sshd_server
|
||||
@skipIf(
|
||||
not salt.utils.path.which("ansible-playbook"), "ansible-playbook is not installed"
|
||||
)
|
||||
|
@ -46,7 +42,7 @@ class AnsiblePlaybooksTestCase(ModuleCase, SaltReturnAssertsMixin):
|
|||
)
|
||||
|
||||
def setUp(self):
|
||||
priv_file = os.path.join(RUNTIME_VARS.TMP_CONF_DIR, "key_test")
|
||||
priv_file = os.path.join(RUNTIME_VARS.TMP_SSH_CONF_DIR, "client_key")
|
||||
data = {
|
||||
"all": {
|
||||
"hosts": {
|
||||
|
|
|
@ -1,10 +1,8 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
Classes for starting/stopping/status salt daemons, auxiliary
|
||||
scripts, generic commands.
|
||||
"""
|
||||
|
||||
from __future__ import absolute_import
|
||||
|
||||
import atexit
|
||||
import copy
|
||||
|
@ -28,12 +26,7 @@ import salt.utils.platform
|
|||
import salt.utils.process
|
||||
import salt.utils.psutil_compat as psutils
|
||||
import salt.utils.yaml
|
||||
from salt.ext import six
|
||||
from salt.ext.six.moves import range
|
||||
from saltfactories.utils.processes.helpers import (
|
||||
terminate_process,
|
||||
terminate_process_list,
|
||||
)
|
||||
from saltfactories.utils.processes import terminate_process, terminate_process_list
|
||||
from tests.support.cli_scripts import ScriptPathMixin
|
||||
from tests.support.runtests import RUNTIME_VARS
|
||||
from tests.support.unit import TestCase
|
||||
|
@ -74,12 +67,12 @@ class TestProgramMeta(type):
|
|||
dirtree.update(attrs.get("dirtree", []))
|
||||
attrs["dirtree"] = dirtree
|
||||
|
||||
return super(TestProgramMeta, mcs).__new__(mcs, name, bases, attrs)
|
||||
return super().__new__(mcs, name, bases, attrs)
|
||||
|
||||
|
||||
# pylint: disable=too-many-instance-attributes
|
||||
@pytest.mark.windows_whitelisted
|
||||
class TestProgram(six.with_metaclass(TestProgramMeta, object)):
|
||||
class TestProgram(metaclass=TestProgramMeta):
|
||||
"""
|
||||
Set up an arbitrary executable to run.
|
||||
|
||||
|
@ -89,14 +82,14 @@ class TestProgram(six.with_metaclass(TestProgramMeta, object)):
|
|||
empty_config = ""
|
||||
config_file = ""
|
||||
|
||||
config_attrs = set(["name", "test_dir", "config_dirs"])
|
||||
config_attrs = {"name", "test_dir", "config_dirs"}
|
||||
config_vals = {}
|
||||
config_base = ""
|
||||
config_dir = os.path.join("etc")
|
||||
configs = {}
|
||||
config_types = (
|
||||
str,
|
||||
six.string_types,
|
||||
(str,),
|
||||
)
|
||||
|
||||
dirtree = [
|
||||
|
@ -157,7 +150,7 @@ class TestProgram(six.with_metaclass(TestProgramMeta, object)):
|
|||
if not self.name:
|
||||
if not self.program:
|
||||
raise ValueError(
|
||||
'"{0}" object must specify "program" parameter'.format(
|
||||
'"{}" object must specify "program" parameter'.format(
|
||||
self.__class__.__name__
|
||||
)
|
||||
)
|
||||
|
@ -229,7 +222,7 @@ class TestProgram(six.with_metaclass(TestProgramMeta, object)):
|
|||
os.makedirs(self._parent_dir)
|
||||
elif not os.path.isdir(self._parent_dir):
|
||||
raise ValueError(
|
||||
'Parent path "{0}" exists but is not a directory'.format(
|
||||
'Parent path "{}" exists but is not a directory'.format(
|
||||
self._parent_dir
|
||||
)
|
||||
)
|
||||
|
@ -243,9 +236,7 @@ class TestProgram(six.with_metaclass(TestProgramMeta, object)):
|
|||
with salt.utils.files.fopen(cpath, "w") as cfo:
|
||||
cfg = self.config_stringify(config)
|
||||
log.debug(
|
||||
"Writing configuration for {0} to {1}:\n{2}".format(
|
||||
self.name, cpath, cfg
|
||||
)
|
||||
"Writing configuration for {} to {}:\n{}".format(self.name, cpath, cfg)
|
||||
)
|
||||
cfo.write(cfg)
|
||||
cfo.flush()
|
||||
|
@ -267,7 +258,7 @@ class TestProgram(six.with_metaclass(TestProgramMeta, object)):
|
|||
|
||||
def config_subs(self):
|
||||
"""Get the substitution values for use to generate the config"""
|
||||
subs = dict([(attr, getattr(self, attr, None)) for attr in self.config_attrs])
|
||||
subs = {attr: getattr(self, attr, None) for attr in self.config_attrs}
|
||||
for key, val in self.config_vals.items():
|
||||
subs[key] = val.format(**subs)
|
||||
return subs
|
||||
|
@ -296,17 +287,17 @@ class TestProgram(six.with_metaclass(TestProgramMeta, object)):
|
|||
"""Create directory structure."""
|
||||
subdirs = []
|
||||
for branch in self.dirtree:
|
||||
log.debug("checking dirtree: {0}".format(branch))
|
||||
log.debug("checking dirtree: {}".format(branch))
|
||||
if not branch:
|
||||
continue
|
||||
if isinstance(branch, six.string_types) and branch[0] == "&":
|
||||
log.debug('Looking up dirtree branch "{0}"'.format(branch))
|
||||
if isinstance(branch, str) and branch[0] == "&":
|
||||
log.debug('Looking up dirtree branch "{}"'.format(branch))
|
||||
try:
|
||||
dirattr = getattr(self, branch[1:], None)
|
||||
log.debug('dirtree "{0}" => "{1}"'.format(branch, dirattr))
|
||||
log.debug('dirtree "{}" => "{}"'.format(branch, dirattr))
|
||||
except AttributeError:
|
||||
raise ValueError(
|
||||
'Unable to find dirtree attribute "{0}" on object "{1}.name = {2}: {3}"'.format(
|
||||
'Unable to find dirtree attribute "{}" on object "{}.name = {}: {}"'.format(
|
||||
branch, self.__class__.__name__, self.name, dir(self),
|
||||
)
|
||||
)
|
||||
|
@ -314,25 +305,25 @@ class TestProgram(six.with_metaclass(TestProgramMeta, object)):
|
|||
if not dirattr:
|
||||
continue
|
||||
|
||||
if isinstance(dirattr, six.string_types):
|
||||
if isinstance(dirattr, str):
|
||||
subdirs.append(dirattr)
|
||||
elif hasattr(dirattr, "__iter__"):
|
||||
subdirs.extend(dirattr)
|
||||
else:
|
||||
raise TypeError(
|
||||
"Branch type of {0} in dirtree is unhandled".format(branch)
|
||||
"Branch type of {} in dirtree is unhandled".format(branch)
|
||||
)
|
||||
elif isinstance(branch, six.string_types):
|
||||
elif isinstance(branch, str):
|
||||
subdirs.append(branch)
|
||||
else:
|
||||
raise TypeError(
|
||||
"Branch type of {0} in dirtree is unhandled".format(branch)
|
||||
"Branch type of {} in dirtree is unhandled".format(branch)
|
||||
)
|
||||
|
||||
for subdir in subdirs:
|
||||
path = self.abs_path(subdir)
|
||||
if not os.path.exists(path):
|
||||
log.debug("make_dirtree: {0}".format(path))
|
||||
log.debug("make_dirtree: {}".format(path))
|
||||
os.makedirs(path)
|
||||
|
||||
def setup(self, *args, **kwargs):
|
||||
|
@ -435,11 +426,6 @@ class TestProgram(six.with_metaclass(TestProgramMeta, object)):
|
|||
cmd_env = dict(os.environ)
|
||||
cmd_env.update(env_delta)
|
||||
|
||||
if salt.utils.platform.is_windows() and six.PY2:
|
||||
for k, v in cmd_env.items():
|
||||
if isinstance(k, six.text_type) or isinstance(v, six.text_type):
|
||||
cmd_env[k.encode("ascii")] = v.encode("ascii")
|
||||
|
||||
popen_kwargs = {
|
||||
"shell": self.shell,
|
||||
"stdout": subprocess.PIPE,
|
||||
|
@ -486,7 +472,7 @@ class TestProgram(six.with_metaclass(TestProgramMeta, object)):
|
|||
out = process.stdout.read().splitlines()
|
||||
out.extend(
|
||||
[
|
||||
"Process took more than {0} seconds to complete. "
|
||||
"Process took more than {} seconds to complete. "
|
||||
"Process Killed!".format(timeout)
|
||||
]
|
||||
)
|
||||
|
@ -574,10 +560,10 @@ class TestSaltProgramMeta(TestProgramMeta):
|
|||
def __new__(mcs, name, bases, attrs):
|
||||
if attrs.get("script") is None:
|
||||
if "Salt" in name:
|
||||
script = "salt-{0}".format(name.rsplit("Salt", 1)[-1].lower())
|
||||
script = "salt-{}".format(name.rsplit("Salt", 1)[-1].lower())
|
||||
if script is None:
|
||||
raise AttributeError(
|
||||
'Class {0}: Unable to set "script" attribute: class name'
|
||||
'Class {}: Unable to set "script" attribute: class name'
|
||||
' must include "Salt" or "script" must be explicitly set.'.format(
|
||||
name
|
||||
)
|
||||
|
@ -599,20 +585,18 @@ class TestSaltProgramMeta(TestProgramMeta):
|
|||
configs.update(attrs.get("configs", {}))
|
||||
attrs["configs"] = configs
|
||||
|
||||
return super(TestSaltProgramMeta, mcs).__new__(mcs, name, bases, attrs)
|
||||
return super().__new__(mcs, name, bases, attrs)
|
||||
|
||||
|
||||
@pytest.mark.windows_whitelisted
|
||||
class TestSaltProgram(
|
||||
six.with_metaclass(TestSaltProgramMeta, TestProgram, ScriptPathMixin)
|
||||
):
|
||||
class TestSaltProgram(TestProgram, ScriptPathMixin, metaclass=TestSaltProgramMeta):
|
||||
"""
|
||||
This is like TestProgram but with some functions to run a salt-specific
|
||||
auxiliary program.
|
||||
"""
|
||||
|
||||
config_types = (dict,)
|
||||
config_attrs = set(["log_dir", "script_dir"])
|
||||
config_attrs = {"log_dir", "script_dir"}
|
||||
|
||||
pub_port = 4505
|
||||
ret_port = 4506
|
||||
|
@ -620,7 +604,7 @@ class TestSaltProgram(
|
|||
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
try:
|
||||
connect = sock.bind(("localhost", port))
|
||||
except (socket.error, OSError):
|
||||
except OSError:
|
||||
# these ports are already in use, use different ones
|
||||
pub_port = 4606
|
||||
ret_port = 4607
|
||||
|
@ -653,7 +637,7 @@ class TestSaltProgram(
|
|||
if len(args) < 2 and "program" not in kwargs:
|
||||
# This is effectively a place-holder - it gets set correctly after super()
|
||||
kwargs["program"] = self.script
|
||||
super(TestSaltProgram, self).__init__(*args, **kwargs)
|
||||
super().__init__(*args, **kwargs)
|
||||
self.program = self.get_script_path(self.script)
|
||||
|
||||
def config_merge(self, base, overrides):
|
||||
|
@ -667,7 +651,7 @@ class TestSaltProgram(
|
|||
cfg_base = {}
|
||||
for key, val in self.config_base.items():
|
||||
_val = val
|
||||
if val and isinstance(val, six.string_types) and val[0] == "&":
|
||||
if val and isinstance(val, str) and val[0] == "&":
|
||||
_val = getattr(self, val[1:], None)
|
||||
if _val is None:
|
||||
continue
|
||||
|
@ -676,13 +660,13 @@ class TestSaltProgram(
|
|||
cfg = {}
|
||||
for key, val in self.configs.get(config, {}).get("map", {}).items():
|
||||
_val = val
|
||||
if val and isinstance(val, six.string_types) and val[0] == "&":
|
||||
if val and isinstance(val, str) and val[0] == "&":
|
||||
_val = getattr(self, val[1:], None)
|
||||
if _val is None:
|
||||
continue
|
||||
cfg[key] = _val
|
||||
cfg = self.config_merge(cfg_base, cfg)
|
||||
log.debug("Generated config => {0}".format(cfg))
|
||||
log.debug("Generated config => {}".format(cfg))
|
||||
return cfg
|
||||
|
||||
def config_stringify(self, config):
|
||||
|
@ -690,7 +674,7 @@ class TestSaltProgram(
|
|||
subs = self.config_subs()
|
||||
cfg = {}
|
||||
for key, val in self.config_get(config).items():
|
||||
if isinstance(val, six.string_types):
|
||||
if isinstance(val, str):
|
||||
cfg[key] = val.format(**subs)
|
||||
else:
|
||||
cfg[key] = val
|
||||
|
@ -701,7 +685,7 @@ class TestSaltProgram(
|
|||
args = kwargs.setdefault("args", [])
|
||||
if "-c" not in args and "--config-dir" not in args:
|
||||
args.extend(["--config-dir", self.abs_path(self.config_dir)])
|
||||
return super(TestSaltProgram, self).run(**kwargs)
|
||||
return super().run(**kwargs)
|
||||
|
||||
|
||||
@pytest.mark.windows_whitelisted
|
||||
|
@ -728,7 +712,7 @@ class TestProgramSaltRun(TestSaltProgram):
|
|||
def __init__(self, *args, **kwargs):
|
||||
cfgb = kwargs.setdefault("config_base", {})
|
||||
_ = cfgb.setdefault("user", getpass.getuser())
|
||||
super(TestProgramSaltRun, self).__init__(*args, **kwargs)
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
|
||||
@pytest.mark.windows_whitelisted
|
||||
|
@ -749,14 +733,14 @@ class TestDaemon(TestProgram):
|
|||
self.script = kwargs.pop("script", self.script)
|
||||
self.pid_file = kwargs.pop(
|
||||
"pid_file",
|
||||
self.pid_file if self.pid_file else "{0}.pid".format(self.script),
|
||||
self.pid_file if self.pid_file else "{}.pid".format(self.script),
|
||||
)
|
||||
self.pid_dir = kwargs.pop("pid_dir", self.pid_dir)
|
||||
self._shutdown = False
|
||||
if not args and "program" not in kwargs:
|
||||
# This is effectively a place-holder - it gets set correctly after super()
|
||||
kwargs["program"] = self.script
|
||||
super(TestDaemon, self).__init__(*args, **kwargs)
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
@property
|
||||
def pid_path(self):
|
||||
|
@ -785,7 +769,7 @@ class TestDaemon(TestProgram):
|
|||
return pid
|
||||
if endtime < time.time():
|
||||
raise TimeoutError(
|
||||
'Timeout waiting for "{0}" pid in "{1}"'.format(
|
||||
'Timeout waiting for "{}" pid in "{}"'.format(
|
||||
self.name, self.abs_path(self.pid_path)
|
||||
)
|
||||
)
|
||||
|
@ -805,55 +789,27 @@ class TestDaemon(TestProgram):
|
|||
def find_orphans(self, cmdline):
|
||||
"""Find orphaned processes matching the specified cmdline"""
|
||||
ret = []
|
||||
if six.PY3:
|
||||
cmdline = " ".join(cmdline)
|
||||
for proc in psutils.process_iter():
|
||||
try:
|
||||
for item in proc.cmdline():
|
||||
if cmdline in item:
|
||||
ret.append(proc)
|
||||
except psutils.NoSuchProcess:
|
||||
# Process exited between when process_iter was invoked and
|
||||
# when we tried to invoke this instance's cmdline() func.
|
||||
cmdline = " ".join(cmdline)
|
||||
for proc in psutils.process_iter():
|
||||
try:
|
||||
for item in proc.cmdline():
|
||||
if cmdline in item:
|
||||
ret.append(proc)
|
||||
except psutils.NoSuchProcess:
|
||||
# Process exited between when process_iter was invoked and
|
||||
# when we tried to invoke this instance's cmdline() func.
|
||||
continue
|
||||
except psutils.AccessDenied:
|
||||
# We might get access denied if not running as root
|
||||
if not salt.utils.platform.is_windows():
|
||||
pinfo = proc.as_dict(attrs=["pid", "name", "username"])
|
||||
log.error(
|
||||
"Unable to access process %s, " "running command %s as user %s",
|
||||
pinfo["pid"],
|
||||
pinfo["name"],
|
||||
pinfo["username"],
|
||||
)
|
||||
continue
|
||||
except psutils.AccessDenied:
|
||||
# We might get access denied if not running as root
|
||||
if not salt.utils.platform.is_windows():
|
||||
pinfo = proc.as_dict(attrs=["pid", "name", "username"])
|
||||
log.error(
|
||||
"Unable to access process %s, "
|
||||
"running command %s as user %s",
|
||||
pinfo["pid"],
|
||||
pinfo["name"],
|
||||
pinfo["username"],
|
||||
)
|
||||
continue
|
||||
else:
|
||||
cmd_len = len(cmdline)
|
||||
for proc in psutils.process_iter():
|
||||
try:
|
||||
proc_cmdline = proc.cmdline()
|
||||
except psutils.NoSuchProcess:
|
||||
# Process exited between when process_iter was invoked and
|
||||
# when we tried to invoke this instance's cmdline() func.
|
||||
continue
|
||||
except psutils.AccessDenied:
|
||||
# We might get access denied if not running as root
|
||||
if not salt.utils.platform.is_windows():
|
||||
pinfo = proc.as_dict(attrs=["pid", "name", "username"])
|
||||
log.error(
|
||||
"Unable to access process %s, "
|
||||
"running command %s as user %s",
|
||||
pinfo["pid"],
|
||||
pinfo["name"],
|
||||
pinfo["username"],
|
||||
)
|
||||
continue
|
||||
if any(
|
||||
(cmdline == proc_cmdline[n : n + cmd_len])
|
||||
for n in range(len(proc_cmdline) - cmd_len + 1)
|
||||
):
|
||||
ret.append(proc)
|
||||
return ret
|
||||
|
||||
def shutdown(self, signum=signal.SIGTERM, timeout=10, wait_for_orphans=0):
|
||||
|
@ -890,13 +846,11 @@ class TestDaemon(TestProgram):
|
|||
|
||||
# Shutdown if not alreadt shutdown
|
||||
self.shutdown()
|
||||
super(TestDaemon, self).cleanup(*args, **kwargs)
|
||||
super().cleanup(*args, **kwargs)
|
||||
|
||||
|
||||
@pytest.mark.windows_whitelisted
|
||||
class TestSaltDaemon(
|
||||
six.with_metaclass(TestSaltProgramMeta, TestDaemon, TestSaltProgram)
|
||||
):
|
||||
class TestSaltDaemon(TestDaemon, TestSaltProgram, metaclass=TestSaltProgramMeta):
|
||||
"""
|
||||
A class to run arbitrary salt daemons (master, minion, syndic, etc.)
|
||||
"""
|
||||
|
@ -913,7 +867,7 @@ class TestDaemonSaltMaster(TestSaltDaemon):
|
|||
def __init__(self, *args, **kwargs):
|
||||
cfgb = kwargs.setdefault("config_base", {})
|
||||
_ = cfgb.setdefault("user", getpass.getuser())
|
||||
super(TestDaemonSaltMaster, self).__init__(*args, **kwargs)
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
|
||||
@pytest.mark.windows_whitelisted
|
||||
|
@ -927,7 +881,7 @@ class TestDaemonSaltMinion(TestSaltDaemon):
|
|||
def __init__(self, *args, **kwargs):
|
||||
cfgb = kwargs.setdefault("config_base", {})
|
||||
_ = cfgb.setdefault("user", getpass.getuser())
|
||||
super(TestDaemonSaltMinion, self).__init__(*args, **kwargs)
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
|
||||
@pytest.mark.windows_whitelisted
|
||||
|
@ -951,7 +905,7 @@ class TestDaemonSaltSyndic(TestSaltDaemon):
|
|||
def __init__(self, *args, **kwargs):
|
||||
cfgb = kwargs.setdefault("config_base", {})
|
||||
_ = cfgb.setdefault("user", getpass.getuser())
|
||||
super(TestDaemonSaltSyndic, self).__init__(*args, **kwargs)
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
|
||||
@pytest.mark.windows_whitelisted
|
||||
|
@ -966,14 +920,14 @@ class TestDaemonSaltProxy(TestSaltDaemon):
|
|||
def __init__(self, *args, **kwargs):
|
||||
cfgb = kwargs.setdefault("config_base", {})
|
||||
_ = cfgb.setdefault("user", getpass.getuser())
|
||||
super(TestDaemonSaltProxy, self).__init__(*args, **kwargs)
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
def run(self, **kwargs):
|
||||
if not kwargs.get("verbatim_args"):
|
||||
args = kwargs.setdefault("args", [])
|
||||
if "--proxyid" not in args:
|
||||
args.extend(["--proxyid", self.name])
|
||||
return super(TestDaemonSaltProxy, self).run(**kwargs)
|
||||
return super().run(**kwargs)
|
||||
|
||||
|
||||
@pytest.mark.windows_whitelisted
|
||||
|
@ -986,14 +940,14 @@ class TestProgramCase(TestCase):
|
|||
# Setup for scripts
|
||||
if not getattr(self, "_test_dir", None):
|
||||
self._test_dir = tempfile.mkdtemp(prefix="salt-testdaemon-")
|
||||
super(TestProgramCase, self).setUp()
|
||||
super().setUp()
|
||||
|
||||
def tearDown(self):
|
||||
# shutdown for scripts
|
||||
if self._test_dir and os.path.sep == self._test_dir[0]:
|
||||
shutil.rmtree(self._test_dir)
|
||||
self._test_dir = None
|
||||
super(TestProgramCase, self).tearDown()
|
||||
super().tearDown()
|
||||
|
||||
def assert_exit_status(
|
||||
self, status, ex_status, message=None, stdout=None, stderr=None
|
||||
|
@ -1003,13 +957,13 @@ class TestProgramCase(TestCase):
|
|||
"""
|
||||
|
||||
ex_val = getattr(exitcodes, ex_status)
|
||||
_message = "" if not message else " ({0})".format(message)
|
||||
_stdout = "" if not stdout else "\nstdout: {0}".format(stdout)
|
||||
_stderr = "" if not stderr else "\nstderr: {0}".format(stderr)
|
||||
_message = "" if not message else " ({})".format(message)
|
||||
_stdout = "" if not stdout else "\nstdout: {}".format(stdout)
|
||||
_stderr = "" if not stderr else "\nstderr: {}".format(stderr)
|
||||
self.assertEqual(
|
||||
status,
|
||||
ex_val,
|
||||
"Exit status was {0}, must be {1} (salt.default.exitcodes.{2}){3}{4}{5}".format(
|
||||
"Exit status was {}, must be {} (salt.default.exitcodes.{}){}{}{}".format(
|
||||
status, ex_val, ex_status, _message, _stdout, _stderr,
|
||||
),
|
||||
)
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
|
||||
import logging
|
||||
import os
|
||||
import pathlib
|
||||
import shutil
|
||||
|
||||
import pytest
|
||||
|
@ -19,14 +20,27 @@ log = logging.getLogger(__name__)
|
|||
|
||||
|
||||
@pytest.fixture(scope="package")
|
||||
def salt_mm_master_config(request, salt_factories):
|
||||
root_dir = salt_factories._get_root_dir_for_daemon("mm-master")
|
||||
def ext_pillar_file_tree():
|
||||
pillar_file_tree = {
|
||||
"root_dir": str(pathlib.Path(RUNTIME_VARS.PILLAR_DIR) / "base" / "file_tree"),
|
||||
"follow_dir_links": False,
|
||||
"keep_newline": True,
|
||||
}
|
||||
return {"file_tree": pillar_file_tree}
|
||||
|
||||
|
||||
@pytest.fixture(scope="package")
|
||||
def salt_mm_master(request, salt_factories, ext_pillar_file_tree):
|
||||
with salt.utils.files.fopen(
|
||||
os.path.join(RUNTIME_VARS.CONF_DIR, "mm_master")
|
||||
) as rfh:
|
||||
config_defaults = yaml.deserialize(rfh.read())
|
||||
|
||||
config_defaults["root_dir"] = root_dir.strpath
|
||||
master_id = "mm-master"
|
||||
root_dir = salt_factories.get_root_dir_for_daemon(master_id)
|
||||
config_defaults["root_dir"] = str(root_dir)
|
||||
config_defaults["ext_pillar"] = [ext_pillar_file_tree]
|
||||
config_defaults["open_mode"] = True
|
||||
config_defaults["transport"] = request.config.getoption("--transport")
|
||||
|
||||
config_overrides = {
|
||||
|
@ -49,152 +63,125 @@ def salt_mm_master_config(request, salt_factories):
|
|||
"prod": [RUNTIME_VARS.TMP_PRODENV_PILLAR_TREE],
|
||||
},
|
||||
}
|
||||
return salt_factories.configure_master(
|
||||
request,
|
||||
"mm-master",
|
||||
factory = salt_factories.get_salt_master_daemon(
|
||||
master_id,
|
||||
config_defaults=config_defaults,
|
||||
config_overrides=config_overrides,
|
||||
extra_cli_arguments_after_first_start_failure=["--log-level=debug"],
|
||||
)
|
||||
with factory.started():
|
||||
yield factory
|
||||
|
||||
|
||||
@pytest.fixture(scope="package")
|
||||
def salt_mm_minion_config(request, salt_factories, salt_mm_master, salt_mm_sub_master):
|
||||
def salt_mm_sub_master(salt_factories, salt_mm_master, ext_pillar_file_tree):
|
||||
with salt.utils.files.fopen(
|
||||
os.path.join(RUNTIME_VARS.CONF_DIR, "mm_sub_master")
|
||||
) as rfh:
|
||||
config_defaults = yaml.deserialize(rfh.read())
|
||||
|
||||
master_id = "mm-sub-master"
|
||||
root_dir = salt_factories.get_root_dir_for_daemon(master_id)
|
||||
config_defaults["root_dir"] = str(root_dir)
|
||||
config_defaults["ext_pillar"] = [ext_pillar_file_tree]
|
||||
config_defaults["open_mode"] = True
|
||||
config_defaults["transport"] = salt_mm_master.config["transport"]
|
||||
|
||||
config_overrides = {
|
||||
"file_roots": {
|
||||
"base": [
|
||||
RUNTIME_VARS.TMP_STATE_TREE,
|
||||
os.path.join(RUNTIME_VARS.FILES, "file", "base"),
|
||||
],
|
||||
# Alternate root to test __env__ choices
|
||||
"prod": [
|
||||
RUNTIME_VARS.TMP_PRODENV_STATE_TREE,
|
||||
os.path.join(RUNTIME_VARS.FILES, "file", "prod"),
|
||||
],
|
||||
},
|
||||
"pillar_roots": {
|
||||
"base": [
|
||||
RUNTIME_VARS.TMP_PILLAR_TREE,
|
||||
os.path.join(RUNTIME_VARS.FILES, "pillar", "base"),
|
||||
],
|
||||
"prod": [RUNTIME_VARS.TMP_PRODENV_PILLAR_TREE],
|
||||
},
|
||||
}
|
||||
|
||||
factory = salt_factories.get_salt_master_daemon(
|
||||
master_id,
|
||||
config_defaults=config_defaults,
|
||||
config_overrides=config_overrides,
|
||||
extra_cli_arguments_after_first_start_failure=["--log-level=debug"],
|
||||
)
|
||||
|
||||
# The secondary salt master depends on the primarily salt master fixture
|
||||
# because we need to clone the keys
|
||||
for keyfile in ("master.pem", "master.pub"):
|
||||
shutil.copyfile(
|
||||
os.path.join(salt_mm_master.config["pki_dir"], keyfile),
|
||||
os.path.join(factory.config["pki_dir"], keyfile),
|
||||
)
|
||||
with factory.started():
|
||||
yield factory
|
||||
|
||||
|
||||
@pytest.fixture(scope="package")
|
||||
def salt_mm_minion(salt_mm_master, salt_mm_sub_master):
|
||||
with salt.utils.files.fopen(
|
||||
os.path.join(RUNTIME_VARS.CONF_DIR, "mm_minion")
|
||||
) as rfh:
|
||||
config_defaults = yaml.deserialize(rfh.read())
|
||||
config_defaults["hosts.file"] = os.path.join(RUNTIME_VARS.TMP, "hosts")
|
||||
config_defaults["aliases.file"] = os.path.join(RUNTIME_VARS.TMP, "aliases")
|
||||
config_defaults["transport"] = request.config.getoption("--transport")
|
||||
config_defaults["transport"] = salt_mm_master.config["transport"]
|
||||
|
||||
mm_master_port = salt_mm_master.config["ret_port"]
|
||||
mm_sub_master_port = salt_mm_sub_master.config["ret_port"]
|
||||
config_overrides = {
|
||||
"master_port": "",
|
||||
"master": [
|
||||
"localhost:{}".format(mm_master_port),
|
||||
"localhost:{}".format(mm_sub_master_port),
|
||||
],
|
||||
"test.foo": "baz",
|
||||
}
|
||||
return salt_factories.configure_minion(
|
||||
request,
|
||||
factory = salt_mm_master.get_salt_minion_daemon(
|
||||
"mm-minion",
|
||||
master_id=salt_mm_master.config["id"],
|
||||
config_defaults=config_defaults,
|
||||
config_overrides=config_overrides,
|
||||
extra_cli_arguments_after_first_start_failure=["--log-level=debug"],
|
||||
)
|
||||
with factory.started():
|
||||
yield factory
|
||||
|
||||
|
||||
@pytest.fixture(scope="package")
|
||||
def salt_mm_sub_master_config(request, salt_factories, salt_mm_master):
|
||||
with salt.utils.files.fopen(
|
||||
os.path.join(RUNTIME_VARS.CONF_DIR, "mm_sub_master")
|
||||
) as rfh:
|
||||
config_defaults = yaml.deserialize(rfh.read())
|
||||
root_dir = salt_factories._get_root_dir_for_daemon("mm-master")
|
||||
|
||||
config_defaults["root_dir"] = root_dir.strpath
|
||||
config_defaults["transport"] = request.config.getoption("--transport")
|
||||
|
||||
config_overrides = {
|
||||
"file_roots": {
|
||||
"base": [
|
||||
RUNTIME_VARS.TMP_STATE_TREE,
|
||||
os.path.join(RUNTIME_VARS.FILES, "file", "base"),
|
||||
],
|
||||
# Alternate root to test __env__ choices
|
||||
"prod": [
|
||||
RUNTIME_VARS.TMP_PRODENV_STATE_TREE,
|
||||
os.path.join(RUNTIME_VARS.FILES, "file", "prod"),
|
||||
],
|
||||
},
|
||||
"pillar_roots": {
|
||||
"base": [
|
||||
RUNTIME_VARS.TMP_PILLAR_TREE,
|
||||
os.path.join(RUNTIME_VARS.FILES, "pillar", "base"),
|
||||
],
|
||||
"prod": [RUNTIME_VARS.TMP_PRODENV_PILLAR_TREE],
|
||||
},
|
||||
}
|
||||
return salt_factories.configure_master(
|
||||
request,
|
||||
"mm-sub-master",
|
||||
config_defaults=config_defaults,
|
||||
config_overrides=config_overrides,
|
||||
)
|
||||
|
||||
|
||||
@pytest.fixture(scope="package")
|
||||
def salt_mm_sub_minion_config(
|
||||
request, salt_factories, salt_mm_master, salt_mm_sub_master
|
||||
):
|
||||
def salt_mm_sub_minion(salt_mm_master, salt_mm_sub_master):
|
||||
with salt.utils.files.fopen(
|
||||
os.path.join(RUNTIME_VARS.CONF_DIR, "mm_sub_minion")
|
||||
) as rfh:
|
||||
config_defaults = yaml.deserialize(rfh.read())
|
||||
config_defaults["hosts.file"] = os.path.join(RUNTIME_VARS.TMP, "hosts")
|
||||
config_defaults["aliases.file"] = os.path.join(RUNTIME_VARS.TMP, "aliases")
|
||||
config_defaults["transport"] = request.config.getoption("--transport")
|
||||
config_defaults["transport"] = salt_mm_master.config["transport"]
|
||||
|
||||
mm_master_port = salt_mm_master.config["ret_port"]
|
||||
mm_sub_master_port = salt_mm_sub_master.config["ret_port"]
|
||||
config_overrides = {
|
||||
"master_port": "",
|
||||
"master": [
|
||||
"localhost:{}".format(mm_master_port),
|
||||
"localhost:{}".format(mm_sub_master_port),
|
||||
],
|
||||
"test.foo": "baz",
|
||||
}
|
||||
return salt_factories.configure_minion(
|
||||
request,
|
||||
factory = salt_mm_sub_master.get_salt_minion_daemon(
|
||||
"mm-sub-minion",
|
||||
master_id=salt_mm_sub_master.config["id"],
|
||||
config_defaults=config_defaults,
|
||||
config_overrides=config_overrides,
|
||||
extra_cli_arguments_after_first_start_failure=["--log-level=debug"],
|
||||
)
|
||||
|
||||
|
||||
@pytest.fixture(scope="package")
|
||||
def salt_mm_master(request, salt_factories, salt_mm_master_config):
|
||||
return salt_factories.spawn_master(request, "mm-master")
|
||||
|
||||
|
||||
@pytest.fixture(scope="package")
|
||||
def salt_mm_sub_master(
|
||||
request, salt_factories, salt_mm_master, salt_mm_sub_master_config
|
||||
):
|
||||
# The secondary salt master depends on the primarily salt master fixture
|
||||
# because we need to clone the keys
|
||||
for keyfile in ("master.pem", "master.pub"):
|
||||
shutil.copyfile(
|
||||
os.path.join(salt_mm_master.config["pki_dir"], keyfile),
|
||||
os.path.join(salt_mm_sub_master_config["pki_dir"], keyfile),
|
||||
)
|
||||
return salt_factories.spawn_master(request, "mm-sub-master")
|
||||
|
||||
|
||||
@pytest.fixture(scope="package")
|
||||
def salt_mm_minion(
|
||||
request, salt_factories, salt_mm_master, salt_mm_sub_master, salt_mm_minion_config
|
||||
):
|
||||
return salt_factories.spawn_minion(
|
||||
request, "mm-minion", master_id=salt_mm_master.config["id"]
|
||||
)
|
||||
|
||||
|
||||
@pytest.fixture(scope="package")
|
||||
def salt_mm_sub_minion(
|
||||
request,
|
||||
salt_factories,
|
||||
salt_mm_master,
|
||||
salt_mm_sub_master,
|
||||
salt_mm_sub_minion_config,
|
||||
):
|
||||
return salt_factories.spawn_minion(
|
||||
request, "mm-sub-minion", master_id=salt_mm_sub_master.config["id"]
|
||||
)
|
||||
with factory.started():
|
||||
yield factory
|
||||
|
||||
|
||||
@pytest.fixture(scope="package", autouse=True)
|
||||
|
@ -204,10 +191,9 @@ def bridge_pytest_and_runtests( # pylint: disable=function-redefined
|
|||
prod_env_state_tree_root_dir,
|
||||
base_env_pillar_tree_root_dir,
|
||||
prod_env_pillar_tree_root_dir,
|
||||
salt_factories,
|
||||
salt_mm_master,
|
||||
salt_mm_minion,
|
||||
salt_mm_sub_master,
|
||||
salt_mm_minion,
|
||||
salt_mm_sub_minion,
|
||||
):
|
||||
# Make sure unittest2 uses the pytest generated configuration
|
||||
|
|
227
tests/pytests/conftest.py
Normal file
227
tests/pytests/conftest.py
Normal file
|
@ -0,0 +1,227 @@
|
|||
"""
|
||||
tests.pytests.conftest
|
||||
~~~~~~~~~~~~~~~~~~~~~~
|
||||
"""
|
||||
import logging
|
||||
import os
|
||||
import shutil
|
||||
import stat
|
||||
|
||||
import pytest
|
||||
import salt.utils.files
|
||||
import salt.utils.platform
|
||||
from salt.serializers import yaml
|
||||
from saltfactories.utils import random_string
|
||||
from tests.support.helpers import get_virtualenv_binary_path
|
||||
from tests.support.runtests import RUNTIME_VARS
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@pytest.fixture(scope="session")
|
||||
def salt_master_factory(
|
||||
request,
|
||||
salt_factories,
|
||||
base_env_state_tree_root_dir,
|
||||
base_env_pillar_tree_root_dir,
|
||||
prod_env_state_tree_root_dir,
|
||||
prod_env_pillar_tree_root_dir,
|
||||
):
|
||||
master_id = random_string("master-")
|
||||
root_dir = salt_factories.get_root_dir_for_daemon(master_id)
|
||||
conf_dir = root_dir / "conf"
|
||||
conf_dir.mkdir(exist_ok=True)
|
||||
|
||||
with salt.utils.files.fopen(os.path.join(RUNTIME_VARS.CONF_DIR, "master")) as rfh:
|
||||
config_defaults = yaml.deserialize(rfh.read())
|
||||
|
||||
tests_known_hosts_file = str(root_dir / "salt_ssh_known_hosts")
|
||||
with salt.utils.files.fopen(tests_known_hosts_file, "w") as known_hosts:
|
||||
known_hosts.write("")
|
||||
|
||||
config_defaults["root_dir"] = str(root_dir)
|
||||
config_defaults["known_hosts_file"] = tests_known_hosts_file
|
||||
config_defaults["syndic_master"] = "localhost"
|
||||
config_defaults["transport"] = request.config.getoption("--transport")
|
||||
config_defaults["reactor"] = [
|
||||
{"salt/test/reactor": [os.path.join(RUNTIME_VARS.FILES, "reactor-test.sls")]}
|
||||
]
|
||||
|
||||
config_overrides = {}
|
||||
ext_pillar = []
|
||||
if salt.utils.platform.is_windows():
|
||||
ext_pillar.append(
|
||||
{"cmd_yaml": "type {}".format(os.path.join(RUNTIME_VARS.FILES, "ext.yaml"))}
|
||||
)
|
||||
else:
|
||||
ext_pillar.append(
|
||||
{"cmd_yaml": "cat {}".format(os.path.join(RUNTIME_VARS.FILES, "ext.yaml"))}
|
||||
)
|
||||
ext_pillar.append(
|
||||
{
|
||||
"file_tree": {
|
||||
"root_dir": os.path.join(RUNTIME_VARS.PILLAR_DIR, "base", "file_tree"),
|
||||
"follow_dir_links": False,
|
||||
"keep_newline": True,
|
||||
}
|
||||
}
|
||||
)
|
||||
config_overrides["pillar_opts"] = True
|
||||
|
||||
# We need to copy the extension modules into the new master root_dir or
|
||||
# it will be prefixed by it
|
||||
extension_modules_path = str(root_dir / "extension_modules")
|
||||
if not os.path.exists(extension_modules_path):
|
||||
shutil.copytree(
|
||||
os.path.join(RUNTIME_VARS.FILES, "extension_modules"),
|
||||
extension_modules_path,
|
||||
)
|
||||
|
||||
# Copy the autosign_file to the new master root_dir
|
||||
autosign_file_path = str(root_dir / "autosign_file")
|
||||
shutil.copyfile(
|
||||
os.path.join(RUNTIME_VARS.FILES, "autosign_file"), autosign_file_path
|
||||
)
|
||||
# all read, only owner write
|
||||
autosign_file_permissions = (
|
||||
stat.S_IRUSR | stat.S_IRGRP | stat.S_IROTH | stat.S_IWUSR
|
||||
)
|
||||
os.chmod(autosign_file_path, autosign_file_permissions)
|
||||
|
||||
config_overrides.update(
|
||||
{
|
||||
"ext_pillar": ext_pillar,
|
||||
"extension_modules": extension_modules_path,
|
||||
"file_roots": {
|
||||
"base": [
|
||||
str(base_env_state_tree_root_dir),
|
||||
os.path.join(RUNTIME_VARS.FILES, "file", "base"),
|
||||
],
|
||||
# Alternate root to test __env__ choices
|
||||
"prod": [
|
||||
str(prod_env_state_tree_root_dir),
|
||||
os.path.join(RUNTIME_VARS.FILES, "file", "prod"),
|
||||
],
|
||||
},
|
||||
"pillar_roots": {
|
||||
"base": [
|
||||
str(base_env_pillar_tree_root_dir),
|
||||
os.path.join(RUNTIME_VARS.FILES, "pillar", "base"),
|
||||
],
|
||||
"prod": [str(prod_env_pillar_tree_root_dir)],
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
# Let's copy over the test cloud config files and directories into the running master config directory
|
||||
for entry in os.listdir(RUNTIME_VARS.CONF_DIR):
|
||||
if not entry.startswith("cloud"):
|
||||
continue
|
||||
source = os.path.join(RUNTIME_VARS.CONF_DIR, entry)
|
||||
dest = str(conf_dir / entry)
|
||||
if os.path.isdir(source):
|
||||
shutil.copytree(source, dest)
|
||||
else:
|
||||
shutil.copyfile(source, dest)
|
||||
|
||||
factory = salt_factories.get_salt_master_daemon(
|
||||
master_id,
|
||||
config_defaults=config_defaults,
|
||||
config_overrides=config_overrides,
|
||||
extra_cli_arguments_after_first_start_failure=["--log-level=debug"],
|
||||
)
|
||||
return factory
|
||||
|
||||
|
||||
@pytest.fixture(scope="session")
|
||||
def salt_minion_factory(salt_master_factory):
|
||||
with salt.utils.files.fopen(os.path.join(RUNTIME_VARS.CONF_DIR, "minion")) as rfh:
|
||||
config_defaults = yaml.deserialize(rfh.read())
|
||||
config_defaults["hosts.file"] = os.path.join(RUNTIME_VARS.TMP, "hosts")
|
||||
config_defaults["aliases.file"] = os.path.join(RUNTIME_VARS.TMP, "aliases")
|
||||
config_defaults["transport"] = salt_master_factory.config["transport"]
|
||||
|
||||
config_overrides = {
|
||||
"file_roots": salt_master_factory.config["file_roots"].copy(),
|
||||
"pillar_roots": salt_master_factory.config["pillar_roots"].copy(),
|
||||
}
|
||||
|
||||
virtualenv_binary = get_virtualenv_binary_path()
|
||||
if virtualenv_binary:
|
||||
config_overrides["venv_bin"] = virtualenv_binary
|
||||
factory = salt_master_factory.get_salt_minion_daemon(
|
||||
random_string("minion-"),
|
||||
config_defaults=config_defaults,
|
||||
config_overrides=config_overrides,
|
||||
extra_cli_arguments_after_first_start_failure=["--log-level=debug"],
|
||||
)
|
||||
factory.register_after_terminate_callback(
|
||||
pytest.helpers.remove_stale_minion_key, salt_master_factory, factory.id
|
||||
)
|
||||
return factory
|
||||
|
||||
|
||||
@pytest.fixture(scope="session")
|
||||
def salt_sub_minion_factory(salt_master_factory):
|
||||
with salt.utils.files.fopen(
|
||||
os.path.join(RUNTIME_VARS.CONF_DIR, "sub_minion")
|
||||
) as rfh:
|
||||
config_defaults = yaml.deserialize(rfh.read())
|
||||
config_defaults["hosts.file"] = os.path.join(RUNTIME_VARS.TMP, "hosts")
|
||||
config_defaults["aliases.file"] = os.path.join(RUNTIME_VARS.TMP, "aliases")
|
||||
config_defaults["transport"] = salt_master_factory.config["transport"]
|
||||
|
||||
config_overrides = {
|
||||
"file_roots": salt_master_factory.config["file_roots"].copy(),
|
||||
"pillar_roots": salt_master_factory.config["pillar_roots"].copy(),
|
||||
}
|
||||
|
||||
virtualenv_binary = get_virtualenv_binary_path()
|
||||
if virtualenv_binary:
|
||||
config_overrides["venv_bin"] = virtualenv_binary
|
||||
factory = salt_master_factory.get_salt_minion_daemon(
|
||||
random_string("sub-minion-"),
|
||||
config_defaults=config_defaults,
|
||||
config_overrides=config_overrides,
|
||||
extra_cli_arguments_after_first_start_failure=["--log-level=debug"],
|
||||
)
|
||||
factory.register_after_terminate_callback(
|
||||
pytest.helpers.remove_stale_minion_key, salt_master_factory, factory.id
|
||||
)
|
||||
return factory
|
||||
|
||||
|
||||
@pytest.fixture(scope="session")
|
||||
def salt_proxy_factory(salt_factories, salt_master_factory):
|
||||
proxy_minion_id = random_string("proxytest-")
|
||||
root_dir = salt_factories.get_root_dir_for_daemon(proxy_minion_id)
|
||||
conf_dir = root_dir / "conf"
|
||||
conf_dir.mkdir(parents=True, exist_ok=True)
|
||||
RUNTIME_VARS.TMP_PROXY_CONF_DIR = str(conf_dir)
|
||||
|
||||
with salt.utils.files.fopen(os.path.join(RUNTIME_VARS.CONF_DIR, "proxy")) as rfh:
|
||||
config_defaults = yaml.deserialize(rfh.read())
|
||||
|
||||
config_defaults["root_dir"] = str(root_dir)
|
||||
config_defaults["hosts.file"] = os.path.join(RUNTIME_VARS.TMP, "hosts")
|
||||
config_defaults["aliases.file"] = os.path.join(RUNTIME_VARS.TMP, "aliases")
|
||||
config_defaults["transport"] = salt_master_factory.config["transport"]
|
||||
config_defaults["user"] = salt_master_factory.config["user"]
|
||||
|
||||
factory = salt_master_factory.get_salt_proxy_minion_daemon(
|
||||
proxy_minion_id,
|
||||
config_defaults=config_defaults,
|
||||
extra_cli_arguments_after_first_start_failure=["--log-level=debug"],
|
||||
start_timeout=240,
|
||||
)
|
||||
factory.register_after_terminate_callback(
|
||||
pytest.helpers.remove_stale_minion_key, salt_master_factory, factory.id
|
||||
)
|
||||
return factory
|
||||
|
||||
|
||||
@pytest.fixture(scope="session")
|
||||
def bridge_pytest_and_runtests():
|
||||
"""
|
||||
We're basically overriding the same fixture defined in tests/conftest.py
|
||||
"""
|
|
@ -1,51 +1,108 @@
|
|||
"""
|
||||
tests.pytests.integration.conftest
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
PyTest fixtures
|
||||
"""
|
||||
import pytest
|
||||
|
||||
|
||||
@pytest.fixture(scope="package")
|
||||
def salt_master(request, salt_factories, salt_master_config):
|
||||
return salt_factories.spawn_master(request, "master")
|
||||
def salt_master(salt_master_factory):
|
||||
"""
|
||||
A running salt-master fixture
|
||||
"""
|
||||
with salt_master_factory.started():
|
||||
yield salt_master_factory
|
||||
|
||||
|
||||
@pytest.fixture(scope="package")
|
||||
def salt_minion(request, salt_factories, salt_master, salt_minion_config):
|
||||
proc = salt_factories.spawn_minion(request, "minion", master_id="master")
|
||||
# Sync All
|
||||
salt_call_cli = salt_factories.get_salt_call_cli("minion")
|
||||
ret = salt_call_cli.run("saltutil.sync_all", _timeout=120)
|
||||
assert ret.exitcode == 0, ret
|
||||
return proc
|
||||
def salt_minion(salt_master, salt_minion_factory):
|
||||
"""
|
||||
A running salt-minion fixture
|
||||
"""
|
||||
assert salt_master.is_running()
|
||||
with salt_minion_factory.started():
|
||||
# Sync All
|
||||
salt_call_cli = salt_minion_factory.get_salt_call_cli()
|
||||
ret = salt_call_cli.run("saltutil.sync_all", _timeout=120)
|
||||
assert ret.exitcode == 0, ret
|
||||
yield salt_minion_factory
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def salt_sub_minion(salt_master, salt_sub_minion_factory):
|
||||
"""
|
||||
A second running salt-minion fixture
|
||||
"""
|
||||
assert salt_master.is_running()
|
||||
with salt_sub_minion_factory.started():
|
||||
# Sync All
|
||||
salt_call_cli = salt_sub_minion_factory.get_salt_call_cli()
|
||||
ret = salt_call_cli.run("saltutil.sync_all", _timeout=120)
|
||||
assert ret.exitcode == 0, ret
|
||||
yield salt_sub_minion_factory
|
||||
|
||||
|
||||
@pytest.fixture(scope="package")
|
||||
def salt_sub_minion(request, salt_factories, salt_master, salt_sub_minion_config):
|
||||
proc = salt_factories.spawn_minion(request, "sub_minion", master_id="master")
|
||||
# Sync All
|
||||
salt_call_cli = salt_factories.get_salt_call_cli("sub_minion")
|
||||
ret = salt_call_cli.run("saltutil.sync_all", _timeout=120)
|
||||
assert ret.exitcode == 0, ret
|
||||
return proc
|
||||
def salt_proxy(salt_master, salt_proxy_factory):
|
||||
"""
|
||||
A running salt-proxy fixture
|
||||
"""
|
||||
assert salt_master.is_running()
|
||||
with salt_proxy_factory.started():
|
||||
yield salt_proxy_factory
|
||||
|
||||
|
||||
@pytest.fixture(scope="package")
|
||||
def salt_cli(salt_factories, salt_minion, salt_master):
|
||||
return salt_factories.get_salt_cli(salt_master.config["id"])
|
||||
def salt_cli(salt_master):
|
||||
"""
|
||||
The ``salt`` CLI as a fixture against the running master
|
||||
"""
|
||||
assert salt_master.is_running()
|
||||
return salt_master.get_salt_cli()
|
||||
|
||||
|
||||
@pytest.fixture(scope="package")
|
||||
def salt_cp_cli(salt_factories, salt_minion, salt_master):
|
||||
return salt_factories.get_salt_cp_cli(salt_master.config["id"])
|
||||
def salt_call_cli(salt_minion):
|
||||
"""
|
||||
The ``salt-call`` CLI as a fixture against the running minion
|
||||
"""
|
||||
assert salt_minion.is_running()
|
||||
return salt_minion.get_salt_call_cli()
|
||||
|
||||
|
||||
@pytest.fixture(scope="package")
|
||||
def salt_key_cli(salt_factories, salt_minion, salt_master):
|
||||
return salt_factories.get_salt_key_cli(salt_master.config["id"])
|
||||
def salt_cp_cli(salt_master):
|
||||
"""
|
||||
The ``salt-cp`` CLI as a fixture against the running master
|
||||
"""
|
||||
assert salt_master.is_running()
|
||||
return salt_master.get_salt_cp_cli()
|
||||
|
||||
|
||||
@pytest.fixture(scope="package")
|
||||
def salt_run_cli(salt_factories, salt_minion, salt_master):
|
||||
return salt_factories.get_salt_run_cli(salt_master.config["id"])
|
||||
def salt_key_cli(salt_master):
|
||||
"""
|
||||
The ``salt-key`` CLI as a fixture against the running master
|
||||
"""
|
||||
assert salt_master.is_running()
|
||||
return salt_master.get_salt_key_cli()
|
||||
|
||||
|
||||
@pytest.fixture(scope="package")
|
||||
def salt_call_cli(salt_factories, salt_minion, salt_master):
|
||||
return salt_factories.get_salt_call_cli(salt_minion.config["id"])
|
||||
def salt_run_cli(salt_master):
|
||||
"""
|
||||
The ``salt-run`` CLI as a fixture against the running master
|
||||
"""
|
||||
assert salt_master.is_running()
|
||||
return salt_master.get_salt_run_cli()
|
||||
|
||||
|
||||
@pytest.fixture(scope="package")
|
||||
def salt_ssh_cli(salt_master):
|
||||
"""
|
||||
The ``salt-ssh`` CLI as a fixture against the running master
|
||||
"""
|
||||
assert salt_master.is_running()
|
||||
return salt_master.get_salt_ssh_cli()
|
||||
|
|
|
@ -2,17 +2,13 @@
|
|||
Validate the virt module
|
||||
"""
|
||||
import logging
|
||||
import pathlib
|
||||
from numbers import Number
|
||||
from xml.etree import ElementTree
|
||||
|
||||
import pytest
|
||||
from saltfactories.utils import cli_scripts
|
||||
from tests.support.helpers import skip_if_binaries_missing, slowTest
|
||||
from tests.support.saltfactories_compat import (
|
||||
ContainerFactory,
|
||||
SaltVirtMinionContainerFactory,
|
||||
)
|
||||
from tests.support.virt import SaltVirtMinionContainerFactory
|
||||
|
||||
docker = pytest.importorskip("docker")
|
||||
|
||||
|
@ -26,7 +22,7 @@ def docker_client():
|
|||
urllib3_connectionpool_handler.setLevel(logging.INFO)
|
||||
try:
|
||||
client = docker.from_env()
|
||||
connectable = ContainerFactory.client_connectable(client)
|
||||
connectable = SaltVirtMinionContainerFactory.client_connectable(client)
|
||||
if connectable is not True: # pragma: no cover
|
||||
pytest.skip(connectable)
|
||||
client.images.pull("quay.io/rst0git/virt-minion")
|
||||
|
@ -65,10 +61,7 @@ def virt_minion_0(
|
|||
virt_minion_0_id,
|
||||
virt_minion_1_id,
|
||||
):
|
||||
salt_master.id = salt_master.config["id"]
|
||||
root_dir = pathlib.Path(
|
||||
salt_factories._get_root_dir_for_daemon(virt_minion_0_id).strpath
|
||||
)
|
||||
root_dir = salt_factories.get_root_dir_for_daemon(virt_minion_0_id)
|
||||
config_defaults = {
|
||||
"root_dir": str(root_dir),
|
||||
"id": virt_minion_0_id,
|
||||
|
@ -102,6 +95,9 @@ def virt_minion_0(
|
|||
}
|
||||
},
|
||||
)
|
||||
factory.register_after_terminate_callback(
|
||||
pytest.helpers.remove_stale_minion_key, salt_master, factory.id
|
||||
)
|
||||
with factory.started():
|
||||
yield factory
|
||||
|
||||
|
@ -115,10 +111,7 @@ def virt_minion_1(
|
|||
virt_minion_0_id,
|
||||
virt_minion_1_id,
|
||||
):
|
||||
salt_master.id = salt_master.config["id"]
|
||||
root_dir = pathlib.Path(
|
||||
salt_factories._get_root_dir_for_daemon(virt_minion_1_id).strpath
|
||||
)
|
||||
root_dir = salt_factories.get_root_dir_for_daemon(virt_minion_1_id)
|
||||
config_defaults = {
|
||||
"root_dir": str(root_dir),
|
||||
"id": virt_minion_1_id,
|
||||
|
@ -152,13 +145,16 @@ def virt_minion_1(
|
|||
}
|
||||
},
|
||||
)
|
||||
factory.register_after_terminate_callback(
|
||||
pytest.helpers.remove_stale_minion_key, salt_master, factory.id
|
||||
)
|
||||
with factory.started():
|
||||
yield factory
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def salt_cli(salt_factories, salt_master, virt_minion_0, virt_minion_1):
|
||||
return salt_factories.get_salt_cli(salt_master.config["id"])
|
||||
def salt_cli(salt_master, virt_minion_0, virt_minion_1):
|
||||
return salt_master.get_salt_cli()
|
||||
|
||||
|
||||
@skip_if_binaries_missing("docker")
|
||||
|
|
|
@ -23,10 +23,11 @@ import textwrap
|
|||
import time
|
||||
from datetime import datetime, timedelta
|
||||
|
||||
import pytest
|
||||
import salt.utils.files
|
||||
from saltfactories.utils.processes.helpers import terminate_process
|
||||
from saltfactories.utils.processes import terminate_process
|
||||
from tests.support.cli_scripts import ScriptPathMixin
|
||||
from tests.support.helpers import RedirectStdStreams, requires_sshd_server
|
||||
from tests.support.helpers import SKIP_IF_NOT_RUNNING_PYTEST, RedirectStdStreams
|
||||
from tests.support.mixins import ( # pylint: disable=unused-import
|
||||
AdaptedConfigurationTestCaseMixin,
|
||||
SaltClientTestCaseMixin,
|
||||
|
@ -107,14 +108,17 @@ class ShellCase(TestCase, AdaptedConfigurationTestCaseMixin, ScriptPathMixin):
|
|||
timeout = self.RUN_TIMEOUT
|
||||
if not roster_file:
|
||||
roster_file = os.path.join(RUNTIME_VARS.TMP_CONF_DIR, "roster")
|
||||
arg_str = "{} {} -l{} -i --priv {} --roster-file {} {} localhost {} --out=json".format(
|
||||
" -W" if wipe else "",
|
||||
" -r" if raw else "",
|
||||
log_level,
|
||||
os.path.join(RUNTIME_VARS.TMP_CONF_DIR, "key_test"),
|
||||
roster_file,
|
||||
ssh_opts,
|
||||
arg_str,
|
||||
arg_str = (
|
||||
"{wipe} {raw} -l {log_level} --ignore-host-keys --priv {client_key} --roster-file "
|
||||
"{roster_file} {ssh_opts} localhost {arg_str} --out=json"
|
||||
).format(
|
||||
wipe=" -W" if wipe else "",
|
||||
raw=" -r" if raw else "",
|
||||
log_level=log_level,
|
||||
client_key=os.path.join(RUNTIME_VARS.TMP_SSH_CONF_DIR, "client_key"),
|
||||
roster_file=roster_file,
|
||||
ssh_opts=ssh_opts,
|
||||
arg_str=arg_str,
|
||||
)
|
||||
ret = self.run_script(
|
||||
"salt-ssh",
|
||||
|
@ -453,6 +457,7 @@ class ShellCase(TestCase, AdaptedConfigurationTestCaseMixin, ScriptPathMixin):
|
|||
|
||||
return ret[0] if len(ret) == 1 else tuple(ret)
|
||||
|
||||
log.debug("Running Popen(%r, %r)", cmd, popen_kwargs)
|
||||
process = subprocess.Popen(cmd, **popen_kwargs)
|
||||
|
||||
if timeout is not None:
|
||||
|
@ -931,7 +936,9 @@ class SyndicCase(TestCase, SaltClientTestCaseMixin):
|
|||
return orig["minion"]
|
||||
|
||||
|
||||
@requires_sshd_server
|
||||
@SKIP_IF_NOT_RUNNING_PYTEST
|
||||
@pytest.mark.usefixtures("salt_ssh_cli")
|
||||
@pytest.mark.requires_sshd_server
|
||||
class SSHCase(ShellCase):
|
||||
"""
|
||||
Execute a command via salt-ssh
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
tests.support.cli_scripts
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
@ -6,13 +5,11 @@
|
|||
Code to generate Salt CLI scripts for test runs
|
||||
"""
|
||||
|
||||
from __future__ import absolute_import, unicode_literals
|
||||
|
||||
import logging
|
||||
import os
|
||||
import sys
|
||||
|
||||
from saltfactories.utils import cli_scripts
|
||||
from tests.support.saltfactories_compat import generate_script
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
@ -31,10 +28,9 @@ def get_script_path(bin_dir, script_name):
|
|||
script_path = os.path.join(bin_dir, cli_script_name)
|
||||
|
||||
if not os.path.isfile(script_path):
|
||||
cli_scripts.generate_script(
|
||||
generate_script(
|
||||
bin_dir=bin_dir,
|
||||
script_name=script_name,
|
||||
executable=sys.executable,
|
||||
code_dir=RUNTIME_VARS.CODE_DIR,
|
||||
inject_coverage="COVERAGE_PROCESS_START" in os.environ,
|
||||
inject_sitecustomize="COVERAGE_PROCESS_START" in os.environ,
|
||||
|
@ -43,7 +39,7 @@ def get_script_path(bin_dir, script_name):
|
|||
return script_path
|
||||
|
||||
|
||||
class ScriptPathMixin(object):
|
||||
class ScriptPathMixin:
|
||||
def get_script_path(self, script_name):
|
||||
"""
|
||||
Return the path to a testing runtime script
|
||||
|
|
|
@ -9,7 +9,7 @@ import shutil
|
|||
import tempfile
|
||||
import textwrap
|
||||
|
||||
import attr # pylint: disable=3rd-party-module-not-gated
|
||||
import attr
|
||||
import pytest
|
||||
import salt.utils.files
|
||||
import salt.utils.path
|
||||
|
@ -18,6 +18,8 @@ import salt.utils.yaml
|
|||
from salt.fileserver import gitfs
|
||||
from salt.pillar import git_pillar
|
||||
from salt.utils.immutabletypes import freeze
|
||||
from saltfactories.factories.base import DaemonFactory
|
||||
from saltfactories.factories.daemons.sshd import SshdDaemonFactory as _SshdDaemonFactory
|
||||
from saltfactories.utils.ports import get_unused_localhost_port
|
||||
from tests.support.case import ModuleCase
|
||||
from tests.support.helpers import (
|
||||
|
@ -28,8 +30,6 @@ from tests.support.helpers import (
|
|||
from tests.support.mixins import LoaderModuleMockMixin
|
||||
from tests.support.mock import patch
|
||||
from tests.support.runtests import RUNTIME_VARS
|
||||
from tests.support.saltfactories_compat import DaemonFactory
|
||||
from tests.support.saltfactories_compat import SshdDaemonFactory as _SshdDaemonFactory
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
@ -269,15 +269,11 @@ class NginxDaemon(DaemonFactory):
|
|||
|
||||
|
||||
@pytest.fixture(scope="class")
|
||||
def ssh_pillar_tests_prep(request, salt_factories, salt_master, salt_minion):
|
||||
def ssh_pillar_tests_prep(request, salt_master, salt_minion):
|
||||
"""
|
||||
Stand up an SSHD server to serve up git repos for tests.
|
||||
"""
|
||||
try:
|
||||
salt_call_cli = salt_minion.get_salt_call_cli()
|
||||
raise RuntimeError("s0undt3ch, it's time to cleanup this spaghetti code!")
|
||||
except AttributeError:
|
||||
salt_call_cli = salt_factories.get_salt_call_cli(salt_minion.config["id"])
|
||||
salt_call_cli = salt_minion.get_salt_call_cli()
|
||||
|
||||
sshd_bin = salt.utils.path.which("sshd")
|
||||
sshd_config_dir = tempfile.mkdtemp(dir=RUNTIME_VARS.TMP)
|
||||
|
@ -325,16 +321,12 @@ def ssh_pillar_tests_prep(request, salt_factories, salt_master, salt_minion):
|
|||
|
||||
|
||||
@pytest.fixture(scope="class")
|
||||
def webserver_pillar_tests_prep(request, salt_factories, salt_master, salt_minion):
|
||||
def webserver_pillar_tests_prep(request, salt_master, salt_minion):
|
||||
"""
|
||||
Stand up an nginx + uWSGI + git-http-backend webserver to
|
||||
serve up git repos for tests.
|
||||
"""
|
||||
try:
|
||||
salt_call_cli = salt_minion.get_salt_call_cli()
|
||||
raise RuntimeError("s0undt3ch, it's time to cleanup this spaghetti code!")
|
||||
except AttributeError:
|
||||
salt_call_cli = salt_factories.get_salt_call_cli(salt_minion.config["id"])
|
||||
salt_call_cli = salt_minion.get_salt_call_cli()
|
||||
|
||||
root_dir = tempfile.mkdtemp(dir=RUNTIME_VARS.TMP)
|
||||
config_dir = os.path.join(root_dir, "config")
|
||||
|
|
|
@ -39,9 +39,9 @@ import salt.utils.stringutils
|
|||
import salt.utils.versions
|
||||
from salt.ext import six
|
||||
from salt.ext.six.moves import builtins
|
||||
from saltfactories.exceptions import ProcessFailed
|
||||
from saltfactories.exceptions import FactoryFailure as ProcessFailed
|
||||
from saltfactories.utils.ports import get_unused_localhost_port
|
||||
from saltfactories.utils.processes.bases import ProcessResult
|
||||
from saltfactories.utils.processes import ProcessResult
|
||||
from tests.support.mock import patch
|
||||
from tests.support.runtests import RUNTIME_VARS
|
||||
from tests.support.sminion import create_sminion
|
||||
|
@ -176,6 +176,7 @@ def slowTest(caller):
|
|||
|
||||
if RUNTIME_VARS.PYTEST_SESSION:
|
||||
setattr(caller, "__slow_test__", True)
|
||||
return caller
|
||||
|
||||
if os.environ.get("SLOW_TESTS", "False").lower() == "false":
|
||||
reason = "Slow tests are disabled"
|
||||
|
@ -285,27 +286,9 @@ def requires_sshd_server(caller):
|
|||
def test_create_user(self):
|
||||
pass
|
||||
"""
|
||||
if inspect.isclass(caller):
|
||||
# We're decorating a class
|
||||
old_setup = getattr(caller, "setUp", None)
|
||||
|
||||
def setUp(self, *args, **kwargs):
|
||||
if os.environ.get("SSH_DAEMON_RUNNING", "False").lower() == "false":
|
||||
self.skipTest("SSH tests are disabled")
|
||||
if old_setup is not None:
|
||||
old_setup(self, *args, **kwargs)
|
||||
|
||||
caller.setUp = setUp
|
||||
return caller
|
||||
|
||||
# We're simply decorating functions
|
||||
@functools.wraps(caller)
|
||||
def wrap(cls):
|
||||
if os.environ.get("SSH_DAEMON_RUNNING", "False").lower() == "false":
|
||||
cls.skipTest("SSH tests are disabled")
|
||||
return caller(cls)
|
||||
|
||||
return wrap
|
||||
raise RuntimeError(
|
||||
"Please replace @requires_sshd_server with @pytest.mark.requires_sshd_server"
|
||||
)
|
||||
|
||||
|
||||
class RedirectStdStreams:
|
||||
|
@ -1673,7 +1656,12 @@ class VirtualEnv:
|
|||
kwargs.setdefault("stderr", subprocess.PIPE)
|
||||
kwargs.setdefault("universal_newlines", True)
|
||||
proc = subprocess.run(args, check=False, **kwargs)
|
||||
ret = ProcessResult(proc.returncode, proc.stdout, proc.stderr, proc.args)
|
||||
ret = ProcessResult(
|
||||
exitcode=proc.returncode,
|
||||
stdout=proc.stdout,
|
||||
stderr=proc.stderr,
|
||||
cmdline=proc.args,
|
||||
)
|
||||
log.debug(ret)
|
||||
if check is True:
|
||||
try:
|
||||
|
|
|
@ -77,6 +77,7 @@ TMP_MM_SUB_CONF_DIR = TMP_MM_SUB_MINION_CONF_DIR = os.path.join(
|
|||
TMP_CONF_DIR, "sub-multimaster"
|
||||
)
|
||||
TMP_PROXY_CONF_DIR = TMP_CONF_DIR
|
||||
TMP_SSH_CONF_DIR = TMP_MINION_CONF_DIR
|
||||
CONF_DIR = os.path.join(INTEGRATION_TEST_DIR, "files", "conf")
|
||||
PILLAR_DIR = os.path.join(FILES, "pillar")
|
||||
TMP_SCRIPT_DIR = os.path.join(TMP, "scripts")
|
||||
|
|
|
@ -12,12 +12,13 @@
|
|||
|
||||
import logging
|
||||
|
||||
from saltfactories.utils.processes.helpers import ( # pylint: disable=unused-import
|
||||
from saltfactories.utils.processes import ( # pylint: disable=unused-import
|
||||
collect_child_processes,
|
||||
terminate_process,
|
||||
terminate_process_list,
|
||||
)
|
||||
from tests.support.cli_scripts import ScriptPathMixin
|
||||
from tests.support.cli_scripts import ScriptPathMixin, get_script_path
|
||||
from tests.support.runtests import RUNTIME_VARS
|
||||
|
||||
try:
|
||||
from pytestsalt.fixtures.daemons import Salt as PytestSalt
|
||||
|
@ -32,14 +33,14 @@ except ImportError:
|
|||
# If this happens, we are running under pytest which uninstalls pytest-salt due to impatabilites
|
||||
# These imports won't actually work but these classes are only used when running under runtests,
|
||||
# so, we're just making sure we also don't hit NameError's
|
||||
from saltfactories.utils.processes.salts import SaltCallCLI as PytestSaltCall
|
||||
from saltfactories.utils.processes.salts import SaltCLI as PytestSalt
|
||||
from saltfactories.utils.processes.salts import SaltKeyCLI as PytestSaltKey
|
||||
from saltfactories.utils.processes.salts import SaltMaster as PytestSaltMaster
|
||||
from saltfactories.utils.processes.salts import SaltMinion as PytestSaltMinion
|
||||
from saltfactories.utils.processes.salts import SaltProxyMinion as PytestSaltProxy
|
||||
from saltfactories.utils.processes.salts import SaltRunCLI as PytestSaltRun
|
||||
from saltfactories.utils.processes.salts import SaltSyndic as PytestSaltSyndic
|
||||
from tests.support.saltfactories_compat import SaltCallCLI as PytestSaltCall
|
||||
from tests.support.saltfactories_compat import SaltCLI as PytestSalt
|
||||
from tests.support.saltfactories_compat import SaltKeyCLI as PytestSaltKey
|
||||
from tests.support.saltfactories_compat import SaltMaster as PytestSaltMaster
|
||||
from tests.support.saltfactories_compat import SaltMinion as PytestSaltMinion
|
||||
from tests.support.saltfactories_compat import SaltProxyMinion as PytestSaltProxy
|
||||
from tests.support.saltfactories_compat import SaltRunCLI as PytestSaltRun
|
||||
from tests.support.saltfactories_compat import SaltSyndic as PytestSaltSyndic
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
@ -144,6 +145,7 @@ def start_daemon(
|
|||
log.info("[%s] Starting pytest %s(%s)", daemon_name, daemon_log_prefix, daemon_id)
|
||||
attempts = 0
|
||||
process = None
|
||||
get_script_path(RUNTIME_VARS.TMP_SCRIPT_DIR, daemon_cli_script_name)
|
||||
while attempts <= 3: # pylint: disable=too-many-nested-blocks
|
||||
attempts += 1
|
||||
try:
|
||||
|
|
|
@ -1,475 +0,0 @@
|
|||
"""
|
||||
tests.support.pytest.fixtures
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The purpose of this fixtures module is provide the same set of available fixture for the old unittest
|
||||
test suite under ``test/integration``, ``tests/multimaster`` and ``tests/unit``.
|
||||
|
||||
Please refrain from adding fixtures to this module and instead add them to the appropriate
|
||||
``conftest.py`` file.
|
||||
"""
|
||||
import os
|
||||
import shutil
|
||||
import stat
|
||||
|
||||
import pytest
|
||||
import salt.utils.files
|
||||
from salt.serializers import yaml
|
||||
from salt.utils.immutabletypes import freeze
|
||||
from tests.support.helpers import get_virtualenv_binary_path
|
||||
from tests.support.runtests import RUNTIME_VARS
|
||||
|
||||
|
||||
@pytest.fixture(scope="session")
|
||||
def integration_files_dir(salt_factories):
|
||||
"""
|
||||
Fixture which returns the salt integration files directory path.
|
||||
Creates the directory if it does not yet exist.
|
||||
"""
|
||||
dirname = salt_factories.root_dir.join("integration-files")
|
||||
dirname.ensure(dir=True)
|
||||
return dirname
|
||||
|
||||
|
||||
@pytest.fixture(scope="session")
|
||||
def state_tree_root_dir(integration_files_dir):
|
||||
"""
|
||||
Fixture which returns the salt state tree root directory path.
|
||||
Creates the directory if it does not yet exist.
|
||||
"""
|
||||
dirname = integration_files_dir.join("state-tree")
|
||||
dirname.ensure(dir=True)
|
||||
return dirname
|
||||
|
||||
|
||||
@pytest.fixture(scope="session")
|
||||
def pillar_tree_root_dir(integration_files_dir):
|
||||
"""
|
||||
Fixture which returns the salt pillar tree root directory path.
|
||||
Creates the directory if it does not yet exist.
|
||||
"""
|
||||
dirname = integration_files_dir.join("pillar-tree")
|
||||
dirname.ensure(dir=True)
|
||||
return dirname
|
||||
|
||||
|
||||
@pytest.fixture(scope="session")
|
||||
def base_env_state_tree_root_dir(state_tree_root_dir):
|
||||
"""
|
||||
Fixture which returns the salt base environment state tree directory path.
|
||||
Creates the directory if it does not yet exist.
|
||||
"""
|
||||
dirname = state_tree_root_dir.join("base")
|
||||
dirname.ensure(dir=True)
|
||||
RUNTIME_VARS.TMP_STATE_TREE = dirname.realpath().strpath
|
||||
RUNTIME_VARS.TMP_BASEENV_STATE_TREE = RUNTIME_VARS.TMP_STATE_TREE
|
||||
return dirname
|
||||
|
||||
|
||||
@pytest.fixture(scope="session")
|
||||
def prod_env_state_tree_root_dir(state_tree_root_dir):
|
||||
"""
|
||||
Fixture which returns the salt prod environment state tree directory path.
|
||||
Creates the directory if it does not yet exist.
|
||||
"""
|
||||
dirname = state_tree_root_dir.join("prod")
|
||||
dirname.ensure(dir=True)
|
||||
RUNTIME_VARS.TMP_PRODENV_STATE_TREE = dirname.realpath().strpath
|
||||
return dirname
|
||||
|
||||
|
||||
@pytest.fixture(scope="session")
|
||||
def base_env_pillar_tree_root_dir(pillar_tree_root_dir):
|
||||
"""
|
||||
Fixture which returns the salt base environment pillar tree directory path.
|
||||
Creates the directory if it does not yet exist.
|
||||
"""
|
||||
dirname = pillar_tree_root_dir.join("base")
|
||||
dirname.ensure(dir=True)
|
||||
RUNTIME_VARS.TMP_PILLAR_TREE = dirname.realpath().strpath
|
||||
RUNTIME_VARS.TMP_BASEENV_PILLAR_TREE = RUNTIME_VARS.TMP_PILLAR_TREE
|
||||
return dirname
|
||||
|
||||
|
||||
@pytest.fixture(scope="session")
|
||||
def prod_env_pillar_tree_root_dir(pillar_tree_root_dir):
|
||||
"""
|
||||
Fixture which returns the salt prod environment pillar tree directory path.
|
||||
Creates the directory if it does not yet exist.
|
||||
"""
|
||||
dirname = pillar_tree_root_dir.join("prod")
|
||||
dirname.ensure(dir=True)
|
||||
RUNTIME_VARS.TMP_PRODENV_PILLAR_TREE = dirname.realpath().strpath
|
||||
return dirname
|
||||
|
||||
|
||||
@pytest.fixture(scope="session")
|
||||
def salt_syndic_master_config(request, salt_factories):
|
||||
root_dir = salt_factories._get_root_dir_for_daemon("syndic_master")
|
||||
|
||||
with salt.utils.files.fopen(
|
||||
os.path.join(RUNTIME_VARS.CONF_DIR, "syndic_master")
|
||||
) as rfh:
|
||||
config_defaults = yaml.deserialize(rfh.read())
|
||||
|
||||
tests_known_hosts_file = root_dir.join("salt_ssh_known_hosts").strpath
|
||||
with salt.utils.files.fopen(tests_known_hosts_file, "w") as known_hosts:
|
||||
known_hosts.write("")
|
||||
|
||||
config_defaults["root_dir"] = root_dir.strpath
|
||||
config_defaults["known_hosts_file"] = tests_known_hosts_file
|
||||
config_defaults["syndic_master"] = "localhost"
|
||||
config_defaults["transport"] = request.config.getoption("--transport")
|
||||
|
||||
config_overrides = {}
|
||||
ext_pillar = []
|
||||
if salt.utils.platform.is_windows():
|
||||
ext_pillar.append(
|
||||
{"cmd_yaml": "type {}".format(os.path.join(RUNTIME_VARS.FILES, "ext.yaml"))}
|
||||
)
|
||||
else:
|
||||
ext_pillar.append(
|
||||
{"cmd_yaml": "cat {}".format(os.path.join(RUNTIME_VARS.FILES, "ext.yaml"))}
|
||||
)
|
||||
|
||||
# We need to copy the extension modules into the new master root_dir or
|
||||
# it will be prefixed by it
|
||||
extension_modules_path = root_dir.join("extension_modules").strpath
|
||||
if not os.path.exists(extension_modules_path):
|
||||
shutil.copytree(
|
||||
os.path.join(RUNTIME_VARS.FILES, "extension_modules"),
|
||||
extension_modules_path,
|
||||
)
|
||||
|
||||
# Copy the autosign_file to the new master root_dir
|
||||
autosign_file_path = root_dir.join("autosign_file").strpath
|
||||
shutil.copyfile(
|
||||
os.path.join(RUNTIME_VARS.FILES, "autosign_file"), autosign_file_path
|
||||
)
|
||||
# all read, only owner write
|
||||
autosign_file_permissions = (
|
||||
stat.S_IRUSR | stat.S_IRGRP | stat.S_IROTH | stat.S_IWUSR
|
||||
)
|
||||
os.chmod(autosign_file_path, autosign_file_permissions)
|
||||
|
||||
config_overrides.update(
|
||||
{
|
||||
"ext_pillar": ext_pillar,
|
||||
"extension_modules": extension_modules_path,
|
||||
"file_roots": {
|
||||
"base": [
|
||||
RUNTIME_VARS.TMP_STATE_TREE,
|
||||
os.path.join(RUNTIME_VARS.FILES, "file", "base"),
|
||||
],
|
||||
# Alternate root to test __env__ choices
|
||||
"prod": [
|
||||
RUNTIME_VARS.TMP_PRODENV_STATE_TREE,
|
||||
os.path.join(RUNTIME_VARS.FILES, "file", "prod"),
|
||||
],
|
||||
},
|
||||
"pillar_roots": {
|
||||
"base": [
|
||||
RUNTIME_VARS.TMP_PILLAR_TREE,
|
||||
os.path.join(RUNTIME_VARS.FILES, "pillar", "base"),
|
||||
],
|
||||
"prod": [RUNTIME_VARS.TMP_PRODENV_PILLAR_TREE],
|
||||
},
|
||||
}
|
||||
)
|
||||
return salt_factories.configure_master(
|
||||
request,
|
||||
"syndic_master",
|
||||
order_masters=True,
|
||||
config_defaults=config_defaults,
|
||||
config_overrides=config_overrides,
|
||||
)
|
||||
|
||||
|
||||
@pytest.fixture(scope="session")
|
||||
def salt_syndic_config(request, salt_factories, salt_syndic_master_config):
|
||||
return salt_factories.configure_syndic(
|
||||
request, "syndic", master_of_masters_id="syndic_master"
|
||||
)
|
||||
|
||||
|
||||
@pytest.fixture(scope="session")
|
||||
def salt_master_config(request, salt_factories, salt_syndic_master_config):
|
||||
root_dir = salt_factories._get_root_dir_for_daemon("master")
|
||||
conf_dir = root_dir.join("conf").ensure(dir=True)
|
||||
|
||||
with salt.utils.files.fopen(os.path.join(RUNTIME_VARS.CONF_DIR, "master")) as rfh:
|
||||
config_defaults = yaml.deserialize(rfh.read())
|
||||
|
||||
tests_known_hosts_file = root_dir.join("salt_ssh_known_hosts").strpath
|
||||
with salt.utils.files.fopen(tests_known_hosts_file, "w") as known_hosts:
|
||||
known_hosts.write("")
|
||||
|
||||
config_defaults["root_dir"] = root_dir.strpath
|
||||
config_defaults["known_hosts_file"] = tests_known_hosts_file
|
||||
config_defaults["syndic_master"] = "localhost"
|
||||
config_defaults["transport"] = request.config.getoption("--transport")
|
||||
config_defaults["reactor"] = [
|
||||
{"salt/test/reactor": [os.path.join(RUNTIME_VARS.FILES, "reactor-test.sls")]}
|
||||
]
|
||||
|
||||
config_overrides = {}
|
||||
ext_pillar = []
|
||||
if salt.utils.platform.is_windows():
|
||||
ext_pillar.append(
|
||||
{"cmd_yaml": "type {}".format(os.path.join(RUNTIME_VARS.FILES, "ext.yaml"))}
|
||||
)
|
||||
else:
|
||||
ext_pillar.append(
|
||||
{"cmd_yaml": "cat {}".format(os.path.join(RUNTIME_VARS.FILES, "ext.yaml"))}
|
||||
)
|
||||
ext_pillar.append(
|
||||
{
|
||||
"file_tree": {
|
||||
"root_dir": os.path.join(RUNTIME_VARS.PILLAR_DIR, "base", "file_tree"),
|
||||
"follow_dir_links": False,
|
||||
"keep_newline": True,
|
||||
}
|
||||
}
|
||||
)
|
||||
config_overrides["pillar_opts"] = True
|
||||
|
||||
# We need to copy the extension modules into the new master root_dir or
|
||||
# it will be prefixed by it
|
||||
extension_modules_path = root_dir.join("extension_modules").strpath
|
||||
if not os.path.exists(extension_modules_path):
|
||||
shutil.copytree(
|
||||
os.path.join(RUNTIME_VARS.FILES, "extension_modules"),
|
||||
extension_modules_path,
|
||||
)
|
||||
|
||||
# Copy the autosign_file to the new master root_dir
|
||||
autosign_file_path = root_dir.join("autosign_file").strpath
|
||||
shutil.copyfile(
|
||||
os.path.join(RUNTIME_VARS.FILES, "autosign_file"), autosign_file_path
|
||||
)
|
||||
# all read, only owner write
|
||||
autosign_file_permissions = (
|
||||
stat.S_IRUSR | stat.S_IRGRP | stat.S_IROTH | stat.S_IWUSR
|
||||
)
|
||||
os.chmod(autosign_file_path, autosign_file_permissions)
|
||||
|
||||
config_overrides.update(
|
||||
{
|
||||
"ext_pillar": ext_pillar,
|
||||
"extension_modules": extension_modules_path,
|
||||
"file_roots": {
|
||||
"base": [
|
||||
RUNTIME_VARS.TMP_STATE_TREE,
|
||||
os.path.join(RUNTIME_VARS.FILES, "file", "base"),
|
||||
],
|
||||
# Alternate root to test __env__ choices
|
||||
"prod": [
|
||||
RUNTIME_VARS.TMP_PRODENV_STATE_TREE,
|
||||
os.path.join(RUNTIME_VARS.FILES, "file", "prod"),
|
||||
],
|
||||
},
|
||||
"pillar_roots": {
|
||||
"base": [
|
||||
RUNTIME_VARS.TMP_PILLAR_TREE,
|
||||
os.path.join(RUNTIME_VARS.FILES, "pillar", "base"),
|
||||
],
|
||||
"prod": [RUNTIME_VARS.TMP_PRODENV_PILLAR_TREE],
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
# Let's copy over the test cloud config files and directories into the running master config directory
|
||||
for entry in os.listdir(RUNTIME_VARS.CONF_DIR):
|
||||
if not entry.startswith("cloud"):
|
||||
continue
|
||||
source = os.path.join(RUNTIME_VARS.CONF_DIR, entry)
|
||||
dest = conf_dir.join(entry).strpath
|
||||
if os.path.isdir(source):
|
||||
shutil.copytree(source, dest)
|
||||
else:
|
||||
shutil.copyfile(source, dest)
|
||||
|
||||
return salt_factories.configure_master(
|
||||
request,
|
||||
"master",
|
||||
master_of_masters_id="syndic_master",
|
||||
config_defaults=config_defaults,
|
||||
config_overrides=config_overrides,
|
||||
)
|
||||
|
||||
|
||||
@pytest.fixture(scope="session")
|
||||
def salt_minion_config(request, salt_factories, salt_master_config):
|
||||
with salt.utils.files.fopen(os.path.join(RUNTIME_VARS.CONF_DIR, "minion")) as rfh:
|
||||
config_defaults = yaml.deserialize(rfh.read())
|
||||
config_defaults["hosts.file"] = os.path.join(RUNTIME_VARS.TMP, "hosts")
|
||||
config_defaults["aliases.file"] = os.path.join(RUNTIME_VARS.TMP, "aliases")
|
||||
config_defaults["transport"] = request.config.getoption("--transport")
|
||||
|
||||
config_overrides = {
|
||||
"file_roots": {
|
||||
"base": [
|
||||
RUNTIME_VARS.TMP_STATE_TREE,
|
||||
os.path.join(RUNTIME_VARS.FILES, "file", "base"),
|
||||
],
|
||||
# Alternate root to test __env__ choices
|
||||
"prod": [
|
||||
RUNTIME_VARS.TMP_PRODENV_STATE_TREE,
|
||||
os.path.join(RUNTIME_VARS.FILES, "file", "prod"),
|
||||
],
|
||||
},
|
||||
"pillar_roots": {
|
||||
"base": [
|
||||
RUNTIME_VARS.TMP_PILLAR_TREE,
|
||||
os.path.join(RUNTIME_VARS.FILES, "pillar", "base"),
|
||||
],
|
||||
"prod": [RUNTIME_VARS.TMP_PRODENV_PILLAR_TREE],
|
||||
},
|
||||
}
|
||||
virtualenv_binary = get_virtualenv_binary_path()
|
||||
if virtualenv_binary:
|
||||
config_overrides["venv_bin"] = virtualenv_binary
|
||||
return salt_factories.configure_minion(
|
||||
request,
|
||||
"minion",
|
||||
master_id="master",
|
||||
config_defaults=config_defaults,
|
||||
config_overrides=config_overrides,
|
||||
)
|
||||
|
||||
|
||||
@pytest.fixture(scope="session")
|
||||
def salt_sub_minion_config(request, salt_factories, salt_master_config):
|
||||
with salt.utils.files.fopen(
|
||||
os.path.join(RUNTIME_VARS.CONF_DIR, "sub_minion")
|
||||
) as rfh:
|
||||
config_defaults = yaml.deserialize(rfh.read())
|
||||
config_defaults["hosts.file"] = os.path.join(RUNTIME_VARS.TMP, "hosts")
|
||||
config_defaults["aliases.file"] = os.path.join(RUNTIME_VARS.TMP, "aliases")
|
||||
config_defaults["transport"] = request.config.getoption("--transport")
|
||||
|
||||
config_overrides = {
|
||||
"file_roots": {
|
||||
"base": [
|
||||
RUNTIME_VARS.TMP_STATE_TREE,
|
||||
os.path.join(RUNTIME_VARS.FILES, "file", "base"),
|
||||
],
|
||||
# Alternate root to test __env__ choices
|
||||
"prod": [
|
||||
RUNTIME_VARS.TMP_PRODENV_STATE_TREE,
|
||||
os.path.join(RUNTIME_VARS.FILES, "file", "prod"),
|
||||
],
|
||||
},
|
||||
"pillar_roots": {
|
||||
"base": [
|
||||
RUNTIME_VARS.TMP_PILLAR_TREE,
|
||||
os.path.join(RUNTIME_VARS.FILES, "pillar", "base"),
|
||||
],
|
||||
"prod": [RUNTIME_VARS.TMP_PRODENV_PILLAR_TREE],
|
||||
},
|
||||
}
|
||||
virtualenv_binary = get_virtualenv_binary_path()
|
||||
if virtualenv_binary:
|
||||
config_overrides["venv_bin"] = virtualenv_binary
|
||||
return salt_factories.configure_minion(
|
||||
request,
|
||||
"sub_minion",
|
||||
master_id="master",
|
||||
config_defaults=config_defaults,
|
||||
config_overrides=config_overrides,
|
||||
)
|
||||
|
||||
|
||||
@pytest.hookspec(firstresult=True)
|
||||
def pytest_saltfactories_syndic_configuration_defaults(
|
||||
request, factories_manager, root_dir, syndic_id, syndic_master_port
|
||||
):
|
||||
"""
|
||||
Hook which should return a dictionary tailored for the provided syndic_id with 3 keys:
|
||||
|
||||
* `master`: The default config for the master running along with the syndic
|
||||
* `minion`: The default config for the master running along with the syndic
|
||||
* `syndic`: The default config for the master running along with the syndic
|
||||
|
||||
Stops at the first non None result
|
||||
"""
|
||||
factory_opts = {"master": None, "minion": None, "syndic": None}
|
||||
if syndic_id == "syndic":
|
||||
with salt.utils.files.fopen(
|
||||
os.path.join(RUNTIME_VARS.CONF_DIR, "syndic")
|
||||
) as rfh:
|
||||
opts = yaml.deserialize(rfh.read())
|
||||
|
||||
opts["hosts.file"] = os.path.join(RUNTIME_VARS.TMP, "hosts")
|
||||
opts["aliases.file"] = os.path.join(RUNTIME_VARS.TMP, "aliases")
|
||||
opts["transport"] = request.config.getoption("--transport")
|
||||
factory_opts["syndic"] = opts
|
||||
return factory_opts
|
||||
|
||||
|
||||
@pytest.hookspec(firstresult=True)
|
||||
def pytest_saltfactories_syndic_configuration_overrides(
|
||||
request, factories_manager, syndic_id, config_defaults
|
||||
):
|
||||
"""
|
||||
Hook which should return a dictionary tailored for the provided syndic_id.
|
||||
This dictionary will override the default_options dictionary.
|
||||
|
||||
The returned dictionary should contain 3 keys:
|
||||
|
||||
* `master`: The config overrides for the master running along with the syndic
|
||||
* `minion`: The config overrides for the master running along with the syndic
|
||||
* `syndic`: The config overridess for the master running along with the syndic
|
||||
|
||||
The `default_options` parameter be None or have 3 keys, `master`, `minion`, `syndic`,
|
||||
while will contain the default options for each of the daemons.
|
||||
|
||||
Stops at the first non None result
|
||||
"""
|
||||
|
||||
|
||||
@pytest.fixture(scope="session", autouse=True)
|
||||
def bridge_pytest_and_runtests(
|
||||
reap_stray_processes,
|
||||
base_env_state_tree_root_dir,
|
||||
prod_env_state_tree_root_dir,
|
||||
base_env_pillar_tree_root_dir,
|
||||
prod_env_pillar_tree_root_dir,
|
||||
salt_factories,
|
||||
salt_syndic_master_config,
|
||||
salt_syndic_config,
|
||||
salt_master_config,
|
||||
salt_minion_config,
|
||||
salt_sub_minion_config,
|
||||
):
|
||||
# Make sure unittest2 uses the pytest generated configuration
|
||||
RUNTIME_VARS.RUNTIME_CONFIGS["master"] = freeze(salt_master_config)
|
||||
RUNTIME_VARS.RUNTIME_CONFIGS["minion"] = freeze(salt_minion_config)
|
||||
RUNTIME_VARS.RUNTIME_CONFIGS["sub_minion"] = freeze(salt_sub_minion_config)
|
||||
RUNTIME_VARS.RUNTIME_CONFIGS["syndic_master"] = freeze(salt_syndic_master_config)
|
||||
RUNTIME_VARS.RUNTIME_CONFIGS["syndic"] = freeze(salt_syndic_config)
|
||||
RUNTIME_VARS.RUNTIME_CONFIGS["client_config"] = freeze(
|
||||
salt.config.client_config(salt_master_config["conf_file"])
|
||||
)
|
||||
|
||||
# Make sure unittest2 classes know their paths
|
||||
RUNTIME_VARS.TMP_ROOT_DIR = salt_factories.root_dir.realpath().strpath
|
||||
RUNTIME_VARS.TMP_CONF_DIR = os.path.dirname(salt_master_config["conf_file"])
|
||||
RUNTIME_VARS.TMP_MINION_CONF_DIR = os.path.dirname(salt_minion_config["conf_file"])
|
||||
RUNTIME_VARS.TMP_SUB_MINION_CONF_DIR = os.path.dirname(
|
||||
salt_sub_minion_config["conf_file"]
|
||||
)
|
||||
RUNTIME_VARS.TMP_SYNDIC_MASTER_CONF_DIR = os.path.dirname(
|
||||
salt_syndic_master_config["conf_file"]
|
||||
)
|
||||
RUNTIME_VARS.TMP_SYNDIC_MINION_CONF_DIR = os.path.dirname(
|
||||
salt_syndic_config["conf_file"]
|
||||
)
|
||||
|
||||
|
||||
# Only allow star importing the functions defined in this module
|
||||
__all__ = [
|
||||
name
|
||||
for (name, func) in locals().items()
|
||||
if getattr(func, "__module__", None) == __name__
|
||||
]
|
|
@ -1,4 +1,3 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
tests.support.pytest.helpers
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
@ -251,6 +250,15 @@ def salt_loader_module_functions(module):
|
|||
return funcs
|
||||
|
||||
|
||||
@pytest.helpers.register
|
||||
def remove_stale_minion_key(master, minion_id):
|
||||
key_path = os.path.join(master.config["pki_dir"], "minions", minion_id)
|
||||
if os.path.exists(key_path):
|
||||
os.unlink(key_path)
|
||||
else:
|
||||
log.debug("The minion(id=%r) key was not found at %s", minion_id, key_path)
|
||||
|
||||
|
||||
# Only allow star importing the functions defined in this module
|
||||
__all__ = [
|
||||
name
|
||||
|
|
|
@ -42,8 +42,8 @@
|
|||
minion_config_path = os.path.join(RUNTIME_VARS.TMP_CONF_DIR, 'minion')
|
||||
|
||||
.. _`pytest`: http://pytest.org
|
||||
.. _`nose`: https://nose.readthedocs.org
|
||||
"""
|
||||
"""
|
||||
|
||||
import logging
|
||||
import os
|
||||
import shutil
|
||||
|
@ -189,6 +189,7 @@ RUNTIME_VARS = RuntimeVars(
|
|||
TMP_MM_MINION_CONF_DIR=paths.TMP_MM_MINION_CONF_DIR,
|
||||
TMP_MM_SUB_CONF_DIR=paths.TMP_MM_SUB_CONF_DIR,
|
||||
TMP_MM_SUB_MINION_CONF_DIR=paths.TMP_MM_SUB_CONF_DIR,
|
||||
TMP_SSH_CONF_DIR=paths.TMP_SSH_CONF_DIR,
|
||||
TMP_SCRIPT_DIR=paths.TMP_SCRIPT_DIR,
|
||||
TMP_STATE_TREE=paths.TMP_STATE_TREE,
|
||||
TMP_BASEENV_STATE_TREE=paths.TMP_STATE_TREE,
|
||||
|
|
File diff suppressed because it is too large
Load diff
85
tests/support/virt.py
Normal file
85
tests/support/virt.py
Normal file
|
@ -0,0 +1,85 @@
|
|||
import time
|
||||
import uuid
|
||||
|
||||
import attr
|
||||
from saltfactories.factories.daemons.container import SaltMinionContainerFactory
|
||||
from saltfactories.utils import ports
|
||||
from tests.support.runtests import RUNTIME_VARS
|
||||
|
||||
|
||||
@attr.s(kw_only=True, slots=True)
|
||||
class SaltVirtMinionContainerFactory(SaltMinionContainerFactory):
|
||||
|
||||
host_uuid = attr.ib(default=attr.Factory(uuid.uuid4))
|
||||
ssh_port = attr.ib(
|
||||
default=attr.Factory(ports.get_unused_localhost_port), repr=False
|
||||
)
|
||||
sshd_port = attr.ib(default=attr.Factory(ports.get_unused_localhost_port))
|
||||
libvirt_tcp_port = attr.ib(
|
||||
default=attr.Factory(ports.get_unused_localhost_port), repr=False
|
||||
)
|
||||
libvirt_tls_port = attr.ib(
|
||||
default=attr.Factory(ports.get_unused_localhost_port), repr=False
|
||||
)
|
||||
|
||||
uri = attr.ib(init=False)
|
||||
ssh_uri = attr.ib(init=False)
|
||||
tcp_uri = attr.ib(init=False)
|
||||
tls_uri = attr.ib(init=False)
|
||||
|
||||
def __attrs_post_init__(self):
|
||||
self.uri = "localhost:{}".format(self.sshd_port)
|
||||
self.ssh_uri = "qemu+ssh://{}/system".format(self.uri)
|
||||
self.tcp_uri = "qemu+tcp://localhost:{}/system".format(self.libvirt_tcp_port)
|
||||
self.tls_uri = "qemu+tls://localhost:{}/system".format(self.libvirt_tls_port)
|
||||
|
||||
if self.check_ports is None:
|
||||
self.check_ports = []
|
||||
self.check_ports.extend(
|
||||
[self.sshd_port, self.libvirt_tcp_port, self.libvirt_tls_port]
|
||||
)
|
||||
if "environment" not in self.container_run_kwargs:
|
||||
self.container_run_kwargs["environment"] = {}
|
||||
self.container_run_kwargs["environment"].update(
|
||||
{
|
||||
"SSH_PORT": str(self.ssh_port),
|
||||
"SSHD_PORT": str(self.sshd_port),
|
||||
"LIBVIRT_TCP_PORT": str(self.libvirt_tcp_port),
|
||||
"LIBVIRT_TLS_PORT": str(self.libvirt_tls_port),
|
||||
"NO_START_MINION": "1",
|
||||
"HOST_UUID": self.host_uuid,
|
||||
}
|
||||
)
|
||||
if "ports" not in self.container_run_kwargs:
|
||||
self.container_run_kwargs["ports"] = {}
|
||||
self.container_run_kwargs["ports"].update(
|
||||
{
|
||||
"{}/tcp".format(self.ssh_port): self.ssh_port,
|
||||
"{}/tcp".format(self.sshd_port): self.sshd_port,
|
||||
"{}/tcp".format(self.libvirt_tcp_port): self.libvirt_tcp_port,
|
||||
"{}/tcp".format(self.libvirt_tls_port): self.libvirt_tls_port,
|
||||
}
|
||||
)
|
||||
if "volumes" not in self.container_run_kwargs:
|
||||
self.container_run_kwargs["volumes"] = {}
|
||||
self.container_run_kwargs["volumes"].update(
|
||||
{
|
||||
RUNTIME_VARS.CODE_DIR: {"bind": "/salt", "mode": "z"},
|
||||
RUNTIME_VARS.CODE_DIR: {"bind": RUNTIME_VARS.CODE_DIR, "mode": "z"},
|
||||
}
|
||||
)
|
||||
self.container_run_kwargs["working_dir"] = RUNTIME_VARS.CODE_DIR
|
||||
self.container_run_kwargs["network_mode"] = "host"
|
||||
self.container_run_kwargs["cap_add"] = ["ALL"]
|
||||
self.container_run_kwargs["privileged"] = True
|
||||
super().__attrs_post_init__()
|
||||
self.python_executable = "python3"
|
||||
|
||||
def _container_start_checks(self):
|
||||
# Once we're able to ls the salt-minion script it means the container
|
||||
# has salt installed
|
||||
ret = self.run("ls", "-lah", self.get_script_path())
|
||||
if ret.exitcode == 0:
|
||||
return True
|
||||
time.sleep(1)
|
||||
return False
|
|
@ -9,17 +9,13 @@ import copy
|
|||
import logging
|
||||
import textwrap
|
||||
|
||||
import pytest
|
||||
import salt.modules.aptpkg as aptpkg
|
||||
from salt.exceptions import CommandExecutionError, SaltInvocationError
|
||||
from tests.support.mixins import LoaderModuleMockMixin
|
||||
from tests.support.mock import MagicMock, Mock, call, patch
|
||||
from tests.support.unit import TestCase, skipIf
|
||||
|
||||
try:
|
||||
import pytest
|
||||
except ImportError:
|
||||
pytest = None
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
|
@ -852,7 +848,7 @@ class AptUtilsTestCase(TestCase, LoaderModuleMockMixin):
|
|||
aptpkg.__salt__,
|
||||
{"cmd.run_all": cmd_mock, "config.get": MagicMock(return_value=False)},
|
||||
):
|
||||
with patch("time.sleep", MagicMock()) as sleep_mock:
|
||||
with patch("salt.modules.aptpkg.time.sleep", MagicMock()) as sleep_mock:
|
||||
aptpkg._call_apt(
|
||||
["dpkg", "-l", "python"],
|
||||
python_shell=True,
|
||||
|
|
|
@ -1,10 +1,8 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
tests.unit.utils.scheduler.base
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
"""
|
||||
|
||||
from __future__ import absolute_import
|
||||
|
||||
import copy
|
||||
import logging
|
||||
|
@ -14,7 +12,7 @@ import salt.utils.platform
|
|||
import salt.utils.schedule
|
||||
from salt.modules.test import ping
|
||||
from salt.utils.process import SubprocessList
|
||||
from saltfactories.utils.processes.helpers import terminate_process
|
||||
from saltfactories.utils.processes import terminate_process
|
||||
from tests.support.mixins import SaltReturnAssertsMixin
|
||||
from tests.support.mock import MagicMock, patch
|
||||
from tests.support.runtests import RUNTIME_VARS
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
:codeauthor: Pedro Algarvio (pedro@algarvio.me)
|
||||
|
||||
|
@ -6,7 +5,6 @@
|
|||
tests.unit.utils.event_test
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
"""
|
||||
from __future__ import absolute_import, print_function, unicode_literals
|
||||
|
||||
import hashlib
|
||||
import os
|
||||
|
@ -21,7 +19,7 @@ import zmq
|
|||
import zmq.eventloop.ioloop
|
||||
from salt.ext.six.moves import range
|
||||
from salt.ext.tornado.testing import AsyncTestCase
|
||||
from saltfactories.utils.processes.helpers import terminate_process
|
||||
from saltfactories.utils.processes import terminate_process
|
||||
from tests.support.events import eventpublisher_process, eventsender_process
|
||||
from tests.support.helpers import slowTest
|
||||
from tests.support.runtests import RUNTIME_VARS
|
||||
|
@ -49,7 +47,7 @@ class TestSaltEvent(TestCase):
|
|||
def assertGotEvent(self, evt, data, msg=None):
|
||||
self.assertIsNotNone(evt, msg)
|
||||
for key in data:
|
||||
self.assertIn(key, evt, "{0}: Key {1} missing".format(msg, key))
|
||||
self.assertIn(key, evt, "{}: Key {} missing".format(msg, key))
|
||||
assertMsg = "{0}: Key {1} value mismatch, {2} != {3}"
|
||||
assertMsg = assertMsg.format(msg, key, data[key], evt[key])
|
||||
self.assertEqual(data[key], evt[key], assertMsg)
|
||||
|
@ -57,11 +55,11 @@ class TestSaltEvent(TestCase):
|
|||
def test_master_event(self):
|
||||
me = salt.utils.event.MasterEvent(self.sock_dir, listen=False)
|
||||
self.assertEqual(
|
||||
me.puburi, "{0}".format(os.path.join(self.sock_dir, "master_event_pub.ipc"))
|
||||
me.puburi, "{}".format(os.path.join(self.sock_dir, "master_event_pub.ipc"))
|
||||
)
|
||||
self.assertEqual(
|
||||
me.pulluri,
|
||||
"{0}".format(os.path.join(self.sock_dir, "master_event_pull.ipc")),
|
||||
"{}".format(os.path.join(self.sock_dir, "master_event_pull.ipc")),
|
||||
)
|
||||
|
||||
def test_minion_event(self):
|
||||
|
@ -72,14 +70,14 @@ class TestSaltEvent(TestCase):
|
|||
me = salt.utils.event.MinionEvent(opts, listen=False)
|
||||
self.assertEqual(
|
||||
me.puburi,
|
||||
"{0}".format(
|
||||
os.path.join(self.sock_dir, "minion_event_{0}_pub.ipc".format(id_hash))
|
||||
"{}".format(
|
||||
os.path.join(self.sock_dir, "minion_event_{}_pub.ipc".format(id_hash))
|
||||
),
|
||||
)
|
||||
self.assertEqual(
|
||||
me.pulluri,
|
||||
"{0}".format(
|
||||
os.path.join(self.sock_dir, "minion_event_{0}_pull.ipc".format(id_hash))
|
||||
"{}".format(
|
||||
os.path.join(self.sock_dir, "minion_event_{}_pull.ipc".format(id_hash))
|
||||
),
|
||||
)
|
||||
|
||||
|
@ -94,14 +92,14 @@ class TestSaltEvent(TestCase):
|
|||
id_hash = hashlib.sha256(salt.utils.stringutils.to_bytes("")).hexdigest()[:10]
|
||||
self.assertEqual(
|
||||
me.puburi,
|
||||
"{0}".format(
|
||||
os.path.join(self.sock_dir, "minion_event_{0}_pub.ipc".format(id_hash))
|
||||
"{}".format(
|
||||
os.path.join(self.sock_dir, "minion_event_{}_pub.ipc".format(id_hash))
|
||||
),
|
||||
)
|
||||
self.assertEqual(
|
||||
me.pulluri,
|
||||
"{0}".format(
|
||||
os.path.join(self.sock_dir, "minion_event_{0}_pull.ipc".format(id_hash))
|
||||
"{}".format(
|
||||
os.path.join(self.sock_dir, "minion_event_{}_pull.ipc".format(id_hash))
|
||||
),
|
||||
)
|
||||
|
||||
|
@ -270,11 +268,9 @@ class TestSaltEvent(TestCase):
|
|||
with eventpublisher_process(self.sock_dir):
|
||||
me = salt.utils.event.MasterEvent(self.sock_dir, listen=True)
|
||||
for i in range(500):
|
||||
me.fire_event({"data": "{0}".format(i)}, "testevents")
|
||||
me.fire_event({"data": "{}".format(i)}, "testevents")
|
||||
evt = me.get_event(tag="testevents")
|
||||
self.assertGotEvent(
|
||||
evt, {"data": "{0}".format(i)}, "Event {0}".format(i)
|
||||
)
|
||||
self.assertGotEvent(evt, {"data": "{}".format(i)}, "Event {}".format(i))
|
||||
|
||||
@slowTest
|
||||
def test_event_many_backlog(self):
|
||||
|
@ -283,12 +279,10 @@ class TestSaltEvent(TestCase):
|
|||
me = salt.utils.event.MasterEvent(self.sock_dir, listen=True)
|
||||
# Must not exceed zmq HWM
|
||||
for i in range(500):
|
||||
me.fire_event({"data": "{0}".format(i)}, "testevents")
|
||||
me.fire_event({"data": "{}".format(i)}, "testevents")
|
||||
for i in range(500):
|
||||
evt = me.get_event(tag="testevents")
|
||||
self.assertGotEvent(
|
||||
evt, {"data": "{0}".format(i)}, "Event {0}".format(i)
|
||||
)
|
||||
self.assertGotEvent(evt, {"data": "{}".format(i)}, "Event {}".format(i))
|
||||
|
||||
# Test the fire_master function. As it wraps the underlying fire_event,
|
||||
# we don't need to perform extensive testing.
|
||||
|
@ -312,7 +306,7 @@ class TestAsyncEventPublisher(AsyncTestCase):
|
|||
return salt.ext.tornado.ioloop.IOLoop()
|
||||
|
||||
def setUp(self):
|
||||
super(TestAsyncEventPublisher, self).setUp()
|
||||
super().setUp()
|
||||
self.sock_dir = os.path.join(RUNTIME_VARS.TMP, "test-socks")
|
||||
if not os.path.exists(self.sock_dir):
|
||||
os.makedirs(self.sock_dir)
|
||||
|
|
Loading…
Add table
Reference in a new issue