From e1574590163f3ada8cf632a98aeb9f5f76785fbe Mon Sep 17 00:00:00 2001 From: Pedro Algarvio Date: Thu, 7 May 2020 19:10:55 +0100 Subject: [PATCH] Switch to pytest-salt-factories --- .pylintrc | 3 +- noxfile.py | 3 + requirements/pytest.txt | 3 +- requirements/static/py3.5/darwin.txt | 3 +- requirements/static/py3.5/linux.txt | 3 +- requirements/static/py3.5/windows.txt | 3 +- requirements/static/py3.6/darwin.txt | 3 +- requirements/static/py3.6/linux.txt | 3 +- requirements/static/py3.6/windows.txt | 3 +- requirements/static/py3.7/darwin.txt | 3 +- requirements/static/py3.7/linux.txt | 3 +- requirements/static/py3.7/windows.txt | 3 +- requirements/static/py3.8/darwin.txt | 3 +- requirements/static/py3.8/linux.txt | 3 +- requirements/static/py3.9/darwin.txt | 3 +- requirements/static/py3.9/linux.txt | 3 +- tests/conftest.py | 853 +++++++++++--------------- tests/integration/conftest.py | 70 ++- tests/multimaster/conftest.py | 829 ++----------------------- tests/support/cli_scripts.py | 5 +- tests/support/gitfs.py | 12 +- tests/support/helpers.py | 2 +- tests/support/mixins.py | 8 +- tests/support/processes.py | 37 +- tests/support/runtests.py | 2 - 25 files changed, 517 insertions(+), 1349 deletions(-) diff --git a/.pylintrc b/.pylintrc index 2ee9334a8ba..551463b2ded 100644 --- a/.pylintrc +++ b/.pylintrc @@ -682,8 +682,9 @@ allowed-3rd-party-modules=msgpack, libcloud, zmq, pytest, + setuptools, pytestsalt, - setuptools + saltfactories [EXCEPTIONS] diff --git a/noxfile.py b/noxfile.py index 189c4c5bdae..7c473a17151 100644 --- a/noxfile.py +++ b/noxfile.py @@ -680,6 +680,9 @@ def pytest_parametrized(session, coverage, transport, crypto): # Install requirements _install_requirements(session, transport) + session.run( + "pip", "uninstall", "-y", "pytest-salt", silent=True, + ) if crypto: session.run( "pip", diff --git a/requirements/pytest.txt b/requirements/pytest.txt index 1b2f2a5f8c4..101b61f4e08 100644 --- a/requirements/pytest.txt +++ b/requirements/pytest.txt @@ -1,7 +1,8 @@ mock >= 3.0.0 # PyTest pytest >=4.6.9,<4.7 # PyTest 4.6.x are the last Py2 and Py3 releases -pytest-salt >= 2020.1.27 +pytest-salt +pytest-salt-factories >= 0.10.0 pytest-tempdir >= 2019.10.12 pytest-helpers-namespace >= 2019.1.8 pytest-salt-runtests-bridge >= 2019.12.5 diff --git a/requirements/static/py3.5/darwin.txt b/requirements/static/py3.5/darwin.txt index 1fd6b10e37d..e75b029b336 100644 --- a/requirements/static/py3.5/darwin.txt +++ b/requirements/static/py3.5/darwin.txt @@ -88,6 +88,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.10.4 pytest-salt-runtests-bridge==2019.12.5 pytest-salt==2020.1.27 pytest-tempdir==2019.10.12 @@ -108,7 +109,7 @@ s3transfer==0.2.0 # via boto3 salttesting==2017.6.1 scp==0.13.2 # via junos-eznc setproctitle==1.1.10 -six==1.12.0 # via bcrypt, cheroot, cherrypy, cryptography, docker, docker-pycreds, google-auth, junos-eznc, kubernetes, mock, more-itertools, moto, ncclient, packaging, pathlib2, pynacl, pyopenssl, pytest, python-dateutil, python-jose, pyvmomi, responses, salttesting, tempora, textfsm, transitions, vcert, virtualenv, websocket-client +six==1.12.0 # via bcrypt, cheroot, cherrypy, cryptography, docker, docker-pycreds, google-auth, junos-eznc, kubernetes, mock, more-itertools, moto, ncclient, packaging, pathlib2, pynacl, pyopenssl, pytest, pytest-salt-factories, python-dateutil, python-jose, pyvmomi, responses, salttesting, tempora, textfsm, transitions, vcert, virtualenv, websocket-client smmap2==2.0.5 # via gitdb2 strict-rfc3339==0.7 tempora==1.14.1 # via portend diff --git a/requirements/static/py3.5/linux.txt b/requirements/static/py3.5/linux.txt index 455df467a42..45482137feb 100644 --- a/requirements/static/py3.5/linux.txt +++ b/requirements/static/py3.5/linux.txt @@ -84,6 +84,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.10.4 pytest-salt-runtests-bridge==2019.12.5 pytest-salt==2020.1.27 pytest-tempdir==2019.10.12 @@ -105,7 +106,7 @@ salttesting==2017.6.1 scp==0.13.2 # via junos-eznc setproctitle==1.1.10 setuptools-scm==3.2.0 -six==1.12.0 # via bcrypt, cheroot, cherrypy, cryptography, docker, docker-pycreds, google-auth, junos-eznc, kazoo, kubernetes, mock, more-itertools, moto, ncclient, packaging, pathlib2, pygit2, pynacl, pyopenssl, pytest, python-dateutil, python-jose, pyvmomi, responses, salttesting, tempora, textfsm, transitions, vcert, websocket-client +six==1.12.0 # via bcrypt, cheroot, cherrypy, cryptography, docker, docker-pycreds, google-auth, junos-eznc, kazoo, kubernetes, mock, more-itertools, moto, ncclient, packaging, pathlib2, pygit2, pynacl, pyopenssl, pytest, pytest-salt-factories, python-dateutil, python-jose, pyvmomi, responses, salttesting, tempora, textfsm, transitions, vcert, websocket-client smmap2==2.0.5 # via gitdb2 strict-rfc3339==0.7 tempora==1.14.1 # via portend diff --git a/requirements/static/py3.5/windows.txt b/requirements/static/py3.5/windows.txt index b6ce1f02195..a108b74a9e2 100644 --- a/requirements/static/py3.5/windows.txt +++ b/requirements/static/py3.5/windows.txt @@ -78,6 +78,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.10.4 pytest-salt-runtests-bridge==2019.12.5 pytest-salt==2020.1.27 pytest-tempdir==2019.10.12 @@ -100,7 +101,7 @@ s3transfer==0.2.0 # via boto3 salttesting==2017.6.1 sed==0.3.1 setproctitle==1.1.10 -six==1.12.0 # via cheroot, cherrypy, cryptography, docker, docker-pycreds, google-auth, kubernetes, mock, more-itertools, moto, packaging, pathlib2, pygit2, pyopenssl, pytest, python-dateutil, python-jose, pyvmomi, responses, salttesting, tempora, websocket-client +six==1.12.0 # via cheroot, cherrypy, cryptography, docker, docker-pycreds, google-auth, kubernetes, mock, more-itertools, moto, packaging, pathlib2, pygit2, pyopenssl, pytest, pytest-salt-factories, python-dateutil, python-jose, pyvmomi, responses, salttesting, tempora, websocket-client smmap2==2.0.5 strict-rfc3339==0.7 tempora==1.14.1 # via portend diff --git a/requirements/static/py3.6/darwin.txt b/requirements/static/py3.6/darwin.txt index 3209d0cddea..8a407372ec0 100644 --- a/requirements/static/py3.6/darwin.txt +++ b/requirements/static/py3.6/darwin.txt @@ -87,6 +87,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.10.4 pytest-salt-runtests-bridge==2019.12.5 pytest-salt==2020.1.27 pytest-tempdir==2019.10.12 @@ -107,7 +108,7 @@ s3transfer==0.2.0 # via boto3 salttesting==2017.6.1 scp==0.13.2 # via junos-eznc setproctitle==1.1.10 -six==1.12.0 # via bcrypt, cheroot, cherrypy, cryptography, docker, docker-pycreds, google-auth, junos-eznc, kubernetes, mock, more-itertools, moto, ncclient, packaging, pynacl, pyopenssl, pytest, python-dateutil, python-jose, pyvmomi, responses, salttesting, tempora, textfsm, transitions, vcert, virtualenv, websocket-client +six==1.12.0 # via bcrypt, cheroot, cherrypy, cryptography, docker, docker-pycreds, google-auth, junos-eznc, kubernetes, mock, more-itertools, moto, ncclient, packaging, pynacl, pyopenssl, pytest, pytest-salt-factories, python-dateutil, python-jose, pyvmomi, responses, salttesting, tempora, textfsm, transitions, vcert, virtualenv, websocket-client smmap2==2.0.5 # via gitdb2 strict-rfc3339==0.7 tempora==1.14.1 # via portend diff --git a/requirements/static/py3.6/linux.txt b/requirements/static/py3.6/linux.txt index c49ee42115d..4774427eb06 100644 --- a/requirements/static/py3.6/linux.txt +++ b/requirements/static/py3.6/linux.txt @@ -83,6 +83,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.10.4 pytest-salt-runtests-bridge==2019.12.5 pytest-salt==2020.1.27 pytest-tempdir==2019.10.12 @@ -104,7 +105,7 @@ salttesting==2017.6.1 scp==0.13.2 # via junos-eznc setproctitle==1.1.10 setuptools-scm==3.2.0 -six==1.12.0 # via bcrypt, cheroot, cherrypy, cryptography, docker, docker-pycreds, google-auth, junos-eznc, kazoo, kubernetes, mock, more-itertools, moto, ncclient, packaging, pygit2, pynacl, pyopenssl, pytest, python-dateutil, python-jose, pyvmomi, responses, salttesting, tempora, textfsm, transitions, vcert, websocket-client +six==1.12.0 # via bcrypt, cheroot, cherrypy, cryptography, docker, docker-pycreds, google-auth, junos-eznc, kazoo, kubernetes, mock, more-itertools, moto, ncclient, packaging, pygit2, pynacl, pyopenssl, pytest, pytest-salt-factories, python-dateutil, python-jose, pyvmomi, responses, salttesting, tempora, textfsm, transitions, vcert, websocket-client smmap2==2.0.5 # via gitdb2 strict-rfc3339==0.7 tempora==1.14.1 # via portend diff --git a/requirements/static/py3.6/windows.txt b/requirements/static/py3.6/windows.txt index 4e11224b4cc..8bc1701907e 100644 --- a/requirements/static/py3.6/windows.txt +++ b/requirements/static/py3.6/windows.txt @@ -77,6 +77,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.10.4 pytest-salt-runtests-bridge==2019.12.5 pytest-salt==2020.1.27 pytest-tempdir==2019.10.12 @@ -99,7 +100,7 @@ s3transfer==0.2.0 # via boto3 salttesting==2017.6.1 sed==0.3.1 setproctitle==1.1.10 -six==1.12.0 # via cheroot, cherrypy, cryptography, docker, docker-pycreds, google-auth, kubernetes, mock, more-itertools, moto, packaging, pygit2, pyopenssl, pytest, python-dateutil, python-jose, pyvmomi, responses, salttesting, tempora, websocket-client +six==1.12.0 # via cheroot, cherrypy, cryptography, docker, docker-pycreds, google-auth, kubernetes, mock, more-itertools, moto, packaging, pygit2, pyopenssl, pytest, pytest-salt-factories, python-dateutil, python-jose, pyvmomi, responses, salttesting, tempora, websocket-client smmap2==2.0.5 strict-rfc3339==0.7 tempora==1.14.1 # via portend diff --git a/requirements/static/py3.7/darwin.txt b/requirements/static/py3.7/darwin.txt index a7f61e83289..825d8d7c1e8 100644 --- a/requirements/static/py3.7/darwin.txt +++ b/requirements/static/py3.7/darwin.txt @@ -86,6 +86,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.10.4 pytest-salt-runtests-bridge==2019.12.5 pytest-salt==2020.1.27 pytest-tempdir==2019.10.12 @@ -106,7 +107,7 @@ s3transfer==0.2.0 # via boto3 salttesting==2017.6.1 scp==0.13.2 # via junos-eznc setproctitle==1.1.10 -six==1.12.0 # via bcrypt, cheroot, cherrypy, cryptography, docker, docker-pycreds, google-auth, junos-eznc, kubernetes, mock, more-itertools, moto, ncclient, packaging, pynacl, pyopenssl, pytest, python-dateutil, python-jose, pyvmomi, responses, salttesting, tempora, textfsm, transitions, vcert, virtualenv, websocket-client +six==1.12.0 # via bcrypt, cheroot, cherrypy, cryptography, docker, docker-pycreds, google-auth, junos-eznc, kubernetes, mock, more-itertools, moto, ncclient, packaging, pynacl, pyopenssl, pytest, pytest-salt-factories, python-dateutil, python-jose, pyvmomi, responses, salttesting, tempora, textfsm, transitions, vcert, virtualenv, websocket-client smmap2==2.0.5 # via gitdb2 strict-rfc3339==0.7 tempora==1.14.1 # via portend diff --git a/requirements/static/py3.7/linux.txt b/requirements/static/py3.7/linux.txt index cf8340ab263..10611cf40e5 100644 --- a/requirements/static/py3.7/linux.txt +++ b/requirements/static/py3.7/linux.txt @@ -83,6 +83,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.10.4 pytest-salt-runtests-bridge==2019.12.5 pytest-salt==2020.1.27 pytest-tempdir==2019.10.12 @@ -104,7 +105,7 @@ salttesting==2017.6.1 scp==0.13.2 # via junos-eznc setproctitle==1.1.10 setuptools-scm==3.2.0 -six==1.12.0 # via bcrypt, cheroot, cherrypy, cryptography, docker, docker-pycreds, google-auth, junos-eznc, kazoo, kubernetes, mock, more-itertools, moto, ncclient, packaging, pygit2, pynacl, pyopenssl, pytest, python-dateutil, python-jose, pyvmomi, responses, salttesting, tempora, textfsm, transitions, vcert, websocket-client +six==1.12.0 # via bcrypt, cheroot, cherrypy, cryptography, docker, docker-pycreds, google-auth, junos-eznc, kazoo, kubernetes, mock, more-itertools, moto, ncclient, packaging, pygit2, pynacl, pyopenssl, pytest, pytest-salt-factories, python-dateutil, python-jose, pyvmomi, responses, salttesting, tempora, textfsm, transitions, vcert, websocket-client smmap2==2.0.5 # via gitdb2 strict-rfc3339==0.7 tempora==1.14.1 # via portend diff --git a/requirements/static/py3.7/windows.txt b/requirements/static/py3.7/windows.txt index d04a40b7e01..270f169c83c 100644 --- a/requirements/static/py3.7/windows.txt +++ b/requirements/static/py3.7/windows.txt @@ -76,6 +76,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.10.4 pytest-salt-runtests-bridge==2019.12.5 pytest-salt==2020.1.27 pytest-tempdir==2019.10.12 @@ -98,7 +99,7 @@ s3transfer==0.2.0 # via boto3 salttesting==2017.6.1 sed==0.3.1 setproctitle==1.1.10 -six==1.12.0 # via cheroot, cherrypy, cryptography, docker, docker-pycreds, google-auth, kubernetes, mock, more-itertools, moto, packaging, pygit2, pyopenssl, pytest, python-dateutil, python-jose, pyvmomi, responses, salttesting, tempora, websocket-client +six==1.12.0 # via cheroot, cherrypy, cryptography, docker, docker-pycreds, google-auth, kubernetes, mock, more-itertools, moto, packaging, pygit2, pyopenssl, pytest, pytest-salt-factories, python-dateutil, python-jose, pyvmomi, responses, salttesting, tempora, websocket-client smmap2==2.0.5 strict-rfc3339==0.7 tempora==1.14.1 # via portend diff --git a/requirements/static/py3.8/darwin.txt b/requirements/static/py3.8/darwin.txt index 1e9cfa405cb..841f07ad477 100644 --- a/requirements/static/py3.8/darwin.txt +++ b/requirements/static/py3.8/darwin.txt @@ -85,6 +85,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.10.4 pytest-salt-runtests-bridge==2019.12.5 pytest-salt==2020.1.27 pytest-tempdir==2019.10.12 @@ -105,7 +106,7 @@ s3transfer==0.2.0 # via boto3 salttesting==2017.6.1 scp==0.13.2 # via junos-eznc setproctitle==1.1.10 -six==1.12.0 # via bcrypt, cheroot, cherrypy, cryptography, docker, docker-pycreds, google-auth, junos-eznc, kubernetes, mock, more-itertools, moto, ncclient, packaging, pynacl, pyopenssl, pytest, python-dateutil, python-jose, pyvmomi, responses, salttesting, tempora, textfsm, transitions, vcert, virtualenv, websocket-client +six==1.12.0 # via bcrypt, cheroot, cherrypy, cryptography, docker, docker-pycreds, google-auth, junos-eznc, kubernetes, mock, more-itertools, moto, ncclient, packaging, pynacl, pyopenssl, pytest, pytest-salt-factories, python-dateutil, python-jose, pyvmomi, responses, salttesting, tempora, textfsm, transitions, vcert, virtualenv, websocket-client smmap2==2.0.5 # via gitdb2 strict-rfc3339==0.7 tempora==1.14.1 # via portend diff --git a/requirements/static/py3.8/linux.txt b/requirements/static/py3.8/linux.txt index 7469f78521d..77f4140d47a 100644 --- a/requirements/static/py3.8/linux.txt +++ b/requirements/static/py3.8/linux.txt @@ -83,6 +83,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.10.4 pytest-salt-runtests-bridge==2019.12.5 pytest-salt==2020.1.27 pytest-tempdir==2019.10.12 @@ -104,7 +105,7 @@ salttesting==2017.6.1 scp==0.13.2 # via junos-eznc setproctitle==1.1.10 setuptools-scm==3.2.0 -six==1.12.0 # via bcrypt, cheroot, cherrypy, cryptography, docker, docker-pycreds, google-auth, junos-eznc, kazoo, kubernetes, mock, more-itertools, moto, ncclient, packaging, pynacl, pyopenssl, pytest, python-dateutil, python-jose, pyvmomi, responses, salttesting, tempora, textfsm, transitions, vcert, websocket-client +six==1.12.0 # via bcrypt, cheroot, cherrypy, cryptography, docker, docker-pycreds, google-auth, junos-eznc, kazoo, kubernetes, mock, more-itertools, moto, ncclient, packaging, pynacl, pyopenssl, pytest, pytest-salt-factories, python-dateutil, python-jose, pyvmomi, responses, salttesting, tempora, textfsm, transitions, vcert, websocket-client smmap2==2.0.5 # via gitdb2 strict-rfc3339==0.7 tempora==1.14.1 # via portend diff --git a/requirements/static/py3.9/darwin.txt b/requirements/static/py3.9/darwin.txt index 1797abe753a..30880ba5968 100644 --- a/requirements/static/py3.9/darwin.txt +++ b/requirements/static/py3.9/darwin.txt @@ -85,6 +85,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.10.4 pytest-salt-runtests-bridge==2019.12.5 pytest-salt==2020.1.27 pytest-tempdir==2019.10.12 @@ -105,7 +106,7 @@ s3transfer==0.2.0 # via boto3 salttesting==2017.6.1 scp==0.13.2 # via junos-eznc setproctitle==1.1.10 -six==1.12.0 # via bcrypt, cheroot, cherrypy, cryptography, docker, docker-pycreds, google-auth, junos-eznc, kubernetes, mock, more-itertools, moto, ncclient, packaging, pynacl, pyopenssl, pytest, python-dateutil, python-jose, pyvmomi, responses, salttesting, tempora, textfsm, transitions, vcert, virtualenv, websocket-client +six==1.12.0 # via bcrypt, cheroot, cherrypy, cryptography, docker, docker-pycreds, google-auth, junos-eznc, kubernetes, mock, more-itertools, moto, ncclient, packaging, pynacl, pyopenssl, pytest, pytest-salt-factories, python-dateutil, python-jose, pyvmomi, responses, salttesting, tempora, textfsm, transitions, vcert, virtualenv, websocket-client smmap2==2.0.5 # via gitdb2 strict-rfc3339==0.7 tempora==1.14.1 # via portend diff --git a/requirements/static/py3.9/linux.txt b/requirements/static/py3.9/linux.txt index 0a815b2aae2..ca623207cb0 100644 --- a/requirements/static/py3.9/linux.txt +++ b/requirements/static/py3.9/linux.txt @@ -83,6 +83,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.10.4 pytest-salt-runtests-bridge==2019.12.5 pytest-salt==2020.1.27 pytest-tempdir==2019.10.12 @@ -104,7 +105,7 @@ salttesting==2017.6.1 scp==0.13.2 # via junos-eznc setproctitle==1.1.10 setuptools-scm==3.2.0 -six==1.12.0 # via bcrypt, cheroot, cherrypy, cryptography, docker, docker-pycreds, google-auth, junos-eznc, kazoo, kubernetes, mock, more-itertools, moto, ncclient, packaging, pynacl, pyopenssl, pytest, python-dateutil, python-jose, pyvmomi, responses, salttesting, tempora, textfsm, transitions, vcert, websocket-client +six==1.12.0 # via bcrypt, cheroot, cherrypy, cryptography, docker, docker-pycreds, google-auth, junos-eznc, kazoo, kubernetes, mock, more-itertools, moto, ncclient, packaging, pynacl, pyopenssl, pytest, pytest-salt-factories, python-dateutil, python-jose, pyvmomi, responses, salttesting, tempora, textfsm, transitions, vcert, websocket-client smmap2==2.0.5 # via gitdb2 strict-rfc3339==0.7 tempora==1.14.1 # via portend diff --git a/tests/conftest.py b/tests/conftest.py index 4debd1e16be..45385904cd5 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -37,7 +37,6 @@ import salt.utils.path import salt.utils.platform import salt.utils.win_functions from _pytest.mark.evaluate import MarkEvaluator -from pytestsalt.utils import cli_scripts from salt.ext import six from salt.serializers import yaml from salt.utils.immutabletypes import freeze @@ -56,7 +55,6 @@ if CODE_DIR in sys.path: sys.path.remove(CODE_DIR) sys.path.insert(0, CODE_DIR) - # Coverage if "COVERAGE_PROCESS_START" in os.environ: MAYBE_RUN_COVERAGE = True @@ -116,18 +114,6 @@ log = logging.getLogger("salt.testsuite") # ----- PyTest Tempdir Plugin Hooks ---------------------------------------------------------------------------------> -def pytest_tempdir_temproot(): - # Taken from https://github.com/saltstack/salt/blob/v2019.2.0/tests/support/paths.py - # Avoid ${TMPDIR} and gettempdir() on MacOS as they yield a base path too long - # for unix sockets: ``error: AF_UNIX path too long`` - # Gentoo Portage prefers ebuild tests are rooted in ${TMPDIR} - if not sys.platform.startswith("darwin"): - tempdir = os.environ.get("TMPDIR") or tempfile.gettempdir() - else: - tempdir = "/tmp" - return os.path.abspath(os.path.realpath(tempdir)) - - def pytest_tempdir_basename(): """ Return the temporary directory basename for the salt test suite. @@ -339,32 +325,6 @@ def pytest_report_header(): return "max open files; soft: {}; hard: {}".format(soft, hard) -def pytest_runtest_logstart(nodeid): - """ - signal the start of running a single test item. - - This hook will be called **before** :func:`pytest_runtest_setup`, :func:`pytest_runtest_call` and - :func:`pytest_runtest_teardown` hooks. - - :param str nodeid: full id of the item - :param location: a triple of ``(filename, linenum, testname)`` - """ - log.debug(">>>>> START >>>>> %s", nodeid) - - -def pytest_runtest_logfinish(nodeid): - """ - signal the complete finish of running a single test item. - - This hook will be called **after** :func:`pytest_runtest_setup`, :func:`pytest_runtest_call` and - :func:`pytest_runtest_teardown` hooks. - - :param str nodeid: full id of the item - :param location: a triple of ``(filename, linenum, testname)`` - """ - log.debug("<<<<< END <<<<<<< %s", nodeid) - - @pytest.hookimpl(hookwrapper=True, trylast=True) def pytest_collection_modifyitems(config, items): """ @@ -404,13 +364,17 @@ def pytest_collection_modifyitems(config, items): return self._finished except AttributeError: if self.node_ids: - log.debug( - "%s is still going to be used, not terminating it. " - "Still in use on:\n%s", - self, - pprint.pformat(list(self.node_ids)), - ) - return + if ( + not request.session.shouldfail + and not request.session.shouldstop + ): + log.debug( + "%s is still going to be used, not terminating it. " + "Still in use on:\n%s", + self, + pprint.pformat(list(self.node_ids)), + ) + return log.debug("Finish called on %s", self) try: return func(request) @@ -458,7 +422,8 @@ def pytest_runtest_protocol(item, nextitem): yield finally: for fixturedef in used_fixture_defs: - fixturedef.node_ids.remove(item.nodeid) + if item.nodeid in fixturedef.node_ids: + fixturedef.node_ids.remove(item.nodeid) if not fixturedef.node_ids: # This fixture is not used in any more test functions fixturedef.finish(request) @@ -919,301 +884,6 @@ def temp_state_file(name, contents, saltenv="base", strip_first_newline=True): # ----- Fixtures Overrides ------------------------------------------------------------------------------------------> -# ----- Generate CLI Scripts ----------------------------------------------------------------------------------------> -@pytest.fixture(scope="session") -def cli_master_script_name(): - """ - Return the CLI script basename - """ - return "cli_salt_master.py" - - -@pytest.fixture(scope="session") -def cli_minion_script_name(): - """ - Return the CLI script basename - """ - return "cli_salt_minion.py" - - -@pytest.fixture(scope="session") -def cli_salt_script_name(): - """ - Return the CLI script basename - """ - return "cli_salt.py" - - -@pytest.fixture(scope="session") -def cli_run_script_name(): - """ - Return the CLI script basename - """ - return "cli_salt_run.py" - - -@pytest.fixture(scope="session") -def cli_key_script_name(): - """ - Return the CLI script basename - """ - return "cli_salt_key.py" - - -@pytest.fixture(scope="session") -def cli_call_script_name(): - """ - Return the CLI script basename - """ - return "cli_salt_call.py" - - -@pytest.fixture(scope="session") -def cli_syndic_script_name(): - """ - Return the CLI script basename - """ - return "cli_salt_syndic.py" - - -@pytest.fixture(scope="session") -def cli_ssh_script_name(): - """ - Return the CLI script basename - """ - return "cli_salt_ssh.py" - - -@pytest.fixture(scope="session") -def cli_proxy_script_name(): - """ - Return the CLI script basename - """ - return "cli_salt_proxy.py" - - -@pytest.fixture(scope="session") -def cli_bin_dir( - tempdir, - request, - python_executable_path, - cli_master_script_name, - cli_minion_script_name, - cli_salt_script_name, - cli_call_script_name, - cli_key_script_name, - cli_run_script_name, - cli_ssh_script_name, - cli_syndic_script_name, - cli_proxy_script_name, -): - """ - Return the path to the CLI script directory to use - """ - tmp_cli_scripts_dir = tempdir.join("cli-scrips-bin") - # Make sure we re-write the scripts every time we start the tests - shutil.rmtree(tmp_cli_scripts_dir.strpath, ignore_errors=True) - tmp_cli_scripts_dir.ensure(dir=True) - cli_bin_dir_path = tmp_cli_scripts_dir.strpath - - # Now that we have the CLI directory created, lets generate the required CLI scripts to run salt's test suite - for script_name in ( - cli_master_script_name, - cli_minion_script_name, - cli_call_script_name, - cli_key_script_name, - cli_run_script_name, - cli_salt_script_name, - cli_ssh_script_name, - cli_syndic_script_name, - cli_proxy_script_name, - ): - original_script_name = ( - os.path.splitext(script_name)[0].split("cli_")[-1].replace("_", "-") - ) - cli_scripts.generate_script( - bin_dir=cli_bin_dir_path, - script_name=original_script_name, - executable=sys.executable, - code_dir=CODE_DIR, - inject_sitecustomize=MAYBE_RUN_COVERAGE, - ) - - # Return the CLI bin dir value - return cli_bin_dir_path - - -# <---- Generate CLI Scripts ----------------------------------------------------------------------------------------- - - -# ----- Salt Configuration ------------------------------------------------------------------------------------------> -@pytest.fixture(scope="session") -def session_master_of_masters_id(): - """ - Returns the master of masters id - """ - return "syndic_master" - - -@pytest.fixture(scope="session") -def session_master_id(): - """ - Returns the session scoped master id - """ - return "master" - - -@pytest.fixture(scope="session") -def session_minion_id(): - """ - Returns the session scoped minion id - """ - return "minion" - - -@pytest.fixture(scope="session") -def session_secondary_minion_id(): - """ - Returns the session scoped secondary minion id - """ - return "sub_minion" - - -@pytest.fixture(scope="session") -def session_syndic_id(): - """ - Returns the session scoped syndic id - """ - return "syndic" - - -@pytest.fixture(scope="session") -def session_proxy_id(): - """ - Returns the session scoped proxy id - """ - return "proxytest" - - -@pytest.fixture(scope="session") -def salt_fail_hard(): - """ - Return the salt fail hard value - """ - return True - - -@pytest.fixture(scope="session") -def session_master_default_options(request, session_root_dir): - with salt.utils.files.fopen(os.path.join(RUNTIME_VARS.CONF_DIR, "master")) as rfh: - opts = yaml.deserialize(rfh.read()) - - tests_known_hosts_file = session_root_dir.join("salt_ssh_known_hosts").strpath - with salt.utils.files.fopen(tests_known_hosts_file, "w") as known_hosts: - known_hosts.write("") - - opts["known_hosts_file"] = tests_known_hosts_file - opts["syndic_master"] = "localhost" - opts["transport"] = request.config.getoption("--transport") - - # Config settings to test `event_return` - if "returner_dirs" not in opts: - opts["returner_dirs"] = [] - opts["returner_dirs"].append(os.path.join(RUNTIME_VARS.FILES, "returners")) - opts["event_return"] = "runtests_noop" - - return opts - - -@pytest.fixture(scope="session") -def session_master_config_overrides(session_root_dir): - 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, - } - } - ) - - # We need to copy the extension modules into the new master root_dir or - # it will be prefixed by it - extension_modules_path = session_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 = session_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) - - pytest_stop_sending_events_file = session_root_dir.join( - "pytest_stop_sending_events_file" - ).strpath - with salt.utils.files.fopen(pytest_stop_sending_events_file, "w") as wfh: - wfh.write("") - - return { - "pillar_opts": True, - "ext_pillar": ext_pillar, - "extension_modules": extension_modules_path, - "file_roots": { - "base": [os.path.join(RUNTIME_VARS.FILES, "file", "base")], - # Alternate root to test __env__ choices - "prod": [os.path.join(RUNTIME_VARS.FILES, "file", "prod")], - }, - "pillar_roots": {"base": [os.path.join(RUNTIME_VARS.FILES, "pillar", "base")]}, - "reactor": [ - { - "salt/minion/*/start": [ - os.path.join(RUNTIME_VARS.FILES, "reactor-sync-minion.sls") - ], - }, - { - "salt/test/reactor": [ - os.path.join(RUNTIME_VARS.FILES, "reactor-test.sls") - ], - }, - ], - "pytest_stop_sending_events_file": pytest_stop_sending_events_file, - } - - -@pytest.fixture(scope="session") -def session_minion_default_options(request, tempdir): - with salt.utils.files.fopen(os.path.join(RUNTIME_VARS.CONF_DIR, "minion")) as rfh: - opts = yaml.deserialize(rfh.read()) - - opts["hosts.file"] = tempdir.join("hosts").strpath - opts["aliases.file"] = tempdir.join("aliases").strpath - opts["transport"] = request.config.getoption("--transport") - - return opts - - def _get_virtualenv_binary_path(): try: return _get_virtualenv_binary_path.__virtualenv_binary__ @@ -1254,75 +924,140 @@ def _get_virtualenv_binary_path(): return virtualenv_binary -@pytest.fixture(scope="session") -def session_minion_config_overrides(): - opts = { - "file_roots": { - "base": [os.path.join(RUNTIME_VARS.FILES, "file", "base")], - # Alternate root to test __env__ choices - "prod": [os.path.join(RUNTIME_VARS.FILES, "file", "prod")], - }, - "pillar_roots": {"base": [os.path.join(RUNTIME_VARS.FILES, "pillar", "base")]}, - } - virtualenv_binary = _get_virtualenv_binary_path() - if virtualenv_binary: - opts["venv_bin"] = virtualenv_binary - return opts +# @pytest.fixture(scope='session') +# def salt_syndic_master_config(request, salt_factories): +# return salt_factories.configure_master(request, 'syndic_master', order_masters=True) + +# @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): +# return salt_factories.configure_master(request, 'master', master_of_masters_id='syndic_master') @pytest.fixture(scope="session") -def session_secondary_minion_default_options(request, tempdir): - with salt.utils.files.fopen( - os.path.join(RUNTIME_VARS.CONF_DIR, "sub_minion") - ) as rfh: - opts = yaml.deserialize(rfh.read()) - - opts["hosts.file"] = tempdir.join("hosts").strpath - opts["aliases.file"] = tempdir.join("aliases").strpath - opts["transport"] = request.config.getoption("--transport") - - return opts +def salt_master_config(request, salt_factories): + return salt_factories.configure_master(request, "master") @pytest.fixture(scope="session") -def session_seconary_minion_config_overrides(): +def salt_minion_config(request, salt_factories, salt_master_config): + return salt_factories.configure_minion(request, "minion", master_id="master") + + +@pytest.fixture(scope="session") +def salt_sub_minion_config(request, salt_factories, salt_master_config): + return salt_factories.configure_minion(request, "sub_minion", master_id="master") + + +def pytest_saltfactories_generate_default_master_configuration( + request, factories_manager, root_dir, master_id, order_masters +): + """ + Hook which should return a dictionary tailored for the provided master_id + + Stops at the first non None result + """ + if master_id == "master": + with salt.utils.files.fopen( + os.path.join(RUNTIME_VARS.CONF_DIR, "master") + ) as rfh: + opts = 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("") + + opts["known_hosts_file"] = tests_known_hosts_file + opts["syndic_master"] = "localhost" + opts["transport"] = request.config.getoption("--transport") + + # Config settings to test `event_return` + if "returner_dirs" not in opts: + opts["returner_dirs"] = [] + opts["returner_dirs"].append(os.path.join(RUNTIME_VARS.FILES, "returners")) + opts["event_return"] = "runtests_noop" + + return opts + elif master_id == "syndic_master": + with salt.utils.files.fopen( + os.path.join(RUNTIME_VARS.CONF_DIR, "syndic_master") + ) as rfh: + opts = yaml.deserialize(rfh.read()) + + opts["hosts.file"] = root_dir.join("hosts").strpath + opts["aliases.file"] = root_dir.join("aliases").strpath + opts["transport"] = request.config.getoption("--transport") + + return opts + elif master_id == "mm-master": + with salt.utils.files.fopen( + os.path.join(RUNTIME_VARS.CONF_DIR, "mm_master") + ) as rfh: + opts = yaml.deserialize(rfh.read()) + return opts + elif master_id == "mm-sub-master": + with salt.utils.files.fopen( + os.path.join(RUNTIME_VARS.CONF_DIR, "mm_sub_master") + ) as rfh: + opts = yaml.deserialize(rfh.read()) + return opts + + +def pytest_saltfactories_master_configuration_overrides( + request, factories_manager, root_dir, master_id, default_options, order_masters +): + """ + Hook which should return a dictionary tailored for the provided master_id. + This dictionary will override the default_options dictionary. + + Stops at the first non None result + """ opts = {} - virtualenv_binary = _get_virtualenv_binary_path() - if virtualenv_binary: - opts["venv_bin"] = virtualenv_binary - return opts - - -@pytest.fixture(scope="session") -def session_master_of_masters_default_options(request, tempdir): - with salt.utils.files.fopen( - os.path.join(RUNTIME_VARS.CONF_DIR, "syndic_master") - ) as rfh: - opts = yaml.deserialize(rfh.read()) - - opts["hosts.file"] = tempdir.join("hosts").strpath - opts["aliases.file"] = tempdir.join("aliases").strpath - opts["transport"] = request.config.getoption("--transport") - - return opts - - -@pytest.fixture(scope="session") -def session_master_of_masters_config_overrides(session_master_of_masters_root_dir): + ext_pillar = [] if salt.utils.platform.is_windows(): - ext_pillar = { - "cmd_yaml": "type {0}".format(os.path.join(RUNTIME_VARS.FILES, "ext.yaml")) - } + ext_pillar.append( + { + "cmd_yaml": "type {0}".format( + os.path.join(RUNTIME_VARS.FILES, "ext.yaml") + ) + } + ) else: - ext_pillar = { - "cmd_yaml": "cat {0}".format(os.path.join(RUNTIME_VARS.FILES, "ext.yaml")) - } + ext_pillar.append( + {"cmd_yaml": "cat {0}".format(os.path.join(RUNTIME_VARS.FILES, "ext.yaml"))} + ) + if master_id == "master": + ext_pillar.append( + { + "file_tree": { + "root_dir": os.path.join( + RUNTIME_VARS.PILLAR_DIR, "base", "file_tree" + ), + "follow_dir_links": False, + "keep_newline": True, + } + } + ) + opts["pillar_opts"] = True + opts["reactor"] = [ + { + "salt/minion/*/start": [ + os.path.join(RUNTIME_VARS.FILES, "reactor-sync-minion.sls") + ], + }, + { + "salt/test/reactor": [ + os.path.join(RUNTIME_VARS.FILES, "reactor-test.sls") + ], + }, + ] # We need to copy the extension modules into the new master root_dir or # it will be prefixed by it - extension_modules_path = session_master_of_masters_root_dir.join( - "extension_modules" - ).strpath + 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"), @@ -1330,9 +1065,7 @@ def session_master_of_masters_config_overrides(session_master_of_masters_root_di ) # Copy the autosign_file to the new master root_dir - autosign_file_path = session_master_of_masters_root_dir.join( - "autosign_file" - ).strpath + autosign_file_path = root_dir.join("autosign_file").strpath shutil.copyfile( os.path.join(RUNTIME_VARS.FILES, "autosign_file"), autosign_file_path ) @@ -1342,128 +1075,242 @@ def session_master_of_masters_config_overrides(session_master_of_masters_root_di ) os.chmod(autosign_file_path, autosign_file_permissions) - pytest_stop_sending_events_file = session_master_of_masters_root_dir.join( - "pytest_stop_sending_events_file" - ).strpath - with salt.utils.files.fopen(pytest_stop_sending_events_file, "w") as wfh: - wfh.write("") - - return { - "ext_pillar": [ext_pillar], - "extension_modules": extension_modules_path, - "file_roots": { - "base": [os.path.join(RUNTIME_VARS.FILES, "file", "base")], - # Alternate root to test __env__ choices - "prod": [os.path.join(RUNTIME_VARS.FILES, "file", "prod")], - }, - "pillar_roots": {"base": [os.path.join(RUNTIME_VARS.FILES, "pillar", "base")]}, - "pytest_stop_sending_events_file": pytest_stop_sending_events_file, - } + opts.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 opts -@pytest.fixture(scope="session") -def session_syndic_master_default_options(request, tempdir): - with salt.utils.files.fopen( - os.path.join(RUNTIME_VARS.CONF_DIR, "syndic_master") - ) as rfh: - opts = yaml.deserialize(rfh.read()) +def pytest_saltfactories_generate_default_minion_configuration( + request, factories_manager, root_dir, minion_id, master_port +): + """ + Hook which should return a dictionary tailored for the provided minion_id - opts["hosts.file"] = tempdir.join("hosts").strpath - opts["aliases.file"] = tempdir.join("aliases").strpath - opts["transport"] = request.config.getoption("--transport") + Stops at the first non None result + """ + if minion_id == "minion": + with salt.utils.files.fopen( + os.path.join(RUNTIME_VARS.CONF_DIR, "minion") + ) as rfh: + opts = yaml.deserialize(rfh.read()) + elif minion_id == "sub_minion": + with salt.utils.files.fopen( + os.path.join(RUNTIME_VARS.CONF_DIR, "sub_minion") + ) as rfh: + opts = yaml.deserialize(rfh.read()) + elif minion_id == "mm-minion": + with salt.utils.files.fopen( + os.path.join(RUNTIME_VARS.CONF_DIR, "mm_minion") + ) as rfh: + opts = yaml.deserialize(rfh.read()) + elif minion_id == "mm-sub-minion": + with salt.utils.files.fopen( + os.path.join(RUNTIME_VARS.CONF_DIR, "mm_sub_minion") + ) as rfh: + opts = yaml.deserialize(rfh.read()) + else: + raise RuntimeError("Not prepared to handle minion_id '{}'".format(minion_id)) + opts["hosts.file"] = root_dir.join("hosts").strpath + opts["aliases.file"] = root_dir.join("aliases").strpath + opts["transport"] = request.config.getoption("--transport") + + return opts + + +def pytest_saltfactories_minion_configuration_overrides( + request, factories_manager, root_dir, minion_id, default_options +): + """ + Hook which should return a dictionary tailored for the provided minion_id. + This dictionary will override the default_options dictionary. + + Stops at the first non None result + """ + if minion_id in ("minion", "sub_minion"): + opts = { + "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: + opts["venv_bin"] = virtualenv_binary + return opts + if minion_id in ("mm-minion", "mm-sub-minion"): + mm_master_port = factories_manager.cache["configs"]["masters"]["mm-master"][ + "ret_port" + ] + mm_sub_master_port = factories_manager.cache["configs"]["masters"][ + "mm-sub-master" + ]["ret_port"] + opts = { + "master_port": "", + "master": [ + "localhost:{}".format(mm_master_port), + "localhost:{}".format(mm_sub_master_port), + ], + "test.foo": "baz", + } return opts -@pytest.fixture(scope="session") -def session_syndic_default_options(request, tempdir): - with salt.utils.files.fopen(os.path.join(RUNTIME_VARS.CONF_DIR, "syndic")) as rfh: - opts = yaml.deserialize(rfh.read()) +@pytest.hookspec(firstresult=True) +def pytest_saltfactories_generate_default_syndic_configuration( + 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: - opts["hosts.file"] = tempdir.join("hosts").strpath - opts["aliases.file"] = tempdir.join("aliases").strpath - opts["transport"] = request.config.getoption("--transport") + * `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 - return opts + 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"] = root_dir.join("hosts").strpath + opts["aliases.file"] = root_dir.join("aliases").strpath + opts["transport"] = request.config.getoption("--transport") + factory_opts["syndic"] = opts + return factory_opts -@pytest.fixture(scope="session") -def session_proxy_default_options(request, tempdir): - with salt.utils.files.fopen(os.path.join(RUNTIME_VARS.CONF_DIR, "proxy")) as rfh: - opts = yaml.deserialize(rfh.read()) +@pytest.hookspec(firstresult=True) +def pytest_saltfactories_syndic_configuration_overrides( + request, factories_manager, syndic_id, default_options +): + """ + Hook which should return a dictionary tailored for the provided syndic_id. + This dictionary will override the default_options dictionary. - opts["hosts.file"] = tempdir.join("hosts").strpath - opts["aliases.file"] = tempdir.join("aliases").strpath - opts["transport"] = request.config.getoption("--transport") + The returned dictionary should contain 3 keys: - return opts + * `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.hookspec(firstresult=True) +def pytest_saltfactories_generate_default_proxy_minion_configuration( + request, factories_manager, proxy_minion_id, master_port +): + """ + Hook which should return a dictionary tailored for the provided proxy_minion_id + + Stops at the first non None result + """ + + +@pytest.hookspec(firstresult=True) +def pytest_saltfactories_proxy_minion_configuration_overrides( + request, factories_manager, root_dir, proxy_minion_id, default_options +): + """ + Hook which should return a dictionary tailored for the provided proxy_minion_id. + This dictionary will override the default_options dictionary. + + Stops at the first non None result + """ + if proxy_minion_id == "proxy": + with salt.utils.files.fopen( + os.path.join(RUNTIME_VARS.CONF_DIR, "proxy") + ) as rfh: + opts = yaml.deserialize(rfh.read()) + else: + raise RuntimeError( + "Not prepared to handle proxy minion_id '{}'".format(proxy_minion_id) + ) + + opts["hosts.file"] = root_dir.join("hosts").strpath + opts["aliases.file"] = root_dir.join("aliases").strpath + opts["transport"] = request.config.getoption("--transport") + + return opts @pytest.fixture(scope="session", autouse=True) def bridge_pytest_and_runtests( reap_stray_processes, - session_root_dir, - session_conf_dir, - session_secondary_conf_dir, - session_syndic_conf_dir, - session_master_of_masters_conf_dir, - session_base_env_pillar_tree_root_dir, - session_base_env_state_tree_root_dir, - session_prod_env_state_tree_root_dir, - session_master_config, - session_minion_config, - session_secondary_minion_config, - session_master_of_masters_config, - session_syndic_config, + 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 = session_root_dir.realpath().strpath - RUNTIME_VARS.TMP_CONF_DIR = session_conf_dir.realpath().strpath - RUNTIME_VARS.TMP_SUB_MINION_CONF_DIR = session_secondary_conf_dir.realpath().strpath - RUNTIME_VARS.TMP_SYNDIC_MASTER_CONF_DIR = ( - session_master_of_masters_conf_dir.realpath().strpath + 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_MINION_CONF_DIR = session_syndic_conf_dir.realpath().strpath - RUNTIME_VARS.TMP_PILLAR_TREE = ( - session_base_env_pillar_tree_root_dir.realpath().strpath - ) - RUNTIME_VARS.TMP_STATE_TREE = ( - session_base_env_state_tree_root_dir.realpath().strpath - ) - RUNTIME_VARS.TMP_PRODENV_STATE_TREE = ( - session_prod_env_state_tree_root_dir.realpath().strpath - ) - - # Make sure unittest2 uses the pytest generated configuration - RUNTIME_VARS.RUNTIME_CONFIGS["master"] = freeze(session_master_config) - RUNTIME_VARS.RUNTIME_CONFIGS["minion"] = freeze(session_minion_config) - RUNTIME_VARS.RUNTIME_CONFIGS["sub_minion"] = freeze(session_secondary_minion_config) - RUNTIME_VARS.RUNTIME_CONFIGS["syndic_master"] = freeze( - session_master_of_masters_config - ) - RUNTIME_VARS.RUNTIME_CONFIGS["syndic"] = freeze(session_syndic_config) - RUNTIME_VARS.RUNTIME_CONFIGS["client_config"] = freeze( - salt.config.client_config(session_conf_dir.join("master").strpath) - ) - - # Copy configuration files and directories which are not automatically generated - for entry in os.listdir(RUNTIME_VARS.CONF_DIR): - if entry in ( - "master", - "minion", - "sub_minion", - "syndic", - "syndic_master", - "proxy", - ): - # These have runtime computed values and are handled by pytest-salt fixtures - continue - entry_path = os.path.join(RUNTIME_VARS.CONF_DIR, entry) - if os.path.isfile(entry_path): - shutil.copy(entry_path, os.path.join(RUNTIME_VARS.TMP_CONF_DIR, entry)) - elif os.path.isdir(entry_path): - shutil.copytree(entry_path, os.path.join(RUNTIME_VARS.TMP_CONF_DIR, entry)) + # 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']) # <---- Salt Configuration ------------------------------------------------------------------------------------------- diff --git a/tests/integration/conftest.py b/tests/integration/conftest.py index 853139d225b..5be3a7497c7 100644 --- a/tests/integration/conftest.py +++ b/tests/integration/conftest.py @@ -7,48 +7,54 @@ """ # pylint: disable=unused-argument,redefined-outer-name -# Import Python libs from __future__ import absolute_import, unicode_literals import logging -from collections import OrderedDict -# Import 3rd-party libs -import psutil 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): + return salt_factories.spawn_master(request, "master") + + +@pytest.fixture(scope="package") +def salt_minion(request, salt_factories, salt_master): + return salt_factories.spawn_minion(request, "minion", master_id="master") + + +@pytest.fixture(scope="package") +def salt_sub_minion(request, salt_factories, salt_master): + return salt_factories.spawn_minion(request, "sub_minion", master_id="master") + + @pytest.fixture(scope="package", autouse=True) -def default_session_daemons( - request, - log_server, - session_salt_master, - session_salt_minion, - session_secondary_salt_minion, +def bridge_pytest_and_runtests( + bridge_pytest_and_runtests, + salt_factories, + # salt_syndic_master, + # salt_syndic, + salt_master, + salt_minion, + salt_sub_minion, ): - request.session.stats_processes.update( - OrderedDict( - ( - ("Salt Master", psutil.Process(session_salt_master.pid)), - ("Salt Minion", psutil.Process(session_salt_minion.pid)), - ("Salt Sub Minion", psutil.Process(session_secondary_salt_minion.pid)), - ) - ).items() - ) - - # Run tests yield - - # Stop daemons now(they would be stopped at the end of the test run session - for daemon in ( - session_secondary_salt_minion, - session_salt_minion, - session_salt_master, - ): - try: - daemon.terminate() - except Exception as exc: # pylint: disable=broad-except - log.warning("Failed to terminate daemon: %s", daemon.__class__.__name__) diff --git a/tests/multimaster/conftest.py b/tests/multimaster/conftest.py index f973e1bfc0c..5b1425d09c9 100644 --- a/tests/multimaster/conftest.py +++ b/tests/multimaster/conftest.py @@ -10,809 +10,100 @@ from __future__ import absolute_import, print_function, unicode_literals import logging import os import shutil -from collections import OrderedDict -import psutil import pytest -import salt.utils.files -from pytestsalt.fixtures.config import apply_master_config, apply_minion_config -from pytestsalt.fixtures.daemons import SaltMaster, SaltMinion, start_daemon -from pytestsalt.fixtures.ports import get_unused_localhost_port -from salt.serializers import yaml from salt.utils.immutabletypes import freeze from tests.support.runtests import RUNTIME_VARS log = logging.getLogger(__name__) -SESSION_ROOT_DIR = "session-mm-root" -SESSION_SECONDARY_ROOT_DIR = "session-secondary-mm-root" + +@pytest.fixture(scope="package") +def salt_mm_master_config(request, salt_factories): + return salt_factories.configure_master(request, "mm-master") -@pytest.fixture(scope="session") -def session_mm_root_dir(tempdir): - """ - Return the session scoped salt root dir - """ - return tempdir.mkdir(SESSION_ROOT_DIR) - - -@pytest.fixture(scope="session") -def session_mm_conf_dir(session_mm_root_dir): - """ - Return the session scoped salt root dir - """ - return session_mm_root_dir.join("conf").ensure(dir=True) - - -# ----- Master Fixtures ---------------------------------------------------------------------------------------------> -@pytest.fixture(scope="session") -def session_mm_master_id(): - """ - Returns the session scoped master id - """ - return "mm-master" - - -@pytest.fixture(scope="session") -def session_mm_master_publish_port(): - """ - Returns an unused localhost port for the master publish interface - """ - return get_unused_localhost_port() - - -@pytest.fixture(scope="session") -def session_mm_master_return_port(): - """ - Returns an unused localhost port for the master return interface - """ - return get_unused_localhost_port() - - -@pytest.fixture(scope="session") -def session_mm_master_engine_port(): - """ - Returns an unused localhost port for the pytest session salt master engine - """ - return get_unused_localhost_port() - - -@pytest.fixture(scope="session") -def session_mm_master_tcp_master_pub_port(): - """ - Returns an unused localhost port - """ - return get_unused_localhost_port() - - -@pytest.fixture(scope="session") -def session_mm_master_tcp_master_pull_port(): - """ - Returns an unused localhost port - """ - return get_unused_localhost_port() - - -@pytest.fixture(scope="session") -def session_mm_master_tcp_master_publish_pull(): - """ - Returns an unused localhost port - """ - return get_unused_localhost_port() - - -@pytest.fixture(scope="session") -def session_mm_master_tcp_master_workers(): - """ - Returns an unused localhost port - """ - return get_unused_localhost_port() - - -@pytest.fixture(scope="session") -def session_mm_master_log_prefix(session_mm_master_id): - return "salt-master/{}".format(session_mm_master_id) - - -@pytest.fixture(scope="session") -def session_mm_master_config_file(session_mm_conf_dir): - """ - Returns the path to the salt master configuration file - """ - return session_mm_conf_dir.join("master").realpath().strpath - - -@pytest.fixture(scope="session") -def session_mm_master_default_options(session_master_default_options): - with salt.utils.files.fopen( - os.path.join(RUNTIME_VARS.CONF_DIR, "mm_master") - ) as rfh: - config_file_opts = yaml.deserialize(rfh.read()) - opts = session_master_default_options.copy() - if config_file_opts: - opts.update(config_file_opts) - return opts - - -@pytest.fixture(scope="session") -def session_mm_master_config_overrides( - session_master_config_overrides, session_mm_root_dir -): - overrides = session_master_config_overrides.copy() - pytest_stop_sending_events_file = session_mm_root_dir.join( - "pytest_mm_stop_sending_events_file" - ).strpath - with salt.utils.files.fopen(pytest_stop_sending_events_file, "w") as wfh: - wfh.write("") - overrides["pytest_stop_sending_events_file"] = pytest_stop_sending_events_file - return overrides - - -@pytest.fixture(scope="session") -def session_mm_master_config( - session_mm_root_dir, - session_mm_master_default_options, - session_mm_master_config_file, - session_mm_master_publish_port, - session_mm_master_return_port, - session_mm_master_engine_port, - session_mm_master_config_overrides, - session_mm_master_id, - session_base_env_state_tree_root_dir, - session_prod_env_state_tree_root_dir, - session_base_env_pillar_tree_root_dir, - session_prod_env_pillar_tree_root_dir, - running_username, - log_server_port, - log_server_level, - engines_dir, - log_handlers_dir, - session_mm_master_log_prefix, - session_mm_master_tcp_master_pub_port, - session_mm_master_tcp_master_pull_port, - session_mm_master_tcp_master_publish_pull, - session_mm_master_tcp_master_workers, -): - """ - This fixture will return the salt master configuration options after being - overridden with any options passed from ``session_master_config_overrides`` - """ - return apply_master_config( - session_mm_master_default_options, - session_mm_root_dir, - session_mm_master_config_file, - session_mm_master_publish_port, - session_mm_master_return_port, - session_mm_master_engine_port, - session_mm_master_config_overrides, - session_mm_master_id, - [session_base_env_state_tree_root_dir.strpath], - [session_prod_env_state_tree_root_dir.strpath], - [session_base_env_pillar_tree_root_dir.strpath], - [session_prod_env_pillar_tree_root_dir.strpath], - running_username, - log_server_port, - log_server_level, - engines_dir, - log_handlers_dir, - session_mm_master_log_prefix, - session_mm_master_tcp_master_pub_port, - session_mm_master_tcp_master_pull_port, - session_mm_master_tcp_master_publish_pull, - session_mm_master_tcp_master_workers, +@pytest.fixture(scope="package") +def salt_mm_minion_config(request, salt_factories, salt_mm_master, salt_mm_sub_master): + return salt_factories.configure_minion( + request, "mm-minion", master_id=salt_mm_master.config["id"] ) -@pytest.fixture(scope="session") -def session_mm_salt_master( - request, - session_mm_conf_dir, - session_mm_master_id, - session_mm_master_config, - log_server, # pylint: disable=unused-argument - session_mm_master_log_prefix, - cli_master_script_name, - _cli_bin_dir, - _salt_fail_hard, +@pytest.fixture(scope="package") +def salt_mm_sub_master_config(request, salt_factories, salt_mm_master): + return salt_factories.configure_master(request, "mm-sub-master") + + +@pytest.fixture(scope="package") +def salt_mm_sub_minion_config( + request, salt_factories, salt_mm_master, salt_mm_sub_master ): - """ - Returns a running salt-master - """ - return start_daemon( - request, - daemon_name="salt-master", - daemon_id=session_mm_master_id, - daemon_log_prefix=session_mm_master_log_prefix, - daemon_cli_script_name=cli_master_script_name, - daemon_config=session_mm_master_config, - daemon_config_dir=session_mm_conf_dir, - daemon_class=SaltMaster, - bin_dir_path=_cli_bin_dir, - fail_hard=_salt_fail_hard, - event_listener_config_dir=session_mm_conf_dir, - start_timeout=60, + return salt_factories.configure_minion( + request, "mm-sub-minion", master_id=salt_mm_sub_master.config["id"] ) -# <---- Master Fixtures ---------------------------------------------------------------------------------------------- +@pytest.fixture(scope="package") +def salt_mm_master(request, salt_factories): + return salt_factories.spawn_master(request, "mm-master") -@pytest.fixture(scope="session") -def session_mm_secondary_root_dir(tempdir): - """ - Return the session scoped salt secondary root dir - """ - return tempdir.mkdir(SESSION_SECONDARY_ROOT_DIR) - - -@pytest.fixture(scope="session") -def session_mm_secondary_conf_dir(session_mm_secondary_root_dir): - """ - Return the session scoped salt root dir - """ - return session_mm_secondary_root_dir.join("conf").ensure(dir=True) - - -# ----- Sub Master Fixtures -----------------------------------------------------------------------------------------> - - -@pytest.fixture(scope="session") -def session_mm_secondary_master_id(): - """ - Returns the session scoped master id - """ - return "mm-sub-master" - - -@pytest.fixture(scope="session") -def session_mm_secondary_master_publish_port(): - """ - Returns an unused localhost port for the master publish interface - """ - return get_unused_localhost_port() - - -@pytest.fixture(scope="session") -def session_mm_secondary_master_return_port(): - """ - Returns an unused localhost port for the master return interface - """ - return get_unused_localhost_port() - - -@pytest.fixture(scope="session") -def session_mm_secondary_master_engine_port(): - """ - Returns an unused localhost port for the pytest session salt master engine - """ - return get_unused_localhost_port() - - -@pytest.fixture(scope="session") -def session_mm_secondary_master_tcp_master_pub_port(): - """ - Returns an unused localhost port - """ - return get_unused_localhost_port() - - -@pytest.fixture(scope="session") -def session_mm_secondary_master_tcp_master_pull_port(): - """ - Returns an unused localhost port - """ - return get_unused_localhost_port() - - -@pytest.fixture(scope="session") -def session_mm_secondary_master_tcp_master_publish_pull(): - """ - Returns an unused localhost port - """ - return get_unused_localhost_port() - - -@pytest.fixture(scope="session") -def session_mm_secondary_master_tcp_master_workers(): - """ - Returns an unused localhost port - """ - return get_unused_localhost_port() - - -@pytest.fixture(scope="session") -def session_mm_secondary_master_log_prefix(session_mm_secondary_master_id): - return "salt-master/{}".format(session_mm_secondary_master_id) - - -@pytest.fixture(scope="session") -def session_mm_secondary_master_config_file(session_mm_secondary_conf_dir): - """ - Returns the path to the salt master configuration file - """ - return session_mm_secondary_conf_dir.join("master").realpath().strpath - - -@pytest.fixture(scope="session") -def session_mm_secondary_master_default_options(session_master_default_options): - opts = session_master_default_options.copy() - with salt.utils.files.fopen( - os.path.join(RUNTIME_VARS.CONF_DIR, "mm_sub_master") - ) as rfh: - opts.update(yaml.deserialize(rfh.read())) - return opts - - -@pytest.fixture(scope="session") -def session_mm_secondary_master_config_overrides( - session_master_config_overrides, session_mm_secondary_root_dir +@pytest.fixture(scope="package") +def salt_mm_sub_master( + request, salt_factories, salt_mm_master, salt_mm_sub_master_config ): - overrides = session_master_config_overrides.copy() - pytest_stop_sending_events_file = session_mm_secondary_root_dir.join( - "pytest_mm_stop_sending_events_file" - ).strpath - with salt.utils.files.fopen(pytest_stop_sending_events_file, "w") as wfh: - wfh.write("") - overrides["pytest_stop_sending_events_file"] = pytest_stop_sending_events_file - return overrides - - -@pytest.fixture(scope="session") -def session_mm_secondary_master_config( - session_mm_secondary_root_dir, - session_mm_secondary_master_default_options, - session_mm_secondary_master_config_file, - session_mm_secondary_master_publish_port, - session_mm_secondary_master_return_port, - session_mm_secondary_master_engine_port, - session_mm_secondary_master_config_overrides, - session_mm_secondary_master_id, - session_base_env_state_tree_root_dir, - session_prod_env_state_tree_root_dir, - session_base_env_pillar_tree_root_dir, - session_prod_env_pillar_tree_root_dir, - running_username, - log_server_port, - log_server_level, - engines_dir, - log_handlers_dir, - session_mm_secondary_master_log_prefix, - session_mm_secondary_master_tcp_master_pub_port, - session_mm_secondary_master_tcp_master_pull_port, - session_mm_secondary_master_tcp_master_publish_pull, - session_mm_secondary_master_tcp_master_workers, -): - """ - This fixture will return the salt master configuration options after being - overridden with any options passed from ``session_master_config_overrides`` - """ - return apply_master_config( - session_mm_secondary_master_default_options, - session_mm_secondary_root_dir, - session_mm_secondary_master_config_file, - session_mm_secondary_master_publish_port, - session_mm_secondary_master_return_port, - session_mm_secondary_master_engine_port, - session_mm_secondary_master_config_overrides, - session_mm_secondary_master_id, - [session_base_env_state_tree_root_dir.strpath], - [session_prod_env_state_tree_root_dir.strpath], - [session_base_env_pillar_tree_root_dir.strpath], - [session_prod_env_pillar_tree_root_dir.strpath], - running_username, - log_server_port, - log_server_level, - engines_dir, - log_handlers_dir, - session_mm_secondary_master_log_prefix, - session_mm_secondary_master_tcp_master_pub_port, - session_mm_secondary_master_tcp_master_pull_port, - session_mm_secondary_master_tcp_master_publish_pull, - session_mm_secondary_master_tcp_master_workers, - ) - - -@pytest.fixture(scope="session") -def session_mm_secondary_salt_master( - request, - session_mm_secondary_conf_dir, - session_mm_secondary_master_id, - session_mm_secondary_master_config, - log_server, # pylint: disable=unused-argument - session_mm_secondary_master_log_prefix, - cli_master_script_name, - _cli_bin_dir, - _salt_fail_hard, - session_mm_master_config, - session_mm_salt_master, -): - """ - Returns a running salt-master - """ # 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(session_mm_master_config["pki_dir"], keyfile), - os.path.join(session_mm_secondary_master_config["pki_dir"], keyfile), + os.path.join(salt_mm_master.config["pki_dir"], keyfile), + os.path.join(salt_mm_sub_master_config["pki_dir"], keyfile), ) - return start_daemon( - request, - daemon_name="salt-master", - daemon_id=session_mm_secondary_master_id, - daemon_log_prefix=session_mm_secondary_master_log_prefix, - daemon_cli_script_name=cli_master_script_name, - daemon_config=session_mm_secondary_master_config, - daemon_config_dir=session_mm_secondary_conf_dir, - daemon_class=SaltMaster, - bin_dir_path=_cli_bin_dir, - fail_hard=_salt_fail_hard, - event_listener_config_dir=session_mm_secondary_conf_dir, - start_timeout=60, + 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): + return salt_factories.spawn_minion( + request, "mm-minion", master_id=salt_mm_master.config["id"] ) -# <---- Sub Master Fixtures ------------------------------------------------------------------------------------------ - -# ----- Sub Minion Fixtures ---------------------------------------------------------------------------------------------> -@pytest.fixture(scope="session") -def session_mm_secondary_minion_id(): - """ - Returns the session scoped minion id - """ - return "mm-sub-minion" - - -@pytest.fixture(scope="session") -def session_mm_secondary_minion_tcp_pub_port(): - """ - Returns an unused localhost port - """ - return get_unused_localhost_port() - - -@pytest.fixture(scope="session") -def session_mm_secondary_minion_tcp_pull_port(): - """ - Returns an unused localhost port - """ - return get_unused_localhost_port() - - -@pytest.fixture(scope="session") -def session_mm_secondary_minion_log_prefix(session_mm_secondary_minion_id): - return "salt-minion/{}".format(session_mm_secondary_minion_id) - - -@pytest.fixture(scope="session") -def session_mm_secondary_minion_config_file(session_mm_secondary_conf_dir): - """ - Returns the path to the salt minion configuration file - """ - return session_mm_secondary_conf_dir.join("minion").realpath().strpath - - -@pytest.fixture(scope="session") -def session_mm_secondary_minion_default_options( - session_secondary_minion_default_options, -): - opts = session_secondary_minion_default_options.copy() - with salt.utils.files.fopen( - os.path.join(RUNTIME_VARS.CONF_DIR, "mm_sub_minion") - ) as rfh: - opts.update(yaml.deserialize(rfh.read())) - return opts - - -@pytest.fixture(scope="session") -def session_mm_secondary_minion_config_overrides( - session_secondary_minion_config_overrides, - session_mm_master_return_port, - session_mm_secondary_master_return_port, -): - if session_secondary_minion_config_overrides: - opts = session_secondary_minion_config_overrides.copy() - else: - opts = {} - opts["master_port"] = None - opts["master"] = [ - "localhost:{}".format(session_mm_master_return_port), - "localhost:{}".format(session_mm_secondary_master_return_port), - ] - return opts - - -@pytest.fixture(scope="session") -def session_mm_secondary_minion_config( - session_mm_secondary_root_dir, - session_mm_secondary_minion_config_file, - session_mm_secondary_master_return_port, - session_mm_secondary_minion_default_options, - session_mm_secondary_minion_config_overrides, - session_mm_secondary_minion_id, - running_username, - log_server_port, - log_server_level, - log_handlers_dir, - session_mm_secondary_minion_log_prefix, - session_mm_secondary_minion_tcp_pub_port, - session_mm_secondary_minion_tcp_pull_port, -): - """ - This fixture will return the session salt minion configuration options after being - overridden with any options passed from ``session_secondary_minion_config_overrides`` - """ - return apply_minion_config( - session_mm_secondary_minion_default_options, - session_mm_secondary_root_dir, - session_mm_secondary_minion_config_file, - session_mm_secondary_master_return_port, - session_mm_secondary_minion_config_overrides, - session_mm_secondary_minion_id, - running_username, - log_server_port, - log_server_level, - log_handlers_dir, - session_mm_secondary_minion_log_prefix, - session_mm_secondary_minion_tcp_pub_port, - session_mm_secondary_minion_tcp_pull_port, +@pytest.fixture(scope="package") +def salt_mm_sub_minion(request, salt_factories, salt_mm_master, salt_mm_sub_master): + return salt_factories.spawn_minion( + request, "mm-sub-minion", master_id=salt_mm_sub_master.config["id"] ) -@pytest.fixture(scope="session") -def session_mm_secondary_salt_minion( - request, - session_mm_salt_master, - session_mm_secondary_salt_master, - session_mm_secondary_minion_id, - session_mm_secondary_minion_config, - session_mm_secondary_minion_log_prefix, - cli_minion_script_name, - log_server, - _cli_bin_dir, - _salt_fail_hard, - session_mm_secondary_conf_dir, -): - """ - Returns a running salt-minion - """ - return start_daemon( - request, - daemon_name="salt-minion", - daemon_id=session_mm_secondary_minion_id, - daemon_log_prefix=session_mm_secondary_minion_log_prefix, - daemon_cli_script_name=cli_minion_script_name, - daemon_config=session_mm_secondary_minion_config, - daemon_config_dir=session_mm_secondary_conf_dir, - daemon_class=SaltMinion, - bin_dir_path=_cli_bin_dir, - fail_hard=_salt_fail_hard, - event_listener_config_dir=session_mm_secondary_conf_dir, - start_timeout=60, - ) - - -# <---- Minion Fixtures ---------------------------------------------------------------------------------------------- - -# ----- Minion Fixtures -----------------------------------------------------------------------------------------> -@pytest.fixture(scope="session") -def session_mm_minion_id(): - """ - Returns the session scoped minion id - """ - return "mm-minion" - - -@pytest.fixture(scope="session") -def session_mm_minion_tcp_pub_port(): - """ - Returns an unused localhost port - """ - return get_unused_localhost_port() - - -@pytest.fixture(scope="session") -def session_mm_minion_tcp_pull_port(): - """ - Returns an unused localhost port - """ - return get_unused_localhost_port() - - -@pytest.fixture(scope="session") -def session_mm_minion_log_prefix(session_mm_minion_id): - return "salt-minion/{}".format(session_mm_minion_id) - - -@pytest.fixture(scope="session") -def session_mm_minion_config_file(session_mm_conf_dir): - """ - Returns the path to the salt minion configuration file - """ - return session_mm_conf_dir.join("minion").realpath().strpath - - -@pytest.fixture(scope="session") -def session_mm_minion_default_options(session_minion_default_options): - opts = session_minion_default_options.copy() - with salt.utils.files.fopen( - os.path.join(RUNTIME_VARS.CONF_DIR, "mm_sub_minion") - ) as rfh: - opts.update(yaml.deserialize(rfh.read())) - return opts - - -@pytest.fixture(scope="session") -def session_mm_minion_config_overrides( - session_minion_config_overrides, - session_mm_master_return_port, - session_mm_secondary_master_return_port, -): - if session_minion_config_overrides: - opts = session_minion_config_overrides.copy() - else: - opts = {} - opts["master_port"] = None - opts["master"] = [ - "localhost:{}".format(session_mm_master_return_port), - "localhost:{}".format(session_mm_secondary_master_return_port), - ] - return opts - - -@pytest.fixture(scope="session") -def session_mm_minion_config( - session_mm_root_dir, - session_mm_minion_config_file, - session_mm_master_return_port, - session_mm_minion_default_options, - session_mm_minion_config_overrides, - session_mm_minion_id, - running_username, - log_server_port, - log_server_level, - log_handlers_dir, - session_mm_minion_log_prefix, - session_mm_minion_tcp_pub_port, - session_mm_minion_tcp_pull_port, -): - """ - This fixture will return the session salt minion configuration options after being - overridden with any options passed from ``session_minion_config_overrides`` - """ - return apply_minion_config( - session_mm_minion_default_options, - session_mm_root_dir, - session_mm_minion_config_file, - session_mm_master_return_port, - session_mm_minion_config_overrides, - session_mm_minion_id, - running_username, - log_server_port, - log_server_level, - log_handlers_dir, - session_mm_minion_log_prefix, - session_mm_minion_tcp_pub_port, - session_mm_minion_tcp_pull_port, - ) - - -@pytest.fixture(scope="session") -def session_mm_salt_minion( - request, - session_mm_salt_master, - session_mm_secondary_salt_master, - session_mm_minion_id, - session_mm_minion_config, - session_mm_minion_log_prefix, - cli_minion_script_name, - log_server, - _cli_bin_dir, - _salt_fail_hard, - session_mm_conf_dir, -): - """ - Returns a running salt-minion - """ - return start_daemon( - request, - daemon_name="salt-minion", - daemon_id=session_mm_minion_id, - daemon_log_prefix=session_mm_minion_log_prefix, - daemon_cli_script_name=cli_minion_script_name, - daemon_config=session_mm_minion_config, - daemon_config_dir=session_mm_conf_dir, - daemon_class=SaltMinion, - bin_dir_path=_cli_bin_dir, - fail_hard=_salt_fail_hard, - event_listener_config_dir=session_mm_conf_dir, - start_timeout=60, - ) - - -# <---- Sub Minion Fixtures ------------------------------------------------------------------------------------------ - - -@pytest.fixture(scope="session") -def default_session_daemons( - request, - log_server, - session_mm_salt_master, - session_mm_secondary_salt_master, - session_mm_salt_minion, - session_mm_secondary_salt_minion, -): - - request.session.stats_processes.update( - OrderedDict( - ( - ("Salt MM Master", psutil.Process(session_mm_salt_master.pid)), - ("Salt MM Minion", psutil.Process(session_mm_salt_minion.pid)), - ( - "Salt MM Sub Master", - psutil.Process(session_mm_secondary_salt_master.pid), - ), - ( - "Salt MM Sub Minion", - psutil.Process(session_mm_secondary_salt_minion.pid), - ), - ) - ).items() - ) - - # Run tests - yield - - # Stop daemons now(they would be stopped at the end of the test run session - for daemon in ( - session_mm_secondary_salt_minion, - session_mm_secondary_salt_master, - session_mm_salt_minion, - session_mm_salt_master, - ): - try: - daemon.terminate() - except Exception as exc: # pylint: disable=broad-except - log.warning("Failed to terminate daemon: %s", daemon.__class__.__name__) - - -@pytest.fixture(scope="session", autouse=True) -def mm_bridge_pytest_and_runtests( +@pytest.fixture(scope="package", autouse=True) +def bridge_pytest_and_runtests( reap_stray_processes, - session_mm_conf_dir, - session_mm_secondary_conf_dir, - session_base_env_pillar_tree_root_dir, - session_base_env_state_tree_root_dir, - session_prod_env_state_tree_root_dir, - session_mm_master_config, - session_mm_minion_config, - session_mm_secondary_master_config, - session_mm_secondary_minion_config, - default_session_daemons, + 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_mm_master, + salt_mm_minion, + salt_mm_sub_master, + salt_mm_sub_minion, ): + # Make sure unittest2 uses the pytest generated configuration + RUNTIME_VARS.RUNTIME_CONFIGS["mm_master"] = freeze(salt_mm_master.config) + RUNTIME_VARS.RUNTIME_CONFIGS["mm_minion"] = freeze(salt_mm_minion.config) + RUNTIME_VARS.RUNTIME_CONFIGS["mm_sub_master"] = freeze(salt_mm_sub_master.config) + RUNTIME_VARS.RUNTIME_CONFIGS["mm_sub_minion"] = freeze(salt_mm_sub_minion.config) # Make sure unittest2 classes know their paths - RUNTIME_VARS.TMP_MM_CONF_DIR = session_mm_conf_dir.realpath().strpath - RUNTIME_VARS.TMP_MM_SUB_CONF_DIR = session_mm_secondary_conf_dir.realpath().strpath - RUNTIME_VARS.TMP_SUB_MINION_CONF_DIR = ( - session_mm_secondary_conf_dir.realpath().strpath + RUNTIME_VARS.TMP_MM_CONF_DIR = os.path.dirname(salt_mm_master.config["conf_file"]) + RUNTIME_VARS.TMP_MM_MINION_CONF_DIR = os.path.dirname( + salt_mm_minion.config["conf_file"] ) - RUNTIME_VARS.TMP_PILLAR_TREE = ( - session_base_env_pillar_tree_root_dir.realpath().strpath + RUNTIME_VARS.TMP_MM_SUB_CONF_DIR = os.path.dirname( + salt_mm_sub_master.config["conf_file"] ) - RUNTIME_VARS.TMP_STATE_TREE = ( - session_base_env_state_tree_root_dir.realpath().strpath - ) - RUNTIME_VARS.TMP_PRODENV_STATE_TREE = ( - session_prod_env_state_tree_root_dir.realpath().strpath - ) - - # Make sure unittest2 uses the pytest generated configuration - RUNTIME_VARS.RUNTIME_CONFIGS["mm_master"] = freeze(session_mm_master_config) - RUNTIME_VARS.RUNTIME_CONFIGS["mm_minion"] = freeze(session_mm_minion_config) - RUNTIME_VARS.RUNTIME_CONFIGS["mm_sub_master"] = freeze( - session_mm_secondary_master_config - ) - RUNTIME_VARS.RUNTIME_CONFIGS["mm_sub_minion"] = freeze( - session_mm_secondary_minion_config + RUNTIME_VARS.TMP_MM_SUB_MINION_CONF_DIR = os.path.dirname( + salt_mm_sub_minion.config["conf_file"] ) diff --git a/tests/support/cli_scripts.py b/tests/support/cli_scripts.py index fcab3d9e33f..0a118ed82b0 100644 --- a/tests/support/cli_scripts.py +++ b/tests/support/cli_scripts.py @@ -6,15 +6,13 @@ Code to generate Salt CLI scripts for test runs """ -# Import Python Libs from __future__ import absolute_import, unicode_literals import logging import os import sys -# Import Pytest Salt libs -from pytestsalt.utils import cli_scripts +from saltfactories.utils import cli_scripts log = logging.getLogger(__name__) @@ -38,6 +36,7 @@ def get_script_path(bin_dir, script_name): 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, ) log.info("Returning script path %r", script_path) diff --git a/tests/support/gitfs.py b/tests/support/gitfs.py index ad638bda59f..0df8863770c 100644 --- a/tests/support/gitfs.py +++ b/tests/support/gitfs.py @@ -3,7 +3,6 @@ Base classes for gitfs/git_pillar integration tests """ -# Import python libs from __future__ import absolute_import, print_function, unicode_literals import copy @@ -19,20 +18,17 @@ import textwrap import threading import time -# Import 3rd-party libs import psutil import salt.ext.six as six - -# Import Salt libs import salt.utils.files import salt.utils.path import salt.utils.yaml -from pytestsalt.utils import SaltDaemonScriptBase as _SaltDaemonScriptBase -from pytestsalt.utils import terminate_process from salt.fileserver import gitfs from salt.pillar import git_pillar - -# Import Salt Testing libs +from saltfactories.utils.processes.helpers import terminate_process +from saltfactories.utils.processes.salts import ( + SaltDaemonScriptBase as _SaltDaemonScriptBase, +) from tests.support.case import ModuleCase from tests.support.helpers import ( get_unused_localhost_port, diff --git a/tests/support/helpers.py b/tests/support/helpers.py index 1b2e33961c0..76f6d5325ec 100644 --- a/tests/support/helpers.py +++ b/tests/support/helpers.py @@ -40,9 +40,9 @@ import salt.utils.files import salt.utils.platform import salt.utils.stringutils import salt.utils.versions -from pytestsalt.utils import get_unused_localhost_port from salt.ext import six from salt.ext.six.moves import builtins, range +from saltfactories.utils.ports import get_unused_localhost_port from tests.support.mock import patch from tests.support.runtests import RUNTIME_VARS from tests.support.sminion import create_sminion diff --git a/tests/support/mixins.py b/tests/support/mixins.py index 72b6736f507..a184b93b1e9 100644 --- a/tests/support/mixins.py +++ b/tests/support/mixins.py @@ -200,6 +200,10 @@ class AdaptedConfigurationTestCaseMixin(object): @staticmethod def get_config_file_path(filename): + if filename == "master": + return os.path.join(RUNTIME_VARS.TMP_CONF_DIR, filename) + if filename == "minion": + return os.path.join(RUNTIME_VARS.TMP_MINION_CONF_DIR, filename) if filename == "syndic_master": return os.path.join(RUNTIME_VARS.TMP_SYNDIC_MASTER_CONF_DIR, "master") if filename == "syndic": @@ -211,9 +215,9 @@ class AdaptedConfigurationTestCaseMixin(object): if filename == "mm_sub_master": return os.path.join(RUNTIME_VARS.TMP_MM_SUB_CONF_DIR, "master") if filename == "mm_minion": - return os.path.join(RUNTIME_VARS.TMP_MM_CONF_DIR, "minion") + return os.path.join(RUNTIME_VARS.TMP_MM_MINION_CONF_DIR, "minion") if filename == "mm_sub_minion": - return os.path.join(RUNTIME_VARS.TMP_MM_SUB_CONF_DIR, "minion") + return os.path.join(RUNTIME_VARS.TMP_MM_SUB_MINION_CONF_DIR, "minion") return os.path.join(RUNTIME_VARS.TMP_CONF_DIR, filename) @property diff --git a/tests/support/processes.py b/tests/support/processes.py index 92e6a4b84e2..4f264862a46 100644 --- a/tests/support/processes.py +++ b/tests/support/processes.py @@ -10,30 +10,39 @@ Process handling utilities """ -# Import python libs from __future__ import absolute_import import logging -from pytestsalt.fixtures.daemons import Salt as PytestSalt -from pytestsalt.fixtures.daemons import SaltCall as PytestSaltCall -from pytestsalt.fixtures.daemons import SaltKey as PytestSaltKey -from pytestsalt.fixtures.daemons import SaltMaster as PytestSaltMaster -from pytestsalt.fixtures.daemons import SaltMinion as PytestSaltMinion -from pytestsalt.fixtures.daemons import SaltProxy as PytestSaltProxy -from pytestsalt.fixtures.daemons import SaltRun as PytestSaltRun -from pytestsalt.fixtures.daemons import SaltSyndic as PytestSaltSyndic - -# Import pytest-salt libs -from pytestsalt.utils import ( # pylint: disable=unused-import +from saltfactories.utils.processes.helpers import ( # pylint: disable=unused-import collect_child_processes, terminate_process, terminate_process_list, ) - -# Import tests support libs from tests.support.cli_scripts import ScriptPathMixin +try: + from pytestsalt.fixtures.daemons import Salt as PytestSalt + from pytestsalt.fixtures.daemons import SaltCall as PytestSaltCall + from pytestsalt.fixtures.daemons import SaltKey as PytestSaltKey + from pytestsalt.fixtures.daemons import SaltMaster as PytestSaltMaster + from pytestsalt.fixtures.daemons import SaltMinion as PytestSaltMinion + from pytestsalt.fixtures.daemons import SaltProxy as PytestSaltProxy + from pytestsalt.fixtures.daemons import SaltRun as PytestSaltRun + from pytestsalt.fixtures.daemons import SaltSyndic as PytestSaltSyndic +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 + log = logging.getLogger(__name__) diff --git a/tests/support/runtests.py b/tests/support/runtests.py index 46b1da5bf24..8150815010d 100644 --- a/tests/support/runtests.py +++ b/tests/support/runtests.py @@ -45,7 +45,6 @@ .. _`pytest`: http://pytest.org .. _`nose`: https://nose.readthedocs.org """ - from __future__ import absolute_import, print_function import logging @@ -62,7 +61,6 @@ try: except ImportError: import salt.utils.win_functions - log = logging.getLogger(__name__)