132 lines
4.8 KiB
Diff
132 lines
4.8 KiB
Diff
|
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
|
||
|
|
||
|
|