diff --git a/changelog/60003.fixed b/changelog/60003.fixed new file mode 100644 index 00000000000..7b0ccd4010c --- /dev/null +++ b/changelog/60003.fixed @@ -0,0 +1 @@ +Fix salt-ssh when using imports with extra-filerefs. diff --git a/salt/client/ssh/wrapper/state.py b/salt/client/ssh/wrapper/state.py index 4787ce6eb52..5bfc1ecd049 100644 --- a/salt/client/ssh/wrapper/state.py +++ b/salt/client/ssh/wrapper/state.py @@ -768,7 +768,7 @@ def top(topfn, test=None, **kwargs): ) as st_: st_.opts["state_top"] = os.path.join("salt://", topfn) st_.push_active() - chunks = st_.compile_low_chunks() + chunks = st_.compile_low_chunks(context=__context__.value()) file_refs = salt.client.ssh.state.lowstate_file_refs( chunks, _merge_extra_filerefs( @@ -840,7 +840,7 @@ def show_highstate(**kwargs): context=__context__.value(), ) as st_: st_.push_active() - chunks = st_.compile_highstate() + chunks = st_.compile_highstate(context=__context__.value()) _cleanup_slsmod_high_data(chunks) return chunks @@ -865,7 +865,7 @@ def show_lowstate(**kwargs): context=__context__.value(), ) as st_: st_.push_active() - chunks = st_.compile_low_chunks() + chunks = st_.compile_low_chunks(context=__context__.value()) _cleanup_slsmod_low_data(chunks) return chunks @@ -932,7 +932,9 @@ def sls_id(id_, mods, test=None, queue=False, **kwargs): split_mods = _parse_mods(mods) st_.push_active() - high_, errors = st_.render_highstate({opts["saltenv"]: split_mods}) + high_, errors = st_.render_highstate( + {opts["saltenv"]: split_mods}, context=__context__.value() + ) errors += st_.state.verify_high(high_) # Apply requisites to high data high_, req_in_errors = st_.state.requisite_in(high_) @@ -988,7 +990,9 @@ def show_sls(mods, saltenv="base", test=None, **kwargs): ) as st_: st_.push_active() mods = _parse_mods(mods) - high_data, errors = st_.render_highstate({saltenv: mods}) + high_data, errors = st_.render_highstate( + {saltenv: mods}, context=__context__.value() + ) high_data, ext_errors = st_.state.reconcile_extend(high_data) errors += ext_errors errors += st_.state.verify_high(high_data) @@ -1015,7 +1019,7 @@ def show_low_sls(mods, saltenv="base", test=None, **kwargs): .. code-block:: bash - salt '*' state.show_sls core,edit.vim dev + salt '*' state.show_low_sls core,edit.vim dev """ __pillar__.update(kwargs.get("pillar", {})) __opts__["grains"] = __grains__.value() @@ -1034,7 +1038,9 @@ def show_low_sls(mods, saltenv="base", test=None, **kwargs): ) as st_: st_.push_active() mods = _parse_mods(mods) - high_data, errors = st_.render_highstate({saltenv: mods}) + high_data, errors = st_.render_highstate( + {saltenv: mods}, context=__context__.value() + ) high_data, ext_errors = st_.state.reconcile_extend(high_data) errors += ext_errors errors += st_.state.verify_high(high_data) @@ -1070,7 +1076,7 @@ def show_top(**kwargs): __context__["fileclient"], context=__context__.value(), ) as st_: - top_data = st_.get_top(context=__context__) + top_data = st_.get_top(context=__context__.value()) errors = [] errors += st_.verify_tops(top_data) if errors: diff --git a/salt/state.py b/salt/state.py index 6f71020040a..60f53af252d 100644 --- a/salt/state.py +++ b/salt/state.py @@ -4768,15 +4768,15 @@ class BaseHighState: return self.state.call_high(high, orchestration_jid) - def compile_highstate(self): + def compile_highstate(self, context=None): """ Return just the highstate or the errors """ err = [] - top = self.get_top() + top = self.get_top(context=context) err += self.verify_tops(top) matches = self.top_matches(top) - high, errors = self.render_highstate(matches) + high, errors = self.render_highstate(matches, context=context) err += errors if err: diff --git a/tests/pytests/integration/ssh/test_state.py b/tests/pytests/integration/ssh/test_state.py index 9520a660e03..9d3a38d2c9f 100644 --- a/tests/pytests/integration/ssh/test_state.py +++ b/tests/pytests/integration/ssh/test_state.py @@ -22,7 +22,6 @@ def state_tree(base_env_state_tree_root_dir): """ state_file = """ {%- from "map.jinja" import abc with context %} - Ok with {{ abc }}: test.succeed_without_changes """ @@ -35,27 +34,117 @@ def state_tree(base_env_state_tree_root_dir): state_tempfile = pytest.helpers.temp_file( "test.sls", state_file, base_env_state_tree_root_dir ) + with top_tempfile, map_tempfile, state_tempfile: + yield + + +@pytest.fixture(scope="module") +def state_tree_dir(base_env_state_tree_root_dir): + """ + State tree with files to test salt-ssh + when the map.jinja file is in another directory + """ + top_file = """ + {%- from "test/map.jinja" import abc with context %} + base: + 'localhost': + - test + '127.0.0.1': + - test + """ + map_file = """ + {%- set abc = "def" %} + """ + state_file = """ + {%- from "test/map.jinja" import abc with context %} + + Ok with {{ abc }}: + test.succeed_without_changes + """ + top_tempfile = pytest.helpers.temp_file( + "top.sls", top_file, base_env_state_tree_root_dir + ) + map_tempfile = pytest.helpers.temp_file( + "test/map.jinja", map_file, base_env_state_tree_root_dir + ) + state_tempfile = pytest.helpers.temp_file( + "test.sls", state_file, base_env_state_tree_root_dir + ) with top_tempfile, map_tempfile, state_tempfile: yield -@pytest.mark.parametrize( - "ssh_cmd", ["state.sls", "state.highstate", "state.apply", "state.show_top"] -) @pytest.mark.slow_test -def test_state_with_import(salt_ssh_cli, state_tree, ssh_cmd): +def test_state_with_import(salt_ssh_cli, state_tree): """ verify salt-ssh can use imported map files in states """ - if ssh_cmd == "state.sls": - ret = salt_ssh_cli.run(ssh_cmd, "test") - else: - ret = salt_ssh_cli.run(ssh_cmd) + ret = salt_ssh_cli.run("state.sls", "test") assert ret.returncode == 0 assert ret.data +@pytest.mark.parametrize( + "ssh_cmd", + [ + "state.sls", + "state.highstate", + "state.apply", + "state.show_top", + "state.show_highstate", + "state.show_low_sls", + "state.show_lowstate", + "state.sls_id", + "state.show_sls", + "state.top", + ], +) +@pytest.mark.slow_test +def test_state_with_import_dir(salt_ssh_cli, state_tree_dir, ssh_cmd): + """ + verify salt-ssh can use imported map files in states + when the map files are in another directory outside of + sls files importing them. + """ + if ssh_cmd in ("state.sls", "state.show_low_sls", "state.show_sls"): + ret = salt_ssh_cli.run("-w", "-t", ssh_cmd, "test") + elif ssh_cmd == "state.top": + ret = salt_ssh_cli.run("-w", "-t", ssh_cmd, "top.sls") + elif ssh_cmd == "state.sls_id": + ret = salt_ssh_cli.run("-w", "-t", ssh_cmd, "Ok with def", "test") + else: + ret = salt_ssh_cli.run("-w", "-t", ssh_cmd) + assert ret.returncode == 0 + if ssh_cmd == "state.show_top": + assert ret.data == {"base": ["test", "master_tops_test"]} or {"base": ["test"]} + elif ssh_cmd in ("state.show_highstate", "state.show_sls"): + assert ret.data == { + "Ok with def": { + "__sls__": "test", + "__env__": "base", + "test": ["succeed_without_changes", {"order": 10000}], + } + } + elif ssh_cmd in ("state.show_low_sls", "state.show_lowstate", "state.show_sls"): + assert ret.data == [ + { + "state": "test", + "name": "Ok with def", + "__sls__": "test", + "__env__": "base", + "__id__": "Ok with def", + "order": 10000, + "fun": "succeed_without_changes", + } + ] + else: + assert ret.data["test_|-Ok with def_|-Ok with def_|-succeed_without_changes"][ + "result" + ] + assert ret.data + + @pytest.fixture def nested_state_tree(base_env_state_tree_root_dir, tmp_path): top_file = """