summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTobias Henkel <tobias.henkel@bmw.de>2019-03-03 19:28:11 +0100
committerTobias Henkel <tobias.henkel@bmw.de>2019-03-06 21:51:33 +0100
commit6f754dd87876486631508fecf28bf7af460d1689 (patch)
treeee648fd7e37a001f268da22b17a366b192657414
parentf72682f4772a4b88073ced489cce142c2fef0718 (diff)
Log exception on module failure with empty stdout
In the zuul_stream callback we check for 'MODULE FAILURE' and then log stdout, exception or stderr whichever we find first. However in some cases stdout exists but is empty. In this case we don't log the error reason and the user needs to look into the json log which contains the correct information. This can be easily fixed by checking if stdout is empty. Change-Id: I8019d40e2e99310eaeab03f652368dac66e1ee17
Notes
Notes (review): Code-Review+2: James E. Blair <corvus@inaugust.com> Code-Review+2: Monty Taylor <mordred@inaugust.com> Workflow+1: Monty Taylor <mordred@inaugust.com> Verified+2: Zuul Submitted-by: Zuul Submitted-at: Thu, 07 Mar 2019 22:18:31 +0000 Reviewed-on: https://review.openstack.org/640650 Project: openstack-infra/zuul Branch: refs/heads/master
-rw-r--r--tests/fixtures/config/remote-zuul-stream/git/org_project/playbooks/command.yaml16
-rw-r--r--tests/remote/test_remote_zuul_stream.py9
-rw-r--r--zuul/ansible/callback/zuul_stream.py54
3 files changed, 45 insertions, 34 deletions
diff --git a/tests/fixtures/config/remote-zuul-stream/git/org_project/playbooks/command.yaml b/tests/fixtures/config/remote-zuul-stream/git/org_project/playbooks/command.yaml
index 6081351..7839494 100644
--- a/tests/fixtures/config/remote-zuul-stream/git/org_project/playbooks/command.yaml
+++ b/tests/fixtures/config/remote-zuul-stream/git/org_project/playbooks/command.yaml
@@ -82,3 +82,19 @@
82 - failed_in_loop1 82 - failed_in_loop1
83 - failed_in_loop2 83 - failed_in_loop2
84 ignore_errors: True 84 ignore_errors: True
85
86- hosts: all
87 tasks:
88 - name: Remote shell task with python exception
89 command: echo foo
90 args:
91 chdir: /remote-shelltask/somewhere/that/does/not/exist
92 failed_when: false
93
94- hosts: localhost
95 tasks:
96 - name: Local shell task with python exception
97 command: echo foo
98 args:
99 chdir: /local-shelltask/somewhere/that/does/not/exist
100 failed_when: false
diff --git a/tests/remote/test_remote_zuul_stream.py b/tests/remote/test_remote_zuul_stream.py
index 91139f4..686a68c 100644
--- a/tests/remote/test_remote_zuul_stream.py
+++ b/tests/remote/test_remote_zuul_stream.py
@@ -133,6 +133,15 @@ class TestZuulStream(AnsibleZuulTestCase):
133 self.assertLogLine(r'compute1 \| failed_in_loop2', text) 133 self.assertLogLine(r'compute1 \| failed_in_loop2', text)
134 self.assertLogLine(r'compute1 \| ok: Item: failed_in_loop2 ' 134 self.assertLogLine(r'compute1 \| ok: Item: failed_in_loop2 '
135 r'Result: 1', text) 135 r'Result: 1', text)
136 self.assertLogLine(r'localhost \| .*No such file or directory: .*'
137 r'\'/local-shelltask/somewhere/'
138 r'that/does/not/exist\'', text)
139 self.assertLogLine(r'compute1 \| .*No such file or directory: .*'
140 r'\'/remote-shelltask/somewhere/'
141 r'that/does/not/exist\'', text)
142 self.assertLogLine(r'controller \| .*No such file or directory: .*'
143 r'\'/remote-shelltask/somewhere/'
144 r'that/does/not/exist\'', text)
136 self.assertLogLine( 145 self.assertLogLine(
137 r'controller \| ok: Runtime: \d:\d\d:\d\d\.\d\d\d\d\d\d', text) 146 r'controller \| ok: Runtime: \d:\d\d:\d\d\.\d\d\d\d\d\d', text)
138 self.assertLogLine('PLAY RECAP', text) 147 self.assertLogLine('PLAY RECAP', text)
diff --git a/zuul/ansible/callback/zuul_stream.py b/zuul/ansible/callback/zuul_stream.py
index 36ee465..966c900 100644
--- a/zuul/ansible/callback/zuul_stream.py
+++ b/zuul/ansible/callback/zuul_stream.py
@@ -182,6 +182,20 @@ class CallbackModule(default.CallbackModule):
182 self._log("%s | %s " % (host, ln), ts=ts) 182 self._log("%s | %s " % (host, ln), ts=ts)
183 return False 183 return False
184 184
185 def _log_module_failure(self, result, result_dict):
186 if 'module_stdout' in result_dict and result_dict['module_stdout']:
187 self._log_message(
188 result, status='MODULE FAILURE',
189 msg=result_dict['module_stdout'])
190 elif 'exception' in result_dict and result_dict['exception']:
191 self._log_message(
192 result, status='MODULE FAILURE',
193 msg=result_dict['exception'])
194 elif 'module_stderr' in result_dict:
195 self._log_message(
196 result, status='MODULE FAILURE',
197 msg=result_dict['module_stderr'])
198
185 def v2_playbook_on_start(self, playbook): 199 def v2_playbook_on_start(self, playbook):
186 self._playbook_name = os.path.splitext(playbook._file_name)[0] 200 self._playbook_name = os.path.splitext(playbook._file_name)[0]
187 201
@@ -311,18 +325,7 @@ class CallbackModule(default.CallbackModule):
311 # items have their own events 325 # items have their own events
312 pass 326 pass
313 elif (result_dict.get('msg') == 'MODULE FAILURE'): 327 elif (result_dict.get('msg') == 'MODULE FAILURE'):
314 if 'module_stdout' in result_dict: 328 self._log_module_failure(result, result_dict)
315 self._log_message(
316 result, status='MODULE FAILURE',
317 msg=result_dict['module_stdout'])
318 elif 'exception' in result_dict:
319 self._log_message(
320 result, status='MODULE FAILURE',
321 msg=result_dict['exception'])
322 elif 'module_stderr' in result_dict:
323 self._log_message(
324 result, status='MODULE FAILURE',
325 msg=result_dict['module_stderr'])
326 else: 329 else:
327 self._log_message( 330 self._log_message(
328 result=result, status='ERROR', result_dict=result_dict) 331 result=result, status='ERROR', result_dict=result_dict)
@@ -388,18 +391,7 @@ class CallbackModule(default.CallbackModule):
388 pass 391 pass
389 392
390 elif (result_dict.get('msg') == 'MODULE FAILURE'): 393 elif (result_dict.get('msg') == 'MODULE FAILURE'):
391 if 'module_stdout' in result_dict: 394 self._log_module_failure(result, result_dict)
392 self._log_message(
393 result, status='MODULE FAILURE',
394 msg=result_dict['module_stdout'])
395 elif 'exception' in result_dict:
396 self._log_message(
397 result, status='MODULE FAILURE',
398 msg=result_dict['exception'])
399 elif 'module_stderr' in result_dict:
400 self._log_message(
401 result, status='MODULE FAILURE',
402 msg=result_dict['module_stderr'])
403 elif result._task.action == 'debug': 395 elif result._task.action == 'debug':
404 # this is a debug statement, handle it special 396 # this is a debug statement, handle it special
405 for key in [k for k in result_dict 397 for key in [k for k in result_dict
@@ -454,11 +446,8 @@ class CallbackModule(default.CallbackModule):
454 else: 446 else:
455 status = 'ok' 447 status = 'ok'
456 448
457 if (result_dict.get('msg') == 'MODULE FAILURE' and 449 if result_dict.get('msg') == 'MODULE FAILURE':
458 'module_stdout' in result_dict): 450 self._log_module_failure(result, result_dict)
459 self._log_message(
460 result, status='MODULE FAILURE',
461 msg="Item: {item}\n{module_stdout}".format(**result_dict))
462 elif result._task.action not in ('command', 'shell', 451 elif result._task.action not in ('command', 'shell',
463 'win_command', 'win_shell'): 452 'win_command', 'win_shell'):
464 if 'msg' in result_dict: 453 if 'msg' in result_dict:
@@ -493,11 +482,8 @@ class CallbackModule(default.CallbackModule):
493 result_dict = dict(result._result) 482 result_dict = dict(result._result)
494 self._process_result_for_localhost(result, is_task=False) 483 self._process_result_for_localhost(result, is_task=False)
495 484
496 if (result_dict.get('msg') == 'MODULE FAILURE' and 485 if result_dict.get('msg') == 'MODULE FAILURE':
497 'module_stdout' in result_dict): 486 self._log_module_failure(result, result_dict)
498 self._log_message(
499 result, status='MODULE FAILURE',
500 msg="Item: {item}\n{module_stdout}".format(**result_dict))
501 elif result._task.action not in ('command', 'shell', 487 elif result._task.action not in ('command', 'shell',
502 'win_command', 'win_shell'): 488 'win_command', 'win_shell'):
503 self._log_message( 489 self._log_message(