mirror of
https://github.com/valitydev/salt.git
synced 2024-11-07 17:09:03 +00:00
Merge pull request #39727 from terminalmage/issue39627
salt.modules.state: check gathered pillar for errors instead of in-memory pillar
This commit is contained in:
commit
7dfc4b572a
@ -31,7 +31,7 @@ import salt.state
|
||||
import salt.utils
|
||||
import salt.utils.jid
|
||||
import salt.utils.url
|
||||
from salt.exceptions import SaltInvocationError
|
||||
from salt.exceptions import CommandExecutionError, SaltInvocationError
|
||||
from salt.runners.state import orchestrate as _orchestrate
|
||||
|
||||
# Import 3rd-party libs
|
||||
@ -98,14 +98,15 @@ def _set_retcode(ret):
|
||||
__context__['retcode'] = 2
|
||||
|
||||
|
||||
def _check_pillar(kwargs):
|
||||
def _check_pillar(kwargs, pillar=None):
|
||||
'''
|
||||
Check the pillar for errors, refuse to run the state if there are errors
|
||||
in the pillar and return the pillar errors
|
||||
'''
|
||||
if kwargs.get('force'):
|
||||
return True
|
||||
if '_errors' in __pillar__:
|
||||
pillar_dict = pillar if pillar is not None else __pillar__
|
||||
if '_errors' in pillar_dict:
|
||||
return False
|
||||
return True
|
||||
|
||||
@ -379,6 +380,12 @@ def template(tem, queue=False, **kwargs):
|
||||
if conflict is not None:
|
||||
return conflict
|
||||
st_ = salt.state.HighState(__opts__, context=__context__)
|
||||
|
||||
if not _check_pillar(kwargs, st_.opts['pillar']):
|
||||
__context__['retcode'] = 5
|
||||
raise CommandExecutionError('Pillar failed to render',
|
||||
info=st_.opts['pillar']['_errors'])
|
||||
|
||||
if not tem.endswith('.sls'):
|
||||
tem = '{sls}.sls'.format(sls=tem)
|
||||
high_state, errors = st_.render_state(tem, saltenv, '', None, local=True)
|
||||
@ -802,6 +809,12 @@ def highstate(test=None,
|
||||
pillar_enc=pillar_enc,
|
||||
mocked=kwargs.get('mock', False))
|
||||
|
||||
if not _check_pillar(kwargs, st_.opts['pillar']):
|
||||
__context__['retcode'] = 5
|
||||
err = ['Pillar failed to render with the following messages:']
|
||||
err += __pillar__['_errors']
|
||||
return err
|
||||
|
||||
st_.push_active()
|
||||
ret = {}
|
||||
orchestration_jid = kwargs.get('orchestration_jid')
|
||||
@ -967,11 +980,6 @@ def sls(mods,
|
||||
__context__['retcode'] = 1
|
||||
return disabled
|
||||
|
||||
if not _check_pillar(kwargs):
|
||||
__context__['retcode'] = 5
|
||||
err = ['Pillar failed to render with the following messages:']
|
||||
err += __pillar__['_errors']
|
||||
return err
|
||||
orig_test = __opts__.get('test', None)
|
||||
opts = _get_opts(kwargs.get('localconfig'))
|
||||
|
||||
@ -1007,6 +1015,12 @@ def sls(mods,
|
||||
pillar_enc=pillar_enc,
|
||||
mocked=kwargs.get('mock', False))
|
||||
|
||||
if not _check_pillar(kwargs, st_.opts['pillar']):
|
||||
__context__['retcode'] = 5
|
||||
err = ['Pillar failed to render with the following messages:']
|
||||
err += __pillar__['_errors']
|
||||
return err
|
||||
|
||||
orchestration_jid = kwargs.get('orchestration_jid')
|
||||
umask = os.umask(0o77)
|
||||
if kwargs.get('cache'):
|
||||
@ -1093,11 +1107,6 @@ def top(topfn,
|
||||
conflict = _check_queue(queue, kwargs)
|
||||
if conflict is not None:
|
||||
return conflict
|
||||
if not _check_pillar(kwargs):
|
||||
__context__['retcode'] = 5
|
||||
err = ['Pillar failed to render with the following messages:']
|
||||
err += __pillar__['_errors']
|
||||
return err
|
||||
orig_test = __opts__.get('test', None)
|
||||
opts = _get_opts(kwargs.get('localconfig'))
|
||||
opts['test'] = _get_test_value(test, **kwargs)
|
||||
@ -1113,6 +1122,12 @@ def top(topfn,
|
||||
)
|
||||
|
||||
st_ = salt.state.HighState(opts, pillar, pillar_enc=pillar_enc, context=__context__)
|
||||
if not _check_pillar(kwargs, st_.opts['pillar']):
|
||||
__context__['retcode'] = 5
|
||||
err = ['Pillar failed to render with the following messages:']
|
||||
err += __pillar__['_errors']
|
||||
return err
|
||||
|
||||
st_.push_active()
|
||||
st_.opts['state_top'] = salt.utils.url.create(topfn)
|
||||
ret = {}
|
||||
@ -1163,6 +1178,12 @@ def show_highstate(queue=False, **kwargs):
|
||||
)
|
||||
|
||||
st_ = salt.state.HighState(__opts__, pillar, pillar_enc=pillar_enc)
|
||||
|
||||
if not _check_pillar(kwargs, st_.opts['pillar']):
|
||||
__context__['retcode'] = 5
|
||||
raise CommandExecutionError('Pillar failed to render',
|
||||
info=st_.opts['pillar']['_errors'])
|
||||
|
||||
st_.push_active()
|
||||
try:
|
||||
ret = st_.compile_highstate()
|
||||
@ -1187,6 +1208,12 @@ def show_lowstate(queue=False, **kwargs):
|
||||
assert False
|
||||
return conflict
|
||||
st_ = salt.state.HighState(__opts__)
|
||||
|
||||
if not _check_pillar(kwargs, st_.opts['pillar']):
|
||||
__context__['retcode'] = 5
|
||||
raise CommandExecutionError('Pillar failed to render',
|
||||
info=st_.opts['pillar']['_errors'])
|
||||
|
||||
st_.push_active()
|
||||
try:
|
||||
ret = st_.compile_low_chunks()
|
||||
@ -1227,6 +1254,13 @@ def sls_id(
|
||||
st_ = salt.state.HighState(opts, proxy=__proxy__)
|
||||
except NameError:
|
||||
st_ = salt.state.HighState(opts)
|
||||
|
||||
if not _check_pillar(kwargs, st_.opts['pillar']):
|
||||
__context__['retcode'] = 5
|
||||
err = ['Pillar failed to render with the following messages:']
|
||||
err += __pillar__['_errors']
|
||||
return err
|
||||
|
||||
if isinstance(mods, six.string_types):
|
||||
split_mods = mods.split(',')
|
||||
st_.push_active()
|
||||
@ -1289,6 +1323,12 @@ def show_low_sls(mods,
|
||||
if 'pillarenv' in kwargs:
|
||||
opts['pillarenv'] = kwargs['pillarenv']
|
||||
st_ = salt.state.HighState(opts)
|
||||
|
||||
if not _check_pillar(kwargs, st_.opts['pillar']):
|
||||
__context__['retcode'] = 5
|
||||
raise CommandExecutionError('Pillar failed to render',
|
||||
info=st_.opts['pillar']['_errors'])
|
||||
|
||||
if isinstance(mods, six.string_types):
|
||||
mods = mods.split(',')
|
||||
st_.push_active()
|
||||
@ -1355,6 +1395,12 @@ def show_sls(mods, saltenv='base', test=None, queue=False, **kwargs):
|
||||
opts['pillarenv'] = kwargs['pillarenv']
|
||||
|
||||
st_ = salt.state.HighState(opts, pillar, pillar_enc=pillar_enc)
|
||||
|
||||
if not _check_pillar(kwargs, st_.opts['pillar']):
|
||||
__context__['retcode'] = 5
|
||||
raise CommandExecutionError('Pillar failed to render',
|
||||
info=st_.opts['pillar']['_errors'])
|
||||
|
||||
if isinstance(mods, six.string_types):
|
||||
mods = mods.split(',')
|
||||
st_.push_active()
|
||||
@ -1399,6 +1445,12 @@ def show_top(queue=False, **kwargs):
|
||||
if conflict is not None:
|
||||
return conflict
|
||||
st_ = salt.state.HighState(opts)
|
||||
|
||||
if not _check_pillar(kwargs, st_.opts['pillar']):
|
||||
__context__['retcode'] = 5
|
||||
raise CommandExecutionError('Pillar failed to render',
|
||||
info=st_.opts['pillar']['_errors'])
|
||||
|
||||
errors = []
|
||||
top_ = st_.get_top()
|
||||
errors += st_.verify_tops(top_)
|
||||
|
@ -824,7 +824,9 @@ class Pillar(object):
|
||||
top, top_errors = self.get_top()
|
||||
if ext:
|
||||
if self.opts.get('ext_pillar_first', False):
|
||||
self.opts['pillar'], errors = self.ext_pillar({}, pillar_dirs)
|
||||
self.opts['pillar'], errors = self.ext_pillar(
|
||||
self.pillar_override,
|
||||
pillar_dirs)
|
||||
self.rend = salt.loader.render(self.opts, self.functions)
|
||||
matches = self.top_matches(top)
|
||||
pillar, errors = self.render_pillar(matches, errors=errors)
|
||||
|
@ -459,6 +459,7 @@ def _process_stack_cfg(cfg, stack, minion_id, pillar, namespace):
|
||||
for sub in namespace.split(':')[::-1]:
|
||||
obj = {sub: obj}
|
||||
stack = _merge_dict(stack, obj)
|
||||
log.info('Stack template "{0}" parsed'.format(path))
|
||||
except exceptions.TopLevelLookupException as e:
|
||||
log.info('Stack template "{0}" not found.'.format(path))
|
||||
continue
|
||||
|
@ -28,7 +28,7 @@ from salt.modules import state
|
||||
# Globals
|
||||
state.__salt__ = {}
|
||||
state.__context__ = {}
|
||||
state.__opts__ = {}
|
||||
state.__opts__ = {'cachedir': '/D'}
|
||||
state.__pillar__ = {}
|
||||
|
||||
|
||||
@ -131,7 +131,8 @@ class MockState(object):
|
||||
Mock HighState class
|
||||
'''
|
||||
flag = False
|
||||
opts = {'state_top': ""}
|
||||
opts = {'state_top': '',
|
||||
'pillar': {}}
|
||||
|
||||
def __init__(self, opts, pillar=None, *args, **kwargs):
|
||||
self.state = MockState.State(opts,
|
||||
@ -465,16 +466,15 @@ class StateTestCase(TestCase):
|
||||
'''
|
||||
Test to clear out cached state file
|
||||
'''
|
||||
with patch.dict(state.__opts__, {"cachedir": "/D/"}):
|
||||
mock = MagicMock(return_value=["A.cache.p", "B.cache.p", "C"])
|
||||
with patch.object(os, 'listdir', mock):
|
||||
mock = MagicMock(return_value=["A.cache.p", "B.cache.p", "C"])
|
||||
with patch.object(os, 'listdir', mock):
|
||||
mock = MagicMock(return_value=True)
|
||||
with patch.object(os.path, 'isfile', mock):
|
||||
mock = MagicMock(return_value=True)
|
||||
with patch.object(os.path, 'isfile', mock):
|
||||
mock = MagicMock(return_value=True)
|
||||
with patch.object(os, 'remove', mock):
|
||||
self.assertEqual(state.clear_cache(),
|
||||
['A.cache.p',
|
||||
'B.cache.p'])
|
||||
with patch.object(os, 'remove', mock):
|
||||
self.assertEqual(state.clear_cache(),
|
||||
['A.cache.p',
|
||||
'B.cache.p'])
|
||||
|
||||
def test_single(self):
|
||||
'''
|
||||
@ -537,11 +537,10 @@ class StateTestCase(TestCase):
|
||||
|
||||
mock = MagicMock(return_value=["True"])
|
||||
with patch.object(state, 'apply_', mock):
|
||||
with patch.dict(state.__opts__, {"cachedir": "/D/"}):
|
||||
mock = MagicMock(return_value="")
|
||||
with patch.object(os, 'remove', mock):
|
||||
self.assertListEqual(state.run_request("name"),
|
||||
["True"])
|
||||
mock = MagicMock(return_value="")
|
||||
with patch.object(os, 'remove', mock):
|
||||
self.assertListEqual(state.run_request("name"),
|
||||
["True"])
|
||||
|
||||
def test_show_highstate(self):
|
||||
'''
|
||||
@ -711,57 +710,53 @@ class StateTestCase(TestCase):
|
||||
mock = MagicMock(return_value=True)
|
||||
with patch.object(salt.payload, 'Serial',
|
||||
mock):
|
||||
with patch.dict(state.__opts__,
|
||||
{"cachedir": "D"}):
|
||||
with patch.object(os.path,
|
||||
'join', mock):
|
||||
with patch.object(
|
||||
state,
|
||||
'_set'
|
||||
'_retcode',
|
||||
mock):
|
||||
self.assertTrue(state.
|
||||
highstate
|
||||
(arg))
|
||||
with patch.object(os.path,
|
||||
'join', mock):
|
||||
with patch.object(
|
||||
state,
|
||||
'_set'
|
||||
'_retcode',
|
||||
mock):
|
||||
self.assertTrue(state.
|
||||
highstate
|
||||
(arg))
|
||||
|
||||
def test_clear_request(self):
|
||||
'''
|
||||
Test to clear out the state execution request without executing it
|
||||
'''
|
||||
with patch.dict(state.__opts__, {"cachedir": "D"}):
|
||||
mock = MagicMock(return_value=True)
|
||||
with patch.object(os.path, 'join', mock):
|
||||
mock = MagicMock(return_value=True)
|
||||
with patch.object(os.path, 'join', mock):
|
||||
mock = MagicMock(return_value=True)
|
||||
with patch.object(salt.payload, 'Serial', mock):
|
||||
mock = MagicMock(side_effect=[False, True, True])
|
||||
with patch.object(os.path, 'isfile', mock):
|
||||
self.assertTrue(state.clear_request("A"))
|
||||
with patch.object(salt.payload, 'Serial', mock):
|
||||
mock = MagicMock(side_effect=[False, True, True])
|
||||
with patch.object(os.path, 'isfile', mock):
|
||||
self.assertTrue(state.clear_request("A"))
|
||||
|
||||
mock = MagicMock(return_value=True)
|
||||
with patch.object(os, 'remove', mock):
|
||||
self.assertTrue(state.clear_request())
|
||||
mock = MagicMock(return_value=True)
|
||||
with patch.object(os, 'remove', mock):
|
||||
self.assertTrue(state.clear_request())
|
||||
|
||||
mock = MagicMock(return_value={})
|
||||
with patch.object(state, 'check_request', mock):
|
||||
self.assertFalse(state.clear_request("A"))
|
||||
mock = MagicMock(return_value={})
|
||||
with patch.object(state, 'check_request', mock):
|
||||
self.assertFalse(state.clear_request("A"))
|
||||
|
||||
@patch('salt.modules.state.salt.payload', MockSerial)
|
||||
def test_check_request(self):
|
||||
'''
|
||||
Test to return the state request information
|
||||
'''
|
||||
with patch.dict(state.__opts__, {"cachedir": "D"}):
|
||||
mock = MagicMock(return_value=True)
|
||||
with patch.object(os.path, 'join', mock):
|
||||
mock = MagicMock(side_effect=[True, True, False])
|
||||
with patch.object(os.path, 'isfile', mock):
|
||||
with patch('salt.utils.fopen', mock_open()):
|
||||
self.assertDictEqual(state.check_request(), {'A': 'B'})
|
||||
mock = MagicMock(return_value=True)
|
||||
with patch.object(os.path, 'join', mock):
|
||||
mock = MagicMock(side_effect=[True, True, False])
|
||||
with patch.object(os.path, 'isfile', mock):
|
||||
with patch('salt.utils.fopen', mock_open()):
|
||||
self.assertDictEqual(state.check_request(), {'A': 'B'})
|
||||
|
||||
with patch('salt.utils.fopen', mock_open()):
|
||||
self.assertEqual(state.check_request("A"), 'B')
|
||||
with patch('salt.utils.fopen', mock_open()):
|
||||
self.assertEqual(state.check_request("A"), 'B')
|
||||
|
||||
self.assertDictEqual(state.check_request(), {})
|
||||
self.assertDictEqual(state.check_request(), {})
|
||||
|
||||
def test_request(self):
|
||||
'''
|
||||
@ -769,28 +764,21 @@ class StateTestCase(TestCase):
|
||||
'''
|
||||
mock = MagicMock(return_value=True)
|
||||
with patch.object(state, 'apply_', mock):
|
||||
with patch.dict(state.__opts__, {"cachedir": "D"}):
|
||||
mock = MagicMock(return_value=True)
|
||||
with patch.object(os.path, 'join', mock):
|
||||
mock = MagicMock(return_value=
|
||||
{"test_run": "",
|
||||
"mods": "",
|
||||
"kwargs": ""})
|
||||
with patch.object(state, 'check_request', mock):
|
||||
mock = MagicMock(return_value=True)
|
||||
with patch.object(os, 'umask', mock):
|
||||
with patch.object(salt.utils, 'is_windows', mock):
|
||||
with patch.dict(state.__salt__,
|
||||
{'cmd.run': mock}):
|
||||
with patch('salt.utils.fopen',
|
||||
mock_open()):
|
||||
mock = MagicMock(
|
||||
return_value=True)
|
||||
with patch.object(os, 'umask',
|
||||
mock):
|
||||
self.assertTrue(
|
||||
state.request("A")
|
||||
)
|
||||
mock = MagicMock(return_value=True)
|
||||
with patch.object(os.path, 'join', mock):
|
||||
mock = MagicMock(return_value=
|
||||
{"test_run": "",
|
||||
"mods": "",
|
||||
"kwargs": ""})
|
||||
with patch.object(state, 'check_request', mock):
|
||||
mock = MagicMock(return_value=True)
|
||||
with patch.object(os, 'umask', mock):
|
||||
with patch.object(salt.utils, 'is_windows', mock):
|
||||
with patch.dict(state.__salt__, {'cmd.run': mock}):
|
||||
with patch('salt.utils.fopen', mock_open()):
|
||||
mock = MagicMock(return_value=True)
|
||||
with patch.object(os, 'umask', mock):
|
||||
self.assertTrue(state.request("A"))
|
||||
|
||||
def test_sls(self):
|
||||
'''
|
||||
@ -847,59 +835,50 @@ class StateTestCase(TestCase):
|
||||
True,
|
||||
pillar="A")
|
||||
|
||||
with patch.dict(
|
||||
state.__opts__,
|
||||
{"cachedir": "/D/"}):
|
||||
mock = MagicMock(return_value=
|
||||
"/D/cache.cache.p")
|
||||
mock = MagicMock(return_value="/D/cache.cache.p")
|
||||
with patch.object(os.path,
|
||||
'join',
|
||||
mock):
|
||||
mock = MagicMock(return_value=True)
|
||||
with patch.object(os.path,
|
||||
'join',
|
||||
'isfile',
|
||||
mock):
|
||||
mock = MagicMock(return_value=True)
|
||||
with patch.object(os.path,
|
||||
'isfile',
|
||||
with patch(
|
||||
'salt.utils.fopen',
|
||||
mock_open()):
|
||||
self.assertTrue(
|
||||
state.sls(arg,
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
True,
|
||||
cache
|
||||
=True
|
||||
)
|
||||
)
|
||||
|
||||
MockState.HighState.flag = True
|
||||
self.assertTrue(state.sls("core,edit"
|
||||
".vim dev",
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
True)
|
||||
)
|
||||
|
||||
MockState.HighState.flag = False
|
||||
mock = MagicMock(return_value=True)
|
||||
with patch.dict(state.__salt__,
|
||||
{'config.option':
|
||||
mock}):
|
||||
mock = MagicMock(return_value=
|
||||
True)
|
||||
with patch.object(
|
||||
state,
|
||||
'_filter_'
|
||||
'running',
|
||||
mock):
|
||||
with patch(
|
||||
'salt.utils.fopen',
|
||||
mock_open()):
|
||||
self.assertTrue(
|
||||
state.sls(arg,
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
True,
|
||||
cache
|
||||
=True
|
||||
)
|
||||
)
|
||||
|
||||
MockState.HighState.flag = True
|
||||
self.assertTrue(state.sls("core,edit"
|
||||
".vim dev",
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
True)
|
||||
)
|
||||
|
||||
MockState.HighState.flag = False
|
||||
mock = MagicMock(return_value=True)
|
||||
with patch.dict(state.__salt__,
|
||||
{'config.option':
|
||||
mock}):
|
||||
mock = MagicMock(return_value=
|
||||
True)
|
||||
with patch.object(
|
||||
state,
|
||||
'_filter_'
|
||||
'running',
|
||||
mock):
|
||||
with patch.dict(
|
||||
state.
|
||||
__opts__,
|
||||
{"cachedir":
|
||||
"/D/"}):
|
||||
self.sub_test_sls()
|
||||
self.sub_test_sls()
|
||||
|
||||
def sub_test_sls(self):
|
||||
'''
|
||||
|
Loading…
Reference in New Issue
Block a user