diff --git a/changelog/63012.changed b/changelog/63012.changed new file mode 100644 index 000000000000..ab5dfae2f380 --- /dev/null +++ b/changelog/63012.changed @@ -0,0 +1 @@ +Requisite state chunks now all consistently contain `__id__`, `__sls__` and `name`. diff --git a/salt/state.py b/salt/state.py index 0d3c8189d55d..3ba8dc8114e1 100644 --- a/salt/state.py +++ b/salt/state.py @@ -918,6 +918,8 @@ def _run_check(self, low_data): Check that unless doesn't return 0, and that onlyif returns a 0. """ ret = {"result": False, "comment": []} + for key in ("__sls__", "__id__", "name"): + ret[key] = low_data.get(key) cmd_opts = {} # Set arguments from cmd.run state as appropriate @@ -979,6 +981,8 @@ def _run_check_onlyif(self, low_data, cmd_opts): command returns False (non 0), the state will not run """ ret = {"result": False} + for key in ("__sls__", "__id__", "name"): + ret[key] = low_data.get(key) if not isinstance(low_data["onlyif"], list): low_data_onlyif = [low_data["onlyif"]] @@ -1054,6 +1058,8 @@ def _run_check_unless(self, low_data, cmd_opts): state will run. """ ret = {"result": False} + for key in ("__sls__", "__id__", "name"): + ret[key] = low_data.get(key) if not isinstance(low_data["unless"], list): low_data_unless = [low_data["unless"]] @@ -1131,6 +1137,8 @@ def _run_check_cmd(self, low_data): Alter the way a successful state run is determined """ ret = {"result": False} + for key in ("__sls__", "__id__", "name"): + ret[key] = low_data.get(key) cmd_opts = {} if "shell" in self.opts["grains"]: cmd_opts["shell"] = self.opts["grains"].get("shell") @@ -1161,6 +1169,8 @@ def _run_check_creates(self, low_data): Check that listed files exist """ ret = {"result": False} + for key in ("__sls__", "__id__", "name"): + ret[key] = low_data.get(key) if isinstance(low_data["creates"], str) and os.path.exists(low_data["creates"]): ret["comment"] = "{} exists".format(low_data["creates"]) @@ -3086,8 +3096,9 @@ def call_chunk(self, low, running, chunks, depth=0): "start_time": start_time, "comment": comment, "__run_num__": self.__run_num, - "__sls__": low["__sls__"], } + for key in ("__sls__", "__id__", "name"): + run_dict[tag][key] = low.get(key) self.__run_num += 1 self.event(run_dict[tag], len(chunks), fire_event=low.get("fire_event")) return running @@ -3112,8 +3123,9 @@ def call_chunk(self, low, running, chunks, depth=0): "result": False, "comment": "Recursive requisite found", "__run_num__": self.__run_num, - "__sls__": low["__sls__"], } + for key in ("__sls__", "__id__", "name"): + running[tag][key] = low.get(key) self.__run_num += 1 self.event( running[tag], len(chunks), fire_event=low.get("fire_event") @@ -3140,8 +3152,9 @@ def call_chunk(self, low, running, chunks, depth=0): "result": False, "comment": "Recursive requisite found", "__run_num__": self.__run_num, - "__sls__": low["__sls__"], } + for key in ("__sls__", "__id__", "name"): + running[tag][key] = low.get(key) else: running = self.call_chunk(low, running, chunks, depth) if self.check_failhard(chunk, running): @@ -3165,7 +3178,8 @@ def call_chunk(self, low, running, chunks, depth=0): self.pre[tag]["changes"] = {} running[tag] = self.pre[tag] running[tag]["__run_num__"] = self.__run_num - running[tag]["__sls__"] = low["__sls__"] + for key in ("__sls__", "__id__", "name"): + running[tag][key] = low.get(key) # otherwise the failure was due to a requisite down the chain else: # determine what the requisite failures where, and return @@ -3199,8 +3213,9 @@ def call_chunk(self, low, running, chunks, depth=0): "start_time": start_time, "comment": _cmt, "__run_num__": self.__run_num, - "__sls__": low["__sls__"], } + for key in ("__sls__", "__id__", "name"): + running[tag][key] = low.get(key) self.pre[tag] = running[tag] self.__run_num += 1 elif status == "change" and not low.get("__prereq__"): @@ -3221,8 +3236,9 @@ def call_chunk(self, low, running, chunks, depth=0): "start_time": start_time, "comment": "No changes detected", "__run_num__": self.__run_num, - "__sls__": low["__sls__"], } + for key in ("__sls__", "__id__", "name"): + pre_ret[key] = low.get(key) running[tag] = pre_ret self.pre[tag] = pre_ret self.__run_num += 1 @@ -3236,8 +3252,9 @@ def call_chunk(self, low, running, chunks, depth=0): "comment": "State was not run because onfail req did not change", "__state_ran__": False, "__run_num__": self.__run_num, - "__sls__": low["__sls__"], } + for key in ("__sls__", "__id__", "name"): + running[tag][key] = low.get(key) self.__run_num += 1 elif status == "onchanges": start_time, duration = _calculate_fake_duration() @@ -3251,8 +3268,9 @@ def call_chunk(self, low, running, chunks, depth=0): ), "__state_ran__": False, "__run_num__": self.__run_num, - "__sls__": low["__sls__"], } + for key in ("__sls__", "__id__", "name"): + running[tag][key] = low.get(key) self.__run_num += 1 else: if low.get("__prereq__"): @@ -3275,8 +3293,9 @@ def call_chunk(self, low, running, chunks, depth=0): "comment": sub_state_data.get("comment", ""), "__state_ran__": True, "__run_num__": self.__run_num, - "__sls__": low["__sls__"], } + for key in ("__sls__", "__id__", "name"): + running[sub_tag][key] = low.get(key) return running @@ -3284,8 +3303,6 @@ def call_beacons(self, chunks, running): """ Find all of the beacon routines and call the associated mod_beacon runs """ - listeners = [] - crefs = {} beacons = [] for chunk in chunks: if "beacon" in chunk: diff --git a/tests/pytests/unit/state/test_state_compiler.py b/tests/pytests/unit/state/test_state_compiler.py index 826e7d62738a..4bf7548a3403 100644 --- a/tests/pytests/unit/state/test_state_compiler.py +++ b/tests/pytests/unit/state/test_state_compiler.py @@ -39,7 +39,7 @@ def test_render_error_on_invalid_requisite(): 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: + with patch("salt.state.State._gather_pillar"): high_data = { "git": OrderedDict( [ @@ -96,8 +96,10 @@ def test_verify_onlyif_parse(): "order": 10000, } expected_result = {"comment": "onlyif condition is true", "result": False} + for key in ("__sls__", "__id__", "name"): + expected_result[key] = low_data.get(key) - with patch("salt.state.State._gather_pillar") as state_patch: + with patch("salt.state.State._gather_pillar"): minion_opts = salt.config.DEFAULT_MINION_OPTS.copy() state_obj = salt.state.State(minion_opts) return_result = state_obj._run_check_onlyif(low_data, "") @@ -122,8 +124,10 @@ def test_verify_onlyif_parse_deep_return(): "fun": "nop", } expected_result = {"comment": "onlyif condition is true", "result": False} + for key in ("__sls__", "__id__", "name"): + expected_result[key] = low_data.get(key) - with patch("salt.state.State._gather_pillar") as state_patch: + with patch("salt.state.State._gather_pillar"): minion_opts = salt.config.DEFAULT_MINION_OPTS.copy() state_obj = salt.state.State(minion_opts) return_result = state_obj._run_check_onlyif(low_data, "") @@ -151,8 +155,10 @@ def test_verify_onlyif_cmd_error(): "result": True, "skip_watch": True, } + for key in ("__sls__", "__id__", "name"): + expected_result[key] = low_data.get(key) - with patch("salt.state.State._gather_pillar") as state_patch: + with patch("salt.state.State._gather_pillar"): minion_opts = salt.config.DEFAULT_MINION_OPTS.copy() state_obj = salt.state.State(minion_opts) mock = MagicMock(side_effect=CommandExecutionError("Boom!")) @@ -185,8 +191,10 @@ def test_verify_unless_cmd_error(): "result": True, "skip_watch": True, } + for key in ("__sls__", "__id__", "name"): + expected_result[key] = low_data.get(key) - with patch("salt.state.State._gather_pillar") as state_patch: + with patch("salt.state.State._gather_pillar"): minion_opts = salt.config.DEFAULT_MINION_OPTS.copy() state_obj = salt.state.State(minion_opts) mock = MagicMock(side_effect=CommandExecutionError("Boom!")) @@ -217,7 +225,9 @@ def test_verify_unless_list_cmd(): "comment": "unless condition is false", "result": False, } - with patch("salt.state.State._gather_pillar") as state_patch: + for key in ("__sls__", "__id__", "name"): + expected_result[key] = low_data.get(key) + with patch("salt.state.State._gather_pillar"): minion_opts = salt.config.DEFAULT_MINION_OPTS.copy() state_obj = salt.state.State(minion_opts) return_result = state_obj._run_check_unless(low_data, {}) @@ -243,7 +253,9 @@ def test_verify_unless_list_cmd_different_order(): "comment": "unless condition is false", "result": False, } - with patch("salt.state.State._gather_pillar") as state_patch: + for key in ("__sls__", "__id__", "name"): + expected_result[key] = low_data.get(key) + with patch("salt.state.State._gather_pillar"): minion_opts = salt.config.DEFAULT_MINION_OPTS.copy() state_obj = salt.state.State(minion_opts) return_result = state_obj._run_check_unless(low_data, {}) @@ -266,7 +278,9 @@ def test_verify_onlyif_list_cmd_different_order(): "result": True, "skip_watch": True, } - with patch("salt.state.State._gather_pillar") as state_patch: + for key in ("__sls__", "__id__", "name"): + expected_result[key] = low_data.get(key) + with patch("salt.state.State._gather_pillar"): minion_opts = salt.config.DEFAULT_MINION_OPTS.copy() state_obj = salt.state.State(minion_opts) return_result = state_obj._run_check_onlyif(low_data, {}) @@ -289,7 +303,9 @@ def test_verify_unless_list_cmd_valid(): "fun": "run", } expected_result = {"comment": "unless condition is false", "result": False} - with patch("salt.state.State._gather_pillar") as state_patch: + for key in ("__sls__", "__id__", "name"): + expected_result[key] = low_data.get(key) + with patch("salt.state.State._gather_pillar"): minion_opts = salt.config.DEFAULT_MINION_OPTS.copy() state_obj = salt.state.State(minion_opts) return_result = state_obj._run_check_unless(low_data, {}) @@ -308,7 +324,9 @@ def test_verify_onlyif_list_cmd_valid(): "fun": "run", } expected_result = {"comment": "onlyif condition is true", "result": False} - with patch("salt.state.State._gather_pillar") as state_patch: + for key in ("__sls__", "__id__", "name"): + expected_result[key] = low_data.get(key) + with patch("salt.state.State._gather_pillar"): minion_opts = salt.config.DEFAULT_MINION_OPTS.copy() state_obj = salt.state.State(minion_opts) return_result = state_obj._run_check_onlyif(low_data, {}) @@ -335,7 +353,9 @@ def test_verify_unless_list_cmd_invalid(): "result": True, "skip_watch": True, } - with patch("salt.state.State._gather_pillar") as state_patch: + for key in ("__sls__", "__id__", "name"): + expected_result[key] = low_data.get(key) + with patch("salt.state.State._gather_pillar"): minion_opts = salt.config.DEFAULT_MINION_OPTS.copy() state_obj = salt.state.State(minion_opts) return_result = state_obj._run_check_unless(low_data, {}) @@ -358,7 +378,9 @@ def test_verify_onlyif_list_cmd_invalid(): "result": True, "skip_watch": True, } - with patch("salt.state.State._gather_pillar") as state_patch: + for key in ("__sls__", "__id__", "name"): + expected_result[key] = low_data.get(key) + with patch("salt.state.State._gather_pillar"): minion_opts = salt.config.DEFAULT_MINION_OPTS.copy() state_obj = salt.state.State(minion_opts) return_result = state_obj._run_check_onlyif(low_data, {}) @@ -384,8 +406,10 @@ def test_verify_unless_parse(): "result": True, "skip_watch": True, } + for key in ("__sls__", "__id__", "name"): + expected_result[key] = low_data.get(key) - with patch("salt.state.State._gather_pillar") as state_patch: + with patch("salt.state.State._gather_pillar"): minion_opts = salt.config.DEFAULT_MINION_OPTS.copy() state_obj = salt.state.State(minion_opts) return_result = state_obj._run_check_unless(low_data, "") @@ -410,8 +434,10 @@ def test_verify_unless_parse_deep_return(): "fun": "nop", } expected_result = {"comment": "unless condition is false", "result": False} + for key in ("__sls__", "__id__", "name"): + expected_result[key] = low_data.get(key) - with patch("salt.state.State._gather_pillar") as state_patch: + with patch("salt.state.State._gather_pillar"): minion_opts = salt.config.DEFAULT_MINION_OPTS.copy() state_obj = salt.state.State(minion_opts) return_result = state_obj._run_check_unless(low_data, "") @@ -430,7 +456,7 @@ def test_verify_creates(): "fun": "run", } - with patch("salt.state.State._gather_pillar") as state_patch: + with patch("salt.state.State._gather_pillar"): minion_opts = salt.config.DEFAULT_MINION_OPTS.copy() state_obj = salt.state.State(minion_opts) with patch("os.path.exists") as path_mock: @@ -440,6 +466,8 @@ def test_verify_creates(): "result": True, "skip_watch": True, } + for key in ("__sls__", "__id__", "name"): + expected_result[key] = low_data.get(key) return_result = state_obj._run_check_creates(low_data) assert expected_result == return_result @@ -448,6 +476,8 @@ def test_verify_creates(): "comment": "Creates files not found", "result": False, } + for key in ("__sls__", "__id__", "name"): + expected_result[key] = low_data.get(key) return_result = state_obj._run_check_creates(low_data) assert expected_result == return_result @@ -464,7 +494,7 @@ def test_verify_creates_list(): "fun": "run", } - with patch("salt.state.State._gather_pillar") as state_patch: + with patch("salt.state.State._gather_pillar"): minion_opts = salt.config.DEFAULT_MINION_OPTS.copy() state_obj = salt.state.State(minion_opts) with patch("os.path.exists") as path_mock: @@ -474,6 +504,8 @@ def test_verify_creates_list(): "result": True, "skip_watch": True, } + for key in ("__sls__", "__id__", "name"): + expected_result[key] = low_data.get(key) return_result = state_obj._run_check_creates(low_data) assert expected_result == return_result @@ -482,6 +514,8 @@ def test_verify_creates_list(): "comment": "Creates files not found", "result": False, } + for key in ("__sls__", "__id__", "name"): + expected_result[key] = low_data.get(key) return_result = state_obj._run_check_creates(low_data) assert expected_result == return_result @@ -524,7 +558,9 @@ def test_verify_onlyif_parse_slots(tmp_path): "order": 10000, } expected_result = {"comment": "onlyif condition is true", "result": False} - with patch("salt.state.State._gather_pillar") as state_patch: + for key in ("__sls__", "__id__", "name"): + expected_result[key] = low_data.get(key) + with patch("salt.state.State._gather_pillar"): minion_opts = salt.config.DEFAULT_MINION_OPTS.copy() state_obj = salt.state.State(minion_opts) return_result = state_obj._run_check_onlyif(low_data, "") @@ -547,7 +583,9 @@ def test_verify_onlyif_list_cmd(): "result": True, "skip_watch": True, } - with patch("salt.state.State._gather_pillar") as state_patch: + for key in ("__sls__", "__id__", "name"): + expected_result[key] = low_data.get(key) + with patch("salt.state.State._gather_pillar"): minion_opts = salt.config.DEFAULT_MINION_OPTS.copy() state_obj = salt.state.State(minion_opts) return_result = state_obj._run_check_onlyif(low_data, {}) @@ -578,7 +616,7 @@ def test_verify_onlyif_cmd_args(): "order": 10000, } - with patch("salt.state.State._gather_pillar") as state_patch: + with patch("salt.state.State._gather_pillar"): minion_opts = salt.config.DEFAULT_MINION_OPTS.copy() state_obj = salt.state.State(minion_opts) mock = MagicMock() @@ -629,8 +667,10 @@ def test_verify_unless_parse_slots(tmp_path): "result": True, "skip_watch": True, } + for key in ("__sls__", "__id__", "name"): + expected_result[key] = low_data.get(key) - with patch("salt.state.State._gather_pillar") as state_patch: + with patch("salt.state.State._gather_pillar"): minion_opts = salt.config.DEFAULT_MINION_OPTS.copy() state_obj = salt.state.State(minion_opts) return_result = state_obj._run_check_unless(low_data, "") @@ -654,19 +694,18 @@ def test_verify_retry_parsing(): "fun": "managed", } expected_result = { - "__id__": "download sample data", "__run_num__": 0, - "__sls__": "demo.download", "changes": {}, "comment": "['unless condition is true'] The state would be retried every 5 " "seconds (with a splay of up to 0 seconds) a maximum of 5 times or " "until a result of True is returned", - "name": "/tmp/saltstack.README.rst", "result": True, "skip_watch": True, } + for key in ("__sls__", "__id__", "name"): + expected_result[key] = low_data.get(key) - with patch("salt.state.State._gather_pillar") as state_patch: + with patch("salt.state.State._gather_pillar"): minion_opts = salt.config.DEFAULT_MINION_OPTS.copy() minion_opts["test"] = True minion_opts["file_client"] = "local" @@ -685,7 +724,7 @@ def test_render_requisite_require_disabled(tmp_path): 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: + with patch("salt.state.State._gather_pillar"): high_data = { "step_one": OrderedDict( [ @@ -726,7 +765,7 @@ def test_render_requisite_require_in_disabled(tmp_path): 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: + with patch("salt.state.State._gather_pillar"): high_data = { "step_one": { "test": ["succeed_with_changes", {"order": 10000}], @@ -799,7 +838,7 @@ def test_call_chunk_sub_state_run(): expected_sub_state_tag = ( "external_state_|-external_state_id_|-external_state_name_|-external_function" ) - with patch("salt.state.State._gather_pillar") as state_patch: + with patch("salt.state.State._gather_pillar"): with patch("salt.state.State.call", return_value=mock_call_return): minion_opts = salt.config.DEFAULT_MINION_OPTS.copy() minion_opts["disabled_requisites"] = ["require"] @@ -920,7 +959,7 @@ def test_aggregate_requisites(): }, ] - with patch("salt.state.State._gather_pillar") as state_patch: + with patch("salt.state.State._gather_pillar"): minion_opts = salt.config.DEFAULT_MINION_OPTS.copy() state_obj = salt.state.State(minion_opts) low_ret = state_obj._aggregate_requisites(low, chunks) @@ -1006,7 +1045,7 @@ def test_mod_aggregate(): "pkgs": ["figlet", "sl"], } - with patch("salt.state.State._gather_pillar") as state_patch: + with patch("salt.state.State._gather_pillar"): minion_opts = salt.config.DEFAULT_MINION_OPTS.copy() state_obj = salt.state.State(minion_opts) with patch.dict(