Merge branch '2016.3' into '2016.11'

Conflicts:
  - tests/unit/config/config_test.py
This commit is contained in:
rallytime 2016-12-09 11:45:14 -07:00
commit 627242ab5d
5 changed files with 137 additions and 17 deletions

View file

@ -1719,7 +1719,7 @@ def _absolute_path(path, relative_to=None):
return path
def load_config(path, env_var, default_path=None):
def load_config(path, env_var, default_path=None, exit_on_config_errors=True):
'''
Returns configuration dict from parsing either the file described by
``path`` or the environment variable described by ``env_var`` as YAML.
@ -1767,17 +1767,20 @@ def load_config(path, env_var, default_path=None):
ifile.readline() # skip first line
out.write(ifile.read())
opts = {}
if salt.utils.validate.path.is_readable(path):
try:
opts = _read_conf_file(path)
opts['conf_file'] = path
return opts
except salt.exceptions.SaltConfigurationError as error:
log.error(error)
sys.exit(salt.defaults.exitcodes.EX_GENERIC)
if exit_on_config_errors:
sys.exit(salt.defaults.exitcodes.EX_GENERIC)
else:
log.debug('Missing configuration file: {0}'.format(path))
log.debug('Missing configuration file: {0}'.format(path))
return {}
return opts
def include_config(include, orig_path, verbose, exit_on_config_errors=False):
@ -1822,6 +1825,9 @@ def include_config(include, orig_path, verbose, exit_on_config_errors=False):
log.error(error)
if exit_on_config_errors:
sys.exit(salt.defaults.exitcodes.EX_GENERIC)
else:
# Initialize default config if we wish to skip config errors
opts = {}
include = opts.get('include', [])
if include:
@ -3213,8 +3219,10 @@ def master_config(path, env_var='SALT_MASTER_CONFIG', defaults=None, exit_on_con
defaults['default_include'])
include = overrides.get('include', [])
overrides.update(include_config(default_include, path, verbose=False), exit_on_config_errors=exit_on_config_errors)
overrides.update(include_config(include, path, verbose=True), exit_on_config_errors=exit_on_config_errors)
overrides.update(include_config(default_include, path, verbose=False),
exit_on_config_errors=exit_on_config_errors)
overrides.update(include_config(include, path, verbose=True),
exit_on_config_errors=exit_on_config_errors)
opts = apply_master_config(overrides, defaults)
_validate_opts(opts)
# If 'nodegroups:' is uncommented in the master config file, and there are

View file

@ -331,7 +331,8 @@ def get_url(path, dest='', saltenv='base', makedirs=False):
def get_file_str(path, saltenv='base'):
'''
Return the contents of a file from a URL
Download a file from a URL to the Minion cache directory and return the
contents of that file
Returns ``False`` if Salt was unable to cache a file from a URL.
@ -351,8 +352,9 @@ def get_file_str(path, saltenv='base'):
def cache_file(path, saltenv='base'):
'''
Used to cache a single file on the salt-minion
Returns the location of the new cached file on the minion
Used to cache a single file on the Minion
Returns the location of the new cached file on the Minion.
CLI Example:
@ -413,9 +415,9 @@ def cache_file(path, saltenv='base'):
def cache_files(paths, saltenv='base'):
'''
Used to gather many files from the master, the gathered files will be
Used to gather many files from the Master, the gathered files will be
saved in the minion cachedir reflective to the paths retrieved from the
master.
Master
CLI Example:

View file

