mirror of
https://github.com/saltstack/salt.git
synced 2025-04-17 10:10:20 +00:00
Merge branch '2017.7' into 'develop'
Conflicts: - salt/engines/slack.py - salt/modules/win_pkg.py - salt/utils/versions.py
This commit is contained in:
commit
6ca3607770
14 changed files with 105 additions and 44 deletions
|
@ -21,7 +21,7 @@ Or you may specify a map which includes all VMs to perform the action on:
|
|||
|
||||
$ salt-cloud -a reboot -m /path/to/mapfile
|
||||
|
||||
The following is a list of actions currently supported by salt-cloud:
|
||||
The following is an example list of actions currently supported by ``salt-cloud``:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
|
@ -36,5 +36,5 @@ The following is a list of actions currently supported by salt-cloud:
|
|||
- start
|
||||
- stop
|
||||
|
||||
Another useful reference for viewing more salt-cloud actions is the
|
||||
:ref:Salt Cloud Feature Matrix <salt-cloud-feature-matrix>
|
||||
Another useful reference for viewing more ``salt-cloud`` actions is the
|
||||
:ref:`Salt Cloud Feature Matrix <salt-cloud-feature-matrix>`.
|
||||
|
|
|
@ -26,5 +26,5 @@ gathering information about instances on a provider basis:
|
|||
$ salt-cloud -f list_nodes_full linode
|
||||
$ salt-cloud -f list_nodes_select linode
|
||||
|
||||
Another useful reference for viewing salt-cloud functions is the
|
||||
Another useful reference for viewing ``salt-cloud`` functions is the
|
||||
:ref:`Salt Cloud Feature Matrix <salt-cloud-feature-matrix>`.
|
||||
|
|
|
@ -3,3 +3,13 @@ Salt 2016.11.7 Release Notes
|
|||
============================
|
||||
|
||||
Version 2016.11.7 is a bugfix release for :ref:`2016.11.0 <release-2016-11-0>`.
|
||||
|
||||
Changes for v2016.11.6..v2016.11.7
|
||||
----------------------------------
|
||||
|
||||
Security Fix
|
||||
============
|
||||
|
||||
CVE-2017-12791 Maliciously crafted minion IDs can cause unwanted directory traversals on the Salt-master
|
||||
|
||||
Correct a flaw in minion id validation which could allow certain minions to authenticate to a master despite not having the correct credentials. To exploit the vulnerability, an attacker must create a salt-minion with an ID containing characters that will cause a directory traversal. Credit for discovering the security flaw goes to: Vernhk@qq.com
|
||||
|
|
|
@ -728,12 +728,18 @@ def request_instance(vm_=None, call=None):
|
|||
|
||||
else:
|
||||
pool = floating_ip_conf.get('pool', 'public')
|
||||
for fl_ip, opts in six.iteritems(conn.floating_ip_list()):
|
||||
if opts['fixed_ip'] is None and opts['pool'] == pool:
|
||||
floating_ip = fl_ip
|
||||
break
|
||||
if floating_ip is None:
|
||||
try:
|
||||
floating_ip = conn.floating_ip_create(pool)['ip']
|
||||
except Exception:
|
||||
log.info('A new IP address was unable to be allocated. '
|
||||
'An IP address will be pulled from the already allocated list, '
|
||||
'This will cause a race condition when building in parallel.')
|
||||
for fl_ip, opts in six.iteritems(conn.floating_ip_list()):
|
||||
if opts['fixed_ip'] is None and opts['pool'] == pool:
|
||||
floating_ip = fl_ip
|
||||
break
|
||||
if floating_ip is None:
|
||||
log.error('No IP addresses available to allocate for this server: {0}'.format(vm_['name']))
|
||||
|
||||
def __query_node_data(vm_):
|
||||
try:
|
||||
|
|
|
@ -640,6 +640,13 @@ class Client(object):
|
|||
|
||||
def on_header(hdr):
|
||||
if write_body[1] is not False and write_body[2] is None:
|
||||
if not hdr.strip() and 'Content-Type' not in write_body[1]:
|
||||
# We've reached the end of the headers and not yet
|
||||
# found the Content-Type. Reset the values we're
|
||||
# tracking so that we properly follow the redirect.
|
||||
write_body[0] = None
|
||||
write_body[1] = False
|
||||
return
|
||||
# Try to find out what content type encoding is used if
|
||||
# this is a text file
|
||||
write_body[1].parse_line(hdr) # pylint: disable=no-member
|
||||
|
|
|
@ -3848,7 +3848,6 @@ def save(name,
|
|||
if os.path.exists(path) and not overwrite:
|
||||
raise CommandExecutionError('{0} already exists'.format(path))
|
||||
|
||||
compression = kwargs.get('compression')
|
||||
if compression is None:
|
||||
if path.endswith('.tar.gz') or path.endswith('.tgz'):
|
||||
compression = 'gzip'
|
||||
|
@ -3954,7 +3953,7 @@ def save(name,
|
|||
ret['Size_Human'] = _size_fmt(ret['Size'])
|
||||
|
||||
# Process push
|
||||
if kwargs.get(push, False):
|
||||
if kwargs.get('push', False):
|
||||
ret['Push'] = __salt__['cp.push'](path)
|
||||
|
||||
return ret
|
||||
|
|
|
@ -80,7 +80,8 @@ for service_dir in VALID_SERVICE_DIRS:
|
|||
AVAIL_SVR_DIRS = []
|
||||
|
||||
# Define the module's virtual name
|
||||
__virtualname__ = 'service'
|
||||
__virtualname__ = 'runit'
|
||||
__virtual_aliases__ = ('runit',)
|
||||
|
||||
|
||||
def __virtual__():
|
||||
|
@ -91,8 +92,12 @@ def __virtual__():
|
|||
if __grains__.get('init') == 'runit':
|
||||
if __grains__['os'] == 'Void':
|
||||
add_svc_avail_path('/etc/sv')
|
||||
global __virtualname__
|
||||
__virtualname__ = 'service'
|
||||
return __virtualname__
|
||||
return False
|
||||
if salt.utils.which('sv'):
|
||||
return __virtualname__
|
||||
return (False, 'Runit not available. Please install sv')
|
||||
|
||||
|
||||
def _service_path(name):
|
||||
|
|
|
@ -1285,6 +1285,18 @@ def install(name=None, refresh=False, pkgs=None, **kwargs):
|
|||
#Compute msiexec string
|
||||
use_msiexec, msiexec = _get_msiexec(pkginfo[version_num].get('msiexec', False))
|
||||
|
||||
# Build cmd and arguments
|
||||
# cmd and arguments must be seperated for use with the task scheduler
|
||||
if use_msiexec:
|
||||
cmd = msiexec
|
||||
arguments = ['/i', cached_pkg]
|
||||
if pkginfo['version_num'].get('allusers', True):
|
||||
arguments.append('ALLUSERS="1"')
|
||||
arguments.extend(salt.utils.shlex_split(install_flags))
|
||||
else:
|
||||
cmd = cached_pkg
|
||||
arguments = salt.utils.shlex_split(install_flags)
|
||||
|
||||
# Install the software
|
||||
# Check Use Scheduler Option
|
||||
if pkginfo[version_num].get('use_scheduler', False):
|
||||
|
@ -1313,21 +1325,43 @@ def install(name=None, refresh=False, pkgs=None, **kwargs):
|
|||
start_time='01:00',
|
||||
ac_only=False,
|
||||
stop_if_on_batteries=False)
|
||||
|
||||
# Run Scheduled Task
|
||||
if not __salt__['task.run_wait'](name='update-salt-software'):
|
||||
log.error('Failed to install {0}'.format(pkg_name))
|
||||
log.error('Scheduled Task failed to run')
|
||||
ret[pkg_name] = {'install status': 'failed'}
|
||||
else:
|
||||
# Build the install command
|
||||
cmd = []
|
||||
if use_msiexec:
|
||||
cmd.extend([msiexec, '/i', cached_pkg])
|
||||
if pkginfo[version_num].get('allusers', True):
|
||||
cmd.append('ALLUSERS="1"')
|
||||
# Special handling for installing salt
|
||||
if pkg_name in ['salt-minion', 'salt-minion-py3']:
|
||||
ret[pkg_name] = {'install status': 'task started'}
|
||||
if not __salt__['task.run'](name='update-salt-software'):
|
||||
log.error('Failed to install {0}'.format(pkg_name))
|
||||
log.error('Scheduled Task failed to run')
|
||||
ret[pkg_name] = {'install status': 'failed'}
|
||||
else:
|
||||
|
||||
# Make sure the task is running, try for 5 secs
|
||||
from time import time
|
||||
t_end = time() + 5
|
||||
while time() < t_end:
|
||||
task_running = __salt__['task.status'](
|
||||
'update-salt-software') == 'Running'
|
||||
if task_running:
|
||||
break
|
||||
|
||||
if not task_running:
|
||||
log.error(
|
||||
'Failed to install {0}'.format(pkg_name))
|
||||
log.error('Scheduled Task failed to run')
|
||||
ret[pkg_name] = {'install status': 'failed'}
|
||||
|
||||
# All other packages run with task scheduler
|
||||
else:
|
||||
cmd.append(cached_pkg)
|
||||
cmd.extend(salt.utils.args.shlex_split(install_flags))
|
||||
if not __salt__['task.run_wait'](name='update-salt-software'):
|
||||
log.error('Failed to install {0}'.format(pkg_name))
|
||||
log.error('Scheduled Task failed to run')
|
||||
ret[pkg_name] = {'install status': 'failed'}
|
||||
else:
|
||||
|
||||
# Combine cmd and arguments
|
||||
cmd = [cmd].extend(arguments)
|
||||
|
||||
# Launch the command
|
||||
result = __salt__['cmd.run_all'](cmd,
|
||||
cache_path,
|
||||
|
|
|
@ -1260,7 +1260,7 @@ def status(name, location='\\'):
|
|||
task_service = win32com.client.Dispatch("Schedule.Service")
|
||||
task_service.Connect()
|
||||
|
||||
# get the folder to delete the folder from
|
||||
# get the folder where the task is defined
|
||||
task_folder = task_service.GetFolder(location)
|
||||
task = task_folder.GetTask(name)
|
||||
|
||||
|
|
|
@ -900,7 +900,7 @@ def mod_watch(name,
|
|||
try:
|
||||
result = func(name, **func_kwargs)
|
||||
except CommandExecutionError as exc:
|
||||
ret['result'] = True
|
||||
ret['result'] = False
|
||||
ret['comment'] = exc.strerror
|
||||
return ret
|
||||
|
||||
|
|
|
@ -284,6 +284,9 @@ class ReactWrap(object):
|
|||
# Update called function's low data with event user to
|
||||
# segregate events fired by reactor and avoid reaction loops
|
||||
kwargs['__user__'] = self.event_user
|
||||
# Replace ``state`` kwarg which comes from high data compiler.
|
||||
# It breaks some runner functions and seems unnecessary.
|
||||
kwargs['__state__'] = kwargs.pop('state')
|
||||
|
||||
l_fun(*f_call.get('args', ()), **kwargs)
|
||||
except Exception:
|
||||
|
|
|
@ -852,6 +852,12 @@ class Schedule(object):
|
|||
|
||||
ret['return'] = self.functions[func](*args, **kwargs)
|
||||
|
||||
# runners do not provide retcode
|
||||
if 'retcode' in self.functions.pack['__context__']:
|
||||
ret['retcode'] = self.functions.pack['__context__']['retcode']
|
||||
|
||||
ret['success'] = True
|
||||
|
||||
data_returner = data.get('returner', None)
|
||||
if data_returner or self.schedule_returner:
|
||||
if 'return_config' in data:
|
||||
|
@ -868,7 +874,6 @@ class Schedule(object):
|
|||
for returner in OrderedDict.fromkeys(rets):
|
||||
ret_str = '{0}.returner'.format(returner)
|
||||
if ret_str in self.returners:
|
||||
ret['success'] = True
|
||||
self.returners[ret_str](ret)
|
||||
else:
|
||||
log.info(
|
||||
|
@ -877,11 +882,6 @@ class Schedule(object):
|
|||
)
|
||||
)
|
||||
|
||||
# runners do not provide retcode
|
||||
if 'retcode' in self.functions.pack['__context__']:
|
||||
ret['retcode'] = self.functions.pack['__context__']['retcode']
|
||||
|
||||
ret['success'] = True
|
||||
except Exception:
|
||||
log.exception("Unhandled exception running {0}".format(ret['fun']))
|
||||
# Although catch-all exception handlers are bad, the exception here
|
||||
|
|
|
@ -19,8 +19,9 @@ from tornado.httpclient import HTTPClient
|
|||
|
||||
GEM = 'tidy'
|
||||
GEM_VER = '1.1.2'
|
||||
OLD_GEM = 'thor'
|
||||
OLD_VERSION = '0.17.0'
|
||||
OLD_GEM = 'brass'
|
||||
OLD_VERSION = '1.0.0'
|
||||
NEW_VERSION = '1.2.1'
|
||||
GEM_LIST = [GEM, OLD_GEM]
|
||||
|
||||
|
||||
|
@ -129,18 +130,18 @@ class GemModuleTest(ModuleCase):
|
|||
|
||||
self.run_function('gem.install', [OLD_GEM], version=OLD_VERSION)
|
||||
gem_list = self.run_function('gem.list', [OLD_GEM])
|
||||
self.assertEqual({'thor': ['0.17.0']}, gem_list)
|
||||
self.assertEqual({OLD_GEM: [OLD_VERSION]}, gem_list)
|
||||
|
||||
self.run_function('gem.update', [OLD_GEM])
|
||||
gem_list = self.run_function('gem.list', [OLD_GEM])
|
||||
self.assertEqual({'thor': ['0.19.4', '0.17.0']}, gem_list)
|
||||
self.assertEqual({OLD_GEM: [NEW_VERSION, OLD_VERSION]}, gem_list)
|
||||
|
||||
self.run_function('gem.uninstall', [OLD_GEM])
|
||||
self.assertFalse(self.run_function('gem.list', [OLD_GEM]))
|
||||
|
||||
def test_udpate_system(self):
|
||||
def test_update_system(self):
|
||||
'''
|
||||
gem.udpate_system
|
||||
gem.update_system
|
||||
'''
|
||||
ret = self.run_function('gem.update_system')
|
||||
self.assertTrue(ret)
|
||||
|
|
|
@ -11,15 +11,11 @@ from tests.support.unit import skipIf, TestCase
|
|||
from tests.support.mock import NO_MOCK, NO_MOCK_REASON, patch
|
||||
|
||||
# Import Salt libs
|
||||
import salt.config
|
||||
import salt.loader
|
||||
import salt.utils.boto
|
||||
from salt.ext import six
|
||||
from salt.utils.versions import LooseVersion
|
||||
import salt.states.boto_vpc as boto_vpc
|
||||
|
||||
# Import test suite libs
|
||||
|
||||
# pylint: disable=import-error,unused-import
|
||||
from tests.unit.modules.test_boto_vpc import BotoVpcTestCaseMixin
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue