Skip to content

Commit

Permalink
Merge pull request #49955 from garethgreenaway/disable_requisites
Browse files Browse the repository at this point in the history
[develop] Adding ability to disable requisites
  • Loading branch information
Mike Place authored Oct 23, 2018
2 parents 809c097 + 1cca32f commit 2a23adf
Show file tree
Hide file tree
Showing 5 changed files with 84 additions and 0 deletions.
9 changes: 9 additions & 0 deletions conf/minion
Original file line number Diff line number Diff line change
Expand Up @@ -560,6 +560,15 @@
#
#state_aggregate: False

# Disable requisites during state runs by specifying a single requisite
# or a list of requisites to disable.
#
# disabled_requisites: require_in
#
# disabled_requisites:
# - require
# - require_in

##### File Directory Settings #####
##########################################
# The Salt Minion can redirect all file server operations to a local directory,
Expand Down
3 changes: 3 additions & 0 deletions doc/topics/releases/neon.rst
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,9 @@ State Changes
- The ``onchanges`` and ``prereq`` :ref:`requisites <requisites>` now behave
properly in test mode.

- Adding a new option for the State compiler, ``disabled_requisites`` will allow
requisites to be disabled during State runs.

- Added new :py:func:`ssh_auth.manage <salt.states.ssh_auth.manage>` state to
ensure only the specified ssh keys are present for the specified user.

Expand Down
4 changes: 4 additions & 0 deletions salt/config/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -1198,6 +1198,9 @@ def _gather_buffer_space():
# Use Adler32 hashing algorithm for server_id (default False until Sodium, "adler32" after)
# Possible values are: False, adler32, crc32
'server_id_use_crc': (bool, six.string_types),

# Disable requisites during State runs
'disabled_requisites': (six.string_types, list),
}

# default configurations
Expand Down Expand Up @@ -1496,6 +1499,7 @@ def _gather_buffer_space():
'schedule': {},
'ssh_merge_pillar': True,
'server_id_use_crc': False,
'disabled_requisites': [],
}

DEFAULT_MASTER_OPTS = {
Expand Down
12 changes: 12 additions & 0 deletions salt/state.py
Original file line number Diff line number Diff line change
Expand Up @@ -1522,6 +1522,9 @@ def requisite_in(self, high):
req_in_all = req_in.union({'require', 'watch', 'onfail', 'onfail_stop', 'onchanges'})
extend = {}
errors = []
disabled_reqs = self.opts.get('disabled_requisites', [])
if not isinstance(disabled_reqs, list):
disabled_reqs = [disabled_reqs]
for id_, body in six.iteritems(high):
if not isinstance(body, dict):
continue
Expand All @@ -1540,6 +1543,9 @@ def requisite_in(self, high):
key = next(iter(arg))
if key not in req_in:
continue
if key in disabled_reqs:
log.warning('The %s requisite has been disabled, Ignoring.', key)
continue
rkey = key.split('_')[0]
items = arg[key]
if isinstance(items, dict):
Expand Down Expand Up @@ -2260,6 +2266,9 @@ def check_requisite(self, low, running, chunks, pre=False):
Look into the running data to check the status of all requisite
states
'''
disabled_reqs = self.opts.get('disabled_requisites', [])
if not isinstance(disabled_reqs, list):
disabled_reqs = [disabled_reqs]
present = False
# If mod_watch is not available make it a require
if 'watch' in low:
Expand Down Expand Up @@ -2311,6 +2320,9 @@ def check_requisite(self, low, running, chunks, pre=False):
reqs['prerequired'] = []
for r_state in reqs:
if r_state in low and low[r_state] is not None:
if r_state in disabled_reqs:
log.warning('The %s requisite has been disabled, Ignoring.', r_state)
continue
for req in low[r_state]:
if isinstance(req, six.string_types):
req = {'id': req}
Expand Down
56 changes: 56 additions & 0 deletions tests/unit/test_state.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,62 @@ def test_render_error_on_invalid_requisite(self):
with self.assertRaises(salt.exceptions.SaltRenderError):
state_obj.call_high(high_data)

def test_render_requisite_require_disabled(self):
'''
Test that the state compiler correctly deliver a rendering
exception when a requisite cannot be resolved
'''
with patch('salt.state.State._gather_pillar') as state_patch:
high_data = {
'step_one': OrderedDict([
('test', [
OrderedDict([
('require', [
OrderedDict([
('test', 'step_two')])])]),
'succeed_with_changes', {'order': 10000}]),
('__sls__', 'test.disable_require'),
('__env__', 'base')]),
'step_two': {'test': ['succeed_with_changes',
{'order': 10001}],
'__env__': 'base',
'__sls__': 'test.disable_require'}}

minion_opts = self.get_temp_config('minion')
minion_opts['disabled_requisites'] = ['require']
state_obj = salt.state.State(minion_opts)
ret = state_obj.call_high(high_data)
run_num = ret['test_|-step_one_|-step_one_|-succeed_with_changes']['__run_num__']
self.assertEqual(run_num, 0)

def test_render_requisite_require_in_disabled(self):
'''
Test that the state compiler correctly deliver a rendering
exception when a requisite cannot be resolved
'''
with patch('salt.state.State._gather_pillar') as state_patch:
high_data = {
'step_one': {'test': ['succeed_with_changes',
{'order': 10000}],
'__env__': 'base',
'__sls__': 'test.disable_require_in'},
'step_two': OrderedDict([
('test', [
OrderedDict([
('require_in', [
OrderedDict([
('test', 'step_one')])])]),
'succeed_with_changes', {'order': 10001}]),
('__sls__', 'test.disable_require_in'),
('__env__', 'base')])}

minion_opts = self.get_temp_config('minion')
minion_opts['disabled_requisites'] = ['require_in']
state_obj = salt.state.State(minion_opts)
ret = state_obj.call_high(high_data)
run_num = ret['test_|-step_one_|-step_one_|-succeed_with_changes']['__run_num__']
self.assertEqual(run_num, 0)


class HighStateTestCase(TestCase, AdaptedConfigurationTestCaseMixin):
def setUp(self):
Expand Down

0 comments on commit 2a23adf

Please sign in to comment.