20 Commits 8096e08964 ... 578f1ba1f6

Autor SHA1 Mensagem Data
  Barney Sowood 578f1ba1f6 Merge pull request #227 from barneysowood/fix-test-suite 1 ano atrás
  Barney Sowood b376591e4b Merge pull request #226 from barneysowood/tests-github-actions 1 ano atrás
  Barney Sowood 369b5a1fd6 Use importlib-metadata<5.0.0 on older python/salt 1 ano atrás
  Barney Sowood 7588e211ee Enable all netapi clients 1 ano atrás
  Barney Sowood d51f7250e9 Fix jinja 3.1 issue 1 ano atrás
  Barney Sowood 1bbe77a0cb Update vanilla integration tests for new pytest 1 ano atrás
  Barney Sowood 96484be110 Update client integration tests 1 ano atrás
  Barney Sowood 952bf25be3 Update fixtures to use pytest-salt-factories 1 ano atrás
  Barney Sowood 53cc63f1e5 Update tox.ini to use new pytest options 1 ano atrás
  Barney Sowood e59dd58f47 Update testing requirements 1 ano atrás
  Barney Sowood ec53778ad0 Drop testing of python 3.5 and 3.6 1 ano atrás
  Barney Sowood e4afa37895 Removed scheduled run of flake8 1 ano atrás
  Barney Sowood 1c1aca7ef6 Update requirements to match current salt 1 ano atrás
  Barney Sowood acce4f6c5b Update pytest-salt url 1 ano atrás
  Barney Sowood 6f897d95e9 Run tox without -vv 1 ano atrás
  Barney Sowood d3c6c18df9 Add exclusion for master and py3.5/3.6 1 ano atrás
  Barney Sowood b28888cc7a Add GH Actions workflow for flake8 1 ano atrás
  Barney Sowood 29b0313df0 Add GH Actions workflow 1 ano atrás
  Barney Sowood e7d7bd9b51 Update coverage version to current 1 ano atrás
  Barney Sowood a83fc07432 Update python and salt versions in tox.ini 1 ano atrás

+ 21 - 0
.github/workflows/flake8.yaml

@@ -0,0 +1,21 @@
+name: flake8 lint
+on:
+  push:
+  pull_request:
+
+jobs:
+  flake8-lint:
+    runs-on: ubuntu-20.04
+    name: flake8 lint
+    steps:
+      - name: Setup python for flake8
+        uses: actions/setup-python@v4
+        with:
+          python-version: "3.8"
+      - uses: actions/checkout@v3
+      - name: Install tox
+        run: python -m pip install tox
+      - name: Setup flake8
+        run: tox --notest -e flake8
+      - name: Run flake8
+        run: tox -e flake8

+ 42 - 0
.github/workflows/test.yaml

@@ -0,0 +1,42 @@
+name: test
+on:
+  push:
+  pull_request:
+  schedule:
+    - cron: "0 8 * * *"
+
+jobs:
+  test:
+    name: test ${{ matrix.py }} - ${{ matrix.netapi }} - ${{ matrix.salt }}
+    runs-on: ubuntu-20.04
+    strategy:
+      fail-fast: false
+      matrix:
+        py:
+          - "3.7"
+          - "3.8"
+        netapi:
+          - "cherrypy"
+          - "tornado"
+        salt:
+          - "v3004.2"
+          - "v3005.1"
+          - "master"
+    steps:
+      - name: Setup python for test ${{ matrix.py }}
+        uses: actions/setup-python@v4
+        with:
+          python-version: ${{ matrix.py }}
+      - uses: actions/checkout@v3
+      - name: Install setuptools_scm
+        run: python -m pip install setuptools_scm
+      - name: Install tox
+        run: python -m pip install tox
+      - name: Install dependencies
+        run: sudo apt update && sudo apt install -y libc6-dev libffi-dev gcc git openssh-server libzmq3-dev
+        env:
+          DEBIAN_FRONTEND: noninteractive
+      - name: Setup tests
+        run: tox --notest -e py${{ matrix.py }}-${{ matrix.netapi }}-${{ matrix.salt }}
+      - name: Run tests
+        run: tox -e py${{ matrix.py }}-${{ matrix.netapi }}-${{ matrix.salt }}

+ 108 - 162
tests/conftest.py

@@ -2,7 +2,6 @@
 from __future__ import absolute_import, unicode_literals, print_function
 
 # Import python libraries
-import distutils.spawn
 import logging
 import os.path
 import shutil
