mirror of
https://github.com/saltstack/salt.git
synced 2025-04-17 10:10:20 +00:00
Merge pull request #48037 from terminalmage/fix-custom-types-sync-docs
Add "sync_mods" argument to state.apply/state.sls
This commit is contained in:
commit
731ec0a11a
4 changed files with 167 additions and 49 deletions
23
doc/faq.rst
23
doc/faq.rst
|
@ -148,22 +148,23 @@ Why aren't my custom modules/states/etc. available on my Minions?
|
|||
-----------------------------------------------------------------
|
||||
|
||||
Custom modules are synced to Minions when
|
||||
:mod:`saltutil.sync_modules <salt.modules.saltutil.sync_modules>`,
|
||||
or :mod:`saltutil.sync_all <salt.modules.saltutil.sync_all>` is run.
|
||||
Custom modules are also synced by :mod:`state.apply` when run without
|
||||
any arguments.
|
||||
:py:func:`saltutil.sync_modules <salt.modules.saltutil.sync_modules>`,
|
||||
or :py:func:`saltutil.sync_all <salt.modules.saltutil.sync_all>` is run.
|
||||
|
||||
Similarly, custom states are synced to Minions when :py:func:`saltutil.sync_states
|
||||
<salt.modules.saltutil.sync_states>`, or :py:func:`saltutil.sync_all
|
||||
<salt.modules.saltutil.sync_all>` is run.
|
||||
|
||||
Similarly, custom states are synced to Minions
|
||||
when :mod:`state.apply <salt.modules.state.apply_>`,
|
||||
:mod:`saltutil.sync_states <salt.modules.saltutil.sync_states>`, or
|
||||
:mod:`saltutil.sync_all <salt.modules.saltutil.sync_all>` is run.
|
||||
They are both also synced when a :ref:`highstate <running-highstate>` is
|
||||
triggered.
|
||||
|
||||
Custom states are also synced by :mod:`state.apply<salt.modules.state.apply_>`
|
||||
when run without any arguments.
|
||||
As of the Fluorine release, as well as 2017.7.7 and 2018.3.2 in their
|
||||
respective release cycles, the ``sync`` argument to :py:func:`state.apply
|
||||
<salt.modules.state.apply_>`/:py:func:`state.sls <salt.modules.state.sls>` can
|
||||
be used to sync custom types when running individual SLS files.
|
||||
|
||||
Other custom types (renderers, outputters, etc.) have similar behavior, see the
|
||||
documentation for the :mod:`saltutil <salt.modules.saltutil>` module for more
|
||||
documentation for the :py:func:`saltutil <salt.modules.saltutil>` module for more
|
||||
information.
|
||||
|
||||
:ref:`This reactor example <minion-start-reactor>` can be used to automatically
|
||||
|
|
|
@ -135,13 +135,18 @@ where it is necessary to invoke the same function from a custom :ref:`outputter
|
|||
<all-salt.output>`/returner, as well as an execution module.
|
||||
|
||||
Utility modules placed in ``salt://_utils/`` will be synced to the minions when
|
||||
any of the following Salt functions are called:
|
||||
a :ref:`highstate <running-highstate>` is run, as well as when any of the
|
||||
following Salt functions are called:
|
||||
|
||||
* :mod:`state.apply <salt.modules.state.apply_>`
|
||||
* :mod:`saltutil.sync_utils <salt.modules.saltutil.sync_utils>`
|
||||
* :mod:`saltutil.sync_all <salt.modules.saltutil.sync_all>`
|
||||
* :py:func:`saltutil.sync_utils <salt.modules.saltutil.sync_utils>`
|
||||
* :py:func:`saltutil.sync_all <salt.modules.saltutil.sync_all>`
|
||||
|
||||
As of the Fluorine release, as well as 2017.7.7 and 2018.3.2 in their
|
||||
respective release cycles, the ``sync`` argument to :py:func:`state.apply
|
||||
<salt.modules.state.apply_>`/:py:func:`state.sls <salt.modules.state.sls>` can
|
||||
be used to sync custom types when running individual SLS files.
|
||||
|
||||
To sync to the Master, use either of the following:
|
||||
|
||||
* :mod:`saltutil.sync_utils <salt.runners.saltutil.sync_utils>`
|
||||
* :mod:`saltutil.sync_all <salt.runners.saltutil.sync_all>`
|
||||
* :py:func:`saltutil.sync_utils <salt.runners.saltutil.sync_utils>`
|
||||
* :py:func:`saltutil.sync_all <salt.runners.saltutil.sync_all>`
|
||||
|
|
|
@ -458,8 +458,7 @@ def template_str(tem, queue=False, **kwargs):
|
|||
return ret
|
||||
|
||||
|
||||
def apply_(mods=None,
|
||||
**kwargs):
|
||||
def apply_(mods=None, **kwargs):
|
||||
'''
|
||||
.. versionadded:: 2015.5.0
|
||||
|
||||
|
@ -599,6 +598,22 @@ def apply_(mods=None,
|
|||
.. code-block:: bash
|
||||
|
||||
salt '*' state.apply test localconfig=/path/to/minion.yml
|
||||
|
||||
sync_mods
|
||||
If specified, the desired custom module types will be synced prior to
|
||||
running the SLS files:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
salt '*' state.apply test sync_mods=states,modules
|
||||
salt '*' state.apply test sync_mods=all
|
||||
|
||||
.. note::
|
||||
This option is ignored when no SLS files are specified, as a
|
||||
:ref:`highstate <running-highstate>` automatically syncs all custom
|
||||
module types.
|
||||
|
||||
.. versionadded:: 2017.7.8,2018.3.3,Fluorine
|
||||
'''
|
||||
if mods:
|
||||
return sls(mods, **kwargs)
|
||||
|
@ -928,7 +943,7 @@ def highstate(test=None, queue=False, **kwargs):
|
|||
return ret
|
||||
|
||||
|
||||
def sls(mods, test=None, exclude=None, queue=False, **kwargs):
|
||||
def sls(mods, test=None, exclude=None, queue=False, sync_mods=None, **kwargs):
|
||||
'''
|
||||
Execute the states in one or more SLS files
|
||||
|
||||
|
@ -1019,6 +1034,17 @@ def sls(mods, test=None, exclude=None, queue=False, **kwargs):
|
|||
|
||||
.. versionadded:: 2015.8.4
|
||||
|
||||
sync_mods
|
||||
If specified, the desired custom module types will be synced prior to
|
||||
running the SLS files:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
salt '*' state.sls test sync_mods=states,modules
|
||||
salt '*' state.sls test sync_mods=all
|
||||
|
||||
.. versionadded:: 2017.7.8,2018.3.3,Fluorine
|
||||
|
||||
CLI Example:
|
||||
|
||||
.. code-block:: bash
|
||||
|
@ -1087,6 +1113,28 @@ def sls(mods, test=None, exclude=None, queue=False, **kwargs):
|
|||
'{0}.cache.p'.format(kwargs.get('cache_name', 'highstate'))
|
||||
)
|
||||
|
||||
if sync_mods is True:
|
||||
sync_mods = ['all']
|
||||
if sync_mods is not None:
|
||||
sync_mods = salt.utils.split_input(sync_mods)
|
||||
else:
|
||||
sync_mods = []
|
||||
|
||||
if 'all' in sync_mods and sync_mods != ['all']:
|
||||
# Prevent unnecessary extra syncing
|
||||
sync_mods = ['all']
|
||||
|
||||
for module_type in sync_mods:
|
||||
try:
|
||||
__salt__['saltutil.sync_{0}'.format(module_type)](
|
||||
saltenv=opts['environment']
|
||||
)
|
||||
except KeyError:
|
||||
log.warning(
|
||||
'Invalid custom module type \'%s\', ignoring',
|
||||
module_type
|
||||
)
|
||||
|
||||
try:
|
||||
st_ = salt.state.HighState(opts,
|
||||
pillar_override,
|
||||
|
|
|
@ -11,6 +11,7 @@ import os
|
|||
from tests.support.mixins import LoaderModuleMockMixin
|
||||
from tests.support.unit import TestCase, skipIf
|
||||
from tests.support.mock import (
|
||||
Mock,
|
||||
MagicMock,
|
||||
patch,
|
||||
mock_open,
|
||||
|
@ -357,6 +358,9 @@ class StateTestCase(TestCase, LoaderModuleMockMixin):
|
|||
'environment': None,
|
||||
'__cli': 'salt',
|
||||
},
|
||||
'__salt__': {
|
||||
'config.option': MagicMock(return_value=''),
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
|
@ -752,28 +756,25 @@ class StateTestCase(TestCase, LoaderModuleMockMixin):
|
|||
"whitelist=sls1.sls",
|
||||
pillar="A")
|
||||
|
||||
mock = MagicMock(return_value=True)
|
||||
with patch.dict(state.__salt__,
|
||||
{'config.option': mock}):
|
||||
mock = MagicMock(return_value="A")
|
||||
mock = MagicMock(return_value="A")
|
||||
with patch.object(state, '_filter_running',
|
||||
mock):
|
||||
mock = MagicMock(return_value=True)
|
||||
with patch.object(state, '_filter_running',
|
||||
mock):
|
||||
mock = MagicMock(return_value=True)
|
||||
with patch.object(state, '_filter_running',
|
||||
with patch.object(salt.payload, 'Serial',
|
||||
mock):
|
||||
mock = MagicMock(return_value=True)
|
||||
with patch.object(salt.payload, 'Serial',
|
||||
mock):
|
||||
with patch.object(os.path,
|
||||
'join', mock):
|
||||
with patch.object(
|
||||
state,
|
||||
'_set'
|
||||
'_retcode',
|
||||
mock):
|
||||
self.assertTrue(state.
|
||||
highstate
|
||||
(arg))
|
||||
with patch.object(os.path,
|
||||
'join', mock):
|
||||
with patch.object(
|
||||
state,
|
||||
'_set'
|
||||
'_retcode',
|
||||
mock):
|
||||
self.assertTrue(state.
|
||||
highstate
|
||||
(arg))
|
||||
|
||||
def test_clear_request(self):
|
||||
'''
|
||||
|
@ -914,17 +915,11 @@ class StateTestCase(TestCase, LoaderModuleMockMixin):
|
|||
|
||||
MockState.HighState.flag = False
|
||||
mock = MagicMock(return_value=True)
|
||||
with patch.dict(state.__salt__,
|
||||
{'config.option':
|
||||
mock}):
|
||||
mock = MagicMock(return_value=
|
||||
True)
|
||||
with patch.object(
|
||||
state,
|
||||
'_filter_'
|
||||
'running',
|
||||
mock):
|
||||
self.sub_test_sls()
|
||||
with patch.object(state,
|
||||
'_filter_'
|
||||
'running',
|
||||
mock):
|
||||
self.sub_test_sls()
|
||||
|
||||
def sub_test_sls(self):
|
||||
'''
|
||||
|
@ -947,6 +942,75 @@ class StateTestCase(TestCase, LoaderModuleMockMixin):
|
|||
None,
|
||||
True))
|
||||
|
||||
def test_sls_sync(self):
|
||||
'''
|
||||
Test test.sls with the sync argument
|
||||
|
||||
We're only mocking the sync functions we expect to sync. If any other
|
||||
sync functions are run then they will raise a KeyError, which we want
|
||||
as it will tell us that we are syncing things we shouldn't.
|
||||
'''
|
||||
mock_empty_list = MagicMock(return_value=[])
|
||||
with patch.object(state, 'running', mock_empty_list), \
|
||||
patch.object(state, '_disabled', mock_empty_list), \
|
||||
patch.object(state, '_get_pillar_errors', mock_empty_list):
|
||||
|
||||
sync_mocks = {
|
||||
'saltutil.sync_modules': Mock(),
|
||||
'saltutil.sync_states': Mock(),
|
||||
}
|
||||
with patch.dict(state.__salt__, sync_mocks):
|
||||
state.sls('foo', sync_mods='modules,states')
|
||||
|
||||
for key in sync_mocks:
|
||||
call_count = sync_mocks[key].call_count
|
||||
expected = 1
|
||||
assert call_count == expected, \
|
||||
'{0} called {1} time(s) (expected: {2})'.format(
|
||||
key, call_count, expected
|
||||
)
|
||||
|
||||
# Test syncing all
|
||||
sync_mocks = {'saltutil.sync_all': Mock()}
|
||||
with patch.dict(state.__salt__, sync_mocks):
|
||||
state.sls('foo', sync_mods='all')
|
||||
|
||||
for key in sync_mocks:
|
||||
call_count = sync_mocks[key].call_count
|
||||
expected = 1
|
||||
assert call_count == expected, \
|
||||
'{0} called {1} time(s) (expected: {2})'.format(
|
||||
key, call_count, expected
|
||||
)
|
||||
|
||||
# sync_mods=True should be interpreted as sync_mods=all
|
||||
sync_mocks = {'saltutil.sync_all': Mock()}
|
||||
with patch.dict(state.__salt__, sync_mocks):
|
||||
state.sls('foo', sync_mods=True)
|
||||
|
||||
for key in sync_mocks:
|
||||
call_count = sync_mocks[key].call_count
|
||||
expected = 1
|
||||
assert call_count == expected, \
|
||||
'{0} called {1} time(s) (expected: {2})'.format(
|
||||
key, call_count, expected
|
||||
)
|
||||
|
||||
# Test syncing all when "all" is passed along with module types.
|
||||
# This tests that we *only* run a sync_all and avoid unnecessary
|
||||
# extra syncing.
|
||||
sync_mocks = {'saltutil.sync_all': Mock()}
|
||||
with patch.dict(state.__salt__, sync_mocks):
|
||||
state.sls('foo', sync_mods='modules,all')
|
||||
|
||||
for key in sync_mocks:
|
||||
call_count = sync_mocks[key].call_count
|
||||
expected = 1
|
||||
assert call_count == expected, \
|
||||
'{0} called {1} time(s) (expected: {2})'.format(
|
||||
key, call_count, expected
|
||||
)
|
||||
|
||||
def test_pkg(self):
|
||||
'''
|
||||
Test to execute a packaged state run
|
||||
|
|
Loading…
Add table
Reference in a new issue