diff options
Diffstat (limited to 'tests')
-rw-r--r-- | tests/fixtures/config/mqtt-driver/git/common-config/zuul.d/config.yaml | 4 | ||||
-rw-r--r-- | tests/fixtures/config/remote-zuul-stream/git/org_project/playbooks/command.yaml | 14 | ||||
-rw-r--r-- | tests/remote/test_remote_zuul_stream.py | 48 | ||||
-rw-r--r-- | tests/unit/test_connection.py | 14 | ||||
-rw-r--r-- | tests/unit/test_inventory.py | 6 | ||||
-rw-r--r-- | tests/unit/test_scheduler.py | 11 |
6 files changed, 91 insertions, 6 deletions
diff --git a/tests/fixtures/config/mqtt-driver/git/common-config/zuul.d/config.yaml b/tests/fixtures/config/mqtt-driver/git/common-config/zuul.d/config.yaml index c842e9424..1cee46f5c 100644 --- a/tests/fixtures/config/mqtt-driver/git/common-config/zuul.d/config.yaml +++ b/tests/fixtures/config/mqtt-driver/git/common-config/zuul.d/config.yaml @@ -7,11 +7,15 @@ start: mqtt: topic: "{tenant}/zuul_start/{pipeline}/{project}/{branch}" + # This doesn't make sense here -- there should be no return + # data yet, which is why we include it in this test. + include-returned-data: True success: gerrit: Verified: 1 mqtt: topic: "{tenant}/zuul_buildset/{pipeline}/{project}/{branch}" + include-returned-data: True failure: gerrit: Verified: -1 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 d737a1a9b..539db80b7 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 @@ -114,3 +114,17 @@ - name: Command Not Found command: command-not-found failed_when: false + +- hosts: compute1 + tasks: + + - name: Debug raw variable in msg + debug: + msg: '{{ ansible_version }}' + + - name: Debug raw variable in a loop + debug: + msg: '{{ ansible_version }}' + loop: + - 1 + - 2 diff --git a/tests/remote/test_remote_zuul_stream.py b/tests/remote/test_remote_zuul_stream.py index bb2b54a21..b84c4b0d8 100644 --- a/tests/remote/test_remote_zuul_stream.py +++ b/tests/remote/test_remote_zuul_stream.py @@ -12,6 +12,8 @@ # License for the specific language governing permissions and limitations # under the License. +import io +import logging import os import re import textwrap @@ -31,6 +33,12 @@ class FunctionalZuulStreamMixIn: self.executor_server.log_console_port = self.log_console_port self.wait_timeout = 180 self.fake_nodepool.remote_ansible = True + # This catches the Ansible output; rather than the callback + # output captured in the job log. For example if the callback + # fails, there will be an error output in this stream. + self.logger = logging.getLogger('zuul.AnsibleJob') + self.console_output = io.StringIO() + self.logger.addHandler(logging.StreamHandler(self.console_output)) ansible_remote = os.environ.get('ZUUL_REMOTE_IPV4') self.assertIsNotNone(ansible_remote) @@ -92,14 +100,20 @@ class FunctionalZuulStreamMixIn: 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) + def _assertLogLine(self, line, log, full_match=True): + pattern = (r'^\d\d\d\d-\d\d-\d\d \d\d:\d\d\:\d\d\.\d\d\d\d\d\d \| %s%s' + % (line, '$' if full_match else '')) 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 assertLogLineStartsWith(self, line, log): + self._assertLogLine(line, log, full_match=False) + + def assertLogLine(self, line, log): + self._assertLogLine(line, log, full_match=True) + def _getLogTime(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)' r' \| %s\n' @@ -120,7 +134,21 @@ class FunctionalZuulStreamMixIn: build = self.history[-1] self.assertEqual(build.result, 'SUCCESS') + console_output = self.console_output.getvalue() + # This should be generic enough to match any callback + # plugin failures, which look something like + # + # [WARNING]: Failure using method (v2_runner_on_ok) in \ + # callback plugin + # (<ansible.plugins.callback.zuul_stream.CallbackModule object at' + # 0x7f89f72a20b0>): 'dict' object has no attribute 'startswith'" + # Callback Exception: + # ... + # + self.assertNotIn('[WARNING]: Failure using method', console_output) + text = self._get_job_output(build) + self.assertLogLine( r'RUN START: \[untrusted : review.example.com/org/project/' r'playbooks/command.yaml@master\]', text) @@ -186,6 +214,20 @@ class FunctionalZuulStreamMixIn: self.assertLess((time2 - time1) / timedelta(milliseconds=1), 9000) + # This is from the debug: msg='{{ ansible_version }}' + # testing raw variable output. To make it version + # agnostic, match just the start of + # compute1 | ok: {'string': '2.9.27'... + + # NOTE(ianw) 2022-08-24 : I don't know why the callback + # for debug: msg= doesn't put the hostname first like + # other output. Undetermined if bug or feature. + self.assertLogLineStartsWith( + r"""\{'string': '\d.""", text) + # ... handling loops is a different path, and that does + self.assertLogLineStartsWith( + r"""compute1 \| ok: \{'string': '\d.""", text) + def test_module_exception(self): job = self._run_job('module_failure_exception') with self.jobLog(job): diff --git a/tests/unit/test_connection.py b/tests/unit/test_connection.py index b4c155240..bae4ff258 100644 --- a/tests/unit/test_connection.py +++ b/tests/unit/test_connection.py @@ -681,9 +681,13 @@ class TestMQTTConnection(ZuulTestCase): 'type': 'container_image' }} self.executor_server.returnData( - "test", A, {"zuul": {"log_url": "some-log-url", - 'artifacts': [artifact], - }} + "test", A, { + "zuul": { + "log_url": "some-log-url", + 'artifacts': [artifact], + }, + 'foo': 'bar', + } ) self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1)) self.waitUntilSettled() @@ -703,6 +707,9 @@ class TestMQTTConnection(ZuulTestCase): 'test') self.assertNotIn('result', mqtt_payload['buildset']['builds'][0]) self.assertNotIn('artifacts', mqtt_payload['buildset']['builds'][0]) + builds = mqtt_payload['buildset']['builds'] + test_job = [b for b in builds if b['job_name'] == 'test'][0] + self.assertNotIn('returned_data', test_job) self.assertEquals(success_event.get('topic'), 'tenant-one/zuul_buildset/check/org/project/master') @@ -720,6 +727,7 @@ class TestMQTTConnection(ZuulTestCase): self.assertEquals(test_job['dependencies'], []) self.assertEquals(test_job['artifacts'], [artifact]) self.assertEquals(test_job['log_url'], 'some-log-url/') + self.assertEquals(test_job['returned_data'], {'foo': 'bar'}) build_id = test_job["uuid"] self.assertEquals( test_job["web_url"], diff --git a/tests/unit/test_inventory.py b/tests/unit/test_inventory.py index 1e96372ed..83a62a0e7 100644 --- a/tests/unit/test_inventory.py +++ b/tests/unit/test_inventory.py @@ -104,6 +104,7 @@ class TestInventoryGithub(TestInventoryBase): z_vars = inventory['all']['vars']['zuul'] self.assertIn('executor', z_vars) self.assertIn('src_root', z_vars['executor']) + self.assertIn('ansible_version', z_vars) self.assertIn('job', z_vars) self.assertIn('event_id', z_vars) self.assertEqual(z_vars['job'], 'single-inventory') @@ -137,6 +138,7 @@ class TestInventoryPythonPath(TestInventoryBase): z_vars = inventory['all']['vars']['zuul'] self.assertIn('executor', z_vars) self.assertIn('src_root', z_vars['executor']) + self.assertIn('ansible_version', z_vars) self.assertIn('job', z_vars) self.assertEqual(z_vars['job'], 'single-inventory') self.assertEqual(z_vars['message'], 'QQ==') @@ -167,6 +169,7 @@ class TestInventoryShellType(TestInventoryBase): z_vars = inventory['all']['vars']['zuul'] self.assertIn('executor', z_vars) self.assertIn('src_root', z_vars['executor']) + self.assertIn('ansible_version', z_vars) self.assertIn('job', z_vars) self.assertEqual(z_vars['job'], 'single-inventory') self.assertEqual(z_vars['message'], 'QQ==') @@ -195,6 +198,7 @@ class TestInventoryAutoPython(TestInventoryBase): self.assertIn('executor', z_vars) self.assertIn('src_root', z_vars['executor']) self.assertIn('job', z_vars) + self.assertEqual(z_vars['ansible_version'], '2.8') self.assertEqual(z_vars['job'], 'ansible-version28-inventory') self.assertEqual(z_vars['message'], 'QQ==') @@ -219,6 +223,7 @@ class TestInventoryAutoPython(TestInventoryBase): self.assertIn('executor', z_vars) self.assertIn('src_root', z_vars['executor']) self.assertIn('job', z_vars) + self.assertEqual(z_vars['ansible_version'], '2.9') self.assertEqual(z_vars['job'], 'ansible-version29-inventory') self.assertEqual(z_vars['message'], 'QQ==') @@ -243,6 +248,7 @@ class TestInventoryAutoPython(TestInventoryBase): self.assertIn('executor', z_vars) self.assertIn('src_root', z_vars['executor']) self.assertIn('job', z_vars) + self.assertEqual(z_vars['ansible_version'], '5') self.assertEqual(z_vars['job'], 'ansible-version5-inventory') self.assertEqual(z_vars['message'], 'QQ==') diff --git a/tests/unit/test_scheduler.py b/tests/unit/test_scheduler.py index 978bc00a4..3445e9dc6 100644 --- a/tests/unit/test_scheduler.py +++ b/tests/unit/test_scheduler.py @@ -5372,6 +5372,17 @@ For CI problems and help debugging, contact ci@example.org""" 'database'].getBuildsets()) if buildsets: break + # Stop queuing timer triggered jobs so that the assertions + # below don't race against more jobs being queued. + self.commitConfigUpdate('org/common-config', 'layouts/no-timer.yaml') + self.scheds.execute(lambda app: app.sched.reconfigure(app.config)) + self.waitUntilSettled() + # If APScheduler is in mid-event when we remove the job, we + # can end up with one more event firing, so give it an extra + # second to settle. + time.sleep(3) + self.waitUntilSettled() + self.assertEqual(buildsets[0].result, 'CONFIG_ERROR') self.assertIn('Job project-test2 depends on project-test1 ' 'which was not run', buildsets[0].message) |