Merge branch '2016.11' into 'nitrogen'

Conflicts:
  - salt/config/__init__.py
  - salt/modules/elasticsearch.py
  - tests/integration/__init__.py
This commit is contained in:
rallytime 2017-05-23 10:36:41 -06:00
commit 616ac7289b
17 changed files with 822 additions and 51 deletions

View file

@ -1602,13 +1602,10 @@ 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.
# These are merged with DEFAULT_MINION_OPTS since many of them also apply here.
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': True,
'append_minionid_config_dirs': ['cachedir', 'pidfile', 'default_include'],
@ -1622,8 +1619,10 @@ DEFAULT_PROXY_MINION_OPTS = {
'proxy_keep_alive': True, # by default will try to keep alive the connection
'proxy_keep_alive_interval': 1 # frequency of the proxy keepalive in minutes
'pki_dir': os.path.join(salt.syspaths.CONFIG_DIR, 'pki', 'proxy'),
'cachedir': os.path.join(salt.syspaths.CACHE_DIR, 'proxy'),
'sock_dir': os.path.join(salt.syspaths.SOCK_DIR, 'proxy'),
}
# ----- Salt Cloud Configuration Defaults ----------------------------------->
DEFAULT_CLOUD_OPTS = {
'verify_env': True,
@ -2113,9 +2112,6 @@ def minion_config(path,
if defaults is None:
defaults = DEFAULT_MINION_OPTS.copy()
if path is not None and path.endswith('proxy'):
defaults.update(DEFAULT_PROXY_MINION_OPTS)
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
@ -2145,6 +2141,58 @@ 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 defaults is None:
defaults = DEFAULT_MINION_OPTS.copy()
defaults.update(DEFAULT_PROXY_MINION_OPTS)
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

@ -13,8 +13,8 @@ import os
import re
import shlex
import stat
import subprocess
import tarfile
import tempfile
import zipfile
try:
from shlex import quote as _quote # pylint: disable=E0611
@ -164,7 +164,10 @@ def list_(name,
files = []
links = []
try:
with contextlib.closing(tarfile.open(cached)) as tar_archive:
open_kwargs = {'name': cached} \
if not isinstance(cached, subprocess.Popen) \
else {'fileobj': cached.stdout, 'mode': 'r|'}
with contextlib.closing(tarfile.open(**open_kwargs)) as tar_archive:
for member in tar_archive.getmembers():
if member.issym():
links.append(member.name)
@ -175,7 +178,15 @@ def list_(name,
return dirs, files, links
except tarfile.ReadError:
if not failhard:
if failhard:
if isinstance(cached, subprocess.Popen):
stderr = cached.communicate()[1]
if cached.returncode != 0:
raise CommandExecutionError(
'Failed to decompress {0}'.format(name),
info={'error': stderr}
)
else:
if not salt.utils.which('tar'):
raise CommandExecutionError('\'tar\' command not available')
if decompress_cmd is not None:
@ -194,29 +205,12 @@ def list_(name,
decompress_cmd = 'xz --decompress --stdout'
if decompress_cmd:
fd, decompressed = tempfile.mkstemp()
os.close(fd)
try:
cmd = '{0} {1} > {2}'.format(decompress_cmd,
_quote(cached),
_quote(decompressed))
result = __salt__['cmd.run_all'](cmd, python_shell=True)
if result['retcode'] != 0:
raise CommandExecutionError(
'Failed to decompress {0}'.format(name),
info={'error': result['stderr']}
)
return _list_tar(name, decompressed, None, True)
finally:
try:
os.remove(decompressed)
except OSError as exc:
if exc.errno != errno.ENOENT:
log.warning(
'Failed to remove intermediate '
'decompressed archive %s: %s',
decompressed, exc.__str__()
)
decompressed = subprocess.Popen(
'{0} {1}'.format(decompress_cmd, _quote(cached)),
shell=True,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
return _list_tar(name, decompressed, None, True)
raise CommandExecutionError(
'Unable to list contents of {0}. If this is an XZ-compressed tar '

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'

View file

@ -93,6 +93,20 @@ def set_(name, value, **kwargs):
if 'jail' in kwargs:
cmd += ' -j '+kwargs['jail']
# This is here because the YAML parser likes to convert the string literals
# YES, NO, Yes, No, True, False, etc. to boolean types. However, in this case,
# we will check to see if that happened and replace it with "YES" or "NO" because
# those items are accepted in sysrc.
if type(value) == bool:
if value:
value = "YES"
else:
value = "NO"
# This is here for the same reason, except for numbers
if type(value) == int:
value = str(value)
cmd += ' '+name+"=\""+value+"\""
sysrcs = __salt__['cmd.run'](cmd)
@ -105,9 +119,6 @@ def set_(name, value, **kwargs):
newval = sysrc.split(': ')[2].split(" -> ")[1]
if rcfile not in ret:
ret[rcfile] = {}
#ret[rcfile][var] = {}
#ret[rcfile][var]['old'] = oldval
#ret[rcfile][var]['new'] = newval
ret[rcfile][var] = newval
return ret

237
salt/proxy/dummy.py Normal file
View file

@ -0,0 +1,237 @@
# -*- 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):
pck = open(FILENAME, 'wb')
pickle.dump(details, pck)
pck.close()
def _load_state():
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

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

View file

@ -1684,7 +1684,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

@ -1774,7 +1774,7 @@ class ProxyMinionOptionParser(six.with_metaclass(OptionParserMeta,
except AttributeError:
minion_id = None
return config.minion_config(self.get_config_file_path(),
return config.proxy_config(self.get_config_file_path(),
cache_minion_id=False,
minion_id=minion_id)

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

@ -661,6 +661,7 @@ class TestDaemon(object):
* syndic
* syndic_master
* sub_minion
* proxy
'''
return RUNTIME_VARS.RUNTIME_CONFIGS[role]
@ -742,6 +743,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
@ -853,7 +864,7 @@ class TestDaemon(object):
os.path.join(RUNTIME_VARS.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(RUNTIME_VARS.TMP_CONF_DIR, entry), 'w') as fp_:
fp_.write(yaml.dump(computed_config, default_flow_style=False))
@ -938,6 +949,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
@ -949,6 +961,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,52 @@
# -*- coding: utf-8 -*-
# Import python libs
from __future__ import absolute_import
import sys
# Import Salt Testing libs
from salttesting import skipIf
from salttesting.helpers import ensure_in_syspath, destructiveTest
ensure_in_syspath('../../')
# Import salt libs
import integration
class SysrcModuleTest(integration.ModuleCase):
def setUp(self):
super(SysrcModuleTest, self).setUp()
ret = self.run_function('cmd.has_exec', ['sysrc'])
if not ret:
self.skipTest('sysrc not found')
@skipIf(not sys.platform.startswith('freebsd'), 'FreeBSD specific')
def test_show(self):
ret = self.run_function('sysrc.get')
self.assertIsInstance(ret, dict, 'sysrc.get returned wrong type, expecting dictionary')
self.assertIn('/etc/rc.conf', ret, 'sysrc.get should have an rc.conf key in it.')
@skipIf(not sys.platform.startswith('freebsd'), 'FreeBSD specific')
@destructiveTest
def test_set(self):
ret = self.run_function('sysrc.set', ['test_var', '1'])
self.assertIsInstance(ret, dict, 'sysrc.get returned wrong type, expecting dictionary')
self.assertIn('/etc/rc.conf', ret, 'sysrc.set should have an rc.conf key in it.')
self.assertIn('1', ret['/etc/rc.conf']['test_var'], 'sysrc.set should return the value it set.')
ret = self.run_function('sysrc.remove', ['test_var'])
self.assertEqual('test_var removed', ret)
@skipIf(not sys.platform.startswith('freebsd'), 'FreeBSD specific')
@destructiveTest
def test_set_bool(self):
ret = self.run_function('sysrc.set', ['test_var', True])
self.assertIsInstance(ret, dict, 'sysrc.get returned wrong type, expecting dictionary')
self.assertIn('/etc/rc.conf', ret, 'sysrc.set should have an rc.conf key in it.')
self.assertIn('YES', ret['/etc/rc.conf']['test_var'], 'sysrc.set should return the value it set.')
ret = self.run_function('sysrc.remove', ['test_var'])
self.assertEqual('test_var removed', ret)
if __name__ == '__main__':
from integration import run_tests
run_tests(SysrcModuleTest)

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

@ -154,6 +154,9 @@ TEST_SUITES = {
'reactor':
{'display_name': 'Reactor',
'path': 'integration/reactor'},
'proxy':
{'display_name': 'Proxy',
'path': 'integration/proxy'},
}
@ -162,7 +165,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
@ -172,24 +176,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)
@ -399,6 +409,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
@ -430,7 +450,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(
@ -471,6 +493,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')
@ -511,6 +534,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()))
@ -609,7 +641,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):

View file

@ -556,7 +556,7 @@ class ProxyMinionOptionParserTestCase(LogSettingsParserTests):
# Log file
self.log_file = '/tmp/salt_proxy_minion_parser_test'
# Function to patch
self.config_func = 'salt.config.minion_config'
self.config_func = 'salt.config.proxy_config'
# Mock log setup
self.setup_log()