Skip to content

Commit 578f1ba

Browse files
authored
Merge pull request #227 from barneysowood/fix-test-suite
Fix test suite and move to pytest-salt-factories
2 parents b376591 + 369b5a1 commit 578f1ba

File tree

6 files changed

+129
-189
lines changed

6 files changed

+129
-189
lines changed

.github/workflows/test.yaml

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,6 @@ jobs:
1313
fail-fast: false
1414
matrix:
1515
py:
16-
- "3.5"
17-
- "3.6"
1816
- "3.7"
1917
- "3.8"
2018
netapi:
@@ -24,11 +22,6 @@ jobs:
2422
- "v3004.2"
2523
- "v3005.1"
2624
- "master"
27-
exclude:
28-
- salt: master
29-
py: "3.5"
30-
- salt: master
31-
py: "3.6"
3225
steps:
3326
- name: Setup python for test ${{ matrix.py }}
3427
uses: actions/setup-python@v4

tests/conftest.py

Lines changed: 108 additions & 162 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
from __future__ import absolute_import, unicode_literals, print_function
33

44
# Import python libraries
5-
import distutils.spawn
65
import logging
76
import os.path
87
import shutil
@@ -11,56 +10,94 @@
1110
import textwrap
1211

1312
# Import Salt Libraries
14-
import salt.client
15-
import salt.config
1613
import salt.utils.yaml as yaml
1714

1815
# Import pytest libraries
1916
import pytest
20-
from pytestsalt.utils import SaltDaemonScriptBase, start_daemon, get_unused_localhost_port
17+
from pytestskipmarkers.utils import ports
18+
from saltfactories.utils import random_string, running_username
2119

2220
# Import Pepper libraries
2321
import pepper
2422
import pepper.script
2523

26-
DEFAULT_MASTER_ID = 'pytest-salt-master'
27-
DEFAULT_MINION_ID = 'pytest-salt-minion'
2824

2925
log = logging.getLogger(__name__)
3026

3127

3228
@pytest.fixture(scope='session')
33-
def install_sshd_server():
34-
if distutils.spawn.find_executable('sshd'):
35-
return
36-
__opts__ = salt.config.minion_config('tests/minion.conf')
37-
__opts__['file_client'] = 'local'
38-
caller = salt.client.Caller(mopts=__opts__)
39-
caller.cmd('pkg.install', 'openssh-server')
29+
def sshd_config_dir(salt_factories):
30+
config_dir = salt_factories.get_root_dir_for_daemon("sshd")
31+
yield config_dir
32+
shutil.rmtree(str(config_dir), ignore_errors=True)
4033

4134

42-
class SaltApi(SaltDaemonScriptBase):
43-
'''
44-
Class which runs the salt-api daemon
45-
'''
46-
47-
def get_script_args(self):
48-
return ['-l', 'quiet']
35+
@pytest.fixture(scope='session')
36+
def session_sshd_server(salt_factories, sshd_config_dir, session_master):
37+
sshd_config_dict = {
38+
"Protocol": "2",
39+
# Turn strict modes off so that we can operate in /tmp
40+
"StrictModes": "no",
41+
# Logging
42+
"SyslogFacility": "AUTH",
43+
"LogLevel": "INFO",
44+
# Authentication:
45+
"LoginGraceTime": "120",
46+
"PermitRootLogin": "without-password",
47+
"PubkeyAuthentication": "yes",
48+
# Don't read the user's ~/.rhosts and ~/.shosts files
49+
"IgnoreRhosts": "yes",
50+
"HostbasedAuthentication": "no",
51+
# To enable empty passwords, change to yes (NOT RECOMMENDED)
52+
"PermitEmptyPasswords": "no",
53+
# Change to yes to enable challenge-response passwords (beware issues with
54+
# some PAM modules and threads)
55+
"ChallengeResponseAuthentication": "no",
56+
# Change to no to disable tunnelled clear text passwords
57+
"PasswordAuthentication": "no",
58+
"X11Forwarding": "no",
59+
"X11DisplayOffset": "10",
60+
"PrintMotd": "no",
61+
"PrintLastLog": "yes",
62+
"TCPKeepAlive": "yes",
63+
"AcceptEnv": "LANG LC_*",
64+
"UsePAM": "yes",
65+
}
66+
factory = salt_factories.get_sshd_daemon(
67+
sshd_config_dict=sshd_config_dict,
68+
config_dir=sshd_config_dir,
69+
)
70+
with factory.started():
71+
yield factory
4972

50-
def get_check_ports(self):
51-
if 'rest_cherrypy' in self.config:
52-
return [self.config['rest_cherrypy']['port']]
5373

