123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524 |
- # -*- coding: utf-8 -*-
- """
- 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 sys
- import pytest
- import salt.utils.files
- from salt.serializers import yaml
- from salt.utils.immutabletypes import freeze
- from tests.support.runtests import RUNTIME_VARS
- def _get_virtualenv_binary_path():
- try:
- return _get_virtualenv_binary_path.__virtualenv_binary__
- except AttributeError:
- # Under windows we can't seem to properly create a virtualenv off of another
- # virtualenv, we can on linux but we will still point to the virtualenv binary
- # outside the virtualenv running the test suite, if that's the case.
- try:
- real_prefix = sys.real_prefix
- # The above attribute exists, this is a virtualenv
- if salt.utils.platform.is_windows():
- virtualenv_binary = os.path.join(
- real_prefix, "Scripts", "virtualenv.exe"
- )
- else:
- # We need to remove the virtualenv from PATH or we'll get the virtualenv binary
- # from within the virtualenv, we don't want that
- path = os.environ.get("PATH")
- if path is not None:
- path_items = path.split(os.pathsep)
- for item in path_items[:]:
- if item.startswith(sys.base_prefix):
- path_items.remove(item)
- os.environ["PATH"] = os.pathsep.join(path_items)
- virtualenv_binary = salt.utils.path.which("virtualenv")
- if path is not None:
- # Restore previous environ PATH
- os.environ["PATH"] = path
- if not virtualenv_binary.startswith(real_prefix):
- virtualenv_binary = None
- if virtualenv_binary and not os.path.exists(virtualenv_binary):
- # It doesn't exist?!
- virtualenv_binary = None
- except AttributeError:
- # We're not running inside a virtualenv
- virtualenv_binary = None
- _get_virtualenv_binary_path.__virtualenv_binary__ = virtualenv_binary
- return virtualenv_binary
- @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 {0}".format(
- os.path.join(RUNTIME_VARS.FILES, "ext.yaml")
- )
- }
- )
- else:
- ext_pillar.append(
- {"cmd_yaml": "cat {0}".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 {0}".format(
- os.path.join(RUNTIME_VARS.FILES, "ext.yaml")
- )
- }
- )
- else:
- ext_pillar.append(
- {"cmd_yaml": "cat {0}".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__
- ]
|