blob: 0d081d5c6010bd7953edd8b7999ee36a4d36e6b6 [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
23from unittest import skip
James E. Blair59fdbac2015-12-07 17:08:06 -080024
James E. Blairb9c0d772017-03-03 14:34:49 -080025import testtools
26
27import zuul.configloader
James E. Blairbf1a4f22017-03-17 10:59:37 -070028from zuul.lib import encryption
Ricardo Carrillo Cruz22994f92016-12-02 11:41:58 +000029from tests.base import AnsibleZuulTestCase, ZuulTestCase, FIXTURE_DIR
James E. Blair59fdbac2015-12-07 17:08:06 -080030
James E. Blair59fdbac2015-12-07 17:08:06 -080031
James E. Blair3f876d52016-07-22 13:07:14 -070032class TestMultipleTenants(AnsibleZuulTestCase):
James E. Blair59fdbac2015-12-07 17:08:06 -080033 # A temporary class to hold new tests while others are disabled
34
James E. Blair2a629ec2015-12-22 15:32:02 -080035 tenant_config_file = 'config/multi-tenant/main.yaml'
James E. Blair59fdbac2015-12-07 17:08:06 -080036
James E. Blair83005782015-12-11 14:46:03 -080037 def test_multiple_tenants(self):
James E. Blair96f26942015-12-09 10:15:59 -080038 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A')
Tobias Henkelbf24fd12017-07-27 06:13:07 +020039 A.addApproval('Code-Review', 2)
40 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
James E. Blair59fdbac2015-12-07 17:08:06 -080041 self.waitUntilSettled()
James E. Blair96f26942015-12-09 10:15:59 -080042 self.assertEqual(self.getJobFromHistory('project1-test1').result,
James E. Blair59fdbac2015-12-07 17:08:06 -080043 'SUCCESS')
James E. Blair96c6bf82016-01-15 16:20:40 -080044 self.assertEqual(self.getJobFromHistory('python27').result,
45 'SUCCESS')
James E. Blair59fdbac2015-12-07 17:08:06 -080046 self.assertEqual(A.data['status'], 'MERGED')
James E. Blair96f26942015-12-09 10:15:59 -080047 self.assertEqual(A.reported, 2,
48 "A should report start and success")
49 self.assertIn('tenant-one-gate', A.messages[1],
50 "A should transit tenant-one gate")
51 self.assertNotIn('tenant-two-gate', A.messages[1],
52 "A should *not* transit tenant-two gate")
James E. Blair59fdbac2015-12-07 17:08:06 -080053
James E. Blair96f26942015-12-09 10:15:59 -080054 B = self.fake_gerrit.addFakeChange('org/project2', 'master', 'B')
Tobias Henkelbf24fd12017-07-27 06:13:07 +020055 B.addApproval('Code-Review', 2)
56 self.fake_gerrit.addEvent(B.addApproval('Approved', 1))
James E. Blair96f26942015-12-09 10:15:59 -080057 self.waitUntilSettled()
James E. Blair96c6bf82016-01-15 16:20:40 -080058 self.assertEqual(self.getJobFromHistory('python27',
59 'org/project2').result,
60 'SUCCESS')
James E. Blair96f26942015-12-09 10:15:59 -080061 self.assertEqual(self.getJobFromHistory('project2-test1').result,
62 'SUCCESS')
63 self.assertEqual(B.data['status'], 'MERGED')
64 self.assertEqual(B.reported, 2,
65 "B should report start and success")
66 self.assertIn('tenant-two-gate', B.messages[1],
67 "B should transit tenant-two gate")
68 self.assertNotIn('tenant-one-gate', B.messages[1],
69 "B should *not* transit tenant-one gate")
James E. Blair59fdbac2015-12-07 17:08:06 -080070
James E. Blair96f26942015-12-09 10:15:59 -080071 self.assertEqual(A.reported, 2, "Activity in tenant two should"
72 "not affect tenant one")
James E. Blair14abdf42015-12-09 16:11:53 -080073
James E. Blair83005782015-12-11 14:46:03 -080074
Tobias Henkel83167622017-06-30 19:45:03 +020075class TestFinal(ZuulTestCase):
76
77 tenant_config_file = 'config/final/main.yaml'
78
79 def test_final_variant_ok(self):
80 # test clean usage of final parent job
81 in_repo_conf = textwrap.dedent(
82 """
83 - project:
84 name: org/project
85 check:
86 jobs:
87 - job-final
88 """)
89
90 file_dict = {'.zuul.yaml': in_repo_conf}
91 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
92 files=file_dict)
93 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
94 self.waitUntilSettled()
95
96 self.assertEqual(A.reported, 1)
97 self.assertEqual(A.patchsets[-1]['approvals'][0]['value'], '1')
98
99 def test_final_variant_error(self):
100 # test misuse of final parent job
101 in_repo_conf = textwrap.dedent(
102 """
103 - project:
104 name: org/project
105 check:
106 jobs:
107 - job-final:
108 vars:
109 dont_override_this: bar
110 """)
111 file_dict = {'.zuul.yaml': in_repo_conf}
112 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
113 files=file_dict)
114 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
115 self.waitUntilSettled()
116
117 # The second patch tried to override some variables.
118 # Thus it should fail.
119 self.assertEqual(A.reported, 1)
120 self.assertEqual(A.patchsets[-1]['approvals'][0]['value'], '-1')
121 self.assertIn('Unable to modify final job', A.messages[0])
122
123 def test_final_inheritance(self):
124 # test misuse of final parent job
125 in_repo_conf = textwrap.dedent(
126 """
127 - job:
128 name: project-test
129 parent: job-final
130
131 - project:
132 name: org/project
133 check:
134 jobs:
135 - project-test
136 """)
137
138 in_repo_playbook = textwrap.dedent(
139 """
140 - hosts: all
141 tasks: []
142 """)
143
144 file_dict = {'.zuul.yaml': in_repo_conf,
145 'playbooks/project-test.yaml': in_repo_playbook}
146 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
147 files=file_dict)
148 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
149 self.waitUntilSettled()
150
151 # The second patch tried to override some variables.
152 # Thus it should fail.
153 self.assertEqual(A.reported, 1)
154 self.assertEqual(A.patchsets[-1]['approvals'][0]['value'], '-1')
155 self.assertIn('Unable to inherit from final job', A.messages[0])
156
157
James E. Blairff555742017-02-19 11:34:27 -0800158class TestInRepoConfig(ZuulTestCase):
James E. Blair83005782015-12-11 14:46:03 -0800159 # A temporary class to hold new tests while others are disabled
160
Tobias Henkelabf973e2017-07-28 10:07:34 +0200161 config_file = 'zuul-connections-gerrit-and-github.conf'
James E. Blair2a629ec2015-12-22 15:32:02 -0800162 tenant_config_file = 'config/in-repo/main.yaml'
James E. Blair83005782015-12-11 14:46:03 -0800163
James E. Blair83005782015-12-11 14:46:03 -0800164 def test_in_repo_config(self):
James E. Blair14abdf42015-12-09 16:11:53 -0800165 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
Tobias Henkelbf24fd12017-07-27 06:13:07 +0200166 A.addApproval('Code-Review', 2)
167 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
James E. Blair14abdf42015-12-09 16:11:53 -0800168 self.waitUntilSettled()
169 self.assertEqual(self.getJobFromHistory('project-test1').result,
170 'SUCCESS')
171 self.assertEqual(A.data['status'], 'MERGED')
172 self.assertEqual(A.reported, 2,
173 "A should report start and success")
174 self.assertIn('tenant-one-gate', A.messages[1],
175 "A should transit tenant-one gate")
James E. Blairb97ed802015-12-21 15:55:35 -0800176
James E. Blair3a098dd2017-10-04 14:37:29 -0700177 @skip("This test is useful, but not reliable")
178 def test_full_and_dynamic_reconfig(self):
179 self.executor_server.hold_jobs_in_build = True
180 in_repo_conf = textwrap.dedent(
181 """
182 - job:
183 name: project-test1
184
185 - project:
186 name: org/project
187 tenant-one-gate:
188 jobs:
189 - project-test1
190 """)
191
192 file_dict = {'.zuul.yaml': in_repo_conf}
193 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
194 files=file_dict)
195 A.addApproval('Code-Review', 2)
196 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
197 self.waitUntilSettled()
198 self.sched.reconfigure(self.config)
199 self.waitUntilSettled()
200
201 gc.collect()
202 pipelines = [obj for obj in gc.get_objects()
203 if isinstance(obj, zuul.model.Pipeline)]
204 self.assertEqual(len(pipelines), 4)
205
206 self.executor_server.hold_jobs_in_build = False
207 self.executor_server.release()
208 self.waitUntilSettled()
209
James E. Blair8b1dc3f2016-07-05 16:49:00 -0700210 def test_dynamic_config(self):
211 in_repo_conf = textwrap.dedent(
212 """
213 - job:
Tobias Henkelf02cf512017-07-21 22:55:34 +0200214 name: project-test1
215
216 - job:
James E. Blair8b1dc3f2016-07-05 16:49:00 -0700217 name: project-test2
218
219 - project:
220 name: org/project
221 tenant-one-gate:
222 jobs:
223 - project-test2
224 """)
225
James E. Blairc73c73a2017-01-20 15:15:15 -0800226 in_repo_playbook = textwrap.dedent(
227 """
228 - hosts: all
229 tasks: []
230 """)
231
232 file_dict = {'.zuul.yaml': in_repo_conf,
233 'playbooks/project-test2.yaml': in_repo_playbook}
James E. Blair8b1dc3f2016-07-05 16:49:00 -0700234 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
James E. Blairc73c73a2017-01-20 15:15:15 -0800235 files=file_dict)
Tobias Henkelbf24fd12017-07-27 06:13:07 +0200236 A.addApproval('Code-Review', 2)
237 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
James E. Blair8b1dc3f2016-07-05 16:49:00 -0700238 self.waitUntilSettled()
James E. Blair8b1dc3f2016-07-05 16:49:00 -0700239 self.assertEqual(A.data['status'], 'MERGED')
240 self.assertEqual(A.reported, 2,
241 "A should report start and success")
242 self.assertIn('tenant-one-gate', A.messages[1],
243 "A should transit tenant-one gate")
James E. Blair646322f2017-01-27 15:50:34 -0800244 self.assertHistory([
245 dict(name='project-test2', result='SUCCESS', changes='1,1')])
246
James E. Blairc2a5ed72017-02-20 14:12:01 -0500247 self.fake_gerrit.addEvent(A.getChangeMergedEvent())
James E. Blair7bbd7a32017-03-06 11:36:13 -0800248 self.waitUntilSettled()
James E. Blairc2a5ed72017-02-20 14:12:01 -0500249
James E. Blair646322f2017-01-27 15:50:34 -0800250 # Now that the config change is landed, it should be live for
251 # subsequent changes.
252 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
Tobias Henkelbf24fd12017-07-27 06:13:07 +0200253 B.addApproval('Code-Review', 2)
254 self.fake_gerrit.addEvent(B.addApproval('Approved', 1))
James E. Blair646322f2017-01-27 15:50:34 -0800255 self.waitUntilSettled()
256 self.assertEqual(self.getJobFromHistory('project-test2').result,
257 'SUCCESS')
258 self.assertHistory([
259 dict(name='project-test2', result='SUCCESS', changes='1,1'),
260 dict(name='project-test2', result='SUCCESS', changes='2,1')])
James E. Blairc73c73a2017-01-20 15:15:15 -0800261
Tobias Henkelf02cf512017-07-21 22:55:34 +0200262 def test_dynamic_config_non_existing_job(self):
263 """Test that requesting a non existent job fails"""
264 in_repo_conf = textwrap.dedent(
265 """
266 - job:
267 name: project-test1
268
269 - project:
270 name: org/project
271 check:
272 jobs:
273 - non-existent-job
274 """)
275
276 in_repo_playbook = textwrap.dedent(
277 """
278 - hosts: all
279 tasks: []
280 """)
281
282 file_dict = {'.zuul.yaml': in_repo_conf,
283 'playbooks/project-test2.yaml': in_repo_playbook}
284 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
285 files=file_dict)
286 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
287 self.waitUntilSettled()
288 self.assertEqual(A.reported, 1,
289 "A should report failure")
290 self.assertEqual(A.patchsets[0]['approvals'][0]['value'], "-1")
291 self.assertIn('Job non-existent-job not defined', A.messages[0],
292 "A should have failed the check pipeline")
293 self.assertHistory([])
294
295 def test_dynamic_config_non_existing_job_in_template(self):
296 """Test that requesting a non existent job fails"""
297 in_repo_conf = textwrap.dedent(
298 """
299 - job:
300 name: project-test1
301
302 - project-template:
303 name: test-template
304 check:
305 jobs:
306 - non-existent-job
307
308 - project:
309 name: org/project
310 templates:
311 - test-template
312 """)
313
314 in_repo_playbook = textwrap.dedent(
315 """
316 - hosts: all
317 tasks: []
318 """)
319
320 file_dict = {'.zuul.yaml': in_repo_conf,
321 'playbooks/project-test2.yaml': in_repo_playbook}
322 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
323 files=file_dict)
324 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
325 self.waitUntilSettled()
326 self.assertEqual(A.reported, 1,
327 "A should report failure")
328 self.assertEqual(A.patchsets[0]['approvals'][0]['value'], "-1")
329 self.assertIn('Job non-existent-job not defined', A.messages[0],
330 "A should have failed the check pipeline")
331 self.assertHistory([])
332
Tobias Henkel0f714002017-06-30 23:30:52 +0200333 def test_dynamic_config_new_patchset(self):
334 self.executor_server.hold_jobs_in_build = True
335
336 tenant = self.sched.abide.tenants.get('tenant-one')
337 check_pipeline = tenant.layout.pipelines['check']
338
339 in_repo_conf = textwrap.dedent(
340 """
341 - job:
Tobias Henkelf02cf512017-07-21 22:55:34 +0200342 name: project-test1
343
344 - job:
Tobias Henkel0f714002017-06-30 23:30:52 +0200345 name: project-test2
346
347 - project:
348 name: org/project
349 check:
350 jobs:
351 - project-test2
352 """)
353
354 in_repo_playbook = textwrap.dedent(
355 """
356 - hosts: all
357 tasks: []
358 """)
359
360 file_dict = {'.zuul.yaml': in_repo_conf,
361 'playbooks/project-test2.yaml': in_repo_playbook}
362 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
363 files=file_dict)
364 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
365 self.waitUntilSettled()
366
367 items = check_pipeline.getAllItems()
368 self.assertEqual(items[0].change.number, '1')
369 self.assertEqual(items[0].change.patchset, '1')
370 self.assertTrue(items[0].live)
371
372 in_repo_conf = textwrap.dedent(
373 """
374 - job:
Tobias Henkel0ce7ec62017-07-21 22:50:17 +0200375 name: project-test1
376
377 - job:
Tobias Henkel0f714002017-06-30 23:30:52 +0200378 name: project-test2
379
380 - project:
381 name: org/project
382 check:
383 jobs:
384 - project-test1
385 - project-test2
386 """)
387 file_dict = {'.zuul.yaml': in_repo_conf,
388 'playbooks/project-test2.yaml': in_repo_playbook}
389
390 A.addPatchset(files=file_dict)
391 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(2))
392
393 self.waitUntilSettled()
394
395 items = check_pipeline.getAllItems()
396 self.assertEqual(items[0].change.number, '1')
397 self.assertEqual(items[0].change.patchset, '2')
398 self.assertTrue(items[0].live)
399
400 self.executor_server.hold_jobs_in_build = False
Tobias Henkel0ce7ec62017-07-21 22:50:17 +0200401 self.executor_server.release('project-test1')
402 self.waitUntilSettled()
Tobias Henkel0f714002017-06-30 23:30:52 +0200403 self.executor_server.release()
404 self.waitUntilSettled()
405
Tobias Henkel0ce7ec62017-07-21 22:50:17 +0200406 self.assertHistory([
407 dict(name='project-test2', result='ABORTED', changes='1,1'),
408 dict(name='project-test1', result='SUCCESS', changes='1,2'),
409 dict(name='project-test2', result='SUCCESS', changes='1,2')])
410
James E. Blairff555742017-02-19 11:34:27 -0800411 def test_in_repo_branch(self):
412 in_repo_conf = textwrap.dedent(
413 """
414 - job:
Tobias Henkelf02cf512017-07-21 22:55:34 +0200415 name: project-test1
416
417 - job:
James E. Blairff555742017-02-19 11:34:27 -0800418 name: project-test2
419
420 - project:
421 name: org/project
422 tenant-one-gate:
423 jobs:
424 - project-test2
425 """)
426
427 in_repo_playbook = textwrap.dedent(
428 """
429 - hosts: all
430 tasks: []
431 """)
432
433 file_dict = {'.zuul.yaml': in_repo_conf,
434 'playbooks/project-test2.yaml': in_repo_playbook}
435 self.create_branch('org/project', 'stable')
James E. Blair72facdc2017-08-17 10:29:12 -0700436 self.fake_gerrit.addEvent(
437 self.fake_gerrit.getFakeBranchCreatedEvent(
438 'org/project', 'stable'))
James E. Blair6069f2b2017-09-26 16:34:11 -0700439 self.waitUntilSettled()
James E. Blairff555742017-02-19 11:34:27 -0800440 A = self.fake_gerrit.addFakeChange('org/project', 'stable', 'A',
441 files=file_dict)
Tobias Henkelbf24fd12017-07-27 06:13:07 +0200442 A.addApproval('Code-Review', 2)
443 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
James E. Blairff555742017-02-19 11:34:27 -0800444 self.waitUntilSettled()
445 self.assertEqual(A.data['status'], 'MERGED')
446 self.assertEqual(A.reported, 2,
447 "A should report start and success")
448 self.assertIn('tenant-one-gate', A.messages[1],
449 "A should transit tenant-one gate")
450 self.assertHistory([
451 dict(name='project-test2', result='SUCCESS', changes='1,1')])
452 self.fake_gerrit.addEvent(A.getChangeMergedEvent())
James E. Blair7bbd7a32017-03-06 11:36:13 -0800453 self.waitUntilSettled()
James E. Blairff555742017-02-19 11:34:27 -0800454
455 # The config change should not affect master.
456 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
Tobias Henkelbf24fd12017-07-27 06:13:07 +0200457 B.addApproval('Code-Review', 2)
458 self.fake_gerrit.addEvent(B.addApproval('Approved', 1))
James E. Blairff555742017-02-19 11:34:27 -0800459 self.waitUntilSettled()
460 self.assertHistory([
461 dict(name='project-test2', result='SUCCESS', changes='1,1'),
462 dict(name='project-test1', result='SUCCESS', changes='2,1')])
463
464 # The config change should be live for further changes on
465 # stable.
466 C = self.fake_gerrit.addFakeChange('org/project', 'stable', 'C')
Tobias Henkelbf24fd12017-07-27 06:13:07 +0200467 C.addApproval('Code-Review', 2)
468 self.fake_gerrit.addEvent(C.addApproval('Approved', 1))
James E. Blairff555742017-02-19 11:34:27 -0800469 self.waitUntilSettled()
470 self.assertHistory([
471 dict(name='project-test2', result='SUCCESS', changes='1,1'),
472 dict(name='project-test1', result='SUCCESS', changes='2,1'),
473 dict(name='project-test2', result='SUCCESS', changes='3,1')])
474
James E. Blaira5a12492017-05-03 11:40:48 -0700475 def test_crd_dynamic_config_branch(self):
476 # Test that we can create a job in one repo and be able to use
477 # it from a different branch on a different repo.
478
479 self.create_branch('org/project1', 'stable')
James E. Blair72facdc2017-08-17 10:29:12 -0700480 self.fake_gerrit.addEvent(
481 self.fake_gerrit.getFakeBranchCreatedEvent(
482 'org/project1', 'stable'))
James E. Blaira5a12492017-05-03 11:40:48 -0700483
484 in_repo_conf = textwrap.dedent(
485 """
486 - job:
Tobias Henkelf02cf512017-07-21 22:55:34 +0200487 name: project-test1
488
489 - job:
James E. Blaira5a12492017-05-03 11:40:48 -0700490 name: project-test2
491
492 - project:
493 name: org/project
494 check:
495 jobs:
496 - project-test2
497 """)
498
499 in_repo_playbook = textwrap.dedent(
500 """
501 - hosts: all
502 tasks: []
503 """)
504
505 file_dict = {'.zuul.yaml': in_repo_conf,
506 'playbooks/project-test2.yaml': in_repo_playbook}
507 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
508 files=file_dict)
509
510 second_repo_conf = textwrap.dedent(
511 """
512 - project:
513 name: org/project1
514 check:
515 jobs:
516 - project-test2
517 """)
518
519 second_file_dict = {'.zuul.yaml': second_repo_conf}
520 B = self.fake_gerrit.addFakeChange('org/project1', 'stable', 'B',
521 files=second_file_dict)
522 B.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
523 B.subject, A.data['id'])
524
525 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
526 self.waitUntilSettled()
527 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
528 self.waitUntilSettled()
529
530 self.assertEqual(A.reported, 1, "A should report")
531 self.assertHistory([
532 dict(name='project-test2', result='SUCCESS', changes='1,1'),
533 dict(name='project-test2', result='SUCCESS', changes='1,1 2,1'),
534 ])
535
James E. Blair97043882017-09-06 15:51:17 -0700536 def test_yaml_list_error(self):
537 in_repo_conf = textwrap.dedent(
538 """
539 job: foo
540 """)
541
542 file_dict = {'.zuul.yaml': in_repo_conf}
543 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
544 files=file_dict)
545 A.addApproval('Code-Review', 2)
546 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
547 self.waitUntilSettled()
548
549 self.assertEqual(A.data['status'], 'NEW')
550 self.assertEqual(A.reported, 1,
551 "A should report failure")
552 self.assertIn('not a list', A.messages[0],
553 "A should have a syntax error reported")
554
555 def test_yaml_dict_error(self):
556 in_repo_conf = textwrap.dedent(
557 """
558 - job
559 """)
560
561 file_dict = {'.zuul.yaml': in_repo_conf}
562 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
563 files=file_dict)
564 A.addApproval('Code-Review', 2)
565 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
566 self.waitUntilSettled()
567
568 self.assertEqual(A.data['status'], 'NEW')
569 self.assertEqual(A.reported, 1,
570 "A should report failure")
571 self.assertIn('not a dictionary', A.messages[0],
572 "A should have a syntax error reported")
573
574 def test_yaml_key_error(self):
575 in_repo_conf = textwrap.dedent(
576 """
577 - job:
578 name: project-test2
579 """)
580
581 file_dict = {'.zuul.yaml': in_repo_conf}
582 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
583 files=file_dict)
584 A.addApproval('Code-Review', 2)
585 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
586 self.waitUntilSettled()
587
588 self.assertEqual(A.data['status'], 'NEW')
589 self.assertEqual(A.reported, 1,
590 "A should report failure")
591 self.assertIn('has more than one key', A.messages[0],
592 "A should have a syntax error reported")
593
594 def test_yaml_unknown_error(self):
595 in_repo_conf = textwrap.dedent(
596 """
597 - foobar:
598 foo: bar
599 """)
600
601 file_dict = {'.zuul.yaml': in_repo_conf}
602 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
603 files=file_dict)
604 A.addApproval('Code-Review', 2)
605 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
606 self.waitUntilSettled()
607
608 self.assertEqual(A.data['status'], 'NEW')
609 self.assertEqual(A.reported, 1,
610 "A should report failure")
611 self.assertIn('not recognized', A.messages[0],
612 "A should have a syntax error reported")
613
James E. Blair149b69c2017-03-02 10:48:16 -0800614 def test_untrusted_syntax_error(self):
James E. Blaire53250c2017-03-01 14:34:36 -0800615 in_repo_conf = textwrap.dedent(
616 """
617 - job:
618 name: project-test2
619 foo: error
620 """)
621
622 file_dict = {'.zuul.yaml': in_repo_conf}
623 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
624 files=file_dict)
Tobias Henkelbf24fd12017-07-27 06:13:07 +0200625 A.addApproval('Code-Review', 2)
626 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
James E. Blaire53250c2017-03-01 14:34:36 -0800627 self.waitUntilSettled()
628
629 self.assertEqual(A.data['status'], 'NEW')
Tobias Henkel9842bd72017-05-16 13:40:03 +0200630 self.assertEqual(A.reported, 1,
631 "A should report failure")
632 self.assertIn('syntax error', A.messages[0],
James E. Blaire53250c2017-03-01 14:34:36 -0800633 "A should have a syntax error reported")
634
James E. Blair149b69c2017-03-02 10:48:16 -0800635 def test_trusted_syntax_error(self):
636 in_repo_conf = textwrap.dedent(
637 """
638 - job:
639 name: project-test2
640 foo: error
641 """)
642
643 file_dict = {'zuul.yaml': in_repo_conf}
644 A = self.fake_gerrit.addFakeChange('common-config', 'master', 'A',
645 files=file_dict)
Tobias Henkelbf24fd12017-07-27 06:13:07 +0200646 A.addApproval('Code-Review', 2)
647 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
James E. Blair149b69c2017-03-02 10:48:16 -0800648 self.waitUntilSettled()
649
650 self.assertEqual(A.data['status'], 'NEW')
Tobias Henkel9842bd72017-05-16 13:40:03 +0200651 self.assertEqual(A.reported, 1,
652 "A should report failure")
653 self.assertIn('syntax error', A.messages[0],
James E. Blair149b69c2017-03-02 10:48:16 -0800654 "A should have a syntax error reported")
655
James E. Blair6f140c72017-03-03 10:32:07 -0800656 def test_untrusted_yaml_error(self):
657 in_repo_conf = textwrap.dedent(
658 """
659 - job:
660 foo: error
661 """)
662
663 file_dict = {'.zuul.yaml': in_repo_conf}
664 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
665 files=file_dict)
Tobias Henkelbf24fd12017-07-27 06:13:07 +0200666 A.addApproval('Code-Review', 2)
667 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
James E. Blair6f140c72017-03-03 10:32:07 -0800668 self.waitUntilSettled()
669
670 self.assertEqual(A.data['status'], 'NEW')
Tobias Henkel9842bd72017-05-16 13:40:03 +0200671 self.assertEqual(A.reported, 1,
672 "A should report failure")
673 self.assertIn('syntax error', A.messages[0],
James E. Blair6f140c72017-03-03 10:32:07 -0800674 "A should have a syntax error reported")
675
James E. Blairdb04e6a2017-05-03 14:49:36 -0700676 def test_untrusted_shadow_error(self):
677 in_repo_conf = textwrap.dedent(
678 """
679 - job:
680 name: common-config-test
681 """)
682
683 file_dict = {'.zuul.yaml': in_repo_conf}
684 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
685 files=file_dict)
Tobias Henkelbf24fd12017-07-27 06:13:07 +0200686 A.addApproval('Code-Review', 2)
687 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
James E. Blairdb04e6a2017-05-03 14:49:36 -0700688 self.waitUntilSettled()
689
690 self.assertEqual(A.data['status'], 'NEW')
Tobias Henkel9842bd72017-05-16 13:40:03 +0200691 self.assertEqual(A.reported, 1,
692 "A should report failure")
693 self.assertIn('not permitted to shadow', A.messages[0],
James E. Blairdb04e6a2017-05-03 14:49:36 -0700694 "A should have a syntax error reported")
695
James E. Blaird5656ad2017-06-02 14:29:41 -0700696 def test_untrusted_pipeline_error(self):
697 in_repo_conf = textwrap.dedent(
698 """
699 - pipeline:
700 name: test
701 """)
702
703 file_dict = {'.zuul.yaml': in_repo_conf}
704 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
705 files=file_dict)
Tobias Henkelbf24fd12017-07-27 06:13:07 +0200706 A.addApproval('Code-Review', 2)
707 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
James E. Blaird5656ad2017-06-02 14:29:41 -0700708 self.waitUntilSettled()
709
710 self.assertEqual(A.data['status'], 'NEW')
711 self.assertEqual(A.reported, 1,
712 "A should report failure")
713 self.assertIn('Pipelines may not be defined', A.messages[0],
714 "A should have a syntax error reported")
715
716 def test_untrusted_project_error(self):
717 in_repo_conf = textwrap.dedent(
718 """
719 - project:
720 name: org/project1
721 """)
722
723 file_dict = {'.zuul.yaml': in_repo_conf}
724 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
725 files=file_dict)
Tobias Henkelbf24fd12017-07-27 06:13:07 +0200726 A.addApproval('Code-Review', 2)
727 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
James E. Blaird5656ad2017-06-02 14:29:41 -0700728 self.waitUntilSettled()
729
730 self.assertEqual(A.data['status'], 'NEW')
731 self.assertEqual(A.reported, 1,
732 "A should report failure")
733 self.assertIn('the only project definition permitted', A.messages[0],
734 "A should have a syntax error reported")
735
James E. Blairf03173b2017-10-10 10:46:43 -0700736 def test_untrusted_depends_on_trusted(self):
737 with open(os.path.join(FIXTURE_DIR,
738 'config/in-repo/git/',
739 'common-config/zuul.yaml')) as f:
740 common_config = f.read()
741
742 common_config += textwrap.dedent(
743 """
744 - job:
745 name: project-test9
746 """)
747
748 file_dict = {'zuul.yaml': common_config}
749 A = self.fake_gerrit.addFakeChange('common-config', 'master', 'A',
750 files=file_dict)
751 in_repo_conf = textwrap.dedent(
752 """
753 - job:
754 name: project-test1
755 - project:
756 name: org/project
757 check:
758 jobs:
759 - project-test9
760 """)
761
762 file_dict = {'zuul.yaml': in_repo_conf}
763 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B',
764 files=file_dict)
765 B.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
766 B.subject, A.data['id'])
767 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
768 self.waitUntilSettled()
769
770 self.assertEqual(B.data['status'], 'NEW')
771 self.assertEqual(B.reported, 1,
772 "B should report failure")
773 self.assertIn('depends on a change to a config project',
774 B.messages[0],
775 "A should have a syntax error reported")
776
James E. Blaire64b0e42017-06-08 11:23:34 -0700777 def test_duplicate_node_error(self):
778 in_repo_conf = textwrap.dedent(
779 """
780 - nodeset:
781 name: duplicate
782 nodes:
783 - name: compute
James E. Blair16d96a02017-06-08 11:32:56 -0700784 label: foo
James E. Blaire64b0e42017-06-08 11:23:34 -0700785 - name: compute
James E. Blair16d96a02017-06-08 11:32:56 -0700786 label: foo
James E. Blaire64b0e42017-06-08 11:23:34 -0700787 """)
788
789 file_dict = {'.zuul.yaml': in_repo_conf}
790 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
791 files=file_dict)
Tobias Henkelbf24fd12017-07-27 06:13:07 +0200792 A.addApproval('Code-Review', 2)
793 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
James E. Blaire64b0e42017-06-08 11:23:34 -0700794 self.waitUntilSettled()
795
796 self.assertEqual(A.data['status'], 'NEW')
797 self.assertEqual(A.reported, 1,
798 "A should report failure")
799 self.assertIn('appears multiple times', A.messages[0],
800 "A should have a syntax error reported")
801
802 def test_duplicate_group_error(self):
803 in_repo_conf = textwrap.dedent(
804 """
805 - nodeset:
806 name: duplicate
807 nodes:
808 - name: compute
James E. Blair16d96a02017-06-08 11:32:56 -0700809 label: foo
James E. Blaire64b0e42017-06-08 11:23:34 -0700810 groups:
811 - name: group
812 nodes: compute
813 - name: group
814 nodes: compute
815 """)
816
817 file_dict = {'.zuul.yaml': in_repo_conf}
818 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
819 files=file_dict)
Tobias Henkelbf24fd12017-07-27 06:13:07 +0200820 A.addApproval('Code-Review', 2)
821 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
James E. Blaire64b0e42017-06-08 11:23:34 -0700822 self.waitUntilSettled()
823
824 self.assertEqual(A.data['status'], 'NEW')
825 self.assertEqual(A.reported, 1,
826 "A should report failure")
827 self.assertIn('appears multiple times', A.messages[0],
828 "A should have a syntax error reported")
829
James E. Blair4ae399f2017-09-20 17:15:09 -0700830 def test_secret_not_found_error(self):
831 in_repo_conf = textwrap.dedent(
832 """
833 - job:
834 name: test
835 secrets: does-not-exist
836 """)
837
838 file_dict = {'.zuul.yaml': in_repo_conf}
839 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
840 files=file_dict)
841 A.addApproval('Code-Review', 2)
842 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
843 self.waitUntilSettled()
844
845 self.assertEqual(A.data['status'], 'NEW')
846 self.assertEqual(A.reported, 1,
847 "A should report failure")
848 self.assertIn('secret "does-not-exist" was not found', A.messages[0],
849 "A should have a syntax error reported")
850
851 def test_nodeset_not_found_error(self):
852 in_repo_conf = textwrap.dedent(
853 """
854 - job:
855 name: test
856 nodeset: does-not-exist
857 """)
858
859 file_dict = {'.zuul.yaml': in_repo_conf}
860 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
861 files=file_dict)
862 A.addApproval('Code-Review', 2)
863 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
864 self.waitUntilSettled()
865
866 self.assertEqual(A.data['status'], 'NEW')
867 self.assertEqual(A.reported, 1,
868 "A should report failure")
869 self.assertIn('nodeset "does-not-exist" was not found', A.messages[0],
870 "A should have a syntax error reported")
871
James E. Blair89e25eb2017-09-26 09:11:31 -0700872 def test_template_not_found_error(self):
873 in_repo_conf = textwrap.dedent(
874 """
875 - job:
876 name: project-test1
877 - project:
878 name: org/project
879 templates:
880 - does-not-exist
881 """)
882
883 file_dict = {'.zuul.yaml': in_repo_conf}
884 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
885 files=file_dict)
886 A.addApproval('Code-Review', 2)
887 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
888 self.waitUntilSettled()
889
890 self.assertEqual(A.data['status'], 'NEW')
891 self.assertEqual(A.reported, 1,
892 "A should report failure")
893 self.assertIn('project template "does-not-exist" was not found',
894 A.messages[0],
895 "A should have a syntax error reported")
896
Monty Taylor8be3c0c2017-10-06 10:37:37 -0500897 def test_job_list_in_project_template_not_dict_error(self):
898 in_repo_conf = textwrap.dedent(
899 """
900 - job:
901 name: project-test1
902 - project-template:
903 name: some-jobs
904 check:
905 jobs:
906 - project-test1:
907 - required-projects:
908 org/project2
909 """)
910
911 file_dict = {'.zuul.yaml': in_repo_conf}
912 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
913 files=file_dict)
914 A.addApproval('Code-Review', 2)
915 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
916 self.waitUntilSettled()
917
918 self.assertEqual(A.data['status'], 'NEW')
919 self.assertEqual(A.reported, 1,
920 "A should report failure")
921 self.assertIn('expected str for dictionary value',
922 A.messages[0], "A should have a syntax error reported")
923
924 def test_job_list_in_project_not_dict_error(self):
925 in_repo_conf = textwrap.dedent(
926 """
927 - job:
928 name: project-test1
929 - project:
930 name: org/project1
931 check:
932 jobs:
933 - project-test1:
934 - required-projects:
935 org/project2
936 """)
937
938 file_dict = {'.zuul.yaml': in_repo_conf}
939 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
940 files=file_dict)
941 A.addApproval('Code-Review', 2)
942 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
943 self.waitUntilSettled()
944
945 self.assertEqual(A.data['status'], 'NEW')
946 self.assertEqual(A.reported, 1,
947 "A should report failure")
948 self.assertIn('expected str for dictionary value',
949 A.messages[0], "A should have a syntax error reported")
950
James E. Blair1235f142017-10-07 09:11:43 -0700951 def test_project_template(self):
952 # Tests that a project template is not modified when used, and
953 # can therefore be used in subsequent reconfigurations.
954 in_repo_conf = textwrap.dedent(
955 """
956 - job:
957 name: project-test1
958 - project-template:
959 name: some-jobs
960 tenant-one-gate:
961 jobs:
962 - project-test1:
963 required-projects:
964 - org/project1
965 - project:
966 name: org/project
967 templates:
968 - some-jobs
969 """)
970
971 file_dict = {'.zuul.yaml': in_repo_conf}
972 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
973 files=file_dict)
974 A.addApproval('Code-Review', 2)
975 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
976 self.waitUntilSettled()
977 self.assertEqual(A.data['status'], 'MERGED')
978 self.fake_gerrit.addEvent(A.getChangeMergedEvent())
979 self.waitUntilSettled()
980 in_repo_conf = textwrap.dedent(
981 """
982 - project:
983 name: org/project1
984 templates:
985 - some-jobs
986 """)
987 file_dict = {'.zuul.yaml': in_repo_conf}
988 B = self.fake_gerrit.addFakeChange('org/project1', 'master', 'B',
989 files=file_dict)
990 B.addApproval('Code-Review', 2)
991 self.fake_gerrit.addEvent(B.addApproval('Approved', 1))
992 self.waitUntilSettled()
993 self.assertEqual(B.data['status'], 'MERGED')
994
James E. Blairbccdfcf2017-10-07 13:37:26 -0700995 def test_job_remove_add(self):
996 # Tests that a job can be removed from one repo and added in another.
997 # First, remove the current config for project1 since it
998 # references the job we want to remove.
999 file_dict = {'.zuul.yaml': None}
1000 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A',
1001 files=file_dict)
1002 A.setMerged()
1003 self.fake_gerrit.addEvent(A.getChangeMergedEvent())
1004 self.waitUntilSettled()
1005 # Then propose a change to delete the job from one repo...
1006 file_dict = {'.zuul.yaml': None}
1007 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B',
1008 files=file_dict)
1009 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
1010 self.waitUntilSettled()
1011 # ...and a second that depends on it that adds it to another repo.
1012 in_repo_conf = textwrap.dedent(
1013 """
1014 - job:
1015 name: project-test1
1016
1017 - project:
1018 name: org/project1
1019 check:
1020 jobs:
1021 - project-test1
1022 """)
1023 in_repo_playbook = textwrap.dedent(
1024 """
1025 - hosts: all
1026 tasks: []
1027 """)
1028 file_dict = {'.zuul.yaml': in_repo_conf,
1029 'playbooks/project-test1.yaml': in_repo_playbook}
1030 C = self.fake_gerrit.addFakeChange('org/project1', 'master', 'C',
1031 files=file_dict,
1032 parent='refs/changes/1/1/1')
1033 C.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
1034 C.subject, B.data['id'])
1035 self.fake_gerrit.addEvent(C.getPatchsetCreatedEvent(1))
1036 self.waitUntilSettled()
1037 self.assertHistory([
1038 dict(name='project-test1', result='SUCCESS', changes='2,1 3,1'),
1039 ], ordered=False)
1040
James E. Blair09f9ffe2017-07-11 15:30:25 -07001041 def test_multi_repo(self):
1042 downstream_repo_conf = textwrap.dedent(
1043 """
1044 - project:
1045 name: org/project1
1046 tenant-one-gate:
1047 jobs:
1048 - project-test1
1049
1050 - job:
1051 name: project1-test1
1052 parent: project-test1
1053 """)
1054
1055 file_dict = {'.zuul.yaml': downstream_repo_conf}
1056 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A',
1057 files=file_dict)
Tobias Henkelbf24fd12017-07-27 06:13:07 +02001058 A.addApproval('Code-Review', 2)
1059 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
James E. Blair09f9ffe2017-07-11 15:30:25 -07001060 self.waitUntilSettled()
1061
1062 self.assertEqual(A.data['status'], 'MERGED')
1063 self.fake_gerrit.addEvent(A.getChangeMergedEvent())
1064 self.waitUntilSettled()
1065
1066 upstream_repo_conf = textwrap.dedent(
1067 """
1068 - job:
1069 name: project-test1
1070
1071 - job:
1072 name: project-test2
1073
1074 - project:
1075 name: org/project
1076 tenant-one-gate:
1077 jobs:
1078 - project-test1
1079 """)
1080
1081 file_dict = {'.zuul.yaml': upstream_repo_conf}
1082 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B',
1083 files=file_dict)
Tobias Henkelbf24fd12017-07-27 06:13:07 +02001084 B.addApproval('Code-Review', 2)
1085 self.fake_gerrit.addEvent(B.addApproval('Approved', 1))
James E. Blair09f9ffe2017-07-11 15:30:25 -07001086 self.waitUntilSettled()
1087
1088 self.assertEqual(B.data['status'], 'MERGED')
1089 self.fake_gerrit.addEvent(B.getChangeMergedEvent())
1090 self.waitUntilSettled()
1091
1092 tenant = self.sched.abide.tenants.get('tenant-one')
1093 # Ensure the latest change is reflected in the config; if it
1094 # isn't this will raise an exception.
1095 tenant.layout.getJob('project-test2')
1096
James E. Blair332636e2017-09-05 10:14:35 -07001097 def test_pipeline_error(self):
1098 with open(os.path.join(FIXTURE_DIR,
1099 'config/in-repo/git/',
1100 'common-config/zuul.yaml')) as f:
1101 base_common_config = f.read()
1102
1103 in_repo_conf_A = textwrap.dedent(
1104 """
1105 - pipeline:
1106 name: periodic
1107 foo: error
1108 """)
1109
1110 file_dict = {'zuul.yaml': None,
1111 'zuul.d/main.yaml': base_common_config,
1112 'zuul.d/test1.yaml': in_repo_conf_A}
1113 A = self.fake_gerrit.addFakeChange('common-config', 'master', 'A',
1114 files=file_dict)
1115 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
1116 self.waitUntilSettled()
1117 self.assertEqual(A.reported, 1,
1118 "A should report failure")
1119 self.assertIn('syntax error',
1120 A.messages[0],
1121 "A should have an error reported")
1122
1123 def test_change_series_error(self):
1124 with open(os.path.join(FIXTURE_DIR,
1125 'config/in-repo/git/',
1126 'common-config/zuul.yaml')) as f:
1127 base_common_config = f.read()
1128
1129 in_repo_conf_A = textwrap.dedent(
1130 """
1131 - pipeline:
1132 name: periodic
1133 foo: error
1134 """)
1135
1136 file_dict = {'zuul.yaml': None,
1137 'zuul.d/main.yaml': base_common_config,
1138 'zuul.d/test1.yaml': in_repo_conf_A}
1139 A = self.fake_gerrit.addFakeChange('common-config', 'master', 'A',
1140 files=file_dict)
1141
1142 in_repo_conf_B = textwrap.dedent(
1143 """
1144 - job:
1145 name: project-test2
1146 foo: error
1147 """)
1148
1149 file_dict = {'zuul.yaml': None,
1150 'zuul.d/main.yaml': base_common_config,
1151 'zuul.d/test1.yaml': in_repo_conf_A,
1152 'zuul.d/test2.yaml': in_repo_conf_B}
1153 B = self.fake_gerrit.addFakeChange('common-config', 'master', 'B',
1154 files=file_dict)
1155 B.setDependsOn(A, 1)
1156 C = self.fake_gerrit.addFakeChange('common-config', 'master', 'C')
1157 C.setDependsOn(B, 1)
1158 self.fake_gerrit.addEvent(C.getPatchsetCreatedEvent(1))
1159 self.waitUntilSettled()
1160
1161 self.assertEqual(C.reported, 1,
1162 "C should report failure")
1163 self.assertIn('depends on a change that failed to merge',
1164 C.messages[0],
1165 "C should have an error reported")
1166
James E. Blairc73c73a2017-01-20 15:15:15 -08001167
James E. Blairc9455002017-09-06 09:22:19 -07001168class TestInRepoJoin(ZuulTestCase):
1169 # In this config, org/project is not a member of any pipelines, so
1170 # that we may test the changes that cause it to join them.
1171
1172 tenant_config_file = 'config/in-repo-join/main.yaml'
1173
1174 def test_dynamic_dependent_pipeline(self):
1175 # Test dynamically adding a project to a
1176 # dependent pipeline for the first time
1177 self.executor_server.hold_jobs_in_build = True
1178
1179 tenant = self.sched.abide.tenants.get('tenant-one')
1180 gate_pipeline = tenant.layout.pipelines['gate']
1181
1182 in_repo_conf = textwrap.dedent(
1183 """
1184 - job:
1185 name: project-test1
1186
1187 - job:
1188 name: project-test2
1189
1190 - project:
1191 name: org/project
1192 gate:
1193 jobs:
1194 - project-test2
1195 """)
1196
1197 in_repo_playbook = textwrap.dedent(
1198 """
1199 - hosts: all
1200 tasks: []
1201 """)
1202
1203 file_dict = {'.zuul.yaml': in_repo_conf,
1204 'playbooks/project-test2.yaml': in_repo_playbook}
1205 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
1206 files=file_dict)
1207 A.addApproval('Code-Review', 2)
1208 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
1209 self.waitUntilSettled()
1210
1211 items = gate_pipeline.getAllItems()
1212 self.assertEqual(items[0].change.number, '1')
1213 self.assertEqual(items[0].change.patchset, '1')
1214 self.assertTrue(items[0].live)
1215
1216 self.executor_server.hold_jobs_in_build = False
1217 self.executor_server.release()
1218 self.waitUntilSettled()
1219
1220 # Make sure the dynamic queue got cleaned up
1221 self.assertEqual(gate_pipeline.queues, [])
1222
1223 def test_dynamic_dependent_pipeline_failure(self):
1224 # Test that a change behind a failing change adding a project
1225 # to a dependent pipeline is dequeued.
1226 self.executor_server.hold_jobs_in_build = True
1227
1228 in_repo_conf = textwrap.dedent(
1229 """
1230 - job:
1231 name: project-test1
1232
1233 - project:
1234 name: org/project
1235 gate:
1236 jobs:
1237 - project-test1
1238 """)
1239
1240 file_dict = {'.zuul.yaml': in_repo_conf}
1241 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
1242 files=file_dict)
1243 self.executor_server.failJob('project-test1', A)
1244 A.addApproval('Code-Review', 2)
1245 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
1246 self.waitUntilSettled()
1247
1248 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
1249 B.addApproval('Code-Review', 2)
1250 self.fake_gerrit.addEvent(B.addApproval('Approved', 1))
1251 self.waitUntilSettled()
1252
James E. Blair3490c5d2017-09-07 08:33:23 -07001253 self.orderedRelease()
James E. Blairc9455002017-09-06 09:22:19 -07001254 self.waitUntilSettled()
1255 self.assertEqual(A.reported, 2,
1256 "A should report start and failure")
1257 self.assertEqual(A.data['status'], 'NEW')
1258 self.assertEqual(B.reported, 1,
1259 "B should report start")
1260 self.assertHistory([
1261 dict(name='project-test1', result='FAILURE', changes='1,1'),
James E. Blair3490c5d2017-09-07 08:33:23 -07001262 dict(name='project-test1', result='ABORTED', changes='1,1 2,1'),
James E. Blairc9455002017-09-06 09:22:19 -07001263 ], ordered=False)
1264
James E. Blair0af198f2017-09-06 09:52:35 -07001265 def test_dynamic_dependent_pipeline_absent(self):
1266 # Test that a series of dependent changes don't report merge
1267 # failures to a pipeline they aren't in.
1268 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1269 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
1270 B.setDependsOn(A, 1)
1271
1272 A.addApproval('Code-Review', 2)
1273 A.addApproval('Approved', 1)
1274 B.addApproval('Code-Review', 2)
1275 self.fake_gerrit.addEvent(B.addApproval('Approved', 1))
1276 self.waitUntilSettled()
1277 self.assertEqual(A.reported, 0,
1278 "A should not report")
1279 self.assertEqual(A.data['status'], 'NEW')
1280 self.assertEqual(B.reported, 0,
1281 "B should not report")
1282 self.assertEqual(B.data['status'], 'NEW')
1283 self.assertHistory([])
1284
James E. Blairc9455002017-09-06 09:22:19 -07001285
James E. Blairc73c73a2017-01-20 15:15:15 -08001286class TestAnsible(AnsibleZuulTestCase):
1287 # A temporary class to hold new tests while others are disabled
1288
1289 tenant_config_file = 'config/ansible/main.yaml'
1290
1291 def test_playbook(self):
Jamie Lennox7655b552017-03-17 12:33:38 +11001292 # Keep the jobdir around so we can inspect contents if an
1293 # assert fails.
1294 self.executor_server.keep_jobdir = True
1295 # Output extra ansible info so we might see errors.
1296 self.executor_server.verbose = True
1297 # Add a site variables file, used by check-vars
1298 path = os.path.join(FIXTURE_DIR, 'config', 'ansible',
1299 'variables.yaml')
1300 self.config.set('executor', 'variables', path)
James E. Blairc73c73a2017-01-20 15:15:15 -08001301 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1302 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
1303 self.waitUntilSettled()
Tobias Henkel077f2f32017-05-30 20:16:46 +02001304 build_timeout = self.getJobFromHistory('timeout')
Jamie Lennox7655b552017-03-17 12:33:38 +11001305 with self.jobLog(build_timeout):
1306 self.assertEqual(build_timeout.result, 'TIMED_OUT')
Tobias Henkel077f2f32017-05-30 20:16:46 +02001307 build_faillocal = self.getJobFromHistory('faillocal')
Jamie Lennox7655b552017-03-17 12:33:38 +11001308 with self.jobLog(build_faillocal):
1309 self.assertEqual(build_faillocal.result, 'FAILURE')
Tobias Henkel077f2f32017-05-30 20:16:46 +02001310 build_failpost = self.getJobFromHistory('failpost')
Jamie Lennox7655b552017-03-17 12:33:38 +11001311 with self.jobLog(build_failpost):
1312 self.assertEqual(build_failpost.result, 'POST_FAILURE')
Tobias Henkel077f2f32017-05-30 20:16:46 +02001313 build_check_vars = self.getJobFromHistory('check-vars')
Jamie Lennox7655b552017-03-17 12:33:38 +11001314 with self.jobLog(build_check_vars):
1315 self.assertEqual(build_check_vars.result, 'SUCCESS')
Monty Tayloraff8b402017-08-16 18:40:41 -05001316 build_check_secret_names = self.getJobFromHistory('check-secret-names')
1317 with self.jobLog(build_check_secret_names):
1318 self.assertEqual(build_check_secret_names.result, 'SUCCESS')
Tobias Henkel077f2f32017-05-30 20:16:46 +02001319 build_hello = self.getJobFromHistory('hello-world')
Jamie Lennox7655b552017-03-17 12:33:38 +11001320 with self.jobLog(build_hello):
1321 self.assertEqual(build_hello.result, 'SUCCESS')
Tobias Henkel077f2f32017-05-30 20:16:46 +02001322 build_python27 = self.getJobFromHistory('python27')
Jamie Lennox7655b552017-03-17 12:33:38 +11001323 with self.jobLog(build_python27):
1324 self.assertEqual(build_python27.result, 'SUCCESS')
1325 flag_path = os.path.join(self.test_root,
1326 build_python27.uuid + '.flag')
1327 self.assertTrue(os.path.exists(flag_path))
1328 copied_path = os.path.join(self.test_root, build_python27.uuid +
1329 '.copied')
1330 self.assertTrue(os.path.exists(copied_path))
1331 failed_path = os.path.join(self.test_root, build_python27.uuid +
1332 '.failed')
1333 self.assertFalse(os.path.exists(failed_path))
1334 pre_flag_path = os.path.join(self.test_root, build_python27.uuid +
1335 '.pre.flag')
1336 self.assertTrue(os.path.exists(pre_flag_path))
1337 post_flag_path = os.path.join(self.test_root, build_python27.uuid +
1338 '.post.flag')
1339 self.assertTrue(os.path.exists(post_flag_path))
1340 bare_role_flag_path = os.path.join(self.test_root,
1341 build_python27.uuid +
1342 '.bare-role.flag')
1343 self.assertTrue(os.path.exists(bare_role_flag_path))
1344 secrets_path = os.path.join(self.test_root,
1345 build_python27.uuid + '.secrets')
1346 with open(secrets_path) as f:
1347 self.assertEqual(f.read(), "test-username test-password")
James E. Blairb9c0d772017-03-03 14:34:49 -08001348
Jamie Lennox7655b552017-03-17 12:33:38 +11001349 msg = A.messages[0]
1350 success = "{} https://success.example.com/zuul-logs/{}"
1351 fail = "{} https://failure.example.com/zuul-logs/{}"
1352 self.assertIn(success.format("python27", build_python27.uuid), msg)
1353 self.assertIn(fail.format("faillocal", build_faillocal.uuid), msg)
1354 self.assertIn(success.format("check-vars",
1355 build_check_vars.uuid), msg)
1356 self.assertIn(success.format("hello-world", build_hello.uuid), msg)
1357 self.assertIn(fail.format("timeout", build_timeout.uuid), msg)
1358 self.assertIn(fail.format("failpost", build_failpost.uuid), msg)
Tobias Henkel077f2f32017-05-30 20:16:46 +02001359
James E. Blairabbaa6f2017-04-06 16:11:44 -07001360 def _add_job(self, job_name):
1361 conf = textwrap.dedent(
1362 """
1363 - job:
1364 name: %s
1365
1366 - project:
1367 name: org/plugin-project
1368 check:
1369 jobs:
1370 - %s
1371 """ % (job_name, job_name))
1372
1373 file_dict = {'.zuul.yaml': conf}
1374 A = self.fake_gerrit.addFakeChange('org/plugin-project', 'master', 'A',
1375 files=file_dict)
1376 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
1377 self.waitUntilSettled()
1378
1379 def test_plugins(self):
1380 # Keep the jobdir around so we can inspect contents if an
1381 # assert fails.
1382 self.executor_server.keep_jobdir = True
1383 # Output extra ansible info so we might see errors.
1384 self.executor_server.verbose = True
1385
1386 count = 0
1387 plugin_tests = [
1388 ('passwd', 'FAILURE'),
1389 ('cartesian', 'SUCCESS'),
1390 ('consul_kv', 'FAILURE'),
1391 ('credstash', 'FAILURE'),
1392 ('csvfile_good', 'SUCCESS'),
1393 ('csvfile_bad', 'FAILURE'),
Monty Taylor93ad2212017-08-02 14:59:50 -05001394 ('uri_bad_path', 'FAILURE'),
1395 ('uri_bad_scheme', 'FAILURE'),
Monty Taylor788a40e2017-08-02 16:14:05 -05001396 ('block_local_override', 'FAILURE'),
Monty Taylor8da768f2017-08-31 14:15:35 -05001397 ('file_local_good', 'SUCCESS'),
1398 ('file_local_bad', 'FAILURE'),
James E. Blairabbaa6f2017-04-06 16:11:44 -07001399 ]
1400 for job_name, result in plugin_tests:
1401 count += 1
1402 self._add_job(job_name)
1403
1404 job = self.getJobFromHistory(job_name)
1405 with self.jobLog(job):
1406 self.assertEqual(count, len(self.history))
1407 build = self.history[-1]
1408 self.assertEqual(build.result, result)
1409
1410 # TODOv3(jeblair): parse the ansible output and verify we're
1411 # getting the exception we expect.
1412
James E. Blairb9c0d772017-03-03 14:34:49 -08001413
James E. Blaira4d4eef2017-06-30 14:49:17 -07001414class TestPrePlaybooks(AnsibleZuulTestCase):
1415 # A temporary class to hold new tests while others are disabled
1416
1417 tenant_config_file = 'config/pre-playbook/main.yaml'
1418
1419 def test_pre_playbook_fail(self):
1420 # Test that we run the post playbooks (but not the actual
1421 # playbook) when a pre-playbook fails.
1422 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1423 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
1424 self.waitUntilSettled()
1425 build = self.getJobFromHistory('python27')
1426 self.assertIsNone(build.result)
1427 self.assertIn('RETRY_LIMIT', A.messages[0])
1428 flag_path = os.path.join(self.test_root, build.uuid +
1429 '.main.flag')
1430 self.assertFalse(os.path.exists(flag_path))
1431 pre_flag_path = os.path.join(self.test_root, build.uuid +
1432 '.pre.flag')
1433 self.assertFalse(os.path.exists(pre_flag_path))
1434 post_flag_path = os.path.join(self.test_root, build.uuid +
1435 '.post.flag')
James E. Blair21037782017-07-19 11:56:55 -07001436 self.assertTrue(os.path.exists(post_flag_path),
1437 "The file %s should exist" % post_flag_path)
James E. Blaira4d4eef2017-06-30 14:49:17 -07001438
1439
James E. Blairb9c0d772017-03-03 14:34:49 -08001440class TestBrokenConfig(ZuulTestCase):
1441 # Test that we get an appropriate syntax error if we start with a
1442 # broken config.
1443
1444 tenant_config_file = 'config/broken/main.yaml'
1445
1446 def setUp(self):
1447 with testtools.ExpectedException(
1448 zuul.configloader.ConfigurationSyntaxError,
1449 "\nZuul encountered a syntax error"):
1450 super(TestBrokenConfig, self).setUp()
1451
1452 def test_broken_config_on_startup(self):
1453 pass
Ricardo Carrillo Cruz22994f92016-12-02 11:41:58 +00001454
1455
1456class TestProjectKeys(ZuulTestCase):
1457 # Test that we can generate project keys
1458
1459 # Normally the test infrastructure copies a static key in place
1460 # for each project before starting tests. This saves time because
1461 # Zuul's automatic key-generation on startup can be slow. To make
1462 # sure we exercise that code, in this test we allow Zuul to create
1463 # keys for the project on startup.
1464 create_project_keys = True
Tobias Henkelabf973e2017-07-28 10:07:34 +02001465 config_file = 'zuul-connections-gerrit-and-github.conf'
Ricardo Carrillo Cruz22994f92016-12-02 11:41:58 +00001466 tenant_config_file = 'config/in-repo/main.yaml'
1467
1468 def test_key_generation(self):
1469 key_root = os.path.join(self.state_root, 'keys')
1470 private_key_file = os.path.join(key_root, 'gerrit/org/project.pem')
1471 # Make sure that a proper key was created on startup
1472 with open(private_key_file, "rb") as f:
James E. Blairbf1a4f22017-03-17 10:59:37 -07001473 private_key, public_key = \
1474 encryption.deserialize_rsa_keypair(f.read())
Ricardo Carrillo Cruz22994f92016-12-02 11:41:58 +00001475
1476 with open(os.path.join(FIXTURE_DIR, 'private.pem')) as i:
1477 fixture_private_key = i.read()
1478
1479 # Make sure that we didn't just end up with the static fixture
1480 # key
1481 self.assertNotEqual(fixture_private_key, private_key)
1482
1483 # Make sure it's the right length
1484 self.assertEqual(4096, private_key.key_size)
James E. Blairbce76932017-05-04 10:03:15 -07001485
1486
James E. Blairbb94dfa2017-07-11 07:45:19 -07001487class RoleTestCase(ZuulTestCase):
James E. Blair1b27f6a2017-07-14 14:09:07 -07001488 def _assertRolePath(self, build, playbook, content):
1489 path = os.path.join(self.test_root, build.uuid,
1490 'ansible', playbook, 'ansible.cfg')
1491 roles_paths = []
1492 with open(path) as f:
1493 for line in f:
1494 if line.startswith('roles_path'):
1495 roles_paths.append(line)
1496 print(roles_paths)
1497 if content:
1498 self.assertEqual(len(roles_paths), 1,
1499 "Should have one roles_path line in %s" %
1500 (playbook,))
1501 self.assertIn(content, roles_paths[0])
1502 else:
1503 self.assertEqual(len(roles_paths), 0,
1504 "Should have no roles_path line in %s" %
1505 (playbook,))
1506
James E. Blairbb94dfa2017-07-11 07:45:19 -07001507
1508class TestRoles(RoleTestCase):
1509 tenant_config_file = 'config/roles/main.yaml'
1510
James E. Blairbce76932017-05-04 10:03:15 -07001511 def test_role(self):
1512 # This exercises a proposed change to a role being checked out
1513 # and used.
1514 A = self.fake_gerrit.addFakeChange('bare-role', 'master', 'A')
1515 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1516 B.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
1517 B.subject, A.data['id'])
1518 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
1519 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
1520 self.waitUntilSettled()
1521 self.assertHistory([
1522 dict(name='project-test', result='SUCCESS', changes='1,1 2,1'),
1523 ])
James E. Blair6459db12017-06-29 14:57:20 -07001524
James E. Blair1b27f6a2017-07-14 14:09:07 -07001525 def test_role_inheritance(self):
1526 self.executor_server.hold_jobs_in_build = True
1527 conf = textwrap.dedent(
1528 """
1529 - job:
1530 name: parent
1531 roles:
1532 - zuul: bare-role
1533 pre-run: playbooks/parent-pre
1534 post-run: playbooks/parent-post
1535
1536 - job:
1537 name: project-test
1538 parent: parent
1539 roles:
1540 - zuul: org/project
1541
1542 - project:
1543 name: org/project
1544 check:
1545 jobs:
1546 - project-test
1547 """)
1548
1549 file_dict = {'.zuul.yaml': conf}
1550 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
1551 files=file_dict)
1552 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
1553 self.waitUntilSettled()
1554
1555 self.assertEqual(len(self.builds), 1)
1556 build = self.getBuildByName('project-test')
1557 self._assertRolePath(build, 'pre_playbook_0', 'role_0')
1558 self._assertRolePath(build, 'playbook_0', 'role_0')
1559 self._assertRolePath(build, 'playbook_0', 'role_1')
1560 self._assertRolePath(build, 'post_playbook_0', 'role_0')
1561
1562 self.executor_server.hold_jobs_in_build = False
1563 self.executor_server.release()
1564 self.waitUntilSettled()
1565
1566 self.assertHistory([
1567 dict(name='project-test', result='SUCCESS', changes='1,1'),
1568 ])
1569
James E. Blair6f699732017-07-18 14:19:11 -07001570 def test_role_error(self):
1571 conf = textwrap.dedent(
1572 """
1573 - job:
1574 name: project-test
1575 roles:
1576 - zuul: common-config
1577
1578 - project:
1579 name: org/project
1580 check:
1581 jobs:
1582 - project-test
1583 """)
1584
1585 file_dict = {'.zuul.yaml': conf}
1586 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
1587 files=file_dict)
1588 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
1589 self.waitUntilSettled()
1590 self.assertIn(
1591 '- project-test project-test : ERROR Unable to find role',
1592 A.messages[-1])
1593
James E. Blair6459db12017-06-29 14:57:20 -07001594
James E. Blairbb94dfa2017-07-11 07:45:19 -07001595class TestImplicitRoles(RoleTestCase):
1596 tenant_config_file = 'config/implicit-roles/main.yaml'
1597
1598 def test_missing_roles(self):
1599 # Test implicit and explicit roles for a project which does
1600 # not have roles. The implicit role should be silently
1601 # ignored since the project doesn't supply roles, but if a
1602 # user declares an explicit role, it should error.
1603 self.executor_server.hold_jobs_in_build = True
1604 A = self.fake_gerrit.addFakeChange('org/norole-project', 'master', 'A')
1605 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
1606 self.waitUntilSettled()
1607
1608 self.assertEqual(len(self.builds), 2)
1609 build = self.getBuildByName('implicit-role-fail')
1610 self._assertRolePath(build, 'playbook_0', None)
1611
1612 self.executor_server.hold_jobs_in_build = False
1613 self.executor_server.release()
1614 self.waitUntilSettled()
1615 # The retry_limit doesn't get recorded
1616 self.assertHistory([
1617 dict(name='implicit-role-fail', result='SUCCESS', changes='1,1'),
1618 ])
1619
1620 def test_roles(self):
1621 # Test implicit and explicit roles for a project which does
1622 # have roles. In both cases, we should end up with the role
1623 # in the path. In the explicit case, ensure we end up with
1624 # the name we specified.
1625 self.executor_server.hold_jobs_in_build = True
1626 A = self.fake_gerrit.addFakeChange('org/role-project', 'master', 'A')
1627 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
1628 self.waitUntilSettled()
1629
1630 self.assertEqual(len(self.builds), 2)
1631 build = self.getBuildByName('implicit-role-ok')
1632 self._assertRolePath(build, 'playbook_0', 'role_0')
1633
1634 build = self.getBuildByName('explicit-role-ok')
1635 self._assertRolePath(build, 'playbook_0', 'role_0')
1636
1637 self.executor_server.hold_jobs_in_build = False
1638 self.executor_server.release()
1639 self.waitUntilSettled()
1640 self.assertHistory([
1641 dict(name='implicit-role-ok', result='SUCCESS', changes='1,1'),
1642 dict(name='explicit-role-ok', result='SUCCESS', changes='1,1'),
1643 ], ordered=False)
1644
1645
James E. Blair6459db12017-06-29 14:57:20 -07001646class TestShadow(ZuulTestCase):
1647 tenant_config_file = 'config/shadow/main.yaml'
1648
1649 def test_shadow(self):
1650 # Test that a repo is allowed to shadow another's job definitions.
1651 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1652 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
1653 self.waitUntilSettled()
1654 self.assertHistory([
1655 dict(name='test1', result='SUCCESS', changes='1,1'),
1656 dict(name='test2', result='SUCCESS', changes='1,1'),
James E. Blairadafa6c2017-07-12 08:50:56 -07001657 ], ordered=False)
James E. Blair196f61a2017-06-30 15:42:29 -07001658
1659
1660class TestDataReturn(AnsibleZuulTestCase):
1661 tenant_config_file = 'config/data-return/main.yaml'
1662
1663 def test_data_return(self):
1664 # This exercises a proposed change to a role being checked out
1665 # and used.
1666 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1667 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
1668 self.waitUntilSettled()
1669 self.assertHistory([
1670 dict(name='data-return', result='SUCCESS', changes='1,1'),
James E. Blair88e79c02017-07-07 13:36:54 -07001671 dict(name='data-return-relative', result='SUCCESS', changes='1,1'),
1672 ], ordered=False)
1673 self.assertIn('- data-return http://example.com/test/log/url/',
1674 A.messages[-1])
1675 self.assertIn('- data-return-relative '
1676 'http://example.com/test/log/url/docs/index.html',
James E. Blair196f61a2017-06-30 15:42:29 -07001677 A.messages[-1])
Clint Byrumdc8a0902017-07-20 16:36:27 -07001678
1679
1680class TestDiskAccounting(AnsibleZuulTestCase):
1681 config_file = 'zuul-disk-accounting.conf'
1682 tenant_config_file = 'config/disk-accountant/main.yaml'
1683
1684 def test_disk_accountant_kills_job(self):
1685 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1686 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
1687 self.waitUntilSettled()
1688 self.assertHistory([
1689 dict(name='dd-big-empty-file', result='ABORTED', changes='1,1')])
Tristan Cacqueray82f864b2017-08-01 05:54:42 +00001690
1691
1692class TestMaxNodesPerJob(AnsibleZuulTestCase):
1693 tenant_config_file = 'config/multi-tenant/main.yaml'
1694
Tristan Cacquerayc98bff72017-09-10 15:25:26 +00001695 def test_max_timeout_exceeded(self):
Tristan Cacqueray82f864b2017-08-01 05:54:42 +00001696 in_repo_conf = textwrap.dedent(
1697 """
1698 - job:
1699 name: test-job
James E. Blair7e3e6882017-09-20 15:47:13 -07001700 nodeset:
1701 nodes:
1702 - name: node01
1703 label: fake
1704 - name: node02
1705 label: fake
1706 - name: node03
1707 label: fake
1708 - name: node04
1709 label: fake
1710 - name: node05
1711 label: fake
1712 - name: node06
1713 label: fake
Tristan Cacqueray82f864b2017-08-01 05:54:42 +00001714 """)
1715 file_dict = {'.zuul.yaml': in_repo_conf}
1716 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A',
1717 files=file_dict)
1718 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
1719 self.waitUntilSettled()
1720 self.assertIn('The job "test-job" exceeds tenant max-nodes-per-job 5.',
1721 A.messages[0], "A should fail because of nodes limit")
1722
1723 B = self.fake_gerrit.addFakeChange('org/project2', 'master', 'A',
1724 files=file_dict)
1725 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
1726 self.waitUntilSettled()
1727 self.assertNotIn("exceeds tenant max-nodes", B.messages[0],
1728 "B should not fail because of nodes limit")
James E. Blair2bab6e72017-08-07 09:52:45 -07001729
1730
Tristan Cacquerayc98bff72017-09-10 15:25:26 +00001731class TestMaxTimeout(AnsibleZuulTestCase):
1732 tenant_config_file = 'config/multi-tenant/main.yaml'
1733
1734 def test_max_nodes_reached(self):
1735 in_repo_conf = textwrap.dedent(
1736 """
1737 - job:
1738 name: test-job
1739 timeout: 3600
1740 """)
1741 file_dict = {'.zuul.yaml': in_repo_conf}
1742 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A',
1743 files=file_dict)
1744 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
1745 self.waitUntilSettled()
1746 self.assertIn('The job "test-job" exceeds tenant max-job-timeout',
1747 A.messages[0], "A should fail because of timeout limit")
1748
1749 B = self.fake_gerrit.addFakeChange('org/project2', 'master', 'A',
1750 files=file_dict)
1751 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
1752 self.waitUntilSettled()
1753 self.assertNotIn("exceeds tenant max-job-timeout", B.messages[0],
1754 "B should not fail because of timeout limit")
1755
1756
James E. Blair2bab6e72017-08-07 09:52:45 -07001757class TestBaseJobs(ZuulTestCase):
1758 tenant_config_file = 'config/base-jobs/main.yaml'
1759
1760 def test_multiple_base_jobs(self):
1761 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1762 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
1763 self.waitUntilSettled()
1764 self.assertHistory([
1765 dict(name='my-job', result='SUCCESS', changes='1,1'),
1766 dict(name='other-job', result='SUCCESS', changes='1,1'),
1767 ], ordered=False)
1768 self.assertEqual(self.getJobFromHistory('my-job').
1769 parameters['zuul']['jobtags'],
1770 ['mybase'])
1771 self.assertEqual(self.getJobFromHistory('other-job').
1772 parameters['zuul']['jobtags'],
1773 ['otherbase'])
1774
1775 def test_untrusted_base_job(self):
1776 """Test that a base job may not be defined in an untrusted repo"""
1777 in_repo_conf = textwrap.dedent(
1778 """
1779 - job:
1780 name: fail-base
1781 parent: null
1782 """)
1783
1784 file_dict = {'.zuul.yaml': in_repo_conf}
1785 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
1786 files=file_dict)
1787 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
1788 self.waitUntilSettled()
1789 self.assertEqual(A.reported, 1,
1790 "A should report failure")
1791 self.assertEqual(A.patchsets[0]['approvals'][0]['value'], "-1")
1792 self.assertIn('Base jobs must be defined in config projects',
1793 A.messages[0])
1794 self.assertHistory([])
James E. Blairdb089032017-08-15 13:42:12 -07001795
1796
1797class TestSecretLeaks(AnsibleZuulTestCase):
1798 tenant_config_file = 'config/secret-leaks/main.yaml'
1799
1800 def searchForContent(self, path, content):
1801 matches = []
1802 for (dirpath, dirnames, filenames) in os.walk(path):
1803 for filename in filenames:
1804 filepath = os.path.join(dirpath, filename)
1805 with open(filepath, 'rb') as f:
1806 if content in f.read():
1807 matches.append(filepath[len(path):])
1808 return matches
1809
1810 def _test_secret_file(self):
1811 # Or rather -- test that they *don't* leak.
1812 # Keep the jobdir around so we can inspect contents.
1813 self.executor_server.keep_jobdir = True
1814 conf = textwrap.dedent(
1815 """
1816 - project:
1817 name: org/project
1818 check:
1819 jobs:
1820 - secret-file
1821 """)
1822
1823 file_dict = {'.zuul.yaml': conf}
1824 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
1825 files=file_dict)
1826 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
1827 self.waitUntilSettled()
1828 self.assertHistory([
1829 dict(name='secret-file', result='SUCCESS', changes='1,1'),
1830 ], ordered=False)
1831 matches = self.searchForContent(self.history[0].jobdir.root,
1832 b'test-password')
James E. Blaird6a71ca2017-08-18 14:15:05 -07001833 self.assertEqual(set(['/work/secret-file.txt']),
James E. Blairdb089032017-08-15 13:42:12 -07001834 set(matches))
1835
1836 def test_secret_file(self):
1837 self._test_secret_file()
1838
1839 def test_secret_file_verbose(self):
1840 # Output extra ansible info to exercise alternate logging code
1841 # paths.
1842 self.executor_server.verbose = True
1843 self._test_secret_file()
1844
1845 def _test_secret_file_fail(self):
1846 # Or rather -- test that they *don't* leak.
1847 # Keep the jobdir around so we can inspect contents.
1848 self.executor_server.keep_jobdir = True
1849 conf = textwrap.dedent(
1850 """
1851 - project:
1852 name: org/project
1853 check:
1854 jobs:
1855 - secret-file-fail
1856 """)
1857
1858 file_dict = {'.zuul.yaml': conf}
1859 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
1860 files=file_dict)
1861 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
1862 self.waitUntilSettled()
1863 self.assertHistory([
1864 dict(name='secret-file-fail', result='FAILURE', changes='1,1'),
1865 ], ordered=False)
1866 matches = self.searchForContent(self.history[0].jobdir.root,
1867 b'test-password')
James E. Blaird6a71ca2017-08-18 14:15:05 -07001868 self.assertEqual(set(['/work/failure-file.txt']),
James E. Blairdb089032017-08-15 13:42:12 -07001869 set(matches))
1870
1871 def test_secret_file_fail(self):
1872 self._test_secret_file_fail()
1873
1874 def test_secret_file_fail_verbose(self):
1875 # Output extra ansible info to exercise alternate logging code
1876 # paths.
1877 self.executor_server.verbose = True
1878 self._test_secret_file_fail()
James E. Blaira00910c2017-08-23 09:15:04 -07001879
1880
1881class TestJobOutput(AnsibleZuulTestCase):
1882 tenant_config_file = 'config/job-output/main.yaml'
1883
1884 def _get_file(self, build, path):
1885 p = os.path.join(build.jobdir.root, path)
1886 with open(p) as f:
1887 return f.read()
1888
1889 def test_job_output(self):
Monty Taylor0e2489a2017-10-10 11:57:29 -05001890 # Verify that command standard output appears in the job output,
1891 # and that failures in the final playbook get logged.
James E. Blaira00910c2017-08-23 09:15:04 -07001892
1893 # This currently only verifies we receive output from
1894 # localhost. Notably, it does not verify we receive output
1895 # via zuul_console streaming.
1896 self.executor_server.keep_jobdir = True
1897 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1898 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
1899 self.waitUntilSettled()
1900 self.assertHistory([
1901 dict(name='job-output', result='SUCCESS', changes='1,1'),
1902 ], ordered=False)
1903
1904 token = 'Standard output test %s' % (self.history[0].jobdir.src_root)
1905 j = json.loads(self._get_file(self.history[0],
1906 'work/logs/job-output.json'))
1907 self.assertEqual(token,
1908 j[0]['plays'][0]['tasks'][0]
1909 ['hosts']['localhost']['stdout'])
1910
1911 print(self._get_file(self.history[0],
1912 'work/logs/job-output.txt'))
1913 self.assertIn(token,
1914 self._get_file(self.history[0],
1915 'work/logs/job-output.txt'))
Monty Taylor0e2489a2017-10-10 11:57:29 -05001916
1917 def test_job_output_failure_log(self):
1918 logger = logging.getLogger('zuul.AnsibleJob')
1919 output = io.StringIO()
1920 logger.addHandler(logging.StreamHandler(output))
1921
1922 # Verify that a failure in the last post playbook emits the contents
1923 # of the json output to the log
1924 self.executor_server.keep_jobdir = True
1925 A = self.fake_gerrit.addFakeChange('org/project2', 'master', 'A')
1926 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
1927 self.waitUntilSettled()
1928 self.assertHistory([
1929 dict(name='job-output-failure',
1930 result='POST_FAILURE', changes='1,1'),
1931 ], ordered=False)
1932
1933 token = 'Standard output test %s' % (self.history[0].jobdir.src_root)
1934 j = json.loads(self._get_file(self.history[0],
1935 'work/logs/job-output.json'))
1936 self.assertEqual(token,
1937 j[0]['plays'][0]['tasks'][0]
1938 ['hosts']['localhost']['stdout'])
1939
1940 print(self._get_file(self.history[0],
1941 'work/logs/job-output.json'))
1942 self.assertIn(token,
1943 self._get_file(self.history[0],
1944 'work/logs/job-output.txt'))
1945
1946 log_output = output.getvalue()
1947 self.assertIn('Final playbook failed', log_output)
1948 self.assertIn('Failure test', log_output)