54-
if 'rest_tornado' in self.config:
55-
return [self.config['rest_tornado']['port']]
74+
@pytest.fixture(scope='session')
75+
def session_ssh_roster_config(session_sshd_server, session_master):
76+
roster_contents = """
77+
localhost:
78+
host: 127.0.0.1
79+
port: {}
80+
user: {}
81+
priv: {}
82+
mine_functions:
83+
test.arg: ['itworked']
84+
""".format(
85+
session_sshd_server.listen_port,
86+
running_username(),
87+
session_sshd_server.client_key
88+
)
89+
with pytest.helpers.temp_file(
90+
"roster", roster_contents, session_master.config_dir
91+
) as roster_file:
92+
yield roster_file
5693

5794

5895
@pytest.fixture(scope='session')
5996
def salt_api_port():
6097
'''
6198
Returns an unused localhost port for the api port
6299
'''
63-
return get_unused_localhost_port()
100+
return ports.get_unused_localhost_port()
64101

65102

66103
@pytest.fixture(scope='session')
@@ -121,7 +158,7 @@ def output_file():
121158

122159

123160
@pytest.fixture(params=['/run', '/login'])
124-
def pepper_cli(request, session_salt_api, salt_api_port, output_file, install_sshd_server, session_sshd_server):
161+
def pepper_cli(request, session_salt_api, salt_api_port, output_file, session_sshd_server):
125162
'''
126163
Wrapper to invoke Pepper with common params and inside an empty env
127164
'''
@@ -154,6 +191,20 @@ def _run_pepper_cli(*args, **kwargs):
154191
return _run_pepper_cli
155192

156193

194+
@pytest.fixture(scope='session')
195+
def session_master_factory(request, salt_factories, session_master_config_overrides):
196+
return salt_factories.salt_master_daemon(
197+
random_string("master-"),
198+
overrides=session_master_config_overrides
199+
)
200+
201+
202+
@pytest.fixture(scope='session')
203+
def session_master(session_master_factory):
204+
with session_master_factory.started():
205+
yield session_master_factory
206+
207+
157208
@pytest.fixture(scope='session')
158209
def session_master_config_overrides(request, salt_api_port, salt_api_backend):
159210
return {
@@ -175,69 +226,40 @@ def session_master_config_overrides(request, salt_api_port, salt_api_backend):
175226
'token_expire': 94670856,
176227
'ignore_host_keys': True,
177228
'ssh_wipe': True,
229+
'netapi_enable_clients': [
230+
'local',
231+
'local_async',
232+
'local_subset',
233+
'ssh',
234+
'runner',
235+
'runner_async',
236+
'wheel',
237+
'wheel_async',
238+
'run'
239+
]
178240
}
179241

180242

181243
@pytest.fixture(scope='session')
182-
def session_api_log_prefix(master_id):
183-
return 'salt-api/{0}'.format(master_id)
244+
def session_minion_factory(session_master_factory):
245+
"""Return a factory for a randomly named minion connected to master."""
246+
minion_factory = session_master_factory.salt_minion_daemon(random_string("minion-"))
247+
minion_factory.after_terminate(
248+
pytest.helpers.remove_stale_minion_key, session_master_factory, minion_factory.id
249+
)
250+
return minion_factory
184251

185252

186253
@pytest.fixture(scope='session')
187-
def cli_api_script_name():
188-
'''
189-
Return the CLI script basename
190-
'''
191-
return 'salt-api'
192-
193-
194-
@pytest.yield_fixture(scope='session')
195-
def session_salt_api_before_start():
196-
'''
197-
This fixture should be overridden if you need to do
198-
some preparation and clean up work before starting
199-
the salt-api and after ending it.
200-
'''
201-
# Prep routines go here
202-
203-
# Start the salt-api
204-
yield
205-
206-
# Clean routines go here
207-
208-
209-
@pytest.yield_fixture(scope='session')
210-
def session_salt_api_after_start(session_salt_api):
211-
'''
212-
This fixture should be overridden if you need to do
213-
some preparation and clean up work after starting
214-
the salt-api and before ending it.
215-
'''
216-
# Prep routines go here
217-
218-
# Resume test execution
219-
yield
220-
221-
# Clean routines go here
254+
def session_minion(session_master, session_minion_factory): # noqa
255+
assert session_master.is_running()
256+
with session_minion_factory.started():
257+
yield session_minion_factory
222258

223259

