c0058217c7
OBS-URL: https://build.opensuse.org/package/show/systemsmanagement:saltstack/salt?expand=0&rev=184
288 lines
11 KiB
Diff
288 lines
11 KiB
Diff
From 828ca76e2083d87ace12b488277e51d4e30c8c9a Mon Sep 17 00:00:00 2001
|
|
From: =?UTF-8?q?Pablo=20Su=C3=A1rez=20Hern=C3=A1ndez?=
|
|
<psuarezhernandez@suse.com>
|
|
Date: Thu, 21 Jan 2021 11:19:07 +0000
|
|
Subject: [PATCH] Fix onlyif/unless when multiple conditions
|
|
(bsc#1180818)
|
|
|
|
Add unit tests to ensure right onlyif/unless behavior
|
|
|
|
Add extra unit test to cover valid cases
|
|
|
|
Add unit tests cases to ensure proper onlyif/unless behavior
|
|
|
|
Change tests to use 'exit' cmd and work outside Linux
|
|
---
|
|
salt/state.py | 20 ++++--
|
|
tests/unit/test_state.py | 148 ++++++++++++++++++++++++++++++++++++++-
|
|
2 files changed, 163 insertions(+), 5 deletions(-)
|
|
|
|
diff --git a/salt/state.py b/salt/state.py
|
|
index cc6db7e1b2..070a914636 100644
|
|
--- a/salt/state.py
|
|
+++ b/salt/state.py
|
|
@@ -947,8 +947,10 @@ class State:
|
|
"result": True,
|
|
}
|
|
)
|
|
+ return False
|
|
elif cmd == 0:
|
|
ret.update({"comment": "onlyif condition is true", "result": False})
|
|
+ return True
|
|
|
|
for entry in low_data_onlyif:
|
|
if isinstance(entry, str):
|
|
@@ -960,7 +962,8 @@ class State:
|
|
# Command failed, notify onlyif to skip running the item
|
|
cmd = 100
|
|
log.debug("Last command return code: %s", cmd)
|
|
- _check_cmd(cmd)
|
|
+ if not _check_cmd(cmd):
|
|
+ return ret
|
|
elif isinstance(entry, dict):
|
|
if "fun" not in entry:
|
|
ret["comment"] = "no `fun` argument in onlyif: {}".format(entry)
|
|
@@ -972,7 +975,8 @@ class State:
|
|
if get_return:
|
|
result = salt.utils.data.traverse_dict_and_list(result, get_return)
|
|
if self.state_con.get("retcode", 0):
|
|
- _check_cmd(self.state_con["retcode"])
|
|
+ if not _check_cmd(self.state_con["retcode"]):
|
|
+ return ret
|
|
elif not result:
|
|
ret.update(
|
|
{
|
|
@@ -981,6 +985,7 @@ class State:
|
|
"result": True,
|
|
}
|
|
)
|
|
+ return ret
|
|
else:
|
|
ret.update({"comment": "onlyif condition is true", "result": False})
|
|
|
|
@@ -991,6 +996,7 @@ class State:
|
|
"result": False,
|
|
}
|
|
)
|
|
+ return ret
|
|
return ret
|
|
|
|
def _run_check_unless(self, low_data, cmd_opts):
|
|
@@ -1013,8 +1019,10 @@ class State:
|
|
"result": True,
|
|
}
|
|
)
|
|
+ return False
|
|
elif cmd != 0:
|
|
ret.update({"comment": "unless condition is false", "result": False})
|
|
+ return True
|
|
|
|
for entry in low_data_unless:
|
|
if isinstance(entry, str):
|
|
@@ -1026,7 +1034,8 @@ class State:
|
|
except CommandExecutionError:
|
|
# Command failed, so notify unless to skip the item
|
|
cmd = 0
|
|
- _check_cmd(cmd)
|
|
+ if not _check_cmd(cmd):
|
|
+ return ret
|
|
elif isinstance(entry, dict):
|
|
if "fun" not in entry:
|
|
ret["comment"] = "no `fun` argument in unless: {}".format(entry)
|
|
@@ -1038,7 +1047,8 @@ class State:
|
|
if get_return:
|
|
result = salt.utils.data.traverse_dict_and_list(result, get_return)
|
|
if self.state_con.get("retcode", 0):
|
|
- _check_cmd(self.state_con["retcode"])
|
|
+ if not _check_cmd(self.state_con["retcode"]):
|
|
+ return ret
|
|
elif result:
|
|
ret.update(
|
|
{
|
|
@@ -1047,6 +1057,7 @@ class State:
|
|
"result": True,
|
|
}
|
|
)
|
|
+ return ret
|
|
else:
|
|
ret.update(
|
|
{"comment": "unless condition is false", "result": False}
|
|
@@ -1058,6 +1069,7 @@ class State:
|
|
"result": False,
|
|
}
|
|
)
|
|
+ return ret
|
|
|
|
# No reason to stop, return ret
|
|
return ret
|
|
diff --git a/tests/unit/test_state.py b/tests/unit/test_state.py
|
|
index b1bcf8fe83..95018a9cf3 100644
|
|
--- a/tests/unit/test_state.py
|
|
+++ b/tests/unit/test_state.py
|
|
@@ -205,6 +205,152 @@ class StateCompilerTestCase(TestCase, AdaptedConfigurationTestCaseMixin):
|
|
)
|
|
self.assertEqual(expected_result, return_result)
|
|
|
|
+ def test_verify_unless_list_cmd(self):
|
|
+ low_data = {
|
|
+ "state": "cmd",
|
|
+ "name": 'echo "something"',
|
|
+ "__sls__": "tests.cmd",
|
|
+ "__env__": "base",
|
|
+ "__id__": "check unless",
|
|
+ "unless": ["exit 0", "exit 1"],
|
|
+ "order": 10001,
|
|
+ "fun": "run",
|
|
+ }
|
|
+ expected_result = {
|
|
+ "comment": "unless condition is true",
|
|
+ "result": True,
|
|
+ "skip_watch": True,
|
|
+ }
|
|
+ with patch("salt.state.State._gather_pillar") as state_patch:
|
|
+ minion_opts = self.get_temp_config("minion")
|
|
+ state_obj = salt.state.State(minion_opts)
|
|
+ return_result = state_obj._run_check_unless(low_data, {})
|
|
+ self.assertEqual(expected_result, return_result)
|
|
+
|
|
+ def test_verify_unless_list_cmd_different_order(self):
|
|
+ low_data = {
|
|
+ "state": "cmd",
|
|
+ "name": 'echo "something"',
|
|
+ "__sls__": "tests.cmd",
|
|
+ "__env__": "base",
|
|
+ "__id__": "check unless",
|
|
+ "unless": ["exit 1", "exit 0"],
|
|
+ "order": 10001,
|
|
+ "fun": "run",
|
|
+ }
|
|
+ expected_result = {
|
|
+ "comment": "unless condition is true",
|
|
+ "result": True,
|
|
+ "skip_watch": True,
|
|
+ }
|
|
+ with patch("salt.state.State._gather_pillar") as state_patch:
|
|
+ minion_opts = self.get_temp_config("minion")
|
|
+ state_obj = salt.state.State(minion_opts)
|
|
+ return_result = state_obj._run_check_unless(low_data, {})
|
|
+ self.assertEqual(expected_result, return_result)
|
|
+
|
|
+ def test_verify_onlyif_list_cmd_different_order(self):
|
|
+ low_data = {
|
|
+ "state": "cmd",
|
|
+ "name": 'echo "something"',
|
|
+ "__sls__": "tests.cmd",
|
|
+ "__env__": "base",
|
|
+ "__id__": "check onlyif",
|
|
+ "onlyif": ["exit 1", "exit 0"],
|
|
+ "order": 10001,
|
|
+ "fun": "run",
|
|
+ }
|
|
+ expected_result = {
|
|
+ "comment": "onlyif condition is false",
|
|
+ "result": True,
|
|
+ "skip_watch": True,
|
|
+ }
|
|
+ with patch("salt.state.State._gather_pillar") as state_patch:
|
|
+ minion_opts = self.get_temp_config("minion")
|
|
+ state_obj = salt.state.State(minion_opts)
|
|
+ return_result = state_obj._run_check_onlyif(low_data, {})
|
|
+ self.assertEqual(expected_result, return_result)
|
|
+
|
|
+ def test_verify_unless_list_cmd_valid(self):
|
|
+ low_data = {
|
|
+ "state": "cmd",
|
|
+ "name": 'echo "something"',
|
|
+ "__sls__": "tests.cmd",
|
|
+ "__env__": "base",
|
|
+ "__id__": "check unless",
|
|
+ "unless": ["exit 1", "exit 1"],
|
|
+ "order": 10001,
|
|
+ "fun": "run",
|
|
+ }
|
|
+ expected_result = {"comment": "unless condition is false", "result": False}
|
|
+ with patch("salt.state.State._gather_pillar") as state_patch:
|
|
+ minion_opts = self.get_temp_config("minion")
|
|
+ state_obj = salt.state.State(minion_opts)
|
|
+ return_result = state_obj._run_check_unless(low_data, {})
|
|
+ self.assertEqual(expected_result, return_result)
|
|
+
|
|
+ def test_verify_onlyif_list_cmd_valid(self):
|
|
+ low_data = {
|
|
+ "state": "cmd",
|
|
+ "name": 'echo "something"',
|
|
+ "__sls__": "tests.cmd",
|
|
+ "__env__": "base",
|
|
+ "__id__": "check onlyif",
|
|
+ "onlyif": ["exit 0", "exit 0"],
|
|
+ "order": 10001,
|
|
+ "fun": "run",
|
|
+ }
|
|
+ expected_result = {"comment": "onlyif condition is true", "result": False}
|
|
+ with patch("salt.state.State._gather_pillar") as state_patch:
|
|
+ minion_opts = self.get_temp_config("minion")
|
|
+ state_obj = salt.state.State(minion_opts)
|
|
+ return_result = state_obj._run_check_onlyif(low_data, {})
|
|
+ self.assertEqual(expected_result, return_result)
|
|
+
|
|
+ def test_verify_unless_list_cmd_invalid(self):
|
|
+ low_data = {
|
|
+ "state": "cmd",
|
|
+ "name": 'echo "something"',
|
|
+ "__sls__": "tests.cmd",
|
|
+ "__env__": "base",
|
|
+ "__id__": "check unless",
|
|
+ "unless": ["exit 0", "exit 0"],
|
|
+ "order": 10001,
|
|
+ "fun": "run",
|
|
+ }
|
|
+ expected_result = {
|
|
+ "comment": "unless condition is true",
|
|
+ "result": True,
|
|
+ "skip_watch": True,
|
|
+ }
|
|
+ with patch("salt.state.State._gather_pillar") as state_patch:
|
|
+ minion_opts = self.get_temp_config("minion")
|
|
+ state_obj = salt.state.State(minion_opts)
|
|
+ return_result = state_obj._run_check_unless(low_data, {})
|
|
+ self.assertEqual(expected_result, return_result)
|
|
+
|
|
+ def test_verify_onlyif_list_cmd_invalid(self):
|
|
+ low_data = {
|
|
+ "state": "cmd",
|
|
+ "name": 'echo "something"',
|
|
+ "__sls__": "tests.cmd",
|
|
+ "__env__": "base",
|
|
+ "__id__": "check onlyif",
|
|
+ "onlyif": ["exit 1", "exit 1"],
|
|
+ "order": 10001,
|
|
+ "fun": "run",
|
|
+ }
|
|
+ expected_result = {
|
|
+ "comment": "onlyif condition is false",
|
|
+ "result": True,
|
|
+ "skip_watch": True,
|
|
+ }
|
|
+ with patch("salt.state.State._gather_pillar") as state_patch:
|
|
+ minion_opts = self.get_temp_config("minion")
|
|
+ state_obj = salt.state.State(minion_opts)
|
|
+ return_result = state_obj._run_check_onlyif(low_data, {})
|
|
+ self.assertEqual(expected_result, return_result)
|
|
+
|
|
def test_verify_unless_parse(self):
|
|
low_data = {
|
|
"unless": [{"fun": "test.arg", "args": ["arg1", "arg2"]}],
|
|
@@ -376,7 +522,7 @@ class StateCompilerTestCase(TestCase, AdaptedConfigurationTestCaseMixin):
|
|
"__sls__": "tests.cmd",
|
|
"__env__": "base",
|
|
"__id__": "check onlyif",
|
|
- "onlyif": ["/bin/true", "/bin/false"],
|
|
+ "onlyif": ["exit 0", "exit 1"],
|
|
"order": 10001,
|
|
"fun": "run",
|
|
}
|
|
--
|
|
2.29.2
|
|
|
|
|