blob: 164d5b4ee74609ce902b87544f8cdfe9cf95596f [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. Blair7fb04512018-01-23 13:23:13 -0800500class TestBranchMismatch(ZuulTestCase):
501 tenant_config_file = 'config/branch-mismatch/main.yaml'
502
503 def test_job_override_branch(self):
504 "Test that override-checkout overrides branch matchers as well"
505
506 # Make sure the parent job repo is branched, so it gets
507 # implied branch matchers.
508 self.create_branch('org/project1', 'stable')
509 self.fake_gerrit.addEvent(
510 self.fake_gerrit.getFakeBranchCreatedEvent(
511 'org/project1', 'stable'))
512
513 # The child job repo should have a branch which does not exist
514 # in the parent job repo.
515 self.create_branch('org/project2', 'devel')
516 self.fake_gerrit.addEvent(
517 self.fake_gerrit.getFakeBranchCreatedEvent(
518 'org/project2', 'devel'))
519
520 # A job in a repo with a weird branch name should use the
521 # parent job from the parent job's master (default) branch.
522 A = self.fake_gerrit.addFakeChange('org/project2', 'devel', 'A')
523 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
524 self.waitUntilSettled()
525 # project-test2 should run because it inherits from
526 # project-test1 and we will use the fallback branch to find
527 # project-test1 variants, but project-test1 itself, even
528 # though it is in the project-pipeline config, should not run
529 # because it doesn't directly match.
530 self.assertHistory([
531 dict(name='project-test1', result='SUCCESS', changes='1,1'),
532 dict(name='project-test2', result='SUCCESS', changes='1,1'),
533 ], ordered=False)
534
535
James E. Blair2a664502017-10-27 11:39:33 -0700536class TestCentralJobs(ZuulTestCase):
537 tenant_config_file = 'config/central-jobs/main.yaml'
538
539 def setUp(self):
540 super(TestCentralJobs, self).setUp()
541 self.create_branch('org/project', 'stable')
542 self.fake_gerrit.addEvent(
543 self.fake_gerrit.getFakeBranchCreatedEvent(
544 'org/project', 'stable'))
545 self.waitUntilSettled()
546
547 def _updateConfig(self, config, branch):
548 file_dict = {'.zuul.yaml': config}
549 C = self.fake_gerrit.addFakeChange('org/project', branch, 'C',
550 files=file_dict)
551 C.addApproval('Code-Review', 2)
552 self.fake_gerrit.addEvent(C.addApproval('Approved', 1))
553 self.waitUntilSettled()
554 self.fake_gerrit.addEvent(C.getChangeMergedEvent())
555 self.waitUntilSettled()
556
557 def _test_central_job_on_branch(self, branch, other_branch):
558 # Test that a job defined on a branchless repo only runs on
559 # the branch applied
560 config = textwrap.dedent(
561 """
562 - project:
563 name: org/project
564 check:
565 jobs:
566 - central-job
567 """)
568 self._updateConfig(config, branch)
569
570 A = self.fake_gerrit.addFakeChange('org/project', branch, 'A')
571 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
572 self.waitUntilSettled()
573
574 self.assertHistory([
575 dict(name='central-job', result='SUCCESS', changes='2,1')])
576
577 # No jobs should run for this change.
578 B = self.fake_gerrit.addFakeChange('org/project', other_branch, 'B')
579 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
580 self.waitUntilSettled()
581
582 self.assertHistory([
583 dict(name='central-job', result='SUCCESS', changes='2,1')])
584
585 def test_central_job_on_stable(self):
586 self._test_central_job_on_branch('master', 'stable')
587
588 def test_central_job_on_master(self):
589 self._test_central_job_on_branch('stable', 'master')
590
591 def _test_central_template_on_branch(self, branch, other_branch):
592 # Test that a project-template defined on a branchless repo
593 # only runs on the branch applied
594 config = textwrap.dedent(
595 """
596 - project:
597 name: org/project
598 templates: ['central-jobs']
599 """)
600 self._updateConfig(config, branch)
601
602 A = self.fake_gerrit.addFakeChange('org/project', branch, 'A')
603 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
604 self.waitUntilSettled()
605
606 self.assertHistory([
607 dict(name='central-job', result='SUCCESS', changes='2,1')])
608
609 # No jobs should run for this change.
610 B = self.fake_gerrit.addFakeChange('org/project', other_branch, 'B')
611 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
612 self.waitUntilSettled()
613
614 self.assertHistory([
615 dict(name='central-job', result='SUCCESS', changes='2,1')])
616
617 def test_central_template_on_stable(self):
618 self._test_central_template_on_branch('master', 'stable')
619
620 def test_central_template_on_master(self):
621 self._test_central_template_on_branch('stable', 'master')
622
623
James E. Blairff555742017-02-19 11:34:27 -0800624class TestInRepoConfig(ZuulTestCase):
James E. Blair83005782015-12-11 14:46:03 -0800625 # A temporary class to hold new tests while others are disabled
626
Tobias Henkelabf973e2017-07-28 10:07:34 +0200627 config_file = 'zuul-connections-gerrit-and-github.conf'
James E. Blair2a629ec2015-12-22 15:32:02 -0800628 tenant_config_file = 'config/in-repo/main.yaml'
James E. Blair83005782015-12-11 14:46:03 -0800629
James E. Blair83005782015-12-11 14:46:03 -0800630 def test_in_repo_config(self):
James E. Blair14abdf42015-12-09 16:11:53 -0800631 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
Tobias Henkelbf24fd12017-07-27 06:13:07 +0200632 A.addApproval('Code-Review', 2)
633 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
James E. Blair14abdf42015-12-09 16:11:53 -0800634 self.waitUntilSettled()
635 self.assertEqual(self.getJobFromHistory('project-test1').result,
636 'SUCCESS')
637 self.assertEqual(A.data['status'], 'MERGED')
638 self.assertEqual(A.reported, 2,
639 "A should report start and success")
640 self.assertIn('tenant-one-gate', A.messages[1],
641 "A should transit tenant-one gate")
James E. Blairb97ed802015-12-21 15:55:35 -0800642
James E. Blair3a098dd2017-10-04 14:37:29 -0700643 @skip("This test is useful, but not reliable")
644 def test_full_and_dynamic_reconfig(self):
645 self.executor_server.hold_jobs_in_build = True
646 in_repo_conf = textwrap.dedent(
647 """
648 - job:
649 name: project-test1
650
651 - project:
652 name: org/project
653 tenant-one-gate:
654 jobs:
655 - project-test1
656 """)
657
658 file_dict = {'.zuul.yaml': in_repo_conf}
659 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
660 files=file_dict)
661 A.addApproval('Code-Review', 2)
662 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
663 self.waitUntilSettled()
664 self.sched.reconfigure(self.config)
665 self.waitUntilSettled()
666
667 gc.collect()
668 pipelines = [obj for obj in gc.get_objects()
669 if isinstance(obj, zuul.model.Pipeline)]
670 self.assertEqual(len(pipelines), 4)
671
672 self.executor_server.hold_jobs_in_build = False
673 self.executor_server.release()
674 self.waitUntilSettled()
675
James E. Blair8b1dc3f2016-07-05 16:49:00 -0700676 def test_dynamic_config(self):
677 in_repo_conf = textwrap.dedent(
678 """
679 - job:
Tobias Henkelf02cf512017-07-21 22:55:34 +0200680 name: project-test1
681
682 - job:
James E. Blair8b1dc3f2016-07-05 16:49:00 -0700683 name: project-test2
James E. Blair2f589fe2017-10-26 12:57:41 -0700684 run: playbooks/project-test2.yaml
James E. Blair8b1dc3f2016-07-05 16:49:00 -0700685
Tobias Henkel53aa2ad2017-12-22 09:59:45 +0100686 - job:
687 name: project-test3
688 run: playbooks/project-test2.yaml
689
690 # add a job by the short project name
James E. Blair8b1dc3f2016-07-05 16:49:00 -0700691 - project:
692 name: org/project
693 tenant-one-gate:
694 jobs:
695 - project-test2
Tobias Henkel53aa2ad2017-12-22 09:59:45 +0100696
697 # add a job by the canonical project name
698 - project:
699 name: review.example.com/org/project
700 tenant-one-gate:
701 jobs:
702 - project-test3
James E. Blair8b1dc3f2016-07-05 16:49:00 -0700703 """)
704
James E. Blairc73c73a2017-01-20 15:15:15 -0800705 in_repo_playbook = textwrap.dedent(
706 """
707 - hosts: all
708 tasks: []
709 """)
710
711 file_dict = {'.zuul.yaml': in_repo_conf,
712 'playbooks/project-test2.yaml': in_repo_playbook}
James E. Blair8b1dc3f2016-07-05 16:49:00 -0700713 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
James E. Blairc73c73a2017-01-20 15:15:15 -0800714 files=file_dict)
Tobias Henkelbf24fd12017-07-27 06:13:07 +0200715 A.addApproval('Code-Review', 2)
716 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
James E. Blair8b1dc3f2016-07-05 16:49:00 -0700717 self.waitUntilSettled()
James E. Blair8b1dc3f2016-07-05 16:49:00 -0700718 self.assertEqual(A.data['status'], 'MERGED')
719 self.assertEqual(A.reported, 2,
720 "A should report start and success")
721 self.assertIn('tenant-one-gate', A.messages[1],
722 "A should transit tenant-one gate")
James E. Blair646322f2017-01-27 15:50:34 -0800723 self.assertHistory([
Tobias Henkel53aa2ad2017-12-22 09:59:45 +0100724 dict(name='project-test2', result='SUCCESS', changes='1,1'),
725 dict(name='project-test3', result='SUCCESS', changes='1,1'),
726 ], ordered=False)
James E. Blair646322f2017-01-27 15:50:34 -0800727
James E. Blairc2a5ed72017-02-20 14:12:01 -0500728 self.fake_gerrit.addEvent(A.getChangeMergedEvent())
James E. Blair7bbd7a32017-03-06 11:36:13 -0800729 self.waitUntilSettled()
James E. Blairc2a5ed72017-02-20 14:12:01 -0500730
James E. Blair646322f2017-01-27 15:50:34 -0800731 # Now that the config change is landed, it should be live for
732 # subsequent changes.
733 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
Tobias Henkelbf24fd12017-07-27 06:13:07 +0200734 B.addApproval('Code-Review', 2)
735 self.fake_gerrit.addEvent(B.addApproval('Approved', 1))
James E. Blair646322f2017-01-27 15:50:34 -0800736 self.waitUntilSettled()
737 self.assertEqual(self.getJobFromHistory('project-test2').result,
738 'SUCCESS')
739 self.assertHistory([
740 dict(name='project-test2', result='SUCCESS', changes='1,1'),
Tobias Henkel53aa2ad2017-12-22 09:59:45 +0100741 dict(name='project-test3', result='SUCCESS', changes='1,1'),
742 dict(name='project-test2', result='SUCCESS', changes='2,1'),
743 dict(name='project-test3', result='SUCCESS', changes='2,1'),
744 ], ordered=False)
James E. Blairc73c73a2017-01-20 15:15:15 -0800745
James E. Blair6bc10482017-10-20 11:28:53 -0700746 def test_dynamic_template(self):
James E. Blair2a664502017-10-27 11:39:33 -0700747 # Tests that a project can't update a template in another
748 # project.
James E. Blair6bc10482017-10-20 11:28:53 -0700749 in_repo_conf = textwrap.dedent(
750 """
751 - job:
752 name: project-test1
753
754 - project-template:
755 name: common-config-template
756 check:
757 jobs:
758 - project-test1
759
760 - project:
761 name: org/project
762 templates: [common-config-template]
763 """)
764
765 file_dict = {'.zuul.yaml': in_repo_conf}
766 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
767 files=file_dict)
768 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
769 self.waitUntilSettled()
James E. Blair2a664502017-10-27 11:39:33 -0700770
771 self.assertEqual(A.patchsets[0]['approvals'][0]['value'], "-1")
772 self.assertIn('Project template common-config-template '
773 'is already defined',
774 A.messages[0],
775 "A should have failed the check pipeline")
James E. Blair6bc10482017-10-20 11:28:53 -0700776
Tobias Henkelf02cf512017-07-21 22:55:34 +0200777 def test_dynamic_config_non_existing_job(self):
778 """Test that requesting a non existent job fails"""
779 in_repo_conf = textwrap.dedent(
780 """
781 - job:
782 name: project-test1
783
784 - project:
785 name: org/project
786 check:
787 jobs:
788 - non-existent-job
789 """)
790
791 in_repo_playbook = textwrap.dedent(
792 """
793 - hosts: all
794 tasks: []
795 """)
796
797 file_dict = {'.zuul.yaml': in_repo_conf,
798 'playbooks/project-test2.yaml': in_repo_playbook}
799 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
800 files=file_dict)
801 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
802 self.waitUntilSettled()
803 self.assertEqual(A.reported, 1,
804 "A should report failure")
805 self.assertEqual(A.patchsets[0]['approvals'][0]['value'], "-1")
806 self.assertIn('Job non-existent-job not defined', A.messages[0],
807 "A should have failed the check pipeline")
808 self.assertHistory([])
809
810 def test_dynamic_config_non_existing_job_in_template(self):
811 """Test that requesting a non existent job fails"""
812 in_repo_conf = textwrap.dedent(
813 """
814 - job:
815 name: project-test1
816
817 - project-template:
818 name: test-template
819 check:
820 jobs:
821 - non-existent-job
822
823 - project:
824 name: org/project
825 templates:
826 - test-template
827 """)
828
829 in_repo_playbook = textwrap.dedent(
830 """
831 - hosts: all
832 tasks: []
833 """)
834
835 file_dict = {'.zuul.yaml': in_repo_conf,
836 'playbooks/project-test2.yaml': in_repo_playbook}
837 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
838 files=file_dict)
839 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
840 self.waitUntilSettled()
841 self.assertEqual(A.reported, 1,
842 "A should report failure")
843 self.assertEqual(A.patchsets[0]['approvals'][0]['value'], "-1")
844 self.assertIn('Job non-existent-job not defined', A.messages[0],
845 "A should have failed the check pipeline")
846 self.assertHistory([])
847
Tobias Henkel0f714002017-06-30 23:30:52 +0200848 def test_dynamic_config_new_patchset(self):
849 self.executor_server.hold_jobs_in_build = True
850
851 tenant = self.sched.abide.tenants.get('tenant-one')
852 check_pipeline = tenant.layout.pipelines['check']
853
854 in_repo_conf = textwrap.dedent(
855 """
856 - job:
Tobias Henkelf02cf512017-07-21 22:55:34 +0200857 name: project-test1
James E. Blair2f589fe2017-10-26 12:57:41 -0700858 run: playbooks/project-test1.yaml
Tobias Henkelf02cf512017-07-21 22:55:34 +0200859
860 - job:
Tobias Henkel0f714002017-06-30 23:30:52 +0200861 name: project-test2
James E. Blair2f589fe2017-10-26 12:57:41 -0700862 run: playbooks/project-test2.yaml
Tobias Henkel0f714002017-06-30 23:30:52 +0200863
864 - project:
865 name: org/project
866 check:
867 jobs:
868 - project-test2
869 """)
870
871 in_repo_playbook = textwrap.dedent(
872 """
873 - hosts: all
874 tasks: []
875 """)
876
877 file_dict = {'.zuul.yaml': in_repo_conf,
878 'playbooks/project-test2.yaml': in_repo_playbook}
879 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
880 files=file_dict)
881 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
882 self.waitUntilSettled()
883
884 items = check_pipeline.getAllItems()
885 self.assertEqual(items[0].change.number, '1')
886 self.assertEqual(items[0].change.patchset, '1')
887 self.assertTrue(items[0].live)
888
889 in_repo_conf = textwrap.dedent(
890 """
891 - job:
Tobias Henkel0ce7ec62017-07-21 22:50:17 +0200892 name: project-test1
James E. Blair2f589fe2017-10-26 12:57:41 -0700893 run: playbooks/project-test1.yaml
Tobias Henkel0ce7ec62017-07-21 22:50:17 +0200894
895 - job:
Tobias Henkel0f714002017-06-30 23:30:52 +0200896 name: project-test2
James E. Blair2f589fe2017-10-26 12:57:41 -0700897 run: playbooks/project-test2.yaml
Tobias Henkel0f714002017-06-30 23:30:52 +0200898
899 - project:
900 name: org/project
901 check:
902 jobs:
903 - project-test1
904 - project-test2
905 """)
906 file_dict = {'.zuul.yaml': in_repo_conf,
907 'playbooks/project-test2.yaml': in_repo_playbook}
908
909 A.addPatchset(files=file_dict)
910 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(2))
911
912 self.waitUntilSettled()
913
914 items = check_pipeline.getAllItems()
915 self.assertEqual(items[0].change.number, '1')
916 self.assertEqual(items[0].change.patchset, '2')
917 self.assertTrue(items[0].live)
918
919 self.executor_server.hold_jobs_in_build = False
Tobias Henkel0ce7ec62017-07-21 22:50:17 +0200920 self.executor_server.release('project-test1')
921 self.waitUntilSettled()
Tobias Henkel0f714002017-06-30 23:30:52 +0200922 self.executor_server.release()
923 self.waitUntilSettled()
924
Tobias Henkel0ce7ec62017-07-21 22:50:17 +0200925 self.assertHistory([
926 dict(name='project-test2', result='ABORTED', changes='1,1'),
927 dict(name='project-test1', result='SUCCESS', changes='1,2'),
928 dict(name='project-test2', result='SUCCESS', changes='1,2')])
929
James E. Blairff555742017-02-19 11:34:27 -0800930 def test_in_repo_branch(self):
931 in_repo_conf = textwrap.dedent(
932 """
933 - job:
Tobias Henkelf02cf512017-07-21 22:55:34 +0200934 name: project-test1
935
936 - job:
James E. Blairff555742017-02-19 11:34:27 -0800937 name: project-test2
James E. Blair2f589fe2017-10-26 12:57:41 -0700938 run: playbooks/project-test2.yaml
James E. Blairff555742017-02-19 11:34:27 -0800939
940 - project:
941 name: org/project
942 tenant-one-gate:
943 jobs:
944 - project-test2
945 """)
946
947 in_repo_playbook = textwrap.dedent(
948 """
949 - hosts: all
950 tasks: []
951 """)
952
953 file_dict = {'.zuul.yaml': in_repo_conf,
954 'playbooks/project-test2.yaml': in_repo_playbook}
955 self.create_branch('org/project', 'stable')
James E. Blair72facdc2017-08-17 10:29:12 -0700956 self.fake_gerrit.addEvent(
957 self.fake_gerrit.getFakeBranchCreatedEvent(
958 'org/project', 'stable'))
James E. Blair6069f2b2017-09-26 16:34:11 -0700959 self.waitUntilSettled()
James E. Blairff555742017-02-19 11:34:27 -0800960 A = self.fake_gerrit.addFakeChange('org/project', 'stable', 'A',
961 files=file_dict)
Tobias Henkelbf24fd12017-07-27 06:13:07 +0200962 A.addApproval('Code-Review', 2)
963 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
James E. Blairff555742017-02-19 11:34:27 -0800964 self.waitUntilSettled()
965 self.assertEqual(A.data['status'], 'MERGED')
966 self.assertEqual(A.reported, 2,
967 "A should report start and success")
968 self.assertIn('tenant-one-gate', A.messages[1],
969 "A should transit tenant-one gate")
970 self.assertHistory([
971 dict(name='project-test2', result='SUCCESS', changes='1,1')])
972 self.fake_gerrit.addEvent(A.getChangeMergedEvent())
James E. Blair7bbd7a32017-03-06 11:36:13 -0800973 self.waitUntilSettled()
James E. Blairff555742017-02-19 11:34:27 -0800974
975 # The config change should not affect master.
976 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
Tobias Henkelbf24fd12017-07-27 06:13:07 +0200977 B.addApproval('Code-Review', 2)
978 self.fake_gerrit.addEvent(B.addApproval('Approved', 1))
James E. Blairff555742017-02-19 11:34:27 -0800979 self.waitUntilSettled()
980 self.assertHistory([
981 dict(name='project-test2', result='SUCCESS', changes='1,1'),
982 dict(name='project-test1', result='SUCCESS', changes='2,1')])
983
984 # The config change should be live for further changes on
985 # stable.
986 C = self.fake_gerrit.addFakeChange('org/project', 'stable', 'C')
Tobias Henkelbf24fd12017-07-27 06:13:07 +0200987 C.addApproval('Code-Review', 2)
988 self.fake_gerrit.addEvent(C.addApproval('Approved', 1))
James E. Blairff555742017-02-19 11:34:27 -0800989 self.waitUntilSettled()
990 self.assertHistory([
991 dict(name='project-test2', result='SUCCESS', changes='1,1'),
992 dict(name='project-test1', result='SUCCESS', changes='2,1'),
993 dict(name='project-test2', result='SUCCESS', changes='3,1')])
994
James E. Blaira5a12492017-05-03 11:40:48 -0700995 def test_crd_dynamic_config_branch(self):
996 # Test that we can create a job in one repo and be able to use
997 # it from a different branch on a different repo.
998
999 self.create_branch('org/project1', 'stable')
James E. Blair72facdc2017-08-17 10:29:12 -07001000 self.fake_gerrit.addEvent(
1001 self.fake_gerrit.getFakeBranchCreatedEvent(
1002 'org/project1', 'stable'))
James E. Blaira5a12492017-05-03 11:40:48 -07001003
1004 in_repo_conf = textwrap.dedent(
1005 """
1006 - job:
Tobias Henkelf02cf512017-07-21 22:55:34 +02001007 name: project-test1
1008
1009 - job:
James E. Blaira5a12492017-05-03 11:40:48 -07001010 name: project-test2
James E. Blair2f589fe2017-10-26 12:57:41 -07001011 run: playbooks/project-test2.yaml
James E. Blaira5a12492017-05-03 11:40:48 -07001012
1013 - project:
1014 name: org/project
1015 check:
1016 jobs:
1017 - project-test2
1018 """)
1019
1020 in_repo_playbook = textwrap.dedent(
1021 """
1022 - hosts: all
1023 tasks: []
1024 """)
1025
1026 file_dict = {'.zuul.yaml': in_repo_conf,
1027 'playbooks/project-test2.yaml': in_repo_playbook}
1028 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
1029 files=file_dict)
1030
1031 second_repo_conf = textwrap.dedent(
1032 """
1033 - project:
1034 name: org/project1
1035 check:
1036 jobs:
1037 - project-test2
1038 """)
1039
1040 second_file_dict = {'.zuul.yaml': second_repo_conf}
1041 B = self.fake_gerrit.addFakeChange('org/project1', 'stable', 'B',
1042 files=second_file_dict)
1043 B.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
1044 B.subject, A.data['id'])
1045
1046 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
1047 self.waitUntilSettled()
1048 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
1049 self.waitUntilSettled()
1050
1051 self.assertEqual(A.reported, 1, "A should report")
1052 self.assertHistory([
1053 dict(name='project-test2', result='SUCCESS', changes='1,1'),
1054 dict(name='project-test2', result='SUCCESS', changes='1,1 2,1'),
1055 ])
1056
James E. Blair97043882017-09-06 15:51:17 -07001057 def test_yaml_list_error(self):
1058 in_repo_conf = textwrap.dedent(
1059 """
1060 job: foo
1061 """)
1062
1063 file_dict = {'.zuul.yaml': in_repo_conf}
1064 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
1065 files=file_dict)
1066 A.addApproval('Code-Review', 2)
1067 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
1068 self.waitUntilSettled()
1069
1070 self.assertEqual(A.data['status'], 'NEW')
1071 self.assertEqual(A.reported, 1,
1072 "A should report failure")
1073 self.assertIn('not a list', A.messages[0],
1074 "A should have a syntax error reported")
1075
1076 def test_yaml_dict_error(self):
1077 in_repo_conf = textwrap.dedent(
1078 """
1079 - job
1080 """)
1081
1082 file_dict = {'.zuul.yaml': in_repo_conf}
1083 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
1084 files=file_dict)
1085 A.addApproval('Code-Review', 2)
1086 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
1087 self.waitUntilSettled()
1088
1089 self.assertEqual(A.data['status'], 'NEW')
1090 self.assertEqual(A.reported, 1,
1091 "A should report failure")
1092 self.assertIn('not a dictionary', A.messages[0],
1093 "A should have a syntax error reported")
1094
James E. Blairec953e12017-12-11 11:56:18 -08001095 def test_yaml_duplicate_key_error(self):
1096 in_repo_conf = textwrap.dedent(
1097 """
1098 - job:
1099 name: foo
1100 name: bar
1101 """)
1102
1103 file_dict = {'.zuul.yaml': in_repo_conf}
1104 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
1105 files=file_dict)
1106 A.addApproval('Code-Review', 2)
1107 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
1108 self.waitUntilSettled()
1109
1110 self.assertEqual(A.data['status'], 'NEW')
1111 self.assertEqual(A.reported, 1,
1112 "A should report failure")
1113 self.assertIn('appears more than once', A.messages[0],
1114 "A should have a syntax error reported")
1115
James E. Blair97043882017-09-06 15:51:17 -07001116 def test_yaml_key_error(self):
1117 in_repo_conf = textwrap.dedent(
1118 """
1119 - job:
1120 name: project-test2
1121 """)
1122
1123 file_dict = {'.zuul.yaml': in_repo_conf}
1124 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
1125 files=file_dict)
1126 A.addApproval('Code-Review', 2)
1127 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
1128 self.waitUntilSettled()
1129
1130 self.assertEqual(A.data['status'], 'NEW')
1131 self.assertEqual(A.reported, 1,
1132 "A should report failure")
1133 self.assertIn('has more than one key', A.messages[0],
1134 "A should have a syntax error reported")
1135
1136 def test_yaml_unknown_error(self):
1137 in_repo_conf = textwrap.dedent(
1138 """
1139 - foobar:
1140 foo: bar
1141 """)
1142
1143 file_dict = {'.zuul.yaml': in_repo_conf}
1144 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
1145 files=file_dict)
1146 A.addApproval('Code-Review', 2)
1147 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
1148 self.waitUntilSettled()
1149
1150 self.assertEqual(A.data['status'], 'NEW')
1151 self.assertEqual(A.reported, 1,
1152 "A should report failure")
1153 self.assertIn('not recognized', A.messages[0],
1154 "A should have a syntax error reported")
1155
James E. Blair149b69c2017-03-02 10:48:16 -08001156 def test_untrusted_syntax_error(self):
James E. Blaire53250c2017-03-01 14:34:36 -08001157 in_repo_conf = textwrap.dedent(
1158 """
1159 - job:
1160 name: project-test2
1161 foo: error
1162 """)
1163
1164 file_dict = {'.zuul.yaml': in_repo_conf}
1165 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
1166 files=file_dict)
Tobias Henkelbf24fd12017-07-27 06:13:07 +02001167 A.addApproval('Code-Review', 2)
1168 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
James E. Blaire53250c2017-03-01 14:34:36 -08001169 self.waitUntilSettled()
1170
1171 self.assertEqual(A.data['status'], 'NEW')
Tobias Henkel9842bd72017-05-16 13:40:03 +02001172 self.assertEqual(A.reported, 1,
1173 "A should report failure")
1174 self.assertIn('syntax error', A.messages[0],
James E. Blaire53250c2017-03-01 14:34:36 -08001175 "A should have a syntax error reported")
1176
James E. Blair149b69c2017-03-02 10:48:16 -08001177 def test_trusted_syntax_error(self):
1178 in_repo_conf = textwrap.dedent(
1179 """
1180 - job:
1181 name: project-test2
1182 foo: error
1183 """)
1184
1185 file_dict = {'zuul.yaml': in_repo_conf}
1186 A = self.fake_gerrit.addFakeChange('common-config', 'master', 'A',
1187 files=file_dict)
Tobias Henkelbf24fd12017-07-27 06:13:07 +02001188 A.addApproval('Code-Review', 2)
1189 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
James E. Blair149b69c2017-03-02 10:48:16 -08001190 self.waitUntilSettled()
1191
1192 self.assertEqual(A.data['status'], 'NEW')
Tobias Henkel9842bd72017-05-16 13:40:03 +02001193 self.assertEqual(A.reported, 1,
1194 "A should report failure")
1195 self.assertIn('syntax error', A.messages[0],
James E. Blair149b69c2017-03-02 10:48:16 -08001196 "A should have a syntax error reported")
1197
James E. Blair6f140c72017-03-03 10:32:07 -08001198 def test_untrusted_yaml_error(self):
1199 in_repo_conf = textwrap.dedent(
1200 """
1201 - job:
1202 foo: error
1203 """)
1204
1205 file_dict = {'.zuul.yaml': in_repo_conf}
1206 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
1207 files=file_dict)
Tobias Henkelbf24fd12017-07-27 06:13:07 +02001208 A.addApproval('Code-Review', 2)
1209 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
James E. Blair6f140c72017-03-03 10:32:07 -08001210 self.waitUntilSettled()
1211
1212 self.assertEqual(A.data['status'], 'NEW')
Tobias Henkel9842bd72017-05-16 13:40:03 +02001213 self.assertEqual(A.reported, 1,
1214 "A should report failure")
1215 self.assertIn('syntax error', A.messages[0],
James E. Blair6f140c72017-03-03 10:32:07 -08001216 "A should have a syntax error reported")
1217
James E. Blairdb04e6a2017-05-03 14:49:36 -07001218 def test_untrusted_shadow_error(self):
1219 in_repo_conf = textwrap.dedent(
1220 """
1221 - job:
1222 name: common-config-test
1223 """)
1224
1225 file_dict = {'.zuul.yaml': in_repo_conf}
1226 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
1227 files=file_dict)
Tobias Henkelbf24fd12017-07-27 06:13:07 +02001228 A.addApproval('Code-Review', 2)
1229 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
James E. Blairdb04e6a2017-05-03 14:49:36 -07001230 self.waitUntilSettled()
1231
1232 self.assertEqual(A.data['status'], 'NEW')
Tobias Henkel9842bd72017-05-16 13:40:03 +02001233 self.assertEqual(A.reported, 1,
1234 "A should report failure")
1235 self.assertIn('not permitted to shadow', A.messages[0],
James E. Blairdb04e6a2017-05-03 14:49:36 -07001236 "A should have a syntax error reported")
1237
James E. Blaird5656ad2017-06-02 14:29:41 -07001238 def test_untrusted_pipeline_error(self):
1239 in_repo_conf = textwrap.dedent(
1240 """
1241 - pipeline:
1242 name: test
1243 """)
1244
1245 file_dict = {'.zuul.yaml': in_repo_conf}
1246 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
1247 files=file_dict)
Tobias Henkelbf24fd12017-07-27 06:13:07 +02001248 A.addApproval('Code-Review', 2)
1249 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
James E. Blaird5656ad2017-06-02 14:29:41 -07001250 self.waitUntilSettled()
1251
1252 self.assertEqual(A.data['status'], 'NEW')
1253 self.assertEqual(A.reported, 1,
1254 "A should report failure")
1255 self.assertIn('Pipelines may not be defined', A.messages[0],
1256 "A should have a syntax error reported")
1257
1258 def test_untrusted_project_error(self):
1259 in_repo_conf = textwrap.dedent(
1260 """
1261 - project:
1262 name: org/project1
1263 """)
1264
1265 file_dict = {'.zuul.yaml': in_repo_conf}
1266 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
1267 files=file_dict)
Tobias Henkelbf24fd12017-07-27 06:13:07 +02001268 A.addApproval('Code-Review', 2)
1269 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
James E. Blaird5656ad2017-06-02 14:29:41 -07001270 self.waitUntilSettled()
1271
1272 self.assertEqual(A.data['status'], 'NEW')
1273 self.assertEqual(A.reported, 1,
1274 "A should report failure")
1275 self.assertIn('the only project definition permitted', A.messages[0],
1276 "A should have a syntax error reported")
1277
James E. Blairf03173b2017-10-10 10:46:43 -07001278 def test_untrusted_depends_on_trusted(self):
1279 with open(os.path.join(FIXTURE_DIR,
1280 'config/in-repo/git/',
1281 'common-config/zuul.yaml')) as f:
1282 common_config = f.read()
1283
1284 common_config += textwrap.dedent(
1285 """
1286 - job:
1287 name: project-test9
1288 """)
1289
1290 file_dict = {'zuul.yaml': common_config}
1291 A = self.fake_gerrit.addFakeChange('common-config', 'master', 'A',
1292 files=file_dict)
1293 in_repo_conf = textwrap.dedent(
1294 """
1295 - job:
1296 name: project-test1
1297 - project:
1298 name: org/project
1299 check:
1300 jobs:
1301 - project-test9
1302 """)
1303
1304 file_dict = {'zuul.yaml': in_repo_conf}
1305 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B',
1306 files=file_dict)
1307 B.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
1308 B.subject, A.data['id'])
1309 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
1310 self.waitUntilSettled()
1311
1312 self.assertEqual(B.data['status'], 'NEW')
1313 self.assertEqual(B.reported, 1,
1314 "B should report failure")
1315 self.assertIn('depends on a change to a config project',
1316 B.messages[0],
1317 "A should have a syntax error reported")
1318
James E. Blaire64b0e42017-06-08 11:23:34 -07001319 def test_duplicate_node_error(self):
1320 in_repo_conf = textwrap.dedent(
1321 """
1322 - nodeset:
1323 name: duplicate
1324 nodes:
1325 - name: compute
James E. Blair16d96a02017-06-08 11:32:56 -07001326 label: foo
James E. Blaire64b0e42017-06-08 11:23:34 -07001327 - name: compute
James E. Blair16d96a02017-06-08 11:32:56 -07001328 label: foo
James E. Blaire64b0e42017-06-08 11:23:34 -07001329 """)
1330
1331 file_dict = {'.zuul.yaml': in_repo_conf}
1332 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
1333 files=file_dict)
Tobias Henkelbf24fd12017-07-27 06:13:07 +02001334 A.addApproval('Code-Review', 2)
1335 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
James E. Blaire64b0e42017-06-08 11:23:34 -07001336 self.waitUntilSettled()
1337
1338 self.assertEqual(A.data['status'], 'NEW')
1339 self.assertEqual(A.reported, 1,
1340 "A should report failure")
1341 self.assertIn('appears multiple times', A.messages[0],
1342 "A should have a syntax error reported")
1343
1344 def test_duplicate_group_error(self):
1345 in_repo_conf = textwrap.dedent(
1346 """
1347 - nodeset:
1348 name: duplicate
1349 nodes:
1350 - name: compute
James E. Blair16d96a02017-06-08 11:32:56 -07001351 label: foo
James E. Blaire64b0e42017-06-08 11:23:34 -07001352 groups:
1353 - name: group
1354 nodes: compute
1355 - name: group
1356 nodes: compute
1357 """)
1358
1359 file_dict = {'.zuul.yaml': in_repo_conf}
1360 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
1361 files=file_dict)
Tobias Henkelbf24fd12017-07-27 06:13:07 +02001362 A.addApproval('Code-Review', 2)
1363 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
James E. Blaire64b0e42017-06-08 11:23:34 -07001364 self.waitUntilSettled()
1365
1366 self.assertEqual(A.data['status'], 'NEW')
1367 self.assertEqual(A.reported, 1,
1368 "A should report failure")
1369 self.assertIn('appears multiple times', A.messages[0],
1370 "A should have a syntax error reported")
1371
James E. Blair4ae399f2017-09-20 17:15:09 -07001372 def test_secret_not_found_error(self):
1373 in_repo_conf = textwrap.dedent(
1374 """
1375 - job:
1376 name: test
1377 secrets: does-not-exist
1378 """)
1379
1380 file_dict = {'.zuul.yaml': in_repo_conf}
1381 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
1382 files=file_dict)
1383 A.addApproval('Code-Review', 2)
1384 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
1385 self.waitUntilSettled()
1386
1387 self.assertEqual(A.data['status'], 'NEW')
1388 self.assertEqual(A.reported, 1,
1389 "A should report failure")
1390 self.assertIn('secret "does-not-exist" was not found', A.messages[0],
1391 "A should have a syntax error reported")
1392
1393 def test_nodeset_not_found_error(self):
1394 in_repo_conf = textwrap.dedent(
1395 """
1396 - job:
1397 name: test
1398 nodeset: does-not-exist
1399 """)
1400
1401 file_dict = {'.zuul.yaml': in_repo_conf}
1402 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
1403 files=file_dict)
1404 A.addApproval('Code-Review', 2)
1405 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
1406 self.waitUntilSettled()
1407
1408 self.assertEqual(A.data['status'], 'NEW')
1409 self.assertEqual(A.reported, 1,
1410 "A should report failure")
1411 self.assertIn('nodeset "does-not-exist" was not found', A.messages[0],
1412 "A should have a syntax error reported")
1413
James E. Blair89e25eb2017-09-26 09:11:31 -07001414 def test_template_not_found_error(self):
1415 in_repo_conf = textwrap.dedent(
1416 """
1417 - job:
1418 name: project-test1
1419 - project:
1420 name: org/project
1421 templates:
1422 - does-not-exist
1423 """)
1424
1425 file_dict = {'.zuul.yaml': in_repo_conf}
1426 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
1427 files=file_dict)
1428 A.addApproval('Code-Review', 2)
1429 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
1430 self.waitUntilSettled()
1431
1432 self.assertEqual(A.data['status'], 'NEW')
1433 self.assertEqual(A.reported, 1,
1434 "A should report failure")
1435 self.assertIn('project template "does-not-exist" was not found',
1436 A.messages[0],
1437 "A should have a syntax error reported")
1438
Monty Taylor8be3c0c2017-10-06 10:37:37 -05001439 def test_job_list_in_project_template_not_dict_error(self):
1440 in_repo_conf = textwrap.dedent(
1441 """
1442 - job:
1443 name: project-test1
1444 - project-template:
1445 name: some-jobs
1446 check:
1447 jobs:
1448 - project-test1:
1449 - required-projects:
1450 org/project2
1451 """)
1452
1453 file_dict = {'.zuul.yaml': in_repo_conf}
1454 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
1455 files=file_dict)
1456 A.addApproval('Code-Review', 2)
1457 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
1458 self.waitUntilSettled()
1459
1460 self.assertEqual(A.data['status'], 'NEW')
1461 self.assertEqual(A.reported, 1,
1462 "A should report failure")
1463 self.assertIn('expected str for dictionary value',
1464 A.messages[0], "A should have a syntax error reported")
1465
1466 def test_job_list_in_project_not_dict_error(self):
1467 in_repo_conf = textwrap.dedent(
1468 """
1469 - job:
1470 name: project-test1
1471 - project:
1472 name: org/project1
1473 check:
1474 jobs:
1475 - project-test1:
1476 - required-projects:
1477 org/project2
1478 """)
1479
1480 file_dict = {'.zuul.yaml': in_repo_conf}
1481 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
1482 files=file_dict)
1483 A.addApproval('Code-Review', 2)
1484 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
1485 self.waitUntilSettled()
1486
1487 self.assertEqual(A.data['status'], 'NEW')
1488 self.assertEqual(A.reported, 1,
1489 "A should report failure")
1490 self.assertIn('expected str for dictionary value',
1491 A.messages[0], "A should have a syntax error reported")
1492
James E. Blair1235f142017-10-07 09:11:43 -07001493 def test_project_template(self):
1494 # Tests that a project template is not modified when used, and
1495 # can therefore be used in subsequent reconfigurations.
1496 in_repo_conf = textwrap.dedent(
1497 """
1498 - job:
1499 name: project-test1
James E. Blair2f589fe2017-10-26 12:57:41 -07001500 run: playbooks/project-test1.yaml
James E. Blair1235f142017-10-07 09:11:43 -07001501 - project-template:
1502 name: some-jobs
1503 tenant-one-gate:
1504 jobs:
1505 - project-test1:
1506 required-projects:
1507 - org/project1
1508 - project:
1509 name: org/project
1510 templates:
1511 - some-jobs
1512 """)
1513
1514 file_dict = {'.zuul.yaml': in_repo_conf}
1515 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
1516 files=file_dict)
1517 A.addApproval('Code-Review', 2)
1518 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
1519 self.waitUntilSettled()
1520 self.assertEqual(A.data['status'], 'MERGED')
1521 self.fake_gerrit.addEvent(A.getChangeMergedEvent())
1522 self.waitUntilSettled()
1523 in_repo_conf = textwrap.dedent(
1524 """
1525 - project:
1526 name: org/project1
1527 templates:
1528 - some-jobs
1529 """)
1530 file_dict = {'.zuul.yaml': in_repo_conf}
1531 B = self.fake_gerrit.addFakeChange('org/project1', 'master', 'B',
1532 files=file_dict)
1533 B.addApproval('Code-Review', 2)
1534 self.fake_gerrit.addEvent(B.addApproval('Approved', 1))
1535 self.waitUntilSettled()
1536 self.assertEqual(B.data['status'], 'MERGED')
1537
James E. Blairbccdfcf2017-10-07 13:37:26 -07001538 def test_job_remove_add(self):
1539 # Tests that a job can be removed from one repo and added in another.
1540 # First, remove the current config for project1 since it
1541 # references the job we want to remove.
1542 file_dict = {'.zuul.yaml': None}
1543 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A',
1544 files=file_dict)
1545 A.setMerged()
1546 self.fake_gerrit.addEvent(A.getChangeMergedEvent())
1547 self.waitUntilSettled()
1548 # Then propose a change to delete the job from one repo...
1549 file_dict = {'.zuul.yaml': None}
1550 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B',
1551 files=file_dict)
1552 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
1553 self.waitUntilSettled()
1554 # ...and a second that depends on it that adds it to another repo.
1555 in_repo_conf = textwrap.dedent(
1556 """
1557 - job:
1558 name: project-test1
James E. Blair2f589fe2017-10-26 12:57:41 -07001559 run: playbooks/project-test1.yaml
James E. Blairbccdfcf2017-10-07 13:37:26 -07001560
1561 - project:
1562 name: org/project1
1563 check:
1564 jobs:
1565 - project-test1
1566 """)
1567 in_repo_playbook = textwrap.dedent(
1568 """
1569 - hosts: all
1570 tasks: []
1571 """)
1572 file_dict = {'.zuul.yaml': in_repo_conf,
1573 'playbooks/project-test1.yaml': in_repo_playbook}
1574 C = self.fake_gerrit.addFakeChange('org/project1', 'master', 'C',
1575 files=file_dict,
1576 parent='refs/changes/1/1/1')
1577 C.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
1578 C.subject, B.data['id'])
1579 self.fake_gerrit.addEvent(C.getPatchsetCreatedEvent(1))
1580 self.waitUntilSettled()
1581 self.assertHistory([
1582 dict(name='project-test1', result='SUCCESS', changes='2,1 3,1'),
1583 ], ordered=False)
1584
James E. Blair09f9ffe2017-07-11 15:30:25 -07001585 def test_multi_repo(self):
1586 downstream_repo_conf = textwrap.dedent(
1587 """
1588 - project:
1589 name: org/project1
1590 tenant-one-gate:
1591 jobs:
1592 - project-test1
1593
1594 - job:
1595 name: project1-test1
1596 parent: project-test1
1597 """)
1598
1599 file_dict = {'.zuul.yaml': downstream_repo_conf}
1600 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A',
1601 files=file_dict)
Tobias Henkelbf24fd12017-07-27 06:13:07 +02001602 A.addApproval('Code-Review', 2)
1603 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
James E. Blair09f9ffe2017-07-11 15:30:25 -07001604 self.waitUntilSettled()
1605
1606 self.assertEqual(A.data['status'], 'MERGED')
1607 self.fake_gerrit.addEvent(A.getChangeMergedEvent())
1608 self.waitUntilSettled()
1609
1610 upstream_repo_conf = textwrap.dedent(
1611 """
1612 - job:
1613 name: project-test1
James E. Blair2f589fe2017-10-26 12:57:41 -07001614 run: playbooks/project-test1.yaml
James E. Blair09f9ffe2017-07-11 15:30:25 -07001615
1616 - job:
1617 name: project-test2
1618
1619 - project:
1620 name: org/project
1621 tenant-one-gate:
1622 jobs:
1623 - project-test1
1624 """)
1625
1626 file_dict = {'.zuul.yaml': upstream_repo_conf}
1627 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B',
1628 files=file_dict)
Tobias Henkelbf24fd12017-07-27 06:13:07 +02001629 B.addApproval('Code-Review', 2)
1630 self.fake_gerrit.addEvent(B.addApproval('Approved', 1))
James E. Blair09f9ffe2017-07-11 15:30:25 -07001631 self.waitUntilSettled()
1632
1633 self.assertEqual(B.data['status'], 'MERGED')
1634 self.fake_gerrit.addEvent(B.getChangeMergedEvent())
1635 self.waitUntilSettled()
1636
1637 tenant = self.sched.abide.tenants.get('tenant-one')
1638 # Ensure the latest change is reflected in the config; if it
1639 # isn't this will raise an exception.
1640 tenant.layout.getJob('project-test2')
1641
James E. Blair332636e2017-09-05 10:14:35 -07001642 def test_pipeline_error(self):
1643 with open(os.path.join(FIXTURE_DIR,
1644 'config/in-repo/git/',
1645 'common-config/zuul.yaml')) as f:
1646 base_common_config = f.read()
1647
1648 in_repo_conf_A = textwrap.dedent(
1649 """
1650 - pipeline:
1651 name: periodic
1652 foo: error
1653 """)
1654
1655 file_dict = {'zuul.yaml': None,
1656 'zuul.d/main.yaml': base_common_config,
1657 'zuul.d/test1.yaml': in_repo_conf_A}
1658 A = self.fake_gerrit.addFakeChange('common-config', 'master', 'A',
1659 files=file_dict)
1660 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
1661 self.waitUntilSettled()
1662 self.assertEqual(A.reported, 1,
1663 "A should report failure")
1664 self.assertIn('syntax error',
1665 A.messages[0],
1666 "A should have an error reported")
1667
1668 def test_change_series_error(self):
1669 with open(os.path.join(FIXTURE_DIR,
1670 'config/in-repo/git/',
1671 'common-config/zuul.yaml')) as f:
1672 base_common_config = f.read()
1673
1674 in_repo_conf_A = textwrap.dedent(
1675 """
1676 - pipeline:
1677 name: periodic
1678 foo: error
1679 """)
1680
1681 file_dict = {'zuul.yaml': None,
1682 'zuul.d/main.yaml': base_common_config,
1683 'zuul.d/test1.yaml': in_repo_conf_A}
1684 A = self.fake_gerrit.addFakeChange('common-config', 'master', 'A',
1685 files=file_dict)
1686
1687 in_repo_conf_B = textwrap.dedent(
1688 """
1689 - job:
1690 name: project-test2
1691 foo: error
1692 """)
1693
1694 file_dict = {'zuul.yaml': None,
1695 'zuul.d/main.yaml': base_common_config,
1696 'zuul.d/test1.yaml': in_repo_conf_A,
1697 'zuul.d/test2.yaml': in_repo_conf_B}
1698 B = self.fake_gerrit.addFakeChange('common-config', 'master', 'B',
1699 files=file_dict)
1700 B.setDependsOn(A, 1)
1701 C = self.fake_gerrit.addFakeChange('common-config', 'master', 'C')
1702 C.setDependsOn(B, 1)
1703 self.fake_gerrit.addEvent(C.getPatchsetCreatedEvent(1))
1704 self.waitUntilSettled()
1705
1706 self.assertEqual(C.reported, 1,
1707 "C should report failure")
1708 self.assertIn('depends on a change that failed to merge',
1709 C.messages[0],
1710 "C should have an error reported")
1711
James E. Blair1ef8f7c2017-12-13 17:18:34 -08001712 def test_pipeline_debug(self):
1713 in_repo_conf = textwrap.dedent(
1714 """
1715 - job:
1716 name: project-test1
1717 run: playbooks/project-test1.yaml
1718 - project:
1719 name: org/project
1720 check:
1721 debug: True
1722 jobs:
1723 - project-test1
1724 """)
1725
1726 file_dict = {'.zuul.yaml': in_repo_conf}
1727 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
1728 files=file_dict)
1729 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
1730 self.waitUntilSettled()
1731
1732 self.assertEqual(A.data['status'], 'NEW')
1733 self.assertEqual(A.reported, 1,
1734 "A should report success")
1735 self.assertIn('Debug information:',
1736 A.messages[0], "A should have debug info")
1737
James E. Blairc73c73a2017-01-20 15:15:15 -08001738
James E. Blairc9455002017-09-06 09:22:19 -07001739class TestInRepoJoin(ZuulTestCase):
1740 # In this config, org/project is not a member of any pipelines, so
1741 # that we may test the changes that cause it to join them.
1742
1743 tenant_config_file = 'config/in-repo-join/main.yaml'
1744
1745 def test_dynamic_dependent_pipeline(self):
1746 # Test dynamically adding a project to a
1747 # dependent pipeline for the first time
1748 self.executor_server.hold_jobs_in_build = True
1749
1750 tenant = self.sched.abide.tenants.get('tenant-one')
1751 gate_pipeline = tenant.layout.pipelines['gate']
1752
1753 in_repo_conf = textwrap.dedent(
1754 """
1755 - job:
1756 name: project-test1
James E. Blair2f589fe2017-10-26 12:57:41 -07001757 run: playbooks/project-test1.yaml
James E. Blairc9455002017-09-06 09:22:19 -07001758
1759 - job:
1760 name: project-test2
James E. Blair2f589fe2017-10-26 12:57:41 -07001761 run: playbooks/project-test2.yaml
James E. Blairc9455002017-09-06 09:22:19 -07001762
1763 - project:
1764 name: org/project
1765 gate:
1766 jobs:
1767 - project-test2
1768 """)
1769
1770 in_repo_playbook = textwrap.dedent(
1771 """
1772 - hosts: all
1773 tasks: []
1774 """)
1775
1776 file_dict = {'.zuul.yaml': in_repo_conf,
1777 'playbooks/project-test2.yaml': in_repo_playbook}
1778 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
1779 files=file_dict)
1780 A.addApproval('Code-Review', 2)
1781 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
1782 self.waitUntilSettled()
1783
1784 items = gate_pipeline.getAllItems()
1785 self.assertEqual(items[0].change.number, '1')
1786 self.assertEqual(items[0].change.patchset, '1')
1787 self.assertTrue(items[0].live)
1788
1789 self.executor_server.hold_jobs_in_build = False
1790 self.executor_server.release()
1791 self.waitUntilSettled()
1792
1793 # Make sure the dynamic queue got cleaned up
1794 self.assertEqual(gate_pipeline.queues, [])
1795
1796 def test_dynamic_dependent_pipeline_failure(self):
1797 # Test that a change behind a failing change adding a project
1798 # to a dependent pipeline is dequeued.
1799 self.executor_server.hold_jobs_in_build = True
1800
1801 in_repo_conf = textwrap.dedent(
1802 """
1803 - job:
1804 name: project-test1
James E. Blair2f589fe2017-10-26 12:57:41 -07001805 run: playbooks/project-test1.yaml
James E. Blairc9455002017-09-06 09:22:19 -07001806
1807 - project:
1808 name: org/project
1809 gate:
1810 jobs:
1811 - project-test1
1812 """)
1813
1814 file_dict = {'.zuul.yaml': in_repo_conf}
1815 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
1816 files=file_dict)
1817 self.executor_server.failJob('project-test1', A)
1818 A.addApproval('Code-Review', 2)
1819 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
1820 self.waitUntilSettled()
1821
1822 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
1823 B.addApproval('Code-Review', 2)
1824 self.fake_gerrit.addEvent(B.addApproval('Approved', 1))
1825 self.waitUntilSettled()
1826
James E. Blair3490c5d2017-09-07 08:33:23 -07001827 self.orderedRelease()
James E. Blairc9455002017-09-06 09:22:19 -07001828 self.waitUntilSettled()
1829 self.assertEqual(A.reported, 2,
1830 "A should report start and failure")
1831 self.assertEqual(A.data['status'], 'NEW')
1832 self.assertEqual(B.reported, 1,
1833 "B should report start")
1834 self.assertHistory([
1835 dict(name='project-test1', result='FAILURE', changes='1,1'),
James E. Blair3490c5d2017-09-07 08:33:23 -07001836 dict(name='project-test1', result='ABORTED', changes='1,1 2,1'),
James E. Blairc9455002017-09-06 09:22:19 -07001837 ], ordered=False)
1838
James E. Blair0af198f2017-09-06 09:52:35 -07001839 def test_dynamic_dependent_pipeline_absent(self):
1840 # Test that a series of dependent changes don't report merge
1841 # failures to a pipeline they aren't in.
1842 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1843 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
1844 B.setDependsOn(A, 1)
1845
1846 A.addApproval('Code-Review', 2)
1847 A.addApproval('Approved', 1)
1848 B.addApproval('Code-Review', 2)
1849 self.fake_gerrit.addEvent(B.addApproval('Approved', 1))
1850 self.waitUntilSettled()
1851 self.assertEqual(A.reported, 0,
1852 "A should not report")
1853 self.assertEqual(A.data['status'], 'NEW')
1854 self.assertEqual(B.reported, 0,
1855 "B should not report")
1856 self.assertEqual(B.data['status'], 'NEW')
1857 self.assertHistory([])
1858
James E. Blairc9455002017-09-06 09:22:19 -07001859
James E. Blairc73c73a2017-01-20 15:15:15 -08001860class TestAnsible(AnsibleZuulTestCase):
1861 # A temporary class to hold new tests while others are disabled
1862
1863 tenant_config_file = 'config/ansible/main.yaml'
1864
1865 def test_playbook(self):
Jamie Lennox7655b552017-03-17 12:33:38 +11001866 # Keep the jobdir around so we can inspect contents if an
1867 # assert fails.
1868 self.executor_server.keep_jobdir = True
1869 # Output extra ansible info so we might see errors.
1870 self.executor_server.verbose = True
1871 # Add a site variables file, used by check-vars
1872 path = os.path.join(FIXTURE_DIR, 'config', 'ansible',
1873 'variables.yaml')
1874 self.config.set('executor', 'variables', path)
James E. Blairc73c73a2017-01-20 15:15:15 -08001875 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1876 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
1877 self.waitUntilSettled()
Tobias Henkel077f2f32017-05-30 20:16:46 +02001878 build_timeout = self.getJobFromHistory('timeout')
Jamie Lennox7655b552017-03-17 12:33:38 +11001879 with self.jobLog(build_timeout):
1880 self.assertEqual(build_timeout.result, 'TIMED_OUT')
Tobias Henkel077f2f32017-05-30 20:16:46 +02001881 build_faillocal = self.getJobFromHistory('faillocal')
Jamie Lennox7655b552017-03-17 12:33:38 +11001882 with self.jobLog(build_faillocal):
1883 self.assertEqual(build_faillocal.result, 'FAILURE')
Tobias Henkel077f2f32017-05-30 20:16:46 +02001884 build_failpost = self.getJobFromHistory('failpost')
Jamie Lennox7655b552017-03-17 12:33:38 +11001885 with self.jobLog(build_failpost):
1886 self.assertEqual(build_failpost.result, 'POST_FAILURE')
Tobias Henkel077f2f32017-05-30 20:16:46 +02001887 build_check_vars = self.getJobFromHistory('check-vars')
Jamie Lennox7655b552017-03-17 12:33:38 +11001888 with self.jobLog(build_check_vars):
1889 self.assertEqual(build_check_vars.result, 'SUCCESS')
Monty Tayloraff8b402017-08-16 18:40:41 -05001890 build_check_secret_names = self.getJobFromHistory('check-secret-names')
1891 with self.jobLog(build_check_secret_names):
1892 self.assertEqual(build_check_secret_names.result, 'SUCCESS')
Tobias Henkel077f2f32017-05-30 20:16:46 +02001893 build_hello = self.getJobFromHistory('hello-world')
Jamie Lennox7655b552017-03-17 12:33:38 +11001894 with self.jobLog(build_hello):
1895 self.assertEqual(build_hello.result, 'SUCCESS')
Tobias Henkel077f2f32017-05-30 20:16:46 +02001896 build_python27 = self.getJobFromHistory('python27')
Jamie Lennox7655b552017-03-17 12:33:38 +11001897 with self.jobLog(build_python27):
1898 self.assertEqual(build_python27.result, 'SUCCESS')
1899 flag_path = os.path.join(self.test_root,
1900 build_python27.uuid + '.flag')
1901 self.assertTrue(os.path.exists(flag_path))
1902 copied_path = os.path.join(self.test_root, build_python27.uuid +
1903 '.copied')
1904 self.assertTrue(os.path.exists(copied_path))
1905 failed_path = os.path.join(self.test_root, build_python27.uuid +
1906 '.failed')
1907 self.assertFalse(os.path.exists(failed_path))
1908 pre_flag_path = os.path.join(self.test_root, build_python27.uuid +
1909 '.pre.flag')
1910 self.assertTrue(os.path.exists(pre_flag_path))
1911 post_flag_path = os.path.join(self.test_root, build_python27.uuid +
1912 '.post.flag')
1913 self.assertTrue(os.path.exists(post_flag_path))
1914 bare_role_flag_path = os.path.join(self.test_root,
1915 build_python27.uuid +
1916 '.bare-role.flag')
1917 self.assertTrue(os.path.exists(bare_role_flag_path))
1918 secrets_path = os.path.join(self.test_root,
1919 build_python27.uuid + '.secrets')
1920 with open(secrets_path) as f:
1921 self.assertEqual(f.read(), "test-username test-password")
James E. Blairb9c0d772017-03-03 14:34:49 -08001922
Jamie Lennox7655b552017-03-17 12:33:38 +11001923 msg = A.messages[0]
1924 success = "{} https://success.example.com/zuul-logs/{}"
1925 fail = "{} https://failure.example.com/zuul-logs/{}"
1926 self.assertIn(success.format("python27", build_python27.uuid), msg)
1927 self.assertIn(fail.format("faillocal", build_faillocal.uuid), msg)
1928 self.assertIn(success.format("check-vars",
1929 build_check_vars.uuid), msg)
1930 self.assertIn(success.format("hello-world", build_hello.uuid), msg)
1931 self.assertIn(fail.format("timeout", build_timeout.uuid), msg)
1932 self.assertIn(fail.format("failpost", build_failpost.uuid), msg)
Tobias Henkel077f2f32017-05-30 20:16:46 +02001933
James E. Blairabbaa6f2017-04-06 16:11:44 -07001934 def _add_job(self, job_name):
1935 conf = textwrap.dedent(
1936 """
1937 - job:
1938 name: %s
James E. Blair2f589fe2017-10-26 12:57:41 -07001939 run: playbooks/%s.yaml
James E. Blairabbaa6f2017-04-06 16:11:44 -07001940
1941 - project:
1942 name: org/plugin-project
1943 check:
1944 jobs:
1945 - %s
James E. Blair2f589fe2017-10-26 12:57:41 -07001946 """ % (job_name, job_name, job_name))
James E. Blairabbaa6f2017-04-06 16:11:44 -07001947
1948 file_dict = {'.zuul.yaml': conf}
1949 A = self.fake_gerrit.addFakeChange('org/plugin-project', 'master', 'A',
1950 files=file_dict)
1951 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
1952 self.waitUntilSettled()
1953
1954 def test_plugins(self):
1955 # Keep the jobdir around so we can inspect contents if an
1956 # assert fails.
1957 self.executor_server.keep_jobdir = True
1958 # Output extra ansible info so we might see errors.
1959 self.executor_server.verbose = True
1960
1961 count = 0
1962 plugin_tests = [
1963 ('passwd', 'FAILURE'),
1964 ('cartesian', 'SUCCESS'),
1965 ('consul_kv', 'FAILURE'),
1966 ('credstash', 'FAILURE'),
1967 ('csvfile_good', 'SUCCESS'),
1968 ('csvfile_bad', 'FAILURE'),
Monty Taylor93ad2212017-08-02 14:59:50 -05001969 ('uri_bad_path', 'FAILURE'),
1970 ('uri_bad_scheme', 'FAILURE'),
Monty Taylor788a40e2017-08-02 16:14:05 -05001971 ('block_local_override', 'FAILURE'),
Monty Taylor8da768f2017-08-31 14:15:35 -05001972 ('file_local_good', 'SUCCESS'),
1973 ('file_local_bad', 'FAILURE'),
James E. Blairabbaa6f2017-04-06 16:11:44 -07001974 ]
1975 for job_name, result in plugin_tests:
1976 count += 1
1977 self._add_job(job_name)
1978
1979 job = self.getJobFromHistory(job_name)
1980 with self.jobLog(job):
1981 self.assertEqual(count, len(self.history))
1982 build = self.history[-1]
1983 self.assertEqual(build.result, result)
1984
1985 # TODOv3(jeblair): parse the ansible output and verify we're
1986 # getting the exception we expect.
1987
James E. Blairb9c0d772017-03-03 14:34:49 -08001988
James E. Blaira4d4eef2017-06-30 14:49:17 -07001989class TestPrePlaybooks(AnsibleZuulTestCase):
1990 # A temporary class to hold new tests while others are disabled
1991
1992 tenant_config_file = 'config/pre-playbook/main.yaml'
1993
1994 def test_pre_playbook_fail(self):
1995 # Test that we run the post playbooks (but not the actual
1996 # playbook) when a pre-playbook fails.
1997 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1998 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
1999 self.waitUntilSettled()
2000 build = self.getJobFromHistory('python27')
2001 self.assertIsNone(build.result)
2002 self.assertIn('RETRY_LIMIT', A.messages[0])
2003 flag_path = os.path.join(self.test_root, build.uuid +
2004 '.main.flag')
2005 self.assertFalse(os.path.exists(flag_path))
2006 pre_flag_path = os.path.join(self.test_root, build.uuid +
2007 '.pre.flag')
2008 self.assertFalse(os.path.exists(pre_flag_path))
2009 post_flag_path = os.path.join(self.test_root, build.uuid +
2010 '.post.flag')
James E. Blair21037782017-07-19 11:56:55 -07002011 self.assertTrue(os.path.exists(post_flag_path),
2012 "The file %s should exist" % post_flag_path)
James E. Blaira4d4eef2017-06-30 14:49:17 -07002013
2014
James E. Blairbacbb882017-10-17 09:48:23 -07002015class TestPostPlaybooks(AnsibleZuulTestCase):
2016 tenant_config_file = 'config/post-playbook/main.yaml'
2017
2018 def test_post_playbook_abort(self):
2019 # Test that when we abort a job in the post playbook, that we
2020 # don't send back POST_FAILURE.
2021 self.executor_server.verbose = True
2022 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2023 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2024
2025 while not len(self.builds):
2026 time.sleep(0.1)
2027 build = self.builds[0]
2028
2029 post_start = os.path.join(self.test_root, build.uuid +
2030 '.post_start.flag')
2031 start = time.time()
2032 while time.time() < start + 90:
2033 if os.path.exists(post_start):
2034 break
2035 time.sleep(0.1)
2036 # The post playbook has started, abort the job
2037 self.fake_gerrit.addEvent(A.getChangeAbandonedEvent())
2038 self.waitUntilSettled()
2039
2040 build = self.getJobFromHistory('python27')
2041 self.assertEqual('ABORTED', build.result)
2042
2043 post_end = os.path.join(self.test_root, build.uuid +
2044 '.post_end.flag')
2045 self.assertTrue(os.path.exists(post_start))
2046 self.assertFalse(os.path.exists(post_end))
2047
2048
James E. Blairb9c0d772017-03-03 14:34:49 -08002049class TestBrokenConfig(ZuulTestCase):
2050 # Test that we get an appropriate syntax error if we start with a
2051 # broken config.
2052
2053 tenant_config_file = 'config/broken/main.yaml'
2054
2055 def setUp(self):
2056 with testtools.ExpectedException(
2057 zuul.configloader.ConfigurationSyntaxError,
2058 "\nZuul encountered a syntax error"):
2059 super(TestBrokenConfig, self).setUp()
2060
2061 def test_broken_config_on_startup(self):
2062 pass
Ricardo Carrillo Cruz22994f92016-12-02 11:41:58 +00002063
2064
2065class TestProjectKeys(ZuulTestCase):
2066 # Test that we can generate project keys
2067
2068 # Normally the test infrastructure copies a static key in place
2069 # for each project before starting tests. This saves time because
2070 # Zuul's automatic key-generation on startup can be slow. To make
2071 # sure we exercise that code, in this test we allow Zuul to create
2072 # keys for the project on startup.
2073 create_project_keys = True
Tobias Henkelabf973e2017-07-28 10:07:34 +02002074 config_file = 'zuul-connections-gerrit-and-github.conf'
Ricardo Carrillo Cruz22994f92016-12-02 11:41:58 +00002075 tenant_config_file = 'config/in-repo/main.yaml'
2076
2077 def test_key_generation(self):
2078 key_root = os.path.join(self.state_root, 'keys')
2079 private_key_file = os.path.join(key_root, 'gerrit/org/project.pem')
2080 # Make sure that a proper key was created on startup
2081 with open(private_key_file, "rb") as f:
James E. Blairbf1a4f22017-03-17 10:59:37 -07002082 private_key, public_key = \
2083 encryption.deserialize_rsa_keypair(f.read())
Ricardo Carrillo Cruz22994f92016-12-02 11:41:58 +00002084
2085 with open(os.path.join(FIXTURE_DIR, 'private.pem')) as i:
2086 fixture_private_key = i.read()
2087
2088 # Make sure that we didn't just end up with the static fixture
2089 # key
2090 self.assertNotEqual(fixture_private_key, private_key)
2091
2092 # Make sure it's the right length
2093 self.assertEqual(4096, private_key.key_size)
James E. Blairbce76932017-05-04 10:03:15 -07002094
2095
James E. Blairbb94dfa2017-07-11 07:45:19 -07002096class RoleTestCase(ZuulTestCase):
James E. Blair1b27f6a2017-07-14 14:09:07 -07002097 def _assertRolePath(self, build, playbook, content):
2098 path = os.path.join(self.test_root, build.uuid,
2099 'ansible', playbook, 'ansible.cfg')
2100 roles_paths = []
2101 with open(path) as f:
2102 for line in f:
2103 if line.startswith('roles_path'):
2104 roles_paths.append(line)
2105 print(roles_paths)
2106 if content:
2107 self.assertEqual(len(roles_paths), 1,
2108 "Should have one roles_path line in %s" %
2109 (playbook,))
2110 self.assertIn(content, roles_paths[0])
2111 else:
2112 self.assertEqual(len(roles_paths), 0,
2113 "Should have no roles_path line in %s" %
2114 (playbook,))
2115
James E. Blairbb94dfa2017-07-11 07:45:19 -07002116
2117class TestRoles(RoleTestCase):
2118 tenant_config_file = 'config/roles/main.yaml'
2119
James E. Blairbce76932017-05-04 10:03:15 -07002120 def test_role(self):
2121 # This exercises a proposed change to a role being checked out
2122 # and used.
2123 A = self.fake_gerrit.addFakeChange('bare-role', 'master', 'A')
2124 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2125 B.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
2126 B.subject, A.data['id'])
2127 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2128 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
2129 self.waitUntilSettled()
2130 self.assertHistory([
2131 dict(name='project-test', result='SUCCESS', changes='1,1 2,1'),
2132 ])
James E. Blair6459db12017-06-29 14:57:20 -07002133
James E. Blair1b27f6a2017-07-14 14:09:07 -07002134 def test_role_inheritance(self):
2135 self.executor_server.hold_jobs_in_build = True
2136 conf = textwrap.dedent(
2137 """
2138 - job:
2139 name: parent
2140 roles:
2141 - zuul: bare-role
Ian Wienand548c43c2017-12-05 14:16:32 +11002142 pre-run: playbooks/parent-pre.yaml
2143 post-run: playbooks/parent-post.yaml
James E. Blair1b27f6a2017-07-14 14:09:07 -07002144
2145 - job:
2146 name: project-test
2147 parent: parent
James E. Blair2f589fe2017-10-26 12:57:41 -07002148 run: playbooks/project-test.yaml
James E. Blair1b27f6a2017-07-14 14:09:07 -07002149 roles:
2150 - zuul: org/project
2151
2152 - project:
2153 name: org/project
2154 check:
2155 jobs:
2156 - project-test
2157 """)
2158
2159 file_dict = {'.zuul.yaml': conf}
2160 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
2161 files=file_dict)
2162 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2163 self.waitUntilSettled()
2164
2165 self.assertEqual(len(self.builds), 1)
2166 build = self.getBuildByName('project-test')
2167 self._assertRolePath(build, 'pre_playbook_0', 'role_0')
2168 self._assertRolePath(build, 'playbook_0', 'role_0')
2169 self._assertRolePath(build, 'playbook_0', 'role_1')
2170 self._assertRolePath(build, 'post_playbook_0', 'role_0')
2171
2172 self.executor_server.hold_jobs_in_build = False
2173 self.executor_server.release()
2174 self.waitUntilSettled()
2175
2176 self.assertHistory([
2177 dict(name='project-test', result='SUCCESS', changes='1,1'),
2178 ])
2179
James E. Blair6f699732017-07-18 14:19:11 -07002180 def test_role_error(self):
2181 conf = textwrap.dedent(
2182 """
2183 - job:
2184 name: project-test
James E. Blair2f589fe2017-10-26 12:57:41 -07002185 run: playbooks/project-test.yaml
James E. Blair6f699732017-07-18 14:19:11 -07002186 roles:
2187 - zuul: common-config
2188
2189 - project:
2190 name: org/project
2191 check:
2192 jobs:
2193 - project-test
2194 """)
2195
2196 file_dict = {'.zuul.yaml': conf}
2197 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
2198 files=file_dict)
2199 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2200 self.waitUntilSettled()
2201 self.assertIn(
2202 '- project-test project-test : ERROR Unable to find role',
2203 A.messages[-1])
2204
James E. Blair6459db12017-06-29 14:57:20 -07002205
James E. Blairbb94dfa2017-07-11 07:45:19 -07002206class TestImplicitRoles(RoleTestCase):
2207 tenant_config_file = 'config/implicit-roles/main.yaml'
2208
2209 def test_missing_roles(self):
2210 # Test implicit and explicit roles for a project which does
2211 # not have roles. The implicit role should be silently
2212 # ignored since the project doesn't supply roles, but if a
2213 # user declares an explicit role, it should error.
2214 self.executor_server.hold_jobs_in_build = True
2215 A = self.fake_gerrit.addFakeChange('org/norole-project', 'master', 'A')
2216 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2217 self.waitUntilSettled()
2218
2219 self.assertEqual(len(self.builds), 2)
2220 build = self.getBuildByName('implicit-role-fail')
2221 self._assertRolePath(build, 'playbook_0', None)
2222
2223 self.executor_server.hold_jobs_in_build = False
2224 self.executor_server.release()
2225 self.waitUntilSettled()
2226 # The retry_limit doesn't get recorded
2227 self.assertHistory([
2228 dict(name='implicit-role-fail', result='SUCCESS', changes='1,1'),
2229 ])
2230
2231 def test_roles(self):
2232 # Test implicit and explicit roles for a project which does
2233 # have roles. In both cases, we should end up with the role
2234 # in the path. In the explicit case, ensure we end up with
2235 # the name we specified.
2236 self.executor_server.hold_jobs_in_build = True
2237 A = self.fake_gerrit.addFakeChange('org/role-project', 'master', 'A')
2238 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2239 self.waitUntilSettled()
2240
2241 self.assertEqual(len(self.builds), 2)
2242 build = self.getBuildByName('implicit-role-ok')
2243 self._assertRolePath(build, 'playbook_0', 'role_0')
2244
2245 build = self.getBuildByName('explicit-role-ok')
2246 self._assertRolePath(build, 'playbook_0', 'role_0')
2247
2248 self.executor_server.hold_jobs_in_build = False
2249 self.executor_server.release()
2250 self.waitUntilSettled()
2251 self.assertHistory([
2252 dict(name='implicit-role-ok', result='SUCCESS', changes='1,1'),
2253 dict(name='explicit-role-ok', result='SUCCESS', changes='1,1'),
2254 ], ordered=False)
2255
2256
James E. Blair6459db12017-06-29 14:57:20 -07002257class TestShadow(ZuulTestCase):
2258 tenant_config_file = 'config/shadow/main.yaml'
2259
2260 def test_shadow(self):
2261 # Test that a repo is allowed to shadow another's job definitions.
2262 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2263 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2264 self.waitUntilSettled()
2265 self.assertHistory([
2266 dict(name='test1', result='SUCCESS', changes='1,1'),
2267 dict(name='test2', result='SUCCESS', changes='1,1'),
James E. Blairadafa6c2017-07-12 08:50:56 -07002268 ], ordered=False)
James E. Blair196f61a2017-06-30 15:42:29 -07002269
2270
2271class TestDataReturn(AnsibleZuulTestCase):
2272 tenant_config_file = 'config/data-return/main.yaml'
2273
2274 def test_data_return(self):
James E. Blair196f61a2017-06-30 15:42:29 -07002275 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2276 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2277 self.waitUntilSettled()
2278 self.assertHistory([
2279 dict(name='data-return', result='SUCCESS', changes='1,1'),
James E. Blair88e79c02017-07-07 13:36:54 -07002280 dict(name='data-return-relative', result='SUCCESS', changes='1,1'),
James E. Blair698703c2017-09-15 20:58:30 -06002281 dict(name='child', result='SUCCESS', changes='1,1'),
James E. Blair88e79c02017-07-07 13:36:54 -07002282 ], ordered=False)
2283 self.assertIn('- data-return http://example.com/test/log/url/',
2284 A.messages[-1])
2285 self.assertIn('- data-return-relative '
2286 'http://example.com/test/log/url/docs/index.html',
James E. Blair196f61a2017-06-30 15:42:29 -07002287 A.messages[-1])
Clint Byrumdc8a0902017-07-20 16:36:27 -07002288
2289
2290class TestDiskAccounting(AnsibleZuulTestCase):
2291 config_file = 'zuul-disk-accounting.conf'
2292 tenant_config_file = 'config/disk-accountant/main.yaml'
2293
2294 def test_disk_accountant_kills_job(self):
2295 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2296 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2297 self.waitUntilSettled()
2298 self.assertHistory([
2299 dict(name='dd-big-empty-file', result='ABORTED', changes='1,1')])
Tristan Cacqueray82f864b2017-08-01 05:54:42 +00002300
2301
2302class TestMaxNodesPerJob(AnsibleZuulTestCase):
2303 tenant_config_file = 'config/multi-tenant/main.yaml'
2304
Tristan Cacquerayc98bff72017-09-10 15:25:26 +00002305 def test_max_timeout_exceeded(self):
Tristan Cacqueray82f864b2017-08-01 05:54:42 +00002306 in_repo_conf = textwrap.dedent(
2307 """
2308 - job:
2309 name: test-job
James E. Blair7e3e6882017-09-20 15:47:13 -07002310 nodeset:
2311 nodes:
2312 - name: node01
2313 label: fake
2314 - name: node02
2315 label: fake
2316 - name: node03
2317 label: fake
2318 - name: node04
2319 label: fake
2320 - name: node05
2321 label: fake
2322 - name: node06
2323 label: fake
Tristan Cacqueray82f864b2017-08-01 05:54:42 +00002324 """)
2325 file_dict = {'.zuul.yaml': in_repo_conf}
2326 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A',
2327 files=file_dict)
2328 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2329 self.waitUntilSettled()
2330 self.assertIn('The job "test-job" exceeds tenant max-nodes-per-job 5.',
2331 A.messages[0], "A should fail because of nodes limit")
2332
2333 B = self.fake_gerrit.addFakeChange('org/project2', 'master', 'A',
2334 files=file_dict)
2335 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
2336 self.waitUntilSettled()
2337 self.assertNotIn("exceeds tenant max-nodes", B.messages[0],
2338 "B should not fail because of nodes limit")
James E. Blair2bab6e72017-08-07 09:52:45 -07002339
2340
Tristan Cacquerayc98bff72017-09-10 15:25:26 +00002341class TestMaxTimeout(AnsibleZuulTestCase):
2342 tenant_config_file = 'config/multi-tenant/main.yaml'
2343
2344 def test_max_nodes_reached(self):
2345 in_repo_conf = textwrap.dedent(
2346 """
2347 - job:
2348 name: test-job
2349 timeout: 3600
2350 """)
2351 file_dict = {'.zuul.yaml': in_repo_conf}
2352 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A',
2353 files=file_dict)
2354 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2355 self.waitUntilSettled()
2356 self.assertIn('The job "test-job" exceeds tenant max-job-timeout',
2357 A.messages[0], "A should fail because of timeout limit")
2358
2359 B = self.fake_gerrit.addFakeChange('org/project2', 'master', 'A',
2360 files=file_dict)
2361 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
2362 self.waitUntilSettled()
2363 self.assertNotIn("exceeds tenant max-job-timeout", B.messages[0],
2364 "B should not fail because of timeout limit")
2365
2366
James E. Blair7edc25f2017-10-26 10:47:14 -07002367class TestPragma(ZuulTestCase):
2368 tenant_config_file = 'config/pragma/main.yaml'
2369
2370 def test_no_pragma(self):
2371 self.create_branch('org/project', 'stable')
2372 with open(os.path.join(FIXTURE_DIR,
2373 'config/pragma/git/',
2374 'org_project/nopragma.yaml')) as f:
2375 config = f.read()
2376 file_dict = {'.zuul.yaml': config}
2377 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
2378 files=file_dict)
2379 A.addApproval('Code-Review', 2)
2380 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
2381 self.waitUntilSettled()
2382 self.fake_gerrit.addEvent(A.getChangeMergedEvent())
2383 self.waitUntilSettled()
2384
2385 # This is an untrusted repo with 2 branches, so it should have
2386 # an implied branch matcher for the job.
2387 tenant = self.sched.abide.tenants.get('tenant-one')
2388 jobs = tenant.layout.getJobs('test-job')
2389 self.assertEqual(len(jobs), 1)
2390 for job in tenant.layout.getJobs('test-job'):
2391 self.assertIsNotNone(job.branch_matcher)
2392
2393 def test_pragma(self):
2394 self.create_branch('org/project', 'stable')
2395 with open(os.path.join(FIXTURE_DIR,
2396 'config/pragma/git/',
2397 'org_project/pragma.yaml')) as f:
2398 config = f.read()
2399 file_dict = {'.zuul.yaml': config}
2400 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
2401 files=file_dict)
2402 A.addApproval('Code-Review', 2)
2403 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
2404 self.waitUntilSettled()
2405 self.fake_gerrit.addEvent(A.getChangeMergedEvent())
2406 self.waitUntilSettled()
2407
2408 # This is an untrusted repo with 2 branches, so it would
2409 # normally have an implied branch matcher, but our pragma
2410 # overrides it.
2411 tenant = self.sched.abide.tenants.get('tenant-one')
2412 jobs = tenant.layout.getJobs('test-job')
2413 self.assertEqual(len(jobs), 1)
2414 for job in tenant.layout.getJobs('test-job'):
2415 self.assertIsNone(job.branch_matcher)
2416
2417
James E. Blair37c3d8c2017-12-13 15:06:11 -08002418class TestPragmaMultibranch(ZuulTestCase):
2419 tenant_config_file = 'config/pragma-multibranch/main.yaml'
2420
2421 def test_no_branch_matchers(self):
2422 self.create_branch('org/project1', 'stable/pike')
2423 self.create_branch('org/project2', 'stable/jewel')
2424 self.fake_gerrit.addEvent(
2425 self.fake_gerrit.getFakeBranchCreatedEvent(
2426 'org/project1', 'stable/pike'))
2427 self.fake_gerrit.addEvent(
2428 self.fake_gerrit.getFakeBranchCreatedEvent(
2429 'org/project2', 'stable/jewel'))
2430 self.waitUntilSettled()
2431 # We want the jobs defined on the stable/pike branch of
2432 # project1 to apply to the stable/jewel branch of project2.
2433
2434 # First, without the pragma line, the jobs should not run
2435 # because in project1 they have branch matchers for pike, so
2436 # they will not match a jewel change.
2437 B = self.fake_gerrit.addFakeChange('org/project2', 'stable/jewel', 'B')
2438 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
2439 self.waitUntilSettled()
2440 self.assertHistory([])
2441
2442 # Add a pragma line to disable implied branch matchers in
2443 # project1, so that the jobs and templates apply to both
2444 # branches.
2445 with open(os.path.join(FIXTURE_DIR,
2446 'config/pragma-multibranch/git/',
2447 'org_project1/zuul.yaml')) as f:
2448 config = f.read()
2449 extra_conf = textwrap.dedent(
2450 """
2451 - pragma:
2452 implied-branch-matchers: False
2453 """)
2454 config = extra_conf + config
2455 file_dict = {'zuul.yaml': config}
2456 A = self.fake_gerrit.addFakeChange('org/project1', 'stable/pike', 'A',
2457 files=file_dict)
2458 A.addApproval('Code-Review', 2)
2459 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
2460 self.waitUntilSettled()
2461 self.fake_gerrit.addEvent(A.getChangeMergedEvent())
2462 self.waitUntilSettled()
2463
2464 # Now verify that when we propose a change to jewel, we get
2465 # the pike/jewel jobs.
2466 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
2467 self.waitUntilSettled()
2468 self.assertHistory([
2469 dict(name='test-job1', result='SUCCESS', changes='1,1'),
2470 dict(name='test-job2', result='SUCCESS', changes='1,1'),
2471 ], ordered=False)
2472
2473 def test_supplied_branch_matchers(self):
2474 self.create_branch('org/project1', 'stable/pike')
2475 self.create_branch('org/project2', 'stable/jewel')
2476 self.fake_gerrit.addEvent(
2477 self.fake_gerrit.getFakeBranchCreatedEvent(
2478 'org/project1', 'stable/pike'))
2479 self.fake_gerrit.addEvent(
2480 self.fake_gerrit.getFakeBranchCreatedEvent(
2481 'org/project2', 'stable/jewel'))
2482 self.waitUntilSettled()
2483 # We want the jobs defined on the stable/pike branch of
2484 # project1 to apply to the stable/jewel branch of project2.
2485
2486 # First, without the pragma line, the jobs should not run
2487 # because in project1 they have branch matchers for pike, so
2488 # they will not match a jewel change.
2489 B = self.fake_gerrit.addFakeChange('org/project2', 'stable/jewel', 'B')
2490 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
2491 self.waitUntilSettled()
2492 self.assertHistory([])
2493
2494 # Add a pragma line to disable implied branch matchers in
2495 # project1, so that the jobs and templates apply to both
2496 # branches.
2497 with open(os.path.join(FIXTURE_DIR,
2498 'config/pragma-multibranch/git/',
2499 'org_project1/zuul.yaml')) as f:
2500 config = f.read()
2501 extra_conf = textwrap.dedent(
2502 """
2503 - pragma:
2504 implied-branches:
2505 - stable/pike
2506 - stable/jewel
2507 """)
2508 config = extra_conf + config
2509 file_dict = {'zuul.yaml': config}
2510 A = self.fake_gerrit.addFakeChange('org/project1', 'stable/pike', 'A',
2511 files=file_dict)
2512 A.addApproval('Code-Review', 2)
2513 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
2514 self.waitUntilSettled()
2515 self.fake_gerrit.addEvent(A.getChangeMergedEvent())
2516 self.waitUntilSettled()
2517 # Now verify that when we propose a change to jewel, we get
2518 # the pike/jewel jobs.
2519 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
2520 self.waitUntilSettled()
2521 self.assertHistory([
2522 dict(name='test-job1', result='SUCCESS', changes='1,1'),
2523 dict(name='test-job2', result='SUCCESS', changes='1,1'),
2524 ], ordered=False)
2525
2526
James E. Blair2bab6e72017-08-07 09:52:45 -07002527class TestBaseJobs(ZuulTestCase):
2528 tenant_config_file = 'config/base-jobs/main.yaml'
2529
2530 def test_multiple_base_jobs(self):
2531 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2532 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2533 self.waitUntilSettled()
2534 self.assertHistory([
2535 dict(name='my-job', result='SUCCESS', changes='1,1'),
2536 dict(name='other-job', result='SUCCESS', changes='1,1'),
2537 ], ordered=False)
2538 self.assertEqual(self.getJobFromHistory('my-job').
2539 parameters['zuul']['jobtags'],
2540 ['mybase'])
2541 self.assertEqual(self.getJobFromHistory('other-job').
2542 parameters['zuul']['jobtags'],
2543 ['otherbase'])
2544
2545 def test_untrusted_base_job(self):
2546 """Test that a base job may not be defined in an untrusted repo"""
2547 in_repo_conf = textwrap.dedent(
2548 """
2549 - job:
2550 name: fail-base
2551 parent: null
2552 """)
2553
2554 file_dict = {'.zuul.yaml': in_repo_conf}
2555 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
2556 files=file_dict)
2557 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2558 self.waitUntilSettled()
2559 self.assertEqual(A.reported, 1,
2560 "A should report failure")
2561 self.assertEqual(A.patchsets[0]['approvals'][0]['value'], "-1")
2562 self.assertIn('Base jobs must be defined in config projects',
2563 A.messages[0])
2564 self.assertHistory([])
James E. Blairdb089032017-08-15 13:42:12 -07002565
2566
James E. Blairdf91ab32017-10-25 17:57:13 -07002567class TestSecretInheritance(ZuulTestCase):
2568 tenant_config_file = 'config/secret-inheritance/main.yaml'
2569
2570 def _getSecrets(self, job, pbtype):
2571 secrets = []
2572 build = self.getJobFromHistory(job)
2573 for pb in build.parameters[pbtype]:
2574 secrets.append(pb['secrets'])
2575 return secrets
2576
2577 def _checkTrustedSecrets(self):
2578 secret = {'longpassword': 'test-passwordtest-password',
2579 'password': 'test-password',
2580 'username': 'test-username'}
2581 self.assertEqual(
2582 self._getSecrets('trusted-secrets', 'playbooks'),
James E. Blair2f589fe2017-10-26 12:57:41 -07002583 [{'trusted-secret': secret}])
James E. Blairdf91ab32017-10-25 17:57:13 -07002584 self.assertEqual(
2585 self._getSecrets('trusted-secrets', 'pre_playbooks'), [])
2586 self.assertEqual(
2587 self._getSecrets('trusted-secrets', 'post_playbooks'), [])
2588
2589 self.assertEqual(
2590 self._getSecrets('trusted-secrets-trusted-child',
James E. Blair2f589fe2017-10-26 12:57:41 -07002591 'playbooks'), [{}])
James E. Blairdf91ab32017-10-25 17:57:13 -07002592 self.assertEqual(
2593 self._getSecrets('trusted-secrets-trusted-child',
2594 'pre_playbooks'), [])
2595 self.assertEqual(
2596 self._getSecrets('trusted-secrets-trusted-child',
2597 'post_playbooks'), [])
2598
2599 self.assertEqual(
2600 self._getSecrets('trusted-secrets-untrusted-child',
James E. Blair2f589fe2017-10-26 12:57:41 -07002601 'playbooks'), [{}])
James E. Blairdf91ab32017-10-25 17:57:13 -07002602 self.assertEqual(
2603 self._getSecrets('trusted-secrets-untrusted-child',
2604 'pre_playbooks'), [])
2605 self.assertEqual(
2606 self._getSecrets('trusted-secrets-untrusted-child',
2607 'post_playbooks'), [])
2608
2609 def _checkUntrustedSecrets(self):
2610 secret = {'longpassword': 'test-passwordtest-password',
2611 'password': 'test-password',
2612 'username': 'test-username'}
2613 self.assertEqual(
2614 self._getSecrets('untrusted-secrets', 'playbooks'),
James E. Blair2f589fe2017-10-26 12:57:41 -07002615 [{'untrusted-secret': secret}])
James E. Blairdf91ab32017-10-25 17:57:13 -07002616 self.assertEqual(
2617 self._getSecrets('untrusted-secrets', 'pre_playbooks'), [])
2618 self.assertEqual(
2619 self._getSecrets('untrusted-secrets', 'post_playbooks'), [])
2620
2621 self.assertEqual(
2622 self._getSecrets('untrusted-secrets-trusted-child',
James E. Blair2f589fe2017-10-26 12:57:41 -07002623 'playbooks'), [{}])
James E. Blairdf91ab32017-10-25 17:57:13 -07002624 self.assertEqual(
2625 self._getSecrets('untrusted-secrets-trusted-child',
2626 'pre_playbooks'), [])
2627 self.assertEqual(
2628 self._getSecrets('untrusted-secrets-trusted-child',
2629 'post_playbooks'), [])
2630
2631 self.assertEqual(
2632 self._getSecrets('untrusted-secrets-untrusted-child',
James E. Blair2f589fe2017-10-26 12:57:41 -07002633 'playbooks'), [{}])
James E. Blairdf91ab32017-10-25 17:57:13 -07002634 self.assertEqual(
2635 self._getSecrets('untrusted-secrets-untrusted-child',
2636 'pre_playbooks'), [])
2637 self.assertEqual(
2638 self._getSecrets('untrusted-secrets-untrusted-child',
2639 'post_playbooks'), [])
2640
2641 def test_trusted_secret_inheritance_check(self):
2642 A = self.fake_gerrit.addFakeChange('common-config', 'master', 'A')
2643 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2644 self.waitUntilSettled()
2645 self.assertHistory([
2646 dict(name='trusted-secrets', result='SUCCESS', changes='1,1'),
2647 dict(name='trusted-secrets-trusted-child',
2648 result='SUCCESS', changes='1,1'),
2649 dict(name='trusted-secrets-untrusted-child',
2650 result='SUCCESS', changes='1,1'),
2651 ], ordered=False)
2652
2653 self._checkTrustedSecrets()
2654
2655 def test_untrusted_secret_inheritance_gate(self):
2656 A = self.fake_gerrit.addFakeChange('common-config', 'master', 'A')
2657 A.addApproval('Code-Review', 2)
2658 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
2659 self.waitUntilSettled()
2660 self.assertHistory([
2661 dict(name='untrusted-secrets', result='SUCCESS', changes='1,1'),
2662 dict(name='untrusted-secrets-trusted-child',
2663 result='SUCCESS', changes='1,1'),
2664 dict(name='untrusted-secrets-untrusted-child',
2665 result='SUCCESS', changes='1,1'),
2666 ], ordered=False)
2667
2668 self._checkUntrustedSecrets()
2669
2670 def test_untrusted_secret_inheritance_check(self):
2671 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2672 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2673 self.waitUntilSettled()
2674 # This configuration tries to run untrusted secrets in an
2675 # non-post-review pipeline and should therefore run no jobs.
2676 self.assertHistory([])
2677
2678
James E. Blairdb089032017-08-15 13:42:12 -07002679class TestSecretLeaks(AnsibleZuulTestCase):
2680 tenant_config_file = 'config/secret-leaks/main.yaml'
2681
2682 def searchForContent(self, path, content):
2683 matches = []
2684 for (dirpath, dirnames, filenames) in os.walk(path):
2685 for filename in filenames:
2686 filepath = os.path.join(dirpath, filename)
2687 with open(filepath, 'rb') as f:
2688 if content in f.read():
2689 matches.append(filepath[len(path):])
2690 return matches
2691
2692 def _test_secret_file(self):
2693 # Or rather -- test that they *don't* leak.
2694 # Keep the jobdir around so we can inspect contents.
2695 self.executor_server.keep_jobdir = True
2696 conf = textwrap.dedent(
2697 """
2698 - project:
2699 name: org/project
2700 check:
2701 jobs:
2702 - secret-file
2703 """)
2704
2705 file_dict = {'.zuul.yaml': conf}
2706 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
2707 files=file_dict)
2708 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2709 self.waitUntilSettled()
2710 self.assertHistory([
2711 dict(name='secret-file', result='SUCCESS', changes='1,1'),
2712 ], ordered=False)
2713 matches = self.searchForContent(self.history[0].jobdir.root,
2714 b'test-password')
James E. Blaird6a71ca2017-08-18 14:15:05 -07002715 self.assertEqual(set(['/work/secret-file.txt']),
James E. Blairdb089032017-08-15 13:42:12 -07002716 set(matches))
2717
2718 def test_secret_file(self):
2719 self._test_secret_file()
2720
2721 def test_secret_file_verbose(self):
2722 # Output extra ansible info to exercise alternate logging code
2723 # paths.
2724 self.executor_server.verbose = True
2725 self._test_secret_file()
2726
2727 def _test_secret_file_fail(self):
2728 # Or rather -- test that they *don't* leak.
2729 # Keep the jobdir around so we can inspect contents.
2730 self.executor_server.keep_jobdir = True
2731 conf = textwrap.dedent(
2732 """
2733 - project:
2734 name: org/project
2735 check:
2736 jobs:
2737 - secret-file-fail
2738 """)
2739
2740 file_dict = {'.zuul.yaml': conf}
2741 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
2742 files=file_dict)
2743 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2744 self.waitUntilSettled()
2745 self.assertHistory([
2746 dict(name='secret-file-fail', result='FAILURE', changes='1,1'),
2747 ], ordered=False)
2748 matches = self.searchForContent(self.history[0].jobdir.root,
2749 b'test-password')
James E. Blaird6a71ca2017-08-18 14:15:05 -07002750 self.assertEqual(set(['/work/failure-file.txt']),
James E. Blairdb089032017-08-15 13:42:12 -07002751 set(matches))
2752
2753 def test_secret_file_fail(self):
2754 self._test_secret_file_fail()
2755
2756 def test_secret_file_fail_verbose(self):
2757 # Output extra ansible info to exercise alternate logging code
2758 # paths.
2759 self.executor_server.verbose = True
2760 self._test_secret_file_fail()
James E. Blaira00910c2017-08-23 09:15:04 -07002761
2762
2763class TestJobOutput(AnsibleZuulTestCase):
2764 tenant_config_file = 'config/job-output/main.yaml'
2765
2766 def _get_file(self, build, path):
2767 p = os.path.join(build.jobdir.root, path)
2768 with open(p) as f:
2769 return f.read()
2770
2771 def test_job_output(self):
Monty Taylor0e2489a2017-10-10 11:57:29 -05002772 # Verify that command standard output appears in the job output,
2773 # and that failures in the final playbook get logged.
James E. Blaira00910c2017-08-23 09:15:04 -07002774
2775 # This currently only verifies we receive output from
2776 # localhost. Notably, it does not verify we receive output
2777 # via zuul_console streaming.
2778 self.executor_server.keep_jobdir = True
2779 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2780 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2781 self.waitUntilSettled()
2782 self.assertHistory([
2783 dict(name='job-output', result='SUCCESS', changes='1,1'),
2784 ], ordered=False)
2785
2786 token = 'Standard output test %s' % (self.history[0].jobdir.src_root)
2787 j = json.loads(self._get_file(self.history[0],
2788 'work/logs/job-output.json'))
2789 self.assertEqual(token,
2790 j[0]['plays'][0]['tasks'][0]
2791 ['hosts']['localhost']['stdout'])
2792
2793 print(self._get_file(self.history[0],
2794 'work/logs/job-output.txt'))
2795 self.assertIn(token,
2796 self._get_file(self.history[0],
2797 'work/logs/job-output.txt'))
Monty Taylor0e2489a2017-10-10 11:57:29 -05002798
2799 def test_job_output_failure_log(self):
2800 logger = logging.getLogger('zuul.AnsibleJob')
2801 output = io.StringIO()
2802 logger.addHandler(logging.StreamHandler(output))
2803
2804 # Verify that a failure in the last post playbook emits the contents
2805 # of the json output to the log
2806 self.executor_server.keep_jobdir = True
2807 A = self.fake_gerrit.addFakeChange('org/project2', 'master', 'A')
2808 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2809 self.waitUntilSettled()
2810 self.assertHistory([
2811 dict(name='job-output-failure',
2812 result='POST_FAILURE', changes='1,1'),
2813 ], ordered=False)
2814
2815 token = 'Standard output test %s' % (self.history[0].jobdir.src_root)
2816 j = json.loads(self._get_file(self.history[0],
2817 'work/logs/job-output.json'))
2818 self.assertEqual(token,
2819 j[0]['plays'][0]['tasks'][0]
2820 ['hosts']['localhost']['stdout'])
2821
2822 print(self._get_file(self.history[0],
2823 'work/logs/job-output.json'))
2824 self.assertIn(token,
2825 self._get_file(self.history[0],
2826 'work/logs/job-output.txt'))
2827
2828 log_output = output.getvalue()
2829 self.assertIn('Final playbook failed', log_output)
2830 self.assertIn('Failure test', log_output)