mirror of
https://github.com/saltstack/salt.git
synced 2025-04-17 10:10:20 +00:00
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:
commit
f6eae029f0
27 changed files with 243 additions and 1364 deletions
|
@ -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
|
||||
|
|
|
@ -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):
|
||||
|
|
|
@ -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']:
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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:
|
||||
|
||||
|
|
|
@ -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):
|
||||
|
|
|
@ -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']
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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']:
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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):
|
||||
|
|
|
@ -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__)
|
||||
|
||||
|
|
|
@ -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_)
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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):
|
||||
'''
|
||||
|
|
|
@ -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):
|
||||
|
|
1270
tests/jenkins-ng.py
1270
tests/jenkins-ng.py
File diff suppressed because it is too large
Load diff
|
@ -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
|
||||
|
|
49
tests/unit/modules/zpool_test.py
Normal file
49
tests/unit/modules/zpool_test.py
Normal 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)
|
|
@ -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)
|
||||
|
|
Loading…
Add table
Reference in a new issue