blob: 4f6bbdda2819d50930520d835b396a6771048bfb [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):
77
78 tenant_config_file = 'config/protected/main.yaml'
79
80 def test_protected_ok(self):
81 # test clean usage of final parent job
82 in_repo_conf = textwrap.dedent(
83 """
84 - job:
85 name: job-protected
86 protected: true
87 run: playbooks/job-protected.yaml
88
89 - project:
90 name: org/project
91 check:
92 jobs:
93 - job-child-ok
94
95 - job:
96 name: job-child-ok
97 parent: job-protected
98
99 - project:
100 name: org/project
101 check:
102 jobs:
103 - job-child-ok
104
105 """)
106
107 file_dict = {'zuul.yaml': in_repo_conf}
108 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
109 files=file_dict)
110 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
111 self.waitUntilSettled()
112
113 self.assertEqual(A.reported, 1)
114 self.assertEqual(A.patchsets[-1]['approvals'][0]['value'], '1')
115
116 def test_protected_reset(self):
117 # try to reset protected flag
118 in_repo_conf = textwrap.dedent(
119 """
120 - job:
121 name: job-protected
122 protected: true
123 run: playbooks/job-protected.yaml
124
125 - job:
126 name: job-child-reset-protected
127 parent: job-protected
128 protected: false
129
130 - project:
131 name: org/project
132 check:
133 jobs:
134 - job-child-reset-protected
135
136 """)
137
138 file_dict = {'zuul.yaml': in_repo_conf}
139 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
140 files=file_dict)
141 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
142 self.waitUntilSettled()
143
144 # The second patch tried to override some variables.
145 # Thus it should fail.
146 self.assertEqual(A.reported, 1)
147 self.assertEqual(A.patchsets[-1]['approvals'][0]['value'], '-1')
148 self.assertIn('Unable to reset protected attribute', A.messages[0])
149
150 def test_protected_inherit_not_ok(self):
151 # try to inherit from a protected job in different project
152 in_repo_conf = textwrap.dedent(
153 """
154 - job:
155 name: job-child-notok
156 run: playbooks/job-child-notok.yaml
157 parent: job-protected
158
159 - project:
160 name: org/project1
161 check:
162 jobs:
163 - job-child-notok
164
165 """)
166
167 file_dict = {'zuul.yaml': in_repo_conf}
168 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A',
169 files=file_dict)
170 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
171 self.waitUntilSettled()
172
173 self.assertEqual(A.reported, 1)
174 self.assertEqual(A.patchsets[-1]['approvals'][0]['value'], '-1')
175 self.assertIn(
176 "which is defined in review.example.com/org/project is protected "
177 "and cannot be inherited from other projects.", A.messages[0])
178
179
Tobias Henkel83167622017-06-30 19:45:03 +0200180class TestFinal(ZuulTestCase):
181
182 tenant_config_file = 'config/final/main.yaml'
183
184 def test_final_variant_ok(self):
185 # test clean usage of final parent job
186 in_repo_conf = textwrap.dedent(
187 """
188 - project:
189 name: org/project
190 check:
191 jobs:
192 - job-final
193 """)
194
195 file_dict = {'.zuul.yaml': in_repo_conf}
196 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
197 files=file_dict)
198 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
199 self.waitUntilSettled()
200
201 self.assertEqual(A.reported, 1)
202 self.assertEqual(A.patchsets[-1]['approvals'][0]['value'], '1')
203
204 def test_final_variant_error(self):
205 # test misuse of final parent job
206 in_repo_conf = textwrap.dedent(
207 """
208 - project:
209 name: org/project
210 check:
211 jobs:
212 - job-final:
213 vars:
214 dont_override_this: bar
215 """)
216 file_dict = {'.zuul.yaml': in_repo_conf}
217 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
218 files=file_dict)
219 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
220 self.waitUntilSettled()
221
222 # The second patch tried to override some variables.
223 # Thus it should fail.
224 self.assertEqual(A.reported, 1)
225 self.assertEqual(A.patchsets[-1]['approvals'][0]['value'], '-1')
226 self.assertIn('Unable to modify final job', A.messages[0])
227
228 def test_final_inheritance(self):
229 # test misuse of final parent job
230 in_repo_conf = textwrap.dedent(
231 """
232 - job:
233 name: project-test
234 parent: job-final
James E. Blair2f589fe2017-10-26 12:57:41 -0700235 run: playbooks/project-test.yaml
Tobias Henkel83167622017-06-30 19:45:03 +0200236
237 - project:
238 name: org/project
239 check:
240 jobs:
241 - project-test
242 """)
243
244 in_repo_playbook = textwrap.dedent(
245 """
246 - hosts: all
247 tasks: []
248 """)
249
250 file_dict = {'.zuul.yaml': in_repo_conf,
251 'playbooks/project-test.yaml': in_repo_playbook}
252 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
253 files=file_dict)
254 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
255 self.waitUntilSettled()
256
257 # The second patch tried to override some variables.
258 # Thus it should fail.
259 self.assertEqual(A.reported, 1)
260 self.assertEqual(A.patchsets[-1]['approvals'][0]['value'], '-1')
James E. Blairc32a8352017-10-11 16:27:50 -0700261 self.assertIn('Unable to modify final job', A.messages[0])
Tobias Henkel83167622017-06-30 19:45:03 +0200262
263
James E. Blair1edfd972017-12-01 15:54:24 -0800264class TestBranchTag(ZuulTestCase):
265 tenant_config_file = 'config/branch-tag/main.yaml'
266
267 def test_negative_branch_match(self):
268 # Test that a negative branch matcher works with implied branches.
269 event = self.fake_gerrit.addFakeTag('org/project', 'master', 'foo')
270 self.fake_gerrit.addEvent(event)
271 self.waitUntilSettled()
272 self.assertHistory([
273 dict(name='test-job', result='SUCCESS', ref='refs/tags/foo')])
274
275
James E. Blair9ab8db42017-12-01 15:12:04 -0800276class TestBranchNegative(ZuulTestCase):
277 tenant_config_file = 'config/branch-negative/main.yaml'
278
279 def test_negative_branch_match(self):
280 # Test that a negative branch matcher works with implied branches.
281 self.create_branch('org/project', 'stable/pike')
282 self.fake_gerrit.addEvent(
283 self.fake_gerrit.getFakeBranchCreatedEvent(
284 'org/project', 'stable/pike'))
285 self.waitUntilSettled()
286
287 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
288 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
289 self.waitUntilSettled()
290 B = self.fake_gerrit.addFakeChange('org/project', 'stable/pike', 'A')
291 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
292 self.waitUntilSettled()
293 self.assertHistory([
294 dict(name='test-job', result='SUCCESS', changes='1,1')])
295
296
James E. Blaire36d1a32017-11-28 13:33:38 -0800297class TestBranchTemplates(ZuulTestCase):
298 tenant_config_file = 'config/branch-templates/main.yaml'
299
300 def test_template_removal_from_branch(self):
301 # Test that a template can be removed from one branch but not
302 # another.
303 # This creates a new branch with a copy of the config in master
304 self.create_branch('puppet-integration', 'stable/newton')
305 self.create_branch('puppet-integration', 'stable/ocata')
306 self.create_branch('puppet-tripleo', 'stable/newton')
307 self.create_branch('puppet-tripleo', 'stable/ocata')
308 self.fake_gerrit.addEvent(
309 self.fake_gerrit.getFakeBranchCreatedEvent(
310 'puppet-integration', 'stable/newton'))
311 self.fake_gerrit.addEvent(
312 self.fake_gerrit.getFakeBranchCreatedEvent(
313 'puppet-integration', 'stable/ocata'))
314 self.fake_gerrit.addEvent(
315 self.fake_gerrit.getFakeBranchCreatedEvent(
316 'puppet-tripleo', 'stable/newton'))
317 self.fake_gerrit.addEvent(
318 self.fake_gerrit.getFakeBranchCreatedEvent(
319 'puppet-tripleo', 'stable/ocata'))
320 self.waitUntilSettled()
321
322 in_repo_conf = textwrap.dedent(
323 """
324 - project:
325 name: puppet-tripleo
326 check:
327 jobs:
328 - puppet-something
329 """)
330
331 file_dict = {'.zuul.yaml': in_repo_conf}
332 A = self.fake_gerrit.addFakeChange('puppet-tripleo', 'stable/newton',
333 'A', files=file_dict)
334 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
335 self.waitUntilSettled()
336 self.assertHistory([
337 dict(name='puppet-something', result='SUCCESS', changes='1,1')])
338
339 def test_template_change_on_branch(self):
340 # Test that the contents of a template can be changed on one
341 # branch without affecting another.
342
343 # This creates a new branch with a copy of the config in master
344 self.create_branch('puppet-integration', 'stable/newton')
345 self.create_branch('puppet-integration', 'stable/ocata')
346 self.create_branch('puppet-tripleo', 'stable/newton')
347 self.create_branch('puppet-tripleo', 'stable/ocata')
348 self.fake_gerrit.addEvent(
349 self.fake_gerrit.getFakeBranchCreatedEvent(
350 'puppet-integration', 'stable/newton'))
351 self.fake_gerrit.addEvent(
352 self.fake_gerrit.getFakeBranchCreatedEvent(
353 'puppet-integration', 'stable/ocata'))
354 self.fake_gerrit.addEvent(
355 self.fake_gerrit.getFakeBranchCreatedEvent(
356 'puppet-tripleo', 'stable/newton'))
357 self.fake_gerrit.addEvent(
358 self.fake_gerrit.getFakeBranchCreatedEvent(
359 'puppet-tripleo', 'stable/ocata'))
360 self.waitUntilSettled()
361
362 in_repo_conf = textwrap.dedent("""
363 - job:
364 name: puppet-unit-base
365 run: playbooks/run-unit-tests.yaml
366
367 - job:
368 name: puppet-unit-3.8
369 parent: puppet-unit-base
370 branches: ^(stable/(newton|ocata)).*$
371 vars:
372 puppet_gem_version: 3.8
373
374 - job:
375 name: puppet-something
376 run: playbooks/run-unit-tests.yaml
377
378 - project-template:
379 name: puppet-unit
380 check:
381 jobs:
382 - puppet-something
383
384 - project:
385 name: puppet-integration
386 templates:
387 - puppet-unit
388 """)
389
390 file_dict = {'.zuul.yaml': in_repo_conf}
391 A = self.fake_gerrit.addFakeChange('puppet-integration',
392 'stable/newton',
393 'A', files=file_dict)
394 B = self.fake_gerrit.addFakeChange('puppet-tripleo',
395 'stable/newton',
396 'B')
397 B.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
398 B.subject, A.data['id'])
399 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
400 self.waitUntilSettled()
401 self.assertHistory([
402 dict(name='puppet-something', result='SUCCESS',
403 changes='1,1 2,1')])
404
405
James E. Blair09998792017-10-15 18:02:18 -0700406class TestBranchVariants(ZuulTestCase):
407 tenant_config_file = 'config/branch-variants/main.yaml'
408
409 def test_branch_variants(self):
410 # Test branch variants of jobs with inheritance
411 self.executor_server.hold_jobs_in_build = True
412 # This creates a new branch with a copy of the config in master
413 self.create_branch('puppet-integration', 'stable')
414 self.fake_gerrit.addEvent(
415 self.fake_gerrit.getFakeBranchCreatedEvent(
416 'puppet-integration', 'stable'))
417 self.waitUntilSettled()
418
419 A = self.fake_gerrit.addFakeChange('puppet-integration', 'stable', 'A')
420 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
421 self.waitUntilSettled()
422
423 self.assertEqual(len(self.builds[0].parameters['pre_playbooks']), 3)
424 self.executor_server.hold_jobs_in_build = False
425 self.executor_server.release()
426 self.waitUntilSettled()
427
James E. Blairc9e77592017-10-24 09:25:23 -0700428 def test_branch_variants_reconfigure(self):
429 # Test branch variants of jobs with inheritance
430 self.executor_server.hold_jobs_in_build = True
431 # This creates a new branch with a copy of the config in master
432 self.create_branch('puppet-integration', 'stable')
433 self.fake_gerrit.addEvent(
434 self.fake_gerrit.getFakeBranchCreatedEvent(
435 'puppet-integration', 'stable'))
436 self.waitUntilSettled()
437
438 with open(os.path.join(FIXTURE_DIR,
439 'config/branch-variants/git/',
440 'puppet-integration/.zuul.yaml')) as f:
441 config = f.read()
442
443 # Push a change that triggers a dynamic reconfiguration
444 file_dict = {'.zuul.yaml': config}
445 A = self.fake_gerrit.addFakeChange('puppet-integration', 'master', 'A',
446 files=file_dict)
447 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
448 self.waitUntilSettled()
449
450 ipath = self.builds[0].parameters['zuul']['_inheritance_path']
451 for i in ipath:
452 self.log.debug("inheritance path %s", i)
453 self.assertEqual(len(ipath), 5)
454 self.executor_server.hold_jobs_in_build = False
455 self.executor_server.release()
456 self.waitUntilSettled()
457
James E. Blairc32a8352017-10-11 16:27:50 -0700458 def test_branch_variants_divergent(self):
459 # Test branches can diverge and become independent
460 self.executor_server.hold_jobs_in_build = True
461 # This creates a new branch with a copy of the config in master
462 self.create_branch('puppet-integration', 'stable')
463 self.fake_gerrit.addEvent(
464 self.fake_gerrit.getFakeBranchCreatedEvent(
465 'puppet-integration', 'stable'))
466 self.waitUntilSettled()
467
468 with open(os.path.join(FIXTURE_DIR,
469 'config/branch-variants/git/',
470 'puppet-integration/stable.zuul.yaml')) as f:
471 config = f.read()
472
473 file_dict = {'.zuul.yaml': config}
474 C = self.fake_gerrit.addFakeChange('puppet-integration', 'stable', 'C',
475 files=file_dict)
476 C.addApproval('Code-Review', 2)
477 self.fake_gerrit.addEvent(C.addApproval('Approved', 1))
478 self.waitUntilSettled()
479 self.fake_gerrit.addEvent(C.getChangeMergedEvent())
480 self.waitUntilSettled()
481
482 A = self.fake_gerrit.addFakeChange('puppet-integration', 'master', 'A')
483 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
484 self.waitUntilSettled()
485 B = self.fake_gerrit.addFakeChange('puppet-integration', 'stable', 'B')
486 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
487 self.waitUntilSettled()
488
489 self.assertEqual(self.builds[0].parameters['zuul']['jobtags'],
490 ['master'])
491
492 self.assertEqual(self.builds[1].parameters['zuul']['jobtags'],
493 ['stable'])
494
495 self.executor_server.hold_jobs_in_build = False
496 self.executor_server.release()
497 self.waitUntilSettled()
498
James E. Blair09998792017-10-15 18:02:18 -0700499
James E. Blair2a664502017-10-27 11:39:33 -0700500class TestCentralJobs(ZuulTestCase):
501 tenant_config_file = 'config/central-jobs/main.yaml'
502
503 def setUp(self):
504 super(TestCentralJobs, self).setUp()
505 self.create_branch('org/project', 'stable')
506 self.fake_gerrit.addEvent(
507 self.fake_gerrit.getFakeBranchCreatedEvent(
508 'org/project', 'stable'))
509 self.waitUntilSettled()
510
511 def _updateConfig(self, config, branch):
512 file_dict = {'.zuul.yaml': config}
513 C = self.fake_gerrit.addFakeChange('org/project', branch, 'C',
514 files=file_dict)
515 C.addApproval('Code-Review', 2)
516 self.fake_gerrit.addEvent(C.addApproval('Approved', 1))
517 self.waitUntilSettled()
518 self.fake_gerrit.addEvent(C.getChangeMergedEvent())
519 self.waitUntilSettled()
520
521 def _test_central_job_on_branch(self, branch, other_branch):
522 # Test that a job defined on a branchless repo only runs on
523 # the branch applied
524 config = textwrap.dedent(
525 """
526 - project:
527 name: org/project
528 check:
529 jobs:
530 - central-job
531 """)
532 self._updateConfig(config, branch)
533
534 A = self.fake_gerrit.addFakeChange('org/project', branch, 'A')
535 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
536 self.waitUntilSettled()
537
538 self.assertHistory([
539 dict(name='central-job', result='SUCCESS', changes='2,1')])
540
541 # No jobs should run for this change.
542 B = self.fake_gerrit.addFakeChange('org/project', other_branch, 'B')
543 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
544 self.waitUntilSettled()
545
546 self.assertHistory([
547 dict(name='central-job', result='SUCCESS', changes='2,1')])
548
549 def test_central_job_on_stable(self):
550 self._test_central_job_on_branch('master', 'stable')
551
552 def test_central_job_on_master(self):
553 self._test_central_job_on_branch('stable', 'master')
554
555 def _test_central_template_on_branch(self, branch, other_branch):
556 # Test that a project-template defined on a branchless repo
557 # only runs on the branch applied
558 config = textwrap.dedent(
559 """
560 - project:
561 name: org/project
562 templates: ['central-jobs']
563 """)
564 self._updateConfig(config, branch)
565
566 A = self.fake_gerrit.addFakeChange('org/project', branch, 'A')
567 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
568 self.waitUntilSettled()
569
570 self.assertHistory([
571 dict(name='central-job', result='SUCCESS', changes='2,1')])
572
573 # No jobs should run for this change.
574 B = self.fake_gerrit.addFakeChange('org/project', other_branch, 'B')
575 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
576 self.waitUntilSettled()
577
578 self.assertHistory([
579 dict(name='central-job', result='SUCCESS', changes='2,1')])
580
581 def test_central_template_on_stable(self):
582 self._test_central_template_on_branch('master', 'stable')
583
584 def test_central_template_on_master(self):
585 self._test_central_template_on_branch('stable', 'master')
586
587
James E. Blairff555742017-02-19 11:34:27 -0800588class TestInRepoConfig(ZuulTestCase):
James E. Blair83005782015-12-11 14:46:03 -0800589 # A temporary class to hold new tests while others are disabled
590
Tobias Henkelabf973e2017-07-28 10:07:34 +0200591 config_file = 'zuul-connections-gerrit-and-github.conf'
James E. Blair2a629ec2015-12-22 15:32:02 -0800592 tenant_config_file = 'config/in-repo/main.yaml'
James E. Blair83005782015-12-11 14:46:03 -0800593
James E. Blair83005782015-12-11 14:46:03 -0800594 def test_in_repo_config(self):
James E. Blair14abdf42015-12-09 16:11:53 -0800595 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
Tobias Henkelbf24fd12017-07-27 06:13:07 +0200596 A.addApproval('Code-Review', 2)
597 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
James E. Blair14abdf42015-12-09 16:11:53 -0800598 self.waitUntilSettled()
599 self.assertEqual(self.getJobFromHistory('project-test1').result,
600 'SUCCESS')
601 self.assertEqual(A.data['status'], 'MERGED')
602 self.assertEqual(A.reported, 2,
603 "A should report start and success")
604 self.assertIn('tenant-one-gate', A.messages[1],
605 "A should transit tenant-one gate")
James E. Blairb97ed802015-12-21 15:55:35 -0800606
James E. Blair3a098dd2017-10-04 14:37:29 -0700607 @skip("This test is useful, but not reliable")
608 def test_full_and_dynamic_reconfig(self):
609 self.executor_server.hold_jobs_in_build = True
610 in_repo_conf = textwrap.dedent(
611 """
612 - job:
613 name: project-test1
614
615 - project:
616 name: org/project
617 tenant-one-gate:
618 jobs:
619 - project-test1
620 """)
621
622 file_dict = {'.zuul.yaml': in_repo_conf}
623 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
624 files=file_dict)
625 A.addApproval('Code-Review', 2)
626 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
627 self.waitUntilSettled()
628 self.sched.reconfigure(self.config)
629 self.waitUntilSettled()
630
631 gc.collect()
632 pipelines = [obj for obj in gc.get_objects()
633 if isinstance(obj, zuul.model.Pipeline)]
634 self.assertEqual(len(pipelines), 4)
635
636 self.executor_server.hold_jobs_in_build = False
637 self.executor_server.release()
638 self.waitUntilSettled()
639
James E. Blair8b1dc3f2016-07-05 16:49:00 -0700640 def test_dynamic_config(self):
641 in_repo_conf = textwrap.dedent(
642 """
643 - job:
Tobias Henkelf02cf512017-07-21 22:55:34 +0200644 name: project-test1
645
646 - job:
James E. Blair8b1dc3f2016-07-05 16:49:00 -0700647 name: project-test2
James E. Blair2f589fe2017-10-26 12:57:41 -0700648 run: playbooks/project-test2.yaml
James E. Blair8b1dc3f2016-07-05 16:49:00 -0700649
Tobias Henkel53aa2ad2017-12-22 09:59:45 +0100650 - job:
651 name: project-test3
652 run: playbooks/project-test2.yaml
653
654 # add a job by the short project name
James E. Blair8b1dc3f2016-07-05 16:49:00 -0700655 - project:
656 name: org/project
657 tenant-one-gate:
658 jobs:
659 - project-test2
Tobias Henkel53aa2ad2017-12-22 09:59:45 +0100660
661 # add a job by the canonical project name
662 - project:
663 name: review.example.com/org/project
664 tenant-one-gate:
665 jobs:
666 - project-test3
James E. Blair8b1dc3f2016-07-05 16:49:00 -0700667 """)
668
James E. Blairc73c73a2017-01-20 15:15:15 -0800669 in_repo_playbook = textwrap.dedent(
670 """
671 - hosts: all
672 tasks: []
673 """)
674
675 file_dict = {'.zuul.yaml': in_repo_conf,
676 'playbooks/project-test2.yaml': in_repo_playbook}
James E. Blair8b1dc3f2016-07-05 16:49:00 -0700677 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
James E. Blairc73c73a2017-01-20 15:15:15 -0800678 files=file_dict)
Tobias Henkelbf24fd12017-07-27 06:13:07 +0200679 A.addApproval('Code-Review', 2)
680 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
James E. Blair8b1dc3f2016-07-05 16:49:00 -0700681 self.waitUntilSettled()
James E. Blair8b1dc3f2016-07-05 16:49:00 -0700682 self.assertEqual(A.data['status'], 'MERGED')
683 self.assertEqual(A.reported, 2,
684 "A should report start and success")
685 self.assertIn('tenant-one-gate', A.messages[1],
686 "A should transit tenant-one gate")
James E. Blair646322f2017-01-27 15:50:34 -0800687 self.assertHistory([
Tobias Henkel53aa2ad2017-12-22 09:59:45 +0100688 dict(name='project-test2', result='SUCCESS', changes='1,1'),
689 dict(name='project-test3', result='SUCCESS', changes='1,1'),
690 ], ordered=False)
James E. Blair646322f2017-01-27 15:50:34 -0800691
James E. Blairc2a5ed72017-02-20 14:12:01 -0500692 self.fake_gerrit.addEvent(A.getChangeMergedEvent())
James E. Blair7bbd7a32017-03-06 11:36:13 -0800693 self.waitUntilSettled()
James E. Blairc2a5ed72017-02-20 14:12:01 -0500694
James E. Blair646322f2017-01-27 15:50:34 -0800695 # Now that the config change is landed, it should be live for
696 # subsequent changes.
697 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
Tobias Henkelbf24fd12017-07-27 06:13:07 +0200698 B.addApproval('Code-Review', 2)
699 self.fake_gerrit.addEvent(B.addApproval('Approved', 1))
James E. Blair646322f2017-01-27 15:50:34 -0800700 self.waitUntilSettled()
701 self.assertEqual(self.getJobFromHistory('project-test2').result,
702 'SUCCESS')
703 self.assertHistory([
704 dict(name='project-test2', result='SUCCESS', changes='1,1'),
Tobias Henkel53aa2ad2017-12-22 09:59:45 +0100705 dict(name='project-test3', result='SUCCESS', changes='1,1'),
706 dict(name='project-test2', result='SUCCESS', changes='2,1'),
707 dict(name='project-test3', result='SUCCESS', changes='2,1'),
708 ], ordered=False)
James E. Blairc73c73a2017-01-20 15:15:15 -0800709
James E. Blair6bc10482017-10-20 11:28:53 -0700710 def test_dynamic_template(self):
James E. Blair2a664502017-10-27 11:39:33 -0700711 # Tests that a project can't update a template in another
712 # project.
James E. Blair6bc10482017-10-20 11:28:53 -0700713 in_repo_conf = textwrap.dedent(
714 """
715 - job:
716 name: project-test1
717
718 - project-template:
719 name: common-config-template
720 check:
721 jobs:
722 - project-test1
723
724 - project:
725 name: org/project
726 templates: [common-config-template]
727 """)
728
729 file_dict = {'.zuul.yaml': in_repo_conf}
730 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
731 files=file_dict)
732 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
733 self.waitUntilSettled()
James E. Blair2a664502017-10-27 11:39:33 -0700734
735 self.assertEqual(A.patchsets[0]['approvals'][0]['value'], "-1")
736 self.assertIn('Project template common-config-template '
737 'is already defined',
738 A.messages[0],
739 "A should have failed the check pipeline")
James E. Blair6bc10482017-10-20 11:28:53 -0700740
Tobias Henkelf02cf512017-07-21 22:55:34 +0200741 def test_dynamic_config_non_existing_job(self):
742 """Test that requesting a non existent job fails"""
743 in_repo_conf = textwrap.dedent(
744 """
745 - job:
746 name: project-test1
747
748 - project:
749 name: org/project
750 check:
751 jobs:
752 - non-existent-job
753 """)
754
755 in_repo_playbook = textwrap.dedent(
756 """
757 - hosts: all
758 tasks: []
759 """)
760
761 file_dict = {'.zuul.yaml': in_repo_conf,
762 'playbooks/project-test2.yaml': in_repo_playbook}
763 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
764 files=file_dict)
765 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
766 self.waitUntilSettled()
767 self.assertEqual(A.reported, 1,
768 "A should report failure")
769 self.assertEqual(A.patchsets[0]['approvals'][0]['value'], "-1")
770 self.assertIn('Job non-existent-job not defined', A.messages[0],
771 "A should have failed the check pipeline")
772 self.assertHistory([])
773
774 def test_dynamic_config_non_existing_job_in_template(self):
775 """Test that requesting a non existent job fails"""
776 in_repo_conf = textwrap.dedent(
777 """
778 - job:
779 name: project-test1
780
781 - project-template:
782 name: test-template
783 check:
784 jobs:
785 - non-existent-job
786
787 - project:
788 name: org/project
789 templates:
790 - test-template
791 """)
792
793 in_repo_playbook = textwrap.dedent(
794 """
795 - hosts: all
796 tasks: []
797 """)
798
799 file_dict = {'.zuul.yaml': in_repo_conf,
800 'playbooks/project-test2.yaml': in_repo_playbook}
801 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
802 files=file_dict)
803 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
804 self.waitUntilSettled()
805 self.assertEqual(A.reported, 1,
806 "A should report failure")
807 self.assertEqual(A.patchsets[0]['approvals'][0]['value'], "-1")
808 self.assertIn('Job non-existent-job not defined', A.messages[0],
809 "A should have failed the check pipeline")
810 self.assertHistory([])
811
Tobias Henkel0f714002017-06-30 23:30:52 +0200812 def test_dynamic_config_new_patchset(self):
813 self.executor_server.hold_jobs_in_build = True
814
815 tenant = self.sched.abide.tenants.get('tenant-one')
816 check_pipeline = tenant.layout.pipelines['check']
817
818 in_repo_conf = textwrap.dedent(
819 """
820 - job:
Tobias Henkelf02cf512017-07-21 22:55:34 +0200821 name: project-test1
James E. Blair2f589fe2017-10-26 12:57:41 -0700822 run: playbooks/project-test1.yaml
Tobias Henkelf02cf512017-07-21 22:55:34 +0200823
824 - job:
Tobias Henkel0f714002017-06-30 23:30:52 +0200825 name: project-test2
James E. Blair2f589fe2017-10-26 12:57:41 -0700826 run: playbooks/project-test2.yaml
Tobias Henkel0f714002017-06-30 23:30:52 +0200827
828 - project:
829 name: org/project
830 check:
831 jobs:
832 - project-test2
833 """)
834
835 in_repo_playbook = textwrap.dedent(
836 """
837 - hosts: all
838 tasks: []
839 """)
840
841 file_dict = {'.zuul.yaml': in_repo_conf,
842 'playbooks/project-test2.yaml': in_repo_playbook}
843 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
844 files=file_dict)
845 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
846 self.waitUntilSettled()
847
848 items = check_pipeline.getAllItems()
849 self.assertEqual(items[0].change.number, '1')
850 self.assertEqual(items[0].change.patchset, '1')
851 self.assertTrue(items[0].live)
852
853 in_repo_conf = textwrap.dedent(
854 """
855 - job:
Tobias Henkel0ce7ec62017-07-21 22:50:17 +0200856 name: project-test1
James E. Blair2f589fe2017-10-26 12:57:41 -0700857 run: playbooks/project-test1.yaml
Tobias Henkel0ce7ec62017-07-21 22:50:17 +0200858
859 - job:
Tobias Henkel0f714002017-06-30 23:30:52 +0200860 name: project-test2
James E. Blair2f589fe2017-10-26 12:57:41 -0700861 run: playbooks/project-test2.yaml
Tobias Henkel0f714002017-06-30 23:30:52 +0200862
863 - project:
864 name: org/project
865 check:
866 jobs:
867 - project-test1
868 - project-test2
869 """)
870 file_dict = {'.zuul.yaml': in_repo_conf,
871 'playbooks/project-test2.yaml': in_repo_playbook}
872
873 A.addPatchset(files=file_dict)
874 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(2))
875
876 self.waitUntilSettled()
877
878 items = check_pipeline.getAllItems()
879 self.assertEqual(items[0].change.number, '1')
880 self.assertEqual(items[0].change.patchset, '2')
881 self.assertTrue(items[0].live)
882
883 self.executor_server.hold_jobs_in_build = False
Tobias Henkel0ce7ec62017-07-21 22:50:17 +0200884 self.executor_server.release('project-test1')
885 self.waitUntilSettled()
Tobias Henkel0f714002017-06-30 23:30:52 +0200886 self.executor_server.release()
887 self.waitUntilSettled()
888
Tobias Henkel0ce7ec62017-07-21 22:50:17 +0200889 self.assertHistory([
890 dict(name='project-test2', result='ABORTED', changes='1,1'),
891 dict(name='project-test1', result='SUCCESS', changes='1,2'),
892 dict(name='project-test2', result='SUCCESS', changes='1,2')])
893
James E. Blairff555742017-02-19 11:34:27 -0800894 def test_in_repo_branch(self):
895 in_repo_conf = textwrap.dedent(
896 """
897 - job:
Tobias Henkelf02cf512017-07-21 22:55:34 +0200898 name: project-test1
899
900 - job:
James E. Blairff555742017-02-19 11:34:27 -0800901 name: project-test2
James E. Blair2f589fe2017-10-26 12:57:41 -0700902 run: playbooks/project-test2.yaml
James E. Blairff555742017-02-19 11:34:27 -0800903
904 - project:
905 name: org/project
906 tenant-one-gate:
907 jobs:
908 - project-test2
909 """)
910
911 in_repo_playbook = textwrap.dedent(
912 """
913 - hosts: all
914 tasks: []
915 """)
916
917 file_dict = {'.zuul.yaml': in_repo_conf,
918 'playbooks/project-test2.yaml': in_repo_playbook}
919 self.create_branch('org/project', 'stable')
James E. Blair72facdc2017-08-17 10:29:12 -0700920 self.fake_gerrit.addEvent(
921 self.fake_gerrit.getFakeBranchCreatedEvent(
922 'org/project', 'stable'))
James E. Blair6069f2b2017-09-26 16:34:11 -0700923 self.waitUntilSettled()
James E. Blairff555742017-02-19 11:34:27 -0800924 A = self.fake_gerrit.addFakeChange('org/project', 'stable', 'A',
925 files=file_dict)
Tobias Henkelbf24fd12017-07-27 06:13:07 +0200926 A.addApproval('Code-Review', 2)
927 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
James E. Blairff555742017-02-19 11:34:27 -0800928 self.waitUntilSettled()
929 self.assertEqual(A.data['status'], 'MERGED')
930 self.assertEqual(A.reported, 2,
931 "A should report start and success")
932 self.assertIn('tenant-one-gate', A.messages[1],
933 "A should transit tenant-one gate")
934 self.assertHistory([
935 dict(name='project-test2', result='SUCCESS', changes='1,1')])
936 self.fake_gerrit.addEvent(A.getChangeMergedEvent())
James E. Blair7bbd7a32017-03-06 11:36:13 -0800937 self.waitUntilSettled()
James E. Blairff555742017-02-19 11:34:27 -0800938
939 # The config change should not affect master.
940 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
Tobias Henkelbf24fd12017-07-27 06:13:07 +0200941 B.addApproval('Code-Review', 2)
942 self.fake_gerrit.addEvent(B.addApproval('Approved', 1))
James E. Blairff555742017-02-19 11:34:27 -0800943 self.waitUntilSettled()
944 self.assertHistory([
945 dict(name='project-test2', result='SUCCESS', changes='1,1'),
946 dict(name='project-test1', result='SUCCESS', changes='2,1')])
947
948 # The config change should be live for further changes on
949 # stable.
950 C = self.fake_gerrit.addFakeChange('org/project', 'stable', 'C')
Tobias Henkelbf24fd12017-07-27 06:13:07 +0200951 C.addApproval('Code-Review', 2)
952 self.fake_gerrit.addEvent(C.addApproval('Approved', 1))
James E. Blairff555742017-02-19 11:34:27 -0800953 self.waitUntilSettled()
954 self.assertHistory([
955 dict(name='project-test2', result='SUCCESS', changes='1,1'),
956 dict(name='project-test1', result='SUCCESS', changes='2,1'),
957 dict(name='project-test2', result='SUCCESS', changes='3,1')])
958
James E. Blaira5a12492017-05-03 11:40:48 -0700959 def test_crd_dynamic_config_branch(self):
960 # Test that we can create a job in one repo and be able to use
961 # it from a different branch on a different repo.
962
963 self.create_branch('org/project1', 'stable')
James E. Blair72facdc2017-08-17 10:29:12 -0700964 self.fake_gerrit.addEvent(
965 self.fake_gerrit.getFakeBranchCreatedEvent(
966 'org/project1', 'stable'))
James E. Blaira5a12492017-05-03 11:40:48 -0700967
968 in_repo_conf = textwrap.dedent(
969 """
970 - job:
Tobias Henkelf02cf512017-07-21 22:55:34 +0200971 name: project-test1
972
973 - job:
James E. Blaira5a12492017-05-03 11:40:48 -0700974 name: project-test2
James E. Blair2f589fe2017-10-26 12:57:41 -0700975 run: playbooks/project-test2.yaml
James E. Blaira5a12492017-05-03 11:40:48 -0700976
977 - project:
978 name: org/project
979 check:
980 jobs:
981 - project-test2
982 """)
983
984 in_repo_playbook = textwrap.dedent(
985 """
986 - hosts: all
987 tasks: []
988 """)
989
990 file_dict = {'.zuul.yaml': in_repo_conf,
991 'playbooks/project-test2.yaml': in_repo_playbook}
992 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
993 files=file_dict)
994
995 second_repo_conf = textwrap.dedent(
996 """
997 - project:
998 name: org/project1
999 check:
1000 jobs:
1001 - project-test2
1002 """)
1003
1004 second_file_dict = {'.zuul.yaml': second_repo_conf}
1005 B = self.fake_gerrit.addFakeChange('org/project1', 'stable', 'B',
1006 files=second_file_dict)
1007 B.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
1008 B.subject, A.data['id'])
1009
1010 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
1011 self.waitUntilSettled()
1012 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
1013 self.waitUntilSettled()
1014
1015 self.assertEqual(A.reported, 1, "A should report")
1016 self.assertHistory([
1017 dict(name='project-test2', result='SUCCESS', changes='1,1'),
1018 dict(name='project-test2', result='SUCCESS', changes='1,1 2,1'),
1019 ])
1020
James E. Blair97043882017-09-06 15:51:17 -07001021 def test_yaml_list_error(self):
1022 in_repo_conf = textwrap.dedent(
1023 """
1024 job: foo
1025 """)
1026
1027 file_dict = {'.zuul.yaml': in_repo_conf}
1028 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
1029 files=file_dict)
1030 A.addApproval('Code-Review', 2)
1031 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
1032 self.waitUntilSettled()
1033
1034 self.assertEqual(A.data['status'], 'NEW')
1035 self.assertEqual(A.reported, 1,
1036 "A should report failure")
1037 self.assertIn('not a list', A.messages[0],
1038 "A should have a syntax error reported")
1039
1040 def test_yaml_dict_error(self):
1041 in_repo_conf = textwrap.dedent(
1042 """
1043 - job
1044 """)
1045
1046 file_dict = {'.zuul.yaml': in_repo_conf}
1047 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
1048 files=file_dict)
1049 A.addApproval('Code-Review', 2)
1050 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
1051 self.waitUntilSettled()
1052
1053 self.assertEqual(A.data['status'], 'NEW')
1054 self.assertEqual(A.reported, 1,
1055 "A should report failure")
1056 self.assertIn('not a dictionary', A.messages[0],
1057 "A should have a syntax error reported")
1058
James E. Blairec953e12017-12-11 11:56:18 -08001059 def test_yaml_duplicate_key_error(self):
1060 in_repo_conf = textwrap.dedent(
1061 """
1062 - job:
1063 name: foo
1064 name: bar
1065 """)
1066
1067 file_dict = {'.zuul.yaml': in_repo_conf}
1068 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
1069 files=file_dict)
1070 A.addApproval('Code-Review', 2)
1071 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
1072 self.waitUntilSettled()
1073
1074 self.assertEqual(A.data['status'], 'NEW')
1075 self.assertEqual(A.reported, 1,
1076 "A should report failure")
1077 self.assertIn('appears more than once', A.messages[0],
1078 "A should have a syntax error reported")
1079
James E. Blair97043882017-09-06 15:51:17 -07001080 def test_yaml_key_error(self):
1081 in_repo_conf = textwrap.dedent(
1082 """
1083 - job:
1084 name: project-test2
1085 """)
1086
1087 file_dict = {'.zuul.yaml': in_repo_conf}
1088 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
1089 files=file_dict)
1090 A.addApproval('Code-Review', 2)
1091 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
1092 self.waitUntilSettled()
1093
1094 self.assertEqual(A.data['status'], 'NEW')
1095 self.assertEqual(A.reported, 1,
1096 "A should report failure")
1097 self.assertIn('has more than one key', A.messages[0],
1098 "A should have a syntax error reported")
1099
1100 def test_yaml_unknown_error(self):
1101 in_repo_conf = textwrap.dedent(
1102 """
1103 - foobar:
1104 foo: bar
1105 """)
1106
1107 file_dict = {'.zuul.yaml': in_repo_conf}
1108 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
1109 files=file_dict)
1110 A.addApproval('Code-Review', 2)
1111 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
1112 self.waitUntilSettled()
1113
1114 self.assertEqual(A.data['status'], 'NEW')
1115 self.assertEqual(A.reported, 1,
1116 "A should report failure")
1117 self.assertIn('not recognized', A.messages[0],
1118 "A should have a syntax error reported")
1119
James E. Blair149b69c2017-03-02 10:48:16 -08001120 def test_untrusted_syntax_error(self):
James E. Blaire53250c2017-03-01 14:34:36 -08001121 in_repo_conf = textwrap.dedent(
1122 """
1123 - job:
1124 name: project-test2
1125 foo: error
1126 """)
1127
1128 file_dict = {'.zuul.yaml': in_repo_conf}
1129 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
1130 files=file_dict)
Tobias Henkelbf24fd12017-07-27 06:13:07 +02001131 A.addApproval('Code-Review', 2)
1132 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
James E. Blaire53250c2017-03-01 14:34:36 -08001133 self.waitUntilSettled()
1134
1135 self.assertEqual(A.data['status'], 'NEW')
Tobias Henkel9842bd72017-05-16 13:40:03 +02001136 self.assertEqual(A.reported, 1,
1137 "A should report failure")
1138 self.assertIn('syntax error', A.messages[0],
James E. Blaire53250c2017-03-01 14:34:36 -08001139 "A should have a syntax error reported")
1140
James E. Blair149b69c2017-03-02 10:48:16 -08001141 def test_trusted_syntax_error(self):
1142 in_repo_conf = textwrap.dedent(
1143 """
1144 - job:
1145 name: project-test2
1146 foo: error
1147 """)
1148
1149 file_dict = {'zuul.yaml': in_repo_conf}
1150 A = self.fake_gerrit.addFakeChange('common-config', 'master', 'A',
1151 files=file_dict)
Tobias Henkelbf24fd12017-07-27 06:13:07 +02001152 A.addApproval('Code-Review', 2)
1153 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
James E. Blair149b69c2017-03-02 10:48:16 -08001154 self.waitUntilSettled()
1155
1156 self.assertEqual(A.data['status'], 'NEW')
Tobias Henkel9842bd72017-05-16 13:40:03 +02001157 self.assertEqual(A.reported, 1,
1158 "A should report failure")
1159 self.assertIn('syntax error', A.messages[0],
James E. Blair149b69c2017-03-02 10:48:16 -08001160 "A should have a syntax error reported")
1161
James E. Blair6f140c72017-03-03 10:32:07 -08001162 def test_untrusted_yaml_error(self):
1163 in_repo_conf = textwrap.dedent(
1164 """
1165 - job:
1166 foo: error
1167 """)
1168
1169 file_dict = {'.zuul.yaml': in_repo_conf}
1170 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
1171 files=file_dict)
Tobias Henkelbf24fd12017-07-27 06:13:07 +02001172 A.addApproval('Code-Review', 2)
1173 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
James E. Blair6f140c72017-03-03 10:32:07 -08001174 self.waitUntilSettled()
1175
1176 self.assertEqual(A.data['status'], 'NEW')
Tobias Henkel9842bd72017-05-16 13:40:03 +02001177 self.assertEqual(A.reported, 1,
1178 "A should report failure")
1179 self.assertIn('syntax error', A.messages[0],
James E. Blair6f140c72017-03-03 10:32:07 -08001180 "A should have a syntax error reported")
1181
James E. Blairdb04e6a2017-05-03 14:49:36 -07001182 def test_untrusted_shadow_error(self):
1183 in_repo_conf = textwrap.dedent(
1184 """
1185 - job:
1186 name: common-config-test
1187 """)
1188
1189 file_dict = {'.zuul.yaml': in_repo_conf}
1190 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
1191 files=file_dict)
Tobias Henkelbf24fd12017-07-27 06:13:07 +02001192 A.addApproval('Code-Review', 2)
1193 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
James E. Blairdb04e6a2017-05-03 14:49:36 -07001194 self.waitUntilSettled()
1195
1196 self.assertEqual(A.data['status'], 'NEW')
Tobias Henkel9842bd72017-05-16 13:40:03 +02001197 self.assertEqual(A.reported, 1,
1198 "A should report failure")
1199 self.assertIn('not permitted to shadow', A.messages[0],
James E. Blairdb04e6a2017-05-03 14:49:36 -07001200 "A should have a syntax error reported")
1201
James E. Blaird5656ad2017-06-02 14:29:41 -07001202 def test_untrusted_pipeline_error(self):
1203 in_repo_conf = textwrap.dedent(
1204 """
1205 - pipeline:
1206 name: test
1207 """)
1208
1209 file_dict = {'.zuul.yaml': in_repo_conf}
1210 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
1211 files=file_dict)
Tobias Henkelbf24fd12017-07-27 06:13:07 +02001212 A.addApproval('Code-Review', 2)
1213 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
James E. Blaird5656ad2017-06-02 14:29:41 -07001214 self.waitUntilSettled()
1215
1216 self.assertEqual(A.data['status'], 'NEW')
1217 self.assertEqual(A.reported, 1,
1218 "A should report failure")
1219 self.assertIn('Pipelines may not be defined', A.messages[0],
1220 "A should have a syntax error reported")
1221
1222 def test_untrusted_project_error(self):
1223 in_repo_conf = textwrap.dedent(
1224 """
1225 - project:
1226 name: org/project1
1227 """)
1228
1229 file_dict = {'.zuul.yaml': in_repo_conf}
1230 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
1231 files=file_dict)
Tobias Henkelbf24fd12017-07-27 06:13:07 +02001232 A.addApproval('Code-Review', 2)
1233 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
James E. Blaird5656ad2017-06-02 14:29:41 -07001234 self.waitUntilSettled()
1235
1236 self.assertEqual(A.data['status'], 'NEW')
1237 self.assertEqual(A.reported, 1,
1238 "A should report failure")
1239 self.assertIn('the only project definition permitted', A.messages[0],
1240 "A should have a syntax error reported")
1241
James E. Blairf03173b2017-10-10 10:46:43 -07001242 def test_untrusted_depends_on_trusted(self):
1243 with open(os.path.join(FIXTURE_DIR,
1244 'config/in-repo/git/',
1245 'common-config/zuul.yaml')) as f:
1246 common_config = f.read()
1247
1248 common_config += textwrap.dedent(
1249 """
1250 - job:
1251 name: project-test9
1252 """)
1253
1254 file_dict = {'zuul.yaml': common_config}
1255 A = self.fake_gerrit.addFakeChange('common-config', 'master', 'A',
1256 files=file_dict)
1257 in_repo_conf = textwrap.dedent(
1258 """
1259 - job:
1260 name: project-test1
1261 - project:
1262 name: org/project
1263 check:
1264 jobs:
1265 - project-test9
1266 """)
1267
1268 file_dict = {'zuul.yaml': in_repo_conf}
1269 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B',
1270 files=file_dict)
1271 B.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
1272 B.subject, A.data['id'])
1273 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
1274 self.waitUntilSettled()
1275
1276 self.assertEqual(B.data['status'], 'NEW')
1277 self.assertEqual(B.reported, 1,
1278 "B should report failure")
1279 self.assertIn('depends on a change to a config project',
1280 B.messages[0],
1281 "A should have a syntax error reported")
1282
James E. Blaire64b0e42017-06-08 11:23:34 -07001283 def test_duplicate_node_error(self):
1284 in_repo_conf = textwrap.dedent(
1285 """
1286 - nodeset:
1287 name: duplicate
1288 nodes:
1289 - name: compute
James E. Blair16d96a02017-06-08 11:32:56 -07001290 label: foo
James E. Blaire64b0e42017-06-08 11:23:34 -07001291 - name: compute
James E. Blair16d96a02017-06-08 11:32:56 -07001292 label: foo
James E. Blaire64b0e42017-06-08 11:23:34 -07001293 """)
1294
1295 file_dict = {'.zuul.yaml': in_repo_conf}
1296 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
1297 files=file_dict)
Tobias Henkelbf24fd12017-07-27 06:13:07 +02001298 A.addApproval('Code-Review', 2)
1299 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
James E. Blaire64b0e42017-06-08 11:23:34 -07001300 self.waitUntilSettled()
1301
1302 self.assertEqual(A.data['status'], 'NEW')
1303 self.assertEqual(A.reported, 1,
1304 "A should report failure")
1305 self.assertIn('appears multiple times', A.messages[0],
1306 "A should have a syntax error reported")
1307
1308 def test_duplicate_group_error(self):
1309 in_repo_conf = textwrap.dedent(
1310 """
1311 - nodeset:
1312 name: duplicate
1313 nodes:
1314 - name: compute
James E. Blair16d96a02017-06-08 11:32:56 -07001315 label: foo
James E. Blaire64b0e42017-06-08 11:23:34 -07001316 groups:
1317 - name: group
1318 nodes: compute
1319 - name: group
1320 nodes: compute
1321 """)
1322
1323 file_dict = {'.zuul.yaml': in_repo_conf}
1324 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
1325 files=file_dict)
Tobias Henkelbf24fd12017-07-27 06:13:07 +02001326 A.addApproval('Code-Review', 2)
1327 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
James E. Blaire64b0e42017-06-08 11:23:34 -07001328 self.waitUntilSettled()
1329
1330 self.assertEqual(A.data['status'], 'NEW')
1331 self.assertEqual(A.reported, 1,
1332 "A should report failure")
1333 self.assertIn('appears multiple times', A.messages[0],
1334 "A should have a syntax error reported")
1335
James E. Blair4ae399f2017-09-20 17:15:09 -07001336 def test_secret_not_found_error(self):
1337 in_repo_conf = textwrap.dedent(
1338 """
1339 - job:
1340 name: test
1341 secrets: does-not-exist
1342 """)
1343
1344 file_dict = {'.zuul.yaml': in_repo_conf}
1345 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
1346 files=file_dict)
1347 A.addApproval('Code-Review', 2)
1348 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
1349 self.waitUntilSettled()
1350
1351 self.assertEqual(A.data['status'], 'NEW')
1352 self.assertEqual(A.reported, 1,
1353 "A should report failure")
1354 self.assertIn('secret "does-not-exist" was not found', A.messages[0],
1355 "A should have a syntax error reported")
1356
1357 def test_nodeset_not_found_error(self):
1358 in_repo_conf = textwrap.dedent(
1359 """
1360 - job:
1361 name: test
1362 nodeset: does-not-exist
1363 """)
1364
1365 file_dict = {'.zuul.yaml': in_repo_conf}
1366 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
1367 files=file_dict)
1368 A.addApproval('Code-Review', 2)
1369 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
1370 self.waitUntilSettled()
1371
1372 self.assertEqual(A.data['status'], 'NEW')
1373 self.assertEqual(A.reported, 1,
1374 "A should report failure")
1375 self.assertIn('nodeset "does-not-exist" was not found', A.messages[0],
1376 "A should have a syntax error reported")
1377
James E. Blair89e25eb2017-09-26 09:11:31 -07001378 def test_template_not_found_error(self):
1379 in_repo_conf = textwrap.dedent(
1380 """
1381 - job:
1382 name: project-test1
1383 - project:
1384 name: org/project
1385 templates:
1386 - does-not-exist
1387 """)
1388
1389 file_dict = {'.zuul.yaml': in_repo_conf}
1390 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
1391 files=file_dict)
1392 A.addApproval('Code-Review', 2)
1393 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
1394 self.waitUntilSettled()
1395
1396 self.assertEqual(A.data['status'], 'NEW')
1397 self.assertEqual(A.reported, 1,
1398 "A should report failure")
1399 self.assertIn('project template "does-not-exist" was not found',
1400 A.messages[0],
1401 "A should have a syntax error reported")
1402
Monty Taylor8be3c0c2017-10-06 10:37:37 -05001403 def test_job_list_in_project_template_not_dict_error(self):
1404 in_repo_conf = textwrap.dedent(
1405 """
1406 - job:
1407 name: project-test1
1408 - project-template:
1409 name: some-jobs
1410 check:
1411 jobs:
1412 - project-test1:
1413 - required-projects:
1414 org/project2
1415 """)
1416
1417 file_dict = {'.zuul.yaml': in_repo_conf}
1418 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
1419 files=file_dict)
1420 A.addApproval('Code-Review', 2)
1421 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
1422 self.waitUntilSettled()
1423
1424 self.assertEqual(A.data['status'], 'NEW')
1425 self.assertEqual(A.reported, 1,
1426 "A should report failure")
1427 self.assertIn('expected str for dictionary value',
1428 A.messages[0], "A should have a syntax error reported")
1429
1430 def test_job_list_in_project_not_dict_error(self):
1431 in_repo_conf = textwrap.dedent(
1432 """
1433 - job:
1434 name: project-test1
1435 - project:
1436 name: org/project1
1437 check:
1438 jobs:
1439 - project-test1:
1440 - required-projects:
1441 org/project2
1442 """)
1443
1444 file_dict = {'.zuul.yaml': in_repo_conf}
1445 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
1446 files=file_dict)
1447 A.addApproval('Code-Review', 2)
1448 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
1449 self.waitUntilSettled()
1450
1451 self.assertEqual(A.data['status'], 'NEW')
1452 self.assertEqual(A.reported, 1,
1453 "A should report failure")
1454 self.assertIn('expected str for dictionary value',
1455 A.messages[0], "A should have a syntax error reported")
1456
James E. Blair1235f142017-10-07 09:11:43 -07001457 def test_project_template(self):
1458 # Tests that a project template is not modified when used, and
1459 # can therefore be used in subsequent reconfigurations.
1460 in_repo_conf = textwrap.dedent(
1461 """
1462 - job:
1463 name: project-test1
James E. Blair2f589fe2017-10-26 12:57:41 -07001464 run: playbooks/project-test1.yaml
James E. Blair1235f142017-10-07 09:11:43 -07001465 - project-template:
1466 name: some-jobs
1467 tenant-one-gate:
1468 jobs:
1469 - project-test1:
1470 required-projects:
1471 - org/project1
1472 - project:
1473 name: org/project
1474 templates:
1475 - some-jobs
1476 """)
1477
1478 file_dict = {'.zuul.yaml': in_repo_conf}
1479 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
1480 files=file_dict)
1481 A.addApproval('Code-Review', 2)
1482 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
1483 self.waitUntilSettled()
1484 self.assertEqual(A.data['status'], 'MERGED')
1485 self.fake_gerrit.addEvent(A.getChangeMergedEvent())
1486 self.waitUntilSettled()
1487 in_repo_conf = textwrap.dedent(
1488 """
1489 - project:
1490 name: org/project1
1491 templates:
1492 - some-jobs
1493 """)
1494 file_dict = {'.zuul.yaml': in_repo_conf}
1495 B = self.fake_gerrit.addFakeChange('org/project1', 'master', 'B',
1496 files=file_dict)
1497 B.addApproval('Code-Review', 2)
1498 self.fake_gerrit.addEvent(B.addApproval('Approved', 1))
1499 self.waitUntilSettled()
1500 self.assertEqual(B.data['status'], 'MERGED')
1501
James E. Blairbccdfcf2017-10-07 13:37:26 -07001502 def test_job_remove_add(self):
1503 # Tests that a job can be removed from one repo and added in another.
1504 # First, remove the current config for project1 since it
1505 # references the job we want to remove.
1506 file_dict = {'.zuul.yaml': None}
1507 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A',
1508 files=file_dict)
1509 A.setMerged()
1510 self.fake_gerrit.addEvent(A.getChangeMergedEvent())
1511 self.waitUntilSettled()
1512 # Then propose a change to delete the job from one repo...
1513 file_dict = {'.zuul.yaml': None}
1514 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B',
1515 files=file_dict)
1516 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
1517 self.waitUntilSettled()
1518 # ...and a second that depends on it that adds it to another repo.
1519 in_repo_conf = textwrap.dedent(
1520 """
1521 - job:
1522 name: project-test1
James E. Blair2f589fe2017-10-26 12:57:41 -07001523 run: playbooks/project-test1.yaml
James E. Blairbccdfcf2017-10-07 13:37:26 -07001524
1525 - project:
1526 name: org/project1
1527 check:
1528 jobs:
1529 - project-test1
1530 """)
1531 in_repo_playbook = textwrap.dedent(
1532 """
1533 - hosts: all
1534 tasks: []
1535 """)
1536 file_dict = {'.zuul.yaml': in_repo_conf,
1537 'playbooks/project-test1.yaml': in_repo_playbook}
1538 C = self.fake_gerrit.addFakeChange('org/project1', 'master', 'C',
1539 files=file_dict,
1540 parent='refs/changes/1/1/1')
1541 C.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
1542 C.subject, B.data['id'])
1543 self.fake_gerrit.addEvent(C.getPatchsetCreatedEvent(1))
1544 self.waitUntilSettled()
1545 self.assertHistory([
1546 dict(name='project-test1', result='SUCCESS', changes='2,1 3,1'),
1547 ], ordered=False)
1548
James E. Blair09f9ffe2017-07-11 15:30:25 -07001549 def test_multi_repo(self):
1550 downstream_repo_conf = textwrap.dedent(
1551 """
1552 - project:
1553 name: org/project1
1554 tenant-one-gate:
1555 jobs:
1556 - project-test1
1557
1558 - job:
1559 name: project1-test1
1560 parent: project-test1
1561 """)
1562
1563 file_dict = {'.zuul.yaml': downstream_repo_conf}
1564 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A',
1565 files=file_dict)
Tobias Henkelbf24fd12017-07-27 06:13:07 +02001566 A.addApproval('Code-Review', 2)
1567 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
James E. Blair09f9ffe2017-07-11 15:30:25 -07001568 self.waitUntilSettled()
1569
1570 self.assertEqual(A.data['status'], 'MERGED')
1571 self.fake_gerrit.addEvent(A.getChangeMergedEvent())
1572 self.waitUntilSettled()
1573
1574 upstream_repo_conf = textwrap.dedent(
1575 """
1576 - job:
1577 name: project-test1
James E. Blair2f589fe2017-10-26 12:57:41 -07001578 run: playbooks/project-test1.yaml
James E. Blair09f9ffe2017-07-11 15:30:25 -07001579
1580 - job:
1581 name: project-test2
1582
1583 - project:
1584 name: org/project
1585 tenant-one-gate:
1586 jobs:
1587 - project-test1
1588 """)
1589
1590 file_dict = {'.zuul.yaml': upstream_repo_conf}
1591 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B',
1592 files=file_dict)
Tobias Henkelbf24fd12017-07-27 06:13:07 +02001593 B.addApproval('Code-Review', 2)
1594 self.fake_gerrit.addEvent(B.addApproval('Approved', 1))
James E. Blair09f9ffe2017-07-11 15:30:25 -07001595 self.waitUntilSettled()
1596
1597 self.assertEqual(B.data['status'], 'MERGED')
1598 self.fake_gerrit.addEvent(B.getChangeMergedEvent())
1599 self.waitUntilSettled()
1600
1601 tenant = self.sched.abide.tenants.get('tenant-one')
1602 # Ensure the latest change is reflected in the config; if it
1603 # isn't this will raise an exception.
1604 tenant.layout.getJob('project-test2')
1605
James E. Blair332636e2017-09-05 10:14:35 -07001606 def test_pipeline_error(self):
1607 with open(os.path.join(FIXTURE_DIR,
1608 'config/in-repo/git/',
1609 'common-config/zuul.yaml')) as f:
1610 base_common_config = f.read()
1611
1612 in_repo_conf_A = textwrap.dedent(
1613 """
1614 - pipeline:
1615 name: periodic
1616 foo: error
1617 """)
1618
1619 file_dict = {'zuul.yaml': None,
1620 'zuul.d/main.yaml': base_common_config,
1621 'zuul.d/test1.yaml': in_repo_conf_A}
1622 A = self.fake_gerrit.addFakeChange('common-config', 'master', 'A',
1623 files=file_dict)
1624 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
1625 self.waitUntilSettled()
1626 self.assertEqual(A.reported, 1,
1627 "A should report failure")
1628 self.assertIn('syntax error',
1629 A.messages[0],
1630 "A should have an error reported")
1631
1632 def test_change_series_error(self):
1633 with open(os.path.join(FIXTURE_DIR,
1634 'config/in-repo/git/',
1635 'common-config/zuul.yaml')) as f:
1636 base_common_config = f.read()
1637
1638 in_repo_conf_A = textwrap.dedent(
1639 """
1640 - pipeline:
1641 name: periodic
1642 foo: error
1643 """)
1644
1645 file_dict = {'zuul.yaml': None,
1646 'zuul.d/main.yaml': base_common_config,
1647 'zuul.d/test1.yaml': in_repo_conf_A}
1648 A = self.fake_gerrit.addFakeChange('common-config', 'master', 'A',
1649 files=file_dict)
1650
1651 in_repo_conf_B = textwrap.dedent(
1652 """
1653 - job:
1654 name: project-test2
1655 foo: error
1656 """)
1657
1658 file_dict = {'zuul.yaml': None,
1659 'zuul.d/main.yaml': base_common_config,
1660 'zuul.d/test1.yaml': in_repo_conf_A,
1661 'zuul.d/test2.yaml': in_repo_conf_B}
1662 B = self.fake_gerrit.addFakeChange('common-config', 'master', 'B',
1663 files=file_dict)
1664 B.setDependsOn(A, 1)
1665 C = self.fake_gerrit.addFakeChange('common-config', 'master', 'C')
1666 C.setDependsOn(B, 1)
1667 self.fake_gerrit.addEvent(C.getPatchsetCreatedEvent(1))
1668 self.waitUntilSettled()
1669
1670 self.assertEqual(C.reported, 1,
1671 "C should report failure")
1672 self.assertIn('depends on a change that failed to merge',
1673 C.messages[0],
1674 "C should have an error reported")
1675
James E. Blair1ef8f7c2017-12-13 17:18:34 -08001676 def test_pipeline_debug(self):
1677 in_repo_conf = textwrap.dedent(
1678 """
1679 - job:
1680 name: project-test1
1681 run: playbooks/project-test1.yaml
1682 - project:
1683 name: org/project
1684 check:
1685 debug: True
1686 jobs:
1687 - project-test1
1688 """)
1689
1690 file_dict = {'.zuul.yaml': in_repo_conf}
1691 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
1692 files=file_dict)
1693 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
1694 self.waitUntilSettled()
1695
1696 self.assertEqual(A.data['status'], 'NEW')
1697 self.assertEqual(A.reported, 1,
1698 "A should report success")
1699 self.assertIn('Debug information:',
1700 A.messages[0], "A should have debug info")
1701
James E. Blairc73c73a2017-01-20 15:15:15 -08001702
James E. Blairc9455002017-09-06 09:22:19 -07001703class TestInRepoJoin(ZuulTestCase):
1704 # In this config, org/project is not a member of any pipelines, so
1705 # that we may test the changes that cause it to join them.
1706
1707 tenant_config_file = 'config/in-repo-join/main.yaml'
1708
1709 def test_dynamic_dependent_pipeline(self):
1710 # Test dynamically adding a project to a
1711 # dependent pipeline for the first time
1712 self.executor_server.hold_jobs_in_build = True
1713
1714 tenant = self.sched.abide.tenants.get('tenant-one')
1715 gate_pipeline = tenant.layout.pipelines['gate']
1716
1717 in_repo_conf = textwrap.dedent(
1718 """
1719 - job:
1720 name: project-test1
James E. Blair2f589fe2017-10-26 12:57:41 -07001721 run: playbooks/project-test1.yaml
James E. Blairc9455002017-09-06 09:22:19 -07001722
1723 - job:
1724 name: project-test2
James E. Blair2f589fe2017-10-26 12:57:41 -07001725 run: playbooks/project-test2.yaml
James E. Blairc9455002017-09-06 09:22:19 -07001726
1727 - project:
1728 name: org/project
1729 gate:
1730 jobs:
1731 - project-test2
1732 """)
1733
1734 in_repo_playbook = textwrap.dedent(
1735 """
1736 - hosts: all
1737 tasks: []
1738 """)
1739
1740 file_dict = {'.zuul.yaml': in_repo_conf,
1741 'playbooks/project-test2.yaml': in_repo_playbook}
1742 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
1743 files=file_dict)
1744 A.addApproval('Code-Review', 2)
1745 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
1746 self.waitUntilSettled()
1747
1748 items = gate_pipeline.getAllItems()
1749 self.assertEqual(items[0].change.number, '1')
1750 self.assertEqual(items[0].change.patchset, '1')
1751 self.assertTrue(items[0].live)
1752
1753 self.executor_server.hold_jobs_in_build = False
1754 self.executor_server.release()
1755 self.waitUntilSettled()
1756
1757 # Make sure the dynamic queue got cleaned up
1758 self.assertEqual(gate_pipeline.queues, [])
1759
1760 def test_dynamic_dependent_pipeline_failure(self):
1761 # Test that a change behind a failing change adding a project
1762 # to a dependent pipeline is dequeued.
1763 self.executor_server.hold_jobs_in_build = True
1764
1765 in_repo_conf = textwrap.dedent(
1766 """
1767 - job:
1768 name: project-test1
James E. Blair2f589fe2017-10-26 12:57:41 -07001769 run: playbooks/project-test1.yaml
James E. Blairc9455002017-09-06 09:22:19 -07001770
1771 - project:
1772 name: org/project
1773 gate:
1774 jobs:
1775 - project-test1
1776 """)
1777
1778 file_dict = {'.zuul.yaml': in_repo_conf}
1779 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
1780 files=file_dict)
1781 self.executor_server.failJob('project-test1', A)
1782 A.addApproval('Code-Review', 2)
1783 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
1784 self.waitUntilSettled()
1785
1786 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
1787 B.addApproval('Code-Review', 2)
1788 self.fake_gerrit.addEvent(B.addApproval('Approved', 1))
1789 self.waitUntilSettled()
1790
James E. Blair3490c5d2017-09-07 08:33:23 -07001791 self.orderedRelease()
James E. Blairc9455002017-09-06 09:22:19 -07001792 self.waitUntilSettled()
1793 self.assertEqual(A.reported, 2,
1794 "A should report start and failure")
1795 self.assertEqual(A.data['status'], 'NEW')
1796 self.assertEqual(B.reported, 1,
1797 "B should report start")
1798 self.assertHistory([
1799 dict(name='project-test1', result='FAILURE', changes='1,1'),
James E. Blair3490c5d2017-09-07 08:33:23 -07001800 dict(name='project-test1', result='ABORTED', changes='1,1 2,1'),
James E. Blairc9455002017-09-06 09:22:19 -07001801 ], ordered=False)
1802
James E. Blair0af198f2017-09-06 09:52:35 -07001803 def test_dynamic_dependent_pipeline_absent(self):
1804 # Test that a series of dependent changes don't report merge
1805 # failures to a pipeline they aren't in.
1806 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1807 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
1808 B.setDependsOn(A, 1)
1809
1810 A.addApproval('Code-Review', 2)
1811 A.addApproval('Approved', 1)
1812 B.addApproval('Code-Review', 2)
1813 self.fake_gerrit.addEvent(B.addApproval('Approved', 1))
1814 self.waitUntilSettled()
1815 self.assertEqual(A.reported, 0,
1816 "A should not report")
1817 self.assertEqual(A.data['status'], 'NEW')
1818 self.assertEqual(B.reported, 0,
1819 "B should not report")
1820 self.assertEqual(B.data['status'], 'NEW')
1821 self.assertHistory([])
1822
James E. Blairc9455002017-09-06 09:22:19 -07001823
James E. Blairc73c73a2017-01-20 15:15:15 -08001824class TestAnsible(AnsibleZuulTestCase):
1825 # A temporary class to hold new tests while others are disabled
1826
1827 tenant_config_file = 'config/ansible/main.yaml'
1828
1829 def test_playbook(self):
Jamie Lennox7655b552017-03-17 12:33:38 +11001830 # Keep the jobdir around so we can inspect contents if an
1831 # assert fails.
1832 self.executor_server.keep_jobdir = True
1833 # Output extra ansible info so we might see errors.
1834 self.executor_server.verbose = True
1835 # Add a site variables file, used by check-vars
1836 path = os.path.join(FIXTURE_DIR, 'config', 'ansible',
1837 'variables.yaml')
1838 self.config.set('executor', 'variables', path)
James E. Blairc73c73a2017-01-20 15:15:15 -08001839 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1840 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
1841 self.waitUntilSettled()
Tobias Henkel077f2f32017-05-30 20:16:46 +02001842 build_timeout = self.getJobFromHistory('timeout')
Jamie Lennox7655b552017-03-17 12:33:38 +11001843 with self.jobLog(build_timeout):
1844 self.assertEqual(build_timeout.result, 'TIMED_OUT')
Tobias Henkel077f2f32017-05-30 20:16:46 +02001845 build_faillocal = self.getJobFromHistory('faillocal')
Jamie Lennox7655b552017-03-17 12:33:38 +11001846 with self.jobLog(build_faillocal):
1847 self.assertEqual(build_faillocal.result, 'FAILURE')
Tobias Henkel077f2f32017-05-30 20:16:46 +02001848 build_failpost = self.getJobFromHistory('failpost')
Jamie Lennox7655b552017-03-17 12:33:38 +11001849 with self.jobLog(build_failpost):
1850 self.assertEqual(build_failpost.result, 'POST_FAILURE')
Tobias Henkel077f2f32017-05-30 20:16:46 +02001851 build_check_vars = self.getJobFromHistory('check-vars')
Jamie Lennox7655b552017-03-17 12:33:38 +11001852 with self.jobLog(build_check_vars):
1853 self.assertEqual(build_check_vars.result, 'SUCCESS')
Monty Tayloraff8b402017-08-16 18:40:41 -05001854 build_check_secret_names = self.getJobFromHistory('check-secret-names')
1855 with self.jobLog(build_check_secret_names):
1856 self.assertEqual(build_check_secret_names.result, 'SUCCESS')
Tobias Henkel077f2f32017-05-30 20:16:46 +02001857 build_hello = self.getJobFromHistory('hello-world')
Jamie Lennox7655b552017-03-17 12:33:38 +11001858 with self.jobLog(build_hello):
1859 self.assertEqual(build_hello.result, 'SUCCESS')
Tobias Henkel077f2f32017-05-30 20:16:46 +02001860 build_python27 = self.getJobFromHistory('python27')
Jamie Lennox7655b552017-03-17 12:33:38 +11001861 with self.jobLog(build_python27):
1862 self.assertEqual(build_python27.result, 'SUCCESS')
1863 flag_path = os.path.join(self.test_root,
1864 build_python27.uuid + '.flag')
1865 self.assertTrue(os.path.exists(flag_path))
1866 copied_path = os.path.join(self.test_root, build_python27.uuid +
1867 '.copied')
1868 self.assertTrue(os.path.exists(copied_path))
1869 failed_path = os.path.join(self.test_root, build_python27.uuid +
1870 '.failed')
1871 self.assertFalse(os.path.exists(failed_path))
1872 pre_flag_path = os.path.join(self.test_root, build_python27.uuid +
1873 '.pre.flag')
1874 self.assertTrue(os.path.exists(pre_flag_path))
1875 post_flag_path = os.path.join(self.test_root, build_python27.uuid +
1876 '.post.flag')
1877 self.assertTrue(os.path.exists(post_flag_path))
1878 bare_role_flag_path = os.path.join(self.test_root,
1879 build_python27.uuid +
1880 '.bare-role.flag')
1881 self.assertTrue(os.path.exists(bare_role_flag_path))
1882 secrets_path = os.path.join(self.test_root,
1883 build_python27.uuid + '.secrets')
1884 with open(secrets_path) as f:
1885 self.assertEqual(f.read(), "test-username test-password")
James E. Blairb9c0d772017-03-03 14:34:49 -08001886
Jamie Lennox7655b552017-03-17 12:33:38 +11001887 msg = A.messages[0]
1888 success = "{} https://success.example.com/zuul-logs/{}"
1889 fail = "{} https://failure.example.com/zuul-logs/{}"
1890 self.assertIn(success.format("python27", build_python27.uuid), msg)
1891 self.assertIn(fail.format("faillocal", build_faillocal.uuid), msg)
1892 self.assertIn(success.format("check-vars",
1893 build_check_vars.uuid), msg)
1894 self.assertIn(success.format("hello-world", build_hello.uuid), msg)
1895 self.assertIn(fail.format("timeout", build_timeout.uuid), msg)
1896 self.assertIn(fail.format("failpost", build_failpost.uuid), msg)
Tobias Henkel077f2f32017-05-30 20:16:46 +02001897
James E. Blairabbaa6f2017-04-06 16:11:44 -07001898 def _add_job(self, job_name):
1899 conf = textwrap.dedent(
1900 """
1901 - job:
1902 name: %s
James E. Blair2f589fe2017-10-26 12:57:41 -07001903 run: playbooks/%s.yaml
James E. Blairabbaa6f2017-04-06 16:11:44 -07001904
1905 - project:
1906 name: org/plugin-project
1907 check:
1908 jobs:
1909 - %s
James E. Blair2f589fe2017-10-26 12:57:41 -07001910 """ % (job_name, job_name, job_name))
James E. Blairabbaa6f2017-04-06 16:11:44 -07001911
1912 file_dict = {'.zuul.yaml': conf}
1913 A = self.fake_gerrit.addFakeChange('org/plugin-project', 'master', 'A',
1914 files=file_dict)
1915 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
1916 self.waitUntilSettled()
1917
1918 def test_plugins(self):
1919 # Keep the jobdir around so we can inspect contents if an
1920 # assert fails.
1921 self.executor_server.keep_jobdir = True
1922 # Output extra ansible info so we might see errors.
1923 self.executor_server.verbose = True
1924
1925 count = 0
1926 plugin_tests = [
1927 ('passwd', 'FAILURE'),
1928 ('cartesian', 'SUCCESS'),
1929 ('consul_kv', 'FAILURE'),
1930 ('credstash', 'FAILURE'),
1931 ('csvfile_good', 'SUCCESS'),
1932 ('csvfile_bad', 'FAILURE'),
Monty Taylor93ad2212017-08-02 14:59:50 -05001933 ('uri_bad_path', 'FAILURE'),
1934 ('uri_bad_scheme', 'FAILURE'),
Monty Taylor788a40e2017-08-02 16:14:05 -05001935 ('block_local_override', 'FAILURE'),
Monty Taylor8da768f2017-08-31 14:15:35 -05001936 ('file_local_good', 'SUCCESS'),
1937 ('file_local_bad', 'FAILURE'),
James E. Blairabbaa6f2017-04-06 16:11:44 -07001938 ]
1939 for job_name, result in plugin_tests:
1940 count += 1
1941 self._add_job(job_name)
1942
1943 job = self.getJobFromHistory(job_name)
1944 with self.jobLog(job):
1945 self.assertEqual(count, len(self.history))
1946 build = self.history[-1]
1947 self.assertEqual(build.result, result)
1948
1949 # TODOv3(jeblair): parse the ansible output and verify we're
1950 # getting the exception we expect.
1951
James E. Blairb9c0d772017-03-03 14:34:49 -08001952
James E. Blaira4d4eef2017-06-30 14:49:17 -07001953class TestPrePlaybooks(AnsibleZuulTestCase):
1954 # A temporary class to hold new tests while others are disabled
1955
1956 tenant_config_file = 'config/pre-playbook/main.yaml'
1957
1958 def test_pre_playbook_fail(self):
1959 # Test that we run the post playbooks (but not the actual
1960 # playbook) when a pre-playbook fails.
1961 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1962 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
1963 self.waitUntilSettled()
1964 build = self.getJobFromHistory('python27')
1965 self.assertIsNone(build.result)
1966 self.assertIn('RETRY_LIMIT', A.messages[0])
1967 flag_path = os.path.join(self.test_root, build.uuid +
1968 '.main.flag')
1969 self.assertFalse(os.path.exists(flag_path))
1970 pre_flag_path = os.path.join(self.test_root, build.uuid +
1971 '.pre.flag')
1972 self.assertFalse(os.path.exists(pre_flag_path))
1973 post_flag_path = os.path.join(self.test_root, build.uuid +
1974 '.post.flag')
James E. Blair21037782017-07-19 11:56:55 -07001975 self.assertTrue(os.path.exists(post_flag_path),
1976 "The file %s should exist" % post_flag_path)
James E. Blaira4d4eef2017-06-30 14:49:17 -07001977
1978
James E. Blairbacbb882017-10-17 09:48:23 -07001979class TestPostPlaybooks(AnsibleZuulTestCase):
1980 tenant_config_file = 'config/post-playbook/main.yaml'
1981
1982 def test_post_playbook_abort(self):
1983 # Test that when we abort a job in the post playbook, that we
1984 # don't send back POST_FAILURE.
1985 self.executor_server.verbose = True
1986 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1987 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
1988
1989 while not len(self.builds):
1990 time.sleep(0.1)
1991 build = self.builds[0]
1992
1993 post_start = os.path.join(self.test_root, build.uuid +
1994 '.post_start.flag')
1995 start = time.time()
1996 while time.time() < start + 90:
1997 if os.path.exists(post_start):
1998 break
1999 time.sleep(0.1)
2000 # The post playbook has started, abort the job
2001 self.fake_gerrit.addEvent(A.getChangeAbandonedEvent())
2002 self.waitUntilSettled()
2003
2004 build = self.getJobFromHistory('python27')
2005 self.assertEqual('ABORTED', build.result)
2006
2007 post_end = os.path.join(self.test_root, build.uuid +
2008 '.post_end.flag')
2009 self.assertTrue(os.path.exists(post_start))
2010 self.assertFalse(os.path.exists(post_end))
2011
2012
James E. Blairb9c0d772017-03-03 14:34:49 -08002013class TestBrokenConfig(ZuulTestCase):
2014 # Test that we get an appropriate syntax error if we start with a
2015 # broken config.
2016
2017 tenant_config_file = 'config/broken/main.yaml'
2018
2019 def setUp(self):
2020 with testtools.ExpectedException(
2021 zuul.configloader.ConfigurationSyntaxError,
2022 "\nZuul encountered a syntax error"):
2023 super(TestBrokenConfig, self).setUp()
2024
2025 def test_broken_config_on_startup(self):
2026 pass
Ricardo Carrillo Cruz22994f92016-12-02 11:41:58 +00002027
2028
2029class TestProjectKeys(ZuulTestCase):
2030 # Test that we can generate project keys
2031
2032 # Normally the test infrastructure copies a static key in place
2033 # for each project before starting tests. This saves time because
2034 # Zuul's automatic key-generation on startup can be slow. To make
2035 # sure we exercise that code, in this test we allow Zuul to create
2036 # keys for the project on startup.
2037 create_project_keys = True
Tobias Henkelabf973e2017-07-28 10:07:34 +02002038 config_file = 'zuul-connections-gerrit-and-github.conf'
Ricardo Carrillo Cruz22994f92016-12-02 11:41:58 +00002039 tenant_config_file = 'config/in-repo/main.yaml'
2040
2041 def test_key_generation(self):
2042 key_root = os.path.join(self.state_root, 'keys')
2043 private_key_file = os.path.join(key_root, 'gerrit/org/project.pem')
2044 # Make sure that a proper key was created on startup
2045 with open(private_key_file, "rb") as f:
James E. Blairbf1a4f22017-03-17 10:59:37 -07002046 private_key, public_key = \
2047 encryption.deserialize_rsa_keypair(f.read())
Ricardo Carrillo Cruz22994f92016-12-02 11:41:58 +00002048
2049 with open(os.path.join(FIXTURE_DIR, 'private.pem')) as i:
2050 fixture_private_key = i.read()
2051
2052 # Make sure that we didn't just end up with the static fixture
2053 # key
2054 self.assertNotEqual(fixture_private_key, private_key)
2055
2056 # Make sure it's the right length
2057 self.assertEqual(4096, private_key.key_size)
James E. Blairbce76932017-05-04 10:03:15 -07002058
2059
James E. Blairbb94dfa2017-07-11 07:45:19 -07002060class RoleTestCase(ZuulTestCase):
James E. Blair1b27f6a2017-07-14 14:09:07 -07002061 def _assertRolePath(self, build, playbook, content):
2062 path = os.path.join(self.test_root, build.uuid,
2063 'ansible', playbook, 'ansible.cfg')
2064 roles_paths = []
2065 with open(path) as f:
2066 for line in f:
2067 if line.startswith('roles_path'):
2068 roles_paths.append(line)
2069 print(roles_paths)
2070 if content:
2071 self.assertEqual(len(roles_paths), 1,
2072 "Should have one roles_path line in %s" %
2073 (playbook,))
2074 self.assertIn(content, roles_paths[0])
2075 else:
2076 self.assertEqual(len(roles_paths), 0,
2077 "Should have no roles_path line in %s" %
2078 (playbook,))
2079
James E. Blairbb94dfa2017-07-11 07:45:19 -07002080
2081class TestRoles(RoleTestCase):
2082 tenant_config_file = 'config/roles/main.yaml'
2083
James E. Blairbce76932017-05-04 10:03:15 -07002084 def test_role(self):
2085 # This exercises a proposed change to a role being checked out
2086 # and used.
2087 A = self.fake_gerrit.addFakeChange('bare-role', 'master', 'A')
2088 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2089 B.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
2090 B.subject, A.data['id'])
2091 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2092 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
2093 self.waitUntilSettled()
2094 self.assertHistory([
2095 dict(name='project-test', result='SUCCESS', changes='1,1 2,1'),
2096 ])
James E. Blair6459db12017-06-29 14:57:20 -07002097
James E. Blair1b27f6a2017-07-14 14:09:07 -07002098 def test_role_inheritance(self):
2099 self.executor_server.hold_jobs_in_build = True
2100 conf = textwrap.dedent(
2101 """
2102 - job:
2103 name: parent
2104 roles:
2105 - zuul: bare-role
Ian Wienand548c43c2017-12-05 14:16:32 +11002106 pre-run: playbooks/parent-pre.yaml
2107 post-run: playbooks/parent-post.yaml
James E. Blair1b27f6a2017-07-14 14:09:07 -07002108
2109 - job:
2110 name: project-test
2111 parent: parent
James E. Blair2f589fe2017-10-26 12:57:41 -07002112 run: playbooks/project-test.yaml
James E. Blair1b27f6a2017-07-14 14:09:07 -07002113 roles:
2114 - zuul: org/project
2115
2116 - project:
2117 name: org/project
2118 check:
2119 jobs:
2120 - project-test
2121 """)
2122
2123 file_dict = {'.zuul.yaml': conf}
2124 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
2125 files=file_dict)
2126 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2127 self.waitUntilSettled()
2128
2129 self.assertEqual(len(self.builds), 1)
2130 build = self.getBuildByName('project-test')
2131 self._assertRolePath(build, 'pre_playbook_0', 'role_0')
2132 self._assertRolePath(build, 'playbook_0', 'role_0')
2133 self._assertRolePath(build, 'playbook_0', 'role_1')
2134 self._assertRolePath(build, 'post_playbook_0', 'role_0')
2135
2136 self.executor_server.hold_jobs_in_build = False
2137 self.executor_server.release()
2138 self.waitUntilSettled()
2139
2140 self.assertHistory([
2141 dict(name='project-test', result='SUCCESS', changes='1,1'),
2142 ])
2143
James E. Blair6f699732017-07-18 14:19:11 -07002144 def test_role_error(self):
2145 conf = textwrap.dedent(
2146 """
2147 - job:
2148 name: project-test
James E. Blair2f589fe2017-10-26 12:57:41 -07002149 run: playbooks/project-test.yaml
James E. Blair6f699732017-07-18 14:19:11 -07002150 roles:
2151 - zuul: common-config
2152
2153 - project:
2154 name: org/project
2155 check:
2156 jobs:
2157 - project-test
2158 """)
2159
2160 file_dict = {'.zuul.yaml': conf}
2161 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
2162 files=file_dict)
2163 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2164 self.waitUntilSettled()
2165 self.assertIn(
2166 '- project-test project-test : ERROR Unable to find role',
2167 A.messages[-1])
2168
James E. Blair6459db12017-06-29 14:57:20 -07002169
James E. Blairbb94dfa2017-07-11 07:45:19 -07002170class TestImplicitRoles(RoleTestCase):
2171 tenant_config_file = 'config/implicit-roles/main.yaml'
2172
2173 def test_missing_roles(self):
2174 # Test implicit and explicit roles for a project which does
2175 # not have roles. The implicit role should be silently
2176 # ignored since the project doesn't supply roles, but if a
2177 # user declares an explicit role, it should error.
2178 self.executor_server.hold_jobs_in_build = True
2179 A = self.fake_gerrit.addFakeChange('org/norole-project', 'master', 'A')
2180 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2181 self.waitUntilSettled()
2182
2183 self.assertEqual(len(self.builds), 2)
2184 build = self.getBuildByName('implicit-role-fail')
2185 self._assertRolePath(build, 'playbook_0', None)
2186
2187 self.executor_server.hold_jobs_in_build = False
2188 self.executor_server.release()
2189 self.waitUntilSettled()
2190 # The retry_limit doesn't get recorded
2191 self.assertHistory([
2192 dict(name='implicit-role-fail', result='SUCCESS', changes='1,1'),
2193 ])
2194
2195 def test_roles(self):
2196 # Test implicit and explicit roles for a project which does
2197 # have roles. In both cases, we should end up with the role
2198 # in the path. In the explicit case, ensure we end up with
2199 # the name we specified.
2200 self.executor_server.hold_jobs_in_build = True
2201 A = self.fake_gerrit.addFakeChange('org/role-project', 'master', 'A')
2202 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2203 self.waitUntilSettled()
2204
2205 self.assertEqual(len(self.builds), 2)
2206 build = self.getBuildByName('implicit-role-ok')
2207 self._assertRolePath(build, 'playbook_0', 'role_0')
2208
2209 build = self.getBuildByName('explicit-role-ok')
2210 self._assertRolePath(build, 'playbook_0', 'role_0')
2211
2212 self.executor_server.hold_jobs_in_build = False
2213 self.executor_server.release()
2214 self.waitUntilSettled()
2215 self.assertHistory([
2216 dict(name='implicit-role-ok', result='SUCCESS', changes='1,1'),
2217 dict(name='explicit-role-ok', result='SUCCESS', changes='1,1'),
2218 ], ordered=False)
2219
2220
James E. Blair6459db12017-06-29 14:57:20 -07002221class TestShadow(ZuulTestCase):
2222 tenant_config_file = 'config/shadow/main.yaml'
2223
2224 def test_shadow(self):
2225 # Test that a repo is allowed to shadow another's job definitions.
2226 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2227 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2228 self.waitUntilSettled()
2229 self.assertHistory([
2230 dict(name='test1', result='SUCCESS', changes='1,1'),
2231 dict(name='test2', result='SUCCESS', changes='1,1'),
James E. Blairadafa6c2017-07-12 08:50:56 -07002232 ], ordered=False)
James E. Blair196f61a2017-06-30 15:42:29 -07002233
2234
2235class TestDataReturn(AnsibleZuulTestCase):
2236 tenant_config_file = 'config/data-return/main.yaml'
2237
2238 def test_data_return(self):
James E. Blair196f61a2017-06-30 15:42:29 -07002239 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2240 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2241 self.waitUntilSettled()
2242 self.assertHistory([
2243 dict(name='data-return', result='SUCCESS', changes='1,1'),
James E. Blair88e79c02017-07-07 13:36:54 -07002244 dict(name='data-return-relative', result='SUCCESS', changes='1,1'),
James E. Blair698703c2017-09-15 20:58:30 -06002245 dict(name='child', result='SUCCESS', changes='1,1'),
James E. Blair88e79c02017-07-07 13:36:54 -07002246 ], ordered=False)
2247 self.assertIn('- data-return http://example.com/test/log/url/',
2248 A.messages[-1])
2249 self.assertIn('- data-return-relative '
2250 'http://example.com/test/log/url/docs/index.html',
James E. Blair196f61a2017-06-30 15:42:29 -07002251 A.messages[-1])
Clint Byrumdc8a0902017-07-20 16:36:27 -07002252
2253
2254class TestDiskAccounting(AnsibleZuulTestCase):
2255 config_file = 'zuul-disk-accounting.conf'
2256 tenant_config_file = 'config/disk-accountant/main.yaml'
2257
2258 def test_disk_accountant_kills_job(self):
2259 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2260 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2261 self.waitUntilSettled()
2262 self.assertHistory([
2263 dict(name='dd-big-empty-file', result='ABORTED', changes='1,1')])
Tristan Cacqueray82f864b2017-08-01 05:54:42 +00002264
2265
2266class TestMaxNodesPerJob(AnsibleZuulTestCase):
2267 tenant_config_file = 'config/multi-tenant/main.yaml'
2268
Tristan Cacquerayc98bff72017-09-10 15:25:26 +00002269 def test_max_timeout_exceeded(self):
Tristan Cacqueray82f864b2017-08-01 05:54:42 +00002270 in_repo_conf = textwrap.dedent(
2271 """
2272 - job:
2273 name: test-job
James E. Blair7e3e6882017-09-20 15:47:13 -07002274 nodeset:
2275 nodes:
2276 - name: node01
2277 label: fake
2278 - name: node02
2279 label: fake
2280 - name: node03
2281 label: fake
2282 - name: node04
2283 label: fake
2284 - name: node05
2285 label: fake
2286 - name: node06
2287 label: fake
Tristan Cacqueray82f864b2017-08-01 05:54:42 +00002288 """)
2289 file_dict = {'.zuul.yaml': in_repo_conf}
2290 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A',
2291 files=file_dict)
2292 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2293 self.waitUntilSettled()
2294 self.assertIn('The job "test-job" exceeds tenant max-nodes-per-job 5.',
2295 A.messages[0], "A should fail because of nodes limit")
2296
2297 B = self.fake_gerrit.addFakeChange('org/project2', 'master', 'A',
2298 files=file_dict)
2299 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
2300 self.waitUntilSettled()
2301 self.assertNotIn("exceeds tenant max-nodes", B.messages[0],
2302 "B should not fail because of nodes limit")
James E. Blair2bab6e72017-08-07 09:52:45 -07002303
2304
Tristan Cacquerayc98bff72017-09-10 15:25:26 +00002305class TestMaxTimeout(AnsibleZuulTestCase):
2306 tenant_config_file = 'config/multi-tenant/main.yaml'
2307
2308 def test_max_nodes_reached(self):
2309 in_repo_conf = textwrap.dedent(
2310 """
2311 - job:
2312 name: test-job
2313 timeout: 3600
2314 """)
2315 file_dict = {'.zuul.yaml': in_repo_conf}
2316 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A',
2317 files=file_dict)
2318 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2319 self.waitUntilSettled()
2320 self.assertIn('The job "test-job" exceeds tenant max-job-timeout',
2321 A.messages[0], "A should fail because of timeout limit")
2322
2323 B = self.fake_gerrit.addFakeChange('org/project2', 'master', 'A',
2324 files=file_dict)
2325 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
2326 self.waitUntilSettled()
2327 self.assertNotIn("exceeds tenant max-job-timeout", B.messages[0],
2328 "B should not fail because of timeout limit")
2329
2330
James E. Blair7edc25f2017-10-26 10:47:14 -07002331class TestPragma(ZuulTestCase):
2332 tenant_config_file = 'config/pragma/main.yaml'
2333
2334 def test_no_pragma(self):
2335 self.create_branch('org/project', 'stable')
2336 with open(os.path.join(FIXTURE_DIR,
2337 'config/pragma/git/',
2338 'org_project/nopragma.yaml')) as f:
2339 config = f.read()
2340 file_dict = {'.zuul.yaml': config}
2341 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
2342 files=file_dict)
2343 A.addApproval('Code-Review', 2)
2344 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
2345 self.waitUntilSettled()
2346 self.fake_gerrit.addEvent(A.getChangeMergedEvent())
2347 self.waitUntilSettled()
2348
2349 # This is an untrusted repo with 2 branches, so it should have
2350 # an implied branch matcher for the job.
2351 tenant = self.sched.abide.tenants.get('tenant-one')
2352 jobs = tenant.layout.getJobs('test-job')
2353 self.assertEqual(len(jobs), 1)
2354 for job in tenant.layout.getJobs('test-job'):
2355 self.assertIsNotNone(job.branch_matcher)
2356
2357 def test_pragma(self):
2358 self.create_branch('org/project', 'stable')
2359 with open(os.path.join(FIXTURE_DIR,
2360 'config/pragma/git/',
2361 'org_project/pragma.yaml')) as f:
2362 config = f.read()
2363 file_dict = {'.zuul.yaml': config}
2364 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
2365 files=file_dict)
2366 A.addApproval('Code-Review', 2)
2367 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
2368 self.waitUntilSettled()
2369 self.fake_gerrit.addEvent(A.getChangeMergedEvent())
2370 self.waitUntilSettled()
2371
2372 # This is an untrusted repo with 2 branches, so it would
2373 # normally have an implied branch matcher, but our pragma
2374 # overrides it.
2375 tenant = self.sched.abide.tenants.get('tenant-one')
2376 jobs = tenant.layout.getJobs('test-job')
2377 self.assertEqual(len(jobs), 1)
2378 for job in tenant.layout.getJobs('test-job'):
2379 self.assertIsNone(job.branch_matcher)
2380
2381
James E. Blair37c3d8c2017-12-13 15:06:11 -08002382class TestPragmaMultibranch(ZuulTestCase):
2383 tenant_config_file = 'config/pragma-multibranch/main.yaml'
2384
2385 def test_no_branch_matchers(self):
2386 self.create_branch('org/project1', 'stable/pike')
2387 self.create_branch('org/project2', 'stable/jewel')
2388 self.fake_gerrit.addEvent(
2389 self.fake_gerrit.getFakeBranchCreatedEvent(
2390 'org/project1', 'stable/pike'))
2391 self.fake_gerrit.addEvent(
2392 self.fake_gerrit.getFakeBranchCreatedEvent(
2393 'org/project2', 'stable/jewel'))
2394 self.waitUntilSettled()
2395 # We want the jobs defined on the stable/pike branch of
2396 # project1 to apply to the stable/jewel branch of project2.
2397
2398 # First, without the pragma line, the jobs should not run
2399 # because in project1 they have branch matchers for pike, so
2400 # they will not match a jewel change.
2401 B = self.fake_gerrit.addFakeChange('org/project2', 'stable/jewel', 'B')
2402 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
2403 self.waitUntilSettled()
2404 self.assertHistory([])
2405
2406 # Add a pragma line to disable implied branch matchers in
2407 # project1, so that the jobs and templates apply to both
2408 # branches.
2409 with open(os.path.join(FIXTURE_DIR,
2410 'config/pragma-multibranch/git/',
2411 'org_project1/zuul.yaml')) as f:
2412 config = f.read()
2413 extra_conf = textwrap.dedent(
2414 """
2415 - pragma:
2416 implied-branch-matchers: False
2417 """)
2418 config = extra_conf + config
2419 file_dict = {'zuul.yaml': config}
2420 A = self.fake_gerrit.addFakeChange('org/project1', 'stable/pike', 'A',
2421 files=file_dict)
2422 A.addApproval('Code-Review', 2)
2423 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
2424 self.waitUntilSettled()
2425 self.fake_gerrit.addEvent(A.getChangeMergedEvent())
2426 self.waitUntilSettled()
2427
2428 # Now verify that when we propose a change to jewel, we get
2429 # the pike/jewel jobs.
2430 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
2431 self.waitUntilSettled()
2432 self.assertHistory([
2433 dict(name='test-job1', result='SUCCESS', changes='1,1'),
2434 dict(name='test-job2', result='SUCCESS', changes='1,1'),
2435 ], ordered=False)
2436
2437 def test_supplied_branch_matchers(self):
2438 self.create_branch('org/project1', 'stable/pike')
2439 self.create_branch('org/project2', 'stable/jewel')
2440 self.fake_gerrit.addEvent(
2441 self.fake_gerrit.getFakeBranchCreatedEvent(
2442 'org/project1', 'stable/pike'))
2443 self.fake_gerrit.addEvent(
2444 self.fake_gerrit.getFakeBranchCreatedEvent(
2445 'org/project2', 'stable/jewel'))
2446 self.waitUntilSettled()
2447 # We want the jobs defined on the stable/pike branch of
2448 # project1 to apply to the stable/jewel branch of project2.
2449
2450 # First, without the pragma line, the jobs should not run
2451 # because in project1 they have branch matchers for pike, so
2452 # they will not match a jewel change.
2453 B = self.fake_gerrit.addFakeChange('org/project2', 'stable/jewel', 'B')
2454 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
2455 self.waitUntilSettled()
2456 self.assertHistory([])
2457
2458 # Add a pragma line to disable implied branch matchers in
2459 # project1, so that the jobs and templates apply to both
2460 # branches.
2461 with open(os.path.join(FIXTURE_DIR,
2462 'config/pragma-multibranch/git/',
2463 'org_project1/zuul.yaml')) as f:
2464 config = f.read()
2465 extra_conf = textwrap.dedent(
2466 """
2467 - pragma:
2468 implied-branches:
2469 - stable/pike
2470 - stable/jewel
2471 """)
2472 config = extra_conf + config
2473 file_dict = {'zuul.yaml': config}
2474 A = self.fake_gerrit.addFakeChange('org/project1', 'stable/pike', 'A',
2475 files=file_dict)
2476 A.addApproval('Code-Review', 2)
2477 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
2478 self.waitUntilSettled()
2479 self.fake_gerrit.addEvent(A.getChangeMergedEvent())
2480 self.waitUntilSettled()
2481 # Now verify that when we propose a change to jewel, we get
2482 # the pike/jewel jobs.
2483 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
2484 self.waitUntilSettled()
2485 self.assertHistory([
2486 dict(name='test-job1', result='SUCCESS', changes='1,1'),
2487 dict(name='test-job2', result='SUCCESS', changes='1,1'),
2488 ], ordered=False)
2489
2490
James E. Blair2bab6e72017-08-07 09:52:45 -07002491class TestBaseJobs(ZuulTestCase):
2492 tenant_config_file = 'config/base-jobs/main.yaml'
2493
2494 def test_multiple_base_jobs(self):
2495 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2496 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2497 self.waitUntilSettled()
2498 self.assertHistory([
2499 dict(name='my-job', result='SUCCESS', changes='1,1'),
2500 dict(name='other-job', result='SUCCESS', changes='1,1'),
2501 ], ordered=False)
2502 self.assertEqual(self.getJobFromHistory('my-job').
2503 parameters['zuul']['jobtags'],
2504 ['mybase'])
2505 self.assertEqual(self.getJobFromHistory('other-job').
2506 parameters['zuul']['jobtags'],
2507 ['otherbase'])
2508
2509 def test_untrusted_base_job(self):
2510 """Test that a base job may not be defined in an untrusted repo"""
2511 in_repo_conf = textwrap.dedent(
2512 """
2513 - job:
2514 name: fail-base
2515 parent: null
2516 """)
2517
2518 file_dict = {'.zuul.yaml': in_repo_conf}
2519 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
2520 files=file_dict)
2521 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2522 self.waitUntilSettled()
2523 self.assertEqual(A.reported, 1,
2524 "A should report failure")
2525 self.assertEqual(A.patchsets[0]['approvals'][0]['value'], "-1")
2526 self.assertIn('Base jobs must be defined in config projects',
2527 A.messages[0])
2528 self.assertHistory([])
James E. Blairdb089032017-08-15 13:42:12 -07002529
2530
James E. Blaira17a8e72018-01-17 13:45:25 -08002531class TestSecrets(ZuulTestCase):
2532 tenant_config_file = 'config/secrets/main.yaml'
2533 secret = {'password': 'test-password',
2534 'username': 'test-username'}
2535
2536 def _getSecrets(self, job, pbtype):
2537 secrets = []
2538 build = self.getJobFromHistory(job)
2539 for pb in build.parameters[pbtype]:
2540 secrets.append(pb['secrets'])
2541 return secrets
2542
2543 def test_secret_branch(self):
2544 # Test that we can use a secret defined in another branch of
2545 # the same project.
2546 self.create_branch('org/project2', 'stable')
2547 self.fake_gerrit.addEvent(
2548 self.fake_gerrit.getFakeBranchCreatedEvent(
2549 'org/project2', 'stable'))
2550 self.waitUntilSettled()
2551
2552 with open(os.path.join(FIXTURE_DIR,
2553 'config/secrets/git/',
2554 'org_project2/zuul-secret.yaml')) as f:
2555 config = f.read()
2556
2557 file_dict = {'zuul.yaml': config}
2558 A = self.fake_gerrit.addFakeChange('org/project2', 'master', 'A',
2559 files=file_dict)
2560 A.addApproval('Code-Review', 2)
2561 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
2562 self.waitUntilSettled()
2563 self.assertEqual(A.data['status'], 'MERGED')
2564 self.fake_gerrit.addEvent(A.getChangeMergedEvent())
2565 self.waitUntilSettled()
2566
2567 in_repo_conf = textwrap.dedent(
2568 """
2569 - job:
2570 parent: base
2571 name: project2-secret
2572 run: playbooks/secret.yaml
2573 secrets: [project2_secret]
2574
2575 - project:
2576 check:
2577 jobs:
2578 - project2-secret
2579 gate:
2580 jobs:
2581 - noop
2582 """)
2583 file_dict = {'zuul.yaml': in_repo_conf}
2584 B = self.fake_gerrit.addFakeChange('org/project2', 'stable', 'B',
2585 files=file_dict)
2586 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
2587 self.waitUntilSettled()
2588 self.assertEqual(B.reported, 1, "B should report success")
2589 self.assertHistory([
2590 dict(name='project2-secret', result='SUCCESS', changes='2,1'),
2591 ])
2592 self.assertEqual(
2593 self._getSecrets('project2-secret', 'playbooks'),
2594 [{'project2_secret': self.secret}])
2595
2596 def test_secret_branch_duplicate(self):
2597 # Test that we can create a duplicate secret on a different
2598 # branch of the same project -- i.e., that when we branch
2599 # master to stable on a project with a secret, nothing
2600 # changes.
2601 self.create_branch('org/project1', 'stable')
2602 self.fake_gerrit.addEvent(
2603 self.fake_gerrit.getFakeBranchCreatedEvent(
2604 'org/project1', 'stable'))
2605 self.waitUntilSettled()
2606
2607 A = self.fake_gerrit.addFakeChange('org/project1', 'stable', 'A')
2608 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2609 self.waitUntilSettled()
2610 self.assertEqual(A.reported, 1,
2611 "A should report success")
2612 self.assertHistory([
2613 dict(name='project1-secret', result='SUCCESS', changes='1,1'),
2614 ])
2615 self.assertEqual(
2616 self._getSecrets('project1-secret', 'playbooks'),
2617 [{'project1_secret': self.secret}])
2618
2619 def test_secret_branch_error_same_branch(self):
2620 # Test that we are unable to define a secret twice on the same
2621 # project-branch.
2622 in_repo_conf = textwrap.dedent(
2623 """
2624 - secret:
2625 name: project1_secret
2626 data: {}
2627 - secret:
2628 name: project1_secret
2629 data: {}
2630 """)
2631 file_dict = {'zuul.yaml': in_repo_conf}
2632 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A',
2633 files=file_dict)
2634 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2635 self.waitUntilSettled()
2636 self.assertIn('already defined', A.messages[0])
2637
2638 def test_secret_branch_error_same_project(self):
2639 # Test that we are unable to create a secret which differs
2640 # from another with the same name -- i.e., that if we have a
2641 # duplicate secret on multiple branches of the same project,
2642 # they must be identical.
2643 self.create_branch('org/project1', 'stable')
2644 self.fake_gerrit.addEvent(
2645 self.fake_gerrit.getFakeBranchCreatedEvent(
2646 'org/project1', 'stable'))
2647 self.waitUntilSettled()
2648
2649 in_repo_conf = textwrap.dedent(
2650 """
2651 - secret:
2652 name: project1_secret
2653 data: {}
2654 """)
2655 file_dict = {'zuul.yaml': in_repo_conf}
2656 A = self.fake_gerrit.addFakeChange('org/project1', 'stable', 'A',
2657 files=file_dict)
2658 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2659 self.waitUntilSettled()
2660 self.assertIn('does not match existing definition in branch master',
2661 A.messages[0])
2662
2663 def test_secret_branch_error_other_project(self):
2664 # Test that we are unable to create a secret with the same
2665 # name as another. We're never allowed to have a secret with
2666 # the same name outside of a project.
2667 in_repo_conf = textwrap.dedent(
2668 """
2669 - secret:
2670 name: project1_secret
2671 data: {}
2672 """)
2673 file_dict = {'zuul.yaml': in_repo_conf}
2674 A = self.fake_gerrit.addFakeChange('org/project2', 'master', 'A',
2675 files=file_dict)
2676 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2677 self.waitUntilSettled()
2678 self.assertIn('already defined in project org/project1',
2679 A.messages[0])
2680
2681
James E. Blairdf91ab32017-10-25 17:57:13 -07002682class TestSecretInheritance(ZuulTestCase):
2683 tenant_config_file = 'config/secret-inheritance/main.yaml'
2684
2685 def _getSecrets(self, job, pbtype):
2686 secrets = []
2687 build = self.getJobFromHistory(job)
2688 for pb in build.parameters[pbtype]:
2689 secrets.append(pb['secrets'])
2690 return secrets
2691
2692 def _checkTrustedSecrets(self):
2693 secret = {'longpassword': 'test-passwordtest-password',
2694 'password': 'test-password',
2695 'username': 'test-username'}
2696 self.assertEqual(
2697 self._getSecrets('trusted-secrets', 'playbooks'),
James E. Blair2f589fe2017-10-26 12:57:41 -07002698 [{'trusted-secret': secret}])
James E. Blairdf91ab32017-10-25 17:57:13 -07002699 self.assertEqual(
2700 self._getSecrets('trusted-secrets', 'pre_playbooks'), [])
2701 self.assertEqual(
2702 self._getSecrets('trusted-secrets', 'post_playbooks'), [])
2703
2704 self.assertEqual(
2705 self._getSecrets('trusted-secrets-trusted-child',
James E. Blair2f589fe2017-10-26 12:57:41 -07002706 'playbooks'), [{}])
James E. Blairdf91ab32017-10-25 17:57:13 -07002707 self.assertEqual(
2708 self._getSecrets('trusted-secrets-trusted-child',
2709 'pre_playbooks'), [])
2710 self.assertEqual(
2711 self._getSecrets('trusted-secrets-trusted-child',
2712 'post_playbooks'), [])
2713
2714 self.assertEqual(
2715 self._getSecrets('trusted-secrets-untrusted-child',
James E. Blair2f589fe2017-10-26 12:57:41 -07002716 'playbooks'), [{}])
James E. Blairdf91ab32017-10-25 17:57:13 -07002717 self.assertEqual(
2718 self._getSecrets('trusted-secrets-untrusted-child',
2719 'pre_playbooks'), [])
2720 self.assertEqual(
2721 self._getSecrets('trusted-secrets-untrusted-child',
2722 'post_playbooks'), [])
2723
2724 def _checkUntrustedSecrets(self):
2725 secret = {'longpassword': 'test-passwordtest-password',
2726 'password': 'test-password',
2727 'username': 'test-username'}
2728 self.assertEqual(
2729 self._getSecrets('untrusted-secrets', 'playbooks'),
James E. Blair2f589fe2017-10-26 12:57:41 -07002730 [{'untrusted-secret': secret}])
James E. Blairdf91ab32017-10-25 17:57:13 -07002731 self.assertEqual(
2732 self._getSecrets('untrusted-secrets', 'pre_playbooks'), [])
2733 self.assertEqual(
2734 self._getSecrets('untrusted-secrets', 'post_playbooks'), [])
2735
2736 self.assertEqual(
2737 self._getSecrets('untrusted-secrets-trusted-child',
James E. Blair2f589fe2017-10-26 12:57:41 -07002738 'playbooks'), [{}])
James E. Blairdf91ab32017-10-25 17:57:13 -07002739 self.assertEqual(
2740 self._getSecrets('untrusted-secrets-trusted-child',
2741 'pre_playbooks'), [])
2742 self.assertEqual(
2743 self._getSecrets('untrusted-secrets-trusted-child',
2744 'post_playbooks'), [])
2745
2746 self.assertEqual(
2747 self._getSecrets('untrusted-secrets-untrusted-child',
James E. Blair2f589fe2017-10-26 12:57:41 -07002748 'playbooks'), [{}])
James E. Blairdf91ab32017-10-25 17:57:13 -07002749 self.assertEqual(
2750 self._getSecrets('untrusted-secrets-untrusted-child',
2751 'pre_playbooks'), [])
2752 self.assertEqual(
2753 self._getSecrets('untrusted-secrets-untrusted-child',
2754 'post_playbooks'), [])
2755
2756 def test_trusted_secret_inheritance_check(self):
2757 A = self.fake_gerrit.addFakeChange('common-config', 'master', 'A')
2758 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2759 self.waitUntilSettled()
2760 self.assertHistory([
2761 dict(name='trusted-secrets', result='SUCCESS', changes='1,1'),
2762 dict(name='trusted-secrets-trusted-child',
2763 result='SUCCESS', changes='1,1'),
2764 dict(name='trusted-secrets-untrusted-child',
2765 result='SUCCESS', changes='1,1'),
2766 ], ordered=False)
2767
2768 self._checkTrustedSecrets()
2769
2770 def test_untrusted_secret_inheritance_gate(self):
2771 A = self.fake_gerrit.addFakeChange('common-config', 'master', 'A')
2772 A.addApproval('Code-Review', 2)
2773 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
2774 self.waitUntilSettled()
2775 self.assertHistory([
2776 dict(name='untrusted-secrets', result='SUCCESS', changes='1,1'),
2777 dict(name='untrusted-secrets-trusted-child',
2778 result='SUCCESS', changes='1,1'),
2779 dict(name='untrusted-secrets-untrusted-child',
2780 result='SUCCESS', changes='1,1'),
2781 ], ordered=False)
2782
2783 self._checkUntrustedSecrets()
2784
2785 def test_untrusted_secret_inheritance_check(self):
2786 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2787 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2788 self.waitUntilSettled()
2789 # This configuration tries to run untrusted secrets in an
2790 # non-post-review pipeline and should therefore run no jobs.
2791 self.assertHistory([])
2792
2793
James E. Blairdb089032017-08-15 13:42:12 -07002794class TestSecretLeaks(AnsibleZuulTestCase):
2795 tenant_config_file = 'config/secret-leaks/main.yaml'
2796
2797 def searchForContent(self, path, content):
2798 matches = []
2799 for (dirpath, dirnames, filenames) in os.walk(path):
2800 for filename in filenames:
2801 filepath = os.path.join(dirpath, filename)
2802 with open(filepath, 'rb') as f:
2803 if content in f.read():
2804 matches.append(filepath[len(path):])
2805 return matches
2806
2807 def _test_secret_file(self):
2808 # Or rather -- test that they *don't* leak.
2809 # Keep the jobdir around so we can inspect contents.
2810 self.executor_server.keep_jobdir = True
2811 conf = textwrap.dedent(
2812 """
2813 - project:
2814 name: org/project
2815 check:
2816 jobs:
2817 - secret-file
2818 """)
2819
2820 file_dict = {'.zuul.yaml': conf}
2821 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
2822 files=file_dict)
2823 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2824 self.waitUntilSettled()
2825 self.assertHistory([
2826 dict(name='secret-file', result='SUCCESS', changes='1,1'),
2827 ], ordered=False)
2828 matches = self.searchForContent(self.history[0].jobdir.root,
2829 b'test-password')
James E. Blaird6a71ca2017-08-18 14:15:05 -07002830 self.assertEqual(set(['/work/secret-file.txt']),
James E. Blairdb089032017-08-15 13:42:12 -07002831 set(matches))
2832
2833 def test_secret_file(self):
2834 self._test_secret_file()
2835
2836 def test_secret_file_verbose(self):
2837 # Output extra ansible info to exercise alternate logging code
2838 # paths.
2839 self.executor_server.verbose = True
2840 self._test_secret_file()
2841
2842 def _test_secret_file_fail(self):
2843 # Or rather -- test that they *don't* leak.
2844 # Keep the jobdir around so we can inspect contents.
2845 self.executor_server.keep_jobdir = True
2846 conf = textwrap.dedent(
2847 """
2848 - project:
2849 name: org/project
2850 check:
2851 jobs:
2852 - secret-file-fail
2853 """)
2854
2855 file_dict = {'.zuul.yaml': conf}
2856 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
2857 files=file_dict)
2858 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2859 self.waitUntilSettled()
2860 self.assertHistory([
2861 dict(name='secret-file-fail', result='FAILURE', changes='1,1'),
2862 ], ordered=False)
2863 matches = self.searchForContent(self.history[0].jobdir.root,
2864 b'test-password')
James E. Blaird6a71ca2017-08-18 14:15:05 -07002865 self.assertEqual(set(['/work/failure-file.txt']),
James E. Blairdb089032017-08-15 13:42:12 -07002866 set(matches))
2867
2868 def test_secret_file_fail(self):
2869 self._test_secret_file_fail()
2870
2871 def test_secret_file_fail_verbose(self):
2872 # Output extra ansible info to exercise alternate logging code
2873 # paths.
2874 self.executor_server.verbose = True
2875 self._test_secret_file_fail()
James E. Blaira00910c2017-08-23 09:15:04 -07002876
2877
James E. Blair8446c412018-01-17 15:49:59 -08002878class TestNodesets(ZuulTestCase):
2879 tenant_config_file = 'config/nodesets/main.yaml'
2880
2881 def test_nodeset_branch(self):
2882 # Test that we can use a nodeset defined in another branch of
2883 # the same project.
2884 self.create_branch('org/project2', 'stable')
2885 self.fake_gerrit.addEvent(
2886 self.fake_gerrit.getFakeBranchCreatedEvent(
2887 'org/project2', 'stable'))
2888 self.waitUntilSettled()
2889
2890 with open(os.path.join(FIXTURE_DIR,
2891 'config/nodesets/git/',
2892 'org_project2/zuul-nodeset.yaml')) as f:
2893 config = f.read()
2894
2895 file_dict = {'zuul.yaml': config}
2896 A = self.fake_gerrit.addFakeChange('org/project2', 'master', 'A',
2897 files=file_dict)
2898 A.addApproval('Code-Review', 2)
2899 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
2900 self.waitUntilSettled()
2901 self.assertEqual(A.data['status'], 'MERGED')
2902 self.fake_gerrit.addEvent(A.getChangeMergedEvent())
2903 self.waitUntilSettled()
2904
2905 in_repo_conf = textwrap.dedent(
2906 """
2907 - job:
2908 parent: base
2909 name: project2-test
2910 nodeset: project2-nodeset
2911
2912 - project:
2913 check:
2914 jobs:
2915 - project2-test
2916 gate:
2917 jobs:
2918 - noop
2919 """)
2920 file_dict = {'zuul.yaml': in_repo_conf}
2921 B = self.fake_gerrit.addFakeChange('org/project2', 'stable', 'B',
2922 files=file_dict)
2923 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
2924 self.waitUntilSettled()
2925 self.assertEqual(B.reported, 1, "B should report success")
2926 self.assertHistory([
2927 dict(name='project2-test', result='SUCCESS', changes='2,1',
2928 node='ubuntu-xenial'),
2929 ])
2930
2931 def test_nodeset_branch_duplicate(self):
Monty Taylorbc1d0bb2018-01-22 17:05:31 -06002932 # Test that we can create a duplicate nodeset on a different
James E. Blair8446c412018-01-17 15:49:59 -08002933 # branch of the same project -- i.e., that when we branch
Monty Taylorbc1d0bb2018-01-22 17:05:31 -06002934 # master to stable on a project with a nodeset, nothing
James E. Blair8446c412018-01-17 15:49:59 -08002935 # changes.
2936 self.create_branch('org/project1', 'stable')
2937 self.fake_gerrit.addEvent(
2938 self.fake_gerrit.getFakeBranchCreatedEvent(
2939 'org/project1', 'stable'))
2940 self.waitUntilSettled()
2941
2942 A = self.fake_gerrit.addFakeChange('org/project1', 'stable', 'A')
2943 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2944 self.waitUntilSettled()
2945 self.assertEqual(A.reported, 1,
2946 "A should report success")
2947 self.assertHistory([
2948 dict(name='project1-test', result='SUCCESS', changes='1,1',
2949 node='ubuntu-xenial'),
2950 ])
2951
2952 def test_nodeset_branch_error_same_branch(self):
2953 # Test that we are unable to define a nodeset twice on the same
2954 # project-branch.
2955 in_repo_conf = textwrap.dedent(
2956 """
2957 - nodeset:
2958 name: project1-nodeset
2959 nodes: []
2960 - nodeset:
2961 name: project1-nodeset
2962 nodes: []
2963 """)
2964 file_dict = {'zuul.yaml': in_repo_conf}
2965 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A',
2966 files=file_dict)
2967 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2968 self.waitUntilSettled()
2969 self.assertIn('already defined', A.messages[0])
2970
2971 def test_nodeset_branch_error_same_project(self):
2972 # Test that we are unable to create a nodeset which differs
2973 # from another with the same name -- i.e., that if we have a
2974 # duplicate nodeset on multiple branches of the same project,
2975 # they must be identical.
2976 self.create_branch('org/project1', 'stable')
2977 self.fake_gerrit.addEvent(
2978 self.fake_gerrit.getFakeBranchCreatedEvent(
2979 'org/project1', 'stable'))
2980 self.waitUntilSettled()
2981
2982 in_repo_conf = textwrap.dedent(
2983 """
2984 - nodeset:
2985 name: project1-nodeset
2986 nodes: []
2987 """)
2988 file_dict = {'zuul.yaml': in_repo_conf}
2989 A = self.fake_gerrit.addFakeChange('org/project1', 'stable', 'A',
2990 files=file_dict)
2991 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2992 self.waitUntilSettled()
2993 self.assertIn('does not match existing definition in branch master',
2994 A.messages[0])
2995
2996 def test_nodeset_branch_error_other_project(self):
2997 # Test that we are unable to create a nodeset with the same
2998 # name as another. We're never allowed to have a nodeset with
2999 # the same name outside of a project.
3000 in_repo_conf = textwrap.dedent(
3001 """
3002 - nodeset:
3003 name: project1-nodeset
3004 nodes: []
3005 """)
3006 file_dict = {'zuul.yaml': in_repo_conf}
3007 A = self.fake_gerrit.addFakeChange('org/project2', 'master', 'A',
3008 files=file_dict)
3009 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
3010 self.waitUntilSettled()
3011 self.assertIn('already defined in project org/project1',
3012 A.messages[0])
3013
3014
James E. Blaira00910c2017-08-23 09:15:04 -07003015class TestJobOutput(AnsibleZuulTestCase):
3016 tenant_config_file = 'config/job-output/main.yaml'
3017
3018 def _get_file(self, build, path):
3019 p = os.path.join(build.jobdir.root, path)
3020 with open(p) as f:
3021 return f.read()
3022
3023 def test_job_output(self):
Monty Taylor0e2489a2017-10-10 11:57:29 -05003024 # Verify that command standard output appears in the job output,
3025 # and that failures in the final playbook get logged.
James E. Blaira00910c2017-08-23 09:15:04 -07003026
3027 # This currently only verifies we receive output from
3028 # localhost. Notably, it does not verify we receive output
3029 # via zuul_console streaming.
3030 self.executor_server.keep_jobdir = True
3031 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
3032 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
3033 self.waitUntilSettled()
3034 self.assertHistory([
3035 dict(name='job-output', result='SUCCESS', changes='1,1'),
3036 ], ordered=False)
3037
3038 token = 'Standard output test %s' % (self.history[0].jobdir.src_root)
3039 j = json.loads(self._get_file(self.history[0],
3040 'work/logs/job-output.json'))
3041 self.assertEqual(token,
3042 j[0]['plays'][0]['tasks'][0]
3043 ['hosts']['localhost']['stdout'])
3044
3045 print(self._get_file(self.history[0],
3046 'work/logs/job-output.txt'))
3047 self.assertIn(token,
3048 self._get_file(self.history[0],
3049 'work/logs/job-output.txt'))
Monty Taylor0e2489a2017-10-10 11:57:29 -05003050
3051 def test_job_output_failure_log(self):
3052 logger = logging.getLogger('zuul.AnsibleJob')
3053 output = io.StringIO()
3054 logger.addHandler(logging.StreamHandler(output))
3055
3056 # Verify that a failure in the last post playbook emits the contents
3057 # of the json output to the log
3058 self.executor_server.keep_jobdir = True
3059 A = self.fake_gerrit.addFakeChange('org/project2', 'master', 'A')
3060 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
3061 self.waitUntilSettled()
3062 self.assertHistory([
3063 dict(name='job-output-failure',
3064 result='POST_FAILURE', changes='1,1'),
3065 ], ordered=False)
3066
3067 token = 'Standard output test %s' % (self.history[0].jobdir.src_root)
3068 j = json.loads(self._get_file(self.history[0],
3069 'work/logs/job-output.json'))
3070 self.assertEqual(token,
3071 j[0]['plays'][0]['tasks'][0]
3072 ['hosts']['localhost']['stdout'])
3073
3074 print(self._get_file(self.history[0],
3075 'work/logs/job-output.json'))
3076 self.assertIn(token,
3077 self._get_file(self.history[0],
3078 'work/logs/job-output.txt'))
3079
3080 log_output = output.getvalue()
3081 self.assertIn('Final playbook failed', log_output)
3082 self.assertIn('Failure test', log_output)