Fixes cmd.run with requisites on Windows

Formats the command properly for powershell
Adds changelog and tests
This commit is contained in:
Shane Lee 2024-07-17 14:47:14 -06:00 committed by Daniel Wozniak
parent 176bd3aca8
commit 0fcde71062
5 changed files with 84 additions and 6 deletions

2
changelog/66596.fixed.md Normal file
View file

@ -0,0 +1,2 @@
Fixed an issue with cmd.run with requirements when the shell is not the
default

View file

@ -290,7 +290,11 @@ def _prep_powershell_cmd(win_shell, cmd, encoded_cmd):
# Strip whitespace # Strip whitespace
if isinstance(cmd, list): if isinstance(cmd, list):
cmd = " ".join(cmd) cmd = " ".join(cmd)
new_cmd.extend(["-Command", f"& {{{cmd.strip()}}}"])
if cmd.startswith("$"):
new_cmd.extend(["-Command", f"{cmd.strip()}"])
else:
new_cmd.extend(["-Command", f"& {cmd.strip()}"])
log.debug(new_cmd) log.debug(new_cmd)
return new_cmd return new_cmd
@ -4104,6 +4108,7 @@ def powershell(
cmd = salt.utils.stringutils.to_str(cmd) cmd = salt.utils.stringutils.to_str(cmd)
encoded_cmd = True encoded_cmd = True
else: else:
cmd = f"{{{cmd}}}"
encoded_cmd = False encoded_cmd = False
# Retrieve the response, while overriding shell with 'powershell' # Retrieve the response, while overriding shell with 'powershell'

View file

@ -0,0 +1,64 @@
import os
import pytest
import salt.utils.path
pytestmark = [
pytest.mark.windows_whitelisted,
pytest.mark.skip_unless_on_windows,
pytest.mark.destructive_test,
pytest.mark.slow_test,
]
@pytest.fixture(params=["powershell", "pwsh"])
def shell(request):
"""
This will run the test on powershell and powershell core (pwsh). If
powershell core is not installed that test run will be skipped
"""
if request.param == "pwsh" and salt.utils.path.which("pwsh") is None:
pytest.skip("Powershell 7 Not Present")
return request.param
def test_cmd_run_unless_true(shell, cmd):
# We need a directory that we know exists that has stuff in it
win_dir = os.getenv("WINDIR")
ret = cmd.run(name="echo foo", unless=f"ls {win_dir}", shell=shell)
assert ret.filtered["result"] is True
assert ret.filtered["name"] == "echo foo"
assert ret.filtered["comment"] == "unless condition is true"
assert ret.filtered["changes"] == {}
def test_cmd_run_unless_false(shell, cmd):
# We need a directory that we know does not exist
win_dir = "C:\\This\\Dir\\Does\\Not\\Exist"
ret = cmd.run(name="echo foo", unless=f"ls {win_dir}", shell=shell)
assert ret.filtered["result"] is True
assert ret.filtered["name"] == "echo foo"
assert ret.filtered["comment"] == 'Command "echo foo" run'
assert ret.filtered["changes"]["stdout"] == "foo"
def test_cmd_run_onlyif_true(shell, cmd):
# We need a directory that we know exists that has stuff in it
win_dir = os.getenv("WINDIR")
ret = cmd.run(name="echo foo", onlyif=f"ls {win_dir}", shell=shell)
assert ret.filtered["result"] is True
assert ret.filtered["name"] == "echo foo"
assert ret.filtered["comment"] == 'Command "echo foo" run'
assert ret.filtered["changes"]["stdout"] == "foo"
def test_cmd_run_onlyif_false(shell, cmd):
# We need a directory that we know does not exist
win_dir = "C:\\This\\Dir\\Does\\Not\\Exist"
ret = cmd.run(name="echo foo", onlyif=f"ls {win_dir}", shell=shell)
assert ret.filtered["result"] is True
assert ret.filtered["name"] == "echo foo"
assert ret.filtered["comment"] == "onlyif condition is false"
assert ret.filtered["changes"] == {}

View file

@ -1059,7 +1059,14 @@ def test_prep_powershell_cmd_no_powershell():
) )
def test_prep_powershell_cmd(): @pytest.mark.parametrize(
"cmd, parsed",
[
("Write-Host foo", "& Write-Host foo"),
("$PSVersionTable", "$PSVersionTable"),
],
)
def test_prep_powershell_cmd(cmd, parsed):
""" """
Tests _prep_powershell_cmd returns correct cmd Tests _prep_powershell_cmd returns correct cmd
""" """
@ -1068,7 +1075,7 @@ def test_prep_powershell_cmd():
"salt.utils.path.which", return_value="C:\\powershell.exe" "salt.utils.path.which", return_value="C:\\powershell.exe"
): ):
ret = cmdmod._prep_powershell_cmd( ret = cmdmod._prep_powershell_cmd(
win_shell="powershell", cmd="$PSVersionTable", encoded_cmd=False win_shell="powershell", cmd=cmd, encoded_cmd=False
) )
expected = [ expected = [
"C:\\powershell.exe", "C:\\powershell.exe",
@ -1077,7 +1084,7 @@ def test_prep_powershell_cmd():
"-ExecutionPolicy", "-ExecutionPolicy",
"Bypass", "Bypass",
"-Command", "-Command",
"& {$PSVersionTable}", parsed,
] ]
assert ret == expected assert ret == expected

View file

@ -474,10 +474,10 @@ def test_install_venv():
) )
def test_install_log_argument_in_resulting_command(python_binary): def test_install_log_argument_in_resulting_command(python_binary, tmp_path):
with patch("os.access") as mock_path: with patch("os.access") as mock_path:
pkg = "pep8" pkg = "pep8"
log_path = "/tmp/pip-install.log" log_path = str(tmp_path / "pip-install.log")
mock = MagicMock(return_value={"retcode": 0, "stdout": ""}) mock = MagicMock(return_value={"retcode": 0, "stdout": ""})
with patch.dict(pip.__salt__, {"cmd.run_all": mock}): with patch.dict(pip.__salt__, {"cmd.run_all": mock}):
pip.install(pkg, log=log_path) pip.install(pkg, log=log_path)