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
if isinstance(cmd, list):
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)
return new_cmd
@ -4104,6 +4108,7 @@ def powershell(
cmd = salt.utils.stringutils.to_str(cmd)
encoded_cmd = True
else:
cmd = f"{{{cmd}}}"
encoded_cmd = False
# 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
"""
@ -1068,7 +1075,7 @@ def test_prep_powershell_cmd():
"salt.utils.path.which", return_value="C:\\powershell.exe"
):
ret = cmdmod._prep_powershell_cmd(
win_shell="powershell", cmd="$PSVersionTable", encoded_cmd=False
win_shell="powershell", cmd=cmd, encoded_cmd=False
)
expected = [
"C:\\powershell.exe",
@ -1077,7 +1084,7 @@ def test_prep_powershell_cmd():
"-ExecutionPolicy",
"Bypass",
"-Command",
"& {$PSVersionTable}",
parsed,
]
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:
pkg = "pep8"
log_path = "/tmp/pip-install.log"
log_path = str(tmp_path / "pip-install.log")
mock = MagicMock(return_value={"retcode": 0, "stdout": ""})
with patch.dict(pip.__salt__, {"cmd.run_all": mock}):
pip.install(pkg, log=log_path)