blob: b9c9b32533859669eb16d910ef8aa2203defe2a9 [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. Blair1edfd972017-12-01 15:54:24 -0800160class TestBranchTag(ZuulTestCase):
161 tenant_config_file = 'config/branch-tag/main.yaml'
162
163 def test_negative_branch_match(self):
164 # Test that a negative branch matcher works with implied branches.
165 event = self.fake_gerrit.addFakeTag('org/project', 'master', 'foo')
166 self.fake_gerrit.addEvent(event)
167 self.waitUntilSettled()
168 self.assertHistory([
169 dict(name='test-job', result='SUCCESS', ref='refs/tags/foo')])
170
171
James E. Blair9ab8db42017-12-01 15:12:04 -0800172class TestBranchNegative(ZuulTestCase):
173 tenant_config_file = 'config/branch-negative/main.yaml'
174
175 def test_negative_branch_match(self):
176 # Test that a negative branch matcher works with implied branches.
177 self.create_branch('org/project', 'stable/pike')
178 self.fake_gerrit.addEvent(
179 self.fake_gerrit.getFakeBranchCreatedEvent(
180 'org/project', 'stable/pike'))
181 self.waitUntilSettled()
182
183 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
184 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
185 self.waitUntilSettled()
186 B = self.fake_gerrit.addFakeChange('org/project', 'stable/pike', 'A')
187 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
188 self.waitUntilSettled()
189 self.assertHistory([
190 dict(name='test-job', result='SUCCESS', changes='1,1')])
191
192
James E. Blaire36d1a32017-11-28 13:33:38 -0800193class TestBranchTemplates(ZuulTestCase):
194 tenant_config_file = 'config/branch-templates/main.yaml'
195
196 def test_template_removal_from_branch(self):
197 # Test that a template can be removed from one branch but not
198 # another.
199 # This creates a new branch with a copy of the config in master
200 self.create_branch('puppet-integration', 'stable/newton')
201 self.create_branch('puppet-integration', 'stable/ocata')
202 self.create_branch('puppet-tripleo', 'stable/newton')
203 self.create_branch('puppet-tripleo', 'stable/ocata')
204 self.fake_gerrit.addEvent(
205 self.fake_gerrit.getFakeBranchCreatedEvent(
206 'puppet-integration', 'stable/newton'))
207 self.fake_gerrit.addEvent(
208 self.fake_gerrit.getFakeBranchCreatedEvent(
209 'puppet-integration', 'stable/ocata'))
210 self.fake_gerrit.addEvent(
211 self.fake_gerrit.getFakeBranchCreatedEvent(
212 'puppet-tripleo', 'stable/newton'))
213 self.fake_gerrit.addEvent(
214 self.fake_gerrit.getFakeBranchCreatedEvent(
215 'puppet-tripleo', 'stable/ocata'))
216 self.waitUntilSettled()
217
218 in_repo_conf = textwrap.dedent(
219 """
220 - project:
221 name: puppet-tripleo
222 check:
223 jobs:
224 - puppet-something
225 """)
226
227 file_dict = {'.zuul.yaml': in_repo_conf}
228 A = self.fake_gerrit.addFakeChange('puppet-tripleo', 'stable/newton',
229 'A', files=file_dict)
230 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
231 self.waitUntilSettled()
232 self.assertHistory([
233 dict(name='puppet-something', result='SUCCESS', changes='1,1')])
234
235 def test_template_change_on_branch(self):
236 # Test that the contents of a template can be changed on one
237 # branch without affecting another.
238
239 # This creates a new branch with a copy of the config in master
240 self.create_branch('puppet-integration', 'stable/newton')
241 self.create_branch('puppet-integration', 'stable/ocata')
242 self.create_branch('puppet-tripleo', 'stable/newton')
243 self.create_branch('puppet-tripleo', 'stable/ocata')
244 self.fake_gerrit.addEvent(
245 self.fake_gerrit.getFakeBranchCreatedEvent(
246 'puppet-integration', 'stable/newton'))
247 self.fake_gerrit.addEvent(
248 self.fake_gerrit.getFakeBranchCreatedEvent(
249 'puppet-integration', 'stable/ocata'))
250 self.fake_gerrit.addEvent(
251 self.fake_gerrit.getFakeBranchCreatedEvent(
252 'puppet-tripleo', 'stable/newton'))
253 self.fake_gerrit.addEvent(
254 self.fake_gerrit.getFakeBranchCreatedEvent(
255 'puppet-tripleo', 'stable/ocata'))
256 self.waitUntilSettled()
257
258 in_repo_conf = textwrap.dedent("""
259 - job:
260 name: puppet-unit-base
261 run: playbooks/run-unit-tests.yaml
262
263 - job:
264 name: puppet-unit-3.8
265 parent: puppet-unit-base
266 branches: ^(stable/(newton|ocata)).*$
267 vars:
268 puppet_gem_version: 3.8
269
270 - job:
271 name: puppet-something
272 run: playbooks/run-unit-tests.yaml
273
274 - project-template:
275 name: puppet-unit
276 check:
277 jobs:
278 - puppet-something
279
280 - project:
281 name: puppet-integration
282 templates:
283 - puppet-unit
284 """)
285
286 file_dict = {'.zuul.yaml': in_repo_conf}
287 A = self.fake_gerrit.addFakeChange('puppet-integration',
288 'stable/newton',
289 'A', files=file_dict)
290 B = self.fake_gerrit.addFakeChange('puppet-tripleo',
291 'stable/newton',
292 'B')
293 B.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
294 B.subject, A.data['id'])
295 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
296 self.waitUntilSettled()
297 self.assertHistory([
298 dict(name='puppet-something', result='SUCCESS',
299 changes='1,1 2,1')])
300
301
James E. Blair09998792017-10-15 18:02:18 -0700302class TestBranchVariants(ZuulTestCase):
303 tenant_config_file = 'config/branch-variants/main.yaml'
304
305 def test_branch_variants(self):
306 # Test branch variants of jobs with inheritance
307 self.executor_server.hold_jobs_in_build = True
308 # This creates a new branch with a copy of the config in master
309 self.create_branch('puppet-integration', 'stable')
310 self.fake_gerrit.addEvent(
311 self.fake_gerrit.getFakeBranchCreatedEvent(
312 'puppet-integration', 'stable'))
313 self.waitUntilSettled()
314
315 A = self.fake_gerrit.addFakeChange('puppet-integration', 'stable', 'A')
316 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
317 self.waitUntilSettled()
318
319 self.assertEqual(len(self.builds[0].parameters['pre_playbooks']), 3)
320 self.executor_server.hold_jobs_in_build = False
321 self.executor_server.release()
322 self.waitUntilSettled()
323
James E. Blairc9e77592017-10-24 09:25:23 -0700324 def test_branch_variants_reconfigure(self):
325 # Test branch variants of jobs with inheritance
326 self.executor_server.hold_jobs_in_build = True
327 # This creates a new branch with a copy of the config in master
328 self.create_branch('puppet-integration', 'stable')
329 self.fake_gerrit.addEvent(
330 self.fake_gerrit.getFakeBranchCreatedEvent(
331 'puppet-integration', 'stable'))
332 self.waitUntilSettled()
333
334 with open(os.path.join(FIXTURE_DIR,
335 'config/branch-variants/git/',
336 'puppet-integration/.zuul.yaml')) as f:
337 config = f.read()
338
339 # Push a change that triggers a dynamic reconfiguration
340 file_dict = {'.zuul.yaml': config}
341 A = self.fake_gerrit.addFakeChange('puppet-integration', 'master', 'A',
342 files=file_dict)
343 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
344 self.waitUntilSettled()
345
346 ipath = self.builds[0].parameters['zuul']['_inheritance_path']
347 for i in ipath:
348 self.log.debug("inheritance path %s", i)
349 self.assertEqual(len(ipath), 5)
350 self.executor_server.hold_jobs_in_build = False
351 self.executor_server.release()
352 self.waitUntilSettled()
353
James E. Blairc32a8352017-10-11 16:27:50 -0700354 def test_branch_variants_divergent(self):
355 # Test branches can diverge and become independent
356 self.executor_server.hold_jobs_in_build = True
357 # This creates a new branch with a copy of the config in master
358 self.create_branch('puppet-integration', 'stable')
359 self.fake_gerrit.addEvent(
360 self.fake_gerrit.getFakeBranchCreatedEvent(
361 'puppet-integration', 'stable'))
362 self.waitUntilSettled()
363
364 with open(os.path.join(FIXTURE_DIR,
365 'config/branch-variants/git/',
366 'puppet-integration/stable.zuul.yaml')) as f:
367 config = f.read()
368
369 file_dict = {'.zuul.yaml': config}
370 C = self.fake_gerrit.addFakeChange('puppet-integration', 'stable', 'C',
371 files=file_dict)
372 C.addApproval('Code-Review', 2)
373 self.fake_gerrit.addEvent(C.addApproval('Approved', 1))
374 self.waitUntilSettled()
375 self.fake_gerrit.addEvent(C.getChangeMergedEvent())
376 self.waitUntilSettled()
377
378 A = self.fake_gerrit.addFakeChange('puppet-integration', 'master', 'A')
379 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
380 self.waitUntilSettled()
381 B = self.fake_gerrit.addFakeChange('puppet-integration', 'stable', 'B')
382 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
383 self.waitUntilSettled()
384
385 self.assertEqual(self.builds[0].parameters['zuul']['jobtags'],
386 ['master'])
387
388 self.assertEqual(self.builds[1].parameters['zuul']['jobtags'],
389 ['stable'])
390
391 self.executor_server.hold_jobs_in_build = False
392 self.executor_server.release()
393 self.waitUntilSettled()
394
James E. Blair09998792017-10-15 18:02:18 -0700395
James E. Blair2a664502017-10-27 11:39:33 -0700396class TestCentralJobs(ZuulTestCase):
397 tenant_config_file = 'config/central-jobs/main.yaml'
398
399 def setUp(self):
400 super(TestCentralJobs, self).setUp()
401 self.create_branch('org/project', 'stable')
402 self.fake_gerrit.addEvent(
403 self.fake_gerrit.getFakeBranchCreatedEvent(
404 'org/project', 'stable'))
405 self.waitUntilSettled()
406
407 def _updateConfig(self, config, branch):
408 file_dict = {'.zuul.yaml': config}
409 C = self.fake_gerrit.addFakeChange('org/project', branch, 'C',
410 files=file_dict)
411 C.addApproval('Code-Review', 2)
412 self.fake_gerrit.addEvent(C.addApproval('Approved', 1))
413 self.waitUntilSettled()
414 self.fake_gerrit.addEvent(C.getChangeMergedEvent())
415 self.waitUntilSettled()
416
417 def _test_central_job_on_branch(self, branch, other_branch):
418 # Test that a job defined on a branchless repo only runs on
419 # the branch applied
420 config = textwrap.dedent(
421 """
422 - project:
423 name: org/project
424 check:
425 jobs:
426 - central-job
427 """)
428 self._updateConfig(config, branch)
429
430 A = self.fake_gerrit.addFakeChange('org/project', branch, 'A')
431 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
432 self.waitUntilSettled()
433
434 self.assertHistory([
435 dict(name='central-job', result='SUCCESS', changes='2,1')])
436
437 # No jobs should run for this change.
438 B = self.fake_gerrit.addFakeChange('org/project', other_branch, 'B')
439 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
440 self.waitUntilSettled()
441
442 self.assertHistory([
443 dict(name='central-job', result='SUCCESS', changes='2,1')])
444
445 def test_central_job_on_stable(self):
446 self._test_central_job_on_branch('master', 'stable')
447
448 def test_central_job_on_master(self):
449 self._test_central_job_on_branch('stable', 'master')
450
451 def _test_central_template_on_branch(self, branch, other_branch):
452 # Test that a project-template defined on a branchless repo
453 # only runs on the branch applied
454 config = textwrap.dedent(
455 """
456 - project:
457 name: org/project
458 templates: ['central-jobs']
459 """)
460 self._updateConfig(config, branch)
461
462 A = self.fake_gerrit.addFakeChange('org/project', branch, 'A')
463 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
464 self.waitUntilSettled()
465
466 self.assertHistory([
467 dict(name='central-job', result='SUCCESS', changes='2,1')])
468
469 # No jobs should run for this change.
470 B = self.fake_gerrit.addFakeChange('org/project', other_branch, 'B')
471 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
472 self.waitUntilSettled()
473
474 self.assertHistory([
475 dict(name='central-job', result='SUCCESS', changes='2,1')])
476
477 def test_central_template_on_stable(self):
478 self._test_central_template_on_branch('master', 'stable')
479
480 def test_central_template_on_master(self):
481 self._test_central_template_on_branch('stable', 'master')
482
483
James E. Blairff555742017-02-19 11:34:27 -0800484class TestInRepoConfig(ZuulTestCase):
James E. Blair83005782015-12-11 14:46:03 -0800485 # A temporary class to hold new tests while others are disabled
486
Tobias Henkelabf973e2017-07-28 10:07:34 +0200487 config_file = 'zuul-connections-gerrit-and-github.conf'
James E. Blair2a629ec2015-12-22 15:32:02 -0800488 tenant_config_file = 'config/in-repo/main.yaml'
James E. Blair83005782015-12-11 14:46:03 -0800489
James E. Blair83005782015-12-11 14:46:03 -0800490 def test_in_repo_config(self):
James E. Blair14abdf42015-12-09 16:11:53 -0800491 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
Tobias Henkelbf24fd12017-07-27 06:13:07 +0200492 A.addApproval('Code-Review', 2)
493 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
James E. Blair14abdf42015-12-09 16:11:53 -0800494 self.waitUntilSettled()
495 self.assertEqual(self.getJobFromHistory('project-test1').result,
496 'SUCCESS')
497 self.assertEqual(A.data['status'], 'MERGED')
498 self.assertEqual(A.reported, 2,
499 "A should report start and success")
500 self.assertIn('tenant-one-gate', A.messages[1],
501 "A should transit tenant-one gate")
James E. Blairb97ed802015-12-21 15:55:35 -0800502
James E. Blair3a098dd2017-10-04 14:37:29 -0700503 @skip("This test is useful, but not reliable")
504 def test_full_and_dynamic_reconfig(self):
505 self.executor_server.hold_jobs_in_build = True
506 in_repo_conf = textwrap.dedent(
507 """
508 - job:
509 name: project-test1
510
511 - project:
512 name: org/project
513 tenant-one-gate:
514 jobs:
515 - project-test1
516 """)
517
518 file_dict = {'.zuul.yaml': in_repo_conf}
519 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
520 files=file_dict)
521 A.addApproval('Code-Review', 2)
522 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
523 self.waitUntilSettled()
524 self.sched.reconfigure(self.config)
525 self.waitUntilSettled()
526
527 gc.collect()
528 pipelines = [obj for obj in gc.get_objects()
529 if isinstance(obj, zuul.model.Pipeline)]
530 self.assertEqual(len(pipelines), 4)
531
532 self.executor_server.hold_jobs_in_build = False
533 self.executor_server.release()
534 self.waitUntilSettled()
535
James E. Blair8b1dc3f2016-07-05 16:49:00 -0700536 def test_dynamic_config(self):
537 in_repo_conf = textwrap.dedent(
538 """
539 - job:
Tobias Henkelf02cf512017-07-21 22:55:34 +0200540 name: project-test1
541
542 - job:
James E. Blair8b1dc3f2016-07-05 16:49:00 -0700543 name: project-test2
James E. Blair2f589fe2017-10-26 12:57:41 -0700544 run: playbooks/project-test2.yaml
James E. Blair8b1dc3f2016-07-05 16:49:00 -0700545
546 - project:
547 name: org/project
548 tenant-one-gate:
549 jobs:
550 - project-test2
551 """)
552
James E. Blairc73c73a2017-01-20 15:15:15 -0800553 in_repo_playbook = textwrap.dedent(
554 """
555 - hosts: all
556 tasks: []
557 """)
558
559 file_dict = {'.zuul.yaml': in_repo_conf,
560 'playbooks/project-test2.yaml': in_repo_playbook}
James E. Blair8b1dc3f2016-07-05 16:49:00 -0700561 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
James E. Blairc73c73a2017-01-20 15:15:15 -0800562 files=file_dict)
Tobias Henkelbf24fd12017-07-27 06:13:07 +0200563 A.addApproval('Code-Review', 2)
564 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
James E. Blair8b1dc3f2016-07-05 16:49:00 -0700565 self.waitUntilSettled()
James E. Blair8b1dc3f2016-07-05 16:49:00 -0700566 self.assertEqual(A.data['status'], 'MERGED')
567 self.assertEqual(A.reported, 2,
568 "A should report start and success")
569 self.assertIn('tenant-one-gate', A.messages[1],
570 "A should transit tenant-one gate")
James E. Blair646322f2017-01-27 15:50:34 -0800571 self.assertHistory([
572 dict(name='project-test2', result='SUCCESS', changes='1,1')])
573
James E. Blairc2a5ed72017-02-20 14:12:01 -0500574 self.fake_gerrit.addEvent(A.getChangeMergedEvent())
James E. Blair7bbd7a32017-03-06 11:36:13 -0800575 self.waitUntilSettled()
James E. Blairc2a5ed72017-02-20 14:12:01 -0500576
James E. Blair646322f2017-01-27 15:50:34 -0800577 # Now that the config change is landed, it should be live for
578 # subsequent changes.
579 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
Tobias Henkelbf24fd12017-07-27 06:13:07 +0200580 B.addApproval('Code-Review', 2)
581 self.fake_gerrit.addEvent(B.addApproval('Approved', 1))
James E. Blair646322f2017-01-27 15:50:34 -0800582 self.waitUntilSettled()
583 self.assertEqual(self.getJobFromHistory('project-test2').result,
584 'SUCCESS')
585 self.assertHistory([
586 dict(name='project-test2', result='SUCCESS', changes='1,1'),
587 dict(name='project-test2', result='SUCCESS', changes='2,1')])
James E. Blairc73c73a2017-01-20 15:15:15 -0800588
James E. Blair6bc10482017-10-20 11:28:53 -0700589 def test_dynamic_template(self):
James E. Blair2a664502017-10-27 11:39:33 -0700590 # Tests that a project can't update a template in another
591 # project.
James E. Blair6bc10482017-10-20 11:28:53 -0700592 in_repo_conf = textwrap.dedent(
593 """
594 - job:
595 name: project-test1
596
597 - project-template:
598 name: common-config-template
599 check:
600 jobs:
601 - project-test1
602
603 - project:
604 name: org/project
605 templates: [common-config-template]
606 """)
607
608 file_dict = {'.zuul.yaml': in_repo_conf}
609 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
610 files=file_dict)
611 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
612 self.waitUntilSettled()
James E. Blair2a664502017-10-27 11:39:33 -0700613
614 self.assertEqual(A.patchsets[0]['approvals'][0]['value'], "-1")
615 self.assertIn('Project template common-config-template '
616 'is already defined',
617 A.messages[0],
618 "A should have failed the check pipeline")
James E. Blair6bc10482017-10-20 11:28:53 -0700619
Tobias Henkelf02cf512017-07-21 22:55:34 +0200620 def test_dynamic_config_non_existing_job(self):
621 """Test that requesting a non existent job fails"""
622 in_repo_conf = textwrap.dedent(
623 """
624 - job:
625 name: project-test1
626
627 - project:
628 name: org/project
629 check:
630 jobs:
631 - non-existent-job
632 """)
633
634 in_repo_playbook = textwrap.dedent(
635 """
636 - hosts: all
637 tasks: []
638 """)
639
640 file_dict = {'.zuul.yaml': in_repo_conf,
641 'playbooks/project-test2.yaml': in_repo_playbook}
642 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
643 files=file_dict)
644 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
645 self.waitUntilSettled()
646 self.assertEqual(A.reported, 1,
647 "A should report failure")
648 self.assertEqual(A.patchsets[0]['approvals'][0]['value'], "-1")
649 self.assertIn('Job non-existent-job not defined', A.messages[0],
650 "A should have failed the check pipeline")
651 self.assertHistory([])
652
653 def test_dynamic_config_non_existing_job_in_template(self):
654 """Test that requesting a non existent job fails"""
655 in_repo_conf = textwrap.dedent(
656 """
657 - job:
658 name: project-test1
659
660 - project-template:
661 name: test-template
662 check:
663 jobs:
664 - non-existent-job
665
666 - project:
667 name: org/project
668 templates:
669 - test-template
670 """)
671
672 in_repo_playbook = textwrap.dedent(
673 """
674 - hosts: all
675 tasks: []
676 """)
677
678 file_dict = {'.zuul.yaml': in_repo_conf,
679 'playbooks/project-test2.yaml': in_repo_playbook}
680 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
681 files=file_dict)
682 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
683 self.waitUntilSettled()
684 self.assertEqual(A.reported, 1,
685 "A should report failure")
686 self.assertEqual(A.patchsets[0]['approvals'][0]['value'], "-1")
687 self.assertIn('Job non-existent-job not defined', A.messages[0],
688 "A should have failed the check pipeline")
689 self.assertHistory([])
690
Tobias Henkel0f714002017-06-30 23:30:52 +0200691 def test_dynamic_config_new_patchset(self):
692 self.executor_server.hold_jobs_in_build = True
693
694 tenant = self.sched.abide.tenants.get('tenant-one')
695 check_pipeline = tenant.layout.pipelines['check']
696
697 in_repo_conf = textwrap.dedent(
698 """
699 - job:
Tobias Henkelf02cf512017-07-21 22:55:34 +0200700 name: project-test1
James E. Blair2f589fe2017-10-26 12:57:41 -0700701 run: playbooks/project-test1.yaml
Tobias Henkelf02cf512017-07-21 22:55:34 +0200702
703 - job:
Tobias Henkel0f714002017-06-30 23:30:52 +0200704 name: project-test2
James E. Blair2f589fe2017-10-26 12:57:41 -0700705 run: playbooks/project-test2.yaml
Tobias Henkel0f714002017-06-30 23:30:52 +0200706
707 - project:
708 name: org/project
709 check:
710 jobs:
711 - project-test2
712 """)
713
714 in_repo_playbook = textwrap.dedent(
715 """
716 - hosts: all
717 tasks: []
718 """)
719
720 file_dict = {'.zuul.yaml': in_repo_conf,
721 'playbooks/project-test2.yaml': in_repo_playbook}
722 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
723 files=file_dict)
724 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
725 self.waitUntilSettled()
726
727 items = check_pipeline.getAllItems()
728 self.assertEqual(items[0].change.number, '1')
729 self.assertEqual(items[0].change.patchset, '1')
730 self.assertTrue(items[0].live)
731
732 in_repo_conf = textwrap.dedent(
733 """
734 - job:
Tobias Henkel0ce7ec62017-07-21 22:50:17 +0200735 name: project-test1
James E. Blair2f589fe2017-10-26 12:57:41 -0700736 run: playbooks/project-test1.yaml
Tobias Henkel0ce7ec62017-07-21 22:50:17 +0200737
738 - job:
Tobias Henkel0f714002017-06-30 23:30:52 +0200739 name: project-test2
James E. Blair2f589fe2017-10-26 12:57:41 -0700740 run: playbooks/project-test2.yaml
Tobias Henkel0f714002017-06-30 23:30:52 +0200741
742 - project:
743 name: org/project
744 check:
745 jobs:
746 - project-test1
747 - project-test2
748 """)
749 file_dict = {'.zuul.yaml': in_repo_conf,
750 'playbooks/project-test2.yaml': in_repo_playbook}
751
752 A.addPatchset(files=file_dict)
753 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(2))
754
755 self.waitUntilSettled()
756
757 items = check_pipeline.getAllItems()
758 self.assertEqual(items[0].change.number, '1')
759 self.assertEqual(items[0].change.patchset, '2')
760 self.assertTrue(items[0].live)
761
762 self.executor_server.hold_jobs_in_build = False
Tobias Henkel0ce7ec62017-07-21 22:50:17 +0200763 self.executor_server.release('project-test1')
764 self.waitUntilSettled()
Tobias Henkel0f714002017-06-30 23:30:52 +0200765 self.executor_server.release()
766 self.waitUntilSettled()
767
Tobias Henkel0ce7ec62017-07-21 22:50:17 +0200768 self.assertHistory([
769 dict(name='project-test2', result='ABORTED', changes='1,1'),
770 dict(name='project-test1', result='SUCCESS', changes='1,2'),
771 dict(name='project-test2', result='SUCCESS', changes='1,2')])
772
James E. Blairff555742017-02-19 11:34:27 -0800773 def test_in_repo_branch(self):
774 in_repo_conf = textwrap.dedent(
775 """
776 - job:
Tobias Henkelf02cf512017-07-21 22:55:34 +0200777 name: project-test1
778
779 - job:
James E. Blairff555742017-02-19 11:34:27 -0800780 name: project-test2
James E. Blair2f589fe2017-10-26 12:57:41 -0700781 run: playbooks/project-test2.yaml
James E. Blairff555742017-02-19 11:34:27 -0800782
783 - project:
784 name: org/project
785 tenant-one-gate:
786 jobs:
787 - project-test2
788 """)
789
790 in_repo_playbook = textwrap.dedent(
791 """
792 - hosts: all
793 tasks: []
794 """)
795
796 file_dict = {'.zuul.yaml': in_repo_conf,
797 'playbooks/project-test2.yaml': in_repo_playbook}
798 self.create_branch('org/project', 'stable')
James E. Blair72facdc2017-08-17 10:29:12 -0700799 self.fake_gerrit.addEvent(
800 self.fake_gerrit.getFakeBranchCreatedEvent(
801 'org/project', 'stable'))
James E. Blair6069f2b2017-09-26 16:34:11 -0700802 self.waitUntilSettled()
James E. Blairff555742017-02-19 11:34:27 -0800803 A = self.fake_gerrit.addFakeChange('org/project', 'stable', 'A',
804 files=file_dict)
Tobias Henkelbf24fd12017-07-27 06:13:07 +0200805 A.addApproval('Code-Review', 2)
806 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
James E. Blairff555742017-02-19 11:34:27 -0800807 self.waitUntilSettled()
808 self.assertEqual(A.data['status'], 'MERGED')
809 self.assertEqual(A.reported, 2,
810 "A should report start and success")
811 self.assertIn('tenant-one-gate', A.messages[1],
812 "A should transit tenant-one gate")
813 self.assertHistory([
814 dict(name='project-test2', result='SUCCESS', changes='1,1')])
815 self.fake_gerrit.addEvent(A.getChangeMergedEvent())
James E. Blair7bbd7a32017-03-06 11:36:13 -0800816 self.waitUntilSettled()
James E. Blairff555742017-02-19 11:34:27 -0800817
818 # The config change should not affect master.
819 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
Tobias Henkelbf24fd12017-07-27 06:13:07 +0200820 B.addApproval('Code-Review', 2)
821 self.fake_gerrit.addEvent(B.addApproval('Approved', 1))
James E. Blairff555742017-02-19 11:34:27 -0800822 self.waitUntilSettled()
823 self.assertHistory([
824 dict(name='project-test2', result='SUCCESS', changes='1,1'),
825 dict(name='project-test1', result='SUCCESS', changes='2,1')])
826
827 # The config change should be live for further changes on
828 # stable.
829 C = self.fake_gerrit.addFakeChange('org/project', 'stable', 'C')
Tobias Henkelbf24fd12017-07-27 06:13:07 +0200830 C.addApproval('Code-Review', 2)
831 self.fake_gerrit.addEvent(C.addApproval('Approved', 1))
James E. Blairff555742017-02-19 11:34:27 -0800832 self.waitUntilSettled()
833 self.assertHistory([
834 dict(name='project-test2', result='SUCCESS', changes='1,1'),
835 dict(name='project-test1', result='SUCCESS', changes='2,1'),
836 dict(name='project-test2', result='SUCCESS', changes='3,1')])
837
James E. Blaira5a12492017-05-03 11:40:48 -0700838 def test_crd_dynamic_config_branch(self):
839 # Test that we can create a job in one repo and be able to use
840 # it from a different branch on a different repo.
841
842 self.create_branch('org/project1', 'stable')
James E. Blair72facdc2017-08-17 10:29:12 -0700843 self.fake_gerrit.addEvent(
844 self.fake_gerrit.getFakeBranchCreatedEvent(
845 'org/project1', 'stable'))
James E. Blaira5a12492017-05-03 11:40:48 -0700846
847 in_repo_conf = textwrap.dedent(
848 """
849 - job:
Tobias Henkelf02cf512017-07-21 22:55:34 +0200850 name: project-test1
851
852 - job:
James E. Blaira5a12492017-05-03 11:40:48 -0700853 name: project-test2
James E. Blair2f589fe2017-10-26 12:57:41 -0700854 run: playbooks/project-test2.yaml
James E. Blaira5a12492017-05-03 11:40:48 -0700855
856 - project:
857 name: org/project
858 check:
859 jobs:
860 - project-test2
861 """)
862
863 in_repo_playbook = textwrap.dedent(
864 """
865 - hosts: all
866 tasks: []
867 """)
868
869 file_dict = {'.zuul.yaml': in_repo_conf,
870 'playbooks/project-test2.yaml': in_repo_playbook}
871 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
872 files=file_dict)
873
874 second_repo_conf = textwrap.dedent(
875 """
876 - project:
877 name: org/project1
878 check:
879 jobs:
880 - project-test2
881 """)
882
883 second_file_dict = {'.zuul.yaml': second_repo_conf}
884 B = self.fake_gerrit.addFakeChange('org/project1', 'stable', 'B',
885 files=second_file_dict)
886 B.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
887 B.subject, A.data['id'])
888
889 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
890 self.waitUntilSettled()
891 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
892 self.waitUntilSettled()
893
894 self.assertEqual(A.reported, 1, "A should report")
895 self.assertHistory([
896 dict(name='project-test2', result='SUCCESS', changes='1,1'),
897 dict(name='project-test2', result='SUCCESS', changes='1,1 2,1'),
898 ])
899
James E. Blair97043882017-09-06 15:51:17 -0700900 def test_yaml_list_error(self):
901 in_repo_conf = textwrap.dedent(
902 """
903 job: foo
904 """)
905
906 file_dict = {'.zuul.yaml': in_repo_conf}
907 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
908 files=file_dict)
909 A.addApproval('Code-Review', 2)
910 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
911 self.waitUntilSettled()
912
913 self.assertEqual(A.data['status'], 'NEW')
914 self.assertEqual(A.reported, 1,
915 "A should report failure")
916 self.assertIn('not a list', A.messages[0],
917 "A should have a syntax error reported")
918
919 def test_yaml_dict_error(self):
920 in_repo_conf = textwrap.dedent(
921 """
922 - job
923 """)
924
925 file_dict = {'.zuul.yaml': in_repo_conf}
926 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
927 files=file_dict)
928 A.addApproval('Code-Review', 2)
929 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
930 self.waitUntilSettled()
931
932 self.assertEqual(A.data['status'], 'NEW')
933 self.assertEqual(A.reported, 1,
934 "A should report failure")
935 self.assertIn('not a dictionary', A.messages[0],
936 "A should have a syntax error reported")
937
938 def test_yaml_key_error(self):
939 in_repo_conf = textwrap.dedent(
940 """
941 - job:
942 name: project-test2
943 """)
944
945 file_dict = {'.zuul.yaml': in_repo_conf}
946 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
947 files=file_dict)
948 A.addApproval('Code-Review', 2)
949 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
950 self.waitUntilSettled()
951
952 self.assertEqual(A.data['status'], 'NEW')
953 self.assertEqual(A.reported, 1,
954 "A should report failure")
955 self.assertIn('has more than one key', A.messages[0],
956 "A should have a syntax error reported")
957
958 def test_yaml_unknown_error(self):
959 in_repo_conf = textwrap.dedent(
960 """
961 - foobar:
962 foo: bar
963 """)
964
965 file_dict = {'.zuul.yaml': in_repo_conf}
966 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
967 files=file_dict)
968 A.addApproval('Code-Review', 2)
969 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
970 self.waitUntilSettled()
971
972 self.assertEqual(A.data['status'], 'NEW')
973 self.assertEqual(A.reported, 1,
974 "A should report failure")
975 self.assertIn('not recognized', A.messages[0],
976 "A should have a syntax error reported")
977
James E. Blair149b69c2017-03-02 10:48:16 -0800978 def test_untrusted_syntax_error(self):
James E. Blaire53250c2017-03-01 14:34:36 -0800979 in_repo_conf = textwrap.dedent(
980 """
981 - job:
982 name: project-test2
983 foo: error
984 """)
985
986 file_dict = {'.zuul.yaml': in_repo_conf}
987 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
988 files=file_dict)
Tobias Henkelbf24fd12017-07-27 06:13:07 +0200989 A.addApproval('Code-Review', 2)
990 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
James E. Blaire53250c2017-03-01 14:34:36 -0800991 self.waitUntilSettled()
992
993 self.assertEqual(A.data['status'], 'NEW')
Tobias Henkel9842bd72017-05-16 13:40:03 +0200994 self.assertEqual(A.reported, 1,
995 "A should report failure")
996 self.assertIn('syntax error', A.messages[0],
James E. Blaire53250c2017-03-01 14:34:36 -0800997 "A should have a syntax error reported")
998
James E. Blair149b69c2017-03-02 10:48:16 -0800999 def test_trusted_syntax_error(self):
1000 in_repo_conf = textwrap.dedent(
1001 """
1002 - job:
1003 name: project-test2
1004 foo: error
1005 """)
1006
1007 file_dict = {'zuul.yaml': in_repo_conf}
1008 A = self.fake_gerrit.addFakeChange('common-config', 'master', 'A',
1009 files=file_dict)
Tobias Henkelbf24fd12017-07-27 06:13:07 +02001010 A.addApproval('Code-Review', 2)
1011 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
James E. Blair149b69c2017-03-02 10:48:16 -08001012 self.waitUntilSettled()
1013
1014 self.assertEqual(A.data['status'], 'NEW')
Tobias Henkel9842bd72017-05-16 13:40:03 +02001015 self.assertEqual(A.reported, 1,
1016 "A should report failure")
1017 self.assertIn('syntax error', A.messages[0],
James E. Blair149b69c2017-03-02 10:48:16 -08001018 "A should have a syntax error reported")
1019
James E. Blair6f140c72017-03-03 10:32:07 -08001020 def test_untrusted_yaml_error(self):
1021 in_repo_conf = textwrap.dedent(
1022 """
1023 - job:
1024 foo: error
1025 """)
1026
1027 file_dict = {'.zuul.yaml': in_repo_conf}
1028 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
1029 files=file_dict)
Tobias Henkelbf24fd12017-07-27 06:13:07 +02001030 A.addApproval('Code-Review', 2)
1031 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
James E. Blair6f140c72017-03-03 10:32:07 -08001032 self.waitUntilSettled()
1033
1034 self.assertEqual(A.data['status'], 'NEW')
Tobias Henkel9842bd72017-05-16 13:40:03 +02001035 self.assertEqual(A.reported, 1,
1036 "A should report failure")
1037 self.assertIn('syntax error', A.messages[0],
James E. Blair6f140c72017-03-03 10:32:07 -08001038 "A should have a syntax error reported")
1039
James E. Blairdb04e6a2017-05-03 14:49:36 -07001040 def test_untrusted_shadow_error(self):
1041 in_repo_conf = textwrap.dedent(
1042 """
1043 - job:
1044 name: common-config-test
1045 """)
1046
1047 file_dict = {'.zuul.yaml': in_repo_conf}
1048 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
1049 files=file_dict)
Tobias Henkelbf24fd12017-07-27 06:13:07 +02001050 A.addApproval('Code-Review', 2)
1051 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
James E. Blairdb04e6a2017-05-03 14:49:36 -07001052 self.waitUntilSettled()
1053
1054 self.assertEqual(A.data['status'], 'NEW')
Tobias Henkel9842bd72017-05-16 13:40:03 +02001055 self.assertEqual(A.reported, 1,
1056 "A should report failure")
1057 self.assertIn('not permitted to shadow', A.messages[0],
James E. Blairdb04e6a2017-05-03 14:49:36 -07001058 "A should have a syntax error reported")
1059
James E. Blaird5656ad2017-06-02 14:29:41 -07001060 def test_untrusted_pipeline_error(self):
1061 in_repo_conf = textwrap.dedent(
1062 """
1063 - pipeline:
1064 name: test
1065 """)
1066
1067 file_dict = {'.zuul.yaml': in_repo_conf}
1068 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
1069 files=file_dict)
Tobias Henkelbf24fd12017-07-27 06:13:07 +02001070 A.addApproval('Code-Review', 2)
1071 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
James E. Blaird5656ad2017-06-02 14:29:41 -07001072 self.waitUntilSettled()
1073
1074 self.assertEqual(A.data['status'], 'NEW')
1075 self.assertEqual(A.reported, 1,
1076 "A should report failure")
1077 self.assertIn('Pipelines may not be defined', A.messages[0],
1078 "A should have a syntax error reported")
1079
1080 def test_untrusted_project_error(self):
1081 in_repo_conf = textwrap.dedent(
1082 """
1083 - project:
1084 name: org/project1
1085 """)
1086
1087 file_dict = {'.zuul.yaml': in_repo_conf}
1088 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
1089 files=file_dict)
Tobias Henkelbf24fd12017-07-27 06:13:07 +02001090 A.addApproval('Code-Review', 2)
1091 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
James E. Blaird5656ad2017-06-02 14:29:41 -07001092 self.waitUntilSettled()
1093
1094 self.assertEqual(A.data['status'], 'NEW')
1095 self.assertEqual(A.reported, 1,
1096 "A should report failure")
1097 self.assertIn('the only project definition permitted', A.messages[0],
1098 "A should have a syntax error reported")
1099
James E. Blairf03173b2017-10-10 10:46:43 -07001100 def test_untrusted_depends_on_trusted(self):
1101 with open(os.path.join(FIXTURE_DIR,
1102 'config/in-repo/git/',
1103 'common-config/zuul.yaml')) as f:
1104 common_config = f.read()
1105
1106 common_config += textwrap.dedent(
1107 """
1108 - job:
1109 name: project-test9
1110 """)
1111
1112 file_dict = {'zuul.yaml': common_config}
1113 A = self.fake_gerrit.addFakeChange('common-config', 'master', 'A',
1114 files=file_dict)
1115 in_repo_conf = textwrap.dedent(
1116 """
1117 - job:
1118 name: project-test1
1119 - project:
1120 name: org/project
1121 check:
1122 jobs:
1123 - project-test9
1124 """)
1125
1126 file_dict = {'zuul.yaml': in_repo_conf}
1127 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B',
1128 files=file_dict)
1129 B.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
1130 B.subject, A.data['id'])
1131 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
1132 self.waitUntilSettled()
1133
1134 self.assertEqual(B.data['status'], 'NEW')
1135 self.assertEqual(B.reported, 1,
1136 "B should report failure")
1137 self.assertIn('depends on a change to a config project',
1138 B.messages[0],
1139 "A should have a syntax error reported")
1140
James E. Blaire64b0e42017-06-08 11:23:34 -07001141 def test_duplicate_node_error(self):
1142 in_repo_conf = textwrap.dedent(
1143 """
1144 - nodeset:
1145 name: duplicate
1146 nodes:
1147 - name: compute
James E. Blair16d96a02017-06-08 11:32:56 -07001148 label: foo
James E. Blaire64b0e42017-06-08 11:23:34 -07001149 - name: compute
James E. Blair16d96a02017-06-08 11:32:56 -07001150 label: foo
James E. Blaire64b0e42017-06-08 11:23:34 -07001151 """)
1152
1153 file_dict = {'.zuul.yaml': in_repo_conf}
1154 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
1155 files=file_dict)
Tobias Henkelbf24fd12017-07-27 06:13:07 +02001156 A.addApproval('Code-Review', 2)
1157 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
James E. Blaire64b0e42017-06-08 11:23:34 -07001158 self.waitUntilSettled()
1159
1160 self.assertEqual(A.data['status'], 'NEW')
1161 self.assertEqual(A.reported, 1,
1162 "A should report failure")
1163 self.assertIn('appears multiple times', A.messages[0],
1164 "A should have a syntax error reported")
1165
1166 def test_duplicate_group_error(self):
1167 in_repo_conf = textwrap.dedent(
1168 """
1169 - nodeset:
1170 name: duplicate
1171 nodes:
1172 - name: compute
James E. Blair16d96a02017-06-08 11:32:56 -07001173 label: foo
James E. Blaire64b0e42017-06-08 11:23:34 -07001174 groups:
1175 - name: group
1176 nodes: compute
1177 - name: group
1178 nodes: compute
1179 """)
1180
1181 file_dict = {'.zuul.yaml': in_repo_conf}
1182 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
1183 files=file_dict)
Tobias Henkelbf24fd12017-07-27 06:13:07 +02001184 A.addApproval('Code-Review', 2)
1185 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
James E. Blaire64b0e42017-06-08 11:23:34 -07001186 self.waitUntilSettled()
1187
1188 self.assertEqual(A.data['status'], 'NEW')
1189 self.assertEqual(A.reported, 1,
1190 "A should report failure")
1191 self.assertIn('appears multiple times', A.messages[0],
1192 "A should have a syntax error reported")
1193
James E. Blair4ae399f2017-09-20 17:15:09 -07001194 def test_secret_not_found_error(self):
1195 in_repo_conf = textwrap.dedent(
1196 """
1197 - job:
1198 name: test
1199 secrets: does-not-exist
1200 """)
1201
1202 file_dict = {'.zuul.yaml': in_repo_conf}
1203 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
1204 files=file_dict)
1205 A.addApproval('Code-Review', 2)
1206 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
1207 self.waitUntilSettled()
1208
1209 self.assertEqual(A.data['status'], 'NEW')
1210 self.assertEqual(A.reported, 1,
1211 "A should report failure")
1212 self.assertIn('secret "does-not-exist" was not found', A.messages[0],
1213 "A should have a syntax error reported")
1214
1215 def test_nodeset_not_found_error(self):
1216 in_repo_conf = textwrap.dedent(
1217 """
1218 - job:
1219 name: test
1220 nodeset: does-not-exist
1221 """)
1222
1223 file_dict = {'.zuul.yaml': in_repo_conf}
1224 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
1225 files=file_dict)
1226 A.addApproval('Code-Review', 2)
1227 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
1228 self.waitUntilSettled()
1229
1230 self.assertEqual(A.data['status'], 'NEW')
1231 self.assertEqual(A.reported, 1,
1232 "A should report failure")
1233 self.assertIn('nodeset "does-not-exist" was not found', A.messages[0],
1234 "A should have a syntax error reported")
1235
James E. Blair89e25eb2017-09-26 09:11:31 -07001236 def test_template_not_found_error(self):
1237 in_repo_conf = textwrap.dedent(
1238 """
1239 - job:
1240 name: project-test1
1241 - project:
1242 name: org/project
1243 templates:
1244 - does-not-exist
1245 """)
1246
1247 file_dict = {'.zuul.yaml': in_repo_conf}
1248 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
1249 files=file_dict)
1250 A.addApproval('Code-Review', 2)
1251 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
1252 self.waitUntilSettled()
1253
1254 self.assertEqual(A.data['status'], 'NEW')
1255 self.assertEqual(A.reported, 1,
1256 "A should report failure")
1257 self.assertIn('project template "does-not-exist" was not found',
1258 A.messages[0],
1259 "A should have a syntax error reported")
1260
Monty Taylor8be3c0c2017-10-06 10:37:37 -05001261 def test_job_list_in_project_template_not_dict_error(self):
1262 in_repo_conf = textwrap.dedent(
1263 """
1264 - job:
1265 name: project-test1
1266 - project-template:
1267 name: some-jobs
1268 check:
1269 jobs:
1270 - project-test1:
1271 - required-projects:
1272 org/project2
1273 """)
1274
1275 file_dict = {'.zuul.yaml': in_repo_conf}
1276 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
1277 files=file_dict)
1278 A.addApproval('Code-Review', 2)
1279 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
1280 self.waitUntilSettled()
1281
1282 self.assertEqual(A.data['status'], 'NEW')
1283 self.assertEqual(A.reported, 1,
1284 "A should report failure")
1285 self.assertIn('expected str for dictionary value',
1286 A.messages[0], "A should have a syntax error reported")
1287
1288 def test_job_list_in_project_not_dict_error(self):
1289 in_repo_conf = textwrap.dedent(
1290 """
1291 - job:
1292 name: project-test1
1293 - project:
1294 name: org/project1
1295 check:
1296 jobs:
1297 - project-test1:
1298 - required-projects:
1299 org/project2
1300 """)
1301
1302 file_dict = {'.zuul.yaml': in_repo_conf}
1303 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
1304 files=file_dict)
1305 A.addApproval('Code-Review', 2)
1306 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
1307 self.waitUntilSettled()
1308
1309 self.assertEqual(A.data['status'], 'NEW')
1310 self.assertEqual(A.reported, 1,
1311 "A should report failure")
1312 self.assertIn('expected str for dictionary value',
1313 A.messages[0], "A should have a syntax error reported")
1314
James E. Blair1235f142017-10-07 09:11:43 -07001315 def test_project_template(self):
1316 # Tests that a project template is not modified when used, and
1317 # can therefore be used in subsequent reconfigurations.
1318 in_repo_conf = textwrap.dedent(
1319 """
1320 - job:
1321 name: project-test1
James E. Blair2f589fe2017-10-26 12:57:41 -07001322 run: playbooks/project-test1.yaml
James E. Blair1235f142017-10-07 09:11:43 -07001323 - project-template:
1324 name: some-jobs
1325 tenant-one-gate:
1326 jobs:
1327 - project-test1:
1328 required-projects:
1329 - org/project1
1330 - project:
1331 name: org/project
1332 templates:
1333 - some-jobs
1334 """)
1335
1336 file_dict = {'.zuul.yaml': in_repo_conf}
1337 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
1338 files=file_dict)
1339 A.addApproval('Code-Review', 2)
1340 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
1341 self.waitUntilSettled()
1342 self.assertEqual(A.data['status'], 'MERGED')
1343 self.fake_gerrit.addEvent(A.getChangeMergedEvent())
1344 self.waitUntilSettled()
1345 in_repo_conf = textwrap.dedent(
1346 """
1347 - project:
1348 name: org/project1
1349 templates:
1350 - some-jobs
1351 """)
1352 file_dict = {'.zuul.yaml': in_repo_conf}
1353 B = self.fake_gerrit.addFakeChange('org/project1', 'master', 'B',
1354 files=file_dict)
1355 B.addApproval('Code-Review', 2)
1356 self.fake_gerrit.addEvent(B.addApproval('Approved', 1))
1357 self.waitUntilSettled()
1358 self.assertEqual(B.data['status'], 'MERGED')
1359
James E. Blairbccdfcf2017-10-07 13:37:26 -07001360 def test_job_remove_add(self):
1361 # Tests that a job can be removed from one repo and added in another.
1362 # First, remove the current config for project1 since it
1363 # references the job we want to remove.
1364 file_dict = {'.zuul.yaml': None}
1365 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A',
1366 files=file_dict)
1367 A.setMerged()
1368 self.fake_gerrit.addEvent(A.getChangeMergedEvent())
1369 self.waitUntilSettled()
1370 # Then propose a change to delete the job from one repo...
1371 file_dict = {'.zuul.yaml': None}
1372 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B',
1373 files=file_dict)
1374 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
1375 self.waitUntilSettled()
1376 # ...and a second that depends on it that adds it to another repo.
1377 in_repo_conf = textwrap.dedent(
1378 """
1379 - job:
1380 name: project-test1
James E. Blair2f589fe2017-10-26 12:57:41 -07001381 run: playbooks/project-test1.yaml
James E. Blairbccdfcf2017-10-07 13:37:26 -07001382
1383 - project:
1384 name: org/project1
1385 check:
1386 jobs:
1387 - project-test1
1388 """)
1389 in_repo_playbook = textwrap.dedent(
1390 """
1391 - hosts: all
1392 tasks: []
1393 """)
1394 file_dict = {'.zuul.yaml': in_repo_conf,
1395 'playbooks/project-test1.yaml': in_repo_playbook}
1396 C = self.fake_gerrit.addFakeChange('org/project1', 'master', 'C',
1397 files=file_dict,
1398 parent='refs/changes/1/1/1')
1399 C.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
1400 C.subject, B.data['id'])
1401 self.fake_gerrit.addEvent(C.getPatchsetCreatedEvent(1))
1402 self.waitUntilSettled()
1403 self.assertHistory([
1404 dict(name='project-test1', result='SUCCESS', changes='2,1 3,1'),
1405 ], ordered=False)
1406
James E. Blair09f9ffe2017-07-11 15:30:25 -07001407 def test_multi_repo(self):
1408 downstream_repo_conf = textwrap.dedent(
1409 """
1410 - project:
1411 name: org/project1
1412 tenant-one-gate:
1413 jobs:
1414 - project-test1
1415
1416 - job:
1417 name: project1-test1
1418 parent: project-test1
1419 """)
1420
1421 file_dict = {'.zuul.yaml': downstream_repo_conf}
1422 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A',
1423 files=file_dict)
Tobias Henkelbf24fd12017-07-27 06:13:07 +02001424 A.addApproval('Code-Review', 2)
1425 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
James E. Blair09f9ffe2017-07-11 15:30:25 -07001426 self.waitUntilSettled()
1427
1428 self.assertEqual(A.data['status'], 'MERGED')
1429 self.fake_gerrit.addEvent(A.getChangeMergedEvent())
1430 self.waitUntilSettled()
1431
1432 upstream_repo_conf = textwrap.dedent(
1433 """
1434 - job:
1435 name: project-test1
James E. Blair2f589fe2017-10-26 12:57:41 -07001436 run: playbooks/project-test1.yaml
James E. Blair09f9ffe2017-07-11 15:30:25 -07001437
1438 - job:
1439 name: project-test2
1440
1441 - project:
1442 name: org/project
1443 tenant-one-gate:
1444 jobs:
1445 - project-test1
1446 """)
1447
1448 file_dict = {'.zuul.yaml': upstream_repo_conf}
1449 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B',
1450 files=file_dict)
Tobias Henkelbf24fd12017-07-27 06:13:07 +02001451 B.addApproval('Code-Review', 2)
1452 self.fake_gerrit.addEvent(B.addApproval('Approved', 1))
James E. Blair09f9ffe2017-07-11 15:30:25 -07001453 self.waitUntilSettled()
1454
1455 self.assertEqual(B.data['status'], 'MERGED')
1456 self.fake_gerrit.addEvent(B.getChangeMergedEvent())
1457 self.waitUntilSettled()
1458
1459 tenant = self.sched.abide.tenants.get('tenant-one')
1460 # Ensure the latest change is reflected in the config; if it
1461 # isn't this will raise an exception.
1462 tenant.layout.getJob('project-test2')
1463
James E. Blair332636e2017-09-05 10:14:35 -07001464 def test_pipeline_error(self):
1465 with open(os.path.join(FIXTURE_DIR,
1466 'config/in-repo/git/',
1467 'common-config/zuul.yaml')) as f:
1468 base_common_config = f.read()
1469
1470 in_repo_conf_A = textwrap.dedent(
1471 """
1472 - pipeline:
1473 name: periodic
1474 foo: error
1475 """)
1476
1477 file_dict = {'zuul.yaml': None,
1478 'zuul.d/main.yaml': base_common_config,
1479 'zuul.d/test1.yaml': in_repo_conf_A}
1480 A = self.fake_gerrit.addFakeChange('common-config', 'master', 'A',
1481 files=file_dict)
1482 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
1483 self.waitUntilSettled()
1484 self.assertEqual(A.reported, 1,
1485 "A should report failure")
1486 self.assertIn('syntax error',
1487 A.messages[0],
1488 "A should have an error reported")
1489
1490 def test_change_series_error(self):
1491 with open(os.path.join(FIXTURE_DIR,
1492 'config/in-repo/git/',
1493 'common-config/zuul.yaml')) as f:
1494 base_common_config = f.read()
1495
1496 in_repo_conf_A = textwrap.dedent(
1497 """
1498 - pipeline:
1499 name: periodic
1500 foo: error
1501 """)
1502
1503 file_dict = {'zuul.yaml': None,
1504 'zuul.d/main.yaml': base_common_config,
1505 'zuul.d/test1.yaml': in_repo_conf_A}
1506 A = self.fake_gerrit.addFakeChange('common-config', 'master', 'A',
1507 files=file_dict)
1508
1509 in_repo_conf_B = textwrap.dedent(
1510 """
1511 - job:
1512 name: project-test2
1513 foo: error
1514 """)
1515
1516 file_dict = {'zuul.yaml': None,
1517 'zuul.d/main.yaml': base_common_config,
1518 'zuul.d/test1.yaml': in_repo_conf_A,
1519 'zuul.d/test2.yaml': in_repo_conf_B}
1520 B = self.fake_gerrit.addFakeChange('common-config', 'master', 'B',
1521 files=file_dict)
1522 B.setDependsOn(A, 1)
1523 C = self.fake_gerrit.addFakeChange('common-config', 'master', 'C')
1524 C.setDependsOn(B, 1)
1525 self.fake_gerrit.addEvent(C.getPatchsetCreatedEvent(1))
1526 self.waitUntilSettled()
1527
1528 self.assertEqual(C.reported, 1,
1529 "C should report failure")
1530 self.assertIn('depends on a change that failed to merge',
1531 C.messages[0],
1532 "C should have an error reported")
1533
James E. Blairc73c73a2017-01-20 15:15:15 -08001534
James E. Blairc9455002017-09-06 09:22:19 -07001535class TestInRepoJoin(ZuulTestCase):
1536 # In this config, org/project is not a member of any pipelines, so
1537 # that we may test the changes that cause it to join them.
1538
1539 tenant_config_file = 'config/in-repo-join/main.yaml'
1540
1541 def test_dynamic_dependent_pipeline(self):
1542 # Test dynamically adding a project to a
1543 # dependent pipeline for the first time
1544 self.executor_server.hold_jobs_in_build = True
1545
1546 tenant = self.sched.abide.tenants.get('tenant-one')
1547 gate_pipeline = tenant.layout.pipelines['gate']
1548
1549 in_repo_conf = textwrap.dedent(
1550 """
1551 - job:
1552 name: project-test1
James E. Blair2f589fe2017-10-26 12:57:41 -07001553 run: playbooks/project-test1.yaml
James E. Blairc9455002017-09-06 09:22:19 -07001554
1555 - job:
1556 name: project-test2
James E. Blair2f589fe2017-10-26 12:57:41 -07001557 run: playbooks/project-test2.yaml
James E. Blairc9455002017-09-06 09:22:19 -07001558
1559 - project:
1560 name: org/project
1561 gate:
1562 jobs:
1563 - project-test2
1564 """)
1565
1566 in_repo_playbook = textwrap.dedent(
1567 """
1568 - hosts: all
1569 tasks: []
1570 """)
1571
1572 file_dict = {'.zuul.yaml': in_repo_conf,
1573 'playbooks/project-test2.yaml': in_repo_playbook}
1574 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
1575 files=file_dict)
1576 A.addApproval('Code-Review', 2)
1577 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
1578 self.waitUntilSettled()
1579
1580 items = gate_pipeline.getAllItems()
1581 self.assertEqual(items[0].change.number, '1')
1582 self.assertEqual(items[0].change.patchset, '1')
1583 self.assertTrue(items[0].live)
1584
1585 self.executor_server.hold_jobs_in_build = False
1586 self.executor_server.release()
1587 self.waitUntilSettled()
1588
1589 # Make sure the dynamic queue got cleaned up
1590 self.assertEqual(gate_pipeline.queues, [])
1591
1592 def test_dynamic_dependent_pipeline_failure(self):
1593 # Test that a change behind a failing change adding a project
1594 # to a dependent pipeline is dequeued.
1595 self.executor_server.hold_jobs_in_build = True
1596
1597 in_repo_conf = textwrap.dedent(
1598 """
1599 - job:
1600 name: project-test1
James E. Blair2f589fe2017-10-26 12:57:41 -07001601 run: playbooks/project-test1.yaml
James E. Blairc9455002017-09-06 09:22:19 -07001602
1603 - project:
1604 name: org/project
1605 gate:
1606 jobs:
1607 - project-test1
1608 """)
1609
1610 file_dict = {'.zuul.yaml': in_repo_conf}
1611 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
1612 files=file_dict)
1613 self.executor_server.failJob('project-test1', A)
1614 A.addApproval('Code-Review', 2)
1615 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
1616 self.waitUntilSettled()
1617
1618 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
1619 B.addApproval('Code-Review', 2)
1620 self.fake_gerrit.addEvent(B.addApproval('Approved', 1))
1621 self.waitUntilSettled()
1622
James E. Blair3490c5d2017-09-07 08:33:23 -07001623 self.orderedRelease()
James E. Blairc9455002017-09-06 09:22:19 -07001624 self.waitUntilSettled()
1625 self.assertEqual(A.reported, 2,
1626 "A should report start and failure")
1627 self.assertEqual(A.data['status'], 'NEW')
1628 self.assertEqual(B.reported, 1,
1629 "B should report start")
1630 self.assertHistory([
1631 dict(name='project-test1', result='FAILURE', changes='1,1'),
James E. Blair3490c5d2017-09-07 08:33:23 -07001632 dict(name='project-test1', result='ABORTED', changes='1,1 2,1'),
James E. Blairc9455002017-09-06 09:22:19 -07001633 ], ordered=False)
1634
James E. Blair0af198f2017-09-06 09:52:35 -07001635 def test_dynamic_dependent_pipeline_absent(self):
1636 # Test that a series of dependent changes don't report merge
1637 # failures to a pipeline they aren't in.
1638 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1639 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
1640 B.setDependsOn(A, 1)
1641
1642 A.addApproval('Code-Review', 2)
1643 A.addApproval('Approved', 1)
1644 B.addApproval('Code-Review', 2)
1645 self.fake_gerrit.addEvent(B.addApproval('Approved', 1))
1646 self.waitUntilSettled()
1647 self.assertEqual(A.reported, 0,
1648 "A should not report")
1649 self.assertEqual(A.data['status'], 'NEW')
1650 self.assertEqual(B.reported, 0,
1651 "B should not report")
1652 self.assertEqual(B.data['status'], 'NEW')
1653 self.assertHistory([])
1654
James E. Blairc9455002017-09-06 09:22:19 -07001655
James E. Blairc73c73a2017-01-20 15:15:15 -08001656class TestAnsible(AnsibleZuulTestCase):
1657 # A temporary class to hold new tests while others are disabled
1658
1659 tenant_config_file = 'config/ansible/main.yaml'
1660
1661 def test_playbook(self):
Jamie Lennox7655b552017-03-17 12:33:38 +11001662 # Keep the jobdir around so we can inspect contents if an
1663 # assert fails.
1664 self.executor_server.keep_jobdir = True
1665 # Output extra ansible info so we might see errors.
1666 self.executor_server.verbose = True
1667 # Add a site variables file, used by check-vars
1668 path = os.path.join(FIXTURE_DIR, 'config', 'ansible',
1669 'variables.yaml')
1670 self.config.set('executor', 'variables', path)
James E. Blairc73c73a2017-01-20 15:15:15 -08001671 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1672 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
1673 self.waitUntilSettled()
Tobias Henkel077f2f32017-05-30 20:16:46 +02001674 build_timeout = self.getJobFromHistory('timeout')
Jamie Lennox7655b552017-03-17 12:33:38 +11001675 with self.jobLog(build_timeout):
1676 self.assertEqual(build_timeout.result, 'TIMED_OUT')
Tobias Henkel077f2f32017-05-30 20:16:46 +02001677 build_faillocal = self.getJobFromHistory('faillocal')
Jamie Lennox7655b552017-03-17 12:33:38 +11001678 with self.jobLog(build_faillocal):
1679 self.assertEqual(build_faillocal.result, 'FAILURE')
Tobias Henkel077f2f32017-05-30 20:16:46 +02001680 build_failpost = self.getJobFromHistory('failpost')
Jamie Lennox7655b552017-03-17 12:33:38 +11001681 with self.jobLog(build_failpost):
1682 self.assertEqual(build_failpost.result, 'POST_FAILURE')
Tobias Henkel077f2f32017-05-30 20:16:46 +02001683 build_check_vars = self.getJobFromHistory('check-vars')
Jamie Lennox7655b552017-03-17 12:33:38 +11001684 with self.jobLog(build_check_vars):
1685 self.assertEqual(build_check_vars.result, 'SUCCESS')
Monty Tayloraff8b402017-08-16 18:40:41 -05001686 build_check_secret_names = self.getJobFromHistory('check-secret-names')
1687 with self.jobLog(build_check_secret_names):
1688 self.assertEqual(build_check_secret_names.result, 'SUCCESS')
Tobias Henkel077f2f32017-05-30 20:16:46 +02001689 build_hello = self.getJobFromHistory('hello-world')
Jamie Lennox7655b552017-03-17 12:33:38 +11001690 with self.jobLog(build_hello):
1691 self.assertEqual(build_hello.result, 'SUCCESS')
Tobias Henkel077f2f32017-05-30 20:16:46 +02001692 build_python27 = self.getJobFromHistory('python27')
Jamie Lennox7655b552017-03-17 12:33:38 +11001693 with self.jobLog(build_python27):
1694 self.assertEqual(build_python27.result, 'SUCCESS')
1695 flag_path = os.path.join(self.test_root,
1696 build_python27.uuid + '.flag')
1697 self.assertTrue(os.path.exists(flag_path))
1698 copied_path = os.path.join(self.test_root, build_python27.uuid +
1699 '.copied')
1700 self.assertTrue(os.path.exists(copied_path))
1701 failed_path = os.path.join(self.test_root, build_python27.uuid +
1702 '.failed')
1703 self.assertFalse(os.path.exists(failed_path))
1704 pre_flag_path = os.path.join(self.test_root, build_python27.uuid +
1705 '.pre.flag')
1706 self.assertTrue(os.path.exists(pre_flag_path))
1707 post_flag_path = os.path.join(self.test_root, build_python27.uuid +
1708 '.post.flag')
1709 self.assertTrue(os.path.exists(post_flag_path))
1710 bare_role_flag_path = os.path.join(self.test_root,
1711 build_python27.uuid +
1712 '.bare-role.flag')
1713 self.assertTrue(os.path.exists(bare_role_flag_path))
1714 secrets_path = os.path.join(self.test_root,
1715 build_python27.uuid + '.secrets')
1716 with open(secrets_path) as f:
1717 self.assertEqual(f.read(), "test-username test-password")
James E. Blairb9c0d772017-03-03 14:34:49 -08001718
Jamie Lennox7655b552017-03-17 12:33:38 +11001719 msg = A.messages[0]
1720 success = "{} https://success.example.com/zuul-logs/{}"
1721 fail = "{} https://failure.example.com/zuul-logs/{}"
1722 self.assertIn(success.format("python27", build_python27.uuid), msg)
1723 self.assertIn(fail.format("faillocal", build_faillocal.uuid), msg)
1724 self.assertIn(success.format("check-vars",
1725 build_check_vars.uuid), msg)
1726 self.assertIn(success.format("hello-world", build_hello.uuid), msg)
1727 self.assertIn(fail.format("timeout", build_timeout.uuid), msg)
1728 self.assertIn(fail.format("failpost", build_failpost.uuid), msg)
Tobias Henkel077f2f32017-05-30 20:16:46 +02001729
James E. Blairabbaa6f2017-04-06 16:11:44 -07001730 def _add_job(self, job_name):
1731 conf = textwrap.dedent(
1732 """
1733 - job:
1734 name: %s
James E. Blair2f589fe2017-10-26 12:57:41 -07001735 run: playbooks/%s.yaml
James E. Blairabbaa6f2017-04-06 16:11:44 -07001736
1737 - project:
1738 name: org/plugin-project
1739 check:
1740 jobs:
1741 - %s
James E. Blair2f589fe2017-10-26 12:57:41 -07001742 """ % (job_name, job_name, job_name))
James E. Blairabbaa6f2017-04-06 16:11:44 -07001743
1744 file_dict = {'.zuul.yaml': conf}
1745 A = self.fake_gerrit.addFakeChange('org/plugin-project', 'master', 'A',
1746 files=file_dict)
1747 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
1748 self.waitUntilSettled()
1749
1750 def test_plugins(self):
1751 # Keep the jobdir around so we can inspect contents if an
1752 # assert fails.
1753 self.executor_server.keep_jobdir = True
1754 # Output extra ansible info so we might see errors.
1755 self.executor_server.verbose = True
1756
1757 count = 0
1758 plugin_tests = [
1759 ('passwd', 'FAILURE'),
1760 ('cartesian', 'SUCCESS'),
1761 ('consul_kv', 'FAILURE'),
1762 ('credstash', 'FAILURE'),
1763 ('csvfile_good', 'SUCCESS'),
1764 ('csvfile_bad', 'FAILURE'),
Monty Taylor93ad2212017-08-02 14:59:50 -05001765 ('uri_bad_path', 'FAILURE'),
1766 ('uri_bad_scheme', 'FAILURE'),
Monty Taylor788a40e2017-08-02 16:14:05 -05001767 ('block_local_override', 'FAILURE'),
Monty Taylor8da768f2017-08-31 14:15:35 -05001768 ('file_local_good', 'SUCCESS'),
1769 ('file_local_bad', 'FAILURE'),
James E. Blairabbaa6f2017-04-06 16:11:44 -07001770 ]
1771 for job_name, result in plugin_tests:
1772 count += 1
1773 self._add_job(job_name)
1774
1775 job = self.getJobFromHistory(job_name)
1776 with self.jobLog(job):
1777 self.assertEqual(count, len(self.history))
1778 build = self.history[-1]
1779 self.assertEqual(build.result, result)
1780
1781 # TODOv3(jeblair): parse the ansible output and verify we're
1782 # getting the exception we expect.
1783
James E. Blairb9c0d772017-03-03 14:34:49 -08001784
James E. Blaira4d4eef2017-06-30 14:49:17 -07001785class TestPrePlaybooks(AnsibleZuulTestCase):
1786 # A temporary class to hold new tests while others are disabled
1787
1788 tenant_config_file = 'config/pre-playbook/main.yaml'
1789
1790 def test_pre_playbook_fail(self):
1791 # Test that we run the post playbooks (but not the actual
1792 # playbook) when a pre-playbook fails.
1793 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1794 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
1795 self.waitUntilSettled()
1796 build = self.getJobFromHistory('python27')
1797 self.assertIsNone(build.result)
1798 self.assertIn('RETRY_LIMIT', A.messages[0])
1799 flag_path = os.path.join(self.test_root, build.uuid +
1800 '.main.flag')
1801 self.assertFalse(os.path.exists(flag_path))
1802 pre_flag_path = os.path.join(self.test_root, build.uuid +
1803 '.pre.flag')
1804 self.assertFalse(os.path.exists(pre_flag_path))
1805 post_flag_path = os.path.join(self.test_root, build.uuid +
1806 '.post.flag')
James E. Blair21037782017-07-19 11:56:55 -07001807 self.assertTrue(os.path.exists(post_flag_path),
1808 "The file %s should exist" % post_flag_path)
James E. Blaira4d4eef2017-06-30 14:49:17 -07001809
1810
James E. Blairbacbb882017-10-17 09:48:23 -07001811class TestPostPlaybooks(AnsibleZuulTestCase):
1812 tenant_config_file = 'config/post-playbook/main.yaml'
1813
1814 def test_post_playbook_abort(self):
1815 # Test that when we abort a job in the post playbook, that we
1816 # don't send back POST_FAILURE.
1817 self.executor_server.verbose = True
1818 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1819 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
1820
1821 while not len(self.builds):
1822 time.sleep(0.1)
1823 build = self.builds[0]
1824
1825 post_start = os.path.join(self.test_root, build.uuid +
1826 '.post_start.flag')
1827 start = time.time()
1828 while time.time() < start + 90:
1829 if os.path.exists(post_start):
1830 break
1831 time.sleep(0.1)
1832 # The post playbook has started, abort the job
1833 self.fake_gerrit.addEvent(A.getChangeAbandonedEvent())
1834 self.waitUntilSettled()
1835
1836 build = self.getJobFromHistory('python27')
1837 self.assertEqual('ABORTED', build.result)
1838
1839 post_end = os.path.join(self.test_root, build.uuid +
1840 '.post_end.flag')
1841 self.assertTrue(os.path.exists(post_start))
1842 self.assertFalse(os.path.exists(post_end))
1843
1844
James E. Blairb9c0d772017-03-03 14:34:49 -08001845class TestBrokenConfig(ZuulTestCase):
1846 # Test that we get an appropriate syntax error if we start with a
1847 # broken config.
1848
1849 tenant_config_file = 'config/broken/main.yaml'
1850
1851 def setUp(self):
1852 with testtools.ExpectedException(
1853 zuul.configloader.ConfigurationSyntaxError,
1854 "\nZuul encountered a syntax error"):
1855 super(TestBrokenConfig, self).setUp()
1856
1857 def test_broken_config_on_startup(self):
1858 pass
Ricardo Carrillo Cruz22994f92016-12-02 11:41:58 +00001859
1860
1861class TestProjectKeys(ZuulTestCase):
1862 # Test that we can generate project keys
1863
1864 # Normally the test infrastructure copies a static key in place
1865 # for each project before starting tests. This saves time because
1866 # Zuul's automatic key-generation on startup can be slow. To make
1867 # sure we exercise that code, in this test we allow Zuul to create
1868 # keys for the project on startup.
1869 create_project_keys = True
Tobias Henkelabf973e2017-07-28 10:07:34 +02001870 config_file = 'zuul-connections-gerrit-and-github.conf'
Ricardo Carrillo Cruz22994f92016-12-02 11:41:58 +00001871 tenant_config_file = 'config/in-repo/main.yaml'
1872
1873 def test_key_generation(self):
1874 key_root = os.path.join(self.state_root, 'keys')
1875 private_key_file = os.path.join(key_root, 'gerrit/org/project.pem')
1876 # Make sure that a proper key was created on startup
1877 with open(private_key_file, "rb") as f:
James E. Blairbf1a4f22017-03-17 10:59:37 -07001878 private_key, public_key = \
1879 encryption.deserialize_rsa_keypair(f.read())
Ricardo Carrillo Cruz22994f92016-12-02 11:41:58 +00001880
1881 with open(os.path.join(FIXTURE_DIR, 'private.pem')) as i:
1882 fixture_private_key = i.read()
1883
1884 # Make sure that we didn't just end up with the static fixture
1885 # key
1886 self.assertNotEqual(fixture_private_key, private_key)
1887
1888 # Make sure it's the right length
1889 self.assertEqual(4096, private_key.key_size)
James E. Blairbce76932017-05-04 10:03:15 -07001890
1891
James E. Blairbb94dfa2017-07-11 07:45:19 -07001892class RoleTestCase(ZuulTestCase):
James E. Blair1b27f6a2017-07-14 14:09:07 -07001893 def _assertRolePath(self, build, playbook, content):
1894 path = os.path.join(self.test_root, build.uuid,
1895 'ansible', playbook, 'ansible.cfg')
1896 roles_paths = []
1897 with open(path) as f:
1898 for line in f:
1899 if line.startswith('roles_path'):
1900 roles_paths.append(line)
1901 print(roles_paths)
1902 if content:
1903 self.assertEqual(len(roles_paths), 1,
1904 "Should have one roles_path line in %s" %
1905 (playbook,))
1906 self.assertIn(content, roles_paths[0])
1907 else:
1908 self.assertEqual(len(roles_paths), 0,
1909 "Should have no roles_path line in %s" %
1910 (playbook,))
1911
James E. Blairbb94dfa2017-07-11 07:45:19 -07001912
1913class TestRoles(RoleTestCase):
1914 tenant_config_file = 'config/roles/main.yaml'
1915
James E. Blairbce76932017-05-04 10:03:15 -07001916 def test_role(self):
1917 # This exercises a proposed change to a role being checked out
1918 # and used.
1919 A = self.fake_gerrit.addFakeChange('bare-role', 'master', 'A')
1920 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1921 B.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
1922 B.subject, A.data['id'])
1923 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
1924 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
1925 self.waitUntilSettled()
1926 self.assertHistory([
1927 dict(name='project-test', result='SUCCESS', changes='1,1 2,1'),
1928 ])
James E. Blair6459db12017-06-29 14:57:20 -07001929
James E. Blair1b27f6a2017-07-14 14:09:07 -07001930 def test_role_inheritance(self):
1931 self.executor_server.hold_jobs_in_build = True
1932 conf = textwrap.dedent(
1933 """
1934 - job:
1935 name: parent
1936 roles:
1937 - zuul: bare-role
Ian Wienand548c43c2017-12-05 14:16:32 +11001938 pre-run: playbooks/parent-pre.yaml
1939 post-run: playbooks/parent-post.yaml
James E. Blair1b27f6a2017-07-14 14:09:07 -07001940
1941 - job:
1942 name: project-test
1943 parent: parent
James E. Blair2f589fe2017-10-26 12:57:41 -07001944 run: playbooks/project-test.yaml
James E. Blair1b27f6a2017-07-14 14:09:07 -07001945 roles:
1946 - zuul: org/project
1947
1948 - project:
1949 name: org/project
1950 check:
1951 jobs:
1952 - project-test
1953 """)
1954
1955 file_dict = {'.zuul.yaml': conf}
1956 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
1957 files=file_dict)
1958 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
1959 self.waitUntilSettled()
1960
1961 self.assertEqual(len(self.builds), 1)
1962 build = self.getBuildByName('project-test')
1963 self._assertRolePath(build, 'pre_playbook_0', 'role_0')
1964 self._assertRolePath(build, 'playbook_0', 'role_0')
1965 self._assertRolePath(build, 'playbook_0', 'role_1')
1966 self._assertRolePath(build, 'post_playbook_0', 'role_0')
1967
1968 self.executor_server.hold_jobs_in_build = False
1969 self.executor_server.release()
1970 self.waitUntilSettled()
1971
1972 self.assertHistory([
1973 dict(name='project-test', result='SUCCESS', changes='1,1'),
1974 ])
1975
James E. Blair6f699732017-07-18 14:19:11 -07001976 def test_role_error(self):
1977 conf = textwrap.dedent(
1978 """
1979 - job:
1980 name: project-test
James E. Blair2f589fe2017-10-26 12:57:41 -07001981 run: playbooks/project-test.yaml
James E. Blair6f699732017-07-18 14:19:11 -07001982 roles:
1983 - zuul: common-config
1984
1985 - project:
1986 name: org/project
1987 check:
1988 jobs:
1989 - project-test
1990 """)
1991
1992 file_dict = {'.zuul.yaml': conf}
1993 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
1994 files=file_dict)
1995 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
1996 self.waitUntilSettled()
1997 self.assertIn(
1998 '- project-test project-test : ERROR Unable to find role',
1999 A.messages[-1])
2000
James E. Blair6459db12017-06-29 14:57:20 -07002001
James E. Blairbb94dfa2017-07-11 07:45:19 -07002002class TestImplicitRoles(RoleTestCase):
2003 tenant_config_file = 'config/implicit-roles/main.yaml'
2004
2005 def test_missing_roles(self):
2006 # Test implicit and explicit roles for a project which does
2007 # not have roles. The implicit role should be silently
2008 # ignored since the project doesn't supply roles, but if a
2009 # user declares an explicit role, it should error.
2010 self.executor_server.hold_jobs_in_build = True
2011 A = self.fake_gerrit.addFakeChange('org/norole-project', 'master', 'A')
2012 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2013 self.waitUntilSettled()
2014
2015 self.assertEqual(len(self.builds), 2)
2016 build = self.getBuildByName('implicit-role-fail')
2017 self._assertRolePath(build, 'playbook_0', None)
2018
2019 self.executor_server.hold_jobs_in_build = False
2020 self.executor_server.release()
2021 self.waitUntilSettled()
2022 # The retry_limit doesn't get recorded
2023 self.assertHistory([
2024 dict(name='implicit-role-fail', result='SUCCESS', changes='1,1'),
2025 ])
2026
2027 def test_roles(self):
2028 # Test implicit and explicit roles for a project which does
2029 # have roles. In both cases, we should end up with the role
2030 # in the path. In the explicit case, ensure we end up with
2031 # the name we specified.
2032 self.executor_server.hold_jobs_in_build = True
2033 A = self.fake_gerrit.addFakeChange('org/role-project', 'master', 'A')
2034 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2035 self.waitUntilSettled()
2036
2037 self.assertEqual(len(self.builds), 2)
2038 build = self.getBuildByName('implicit-role-ok')
2039 self._assertRolePath(build, 'playbook_0', 'role_0')
2040
2041 build = self.getBuildByName('explicit-role-ok')
2042 self._assertRolePath(build, 'playbook_0', 'role_0')
2043
2044 self.executor_server.hold_jobs_in_build = False
2045 self.executor_server.release()
2046 self.waitUntilSettled()
2047 self.assertHistory([
2048 dict(name='implicit-role-ok', result='SUCCESS', changes='1,1'),
2049 dict(name='explicit-role-ok', result='SUCCESS', changes='1,1'),
2050 ], ordered=False)
2051
2052
James E. Blair6459db12017-06-29 14:57:20 -07002053class TestShadow(ZuulTestCase):
2054 tenant_config_file = 'config/shadow/main.yaml'
2055
2056 def test_shadow(self):
2057 # Test that a repo is allowed to shadow another's job definitions.
2058 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2059 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2060 self.waitUntilSettled()
2061 self.assertHistory([
2062 dict(name='test1', result='SUCCESS', changes='1,1'),
2063 dict(name='test2', result='SUCCESS', changes='1,1'),
James E. Blairadafa6c2017-07-12 08:50:56 -07002064 ], ordered=False)
James E. Blair196f61a2017-06-30 15:42:29 -07002065
2066
2067class TestDataReturn(AnsibleZuulTestCase):
2068 tenant_config_file = 'config/data-return/main.yaml'
2069
2070 def test_data_return(self):
James E. Blair196f61a2017-06-30 15:42:29 -07002071 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2072 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2073 self.waitUntilSettled()
2074 self.assertHistory([
2075 dict(name='data-return', result='SUCCESS', changes='1,1'),
James E. Blair88e79c02017-07-07 13:36:54 -07002076 dict(name='data-return-relative', result='SUCCESS', changes='1,1'),
James E. Blair698703c2017-09-15 20:58:30 -06002077 dict(name='child', result='SUCCESS', changes='1,1'),
James E. Blair88e79c02017-07-07 13:36:54 -07002078 ], ordered=False)
2079 self.assertIn('- data-return http://example.com/test/log/url/',
2080 A.messages[-1])
2081 self.assertIn('- data-return-relative '
2082 'http://example.com/test/log/url/docs/index.html',
James E. Blair196f61a2017-06-30 15:42:29 -07002083 A.messages[-1])
Clint Byrumdc8a0902017-07-20 16:36:27 -07002084
2085
2086class TestDiskAccounting(AnsibleZuulTestCase):
2087 config_file = 'zuul-disk-accounting.conf'
2088 tenant_config_file = 'config/disk-accountant/main.yaml'
2089
2090 def test_disk_accountant_kills_job(self):
2091 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2092 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2093 self.waitUntilSettled()
2094 self.assertHistory([
2095 dict(name='dd-big-empty-file', result='ABORTED', changes='1,1')])
Tristan Cacqueray82f864b2017-08-01 05:54:42 +00002096
2097
2098class TestMaxNodesPerJob(AnsibleZuulTestCase):
2099 tenant_config_file = 'config/multi-tenant/main.yaml'
2100
Tristan Cacquerayc98bff72017-09-10 15:25:26 +00002101 def test_max_timeout_exceeded(self):
Tristan Cacqueray82f864b2017-08-01 05:54:42 +00002102 in_repo_conf = textwrap.dedent(
2103 """
2104 - job:
2105 name: test-job
James E. Blair7e3e6882017-09-20 15:47:13 -07002106 nodeset:
2107 nodes:
2108 - name: node01
2109 label: fake
2110 - name: node02
2111 label: fake
2112 - name: node03
2113 label: fake
2114 - name: node04
2115 label: fake
2116 - name: node05
2117 label: fake
2118 - name: node06
2119 label: fake
Tristan Cacqueray82f864b2017-08-01 05:54:42 +00002120 """)
2121 file_dict = {'.zuul.yaml': in_repo_conf}
2122 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A',
2123 files=file_dict)
2124 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2125 self.waitUntilSettled()
2126 self.assertIn('The job "test-job" exceeds tenant max-nodes-per-job 5.',
2127 A.messages[0], "A should fail because of nodes limit")
2128
2129 B = self.fake_gerrit.addFakeChange('org/project2', 'master', 'A',
2130 files=file_dict)
2131 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
2132 self.waitUntilSettled()
2133 self.assertNotIn("exceeds tenant max-nodes", B.messages[0],
2134 "B should not fail because of nodes limit")
James E. Blair2bab6e72017-08-07 09:52:45 -07002135
2136
Tristan Cacquerayc98bff72017-09-10 15:25:26 +00002137class TestMaxTimeout(AnsibleZuulTestCase):
2138 tenant_config_file = 'config/multi-tenant/main.yaml'
2139
2140 def test_max_nodes_reached(self):
2141 in_repo_conf = textwrap.dedent(
2142 """
2143 - job:
2144 name: test-job
2145 timeout: 3600
2146 """)
2147 file_dict = {'.zuul.yaml': in_repo_conf}
2148 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A',
2149 files=file_dict)
2150 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2151 self.waitUntilSettled()
2152 self.assertIn('The job "test-job" exceeds tenant max-job-timeout',
2153 A.messages[0], "A should fail because of timeout limit")
2154
2155 B = self.fake_gerrit.addFakeChange('org/project2', 'master', 'A',
2156 files=file_dict)
2157 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
2158 self.waitUntilSettled()
2159 self.assertNotIn("exceeds tenant max-job-timeout", B.messages[0],
2160 "B should not fail because of timeout limit")
2161
2162
James E. Blair7edc25f2017-10-26 10:47:14 -07002163class TestPragma(ZuulTestCase):
2164 tenant_config_file = 'config/pragma/main.yaml'
2165
2166 def test_no_pragma(self):
2167 self.create_branch('org/project', 'stable')
2168 with open(os.path.join(FIXTURE_DIR,
2169 'config/pragma/git/',
2170 'org_project/nopragma.yaml')) as f:
2171 config = f.read()
2172 file_dict = {'.zuul.yaml': config}
2173 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
2174 files=file_dict)
2175 A.addApproval('Code-Review', 2)
2176 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
2177 self.waitUntilSettled()
2178 self.fake_gerrit.addEvent(A.getChangeMergedEvent())
2179 self.waitUntilSettled()
2180
2181 # This is an untrusted repo with 2 branches, so it should have
2182 # an implied branch matcher for the job.
2183 tenant = self.sched.abide.tenants.get('tenant-one')
2184 jobs = tenant.layout.getJobs('test-job')
2185 self.assertEqual(len(jobs), 1)
2186 for job in tenant.layout.getJobs('test-job'):
2187 self.assertIsNotNone(job.branch_matcher)
2188
2189 def test_pragma(self):
2190 self.create_branch('org/project', 'stable')
2191 with open(os.path.join(FIXTURE_DIR,
2192 'config/pragma/git/',
2193 'org_project/pragma.yaml')) as f:
2194 config = f.read()
2195 file_dict = {'.zuul.yaml': config}
2196 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
2197 files=file_dict)
2198 A.addApproval('Code-Review', 2)
2199 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
2200 self.waitUntilSettled()
2201 self.fake_gerrit.addEvent(A.getChangeMergedEvent())
2202 self.waitUntilSettled()
2203
2204 # This is an untrusted repo with 2 branches, so it would
2205 # normally have an implied branch matcher, but our pragma
2206 # overrides it.
2207 tenant = self.sched.abide.tenants.get('tenant-one')
2208 jobs = tenant.layout.getJobs('test-job')
2209 self.assertEqual(len(jobs), 1)
2210 for job in tenant.layout.getJobs('test-job'):
2211 self.assertIsNone(job.branch_matcher)
2212
2213
James E. Blair2bab6e72017-08-07 09:52:45 -07002214class TestBaseJobs(ZuulTestCase):
2215 tenant_config_file = 'config/base-jobs/main.yaml'
2216
2217 def test_multiple_base_jobs(self):
2218 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2219 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2220 self.waitUntilSettled()
2221 self.assertHistory([
2222 dict(name='my-job', result='SUCCESS', changes='1,1'),
2223 dict(name='other-job', result='SUCCESS', changes='1,1'),
2224 ], ordered=False)
2225 self.assertEqual(self.getJobFromHistory('my-job').
2226 parameters['zuul']['jobtags'],
2227 ['mybase'])
2228 self.assertEqual(self.getJobFromHistory('other-job').
2229 parameters['zuul']['jobtags'],
2230 ['otherbase'])
2231
2232 def test_untrusted_base_job(self):
2233 """Test that a base job may not be defined in an untrusted repo"""
2234 in_repo_conf = textwrap.dedent(
2235 """
2236 - job:
2237 name: fail-base
2238 parent: null
2239 """)
2240
2241 file_dict = {'.zuul.yaml': in_repo_conf}
2242 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
2243 files=file_dict)
2244 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2245 self.waitUntilSettled()
2246 self.assertEqual(A.reported, 1,
2247 "A should report failure")
2248 self.assertEqual(A.patchsets[0]['approvals'][0]['value'], "-1")
2249 self.assertIn('Base jobs must be defined in config projects',
2250 A.messages[0])
2251 self.assertHistory([])
James E. Blairdb089032017-08-15 13:42:12 -07002252
2253
James E. Blairdf91ab32017-10-25 17:57:13 -07002254class TestSecretInheritance(ZuulTestCase):
2255 tenant_config_file = 'config/secret-inheritance/main.yaml'
2256
2257 def _getSecrets(self, job, pbtype):
2258 secrets = []
2259 build = self.getJobFromHistory(job)
2260 for pb in build.parameters[pbtype]:
2261 secrets.append(pb['secrets'])
2262 return secrets
2263
2264 def _checkTrustedSecrets(self):
2265 secret = {'longpassword': 'test-passwordtest-password',
2266 'password': 'test-password',
2267 'username': 'test-username'}
2268 self.assertEqual(
2269 self._getSecrets('trusted-secrets', 'playbooks'),
James E. Blair2f589fe2017-10-26 12:57:41 -07002270 [{'trusted-secret': secret}])
James E. Blairdf91ab32017-10-25 17:57:13 -07002271 self.assertEqual(
2272 self._getSecrets('trusted-secrets', 'pre_playbooks'), [])
2273 self.assertEqual(
2274 self._getSecrets('trusted-secrets', 'post_playbooks'), [])
2275
2276 self.assertEqual(
2277 self._getSecrets('trusted-secrets-trusted-child',
James E. Blair2f589fe2017-10-26 12:57:41 -07002278 'playbooks'), [{}])
James E. Blairdf91ab32017-10-25 17:57:13 -07002279 self.assertEqual(
2280 self._getSecrets('trusted-secrets-trusted-child',
2281 'pre_playbooks'), [])
2282 self.assertEqual(
2283 self._getSecrets('trusted-secrets-trusted-child',
2284 'post_playbooks'), [])
2285
2286 self.assertEqual(
2287 self._getSecrets('trusted-secrets-untrusted-child',
James E. Blair2f589fe2017-10-26 12:57:41 -07002288 'playbooks'), [{}])
James E. Blairdf91ab32017-10-25 17:57:13 -07002289 self.assertEqual(
2290 self._getSecrets('trusted-secrets-untrusted-child',
2291 'pre_playbooks'), [])
2292 self.assertEqual(
2293 self._getSecrets('trusted-secrets-untrusted-child',
2294 'post_playbooks'), [])
2295
2296 def _checkUntrustedSecrets(self):
2297 secret = {'longpassword': 'test-passwordtest-password',
2298 'password': 'test-password',
2299 'username': 'test-username'}
2300 self.assertEqual(
2301 self._getSecrets('untrusted-secrets', 'playbooks'),
James E. Blair2f589fe2017-10-26 12:57:41 -07002302 [{'untrusted-secret': secret}])
James E. Blairdf91ab32017-10-25 17:57:13 -07002303 self.assertEqual(
2304 self._getSecrets('untrusted-secrets', 'pre_playbooks'), [])
2305 self.assertEqual(
2306 self._getSecrets('untrusted-secrets', 'post_playbooks'), [])
2307
2308 self.assertEqual(
2309 self._getSecrets('untrusted-secrets-trusted-child',
James E. Blair2f589fe2017-10-26 12:57:41 -07002310 'playbooks'), [{}])
James E. Blairdf91ab32017-10-25 17:57:13 -07002311 self.assertEqual(
2312 self._getSecrets('untrusted-secrets-trusted-child',
2313 'pre_playbooks'), [])
2314 self.assertEqual(
2315 self._getSecrets('untrusted-secrets-trusted-child',
2316 'post_playbooks'), [])
2317
2318 self.assertEqual(
2319 self._getSecrets('untrusted-secrets-untrusted-child',
James E. Blair2f589fe2017-10-26 12:57:41 -07002320 'playbooks'), [{}])
James E. Blairdf91ab32017-10-25 17:57:13 -07002321 self.assertEqual(
2322 self._getSecrets('untrusted-secrets-untrusted-child',
2323 'pre_playbooks'), [])
2324 self.assertEqual(
2325 self._getSecrets('untrusted-secrets-untrusted-child',
2326 'post_playbooks'), [])
2327
2328 def test_trusted_secret_inheritance_check(self):
2329 A = self.fake_gerrit.addFakeChange('common-config', 'master', 'A')
2330 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2331 self.waitUntilSettled()
2332 self.assertHistory([
2333 dict(name='trusted-secrets', result='SUCCESS', changes='1,1'),
2334 dict(name='trusted-secrets-trusted-child',
2335 result='SUCCESS', changes='1,1'),
2336 dict(name='trusted-secrets-untrusted-child',
2337 result='SUCCESS', changes='1,1'),
2338 ], ordered=False)
2339
2340 self._checkTrustedSecrets()
2341
2342 def test_untrusted_secret_inheritance_gate(self):
2343 A = self.fake_gerrit.addFakeChange('common-config', 'master', 'A')
2344 A.addApproval('Code-Review', 2)
2345 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
2346 self.waitUntilSettled()
2347 self.assertHistory([
2348 dict(name='untrusted-secrets', result='SUCCESS', changes='1,1'),
2349 dict(name='untrusted-secrets-trusted-child',
2350 result='SUCCESS', changes='1,1'),
2351 dict(name='untrusted-secrets-untrusted-child',
2352 result='SUCCESS', changes='1,1'),
2353 ], ordered=False)
2354
2355 self._checkUntrustedSecrets()
2356
2357 def test_untrusted_secret_inheritance_check(self):
2358 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2359 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2360 self.waitUntilSettled()
2361 # This configuration tries to run untrusted secrets in an
2362 # non-post-review pipeline and should therefore run no jobs.
2363 self.assertHistory([])
2364
2365
James E. Blairdb089032017-08-15 13:42:12 -07002366class TestSecretLeaks(AnsibleZuulTestCase):
2367 tenant_config_file = 'config/secret-leaks/main.yaml'
2368
2369 def searchForContent(self, path, content):
2370 matches = []
2371 for (dirpath, dirnames, filenames) in os.walk(path):
2372 for filename in filenames:
2373 filepath = os.path.join(dirpath, filename)
2374 with open(filepath, 'rb') as f:
2375 if content in f.read():
2376 matches.append(filepath[len(path):])
2377 return matches
2378
2379 def _test_secret_file(self):
2380 # Or rather -- test that they *don't* leak.
2381 # Keep the jobdir around so we can inspect contents.
2382 self.executor_server.keep_jobdir = True
2383 conf = textwrap.dedent(
2384 """
2385 - project:
2386 name: org/project
2387 check:
2388 jobs:
2389 - secret-file
2390 """)
2391
2392 file_dict = {'.zuul.yaml': conf}
2393 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
2394 files=file_dict)
2395 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2396 self.waitUntilSettled()
2397 self.assertHistory([
2398 dict(name='secret-file', result='SUCCESS', changes='1,1'),
2399 ], ordered=False)
2400 matches = self.searchForContent(self.history[0].jobdir.root,
2401 b'test-password')
James E. Blaird6a71ca2017-08-18 14:15:05 -07002402 self.assertEqual(set(['/work/secret-file.txt']),
James E. Blairdb089032017-08-15 13:42:12 -07002403 set(matches))
2404
2405 def test_secret_file(self):
2406 self._test_secret_file()
2407
2408 def test_secret_file_verbose(self):
2409 # Output extra ansible info to exercise alternate logging code
2410 # paths.
2411 self.executor_server.verbose = True
2412 self._test_secret_file()
2413
2414 def _test_secret_file_fail(self):
2415 # Or rather -- test that they *don't* leak.
2416 # Keep the jobdir around so we can inspect contents.
2417 self.executor_server.keep_jobdir = True
2418 conf = textwrap.dedent(
2419 """
2420 - project:
2421 name: org/project
2422 check:
2423 jobs:
2424 - secret-file-fail
2425 """)
2426
2427 file_dict = {'.zuul.yaml': conf}
2428 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
2429 files=file_dict)
2430 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2431 self.waitUntilSettled()
2432 self.assertHistory([
2433 dict(name='secret-file-fail', result='FAILURE', changes='1,1'),
2434 ], ordered=False)
2435 matches = self.searchForContent(self.history[0].jobdir.root,
2436 b'test-password')
James E. Blaird6a71ca2017-08-18 14:15:05 -07002437 self.assertEqual(set(['/work/failure-file.txt']),
James E. Blairdb089032017-08-15 13:42:12 -07002438 set(matches))
2439
2440 def test_secret_file_fail(self):
2441 self._test_secret_file_fail()
2442
2443 def test_secret_file_fail_verbose(self):
2444 # Output extra ansible info to exercise alternate logging code
2445 # paths.
2446 self.executor_server.verbose = True
2447 self._test_secret_file_fail()
James E. Blaira00910c2017-08-23 09:15:04 -07002448
2449
2450class TestJobOutput(AnsibleZuulTestCase):
2451 tenant_config_file = 'config/job-output/main.yaml'
2452
2453 def _get_file(self, build, path):
2454 p = os.path.join(build.jobdir.root, path)
2455 with open(p) as f:
2456 return f.read()
2457
2458 def test_job_output(self):
Monty Taylor0e2489a2017-10-10 11:57:29 -05002459 # Verify that command standard output appears in the job output,
2460 # and that failures in the final playbook get logged.
James E. Blaira00910c2017-08-23 09:15:04 -07002461
2462 # This currently only verifies we receive output from
2463 # localhost. Notably, it does not verify we receive output
2464 # via zuul_console streaming.
2465 self.executor_server.keep_jobdir = True
2466 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2467 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2468 self.waitUntilSettled()
2469 self.assertHistory([
2470 dict(name='job-output', result='SUCCESS', changes='1,1'),
2471 ], ordered=False)
2472
2473 token = 'Standard output test %s' % (self.history[0].jobdir.src_root)
2474 j = json.loads(self._get_file(self.history[0],
2475 'work/logs/job-output.json'))
2476 self.assertEqual(token,
2477 j[0]['plays'][0]['tasks'][0]
2478 ['hosts']['localhost']['stdout'])
2479
2480 print(self._get_file(self.history[0],
2481 'work/logs/job-output.txt'))
2482 self.assertIn(token,
2483 self._get_file(self.history[0],
2484 'work/logs/job-output.txt'))
Monty Taylor0e2489a2017-10-10 11:57:29 -05002485
2486 def test_job_output_failure_log(self):
2487 logger = logging.getLogger('zuul.AnsibleJob')
2488 output = io.StringIO()
2489 logger.addHandler(logging.StreamHandler(output))
2490
2491 # Verify that a failure in the last post playbook emits the contents
2492 # of the json output to the log
2493 self.executor_server.keep_jobdir = True
2494 A = self.fake_gerrit.addFakeChange('org/project2', 'master', 'A')
2495 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2496 self.waitUntilSettled()
2497 self.assertHistory([
2498 dict(name='job-output-failure',
2499 result='POST_FAILURE', changes='1,1'),
2500 ], ordered=False)
2501
2502 token = 'Standard output test %s' % (self.history[0].jobdir.src_root)
2503 j = json.loads(self._get_file(self.history[0],
2504 'work/logs/job-output.json'))
2505 self.assertEqual(token,
2506 j[0]['plays'][0]['tasks'][0]
2507 ['hosts']['localhost']['stdout'])
2508
2509 print(self._get_file(self.history[0],
2510 'work/logs/job-output.json'))
2511 self.assertIn(token,
2512 self._get_file(self.history[0],
2513 'work/logs/job-output.txt'))
2514
2515 log_output = output.getvalue()
2516 self.assertIn('Final playbook failed', log_output)
2517 self.assertIn('Failure test', log_output)