Merge branch '2014.7' into merge-forward-2015.2

Conflicts:
	pkg/windows/installer/Salt-Minion-Setup.nsi
	salt/grains/core.py
	salt/minion.py
	salt/modules/mongodb.py
	salt/states/archive.py
	salt/states/mount.py
	salt/utils/master.py
	salt/utils/schedule.py
	salt/utils/thin.py
	tests/jenkins-ng.py
This commit is contained in:
Colton Myers 2015-01-06 13:14:27 -07:00
commit f6eae029f0
27 changed files with 243 additions and 1364 deletions

View file

@ -138,14 +138,14 @@ InstallDirRegKey HKLM "${PRODUCT_DIR_REGKEY}" ""
ShowInstDetails show
ShowUnInstDetails show
; Check and install Visual C++ 2008 SP1 redist packages
; Check and install Visual C++ 2008 SP1 MFC Security Update redist packages
; See http://blogs.msdn.com/b/astebner/archive/2009/01/29/9384143.aspx for more info
Section -Prerequisites
!define VC_REDIST_X64_GUID "{8220EEFE-38CD-377E-8595-13398D740ACE}"
!define VC_REDIST_X86_GUID "{9A25302D-30C0-39D9-BD6F-21E6EC160475}"
!define VC_REDIST_X64_URI "http://download.microsoft.com/download/2/d/6/2d61c766-107b-409d-8fba-c39e61ca08e8/vcredist_x64.exe"
!define VC_REDIST_X86_URI "http://download.microsoft.com/download/d/d/9/dd9a82d0-52ef-40db-8dab-795376989c03/vcredist_x86.exe"
!define VC_REDIST_X64_GUID "{5FCE6D76-F5DC-37AB-B2B8-22AB8CEDB1D4}"
!define VC_REDIST_X86_GUID "{9BE518E6-ECC6-35A9-88E4-87755C07200F}"
!define VC_REDIST_X64_URI "http://download.microsoft.com/download/5/D/8/5D8C65CB-C849-4025-8E95-C3966CAFD8AE/vcredist_x64.exe"
!define VC_REDIST_X86_URI "http://download.microsoft.com/download/5/D/8/5D8C65CB-C849-4025-8E95-C3966CAFD8AE/vcredist_x86.exe"
Var /GLOBAL VcRedistGuid
Var /GLOBAL VcRedistUri

View file

@ -18,6 +18,7 @@ except ImportError:
# In case a non-master needs to import this module
pass
import tempfile
# Import salt libs
import salt.crypt
@ -687,12 +688,15 @@ class RemoteFuncs(object):
if not os.path.isdir(cdir):
os.makedirs(cdir)
datap = os.path.join(cdir, 'data.p')
with salt.utils.fopen(datap, 'w+b') as fp_:
tmpfh, tmpfname = tempfile.mkstemp(dir=cdir)
os.close(tmpfh)
with salt.utils.fopen(tmpfname, 'w+b') as fp_:
fp_.write(
self.serial.dumps(
{'grains': load['grains'],
'pillar': data})
)
os.rename(tmpfname, datap)
return data
def _minion_event(self, load):

View file

