blob: 70d9211232257374388b458a9e84ff00d06b85f2 [file] [log] [blame]
James E. Blair59fdbac2015-12-07 17:08:06 -08001#!/usr/bin/env python
2
3# Copyright 2012 Hewlett-Packard Development Company, L.P.
4#
5# Licensed under the Apache License, Version 2.0 (the "License"); you may
6# not use this file except in compliance with the License. You may obtain
7# a copy of the License at
8#
9# http://www.apache.org/licenses/LICENSE-2.0
10#
11# Unless required by applicable law or agreed to in writing, software
12# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14# License for the specific language governing permissions and limitations
15# under the License.
16
Monty Taylor0e2489a2017-10-10 11:57:29 -050017import io
James E. Blaira00910c2017-08-23 09:15:04 -070018import json
Monty Taylor0e2489a2017-10-10 11:57:29 -050019import logging
James E. Blaira92cbc82017-01-23 14:56:49 -080020import os
James E. Blair14abdf42015-12-09 16:11:53 -080021import textwrap
James E. Blair3a098dd2017-10-04 14:37:29 -070022import gc
James E. Blairbacbb882017-10-17 09:48:23 -070023import time
James E. Blair3a098dd2017-10-04 14:37:29 -070024from unittest import skip
James E. Blair59fdbac2015-12-07 17:08:06 -080025
James E. Blairb9c0d772017-03-03 14:34:49 -080026import testtools
27
28import zuul.configloader
James E. Blairbf1a4f22017-03-17 10:59:37 -070029from zuul.lib import encryption
Ricardo Carrillo Cruz22994f92016-12-02 11:41:58 +000030from tests.base import AnsibleZuulTestCase, ZuulTestCase, FIXTURE_DIR
James E. Blair59fdbac2015-12-07 17:08:06 -080031
James E. Blair59fdbac2015-12-07 17:08:06 -080032
James E. Blair3f876d52016-07-22 13:07:14 -070033class TestMultipleTenants(AnsibleZuulTestCase):
James E. Blair59fdbac2015-12-07 17:08:06 -080034 # A temporary class to hold new tests while others are disabled
35
James E. Blair2a629ec2015-12-22 15:32:02 -080036 tenant_config_file = 'config/multi-tenant/main.yaml'
James E. Blair59fdbac2015-12-07 17:08:06 -080037
James E. Blair83005782015-12-11 14:46:03 -080038 def test_multiple_tenants(self):
James E. Blair96f26942015-12-09 10:15:59 -080039 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A')
Tobias Henkelbf24fd12017-07-27 06:13:07 +020040 A.addApproval('Code-Review', 2)
41 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
James E. Blair59fdbac2015-12-07 17:08:06 -080042 self.waitUntilSettled()
James E. Blair96f26942015-12-09 10:15:59 -080043 self.assertEqual(self.getJobFromHistory('project1-test1').result,
James E. Blair59fdbac2015-12-07 17:08:06 -080044 'SUCCESS')
James E. Blair96c6bf82016-01-15 16:20:40 -080045 self.assertEqual(self.getJobFromHistory('python27').result,
46 'SUCCESS')
James E. Blair59fdbac2015-12-07 17:08:06 -080047 self.assertEqual(A.data['status'], 'MERGED')
James E. Blair96f26942015-12-09 10:15:59 -080048 self.assertEqual(A.reported, 2,
49 "A should report start and success")
50 self.assertIn('tenant-one-gate', A.messages[1],
51 "A should transit tenant-one gate")
52 self.assertNotIn('tenant-two-gate', A.messages[1],
53 "A should *not* transit tenant-two gate")
James E. Blair59fdbac2015-12-07 17:08:06 -080054
James E. Blair96f26942015-12-09 10:15:59 -080055 B = self.fake_gerrit.addFakeChange('org/project2', 'master', 'B')
Tobias Henkelbf24fd12017-07-27 06:13:07 +020056 B.addApproval('Code-Review', 2)
57 self.fake_gerrit.addEvent(B.addApproval('Approved', 1))
James E. Blair96f26942015-12-09 10:15:59 -080058 self.waitUntilSettled()
James E. Blair96c6bf82016-01-15 16:20:40 -080059 self.assertEqual(self.getJobFromHistory('python27',
60 'org/project2').result,
61 'SUCCESS')
James E. Blair96f26942015-12-09 10:15:59 -080062 self.assertEqual(self.getJobFromHistory('project2-test1').result,
63 'SUCCESS')
64 self.assertEqual(B.data['status'], 'MERGED')
65 self.assertEqual(B.reported, 2,
66 "B should report start and success")
67 self.assertIn('tenant-two-gate', B.messages[1],
68 "B should transit tenant-two gate")
69 self.assertNotIn('tenant-one-gate', B.messages[1],
70 "B should *not* transit tenant-one gate")
James E. Blair59fdbac2015-12-07 17:08:06 -080071
James E. Blair96f26942015-12-09 10:15:59 -080072 self.assertEqual(A.reported, 2, "Activity in tenant two should"
73 "not affect tenant one")
James E. Blair14abdf42015-12-09 16:11:53 -080074
James E. Blair83005782015-12-11 14:46:03 -080075
Tobias Henkel83167622017-06-30 19:45:03 +020076class TestFinal(ZuulTestCase):
77
78 tenant_config_file = 'config/final/main.yaml'
79
80 def test_final_variant_ok(self):
81 # test clean usage of final parent job
82 in_repo_conf = textwrap.dedent(
83 """
84 - project:
85 name: org/project
86 check:
87 jobs:
88 - job-final
89 """)
90
91 file_dict = {'.zuul.yaml': in_repo_conf}
92 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
93 files=file_dict)
94 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
95 self.waitUntilSettled()
96
97 self.assertEqual(A.reported, 1)
98 self.assertEqual(A.patchsets[-1]['approvals'][0]['value'], '1')
99
100 def test_final_variant_error(self):
101 # test misuse of final parent job
102 in_repo_conf = textwrap.dedent(
103 """
104 - project:
105 name: org/project
106 check:
107 jobs:
108 - job-final:
109 vars:
110 dont_override_this: bar
111 """)
112 file_dict = {'.zuul.yaml': in_repo_conf}
113 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
114 files=file_dict)
115 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
116 self.waitUntilSettled()
117
118 # The second patch tried to override some variables.
119 # Thus it should fail.
120 self.assertEqual(A.reported, 1)
121 self.assertEqual(A.patchsets[-1]['approvals'][0]['value'], '-1')
122 self.assertIn('Unable to modify final job', A.messages[0])
123
124 def test_final_inheritance(self):
125 # test misuse of final parent job
126 in_repo_conf = textwrap.dedent(
127 """
128 - job:
129 name: project-test
130 parent: job-final
James E. Blair2f589fe2017-10-26 12:57:41 -0700131 run: playbooks/project-test.yaml
Tobias Henkel83167622017-06-30 19:45:03 +0200132
133 - project:
134 name: org/project
135 check:
136 jobs:
137 - project-test
138 """)
139
140 in_repo_playbook = textwrap.dedent(
141 """
142 - hosts: all
143 tasks: []
144 """)
145
146 file_dict = {'.zuul.yaml': in_repo_conf,
147 'playbooks/project-test.yaml': in_repo_playbook}
148 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
149 files=file_dict)
150 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
151 self.waitUntilSettled()
152
153 # The second patch tried to override some variables.
154 # Thus it should fail.
155 self.assertEqual(A.reported, 1)
156 self.assertEqual(A.patchsets[-1]['approvals'][0]['value'], '-1')
James E. Blairc32a8352017-10-11 16:27:50 -0700157 self.assertIn('Unable to modify final job', A.messages[0])
Tobias Henkel83167622017-06-30 19:45:03 +0200158
159
James E. Blair9ab8db42017-12-01 15:12:04 -0800160class TestBranchNegative(ZuulTestCase):
161 tenant_config_file = 'config/branch-negative/main.yaml'
162
163 def test_negative_branch_match(self):
164 # Test that a negative branch matcher works with implied branches.
165 self.create_branch('org/project', 'stable/pike')
166 self.fake_gerrit.addEvent(
167 self.fake_gerrit.getFakeBranchCreatedEvent(
168 'org/project', 'stable/pike'))
169 self.waitUntilSettled()
170
171 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
172 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
173 self.waitUntilSettled()
174 B = self.fake_gerrit.addFakeChange('org/project', 'stable/pike', 'A')
175 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
176 self.waitUntilSettled()
177 self.assertHistory([
178 dict(name='test-job', result='SUCCESS', changes='1,1')])
179
180
James E. Blaire36d1a32017-11-28 13:33:38 -0800181class TestBranchTemplates(ZuulTestCase):
182 tenant_config_file = 'config/branch-templates/main.yaml'
183
184 def test_template_removal_from_branch(self):
185 # Test that a template can be removed from one branch but not
186 # another.
187 # This creates a new branch with a copy of the config in master
188 self.create_branch('puppet-integration', 'stable/newton')
189 self.create_branch('puppet-integration', 'stable/ocata')
190 self.create_branch('puppet-tripleo', 'stable/newton')
191 self.create_branch('puppet-tripleo', 'stable/ocata')
192 self.fake_gerrit.addEvent(
193 self.fake_gerrit.getFakeBranchCreatedEvent(
194 'puppet-integration', 'stable/newton'))
195 self.fake_gerrit.addEvent(
196 self.fake_gerrit.getFakeBranchCreatedEvent(
197 'puppet-integration', 'stable/ocata'))
198 self.fake_gerrit.addEvent(
199 self.fake_gerrit.getFakeBranchCreatedEvent(
200 'puppet-tripleo', 'stable/newton'))
201 self.fake_gerrit.addEvent(
202 self.fake_gerrit.getFakeBranchCreatedEvent(
203 'puppet-tripleo', 'stable/ocata'))
204 self.waitUntilSettled()
205
206 in_repo_conf = textwrap.dedent(
207 """
208 - project:
209 name: puppet-tripleo
210 check:
211 jobs:
212 - puppet-something
213 """)
214
215 file_dict = {'.zuul.yaml': in_repo_conf}
216 A = self.fake_gerrit.addFakeChange('puppet-tripleo', 'stable/newton',
217 'A', files=file_dict)
218 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
219 self.waitUntilSettled()
220 self.assertHistory([
221 dict(name='puppet-something', result='SUCCESS', changes='1,1')])
222
223 def test_template_change_on_branch(self):
224 # Test that the contents of a template can be changed on one
225 # branch without affecting another.
226
227 # This creates a new branch with a copy of the config in master
228 self.create_branch('puppet-integration', 'stable/newton')
229 self.create_branch('puppet-integration', 'stable/ocata')
230 self.create_branch('puppet-tripleo', 'stable/newton')
231 self.create_branch('puppet-tripleo', 'stable/ocata')
232 self.fake_gerrit.addEvent(
233 self.fake_gerrit.getFakeBranchCreatedEvent(
234 'puppet-integration', 'stable/newton'))
235 self.fake_gerrit.addEvent(
236 self.fake_gerrit.getFakeBranchCreatedEvent(
237 'puppet-integration', 'stable/ocata'))
238 self.fake_gerrit.addEvent(
239 self.fake_gerrit.getFakeBranchCreatedEvent(
240 'puppet-tripleo', 'stable/newton'))
241 self.fake_gerrit.addEvent(
242 self.fake_gerrit.getFakeBranchCreatedEvent(
243 'puppet-tripleo', 'stable/ocata'))
244 self.waitUntilSettled()
245
246 in_repo_conf = textwrap.dedent("""
247 - job:
248 name: puppet-unit-base
249 run: playbooks/run-unit-tests.yaml
250
251 - job:
252 name: puppet-unit-3.8
253 parent: puppet-unit-base
254 branches: ^(stable/(newton|ocata)).*$
255 vars:
256 puppet_gem_version: 3.8
257
258 - job:
259 name: puppet-something
260 run: playbooks/run-unit-tests.yaml
261
262 - project-template:
263 name: puppet-unit
264 check:
265 jobs:
266 - puppet-something
267
268 - project:
269 name: puppet-integration
270 templates:
271 - puppet-unit
272 """)
273
274 file_dict = {'.zuul.yaml': in_repo_conf}
275 A = self.fake_gerrit.addFakeChange('puppet-integration',
276 'stable/newton',
277 'A', files=file_dict)
278 B = self.fake_gerrit.addFakeChange('puppet-tripleo',
279 'stable/newton',
280 'B')
281 B.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
282 B.subject, A.data['id'])
283 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
284 self.waitUntilSettled()
285 self.assertHistory([
286 dict(name='puppet-something', result='SUCCESS',
287 changes='1,1 2,1')])
288
289
James E. Blair09998792017-10-15 18:02:18 -0700290class TestBranchVariants(ZuulTestCase):
291 tenant_config_file = 'config/branch-variants/main.yaml'
292
293 def test_branch_variants(self):
294 # Test branch variants of jobs with inheritance
295 self.executor_server.hold_jobs_in_build = True
296 # This creates a new branch with a copy of the config in master
297 self.create_branch('puppet-integration', 'stable')
298 self.fake_gerrit.addEvent(
299 self.fake_gerrit.getFakeBranchCreatedEvent(
300 'puppet-integration', 'stable'))
301 self.waitUntilSettled()
302
303 A = self.fake_gerrit.addFakeChange('puppet-integration', 'stable', 'A')
304 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
305 self.waitUntilSettled()
306
307 self.assertEqual(len(self.builds[0].parameters['pre_playbooks']), 3)
308 self.executor_server.hold_jobs_in_build = False
309 self.executor_server.release()
310 self.waitUntilSettled()
311
James E. Blairc9e77592017-10-24 09:25:23 -0700312 def test_branch_variants_reconfigure(self):
313 # Test branch variants of jobs with inheritance
314 self.executor_server.hold_jobs_in_build = True
315 # This creates a new branch with a copy of the config in master
316 self.create_branch('puppet-integration', 'stable')
317 self.fake_gerrit.addEvent(
318 self.fake_gerrit.getFakeBranchCreatedEvent(
319 'puppet-integration', 'stable'))
320 self.waitUntilSettled()
321
322 with open(os.path.join(FIXTURE_DIR,
323 'config/branch-variants/git/',
324 'puppet-integration/.zuul.yaml')) as f:
325 config = f.read()
326
327 # Push a change that triggers a dynamic reconfiguration
328 file_dict = {'.zuul.yaml': config}
329 A = self.fake_gerrit.addFakeChange('puppet-integration', 'master', 'A',
330 files=file_dict)
331 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
332 self.waitUntilSettled()
333
334 ipath = self.builds[0].parameters['zuul']['_inheritance_path']
335 for i in ipath:
336 self.log.debug("inheritance path %s", i)
337 self.assertEqual(len(ipath), 5)
338 self.executor_server.hold_jobs_in_build = False
339 self.executor_server.release()
340 self.waitUntilSettled()
341
James E. Blairc32a8352017-10-11 16:27:50 -0700342 def test_branch_variants_divergent(self):
343 # Test branches can diverge and become independent
344 self.executor_server.hold_jobs_in_build = True
345 # This creates a new branch with a copy of the config in master
346 self.create_branch('puppet-integration', 'stable')
347 self.fake_gerrit.addEvent(
348 self.fake_gerrit.getFakeBranchCreatedEvent(
349 'puppet-integration', 'stable'))
350 self.waitUntilSettled()
351
352 with open(os.path.join(FIXTURE_DIR,
353 'config/branch-variants/git/',
354 'puppet-integration/stable.zuul.yaml')) as f:
355 config = f.read()
356
357 file_dict = {'.zuul.yaml': config}
358 C = self.fake_gerrit.addFakeChange('puppet-integration', 'stable', 'C',
359 files=file_dict)
360 C.addApproval('Code-Review', 2)
361 self.fake_gerrit.addEvent(C.addApproval('Approved', 1))
362 self.waitUntilSettled()
363 self.fake_gerrit.addEvent(C.getChangeMergedEvent())
364 self.waitUntilSettled()
365
366 A = self.fake_gerrit.addFakeChange('puppet-integration', 'master', 'A')
367 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
368 self.waitUntilSettled()
369 B = self.fake_gerrit.addFakeChange('puppet-integration', 'stable', 'B')
370 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
371 self.waitUntilSettled()
372
373 self.assertEqual(self.builds[0].parameters['zuul']['jobtags'],
374 ['master'])
375
376 self.assertEqual(self.builds[1].parameters['zuul']['jobtags'],
377 ['stable'])
378
379 self.executor_server.hold_jobs_in_build = False
380 self.executor_server.release()
381 self.waitUntilSettled()
382
James E. Blair09998792017-10-15 18:02:18 -0700383
James E. Blair2a664502017-10-27 11:39:33 -0700384class TestCentralJobs(ZuulTestCase):
385 tenant_config_file = 'config/central-jobs/main.yaml'
386
387 def setUp(self):
388 super(TestCentralJobs, self).setUp()
389 self.create_branch('org/project', 'stable')
390 self.fake_gerrit.addEvent(
391 self.fake_gerrit.getFakeBranchCreatedEvent(
392 'org/project', 'stable'))
393 self.waitUntilSettled()
394
395 def _updateConfig(self, config, branch):
396 file_dict = {'.zuul.yaml': config}
397 C = self.fake_gerrit.addFakeChange('org/project', branch, 'C',
398 files=file_dict)
399 C.addApproval('Code-Review', 2)
400 self.fake_gerrit.addEvent(C.addApproval('Approved', 1))
401 self.waitUntilSettled()
402 self.fake_gerrit.addEvent(C.getChangeMergedEvent())
403 self.waitUntilSettled()
404
405 def _test_central_job_on_branch(self, branch, other_branch):
406 # Test that a job defined on a branchless repo only runs on
407 # the branch applied
408 config = textwrap.dedent(
409 """
410 - project:
411 name: org/project
412 check:
413 jobs:
414 - central-job
415 """)
416 self._updateConfig(config, branch)
417
418 A = self.fake_gerrit.addFakeChange('org/project', branch, 'A')
419 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
420 self.waitUntilSettled()
421
422 self.assertHistory([
423 dict(name='central-job', result='SUCCESS', changes='2,1')])
424
425 # No jobs should run for this change.
426 B = self.fake_gerrit.addFakeChange('org/project', other_branch, 'B')
427 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
428 self.waitUntilSettled()
429
430 self.assertHistory([
431 dict(name='central-job', result='SUCCESS', changes='2,1')])
432
433 def test_central_job_on_stable(self):
434 self._test_central_job_on_branch('master', 'stable')
435
436 def test_central_job_on_master(self):
437 self._test_central_job_on_branch('stable', 'master')
438
439 def _test_central_template_on_branch(self, branch, other_branch):
440 # Test that a project-template defined on a branchless repo
441 # only runs on the branch applied
442 config = textwrap.dedent(
443 """
444 - project:
445 name: org/project
446 templates: ['central-jobs']
447 """)
448 self._updateConfig(config, branch)
449
450 A = self.fake_gerrit.addFakeChange('org/project', branch, 'A')
451 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
452 self.waitUntilSettled()
453
454 self.assertHistory([
455 dict(name='central-job', result='SUCCESS', changes='2,1')])
456
457 # No jobs should run for this change.
458 B = self.fake_gerrit.addFakeChange('org/project', other_branch, 'B')
459 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
460 self.waitUntilSettled()
461
462 self.assertHistory([
463 dict(name='central-job', result='SUCCESS', changes='2,1')])
464
465 def test_central_template_on_stable(self):
466 self._test_central_template_on_branch('master', 'stable')
467
468 def test_central_template_on_master(self):
469 self._test_central_template_on_branch('stable', 'master')
470
471
James E. Blairff555742017-02-19 11:34:27 -0800472class TestInRepoConfig(ZuulTestCase):
James E. Blair83005782015-12-11 14:46:03 -0800473 # A temporary class to hold new tests while others are disabled
474
Tobias Henkelabf973e2017-07-28 10:07:34 +0200475 config_file = 'zuul-connections-gerrit-and-github.conf'
James E. Blair2a629ec2015-12-22 15:32:02 -0800476 tenant_config_file = 'config/in-repo/main.yaml'
James E. Blair83005782015-12-11 14:46:03 -0800477
James E. Blair83005782015-12-11 14:46:03 -0800478 def test_in_repo_config(self):
James E. Blair14abdf42015-12-09 16:11:53 -0800479 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
Tobias Henkelbf24fd12017-07-27 06:13:07 +0200480 A.addApproval('Code-Review', 2)
481 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
James E. Blair14abdf42015-12-09 16:11:53 -0800482 self.waitUntilSettled()
483 self.assertEqual(self.getJobFromHistory('project-test1').result,
484 'SUCCESS')
485 self.assertEqual(A.data['status'], 'MERGED')
486 self.assertEqual(A.reported, 2,
487 "A should report start and success")
488 self.assertIn('tenant-one-gate', A.messages[1],
489 "A should transit tenant-one gate")
James E. Blairb97ed802015-12-21 15:55:35 -0800490
James E. Blair3a098dd2017-10-04 14:37:29 -0700491 @skip("This test is useful, but not reliable")
492 def test_full_and_dynamic_reconfig(self):
493 self.executor_server.hold_jobs_in_build = True
494 in_repo_conf = textwrap.dedent(
495 """
496 - job:
497 name: project-test1
498
499 - project:
500 name: org/project
501 tenant-one-gate:
502 jobs:
503 - project-test1
504 """)
505
506 file_dict = {'.zuul.yaml': in_repo_conf}
507 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
508 files=file_dict)
509 A.addApproval('Code-Review', 2)
510 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
511 self.waitUntilSettled()
512 self.sched.reconfigure(self.config)
513 self.waitUntilSettled()
514
515 gc.collect()
516 pipelines = [obj for obj in gc.get_objects()
517 if isinstance(obj, zuul.model.Pipeline)]
518 self.assertEqual(len(pipelines), 4)
519
520 self.executor_server.hold_jobs_in_build = False
521 self.executor_server.release()
522 self.waitUntilSettled()
523
James E. Blair8b1dc3f2016-07-05 16:49:00 -0700524 def test_dynamic_config(self):
525 in_repo_conf = textwrap.dedent(
526 """
527 - job:
Tobias Henkelf02cf512017-07-21 22:55:34 +0200528 name: project-test1
529
530 - job:
James E. Blair8b1dc3f2016-07-05 16:49:00 -0700531 name: project-test2
James E. Blair2f589fe2017-10-26 12:57:41 -0700532 run: playbooks/project-test2.yaml
James E. Blair8b1dc3f2016-07-05 16:49:00 -0700533
534 - project:
535 name: org/project
536 tenant-one-gate:
537 jobs:
538 - project-test2
539 """)
540
James E. Blairc73c73a2017-01-20 15:15:15 -0800541 in_repo_playbook = textwrap.dedent(
542 """
543 - hosts: all
544 tasks: []
545 """)
546
547 file_dict = {'.zuul.yaml': in_repo_conf,
548 'playbooks/project-test2.yaml': in_repo_playbook}
James E. Blair8b1dc3f2016-07-05 16:49:00 -0700549 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
James E. Blairc73c73a2017-01-20 15:15:15 -0800550 files=file_dict)
Tobias Henkelbf24fd12017-07-27 06:13:07 +0200551 A.addApproval('Code-Review', 2)
552 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
James E. Blair8b1dc3f2016-07-05 16:49:00 -0700553 self.waitUntilSettled()
James E. Blair8b1dc3f2016-07-05 16:49:00 -0700554 self.assertEqual(A.data['status'], 'MERGED')
555 self.assertEqual(A.reported, 2,
556 "A should report start and success")
557 self.assertIn('tenant-one-gate', A.messages[1],
558 "A should transit tenant-one gate")
James E. Blair646322f2017-01-27 15:50:34 -0800559 self.assertHistory([
560 dict(name='project-test2', result='SUCCESS', changes='1,1')])
561
James E. Blairc2a5ed72017-02-20 14:12:01 -0500562 self.fake_gerrit.addEvent(A.getChangeMergedEvent())
James E. Blair7bbd7a32017-03-06 11:36:13 -0800563 self.waitUntilSettled()
James E. Blairc2a5ed72017-02-20 14:12:01 -0500564
James E. Blair646322f2017-01-27 15:50:34 -0800565 # Now that the config change is landed, it should be live for
566 # subsequent changes.
567 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
Tobias Henkelbf24fd12017-07-27 06:13:07 +0200568 B.addApproval('Code-Review', 2)
569 self.fake_gerrit.addEvent(B.addApproval('Approved', 1))
James E. Blair646322f2017-01-27 15:50:34 -0800570 self.waitUntilSettled()
571 self.assertEqual(self.getJobFromHistory('project-test2').result,
572 'SUCCESS')
573 self.assertHistory([
574 dict(name='project-test2', result='SUCCESS', changes='1,1'),
575 dict(name='project-test2', result='SUCCESS', changes='2,1')])
James E. Blairc73c73a2017-01-20 15:15:15 -0800576
James E. Blair6bc10482017-10-20 11:28:53 -0700577 def test_dynamic_template(self):
James E. Blair2a664502017-10-27 11:39:33 -0700578 # Tests that a project can't update a template in another
579 # project.
James E. Blair6bc10482017-10-20 11:28:53 -0700580 in_repo_conf = textwrap.dedent(
581 """
582 - job:
583 name: project-test1
584
585 - project-template:
586 name: common-config-template
587 check:
588 jobs:
589 - project-test1
590
591 - project:
592 name: org/project
593 templates: [common-config-template]
594 """)
595
596 file_dict = {'.zuul.yaml': in_repo_conf}
597 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
598 files=file_dict)
599 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
600 self.waitUntilSettled()
James E. Blair2a664502017-10-27 11:39:33 -0700601
602 self.assertEqual(A.patchsets[0]['approvals'][0]['value'], "-1")
603 self.assertIn('Project template common-config-template '
604 'is already defined',
605 A.messages[0],
606 "A should have failed the check pipeline")
James E. Blair6bc10482017-10-20 11:28:53 -0700607
Tobias Henkelf02cf512017-07-21 22:55:34 +0200608 def test_dynamic_config_non_existing_job(self):
609 """Test that requesting a non existent job fails"""
610 in_repo_conf = textwrap.dedent(
611 """
612 - job:
613 name: project-test1
614
615 - project:
616 name: org/project
617 check:
618 jobs:
619 - non-existent-job
620 """)
621
622 in_repo_playbook = textwrap.dedent(
623 """
624 - hosts: all
625 tasks: []
626 """)
627
628 file_dict = {'.zuul.yaml': in_repo_conf,
629 'playbooks/project-test2.yaml': in_repo_playbook}
630 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
631 files=file_dict)
632 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
633 self.waitUntilSettled()
634 self.assertEqual(A.reported, 1,
635 "A should report failure")
636 self.assertEqual(A.patchsets[0]['approvals'][0]['value'], "-1")
637 self.assertIn('Job non-existent-job not defined', A.messages[0],
638 "A should have failed the check pipeline")
639 self.assertHistory([])
640
641 def test_dynamic_config_non_existing_job_in_template(self):
642 """Test that requesting a non existent job fails"""
643 in_repo_conf = textwrap.dedent(
644 """
645 - job:
646 name: project-test1
647
648 - project-template:
649 name: test-template
650 check:
651 jobs:
652 - non-existent-job
653
654 - project:
655 name: org/project
656 templates:
657 - test-template
658 """)
659
660 in_repo_playbook = textwrap.dedent(
661 """
662 - hosts: all
663 tasks: []
664 """)
665
666 file_dict = {'.zuul.yaml': in_repo_conf,
667 'playbooks/project-test2.yaml': in_repo_playbook}
668 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
669 files=file_dict)
670 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
671 self.waitUntilSettled()
672 self.assertEqual(A.reported, 1,
673 "A should report failure")
674 self.assertEqual(A.patchsets[0]['approvals'][0]['value'], "-1")
675 self.assertIn('Job non-existent-job not defined', A.messages[0],
676 "A should have failed the check pipeline")
677 self.assertHistory([])
678
Tobias Henkel0f714002017-06-30 23:30:52 +0200679 def test_dynamic_config_new_patchset(self):
680 self.executor_server.hold_jobs_in_build = True
681
682 tenant = self.sched.abide.tenants.get('tenant-one')
683 check_pipeline = tenant.layout.pipelines['check']
684
685 in_repo_conf = textwrap.dedent(
686 """
687 - job:
Tobias Henkelf02cf512017-07-21 22:55:34 +0200688 name: project-test1
James E. Blair2f589fe2017-10-26 12:57:41 -0700689 run: playbooks/project-test1.yaml
Tobias Henkelf02cf512017-07-21 22:55:34 +0200690
691 - job:
Tobias Henkel0f714002017-06-30 23:30:52 +0200692 name: project-test2
James E. Blair2f589fe2017-10-26 12:57:41 -0700693 run: playbooks/project-test2.yaml
Tobias Henkel0f714002017-06-30 23:30:52 +0200694
695 - project:
696 name: org/project
697 check:
698 jobs:
699 - project-test2
700 """)
701
702 in_repo_playbook = textwrap.dedent(
703 """
704 - hosts: all
705 tasks: []
706 """)
707
708 file_dict = {'.zuul.yaml': in_repo_conf,
709 'playbooks/project-test2.yaml': in_repo_playbook}
710 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
711 files=file_dict)
712 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
713 self.waitUntilSettled()
714
715 items = check_pipeline.getAllItems()
716 self.assertEqual(items[0].change.number, '1')
717 self.assertEqual(items[0].change.patchset, '1')
718 self.assertTrue(items[0].live)
719
720 in_repo_conf = textwrap.dedent(
721 """
722 - job:
Tobias Henkel0ce7ec62017-07-21 22:50:17 +0200723 name: project-test1
James E. Blair2f589fe2017-10-26 12:57:41 -0700724 run: playbooks/project-test1.yaml
Tobias Henkel0ce7ec62017-07-21 22:50:17 +0200725
726 - job:
Tobias Henkel0f714002017-06-30 23:30:52 +0200727 name: project-test2
James E. Blair2f589fe2017-10-26 12:57:41 -0700728 run: playbooks/project-test2.yaml
Tobias Henkel0f714002017-06-30 23:30:52 +0200729
730 - project:
731 name: org/project
732 check:
733 jobs:
734 - project-test1
735 - project-test2
736 """)
737 file_dict = {'.zuul.yaml': in_repo_conf,
738 'playbooks/project-test2.yaml': in_repo_playbook}
739
740 A.addPatchset(files=file_dict)
741 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(2))
742
743 self.waitUntilSettled()
744
745 items = check_pipeline.getAllItems()
746 self.assertEqual(items[0].change.number, '1')
747 self.assertEqual(items[0].change.patchset, '2')
748 self.assertTrue(items[0].live)
749
750 self.executor_server.hold_jobs_in_build = False
Tobias Henkel0ce7ec62017-07-21 22:50:17 +0200751 self.executor_server.release('project-test1')
752 self.waitUntilSettled()
Tobias Henkel0f714002017-06-30 23:30:52 +0200753 self.executor_server.release()
754 self.waitUntilSettled()
755
Tobias Henkel0ce7ec62017-07-21 22:50:17 +0200756 self.assertHistory([
757 dict(name='project-test2', result='ABORTED', changes='1,1'),
758 dict(name='project-test1', result='SUCCESS', changes='1,2'),
759 dict(name='project-test2', result='SUCCESS', changes='1,2')])
760
James E. Blairff555742017-02-19 11:34:27 -0800761 def test_in_repo_branch(self):
762 in_repo_conf = textwrap.dedent(
763 """
764 - job:
Tobias Henkelf02cf512017-07-21 22:55:34 +0200765 name: project-test1
766
767 - job:
James E. Blairff555742017-02-19 11:34:27 -0800768 name: project-test2
James E. Blair2f589fe2017-10-26 12:57:41 -0700769 run: playbooks/project-test2.yaml
James E. Blairff555742017-02-19 11:34:27 -0800770
771 - project:
772 name: org/project
773 tenant-one-gate:
774 jobs:
775 - project-test2
776 """)
777
778 in_repo_playbook = textwrap.dedent(
779 """
780 - hosts: all
781 tasks: []
782 """)
783
784 file_dict = {'.zuul.yaml': in_repo_conf,
785 'playbooks/project-test2.yaml': in_repo_playbook}
786 self.create_branch('org/project', 'stable')
James E. Blair72facdc2017-08-17 10:29:12 -0700787 self.fake_gerrit.addEvent(
788 self.fake_gerrit.getFakeBranchCreatedEvent(
789 'org/project', 'stable'))
James E. Blair6069f2b2017-09-26 16:34:11 -0700790 self.waitUntilSettled()
James E. Blairff555742017-02-19 11:34:27 -0800791 A = self.fake_gerrit.addFakeChange('org/project', 'stable', 'A',
792 files=file_dict)
Tobias Henkelbf24fd12017-07-27 06:13:07 +0200793 A.addApproval('Code-Review', 2)
794 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
James E. Blairff555742017-02-19 11:34:27 -0800795 self.waitUntilSettled()
796 self.assertEqual(A.data['status'], 'MERGED')
797 self.assertEqual(A.reported, 2,
798 "A should report start and success")
799 self.assertIn('tenant-one-gate', A.messages[1],
800 "A should transit tenant-one gate")
801 self.assertHistory([
802 dict(name='project-test2', result='SUCCESS', changes='1,1')])
803 self.fake_gerrit.addEvent(A.getChangeMergedEvent())
James E. Blair7bbd7a32017-03-06 11:36:13 -0800804 self.waitUntilSettled()
James E. Blairff555742017-02-19 11:34:27 -0800805
806 # The config change should not affect master.
807 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
Tobias Henkelbf24fd12017-07-27 06:13:07 +0200808 B.addApproval('Code-Review', 2)
809 self.fake_gerrit.addEvent(B.addApproval('Approved', 1))
James E. Blairff555742017-02-19 11:34:27 -0800810 self.waitUntilSettled()
811 self.assertHistory([
812 dict(name='project-test2', result='SUCCESS', changes='1,1'),
813 dict(name='project-test1', result='SUCCESS', changes='2,1')])
814
815 # The config change should be live for further changes on
816 # stable.
817 C = self.fake_gerrit.addFakeChange('org/project', 'stable', 'C')
Tobias Henkelbf24fd12017-07-27 06:13:07 +0200818 C.addApproval('Code-Review', 2)
819 self.fake_gerrit.addEvent(C.addApproval('Approved', 1))
James E. Blairff555742017-02-19 11:34:27 -0800820 self.waitUntilSettled()
821 self.assertHistory([
822 dict(name='project-test2', result='SUCCESS', changes='1,1'),
823 dict(name='project-test1', result='SUCCESS', changes='2,1'),
824 dict(name='project-test2', result='SUCCESS', changes='3,1')])
825
James E. Blaira5a12492017-05-03 11:40:48 -0700826 def test_crd_dynamic_config_branch(self):
827 # Test that we can create a job in one repo and be able to use
828 # it from a different branch on a different repo.
829
830 self.create_branch('org/project1', 'stable')
James E. Blair72facdc2017-08-17 10:29:12 -0700831 self.fake_gerrit.addEvent(
832 self.fake_gerrit.getFakeBranchCreatedEvent(
833 'org/project1', 'stable'))
James E. Blaira5a12492017-05-03 11:40:48 -0700834
835 in_repo_conf = textwrap.dedent(
836 """
837 - job:
Tobias Henkelf02cf512017-07-21 22:55:34 +0200838 name: project-test1
839
840 - job:
James E. Blaira5a12492017-05-03 11:40:48 -0700841 name: project-test2
James E. Blair2f589fe2017-10-26 12:57:41 -0700842 run: playbooks/project-test2.yaml
James E. Blaira5a12492017-05-03 11:40:48 -0700843
844 - project:
845 name: org/project
846 check:
847 jobs:
848 - project-test2
849 """)
850
851 in_repo_playbook = textwrap.dedent(
852 """
853 - hosts: all
854 tasks: []
855 """)
856
857 file_dict = {'.zuul.yaml': in_repo_conf,
858 'playbooks/project-test2.yaml': in_repo_playbook}
859 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
860 files=file_dict)
861
862 second_repo_conf = textwrap.dedent(
863 """
864 - project:
865 name: org/project1
866 check:
867 jobs:
868 - project-test2
869 """)
870
871 second_file_dict = {'.zuul.yaml': second_repo_conf}
872 B = self.fake_gerrit.addFakeChange('org/project1', 'stable', 'B',
873 files=second_file_dict)
874 B.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
875 B.subject, A.data['id'])
876
877 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
878 self.waitUntilSettled()
879 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
880 self.waitUntilSettled()
881
882 self.assertEqual(A.reported, 1, "A should report")
883 self.assertHistory([
884 dict(name='project-test2', result='SUCCESS', changes='1,1'),
885 dict(name='project-test2', result='SUCCESS', changes='1,1 2,1'),
886 ])
887
James E. Blair97043882017-09-06 15:51:17 -0700888 def test_yaml_list_error(self):
889 in_repo_conf = textwrap.dedent(
890 """
891 job: foo
892 """)
893
894 file_dict = {'.zuul.yaml': in_repo_conf}
895 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
896 files=file_dict)
897 A.addApproval('Code-Review', 2)
898 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
899 self.waitUntilSettled()
900
901 self.assertEqual(A.data['status'], 'NEW')
902 self.assertEqual(A.reported, 1,
903 "A should report failure")
904 self.assertIn('not a list', A.messages[0],
905 "A should have a syntax error reported")
906
907 def test_yaml_dict_error(self):
908 in_repo_conf = textwrap.dedent(
909 """
910 - job
911 """)
912
913 file_dict = {'.zuul.yaml': in_repo_conf}
914 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
915 files=file_dict)
916 A.addApproval('Code-Review', 2)
917 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
918 self.waitUntilSettled()
919
920 self.assertEqual(A.data['status'], 'NEW')
921 self.assertEqual(A.reported, 1,
922 "A should report failure")
923 self.assertIn('not a dictionary', A.messages[0],
924 "A should have a syntax error reported")
925
926 def test_yaml_key_error(self):
927 in_repo_conf = textwrap.dedent(
928 """
929 - job:
930 name: project-test2
931 """)
932
933 file_dict = {'.zuul.yaml': in_repo_conf}
934 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
935 files=file_dict)
936 A.addApproval('Code-Review', 2)
937 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
938 self.waitUntilSettled()
939
940 self.assertEqual(A.data['status'], 'NEW')
941 self.assertEqual(A.reported, 1,
942 "A should report failure")
943 self.assertIn('has more than one key', A.messages[0],
944 "A should have a syntax error reported")
945
946 def test_yaml_unknown_error(self):
947 in_repo_conf = textwrap.dedent(
948 """
949 - foobar:
950 foo: bar
951 """)
952
953 file_dict = {'.zuul.yaml': in_repo_conf}
954 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
955 files=file_dict)
956 A.addApproval('Code-Review', 2)
957 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
958 self.waitUntilSettled()
959
960 self.assertEqual(A.data['status'], 'NEW')
961 self.assertEqual(A.reported, 1,
962 "A should report failure")
963 self.assertIn('not recognized', A.messages[0],
964 "A should have a syntax error reported")
965
James E. Blair149b69c2017-03-02 10:48:16 -0800966 def test_untrusted_syntax_error(self):
James E. Blaire53250c2017-03-01 14:34:36 -0800967 in_repo_conf = textwrap.dedent(
968 """
969 - job:
970 name: project-test2
971 foo: error
972 """)
973
974 file_dict = {'.zuul.yaml': in_repo_conf}
975 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
976 files=file_dict)
Tobias Henkelbf24fd12017-07-27 06:13:07 +0200977 A.addApproval('Code-Review', 2)
978 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
James E. Blaire53250c2017-03-01 14:34:36 -0800979 self.waitUntilSettled()
980
981 self.assertEqual(A.data['status'], 'NEW')
Tobias Henkel9842bd72017-05-16 13:40:03 +0200982 self.assertEqual(A.reported, 1,
983 "A should report failure")
984 self.assertIn('syntax error', A.messages[0],
James E. Blaire53250c2017-03-01 14:34:36 -0800985 "A should have a syntax error reported")
986
James E. Blair149b69c2017-03-02 10:48:16 -0800987 def test_trusted_syntax_error(self):
988 in_repo_conf = textwrap.dedent(
989 """
990 - job:
991 name: project-test2
992 foo: error
993 """)
994
995 file_dict = {'zuul.yaml': in_repo_conf}
996 A = self.fake_gerrit.addFakeChange('common-config', 'master', 'A',
997 files=file_dict)
Tobias Henkelbf24fd12017-07-27 06:13:07 +0200998 A.addApproval('Code-Review', 2)
999 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
James E. Blair149b69c2017-03-02 10:48:16 -08001000 self.waitUntilSettled()
1001
1002 self.assertEqual(A.data['status'], 'NEW')
Tobias Henkel9842bd72017-05-16 13:40:03 +02001003 self.assertEqual(A.reported, 1,
1004 "A should report failure")
1005 self.assertIn('syntax error', A.messages[0],
James E. Blair149b69c2017-03-02 10:48:16 -08001006 "A should have a syntax error reported")
1007
James E. Blair6f140c72017-03-03 10:32:07 -08001008 def test_untrusted_yaml_error(self):
1009 in_repo_conf = textwrap.dedent(
1010 """
1011 - job:
1012 foo: error
1013 """)
1014
1015 file_dict = {'.zuul.yaml': in_repo_conf}
1016 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
1017 files=file_dict)
Tobias Henkelbf24fd12017-07-27 06:13:07 +02001018 A.addApproval('Code-Review', 2)
1019 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
James E. Blair6f140c72017-03-03 10:32:07 -08001020 self.waitUntilSettled()
1021
1022 self.assertEqual(A.data['status'], 'NEW')
Tobias Henkel9842bd72017-05-16 13:40:03 +02001023 self.assertEqual(A.reported, 1,
1024 "A should report failure")
1025 self.assertIn('syntax error', A.messages[0],
James E. Blair6f140c72017-03-03 10:32:07 -08001026 "A should have a syntax error reported")
1027
James E. Blairdb04e6a2017-05-03 14:49:36 -07001028 def test_untrusted_shadow_error(self):
1029 in_repo_conf = textwrap.dedent(
1030 """
1031 - job:
1032 name: common-config-test
1033 """)
1034
1035 file_dict = {'.zuul.yaml': in_repo_conf}
1036 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
1037 files=file_dict)
Tobias Henkelbf24fd12017-07-27 06:13:07 +02001038 A.addApproval('Code-Review', 2)
1039 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
James E. Blairdb04e6a2017-05-03 14:49:36 -07001040 self.waitUntilSettled()
1041
1042 self.assertEqual(A.data['status'], 'NEW')
Tobias Henkel9842bd72017-05-16 13:40:03 +02001043 self.assertEqual(A.reported, 1,
1044 "A should report failure")
1045 self.assertIn('not permitted to shadow', A.messages[0],
James E. Blairdb04e6a2017-05-03 14:49:36 -07001046 "A should have a syntax error reported")
1047
James E. Blaird5656ad2017-06-02 14:29:41 -07001048 def test_untrusted_pipeline_error(self):
1049 in_repo_conf = textwrap.dedent(
1050 """
1051 - pipeline:
1052 name: test
1053 """)
1054
1055 file_dict = {'.zuul.yaml': in_repo_conf}
1056 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
1057 files=file_dict)
Tobias Henkelbf24fd12017-07-27 06:13:07 +02001058 A.addApproval('Code-Review', 2)
1059 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
James E. Blaird5656ad2017-06-02 14:29:41 -07001060 self.waitUntilSettled()
1061
1062 self.assertEqual(A.data['status'], 'NEW')
1063 self.assertEqual(A.reported, 1,
1064 "A should report failure")
1065 self.assertIn('Pipelines may not be defined', A.messages[0],
1066 "A should have a syntax error reported")
1067
1068 def test_untrusted_project_error(self):
1069 in_repo_conf = textwrap.dedent(
1070 """
1071 - project:
1072 name: org/project1
1073 """)
1074
1075 file_dict = {'.zuul.yaml': in_repo_conf}
1076 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
1077 files=file_dict)
Tobias Henkelbf24fd12017-07-27 06:13:07 +02001078 A.addApproval('Code-Review', 2)
1079 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
James E. Blaird5656ad2017-06-02 14:29:41 -07001080 self.waitUntilSettled()
1081
1082 self.assertEqual(A.data['status'], 'NEW')
1083 self.assertEqual(A.reported, 1,
1084 "A should report failure")
1085 self.assertIn('the only project definition permitted', A.messages[0],
1086 "A should have a syntax error reported")
1087
James E. Blairf03173b2017-10-10 10:46:43 -07001088 def test_untrusted_depends_on_trusted(self):
1089 with open(os.path.join(FIXTURE_DIR,
1090 'config/in-repo/git/',
1091 'common-config/zuul.yaml')) as f:
1092 common_config = f.read()
1093
1094 common_config += textwrap.dedent(
1095 """
1096 - job:
1097 name: project-test9
1098 """)
1099
1100 file_dict = {'zuul.yaml': common_config}
1101 A = self.fake_gerrit.addFakeChange('common-config', 'master', 'A',
1102 files=file_dict)
1103 in_repo_conf = textwrap.dedent(
1104 """
1105 - job:
1106 name: project-test1
1107 - project:
1108 name: org/project
1109 check:
1110 jobs:
1111 - project-test9
1112 """)
1113
1114 file_dict = {'zuul.yaml': in_repo_conf}
1115 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B',
1116 files=file_dict)
1117 B.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
1118 B.subject, A.data['id'])
1119 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
1120 self.waitUntilSettled()
1121
1122 self.assertEqual(B.data['status'], 'NEW')
1123 self.assertEqual(B.reported, 1,
1124 "B should report failure")
1125 self.assertIn('depends on a change to a config project',
1126 B.messages[0],
1127 "A should have a syntax error reported")
1128
James E. Blaire64b0e42017-06-08 11:23:34 -07001129 def test_duplicate_node_error(self):
1130 in_repo_conf = textwrap.dedent(
1131 """
1132 - nodeset:
1133 name: duplicate
1134 nodes:
1135 - name: compute
James E. Blair16d96a02017-06-08 11:32:56 -07001136 label: foo
James E. Blaire64b0e42017-06-08 11:23:34 -07001137 - name: compute
James E. Blair16d96a02017-06-08 11:32:56 -07001138 label: foo
James E. Blaire64b0e42017-06-08 11:23:34 -07001139 """)
1140
1141 file_dict = {'.zuul.yaml': in_repo_conf}
1142 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
1143 files=file_dict)
Tobias Henkelbf24fd12017-07-27 06:13:07 +02001144 A.addApproval('Code-Review', 2)
1145 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
James E. Blaire64b0e42017-06-08 11:23:34 -07001146 self.waitUntilSettled()
1147
1148 self.assertEqual(A.data['status'], 'NEW')
1149 self.assertEqual(A.reported, 1,
1150 "A should report failure")
1151 self.assertIn('appears multiple times', A.messages[0],
1152 "A should have a syntax error reported")
1153
1154 def test_duplicate_group_error(self):
1155 in_repo_conf = textwrap.dedent(
1156 """
1157 - nodeset:
1158 name: duplicate
1159 nodes:
1160 - name: compute
James E. Blair16d96a02017-06-08 11:32:56 -07001161 label: foo
James E. Blaire64b0e42017-06-08 11:23:34 -07001162 groups:
1163 - name: group
1164 nodes: compute
1165 - name: group
1166 nodes: compute
1167 """)
1168
1169 file_dict = {'.zuul.yaml': in_repo_conf}
1170 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
1171 files=file_dict)
Tobias Henkelbf24fd12017-07-27 06:13:07 +02001172 A.addApproval('Code-Review', 2)
1173 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
James E. Blaire64b0e42017-06-08 11:23:34 -07001174 self.waitUntilSettled()
1175
1176 self.assertEqual(A.data['status'], 'NEW')
1177 self.assertEqual(A.reported, 1,
1178 "A should report failure")
1179 self.assertIn('appears multiple times', A.messages[0],
1180 "A should have a syntax error reported")
1181
James E. Blair4ae399f2017-09-20 17:15:09 -07001182 def test_secret_not_found_error(self):
1183 in_repo_conf = textwrap.dedent(
1184 """
1185 - job:
1186 name: test
1187 secrets: does-not-exist
1188 """)
1189
1190 file_dict = {'.zuul.yaml': in_repo_conf}
1191 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
1192 files=file_dict)
1193 A.addApproval('Code-Review', 2)
1194 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
1195 self.waitUntilSettled()
1196
1197 self.assertEqual(A.data['status'], 'NEW')
1198 self.assertEqual(A.reported, 1,
1199 "A should report failure")
1200 self.assertIn('secret "does-not-exist" was not found', A.messages[0],
1201 "A should have a syntax error reported")
1202
1203 def test_nodeset_not_found_error(self):
1204 in_repo_conf = textwrap.dedent(
1205 """
1206 - job:
1207 name: test
1208 nodeset: does-not-exist
1209 """)
1210
1211 file_dict = {'.zuul.yaml': in_repo_conf}
1212 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
1213 files=file_dict)
1214 A.addApproval('Code-Review', 2)
1215 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
1216 self.waitUntilSettled()
1217
1218 self.assertEqual(A.data['status'], 'NEW')
1219 self.assertEqual(A.reported, 1,
1220 "A should report failure")
1221 self.assertIn('nodeset "does-not-exist" was not found', A.messages[0],
1222 "A should have a syntax error reported")
1223
James E. Blair89e25eb2017-09-26 09:11:31 -07001224 def test_template_not_found_error(self):
1225 in_repo_conf = textwrap.dedent(
1226 """
1227 - job:
1228 name: project-test1
1229 - project:
1230 name: org/project
1231 templates:
1232 - does-not-exist
1233 """)
1234
1235 file_dict = {'.zuul.yaml': in_repo_conf}
1236 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
1237 files=file_dict)
1238 A.addApproval('Code-Review', 2)
1239 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
1240 self.waitUntilSettled()
1241
1242 self.assertEqual(A.data['status'], 'NEW')
1243 self.assertEqual(A.reported, 1,
1244 "A should report failure")
1245 self.assertIn('project template "does-not-exist" was not found',
1246 A.messages[0],
1247 "A should have a syntax error reported")
1248
Monty Taylor8be3c0c2017-10-06 10:37:37 -05001249 def test_job_list_in_project_template_not_dict_error(self):
1250 in_repo_conf = textwrap.dedent(
1251 """
1252 - job:
1253 name: project-test1
1254 - project-template:
1255 name: some-jobs
1256 check:
1257 jobs:
1258 - project-test1:
1259 - required-projects:
1260 org/project2
1261 """)
1262
1263 file_dict = {'.zuul.yaml': in_repo_conf}
1264 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
1265 files=file_dict)
1266 A.addApproval('Code-Review', 2)
1267 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
1268 self.waitUntilSettled()
1269
1270 self.assertEqual(A.data['status'], 'NEW')
1271 self.assertEqual(A.reported, 1,
1272 "A should report failure")
1273 self.assertIn('expected str for dictionary value',
1274 A.messages[0], "A should have a syntax error reported")
1275
1276 def test_job_list_in_project_not_dict_error(self):
1277 in_repo_conf = textwrap.dedent(
1278 """
1279 - job:
1280 name: project-test1
1281 - project:
1282 name: org/project1
1283 check:
1284 jobs:
1285 - project-test1:
1286 - required-projects:
1287 org/project2
1288 """)
1289
1290 file_dict = {'.zuul.yaml': in_repo_conf}
1291 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
1292 files=file_dict)
1293 A.addApproval('Code-Review', 2)
1294 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
1295 self.waitUntilSettled()
1296
1297 self.assertEqual(A.data['status'], 'NEW')
1298 self.assertEqual(A.reported, 1,
1299 "A should report failure")
1300 self.assertIn('expected str for dictionary value',
1301 A.messages[0], "A should have a syntax error reported")
1302
James E. Blair1235f142017-10-07 09:11:43 -07001303 def test_project_template(self):
1304 # Tests that a project template is not modified when used, and
1305 # can therefore be used in subsequent reconfigurations.
1306 in_repo_conf = textwrap.dedent(
1307 """
1308 - job:
1309 name: project-test1
James E. Blair2f589fe2017-10-26 12:57:41 -07001310 run: playbooks/project-test1.yaml
James E. Blair1235f142017-10-07 09:11:43 -07001311 - project-template:
1312 name: some-jobs
1313 tenant-one-gate:
1314 jobs:
1315 - project-test1:
1316 required-projects:
1317 - org/project1
1318 - project:
1319 name: org/project
1320 templates:
1321 - some-jobs
1322 """)
1323
1324 file_dict = {'.zuul.yaml': in_repo_conf}
1325 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
1326 files=file_dict)
1327 A.addApproval('Code-Review', 2)
1328 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
1329 self.waitUntilSettled()
1330 self.assertEqual(A.data['status'], 'MERGED')
1331 self.fake_gerrit.addEvent(A.getChangeMergedEvent())
1332 self.waitUntilSettled()
1333 in_repo_conf = textwrap.dedent(
1334 """
1335 - project:
1336 name: org/project1
1337 templates:
1338 - some-jobs
1339 """)
1340 file_dict = {'.zuul.yaml': in_repo_conf}
1341 B = self.fake_gerrit.addFakeChange('org/project1', 'master', 'B',
1342 files=file_dict)
1343 B.addApproval('Code-Review', 2)
1344 self.fake_gerrit.addEvent(B.addApproval('Approved', 1))
1345 self.waitUntilSettled()
1346 self.assertEqual(B.data['status'], 'MERGED')
1347
James E. Blairbccdfcf2017-10-07 13:37:26 -07001348 def test_job_remove_add(self):
1349 # Tests that a job can be removed from one repo and added in another.
1350 # First, remove the current config for project1 since it
1351 # references the job we want to remove.
1352 file_dict = {'.zuul.yaml': None}
1353 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A',
1354 files=file_dict)
1355 A.setMerged()
1356 self.fake_gerrit.addEvent(A.getChangeMergedEvent())
1357 self.waitUntilSettled()
1358 # Then propose a change to delete the job from one repo...
1359 file_dict = {'.zuul.yaml': None}
1360 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B',
1361 files=file_dict)
1362 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
1363 self.waitUntilSettled()
1364 # ...and a second that depends on it that adds it to another repo.
1365 in_repo_conf = textwrap.dedent(
1366 """
1367 - job:
1368 name: project-test1
James E. Blair2f589fe2017-10-26 12:57:41 -07001369 run: playbooks/project-test1.yaml
James E. Blairbccdfcf2017-10-07 13:37:26 -07001370
1371 - project:
1372 name: org/project1
1373 check:
1374 jobs:
1375 - project-test1
1376 """)
1377 in_repo_playbook = textwrap.dedent(
1378 """
1379 - hosts: all
1380 tasks: []
1381 """)
1382 file_dict = {'.zuul.yaml': in_repo_conf,
1383 'playbooks/project-test1.yaml': in_repo_playbook}
1384 C = self.fake_gerrit.addFakeChange('org/project1', 'master', 'C',
1385 files=file_dict,
1386 parent='refs/changes/1/1/1')
1387 C.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
1388 C.subject, B.data['id'])
1389 self.fake_gerrit.addEvent(C.getPatchsetCreatedEvent(1))
1390 self.waitUntilSettled()
1391 self.assertHistory([
1392 dict(name='project-test1', result='SUCCESS', changes='2,1 3,1'),
1393 ], ordered=False)
1394
James E. Blair09f9ffe2017-07-11 15:30:25 -07001395 def test_multi_repo(self):
1396 downstream_repo_conf = textwrap.dedent(
1397 """
1398 - project:
1399 name: org/project1
1400 tenant-one-gate:
1401 jobs:
1402 - project-test1
1403
1404 - job:
1405 name: project1-test1
1406 parent: project-test1
1407 """)
1408
1409 file_dict = {'.zuul.yaml': downstream_repo_conf}
1410 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A',
1411 files=file_dict)
Tobias Henkelbf24fd12017-07-27 06:13:07 +02001412 A.addApproval('Code-Review', 2)
1413 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
James E. Blair09f9ffe2017-07-11 15:30:25 -07001414 self.waitUntilSettled()
1415
1416 self.assertEqual(A.data['status'], 'MERGED')
1417 self.fake_gerrit.addEvent(A.getChangeMergedEvent())
1418 self.waitUntilSettled()
1419
1420 upstream_repo_conf = textwrap.dedent(
1421 """
1422 - job:
1423 name: project-test1
James E. Blair2f589fe2017-10-26 12:57:41 -07001424 run: playbooks/project-test1.yaml
James E. Blair09f9ffe2017-07-11 15:30:25 -07001425
1426 - job:
1427 name: project-test2
1428
1429 - project:
1430 name: org/project
1431 tenant-one-gate:
1432 jobs:
1433 - project-test1
1434 """)
1435
1436 file_dict = {'.zuul.yaml': upstream_repo_conf}
1437 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B',
1438 files=file_dict)
Tobias Henkelbf24fd12017-07-27 06:13:07 +02001439 B.addApproval('Code-Review', 2)
1440 self.fake_gerrit.addEvent(B.addApproval('Approved', 1))
James E. Blair09f9ffe2017-07-11 15:30:25 -07001441 self.waitUntilSettled()
1442
1443 self.assertEqual(B.data['status'], 'MERGED')
1444 self.fake_gerrit.addEvent(B.getChangeMergedEvent())
1445 self.waitUntilSettled()
1446
1447 tenant = self.sched.abide.tenants.get('tenant-one')
1448 # Ensure the latest change is reflected in the config; if it
1449 # isn't this will raise an exception.
1450 tenant.layout.getJob('project-test2')
1451
James E. Blair332636e2017-09-05 10:14:35 -07001452 def test_pipeline_error(self):
1453 with open(os.path.join(FIXTURE_DIR,
1454 'config/in-repo/git/',
1455 'common-config/zuul.yaml')) as f:
1456 base_common_config = f.read()
1457
1458 in_repo_conf_A = textwrap.dedent(
1459 """
1460 - pipeline:
1461 name: periodic
1462 foo: error
1463 """)
1464
1465 file_dict = {'zuul.yaml': None,
1466 'zuul.d/main.yaml': base_common_config,
1467 'zuul.d/test1.yaml': in_repo_conf_A}
1468 A = self.fake_gerrit.addFakeChange('common-config', 'master', 'A',
1469 files=file_dict)
1470 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
1471 self.waitUntilSettled()
1472 self.assertEqual(A.reported, 1,
1473 "A should report failure")
1474 self.assertIn('syntax error',
1475 A.messages[0],
1476 "A should have an error reported")
1477
1478 def test_change_series_error(self):
1479 with open(os.path.join(FIXTURE_DIR,
1480 'config/in-repo/git/',
1481 'common-config/zuul.yaml')) as f:
1482 base_common_config = f.read()
1483
1484 in_repo_conf_A = textwrap.dedent(
1485 """
1486 - pipeline:
1487 name: periodic
1488 foo: error
1489 """)
1490
1491 file_dict = {'zuul.yaml': None,
1492 'zuul.d/main.yaml': base_common_config,
1493 'zuul.d/test1.yaml': in_repo_conf_A}
1494 A = self.fake_gerrit.addFakeChange('common-config', 'master', 'A',
1495 files=file_dict)
1496
1497 in_repo_conf_B = textwrap.dedent(
1498 """
1499 - job:
1500 name: project-test2
1501 foo: error
1502 """)
1503
1504 file_dict = {'zuul.yaml': None,
1505 'zuul.d/main.yaml': base_common_config,
1506 'zuul.d/test1.yaml': in_repo_conf_A,
1507 'zuul.d/test2.yaml': in_repo_conf_B}
1508 B = self.fake_gerrit.addFakeChange('common-config', 'master', 'B',
1509 files=file_dict)
1510 B.setDependsOn(A, 1)
1511 C = self.fake_gerrit.addFakeChange('common-config', 'master', 'C')
1512 C.setDependsOn(B, 1)
1513 self.fake_gerrit.addEvent(C.getPatchsetCreatedEvent(1))
1514 self.waitUntilSettled()
1515
1516 self.assertEqual(C.reported, 1,
1517 "C should report failure")
1518 self.assertIn('depends on a change that failed to merge',
1519 C.messages[0],
1520 "C should have an error reported")
1521
James E. Blairc73c73a2017-01-20 15:15:15 -08001522
James E. Blairc9455002017-09-06 09:22:19 -07001523class TestInRepoJoin(ZuulTestCase):
1524 # In this config, org/project is not a member of any pipelines, so
1525 # that we may test the changes that cause it to join them.
1526
1527 tenant_config_file = 'config/in-repo-join/main.yaml'
1528
1529 def test_dynamic_dependent_pipeline(self):
1530 # Test dynamically adding a project to a
1531 # dependent pipeline for the first time
1532 self.executor_server.hold_jobs_in_build = True
1533
1534 tenant = self.sched.abide.tenants.get('tenant-one')
1535 gate_pipeline = tenant.layout.pipelines['gate']
1536
1537 in_repo_conf = textwrap.dedent(
1538 """
1539 - job:
1540 name: project-test1
James E. Blair2f589fe2017-10-26 12:57:41 -07001541 run: playbooks/project-test1.yaml
James E. Blairc9455002017-09-06 09:22:19 -07001542
1543 - job:
1544 name: project-test2
James E. Blair2f589fe2017-10-26 12:57:41 -07001545 run: playbooks/project-test2.yaml
James E. Blairc9455002017-09-06 09:22:19 -07001546
1547 - project:
1548 name: org/project
1549 gate:
1550 jobs:
1551 - project-test2
1552 """)
1553
1554 in_repo_playbook = textwrap.dedent(
1555 """
1556 - hosts: all
1557 tasks: []
1558 """)
1559
1560 file_dict = {'.zuul.yaml': in_repo_conf,
1561 'playbooks/project-test2.yaml': in_repo_playbook}
1562 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
1563 files=file_dict)
1564 A.addApproval('Code-Review', 2)
1565 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
1566 self.waitUntilSettled()
1567
1568 items = gate_pipeline.getAllItems()
1569 self.assertEqual(items[0].change.number, '1')
1570 self.assertEqual(items[0].change.patchset, '1')
1571 self.assertTrue(items[0].live)
1572
1573 self.executor_server.hold_jobs_in_build = False
1574 self.executor_server.release()
1575 self.waitUntilSettled()
1576
1577 # Make sure the dynamic queue got cleaned up
1578 self.assertEqual(gate_pipeline.queues, [])
1579
1580 def test_dynamic_dependent_pipeline_failure(self):
1581 # Test that a change behind a failing change adding a project
1582 # to a dependent pipeline is dequeued.
1583 self.executor_server.hold_jobs_in_build = True
1584
1585 in_repo_conf = textwrap.dedent(
1586 """
1587 - job:
1588 name: project-test1
James E. Blair2f589fe2017-10-26 12:57:41 -07001589 run: playbooks/project-test1.yaml
James E. Blairc9455002017-09-06 09:22:19 -07001590
1591 - project:
1592 name: org/project
1593 gate:
1594 jobs:
1595 - project-test1
1596 """)
1597
1598 file_dict = {'.zuul.yaml': in_repo_conf}
1599 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
1600 files=file_dict)
1601 self.executor_server.failJob('project-test1', A)
1602 A.addApproval('Code-Review', 2)
1603 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
1604 self.waitUntilSettled()
1605
1606 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
1607 B.addApproval('Code-Review', 2)
1608 self.fake_gerrit.addEvent(B.addApproval('Approved', 1))
1609 self.waitUntilSettled()
1610
James E. Blair3490c5d2017-09-07 08:33:23 -07001611 self.orderedRelease()
James E. Blairc9455002017-09-06 09:22:19 -07001612 self.waitUntilSettled()
1613 self.assertEqual(A.reported, 2,
1614 "A should report start and failure")
1615 self.assertEqual(A.data['status'], 'NEW')
1616 self.assertEqual(B.reported, 1,
1617 "B should report start")
1618 self.assertHistory([
1619 dict(name='project-test1', result='FAILURE', changes='1,1'),
James E. Blair3490c5d2017-09-07 08:33:23 -07001620 dict(name='project-test1', result='ABORTED', changes='1,1 2,1'),
James E. Blairc9455002017-09-06 09:22:19 -07001621 ], ordered=False)
1622
James E. Blair0af198f2017-09-06 09:52:35 -07001623 def test_dynamic_dependent_pipeline_absent(self):
1624 # Test that a series of dependent changes don't report merge
1625 # failures to a pipeline they aren't in.
1626 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1627 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
1628 B.setDependsOn(A, 1)
1629
1630 A.addApproval('Code-Review', 2)
1631 A.addApproval('Approved', 1)
1632 B.addApproval('Code-Review', 2)
1633 self.fake_gerrit.addEvent(B.addApproval('Approved', 1))
1634 self.waitUntilSettled()
1635 self.assertEqual(A.reported, 0,
1636 "A should not report")
1637 self.assertEqual(A.data['status'], 'NEW')
1638 self.assertEqual(B.reported, 0,
1639 "B should not report")
1640 self.assertEqual(B.data['status'], 'NEW')
1641 self.assertHistory([])
1642
James E. Blairc9455002017-09-06 09:22:19 -07001643
James E. Blairc73c73a2017-01-20 15:15:15 -08001644class TestAnsible(AnsibleZuulTestCase):
1645 # A temporary class to hold new tests while others are disabled
1646
1647 tenant_config_file = 'config/ansible/main.yaml'
1648
1649 def test_playbook(self):
Jamie Lennox7655b552017-03-17 12:33:38 +11001650 # Keep the jobdir around so we can inspect contents if an
1651 # assert fails.
1652 self.executor_server.keep_jobdir = True
1653 # Output extra ansible info so we might see errors.
1654 self.executor_server.verbose = True
1655 # Add a site variables file, used by check-vars
1656 path = os.path.join(FIXTURE_DIR, 'config', 'ansible',
1657 'variables.yaml')
1658 self.config.set('executor', 'variables', path)
James E. Blairc73c73a2017-01-20 15:15:15 -08001659 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1660 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
1661 self.waitUntilSettled()
Tobias Henkel077f2f32017-05-30 20:16:46 +02001662 build_timeout = self.getJobFromHistory('timeout')
Jamie Lennox7655b552017-03-17 12:33:38 +11001663 with self.jobLog(build_timeout):
1664 self.assertEqual(build_timeout.result, 'TIMED_OUT')
Tobias Henkel077f2f32017-05-30 20:16:46 +02001665 build_faillocal = self.getJobFromHistory('faillocal')
Jamie Lennox7655b552017-03-17 12:33:38 +11001666 with self.jobLog(build_faillocal):
1667 self.assertEqual(build_faillocal.result, 'FAILURE')
Tobias Henkel077f2f32017-05-30 20:16:46 +02001668 build_failpost = self.getJobFromHistory('failpost')
Jamie Lennox7655b552017-03-17 12:33:38 +11001669 with self.jobLog(build_failpost):
1670 self.assertEqual(build_failpost.result, 'POST_FAILURE')
Tobias Henkel077f2f32017-05-30 20:16:46 +02001671 build_check_vars = self.getJobFromHistory('check-vars')
Jamie Lennox7655b552017-03-17 12:33:38 +11001672 with self.jobLog(build_check_vars):
1673 self.assertEqual(build_check_vars.result, 'SUCCESS')
Monty Tayloraff8b402017-08-16 18:40:41 -05001674 build_check_secret_names = self.getJobFromHistory('check-secret-names')
1675 with self.jobLog(build_check_secret_names):
1676 self.assertEqual(build_check_secret_names.result, 'SUCCESS')
Tobias Henkel077f2f32017-05-30 20:16:46 +02001677 build_hello = self.getJobFromHistory('hello-world')
Jamie Lennox7655b552017-03-17 12:33:38 +11001678 with self.jobLog(build_hello):
1679 self.assertEqual(build_hello.result, 'SUCCESS')
Tobias Henkel077f2f32017-05-30 20:16:46 +02001680 build_python27 = self.getJobFromHistory('python27')
Jamie Lennox7655b552017-03-17 12:33:38 +11001681 with self.jobLog(build_python27):
1682 self.assertEqual(build_python27.result, 'SUCCESS')
1683 flag_path = os.path.join(self.test_root,
1684 build_python27.uuid + '.flag')
1685 self.assertTrue(os.path.exists(flag_path))
1686 copied_path = os.path.join(self.test_root, build_python27.uuid +
1687 '.copied')
1688 self.assertTrue(os.path.exists(copied_path))
1689 failed_path = os.path.join(self.test_root, build_python27.uuid +
1690 '.failed')
1691 self.assertFalse(os.path.exists(failed_path))
1692 pre_flag_path = os.path.join(self.test_root, build_python27.uuid +
1693 '.pre.flag')
1694 self.assertTrue(os.path.exists(pre_flag_path))
1695 post_flag_path = os.path.join(self.test_root, build_python27.uuid +
1696 '.post.flag')
1697 self.assertTrue(os.path.exists(post_flag_path))
1698 bare_role_flag_path = os.path.join(self.test_root,
1699 build_python27.uuid +
1700 '.bare-role.flag')
1701 self.assertTrue(os.path.exists(bare_role_flag_path))
1702 secrets_path = os.path.join(self.test_root,
1703 build_python27.uuid + '.secrets')
1704 with open(secrets_path) as f:
1705 self.assertEqual(f.read(), "test-username test-password")
James E. Blairb9c0d772017-03-03 14:34:49 -08001706
Jamie Lennox7655b552017-03-17 12:33:38 +11001707 msg = A.messages[0]
1708 success = "{} https://success.example.com/zuul-logs/{}"
1709 fail = "{} https://failure.example.com/zuul-logs/{}"
1710 self.assertIn(success.format("python27", build_python27.uuid), msg)
1711 self.assertIn(fail.format("faillocal", build_faillocal.uuid), msg)
1712 self.assertIn(success.format("check-vars",
1713 build_check_vars.uuid), msg)
1714 self.assertIn(success.format("hello-world", build_hello.uuid), msg)
1715 self.assertIn(fail.format("timeout", build_timeout.uuid), msg)
1716 self.assertIn(fail.format("failpost", build_failpost.uuid), msg)
Tobias Henkel077f2f32017-05-30 20:16:46 +02001717
James E. Blairabbaa6f2017-04-06 16:11:44 -07001718 def _add_job(self, job_name):
1719 conf = textwrap.dedent(
1720 """
1721 - job:
1722 name: %s
James E. Blair2f589fe2017-10-26 12:57:41 -07001723 run: playbooks/%s.yaml
James E. Blairabbaa6f2017-04-06 16:11:44 -07001724
1725 - project:
1726 name: org/plugin-project
1727 check:
1728 jobs:
1729 - %s
James E. Blair2f589fe2017-10-26 12:57:41 -07001730 """ % (job_name, job_name, job_name))
James E. Blairabbaa6f2017-04-06 16:11:44 -07001731
1732 file_dict = {'.zuul.yaml': conf}
1733 A = self.fake_gerrit.addFakeChange('org/plugin-project', 'master', 'A',
1734 files=file_dict)
1735 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
1736 self.waitUntilSettled()
1737
1738 def test_plugins(self):
1739 # Keep the jobdir around so we can inspect contents if an
1740 # assert fails.
1741 self.executor_server.keep_jobdir = True
1742 # Output extra ansible info so we might see errors.
1743 self.executor_server.verbose = True
1744
1745 count = 0
1746 plugin_tests = [
1747 ('passwd', 'FAILURE'),
1748 ('cartesian', 'SUCCESS'),
1749 ('consul_kv', 'FAILURE'),
1750 ('credstash', 'FAILURE'),
1751 ('csvfile_good', 'SUCCESS'),
1752 ('csvfile_bad', 'FAILURE'),
Monty Taylor93ad2212017-08-02 14:59:50 -05001753 ('uri_bad_path', 'FAILURE'),
1754 ('uri_bad_scheme', 'FAILURE'),
Monty Taylor788a40e2017-08-02 16:14:05 -05001755 ('block_local_override', 'FAILURE'),
Monty Taylor8da768f2017-08-31 14:15:35 -05001756 ('file_local_good', 'SUCCESS'),
1757 ('file_local_bad', 'FAILURE'),
James E. Blairabbaa6f2017-04-06 16:11:44 -07001758 ]
1759 for job_name, result in plugin_tests:
1760 count += 1
1761 self._add_job(job_name)
1762
1763 job = self.getJobFromHistory(job_name)
1764 with self.jobLog(job):
1765 self.assertEqual(count, len(self.history))
1766 build = self.history[-1]
1767 self.assertEqual(build.result, result)
1768
1769 # TODOv3(jeblair): parse the ansible output and verify we're
1770 # getting the exception we expect.
1771
James E. Blairb9c0d772017-03-03 14:34:49 -08001772
James E. Blaira4d4eef2017-06-30 14:49:17 -07001773class TestPrePlaybooks(AnsibleZuulTestCase):
1774 # A temporary class to hold new tests while others are disabled
1775
1776 tenant_config_file = 'config/pre-playbook/main.yaml'
1777
1778 def test_pre_playbook_fail(self):
1779 # Test that we run the post playbooks (but not the actual
1780 # playbook) when a pre-playbook fails.
1781 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1782 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
1783 self.waitUntilSettled()
1784 build = self.getJobFromHistory('python27')
1785 self.assertIsNone(build.result)
1786 self.assertIn('RETRY_LIMIT', A.messages[0])
1787 flag_path = os.path.join(self.test_root, build.uuid +
1788 '.main.flag')
1789 self.assertFalse(os.path.exists(flag_path))
1790 pre_flag_path = os.path.join(self.test_root, build.uuid +
1791 '.pre.flag')
1792 self.assertFalse(os.path.exists(pre_flag_path))
1793 post_flag_path = os.path.join(self.test_root, build.uuid +
1794 '.post.flag')
James E. Blair21037782017-07-19 11:56:55 -07001795 self.assertTrue(os.path.exists(post_flag_path),
1796 "The file %s should exist" % post_flag_path)
James E. Blaira4d4eef2017-06-30 14:49:17 -07001797
1798
James E. Blairbacbb882017-10-17 09:48:23 -07001799class TestPostPlaybooks(AnsibleZuulTestCase):
1800 tenant_config_file = 'config/post-playbook/main.yaml'
1801
1802 def test_post_playbook_abort(self):
1803 # Test that when we abort a job in the post playbook, that we
1804 # don't send back POST_FAILURE.
1805 self.executor_server.verbose = True
1806 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1807 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
1808
1809 while not len(self.builds):
1810 time.sleep(0.1)
1811 build = self.builds[0]
1812
1813 post_start = os.path.join(self.test_root, build.uuid +
1814 '.post_start.flag')
1815 start = time.time()
1816 while time.time() < start + 90:
1817 if os.path.exists(post_start):
1818 break
1819 time.sleep(0.1)
1820 # The post playbook has started, abort the job
1821 self.fake_gerrit.addEvent(A.getChangeAbandonedEvent())
1822 self.waitUntilSettled()
1823
1824 build = self.getJobFromHistory('python27')
1825 self.assertEqual('ABORTED', build.result)
1826
1827 post_end = os.path.join(self.test_root, build.uuid +
1828 '.post_end.flag')
1829 self.assertTrue(os.path.exists(post_start))
1830 self.assertFalse(os.path.exists(post_end))
1831
1832
James E. Blairb9c0d772017-03-03 14:34:49 -08001833class TestBrokenConfig(ZuulTestCase):
1834 # Test that we get an appropriate syntax error if we start with a
1835 # broken config.
1836
1837 tenant_config_file = 'config/broken/main.yaml'
1838
1839 def setUp(self):
1840 with testtools.ExpectedException(
1841 zuul.configloader.ConfigurationSyntaxError,
1842 "\nZuul encountered a syntax error"):
1843 super(TestBrokenConfig, self).setUp()
1844
1845 def test_broken_config_on_startup(self):
1846 pass
Ricardo Carrillo Cruz22994f92016-12-02 11:41:58 +00001847
1848
1849class TestProjectKeys(ZuulTestCase):
1850 # Test that we can generate project keys
1851
1852 # Normally the test infrastructure copies a static key in place
1853 # for each project before starting tests. This saves time because
1854 # Zuul's automatic key-generation on startup can be slow. To make
1855 # sure we exercise that code, in this test we allow Zuul to create
1856 # keys for the project on startup.
1857 create_project_keys = True
Tobias Henkelabf973e2017-07-28 10:07:34 +02001858 config_file = 'zuul-connections-gerrit-and-github.conf'
Ricardo Carrillo Cruz22994f92016-12-02 11:41:58 +00001859 tenant_config_file = 'config/in-repo/main.yaml'
1860
1861 def test_key_generation(self):
1862 key_root = os.path.join(self.state_root, 'keys')
1863 private_key_file = os.path.join(key_root, 'gerrit/org/project.pem')
1864 # Make sure that a proper key was created on startup
1865 with open(private_key_file, "rb") as f:
James E. Blairbf1a4f22017-03-17 10:59:37 -07001866 private_key, public_key = \
1867 encryption.deserialize_rsa_keypair(f.read())
Ricardo Carrillo Cruz22994f92016-12-02 11:41:58 +00001868
1869 with open(os.path.join(FIXTURE_DIR, 'private.pem')) as i:
1870 fixture_private_key = i.read()
1871
1872 # Make sure that we didn't just end up with the static fixture
1873 # key
1874 self.assertNotEqual(fixture_private_key, private_key)
1875
1876 # Make sure it's the right length
1877 self.assertEqual(4096, private_key.key_size)
James E. Blairbce76932017-05-04 10:03:15 -07001878
1879
James E. Blairbb94dfa2017-07-11 07:45:19 -07001880class RoleTestCase(ZuulTestCase):
James E. Blair1b27f6a2017-07-14 14:09:07 -07001881 def _assertRolePath(self, build, playbook, content):
1882 path = os.path.join(self.test_root, build.uuid,
1883 'ansible', playbook, 'ansible.cfg')
1884 roles_paths = []
1885 with open(path) as f:
1886 for line in f:
1887 if line.startswith('roles_path'):
1888 roles_paths.append(line)
1889 print(roles_paths)
1890 if content:
1891 self.assertEqual(len(roles_paths), 1,
1892 "Should have one roles_path line in %s" %
1893 (playbook,))
1894 self.assertIn(content, roles_paths[0])
1895 else:
1896 self.assertEqual(len(roles_paths), 0,
1897 "Should have no roles_path line in %s" %
1898 (playbook,))
1899
James E. Blairbb94dfa2017-07-11 07:45:19 -07001900
1901class TestRoles(RoleTestCase):
1902 tenant_config_file = 'config/roles/main.yaml'
1903
James E. Blairbce76932017-05-04 10:03:15 -07001904 def test_role(self):
1905 # This exercises a proposed change to a role being checked out
1906 # and used.
1907 A = self.fake_gerrit.addFakeChange('bare-role', 'master', 'A')
1908 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1909 B.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
1910 B.subject, A.data['id'])
1911 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
1912 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
1913 self.waitUntilSettled()
1914 self.assertHistory([
1915 dict(name='project-test', result='SUCCESS', changes='1,1 2,1'),
1916 ])
James E. Blair6459db12017-06-29 14:57:20 -07001917
James E. Blair1b27f6a2017-07-14 14:09:07 -07001918 def test_role_inheritance(self):
1919 self.executor_server.hold_jobs_in_build = True
1920 conf = textwrap.dedent(
1921 """
1922 - job:
1923 name: parent
1924 roles:
1925 - zuul: bare-role
1926 pre-run: playbooks/parent-pre
1927 post-run: playbooks/parent-post
1928
1929 - job:
1930 name: project-test
1931 parent: parent
James E. Blair2f589fe2017-10-26 12:57:41 -07001932 run: playbooks/project-test.yaml
James E. Blair1b27f6a2017-07-14 14:09:07 -07001933 roles:
1934 - zuul: org/project
1935
1936 - project:
1937 name: org/project
1938 check:
1939 jobs:
1940 - project-test
1941 """)
1942
1943 file_dict = {'.zuul.yaml': conf}
1944 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
1945 files=file_dict)
1946 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
1947 self.waitUntilSettled()
1948
1949 self.assertEqual(len(self.builds), 1)
1950 build = self.getBuildByName('project-test')
1951 self._assertRolePath(build, 'pre_playbook_0', 'role_0')
1952 self._assertRolePath(build, 'playbook_0', 'role_0')
1953 self._assertRolePath(build, 'playbook_0', 'role_1')
1954 self._assertRolePath(build, 'post_playbook_0', 'role_0')
1955
1956 self.executor_server.hold_jobs_in_build = False
1957 self.executor_server.release()
1958 self.waitUntilSettled()
1959
1960 self.assertHistory([
1961 dict(name='project-test', result='SUCCESS', changes='1,1'),
1962 ])
1963
James E. Blair6f699732017-07-18 14:19:11 -07001964 def test_role_error(self):
1965 conf = textwrap.dedent(
1966 """
1967 - job:
1968 name: project-test
James E. Blair2f589fe2017-10-26 12:57:41 -07001969 run: playbooks/project-test.yaml
James E. Blair6f699732017-07-18 14:19:11 -07001970 roles:
1971 - zuul: common-config
1972
1973 - project:
1974 name: org/project
1975 check:
1976 jobs:
1977 - project-test
1978 """)
1979
1980 file_dict = {'.zuul.yaml': conf}
1981 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
1982 files=file_dict)
1983 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
1984 self.waitUntilSettled()
1985 self.assertIn(
1986 '- project-test project-test : ERROR Unable to find role',
1987 A.messages[-1])
1988
James E. Blair6459db12017-06-29 14:57:20 -07001989
James E. Blairbb94dfa2017-07-11 07:45:19 -07001990class TestImplicitRoles(RoleTestCase):
1991 tenant_config_file = 'config/implicit-roles/main.yaml'
1992
1993 def test_missing_roles(self):
1994 # Test implicit and explicit roles for a project which does
1995 # not have roles. The implicit role should be silently
1996 # ignored since the project doesn't supply roles, but if a
1997 # user declares an explicit role, it should error.
1998 self.executor_server.hold_jobs_in_build = True
1999 A = self.fake_gerrit.addFakeChange('org/norole-project', 'master', 'A')
2000 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2001 self.waitUntilSettled()
2002
2003 self.assertEqual(len(self.builds), 2)
2004 build = self.getBuildByName('implicit-role-fail')
2005 self._assertRolePath(build, 'playbook_0', None)
2006
2007 self.executor_server.hold_jobs_in_build = False
2008 self.executor_server.release()
2009 self.waitUntilSettled()
2010 # The retry_limit doesn't get recorded
2011 self.assertHistory([
2012 dict(name='implicit-role-fail', result='SUCCESS', changes='1,1'),
2013 ])
2014
2015 def test_roles(self):
2016 # Test implicit and explicit roles for a project which does
2017 # have roles. In both cases, we should end up with the role
2018 # in the path. In the explicit case, ensure we end up with
2019 # the name we specified.
2020 self.executor_server.hold_jobs_in_build = True
2021 A = self.fake_gerrit.addFakeChange('org/role-project', 'master', 'A')
2022 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2023 self.waitUntilSettled()
2024
2025 self.assertEqual(len(self.builds), 2)
2026 build = self.getBuildByName('implicit-role-ok')
2027 self._assertRolePath(build, 'playbook_0', 'role_0')
2028
2029 build = self.getBuildByName('explicit-role-ok')
2030 self._assertRolePath(build, 'playbook_0', 'role_0')
2031
2032 self.executor_server.hold_jobs_in_build = False
2033 self.executor_server.release()
2034 self.waitUntilSettled()
2035 self.assertHistory([
2036 dict(name='implicit-role-ok', result='SUCCESS', changes='1,1'),
2037 dict(name='explicit-role-ok', result='SUCCESS', changes='1,1'),
2038 ], ordered=False)
2039
2040
James E. Blair6459db12017-06-29 14:57:20 -07002041class TestShadow(ZuulTestCase):
2042 tenant_config_file = 'config/shadow/main.yaml'
2043
2044 def test_shadow(self):
2045 # Test that a repo is allowed to shadow another's job definitions.
2046 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2047 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2048 self.waitUntilSettled()
2049 self.assertHistory([
2050 dict(name='test1', result='SUCCESS', changes='1,1'),
2051 dict(name='test2', result='SUCCESS', changes='1,1'),
James E. Blairadafa6c2017-07-12 08:50:56 -07002052 ], ordered=False)
James E. Blair196f61a2017-06-30 15:42:29 -07002053
2054
2055class TestDataReturn(AnsibleZuulTestCase):
2056 tenant_config_file = 'config/data-return/main.yaml'
2057
2058 def test_data_return(self):
James E. Blair196f61a2017-06-30 15:42:29 -07002059 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2060 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2061 self.waitUntilSettled()
2062 self.assertHistory([
2063 dict(name='data-return', result='SUCCESS', changes='1,1'),
James E. Blair88e79c02017-07-07 13:36:54 -07002064 dict(name='data-return-relative', result='SUCCESS', changes='1,1'),
James E. Blair698703c2017-09-15 20:58:30 -06002065 dict(name='child', result='SUCCESS', changes='1,1'),
James E. Blair88e79c02017-07-07 13:36:54 -07002066 ], ordered=False)
2067 self.assertIn('- data-return http://example.com/test/log/url/',
2068 A.messages[-1])
2069 self.assertIn('- data-return-relative '
2070 'http://example.com/test/log/url/docs/index.html',
James E. Blair196f61a2017-06-30 15:42:29 -07002071 A.messages[-1])
Clint Byrumdc8a0902017-07-20 16:36:27 -07002072
2073
2074class TestDiskAccounting(AnsibleZuulTestCase):
2075 config_file = 'zuul-disk-accounting.conf'
2076 tenant_config_file = 'config/disk-accountant/main.yaml'
2077
2078 def test_disk_accountant_kills_job(self):
2079 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2080 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2081 self.waitUntilSettled()
2082 self.assertHistory([
2083 dict(name='dd-big-empty-file', result='ABORTED', changes='1,1')])
Tristan Cacqueray82f864b2017-08-01 05:54:42 +00002084
2085
2086class TestMaxNodesPerJob(AnsibleZuulTestCase):
2087 tenant_config_file = 'config/multi-tenant/main.yaml'
2088
Tristan Cacquerayc98bff72017-09-10 15:25:26 +00002089 def test_max_timeout_exceeded(self):
Tristan Cacqueray82f864b2017-08-01 05:54:42 +00002090 in_repo_conf = textwrap.dedent(
2091 """
2092 - job:
2093 name: test-job
James E. Blair7e3e6882017-09-20 15:47:13 -07002094 nodeset:
2095 nodes:
2096 - name: node01
2097 label: fake
2098 - name: node02
2099 label: fake
2100 - name: node03
2101 label: fake
2102 - name: node04
2103 label: fake
2104 - name: node05
2105 label: fake
2106 - name: node06
2107 label: fake
Tristan Cacqueray82f864b2017-08-01 05:54:42 +00002108 """)
2109 file_dict = {'.zuul.yaml': in_repo_conf}
2110 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A',
2111 files=file_dict)
2112 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2113 self.waitUntilSettled()
2114 self.assertIn('The job "test-job" exceeds tenant max-nodes-per-job 5.',
2115 A.messages[0], "A should fail because of nodes limit")
2116
2117 B = self.fake_gerrit.addFakeChange('org/project2', 'master', 'A',
2118 files=file_dict)
2119 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
2120 self.waitUntilSettled()
2121 self.assertNotIn("exceeds tenant max-nodes", B.messages[0],
2122 "B should not fail because of nodes limit")
James E. Blair2bab6e72017-08-07 09:52:45 -07002123
2124
Tristan Cacquerayc98bff72017-09-10 15:25:26 +00002125class TestMaxTimeout(AnsibleZuulTestCase):
2126 tenant_config_file = 'config/multi-tenant/main.yaml'
2127
2128 def test_max_nodes_reached(self):
2129 in_repo_conf = textwrap.dedent(
2130 """
2131 - job:
2132 name: test-job
2133 timeout: 3600
2134 """)
2135 file_dict = {'.zuul.yaml': in_repo_conf}
2136 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A',
2137 files=file_dict)
2138 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2139 self.waitUntilSettled()
2140 self.assertIn('The job "test-job" exceeds tenant max-job-timeout',
2141 A.messages[0], "A should fail because of timeout limit")
2142
2143 B = self.fake_gerrit.addFakeChange('org/project2', 'master', 'A',
2144 files=file_dict)
2145 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
2146 self.waitUntilSettled()
2147 self.assertNotIn("exceeds tenant max-job-timeout", B.messages[0],
2148 "B should not fail because of timeout limit")
2149
2150
James E. Blair7edc25f2017-10-26 10:47:14 -07002151class TestPragma(ZuulTestCase):
2152 tenant_config_file = 'config/pragma/main.yaml'
2153
2154 def test_no_pragma(self):
2155 self.create_branch('org/project', 'stable')
2156 with open(os.path.join(FIXTURE_DIR,
2157 'config/pragma/git/',
2158 'org_project/nopragma.yaml')) as f:
2159 config = f.read()
2160 file_dict = {'.zuul.yaml': config}
2161 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
2162 files=file_dict)
2163 A.addApproval('Code-Review', 2)
2164 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
2165 self.waitUntilSettled()
2166 self.fake_gerrit.addEvent(A.getChangeMergedEvent())
2167 self.waitUntilSettled()
2168
2169 # This is an untrusted repo with 2 branches, so it should have
2170 # an implied branch matcher for the job.
2171 tenant = self.sched.abide.tenants.get('tenant-one')
2172 jobs = tenant.layout.getJobs('test-job')
2173 self.assertEqual(len(jobs), 1)
2174 for job in tenant.layout.getJobs('test-job'):
2175 self.assertIsNotNone(job.branch_matcher)
2176
2177 def test_pragma(self):
2178 self.create_branch('org/project', 'stable')
2179 with open(os.path.join(FIXTURE_DIR,
2180 'config/pragma/git/',
2181 'org_project/pragma.yaml')) as f:
2182 config = f.read()
2183 file_dict = {'.zuul.yaml': config}
2184 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
2185 files=file_dict)
2186 A.addApproval('Code-Review', 2)
2187 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
2188 self.waitUntilSettled()
2189 self.fake_gerrit.addEvent(A.getChangeMergedEvent())
2190 self.waitUntilSettled()
2191
2192 # This is an untrusted repo with 2 branches, so it would
2193 # normally have an implied branch matcher, but our pragma
2194 # overrides it.
2195 tenant = self.sched.abide.tenants.get('tenant-one')
2196 jobs = tenant.layout.getJobs('test-job')
2197 self.assertEqual(len(jobs), 1)
2198 for job in tenant.layout.getJobs('test-job'):
2199 self.assertIsNone(job.branch_matcher)
2200
2201
James E. Blair2bab6e72017-08-07 09:52:45 -07002202class TestBaseJobs(ZuulTestCase):
2203 tenant_config_file = 'config/base-jobs/main.yaml'
2204
2205 def test_multiple_base_jobs(self):
2206 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2207 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2208 self.waitUntilSettled()
2209 self.assertHistory([
2210 dict(name='my-job', result='SUCCESS', changes='1,1'),
2211 dict(name='other-job', result='SUCCESS', changes='1,1'),
2212 ], ordered=False)
2213 self.assertEqual(self.getJobFromHistory('my-job').
2214 parameters['zuul']['jobtags'],
2215 ['mybase'])
2216 self.assertEqual(self.getJobFromHistory('other-job').
2217 parameters['zuul']['jobtags'],
2218 ['otherbase'])
2219
2220 def test_untrusted_base_job(self):
2221 """Test that a base job may not be defined in an untrusted repo"""
2222 in_repo_conf = textwrap.dedent(
2223 """
2224 - job:
2225 name: fail-base
2226 parent: null
2227 """)
2228
2229 file_dict = {'.zuul.yaml': in_repo_conf}
2230 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
2231 files=file_dict)
2232 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2233 self.waitUntilSettled()
2234 self.assertEqual(A.reported, 1,
2235 "A should report failure")
2236 self.assertEqual(A.patchsets[0]['approvals'][0]['value'], "-1")
2237 self.assertIn('Base jobs must be defined in config projects',
2238 A.messages[0])
2239 self.assertHistory([])
James E. Blairdb089032017-08-15 13:42:12 -07002240
2241
James E. Blairdf91ab32017-10-25 17:57:13 -07002242class TestSecretInheritance(ZuulTestCase):
2243 tenant_config_file = 'config/secret-inheritance/main.yaml'
2244
2245 def _getSecrets(self, job, pbtype):
2246 secrets = []
2247 build = self.getJobFromHistory(job)
2248 for pb in build.parameters[pbtype]:
2249 secrets.append(pb['secrets'])
2250 return secrets
2251
2252 def _checkTrustedSecrets(self):
2253 secret = {'longpassword': 'test-passwordtest-password',
2254 'password': 'test-password',
2255 'username': 'test-username'}
2256 self.assertEqual(
2257 self._getSecrets('trusted-secrets', 'playbooks'),
James E. Blair2f589fe2017-10-26 12:57:41 -07002258 [{'trusted-secret': secret}])
James E. Blairdf91ab32017-10-25 17:57:13 -07002259 self.assertEqual(
2260 self._getSecrets('trusted-secrets', 'pre_playbooks'), [])
2261 self.assertEqual(
2262 self._getSecrets('trusted-secrets', 'post_playbooks'), [])
2263
2264 self.assertEqual(
2265 self._getSecrets('trusted-secrets-trusted-child',
James E. Blair2f589fe2017-10-26 12:57:41 -07002266 'playbooks'), [{}])
James E. Blairdf91ab32017-10-25 17:57:13 -07002267 self.assertEqual(
2268 self._getSecrets('trusted-secrets-trusted-child',
2269 'pre_playbooks'), [])
2270 self.assertEqual(
2271 self._getSecrets('trusted-secrets-trusted-child',
2272 'post_playbooks'), [])
2273
2274 self.assertEqual(
2275 self._getSecrets('trusted-secrets-untrusted-child',
James E. Blair2f589fe2017-10-26 12:57:41 -07002276 'playbooks'), [{}])
James E. Blairdf91ab32017-10-25 17:57:13 -07002277 self.assertEqual(
2278 self._getSecrets('trusted-secrets-untrusted-child',
2279 'pre_playbooks'), [])
2280 self.assertEqual(
2281 self._getSecrets('trusted-secrets-untrusted-child',
2282 'post_playbooks'), [])
2283
2284 def _checkUntrustedSecrets(self):
2285 secret = {'longpassword': 'test-passwordtest-password',
2286 'password': 'test-password',
2287 'username': 'test-username'}
2288 self.assertEqual(
2289 self._getSecrets('untrusted-secrets', 'playbooks'),
James E. Blair2f589fe2017-10-26 12:57:41 -07002290 [{'untrusted-secret': secret}])
James E. Blairdf91ab32017-10-25 17:57:13 -07002291 self.assertEqual(
2292 self._getSecrets('untrusted-secrets', 'pre_playbooks'), [])
2293 self.assertEqual(
2294 self._getSecrets('untrusted-secrets', 'post_playbooks'), [])
2295
2296 self.assertEqual(
2297 self._getSecrets('untrusted-secrets-trusted-child',
James E. Blair2f589fe2017-10-26 12:57:41 -07002298 'playbooks'), [{}])
James E. Blairdf91ab32017-10-25 17:57:13 -07002299 self.assertEqual(
2300 self._getSecrets('untrusted-secrets-trusted-child',
2301 'pre_playbooks'), [])
2302 self.assertEqual(
2303 self._getSecrets('untrusted-secrets-trusted-child',
2304 'post_playbooks'), [])
2305
2306 self.assertEqual(
2307 self._getSecrets('untrusted-secrets-untrusted-child',
James E. Blair2f589fe2017-10-26 12:57:41 -07002308 'playbooks'), [{}])
James E. Blairdf91ab32017-10-25 17:57:13 -07002309 self.assertEqual(
2310 self._getSecrets('untrusted-secrets-untrusted-child',
2311 'pre_playbooks'), [])
2312 self.assertEqual(
2313 self._getSecrets('untrusted-secrets-untrusted-child',
2314 'post_playbooks'), [])
2315
2316 def test_trusted_secret_inheritance_check(self):
2317 A = self.fake_gerrit.addFakeChange('common-config', 'master', 'A')
2318 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2319 self.waitUntilSettled()
2320 self.assertHistory([
2321 dict(name='trusted-secrets', result='SUCCESS', changes='1,1'),
2322 dict(name='trusted-secrets-trusted-child',
2323 result='SUCCESS', changes='1,1'),
2324 dict(name='trusted-secrets-untrusted-child',
2325 result='SUCCESS', changes='1,1'),
2326 ], ordered=False)
2327
2328 self._checkTrustedSecrets()
2329
2330 def test_untrusted_secret_inheritance_gate(self):
2331 A = self.fake_gerrit.addFakeChange('common-config', 'master', 'A')
2332 A.addApproval('Code-Review', 2)
2333 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
2334 self.waitUntilSettled()
2335 self.assertHistory([
2336 dict(name='untrusted-secrets', result='SUCCESS', changes='1,1'),
2337 dict(name='untrusted-secrets-trusted-child',
2338 result='SUCCESS', changes='1,1'),
2339 dict(name='untrusted-secrets-untrusted-child',
2340 result='SUCCESS', changes='1,1'),
2341 ], ordered=False)
2342
2343 self._checkUntrustedSecrets()
2344
2345 def test_untrusted_secret_inheritance_check(self):
2346 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2347 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2348 self.waitUntilSettled()
2349 # This configuration tries to run untrusted secrets in an
2350 # non-post-review pipeline and should therefore run no jobs.
2351 self.assertHistory([])
2352
2353
James E. Blairdb089032017-08-15 13:42:12 -07002354class TestSecretLeaks(AnsibleZuulTestCase):
2355 tenant_config_file = 'config/secret-leaks/main.yaml'
2356
2357 def searchForContent(self, path, content):
2358 matches = []
2359 for (dirpath, dirnames, filenames) in os.walk(path):
2360 for filename in filenames:
2361 filepath = os.path.join(dirpath, filename)
2362 with open(filepath, 'rb') as f:
2363 if content in f.read():
2364 matches.append(filepath[len(path):])
2365 return matches
2366
2367 def _test_secret_file(self):
2368 # Or rather -- test that they *don't* leak.
2369 # Keep the jobdir around so we can inspect contents.
2370 self.executor_server.keep_jobdir = True
2371 conf = textwrap.dedent(
2372 """
2373 - project:
2374 name: org/project
2375 check:
2376 jobs:
2377 - secret-file
2378 """)
2379
2380 file_dict = {'.zuul.yaml': conf}
2381 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
2382 files=file_dict)
2383 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2384 self.waitUntilSettled()
2385 self.assertHistory([
2386 dict(name='secret-file', result='SUCCESS', changes='1,1'),
2387 ], ordered=False)
2388 matches = self.searchForContent(self.history[0].jobdir.root,
2389 b'test-password')
James E. Blaird6a71ca2017-08-18 14:15:05 -07002390 self.assertEqual(set(['/work/secret-file.txt']),
James E. Blairdb089032017-08-15 13:42:12 -07002391 set(matches))
2392
2393 def test_secret_file(self):
2394 self._test_secret_file()
2395
2396 def test_secret_file_verbose(self):
2397 # Output extra ansible info to exercise alternate logging code
2398 # paths.
2399 self.executor_server.verbose = True
2400 self._test_secret_file()
2401
2402 def _test_secret_file_fail(self):
2403 # Or rather -- test that they *don't* leak.
2404 # Keep the jobdir around so we can inspect contents.
2405 self.executor_server.keep_jobdir = True
2406 conf = textwrap.dedent(
2407 """
2408 - project:
2409 name: org/project
2410 check:
2411 jobs:
2412 - secret-file-fail
2413 """)
2414
2415 file_dict = {'.zuul.yaml': conf}
2416 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
2417 files=file_dict)
2418 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2419 self.waitUntilSettled()
2420 self.assertHistory([
2421 dict(name='secret-file-fail', result='FAILURE', changes='1,1'),
2422 ], ordered=False)
2423 matches = self.searchForContent(self.history[0].jobdir.root,
2424 b'test-password')
James E. Blaird6a71ca2017-08-18 14:15:05 -07002425 self.assertEqual(set(['/work/failure-file.txt']),
James E. Blairdb089032017-08-15 13:42:12 -07002426 set(matches))
2427
2428 def test_secret_file_fail(self):
2429 self._test_secret_file_fail()
2430
2431 def test_secret_file_fail_verbose(self):
2432 # Output extra ansible info to exercise alternate logging code
2433 # paths.
2434 self.executor_server.verbose = True
2435 self._test_secret_file_fail()
James E. Blaira00910c2017-08-23 09:15:04 -07002436
2437
2438class TestJobOutput(AnsibleZuulTestCase):
2439 tenant_config_file = 'config/job-output/main.yaml'
2440
2441 def _get_file(self, build, path):
2442 p = os.path.join(build.jobdir.root, path)
2443 with open(p) as f:
2444 return f.read()
2445
2446 def test_job_output(self):
Monty Taylor0e2489a2017-10-10 11:57:29 -05002447 # Verify that command standard output appears in the job output,
2448 # and that failures in the final playbook get logged.
James E. Blaira00910c2017-08-23 09:15:04 -07002449
2450 # This currently only verifies we receive output from
2451 # localhost. Notably, it does not verify we receive output
2452 # via zuul_console streaming.
2453 self.executor_server.keep_jobdir = True
2454 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2455 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2456 self.waitUntilSettled()
2457 self.assertHistory([
2458 dict(name='job-output', result='SUCCESS', changes='1,1'),
2459 ], ordered=False)
2460
2461 token = 'Standard output test %s' % (self.history[0].jobdir.src_root)
2462 j = json.loads(self._get_file(self.history[0],
2463 'work/logs/job-output.json'))
2464 self.assertEqual(token,
2465 j[0]['plays'][0]['tasks'][0]
2466 ['hosts']['localhost']['stdout'])
2467
2468 print(self._get_file(self.history[0],
2469 'work/logs/job-output.txt'))
2470 self.assertIn(token,
2471 self._get_file(self.history[0],
2472 'work/logs/job-output.txt'))
Monty Taylor0e2489a2017-10-10 11:57:29 -05002473
2474 def test_job_output_failure_log(self):
2475 logger = logging.getLogger('zuul.AnsibleJob')
2476 output = io.StringIO()
2477 logger.addHandler(logging.StreamHandler(output))
2478
2479 # Verify that a failure in the last post playbook emits the contents
2480 # of the json output to the log
2481 self.executor_server.keep_jobdir = True
2482 A = self.fake_gerrit.addFakeChange('org/project2', 'master', 'A')
2483 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2484 self.waitUntilSettled()
2485 self.assertHistory([
2486 dict(name='job-output-failure',
2487 result='POST_FAILURE', changes='1,1'),
2488 ], ordered=False)
2489
2490 token = 'Standard output test %s' % (self.history[0].jobdir.src_root)
2491 j = json.loads(self._get_file(self.history[0],
2492 'work/logs/job-output.json'))
2493 self.assertEqual(token,
2494 j[0]['plays'][0]['tasks'][0]
2495 ['hosts']['localhost']['stdout'])
2496
2497 print(self._get_file(self.history[0],
2498 'work/logs/job-output.json'))
2499 self.assertIn(token,
2500 self._get_file(self.history[0],
2501 'work/logs/job-output.txt'))
2502
2503 log_output = output.getvalue()
2504 self.assertIn('Final playbook failed', log_output)
2505 self.assertIn('Failure test', log_output)