mirror of
https://github.com/saltstack/salt.git
synced 2025-04-17 10:10:20 +00:00
Daemons are now started/stopped on tests, not by salt
This commit is contained in:
parent
ed60f0d17e
commit
5b030dd702
5 changed files with 380 additions and 231 deletions
|
@ -1,3 +1,4 @@
|
|||
daemon off;
|
||||
worker_processes 1;
|
||||
error_log {{ pillar['git_pillar']['config_dir'] }}/error.log;
|
||||
pid {{ pillar['git_pillar']['config_dir'] }}/nginx.pid;
|
||||
|
|
|
@ -2,7 +2,6 @@ uwsgi:
|
|||
socket: 127.0.0.1:{{ pillar['git_pillar']['uwsgi_port'] }}
|
||||
cgi: {{ pillar['git_pillar']['git-http-backend'] }}
|
||||
chdir: %d
|
||||
daemonize: {{ pillar['git_pillar']['config_dir'] }}/uwsgi.log
|
||||
pidfile: {{ pillar['git_pillar']['config_dir'] }}/uwsgi.pid
|
||||
# This is required to work around a bug in git-http-backend, introduced in
|
||||
# git 2.4.4 and worked around with cgi-close-stdin-on-eof in uwsgi >= 2.0.13.
|
||||
|
|
|
@ -50,15 +50,3 @@ uwsgi:
|
|||
UWSGI_PROFILE: cgi
|
||||
- require:
|
||||
- virtualenv: {{ venv_dir }}
|
||||
|
||||
start_uwsgi:
|
||||
cmd.run:
|
||||
- name: 'uwsgi --yaml {{ config_dir }}/uwsgi.yml'
|
||||
- require:
|
||||
- file: {{ config_dir }}/uwsgi.yml
|
||||
|
||||
start_nginx:
|
||||
cmd.run:
|
||||
- name: 'nginx -c {{ config_dir }}/nginx.conf'
|
||||
- require:
|
||||
- file: {{ config_dir }}/nginx.conf
|
||||
|
|
|
@ -31,14 +31,3 @@
|
|||
- group: root
|
||||
- mode: 755
|
||||
{%- endif %}
|
||||
|
||||
start_sshd:
|
||||
cmd.run:
|
||||
- name: '{{ pillar['git_pillar']['sshd_bin'] }} -f {{ sshd_config_dir }}/sshd_config'
|
||||
- require:
|
||||
- file: {{ sshd_config_dir }}/sshd_config
|
||||
- file: {{ sshd_config_dir }}/ssh_host_rsa_key
|
||||
- file: {{ sshd_config_dir }}/ssh_host_rsa_key.pub
|
||||
{%- if grains['os_family'] == 'Debian' %}
|
||||
- file: /var/run/sshd
|
||||
{%- endif %}
|
||||
|
|
|
@ -9,30 +9,30 @@ import copy
|
|||
import errno
|
||||
import logging
|
||||
import os
|
||||
import psutil
|
||||
import pprint
|
||||
import shutil
|
||||
import signal
|
||||
import tempfile
|
||||
import textwrap
|
||||
import time
|
||||
|
||||
# Import 3rd-party libs
|
||||
import psutil
|
||||
|
||||
# Import Salt libs
|
||||
import salt.utils.files
|
||||
import salt.utils.path
|
||||
import salt.utils.yaml
|
||||
import salt.ext.six as six
|
||||
from salt.fileserver import gitfs
|
||||
from salt.pillar import git_pillar
|
||||
from salt.ext.six.moves import range # pylint: disable=redefined-builtin
|
||||
|
||||
# Import Salt Testing libs
|
||||
from tests.support.case import ModuleCase
|
||||
from tests.support.mixins import LoaderModuleMockMixin, SaltReturnAssertsMixin
|
||||
from tests.support.paths import TMP
|
||||
from tests.support.helpers import (
|
||||
get_unused_localhost_port,
|
||||
requires_system_grains,
|
||||
)
|
||||
from tests.support.helpers import get_unused_localhost_port, requires_system_grains
|
||||
from tests.support.runtests import RUNTIME_VARS
|
||||
from tests.support.mock import patch
|
||||
from pytestsalt.utils import SaltDaemonScriptBase, terminate_process
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
@ -72,66 +72,224 @@ _OPTS = {
|
|||
PROC_TIMEOUT = 10
|
||||
|
||||
|
||||
class ProcessManager(object):
|
||||
def start_daemon(daemon_cli_script_name,
|
||||
daemon_config_dir,
|
||||
daemon_check_port,
|
||||
daemon_class,
|
||||
fail_hard=False,
|
||||
start_timeout=10,
|
||||
slow_stop=True,
|
||||
environ=None,
|
||||
cwd=None,
|
||||
max_attempts=3,
|
||||
**kwargs):
|
||||
'''
|
||||
Functions used both to set up self-contained SSH/HTTP servers for testing
|
||||
Returns a running process daemon
|
||||
'''
|
||||
wait = 10
|
||||
|
||||
def find_proc(self, name=None, search=None):
|
||||
def _search(proc):
|
||||
return any([search in x for x in proc.cmdline()])
|
||||
if name is None and search is None:
|
||||
raise ValueError('one of name or search is required')
|
||||
for proc in psutil.process_iter():
|
||||
if name is not None:
|
||||
try:
|
||||
if search is None:
|
||||
if name in proc.name():
|
||||
return proc
|
||||
elif name in proc.name() and _search(proc):
|
||||
return proc
|
||||
except psutil.NoSuchProcess:
|
||||
# Whichever process we are interrogating is no longer alive.
|
||||
# Skip it and keep searching.
|
||||
continue
|
||||
else:
|
||||
if _search(proc):
|
||||
return proc
|
||||
return None
|
||||
|
||||
def wait_proc(self, name=None, search=None, timeout=PROC_TIMEOUT):
|
||||
for idx in range(1, self.wait + 1):
|
||||
proc = self.find_proc(name=name, search=search)
|
||||
if proc is not None:
|
||||
return proc
|
||||
else:
|
||||
if idx != self.wait:
|
||||
log.debug(
|
||||
'Waiting for %s process (%d of %d)',
|
||||
name, idx, self.wait
|
||||
)
|
||||
time.sleep(1)
|
||||
else:
|
||||
log.debug(
|
||||
'Failed fo find %s process after %d seconds',
|
||||
name, self.wait
|
||||
)
|
||||
raise Exception(
|
||||
'Unable to find {0} process running from temp config file {1} '
|
||||
'using psutil'.format(name, search)
|
||||
log.info('[%s] Starting %s', daemon_class.log_prefix, daemon_class.__name__)
|
||||
attempts = 0
|
||||
process = None
|
||||
while attempts <= max_attempts: # pylint: disable=too-many-nested-blocks
|
||||
attempts += 1
|
||||
process = daemon_class(str(daemon_config_dir),
|
||||
daemon_check_port,
|
||||
cli_script_name=daemon_cli_script_name,
|
||||
slow_stop=slow_stop,
|
||||
environ=environ,
|
||||
cwd=cwd,
|
||||
**kwargs)
|
||||
process.start()
|
||||
if process.is_alive():
|
||||
try:
|
||||
connectable = process.wait_until_running(timeout=start_timeout)
|
||||
if connectable is False:
|
||||
connectable = process.wait_until_running(timeout=start_timeout/2)
|
||||
if connectable is False:
|
||||
process.terminate()
|
||||
if attempts >= max_attempts:
|
||||
raise AssertionError(
|
||||
'The pytest {} has failed to confirm running status '
|
||||
'after {} attempts'.format(daemon_class.__name__, attempts))
|
||||
continue
|
||||
except Exception as exc: # pylint: disable=broad-except
|
||||
log.exception('[%s] %s', daemon_class.log_prefix, exc, exc_info=True)
|
||||
terminate_process(process.pid, kill_children=True, slow_stop=slow_stop)
|
||||
if attempts >= max_attempts:
|
||||
raise AssertionError(str(exc))
|
||||
continue
|
||||
# A little breathing before returning the process
|
||||
time.sleep(0.5)
|
||||
log.info(
|
||||
'[%s] The %s is running after %d attempts',
|
||||
daemon_class.log_prefix,
|
||||
daemon_class.__name__,
|
||||
attempts
|
||||
)
|
||||
return process
|
||||
else:
|
||||
terminate_process(process.pid, kill_children=True, slow_stop=slow_stop)
|
||||
time.sleep(1)
|
||||
continue
|
||||
else: # pylint: disable=useless-else-on-loop
|
||||
# Wrong, we have a return, its not useless
|
||||
if process is not None:
|
||||
terminate_process(process.pid, kill_children=True, slow_stop=slow_stop)
|
||||
raise AssertionError(
|
||||
'The {} has failed to start after {} attempts'.format(
|
||||
daemon_class.__name__,
|
||||
attempts-1
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
class SSHDMixin(ModuleCase, ProcessManager, SaltReturnAssertsMixin):
|
||||
class UwsgiDaemon(SaltDaemonScriptBase):
|
||||
|
||||
log_prefix = 'uWSGI'
|
||||
|
||||
def __init__(self,
|
||||
config_dir,
|
||||
uwsgi_port,
|
||||
cli_script_name='uwsgi',
|
||||
**kwargs):
|
||||
super(UwsgiDaemon, self).__init__(None, # request
|
||||
{'check_port': uwsgi_port}, # config
|
||||
config_dir, # config_dir
|
||||
None, # bin_dir_path
|
||||
self.__class__.log_prefix, # log_prefix
|
||||
cli_script_name=cli_script_name,
|
||||
**kwargs)
|
||||
|
||||
def get_script_path(self, script_name):
|
||||
'''
|
||||
Returns the path to the script to run
|
||||
'''
|
||||
return script_name
|
||||
|
||||
def get_base_script_args(self):
|
||||
'''
|
||||
Returns any additional arguments to pass to the CLI script
|
||||
'''
|
||||
return ['--yaml', os.path.join(self.config_dir, 'uwsgi.yml')]
|
||||
|
||||
def get_check_ports(self):
|
||||
'''
|
||||
Return a list of ports to check against to ensure the daemon is running
|
||||
'''
|
||||
return [self.config['check_port']]
|
||||
|
||||
def get_salt_run_event_listener(self):
|
||||
# Remove this method once pytest-salt get's past 2019.7.20
|
||||
# Just return a class with a terminate method
|
||||
class EV(object):
|
||||
def terminate(self):
|
||||
pass
|
||||
|
||||
return EV()
|
||||
|
||||
|
||||
class NginxDaemon(SaltDaemonScriptBase):
|
||||
|
||||
log_prefix = 'Nginx'
|
||||
|
||||
def __init__(self,
|
||||
config_dir,
|
||||
nginx_port,
|
||||
cli_script_name='nginx',
|
||||
**kwargs):
|
||||
super(NginxDaemon, self).__init__(None, # request
|
||||
{'check_port': nginx_port}, # config
|
||||
config_dir, # config_dir
|
||||
None, # bin_dir_path
|
||||
self.__class__.log_prefix, # log_prefix
|
||||
cli_script_name=cli_script_name,
|
||||
**kwargs)
|
||||
|
||||
def get_script_path(self, script_name):
|
||||
'''
|
||||
Returns the path to the script to run
|
||||
'''
|
||||
return script_name
|
||||
|
||||
def get_base_script_args(self):
|
||||
'''
|
||||
Returns any additional arguments to pass to the CLI script
|
||||
'''
|
||||
return ['-c', os.path.join(self.config_dir, 'nginx.conf')]
|
||||
|
||||
def get_check_ports(self):
|
||||
'''
|
||||
Return a list of ports to check against to ensure the daemon is running
|
||||
'''
|
||||
return [self.config['check_port']]
|
||||
|
||||
def get_salt_run_event_listener(self):
|
||||
# Remove this method once pytest-salt get's past 2019.7.20
|
||||
# Just return a class with a terminate method
|
||||
class EV(object):
|
||||
def terminate(self):
|
||||
pass
|
||||
|
||||
return EV()
|
||||
|
||||
|
||||
class SshdDaemon(SaltDaemonScriptBase):
|
||||
|
||||
log_prefix = 'SSHD'
|
||||
|
||||
def __init__(self,
|
||||
config_dir,
|
||||
sshd_port,
|
||||
cli_script_name='sshd',
|
||||
**kwargs):
|
||||
super(SshdDaemon, self).__init__(None, # request
|
||||
{'check_port': sshd_port}, # config
|
||||
config_dir, # config_dir
|
||||
None, # bin_dir_path
|
||||
self.__class__.log_prefix, # log_prefix
|
||||
cli_script_name=cli_script_name,
|
||||
**kwargs)
|
||||
|
||||
def get_script_path(self, script_name):
|
||||
'''
|
||||
Returns the path to the script to run
|
||||
'''
|
||||
return script_name
|
||||
|
||||
def get_base_script_args(self):
|
||||
'''
|
||||
Returns any additional arguments to pass to the CLI script
|
||||
'''
|
||||
return ['-D', '-e', '-f', os.path.join(self.config_dir, 'sshd_config')]
|
||||
|
||||
def get_check_ports(self):
|
||||
'''
|
||||
Return a list of ports to check against to ensure the daemon is running
|
||||
'''
|
||||
return [self.config['check_port']]
|
||||
|
||||
def get_salt_run_event_listener(self):
|
||||
# Remove this method once pytest-salt get's past 2019.7.20
|
||||
# Just return a class with a terminate method
|
||||
class EV(object):
|
||||
def terminate(self):
|
||||
pass
|
||||
|
||||
return EV()
|
||||
|
||||
|
||||
class SSHDMixin(ModuleCase, SaltReturnAssertsMixin):
|
||||
'''
|
||||
Functions to stand up an SSHD server to serve up git repos for tests.
|
||||
'''
|
||||
sshd_proc = None
|
||||
prep_states_ran = False
|
||||
known_hosts_setup = False
|
||||
|
||||
@classmethod
|
||||
def prep_server(cls):
|
||||
cls.sshd_config_dir = tempfile.mkdtemp(dir=TMP)
|
||||
log.info('%s: prep_server()', cls.__name__)
|
||||
cls.sshd_bin = salt.utils.path.which('sshd')
|
||||
cls.sshd_config_dir = tempfile.mkdtemp(dir=RUNTIME_VARS.TMP)
|
||||
cls.sshd_config = os.path.join(cls.sshd_config_dir, 'sshd_config')
|
||||
cls.sshd_port = get_unused_localhost_port()
|
||||
cls.url = 'ssh://{username}@127.0.0.1:{port}/~/repo.git'.format(
|
||||
|
@ -151,35 +309,103 @@ class SSHDMixin(ModuleCase, ProcessManager, SaltReturnAssertsMixin):
|
|||
'passphrase': cls.passphrase}
|
||||
|
||||
def spawn_server(self):
|
||||
ret = self.run_function(
|
||||
'state.apply',
|
||||
mods='git_pillar.ssh',
|
||||
pillar={'git_pillar': {'git_ssh': self.git_ssh,
|
||||
'id_rsa_nopass': self.id_rsa_nopass,
|
||||
'id_rsa_withpass': self.id_rsa_withpass,
|
||||
'sshd_bin': self.sshd_bin,
|
||||
'sshd_port': self.sshd_port,
|
||||
'sshd_config_dir': self.sshd_config_dir,
|
||||
'master_user': self.master_opts['user'],
|
||||
'user': self.username}}
|
||||
)
|
||||
|
||||
try:
|
||||
self.sshd_proc = self.wait_proc(name='sshd',
|
||||
search=self.sshd_config)
|
||||
finally:
|
||||
# Do the assert after we check for the PID so that we can track
|
||||
# it regardless of whether or not something else in the SLS
|
||||
# failed (but the SSH server still started).
|
||||
if self.prep_states_ran is False:
|
||||
ret = self.run_function(
|
||||
'state.apply',
|
||||
mods='git_pillar.ssh',
|
||||
pillar={'git_pillar': {'git_ssh': self.git_ssh,
|
||||
'id_rsa_nopass': self.id_rsa_nopass,
|
||||
'id_rsa_withpass': self.id_rsa_withpass,
|
||||
'sshd_bin': self.sshd_bin,
|
||||
'sshd_port': self.sshd_port,
|
||||
'sshd_config_dir': self.sshd_config_dir,
|
||||
'master_user': self.master_opts['user'],
|
||||
'user': self.username}}
|
||||
)
|
||||
self.assertSaltTrueReturn(ret)
|
||||
SSHDMixin.prep_states_ran = True
|
||||
log.info('%s: States applied', self.__class__.__name__)
|
||||
if self.sshd_proc is not None:
|
||||
if not psutil.pid_exists(self.sshd_proc.pid):
|
||||
log.info('%s: sshd started but appears to be dead now. Will try to restart it.',
|
||||
self.__class__.__name__)
|
||||
SSHDMixin.sshd_proc = None
|
||||
if self.sshd_proc is None:
|
||||
SSHDMixin.sshd_proc = start_daemon(self.sshd_bin, self.sshd_config_dir, self.sshd_port, SshdDaemon)
|
||||
log.info('%s: sshd started', self.__class__.__name__)
|
||||
if self.known_hosts_setup is False:
|
||||
known_hosts_ret = self.run_function(
|
||||
'ssh.set_known_host',
|
||||
user=self.master_opts['user'],
|
||||
hostname='127.0.0.1',
|
||||
port=self.sshd_port,
|
||||
enc='ssh-rsa',
|
||||
fingerprint='fd:6f:7f:5d:06:6b:f2:06:0d:26:93:9e:5a:b5:19:46',
|
||||
hash_known_hosts=False,
|
||||
fingerprint_hash_type='md5',
|
||||
)
|
||||
if 'error' in known_hosts_ret:
|
||||
raise AssertionError(
|
||||
'Failed to add key to {0} user\'s known_hosts '
|
||||
'file: {1}'.format(
|
||||
self.master_opts['user'],
|
||||
known_hosts_ret['error']
|
||||
)
|
||||
)
|
||||
SSHDMixin.known_hosts_setup = True
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super(SSHDMixin, cls).setUpClass()
|
||||
cls.prep_server()
|
||||
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
if cls.sshd_proc is not None:
|
||||
log.info('[%s] Stopping %s', cls.sshd_proc.log_prefix, cls.sshd_proc.__class__.__name__)
|
||||
terminate_process(cls.sshd_proc.pid, kill_children=True, slow_stop=True)
|
||||
log.info('[%s] %s stopped', cls.sshd_proc.log_prefix, cls.sshd_proc.__class__.__name__)
|
||||
cls.sshd_proc = None
|
||||
client = RUNTIME_VARS.RUNTIME_CONFIGS.get('runtime_client')
|
||||
if client is not None and cls.prep_states_ran:
|
||||
ret = client.cmd('minion',
|
||||
'state.single',
|
||||
arg=['user.absent'],
|
||||
kwarg=dict(name=cls.username, purge=True))
|
||||
try:
|
||||
if ret and 'minion' in ret:
|
||||
ret_data = next(six.itervalues(ret['minion']))
|
||||
if not ret_data['result']:
|
||||
log.warning('Failed to delete test account %s', cls.username)
|
||||
except KeyError:
|
||||
log.warning('Failed to delete test account. Salt return:\n%s',
|
||||
pprint.pformat(ret))
|
||||
elif cls.prep_states_ran is True:
|
||||
log.warning('Test account %s was left behind since "RUNTIME_VARS.RUNTIME_CONFIGS" did not '
|
||||
'have an instantiated salt client.')
|
||||
for dirname in (cls.sshd_config_dir, cls.admin_repo, cls.bare_repo):
|
||||
if dirname is not None:
|
||||
shutil.rmtree(dirname, ignore_errors=True)
|
||||
ssh_dir = os.path.expanduser('~/.ssh')
|
||||
for filename in (cls.id_rsa_nopass,
|
||||
cls.id_rsa_nopass + '.pub',
|
||||
cls.id_rsa_withpass,
|
||||
cls.id_rsa_withpass + '.pub',
|
||||
cls.git_ssh):
|
||||
try:
|
||||
os.remove(os.path.join(ssh_dir, filename))
|
||||
except OSError as exc:
|
||||
if exc.errno != errno.ENOENT:
|
||||
raise
|
||||
|
||||
|
||||
class WebserverMixin(ModuleCase, ProcessManager, SaltReturnAssertsMixin):
|
||||
class WebserverMixin(ModuleCase, SaltReturnAssertsMixin):
|
||||
'''
|
||||
Functions to stand up an nginx + uWSGI + git-http-backend webserver to
|
||||
serve up git repos for tests.
|
||||
'''
|
||||
nginx_proc = uwsgi_proc = None
|
||||
prep_states_ran = False
|
||||
|
||||
@classmethod
|
||||
def prep_server(cls):
|
||||
|
@ -187,7 +413,7 @@ class WebserverMixin(ModuleCase, ProcessManager, SaltReturnAssertsMixin):
|
|||
Set up all the webserver paths. Designed to be run once in a
|
||||
setUpClass function.
|
||||
'''
|
||||
cls.root_dir = tempfile.mkdtemp(dir=TMP)
|
||||
cls.root_dir = tempfile.mkdtemp(dir=RUNTIME_VARS.TMP)
|
||||
cls.config_dir = os.path.join(cls.root_dir, 'config')
|
||||
cls.nginx_conf = os.path.join(cls.config_dir, 'nginx.conf')
|
||||
cls.uwsgi_conf = os.path.join(cls.config_dir, 'uwsgi.yml')
|
||||
|
@ -208,15 +434,13 @@ class WebserverMixin(ModuleCase, ProcessManager, SaltReturnAssertsMixin):
|
|||
for credential_param in ('user', 'password'):
|
||||
if hasattr(cls, credential_param):
|
||||
cls.ext_opts[credential_param] = getattr(cls, credential_param)
|
||||
|
||||
def spawn_server(self):
|
||||
auth_enabled = hasattr(self, 'username') and hasattr(self, 'password')
|
||||
pillar = {'git_pillar': {'config_dir': self.config_dir,
|
||||
'git_dir': self.git_dir,
|
||||
'venv_dir': self.venv_dir,
|
||||
'root_dir': self.root_dir,
|
||||
'nginx_port': self.nginx_port,
|
||||
'uwsgi_port': self.uwsgi_port,
|
||||
auth_enabled = hasattr(cls, 'username') and hasattr(cls, 'password')
|
||||
pillar = {'git_pillar': {'config_dir': cls.config_dir,
|
||||
'git_dir': cls.git_dir,
|
||||
'venv_dir': cls.venv_dir,
|
||||
'root_dir': cls.root_dir,
|
||||
'nginx_port': cls.nginx_port,
|
||||
'uwsgi_port': cls.uwsgi_port,
|
||||
'auth_enabled': auth_enabled}}
|
||||
|
||||
# Different libexec dir for git backend on Debian-based systems
|
||||
|
@ -224,33 +448,57 @@ class WebserverMixin(ModuleCase, ProcessManager, SaltReturnAssertsMixin):
|
|||
if not os.path.exists(git_core):
|
||||
git_core = '/usr/lib/git-core'
|
||||
|
||||
pillar['git_pillar']['git-http-backend'] = os.path.join(
|
||||
git_core,
|
||||
'git-http-backend')
|
||||
|
||||
ret = self.run_function(
|
||||
'state.apply',
|
||||
mods='git_pillar.http',
|
||||
pillar=pillar)
|
||||
|
||||
if not os.path.exists(pillar['git_pillar']['git-http-backend']):
|
||||
self.fail(
|
||||
'{0} not found. Either git is not installed, or the test '
|
||||
'class needs to be updated.'.format(
|
||||
pillar['git_pillar']['git-http-backend']
|
||||
)
|
||||
if not os.path.exists(git_core):
|
||||
raise AssertionError(
|
||||
'{} not found. Either git is not installed, or the test '
|
||||
'class needs to be updated.'.format(git_core)
|
||||
)
|
||||
|
||||
try:
|
||||
self.nginx_proc = self.wait_proc(name='nginx',
|
||||
search=self.nginx_conf)
|
||||
self.uwsgi_proc = self.wait_proc(name='uwsgi',
|
||||
search=self.uwsgi_conf)
|
||||
finally:
|
||||
# Do the assert after we check for the PID so that we can track
|
||||
# it regardless of whether or not something else in the SLS
|
||||
# failed (but the webserver still started).
|
||||
pillar['git_pillar']['git-http-backend'] = os.path.join(git_core, 'git-http-backend')
|
||||
cls.pillar = pillar
|
||||
|
||||
def spawn_server(self):
|
||||
if self.prep_states_ran is False:
|
||||
ret = self.run_function('state.apply', mods='git_pillar.http', pillar=self.pillar)
|
||||
self.assertSaltTrueReturn(ret)
|
||||
WebserverMixin.prep_states_ran = True
|
||||
log.info('%s: States applied', self.__class__.__name__)
|
||||
if self.uwsgi_proc is not None:
|
||||
if not psutil.pid_exists(self.uwsgi_proc.pid):
|
||||
log.warning('%s: uWsgi started but appears to be dead now. Will try to restart it.',
|
||||
self.__class__.__name__)
|
||||
WebserverMixin.uwsgi_proc = None
|
||||
if self.uwsgi_proc is None:
|
||||
WebserverMixin.uwsgi_proc = start_daemon(self.uwsgi_bin, self.config_dir, self.uwsgi_port, UwsgiDaemon)
|
||||
log.info('%s: %s started', self.__class__.__name__, self.uwsgi_bin)
|
||||
if self.nginx_proc is not None:
|
||||
if not psutil.pid_exists(self.nginx_proc.pid):
|
||||
log.warning('%s: nginx started but appears to be dead now. Will try to restart it.',
|
||||
self.__class__.__name__)
|
||||
WebserverMixin.nginx_proc = None
|
||||
if self.nginx_proc is None:
|
||||
WebserverMixin.nginx_proc = start_daemon('nginx', self.config_dir, self.nginx_port, NginxDaemon)
|
||||
log.info('%s: nginx started', self.__class__.__name__)
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super(WebserverMixin, cls).setUpClass()
|
||||
cls.prep_server()
|
||||
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
if cls.nginx_proc is not None:
|
||||
log.info('[%s] Stopping %s', cls.nginx_proc.log_prefix, cls.nginx_proc.__class__.__name__)
|
||||
terminate_process(cls.nginx_proc.pid, kill_children=True, slow_stop=True)
|
||||
log.info('[%s] %s stopped', cls.nginx_proc.log_prefix, cls.nginx_proc.__class__.__name__)
|
||||
cls.nginx_proc = None
|
||||
if cls.uwsgi_proc is not None:
|
||||
log.info('[%s] Stopping %s', cls.uwsgi_proc.log_prefix, cls.uwsgi_proc.__class__.__name__)
|
||||
terminate_process(cls.uwsgi_proc.pid, kill_children=True, slow_stop=True)
|
||||
log.info('[%s] %s stopped', cls.uwsgi_proc.log_prefix, cls.uwsgi_proc.__class__.__name__)
|
||||
cls.uwsgi_proc = None
|
||||
shutil.rmtree(cls.root_dir, ignore_errors=True)
|
||||
cls.pillar = None
|
||||
|
||||
|
||||
class GitTestBase(ModuleCase):
|
||||
|
@ -275,29 +523,11 @@ class GitTestBase(ModuleCase):
|
|||
def is_pre_el7(self, grains):
|
||||
return grains['os_family'] == 'RedHat' and grains['osmajorrelease'] < 7
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
cls.prep_server()
|
||||
|
||||
def setUp(self):
|
||||
# Make the test class available to the tearDownClass so we can clean up
|
||||
# after ourselves. This (and the gated block below) prevent us from
|
||||
# needing to spend the extra time creating an ssh server and user and
|
||||
# then tear them down separately for each test.
|
||||
self.update_class(self)
|
||||
if self.is_pre_el7(): # pylint: disable=E1120
|
||||
self.skipTest(
|
||||
'RHEL < 7 has too old a version of git to run these tests')
|
||||
|
||||
@classmethod
|
||||
def update_class(cls, case):
|
||||
'''
|
||||
Make the test class available to the tearDownClass. Note that this
|
||||
cannot be defined in a parent class and inherited, as this will cause
|
||||
the parent class to be modified.
|
||||
'''
|
||||
if getattr(cls, 'case') is None:
|
||||
setattr(cls, 'case', case)
|
||||
self.spawn_server()
|
||||
|
||||
def make_repo(self, root_dir, user='root'):
|
||||
raise NotImplementedError()
|
||||
|
@ -337,7 +567,7 @@ class GitPillarTestBase(GitTestBase, LoaderModuleMockMixin):
|
|||
'''
|
||||
Run git_pillar with the specified configuration
|
||||
'''
|
||||
cachedir = tempfile.mkdtemp(dir=TMP)
|
||||
cachedir = tempfile.mkdtemp(dir=RUNTIME_VARS.TMP)
|
||||
self.addCleanup(shutil.rmtree, cachedir, ignore_errors=True)
|
||||
ext_pillar_opts = {'optimization_order': [0, 1, 2]}
|
||||
ext_pillar_opts.update(
|
||||
|
@ -357,6 +587,7 @@ class GitPillarTestBase(GitTestBase, LoaderModuleMockMixin):
|
|||
)
|
||||
|
||||
def make_repo(self, root_dir, user='root'):
|
||||
log.info('Creating test Git repo....')
|
||||
self.bare_repo = os.path.join(root_dir, 'repo.git')
|
||||
self.admin_repo = os.path.join(root_dir, 'admin')
|
||||
|
||||
|
@ -497,8 +728,10 @@ class GitPillarTestBase(GitTestBase, LoaderModuleMockMixin):
|
|||
- mounted.bar
|
||||
'''))
|
||||
_push('top_mounted', 'add top_mounted branch')
|
||||
log.info('Test Git repo created.')
|
||||
|
||||
def make_extra_repo(self, root_dir, user='root'):
|
||||
log.info('Creating extra test Git repo....')
|
||||
self.bare_extra_repo = os.path.join(root_dir, 'extra_repo.git')
|
||||
self.admin_extra_repo = os.path.join(root_dir, 'admin_extra')
|
||||
|
||||
|
@ -552,6 +785,7 @@ class GitPillarTestBase(GitTestBase, LoaderModuleMockMixin):
|
|||
motd: The force will be with you. Always.
|
||||
'''))
|
||||
_push('master', 'initial commit')
|
||||
log.info('Extra test Git repo created.')
|
||||
|
||||
|
||||
class GitPillarSSHTestBase(GitPillarTestBase, SSHDMixin):
|
||||
|
@ -560,70 +794,26 @@ class GitPillarSSHTestBase(GitPillarTestBase, SSHDMixin):
|
|||
'''
|
||||
id_rsa_nopass = id_rsa_withpass = None
|
||||
git_ssh = '/tmp/git_ssh'
|
||||
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
if cls.case is None:
|
||||
return
|
||||
if cls.case.sshd_proc is not None:
|
||||
cls.case.sshd_proc.send_signal(signal.SIGTERM)
|
||||
cls.case.run_state('user.absent', name=cls.username, purge=True)
|
||||
for dirname in (cls.sshd_config_dir, cls.case.admin_repo,
|
||||
cls.case.bare_repo):
|
||||
if dirname is not None:
|
||||
shutil.rmtree(dirname, ignore_errors=True)
|
||||
ssh_dir = os.path.expanduser('~/.ssh')
|
||||
for filename in (cls.id_rsa_nopass,
|
||||
cls.id_rsa_nopass + '.pub',
|
||||
cls.id_rsa_withpass,
|
||||
cls.id_rsa_withpass + '.pub',
|
||||
cls.git_ssh):
|
||||
try:
|
||||
os.remove(os.path.join(ssh_dir, filename))
|
||||
except OSError as exc:
|
||||
if exc.errno != errno.ENOENT:
|
||||
raise
|
||||
home_resolved = False
|
||||
|
||||
def setUp(self):
|
||||
'''
|
||||
Create the SSH server and user, and create the git repo
|
||||
'''
|
||||
log.info('%s.setUp() started...', self.__class__.__name__)
|
||||
super(GitPillarSSHTestBase, self).setUp()
|
||||
self.sshd_proc = self.find_proc(name='sshd',
|
||||
search=self.sshd_config)
|
||||
self.sshd_bin = salt.utils.path.which('sshd')
|
||||
|
||||
if self.sshd_proc is None:
|
||||
self.spawn_server()
|
||||
|
||||
known_hosts_ret = self.run_function(
|
||||
'ssh.set_known_host',
|
||||
user=self.master_opts['user'],
|
||||
hostname='127.0.0.1',
|
||||
port=self.sshd_port,
|
||||
enc='ssh-rsa',
|
||||
fingerprint='fd:6f:7f:5d:06:6b:f2:06:0d:26:93:9e:5a:b5:19:46',
|
||||
hash_known_hosts=False,
|
||||
fingerprint_hash_type='md5',
|
||||
)
|
||||
if 'error' in known_hosts_ret:
|
||||
raise Exception(
|
||||
'Failed to add key to {0} user\'s known_hosts '
|
||||
'file: {1}'.format(
|
||||
self.master_opts['user'],
|
||||
known_hosts_ret['error']
|
||||
if self.username and self.home_resolved is False:
|
||||
root_dir = os.path.expanduser('~{0}'.format(self.username))
|
||||
if root_dir.startswith('~'):
|
||||
raise AssertionError(
|
||||
'Unable to resolve homedir for user \'{0}\''.format(
|
||||
self.username
|
||||
)
|
||||
)
|
||||
|
||||
root_dir = os.path.expanduser('~{0}'.format(self.username))
|
||||
if root_dir.startswith('~'):
|
||||
self.fail(
|
||||
'Unable to resolve homedir for user \'{0}\''.format(
|
||||
self.username
|
||||
)
|
||||
)
|
||||
self.make_repo(root_dir, user=self.username)
|
||||
self.make_extra_repo(root_dir, user=self.username)
|
||||
GitPillarSSHTestBase.home_resolved = True
|
||||
self.make_repo(root_dir, user=self.username)
|
||||
self.make_extra_repo(root_dir, user=self.username)
|
||||
log.info('%s.setUp() complete.', self.__class__.__name__)
|
||||
|
||||
def get_pillar(self, ext_pillar_conf):
|
||||
'''
|
||||
|
@ -647,31 +837,13 @@ class GitPillarHTTPTestBase(GitPillarTestBase, WebserverMixin):
|
|||
'''
|
||||
Base class for GitPython and Pygit2 HTTP tests
|
||||
'''
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
for proc in (cls.case.nginx_proc, cls.case.uwsgi_proc):
|
||||
if proc is not None:
|
||||
try:
|
||||
proc.send_signal(signal.SIGTERM)
|
||||
time.sleep(1)
|
||||
if proc.is_running():
|
||||
proc.send_signal(signal.SIGKILL)
|
||||
except psutil.NoSuchProcess:
|
||||
pass
|
||||
shutil.rmtree(cls.root_dir, ignore_errors=True)
|
||||
|
||||
def setUp(self):
|
||||
'''
|
||||
Create and start the webserver, and create the git repo
|
||||
'''
|
||||
log.info('%s.setUp() started...', self.__class__.__name__)
|
||||
super(GitPillarHTTPTestBase, self).setUp()
|
||||
self.nginx_proc = self.find_proc(name='nginx',
|
||||
search=self.nginx_conf)
|
||||
self.uwsgi_proc = self.find_proc(name='uwsgi',
|
||||
search=self.uwsgi_conf)
|
||||
|
||||
if self.nginx_proc is None and self.uwsgi_proc is None:
|
||||
self.spawn_server() # pylint: disable=E1120
|
||||
|
||||
self.make_repo(self.repo_dir)
|
||||
self.make_extra_repo(self.repo_dir)
|
||||
log.info('%s.setUp() complete', self.__class__.__name__)
|
||||
|
|
Loading…
Add table
Reference in a new issue