blob: fbc629b942e58e198aad134b4ff038f97c15ef11 [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
James E. Blaira00910c2017-08-23 09:15:04 -070017import json
James E. Blaira92cbc82017-01-23 14:56:49 -080018import os
James E. Blair14abdf42015-12-09 16:11:53 -080019import textwrap
James E. Blair3a098dd2017-10-04 14:37:29 -070020import gc
21from unittest import skip
James E. Blair59fdbac2015-12-07 17:08:06 -080022
James E. Blairb9c0d772017-03-03 14:34:49 -080023import testtools
24
25import zuul.configloader
James E. Blairbf1a4f22017-03-17 10:59:37 -070026from zuul.lib import encryption
Ricardo Carrillo Cruz22994f92016-12-02 11:41:58 +000027from tests.base import AnsibleZuulTestCase, ZuulTestCase, FIXTURE_DIR
James E. Blair59fdbac2015-12-07 17:08:06 -080028
James E. Blair59fdbac2015-12-07 17:08:06 -080029
James E. Blair3f876d52016-07-22 13:07:14 -070030class TestMultipleTenants(AnsibleZuulTestCase):
James E. Blair59fdbac2015-12-07 17:08:06 -080031 # A temporary class to hold new tests while others are disabled
32
James E. Blair2a629ec2015-12-22 15:32:02 -080033 tenant_config_file = 'config/multi-tenant/main.yaml'
James E. Blair59fdbac2015-12-07 17:08:06 -080034
James E. Blair83005782015-12-11 14:46:03 -080035 def test_multiple_tenants(self):
James E. Blair96f26942015-12-09 10:15:59 -080036 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A')
Tobias Henkelbf24fd12017-07-27 06:13:07 +020037 A.addApproval('Code-Review', 2)
38 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
James E. Blair59fdbac2015-12-07 17:08:06 -080039 self.waitUntilSettled()
James E. Blair96f26942015-12-09 10:15:59 -080040 self.assertEqual(self.getJobFromHistory('project1-test1').result,
James E. Blair59fdbac2015-12-07 17:08:06 -080041 'SUCCESS')
James E. Blair96c6bf82016-01-15 16:20:40 -080042 self.assertEqual(self.getJobFromHistory('python27').result,
43 'SUCCESS')
James E. Blair59fdbac2015-12-07 17:08:06 -080044 self.assertEqual(A.data['status'], 'MERGED')
James E. Blair96f26942015-12-09 10:15:59 -080045 self.assertEqual(A.reported, 2,
46 "A should report start and success")
47 self.assertIn('tenant-one-gate', A.messages[1],
48 "A should transit tenant-one gate")
49 self.assertNotIn('tenant-two-gate', A.messages[1],
50 "A should *not* transit tenant-two gate")
James E. Blair59fdbac2015-12-07 17:08:06 -080051
James E. Blair96f26942015-12-09 10:15:59 -080052 B = self.fake_gerrit.addFakeChange('org/project2', 'master', 'B')
Tobias Henkelbf24fd12017-07-27 06:13:07 +020053 B.addApproval('Code-Review', 2)
54 self.fake_gerrit.addEvent(B.addApproval('Approved', 1))
James E. Blair96f26942015-12-09 10:15:59 -080055 self.waitUntilSettled()
James E. Blair96c6bf82016-01-15 16:20:40 -080056 self.assertEqual(self.getJobFromHistory('python27',
57 'org/project2').result,
58 'SUCCESS')
James E. Blair96f26942015-12-09 10:15:59 -080059 self.assertEqual(self.getJobFromHistory('project2-test1').result,
60 'SUCCESS')
61 self.assertEqual(B.data['status'], 'MERGED')
62 self.assertEqual(B.reported, 2,
63 "B should report start and success")
64 self.assertIn('tenant-two-gate', B.messages[1],
65 "B should transit tenant-two gate")
66 self.assertNotIn('tenant-one-gate', B.messages[1],
67 "B should *not* transit tenant-one gate")
James E. Blair59fdbac2015-12-07 17:08:06 -080068
James E. Blair96f26942015-12-09 10:15:59 -080069 self.assertEqual(A.reported, 2, "Activity in tenant two should"
70 "not affect tenant one")
James E. Blair14abdf42015-12-09 16:11:53 -080071
James E. Blair83005782015-12-11 14:46:03 -080072
Tobias Henkel83167622017-06-30 19:45:03 +020073class TestFinal(ZuulTestCase):
74
75 tenant_config_file = 'config/final/main.yaml'
76
77 def test_final_variant_ok(self):
78 # test clean usage of final parent job
79 in_repo_conf = textwrap.dedent(
80 """
81 - project:
82 name: org/project
83 check:
84 jobs:
85 - job-final
86 """)
87
88 file_dict = {'.zuul.yaml': in_repo_conf}
89 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
90 files=file_dict)
91 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
92 self.waitUntilSettled()
93
94 self.assertEqual(A.reported, 1)
95 self.assertEqual(A.patchsets[-1]['approvals'][0]['value'], '1')
96
97 def test_final_variant_error(self):
98 # test misuse of final parent job
99 in_repo_conf = textwrap.dedent(
100 """
101 - project:
102 name: org/project
103 check:
104 jobs:
105 - job-final:
106 vars:
107 dont_override_this: bar
108 """)
109 file_dict = {'.zuul.yaml': in_repo_conf}
110 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
111 files=file_dict)
112 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
113 self.waitUntilSettled()
114
115 # The second patch tried to override some variables.
116 # Thus it should fail.
117 self.assertEqual(A.reported, 1)
118 self.assertEqual(A.patchsets[-1]['approvals'][0]['value'], '-1')
119 self.assertIn('Unable to modify final job', A.messages[0])
120
121 def test_final_inheritance(self):
122 # test misuse of final parent job
123 in_repo_conf = textwrap.dedent(
124 """
125 - job:
126 name: project-test
127 parent: job-final
128
129 - project:
130 name: org/project
131 check:
132 jobs:
133 - project-test
134 """)
135
136 in_repo_playbook = textwrap.dedent(
137 """
138 - hosts: all
139 tasks: []
140 """)
141
142 file_dict = {'.zuul.yaml': in_repo_conf,
143 'playbooks/project-test.yaml': in_repo_playbook}
144 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
145 files=file_dict)
146 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
147 self.waitUntilSettled()
148
149 # The second patch tried to override some variables.
150 # Thus it should fail.
151 self.assertEqual(A.reported, 1)
152 self.assertEqual(A.patchsets[-1]['approvals'][0]['value'], '-1')
153 self.assertIn('Unable to inherit from final job', A.messages[0])
154
155
James E. Blairff555742017-02-19 11:34:27 -0800156class TestInRepoConfig(ZuulTestCase):
James E. Blair83005782015-12-11 14:46:03 -0800157 # A temporary class to hold new tests while others are disabled
158
Tobias Henkelabf973e2017-07-28 10:07:34 +0200159 config_file = 'zuul-connections-gerrit-and-github.conf'
James E. Blair2a629ec2015-12-22 15:32:02 -0800160 tenant_config_file = 'config/in-repo/main.yaml'
James E. Blair83005782015-12-11 14:46:03 -0800161
James E. Blair83005782015-12-11 14:46:03 -0800162 def test_in_repo_config(self):
James E. Blair14abdf42015-12-09 16:11:53 -0800163 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
Tobias Henkelbf24fd12017-07-27 06:13:07 +0200164 A.addApproval('Code-Review', 2)
165 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
James E. Blair14abdf42015-12-09 16:11:53 -0800166 self.waitUntilSettled()
167 self.assertEqual(self.getJobFromHistory('project-test1').result,
168 'SUCCESS')
169 self.assertEqual(A.data['status'], 'MERGED')
170 self.assertEqual(A.reported, 2,
171 "A should report start and success")
172 self.assertIn('tenant-one-gate', A.messages[1],
173 "A should transit tenant-one gate")
James E. Blairb97ed802015-12-21 15:55:35 -0800174
James E. Blair3a098dd2017-10-04 14:37:29 -0700175 @skip("This test is useful, but not reliable")
176 def test_full_and_dynamic_reconfig(self):
177 self.executor_server.hold_jobs_in_build = True
178 in_repo_conf = textwrap.dedent(
179 """
180 - job:
181 name: project-test1
182
183 - project:
184 name: org/project
185 tenant-one-gate:
186 jobs:
187 - project-test1
188 """)
189
190 file_dict = {'.zuul.yaml': in_repo_conf}
191 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
192 files=file_dict)
193 A.addApproval('Code-Review', 2)
194 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
195 self.waitUntilSettled()
196 self.sched.reconfigure(self.config)
197 self.waitUntilSettled()
198
199 gc.collect()
200 pipelines = [obj for obj in gc.get_objects()
201 if isinstance(obj, zuul.model.Pipeline)]
202 self.assertEqual(len(pipelines), 4)
203
204 self.executor_server.hold_jobs_in_build = False
205 self.executor_server.release()
206 self.waitUntilSettled()
207
James E. Blair8b1dc3f2016-07-05 16:49:00 -0700208 def test_dynamic_config(self):
209 in_repo_conf = textwrap.dedent(
210 """
211 - job:
Tobias Henkelf02cf512017-07-21 22:55:34 +0200212 name: project-test1
213
214 - job:
James E. Blair8b1dc3f2016-07-05 16:49:00 -0700215 name: project-test2
216
217 - project:
218 name: org/project
219 tenant-one-gate:
220 jobs:
221 - project-test2
222 """)
223
James E. Blairc73c73a2017-01-20 15:15:15 -0800224 in_repo_playbook = textwrap.dedent(
225 """
226 - hosts: all
227 tasks: []
228 """)
229
230 file_dict = {'.zuul.yaml': in_repo_conf,
231 'playbooks/project-test2.yaml': in_repo_playbook}
James E. Blair8b1dc3f2016-07-05 16:49:00 -0700232 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
James E. Blairc73c73a2017-01-20 15:15:15 -0800233 files=file_dict)
Tobias Henkelbf24fd12017-07-27 06:13:07 +0200234 A.addApproval('Code-Review', 2)
235 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
James E. Blair8b1dc3f2016-07-05 16:49:00 -0700236 self.waitUntilSettled()
James E. Blair8b1dc3f2016-07-05 16:49:00 -0700237 self.assertEqual(A.data['status'], 'MERGED')
238 self.assertEqual(A.reported, 2,
239 "A should report start and success")
240 self.assertIn('tenant-one-gate', A.messages[1],
241 "A should transit tenant-one gate")
James E. Blair646322f2017-01-27 15:50:34 -0800242 self.assertHistory([
243 dict(name='project-test2', result='SUCCESS', changes='1,1')])
244
James E. Blairc2a5ed72017-02-20 14:12:01 -0500245 self.fake_gerrit.addEvent(A.getChangeMergedEvent())
James E. Blair7bbd7a32017-03-06 11:36:13 -0800246 self.waitUntilSettled()
James E. Blairc2a5ed72017-02-20 14:12:01 -0500247
James E. Blair646322f2017-01-27 15:50:34 -0800248 # Now that the config change is landed, it should be live for
249 # subsequent changes.
250 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
Tobias Henkelbf24fd12017-07-27 06:13:07 +0200251 B.addApproval('Code-Review', 2)
252 self.fake_gerrit.addEvent(B.addApproval('Approved', 1))
James E. Blair646322f2017-01-27 15:50:34 -0800253 self.waitUntilSettled()
254 self.assertEqual(self.getJobFromHistory('project-test2').result,
255 'SUCCESS')
256 self.assertHistory([
257 dict(name='project-test2', result='SUCCESS', changes='1,1'),
258 dict(name='project-test2', result='SUCCESS', changes='2,1')])
James E. Blairc73c73a2017-01-20 15:15:15 -0800259
Tobias Henkelf02cf512017-07-21 22:55:34 +0200260 def test_dynamic_config_non_existing_job(self):
261 """Test that requesting a non existent job fails"""
262 in_repo_conf = textwrap.dedent(
263 """
264 - job:
265 name: project-test1
266
267 - project:
268 name: org/project
269 check:
270 jobs:
271 - non-existent-job
272 """)
273
274 in_repo_playbook = textwrap.dedent(
275 """
276 - hosts: all
277 tasks: []
278 """)
279
280 file_dict = {'.zuul.yaml': in_repo_conf,
281 'playbooks/project-test2.yaml': in_repo_playbook}
282 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
283 files=file_dict)
284 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
285 self.waitUntilSettled()
286 self.assertEqual(A.reported, 1,
287 "A should report failure")
288 self.assertEqual(A.patchsets[0]['approvals'][0]['value'], "-1")
289 self.assertIn('Job non-existent-job not defined', A.messages[0],
290 "A should have failed the check pipeline")
291 self.assertHistory([])
292
293 def test_dynamic_config_non_existing_job_in_template(self):
294 """Test that requesting a non existent job fails"""
295 in_repo_conf = textwrap.dedent(
296 """
297 - job:
298 name: project-test1
299
300 - project-template:
301 name: test-template
302 check:
303 jobs:
304 - non-existent-job
305
306 - project:
307 name: org/project
308 templates:
309 - test-template
310 """)
311
312 in_repo_playbook = textwrap.dedent(
313 """
314 - hosts: all
315 tasks: []
316 """)
317
318 file_dict = {'.zuul.yaml': in_repo_conf,
319 'playbooks/project-test2.yaml': in_repo_playbook}
320 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
321 files=file_dict)
322 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
323 self.waitUntilSettled()
324 self.assertEqual(A.reported, 1,
325 "A should report failure")
326 self.assertEqual(A.patchsets[0]['approvals'][0]['value'], "-1")
327 self.assertIn('Job non-existent-job not defined', A.messages[0],
328 "A should have failed the check pipeline")
329 self.assertHistory([])
330
Tobias Henkel0f714002017-06-30 23:30:52 +0200331 def test_dynamic_config_new_patchset(self):
332 self.executor_server.hold_jobs_in_build = True
333
334 tenant = self.sched.abide.tenants.get('tenant-one')
335 check_pipeline = tenant.layout.pipelines['check']
336
337 in_repo_conf = textwrap.dedent(
338 """
339 - job:
Tobias Henkelf02cf512017-07-21 22:55:34 +0200340 name: project-test1
341
342 - job:
Tobias Henkel0f714002017-06-30 23:30:52 +0200343 name: project-test2
344
345 - project:
346 name: org/project
347 check:
348 jobs:
349 - project-test2
350 """)
351
352 in_repo_playbook = textwrap.dedent(
353 """
354 - hosts: all
355 tasks: []
356 """)
357
358 file_dict = {'.zuul.yaml': in_repo_conf,
359 'playbooks/project-test2.yaml': in_repo_playbook}
360 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
361 files=file_dict)
362 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
363 self.waitUntilSettled()
364
365 items = check_pipeline.getAllItems()
366 self.assertEqual(items[0].change.number, '1')
367 self.assertEqual(items[0].change.patchset, '1')
368 self.assertTrue(items[0].live)
369
370 in_repo_conf = textwrap.dedent(
371 """
372 - job:
Tobias Henkel0ce7ec62017-07-21 22:50:17 +0200373 name: project-test1
374
375 - job:
Tobias Henkel0f714002017-06-30 23:30:52 +0200376 name: project-test2
377
378 - project:
379 name: org/project
380 check:
381 jobs:
382 - project-test1
383 - project-test2
384 """)
385 file_dict = {'.zuul.yaml': in_repo_conf,
386 'playbooks/project-test2.yaml': in_repo_playbook}
387
388 A.addPatchset(files=file_dict)
389 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(2))
390
391 self.waitUntilSettled()
392
393 items = check_pipeline.getAllItems()
394 self.assertEqual(items[0].change.number, '1')
395 self.assertEqual(items[0].change.patchset, '2')
396 self.assertTrue(items[0].live)
397
398 self.executor_server.hold_jobs_in_build = False
Tobias Henkel0ce7ec62017-07-21 22:50:17 +0200399 self.executor_server.release('project-test1')
400 self.waitUntilSettled()
Tobias Henkel0f714002017-06-30 23:30:52 +0200401 self.executor_server.release()
402 self.waitUntilSettled()
403
Tobias Henkel0ce7ec62017-07-21 22:50:17 +0200404 self.assertHistory([
405 dict(name='project-test2', result='ABORTED', changes='1,1'),
406 dict(name='project-test1', result='SUCCESS', changes='1,2'),
407 dict(name='project-test2', result='SUCCESS', changes='1,2')])
408
James E. Blairff555742017-02-19 11:34:27 -0800409 def test_in_repo_branch(self):
410 in_repo_conf = textwrap.dedent(
411 """
412 - job:
Tobias Henkelf02cf512017-07-21 22:55:34 +0200413 name: project-test1
414
415 - job:
James E. Blairff555742017-02-19 11:34:27 -0800416 name: project-test2
417
418 - project:
419 name: org/project
420 tenant-one-gate:
421 jobs:
422 - project-test2
423 """)
424
425 in_repo_playbook = textwrap.dedent(
426 """
427 - hosts: all
428 tasks: []
429 """)
430
431 file_dict = {'.zuul.yaml': in_repo_conf,
432 'playbooks/project-test2.yaml': in_repo_playbook}
433 self.create_branch('org/project', 'stable')
James E. Blair72facdc2017-08-17 10:29:12 -0700434 self.fake_gerrit.addEvent(
435 self.fake_gerrit.getFakeBranchCreatedEvent(
436 'org/project', 'stable'))
James E. Blair6069f2b2017-09-26 16:34:11 -0700437 self.waitUntilSettled()
James E. Blairff555742017-02-19 11:34:27 -0800438 A = self.fake_gerrit.addFakeChange('org/project', 'stable', 'A',
439 files=file_dict)
Tobias Henkelbf24fd12017-07-27 06:13:07 +0200440 A.addApproval('Code-Review', 2)
441 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
James E. Blairff555742017-02-19 11:34:27 -0800442 self.waitUntilSettled()
443 self.assertEqual(A.data['status'], 'MERGED')
444 self.assertEqual(A.reported, 2,
445 "A should report start and success")
446 self.assertIn('tenant-one-gate', A.messages[1],
447 "A should transit tenant-one gate")
448 self.assertHistory([
449 dict(name='project-test2', result='SUCCESS', changes='1,1')])
450 self.fake_gerrit.addEvent(A.getChangeMergedEvent())
James E. Blair7bbd7a32017-03-06 11:36:13 -0800451 self.waitUntilSettled()
James E. Blairff555742017-02-19 11:34:27 -0800452
453 # The config change should not affect master.
454 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
Tobias Henkelbf24fd12017-07-27 06:13:07 +0200455 B.addApproval('Code-Review', 2)
456 self.fake_gerrit.addEvent(B.addApproval('Approved', 1))
James E. Blairff555742017-02-19 11:34:27 -0800457 self.waitUntilSettled()
458 self.assertHistory([
459 dict(name='project-test2', result='SUCCESS', changes='1,1'),
460 dict(name='project-test1', result='SUCCESS', changes='2,1')])
461
462 # The config change should be live for further changes on
463 # stable.
464 C = self.fake_gerrit.addFakeChange('org/project', 'stable', 'C')
Tobias Henkelbf24fd12017-07-27 06:13:07 +0200465 C.addApproval('Code-Review', 2)
466 self.fake_gerrit.addEvent(C.addApproval('Approved', 1))
James E. Blairff555742017-02-19 11:34:27 -0800467 self.waitUntilSettled()
468 self.assertHistory([
469 dict(name='project-test2', result='SUCCESS', changes='1,1'),
470 dict(name='project-test1', result='SUCCESS', changes='2,1'),
471 dict(name='project-test2', result='SUCCESS', changes='3,1')])
472
James E. Blaira5a12492017-05-03 11:40:48 -0700473 def test_crd_dynamic_config_branch(self):
474 # Test that we can create a job in one repo and be able to use
475 # it from a different branch on a different repo.
476
477 self.create_branch('org/project1', 'stable')
James E. Blair72facdc2017-08-17 10:29:12 -0700478 self.fake_gerrit.addEvent(
479 self.fake_gerrit.getFakeBranchCreatedEvent(
480 'org/project1', 'stable'))
James E. Blaira5a12492017-05-03 11:40:48 -0700481
482 in_repo_conf = textwrap.dedent(
483 """
484 - job:
Tobias Henkelf02cf512017-07-21 22:55:34 +0200485 name: project-test1
486
487 - job:
James E. Blaira5a12492017-05-03 11:40:48 -0700488 name: project-test2
489
490 - project:
491 name: org/project
492 check:
493 jobs:
494 - project-test2
495 """)
496
497 in_repo_playbook = textwrap.dedent(
498 """
499 - hosts: all
500 tasks: []
501 """)
502
503 file_dict = {'.zuul.yaml': in_repo_conf,
504 'playbooks/project-test2.yaml': in_repo_playbook}
505 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
506 files=file_dict)
507
508 second_repo_conf = textwrap.dedent(
509 """
510 - project:
511 name: org/project1
512 check:
513 jobs:
514 - project-test2
515 """)
516
517 second_file_dict = {'.zuul.yaml': second_repo_conf}
518 B = self.fake_gerrit.addFakeChange('org/project1', 'stable', 'B',
519 files=second_file_dict)
520 B.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
521 B.subject, A.data['id'])
522
523 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
524 self.waitUntilSettled()
525 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
526 self.waitUntilSettled()
527
528 self.assertEqual(A.reported, 1, "A should report")
529 self.assertHistory([
530 dict(name='project-test2', result='SUCCESS', changes='1,1'),
531 dict(name='project-test2', result='SUCCESS', changes='1,1 2,1'),
532 ])
533
James E. Blair97043882017-09-06 15:51:17 -0700534 def test_yaml_list_error(self):
535 in_repo_conf = textwrap.dedent(
536 """
537 job: foo
538 """)
539
540 file_dict = {'.zuul.yaml': in_repo_conf}
541 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
542 files=file_dict)
543 A.addApproval('Code-Review', 2)
544 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
545 self.waitUntilSettled()
546
547 self.assertEqual(A.data['status'], 'NEW')
548 self.assertEqual(A.reported, 1,
549 "A should report failure")
550 self.assertIn('not a list', A.messages[0],
551 "A should have a syntax error reported")
552
553 def test_yaml_dict_error(self):
554 in_repo_conf = textwrap.dedent(
555 """
556 - job
557 """)
558
559 file_dict = {'.zuul.yaml': in_repo_conf}
560 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
561 files=file_dict)
562 A.addApproval('Code-Review', 2)
563 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
564 self.waitUntilSettled()
565
566 self.assertEqual(A.data['status'], 'NEW')
567 self.assertEqual(A.reported, 1,
568 "A should report failure")
569 self.assertIn('not a dictionary', A.messages[0],
570 "A should have a syntax error reported")
571
572 def test_yaml_key_error(self):
573 in_repo_conf = textwrap.dedent(
574 """
575 - job:
576 name: project-test2
577 """)
578
579 file_dict = {'.zuul.yaml': in_repo_conf}
580 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
581 files=file_dict)
582 A.addApproval('Code-Review', 2)
583 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
584 self.waitUntilSettled()
585
586 self.assertEqual(A.data['status'], 'NEW')
587 self.assertEqual(A.reported, 1,
588 "A should report failure")
589 self.assertIn('has more than one key', A.messages[0],
590 "A should have a syntax error reported")
591
592 def test_yaml_unknown_error(self):
593 in_repo_conf = textwrap.dedent(
594 """
595 - foobar:
596 foo: bar
597 """)
598
599 file_dict = {'.zuul.yaml': in_repo_conf}
600 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
601 files=file_dict)
602 A.addApproval('Code-Review', 2)
603 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
604 self.waitUntilSettled()
605
606 self.assertEqual(A.data['status'], 'NEW')
607 self.assertEqual(A.reported, 1,
608 "A should report failure")
609 self.assertIn('not recognized', A.messages[0],
610 "A should have a syntax error reported")
611
James E. Blair149b69c2017-03-02 10:48:16 -0800612 def test_untrusted_syntax_error(self):
James E. Blaire53250c2017-03-01 14:34:36 -0800613 in_repo_conf = textwrap.dedent(
614 """
615 - job:
616 name: project-test2
617 foo: error
618 """)
619
620 file_dict = {'.zuul.yaml': in_repo_conf}
621 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
622 files=file_dict)
Tobias Henkelbf24fd12017-07-27 06:13:07 +0200623 A.addApproval('Code-Review', 2)
624 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
James E. Blaire53250c2017-03-01 14:34:36 -0800625 self.waitUntilSettled()
626
627 self.assertEqual(A.data['status'], 'NEW')
Tobias Henkel9842bd72017-05-16 13:40:03 +0200628 self.assertEqual(A.reported, 1,
629 "A should report failure")
630 self.assertIn('syntax error', A.messages[0],
James E. Blaire53250c2017-03-01 14:34:36 -0800631 "A should have a syntax error reported")
632
James E. Blair149b69c2017-03-02 10:48:16 -0800633 def test_trusted_syntax_error(self):
634 in_repo_conf = textwrap.dedent(
635 """
636 - job:
637 name: project-test2
638 foo: error
639 """)
640
641 file_dict = {'zuul.yaml': in_repo_conf}
642 A = self.fake_gerrit.addFakeChange('common-config', 'master', 'A',
643 files=file_dict)
Tobias Henkelbf24fd12017-07-27 06:13:07 +0200644 A.addApproval('Code-Review', 2)
645 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
James E. Blair149b69c2017-03-02 10:48:16 -0800646 self.waitUntilSettled()
647
648 self.assertEqual(A.data['status'], 'NEW')
Tobias Henkel9842bd72017-05-16 13:40:03 +0200649 self.assertEqual(A.reported, 1,
650 "A should report failure")
651 self.assertIn('syntax error', A.messages[0],
James E. Blair149b69c2017-03-02 10:48:16 -0800652 "A should have a syntax error reported")
653
James E. Blair6f140c72017-03-03 10:32:07 -0800654 def test_untrusted_yaml_error(self):
655 in_repo_conf = textwrap.dedent(
656 """
657 - job:
658 foo: error
659 """)
660
661 file_dict = {'.zuul.yaml': in_repo_conf}
662 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
663 files=file_dict)
Tobias Henkelbf24fd12017-07-27 06:13:07 +0200664 A.addApproval('Code-Review', 2)
665 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
James E. Blair6f140c72017-03-03 10:32:07 -0800666 self.waitUntilSettled()
667
668 self.assertEqual(A.data['status'], 'NEW')
Tobias Henkel9842bd72017-05-16 13:40:03 +0200669 self.assertEqual(A.reported, 1,
670 "A should report failure")
671 self.assertIn('syntax error', A.messages[0],
James E. Blair6f140c72017-03-03 10:32:07 -0800672 "A should have a syntax error reported")
673
James E. Blairdb04e6a2017-05-03 14:49:36 -0700674 def test_untrusted_shadow_error(self):
675 in_repo_conf = textwrap.dedent(
676 """
677 - job:
678 name: common-config-test
679 """)
680
681 file_dict = {'.zuul.yaml': in_repo_conf}
682 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
683 files=file_dict)
Tobias Henkelbf24fd12017-07-27 06:13:07 +0200684 A.addApproval('Code-Review', 2)
685 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
James E. Blairdb04e6a2017-05-03 14:49:36 -0700686 self.waitUntilSettled()
687
688 self.assertEqual(A.data['status'], 'NEW')
Tobias Henkel9842bd72017-05-16 13:40:03 +0200689 self.assertEqual(A.reported, 1,
690 "A should report failure")
691 self.assertIn('not permitted to shadow', A.messages[0],
James E. Blairdb04e6a2017-05-03 14:49:36 -0700692 "A should have a syntax error reported")
693
James E. Blaird5656ad2017-06-02 14:29:41 -0700694 def test_untrusted_pipeline_error(self):
695 in_repo_conf = textwrap.dedent(
696 """
697 - pipeline:
698 name: test
699 """)
700
701 file_dict = {'.zuul.yaml': in_repo_conf}
702 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
703 files=file_dict)
Tobias Henkelbf24fd12017-07-27 06:13:07 +0200704 A.addApproval('Code-Review', 2)
705 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
James E. Blaird5656ad2017-06-02 14:29:41 -0700706 self.waitUntilSettled()
707
708 self.assertEqual(A.data['status'], 'NEW')
709 self.assertEqual(A.reported, 1,
710 "A should report failure")
711 self.assertIn('Pipelines may not be defined', A.messages[0],
712 "A should have a syntax error reported")
713
714 def test_untrusted_project_error(self):
715 in_repo_conf = textwrap.dedent(
716 """
717 - project:
718 name: org/project1
719 """)
720
721 file_dict = {'.zuul.yaml': in_repo_conf}
722 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
723 files=file_dict)
Tobias Henkelbf24fd12017-07-27 06:13:07 +0200724 A.addApproval('Code-Review', 2)
725 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
James E. Blaird5656ad2017-06-02 14:29:41 -0700726 self.waitUntilSettled()
727
728 self.assertEqual(A.data['status'], 'NEW')
729 self.assertEqual(A.reported, 1,
730 "A should report failure")
731 self.assertIn('the only project definition permitted', A.messages[0],
732 "A should have a syntax error reported")
733
James E. Blairf03173b2017-10-10 10:46:43 -0700734 def test_untrusted_depends_on_trusted(self):
735 with open(os.path.join(FIXTURE_DIR,
736 'config/in-repo/git/',
737 'common-config/zuul.yaml')) as f:
738 common_config = f.read()
739
740 common_config += textwrap.dedent(
741 """
742 - job:
743 name: project-test9
744 """)
745
746 file_dict = {'zuul.yaml': common_config}
747 A = self.fake_gerrit.addFakeChange('common-config', 'master', 'A',
748 files=file_dict)
749 in_repo_conf = textwrap.dedent(
750 """
751 - job:
752 name: project-test1
753 - project:
754 name: org/project
755 check:
756 jobs:
757 - project-test9
758 """)
759
760 file_dict = {'zuul.yaml': in_repo_conf}
761 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B',
762 files=file_dict)
763 B.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
764 B.subject, A.data['id'])
765 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
766 self.waitUntilSettled()
767
768 self.assertEqual(B.data['status'], 'NEW')
769 self.assertEqual(B.reported, 1,
770 "B should report failure")
771 self.assertIn('depends on a change to a config project',
772 B.messages[0],
773 "A should have a syntax error reported")
774
James E. Blaire64b0e42017-06-08 11:23:34 -0700775 def test_duplicate_node_error(self):
776 in_repo_conf = textwrap.dedent(
777 """
778 - nodeset:
779 name: duplicate
780 nodes:
781 - name: compute
James E. Blair16d96a02017-06-08 11:32:56 -0700782 label: foo
James E. Blaire64b0e42017-06-08 11:23:34 -0700783 - name: compute
James E. Blair16d96a02017-06-08 11:32:56 -0700784 label: foo
James E. Blaire64b0e42017-06-08 11:23:34 -0700785 """)
786
787 file_dict = {'.zuul.yaml': in_repo_conf}
788 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
789 files=file_dict)
Tobias Henkelbf24fd12017-07-27 06:13:07 +0200790 A.addApproval('Code-Review', 2)
791 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
James E. Blaire64b0e42017-06-08 11:23:34 -0700792 self.waitUntilSettled()
793
794 self.assertEqual(A.data['status'], 'NEW')
795 self.assertEqual(A.reported, 1,
796 "A should report failure")
797 self.assertIn('appears multiple times', A.messages[0],
798 "A should have a syntax error reported")
799
800 def test_duplicate_group_error(self):
801 in_repo_conf = textwrap.dedent(
802 """
803 - nodeset:
804 name: duplicate
805 nodes:
806 - name: compute
James E. Blair16d96a02017-06-08 11:32:56 -0700807 label: foo
James E. Blaire64b0e42017-06-08 11:23:34 -0700808 groups:
809 - name: group
810 nodes: compute
811 - name: group
812 nodes: compute
813 """)
814
815 file_dict = {'.zuul.yaml': in_repo_conf}
816 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
817 files=file_dict)
Tobias Henkelbf24fd12017-07-27 06:13:07 +0200818 A.addApproval('Code-Review', 2)
819 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
James E. Blaire64b0e42017-06-08 11:23:34 -0700820 self.waitUntilSettled()
821
822 self.assertEqual(A.data['status'], 'NEW')
823 self.assertEqual(A.reported, 1,
824 "A should report failure")
825 self.assertIn('appears multiple times', A.messages[0],
826 "A should have a syntax error reported")
827
James E. Blair4ae399f2017-09-20 17:15:09 -0700828 def test_secret_not_found_error(self):
829 in_repo_conf = textwrap.dedent(
830 """
831 - job:
832 name: test
833 secrets: does-not-exist
834 """)
835
836 file_dict = {'.zuul.yaml': in_repo_conf}
837 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
838 files=file_dict)
839 A.addApproval('Code-Review', 2)
840 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
841 self.waitUntilSettled()
842
843 self.assertEqual(A.data['status'], 'NEW')
844 self.assertEqual(A.reported, 1,
845 "A should report failure")
846 self.assertIn('secret "does-not-exist" was not found', A.messages[0],
847 "A should have a syntax error reported")
848
849 def test_nodeset_not_found_error(self):
850 in_repo_conf = textwrap.dedent(
851 """
852 - job:
853 name: test
854 nodeset: does-not-exist
855 """)
856
857 file_dict = {'.zuul.yaml': in_repo_conf}
858 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
859 files=file_dict)
860 A.addApproval('Code-Review', 2)
861 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
862 self.waitUntilSettled()
863
864 self.assertEqual(A.data['status'], 'NEW')
865 self.assertEqual(A.reported, 1,
866 "A should report failure")
867 self.assertIn('nodeset "does-not-exist" was not found', A.messages[0],
868 "A should have a syntax error reported")
869
James E. Blair89e25eb2017-09-26 09:11:31 -0700870 def test_template_not_found_error(self):
871 in_repo_conf = textwrap.dedent(
872 """
873 - job:
874 name: project-test1
875 - project:
876 name: org/project
877 templates:
878 - does-not-exist
879 """)
880
881 file_dict = {'.zuul.yaml': in_repo_conf}
882 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
883 files=file_dict)
884 A.addApproval('Code-Review', 2)
885 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
886 self.waitUntilSettled()
887
888 self.assertEqual(A.data['status'], 'NEW')
889 self.assertEqual(A.reported, 1,
890 "A should report failure")
891 self.assertIn('project template "does-not-exist" was not found',
892 A.messages[0],
893 "A should have a syntax error reported")
894
Monty Taylor8be3c0c2017-10-06 10:37:37 -0500895 def test_job_list_in_project_template_not_dict_error(self):
896 in_repo_conf = textwrap.dedent(
897 """
898 - job:
899 name: project-test1
900 - project-template:
901 name: some-jobs
902 check:
903 jobs:
904 - project-test1:
905 - required-projects:
906 org/project2
907 """)
908
909 file_dict = {'.zuul.yaml': in_repo_conf}
910 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
911 files=file_dict)
912 A.addApproval('Code-Review', 2)
913 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
914 self.waitUntilSettled()
915
916 self.assertEqual(A.data['status'], 'NEW')
917 self.assertEqual(A.reported, 1,
918 "A should report failure")
919 self.assertIn('expected str for dictionary value',
920 A.messages[0], "A should have a syntax error reported")
921
922 def test_job_list_in_project_not_dict_error(self):
923 in_repo_conf = textwrap.dedent(
924 """
925 - job:
926 name: project-test1
927 - project:
928 name: org/project1
929 check:
930 jobs:
931 - project-test1:
932 - required-projects:
933 org/project2
934 """)
935
936 file_dict = {'.zuul.yaml': in_repo_conf}
937 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
938 files=file_dict)
939 A.addApproval('Code-Review', 2)
940 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
941 self.waitUntilSettled()
942
943 self.assertEqual(A.data['status'], 'NEW')
944 self.assertEqual(A.reported, 1,
945 "A should report failure")
946 self.assertIn('expected str for dictionary value',
947 A.messages[0], "A should have a syntax error reported")
948
James E. Blair1235f142017-10-07 09:11:43 -0700949 def test_project_template(self):
950 # Tests that a project template is not modified when used, and
951 # can therefore be used in subsequent reconfigurations.
952 in_repo_conf = textwrap.dedent(
953 """
954 - job:
955 name: project-test1
956 - project-template:
957 name: some-jobs
958 tenant-one-gate:
959 jobs:
960 - project-test1:
961 required-projects:
962 - org/project1
963 - project:
964 name: org/project
965 templates:
966 - some-jobs
967 """)
968
969 file_dict = {'.zuul.yaml': in_repo_conf}
970 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
971 files=file_dict)
972 A.addApproval('Code-Review', 2)
973 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
974 self.waitUntilSettled()
975 self.assertEqual(A.data['status'], 'MERGED')
976 self.fake_gerrit.addEvent(A.getChangeMergedEvent())
977 self.waitUntilSettled()
978 in_repo_conf = textwrap.dedent(
979 """
980 - project:
981 name: org/project1
982 templates:
983 - some-jobs
984 """)
985 file_dict = {'.zuul.yaml': in_repo_conf}
986 B = self.fake_gerrit.addFakeChange('org/project1', 'master', 'B',
987 files=file_dict)
988 B.addApproval('Code-Review', 2)
989 self.fake_gerrit.addEvent(B.addApproval('Approved', 1))
990 self.waitUntilSettled()
991 self.assertEqual(B.data['status'], 'MERGED')
992
James E. Blairbccdfcf2017-10-07 13:37:26 -0700993 def test_job_remove_add(self):
994 # Tests that a job can be removed from one repo and added in another.
995 # First, remove the current config for project1 since it
996 # references the job we want to remove.
997 file_dict = {'.zuul.yaml': None}
998 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A',
999 files=file_dict)
1000 A.setMerged()
1001 self.fake_gerrit.addEvent(A.getChangeMergedEvent())
1002 self.waitUntilSettled()
1003 # Then propose a change to delete the job from one repo...
1004 file_dict = {'.zuul.yaml': None}
1005 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B',
1006 files=file_dict)
1007 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
1008 self.waitUntilSettled()
1009 # ...and a second that depends on it that adds it to another repo.
1010 in_repo_conf = textwrap.dedent(
1011 """
1012 - job:
1013 name: project-test1
1014
1015 - project:
1016 name: org/project1
1017 check:
1018 jobs:
1019 - project-test1
1020 """)
1021 in_repo_playbook = textwrap.dedent(
1022 """
1023 - hosts: all
1024 tasks: []
1025 """)
1026 file_dict = {'.zuul.yaml': in_repo_conf,
1027 'playbooks/project-test1.yaml': in_repo_playbook}
1028 C = self.fake_gerrit.addFakeChange('org/project1', 'master', 'C',
1029 files=file_dict,
1030 parent='refs/changes/1/1/1')
1031 C.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
1032 C.subject, B.data['id'])
1033 self.fake_gerrit.addEvent(C.getPatchsetCreatedEvent(1))
1034 self.waitUntilSettled()
1035 self.assertHistory([
1036 dict(name='project-test1', result='SUCCESS', changes='2,1 3,1'),
1037 ], ordered=False)
1038
James E. Blair09f9ffe2017-07-11 15:30:25 -07001039 def test_multi_repo(self):
1040 downstream_repo_conf = textwrap.dedent(
1041 """
1042 - project:
1043 name: org/project1
1044 tenant-one-gate:
1045 jobs:
1046 - project-test1
1047
1048 - job:
1049 name: project1-test1
1050 parent: project-test1
1051 """)
1052
1053 file_dict = {'.zuul.yaml': downstream_repo_conf}
1054 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A',
1055 files=file_dict)
Tobias Henkelbf24fd12017-07-27 06:13:07 +02001056 A.addApproval('Code-Review', 2)
1057 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
James E. Blair09f9ffe2017-07-11 15:30:25 -07001058 self.waitUntilSettled()
1059
1060 self.assertEqual(A.data['status'], 'MERGED')
1061 self.fake_gerrit.addEvent(A.getChangeMergedEvent())
1062 self.waitUntilSettled()
1063
1064 upstream_repo_conf = textwrap.dedent(
1065 """
1066 - job:
1067 name: project-test1
1068
1069 - job:
1070 name: project-test2
1071
1072 - project:
1073 name: org/project
1074 tenant-one-gate:
1075 jobs:
1076 - project-test1
1077 """)
1078
1079 file_dict = {'.zuul.yaml': upstream_repo_conf}
1080 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B',
1081 files=file_dict)
Tobias Henkelbf24fd12017-07-27 06:13:07 +02001082 B.addApproval('Code-Review', 2)
1083 self.fake_gerrit.addEvent(B.addApproval('Approved', 1))
James E. Blair09f9ffe2017-07-11 15:30:25 -07001084 self.waitUntilSettled()
1085
1086 self.assertEqual(B.data['status'], 'MERGED')
1087 self.fake_gerrit.addEvent(B.getChangeMergedEvent())
1088 self.waitUntilSettled()
1089
1090 tenant = self.sched.abide.tenants.get('tenant-one')
1091 # Ensure the latest change is reflected in the config; if it
1092 # isn't this will raise an exception.
1093 tenant.layout.getJob('project-test2')
1094
James E. Blair332636e2017-09-05 10:14:35 -07001095 def test_pipeline_error(self):
1096 with open(os.path.join(FIXTURE_DIR,
1097 'config/in-repo/git/',
1098 'common-config/zuul.yaml')) as f:
1099 base_common_config = f.read()
1100
1101 in_repo_conf_A = textwrap.dedent(
1102 """
1103 - pipeline:
1104 name: periodic
1105 foo: error
1106 """)
1107
1108 file_dict = {'zuul.yaml': None,
1109 'zuul.d/main.yaml': base_common_config,
1110 'zuul.d/test1.yaml': in_repo_conf_A}
1111 A = self.fake_gerrit.addFakeChange('common-config', 'master', 'A',
1112 files=file_dict)
1113 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
1114 self.waitUntilSettled()
1115 self.assertEqual(A.reported, 1,
1116 "A should report failure")
1117 self.assertIn('syntax error',
1118 A.messages[0],
1119 "A should have an error reported")
1120
1121 def test_change_series_error(self):
1122 with open(os.path.join(FIXTURE_DIR,
1123 'config/in-repo/git/',
1124 'common-config/zuul.yaml')) as f:
1125 base_common_config = f.read()
1126
1127 in_repo_conf_A = textwrap.dedent(
1128 """
1129 - pipeline:
1130 name: periodic
1131 foo: error
1132 """)
1133
1134 file_dict = {'zuul.yaml': None,
1135 'zuul.d/main.yaml': base_common_config,
1136 'zuul.d/test1.yaml': in_repo_conf_A}
1137 A = self.fake_gerrit.addFakeChange('common-config', 'master', 'A',
1138 files=file_dict)
1139
1140 in_repo_conf_B = textwrap.dedent(
1141 """
1142 - job:
1143 name: project-test2
1144 foo: error
1145 """)
1146
1147 file_dict = {'zuul.yaml': None,
1148 'zuul.d/main.yaml': base_common_config,
1149 'zuul.d/test1.yaml': in_repo_conf_A,
1150 'zuul.d/test2.yaml': in_repo_conf_B}
1151 B = self.fake_gerrit.addFakeChange('common-config', 'master', 'B',
1152 files=file_dict)
1153 B.setDependsOn(A, 1)
1154 C = self.fake_gerrit.addFakeChange('common-config', 'master', 'C')
1155 C.setDependsOn(B, 1)
1156 self.fake_gerrit.addEvent(C.getPatchsetCreatedEvent(1))
1157 self.waitUntilSettled()
1158
1159 self.assertEqual(C.reported, 1,
1160 "C should report failure")
1161 self.assertIn('depends on a change that failed to merge',
1162 C.messages[0],
1163 "C should have an error reported")
1164
James E. Blairc73c73a2017-01-20 15:15:15 -08001165
James E. Blairc9455002017-09-06 09:22:19 -07001166class TestInRepoJoin(ZuulTestCase):
1167 # In this config, org/project is not a member of any pipelines, so
1168 # that we may test the changes that cause it to join them.
1169
1170 tenant_config_file = 'config/in-repo-join/main.yaml'
1171
1172 def test_dynamic_dependent_pipeline(self):
1173 # Test dynamically adding a project to a
1174 # dependent pipeline for the first time
1175 self.executor_server.hold_jobs_in_build = True
1176
1177 tenant = self.sched.abide.tenants.get('tenant-one')
1178 gate_pipeline = tenant.layout.pipelines['gate']
1179
1180 in_repo_conf = textwrap.dedent(
1181 """
1182 - job:
1183 name: project-test1
1184
1185 - job:
1186 name: project-test2
1187
1188 - project:
1189 name: org/project
1190 gate:
1191 jobs:
1192 - project-test2
1193 """)
1194
1195 in_repo_playbook = textwrap.dedent(
1196 """
1197 - hosts: all
1198 tasks: []
1199 """)
1200
1201 file_dict = {'.zuul.yaml': in_repo_conf,
1202 'playbooks/project-test2.yaml': in_repo_playbook}
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 items = gate_pipeline.getAllItems()
1210 self.assertEqual(items[0].change.number, '1')
1211 self.assertEqual(items[0].change.patchset, '1')
1212 self.assertTrue(items[0].live)
1213
1214 self.executor_server.hold_jobs_in_build = False
1215 self.executor_server.release()
1216 self.waitUntilSettled()
1217
1218 # Make sure the dynamic queue got cleaned up
1219 self.assertEqual(gate_pipeline.queues, [])
1220
1221 def test_dynamic_dependent_pipeline_failure(self):
1222 # Test that a change behind a failing change adding a project
1223 # to a dependent pipeline is dequeued.
1224 self.executor_server.hold_jobs_in_build = True
1225
1226 in_repo_conf = textwrap.dedent(
1227 """
1228 - job:
1229 name: project-test1
1230
1231 - project:
1232 name: org/project
1233 gate:
1234 jobs:
1235 - project-test1
1236 """)
1237
1238 file_dict = {'.zuul.yaml': in_repo_conf}
1239 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
1240 files=file_dict)
1241 self.executor_server.failJob('project-test1', A)
1242 A.addApproval('Code-Review', 2)
1243 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
1244 self.waitUntilSettled()
1245
1246 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
1247 B.addApproval('Code-Review', 2)
1248 self.fake_gerrit.addEvent(B.addApproval('Approved', 1))
1249 self.waitUntilSettled()
1250
James E. Blair3490c5d2017-09-07 08:33:23 -07001251 self.orderedRelease()
James E. Blairc9455002017-09-06 09:22:19 -07001252 self.waitUntilSettled()
1253 self.assertEqual(A.reported, 2,
1254 "A should report start and failure")
1255 self.assertEqual(A.data['status'], 'NEW')
1256 self.assertEqual(B.reported, 1,
1257 "B should report start")
1258 self.assertHistory([
1259 dict(name='project-test1', result='FAILURE', changes='1,1'),
James E. Blair3490c5d2017-09-07 08:33:23 -07001260 dict(name='project-test1', result='ABORTED', changes='1,1 2,1'),
James E. Blairc9455002017-09-06 09:22:19 -07001261 ], ordered=False)
1262
James E. Blair0af198f2017-09-06 09:52:35 -07001263 def test_dynamic_dependent_pipeline_absent(self):
1264 # Test that a series of dependent changes don't report merge
1265 # failures to a pipeline they aren't in.
1266 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1267 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
1268 B.setDependsOn(A, 1)
1269
1270 A.addApproval('Code-Review', 2)
1271 A.addApproval('Approved', 1)
1272 B.addApproval('Code-Review', 2)
1273 self.fake_gerrit.addEvent(B.addApproval('Approved', 1))
1274 self.waitUntilSettled()
1275 self.assertEqual(A.reported, 0,
1276 "A should not report")
1277 self.assertEqual(A.data['status'], 'NEW')
1278 self.assertEqual(B.reported, 0,
1279 "B should not report")
1280 self.assertEqual(B.data['status'], 'NEW')
1281 self.assertHistory([])
1282
James E. Blairc9455002017-09-06 09:22:19 -07001283
James E. Blairc73c73a2017-01-20 15:15:15 -08001284class TestAnsible(AnsibleZuulTestCase):
1285 # A temporary class to hold new tests while others are disabled
1286
1287 tenant_config_file = 'config/ansible/main.yaml'
1288
1289 def test_playbook(self):
Jamie Lennox7655b552017-03-17 12:33:38 +11001290 # Keep the jobdir around so we can inspect contents if an
1291 # assert fails.
1292 self.executor_server.keep_jobdir = True
1293 # Output extra ansible info so we might see errors.
1294 self.executor_server.verbose = True
1295 # Add a site variables file, used by check-vars
1296 path = os.path.join(FIXTURE_DIR, 'config', 'ansible',
1297 'variables.yaml')
1298 self.config.set('executor', 'variables', path)
James E. Blairc73c73a2017-01-20 15:15:15 -08001299 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1300 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
1301 self.waitUntilSettled()
Tobias Henkel077f2f32017-05-30 20:16:46 +02001302 build_timeout = self.getJobFromHistory('timeout')
Jamie Lennox7655b552017-03-17 12:33:38 +11001303 with self.jobLog(build_timeout):
1304 self.assertEqual(build_timeout.result, 'TIMED_OUT')
Tobias Henkel077f2f32017-05-30 20:16:46 +02001305 build_faillocal = self.getJobFromHistory('faillocal')
Jamie Lennox7655b552017-03-17 12:33:38 +11001306 with self.jobLog(build_faillocal):
1307 self.assertEqual(build_faillocal.result, 'FAILURE')
Tobias Henkel077f2f32017-05-30 20:16:46 +02001308 build_failpost = self.getJobFromHistory('failpost')
Jamie Lennox7655b552017-03-17 12:33:38 +11001309 with self.jobLog(build_failpost):
1310 self.assertEqual(build_failpost.result, 'POST_FAILURE')
Tobias Henkel077f2f32017-05-30 20:16:46 +02001311 build_check_vars = self.getJobFromHistory('check-vars')
Jamie Lennox7655b552017-03-17 12:33:38 +11001312 with self.jobLog(build_check_vars):
1313 self.assertEqual(build_check_vars.result, 'SUCCESS')
Monty Tayloraff8b402017-08-16 18:40:41 -05001314 build_check_secret_names = self.getJobFromHistory('check-secret-names')
1315 with self.jobLog(build_check_secret_names):
1316 self.assertEqual(build_check_secret_names.result, 'SUCCESS')
Tobias Henkel077f2f32017-05-30 20:16:46 +02001317 build_hello = self.getJobFromHistory('hello-world')
Jamie Lennox7655b552017-03-17 12:33:38 +11001318 with self.jobLog(build_hello):
1319 self.assertEqual(build_hello.result, 'SUCCESS')
Tobias Henkel077f2f32017-05-30 20:16:46 +02001320 build_python27 = self.getJobFromHistory('python27')
Jamie Lennox7655b552017-03-17 12:33:38 +11001321 with self.jobLog(build_python27):
1322 self.assertEqual(build_python27.result, 'SUCCESS')
1323 flag_path = os.path.join(self.test_root,
1324 build_python27.uuid + '.flag')
1325 self.assertTrue(os.path.exists(flag_path))
1326 copied_path = os.path.join(self.test_root, build_python27.uuid +
1327 '.copied')
1328 self.assertTrue(os.path.exists(copied_path))
1329 failed_path = os.path.join(self.test_root, build_python27.uuid +
1330 '.failed')
1331 self.assertFalse(os.path.exists(failed_path))
1332 pre_flag_path = os.path.join(self.test_root, build_python27.uuid +
1333 '.pre.flag')
1334 self.assertTrue(os.path.exists(pre_flag_path))
1335 post_flag_path = os.path.join(self.test_root, build_python27.uuid +
1336 '.post.flag')
1337 self.assertTrue(os.path.exists(post_flag_path))
1338 bare_role_flag_path = os.path.join(self.test_root,
1339 build_python27.uuid +
1340 '.bare-role.flag')
1341 self.assertTrue(os.path.exists(bare_role_flag_path))
1342 secrets_path = os.path.join(self.test_root,
1343 build_python27.uuid + '.secrets')
1344 with open(secrets_path) as f:
1345 self.assertEqual(f.read(), "test-username test-password")
James E. Blairb9c0d772017-03-03 14:34:49 -08001346
Jamie Lennox7655b552017-03-17 12:33:38 +11001347 msg = A.messages[0]
1348 success = "{} https://success.example.com/zuul-logs/{}"
1349 fail = "{} https://failure.example.com/zuul-logs/{}"
1350 self.assertIn(success.format("python27", build_python27.uuid), msg)
1351 self.assertIn(fail.format("faillocal", build_faillocal.uuid), msg)
1352 self.assertIn(success.format("check-vars",
1353 build_check_vars.uuid), msg)
1354 self.assertIn(success.format("hello-world", build_hello.uuid), msg)
1355 self.assertIn(fail.format("timeout", build_timeout.uuid), msg)
1356 self.assertIn(fail.format("failpost", build_failpost.uuid), msg)
Tobias Henkel077f2f32017-05-30 20:16:46 +02001357
James E. Blairabbaa6f2017-04-06 16:11:44 -07001358 def _add_job(self, job_name):
1359 conf = textwrap.dedent(
1360 """
1361 - job:
1362 name: %s
1363
1364 - project:
1365 name: org/plugin-project
1366 check:
1367 jobs:
1368 - %s
1369 """ % (job_name, job_name))
1370
1371 file_dict = {'.zuul.yaml': conf}
1372 A = self.fake_gerrit.addFakeChange('org/plugin-project', 'master', 'A',
1373 files=file_dict)
1374 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
1375 self.waitUntilSettled()
1376
1377 def test_plugins(self):
1378 # Keep the jobdir around so we can inspect contents if an
1379 # assert fails.
1380 self.executor_server.keep_jobdir = True
1381 # Output extra ansible info so we might see errors.
1382 self.executor_server.verbose = True
1383
1384 count = 0
1385 plugin_tests = [
1386 ('passwd', 'FAILURE'),
1387 ('cartesian', 'SUCCESS'),
1388 ('consul_kv', 'FAILURE'),
1389 ('credstash', 'FAILURE'),
1390 ('csvfile_good', 'SUCCESS'),
1391 ('csvfile_bad', 'FAILURE'),
Monty Taylor93ad2212017-08-02 14:59:50 -05001392 ('uri_bad_path', 'FAILURE'),
1393 ('uri_bad_scheme', 'FAILURE'),
Monty Taylor788a40e2017-08-02 16:14:05 -05001394 ('block_local_override', 'FAILURE'),
Monty Taylor8da768f2017-08-31 14:15:35 -05001395 ('file_local_good', 'SUCCESS'),
1396 ('file_local_bad', 'FAILURE'),
James E. Blairabbaa6f2017-04-06 16:11:44 -07001397 ]
1398 for job_name, result in plugin_tests:
1399 count += 1
1400 self._add_job(job_name)
1401
1402 job = self.getJobFromHistory(job_name)
1403 with self.jobLog(job):
1404 self.assertEqual(count, len(self.history))
1405 build = self.history[-1]
1406 self.assertEqual(build.result, result)
1407
1408 # TODOv3(jeblair): parse the ansible output and verify we're
1409 # getting the exception we expect.
1410
James E. Blairb9c0d772017-03-03 14:34:49 -08001411
James E. Blaira4d4eef2017-06-30 14:49:17 -07001412class TestPrePlaybooks(AnsibleZuulTestCase):
1413 # A temporary class to hold new tests while others are disabled
1414
1415 tenant_config_file = 'config/pre-playbook/main.yaml'
1416
1417 def test_pre_playbook_fail(self):
1418 # Test that we run the post playbooks (but not the actual
1419 # playbook) when a pre-playbook fails.
1420 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1421 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
1422 self.waitUntilSettled()
1423 build = self.getJobFromHistory('python27')
1424 self.assertIsNone(build.result)
1425 self.assertIn('RETRY_LIMIT', A.messages[0])
1426 flag_path = os.path.join(self.test_root, build.uuid +
1427 '.main.flag')
1428 self.assertFalse(os.path.exists(flag_path))
1429 pre_flag_path = os.path.join(self.test_root, build.uuid +
1430 '.pre.flag')
1431 self.assertFalse(os.path.exists(pre_flag_path))
1432 post_flag_path = os.path.join(self.test_root, build.uuid +
1433 '.post.flag')
James E. Blair21037782017-07-19 11:56:55 -07001434 self.assertTrue(os.path.exists(post_flag_path),
1435 "The file %s should exist" % post_flag_path)
James E. Blaira4d4eef2017-06-30 14:49:17 -07001436
1437
James E. Blairb9c0d772017-03-03 14:34:49 -08001438class TestBrokenConfig(ZuulTestCase):
1439 # Test that we get an appropriate syntax error if we start with a
1440 # broken config.
1441
1442 tenant_config_file = 'config/broken/main.yaml'
1443
1444 def setUp(self):
1445 with testtools.ExpectedException(
1446 zuul.configloader.ConfigurationSyntaxError,
1447 "\nZuul encountered a syntax error"):
1448 super(TestBrokenConfig, self).setUp()
1449
1450 def test_broken_config_on_startup(self):
1451 pass
Ricardo Carrillo Cruz22994f92016-12-02 11:41:58 +00001452
1453
1454class TestProjectKeys(ZuulTestCase):
1455 # Test that we can generate project keys
1456
1457 # Normally the test infrastructure copies a static key in place
1458 # for each project before starting tests. This saves time because
1459 # Zuul's automatic key-generation on startup can be slow. To make
1460 # sure we exercise that code, in this test we allow Zuul to create
1461 # keys for the project on startup.
1462 create_project_keys = True
Tobias Henkelabf973e2017-07-28 10:07:34 +02001463 config_file = 'zuul-connections-gerrit-and-github.conf'
Ricardo Carrillo Cruz22994f92016-12-02 11:41:58 +00001464 tenant_config_file = 'config/in-repo/main.yaml'
1465
1466 def test_key_generation(self):
1467 key_root = os.path.join(self.state_root, 'keys')
1468 private_key_file = os.path.join(key_root, 'gerrit/org/project.pem')
1469 # Make sure that a proper key was created on startup
1470 with open(private_key_file, "rb") as f:
James E. Blairbf1a4f22017-03-17 10:59:37 -07001471 private_key, public_key = \
1472 encryption.deserialize_rsa_keypair(f.read())
Ricardo Carrillo Cruz22994f92016-12-02 11:41:58 +00001473
1474 with open(os.path.join(FIXTURE_DIR, 'private.pem')) as i:
1475 fixture_private_key = i.read()
1476
1477 # Make sure that we didn't just end up with the static fixture
1478 # key
1479 self.assertNotEqual(fixture_private_key, private_key)
1480
1481 # Make sure it's the right length
1482 self.assertEqual(4096, private_key.key_size)
James E. Blairbce76932017-05-04 10:03:15 -07001483
1484
James E. Blairbb94dfa2017-07-11 07:45:19 -07001485class RoleTestCase(ZuulTestCase):
James E. Blair1b27f6a2017-07-14 14:09:07 -07001486 def _assertRolePath(self, build, playbook, content):
1487 path = os.path.join(self.test_root, build.uuid,
1488 'ansible', playbook, 'ansible.cfg')
1489 roles_paths = []
1490 with open(path) as f:
1491 for line in f:
1492 if line.startswith('roles_path'):
1493 roles_paths.append(line)
1494 print(roles_paths)
1495 if content:
1496 self.assertEqual(len(roles_paths), 1,
1497 "Should have one roles_path line in %s" %
1498 (playbook,))
1499 self.assertIn(content, roles_paths[0])
1500 else:
1501 self.assertEqual(len(roles_paths), 0,
1502 "Should have no roles_path line in %s" %
1503 (playbook,))
1504
James E. Blairbb94dfa2017-07-11 07:45:19 -07001505
1506class TestRoles(RoleTestCase):
1507 tenant_config_file = 'config/roles/main.yaml'
1508
James E. Blairbce76932017-05-04 10:03:15 -07001509 def test_role(self):
1510 # This exercises a proposed change to a role being checked out
1511 # and used.
1512 A = self.fake_gerrit.addFakeChange('bare-role', 'master', 'A')
1513 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1514 B.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
1515 B.subject, A.data['id'])
1516 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
1517 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
1518 self.waitUntilSettled()
1519 self.assertHistory([
1520 dict(name='project-test', result='SUCCESS', changes='1,1 2,1'),
1521 ])
James E. Blair6459db12017-06-29 14:57:20 -07001522
James E. Blair1b27f6a2017-07-14 14:09:07 -07001523 def test_role_inheritance(self):
1524 self.executor_server.hold_jobs_in_build = True
1525 conf = textwrap.dedent(
1526 """
1527 - job:
1528 name: parent
1529 roles:
1530 - zuul: bare-role
1531 pre-run: playbooks/parent-pre
1532 post-run: playbooks/parent-post
1533
1534 - job:
1535 name: project-test
1536 parent: parent
1537 roles:
1538 - zuul: org/project
1539
1540 - project:
1541 name: org/project
1542 check:
1543 jobs:
1544 - project-test
1545 """)
1546
1547 file_dict = {'.zuul.yaml': conf}
1548 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
1549 files=file_dict)
1550 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
1551 self.waitUntilSettled()
1552
1553 self.assertEqual(len(self.builds), 1)
1554 build = self.getBuildByName('project-test')
1555 self._assertRolePath(build, 'pre_playbook_0', 'role_0')
1556 self._assertRolePath(build, 'playbook_0', 'role_0')
1557 self._assertRolePath(build, 'playbook_0', 'role_1')
1558 self._assertRolePath(build, 'post_playbook_0', 'role_0')
1559
1560 self.executor_server.hold_jobs_in_build = False
1561 self.executor_server.release()
1562 self.waitUntilSettled()
1563
1564 self.assertHistory([
1565 dict(name='project-test', result='SUCCESS', changes='1,1'),
1566 ])
1567
James E. Blair6f699732017-07-18 14:19:11 -07001568 def test_role_error(self):
1569 conf = textwrap.dedent(
1570 """
1571 - job:
1572 name: project-test
1573 roles:
1574 - zuul: common-config
1575
1576 - project:
1577 name: org/project
1578 check:
1579 jobs:
1580 - project-test
1581 """)
1582
1583 file_dict = {'.zuul.yaml': conf}
1584 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
1585 files=file_dict)
1586 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
1587 self.waitUntilSettled()
1588 self.assertIn(
1589 '- project-test project-test : ERROR Unable to find role',
1590 A.messages[-1])
1591
James E. Blair6459db12017-06-29 14:57:20 -07001592
James E. Blairbb94dfa2017-07-11 07:45:19 -07001593class TestImplicitRoles(RoleTestCase):
1594 tenant_config_file = 'config/implicit-roles/main.yaml'
1595
1596 def test_missing_roles(self):
1597 # Test implicit and explicit roles for a project which does
1598 # not have roles. The implicit role should be silently
1599 # ignored since the project doesn't supply roles, but if a
1600 # user declares an explicit role, it should error.
1601 self.executor_server.hold_jobs_in_build = True
1602 A = self.fake_gerrit.addFakeChange('org/norole-project', 'master', 'A')
1603 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
1604 self.waitUntilSettled()
1605
1606 self.assertEqual(len(self.builds), 2)
1607 build = self.getBuildByName('implicit-role-fail')
1608 self._assertRolePath(build, 'playbook_0', None)
1609
1610 self.executor_server.hold_jobs_in_build = False
1611 self.executor_server.release()
1612 self.waitUntilSettled()
1613 # The retry_limit doesn't get recorded
1614 self.assertHistory([
1615 dict(name='implicit-role-fail', result='SUCCESS', changes='1,1'),
1616 ])
1617
1618 def test_roles(self):
1619 # Test implicit and explicit roles for a project which does
1620 # have roles. In both cases, we should end up with the role
1621 # in the path. In the explicit case, ensure we end up with
1622 # the name we specified.
1623 self.executor_server.hold_jobs_in_build = True
1624 A = self.fake_gerrit.addFakeChange('org/role-project', 'master', 'A')
1625 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
1626 self.waitUntilSettled()
1627
1628 self.assertEqual(len(self.builds), 2)
1629 build = self.getBuildByName('implicit-role-ok')
1630 self._assertRolePath(build, 'playbook_0', 'role_0')
1631
1632 build = self.getBuildByName('explicit-role-ok')
1633 self._assertRolePath(build, 'playbook_0', 'role_0')
1634
1635 self.executor_server.hold_jobs_in_build = False
1636 self.executor_server.release()
1637 self.waitUntilSettled()
1638 self.assertHistory([
1639 dict(name='implicit-role-ok', result='SUCCESS', changes='1,1'),
1640 dict(name='explicit-role-ok', result='SUCCESS', changes='1,1'),
1641 ], ordered=False)
1642
1643
James E. Blair6459db12017-06-29 14:57:20 -07001644class TestShadow(ZuulTestCase):
1645 tenant_config_file = 'config/shadow/main.yaml'
1646
1647 def test_shadow(self):
1648 # Test that a repo is allowed to shadow another's job definitions.
1649 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1650 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
1651 self.waitUntilSettled()
1652 self.assertHistory([
1653 dict(name='test1', result='SUCCESS', changes='1,1'),
1654 dict(name='test2', result='SUCCESS', changes='1,1'),
James E. Blairadafa6c2017-07-12 08:50:56 -07001655 ], ordered=False)
James E. Blair196f61a2017-06-30 15:42:29 -07001656
1657
1658class TestDataReturn(AnsibleZuulTestCase):
1659 tenant_config_file = 'config/data-return/main.yaml'
1660
1661 def test_data_return(self):
1662 # This exercises a proposed change to a role being checked out
1663 # and used.
1664 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1665 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
1666 self.waitUntilSettled()
1667 self.assertHistory([
1668 dict(name='data-return', result='SUCCESS', changes='1,1'),
James E. Blair88e79c02017-07-07 13:36:54 -07001669 dict(name='data-return-relative', result='SUCCESS', changes='1,1'),
1670 ], ordered=False)
1671 self.assertIn('- data-return http://example.com/test/log/url/',
1672 A.messages[-1])
1673 self.assertIn('- data-return-relative '
1674 'http://example.com/test/log/url/docs/index.html',
James E. Blair196f61a2017-06-30 15:42:29 -07001675 A.messages[-1])
Clint Byrumdc8a0902017-07-20 16:36:27 -07001676
1677
1678class TestDiskAccounting(AnsibleZuulTestCase):
1679 config_file = 'zuul-disk-accounting.conf'
1680 tenant_config_file = 'config/disk-accountant/main.yaml'
1681
1682 def test_disk_accountant_kills_job(self):
1683 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1684 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
1685 self.waitUntilSettled()
1686 self.assertHistory([
1687 dict(name='dd-big-empty-file', result='ABORTED', changes='1,1')])
Tristan Cacqueray82f864b2017-08-01 05:54:42 +00001688
1689
1690class TestMaxNodesPerJob(AnsibleZuulTestCase):
1691 tenant_config_file = 'config/multi-tenant/main.yaml'
1692
Tristan Cacquerayc98bff72017-09-10 15:25:26 +00001693 def test_max_timeout_exceeded(self):
Tristan Cacqueray82f864b2017-08-01 05:54:42 +00001694 in_repo_conf = textwrap.dedent(
1695 """
1696 - job:
1697 name: test-job
James E. Blair7e3e6882017-09-20 15:47:13 -07001698 nodeset:
1699 nodes:
1700 - name: node01
1701 label: fake
1702 - name: node02
1703 label: fake
1704 - name: node03
1705 label: fake
1706 - name: node04
1707 label: fake
1708 - name: node05
1709 label: fake
1710 - name: node06
1711 label: fake
Tristan Cacqueray82f864b2017-08-01 05:54:42 +00001712 """)
1713 file_dict = {'.zuul.yaml': in_repo_conf}
1714 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A',
1715 files=file_dict)
1716 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
1717 self.waitUntilSettled()
1718 self.assertIn('The job "test-job" exceeds tenant max-nodes-per-job 5.',
1719 A.messages[0], "A should fail because of nodes limit")
1720
1721 B = self.fake_gerrit.addFakeChange('org/project2', 'master', 'A',
1722 files=file_dict)
1723 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
1724 self.waitUntilSettled()
1725 self.assertNotIn("exceeds tenant max-nodes", B.messages[0],
1726 "B should not fail because of nodes limit")
James E. Blair2bab6e72017-08-07 09:52:45 -07001727
1728
Tristan Cacquerayc98bff72017-09-10 15:25:26 +00001729class TestMaxTimeout(AnsibleZuulTestCase):
1730 tenant_config_file = 'config/multi-tenant/main.yaml'
1731
1732 def test_max_nodes_reached(self):
1733 in_repo_conf = textwrap.dedent(
1734 """
1735 - job:
1736 name: test-job
1737 timeout: 3600
1738 """)
1739 file_dict = {'.zuul.yaml': in_repo_conf}
1740 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A',
1741 files=file_dict)
1742 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
1743 self.waitUntilSettled()
1744 self.assertIn('The job "test-job" exceeds tenant max-job-timeout',
1745 A.messages[0], "A should fail because of timeout limit")
1746
1747 B = self.fake_gerrit.addFakeChange('org/project2', 'master', 'A',
1748 files=file_dict)
1749 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
1750 self.waitUntilSettled()
1751 self.assertNotIn("exceeds tenant max-job-timeout", B.messages[0],
1752 "B should not fail because of timeout limit")
1753
1754
James E. Blair2bab6e72017-08-07 09:52:45 -07001755class TestBaseJobs(ZuulTestCase):
1756 tenant_config_file = 'config/base-jobs/main.yaml'
1757
1758 def test_multiple_base_jobs(self):
1759 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1760 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
1761 self.waitUntilSettled()
1762 self.assertHistory([
1763 dict(name='my-job', result='SUCCESS', changes='1,1'),
1764 dict(name='other-job', result='SUCCESS', changes='1,1'),
1765 ], ordered=False)
1766 self.assertEqual(self.getJobFromHistory('my-job').
1767 parameters['zuul']['jobtags'],
1768 ['mybase'])
1769 self.assertEqual(self.getJobFromHistory('other-job').
1770 parameters['zuul']['jobtags'],
1771 ['otherbase'])
1772
1773 def test_untrusted_base_job(self):
1774 """Test that a base job may not be defined in an untrusted repo"""
1775 in_repo_conf = textwrap.dedent(
1776 """
1777 - job:
1778 name: fail-base
1779 parent: null
1780 """)
1781
1782 file_dict = {'.zuul.yaml': in_repo_conf}
1783 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
1784 files=file_dict)
1785 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
1786 self.waitUntilSettled()
1787 self.assertEqual(A.reported, 1,
1788 "A should report failure")
1789 self.assertEqual(A.patchsets[0]['approvals'][0]['value'], "-1")
1790 self.assertIn('Base jobs must be defined in config projects',
1791 A.messages[0])
1792 self.assertHistory([])
James E. Blairdb089032017-08-15 13:42:12 -07001793
1794
1795class TestSecretLeaks(AnsibleZuulTestCase):
1796 tenant_config_file = 'config/secret-leaks/main.yaml'
1797
1798 def searchForContent(self, path, content):
1799 matches = []
1800 for (dirpath, dirnames, filenames) in os.walk(path):
1801 for filename in filenames:
1802 filepath = os.path.join(dirpath, filename)
1803 with open(filepath, 'rb') as f:
1804 if content in f.read():
1805 matches.append(filepath[len(path):])
1806 return matches
1807
1808 def _test_secret_file(self):
1809 # Or rather -- test that they *don't* leak.
1810 # Keep the jobdir around so we can inspect contents.
1811 self.executor_server.keep_jobdir = True
1812 conf = textwrap.dedent(
1813 """
1814 - project:
1815 name: org/project
1816 check:
1817 jobs:
1818 - secret-file
1819 """)
1820
1821 file_dict = {'.zuul.yaml': conf}
1822 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
1823 files=file_dict)
1824 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
1825 self.waitUntilSettled()
1826 self.assertHistory([
1827 dict(name='secret-file', result='SUCCESS', changes='1,1'),
1828 ], ordered=False)
1829 matches = self.searchForContent(self.history[0].jobdir.root,
1830 b'test-password')
James E. Blaird6a71ca2017-08-18 14:15:05 -07001831 self.assertEqual(set(['/work/secret-file.txt']),
James E. Blairdb089032017-08-15 13:42:12 -07001832 set(matches))
1833
1834 def test_secret_file(self):
1835 self._test_secret_file()
1836
1837 def test_secret_file_verbose(self):
1838 # Output extra ansible info to exercise alternate logging code
1839 # paths.
1840 self.executor_server.verbose = True
1841 self._test_secret_file()
1842
1843 def _test_secret_file_fail(self):
1844 # Or rather -- test that they *don't* leak.
1845 # Keep the jobdir around so we can inspect contents.
1846 self.executor_server.keep_jobdir = True
1847 conf = textwrap.dedent(
1848 """
1849 - project:
1850 name: org/project
1851 check:
1852 jobs:
1853 - secret-file-fail
1854 """)
1855
1856 file_dict = {'.zuul.yaml': conf}
1857 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
1858 files=file_dict)
1859 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
1860 self.waitUntilSettled()
1861 self.assertHistory([
1862 dict(name='secret-file-fail', result='FAILURE', changes='1,1'),
1863 ], ordered=False)
1864 matches = self.searchForContent(self.history[0].jobdir.root,
1865 b'test-password')
James E. Blaird6a71ca2017-08-18 14:15:05 -07001866 self.assertEqual(set(['/work/failure-file.txt']),
James E. Blairdb089032017-08-15 13:42:12 -07001867 set(matches))
1868
1869 def test_secret_file_fail(self):
1870 self._test_secret_file_fail()
1871
1872 def test_secret_file_fail_verbose(self):
1873 # Output extra ansible info to exercise alternate logging code
1874 # paths.
1875 self.executor_server.verbose = True
1876 self._test_secret_file_fail()
James E. Blaira00910c2017-08-23 09:15:04 -07001877
1878
1879class TestJobOutput(AnsibleZuulTestCase):
1880 tenant_config_file = 'config/job-output/main.yaml'
1881
1882 def _get_file(self, build, path):
1883 p = os.path.join(build.jobdir.root, path)
1884 with open(p) as f:
1885 return f.read()
1886
1887 def test_job_output(self):
1888 # Verify that command standard output appears in the job output
1889
1890 # This currently only verifies we receive output from
1891 # localhost. Notably, it does not verify we receive output
1892 # via zuul_console streaming.
1893 self.executor_server.keep_jobdir = True
1894 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1895 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
1896 self.waitUntilSettled()
1897 self.assertHistory([
1898 dict(name='job-output', result='SUCCESS', changes='1,1'),
1899 ], ordered=False)
1900
1901 token = 'Standard output test %s' % (self.history[0].jobdir.src_root)
1902 j = json.loads(self._get_file(self.history[0],
1903 'work/logs/job-output.json'))
1904 self.assertEqual(token,
1905 j[0]['plays'][0]['tasks'][0]
1906 ['hosts']['localhost']['stdout'])
1907
1908 print(self._get_file(self.history[0],
1909 'work/logs/job-output.txt'))
1910 self.assertIn(token,
1911 self._get_file(self.history[0],
1912 'work/logs/job-output.txt'))