Skip to content

Commit

Permalink
Merge pull request saltstack#56298 from raddessi/master.state-test
Browse files Browse the repository at this point in the history
Added test function to state module
  • Loading branch information
dwoz authored Apr 22, 2020
2 parents 138fc18 + a226720 commit 4d21cb5
Show file tree
Hide file tree
Showing 4 changed files with 82 additions and 0 deletions.
10 changes: 10 additions & 0 deletions doc/topics/releases/sodium.rst
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,16 @@ The old syntax for the mine_function - as a dict, or as a list with dicts that
contain more than exactly one key - is still supported but discouraged in favor
of the more uniform syntax of module.run.

State Execution Module
======================

The :mod:`state.test <salt.modules.state.test>` function
can be used to test a state on a minion. This works by executing the
:mod:`state.apply <salt.modules.state.apply>` function while forcing the ``test`` kwarg
to ``True`` so that the ``state.apply`` function is not required to be called by the
user directly. This also allows you to add the ``state.test`` function to a minion's
``minion_blackout_whitelist`` pillar if you wish to be able to test a state while a
minion is in blackout.

New Grains
==========
Expand Down
16 changes: 16 additions & 0 deletions salt/modules/state.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@
"template": "highstate",
"template_str": "highstate",
"apply_": "highstate",
"test": "highstate",
"request": "highstate",
"check_request": "highstate",
"run_request": "highstate",
Expand Down Expand Up @@ -799,6 +800,21 @@ def apply_(mods=None, **kwargs):
return highstate(**kwargs)


def test(*args, **kwargs):
"""
.. versionadded:: Sodium
Alias for `state.apply` with the kwarg `test` forced to `True`.
This is a nicety to avoid the need to type out `test=True` and the possibility of
a typo causing changes you do not intend.
"""
kwargs["test"] = True
ret = apply_(*args, **kwargs)

return ret


def request(mods=None, **kwargs):
"""
.. versionadded:: 2015.5.0
Expand Down
31 changes: 31 additions & 0 deletions tests/integration/modules/test_state.py
Original file line number Diff line number Diff line change
Expand Up @@ -2354,6 +2354,37 @@ def test_state_sls_id_test_false_pillar_true(self):
self.assertEqual(val["comment"], "File {0} updated".format(file_name))
self.assertEqual(val["changes"]["diff"], "New file")

def test_state_test_pillar_false(self):
"""
test state.test forces test kwarg to True even when pillar is set to False
"""
self._add_runtime_pillar(pillar={"test": False})
testfile = os.path.join(RUNTIME_VARS.TMP, "testfile")
comment = "The file {0} is set to be changed\nNote: No changes made, actual changes may\nbe different due to other states.".format(
testfile
)
ret = self.run_function("state.test", ["core"])

for key, val in ret.items():
self.assertEqual(val["comment"], comment)
self.assertEqual(val["changes"], {"newfile": testfile})

def test_state_test_test_false_pillar_false(self):
"""
test state.test forces test kwarg to True even when pillar and kwarg are set
to False
"""
self._add_runtime_pillar(pillar={"test": False})
testfile = os.path.join(RUNTIME_VARS.TMP, "testfile")
comment = "The file {0} is set to be changed\nNote: No changes made, actual changes may\nbe different due to other states.".format(
testfile
)
ret = self.run_function("state.test", ["core"], test=False)

for key, val in ret.items():
self.assertEqual(val["comment"], comment)
self.assertEqual(val["changes"], {"newfile": testfile})

@skipIf(
six.PY3 and salt.utils.platform.is_darwin(), "Test is broken on macosx and PY3"
)
Expand Down
25 changes: 25 additions & 0 deletions tests/unit/modules/test_state.py
Original file line number Diff line number Diff line change
Expand Up @@ -432,6 +432,23 @@ def test_apply_(self):
with patch.object(state, "highstate", mock):
self.assertTrue(state.apply_(None))

def test_test(self):
"""
Test to apply states in test mode
"""
with patch.dict(state.__opts__, {"test": False}):
mock = MagicMock(return_value=True)
with patch.object(state, "sls", mock):
self.assertTrue(state.test(True))
mock.assert_called_once_with(True, test=True)
self.assertEqual(state.__opts__["test"], False)

mock = MagicMock(return_value=True)
with patch.object(state, "highstate", mock):
self.assertTrue(state.test(None))
mock.assert_called_once_with(test=True)
self.assertEqual(state.__opts__["test"], False)

def test_list_disabled(self):
"""
Test to list disabled states
Expand Down Expand Up @@ -1194,6 +1211,14 @@ def test_lock_saltenv(self):
with self.assertRaisesRegex(CommandExecutionError, lock_msg):
state.apply_(saltenv="base")

# Test "test" with SLS
with self.assertRaisesRegex(CommandExecutionError, lock_msg):
state.test("foo", saltenv="base")

# Test "test" with Highstate
with self.assertRaisesRegex(CommandExecutionError, lock_msg):
state.test(saltenv="base")

# Test highstate
with self.assertRaisesRegex(CommandExecutionError, lock_msg):
state.highstate(saltenv="base")
Expand Down

0 comments on commit 4d21cb5

Please sign in to comment.