zuul-stream : don't write out logfile for tasks in loops

In zuul_stream.py:v2_playbook_on_task_start() it checks for
"task.loop" and exits if the task is part of a loop.

However the library/command.py override still writes out the console
log despite it never being read.  To avoid leaving this file around,
mark a sentinel uuid in the action plugin if the command is part of a
loop.  In that case, for simplicity we just write to /dev/null -- that
way no other assumptions in the library/command.py have to change; it
just doesn't leave a file on disk.

This is currently difficult to test as the infrastructure zuul_console
leaves /tmp/console-* files and we do not know what comes from that,
or testing.  After this and the related change
I823156dc2bcae91bd6d9770bd1520aa55ad875b4 are deployed to the
infrastructure executors, we can make a simple and complete test for
the future by just ensuring no /tmp/console-* files are left behind
afer testing.  I have tested this locally and do not see files from
loops, which I was before this change.

Change-Id: I4f4660c3c0b0f170561c14940cc159dc43eadc79
This commit is contained in:
Ian Wienand
2022-07-22 16:36:53 +10:00
parent 559602910f
commit f8677cddb9
4 changed files with 44 additions and 14 deletions

View File

@@ -168,7 +168,15 @@ _log_lines = []
class Console(object):
def __init__(self, log_uuid):
self.logfile_name = LOG_STREAM_FILE.format(log_uuid=log_uuid)
# The streamer currently will not ask us for output from
# loops. This flag uuid was set in the action plugin if this
# call was part of a loop. This avoids us leaving behind
# files that will never be read, but also means no other
# special-casing for any of this path.
if log_uuid == 'in-loop-ignore':
self.logfile_name = os.devnull
else:
self.logfile_name = LOG_STREAM_FILE.format(log_uuid=log_uuid)
def __enter__(self):
self.logfile = open(self.logfile_name, 'ab', buffering=0)

View File

@@ -168,7 +168,15 @@ _log_lines = []
class Console(object):
def __init__(self, log_uuid):
self.logfile_name = LOG_STREAM_FILE.format(log_uuid=log_uuid)
# The streamer currently will not ask us for output from
# loops. This flag uuid was set in the action plugin if this
# call was part of a loop. This avoids us leaving behind
# files that will never be read, but also means no other
# special-casing for any of this path.
if log_uuid == 'in-loop-ignore':
self.logfile_name = os.devnull
else:
self.logfile_name = LOG_STREAM_FILE.format(log_uuid=log_uuid)
def __enter__(self):
self.logfile = open(self.logfile_name, 'ab', buffering=0)

View File

@@ -25,15 +25,21 @@ class ActionModule(command.ActionModule):
if self._task.action in (
'command', 'shell',
'ansible.builtin.command', 'ansible.builtin.shell'):
# Get a unique key for ZUUL_LOG_ID_MAP. ZUUL_LOG_ID_MAP
# is read-only since we are forked. Use it to add a
# counter to the log id so that if we run the same task
# more than once, we get a unique log file. See comments
# in paths.py for details.
log_host = paths._sanitize_filename(
task_vars.get('inventory_hostname'))
key = "%s-%s" % (self._task._uuid, log_host)
count = paths.ZUUL_LOG_ID_MAP.get(key, 0)
self._task.args['zuul_log_id'] = "%s-%s-%s" % (
self._task._uuid, count, log_host)
# This is a bit lame, but we do not log loops in the
# zuul_stream.py callback. This allows us to not write
# out command.py output to files that will never be read.
if 'ansible_loop_var' in task_vars:
self._task.args['zuul_log_id'] = 'in-loop-ignore'
else:
# Get a unique key for ZUUL_LOG_ID_MAP. ZUUL_LOG_ID_MAP
# is read-only since we are forked. Use it to add a
# counter to the log id so that if we run the same task
# more than once, we get a unique log file. See comments
# in paths.py for details.
log_host = paths._sanitize_filename(
task_vars.get('inventory_hostname'))
key = "%s-%s" % (self._task._uuid, log_host)
count = paths.ZUUL_LOG_ID_MAP.get(key, 0)
self._task.args['zuul_log_id'] = "%s-%s-%s" % (
self._task._uuid, count, log_host)
return super(ActionModule, self).run(tmp, task_vars)

View File

@@ -263,7 +263,15 @@ _log_lines = []
class Console(object):
def __init__(self, log_uuid):
self.logfile_name = LOG_STREAM_FILE.format(log_uuid=log_uuid)
# The streamer currently will not ask us for output from
# loops. This flag uuid was set in the action plugin if this
# call was part of a loop. This avoids us leaving behind
# files that will never be read, but also means no other
# special-casing for any of this path.
if log_uuid == 'in-loop-ignore':
self.logfile_name = os.devnull
else:
self.logfile_name = LOG_STREAM_FILE.format(log_uuid=log_uuid)
def __enter__(self):
self.logfile = open(self.logfile_name, 'ab', buffering=0)