Files
zuul/tests/remote/test_remote_zuul_stream.py
T
Tobias Henkel 0ae7a157e2 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
2018-11-05 22:21:38 +01:00

156 lines
6.8 KiB
Python

# Copyright 2018 Red Hat, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import os
import re
import textwrap
from tests.base import AnsibleZuulTestCase
class TestZuulStream(AnsibleZuulTestCase):
tenant_config_file = 'config/remote-zuul-stream/main.yaml'
def setUp(self):
super(TestZuulStream, self).setUp()
self.fake_nodepool.remote_ansible = True
ansible_remote = os.environ.get('ZUUL_REMOTE_IPV4')
self.assertIsNotNone(ansible_remote)
# on some systems this test may run longer than 30 seconds
self.wait_timeout = 60
def _run_job(self, job_name):
# Keep the jobdir around so we can inspect contents if an
# assert fails. It will be cleaned up anyway as it is contained
# in a tmp dir which gets cleaned up after the test.
self.executor_server.keep_jobdir = True
# Output extra ansible info so we might see errors.
self.executor_server.verbose = True
conf = textwrap.dedent(
"""
- job:
name: {job_name}
run: playbooks/{job_name}.yaml
roles:
- zuul: org/common-config
nodeset:
nodes:
- name: compute1
label: whatever
- name: controller
label: whatever
- project:
check:
jobs:
- {job_name}
""".format(job_name=job_name))
file_dict = {'zuul.yaml': conf}
A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
files=file_dict)
self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
self.waitUntilSettled()
job = self.getJobFromHistory(job_name)
return job
def _get_job_output(self, build):
path = os.path.join(self.test_root, build.uuid,
'work', 'logs', 'job-output.txt')
with open(path) as f:
return f.read()
def assertLogLine(self, line, log):
pattern = (r'^\d\d\d\d-\d\d-\d\d \d\d:\d\d\:\d\d\.\d\d\d\d\d\d \| %s$'
% line)
log_re = re.compile(pattern, re.MULTILINE)
m = log_re.search(log)
if m is None:
raise Exception("'%s' not found in log" % (line,))
def test_command(self):
job = self._run_job('command')
with self.jobLog(job):
build = self.history[-1]
self.assertEqual(build.result, 'SUCCESS')
text = self._get_job_output(build)
self.assertLogLine(
r'RUN START: \[untrusted : review.example.com/org/project/'
r'playbooks/command.yaml@master\]', text)
self.assertLogLine(r'PLAY \[all\]', text)
self.assertLogLine(r'TASK \[Show contents of first file\]', text)
self.assertLogLine(r'controller \| command test one', text)
self.assertLogLine(
r'controller \| ok: Runtime: \d:\d\d:\d\d\.\d\d\d\d\d\d', text)
self.assertLogLine(r'TASK \[Show contents of second file\]', text)
self.assertLogLine(r'compute1 \| command test two', text)
self.assertLogLine(r'controller \| command test two', text)
self.assertLogLine(r'compute1 \| This is a rescue task', text)
self.assertLogLine(r'controller \| This is a rescue task', text)
self.assertLogLine(r'compute1 \| This is an always task', text)
self.assertLogLine(r'controller \| This is an always task', text)
self.assertLogLine(r'compute1 \| This is a handler', text)
self.assertLogLine(r'controller \| This is a handler', text)
self.assertLogLine(r'controller \| First free task', text)
self.assertLogLine(r'controller \| Second free task', text)
self.assertLogLine(r'controller \| This is a shell task after an '
'included role', text)
self.assertLogLine(r'compute1 \| This is a shell task after an '
'included role', text)
self.assertLogLine(r'controller \| This is a command task after '
'an included role', text)
self.assertLogLine(r'compute1 \| This is a command task after an '
'included role', text)
self.assertLogLine(r'controller \| This is a shell task with '
'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)
self.assertLogLine(
r'controller \| ok: \d+ changed: \d+ unreachable: 0 failed: 1',
text)
self.assertLogLine(
r'RUN END RESULT_NORMAL: \[untrusted : review.example.com/'
r'org/project/playbooks/command.yaml@master]', text)
def test_module_failure(self):
job = self._run_job('module_failure')
with self.jobLog(job):
build = self.history[-1]
self.assertEqual(build.result, 'FAILURE')
text = self._get_job_output(build)
self.assertLogLine(r'TASK \[Module failure\]', text)
self.assertLogLine(
r'controller \| MODULE FAILURE: This module is broken', text)