859b845155
OBS-URL: https://build.opensuse.org/package/show/systemsmanagement:saltstack/salt?expand=0&rev=165
466 lines
14 KiB
Diff
466 lines
14 KiB
Diff
From d99badeda9818ba54a3af1d0145c5278fe0edee1 Mon Sep 17 00:00:00 2001
|
|
From: Christian McHugh <mchughc@dnb.com>
|
|
Date: Wed, 24 Oct 2018 15:49:58 +0100
|
|
Subject: [PATCH] Backport "saltutil" state module to 2019.2 codebase
|
|
|
|
add individual syncers and release note
|
|
|
|
add individual syncers
|
|
|
|
adjust state comment output and cleanup tests
|
|
---
|
|
salt/states/saltutil.py | 311 +++++++++++++++++++++++++++++
|
|
tests/unit/states/test_saltutil.py | 121 +++++++++++
|
|
2 files changed, 432 insertions(+)
|
|
create mode 100644 salt/states/saltutil.py
|
|
create mode 100644 tests/unit/states/test_saltutil.py
|
|
|
|
diff --git a/salt/states/saltutil.py b/salt/states/saltutil.py
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..99952a1b7d1b8a70bac940ec083eb75776c146c6
|
|
--- /dev/null
|
|
+++ b/salt/states/saltutil.py
|
|
@@ -0,0 +1,311 @@
|
|
+# -*- coding: utf-8 -*-
|
|
+'''
|
|
+Saltutil State
|
|
+==============
|
|
+
|
|
+This state wraps the saltutil execution modules to make them easier to run
|
|
+from a states. Rather than needing to to use ``module.run`` this state allows for
|
|
+improved change detection.
|
|
+
|
|
+ .. versionadded: Neon
|
|
+'''
|
|
+from __future__ import absolute_import, unicode_literals, print_function
|
|
+
|
|
+import logging
|
|
+
|
|
+# Define the module's virtual name
|
|
+__virtualname__ = 'saltutil'
|
|
+
|
|
+log = logging.getLogger(__name__)
|
|
+
|
|
+
|
|
+def __virtual__():
|
|
+ '''
|
|
+ Named saltutil
|
|
+ '''
|
|
+ return __virtualname__
|
|
+
|
|
+
|
|
+def _sync_single(name, module, **kwargs):
|
|
+ ret = {'name': name, 'changes': {}, 'result': True, 'comment': ''}
|
|
+
|
|
+ if __opts__['test']:
|
|
+ ret['result'] = None
|
|
+ ret['comment'] = "saltutil.sync_{0} would have been run".format(module)
|
|
+ return ret
|
|
+
|
|
+ try:
|
|
+ sync_status = __salt__['saltutil.sync_{0}'.format(module)](**kwargs)
|
|
+ if sync_status:
|
|
+ ret['changes'][module] = sync_status
|
|
+ ret['comment'] = "Updated {0}.".format(module)
|
|
+ except Exception as e:
|
|
+ log.error("Failed to run saltutil.sync_%s: %s", module, e)
|
|
+ ret['result'] = False
|
|
+ ret['comment'] = "Failed to run sync_{0}: {1}".format(module, e)
|
|
+ return ret
|
|
+
|
|
+ if not ret['changes']:
|
|
+ ret['comment'] = "No updates to sync"
|
|
+
|
|
+ return ret
|
|
+
|
|
+
|
|
+def sync_all(name, **kwargs):
|
|
+ '''
|
|
+ Performs the same task as saltutil.sync_all module
|
|
+ See :mod:`saltutil module for full list of options <salt.modules.saltutil>`
|
|
+
|
|
+ .. code-block:: yaml
|
|
+
|
|
+ sync_everything:
|
|
+ saltutil.sync_all:
|
|
+ - refresh: True
|
|
+ '''
|
|
+ ret = {'name': name, 'changes': {}, 'result': True, 'comment': ''}
|
|
+
|
|
+ if __opts__['test']:
|
|
+ ret['result'] = None
|
|
+ ret['comment'] = "saltutil.sync_all would have been run"
|
|
+ return ret
|
|
+
|
|
+ try:
|
|
+ sync_status = __salt__['saltutil.sync_all'](**kwargs)
|
|
+ for key, value in sync_status.items():
|
|
+ if value:
|
|
+ ret['changes'][key] = value
|
|
+ ret['comment'] = "Sync performed"
|
|
+ except Exception as e:
|
|
+ log.error("Failed to run saltutil.sync_all: %s", e)
|
|
+ ret['result'] = False
|
|
+ ret['comment'] = "Failed to run sync_all: {0}".format(e)
|
|
+ return ret
|
|
+
|
|
+ if not ret['changes']:
|
|
+ ret['comment'] = "No updates to sync"
|
|
+
|
|
+ return ret
|
|
+
|
|
+
|
|
+def sync_beacons(name, **kwargs):
|
|
+ '''
|
|
+ Performs the same task as saltutil.sync_beacons module
|
|
+ See :mod:`saltutil module for full list of options <salt.modules.saltutil>`
|
|
+
|
|
+ .. code-block:: yaml
|
|
+
|
|
+ sync_everything:
|
|
+ saltutil.sync_beacons:
|
|
+ - refresh: True
|
|
+ '''
|
|
+ return _sync_single(name, "beacons", **kwargs)
|
|
+
|
|
+
|
|
+def sync_clouds(name, **kwargs):
|
|
+ '''
|
|
+ Performs the same task as saltutil.sync_clouds module
|
|
+ See :mod:`saltutil module for full list of options <salt.modules.saltutil>`
|
|
+
|
|
+ .. code-block:: yaml
|
|
+
|
|
+ sync_everything:
|
|
+ saltutil.sync_clouds:
|
|
+ - refresh: True
|
|
+ '''
|
|
+ return _sync_single(name, "clouds", **kwargs)
|
|
+
|
|
+
|
|
+def sync_engines(name, **kwargs):
|
|
+ '''
|
|
+ Performs the same task as saltutil.sync_engines module
|
|
+ See :mod:`saltutil module for full list of options <salt.modules.saltutil>`
|
|
+
|
|
+ .. code-block:: yaml
|
|
+
|
|
+ sync_everything:
|
|
+ saltutil.sync_engines:
|
|
+ - refresh: True
|
|
+ '''
|
|
+ return _sync_single(name, "engines", **kwargs)
|
|
+
|
|
+
|
|
+def sync_grains(name, **kwargs):
|
|
+ '''
|
|
+ Performs the same task as saltutil.sync_grains module
|
|
+ See :mod:`saltutil module for full list of options <salt.modules.saltutil>`
|
|
+
|
|
+ .. code-block:: yaml
|
|
+
|
|
+ sync_everything:
|
|
+ saltutil.sync_grains:
|
|
+ - refresh: True
|
|
+ '''
|
|
+ return _sync_single(name, "grains", **kwargs)
|
|
+
|
|
+
|
|
+def sync_log_handlers(name, **kwargs):
|
|
+ '''
|
|
+ Performs the same task as saltutil.sync_log_handlers module
|
|
+ See :mod:`saltutil module for full list of options <salt.modules.saltutil>`
|
|
+
|
|
+ .. code-block:: yaml
|
|
+
|
|
+ sync_everything:
|
|
+ saltutil.sync_log_handlers:
|
|
+ - refresh: True
|
|
+ '''
|
|
+ return _sync_single(name, "log_handlers", **kwargs)
|
|
+
|
|
+
|
|
+def sync_modules(name, **kwargs):
|
|
+ '''
|
|
+ Performs the same task as saltutil.sync_modules module
|
|
+ See :mod:`saltutil module for full list of options <salt.modules.saltutil>`
|
|
+
|
|
+ .. code-block:: yaml
|
|
+
|
|
+ sync_everything:
|
|
+ saltutil.sync_modules:
|
|
+ - refresh: True
|
|
+ '''
|
|
+ return _sync_single(name, "modules", **kwargs)
|
|
+
|
|
+
|
|
+def sync_output(name, **kwargs):
|
|
+ '''
|
|
+ Performs the same task as saltutil.sync_output module
|
|
+ See :mod:`saltutil module for full list of options <salt.modules.saltutil>`
|
|
+
|
|
+ .. code-block:: yaml
|
|
+
|
|
+ sync_everything:
|
|
+ saltutil.sync_output:
|
|
+ - refresh: True
|
|
+ '''
|
|
+ return _sync_single(name, "output", **kwargs)
|
|
+
|
|
+
|
|
+def sync_outputters(name, **kwargs):
|
|
+ '''
|
|
+ Performs the same task as saltutil.sync_outputters module
|
|
+ See :mod:`saltutil module for full list of options <salt.modules.saltutil>`
|
|
+
|
|
+ .. code-block:: yaml
|
|
+
|
|
+ sync_everything:
|
|
+ saltutil.sync_outputters:
|
|
+ - refresh: True
|
|
+ '''
|
|
+ return _sync_single(name, "outputters", **kwargs)
|
|
+
|
|
+
|
|
+def sync_pillar(name, **kwargs):
|
|
+ '''
|
|
+ Performs the same task as saltutil.sync_pillar module
|
|
+ See :mod:`saltutil module for full list of options <salt.modules.saltutil>`
|
|
+
|
|
+ .. code-block:: yaml
|
|
+
|
|
+ sync_everything:
|
|
+ saltutil.sync_pillar:
|
|
+ - refresh: True
|
|
+ '''
|
|
+ return _sync_single(name, "pillar", **kwargs)
|
|
+
|
|
+
|
|
+def sync_proxymodules(name, **kwargs):
|
|
+ '''
|
|
+ Performs the same task as saltutil.sync_proxymodules module
|
|
+ See :mod:`saltutil module for full list of options <salt.modules.saltutil>`
|
|
+
|
|
+ .. code-block:: yaml
|
|
+
|
|
+ sync_everything:
|
|
+ saltutil.sync_proxymodules:
|
|
+ - refresh: True
|
|
+ '''
|
|
+ return _sync_single(name, "proxymodules", **kwargs)
|
|
+
|
|
+
|
|
+def sync_renderers(name, **kwargs):
|
|
+ '''
|
|
+ Performs the same task as saltutil.sync_renderers module
|
|
+ See :mod:`saltutil module for full list of options <salt.modules.saltutil>`
|
|
+
|
|
+ .. code-block:: yaml
|
|
+
|
|
+ sync_everything:
|
|
+ saltutil.sync_renderers:
|
|
+ - refresh: True
|
|
+ '''
|
|
+ return _sync_single(name, "renderers", **kwargs)
|
|
+
|
|
+
|
|
+def sync_returners(name, **kwargs):
|
|
+ '''
|
|
+ Performs the same task as saltutil.sync_returners module
|
|
+ See :mod:`saltutil module for full list of options <salt.modules.saltutil>`
|
|
+
|
|
+ .. code-block:: yaml
|
|
+
|
|
+ sync_everything:
|
|
+ saltutil.sync_returners:
|
|
+ - refresh: True
|
|
+ '''
|
|
+ return _sync_single(name, "returners", **kwargs)
|
|
+
|
|
+
|
|
+def sync_sdb(name, **kwargs):
|
|
+ '''
|
|
+ Performs the same task as saltutil.sync_sdb module
|
|
+ See :mod:`saltutil module for full list of options <salt.modules.saltutil>`
|
|
+
|
|
+ .. code-block:: yaml
|
|
+
|
|
+ sync_everything:
|
|
+ saltutil.sync_sdb:
|
|
+ - refresh: True
|
|
+ '''
|
|
+ return _sync_single(name, "sdb", **kwargs)
|
|
+
|
|
+
|
|
+def sync_states(name, **kwargs):
|
|
+ '''
|
|
+ Performs the same task as saltutil.sync_states module
|
|
+ See :mod:`saltutil module for full list of options <salt.modules.saltutil>`
|
|
+
|
|
+ .. code-block:: yaml
|
|
+
|
|
+ sync_everything:
|
|
+ saltutil.sync_states:
|
|
+ - refresh: True
|
|
+ '''
|
|
+ return _sync_single(name, "states", **kwargs)
|
|
+
|
|
+
|
|
+def sync_thorium(name, **kwargs):
|
|
+ '''
|
|
+ Performs the same task as saltutil.sync_thorium module
|
|
+ See :mod:`saltutil module for full list of options <salt.modules.saltutil>`
|
|
+
|
|
+ .. code-block:: yaml
|
|
+
|
|
+ sync_everything:
|
|
+ saltutil.sync_thorium:
|
|
+ - refresh: True
|
|
+ '''
|
|
+ return _sync_single(name, "thorium", **kwargs)
|
|
+
|
|
+
|
|
+def sync_utils(name, **kwargs):
|
|
+ '''
|
|
+ Performs the same task as saltutil.sync_utils module
|
|
+ See :mod:`saltutil module for full list of options <salt.modules.saltutil>`
|
|
+
|
|
+ .. code-block:: yaml
|
|
+
|
|
+ sync_everything:
|
|
+ saltutil.sync_utils:
|
|
+ - refresh: True
|
|
+ '''
|
|
+ return _sync_single(name, "utils", **kwargs)
|
|
diff --git a/tests/unit/states/test_saltutil.py b/tests/unit/states/test_saltutil.py
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..707201e9e2d3c285ed497e7f497158907a1834eb
|
|
--- /dev/null
|
|
+++ b/tests/unit/states/test_saltutil.py
|
|
@@ -0,0 +1,121 @@
|
|
+# -*- coding: utf-8 -*-
|
|
+'''
|
|
+ Tests for the saltutil state
|
|
+'''
|
|
+# Import Python libs
|
|
+from __future__ import absolute_import, print_function, unicode_literals
|
|
+
|
|
+# Import Salt Testing Libs
|
|
+from tests.support.mixins import LoaderModuleMockMixin
|
|
+from tests.support.unit import skipIf, TestCase
|
|
+from tests.support.mock import (
|
|
+ NO_MOCK,
|
|
+ NO_MOCK_REASON,
|
|
+ MagicMock,
|
|
+ patch
|
|
+)
|
|
+
|
|
+# Import Salt Libs
|
|
+import salt.states.saltutil as saltutil
|
|
+
|
|
+
|
|
+@skipIf(NO_MOCK, NO_MOCK_REASON)
|
|
+class Saltutil(TestCase, LoaderModuleMockMixin):
|
|
+ '''
|
|
+ Test cases for salt.states.saltutil
|
|
+ '''
|
|
+ def setup_loader_modules(self):
|
|
+ return {saltutil: {'__opts__': {'test': False}}}
|
|
+
|
|
+ def test_saltutil_sync_all_nochange(self):
|
|
+ sync_output = {
|
|
+ "clouds": [],
|
|
+ "engines": [],
|
|
+ "grains": [],
|
|
+ "beacons": [],
|
|
+ "utils": [],
|
|
+ "returners": [],
|
|
+ "modules": [],
|
|
+ "renderers": [],
|
|
+ "log_handlers": [],
|
|
+ "thorium": [],
|
|
+ "states": [],
|
|
+ "sdb": [],
|
|
+ "proxymodules": [],
|
|
+ "output": [],
|
|
+ "pillar": []
|
|
+ }
|
|
+ state_id = 'somename'
|
|
+ state_result = {'changes': {},
|
|
+ 'comment': 'No updates to sync',
|
|
+ 'name': 'somename',
|
|
+ 'result': True
|
|
+ }
|
|
+
|
|
+ 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)
|
|
+ self.assertEqual(result, state_result)
|
|
+
|
|
+ def test_saltutil_sync_all_test(self):
|
|
+ sync_output = {
|
|
+ "clouds": [],
|
|
+ "engines": [],
|
|
+ "grains": [],
|
|
+ "beacons": [],
|
|
+ "utils": [],
|
|
+ "returners": [],
|
|
+ "modules": [],
|
|
+ "renderers": [],
|
|
+ "log_handlers": [],
|
|
+ "thorium": [],
|
|
+ "states": [],
|
|
+ "sdb": [],
|
|
+ "proxymodules": [],
|
|
+ "output": [],
|
|
+ "pillar": []
|
|
+ }
|
|
+ state_id = 'somename'
|
|
+ state_result = {'changes': {},
|
|
+ 'comment': 'saltutil.sync_all would have been run',
|
|
+ 'name': 'somename',
|
|
+ 'result': None
|
|
+ }
|
|
+
|
|
+ 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)
|
|
+ self.assertEqual(result, state_result)
|
|
+
|
|
+
|
|
+ def test_saltutil_sync_all_change(self):
|
|
+ sync_output = {
|
|
+ "clouds": [],
|
|
+ "engines": [],
|
|
+ "grains": [],
|
|
+ "beacons": [],
|
|
+ "utils": [],
|
|
+ "returners": [],
|
|
+ "modules": ["modules.file"],
|
|
+ "renderers": [],
|
|
+ "log_handlers": [],
|
|
+ "thorium": [],
|
|
+ "states": ["states.saltutil", "states.ssh_auth"],
|
|
+ "sdb": [],
|
|
+ "proxymodules": [],
|
|
+ "output": [],
|
|
+ "pillar": []
|
|
+ }
|
|
+ state_id = 'somename'
|
|
+ state_result = {'changes': {'modules': ['modules.file'],
|
|
+ 'states': ['states.saltutil', 'states.ssh_auth']},
|
|
+ 'comment': 'Sync performed',
|
|
+ 'name': 'somename',
|
|
+ 'result': True
|
|
+ }
|
|
+
|
|
+ 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)
|
|
+ self.assertEqual(result, state_result)
|
|
--
|
|
2.23.0
|
|
|
|
|