mirror of
https://github.com/valitydev/salt.git
synced 2024-11-08 09:23:56 +00:00
Merge pull request #44153 from rallytime/merge-develop
[develop] Merge forward from 2017.7 to develop
This commit is contained in:
commit
990a454f99
@ -6,7 +6,7 @@ Introduced in Salt version ``2017.7.0`` it is now possible to run select states
|
||||
in parallel. This is accomplished very easily by adding the ``parallel: True``
|
||||
option to your state declaration:
|
||||
|
||||
.. code_block:: yaml
|
||||
.. code-block:: yaml
|
||||
|
||||
nginx:
|
||||
service.running:
|
||||
@ -24,7 +24,7 @@ state to finish.
|
||||
|
||||
Given this example:
|
||||
|
||||
.. code_block:: yaml
|
||||
.. code-block:: yaml
|
||||
|
||||
sleep 10:
|
||||
cmd.run:
|
||||
@ -74,16 +74,16 @@ also complete.
|
||||
Things to be Careful of
|
||||
=======================
|
||||
|
||||
Parallel States does not prevent you from creating parallel conflicts on your
|
||||
Parallel States do not prevent you from creating parallel conflicts on your
|
||||
system. This means that if you start multiple package installs using Salt then
|
||||
the package manager will block or fail. If you attempt to manage the same file
|
||||
with multiple states in parallel then the result can produce an unexpected
|
||||
file.
|
||||
|
||||
Make sure that the states you choose to run in parallel do not conflict, or
|
||||
else, like in and parallel programming environment, the outcome may not be
|
||||
else, like in any parallel programming environment, the outcome may not be
|
||||
what you expect. Doing things like just making all states run in parallel
|
||||
will almost certinly result in unexpected behavior.
|
||||
will almost certainly result in unexpected behavior.
|
||||
|
||||
With that said, running states in parallel should be safe the vast majority
|
||||
of the time and the most likely culprit for unexpected behavior is running
|
||||
|
@ -14,23 +14,33 @@ CVE-2017-14695 Directory traversal vulnerability in minion id validation in Salt
|
||||
|
||||
CVE-2017-14696 Remote Denial of Service with a specially crafted authentication request. Credit for discovering the security flaw goes to: Julian Brost (julian@0x4a42.net)
|
||||
|
||||
Extended changelog courtesy of Todd Stansell (https://github.com/tjstansell/salt-changelogs):
|
||||
|
||||
Known Issues
|
||||
============
|
||||
|
||||
On 2017.7.2 when using salt-api and cherrypy version 5.6.0, issue `#43581`_ will occur when starting the salt-api service. We have patched the cherry-py packages for python-cherrypy-5.6.0-2 from repo.saltstack.com. If you are using python-cherrypy-5.6.0-1 please ensure to run `yum install python-cherrypy` to install the new patched version.
|
||||
|
||||
*Generated at: 2017-09-26T21:06:19Z*
|
||||
Extended changelog courtesy of Todd Stansell (https://github.com/tjstansell/salt-changelogs):
|
||||
|
||||
Statistics:
|
||||
*Generated at: 2017-10-02T21:10:14Z*
|
||||
|
||||
- Total Merges: **326**
|
||||
- Total Issue references: **133**
|
||||
- Total PR references: **389**
|
||||
Statistics
|
||||
==========
|
||||
|
||||
Changes:
|
||||
- Total Merges: **328**
|
||||
- Total Issue references: **134**
|
||||
- Total PR references: **391**
|
||||
|
||||
Changes
|
||||
=======
|
||||
|
||||
- **PR** `#43868`_: (*rallytime*) Back-port `#43847`_ to 2017.7.2
|
||||
* Fix to module.run
|
||||
|
||||
- **PR** `#43756`_: (*gtmanfred*) split build and install for pkg osx
|
||||
@ *2017-09-26T20:51:28Z*
|
||||
|
||||
* 88414d5 Merge pull request `#43756`_ from gtmanfred/2017.7.2
|
||||
* f7df41f split build and install for pkg osx
|
||||
|
||||
- **PR** `#43585`_: (*rallytime*) Back-port `#43330`_ to 2017.7.2
|
||||
@ *2017-09-19T17:33:34Z*
|
||||
@ -3110,6 +3120,12 @@ Changes:
|
||||
.. _`#480`: https://github.com/saltstack/salt/issues/480
|
||||
.. _`#495`: https://github.com/saltstack/salt/issues/495
|
||||
.. _`#43581`: https://github.com/saltstack/salt/issues/43581
|
||||
.. _`#43756`: https://github.com/saltstack/salt/pull/43756
|
||||
.. _`#43847`: https://github.com/saltstack/salt/pull/43847
|
||||
.. _`#43868`: https://github.com/saltstack/salt/pull/43868
|
||||
.. _`#475`: https://github.com/saltstack/salt/issues/475
|
||||
.. _`#480`: https://github.com/saltstack/salt/issues/480
|
||||
.. _`#495`: https://github.com/saltstack/salt/issues/495
|
||||
.. _`bp-37424`: https://github.com/saltstack/salt/pull/37424
|
||||
.. _`bp-39366`: https://github.com/saltstack/salt/pull/39366
|
||||
.. _`bp-41543`: https://github.com/saltstack/salt/pull/41543
|
||||
|
@ -27,7 +27,7 @@ Installing Dependencies
|
||||
=======================
|
||||
|
||||
Both pygit2_ and GitPython_ are supported Python interfaces to git. If
|
||||
compatible versions of both are installed, pygit2_ will preferred. In these
|
||||
compatible versions of both are installed, pygit2_ will be preferred. In these
|
||||
cases, GitPython_ can be forced using the :conf_master:`gitfs_provider`
|
||||
parameter in the master config file.
|
||||
|
||||
|
@ -88,7 +88,8 @@ sudo $PKGRESOURCES/build_env.sh $PYVER
|
||||
echo -n -e "\033]0;Build: Install Salt\007"
|
||||
sudo rm -rf $SRCDIR/build
|
||||
sudo rm -rf $SRCDIR/dist
|
||||
sudo $PYTHON $SRCDIR/setup.py build -e "$PYTHON -E -s" install
|
||||
sudo $PYTHON $SRCDIR/setup.py build -e "$PYTHON -E -s"
|
||||
sudo $PYTHON $SRCDIR/setup.py install
|
||||
|
||||
############################################################################
|
||||
# Build Package
|
||||
|
@ -132,7 +132,7 @@ def version(*names, **kwargs):
|
||||
return __salt__['pkg_resource.version'](*names, **kwargs)
|
||||
|
||||
|
||||
def refresh_db(failhard=False):
|
||||
def refresh_db(failhard=False, **kwargs): # pylint: disable=unused-argument
|
||||
'''
|
||||
Updates the opkg database to latest packages based upon repositories
|
||||
|
||||
@ -514,7 +514,7 @@ def purge(name=None, pkgs=None, **kwargs): # pylint: disable=unused-argument
|
||||
return remove(name=name, pkgs=pkgs)
|
||||
|
||||
|
||||
def upgrade(refresh=True):
|
||||
def upgrade(refresh=True, **kwargs): # pylint: disable=unused-argument
|
||||
'''
|
||||
Upgrades all packages via ``opkg upgrade``
|
||||
|
||||
@ -803,7 +803,7 @@ def list_pkgs(versions_as_list=False, **kwargs):
|
||||
return ret
|
||||
|
||||
|
||||
def list_upgrades(refresh=True):
|
||||
def list_upgrades(refresh=True, **kwargs): # pylint: disable=unused-argument
|
||||
'''
|
||||
List all available package upgrades.
|
||||
|
||||
@ -976,7 +976,7 @@ def info_installed(*names, **kwargs):
|
||||
return ret
|
||||
|
||||
|
||||
def upgrade_available(name):
|
||||
def upgrade_available(name, **kwargs): # pylint: disable=unused-argument
|
||||
'''
|
||||
Check whether or not an upgrade is available for a given package
|
||||
|
||||
@ -989,7 +989,7 @@ def upgrade_available(name):
|
||||
return latest_version(name) != ''
|
||||
|
||||
|
||||
def version_cmp(pkg1, pkg2, ignore_epoch=False):
|
||||
def version_cmp(pkg1, pkg2, ignore_epoch=False, **kwargs): # pylint: disable=unused-argument
|
||||
'''
|
||||
Do a cmp-style comparison on two packages. Return -1 if pkg1 < pkg2, 0 if
|
||||
pkg1 == pkg2, and 1 if pkg1 > pkg2. Return None if there was a problem
|
||||
@ -1038,7 +1038,7 @@ def version_cmp(pkg1, pkg2, ignore_epoch=False):
|
||||
return None
|
||||
|
||||
|
||||
def list_repos():
|
||||
def list_repos(**kwargs): # pylint: disable=unused-argument
|
||||
'''
|
||||
Lists all repos on /etc/opkg/*.conf
|
||||
|
||||
@ -1075,7 +1075,7 @@ def list_repos():
|
||||
return repos
|
||||
|
||||
|
||||
def get_repo(alias):
|
||||
def get_repo(alias, **kwargs): # pylint: disable=unused-argument
|
||||
'''
|
||||
Display a repo from the /etc/opkg/*.conf
|
||||
|
||||
@ -1146,7 +1146,7 @@ def _mod_repo_in_file(alias, repostr, filepath):
|
||||
fhandle.writelines(output)
|
||||
|
||||
|
||||
def del_repo(alias):
|
||||
def del_repo(alias, **kwargs): # pylint: disable=unused-argument
|
||||
'''
|
||||
Delete a repo from /etc/opkg/*.conf
|
||||
|
||||
@ -1260,7 +1260,7 @@ def mod_repo(alias, **kwargs):
|
||||
refresh_db()
|
||||
|
||||
|
||||
def file_list(*packages):
|
||||
def file_list(*packages, **kwargs): # pylint: disable=unused-argument
|
||||
'''
|
||||
List the files that belong to a package. Not specifying any packages will
|
||||
return a list of _every_ file on the system's package database (not
|
||||
@ -1281,7 +1281,7 @@ def file_list(*packages):
|
||||
return {'errors': output['errors'], 'files': files}
|
||||
|
||||
|
||||
def file_dict(*packages):
|
||||
def file_dict(*packages, **kwargs): # pylint: disable=unused-argument
|
||||
'''
|
||||
List the files that belong to a package, grouped by package. Not
|
||||
specifying any packages will return a list of _every_ file on the system's
|
||||
@ -1323,7 +1323,7 @@ def file_dict(*packages):
|
||||
return {'errors': errors, 'packages': ret}
|
||||
|
||||
|
||||
def owner(*paths):
|
||||
def owner(*paths, **kwargs): # pylint: disable=unused-argument
|
||||
'''
|
||||
Return the name of the package that owns the file. Multiple file paths can
|
||||
be passed. Like :mod:`pkg.version <salt.modules.opkg.version`, if a single
|
||||
|
@ -159,7 +159,7 @@ def formatted(name, fs_type='ext4', force=False, **kwargs):
|
||||
ret['result'] = None
|
||||
return ret
|
||||
|
||||
__salt__['disk.format_'](name, fs_type, force=force, **kwargs)
|
||||
__salt__['disk.format'](name, fs_type, force=force, **kwargs)
|
||||
|
||||
# Repeat fstype check up to 10 times with 3s sleeping between each
|
||||
# to avoid detection failing although mkfs has succeeded
|
||||
|
@ -206,8 +206,13 @@ def wrap_tmpl_func(render_str):
|
||||
if six.PY2:
|
||||
output = output.encode(SLS_ENCODING)
|
||||
if salt.utils.platform.is_windows():
|
||||
newline = False
|
||||
if output.endswith(('\n', os.linesep)):
|
||||
newline = True
|
||||
# Write out with Windows newlines
|
||||
output = os.linesep.join(output.splitlines())
|
||||
if newline:
|
||||
output += os.linesep
|
||||
|
||||
except SaltRenderError as exc:
|
||||
log.error("Rendering exception occurred: {0}".format(exc))
|
||||
@ -331,7 +336,7 @@ def render_jinja_tmpl(tmplstr, context, tmplpath=None):
|
||||
# http://jinja.pocoo.org/docs/api/#unicode
|
||||
tmplstr = tmplstr.decode(SLS_ENCODING)
|
||||
|
||||
if tmplstr.endswith('\n'):
|
||||
if tmplstr.endswith(os.linesep):
|
||||
newline = True
|
||||
|
||||
if not saltenv:
|
||||
@ -441,7 +446,7 @@ def render_jinja_tmpl(tmplstr, context, tmplpath=None):
|
||||
# Workaround a bug in Jinja that removes the final newline
|
||||
# (https://github.com/mitsuhiko/jinja2/issues/75)
|
||||
if newline:
|
||||
output += '\n'
|
||||
output += os.linesep
|
||||
|
||||
return output
|
||||
|
||||
|
@ -100,7 +100,7 @@ class BlockdevTestCase(TestCase, LoaderModuleMockMixin):
|
||||
|
||||
# Test state return when block device format fails
|
||||
with patch.dict(blockdev.__salt__, {'cmd.run': MagicMock(return_value=mock_ext4),
|
||||
'disk.format_': MagicMock(return_value=True)}):
|
||||
'disk.format': MagicMock(return_value=True)}):
|
||||
comt = ('Failed to format {0}'.format(name))
|
||||
ret.update({'comment': comt, 'result': False})
|
||||
with patch.object(salt.utils.path, 'which',
|
||||
|
@ -33,6 +33,7 @@ from salt.utils.jinja import (
|
||||
)
|
||||
from salt.utils.templates import JINJA, render_jinja_tmpl
|
||||
from salt.utils.odict import OrderedDict
|
||||
import salt.utils.stringutils
|
||||
|
||||
# Import 3rd party libs
|
||||
import yaml
|
||||
@ -176,12 +177,9 @@ class TestGetTemplate(TestCase):
|
||||
with salt.utils.files.fopen(fn_) as fp_:
|
||||
out = render_jinja_tmpl(
|
||||
fp_.read(),
|
||||
dict(
|
||||
opts=self.local_opts,
|
||||
saltenv='test',
|
||||
salt=self.local_salt
|
||||
))
|
||||
self.assertEqual(out, 'world\n')
|
||||
dict(opts=self.local_opts, saltenv='test', salt=self.local_salt)
|
||||
)
|
||||
self.assertEqual(out, 'world' + os.linesep)
|
||||
|
||||
def test_fallback_noloader(self):
|
||||
'''
|
||||
@ -192,12 +190,9 @@ class TestGetTemplate(TestCase):
|
||||
with salt.utils.files.fopen(filename) as fp_:
|
||||
out = render_jinja_tmpl(
|
||||
fp_.read(),
|
||||
dict(
|
||||
opts=self.local_opts,
|
||||
saltenv='test',
|
||||
salt=self.local_salt
|
||||
))
|
||||
self.assertEqual(out, 'Hey world !a b !\n')
|
||||
dict(opts=self.local_opts, saltenv='test', salt=self.local_salt)
|
||||
)
|
||||
self.assertEqual(out, 'Hey world !a b !' + os.linesep)
|
||||
|
||||
def test_saltenv(self):
|
||||
'''
|
||||
@ -216,7 +211,7 @@ class TestGetTemplate(TestCase):
|
||||
'file_roots': self.local_opts['file_roots'],
|
||||
'pillar_roots': self.local_opts['pillar_roots']},
|
||||
a='Hi', b='Salt', saltenv='test', salt=self.local_salt))
|
||||
self.assertEqual(out, 'Hey world !Hi Salt !\n')
|
||||
self.assertEqual(out, 'Hey world !Hi Salt !' + os.linesep)
|
||||
self.assertEqual(fc.requests[0]['path'], 'salt://macro')
|
||||
|
||||
def test_macro_additional_log_for_generalexc(self):
|
||||
@ -225,7 +220,7 @@ class TestGetTemplate(TestCase):
|
||||
more output from trace.
|
||||
'''
|
||||
expected = r'''Jinja error:.*division.*
|
||||
.*/macrogeneral\(2\):
|
||||
.*macrogeneral\(2\):
|
||||
---
|
||||
\{% macro mymacro\(\) -%\}
|
||||
\{\{ 1/0 \}\} <======================
|
||||
@ -249,7 +244,7 @@ class TestGetTemplate(TestCase):
|
||||
more output from trace.
|
||||
'''
|
||||
expected = r'''Jinja variable 'b' is undefined
|
||||
.*/macroundefined\(2\):
|
||||
.*macroundefined\(2\):
|
||||
---
|
||||
\{% macro mymacro\(\) -%\}
|
||||
\{\{b.greetee\}\} <-- error is here <======================
|
||||
@ -272,7 +267,7 @@ class TestGetTemplate(TestCase):
|
||||
If we failed in a macro, get more output from trace.
|
||||
'''
|
||||
expected = r'''Jinja syntax error: expected token .*end.*got '-'.*
|
||||
.*/macroerror\(2\):
|
||||
.*macroerror\(2\):
|
||||
---
|
||||
# macro
|
||||
\{% macro mymacro\(greeting, greetee='world'\) -\} <-- error is here <======================
|
||||
@ -302,7 +297,7 @@ class TestGetTemplate(TestCase):
|
||||
'file_roots': self.local_opts['file_roots'],
|
||||
'pillar_roots': self.local_opts['pillar_roots']},
|
||||
a='Hi', b='Sàlt', saltenv='test', salt=self.local_salt))
|
||||
self.assertEqual(out, u'Hey world !Hi Sàlt !\n')
|
||||
self.assertEqual(out, salt.utils.stringutils.to_unicode('Hey world !Hi Sàlt !' + os.linesep))
|
||||
self.assertEqual(fc.requests[0]['path'], 'salt://macro')
|
||||
|
||||
filename = os.path.join(TEMPLATES_DIR, 'files', 'test', 'non_ascii')
|
||||
@ -313,7 +308,7 @@ class TestGetTemplate(TestCase):
|
||||
'file_roots': self.local_opts['file_roots'],
|
||||
'pillar_roots': self.local_opts['pillar_roots']},
|
||||
a='Hi', b='Sàlt', saltenv='test', salt=self.local_salt))
|
||||
self.assertEqual(u'Assunção\n', out)
|
||||
self.assertEqual(u'Assunção' + os.linesep, out)
|
||||
self.assertEqual(fc.requests[0]['path'], 'salt://macro')
|
||||
|
||||
@skipIf(HAS_TIMELIB is False, 'The `timelib` library is not installed.')
|
||||
@ -376,8 +371,8 @@ class TestGetTemplate(TestCase):
|
||||
with salt.utils.files.fopen(out['data']) as fp:
|
||||
result = fp.read()
|
||||
if six.PY2:
|
||||
result = result.decode('utf-8')
|
||||
self.assertEqual(u'Assunção\n', result)
|
||||
result = salt.utils.stringutils.to_unicode(result)
|
||||
self.assertEqual(salt.utils.stringutils.to_unicode('Assunção' + os.linesep), result)
|
||||
|
||||
def test_get_context_has_enough_context(self):
|
||||
template = '1\n2\n3\n4\n5\n6\n7\n8\n9\na\nb\nc\nd\ne\nf'
|
||||
|
@ -439,7 +439,7 @@ class PillarTestCase(TestCase):
|
||||
def _setup_test_topfile_mocks(self, Matcher, get_file_client,
|
||||
nodegroup_order, glob_order):
|
||||
# Write a simple topfile and two pillar state files
|
||||
self.top_file = tempfile.NamedTemporaryFile(dir=TMP)
|
||||
self.top_file = tempfile.NamedTemporaryFile(dir=TMP, delete=False)
|
||||
s = '''
|
||||
base:
|
||||
group:
|
||||
@ -456,19 +456,19 @@ base:
|
||||
'''.format(nodegroup_order=nodegroup_order, glob_order=glob_order)
|
||||
self.top_file.write(salt.utils.stringutils.to_bytes(s))
|
||||
self.top_file.flush()
|
||||
self.ssh_file = tempfile.NamedTemporaryFile(dir=TMP)
|
||||
self.ssh_file = tempfile.NamedTemporaryFile(dir=TMP, delete=False)
|
||||
self.ssh_file.write(b'''
|
||||
ssh:
|
||||
foo
|
||||
''')
|
||||
self.ssh_file.flush()
|
||||
self.ssh_minion_file = tempfile.NamedTemporaryFile(dir=TMP)
|
||||
self.ssh_minion_file = tempfile.NamedTemporaryFile(dir=TMP, delete=False)
|
||||
self.ssh_minion_file.write(b'''
|
||||
ssh:
|
||||
bar
|
||||
''')
|
||||
self.ssh_minion_file.flush()
|
||||
self.generic_file = tempfile.NamedTemporaryFile(dir=TMP)
|
||||
self.generic_file = tempfile.NamedTemporaryFile(dir=TMP, delete=False)
|
||||
self.generic_file.write(b'''
|
||||
generic:
|
||||
key1:
|
||||
@ -478,7 +478,7 @@ generic:
|
||||
sub_key1: []
|
||||
''')
|
||||
self.generic_file.flush()
|
||||
self.generic_minion_file = tempfile.NamedTemporaryFile(dir=TMP)
|
||||
self.generic_minion_file = tempfile.NamedTemporaryFile(dir=TMP, delete=False)
|
||||
self.generic_minion_file.write(b'''
|
||||
generic:
|
||||
key1:
|
||||
@ -507,7 +507,7 @@ generic:
|
||||
client.get_state.side_effect = get_state
|
||||
|
||||
def _setup_test_include_mocks(self, Matcher, get_file_client):
|
||||
self.top_file = top_file = tempfile.NamedTemporaryFile(dir=TMP)
|
||||
self.top_file = top_file = tempfile.NamedTemporaryFile(dir=TMP, delete=False)
|
||||
top_file.write(b'''
|
||||
base:
|
||||
'*':
|
||||
@ -518,21 +518,21 @@ base:
|
||||
- test
|
||||
''')
|
||||
top_file.flush()
|
||||
self.init_sls = init_sls = tempfile.NamedTemporaryFile(dir=TMP)
|
||||
self.init_sls = init_sls = tempfile.NamedTemporaryFile(dir=TMP, delete=False)
|
||||
init_sls.write(b'''
|
||||
include:
|
||||
- test.sub1
|
||||
- test.sub2
|
||||
''')
|
||||
init_sls.flush()
|
||||
self.sub1_sls = sub1_sls = tempfile.NamedTemporaryFile(dir=TMP)
|
||||
self.sub1_sls = sub1_sls = tempfile.NamedTemporaryFile(dir=TMP, delete=False)
|
||||
sub1_sls.write(b'''
|
||||
p1:
|
||||
- value1_1
|
||||
- value1_2
|
||||
''')
|
||||
sub1_sls.flush()
|
||||
self.sub2_sls = sub2_sls = tempfile.NamedTemporaryFile(dir=TMP)
|
||||
self.sub2_sls = sub2_sls = tempfile.NamedTemporaryFile(dir=TMP, delete=False)
|
||||
sub2_sls.write(b'''
|
||||
p1:
|
||||
- value1_3
|
||||
|
Loading…
Reference in New Issue
Block a user