File explore-module.run-response-to-catch-the-result-in-d.patch of Package salt.8688
From 8c6b77bfd913b3b47d3d4206ec0a9e08754b6f93 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Pablo=20Su=C3=A1rez=20Hern=C3=A1ndez?=
<psuarezhernandez@suse.com>
Date: Wed, 7 Mar 2018 09:42:46 +0000
Subject: [PATCH] Explore 'module.run' response to catch the 'result' in
depth
Fix Python3 and pylint issue
Rename and fix recursive method
Add new unit test to check state.apply within module.run
---
salt/states/module.py | 18 ++++++++++++
tests/unit/states/test_module.py | 62 ++++++++++++++++++++++++++++++++++++++++
2 files changed, 80 insertions(+)
diff --git a/salt/states/module.py b/salt/states/module.py
index fda8bdf17a..2190ffa3d2 100644
--- a/salt/states/module.py
+++ b/salt/states/module.py
@@ -531,7 +531,25 @@ def _get_result(func_ret, changes):
res = changes_ret.get('result', {})
elif changes_ret.get('retcode', 0) != 0:
res = False
+ # Explore dict in depth to determine if there is a
+ # 'result' key set to False which sets the global
+ # state result.
+ else:
+ res = _get_dict_result(changes_ret)
return res
+
+def _get_dict_result(node):
+ ret = True
+ for key, val in six.iteritems(node):
+ if key == 'result' and val is False:
+ ret = False
+ break
+ elif isinstance(val, dict):
+ ret = _get_dict_result(val)
+ if ret is False:
+ break
+ return ret
+
mod_watch = salt.utils.functools.alias_function(run, 'mod_watch')
diff --git a/tests/unit/states/test_module.py b/tests/unit/states/test_module.py
index 12ad54f979..bf4ddcc5b4 100644
--- a/tests/unit/states/test_module.py
+++ b/tests/unit/states/test_module.py
@@ -25,6 +25,57 @@ log = logging.getLogger(__name__)
CMD = 'foo.bar'
+STATE_APPLY_RET = {
+ 'module_|-test2_|-state.apply_|-run': {
+ 'comment': 'Module function state.apply executed',
+ 'name': 'state.apply',
+ 'start_time': '16:11:48.818932',
+ 'result': False,
+ 'duration': 179.439,
+ '__run_num__': 0,
+ 'changes': {
+ 'ret': {
+ 'module_|-test3_|-state.apply_|-run': {
+ 'comment': 'Module function state.apply executed',
+ 'name': 'state.apply',
+ 'start_time': '16:11:48.904796',
+ 'result': True,
+ 'duration': 89.522,
+ '__run_num__': 0,
+ 'changes': {
+ 'ret': {
+ 'module_|-test4_|-cmd.run_|-run': {
+ 'comment': 'Module function cmd.run executed',
+ 'name': 'cmd.run',
+ 'start_time': '16:11:48.988574',
+ 'result': True,
+ 'duration': 4.543,
+ '__run_num__': 0,
+ 'changes': {
+ 'ret': 'Wed Mar 7 16:11:48 CET 2018'
+ },
+ '__id__': 'test4'
+ }
+ }
+ },
+ '__id__': 'test3'
+ },
+ 'module_|-test3_fail_|-test3_fail_|-run': {
+ 'comment': 'Module function test3_fail is not available',
+ 'name': 'test3_fail',
+ 'start_time': '16:11:48.994607',
+ 'result': False,
+ 'duration': 0.466,
+ '__run_num__': 1,
+ 'changes': {},
+ '__id__': 'test3_fail'
+ }
+ }
+ },
+ '__id__': 'test2'
+ }
+}
+
def _mocked_func_named(name, names=('Fred', 'Swen',)):
'''
@@ -140,6 +191,17 @@ class ModuleStateTest(TestCase, LoaderModuleMockMixin):
if ret['comment'] != '{0}: Success'.format(CMD) or not ret['result']:
self.fail('module.run failed: {0}'.format(ret))
+ def test_run_state_apply_result_false(self):
+ '''
+ Tests the 'result' of module.run that calls state.apply execution module
+ :return:
+ '''
+ with patch.dict(module.__salt__, {"state.apply": MagicMock(return_value=STATE_APPLY_RET)}):
+ with patch.dict(module.__opts__, {'use_deprecated': ['module.run']}):
+ ret = module.run(**{"name": "state.apply", 'mods': 'test2'})
+ if ret['result']:
+ self.fail('module.run did not report false result: {0}'.format(ret))
+
def test_run_unexpected_keywords(self):
with patch.dict(module.__salt__, {CMD: _mocked_func_args}):
with patch.dict(module.__opts__, {'use_superseded': ['module.run']}):
--
2.16.2