224260
@pytest.fixture(scope='session')
225-
def _salt_fail_hard(request, salt_fail_hard):
226-
'''
227-
Return the salt fail hard value
228-
'''
229-
fail_hard = request.config.getoption('salt_fail_hard')
230-
if fail_hard is not None:
231-
# We were passed --salt-fail-hard as a CLI option
232-
return fail_hard
233-
234-
# The salt fail hard was not passed as a CLI option
235-
fail_hard = request.config.getini('salt_fail_hard')
236-
if fail_hard != []:
237-
# We were passed salt_fail_hard as a INI option
238-
return fail_hard
239-
240-
return salt_fail_hard
261+
def session_minion_id(session_minion):
262+
return session_minion.id
241263

242264

243265
@pytest.fixture(scope='session')
@@ -257,91 +279,15 @@ def salt_api_backend(request):
257279

258280

259281
@pytest.fixture(scope='session')
260-
def master_id(salt_master_id_counter):
261-
'''
262-
Returns the master id
263-
'''
264-
return DEFAULT_MASTER_ID + '-{0}'.format(salt_master_id_counter())
282+
def session_salt_api_factory(session_master_factory):
283+
return session_master_factory.salt_api_daemon()
265284

266285

267286
@pytest.fixture(scope='session')
268-
def minion_id(salt_minion_id_counter):
269-
'''
270-
Returns the minion id
271-
'''
272-
return DEFAULT_MINION_ID + '-{0}'.format(salt_minion_id_counter())
273-
274-
275-
@pytest.fixture(scope='session')
276-
def session_salt_api(request,
277-
session_salt_minion,
278-
session_master_id,
279-
session_master_config,
280-
session_salt_api_before_start, # pylint: disable=unused-argument
281-
session_api_log_prefix,
282-
cli_api_script_name,
283-
log_server,
284-
_cli_bin_dir,
285-
session_conf_dir):
286-
'''
287-
Returns a running salt-api
288-
'''
289-
return start_daemon(request,
290-
daemon_name='salt-api',
291-
daemon_id=session_master_id,
292-
daemon_log_prefix=session_api_log_prefix,
293-
daemon_cli_script_name=cli_api_script_name,
294-
daemon_config=session_master_config,
295-
daemon_config_dir=session_conf_dir,
296-
daemon_class=SaltApi,
297-
bin_dir_path=_cli_bin_dir,
298-
start_timeout=30)
299-
300-
301-
@pytest.fixture(scope='session')
302-
def session_sshd_config_lines(session_sshd_port):
303-
'''
304-
Return a list of lines which will make the sshd_config file
305-
'''
306-
return [
307-
'Port {0}'.format(session_sshd_port),
308-
'ListenAddress 127.0.0.1',
309-
'Protocol 2',
310-
'UsePrivilegeSeparation yes',
311-
'# Turn strict modes off so that we can operate in /tmp',
312-
'StrictModes no',
313-
'# Logging',
314-
'SyslogFacility AUTH',
315-
'LogLevel INFO',
316-
'# Authentication:',
317-
'LoginGraceTime 120',
318-
'PermitRootLogin without-password',
319-
'StrictModes yes',
320-
'PubkeyAuthentication yes',
321-
'#AuthorizedKeysFile %h/.ssh/authorized_keys',
322-
'#AuthorizedKeysFile key_test.pub',
323-
'# Don\'t read the user\'s ~/.rhosts and ~/.shosts files',
324-
'IgnoreRhosts yes',
325-
'# similar for protocol version 2',
326-
'HostbasedAuthentication no',
327-
'#IgnoreUserKnownHosts yes',
328-
'# To enable empty passwords, change to yes (NOT RECOMMENDED)',
329-
'PermitEmptyPasswords no',
330-
'# Change to yes to enable challenge-response passwords (beware issues with',
331-
'# some PAM modules and threads)',
332-
'ChallengeResponseAuthentication no',
333-
'# Change to no to disable tunnelled clear text passwords',
334-
'PasswordAuthentication no',
335-
'X11Forwarding no',
336-
'X11DisplayOffset 10',
337-
'PrintMotd no',
338-
'PrintLastLog yes',
339-
'TCPKeepAlive yes',
340-
'#UseLogin no',
341-
'AcceptEnv LANG LC_*',
342-
'Subsystem sftp /usr/lib/openssh/sftp-server',
343-
'#UsePAM yes',
344-
]
287+
def session_salt_api(session_master, session_salt_api_factory):
288+
assert session_master.is_running()
289+
with session_salt_api_factory.started():
290+
yield session_salt_api_factory
345291

346292

347293
def pytest_addoption(parser):

0 commit comments

Comments
 (0)