@ -348,7 +348,7 @@ def _sunos_cpudata():
grains['cpuarch'] = __salt__['cmd.run']('uname -p')
psrinfo = '/usr/sbin/psrinfo 2>/dev/null'
grains['num_cpus'] = len(__salt__['cmd.run'](psrinfo).splitlines())
grains['num_cpus'] = len(__salt__['cmd.run'](psrinfo, python_shell=True).splitlines())
kstat_info = 'kstat -p cpu_info:0:*:brand'
for line in __salt__['cmd.run'](kstat_info).splitlines():
match = re.match(r'(\w+:\d+:\w+\d+:\w+)\s+(.+)', line)
@ -394,7 +394,7 @@ def _memdata(osdata):
grains['mem_total'] = int(mem) / 1024 / 1024
elif osdata['kernel'] == 'SunOS':
prtconf = '/usr/sbin/prtconf 2>/dev/null'
for line in __salt__['cmd.run'](prtconf).splitlines():
for line in __salt__['cmd.run'](prtconf, python_shell=True).splitlines():
comps = line.split(' ')
if comps[0].strip() == 'Memory' and comps[1].strip() == 'size:':
grains['mem_total'] = int(comps[2].strip())
@ -1691,7 +1691,7 @@ def _smartos_zone_data():
grains['pkgsrcpath'] = 'Unknown'
grains['zonename'] = __salt__['cmd.run']('zonename')
grains['zoneid'] = __salt__['cmd.run']('zoneadm list -p').split()[1]
grains['zoneid'] = __salt__['cmd.run']('zoneadm list -p | awk -F: \'{ print $1 }\'', python_shell=True)
grains['hypervisor_uuid'] = __salt__['cmd.run']('mdata-get sdc:server_uuid')
grains['datacenter'] = __salt__['cmd.run']('mdata-get sdc:datacenter_name')
if "FAILURE" in grains['datacenter'] or "No metadata" in grains['datacenter']:

View file

@ -17,6 +17,7 @@ import hashlib
import resource
import multiprocessing
import sys
import tempfile
# Import third party libs
import zmq
@ -1220,12 +1221,15 @@ class AESFuncs(object):
if not os.path.isdir(cdir):
os.makedirs(cdir)
datap = os.path.join(cdir, 'data.p')
with salt.utils.fopen(datap, 'w+b') as fp_:
tmpfh, tmpfname = tempfile.mkstemp(dir=cdir)
os.close(tmpfh)
with salt.utils.fopen(tmpfname, 'w+b') as fp_:
fp_.write(
self.serial.dumps(
{'grains': load['grains'],
'pillar': data})
)
os.rename(tmpfname, datap)
for mod in mods:
sys.modules[mod].__grains__ = self.opts['grains']
return data
@ -1788,11 +1792,20 @@ class ClearFuncs(object):
log.info('Authentication accepted from {id}'.format(**load))
# only write to disk if you are adding the file, and in open mode,
# which implies we accept any key from a minion (key needs to be
# written every time because what's on disk is used for encrypting)
if not os.path.isfile(pubfn) or self.opts['open_mode']:
# which implies we accept any key from a minion.
if not os.path.isfile(pubfn) and not self.opts['open_mode']:
with salt.utils.fopen(pubfn, 'w+') as fp_:
fp_.write(load['pub'])
elif self.opts['open_mode']:
disk_key = ''
if os.path.isfile(pubfn):
with salt.utils.fopen(pubfn, 'r') as fp_:
disk_key = fp_.read()
if load['pub'] and load['pub'] != disk_key:
log.debug('Host key change detected in open mode.')
with salt.utils.fopen(pubfn, 'w+') as fp_:
fp_.write(load['pub'])
pub = None
# the con_cache is enabled, send the minion id to the cache

View file

@ -592,6 +592,7 @@ class Minion(MinionBase):
Pass in the options dict
'''
self._running = None
self.win_proc = []
# Warn if ZMQ < 3.2
if HAS_ZMQ:
@ -1017,6 +1018,8 @@ class Minion(MinionBase):
process.start()
if not sys.platform.startswith('win'):
process.join()
else:
self.win_proc.append(process)
@classmethod
def _thread_return(cls, minion_instance, opts, data):
@ -1662,6 +1665,21 @@ class Minion(MinionBase):
log.debug('Forwarding salt error event tag={tag}'.format(tag=tag))
self._fire_master(data, tag)
def _windows_thread_cleanup(self):
'''
Cleanup Windows threads
'''
if not salt.utils.is_windows():
return
for thread in self.win_proc:
if not thread.is_alive():
thread.join()
try:
self.win_proc.remove(thread)
del thread
except (ValueError, NameError):
pass
# Main Minion Tune In
def tune_in(self):
'''
@ -1727,6 +1745,7 @@ class Minion(MinionBase):
while self._running is True:
loop_interval = self.process_schedule(self, loop_interval)
self._windows_thread_cleanup()
try:
socks = self._do_poll(loop_interval)

