blob: f019ead38261addd9d83e47ed02bffae2df91670 [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 Henkel130b0002017-11-26 20:27:59 +010076class TestProtected(ZuulTestCase):
Tobias Henkel130b0002017-11-26 20:27:59 +010077 tenant_config_file = 'config/protected/main.yaml'
78
79 def test_protected_ok(self):
James E. Blair979bf242017-09-15 21:13:32 -060080 # test clean usage of final parent job
81 in_repo_conf = textwrap.dedent(
82 """
83 - job:
84 name: job-protected
85 protected: true
86 run: playbooks/job-protected.yaml
Tobias Henkel130b0002017-11-26 20:27:59 +010087
James E. Blair979bf242017-09-15 21:13:32 -060088 - project:
89 name: org/project
90 check:
91 jobs:
92 - job-child-ok
Tobias Henkel130b0002017-11-26 20:27:59 +010093
James E. Blair979bf242017-09-15 21:13:32 -060094 - job:
95 name: job-child-ok
96 parent: job-protected
Tobias Henkel130b0002017-11-26 20:27:59 +010097
James E. Blair979bf242017-09-15 21:13:32 -060098 - project:
99 name: org/project
100 check:
101 jobs:
102 - job-child-ok
Tobias Henkel130b0002017-11-26 20:27:59 +0100103
James E. Blair979bf242017-09-15 21:13:32 -0600104 """)
Tobias Henkel130b0002017-11-26 20:27:59 +0100105
James E. Blair979bf242017-09-15 21:13:32 -0600106 file_dict = {'zuul.yaml': in_repo_conf}
107 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
108 files=file_dict)
109 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
110 self.waitUntilSettled()
Tobias Henkel130b0002017-11-26 20:27:59 +0100111
James E. Blair979bf242017-09-15 21:13:32 -0600112 self.assertEqual(A.reported, 1)
113 self.assertEqual(A.patchsets[-1]['approvals'][0]['value'], '1')
Tobias Henkel130b0002017-11-26 20:27:59 +0100114
115 def test_protected_reset(self):
116 # try to reset protected flag
117 in_repo_conf = textwrap.dedent(
118 """
119 - job:
120 name: job-protected
121 protected: true
122 run: playbooks/job-protected.yaml
123
124 - job:
125 name: job-child-reset-protected
126 parent: job-protected
127 protected: false
128
129 - project:
130 name: org/project
131 check:
132 jobs:
133 - job-child-reset-protected
134
135 """)
136
137 file_dict = {'zuul.yaml': in_repo_conf}
138 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
139 files=file_dict)
140 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
141 self.waitUntilSettled()
142
143 # The second patch tried to override some variables.
144 # Thus it should fail.
145 self.assertEqual(A.reported, 1)
146 self.assertEqual(A.patchsets[-1]['approvals'][0]['value'], '-1')
147 self.assertIn('Unable to reset protected attribute', A.messages[0])
148
149 def test_protected_inherit_not_ok(self):
150 # try to inherit from a protected job in different project
151 in_repo_conf = textwrap.dedent(
152 """
153 - job:
154 name: job-child-notok
155 run: playbooks/job-child-notok.yaml
156 parent: job-protected
157
158 - project:
159 name: org/project1
160 check:
161 jobs:
162 - job-child-notok
163
164 """)
165
166 file_dict = {'zuul.yaml': in_repo_conf}
167 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A',
168 files=file_dict)
169 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
170 self.waitUntilSettled()
171
172 self.assertEqual(A.reported, 1)
173 self.assertEqual(A.patchsets[-1]['approvals'][0]['value'], '-1')
174 self.assertIn(
175 "which is defined in review.example.com/org/project is protected "
176 "and cannot be inherited from other projects.", A.messages[0])
177
178
James E. Blair979bf242017-09-15 21:13:32 -0600179class TestAbstract(ZuulTestCase):
180 tenant_config_file = 'config/abstract/main.yaml'
181
182 def test_abstract_fail(self):
183 in_repo_conf = textwrap.dedent(
184 """
185 - project:
186 check:
187 jobs:
188 - job-abstract
189 """)
190
191 file_dict = {'zuul.yaml': in_repo_conf}
192 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
193 files=file_dict)
194 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
195 self.waitUntilSettled()
196
197 self.assertEqual(A.reported, 1)
198 self.assertEqual(A.patchsets[-1]['approvals'][0]['value'], '-1')
199 self.assertIn('may not be directly run', A.messages[0])
200
201 def test_child_of_abstract(self):
202 in_repo_conf = textwrap.dedent(
203 """
204 - project:
205 check:
206 jobs:
207 - job-child
208 """)
209
210 file_dict = {'zuul.yaml': in_repo_conf}
211 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
212 files=file_dict)
213 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
214 self.waitUntilSettled()
215
216 self.assertEqual(A.reported, 1)
217 self.assertEqual(A.patchsets[-1]['approvals'][0]['value'], '1')
218
219
Tobias Henkel83167622017-06-30 19:45:03 +0200220class TestFinal(ZuulTestCase):
221
222 tenant_config_file = 'config/final/main.yaml'
223
224 def test_final_variant_ok(self):
225 # test clean usage of final parent job
226 in_repo_conf = textwrap.dedent(
227 """
228 - project:
229 name: org/project
230 check:
231 jobs:
232 - job-final
233 """)
234
235 file_dict = {'.zuul.yaml': in_repo_conf}
236 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
237 files=file_dict)
238 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
239 self.waitUntilSettled()
240
241 self.assertEqual(A.reported, 1)
242 self.assertEqual(A.patchsets[-1]['approvals'][0]['value'], '1')
243
244 def test_final_variant_error(self):
245 # test misuse of final parent job
246 in_repo_conf = textwrap.dedent(
247 """
248 - project:
249 name: org/project
250 check:
251 jobs:
252 - job-final:
253 vars:
254 dont_override_this: bar
255 """)
256 file_dict = {'.zuul.yaml': in_repo_conf}
257 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
258 files=file_dict)
259 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
260 self.waitUntilSettled()
261
262 # The second patch tried to override some variables.
263 # Thus it should fail.
264 self.assertEqual(A.reported, 1)
265 self.assertEqual(A.patchsets[-1]['approvals'][0]['value'], '-1')
266 self.assertIn('Unable to modify final job', A.messages[0])
267
268 def test_final_inheritance(self):
269 # test misuse of final parent job
270 in_repo_conf = textwrap.dedent(
271 """
272 - job:
273 name: project-test
274 parent: job-final
James E. Blair2f589fe2017-10-26 12:57:41 -0700275 run: playbooks/project-test.yaml
Tobias Henkel83167622017-06-30 19:45:03 +0200276
277 - project:
278 name: org/project
279 check:
280 jobs:
281 - project-test
282 """)
283
284 in_repo_playbook = textwrap.dedent(
285 """
286 - hosts: all
287 tasks: []
288 """)
289
290 file_dict = {'.zuul.yaml': in_repo_conf,
291 'playbooks/project-test.yaml': in_repo_playbook}
292 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
293 files=file_dict)
294 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
295 self.waitUntilSettled()
296
297 # The second patch tried to override some variables.
298 # Thus it should fail.
299 self.assertEqual(A.reported, 1)
300 self.assertEqual(A.patchsets[-1]['approvals'][0]['value'], '-1')
James E. Blairc32a8352017-10-11 16:27:50 -0700301 self.assertIn('Unable to modify final job', A.messages[0])
Tobias Henkel83167622017-06-30 19:45:03 +0200302
303
James E. Blairc6d48652018-02-14 14:20:13 -0800304class TestBranchDeletion(ZuulTestCase):
305 tenant_config_file = 'config/branch-deletion/main.yaml'
306
307 def test_branch_delete(self):
308 # This tests a tenant reconfiguration on deleting a branch
309 # *after* an earlier failed tenant reconfiguration. This
310 # ensures that cached data are appropriately removed, even if
311 # we are recovering from an invalid config.
312 self.create_branch('org/project', 'stable/queens')
313 self.fake_gerrit.addEvent(
314 self.fake_gerrit.getFakeBranchCreatedEvent(
315 'org/project', 'stable/queens'))
316 self.waitUntilSettled()
317
318 in_repo_conf = textwrap.dedent(
319 """
320 - project:
321 check:
322 jobs:
323 - nonexistent-job
324 """)
325
326 file_dict = {'zuul.yaml': in_repo_conf}
327 A = self.fake_gerrit.addFakeChange('org/project', 'stable/queens', 'A',
328 files=file_dict)
329 A.setMerged()
330 self.fake_gerrit.addEvent(A.getChangeMergedEvent())
331 self.waitUntilSettled()
332
333 self.delete_branch('org/project', 'stable/queens')
334 self.fake_gerrit.addEvent(
335 self.fake_gerrit.getFakeBranchDeletedEvent(
336 'org/project', 'stable/queens'))
337 self.waitUntilSettled()
338
339 in_repo_conf = textwrap.dedent(
340 """
341 - project:
342 check:
343 jobs:
344 - base
345 """)
346
347 file_dict = {'zuul.yaml': in_repo_conf}
348 B = self.fake_gerrit.addFakeChange('org/project1', 'master', 'B',
349 files=file_dict)
350 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
351 self.waitUntilSettled()
352 self.assertEqual(B.reported, 1)
353 self.assertHistory([
354 dict(name='base', result='SUCCESS', changes='2,1')])
355
356 def test_branch_delete_full_reconfiguration(self):
357 # This tests a full configuration after deleting a branch
358 # *after* an earlier failed tenant reconfiguration. This
359 # ensures that cached data are appropriately removed, even if
360 # we are recovering from an invalid config.
361 self.create_branch('org/project', 'stable/queens')
362 self.fake_gerrit.addEvent(
363 self.fake_gerrit.getFakeBranchCreatedEvent(
364 'org/project', 'stable/queens'))
365 self.waitUntilSettled()
366
367 in_repo_conf = textwrap.dedent(
368 """
369 - project:
370 check:
371 jobs:
372 - nonexistent-job
373 """)
374
375 file_dict = {'zuul.yaml': in_repo_conf}
376 A = self.fake_gerrit.addFakeChange('org/project', 'stable/queens', 'A',
377 files=file_dict)
378 A.setMerged()
379 self.fake_gerrit.addEvent(A.getChangeMergedEvent())
380 self.waitUntilSettled()
381
382 self.delete_branch('org/project', 'stable/queens')
383 self.sched.reconfigure(self.config)
384 self.waitUntilSettled()
385
386 in_repo_conf = textwrap.dedent(
387 """
388 - project:
389 check:
390 jobs:
391 - base
392 """)
393
394 file_dict = {'zuul.yaml': in_repo_conf}
395 B = self.fake_gerrit.addFakeChange('org/project1', 'master', 'B',
396 files=file_dict)
397 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
398 self.waitUntilSettled()
399 self.assertEqual(B.reported, 1)
400 self.assertHistory([
401 dict(name='base', result='SUCCESS', changes='2,1')])
402
403
James E. Blair1edfd972017-12-01 15:54:24 -0800404class TestBranchTag(ZuulTestCase):
405 tenant_config_file = 'config/branch-tag/main.yaml'
406
407 def test_negative_branch_match(self):
408 # Test that a negative branch matcher works with implied branches.
409 event = self.fake_gerrit.addFakeTag('org/project', 'master', 'foo')
410 self.fake_gerrit.addEvent(event)
411 self.waitUntilSettled()
412 self.assertHistory([
413 dict(name='test-job', result='SUCCESS', ref='refs/tags/foo')])
414
415
James E. Blair9ab8db42017-12-01 15:12:04 -0800416class TestBranchNegative(ZuulTestCase):
417 tenant_config_file = 'config/branch-negative/main.yaml'
418
419 def test_negative_branch_match(self):
420 # Test that a negative branch matcher works with implied branches.
421 self.create_branch('org/project', 'stable/pike')
422 self.fake_gerrit.addEvent(
423 self.fake_gerrit.getFakeBranchCreatedEvent(
424 'org/project', 'stable/pike'))
425 self.waitUntilSettled()
426
427 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
428 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
429 self.waitUntilSettled()
430 B = self.fake_gerrit.addFakeChange('org/project', 'stable/pike', 'A')
431 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
432 self.waitUntilSettled()
433 self.assertHistory([
434 dict(name='test-job', result='SUCCESS', changes='1,1')])
435
436
James E. Blaire36d1a32017-11-28 13:33:38 -0800437class TestBranchTemplates(ZuulTestCase):
438 tenant_config_file = 'config/branch-templates/main.yaml'
439
440 def test_template_removal_from_branch(self):
441 # Test that a template can be removed from one branch but not
442 # another.
443 # This creates a new branch with a copy of the config in master
444 self.create_branch('puppet-integration', 'stable/newton')
445 self.create_branch('puppet-integration', 'stable/ocata')
446 self.create_branch('puppet-tripleo', 'stable/newton')
447 self.create_branch('puppet-tripleo', 'stable/ocata')
448 self.fake_gerrit.addEvent(
449 self.fake_gerrit.getFakeBranchCreatedEvent(
450 'puppet-integration', 'stable/newton'))
451 self.fake_gerrit.addEvent(
452 self.fake_gerrit.getFakeBranchCreatedEvent(
453 'puppet-integration', 'stable/ocata'))
454 self.fake_gerrit.addEvent(
455 self.fake_gerrit.getFakeBranchCreatedEvent(
456 'puppet-tripleo', 'stable/newton'))
457 self.fake_gerrit.addEvent(
458 self.fake_gerrit.getFakeBranchCreatedEvent(
459 'puppet-tripleo', 'stable/ocata'))
460 self.waitUntilSettled()
461
462 in_repo_conf = textwrap.dedent(
463 """
464 - project:
465 name: puppet-tripleo
466 check:
467 jobs:
468 - puppet-something
469 """)
470
471 file_dict = {'.zuul.yaml': in_repo_conf}
472 A = self.fake_gerrit.addFakeChange('puppet-tripleo', 'stable/newton',
473 'A', files=file_dict)
474 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
475 self.waitUntilSettled()
476 self.assertHistory([
477 dict(name='puppet-something', result='SUCCESS', changes='1,1')])
478
479 def test_template_change_on_branch(self):
480 # Test that the contents of a template can be changed on one
481 # branch without affecting another.
482
483 # This creates a new branch with a copy of the config in master
484 self.create_branch('puppet-integration', 'stable/newton')
485 self.create_branch('puppet-integration', 'stable/ocata')
486 self.create_branch('puppet-tripleo', 'stable/newton')
487 self.create_branch('puppet-tripleo', 'stable/ocata')
488 self.fake_gerrit.addEvent(
489 self.fake_gerrit.getFakeBranchCreatedEvent(
490 'puppet-integration', 'stable/newton'))
491 self.fake_gerrit.addEvent(
492 self.fake_gerrit.getFakeBranchCreatedEvent(
493 'puppet-integration', 'stable/ocata'))
494 self.fake_gerrit.addEvent(
495 self.fake_gerrit.getFakeBranchCreatedEvent(
496 'puppet-tripleo', 'stable/newton'))
497 self.fake_gerrit.addEvent(
498 self.fake_gerrit.getFakeBranchCreatedEvent(
499 'puppet-tripleo', 'stable/ocata'))
500 self.waitUntilSettled()
501
502 in_repo_conf = textwrap.dedent("""
503 - job:
504 name: puppet-unit-base
505 run: playbooks/run-unit-tests.yaml
506
507 - job:
508 name: puppet-unit-3.8
509 parent: puppet-unit-base
510 branches: ^(stable/(newton|ocata)).*$
511 vars:
512 puppet_gem_version: 3.8
513
514 - job:
515 name: puppet-something
516 run: playbooks/run-unit-tests.yaml
517
518 - project-template:
519 name: puppet-unit
520 check:
521 jobs:
522 - puppet-something
523
524 - project:
525 name: puppet-integration
526 templates:
527 - puppet-unit
528 """)
529
530 file_dict = {'.zuul.yaml': in_repo_conf}
531 A = self.fake_gerrit.addFakeChange('puppet-integration',
532 'stable/newton',
533 'A', files=file_dict)
534 B = self.fake_gerrit.addFakeChange('puppet-tripleo',
535 'stable/newton',
536 'B')
537 B.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
538 B.subject, A.data['id'])
539 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
540 self.waitUntilSettled()
541 self.assertHistory([
542 dict(name='puppet-something', result='SUCCESS',
543 changes='1,1 2,1')])
544
545
James E. Blair09998792017-10-15 18:02:18 -0700546class TestBranchVariants(ZuulTestCase):
547 tenant_config_file = 'config/branch-variants/main.yaml'
548
549 def test_branch_variants(self):
550 # Test branch variants of jobs with inheritance
551 self.executor_server.hold_jobs_in_build = True
552 # This creates a new branch with a copy of the config in master
553 self.create_branch('puppet-integration', 'stable')
554 self.fake_gerrit.addEvent(
555 self.fake_gerrit.getFakeBranchCreatedEvent(
556 'puppet-integration', 'stable'))
557 self.waitUntilSettled()
558
559 A = self.fake_gerrit.addFakeChange('puppet-integration', 'stable', 'A')
560 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
561 self.waitUntilSettled()
562
563 self.assertEqual(len(self.builds[0].parameters['pre_playbooks']), 3)
564 self.executor_server.hold_jobs_in_build = False
565 self.executor_server.release()
566 self.waitUntilSettled()
567
James E. Blairc9e77592017-10-24 09:25:23 -0700568 def test_branch_variants_reconfigure(self):
569 # Test branch variants of jobs with inheritance
570 self.executor_server.hold_jobs_in_build = True
571 # This creates a new branch with a copy of the config in master
572 self.create_branch('puppet-integration', 'stable')
573 self.fake_gerrit.addEvent(
574 self.fake_gerrit.getFakeBranchCreatedEvent(
575 'puppet-integration', 'stable'))
576 self.waitUntilSettled()
577
578 with open(os.path.join(FIXTURE_DIR,
579 'config/branch-variants/git/',
580 'puppet-integration/.zuul.yaml')) as f:
581 config = f.read()
582
583 # Push a change that triggers a dynamic reconfiguration
584 file_dict = {'.zuul.yaml': config}
585 A = self.fake_gerrit.addFakeChange('puppet-integration', 'master', 'A',
586 files=file_dict)
587 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
588 self.waitUntilSettled()
589
590 ipath = self.builds[0].parameters['zuul']['_inheritance_path']
591 for i in ipath:
592 self.log.debug("inheritance path %s", i)
593 self.assertEqual(len(ipath), 5)
594 self.executor_server.hold_jobs_in_build = False
595 self.executor_server.release()
596 self.waitUntilSettled()
597
James E. Blairc32a8352017-10-11 16:27:50 -0700598 def test_branch_variants_divergent(self):
599 # Test branches can diverge and become independent
600 self.executor_server.hold_jobs_in_build = True
601 # This creates a new branch with a copy of the config in master
602 self.create_branch('puppet-integration', 'stable')
603 self.fake_gerrit.addEvent(
604 self.fake_gerrit.getFakeBranchCreatedEvent(
605 'puppet-integration', 'stable'))
606 self.waitUntilSettled()
607
608 with open(os.path.join(FIXTURE_DIR,
609 'config/branch-variants/git/',
610 'puppet-integration/stable.zuul.yaml')) as f:
611 config = f.read()
612
613 file_dict = {'.zuul.yaml': config}
614 C = self.fake_gerrit.addFakeChange('puppet-integration', 'stable', 'C',
615 files=file_dict)
616 C.addApproval('Code-Review', 2)
617 self.fake_gerrit.addEvent(C.addApproval('Approved', 1))
618 self.waitUntilSettled()
619 self.fake_gerrit.addEvent(C.getChangeMergedEvent())
620 self.waitUntilSettled()
621
622 A = self.fake_gerrit.addFakeChange('puppet-integration', 'master', 'A')
623 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
624 self.waitUntilSettled()
625 B = self.fake_gerrit.addFakeChange('puppet-integration', 'stable', 'B')
626 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
627 self.waitUntilSettled()
628
629 self.assertEqual(self.builds[0].parameters['zuul']['jobtags'],
630 ['master'])
631
632 self.assertEqual(self.builds[1].parameters['zuul']['jobtags'],
633 ['stable'])
634
635 self.executor_server.hold_jobs_in_build = False
636 self.executor_server.release()
637 self.waitUntilSettled()
638
James E. Blair09998792017-10-15 18:02:18 -0700639
James E. Blair7fb04512018-01-23 13:23:13 -0800640class TestBranchMismatch(ZuulTestCase):
641 tenant_config_file = 'config/branch-mismatch/main.yaml'
642
643 def test_job_override_branch(self):
644 "Test that override-checkout overrides branch matchers as well"
645
646 # Make sure the parent job repo is branched, so it gets
647 # implied branch matchers.
648 self.create_branch('org/project1', 'stable')
649 self.fake_gerrit.addEvent(
650 self.fake_gerrit.getFakeBranchCreatedEvent(
651 'org/project1', 'stable'))
652
653 # The child job repo should have a branch which does not exist
654 # in the parent job repo.
655 self.create_branch('org/project2', 'devel')
656 self.fake_gerrit.addEvent(
657 self.fake_gerrit.getFakeBranchCreatedEvent(
658 'org/project2', 'devel'))
659
660 # A job in a repo with a weird branch name should use the
661 # parent job from the parent job's master (default) branch.
662 A = self.fake_gerrit.addFakeChange('org/project2', 'devel', 'A')
663 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
664 self.waitUntilSettled()
665 # project-test2 should run because it inherits from
666 # project-test1 and we will use the fallback branch to find
667 # project-test1 variants, but project-test1 itself, even
668 # though it is in the project-pipeline config, should not run
669 # because it doesn't directly match.
670 self.assertHistory([
671 dict(name='project-test1', result='SUCCESS', changes='1,1'),
672 dict(name='project-test2', result='SUCCESS', changes='1,1'),
673 ], ordered=False)
674
675
James E. Blair5d71d1a2018-01-26 14:26:18 -0800676class TestAllowedProjects(ZuulTestCase):
677 tenant_config_file = 'config/allowed-projects/main.yaml'
678
679 def test_allowed_projects(self):
680 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A')
681 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
682 self.waitUntilSettled()
683 self.assertEqual(A.reported, 1)
684 self.assertIn('Build succeeded', A.messages[0])
685
686 B = self.fake_gerrit.addFakeChange('org/project2', 'master', 'B')
687 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
688 self.waitUntilSettled()
689 self.assertEqual(B.reported, 1)
690 self.assertIn('Project org/project2 is not allowed '
691 'to run job test-project2', B.messages[0])
692
693 C = self.fake_gerrit.addFakeChange('org/project3', 'master', 'C')
694 self.fake_gerrit.addEvent(C.getPatchsetCreatedEvent(1))
695 self.waitUntilSettled()
696 self.assertEqual(C.reported, 1)
697 self.assertIn('Project org/project3 is not allowed '
698 'to run job restricted-job', C.messages[0])
699
700 self.assertHistory([
701 dict(name='test-project1', result='SUCCESS', changes='1,1'),
702 dict(name='restricted-job', result='SUCCESS', changes='1,1'),
703 ], ordered=False)
704
705
James E. Blair2a664502017-10-27 11:39:33 -0700706class TestCentralJobs(ZuulTestCase):
707 tenant_config_file = 'config/central-jobs/main.yaml'
708
709 def setUp(self):
710 super(TestCentralJobs, self).setUp()
711 self.create_branch('org/project', 'stable')
712 self.fake_gerrit.addEvent(
713 self.fake_gerrit.getFakeBranchCreatedEvent(
714 'org/project', 'stable'))
715 self.waitUntilSettled()
716
717 def _updateConfig(self, config, branch):
718 file_dict = {'.zuul.yaml': config}
719 C = self.fake_gerrit.addFakeChange('org/project', branch, 'C',
720 files=file_dict)
721 C.addApproval('Code-Review', 2)
722 self.fake_gerrit.addEvent(C.addApproval('Approved', 1))
723 self.waitUntilSettled()
724 self.fake_gerrit.addEvent(C.getChangeMergedEvent())
725 self.waitUntilSettled()
726
727 def _test_central_job_on_branch(self, branch, other_branch):
728 # Test that a job defined on a branchless repo only runs on
729 # the branch applied
730 config = textwrap.dedent(
731 """
732 - project:
733 name: org/project
734 check:
735 jobs:
736 - central-job
737 """)
738 self._updateConfig(config, branch)
739
740 A = self.fake_gerrit.addFakeChange('org/project', branch, 'A')
741 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
742 self.waitUntilSettled()
743
744 self.assertHistory([
745 dict(name='central-job', result='SUCCESS', changes='2,1')])
746
747 # No jobs should run for this change.
748 B = self.fake_gerrit.addFakeChange('org/project', other_branch, 'B')
749 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
750 self.waitUntilSettled()
751
752 self.assertHistory([
753 dict(name='central-job', result='SUCCESS', changes='2,1')])
754
755 def test_central_job_on_stable(self):
756 self._test_central_job_on_branch('master', 'stable')
757
758 def test_central_job_on_master(self):
759 self._test_central_job_on_branch('stable', 'master')
760
761 def _test_central_template_on_branch(self, branch, other_branch):
762 # Test that a project-template defined on a branchless repo
763 # only runs on the branch applied
764 config = textwrap.dedent(
765 """
766 - project:
767 name: org/project
768 templates: ['central-jobs']
769 """)
770 self._updateConfig(config, branch)
771
772 A = self.fake_gerrit.addFakeChange('org/project', branch, 'A')
773 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
774 self.waitUntilSettled()
775
776 self.assertHistory([
777 dict(name='central-job', result='SUCCESS', changes='2,1')])
778
779 # No jobs should run for this change.
780 B = self.fake_gerrit.addFakeChange('org/project', other_branch, 'B')
781 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
782 self.waitUntilSettled()
783
784 self.assertHistory([
785 dict(name='central-job', result='SUCCESS', changes='2,1')])
786
787 def test_central_template_on_stable(self):
788 self._test_central_template_on_branch('master', 'stable')
789
790 def test_central_template_on_master(self):
791 self._test_central_template_on_branch('stable', 'master')
792
793
James E. Blairff555742017-02-19 11:34:27 -0800794class TestInRepoConfig(ZuulTestCase):
James E. Blair83005782015-12-11 14:46:03 -0800795 # A temporary class to hold new tests while others are disabled
796
Tobias Henkelabf973e2017-07-28 10:07:34 +0200797 config_file = 'zuul-connections-gerrit-and-github.conf'
James E. Blair2a629ec2015-12-22 15:32:02 -0800798 tenant_config_file = 'config/in-repo/main.yaml'
James E. Blair83005782015-12-11 14:46:03 -0800799
James E. Blair83005782015-12-11 14:46:03 -0800800 def test_in_repo_config(self):
James E. Blair14abdf42015-12-09 16:11:53 -0800801 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
Tobias Henkelbf24fd12017-07-27 06:13:07 +0200802 A.addApproval('Code-Review', 2)
803 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
James E. Blair14abdf42015-12-09 16:11:53 -0800804 self.waitUntilSettled()
805 self.assertEqual(self.getJobFromHistory('project-test1').result,
806 'SUCCESS')
807 self.assertEqual(A.data['status'], 'MERGED')
808 self.assertEqual(A.reported, 2,
809 "A should report start and success")
810 self.assertIn('tenant-one-gate', A.messages[1],
811 "A should transit tenant-one gate")
James E. Blairb97ed802015-12-21 15:55:35 -0800812
James E. Blair3a098dd2017-10-04 14:37:29 -0700813 @skip("This test is useful, but not reliable")
814 def test_full_and_dynamic_reconfig(self):
815 self.executor_server.hold_jobs_in_build = True
816 in_repo_conf = textwrap.dedent(
817 """
818 - job:
819 name: project-test1
820
821 - project:
822 name: org/project
823 tenant-one-gate:
824 jobs:
825 - project-test1
826 """)
827
828 file_dict = {'.zuul.yaml': in_repo_conf}
829 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
830 files=file_dict)
831 A.addApproval('Code-Review', 2)
832 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
833 self.waitUntilSettled()
834 self.sched.reconfigure(self.config)
835 self.waitUntilSettled()
836
837 gc.collect()
838 pipelines = [obj for obj in gc.get_objects()
839 if isinstance(obj, zuul.model.Pipeline)]
840 self.assertEqual(len(pipelines), 4)
841
842 self.executor_server.hold_jobs_in_build = False
843 self.executor_server.release()
844 self.waitUntilSettled()
845
James E. Blair8b1dc3f2016-07-05 16:49:00 -0700846 def test_dynamic_config(self):
847 in_repo_conf = textwrap.dedent(
848 """
849 - job:
Tobias Henkelf02cf512017-07-21 22:55:34 +0200850 name: project-test1
851
852 - job:
James E. Blair8b1dc3f2016-07-05 16:49:00 -0700853 name: project-test2
James E. Blair2f589fe2017-10-26 12:57:41 -0700854 run: playbooks/project-test2.yaml
James E. Blair8b1dc3f2016-07-05 16:49:00 -0700855
Tobias Henkel53aa2ad2017-12-22 09:59:45 +0100856 - job:
857 name: project-test3
858 run: playbooks/project-test2.yaml
859
860 # add a job by the short project name
James E. Blair8b1dc3f2016-07-05 16:49:00 -0700861 - project:
862 name: org/project
863 tenant-one-gate:
864 jobs:
865 - project-test2
Tobias Henkel53aa2ad2017-12-22 09:59:45 +0100866
867 # add a job by the canonical project name
868 - project:
869 name: review.example.com/org/project
870 tenant-one-gate:
871 jobs:
872 - project-test3
James E. Blair8b1dc3f2016-07-05 16:49:00 -0700873 """)
874
James E. Blairc73c73a2017-01-20 15:15:15 -0800875 in_repo_playbook = textwrap.dedent(
876 """
877 - hosts: all
878 tasks: []
879 """)
880
881 file_dict = {'.zuul.yaml': in_repo_conf,
882 'playbooks/project-test2.yaml': in_repo_playbook}
James E. Blair8b1dc3f2016-07-05 16:49:00 -0700883 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
James E. Blairc73c73a2017-01-20 15:15:15 -0800884 files=file_dict)
Tobias Henkelbf24fd12017-07-27 06:13:07 +0200885 A.addApproval('Code-Review', 2)
886 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
James E. Blair8b1dc3f2016-07-05 16:49:00 -0700887 self.waitUntilSettled()
James E. Blair8b1dc3f2016-07-05 16:49:00 -0700888 self.assertEqual(A.data['status'], 'MERGED')
889 self.assertEqual(A.reported, 2,
890 "A should report start and success")
891 self.assertIn('tenant-one-gate', A.messages[1],
892 "A should transit tenant-one gate")
James E. Blair646322f2017-01-27 15:50:34 -0800893 self.assertHistory([
Tobias Henkel53aa2ad2017-12-22 09:59:45 +0100894 dict(name='project-test2', result='SUCCESS', changes='1,1'),
895 dict(name='project-test3', result='SUCCESS', changes='1,1'),
896 ], ordered=False)
James E. Blair646322f2017-01-27 15:50:34 -0800897
James E. Blairc2a5ed72017-02-20 14:12:01 -0500898 self.fake_gerrit.addEvent(A.getChangeMergedEvent())
James E. Blair7bbd7a32017-03-06 11:36:13 -0800899 self.waitUntilSettled()
James E. Blairc2a5ed72017-02-20 14:12:01 -0500900
James E. Blair646322f2017-01-27 15:50:34 -0800901 # Now that the config change is landed, it should be live for
902 # subsequent changes.
903 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
Tobias Henkelbf24fd12017-07-27 06:13:07 +0200904 B.addApproval('Code-Review', 2)
905 self.fake_gerrit.addEvent(B.addApproval('Approved', 1))
James E. Blair646322f2017-01-27 15:50:34 -0800906 self.waitUntilSettled()
907 self.assertEqual(self.getJobFromHistory('project-test2').result,
908 'SUCCESS')
909 self.assertHistory([
910 dict(name='project-test2', result='SUCCESS', changes='1,1'),
Tobias Henkel53aa2ad2017-12-22 09:59:45 +0100911 dict(name='project-test3', result='SUCCESS', changes='1,1'),
912 dict(name='project-test2', result='SUCCESS', changes='2,1'),
913 dict(name='project-test3', result='SUCCESS', changes='2,1'),
914 ], ordered=False)
James E. Blairc73c73a2017-01-20 15:15:15 -0800915
James E. Blair6bc10482017-10-20 11:28:53 -0700916 def test_dynamic_template(self):
James E. Blair2a664502017-10-27 11:39:33 -0700917 # Tests that a project can't update a template in another
918 # project.
James E. Blair6bc10482017-10-20 11:28:53 -0700919 in_repo_conf = textwrap.dedent(
920 """
921 - job:
922 name: project-test1
923
924 - project-template:
925 name: common-config-template
926 check:
927 jobs:
928 - project-test1
929
930 - project:
931 name: org/project
932 templates: [common-config-template]
933 """)
934
935 file_dict = {'.zuul.yaml': in_repo_conf}
936 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
937 files=file_dict)
938 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
939 self.waitUntilSettled()
James E. Blair2a664502017-10-27 11:39:33 -0700940
941 self.assertEqual(A.patchsets[0]['approvals'][0]['value'], "-1")
942 self.assertIn('Project template common-config-template '
943 'is already defined',
944 A.messages[0],
945 "A should have failed the check pipeline")
James E. Blair6bc10482017-10-20 11:28:53 -0700946
Tobias Henkelf02cf512017-07-21 22:55:34 +0200947 def test_dynamic_config_non_existing_job(self):
948 """Test that requesting a non existent job fails"""
949 in_repo_conf = textwrap.dedent(
950 """
951 - job:
952 name: project-test1
953
954 - project:
955 name: org/project
956 check:
957 jobs:
958 - non-existent-job
959 """)
960
961 in_repo_playbook = textwrap.dedent(
962 """
963 - hosts: all
964 tasks: []
965 """)
966
967 file_dict = {'.zuul.yaml': in_repo_conf,
968 'playbooks/project-test2.yaml': in_repo_playbook}
969 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
970 files=file_dict)
971 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
972 self.waitUntilSettled()
973 self.assertEqual(A.reported, 1,
974 "A should report failure")
975 self.assertEqual(A.patchsets[0]['approvals'][0]['value'], "-1")
976 self.assertIn('Job non-existent-job not defined', A.messages[0],
977 "A should have failed the check pipeline")
978 self.assertHistory([])
979
980 def test_dynamic_config_non_existing_job_in_template(self):
981 """Test that requesting a non existent job fails"""
982 in_repo_conf = textwrap.dedent(
983 """
984 - job:
985 name: project-test1
986
987 - project-template:
988 name: test-template
989 check:
990 jobs:
991 - non-existent-job
992
993 - project:
994 name: org/project
995 templates:
996 - test-template
997 """)
998
999 in_repo_playbook = textwrap.dedent(
1000 """
1001 - hosts: all
1002 tasks: []
1003 """)
1004
1005 file_dict = {'.zuul.yaml': in_repo_conf,
1006 'playbooks/project-test2.yaml': in_repo_playbook}
1007 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
1008 files=file_dict)
1009 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
1010 self.waitUntilSettled()
1011 self.assertEqual(A.reported, 1,
1012 "A should report failure")
1013 self.assertEqual(A.patchsets[0]['approvals'][0]['value'], "-1")
1014 self.assertIn('Job non-existent-job not defined', A.messages[0],
1015 "A should have failed the check pipeline")
1016 self.assertHistory([])
1017
Tobias Henkel0f714002017-06-30 23:30:52 +02001018 def test_dynamic_config_new_patchset(self):
1019 self.executor_server.hold_jobs_in_build = True
1020
1021 tenant = self.sched.abide.tenants.get('tenant-one')
1022 check_pipeline = tenant.layout.pipelines['check']
1023
1024 in_repo_conf = textwrap.dedent(
1025 """
1026 - job:
Tobias Henkelf02cf512017-07-21 22:55:34 +02001027 name: project-test1
James E. Blair2f589fe2017-10-26 12:57:41 -07001028 run: playbooks/project-test1.yaml
Tobias Henkelf02cf512017-07-21 22:55:34 +02001029
1030 - job:
Tobias Henkel0f714002017-06-30 23:30:52 +02001031 name: project-test2
James E. Blair2f589fe2017-10-26 12:57:41 -07001032 run: playbooks/project-test2.yaml
Tobias Henkel0f714002017-06-30 23:30:52 +02001033
1034 - project:
1035 name: org/project
1036 check:
1037 jobs:
1038 - project-test2
1039 """)
1040
1041 in_repo_playbook = textwrap.dedent(
1042 """
1043 - hosts: all
1044 tasks: []
1045 """)
1046
1047 file_dict = {'.zuul.yaml': in_repo_conf,
1048 'playbooks/project-test2.yaml': in_repo_playbook}
1049 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
1050 files=file_dict)
1051 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
1052 self.waitUntilSettled()
1053
1054 items = check_pipeline.getAllItems()
1055 self.assertEqual(items[0].change.number, '1')
1056 self.assertEqual(items[0].change.patchset, '1')
1057 self.assertTrue(items[0].live)
1058
1059 in_repo_conf = textwrap.dedent(
1060 """
1061 - job:
Tobias Henkel0ce7ec62017-07-21 22:50:17 +02001062 name: project-test1
James E. Blair2f589fe2017-10-26 12:57:41 -07001063 run: playbooks/project-test1.yaml
Tobias Henkel0ce7ec62017-07-21 22:50:17 +02001064
1065 - job:
Tobias Henkel0f714002017-06-30 23:30:52 +02001066 name: project-test2
James E. Blair2f589fe2017-10-26 12:57:41 -07001067 run: playbooks/project-test2.yaml
Tobias Henkel0f714002017-06-30 23:30:52 +02001068
1069 - project:
1070 name: org/project
1071 check:
1072 jobs:
1073 - project-test1
1074 - project-test2
1075 """)
1076 file_dict = {'.zuul.yaml': in_repo_conf,
1077 'playbooks/project-test2.yaml': in_repo_playbook}
1078
1079 A.addPatchset(files=file_dict)
1080 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(2))
1081
1082 self.waitUntilSettled()
1083
1084 items = check_pipeline.getAllItems()
1085 self.assertEqual(items[0].change.number, '1')
1086 self.assertEqual(items[0].change.patchset, '2')
1087 self.assertTrue(items[0].live)
1088
1089 self.executor_server.hold_jobs_in_build = False
Tobias Henkel0ce7ec62017-07-21 22:50:17 +02001090 self.executor_server.release('project-test1')
1091 self.waitUntilSettled()
Tobias Henkel0f714002017-06-30 23:30:52 +02001092 self.executor_server.release()
1093 self.waitUntilSettled()
1094
Tobias Henkel0ce7ec62017-07-21 22:50:17 +02001095 self.assertHistory([
1096 dict(name='project-test2', result='ABORTED', changes='1,1'),
1097 dict(name='project-test1', result='SUCCESS', changes='1,2'),
1098 dict(name='project-test2', result='SUCCESS', changes='1,2')])
1099
James E. Blairff555742017-02-19 11:34:27 -08001100 def test_in_repo_branch(self):
1101 in_repo_conf = textwrap.dedent(
1102 """
1103 - job:
Tobias Henkelf02cf512017-07-21 22:55:34 +02001104 name: project-test1
1105
1106 - job:
James E. Blairff555742017-02-19 11:34:27 -08001107 name: project-test2
James E. Blair2f589fe2017-10-26 12:57:41 -07001108 run: playbooks/project-test2.yaml
James E. Blairff555742017-02-19 11:34:27 -08001109
1110 - project:
1111 name: org/project
1112 tenant-one-gate:
1113 jobs:
1114 - project-test2
1115 """)
1116
1117 in_repo_playbook = textwrap.dedent(
1118 """
1119 - hosts: all
1120 tasks: []
1121 """)
1122
1123 file_dict = {'.zuul.yaml': in_repo_conf,
1124 'playbooks/project-test2.yaml': in_repo_playbook}
1125 self.create_branch('org/project', 'stable')
James E. Blair72facdc2017-08-17 10:29:12 -07001126 self.fake_gerrit.addEvent(
1127 self.fake_gerrit.getFakeBranchCreatedEvent(
1128 'org/project', 'stable'))
James E. Blair6069f2b2017-09-26 16:34:11 -07001129 self.waitUntilSettled()
James E. Blairff555742017-02-19 11:34:27 -08001130 A = self.fake_gerrit.addFakeChange('org/project', 'stable', 'A',
1131 files=file_dict)
Tobias Henkelbf24fd12017-07-27 06:13:07 +02001132 A.addApproval('Code-Review', 2)
1133 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
James E. Blairff555742017-02-19 11:34:27 -08001134 self.waitUntilSettled()
1135 self.assertEqual(A.data['status'], 'MERGED')
1136 self.assertEqual(A.reported, 2,
1137 "A should report start and success")
1138 self.assertIn('tenant-one-gate', A.messages[1],
1139 "A should transit tenant-one gate")
1140 self.assertHistory([
1141 dict(name='project-test2', result='SUCCESS', changes='1,1')])
1142 self.fake_gerrit.addEvent(A.getChangeMergedEvent())
James E. Blair7bbd7a32017-03-06 11:36:13 -08001143 self.waitUntilSettled()
James E. Blairff555742017-02-19 11:34:27 -08001144
1145 # The config change should not affect master.
1146 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
Tobias Henkelbf24fd12017-07-27 06:13:07 +02001147 B.addApproval('Code-Review', 2)
1148 self.fake_gerrit.addEvent(B.addApproval('Approved', 1))
James E. Blairff555742017-02-19 11:34:27 -08001149 self.waitUntilSettled()
1150 self.assertHistory([
1151 dict(name='project-test2', result='SUCCESS', changes='1,1'),
1152 dict(name='project-test1', result='SUCCESS', changes='2,1')])
1153
1154 # The config change should be live for further changes on
1155 # stable.
1156 C = self.fake_gerrit.addFakeChange('org/project', 'stable', 'C')
Tobias Henkelbf24fd12017-07-27 06:13:07 +02001157 C.addApproval('Code-Review', 2)
1158 self.fake_gerrit.addEvent(C.addApproval('Approved', 1))
James E. Blairff555742017-02-19 11:34:27 -08001159 self.waitUntilSettled()
1160 self.assertHistory([
1161 dict(name='project-test2', result='SUCCESS', changes='1,1'),
1162 dict(name='project-test1', result='SUCCESS', changes='2,1'),
1163 dict(name='project-test2', result='SUCCESS', changes='3,1')])
1164
James E. Blaira5a12492017-05-03 11:40:48 -07001165 def test_crd_dynamic_config_branch(self):
1166 # Test that we can create a job in one repo and be able to use
1167 # it from a different branch on a different repo.
1168
1169 self.create_branch('org/project1', 'stable')
James E. Blair72facdc2017-08-17 10:29:12 -07001170 self.fake_gerrit.addEvent(
1171 self.fake_gerrit.getFakeBranchCreatedEvent(
1172 'org/project1', 'stable'))
James E. Blaira5a12492017-05-03 11:40:48 -07001173
1174 in_repo_conf = textwrap.dedent(
1175 """
1176 - job:
Tobias Henkelf02cf512017-07-21 22:55:34 +02001177 name: project-test1
1178
1179 - job:
James E. Blaira5a12492017-05-03 11:40:48 -07001180 name: project-test2
James E. Blair2f589fe2017-10-26 12:57:41 -07001181 run: playbooks/project-test2.yaml
James E. Blaira5a12492017-05-03 11:40:48 -07001182
1183 - project:
1184 name: org/project
1185 check:
1186 jobs:
1187 - project-test2
1188 """)
1189
1190 in_repo_playbook = textwrap.dedent(
1191 """
1192 - hosts: all
1193 tasks: []
1194 """)
1195
1196 file_dict = {'.zuul.yaml': in_repo_conf,
1197 'playbooks/project-test2.yaml': in_repo_playbook}
1198 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
1199 files=file_dict)
1200
1201 second_repo_conf = textwrap.dedent(
1202 """
1203 - project:
1204 name: org/project1
1205 check:
1206 jobs:
1207 - project-test2
1208 """)
1209
1210 second_file_dict = {'.zuul.yaml': second_repo_conf}
1211 B = self.fake_gerrit.addFakeChange('org/project1', 'stable', 'B',
1212 files=second_file_dict)
1213 B.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
1214 B.subject, A.data['id'])
1215
1216 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
1217 self.waitUntilSettled()
1218 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
1219 self.waitUntilSettled()
1220
1221 self.assertEqual(A.reported, 1, "A should report")
1222 self.assertHistory([
1223 dict(name='project-test2', result='SUCCESS', changes='1,1'),
1224 dict(name='project-test2', result='SUCCESS', changes='1,1 2,1'),
1225 ])
1226
James E. Blair97043882017-09-06 15:51:17 -07001227 def test_yaml_list_error(self):
1228 in_repo_conf = textwrap.dedent(
1229 """
1230 job: foo
1231 """)
1232
1233 file_dict = {'.zuul.yaml': in_repo_conf}
1234 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
1235 files=file_dict)
1236 A.addApproval('Code-Review', 2)
1237 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
1238 self.waitUntilSettled()
1239
1240 self.assertEqual(A.data['status'], 'NEW')
1241 self.assertEqual(A.reported, 1,
1242 "A should report failure")
1243 self.assertIn('not a list', A.messages[0],
1244 "A should have a syntax error reported")
1245
1246 def test_yaml_dict_error(self):
1247 in_repo_conf = textwrap.dedent(
1248 """
1249 - job
1250 """)
1251
1252 file_dict = {'.zuul.yaml': in_repo_conf}
1253 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
1254 files=file_dict)
1255 A.addApproval('Code-Review', 2)
1256 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
1257 self.waitUntilSettled()
1258
1259 self.assertEqual(A.data['status'], 'NEW')
1260 self.assertEqual(A.reported, 1,
1261 "A should report failure")
1262 self.assertIn('not a dictionary', A.messages[0],
1263 "A should have a syntax error reported")
1264
James E. Blairec953e12017-12-11 11:56:18 -08001265 def test_yaml_duplicate_key_error(self):
1266 in_repo_conf = textwrap.dedent(
1267 """
1268 - job:
1269 name: foo
1270 name: bar
1271 """)
1272
1273 file_dict = {'.zuul.yaml': in_repo_conf}
1274 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
1275 files=file_dict)
1276 A.addApproval('Code-Review', 2)
1277 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
1278 self.waitUntilSettled()
1279
1280 self.assertEqual(A.data['status'], 'NEW')
1281 self.assertEqual(A.reported, 1,
1282 "A should report failure")
1283 self.assertIn('appears more than once', A.messages[0],
1284 "A should have a syntax error reported")
1285
James E. Blair97043882017-09-06 15:51:17 -07001286 def test_yaml_key_error(self):
1287 in_repo_conf = textwrap.dedent(
1288 """
1289 - job:
1290 name: project-test2
1291 """)
1292
1293 file_dict = {'.zuul.yaml': in_repo_conf}
1294 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
1295 files=file_dict)
1296 A.addApproval('Code-Review', 2)
1297 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
1298 self.waitUntilSettled()
1299
1300 self.assertEqual(A.data['status'], 'NEW')
1301 self.assertEqual(A.reported, 1,
1302 "A should report failure")
1303 self.assertIn('has more than one key', A.messages[0],
1304 "A should have a syntax error reported")
1305
1306 def test_yaml_unknown_error(self):
1307 in_repo_conf = textwrap.dedent(
1308 """
1309 - foobar:
1310 foo: bar
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('not recognized', A.messages[0],
1324 "A should have a syntax error reported")
1325
James E. Blair149b69c2017-03-02 10:48:16 -08001326 def test_untrusted_syntax_error(self):
James E. Blaire53250c2017-03-01 14:34:36 -08001327 in_repo_conf = textwrap.dedent(
1328 """
1329 - job:
1330 name: project-test2
1331 foo: error
1332 """)
1333
1334 file_dict = {'.zuul.yaml': in_repo_conf}
1335 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
1336 files=file_dict)
Tobias Henkelbf24fd12017-07-27 06:13:07 +02001337 A.addApproval('Code-Review', 2)
1338 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
James E. Blaire53250c2017-03-01 14:34:36 -08001339 self.waitUntilSettled()
1340
1341 self.assertEqual(A.data['status'], 'NEW')
Tobias Henkel9842bd72017-05-16 13:40:03 +02001342 self.assertEqual(A.reported, 1,
1343 "A should report failure")
1344 self.assertIn('syntax error', A.messages[0],
James E. Blaire53250c2017-03-01 14:34:36 -08001345 "A should have a syntax error reported")
1346
James E. Blair149b69c2017-03-02 10:48:16 -08001347 def test_trusted_syntax_error(self):
1348 in_repo_conf = textwrap.dedent(
1349 """
1350 - job:
1351 name: project-test2
1352 foo: error
1353 """)
1354
1355 file_dict = {'zuul.yaml': in_repo_conf}
1356 A = self.fake_gerrit.addFakeChange('common-config', 'master', 'A',
1357 files=file_dict)
Tobias Henkelbf24fd12017-07-27 06:13:07 +02001358 A.addApproval('Code-Review', 2)
1359 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
James E. Blair149b69c2017-03-02 10:48:16 -08001360 self.waitUntilSettled()
1361
1362 self.assertEqual(A.data['status'], 'NEW')
Tobias Henkel9842bd72017-05-16 13:40:03 +02001363 self.assertEqual(A.reported, 1,
1364 "A should report failure")
1365 self.assertIn('syntax error', A.messages[0],
James E. Blair149b69c2017-03-02 10:48:16 -08001366 "A should have a syntax error reported")
1367
James E. Blair6f140c72017-03-03 10:32:07 -08001368 def test_untrusted_yaml_error(self):
1369 in_repo_conf = textwrap.dedent(
1370 """
1371 - job:
1372 foo: error
1373 """)
1374
1375 file_dict = {'.zuul.yaml': in_repo_conf}
1376 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
1377 files=file_dict)
Tobias Henkelbf24fd12017-07-27 06:13:07 +02001378 A.addApproval('Code-Review', 2)
1379 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
James E. Blair6f140c72017-03-03 10:32:07 -08001380 self.waitUntilSettled()
1381
1382 self.assertEqual(A.data['status'], 'NEW')
Tobias Henkel9842bd72017-05-16 13:40:03 +02001383 self.assertEqual(A.reported, 1,
1384 "A should report failure")
1385 self.assertIn('syntax error', A.messages[0],
James E. Blair6f140c72017-03-03 10:32:07 -08001386 "A should have a syntax error reported")
1387
James E. Blairdb04e6a2017-05-03 14:49:36 -07001388 def test_untrusted_shadow_error(self):
1389 in_repo_conf = textwrap.dedent(
1390 """
1391 - job:
1392 name: common-config-test
1393 """)
1394
1395 file_dict = {'.zuul.yaml': in_repo_conf}
1396 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
1397 files=file_dict)
Tobias Henkelbf24fd12017-07-27 06:13:07 +02001398 A.addApproval('Code-Review', 2)
1399 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
James E. Blairdb04e6a2017-05-03 14:49:36 -07001400 self.waitUntilSettled()
1401
1402 self.assertEqual(A.data['status'], 'NEW')
Tobias Henkel9842bd72017-05-16 13:40:03 +02001403 self.assertEqual(A.reported, 1,
1404 "A should report failure")
1405 self.assertIn('not permitted to shadow', A.messages[0],
James E. Blairdb04e6a2017-05-03 14:49:36 -07001406 "A should have a syntax error reported")
1407
James E. Blaird5656ad2017-06-02 14:29:41 -07001408 def test_untrusted_pipeline_error(self):
1409 in_repo_conf = textwrap.dedent(
1410 """
1411 - pipeline:
1412 name: test
1413 """)
1414
1415 file_dict = {'.zuul.yaml': in_repo_conf}
1416 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
1417 files=file_dict)
Tobias Henkelbf24fd12017-07-27 06:13:07 +02001418 A.addApproval('Code-Review', 2)
1419 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
James E. Blaird5656ad2017-06-02 14:29:41 -07001420 self.waitUntilSettled()
1421
1422 self.assertEqual(A.data['status'], 'NEW')
1423 self.assertEqual(A.reported, 1,
1424 "A should report failure")
1425 self.assertIn('Pipelines may not be defined', A.messages[0],
1426 "A should have a syntax error reported")
1427
1428 def test_untrusted_project_error(self):
1429 in_repo_conf = textwrap.dedent(
1430 """
1431 - project:
1432 name: org/project1
1433 """)
1434
1435 file_dict = {'.zuul.yaml': in_repo_conf}
1436 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
1437 files=file_dict)
Tobias Henkelbf24fd12017-07-27 06:13:07 +02001438 A.addApproval('Code-Review', 2)
1439 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
James E. Blaird5656ad2017-06-02 14:29:41 -07001440 self.waitUntilSettled()
1441
1442 self.assertEqual(A.data['status'], 'NEW')
1443 self.assertEqual(A.reported, 1,
1444 "A should report failure")
1445 self.assertIn('the only project definition permitted', A.messages[0],
1446 "A should have a syntax error reported")
1447
James E. Blairf03173b2017-10-10 10:46:43 -07001448 def test_untrusted_depends_on_trusted(self):
1449 with open(os.path.join(FIXTURE_DIR,
1450 'config/in-repo/git/',
1451 'common-config/zuul.yaml')) as f:
1452 common_config = f.read()
1453
1454 common_config += textwrap.dedent(
1455 """
1456 - job:
1457 name: project-test9
1458 """)
1459
1460 file_dict = {'zuul.yaml': common_config}
1461 A = self.fake_gerrit.addFakeChange('common-config', 'master', 'A',
1462 files=file_dict)
1463 in_repo_conf = textwrap.dedent(
1464 """
1465 - job:
1466 name: project-test1
1467 - project:
1468 name: org/project
1469 check:
1470 jobs:
1471 - project-test9
1472 """)
1473
1474 file_dict = {'zuul.yaml': in_repo_conf}
1475 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B',
1476 files=file_dict)
1477 B.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
1478 B.subject, A.data['id'])
1479 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
1480 self.waitUntilSettled()
1481
1482 self.assertEqual(B.data['status'], 'NEW')
1483 self.assertEqual(B.reported, 1,
1484 "B should report failure")
1485 self.assertIn('depends on a change to a config project',
1486 B.messages[0],
1487 "A should have a syntax error reported")
1488
James E. Blaire64b0e42017-06-08 11:23:34 -07001489 def test_duplicate_node_error(self):
1490 in_repo_conf = textwrap.dedent(
1491 """
1492 - nodeset:
1493 name: duplicate
1494 nodes:
1495 - name: compute
James E. Blair16d96a02017-06-08 11:32:56 -07001496 label: foo
James E. Blaire64b0e42017-06-08 11:23:34 -07001497 - name: compute
James E. Blair16d96a02017-06-08 11:32:56 -07001498 label: foo
James E. Blaire64b0e42017-06-08 11:23:34 -07001499 """)
1500
1501 file_dict = {'.zuul.yaml': in_repo_conf}
1502 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
1503 files=file_dict)
Tobias Henkelbf24fd12017-07-27 06:13:07 +02001504 A.addApproval('Code-Review', 2)
1505 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
James E. Blaire64b0e42017-06-08 11:23:34 -07001506 self.waitUntilSettled()
1507
1508 self.assertEqual(A.data['status'], 'NEW')
1509 self.assertEqual(A.reported, 1,
1510 "A should report failure")
1511 self.assertIn('appears multiple times', A.messages[0],
1512 "A should have a syntax error reported")
1513
1514 def test_duplicate_group_error(self):
1515 in_repo_conf = textwrap.dedent(
1516 """
1517 - nodeset:
1518 name: duplicate
1519 nodes:
1520 - name: compute
James E. Blair16d96a02017-06-08 11:32:56 -07001521 label: foo
James E. Blaire64b0e42017-06-08 11:23:34 -07001522 groups:
1523 - name: group
1524 nodes: compute
1525 - name: group
1526 nodes: compute
1527 """)
1528
1529 file_dict = {'.zuul.yaml': in_repo_conf}
1530 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
1531 files=file_dict)
Tobias Henkelbf24fd12017-07-27 06:13:07 +02001532 A.addApproval('Code-Review', 2)
1533 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
James E. Blaire64b0e42017-06-08 11:23:34 -07001534 self.waitUntilSettled()
1535
1536 self.assertEqual(A.data['status'], 'NEW')
1537 self.assertEqual(A.reported, 1,
1538 "A should report failure")
1539 self.assertIn('appears multiple times', A.messages[0],
1540 "A should have a syntax error reported")
1541
James E. Blair4ae399f2017-09-20 17:15:09 -07001542 def test_secret_not_found_error(self):
1543 in_repo_conf = textwrap.dedent(
1544 """
1545 - job:
1546 name: test
1547 secrets: does-not-exist
1548 """)
1549
1550 file_dict = {'.zuul.yaml': in_repo_conf}
1551 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
1552 files=file_dict)
1553 A.addApproval('Code-Review', 2)
1554 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
1555 self.waitUntilSettled()
1556
1557 self.assertEqual(A.data['status'], 'NEW')
1558 self.assertEqual(A.reported, 1,
1559 "A should report failure")
1560 self.assertIn('secret "does-not-exist" was not found', A.messages[0],
1561 "A should have a syntax error reported")
1562
1563 def test_nodeset_not_found_error(self):
1564 in_repo_conf = textwrap.dedent(
1565 """
1566 - job:
1567 name: test
1568 nodeset: does-not-exist
1569 """)
1570
1571 file_dict = {'.zuul.yaml': in_repo_conf}
1572 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
1573 files=file_dict)
1574 A.addApproval('Code-Review', 2)
1575 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
1576 self.waitUntilSettled()
1577
1578 self.assertEqual(A.data['status'], 'NEW')
1579 self.assertEqual(A.reported, 1,
1580 "A should report failure")
1581 self.assertIn('nodeset "does-not-exist" was not found', A.messages[0],
1582 "A should have a syntax error reported")
1583
James E. Blair89e25eb2017-09-26 09:11:31 -07001584 def test_template_not_found_error(self):
1585 in_repo_conf = textwrap.dedent(
1586 """
1587 - job:
1588 name: project-test1
1589 - project:
1590 name: org/project
1591 templates:
1592 - does-not-exist
1593 """)
1594
1595 file_dict = {'.zuul.yaml': in_repo_conf}
1596 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
1597 files=file_dict)
1598 A.addApproval('Code-Review', 2)
1599 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
1600 self.waitUntilSettled()
1601
1602 self.assertEqual(A.data['status'], 'NEW')
1603 self.assertEqual(A.reported, 1,
1604 "A should report failure")
1605 self.assertIn('project template "does-not-exist" was not found',
1606 A.messages[0],
1607 "A should have a syntax error reported")
1608
Monty Taylor8be3c0c2017-10-06 10:37:37 -05001609 def test_job_list_in_project_template_not_dict_error(self):
1610 in_repo_conf = textwrap.dedent(
1611 """
1612 - job:
1613 name: project-test1
1614 - project-template:
1615 name: some-jobs
1616 check:
1617 jobs:
1618 - project-test1:
1619 - required-projects:
1620 org/project2
1621 """)
1622
1623 file_dict = {'.zuul.yaml': in_repo_conf}
1624 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
1625 files=file_dict)
1626 A.addApproval('Code-Review', 2)
1627 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
1628 self.waitUntilSettled()
1629
1630 self.assertEqual(A.data['status'], 'NEW')
1631 self.assertEqual(A.reported, 1,
1632 "A should report failure")
1633 self.assertIn('expected str for dictionary value',
1634 A.messages[0], "A should have a syntax error reported")
1635
1636 def test_job_list_in_project_not_dict_error(self):
1637 in_repo_conf = textwrap.dedent(
1638 """
1639 - job:
1640 name: project-test1
1641 - project:
1642 name: org/project1
1643 check:
1644 jobs:
1645 - project-test1:
1646 - required-projects:
1647 org/project2
1648 """)
1649
1650 file_dict = {'.zuul.yaml': in_repo_conf}
1651 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
1652 files=file_dict)
1653 A.addApproval('Code-Review', 2)
1654 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
1655 self.waitUntilSettled()
1656
1657 self.assertEqual(A.data['status'], 'NEW')
1658 self.assertEqual(A.reported, 1,
1659 "A should report failure")
1660 self.assertIn('expected str for dictionary value',
1661 A.messages[0], "A should have a syntax error reported")
1662
James E. Blair1235f142017-10-07 09:11:43 -07001663 def test_project_template(self):
1664 # Tests that a project template is not modified when used, and
1665 # can therefore be used in subsequent reconfigurations.
1666 in_repo_conf = textwrap.dedent(
1667 """
1668 - job:
1669 name: project-test1
James E. Blair2f589fe2017-10-26 12:57:41 -07001670 run: playbooks/project-test1.yaml
James E. Blair1235f142017-10-07 09:11:43 -07001671 - project-template:
1672 name: some-jobs
1673 tenant-one-gate:
1674 jobs:
1675 - project-test1:
1676 required-projects:
1677 - org/project1
1678 - project:
1679 name: org/project
1680 templates:
1681 - some-jobs
1682 """)
1683
1684 file_dict = {'.zuul.yaml': in_repo_conf}
1685 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
1686 files=file_dict)
1687 A.addApproval('Code-Review', 2)
1688 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
1689 self.waitUntilSettled()
1690 self.assertEqual(A.data['status'], 'MERGED')
1691 self.fake_gerrit.addEvent(A.getChangeMergedEvent())
1692 self.waitUntilSettled()
1693 in_repo_conf = textwrap.dedent(
1694 """
1695 - project:
1696 name: org/project1
1697 templates:
1698 - some-jobs
1699 """)
1700 file_dict = {'.zuul.yaml': in_repo_conf}
1701 B = self.fake_gerrit.addFakeChange('org/project1', 'master', 'B',
1702 files=file_dict)
1703 B.addApproval('Code-Review', 2)
1704 self.fake_gerrit.addEvent(B.addApproval('Approved', 1))
1705 self.waitUntilSettled()
1706 self.assertEqual(B.data['status'], 'MERGED')
1707
James E. Blairbccdfcf2017-10-07 13:37:26 -07001708 def test_job_remove_add(self):
1709 # Tests that a job can be removed from one repo and added in another.
1710 # First, remove the current config for project1 since it
1711 # references the job we want to remove.
1712 file_dict = {'.zuul.yaml': None}
1713 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A',
1714 files=file_dict)
1715 A.setMerged()
1716 self.fake_gerrit.addEvent(A.getChangeMergedEvent())
1717 self.waitUntilSettled()
1718 # Then propose a change to delete the job from one repo...
1719 file_dict = {'.zuul.yaml': None}
1720 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B',
1721 files=file_dict)
1722 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
1723 self.waitUntilSettled()
1724 # ...and a second that depends on it that adds it to another repo.
1725 in_repo_conf = textwrap.dedent(
1726 """
1727 - job:
1728 name: project-test1
James E. Blair2f589fe2017-10-26 12:57:41 -07001729 run: playbooks/project-test1.yaml
James E. Blairbccdfcf2017-10-07 13:37:26 -07001730
1731 - project:
1732 name: org/project1
1733 check:
1734 jobs:
1735 - project-test1
1736 """)
1737 in_repo_playbook = textwrap.dedent(
1738 """
1739 - hosts: all
1740 tasks: []
1741 """)
1742 file_dict = {'.zuul.yaml': in_repo_conf,
1743 'playbooks/project-test1.yaml': in_repo_playbook}
1744 C = self.fake_gerrit.addFakeChange('org/project1', 'master', 'C',
1745 files=file_dict,
1746 parent='refs/changes/1/1/1')
1747 C.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
1748 C.subject, B.data['id'])
1749 self.fake_gerrit.addEvent(C.getPatchsetCreatedEvent(1))
1750 self.waitUntilSettled()
1751 self.assertHistory([
1752 dict(name='project-test1', result='SUCCESS', changes='2,1 3,1'),
1753 ], ordered=False)
1754
James E. Blair09f9ffe2017-07-11 15:30:25 -07001755 def test_multi_repo(self):
1756 downstream_repo_conf = textwrap.dedent(
1757 """
1758 - project:
1759 name: org/project1
1760 tenant-one-gate:
1761 jobs:
1762 - project-test1
1763
1764 - job:
1765 name: project1-test1
1766 parent: project-test1
1767 """)
1768
1769 file_dict = {'.zuul.yaml': downstream_repo_conf}
1770 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A',
1771 files=file_dict)
Tobias Henkelbf24fd12017-07-27 06:13:07 +02001772 A.addApproval('Code-Review', 2)
1773 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
James E. Blair09f9ffe2017-07-11 15:30:25 -07001774 self.waitUntilSettled()
1775
1776 self.assertEqual(A.data['status'], 'MERGED')
1777 self.fake_gerrit.addEvent(A.getChangeMergedEvent())
1778 self.waitUntilSettled()
1779
1780 upstream_repo_conf = textwrap.dedent(
1781 """
1782 - job:
1783 name: project-test1
James E. Blair2f589fe2017-10-26 12:57:41 -07001784 run: playbooks/project-test1.yaml
James E. Blair09f9ffe2017-07-11 15:30:25 -07001785
1786 - job:
1787 name: project-test2
1788
1789 - project:
1790 name: org/project
1791 tenant-one-gate:
1792 jobs:
1793 - project-test1
1794 """)
1795
1796 file_dict = {'.zuul.yaml': upstream_repo_conf}
1797 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B',
1798 files=file_dict)
Tobias Henkelbf24fd12017-07-27 06:13:07 +02001799 B.addApproval('Code-Review', 2)
1800 self.fake_gerrit.addEvent(B.addApproval('Approved', 1))
James E. Blair09f9ffe2017-07-11 15:30:25 -07001801 self.waitUntilSettled()
1802
1803 self.assertEqual(B.data['status'], 'MERGED')
1804 self.fake_gerrit.addEvent(B.getChangeMergedEvent())
1805 self.waitUntilSettled()
1806
1807 tenant = self.sched.abide.tenants.get('tenant-one')
1808 # Ensure the latest change is reflected in the config; if it
1809 # isn't this will raise an exception.
1810 tenant.layout.getJob('project-test2')
1811
James E. Blair332636e2017-09-05 10:14:35 -07001812 def test_pipeline_error(self):
1813 with open(os.path.join(FIXTURE_DIR,
1814 'config/in-repo/git/',
1815 'common-config/zuul.yaml')) as f:
1816 base_common_config = f.read()
1817
1818 in_repo_conf_A = textwrap.dedent(
1819 """
1820 - pipeline:
1821 name: periodic
1822 foo: error
1823 """)
1824
1825 file_dict = {'zuul.yaml': None,
1826 'zuul.d/main.yaml': base_common_config,
1827 'zuul.d/test1.yaml': in_repo_conf_A}
1828 A = self.fake_gerrit.addFakeChange('common-config', 'master', 'A',
1829 files=file_dict)
1830 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
1831 self.waitUntilSettled()
1832 self.assertEqual(A.reported, 1,
1833 "A should report failure")
1834 self.assertIn('syntax error',
1835 A.messages[0],
1836 "A should have an error reported")
1837
1838 def test_change_series_error(self):
1839 with open(os.path.join(FIXTURE_DIR,
1840 'config/in-repo/git/',
1841 'common-config/zuul.yaml')) as f:
1842 base_common_config = f.read()
1843
1844 in_repo_conf_A = textwrap.dedent(
1845 """
1846 - pipeline:
1847 name: periodic
1848 foo: error
1849 """)
1850
1851 file_dict = {'zuul.yaml': None,
1852 'zuul.d/main.yaml': base_common_config,
1853 'zuul.d/test1.yaml': in_repo_conf_A}
1854 A = self.fake_gerrit.addFakeChange('common-config', 'master', 'A',
1855 files=file_dict)
1856
1857 in_repo_conf_B = textwrap.dedent(
1858 """
1859 - job:
1860 name: project-test2
1861 foo: error
1862 """)
1863
1864 file_dict = {'zuul.yaml': None,
1865 'zuul.d/main.yaml': base_common_config,
1866 'zuul.d/test1.yaml': in_repo_conf_A,
1867 'zuul.d/test2.yaml': in_repo_conf_B}
1868 B = self.fake_gerrit.addFakeChange('common-config', 'master', 'B',
1869 files=file_dict)
1870 B.setDependsOn(A, 1)
1871 C = self.fake_gerrit.addFakeChange('common-config', 'master', 'C')
1872 C.setDependsOn(B, 1)
1873 self.fake_gerrit.addEvent(C.getPatchsetCreatedEvent(1))
1874 self.waitUntilSettled()
1875
1876 self.assertEqual(C.reported, 1,
1877 "C should report failure")
1878 self.assertIn('depends on a change that failed to merge',
1879 C.messages[0],
1880 "C should have an error reported")
1881
James E. Blair1ef8f7c2017-12-13 17:18:34 -08001882 def test_pipeline_debug(self):
1883 in_repo_conf = textwrap.dedent(
1884 """
1885 - job:
1886 name: project-test1
1887 run: playbooks/project-test1.yaml
1888 - project:
1889 name: org/project
1890 check:
1891 debug: True
1892 jobs:
1893 - project-test1
1894 """)
1895
1896 file_dict = {'.zuul.yaml': in_repo_conf}
1897 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
1898 files=file_dict)
1899 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
1900 self.waitUntilSettled()
1901
1902 self.assertEqual(A.data['status'], 'NEW')
1903 self.assertEqual(A.reported, 1,
1904 "A should report success")
1905 self.assertIn('Debug information:',
1906 A.messages[0], "A should have debug info")
1907
James E. Blairc73c73a2017-01-20 15:15:15 -08001908
James E. Blairc9455002017-09-06 09:22:19 -07001909class TestInRepoJoin(ZuulTestCase):
1910 # In this config, org/project is not a member of any pipelines, so
1911 # that we may test the changes that cause it to join them.
1912
1913 tenant_config_file = 'config/in-repo-join/main.yaml'
1914
1915 def test_dynamic_dependent_pipeline(self):
1916 # Test dynamically adding a project to a
1917 # dependent pipeline for the first time
1918 self.executor_server.hold_jobs_in_build = True
1919
1920 tenant = self.sched.abide.tenants.get('tenant-one')
1921 gate_pipeline = tenant.layout.pipelines['gate']
1922
1923 in_repo_conf = textwrap.dedent(
1924 """
1925 - job:
1926 name: project-test1
James E. Blair2f589fe2017-10-26 12:57:41 -07001927 run: playbooks/project-test1.yaml
James E. Blairc9455002017-09-06 09:22:19 -07001928
1929 - job:
1930 name: project-test2
James E. Blair2f589fe2017-10-26 12:57:41 -07001931 run: playbooks/project-test2.yaml
James E. Blairc9455002017-09-06 09:22:19 -07001932
1933 - project:
1934 name: org/project
1935 gate:
1936 jobs:
1937 - project-test2
1938 """)
1939
1940 in_repo_playbook = textwrap.dedent(
1941 """
1942 - hosts: all
1943 tasks: []
1944 """)
1945
1946 file_dict = {'.zuul.yaml': in_repo_conf,
1947 'playbooks/project-test2.yaml': in_repo_playbook}
1948 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
1949 files=file_dict)
1950 A.addApproval('Code-Review', 2)
1951 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
1952 self.waitUntilSettled()
1953
1954 items = gate_pipeline.getAllItems()
1955 self.assertEqual(items[0].change.number, '1')
1956 self.assertEqual(items[0].change.patchset, '1')
1957 self.assertTrue(items[0].live)
1958
1959 self.executor_server.hold_jobs_in_build = False
1960 self.executor_server.release()
1961 self.waitUntilSettled()
1962
1963 # Make sure the dynamic queue got cleaned up
1964 self.assertEqual(gate_pipeline.queues, [])
1965
1966 def test_dynamic_dependent_pipeline_failure(self):
1967 # Test that a change behind a failing change adding a project
1968 # to a dependent pipeline is dequeued.
1969 self.executor_server.hold_jobs_in_build = True
1970
1971 in_repo_conf = textwrap.dedent(
1972 """
1973 - job:
1974 name: project-test1
James E. Blair2f589fe2017-10-26 12:57:41 -07001975 run: playbooks/project-test1.yaml
James E. Blairc9455002017-09-06 09:22:19 -07001976
1977 - project:
1978 name: org/project
1979 gate:
1980 jobs:
1981 - project-test1
1982 """)
1983
1984 file_dict = {'.zuul.yaml': in_repo_conf}
1985 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
1986 files=file_dict)
1987 self.executor_server.failJob('project-test1', A)
1988 A.addApproval('Code-Review', 2)
1989 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
1990 self.waitUntilSettled()
1991
1992 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
1993 B.addApproval('Code-Review', 2)
1994 self.fake_gerrit.addEvent(B.addApproval('Approved', 1))
1995 self.waitUntilSettled()
1996
James E. Blair3490c5d2017-09-07 08:33:23 -07001997 self.orderedRelease()
James E. Blairc9455002017-09-06 09:22:19 -07001998 self.waitUntilSettled()
1999 self.assertEqual(A.reported, 2,
2000 "A should report start and failure")
2001 self.assertEqual(A.data['status'], 'NEW')
2002 self.assertEqual(B.reported, 1,
2003 "B should report start")
2004 self.assertHistory([
2005 dict(name='project-test1', result='FAILURE', changes='1,1'),
James E. Blair3490c5d2017-09-07 08:33:23 -07002006 dict(name='project-test1', result='ABORTED', changes='1,1 2,1'),
James E. Blairc9455002017-09-06 09:22:19 -07002007 ], ordered=False)
2008
James E. Blair0af198f2017-09-06 09:52:35 -07002009 def test_dynamic_dependent_pipeline_absent(self):
2010 # Test that a series of dependent changes don't report merge
2011 # failures to a pipeline they aren't in.
2012 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2013 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
2014 B.setDependsOn(A, 1)
2015
2016 A.addApproval('Code-Review', 2)
2017 A.addApproval('Approved', 1)
2018 B.addApproval('Code-Review', 2)
2019 self.fake_gerrit.addEvent(B.addApproval('Approved', 1))
2020 self.waitUntilSettled()
2021 self.assertEqual(A.reported, 0,
2022 "A should not report")
2023 self.assertEqual(A.data['status'], 'NEW')
2024 self.assertEqual(B.reported, 0,
2025 "B should not report")
2026 self.assertEqual(B.data['status'], 'NEW')
2027 self.assertHistory([])
2028
James E. Blairc9455002017-09-06 09:22:19 -07002029
James E. Blairc73c73a2017-01-20 15:15:15 -08002030class TestAnsible(AnsibleZuulTestCase):
2031 # A temporary class to hold new tests while others are disabled
2032
2033 tenant_config_file = 'config/ansible/main.yaml'
2034
2035 def test_playbook(self):
James E. Blair73d421b2018-02-19 10:54:25 -08002036 # This test runs a bit long and needs extra time.
2037 self.wait_timeout = 120
Jamie Lennox7655b552017-03-17 12:33:38 +11002038 # Keep the jobdir around so we can inspect contents if an
2039 # assert fails.
2040 self.executor_server.keep_jobdir = True
2041 # Output extra ansible info so we might see errors.
2042 self.executor_server.verbose = True
2043 # Add a site variables file, used by check-vars
2044 path = os.path.join(FIXTURE_DIR, 'config', 'ansible',
2045 'variables.yaml')
2046 self.config.set('executor', 'variables', path)
James E. Blairc73c73a2017-01-20 15:15:15 -08002047 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2048 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2049 self.waitUntilSettled()
Tobias Henkel077f2f32017-05-30 20:16:46 +02002050 build_timeout = self.getJobFromHistory('timeout')
Jamie Lennox7655b552017-03-17 12:33:38 +11002051 with self.jobLog(build_timeout):
2052 self.assertEqual(build_timeout.result, 'TIMED_OUT')
Clark Boylanb2c22b32018-02-16 11:00:50 -08002053 post_flag_path = os.path.join(self.test_root, build_timeout.uuid +
2054 '.post.flag')
2055 self.assertTrue(os.path.exists(post_flag_path))
2056 build_post_timeout = self.getJobFromHistory('post-timeout')
2057 with self.jobLog(build_post_timeout):
2058 self.assertEqual(build_post_timeout.result, 'POST_FAILURE')
Tobias Henkel077f2f32017-05-30 20:16:46 +02002059 build_faillocal = self.getJobFromHistory('faillocal')
Jamie Lennox7655b552017-03-17 12:33:38 +11002060 with self.jobLog(build_faillocal):
2061 self.assertEqual(build_faillocal.result, 'FAILURE')
Tobias Henkel077f2f32017-05-30 20:16:46 +02002062 build_failpost = self.getJobFromHistory('failpost')
Jamie Lennox7655b552017-03-17 12:33:38 +11002063 with self.jobLog(build_failpost):
2064 self.assertEqual(build_failpost.result, 'POST_FAILURE')
Tobias Henkel077f2f32017-05-30 20:16:46 +02002065 build_check_vars = self.getJobFromHistory('check-vars')
Jamie Lennox7655b552017-03-17 12:33:38 +11002066 with self.jobLog(build_check_vars):
2067 self.assertEqual(build_check_vars.result, 'SUCCESS')
Monty Tayloraff8b402017-08-16 18:40:41 -05002068 build_check_secret_names = self.getJobFromHistory('check-secret-names')
2069 with self.jobLog(build_check_secret_names):
2070 self.assertEqual(build_check_secret_names.result, 'SUCCESS')
Tobias Henkel077f2f32017-05-30 20:16:46 +02002071 build_hello = self.getJobFromHistory('hello-world')
Jamie Lennox7655b552017-03-17 12:33:38 +11002072 with self.jobLog(build_hello):
2073 self.assertEqual(build_hello.result, 'SUCCESS')
Tobias Henkel077f2f32017-05-30 20:16:46 +02002074 build_python27 = self.getJobFromHistory('python27')
Jamie Lennox7655b552017-03-17 12:33:38 +11002075 with self.jobLog(build_python27):
2076 self.assertEqual(build_python27.result, 'SUCCESS')
2077 flag_path = os.path.join(self.test_root,
2078 build_python27.uuid + '.flag')
2079 self.assertTrue(os.path.exists(flag_path))
2080 copied_path = os.path.join(self.test_root, build_python27.uuid +
2081 '.copied')
2082 self.assertTrue(os.path.exists(copied_path))
2083 failed_path = os.path.join(self.test_root, build_python27.uuid +
2084 '.failed')
2085 self.assertFalse(os.path.exists(failed_path))
2086 pre_flag_path = os.path.join(self.test_root, build_python27.uuid +
2087 '.pre.flag')
2088 self.assertTrue(os.path.exists(pre_flag_path))
2089 post_flag_path = os.path.join(self.test_root, build_python27.uuid +
2090 '.post.flag')
2091 self.assertTrue(os.path.exists(post_flag_path))
2092 bare_role_flag_path = os.path.join(self.test_root,
2093 build_python27.uuid +
2094 '.bare-role.flag')
2095 self.assertTrue(os.path.exists(bare_role_flag_path))
2096 secrets_path = os.path.join(self.test_root,
2097 build_python27.uuid + '.secrets')
2098 with open(secrets_path) as f:
2099 self.assertEqual(f.read(), "test-username test-password")
James E. Blairb9c0d772017-03-03 14:34:49 -08002100
Jamie Lennox7655b552017-03-17 12:33:38 +11002101 msg = A.messages[0]
2102 success = "{} https://success.example.com/zuul-logs/{}"
2103 fail = "{} https://failure.example.com/zuul-logs/{}"
2104 self.assertIn(success.format("python27", build_python27.uuid), msg)
2105 self.assertIn(fail.format("faillocal", build_faillocal.uuid), msg)
2106 self.assertIn(success.format("check-vars",
2107 build_check_vars.uuid), msg)
2108 self.assertIn(success.format("hello-world", build_hello.uuid), msg)
2109 self.assertIn(fail.format("timeout", build_timeout.uuid), msg)
2110 self.assertIn(fail.format("failpost", build_failpost.uuid), msg)
Tobias Henkel077f2f32017-05-30 20:16:46 +02002111
James E. Blairabbaa6f2017-04-06 16:11:44 -07002112 def _add_job(self, job_name):
2113 conf = textwrap.dedent(
2114 """
2115 - job:
2116 name: %s
James E. Blair2f589fe2017-10-26 12:57:41 -07002117 run: playbooks/%s.yaml
James E. Blairabbaa6f2017-04-06 16:11:44 -07002118
2119 - project:
2120 name: org/plugin-project
2121 check:
2122 jobs:
2123 - %s
James E. Blair2f589fe2017-10-26 12:57:41 -07002124 """ % (job_name, job_name, job_name))
James E. Blairabbaa6f2017-04-06 16:11:44 -07002125
2126 file_dict = {'.zuul.yaml': conf}
2127 A = self.fake_gerrit.addFakeChange('org/plugin-project', 'master', 'A',
2128 files=file_dict)
2129 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2130 self.waitUntilSettled()
2131
2132 def test_plugins(self):
2133 # Keep the jobdir around so we can inspect contents if an
2134 # assert fails.
2135 self.executor_server.keep_jobdir = True
2136 # Output extra ansible info so we might see errors.
2137 self.executor_server.verbose = True
2138
2139 count = 0
2140 plugin_tests = [
2141 ('passwd', 'FAILURE'),
2142 ('cartesian', 'SUCCESS'),
2143 ('consul_kv', 'FAILURE'),
2144 ('credstash', 'FAILURE'),
2145 ('csvfile_good', 'SUCCESS'),
2146 ('csvfile_bad', 'FAILURE'),
Monty Taylor93ad2212017-08-02 14:59:50 -05002147 ('uri_bad_path', 'FAILURE'),
2148 ('uri_bad_scheme', 'FAILURE'),
Monty Taylor788a40e2017-08-02 16:14:05 -05002149 ('block_local_override', 'FAILURE'),
Monty Taylor8da768f2017-08-31 14:15:35 -05002150 ('file_local_good', 'SUCCESS'),
2151 ('file_local_bad', 'FAILURE'),
James E. Blairabbaa6f2017-04-06 16:11:44 -07002152 ]
2153 for job_name, result in plugin_tests:
2154 count += 1
2155 self._add_job(job_name)
2156
2157 job = self.getJobFromHistory(job_name)
2158 with self.jobLog(job):
2159 self.assertEqual(count, len(self.history))
2160 build = self.history[-1]
2161 self.assertEqual(build.result, result)
2162
2163 # TODOv3(jeblair): parse the ansible output and verify we're
2164 # getting the exception we expect.
2165
James E. Blairb9c0d772017-03-03 14:34:49 -08002166
James E. Blaira4d4eef2017-06-30 14:49:17 -07002167class TestPrePlaybooks(AnsibleZuulTestCase):
2168 # A temporary class to hold new tests while others are disabled
2169
2170 tenant_config_file = 'config/pre-playbook/main.yaml'
2171
2172 def test_pre_playbook_fail(self):
2173 # Test that we run the post playbooks (but not the actual
2174 # playbook) when a pre-playbook fails.
2175 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2176 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2177 self.waitUntilSettled()
2178 build = self.getJobFromHistory('python27')
2179 self.assertIsNone(build.result)
2180 self.assertIn('RETRY_LIMIT', A.messages[0])
2181 flag_path = os.path.join(self.test_root, build.uuid +
2182 '.main.flag')
2183 self.assertFalse(os.path.exists(flag_path))
2184 pre_flag_path = os.path.join(self.test_root, build.uuid +
2185 '.pre.flag')
2186 self.assertFalse(os.path.exists(pre_flag_path))
2187 post_flag_path = os.path.join(self.test_root, build.uuid +
2188 '.post.flag')
James E. Blair21037782017-07-19 11:56:55 -07002189 self.assertTrue(os.path.exists(post_flag_path),
2190 "The file %s should exist" % post_flag_path)
James E. Blaira4d4eef2017-06-30 14:49:17 -07002191
2192
James E. Blairbacbb882017-10-17 09:48:23 -07002193class TestPostPlaybooks(AnsibleZuulTestCase):
2194 tenant_config_file = 'config/post-playbook/main.yaml'
2195
2196 def test_post_playbook_abort(self):
2197 # Test that when we abort a job in the post playbook, that we
2198 # don't send back POST_FAILURE.
2199 self.executor_server.verbose = True
2200 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2201 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2202
2203 while not len(self.builds):
2204 time.sleep(0.1)
2205 build = self.builds[0]
2206
2207 post_start = os.path.join(self.test_root, build.uuid +
2208 '.post_start.flag')
2209 start = time.time()
2210 while time.time() < start + 90:
2211 if os.path.exists(post_start):
2212 break
2213 time.sleep(0.1)
2214 # The post playbook has started, abort the job
2215 self.fake_gerrit.addEvent(A.getChangeAbandonedEvent())
2216 self.waitUntilSettled()
2217
2218 build = self.getJobFromHistory('python27')
2219 self.assertEqual('ABORTED', build.result)
2220
2221 post_end = os.path.join(self.test_root, build.uuid +
2222 '.post_end.flag')
2223 self.assertTrue(os.path.exists(post_start))
2224 self.assertFalse(os.path.exists(post_end))
2225
2226
James E. Blairb9c0d772017-03-03 14:34:49 -08002227class TestBrokenConfig(ZuulTestCase):
2228 # Test that we get an appropriate syntax error if we start with a
2229 # broken config.
2230
2231 tenant_config_file = 'config/broken/main.yaml'
2232
2233 def setUp(self):
2234 with testtools.ExpectedException(
2235 zuul.configloader.ConfigurationSyntaxError,
2236 "\nZuul encountered a syntax error"):
2237 super(TestBrokenConfig, self).setUp()
2238
2239 def test_broken_config_on_startup(self):
2240 pass
Ricardo Carrillo Cruz22994f92016-12-02 11:41:58 +00002241
2242
2243class TestProjectKeys(ZuulTestCase):
2244 # Test that we can generate project keys
2245
2246 # Normally the test infrastructure copies a static key in place
2247 # for each project before starting tests. This saves time because
2248 # Zuul's automatic key-generation on startup can be slow. To make
2249 # sure we exercise that code, in this test we allow Zuul to create
2250 # keys for the project on startup.
2251 create_project_keys = True
Tobias Henkelabf973e2017-07-28 10:07:34 +02002252 config_file = 'zuul-connections-gerrit-and-github.conf'
Ricardo Carrillo Cruz22994f92016-12-02 11:41:58 +00002253 tenant_config_file = 'config/in-repo/main.yaml'
2254
2255 def test_key_generation(self):
2256 key_root = os.path.join(self.state_root, 'keys')
2257 private_key_file = os.path.join(key_root, 'gerrit/org/project.pem')
2258 # Make sure that a proper key was created on startup
2259 with open(private_key_file, "rb") as f:
James E. Blairbf1a4f22017-03-17 10:59:37 -07002260 private_key, public_key = \
2261 encryption.deserialize_rsa_keypair(f.read())
Ricardo Carrillo Cruz22994f92016-12-02 11:41:58 +00002262
2263 with open(os.path.join(FIXTURE_DIR, 'private.pem')) as i:
2264 fixture_private_key = i.read()
2265
2266 # Make sure that we didn't just end up with the static fixture
2267 # key
2268 self.assertNotEqual(fixture_private_key, private_key)
2269
2270 # Make sure it's the right length
2271 self.assertEqual(4096, private_key.key_size)
James E. Blairbce76932017-05-04 10:03:15 -07002272
2273
James E. Blairbb94dfa2017-07-11 07:45:19 -07002274class RoleTestCase(ZuulTestCase):
James E. Blair1b27f6a2017-07-14 14:09:07 -07002275 def _assertRolePath(self, build, playbook, content):
2276 path = os.path.join(self.test_root, build.uuid,
2277 'ansible', playbook, 'ansible.cfg')
2278 roles_paths = []
2279 with open(path) as f:
2280 for line in f:
2281 if line.startswith('roles_path'):
2282 roles_paths.append(line)
2283 print(roles_paths)
2284 if content:
2285 self.assertEqual(len(roles_paths), 1,
2286 "Should have one roles_path line in %s" %
2287 (playbook,))
2288 self.assertIn(content, roles_paths[0])
2289 else:
2290 self.assertEqual(len(roles_paths), 0,
2291 "Should have no roles_path line in %s" %
2292 (playbook,))
2293
James E. Blairbb94dfa2017-07-11 07:45:19 -07002294
2295class TestRoles(RoleTestCase):
2296 tenant_config_file = 'config/roles/main.yaml'
2297
James E. Blairbce76932017-05-04 10:03:15 -07002298 def test_role(self):
2299 # This exercises a proposed change to a role being checked out
2300 # and used.
2301 A = self.fake_gerrit.addFakeChange('bare-role', 'master', 'A')
2302 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2303 B.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
2304 B.subject, A.data['id'])
2305 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2306 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
2307 self.waitUntilSettled()
2308 self.assertHistory([
2309 dict(name='project-test', result='SUCCESS', changes='1,1 2,1'),
2310 ])
James E. Blair6459db12017-06-29 14:57:20 -07002311
James E. Blair1b27f6a2017-07-14 14:09:07 -07002312 def test_role_inheritance(self):
2313 self.executor_server.hold_jobs_in_build = True
2314 conf = textwrap.dedent(
2315 """
2316 - job:
2317 name: parent
2318 roles:
2319 - zuul: bare-role
Ian Wienand548c43c2017-12-05 14:16:32 +11002320 pre-run: playbooks/parent-pre.yaml
2321 post-run: playbooks/parent-post.yaml
James E. Blair1b27f6a2017-07-14 14:09:07 -07002322
2323 - job:
2324 name: project-test
2325 parent: parent
James E. Blair2f589fe2017-10-26 12:57:41 -07002326 run: playbooks/project-test.yaml
James E. Blair1b27f6a2017-07-14 14:09:07 -07002327 roles:
2328 - zuul: org/project
2329
2330 - project:
2331 name: org/project
2332 check:
2333 jobs:
2334 - project-test
2335 """)
2336
2337 file_dict = {'.zuul.yaml': conf}
2338 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
2339 files=file_dict)
2340 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2341 self.waitUntilSettled()
2342
2343 self.assertEqual(len(self.builds), 1)
2344 build = self.getBuildByName('project-test')
2345 self._assertRolePath(build, 'pre_playbook_0', 'role_0')
2346 self._assertRolePath(build, 'playbook_0', 'role_0')
2347 self._assertRolePath(build, 'playbook_0', 'role_1')
2348 self._assertRolePath(build, 'post_playbook_0', 'role_0')
2349
2350 self.executor_server.hold_jobs_in_build = False
2351 self.executor_server.release()
2352 self.waitUntilSettled()
2353
2354 self.assertHistory([
2355 dict(name='project-test', result='SUCCESS', changes='1,1'),
2356 ])
2357
James E. Blair6f699732017-07-18 14:19:11 -07002358 def test_role_error(self):
2359 conf = textwrap.dedent(
2360 """
2361 - job:
2362 name: project-test
James E. Blair2f589fe2017-10-26 12:57:41 -07002363 run: playbooks/project-test.yaml
James E. Blair6f699732017-07-18 14:19:11 -07002364 roles:
2365 - zuul: common-config
2366
2367 - project:
2368 name: org/project
2369 check:
2370 jobs:
2371 - project-test
2372 """)
2373
2374 file_dict = {'.zuul.yaml': conf}
2375 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
2376 files=file_dict)
2377 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2378 self.waitUntilSettled()
2379 self.assertIn(
2380 '- project-test project-test : ERROR Unable to find role',
2381 A.messages[-1])
2382
James E. Blair6459db12017-06-29 14:57:20 -07002383
James E. Blairbb94dfa2017-07-11 07:45:19 -07002384class TestImplicitRoles(RoleTestCase):
2385 tenant_config_file = 'config/implicit-roles/main.yaml'
2386
2387 def test_missing_roles(self):
2388 # Test implicit and explicit roles for a project which does
2389 # not have roles. The implicit role should be silently
2390 # ignored since the project doesn't supply roles, but if a
2391 # user declares an explicit role, it should error.
2392 self.executor_server.hold_jobs_in_build = True
2393 A = self.fake_gerrit.addFakeChange('org/norole-project', 'master', 'A')
2394 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2395 self.waitUntilSettled()
2396
2397 self.assertEqual(len(self.builds), 2)
2398 build = self.getBuildByName('implicit-role-fail')
2399 self._assertRolePath(build, 'playbook_0', None)
2400
2401 self.executor_server.hold_jobs_in_build = False
2402 self.executor_server.release()
2403 self.waitUntilSettled()
2404 # The retry_limit doesn't get recorded
2405 self.assertHistory([
2406 dict(name='implicit-role-fail', result='SUCCESS', changes='1,1'),
2407 ])
2408
2409 def test_roles(self):
2410 # Test implicit and explicit roles for a project which does
2411 # have roles. In both cases, we should end up with the role
2412 # in the path. In the explicit case, ensure we end up with
2413 # the name we specified.
2414 self.executor_server.hold_jobs_in_build = True
2415 A = self.fake_gerrit.addFakeChange('org/role-project', 'master', 'A')
2416 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2417 self.waitUntilSettled()
2418
2419 self.assertEqual(len(self.builds), 2)
2420 build = self.getBuildByName('implicit-role-ok')
2421 self._assertRolePath(build, 'playbook_0', 'role_0')
2422
2423 build = self.getBuildByName('explicit-role-ok')
2424 self._assertRolePath(build, 'playbook_0', 'role_0')
2425
2426 self.executor_server.hold_jobs_in_build = False
2427 self.executor_server.release()
2428 self.waitUntilSettled()
2429 self.assertHistory([
2430 dict(name='implicit-role-ok', result='SUCCESS', changes='1,1'),
2431 dict(name='explicit-role-ok', result='SUCCESS', changes='1,1'),
2432 ], ordered=False)
2433
2434
James E. Blair6459db12017-06-29 14:57:20 -07002435class TestShadow(ZuulTestCase):
2436 tenant_config_file = 'config/shadow/main.yaml'
2437
2438 def test_shadow(self):
2439 # Test that a repo is allowed to shadow another's job definitions.
2440 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2441 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2442 self.waitUntilSettled()
2443 self.assertHistory([
2444 dict(name='test1', result='SUCCESS', changes='1,1'),
2445 dict(name='test2', result='SUCCESS', changes='1,1'),
James E. Blairadafa6c2017-07-12 08:50:56 -07002446 ], ordered=False)
James E. Blair196f61a2017-06-30 15:42:29 -07002447
2448
2449class TestDataReturn(AnsibleZuulTestCase):
2450 tenant_config_file = 'config/data-return/main.yaml'
2451
2452 def test_data_return(self):
James E. Blair196f61a2017-06-30 15:42:29 -07002453 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2454 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2455 self.waitUntilSettled()
2456 self.assertHistory([
2457 dict(name='data-return', result='SUCCESS', changes='1,1'),
James E. Blair88e79c02017-07-07 13:36:54 -07002458 dict(name='data-return-relative', result='SUCCESS', changes='1,1'),
James E. Blair698703c2017-09-15 20:58:30 -06002459 dict(name='child', result='SUCCESS', changes='1,1'),
James E. Blair88e79c02017-07-07 13:36:54 -07002460 ], ordered=False)
2461 self.assertIn('- data-return http://example.com/test/log/url/',
2462 A.messages[-1])
2463 self.assertIn('- data-return-relative '
2464 'http://example.com/test/log/url/docs/index.html',
James E. Blair196f61a2017-06-30 15:42:29 -07002465 A.messages[-1])
Clint Byrumdc8a0902017-07-20 16:36:27 -07002466
2467
2468class TestDiskAccounting(AnsibleZuulTestCase):
2469 config_file = 'zuul-disk-accounting.conf'
2470 tenant_config_file = 'config/disk-accountant/main.yaml'
2471
2472 def test_disk_accountant_kills_job(self):
2473 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2474 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2475 self.waitUntilSettled()
2476 self.assertHistory([
2477 dict(name='dd-big-empty-file', result='ABORTED', changes='1,1')])
Tristan Cacqueray82f864b2017-08-01 05:54:42 +00002478
2479
2480class TestMaxNodesPerJob(AnsibleZuulTestCase):
2481 tenant_config_file = 'config/multi-tenant/main.yaml'
2482
Tristan Cacquerayc98bff72017-09-10 15:25:26 +00002483 def test_max_timeout_exceeded(self):
Tristan Cacqueray82f864b2017-08-01 05:54:42 +00002484 in_repo_conf = textwrap.dedent(
2485 """
2486 - job:
2487 name: test-job
James E. Blair7e3e6882017-09-20 15:47:13 -07002488 nodeset:
2489 nodes:
2490 - name: node01
2491 label: fake
2492 - name: node02
2493 label: fake
2494 - name: node03
2495 label: fake
2496 - name: node04
2497 label: fake
2498 - name: node05
2499 label: fake
2500 - name: node06
2501 label: fake
Tristan Cacqueray82f864b2017-08-01 05:54:42 +00002502 """)
2503 file_dict = {'.zuul.yaml': in_repo_conf}
2504 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A',
2505 files=file_dict)
2506 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2507 self.waitUntilSettled()
2508 self.assertIn('The job "test-job" exceeds tenant max-nodes-per-job 5.',
2509 A.messages[0], "A should fail because of nodes limit")
2510
2511 B = self.fake_gerrit.addFakeChange('org/project2', 'master', 'A',
2512 files=file_dict)
2513 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
2514 self.waitUntilSettled()
2515 self.assertNotIn("exceeds tenant max-nodes", B.messages[0],
2516 "B should not fail because of nodes limit")
James E. Blair2bab6e72017-08-07 09:52:45 -07002517
2518
Tristan Cacquerayc98bff72017-09-10 15:25:26 +00002519class TestMaxTimeout(AnsibleZuulTestCase):
2520 tenant_config_file = 'config/multi-tenant/main.yaml'
2521
2522 def test_max_nodes_reached(self):
2523 in_repo_conf = textwrap.dedent(
2524 """
2525 - job:
2526 name: test-job
2527 timeout: 3600
2528 """)
2529 file_dict = {'.zuul.yaml': in_repo_conf}
2530 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A',
2531 files=file_dict)
2532 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2533 self.waitUntilSettled()
2534 self.assertIn('The job "test-job" exceeds tenant max-job-timeout',
2535 A.messages[0], "A should fail because of timeout limit")
2536
2537 B = self.fake_gerrit.addFakeChange('org/project2', 'master', 'A',
2538 files=file_dict)
2539 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
2540 self.waitUntilSettled()
2541 self.assertNotIn("exceeds tenant max-job-timeout", B.messages[0],
2542 "B should not fail because of timeout limit")
2543
2544
James E. Blair7edc25f2017-10-26 10:47:14 -07002545class TestPragma(ZuulTestCase):
2546 tenant_config_file = 'config/pragma/main.yaml'
2547
2548 def test_no_pragma(self):
2549 self.create_branch('org/project', 'stable')
2550 with open(os.path.join(FIXTURE_DIR,
2551 'config/pragma/git/',
2552 'org_project/nopragma.yaml')) as f:
2553 config = f.read()
2554 file_dict = {'.zuul.yaml': config}
2555 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
2556 files=file_dict)
2557 A.addApproval('Code-Review', 2)
2558 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
2559 self.waitUntilSettled()
2560 self.fake_gerrit.addEvent(A.getChangeMergedEvent())
2561 self.waitUntilSettled()
2562
2563 # This is an untrusted repo with 2 branches, so it should have
2564 # an implied branch matcher for the job.
2565 tenant = self.sched.abide.tenants.get('tenant-one')
2566 jobs = tenant.layout.getJobs('test-job')
2567 self.assertEqual(len(jobs), 1)
2568 for job in tenant.layout.getJobs('test-job'):
2569 self.assertIsNotNone(job.branch_matcher)
2570
2571 def test_pragma(self):
2572 self.create_branch('org/project', 'stable')
2573 with open(os.path.join(FIXTURE_DIR,
2574 'config/pragma/git/',
2575 'org_project/pragma.yaml')) as f:
2576 config = f.read()
2577 file_dict = {'.zuul.yaml': config}
2578 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
2579 files=file_dict)
2580 A.addApproval('Code-Review', 2)
2581 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
2582 self.waitUntilSettled()
2583 self.fake_gerrit.addEvent(A.getChangeMergedEvent())
2584 self.waitUntilSettled()
2585
2586 # This is an untrusted repo with 2 branches, so it would
2587 # normally have an implied branch matcher, but our pragma
2588 # overrides it.
2589 tenant = self.sched.abide.tenants.get('tenant-one')
2590 jobs = tenant.layout.getJobs('test-job')
2591 self.assertEqual(len(jobs), 1)
2592 for job in tenant.layout.getJobs('test-job'):
2593 self.assertIsNone(job.branch_matcher)
2594
2595
James E. Blair37c3d8c2017-12-13 15:06:11 -08002596class TestPragmaMultibranch(ZuulTestCase):
2597 tenant_config_file = 'config/pragma-multibranch/main.yaml'
2598
2599 def test_no_branch_matchers(self):
2600 self.create_branch('org/project1', 'stable/pike')
2601 self.create_branch('org/project2', 'stable/jewel')
2602 self.fake_gerrit.addEvent(
2603 self.fake_gerrit.getFakeBranchCreatedEvent(
2604 'org/project1', 'stable/pike'))
2605 self.fake_gerrit.addEvent(
2606 self.fake_gerrit.getFakeBranchCreatedEvent(
2607 'org/project2', 'stable/jewel'))
2608 self.waitUntilSettled()
2609 # We want the jobs defined on the stable/pike branch of
2610 # project1 to apply to the stable/jewel branch of project2.
2611
2612 # First, without the pragma line, the jobs should not run
2613 # because in project1 they have branch matchers for pike, so
2614 # they will not match a jewel change.
2615 B = self.fake_gerrit.addFakeChange('org/project2', 'stable/jewel', 'B')
2616 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
2617 self.waitUntilSettled()
2618 self.assertHistory([])
2619
2620 # Add a pragma line to disable implied branch matchers in
2621 # project1, so that the jobs and templates apply to both
2622 # branches.
2623 with open(os.path.join(FIXTURE_DIR,
2624 'config/pragma-multibranch/git/',
2625 'org_project1/zuul.yaml')) as f:
2626 config = f.read()
2627 extra_conf = textwrap.dedent(
2628 """
2629 - pragma:
2630 implied-branch-matchers: False
2631 """)
2632 config = extra_conf + config
2633 file_dict = {'zuul.yaml': config}
2634 A = self.fake_gerrit.addFakeChange('org/project1', 'stable/pike', 'A',
2635 files=file_dict)
2636 A.addApproval('Code-Review', 2)
2637 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
2638 self.waitUntilSettled()
2639 self.fake_gerrit.addEvent(A.getChangeMergedEvent())
2640 self.waitUntilSettled()
2641
2642 # Now verify that when we propose a change to jewel, we get
2643 # the pike/jewel jobs.
2644 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
2645 self.waitUntilSettled()
2646 self.assertHistory([
2647 dict(name='test-job1', result='SUCCESS', changes='1,1'),
2648 dict(name='test-job2', result='SUCCESS', changes='1,1'),
2649 ], ordered=False)
2650
2651 def test_supplied_branch_matchers(self):
2652 self.create_branch('org/project1', 'stable/pike')
2653 self.create_branch('org/project2', 'stable/jewel')
2654 self.fake_gerrit.addEvent(
2655 self.fake_gerrit.getFakeBranchCreatedEvent(
2656 'org/project1', 'stable/pike'))
2657 self.fake_gerrit.addEvent(
2658 self.fake_gerrit.getFakeBranchCreatedEvent(
2659 'org/project2', 'stable/jewel'))
2660 self.waitUntilSettled()
2661 # We want the jobs defined on the stable/pike branch of
2662 # project1 to apply to the stable/jewel branch of project2.
2663
2664 # First, without the pragma line, the jobs should not run
2665 # because in project1 they have branch matchers for pike, so
2666 # they will not match a jewel change.
2667 B = self.fake_gerrit.addFakeChange('org/project2', 'stable/jewel', 'B')
2668 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
2669 self.waitUntilSettled()
2670 self.assertHistory([])
2671
2672 # Add a pragma line to disable implied branch matchers in
2673 # project1, so that the jobs and templates apply to both
2674 # branches.
2675 with open(os.path.join(FIXTURE_DIR,
2676 'config/pragma-multibranch/git/',
2677 'org_project1/zuul.yaml')) as f:
2678 config = f.read()
2679 extra_conf = textwrap.dedent(
2680 """
2681 - pragma:
2682 implied-branches:
2683 - stable/pike
2684 - stable/jewel
2685 """)
2686 config = extra_conf + config
2687 file_dict = {'zuul.yaml': config}
2688 A = self.fake_gerrit.addFakeChange('org/project1', 'stable/pike', 'A',
2689 files=file_dict)
2690 A.addApproval('Code-Review', 2)
2691 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
2692 self.waitUntilSettled()
2693 self.fake_gerrit.addEvent(A.getChangeMergedEvent())
2694 self.waitUntilSettled()
2695 # Now verify that when we propose a change to jewel, we get
2696 # the pike/jewel jobs.
2697 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
2698 self.waitUntilSettled()
2699 self.assertHistory([
2700 dict(name='test-job1', result='SUCCESS', changes='1,1'),
2701 dict(name='test-job2', result='SUCCESS', changes='1,1'),
2702 ], ordered=False)
2703
2704
James E. Blair2bab6e72017-08-07 09:52:45 -07002705class TestBaseJobs(ZuulTestCase):
2706 tenant_config_file = 'config/base-jobs/main.yaml'
2707
2708 def test_multiple_base_jobs(self):
2709 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2710 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2711 self.waitUntilSettled()
2712 self.assertHistory([
2713 dict(name='my-job', result='SUCCESS', changes='1,1'),
2714 dict(name='other-job', result='SUCCESS', changes='1,1'),
2715 ], ordered=False)
2716 self.assertEqual(self.getJobFromHistory('my-job').
2717 parameters['zuul']['jobtags'],
2718 ['mybase'])
2719 self.assertEqual(self.getJobFromHistory('other-job').
2720 parameters['zuul']['jobtags'],
2721 ['otherbase'])
2722
2723 def test_untrusted_base_job(self):
2724 """Test that a base job may not be defined in an untrusted repo"""
2725 in_repo_conf = textwrap.dedent(
2726 """
2727 - job:
2728 name: fail-base
2729 parent: null
2730 """)
2731
2732 file_dict = {'.zuul.yaml': in_repo_conf}
2733 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
2734 files=file_dict)
2735 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2736 self.waitUntilSettled()
2737 self.assertEqual(A.reported, 1,
2738 "A should report failure")
2739 self.assertEqual(A.patchsets[0]['approvals'][0]['value'], "-1")
2740 self.assertIn('Base jobs must be defined in config projects',
2741 A.messages[0])
2742 self.assertHistory([])
James E. Blairdb089032017-08-15 13:42:12 -07002743
2744
James E. Blaira17a8e72018-01-17 13:45:25 -08002745class TestSecrets(ZuulTestCase):
2746 tenant_config_file = 'config/secrets/main.yaml'
2747 secret = {'password': 'test-password',
2748 'username': 'test-username'}
2749
2750 def _getSecrets(self, job, pbtype):
2751 secrets = []
2752 build = self.getJobFromHistory(job)
2753 for pb in build.parameters[pbtype]:
2754 secrets.append(pb['secrets'])
2755 return secrets
2756
2757 def test_secret_branch(self):
2758 # Test that we can use a secret defined in another branch of
2759 # the same project.
2760 self.create_branch('org/project2', 'stable')
2761 self.fake_gerrit.addEvent(
2762 self.fake_gerrit.getFakeBranchCreatedEvent(
2763 'org/project2', 'stable'))
2764 self.waitUntilSettled()
2765
2766 with open(os.path.join(FIXTURE_DIR,
2767 'config/secrets/git/',
2768 'org_project2/zuul-secret.yaml')) as f:
2769 config = f.read()
2770
2771 file_dict = {'zuul.yaml': config}
2772 A = self.fake_gerrit.addFakeChange('org/project2', 'master', 'A',
2773 files=file_dict)
2774 A.addApproval('Code-Review', 2)
2775 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
2776 self.waitUntilSettled()
2777 self.assertEqual(A.data['status'], 'MERGED')
2778 self.fake_gerrit.addEvent(A.getChangeMergedEvent())
2779 self.waitUntilSettled()
2780
2781 in_repo_conf = textwrap.dedent(
2782 """
2783 - job:
2784 parent: base
2785 name: project2-secret
2786 run: playbooks/secret.yaml
2787 secrets: [project2_secret]
2788
2789 - project:
2790 check:
2791 jobs:
2792 - project2-secret
2793 gate:
2794 jobs:
2795 - noop
2796 """)
2797 file_dict = {'zuul.yaml': in_repo_conf}
2798 B = self.fake_gerrit.addFakeChange('org/project2', 'stable', 'B',
2799 files=file_dict)
2800 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
2801 self.waitUntilSettled()
2802 self.assertEqual(B.reported, 1, "B should report success")
2803 self.assertHistory([
2804 dict(name='project2-secret', result='SUCCESS', changes='2,1'),
2805 ])
2806 self.assertEqual(
2807 self._getSecrets('project2-secret', 'playbooks'),
2808 [{'project2_secret': self.secret}])
2809
2810 def test_secret_branch_duplicate(self):
2811 # Test that we can create a duplicate secret on a different
2812 # branch of the same project -- i.e., that when we branch
2813 # master to stable on a project with a secret, nothing
2814 # changes.
2815 self.create_branch('org/project1', 'stable')
2816 self.fake_gerrit.addEvent(
2817 self.fake_gerrit.getFakeBranchCreatedEvent(
2818 'org/project1', 'stable'))
2819 self.waitUntilSettled()
2820
2821 A = self.fake_gerrit.addFakeChange('org/project1', 'stable', 'A')
2822 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2823 self.waitUntilSettled()
2824 self.assertEqual(A.reported, 1,
2825 "A should report success")
2826 self.assertHistory([
2827 dict(name='project1-secret', result='SUCCESS', changes='1,1'),
2828 ])
2829 self.assertEqual(
2830 self._getSecrets('project1-secret', 'playbooks'),
2831 [{'project1_secret': self.secret}])
2832
2833 def test_secret_branch_error_same_branch(self):
2834 # Test that we are unable to define a secret twice on the same
2835 # project-branch.
2836 in_repo_conf = textwrap.dedent(
2837 """
2838 - secret:
2839 name: project1_secret
2840 data: {}
2841 - secret:
2842 name: project1_secret
2843 data: {}
2844 """)
2845 file_dict = {'zuul.yaml': in_repo_conf}
2846 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A',
2847 files=file_dict)
2848 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2849 self.waitUntilSettled()
2850 self.assertIn('already defined', A.messages[0])
2851
2852 def test_secret_branch_error_same_project(self):
2853 # Test that we are unable to create a secret which differs
2854 # from another with the same name -- i.e., that if we have a
2855 # duplicate secret on multiple branches of the same project,
2856 # they must be identical.
2857 self.create_branch('org/project1', 'stable')
2858 self.fake_gerrit.addEvent(
2859 self.fake_gerrit.getFakeBranchCreatedEvent(
2860 'org/project1', 'stable'))
2861 self.waitUntilSettled()
2862
2863 in_repo_conf = textwrap.dedent(
2864 """
2865 - secret:
2866 name: project1_secret
2867 data: {}
2868 """)
2869 file_dict = {'zuul.yaml': in_repo_conf}
2870 A = self.fake_gerrit.addFakeChange('org/project1', 'stable', 'A',
2871 files=file_dict)
2872 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2873 self.waitUntilSettled()
2874 self.assertIn('does not match existing definition in branch master',
2875 A.messages[0])
2876
2877 def test_secret_branch_error_other_project(self):
2878 # Test that we are unable to create a secret with the same
2879 # name as another. We're never allowed to have a secret with
2880 # the same name outside of a project.
2881 in_repo_conf = textwrap.dedent(
2882 """
2883 - secret:
2884 name: project1_secret
2885 data: {}
2886 """)
2887 file_dict = {'zuul.yaml': in_repo_conf}
2888 A = self.fake_gerrit.addFakeChange('org/project2', 'master', 'A',
2889 files=file_dict)
2890 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2891 self.waitUntilSettled()
2892 self.assertIn('already defined in project org/project1',
2893 A.messages[0])
2894
2895
James E. Blairdf91ab32017-10-25 17:57:13 -07002896class TestSecretInheritance(ZuulTestCase):
2897 tenant_config_file = 'config/secret-inheritance/main.yaml'
2898
2899 def _getSecrets(self, job, pbtype):
2900 secrets = []
2901 build = self.getJobFromHistory(job)
2902 for pb in build.parameters[pbtype]:
2903 secrets.append(pb['secrets'])
2904 return secrets
2905
2906 def _checkTrustedSecrets(self):
2907 secret = {'longpassword': 'test-passwordtest-password',
2908 'password': 'test-password',
2909 'username': 'test-username'}
2910 self.assertEqual(
2911 self._getSecrets('trusted-secrets', 'playbooks'),
James E. Blair2f589fe2017-10-26 12:57:41 -07002912 [{'trusted-secret': secret}])
James E. Blairdf91ab32017-10-25 17:57:13 -07002913 self.assertEqual(
2914 self._getSecrets('trusted-secrets', 'pre_playbooks'), [])
2915 self.assertEqual(
2916 self._getSecrets('trusted-secrets', 'post_playbooks'), [])
2917
2918 self.assertEqual(
2919 self._getSecrets('trusted-secrets-trusted-child',
James E. Blair2f589fe2017-10-26 12:57:41 -07002920 'playbooks'), [{}])
James E. Blairdf91ab32017-10-25 17:57:13 -07002921 self.assertEqual(
2922 self._getSecrets('trusted-secrets-trusted-child',
2923 'pre_playbooks'), [])
2924 self.assertEqual(
2925 self._getSecrets('trusted-secrets-trusted-child',
2926 'post_playbooks'), [])
2927
2928 self.assertEqual(
2929 self._getSecrets('trusted-secrets-untrusted-child',
James E. Blair2f589fe2017-10-26 12:57:41 -07002930 'playbooks'), [{}])
James E. Blairdf91ab32017-10-25 17:57:13 -07002931 self.assertEqual(
2932 self._getSecrets('trusted-secrets-untrusted-child',
2933 'pre_playbooks'), [])
2934 self.assertEqual(
2935 self._getSecrets('trusted-secrets-untrusted-child',
2936 'post_playbooks'), [])
2937
2938 def _checkUntrustedSecrets(self):
2939 secret = {'longpassword': 'test-passwordtest-password',
2940 'password': 'test-password',
2941 'username': 'test-username'}
2942 self.assertEqual(
2943 self._getSecrets('untrusted-secrets', 'playbooks'),
James E. Blair2f589fe2017-10-26 12:57:41 -07002944 [{'untrusted-secret': secret}])
James E. Blairdf91ab32017-10-25 17:57:13 -07002945 self.assertEqual(
2946 self._getSecrets('untrusted-secrets', 'pre_playbooks'), [])
2947 self.assertEqual(
2948 self._getSecrets('untrusted-secrets', 'post_playbooks'), [])
2949
2950 self.assertEqual(
2951 self._getSecrets('untrusted-secrets-trusted-child',
James E. Blair2f589fe2017-10-26 12:57:41 -07002952 'playbooks'), [{}])
James E. Blairdf91ab32017-10-25 17:57:13 -07002953 self.assertEqual(
2954 self._getSecrets('untrusted-secrets-trusted-child',
2955 'pre_playbooks'), [])
2956 self.assertEqual(
2957 self._getSecrets('untrusted-secrets-trusted-child',
2958 'post_playbooks'), [])
2959
2960 self.assertEqual(
2961 self._getSecrets('untrusted-secrets-untrusted-child',
James E. Blair2f589fe2017-10-26 12:57:41 -07002962 'playbooks'), [{}])
James E. Blairdf91ab32017-10-25 17:57:13 -07002963 self.assertEqual(
2964 self._getSecrets('untrusted-secrets-untrusted-child',
2965 'pre_playbooks'), [])
2966 self.assertEqual(
2967 self._getSecrets('untrusted-secrets-untrusted-child',
2968 'post_playbooks'), [])
2969
2970 def test_trusted_secret_inheritance_check(self):
2971 A = self.fake_gerrit.addFakeChange('common-config', 'master', 'A')
2972 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2973 self.waitUntilSettled()
2974 self.assertHistory([
2975 dict(name='trusted-secrets', result='SUCCESS', changes='1,1'),
2976 dict(name='trusted-secrets-trusted-child',
2977 result='SUCCESS', changes='1,1'),
2978 dict(name='trusted-secrets-untrusted-child',
2979 result='SUCCESS', changes='1,1'),
2980 ], ordered=False)
2981
2982 self._checkTrustedSecrets()
2983
2984 def test_untrusted_secret_inheritance_gate(self):
2985 A = self.fake_gerrit.addFakeChange('common-config', 'master', 'A')
2986 A.addApproval('Code-Review', 2)
2987 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
2988 self.waitUntilSettled()
2989 self.assertHistory([
2990 dict(name='untrusted-secrets', result='SUCCESS', changes='1,1'),
2991 dict(name='untrusted-secrets-trusted-child',
2992 result='SUCCESS', changes='1,1'),
2993 dict(name='untrusted-secrets-untrusted-child',
2994 result='SUCCESS', changes='1,1'),
2995 ], ordered=False)
2996
2997 self._checkUntrustedSecrets()
2998
2999 def test_untrusted_secret_inheritance_check(self):
3000 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
3001 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
3002 self.waitUntilSettled()
3003 # This configuration tries to run untrusted secrets in an
3004 # non-post-review pipeline and should therefore run no jobs.
3005 self.assertHistory([])
3006
3007
James E. Blairdb089032017-08-15 13:42:12 -07003008class TestSecretLeaks(AnsibleZuulTestCase):
3009 tenant_config_file = 'config/secret-leaks/main.yaml'
3010
3011 def searchForContent(self, path, content):
3012 matches = []
3013 for (dirpath, dirnames, filenames) in os.walk(path):
3014 for filename in filenames:
3015 filepath = os.path.join(dirpath, filename)
3016 with open(filepath, 'rb') as f:
3017 if content in f.read():
3018 matches.append(filepath[len(path):])
3019 return matches
3020
3021 def _test_secret_file(self):
3022 # Or rather -- test that they *don't* leak.
3023 # Keep the jobdir around so we can inspect contents.
3024 self.executor_server.keep_jobdir = True
3025 conf = textwrap.dedent(
3026 """
3027 - project:
3028 name: org/project
3029 check:
3030 jobs:
3031 - secret-file
3032 """)
3033
3034 file_dict = {'.zuul.yaml': conf}
3035 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
3036 files=file_dict)
3037 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
3038 self.waitUntilSettled()
3039 self.assertHistory([
3040 dict(name='secret-file', result='SUCCESS', changes='1,1'),
3041 ], ordered=False)
3042 matches = self.searchForContent(self.history[0].jobdir.root,
3043 b'test-password')
James E. Blaird6a71ca2017-08-18 14:15:05 -07003044 self.assertEqual(set(['/work/secret-file.txt']),
James E. Blairdb089032017-08-15 13:42:12 -07003045 set(matches))
3046
3047 def test_secret_file(self):
3048 self._test_secret_file()
3049
3050 def test_secret_file_verbose(self):
3051 # Output extra ansible info to exercise alternate logging code
3052 # paths.
3053 self.executor_server.verbose = True
3054 self._test_secret_file()
3055
3056 def _test_secret_file_fail(self):
3057 # Or rather -- test that they *don't* leak.
3058 # Keep the jobdir around so we can inspect contents.
3059 self.executor_server.keep_jobdir = True
3060 conf = textwrap.dedent(
3061 """
3062 - project:
3063 name: org/project
3064 check:
3065 jobs:
3066 - secret-file-fail
3067 """)
3068
3069 file_dict = {'.zuul.yaml': conf}
3070 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
3071 files=file_dict)
3072 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
3073 self.waitUntilSettled()
3074 self.assertHistory([
3075 dict(name='secret-file-fail', result='FAILURE', changes='1,1'),
3076 ], ordered=False)
3077 matches = self.searchForContent(self.history[0].jobdir.root,
3078 b'test-password')
James E. Blaird6a71ca2017-08-18 14:15:05 -07003079 self.assertEqual(set(['/work/failure-file.txt']),
James E. Blairdb089032017-08-15 13:42:12 -07003080 set(matches))
3081
3082 def test_secret_file_fail(self):
3083 self._test_secret_file_fail()
3084
3085 def test_secret_file_fail_verbose(self):
3086 # Output extra ansible info to exercise alternate logging code
3087 # paths.
3088 self.executor_server.verbose = True
3089 self._test_secret_file_fail()
James E. Blaira00910c2017-08-23 09:15:04 -07003090
3091
James E. Blair8446c412018-01-17 15:49:59 -08003092class TestNodesets(ZuulTestCase):
3093 tenant_config_file = 'config/nodesets/main.yaml'
3094
3095 def test_nodeset_branch(self):
3096 # Test that we can use a nodeset defined in another branch of
3097 # the same project.
3098 self.create_branch('org/project2', 'stable')
3099 self.fake_gerrit.addEvent(
3100 self.fake_gerrit.getFakeBranchCreatedEvent(
3101 'org/project2', 'stable'))
3102 self.waitUntilSettled()
3103
3104 with open(os.path.join(FIXTURE_DIR,
3105 'config/nodesets/git/',
3106 'org_project2/zuul-nodeset.yaml')) as f:
3107 config = f.read()
3108
3109 file_dict = {'zuul.yaml': config}
3110 A = self.fake_gerrit.addFakeChange('org/project2', 'master', 'A',
3111 files=file_dict)
3112 A.addApproval('Code-Review', 2)
3113 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
3114 self.waitUntilSettled()
3115 self.assertEqual(A.data['status'], 'MERGED')
3116 self.fake_gerrit.addEvent(A.getChangeMergedEvent())
3117 self.waitUntilSettled()
3118
3119 in_repo_conf = textwrap.dedent(
3120 """
3121 - job:
3122 parent: base
3123 name: project2-test
3124 nodeset: project2-nodeset
3125
3126 - project:
3127 check:
3128 jobs:
3129 - project2-test
3130 gate:
3131 jobs:
3132 - noop
3133 """)
3134 file_dict = {'zuul.yaml': in_repo_conf}
3135 B = self.fake_gerrit.addFakeChange('org/project2', 'stable', 'B',
3136 files=file_dict)
3137 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
3138 self.waitUntilSettled()
3139 self.assertEqual(B.reported, 1, "B should report success")
3140 self.assertHistory([
3141 dict(name='project2-test', result='SUCCESS', changes='2,1',
3142 node='ubuntu-xenial'),
3143 ])
3144
3145 def test_nodeset_branch_duplicate(self):
Monty Taylorbc1d0bb2018-01-22 17:05:31 -06003146 # Test that we can create a duplicate nodeset on a different
James E. Blair8446c412018-01-17 15:49:59 -08003147 # branch of the same project -- i.e., that when we branch
Monty Taylorbc1d0bb2018-01-22 17:05:31 -06003148 # master to stable on a project with a nodeset, nothing
James E. Blair8446c412018-01-17 15:49:59 -08003149 # changes.
3150 self.create_branch('org/project1', 'stable')
3151 self.fake_gerrit.addEvent(
3152 self.fake_gerrit.getFakeBranchCreatedEvent(
3153 'org/project1', 'stable'))
3154 self.waitUntilSettled()
3155
3156 A = self.fake_gerrit.addFakeChange('org/project1', 'stable', 'A')
3157 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
3158 self.waitUntilSettled()
3159 self.assertEqual(A.reported, 1,
3160 "A should report success")
3161 self.assertHistory([
3162 dict(name='project1-test', result='SUCCESS', changes='1,1',
3163 node='ubuntu-xenial'),
3164 ])
3165
3166 def test_nodeset_branch_error_same_branch(self):
3167 # Test that we are unable to define a nodeset twice on the same
3168 # project-branch.
3169 in_repo_conf = textwrap.dedent(
3170 """
3171 - nodeset:
3172 name: project1-nodeset
3173 nodes: []
3174 - nodeset:
3175 name: project1-nodeset
3176 nodes: []
3177 """)
3178 file_dict = {'zuul.yaml': in_repo_conf}
3179 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A',
3180 files=file_dict)
3181 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
3182 self.waitUntilSettled()
3183 self.assertIn('already defined', A.messages[0])
3184
3185 def test_nodeset_branch_error_same_project(self):
3186 # Test that we are unable to create a nodeset which differs
3187 # from another with the same name -- i.e., that if we have a
3188 # duplicate nodeset on multiple branches of the same project,
3189 # they must be identical.
3190 self.create_branch('org/project1', 'stable')
3191 self.fake_gerrit.addEvent(
3192 self.fake_gerrit.getFakeBranchCreatedEvent(
3193 'org/project1', 'stable'))
3194 self.waitUntilSettled()
3195
3196 in_repo_conf = textwrap.dedent(
3197 """
3198 - nodeset:
3199 name: project1-nodeset
3200 nodes: []
3201 """)
3202 file_dict = {'zuul.yaml': in_repo_conf}
3203 A = self.fake_gerrit.addFakeChange('org/project1', 'stable', 'A',
3204 files=file_dict)
3205 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
3206 self.waitUntilSettled()
3207 self.assertIn('does not match existing definition in branch master',
3208 A.messages[0])
3209
3210 def test_nodeset_branch_error_other_project(self):
3211 # Test that we are unable to create a nodeset with the same
3212 # name as another. We're never allowed to have a nodeset with
3213 # the same name outside of a project.
3214 in_repo_conf = textwrap.dedent(
3215 """
3216 - nodeset:
3217 name: project1-nodeset
3218 nodes: []
3219 """)
3220 file_dict = {'zuul.yaml': in_repo_conf}
3221 A = self.fake_gerrit.addFakeChange('org/project2', 'master', 'A',
3222 files=file_dict)
3223 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
3224 self.waitUntilSettled()
3225 self.assertIn('already defined in project org/project1',
3226 A.messages[0])
3227
3228
James E. Blair9596b942018-01-18 14:21:44 -08003229class TestSemaphoreBranches(ZuulTestCase):
3230 tenant_config_file = 'config/semaphore-branches/main.yaml'
3231
3232 def test_semaphore_branch(self):
3233 # Test that we can use a semaphore defined in another branch of
3234 # the same project.
3235 self.create_branch('org/project2', 'stable')
3236 self.fake_gerrit.addEvent(
3237 self.fake_gerrit.getFakeBranchCreatedEvent(
3238 'org/project2', 'stable'))
3239 self.waitUntilSettled()
3240
3241 with open(os.path.join(FIXTURE_DIR,
3242 'config/semaphore-branches/git/',
3243 'org_project2/zuul-semaphore.yaml')) as f:
3244 config = f.read()
3245
3246 file_dict = {'zuul.yaml': config}
3247 A = self.fake_gerrit.addFakeChange('org/project2', 'master', 'A',
3248 files=file_dict)
3249 A.addApproval('Code-Review', 2)
3250 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
3251 self.waitUntilSettled()
3252 self.assertEqual(A.data['status'], 'MERGED')
3253 self.fake_gerrit.addEvent(A.getChangeMergedEvent())
3254 self.waitUntilSettled()
3255
3256 in_repo_conf = textwrap.dedent(
3257 """
3258 - job:
3259 parent: base
3260 name: project2-test
3261 semaphore: project2-semaphore
3262
3263 - project:
3264 check:
3265 jobs:
3266 - project2-test
3267 gate:
3268 jobs:
3269 - noop
3270 """)
3271 file_dict = {'zuul.yaml': in_repo_conf}
3272 B = self.fake_gerrit.addFakeChange('org/project2', 'stable', 'B',
3273 files=file_dict)
3274 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
3275 self.waitUntilSettled()
3276 self.assertEqual(B.reported, 1, "B should report success")
3277 self.assertHistory([
3278 dict(name='project2-test', result='SUCCESS', changes='2,1')
3279 ])
3280
3281 def test_semaphore_branch_duplicate(self):
3282 # Test that we can create a duplicate semaphore on a different
3283 # branch of the same project -- i.e., that when we branch
3284 # master to stable on a project with a semaphore, nothing
3285 # changes.
3286 self.create_branch('org/project1', 'stable')
3287 self.fake_gerrit.addEvent(
3288 self.fake_gerrit.getFakeBranchCreatedEvent(
3289 'org/project1', 'stable'))
3290 self.waitUntilSettled()
3291
3292 A = self.fake_gerrit.addFakeChange('org/project1', 'stable', 'A')
3293 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
3294 self.waitUntilSettled()
3295 self.assertEqual(A.reported, 1,
3296 "A should report success")
3297 self.assertHistory([
3298 dict(name='project1-test', result='SUCCESS', changes='1,1')
3299 ])
3300
3301 def test_semaphore_branch_error_same_branch(self):
3302 # Test that we are unable to define a semaphore twice on the same
3303 # project-branch.
3304 in_repo_conf = textwrap.dedent(
3305 """
3306 - semaphore:
3307 name: project1-semaphore
3308 max: 2
3309 - semaphore:
3310 name: project1-semaphore
3311 max: 2
3312 """)
3313 file_dict = {'zuul.yaml': in_repo_conf}
3314 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A',
3315 files=file_dict)
3316 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
3317 self.waitUntilSettled()
3318 self.assertIn('already defined', A.messages[0])
3319
3320 def test_semaphore_branch_error_same_project(self):
3321 # Test that we are unable to create a semaphore which differs
3322 # from another with the same name -- i.e., that if we have a
3323 # duplicate semaphore on multiple branches of the same project,
3324 # they must be identical.
3325 self.create_branch('org/project1', 'stable')
3326 self.fake_gerrit.addEvent(
3327 self.fake_gerrit.getFakeBranchCreatedEvent(
3328 'org/project1', 'stable'))
3329 self.waitUntilSettled()
3330
3331 in_repo_conf = textwrap.dedent(
3332 """
3333 - semaphore:
3334 name: project1-semaphore
3335 max: 4
3336 """)
3337 file_dict = {'zuul.yaml': in_repo_conf}
3338 A = self.fake_gerrit.addFakeChange('org/project1', 'stable', 'A',
3339 files=file_dict)
3340 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
3341 self.waitUntilSettled()
3342 self.assertIn('does not match existing definition in branch master',
3343 A.messages[0])
3344
3345 def test_semaphore_branch_error_other_project(self):
3346 # Test that we are unable to create a semaphore with the same
3347 # name as another. We're never allowed to have a semaphore with
3348 # the same name outside of a project.
3349 in_repo_conf = textwrap.dedent(
3350 """
3351 - semaphore:
3352 name: project1-semaphore
3353 max: 2
3354 """)
3355 file_dict = {'zuul.yaml': in_repo_conf}
3356 A = self.fake_gerrit.addFakeChange('org/project2', 'master', 'A',
3357 files=file_dict)
3358 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
3359 self.waitUntilSettled()
3360 self.assertIn('already defined in project org/project1',
3361 A.messages[0])
3362
3363
James E. Blaira00910c2017-08-23 09:15:04 -07003364class TestJobOutput(AnsibleZuulTestCase):
3365 tenant_config_file = 'config/job-output/main.yaml'
3366
3367 def _get_file(self, build, path):
3368 p = os.path.join(build.jobdir.root, path)
3369 with open(p) as f:
3370 return f.read()
3371
3372 def test_job_output(self):
Monty Taylor0e2489a2017-10-10 11:57:29 -05003373 # Verify that command standard output appears in the job output,
3374 # and that failures in the final playbook get logged.
James E. Blaira00910c2017-08-23 09:15:04 -07003375
3376 # This currently only verifies we receive output from
3377 # localhost. Notably, it does not verify we receive output
3378 # via zuul_console streaming.
3379 self.executor_server.keep_jobdir = True
3380 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
3381 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
3382 self.waitUntilSettled()
3383 self.assertHistory([
3384 dict(name='job-output', result='SUCCESS', changes='1,1'),
3385 ], ordered=False)
3386
3387 token = 'Standard output test %s' % (self.history[0].jobdir.src_root)
3388 j = json.loads(self._get_file(self.history[0],
3389 'work/logs/job-output.json'))
3390 self.assertEqual(token,
3391 j[0]['plays'][0]['tasks'][0]
3392 ['hosts']['localhost']['stdout'])
3393
3394 print(self._get_file(self.history[0],
3395 'work/logs/job-output.txt'))
3396 self.assertIn(token,
3397 self._get_file(self.history[0],
3398 'work/logs/job-output.txt'))
Monty Taylor0e2489a2017-10-10 11:57:29 -05003399
3400 def test_job_output_failure_log(self):
3401 logger = logging.getLogger('zuul.AnsibleJob')
3402 output = io.StringIO()
3403 logger.addHandler(logging.StreamHandler(output))
3404
3405 # Verify that a failure in the last post playbook emits the contents
3406 # of the json output to the log
3407 self.executor_server.keep_jobdir = True
3408 A = self.fake_gerrit.addFakeChange('org/project2', 'master', 'A')
3409 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
3410 self.waitUntilSettled()
3411 self.assertHistory([
3412 dict(name='job-output-failure',
3413 result='POST_FAILURE', changes='1,1'),
3414 ], ordered=False)
3415
3416 token = 'Standard output test %s' % (self.history[0].jobdir.src_root)
3417 j = json.loads(self._get_file(self.history[0],
3418 'work/logs/job-output.json'))
3419 self.assertEqual(token,
3420 j[0]['plays'][0]['tasks'][0]
3421 ['hosts']['localhost']['stdout'])
3422
3423 print(self._get_file(self.history[0],
3424 'work/logs/job-output.json'))
3425 self.assertIn(token,
3426 self._get_file(self.history[0],
3427 'work/logs/job-output.txt'))
3428
3429 log_output = output.getvalue()
3430 self.assertIn('Final playbook failed', log_output)
3431 self.assertIn('Failure test', log_output)