blob: 2779e6e66bcd58bad0575c475dac4117efcde41b [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. Blair1edfd972017-12-01 15:54:24 -0800160class TestBranchTag(ZuulTestCase):
161 tenant_config_file = 'config/branch-tag/main.yaml'
162
163 def test_negative_branch_match(self):
164 # Test that a negative branch matcher works with implied branches.
165 event = self.fake_gerrit.addFakeTag('org/project', 'master', 'foo')
166 self.fake_gerrit.addEvent(event)
167 self.waitUntilSettled()
168 self.assertHistory([
169 dict(name='test-job', result='SUCCESS', ref='refs/tags/foo')])
170
171
James E. Blair9ab8db42017-12-01 15:12:04 -0800172class TestBranchNegative(ZuulTestCase):
173 tenant_config_file = 'config/branch-negative/main.yaml'
174
175 def test_negative_branch_match(self):
176 # Test that a negative branch matcher works with implied branches.
177 self.create_branch('org/project', 'stable/pike')
178 self.fake_gerrit.addEvent(
179 self.fake_gerrit.getFakeBranchCreatedEvent(
180 'org/project', 'stable/pike'))
181 self.waitUntilSettled()
182
183 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
184 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
185 self.waitUntilSettled()
186 B = self.fake_gerrit.addFakeChange('org/project', 'stable/pike', 'A')
187 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
188 self.waitUntilSettled()
189 self.assertHistory([
190 dict(name='test-job', result='SUCCESS', changes='1,1')])
191
192
James E. Blaire36d1a32017-11-28 13:33:38 -0800193class TestBranchTemplates(ZuulTestCase):
194 tenant_config_file = 'config/branch-templates/main.yaml'
195
196 def test_template_removal_from_branch(self):
197 # Test that a template can be removed from one branch but not
198 # another.
199 # This creates a new branch with a copy of the config in master
200 self.create_branch('puppet-integration', 'stable/newton')
201 self.create_branch('puppet-integration', 'stable/ocata')
202 self.create_branch('puppet-tripleo', 'stable/newton')
203 self.create_branch('puppet-tripleo', 'stable/ocata')
204 self.fake_gerrit.addEvent(
205 self.fake_gerrit.getFakeBranchCreatedEvent(
206 'puppet-integration', 'stable/newton'))
207 self.fake_gerrit.addEvent(
208 self.fake_gerrit.getFakeBranchCreatedEvent(
209 'puppet-integration', 'stable/ocata'))
210 self.fake_gerrit.addEvent(
211 self.fake_gerrit.getFakeBranchCreatedEvent(
212 'puppet-tripleo', 'stable/newton'))
213 self.fake_gerrit.addEvent(
214 self.fake_gerrit.getFakeBranchCreatedEvent(
215 'puppet-tripleo', 'stable/ocata'))
216 self.waitUntilSettled()
217
218 in_repo_conf = textwrap.dedent(
219 """
220 - project:
221 name: puppet-tripleo
222 check:
223 jobs:
224 - puppet-something
225 """)
226
227 file_dict = {'.zuul.yaml': in_repo_conf}
228 A = self.fake_gerrit.addFakeChange('puppet-tripleo', 'stable/newton',
229 'A', files=file_dict)
230 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
231 self.waitUntilSettled()
232 self.assertHistory([
233 dict(name='puppet-something', result='SUCCESS', changes='1,1')])
234
235 def test_template_change_on_branch(self):
236 # Test that the contents of a template can be changed on one
237 # branch without affecting another.
238
239 # This creates a new branch with a copy of the config in master
240 self.create_branch('puppet-integration', 'stable/newton')
241 self.create_branch('puppet-integration', 'stable/ocata')
242 self.create_branch('puppet-tripleo', 'stable/newton')
243 self.create_branch('puppet-tripleo', 'stable/ocata')
244 self.fake_gerrit.addEvent(
245 self.fake_gerrit.getFakeBranchCreatedEvent(
246 'puppet-integration', 'stable/newton'))
247 self.fake_gerrit.addEvent(
248 self.fake_gerrit.getFakeBranchCreatedEvent(
249 'puppet-integration', 'stable/ocata'))
250 self.fake_gerrit.addEvent(
251 self.fake_gerrit.getFakeBranchCreatedEvent(
252 'puppet-tripleo', 'stable/newton'))
253 self.fake_gerrit.addEvent(
254 self.fake_gerrit.getFakeBranchCreatedEvent(
255 'puppet-tripleo', 'stable/ocata'))
256 self.waitUntilSettled()
257
258 in_repo_conf = textwrap.dedent("""
259 - job:
260 name: puppet-unit-base
261 run: playbooks/run-unit-tests.yaml
262
263 - job:
264 name: puppet-unit-3.8
265 parent: puppet-unit-base
266 branches: ^(stable/(newton|ocata)).*$
267 vars:
268 puppet_gem_version: 3.8
269
270 - job:
271 name: puppet-something
272 run: playbooks/run-unit-tests.yaml
273
274 - project-template:
275 name: puppet-unit
276 check:
277 jobs:
278 - puppet-something
279
280 - project:
281 name: puppet-integration
282 templates:
283 - puppet-unit
284 """)
285
286 file_dict = {'.zuul.yaml': in_repo_conf}
287 A = self.fake_gerrit.addFakeChange('puppet-integration',
288 'stable/newton',
289 'A', files=file_dict)
290 B = self.fake_gerrit.addFakeChange('puppet-tripleo',
291 'stable/newton',
292 'B')
293 B.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
294 B.subject, A.data['id'])
295 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
296 self.waitUntilSettled()
297 self.assertHistory([
298 dict(name='puppet-something', result='SUCCESS',
299 changes='1,1 2,1')])
300
301
James E. Blair09998792017-10-15 18:02:18 -0700302class TestBranchVariants(ZuulTestCase):
303 tenant_config_file = 'config/branch-variants/main.yaml'
304
305 def test_branch_variants(self):
306 # Test branch variants of jobs with inheritance
307 self.executor_server.hold_jobs_in_build = True
308 # This creates a new branch with a copy of the config in master
309 self.create_branch('puppet-integration', 'stable')
310 self.fake_gerrit.addEvent(
311 self.fake_gerrit.getFakeBranchCreatedEvent(
312 'puppet-integration', 'stable'))
313 self.waitUntilSettled()
314
315 A = self.fake_gerrit.addFakeChange('puppet-integration', 'stable', 'A')
316 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
317 self.waitUntilSettled()
318
319 self.assertEqual(len(self.builds[0].parameters['pre_playbooks']), 3)
320 self.executor_server.hold_jobs_in_build = False
321 self.executor_server.release()
322 self.waitUntilSettled()
323
James E. Blairc9e77592017-10-24 09:25:23 -0700324 def test_branch_variants_reconfigure(self):
325 # Test branch variants of jobs with inheritance
326 self.executor_server.hold_jobs_in_build = True
327 # This creates a new branch with a copy of the config in master
328 self.create_branch('puppet-integration', 'stable')
329 self.fake_gerrit.addEvent(
330 self.fake_gerrit.getFakeBranchCreatedEvent(
331 'puppet-integration', 'stable'))
332 self.waitUntilSettled()
333
334 with open(os.path.join(FIXTURE_DIR,
335 'config/branch-variants/git/',
336 'puppet-integration/.zuul.yaml')) as f:
337 config = f.read()
338
339 # Push a change that triggers a dynamic reconfiguration
340 file_dict = {'.zuul.yaml': config}
341 A = self.fake_gerrit.addFakeChange('puppet-integration', 'master', 'A',
342 files=file_dict)
343 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
344 self.waitUntilSettled()
345
346 ipath = self.builds[0].parameters['zuul']['_inheritance_path']
347 for i in ipath:
348 self.log.debug("inheritance path %s", i)
349 self.assertEqual(len(ipath), 5)
350 self.executor_server.hold_jobs_in_build = False
351 self.executor_server.release()
352 self.waitUntilSettled()
353
James E. Blairc32a8352017-10-11 16:27:50 -0700354 def test_branch_variants_divergent(self):
355 # Test branches can diverge and become independent
356 self.executor_server.hold_jobs_in_build = True
357 # This creates a new branch with a copy of the config in master
358 self.create_branch('puppet-integration', 'stable')
359 self.fake_gerrit.addEvent(
360 self.fake_gerrit.getFakeBranchCreatedEvent(
361 'puppet-integration', 'stable'))
362 self.waitUntilSettled()
363
364 with open(os.path.join(FIXTURE_DIR,
365 'config/branch-variants/git/',
366 'puppet-integration/stable.zuul.yaml')) as f:
367 config = f.read()
368
369 file_dict = {'.zuul.yaml': config}
370 C = self.fake_gerrit.addFakeChange('puppet-integration', 'stable', 'C',
371 files=file_dict)
372 C.addApproval('Code-Review', 2)
373 self.fake_gerrit.addEvent(C.addApproval('Approved', 1))
374 self.waitUntilSettled()
375 self.fake_gerrit.addEvent(C.getChangeMergedEvent())
376 self.waitUntilSettled()
377
378 A = self.fake_gerrit.addFakeChange('puppet-integration', 'master', 'A')
379 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
380 self.waitUntilSettled()
381 B = self.fake_gerrit.addFakeChange('puppet-integration', 'stable', 'B')
382 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
383 self.waitUntilSettled()
384
385 self.assertEqual(self.builds[0].parameters['zuul']['jobtags'],
386 ['master'])
387
388 self.assertEqual(self.builds[1].parameters['zuul']['jobtags'],
389 ['stable'])
390
391 self.executor_server.hold_jobs_in_build = False
392 self.executor_server.release()
393 self.waitUntilSettled()
394
James E. Blair09998792017-10-15 18:02:18 -0700395
James E. Blair2a664502017-10-27 11:39:33 -0700396class TestCentralJobs(ZuulTestCase):
397 tenant_config_file = 'config/central-jobs/main.yaml'
398
399 def setUp(self):
400 super(TestCentralJobs, self).setUp()
401 self.create_branch('org/project', 'stable')
402 self.fake_gerrit.addEvent(
403 self.fake_gerrit.getFakeBranchCreatedEvent(
404 'org/project', 'stable'))
405 self.waitUntilSettled()
406
407 def _updateConfig(self, config, branch):
408 file_dict = {'.zuul.yaml': config}
409 C = self.fake_gerrit.addFakeChange('org/project', branch, 'C',
410 files=file_dict)
411 C.addApproval('Code-Review', 2)
412 self.fake_gerrit.addEvent(C.addApproval('Approved', 1))
413 self.waitUntilSettled()
414 self.fake_gerrit.addEvent(C.getChangeMergedEvent())
415 self.waitUntilSettled()
416
417 def _test_central_job_on_branch(self, branch, other_branch):
418 # Test that a job defined on a branchless repo only runs on
419 # the branch applied
420 config = textwrap.dedent(
421 """
422 - project:
423 name: org/project
424 check:
425 jobs:
426 - central-job
427 """)
428 self._updateConfig(config, branch)
429
430 A = self.fake_gerrit.addFakeChange('org/project', branch, 'A')
431 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
432 self.waitUntilSettled()
433
434 self.assertHistory([
435 dict(name='central-job', result='SUCCESS', changes='2,1')])
436
437 # No jobs should run for this change.
438 B = self.fake_gerrit.addFakeChange('org/project', other_branch, 'B')
439 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
440 self.waitUntilSettled()
441
442 self.assertHistory([
443 dict(name='central-job', result='SUCCESS', changes='2,1')])
444
445 def test_central_job_on_stable(self):
446 self._test_central_job_on_branch('master', 'stable')
447
448 def test_central_job_on_master(self):
449 self._test_central_job_on_branch('stable', 'master')
450
451 def _test_central_template_on_branch(self, branch, other_branch):
452 # Test that a project-template defined on a branchless repo
453 # only runs on the branch applied
454 config = textwrap.dedent(
455 """
456 - project:
457 name: org/project
458 templates: ['central-jobs']
459 """)
460 self._updateConfig(config, branch)
461
462 A = self.fake_gerrit.addFakeChange('org/project', branch, 'A')
463 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
464 self.waitUntilSettled()
465
466 self.assertHistory([
467 dict(name='central-job', result='SUCCESS', changes='2,1')])
468
469 # No jobs should run for this change.
470 B = self.fake_gerrit.addFakeChange('org/project', other_branch, 'B')
471 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
472 self.waitUntilSettled()
473
474 self.assertHistory([
475 dict(name='central-job', result='SUCCESS', changes='2,1')])
476
477 def test_central_template_on_stable(self):
478 self._test_central_template_on_branch('master', 'stable')
479
480 def test_central_template_on_master(self):
481 self._test_central_template_on_branch('stable', 'master')
482
483
James E. Blairff555742017-02-19 11:34:27 -0800484class TestInRepoConfig(ZuulTestCase):
James E. Blair83005782015-12-11 14:46:03 -0800485 # A temporary class to hold new tests while others are disabled
486
Tobias Henkelabf973e2017-07-28 10:07:34 +0200487 config_file = 'zuul-connections-gerrit-and-github.conf'
James E. Blair2a629ec2015-12-22 15:32:02 -0800488 tenant_config_file = 'config/in-repo/main.yaml'
James E. Blair83005782015-12-11 14:46:03 -0800489
James E. Blair83005782015-12-11 14:46:03 -0800490 def test_in_repo_config(self):
James E. Blair14abdf42015-12-09 16:11:53 -0800491 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
Tobias Henkelbf24fd12017-07-27 06:13:07 +0200492 A.addApproval('Code-Review', 2)
493 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
James E. Blair14abdf42015-12-09 16:11:53 -0800494 self.waitUntilSettled()
495 self.assertEqual(self.getJobFromHistory('project-test1').result,
496 'SUCCESS')
497 self.assertEqual(A.data['status'], 'MERGED')
498 self.assertEqual(A.reported, 2,
499 "A should report start and success")
500 self.assertIn('tenant-one-gate', A.messages[1],
501 "A should transit tenant-one gate")
James E. Blairb97ed802015-12-21 15:55:35 -0800502
James E. Blair3a098dd2017-10-04 14:37:29 -0700503 @skip("This test is useful, but not reliable")
504 def test_full_and_dynamic_reconfig(self):
505 self.executor_server.hold_jobs_in_build = True
506 in_repo_conf = textwrap.dedent(
507 """
508 - job:
509 name: project-test1
510
511 - project:
512 name: org/project
513 tenant-one-gate:
514 jobs:
515 - project-test1
516 """)
517
518 file_dict = {'.zuul.yaml': in_repo_conf}
519 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
520 files=file_dict)
521 A.addApproval('Code-Review', 2)
522 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
523 self.waitUntilSettled()
524 self.sched.reconfigure(self.config)
525 self.waitUntilSettled()
526
527 gc.collect()
528 pipelines = [obj for obj in gc.get_objects()
529 if isinstance(obj, zuul.model.Pipeline)]
530 self.assertEqual(len(pipelines), 4)
531
532 self.executor_server.hold_jobs_in_build = False
533 self.executor_server.release()
534 self.waitUntilSettled()
535
James E. Blair8b1dc3f2016-07-05 16:49:00 -0700536 def test_dynamic_config(self):
537 in_repo_conf = textwrap.dedent(
538 """
539 - job:
Tobias Henkelf02cf512017-07-21 22:55:34 +0200540 name: project-test1
541
542 - job:
James E. Blair8b1dc3f2016-07-05 16:49:00 -0700543 name: project-test2
James E. Blair2f589fe2017-10-26 12:57:41 -0700544 run: playbooks/project-test2.yaml
James E. Blair8b1dc3f2016-07-05 16:49:00 -0700545
Tobias Henkel53aa2ad2017-12-22 09:59:45 +0100546 - job:
547 name: project-test3
548 run: playbooks/project-test2.yaml
549
550 # add a job by the short project name
James E. Blair8b1dc3f2016-07-05 16:49:00 -0700551 - project:
552 name: org/project
553 tenant-one-gate:
554 jobs:
555 - project-test2
Tobias Henkel53aa2ad2017-12-22 09:59:45 +0100556
557 # add a job by the canonical project name
558 - project:
559 name: review.example.com/org/project
560 tenant-one-gate:
561 jobs:
562 - project-test3
James E. Blair8b1dc3f2016-07-05 16:49:00 -0700563 """)
564
James E. Blairc73c73a2017-01-20 15:15:15 -0800565 in_repo_playbook = textwrap.dedent(
566 """
567 - hosts: all
568 tasks: []
569 """)
570
571 file_dict = {'.zuul.yaml': in_repo_conf,
572 'playbooks/project-test2.yaml': in_repo_playbook}
James E. Blair8b1dc3f2016-07-05 16:49:00 -0700573 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
James E. Blairc73c73a2017-01-20 15:15:15 -0800574 files=file_dict)
Tobias Henkelbf24fd12017-07-27 06:13:07 +0200575 A.addApproval('Code-Review', 2)
576 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
James E. Blair8b1dc3f2016-07-05 16:49:00 -0700577 self.waitUntilSettled()
James E. Blair8b1dc3f2016-07-05 16:49:00 -0700578 self.assertEqual(A.data['status'], 'MERGED')
579 self.assertEqual(A.reported, 2,
580 "A should report start and success")
581 self.assertIn('tenant-one-gate', A.messages[1],
582 "A should transit tenant-one gate")
James E. Blair646322f2017-01-27 15:50:34 -0800583 self.assertHistory([
Tobias Henkel53aa2ad2017-12-22 09:59:45 +0100584 dict(name='project-test2', result='SUCCESS', changes='1,1'),
585 dict(name='project-test3', result='SUCCESS', changes='1,1'),
586 ], ordered=False)
James E. Blair646322f2017-01-27 15:50:34 -0800587
James E. Blairc2a5ed72017-02-20 14:12:01 -0500588 self.fake_gerrit.addEvent(A.getChangeMergedEvent())
James E. Blair7bbd7a32017-03-06 11:36:13 -0800589 self.waitUntilSettled()
James E. Blairc2a5ed72017-02-20 14:12:01 -0500590
James E. Blair646322f2017-01-27 15:50:34 -0800591 # Now that the config change is landed, it should be live for
592 # subsequent changes.
593 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
Tobias Henkelbf24fd12017-07-27 06:13:07 +0200594 B.addApproval('Code-Review', 2)
595 self.fake_gerrit.addEvent(B.addApproval('Approved', 1))
James E. Blair646322f2017-01-27 15:50:34 -0800596 self.waitUntilSettled()
597 self.assertEqual(self.getJobFromHistory('project-test2').result,
598 'SUCCESS')
599 self.assertHistory([
600 dict(name='project-test2', result='SUCCESS', changes='1,1'),
Tobias Henkel53aa2ad2017-12-22 09:59:45 +0100601 dict(name='project-test3', result='SUCCESS', changes='1,1'),
602 dict(name='project-test2', result='SUCCESS', changes='2,1'),
603 dict(name='project-test3', result='SUCCESS', changes='2,1'),
604 ], ordered=False)
James E. Blairc73c73a2017-01-20 15:15:15 -0800605
James E. Blair6bc10482017-10-20 11:28:53 -0700606 def test_dynamic_template(self):
James E. Blair2a664502017-10-27 11:39:33 -0700607 # Tests that a project can't update a template in another
608 # project.
James E. Blair6bc10482017-10-20 11:28:53 -0700609 in_repo_conf = textwrap.dedent(
610 """
611 - job:
612 name: project-test1
613
614 - project-template:
615 name: common-config-template
616 check:
617 jobs:
618 - project-test1
619
620 - project:
621 name: org/project
622 templates: [common-config-template]
623 """)
624
625 file_dict = {'.zuul.yaml': in_repo_conf}
626 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
627 files=file_dict)
628 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
629 self.waitUntilSettled()
James E. Blair2a664502017-10-27 11:39:33 -0700630
631 self.assertEqual(A.patchsets[0]['approvals'][0]['value'], "-1")
632 self.assertIn('Project template common-config-template '
633 'is already defined',
634 A.messages[0],
635 "A should have failed the check pipeline")
James E. Blair6bc10482017-10-20 11:28:53 -0700636
Tobias Henkelf02cf512017-07-21 22:55:34 +0200637 def test_dynamic_config_non_existing_job(self):
638 """Test that requesting a non existent job fails"""
639 in_repo_conf = textwrap.dedent(
640 """
641 - job:
642 name: project-test1
643
644 - project:
645 name: org/project
646 check:
647 jobs:
648 - non-existent-job
649 """)
650
651 in_repo_playbook = textwrap.dedent(
652 """
653 - hosts: all
654 tasks: []
655 """)
656
657 file_dict = {'.zuul.yaml': in_repo_conf,
658 'playbooks/project-test2.yaml': in_repo_playbook}
659 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
660 files=file_dict)
661 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
662 self.waitUntilSettled()
663 self.assertEqual(A.reported, 1,
664 "A should report failure")
665 self.assertEqual(A.patchsets[0]['approvals'][0]['value'], "-1")
666 self.assertIn('Job non-existent-job not defined', A.messages[0],
667 "A should have failed the check pipeline")
668 self.assertHistory([])
669
670 def test_dynamic_config_non_existing_job_in_template(self):
671 """Test that requesting a non existent job fails"""
672 in_repo_conf = textwrap.dedent(
673 """
674 - job:
675 name: project-test1
676
677 - project-template:
678 name: test-template
679 check:
680 jobs:
681 - non-existent-job
682
683 - project:
684 name: org/project
685 templates:
686 - test-template
687 """)
688
689 in_repo_playbook = textwrap.dedent(
690 """
691 - hosts: all
692 tasks: []
693 """)
694
695 file_dict = {'.zuul.yaml': in_repo_conf,
696 'playbooks/project-test2.yaml': in_repo_playbook}
697 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
698 files=file_dict)
699 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
700 self.waitUntilSettled()
701 self.assertEqual(A.reported, 1,
702 "A should report failure")
703 self.assertEqual(A.patchsets[0]['approvals'][0]['value'], "-1")
704 self.assertIn('Job non-existent-job not defined', A.messages[0],
705 "A should have failed the check pipeline")
706 self.assertHistory([])
707
Tobias Henkel0f714002017-06-30 23:30:52 +0200708 def test_dynamic_config_new_patchset(self):
709 self.executor_server.hold_jobs_in_build = True
710
711 tenant = self.sched.abide.tenants.get('tenant-one')
712 check_pipeline = tenant.layout.pipelines['check']
713
714 in_repo_conf = textwrap.dedent(
715 """
716 - job:
Tobias Henkelf02cf512017-07-21 22:55:34 +0200717 name: project-test1
James E. Blair2f589fe2017-10-26 12:57:41 -0700718 run: playbooks/project-test1.yaml
Tobias Henkelf02cf512017-07-21 22:55:34 +0200719
720 - job:
Tobias Henkel0f714002017-06-30 23:30:52 +0200721 name: project-test2
James E. Blair2f589fe2017-10-26 12:57:41 -0700722 run: playbooks/project-test2.yaml
Tobias Henkel0f714002017-06-30 23:30:52 +0200723
724 - project:
725 name: org/project
726 check:
727 jobs:
728 - project-test2
729 """)
730
731 in_repo_playbook = textwrap.dedent(
732 """
733 - hosts: all
734 tasks: []
735 """)
736
737 file_dict = {'.zuul.yaml': in_repo_conf,
738 'playbooks/project-test2.yaml': in_repo_playbook}
739 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
740 files=file_dict)
741 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
742 self.waitUntilSettled()
743
744 items = check_pipeline.getAllItems()
745 self.assertEqual(items[0].change.number, '1')
746 self.assertEqual(items[0].change.patchset, '1')
747 self.assertTrue(items[0].live)
748
749 in_repo_conf = textwrap.dedent(
750 """
751 - job:
Tobias Henkel0ce7ec62017-07-21 22:50:17 +0200752 name: project-test1
James E. Blair2f589fe2017-10-26 12:57:41 -0700753 run: playbooks/project-test1.yaml
Tobias Henkel0ce7ec62017-07-21 22:50:17 +0200754
755 - job:
Tobias Henkel0f714002017-06-30 23:30:52 +0200756 name: project-test2
James E. Blair2f589fe2017-10-26 12:57:41 -0700757 run: playbooks/project-test2.yaml
Tobias Henkel0f714002017-06-30 23:30:52 +0200758
759 - project:
760 name: org/project
761 check:
762 jobs:
763 - project-test1
764 - project-test2
765 """)
766 file_dict = {'.zuul.yaml': in_repo_conf,
767 'playbooks/project-test2.yaml': in_repo_playbook}
768
769 A.addPatchset(files=file_dict)
770 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(2))
771
772 self.waitUntilSettled()
773
774 items = check_pipeline.getAllItems()
775 self.assertEqual(items[0].change.number, '1')
776 self.assertEqual(items[0].change.patchset, '2')
777 self.assertTrue(items[0].live)
778
779 self.executor_server.hold_jobs_in_build = False
Tobias Henkel0ce7ec62017-07-21 22:50:17 +0200780 self.executor_server.release('project-test1')
781 self.waitUntilSettled()
Tobias Henkel0f714002017-06-30 23:30:52 +0200782 self.executor_server.release()
783 self.waitUntilSettled()
784
Tobias Henkel0ce7ec62017-07-21 22:50:17 +0200785 self.assertHistory([
786 dict(name='project-test2', result='ABORTED', changes='1,1'),
787 dict(name='project-test1', result='SUCCESS', changes='1,2'),
788 dict(name='project-test2', result='SUCCESS', changes='1,2')])
789
James E. Blairff555742017-02-19 11:34:27 -0800790 def test_in_repo_branch(self):
791 in_repo_conf = textwrap.dedent(
792 """
793 - job:
Tobias Henkelf02cf512017-07-21 22:55:34 +0200794 name: project-test1
795
796 - job:
James E. Blairff555742017-02-19 11:34:27 -0800797 name: project-test2
James E. Blair2f589fe2017-10-26 12:57:41 -0700798 run: playbooks/project-test2.yaml
James E. Blairff555742017-02-19 11:34:27 -0800799
800 - project:
801 name: org/project
802 tenant-one-gate:
803 jobs:
804 - project-test2
805 """)
806
807 in_repo_playbook = textwrap.dedent(
808 """
809 - hosts: all
810 tasks: []
811 """)
812
813 file_dict = {'.zuul.yaml': in_repo_conf,
814 'playbooks/project-test2.yaml': in_repo_playbook}
815 self.create_branch('org/project', 'stable')
James E. Blair72facdc2017-08-17 10:29:12 -0700816 self.fake_gerrit.addEvent(
817 self.fake_gerrit.getFakeBranchCreatedEvent(
818 'org/project', 'stable'))
James E. Blair6069f2b2017-09-26 16:34:11 -0700819 self.waitUntilSettled()
James E. Blairff555742017-02-19 11:34:27 -0800820 A = self.fake_gerrit.addFakeChange('org/project', 'stable', 'A',
821 files=file_dict)
Tobias Henkelbf24fd12017-07-27 06:13:07 +0200822 A.addApproval('Code-Review', 2)
823 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
James E. Blairff555742017-02-19 11:34:27 -0800824 self.waitUntilSettled()
825 self.assertEqual(A.data['status'], 'MERGED')
826 self.assertEqual(A.reported, 2,
827 "A should report start and success")
828 self.assertIn('tenant-one-gate', A.messages[1],
829 "A should transit tenant-one gate")
830 self.assertHistory([
831 dict(name='project-test2', result='SUCCESS', changes='1,1')])
832 self.fake_gerrit.addEvent(A.getChangeMergedEvent())
James E. Blair7bbd7a32017-03-06 11:36:13 -0800833 self.waitUntilSettled()
James E. Blairff555742017-02-19 11:34:27 -0800834
835 # The config change should not affect master.
836 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
Tobias Henkelbf24fd12017-07-27 06:13:07 +0200837 B.addApproval('Code-Review', 2)
838 self.fake_gerrit.addEvent(B.addApproval('Approved', 1))
James E. Blairff555742017-02-19 11:34:27 -0800839 self.waitUntilSettled()
840 self.assertHistory([
841 dict(name='project-test2', result='SUCCESS', changes='1,1'),
842 dict(name='project-test1', result='SUCCESS', changes='2,1')])
843
844 # The config change should be live for further changes on
845 # stable.
846 C = self.fake_gerrit.addFakeChange('org/project', 'stable', 'C')
Tobias Henkelbf24fd12017-07-27 06:13:07 +0200847 C.addApproval('Code-Review', 2)
848 self.fake_gerrit.addEvent(C.addApproval('Approved', 1))
James E. Blairff555742017-02-19 11:34:27 -0800849 self.waitUntilSettled()
850 self.assertHistory([
851 dict(name='project-test2', result='SUCCESS', changes='1,1'),
852 dict(name='project-test1', result='SUCCESS', changes='2,1'),
853 dict(name='project-test2', result='SUCCESS', changes='3,1')])
854
James E. Blaira5a12492017-05-03 11:40:48 -0700855 def test_crd_dynamic_config_branch(self):
856 # Test that we can create a job in one repo and be able to use
857 # it from a different branch on a different repo.
858
859 self.create_branch('org/project1', 'stable')
James E. Blair72facdc2017-08-17 10:29:12 -0700860 self.fake_gerrit.addEvent(
861 self.fake_gerrit.getFakeBranchCreatedEvent(
862 'org/project1', 'stable'))
James E. Blaira5a12492017-05-03 11:40:48 -0700863
864 in_repo_conf = textwrap.dedent(
865 """
866 - job:
Tobias Henkelf02cf512017-07-21 22:55:34 +0200867 name: project-test1
868
869 - job:
James E. Blaira5a12492017-05-03 11:40:48 -0700870 name: project-test2
James E. Blair2f589fe2017-10-26 12:57:41 -0700871 run: playbooks/project-test2.yaml
James E. Blaira5a12492017-05-03 11:40:48 -0700872
873 - project:
874 name: org/project
875 check:
876 jobs:
877 - project-test2
878 """)
879
880 in_repo_playbook = textwrap.dedent(
881 """
882 - hosts: all
883 tasks: []
884 """)
885
886 file_dict = {'.zuul.yaml': in_repo_conf,
887 'playbooks/project-test2.yaml': in_repo_playbook}
888 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
889 files=file_dict)
890
891 second_repo_conf = textwrap.dedent(
892 """
893 - project:
894 name: org/project1
895 check:
896 jobs:
897 - project-test2
898 """)
899
900 second_file_dict = {'.zuul.yaml': second_repo_conf}
901 B = self.fake_gerrit.addFakeChange('org/project1', 'stable', 'B',
902 files=second_file_dict)
903 B.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
904 B.subject, A.data['id'])
905
906 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
907 self.waitUntilSettled()
908 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
909 self.waitUntilSettled()
910
911 self.assertEqual(A.reported, 1, "A should report")
912 self.assertHistory([
913 dict(name='project-test2', result='SUCCESS', changes='1,1'),
914 dict(name='project-test2', result='SUCCESS', changes='1,1 2,1'),
915 ])
916
James E. Blair97043882017-09-06 15:51:17 -0700917 def test_yaml_list_error(self):
918 in_repo_conf = textwrap.dedent(
919 """
920 job: foo
921 """)
922
923 file_dict = {'.zuul.yaml': in_repo_conf}
924 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
925 files=file_dict)
926 A.addApproval('Code-Review', 2)
927 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
928 self.waitUntilSettled()
929
930 self.assertEqual(A.data['status'], 'NEW')
931 self.assertEqual(A.reported, 1,
932 "A should report failure")
933 self.assertIn('not a list', A.messages[0],
934 "A should have a syntax error reported")
935
936 def test_yaml_dict_error(self):
937 in_repo_conf = textwrap.dedent(
938 """
939 - job
940 """)
941
942 file_dict = {'.zuul.yaml': in_repo_conf}
943 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
944 files=file_dict)
945 A.addApproval('Code-Review', 2)
946 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
947 self.waitUntilSettled()
948
949 self.assertEqual(A.data['status'], 'NEW')
950 self.assertEqual(A.reported, 1,
951 "A should report failure")
952 self.assertIn('not a dictionary', A.messages[0],
953 "A should have a syntax error reported")
954
James E. Blairec953e12017-12-11 11:56:18 -0800955 def test_yaml_duplicate_key_error(self):
956 in_repo_conf = textwrap.dedent(
957 """
958 - job:
959 name: foo
960 name: bar
961 """)
962
963 file_dict = {'.zuul.yaml': in_repo_conf}
964 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
965 files=file_dict)
966 A.addApproval('Code-Review', 2)
967 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
968 self.waitUntilSettled()
969
970 self.assertEqual(A.data['status'], 'NEW')
971 self.assertEqual(A.reported, 1,
972 "A should report failure")
973 self.assertIn('appears more than once', A.messages[0],
974 "A should have a syntax error reported")
975
James E. Blair97043882017-09-06 15:51:17 -0700976 def test_yaml_key_error(self):
977 in_repo_conf = textwrap.dedent(
978 """
979 - job:
980 name: project-test2
981 """)
982
983 file_dict = {'.zuul.yaml': in_repo_conf}
984 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
985 files=file_dict)
986 A.addApproval('Code-Review', 2)
987 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
988 self.waitUntilSettled()
989
990 self.assertEqual(A.data['status'], 'NEW')
991 self.assertEqual(A.reported, 1,
992 "A should report failure")
993 self.assertIn('has more than one key', A.messages[0],
994 "A should have a syntax error reported")
995
996 def test_yaml_unknown_error(self):
997 in_repo_conf = textwrap.dedent(
998 """
999 - foobar:
1000 foo: bar
1001 """)
1002
1003 file_dict = {'.zuul.yaml': in_repo_conf}
1004 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
1005 files=file_dict)
1006 A.addApproval('Code-Review', 2)
1007 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
1008 self.waitUntilSettled()
1009
1010 self.assertEqual(A.data['status'], 'NEW')
1011 self.assertEqual(A.reported, 1,
1012 "A should report failure")
1013 self.assertIn('not recognized', A.messages[0],
1014 "A should have a syntax error reported")
1015
James E. Blair149b69c2017-03-02 10:48:16 -08001016 def test_untrusted_syntax_error(self):
James E. Blaire53250c2017-03-01 14:34:36 -08001017 in_repo_conf = textwrap.dedent(
1018 """
1019 - job:
1020 name: project-test2
1021 foo: error
1022 """)
1023
1024 file_dict = {'.zuul.yaml': in_repo_conf}
1025 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
1026 files=file_dict)
Tobias Henkelbf24fd12017-07-27 06:13:07 +02001027 A.addApproval('Code-Review', 2)
1028 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
James E. Blaire53250c2017-03-01 14:34:36 -08001029 self.waitUntilSettled()
1030
1031 self.assertEqual(A.data['status'], 'NEW')
Tobias Henkel9842bd72017-05-16 13:40:03 +02001032 self.assertEqual(A.reported, 1,
1033 "A should report failure")
1034 self.assertIn('syntax error', A.messages[0],
James E. Blaire53250c2017-03-01 14:34:36 -08001035 "A should have a syntax error reported")
1036
James E. Blair149b69c2017-03-02 10:48:16 -08001037 def test_trusted_syntax_error(self):
1038 in_repo_conf = textwrap.dedent(
1039 """
1040 - job:
1041 name: project-test2
1042 foo: error
1043 """)
1044
1045 file_dict = {'zuul.yaml': in_repo_conf}
1046 A = self.fake_gerrit.addFakeChange('common-config', 'master', 'A',
1047 files=file_dict)
Tobias Henkelbf24fd12017-07-27 06:13:07 +02001048 A.addApproval('Code-Review', 2)
1049 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
James E. Blair149b69c2017-03-02 10:48:16 -08001050 self.waitUntilSettled()
1051
1052 self.assertEqual(A.data['status'], 'NEW')
Tobias Henkel9842bd72017-05-16 13:40:03 +02001053 self.assertEqual(A.reported, 1,
1054 "A should report failure")
1055 self.assertIn('syntax error', A.messages[0],
James E. Blair149b69c2017-03-02 10:48:16 -08001056 "A should have a syntax error reported")
1057
James E. Blair6f140c72017-03-03 10:32:07 -08001058 def test_untrusted_yaml_error(self):
1059 in_repo_conf = textwrap.dedent(
1060 """
1061 - job:
1062 foo: error
1063 """)
1064
1065 file_dict = {'.zuul.yaml': in_repo_conf}
1066 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
1067 files=file_dict)
Tobias Henkelbf24fd12017-07-27 06:13:07 +02001068 A.addApproval('Code-Review', 2)
1069 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
James E. Blair6f140c72017-03-03 10:32:07 -08001070 self.waitUntilSettled()
1071
1072 self.assertEqual(A.data['status'], 'NEW')
Tobias Henkel9842bd72017-05-16 13:40:03 +02001073 self.assertEqual(A.reported, 1,
1074 "A should report failure")
1075 self.assertIn('syntax error', A.messages[0],
James E. Blair6f140c72017-03-03 10:32:07 -08001076 "A should have a syntax error reported")
1077
James E. Blairdb04e6a2017-05-03 14:49:36 -07001078 def test_untrusted_shadow_error(self):
1079 in_repo_conf = textwrap.dedent(
1080 """
1081 - job:
1082 name: common-config-test
1083 """)
1084
1085 file_dict = {'.zuul.yaml': in_repo_conf}
1086 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
1087 files=file_dict)
Tobias Henkelbf24fd12017-07-27 06:13:07 +02001088 A.addApproval('Code-Review', 2)
1089 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
James E. Blairdb04e6a2017-05-03 14:49:36 -07001090 self.waitUntilSettled()
1091
1092 self.assertEqual(A.data['status'], 'NEW')
Tobias Henkel9842bd72017-05-16 13:40:03 +02001093 self.assertEqual(A.reported, 1,
1094 "A should report failure")
1095 self.assertIn('not permitted to shadow', A.messages[0],
James E. Blairdb04e6a2017-05-03 14:49:36 -07001096 "A should have a syntax error reported")
1097
James E. Blaird5656ad2017-06-02 14:29:41 -07001098 def test_untrusted_pipeline_error(self):
1099 in_repo_conf = textwrap.dedent(
1100 """
1101 - pipeline:
1102 name: test
1103 """)
1104
1105 file_dict = {'.zuul.yaml': in_repo_conf}
1106 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
1107 files=file_dict)
Tobias Henkelbf24fd12017-07-27 06:13:07 +02001108 A.addApproval('Code-Review', 2)
1109 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
James E. Blaird5656ad2017-06-02 14:29:41 -07001110 self.waitUntilSettled()
1111
1112 self.assertEqual(A.data['status'], 'NEW')
1113 self.assertEqual(A.reported, 1,
1114 "A should report failure")
1115 self.assertIn('Pipelines may not be defined', A.messages[0],
1116 "A should have a syntax error reported")
1117
1118 def test_untrusted_project_error(self):
1119 in_repo_conf = textwrap.dedent(
1120 """
1121 - project:
1122 name: org/project1
1123 """)
1124
1125 file_dict = {'.zuul.yaml': in_repo_conf}
1126 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
1127 files=file_dict)
Tobias Henkelbf24fd12017-07-27 06:13:07 +02001128 A.addApproval('Code-Review', 2)
1129 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
James E. Blaird5656ad2017-06-02 14:29:41 -07001130 self.waitUntilSettled()
1131
1132 self.assertEqual(A.data['status'], 'NEW')
1133 self.assertEqual(A.reported, 1,
1134 "A should report failure")
1135 self.assertIn('the only project definition permitted', A.messages[0],
1136 "A should have a syntax error reported")
1137
James E. Blairf03173b2017-10-10 10:46:43 -07001138 def test_untrusted_depends_on_trusted(self):
1139 with open(os.path.join(FIXTURE_DIR,
1140 'config/in-repo/git/',
1141 'common-config/zuul.yaml')) as f:
1142 common_config = f.read()
1143
1144 common_config += textwrap.dedent(
1145 """
1146 - job:
1147 name: project-test9
1148 """)
1149
1150 file_dict = {'zuul.yaml': common_config}
1151 A = self.fake_gerrit.addFakeChange('common-config', 'master', 'A',
1152 files=file_dict)
1153 in_repo_conf = textwrap.dedent(
1154 """
1155 - job:
1156 name: project-test1
1157 - project:
1158 name: org/project
1159 check:
1160 jobs:
1161 - project-test9
1162 """)
1163
1164 file_dict = {'zuul.yaml': in_repo_conf}
1165 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B',
1166 files=file_dict)
1167 B.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
1168 B.subject, A.data['id'])
1169 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
1170 self.waitUntilSettled()
1171
1172 self.assertEqual(B.data['status'], 'NEW')
1173 self.assertEqual(B.reported, 1,
1174 "B should report failure")
1175 self.assertIn('depends on a change to a config project',
1176 B.messages[0],
1177 "A should have a syntax error reported")
1178
James E. Blaire64b0e42017-06-08 11:23:34 -07001179 def test_duplicate_node_error(self):
1180 in_repo_conf = textwrap.dedent(
1181 """
1182 - nodeset:
1183 name: duplicate
1184 nodes:
1185 - name: compute
James E. Blair16d96a02017-06-08 11:32:56 -07001186 label: foo
James E. Blaire64b0e42017-06-08 11:23:34 -07001187 - name: compute
James E. Blair16d96a02017-06-08 11:32:56 -07001188 label: foo
James E. Blaire64b0e42017-06-08 11:23:34 -07001189 """)
1190
1191 file_dict = {'.zuul.yaml': in_repo_conf}
1192 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
1193 files=file_dict)
Tobias Henkelbf24fd12017-07-27 06:13:07 +02001194 A.addApproval('Code-Review', 2)
1195 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
James E. Blaire64b0e42017-06-08 11:23:34 -07001196 self.waitUntilSettled()
1197
1198 self.assertEqual(A.data['status'], 'NEW')
1199 self.assertEqual(A.reported, 1,
1200 "A should report failure")
1201 self.assertIn('appears multiple times', A.messages[0],
1202 "A should have a syntax error reported")
1203
1204 def test_duplicate_group_error(self):
1205 in_repo_conf = textwrap.dedent(
1206 """
1207 - nodeset:
1208 name: duplicate
1209 nodes:
1210 - name: compute
James E. Blair16d96a02017-06-08 11:32:56 -07001211 label: foo
James E. Blaire64b0e42017-06-08 11:23:34 -07001212 groups:
1213 - name: group
1214 nodes: compute
1215 - name: group
1216 nodes: compute
1217 """)
1218
1219 file_dict = {'.zuul.yaml': in_repo_conf}
1220 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
1221 files=file_dict)
Tobias Henkelbf24fd12017-07-27 06:13:07 +02001222 A.addApproval('Code-Review', 2)
1223 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
James E. Blaire64b0e42017-06-08 11:23:34 -07001224 self.waitUntilSettled()
1225
1226 self.assertEqual(A.data['status'], 'NEW')
1227 self.assertEqual(A.reported, 1,
1228 "A should report failure")
1229 self.assertIn('appears multiple times', A.messages[0],
1230 "A should have a syntax error reported")
1231
James E. Blair4ae399f2017-09-20 17:15:09 -07001232 def test_secret_not_found_error(self):
1233 in_repo_conf = textwrap.dedent(
1234 """
1235 - job:
1236 name: test
1237 secrets: does-not-exist
1238 """)
1239
1240 file_dict = {'.zuul.yaml': in_repo_conf}
1241 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
1242 files=file_dict)
1243 A.addApproval('Code-Review', 2)
1244 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
1245 self.waitUntilSettled()
1246
1247 self.assertEqual(A.data['status'], 'NEW')
1248 self.assertEqual(A.reported, 1,
1249 "A should report failure")
1250 self.assertIn('secret "does-not-exist" was not found', A.messages[0],
1251 "A should have a syntax error reported")
1252
1253 def test_nodeset_not_found_error(self):
1254 in_repo_conf = textwrap.dedent(
1255 """
1256 - job:
1257 name: test
1258 nodeset: does-not-exist
1259 """)
1260
1261 file_dict = {'.zuul.yaml': in_repo_conf}
1262 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
1263 files=file_dict)
1264 A.addApproval('Code-Review', 2)
1265 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
1266 self.waitUntilSettled()
1267
1268 self.assertEqual(A.data['status'], 'NEW')
1269 self.assertEqual(A.reported, 1,
1270 "A should report failure")
1271 self.assertIn('nodeset "does-not-exist" was not found', A.messages[0],
1272 "A should have a syntax error reported")
1273
James E. Blair89e25eb2017-09-26 09:11:31 -07001274 def test_template_not_found_error(self):
1275 in_repo_conf = textwrap.dedent(
1276 """
1277 - job:
1278 name: project-test1
1279 - project:
1280 name: org/project
1281 templates:
1282 - does-not-exist
1283 """)
1284
1285 file_dict = {'.zuul.yaml': in_repo_conf}
1286 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
1287 files=file_dict)
1288 A.addApproval('Code-Review', 2)
1289 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
1290 self.waitUntilSettled()
1291
1292 self.assertEqual(A.data['status'], 'NEW')
1293 self.assertEqual(A.reported, 1,
1294 "A should report failure")
1295 self.assertIn('project template "does-not-exist" was not found',
1296 A.messages[0],
1297 "A should have a syntax error reported")
1298
Monty Taylor8be3c0c2017-10-06 10:37:37 -05001299 def test_job_list_in_project_template_not_dict_error(self):
1300 in_repo_conf = textwrap.dedent(
1301 """
1302 - job:
1303 name: project-test1
1304 - project-template:
1305 name: some-jobs
1306 check:
1307 jobs:
1308 - project-test1:
1309 - required-projects:
1310 org/project2
1311 """)
1312
1313 file_dict = {'.zuul.yaml': in_repo_conf}
1314 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
1315 files=file_dict)
1316 A.addApproval('Code-Review', 2)
1317 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
1318 self.waitUntilSettled()
1319
1320 self.assertEqual(A.data['status'], 'NEW')
1321 self.assertEqual(A.reported, 1,
1322 "A should report failure")
1323 self.assertIn('expected str for dictionary value',
1324 A.messages[0], "A should have a syntax error reported")
1325
1326 def test_job_list_in_project_not_dict_error(self):
1327 in_repo_conf = textwrap.dedent(
1328 """
1329 - job:
1330 name: project-test1
1331 - project:
1332 name: org/project1
1333 check:
1334 jobs:
1335 - project-test1:
1336 - required-projects:
1337 org/project2
1338 """)
1339
1340 file_dict = {'.zuul.yaml': in_repo_conf}
1341 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
1342 files=file_dict)
1343 A.addApproval('Code-Review', 2)
1344 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
1345 self.waitUntilSettled()
1346
1347 self.assertEqual(A.data['status'], 'NEW')
1348 self.assertEqual(A.reported, 1,
1349 "A should report failure")
1350 self.assertIn('expected str for dictionary value',
1351 A.messages[0], "A should have a syntax error reported")
1352
James E. Blair1235f142017-10-07 09:11:43 -07001353 def test_project_template(self):
1354 # Tests that a project template is not modified when used, and
1355 # can therefore be used in subsequent reconfigurations.
1356 in_repo_conf = textwrap.dedent(
1357 """
1358 - job:
1359 name: project-test1
James E. Blair2f589fe2017-10-26 12:57:41 -07001360 run: playbooks/project-test1.yaml
James E. Blair1235f142017-10-07 09:11:43 -07001361 - project-template:
1362 name: some-jobs
1363 tenant-one-gate:
1364 jobs:
1365 - project-test1:
1366 required-projects:
1367 - org/project1
1368 - project:
1369 name: org/project
1370 templates:
1371 - some-jobs
1372 """)
1373
1374 file_dict = {'.zuul.yaml': in_repo_conf}
1375 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
1376 files=file_dict)
1377 A.addApproval('Code-Review', 2)
1378 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
1379 self.waitUntilSettled()
1380 self.assertEqual(A.data['status'], 'MERGED')
1381 self.fake_gerrit.addEvent(A.getChangeMergedEvent())
1382 self.waitUntilSettled()
1383 in_repo_conf = textwrap.dedent(
1384 """
1385 - project:
1386 name: org/project1
1387 templates:
1388 - some-jobs
1389 """)
1390 file_dict = {'.zuul.yaml': in_repo_conf}
1391 B = self.fake_gerrit.addFakeChange('org/project1', 'master', 'B',
1392 files=file_dict)
1393 B.addApproval('Code-Review', 2)
1394 self.fake_gerrit.addEvent(B.addApproval('Approved', 1))
1395 self.waitUntilSettled()
1396 self.assertEqual(B.data['status'], 'MERGED')
1397
James E. Blairbccdfcf2017-10-07 13:37:26 -07001398 def test_job_remove_add(self):
1399 # Tests that a job can be removed from one repo and added in another.
1400 # First, remove the current config for project1 since it
1401 # references the job we want to remove.
1402 file_dict = {'.zuul.yaml': None}
1403 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A',
1404 files=file_dict)
1405 A.setMerged()
1406 self.fake_gerrit.addEvent(A.getChangeMergedEvent())
1407 self.waitUntilSettled()
1408 # Then propose a change to delete the job from one repo...
1409 file_dict = {'.zuul.yaml': None}
1410 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B',
1411 files=file_dict)
1412 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
1413 self.waitUntilSettled()
1414 # ...and a second that depends on it that adds it to another repo.
1415 in_repo_conf = textwrap.dedent(
1416 """
1417 - job:
1418 name: project-test1
James E. Blair2f589fe2017-10-26 12:57:41 -07001419 run: playbooks/project-test1.yaml
James E. Blairbccdfcf2017-10-07 13:37:26 -07001420
1421 - project:
1422 name: org/project1
1423 check:
1424 jobs:
1425 - project-test1
1426 """)
1427 in_repo_playbook = textwrap.dedent(
1428 """
1429 - hosts: all
1430 tasks: []
1431 """)
1432 file_dict = {'.zuul.yaml': in_repo_conf,
1433 'playbooks/project-test1.yaml': in_repo_playbook}
1434 C = self.fake_gerrit.addFakeChange('org/project1', 'master', 'C',
1435 files=file_dict,
1436 parent='refs/changes/1/1/1')
1437 C.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
1438 C.subject, B.data['id'])
1439 self.fake_gerrit.addEvent(C.getPatchsetCreatedEvent(1))
1440 self.waitUntilSettled()
1441 self.assertHistory([
1442 dict(name='project-test1', result='SUCCESS', changes='2,1 3,1'),
1443 ], ordered=False)
1444
James E. Blair09f9ffe2017-07-11 15:30:25 -07001445 def test_multi_repo(self):
1446 downstream_repo_conf = textwrap.dedent(
1447 """
1448 - project:
1449 name: org/project1
1450 tenant-one-gate:
1451 jobs:
1452 - project-test1
1453
1454 - job:
1455 name: project1-test1
1456 parent: project-test1
1457 """)
1458
1459 file_dict = {'.zuul.yaml': downstream_repo_conf}
1460 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A',
1461 files=file_dict)
Tobias Henkelbf24fd12017-07-27 06:13:07 +02001462 A.addApproval('Code-Review', 2)
1463 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
James E. Blair09f9ffe2017-07-11 15:30:25 -07001464 self.waitUntilSettled()
1465
1466 self.assertEqual(A.data['status'], 'MERGED')
1467 self.fake_gerrit.addEvent(A.getChangeMergedEvent())
1468 self.waitUntilSettled()
1469
1470 upstream_repo_conf = textwrap.dedent(
1471 """
1472 - job:
1473 name: project-test1
James E. Blair2f589fe2017-10-26 12:57:41 -07001474 run: playbooks/project-test1.yaml
James E. Blair09f9ffe2017-07-11 15:30:25 -07001475
1476 - job:
1477 name: project-test2
1478
1479 - project:
1480 name: org/project
1481 tenant-one-gate:
1482 jobs:
1483 - project-test1
1484 """)
1485
1486 file_dict = {'.zuul.yaml': upstream_repo_conf}
1487 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B',
1488 files=file_dict)
Tobias Henkelbf24fd12017-07-27 06:13:07 +02001489 B.addApproval('Code-Review', 2)
1490 self.fake_gerrit.addEvent(B.addApproval('Approved', 1))
James E. Blair09f9ffe2017-07-11 15:30:25 -07001491 self.waitUntilSettled()
1492
1493 self.assertEqual(B.data['status'], 'MERGED')
1494 self.fake_gerrit.addEvent(B.getChangeMergedEvent())
1495 self.waitUntilSettled()
1496
1497 tenant = self.sched.abide.tenants.get('tenant-one')
1498 # Ensure the latest change is reflected in the config; if it
1499 # isn't this will raise an exception.
1500 tenant.layout.getJob('project-test2')
1501
James E. Blair332636e2017-09-05 10:14:35 -07001502 def test_pipeline_error(self):
1503 with open(os.path.join(FIXTURE_DIR,
1504 'config/in-repo/git/',
1505 'common-config/zuul.yaml')) as f:
1506 base_common_config = f.read()
1507
1508 in_repo_conf_A = textwrap.dedent(
1509 """
1510 - pipeline:
1511 name: periodic
1512 foo: error
1513 """)
1514
1515 file_dict = {'zuul.yaml': None,
1516 'zuul.d/main.yaml': base_common_config,
1517 'zuul.d/test1.yaml': in_repo_conf_A}
1518 A = self.fake_gerrit.addFakeChange('common-config', 'master', 'A',
1519 files=file_dict)
1520 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
1521 self.waitUntilSettled()
1522 self.assertEqual(A.reported, 1,
1523 "A should report failure")
1524 self.assertIn('syntax error',
1525 A.messages[0],
1526 "A should have an error reported")
1527
1528 def test_change_series_error(self):
1529 with open(os.path.join(FIXTURE_DIR,
1530 'config/in-repo/git/',
1531 'common-config/zuul.yaml')) as f:
1532 base_common_config = f.read()
1533
1534 in_repo_conf_A = textwrap.dedent(
1535 """
1536 - pipeline:
1537 name: periodic
1538 foo: error
1539 """)
1540
1541 file_dict = {'zuul.yaml': None,
1542 'zuul.d/main.yaml': base_common_config,
1543 'zuul.d/test1.yaml': in_repo_conf_A}
1544 A = self.fake_gerrit.addFakeChange('common-config', 'master', 'A',
1545 files=file_dict)
1546
1547 in_repo_conf_B = textwrap.dedent(
1548 """
1549 - job:
1550 name: project-test2
1551 foo: error
1552 """)
1553
1554 file_dict = {'zuul.yaml': None,
1555 'zuul.d/main.yaml': base_common_config,
1556 'zuul.d/test1.yaml': in_repo_conf_A,
1557 'zuul.d/test2.yaml': in_repo_conf_B}
1558 B = self.fake_gerrit.addFakeChange('common-config', 'master', 'B',
1559 files=file_dict)
1560 B.setDependsOn(A, 1)
1561 C = self.fake_gerrit.addFakeChange('common-config', 'master', 'C')
1562 C.setDependsOn(B, 1)
1563 self.fake_gerrit.addEvent(C.getPatchsetCreatedEvent(1))
1564 self.waitUntilSettled()
1565
1566 self.assertEqual(C.reported, 1,
1567 "C should report failure")
1568 self.assertIn('depends on a change that failed to merge',
1569 C.messages[0],
1570 "C should have an error reported")
1571
James E. Blair1ef8f7c2017-12-13 17:18:34 -08001572 def test_pipeline_debug(self):
1573 in_repo_conf = textwrap.dedent(
1574 """
1575 - job:
1576 name: project-test1
1577 run: playbooks/project-test1.yaml
1578 - project:
1579 name: org/project
1580 check:
1581 debug: True
1582 jobs:
1583 - project-test1
1584 """)
1585
1586 file_dict = {'.zuul.yaml': in_repo_conf}
1587 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
1588 files=file_dict)
1589 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
1590 self.waitUntilSettled()
1591
1592 self.assertEqual(A.data['status'], 'NEW')
1593 self.assertEqual(A.reported, 1,
1594 "A should report success")
1595 self.assertIn('Debug information:',
1596 A.messages[0], "A should have debug info")
1597
James E. Blairc73c73a2017-01-20 15:15:15 -08001598
James E. Blairc9455002017-09-06 09:22:19 -07001599class TestInRepoJoin(ZuulTestCase):
1600 # In this config, org/project is not a member of any pipelines, so
1601 # that we may test the changes that cause it to join them.
1602
1603 tenant_config_file = 'config/in-repo-join/main.yaml'
1604
1605 def test_dynamic_dependent_pipeline(self):
1606 # Test dynamically adding a project to a
1607 # dependent pipeline for the first time
1608 self.executor_server.hold_jobs_in_build = True
1609
1610 tenant = self.sched.abide.tenants.get('tenant-one')
1611 gate_pipeline = tenant.layout.pipelines['gate']
1612
1613 in_repo_conf = textwrap.dedent(
1614 """
1615 - job:
1616 name: project-test1
James E. Blair2f589fe2017-10-26 12:57:41 -07001617 run: playbooks/project-test1.yaml
James E. Blairc9455002017-09-06 09:22:19 -07001618
1619 - job:
1620 name: project-test2
James E. Blair2f589fe2017-10-26 12:57:41 -07001621 run: playbooks/project-test2.yaml
James E. Blairc9455002017-09-06 09:22:19 -07001622
1623 - project:
1624 name: org/project
1625 gate:
1626 jobs:
1627 - project-test2
1628 """)
1629
1630 in_repo_playbook = textwrap.dedent(
1631 """
1632 - hosts: all
1633 tasks: []
1634 """)
1635
1636 file_dict = {'.zuul.yaml': in_repo_conf,
1637 'playbooks/project-test2.yaml': in_repo_playbook}
1638 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
1639 files=file_dict)
1640 A.addApproval('Code-Review', 2)
1641 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
1642 self.waitUntilSettled()
1643
1644 items = gate_pipeline.getAllItems()
1645 self.assertEqual(items[0].change.number, '1')
1646 self.assertEqual(items[0].change.patchset, '1')
1647 self.assertTrue(items[0].live)
1648
1649 self.executor_server.hold_jobs_in_build = False
1650 self.executor_server.release()
1651 self.waitUntilSettled()
1652
1653 # Make sure the dynamic queue got cleaned up
1654 self.assertEqual(gate_pipeline.queues, [])
1655
1656 def test_dynamic_dependent_pipeline_failure(self):
1657 # Test that a change behind a failing change adding a project
1658 # to a dependent pipeline is dequeued.
1659 self.executor_server.hold_jobs_in_build = True
1660
1661 in_repo_conf = textwrap.dedent(
1662 """
1663 - job:
1664 name: project-test1
James E. Blair2f589fe2017-10-26 12:57:41 -07001665 run: playbooks/project-test1.yaml
James E. Blairc9455002017-09-06 09:22:19 -07001666
1667 - project:
1668 name: org/project
1669 gate:
1670 jobs:
1671 - project-test1
1672 """)
1673
1674 file_dict = {'.zuul.yaml': in_repo_conf}
1675 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
1676 files=file_dict)
1677 self.executor_server.failJob('project-test1', A)
1678 A.addApproval('Code-Review', 2)
1679 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
1680 self.waitUntilSettled()
1681
1682 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
1683 B.addApproval('Code-Review', 2)
1684 self.fake_gerrit.addEvent(B.addApproval('Approved', 1))
1685 self.waitUntilSettled()
1686
James E. Blair3490c5d2017-09-07 08:33:23 -07001687 self.orderedRelease()
James E. Blairc9455002017-09-06 09:22:19 -07001688 self.waitUntilSettled()
1689 self.assertEqual(A.reported, 2,
1690 "A should report start and failure")
1691 self.assertEqual(A.data['status'], 'NEW')
1692 self.assertEqual(B.reported, 1,
1693 "B should report start")
1694 self.assertHistory([
1695 dict(name='project-test1', result='FAILURE', changes='1,1'),
James E. Blair3490c5d2017-09-07 08:33:23 -07001696 dict(name='project-test1', result='ABORTED', changes='1,1 2,1'),
James E. Blairc9455002017-09-06 09:22:19 -07001697 ], ordered=False)
1698
James E. Blair0af198f2017-09-06 09:52:35 -07001699 def test_dynamic_dependent_pipeline_absent(self):
1700 # Test that a series of dependent changes don't report merge
1701 # failures to a pipeline they aren't in.
1702 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1703 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
1704 B.setDependsOn(A, 1)
1705
1706 A.addApproval('Code-Review', 2)
1707 A.addApproval('Approved', 1)
1708 B.addApproval('Code-Review', 2)
1709 self.fake_gerrit.addEvent(B.addApproval('Approved', 1))
1710 self.waitUntilSettled()
1711 self.assertEqual(A.reported, 0,
1712 "A should not report")
1713 self.assertEqual(A.data['status'], 'NEW')
1714 self.assertEqual(B.reported, 0,
1715 "B should not report")
1716 self.assertEqual(B.data['status'], 'NEW')
1717 self.assertHistory([])
1718
James E. Blairc9455002017-09-06 09:22:19 -07001719
James E. Blairc73c73a2017-01-20 15:15:15 -08001720class TestAnsible(AnsibleZuulTestCase):
1721 # A temporary class to hold new tests while others are disabled
1722
1723 tenant_config_file = 'config/ansible/main.yaml'
1724
1725 def test_playbook(self):
Jamie Lennox7655b552017-03-17 12:33:38 +11001726 # Keep the jobdir around so we can inspect contents if an
1727 # assert fails.
1728 self.executor_server.keep_jobdir = True
1729 # Output extra ansible info so we might see errors.
1730 self.executor_server.verbose = True
1731 # Add a site variables file, used by check-vars
1732 path = os.path.join(FIXTURE_DIR, 'config', 'ansible',
1733 'variables.yaml')
1734 self.config.set('executor', 'variables', path)
James E. Blairc73c73a2017-01-20 15:15:15 -08001735 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1736 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
1737 self.waitUntilSettled()
Tobias Henkel077f2f32017-05-30 20:16:46 +02001738 build_timeout = self.getJobFromHistory('timeout')
Jamie Lennox7655b552017-03-17 12:33:38 +11001739 with self.jobLog(build_timeout):
1740 self.assertEqual(build_timeout.result, 'TIMED_OUT')
Tobias Henkel077f2f32017-05-30 20:16:46 +02001741 build_faillocal = self.getJobFromHistory('faillocal')
Jamie Lennox7655b552017-03-17 12:33:38 +11001742 with self.jobLog(build_faillocal):
1743 self.assertEqual(build_faillocal.result, 'FAILURE')
Tobias Henkel077f2f32017-05-30 20:16:46 +02001744 build_failpost = self.getJobFromHistory('failpost')
Jamie Lennox7655b552017-03-17 12:33:38 +11001745 with self.jobLog(build_failpost):
1746 self.assertEqual(build_failpost.result, 'POST_FAILURE')
Tobias Henkel077f2f32017-05-30 20:16:46 +02001747 build_check_vars = self.getJobFromHistory('check-vars')
Jamie Lennox7655b552017-03-17 12:33:38 +11001748 with self.jobLog(build_check_vars):
1749 self.assertEqual(build_check_vars.result, 'SUCCESS')
Monty Tayloraff8b402017-08-16 18:40:41 -05001750 build_check_secret_names = self.getJobFromHistory('check-secret-names')
1751 with self.jobLog(build_check_secret_names):
1752 self.assertEqual(build_check_secret_names.result, 'SUCCESS')
Tobias Henkel077f2f32017-05-30 20:16:46 +02001753 build_hello = self.getJobFromHistory('hello-world')
Jamie Lennox7655b552017-03-17 12:33:38 +11001754 with self.jobLog(build_hello):
1755 self.assertEqual(build_hello.result, 'SUCCESS')
Tobias Henkel077f2f32017-05-30 20:16:46 +02001756 build_python27 = self.getJobFromHistory('python27')
Jamie Lennox7655b552017-03-17 12:33:38 +11001757 with self.jobLog(build_python27):
1758 self.assertEqual(build_python27.result, 'SUCCESS')
1759 flag_path = os.path.join(self.test_root,
1760 build_python27.uuid + '.flag')
1761 self.assertTrue(os.path.exists(flag_path))
1762 copied_path = os.path.join(self.test_root, build_python27.uuid +
1763 '.copied')
1764 self.assertTrue(os.path.exists(copied_path))
1765 failed_path = os.path.join(self.test_root, build_python27.uuid +
1766 '.failed')
1767 self.assertFalse(os.path.exists(failed_path))
1768 pre_flag_path = os.path.join(self.test_root, build_python27.uuid +
1769 '.pre.flag')
1770 self.assertTrue(os.path.exists(pre_flag_path))
1771 post_flag_path = os.path.join(self.test_root, build_python27.uuid +
1772 '.post.flag')
1773 self.assertTrue(os.path.exists(post_flag_path))
1774 bare_role_flag_path = os.path.join(self.test_root,
1775 build_python27.uuid +
1776 '.bare-role.flag')
1777 self.assertTrue(os.path.exists(bare_role_flag_path))
1778 secrets_path = os.path.join(self.test_root,
1779 build_python27.uuid + '.secrets')
1780 with open(secrets_path) as f:
1781 self.assertEqual(f.read(), "test-username test-password")
James E. Blairb9c0d772017-03-03 14:34:49 -08001782
Jamie Lennox7655b552017-03-17 12:33:38 +11001783 msg = A.messages[0]
1784 success = "{} https://success.example.com/zuul-logs/{}"
1785 fail = "{} https://failure.example.com/zuul-logs/{}"
1786 self.assertIn(success.format("python27", build_python27.uuid), msg)
1787 self.assertIn(fail.format("faillocal", build_faillocal.uuid), msg)
1788 self.assertIn(success.format("check-vars",
1789 build_check_vars.uuid), msg)
1790 self.assertIn(success.format("hello-world", build_hello.uuid), msg)
1791 self.assertIn(fail.format("timeout", build_timeout.uuid), msg)
1792 self.assertIn(fail.format("failpost", build_failpost.uuid), msg)
Tobias Henkel077f2f32017-05-30 20:16:46 +02001793
James E. Blairabbaa6f2017-04-06 16:11:44 -07001794 def _add_job(self, job_name):
1795 conf = textwrap.dedent(
1796 """
1797 - job:
1798 name: %s
James E. Blair2f589fe2017-10-26 12:57:41 -07001799 run: playbooks/%s.yaml
James E. Blairabbaa6f2017-04-06 16:11:44 -07001800
1801 - project:
1802 name: org/plugin-project
1803 check:
1804 jobs:
1805 - %s
James E. Blair2f589fe2017-10-26 12:57:41 -07001806 """ % (job_name, job_name, job_name))
James E. Blairabbaa6f2017-04-06 16:11:44 -07001807
1808 file_dict = {'.zuul.yaml': conf}
1809 A = self.fake_gerrit.addFakeChange('org/plugin-project', 'master', 'A',
1810 files=file_dict)
1811 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
1812 self.waitUntilSettled()
1813
1814 def test_plugins(self):
1815 # Keep the jobdir around so we can inspect contents if an
1816 # assert fails.
1817 self.executor_server.keep_jobdir = True
1818 # Output extra ansible info so we might see errors.
1819 self.executor_server.verbose = True
1820
1821 count = 0
1822 plugin_tests = [
1823 ('passwd', 'FAILURE'),
1824 ('cartesian', 'SUCCESS'),
1825 ('consul_kv', 'FAILURE'),
1826 ('credstash', 'FAILURE'),
1827 ('csvfile_good', 'SUCCESS'),
1828 ('csvfile_bad', 'FAILURE'),
Monty Taylor93ad2212017-08-02 14:59:50 -05001829 ('uri_bad_path', 'FAILURE'),
1830 ('uri_bad_scheme', 'FAILURE'),
Monty Taylor788a40e2017-08-02 16:14:05 -05001831 ('block_local_override', 'FAILURE'),
Monty Taylor8da768f2017-08-31 14:15:35 -05001832 ('file_local_good', 'SUCCESS'),
1833 ('file_local_bad', 'FAILURE'),
James E. Blairabbaa6f2017-04-06 16:11:44 -07001834 ]
1835 for job_name, result in plugin_tests:
1836 count += 1
1837 self._add_job(job_name)
1838
1839 job = self.getJobFromHistory(job_name)
1840 with self.jobLog(job):
1841 self.assertEqual(count, len(self.history))
1842 build = self.history[-1]
1843 self.assertEqual(build.result, result)
1844
1845 # TODOv3(jeblair): parse the ansible output and verify we're
1846 # getting the exception we expect.
1847
James E. Blairb9c0d772017-03-03 14:34:49 -08001848
James E. Blaira4d4eef2017-06-30 14:49:17 -07001849class TestPrePlaybooks(AnsibleZuulTestCase):
1850 # A temporary class to hold new tests while others are disabled
1851
1852 tenant_config_file = 'config/pre-playbook/main.yaml'
1853
1854 def test_pre_playbook_fail(self):
1855 # Test that we run the post playbooks (but not the actual
1856 # playbook) when a pre-playbook fails.
1857 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1858 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
1859 self.waitUntilSettled()
1860 build = self.getJobFromHistory('python27')
1861 self.assertIsNone(build.result)
1862 self.assertIn('RETRY_LIMIT', A.messages[0])
1863 flag_path = os.path.join(self.test_root, build.uuid +
1864 '.main.flag')
1865 self.assertFalse(os.path.exists(flag_path))
1866 pre_flag_path = os.path.join(self.test_root, build.uuid +
1867 '.pre.flag')
1868 self.assertFalse(os.path.exists(pre_flag_path))
1869 post_flag_path = os.path.join(self.test_root, build.uuid +
1870 '.post.flag')
James E. Blair21037782017-07-19 11:56:55 -07001871 self.assertTrue(os.path.exists(post_flag_path),
1872 "The file %s should exist" % post_flag_path)
James E. Blaira4d4eef2017-06-30 14:49:17 -07001873
1874
James E. Blairbacbb882017-10-17 09:48:23 -07001875class TestPostPlaybooks(AnsibleZuulTestCase):
1876 tenant_config_file = 'config/post-playbook/main.yaml'
1877
1878 def test_post_playbook_abort(self):
1879 # Test that when we abort a job in the post playbook, that we
1880 # don't send back POST_FAILURE.
1881 self.executor_server.verbose = True
1882 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1883 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
1884
1885 while not len(self.builds):
1886 time.sleep(0.1)
1887 build = self.builds[0]
1888
1889 post_start = os.path.join(self.test_root, build.uuid +
1890 '.post_start.flag')
1891 start = time.time()
1892 while time.time() < start + 90:
1893 if os.path.exists(post_start):
1894 break
1895 time.sleep(0.1)
1896 # The post playbook has started, abort the job
1897 self.fake_gerrit.addEvent(A.getChangeAbandonedEvent())
1898 self.waitUntilSettled()
1899
1900 build = self.getJobFromHistory('python27')
1901 self.assertEqual('ABORTED', build.result)
1902
1903 post_end = os.path.join(self.test_root, build.uuid +
1904 '.post_end.flag')
1905 self.assertTrue(os.path.exists(post_start))
1906 self.assertFalse(os.path.exists(post_end))
1907
1908
James E. Blairb9c0d772017-03-03 14:34:49 -08001909class TestBrokenConfig(ZuulTestCase):
1910 # Test that we get an appropriate syntax error if we start with a
1911 # broken config.
1912
1913 tenant_config_file = 'config/broken/main.yaml'
1914
1915 def setUp(self):
1916 with testtools.ExpectedException(
1917 zuul.configloader.ConfigurationSyntaxError,
1918 "\nZuul encountered a syntax error"):
1919 super(TestBrokenConfig, self).setUp()
1920
1921 def test_broken_config_on_startup(self):
1922 pass
Ricardo Carrillo Cruz22994f92016-12-02 11:41:58 +00001923
1924
1925class TestProjectKeys(ZuulTestCase):
1926 # Test that we can generate project keys
1927
1928 # Normally the test infrastructure copies a static key in place
1929 # for each project before starting tests. This saves time because
1930 # Zuul's automatic key-generation on startup can be slow. To make
1931 # sure we exercise that code, in this test we allow Zuul to create
1932 # keys for the project on startup.
1933 create_project_keys = True
Tobias Henkelabf973e2017-07-28 10:07:34 +02001934 config_file = 'zuul-connections-gerrit-and-github.conf'
Ricardo Carrillo Cruz22994f92016-12-02 11:41:58 +00001935 tenant_config_file = 'config/in-repo/main.yaml'
1936
1937 def test_key_generation(self):
1938 key_root = os.path.join(self.state_root, 'keys')
1939 private_key_file = os.path.join(key_root, 'gerrit/org/project.pem')
1940 # Make sure that a proper key was created on startup
1941 with open(private_key_file, "rb") as f:
James E. Blairbf1a4f22017-03-17 10:59:37 -07001942 private_key, public_key = \
1943 encryption.deserialize_rsa_keypair(f.read())
Ricardo Carrillo Cruz22994f92016-12-02 11:41:58 +00001944
1945 with open(os.path.join(FIXTURE_DIR, 'private.pem')) as i:
1946 fixture_private_key = i.read()
1947
1948 # Make sure that we didn't just end up with the static fixture
1949 # key
1950 self.assertNotEqual(fixture_private_key, private_key)
1951
1952 # Make sure it's the right length
1953 self.assertEqual(4096, private_key.key_size)
James E. Blairbce76932017-05-04 10:03:15 -07001954
1955
James E. Blairbb94dfa2017-07-11 07:45:19 -07001956class RoleTestCase(ZuulTestCase):
James E. Blair1b27f6a2017-07-14 14:09:07 -07001957 def _assertRolePath(self, build, playbook, content):
1958 path = os.path.join(self.test_root, build.uuid,
1959 'ansible', playbook, 'ansible.cfg')
1960 roles_paths = []
1961 with open(path) as f:
1962 for line in f:
1963 if line.startswith('roles_path'):
1964 roles_paths.append(line)
1965 print(roles_paths)
1966 if content:
1967 self.assertEqual(len(roles_paths), 1,
1968 "Should have one roles_path line in %s" %
1969 (playbook,))
1970 self.assertIn(content, roles_paths[0])
1971 else:
1972 self.assertEqual(len(roles_paths), 0,
1973 "Should have no roles_path line in %s" %
1974 (playbook,))
1975
James E. Blairbb94dfa2017-07-11 07:45:19 -07001976
1977class TestRoles(RoleTestCase):
1978 tenant_config_file = 'config/roles/main.yaml'
1979
James E. Blairbce76932017-05-04 10:03:15 -07001980 def test_role(self):
1981 # This exercises a proposed change to a role being checked out
1982 # and used.
1983 A = self.fake_gerrit.addFakeChange('bare-role', 'master', 'A')
1984 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1985 B.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
1986 B.subject, A.data['id'])
1987 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
1988 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
1989 self.waitUntilSettled()
1990 self.assertHistory([
1991 dict(name='project-test', result='SUCCESS', changes='1,1 2,1'),
1992 ])
James E. Blair6459db12017-06-29 14:57:20 -07001993
James E. Blair1b27f6a2017-07-14 14:09:07 -07001994 def test_role_inheritance(self):
1995 self.executor_server.hold_jobs_in_build = True
1996 conf = textwrap.dedent(
1997 """
1998 - job:
1999 name: parent
2000 roles:
2001 - zuul: bare-role
Ian Wienand548c43c2017-12-05 14:16:32 +11002002 pre-run: playbooks/parent-pre.yaml
2003 post-run: playbooks/parent-post.yaml
James E. Blair1b27f6a2017-07-14 14:09:07 -07002004
2005 - job:
2006 name: project-test
2007 parent: parent
James E. Blair2f589fe2017-10-26 12:57:41 -07002008 run: playbooks/project-test.yaml
James E. Blair1b27f6a2017-07-14 14:09:07 -07002009 roles:
2010 - zuul: org/project
2011
2012 - project:
2013 name: org/project
2014 check:
2015 jobs:
2016 - project-test
2017 """)
2018
2019 file_dict = {'.zuul.yaml': conf}
2020 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
2021 files=file_dict)
2022 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2023 self.waitUntilSettled()
2024
2025 self.assertEqual(len(self.builds), 1)
2026 build = self.getBuildByName('project-test')
2027 self._assertRolePath(build, 'pre_playbook_0', 'role_0')
2028 self._assertRolePath(build, 'playbook_0', 'role_0')
2029 self._assertRolePath(build, 'playbook_0', 'role_1')
2030 self._assertRolePath(build, 'post_playbook_0', 'role_0')
2031
2032 self.executor_server.hold_jobs_in_build = False
2033 self.executor_server.release()
2034 self.waitUntilSettled()
2035
2036 self.assertHistory([
2037 dict(name='project-test', result='SUCCESS', changes='1,1'),
2038 ])
2039
James E. Blair6f699732017-07-18 14:19:11 -07002040 def test_role_error(self):
2041 conf = textwrap.dedent(
2042 """
2043 - job:
2044 name: project-test
James E. Blair2f589fe2017-10-26 12:57:41 -07002045 run: playbooks/project-test.yaml
James E. Blair6f699732017-07-18 14:19:11 -07002046 roles:
2047 - zuul: common-config
2048
2049 - project:
2050 name: org/project
2051 check:
2052 jobs:
2053 - project-test
2054 """)
2055
2056 file_dict = {'.zuul.yaml': conf}
2057 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
2058 files=file_dict)
2059 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2060 self.waitUntilSettled()
2061 self.assertIn(
2062 '- project-test project-test : ERROR Unable to find role',
2063 A.messages[-1])
2064
James E. Blair6459db12017-06-29 14:57:20 -07002065
James E. Blairbb94dfa2017-07-11 07:45:19 -07002066class TestImplicitRoles(RoleTestCase):
2067 tenant_config_file = 'config/implicit-roles/main.yaml'
2068
2069 def test_missing_roles(self):
2070 # Test implicit and explicit roles for a project which does
2071 # not have roles. The implicit role should be silently
2072 # ignored since the project doesn't supply roles, but if a
2073 # user declares an explicit role, it should error.
2074 self.executor_server.hold_jobs_in_build = True
2075 A = self.fake_gerrit.addFakeChange('org/norole-project', 'master', 'A')
2076 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2077 self.waitUntilSettled()
2078
2079 self.assertEqual(len(self.builds), 2)
2080 build = self.getBuildByName('implicit-role-fail')
2081 self._assertRolePath(build, 'playbook_0', None)
2082
2083 self.executor_server.hold_jobs_in_build = False
2084 self.executor_server.release()
2085 self.waitUntilSettled()
2086 # The retry_limit doesn't get recorded
2087 self.assertHistory([
2088 dict(name='implicit-role-fail', result='SUCCESS', changes='1,1'),
2089 ])
2090
2091 def test_roles(self):
2092 # Test implicit and explicit roles for a project which does
2093 # have roles. In both cases, we should end up with the role
2094 # in the path. In the explicit case, ensure we end up with
2095 # the name we specified.
2096 self.executor_server.hold_jobs_in_build = True
2097 A = self.fake_gerrit.addFakeChange('org/role-project', 'master', 'A')
2098 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2099 self.waitUntilSettled()
2100
2101 self.assertEqual(len(self.builds), 2)
2102 build = self.getBuildByName('implicit-role-ok')
2103 self._assertRolePath(build, 'playbook_0', 'role_0')
2104
2105 build = self.getBuildByName('explicit-role-ok')
2106 self._assertRolePath(build, 'playbook_0', 'role_0')
2107
2108 self.executor_server.hold_jobs_in_build = False
2109 self.executor_server.release()
2110 self.waitUntilSettled()
2111 self.assertHistory([
2112 dict(name='implicit-role-ok', result='SUCCESS', changes='1,1'),
2113 dict(name='explicit-role-ok', result='SUCCESS', changes='1,1'),
2114 ], ordered=False)
2115
2116
James E. Blair6459db12017-06-29 14:57:20 -07002117class TestShadow(ZuulTestCase):
2118 tenant_config_file = 'config/shadow/main.yaml'
2119
2120 def test_shadow(self):
2121 # Test that a repo is allowed to shadow another's job definitions.
2122 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2123 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2124 self.waitUntilSettled()
2125 self.assertHistory([
2126 dict(name='test1', result='SUCCESS', changes='1,1'),
2127 dict(name='test2', result='SUCCESS', changes='1,1'),
James E. Blairadafa6c2017-07-12 08:50:56 -07002128 ], ordered=False)
James E. Blair196f61a2017-06-30 15:42:29 -07002129
2130
2131class TestDataReturn(AnsibleZuulTestCase):
2132 tenant_config_file = 'config/data-return/main.yaml'
2133
2134 def test_data_return(self):
James E. Blair196f61a2017-06-30 15:42:29 -07002135 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2136 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2137 self.waitUntilSettled()
2138 self.assertHistory([
2139 dict(name='data-return', result='SUCCESS', changes='1,1'),
James E. Blair88e79c02017-07-07 13:36:54 -07002140 dict(name='data-return-relative', result='SUCCESS', changes='1,1'),
James E. Blair698703c2017-09-15 20:58:30 -06002141 dict(name='child', result='SUCCESS', changes='1,1'),
James E. Blair88e79c02017-07-07 13:36:54 -07002142 ], ordered=False)
2143 self.assertIn('- data-return http://example.com/test/log/url/',
2144 A.messages[-1])
2145 self.assertIn('- data-return-relative '
2146 'http://example.com/test/log/url/docs/index.html',
James E. Blair196f61a2017-06-30 15:42:29 -07002147 A.messages[-1])
Clint Byrumdc8a0902017-07-20 16:36:27 -07002148
2149
2150class TestDiskAccounting(AnsibleZuulTestCase):
2151 config_file = 'zuul-disk-accounting.conf'
2152 tenant_config_file = 'config/disk-accountant/main.yaml'
2153
2154 def test_disk_accountant_kills_job(self):
2155 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2156 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2157 self.waitUntilSettled()
2158 self.assertHistory([
2159 dict(name='dd-big-empty-file', result='ABORTED', changes='1,1')])
Tristan Cacqueray82f864b2017-08-01 05:54:42 +00002160
2161
2162class TestMaxNodesPerJob(AnsibleZuulTestCase):
2163 tenant_config_file = 'config/multi-tenant/main.yaml'
2164
Tristan Cacquerayc98bff72017-09-10 15:25:26 +00002165 def test_max_timeout_exceeded(self):
Tristan Cacqueray82f864b2017-08-01 05:54:42 +00002166 in_repo_conf = textwrap.dedent(
2167 """
2168 - job:
2169 name: test-job
James E. Blair7e3e6882017-09-20 15:47:13 -07002170 nodeset:
2171 nodes:
2172 - name: node01
2173 label: fake
2174 - name: node02
2175 label: fake
2176 - name: node03
2177 label: fake
2178 - name: node04
2179 label: fake
2180 - name: node05
2181 label: fake
2182 - name: node06
2183 label: fake
Tristan Cacqueray82f864b2017-08-01 05:54:42 +00002184 """)
2185 file_dict = {'.zuul.yaml': in_repo_conf}
2186 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A',
2187 files=file_dict)
2188 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2189 self.waitUntilSettled()
2190 self.assertIn('The job "test-job" exceeds tenant max-nodes-per-job 5.',
2191 A.messages[0], "A should fail because of nodes limit")
2192
2193 B = self.fake_gerrit.addFakeChange('org/project2', 'master', 'A',
2194 files=file_dict)
2195 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
2196 self.waitUntilSettled()
2197 self.assertNotIn("exceeds tenant max-nodes", B.messages[0],
2198 "B should not fail because of nodes limit")
James E. Blair2bab6e72017-08-07 09:52:45 -07002199
2200
Tristan Cacquerayc98bff72017-09-10 15:25:26 +00002201class TestMaxTimeout(AnsibleZuulTestCase):
2202 tenant_config_file = 'config/multi-tenant/main.yaml'
2203
2204 def test_max_nodes_reached(self):
2205 in_repo_conf = textwrap.dedent(
2206 """
2207 - job:
2208 name: test-job
2209 timeout: 3600
2210 """)
2211 file_dict = {'.zuul.yaml': in_repo_conf}
2212 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A',
2213 files=file_dict)
2214 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2215 self.waitUntilSettled()
2216 self.assertIn('The job "test-job" exceeds tenant max-job-timeout',
2217 A.messages[0], "A should fail because of timeout limit")
2218
2219 B = self.fake_gerrit.addFakeChange('org/project2', 'master', 'A',
2220 files=file_dict)
2221 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
2222 self.waitUntilSettled()
2223 self.assertNotIn("exceeds tenant max-job-timeout", B.messages[0],
2224 "B should not fail because of timeout limit")
2225
2226
James E. Blair7edc25f2017-10-26 10:47:14 -07002227class TestPragma(ZuulTestCase):
2228 tenant_config_file = 'config/pragma/main.yaml'
2229
2230 def test_no_pragma(self):
2231 self.create_branch('org/project', 'stable')
2232 with open(os.path.join(FIXTURE_DIR,
2233 'config/pragma/git/',
2234 'org_project/nopragma.yaml')) as f:
2235 config = f.read()
2236 file_dict = {'.zuul.yaml': config}
2237 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
2238 files=file_dict)
2239 A.addApproval('Code-Review', 2)
2240 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
2241 self.waitUntilSettled()
2242 self.fake_gerrit.addEvent(A.getChangeMergedEvent())
2243 self.waitUntilSettled()
2244
2245 # This is an untrusted repo with 2 branches, so it should have
2246 # an implied branch matcher for the job.
2247 tenant = self.sched.abide.tenants.get('tenant-one')
2248 jobs = tenant.layout.getJobs('test-job')
2249 self.assertEqual(len(jobs), 1)
2250 for job in tenant.layout.getJobs('test-job'):
2251 self.assertIsNotNone(job.branch_matcher)
2252
2253 def test_pragma(self):
2254 self.create_branch('org/project', 'stable')
2255 with open(os.path.join(FIXTURE_DIR,
2256 'config/pragma/git/',
2257 'org_project/pragma.yaml')) as f:
2258 config = f.read()
2259 file_dict = {'.zuul.yaml': config}
2260 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
2261 files=file_dict)
2262 A.addApproval('Code-Review', 2)
2263 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
2264 self.waitUntilSettled()
2265 self.fake_gerrit.addEvent(A.getChangeMergedEvent())
2266 self.waitUntilSettled()
2267
2268 # This is an untrusted repo with 2 branches, so it would
2269 # normally have an implied branch matcher, but our pragma
2270 # overrides it.
2271 tenant = self.sched.abide.tenants.get('tenant-one')
2272 jobs = tenant.layout.getJobs('test-job')
2273 self.assertEqual(len(jobs), 1)
2274 for job in tenant.layout.getJobs('test-job'):
2275 self.assertIsNone(job.branch_matcher)
2276
2277
James E. Blair37c3d8c2017-12-13 15:06:11 -08002278class TestPragmaMultibranch(ZuulTestCase):
2279 tenant_config_file = 'config/pragma-multibranch/main.yaml'
2280
2281 def test_no_branch_matchers(self):
2282 self.create_branch('org/project1', 'stable/pike')
2283 self.create_branch('org/project2', 'stable/jewel')
2284 self.fake_gerrit.addEvent(
2285 self.fake_gerrit.getFakeBranchCreatedEvent(
2286 'org/project1', 'stable/pike'))
2287 self.fake_gerrit.addEvent(
2288 self.fake_gerrit.getFakeBranchCreatedEvent(
2289 'org/project2', 'stable/jewel'))
2290 self.waitUntilSettled()
2291 # We want the jobs defined on the stable/pike branch of
2292 # project1 to apply to the stable/jewel branch of project2.
2293
2294 # First, without the pragma line, the jobs should not run
2295 # because in project1 they have branch matchers for pike, so
2296 # they will not match a jewel change.
2297 B = self.fake_gerrit.addFakeChange('org/project2', 'stable/jewel', 'B')
2298 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
2299 self.waitUntilSettled()
2300 self.assertHistory([])
2301
2302 # Add a pragma line to disable implied branch matchers in
2303 # project1, so that the jobs and templates apply to both
2304 # branches.
2305 with open(os.path.join(FIXTURE_DIR,
2306 'config/pragma-multibranch/git/',
2307 'org_project1/zuul.yaml')) as f:
2308 config = f.read()
2309 extra_conf = textwrap.dedent(
2310 """
2311 - pragma:
2312 implied-branch-matchers: False
2313 """)
2314 config = extra_conf + config
2315 file_dict = {'zuul.yaml': config}
2316 A = self.fake_gerrit.addFakeChange('org/project1', 'stable/pike', 'A',
2317 files=file_dict)
2318 A.addApproval('Code-Review', 2)
2319 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
2320 self.waitUntilSettled()
2321 self.fake_gerrit.addEvent(A.getChangeMergedEvent())
2322 self.waitUntilSettled()
2323
2324 # Now verify that when we propose a change to jewel, we get
2325 # the pike/jewel jobs.
2326 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
2327 self.waitUntilSettled()
2328 self.assertHistory([
2329 dict(name='test-job1', result='SUCCESS', changes='1,1'),
2330 dict(name='test-job2', result='SUCCESS', changes='1,1'),
2331 ], ordered=False)
2332
2333 def test_supplied_branch_matchers(self):
2334 self.create_branch('org/project1', 'stable/pike')
2335 self.create_branch('org/project2', 'stable/jewel')
2336 self.fake_gerrit.addEvent(
2337 self.fake_gerrit.getFakeBranchCreatedEvent(
2338 'org/project1', 'stable/pike'))
2339 self.fake_gerrit.addEvent(
2340 self.fake_gerrit.getFakeBranchCreatedEvent(
2341 'org/project2', 'stable/jewel'))
2342 self.waitUntilSettled()
2343 # We want the jobs defined on the stable/pike branch of
2344 # project1 to apply to the stable/jewel branch of project2.
2345
2346 # First, without the pragma line, the jobs should not run
2347 # because in project1 they have branch matchers for pike, so
2348 # they will not match a jewel change.
2349 B = self.fake_gerrit.addFakeChange('org/project2', 'stable/jewel', 'B')
2350 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
2351 self.waitUntilSettled()
2352 self.assertHistory([])
2353
2354 # Add a pragma line to disable implied branch matchers in
2355 # project1, so that the jobs and templates apply to both
2356 # branches.
2357 with open(os.path.join(FIXTURE_DIR,
2358 'config/pragma-multibranch/git/',
2359 'org_project1/zuul.yaml')) as f:
2360 config = f.read()
2361 extra_conf = textwrap.dedent(
2362 """
2363 - pragma:
2364 implied-branches:
2365 - stable/pike
2366 - stable/jewel
2367 """)
2368 config = extra_conf + config
2369 file_dict = {'zuul.yaml': config}
2370 A = self.fake_gerrit.addFakeChange('org/project1', 'stable/pike', 'A',
2371 files=file_dict)
2372 A.addApproval('Code-Review', 2)
2373 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
2374 self.waitUntilSettled()
2375 self.fake_gerrit.addEvent(A.getChangeMergedEvent())
2376 self.waitUntilSettled()
2377 # Now verify that when we propose a change to jewel, we get
2378 # the pike/jewel jobs.
2379 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
2380 self.waitUntilSettled()
2381 self.assertHistory([
2382 dict(name='test-job1', result='SUCCESS', changes='1,1'),
2383 dict(name='test-job2', result='SUCCESS', changes='1,1'),
2384 ], ordered=False)
2385
2386
James E. Blair2bab6e72017-08-07 09:52:45 -07002387class TestBaseJobs(ZuulTestCase):
2388 tenant_config_file = 'config/base-jobs/main.yaml'
2389
2390 def test_multiple_base_jobs(self):
2391 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2392 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2393 self.waitUntilSettled()
2394 self.assertHistory([
2395 dict(name='my-job', result='SUCCESS', changes='1,1'),
2396 dict(name='other-job', result='SUCCESS', changes='1,1'),
2397 ], ordered=False)
2398 self.assertEqual(self.getJobFromHistory('my-job').
2399 parameters['zuul']['jobtags'],
2400 ['mybase'])
2401 self.assertEqual(self.getJobFromHistory('other-job').
2402 parameters['zuul']['jobtags'],
2403 ['otherbase'])
2404
2405 def test_untrusted_base_job(self):
2406 """Test that a base job may not be defined in an untrusted repo"""
2407 in_repo_conf = textwrap.dedent(
2408 """
2409 - job:
2410 name: fail-base
2411 parent: null
2412 """)
2413
2414 file_dict = {'.zuul.yaml': in_repo_conf}
2415 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
2416 files=file_dict)
2417 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2418 self.waitUntilSettled()
2419 self.assertEqual(A.reported, 1,
2420 "A should report failure")
2421 self.assertEqual(A.patchsets[0]['approvals'][0]['value'], "-1")
2422 self.assertIn('Base jobs must be defined in config projects',
2423 A.messages[0])
2424 self.assertHistory([])
James E. Blairdb089032017-08-15 13:42:12 -07002425
2426
James E. Blairdf91ab32017-10-25 17:57:13 -07002427class TestSecretInheritance(ZuulTestCase):
2428 tenant_config_file = 'config/secret-inheritance/main.yaml'
2429
2430 def _getSecrets(self, job, pbtype):
2431 secrets = []
2432 build = self.getJobFromHistory(job)
2433 for pb in build.parameters[pbtype]:
2434 secrets.append(pb['secrets'])
2435 return secrets
2436
2437 def _checkTrustedSecrets(self):
2438 secret = {'longpassword': 'test-passwordtest-password',
2439 'password': 'test-password',
2440 'username': 'test-username'}
2441 self.assertEqual(
2442 self._getSecrets('trusted-secrets', 'playbooks'),
James E. Blair2f589fe2017-10-26 12:57:41 -07002443 [{'trusted-secret': secret}])
James E. Blairdf91ab32017-10-25 17:57:13 -07002444 self.assertEqual(
2445 self._getSecrets('trusted-secrets', 'pre_playbooks'), [])
2446 self.assertEqual(
2447 self._getSecrets('trusted-secrets', 'post_playbooks'), [])
2448
2449 self.assertEqual(
2450 self._getSecrets('trusted-secrets-trusted-child',
James E. Blair2f589fe2017-10-26 12:57:41 -07002451 'playbooks'), [{}])
James E. Blairdf91ab32017-10-25 17:57:13 -07002452 self.assertEqual(
2453 self._getSecrets('trusted-secrets-trusted-child',
2454 'pre_playbooks'), [])
2455 self.assertEqual(
2456 self._getSecrets('trusted-secrets-trusted-child',
2457 'post_playbooks'), [])
2458
2459 self.assertEqual(
2460 self._getSecrets('trusted-secrets-untrusted-child',
James E. Blair2f589fe2017-10-26 12:57:41 -07002461 'playbooks'), [{}])
James E. Blairdf91ab32017-10-25 17:57:13 -07002462 self.assertEqual(
2463 self._getSecrets('trusted-secrets-untrusted-child',
2464 'pre_playbooks'), [])
2465 self.assertEqual(
2466 self._getSecrets('trusted-secrets-untrusted-child',
2467 'post_playbooks'), [])
2468
2469 def _checkUntrustedSecrets(self):
2470 secret = {'longpassword': 'test-passwordtest-password',
2471 'password': 'test-password',
2472 'username': 'test-username'}
2473 self.assertEqual(
2474 self._getSecrets('untrusted-secrets', 'playbooks'),
James E. Blair2f589fe2017-10-26 12:57:41 -07002475 [{'untrusted-secret': secret}])
James E. Blairdf91ab32017-10-25 17:57:13 -07002476 self.assertEqual(
2477 self._getSecrets('untrusted-secrets', 'pre_playbooks'), [])
2478 self.assertEqual(
2479 self._getSecrets('untrusted-secrets', 'post_playbooks'), [])
2480
2481 self.assertEqual(
2482 self._getSecrets('untrusted-secrets-trusted-child',
James E. Blair2f589fe2017-10-26 12:57:41 -07002483 'playbooks'), [{}])
James E. Blairdf91ab32017-10-25 17:57:13 -07002484 self.assertEqual(
2485 self._getSecrets('untrusted-secrets-trusted-child',
2486 'pre_playbooks'), [])
2487 self.assertEqual(
2488 self._getSecrets('untrusted-secrets-trusted-child',
2489 'post_playbooks'), [])
2490
2491 self.assertEqual(
2492 self._getSecrets('untrusted-secrets-untrusted-child',
James E. Blair2f589fe2017-10-26 12:57:41 -07002493 'playbooks'), [{}])
James E. Blairdf91ab32017-10-25 17:57:13 -07002494 self.assertEqual(
2495 self._getSecrets('untrusted-secrets-untrusted-child',
2496 'pre_playbooks'), [])
2497 self.assertEqual(
2498 self._getSecrets('untrusted-secrets-untrusted-child',
2499 'post_playbooks'), [])
2500
2501 def test_trusted_secret_inheritance_check(self):
2502 A = self.fake_gerrit.addFakeChange('common-config', 'master', 'A')
2503 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2504 self.waitUntilSettled()
2505 self.assertHistory([
2506 dict(name='trusted-secrets', result='SUCCESS', changes='1,1'),
2507 dict(name='trusted-secrets-trusted-child',
2508 result='SUCCESS', changes='1,1'),
2509 dict(name='trusted-secrets-untrusted-child',
2510 result='SUCCESS', changes='1,1'),
2511 ], ordered=False)
2512
2513 self._checkTrustedSecrets()
2514
2515 def test_untrusted_secret_inheritance_gate(self):
2516 A = self.fake_gerrit.addFakeChange('common-config', 'master', 'A')
2517 A.addApproval('Code-Review', 2)
2518 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
2519 self.waitUntilSettled()
2520 self.assertHistory([
2521 dict(name='untrusted-secrets', result='SUCCESS', changes='1,1'),
2522 dict(name='untrusted-secrets-trusted-child',
2523 result='SUCCESS', changes='1,1'),
2524 dict(name='untrusted-secrets-untrusted-child',
2525 result='SUCCESS', changes='1,1'),
2526 ], ordered=False)
2527
2528 self._checkUntrustedSecrets()
2529
2530 def test_untrusted_secret_inheritance_check(self):
2531 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2532 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2533 self.waitUntilSettled()
2534 # This configuration tries to run untrusted secrets in an
2535 # non-post-review pipeline and should therefore run no jobs.
2536 self.assertHistory([])
2537
2538
James E. Blairdb089032017-08-15 13:42:12 -07002539class TestSecretLeaks(AnsibleZuulTestCase):
2540 tenant_config_file = 'config/secret-leaks/main.yaml'
2541
2542 def searchForContent(self, path, content):
2543 matches = []
2544 for (dirpath, dirnames, filenames) in os.walk(path):
2545 for filename in filenames:
2546 filepath = os.path.join(dirpath, filename)
2547 with open(filepath, 'rb') as f:
2548 if content in f.read():
2549 matches.append(filepath[len(path):])
2550 return matches
2551
2552 def _test_secret_file(self):
2553 # Or rather -- test that they *don't* leak.
2554 # Keep the jobdir around so we can inspect contents.
2555 self.executor_server.keep_jobdir = True
2556 conf = textwrap.dedent(
2557 """
2558 - project:
2559 name: org/project
2560 check:
2561 jobs:
2562 - secret-file
2563 """)
2564
2565 file_dict = {'.zuul.yaml': conf}
2566 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
2567 files=file_dict)
2568 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2569 self.waitUntilSettled()
2570 self.assertHistory([
2571 dict(name='secret-file', result='SUCCESS', changes='1,1'),
2572 ], ordered=False)
2573 matches = self.searchForContent(self.history[0].jobdir.root,
2574 b'test-password')
James E. Blaird6a71ca2017-08-18 14:15:05 -07002575 self.assertEqual(set(['/work/secret-file.txt']),
James E. Blairdb089032017-08-15 13:42:12 -07002576 set(matches))
2577
2578 def test_secret_file(self):
2579 self._test_secret_file()
2580
2581 def test_secret_file_verbose(self):
2582 # Output extra ansible info to exercise alternate logging code
2583 # paths.
2584 self.executor_server.verbose = True
2585 self._test_secret_file()
2586
2587 def _test_secret_file_fail(self):
2588 # Or rather -- test that they *don't* leak.
2589 # Keep the jobdir around so we can inspect contents.
2590 self.executor_server.keep_jobdir = True
2591 conf = textwrap.dedent(
2592 """
2593 - project:
2594 name: org/project
2595 check:
2596 jobs:
2597 - secret-file-fail
2598 """)
2599
2600 file_dict = {'.zuul.yaml': conf}
2601 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
2602 files=file_dict)
2603 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2604 self.waitUntilSettled()
2605 self.assertHistory([
2606 dict(name='secret-file-fail', result='FAILURE', changes='1,1'),
2607 ], ordered=False)
2608 matches = self.searchForContent(self.history[0].jobdir.root,
2609 b'test-password')
James E. Blaird6a71ca2017-08-18 14:15:05 -07002610 self.assertEqual(set(['/work/failure-file.txt']),
James E. Blairdb089032017-08-15 13:42:12 -07002611 set(matches))
2612
2613 def test_secret_file_fail(self):
2614 self._test_secret_file_fail()
2615
2616 def test_secret_file_fail_verbose(self):
2617 # Output extra ansible info to exercise alternate logging code
2618 # paths.
2619 self.executor_server.verbose = True
2620 self._test_secret_file_fail()
James E. Blaira00910c2017-08-23 09:15:04 -07002621
2622
2623class TestJobOutput(AnsibleZuulTestCase):
2624 tenant_config_file = 'config/job-output/main.yaml'
2625
2626 def _get_file(self, build, path):
2627 p = os.path.join(build.jobdir.root, path)
2628 with open(p) as f:
2629 return f.read()
2630
2631 def test_job_output(self):
Monty Taylor0e2489a2017-10-10 11:57:29 -05002632 # Verify that command standard output appears in the job output,
2633 # and that failures in the final playbook get logged.
James E. Blaira00910c2017-08-23 09:15:04 -07002634
2635 # This currently only verifies we receive output from
2636 # localhost. Notably, it does not verify we receive output
2637 # via zuul_console streaming.
2638 self.executor_server.keep_jobdir = True
2639 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2640 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2641 self.waitUntilSettled()
2642 self.assertHistory([
2643 dict(name='job-output', result='SUCCESS', changes='1,1'),
2644 ], ordered=False)
2645
2646 token = 'Standard output test %s' % (self.history[0].jobdir.src_root)
2647 j = json.loads(self._get_file(self.history[0],
2648 'work/logs/job-output.json'))
2649 self.assertEqual(token,
2650 j[0]['plays'][0]['tasks'][0]
2651 ['hosts']['localhost']['stdout'])
2652
2653 print(self._get_file(self.history[0],
2654 'work/logs/job-output.txt'))
2655 self.assertIn(token,
2656 self._get_file(self.history[0],
2657 'work/logs/job-output.txt'))
Monty Taylor0e2489a2017-10-10 11:57:29 -05002658
2659 def test_job_output_failure_log(self):
2660 logger = logging.getLogger('zuul.AnsibleJob')
2661 output = io.StringIO()
2662 logger.addHandler(logging.StreamHandler(output))
2663
2664 # Verify that a failure in the last post playbook emits the contents
2665 # of the json output to the log
2666 self.executor_server.keep_jobdir = True
2667 A = self.fake_gerrit.addFakeChange('org/project2', 'master', 'A')
2668 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2669 self.waitUntilSettled()
2670 self.assertHistory([
2671 dict(name='job-output-failure',
2672 result='POST_FAILURE', changes='1,1'),
2673 ], ordered=False)
2674
2675 token = 'Standard output test %s' % (self.history[0].jobdir.src_root)
2676 j = json.loads(self._get_file(self.history[0],
2677 'work/logs/job-output.json'))
2678 self.assertEqual(token,
2679 j[0]['plays'][0]['tasks'][0]
2680 ['hosts']['localhost']['stdout'])
2681
2682 print(self._get_file(self.history[0],
2683 'work/logs/job-output.json'))
2684 self.assertIn(token,
2685 self._get_file(self.history[0],
2686 'work/logs/job-output.txt'))
2687
2688 log_output = output.getvalue()
2689 self.assertIn('Final playbook failed', log_output)
2690 self.assertIn('Failure test', log_output)