Rescue proxy_auto_tests PR from git rebase hell

This commit is contained in:
C. R. Oldham 2017-05-05 15:32:16 -06:00
parent ff6fa2b120
commit 3be90cc9f4
12 changed files with 1002 additions and 22 deletions

View File

@ -1482,19 +1482,249 @@ DEFAULT_MASTER_OPTS = {
# ----- Salt Proxy Minion Configuration Defaults ----------------------------------->
# Note DEFAULT_MINION_OPTS
# is loaded first, then if we are setting up a proxy, the config is overwritten with
# these settings.
DEFAULT_PROXY_MINION_OPTS = {
'conf_file': os.path.join(salt.syspaths.CONFIG_DIR, 'proxy'),
'log_file': os.path.join(salt.syspaths.LOGS_DIR, 'proxy'),
'sign_pub_messages': False,
'add_proxymodule_to_opts': False,
'proxy_merge_grains_in_module': False,
'append_minionid_config_dirs': ['cachedir', 'pidfile'],
'default_include': 'proxy.d/*.conf',
'interface': '0.0.0.0',
'master': 'salt',
'master_type': 'str',
'master_uri_format': 'default',
'master_port': 4506,
'master_finger': '',
'master_shuffle': False,
'master_alive_interval': 0,
'master_failback': False,
'master_failback_interval': 0,
'verify_master_pubkey_sign': False,
'sign_pub_messages': False,
'always_verify_signature': False,
'master_sign_key_name': 'master_sign',
'syndic_finger': '',
'user': salt.utils.get_user(),
'root_dir': salt.syspaths.ROOT_DIR,
'pki_dir': os.path.join(salt.syspaths.CONFIG_DIR, 'pki', 'proxy'),
'id': '',
'cachedir': os.path.join(salt.syspaths.CACHE_DIR, 'proxy'),
'cache_jobs': False,
'grains_cache': False,
'grains_cache_expiration': 300,
'grains_deep_merge': False,
'sock_dir': os.path.join(salt.syspaths.SOCK_DIR, 'proxy'),
'backup_mode': '',
'renderer': 'yaml_jinja',
'renderer_whitelist': [],
'renderer_blacklist': [],
'random_startup_delay': 0,
'failhard': False,
'autoload_dynamic_modules': True,
'environment': None,
'pillarenv': None,
'pillar_opts': False,
# ``pillar_cache``, ``pillar_cache_ttl`` and ``pillar_cache_backend``
# are not used on the minion but are unavoidably in the code path
'pillar_cache': False,
'pillar_cache_ttl': 3600,
'pillar_cache_backend': 'disk',
'extension_modules': os.path.join(salt.syspaths.CACHE_DIR, 'proxy', 'extmods'),
'state_top': 'top.sls',
'state_top_saltenv': None,
'startup_states': '',
'sls_list': [],
'top_file': '',
'thorium_interval': 0.5,
'thorium_roots': {
'base': [salt.syspaths.BASE_THORIUM_ROOTS_DIR],
},
'file_client': 'remote',
'use_master_when_local': False,
'file_roots': {
'base': [salt.syspaths.BASE_FILE_ROOTS_DIR,
salt.syspaths.SPM_FORMULA_PATH]
},
'top_file_merging_strategy': 'merge',
'env_order': [],
'default_top': 'base',
'fileserver_limit_traversal': False,
'file_recv': False,
'file_recv_max_size': 100,
'file_ignore_regex': [],
'file_ignore_glob': [],
'fileserver_backend': ['roots'],
'fileserver_followsymlinks': True,
'fileserver_ignoresymlinks': False,
'pillar_roots': {
'base': [salt.syspaths.BASE_PILLAR_ROOTS_DIR,
salt.syspaths.SPM_PILLAR_PATH]
},
'on_demand_ext_pillar': ['libvirt', 'virtkey'],
'git_pillar_base': 'master',
'git_pillar_branch': 'master',
'git_pillar_env': '',
'git_pillar_root': '',
'git_pillar_ssl_verify': True,
'git_pillar_global_lock': True,
'git_pillar_user': '',
'git_pillar_password': '',
'git_pillar_insecure_auth': False,
'git_pillar_privkey': '',
'git_pillar_pubkey': '',
'git_pillar_passphrase': '',
'gitfs_remotes': [],
'gitfs_mountpoint': '',
'gitfs_root': '',
'gitfs_base': 'master',
'gitfs_user': '',
'gitfs_password': '',
'gitfs_insecure_auth': False,
'gitfs_privkey': '',
'gitfs_pubkey': '',
'gitfs_passphrase': '',
'gitfs_env_whitelist': [],
'gitfs_env_blacklist': [],
'gitfs_global_lock': True,
'gitfs_ssl_verify': True,
'gitfs_saltenv': [],
'hash_type': 'sha256',
'disable_modules': [],
'disable_returners': [],
'whitelist_modules': [],
'module_dirs': [],
'returner_dirs': [],
'grains_dirs': [],
'states_dirs': [],
'render_dirs': [],
'outputter_dirs': [],
'utils_dirs': [],
'providers': {},
'clean_dynamic_modules': True,
'open_mode': False,
'auto_accept': True,
'autosign_timeout': 120,
'multiprocessing': True,
'mine_enabled': True,
'mine_return_job': False,
'mine_interval': 60,
'ipc_mode': _DFLT_IPC_MODE,
'ipc_write_buffer': _DFLT_IPC_WBUFFER,
'ipv6': None,
'file_buffer_size': 262144,
'tcp_pub_port': 4510,
'tcp_pull_port': 4511,
'tcp_authentication_retries': 5,
'log_level': 'warning',
'log_level_logfile': None,
'log_datefmt': _DFLT_LOG_DATEFMT,
'log_datefmt_logfile': _DFLT_LOG_DATEFMT_LOGFILE,
'log_fmt_console': _DFLT_LOG_FMT_CONSOLE,
'log_fmt_logfile': _DFLT_LOG_FMT_LOGFILE,
'log_granular_levels': {},
'max_event_size': 1048576,
'test': False,
'ext_job_cache': '',
'cython_enable': False,
'enable_zip_modules': False,
'state_verbose': True,
'state_output': 'full',
'state_output_diff': False,
'state_auto_order': True,
'state_events': False,
'state_aggregate': False,
'snapper_states': False,
'snapper_states_config': 'root',
'acceptance_wait_time': 10,
'acceptance_wait_time_max': 0,
'rejected_retry': False,
'loop_interval': 1,
'verify_env': True,
'grains': {},
'permissive_pki_access': False,
'update_url': False,
'update_restart_services': [],
'retry_dns': 30,
'recon_max': 10000,
'recon_default': 1000,
'recon_randomize': True,
'return_retry_timer': 5,
'return_retry_timer_max': 10,
'random_reauth_delay': 10,
'winrepo_source_dir': 'salt://win/repo-ng/',
'winrepo_dir': os.path.join(salt.syspaths.BASE_FILE_ROOTS_DIR, 'win', 'repo'),
'winrepo_dir_ng': os.path.join(salt.syspaths.BASE_FILE_ROOTS_DIR, 'win', 'repo-ng'),
'winrepo_cachefile': 'winrepo.p',
'winrepo_cache_expire_max': 21600,
'winrepo_cache_expire_min': 0,
'winrepo_remotes': ['https://github.com/saltstack/salt-winrepo.git'],
'winrepo_remotes_ng': ['https://github.com/saltstack/salt-winrepo-ng.git'],
'winrepo_branch': 'master',
'winrepo_ssl_verify': True,
'winrepo_user': '',
'winrepo_password': '',
'winrepo_insecure_auth': False,
'winrepo_privkey': '',
'winrepo_pubkey': '',
'winrepo_passphrase': '',
'pidfile': os.path.join(salt.syspaths.PIDFILE_DIR, 'salt-proxy.pid'),
'range_server': 'range:80',
'reactor_refresh_interval': 60,
'reactor_worker_threads': 10,
'reactor_worker_hwm': 10000,
'engines': [],
'tcp_keepalive': True,
'tcp_keepalive_idle': 300,
'tcp_keepalive_cnt': -1,
'tcp_keepalive_intvl': -1,
'modules_max_memory': -1,
'grains_refresh_every': 0,
'minion_id_caching': True,
'keysize': 2048,
'transport': 'zeromq',
'auth_timeout': 5,
'auth_tries': 7,
'master_tries': _MASTER_TRIES,
'auth_safemode': False,
'random_master': False,
'minion_floscript': os.path.join(FLO_DIR, 'minion.flo'),
'caller_floscript': os.path.join(FLO_DIR, 'caller.flo'),
'ioflo_verbose': 0,
'ioflo_period': 0.1,
'ioflo_realtime': True,
'ioflo_console_logdir': '',
'raet_port': 4510,
'raet_alt_port': 4511,
'raet_mutable': False,
'raet_main': False,
'raet_clear_remotes': True,
'raet_clear_remote_masters': True,
'raet_road_bufcnt': 2,
'raet_lane_bufcnt': 100,
'cluster_mode': False,
'cluster_masters': [],
'restart_on_error': False,
'ping_interval': 0,
'username': None,
'password': None,
'zmq_filtering': False,
'zmq_monitor': False,
'cache_sreqs': True,
'cmd_safe': True,
'sudo_user': '',
'http_request_timeout': 1 * 60 * 60.0, # 1 hour
'http_max_body': 100 * 1024 * 1024 * 1024, # 100GB
'event_match_type': 'startswith',
'minion_restart_command': [],
'pub_ret': True,
'proxy_host': '',
'proxy_username': '',
'proxy_password': '',
'proxy_port': 0,
'minion_jid_queue_hwm': 100,
'ssl': None,
'cache': 'localfs',
}
# ----- Salt Cloud Configuration Defaults ----------------------------------->
DEFAULT_CLOUD_OPTS = {
'verify_env': True,
@ -1998,6 +2228,56 @@ def minion_config(path,
return opts
def proxy_config(path,
env_var='SALT_PROXY_CONFIG',
defaults=None,
cache_minion_id=False,
ignore_config_errors=True,
minion_id=None):
'''
Reads in the proxy minion configuration file and sets up special options
This is useful for Minion-side operations, such as the
:py:class:`~salt.client.Caller` class, and manually running the loader
interface.
.. code-block:: python
import salt.config
proxy_opts = salt.config.proxy_config('/etc/salt/proxy')
'''
if path is not None and path.endswith('proxy'):
defaults = DEFAULT_PROXY_MINION_OPTS.copy()
if not os.environ.get(env_var, None):
# No valid setting was given using the configuration variable.
# Lets see is SALT_CONFIG_DIR is of any use
salt_config_dir = os.environ.get('SALT_CONFIG_DIR', None)
if salt_config_dir:
env_config_file_path = os.path.join(salt_config_dir, 'proxy')
if salt_config_dir and os.path.isfile(env_config_file_path):
# We can get a configuration file using SALT_CONFIG_DIR, let's
# update the environment with this information
os.environ[env_var] = env_config_file_path
overrides = load_config(path, env_var, DEFAULT_PROXY_MINION_OPTS['conf_file'])
default_include = overrides.get('default_include',
defaults['default_include'])
include = overrides.get('include', [])
overrides.update(include_config(default_include, path, verbose=False,
exit_on_config_errors=not ignore_config_errors))
overrides.update(include_config(include, path, verbose=True,
exit_on_config_errors=not ignore_config_errors))
opts = apply_minion_config(overrides, defaults,
cache_minion_id=cache_minion_id,
minion_id=minion_id)
apply_sdb(opts)
_validate_opts(opts)
return opts
def syndic_config(master_config_path,
minion_config_path,
master_env_var='SALT_MASTER_CONFIG',

View File

@ -0,0 +1,94 @@
# -*- coding: utf-8 -*-
'''
Package support for the dummy proxy used by the test suite
'''
from __future__ import absolute_import
# Import python libs
import logging
import salt.utils
log = logging.getLogger(__name__)
# Define the module's virtual name
__virtualname__ = 'pkg'
def __virtual__():
'''
Only work on systems that are a proxy minion
'''
try:
if salt.utils.is_proxy() and __opts__['proxy']['proxytype'] == 'dummy':
return __virtualname__
except KeyError:
return (False, 'The dummyproxy_package execution module failed to load. Check the proxy key in pillar or /etc/salt/proxy.')
return (False, 'The dummyproxy_package execution module failed to load: only works on a dummy proxy minion.')
def list_pkgs(versions_as_list=False, **kwargs):
return __proxy__['dummy.package_list']()
def install(name=None, refresh=False, fromrepo=None,
pkgs=None, sources=None, **kwargs):
return __proxy__['dummy.package_install'](name, **kwargs)
def remove(name=None, pkgs=None, **kwargs):
return __proxy__['dummy.package_remove'](name)
def version(*names, **kwargs):
'''
Returns a string representing the package version or an empty string if not
installed. If more than one package name is specified, a dict of
name/version pairs is returned.
CLI Example:
.. code-block:: bash
salt '*' pkg.version <package name>
salt '*' pkg.version <package1> <package2> <package3> ...
'''
if len(names) == 1:
vers = __proxy__['dummy.package_status'](names[0])
return vers[names[0]]
else:
results = {}
for n in names:
vers = __proxy__['dummy.package_status'](n)
results.update(vers)
return results
def upgrade(name=None, pkgs=None, refresh=True, skip_verify=True,
normalize=True, **kwargs):
old = __proxy__['dummy.package_list']()
new = __proxy__['dummy.uptodate']()
pkg_installed = __proxy__['dummy.upgrade']()
ret = salt.utils.compare_dicts(old, pkg_installed)
return ret
def installed(name,
version=None,
refresh=False,
fromrepo=None,
skip_verify=False,
pkgs=None,
sources=None,
**kwargs):
p = __proxy__['dummy.package_status'](name)
if version is None:
if 'ret' in p:
return str(p['ret'])
else:
return True
else:
if p is not None:
return version == str(p)

View File

@ -0,0 +1,156 @@
# -*- coding: utf-8 -*-
'''
Provide the service module for the dummy proxy used in integration tests
'''
# Import python libs
from __future__ import absolute_import
import salt.utils
import logging
log = logging.getLogger(__name__)
__func_alias__ = {
'list_': 'list'
}
# Define the module's virtual name
__virtualname__ = 'service'
def __virtual__():
'''
Only work on systems that are a proxy minion
'''
try:
if salt.utils.is_proxy() and __opts__['proxy']['proxytype'] == 'dummy':
return __virtualname__
except KeyError:
return (False, 'The dummyproxy_service execution module failed to load. Check the proxy key in pillar or /etc/salt/proxy.')
return (False, 'The dummyproxy_service execution module failed to load: only works on the integration testsuite dummy proxy minion.')
def get_all():
'''
Return a list of all available services
.. versionadded:: 2016.11.3
CLI Example:
.. code-block:: bash
salt '*' service.get_all
'''
proxy_fn = 'dummy.service_list'
return __proxy__[proxy_fn]()
def list_():
'''
Return a list of all available services.
.. versionadded:: 2016.11.3
CLI Example:
.. code-block:: bash
salt '*' service.list
'''
return get_all()
def start(name, sig=None):
'''
Start the specified service on the dummy
.. versionadded:: 2016.11.3
CLI Example:
.. code-block:: bash
salt '*' service.start <service name>
'''
proxy_fn = 'dummy.service_start'
return __proxy__[proxy_fn](name)
def stop(name, sig=None):
'''
Stop the specified service on the dummy
.. versionadded:: 2016.11.3
CLI Example:
.. code-block:: bash
salt '*' service.stop <service name>
'''
proxy_fn = 'dummy.service_stop'
return __proxy__[proxy_fn](name)
def restart(name, sig=None):
'''
Restart the specified service with dummy.
.. versionadded:: 2016.11.3
CLI Example:
.. code-block:: bash
salt '*' service.restart <service name>
'''
proxy_fn = 'dummy.service_restart'
return __proxy__[proxy_fn](name)
def status(name, sig=None):
'''
Return the status for a service via dummy, returns a bool
whether the service is running.
.. versionadded:: 2016.11.3
CLI Example:
.. code-block:: bash
salt '*' service.status <service name>
'''
proxy_fn = 'dummy.service_status'
resp = __proxy__[proxy_fn](name)
if resp['comment'] == 'stopped':
return False
if resp['comment'] == 'running':
return True
def running(name, sig=None):
'''
Return whether this service is running.
.. versionadded:: 2016.11.3
'''
return status(name).get(name, False)
def enabled(name, sig=None):
'''
Only the 'redbull' service is 'enabled' in the test
.. versionadded:: 2016.11.3
'''
return name == 'redbull'

239
salt/proxy/dummy.py Normal file
View File

@ -0,0 +1,239 @@
# -*- coding: utf-8 -*-
'''
This is a dummy proxy-minion designed for testing the proxy minion subsystem.
'''
from __future__ import absolute_import
# Import python libs
import os
import logging
import pickle
# This must be present or the Salt loader won't load this module
__proxyenabled__ = ['dummy']
# Variables are scoped to this module so we can have persistent data
# across calls to fns in here.
DETAILS = {}
DETAILS['services'] = {'apache': 'running', 'ntp': 'running', 'samba': 'stopped'}
DETAILS['packages'] = {'coreutils': '1.0', 'apache': '2.4', 'tinc': '1.4', 'redbull': '999.99'}
FILENAME = os.tmpnam()
# Want logging!
log = logging.getLogger(__file__)
# This does nothing, it's here just as an example and to provide a log
# entry when the module is loaded.
def __virtual__():
'''
Only return if all the modules are available
'''
log.debug('dummy proxy __virtual__() called...')
return True
def _save_state(details):
global FILENAME
pck = open(FILENAME, 'wb')
pickle.dump(details, pck)
pck.close()
def _load_state():
global FILENAME
try:
pck = open(FILENAME, 'r')
DETAILS = pickle.load(pck)
pck.close()
except IOError:
DETAILS = {}
DETAILS['initialized'] = False
_save_state(DETAILS)
return DETAILS
# Every proxy module needs an 'init', though you can
# just put DETAILS['initialized'] = True here if nothing
# else needs to be done.
def init(opts):
log.debug('dummy proxy init() called...')
DETAILS['initialized'] = True
_save_state(DETAILS)
def initialized():
'''
Since grains are loaded in many different places and some of those
places occur before the proxy can be initialized, return whether
our init() function has been called
'''
DETAILS = _load_state()
return DETAILS.get('initialized', False)
def grains():
'''
Make up some grains
'''
DETAILS = _load_state()
if 'grains_cache' not in DETAILS:
DETAILS['grains_cache'] = {'dummy_grain_1': 'one', 'dummy_grain_2': 'two', 'dummy_grain_3': 'three', }
_save_state(DETAILS)
return DETAILS['grains_cache']
def grains_refresh():
'''
Refresh the grains
'''
DETAILS = _load_state()
DETAILS['grains_cache'] = None
_save_state(DETAILS)
return grains()
def fns():
return {'details': 'This key is here because a function in '
'grains/rest_sample.py called fns() here in the proxymodule.'}
def service_start(name):
'''
Start a "service" on the dummy server
'''
DETAILS = _load_state()
DETAILS['services'][name] = 'running'
_save_state(DETAILS)
return 'running'
def service_stop(name):
'''
Stop a "service" on the dummy server
'''
DETAILS = _load_state()
DETAILS['services'][name] = 'stopped'
_save_state(DETAILS)
return 'stopped'
def service_restart(name):
'''
Restart a "service" on the REST server
'''
return True
def service_list():
'''
List "services" on the REST server
'''
DETAILS = _load_state()
return DETAILS['services'].keys()
def service_status(name):
'''
Check if a service is running on the REST server
'''
DETAILS = _load_state()
if DETAILS['services'][name] == 'running':
return {'comment': 'running'}
else:
return {'comment': 'stopped'}
def package_list():
'''
List "packages" installed on the REST server
'''
DETAILS = _load_state()
return DETAILS['packages']
def package_install(name, **kwargs):
'''
Install a "package" on the REST server
'''
DETAILS = _load_state()
if kwargs.get('version', False):
version = kwargs['version']
else:
version = '1.0'
DETAILS['packages'][name] = version
_save_state(DETAILS)
return {name: version}
def upgrade():
'''
"Upgrade" packages
'''
DETAILS = _load_state()
pkgs = uptodate()
DETAILS['packages'] = pkgs
_save_state(DETAILS)
return pkgs
def uptodate():
'''
Call the REST endpoint to see if the packages on the "server" are up to date.
'''
DETAILS = _load_state()
for p in DETAILS['packages']:
version_float = float(DETAILS['packages'][p])
version_float = version_float + 1.0
DETAILS['packages'][p] = str(version_float)
return DETAILS['packages']
def package_remove(name):
'''
Remove a "package" on the REST server
'''
DETAILS = _load_state()
DETAILS['packages'].pop(name)
_save_state(DETAILS)
return DETAILS['packages']
def package_status(name):
'''
Check the installation status of a package on the REST server
'''
DETAILS = _load_state()
if name in DETAILS['packages']:
return {name: DETAILS['packages'][name]}
def ping():
'''
Degenerate ping
'''
log.debug('dummy proxy returning ping')
return True
def shutdown(opts):
'''
For this proxy shutdown is a no-op
'''
log.debug('dummy proxy shutdown() called...')
DETAILS = _load_state()
if 'filename' in DETAILS:
os.unlink(DETAILS['filename'])
def test_from_state():
'''
Test function so we have something to call from a state
:return:
'''
log.debug('test_from_state called')
return 'testvalue'

View File

@ -271,7 +271,7 @@ def proxy_minion_process(queue):
sys.exit(status)
def salt_proxy_minion():
def salt_proxy():
'''
Start a proxy minion.
'''

View File

@ -1675,7 +1675,9 @@ def is_proxy():
# then this will fail.
is_proxy = False
try:
if 'salt-proxy' in main.__file__:
# Changed this from 'salt-proxy in main...' to 'proxy in main...'
# to support the testsuite's temp script that is called 'cli_salt_proxy'
if 'proxy' in main.__file__:
is_proxy = True
except AttributeError:
pass

View File

@ -1,9 +1,11 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
'''
This script is used to kick off a salt proxy minion daemon
'''
from salt.scripts import salt_proxy_minion
from __future__ import absolute_import
from salt.scripts import salt_proxy
from salt.utils import is_windows
from multiprocessing import freeze_support
@ -23,4 +25,4 @@ if __name__ == '__main__':
# This handles the bootstrapping code that is included with frozen
# scripts. It is a no-op on unfrozen code.
freeze_support()
salt_proxy_minion()
salt_proxy()

View File

@ -650,9 +650,31 @@ class SaltMinion(SaltDaemonScriptBase):
return set([self.config['id']])
class SaltProxy(SaltDaemonScriptBase):
'''
Class which runs the salt-proxy daemon
'''
cli_script_name = 'salt-proxy'
def get_script_args(self):
#script_args = ['-l', 'debug', '--proxyid', 'testproxy']
script_args = ['-l', 'quiet', '--proxyid', 'testproxy']
if salt.utils.is_windows() is False:
script_args.append('--disable-keepalive')
return script_args
def get_check_ports(self):
if salt.utils.is_windows():
return set([self.config['tcp_pub_port'],
self.config['tcp_pull_port']])
else:
return set([self.config['id']])
class SaltMaster(SaltDaemonScriptBase):
'''
Class which runs the salt-minion daemon
Class which runs the salt-master daemon
'''
cli_script_name = 'salt-master'
@ -791,8 +813,16 @@ class TestDaemon(object):
self.smaster_process.display_name = 'syndic salt-master'
self.syndic_process = SaltSyndic(self.syndic_opts, TMP_SYNDIC_MINION_CONF_DIR, SCRIPT_DIR)
self.syndic_process.display_name = 'salt-syndic'
for process in (self.master_process, self.minion_process, self.sub_minion_process,
self.smaster_process, self.syndic_process):
processes_to_start = [self.master_process, self.minion_process, self.sub_minion_process,
self.smaster_process, self.syndic_process]
if self.parser.options.proxy or (getattr(self.parser.options, 'name', False)
and any(['proxy' in item
for item in self.parser.options.name])):
self.proxy_process = SaltProxy(self.proxy_opts, TMP_CONF_DIR, SCRIPT_DIR)
self.proxy_process.display_name = 'salt-proxy'
processes_to_start.append(self.proxy_process)
for process in processes_to_start:
sys.stdout.write(
' * {LIGHT_YELLOW}Starting {0} ... {ENDC}'.format(
process.display_name,
@ -1020,6 +1050,7 @@ class TestDaemon(object):
* syndic
* syndic_master
* sub_minion
* proxy
'''
return RUNTIME_CONFIGS[role]
@ -1106,6 +1137,16 @@ class TestDaemon(object):
syndic_master_opts['root_dir'] = os.path.join(TMP, 'rootdir-syndic-master')
syndic_master_opts['pki_dir'] = os.path.join(TMP, 'rootdir-syndic-master', 'pki', 'master')
# This proxy connects to master
proxy_opts = salt.config._read_conf_file(os.path.join(CONF_DIR, 'proxy'))
proxy_opts['cachedir'] = os.path.join(TMP, 'rootdir', 'cache')
proxy_opts['user'] = running_tests_user
proxy_opts['config_dir'] = TMP_CONF_DIR
proxy_opts['root_dir'] = os.path.join(TMP, 'rootdir')
proxy_opts['pki_dir'] = os.path.join(TMP, 'rootdir', 'pki')
proxy_opts['hosts.file'] = os.path.join(TMP, 'rootdir', 'hosts')
proxy_opts['aliases.file'] = os.path.join(TMP, 'rootdir', 'aliases')
if transport == 'raet':
master_opts['transport'] = 'raet'
master_opts['raet_port'] = 64506
@ -1178,7 +1219,7 @@ class TestDaemon(object):
syndic_opts[optname] = optname_path
syndic_master_opts[optname] = optname_path
for conf in (master_opts, minion_opts, sub_minion_opts, syndic_opts, syndic_master_opts):
for conf in (master_opts, minion_opts, sub_minion_opts, syndic_opts, syndic_master_opts, proxy_opts):
if 'log_handlers_dirs' not in conf:
conf['log_handlers_dirs'] = []
conf['log_handlers_dirs'].insert(0, LOG_HANDLERS_DIR)
@ -1186,7 +1227,7 @@ class TestDaemon(object):
# ----- Transcribe Configuration ---------------------------------------------------------------------------->
for entry in os.listdir(CONF_DIR):
if entry in ('master', 'minion', 'sub_minion', 'syndic', 'syndic_master'):
if entry in ('master', 'minion', 'sub_minion', 'syndic', 'syndic_master', 'proxy'):
# These have runtime computed values and will be handled
# differently
continue
@ -1202,7 +1243,7 @@ class TestDaemon(object):
os.path.join(TMP_CONF_DIR, entry)
)
for entry in ('master', 'minion', 'sub_minion', 'syndic', 'syndic_master'):
for entry in ('master', 'minion', 'sub_minion', 'syndic', 'syndic_master', 'proxy'):
computed_config = copy.deepcopy(locals()['{0}_opts'.format(entry)])
with salt.utils.fopen(os.path.join(TMP_CONF_DIR, entry), 'w') as fp_:
fp_.write(yaml.dump(computed_config, default_flow_style=False))
@ -1226,6 +1267,7 @@ class TestDaemon(object):
# ----- Verify Environment ---------------------------------------------------------------------------------->
master_opts = salt.config.master_config(os.path.join(TMP_CONF_DIR, 'master'))
minion_opts = salt.config.minion_config(os.path.join(TMP_CONF_DIR, 'minion'))
proxy_opts = salt.config.proxy_config(os.path.join(TMP_CONF_DIR, 'proxy'))
syndic_opts = salt.config.syndic_config(
os.path.join(TMP_SYNDIC_MINION_CONF_DIR, 'master'),
os.path.join(TMP_SYNDIC_MINION_CONF_DIR, 'minion'),
@ -1238,6 +1280,7 @@ class TestDaemon(object):
RUNTIME_CONFIGS['syndic'] = freeze(syndic_opts)
RUNTIME_CONFIGS['sub_minion'] = freeze(sub_minion_opts)
RUNTIME_CONFIGS['syndic_master'] = freeze(syndic_master_opts)
RUNTIME_CONFIGS['proxy'] = freeze(proxy_opts)
verify_env([os.path.join(master_opts['pki_dir'], 'minions'),
os.path.join(master_opts['pki_dir'], 'minions_pre'),
@ -1284,6 +1327,7 @@ class TestDaemon(object):
cls.master_opts = master_opts
cls.minion_opts = minion_opts
cls.proxy_opts = proxy_opts
cls.sub_minion_opts = sub_minion_opts
cls.syndic_opts = syndic_opts
cls.syndic_master_opts = syndic_master_opts
@ -1295,6 +1339,8 @@ class TestDaemon(object):
'''
self.sub_minion_process.terminate()
self.minion_process.terminate()
if hasattr(self, 'proxy_process'):
self.proxy_process.terminate()
self.master_process.terminate()
try:
self.syndic_process.terminate()

View File

@ -0,0 +1,50 @@
# basic config
# Connects to master
master: localhost
master_port: 64506
interface: 127.0.0.1
tcp_pub_port: 64510
tcp_pull_port: 64511
sock_dir: proxy_sock
id: proxytest
open_mode: True
log_file: proxy.log
log_level_logfile: debug
pidfile: proxy.pid
# module extension
test.foo: baz
integration.test: True
# Grains addons
grains:
test_grain: cheese
script: grail
alot: many
planets:
- mercury
- venus
- earth
- mars
level1:
level2: foo
companions:
one:
- susan
- ian
- barbara
config_test:
spam: eggs
mine_functions:
test.ping: []
# sdb env module
osenv:
driver: env
add_proxymodule_to_opts: False
proxy:
proxytype: dummy

View File

@ -0,0 +1 @@
# -*- coding: utf-8 -*-

View File

@ -0,0 +1,78 @@
# -*- coding: utf-8 -*-
'''
Simple Smoke Tests for Connected Proxy Minion
'''
# Import Python libs
from __future__ import absolute_import
# Import Salt Testing libs
from salttesting.helpers import ensure_in_syspath
ensure_in_syspath('../')
# Import Salt libs
import integration
class ProxyMinionSimpleTestCase(integration.ModuleCase):
'''
Test minion blackout functionality
'''
def test_can_it_ping(self):
'''
Ensure the proxy can ping
'''
ret = self.run_function('test.ping', minion_tgt='proxytest')
self.assertEqual(ret, True)
def test_list_pkgs(self):
'''
Package test 1, really just tests that the virtual function capability
is working OK.
'''
ret = self.run_function('pkg.list_pkgs', minion_tgt='proxytest')
self.assertIn('coreutils', ret)
self.assertIn('apache', ret)
self.assertIn('redbull', ret)
def test_install_pkgs(self):
'''
Package test 2, really just tests that the virtual function capability
is working OK.
'''
ret = self.run_function('pkg.install', ['thispkg'], minion_tgt='proxytest')
self.assertEqual(ret['thispkg'], '1.0')
ret = self.run_function('pkg.list_pkgs', minion_tgt='proxytest')
self.assertEqual(ret['apache'], '2.4')
self.assertEqual(ret['redbull'], '999.99')
self.assertEqual(ret['thispkg'], '1.0')
def test_remove_pkgs(self):
ret = self.run_function('pkg.remove', ['apache'], minion_tgt='proxytest')
self.assertNotIn('apache', ret)
def test_upgrade(self):
ret = self.run_function('pkg.upgrade', minion_tgt='proxytest')
self.assertEqual(ret['coreutils']['new'], '2.0')
self.assertEqual(ret['redbull']['new'], '1000.99')
def test_service_list(self):
ret = self.run_function('service.list', minion_tgt='proxytest')
self.assertIn('ntp', ret)
def test_service_stop(self):
ret = self.run_function('service.stop', ['ntp'], minion_tgt='proxytest')
ret = self.run_function('service.status', ['ntp'], minion_tgt='proxytest')
self.assertFalse(ret)
def test_service_start(self):
ret = self.run_function('service.start', ['samba'], minion_tgt='proxytest')
ret = self.run_function('service.status', ['samba'], minion_tgt='proxytest')
self.assertTrue(ret)
if __name__ == '__main__':
from integration import run_tests
run_tests(ProxyMinionSimpleTestCase, needs_daemon=True)

View File

@ -111,6 +111,9 @@ TEST_SUITES = {
'reactor':
{'display_name': 'Reactor',
'path': 'integration/reactor'},
'proxy':
{'display_name': 'Proxy',
'path': 'integration/proxy'},
}
@ -119,7 +122,8 @@ class SaltTestsuiteParser(SaltCoverageTestingParser):
support_destructive_tests_selection = True
source_code_basedir = SALT_ROOT
def _get_suites(self, include_unit=False, include_cloud_provider=False):
def _get_suites(self, include_unit=False, include_cloud_provider=False,
include_proxy=False):
'''
Return a set of all test suites except unit and cloud provider tests
unless requested
@ -129,24 +133,30 @@ class SaltTestsuiteParser(SaltCoverageTestingParser):
suites -= set(['unit'])
if not include_cloud_provider:
suites -= set(['cloud_provider'])
if not include_proxy:
suites -= set(['proxy'])
return suites
def _check_enabled_suites(self, include_unit=False, include_cloud_provider=False):
def _check_enabled_suites(self, include_unit=False,
include_cloud_provider=False, include_proxy=False):
'''
Query whether test suites have been enabled
'''
suites = self._get_suites(include_unit=include_unit,
include_cloud_provider=include_cloud_provider)
include_cloud_provider=include_cloud_provider,
include_proxy=include_proxy)
return any([getattr(self.options, suite) for suite in suites])
def _enable_suites(self, include_unit=False, include_cloud_provider=False):
def _enable_suites(self, include_unit=False, include_cloud_provider=False,
include_proxy=False):
'''
Enable test suites for current test run
'''
suites = self._get_suites(include_unit=include_unit,
include_cloud_provider=include_cloud_provider)
include_cloud_provider=include_cloud_provider,
include_proxy=include_proxy)
for suite in suites:
setattr(self.options, suite, True)
@ -347,6 +357,16 @@ class SaltTestsuiteParser(SaltCoverageTestingParser):
help='Run salt-api tests'
)
self.test_selection_group.add_option(
'-P',
'--proxy',
'--proxy-tests',
dest='proxy',
action='store_true',
default=False,
help='Run salt-proxy tests'
)
def validate_options(self):
if self.options.cloud_provider:
# Turn on expensive tests execution
@ -367,7 +387,9 @@ class SaltTestsuiteParser(SaltCoverageTestingParser):
# When no tests are specifically enumerated on the command line, setup
# a default run: +unit -cloud_provider
if not self.options.name and not \
self._check_enabled_suites(include_unit=True, include_cloud_provider=True):
self._check_enabled_suites(include_unit=True,
include_cloud_provider=True,
include_proxy=True):
self._enable_suites(include_unit=True)
self.start_coverage(
@ -405,6 +427,7 @@ class SaltTestsuiteParser(SaltCoverageTestingParser):
print_header(' * Salt daemons started')
master_conf = TestDaemon.config('master')
minion_conf = TestDaemon.config('minion')
proxy_conf = TestDaemon.config('proxy')
sub_minion_conf = TestDaemon.config('sub_minion')
syndic_conf = TestDaemon.config('syndic')
syndic_master_conf = TestDaemon.config('syndic_master')
@ -445,6 +468,15 @@ class SaltTestsuiteParser(SaltCoverageTestingParser):
print('tcp pull port: {0}'.format(sub_minion_conf['tcp_pull_port']))
print('\n')
print_header(' * Proxy Minion configuration values', top=True)
print('interface: {0}'.format(proxy_conf['interface']))
print('master: {0}'.format(proxy_conf['master']))
print('master port: {0}'.format(proxy_conf['master_port']))
if minion_conf['ipc_mode'] == 'tcp':
print('tcp pub port: {0}'.format(proxy_conf['tcp_pub_port']))
print('tcp pull port: {0}'.format(proxy_conf['tcp_pull_port']))
print('\n')
print_header(' Your client configuration is at {0}'.format(TestDaemon.config_location()))
print('To access the minion: salt -c {0} minion test.ping'.format(TestDaemon.config_location()))
@ -534,7 +566,7 @@ class SaltTestsuiteParser(SaltCoverageTestingParser):
status = []
# Return an empty status if no tests have been enabled
if not self._check_enabled_suites(include_cloud_provider=True) and not self.options.name:
if not self._check_enabled_suites(include_cloud_provider=True, include_proxy=True) and not self.options.name:
return status
with TestDaemon(self):