mirror of
https://github.com/saltstack/salt.git
synced 2025-04-17 10:10:20 +00:00
Merge branch '2016.3' into '2016.11'
Conflicts: - salt/cli/batch.py - salt/cli/salt.py - salt/transport/client.py - salt/utils/vmware.py - tests/integration/modules/sysmod.py
This commit is contained in:
commit
0e332ab591
15 changed files with 140 additions and 37 deletions
|
@ -12,6 +12,14 @@ Returner Changes
|
|||
accept a ``minions`` keyword argument. All returners which ship with Salt
|
||||
have been modified to do so.
|
||||
|
||||
New Configuration Parameter: ``rotate_aes_key``
|
||||
===============================================
|
||||
|
||||
- ``Rotate_aes_key`` causes Salt to generate a new AES key whenever a minion key
|
||||
is deleted. This eliminates the chance that a deleted minion could continue
|
||||
to eavesdrop on communications with the master if it continues to run after its
|
||||
key is deleted. See the entry in the documentation for `rotate_aes_key`_.
|
||||
|
||||
Ubuntu 16.04 Packages
|
||||
=====================
|
||||
|
||||
|
@ -640,3 +648,4 @@ Changes:
|
|||
.. _`#34647`: https://github.com/saltstack/salt/pull/34647
|
||||
.. _`#34651`: https://github.com/saltstack/salt/pull/34651
|
||||
.. _`#34676`: https://github.com/saltstack/salt/pull/34676
|
||||
.. _ `rotate_aes_key`: https://docs.saltstack.com/en/2015.8/ref/configuration/master.html#rotate-aes-key
|
||||
|
|
|
@ -8,11 +8,18 @@ Version 2016.3.4 is a bugfix release for :doc:`2016.3.0
|
|||
Known Issues
|
||||
------------
|
||||
|
||||
The Salt Minion does not clean up files in ``/tmp`` when rendering templates. This potentially
|
||||
results in either running out of disk space or running out of inodes. Please see `Issue #37541`_
|
||||
for more information. This bug was fixed with `Pull Request #37540`_, which will be available in
|
||||
the ``2016.3.5`` release of Salt.
|
||||
|
||||
The release of the `bootstrap-salt.sh` script that is included with 2016.3.4 release has a bug
|
||||
in it that fails to install salt correctly for git installs using tags in the 2015.5 branch.
|
||||
This bug has not been fixed in the `salt-bootstrap repository`_ yet, but the
|
||||
`previous bootstrap release`_ (v2016.08.16) does not contain this bug.
|
||||
|
||||
.. _`Issue #37541`: https://github.com/saltstack/salt/issues/37541
|
||||
.. _`Pull Request #37540`: https://github.com/saltstack/salt/pull/37540
|
||||
.. _`previous bootstrap release`: https://raw.githubusercontent.com/saltstack/salt-bootstrap/v2016.08.16/bootstrap-salt.sh
|
||||
.. _`salt-bootstrap repository`: https://github.com/saltstack/salt-bootstrap
|
||||
|
||||
|
|
|
@ -208,9 +208,9 @@ class Batch(object):
|
|||
break
|
||||
continue
|
||||
if self.opts.get('raw'):
|
||||
parts.update({part['id']: part})
|
||||
if part['id'] in minion_tracker[queue]['minions']:
|
||||
minion_tracker[queue]['minions'].remove(part['id'])
|
||||
parts.update({part['data']['id']: part})
|
||||
if part['data']['id'] in minion_tracker[queue]['minions']:
|
||||
minion_tracker[queue]['minions'].remove(part['data']['id'])
|
||||
else:
|
||||
print_cli('minion {0} was already deleted from tracker, probably a duplicate key'.format(part['id']))
|
||||
else:
|
||||
|
@ -242,15 +242,11 @@ class Batch(object):
|
|||
if bwait:
|
||||
wait.append(datetime.now() + timedelta(seconds=bwait))
|
||||
if self.opts.get('raw'):
|
||||
ret[minion] = data
|
||||
yield data
|
||||
elif self.opts.get('failhard'):
|
||||
# When failhard is passed, we need to return all data to include
|
||||
# the retcode to use in salt/cli/salt.py later. See issue #24996.
|
||||
else:
|
||||
ret[minion] = data
|
||||
yield {minion: data}
|
||||
else:
|
||||
ret[minion] = data['ret']
|
||||
yield {minion: data['ret']}
|
||||
if not self.quiet:
|
||||
ret[minion] = data['ret']
|
||||
data[minion] = data.pop('ret')
|
||||
|
|
|
@ -51,6 +51,10 @@ class SaltCMD(parsers.SaltCMDOptionParser):
|
|||
return
|
||||
|
||||
if self.options.batch or self.options.static:
|
||||
# _run_batch() will handle all output and
|
||||
# exit with the appropriate error condition
|
||||
# Execution will not continue past this point
|
||||
# in batch mode.
|
||||
self._run_batch()
|
||||
return
|
||||
|
||||
|
@ -239,10 +243,14 @@ class SaltCMD(parsers.SaltCMDOptionParser):
|
|||
# We will print errors to the console further down the stack
|
||||
sys.exit(1)
|
||||
# Printing the output is already taken care of in run() itself
|
||||
retcode = 0
|
||||
for res in batch.run():
|
||||
if self.options.failhard:
|
||||
for ret in six.itervalues(res):
|
||||
retcode = self._get_retcode(ret)
|
||||
for ret in six.itervalues(res):
|
||||
job_retcode = salt.utils.job.get_retcode(ret)
|
||||
if job_retcode > retcode:
|
||||
# Exit with the highest retcode we find
|
||||
retcode = job_retcode
|
||||
if self.options.failhard:
|
||||
if retcode != 0:
|
||||
sys.stderr.write(
|
||||
'{0}\nERROR: Minions returned with non-zero exit code.\n'.format(
|
||||
|
@ -250,6 +258,7 @@ class SaltCMD(parsers.SaltCMDOptionParser):
|
|||
)
|
||||
)
|
||||
sys.exit(retcode)
|
||||
sys.exit(retcode)
|
||||
|
||||
def _print_errors_summary(self, errors):
|
||||
if errors:
|
||||
|
|
|
@ -648,22 +648,34 @@ def list_keypairs(call=None):
|
|||
)
|
||||
return False
|
||||
|
||||
items = query(method='account/keys')
|
||||
fetch = True
|
||||
page = 1
|
||||
ret = {}
|
||||
for key_pair in items['ssh_keys']:
|
||||
name = key_pair['name']
|
||||
if name in ret:
|
||||
raise SaltCloudSystemExit(
|
||||
'A duplicate key pair name, \'{0}\', was found in DigitalOcean\'s '
|
||||
'key pair list. Please change the key name stored by DigitalOcean. '
|
||||
'Be sure to adjust the value of \'ssh_key_file\' in your cloud '
|
||||
'profile or provider configuration, if necessary.'.format(
|
||||
name
|
||||
|
||||
while fetch:
|
||||
items = query(method='account/keys', command='?page=' + str(page) +
|
||||
'&per_page=100')
|
||||
|
||||
for key_pair in items['ssh_keys']:
|
||||
name = key_pair['name']
|
||||
if name in ret:
|
||||
raise SaltCloudSystemExit(
|
||||
'A duplicate key pair name, \'{0}\', was found in DigitalOcean\'s '
|
||||
'key pair list. Please change the key name stored by DigitalOcean. '
|
||||
'Be sure to adjust the value of \'ssh_key_file\' in your cloud '
|
||||
'profile or provider configuration, if necessary.'.format(
|
||||
name
|
||||
)
|
||||
)
|
||||
)
|
||||
ret[name] = {}
|
||||
for item in six.iterkeys(key_pair):
|
||||
ret[name][item] = str(key_pair[item])
|
||||
ret[name] = {}
|
||||
for item in six.iterkeys(key_pair):
|
||||
ret[name][item] = str(key_pair[item])
|
||||
|
||||
page += 1
|
||||
try:
|
||||
fetch = 'next' in items['links']['pages']
|
||||
except KeyError:
|
||||
fetch = False
|
||||
|
||||
return ret
|
||||
|
||||
|
|
|
@ -87,7 +87,7 @@ import salt.utils
|
|||
import tempfile
|
||||
import salt.utils.locales
|
||||
import salt.utils.url
|
||||
from salt.ext.six import string_types
|
||||
from salt.ext.six import string_types, iteritems
|
||||
from salt.exceptions import CommandExecutionError, CommandNotFoundError
|
||||
|
||||
|
||||
|
@ -788,6 +788,9 @@ def install(pkgs=None, # pylint: disable=R0912,R0913,R0914
|
|||
|
||||
if env_vars:
|
||||
if isinstance(env_vars, dict):
|
||||
for k, v in iteritems(env_vars):
|
||||
if not isinstance(v, string_types):
|
||||
env_vars[k] = str(v)
|
||||
os.environ.update(env_vars)
|
||||
else:
|
||||
raise CommandExecutionError(
|
||||
|
|
|
@ -125,6 +125,14 @@ The corresponding Pillar top file would look like this:
|
|||
'*':
|
||||
- bar
|
||||
|
||||
.. note::
|
||||
This feature was unintentionally omitted when git_pillar was rewritten for
|
||||
the 2015.8.0 release. It was added again in the 2016.3.4 release, but it
|
||||
has changed slightly in that release. On Salt masters running 2015.8.0
|
||||
through 2016.3.3, this feature can only be accessed using the legacy config
|
||||
described above. For 2016.3.4 and later, refer to explanation of the
|
||||
``__env__`` parameter in the below section.
|
||||
|
||||
.. _git-pillar-2015-8-0-and-later:
|
||||
|
||||
Configuring git_pillar for Salt releases 2015.8.0 and later
|
||||
|
@ -204,6 +212,36 @@ per-remote parameter:
|
|||
- production https://gitserver/git-pillar.git:
|
||||
- env: prod
|
||||
|
||||
If ``__env__`` is specified as the branch name, then git_pillar will use the
|
||||
branch specified by :conf_master:`git_pillar_base`:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
ext_pillar:
|
||||
- git:
|
||||
- __env__ https://gitserver/git-pillar.git:
|
||||
- root: pillar
|
||||
|
||||
The corresponding Pillar top file would look like this:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
{{env}}:
|
||||
'*':
|
||||
- bar
|
||||
|
||||
.. note::
|
||||
This feature was unintentionally omitted when git_pillar was rewritten for
|
||||
the 2015.8.0 release. It was added again in the 2016.3.4 release, but it
|
||||
has changed slightly in that release. On Salt masters running 2015.8.0
|
||||
through 2016.3.3, this feature can only be accessed using the legacy config
|
||||
in the previous section of this page.
|
||||
|
||||
For 2016.3.4 and later, the above example is accurate, and the value
|
||||
replaced by ``__env__`` is :conf_master:`git_pillar_base`, while the legacy
|
||||
config's version of this feature replaces ``__env__`` with
|
||||
:conf_master:`gitfs_base`.
|
||||
|
||||
With the addition of pygit2_ support, git_pillar can now interact with
|
||||
authenticated remotes. Authentication works just like in gitfs (as outlined in
|
||||
the :ref:`Git Fileserver Backend Walkthrough <gitfs-authentication>`), only
|
||||
|
|
|
@ -2924,12 +2924,8 @@ class BaseHighState(object):
|
|||
'''
|
||||
if not self.opts['autoload_dynamic_modules']:
|
||||
return
|
||||
if self.opts.get('local', False):
|
||||
syncd = self.state.functions['saltutil.sync_all'](list(matches),
|
||||
refresh=False)
|
||||
else:
|
||||
syncd = self.state.functions['saltutil.sync_all'](list(matches),
|
||||
refresh=False)
|
||||
syncd = self.state.functions['saltutil.sync_all'](list(matches),
|
||||
refresh=False)
|
||||
if syncd['grains']:
|
||||
self.opts['grains'] = salt.loader.grains(self.opts)
|
||||
self.state.opts['pillar'] = self.state._gather_pillar()
|
||||
|
|
|
@ -114,7 +114,7 @@ class AsyncReqChannel(AsyncChannel):
|
|||
return salt.transport.tcp.AsyncTCPReqChannel(opts, **kwargs)
|
||||
elif ttype == 'raet':
|
||||
import salt.transport.raet
|
||||
return salt.transport.raet.AsyncRAETReqChannel(opts, **kwargs)
|
||||
return salt.transport.raet.RAETReqChannel(opts, **kwargs)
|
||||
elif ttype == 'local':
|
||||
import salt.transport.local
|
||||
return salt.transport.local.AsyncLocalChannel(opts, **kwargs)
|
||||
|
|
|
@ -577,8 +577,10 @@ def get_location(opts=None, provider=None):
|
|||
DEFAULT_LOCATION
|
||||
'''
|
||||
if opts is None:
|
||||
opts = __opts__
|
||||
ret = opts.get('location', provider.get('location'))
|
||||
opts = {}
|
||||
ret = opts.get('location')
|
||||
if ret is None and provider is not None:
|
||||
ret = provider.get('location')
|
||||
if ret is None:
|
||||
ret = get_region_from_metadata()
|
||||
if ret is None:
|
||||
|
|
|
@ -360,7 +360,7 @@ class GroupOption(Option):
|
|||
self.gids.add(int(name))
|
||||
else:
|
||||
try:
|
||||
self.gids.add(grp.getgrnam(value).gr_gid)
|
||||
self.gids.add(grp.getgrnam(name).gr_gid)
|
||||
except KeyError:
|
||||
raise ValueError('no such group "{0}"'.format(name))
|
||||
|
||||
|
|
|
@ -787,6 +787,7 @@ class CkMinions(object):
|
|||
# so this fn is permitted by all minions
|
||||
if self.match_check(auth_list_entry, fun):
|
||||
return True
|
||||
continue
|
||||
if isinstance(auth_list_entry, dict):
|
||||
if len(auth_list_entry) != 1:
|
||||
log.info('Malformed ACL: {0}'.format(auth_list_entry))
|
||||
|
|
|
@ -54,6 +54,12 @@ class BatchTest(integration.ShellCase):
|
|||
self.assertIn(sub_min_ret, cmd)
|
||||
self.assertIn(min_ret, cmd)
|
||||
|
||||
def test_batch_exit_code(self):
|
||||
'''
|
||||
Test that a failed state returns a non-zero exit code in batch mode
|
||||
'''
|
||||
cmd = self.run_salt(' "*" state.single test.fail_without_changes name=test_me -b 25%', with_retcode=True)
|
||||
self.assertEqual(cmd[-1], 2)
|
||||
|
||||
if __name__ == '__main__':
|
||||
from integration import run_tests
|
||||
|
|
|
@ -85,6 +85,29 @@ class StdTest(integration.ModuleCase):
|
|||
continue
|
||||
self.assertTrue(ret['minion'])
|
||||
|
||||
def test_batch(self):
|
||||
'''
|
||||
test cmd_batch
|
||||
'''
|
||||
cmd_batch = self.client.cmd_batch(
|
||||
'minion',
|
||||
'test.ping',
|
||||
)
|
||||
for ret in cmd_batch:
|
||||
self.assertTrue(ret['minion'])
|
||||
|
||||
def test_batch_raw(self):
|
||||
'''
|
||||
test cmd_batch with raw option
|
||||
'''
|
||||
cmd_batch = self.client.cmd_batch(
|
||||
'minion',
|
||||
'test.ping',
|
||||
raw=True,
|
||||
)
|
||||
for ret in cmd_batch:
|
||||
self.assertTrue(ret['data']['success'])
|
||||
|
||||
def test_full_returns(self):
|
||||
'''
|
||||
test cmd_iter
|
||||
|
|
|
@ -45,6 +45,7 @@ class SysModuleTest(integration.ModuleCase):
|
|||
'nspawn.restart',
|
||||
'lowpkg.bin_pkg_info',
|
||||
'state.apply',
|
||||
'pip.iteritems',
|
||||
'cmd.win_runas',
|
||||
'status.list2cmdline'
|
||||
)
|
||||
|
|
Loading…
Add table
Reference in a new issue