mirror of
https://github.com/saltstack/salt.git
synced 2025-04-16 09:40:20 +00:00
Fix some tests
This commit is contained in:
parent
dccf230a01
commit
580ad437fd
8 changed files with 122 additions and 54 deletions
|
@ -1,6 +1,5 @@
|
||||||
Fixes multiple issues with the cmd module on Windows. ``stderr`` is no
|
Fixes multiple issues with the cmd module on Windows. Scripts are called using
|
||||||
longer piped to ``stdout`` by default on ``cmd.run``. Scripts are called
|
the ``-File`` parameter to the ``powershell.exe`` binary. ``CLIXML`` data in
|
||||||
using the ``-File`` parameter to the ``powershell.exe`` binary. ``CLIXML``
|
stderr is now removed (only applies to encoded commands). Commands can now be
|
||||||
data in stderr is now removed (only applies to encoded commands). Commands can
|
sent to ``cmd.powershell`` as a list. Makes sure JSON data returned is valid.
|
||||||
now be sent to ``cmd.powershell`` as a list. Makes sure JSON data returned is
|
Strips whitespace from the return when using ``runas``.
|
||||||
valid. Strips whitespace from the return when using ``runas``.
|
|
||||||
|
|
|
@ -276,16 +276,21 @@ def _prep_powershell_cmd(win_shell, cmd, encoded_cmd):
|
||||||
stack = traceback.extract_stack(limit=3)
|
stack = traceback.extract_stack(limit=3)
|
||||||
if stack[-3][2] == "script":
|
if stack[-3][2] == "script":
|
||||||
# If this is cmd.script, then we're running a file
|
# If this is cmd.script, then we're running a file
|
||||||
new_cmd.extend(["-File", f"{cmd}"])
|
# You might be tempted to use -File here instead of -Command
|
||||||
|
# The problem with using -File is that any arguments that contain
|
||||||
|
# powershell commands themselves will not be evaluated
|
||||||
|
# See GitHub issue #56195
|
||||||
|
new_cmd.append("-Command")
|
||||||
|
if isinstance(cmd, list):
|
||||||
|
cmd = " ".join(cmd)
|
||||||
|
new_cmd.append(f"& {cmd.strip()}")
|
||||||
elif encoded_cmd:
|
elif encoded_cmd:
|
||||||
new_cmd.extend(["-EncodedCommand", f"{cmd}"])
|
new_cmd.extend(["-EncodedCommand", f"{cmd}"])
|
||||||
else:
|
else:
|
||||||
# Strip whitespace
|
# Strip whitespace
|
||||||
if isinstance(cmd, str):
|
if isinstance(cmd, list):
|
||||||
cmd = cmd.strip()
|
cmd = " ".join(cmd)
|
||||||
elif isinstance(cmd, list):
|
new_cmd.extend(["-Command", f"& {{{cmd.strip()}}}"])
|
||||||
cmd = " ".join(cmd).strip()
|
|
||||||
new_cmd.extend(["-Command", f"& {{{cmd}}}"])
|
|
||||||
|
|
||||||
log.debug(new_cmd)
|
log.debug(new_cmd)
|
||||||
return new_cmd
|
return new_cmd
|
||||||
|
|
|
@ -450,7 +450,9 @@ def get_config():
|
||||||
raise
|
raise
|
||||||
|
|
||||||
config = dict()
|
config = dict()
|
||||||
if raw_config:
|
if not raw_config:
|
||||||
|
raise CommandExecutionError("Not Configured")
|
||||||
|
else:
|
||||||
# Does this Configuration contain a single resource
|
# Does this Configuration contain a single resource
|
||||||
if "ConfigurationName" in raw_config:
|
if "ConfigurationName" in raw_config:
|
||||||
# Load the single resource
|
# Load the single resource
|
||||||
|
@ -606,11 +608,13 @@ def test_config():
|
||||||
"""
|
"""
|
||||||
cmd = "Test-DscConfiguration"
|
cmd = "Test-DscConfiguration"
|
||||||
try:
|
try:
|
||||||
_pshell(cmd, ignore_retcode=True)
|
result = _pshell(cmd, ignore_retcode=True)
|
||||||
except CommandExecutionError as exc:
|
except CommandExecutionError as exc:
|
||||||
if "Current configuration does not exist" in exc.info["stderr"]:
|
if "Current configuration does not exist" in exc.info["stderr"]:
|
||||||
raise CommandExecutionError("Not Configured")
|
raise CommandExecutionError("Not Configured")
|
||||||
raise
|
raise
|
||||||
|
if not result:
|
||||||
|
raise CommandExecutionError("Not Configured")
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
@ -635,11 +639,14 @@ def get_config_status():
|
||||||
"Type, Mode, RebootRequested, NumberofResources"
|
"Type, Mode, RebootRequested, NumberofResources"
|
||||||
)
|
)
|
||||||
try:
|
try:
|
||||||
return _pshell(cmd, ignore_retcode=True)
|
result = _pshell(cmd, ignore_retcode=True)
|
||||||
except CommandExecutionError as exc:
|
except CommandExecutionError as exc:
|
||||||
if "No status information available" in exc.info["stderr"]:
|
if "No status information available" in exc.info["stderr"]:
|
||||||
raise CommandExecutionError("Not Configured")
|
raise CommandExecutionError("Not Configured")
|
||||||
raise
|
raise
|
||||||
|
if not result:
|
||||||
|
raise CommandExecutionError("Not Configured")
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
def get_lcm_config():
|
def get_lcm_config():
|
||||||
|
|
|
@ -596,39 +596,3 @@ class CMDModuleTest(ModuleCase):
|
||||||
).splitlines()
|
).splitlines()
|
||||||
self.assertIn("abc=123", out)
|
self.assertIn("abc=123", out)
|
||||||
self.assertIn("ABC=456", out)
|
self.assertIn("ABC=456", out)
|
||||||
|
|
||||||
@pytest.mark.slow_test
|
|
||||||
@pytest.mark.skip_unless_on_windows(reason="Minion is not Windows")
|
|
||||||
def test_windows_powershell_script_args(self):
|
|
||||||
"""
|
|
||||||
Ensure that powershell processes inline script in args
|
|
||||||
"""
|
|
||||||
val = "i like cheese"
|
|
||||||
args = (
|
|
||||||
'-SecureString (ConvertTo-SecureString -String "{}" -AsPlainText -Force)'
|
|
||||||
" -ErrorAction Stop".format(val)
|
|
||||||
)
|
|
||||||
script = "salt://issue-56195/test.ps1"
|
|
||||||
ret = self.run_function(
|
|
||||||
"cmd.script", [script], args=args, shell="powershell", saltenv="base"
|
|
||||||
)
|
|
||||||
self.assertEqual(ret["stdout"], val)
|
|
||||||
|
|
||||||
@pytest.mark.slow_test
|
|
||||||
@pytest.mark.skip_unless_on_windows(reason="Minion is not Windows")
|
|
||||||
@pytest.mark.skip_if_binaries_missing("pwsh")
|
|
||||||
def test_windows_powershell_script_args_pwsh(self):
|
|
||||||
"""
|
|
||||||
Ensure that powershell processes inline script in args with powershell
|
|
||||||
core
|
|
||||||
"""
|
|
||||||
val = "i like cheese"
|
|
||||||
args = (
|
|
||||||
'-SecureString (ConvertTo-SecureString -String "{}" -AsPlainText -Force)'
|
|
||||||
" -ErrorAction Stop".format(val)
|
|
||||||
)
|
|
||||||
script = "salt://issue-56195/test.ps1"
|
|
||||||
ret = self.run_function(
|
|
||||||
"cmd.script", [script], args=args, shell="pwsh", saltenv="base"
|
|
||||||
)
|
|
||||||
self.assertEqual(ret["stdout"], val)
|
|
||||||
|
|
|
@ -15,6 +15,7 @@ def shell(request):
|
||||||
This will run the test on powershell and powershell core (pwsh). If
|
This will run the test on powershell and powershell core (pwsh). If
|
||||||
powershell core is not installed that test run will be skipped
|
powershell core is not installed that test run will be skipped
|
||||||
"""
|
"""
|
||||||
|
|
||||||
if request.param == "pwsh" and salt.utils.path.which("pwsh") is None:
|
if request.param == "pwsh" and salt.utils.path.which("pwsh") is None:
|
||||||
pytest.skip("Powershell 7 Not Present")
|
pytest.skip("Powershell 7 Not Present")
|
||||||
return request.param
|
return request.param
|
||||||
|
@ -178,7 +179,9 @@ def test_cmd_run_encoded_cmd(shell, cmd, expected, encoded_cmd):
|
||||||
"""
|
"""
|
||||||
Ensure that cmd.run supports running shell='powershell'
|
Ensure that cmd.run supports running shell='powershell'
|
||||||
"""
|
"""
|
||||||
ret = cmdmod.run(cmd=cmd, shell=shell, encoded_cmd=encoded_cmd, redirect_stderr=False)
|
ret = cmdmod.run(
|
||||||
|
cmd=cmd, shell=shell, encoded_cmd=encoded_cmd, redirect_stderr=False
|
||||||
|
)
|
||||||
assert ret == expected
|
assert ret == expected
|
||||||
|
|
||||||
|
|
||||||
|
|
87
tests/pytests/functional/modules/cmd/test_script.py
Normal file
87
tests/pytests/functional/modules/cmd/test_script.py
Normal file
|
@ -0,0 +1,87 @@
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
import salt.utils.path
|
||||||
|
|
||||||
|
pytestmark = [
|
||||||
|
pytest.mark.core_test,
|
||||||
|
pytest.mark.windows_whitelisted,
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture(scope="module")
|
||||||
|
def cmd(modules):
|
||||||
|
return modules.cmd
|
||||||
|
|
||||||
|
|
||||||
|
@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
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture(scope="module")
|
||||||
|
def account():
|
||||||
|
with pytest.helpers.create_account() as _account:
|
||||||
|
yield _account
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def issue_56195(state_tree):
|
||||||
|
contents = """
|
||||||
|
[CmdLetBinding()]
|
||||||
|
Param(
|
||||||
|
[SecureString] $SecureString
|
||||||
|
)
|
||||||
|
$Credential = New-Object System.Net.NetworkCredential("DummyId", $SecureString)
|
||||||
|
$Credential.Password
|
||||||
|
"""
|
||||||
|
with pytest.helpers.temp_file("test.ps1", contents, state_tree / "issue-56195"):
|
||||||
|
yield
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.skip_unless_on_windows(reason="Minion is not Windows")
|
||||||
|
def test_windows_script_args_powershell(cmd, shell, issue_56195):
|
||||||
|
"""
|
||||||
|
Ensure that powershell processes an inline script with args where the args
|
||||||
|
contain powershell that needs to be rendered
|
||||||
|
"""
|
||||||
|
password = "i like cheese"
|
||||||
|
args = (
|
||||||
|
"-SecureString (ConvertTo-SecureString -String '{}' -AsPlainText -Force)"
|
||||||
|
" -ErrorAction Stop".format(password)
|
||||||
|
)
|
||||||
|
script = "salt://issue-56195/test.ps1"
|
||||||
|
|
||||||
|
ret = cmd.script(source=script, args=args, shell="powershell", saltenv="base")
|
||||||
|
|
||||||
|
assert ret["stdout"] == password
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.skip_unless_on_windows(reason="Minion is not Windows")
|
||||||
|
def test_windows_script_args_powershell_runas(cmd, shell, account, issue_56195):
|
||||||
|
"""
|
||||||
|
Ensure that powershell processes an inline script with args where the args
|
||||||
|
contain powershell that needs to be rendered
|
||||||
|
"""
|
||||||
|
password = "i like cheese"
|
||||||
|
args = (
|
||||||
|
"-SecureString (ConvertTo-SecureString -String '{}' -AsPlainText -Force)"
|
||||||
|
" -ErrorAction Stop".format(password)
|
||||||
|
)
|
||||||
|
script = "salt://issue-56195/test.ps1"
|
||||||
|
|
||||||
|
ret = cmd.script(
|
||||||
|
source=script,
|
||||||
|
args=args,
|
||||||
|
shell="powershell",
|
||||||
|
saltenv="base",
|
||||||
|
runas=account.username,
|
||||||
|
password=account.password,
|
||||||
|
)
|
||||||
|
|
||||||
|
assert ret["stdout"] == password
|
|
@ -333,6 +333,9 @@ def test_setpassword_int(user, account_int):
|
||||||
)
|
)
|
||||||
def test_update_str(user, value_name, new_value, info_field, expected, account_str):
|
def test_update_str(user, value_name, new_value, info_field, expected, account_str):
|
||||||
setting = {value_name: new_value}
|
setting = {value_name: new_value}
|
||||||
|
# You can't expire an account if the password never expires
|
||||||
|
if value_name == "expired":
|
||||||
|
setting.update({"password_never_expires": not new_value})
|
||||||
ret = user.update(account_str.username, **setting)
|
ret = user.update(account_str.username, **setting)
|
||||||
assert ret is True
|
assert ret is True
|
||||||
ret = user.info(account_str.username)
|
ret = user.info(account_str.username)
|
||||||
|
|
|
@ -1125,8 +1125,8 @@ def test_prep_powershell_cmd_script():
|
||||||
"-NoProfile",
|
"-NoProfile",
|
||||||
"-ExecutionPolicy",
|
"-ExecutionPolicy",
|
||||||
"Bypass",
|
"Bypass",
|
||||||
"-File",
|
"-Command",
|
||||||
script,
|
f"& {script}",
|
||||||
]
|
]
|
||||||
assert ret == expected
|
assert ret == expected
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue