mirror of
https://github.com/valitydev/salt.git
synced 2024-11-06 16:45:27 +00:00
Merge branch 'develop' into improvement-spm-base_paths
This commit is contained in:
commit
52248ff433
@ -1,5 +1,5 @@
|
||||
---
|
||||
<% vagrant = system('which vagrant 2>/dev/null >/dev/null') %>
|
||||
<% vagrant = system('gem list -i kitchen-vagrant 2>/dev/null >/dev/null') %>
|
||||
<% version = '2017.7.4' %>
|
||||
<% platformsfile = ENV['SALT_KITCHEN_PLATFORMS'] || '.kitchen/platforms.yml' %>
|
||||
<% driverfile = ENV['SALT_KITCHEN_DRIVER'] || '.kitchen/driver.yml' %>
|
||||
@ -94,12 +94,9 @@ platforms:
|
||||
- yum install -y upstart
|
||||
provisioner:
|
||||
salt_bootstrap_options: -P -p rsync -y -x python2.7 -X git v<%= version %> >/dev/null
|
||||
- name: ubuntu-rolling
|
||||
- name: ubuntu-18.04
|
||||
driver_config:
|
||||
image: ubuntu:rolling
|
||||
run_command: /lib/systemd/systemd
|
||||
provisioner:
|
||||
salt_bootstrap_url: https://raw.githubusercontent.com/saltstack/salt-bootstrap/develop/bootstrap-salt.sh
|
||||
- name: ubuntu-16.04
|
||||
driver_config:
|
||||
run_command: /lib/systemd/systemd
|
||||
|
@ -38,7 +38,10 @@ from __future__ import division
|
||||
import re
|
||||
from docutils import nodes
|
||||
from docutils.parsers.rst import directives
|
||||
from sphinx.util.compat import Directive
|
||||
try:
|
||||
from sphinx.util.compat import Directive
|
||||
except ImportError:
|
||||
from docutils.parsers.rst import Directive
|
||||
|
||||
CONTROL_HEIGHT = 30
|
||||
|
||||
|
@ -17,3 +17,4 @@ roster modules
|
||||
flat
|
||||
range
|
||||
scan
|
||||
sshconfig
|
||||
|
6
doc/ref/roster/all/salt.roster.sshconfig.rst
Normal file
6
doc/ref/roster/all/salt.roster.sshconfig.rst
Normal file
@ -0,0 +1,6 @@
|
||||
=====================
|
||||
salt.roster.sshconfig
|
||||
=====================
|
||||
|
||||
.. automodule:: salt.roster.sshconfig
|
||||
:members:
|
@ -314,11 +314,14 @@ state modules
|
||||
winrepo
|
||||
x509
|
||||
xmpp
|
||||
zabbix_action
|
||||
zabbix_host
|
||||
zabbix_hostgroup
|
||||
zabbix_mediatype
|
||||
zabbix_template
|
||||
zabbix_user
|
||||
zabbix_usergroup
|
||||
zabbix_valuemap
|
||||
zcbuildout
|
||||
zenoss
|
||||
zk_concurrency
|
||||
|
@ -1,5 +1,5 @@
|
||||
salt.states.zabbix_action module
|
||||
==============================
|
||||
salt.states.zabbix_action
|
||||
=========================
|
||||
|
||||
.. automodule:: salt.states.zabbix_action
|
||||
:members:
|
||||
|
@ -1,5 +1,5 @@
|
||||
salt.states.zabbix_template module
|
||||
==============================
|
||||
salt.states.zabbix_template
|
||||
===========================
|
||||
|
||||
.. automodule:: salt.states.zabbix_template
|
||||
:members:
|
||||
|
@ -1,5 +1,5 @@
|
||||
salt.states.zabbix_valuemap module
|
||||
==============================
|
||||
salt.states.zabbix_valuemap
|
||||
===========================
|
||||
|
||||
.. automodule:: salt.states.zabbix_valuemap
|
||||
:members:
|
||||
|
@ -1,8 +1,9 @@
|
||||
===========================
|
||||
Salt 2017.7.6 Release Notes
|
||||
In Progress: Salt 2017.7.6 Release Notes
|
||||
===========================
|
||||
|
||||
Version 2017.7.6 is a bugfix release for :ref:`2017.7.0 <release-2017-7-0>`.
|
||||
Version 2017.7.6 is an **unreleased** bugfix release for :ref:`2017.7.0 <release-2017-7-0>`.
|
||||
This release is still in progress and has not been released yet.
|
||||
|
||||
Option to Return to Previous Pillar Include Behavior
|
||||
----------------------------------------------------
|
||||
|
@ -59,11 +59,13 @@ To match a nodegroup on the CLI, use the ``-N`` command-line option:
|
||||
|
||||
salt -N group1 test.ping
|
||||
|
||||
.. versionadded:: Fluorine
|
||||
.. note::
|
||||
|
||||
The ``N@`` classifier cannot be used in compound matches within the CLI or
|
||||
:term:`top file`, it is only recognized in the :conf_master:`nodegroups`
|
||||
master config file parameter.
|
||||
The ``N@`` classifier historically could not be used in compound matches
|
||||
within the CLI or :term:`top file`, it was only recognized in the
|
||||
:conf_master:`nodegroups` master config file parameter. As of Fluorine
|
||||
release, this limitation no longer exists.
|
||||
|
||||
To match a nodegroup in your :term:`top file`, make sure to put ``- match:
|
||||
nodegroup`` on the line directly following the nodegroup name.
|
||||
|
@ -740,7 +740,7 @@ Function ${un}uninstallSalt
|
||||
|
||||
# Remove files
|
||||
Delete "$INSTDIR\uninst.exe"
|
||||
Delete "$INSTDIR\nssm.exe"
|
||||
Delete "$INSTDIR\ssm.exe"
|
||||
Delete "$INSTDIR\salt*"
|
||||
Delete "$INSTDIR\vcredist.exe"
|
||||
RMDir /r "$INSTDIR\bin"
|
||||
|
@ -35,7 +35,7 @@ Function Get-Settings {
|
||||
|
||||
# Prerequisite software
|
||||
$Prerequisites = @{
|
||||
"NSIS" = "nsis-3.02.1-setup.exe"
|
||||
"NSIS" = "nsis-3.03-setup.exe"
|
||||
"VCforPython" = "VCForPython27.msi"
|
||||
"VCppBuildTools" = "visualcppbuildtools_full.exe"
|
||||
}
|
||||
@ -59,21 +59,15 @@ Function Get-Settings {
|
||||
|
||||
# Filenames for 64 bit Windows
|
||||
$64bitPrograms = @{
|
||||
"PyCrypto2" = "pycrypto-2.6.1-cp27-none-win_amd64.whl"
|
||||
"Python2" = "python-2.7.14.amd64.msi"
|
||||
"PyWin322" = "pywin32-221-cp27-cp27m-win_amd64.whl"
|
||||
"Python3" = "python-3.5.3-amd64.exe"
|
||||
"PyWin323" = "pywin32-221-cp35-cp35m-win_amd64.whl"
|
||||
}
|
||||
$ini.Add("64bitPrograms", $64bitPrograms)
|
||||
|
||||
# Filenames for 32 bit Windows
|
||||
$32bitPrograms = @{
|
||||
"PyCrypto2" = "pycrypto-2.6.1-cp27-none-win32.whl"
|
||||
"Python2" = "python-2.7.14.msi"
|
||||
"PyWin322" = "pywin32-221-cp27-cp27m-win32.whl"
|
||||
"Python3" = "python-3.5.3.exe"
|
||||
"PyWin323" = "pywin32-221-cp35-cp35m-win32.whl"
|
||||
}
|
||||
$ini.Add("32bitPrograms", $32bitPrograms)
|
||||
|
||||
|
4
requirements/base-py2.txt
Normal file
4
requirements/base-py2.txt
Normal file
@ -0,0 +1,4 @@
|
||||
-r base.txt
|
||||
|
||||
# Required by Tornado to handle threads stuff.
|
||||
futures>=2.0
|
1
requirements/base-py3.txt
Normal file
1
requirements/base-py3.txt
Normal file
@ -0,0 +1 @@
|
||||
-r base.txt
|
@ -135,9 +135,9 @@ def lowstate_file_refs(chunks, extras=''):
|
||||
elif state.startswith('__'):
|
||||
continue
|
||||
crefs.extend(salt_refs(chunk[state]))
|
||||
if saltenv not in refs:
|
||||
refs[saltenv] = []
|
||||
if crefs:
|
||||
if saltenv not in refs:
|
||||
refs[saltenv] = []
|
||||
refs[saltenv].append(crefs)
|
||||
if extras:
|
||||
extra_refs = extras.split(',')
|
||||
|
@ -3699,6 +3699,25 @@ def enable_term_protect(name, call=None):
|
||||
return _toggle_term_protect(name, 'true')
|
||||
|
||||
|
||||
def disable_term_protect(name, call=None):
|
||||
'''
|
||||
Disable termination protection on a node
|
||||
|
||||
CLI Example:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
salt-cloud -a disable_term_protect mymachine
|
||||
'''
|
||||
if call != 'action':
|
||||
raise SaltCloudSystemExit(
|
||||
'The enable_term_protect action must be called with '
|
||||
'-a or --action.'
|
||||
)
|
||||
|
||||
return _toggle_term_protect(name, 'false')
|
||||
|
||||
|
||||
def disable_detailed_monitoring(name, call=None):
|
||||
'''
|
||||
Enable/disable detailed monitoring on a node
|
||||
|
@ -3421,7 +3421,7 @@ def is_profile_configured(opts, provider, profile_name, vm_=None):
|
||||
# Most drivers need a size, but some do not.
|
||||
non_size_drivers = ['opennebula', 'parallels', 'proxmox', 'scaleway',
|
||||
'softlayer', 'softlayer_hw', 'vmware', 'vsphere',
|
||||
'virtualbox', 'libvirt', 'oneandone']
|
||||
'virtualbox', 'libvirt', 'oneandone', 'profitbricks']
|
||||
|
||||
provider_key = opts['providers'][alias][driver]
|
||||
profile_key = opts['providers'][alias][driver]['profiles'][profile_name]
|
||||
|
@ -459,7 +459,11 @@ def _bsd_memdata(osdata):
|
||||
|
||||
if osdata['kernel'] in ['OpenBSD', 'NetBSD']:
|
||||
swapctl = salt.utils.path.which('swapctl')
|
||||
swap_total = __salt__['cmd.run']('{0} -sk'.format(swapctl)).split(' ')[1]
|
||||
swap_data = __salt__['cmd.run']('{0} -sk'.format(swapctl))
|
||||
if swap_data == 'no swap devices configured':
|
||||
swap_total = 0
|
||||
else:
|
||||
swap_total = swap_data.split(' ')[1]
|
||||
else:
|
||||
swap_total = __salt__['cmd.run']('{0} -n vm.swap_total'.format(sysctl))
|
||||
grains['swap_total'] = int(swap_total) // 1024 // 1024
|
||||
|
@ -3370,6 +3370,8 @@ class Matcher(object):
|
||||
'''
|
||||
Runs the compound target check
|
||||
'''
|
||||
nodegroups = self.opts.get('nodegroups', {})
|
||||
|
||||
if not isinstance(tgt, six.string_types) and not isinstance(tgt, (list, tuple)):
|
||||
log.error('Compound target received that is neither string, list nor tuple')
|
||||
return False
|
||||
@ -3391,9 +3393,11 @@ class Matcher(object):
|
||||
if isinstance(tgt, six.string_types):
|
||||
words = tgt.split()
|
||||
else:
|
||||
words = tgt
|
||||
# we make a shallow copy in order to not affect the passed in arg
|
||||
words = tgt[:]
|
||||
|
||||
for word in words:
|
||||
while words:
|
||||
word = words.pop(0)
|
||||
target_info = salt.utils.minions.parse_target(word)
|
||||
|
||||
# Easy check first
|
||||
@ -3415,10 +3419,12 @@ class Matcher(object):
|
||||
|
||||
elif target_info and target_info['engine']:
|
||||
if 'N' == target_info['engine']:
|
||||
# Nodegroups should already be expanded/resolved to other engines
|
||||
log.error(
|
||||
'Detected nodegroup expansion failure of "%s"', word)
|
||||
return False
|
||||
# if we encounter a node group, just evaluate it in-place
|
||||
decomposed = salt.utils.minions.nodegroup_comp(target_info['pattern'], nodegroups)
|
||||
if decomposed:
|
||||
words = decomposed + words
|
||||
continue
|
||||
|
||||
engine = ref.get(target_info['engine'])
|
||||
if not engine:
|
||||
# If an unknown engine is called at any time, fail out
|
||||
|
@ -36,6 +36,7 @@ import salt.utils.timed_subprocess
|
||||
import salt.utils.user
|
||||
import salt.utils.versions
|
||||
import salt.utils.vt
|
||||
import salt.utils.win_dacl
|
||||
import salt.utils.win_reg
|
||||
import salt.grains.extra
|
||||
from salt.ext import six
|
||||
@ -542,6 +543,7 @@ def _run(cmd,
|
||||
env.setdefault('LC_TELEPHONE', 'C')
|
||||
env.setdefault('LC_MEASUREMENT', 'C')
|
||||
env.setdefault('LC_IDENTIFICATION', 'C')
|
||||
env.setdefault('LANGUAGE', 'C')
|
||||
else:
|
||||
# On Windows set the codepage to US English.
|
||||
if python_shell:
|
||||
@ -2415,11 +2417,14 @@ def script(source,
|
||||
# "env" is not supported; Use "saltenv".
|
||||
kwargs.pop('__env__')
|
||||
|
||||
win_cwd = False
|
||||
if salt.utils.platform.is_windows() and runas and cwd is None:
|
||||
# Create a temp working directory
|
||||
cwd = tempfile.mkdtemp(dir=__opts__['cachedir'])
|
||||
__salt__['win_dacl.add_ace'](
|
||||
cwd, 'File', runas, 'READ&EXECUTE', 'ALLOW',
|
||||
'FOLDER&SUBFOLDERS&FILES')
|
||||
win_cwd = True
|
||||
salt.utils.win_dacl.set_permissions(obj_name=cwd,
|
||||
principal=runas,
|
||||
permissions='full_control')
|
||||
|
||||
path = salt.utils.files.mkstemp(dir=cwd, suffix=os.path.splitext(source)[1])
|
||||
|
||||
@ -2433,10 +2438,10 @@ def script(source,
|
||||
saltenv,
|
||||
**kwargs)
|
||||
if not fn_:
|
||||
if salt.utils.platform.is_windows() and runas:
|
||||
_cleanup_tempfile(path)
|
||||
# If a temp working directory was created (Windows), let's remove that
|
||||
if win_cwd:
|
||||
_cleanup_tempfile(cwd)
|
||||
else:
|
||||
_cleanup_tempfile(path)
|
||||
return {'pid': 0,
|
||||
'retcode': 1,
|
||||
'stdout': '',
|
||||
@ -2445,10 +2450,10 @@ def script(source,
|
||||
else:
|
||||
fn_ = __salt__['cp.cache_file'](source, saltenv)
|
||||
if not fn_:
|
||||
if salt.utils.platform.is_windows() and runas:
|
||||
_cleanup_tempfile(path)
|
||||
# If a temp working directory was created (Windows), let's remove that
|
||||
if win_cwd:
|
||||
_cleanup_tempfile(cwd)
|
||||
else:
|
||||
_cleanup_tempfile(path)
|
||||
return {'pid': 0,
|
||||
'retcode': 1,
|
||||
'stdout': '',
|
||||
@ -2481,10 +2486,10 @@ def script(source,
|
||||
password=password,
|
||||
success_retcodes=success_retcodes,
|
||||
**kwargs)
|
||||
if salt.utils.platform.is_windows() and runas:
|
||||
_cleanup_tempfile(path)
|
||||
# If a temp working directory was created (Windows), let's remove that
|
||||
if win_cwd:
|
||||
_cleanup_tempfile(cwd)
|
||||
else:
|
||||
_cleanup_tempfile(path)
|
||||
|
||||
if hide_output:
|
||||
ret['stdout'] = ret['stderr'] = ''
|
||||
|
@ -867,7 +867,7 @@ def _network_conf(conf_tuples=None, **kwargs):
|
||||
# on old versions of lxc, still support the gateway auto mode
|
||||
# if we didn't explicitly say no to
|
||||
# (lxc.network.ipv4.gateway: auto)
|
||||
if _LooseVersion(version()) <= '1.0.7' and \
|
||||
if _LooseVersion(version()) <= _LooseVersion('1.0.7') and \
|
||||
True not in ['lxc.network.ipv4.gateway' in a for a in ret] and \
|
||||
True in ['lxc.network.ipv4' in a for a in ret]:
|
||||
ret.append({'lxc.network.ipv4.gateway': 'auto'})
|
||||
@ -2077,7 +2077,7 @@ def clone(name,
|
||||
if backing in ('dir', 'overlayfs', 'btrfs'):
|
||||
size = None
|
||||
# LXC commands and options changed in 2.0 - CF issue #34086 for details
|
||||
if version() >= _LooseVersion('2.0'):
|
||||
if _LooseVersion(version()) >= _LooseVersion('2.0'):
|
||||
# https://linuxcontainers.org/lxc/manpages//man1/lxc-copy.1.html
|
||||
cmd = 'lxc-copy'
|
||||
cmd += ' {0} -n {1} -N {2}'.format(snapshot, orig, name)
|
||||
|
@ -119,40 +119,82 @@ def __virtual__():
|
||||
return 'pip'
|
||||
|
||||
|
||||
def _clear_context(bin_env=None):
|
||||
'''
|
||||
Remove the cached pip version
|
||||
'''
|
||||
contextkey = 'pip.version'
|
||||
if bin_env is not None:
|
||||
contextkey = '{0}.{1}'.format(contextkey, bin_env)
|
||||
__context__.pop(contextkey, None)
|
||||
|
||||
|
||||
def _get_pip_bin(bin_env):
|
||||
'''
|
||||
Locate the pip binary, either from `bin_env` as a virtualenv, as the
|
||||
executable itself, or from searching conventional filesystem locations
|
||||
'''
|
||||
if not bin_env:
|
||||
which_result = __salt__['cmd.which_bin'](
|
||||
['pip{0}.{1}'.format(*sys.version_info[:2]),
|
||||
'pip{0}'.format(sys.version_info[0]),
|
||||
'pip', 'pip-python']
|
||||
)
|
||||
if salt.utils.platform.is_windows() and six.PY2 \
|
||||
and isinstance(which_result, str):
|
||||
which_result.encode('string-escape')
|
||||
if which_result is None:
|
||||
raise CommandNotFoundError('Could not find a `pip` binary')
|
||||
return which_result
|
||||
logger.debug('pip: Using pip from currently-running Python')
|
||||
return [os.path.normpath(sys.executable), '-m', 'pip']
|
||||
|
||||
# try to get pip bin from virtualenv, bin_env
|
||||
python_bin = 'python.exe' if salt.utils.platform.is_windows() else 'python'
|
||||
|
||||
def _search_paths(*basedirs):
|
||||
ret = []
|
||||
for path in basedirs:
|
||||
ret.extend([
|
||||
os.path.join(path, python_bin),
|
||||
os.path.join(path, 'bin', python_bin),
|
||||
os.path.join(path, 'Scripts', python_bin)
|
||||
])
|
||||
return ret
|
||||
|
||||
# try to get python bin from virtualenv (i.e. bin_env)
|
||||
if os.path.isdir(bin_env):
|
||||
if salt.utils.platform.is_windows():
|
||||
pip_bin = os.path.join(bin_env, 'Scripts', 'pip.exe')
|
||||
else:
|
||||
pip_bin = os.path.join(bin_env, 'bin', 'pip')
|
||||
if os.path.isfile(pip_bin):
|
||||
return pip_bin
|
||||
msg = 'Could not find a `pip` binary in virtualenv {0}'.format(bin_env)
|
||||
raise CommandNotFoundError(msg)
|
||||
# bin_env is the pip binary
|
||||
for bin_path in _search_paths(bin_env):
|
||||
if os.path.isfile(bin_path):
|
||||
if os.access(bin_path, os.X_OK):
|
||||
logger.debug('pip: Found python binary: %s', bin_path)
|
||||
return [os.path.normpath(bin_path), '-m', 'pip']
|
||||
else:
|
||||
logger.debug(
|
||||
'pip: Found python binary by name but it is not '
|
||||
'executable: %s', bin_path
|
||||
)
|
||||
raise CommandNotFoundError(
|
||||
'Could not find a pip binary in virtualenv {0}'.format(bin_env)
|
||||
)
|
||||
|
||||
# bin_env is the python or pip binary
|
||||
elif os.access(bin_env, os.X_OK):
|
||||
if os.path.isfile(bin_env) or os.path.islink(bin_env):
|
||||
return bin_env
|
||||
if os.path.isfile(bin_env):
|
||||
# If the python binary was passed, return it
|
||||
if 'python' in os.path.basename(bin_env):
|
||||
return [os.path.normpath(bin_env), '-m', 'pip']
|
||||
# Try to find the python binary based on the location of pip in a
|
||||
# virtual environment, should be relative
|
||||
if 'pip' in os.path.basename(bin_env):
|
||||
# Look in the same directory as the pip binary, and also its
|
||||
# parent directories.
|
||||
pip_dirname = os.path.dirname(bin_env)
|
||||
pip_parent_dir = os.path.dirname(pip_dirname)
|
||||
for bin_path in _search_paths(pip_dirname, pip_parent_dir):
|
||||
if os.path.isfile(bin_path):
|
||||
logger.debug('pip: Found python binary: %s', bin_path)
|
||||
return [os.path.normpath(bin_path), '-m', 'pip']
|
||||
|
||||
# Couldn't find python, use the passed pip binary
|
||||
# This has the limitation of being unable to update pip itself
|
||||
return [os.path.normpath(bin_env)]
|
||||
|
||||
raise CommandExecutionError(
|
||||
'Could not find a pip binary within {0}'.format(bin_env)
|
||||
)
|
||||
else:
|
||||
raise CommandNotFoundError('Could not find a `pip` binary')
|
||||
raise CommandNotFoundError(
|
||||
'Access denied to {0}, could not find a pip binary'.format(bin_env)
|
||||
)
|
||||
|
||||
|
||||
def _get_cached_requirements(requirements, saltenv):
|
||||
@ -271,15 +313,21 @@ def _process_requirements(requirements, cmd, cwd, saltenv, user):
|
||||
treq = tempfile.mkdtemp()
|
||||
|
||||
__salt__['file.chown'](treq, user, None)
|
||||
# In Windows, just being owner of a file isn't enough. You also
|
||||
# need permissions
|
||||
if salt.utils.platform.is_windows():
|
||||
__utils__['win_dacl.set_permissions'](
|
||||
obj_name=treq,
|
||||
principal=user,
|
||||
permissions='read_execute')
|
||||
|
||||
current_directory = None
|
||||
|
||||
if not current_directory:
|
||||
current_directory = os.path.abspath(os.curdir)
|
||||
|
||||
logger.info('_process_requirements from directory,' +
|
||||
'%s -- requirement: %s', cwd, requirement
|
||||
)
|
||||
logger.info('_process_requirements from directory, '
|
||||
'%s -- requirement: %s', cwd, requirement)
|
||||
|
||||
if cwd is None:
|
||||
r = requirement
|
||||
@ -384,7 +432,6 @@ def install(pkgs=None, # pylint: disable=R0912,R0913,R0914
|
||||
global_options=None,
|
||||
install_options=None,
|
||||
user=None,
|
||||
no_chown=False,
|
||||
cwd=None,
|
||||
pre_releases=False,
|
||||
cert=None,
|
||||
@ -398,7 +445,8 @@ def install(pkgs=None, # pylint: disable=R0912,R0913,R0914
|
||||
trusted_host=None,
|
||||
no_cache_dir=False,
|
||||
cache_dir=None,
|
||||
no_binary=None):
|
||||
no_binary=None,
|
||||
**kwargs):
|
||||
'''
|
||||
Install packages with pip
|
||||
|
||||
@ -520,10 +568,6 @@ def install(pkgs=None, # pylint: disable=R0912,R0913,R0914
|
||||
user
|
||||
The user under which to run pip
|
||||
|
||||
no_chown
|
||||
When user is given, do not attempt to copy and chown a requirements
|
||||
file
|
||||
|
||||
cwd
|
||||
Current working directory to run pip from
|
||||
|
||||
@ -584,9 +628,14 @@ def install(pkgs=None, # pylint: disable=R0912,R0913,R0914
|
||||
editable=git+https://github.com/worldcompany/djangoembed.git#egg=djangoembed upgrade=True no_deps=True
|
||||
|
||||
'''
|
||||
pip_bin = _get_pip_bin(bin_env)
|
||||
|
||||
cmd = [pip_bin, 'install']
|
||||
if 'no_chown' in kwargs:
|
||||
salt.utils.versions.warn_until(
|
||||
'Flourine',
|
||||
'The no_chown argument has been deprecated and is no longer used. '
|
||||
'Its functionality was removed in Boron.')
|
||||
kwargs.pop('no_chown')
|
||||
cmd = _get_pip_bin(bin_env)
|
||||
cmd.append('install')
|
||||
|
||||
cleanup_requirements, error = _process_requirements(
|
||||
requirements=requirements,
|
||||
@ -599,10 +648,11 @@ def install(pkgs=None, # pylint: disable=R0912,R0913,R0914
|
||||
if error:
|
||||
return error
|
||||
|
||||
cur_version = version(bin_env)
|
||||
|
||||
if use_wheel:
|
||||
min_version = '1.4'
|
||||
max_version = '9.0.3'
|
||||
cur_version = __salt__['pip.version'](bin_env)
|
||||
too_low = salt.utils.versions.compare(ver1=cur_version, oper='<', ver2=min_version)
|
||||
too_high = salt.utils.versions.compare(ver1=cur_version, oper='>', ver2=max_version)
|
||||
if too_low or too_high:
|
||||
@ -617,7 +667,6 @@ def install(pkgs=None, # pylint: disable=R0912,R0913,R0914
|
||||
if no_use_wheel:
|
||||
min_version = '1.4'
|
||||
max_version = '9.0.3'
|
||||
cur_version = __salt__['pip.version'](bin_env)
|
||||
too_low = salt.utils.versions.compare(ver1=cur_version, oper='<', ver2=min_version)
|
||||
too_high = salt.utils.versions.compare(ver1=cur_version, oper='>', ver2=max_version)
|
||||
if too_low or too_high:
|
||||
@ -631,7 +680,6 @@ def install(pkgs=None, # pylint: disable=R0912,R0913,R0914
|
||||
|
||||
if no_binary:
|
||||
min_version = '7.0.0'
|
||||
cur_version = __salt__['pip.version'](bin_env)
|
||||
too_low = salt.utils.versions.compare(ver1=cur_version, oper='<', ver2=min_version)
|
||||
if too_low:
|
||||
logger.error(
|
||||
@ -706,8 +754,7 @@ def install(pkgs=None, # pylint: disable=R0912,R0913,R0914
|
||||
|
||||
if mirrors:
|
||||
# https://github.com/pypa/pip/pull/2641/files#diff-3ef137fb9ffdd400f117a565cd94c188L216
|
||||
pip_version = version(pip_bin)
|
||||
if salt.utils.versions.compare(ver1=pip_version, oper='>=', ver2='7.0.0'):
|
||||
if salt.utils.versions.compare(ver1=cur_version, oper='>=', ver2='7.0.0'):
|
||||
raise CommandExecutionError(
|
||||
'pip >= 7.0.0 does not support mirror argument:'
|
||||
' use index_url and/or extra_index_url instead'
|
||||
@ -735,7 +782,7 @@ def install(pkgs=None, # pylint: disable=R0912,R0913,R0914
|
||||
|
||||
if download_cache or cache_dir:
|
||||
cmd.extend(['--cache-dir' if salt.utils.versions.compare(
|
||||
ver1=version(bin_env), oper='>=', ver2='6.0'
|
||||
ver1=cur_version, oper='>=', ver2='6.0'
|
||||
) else '--download-cache', download_cache or cache_dir])
|
||||
|
||||
if source:
|
||||
@ -772,7 +819,7 @@ def install(pkgs=None, # pylint: disable=R0912,R0913,R0914
|
||||
|
||||
if pre_releases:
|
||||
# Check the locally installed pip version
|
||||
pip_version = version(pip_bin)
|
||||
pip_version = cur_version
|
||||
|
||||
# From pip v1.4 the --pre flag is available
|
||||
if salt.utils.versions.compare(ver1=pip_version, oper='>=', ver2='1.4'):
|
||||
@ -857,6 +904,9 @@ def install(pkgs=None, # pylint: disable=R0912,R0913,R0914
|
||||
|
||||
cmd_kwargs = dict(saltenv=saltenv, use_vt=use_vt, runas=user)
|
||||
|
||||
if kwargs:
|
||||
cmd_kwargs.update(kwargs)
|
||||
|
||||
if env_vars:
|
||||
cmd_kwargs.setdefault('env', {}).update(_format_env_vars(env_vars))
|
||||
|
||||
@ -874,6 +924,7 @@ def install(pkgs=None, # pylint: disable=R0912,R0913,R0914
|
||||
|
||||
return __salt__['cmd.run_all'](cmd, python_shell=False, **cmd_kwargs)
|
||||
finally:
|
||||
_clear_context(bin_env)
|
||||
for tempdir in [cr for cr in cleanup_requirements if cr is not None]:
|
||||
if os.path.isdir(tempdir):
|
||||
shutil.rmtree(tempdir)
|
||||
@ -886,7 +937,6 @@ def uninstall(pkgs=None,
|
||||
proxy=None,
|
||||
timeout=None,
|
||||
user=None,
|
||||
no_chown=False,
|
||||
cwd=None,
|
||||
saltenv='base',
|
||||
use_vt=False):
|
||||
@ -919,11 +969,6 @@ def uninstall(pkgs=None,
|
||||
Set the socket timeout (default 15 seconds)
|
||||
user
|
||||
The user under which to run pip
|
||||
no_chown
|
||||
When user is given, do not attempt to copy and chown
|
||||
a requirements file (needed if the requirements file refers to other
|
||||
files via relative paths, as the copy-and-chown procedure does not
|
||||
account for such files)
|
||||
cwd
|
||||
Current working directory to run pip from
|
||||
use_vt
|
||||
@ -939,9 +984,8 @@ def uninstall(pkgs=None,
|
||||
salt '*' pip.uninstall <package name> bin_env=/path/to/pip_bin
|
||||
|
||||
'''
|
||||
pip_bin = _get_pip_bin(bin_env)
|
||||
|
||||
cmd = [pip_bin, 'uninstall', '-y']
|
||||
cmd = _get_pip_bin(bin_env)
|
||||
cmd.extend(['uninstall', '-y'])
|
||||
|
||||
cleanup_requirements, error = _process_requirements(
|
||||
requirements=requirements, cmd=cmd, saltenv=saltenv, user=user,
|
||||
@ -1001,6 +1045,7 @@ def uninstall(pkgs=None,
|
||||
try:
|
||||
return __salt__['cmd.run_all'](cmd, **cmd_kwargs)
|
||||
finally:
|
||||
_clear_context(bin_env)
|
||||
for requirement in cleanup_requirements:
|
||||
if requirement:
|
||||
try:
|
||||
@ -1013,7 +1058,8 @@ def freeze(bin_env=None,
|
||||
user=None,
|
||||
cwd=None,
|
||||
use_vt=False,
|
||||
env_vars=None):
|
||||
env_vars=None,
|
||||
**kwargs):
|
||||
'''
|
||||
Return a list of installed packages either globally or in the specified
|
||||
virtualenv
|
||||
@ -1046,15 +1092,13 @@ def freeze(bin_env=None,
|
||||
The packages pip, wheel, setuptools, and distribute are included if the
|
||||
installed pip is new enough.
|
||||
'''
|
||||
pip_bin = _get_pip_bin(bin_env)
|
||||
|
||||
cmd = [pip_bin, 'freeze']
|
||||
cmd = _get_pip_bin(bin_env)
|
||||
cmd.append('freeze')
|
||||
|
||||
# Include pip, setuptools, distribute, wheel
|
||||
min_version = '8.0.3'
|
||||
cur_version = version(bin_env)
|
||||
if not salt.utils.versions.compare(ver1=cur_version, oper='>=',
|
||||
ver2=min_version):
|
||||
if salt.utils.versions.compare(ver1=cur_version, oper='<', ver2=min_version):
|
||||
logger.warning(
|
||||
'The version of pip installed is %s, which is older than %s. '
|
||||
'The packages pip, wheel, setuptools, and distribute will not be '
|
||||
@ -1064,14 +1108,16 @@ def freeze(bin_env=None,
|
||||
cmd.append('--all')
|
||||
|
||||
cmd_kwargs = dict(runas=user, cwd=cwd, use_vt=use_vt, python_shell=False)
|
||||
if kwargs:
|
||||
cmd_kwargs.update(**kwargs)
|
||||
if bin_env and os.path.isdir(bin_env):
|
||||
cmd_kwargs['env'] = {'VIRTUAL_ENV': bin_env}
|
||||
if env_vars:
|
||||
cmd_kwargs.setdefault('env', {}).update(_format_env_vars(env_vars))
|
||||
result = __salt__['cmd.run_all'](cmd, **cmd_kwargs)
|
||||
|
||||
if result['retcode'] > 0:
|
||||
raise CommandExecutionError(result['stderr'])
|
||||
if result['retcode']:
|
||||
raise CommandExecutionError(result['stderr'], info=result)
|
||||
|
||||
return result['stdout'].splitlines()
|
||||
|
||||
@ -1080,7 +1126,8 @@ def list_(prefix=None,
|
||||
bin_env=None,
|
||||
user=None,
|
||||
cwd=None,
|
||||
env_vars=None):
|
||||
env_vars=None,
|
||||
**kwargs):
|
||||
'''
|
||||
Filter list of installed apps from ``freeze`` and check to see if
|
||||
``prefix`` exists in the list of packages installed.
|
||||
@ -1109,7 +1156,11 @@ def list_(prefix=None,
|
||||
if prefix is None or 'pip'.startswith(prefix):
|
||||
packages['pip'] = version(bin_env)
|
||||
|
||||
for line in freeze(bin_env=bin_env, user=user, cwd=cwd, env_vars=env_vars):
|
||||
for line in freeze(bin_env=bin_env,
|
||||
user=user,
|
||||
cwd=cwd,
|
||||
env_vars=env_vars,
|
||||
**kwargs):
|
||||
if line.startswith('-f') or line.startswith('#'):
|
||||
# ignore -f line as it contains --find-links directory
|
||||
# ignore comment lines
|
||||
@ -1119,7 +1170,15 @@ def list_(prefix=None,
|
||||
continue
|
||||
elif line.startswith('-e'):
|
||||
line = line.split('-e ')[1]
|
||||
version_, name = line.split('#egg=')
|
||||
if '#egg=' in line:
|
||||
version_, name = line.split('#egg=')
|
||||
else:
|
||||
if len(line.split('===')) >= 2:
|
||||
name = line.split('===')[0]
|
||||
version_ = line.split('===')[1]
|
||||
elif len(line.split('==')) >= 2:
|
||||
name = line.split('==')[0]
|
||||
version_ = line.split('==')[1]
|
||||
elif len(line.split('===')) >= 2:
|
||||
name = line.split('===')[0]
|
||||
version_ = line.split('===')[1]
|
||||
@ -1154,14 +1213,27 @@ def version(bin_env=None):
|
||||
|
||||
salt '*' pip.version
|
||||
'''
|
||||
pip_bin = _get_pip_bin(bin_env)
|
||||
contextkey = 'pip.version'
|
||||
if bin_env is not None:
|
||||
contextkey = '{0}.{1}'.format(contextkey, bin_env)
|
||||
|
||||
if contextkey in __context__:
|
||||
return __context__[contextkey]
|
||||
|
||||
cmd = _get_pip_bin(bin_env)[:]
|
||||
cmd.append('--version')
|
||||
|
||||
ret = __salt__['cmd.run_all'](cmd, python_shell=False)
|
||||
if ret['retcode']:
|
||||
raise CommandNotFoundError('Could not find a `pip` binary')
|
||||
|
||||
output = __salt__['cmd.run_stdout'](
|
||||
'{0} --version'.format(pip_bin), python_shell=False)
|
||||
try:
|
||||
return re.match(r'^pip (\S+)', output).group(1)
|
||||
pip_version = re.match(r'^pip (\S+)', ret['stdout']).group(1)
|
||||
except AttributeError:
|
||||
return None
|
||||
pip_version = None
|
||||
|
||||
__context__[contextkey] = pip_version
|
||||
return pip_version
|
||||
|
||||
|
||||
def list_upgrades(bin_env=None,
|
||||
@ -1176,15 +1248,15 @@ def list_upgrades(bin_env=None,
|
||||
|
||||
salt '*' pip.list_upgrades
|
||||
'''
|
||||
pip_bin = _get_pip_bin(bin_env)
|
||||
cmd = _get_pip_bin(bin_env)
|
||||
cmd.extend(['list', '--outdated'])
|
||||
|
||||
cmd = [pip_bin, 'list', '--outdated']
|
||||
|
||||
# If pip >= 9.0 use --format=json
|
||||
pip_version = version(bin_env)
|
||||
# Pip started supporting the ability to output json starting with 9.0.0
|
||||
min_version = '9.0'
|
||||
cur_version = version(pip_bin)
|
||||
if salt.utils.versions.compare(ver1=cur_version, oper='>=',
|
||||
ver2=min_version):
|
||||
if salt.utils.versions.compare(ver1=pip_version,
|
||||
oper='>=',
|
||||
ver2=min_version):
|
||||
cmd.append('--format=json')
|
||||
|
||||
cmd_kwargs = dict(cwd=cwd, runas=user)
|
||||
@ -1192,54 +1264,78 @@ def list_upgrades(bin_env=None,
|
||||
cmd_kwargs['env'] = {'VIRTUAL_ENV': bin_env}
|
||||
|
||||
result = __salt__['cmd.run_all'](cmd, **cmd_kwargs)
|
||||
if result['retcode'] > 0:
|
||||
logger.error(result['stderr'])
|
||||
raise CommandExecutionError(result['stderr'])
|
||||
if result['retcode']:
|
||||
raise CommandExecutionError(result['stderr'], info=result)
|
||||
|
||||
packages = {}
|
||||
try:
|
||||
json_results = salt.utils.json.loads(result['stdout'])
|
||||
for json_result in json_results:
|
||||
packages[json_result['name']] = json_result['latest_version']
|
||||
except ValueError:
|
||||
# Pip started supporting the ability to output json starting with 9.0.0
|
||||
# Older versions will have to parse stdout
|
||||
if salt.utils.versions.compare(ver1=pip_version, oper='<', ver2='9.0.0'):
|
||||
# Pip versions < 8.0.0 had a different output format
|
||||
# Sample data:
|
||||
# pip (Current: 7.1.2 Latest: 10.0.1 [wheel])
|
||||
# psutil (Current: 5.2.2 Latest: 5.4.5 [wheel])
|
||||
# pyasn1 (Current: 0.2.3 Latest: 0.4.2 [wheel])
|
||||
# pycparser (Current: 2.17 Latest: 2.18 [sdist])
|
||||
if salt.utils.versions.compare(ver1=pip_version, oper='<', ver2='8.0.0'):
|
||||
logger.debug('pip module: Old output format')
|
||||
pat = re.compile(r'(\S*)\s+\(.*Latest:\s+(.*)\)')
|
||||
|
||||
# New output format for version 8.0.0+
|
||||
# Sample data:
|
||||
# pip (8.0.0) - Latest: 10.0.1 [wheel]
|
||||
# psutil (5.2.2) - Latest: 5.4.5 [wheel]
|
||||
# pyasn1 (0.2.3) - Latest: 0.4.2 [wheel]
|
||||
# pycparser (2.17) - Latest: 2.18 [sdist]
|
||||
else:
|
||||
logger.debug('pip module: New output format')
|
||||
pat = re.compile(r'(\S*)\s+\(.*\)\s+-\s+Latest:\s+(.*)')
|
||||
|
||||
for line in result['stdout'].splitlines():
|
||||
match = re.search(r'(\S*)\s+.*Latest:\s+(.*)', line)
|
||||
match = pat.search(line)
|
||||
if match:
|
||||
name, version_ = match.groups()
|
||||
else:
|
||||
logger.error('Can\'t parse line \'%s\'', line)
|
||||
logger.error('Can\'t parse line \'{0}\''.format(line))
|
||||
continue
|
||||
packages[name] = version_
|
||||
|
||||
else:
|
||||
logger.debug('pip module: JSON output format')
|
||||
try:
|
||||
pkgs = salt.utils.json.loads(result['stdout'], strict=False)
|
||||
except ValueError:
|
||||
raise CommandExecutionError('Invalid JSON', info=result)
|
||||
|
||||
for pkg in pkgs:
|
||||
packages[pkg['name']] = '{0} [{1}]'.format(pkg['latest_version'],
|
||||
pkg['latest_filetype'])
|
||||
|
||||
return packages
|
||||
|
||||
|
||||
def is_installed(pkgname=None,
|
||||
bin_env=None,
|
||||
user=None,
|
||||
cwd=None):
|
||||
bin_env=None,
|
||||
user=None,
|
||||
cwd=None):
|
||||
'''
|
||||
.. versionadded:: 2018.3.0
|
||||
|
||||
Filter list of installed apps from ``freeze`` and return True or False if
|
||||
``pkgname`` exists in the list of packages installed.
|
||||
|
||||
.. note::
|
||||
|
||||
If the version of pip available is older than 8.0.3, the packages
|
||||
wheel, setuptools, and distribute will not be reported by this function
|
||||
even if they are installed. Unlike
|
||||
:py:func:`pip.freeze <salt.modules.pip.freeze>`, this function always
|
||||
reports the version of pip which is installed.
|
||||
even if they are installed. Unlike :py:func:`pip.freeze
|
||||
<salt.modules.pip.freeze>`, this function always reports the version of
|
||||
pip which is installed.
|
||||
|
||||
CLI Example:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
salt '*' pip.is_installed salt
|
||||
|
||||
.. versionadded:: 2018.3.0
|
||||
|
||||
The packages wheel, setuptools, and distribute are included if the
|
||||
installed pip is new enough.
|
||||
'''
|
||||
for line in freeze(bin_env=bin_env, user=user, cwd=cwd):
|
||||
if line.startswith('-f') or line.startswith('#'):
|
||||
@ -1294,7 +1390,11 @@ def upgrade(bin_env=None,
|
||||
'''
|
||||
.. versionadded:: 2015.5.0
|
||||
|
||||
Upgrades outdated pip packages
|
||||
Upgrades outdated pip packages.
|
||||
|
||||
.. note::
|
||||
On Windows you can't update salt from pip using salt, so salt will be
|
||||
skipped
|
||||
|
||||
Returns a dict containing the changes.
|
||||
|
||||
@ -1312,16 +1412,19 @@ def upgrade(bin_env=None,
|
||||
'result': True,
|
||||
'comment': '',
|
||||
}
|
||||
pip_bin = _get_pip_bin(bin_env)
|
||||
cmd = _get_pip_bin(bin_env)
|
||||
cmd.extend(['install', '-U'])
|
||||
|
||||
old = list_(bin_env=bin_env, user=user, cwd=cwd)
|
||||
|
||||
cmd = [pip_bin, 'install', '-U']
|
||||
cmd_kwargs = dict(cwd=cwd, use_vt=use_vt)
|
||||
if bin_env and os.path.isdir(bin_env):
|
||||
cmd_kwargs['env'] = {'VIRTUAL_ENV': bin_env}
|
||||
errors = False
|
||||
for pkg in list_upgrades(bin_env=bin_env, user=user, cwd=cwd):
|
||||
if pkg == 'salt':
|
||||
if salt.utils.platform.is_windows():
|
||||
continue
|
||||
result = __salt__['cmd.run_all'](cmd + [pkg], **cmd_kwargs)
|
||||
if result['retcode'] != 0:
|
||||
errors = True
|
||||
@ -1330,6 +1433,7 @@ def upgrade(bin_env=None,
|
||||
if errors:
|
||||
ret['result'] = False
|
||||
|
||||
_clear_context(bin_env)
|
||||
new = list_(bin_env=bin_env, user=user, cwd=cwd)
|
||||
|
||||
ret['changes'] = salt.utils.data.compare_dicts(old, new)
|
||||
@ -1383,9 +1487,8 @@ def list_all_versions(pkg,
|
||||
|
||||
salt '*' pip.list_all_versions <package name>
|
||||
'''
|
||||
pip_bin = _get_pip_bin(bin_env)
|
||||
|
||||
cmd = [pip_bin, 'install', '{0}==versions'.format(pkg)]
|
||||
cmd = _get_pip_bin(bin_env)
|
||||
cmd.extend(['install', '{0}==versions'.format(pkg)])
|
||||
|
||||
if index_url:
|
||||
if not salt.utils.url.validate(index_url, VALID_PROTOS):
|
||||
|
@ -57,7 +57,8 @@ def create(path,
|
||||
upgrade=None,
|
||||
user=None,
|
||||
use_vt=False,
|
||||
saltenv='base'):
|
||||
saltenv='base',
|
||||
**kwargs):
|
||||
'''
|
||||
Create a virtualenv
|
||||
|
||||
@ -103,6 +104,11 @@ def create(path,
|
||||
user : None
|
||||
Set ownership for the virtualenv
|
||||
|
||||
.. note::
|
||||
On Windows you must also pass a ``password`` parameter. Additionally,
|
||||
the user must have permissions to the location where the virtual
|
||||
environment is being created
|
||||
|
||||
runas : None
|
||||
Set ownership for the virtualenv
|
||||
|
||||
@ -162,7 +168,7 @@ def create(path,
|
||||
# Unable to import?? Let's parse the version from the console
|
||||
version_cmd = [venv_bin, '--version']
|
||||
ret = __salt__['cmd.run_all'](
|
||||
version_cmd, runas=user, python_shell=False
|
||||
version_cmd, runas=user, python_shell=False, **kwargs
|
||||
)
|
||||
if ret['retcode'] > 0 or not ret['stdout'].strip():
|
||||
raise CommandExecutionError(
|
||||
@ -252,7 +258,7 @@ def create(path,
|
||||
cmd.append(path)
|
||||
|
||||
# Let's create the virtualenv
|
||||
ret = __salt__['cmd.run_all'](cmd, runas=user, python_shell=False)
|
||||
ret = __salt__['cmd.run_all'](cmd, runas=user, python_shell=False, **kwargs)
|
||||
if ret['retcode'] != 0:
|
||||
# Something went wrong. Let's bail out now!
|
||||
return ret
|
||||
|
@ -719,23 +719,24 @@ def set_lcm_config(config_mode=None,
|
||||
'ApplyAndAutoCorrect'):
|
||||
error = 'config_mode must be one of ApplyOnly, ApplyAndMonitor, ' \
|
||||
'or ApplyAndAutoCorrect. Passed {0}'.format(config_mode)
|
||||
SaltInvocationError(error)
|
||||
return error
|
||||
raise SaltInvocationError(error)
|
||||
cmd += ' ConfigurationMode = "{0}";'.format(config_mode)
|
||||
if config_mode_freq:
|
||||
if not isinstance(config_mode_freq, int):
|
||||
SaltInvocationError('config_mode_freq must be an integer')
|
||||
return 'config_mode_freq must be an integer. Passed {0}'.\
|
||||
format(config_mode_freq)
|
||||
error = 'config_mode_freq must be an integer. Passed {0}'.format(
|
||||
config_mode_freq
|
||||
)
|
||||
raise SaltInvocationError(error)
|
||||
cmd += ' ConfigurationModeFrequencyMins = {0};'.format(config_mode_freq)
|
||||
if refresh_mode:
|
||||
if refresh_mode not in ('Disabled', 'Push', 'Pull'):
|
||||
SaltInvocationError('refresh_mode must be one of Disabled, Push, '
|
||||
'or Pull')
|
||||
raise SaltInvocationError(
|
||||
'refresh_mode must be one of Disabled, Push, or Pull'
|
||||
)
|
||||
cmd += ' RefreshMode = "{0}";'.format(refresh_mode)
|
||||
if refresh_freq:
|
||||
if not isinstance(refresh_freq, int):
|
||||
SaltInvocationError('refresh_freq must be an integer')
|
||||
raise SaltInvocationError('refresh_freq must be an integer')
|
||||
cmd += ' RefreshFrequencyMins = {0};'.format(refresh_freq)
|
||||
if reboot_if_needed is not None:
|
||||
if not isinstance(reboot_if_needed, bool):
|
||||
@ -748,8 +749,10 @@ def set_lcm_config(config_mode=None,
|
||||
if action_after_reboot:
|
||||
if action_after_reboot not in ('ContinueConfiguration',
|
||||
'StopConfiguration'):
|
||||
SaltInvocationError('action_after_reboot must be one of '
|
||||
'ContinueConfiguration or StopConfiguration')
|
||||
raise SaltInvocationError(
|
||||
'action_after_reboot must be one of '
|
||||
'ContinueConfiguration or StopConfiguration'
|
||||
)
|
||||
cmd += ' ActionAfterReboot = "{0}"'.format(action_after_reboot)
|
||||
if certificate_id is not None:
|
||||
if certificate_id == '':
|
||||
@ -761,7 +764,7 @@ def set_lcm_config(config_mode=None,
|
||||
cmd += ' ConfigurationID = "{0}";'.format(configuration_id)
|
||||
if allow_module_overwrite is not None:
|
||||
if not isinstance(allow_module_overwrite, bool):
|
||||
SaltInvocationError('allow_module_overwrite must be a boolean value')
|
||||
raise SaltInvocationError('allow_module_overwrite must be a boolean value')
|
||||
if allow_module_overwrite:
|
||||
allow_module_overwrite = '$true'
|
||||
else:
|
||||
@ -771,13 +774,14 @@ def set_lcm_config(config_mode=None,
|
||||
if debug_mode is None:
|
||||
debug_mode = 'None'
|
||||
if debug_mode not in ('None', 'ForceModuleImport', 'All'):
|
||||
SaltInvocationError('debug_mode must be one of None, '
|
||||
'ForceModuleImport, ResourceScriptBreakAll, or '
|
||||
'All')
|
||||
raise SaltInvocationError(
|
||||
'debug_mode must be one of None, ForceModuleImport, '
|
||||
'ResourceScriptBreakAll, or All'
|
||||
)
|
||||
cmd += ' DebugMode = "{0}";'.format(debug_mode)
|
||||
if status_retention_days:
|
||||
if not isinstance(status_retention_days, int):
|
||||
SaltInvocationError('status_retention_days must be an integer')
|
||||
raise SaltInvocationError('status_retention_days must be an integer')
|
||||
cmd += ' StatusRetentionTimeInDays = {0};'.format(status_retention_days)
|
||||
cmd += ' }}};'
|
||||
cmd += r'SaltConfig -OutputPath "{0}\SaltConfig"'.format(temp_dir)
|
||||
|
@ -4364,7 +4364,7 @@ def _checkAllAdmxPolicies(policy_class,
|
||||
if ENABLED_VALUE_XPATH(admx_policy) and this_policy_setting == 'Not Configured':
|
||||
# some policies have a disabled list but not an enabled list
|
||||
# added this to address those issues
|
||||
if DISABLED_LIST_XPATH(admx_policy):
|
||||
if DISABLED_LIST_XPATH(admx_policy) or DISABLED_VALUE_XPATH(admx_policy):
|
||||
element_only_enabled_disabled = False
|
||||
explicit_enable_disable_value_setting = True
|
||||
if _checkValueItemParent(admx_policy,
|
||||
@ -4374,14 +4374,14 @@ def _checkAllAdmxPolicies(policy_class,
|
||||
ENABLED_VALUE_XPATH,
|
||||
policy_filedata):
|
||||
this_policy_setting = 'Enabled'
|
||||
log.debug('%s is enabled', this_policyname)
|
||||
log.debug('%s is enabled by detected ENABLED_VALUE_XPATH', this_policyname)
|
||||
if this_policynamespace not in policy_vals:
|
||||
policy_vals[this_policynamespace] = {}
|
||||
policy_vals[this_policynamespace][this_policyname] = this_policy_setting
|
||||
if DISABLED_VALUE_XPATH(admx_policy) and this_policy_setting == 'Not Configured':
|
||||
# some policies have a disabled list but not an enabled list
|
||||
# added this to address those issues
|
||||
if ENABLED_LIST_XPATH(admx_policy):
|
||||
if ENABLED_LIST_XPATH(admx_policy) or ENABLED_VALUE_XPATH(admx_policy):
|
||||
element_only_enabled_disabled = False
|
||||
explicit_enable_disable_value_setting = True
|
||||
if _checkValueItemParent(admx_policy,
|
||||
@ -4391,25 +4391,27 @@ def _checkAllAdmxPolicies(policy_class,
|
||||
DISABLED_VALUE_XPATH,
|
||||
policy_filedata):
|
||||
this_policy_setting = 'Disabled'
|
||||
log.debug('%s is disabled', this_policyname)
|
||||
log.debug('%s is disabled by detected DISABLED_VALUE_XPATH', this_policyname)
|
||||
if this_policynamespace not in policy_vals:
|
||||
policy_vals[this_policynamespace] = {}
|
||||
policy_vals[this_policynamespace][this_policyname] = this_policy_setting
|
||||
if ENABLED_LIST_XPATH(admx_policy) and this_policy_setting == 'Not Configured':
|
||||
element_only_enabled_disabled = False
|
||||
explicit_enable_disable_value_setting = True
|
||||
if DISABLED_LIST_XPATH(admx_policy) or DISABLED_VALUE_XPATH(admx_policy):
|
||||
element_only_enabled_disabled = False
|
||||
explicit_enable_disable_value_setting = True
|
||||
if _checkListItem(admx_policy, this_policyname, this_key, ENABLED_LIST_XPATH, policy_filedata):
|
||||
this_policy_setting = 'Enabled'
|
||||
log.debug('%s is enabled', this_policyname)
|
||||
log.debug('%s is enabled by detected ENABLED_LIST_XPATH', this_policyname)
|
||||
if this_policynamespace not in policy_vals:
|
||||
policy_vals[this_policynamespace] = {}
|
||||
policy_vals[this_policynamespace][this_policyname] = this_policy_setting
|
||||
if DISABLED_LIST_XPATH(admx_policy) and this_policy_setting == 'Not Configured':
|
||||
element_only_enabled_disabled = False
|
||||
explicit_enable_disable_value_setting = True
|
||||
if ENABLED_LIST_XPATH(admx_policy) or ENABLED_VALUE_XPATH(admx_policy):
|
||||
element_only_enabled_disabled = False
|
||||
explicit_enable_disable_value_setting = True
|
||||
if _checkListItem(admx_policy, this_policyname, this_key, DISABLED_LIST_XPATH, policy_filedata):
|
||||
this_policy_setting = 'Disabled'
|
||||
log.debug('%s is disabled', this_policyname)
|
||||
log.debug('%s is disabled by detected DISABLED_LIST_XPATH', this_policyname)
|
||||
if this_policynamespace not in policy_vals:
|
||||
policy_vals[this_policynamespace] = {}
|
||||
policy_vals[this_policynamespace][this_policyname] = this_policy_setting
|
||||
@ -4424,7 +4426,7 @@ def _checkAllAdmxPolicies(policy_class,
|
||||
'1')),
|
||||
policy_filedata):
|
||||
this_policy_setting = 'Enabled'
|
||||
log.debug('%s is enabled', this_policyname)
|
||||
log.debug('%s is enabled by no explicit enable/disable list or value', this_policyname)
|
||||
if this_policynamespace not in policy_vals:
|
||||
policy_vals[this_policynamespace] = {}
|
||||
policy_vals[this_policynamespace][this_policyname] = this_policy_setting
|
||||
@ -4435,7 +4437,7 @@ def _checkAllAdmxPolicies(policy_class,
|
||||
check_deleted=True)),
|
||||
policy_filedata):
|
||||
this_policy_setting = 'Disabled'
|
||||
log.debug('%s is disabled', this_policyname)
|
||||
log.debug('%s is disabled by no explicit enable/disable list or value', this_policyname)
|
||||
if this_policynamespace not in policy_vals:
|
||||
policy_vals[this_policynamespace] = {}
|
||||
policy_vals[this_policynamespace][this_policyname] = this_policy_setting
|
||||
|
@ -15,7 +15,7 @@ Support for Zabbix
|
||||
|
||||
|
||||
Connection arguments from the minion config file can be overridden on the CLI by using arguments with
|
||||
_connection_ prefix.
|
||||
``_connection_`` prefix.
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
@ -23,26 +23,24 @@ Support for Zabbix
|
||||
|
||||
:codeauthor: Jiri Kotlin <jiri.kotlin@ultimum.io>
|
||||
'''
|
||||
from __future__ import absolute_import
|
||||
from __future__ import print_function
|
||||
from __future__ import unicode_literals
|
||||
from __future__ import absolute_import, print_function, unicode_literals
|
||||
|
||||
# Import python libs
|
||||
# Import Python libs
|
||||
import logging
|
||||
import socket
|
||||
import os
|
||||
|
||||
# Import salt libs
|
||||
try:
|
||||
import salt.utils
|
||||
from salt.ext import six
|
||||
from salt.utils.versions import LooseVersion as _LooseVersion
|
||||
# pylint: disable=import-error,no-name-in-module,unused-import
|
||||
from salt.ext.six.moves.urllib.error import HTTPError, URLError
|
||||
from salt.exceptions import SaltException
|
||||
IMPORTS_OK = True
|
||||
except ImportError:
|
||||
IMPORTS_OK = False
|
||||
# Import Salt libs
|
||||
from salt.ext import six
|
||||
from salt.exceptions import SaltException
|
||||
import salt.utils.data
|
||||
import salt.utils.files
|
||||
import salt.utils.http
|
||||
import salt.utils.json
|
||||
from salt.utils.versions import LooseVersion as _LooseVersion
|
||||
# pylint: disable=import-error,no-name-in-module,unused-import
|
||||
from salt.ext.six.moves.urllib.error import HTTPError, URLError
|
||||
# pylint: enable=import-error,no-name-in-module,unused-import
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
@ -104,9 +102,7 @@ def __virtual__():
|
||||
'''
|
||||
Only load the module if all modules are imported correctly.
|
||||
'''
|
||||
if IMPORTS_OK:
|
||||
return __virtualname__
|
||||
return False, 'Importing modules failed.'
|
||||
return __virtualname__
|
||||
|
||||
|
||||
def _frontend_url():
|
||||
@ -349,7 +345,7 @@ def compare_params(defined, existing, return_old_value=False):
|
||||
defined))
|
||||
|
||||
# Comparison of values
|
||||
if not salt.utils.is_iter(defined):
|
||||
if not salt.utils.data.is_iter(defined):
|
||||
if six.text_type(defined) != six.text_type(existing) and return_old_value:
|
||||
return {'new': six.text_type(defined), 'old': six.text_type(existing)}
|
||||
elif six.text_type(defined) != six.text_type(existing) and not return_old_value:
|
||||
@ -2390,7 +2386,7 @@ def configuration_import(config_file, rules=None, file_format='xml', **connectio
|
||||
else:
|
||||
new_rules[rule] = rules[rule]
|
||||
if 'salt://' in config_file:
|
||||
tmpfile = salt.utils.mkstemp()
|
||||
tmpfile = salt.utils.files.mkstemp()
|
||||
cfile = __salt__['cp.get_file'](config_file, tmpfile)
|
||||
if not cfile or os.path.getsize(cfile) == 0:
|
||||
return {'name': config_file, 'result': False, 'message': 'Failed to fetch config file.'}
|
||||
@ -2399,11 +2395,11 @@ def configuration_import(config_file, rules=None, file_format='xml', **connectio
|
||||
if not os.path.isfile(cfile):
|
||||
return {'name': config_file, 'result': False, 'message': 'Invalid file path.'}
|
||||
|
||||
with salt.utils.fopen(cfile, mode='r') as fp_:
|
||||
with salt.utils.files.fopen(cfile, mode='r') as fp_:
|
||||
xml = fp_.read()
|
||||
|
||||
if 'salt://' in config_file:
|
||||
salt.utils.safe_rm(cfile)
|
||||
salt.utils.files.safe_rm(cfile)
|
||||
|
||||
params = {'format': file_format,
|
||||
'rules': new_rules,
|
||||
|
@ -261,7 +261,7 @@ different grain matches.
|
||||
That said, sometimes a minion may match more than one class. For instance,
|
||||
in the above example, Ubuntu minions will match both the **Debian** and
|
||||
**Ubuntu** classes, since Ubuntu has an ``os_family`` grain of **Debian**
|
||||
an an ``os`` grain of **Ubuntu**. As of the 2017.7.0 release, the order is
|
||||
and an ``os`` grain of **Ubuntu**. As of the 2017.7.0 release, the order is
|
||||
dictated by the order of declaration, with classes defined later overriding
|
||||
earlier ones. Additionally, 2017.7.0 adds support for explicitly defining
|
||||
the ordering using an optional attribute called ``priority``.
|
||||
|
@ -182,25 +182,28 @@ def _check_pkg_version_format(pkg):
|
||||
return ret
|
||||
|
||||
|
||||
def _check_if_installed(prefix, state_pkg_name, version_spec,
|
||||
ignore_installed, force_reinstall,
|
||||
upgrade, user, cwd, bin_env, env_vars,
|
||||
index_url):
|
||||
def _check_if_installed(prefix,
|
||||
state_pkg_name,
|
||||
version_spec,
|
||||
ignore_installed,
|
||||
force_reinstall,
|
||||
upgrade,
|
||||
user,
|
||||
cwd,
|
||||
bin_env,
|
||||
env_vars,
|
||||
index_url,
|
||||
**kwargs):
|
||||
# result: None means the command failed to run
|
||||
# result: True means the package is installed
|
||||
# result: False means the package is not installed
|
||||
ret = {'result': False, 'comment': None}
|
||||
|
||||
# Check if the requested package is already installed.
|
||||
try:
|
||||
pip_list = __salt__['pip.list'](prefix, bin_env=bin_env,
|
||||
user=user, cwd=cwd,
|
||||
env_vars=env_vars)
|
||||
prefix_realname = _find_key(prefix, pip_list)
|
||||
except (CommandNotFoundError, CommandExecutionError) as err:
|
||||
ret['result'] = None
|
||||
ret['comment'] = 'Error installing \'{0}\': {1}'.format(state_pkg_name, err)
|
||||
return ret
|
||||
pip_list = __salt__['pip.list'](prefix, bin_env=bin_env,
|
||||
user=user, cwd=cwd,
|
||||
env_vars=env_vars, **kwargs)
|
||||
prefix_realname = _find_key(prefix, pip_list)
|
||||
|
||||
# If the package was already installed, check
|
||||
# the ignore_installed and force_reinstall flags
|
||||
@ -313,7 +316,6 @@ def installed(name,
|
||||
install_options=None,
|
||||
global_options=None,
|
||||
user=None,
|
||||
no_chown=False,
|
||||
cwd=None,
|
||||
pre_releases=False,
|
||||
cert=None,
|
||||
@ -326,7 +328,8 @@ def installed(name,
|
||||
trusted_host=None,
|
||||
no_cache_dir=False,
|
||||
cache_dir=None,
|
||||
no_binary=None):
|
||||
no_binary=None,
|
||||
**kwargs):
|
||||
'''
|
||||
Make sure the package is installed
|
||||
|
||||
@ -448,10 +451,6 @@ def installed(name,
|
||||
no_install
|
||||
Download and unpack all packages, but don't actually install them
|
||||
|
||||
no_chown
|
||||
When user is given, do not attempt to copy and chown
|
||||
a requirements file
|
||||
|
||||
no_cache_dir:
|
||||
Disable the cache.
|
||||
|
||||
@ -594,6 +593,12 @@ def installed(name,
|
||||
|
||||
.. _`virtualenv`: http://www.virtualenv.org/en/latest/
|
||||
'''
|
||||
if 'no_chown' in kwargs:
|
||||
salt.utils.versions.warn_until(
|
||||
'Flourine',
|
||||
'The no_chown argument has been deprecated and is no longer used. '
|
||||
'Its functionality was removed in Boron.')
|
||||
kwargs.pop('no_chown')
|
||||
|
||||
if pip_bin and not bin_env:
|
||||
bin_env = pip_bin
|
||||
@ -619,11 +624,16 @@ def installed(name,
|
||||
ret = {'name': ';'.join(pkgs), 'result': None,
|
||||
'comment': '', 'changes': {}}
|
||||
|
||||
try:
|
||||
cur_version = __salt__['pip.version'](bin_env)
|
||||
except (CommandNotFoundError, CommandExecutionError) as err:
|
||||
ret['result'] = None
|
||||
ret['comment'] = 'Error installing \'{0}\': {1}'.format(name, err)
|
||||
return ret
|
||||
# Check that the pip binary supports the 'use_wheel' option
|
||||
if use_wheel:
|
||||
min_version = '1.4'
|
||||
max_version = '9.0.3'
|
||||
cur_version = __salt__['pip.version'](bin_env)
|
||||
too_low = salt.utils.versions.compare(ver1=cur_version, oper='<', ver2=min_version)
|
||||
too_high = salt.utils.versions.compare(ver1=cur_version, oper='>', ver2=max_version)
|
||||
if too_low or too_high:
|
||||
@ -637,7 +647,6 @@ def installed(name,
|
||||
if no_use_wheel:
|
||||
min_version = '1.4'
|
||||
max_version = '9.0.3'
|
||||
cur_version = __salt__['pip.version'](bin_env)
|
||||
too_low = salt.utils.versions.compare(ver1=cur_version, oper='<', ver2=min_version)
|
||||
too_high = salt.utils.versions.compare(ver1=cur_version, oper='>', ver2=max_version)
|
||||
if too_low or too_high:
|
||||
@ -650,7 +659,6 @@ def installed(name,
|
||||
# Check that the pip binary supports the 'no_binary' option
|
||||
if no_binary:
|
||||
min_version = '7.0.0'
|
||||
cur_version = __salt__['pip.version'](bin_env)
|
||||
too_low = salt.utils.versions.compare(ver1=cur_version, oper='<', ver2=min_version)
|
||||
if too_low:
|
||||
ret['result'] = False
|
||||
@ -724,7 +732,7 @@ def installed(name,
|
||||
out = _check_if_installed(prefix, state_pkg_name, version_spec,
|
||||
ignore_installed, force_reinstall,
|
||||
upgrade, user, cwd, bin_env, env_vars,
|
||||
index_url)
|
||||
index_url, **kwargs)
|
||||
# If _check_if_installed result is None, something went wrong with
|
||||
# the command running. This way we keep stateful output.
|
||||
if out['result'] is None:
|
||||
@ -804,7 +812,6 @@ def installed(name,
|
||||
install_options=install_options,
|
||||
global_options=global_options,
|
||||
user=user,
|
||||
no_chown=no_chown,
|
||||
cwd=cwd,
|
||||
pre_releases=pre_releases,
|
||||
cert=cert,
|
||||
@ -816,7 +823,8 @@ def installed(name,
|
||||
env_vars=env_vars,
|
||||
use_vt=use_vt,
|
||||
trusted_host=trusted_host,
|
||||
no_cache_dir=no_cache_dir
|
||||
no_cache_dir=no_cache_dir,
|
||||
**kwargs
|
||||
)
|
||||
|
||||
if pip_install_call and pip_install_call.get('retcode', 1) == 0:
|
||||
@ -872,7 +880,8 @@ def installed(name,
|
||||
if prefix:
|
||||
pipsearch = __salt__['pip.list'](prefix, bin_env,
|
||||
user=user, cwd=cwd,
|
||||
env_vars=env_vars)
|
||||
env_vars=env_vars,
|
||||
**kwargs)
|
||||
|
||||
# If we didn't find the package in the system after
|
||||
# installing it report it
|
||||
|
@ -42,7 +42,6 @@ def managed(name,
|
||||
never_download=None,
|
||||
prompt=None,
|
||||
user=None,
|
||||
no_chown=False,
|
||||
cwd=None,
|
||||
index_url=None,
|
||||
extra_index_url=None,
|
||||
@ -61,7 +60,8 @@ def managed(name,
|
||||
pip_no_cache_dir=False,
|
||||
pip_cache_dir=None,
|
||||
process_dependency_links=False,
|
||||
no_binary=None):
|
||||
no_binary=None,
|
||||
**kwargs):
|
||||
'''
|
||||
Create a virtualenv and optionally manage it with pip
|
||||
|
||||
@ -85,11 +85,6 @@ def managed(name,
|
||||
user: None
|
||||
The user under which to run virtualenv and pip.
|
||||
|
||||
no_chown: False
|
||||
When user is given, do not attempt to copy and chown a requirements file
|
||||
(needed if the requirements file refers to other files via relative
|
||||
paths, as the copy-and-chown procedure does not account for such files)
|
||||
|
||||
cwd: None
|
||||
Path to the working directory where `pip install` is executed.
|
||||
|
||||
@ -140,6 +135,13 @@ def managed(name,
|
||||
- env_vars:
|
||||
PATH_VAR: '/usr/local/bin/'
|
||||
'''
|
||||
if 'no_chown' in kwargs:
|
||||
salt.utils.versions.warn_until(
|
||||
'Flourine',
|
||||
'The no_chown argument has been deprecated and is no longer used. '
|
||||
'Its functionality was removed in Boron.')
|
||||
kwargs.pop('no_chown')
|
||||
|
||||
ret = {'name': name, 'result': True, 'comment': '', 'changes': {}}
|
||||
|
||||
if 'virtualenv.create' not in __salt__:
|
||||
@ -211,6 +213,7 @@ def managed(name,
|
||||
prompt=prompt,
|
||||
user=user,
|
||||
use_vt=use_vt,
|
||||
**kwargs
|
||||
)
|
||||
except CommandNotFoundError as err:
|
||||
ret['result'] = False
|
||||
@ -311,7 +314,6 @@ def managed(name,
|
||||
extra_index_url=extra_index_url,
|
||||
download=pip_download,
|
||||
download_cache=pip_download_cache,
|
||||
no_chown=no_chown,
|
||||
pre_releases=pre_releases,
|
||||
exists_action=pip_exists_action,
|
||||
ignore_installed=pip_ignore_installed,
|
||||
@ -321,7 +323,8 @@ def managed(name,
|
||||
use_vt=use_vt,
|
||||
env_vars=env_vars,
|
||||
no_cache_dir=pip_no_cache_dir,
|
||||
cache_dir=pip_cache_dir
|
||||
cache_dir=pip_cache_dir,
|
||||
**kwargs
|
||||
)
|
||||
ret['result'] &= pip_ret['retcode'] == 0
|
||||
if pip_ret['retcode'] > 0:
|
||||
|
@ -475,6 +475,8 @@ class CkMinions(object):
|
||||
minions = set(self._pki_minions())
|
||||
log.debug('minions: %s', minions)
|
||||
|
||||
nodegroups = self.opts.get('nodegroups', {})
|
||||
|
||||
if self.opts.get('minion_data_cache', False):
|
||||
ref = {'G': self._check_grain_minions,
|
||||
'P': self._check_grain_pcre_minions,
|
||||
@ -497,9 +499,11 @@ class CkMinions(object):
|
||||
if isinstance(expr, six.string_types):
|
||||
words = expr.split()
|
||||
else:
|
||||
words = expr
|
||||
# we make a shallow copy in order to not affect the passed in arg
|
||||
words = expr[:]
|
||||
|
||||
for word in words:
|
||||
while words:
|
||||
word = words.pop(0)
|
||||
target_info = parse_target(word)
|
||||
|
||||
# Easy check first
|
||||
@ -556,9 +560,12 @@ class CkMinions(object):
|
||||
|
||||
elif target_info and target_info['engine']:
|
||||
if 'N' == target_info['engine']:
|
||||
# Nodegroups should already be expanded/resolved to other engines
|
||||
log.error('Detected nodegroup expansion failure of "%s"', word)
|
||||
return {'minions': [], 'missing': []}
|
||||
# if we encounter a node group, just evaluate it in-place
|
||||
decomposed = nodegroup_comp(target_info['pattern'], nodegroups)
|
||||
if decomposed:
|
||||
words = decomposed + words
|
||||
continue
|
||||
|
||||
engine = ref.get(target_info['engine'])
|
||||
if not engine:
|
||||
# If an unknown engine is called at any time, fail out
|
||||
|
@ -361,23 +361,46 @@ def check_whitelist_blacklist(value, whitelist=None, blacklist=None):
|
||||
in the blacklist, then the whitelist is checked. If the value isn't
|
||||
found in the whitelist, the function returns ``False``.
|
||||
'''
|
||||
if blacklist is not None:
|
||||
if not isinstance(blacklist, list):
|
||||
# Normalize the input so that we have a list
|
||||
if blacklist:
|
||||
if isinstance(blacklist, six.string_types):
|
||||
blacklist = [blacklist]
|
||||
for expr in blacklist:
|
||||
if expr_match(value, expr):
|
||||
return False
|
||||
if not hasattr(blacklist, '__iter__'):
|
||||
raise TypeError(
|
||||
'Expecting iterable blacklist, but got {0} ({1})'.format(
|
||||
type(blacklist).__name__, blacklist
|
||||
)
|
||||
)
|
||||
else:
|
||||
blacklist = []
|
||||
|
||||
if whitelist:
|
||||
if not isinstance(whitelist, list):
|
||||
if isinstance(whitelist, six.string_types):
|
||||
whitelist = [whitelist]
|
||||
for expr in whitelist:
|
||||
if expr_match(value, expr):
|
||||
return True
|
||||
if not hasattr(whitelist, '__iter__'):
|
||||
raise TypeError(
|
||||
'Expecting iterable whitelist, but got {0} ({1})'.format(
|
||||
type(whitelist).__name__, whitelist
|
||||
)
|
||||
)
|
||||
else:
|
||||
return True
|
||||
whitelist = []
|
||||
|
||||
return False
|
||||
_blacklist_match = any(expr_match(value, expr) for expr in blacklist)
|
||||
_whitelist_match = any(expr_match(value, expr) for expr in whitelist)
|
||||
|
||||
if blacklist and not whitelist:
|
||||
# Blacklist but no whitelist
|
||||
return not _blacklist_match
|
||||
elif whitelist and not blacklist:
|
||||
# Whitelist but no blacklist
|
||||
return _whitelist_match
|
||||
elif blacklist and whitelist:
|
||||
# Both whitelist and blacklist
|
||||
return not _blacklist_match and _whitelist_match
|
||||
else:
|
||||
# No blacklist or whitelist passed
|
||||
return True
|
||||
|
||||
|
||||
def check_include_exclude(path_str, include_pat=None, exclude_pat=None):
|
||||
|
@ -279,7 +279,6 @@ def _command(source, command, flags=None, opts=None,
|
||||
return ' '.join(cmd)
|
||||
|
||||
|
||||
@real_memoize
|
||||
def is_supported():
|
||||
'''
|
||||
Check the system for ZFS support
|
||||
@ -302,7 +301,7 @@ def is_supported():
|
||||
on_supported_platform = True
|
||||
|
||||
# Additional check for the zpool command
|
||||
return (_zpool_cmd() and on_supported_platform) is True
|
||||
return (salt.utils.path.which('zpool') and on_supported_platform) is True
|
||||
|
||||
|
||||
@real_memoize
|
||||
|
@ -6,3 +6,5 @@
|
||||
{#- wheels are disabled because the pip cache dir will not be owned by the above issue-1959 user. Need to check this ASAP #}
|
||||
- no_binary: ':all:'
|
||||
{%- endif %}
|
||||
- env:
|
||||
XDG_CACHE_HOME: /tmp
|
||||
|
1
tests/integration/files/pillar/base/ng1.sls
Normal file
1
tests/integration/files/pillar/base/ng1.sls
Normal file
@ -0,0 +1 @@
|
||||
pillar_from_nodegroup: True
|
1
tests/integration/files/pillar/base/ng2.sls
Normal file
1
tests/integration/files/pillar/base/ng2.sls
Normal file
@ -0,0 +1 @@
|
||||
pillar_from_nodegroup_with_ghost: True
|
@ -9,3 +9,7 @@ base:
|
||||
'localhost':
|
||||
- generic
|
||||
- blackout
|
||||
'N@mins not L@minion':
|
||||
- ng1
|
||||
'N@missing_minion':
|
||||
- ng2
|
||||
|
@ -189,6 +189,29 @@ GPG_PILLAR_DECRYPTED = {
|
||||
}
|
||||
|
||||
|
||||
class BasePillarTest(ModuleCase):
|
||||
'''
|
||||
Tests for pillar decryption
|
||||
'''
|
||||
def test_pillar_top_compound_match(self, grains=None):
|
||||
'''
|
||||
Test that a compound match topfile that refers to a nodegroup via N@ works
|
||||
as expected.
|
||||
'''
|
||||
if not grains:
|
||||
grains = {}
|
||||
grains['os'] = 'Fedora'
|
||||
pillar_obj = pillar.Pillar(self.get_config('master', from_scratch=True), grains, 'minion', 'base')
|
||||
ret = pillar_obj.compile_pillar()
|
||||
self.assertEqual(ret.get('pillar_from_nodegroup_with_ghost'), True)
|
||||
self.assertEqual(ret.get('pillar_from_nodegroup'), None)
|
||||
|
||||
sub_pillar_obj = pillar.Pillar(self.get_config('master', from_scratch=True), grains, 'sub_minion', 'base')
|
||||
sub_ret = sub_pillar_obj.compile_pillar()
|
||||
self.assertEqual(sub_ret.get('pillar_from_nodegroup_with_ghost'), None)
|
||||
self.assertEqual(sub_ret.get('pillar_from_nodegroup'), True)
|
||||
|
||||
|
||||
@skipIf(not salt.utils.path.which('gpg'), 'GPG is not installed')
|
||||
class DecryptGPGPillarTest(ModuleCase):
|
||||
'''
|
||||
|
@ -9,9 +9,9 @@
|
||||
# Import python libs
|
||||
from __future__ import absolute_import, print_function, unicode_literals
|
||||
import os
|
||||
import pwd
|
||||
import shutil
|
||||
import re
|
||||
import shutil
|
||||
import sys
|
||||
import tempfile
|
||||
|
||||
# Import Salt Testing libs
|
||||
@ -23,6 +23,7 @@ from tests.support.helpers import skip_if_not_root
|
||||
# Import salt libs
|
||||
import salt.utils.files
|
||||
import salt.utils.path
|
||||
import salt.utils.platform
|
||||
from salt.modules.virtualenv_mod import KNOWN_BINARY_NAMES
|
||||
|
||||
|
||||
@ -74,23 +75,34 @@ class PipModuleTest(ModuleCase):
|
||||
|
||||
# Let's remove the pip binary
|
||||
pip_bin = os.path.join(self.venv_dir, 'bin', 'pip')
|
||||
py_dir = 'python{0}.{1}'.format(*sys.version_info[:2])
|
||||
site_dir = os.path.join(self.venv_dir, 'lib', py_dir, 'site-packages')
|
||||
if salt.utils.platform.is_windows():
|
||||
pip_bin = os.path.join(self.venv_dir, 'Scripts', 'pip.exe')
|
||||
site_dir = os.path.join(self.venv_dir, 'lib', 'site-packages')
|
||||
if not os.path.isfile(pip_bin):
|
||||
self.skipTest(
|
||||
'Failed to find the pip binary to the test virtualenv'
|
||||
)
|
||||
os.remove(pip_bin)
|
||||
|
||||
# Also remove the pip dir from site-packages
|
||||
# This is needed now that we're using python -m pip instead of the
|
||||
# pip binary directly. python -m pip will still work even if the
|
||||
# pip binary is missing
|
||||
shutil.rmtree(os.path.join(site_dir, 'pip'))
|
||||
|
||||
# Let's run a pip depending functions
|
||||
for func in ('pip.freeze', 'pip.list'):
|
||||
ret = self.run_function(func, bin_env=self.venv_dir)
|
||||
self.assertIn(
|
||||
'Command required for \'{0}\' not found: '
|
||||
'Could not find a `pip` binary in virtualenv'.format(func),
|
||||
'Could not find a `pip` binary'.format(func),
|
||||
ret
|
||||
)
|
||||
|
||||
@skip_if_not_root
|
||||
def test_requirements_as_list_of_chains__sans_no_chown__cwd_set__absolute_file_path(self):
|
||||
def test_requirements_as_list_of_chains__cwd_set__absolute_file_path(self):
|
||||
self.run_function('virtualenv.create', [self.venv_dir])
|
||||
|
||||
# Create a requirements file that depends on another one.
|
||||
@ -109,11 +121,10 @@ class PipModuleTest(ModuleCase):
|
||||
with salt.utils.files.fopen(req2b_filename, 'w') as f:
|
||||
f.write('pep8\n')
|
||||
|
||||
this_user = pwd.getpwuid(os.getuid())[0]
|
||||
requirements_list = [req1_filename, req2_filename]
|
||||
|
||||
ret = self.run_function(
|
||||
'pip.install', requirements=requirements_list, user=this_user,
|
||||
'pip.install', requirements=requirements_list,
|
||||
bin_env=self.venv_dir, cwd=self.venv_dir
|
||||
)
|
||||
try:
|
||||
@ -128,7 +139,7 @@ class PipModuleTest(ModuleCase):
|
||||
raise
|
||||
|
||||
@skip_if_not_root
|
||||
def test_requirements_as_list_of_chains__sans_no_chown__cwd_not_set__absolute_file_path(self):
|
||||
def test_requirements_as_list_of_chains__cwd_not_set__absolute_file_path(self):
|
||||
self.run_function('virtualenv.create', [self.venv_dir])
|
||||
|
||||
# Create a requirements file that depends on another one.
|
||||
@ -147,12 +158,10 @@ class PipModuleTest(ModuleCase):
|
||||
with salt.utils.files.fopen(req2b_filename, 'w') as f:
|
||||
f.write('pep8\n')
|
||||
|
||||
this_user = pwd.getpwuid(os.getuid())[0]
|
||||
requirements_list = [req1_filename, req2_filename]
|
||||
|
||||
ret = self.run_function(
|
||||
'pip.install', requirements=requirements_list, user=this_user,
|
||||
bin_env=self.venv_dir
|
||||
'pip.install', requirements=requirements_list, bin_env=self.venv_dir
|
||||
)
|
||||
try:
|
||||
self.assertEqual(ret['retcode'], 0)
|
||||
@ -167,7 +176,7 @@ class PipModuleTest(ModuleCase):
|
||||
raise
|
||||
|
||||
@skip_if_not_root
|
||||
def test_requirements_as_list__sans_no_chown__absolute_file_path(self):
|
||||
def test_requirements_as_list__absolute_file_path(self):
|
||||
self.run_function('virtualenv.create', [self.venv_dir])
|
||||
|
||||
req1_filename = os.path.join(self.venv_dir, 'requirements.txt')
|
||||
@ -178,12 +187,10 @@ class PipModuleTest(ModuleCase):
|
||||
with salt.utils.files.fopen(req2_filename, 'w') as f:
|
||||
f.write('pep8\n')
|
||||
|
||||
this_user = pwd.getpwuid(os.getuid())[0]
|
||||
requirements_list = [req1_filename, req2_filename]
|
||||
|
||||
ret = self.run_function(
|
||||
'pip.install', requirements=requirements_list, user=this_user,
|
||||
bin_env=self.venv_dir
|
||||
'pip.install', requirements=requirements_list, bin_env=self.venv_dir
|
||||
)
|
||||
|
||||
found = self.pip_successful_install(ret['stdout'])
|
||||
@ -198,7 +205,7 @@ class PipModuleTest(ModuleCase):
|
||||
raise
|
||||
|
||||
@skip_if_not_root
|
||||
def test_requirements_as_list__sans_no_chown__non_absolute_file_path(self):
|
||||
def test_requirements_as_list__non_absolute_file_path(self):
|
||||
self.run_function('virtualenv.create', [self.venv_dir])
|
||||
|
||||
# Create a requirements file that depends on another one.
|
||||
@ -215,11 +222,10 @@ class PipModuleTest(ModuleCase):
|
||||
with salt.utils.files.fopen(req2_filepath, 'w') as f:
|
||||
f.write('pep8\n')
|
||||
|
||||
this_user = pwd.getpwuid(os.getuid())[0]
|
||||
requirements_list = [req1_filename, req2_filename]
|
||||
|
||||
ret = self.run_function(
|
||||
'pip.install', requirements=requirements_list, user=this_user,
|
||||
'pip.install', requirements=requirements_list,
|
||||
bin_env=self.venv_dir, cwd=req_cwd
|
||||
)
|
||||
try:
|
||||
@ -234,7 +240,7 @@ class PipModuleTest(ModuleCase):
|
||||
raise
|
||||
|
||||
@skip_if_not_root
|
||||
def test_chained_requirements__sans_no_chown__absolute_file_path(self):
|
||||
def test_chained_requirements__absolute_file_path(self):
|
||||
self.run_function('virtualenv.create', [self.venv_dir])
|
||||
|
||||
# Create a requirements file that depends on another one.
|
||||
@ -247,10 +253,8 @@ class PipModuleTest(ModuleCase):
|
||||
with salt.utils.files.fopen(req2_filename, 'w') as f:
|
||||
f.write('pep8')
|
||||
|
||||
this_user = pwd.getpwuid(os.getuid())[0]
|
||||
ret = self.run_function(
|
||||
'pip.install', requirements=req1_filename, user=this_user,
|
||||
bin_env=self.venv_dir
|
||||
'pip.install', requirements=req1_filename, bin_env=self.venv_dir
|
||||
)
|
||||
try:
|
||||
self.assertEqual(ret['retcode'], 0)
|
||||
@ -261,7 +265,7 @@ class PipModuleTest(ModuleCase):
|
||||
raise
|
||||
|
||||
@skip_if_not_root
|
||||
def test_chained_requirements__sans_no_chown__non_absolute_file_path(self):
|
||||
def test_chained_requirements__non_absolute_file_path(self):
|
||||
self.run_function('virtualenv.create', [self.venv_dir])
|
||||
|
||||
# Create a requirements file that depends on another one.
|
||||
@ -278,10 +282,9 @@ class PipModuleTest(ModuleCase):
|
||||
with salt.utils.files.fopen(req2_file, 'w') as f:
|
||||
f.write('pep8')
|
||||
|
||||
this_user = pwd.getpwuid(os.getuid())[0]
|
||||
ret = self.run_function(
|
||||
'pip.install', requirements=req1_filename, user=this_user,
|
||||
no_chown=False, cwd=req_basepath, bin_env=self.venv_dir
|
||||
'pip.install', requirements=req1_filename, cwd=req_basepath,
|
||||
bin_env=self.venv_dir
|
||||
)
|
||||
try:
|
||||
self.assertEqual(ret['retcode'], 0)
|
||||
@ -292,7 +295,7 @@ class PipModuleTest(ModuleCase):
|
||||
raise
|
||||
|
||||
@skip_if_not_root
|
||||
def test_issue_4805_nested_requirements_user_no_chown(self):
|
||||
def test_issue_4805_nested_requirements(self):
|
||||
self.run_function('virtualenv.create', [self.venv_dir])
|
||||
|
||||
# Create a requirements file that depends on another one.
|
||||
@ -303,11 +306,8 @@ class PipModuleTest(ModuleCase):
|
||||
with salt.utils.files.fopen(req2_filename, 'w') as f:
|
||||
f.write('pep8')
|
||||
|
||||
this_user = pwd.getpwuid(os.getuid())[0]
|
||||
ret = self.run_function(
|
||||
'pip.install', requirements=req1_filename, user=this_user,
|
||||
no_chown=True, bin_env=self.venv_dir
|
||||
)
|
||||
'pip.install', requirements=req1_filename, bin_env=self.venv_dir)
|
||||
if self._check_download_error(ret['stdout']):
|
||||
self.skipTest('Test skipped due to pip download error')
|
||||
try:
|
||||
@ -436,9 +436,9 @@ class PipModuleTest(ModuleCase):
|
||||
def tearDown(self):
|
||||
super(PipModuleTest, self).tearDown()
|
||||
if os.path.isdir(self.venv_test_dir):
|
||||
shutil.rmtree(self.venv_test_dir)
|
||||
shutil.rmtree(self.venv_test_dir, ignore_errors=True)
|
||||
if os.path.isdir(self.pip_temp):
|
||||
shutil.rmtree(self.pip_temp)
|
||||
shutil.rmtree(self.pip_temp, ignore_errors=True)
|
||||
del self.venv_dir
|
||||
del self.venv_test_dir
|
||||
del self.pip_temp
|
||||
|
@ -88,6 +88,17 @@ class MatchTest(ShellCase, ShellCaseCommonTestsMixin):
|
||||
data = self.run_salt("-C 'J%@knights%^(Lancelot|Galahad)$' test.ping")
|
||||
self.assertTrue(minion_in_returns('minion', data))
|
||||
self.assertTrue(minion_in_returns('sub_minion', data))
|
||||
time.sleep(2)
|
||||
data = self.run_salt("-C 'N@multiline_nodegroup' test.ping")
|
||||
self.assertTrue(minion_in_returns('minion', data))
|
||||
self.assertTrue(minion_in_returns('sub_minion', data))
|
||||
time.sleep(2)
|
||||
data = self.run_salt("-C 'N@multiline_nodegroup not sub_minion' test.ping")
|
||||
self.assertTrue(minion_in_returns('minion', data))
|
||||
self.assertFalse(minion_in_returns('sub_minion', data))
|
||||
data = self.run_salt("-C 'N@multiline_nodegroup not @fakenodegroup not sub_minion' test.ping")
|
||||
self.assertTrue(minion_in_returns('minion', data))
|
||||
self.assertFalse(minion_in_returns('sub_minion', data))
|
||||
|
||||
def test_nodegroup(self):
|
||||
'''
|
||||
|
@ -11,28 +11,38 @@
|
||||
from __future__ import absolute_import, print_function, unicode_literals
|
||||
import errno
|
||||
import os
|
||||
import pwd
|
||||
import glob
|
||||
import shutil
|
||||
import sys
|
||||
|
||||
try:
|
||||
import pwd
|
||||
HAS_PWD = True
|
||||
except ImportError:
|
||||
HAS_PWD = False
|
||||
|
||||
# Import Salt Testing libs
|
||||
from tests.support.mixins import SaltReturnAssertsMixin
|
||||
from tests.support.unit import skipIf
|
||||
from tests.support.runtests import RUNTIME_VARS
|
||||
from tests.support.case import ModuleCase
|
||||
from tests.support.helpers import (
|
||||
destructiveTest,
|
||||
requires_system_grains,
|
||||
with_system_user,
|
||||
skip_if_not_root
|
||||
skip_if_not_root,
|
||||
with_tempdir
|
||||
)
|
||||
from tests.support.mixins import SaltReturnAssertsMixin
|
||||
from tests.support.runtests import RUNTIME_VARS
|
||||
from tests.support.unit import skipIf
|
||||
|
||||
# Import salt libs
|
||||
import salt.utils.files
|
||||
import salt.utils.path
|
||||
import salt.utils.platform
|
||||
import salt.utils.versions
|
||||
import salt.utils.win_dacl
|
||||
import salt.utils.win_functions
|
||||
from salt.modules.virtualenv_mod import KNOWN_BINARY_NAMES
|
||||
from salt.exceptions import CommandExecutionError
|
||||
from tests.support.case import ModuleCase
|
||||
|
||||
# Import 3rd-party libs
|
||||
from salt.ext import six
|
||||
@ -49,7 +59,7 @@ class VirtualEnv(object):
|
||||
|
||||
def __exit__(self, exc_type, exc_value, traceback):
|
||||
if os.path.isdir(self.venv_dir):
|
||||
shutil.rmtree(self.venv_dir)
|
||||
shutil.rmtree(self.venv_dir, ignore_errors=True)
|
||||
|
||||
|
||||
@skipIf(salt.utils.path.which_bin(KNOWN_BINARY_NAMES) is None, 'virtualenv not installed')
|
||||
@ -115,9 +125,10 @@ class PipStateTest(ModuleCase, SaltReturnAssertsMixin):
|
||||
else:
|
||||
os.environ['SHELL'] = orig_shell
|
||||
if os.path.isdir(venv_dir):
|
||||
shutil.rmtree(venv_dir)
|
||||
shutil.rmtree(venv_dir, ignore_errors=True)
|
||||
|
||||
@skipIf(six.PY3, 'Issue is specific to carbon module, which is PY2-only')
|
||||
@skipIf(salt.utils.platform.is_windows(), "Carbon does not install in Windows")
|
||||
@requires_system_grains
|
||||
def test_pip_installed_weird_install(self, grains=None):
|
||||
# First, check to see if this is running on CentOS 5 or MacOS.
|
||||
@ -143,7 +154,7 @@ class PipStateTest(ModuleCase, SaltReturnAssertsMixin):
|
||||
)
|
||||
finally:
|
||||
if os.path.isdir(ographite):
|
||||
shutil.rmtree(ographite)
|
||||
shutil.rmtree(ographite, ignore_errors=True)
|
||||
|
||||
venv_dir = os.path.join(RUNTIME_VARS.TMP, 'pip-installed-weird-install')
|
||||
try:
|
||||
@ -152,7 +163,7 @@ class PipStateTest(ModuleCase, SaltReturnAssertsMixin):
|
||||
# context when running the call to state.sls that comes after.
|
||||
self.run_function('saltutil.sync_modules')
|
||||
# Since we don't have the virtualenv created, pip.installed will
|
||||
# thrown and error.
|
||||
# throw an error.
|
||||
ret = self.run_function(
|
||||
'state.sls', mods='pip-installed-weird-install'
|
||||
)
|
||||
@ -174,7 +185,7 @@ class PipStateTest(ModuleCase, SaltReturnAssertsMixin):
|
||||
raise Exception('Expected state did not run')
|
||||
finally:
|
||||
if os.path.isdir(ographite):
|
||||
shutil.rmtree(ographite)
|
||||
shutil.rmtree(ographite, ignore_errors=True)
|
||||
|
||||
def test_issue_2028_pip_installed_state(self):
|
||||
ret = self.run_function('state.sls', mods='issue-2028-pip-installed')
|
||||
@ -183,14 +194,18 @@ class PipStateTest(ModuleCase, SaltReturnAssertsMixin):
|
||||
RUNTIME_VARS.TMP, 'issue-2028-pip-installed'
|
||||
)
|
||||
|
||||
pep8_bin = os.path.join(venv_dir, 'bin', 'pep8')
|
||||
if salt.utils.platform.is_windows():
|
||||
pep8_bin = os.path.join(venv_dir, 'Scripts', 'pep8.exe')
|
||||
|
||||
try:
|
||||
self.assertSaltTrueReturn(ret)
|
||||
self.assertTrue(
|
||||
os.path.isfile(os.path.join(venv_dir, 'bin', 'pep8'))
|
||||
os.path.isfile(pep8_bin)
|
||||
)
|
||||
finally:
|
||||
if os.path.isdir(venv_dir):
|
||||
shutil.rmtree(venv_dir)
|
||||
shutil.rmtree(venv_dir, ignore_errors=True)
|
||||
|
||||
def test_issue_2087_missing_pip(self):
|
||||
venv_dir = os.path.join(
|
||||
@ -204,12 +219,23 @@ class PipStateTest(ModuleCase, SaltReturnAssertsMixin):
|
||||
|
||||
# Let's remove the pip binary
|
||||
pip_bin = os.path.join(venv_dir, 'bin', 'pip')
|
||||
py_dir = 'python{0}.{1}'.format(*sys.version_info[:2])
|
||||
site_dir = os.path.join(venv_dir, 'lib', py_dir, 'site-packages')
|
||||
if salt.utils.platform.is_windows():
|
||||
pip_bin = os.path.join(venv_dir, 'Scripts', 'pip.exe')
|
||||
site_dir = os.path.join(venv_dir, 'lib', 'site-packages')
|
||||
if not os.path.isfile(pip_bin):
|
||||
self.skipTest(
|
||||
'Failed to find the pip binary to the test virtualenv'
|
||||
)
|
||||
os.remove(pip_bin)
|
||||
|
||||
# Also remove the pip dir from site-packages
|
||||
# This is needed now that we're using python -m pip instead of the
|
||||
# pip binary directly. python -m pip will still work even if the
|
||||
# pip binary is missing
|
||||
shutil.rmtree(os.path.join(site_dir, 'pip'))
|
||||
|
||||
# Let's run the state which should fail because pip is missing
|
||||
ret = self.run_function('state.sls', mods='issue-2087-missing-pip')
|
||||
self.assertSaltFalseReturn(ret)
|
||||
@ -219,7 +245,7 @@ class PipStateTest(ModuleCase, SaltReturnAssertsMixin):
|
||||
)
|
||||
finally:
|
||||
if os.path.isdir(venv_dir):
|
||||
shutil.rmtree(venv_dir)
|
||||
shutil.rmtree(venv_dir, ignore_errors=True)
|
||||
|
||||
def test_issue_5940_multiple_pip_mirrors(self):
|
||||
'''
|
||||
@ -244,148 +270,100 @@ class PipStateTest(ModuleCase, SaltReturnAssertsMixin):
|
||||
self.skipTest('the --mirrors arg has been deprecated and removed in pip==7.0.0')
|
||||
finally:
|
||||
if os.path.isdir(venv_dir):
|
||||
shutil.rmtree(venv_dir)
|
||||
shutil.rmtree(venv_dir, ignore_errors=True)
|
||||
|
||||
@destructiveTest
|
||||
@skip_if_not_root
|
||||
@with_system_user('issue-6912', on_existing='delete', delete=True)
|
||||
def test_issue_6912_wrong_owner(self, username):
|
||||
venv_dir = os.path.join(
|
||||
RUNTIME_VARS.TMP, '6912-wrong-owner'
|
||||
)
|
||||
# ----- Using runas ------------------------------------------------->
|
||||
venv_create = self.run_function(
|
||||
'virtualenv.create', [venv_dir], user=username
|
||||
)
|
||||
if venv_create['retcode'] > 0:
|
||||
self.skipTest(
|
||||
'Failed to create testcase virtual environment: {0}'.format(
|
||||
venv_create
|
||||
)
|
||||
)
|
||||
@with_system_user('issue-6912', on_existing='delete', delete=True,
|
||||
password='PassWord1!')
|
||||
@with_tempdir()
|
||||
def test_issue_6912_wrong_owner(self, temp_dir, username):
|
||||
# Setup virtual environment directory to be used throughout the test
|
||||
venv_dir = os.path.join(temp_dir, '6912-wrong-owner')
|
||||
|
||||
# Using the package name.
|
||||
try:
|
||||
ret = self.run_state(
|
||||
'pip.installed', name='pep8', user=username, bin_env=venv_dir
|
||||
)
|
||||
self.assertSaltTrueReturn(ret)
|
||||
uinfo = pwd.getpwnam(username)
|
||||
for globmatch in (os.path.join(venv_dir, '**', 'pep8*'),
|
||||
os.path.join(venv_dir, '*', '**', 'pep8*'),
|
||||
os.path.join(venv_dir, '*', '*', '**', 'pep8*')):
|
||||
for path in glob.glob(globmatch):
|
||||
# The virtual environment needs to be in a location that is accessible
|
||||
# by both the user running the test and the runas user
|
||||
if salt.utils.platform.is_windows():
|
||||
salt.utils.win_dacl.set_permissions(temp_dir, username, 'full_control')
|
||||
else:
|
||||
uid = self.run_function('file.user_to_uid', [username])
|
||||
os.chown(temp_dir, uid, -1)
|
||||
|
||||
# Create the virtual environment
|
||||
venv_create = self.run_function(
|
||||
'virtualenv.create', [venv_dir], user=username,
|
||||
password='PassWord1!')
|
||||
if venv_create['retcode'] > 0:
|
||||
self.skipTest('Failed to create testcase virtual environment: {0}'
|
||||
''.format(venv_create))
|
||||
|
||||
# pip install passing the package name in `name`
|
||||
ret = self.run_state(
|
||||
'pip.installed', name='pep8', user=username, bin_env=venv_dir,
|
||||
no_cache_dir=True, password='PassWord1!')
|
||||
self.assertSaltTrueReturn(ret)
|
||||
|
||||
if HAS_PWD:
|
||||
uid = pwd.getpwnam(username).pw_uid
|
||||
for globmatch in (os.path.join(venv_dir, '**', 'pep8*'),
|
||||
os.path.join(venv_dir, '*', '**', 'pep8*'),
|
||||
os.path.join(venv_dir, '*', '*', '**', 'pep8*')):
|
||||
for path in glob.glob(globmatch):
|
||||
if HAS_PWD:
|
||||
self.assertEqual(uid, os.stat(path).st_uid)
|
||||
elif salt.utils.platform.is_windows():
|
||||
self.assertEqual(
|
||||
uinfo.pw_uid, os.stat(path).st_uid
|
||||
)
|
||||
salt.utils.win_dacl.get_owner(path), username)
|
||||
|
||||
finally:
|
||||
if os.path.isdir(venv_dir):
|
||||
shutil.rmtree(venv_dir)
|
||||
@destructiveTest
|
||||
@skip_if_not_root
|
||||
@with_system_user('issue-6912', on_existing='delete', delete=True,
|
||||
password='PassWord1!')
|
||||
@with_tempdir()
|
||||
def test_issue_6912_wrong_owner_requirements_file(self, temp_dir, username):
|
||||
# Setup virtual environment directory to be used throughout the test
|
||||
venv_dir = os.path.join(temp_dir, '6912-wrong-owner')
|
||||
|
||||
# Using a requirements file
|
||||
# The virtual environment needs to be in a location that is accessible
|
||||
# by both the user running the test and the runas user
|
||||
if salt.utils.platform.is_windows():
|
||||
salt.utils.win_dacl.set_permissions(temp_dir, username, 'full_control')
|
||||
else:
|
||||
uid = self.run_function('file.user_to_uid', [username])
|
||||
os.chown(temp_dir, uid, -1)
|
||||
|
||||
# Create the virtual environment again as it should have been removed
|
||||
venv_create = self.run_function(
|
||||
'virtualenv.create', [venv_dir], user=username
|
||||
)
|
||||
'virtualenv.create', [venv_dir], user=username,
|
||||
password='PassWord1!')
|
||||
if venv_create['retcode'] > 0:
|
||||
self.skipTest(
|
||||
'Failed to create testcase virtual environment: {0}'.format(
|
||||
ret
|
||||
)
|
||||
)
|
||||
self.skipTest('failed to create testcase virtual environment: {0}'
|
||||
''.format(venv_create))
|
||||
|
||||
# pip install using a requirements file
|
||||
req_filename = os.path.join(
|
||||
RUNTIME_VARS.TMP_STATE_TREE, 'issue-6912-requirements.txt'
|
||||
)
|
||||
with salt.utils.files.fopen(req_filename, 'wb') as reqf:
|
||||
reqf.write(b'pep8\n')
|
||||
|
||||
try:
|
||||
ret = self.run_state(
|
||||
'pip.installed', name='', user=username, bin_env=venv_dir,
|
||||
requirements='salt://issue-6912-requirements.txt'
|
||||
)
|
||||
self.assertSaltTrueReturn(ret)
|
||||
uinfo = pwd.getpwnam(username)
|
||||
for globmatch in (os.path.join(venv_dir, '**', 'pep8*'),
|
||||
os.path.join(venv_dir, '*', '**', 'pep8*'),
|
||||
os.path.join(venv_dir, '*', '*', '**', 'pep8*')):
|
||||
for path in glob.glob(globmatch):
|
||||
ret = self.run_state(
|
||||
'pip.installed', name='', user=username, bin_env=venv_dir,
|
||||
requirements='salt://issue-6912-requirements.txt',
|
||||
no_cache_dir=True, password='PassWord1!')
|
||||
self.assertSaltTrueReturn(ret)
|
||||
|
||||
if HAS_PWD:
|
||||
uid = pwd.getpwnam(username).pw_uid
|
||||
for globmatch in (os.path.join(venv_dir, '**', 'pep8*'),
|
||||
os.path.join(venv_dir, '*', '**', 'pep8*'),
|
||||
os.path.join(venv_dir, '*', '*', '**', 'pep8*')):
|
||||
for path in glob.glob(globmatch):
|
||||
if HAS_PWD:
|
||||
self.assertEqual(uid, os.stat(path).st_uid)
|
||||
elif salt.utils.platform.is_windows():
|
||||
self.assertEqual(
|
||||
uinfo.pw_uid, os.stat(path).st_uid
|
||||
)
|
||||
|
||||
finally:
|
||||
if os.path.isdir(venv_dir):
|
||||
shutil.rmtree(venv_dir)
|
||||
os.unlink(req_filename)
|
||||
# <---- Using runas --------------------------------------------------
|
||||
|
||||
# ----- Using user -------------------------------------------------->
|
||||
venv_create = self.run_function(
|
||||
'virtualenv.create', [venv_dir], user=username
|
||||
)
|
||||
if venv_create['retcode'] > 0:
|
||||
self.skipTest(
|
||||
'Failed to create testcase virtual environment: {0}'.format(
|
||||
ret
|
||||
)
|
||||
)
|
||||
|
||||
# Using the package name
|
||||
try:
|
||||
ret = self.run_state(
|
||||
'pip.installed', name='pep8', user=username, bin_env=venv_dir
|
||||
)
|
||||
self.assertSaltTrueReturn(ret)
|
||||
uinfo = pwd.getpwnam(username)
|
||||
for globmatch in (os.path.join(venv_dir, '**', 'pep8*'),
|
||||
os.path.join(venv_dir, '*', '**', 'pep8*'),
|
||||
os.path.join(venv_dir, '*', '*', '**', 'pep8*')):
|
||||
for path in glob.glob(globmatch):
|
||||
self.assertEqual(
|
||||
uinfo.pw_uid, os.stat(path).st_uid
|
||||
)
|
||||
|
||||
finally:
|
||||
if os.path.isdir(venv_dir):
|
||||
shutil.rmtree(venv_dir)
|
||||
|
||||
# Using a requirements file
|
||||
venv_create = self.run_function(
|
||||
'virtualenv.create', [venv_dir], user=username
|
||||
)
|
||||
if venv_create['retcode'] > 0:
|
||||
self.skipTest(
|
||||
'Failed to create testcase virtual environment: {0}'.format(
|
||||
ret
|
||||
)
|
||||
)
|
||||
req_filename = os.path.join(
|
||||
RUNTIME_VARS.TMP_STATE_TREE, 'issue-6912-requirements.txt'
|
||||
)
|
||||
with salt.utils.files.fopen(req_filename, 'wb') as reqf:
|
||||
reqf.write(b'pep8\n')
|
||||
|
||||
try:
|
||||
ret = self.run_state(
|
||||
'pip.installed', name='', user=username, bin_env=venv_dir,
|
||||
requirements='salt://issue-6912-requirements.txt'
|
||||
)
|
||||
self.assertSaltTrueReturn(ret)
|
||||
uinfo = pwd.getpwnam(username)
|
||||
for globmatch in (os.path.join(venv_dir, '**', 'pep8*'),
|
||||
os.path.join(venv_dir, '*', '**', 'pep8*'),
|
||||
os.path.join(venv_dir, '*', '*', '**', 'pep8*')):
|
||||
for path in glob.glob(globmatch):
|
||||
self.assertEqual(
|
||||
uinfo.pw_uid, os.stat(path).st_uid
|
||||
)
|
||||
|
||||
finally:
|
||||
if os.path.isdir(venv_dir):
|
||||
shutil.rmtree(venv_dir)
|
||||
os.unlink(req_filename)
|
||||
# <---- Using user ---------------------------------------------------
|
||||
salt.utils.win_dacl.get_owner(path), username)
|
||||
|
||||
def test_issue_6833_pip_upgrade_pip(self):
|
||||
# Create the testing virtualenv
|
||||
@ -393,6 +371,7 @@ class PipStateTest(ModuleCase, SaltReturnAssertsMixin):
|
||||
RUNTIME_VARS.TMP, '6833-pip-upgrade-pip'
|
||||
)
|
||||
ret = self.run_function('virtualenv.create', [venv_dir])
|
||||
|
||||
try:
|
||||
try:
|
||||
self.assertEqual(ret['retcode'], 0)
|
||||
@ -435,18 +414,15 @@ class PipStateTest(ModuleCase, SaltReturnAssertsMixin):
|
||||
)
|
||||
try:
|
||||
self.assertSaltTrueReturn(ret)
|
||||
self.assertInSaltReturn(
|
||||
'Installed',
|
||||
ret,
|
||||
['changes', 'pip==8.0.1']
|
||||
)
|
||||
self.assertSaltStateChangesEqual(
|
||||
ret, {'pip==8.0.1': 'Installed'})
|
||||
except AssertionError:
|
||||
import pprint
|
||||
pprint.pprint(ret)
|
||||
raise
|
||||
finally:
|
||||
if os.path.isdir(venv_dir):
|
||||
shutil.rmtree(venv_dir)
|
||||
shutil.rmtree(venv_dir, ignore_errors=True)
|
||||
|
||||
def test_pip_installed_specific_env(self):
|
||||
# Create the testing virtualenv
|
||||
@ -498,16 +474,14 @@ class PipStateTest(ModuleCase, SaltReturnAssertsMixin):
|
||||
)
|
||||
finally:
|
||||
if os.path.isdir(venv_dir):
|
||||
shutil.rmtree(venv_dir)
|
||||
shutil.rmtree(venv_dir, ignore_errors=True)
|
||||
if os.path.isfile(requirements_file):
|
||||
os.unlink(requirements_file)
|
||||
|
||||
def test_22359_pip_installed_unless_does_not_trigger_warnings(self):
|
||||
# This test case should be moved to a format_call unit test specific to
|
||||
# the state internal keywords
|
||||
venv_dir = venv_dir = os.path.join(
|
||||
RUNTIME_VARS.TMP, 'pip-installed-unless'
|
||||
)
|
||||
venv_dir = os.path.join(RUNTIME_VARS.TMP, 'pip-installed-unless')
|
||||
venv_create = self.run_function('virtualenv.create', [venv_dir])
|
||||
if venv_create['retcode'] > 0:
|
||||
self.skipTest(
|
||||
@ -516,17 +490,21 @@ class PipStateTest(ModuleCase, SaltReturnAssertsMixin):
|
||||
)
|
||||
)
|
||||
|
||||
false_cmd = '/bin/false'
|
||||
if salt.utils.platform.is_windows():
|
||||
false_cmd = 'exit 1 >nul'
|
||||
try:
|
||||
ret = self.run_state(
|
||||
'pip.installed', name='pep8', bin_env=venv_dir, unless='/bin/false'
|
||||
'pip.installed', name='pep8', bin_env=venv_dir, unless=false_cmd
|
||||
)
|
||||
self.assertSaltTrueReturn(ret)
|
||||
self.assertNotIn('warnings', next(six.itervalues(ret)))
|
||||
finally:
|
||||
if os.path.isdir(venv_dir):
|
||||
shutil.rmtree(venv_dir)
|
||||
shutil.rmtree(venv_dir, ignore_errors=True)
|
||||
|
||||
@skipIf(sys.version_info[:2] >= (3, 6), 'Old version of virtualenv too old for python3.6')
|
||||
@skipIf(salt.utils.platform.is_windows(), "Carbon does not install in Windows")
|
||||
def test_46127_pip_env_vars(self):
|
||||
'''
|
||||
Test that checks if env_vars passed to pip.installed are also passed
|
||||
@ -550,7 +528,7 @@ class PipStateTest(ModuleCase, SaltReturnAssertsMixin):
|
||||
)
|
||||
finally:
|
||||
if os.path.isdir(ographite):
|
||||
shutil.rmtree(ographite)
|
||||
shutil.rmtree(ographite, ignore_errors=True)
|
||||
|
||||
venv_dir = os.path.join(RUNTIME_VARS.TMP, 'issue-46127-pip-env-vars')
|
||||
try:
|
||||
@ -559,7 +537,7 @@ class PipStateTest(ModuleCase, SaltReturnAssertsMixin):
|
||||
# context when running the call to state.sls that comes after.
|
||||
self.run_function('saltutil.sync_modules')
|
||||
# Since we don't have the virtualenv created, pip.installed will
|
||||
# thrown and error.
|
||||
# throw an error.
|
||||
ret = self.run_function(
|
||||
'state.sls', mods='issue-46127-pip-env-vars'
|
||||
)
|
||||
@ -598,6 +576,6 @@ class PipStateTest(ModuleCase, SaltReturnAssertsMixin):
|
||||
raise Exception('Expected state did not run')
|
||||
finally:
|
||||
if os.path.isdir(ographite):
|
||||
shutil.rmtree(ographite)
|
||||
shutil.rmtree(ographite, ignore_errors=True)
|
||||
if os.path.isdir(venv_dir):
|
||||
shutil.rmtree(venv_dir)
|
||||
|
@ -57,6 +57,7 @@ from tests.support.paths import FILES, TMP
|
||||
|
||||
# Import Salt libs
|
||||
import salt.utils.files
|
||||
import salt.utils.platform
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
@ -613,10 +614,10 @@ def requires_network(only_local_network=False):
|
||||
return decorator
|
||||
|
||||
|
||||
def with_system_user(username, on_existing='delete', delete=True):
|
||||
def with_system_user(username, on_existing='delete', delete=True, password=None):
|
||||
'''
|
||||
Create and optionally destroy a system user to be used within a test
|
||||
case. The system user is crated using the ``user`` salt module.
|
||||
case. The system user is created using the ``user`` salt module.
|
||||
|
||||
The decorated testcase function must accept 'username' as an argument.
|
||||
|
||||
@ -646,7 +647,10 @@ def with_system_user(username, on_existing='delete', delete=True):
|
||||
|
||||
# Let's add the user to the system.
|
||||
log.debug('Creating system user {0!r}'.format(username))
|
||||
create_user = cls.run_function('user.add', [username])
|
||||
kwargs = {'timeout': 60}
|
||||
if salt.utils.platform.is_windows():
|
||||
kwargs.update({'password': password})
|
||||
create_user = cls.run_function('user.add', [username], **kwargs)
|
||||
if not create_user:
|
||||
log.debug('Failed to create system user')
|
||||
# The user was not created
|
||||
@ -702,7 +706,7 @@ def with_system_user(username, on_existing='delete', delete=True):
|
||||
finally:
|
||||
if delete:
|
||||
delete_user = cls.run_function(
|
||||
'user.delete', [username, True, True]
|
||||
'user.delete', [username, True, True], timeout=60
|
||||
)
|
||||
if not delete_user:
|
||||
if failure is None:
|
||||
@ -1117,7 +1121,6 @@ def requires_salt_modules(*names):
|
||||
|
||||
|
||||
def skip_if_binaries_missing(*binaries, **kwargs):
|
||||
import salt.utils
|
||||
import salt.utils.path
|
||||
if len(binaries) == 1:
|
||||
if isinstance(binaries[0], (list, tuple, set, frozenset)):
|
||||
|
@ -3,6 +3,7 @@
|
||||
# Import python libs
|
||||
from __future__ import absolute_import
|
||||
import os
|
||||
import sys
|
||||
|
||||
# Import Salt Testing libs
|
||||
from tests.support.mixins import LoaderModuleMockMixin
|
||||
@ -10,7 +11,6 @@ from tests.support.unit import skipIf, TestCase
|
||||
from tests.support.mock import NO_MOCK, NO_MOCK_REASON, MagicMock, patch
|
||||
|
||||
# Import salt libs
|
||||
from salt.ext import six
|
||||
import salt.utils.platform
|
||||
import salt.modules.pip as pip
|
||||
from salt.exceptions import CommandExecutionError
|
||||
@ -25,9 +25,8 @@ class PipTestCase(TestCase, LoaderModuleMockMixin):
|
||||
mock = MagicMock(return_value={'retcode': 0, 'stdout': ''})
|
||||
with patch.dict(pip.__salt__, {'cmd.run_all': mock}):
|
||||
pip.install(requirements='requirements.txt')
|
||||
expected_cmd = ['pip', 'install', '--requirement',
|
||||
'requirements.txt']
|
||||
mock.assert_called_once_with(
|
||||
expected_cmd = [sys.executable, '-m', 'pip', 'install', '--requirement', 'requirements.txt']
|
||||
mock.assert_called_with(
|
||||
expected_cmd,
|
||||
saltenv='base',
|
||||
runas=None,
|
||||
@ -50,7 +49,7 @@ class PipTestCase(TestCase, LoaderModuleMockMixin):
|
||||
'git+https://github.com/saltstack/salt-testing.git#egg=SaltTesting'
|
||||
]
|
||||
|
||||
expected = ['pip', 'install']
|
||||
expected = [sys.executable, '-m', 'pip', 'install']
|
||||
for item in editables:
|
||||
expected.extend(['--editable', item])
|
||||
|
||||
@ -58,7 +57,7 @@ class PipTestCase(TestCase, LoaderModuleMockMixin):
|
||||
mock = MagicMock(return_value={'retcode': 0, 'stdout': ''})
|
||||
with patch.dict(pip.__salt__, {'cmd.run_all': mock}):
|
||||
pip.install(editable=editables)
|
||||
mock.assert_called_once_with(
|
||||
mock.assert_called_with(
|
||||
expected,
|
||||
saltenv='base',
|
||||
runas=None,
|
||||
@ -70,7 +69,7 @@ class PipTestCase(TestCase, LoaderModuleMockMixin):
|
||||
mock = MagicMock(return_value={'retcode': 0, 'stdout': ''})
|
||||
with patch.dict(pip.__salt__, {'cmd.run_all': mock}):
|
||||
pip.install(editable=','.join(editables))
|
||||
mock.assert_called_once_with(
|
||||
mock.assert_called_with(
|
||||
expected,
|
||||
saltenv='base',
|
||||
runas=None,
|
||||
@ -85,7 +84,8 @@ class PipTestCase(TestCase, LoaderModuleMockMixin):
|
||||
'git+https://github.com/saltstack/salt-testing.git#egg=SaltTesting'
|
||||
]
|
||||
|
||||
expected = ['pip', 'install'] + pkgs
|
||||
expected = [sys.executable, '-m', 'pip', 'install']
|
||||
expected.extend(pkgs)
|
||||
for item in editables:
|
||||
expected.extend(['--editable', item])
|
||||
|
||||
@ -93,7 +93,7 @@ class PipTestCase(TestCase, LoaderModuleMockMixin):
|
||||
mock = MagicMock(return_value={'retcode': 0, 'stdout': ''})
|
||||
with patch.dict(pip.__salt__, {'cmd.run_all': mock}):
|
||||
pip.install(pkgs=pkgs, editable=editables)
|
||||
mock.assert_called_once_with(
|
||||
mock.assert_called_with(
|
||||
expected,
|
||||
saltenv='base',
|
||||
runas=None,
|
||||
@ -105,7 +105,7 @@ class PipTestCase(TestCase, LoaderModuleMockMixin):
|
||||
mock = MagicMock(return_value={'retcode': 0, 'stdout': ''})
|
||||
with patch.dict(pip.__salt__, {'cmd.run_all': mock}):
|
||||
pip.install(pkgs=','.join(pkgs), editable=','.join(editables))
|
||||
mock.assert_called_once_with(
|
||||
mock.assert_called_with(
|
||||
expected,
|
||||
saltenv='base',
|
||||
runas=None,
|
||||
@ -117,8 +117,9 @@ class PipTestCase(TestCase, LoaderModuleMockMixin):
|
||||
mock = MagicMock(return_value={'retcode': 0, 'stdout': ''})
|
||||
with patch.dict(pip.__salt__, {'cmd.run_all': mock}):
|
||||
pip.install(pkgs=pkgs[0], editable=editables[0])
|
||||
mock.assert_called_once_with(
|
||||
['pip', 'install', pkgs[0], '--editable', editables[0]],
|
||||
expected = [sys.executable, '-m', 'pip', 'install', pkgs[0], '--editable', editables[0]]
|
||||
mock.assert_called_with(
|
||||
expected,
|
||||
saltenv='base',
|
||||
runas=None,
|
||||
use_vt=False,
|
||||
@ -136,7 +137,7 @@ class PipTestCase(TestCase, LoaderModuleMockMixin):
|
||||
'http://pypi.crate.io'
|
||||
]
|
||||
|
||||
expected = ['pip', 'install', '--use-mirrors']
|
||||
expected = [sys.executable, '-m', 'pip', 'install', '--use-mirrors']
|
||||
for item in mirrors:
|
||||
expected.extend(['--mirrors', item])
|
||||
expected.append('pep8')
|
||||
@ -145,7 +146,7 @@ class PipTestCase(TestCase, LoaderModuleMockMixin):
|
||||
mock = MagicMock(return_value={'retcode': 0, 'stdout': ''})
|
||||
with patch.dict(pip.__salt__, {'cmd.run_all': mock}):
|
||||
pip.install(pkgs=['pep8'], mirrors=mirrors)
|
||||
mock.assert_called_once_with(
|
||||
mock.assert_called_with(
|
||||
expected,
|
||||
saltenv='base',
|
||||
runas=None,
|
||||
@ -157,7 +158,7 @@ class PipTestCase(TestCase, LoaderModuleMockMixin):
|
||||
mock = MagicMock(return_value={'retcode': 0, 'stdout': ''})
|
||||
with patch.dict(pip.__salt__, {'cmd.run_all': mock}):
|
||||
pip.install(pkgs=['pep8'], mirrors=','.join(mirrors))
|
||||
mock.assert_called_once_with(
|
||||
mock.assert_called_with(
|
||||
expected,
|
||||
saltenv='base',
|
||||
runas=None,
|
||||
@ -165,12 +166,14 @@ class PipTestCase(TestCase, LoaderModuleMockMixin):
|
||||
python_shell=False,
|
||||
)
|
||||
|
||||
expected = [sys.executable, '-m', 'pip', 'install', '--use-mirrors', '--mirrors', mirrors[0], 'pep8']
|
||||
|
||||
# As single string (just use the first element from mirrors)
|
||||
mock = MagicMock(return_value={'retcode': 0, 'stdout': ''})
|
||||
with patch.dict(pip.__salt__, {'cmd.run_all': mock}):
|
||||
pip.install(pkgs=['pep8'], mirrors=mirrors[0])
|
||||
mock.assert_called_once_with(
|
||||
['pip', 'install', '--use-mirrors', '--mirrors', mirrors[0], 'pep8'],
|
||||
mock.assert_called_with(
|
||||
expected,
|
||||
saltenv='base',
|
||||
runas=None,
|
||||
use_vt=False,
|
||||
@ -185,7 +188,7 @@ class PipTestCase(TestCase, LoaderModuleMockMixin):
|
||||
]
|
||||
pkg = 'pep8'
|
||||
|
||||
expected = ['pip', 'install']
|
||||
expected = [sys.executable, '-m', 'pip', 'install']
|
||||
for item in find_links:
|
||||
expected.extend(['--find-links', item])
|
||||
expected.append(pkg)
|
||||
@ -194,7 +197,7 @@ class PipTestCase(TestCase, LoaderModuleMockMixin):
|
||||
mock = MagicMock(return_value={'retcode': 0, 'stdout': ''})
|
||||
with patch.dict(pip.__salt__, {'cmd.run_all': mock}):
|
||||
pip.install(pkg, find_links=find_links)
|
||||
mock.assert_called_once_with(
|
||||
mock.assert_called_with(
|
||||
expected,
|
||||
saltenv='base',
|
||||
runas=None,
|
||||
@ -206,7 +209,7 @@ class PipTestCase(TestCase, LoaderModuleMockMixin):
|
||||
mock = MagicMock(return_value={'retcode': 0, 'stdout': ''})
|
||||
with patch.dict(pip.__salt__, {'cmd.run_all': mock}):
|
||||
pip.install(pkg, find_links=','.join(find_links))
|
||||
mock.assert_called_once_with(
|
||||
mock.assert_called_with(
|
||||
expected,
|
||||
saltenv='base',
|
||||
runas=None,
|
||||
@ -214,12 +217,26 @@ class PipTestCase(TestCase, LoaderModuleMockMixin):
|
||||
python_shell=False,
|
||||
)
|
||||
|
||||
# Valid protos work?
|
||||
mock = MagicMock(return_value={'retcode': 0, 'stdout': ''})
|
||||
with patch.dict(pip.__salt__, {'cmd.run_all': mock}):
|
||||
pip.install(pkg, find_links=find_links)
|
||||
mock.assert_called_with(
|
||||
expected,
|
||||
saltenv='base',
|
||||
runas=None,
|
||||
use_vt=False,
|
||||
python_shell=False,
|
||||
)
|
||||
|
||||
expected = [sys.executable, '-m', 'pip', 'install', '--find-links', find_links[0], pkg]
|
||||
|
||||
# As single string (just use the first element from find_links)
|
||||
mock = MagicMock(return_value={'retcode': 0, 'stdout': ''})
|
||||
with patch.dict(pip.__salt__, {'cmd.run_all': mock}):
|
||||
pip.install(pkg, find_links=find_links[0])
|
||||
mock.assert_called_once_with(
|
||||
['pip', 'install', '--find-links', find_links[0], pkg],
|
||||
mock.assert_called_with(
|
||||
expected,
|
||||
saltenv='base',
|
||||
runas=None,
|
||||
use_vt=False,
|
||||
@ -236,18 +253,6 @@ class PipTestCase(TestCase, LoaderModuleMockMixin):
|
||||
find_links='sftp://pypi.crate.io'
|
||||
)
|
||||
|
||||
# Valid protos work?
|
||||
mock = MagicMock(return_value={'retcode': 0, 'stdout': ''})
|
||||
with patch.dict(pip.__salt__, {'cmd.run_all': mock}):
|
||||
pip.install(pkg, find_links=find_links)
|
||||
mock.assert_called_once_with(
|
||||
expected,
|
||||
saltenv='base',
|
||||
runas=None,
|
||||
use_vt=False,
|
||||
python_shell=False,
|
||||
)
|
||||
|
||||
def test_install_no_index_with_index_url_or_extra_index_url_raises(self):
|
||||
mock = MagicMock(return_value={'retcode': 0, 'stdout': ''})
|
||||
with patch.dict(pip.__salt__, {'cmd.run_all': mock}):
|
||||
@ -276,8 +281,8 @@ class PipTestCase(TestCase, LoaderModuleMockMixin):
|
||||
mock = MagicMock(return_value={'retcode': 0, 'stdout': ''})
|
||||
with patch.dict(pip.__salt__, {'cmd.run_all': mock}):
|
||||
pip.install(requirements='salt://requirements.txt')
|
||||
expected = ['pip', 'install', '--requirement', 'my_cached_reqs']
|
||||
mock.assert_called_once_with(
|
||||
expected = [sys.executable, '-m', 'pip', 'install', '--requirement', 'my_cached_reqs']
|
||||
mock.assert_called_with(
|
||||
expected,
|
||||
saltenv='base',
|
||||
runas=None,
|
||||
@ -287,28 +292,29 @@ class PipTestCase(TestCase, LoaderModuleMockMixin):
|
||||
|
||||
def test_install_venv(self):
|
||||
with patch('os.path') as mock_path:
|
||||
mock_path.is_file.return_value = True
|
||||
mock_path.isdir.return_value = True
|
||||
|
||||
pkg = 'mock'
|
||||
|
||||
def join(*args):
|
||||
return os.sep.join(args)
|
||||
return os.path.normpath(os.sep.join(args))
|
||||
|
||||
mock_path.is_file.return_value = True
|
||||
mock_path.isdir.return_value = True
|
||||
mock_path.join = join
|
||||
|
||||
if salt.utils.platform.is_windows():
|
||||
venv_path = 'C:\\test_env'
|
||||
bin_path = os.path.join(venv_path, 'python.exe')
|
||||
else:
|
||||
venv_path = '/test_env'
|
||||
bin_path = os.path.join(venv_path, 'python')
|
||||
|
||||
mock = MagicMock(return_value={'retcode': 0, 'stdout': ''})
|
||||
with patch.dict(pip.__salt__, {'cmd.run_all': mock}):
|
||||
if salt.utils.platform.is_windows():
|
||||
venv_path = 'c:\\test_env'
|
||||
bin_path = os.path.join(venv_path, 'Scripts', 'pip.exe')
|
||||
if six.PY2:
|
||||
bin_path = bin_path.encode('string-escape')
|
||||
else:
|
||||
venv_path = '/test_env'
|
||||
bin_path = os.path.join(venv_path, 'bin', 'pip')
|
||||
pip.install(pkg, bin_env=venv_path)
|
||||
mock.assert_called_once_with(
|
||||
[bin_path, 'install', pkg],
|
||||
pip_bin = MagicMock(return_value=[bin_path, '-m', 'pip'])
|
||||
|
||||
with patch.dict(pip.__salt__, {'cmd.run_all': mock}), \
|
||||
patch.object(pip, '_get_pip_bin', pip_bin):
|
||||
pip.install('mock', bin_env=venv_path)
|
||||
mock.assert_called_with(
|
||||
[bin_path, '-m', 'pip', 'install', 'mock'],
|
||||
env={'VIRTUAL_ENV': venv_path},
|
||||
saltenv='base',
|
||||
runas=None,
|
||||
@ -323,8 +329,9 @@ class PipTestCase(TestCase, LoaderModuleMockMixin):
|
||||
mock = MagicMock(return_value={'retcode': 0, 'stdout': ''})
|
||||
with patch.dict(pip.__salt__, {'cmd.run_all': mock}):
|
||||
pip.install(pkg, log=log_path)
|
||||
mock.assert_called_once_with(
|
||||
['pip', 'install', '--log', log_path, pkg],
|
||||
expected = [sys.executable, '-m', 'pip', 'install', '--log', log_path, pkg]
|
||||
mock.assert_called_with(
|
||||
expected,
|
||||
saltenv='base',
|
||||
runas=None,
|
||||
use_vt=False,
|
||||
@ -349,12 +356,12 @@ class PipTestCase(TestCase, LoaderModuleMockMixin):
|
||||
def test_install_timeout_argument_in_resulting_command(self):
|
||||
# Passing an int
|
||||
pkg = 'pep8'
|
||||
expected_prefix = ['pip', 'install', '--timeout']
|
||||
expected = [sys.executable, '-m', 'pip', 'install', '--timeout']
|
||||
mock = MagicMock(return_value={'retcode': 0, 'stdout': ''})
|
||||
with patch.dict(pip.__salt__, {'cmd.run_all': mock}):
|
||||
pip.install(pkg, timeout=10)
|
||||
mock.assert_called_once_with(
|
||||
expected_prefix + [10, pkg],
|
||||
mock.assert_called_with(
|
||||
expected + [10, pkg],
|
||||
saltenv='base',
|
||||
runas=None,
|
||||
use_vt=False,
|
||||
@ -365,8 +372,8 @@ class PipTestCase(TestCase, LoaderModuleMockMixin):
|
||||
mock = MagicMock(return_value={'retcode': 0, 'stdout': ''})
|
||||
with patch.dict(pip.__salt__, {'cmd.run_all': mock}):
|
||||
pip.install(pkg, timeout='10')
|
||||
mock.assert_called_once_with(
|
||||
expected_prefix + ['10', pkg],
|
||||
mock.assert_called_with(
|
||||
expected + ['10', pkg],
|
||||
saltenv='base',
|
||||
runas=None,
|
||||
use_vt=False,
|
||||
@ -389,8 +396,9 @@ class PipTestCase(TestCase, LoaderModuleMockMixin):
|
||||
mock = MagicMock(return_value={'retcode': 0, 'stdout': ''})
|
||||
with patch.dict(pip.__salt__, {'cmd.run_all': mock}):
|
||||
pip.install(pkg, index_url=index_url)
|
||||
mock.assert_called_once_with(
|
||||
['pip', 'install', '--index-url', index_url, pkg],
|
||||
expected = [sys.executable, '-m', 'pip', 'install', '--index-url', index_url, pkg]
|
||||
mock.assert_called_with(
|
||||
expected,
|
||||
saltenv='base',
|
||||
runas=None,
|
||||
use_vt=False,
|
||||
@ -403,8 +411,9 @@ class PipTestCase(TestCase, LoaderModuleMockMixin):
|
||||
mock = MagicMock(return_value={'retcode': 0, 'stdout': ''})
|
||||
with patch.dict(pip.__salt__, {'cmd.run_all': mock}):
|
||||
pip.install(pkg, extra_index_url=extra_index_url)
|
||||
mock.assert_called_once_with(
|
||||
['pip', 'install', '--extra-index-url', extra_index_url, pkg],
|
||||
expected = [sys.executable, '-m', 'pip', 'install', '--extra-index-url', extra_index_url, pkg]
|
||||
mock.assert_called_with(
|
||||
expected,
|
||||
saltenv='base',
|
||||
runas=None,
|
||||
use_vt=False,
|
||||
@ -416,8 +425,9 @@ class PipTestCase(TestCase, LoaderModuleMockMixin):
|
||||
mock = MagicMock(return_value={'retcode': 0, 'stdout': ''})
|
||||
with patch.dict(pip.__salt__, {'cmd.run_all': mock}):
|
||||
pip.install(pkg, no_index=True)
|
||||
mock.assert_called_once_with(
|
||||
['pip', 'install', '--no-index', pkg],
|
||||
expected = [sys.executable, '-m', 'pip', 'install', '--no-index', pkg]
|
||||
mock.assert_called_with(
|
||||
expected,
|
||||
saltenv='base',
|
||||
runas=None,
|
||||
use_vt=False,
|
||||
@ -430,8 +440,9 @@ class PipTestCase(TestCase, LoaderModuleMockMixin):
|
||||
mock = MagicMock(return_value={'retcode': 0, 'stdout': ''})
|
||||
with patch.dict(pip.__salt__, {'cmd.run_all': mock}):
|
||||
pip.install(pkg, build=build)
|
||||
mock.assert_called_once_with(
|
||||
['pip', 'install', '--build', build, pkg],
|
||||
expected = [sys.executable, '-m', 'pip', 'install', '--build', build, pkg]
|
||||
mock.assert_called_with(
|
||||
expected,
|
||||
saltenv='base',
|
||||
runas=None,
|
||||
use_vt=False,
|
||||
@ -444,8 +455,9 @@ class PipTestCase(TestCase, LoaderModuleMockMixin):
|
||||
mock = MagicMock(return_value={'retcode': 0, 'stdout': ''})
|
||||
with patch.dict(pip.__salt__, {'cmd.run_all': mock}):
|
||||
pip.install(pkg, target=target)
|
||||
mock.assert_called_once_with(
|
||||
['pip', 'install', '--target', target, pkg],
|
||||
expected = [sys.executable, '-m', 'pip', 'install', '--target', target, pkg]
|
||||
mock.assert_called_with(
|
||||
expected,
|
||||
saltenv='base',
|
||||
runas=None,
|
||||
use_vt=False,
|
||||
@ -458,8 +470,9 @@ class PipTestCase(TestCase, LoaderModuleMockMixin):
|
||||
mock = MagicMock(return_value={'retcode': 0, 'stdout': ''})
|
||||
with patch.dict(pip.__salt__, {'cmd.run_all': mock}):
|
||||
pip.install(pkg, download=download)
|
||||
mock.assert_called_once_with(
|
||||
['pip', 'install', '--download', download, pkg],
|
||||
expected = [sys.executable, '-m', 'pip', 'install', '--download', download, pkg]
|
||||
mock.assert_called_with(
|
||||
expected,
|
||||
saltenv='base',
|
||||
runas=None,
|
||||
use_vt=False,
|
||||
@ -471,8 +484,9 @@ class PipTestCase(TestCase, LoaderModuleMockMixin):
|
||||
mock = MagicMock(return_value={'retcode': 0, 'stdout': ''})
|
||||
with patch.dict(pip.__salt__, {'cmd.run_all': mock}):
|
||||
pip.install(pkg, no_download=True)
|
||||
mock.assert_called_once_with(
|
||||
['pip', 'install', '--no-download', pkg],
|
||||
expected = [sys.executable, '-m', 'pip', 'install', '--no-download', pkg]
|
||||
mock.assert_called_with(
|
||||
expected,
|
||||
saltenv='base',
|
||||
runas=None,
|
||||
use_vt=False,
|
||||
@ -494,8 +508,9 @@ class PipTestCase(TestCase, LoaderModuleMockMixin):
|
||||
MagicMock(return_value=pip_version)):
|
||||
# test `download_cache` kwarg
|
||||
pip.install(pkg, download_cache='/tmp/foo')
|
||||
expected = [sys.executable, '-m', 'pip', 'install', cmd_arg, download_cache, pkg]
|
||||
mock.assert_called_with(
|
||||
['pip', 'install', cmd_arg, download_cache, pkg],
|
||||
expected,
|
||||
saltenv='base',
|
||||
runas=None,
|
||||
use_vt=False,
|
||||
@ -505,7 +520,7 @@ class PipTestCase(TestCase, LoaderModuleMockMixin):
|
||||
# test `cache_dir` kwarg
|
||||
pip.install(pkg, cache_dir='/tmp/foo')
|
||||
mock.assert_called_with(
|
||||
['pip', 'install', cmd_arg, download_cache, pkg],
|
||||
expected,
|
||||
saltenv='base',
|
||||
runas=None,
|
||||
use_vt=False,
|
||||
@ -518,8 +533,9 @@ class PipTestCase(TestCase, LoaderModuleMockMixin):
|
||||
mock = MagicMock(return_value={'retcode': 0, 'stdout': ''})
|
||||
with patch.dict(pip.__salt__, {'cmd.run_all': mock}):
|
||||
pip.install(pkg, source=source)
|
||||
mock.assert_called_once_with(
|
||||
['pip', 'install', '--source', source, pkg],
|
||||
expected = [sys.executable, '-m', 'pip', 'install', '--source', source, pkg]
|
||||
mock.assert_called_with(
|
||||
expected,
|
||||
saltenv='base',
|
||||
runas=None,
|
||||
use_vt=False,
|
||||
@ -531,9 +547,10 @@ class PipTestCase(TestCase, LoaderModuleMockMixin):
|
||||
for action in ('s', 'i', 'w', 'b'):
|
||||
mock = MagicMock(return_value={'retcode': 0, 'stdout': ''})
|
||||
with patch.dict(pip.__salt__, {'cmd.run_all': mock}):
|
||||
pip.install('pep8', exists_action=action)
|
||||
mock.assert_called_once_with(
|
||||
['pip', 'install', '--exists-action', action, pkg],
|
||||
pip.install(pkg, exists_action=action)
|
||||
expected = [sys.executable, '-m', 'pip', 'install', '--exists-action', action, pkg]
|
||||
mock.assert_called_with(
|
||||
expected,
|
||||
saltenv='base',
|
||||
runas=None,
|
||||
use_vt=False,
|
||||
@ -557,7 +574,7 @@ class PipTestCase(TestCase, LoaderModuleMockMixin):
|
||||
]
|
||||
pkg = 'pep8'
|
||||
|
||||
expected = ['pip', 'install']
|
||||
expected = [sys.executable, '-m', 'pip', 'install']
|
||||
for item in install_options:
|
||||
expected.extend(['--install-option', item])
|
||||
expected.append(pkg)
|
||||
@ -566,7 +583,7 @@ class PipTestCase(TestCase, LoaderModuleMockMixin):
|
||||
mock = MagicMock(return_value={'retcode': 0, 'stdout': ''})
|
||||
with patch.dict(pip.__salt__, {'cmd.run_all': mock}):
|
||||
pip.install(pkg, install_options=install_options)
|
||||
mock.assert_called_once_with(
|
||||
mock.assert_called_with(
|
||||
expected,
|
||||
saltenv='base',
|
||||
runas=None,
|
||||
@ -578,7 +595,7 @@ class PipTestCase(TestCase, LoaderModuleMockMixin):
|
||||
mock = MagicMock(return_value={'retcode': 0, 'stdout': ''})
|
||||
with patch.dict(pip.__salt__, {'cmd.run_all': mock}):
|
||||
pip.install(pkg, install_options=','.join(install_options))
|
||||
mock.assert_called_once_with(
|
||||
mock.assert_called_with(
|
||||
expected,
|
||||
saltenv='base',
|
||||
runas=None,
|
||||
@ -590,9 +607,9 @@ class PipTestCase(TestCase, LoaderModuleMockMixin):
|
||||
mock = MagicMock(return_value={'retcode': 0, 'stdout': ''})
|
||||
with patch.dict(pip.__salt__, {'cmd.run_all': mock}):
|
||||
pip.install(pkg, install_options=install_options[0])
|
||||
mock.assert_called_once_with(
|
||||
['pip', 'install', '--install-option',
|
||||
install_options[0], pkg],
|
||||
expected = [sys.executable, '-m', 'pip', 'install', '--install-option', install_options[0], pkg]
|
||||
mock.assert_called_with(
|
||||
expected,
|
||||
saltenv='base',
|
||||
runas=None,
|
||||
use_vt=False,
|
||||
@ -606,7 +623,7 @@ class PipTestCase(TestCase, LoaderModuleMockMixin):
|
||||
]
|
||||
pkg = 'pep8'
|
||||
|
||||
expected = ['pip', 'install']
|
||||
expected = [sys.executable, '-m', 'pip', 'install']
|
||||
for item in global_options:
|
||||
expected.extend(['--global-option', item])
|
||||
expected.append(pkg)
|
||||
@ -615,7 +632,7 @@ class PipTestCase(TestCase, LoaderModuleMockMixin):
|
||||
mock = MagicMock(return_value={'retcode': 0, 'stdout': ''})
|
||||
with patch.dict(pip.__salt__, {'cmd.run_all': mock}):
|
||||
pip.install(pkg, global_options=global_options)
|
||||
mock.assert_called_once_with(
|
||||
mock.assert_called_with(
|
||||
expected,
|
||||
saltenv='base',
|
||||
runas=None,
|
||||
@ -627,7 +644,7 @@ class PipTestCase(TestCase, LoaderModuleMockMixin):
|
||||
mock = MagicMock(return_value={'retcode': 0, 'stdout': ''})
|
||||
with patch.dict(pip.__salt__, {'cmd.run_all': mock}):
|
||||
pip.install(pkg, global_options=','.join(global_options))
|
||||
mock.assert_called_once_with(
|
||||
mock.assert_called_with(
|
||||
expected,
|
||||
saltenv='base',
|
||||
runas=None,
|
||||
@ -639,8 +656,9 @@ class PipTestCase(TestCase, LoaderModuleMockMixin):
|
||||
mock = MagicMock(return_value={'retcode': 0, 'stdout': ''})
|
||||
with patch.dict(pip.__salt__, {'cmd.run_all': mock}):
|
||||
pip.install(pkg, global_options=global_options[0])
|
||||
mock.assert_called_once_with(
|
||||
['pip', 'install', '--global-option', global_options[0], pkg],
|
||||
expected = [sys.executable, '-m', 'pip', 'install', '--global-option', global_options[0], pkg]
|
||||
mock.assert_called_with(
|
||||
expected,
|
||||
saltenv='base',
|
||||
runas=None,
|
||||
use_vt=False,
|
||||
@ -652,8 +670,9 @@ class PipTestCase(TestCase, LoaderModuleMockMixin):
|
||||
mock = MagicMock(return_value={'retcode': 0, 'stdout': ''})
|
||||
with patch.dict(pip.__salt__, {'cmd.run_all': mock}):
|
||||
pip.install(pkg, upgrade=True)
|
||||
mock.assert_called_once_with(
|
||||
['pip', 'install', '--upgrade', pkg],
|
||||
expected = [sys.executable, '-m', 'pip', 'install', '--upgrade', pkg]
|
||||
mock.assert_called_with(
|
||||
expected,
|
||||
saltenv='base',
|
||||
runas=None,
|
||||
use_vt=False,
|
||||
@ -665,8 +684,9 @@ class PipTestCase(TestCase, LoaderModuleMockMixin):
|
||||
mock = MagicMock(return_value={'retcode': 0, 'stdout': ''})
|
||||
with patch.dict(pip.__salt__, {'cmd.run_all': mock}):
|
||||
pip.install(pkg, force_reinstall=True)
|
||||
mock.assert_called_once_with(
|
||||
['pip', 'install', '--force-reinstall', pkg],
|
||||
expected = [sys.executable, '-m', 'pip', 'install', '--force-reinstall', pkg]
|
||||
mock.assert_called_with(
|
||||
expected,
|
||||
saltenv='base',
|
||||
runas=None,
|
||||
use_vt=False,
|
||||
@ -678,8 +698,9 @@ class PipTestCase(TestCase, LoaderModuleMockMixin):
|
||||
mock = MagicMock(return_value={'retcode': 0, 'stdout': ''})
|
||||
with patch.dict(pip.__salt__, {'cmd.run_all': mock}):
|
||||
pip.install(pkg, ignore_installed=True)
|
||||
mock.assert_called_once_with(
|
||||
['pip', 'install', '--ignore-installed', pkg],
|
||||
expected = [sys.executable, '-m', 'pip', 'install', '--ignore-installed', pkg]
|
||||
mock.assert_called_with(
|
||||
expected,
|
||||
saltenv='base',
|
||||
runas=None,
|
||||
use_vt=False,
|
||||
@ -691,8 +712,9 @@ class PipTestCase(TestCase, LoaderModuleMockMixin):
|
||||
mock = MagicMock(return_value={'retcode': 0, 'stdout': ''})
|
||||
with patch.dict(pip.__salt__, {'cmd.run_all': mock}):
|
||||
pip.install(pkg, no_deps=True)
|
||||
mock.assert_called_once_with(
|
||||
['pip', 'install', '--no-deps', pkg],
|
||||
expected = [sys.executable, '-m', 'pip', 'install', '--no-deps', pkg]
|
||||
mock.assert_called_with(
|
||||
expected,
|
||||
saltenv='base',
|
||||
runas=None,
|
||||
use_vt=False,
|
||||
@ -704,8 +726,9 @@ class PipTestCase(TestCase, LoaderModuleMockMixin):
|
||||
mock = MagicMock(return_value={'retcode': 0, 'stdout': ''})
|
||||
with patch.dict(pip.__salt__, {'cmd.run_all': mock}):
|
||||
pip.install(pkg, no_install=True)
|
||||
mock.assert_called_once_with(
|
||||
['pip', 'install', '--no-install', pkg],
|
||||
expected = [sys.executable, '-m', 'pip', 'install', '--no-install', pkg]
|
||||
mock.assert_called_with(
|
||||
expected,
|
||||
saltenv='base',
|
||||
runas=None,
|
||||
use_vt=False,
|
||||
@ -718,8 +741,9 @@ class PipTestCase(TestCase, LoaderModuleMockMixin):
|
||||
mock = MagicMock(return_value={'retcode': 0, 'stdout': ''})
|
||||
with patch.dict(pip.__salt__, {'cmd.run_all': mock}):
|
||||
pip.install(pkg, proxy=proxy)
|
||||
mock.assert_called_once_with(
|
||||
['pip', 'install', '--proxy', proxy, pkg],
|
||||
expected = [sys.executable, '-m', 'pip', 'install', '--proxy', proxy, pkg]
|
||||
mock.assert_called_with(
|
||||
expected,
|
||||
saltenv='base',
|
||||
runas=None,
|
||||
use_vt=False,
|
||||
@ -736,7 +760,7 @@ class PipTestCase(TestCase, LoaderModuleMockMixin):
|
||||
'salt://requirements-1.txt', 'salt://requirements-2.txt'
|
||||
]
|
||||
|
||||
expected = ['pip', 'install']
|
||||
expected = [sys.executable, '-m', 'pip', 'install']
|
||||
for item in cached_reqs:
|
||||
expected.extend(['--requirement', item])
|
||||
|
||||
@ -744,7 +768,7 @@ class PipTestCase(TestCase, LoaderModuleMockMixin):
|
||||
mock = MagicMock(return_value={'retcode': 0, 'stdout': ''})
|
||||
with patch.dict(pip.__salt__, {'cmd.run_all': mock}):
|
||||
pip.install(requirements=requirements)
|
||||
mock.assert_called_once_with(
|
||||
mock.assert_called_with(
|
||||
expected,
|
||||
saltenv='base',
|
||||
runas=None,
|
||||
@ -757,7 +781,7 @@ class PipTestCase(TestCase, LoaderModuleMockMixin):
|
||||
mock = MagicMock(return_value={'retcode': 0, 'stdout': ''})
|
||||
with patch.dict(pip.__salt__, {'cmd.run_all': mock}):
|
||||
pip.install(requirements=','.join(requirements))
|
||||
mock.assert_called_once_with(
|
||||
mock.assert_called_with(
|
||||
expected,
|
||||
saltenv='base',
|
||||
runas=None,
|
||||
@ -770,8 +794,9 @@ class PipTestCase(TestCase, LoaderModuleMockMixin):
|
||||
mock = MagicMock(return_value={'retcode': 0, 'stdout': ''})
|
||||
with patch.dict(pip.__salt__, {'cmd.run_all': mock}):
|
||||
pip.install(requirements=requirements[0])
|
||||
mock.assert_called_once_with(
|
||||
['pip', 'install', '--requirement', cached_reqs[0]],
|
||||
expected = [sys.executable, '-m', 'pip', 'install', '--requirement', cached_reqs[0]]
|
||||
mock.assert_called_with(
|
||||
expected,
|
||||
saltenv='base',
|
||||
runas=None,
|
||||
use_vt=False,
|
||||
@ -788,7 +813,7 @@ class PipTestCase(TestCase, LoaderModuleMockMixin):
|
||||
'salt://requirements-1.txt', 'salt://requirements-2.txt'
|
||||
]
|
||||
|
||||
expected = ['pip', 'uninstall', '-y']
|
||||
expected = [sys.executable, '-m', 'pip', 'uninstall', '-y']
|
||||
for item in cached_reqs:
|
||||
expected.extend(['--requirement', item])
|
||||
|
||||
@ -796,7 +821,7 @@ class PipTestCase(TestCase, LoaderModuleMockMixin):
|
||||
mock = MagicMock(return_value={'retcode': 0, 'stdout': ''})
|
||||
with patch.dict(pip.__salt__, {'cmd.run_all': mock}):
|
||||
pip.uninstall(requirements=requirements)
|
||||
mock.assert_called_once_with(
|
||||
mock.assert_called_with(
|
||||
expected,
|
||||
cwd=None,
|
||||
saltenv='base',
|
||||
@ -810,7 +835,7 @@ class PipTestCase(TestCase, LoaderModuleMockMixin):
|
||||
mock = MagicMock(return_value={'retcode': 0, 'stdout': ''})
|
||||
with patch.dict(pip.__salt__, {'cmd.run_all': mock}):
|
||||
pip.uninstall(requirements=','.join(requirements))
|
||||
mock.assert_called_once_with(
|
||||
mock.assert_called_with(
|
||||
expected,
|
||||
cwd=None,
|
||||
saltenv='base',
|
||||
@ -824,8 +849,9 @@ class PipTestCase(TestCase, LoaderModuleMockMixin):
|
||||
mock = MagicMock(return_value={'retcode': 0, 'stdout': ''})
|
||||
with patch.dict(pip.__salt__, {'cmd.run_all': mock}):
|
||||
pip.uninstall(requirements=requirements[0])
|
||||
mock.assert_called_once_with(
|
||||
['pip', 'uninstall', '-y', '--requirement', cached_reqs[0]],
|
||||
expected = [sys.executable, '-m', 'pip', 'uninstall', '-y', '--requirement', cached_reqs[0]]
|
||||
mock.assert_called_with(
|
||||
expected,
|
||||
cwd=None,
|
||||
saltenv='base',
|
||||
runas=None,
|
||||
@ -839,8 +865,9 @@ class PipTestCase(TestCase, LoaderModuleMockMixin):
|
||||
mock = MagicMock(return_value={'retcode': 0, 'stdout': ''})
|
||||
with patch.dict(pip.__salt__, {'cmd.run_all': mock}):
|
||||
pip.uninstall(pkg, proxy=proxy)
|
||||
mock.assert_called_once_with(
|
||||
['pip', 'uninstall', '-y', '--proxy', proxy, pkg],
|
||||
expected = [sys.executable, '-m', 'pip', 'uninstall', '-y', '--proxy', proxy, pkg]
|
||||
mock.assert_called_with(
|
||||
expected,
|
||||
saltenv='base',
|
||||
cwd=None,
|
||||
runas=None,
|
||||
@ -849,22 +876,24 @@ class PipTestCase(TestCase, LoaderModuleMockMixin):
|
||||
)
|
||||
|
||||
def test_uninstall_log_argument_in_resulting_command(self):
|
||||
with patch('os.path') as mock_path:
|
||||
pkg = 'pep8'
|
||||
log_path = '/tmp/pip-install.log'
|
||||
mock = MagicMock(return_value={'retcode': 0, 'stdout': ''})
|
||||
with patch.dict(pip.__salt__, {'cmd.run_all': mock}):
|
||||
pip.uninstall(pkg, log=log_path)
|
||||
mock.assert_called_once_with(
|
||||
['pip', 'uninstall', '-y', '--log', log_path, pkg],
|
||||
saltenv='base',
|
||||
cwd=None,
|
||||
runas=None,
|
||||
use_vt=False,
|
||||
python_shell=False,
|
||||
)
|
||||
pkg = 'pep8'
|
||||
log_path = '/tmp/pip-install.log'
|
||||
|
||||
# Let's fake a non-writable log file
|
||||
mock = MagicMock(return_value={'retcode': 0, 'stdout': ''})
|
||||
with patch.dict(pip.__salt__, {'cmd.run_all': mock}):
|
||||
pip.uninstall(pkg, log=log_path)
|
||||
expected = [sys.executable, '-m', 'pip', 'uninstall', '-y', '--log', log_path, pkg]
|
||||
mock.assert_called_with(
|
||||
expected,
|
||||
saltenv='base',
|
||||
cwd=None,
|
||||
runas=None,
|
||||
use_vt=False,
|
||||
python_shell=False,
|
||||
)
|
||||
|
||||
# Let's fake a non-writable log file
|
||||
with patch('os.path') as mock_path:
|
||||
mock_path.exists.side_effect = IOError('Fooo!')
|
||||
mock = MagicMock(return_value={'retcode': 0, 'stdout': ''})
|
||||
with patch.dict(pip.__salt__, {'cmd.run_all': mock}):
|
||||
@ -877,13 +906,13 @@ class PipTestCase(TestCase, LoaderModuleMockMixin):
|
||||
|
||||
def test_uninstall_timeout_argument_in_resulting_command(self):
|
||||
pkg = 'pep8'
|
||||
expected_prefix = ['pip', 'uninstall', '-y', '--timeout']
|
||||
expected = [sys.executable, '-m', 'pip', 'uninstall', '-y', '--timeout']
|
||||
# Passing an int
|
||||
mock = MagicMock(return_value={'retcode': 0, 'stdout': ''})
|
||||
with patch.dict(pip.__salt__, {'cmd.run_all': mock}):
|
||||
pip.uninstall(pkg, timeout=10)
|
||||
mock.assert_called_once_with(
|
||||
expected_prefix + [10, pkg],
|
||||
mock.assert_called_with(
|
||||
expected + [10, pkg],
|
||||
cwd=None,
|
||||
saltenv='base',
|
||||
runas=None,
|
||||
@ -895,8 +924,8 @@ class PipTestCase(TestCase, LoaderModuleMockMixin):
|
||||
mock = MagicMock(return_value={'retcode': 0, 'stdout': ''})
|
||||
with patch.dict(pip.__salt__, {'cmd.run_all': mock}):
|
||||
pip.uninstall(pkg, timeout='10')
|
||||
mock.assert_called_once_with(
|
||||
expected_prefix + ['10', pkg],
|
||||
mock.assert_called_with(
|
||||
expected + ['10', pkg],
|
||||
cwd=None,
|
||||
saltenv='base',
|
||||
runas=None,
|
||||
@ -915,6 +944,7 @@ class PipTestCase(TestCase, LoaderModuleMockMixin):
|
||||
)
|
||||
|
||||
def test_freeze_command(self):
|
||||
expected = [sys.executable, '-m', 'pip', 'freeze']
|
||||
eggs = [
|
||||
'M2Crypto==0.21.1',
|
||||
'-e git+git@github.com:s0undt3ch/salt-testing.git@9ed81aa2f918d59d3706e56b18f0782d1ea43bf8#egg=SaltTesting-dev',
|
||||
@ -932,8 +962,8 @@ class PipTestCase(TestCase, LoaderModuleMockMixin):
|
||||
with patch('salt.modules.pip.version',
|
||||
MagicMock(return_value='6.1.1')):
|
||||
ret = pip.freeze()
|
||||
mock.assert_called_once_with(
|
||||
['pip', 'freeze'],
|
||||
mock.assert_called_with(
|
||||
expected,
|
||||
cwd=None,
|
||||
runas=None,
|
||||
use_vt=False,
|
||||
@ -952,8 +982,8 @@ class PipTestCase(TestCase, LoaderModuleMockMixin):
|
||||
with patch('salt.modules.pip.version',
|
||||
MagicMock(return_value='6.1.1')):
|
||||
ret = pip.freeze(env_vars={"foo": "bar"})
|
||||
mock.assert_called_once_with(
|
||||
['pip', 'freeze'],
|
||||
mock.assert_called_with(
|
||||
expected,
|
||||
cwd=None,
|
||||
runas=None,
|
||||
use_vt=False,
|
||||
@ -992,8 +1022,9 @@ class PipTestCase(TestCase, LoaderModuleMockMixin):
|
||||
with patch('salt.modules.pip.version',
|
||||
MagicMock(return_value='9.0.1')):
|
||||
ret = pip.freeze()
|
||||
mock.assert_called_once_with(
|
||||
['pip', 'freeze', '--all'],
|
||||
expected = [sys.executable, '-m', 'pip', 'freeze', '--all']
|
||||
mock.assert_called_with(
|
||||
expected,
|
||||
cwd=None,
|
||||
runas=None,
|
||||
use_vt=False,
|
||||
@ -1025,8 +1056,9 @@ class PipTestCase(TestCase, LoaderModuleMockMixin):
|
||||
with patch('salt.modules.pip.version',
|
||||
MagicMock(return_value=mock_version)):
|
||||
ret = pip.list_()
|
||||
expected = [sys.executable, '-m', 'pip', 'freeze']
|
||||
mock.assert_called_with(
|
||||
['pip', 'freeze'],
|
||||
expected,
|
||||
cwd=None,
|
||||
runas=None,
|
||||
python_shell=False,
|
||||
@ -1072,8 +1104,9 @@ class PipTestCase(TestCase, LoaderModuleMockMixin):
|
||||
with patch('salt.modules.pip.version',
|
||||
MagicMock(return_value=mock_version)):
|
||||
ret = pip.list_()
|
||||
expected = [sys.executable, '-m', 'pip', 'freeze', '--all']
|
||||
mock.assert_called_with(
|
||||
['pip', 'freeze', '--all'],
|
||||
expected,
|
||||
cwd=None,
|
||||
runas=None,
|
||||
python_shell=False,
|
||||
@ -1119,8 +1152,9 @@ class PipTestCase(TestCase, LoaderModuleMockMixin):
|
||||
with patch('salt.modules.pip.version',
|
||||
MagicMock(return_value='6.1.1')):
|
||||
ret = pip.list_(prefix='bb')
|
||||
expected = [sys.executable, '-m', 'pip', 'freeze']
|
||||
mock.assert_called_with(
|
||||
['pip', 'freeze'],
|
||||
expected,
|
||||
cwd=None,
|
||||
runas=None,
|
||||
python_shell=False,
|
||||
@ -1135,9 +1169,9 @@ class PipTestCase(TestCase, LoaderModuleMockMixin):
|
||||
|
||||
def test_list_upgrades_legacy(self):
|
||||
eggs = [
|
||||
'apache-libcloud (1.1.0) - Latest: 2.2.1 [wheel]',
|
||||
'appdirs (1.4.1) - Latest: 1.4.3 [wheel]',
|
||||
'awscli (1.11.63) - Latest: 1.12.1 [sdist]'
|
||||
'apache-libcloud (Current: 1.1.0 Latest: 2.2.1 [wheel])',
|
||||
'appdirs (Current: 1.4.1 Latest: 1.4.3 [wheel])',
|
||||
'awscli (Current: 1.11.63 Latest: 1.12.1 [sdist])'
|
||||
]
|
||||
mock = MagicMock(
|
||||
return_value={
|
||||
@ -1150,7 +1184,7 @@ class PipTestCase(TestCase, LoaderModuleMockMixin):
|
||||
MagicMock(return_value='6.1.1')):
|
||||
ret = pip.list_upgrades()
|
||||
mock.assert_called_with(
|
||||
['pip', 'list', '--outdated'],
|
||||
[sys.executable, '-m', 'pip', 'list', '--outdated'],
|
||||
cwd=None,
|
||||
runas=None,
|
||||
)
|
||||
@ -1178,15 +1212,15 @@ class PipTestCase(TestCase, LoaderModuleMockMixin):
|
||||
MagicMock(return_value='9.1.1')):
|
||||
ret = pip.list_upgrades()
|
||||
mock.assert_called_with(
|
||||
['pip', 'list', '--outdated', '--format=json'],
|
||||
[sys.executable, '-m', 'pip', 'list', '--outdated', '--format=json'],
|
||||
cwd=None,
|
||||
runas=None,
|
||||
)
|
||||
self.assertEqual(
|
||||
ret, {
|
||||
'apache-libcloud': '2.2.1',
|
||||
'appdirs': '1.4.3',
|
||||
'awscli': '1.12.1'
|
||||
'apache-libcloud': '2.2.1 [wheel]',
|
||||
'appdirs': '1.4.3 [wheel]',
|
||||
'awscli': '1.12.1 [sdist]'
|
||||
}
|
||||
)
|
||||
|
||||
@ -1209,7 +1243,7 @@ class PipTestCase(TestCase, LoaderModuleMockMixin):
|
||||
MagicMock(return_value='6.1.1')):
|
||||
ret = pip.is_installed(pkgname='bbfreeze')
|
||||
mock.assert_called_with(
|
||||
['pip', 'freeze'],
|
||||
[sys.executable, '-m', 'pip', 'freeze'],
|
||||
cwd=None,
|
||||
runas=None,
|
||||
python_shell=False,
|
||||
@ -1236,7 +1270,7 @@ class PipTestCase(TestCase, LoaderModuleMockMixin):
|
||||
MagicMock(return_value='6.1.1')):
|
||||
ret = pip.is_installed(pkgname='notexist')
|
||||
mock.assert_called_with(
|
||||
['pip', 'freeze'],
|
||||
[sys.executable, '-m', 'pip', 'freeze'],
|
||||
cwd=None,
|
||||
runas=None,
|
||||
python_shell=False,
|
||||
@ -1256,8 +1290,9 @@ class PipTestCase(TestCase, LoaderModuleMockMixin):
|
||||
with patch('salt.modules.pip.version',
|
||||
MagicMock(return_value='1.3')):
|
||||
pip.install(pkg, pre_releases=True)
|
||||
expected = [sys.executable, '-m', 'pip', 'install', pkg]
|
||||
mock.assert_called_with(
|
||||
['pip', 'install', pkg],
|
||||
expected,
|
||||
saltenv='base',
|
||||
runas=None,
|
||||
use_vt=False,
|
||||
@ -1269,10 +1304,11 @@ class PipTestCase(TestCase, LoaderModuleMockMixin):
|
||||
with patch.dict(pip.__salt__, {'cmd.run_stdout': mock_run,
|
||||
'cmd.run_all': mock_run_all}):
|
||||
with patch('salt.modules.pip._get_pip_bin',
|
||||
MagicMock(return_value='pip')):
|
||||
MagicMock(return_value=['pip'])):
|
||||
pip.install(pkg, pre_releases=True)
|
||||
expected = ['pip', 'install', '--pre', pkg]
|
||||
mock_run_all.assert_called_with(
|
||||
['pip', 'install', '--pre', pkg],
|
||||
expected,
|
||||
saltenv='base',
|
||||
runas=None,
|
||||
use_vt=False,
|
||||
|
@ -17,6 +17,7 @@ from tests.support.mock import NO_MOCK, NO_MOCK_REASON, MagicMock, patch
|
||||
|
||||
# Import salt libs
|
||||
import salt.states.pip_state as pip_state
|
||||
import salt.utils.versions
|
||||
|
||||
# Import 3rd-party libs
|
||||
try:
|
||||
@ -43,211 +44,163 @@ class PipStateTest(TestCase, SaltReturnAssertsMixin, LoaderModuleMockMixin):
|
||||
def test_install_requirements_parsing(self):
|
||||
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.assertSaltFalseReturn({'test': ret})
|
||||
self.assertInSaltComment(
|
||||
'Invalid version specification in package pep8=1.3.2. '
|
||||
'\'=\' is not supported, use \'==\' instead.',
|
||||
{'test': ret}
|
||||
)
|
||||
pip_version = pip.__version__
|
||||
mock_pip_version = MagicMock(return_value=pip_version)
|
||||
with patch.dict(pip_state.__salt__, {'pip.version': mock_pip_version}):
|
||||
with patch.dict(pip_state.__salt__, {'cmd.run_all': mock,
|
||||
'pip.list': pip_list}):
|
||||
with patch.dict(pip_state.__opts__, {'test': True}):
|
||||
if salt.utils.versions.compare(ver1=pip_version,
|
||||
oper='<',
|
||||
ver2='10.0'):
|
||||
ret = pip_state.installed('pep8=1.3.2')
|
||||
self.assertSaltFalseReturn({'test': ret})
|
||||
self.assertInSaltComment(
|
||||
'Invalid version specification in package pep8=1.3.2. '
|
||||
'\'=\' is not supported, use \'==\' instead.',
|
||||
{'test': ret})
|
||||
else:
|
||||
self.assertRaises(
|
||||
pip._internal.exceptions.InstallationError,
|
||||
pip_state.installed, 'pep=1.3.2')
|
||||
|
||||
mock = MagicMock(return_value={'retcode': 0, 'stdout': ''})
|
||||
pip_list = MagicMock(return_value={'pep8': '1.3.3'})
|
||||
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': True}):
|
||||
ret = pip_state.installed('pep8>=1.3.2')
|
||||
self.assertSaltTrueReturn({'test': ret})
|
||||
self.assertInSaltComment(
|
||||
'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'})
|
||||
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': True}):
|
||||
ret = pip_state.installed('pep8>=1.3.2')
|
||||
self.assertSaltTrueReturn({'test': ret})
|
||||
self.assertInSaltComment(
|
||||
'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.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'})
|
||||
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': True}):
|
||||
ret = pip_state.installed('pep8>1.3.1,<1.3.3')
|
||||
self.assertSaltTrueReturn({'test': ret})
|
||||
self.assertInSaltComment(
|
||||
'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.2'})
|
||||
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': True}):
|
||||
ret = pip_state.installed('pep8>1.3.1,<1.3.3')
|
||||
self.assertSaltTrueReturn({'test': ret})
|
||||
self.assertInSaltComment(
|
||||
'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'})
|
||||
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': True}):
|
||||
ret = pip_state.installed('pep8>1.3.1,<1.3.3')
|
||||
self.assertSaltNoneReturn({'test': ret})
|
||||
self.assertInSaltComment(
|
||||
'Python package pep8>1.3.1,<1.3.3 is set to be installed',
|
||||
{'test': ret}
|
||||
)
|
||||
mock = MagicMock(return_value={'retcode': 0, 'stdout': ''})
|
||||
pip_list = MagicMock(return_value={'pep8': '1.3.1'})
|
||||
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': True}):
|
||||
ret = pip_state.installed('pep8>1.3.1,<1.3.3')
|
||||
self.assertSaltNoneReturn({'test': ret})
|
||||
self.assertInSaltComment(
|
||||
'Python package pep8>1.3.1,<1.3.3 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>=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>=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 '
|
||||
'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 '
|
||||
'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}):
|
||||
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(
|
||||
'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}
|
||||
)
|
||||
|
||||
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': '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(
|
||||
'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',
|
||||
self.assertSaltTrueReturn({'test': ret})
|
||||
self.assertInSaltComment('All packages were successfully installed',
|
||||
{'test': ret}
|
||||
)
|
||||
|
||||
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': '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(
|
||||
'https://pypi.python.org/packages/source/S/SaltTesting/'
|
||||
'SaltTesting-0.5.0.tar.gz'
|
||||
'#md5=e6760af92b7165f8be53b5763e40bc24'
|
||||
)
|
||||
self.assertSaltTrueReturn({'test': ret})
|
||||
self.assertInSaltComment('All packages were successfully installed',
|
||||
{'test': ret}
|
||||
)
|
||||
self.assertInSaltReturn(
|
||||
'Installed',
|
||||
{'test': ret},
|
||||
('changes', 'https://pypi.python.org/packages/source/S/'
|
||||
'SaltTesting/SaltTesting-0.5.0.tar.gz'
|
||||
'#md5=e6760af92b7165f8be53b5763e40bc24==???')
|
||||
)
|
||||
|
||||
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'
|
||||
)
|
||||
self.assertSaltTrueReturn({'test': ret})
|
||||
self.assertInSaltComment(
|
||||
'packages are already installed',
|
||||
{'test': ret}
|
||||
self.assertInSaltReturn(
|
||||
'Installed',
|
||||
{'test': ret},
|
||||
('changes', 'https://pypi.python.org/packages/source/S/'
|
||||
'SaltTesting/SaltTesting-0.5.0.tar.gz'
|
||||
'#md5=e6760af92b7165f8be53b5763e40bc24==???')
|
||||
)
|
||||
|
||||
mock = MagicMock(return_value={'retcode': 0, 'stdout': ''})
|
||||
pip_list = MagicMock(return_value={'pep8': '1.3.1'})
|
||||
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': ''})
|
||||
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+git://github.com/saltstack/salt-testing.git#egg=SaltTesting'
|
||||
)
|
||||
self.assertSaltTrueReturn({'test': ret})
|
||||
self.assertInSaltComment(
|
||||
'packages are already installed',
|
||||
{'test': ret}
|
||||
)
|
||||
|
||||
# Test VCS installations with version info like >= 0.1
|
||||
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={
|
||||
@ -260,7 +213,7 @@ class PipStateTest(TestCase, SaltReturnAssertsMixin, LoaderModuleMockMixin):
|
||||
'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'
|
||||
'git+https://github.com/saltstack/salt-testing.git#egg=SaltTesting'
|
||||
)
|
||||
self.assertSaltTrueReturn({'test': ret})
|
||||
self.assertInSaltComment(
|
||||
@ -268,6 +221,63 @@ class PipStateTest(TestCase, SaltReturnAssertsMixin, LoaderModuleMockMixin):
|
||||
{'test': ret}
|
||||
)
|
||||
|
||||
mock = MagicMock(return_value={'retcode': 0, 'stdout': ''})
|
||||
pip_list = MagicMock(return_value={'pep8': '1.3.1'})
|
||||
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': ''})
|
||||
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+git://github.com/saltstack/salt-testing.git#egg=SaltTesting'
|
||||
)
|
||||
self.assertSaltTrueReturn({'test': ret})
|
||||
self.assertInSaltComment(
|
||||
'packages are already installed',
|
||||
{'test': ret}
|
||||
)
|
||||
|
||||
# Test VCS installations with version info like >= 0.1
|
||||
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(
|
||||
'packages are already installed',
|
||||
{'test': ret}
|
||||
)
|
||||
|
||||
def test_install_in_editable_mode(self):
|
||||
'''
|
||||
Check that `name` parameter containing bad characters is not parsed by
|
||||
@ -281,9 +291,11 @@ class PipStateTest(TestCase, SaltReturnAssertsMixin, LoaderModuleMockMixin):
|
||||
'stderr': '',
|
||||
'stdout': 'Cloned!'
|
||||
})
|
||||
pip_version = MagicMock(return_value='10.0.1')
|
||||
with patch.dict(pip_state.__salt__, {'cmd.run_all': mock,
|
||||
'pip.list': pip_list,
|
||||
'pip.install': pip_install}):
|
||||
'pip.install': pip_install,
|
||||
'pip.version': pip_version}):
|
||||
ret = pip_state.installed('state@name',
|
||||
cwd='/path/to/project',
|
||||
editable=['.'])
|
||||
|
@ -208,3 +208,238 @@ class StringutilsTestCase(TestCase):
|
||||
self.assertTrue(salt.utils.stringutils.expr_match(val, r'foo/\w+/baz'))
|
||||
# Regex non-match
|
||||
self.assertFalse(salt.utils.stringutils.expr_match(val, r'foo/\w/baz'))
|
||||
|
||||
def test_check_whitelist_blacklist(self):
|
||||
'''
|
||||
Ensure that whitelist matching works on both PY2 and PY3
|
||||
'''
|
||||
whitelist = ['one/two/three', r'web[0-9]']
|
||||
blacklist = ['four/five/six', r'web[5-9]']
|
||||
|
||||
# Tests with string whitelist/blacklist
|
||||
self.assertFalse(
|
||||
salt.utils.stringutils.check_whitelist_blacklist(
|
||||
'web_one',
|
||||
whitelist=whitelist[1],
|
||||
blacklist=None,
|
||||
)
|
||||
)
|
||||
self.assertFalse(
|
||||
salt.utils.stringutils.check_whitelist_blacklist(
|
||||
'web_one',
|
||||
whitelist=whitelist[1],
|
||||
blacklist=[],
|
||||
)
|
||||
)
|
||||
self.assertTrue(
|
||||
salt.utils.stringutils.check_whitelist_blacklist(
|
||||
'web1',
|
||||
whitelist=whitelist[1],
|
||||
blacklist=None,
|
||||
)
|
||||
)
|
||||
self.assertTrue(
|
||||
salt.utils.stringutils.check_whitelist_blacklist(
|
||||
'web1',
|
||||
whitelist=whitelist[1],
|
||||
blacklist=[],
|
||||
)
|
||||
)
|
||||
self.assertFalse(
|
||||
salt.utils.stringutils.check_whitelist_blacklist(
|
||||
'web5',
|
||||
whitelist=None,
|
||||
blacklist=blacklist[1],
|
||||
)
|
||||
)
|
||||
self.assertFalse(
|
||||
salt.utils.stringutils.check_whitelist_blacklist(
|
||||
'web5',
|
||||
whitelist=[],
|
||||
blacklist=blacklist[1],
|
||||
)
|
||||
)
|
||||
self.assertTrue(
|
||||
salt.utils.stringutils.check_whitelist_blacklist(
|
||||
'web_five',
|
||||
whitelist=None,
|
||||
blacklist=blacklist[1],
|
||||
)
|
||||
)
|
||||
self.assertTrue(
|
||||
salt.utils.stringutils.check_whitelist_blacklist(
|
||||
'web_five',
|
||||
whitelist=[],
|
||||
blacklist=blacklist[1],
|
||||
)
|
||||
)
|
||||
self.assertFalse(
|
||||
salt.utils.stringutils.check_whitelist_blacklist(
|
||||
'web5',
|
||||
whitelist=whitelist[1],
|
||||
blacklist=blacklist[1],
|
||||
)
|
||||
)
|
||||
self.assertTrue(
|
||||
salt.utils.stringutils.check_whitelist_blacklist(
|
||||
'web4',
|
||||
whitelist=whitelist[1],
|
||||
blacklist=blacklist[1],
|
||||
)
|
||||
)
|
||||
|
||||
# Tests with list whitelist/blacklist
|
||||
self.assertFalse(
|
||||
salt.utils.stringutils.check_whitelist_blacklist(
|
||||
'web_one',
|
||||
whitelist=whitelist,
|
||||
blacklist=None,
|
||||
)
|
||||
)
|
||||
self.assertFalse(
|
||||
salt.utils.stringutils.check_whitelist_blacklist(
|
||||
'web_one',
|
||||
whitelist=whitelist,
|
||||
blacklist=[],
|
||||
)
|
||||
)
|
||||
self.assertTrue(
|
||||
salt.utils.stringutils.check_whitelist_blacklist(
|
||||
'web1',
|
||||
whitelist=whitelist,
|
||||
blacklist=None,
|
||||
)
|
||||
)
|
||||
self.assertTrue(
|
||||
salt.utils.stringutils.check_whitelist_blacklist(
|
||||
'web1',
|
||||
whitelist=whitelist,
|
||||
blacklist=[],
|
||||
)
|
||||
)
|
||||
self.assertFalse(
|
||||
salt.utils.stringutils.check_whitelist_blacklist(
|
||||
'web5',
|
||||
whitelist=None,
|
||||
blacklist=blacklist,
|
||||
)
|
||||
)
|
||||
self.assertFalse(
|
||||
salt.utils.stringutils.check_whitelist_blacklist(
|
||||
'web5',
|
||||
whitelist=[],
|
||||
blacklist=blacklist,
|
||||
)
|
||||
)
|
||||
self.assertTrue(
|
||||
salt.utils.stringutils.check_whitelist_blacklist(
|
||||
'web_five',
|
||||
whitelist=None,
|
||||
blacklist=blacklist,
|
||||
)
|
||||
)
|
||||
self.assertTrue(
|
||||
salt.utils.stringutils.check_whitelist_blacklist(
|
||||
'web_five',
|
||||
whitelist=[],
|
||||
blacklist=blacklist,
|
||||
)
|
||||
)
|
||||
self.assertFalse(
|
||||
salt.utils.stringutils.check_whitelist_blacklist(
|
||||
'web5',
|
||||
whitelist=whitelist,
|
||||
blacklist=blacklist,
|
||||
)
|
||||
)
|
||||
self.assertTrue(
|
||||
salt.utils.stringutils.check_whitelist_blacklist(
|
||||
'web4',
|
||||
whitelist=whitelist,
|
||||
blacklist=blacklist,
|
||||
)
|
||||
)
|
||||
|
||||
# Tests with set whitelist/blacklist
|
||||
self.assertFalse(
|
||||
salt.utils.stringutils.check_whitelist_blacklist(
|
||||
'web_one',
|
||||
whitelist=set(whitelist),
|
||||
blacklist=None,
|
||||
)
|
||||
)
|
||||
self.assertFalse(
|
||||
salt.utils.stringutils.check_whitelist_blacklist(
|
||||
'web_one',
|
||||
whitelist=set(whitelist),
|
||||
blacklist=set(),
|
||||
)
|
||||
)
|
||||
self.assertTrue(
|
||||
salt.utils.stringutils.check_whitelist_blacklist(
|
||||
'web1',
|
||||
whitelist=set(whitelist),
|
||||
blacklist=None,
|
||||
)
|
||||
)
|
||||
self.assertTrue(
|
||||
salt.utils.stringutils.check_whitelist_blacklist(
|
||||
'web1',
|
||||
whitelist=set(whitelist),
|
||||
blacklist=set(),
|
||||
)
|
||||
)
|
||||
self.assertFalse(
|
||||
salt.utils.stringutils.check_whitelist_blacklist(
|
||||
'web5',
|
||||
whitelist=None,
|
||||
blacklist=set(blacklist),
|
||||
)
|
||||
)
|
||||
self.assertFalse(
|
||||
salt.utils.stringutils.check_whitelist_blacklist(
|
||||
'web5',
|
||||
whitelist=set(),
|
||||
blacklist=set(blacklist),
|
||||
)
|
||||
)
|
||||
self.assertTrue(
|
||||
salt.utils.stringutils.check_whitelist_blacklist(
|
||||
'web_five',
|
||||
whitelist=None,
|
||||
blacklist=set(blacklist),
|
||||
)
|
||||
)
|
||||
self.assertTrue(
|
||||
salt.utils.stringutils.check_whitelist_blacklist(
|
||||
'web_five',
|
||||
whitelist=set(),
|
||||
blacklist=set(blacklist),
|
||||
)
|
||||
)
|
||||
self.assertFalse(
|
||||
salt.utils.stringutils.check_whitelist_blacklist(
|
||||
'web5',
|
||||
whitelist=set(whitelist),
|
||||
blacklist=set(blacklist),
|
||||
)
|
||||
)
|
||||
self.assertTrue(
|
||||
salt.utils.stringutils.check_whitelist_blacklist(
|
||||
'web4',
|
||||
whitelist=set(whitelist),
|
||||
blacklist=set(blacklist),
|
||||
)
|
||||
)
|
||||
|
||||
# Test with invalid type for whitelist/blacklist
|
||||
self.assertRaises(
|
||||
TypeError,
|
||||
salt.utils.stringutils.check_whitelist_blacklist,
|
||||
'foo', whitelist=123
|
||||
)
|
||||
self.assertRaises(
|
||||
TypeError,
|
||||
salt.utils.stringutils.check_whitelist_blacklist,
|
||||
'foo', blacklist=123
|
||||
)
|
||||
|
@ -891,6 +891,17 @@ class ZfsUtilsTestCase(TestCase):
|
||||
This class contains a set of functions that test salt.utils.zfs utils
|
||||
'''
|
||||
## NOTE: test parameter parsing
|
||||
def test_is_supported(self):
|
||||
'''
|
||||
Test zfs.is_supported method
|
||||
'''
|
||||
for value in [False, True]:
|
||||
with patch('salt.utils.path.which',
|
||||
MagicMock(return_value=value)):
|
||||
with patch('salt.utils.platform.is_linux',
|
||||
MagicMock(return_value=value)):
|
||||
self.assertEqual(value, zfs.is_supported())
|
||||
|
||||
def test_property_data_zpool(self):
|
||||
'''
|
||||
Test parsing of zpool get output
|
||||
|
@ -19,6 +19,7 @@ integration.modules.test_mine
|
||||
integration.modules.test_network
|
||||
integration.modules.test_ntp
|
||||
integration.modules.test_pillar
|
||||
integration.modules.test_pip
|
||||
integration.modules.test_pkg
|
||||
integration.modules.test_publish
|
||||
integration.modules.test_service
|
||||
@ -36,6 +37,7 @@ integration.runners.test_jobs
|
||||
integration.runners.test_salt
|
||||
integration.sdb.test_env
|
||||
integration.states.test_host
|
||||
integration.states.test_pip
|
||||
integration.states.test_reg
|
||||
integration.states.test_renderers
|
||||
integration.utils.testprogram
|
||||
|
Loading…
Reference in New Issue
Block a user