test_cmdmod.py 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391
  1. # -*- coding: utf-8 -*-
  2. # Import python libs
  3. from __future__ import absolute_import, print_function, unicode_literals
  4. import os
  5. import sys
  6. import tempfile
  7. import textwrap
  8. # Import Salt Testing libs
  9. from tests.support.case import ModuleCase
  10. from tests.support.helpers import (
  11. destructiveTest,
  12. skip_if_binaries_missing,
  13. skip_if_not_root,
  14. this_user,
  15. )
  16. from tests.support.paths import TMP
  17. from tests.support.unit import skipIf
  18. # Import salt libs
  19. import salt.utils.path
  20. import salt.utils.platform
  21. # Import 3rd-party libs
  22. from salt.ext import six
  23. AVAILABLE_PYTHON_EXECUTABLE = salt.utils.path.which_bin([
  24. 'python',
  25. 'python2',
  26. 'python2.6',
  27. 'python2.7'
  28. ])
  29. class CMDModuleTest(ModuleCase):
  30. '''
  31. Validate the cmd module
  32. '''
  33. def setUp(self):
  34. self.runas_usr = 'nobody'
  35. if salt.utils.platform.is_darwin():
  36. self.runas_usr = 'macsalttest'
  37. def tearDown(self):
  38. if self._testMethodName == 'test_runas':
  39. if salt.utils.platform.is_darwin():
  40. if self.runas_usr in self.run_function('user.info', [self.runas_usr]).values():
  41. self.run_function('user.delete', [self.runas_usr], remove=True)
  42. def test_run(self):
  43. '''
  44. cmd.run
  45. '''
  46. shell = os.environ.get('SHELL')
  47. if shell is None:
  48. # Failed to get the SHELL var, don't run
  49. self.skipTest('Unable to get the SHELL environment variable')
  50. self.assertTrue(self.run_function('cmd.run', ['echo $SHELL']))
  51. self.assertEqual(
  52. self.run_function('cmd.run',
  53. ['echo $SHELL',
  54. 'shell={0}'.format(shell)],
  55. python_shell=True).rstrip(), shell)
  56. self.assertEqual(self.run_function('cmd.run',
  57. ['ls / | grep etc'],
  58. python_shell=True), 'etc')
  59. self.assertEqual(self.run_function('cmd.run',
  60. ['echo {{grains.id}} | awk "{print $1}"'],
  61. template='jinja',
  62. python_shell=True), 'minion')
  63. self.assertEqual(self.run_function('cmd.run',
  64. ['grep f'],
  65. stdin='one\ntwo\nthree\nfour\nfive\n'), 'four\nfive')
  66. self.assertEqual(self.run_function('cmd.run',
  67. ['echo "a=b" | sed -e s/=/:/g'],
  68. python_shell=True), 'a:b')
  69. def test_stdout(self):
  70. '''
  71. cmd.run_stdout
  72. '''
  73. self.assertEqual(self.run_function('cmd.run_stdout',
  74. ['echo "cheese"']).rstrip(),
  75. 'cheese' if not salt.utils.platform.is_windows() else '"cheese"')
  76. def test_stderr(self):
  77. '''
  78. cmd.run_stderr
  79. '''
  80. if sys.platform.startswith(('freebsd', 'openbsd')):
  81. shell = '/bin/sh'
  82. else:
  83. shell = '/bin/bash'
  84. self.assertEqual(self.run_function('cmd.run_stderr',
  85. ['echo "cheese" 1>&2',
  86. 'shell={0}'.format(shell)], python_shell=True
  87. ).rstrip(),
  88. 'cheese' if not salt.utils.platform.is_windows() else '"cheese"')
  89. def test_run_all(self):
  90. '''
  91. cmd.run_all
  92. '''
  93. if sys.platform.startswith(('freebsd', 'openbsd')):
  94. shell = '/bin/sh'
  95. else:
  96. shell = '/bin/bash'
  97. ret = self.run_function('cmd.run_all', ['echo "cheese" 1>&2',
  98. 'shell={0}'.format(shell)], python_shell=True)
  99. self.assertTrue('pid' in ret)
  100. self.assertTrue('retcode' in ret)
  101. self.assertTrue('stdout' in ret)
  102. self.assertTrue('stderr' in ret)
  103. self.assertTrue(isinstance(ret.get('pid'), int))
  104. self.assertTrue(isinstance(ret.get('retcode'), int))
  105. self.assertTrue(isinstance(ret.get('stdout'), six.string_types))
  106. self.assertTrue(isinstance(ret.get('stderr'), six.string_types))
  107. self.assertEqual(ret.get('stderr').rstrip(), 'cheese' if not salt.utils.platform.is_windows() else '"cheese"')
  108. def test_retcode(self):
  109. '''
  110. cmd.retcode
  111. '''
  112. self.assertEqual(self.run_function('cmd.retcode', ['exit 0'], python_shell=True), 0)
  113. self.assertEqual(self.run_function('cmd.retcode', ['exit 1'], python_shell=True), 1)
  114. def test_blacklist_glob(self):
  115. '''
  116. cmd_blacklist_glob
  117. '''
  118. self.assertEqual(self.run_function('cmd.run',
  119. ['bad_command --foo']).rstrip(),
  120. 'ERROR: The shell command "bad_command --foo" is not permitted')
  121. def test_script(self):
  122. '''
  123. cmd.script
  124. '''
  125. args = 'saltines crackers biscuits=yes'
  126. script = 'salt://script.py'
  127. ret = self.run_function('cmd.script', [script, args])
  128. self.assertEqual(ret['stdout'], args)
  129. def test_script_retcode(self):
  130. '''
  131. cmd.script_retcode
  132. '''
  133. script = 'salt://script.py'
  134. ret = self.run_function('cmd.script_retcode', [script])
  135. self.assertEqual(ret, 0)
  136. def test_script_cwd(self):
  137. '''
  138. cmd.script with cwd
  139. '''
  140. tmp_cwd = tempfile.mkdtemp(dir=TMP)
  141. args = 'saltines crackers biscuits=yes'
  142. script = 'salt://script.py'
  143. ret = self.run_function('cmd.script', [script, args], cwd=tmp_cwd)
  144. self.assertEqual(ret['stdout'], args)
  145. def test_script_cwd_with_space(self):
  146. '''
  147. cmd.script with cwd
  148. '''
  149. tmp_cwd = "{0}{1}test 2".format(tempfile.mkdtemp(dir=TMP), os.path.sep)
  150. os.mkdir(tmp_cwd)
  151. args = 'saltines crackers biscuits=yes'
  152. script = 'salt://script.py'
  153. ret = self.run_function('cmd.script', [script, args], cwd=tmp_cwd)
  154. self.assertEqual(ret['stdout'], args)
  155. @destructiveTest
  156. def test_tty(self):
  157. '''
  158. cmd.tty
  159. '''
  160. for tty in ('tty0', 'pts3'):
  161. if os.path.exists(os.path.join('/dev', tty)):
  162. ret = self.run_function('cmd.tty', [tty, 'apply salt liberally'])
  163. self.assertTrue('Success' in ret)
  164. @skip_if_binaries_missing(['which'])
  165. def test_which(self):
  166. '''
  167. cmd.which
  168. '''
  169. self.assertEqual(self.run_function('cmd.which', ['cat']).rstrip(),
  170. self.run_function('cmd.run', ['which cat']).rstrip())
  171. @skip_if_binaries_missing(['which'])
  172. def test_which_bin(self):
  173. '''
  174. cmd.which_bin
  175. '''
  176. cmds = ['pip3', 'pip2', 'pip', 'pip-python']
  177. ret = self.run_function('cmd.which_bin', [cmds])
  178. self.assertTrue(os.path.split(ret)[1] in cmds)
  179. def test_has_exec(self):
  180. '''
  181. cmd.has_exec
  182. '''
  183. self.assertTrue(self.run_function('cmd.has_exec',
  184. [AVAILABLE_PYTHON_EXECUTABLE]))
  185. self.assertFalse(self.run_function('cmd.has_exec',
  186. ['alllfsdfnwieulrrh9123857ygf']))
  187. def test_exec_code(self):
  188. '''
  189. cmd.exec_code
  190. '''
  191. code = textwrap.dedent('''\
  192. import sys
  193. sys.stdout.write('cheese')''')
  194. self.assertEqual(self.run_function('cmd.exec_code',
  195. [AVAILABLE_PYTHON_EXECUTABLE,
  196. code]).rstrip(),
  197. 'cheese')
  198. def test_exec_code_with_single_arg(self):
  199. '''
  200. cmd.exec_code
  201. '''
  202. code = textwrap.dedent('''\
  203. import sys
  204. sys.stdout.write(sys.argv[1])''')
  205. arg = 'cheese'
  206. self.assertEqual(self.run_function('cmd.exec_code',
  207. [AVAILABLE_PYTHON_EXECUTABLE,
  208. code],
  209. args=arg).rstrip(),
  210. arg)
  211. def test_exec_code_with_multiple_args(self):
  212. '''
  213. cmd.exec_code
  214. '''
  215. code = textwrap.dedent('''\
  216. import sys
  217. sys.stdout.write(sys.argv[1])''')
  218. arg = 'cheese'
  219. self.assertEqual(self.run_function('cmd.exec_code',
  220. [AVAILABLE_PYTHON_EXECUTABLE,
  221. code],
  222. args=[arg, 'test']).rstrip(),
  223. arg)
  224. def test_quotes(self):
  225. '''
  226. cmd.run with quoted command
  227. '''
  228. cmd = '''echo 'SELECT * FROM foo WHERE bar="baz"' '''
  229. expected_result = 'SELECT * FROM foo WHERE bar="baz"'
  230. if salt.utils.platform.is_windows():
  231. expected_result = '\'SELECT * FROM foo WHERE bar="baz"\''
  232. result = self.run_function('cmd.run_stdout', [cmd]).strip()
  233. self.assertEqual(result, expected_result)
  234. @skip_if_not_root
  235. @skipIf(salt.utils.platform.is_windows, 'skip windows, requires password')
  236. def test_quotes_runas(self):
  237. '''
  238. cmd.run with quoted command
  239. '''
  240. cmd = '''echo 'SELECT * FROM foo WHERE bar="baz"' '''
  241. if salt.utils.platform.is_darwin():
  242. cmd = '''echo 'SELECT * FROM foo WHERE bar=\\"baz\\"' '''
  243. expected_result = 'SELECT * FROM foo WHERE bar="baz"'
  244. runas = this_user()
  245. result = self.run_function('cmd.run_stdout', [cmd],
  246. runas=runas).strip()
  247. self.assertEqual(result, expected_result)
  248. @skipIf(salt.utils.platform.is_windows(), 'minion is windows')
  249. @skip_if_not_root
  250. @destructiveTest
  251. def test_runas(self):
  252. '''
  253. Ensure that the env is the runas user's
  254. '''
  255. if salt.utils.platform.is_darwin():
  256. if self.runas_usr not in self.run_function('user.info', [self.runas_usr]).values():
  257. self.run_function('user.add', [self.runas_usr])
  258. out = self.run_function('cmd.run', ['env'], runas=self.runas_usr).splitlines()
  259. self.assertIn('USER={0}'.format(self.runas_usr), out)
  260. @skipIf(not salt.utils.path.which_bin('sleep'), 'sleep cmd not installed')
  261. def test_timeout(self):
  262. '''
  263. cmd.run trigger timeout
  264. '''
  265. out = self.run_function('cmd.run',
  266. ['sleep 2 && echo hello'],
  267. f_timeout=1,
  268. python_shell=True)
  269. self.assertTrue('Timed out' in out)
  270. @skipIf(not salt.utils.path.which_bin('sleep'), 'sleep cmd not installed')
  271. def test_timeout_success(self):
  272. '''
  273. cmd.run sufficient timeout to succeed
  274. '''
  275. out = self.run_function('cmd.run',
  276. ['sleep 1 && echo hello'],
  277. f_timeout=2,
  278. python_shell=True)
  279. self.assertEqual(out, 'hello')
  280. def test_hide_output(self):
  281. '''
  282. Test the hide_output argument
  283. '''
  284. ls_command = ['ls', '/'] \
  285. if not salt.utils.platform.is_windows() \
  286. else ['dir', 'c:\\']
  287. error_command = ['thiscommanddoesnotexist']
  288. # cmd.run
  289. out = self.run_function(
  290. 'cmd.run',
  291. ls_command,
  292. hide_output=True)
  293. self.assertEqual(out, '')
  294. # cmd.shell
  295. out = self.run_function(
  296. 'cmd.shell',
  297. ls_command,
  298. hide_output=True)
  299. self.assertEqual(out, '')
  300. # cmd.run_stdout
  301. out = self.run_function(
  302. 'cmd.run_stdout',
  303. ls_command,
  304. hide_output=True)
  305. self.assertEqual(out, '')
  306. # cmd.run_stderr
  307. out = self.run_function(
  308. 'cmd.shell',
  309. error_command,
  310. hide_output=True)
  311. self.assertEqual(out, '')
  312. # cmd.run_all (command should have produced stdout)
  313. out = self.run_function(
  314. 'cmd.run_all',
  315. ls_command,
  316. hide_output=True)
  317. self.assertEqual(out['stdout'], '')
  318. self.assertEqual(out['stderr'], '')
  319. # cmd.run_all (command should have produced stderr)
  320. out = self.run_function(
  321. 'cmd.run_all',
  322. error_command,
  323. hide_output=True)
  324. self.assertEqual(out['stdout'], '')
  325. self.assertEqual(out['stderr'], '')
  326. def test_cmd_run_whoami(self):
  327. '''
  328. test return of whoami
  329. '''
  330. cmd = self.run_function('cmd.run', ['whoami'])
  331. if salt.utils.platform.is_windows():
  332. self.assertIn('administrator', cmd)
  333. else:
  334. self.assertEqual('root', cmd)
  335. @skipIf(not salt.utils.platform.is_windows(), 'minion is not windows')
  336. def test_windows_env_handling(self):
  337. '''
  338. Ensure that nt.environ is used properly with cmd.run*
  339. '''
  340. out = self.run_function('cmd.run', ['set'], env={"abc": "123", "ABC": "456"}).splitlines()
  341. self.assertIn('abc=123', out)
  342. self.assertIn('ABC=456', out)