blob: 1338d2015f19a01ab80527acd2da124d5e37bb71 [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):
Jamie Lennox7655b552017-03-17 12:33:38 +11002036 # Keep the jobdir around so we can inspect contents if an
2037 # assert fails.
2038 self.executor_server.keep_jobdir = True
2039 # Output extra ansible info so we might see errors.
2040 self.executor_server.verbose = True
2041 # Add a site variables file, used by check-vars
2042 path = os.path.join(FIXTURE_DIR, 'config', 'ansible',
2043 'variables.yaml')
2044 self.config.set('executor', 'variables', path)
James E. Blairc73c73a2017-01-20 15:15:15 -08002045 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2046 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2047 self.waitUntilSettled()
Tobias Henkel077f2f32017-05-30 20:16:46 +02002048 build_timeout = self.getJobFromHistory('timeout')
Jamie Lennox7655b552017-03-17 12:33:38 +11002049 with self.jobLog(build_timeout):
2050 self.assertEqual(build_timeout.result, 'TIMED_OUT')
Tobias Henkel077f2f32017-05-30 20:16:46 +02002051 build_faillocal = self.getJobFromHistory('faillocal')
Jamie Lennox7655b552017-03-17 12:33:38 +11002052 with self.jobLog(build_faillocal):
2053 self.assertEqual(build_faillocal.result, 'FAILURE')
Tobias Henkel077f2f32017-05-30 20:16:46 +02002054 build_failpost = self.getJobFromHistory('failpost')
Jamie Lennox7655b552017-03-17 12:33:38 +11002055 with self.jobLog(build_failpost):
2056 self.assertEqual(build_failpost.result, 'POST_FAILURE')
Tobias Henkel077f2f32017-05-30 20:16:46 +02002057 build_check_vars = self.getJobFromHistory('check-vars')
Jamie Lennox7655b552017-03-17 12:33:38 +11002058 with self.jobLog(build_check_vars):
2059 self.assertEqual(build_check_vars.result, 'SUCCESS')
Monty Tayloraff8b402017-08-16 18:40:41 -05002060 build_check_secret_names = self.getJobFromHistory('check-secret-names')
2061 with self.jobLog(build_check_secret_names):
2062 self.assertEqual(build_check_secret_names.result, 'SUCCESS')
Tobias Henkel077f2f32017-05-30 20:16:46 +02002063 build_hello = self.getJobFromHistory('hello-world')
Jamie Lennox7655b552017-03-17 12:33:38 +11002064 with self.jobLog(build_hello):
2065 self.assertEqual(build_hello.result, 'SUCCESS')
Tobias Henkel077f2f32017-05-30 20:16:46 +02002066 build_python27 = self.getJobFromHistory('python27')
Jamie Lennox7655b552017-03-17 12:33:38 +11002067 with self.jobLog(build_python27):
2068 self.assertEqual(build_python27.result, 'SUCCESS')
2069 flag_path = os.path.join(self.test_root,
2070 build_python27.uuid + '.flag')
2071 self.assertTrue(os.path.exists(flag_path))
2072 copied_path = os.path.join(self.test_root, build_python27.uuid +
2073 '.copied')
2074 self.assertTrue(os.path.exists(copied_path))
2075 failed_path = os.path.join(self.test_root, build_python27.uuid +
2076 '.failed')
2077 self.assertFalse(os.path.exists(failed_path))
2078 pre_flag_path = os.path.join(self.test_root, build_python27.uuid +
2079 '.pre.flag')
2080 self.assertTrue(os.path.exists(pre_flag_path))
2081 post_flag_path = os.path.join(self.test_root, build_python27.uuid +
2082 '.post.flag')
2083 self.assertTrue(os.path.exists(post_flag_path))
2084 bare_role_flag_path = os.path.join(self.test_root,
2085 build_python27.uuid +
2086 '.bare-role.flag')
2087 self.assertTrue(os.path.exists(bare_role_flag_path))
2088 secrets_path = os.path.join(self.test_root,
2089 build_python27.uuid + '.secrets')
2090 with open(secrets_path) as f:
2091 self.assertEqual(f.read(), "test-username test-password")
James E. Blairb9c0d772017-03-03 14:34:49 -08002092
Jamie Lennox7655b552017-03-17 12:33:38 +11002093 msg = A.messages[0]
2094 success = "{} https://success.example.com/zuul-logs/{}"
2095 fail = "{} https://failure.example.com/zuul-logs/{}"
2096 self.assertIn(success.format("python27", build_python27.uuid), msg)
2097 self.assertIn(fail.format("faillocal", build_faillocal.uuid), msg)
2098 self.assertIn(success.format("check-vars",
2099 build_check_vars.uuid), msg)
2100 self.assertIn(success.format("hello-world", build_hello.uuid), msg)
2101 self.assertIn(fail.format("timeout", build_timeout.uuid), msg)
2102 self.assertIn(fail.format("failpost", build_failpost.uuid), msg)
Tobias Henkel077f2f32017-05-30 20:16:46 +02002103
James E. Blairabbaa6f2017-04-06 16:11:44 -07002104 def _add_job(self, job_name):
2105 conf = textwrap.dedent(
2106 """
2107 - job:
2108 name: %s
James E. Blair2f589fe2017-10-26 12:57:41 -07002109 run: playbooks/%s.yaml
James E. Blairabbaa6f2017-04-06 16:11:44 -07002110
2111 - project:
2112 name: org/plugin-project
2113 check:
2114 jobs:
2115 - %s
James E. Blair2f589fe2017-10-26 12:57:41 -07002116 """ % (job_name, job_name, job_name))
James E. Blairabbaa6f2017-04-06 16:11:44 -07002117
2118 file_dict = {'.zuul.yaml': conf}
2119 A = self.fake_gerrit.addFakeChange('org/plugin-project', 'master', 'A',
2120 files=file_dict)
2121 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2122 self.waitUntilSettled()
2123
2124 def test_plugins(self):
2125 # Keep the jobdir around so we can inspect contents if an
2126 # assert fails.
2127 self.executor_server.keep_jobdir = True
2128 # Output extra ansible info so we might see errors.
2129 self.executor_server.verbose = True
2130
2131 count = 0
2132 plugin_tests = [
2133 ('passwd', 'FAILURE'),
2134 ('cartesian', 'SUCCESS'),
2135 ('consul_kv', 'FAILURE'),
2136 ('credstash', 'FAILURE'),
2137 ('csvfile_good', 'SUCCESS'),
2138 ('csvfile_bad', 'FAILURE'),
Monty Taylor93ad2212017-08-02 14:59:50 -05002139 ('uri_bad_path', 'FAILURE'),
2140 ('uri_bad_scheme', 'FAILURE'),
Monty Taylor788a40e2017-08-02 16:14:05 -05002141 ('block_local_override', 'FAILURE'),
Monty Taylor8da768f2017-08-31 14:15:35 -05002142 ('file_local_good', 'SUCCESS'),
2143 ('file_local_bad', 'FAILURE'),
James E. Blairabbaa6f2017-04-06 16:11:44 -07002144 ]
2145 for job_name, result in plugin_tests:
2146 count += 1
2147 self._add_job(job_name)
2148
2149 job = self.getJobFromHistory(job_name)
2150 with self.jobLog(job):
2151 self.assertEqual(count, len(self.history))
2152 build = self.history[-1]
2153 self.assertEqual(build.result, result)
2154
2155 # TODOv3(jeblair): parse the ansible output and verify we're
2156 # getting the exception we expect.
2157
James E. Blairb9c0d772017-03-03 14:34:49 -08002158
James E. Blaira4d4eef2017-06-30 14:49:17 -07002159class TestPrePlaybooks(AnsibleZuulTestCase):
2160 # A temporary class to hold new tests while others are disabled
2161
2162 tenant_config_file = 'config/pre-playbook/main.yaml'
2163
2164 def test_pre_playbook_fail(self):
2165 # Test that we run the post playbooks (but not the actual
2166 # playbook) when a pre-playbook fails.
2167 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2168 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2169 self.waitUntilSettled()
2170 build = self.getJobFromHistory('python27')
2171 self.assertIsNone(build.result)
2172 self.assertIn('RETRY_LIMIT', A.messages[0])
2173 flag_path = os.path.join(self.test_root, build.uuid +
2174 '.main.flag')
2175 self.assertFalse(os.path.exists(flag_path))
2176 pre_flag_path = os.path.join(self.test_root, build.uuid +
2177 '.pre.flag')
2178 self.assertFalse(os.path.exists(pre_flag_path))
2179 post_flag_path = os.path.join(self.test_root, build.uuid +
2180 '.post.flag')
James E. Blair21037782017-07-19 11:56:55 -07002181 self.assertTrue(os.path.exists(post_flag_path),
2182 "The file %s should exist" % post_flag_path)
James E. Blaira4d4eef2017-06-30 14:49:17 -07002183
2184
James E. Blairbacbb882017-10-17 09:48:23 -07002185class TestPostPlaybooks(AnsibleZuulTestCase):
2186 tenant_config_file = 'config/post-playbook/main.yaml'
2187
2188 def test_post_playbook_abort(self):
2189 # Test that when we abort a job in the post playbook, that we
2190 # don't send back POST_FAILURE.
2191 self.executor_server.verbose = True
2192 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2193 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2194
2195 while not len(self.builds):
2196 time.sleep(0.1)
2197 build = self.builds[0]
2198
2199 post_start = os.path.join(self.test_root, build.uuid +
2200 '.post_start.flag')
2201 start = time.time()
2202 while time.time() < start + 90:
2203 if os.path.exists(post_start):
2204 break
2205 time.sleep(0.1)
2206 # The post playbook has started, abort the job
2207 self.fake_gerrit.addEvent(A.getChangeAbandonedEvent())
2208 self.waitUntilSettled()
2209
2210 build = self.getJobFromHistory('python27')
2211 self.assertEqual('ABORTED', build.result)
2212
2213 post_end = os.path.join(self.test_root, build.uuid +
2214 '.post_end.flag')
2215 self.assertTrue(os.path.exists(post_start))
2216 self.assertFalse(os.path.exists(post_end))
2217
2218
James E. Blairb9c0d772017-03-03 14:34:49 -08002219class TestBrokenConfig(ZuulTestCase):
2220 # Test that we get an appropriate syntax error if we start with a
2221 # broken config.
2222
2223 tenant_config_file = 'config/broken/main.yaml'
2224
2225 def setUp(self):
2226 with testtools.ExpectedException(
2227 zuul.configloader.ConfigurationSyntaxError,
2228 "\nZuul encountered a syntax error"):
2229 super(TestBrokenConfig, self).setUp()
2230
2231 def test_broken_config_on_startup(self):
2232 pass
Ricardo Carrillo Cruz22994f92016-12-02 11:41:58 +00002233
2234
2235class TestProjectKeys(ZuulTestCase):
2236 # Test that we can generate project keys
2237
2238 # Normally the test infrastructure copies a static key in place
2239 # for each project before starting tests. This saves time because
2240 # Zuul's automatic key-generation on startup can be slow. To make
2241 # sure we exercise that code, in this test we allow Zuul to create
2242 # keys for the project on startup.
2243 create_project_keys = True
Tobias Henkelabf973e2017-07-28 10:07:34 +02002244 config_file = 'zuul-connections-gerrit-and-github.conf'
Ricardo Carrillo Cruz22994f92016-12-02 11:41:58 +00002245 tenant_config_file = 'config/in-repo/main.yaml'
2246
2247 def test_key_generation(self):
2248 key_root = os.path.join(self.state_root, 'keys')
2249 private_key_file = os.path.join(key_root, 'gerrit/org/project.pem')
2250 # Make sure that a proper key was created on startup
2251 with open(private_key_file, "rb") as f:
James E. Blairbf1a4f22017-03-17 10:59:37 -07002252 private_key, public_key = \
2253 encryption.deserialize_rsa_keypair(f.read())
Ricardo Carrillo Cruz22994f92016-12-02 11:41:58 +00002254
2255 with open(os.path.join(FIXTURE_DIR, 'private.pem')) as i:
2256 fixture_private_key = i.read()
2257
2258 # Make sure that we didn't just end up with the static fixture
2259 # key
2260 self.assertNotEqual(fixture_private_key, private_key)
2261
2262 # Make sure it's the right length
2263 self.assertEqual(4096, private_key.key_size)
James E. Blairbce76932017-05-04 10:03:15 -07002264
2265
James E. Blairbb94dfa2017-07-11 07:45:19 -07002266class RoleTestCase(ZuulTestCase):
James E. Blair1b27f6a2017-07-14 14:09:07 -07002267 def _assertRolePath(self, build, playbook, content):
2268 path = os.path.join(self.test_root, build.uuid,
2269 'ansible', playbook, 'ansible.cfg')
2270 roles_paths = []
2271 with open(path) as f:
2272 for line in f:
2273 if line.startswith('roles_path'):
2274 roles_paths.append(line)
2275 print(roles_paths)
2276 if content:
2277 self.assertEqual(len(roles_paths), 1,
2278 "Should have one roles_path line in %s" %
2279 (playbook,))
2280 self.assertIn(content, roles_paths[0])
2281 else:
2282 self.assertEqual(len(roles_paths), 0,
2283 "Should have no roles_path line in %s" %
2284 (playbook,))
2285
James E. Blairbb94dfa2017-07-11 07:45:19 -07002286
2287class TestRoles(RoleTestCase):
2288 tenant_config_file = 'config/roles/main.yaml'
2289
James E. Blairbce76932017-05-04 10:03:15 -07002290 def test_role(self):
2291 # This exercises a proposed change to a role being checked out
2292 # and used.
2293 A = self.fake_gerrit.addFakeChange('bare-role', 'master', 'A')
2294 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2295 B.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
2296 B.subject, A.data['id'])
2297 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2298 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
2299 self.waitUntilSettled()
2300 self.assertHistory([
2301 dict(name='project-test', result='SUCCESS', changes='1,1 2,1'),
2302 ])
James E. Blair6459db12017-06-29 14:57:20 -07002303
James E. Blair1b27f6a2017-07-14 14:09:07 -07002304 def test_role_inheritance(self):
2305 self.executor_server.hold_jobs_in_build = True
2306 conf = textwrap.dedent(
2307 """
2308 - job:
2309 name: parent
2310 roles:
2311 - zuul: bare-role
Ian Wienand548c43c2017-12-05 14:16:32 +11002312 pre-run: playbooks/parent-pre.yaml
2313 post-run: playbooks/parent-post.yaml
James E. Blair1b27f6a2017-07-14 14:09:07 -07002314
2315 - job:
2316 name: project-test
2317 parent: parent
James E. Blair2f589fe2017-10-26 12:57:41 -07002318 run: playbooks/project-test.yaml
James E. Blair1b27f6a2017-07-14 14:09:07 -07002319 roles:
2320 - zuul: org/project
2321
2322 - project:
2323 name: org/project
2324 check:
2325 jobs:
2326 - project-test
2327 """)
2328
2329 file_dict = {'.zuul.yaml': conf}
2330 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
2331 files=file_dict)
2332 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2333 self.waitUntilSettled()
2334
2335 self.assertEqual(len(self.builds), 1)
2336 build = self.getBuildByName('project-test')
2337 self._assertRolePath(build, 'pre_playbook_0', 'role_0')
2338 self._assertRolePath(build, 'playbook_0', 'role_0')
2339 self._assertRolePath(build, 'playbook_0', 'role_1')
2340 self._assertRolePath(build, 'post_playbook_0', 'role_0')
2341
2342 self.executor_server.hold_jobs_in_build = False
2343 self.executor_server.release()
2344 self.waitUntilSettled()
2345
2346 self.assertHistory([
2347 dict(name='project-test', result='SUCCESS', changes='1,1'),
2348 ])
2349
James E. Blair6f699732017-07-18 14:19:11 -07002350 def test_role_error(self):
2351 conf = textwrap.dedent(
2352 """
2353 - job:
2354 name: project-test
James E. Blair2f589fe2017-10-26 12:57:41 -07002355 run: playbooks/project-test.yaml
James E. Blair6f699732017-07-18 14:19:11 -07002356 roles:
2357 - zuul: common-config
2358
2359 - project:
2360 name: org/project
2361 check:
2362 jobs:
2363 - project-test
2364 """)
2365
2366 file_dict = {'.zuul.yaml': conf}
2367 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
2368 files=file_dict)
2369 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2370 self.waitUntilSettled()
2371 self.assertIn(
2372 '- project-test project-test : ERROR Unable to find role',
2373 A.messages[-1])
2374
James E. Blair6459db12017-06-29 14:57:20 -07002375
James E. Blairbb94dfa2017-07-11 07:45:19 -07002376class TestImplicitRoles(RoleTestCase):
2377 tenant_config_file = 'config/implicit-roles/main.yaml'
2378
2379 def test_missing_roles(self):
2380 # Test implicit and explicit roles for a project which does
2381 # not have roles. The implicit role should be silently
2382 # ignored since the project doesn't supply roles, but if a
2383 # user declares an explicit role, it should error.
2384 self.executor_server.hold_jobs_in_build = True
2385 A = self.fake_gerrit.addFakeChange('org/norole-project', 'master', 'A')
2386 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2387 self.waitUntilSettled()
2388
2389 self.assertEqual(len(self.builds), 2)
2390 build = self.getBuildByName('implicit-role-fail')
2391 self._assertRolePath(build, 'playbook_0', None)
2392
2393 self.executor_server.hold_jobs_in_build = False
2394 self.executor_server.release()
2395 self.waitUntilSettled()
2396 # The retry_limit doesn't get recorded
2397 self.assertHistory([
2398 dict(name='implicit-role-fail', result='SUCCESS', changes='1,1'),
2399 ])
2400
2401 def test_roles(self):
2402 # Test implicit and explicit roles for a project which does
2403 # have roles. In both cases, we should end up with the role
2404 # in the path. In the explicit case, ensure we end up with
2405 # the name we specified.
2406 self.executor_server.hold_jobs_in_build = True
2407 A = self.fake_gerrit.addFakeChange('org/role-project', 'master', 'A')
2408 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2409 self.waitUntilSettled()
2410
2411 self.assertEqual(len(self.builds), 2)
2412 build = self.getBuildByName('implicit-role-ok')
2413 self._assertRolePath(build, 'playbook_0', 'role_0')
2414
2415 build = self.getBuildByName('explicit-role-ok')
2416 self._assertRolePath(build, 'playbook_0', 'role_0')
2417
2418 self.executor_server.hold_jobs_in_build = False
2419 self.executor_server.release()
2420 self.waitUntilSettled()
2421 self.assertHistory([
2422 dict(name='implicit-role-ok', result='SUCCESS', changes='1,1'),
2423 dict(name='explicit-role-ok', result='SUCCESS', changes='1,1'),
2424 ], ordered=False)
2425
2426
James E. Blair6459db12017-06-29 14:57:20 -07002427class TestShadow(ZuulTestCase):
2428 tenant_config_file = 'config/shadow/main.yaml'
2429
2430 def test_shadow(self):
2431 # Test that a repo is allowed to shadow another's job definitions.
2432 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2433 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2434 self.waitUntilSettled()
2435 self.assertHistory([
2436 dict(name='test1', result='SUCCESS', changes='1,1'),
2437 dict(name='test2', result='SUCCESS', changes='1,1'),
James E. Blairadafa6c2017-07-12 08:50:56 -07002438 ], ordered=False)
James E. Blair196f61a2017-06-30 15:42:29 -07002439
2440
2441class TestDataReturn(AnsibleZuulTestCase):
2442 tenant_config_file = 'config/data-return/main.yaml'
2443
2444 def test_data_return(self):
James E. Blair196f61a2017-06-30 15:42:29 -07002445 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2446 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2447 self.waitUntilSettled()
2448 self.assertHistory([
2449 dict(name='data-return', result='SUCCESS', changes='1,1'),
James E. Blair88e79c02017-07-07 13:36:54 -07002450 dict(name='data-return-relative', result='SUCCESS', changes='1,1'),
James E. Blair698703c2017-09-15 20:58:30 -06002451 dict(name='child', result='SUCCESS', changes='1,1'),
James E. Blair88e79c02017-07-07 13:36:54 -07002452 ], ordered=False)
2453 self.assertIn('- data-return http://example.com/test/log/url/',
2454 A.messages[-1])
2455 self.assertIn('- data-return-relative '
2456 'http://example.com/test/log/url/docs/index.html',
James E. Blair196f61a2017-06-30 15:42:29 -07002457 A.messages[-1])
Clint Byrumdc8a0902017-07-20 16:36:27 -07002458
2459
2460class TestDiskAccounting(AnsibleZuulTestCase):
2461 config_file = 'zuul-disk-accounting.conf'
2462 tenant_config_file = 'config/disk-accountant/main.yaml'
2463
2464 def test_disk_accountant_kills_job(self):
2465 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2466 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2467 self.waitUntilSettled()
2468 self.assertHistory([
2469 dict(name='dd-big-empty-file', result='ABORTED', changes='1,1')])
Tristan Cacqueray82f864b2017-08-01 05:54:42 +00002470
2471
2472class TestMaxNodesPerJob(AnsibleZuulTestCase):
2473 tenant_config_file = 'config/multi-tenant/main.yaml'
2474
Tristan Cacquerayc98bff72017-09-10 15:25:26 +00002475 def test_max_timeout_exceeded(self):
Tristan Cacqueray82f864b2017-08-01 05:54:42 +00002476 in_repo_conf = textwrap.dedent(
2477 """
2478 - job:
2479 name: test-job
James E. Blair7e3e6882017-09-20 15:47:13 -07002480 nodeset:
2481 nodes:
2482 - name: node01
2483 label: fake
2484 - name: node02
2485 label: fake
2486 - name: node03
2487 label: fake
2488 - name: node04
2489 label: fake
2490 - name: node05
2491 label: fake
2492 - name: node06
2493 label: fake
Tristan Cacqueray82f864b2017-08-01 05:54:42 +00002494 """)
2495 file_dict = {'.zuul.yaml': in_repo_conf}
2496 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A',
2497 files=file_dict)
2498 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2499 self.waitUntilSettled()
2500 self.assertIn('The job "test-job" exceeds tenant max-nodes-per-job 5.',
2501 A.messages[0], "A should fail because of nodes limit")
2502
2503 B = self.fake_gerrit.addFakeChange('org/project2', 'master', 'A',
2504 files=file_dict)
2505 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
2506 self.waitUntilSettled()
2507 self.assertNotIn("exceeds tenant max-nodes", B.messages[0],
2508 "B should not fail because of nodes limit")
James E. Blair2bab6e72017-08-07 09:52:45 -07002509
2510
Tristan Cacquerayc98bff72017-09-10 15:25:26 +00002511class TestMaxTimeout(AnsibleZuulTestCase):
2512 tenant_config_file = 'config/multi-tenant/main.yaml'
2513
2514 def test_max_nodes_reached(self):
2515 in_repo_conf = textwrap.dedent(
2516 """
2517 - job:
2518 name: test-job
2519 timeout: 3600
2520 """)
2521 file_dict = {'.zuul.yaml': in_repo_conf}
2522 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A',
2523 files=file_dict)
2524 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2525 self.waitUntilSettled()
2526 self.assertIn('The job "test-job" exceeds tenant max-job-timeout',
2527 A.messages[0], "A should fail because of timeout limit")
2528
2529 B = self.fake_gerrit.addFakeChange('org/project2', 'master', 'A',
2530 files=file_dict)
2531 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
2532 self.waitUntilSettled()
2533 self.assertNotIn("exceeds tenant max-job-timeout", B.messages[0],
2534 "B should not fail because of timeout limit")
2535
2536
James E. Blair7edc25f2017-10-26 10:47:14 -07002537class TestPragma(ZuulTestCase):
2538 tenant_config_file = 'config/pragma/main.yaml'
2539
2540 def test_no_pragma(self):
2541 self.create_branch('org/project', 'stable')
2542 with open(os.path.join(FIXTURE_DIR,
2543 'config/pragma/git/',
2544 'org_project/nopragma.yaml')) as f:
2545 config = f.read()
2546 file_dict = {'.zuul.yaml': config}
2547 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
2548 files=file_dict)
2549 A.addApproval('Code-Review', 2)
2550 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
2551 self.waitUntilSettled()
2552 self.fake_gerrit.addEvent(A.getChangeMergedEvent())
2553 self.waitUntilSettled()
2554
2555 # This is an untrusted repo with 2 branches, so it should have
2556 # an implied branch matcher for the job.
2557 tenant = self.sched.abide.tenants.get('tenant-one')
2558 jobs = tenant.layout.getJobs('test-job')
2559 self.assertEqual(len(jobs), 1)
2560 for job in tenant.layout.getJobs('test-job'):
2561 self.assertIsNotNone(job.branch_matcher)
2562
2563 def test_pragma(self):
2564 self.create_branch('org/project', 'stable')
2565 with open(os.path.join(FIXTURE_DIR,
2566 'config/pragma/git/',
2567 'org_project/pragma.yaml')) as f:
2568 config = f.read()
2569 file_dict = {'.zuul.yaml': config}
2570 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
2571 files=file_dict)
2572 A.addApproval('Code-Review', 2)
2573 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
2574 self.waitUntilSettled()
2575 self.fake_gerrit.addEvent(A.getChangeMergedEvent())
2576 self.waitUntilSettled()
2577
2578 # This is an untrusted repo with 2 branches, so it would
2579 # normally have an implied branch matcher, but our pragma
2580 # overrides it.
2581 tenant = self.sched.abide.tenants.get('tenant-one')
2582 jobs = tenant.layout.getJobs('test-job')
2583 self.assertEqual(len(jobs), 1)
2584 for job in tenant.layout.getJobs('test-job'):
2585 self.assertIsNone(job.branch_matcher)
2586
2587
James E. Blair37c3d8c2017-12-13 15:06:11 -08002588class TestPragmaMultibranch(ZuulTestCase):
2589 tenant_config_file = 'config/pragma-multibranch/main.yaml'
2590
2591 def test_no_branch_matchers(self):
2592 self.create_branch('org/project1', 'stable/pike')
2593 self.create_branch('org/project2', 'stable/jewel')
2594 self.fake_gerrit.addEvent(
2595 self.fake_gerrit.getFakeBranchCreatedEvent(
2596 'org/project1', 'stable/pike'))
2597 self.fake_gerrit.addEvent(
2598 self.fake_gerrit.getFakeBranchCreatedEvent(
2599 'org/project2', 'stable/jewel'))
2600 self.waitUntilSettled()
2601 # We want the jobs defined on the stable/pike branch of
2602 # project1 to apply to the stable/jewel branch of project2.
2603
2604 # First, without the pragma line, the jobs should not run
2605 # because in project1 they have branch matchers for pike, so
2606 # they will not match a jewel change.
2607 B = self.fake_gerrit.addFakeChange('org/project2', 'stable/jewel', 'B')
2608 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
2609 self.waitUntilSettled()
2610 self.assertHistory([])
2611
2612 # Add a pragma line to disable implied branch matchers in
2613 # project1, so that the jobs and templates apply to both
2614 # branches.
2615 with open(os.path.join(FIXTURE_DIR,
2616 'config/pragma-multibranch/git/',
2617 'org_project1/zuul.yaml')) as f:
2618 config = f.read()
2619 extra_conf = textwrap.dedent(
2620 """
2621 - pragma:
2622 implied-branch-matchers: False
2623 """)
2624 config = extra_conf + config
2625 file_dict = {'zuul.yaml': config}
2626 A = self.fake_gerrit.addFakeChange('org/project1', 'stable/pike', 'A',
2627 files=file_dict)
2628 A.addApproval('Code-Review', 2)
2629 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
2630 self.waitUntilSettled()
2631 self.fake_gerrit.addEvent(A.getChangeMergedEvent())
2632 self.waitUntilSettled()
2633
2634 # Now verify that when we propose a change to jewel, we get
2635 # the pike/jewel jobs.
2636 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
2637 self.waitUntilSettled()
2638 self.assertHistory([
2639 dict(name='test-job1', result='SUCCESS', changes='1,1'),
2640 dict(name='test-job2', result='SUCCESS', changes='1,1'),
2641 ], ordered=False)
2642
2643 def test_supplied_branch_matchers(self):
2644 self.create_branch('org/project1', 'stable/pike')
2645 self.create_branch('org/project2', 'stable/jewel')
2646 self.fake_gerrit.addEvent(
2647 self.fake_gerrit.getFakeBranchCreatedEvent(
2648 'org/project1', 'stable/pike'))
2649 self.fake_gerrit.addEvent(
2650 self.fake_gerrit.getFakeBranchCreatedEvent(
2651 'org/project2', 'stable/jewel'))
2652 self.waitUntilSettled()
2653 # We want the jobs defined on the stable/pike branch of
2654 # project1 to apply to the stable/jewel branch of project2.
2655
2656 # First, without the pragma line, the jobs should not run
2657 # because in project1 they have branch matchers for pike, so
2658 # they will not match a jewel change.
2659 B = self.fake_gerrit.addFakeChange('org/project2', 'stable/jewel', 'B')
2660 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
2661 self.waitUntilSettled()
2662 self.assertHistory([])
2663
2664 # Add a pragma line to disable implied branch matchers in
2665 # project1, so that the jobs and templates apply to both
2666 # branches.
2667 with open(os.path.join(FIXTURE_DIR,
2668 'config/pragma-multibranch/git/',
2669 'org_project1/zuul.yaml')) as f:
2670 config = f.read()
2671 extra_conf = textwrap.dedent(
2672 """
2673 - pragma:
2674 implied-branches:
2675 - stable/pike
2676 - stable/jewel
2677 """)
2678 config = extra_conf + config
2679 file_dict = {'zuul.yaml': config}
2680 A = self.fake_gerrit.addFakeChange('org/project1', 'stable/pike', 'A',
2681 files=file_dict)
2682 A.addApproval('Code-Review', 2)
2683 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
2684 self.waitUntilSettled()
2685 self.fake_gerrit.addEvent(A.getChangeMergedEvent())
2686 self.waitUntilSettled()
2687 # Now verify that when we propose a change to jewel, we get
2688 # the pike/jewel jobs.
2689 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
2690 self.waitUntilSettled()
2691 self.assertHistory([
2692 dict(name='test-job1', result='SUCCESS', changes='1,1'),
2693 dict(name='test-job2', result='SUCCESS', changes='1,1'),
2694 ], ordered=False)
2695
2696
James E. Blair2bab6e72017-08-07 09:52:45 -07002697class TestBaseJobs(ZuulTestCase):
2698 tenant_config_file = 'config/base-jobs/main.yaml'
2699
2700 def test_multiple_base_jobs(self):
2701 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2702 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2703 self.waitUntilSettled()
2704 self.assertHistory([
2705 dict(name='my-job', result='SUCCESS', changes='1,1'),
2706 dict(name='other-job', result='SUCCESS', changes='1,1'),
2707 ], ordered=False)
2708 self.assertEqual(self.getJobFromHistory('my-job').
2709 parameters['zuul']['jobtags'],
2710 ['mybase'])
2711 self.assertEqual(self.getJobFromHistory('other-job').
2712 parameters['zuul']['jobtags'],
2713 ['otherbase'])
2714
2715 def test_untrusted_base_job(self):
2716 """Test that a base job may not be defined in an untrusted repo"""
2717 in_repo_conf = textwrap.dedent(
2718 """
2719 - job:
2720 name: fail-base
2721 parent: null
2722 """)
2723
2724 file_dict = {'.zuul.yaml': in_repo_conf}
2725 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
2726 files=file_dict)
2727 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2728 self.waitUntilSettled()
2729 self.assertEqual(A.reported, 1,
2730 "A should report failure")
2731 self.assertEqual(A.patchsets[0]['approvals'][0]['value'], "-1")
2732 self.assertIn('Base jobs must be defined in config projects',
2733 A.messages[0])
2734 self.assertHistory([])
James E. Blairdb089032017-08-15 13:42:12 -07002735
2736
James E. Blaira17a8e72018-01-17 13:45:25 -08002737class TestSecrets(ZuulTestCase):
2738 tenant_config_file = 'config/secrets/main.yaml'
2739 secret = {'password': 'test-password',
2740 'username': 'test-username'}
2741
2742 def _getSecrets(self, job, pbtype):
2743 secrets = []
2744 build = self.getJobFromHistory(job)
2745 for pb in build.parameters[pbtype]:
2746 secrets.append(pb['secrets'])
2747 return secrets
2748
2749 def test_secret_branch(self):
2750 # Test that we can use a secret defined in another branch of
2751 # the same project.
2752 self.create_branch('org/project2', 'stable')
2753 self.fake_gerrit.addEvent(
2754 self.fake_gerrit.getFakeBranchCreatedEvent(
2755 'org/project2', 'stable'))
2756 self.waitUntilSettled()
2757
2758 with open(os.path.join(FIXTURE_DIR,
2759 'config/secrets/git/',
2760 'org_project2/zuul-secret.yaml')) as f:
2761 config = f.read()
2762
2763 file_dict = {'zuul.yaml': config}
2764 A = self.fake_gerrit.addFakeChange('org/project2', 'master', 'A',
2765 files=file_dict)
2766 A.addApproval('Code-Review', 2)
2767 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
2768 self.waitUntilSettled()
2769 self.assertEqual(A.data['status'], 'MERGED')
2770 self.fake_gerrit.addEvent(A.getChangeMergedEvent())
2771 self.waitUntilSettled()
2772
2773 in_repo_conf = textwrap.dedent(
2774 """
2775 - job:
2776 parent: base
2777 name: project2-secret
2778 run: playbooks/secret.yaml
2779 secrets: [project2_secret]
2780
2781 - project:
2782 check:
2783 jobs:
2784 - project2-secret
2785 gate:
2786 jobs:
2787 - noop
2788 """)
2789 file_dict = {'zuul.yaml': in_repo_conf}
2790 B = self.fake_gerrit.addFakeChange('org/project2', 'stable', 'B',
2791 files=file_dict)
2792 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
2793 self.waitUntilSettled()
2794 self.assertEqual(B.reported, 1, "B should report success")
2795 self.assertHistory([
2796 dict(name='project2-secret', result='SUCCESS', changes='2,1'),
2797 ])
2798 self.assertEqual(
2799 self._getSecrets('project2-secret', 'playbooks'),
2800 [{'project2_secret': self.secret}])
2801
2802 def test_secret_branch_duplicate(self):
2803 # Test that we can create a duplicate secret on a different
2804 # branch of the same project -- i.e., that when we branch
2805 # master to stable on a project with a secret, nothing
2806 # changes.
2807 self.create_branch('org/project1', 'stable')
2808 self.fake_gerrit.addEvent(
2809 self.fake_gerrit.getFakeBranchCreatedEvent(
2810 'org/project1', 'stable'))
2811 self.waitUntilSettled()
2812
2813 A = self.fake_gerrit.addFakeChange('org/project1', 'stable', 'A')
2814 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2815 self.waitUntilSettled()
2816 self.assertEqual(A.reported, 1,
2817 "A should report success")
2818 self.assertHistory([
2819 dict(name='project1-secret', result='SUCCESS', changes='1,1'),
2820 ])
2821 self.assertEqual(
2822 self._getSecrets('project1-secret', 'playbooks'),
2823 [{'project1_secret': self.secret}])
2824
2825 def test_secret_branch_error_same_branch(self):
2826 # Test that we are unable to define a secret twice on the same
2827 # project-branch.
2828 in_repo_conf = textwrap.dedent(
2829 """
2830 - secret:
2831 name: project1_secret
2832 data: {}
2833 - secret:
2834 name: project1_secret
2835 data: {}
2836 """)
2837 file_dict = {'zuul.yaml': in_repo_conf}
2838 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A',
2839 files=file_dict)
2840 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2841 self.waitUntilSettled()
2842 self.assertIn('already defined', A.messages[0])
2843
2844 def test_secret_branch_error_same_project(self):
2845 # Test that we are unable to create a secret which differs
2846 # from another with the same name -- i.e., that if we have a
2847 # duplicate secret on multiple branches of the same project,
2848 # they must be identical.
2849 self.create_branch('org/project1', 'stable')
2850 self.fake_gerrit.addEvent(
2851 self.fake_gerrit.getFakeBranchCreatedEvent(
2852 'org/project1', 'stable'))
2853 self.waitUntilSettled()
2854
2855 in_repo_conf = textwrap.dedent(
2856 """
2857 - secret:
2858 name: project1_secret
2859 data: {}
2860 """)
2861 file_dict = {'zuul.yaml': in_repo_conf}
2862 A = self.fake_gerrit.addFakeChange('org/project1', 'stable', 'A',
2863 files=file_dict)
2864 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2865 self.waitUntilSettled()
2866 self.assertIn('does not match existing definition in branch master',
2867 A.messages[0])
2868
2869 def test_secret_branch_error_other_project(self):
2870 # Test that we are unable to create a secret with the same
2871 # name as another. We're never allowed to have a secret with
2872 # the same name outside of a project.
2873 in_repo_conf = textwrap.dedent(
2874 """
2875 - secret:
2876 name: project1_secret
2877 data: {}
2878 """)
2879 file_dict = {'zuul.yaml': in_repo_conf}
2880 A = self.fake_gerrit.addFakeChange('org/project2', 'master', 'A',
2881 files=file_dict)
2882 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2883 self.waitUntilSettled()
2884 self.assertIn('already defined in project org/project1',
2885 A.messages[0])
2886
2887
James E. Blairdf91ab32017-10-25 17:57:13 -07002888class TestSecretInheritance(ZuulTestCase):
2889 tenant_config_file = 'config/secret-inheritance/main.yaml'
2890
2891 def _getSecrets(self, job, pbtype):
2892 secrets = []
2893 build = self.getJobFromHistory(job)
2894 for pb in build.parameters[pbtype]:
2895 secrets.append(pb['secrets'])
2896 return secrets
2897
2898 def _checkTrustedSecrets(self):
2899 secret = {'longpassword': 'test-passwordtest-password',
2900 'password': 'test-password',
2901 'username': 'test-username'}
2902 self.assertEqual(
2903 self._getSecrets('trusted-secrets', 'playbooks'),
James E. Blair2f589fe2017-10-26 12:57:41 -07002904 [{'trusted-secret': secret}])
James E. Blairdf91ab32017-10-25 17:57:13 -07002905 self.assertEqual(
2906 self._getSecrets('trusted-secrets', 'pre_playbooks'), [])
2907 self.assertEqual(
2908 self._getSecrets('trusted-secrets', 'post_playbooks'), [])
2909
2910 self.assertEqual(
2911 self._getSecrets('trusted-secrets-trusted-child',
James E. Blair2f589fe2017-10-26 12:57:41 -07002912 'playbooks'), [{}])
James E. Blairdf91ab32017-10-25 17:57:13 -07002913 self.assertEqual(
2914 self._getSecrets('trusted-secrets-trusted-child',
2915 'pre_playbooks'), [])
2916 self.assertEqual(
2917 self._getSecrets('trusted-secrets-trusted-child',
2918 'post_playbooks'), [])
2919
2920 self.assertEqual(
2921 self._getSecrets('trusted-secrets-untrusted-child',
James E. Blair2f589fe2017-10-26 12:57:41 -07002922 'playbooks'), [{}])
James E. Blairdf91ab32017-10-25 17:57:13 -07002923 self.assertEqual(
2924 self._getSecrets('trusted-secrets-untrusted-child',
2925 'pre_playbooks'), [])
2926 self.assertEqual(
2927 self._getSecrets('trusted-secrets-untrusted-child',
2928 'post_playbooks'), [])
2929
2930 def _checkUntrustedSecrets(self):
2931 secret = {'longpassword': 'test-passwordtest-password',
2932 'password': 'test-password',
2933 'username': 'test-username'}
2934 self.assertEqual(
2935 self._getSecrets('untrusted-secrets', 'playbooks'),
James E. Blair2f589fe2017-10-26 12:57:41 -07002936 [{'untrusted-secret': secret}])
James E. Blairdf91ab32017-10-25 17:57:13 -07002937 self.assertEqual(
2938 self._getSecrets('untrusted-secrets', 'pre_playbooks'), [])
2939 self.assertEqual(
2940 self._getSecrets('untrusted-secrets', 'post_playbooks'), [])
2941
2942 self.assertEqual(
2943 self._getSecrets('untrusted-secrets-trusted-child',
James E. Blair2f589fe2017-10-26 12:57:41 -07002944 'playbooks'), [{}])
James E. Blairdf91ab32017-10-25 17:57:13 -07002945 self.assertEqual(
2946 self._getSecrets('untrusted-secrets-trusted-child',
2947 'pre_playbooks'), [])
2948 self.assertEqual(
2949 self._getSecrets('untrusted-secrets-trusted-child',
2950 'post_playbooks'), [])
2951
2952 self.assertEqual(
2953 self._getSecrets('untrusted-secrets-untrusted-child',
James E. Blair2f589fe2017-10-26 12:57:41 -07002954 'playbooks'), [{}])
James E. Blairdf91ab32017-10-25 17:57:13 -07002955 self.assertEqual(
2956 self._getSecrets('untrusted-secrets-untrusted-child',
2957 'pre_playbooks'), [])
2958 self.assertEqual(
2959 self._getSecrets('untrusted-secrets-untrusted-child',
2960 'post_playbooks'), [])
2961
2962 def test_trusted_secret_inheritance_check(self):
2963 A = self.fake_gerrit.addFakeChange('common-config', 'master', 'A')
2964 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2965 self.waitUntilSettled()
2966 self.assertHistory([
2967 dict(name='trusted-secrets', result='SUCCESS', changes='1,1'),
2968 dict(name='trusted-secrets-trusted-child',
2969 result='SUCCESS', changes='1,1'),
2970 dict(name='trusted-secrets-untrusted-child',
2971 result='SUCCESS', changes='1,1'),
2972 ], ordered=False)
2973
2974 self._checkTrustedSecrets()
2975
2976 def test_untrusted_secret_inheritance_gate(self):
2977 A = self.fake_gerrit.addFakeChange('common-config', 'master', 'A')
2978 A.addApproval('Code-Review', 2)
2979 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
2980 self.waitUntilSettled()
2981 self.assertHistory([
2982 dict(name='untrusted-secrets', result='SUCCESS', changes='1,1'),
2983 dict(name='untrusted-secrets-trusted-child',
2984 result='SUCCESS', changes='1,1'),
2985 dict(name='untrusted-secrets-untrusted-child',
2986 result='SUCCESS', changes='1,1'),
2987 ], ordered=False)
2988
2989 self._checkUntrustedSecrets()
2990
2991 def test_untrusted_secret_inheritance_check(self):
2992 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2993 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2994 self.waitUntilSettled()
2995 # This configuration tries to run untrusted secrets in an
2996 # non-post-review pipeline and should therefore run no jobs.
2997 self.assertHistory([])
2998
2999
James E. Blairdb089032017-08-15 13:42:12 -07003000class TestSecretLeaks(AnsibleZuulTestCase):
3001 tenant_config_file = 'config/secret-leaks/main.yaml'
3002
3003 def searchForContent(self, path, content):
3004 matches = []
3005 for (dirpath, dirnames, filenames) in os.walk(path):
3006 for filename in filenames:
3007 filepath = os.path.join(dirpath, filename)
3008 with open(filepath, 'rb') as f:
3009 if content in f.read():
3010 matches.append(filepath[len(path):])
3011 return matches
3012
3013 def _test_secret_file(self):
3014 # Or rather -- test that they *don't* leak.
3015 # Keep the jobdir around so we can inspect contents.
3016 self.executor_server.keep_jobdir = True
3017 conf = textwrap.dedent(
3018 """
3019 - project:
3020 name: org/project
3021 check:
3022 jobs:
3023 - secret-file
3024 """)
3025
3026 file_dict = {'.zuul.yaml': conf}
3027 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
3028 files=file_dict)
3029 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
3030 self.waitUntilSettled()
3031 self.assertHistory([
3032 dict(name='secret-file', result='SUCCESS', changes='1,1'),
3033 ], ordered=False)
3034 matches = self.searchForContent(self.history[0].jobdir.root,
3035 b'test-password')
James E. Blaird6a71ca2017-08-18 14:15:05 -07003036 self.assertEqual(set(['/work/secret-file.txt']),
James E. Blairdb089032017-08-15 13:42:12 -07003037 set(matches))
3038
3039 def test_secret_file(self):
3040 self._test_secret_file()
3041
3042 def test_secret_file_verbose(self):
3043 # Output extra ansible info to exercise alternate logging code
3044 # paths.
3045 self.executor_server.verbose = True
3046 self._test_secret_file()
3047
3048 def _test_secret_file_fail(self):
3049 # Or rather -- test that they *don't* leak.
3050 # Keep the jobdir around so we can inspect contents.
3051 self.executor_server.keep_jobdir = True
3052 conf = textwrap.dedent(
3053 """
3054 - project:
3055 name: org/project
3056 check:
3057 jobs:
3058 - secret-file-fail
3059 """)
3060
3061 file_dict = {'.zuul.yaml': conf}
3062 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
3063 files=file_dict)
3064 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
3065 self.waitUntilSettled()
3066 self.assertHistory([
3067 dict(name='secret-file-fail', result='FAILURE', changes='1,1'),
3068 ], ordered=False)
3069 matches = self.searchForContent(self.history[0].jobdir.root,
3070 b'test-password')
James E. Blaird6a71ca2017-08-18 14:15:05 -07003071 self.assertEqual(set(['/work/failure-file.txt']),
James E. Blairdb089032017-08-15 13:42:12 -07003072 set(matches))
3073
3074 def test_secret_file_fail(self):
3075 self._test_secret_file_fail()
3076
3077 def test_secret_file_fail_verbose(self):
3078 # Output extra ansible info to exercise alternate logging code
3079 # paths.
3080 self.executor_server.verbose = True
3081 self._test_secret_file_fail()
James E. Blaira00910c2017-08-23 09:15:04 -07003082
3083
James E. Blair8446c412018-01-17 15:49:59 -08003084class TestNodesets(ZuulTestCase):
3085 tenant_config_file = 'config/nodesets/main.yaml'
3086
3087 def test_nodeset_branch(self):
3088 # Test that we can use a nodeset defined in another branch of
3089 # the same project.
3090 self.create_branch('org/project2', 'stable')
3091 self.fake_gerrit.addEvent(
3092 self.fake_gerrit.getFakeBranchCreatedEvent(
3093 'org/project2', 'stable'))
3094 self.waitUntilSettled()
3095
3096 with open(os.path.join(FIXTURE_DIR,
3097 'config/nodesets/git/',
3098 'org_project2/zuul-nodeset.yaml')) as f:
3099 config = f.read()
3100
3101 file_dict = {'zuul.yaml': config}
3102 A = self.fake_gerrit.addFakeChange('org/project2', 'master', 'A',
3103 files=file_dict)
3104 A.addApproval('Code-Review', 2)
3105 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
3106 self.waitUntilSettled()
3107 self.assertEqual(A.data['status'], 'MERGED')
3108 self.fake_gerrit.addEvent(A.getChangeMergedEvent())
3109 self.waitUntilSettled()
3110
3111 in_repo_conf = textwrap.dedent(
3112 """
3113 - job:
3114 parent: base
3115 name: project2-test
3116 nodeset: project2-nodeset
3117
3118 - project:
3119 check:
3120 jobs:
3121 - project2-test
3122 gate:
3123 jobs:
3124 - noop
3125 """)
3126 file_dict = {'zuul.yaml': in_repo_conf}
3127 B = self.fake_gerrit.addFakeChange('org/project2', 'stable', 'B',
3128 files=file_dict)
3129 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
3130 self.waitUntilSettled()
3131 self.assertEqual(B.reported, 1, "B should report success")
3132 self.assertHistory([
3133 dict(name='project2-test', result='SUCCESS', changes='2,1',
3134 node='ubuntu-xenial'),
3135 ])
3136
3137 def test_nodeset_branch_duplicate(self):
Monty Taylorbc1d0bb2018-01-22 17:05:31 -06003138 # Test that we can create a duplicate nodeset on a different
James E. Blair8446c412018-01-17 15:49:59 -08003139 # branch of the same project -- i.e., that when we branch
Monty Taylorbc1d0bb2018-01-22 17:05:31 -06003140 # master to stable on a project with a nodeset, nothing
James E. Blair8446c412018-01-17 15:49:59 -08003141 # changes.
3142 self.create_branch('org/project1', 'stable')
3143 self.fake_gerrit.addEvent(
3144 self.fake_gerrit.getFakeBranchCreatedEvent(
3145 'org/project1', 'stable'))
3146 self.waitUntilSettled()
3147
3148 A = self.fake_gerrit.addFakeChange('org/project1', 'stable', 'A')
3149 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
3150 self.waitUntilSettled()
3151 self.assertEqual(A.reported, 1,
3152 "A should report success")
3153 self.assertHistory([
3154 dict(name='project1-test', result='SUCCESS', changes='1,1',
3155 node='ubuntu-xenial'),
3156 ])
3157
3158 def test_nodeset_branch_error_same_branch(self):
3159 # Test that we are unable to define a nodeset twice on the same
3160 # project-branch.
3161 in_repo_conf = textwrap.dedent(
3162 """
3163 - nodeset:
3164 name: project1-nodeset
3165 nodes: []
3166 - nodeset:
3167 name: project1-nodeset
3168 nodes: []
3169 """)
3170 file_dict = {'zuul.yaml': in_repo_conf}
3171 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A',
3172 files=file_dict)
3173 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
3174 self.waitUntilSettled()
3175 self.assertIn('already defined', A.messages[0])
3176
3177 def test_nodeset_branch_error_same_project(self):
3178 # Test that we are unable to create a nodeset which differs
3179 # from another with the same name -- i.e., that if we have a
3180 # duplicate nodeset on multiple branches of the same project,
3181 # they must be identical.
3182 self.create_branch('org/project1', 'stable')
3183 self.fake_gerrit.addEvent(
3184 self.fake_gerrit.getFakeBranchCreatedEvent(
3185 'org/project1', 'stable'))
3186 self.waitUntilSettled()
3187
3188 in_repo_conf = textwrap.dedent(
3189 """
3190 - nodeset:
3191 name: project1-nodeset
3192 nodes: []
3193 """)
3194 file_dict = {'zuul.yaml': in_repo_conf}
3195 A = self.fake_gerrit.addFakeChange('org/project1', 'stable', 'A',
3196 files=file_dict)
3197 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
3198 self.waitUntilSettled()
3199 self.assertIn('does not match existing definition in branch master',
3200 A.messages[0])
3201
3202 def test_nodeset_branch_error_other_project(self):
3203 # Test that we are unable to create a nodeset with the same
3204 # name as another. We're never allowed to have a nodeset with
3205 # the same name outside of a project.
3206 in_repo_conf = textwrap.dedent(
3207 """
3208 - nodeset:
3209 name: project1-nodeset
3210 nodes: []
3211 """)
3212 file_dict = {'zuul.yaml': in_repo_conf}
3213 A = self.fake_gerrit.addFakeChange('org/project2', 'master', 'A',
3214 files=file_dict)
3215 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
3216 self.waitUntilSettled()
3217 self.assertIn('already defined in project org/project1',
3218 A.messages[0])
3219
3220
James E. Blair9596b942018-01-18 14:21:44 -08003221class TestSemaphoreBranches(ZuulTestCase):
3222 tenant_config_file = 'config/semaphore-branches/main.yaml'
3223
3224 def test_semaphore_branch(self):
3225 # Test that we can use a semaphore defined in another branch of
3226 # the same project.
3227 self.create_branch('org/project2', 'stable')
3228 self.fake_gerrit.addEvent(
3229 self.fake_gerrit.getFakeBranchCreatedEvent(
3230 'org/project2', 'stable'))
3231 self.waitUntilSettled()
3232
3233 with open(os.path.join(FIXTURE_DIR,
3234 'config/semaphore-branches/git/',
3235 'org_project2/zuul-semaphore.yaml')) as f:
3236 config = f.read()
3237
3238 file_dict = {'zuul.yaml': config}
3239 A = self.fake_gerrit.addFakeChange('org/project2', 'master', 'A',
3240 files=file_dict)
3241 A.addApproval('Code-Review', 2)
3242 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
3243 self.waitUntilSettled()
3244 self.assertEqual(A.data['status'], 'MERGED')
3245 self.fake_gerrit.addEvent(A.getChangeMergedEvent())
3246 self.waitUntilSettled()
3247
3248 in_repo_conf = textwrap.dedent(
3249 """
3250 - job:
3251 parent: base
3252 name: project2-test
3253 semaphore: project2-semaphore
3254
3255 - project:
3256 check:
3257 jobs:
3258 - project2-test
3259 gate:
3260 jobs:
3261 - noop
3262 """)
3263 file_dict = {'zuul.yaml': in_repo_conf}
3264 B = self.fake_gerrit.addFakeChange('org/project2', 'stable', 'B',
3265 files=file_dict)
3266 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
3267 self.waitUntilSettled()
3268 self.assertEqual(B.reported, 1, "B should report success")
3269 self.assertHistory([
3270 dict(name='project2-test', result='SUCCESS', changes='2,1')
3271 ])
3272
3273 def test_semaphore_branch_duplicate(self):
3274 # Test that we can create a duplicate semaphore on a different
3275 # branch of the same project -- i.e., that when we branch
3276 # master to stable on a project with a semaphore, nothing
3277 # changes.
3278 self.create_branch('org/project1', 'stable')
3279 self.fake_gerrit.addEvent(
3280 self.fake_gerrit.getFakeBranchCreatedEvent(
3281 'org/project1', 'stable'))
3282 self.waitUntilSettled()
3283
3284 A = self.fake_gerrit.addFakeChange('org/project1', 'stable', 'A')
3285 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
3286 self.waitUntilSettled()
3287 self.assertEqual(A.reported, 1,
3288 "A should report success")
3289 self.assertHistory([
3290 dict(name='project1-test', result='SUCCESS', changes='1,1')
3291 ])
3292
3293 def test_semaphore_branch_error_same_branch(self):
3294 # Test that we are unable to define a semaphore twice on the same
3295 # project-branch.
3296 in_repo_conf = textwrap.dedent(
3297 """
3298 - semaphore:
3299 name: project1-semaphore
3300 max: 2
3301 - semaphore:
3302 name: project1-semaphore
3303 max: 2
3304 """)
3305 file_dict = {'zuul.yaml': in_repo_conf}
3306 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A',
3307 files=file_dict)
3308 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
3309 self.waitUntilSettled()
3310 self.assertIn('already defined', A.messages[0])
3311
3312 def test_semaphore_branch_error_same_project(self):
3313 # Test that we are unable to create a semaphore which differs
3314 # from another with the same name -- i.e., that if we have a
3315 # duplicate semaphore on multiple branches of the same project,
3316 # they must be identical.
3317 self.create_branch('org/project1', 'stable')
3318 self.fake_gerrit.addEvent(
3319 self.fake_gerrit.getFakeBranchCreatedEvent(
3320 'org/project1', 'stable'))
3321 self.waitUntilSettled()
3322
3323 in_repo_conf = textwrap.dedent(
3324 """
3325 - semaphore:
3326 name: project1-semaphore
3327 max: 4
3328 """)
3329 file_dict = {'zuul.yaml': in_repo_conf}
3330 A = self.fake_gerrit.addFakeChange('org/project1', 'stable', 'A',
3331 files=file_dict)
3332 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
3333 self.waitUntilSettled()
3334 self.assertIn('does not match existing definition in branch master',
3335 A.messages[0])
3336
3337 def test_semaphore_branch_error_other_project(self):
3338 # Test that we are unable to create a semaphore with the same
3339 # name as another. We're never allowed to have a semaphore with
3340 # the same name outside of a project.
3341 in_repo_conf = textwrap.dedent(
3342 """
3343 - semaphore:
3344 name: project1-semaphore
3345 max: 2
3346 """)
3347 file_dict = {'zuul.yaml': in_repo_conf}
3348 A = self.fake_gerrit.addFakeChange('org/project2', 'master', 'A',
3349 files=file_dict)
3350 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
3351 self.waitUntilSettled()
3352 self.assertIn('already defined in project org/project1',
3353 A.messages[0])
3354
3355
James E. Blaira00910c2017-08-23 09:15:04 -07003356class TestJobOutput(AnsibleZuulTestCase):
3357 tenant_config_file = 'config/job-output/main.yaml'
3358
3359 def _get_file(self, build, path):
3360 p = os.path.join(build.jobdir.root, path)
3361 with open(p) as f:
3362 return f.read()
3363
3364 def test_job_output(self):
Monty Taylor0e2489a2017-10-10 11:57:29 -05003365 # Verify that command standard output appears in the job output,
3366 # and that failures in the final playbook get logged.
James E. Blaira00910c2017-08-23 09:15:04 -07003367
3368 # This currently only verifies we receive output from
3369 # localhost. Notably, it does not verify we receive output
3370 # via zuul_console streaming.
3371 self.executor_server.keep_jobdir = True
3372 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
3373 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
3374 self.waitUntilSettled()
3375 self.assertHistory([
3376 dict(name='job-output', result='SUCCESS', changes='1,1'),
3377 ], ordered=False)
3378
3379 token = 'Standard output test %s' % (self.history[0].jobdir.src_root)
3380 j = json.loads(self._get_file(self.history[0],
3381 'work/logs/job-output.json'))
3382 self.assertEqual(token,
3383 j[0]['plays'][0]['tasks'][0]
3384 ['hosts']['localhost']['stdout'])
3385
3386 print(self._get_file(self.history[0],
3387 'work/logs/job-output.txt'))
3388 self.assertIn(token,
3389 self._get_file(self.history[0],
3390 'work/logs/job-output.txt'))
Monty Taylor0e2489a2017-10-10 11:57:29 -05003391
3392 def test_job_output_failure_log(self):
3393 logger = logging.getLogger('zuul.AnsibleJob')
3394 output = io.StringIO()
3395 logger.addHandler(logging.StreamHandler(output))
3396
3397 # Verify that a failure in the last post playbook emits the contents
3398 # of the json output to the log
3399 self.executor_server.keep_jobdir = True
3400 A = self.fake_gerrit.addFakeChange('org/project2', 'master', 'A')
3401 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
3402 self.waitUntilSettled()
3403 self.assertHistory([
3404 dict(name='job-output-failure',
3405 result='POST_FAILURE', changes='1,1'),
3406 ], ordered=False)
3407
3408 token = 'Standard output test %s' % (self.history[0].jobdir.src_root)
3409 j = json.loads(self._get_file(self.history[0],
3410 'work/logs/job-output.json'))
3411 self.assertEqual(token,
3412 j[0]['plays'][0]['tasks'][0]
3413 ['hosts']['localhost']['stdout'])
3414
3415 print(self._get_file(self.history[0],
3416 'work/logs/job-output.json'))
3417 self.assertIn(token,
3418 self._get_file(self.history[0],
3419 'work/logs/job-output.txt'))
3420
3421 log_output = output.getvalue()
3422 self.assertIn('Final playbook failed', log_output)
3423 self.assertIn('Failure test', log_output)