blob: c04604d54d64a01566194f26c9425153fce7b72a [file] [log] [blame]
James E. Blair59fdbac2015-12-07 17:08:06 -08001#!/usr/bin/env python
2
3# Copyright 2012 Hewlett-Packard Development Company, L.P.
4#
5# Licensed under the Apache License, Version 2.0 (the "License"); you may
6# not use this file except in compliance with the License. You may obtain
7# a copy of the License at
8#
9# http://www.apache.org/licenses/LICENSE-2.0
10#
11# Unless required by applicable law or agreed to in writing, software
12# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14# License for the specific language governing permissions and limitations
15# under the License.
16
Monty Taylor0e2489a2017-10-10 11:57:29 -050017import io
James E. Blaira00910c2017-08-23 09:15:04 -070018import json
Monty Taylor0e2489a2017-10-10 11:57:29 -050019import logging
James E. Blaira92cbc82017-01-23 14:56:49 -080020import os
James E. Blair14abdf42015-12-09 16:11:53 -080021import textwrap
James E. Blair3a098dd2017-10-04 14:37:29 -070022import gc
James E. Blairbacbb882017-10-17 09:48:23 -070023import time
James E. Blair3a098dd2017-10-04 14:37:29 -070024from unittest import skip
James E. Blair59fdbac2015-12-07 17:08:06 -080025
James E. Blairb9c0d772017-03-03 14:34:49 -080026import testtools
27
28import zuul.configloader
James E. Blairbf1a4f22017-03-17 10:59:37 -070029from zuul.lib import encryption
Ricardo Carrillo Cruz22994f92016-12-02 11:41:58 +000030from tests.base import AnsibleZuulTestCase, ZuulTestCase, FIXTURE_DIR
James E. Blair59fdbac2015-12-07 17:08:06 -080031
James E. Blair59fdbac2015-12-07 17:08:06 -080032
James E. Blair3f876d52016-07-22 13:07:14 -070033class TestMultipleTenants(AnsibleZuulTestCase):
James E. Blair59fdbac2015-12-07 17:08:06 -080034 # A temporary class to hold new tests while others are disabled
35
James E. Blair2a629ec2015-12-22 15:32:02 -080036 tenant_config_file = 'config/multi-tenant/main.yaml'
James E. Blair59fdbac2015-12-07 17:08:06 -080037
James E. Blair83005782015-12-11 14:46:03 -080038 def test_multiple_tenants(self):
James E. Blair96f26942015-12-09 10:15:59 -080039 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A')
Tobias Henkelbf24fd12017-07-27 06:13:07 +020040 A.addApproval('Code-Review', 2)
41 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
James E. Blair59fdbac2015-12-07 17:08:06 -080042 self.waitUntilSettled()
James E. Blair96f26942015-12-09 10:15:59 -080043 self.assertEqual(self.getJobFromHistory('project1-test1').result,
James E. Blair59fdbac2015-12-07 17:08:06 -080044 'SUCCESS')
James E. Blair96c6bf82016-01-15 16:20:40 -080045 self.assertEqual(self.getJobFromHistory('python27').result,
46 'SUCCESS')
James E. Blair59fdbac2015-12-07 17:08:06 -080047 self.assertEqual(A.data['status'], 'MERGED')
James E. Blair96f26942015-12-09 10:15:59 -080048 self.assertEqual(A.reported, 2,
49 "A should report start and success")
50 self.assertIn('tenant-one-gate', A.messages[1],
51 "A should transit tenant-one gate")
52 self.assertNotIn('tenant-two-gate', A.messages[1],
53 "A should *not* transit tenant-two gate")
James E. Blair59fdbac2015-12-07 17:08:06 -080054
James E. Blair96f26942015-12-09 10:15:59 -080055 B = self.fake_gerrit.addFakeChange('org/project2', 'master', 'B')
Tobias Henkelbf24fd12017-07-27 06:13:07 +020056 B.addApproval('Code-Review', 2)
57 self.fake_gerrit.addEvent(B.addApproval('Approved', 1))
James E. Blair96f26942015-12-09 10:15:59 -080058 self.waitUntilSettled()
James E. Blair96c6bf82016-01-15 16:20:40 -080059 self.assertEqual(self.getJobFromHistory('python27',
60 'org/project2').result,
61 'SUCCESS')
James E. Blair96f26942015-12-09 10:15:59 -080062 self.assertEqual(self.getJobFromHistory('project2-test1').result,
63 'SUCCESS')
64 self.assertEqual(B.data['status'], 'MERGED')
65 self.assertEqual(B.reported, 2,
66 "B should report start and success")
67 self.assertIn('tenant-two-gate', B.messages[1],
68 "B should transit tenant-two gate")
69 self.assertNotIn('tenant-one-gate', B.messages[1],
70 "B should *not* transit tenant-one gate")
James E. Blair59fdbac2015-12-07 17:08:06 -080071
James E. Blair96f26942015-12-09 10:15:59 -080072 self.assertEqual(A.reported, 2, "Activity in tenant two should"
73 "not affect tenant one")
James E. Blair14abdf42015-12-09 16:11:53 -080074
James E. Blair83005782015-12-11 14:46:03 -080075
Tobias Henkel83167622017-06-30 19:45:03 +020076class TestFinal(ZuulTestCase):
77
78 tenant_config_file = 'config/final/main.yaml'
79
80 def test_final_variant_ok(self):
81 # test clean usage of final parent job
82 in_repo_conf = textwrap.dedent(
83 """
84 - project:
85 name: org/project
86 check:
87 jobs:
88 - job-final
89 """)
90
91 file_dict = {'.zuul.yaml': in_repo_conf}
92 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
93 files=file_dict)
94 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
95 self.waitUntilSettled()
96
97 self.assertEqual(A.reported, 1)
98 self.assertEqual(A.patchsets[-1]['approvals'][0]['value'], '1')
99
100 def test_final_variant_error(self):
101 # test misuse of final parent job
102 in_repo_conf = textwrap.dedent(
103 """
104 - project:
105 name: org/project
106 check:
107 jobs:
108 - job-final:
109 vars:
110 dont_override_this: bar
111 """)
112 file_dict = {'.zuul.yaml': in_repo_conf}
113 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
114 files=file_dict)
115 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
116 self.waitUntilSettled()
117
118 # The second patch tried to override some variables.
119 # Thus it should fail.
120 self.assertEqual(A.reported, 1)
121 self.assertEqual(A.patchsets[-1]['approvals'][0]['value'], '-1')
122 self.assertIn('Unable to modify final job', A.messages[0])
123
124 def test_final_inheritance(self):
125 # test misuse of final parent job
126 in_repo_conf = textwrap.dedent(
127 """
128 - job:
129 name: project-test
130 parent: job-final
James E. Blair2f589fe2017-10-26 12:57:41 -0700131 run: playbooks/project-test.yaml
Tobias Henkel83167622017-06-30 19:45:03 +0200132
133 - project:
134 name: org/project
135 check:
136 jobs:
137 - project-test
138 """)
139
140 in_repo_playbook = textwrap.dedent(
141 """
142 - hosts: all
143 tasks: []
144 """)
145
146 file_dict = {'.zuul.yaml': in_repo_conf,
147 'playbooks/project-test.yaml': in_repo_playbook}
148 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
149 files=file_dict)
150 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
151 self.waitUntilSettled()
152
153 # The second patch tried to override some variables.
154 # Thus it should fail.
155 self.assertEqual(A.reported, 1)
156 self.assertEqual(A.patchsets[-1]['approvals'][0]['value'], '-1')
James E. Blairc32a8352017-10-11 16:27:50 -0700157 self.assertIn('Unable to modify final job', A.messages[0])
Tobias Henkel83167622017-06-30 19:45:03 +0200158
159
James E. Blair09998792017-10-15 18:02:18 -0700160class TestBranchVariants(ZuulTestCase):
161 tenant_config_file = 'config/branch-variants/main.yaml'
162
163 def test_branch_variants(self):
164 # Test branch variants of jobs with inheritance
165 self.executor_server.hold_jobs_in_build = True
166 # This creates a new branch with a copy of the config in master
167 self.create_branch('puppet-integration', 'stable')
168 self.fake_gerrit.addEvent(
169 self.fake_gerrit.getFakeBranchCreatedEvent(
170 'puppet-integration', 'stable'))
171 self.waitUntilSettled()
172
173 A = self.fake_gerrit.addFakeChange('puppet-integration', 'stable', 'A')
174 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
175 self.waitUntilSettled()
176
177 self.assertEqual(len(self.builds[0].parameters['pre_playbooks']), 3)
178 self.executor_server.hold_jobs_in_build = False
179 self.executor_server.release()
180 self.waitUntilSettled()
181
James E. Blairc9e77592017-10-24 09:25:23 -0700182 def test_branch_variants_reconfigure(self):
183 # Test branch variants of jobs with inheritance
184 self.executor_server.hold_jobs_in_build = True
185 # This creates a new branch with a copy of the config in master
186 self.create_branch('puppet-integration', 'stable')
187 self.fake_gerrit.addEvent(
188 self.fake_gerrit.getFakeBranchCreatedEvent(
189 'puppet-integration', 'stable'))
190 self.waitUntilSettled()
191
192 with open(os.path.join(FIXTURE_DIR,
193 'config/branch-variants/git/',
194 'puppet-integration/.zuul.yaml')) as f:
195 config = f.read()
196
197 # Push a change that triggers a dynamic reconfiguration
198 file_dict = {'.zuul.yaml': config}
199 A = self.fake_gerrit.addFakeChange('puppet-integration', 'master', 'A',
200 files=file_dict)
201 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
202 self.waitUntilSettled()
203
204 ipath = self.builds[0].parameters['zuul']['_inheritance_path']
205 for i in ipath:
206 self.log.debug("inheritance path %s", i)
207 self.assertEqual(len(ipath), 5)
208 self.executor_server.hold_jobs_in_build = False
209 self.executor_server.release()
210 self.waitUntilSettled()
211
James E. Blairc32a8352017-10-11 16:27:50 -0700212 def test_branch_variants_divergent(self):
213 # Test branches can diverge and become independent
214 self.executor_server.hold_jobs_in_build = True
215 # This creates a new branch with a copy of the config in master
216 self.create_branch('puppet-integration', 'stable')
217 self.fake_gerrit.addEvent(
218 self.fake_gerrit.getFakeBranchCreatedEvent(
219 'puppet-integration', 'stable'))
220 self.waitUntilSettled()
221
222 with open(os.path.join(FIXTURE_DIR,
223 'config/branch-variants/git/',
224 'puppet-integration/stable.zuul.yaml')) as f:
225 config = f.read()
226
227 file_dict = {'.zuul.yaml': config}
228 C = self.fake_gerrit.addFakeChange('puppet-integration', 'stable', 'C',
229 files=file_dict)
230 C.addApproval('Code-Review', 2)
231 self.fake_gerrit.addEvent(C.addApproval('Approved', 1))
232 self.waitUntilSettled()
233 self.fake_gerrit.addEvent(C.getChangeMergedEvent())
234 self.waitUntilSettled()
235
236 A = self.fake_gerrit.addFakeChange('puppet-integration', 'master', 'A')
237 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
238 self.waitUntilSettled()
239 B = self.fake_gerrit.addFakeChange('puppet-integration', 'stable', 'B')
240 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
241 self.waitUntilSettled()
242
243 self.assertEqual(self.builds[0].parameters['zuul']['jobtags'],
244 ['master'])
245
246 self.assertEqual(self.builds[1].parameters['zuul']['jobtags'],
247 ['stable'])
248
249 self.executor_server.hold_jobs_in_build = False
250 self.executor_server.release()
251 self.waitUntilSettled()
252
James E. Blair09998792017-10-15 18:02:18 -0700253
James E. Blair2a664502017-10-27 11:39:33 -0700254class TestCentralJobs(ZuulTestCase):
255 tenant_config_file = 'config/central-jobs/main.yaml'
256
257 def setUp(self):
258 super(TestCentralJobs, self).setUp()
259 self.create_branch('org/project', 'stable')
260 self.fake_gerrit.addEvent(
261 self.fake_gerrit.getFakeBranchCreatedEvent(
262 'org/project', 'stable'))
263 self.waitUntilSettled()
264
265 def _updateConfig(self, config, branch):
266 file_dict = {'.zuul.yaml': config}
267 C = self.fake_gerrit.addFakeChange('org/project', branch, 'C',
268 files=file_dict)
269 C.addApproval('Code-Review', 2)
270 self.fake_gerrit.addEvent(C.addApproval('Approved', 1))
271 self.waitUntilSettled()
272 self.fake_gerrit.addEvent(C.getChangeMergedEvent())
273 self.waitUntilSettled()
274
275 def _test_central_job_on_branch(self, branch, other_branch):
276 # Test that a job defined on a branchless repo only runs on
277 # the branch applied
278 config = textwrap.dedent(
279 """
280 - project:
281 name: org/project
282 check:
283 jobs:
284 - central-job
285 """)
286 self._updateConfig(config, branch)
287
288 A = self.fake_gerrit.addFakeChange('org/project', branch, 'A')
289 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
290 self.waitUntilSettled()
291
292 self.assertHistory([
293 dict(name='central-job', result='SUCCESS', changes='2,1')])
294
295 # No jobs should run for this change.
296 B = self.fake_gerrit.addFakeChange('org/project', other_branch, 'B')
297 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
298 self.waitUntilSettled()
299
300 self.assertHistory([
301 dict(name='central-job', result='SUCCESS', changes='2,1')])
302
303 def test_central_job_on_stable(self):
304 self._test_central_job_on_branch('master', 'stable')
305
306 def test_central_job_on_master(self):
307 self._test_central_job_on_branch('stable', 'master')
308
309 def _test_central_template_on_branch(self, branch, other_branch):
310 # Test that a project-template defined on a branchless repo
311 # only runs on the branch applied
312 config = textwrap.dedent(
313 """
314 - project:
315 name: org/project
316 templates: ['central-jobs']
317 """)
318 self._updateConfig(config, branch)
319
320 A = self.fake_gerrit.addFakeChange('org/project', branch, 'A')
321 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
322 self.waitUntilSettled()
323
324 self.assertHistory([
325 dict(name='central-job', result='SUCCESS', changes='2,1')])
326
327 # No jobs should run for this change.
328 B = self.fake_gerrit.addFakeChange('org/project', other_branch, 'B')
329 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
330 self.waitUntilSettled()
331
332 self.assertHistory([
333 dict(name='central-job', result='SUCCESS', changes='2,1')])
334
335 def test_central_template_on_stable(self):
336 self._test_central_template_on_branch('master', 'stable')
337
338 def test_central_template_on_master(self):
339 self._test_central_template_on_branch('stable', 'master')
340
341
James E. Blairff555742017-02-19 11:34:27 -0800342class TestInRepoConfig(ZuulTestCase):
James E. Blair83005782015-12-11 14:46:03 -0800343 # A temporary class to hold new tests while others are disabled
344
Tobias Henkelabf973e2017-07-28 10:07:34 +0200345 config_file = 'zuul-connections-gerrit-and-github.conf'
James E. Blair2a629ec2015-12-22 15:32:02 -0800346 tenant_config_file = 'config/in-repo/main.yaml'
James E. Blair83005782015-12-11 14:46:03 -0800347
James E. Blair83005782015-12-11 14:46:03 -0800348 def test_in_repo_config(self):
James E. Blair14abdf42015-12-09 16:11:53 -0800349 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
Tobias Henkelbf24fd12017-07-27 06:13:07 +0200350 A.addApproval('Code-Review', 2)
351 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
James E. Blair14abdf42015-12-09 16:11:53 -0800352 self.waitUntilSettled()
353 self.assertEqual(self.getJobFromHistory('project-test1').result,
354 'SUCCESS')
355 self.assertEqual(A.data['status'], 'MERGED')
356 self.assertEqual(A.reported, 2,
357 "A should report start and success")
358 self.assertIn('tenant-one-gate', A.messages[1],
359 "A should transit tenant-one gate")
James E. Blairb97ed802015-12-21 15:55:35 -0800360
James E. Blair3a098dd2017-10-04 14:37:29 -0700361 @skip("This test is useful, but not reliable")
362 def test_full_and_dynamic_reconfig(self):
363 self.executor_server.hold_jobs_in_build = True
364 in_repo_conf = textwrap.dedent(
365 """
366 - job:
367 name: project-test1
368
369 - project:
370 name: org/project
371 tenant-one-gate:
372 jobs:
373 - project-test1
374 """)
375
376 file_dict = {'.zuul.yaml': in_repo_conf}
377 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
378 files=file_dict)
379 A.addApproval('Code-Review', 2)
380 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
381 self.waitUntilSettled()
382 self.sched.reconfigure(self.config)
383 self.waitUntilSettled()
384
385 gc.collect()
386 pipelines = [obj for obj in gc.get_objects()
387 if isinstance(obj, zuul.model.Pipeline)]
388 self.assertEqual(len(pipelines), 4)
389
390 self.executor_server.hold_jobs_in_build = False
391 self.executor_server.release()
392 self.waitUntilSettled()
393
James E. Blair8b1dc3f2016-07-05 16:49:00 -0700394 def test_dynamic_config(self):
395 in_repo_conf = textwrap.dedent(
396 """
397 - job:
Tobias Henkelf02cf512017-07-21 22:55:34 +0200398 name: project-test1
399
400 - job:
James E. Blair8b1dc3f2016-07-05 16:49:00 -0700401 name: project-test2
James E. Blair2f589fe2017-10-26 12:57:41 -0700402 run: playbooks/project-test2.yaml
James E. Blair8b1dc3f2016-07-05 16:49:00 -0700403
404 - project:
405 name: org/project
406 tenant-one-gate:
407 jobs:
408 - project-test2
409 """)
410
James E. Blairc73c73a2017-01-20 15:15:15 -0800411 in_repo_playbook = textwrap.dedent(
412 """
413 - hosts: all
414 tasks: []
415 """)
416
417 file_dict = {'.zuul.yaml': in_repo_conf,
418 'playbooks/project-test2.yaml': in_repo_playbook}
James E. Blair8b1dc3f2016-07-05 16:49:00 -0700419 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
James E. Blairc73c73a2017-01-20 15:15:15 -0800420 files=file_dict)
Tobias Henkelbf24fd12017-07-27 06:13:07 +0200421 A.addApproval('Code-Review', 2)
422 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
James E. Blair8b1dc3f2016-07-05 16:49:00 -0700423 self.waitUntilSettled()
James E. Blair8b1dc3f2016-07-05 16:49:00 -0700424 self.assertEqual(A.data['status'], 'MERGED')
425 self.assertEqual(A.reported, 2,
426 "A should report start and success")
427 self.assertIn('tenant-one-gate', A.messages[1],
428 "A should transit tenant-one gate")
James E. Blair646322f2017-01-27 15:50:34 -0800429 self.assertHistory([
430 dict(name='project-test2', result='SUCCESS', changes='1,1')])
431
James E. Blairc2a5ed72017-02-20 14:12:01 -0500432 self.fake_gerrit.addEvent(A.getChangeMergedEvent())
James E. Blair7bbd7a32017-03-06 11:36:13 -0800433 self.waitUntilSettled()
James E. Blairc2a5ed72017-02-20 14:12:01 -0500434
James E. Blair646322f2017-01-27 15:50:34 -0800435 # Now that the config change is landed, it should be live for
436 # subsequent changes.
437 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
Tobias Henkelbf24fd12017-07-27 06:13:07 +0200438 B.addApproval('Code-Review', 2)
439 self.fake_gerrit.addEvent(B.addApproval('Approved', 1))
James E. Blair646322f2017-01-27 15:50:34 -0800440 self.waitUntilSettled()
441 self.assertEqual(self.getJobFromHistory('project-test2').result,
442 'SUCCESS')
443 self.assertHistory([
444 dict(name='project-test2', result='SUCCESS', changes='1,1'),
445 dict(name='project-test2', result='SUCCESS', changes='2,1')])
James E. Blairc73c73a2017-01-20 15:15:15 -0800446
James E. Blair6bc10482017-10-20 11:28:53 -0700447 def test_dynamic_template(self):
James E. Blair2a664502017-10-27 11:39:33 -0700448 # Tests that a project can't update a template in another
449 # project.
James E. Blair6bc10482017-10-20 11:28:53 -0700450 in_repo_conf = textwrap.dedent(
451 """
452 - job:
453 name: project-test1
454
455 - project-template:
456 name: common-config-template
457 check:
458 jobs:
459 - project-test1
460
461 - project:
462 name: org/project
463 templates: [common-config-template]
464 """)
465
466 file_dict = {'.zuul.yaml': in_repo_conf}
467 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
468 files=file_dict)
469 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
470 self.waitUntilSettled()
James E. Blair2a664502017-10-27 11:39:33 -0700471
472 self.assertEqual(A.patchsets[0]['approvals'][0]['value'], "-1")
473 self.assertIn('Project template common-config-template '
474 'is already defined',
475 A.messages[0],
476 "A should have failed the check pipeline")
James E. Blair6bc10482017-10-20 11:28:53 -0700477
Tobias Henkelf02cf512017-07-21 22:55:34 +0200478 def test_dynamic_config_non_existing_job(self):
479 """Test that requesting a non existent job fails"""
480 in_repo_conf = textwrap.dedent(
481 """
482 - job:
483 name: project-test1
484
485 - project:
486 name: org/project
487 check:
488 jobs:
489 - non-existent-job
490 """)
491
492 in_repo_playbook = textwrap.dedent(
493 """
494 - hosts: all
495 tasks: []
496 """)
497
498 file_dict = {'.zuul.yaml': in_repo_conf,
499 'playbooks/project-test2.yaml': in_repo_playbook}
500 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
501 files=file_dict)
502 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
503 self.waitUntilSettled()
504 self.assertEqual(A.reported, 1,
505 "A should report failure")
506 self.assertEqual(A.patchsets[0]['approvals'][0]['value'], "-1")
507 self.assertIn('Job non-existent-job not defined', A.messages[0],
508 "A should have failed the check pipeline")
509 self.assertHistory([])
510
511 def test_dynamic_config_non_existing_job_in_template(self):
512 """Test that requesting a non existent job fails"""
513 in_repo_conf = textwrap.dedent(
514 """
515 - job:
516 name: project-test1
517
518 - project-template:
519 name: test-template
520 check:
521 jobs:
522 - non-existent-job
523
524 - project:
525 name: org/project
526 templates:
527 - test-template
528 """)
529
530 in_repo_playbook = textwrap.dedent(
531 """
532 - hosts: all
533 tasks: []
534 """)
535
536 file_dict = {'.zuul.yaml': in_repo_conf,
537 'playbooks/project-test2.yaml': in_repo_playbook}
538 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
539 files=file_dict)
540 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
541 self.waitUntilSettled()
542 self.assertEqual(A.reported, 1,
543 "A should report failure")
544 self.assertEqual(A.patchsets[0]['approvals'][0]['value'], "-1")
545 self.assertIn('Job non-existent-job not defined', A.messages[0],
546 "A should have failed the check pipeline")
547 self.assertHistory([])
548
Tobias Henkel0f714002017-06-30 23:30:52 +0200549 def test_dynamic_config_new_patchset(self):
550 self.executor_server.hold_jobs_in_build = True
551
552 tenant = self.sched.abide.tenants.get('tenant-one')
553 check_pipeline = tenant.layout.pipelines['check']
554
555 in_repo_conf = textwrap.dedent(
556 """
557 - job:
Tobias Henkelf02cf512017-07-21 22:55:34 +0200558 name: project-test1
James E. Blair2f589fe2017-10-26 12:57:41 -0700559 run: playbooks/project-test1.yaml
Tobias Henkelf02cf512017-07-21 22:55:34 +0200560
561 - job:
Tobias Henkel0f714002017-06-30 23:30:52 +0200562 name: project-test2
James E. Blair2f589fe2017-10-26 12:57:41 -0700563 run: playbooks/project-test2.yaml
Tobias Henkel0f714002017-06-30 23:30:52 +0200564
565 - project:
566 name: org/project
567 check:
568 jobs:
569 - project-test2
570 """)
571
572 in_repo_playbook = textwrap.dedent(
573 """
574 - hosts: all
575 tasks: []
576 """)
577
578 file_dict = {'.zuul.yaml': in_repo_conf,
579 'playbooks/project-test2.yaml': in_repo_playbook}
580 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
581 files=file_dict)
582 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
583 self.waitUntilSettled()
584
585 items = check_pipeline.getAllItems()
586 self.assertEqual(items[0].change.number, '1')
587 self.assertEqual(items[0].change.patchset, '1')
588 self.assertTrue(items[0].live)
589
590 in_repo_conf = textwrap.dedent(
591 """
592 - job:
Tobias Henkel0ce7ec62017-07-21 22:50:17 +0200593 name: project-test1
James E. Blair2f589fe2017-10-26 12:57:41 -0700594 run: playbooks/project-test1.yaml
Tobias Henkel0ce7ec62017-07-21 22:50:17 +0200595
596 - job:
Tobias Henkel0f714002017-06-30 23:30:52 +0200597 name: project-test2
James E. Blair2f589fe2017-10-26 12:57:41 -0700598 run: playbooks/project-test2.yaml
Tobias Henkel0f714002017-06-30 23:30:52 +0200599
600 - project:
601 name: org/project
602 check:
603 jobs:
604 - project-test1
605 - project-test2
606 """)
607 file_dict = {'.zuul.yaml': in_repo_conf,
608 'playbooks/project-test2.yaml': in_repo_playbook}
609
610 A.addPatchset(files=file_dict)
611 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(2))
612
613 self.waitUntilSettled()
614
615 items = check_pipeline.getAllItems()
616 self.assertEqual(items[0].change.number, '1')
617 self.assertEqual(items[0].change.patchset, '2')
618 self.assertTrue(items[0].live)
619
620 self.executor_server.hold_jobs_in_build = False
Tobias Henkel0ce7ec62017-07-21 22:50:17 +0200621 self.executor_server.release('project-test1')
622 self.waitUntilSettled()
Tobias Henkel0f714002017-06-30 23:30:52 +0200623 self.executor_server.release()
624 self.waitUntilSettled()
625
Tobias Henkel0ce7ec62017-07-21 22:50:17 +0200626 self.assertHistory([
627 dict(name='project-test2', result='ABORTED', changes='1,1'),
628 dict(name='project-test1', result='SUCCESS', changes='1,2'),
629 dict(name='project-test2', result='SUCCESS', changes='1,2')])
630
James E. Blairff555742017-02-19 11:34:27 -0800631 def test_in_repo_branch(self):
632 in_repo_conf = textwrap.dedent(
633 """
634 - job:
Tobias Henkelf02cf512017-07-21 22:55:34 +0200635 name: project-test1
636
637 - job:
James E. Blairff555742017-02-19 11:34:27 -0800638 name: project-test2
James E. Blair2f589fe2017-10-26 12:57:41 -0700639 run: playbooks/project-test2.yaml
James E. Blairff555742017-02-19 11:34:27 -0800640
641 - project:
642 name: org/project
643 tenant-one-gate:
644 jobs:
645 - project-test2
646 """)
647
648 in_repo_playbook = textwrap.dedent(
649 """
650 - hosts: all
651 tasks: []
652 """)
653
654 file_dict = {'.zuul.yaml': in_repo_conf,
655 'playbooks/project-test2.yaml': in_repo_playbook}
656 self.create_branch('org/project', 'stable')
James E. Blair72facdc2017-08-17 10:29:12 -0700657 self.fake_gerrit.addEvent(
658 self.fake_gerrit.getFakeBranchCreatedEvent(
659 'org/project', 'stable'))
James E. Blair6069f2b2017-09-26 16:34:11 -0700660 self.waitUntilSettled()
James E. Blairff555742017-02-19 11:34:27 -0800661 A = self.fake_gerrit.addFakeChange('org/project', 'stable', 'A',
662 files=file_dict)
Tobias Henkelbf24fd12017-07-27 06:13:07 +0200663 A.addApproval('Code-Review', 2)
664 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
James E. Blairff555742017-02-19 11:34:27 -0800665 self.waitUntilSettled()
666 self.assertEqual(A.data['status'], 'MERGED')
667 self.assertEqual(A.reported, 2,
668 "A should report start and success")
669 self.assertIn('tenant-one-gate', A.messages[1],
670 "A should transit tenant-one gate")
671 self.assertHistory([
672 dict(name='project-test2', result='SUCCESS', changes='1,1')])
673 self.fake_gerrit.addEvent(A.getChangeMergedEvent())
James E. Blair7bbd7a32017-03-06 11:36:13 -0800674 self.waitUntilSettled()
James E. Blairff555742017-02-19 11:34:27 -0800675
676 # The config change should not affect master.
677 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
Tobias Henkelbf24fd12017-07-27 06:13:07 +0200678 B.addApproval('Code-Review', 2)
679 self.fake_gerrit.addEvent(B.addApproval('Approved', 1))
James E. Blairff555742017-02-19 11:34:27 -0800680 self.waitUntilSettled()
681 self.assertHistory([
682 dict(name='project-test2', result='SUCCESS', changes='1,1'),
683 dict(name='project-test1', result='SUCCESS', changes='2,1')])
684
685 # The config change should be live for further changes on
686 # stable.
687 C = self.fake_gerrit.addFakeChange('org/project', 'stable', 'C')
Tobias Henkelbf24fd12017-07-27 06:13:07 +0200688 C.addApproval('Code-Review', 2)
689 self.fake_gerrit.addEvent(C.addApproval('Approved', 1))
James E. Blairff555742017-02-19 11:34:27 -0800690 self.waitUntilSettled()
691 self.assertHistory([
692 dict(name='project-test2', result='SUCCESS', changes='1,1'),
693 dict(name='project-test1', result='SUCCESS', changes='2,1'),
694 dict(name='project-test2', result='SUCCESS', changes='3,1')])
695
James E. Blaira5a12492017-05-03 11:40:48 -0700696 def test_crd_dynamic_config_branch(self):
697 # Test that we can create a job in one repo and be able to use
698 # it from a different branch on a different repo.
699
700 self.create_branch('org/project1', 'stable')
James E. Blair72facdc2017-08-17 10:29:12 -0700701 self.fake_gerrit.addEvent(
702 self.fake_gerrit.getFakeBranchCreatedEvent(
703 'org/project1', 'stable'))
James E. Blaira5a12492017-05-03 11:40:48 -0700704
705 in_repo_conf = textwrap.dedent(
706 """
707 - job:
Tobias Henkelf02cf512017-07-21 22:55:34 +0200708 name: project-test1
709
710 - job:
James E. Blaira5a12492017-05-03 11:40:48 -0700711 name: project-test2
James E. Blair2f589fe2017-10-26 12:57:41 -0700712 run: playbooks/project-test2.yaml
James E. Blaira5a12492017-05-03 11:40:48 -0700713
714 - project:
715 name: org/project
716 check:
717 jobs:
718 - project-test2
719 """)
720
721 in_repo_playbook = textwrap.dedent(
722 """
723 - hosts: all
724 tasks: []
725 """)
726
727 file_dict = {'.zuul.yaml': in_repo_conf,
728 'playbooks/project-test2.yaml': in_repo_playbook}
729 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
730 files=file_dict)
731
732 second_repo_conf = textwrap.dedent(
733 """
734 - project:
735 name: org/project1
736 check:
737 jobs:
738 - project-test2
739 """)
740
741 second_file_dict = {'.zuul.yaml': second_repo_conf}
742 B = self.fake_gerrit.addFakeChange('org/project1', 'stable', 'B',
743 files=second_file_dict)
744 B.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
745 B.subject, A.data['id'])
746
747 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
748 self.waitUntilSettled()
749 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
750 self.waitUntilSettled()
751
752 self.assertEqual(A.reported, 1, "A should report")
753 self.assertHistory([
754 dict(name='project-test2', result='SUCCESS', changes='1,1'),
755 dict(name='project-test2', result='SUCCESS', changes='1,1 2,1'),
756 ])
757
James E. Blair97043882017-09-06 15:51:17 -0700758 def test_yaml_list_error(self):
759 in_repo_conf = textwrap.dedent(
760 """
761 job: foo
762 """)
763
764 file_dict = {'.zuul.yaml': in_repo_conf}
765 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
766 files=file_dict)
767 A.addApproval('Code-Review', 2)
768 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
769 self.waitUntilSettled()
770
771 self.assertEqual(A.data['status'], 'NEW')
772 self.assertEqual(A.reported, 1,
773 "A should report failure")
774 self.assertIn('not a list', A.messages[0],
775 "A should have a syntax error reported")
776
777 def test_yaml_dict_error(self):
778 in_repo_conf = textwrap.dedent(
779 """
780 - job
781 """)
782
783 file_dict = {'.zuul.yaml': in_repo_conf}
784 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
785 files=file_dict)
786 A.addApproval('Code-Review', 2)
787 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
788 self.waitUntilSettled()
789
790 self.assertEqual(A.data['status'], 'NEW')
791 self.assertEqual(A.reported, 1,
792 "A should report failure")
793 self.assertIn('not a dictionary', A.messages[0],
794 "A should have a syntax error reported")
795
796 def test_yaml_key_error(self):
797 in_repo_conf = textwrap.dedent(
798 """
799 - job:
800 name: project-test2
801 """)
802
803 file_dict = {'.zuul.yaml': in_repo_conf}
804 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
805 files=file_dict)
806 A.addApproval('Code-Review', 2)
807 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
808 self.waitUntilSettled()
809
810 self.assertEqual(A.data['status'], 'NEW')
811 self.assertEqual(A.reported, 1,
812 "A should report failure")
813 self.assertIn('has more than one key', A.messages[0],
814 "A should have a syntax error reported")
815
816 def test_yaml_unknown_error(self):
817 in_repo_conf = textwrap.dedent(
818 """
819 - foobar:
820 foo: bar
821 """)
822
823 file_dict = {'.zuul.yaml': in_repo_conf}
824 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
825 files=file_dict)
826 A.addApproval('Code-Review', 2)
827 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
828 self.waitUntilSettled()
829
830 self.assertEqual(A.data['status'], 'NEW')
831 self.assertEqual(A.reported, 1,
832 "A should report failure")
833 self.assertIn('not recognized', A.messages[0],
834 "A should have a syntax error reported")
835
James E. Blair149b69c2017-03-02 10:48:16 -0800836 def test_untrusted_syntax_error(self):
James E. Blaire53250c2017-03-01 14:34:36 -0800837 in_repo_conf = textwrap.dedent(
838 """
839 - job:
840 name: project-test2
841 foo: error
842 """)
843
844 file_dict = {'.zuul.yaml': in_repo_conf}
845 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
846 files=file_dict)
Tobias Henkelbf24fd12017-07-27 06:13:07 +0200847 A.addApproval('Code-Review', 2)
848 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
James E. Blaire53250c2017-03-01 14:34:36 -0800849 self.waitUntilSettled()
850
851 self.assertEqual(A.data['status'], 'NEW')
Tobias Henkel9842bd72017-05-16 13:40:03 +0200852 self.assertEqual(A.reported, 1,
853 "A should report failure")
854 self.assertIn('syntax error', A.messages[0],
James E. Blaire53250c2017-03-01 14:34:36 -0800855 "A should have a syntax error reported")
856
James E. Blair149b69c2017-03-02 10:48:16 -0800857 def test_trusted_syntax_error(self):
858 in_repo_conf = textwrap.dedent(
859 """
860 - job:
861 name: project-test2
862 foo: error
863 """)
864
865 file_dict = {'zuul.yaml': in_repo_conf}
866 A = self.fake_gerrit.addFakeChange('common-config', 'master', 'A',
867 files=file_dict)
Tobias Henkelbf24fd12017-07-27 06:13:07 +0200868 A.addApproval('Code-Review', 2)
869 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
James E. Blair149b69c2017-03-02 10:48:16 -0800870 self.waitUntilSettled()
871
872 self.assertEqual(A.data['status'], 'NEW')
Tobias Henkel9842bd72017-05-16 13:40:03 +0200873 self.assertEqual(A.reported, 1,
874 "A should report failure")
875 self.assertIn('syntax error', A.messages[0],
James E. Blair149b69c2017-03-02 10:48:16 -0800876 "A should have a syntax error reported")
877
James E. Blair6f140c72017-03-03 10:32:07 -0800878 def test_untrusted_yaml_error(self):
879 in_repo_conf = textwrap.dedent(
880 """
881 - job:
882 foo: error
883 """)
884
885 file_dict = {'.zuul.yaml': in_repo_conf}
886 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
887 files=file_dict)
Tobias Henkelbf24fd12017-07-27 06:13:07 +0200888 A.addApproval('Code-Review', 2)
889 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
James E. Blair6f140c72017-03-03 10:32:07 -0800890 self.waitUntilSettled()
891
892 self.assertEqual(A.data['status'], 'NEW')
Tobias Henkel9842bd72017-05-16 13:40:03 +0200893 self.assertEqual(A.reported, 1,
894 "A should report failure")
895 self.assertIn('syntax error', A.messages[0],
James E. Blair6f140c72017-03-03 10:32:07 -0800896 "A should have a syntax error reported")
897
James E. Blairdb04e6a2017-05-03 14:49:36 -0700898 def test_untrusted_shadow_error(self):
899 in_repo_conf = textwrap.dedent(
900 """
901 - job:
902 name: common-config-test
903 """)
904
905 file_dict = {'.zuul.yaml': in_repo_conf}
906 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
907 files=file_dict)
Tobias Henkelbf24fd12017-07-27 06:13:07 +0200908 A.addApproval('Code-Review', 2)
909 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
James E. Blairdb04e6a2017-05-03 14:49:36 -0700910 self.waitUntilSettled()
911
912 self.assertEqual(A.data['status'], 'NEW')
Tobias Henkel9842bd72017-05-16 13:40:03 +0200913 self.assertEqual(A.reported, 1,
914 "A should report failure")
915 self.assertIn('not permitted to shadow', A.messages[0],
James E. Blairdb04e6a2017-05-03 14:49:36 -0700916 "A should have a syntax error reported")
917
James E. Blaird5656ad2017-06-02 14:29:41 -0700918 def test_untrusted_pipeline_error(self):
919 in_repo_conf = textwrap.dedent(
920 """
921 - pipeline:
922 name: test
923 """)
924
925 file_dict = {'.zuul.yaml': in_repo_conf}
926 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
927 files=file_dict)
Tobias Henkelbf24fd12017-07-27 06:13:07 +0200928 A.addApproval('Code-Review', 2)
929 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
James E. Blaird5656ad2017-06-02 14:29:41 -0700930 self.waitUntilSettled()
931
932 self.assertEqual(A.data['status'], 'NEW')
933 self.assertEqual(A.reported, 1,
934 "A should report failure")
935 self.assertIn('Pipelines may not be defined', A.messages[0],
936 "A should have a syntax error reported")
937
938 def test_untrusted_project_error(self):
939 in_repo_conf = textwrap.dedent(
940 """
941 - project:
942 name: org/project1
943 """)
944
945 file_dict = {'.zuul.yaml': in_repo_conf}
946 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
947 files=file_dict)
Tobias Henkelbf24fd12017-07-27 06:13:07 +0200948 A.addApproval('Code-Review', 2)
949 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
James E. Blaird5656ad2017-06-02 14:29:41 -0700950 self.waitUntilSettled()
951
952 self.assertEqual(A.data['status'], 'NEW')
953 self.assertEqual(A.reported, 1,
954 "A should report failure")
955 self.assertIn('the only project definition permitted', A.messages[0],
956 "A should have a syntax error reported")
957
James E. Blairf03173b2017-10-10 10:46:43 -0700958 def test_untrusted_depends_on_trusted(self):
959 with open(os.path.join(FIXTURE_DIR,
960 'config/in-repo/git/',
961 'common-config/zuul.yaml')) as f:
962 common_config = f.read()
963
964 common_config += textwrap.dedent(
965 """
966 - job:
967 name: project-test9
968 """)
969
970 file_dict = {'zuul.yaml': common_config}
971 A = self.fake_gerrit.addFakeChange('common-config', 'master', 'A',
972 files=file_dict)
973 in_repo_conf = textwrap.dedent(
974 """
975 - job:
976 name: project-test1
977 - project:
978 name: org/project
979 check:
980 jobs:
981 - project-test9
982 """)
983
984 file_dict = {'zuul.yaml': in_repo_conf}
985 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B',
986 files=file_dict)
987 B.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
988 B.subject, A.data['id'])
989 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
990 self.waitUntilSettled()
991
992 self.assertEqual(B.data['status'], 'NEW')
993 self.assertEqual(B.reported, 1,
994 "B should report failure")
995 self.assertIn('depends on a change to a config project',
996 B.messages[0],
997 "A should have a syntax error reported")
998
James E. Blaire64b0e42017-06-08 11:23:34 -0700999 def test_duplicate_node_error(self):
1000 in_repo_conf = textwrap.dedent(
1001 """
1002 - nodeset:
1003 name: duplicate
1004 nodes:
1005 - name: compute
James E. Blair16d96a02017-06-08 11:32:56 -07001006 label: foo
James E. Blaire64b0e42017-06-08 11:23:34 -07001007 - name: compute
James E. Blair16d96a02017-06-08 11:32:56 -07001008 label: foo
James E. Blaire64b0e42017-06-08 11:23:34 -07001009 """)
1010
1011 file_dict = {'.zuul.yaml': in_repo_conf}
1012 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
1013 files=file_dict)
Tobias Henkelbf24fd12017-07-27 06:13:07 +02001014 A.addApproval('Code-Review', 2)
1015 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
James E. Blaire64b0e42017-06-08 11:23:34 -07001016 self.waitUntilSettled()
1017
1018 self.assertEqual(A.data['status'], 'NEW')
1019 self.assertEqual(A.reported, 1,
1020 "A should report failure")
1021 self.assertIn('appears multiple times', A.messages[0],
1022 "A should have a syntax error reported")
1023
1024 def test_duplicate_group_error(self):
1025 in_repo_conf = textwrap.dedent(
1026 """
1027 - nodeset:
1028 name: duplicate
1029 nodes:
1030 - name: compute
James E. Blair16d96a02017-06-08 11:32:56 -07001031 label: foo
James E. Blaire64b0e42017-06-08 11:23:34 -07001032 groups:
1033 - name: group
1034 nodes: compute
1035 - name: group
1036 nodes: compute
1037 """)
1038
1039 file_dict = {'.zuul.yaml': in_repo_conf}
1040 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
1041 files=file_dict)
Tobias Henkelbf24fd12017-07-27 06:13:07 +02001042 A.addApproval('Code-Review', 2)
1043 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
James E. Blaire64b0e42017-06-08 11:23:34 -07001044 self.waitUntilSettled()
1045
1046 self.assertEqual(A.data['status'], 'NEW')
1047 self.assertEqual(A.reported, 1,
1048 "A should report failure")
1049 self.assertIn('appears multiple times', A.messages[0],
1050 "A should have a syntax error reported")
1051
James E. Blair4ae399f2017-09-20 17:15:09 -07001052 def test_secret_not_found_error(self):
1053 in_repo_conf = textwrap.dedent(
1054 """
1055 - job:
1056 name: test
1057 secrets: does-not-exist
1058 """)
1059
1060 file_dict = {'.zuul.yaml': in_repo_conf}
1061 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
1062 files=file_dict)
1063 A.addApproval('Code-Review', 2)
1064 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
1065 self.waitUntilSettled()
1066
1067 self.assertEqual(A.data['status'], 'NEW')
1068 self.assertEqual(A.reported, 1,
1069 "A should report failure")
1070 self.assertIn('secret "does-not-exist" was not found', A.messages[0],
1071 "A should have a syntax error reported")
1072
1073 def test_nodeset_not_found_error(self):
1074 in_repo_conf = textwrap.dedent(
1075 """
1076 - job:
1077 name: test
1078 nodeset: does-not-exist
1079 """)
1080
1081 file_dict = {'.zuul.yaml': in_repo_conf}
1082 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
1083 files=file_dict)
1084 A.addApproval('Code-Review', 2)
1085 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
1086 self.waitUntilSettled()
1087
1088 self.assertEqual(A.data['status'], 'NEW')
1089 self.assertEqual(A.reported, 1,
1090 "A should report failure")
1091 self.assertIn('nodeset "does-not-exist" was not found', A.messages[0],
1092 "A should have a syntax error reported")
1093
James E. Blair89e25eb2017-09-26 09:11:31 -07001094 def test_template_not_found_error(self):
1095 in_repo_conf = textwrap.dedent(
1096 """
1097 - job:
1098 name: project-test1
1099 - project:
1100 name: org/project
1101 templates:
1102 - does-not-exist
1103 """)
1104
1105 file_dict = {'.zuul.yaml': in_repo_conf}
1106 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
1107 files=file_dict)
1108 A.addApproval('Code-Review', 2)
1109 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
1110 self.waitUntilSettled()
1111
1112 self.assertEqual(A.data['status'], 'NEW')
1113 self.assertEqual(A.reported, 1,
1114 "A should report failure")
1115 self.assertIn('project template "does-not-exist" was not found',
1116 A.messages[0],
1117 "A should have a syntax error reported")
1118
Monty Taylor8be3c0c2017-10-06 10:37:37 -05001119 def test_job_list_in_project_template_not_dict_error(self):
1120 in_repo_conf = textwrap.dedent(
1121 """
1122 - job:
1123 name: project-test1
1124 - project-template:
1125 name: some-jobs
1126 check:
1127 jobs:
1128 - project-test1:
1129 - required-projects:
1130 org/project2
1131 """)
1132
1133 file_dict = {'.zuul.yaml': in_repo_conf}
1134 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
1135 files=file_dict)
1136 A.addApproval('Code-Review', 2)
1137 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
1138 self.waitUntilSettled()
1139
1140 self.assertEqual(A.data['status'], 'NEW')
1141 self.assertEqual(A.reported, 1,
1142 "A should report failure")
1143 self.assertIn('expected str for dictionary value',
1144 A.messages[0], "A should have a syntax error reported")
1145
1146 def test_job_list_in_project_not_dict_error(self):
1147 in_repo_conf = textwrap.dedent(
1148 """
1149 - job:
1150 name: project-test1
1151 - project:
1152 name: org/project1
1153 check:
1154 jobs:
1155 - project-test1:
1156 - required-projects:
1157 org/project2
1158 """)
1159
1160 file_dict = {'.zuul.yaml': in_repo_conf}
1161 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
1162 files=file_dict)
1163 A.addApproval('Code-Review', 2)
1164 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
1165 self.waitUntilSettled()
1166
1167 self.assertEqual(A.data['status'], 'NEW')
1168 self.assertEqual(A.reported, 1,
1169 "A should report failure")
1170 self.assertIn('expected str for dictionary value',
1171 A.messages[0], "A should have a syntax error reported")
1172
James E. Blair1235f142017-10-07 09:11:43 -07001173 def test_project_template(self):
1174 # Tests that a project template is not modified when used, and
1175 # can therefore be used in subsequent reconfigurations.
1176 in_repo_conf = textwrap.dedent(
1177 """
1178 - job:
1179 name: project-test1
James E. Blair2f589fe2017-10-26 12:57:41 -07001180 run: playbooks/project-test1.yaml
James E. Blair1235f142017-10-07 09:11:43 -07001181 - project-template:
1182 name: some-jobs
1183 tenant-one-gate:
1184 jobs:
1185 - project-test1:
1186 required-projects:
1187 - org/project1
1188 - project:
1189 name: org/project
1190 templates:
1191 - some-jobs
1192 """)
1193
1194 file_dict = {'.zuul.yaml': in_repo_conf}
1195 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
1196 files=file_dict)
1197 A.addApproval('Code-Review', 2)
1198 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
1199 self.waitUntilSettled()
1200 self.assertEqual(A.data['status'], 'MERGED')
1201 self.fake_gerrit.addEvent(A.getChangeMergedEvent())
1202 self.waitUntilSettled()
1203 in_repo_conf = textwrap.dedent(
1204 """
1205 - project:
1206 name: org/project1
1207 templates:
1208 - some-jobs
1209 """)
1210 file_dict = {'.zuul.yaml': in_repo_conf}
1211 B = self.fake_gerrit.addFakeChange('org/project1', 'master', 'B',
1212 files=file_dict)
1213 B.addApproval('Code-Review', 2)
1214 self.fake_gerrit.addEvent(B.addApproval('Approved', 1))
1215 self.waitUntilSettled()
1216 self.assertEqual(B.data['status'], 'MERGED')
1217
James E. Blairbccdfcf2017-10-07 13:37:26 -07001218 def test_job_remove_add(self):
1219 # Tests that a job can be removed from one repo and added in another.
1220 # First, remove the current config for project1 since it
1221 # references the job we want to remove.
1222 file_dict = {'.zuul.yaml': None}
1223 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A',
1224 files=file_dict)
1225 A.setMerged()
1226 self.fake_gerrit.addEvent(A.getChangeMergedEvent())
1227 self.waitUntilSettled()
1228 # Then propose a change to delete the job from one repo...
1229 file_dict = {'.zuul.yaml': None}
1230 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B',
1231 files=file_dict)
1232 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
1233 self.waitUntilSettled()
1234 # ...and a second that depends on it that adds it to another repo.
1235 in_repo_conf = textwrap.dedent(
1236 """
1237 - job:
1238 name: project-test1
James E. Blair2f589fe2017-10-26 12:57:41 -07001239 run: playbooks/project-test1.yaml
James E. Blairbccdfcf2017-10-07 13:37:26 -07001240
1241 - project:
1242 name: org/project1
1243 check:
1244 jobs:
1245 - project-test1
1246 """)
1247 in_repo_playbook = textwrap.dedent(
1248 """
1249 - hosts: all
1250 tasks: []
1251 """)
1252 file_dict = {'.zuul.yaml': in_repo_conf,
1253 'playbooks/project-test1.yaml': in_repo_playbook}
1254 C = self.fake_gerrit.addFakeChange('org/project1', 'master', 'C',
1255 files=file_dict,
1256 parent='refs/changes/1/1/1')
1257 C.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
1258 C.subject, B.data['id'])
1259 self.fake_gerrit.addEvent(C.getPatchsetCreatedEvent(1))
1260 self.waitUntilSettled()
1261 self.assertHistory([
1262 dict(name='project-test1', result='SUCCESS', changes='2,1 3,1'),
1263 ], ordered=False)
1264
James E. Blair09f9ffe2017-07-11 15:30:25 -07001265 def test_multi_repo(self):
1266 downstream_repo_conf = textwrap.dedent(
1267 """
1268 - project:
1269 name: org/project1
1270 tenant-one-gate:
1271 jobs:
1272 - project-test1
1273
1274 - job:
1275 name: project1-test1
1276 parent: project-test1
1277 """)
1278
1279 file_dict = {'.zuul.yaml': downstream_repo_conf}
1280 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A',
1281 files=file_dict)
Tobias Henkelbf24fd12017-07-27 06:13:07 +02001282 A.addApproval('Code-Review', 2)
1283 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
James E. Blair09f9ffe2017-07-11 15:30:25 -07001284 self.waitUntilSettled()
1285
1286 self.assertEqual(A.data['status'], 'MERGED')
1287 self.fake_gerrit.addEvent(A.getChangeMergedEvent())
1288 self.waitUntilSettled()
1289
1290 upstream_repo_conf = textwrap.dedent(
1291 """
1292 - job:
1293 name: project-test1
James E. Blair2f589fe2017-10-26 12:57:41 -07001294 run: playbooks/project-test1.yaml
James E. Blair09f9ffe2017-07-11 15:30:25 -07001295
1296 - job:
1297 name: project-test2
1298
1299 - project:
1300 name: org/project
1301 tenant-one-gate:
1302 jobs:
1303 - project-test1
1304 """)
1305
1306 file_dict = {'.zuul.yaml': upstream_repo_conf}
1307 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B',
1308 files=file_dict)
Tobias Henkelbf24fd12017-07-27 06:13:07 +02001309 B.addApproval('Code-Review', 2)
1310 self.fake_gerrit.addEvent(B.addApproval('Approved', 1))
James E. Blair09f9ffe2017-07-11 15:30:25 -07001311 self.waitUntilSettled()
1312
1313 self.assertEqual(B.data['status'], 'MERGED')
1314 self.fake_gerrit.addEvent(B.getChangeMergedEvent())
1315 self.waitUntilSettled()
1316
1317 tenant = self.sched.abide.tenants.get('tenant-one')
1318 # Ensure the latest change is reflected in the config; if it
1319 # isn't this will raise an exception.
1320 tenant.layout.getJob('project-test2')
1321
James E. Blair332636e2017-09-05 10:14:35 -07001322 def test_pipeline_error(self):
1323 with open(os.path.join(FIXTURE_DIR,
1324 'config/in-repo/git/',
1325 'common-config/zuul.yaml')) as f:
1326 base_common_config = f.read()
1327
1328 in_repo_conf_A = textwrap.dedent(
1329 """
1330 - pipeline:
1331 name: periodic
1332 foo: error
1333 """)
1334
1335 file_dict = {'zuul.yaml': None,
1336 'zuul.d/main.yaml': base_common_config,
1337 'zuul.d/test1.yaml': in_repo_conf_A}
1338 A = self.fake_gerrit.addFakeChange('common-config', 'master', 'A',
1339 files=file_dict)
1340 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
1341 self.waitUntilSettled()
1342 self.assertEqual(A.reported, 1,
1343 "A should report failure")
1344 self.assertIn('syntax error',
1345 A.messages[0],
1346 "A should have an error reported")
1347
1348 def test_change_series_error(self):
1349 with open(os.path.join(FIXTURE_DIR,
1350 'config/in-repo/git/',
1351 'common-config/zuul.yaml')) as f:
1352 base_common_config = f.read()
1353
1354 in_repo_conf_A = textwrap.dedent(
1355 """
1356 - pipeline:
1357 name: periodic
1358 foo: error
1359 """)
1360
1361 file_dict = {'zuul.yaml': None,
1362 'zuul.d/main.yaml': base_common_config,
1363 'zuul.d/test1.yaml': in_repo_conf_A}
1364 A = self.fake_gerrit.addFakeChange('common-config', 'master', 'A',
1365 files=file_dict)
1366
1367 in_repo_conf_B = textwrap.dedent(
1368 """
1369 - job:
1370 name: project-test2
1371 foo: error
1372 """)
1373
1374 file_dict = {'zuul.yaml': None,
1375 'zuul.d/main.yaml': base_common_config,
1376 'zuul.d/test1.yaml': in_repo_conf_A,
1377 'zuul.d/test2.yaml': in_repo_conf_B}
1378 B = self.fake_gerrit.addFakeChange('common-config', 'master', 'B',
1379 files=file_dict)
1380 B.setDependsOn(A, 1)
1381 C = self.fake_gerrit.addFakeChange('common-config', 'master', 'C')
1382 C.setDependsOn(B, 1)
1383 self.fake_gerrit.addEvent(C.getPatchsetCreatedEvent(1))
1384 self.waitUntilSettled()
1385
1386 self.assertEqual(C.reported, 1,
1387 "C should report failure")
1388 self.assertIn('depends on a change that failed to merge',
1389 C.messages[0],
1390 "C should have an error reported")
1391
James E. Blairc73c73a2017-01-20 15:15:15 -08001392
James E. Blairc9455002017-09-06 09:22:19 -07001393class TestInRepoJoin(ZuulTestCase):
1394 # In this config, org/project is not a member of any pipelines, so
1395 # that we may test the changes that cause it to join them.
1396
1397 tenant_config_file = 'config/in-repo-join/main.yaml'
1398
1399 def test_dynamic_dependent_pipeline(self):
1400 # Test dynamically adding a project to a
1401 # dependent pipeline for the first time
1402 self.executor_server.hold_jobs_in_build = True
1403
1404 tenant = self.sched.abide.tenants.get('tenant-one')
1405 gate_pipeline = tenant.layout.pipelines['gate']
1406
1407 in_repo_conf = textwrap.dedent(
1408 """
1409 - job:
1410 name: project-test1
James E. Blair2f589fe2017-10-26 12:57:41 -07001411 run: playbooks/project-test1.yaml
James E. Blairc9455002017-09-06 09:22:19 -07001412
1413 - job:
1414 name: project-test2
James E. Blair2f589fe2017-10-26 12:57:41 -07001415 run: playbooks/project-test2.yaml
James E. Blairc9455002017-09-06 09:22:19 -07001416
1417 - project:
1418 name: org/project
1419 gate:
1420 jobs:
1421 - project-test2
1422 """)
1423
1424 in_repo_playbook = textwrap.dedent(
1425 """
1426 - hosts: all
1427 tasks: []
1428 """)
1429
1430 file_dict = {'.zuul.yaml': in_repo_conf,
1431 'playbooks/project-test2.yaml': in_repo_playbook}
1432 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
1433 files=file_dict)
1434 A.addApproval('Code-Review', 2)
1435 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
1436 self.waitUntilSettled()
1437
1438 items = gate_pipeline.getAllItems()
1439 self.assertEqual(items[0].change.number, '1')
1440 self.assertEqual(items[0].change.patchset, '1')
1441 self.assertTrue(items[0].live)
1442
1443 self.executor_server.hold_jobs_in_build = False
1444 self.executor_server.release()
1445 self.waitUntilSettled()
1446
1447 # Make sure the dynamic queue got cleaned up
1448 self.assertEqual(gate_pipeline.queues, [])
1449
1450 def test_dynamic_dependent_pipeline_failure(self):
1451 # Test that a change behind a failing change adding a project
1452 # to a dependent pipeline is dequeued.
1453 self.executor_server.hold_jobs_in_build = True
1454
1455 in_repo_conf = textwrap.dedent(
1456 """
1457 - job:
1458 name: project-test1
James E. Blair2f589fe2017-10-26 12:57:41 -07001459 run: playbooks/project-test1.yaml
James E. Blairc9455002017-09-06 09:22:19 -07001460
1461 - project:
1462 name: org/project
1463 gate:
1464 jobs:
1465 - project-test1
1466 """)
1467
1468 file_dict = {'.zuul.yaml': in_repo_conf}
1469 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
1470 files=file_dict)
1471 self.executor_server.failJob('project-test1', A)
1472 A.addApproval('Code-Review', 2)
1473 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
1474 self.waitUntilSettled()
1475
1476 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
1477 B.addApproval('Code-Review', 2)
1478 self.fake_gerrit.addEvent(B.addApproval('Approved', 1))
1479 self.waitUntilSettled()
1480
James E. Blair3490c5d2017-09-07 08:33:23 -07001481 self.orderedRelease()
James E. Blairc9455002017-09-06 09:22:19 -07001482 self.waitUntilSettled()
1483 self.assertEqual(A.reported, 2,
1484 "A should report start and failure")
1485 self.assertEqual(A.data['status'], 'NEW')
1486 self.assertEqual(B.reported, 1,
1487 "B should report start")
1488 self.assertHistory([
1489 dict(name='project-test1', result='FAILURE', changes='1,1'),
James E. Blair3490c5d2017-09-07 08:33:23 -07001490 dict(name='project-test1', result='ABORTED', changes='1,1 2,1'),
James E. Blairc9455002017-09-06 09:22:19 -07001491 ], ordered=False)
1492
James E. Blair0af198f2017-09-06 09:52:35 -07001493 def test_dynamic_dependent_pipeline_absent(self):
1494 # Test that a series of dependent changes don't report merge
1495 # failures to a pipeline they aren't in.
1496 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1497 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
1498 B.setDependsOn(A, 1)
1499
1500 A.addApproval('Code-Review', 2)
1501 A.addApproval('Approved', 1)
1502 B.addApproval('Code-Review', 2)
1503 self.fake_gerrit.addEvent(B.addApproval('Approved', 1))
1504 self.waitUntilSettled()
1505 self.assertEqual(A.reported, 0,
1506 "A should not report")
1507 self.assertEqual(A.data['status'], 'NEW')
1508 self.assertEqual(B.reported, 0,
1509 "B should not report")
1510 self.assertEqual(B.data['status'], 'NEW')
1511 self.assertHistory([])
1512
James E. Blairc9455002017-09-06 09:22:19 -07001513
James E. Blairc73c73a2017-01-20 15:15:15 -08001514class TestAnsible(AnsibleZuulTestCase):
1515 # A temporary class to hold new tests while others are disabled
1516
1517 tenant_config_file = 'config/ansible/main.yaml'
1518
1519 def test_playbook(self):
Jamie Lennox7655b552017-03-17 12:33:38 +11001520 # Keep the jobdir around so we can inspect contents if an
1521 # assert fails.
1522 self.executor_server.keep_jobdir = True
1523 # Output extra ansible info so we might see errors.
1524 self.executor_server.verbose = True
1525 # Add a site variables file, used by check-vars
1526 path = os.path.join(FIXTURE_DIR, 'config', 'ansible',
1527 'variables.yaml')
1528 self.config.set('executor', 'variables', path)
James E. Blairc73c73a2017-01-20 15:15:15 -08001529 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1530 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
1531 self.waitUntilSettled()
Tobias Henkel077f2f32017-05-30 20:16:46 +02001532 build_timeout = self.getJobFromHistory('timeout')
Jamie Lennox7655b552017-03-17 12:33:38 +11001533 with self.jobLog(build_timeout):
1534 self.assertEqual(build_timeout.result, 'TIMED_OUT')
Tobias Henkel077f2f32017-05-30 20:16:46 +02001535 build_faillocal = self.getJobFromHistory('faillocal')
Jamie Lennox7655b552017-03-17 12:33:38 +11001536 with self.jobLog(build_faillocal):
1537 self.assertEqual(build_faillocal.result, 'FAILURE')
Tobias Henkel077f2f32017-05-30 20:16:46 +02001538 build_failpost = self.getJobFromHistory('failpost')
Jamie Lennox7655b552017-03-17 12:33:38 +11001539 with self.jobLog(build_failpost):
1540 self.assertEqual(build_failpost.result, 'POST_FAILURE')
Tobias Henkel077f2f32017-05-30 20:16:46 +02001541 build_check_vars = self.getJobFromHistory('check-vars')
Jamie Lennox7655b552017-03-17 12:33:38 +11001542 with self.jobLog(build_check_vars):
1543 self.assertEqual(build_check_vars.result, 'SUCCESS')
Monty Tayloraff8b402017-08-16 18:40:41 -05001544 build_check_secret_names = self.getJobFromHistory('check-secret-names')
1545 with self.jobLog(build_check_secret_names):
1546 self.assertEqual(build_check_secret_names.result, 'SUCCESS')
Tobias Henkel077f2f32017-05-30 20:16:46 +02001547 build_hello = self.getJobFromHistory('hello-world')
Jamie Lennox7655b552017-03-17 12:33:38 +11001548 with self.jobLog(build_hello):
1549 self.assertEqual(build_hello.result, 'SUCCESS')
Tobias Henkel077f2f32017-05-30 20:16:46 +02001550 build_python27 = self.getJobFromHistory('python27')
Jamie Lennox7655b552017-03-17 12:33:38 +11001551 with self.jobLog(build_python27):
1552 self.assertEqual(build_python27.result, 'SUCCESS')
1553 flag_path = os.path.join(self.test_root,
1554 build_python27.uuid + '.flag')
1555 self.assertTrue(os.path.exists(flag_path))
1556 copied_path = os.path.join(self.test_root, build_python27.uuid +
1557 '.copied')
1558 self.assertTrue(os.path.exists(copied_path))
1559 failed_path = os.path.join(self.test_root, build_python27.uuid +
1560 '.failed')
1561 self.assertFalse(os.path.exists(failed_path))
1562 pre_flag_path = os.path.join(self.test_root, build_python27.uuid +
1563 '.pre.flag')
1564 self.assertTrue(os.path.exists(pre_flag_path))
1565 post_flag_path = os.path.join(self.test_root, build_python27.uuid +
1566 '.post.flag')
1567 self.assertTrue(os.path.exists(post_flag_path))
1568 bare_role_flag_path = os.path.join(self.test_root,
1569 build_python27.uuid +
1570 '.bare-role.flag')
1571 self.assertTrue(os.path.exists(bare_role_flag_path))
1572 secrets_path = os.path.join(self.test_root,
1573 build_python27.uuid + '.secrets')
1574 with open(secrets_path) as f:
1575 self.assertEqual(f.read(), "test-username test-password")
James E. Blairb9c0d772017-03-03 14:34:49 -08001576
Jamie Lennox7655b552017-03-17 12:33:38 +11001577 msg = A.messages[0]
1578 success = "{} https://success.example.com/zuul-logs/{}"
1579 fail = "{} https://failure.example.com/zuul-logs/{}"
1580 self.assertIn(success.format("python27", build_python27.uuid), msg)
1581 self.assertIn(fail.format("faillocal", build_faillocal.uuid), msg)
1582 self.assertIn(success.format("check-vars",
1583 build_check_vars.uuid), msg)
1584 self.assertIn(success.format("hello-world", build_hello.uuid), msg)
1585 self.assertIn(fail.format("timeout", build_timeout.uuid), msg)
1586 self.assertIn(fail.format("failpost", build_failpost.uuid), msg)
Tobias Henkel077f2f32017-05-30 20:16:46 +02001587
James E. Blairabbaa6f2017-04-06 16:11:44 -07001588 def _add_job(self, job_name):
1589 conf = textwrap.dedent(
1590 """
1591 - job:
1592 name: %s
James E. Blair2f589fe2017-10-26 12:57:41 -07001593 run: playbooks/%s.yaml
James E. Blairabbaa6f2017-04-06 16:11:44 -07001594
1595 - project:
1596 name: org/plugin-project
1597 check:
1598 jobs:
1599 - %s
James E. Blair2f589fe2017-10-26 12:57:41 -07001600 """ % (job_name, job_name, job_name))
James E. Blairabbaa6f2017-04-06 16:11:44 -07001601
1602 file_dict = {'.zuul.yaml': conf}
1603 A = self.fake_gerrit.addFakeChange('org/plugin-project', 'master', 'A',
1604 files=file_dict)
1605 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
1606 self.waitUntilSettled()
1607
1608 def test_plugins(self):
1609 # Keep the jobdir around so we can inspect contents if an
1610 # assert fails.
1611 self.executor_server.keep_jobdir = True
1612 # Output extra ansible info so we might see errors.
1613 self.executor_server.verbose = True
1614
1615 count = 0
1616 plugin_tests = [
1617 ('passwd', 'FAILURE'),
1618 ('cartesian', 'SUCCESS'),
1619 ('consul_kv', 'FAILURE'),
1620 ('credstash', 'FAILURE'),
1621 ('csvfile_good', 'SUCCESS'),
1622 ('csvfile_bad', 'FAILURE'),
Monty Taylor93ad2212017-08-02 14:59:50 -05001623 ('uri_bad_path', 'FAILURE'),
1624 ('uri_bad_scheme', 'FAILURE'),
Monty Taylor788a40e2017-08-02 16:14:05 -05001625 ('block_local_override', 'FAILURE'),
Monty Taylor8da768f2017-08-31 14:15:35 -05001626 ('file_local_good', 'SUCCESS'),
1627 ('file_local_bad', 'FAILURE'),
James E. Blairabbaa6f2017-04-06 16:11:44 -07001628 ]
1629 for job_name, result in plugin_tests:
1630 count += 1
1631 self._add_job(job_name)
1632
1633 job = self.getJobFromHistory(job_name)
1634 with self.jobLog(job):
1635 self.assertEqual(count, len(self.history))
1636 build = self.history[-1]
1637 self.assertEqual(build.result, result)
1638
1639 # TODOv3(jeblair): parse the ansible output and verify we're
1640 # getting the exception we expect.
1641
James E. Blairb9c0d772017-03-03 14:34:49 -08001642
James E. Blaira4d4eef2017-06-30 14:49:17 -07001643class TestPrePlaybooks(AnsibleZuulTestCase):
1644 # A temporary class to hold new tests while others are disabled
1645
1646 tenant_config_file = 'config/pre-playbook/main.yaml'
1647
1648 def test_pre_playbook_fail(self):
1649 # Test that we run the post playbooks (but not the actual
1650 # playbook) when a pre-playbook fails.
1651 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1652 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
1653 self.waitUntilSettled()
1654 build = self.getJobFromHistory('python27')
1655 self.assertIsNone(build.result)
1656 self.assertIn('RETRY_LIMIT', A.messages[0])
1657 flag_path = os.path.join(self.test_root, build.uuid +
1658 '.main.flag')
1659 self.assertFalse(os.path.exists(flag_path))
1660 pre_flag_path = os.path.join(self.test_root, build.uuid +
1661 '.pre.flag')
1662 self.assertFalse(os.path.exists(pre_flag_path))
1663 post_flag_path = os.path.join(self.test_root, build.uuid +
1664 '.post.flag')
James E. Blair21037782017-07-19 11:56:55 -07001665 self.assertTrue(os.path.exists(post_flag_path),
1666 "The file %s should exist" % post_flag_path)
James E. Blaira4d4eef2017-06-30 14:49:17 -07001667
1668
James E. Blairbacbb882017-10-17 09:48:23 -07001669class TestPostPlaybooks(AnsibleZuulTestCase):
1670 tenant_config_file = 'config/post-playbook/main.yaml'
1671
1672 def test_post_playbook_abort(self):
1673 # Test that when we abort a job in the post playbook, that we
1674 # don't send back POST_FAILURE.
1675 self.executor_server.verbose = True
1676 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1677 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
1678
1679 while not len(self.builds):
1680 time.sleep(0.1)
1681 build = self.builds[0]
1682
1683 post_start = os.path.join(self.test_root, build.uuid +
1684 '.post_start.flag')
1685 start = time.time()
1686 while time.time() < start + 90:
1687 if os.path.exists(post_start):
1688 break
1689 time.sleep(0.1)
1690 # The post playbook has started, abort the job
1691 self.fake_gerrit.addEvent(A.getChangeAbandonedEvent())
1692 self.waitUntilSettled()
1693
1694 build = self.getJobFromHistory('python27')
1695 self.assertEqual('ABORTED', build.result)
1696
1697 post_end = os.path.join(self.test_root, build.uuid +
1698 '.post_end.flag')
1699 self.assertTrue(os.path.exists(post_start))
1700 self.assertFalse(os.path.exists(post_end))
1701
1702
James E. Blairb9c0d772017-03-03 14:34:49 -08001703class TestBrokenConfig(ZuulTestCase):
1704 # Test that we get an appropriate syntax error if we start with a
1705 # broken config.
1706
1707 tenant_config_file = 'config/broken/main.yaml'
1708
1709 def setUp(self):
1710 with testtools.ExpectedException(
1711 zuul.configloader.ConfigurationSyntaxError,
1712 "\nZuul encountered a syntax error"):
1713 super(TestBrokenConfig, self).setUp()
1714
1715 def test_broken_config_on_startup(self):
1716 pass
Ricardo Carrillo Cruz22994f92016-12-02 11:41:58 +00001717
1718
1719class TestProjectKeys(ZuulTestCase):
1720 # Test that we can generate project keys
1721
1722 # Normally the test infrastructure copies a static key in place
1723 # for each project before starting tests. This saves time because
1724 # Zuul's automatic key-generation on startup can be slow. To make
1725 # sure we exercise that code, in this test we allow Zuul to create
1726 # keys for the project on startup.
1727 create_project_keys = True
Tobias Henkelabf973e2017-07-28 10:07:34 +02001728 config_file = 'zuul-connections-gerrit-and-github.conf'
Ricardo Carrillo Cruz22994f92016-12-02 11:41:58 +00001729 tenant_config_file = 'config/in-repo/main.yaml'
1730
1731 def test_key_generation(self):
1732 key_root = os.path.join(self.state_root, 'keys')
1733 private_key_file = os.path.join(key_root, 'gerrit/org/project.pem')
1734 # Make sure that a proper key was created on startup
1735 with open(private_key_file, "rb") as f:
James E. Blairbf1a4f22017-03-17 10:59:37 -07001736 private_key, public_key = \
1737 encryption.deserialize_rsa_keypair(f.read())
Ricardo Carrillo Cruz22994f92016-12-02 11:41:58 +00001738
1739 with open(os.path.join(FIXTURE_DIR, 'private.pem')) as i:
1740 fixture_private_key = i.read()
1741
1742 # Make sure that we didn't just end up with the static fixture
1743 # key
1744 self.assertNotEqual(fixture_private_key, private_key)
1745
1746 # Make sure it's the right length
1747 self.assertEqual(4096, private_key.key_size)
James E. Blairbce76932017-05-04 10:03:15 -07001748
1749
James E. Blairbb94dfa2017-07-11 07:45:19 -07001750class RoleTestCase(ZuulTestCase):
James E. Blair1b27f6a2017-07-14 14:09:07 -07001751 def _assertRolePath(self, build, playbook, content):
1752 path = os.path.join(self.test_root, build.uuid,
1753 'ansible', playbook, 'ansible.cfg')
1754 roles_paths = []
1755 with open(path) as f:
1756 for line in f:
1757 if line.startswith('roles_path'):
1758 roles_paths.append(line)
1759 print(roles_paths)
1760 if content:
1761 self.assertEqual(len(roles_paths), 1,
1762 "Should have one roles_path line in %s" %
1763 (playbook,))
1764 self.assertIn(content, roles_paths[0])
1765 else:
1766 self.assertEqual(len(roles_paths), 0,
1767 "Should have no roles_path line in %s" %
1768 (playbook,))
1769
James E. Blairbb94dfa2017-07-11 07:45:19 -07001770
1771class TestRoles(RoleTestCase):
1772 tenant_config_file = 'config/roles/main.yaml'
1773
James E. Blairbce76932017-05-04 10:03:15 -07001774 def test_role(self):
1775 # This exercises a proposed change to a role being checked out
1776 # and used.
1777 A = self.fake_gerrit.addFakeChange('bare-role', 'master', 'A')
1778 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1779 B.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
1780 B.subject, A.data['id'])
1781 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
1782 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
1783 self.waitUntilSettled()
1784 self.assertHistory([
1785 dict(name='project-test', result='SUCCESS', changes='1,1 2,1'),
1786 ])
James E. Blair6459db12017-06-29 14:57:20 -07001787
James E. Blair1b27f6a2017-07-14 14:09:07 -07001788 def test_role_inheritance(self):
1789 self.executor_server.hold_jobs_in_build = True
1790 conf = textwrap.dedent(
1791 """
1792 - job:
1793 name: parent
1794 roles:
1795 - zuul: bare-role
1796 pre-run: playbooks/parent-pre
1797 post-run: playbooks/parent-post
1798
1799 - job:
1800 name: project-test
1801 parent: parent
James E. Blair2f589fe2017-10-26 12:57:41 -07001802 run: playbooks/project-test.yaml
James E. Blair1b27f6a2017-07-14 14:09:07 -07001803 roles:
1804 - zuul: org/project
1805
1806 - project:
1807 name: org/project
1808 check:
1809 jobs:
1810 - project-test
1811 """)
1812
1813 file_dict = {'.zuul.yaml': conf}
1814 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
1815 files=file_dict)
1816 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
1817 self.waitUntilSettled()
1818
1819 self.assertEqual(len(self.builds), 1)
1820 build = self.getBuildByName('project-test')
1821 self._assertRolePath(build, 'pre_playbook_0', 'role_0')
1822 self._assertRolePath(build, 'playbook_0', 'role_0')
1823 self._assertRolePath(build, 'playbook_0', 'role_1')
1824 self._assertRolePath(build, 'post_playbook_0', 'role_0')
1825
1826 self.executor_server.hold_jobs_in_build = False
1827 self.executor_server.release()
1828 self.waitUntilSettled()
1829
1830 self.assertHistory([
1831 dict(name='project-test', result='SUCCESS', changes='1,1'),
1832 ])
1833
James E. Blair6f699732017-07-18 14:19:11 -07001834 def test_role_error(self):
1835 conf = textwrap.dedent(
1836 """
1837 - job:
1838 name: project-test
James E. Blair2f589fe2017-10-26 12:57:41 -07001839 run: playbooks/project-test.yaml
James E. Blair6f699732017-07-18 14:19:11 -07001840 roles:
1841 - zuul: common-config
1842
1843 - project:
1844 name: org/project
1845 check:
1846 jobs:
1847 - project-test
1848 """)
1849
1850 file_dict = {'.zuul.yaml': conf}
1851 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
1852 files=file_dict)
1853 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
1854 self.waitUntilSettled()
1855 self.assertIn(
1856 '- project-test project-test : ERROR Unable to find role',
1857 A.messages[-1])
1858
James E. Blair6459db12017-06-29 14:57:20 -07001859
James E. Blairbb94dfa2017-07-11 07:45:19 -07001860class TestImplicitRoles(RoleTestCase):
1861 tenant_config_file = 'config/implicit-roles/main.yaml'
1862
1863 def test_missing_roles(self):
1864 # Test implicit and explicit roles for a project which does
1865 # not have roles. The implicit role should be silently
1866 # ignored since the project doesn't supply roles, but if a
1867 # user declares an explicit role, it should error.
1868 self.executor_server.hold_jobs_in_build = True
1869 A = self.fake_gerrit.addFakeChange('org/norole-project', 'master', 'A')
1870 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
1871 self.waitUntilSettled()
1872
1873 self.assertEqual(len(self.builds), 2)
1874 build = self.getBuildByName('implicit-role-fail')
1875 self._assertRolePath(build, 'playbook_0', None)
1876
1877 self.executor_server.hold_jobs_in_build = False
1878 self.executor_server.release()
1879 self.waitUntilSettled()
1880 # The retry_limit doesn't get recorded
1881 self.assertHistory([
1882 dict(name='implicit-role-fail', result='SUCCESS', changes='1,1'),
1883 ])
1884
1885 def test_roles(self):
1886 # Test implicit and explicit roles for a project which does
1887 # have roles. In both cases, we should end up with the role
1888 # in the path. In the explicit case, ensure we end up with
1889 # the name we specified.
1890 self.executor_server.hold_jobs_in_build = True
1891 A = self.fake_gerrit.addFakeChange('org/role-project', 'master', 'A')
1892 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
1893 self.waitUntilSettled()
1894
1895 self.assertEqual(len(self.builds), 2)
1896 build = self.getBuildByName('implicit-role-ok')
1897 self._assertRolePath(build, 'playbook_0', 'role_0')
1898
1899 build = self.getBuildByName('explicit-role-ok')
1900 self._assertRolePath(build, 'playbook_0', 'role_0')
1901
1902 self.executor_server.hold_jobs_in_build = False
1903 self.executor_server.release()
1904 self.waitUntilSettled()
1905 self.assertHistory([
1906 dict(name='implicit-role-ok', result='SUCCESS', changes='1,1'),
1907 dict(name='explicit-role-ok', result='SUCCESS', changes='1,1'),
1908 ], ordered=False)
1909
1910
James E. Blair6459db12017-06-29 14:57:20 -07001911class TestShadow(ZuulTestCase):
1912 tenant_config_file = 'config/shadow/main.yaml'
1913
1914 def test_shadow(self):
1915 # Test that a repo is allowed to shadow another's job definitions.
1916 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1917 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
1918 self.waitUntilSettled()
1919 self.assertHistory([
1920 dict(name='test1', result='SUCCESS', changes='1,1'),
1921 dict(name='test2', result='SUCCESS', changes='1,1'),
James E. Blairadafa6c2017-07-12 08:50:56 -07001922 ], ordered=False)
James E. Blair196f61a2017-06-30 15:42:29 -07001923
1924
1925class TestDataReturn(AnsibleZuulTestCase):
1926 tenant_config_file = 'config/data-return/main.yaml'
1927
1928 def test_data_return(self):
James E. Blair196f61a2017-06-30 15:42:29 -07001929 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1930 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
1931 self.waitUntilSettled()
1932 self.assertHistory([
1933 dict(name='data-return', result='SUCCESS', changes='1,1'),
James E. Blair88e79c02017-07-07 13:36:54 -07001934 dict(name='data-return-relative', result='SUCCESS', changes='1,1'),
James E. Blair698703c2017-09-15 20:58:30 -06001935 dict(name='child', result='SUCCESS', changes='1,1'),
James E. Blair88e79c02017-07-07 13:36:54 -07001936 ], ordered=False)
1937 self.assertIn('- data-return http://example.com/test/log/url/',
1938 A.messages[-1])
1939 self.assertIn('- data-return-relative '
1940 'http://example.com/test/log/url/docs/index.html',
James E. Blair196f61a2017-06-30 15:42:29 -07001941 A.messages[-1])
Clint Byrumdc8a0902017-07-20 16:36:27 -07001942
1943
1944class TestDiskAccounting(AnsibleZuulTestCase):
1945 config_file = 'zuul-disk-accounting.conf'
1946 tenant_config_file = 'config/disk-accountant/main.yaml'
1947
1948 def test_disk_accountant_kills_job(self):
1949 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1950 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
1951 self.waitUntilSettled()
1952 self.assertHistory([
1953 dict(name='dd-big-empty-file', result='ABORTED', changes='1,1')])
Tristan Cacqueray82f864b2017-08-01 05:54:42 +00001954
1955
1956class TestMaxNodesPerJob(AnsibleZuulTestCase):
1957 tenant_config_file = 'config/multi-tenant/main.yaml'
1958
Tristan Cacquerayc98bff72017-09-10 15:25:26 +00001959 def test_max_timeout_exceeded(self):
Tristan Cacqueray82f864b2017-08-01 05:54:42 +00001960 in_repo_conf = textwrap.dedent(
1961 """
1962 - job:
1963 name: test-job
James E. Blair7e3e6882017-09-20 15:47:13 -07001964 nodeset:
1965 nodes:
1966 - name: node01
1967 label: fake
1968 - name: node02
1969 label: fake
1970 - name: node03
1971 label: fake
1972 - name: node04
1973 label: fake
1974 - name: node05
1975 label: fake
1976 - name: node06
1977 label: fake
Tristan Cacqueray82f864b2017-08-01 05:54:42 +00001978 """)
1979 file_dict = {'.zuul.yaml': in_repo_conf}
1980 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A',
1981 files=file_dict)
1982 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
1983 self.waitUntilSettled()
1984 self.assertIn('The job "test-job" exceeds tenant max-nodes-per-job 5.',
1985 A.messages[0], "A should fail because of nodes limit")
1986
1987 B = self.fake_gerrit.addFakeChange('org/project2', 'master', 'A',
1988 files=file_dict)
1989 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
1990 self.waitUntilSettled()
1991 self.assertNotIn("exceeds tenant max-nodes", B.messages[0],
1992 "B should not fail because of nodes limit")
James E. Blair2bab6e72017-08-07 09:52:45 -07001993
1994
Tristan Cacquerayc98bff72017-09-10 15:25:26 +00001995class TestMaxTimeout(AnsibleZuulTestCase):
1996 tenant_config_file = 'config/multi-tenant/main.yaml'
1997
1998 def test_max_nodes_reached(self):
1999 in_repo_conf = textwrap.dedent(
2000 """
2001 - job:
2002 name: test-job
2003 timeout: 3600
2004 """)
2005 file_dict = {'.zuul.yaml': in_repo_conf}
2006 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A',
2007 files=file_dict)
2008 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2009 self.waitUntilSettled()
2010 self.assertIn('The job "test-job" exceeds tenant max-job-timeout',
2011 A.messages[0], "A should fail because of timeout limit")
2012
2013 B = self.fake_gerrit.addFakeChange('org/project2', 'master', 'A',
2014 files=file_dict)
2015 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
2016 self.waitUntilSettled()
2017 self.assertNotIn("exceeds tenant max-job-timeout", B.messages[0],
2018 "B should not fail because of timeout limit")
2019
2020
James E. Blair7edc25f2017-10-26 10:47:14 -07002021class TestPragma(ZuulTestCase):
2022 tenant_config_file = 'config/pragma/main.yaml'
2023
2024 def test_no_pragma(self):
2025 self.create_branch('org/project', 'stable')
2026 with open(os.path.join(FIXTURE_DIR,
2027 'config/pragma/git/',
2028 'org_project/nopragma.yaml')) as f:
2029 config = f.read()
2030 file_dict = {'.zuul.yaml': config}
2031 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
2032 files=file_dict)
2033 A.addApproval('Code-Review', 2)
2034 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
2035 self.waitUntilSettled()
2036 self.fake_gerrit.addEvent(A.getChangeMergedEvent())
2037 self.waitUntilSettled()
2038
2039 # This is an untrusted repo with 2 branches, so it should have
2040 # an implied branch matcher for the job.
2041 tenant = self.sched.abide.tenants.get('tenant-one')
2042 jobs = tenant.layout.getJobs('test-job')
2043 self.assertEqual(len(jobs), 1)
2044 for job in tenant.layout.getJobs('test-job'):
2045 self.assertIsNotNone(job.branch_matcher)
2046
2047 def test_pragma(self):
2048 self.create_branch('org/project', 'stable')
2049 with open(os.path.join(FIXTURE_DIR,
2050 'config/pragma/git/',
2051 'org_project/pragma.yaml')) as f:
2052 config = f.read()
2053 file_dict = {'.zuul.yaml': config}
2054 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
2055 files=file_dict)
2056 A.addApproval('Code-Review', 2)
2057 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
2058 self.waitUntilSettled()
2059 self.fake_gerrit.addEvent(A.getChangeMergedEvent())
2060 self.waitUntilSettled()
2061
2062 # This is an untrusted repo with 2 branches, so it would
2063 # normally have an implied branch matcher, but our pragma
2064 # overrides it.
2065 tenant = self.sched.abide.tenants.get('tenant-one')
2066 jobs = tenant.layout.getJobs('test-job')
2067 self.assertEqual(len(jobs), 1)
2068 for job in tenant.layout.getJobs('test-job'):
2069 self.assertIsNone(job.branch_matcher)
2070
2071
James E. Blair2bab6e72017-08-07 09:52:45 -07002072class TestBaseJobs(ZuulTestCase):
2073 tenant_config_file = 'config/base-jobs/main.yaml'
2074
2075 def test_multiple_base_jobs(self):
2076 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2077 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2078 self.waitUntilSettled()
2079 self.assertHistory([
2080 dict(name='my-job', result='SUCCESS', changes='1,1'),
2081 dict(name='other-job', result='SUCCESS', changes='1,1'),
2082 ], ordered=False)
2083 self.assertEqual(self.getJobFromHistory('my-job').
2084 parameters['zuul']['jobtags'],
2085 ['mybase'])
2086 self.assertEqual(self.getJobFromHistory('other-job').
2087 parameters['zuul']['jobtags'],
2088 ['otherbase'])
2089
2090 def test_untrusted_base_job(self):
2091 """Test that a base job may not be defined in an untrusted repo"""
2092 in_repo_conf = textwrap.dedent(
2093 """
2094 - job:
2095 name: fail-base
2096 parent: null
2097 """)
2098
2099 file_dict = {'.zuul.yaml': in_repo_conf}
2100 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
2101 files=file_dict)
2102 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2103 self.waitUntilSettled()
2104 self.assertEqual(A.reported, 1,
2105 "A should report failure")
2106 self.assertEqual(A.patchsets[0]['approvals'][0]['value'], "-1")
2107 self.assertIn('Base jobs must be defined in config projects',
2108 A.messages[0])
2109 self.assertHistory([])
James E. Blairdb089032017-08-15 13:42:12 -07002110
2111
James E. Blairdf91ab32017-10-25 17:57:13 -07002112class TestSecretInheritance(ZuulTestCase):
2113 tenant_config_file = 'config/secret-inheritance/main.yaml'
2114
2115 def _getSecrets(self, job, pbtype):
2116 secrets = []
2117 build = self.getJobFromHistory(job)
2118 for pb in build.parameters[pbtype]:
2119 secrets.append(pb['secrets'])
2120 return secrets
2121
2122 def _checkTrustedSecrets(self):
2123 secret = {'longpassword': 'test-passwordtest-password',
2124 'password': 'test-password',
2125 'username': 'test-username'}
2126 self.assertEqual(
2127 self._getSecrets('trusted-secrets', 'playbooks'),
James E. Blair2f589fe2017-10-26 12:57:41 -07002128 [{'trusted-secret': secret}])
James E. Blairdf91ab32017-10-25 17:57:13 -07002129 self.assertEqual(
2130 self._getSecrets('trusted-secrets', 'pre_playbooks'), [])
2131 self.assertEqual(
2132 self._getSecrets('trusted-secrets', 'post_playbooks'), [])
2133
2134 self.assertEqual(
2135 self._getSecrets('trusted-secrets-trusted-child',
James E. Blair2f589fe2017-10-26 12:57:41 -07002136 'playbooks'), [{}])
James E. Blairdf91ab32017-10-25 17:57:13 -07002137 self.assertEqual(
2138 self._getSecrets('trusted-secrets-trusted-child',
2139 'pre_playbooks'), [])
2140 self.assertEqual(
2141 self._getSecrets('trusted-secrets-trusted-child',
2142 'post_playbooks'), [])
2143
2144 self.assertEqual(
2145 self._getSecrets('trusted-secrets-untrusted-child',
James E. Blair2f589fe2017-10-26 12:57:41 -07002146 'playbooks'), [{}])
James E. Blairdf91ab32017-10-25 17:57:13 -07002147 self.assertEqual(
2148 self._getSecrets('trusted-secrets-untrusted-child',
2149 'pre_playbooks'), [])
2150 self.assertEqual(
2151 self._getSecrets('trusted-secrets-untrusted-child',
2152 'post_playbooks'), [])
2153
2154 def _checkUntrustedSecrets(self):
2155 secret = {'longpassword': 'test-passwordtest-password',
2156 'password': 'test-password',
2157 'username': 'test-username'}
2158 self.assertEqual(
2159 self._getSecrets('untrusted-secrets', 'playbooks'),
James E. Blair2f589fe2017-10-26 12:57:41 -07002160 [{'untrusted-secret': secret}])
James E. Blairdf91ab32017-10-25 17:57:13 -07002161 self.assertEqual(
2162 self._getSecrets('untrusted-secrets', 'pre_playbooks'), [])
2163 self.assertEqual(
2164 self._getSecrets('untrusted-secrets', 'post_playbooks'), [])
2165
2166 self.assertEqual(
2167 self._getSecrets('untrusted-secrets-trusted-child',
James E. Blair2f589fe2017-10-26 12:57:41 -07002168 'playbooks'), [{}])
James E. Blairdf91ab32017-10-25 17:57:13 -07002169 self.assertEqual(
2170 self._getSecrets('untrusted-secrets-trusted-child',
2171 'pre_playbooks'), [])
2172 self.assertEqual(
2173 self._getSecrets('untrusted-secrets-trusted-child',
2174 'post_playbooks'), [])
2175
2176 self.assertEqual(
2177 self._getSecrets('untrusted-secrets-untrusted-child',
James E. Blair2f589fe2017-10-26 12:57:41 -07002178 'playbooks'), [{}])
James E. Blairdf91ab32017-10-25 17:57:13 -07002179 self.assertEqual(
2180 self._getSecrets('untrusted-secrets-untrusted-child',
2181 'pre_playbooks'), [])
2182 self.assertEqual(
2183 self._getSecrets('untrusted-secrets-untrusted-child',
2184 'post_playbooks'), [])
2185
2186 def test_trusted_secret_inheritance_check(self):
2187 A = self.fake_gerrit.addFakeChange('common-config', 'master', 'A')
2188 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2189 self.waitUntilSettled()
2190 self.assertHistory([
2191 dict(name='trusted-secrets', result='SUCCESS', changes='1,1'),
2192 dict(name='trusted-secrets-trusted-child',
2193 result='SUCCESS', changes='1,1'),
2194 dict(name='trusted-secrets-untrusted-child',
2195 result='SUCCESS', changes='1,1'),
2196 ], ordered=False)
2197
2198 self._checkTrustedSecrets()
2199
2200 def test_untrusted_secret_inheritance_gate(self):
2201 A = self.fake_gerrit.addFakeChange('common-config', 'master', 'A')
2202 A.addApproval('Code-Review', 2)
2203 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
2204 self.waitUntilSettled()
2205 self.assertHistory([
2206 dict(name='untrusted-secrets', result='SUCCESS', changes='1,1'),
2207 dict(name='untrusted-secrets-trusted-child',
2208 result='SUCCESS', changes='1,1'),
2209 dict(name='untrusted-secrets-untrusted-child',
2210 result='SUCCESS', changes='1,1'),
2211 ], ordered=False)
2212
2213 self._checkUntrustedSecrets()
2214
2215 def test_untrusted_secret_inheritance_check(self):
2216 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2217 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2218 self.waitUntilSettled()
2219 # This configuration tries to run untrusted secrets in an
2220 # non-post-review pipeline and should therefore run no jobs.
2221 self.assertHistory([])
2222
2223
James E. Blairdb089032017-08-15 13:42:12 -07002224class TestSecretLeaks(AnsibleZuulTestCase):
2225 tenant_config_file = 'config/secret-leaks/main.yaml'
2226
2227 def searchForContent(self, path, content):
2228 matches = []
2229 for (dirpath, dirnames, filenames) in os.walk(path):
2230 for filename in filenames:
2231 filepath = os.path.join(dirpath, filename)
2232 with open(filepath, 'rb') as f:
2233 if content in f.read():
2234 matches.append(filepath[len(path):])
2235 return matches
2236
2237 def _test_secret_file(self):
2238 # Or rather -- test that they *don't* leak.
2239 # Keep the jobdir around so we can inspect contents.
2240 self.executor_server.keep_jobdir = True
2241 conf = textwrap.dedent(
2242 """
2243 - project:
2244 name: org/project
2245 check:
2246 jobs:
2247 - secret-file
2248 """)
2249
2250 file_dict = {'.zuul.yaml': conf}
2251 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
2252 files=file_dict)
2253 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2254 self.waitUntilSettled()
2255 self.assertHistory([
2256 dict(name='secret-file', result='SUCCESS', changes='1,1'),
2257 ], ordered=False)
2258 matches = self.searchForContent(self.history[0].jobdir.root,
2259 b'test-password')
James E. Blaird6a71ca2017-08-18 14:15:05 -07002260 self.assertEqual(set(['/work/secret-file.txt']),
James E. Blairdb089032017-08-15 13:42:12 -07002261 set(matches))
2262
2263 def test_secret_file(self):
2264 self._test_secret_file()
2265
2266 def test_secret_file_verbose(self):
2267 # Output extra ansible info to exercise alternate logging code
2268 # paths.
2269 self.executor_server.verbose = True
2270 self._test_secret_file()
2271
2272 def _test_secret_file_fail(self):
2273 # Or rather -- test that they *don't* leak.
2274 # Keep the jobdir around so we can inspect contents.
2275 self.executor_server.keep_jobdir = True
2276 conf = textwrap.dedent(
2277 """
2278 - project:
2279 name: org/project
2280 check:
2281 jobs:
2282 - secret-file-fail
2283 """)
2284
2285 file_dict = {'.zuul.yaml': conf}
2286 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
2287 files=file_dict)
2288 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2289 self.waitUntilSettled()
2290 self.assertHistory([
2291 dict(name='secret-file-fail', result='FAILURE', changes='1,1'),
2292 ], ordered=False)
2293 matches = self.searchForContent(self.history[0].jobdir.root,
2294 b'test-password')
James E. Blaird6a71ca2017-08-18 14:15:05 -07002295 self.assertEqual(set(['/work/failure-file.txt']),
James E. Blairdb089032017-08-15 13:42:12 -07002296 set(matches))
2297
2298 def test_secret_file_fail(self):
2299 self._test_secret_file_fail()
2300
2301 def test_secret_file_fail_verbose(self):
2302 # Output extra ansible info to exercise alternate logging code
2303 # paths.
2304 self.executor_server.verbose = True
2305 self._test_secret_file_fail()
James E. Blaira00910c2017-08-23 09:15:04 -07002306
2307
2308class TestJobOutput(AnsibleZuulTestCase):
2309 tenant_config_file = 'config/job-output/main.yaml'
2310
2311 def _get_file(self, build, path):
2312 p = os.path.join(build.jobdir.root, path)
2313 with open(p) as f:
2314 return f.read()
2315
2316 def test_job_output(self):
Monty Taylor0e2489a2017-10-10 11:57:29 -05002317 # Verify that command standard output appears in the job output,
2318 # and that failures in the final playbook get logged.
James E. Blaira00910c2017-08-23 09:15:04 -07002319
2320 # This currently only verifies we receive output from
2321 # localhost. Notably, it does not verify we receive output
2322 # via zuul_console streaming.
2323 self.executor_server.keep_jobdir = True
2324 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2325 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2326 self.waitUntilSettled()
2327 self.assertHistory([
2328 dict(name='job-output', result='SUCCESS', changes='1,1'),
2329 ], ordered=False)
2330
2331 token = 'Standard output test %s' % (self.history[0].jobdir.src_root)
2332 j = json.loads(self._get_file(self.history[0],
2333 'work/logs/job-output.json'))
2334 self.assertEqual(token,
2335 j[0]['plays'][0]['tasks'][0]
2336 ['hosts']['localhost']['stdout'])
2337
2338 print(self._get_file(self.history[0],
2339 'work/logs/job-output.txt'))
2340 self.assertIn(token,
2341 self._get_file(self.history[0],
2342 'work/logs/job-output.txt'))
Monty Taylor0e2489a2017-10-10 11:57:29 -05002343
2344 def test_job_output_failure_log(self):
2345 logger = logging.getLogger('zuul.AnsibleJob')
2346 output = io.StringIO()
2347 logger.addHandler(logging.StreamHandler(output))
2348
2349 # Verify that a failure in the last post playbook emits the contents
2350 # of the json output to the log
2351 self.executor_server.keep_jobdir = True
2352 A = self.fake_gerrit.addFakeChange('org/project2', 'master', 'A')
2353 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2354 self.waitUntilSettled()
2355 self.assertHistory([
2356 dict(name='job-output-failure',
2357 result='POST_FAILURE', changes='1,1'),
2358 ], ordered=False)
2359
2360 token = 'Standard output test %s' % (self.history[0].jobdir.src_root)
2361 j = json.loads(self._get_file(self.history[0],
2362 'work/logs/job-output.json'))
2363 self.assertEqual(token,
2364 j[0]['plays'][0]['tasks'][0]
2365 ['hosts']['localhost']['stdout'])
2366
2367 print(self._get_file(self.history[0],
2368 'work/logs/job-output.json'))
2369 self.assertIn(token,
2370 self._get_file(self.history[0],
2371 'work/logs/job-output.txt'))
2372
2373 log_output = output.getvalue()
2374 self.assertIn('Final playbook failed', log_output)
2375 self.assertIn('Failure test', log_output)