Don't do live streaming in loops

Currently we do live streaming of command and shell tasks in
loops. However this is severely broken as we only get the output of
the first task that ran. This is hard to solve as a per task streaming
in loops is not possible because of missing start events. Further
streaming several tasks at once is difficult too because we don't know
how many tasks we need to stream upfront.

So the intermediate solution until the whole log streaming is reworked
is to just not live stream tasks in loops.

While we're at it also fix a broken log statement and remove duplicate
exit code prints of action tasks.

Change-Id: Ic1358d5b9f939549ffdd5d770fe4eafc047be6f1
This commit is contained in:
Tobias Henkel 2018-11-05 22:17:57 +01:00
parent 1deb5f1e39
commit 0ae7a157e2
No known key found for this signature in database
GPG Key ID: 03750DEC158E5FA2
4 changed files with 48 additions and 2 deletions

View File

@ -62,3 +62,23 @@
strategy: linear
roles:
- include-a-role
- hosts: compute1
tasks:
- name: Single command
command: "echo single"
# Test commands within loops
- name: Command with loop
shell: |
echo {{ item }}
with_items:
- item_in_loop1
- item_in_loop2
- name: Failing command with loop
shell: |
echo {{ item }}
exit 1
with_items:
- failed_in_loop1
- failed_in_loop2
ignore_errors: True

View File

@ -121,6 +121,18 @@ class TestZuulStream(AnsibleZuulTestCase):
'delegate compute1', text)
self.assertLogLine(r'controller \| This is a shell task with '
'delegate controller', text)
self.assertLogLine(r'compute1 \| item_in_loop1', text)
self.assertLogLine(r'compute1 \| ok: Item: item_in_loop1 '
r'Runtime: \d:\d\d:\d\d\.\d\d\d\d\d\d', text)
self.assertLogLine(r'compute1 \| item_in_loop2', text)
self.assertLogLine(r'compute1 \| ok: Item: item_in_loop2 '
r'Runtime: \d:\d\d:\d\d\.\d\d\d\d\d\d', text)
self.assertLogLine(r'compute1 \| failed_in_loop1', text)
self.assertLogLine(r'compute1 \| ok: Item: failed_in_loop1 '
r'Result: 1', text)
self.assertLogLine(r'compute1 \| failed_in_loop2', text)
self.assertLogLine(r'compute1 \| ok: Item: failed_in_loop2 '
r'Result: 1', text)
self.assertLogLine(
r'controller \| ok: Runtime: \d:\d\d:\d\d\.\d\d\d\d\d\d', text)
self.assertLogLine('PLAY RECAP', text)

View File

@ -227,6 +227,10 @@ class CallbackModule(default.CallbackModule):
if ip in ('localhost', '127.0.0.1'):
# Don't try to stream from localhost
continue
if task.loop:
# Don't try to stream from loops
continue
log_id = "%s-%s" % (
task._uuid, paths._sanitize_filename(inventory_hostname))
streamer = threading.Thread(
@ -459,6 +463,11 @@ class CallbackModule(default.CallbackModule):
indent=2, sort_keys=True),
status=status)
else:
stdout_lines = zuul_filter_result(result_dict)
for line in stdout_lines:
hostname = self._get_hostname(result)
self._log("%s | %s " % (hostname, line))
if isinstance(result_dict['item'], str):
self._log_message(
result,
@ -488,8 +497,14 @@ class CallbackModule(default.CallbackModule):
status='ERROR',
result_dict=result_dict)
else:
stdout_lines = zuul_filter_result(result_dict)
for line in stdout_lines:
hostname = self._get_hostname(result)
self._log("%s | %s " % (hostname, line))
# self._log("Result: %s" % (result_dict))
self._log_message(
result, "Item: {item} Result: {result}".format(**result_dict))
result, "Item: {item} Result: {rc}".format(**result_dict))
if self._deferred_result:
self._process_deferred(result)

View File

@ -465,7 +465,6 @@ def zuul_run_command(self, args, zuul_log_id, check_rc=False, close_fds=True, ex
if t.isAlive():
console.addLine("[Zuul] standard output/error still open "
"after child exited")
console.addLine("[Zuul] Task exit code: %s\n" % rc)
# ZUUL: stdout and stderr are in the console log file
# ZUUL: return the saved log lines so we can ship them back
stdout = b('').join(_log_lines)