@@ -11,48 +10,86 @@ import tempfile
 import textwrap
 
 # Import Salt Libraries
-import salt.client
-import salt.config
 import salt.utils.yaml as yaml
 
 # Import pytest libraries
 import pytest
-from pytestsalt.utils import SaltDaemonScriptBase, start_daemon, get_unused_localhost_port
+from pytestskipmarkers.utils import ports
+from saltfactories.utils import random_string, running_username
 
 # Import Pepper libraries
 import pepper
 import pepper.script
 
-DEFAULT_MASTER_ID = 'pytest-salt-master'
-DEFAULT_MINION_ID = 'pytest-salt-minion'
 
 log = logging.getLogger(__name__)
 
 
 @pytest.fixture(scope='session')
-def install_sshd_server():
-    if distutils.spawn.find_executable('sshd'):
-        return
-    __opts__ = salt.config.minion_config('tests/minion.conf')
-    __opts__['file_client'] = 'local'
-    caller = salt.client.Caller(mopts=__opts__)
-    caller.cmd('pkg.install', 'openssh-server')
+def sshd_config_dir(salt_factories):
+    config_dir = salt_factories.get_root_dir_for_daemon("sshd")
+    yield config_dir
+    shutil.rmtree(str(config_dir), ignore_errors=True)
 
 
-class SaltApi(SaltDaemonScriptBase):
-    '''
-    Class which runs the salt-api daemon
-    '''
-
-    def get_script_args(self):
-        return ['-l', 'quiet']
+@pytest.fixture(scope='session')
+def session_sshd_server(salt_factories, sshd_config_dir, session_master):
+    sshd_config_dict = {
+        "Protocol": "2",
+        # Turn strict modes off so that we can operate in /tmp
+        "StrictModes": "no",
+        # Logging
+        "SyslogFacility": "AUTH",
+        "LogLevel": "INFO",
+        # Authentication:
+        "LoginGraceTime": "120",
+        "PermitRootLogin": "without-password",
+        "PubkeyAuthentication": "yes",
+        # Don't read the user's ~/.rhosts and ~/.shosts files
+        "IgnoreRhosts": "yes",
+        "HostbasedAuthentication": "no",
+        # To enable empty passwords, change to yes (NOT RECOMMENDED)
+        "PermitEmptyPasswords": "no",
+        # Change to yes to enable challenge-response passwords (beware issues with
+        # some PAM modules and threads)
+        "ChallengeResponseAuthentication": "no",
+        # Change to no to disable tunnelled clear text passwords
+        "PasswordAuthentication": "no",
+        "X11Forwarding": "no",
+        "X11DisplayOffset": "10",
+        "PrintMotd": "no",
+        "PrintLastLog": "yes",
+        "TCPKeepAlive": "yes",
+        "AcceptEnv": "LANG LC_*",
+        "UsePAM": "yes",
+    }
+    factory = salt_factories.get_sshd_daemon(
+        sshd_config_dict=sshd_config_dict,
+        config_dir=sshd_config_dir,
+    )
+    with factory.started():
+        yield factory
 
-    def get_check_ports(self):
-        if 'rest_cherrypy' in self.config:
-            return [self.config['rest_cherrypy']['port']]
 
-        if 'rest_tornado' in self.config:
-            return [self.config['rest_tornado']['port']]
+@pytest.fixture(scope='session')
+def session_ssh_roster_config(session_sshd_server, session_master):
+    roster_contents = """
+    localhost:
+      host: 127.0.0.1
+      port: {}
+      user: {}
+      priv: {}
+      mine_functions:
+        test.arg: ['itworked']
+    """.format(
+        session_sshd_server.listen_port,
+        running_username(),
+        session_sshd_server.client_key
+    )
+    with pytest.helpers.temp_file(
+        "roster", roster_contents, session_master.config_dir
+    ) as roster_file:
+        yield roster_file
 
 
 @pytest.fixture(scope='session')
@@ -60,7 +97,7 @@ def salt_api_port():
     '''
     Returns an unused localhost port for the api port
     '''
-    return get_unused_localhost_port()
+    return ports.get_unused_localhost_port()
 
 
 @pytest.fixture(scope='session')
@@ -121,7 +158,7 @@ def output_file():
 
 
 @pytest.fixture(params=['/run', '/login'])
-def pepper_cli(request, session_salt_api, salt_api_port, output_file, install_sshd_server, session_sshd_server):
+def pepper_cli(request, session_salt_api, salt_api_port, output_file, session_sshd_server):
     '''
     Wrapper to invoke Pepper with common params and inside an empty env
     '''
