blob: 3e0dc1541c21c92902815d4e15778b0419d1d151 [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. Blaira92cbc82017-01-23 14:56:49 -080017import os
James E. Blair14abdf42015-12-09 16:11:53 -080018import textwrap
James E. Blair59fdbac2015-12-07 17:08:06 -080019
James E. Blairb9c0d772017-03-03 14:34:49 -080020import testtools
21
22import zuul.configloader
James E. Blairbf1a4f22017-03-17 10:59:37 -070023from zuul.lib import encryption
Ricardo Carrillo Cruz22994f92016-12-02 11:41:58 +000024from tests.base import AnsibleZuulTestCase, ZuulTestCase, FIXTURE_DIR
James E. Blair59fdbac2015-12-07 17:08:06 -080025
James E. Blair59fdbac2015-12-07 17:08:06 -080026
James E. Blair3f876d52016-07-22 13:07:14 -070027class TestMultipleTenants(AnsibleZuulTestCase):
James E. Blair59fdbac2015-12-07 17:08:06 -080028 # A temporary class to hold new tests while others are disabled
29
James E. Blair2a629ec2015-12-22 15:32:02 -080030 tenant_config_file = 'config/multi-tenant/main.yaml'
James E. Blair59fdbac2015-12-07 17:08:06 -080031
James E. Blair83005782015-12-11 14:46:03 -080032 def test_multiple_tenants(self):
James E. Blair96f26942015-12-09 10:15:59 -080033 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A')
James E. Blair8b5408c2016-08-08 15:37:46 -070034 A.addApproval('code-review', 2)
35 self.fake_gerrit.addEvent(A.addApproval('approved', 1))
James E. Blair59fdbac2015-12-07 17:08:06 -080036 self.waitUntilSettled()
James E. Blair96f26942015-12-09 10:15:59 -080037 self.assertEqual(self.getJobFromHistory('project1-test1').result,
James E. Blair59fdbac2015-12-07 17:08:06 -080038 'SUCCESS')
James E. Blair96c6bf82016-01-15 16:20:40 -080039 self.assertEqual(self.getJobFromHistory('python27').result,
40 'SUCCESS')
James E. Blair59fdbac2015-12-07 17:08:06 -080041 self.assertEqual(A.data['status'], 'MERGED')
James E. Blair96f26942015-12-09 10:15:59 -080042 self.assertEqual(A.reported, 2,
43 "A should report start and success")
44 self.assertIn('tenant-one-gate', A.messages[1],
45 "A should transit tenant-one gate")
46 self.assertNotIn('tenant-two-gate', A.messages[1],
47 "A should *not* transit tenant-two gate")
James E. Blair59fdbac2015-12-07 17:08:06 -080048
James E. Blair96f26942015-12-09 10:15:59 -080049 B = self.fake_gerrit.addFakeChange('org/project2', 'master', 'B')
James E. Blair8b5408c2016-08-08 15:37:46 -070050 B.addApproval('code-review', 2)
51 self.fake_gerrit.addEvent(B.addApproval('approved', 1))
James E. Blair96f26942015-12-09 10:15:59 -080052 self.waitUntilSettled()
James E. Blair96c6bf82016-01-15 16:20:40 -080053 self.assertEqual(self.getJobFromHistory('python27',
54 'org/project2').result,
55 'SUCCESS')
James E. Blair96f26942015-12-09 10:15:59 -080056 self.assertEqual(self.getJobFromHistory('project2-test1').result,
57 'SUCCESS')
58 self.assertEqual(B.data['status'], 'MERGED')
59 self.assertEqual(B.reported, 2,
60 "B should report start and success")
61 self.assertIn('tenant-two-gate', B.messages[1],
62 "B should transit tenant-two gate")
63 self.assertNotIn('tenant-one-gate', B.messages[1],
64 "B should *not* transit tenant-one gate")
James E. Blair59fdbac2015-12-07 17:08:06 -080065
James E. Blair96f26942015-12-09 10:15:59 -080066 self.assertEqual(A.reported, 2, "Activity in tenant two should"
67 "not affect tenant one")
James E. Blair14abdf42015-12-09 16:11:53 -080068
James E. Blair83005782015-12-11 14:46:03 -080069
James E. Blairff555742017-02-19 11:34:27 -080070class TestInRepoConfig(ZuulTestCase):
James E. Blair83005782015-12-11 14:46:03 -080071 # A temporary class to hold new tests while others are disabled
72
James E. Blair2a629ec2015-12-22 15:32:02 -080073 tenant_config_file = 'config/in-repo/main.yaml'
James E. Blair83005782015-12-11 14:46:03 -080074
James E. Blair83005782015-12-11 14:46:03 -080075 def test_in_repo_config(self):
James E. Blair14abdf42015-12-09 16:11:53 -080076 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
James E. Blair8b5408c2016-08-08 15:37:46 -070077 A.addApproval('code-review', 2)
78 self.fake_gerrit.addEvent(A.addApproval('approved', 1))
James E. Blair14abdf42015-12-09 16:11:53 -080079 self.waitUntilSettled()
80 self.assertEqual(self.getJobFromHistory('project-test1').result,
81 'SUCCESS')
82 self.assertEqual(A.data['status'], 'MERGED')
83 self.assertEqual(A.reported, 2,
84 "A should report start and success")
85 self.assertIn('tenant-one-gate', A.messages[1],
86 "A should transit tenant-one gate")
James E. Blairb97ed802015-12-21 15:55:35 -080087
James E. Blair8b1dc3f2016-07-05 16:49:00 -070088 def test_dynamic_config(self):
89 in_repo_conf = textwrap.dedent(
90 """
91 - job:
92 name: project-test2
93
94 - project:
95 name: org/project
96 tenant-one-gate:
97 jobs:
98 - project-test2
99 """)
100
James E. Blairc73c73a2017-01-20 15:15:15 -0800101 in_repo_playbook = textwrap.dedent(
102 """
103 - hosts: all
104 tasks: []
105 """)
106
107 file_dict = {'.zuul.yaml': in_repo_conf,
108 'playbooks/project-test2.yaml': in_repo_playbook}
James E. Blair8b1dc3f2016-07-05 16:49:00 -0700109 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
James E. Blairc73c73a2017-01-20 15:15:15 -0800110 files=file_dict)
James E. Blair8b5408c2016-08-08 15:37:46 -0700111 A.addApproval('code-review', 2)
112 self.fake_gerrit.addEvent(A.addApproval('approved', 1))
James E. Blair8b1dc3f2016-07-05 16:49:00 -0700113 self.waitUntilSettled()
James E. Blair8b1dc3f2016-07-05 16:49:00 -0700114 self.assertEqual(A.data['status'], 'MERGED')
115 self.assertEqual(A.reported, 2,
116 "A should report start and success")
117 self.assertIn('tenant-one-gate', A.messages[1],
118 "A should transit tenant-one gate")
James E. Blair646322f2017-01-27 15:50:34 -0800119 self.assertHistory([
120 dict(name='project-test2', result='SUCCESS', changes='1,1')])
121
James E. Blairc2a5ed72017-02-20 14:12:01 -0500122 self.fake_gerrit.addEvent(A.getChangeMergedEvent())
James E. Blair7bbd7a32017-03-06 11:36:13 -0800123 self.waitUntilSettled()
James E. Blairc2a5ed72017-02-20 14:12:01 -0500124
James E. Blair646322f2017-01-27 15:50:34 -0800125 # Now that the config change is landed, it should be live for
126 # subsequent changes.
127 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
128 B.addApproval('code-review', 2)
129 self.fake_gerrit.addEvent(B.addApproval('approved', 1))
130 self.waitUntilSettled()
131 self.assertEqual(self.getJobFromHistory('project-test2').result,
132 'SUCCESS')
133 self.assertHistory([
134 dict(name='project-test2', result='SUCCESS', changes='1,1'),
135 dict(name='project-test2', result='SUCCESS', changes='2,1')])
James E. Blairc73c73a2017-01-20 15:15:15 -0800136
Tobias Henkel0f714002017-06-30 23:30:52 +0200137 def test_dynamic_config_new_patchset(self):
138 self.executor_server.hold_jobs_in_build = True
139
140 tenant = self.sched.abide.tenants.get('tenant-one')
141 check_pipeline = tenant.layout.pipelines['check']
142
143 in_repo_conf = textwrap.dedent(
144 """
145 - job:
146 name: project-test2
147
148 - project:
149 name: org/project
150 check:
151 jobs:
152 - project-test2
153 """)
154
155 in_repo_playbook = textwrap.dedent(
156 """
157 - hosts: all
158 tasks: []
159 """)
160
161 file_dict = {'.zuul.yaml': in_repo_conf,
162 'playbooks/project-test2.yaml': in_repo_playbook}
163 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
164 files=file_dict)
165 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
166 self.waitUntilSettled()
167
168 items = check_pipeline.getAllItems()
169 self.assertEqual(items[0].change.number, '1')
170 self.assertEqual(items[0].change.patchset, '1')
171 self.assertTrue(items[0].live)
172
173 in_repo_conf = textwrap.dedent(
174 """
175 - job:
Tobias Henkel0ce7ec62017-07-21 22:50:17 +0200176 name: project-test1
177
178 - job:
Tobias Henkel0f714002017-06-30 23:30:52 +0200179 name: project-test2
180
181 - project:
182 name: org/project
183 check:
184 jobs:
185 - project-test1
186 - project-test2
187 """)
188 file_dict = {'.zuul.yaml': in_repo_conf,
189 'playbooks/project-test2.yaml': in_repo_playbook}
190
191 A.addPatchset(files=file_dict)
192 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(2))
193
194 self.waitUntilSettled()
195
196 items = check_pipeline.getAllItems()
197 self.assertEqual(items[0].change.number, '1')
198 self.assertEqual(items[0].change.patchset, '2')
199 self.assertTrue(items[0].live)
200
201 self.executor_server.hold_jobs_in_build = False
Tobias Henkel0ce7ec62017-07-21 22:50:17 +0200202 self.executor_server.release('project-test1')
203 self.waitUntilSettled()
Tobias Henkel0f714002017-06-30 23:30:52 +0200204 self.executor_server.release()
205 self.waitUntilSettled()
206
Tobias Henkel0ce7ec62017-07-21 22:50:17 +0200207 self.assertHistory([
208 dict(name='project-test2', result='ABORTED', changes='1,1'),
209 dict(name='project-test1', result='SUCCESS', changes='1,2'),
210 dict(name='project-test2', result='SUCCESS', changes='1,2')])
211
Jesse Keating78f544a2017-07-13 14:27:40 -0700212 def test_dynamic_dependent_pipeline(self):
213 # Test dynamically adding a project to a
214 # dependent pipeline for the first time
215 self.executor_server.hold_jobs_in_build = True
216
217 tenant = self.sched.abide.tenants.get('tenant-one')
218 gate_pipeline = tenant.layout.pipelines['gate']
219
220 in_repo_conf = textwrap.dedent(
221 """
222 - job:
223 name: project-test2
224
225 - project:
226 name: org/project
227 gate:
228 jobs:
229 - project-test2
230 """)
231
232 in_repo_playbook = textwrap.dedent(
233 """
234 - hosts: all
235 tasks: []
236 """)
237
238 file_dict = {'.zuul.yaml': in_repo_conf,
239 'playbooks/project-test2.yaml': in_repo_playbook}
240 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
241 files=file_dict)
242 A.addApproval('approved', 1)
243 self.fake_gerrit.addEvent(A.addApproval('code-review', 2))
244 self.waitUntilSettled()
245
246 items = gate_pipeline.getAllItems()
247 self.assertEqual(items[0].change.number, '1')
248 self.assertEqual(items[0].change.patchset, '1')
249 self.assertTrue(items[0].live)
250
251 self.executor_server.hold_jobs_in_build = False
252 self.executor_server.release()
253 self.waitUntilSettled()
254
255 # Make sure the dynamic queue got cleaned up
256 self.assertEqual(gate_pipeline.queues, [])
257
James E. Blairff555742017-02-19 11:34:27 -0800258 def test_in_repo_branch(self):
259 in_repo_conf = textwrap.dedent(
260 """
261 - job:
262 name: project-test2
263
264 - project:
265 name: org/project
266 tenant-one-gate:
267 jobs:
268 - project-test2
269 """)
270
271 in_repo_playbook = textwrap.dedent(
272 """
273 - hosts: all
274 tasks: []
275 """)
276
277 file_dict = {'.zuul.yaml': in_repo_conf,
278 'playbooks/project-test2.yaml': in_repo_playbook}
279 self.create_branch('org/project', 'stable')
280 A = self.fake_gerrit.addFakeChange('org/project', 'stable', 'A',
281 files=file_dict)
282 A.addApproval('code-review', 2)
283 self.fake_gerrit.addEvent(A.addApproval('approved', 1))
284 self.waitUntilSettled()
285 self.assertEqual(A.data['status'], 'MERGED')
286 self.assertEqual(A.reported, 2,
287 "A should report start and success")
288 self.assertIn('tenant-one-gate', A.messages[1],
289 "A should transit tenant-one gate")
290 self.assertHistory([
291 dict(name='project-test2', result='SUCCESS', changes='1,1')])
292 self.fake_gerrit.addEvent(A.getChangeMergedEvent())
James E. Blair7bbd7a32017-03-06 11:36:13 -0800293 self.waitUntilSettled()
James E. Blairff555742017-02-19 11:34:27 -0800294
295 # The config change should not affect master.
296 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
297 B.addApproval('code-review', 2)
298 self.fake_gerrit.addEvent(B.addApproval('approved', 1))
299 self.waitUntilSettled()
300 self.assertHistory([
301 dict(name='project-test2', result='SUCCESS', changes='1,1'),
302 dict(name='project-test1', result='SUCCESS', changes='2,1')])
303
304 # The config change should be live for further changes on
305 # stable.
306 C = self.fake_gerrit.addFakeChange('org/project', 'stable', 'C')
307 C.addApproval('code-review', 2)
308 self.fake_gerrit.addEvent(C.addApproval('approved', 1))
309 self.waitUntilSettled()
310 self.assertHistory([
311 dict(name='project-test2', result='SUCCESS', changes='1,1'),
312 dict(name='project-test1', result='SUCCESS', changes='2,1'),
313 dict(name='project-test2', result='SUCCESS', changes='3,1')])
314
James E. Blaira5a12492017-05-03 11:40:48 -0700315 def test_crd_dynamic_config_branch(self):
316 # Test that we can create a job in one repo and be able to use
317 # it from a different branch on a different repo.
318
319 self.create_branch('org/project1', 'stable')
320
321 in_repo_conf = textwrap.dedent(
322 """
323 - job:
324 name: project-test2
325
326 - project:
327 name: org/project
328 check:
329 jobs:
330 - project-test2
331 """)
332
333 in_repo_playbook = textwrap.dedent(
334 """
335 - hosts: all
336 tasks: []
337 """)
338
339 file_dict = {'.zuul.yaml': in_repo_conf,
340 'playbooks/project-test2.yaml': in_repo_playbook}
341 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
342 files=file_dict)
343
344 second_repo_conf = textwrap.dedent(
345 """
346 - project:
347 name: org/project1
348 check:
349 jobs:
350 - project-test2
351 """)
352
353 second_file_dict = {'.zuul.yaml': second_repo_conf}
354 B = self.fake_gerrit.addFakeChange('org/project1', 'stable', 'B',
355 files=second_file_dict)
356 B.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
357 B.subject, A.data['id'])
358
359 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
360 self.waitUntilSettled()
361 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
362 self.waitUntilSettled()
363
364 self.assertEqual(A.reported, 1, "A should report")
365 self.assertHistory([
366 dict(name='project-test2', result='SUCCESS', changes='1,1'),
367 dict(name='project-test2', result='SUCCESS', changes='1,1 2,1'),
368 ])
369
James E. Blair149b69c2017-03-02 10:48:16 -0800370 def test_untrusted_syntax_error(self):
James E. Blaire53250c2017-03-01 14:34:36 -0800371 in_repo_conf = textwrap.dedent(
372 """
373 - job:
374 name: project-test2
375 foo: error
376 """)
377
378 file_dict = {'.zuul.yaml': in_repo_conf}
379 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
380 files=file_dict)
381 A.addApproval('code-review', 2)
382 self.fake_gerrit.addEvent(A.addApproval('approved', 1))
383 self.waitUntilSettled()
384
385 self.assertEqual(A.data['status'], 'NEW')
Tobias Henkel9842bd72017-05-16 13:40:03 +0200386 self.assertEqual(A.reported, 1,
387 "A should report failure")
388 self.assertIn('syntax error', A.messages[0],
James E. Blaire53250c2017-03-01 14:34:36 -0800389 "A should have a syntax error reported")
390
James E. Blair149b69c2017-03-02 10:48:16 -0800391 def test_trusted_syntax_error(self):
392 in_repo_conf = textwrap.dedent(
393 """
394 - job:
395 name: project-test2
396 foo: error
397 """)
398
399 file_dict = {'zuul.yaml': in_repo_conf}
400 A = self.fake_gerrit.addFakeChange('common-config', 'master', 'A',
401 files=file_dict)
402 A.addApproval('code-review', 2)
403 self.fake_gerrit.addEvent(A.addApproval('approved', 1))
404 self.waitUntilSettled()
405
406 self.assertEqual(A.data['status'], 'NEW')
Tobias Henkel9842bd72017-05-16 13:40:03 +0200407 self.assertEqual(A.reported, 1,
408 "A should report failure")
409 self.assertIn('syntax error', A.messages[0],
James E. Blair149b69c2017-03-02 10:48:16 -0800410 "A should have a syntax error reported")
411
James E. Blair6f140c72017-03-03 10:32:07 -0800412 def test_untrusted_yaml_error(self):
413 in_repo_conf = textwrap.dedent(
414 """
415 - job:
416 foo: error
417 """)
418
419 file_dict = {'.zuul.yaml': in_repo_conf}
420 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
421 files=file_dict)
422 A.addApproval('code-review', 2)
423 self.fake_gerrit.addEvent(A.addApproval('approved', 1))
424 self.waitUntilSettled()
425
426 self.assertEqual(A.data['status'], 'NEW')
Tobias Henkel9842bd72017-05-16 13:40:03 +0200427 self.assertEqual(A.reported, 1,
428 "A should report failure")
429 self.assertIn('syntax error', A.messages[0],
James E. Blair6f140c72017-03-03 10:32:07 -0800430 "A should have a syntax error reported")
431
James E. Blairdb04e6a2017-05-03 14:49:36 -0700432 def test_untrusted_shadow_error(self):
433 in_repo_conf = textwrap.dedent(
434 """
435 - job:
436 name: common-config-test
437 """)
438
439 file_dict = {'.zuul.yaml': in_repo_conf}
440 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
441 files=file_dict)
442 A.addApproval('code-review', 2)
443 self.fake_gerrit.addEvent(A.addApproval('approved', 1))
444 self.waitUntilSettled()
445
446 self.assertEqual(A.data['status'], 'NEW')
Tobias Henkel9842bd72017-05-16 13:40:03 +0200447 self.assertEqual(A.reported, 1,
448 "A should report failure")
449 self.assertIn('not permitted to shadow', A.messages[0],
James E. Blairdb04e6a2017-05-03 14:49:36 -0700450 "A should have a syntax error reported")
451
James E. Blaird5656ad2017-06-02 14:29:41 -0700452 def test_untrusted_pipeline_error(self):
453 in_repo_conf = textwrap.dedent(
454 """
455 - pipeline:
456 name: test
457 """)
458
459 file_dict = {'.zuul.yaml': in_repo_conf}
460 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
461 files=file_dict)
462 A.addApproval('code-review', 2)
463 self.fake_gerrit.addEvent(A.addApproval('approved', 1))
464 self.waitUntilSettled()
465
466 self.assertEqual(A.data['status'], 'NEW')
467 self.assertEqual(A.reported, 1,
468 "A should report failure")
469 self.assertIn('Pipelines may not be defined', A.messages[0],
470 "A should have a syntax error reported")
471
472 def test_untrusted_project_error(self):
473 in_repo_conf = textwrap.dedent(
474 """
475 - project:
476 name: org/project1
477 """)
478
479 file_dict = {'.zuul.yaml': in_repo_conf}
480 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
481 files=file_dict)
482 A.addApproval('code-review', 2)
483 self.fake_gerrit.addEvent(A.addApproval('approved', 1))
484 self.waitUntilSettled()
485
486 self.assertEqual(A.data['status'], 'NEW')
487 self.assertEqual(A.reported, 1,
488 "A should report failure")
489 self.assertIn('the only project definition permitted', A.messages[0],
490 "A should have a syntax error reported")
491
James E. Blaire64b0e42017-06-08 11:23:34 -0700492 def test_duplicate_node_error(self):
493 in_repo_conf = textwrap.dedent(
494 """
495 - nodeset:
496 name: duplicate
497 nodes:
498 - name: compute
James E. Blair16d96a02017-06-08 11:32:56 -0700499 label: foo
James E. Blaire64b0e42017-06-08 11:23:34 -0700500 - name: compute
James E. Blair16d96a02017-06-08 11:32:56 -0700501 label: foo
James E. Blaire64b0e42017-06-08 11:23:34 -0700502 """)
503
504 file_dict = {'.zuul.yaml': in_repo_conf}
505 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
506 files=file_dict)
507 A.addApproval('code-review', 2)
508 self.fake_gerrit.addEvent(A.addApproval('approved', 1))
509 self.waitUntilSettled()
510
511 self.assertEqual(A.data['status'], 'NEW')
512 self.assertEqual(A.reported, 1,
513 "A should report failure")
514 self.assertIn('appears multiple times', A.messages[0],
515 "A should have a syntax error reported")
516
517 def test_duplicate_group_error(self):
518 in_repo_conf = textwrap.dedent(
519 """
520 - nodeset:
521 name: duplicate
522 nodes:
523 - name: compute
James E. Blair16d96a02017-06-08 11:32:56 -0700524 label: foo
James E. Blaire64b0e42017-06-08 11:23:34 -0700525 groups:
526 - name: group
527 nodes: compute
528 - name: group
529 nodes: compute
530 """)
531
532 file_dict = {'.zuul.yaml': in_repo_conf}
533 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
534 files=file_dict)
535 A.addApproval('code-review', 2)
536 self.fake_gerrit.addEvent(A.addApproval('approved', 1))
537 self.waitUntilSettled()
538
539 self.assertEqual(A.data['status'], 'NEW')
540 self.assertEqual(A.reported, 1,
541 "A should report failure")
542 self.assertIn('appears multiple times', A.messages[0],
543 "A should have a syntax error reported")
544
James E. Blair09f9ffe2017-07-11 15:30:25 -0700545 def test_multi_repo(self):
546 downstream_repo_conf = textwrap.dedent(
547 """
548 - project:
549 name: org/project1
550 tenant-one-gate:
551 jobs:
552 - project-test1
553
554 - job:
555 name: project1-test1
556 parent: project-test1
557 """)
558
559 file_dict = {'.zuul.yaml': downstream_repo_conf}
560 A = self.fake_gerrit.addFakeChange('org/project1', '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'], 'MERGED')
567 self.fake_gerrit.addEvent(A.getChangeMergedEvent())
568 self.waitUntilSettled()
569
570 upstream_repo_conf = textwrap.dedent(
571 """
572 - job:
573 name: project-test1
574
575 - job:
576 name: project-test2
577
578 - project:
579 name: org/project
580 tenant-one-gate:
581 jobs:
582 - project-test1
583 """)
584
585 file_dict = {'.zuul.yaml': upstream_repo_conf}
586 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B',
587 files=file_dict)
588 B.addApproval('code-review', 2)
589 self.fake_gerrit.addEvent(B.addApproval('approved', 1))
590 self.waitUntilSettled()
591
592 self.assertEqual(B.data['status'], 'MERGED')
593 self.fake_gerrit.addEvent(B.getChangeMergedEvent())
594 self.waitUntilSettled()
595
596 tenant = self.sched.abide.tenants.get('tenant-one')
597 # Ensure the latest change is reflected in the config; if it
598 # isn't this will raise an exception.
599 tenant.layout.getJob('project-test2')
600
James E. Blairc73c73a2017-01-20 15:15:15 -0800601
602class TestAnsible(AnsibleZuulTestCase):
603 # A temporary class to hold new tests while others are disabled
604
605 tenant_config_file = 'config/ansible/main.yaml'
606
607 def test_playbook(self):
608 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
609 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
610 self.waitUntilSettled()
Tobias Henkel077f2f32017-05-30 20:16:46 +0200611 build_timeout = self.getJobFromHistory('timeout')
612 self.assertEqual(build_timeout.result, 'TIMED_OUT')
613 build_faillocal = self.getJobFromHistory('faillocal')
614 self.assertEqual(build_faillocal.result, 'FAILURE')
615 build_failpost = self.getJobFromHistory('failpost')
616 self.assertEqual(build_failpost.result, 'POST_FAILURE')
617 build_check_vars = self.getJobFromHistory('check-vars')
618 self.assertEqual(build_check_vars.result, 'SUCCESS')
619 build_hello = self.getJobFromHistory('hello-world')
620 self.assertEqual(build_hello.result, 'SUCCESS')
621 build_python27 = self.getJobFromHistory('python27')
622 self.assertEqual(build_python27.result, 'SUCCESS')
623 flag_path = os.path.join(self.test_root, build_python27.uuid + '.flag')
James E. Blaira92cbc82017-01-23 14:56:49 -0800624 self.assertTrue(os.path.exists(flag_path))
Tobias Henkel077f2f32017-05-30 20:16:46 +0200625 copied_path = os.path.join(self.test_root, build_python27.uuid +
Monty Taylorc231d932017-02-03 09:57:15 -0600626 '.copied')
627 self.assertTrue(os.path.exists(copied_path))
Tobias Henkel077f2f32017-05-30 20:16:46 +0200628 failed_path = os.path.join(self.test_root, build_python27.uuid +
Monty Taylorc231d932017-02-03 09:57:15 -0600629 '.failed')
630 self.assertFalse(os.path.exists(failed_path))
Tobias Henkel077f2f32017-05-30 20:16:46 +0200631 pre_flag_path = os.path.join(self.test_root, build_python27.uuid +
James E. Blair66b274e2017-01-31 14:47:52 -0800632 '.pre.flag')
633 self.assertTrue(os.path.exists(pre_flag_path))
Tobias Henkel077f2f32017-05-30 20:16:46 +0200634 post_flag_path = os.path.join(self.test_root, build_python27.uuid +
James E. Blair66b274e2017-01-31 14:47:52 -0800635 '.post.flag')
636 self.assertTrue(os.path.exists(post_flag_path))
James E. Blair5ac93842017-01-20 06:47:34 -0800637 bare_role_flag_path = os.path.join(self.test_root,
Tobias Henkel077f2f32017-05-30 20:16:46 +0200638 build_python27.uuid +
639 '.bare-role.flag')
James E. Blair5ac93842017-01-20 06:47:34 -0800640 self.assertTrue(os.path.exists(bare_role_flag_path))
James E. Blairb9c0d772017-03-03 14:34:49 -0800641
James E. Blair18f86a32017-03-15 14:43:26 -0700642 secrets_path = os.path.join(self.test_root,
Tobias Henkel077f2f32017-05-30 20:16:46 +0200643 build_python27.uuid + '.secrets')
James E. Blair18f86a32017-03-15 14:43:26 -0700644 with open(secrets_path) as f:
645 self.assertEqual(f.read(), "test-username test-password")
646
Tobias Henkel077f2f32017-05-30 20:16:46 +0200647 msg = A.messages[0]
648 success = "{} https://success.example.com/zuul-logs/{}"
649 fail = "{} https://failure.example.com/zuul-logs/{}"
650 self.assertIn(success.format("python27", build_python27.uuid), msg)
651 self.assertIn(fail.format("faillocal", build_faillocal.uuid), msg)
652 self.assertIn(success.format("check-vars", build_check_vars.uuid), msg)
653 self.assertIn(success.format("hello-world", build_hello.uuid), msg)
654 self.assertIn(fail.format("timeout", build_timeout.uuid), msg)
655 self.assertIn(fail.format("failpost", build_failpost.uuid), msg)
656
James E. Blairb9c0d772017-03-03 14:34:49 -0800657
James E. Blaira4d4eef2017-06-30 14:49:17 -0700658class TestPrePlaybooks(AnsibleZuulTestCase):
659 # A temporary class to hold new tests while others are disabled
660
661 tenant_config_file = 'config/pre-playbook/main.yaml'
662
663 def test_pre_playbook_fail(self):
664 # Test that we run the post playbooks (but not the actual
665 # playbook) when a pre-playbook fails.
666 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
667 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
668 self.waitUntilSettled()
669 build = self.getJobFromHistory('python27')
670 self.assertIsNone(build.result)
671 self.assertIn('RETRY_LIMIT', A.messages[0])
672 flag_path = os.path.join(self.test_root, build.uuid +
673 '.main.flag')
674 self.assertFalse(os.path.exists(flag_path))
675 pre_flag_path = os.path.join(self.test_root, build.uuid +
676 '.pre.flag')
677 self.assertFalse(os.path.exists(pre_flag_path))
678 post_flag_path = os.path.join(self.test_root, build.uuid +
679 '.post.flag')
James E. Blair21037782017-07-19 11:56:55 -0700680 self.assertTrue(os.path.exists(post_flag_path),
681 "The file %s should exist" % post_flag_path)
James E. Blaira4d4eef2017-06-30 14:49:17 -0700682
683
James E. Blairb9c0d772017-03-03 14:34:49 -0800684class TestBrokenConfig(ZuulTestCase):
685 # Test that we get an appropriate syntax error if we start with a
686 # broken config.
687
688 tenant_config_file = 'config/broken/main.yaml'
689
690 def setUp(self):
691 with testtools.ExpectedException(
692 zuul.configloader.ConfigurationSyntaxError,
693 "\nZuul encountered a syntax error"):
694 super(TestBrokenConfig, self).setUp()
695
696 def test_broken_config_on_startup(self):
697 pass
Ricardo Carrillo Cruz22994f92016-12-02 11:41:58 +0000698
699
700class TestProjectKeys(ZuulTestCase):
701 # Test that we can generate project keys
702
703 # Normally the test infrastructure copies a static key in place
704 # for each project before starting tests. This saves time because
705 # Zuul's automatic key-generation on startup can be slow. To make
706 # sure we exercise that code, in this test we allow Zuul to create
707 # keys for the project on startup.
708 create_project_keys = True
709 tenant_config_file = 'config/in-repo/main.yaml'
710
711 def test_key_generation(self):
712 key_root = os.path.join(self.state_root, 'keys')
713 private_key_file = os.path.join(key_root, 'gerrit/org/project.pem')
714 # Make sure that a proper key was created on startup
715 with open(private_key_file, "rb") as f:
James E. Blairbf1a4f22017-03-17 10:59:37 -0700716 private_key, public_key = \
717 encryption.deserialize_rsa_keypair(f.read())
Ricardo Carrillo Cruz22994f92016-12-02 11:41:58 +0000718
719 with open(os.path.join(FIXTURE_DIR, 'private.pem')) as i:
720 fixture_private_key = i.read()
721
722 # Make sure that we didn't just end up with the static fixture
723 # key
724 self.assertNotEqual(fixture_private_key, private_key)
725
726 # Make sure it's the right length
727 self.assertEqual(4096, private_key.key_size)
James E. Blairbce76932017-05-04 10:03:15 -0700728
729
James E. Blairbb94dfa2017-07-11 07:45:19 -0700730class RoleTestCase(ZuulTestCase):
James E. Blair1b27f6a2017-07-14 14:09:07 -0700731 def _assertRolePath(self, build, playbook, content):
732 path = os.path.join(self.test_root, build.uuid,
733 'ansible', playbook, 'ansible.cfg')
734 roles_paths = []
735 with open(path) as f:
736 for line in f:
737 if line.startswith('roles_path'):
738 roles_paths.append(line)
739 print(roles_paths)
740 if content:
741 self.assertEqual(len(roles_paths), 1,
742 "Should have one roles_path line in %s" %
743 (playbook,))
744 self.assertIn(content, roles_paths[0])
745 else:
746 self.assertEqual(len(roles_paths), 0,
747 "Should have no roles_path line in %s" %
748 (playbook,))
749
James E. Blairbb94dfa2017-07-11 07:45:19 -0700750
751class TestRoles(RoleTestCase):
752 tenant_config_file = 'config/roles/main.yaml'
753
James E. Blairbce76932017-05-04 10:03:15 -0700754 def test_role(self):
755 # This exercises a proposed change to a role being checked out
756 # and used.
757 A = self.fake_gerrit.addFakeChange('bare-role', 'master', 'A')
758 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
759 B.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
760 B.subject, A.data['id'])
761 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
762 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
763 self.waitUntilSettled()
764 self.assertHistory([
765 dict(name='project-test', result='SUCCESS', changes='1,1 2,1'),
766 ])
James E. Blair6459db12017-06-29 14:57:20 -0700767
James E. Blair1b27f6a2017-07-14 14:09:07 -0700768 def test_role_inheritance(self):
769 self.executor_server.hold_jobs_in_build = True
770 conf = textwrap.dedent(
771 """
772 - job:
773 name: parent
774 roles:
775 - zuul: bare-role
776 pre-run: playbooks/parent-pre
777 post-run: playbooks/parent-post
778
779 - job:
780 name: project-test
781 parent: parent
782 roles:
783 - zuul: org/project
784
785 - project:
786 name: org/project
787 check:
788 jobs:
789 - project-test
790 """)
791
792 file_dict = {'.zuul.yaml': conf}
793 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
794 files=file_dict)
795 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
796 self.waitUntilSettled()
797
798 self.assertEqual(len(self.builds), 1)
799 build = self.getBuildByName('project-test')
800 self._assertRolePath(build, 'pre_playbook_0', 'role_0')
801 self._assertRolePath(build, 'playbook_0', 'role_0')
802 self._assertRolePath(build, 'playbook_0', 'role_1')
803 self._assertRolePath(build, 'post_playbook_0', 'role_0')
804
805 self.executor_server.hold_jobs_in_build = False
806 self.executor_server.release()
807 self.waitUntilSettled()
808
809 self.assertHistory([
810 dict(name='project-test', result='SUCCESS', changes='1,1'),
811 ])
812
James E. Blair6f699732017-07-18 14:19:11 -0700813 def test_role_error(self):
814 conf = textwrap.dedent(
815 """
816 - job:
817 name: project-test
818 roles:
819 - zuul: common-config
820
821 - project:
822 name: org/project
823 check:
824 jobs:
825 - project-test
826 """)
827
828 file_dict = {'.zuul.yaml': conf}
829 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
830 files=file_dict)
831 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
832 self.waitUntilSettled()
833 self.assertIn(
834 '- project-test project-test : ERROR Unable to find role',
835 A.messages[-1])
836
James E. Blair6459db12017-06-29 14:57:20 -0700837
James E. Blairbb94dfa2017-07-11 07:45:19 -0700838class TestImplicitRoles(RoleTestCase):
839 tenant_config_file = 'config/implicit-roles/main.yaml'
840
841 def test_missing_roles(self):
842 # Test implicit and explicit roles for a project which does
843 # not have roles. The implicit role should be silently
844 # ignored since the project doesn't supply roles, but if a
845 # user declares an explicit role, it should error.
846 self.executor_server.hold_jobs_in_build = True
847 A = self.fake_gerrit.addFakeChange('org/norole-project', 'master', 'A')
848 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
849 self.waitUntilSettled()
850
851 self.assertEqual(len(self.builds), 2)
852 build = self.getBuildByName('implicit-role-fail')
853 self._assertRolePath(build, 'playbook_0', None)
854
855 self.executor_server.hold_jobs_in_build = False
856 self.executor_server.release()
857 self.waitUntilSettled()
858 # The retry_limit doesn't get recorded
859 self.assertHistory([
860 dict(name='implicit-role-fail', result='SUCCESS', changes='1,1'),
861 ])
862
863 def test_roles(self):
864 # Test implicit and explicit roles for a project which does
865 # have roles. In both cases, we should end up with the role
866 # in the path. In the explicit case, ensure we end up with
867 # the name we specified.
868 self.executor_server.hold_jobs_in_build = True
869 A = self.fake_gerrit.addFakeChange('org/role-project', 'master', 'A')
870 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
871 self.waitUntilSettled()
872
873 self.assertEqual(len(self.builds), 2)
874 build = self.getBuildByName('implicit-role-ok')
875 self._assertRolePath(build, 'playbook_0', 'role_0')
876
877 build = self.getBuildByName('explicit-role-ok')
878 self._assertRolePath(build, 'playbook_0', 'role_0')
879
880 self.executor_server.hold_jobs_in_build = False
881 self.executor_server.release()
882 self.waitUntilSettled()
883 self.assertHistory([
884 dict(name='implicit-role-ok', result='SUCCESS', changes='1,1'),
885 dict(name='explicit-role-ok', result='SUCCESS', changes='1,1'),
886 ], ordered=False)
887
888
James E. Blair6459db12017-06-29 14:57:20 -0700889class TestShadow(ZuulTestCase):
890 tenant_config_file = 'config/shadow/main.yaml'
891
892 def test_shadow(self):
893 # Test that a repo is allowed to shadow another's job definitions.
894 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
895 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
896 self.waitUntilSettled()
897 self.assertHistory([
898 dict(name='test1', result='SUCCESS', changes='1,1'),
899 dict(name='test2', result='SUCCESS', changes='1,1'),
James E. Blairadafa6c2017-07-12 08:50:56 -0700900 ], ordered=False)
James E. Blair196f61a2017-06-30 15:42:29 -0700901
902
903class TestDataReturn(AnsibleZuulTestCase):
904 tenant_config_file = 'config/data-return/main.yaml'
905
906 def test_data_return(self):
907 # This exercises a proposed change to a role being checked out
908 # and used.
909 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
910 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
911 self.waitUntilSettled()
912 self.assertHistory([
913 dict(name='data-return', result='SUCCESS', changes='1,1'),
James E. Blair88e79c02017-07-07 13:36:54 -0700914 dict(name='data-return-relative', result='SUCCESS', changes='1,1'),
915 ], ordered=False)
916 self.assertIn('- data-return http://example.com/test/log/url/',
917 A.messages[-1])
918 self.assertIn('- data-return-relative '
919 'http://example.com/test/log/url/docs/index.html',
James E. Blair196f61a2017-06-30 15:42:29 -0700920 A.messages[-1])