diff --git a/doc/ref/states/all/index.rst b/doc/ref/states/all/index.rst index 686caf7054f7..d1a81bcbc583 100644 --- a/doc/ref/states/all/index.rst +++ b/doc/ref/states/all/index.rst @@ -258,6 +258,7 @@ state modules rvm salt_proxy saltmod + saltutil schedule selinux serverdensity_device diff --git a/doc/ref/states/all/salt.states.saltutil.rst b/doc/ref/states/all/salt.states.saltutil.rst new file mode 100644 index 000000000000..f9e0360eb832 --- /dev/null +++ b/doc/ref/states/all/salt.states.saltutil.rst @@ -0,0 +1,6 @@ +==================== +salt.states.saltutil +==================== + +.. automodule:: salt.states.saltutil + :members: \ No newline at end of file diff --git a/doc/topics/development/modules/index.rst b/doc/topics/development/modules/index.rst index 7b9918c00bc4..d2598ab62aa2 100644 --- a/doc/topics/development/modules/index.rst +++ b/doc/topics/development/modules/index.rst @@ -69,6 +69,16 @@ dynamic modules when states are run. To disable this behavior set When dynamic modules are autoloaded via states, only the modules defined in the same saltenvs as the states currently being run. +Also it is possible to use the explicit ``saltutil.sync_*`` :py:mod:`state functions ` +to sync the modules (previously it was necessary to use the ``module.run`` state): + +.. code-block::yaml + + synchronize_modules: + saltutil.sync_modules: + - refresh: True + + Sync Via the saltutil Module ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/salt/states/saltutil.py b/salt/states/saltutil.py index 9e4fd99ece40..5cf98f36ac25 100644 --- a/salt/states/saltutil.py +++ b/salt/states/saltutil.py @@ -241,6 +241,20 @@ def sync_proxymodules(name, **kwargs): return _sync_single(name, "proxymodules", **kwargs) +def sync_matchers(name, **kwargs): + ''' + Performs the same task as saltutil.sync_matchers module + See :mod:`saltutil module for full list of options ` + + .. code-block:: yaml + + sync_everything: + saltutil.sync_matchers: + - refresh: True + ''' + return _sync_single(name, "matchers", **kwargs) + + def sync_renderers(name, **kwargs): ''' Performs the same task as saltutil.sync_renderers module @@ -323,3 +337,17 @@ def sync_utils(name, **kwargs): - refresh: True ''' return _sync_single(name, "utils", **kwargs) + + +def sync_serializers(name, **kwargs): + ''' + Performs the same task as saltutil.sync_serializers module + See :mod:`saltutil module for full list of options ` + + .. code-block:: yaml + + sync_everything: + saltutil.sync_serializers: + - refresh: True + ''' + return _sync_single(name, "serializers", **kwargs) diff --git a/tests/unit/states/test_saltutil.py b/tests/unit/states/test_saltutil.py index 222b2bd10ce5..598f18734eb1 100644 --- a/tests/unit/states/test_saltutil.py +++ b/tests/unit/states/test_saltutil.py @@ -5,6 +5,8 @@ # Import Python libs from __future__ import absolute_import, print_function, unicode_literals +import inspect + # Import Salt Testing Libs from tests.support.mixins import LoaderModuleMockMixin from tests.support.unit import skipIf, TestCase @@ -16,7 +18,8 @@ ) # Import Salt Libs -import salt.states.saltutil as saltutil +import salt.states.saltutil as saltutil_state +import salt.modules.saltutil as saltutil_module @skipIf(NO_MOCK, NO_MOCK_REASON) @@ -25,7 +28,7 @@ class Saltutil(TestCase, LoaderModuleMockMixin): Test cases for salt.states.saltutil ''' def setup_loader_modules(self): - return {saltutil: {'__opts__': {'test': False}}} + return {saltutil_state: {'__opts__': {'test': False}}} def test_saltutil_sync_all_nochange(self): sync_output = { @@ -45,6 +48,8 @@ def test_saltutil_sync_all_nochange(self): 'proxymodules': [], 'output': [], 'pillar': [], + 'matchers': [], + 'serializers': [], } state_id = 'somename' state_result = {'changes': {}, @@ -54,8 +59,8 @@ def test_saltutil_sync_all_nochange(self): } mock_moduleout = MagicMock(return_value=sync_output) - with patch.dict(saltutil.__salt__, {'saltutil.sync_all': mock_moduleout}): - result = saltutil.sync_all(state_id, refresh=True) + with patch.dict(saltutil_state.__salt__, {'saltutil.sync_all': mock_moduleout}): + result = saltutil_state.sync_all(state_id, refresh=True) self.assertEqual(result, state_result) def test_saltutil_sync_all_test(self): @@ -76,6 +81,8 @@ def test_saltutil_sync_all_test(self): 'proxymodules': [], 'output': [], 'pillar': [], + 'matchers': [], + 'serializers': [], } state_id = 'somename' state_result = {'changes': {}, @@ -85,9 +92,9 @@ def test_saltutil_sync_all_test(self): } mock_moduleout = MagicMock(return_value=sync_output) - with patch.dict(saltutil.__salt__, {'saltutil.sync_all': mock_moduleout}): - with patch.dict(saltutil.__opts__, {'test': True}): - result = saltutil.sync_all(state_id, refresh=True) + with patch.dict(saltutil_state.__salt__, {'saltutil.sync_all': mock_moduleout}): + with patch.dict(saltutil_state.__opts__, {'test': True}): + result = saltutil_state.sync_all(state_id, refresh=True) self.assertEqual(result, state_result) def test_saltutil_sync_all_change(self): @@ -108,6 +115,8 @@ def test_saltutil_sync_all_change(self): 'proxymodules': [], 'output': [], 'pillar': [], + 'matchers': [], + 'serializers': [], } state_id = 'somename' state_result = {'changes': {'modules': ['modules.file'], @@ -118,6 +127,22 @@ def test_saltutil_sync_all_change(self): } mock_moduleout = MagicMock(return_value=sync_output) - with patch.dict(saltutil.__salt__, {'saltutil.sync_all': mock_moduleout}): - result = saltutil.sync_all(state_id, refresh=True) + with patch.dict(saltutil_state.__salt__, {'saltutil.sync_all': mock_moduleout}): + result = saltutil_state.sync_all(state_id, refresh=True) self.assertEqual(result, state_result) + + def test_saltutil_sync_states_should_match_saltutil_module(self): + module_functions = [ + f[0] for f in inspect.getmembers(saltutil_module, inspect.isfunction) + if f[0].startswith('sync_') + ] + state_functions = [ + f[0] for f in inspect.getmembers(saltutil_state, inspect.isfunction) + if f[0].startswith('sync_') + ] + for fn in module_functions: + self.assertIn( + fn, + state_functions, + msg='modules.saltutil.{} has no matching state in states.saltutil'.format(fn) + )