salt/tests/integration/modules/test_cmdmod.py

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

616 lines
20 KiB
Python
Raw Normal View History

2012-03-27 17:05:38 -06:00
import os
import random
import sys
import tempfile
from contextlib import contextmanager
2020-04-02 20:10:20 -05:00
import pytest
Use explicit unicode strings + break up salt.utils This PR is part of what will be an ongoing effort to use explicit unicode strings in Salt. Because Python 3 does not suport Python 2's raw unicode string syntax (i.e. `ur'\d+'`), we must use `salt.utils.locales.sdecode()` to ensure that the raw string is unicode. However, because of how `salt/utils/__init__.py` has evolved into the hulking monstrosity it is today, this means importing a large module in places where it is not needed, which could negatively impact performance. For this reason, this PR also breaks out some of the functions from `salt/utils/__init__.py` into new/existing modules under `salt/utils/`. The long term goal will be that the modules within this directory do not depend on importing `salt.utils`. A summary of the changes in this PR is as follows: * Moves the following functions from `salt.utils` to new locations (including a deprecation warning if invoked from `salt.utils`): `to_bytes`, `to_str`, `to_unicode`, `str_to_num`, `is_quoted`, `dequote`, `is_hex`, `is_bin_str`, `rand_string`, `contains_whitespace`, `clean_kwargs`, `invalid_kwargs`, `which`, `which_bin`, `path_join`, `shlex_split`, `rand_str`, `is_windows`, `is_proxy`, `is_linux`, `is_darwin`, `is_sunos`, `is_smartos`, `is_smartos_globalzone`, `is_smartos_zone`, `is_freebsd`, `is_netbsd`, `is_openbsd`, `is_aix` * Moves the functions already deprecated by @rallytime to the bottom of `salt/utils/__init__.py` for better organization, so we can keep the deprecated ones separate from the ones yet to be deprecated as we continue to break up `salt.utils` * Updates `salt/*.py` and all files under `salt/client/` to use explicit unicode string literals. * Gets rid of implicit imports of `salt.utils` (e.g. `from salt.utils import foo` becomes `import salt.utils.foo as foo`). * Renames the `test.rand_str` function to `test.random_hash` to more accurately reflect what it does * Modifies `salt.utils.stringutils.random()` (née `salt.utils.rand_string()`) such that it returns a string matching the passed size. Previously this function would get `size` bytes from `os.urandom()`, base64-encode it, and return the result, which would in most cases not be equal to the passed size.
2017-07-24 20:47:15 -05:00
import salt.utils.path
2018-03-30 13:12:02 -05:00
import salt.utils.platform
2020-05-18 17:03:53 +01:00
import salt.utils.user
from tests.support.case import ModuleCase
from tests.support.helpers import SKIP_INITIAL_PHOTONOS_FAILURES, dedent
2018-12-07 17:52:49 +00:00
from tests.support.runtests import RUNTIME_VARS
Use explicit unicode strings + break up salt.utils This PR is part of what will be an ongoing effort to use explicit unicode strings in Salt. Because Python 3 does not suport Python 2's raw unicode string syntax (i.e. `ur'\d+'`), we must use `salt.utils.locales.sdecode()` to ensure that the raw string is unicode. However, because of how `salt/utils/__init__.py` has evolved into the hulking monstrosity it is today, this means importing a large module in places where it is not needed, which could negatively impact performance. For this reason, this PR also breaks out some of the functions from `salt/utils/__init__.py` into new/existing modules under `salt/utils/`. The long term goal will be that the modules within this directory do not depend on importing `salt.utils`. A summary of the changes in this PR is as follows: * Moves the following functions from `salt.utils` to new locations (including a deprecation warning if invoked from `salt.utils`): `to_bytes`, `to_str`, `to_unicode`, `str_to_num`, `is_quoted`, `dequote`, `is_hex`, `is_bin_str`, `rand_string`, `contains_whitespace`, `clean_kwargs`, `invalid_kwargs`, `which`, `which_bin`, `path_join`, `shlex_split`, `rand_str`, `is_windows`, `is_proxy`, `is_linux`, `is_darwin`, `is_sunos`, `is_smartos`, `is_smartos_globalzone`, `is_smartos_zone`, `is_freebsd`, `is_netbsd`, `is_openbsd`, `is_aix` * Moves the functions already deprecated by @rallytime to the bottom of `salt/utils/__init__.py` for better organization, so we can keep the deprecated ones separate from the ones yet to be deprecated as we continue to break up `salt.utils` * Updates `salt/*.py` and all files under `salt/client/` to use explicit unicode string literals. * Gets rid of implicit imports of `salt.utils` (e.g. `from salt.utils import foo` becomes `import salt.utils.foo as foo`). * Renames the `test.rand_str` function to `test.random_hash` to more accurately reflect what it does * Modifies `salt.utils.stringutils.random()` (née `salt.utils.rand_string()`) such that it returns a string matching the passed size. Previously this function would get `size` bytes from `os.urandom()`, base64-encode it, and return the result, which would in most cases not be equal to the passed size.
2017-07-24 20:47:15 -05:00
AVAILABLE_PYTHON_EXECUTABLE = salt.utils.path.which_bin(
["python", "python2", "python2.6", "python2.7"]
)
2012-03-27 17:05:38 -06:00
@pytest.mark.windows_whitelisted
class CMDModuleTest(ModuleCase):
2020-04-02 20:10:20 -05:00
"""
2012-03-27 17:05:38 -06:00
Validate the cmd module
2020-04-02 20:10:20 -05:00
"""
def setUp(self):
2018-08-03 15:32:15 -04:00
self.runas_usr = "nobody"
if salt.utils.platform.is_darwin():
self.runas_usr = "macsalttest"
@contextmanager
def _ensure_user_exists(self, name):
if name in self.run_function("user.info", [name]).values():
# User already exists; don't touch
yield
else:
# Need to create user for test
self.run_function("user.add", [name])
try:
yield
finally:
self.run_function("user.delete", [name], remove=True)
@pytest.mark.slow_test
@pytest.mark.skip_on_windows
2012-03-27 17:05:38 -06:00
def test_run(self):
2020-04-02 20:10:20 -05:00
"""
2012-03-27 17:05:38 -06:00
cmd.run
2020-04-02 20:10:20 -05:00
"""
2013-08-10 12:14:10 -06:00
shell = os.environ.get("SHELL")
if shell is None:
# Failed to get the SHELL var, don't run
2013-08-10 19:50:31 +01:00
self.skipTest("Unable to get the SHELL environment variable")
2012-03-27 17:05:38 -06:00
self.assertTrue(self.run_function("cmd.run", ["echo $SHELL"]))
self.assertEqual(
self.run_function(
"cmd.run", ["echo $SHELL", f"shell={shell}"], python_shell=True
).rstrip(),
2020-04-02 20:10:20 -05:00
shell,
)
2012-03-27 17:05:38 -06:00
self.assertEqual(
2014-12-23 13:02:56 -07:00
self.run_function("cmd.run", ["ls / | grep etc"], python_shell=True), "etc"
2020-04-02 20:10:20 -05:00
)
2012-03-27 17:05:38 -06:00
self.assertEqual(
self.run_function(
2020-04-02 20:10:20 -05:00
"cmd.run",
2012-03-27 17:05:38 -06:00
['echo {{grains.id}} | awk "{print $1}"'],
2015-02-23 15:04:43 -07:00
template="jinja",
python_shell=True,
2020-04-02 20:10:20 -05:00
),
"minion",
)
2012-03-27 17:05:38 -06:00
self.assertEqual(
2013-03-21 16:22:29 -06:00
self.run_function(
2015-02-23 15:04:43 -07:00
"cmd.run", ["grep f"], stdin="one\ntwo\nthree\nfour\nfive\n"
),
"four\nfive",
)
self.assertEqual(
self.run_function(
"cmd.run", ["cat"], stdin="one\\ntwo", stdin_raw_newlines=False
),
"one\ntwo",
)
self.assertEqual(
self.run_function(
"cmd.run", ["cat"], stdin="one\\ntwo", stdin_raw_newlines=True
),
"one\\ntwo",
)
2015-02-23 15:04:43 -07:00
self.assertEqual(
self.run_function(
"cmd.run", ['echo "a=b" | sed -e s/=/:/g'], python_shell=True
),
"a:b",
)
2012-03-27 17:05:38 -06:00
@pytest.mark.slow_test
2012-03-27 17:05:38 -06:00
def test_stdout(self):
2020-04-02 20:10:20 -05:00
"""
2012-03-27 17:05:38 -06:00
cmd.run_stdout
2020-04-02 20:10:20 -05:00
"""
2013-03-21 16:22:29 -06:00
self.assertEqual(
self.run_function("cmd.run_stdout", ['echo "cheese"']).rstrip(),
"cheese" if not salt.utils.platform.is_windows() else '"cheese"',
)
2012-03-27 17:05:38 -06:00
@pytest.mark.slow_test
2012-03-27 17:05:38 -06:00
def test_stderr(self):
2020-04-02 20:10:20 -05:00
"""
2012-03-27 17:05:38 -06:00
cmd.run_stderr
2020-04-02 20:10:20 -05:00
"""
2014-09-04 10:23:59 +02:00
if sys.platform.startswith(("freebsd", "openbsd")):
shell = "/bin/sh"
else:
shell = "/bin/bash"
2013-03-21 16:22:29 -06:00
self.assertEqual(
self.run_function(
"cmd.run_stderr",
['echo "cheese" 1>&2', f"shell={shell}"],
2014-12-23 13:02:56 -07:00
python_shell=True,
).rstrip(),
"cheese" if not salt.utils.platform.is_windows() else '"cheese"',
)
2012-03-27 17:05:38 -06:00
@pytest.mark.slow_test
2012-03-27 17:05:38 -06:00
def test_run_all(self):
2020-04-02 20:10:20 -05:00
"""
2012-03-27 17:05:38 -06:00
cmd.run_all
2020-04-02 20:10:20 -05:00
"""
2014-09-04 10:23:59 +02:00
if sys.platform.startswith(("freebsd", "openbsd")):
shell = "/bin/sh"
else:
shell = "/bin/bash"
2020-04-02 20:10:20 -05:00
ret = self.run_function(
"cmd.run_all",
['echo "cheese" 1>&2', f"shell={shell}"],
2014-12-23 13:02:56 -07:00
python_shell=True,
)
2012-03-27 17:05:38 -06:00
self.assertTrue("pid" in ret)
self.assertTrue("retcode" in ret)
self.assertTrue("stdout" in ret)
self.assertTrue("stderr" in ret)
self.assertTrue(isinstance(ret.get("pid"), int))
self.assertTrue(isinstance(ret.get("retcode"), int))
self.assertTrue(isinstance(ret.get("stdout"), str))
self.assertTrue(isinstance(ret.get("stderr"), str))
self.assertEqual(
ret.get("stderr").rstrip(),
"cheese" if not salt.utils.platform.is_windows() else '"cheese"',
)
2012-03-27 17:05:38 -06:00
@pytest.mark.slow_test
2012-03-27 17:05:38 -06:00
def test_retcode(self):
2020-04-02 20:10:20 -05:00
"""
2012-03-27 17:05:38 -06:00
cmd.retcode
2020-04-02 20:10:20 -05:00
"""
2014-12-23 13:02:56 -07:00
self.assertEqual(
self.run_function("cmd.retcode", ["exit 0"], python_shell=True), 0
)
self.assertEqual(
self.run_function("cmd.retcode", ["exit 1"], python_shell=True), 1
)
2012-03-27 17:05:38 -06:00
@pytest.mark.slow_test
2018-02-08 16:04:25 -08:00
def test_run_all_with_success_retcodes(self):
2020-04-02 20:10:20 -05:00
"""
2018-02-08 16:04:25 -08:00
cmd.run with success_retcodes
2020-04-02 20:10:20 -05:00
"""
ret = self.run_function(
2018-02-08 16:04:25 -08:00
"cmd.run_all", ["exit 42"], success_retcodes=[42], python_shell=True
)
self.assertTrue("retcode" in ret)
self.assertEqual(ret.get("retcode"), 0)
@pytest.mark.slow_test
2018-02-08 16:04:25 -08:00
def test_retcode_with_success_retcodes(self):
2020-04-02 20:10:20 -05:00
"""
2018-02-08 16:04:25 -08:00
cmd.run with success_retcodes
2020-04-02 20:10:20 -05:00
"""
ret = self.run_function(
2018-02-08 16:04:25 -08:00
"cmd.retcode", ["exit 42"], success_retcodes=[42], python_shell=True
)
self.assertEqual(ret, 0)
@pytest.mark.slow_test
def test_run_all_with_success_stderr(self):
2021-03-18 18:55:55 -07:00
"""
cmd.run with success_retcodes
2021-03-18 18:55:55 -07:00
"""
random_file = "{}{}{}".format(
RUNTIME_VARS.TMP_ROOT_DIR, os.path.sep, random.random()
)
if salt.utils.platform.is_windows():
2021-03-18 18:55:55 -07:00
func = "type"
expected_stderr = "cannot find the file specified"
else:
2021-03-18 18:55:55 -07:00
func = "cat"
expected_stderr = "No such file or directory"
2021-03-18 18:55:55 -07:00
ret = self.run_function(
"cmd.run_all",
[f"{func} {random_file}"],
2021-03-18 18:55:55 -07:00
success_stderr=[expected_stderr],
python_shell=True,
)
self.assertTrue("retcode" in ret)
self.assertEqual(ret.get("retcode"), 0)
@pytest.mark.slow_test
2016-08-30 17:13:12 -06:00
def test_blacklist_glob(self):
2020-04-02 20:10:20 -05:00
"""
2016-08-30 17:13:12 -06:00
cmd_blacklist_glob
2020-04-02 20:10:20 -05:00
"""
2016-08-30 17:13:12 -06:00
self.assertEqual(
self.run_function("cmd.run", ["bad_command --foo"]).rstrip(),
'ERROR: The shell command "bad_command --foo" is not permitted',
)
2016-08-30 17:13:12 -06:00
@pytest.mark.slow_test
@pytest.mark.skip_on_windows
2015-03-01 19:54:22 -07:00
def test_script(self):
2020-04-02 20:10:20 -05:00
"""
2015-03-01 19:54:22 -07:00
cmd.script
2020-04-02 20:10:20 -05:00
"""
2015-03-01 19:54:22 -07:00
args = "saltines crackers biscuits=yes"
script = "salt://script.py"
2022-02-08 01:16:07 +00:00
ret = self.run_function("cmd.script", [script, args], saltenv="base")
2015-03-01 19:54:22 -07:00
self.assertEqual(ret["stdout"], args)
@pytest.mark.slow_test
@pytest.mark.skip_on_windows
def test_script_query_string(self):
"""
cmd.script
"""
args = "saltines crackers biscuits=yes"
script = "salt://script.py?saltenv=base"
2022-02-08 01:16:07 +00:00
ret = self.run_function("cmd.script", [script, args], saltenv="base")
self.assertEqual(ret["stdout"], args)
@pytest.mark.slow_test
@pytest.mark.skip_on_windows
2015-03-01 19:54:22 -07:00
def test_script_retcode(self):
2020-04-02 20:10:20 -05:00
"""
2015-03-01 19:54:22 -07:00
cmd.script_retcode
2020-04-02 20:10:20 -05:00
"""
2015-03-01 19:54:22 -07:00
script = "salt://script.py"
2022-02-08 01:16:07 +00:00
ret = self.run_function("cmd.script_retcode", [script], saltenv="base")
2015-03-01 19:54:22 -07:00
self.assertEqual(ret, 0)
@pytest.mark.slow_test
@pytest.mark.skip_on_windows
def test_script_cwd(self):
2020-04-02 20:10:20 -05:00
"""
cmd.script with cwd
2020-04-02 20:10:20 -05:00
"""
2018-12-07 17:52:49 +00:00
tmp_cwd = tempfile.mkdtemp(dir=RUNTIME_VARS.TMP)
args = "saltines crackers biscuits=yes"
script = "salt://script.py"
2022-02-08 01:16:07 +00:00
ret = self.run_function(
"cmd.script", [script, args], cwd=tmp_cwd, saltenv="base"
)
self.assertEqual(ret["stdout"], args)
@pytest.mark.slow_test
@pytest.mark.skip_on_windows
def test_script_cwd_with_space(self):
2020-04-02 20:10:20 -05:00
"""
cmd.script with cwd
2020-04-02 20:10:20 -05:00
"""
tmp_cwd = "{}{}test 2".format(
2018-12-07 17:52:49 +00:00
tempfile.mkdtemp(dir=RUNTIME_VARS.TMP), os.path.sep
)
os.mkdir(tmp_cwd)
args = "saltines crackers biscuits=yes"
script = "salt://script.py"
2022-02-08 01:16:07 +00:00
ret = self.run_function(
"cmd.script", [script, args], cwd=tmp_cwd, saltenv="base"
)
self.assertEqual(ret["stdout"], args)
@pytest.mark.destructive_test
2015-03-01 19:54:22 -07:00
def test_tty(self):
2020-04-02 20:10:20 -05:00
"""
2015-03-01 19:54:22 -07:00
cmd.tty
2020-04-02 20:10:20 -05:00
"""
2015-03-01 19:54:22 -07:00
for tty in ("tty0", "pts3"):
if os.path.exists(os.path.join("/dev", tty)):
ret = self.run_function("cmd.tty", [tty, "apply salt liberally"])
self.assertTrue("Success" in ret)
2021-08-31 13:08:29 -06:00
@pytest.mark.skip_on_windows
@pytest.mark.skip_if_binaries_missing("which")
2012-03-27 17:05:38 -06:00
def test_which(self):
2020-04-02 20:10:20 -05:00
"""
2012-03-27 17:05:38 -06:00
cmd.which
2020-04-02 20:10:20 -05:00
"""
2020-05-05 18:56:30 +01:00
cmd_which = self.run_function("cmd.which", ["cat"])
self.assertIsInstance(cmd_which, str)
cmd_run = self.run_function("cmd.run", ["which cat"])
self.assertIsInstance(cmd_run, str)
self.assertEqual(cmd_which.rstrip(), cmd_run.rstrip())
2012-03-27 17:05:38 -06:00
2021-08-31 13:08:29 -06:00
@pytest.mark.skip_on_windows
@pytest.mark.skip_if_binaries_missing("which")
2015-03-01 19:54:22 -07:00
def test_which_bin(self):
2020-04-02 20:10:20 -05:00
"""
2015-03-01 19:54:22 -07:00
cmd.which_bin
2020-04-02 20:10:20 -05:00
"""
cmds = ["pip3", "pip2", "pip", "pip-python"]
2015-03-01 19:54:22 -07:00
ret = self.run_function("cmd.which_bin", [cmds])
self.assertTrue(os.path.split(ret)[1] in cmds)
@pytest.mark.slow_test
2012-03-27 17:05:38 -06:00
def test_has_exec(self):
2020-04-02 20:10:20 -05:00
"""
2012-03-27 17:05:38 -06:00
cmd.has_exec
2020-04-02 20:10:20 -05:00
"""
self.assertTrue(
self.run_function("cmd.has_exec", [AVAILABLE_PYTHON_EXECUTABLE])
2020-04-02 20:10:20 -05:00
)
2013-03-21 16:22:29 -06:00
self.assertFalse(
self.run_function("cmd.has_exec", ["alllfsdfnwieulrrh9123857ygf"])
)
2012-03-27 17:05:38 -06:00
@pytest.mark.slow_test
2012-03-27 17:05:38 -06:00
def test_exec_code(self):
2020-04-02 20:10:20 -05:00
"""
2012-03-27 17:05:38 -06:00
cmd.exec_code
2020-04-02 20:10:20 -05:00
"""
2020-05-13 23:08:26 +00:00
code = dedent(
"""
import sys
sys.stdout.write('cheese')
"""
2020-05-13 23:08:26 +00:00
)
2013-03-21 16:22:29 -06:00
self.assertEqual(
self.run_function(
"cmd.exec_code", [AVAILABLE_PYTHON_EXECUTABLE, code]
).rstrip(),
2013-03-21 16:22:29 -06:00
"cheese",
)
@pytest.mark.slow_test
def test_exec_code_with_single_arg(self):
2020-04-02 20:10:20 -05:00
"""
cmd.exec_code
2020-04-02 20:10:20 -05:00
"""
2020-05-13 23:08:26 +00:00
code = dedent(
"""
import sys
sys.stdout.write(sys.argv[1])
"""
2020-05-13 23:08:26 +00:00
)
arg = "cheese"
self.assertEqual(
self.run_function(
"cmd.exec_code", [AVAILABLE_PYTHON_EXECUTABLE, code], args=arg
).rstrip(),
arg,
)
@pytest.mark.slow_test
def test_exec_code_with_multiple_args(self):
2020-04-02 20:10:20 -05:00
"""
cmd.exec_code
2020-04-02 20:10:20 -05:00
"""
2020-05-13 23:08:26 +00:00
code = dedent(
"""
import sys
sys.stdout.write(sys.argv[1])
"""
2020-05-13 23:08:26 +00:00
)
arg = "cheese"
self.assertEqual(
self.run_function(
"cmd.exec_code", [AVAILABLE_PYTHON_EXECUTABLE, code], args=[arg, "test"]
).rstrip(),
arg,
)
@pytest.mark.slow_test
def test_quotes(self):
2020-04-02 20:10:20 -05:00
"""
cmd.run with quoted command
2020-04-02 20:10:20 -05:00
"""
cmd = """echo 'SELECT * FROM foo WHERE bar="baz"' """
expected_result = 'SELECT * FROM foo WHERE bar="baz"'
if salt.utils.platform.is_windows():
expected_result = "'SELECT * FROM foo WHERE bar=\"baz\"'"
result = self.run_function("cmd.run_stdout", [cmd]).strip()
self.assertEqual(result, expected_result)
@pytest.mark.skip_if_not_root
2021-02-12 17:43:28 -07:00
@pytest.mark.skip_on_windows(reason="Skip on Windows, requires password")
def test_quotes_runas(self):
2020-04-02 20:10:20 -05:00
"""
cmd.run with quoted command
2020-04-02 20:10:20 -05:00
"""
cmd = """echo 'SELECT * FROM foo WHERE bar="baz"' """
expected_result = 'SELECT * FROM foo WHERE bar="baz"'
2020-05-05 18:56:30 +01:00
result = self.run_function(
"cmd.run_all", [cmd], runas=RUNTIME_VARS.RUNNING_TESTS_USER
)
errmsg = f"The command returned: {result}"
2020-05-05 18:56:30 +01:00
self.assertEqual(result["retcode"], 0, errmsg)
self.assertEqual(result["stdout"], expected_result, errmsg)
@pytest.mark.destructive_test
@pytest.mark.skip_if_not_root
2021-02-12 17:43:28 -07:00
@pytest.mark.skip_on_windows(reason="Skip on Windows, uses unix commands")
@pytest.mark.slow_test
def test_avoid_injecting_shell_code_as_root(self):
2020-04-02 20:10:20 -05:00
"""
cmd.run should execute the whole command as the "runas" user, not
running substitutions as root.
2020-04-02 20:10:20 -05:00
"""
cmd = "echo $(id -u)"
root_id = self.run_function("cmd.run_stdout", [cmd])
2019-10-11 13:17:24 +01:00
runas_root_id = self.run_function(
"cmd.run_stdout", [cmd], runas=RUNTIME_VARS.RUNNING_TESTS_USER
)
with self._ensure_user_exists(self.runas_usr):
user_id = self.run_function("cmd.run_stdout", [cmd], runas=self.runas_usr)
self.assertNotEqual(user_id, root_id)
self.assertNotEqual(user_id, runas_root_id)
self.assertEqual(root_id, runas_root_id)
@pytest.mark.destructive_test
@pytest.mark.skip_if_not_root
2021-02-12 17:43:28 -07:00
@pytest.mark.skip_on_windows(reason="Skip on Windows, uses unix commands")
@pytest.mark.slow_test
def test_cwd_runas(self):
2020-04-02 20:10:20 -05:00
"""
cmd.run should be able to change working directory correctly, whether
or not runas is in use.
2020-04-02 20:10:20 -05:00
"""
cmd = "pwd"
2018-12-07 17:52:49 +00:00
tmp_cwd = tempfile.mkdtemp(dir=RUNTIME_VARS.TMP)
os.chmod(tmp_cwd, 0o711)
cwd_normal = self.run_function("cmd.run_stdout", [cmd], cwd=tmp_cwd).rstrip(
"\n"
)
self.assertEqual(tmp_cwd, cwd_normal)
with self._ensure_user_exists(self.runas_usr):
cwd_runas = self.run_function(
"cmd.run_stdout", [cmd], cwd=tmp_cwd, runas=self.runas_usr
).rstrip("\n")
self.assertEqual(tmp_cwd, cwd_runas)
@pytest.mark.destructive_test
@pytest.mark.skip_if_not_root
2021-02-12 17:43:28 -07:00
@pytest.mark.skip_unless_on_darwin(reason="Applicable to MacOS only")
@pytest.mark.slow_test
def test_runas_env(self):
2020-04-02 20:10:20 -05:00
"""
cmd.run should be able to change working directory correctly, whether
or not runas is in use.
2020-04-02 20:10:20 -05:00
"""
with self._ensure_user_exists(self.runas_usr):
user_path = self.run_function(
"cmd.run_stdout", ['printf %s "$PATH"'], runas=self.runas_usr
)
# XXX: Not sure of a better way. Environment starts out with
# /bin:/usr/bin and should be populated by path helper and the bash
# profile.
self.assertNotEqual("/bin:/usr/bin", user_path)
@pytest.mark.destructive_test
@pytest.mark.skip_if_not_root
2021-02-12 17:43:28 -07:00
@pytest.mark.skip_unless_on_darwin(reason="Applicable to MacOS only")
@pytest.mark.slow_test
def test_runas_complex_command_bad_cwd(self):
2020-04-02 20:10:20 -05:00
"""
cmd.run should not accidentally run parts of a complex command when
given a cwd which cannot be used by the user the command is run as.
Due to the need to use `su -l` to login to another user on MacOS, we
cannot cd into directories that the target user themselves does not
have execute permission for. To an extent, this test is testing that
buggy behaviour, but its purpose is to ensure that the greater bug of
running commands after failing to cd does not occur.
2020-04-02 20:10:20 -05:00
"""
2018-12-07 17:52:49 +00:00
tmp_cwd = tempfile.mkdtemp(dir=RUNTIME_VARS.TMP)
os.chmod(tmp_cwd, 0o700)
with self._ensure_user_exists(self.runas_usr):
cmd_result = self.run_function(
"cmd.run_all",
['pwd; pwd; : $(echo "You have failed the test" >&2)'],
cwd=tmp_cwd,
runas=self.runas_usr,
)
2020-04-02 20:10:20 -05:00
self.assertEqual("", cmd_result["stdout"])
self.assertNotIn("You have failed the test", cmd_result["stderr"])
self.assertNotEqual(0, cmd_result["retcode"])
2020-04-02 20:10:20 -05:00
@SKIP_INITIAL_PHOTONOS_FAILURES
@pytest.mark.skip_on_windows
@pytest.mark.skip_if_not_root
@pytest.mark.destructive_test
@pytest.mark.slow_test
2018-03-30 13:12:02 -05:00
def test_runas(self):
2020-04-02 20:10:20 -05:00
"""
2018-03-30 13:12:02 -05:00
Ensure that the env is the runas user's
2020-04-02 20:10:20 -05:00
"""
with self._ensure_user_exists(self.runas_usr):
out = self.run_function(
2025-01-01 15:03:04 -07:00
"cmd.run", ["env"], runas=self.runas_usr, cwd="/tmp"
).splitlines()
self.assertIn(f"USER={self.runas_usr}", out)
2018-03-30 13:12:02 -05:00
@pytest.mark.skip_if_binaries_missing("sleep", reason="sleep cmd not installed")
def test_timeout(self):
2020-04-02 20:10:20 -05:00
"""
cmd.run trigger timeout
2020-04-02 20:10:20 -05:00
"""
2017-02-25 20:11:06 -06:00
out = self.run_function(
"cmd.run", ["sleep 2 && echo hello"], f_timeout=1, python_shell=True
)
self.assertTrue("Timed out" in out)
@pytest.mark.skip_if_binaries_missing("sleep", reason="sleep cmd not installed")
def test_timeout_success(self):
2020-04-02 20:10:20 -05:00
"""
cmd.run sufficient timeout to succeed
2020-04-02 20:10:20 -05:00
"""
2017-02-25 20:11:06 -06:00
out = self.run_function(
"cmd.run", ["sleep 1 && echo hello"], f_timeout=2, python_shell=True
)
self.assertEqual(out, "hello")
@pytest.mark.slow_test
def test_hide_output(self):
2020-04-02 20:10:20 -05:00
"""
Test the hide_output argument
2020-04-02 20:10:20 -05:00
"""
ls_command = (
["ls", "/"] if not salt.utils.platform.is_windows() else ["dir", "c:\\"]
2020-04-02 20:10:20 -05:00
)
error_command = ["thiscommanddoesnotexist"]
# cmd.run
out = self.run_function("cmd.run", ls_command, hide_output=True)
self.assertEqual(out, "")
# cmd.shell
out = self.run_function("cmd.shell", ls_command, hide_output=True)
self.assertEqual(out, "")
# cmd.run_stdout
out = self.run_function("cmd.run_stdout", ls_command, hide_output=True)
self.assertEqual(out, "")
# cmd.run_stderr
out = self.run_function("cmd.shell", error_command, hide_output=True)
self.assertEqual(out, "")
# cmd.run_all (command should have produced stdout)
out = self.run_function("cmd.run_all", ls_command, hide_output=True)
self.assertEqual(out["stdout"], "")
self.assertEqual(out["stderr"], "")
# cmd.run_all (command should have produced stderr)
out = self.run_function("cmd.run_all", error_command, hide_output=True)
self.assertEqual(out["stdout"], "")
self.assertEqual(out["stderr"], "")
@pytest.mark.slow_test
2018-05-29 21:51:02 +00:00
def test_cmd_run_whoami(self):
2020-04-02 20:10:20 -05:00
"""
2018-05-29 21:51:02 +00:00
test return of whoami
2020-04-02 20:10:20 -05:00
"""
2020-05-18 17:03:53 +01:00
if not salt.utils.platform.is_windows():
user = RUNTIME_VARS.RUNTIME_CONFIGS["master"]["user"]
2018-05-29 21:51:02 +00:00
else:
2020-05-18 17:03:53 +01:00
user = salt.utils.user.get_specific_user()
if user.startswith("sudo_"):
user = user.replace("sudo_", "")
2020-05-18 17:03:53 +01:00
cmd = self.run_function("cmd.run", ["whoami"])
try:
self.assertEqual(user.lower(), cmd.lower())
except AssertionError as exc:
if not salt.utils.platform.is_windows():
raise exc from None
if "\\" in user:
user = user.split("\\")[-1]
self.assertEqual(user.lower(), cmd.lower())
2021-02-12 17:43:28 -07:00
@pytest.mark.skip_unless_on_windows(reason="Minion is not Windows")
@pytest.mark.slow_test
def test_windows_env_handling(self):
2020-04-02 20:10:20 -05:00
"""
Ensure that nt.environ is used properly with cmd.run*
2020-04-02 20:10:20 -05:00
"""
out = self.run_function(
"cmd.run", ["set"], env={"abc": "123", "ABC": "456"}
).splitlines()
self.assertIn("abc=123", out)
self.assertIn("ABC=456", out)