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


openSUSE Build Service is sponsored by