PageRenderTime 92ms CodeModel.GetById 20ms RepoModel.GetById 2ms app.codeStats 0ms

/tests/integration/states/pip.py

https://gitlab.com/ricardo.hernandez/salt
Python | 485 lines | 406 code | 35 blank | 44 comment | 46 complexity | c510778c781944f1544961dda0c93d53 MD5 | raw file
  1. # -*- coding: utf-8 -*-
  2. '''
  3. :codeauthor: :email:`Pedro Algarvio (pedro@algarvio.me)`
  4. tests.integration.states.pip
  5. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  6. '''
  7. # Import python libs
  8. from __future__ import absolute_import
  9. import os
  10. import pwd
  11. import glob
  12. import shutil
  13. # Import Salt Testing libs
  14. from salttesting import skipIf
  15. from salttesting.helpers import (
  16. destructiveTest,
  17. ensure_in_syspath,
  18. requires_system_grains,
  19. with_system_user
  20. )
  21. ensure_in_syspath('../../')
  22. # Import salt libs
  23. import integration
  24. import salt.utils
  25. from salt.modules.virtualenv_mod import KNOWN_BINARY_NAMES
  26. from salt.exceptions import CommandExecutionError
  27. # Import 3rd-party libs
  28. import salt.ext.six as six
  29. @skipIf(salt.utils.which_bin(KNOWN_BINARY_NAMES) is None, 'virtualenv not installed')
  30. class PipStateTest(integration.ModuleCase, integration.SaltReturnAssertsMixIn):
  31. def test_pip_installed_removed(self):
  32. '''
  33. Tests installed and removed states
  34. '''
  35. ret = self.run_state('pip.installed', name='docker-py')
  36. self.assertSaltTrueReturn(ret)
  37. ret = self.run_state('pip.removed', name='docker-py')
  38. self.assertSaltTrueReturn(ret)
  39. def test_pip_installed_errors(self):
  40. venv_dir = os.path.join(
  41. integration.SYS_TMP_DIR, 'pip-installed-errors'
  42. )
  43. try:
  44. # Since we don't have the virtualenv created, pip.installed will
  45. # thrown and error.
  46. # Example error strings:
  47. # * "Error installing 'supervisor': /tmp/pip-installed-errors: not found"
  48. # * "Error installing 'supervisor': /bin/sh: 1: /tmp/pip-installed-errors: not found"
  49. # * "Error installing 'supervisor': /bin/bash: /tmp/pip-installed-errors: No such file or directory"
  50. os.environ['SHELL'] = '/bin/sh'
  51. ret = self.run_function('state.sls', mods='pip-installed-errors')
  52. self.assertSaltFalseReturn(ret)
  53. self.assertSaltCommentRegexpMatches(
  54. ret,
  55. 'Error installing \'supervisor\':'
  56. )
  57. # We now create the missing virtualenv
  58. ret = self.run_function('virtualenv.create', [venv_dir])
  59. self.assertEqual(ret['retcode'], 0)
  60. # The state should not have any issues running now
  61. ret = self.run_function('state.sls', mods='pip-installed-errors')
  62. self.assertSaltTrueReturn(ret)
  63. finally:
  64. if os.path.isdir(venv_dir):
  65. shutil.rmtree(venv_dir)
  66. @requires_system_grains
  67. def test_pip_installed_weird_install(self, grains=None):
  68. # First, check to see if this is running on CentOS 5. If so, skip this test.
  69. if grains['os'] in ('CentOS',) and grains['osrelease_info'][0] in (5,):
  70. self.skipTest('This test does not run reliably on CentOS 5')
  71. ographite = '/opt/graphite'
  72. if os.path.isdir(ographite):
  73. self.skipTest(
  74. 'You already have \'{0}\'. This test would overwrite this '
  75. 'directory'.format(ographite)
  76. )
  77. try:
  78. os.makedirs(ographite)
  79. except OSError as err:
  80. if err.errno == 13:
  81. # Permission denied
  82. self.skipTest(
  83. 'You don\'t have the required permissions to run this test'
  84. )
  85. finally:
  86. if os.path.isdir(ographite):
  87. shutil.rmtree(ographite)
  88. venv_dir = os.path.join(
  89. integration.SYS_TMP_DIR, 'pip-installed-weird-install'
  90. )
  91. try:
  92. # Since we don't have the virtualenv created, pip.installed will
  93. # thrown and error.
  94. ret = self.run_function(
  95. 'state.sls', mods='pip-installed-weird-install'
  96. )
  97. self.assertSaltTrueReturn(ret)
  98. # We cannot use assertInSaltComment here because we need to skip
  99. # some of the state return parts
  100. for key in six.iterkeys(ret):
  101. self.assertTrue(ret[key]['result'])
  102. if ret[key]['comment'] == 'Created new virtualenv':
  103. continue
  104. self.assertEqual(
  105. ret[key]['comment'],
  106. 'There was no error installing package \'carbon\' '
  107. 'although it does not show when calling \'pip.freeze\'.'
  108. )
  109. finally:
  110. if os.path.isdir(venv_dir):
  111. shutil.rmtree(venv_dir)
  112. if os.path.isdir('/opt/graphite'):
  113. shutil.rmtree('/opt/graphite')
  114. def test_issue_2028_pip_installed_state(self):
  115. ret = self.run_function('state.sls', mods='issue-2028-pip-installed')
  116. venv_dir = os.path.join(
  117. integration.SYS_TMP_DIR, 'issue-2028-pip-installed'
  118. )
  119. try:
  120. self.assertSaltTrueReturn(ret)
  121. self.assertTrue(
  122. os.path.isfile(os.path.join(venv_dir, 'bin', 'supervisord'))
  123. )
  124. finally:
  125. if os.path.isdir(venv_dir):
  126. shutil.rmtree(venv_dir)
  127. def test_issue_2087_missing_pip(self):
  128. venv_dir = os.path.join(
  129. integration.SYS_TMP_DIR, 'issue-2087-missing-pip'
  130. )
  131. try:
  132. # Let's create the testing virtualenv
  133. ret = self.run_function('virtualenv.create', [venv_dir])
  134. self.assertEqual(ret['retcode'], 0)
  135. # Let's remove the pip binary
  136. pip_bin = os.path.join(venv_dir, 'bin', 'pip')
  137. if not os.path.isfile(pip_bin):
  138. self.skipTest(
  139. 'Failed to find the pip binary to the test virtualenv'
  140. )
  141. os.remove(pip_bin)
  142. # Let's run the state which should fail because pip is missing
  143. ret = self.run_function('state.sls', mods='issue-2087-missing-pip')
  144. self.assertSaltFalseReturn(ret)
  145. self.assertInSaltComment(
  146. 'Error installing \'pep8\': Could not find a `pip` binary',
  147. ret
  148. )
  149. finally:
  150. if os.path.isdir(venv_dir):
  151. shutil.rmtree(venv_dir)
  152. def test_issue_5940_multiple_pip_mirrors(self):
  153. '''
  154. Test multiple pip mirrors. This test only works with pip < 7.0.0
  155. '''
  156. ret = self.run_function(
  157. 'state.sls', mods='issue-5940-multiple-pip-mirrors'
  158. )
  159. venv_dir = os.path.join(
  160. integration.SYS_TMP_DIR, '5940-multiple-pip-mirrors'
  161. )
  162. try:
  163. self.assertSaltTrueReturn(ret)
  164. self.assertTrue(
  165. os.path.isfile(os.path.join(venv_dir, 'bin', 'pep8'))
  166. )
  167. except (AssertionError, CommandExecutionError):
  168. pip_version = self.run_function('pip.version', [venv_dir])
  169. if salt.utils.compare_versions(ver1=pip_version, oper='>=', ver2='7.0.0'):
  170. self.skipTest('the --mirrors arg has been deprecated and removed in pip==7.0.0')
  171. finally:
  172. if os.path.isdir(venv_dir):
  173. shutil.rmtree(venv_dir)
  174. @destructiveTest
  175. @skipIf(os.geteuid() != 0, 'you must be root to run this test')
  176. @with_system_user('issue-6912', on_existing='delete', delete=True)
  177. def test_issue_6912_wrong_owner(self, username):
  178. venv_dir = os.path.join(
  179. integration.SYS_TMP_DIR, '6912-wrong-owner'
  180. )
  181. # ----- Using runas ------------------------------------------------->
  182. venv_create = self.run_function(
  183. 'virtualenv.create', [venv_dir], user=username
  184. )
  185. if venv_create['retcode'] > 0:
  186. self.skipTest(
  187. 'Failed to create testcase virtual environment: {0}'.format(
  188. venv_create
  189. )
  190. )
  191. # Using the package name.
  192. try:
  193. ret = self.run_state(
  194. 'pip.installed', name='pep8', user=username, bin_env=venv_dir
  195. )
  196. self.assertSaltTrueReturn(ret)
  197. uinfo = pwd.getpwnam(username)
  198. for globmatch in (os.path.join(venv_dir, '**', 'pep8*'),
  199. os.path.join(venv_dir, '*', '**', 'pep8*'),
  200. os.path.join(venv_dir, '*', '*', '**', 'pep8*')):
  201. for path in glob.glob(globmatch):
  202. self.assertEqual(
  203. uinfo.pw_uid, os.stat(path).st_uid
  204. )
  205. finally:
  206. if os.path.isdir(venv_dir):
  207. shutil.rmtree(venv_dir)
  208. # Using a requirements file
  209. venv_create = self.run_function(
  210. 'virtualenv.create', [venv_dir], user=username
  211. )
  212. if venv_create['retcode'] > 0:
  213. self.skipTest(
  214. 'Failed to create testcase virtual environment: {0}'.format(
  215. ret
  216. )
  217. )
  218. req_filename = os.path.join(
  219. integration.TMP_STATE_TREE, 'issue-6912-requirements.txt'
  220. )
  221. with salt.utils.fopen(req_filename, 'wb') as reqf:
  222. reqf.write('pep8')
  223. try:
  224. ret = self.run_state(
  225. 'pip.installed', name='', user=username, bin_env=venv_dir,
  226. requirements='salt://issue-6912-requirements.txt'
  227. )
  228. self.assertSaltTrueReturn(ret)
  229. uinfo = pwd.getpwnam(username)
  230. for globmatch in (os.path.join(venv_dir, '**', 'pep8*'),
  231. os.path.join(venv_dir, '*', '**', 'pep8*'),
  232. os.path.join(venv_dir, '*', '*', '**', 'pep8*')):
  233. for path in glob.glob(globmatch):
  234. self.assertEqual(
  235. uinfo.pw_uid, os.stat(path).st_uid
  236. )
  237. finally:
  238. if os.path.isdir(venv_dir):
  239. shutil.rmtree(venv_dir)
  240. os.unlink(req_filename)
  241. # <---- Using runas --------------------------------------------------
  242. # ----- Using user -------------------------------------------------->
  243. venv_create = self.run_function(
  244. 'virtualenv.create', [venv_dir], user=username
  245. )
  246. if venv_create['retcode'] > 0:
  247. self.skipTest(
  248. 'Failed to create testcase virtual environment: {0}'.format(
  249. ret
  250. )
  251. )
  252. # Using the package name
  253. try:
  254. ret = self.run_state(
  255. 'pip.installed', name='pep8', user=username, bin_env=venv_dir
  256. )
  257. self.assertSaltTrueReturn(ret)
  258. uinfo = pwd.getpwnam(username)
  259. for globmatch in (os.path.join(venv_dir, '**', 'pep8*'),
  260. os.path.join(venv_dir, '*', '**', 'pep8*'),
  261. os.path.join(venv_dir, '*', '*', '**', 'pep8*')):
  262. for path in glob.glob(globmatch):
  263. self.assertEqual(
  264. uinfo.pw_uid, os.stat(path).st_uid
  265. )
  266. finally:
  267. if os.path.isdir(venv_dir):
  268. shutil.rmtree(venv_dir)
  269. # Using a requirements file
  270. venv_create = self.run_function(
  271. 'virtualenv.create', [venv_dir], user=username
  272. )
  273. if venv_create['retcode'] > 0:
  274. self.skipTest(
  275. 'Failed to create testcase virtual environment: {0}'.format(
  276. ret
  277. )
  278. )
  279. req_filename = os.path.join(
  280. integration.TMP_STATE_TREE, 'issue-6912-requirements.txt'
  281. )
  282. with salt.utils.fopen(req_filename, 'wb') as reqf:
  283. reqf.write('pep8')
  284. try:
  285. ret = self.run_state(
  286. 'pip.installed', name='', user=username, bin_env=venv_dir,
  287. requirements='salt://issue-6912-requirements.txt'
  288. )
  289. self.assertSaltTrueReturn(ret)
  290. uinfo = pwd.getpwnam(username)
  291. for globmatch in (os.path.join(venv_dir, '**', 'pep8*'),
  292. os.path.join(venv_dir, '*', '**', 'pep8*'),
  293. os.path.join(venv_dir, '*', '*', '**', 'pep8*')):
  294. for path in glob.glob(globmatch):
  295. self.assertEqual(
  296. uinfo.pw_uid, os.stat(path).st_uid
  297. )
  298. finally:
  299. if os.path.isdir(venv_dir):
  300. shutil.rmtree(venv_dir)
  301. os.unlink(req_filename)
  302. # <---- Using user ---------------------------------------------------
  303. def test_issue_6833_pip_upgrade_pip(self):
  304. # Create the testing virtualenv
  305. venv_dir = os.path.join(
  306. integration.TMP, '6833-pip-upgrade-pip'
  307. )
  308. ret = self.run_function('virtualenv.create', [venv_dir])
  309. try:
  310. try:
  311. self.assertEqual(ret['retcode'], 0)
  312. self.assertIn(
  313. 'New python executable',
  314. ret['stdout']
  315. )
  316. except AssertionError:
  317. import pprint
  318. pprint.pprint(ret)
  319. raise
  320. # Let's install a fixed version pip over whatever pip was
  321. # previously installed
  322. ret = self.run_function(
  323. 'pip.install', ['pip==6.0'], upgrade=True,
  324. ignore_installed=True,
  325. bin_env=venv_dir
  326. )
  327. try:
  328. self.assertEqual(ret['retcode'], 0)
  329. self.assertIn(
  330. 'Successfully installed pip',
  331. ret['stdout']
  332. )
  333. except AssertionError:
  334. import pprint
  335. pprint.pprint(ret)
  336. raise
  337. # Le't make sure we have pip 6.0 installed
  338. self.assertEqual(
  339. self.run_function('pip.list', ['pip'], bin_env=venv_dir),
  340. {'pip': '6.0'}
  341. )
  342. # Now the actual pip upgrade pip test
  343. ret = self.run_state(
  344. 'pip.installed', name='pip==6.0.7', upgrade=True,
  345. bin_env=venv_dir
  346. )
  347. try:
  348. self.assertSaltTrueReturn(ret)
  349. self.assertInSaltReturn(
  350. 'Installed',
  351. ret,
  352. ['changes', 'pip==6.0.7']
  353. )
  354. except AssertionError:
  355. import pprint
  356. pprint.pprint(ret)
  357. raise
  358. finally:
  359. if os.path.isdir(venv_dir):
  360. shutil.rmtree(venv_dir)
  361. def test_pip_installed_specific_env(self):
  362. # Create the testing virtualenv
  363. venv_dir = os.path.join(
  364. integration.TMP, 'pip-installed-specific-env'
  365. )
  366. # Let's write a requirements file
  367. requirements_file = os.path.join(
  368. integration.TMP_PRODENV_STATE_TREE, 'prod-env-requirements.txt'
  369. )
  370. with salt.utils.fopen(requirements_file, 'wb') as reqf:
  371. reqf.write('pep8\n')
  372. try:
  373. self.run_function('virtualenv.create', [venv_dir])
  374. # The requirements file should not be found the base environment
  375. ret = self.run_state(
  376. 'pip.installed', name='', bin_env=venv_dir,
  377. requirements='salt://prod-env-requirements.txt'
  378. )
  379. self.assertSaltFalseReturn(ret)
  380. self.assertInSaltComment(
  381. "'salt://prod-env-requirements.txt' not found", ret
  382. )
  383. # The requirements file must be found in the prod environment
  384. ret = self.run_state(
  385. 'pip.installed', name='', bin_env=venv_dir, saltenv='prod',
  386. requirements='salt://prod-env-requirements.txt'
  387. )
  388. self.assertSaltTrueReturn(ret)
  389. self.assertInSaltComment(
  390. 'Successfully processed requirements file '
  391. 'salt://prod-env-requirements.txt', ret
  392. )
  393. # We're using the base environment but we're passing the prod
  394. # environment as an url arg to salt://
  395. ret = self.run_state(
  396. 'pip.installed', name='', bin_env=venv_dir,
  397. requirements='salt://prod-env-requirements.txt?saltenv=prod'
  398. )
  399. self.assertSaltTrueReturn(ret)
  400. self.assertInSaltComment(
  401. 'Requirements were already installed.',
  402. ret
  403. )
  404. finally:
  405. if os.path.isdir(venv_dir):
  406. shutil.rmtree(venv_dir)
  407. if os.path.isfile(requirements_file):
  408. os.unlink(requirements_file)
  409. def test_22359_pip_installed_unless_does_not_trigger_warnings(self):
  410. # This test case should be moved to a format_call unit test specific to
  411. # the state internal keywords
  412. venv_dir = venv_dir = os.path.join(
  413. integration.TMP, 'pip-installed-unless'
  414. )
  415. venv_create = self.run_function('virtualenv.create', [venv_dir])
  416. if venv_create['retcode'] > 0:
  417. self.skipTest(
  418. 'Failed to create testcase virtual environment: {0}'.format(
  419. venv_create
  420. )
  421. )
  422. try:
  423. ret = self.run_state(
  424. 'pip.installed', name='pep8', bin_env=venv_dir, unless='/bin/false'
  425. )
  426. self.assertSaltTrueReturn(ret)
  427. self.assertNotIn('warnings', next(ret.itervalues()))
  428. finally:
  429. if os.path.isdir(venv_dir):
  430. shutil.rmtree(venv_dir)
  431. if __name__ == '__main__':
  432. from integration import run_tests
  433. run_tests(PipStateTest)