@@ -154,6 +191,20 @@ def pepper_cli(request, session_salt_api, salt_api_port, output_file, install_ss
     return _run_pepper_cli
 
 
+@pytest.fixture(scope='session')
+def session_master_factory(request, salt_factories, session_master_config_overrides):
+    return salt_factories.salt_master_daemon(
+        random_string("master-"),
+        overrides=session_master_config_overrides
+    )
+
+
+@pytest.fixture(scope='session')
+def session_master(session_master_factory):
+    with session_master_factory.started():
+        yield session_master_factory
+
+
 @pytest.fixture(scope='session')
 def session_master_config_overrides(request, salt_api_port, salt_api_backend):
     return {
@@ -175,69 +226,40 @@ def session_master_config_overrides(request, salt_api_port, salt_api_backend):
         'token_expire': 94670856,
         'ignore_host_keys': True,
         'ssh_wipe': True,
+        'netapi_enable_clients': [
+            'local',
+            'local_async',
+            'local_subset',
+            'ssh',
+            'runner',
+            'runner_async',
+            'wheel',
+            'wheel_async',
+            'run'
+        ]
     }
 
 
 @pytest.fixture(scope='session')
-def session_api_log_prefix(master_id):
-    return 'salt-api/{0}'.format(master_id)
+def session_minion_factory(session_master_factory):
+    """Return a factory for a randomly named minion connected to master."""
+    minion_factory = session_master_factory.salt_minion_daemon(random_string("minion-"))
+    minion_factory.after_terminate(
+        pytest.helpers.remove_stale_minion_key, session_master_factory, minion_factory.id
+    )
+    return minion_factory
 
 
 @pytest.fixture(scope='session')
-def cli_api_script_name():
-    '''
-    Return the CLI script basename
-    '''
-    return 'salt-api'
-
-
-@pytest.yield_fixture(scope='session')
-def session_salt_api_before_start():
-    '''
-    This fixture should be overridden if you need to do
-    some preparation and clean up work before starting
-    the salt-api and after ending it.
-    '''
-    # Prep routines go here
-
-    # Start the salt-api
-    yield
-
-    # Clean routines go here
-
-
-@pytest.yield_fixture(scope='session')
-def session_salt_api_after_start(session_salt_api):
-    '''
-    This fixture should be overridden if you need to do
-    some preparation and clean up work after starting
-    the salt-api and before ending it.
-    '''
-    # Prep routines go here
-
-    # Resume test execution
-    yield
-
-    # Clean routines go here
+def session_minion(session_master, session_minion_factory):  # noqa
+    assert session_master.is_running()
+    with session_minion_factory.started():
+        yield session_minion_factory
 
 
 @pytest.fixture(scope='session')
-def _salt_fail_hard(request, salt_fail_hard):
-    '''
-    Return the salt fail hard value
-    '''
-    fail_hard = request.config.getoption('salt_fail_hard')
-    if fail_hard is not None:
-        # We were passed --salt-fail-hard as a CLI option
-        return fail_hard
-
-    # The salt fail hard was not passed as a CLI option
-    fail_hard = request.config.getini('salt_fail_hard')
-    if fail_hard != []:
-        # We were passed salt_fail_hard as a INI option
-        return fail_hard
-
-    return salt_fail_hard
+def session_minion_id(session_minion):
+    return session_minion.id
 
 
 @pytest.fixture(scope='session')
@@ -257,91 +279,15 @@ def salt_api_backend(request):
 
 
 @pytest.fixture(scope='session')
-def master_id(salt_master_id_counter):
-    '''
-    Returns the master id
-    '''
-    return DEFAULT_MASTER_ID + '-{0}'.format(salt_master_id_counter())
+def session_salt_api_factory(session_master_factory):
+    return session_master_factory.salt_api_daemon()
 
 
 @pytest.fixture(scope='session')
-def minion_id(salt_minion_id_counter):
-    '''
-    Returns the minion id
-    '''
-    return DEFAULT_MINION_ID + '-{0}'.format(salt_minion_id_counter())
-
-
-@pytest.fixture(scope='session')
-def session_salt_api(request,
-                     session_salt_minion,
-                     session_master_id,
-                     session_master_config,
-                     session_salt_api_before_start,  # pylint: disable=unused-argument
-                     session_api_log_prefix,
-                     cli_api_script_name,
-                     log_server,
-                     _cli_bin_dir,
-                     session_conf_dir):
-    '''
-    Returns a running salt-api
-    '''
-    return start_daemon(request,
-                        daemon_name='salt-api',
-                        daemon_id=session_master_id,
-                        daemon_log_prefix=session_api_log_prefix,
-                        daemon_cli_script_name=cli_api_script_name,
-                        daemon_config=session_master_config,
-                        daemon_config_dir=session_conf_dir,
-                        daemon_class=SaltApi,
-                        bin_dir_path=_cli_bin_dir,
-                        start_timeout=30)
-
-
-@pytest.fixture(scope='session')
-def session_sshd_config_lines(session_sshd_port):
-    '''
-    Return a list of lines which will make the sshd_config file
-    '''
-    return [
-        'Port {0}'.format(session_sshd_port),
-        'ListenAddress 127.0.0.1',
-        'Protocol 2',
-        'UsePrivilegeSeparation yes',
-        '# Turn strict modes off so that we can operate in /tmp',
-        'StrictModes no',
-        '# Logging',
-        'SyslogFacility AUTH',
-        'LogLevel INFO',
-        '# Authentication:',
-        'LoginGraceTime 120',
-        'PermitRootLogin without-password',
-        'StrictModes yes',
-        'PubkeyAuthentication yes',
-        '#AuthorizedKeysFile	%h/.ssh/authorized_keys',
-        '#AuthorizedKeysFile	key_test.pub',
-        '# Don\'t read the user\'s ~/.rhosts and ~/.shosts files',
-        'IgnoreRhosts yes',
-        '# similar for protocol version 2',
-        'HostbasedAuthentication no',
-        '#IgnoreUserKnownHosts yes',
-        '# To enable empty passwords, change to yes (NOT RECOMMENDED)',
-        'PermitEmptyPasswords no',
-        '# Change to yes to enable challenge-response passwords (beware issues with',
-        '# some PAM modules and threads)',
-        'ChallengeResponseAuthentication no',
-        '# Change to no to disable tunnelled clear text passwords',
-        'PasswordAuthentication no',
-        'X11Forwarding no',
-        'X11DisplayOffset 10',
-        'PrintMotd no',
-        'PrintLastLog yes',
-        'TCPKeepAlive yes',
-        '#UseLogin no',
-        'AcceptEnv LANG LC_*',
-        'Subsystem sftp /usr/lib/openssh/sftp-server',
-        '#UsePAM yes',
-    ]
+def session_salt_api(session_master, session_salt_api_factory):
+    assert session_master.is_running()
+    with session_salt_api_factory.started():
+        yield session_salt_api_factory
 
 
 def pytest_addoption(parser):

+ 13 - 13
tests/integration/test_clients.py

@@ -1,8 +1,7 @@
 # -*- coding: utf-8 -*-
 import json
-import os
+import pathlib
 import pytest
-import sys
 
 
 def test_local_bad_opts(pepper_cli):
@@ -17,7 +16,7 @@ def test_local_bad_opts(pepper_cli):
 
 
 @pytest.mark.xfail(
-    pytest.config.getoption("--salt-api-backend") == "rest_tornado",
+    'config.getoption("--salt-api-backend") == "rest_tornado"',
     reason="timeout kwarg isnt popped until next version of salt/tornado"
 )
 def test_runner_client(pepper_cli):
@@ -30,34 +29,35 @@ def test_runner_client(pepper_cli):
 
 
 @pytest.mark.xfail(
-    pytest.config.getoption("--salt-api-backend") == "rest_tornado",
+    'config.getoption("--salt-api-backend") == "rest_tornado"',
     reason="wheelClient unimplemented for now on tornado",
 )
-def test_wheel_client_arg(pepper_cli, session_minion_id):
+def test_wheel_client_arg(pepper_cli, session_minion):
     ret = pepper_cli('--client=wheel', 'minions.connected')
-    assert ret == ['pytest-session-salt-minion-0']
+    assert ret == [session_minion.id]
 
 
 @pytest.mark.xfail(
-    pytest.config.getoption("--salt-api-backend") == "rest_tornado",
+    'config.getoption("--salt-api-backend") == "rest_tornado"',
     reason="wheelClient unimplemented for now on tornado",
 )
-def test_wheel_client_kwargs(pepper_cli, session_master_config_file):
+def test_wheel_client_kwargs(pepper_cli, session_master):
     ret = pepper_cli(
         '--client=wheel', 'config.update_config', 'file_name=pepper',
         'yaml_contents={0}'.format(json.dumps({"timeout": 5})),
     )
     assert ret == 'Wrote pepper.conf'
-    assert os.path.isfile('{0}.d/pepper.conf'.format(session_master_config_file))
+
+    default_include_dir = pathlib.Path(session_master.config['default_include']).parent
+    pepper_config = (pathlib.Path(session_master.config_dir) / default_include_dir / 'pepper.conf')
+    assert pepper_config.exists
 
 
 @pytest.mark.xfail(
-    pytest.config.getoption("--salt-api-backend") == "rest_tornado",
+    'config.getoption("--salt-api-backend") == "rest_tornado"',
     reason="sshClient unimplemented for now on tornado",
 )
-@pytest.mark.xfail(sys.version_info >= (3, 0),
-                   reason='Broken with python3 right now')
-def test_ssh_client(pepper_cli, session_roster_config, session_roster_config_file):
+def test_ssh_client(pepper_cli, session_ssh_roster_config):
     ret = pepper_cli('--client=ssh', '*', 'test.ping')
     assert ret['ssh']['localhost']['return'] is True
 

+ 1 - 1
tests/integration/test_vanilla.py

@@ -9,7 +9,7 @@ def test_local(pepper_cli, session_minion_id):
 
 
 @pytest.mark.xfail(
-    pytest.config.getoption("--salt-api-backend") == "rest_tornado",
+    'config.getoption("--salt-api-backend") == "rest_tornado"',
     reason="this is broken in rest_tornado until future release",
 )
 def test_long_local(pepper_cli, session_minion_id):

+ 5 - 5
tests/requirements.txt

@@ -1,10 +1,10 @@
 mock
-pytest>=3.5.0,<4.0.0
+pytest>=6.0.0
 pytest-rerunfailures
 pytest-cov
-git+https://github.com/saltstack/pytest-salt@master#egg=pytest-salt
-tornado<5.0.0
+pytest-salt-factories==0.912.2
 CherryPy
 setuptools_scm
-pyzmq>=2.2.0,<17.1.0; python_version == '3.4'  # pyzmq 17.1.0 stopped building wheels for python3.4
-pyzmq>=2.2.0; python_version != '3.4'
+pyzmq<=20.0.0 ; python_version < "3.6"
+pyzmq>=17.0.0 ; python_version < "3.9"
+pyzmq>19.0.2 ; python_version >= "3.9"

+ 9 - 7
tox.ini

@@ -1,14 +1,16 @@
 [tox]
-envlist = py{27,34,35,36,37,38}-{cherrypy,tornado}-{v2018.3,v2019.2,develop},coverage,flake8
+envlist = py{3.7,3.8}-{cherrypy,tornado}-{v3004.2,v3005.1,master},coverage,flake8
 skip_missing_interpreters = true
 skipsdist = false
 
 [testenv]
-passenv = TOXENV CI TRAVIS TRAVIS_* CODECOV_*
+passenv = TOXENV, CI, TRAVIS, TRAVIS_*, CODECOV_*
 deps = -r{toxinidir}/tests/requirements.txt
-    v2018.3: salt<2018.4
-    v2019.2: salt<2019.3
-    develop: git+https://github.com/saltstack/salt.git@develop#egg=salt
+    v3004.2: salt<3004.2
+    v3004.2: jinja2<3.1
+    v3005.1: salt<3005.1
+    py3.7-{cherrypy,tornado}-{v3004.2,v3005.1}: importlib-metadata<5.0.0
+    master: git+https://github.com/saltstack/salt.git@master#egg=salt
 
 changedir = {toxinidir}
 setenv = COVERAGE_FILE = {toxworkdir}/.coverage.{envname}
@@ -25,7 +27,7 @@ commands = flake8 tests/ pepper/ scripts/pepper setup.py
 [testenv:coverage]
 skip_install = True
 deps =
-    coverage >= 4.4.1, < 5
+    coverage >= 7.0.5, < 8
 setenv = COVERAGE_FILE={toxworkdir}/.coverage
 changedir = {toxinidir}
 commands =
@@ -49,7 +51,7 @@ changedir = {toxinidir}/htmlcov
 commands = python -m http.server
 
 [pytest]
-addopts = --showlocals --log-file /tmp/pepper-runtests.log --no-print-logs -ra
+addopts = --showlocals --log-file /tmp/pepper-runtests.log --show-capture=no -ra
 testpaths = tests
 norecursedirs = .git .tox
 usefixtures = pepperconfig