Merge pull request #38529 from rallytime/merge-2016.11

[2016.11] Merge forward from 2016.3 to 2016.11
This commit is contained in:
Mike Place 2017-01-04 10:06:56 -07:00 committed by GitHub
commit 1895eb7533
17 changed files with 157 additions and 83 deletions

View File

@ -357,7 +357,7 @@ class Key(object):
REJ = 'minions_rejected'
DEN = 'minions_denied'
def __init__(self, opts):
def __init__(self, opts, io_loop=None):
self.opts = opts
kind = self.opts.get('__role', '') # application kind
if kind not in salt.utils.kinds.APPL_KINDS:
@ -369,7 +369,9 @@ class Key(object):
opts['sock_dir'],
opts['transport'],
opts=opts,
listen=False)
listen=False,
io_loop=io_loop
)
def _check_minions_directories(self):
'''

View File

@ -248,14 +248,14 @@ def list_(narrow=None,
if narrow:
cmd.append(narrow)
if salt.utils.is_true(all_versions):
cmd.append('-allversions')
cmd.append('--allversions')
if salt.utils.is_true(pre_versions):
cmd.append('-prerelease')
cmd.append('--prerelease')
if source:
cmd.extend(['-source', source])
cmd.extend(['--source', source])
if local_only:
cmd.extend(['-localonly'])
cmd.extend(['-limitoutput'])
cmd.extend(['--localonly'])
cmd.extend(['--limitoutput'])
result = __salt__['cmd.run_all'](cmd, python_shell=False)
@ -292,7 +292,7 @@ def list_webpi():
salt '*' chocolatey.list_webpi
'''
choc_path = _find_chocolatey(__context__, __salt__)
cmd = [choc_path, 'list', '-source', 'webpi']
cmd = [choc_path, 'list', '--source', 'webpi']
result = __salt__['cmd.run_all'](cmd, python_shell=False)
if result['retcode'] != 0:
@ -318,7 +318,7 @@ def list_windowsfeatures():
salt '*' chocolatey.list_windowsfeatures
'''
choc_path = _find_chocolatey(__context__, __salt__)
cmd = [choc_path, 'list', '-source', 'windowsfeatures']
cmd = [choc_path, 'list', '--source', 'windowsfeatures']
result = __salt__['cmd.run_all'](cmd, python_shell=False)
if result['retcode'] != 0:
@ -398,23 +398,25 @@ def install(name,
'''
choc_path = _find_chocolatey(__context__, __salt__)
# chocolatey helpfully only supports a single package argument
# CORRECTION: it also supports multiple package names separated by spaces
# but any additional arguments apply to ALL packages specified
cmd = [choc_path, 'install', name]
if version:
cmd.extend(['-version', version])
cmd.extend(['--version', version])
if source:
cmd.extend(['-source', source])
cmd.extend(['--source', source])
if salt.utils.is_true(force):
cmd.append('-force')
cmd.append('--force')
if salt.utils.is_true(pre_versions):
cmd.append('-prerelease')
cmd.append('--prerelease')
if install_args:
cmd.extend(['-installarguments', install_args])
cmd.extend(['--installarguments', install_args])
if override_args:
cmd.append('-overridearguments')
cmd.append('--overridearguments')
if force_x86:
cmd.append('-forcex86')
cmd.append('--forcex86')
if package_args:
cmd.extend(['-packageparameters', package_args])
cmd.extend(['--packageparameters', package_args])
cmd.extend(_yes(__context__))
result = __salt__['cmd.run_all'](cmd, python_shell=False)
@ -530,9 +532,9 @@ def install_missing(name, version=None, source=None):
# chocolatey helpfully only supports a single package argument
cmd = [choc_path, 'installmissing', name]
if version:
cmd.extend(['-version', version])
cmd.extend(['--version', version])
if source:
cmd.extend(['-source', source])
cmd.extend(['--source', source])
# Shouldn't need this as this code should never run on v0.9.9 and newer
cmd.extend(_yes(__context__))
result = __salt__['cmd.run_all'](cmd, python_shell=False)
@ -658,11 +660,11 @@ def uninstall(name, version=None, uninstall_args=None, override_args=False):
# chocolatey helpfully only supports a single package argument
cmd = [choc_path, 'uninstall', name]
if version:
cmd.extend(['-version', version])
cmd.extend(['--version', version])
if uninstall_args:
cmd.extend(['-uninstallarguments', uninstall_args])
cmd.extend(['--uninstallarguments', uninstall_args])
if override_args:
cmd.extend(['-overridearguments'])
cmd.extend(['--overridearguments'])
cmd.extend(_yes(__context__))
result = __salt__['cmd.run_all'](cmd, python_shell=False)
@ -741,19 +743,19 @@ def upgrade(name,
if version:
cmd.extend(['-version', version])
if source:
cmd.extend(['-source', source])
cmd.extend(['--source', source])
if salt.utils.is_true(force):
cmd.append('-force')
cmd.append('--force')
if salt.utils.is_true(pre_versions):
cmd.append('-prerelease')
cmd.append('--prerelease')
if install_args:
cmd.extend(['-installarguments', install_args])
cmd.extend(['--installarguments', install_args])
if override_args:
cmd.append('-overridearguments')
cmd.append('--overridearguments')
if force_x86:
cmd.append('-forcex86')
cmd.append('--forcex86')
if package_args:
cmd.extend(['-packageparameters', package_args])
cmd.extend(['--packageparameters', package_args])
cmd.extend(_yes(__context__))
result = __salt__['cmd.run_all'](cmd, python_shell=False)
@ -796,9 +798,9 @@ def update(name, source=None, pre_versions=False):
cmd = [choc_path, 'update', name]
if source:
cmd.extend(['-source', source])
cmd.extend(['--source', source])
if salt.utils.is_true(pre_versions):
cmd.append('-prerelease')
cmd.append('--prerelease')
cmd.extend(_yes(__context__))
result = __salt__['cmd.run_all'](cmd, python_shell=False)
@ -844,11 +846,11 @@ def version(name, check_remote=False, source=None, pre_versions=False):
cmd = [choc_path, 'list', name]
if not salt.utils.is_true(check_remote):
cmd.append('-localonly')
cmd.append('--localonly')
if salt.utils.is_true(pre_versions):
cmd.append('-prerelease')
cmd.append('--prerelease')
if source:
cmd.extend(['-source', source])
cmd.extend(['--source', source])
result = __salt__['cmd.run_all'](cmd, python_shell=False)
@ -861,7 +863,7 @@ def version(name, check_remote=False, source=None, pre_versions=False):
res = result['stdout'].split('\n')
ver_re = re.compile(r'(\S+)\s+(.+)')
ver_re = re.compile(r'(\S+)\|(.+)')
for line in res:
if 'packages found' not in line and 'packages installed' not in line:
for name, ver in ver_re.findall(line):
@ -896,11 +898,11 @@ def add_source(name, source_location, username=None, password=None):
'''
choc_path = _find_chocolatey(__context__, __salt__)
cmd = [choc_path, 'sources', 'add', '-name', name, "-source", source_location]
cmd = [choc_path, 'sources', 'add', '--name', name, '--source', source_location]
if username:
cmd.extend(['-u', username])
cmd.extend(['--user', username])
if password:
cmd.extend(['-p', password])
cmd.extend(['--password', password])
result = __salt__['cmd.run_all'](cmd, python_shell=False)
if result['retcode'] != 0:
@ -923,7 +925,7 @@ def _change_source_state(name, state):
'''
choc_path = _find_chocolatey(__context__, __salt__)
cmd = [choc_path, 'source', state, "-name", name]
cmd = [choc_path, 'source', state, '--name', name]
result = __salt__['cmd.run_all'](cmd, python_shell=False)
if result['retcode'] != 0:

View File

@ -339,9 +339,16 @@ def list_tab(user):
comment = comment_line
else:
comment += '\n' + comment_line
elif len(line.split()) > 5:
elif line.find('=') > 0 and (' ' not in line or line.index('=') < line.index(' ')):
# Appears to be a ENV setup line
comps = line.split('=', 1)
dat = {}
dat['name'] = comps[0]
dat['value'] = comps[1]
ret['env'].append(dat)
elif len(line.split(' ')) > 5:
# Appears to be a standard cron line
comps = line.split()
comps = line.split(' ')
dat = {'minute': comps[0],
'hour': comps[1],
'daymonth': comps[2],
@ -357,13 +364,6 @@ def list_tab(user):
identifier = None
comment = None
commented_cron_job = False
elif line.find('=') > 0:
# Appears to be a ENV setup line
comps = line.split('=')
dat = {}
dat['name'] = comps[0]
dat['value'] = ' '.join(comps[1:])
ret['env'].append(dat)
else:
ret['pre'].append(line)
return ret

View File

@ -51,6 +51,7 @@ import salt.utils.atomicfile
import salt.utils.find
import salt.utils.filebuffer
import salt.utils.files
import salt.utils.locales
import salt.utils.templates
import salt.utils.url
from salt.exceptions import CommandExecutionError, SaltInvocationError, get_error_message as _get_error_message
@ -1676,17 +1677,15 @@ def line(path, content, match=None, mode=None, location=None,
before = _regex_to_static(body, before)
match = _regex_to_static(body, match)
if mode == 'delete':
if os.stat(path).st_size == 0 and mode in ('delete', 'replace'):
log.warning('Cannot find text to {0}. File \'{1}\' is empty.'.format(mode, path))
body = ''
elif mode == 'delete':
body = os.linesep.join([line for line in body.split(os.linesep) if line.find(match) < 0])
elif mode == 'replace':
if os.stat(path).st_size == 0:
log.warning('Cannot find text to replace. File \'{0}\' is empty.'.format(path))
body = ''
else:
body = os.linesep.join([(_get_line_indent(file_line, content, indent)
if (file_line.find(match) > -1 and not file_line == content) else file_line)
for file_line in body.split(os.linesep)])
body = os.linesep.join([(_get_line_indent(file_line, content, indent)
if (file_line.find(match) > -1 and not file_line == content) else file_line)
for file_line in body.split(os.linesep)])
elif mode == 'insert':
if not location and not before and not after:
raise CommandExecutionError('On insert must be defined either "location" or "before/after" conditions.')
@ -4592,12 +4591,12 @@ def manage_file(name,
# Only test the checksums on files with managed contents
if source and not (not follow_symlinks and os.path.islink(real_name)):
name_sum = get_hash(real_name, source_sum['hash_type'])
name_sum = get_hash(real_name, source_sum.get('hash_type', __opts__.get('hash_type', 'md5')))
else:
name_sum = None
# Check if file needs to be replaced
if source and (name_sum is None or source_sum['hsum'] != name_sum):
if source and (name_sum is None or source_sum.get('hsum', __opts__.get('hash_type', 'md5')) != name_sum):
if not sfn:
sfn = __salt__['cp.cache_file'](source, saltenv)
if not sfn:
@ -4740,7 +4739,9 @@ def manage_file(name,
ret['comment'] = 'File {0} updated'.format(name)
elif not ret['changes'] and ret['result']:
ret['comment'] = u'File {0} is in the correct state'.format(name)
ret['comment'] = u'File {0} is in the correct state'.format(
salt.utils.locales.sdecode(name)
)
if sfn:
__clean_tmp(sfn)
return ret

View File

@ -35,7 +35,7 @@ def useradd_all(pwfile, user, password, opts='', runas=None):
Add a user to htpasswd file using the htpasswd command. If the htpasswd
file does not exist, it will be created.
.. deprecated:: Nitrogen
.. deprecated:: 2016.3.0
pwfile
Path to htpasswd file

View File

@ -1,6 +1,8 @@
# -*- coding: utf-8 -*-
'''
Virtual machine image management tools
.. deprecated:: 2016.3.0
'''
# Import python libs

View File

@ -233,7 +233,12 @@ def persist(name, value, config=None):
if str(running[name]) != str(value):
assign(name, value)
return 'Updated'
return 'Already set'
else:
return 'Already set'
# It is missing from the running config. We can not set it.
else:
raise CommandExecutionError('sysctl {0} does not exist'.format(name))
nlines.append('{0} = {1}\n'.format(name, value))
edited = True
continue

View File

@ -97,7 +97,7 @@ def rescan_all(host):
.. code-block:: bash
salt '*' scsi.rescan_all(0)
salt '*' scsi.rescan_all 0
'''
if os.path.isdir('/sys/class/scsi_host/host{0}'.format(host)):
cmd = 'echo "- - -" > /sys/class/scsi_host/host{0}/scan'.format(host)

View File

@ -244,7 +244,7 @@ def get_macs(domain):
# Deprecated aliases
def create(domain):
'''
.. deprecated:: Nitrogen
.. deprecated:: 2016.3.0
Use :py:func:`~salt.modules.virt.start` instead.
Start a defined domain
@ -261,7 +261,7 @@ def create(domain):
def destroy(domain):
'''
.. deprecated:: Nitrogen
.. deprecated:: 2016.3.0
Use :py:func:`~salt.modules.virt.stop` instead.
Power off a defined domain
@ -278,7 +278,7 @@ def destroy(domain):
def list_vms():
'''
.. deprecated:: Nitrogen
.. deprecated:: 2016.3.0
Use :py:func:`~salt.modules.virt.list_domains` instead.
List all virtual machines.

View File

@ -380,7 +380,7 @@ def get_resource_path(venv,
package_or_requirement
Name of the package in which the resource resides
.. deprecated:: Nitrogen
.. deprecated:: 2016.3.0
Use ``package`` instead.
resource
@ -391,7 +391,7 @@ def get_resource_path(venv,
resource_name
Name of the resource of which the path is to be returned
.. deprecated:: Nitrogen
.. deprecated:: 2016.3.0
.. versionadded:: 2015.5.0
@ -471,7 +471,7 @@ def get_resource_content(venv,
package_or_requirement
Name of the package in which the resource resides
.. deprecated:: Nitrogen
.. deprecated:: 2016.3.0
Use ``package`` instead.
resource
@ -482,7 +482,7 @@ def get_resource_content(venv,
resource_name
Name of the resource of which the content is to be returned
.. deprecated:: Nitrogen
.. deprecated:: 2016.3.0
.. versionadded:: 2015.5.0

View File

@ -931,7 +931,7 @@ def vm_diskstats(vm_=None):
# Deprecated aliases
def create(domain):
'''
.. deprecated:: Nitrogen
.. deprecated:: 2016.3.0
Use :py:func:`~salt.modules.virt.start` instead.
Start a defined domain
@ -948,7 +948,7 @@ def create(domain):
def destroy(domain):
'''
.. deprecated:: Nitrogen
.. deprecated:: 2016.3.0
Use :py:func:`~salt.modules.virt.stop` instead.
Power off a defined domain
@ -965,7 +965,7 @@ def destroy(domain):
def list_vms():
'''
.. deprecated:: Nitrogen
.. deprecated:: 2016.3.0
Use :py:func:`~salt.modules.virt.list_domains` instead.
List all virtual machines.

View File

@ -464,7 +464,7 @@ def info_available(*names, **kwargs):
def info(*names, **kwargs):
'''
.. deprecated:: Nitrogen
.. deprecated:: 2016.3.0
Use :py:func:`~salt.modules.pkg.info_available` instead.
Return the information of the named package available for the system.

View File

@ -1647,8 +1647,9 @@ class State(object):
Call a state directly with the low data structure, verify data
before processing.
'''
start_time = datetime.datetime.now()
log.info('Running state [{0}] at time {1}'.format(low['name'], start_time.time().isoformat()))
utc_start_time = datetime.datetime.utcnow()
local_start_time = utc_start_time - (datetime.datetime.utcnow() - datetime.datetime.now())
log.info('Running state [{0}] at time {1}'.format(low['name'], local_start_time.time().isoformat()))
errors = self.verify_data(low)
if errors:
ret = {
@ -1786,14 +1787,17 @@ class State(object):
self.__run_num += 1
format_log(ret)
self.check_refresh(low, ret)
finish_time = datetime.datetime.now()
ret['start_time'] = start_time.time().isoformat()
delta = (finish_time - start_time)
utc_finish_time = datetime.datetime.utcnow()
timezone_delta = datetime.datetime.utcnow() - datetime.datetime.now()
local_finish_time = utc_finish_time - timezone_delta
local_start_time = utc_start_time - timezone_delta
ret['start_time'] = local_start_time.time().isoformat()
delta = (utc_finish_time - utc_start_time)
# duration in milliseconds.microseconds
duration = (delta.seconds * 1000000 + delta.microseconds)/1000.0
ret['duration'] = duration
ret['__id__'] = low['__id__']
log.info('Completed state [{0}] at time {1} duration_in_ms={2}'.format(low['name'], finish_time.time().isoformat(), duration))
log.info('Completed state [{0}] at time {1} duration_in_ms={2}'.format(low['name'], local_finish_time.time().isoformat(), duration))
return ret
def call_chunks(self, chunks):

View File

@ -293,7 +293,7 @@ def present(name,
.. versionadded:: 2016.3.0
'''
name = ' '.join(name.strip().split())
name = name.strip()
if identifier is False:
identifier = name
ret = {'changes': {},
@ -380,7 +380,7 @@ def absent(name,
### cannot be removed from the function definition, otherwise the use
### of unsupported arguments will result in a traceback.
name = ' '.join(name.strip().split())
name = name.strip()
if identifier is False:
identifier = name
ret = {'name': name,
@ -689,7 +689,7 @@ def env_absent(name,
the root user
'''
name = ' '.join(name.strip().split())
name = name.strip()
ret = {'name': name,
'result': True,
'changes': {},

View File

@ -879,7 +879,11 @@ def latest(name,
revs_match = _revs_equal(local_rev, remote_rev, remote_rev_type)
try:
# If not a bare repo, check `git diff HEAD` to determine if
# there are local changes.
local_changes = bool(
not bare
and
__salt__['git.diff'](target,
'HEAD',
user=user,

View File

@ -28,6 +28,12 @@ STUB_CRON_TIMESTAMP = {'minute': '1',
STUB_SIMPLE_RAW_CRON = '5 0 * * * /tmp/no_script.sh'
STUB_SIMPLE_CRON_DICT = {'pre': ['5 0 * * * /tmp/no_script.sh'], 'crons': [], 'env': [], 'special': []}
STUB_CRON_SPACES = """
# Lines below here are managed by Salt, do not edit
TEST_VAR="a string with plenty of spaces"
# SALT_CRON_IDENTIFIER:echo "must be double spaced"
11 * * * * echo "must be double spaced"
"""
__grains__ = {}
L = '# Lines below here are managed by Salt, do not edit\n'
@ -529,6 +535,28 @@ class CronTestCase(TestCase):
'pre': ['# An unmanaged commented cron job', '#0 * * * * /bin/true'],
'special': []})
@patch('salt.modules.cron.raw_cron', new=MagicMock(return_value=STUB_CRON_SPACES))
def test_cron_extra_spaces(self):
'''
Issue #38449
'''
self.maxDiff = None
with patch.dict(cron.__grains__, {'os': None}):
ret = cron.list_tab('root')
eret = {'crons': [{'cmd': 'echo "must be double spaced"',
'comment': '',
'commented': False,
'daymonth': '*',
'dayweek': '*',
'hour': '*',
'identifier': 'echo "must be double spaced"',
'minute': '11',
'month': '*'}],
'env': [{'name': 'TEST_VAR', 'value': '"a string with plenty of spaces"'}],
'pre': [''],
'special': []}
self.assertEqual(eret, ret)
@patch('salt.modules.cron.raw_cron',
new=MagicMock(side_effect=[
(L + '\n'),

View File

@ -669,6 +669,32 @@ class FileModuleTestCase(TestCase):
empty_file.close()
os.remove(empty_file.name)
def test_delete_line_in_empty_file(self):
'''
Tests that when calling file.line with ``mode=delete``,
the function doesn't stack trace if the file is empty.
Should return ``False``.
See Issue #38438.
'''
# Create an empty temporary named file
empty_file = tempfile.NamedTemporaryFile(delete=False,
mode='w+')
# Assert that the file was created and is empty
self.assertEqual(os.stat(empty_file.name).st_size, 0)
# Now call the function on the empty file and assert
# the return is False instead of stack-tracing
self.assertFalse(filemod.line(empty_file.name,
content='foo',
match='bar',
mode='delete'))
# Close and remove the file
empty_file.close()
os.remove(empty_file.name)
if __name__ == '__main__':
from integration import run_tests