@ -14,7 +14,6 @@ import integration
from salt.config import cloud_providers_config
# Import Salt Testing Libs
from salttesting import skipIf
from salttesting.helpers import ensure_in_syspath, expensiveTest
ensure_in_syspath('../../../')
@ -37,7 +36,6 @@ INSTANCE_NAME = __random_name()
PROVIDER_NAME = 'ec2'
@skipIf(True, 'Skipping until we can figure out why the testrunner bails.')
class EC2Test(integration.ShellCase):
'''
Integration tests for the EC2 cloud provider in Salt-Cloud

View file

@ -149,6 +149,8 @@ class CPModuleTest(integration.ModuleCase):
self.assertIn('empty', os.listdir(os.path.join(tgt, 'grail')))
self.assertIn('scene', os.listdir(os.path.join(tgt, 'grail', '36')))
# cp.get_url tests
def test_get_url(self):
'''
cp.get_url with salt:// source given
@ -305,6 +307,62 @@ class CPModuleTest(integration.ModuleCase):
self.assertIn('KNIGHT: They\'re nervous, sire.', ret)
self.assertNotIn('bacon', ret)
# cp.get_file_str tests
def test_get_file_str_salt(self):
'''
cp.get_file_str with salt:// source given
'''
src = 'salt://grail/scene33'
ret = self.run_function(
'cp.get_file_str',
[
src,
])
self.assertIn('KNIGHT: They\'re nervous, sire.', ret)
def test_get_file_str_nonexistent_source(self):
'''
cp.get_file_str with nonexistent salt:// source given
'''
src = 'salt://grail/nonexistent_scene'
ret = self.run_function(
'cp.get_file_str',
[
src,
])
self.assertEqual(ret, False)
def test_get_file_str_https(self):
'''
cp.get_file_str with https:// source given
'''
src = 'https://repo.saltstack.com/index.html'
ret = self.run_function(
'cp.get_file_str',
[
src,
])
self.assertIn('Bootstrap', ret)
self.assertIn('Debian', ret)
self.assertIn('Windows', ret)
self.assertNotIn('AYBABTU', ret)
def test_get_file_str_local(self):
'''
cp.get_file_str with file:// source given
'''
src = os.path.join('file://', integration.FILES, 'file/base/file.big')
ret = self.run_function(
'cp.get_file_str',
[
src,
])
self.assertIn('KNIGHT: They\'re nervous, sire.', ret)
self.assertNotIn('bacon', ret)
# caching tests
def test_cache_file(self):
'''
cp.cache_file

View file

@ -18,17 +18,20 @@ import tempfile
from salttesting import TestCase
from salttesting.mock import MagicMock, patch
from salttesting.helpers import ensure_in_syspath
from salt.exceptions import CommandExecutionError
ensure_in_syspath('../')
# Import salt libs
# Import Salt libs
import salt.minion
import salt.utils
import salt.utils.network
import integration
from salt import config as sconfig
from salt.exceptions import SaltCloudConfigError
from salt.exceptions import (
CommandExecutionError,
SaltConfigurationError,
SaltCloudConfigError
)
# Import Third-Party Libs
import yaml
@ -65,6 +68,13 @@ def _unhandled_mock_read(filename):
raise CommandExecutionError('Unhandled mock read for {0}'.format(filename))
def _salt_configuration_error(filename):
'''
Raise an error to indicate error in the Salt configuration file
'''
raise SaltConfigurationError('Configuration error in {0}'.format(filename))
class ConfigTestCase(TestCase, integration.AdaptedConfigurationTestCaseMixIn):
def test_sha256_is_default_for_master(self):
@ -905,6 +915,50 @@ class ConfigTestCase(TestCase, integration.AdaptedConfigurationTestCaseMixIn):
# <---- Salt Cloud Configuration Tests ---------------------------------------------
def test_include_config_without_errors(self):
'''
Tests that include_config function returns valid configuration
'''
include_file = 'minion.d/my.conf'
config_path = '/etc/salt/minion'
config_opts = {'id': 'myminion.example.com'}
with patch('glob.glob', MagicMock(return_value=include_file)):
with patch('salt.config._read_conf_file', MagicMock(return_value=config_opts)):
configuration = sconfig.include_config(include_file, config_path, verbose=False)
self.assertEqual(config_opts, configuration)
def test_include_config_with_errors(self):
'''
Tests that include_config function returns valid configuration even on errors
'''
include_file = 'minion.d/my.conf'
config_path = '/etc/salt/minion'
config_opts = {}
with patch('glob.glob', MagicMock(return_value=include_file)):
with patch('salt.config._read_conf_file', _salt_configuration_error):
configuration = sconfig.include_config(include_file, config_path, verbose=False)
self.assertEqual(config_opts, configuration)
def test_include_config_with_errors_exit(self):
'''
Tests that include_config exits on errors
'''
include_file = 'minion.d/my.conf'
config_path = '/etc/salt/minion'
with patch('glob.glob', MagicMock(return_value=include_file)):
with patch('salt.config._read_conf_file', _salt_configuration_error):
with self.assertRaises(SystemExit):
sconfig.include_config(include_file,
config_path,
verbose=False,
exit_on_config_errors=True)
if __name__ == '__main__':
from integration import run_tests
run_tests(ConfigTestCase, needs_daemon=False)