salt/tests/unit/states/test_pip.py

296 lines
13 KiB
Python
Raw Normal View History

# -*- coding: utf-8 -*-
'''
:codeauthor: :email:`Pedro Algarvio (pedro@algarvio.me)`
tests.unit.states.pip_test
~~~~~~~~~~~~~~~~~~~~~~~~~~
'''
# Import python libs
from __future__ import absolute_import
# Import Salt Testing libs
2017-02-19 15:35:30 +00:00
from tests.integration import SaltReturnAssertsMixIn
from tests.support.mixins import LoaderModuleMockMixin
from tests.support.unit import skipIf, TestCase
from tests.support.mock import NO_MOCK, NO_MOCK_REASON, MagicMock, patch
# Import salt libs
import salt.states.pip_state as pip_state
# Import 3rd-party libs
try:
import pip
HAS_PIP = True
except ImportError:
HAS_PIP = False
@skipIf(NO_MOCK, NO_MOCK_REASON)
@skipIf(not HAS_PIP,
'The \'pip\' library is not importable(installed system-wide)')
2017-02-19 15:35:30 +00:00
class PipStateTest(TestCase, SaltReturnAssertsMixIn, LoaderModuleMockMixin):
loader_module = pip_state
def loader_module_globals(self):
return {
'__env__': 'base',
'__opts__': {'test': False},
'__salt__': {'cmd.which_bin': lambda _: 'pip'}
}
def test_install_requirements_parsing(self):
2013-08-18 06:27:32 +00:00
mock = MagicMock(return_value={'retcode': 0, 'stdout': ''})
pip_list = MagicMock(return_value={'pep8': '1.3.3'})
with patch.dict(pip_state.__salt__, {'cmd.run_all': mock,
'pip.list': pip_list}):
with patch.dict(pip_state.__opts__, {'test': True}):
ret = pip_state.installed('pep8=1.3.2')
2013-08-18 06:27:32 +00:00
self.assertSaltFalseReturn({'test': ret})
self.assertInSaltComment(
'Invalid version specification in package pep8=1.3.2. '
'\'=\' is not supported, use \'==\' instead.',
{'test': ret}
)
mock = MagicMock(return_value={'retcode': 0, 'stdout': ''})
pip_list = MagicMock(return_value={'pep8': '1.3.3'})
2014-12-19 18:05:47 +00:00
pip_install = MagicMock(return_value={'retcode': 0})
with patch.dict(pip_state.__salt__, {'cmd.run_all': mock,
2014-12-19 18:05:47 +00:00
'pip.list': pip_list,
'pip.install': pip_install}):
with patch.dict(pip_state.__opts__, {'test': True}):
ret = pip_state.installed('pep8>=1.3.2')
self.assertSaltTrueReturn({'test': ret})
self.assertInSaltComment(
2014-12-19 18:05:47 +00:00
'Python package pep8>=1.3.2 was already installed',
{'test': ret}
)
mock = MagicMock(return_value={'retcode': 0, 'stdout': ''})
pip_list = MagicMock(return_value={'pep8': '1.3.3'})
with patch.dict(pip_state.__salt__, {'cmd.run_all': mock,
'pip.list': pip_list}):
with patch.dict(pip_state.__opts__, {'test': True}):
ret = pip_state.installed('pep8<1.3.2')
self.assertSaltNoneReturn({'test': ret})
self.assertInSaltComment(
'Python package pep8<1.3.2 is set to be installed',
{'test': ret}
)
mock = MagicMock(return_value={'retcode': 0, 'stdout': ''})
pip_list = MagicMock(return_value={'pep8': '1.3.2'})
2014-12-19 18:05:47 +00:00
pip_install = MagicMock(return_value={'retcode': 0})
with patch.dict(pip_state.__salt__, {'cmd.run_all': mock,
2014-12-19 18:05:47 +00:00
'pip.list': pip_list,
'pip.install': pip_install}):
with patch.dict(pip_state.__opts__, {'test': True}):
ret = pip_state.installed('pep8>1.3.1,<1.3.3')
self.assertSaltTrueReturn({'test': ret})
self.assertInSaltComment(
2014-12-19 18:05:47 +00:00
'Python package pep8>1.3.1,<1.3.3 was already installed',
{'test': ret}
)
mock = MagicMock(return_value={'retcode': 0, 'stdout': ''})
pip_list = MagicMock(return_value={'pep8': '1.3.1'})
2014-12-19 18:05:47 +00:00
pip_install = MagicMock(return_value={'retcode': 0})
with patch.dict(pip_state.__salt__, {'cmd.run_all': mock,
2014-12-19 18:05:47 +00:00
'pip.list': pip_list,
'pip.install': pip_install}):
with patch.dict(pip_state.__opts__, {'test': True}):
ret = pip_state.installed('pep8>1.3.1,<1.3.3')
self.assertSaltNoneReturn({'test': ret})
self.assertInSaltComment(
2014-12-19 18:05:47 +00:00
'Python package pep8>1.3.1,<1.3.3 is set to be installed',
{'test': ret}
)
2013-08-18 06:27:32 +00:00
mock = MagicMock(return_value={'retcode': 0, 'stdout': ''})
pip_list = MagicMock(return_value={'pep8': '1.3.1'})
with patch.dict(pip_state.__salt__, {'cmd.run_all': mock,
'pip.list': pip_list}):
with patch.dict(pip_state.__opts__, {'test': True}):
ret = pip_state.installed(
2013-08-18 06:27:32 +00:00
'git+https://github.com/saltstack/salt-testing.git#egg=SaltTesting>=0.5.1'
)
self.assertSaltNoneReturn({'test': ret})
self.assertInSaltComment(
'Python package git+https://github.com/saltstack/'
'salt-testing.git#egg=SaltTesting>=0.5.1 is set to be '
'installed',
{'test': ret}
)
mock = MagicMock(return_value={'retcode': 0, 'stdout': ''})
pip_list = MagicMock(return_value={'pep8': '1.3.1'})
with patch.dict(pip_state.__salt__, {'cmd.run_all': mock,
'pip.list': pip_list}):
with patch.dict(pip_state.__opts__, {'test': True}):
ret = pip_state.installed(
'git+https://github.com/saltstack/salt-testing.git#egg=SaltTesting'
)
self.assertSaltNoneReturn({'test': ret})
self.assertInSaltComment(
'Python package git+https://github.com/saltstack/'
'salt-testing.git#egg=SaltTesting is set to be '
2013-08-18 06:27:32 +00:00
'installed',
{'test': ret}
)
mock = MagicMock(return_value={'retcode': 0, 'stdout': ''})
pip_list = MagicMock(return_value={'pep8': '1.3.1'})
with patch.dict(pip_state.__salt__, {'cmd.run_all': mock,
'pip.list': pip_list}):
with patch.dict(pip_state.__opts__, {'test': True}):
ret = pip_state.installed(
2013-08-18 06:27:32 +00:00
'https://pypi.python.org/packages/source/S/SaltTesting/'
'SaltTesting-0.5.0.tar.gz'
'#md5=e6760af92b7165f8be53b5763e40bc24'
)
self.assertSaltNoneReturn({'test': ret})
self.assertInSaltComment(
'Python package https://pypi.python.org/packages/source/'
'S/SaltTesting/SaltTesting-0.5.0.tar.gz'
'#md5=e6760af92b7165f8be53b5763e40bc24 is set to be '
'installed',
{'test': ret}
)
2013-08-18 07:03:41 +00:00
mock = MagicMock(return_value={'retcode': 0, 'stdout': ''})
pip_list = MagicMock(return_value={'SaltTesting': '0.5.0'})
pip_install = MagicMock(return_value={
'retcode': 0,
2013-11-27 12:59:56 +00:00
'stderr': '',
2013-08-18 07:03:41 +00:00
'stdout': 'Downloading/unpacking https://pypi.python.org/packages'
'/source/S/SaltTesting/SaltTesting-0.5.0.tar.gz\n '
'Downloading SaltTesting-0.5.0.tar.gz\n Running '
'setup.py egg_info for package from '
'https://pypi.python.org/packages/source/S/SaltTesting/'
'SaltTesting-0.5.0.tar.gz\n \nCleaning up...'
})
with patch.dict(pip_state.__salt__, {'cmd.run_all': mock,
'pip.list': pip_list,
'pip.install': pip_install}):
ret = pip_state.installed(
2013-08-18 07:03:41 +00:00
'https://pypi.python.org/packages/source/S/SaltTesting/'
'SaltTesting-0.5.0.tar.gz'
'#md5=e6760af92b7165f8be53b5763e40bc24'
)
self.assertSaltTrueReturn({'test': ret})
2014-12-19 18:05:47 +00:00
self.assertInSaltComment('All packages were successfully installed',
2013-08-18 07:03:41 +00:00
{'test': ret}
)
self.assertInSaltReturn(
'Installed',
{'test': ret},
('changes', 'https://pypi.python.org/packages/source/S/'
'SaltTesting/SaltTesting-0.5.0.tar.gz'
'#md5=e6760af92b7165f8be53b5763e40bc24==???')
2013-08-18 07:03:41 +00:00
)
mock = MagicMock(return_value={'retcode': 0, 'stdout': ''})
2014-12-19 18:05:47 +00:00
pip_list = MagicMock(return_value={'SaltTesting': '0.5.0'})
pip_install = MagicMock(return_value={
'retcode': 0,
2013-11-27 12:59:56 +00:00
'stderr': '',
'stdout': 'Cloned!'
})
with patch.dict(pip_state.__salt__, {'cmd.run_all': mock,
'pip.list': pip_list,
'pip.install': pip_install}):
with patch.dict(pip_state.__opts__, {'test': False}):
ret = pip_state.installed(
'git+https://github.com/saltstack/salt-testing.git#egg=SaltTesting'
)
self.assertSaltTrueReturn({'test': ret})
self.assertInSaltComment(
2014-12-19 18:05:47 +00:00
'successfully installed',
{'test': ret}
)
mock = MagicMock(return_value={'retcode': 0, 'stdout': ''})
pip_list = MagicMock(return_value={'pep8': '1.3.1'})
2013-11-27 12:59:56 +00:00
pip_install = MagicMock(return_value={'retcode': 0})
with patch.dict(pip_state.__salt__, {'cmd.run_all': mock,
'pip.list': pip_list,
'pip.install': pip_install}):
with patch.dict(pip_state.__opts__, {'test': False}):
ret = pip_state.installed(
'arbitrary ID that should be ignored due to requirements specified',
requirements='/tmp/non-existing-requirements.txt'
)
self.assertSaltTrueReturn({'test': ret})
# Test VCS installations using git+git://
mock = MagicMock(return_value={'retcode': 0, 'stdout': ''})
2014-12-19 18:05:47 +00:00
pip_list = MagicMock(return_value={'SaltTesting': '0.5.0'})
pip_install = MagicMock(return_value={
'retcode': 0,
2013-11-27 12:59:56 +00:00
'stderr': '',
'stdout': 'Cloned!'
})
with patch.dict(pip_state.__salt__, {'cmd.run_all': mock,
'pip.list': pip_list,
'pip.install': pip_install}):
with patch.dict(pip_state.__opts__, {'test': False}):
ret = pip_state.installed(
'git+git://github.com/saltstack/salt-testing.git#egg=SaltTesting'
)
self.assertSaltTrueReturn({'test': ret})
self.assertInSaltComment(
2014-12-19 18:05:47 +00:00
'were successfully installed',
{'test': ret}
)
# Test VCS installations with version info like >= 0.1
2017-02-19 15:35:30 +00:00
with patch.object(pip, '__version__', MagicMock(side_effect=AttributeError(
'Faked missing __version__ attribute'))):
mock = MagicMock(return_value={'retcode': 0, 'stdout': ''})
pip_list = MagicMock(return_value={'SaltTesting': '0.5.0'})
pip_install = MagicMock(return_value={
'retcode': 0,
'stderr': '',
'stdout': 'Cloned!'
})
with patch.dict(pip_state.__salt__, {'cmd.run_all': mock,
'pip.list': pip_list,
'pip.install': pip_install}):
with patch.dict(pip_state.__opts__, {'test': False}):
ret = pip_state.installed(
'git+https://github.com/saltstack/salt-testing.git#egg=SaltTesting>=0.5.0'
)
self.assertSaltTrueReturn({'test': ret})
self.assertInSaltComment(
'were successfully installed',
{'test': ret}
)
def test_install_in_editable_mode(self):
'''
Check that `name` parameter containing bad characters is not parsed by
pip when package is being installed in editable mode.
For more information, see issue #21890.
'''
mock = MagicMock(return_value={'retcode': 0, 'stdout': ''})
pip_list = MagicMock(return_value={})
pip_install = MagicMock(return_value={
'retcode': 0,
'stderr': '',
'stdout': 'Cloned!'
})
with patch.dict(pip_state.__salt__, {'cmd.run_all': mock,
'pip.list': pip_list,
'pip.install': pip_install}):
ret = pip_state.installed('state@name',
cwd='/path/to/project',
editable=['.'])
self.assertSaltTrueReturn({'test': ret})
self.assertInSaltComment(
'successfully installed',
{'test': ret}
)