View file

@ -17,6 +17,7 @@ import shutil
import subprocess
import sys
import traceback
import shlex
from salt.utils import vt
# Import salt libs
@ -360,6 +361,8 @@ def _run(cmd,
.format(cwd)
)
if python_shell is not True and not isinstance(cmd, list):
cmd = shlex.split(cmd)
if not use_vt:
# This is where the magic happens
try:

View file

@ -18,6 +18,7 @@ from __future__ import absolute_import
# Import python libs
import logging
import json
from distutils.version import StrictVersion # pylint: disable=import-error,no-name-in-module
# Import salt libs
from salt.ext.six import string_types
@ -144,7 +145,7 @@ def user_list(user=None, password=None, host=None, port=None, database='admin'):
.. code-block:: bash
salt '*' mongodb.user_list <name> <user> <password> <host> <port> <database>
salt '*' mongodb.user_list <user> <password> <host> <port> <database>
'''
conn = _connect(user, password, host, port)
if not conn:
@ -155,12 +156,20 @@ def user_list(user=None, password=None, host=None, port=None, database='admin'):
mdb = pymongo.database.Database(conn, database)
output = []
mongodb_version = mdb.eval('db.version()')
for user in mdb.system.users.find():
output.append([
('user', user['user']),
('readOnly', user.get('readOnly', 'None'))
])
if StrictVersion(mongodb_version) >= StrictVersion('2.6'):
for user in mdb.eval('db.getUsers()'):
output.append([
('user', user['user']),
('roles', user['roles'])
])
else:
for user in mdb.system.users.find():
output.append([
('user', user['user']),
('readOnly', user.get('readOnly', 'None'))
])
return output
except pymongo.errors.PyMongoError as err:

View file

@ -465,7 +465,7 @@ def mkpart(device, part_type, fs_type=None, start=None, end=None):
.. code-block:: bash
salt '*' partition.mkpart /dev/sda primary fat32 0 639
salt '*' partition.mkpart /dev/sda primary fs_type=fat32 start=0 end=639
salt '*' partition.mkpart /dev/sda primary start=0 end=639
'''
_validate_device(device)

View file

@ -16,14 +16,14 @@ The following grains/pillar should be set:
tomcat-manager:
user: <username>
password: <passwd>
passwd: <password>
or the old format:
.. code-block:: yaml
tomcat-manager.user: <username>
tomcat-manager.password: <passwd>
tomcat-manager.passwd: <password>
Also configure a user in the conf/tomcat-users.xml file:

View file

