Skip to content

Commit

Permalink
Multiple onchanges requisite behaviour
Browse files Browse the repository at this point in the history
Change the onchanges requisite so that if you list multiple onchanges
requisites then only one must change to trigger the state. Currently all
the watched states must change to cause the trigger. This fixes #19592
  • Loading branch information
mattmb committed Jun 16, 2015
1 parent 211bf36 commit a5607d5
Show file tree
Hide file tree
Showing 4 changed files with 72 additions and 5 deletions.
3 changes: 3 additions & 0 deletions doc/ref/states/requisites.rst
Expand Up @@ -326,6 +326,9 @@ The ``onchanges`` requisite makes a state only apply if the required states
generate changes, and if the watched state's "result" is ``True``. This can be
a useful way to execute a post hook after changing aspects of a system.

If a state has multiple ``onchanges`` requisites then the state will trigger
if any of the watched states changes.

use
~~~

Expand Down
8 changes: 5 additions & 3 deletions salt/state.py
Expand Up @@ -1746,7 +1746,9 @@ def check_requisite(self, low, running, chunks, pre=False):
if r_state == 'onchanges':
if not run_dict[tag]['changes']:
fun_stats.add('onchanges')
continue
else:
fun_stats.add('onchangesmet')
continue
if r_state == 'watch' and run_dict[tag]['changes']:
fun_stats.add('change')
continue
Expand All @@ -1768,7 +1770,7 @@ def check_requisite(self, low, running, chunks, pre=False):
status = 'pre'
elif 'onfail' in fun_stats:
status = 'onfail'
elif 'onchanges' in fun_stats:
elif 'onchanges' in fun_stats and not 'onchangesmet' in fun_stats:
status = 'onchanges'
elif 'change' in fun_stats:
status = 'change'
Expand Down Expand Up @@ -1992,7 +1994,7 @@ def call_chunk(self, low, running, chunks):
elif status == 'onchanges':
running[tag] = {'changes': {},
'result': True,
'comment': 'State was not run because onchanges req did not change',
'comment': 'State was not run because none of the onchanges reqs changed',
'__run_num__': self.__run_num,
'__sls__': low['__sls__']}
self.__run_num += 1
Expand Down
@@ -0,0 +1,38 @@
changing_state:
cmd.run:
- name: echo "Changed!"

another_changing_state:
cmd.run:
- name: echo "Changed!"

# mock is installed with salttesting, so it should already be
# present on the system, resulting in no changes
non_changing_state:
pip.installed:
- name: mock

another_non_changing_state:
pip.installed:
- name: mock

test_two_changing_states:
cmd.run:
- name: echo "Success!"
- onchanges:
- cmd: changing_state
- cmd: another_changing_state

test_two_non_changing_states:
cmd.run:
- name: echo "Should not run"
- onchanges:
- pip: non_changing_state
- pip: another_non_changing_state

test_one_changing_state:
cmd.run:
- name: echo "Success!"
- onchanges:
- cmd: changing_state
- pip: non_changing_state
28 changes: 26 additions & 2 deletions tests/integration/modules/state.py
Expand Up @@ -926,7 +926,31 @@ def test_onchanges_requisite(self):

# Then, test the result of the state run when changes are not expected to happen
test_data = state_run['cmd_|-test_non_changing_state_|-echo "Should not run"_|-run']['comment']
expected_result = 'State was not run because onchanges req did not change'
expected_result = 'State was not run because none of the onchanges reqs changed'
self.assertIn(expected_result, test_data)

def test_onchanges_requisite_multiple(self):
'''
Tests a simple state using the onchanges requisite
'''

# Only run the state once and keep the return data
state_run = self.run_function('state.sls',
mods='requisites.onchanges_multiple')

# First, test the result of the state run when two changes are expected to happen
test_data = state_run['cmd_|-test_two_changing_states_|-echo "Success!"_|-run']['comment']
expected_result = 'Command "echo "Success!"" run'
self.assertIn(expected_result, test_data)

# Then, test the result of the state run when two changes are not expected to happen
test_data = state_run['cmd_|-test_two_non_changing_states_|-echo "Should not run"_|-run']['comment']
expected_result = 'State was not run because none of the onchanges reqs changed'
self.assertIn(expected_result, test_data)

# Finally, test the result of the state run when only one of the onchanges requisites changes.
test_data = state_run['cmd_|-test_one_changing_state_|-echo "Success!"_|-run']['comment']
expected_result = 'Command "echo "Success!"" run'
self.assertIn(expected_result, test_data)

def test_onchanges_in_requisite(self):
Expand All @@ -944,7 +968,7 @@ def test_onchanges_in_requisite(self):

# Then, test the result of the state run when changes are not expected to happen
test_data = state_run['cmd_|-test_changes_not_expected_|-echo "Should not run"_|-run']['comment']
expected_result = 'State was not run because onchanges req did not change'
expected_result = 'State was not run because none of the onchanges reqs changed'
self.assertIn(expected_result, test_data)

# onfail tests
Expand Down

0 comments on commit a5607d5

Please sign in to comment.