@ -444,24 +444,22 @@ class Compiler(object):
continue
chunk_order = chunk['order']
if 'name_order' in chunk:
chunk_order = chunk_order + chunk['name_order']
if chunk_order > cap - 1 and chunk_order > 0:
cap = chunk_order + 100
for chunk in chunks:
if 'order' not in chunk:
chunk['order'] = cap
else:
if isinstance(chunk['order'], int) and 'name_order' in chunk:
chunk['order'] = chunk['order'] + chunk.pop('name_order')
if not isinstance(chunk['order'], int):
if chunk['order'] == 'last':
chunk['order'] = cap + 1000000
else:
chunk['order'] = cap
elif isinstance(chunk['order'], int) and chunk['order'] < 0:
chunk['order'] = cap + 1000000 + chunk['order']
continue
if not isinstance(chunk['order'], (int, float)):
if chunk['order'] == 'last':
chunk['order'] = cap + 1000000
else:
chunk['order'] = cap
if 'name_order' in chunk:
chunk['order'] = chunk['order'] + chunk.pop('name_order') / 10000.0
if chunk['order'] < 0:
chunk['order'] = cap + 1000000 + chunk['order']
chunks.sort(key=lambda chunk: (chunk['order'], '{0[state]}{0[name]}{0[fun]}'.format(chunk)))
return chunks
@ -1052,25 +1050,23 @@ class State(object):
continue
chunk_order = chunk['order']
if 'name_order' in chunk:
chunk_order = chunk_order + chunk['name_order']
if chunk_order > cap - 1 and chunk_order > 0:
cap = chunk_order + 100
for chunk in chunks:
if 'order' not in chunk:
chunk['order'] = cap
else:
if isinstance(chunk['order'], int) and 'name_order' in chunk:
chunk['order'] = chunk['order'] + chunk.pop('name_order')
if not isinstance(chunk['order'], int):
if chunk['order'] == 'last':
chunk['order'] = cap + 1000000
else:
chunk['order'] = cap
elif isinstance(chunk['order'], int) and chunk['order'] < 0:
chunk['order'] = cap + 1000000 + chunk['order']
chunks.sort(key=lambda k: (k['order'], '{0[state]}{0[name]}{0[fun]}'.format(k)))
continue
if not isinstance(chunk['order'], (int, float)):
if chunk['order'] == 'last':
chunk['order'] = cap + 1000000
else:
chunk['order'] = cap
if 'name_order' in chunk:
chunk['order'] = chunk['order'] + chunk.pop('name_order') / 10000.0
if chunk['order'] < 0:
chunk['order'] = cap + 1000000 + chunk['order']
chunks.sort(key=lambda chunk: (chunk['order'], '{0[state]}{0[name]}{0[fun]}'.format(chunk)))
return chunks
def compile_high_data(self, high):

View file

@ -197,13 +197,13 @@ def extracted(name,
else:
log.debug('Untar {0} in {1}'.format(filename, name))
results = __salt__['cmd.run_all']('tar x{0} -f {1!r}'.format(
tar_options, filename), cwd=name, runas=archive_user)
tar_cmd = ['tar', 'x{0}'.format(tar_options), '-f', repr(filename)]
results = __salt__['cmd.run_all'](tar_cmd, cwd=name, python_shell=False)
if results['retcode'] != 0:
ret['result'] = False
ret['changes'] = results
return ret
if __salt__['cmd.retcode']('tar --version | grep bsdtar') == 0:
if __salt__['cmd.retcode']('tar --version | grep bsdtar', python_shell=True) == 0:
files = results['stderr']
else:
files = results['stdout']

View file

@ -170,7 +170,7 @@ def change(name, context=None, changes=None, lens=None, **kwargs):
ret['result'] = None
ret['comment'] = 'Executing commands'
if context:
ret['comment'] += ' in file "{1}"'.format(context)
ret['comment'] += ' in file "{0}":\n'.format(context)
ret['comment'] += "\n".join(changes)
return ret

View file

@ -294,7 +294,7 @@ def mod_run_check(cmd_kwargs, onlyif, unless, group, creates):
if onlyif is not None:
if isinstance(onlyif, string_types):
cmd = __salt__['cmd.retcode'](onlyif, ignore_retcode=True, **cmd_kwargs)
cmd = __salt__['cmd.retcode'](onlyif, ignore_retcode=True, python_shell=True, **cmd_kwargs)
log.debug('Last command return code: {0}'.format(cmd))
if cmd != 0:
return {'comment': 'onlyif execution failed',
@ -302,7 +302,7 @@ def mod_run_check(cmd_kwargs, onlyif, unless, group, creates):
'result': True}
elif isinstance(onlyif, list):
for entry in onlyif:
cmd = __salt__['cmd.retcode'](entry, ignore_retcode=True, **cmd_kwargs)
cmd = __salt__['cmd.retcode'](entry, ignore_retcode=True, python_shell=True, **cmd_kwargs)
log.debug('Last command return code: {0}'.format(cmd))
if cmd != 0:
return {'comment': 'onlyif execution failed',
@ -317,7 +317,7 @@ def mod_run_check(cmd_kwargs, onlyif, unless, group, creates):
if unless is not None:
if isinstance(unless, string_types):
cmd = __salt__['cmd.retcode'](unless, ignore_retcode=True, **cmd_kwargs)
cmd = __salt__['cmd.retcode'](unless, ignore_retcode=True, python_shell=True, **cmd_kwargs)
log.debug('Last command return code: {0}'.format(cmd))
if cmd == 0:
return {'comment': 'unless execution succeeded',
@ -325,7 +325,7 @@ def mod_run_check(cmd_kwargs, onlyif, unless, group, creates):
'result': True}
elif isinstance(unless, list):
for entry in unless:
cmd = __salt__['cmd.retcode'](entry, ignore_retcode=True, **cmd_kwargs)
cmd = __salt__['cmd.retcode'](entry, ignore_retcode=True, python_shell=True, **cmd_kwargs)
log.debug('Last command return code: {0}'.format(cmd))
if cmd == 0:
return {'comment': 'unless execution succeeded',
@ -709,7 +709,7 @@ def run(name,
if not __opts__['test']:
try:
cmd_all = __salt__['cmd.run_all'](
name, timeout=timeout, **cmd_kwargs
name, timeout=timeout, python_shell=True, **cmd_kwargs
)
except CommandExecutionError as err:
ret['comment'] = str(err)
@ -904,7 +904,7 @@ def script(name,
# Wow, we passed the test, run this sucker!
try:
cmd_all = __salt__['cmd.script'](source, **cmd_kwargs)
cmd_all = __salt__['cmd.script'](source, python_shell=True, **cmd_kwargs)
except (CommandExecutionError, SaltRenderError, IOError) as err:
ret['comment'] = str(err)
return ret

View file

@ -38,7 +38,6 @@ import logging
import salt.ext.six as six
log = logging.getLogger(__name__)
from salt._compat import string_types
from salt.exceptions import SaltInvocationError
def mounted(name,
@ -176,11 +175,32 @@ def mounted(name,
if uuid_device and uuid_device not in device_list:
device_list.append(uuid_device)
if opts:
mount_invisible_options = ['defaults', 'comment', 'nobootwait', 'reconnect', 'delay_connect', 'nofail']
mount_invisible_options = [
'_netdev',
'actimeo',
'bg',
'comment',
'defaults',
'delay_connect',
'intr',
'nobootwait',
'nofail',
'password',
'reconnect',
'retry',
'soft',
]
# options which are provided as key=value (e.g. password=Zohp5ohb)
mount_invisible_keys = [
'actimeo',
'comment',
'password',
'retry',
]
for opt in opts:
comment_option = opt.split('=')[0]
if comment_option == 'comment':
opt = comment_option
keyval_option = opt.split('=')[0]
if keyval_option in mount_invisible_keys:
opt = keyval_option
if opt not in active[real_name]['opts'] and opt not in active[real_name]['superopts'] and opt not in mount_invisible_options:
if __opts__['test']:
ret['result'] = None
@ -197,7 +217,9 @@ def mounted(name,
mount_result = __salt__['mount.mount'](real_name, device, mkmnt=mkmnt, fstype=fstype, opts=opts)
ret['result'] = mount_result
else:
raise SaltInvocationError('Unable to unmount {0}: {1}.'.format(real_name, unmount_result))
ret['result'] = False
ret['comment'] = 'Unable to unmount {0}: {1}.'.format(real_name, unmount_result)
return ret
else:
ret['changes']['umount'] = "Forced remount because " \
+ "options ({0}) changed".format(opt)

View file

@ -670,16 +670,16 @@ def installed(name,
if requirements or editable:
comments = []
if requirements:
for eachline in pip_install_call.get('stdout', '').split('\n'):
if not eachline.startswith('Requirement already satisfied') and eachline != 'Cleaning up...':
for line in pip_install_call.get('stdout', '').split('\n'):
if not line.startswith('Requirement already satisfied') \
and line != 'Cleaning up...':
ret['changes']['requirements'] = True
if ret['changes'].get('requirements'):
comments.append('Successfully processed requirements file '
'{0}.'.format(requirements))
else:
comments.append('Requirements was successfully installed')
comments.append('Successfully processed requirements file '
'{0}.'.format(requirements))
comments.append('Requirements were already installed.')
if editable:
comments.append('Package successfully installed from VCS '
'checkout {0}.'.format(editable))

View file

@ -226,6 +226,11 @@ class ZeroMQChannel(Channel):
@property
def sreq(self):
# When using threading, like on Windows, don't cache.
# The following block prevents thread leaks.
if not self.opts.get('multiprocessing'):
return salt.payload.SREQ(self.master_uri)
key = self.sreq_key
if not self.opts['cache_sreqs']:

View file

@ -15,6 +15,8 @@ import logging
from threading import Thread, Event
import multiprocessing
import signal
import tempfile
# Import salt libs
import salt.log
import salt.client
@ -376,11 +378,17 @@ class MasterPillarUtil(object):
# Not saving pillar or grains, so just delete the cache file
os.remove(os.path.join(data_file))
elif clear_pillar and minion_grains:
with salt.utils.fopen(data_file, 'w+b') as fp_:
tmpfh, tmpfname = tempfile.mkstemp(dir=cdir)
os.close(tmpfh)
with salt.utils.fopen(tmpfname, 'w+b') as fp_:
fp_.write(self.serial.dumps({'grains': minion_grains}))
os.rename(tmpfname, data_file)
elif clear_grains and minion_pillar:
with salt.utils.fopen(data_file, 'w+b') as fp_:
tmpfh, tmpfname = tempfile.mkstemp(dir=cdir)
os.close(tmpfh)
with salt.utils.fopen(tmpfname, 'w+b') as fp_:
fp_.write(self.serial.dumps({'pillar': minion_pillar}))
os.rename(tmpfname, data_file)
if clear_mine:
# Delete the whole mine file
os.remove(os.path.join(mine_file))
@ -390,8 +398,11 @@ class MasterPillarUtil(object):
mine_data = self.serial.loads(fp_.read())
if isinstance(mine_data, dict):
if mine_data.pop(clear_mine_func, False):
with salt.utils.fopen(mine_file, 'w+b') as fp_:
tmpfh, tmpfname = tempfile.mkstemp(dir=cdir)
os.close(tmpfh)
with salt.utils.fopen(tmpfname, 'w+b') as fp_:
fp_.write(self.serial.dumps(mine_data))
os.rename(tmpfname, mine_file)
except (OSError, IOError):
return True
return True

View file

@ -95,7 +95,7 @@ from salt.ext.six import string_types
import salt.ext.six as six
REQUISITES = set('require watch prereq use require_in watch_in prereq_in use_in onchanges onfail'.split())
REQUISITES = set('listen require watch prereq use listen_in require_in watch_in prereq_in use_in onchanges onfail'.split())
class PyDslError(Exception):

View file

@ -12,7 +12,7 @@ import logging
from salt.utils.odict import OrderedDict
import salt.ext.six as six
REQUISITES = ('require', 'watch', 'use', 'require_in', 'watch_in', 'use_in')
REQUISITES = ('listen', 'require', 'watch', 'use', 'listen_in', 'require_in', 'watch_in', 'use_in')
log = logging.getLogger(__name__)

View file

@ -645,7 +645,7 @@ class Schedule(object):
log.error('Invalid date string {0}.'
'Ignoring job {1}.'.format(i, job))
continue
when = int(when__.strftime('%s'))
when = int(time.mktime(when__.timetuple()))
if when >= now:
_when.append(when)
_when.sort()
@ -710,7 +710,7 @@ class Schedule(object):
except ValueError:
log.error('Invalid date string. Ignoring')
continue
when = int(when__.strftime('%s'))
when = int(time.mktime(when__.timetuple()))
now = int(time.time())
seconds = when - now
@ -735,7 +735,7 @@ class Schedule(object):
log.error('Missing python-croniter. Ignoring job {0}'.format(job))
continue
now = int(datetime.datetime.now().strftime('%s'))
now = int(time.mktime(datetime.datetime.now().timetuple()))
try:
cron = int(croniter.croniter(data['cron'], now).get_next())
except (ValueError, KeyError):
@ -808,12 +808,12 @@ class Schedule(object):
else:
if isinstance(data['range'], dict):
try:
start = int(dateutil_parser.parse(data['range']['start']).strftime('%s'))
start = int(time.mktime(dateutil_parser.parse(data['range']['start']).timetuple()))
except ValueError:
log.error('Invalid date string for start. Ignoring job {0}.'.format(job))
continue
try:
end = int(dateutil_parser.parse(data['range']['end']).strftime('%s'))
end = int(time.mktime(dateutil_parser.parse(data['range']['end']).timetuple()))
except ValueError:
log.error('Invalid date string for end. Ignoring job {0}.'.format(job))
continue
@ -901,7 +901,9 @@ def clean_proc_dir(opts):
with salt.utils.fopen(fn_, 'rb') as fp_:
job = None
try:
job = salt.payload.Serial(opts).load(fp_)
job_data = fp_.read()
if job_data:
job = salt.payload.Serial(opts).load(fp_)
except Exception: # It's corrupted
try:
os.unlink(fn_)

View file

@ -56,6 +56,17 @@ except ImportError:
# Older jinja does not need markupsafe
HAS_MARKUPSAFE = False
# pylint: enable=import-error,no-name-in-module
try:
# Older python where the backport from pypi is installed
from backports import ssl_match_hostname
HAS_SSL_MATCH_HOSTNAME = True
except ImportError:
# Other older python we use our bundled copy
try:
from requests.packages.urllib3.packages import ssl_match_hostname
HAS_SSL_MATCH_HOSTNAME = True
except ImportError:
HAS_SSL_MATCH_HOSTNAME = False
# Import salt libs
import salt
@ -127,6 +138,9 @@ def gen_thin(cachedir, extra_mods='', overwrite=False, so_mods=''):
if HAS_CERTIFI:
tops.append(os.path.dirname(certifi.__file__))
if HAS_SSL_MATCH_HOSTNAME:
tops.append(os.path.dirname(os.path.dirname(ssl_match_hostname.__file__)))
for mod in [m for m in extra_mods.split(',') if m]:
if mod not in locals() and mod not in globals():
try:

View file

@ -43,8 +43,7 @@ class CMDModuleTest(integration.ModuleCase):
self.assertEqual(
self.run_function('cmd.run',
['echo $SHELL',
'shell={0}'.format(shell)]).rstrip(),
shell)
'shell={0}'.format(shell)], python_shell=True).rstrip(), shell)
@patch('pwd.getpwnam')
@patch('subprocess.Popen')
@ -104,7 +103,7 @@ class CMDModuleTest(integration.ModuleCase):
self.assertEqual(self.run_function('cmd.run_stderr',
['echo "cheese" 1>&2',
'shell={0}'.format(shell)]
'shell={0}'.format(shell)], python_shell=True
).rstrip(),
'cheese')
@ -120,7 +119,7 @@ class CMDModuleTest(integration.ModuleCase):
shell = '/bin/bash'
ret = self.run_function('cmd.run_all', ['echo "cheese" 1>&2',
'shell={0}'.format(shell)])
'shell={0}'.format(shell)], python_shell=True)
self.assertTrue('pid' in ret)
self.assertTrue('retcode' in ret)
self.assertTrue('stdout' in ret)
@ -135,8 +134,8 @@ class CMDModuleTest(integration.ModuleCase):
'''
cmd.retcode
'''
self.assertEqual(self.run_function('cmd.retcode', ['exit 0']), 0)
self.assertEqual(self.run_function('cmd.retcode', ['exit 1']), 1)
self.assertEqual(self.run_function('cmd.retcode', ['exit 0'], python_shell=True), 0)
self.assertEqual(self.run_function('cmd.retcode', ['exit 1'], python_shell=True), 1)
@skip_if_binaries_missing(['which'])
def test_which(self):
@ -200,9 +199,11 @@ sys.stdout.write('cheese')
'''
cmd.run trigger timeout
'''
out = self.run_function('cmd.run', ['sleep 2 && echo hello', 'timeout=1'])
self.assertTrue(
'Timed out' in self.run_function(
'cmd.run', ['sleep 2 && echo hello', 'timeout=1']))
'cmd.run', ['sleep 2 && echo hello', 'timeout=1'], python_shell=True))
def test_timeout_success(self):
'''
@ -210,7 +211,7 @@ sys.stdout.write('cheese')
'''
self.assertTrue(
'hello' == self.run_function(
'cmd.run', ['sleep 1 && echo hello', 'timeout=2']))
'cmd.run', ['sleep 1 && echo hello', 'timeout=2'], python_shell=True))
def test_run_cwd_doesnt_exist_issue_7154(self):
'''

View file

@ -390,7 +390,7 @@ class PipStateTest(integration.ModuleCase, integration.SaltReturnAssertsMixIn):
reqf.write('pep8\n')
try:
ret = self.run_function('virtualenv.create', [venv_dir])
self.run_function('virtualenv.create', [venv_dir])
# The requirements file should not be found the base environment
ret = self.run_state(
@ -421,8 +421,8 @@ class PipStateTest(integration.ModuleCase, integration.SaltReturnAssertsMixIn):
)
self.assertSaltTrueReturn(ret)
self.assertInSaltComment(
'Successfully processed requirements file '
'salt://prod-env-requirements.txt', ret
'Requirements were already installed.',
ret
)
finally:
if os.path.isdir(venv_dir):

File diff suppressed because it is too large Load diff

View file

@ -439,7 +439,6 @@ class CpTestCase(TestCase):
mock_buf_size = len(file_data)
mock_id = 'You don\'t need to see his identification.'
ret = None
from time import sleep
class MockChannel(object):
@staticmethod
@ -474,7 +473,6 @@ class CpTestCase(TestCase):
mock_buf_size = len(file_data)
mock_id = 'You don\'t need to see his identification.'
ret = True
from time import sleep
class MockChannel(object):
@staticmethod

View file

@ -0,0 +1,49 @@
# -*- coding: utf-8 -*-
'''
:codeauthor: Nitin Madhok <nmadhok@clemson.edu>`
tests.unit.modules.zpool_test
~~~~~~~~~~~~~~~~~~~~~~~~~~~
'''
# Import Salt Testing libs
from salttesting import skipIf, TestCase
from salttesting.helpers import ensure_in_syspath
# Import Mock libraries
from salttesting.mock import (
MagicMock,
patch,
NO_MOCK,
NO_MOCK_REASON,
)
ensure_in_syspath('../../')
# Import Salt Execution module to test
from salt.modules import zpool
# Globals
zpool.__salt__ = {}
# Skip this test case if we don't have access to mock!
@skipIf(NO_MOCK, NO_MOCK_REASON)
class ZpoolTestCase(TestCase):
'''
This class contains a set of functions that test salt.modules.zpool module
'''
@patch('salt.modules.zpool._check_zpool', MagicMock(return_value='/sbin/zpool'))
def test_exists_success(self):
'''
Tests successful return of exists function
'''
ret = "NAME SIZE ALLOC FREE CAP DEDUP HEALTH ALTROOT\nmyzpool 149G 128K 149G 0% 1.00x ONLINE -"
mock_cmd = MagicMock(return_value=ret)
with patch.dict(zpool.__salt__, {'cmd.run': mock_cmd}):
self.assertTrue(zpool.exists('myzpool'))
if __name__ == '__main__':
from integration import run_tests
run_tests(ZpoolTestCase, needs_daemon=False)

View file

@ -14,6 +14,7 @@ import os
import sys
import random
import subprocess
import time
# Import Salt Testing libs
from salttesting import TestCase, skipIf
@ -184,6 +185,8 @@ class VTTestCase(TestCase):
if buffer_o != expected_data:
self.assertTrue(term.isalive())
# Don't spin
time.sleep(0.1)
# term should be dead now
self.assertEqual(buffer_o, expected_data)