blob: fb80660818d677ac7986876316741979591410a0 [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:
176 name: project-test2
177
178 - project:
179 name: org/project
180 check:
181 jobs:
182 - project-test1
183 - project-test2
184 """)
185 file_dict = {'.zuul.yaml': in_repo_conf,
186 'playbooks/project-test2.yaml': in_repo_playbook}
187
188 A.addPatchset(files=file_dict)
189 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(2))
190
191 self.waitUntilSettled()
192
193 items = check_pipeline.getAllItems()
194 self.assertEqual(items[0].change.number, '1')
195 self.assertEqual(items[0].change.patchset, '2')
196 self.assertTrue(items[0].live)
197
198 self.executor_server.hold_jobs_in_build = False
199 self.executor_server.release()
200 self.waitUntilSettled()
201
Jesse Keating78f544a2017-07-13 14:27:40 -0700202 def test_dynamic_dependent_pipeline(self):
203 # Test dynamically adding a project to a
204 # dependent pipeline for the first time
205 self.executor_server.hold_jobs_in_build = True
206
207 tenant = self.sched.abide.tenants.get('tenant-one')
208 gate_pipeline = tenant.layout.pipelines['gate']
209
210 in_repo_conf = textwrap.dedent(
211 """
212 - job:
213 name: project-test2
214
215 - project:
216 name: org/project
217 gate:
218 jobs:
219 - project-test2
220 """)
221
222 in_repo_playbook = textwrap.dedent(
223 """
224 - hosts: all
225 tasks: []
226 """)
227
228 file_dict = {'.zuul.yaml': in_repo_conf,
229 'playbooks/project-test2.yaml': in_repo_playbook}
230 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
231 files=file_dict)
232 A.addApproval('approved', 1)
233 self.fake_gerrit.addEvent(A.addApproval('code-review', 2))
234 self.waitUntilSettled()
235
236 items = gate_pipeline.getAllItems()
237 self.assertEqual(items[0].change.number, '1')
238 self.assertEqual(items[0].change.patchset, '1')
239 self.assertTrue(items[0].live)
240
241 self.executor_server.hold_jobs_in_build = False
242 self.executor_server.release()
243 self.waitUntilSettled()
244
245 # Make sure the dynamic queue got cleaned up
246 self.assertEqual(gate_pipeline.queues, [])
247
James E. Blairff555742017-02-19 11:34:27 -0800248 def test_in_repo_branch(self):
249 in_repo_conf = textwrap.dedent(
250 """
251 - job:
252 name: project-test2
253
254 - project:
255 name: org/project
256 tenant-one-gate:
257 jobs:
258 - project-test2
259 """)
260
261 in_repo_playbook = textwrap.dedent(
262 """
263 - hosts: all
264 tasks: []
265 """)
266
267 file_dict = {'.zuul.yaml': in_repo_conf,
268 'playbooks/project-test2.yaml': in_repo_playbook}
269 self.create_branch('org/project', 'stable')
270 A = self.fake_gerrit.addFakeChange('org/project', 'stable', 'A',
271 files=file_dict)
272 A.addApproval('code-review', 2)
273 self.fake_gerrit.addEvent(A.addApproval('approved', 1))
274 self.waitUntilSettled()
275 self.assertEqual(A.data['status'], 'MERGED')
276 self.assertEqual(A.reported, 2,
277 "A should report start and success")
278 self.assertIn('tenant-one-gate', A.messages[1],
279 "A should transit tenant-one gate")
280 self.assertHistory([
281 dict(name='project-test2', result='SUCCESS', changes='1,1')])
282 self.fake_gerrit.addEvent(A.getChangeMergedEvent())
James E. Blair7bbd7a32017-03-06 11:36:13 -0800283 self.waitUntilSettled()
James E. Blairff555742017-02-19 11:34:27 -0800284
285 # The config change should not affect master.
286 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
287 B.addApproval('code-review', 2)
288 self.fake_gerrit.addEvent(B.addApproval('approved', 1))
289 self.waitUntilSettled()
290 self.assertHistory([
291 dict(name='project-test2', result='SUCCESS', changes='1,1'),
292 dict(name='project-test1', result='SUCCESS', changes='2,1')])
293
294 # The config change should be live for further changes on
295 # stable.
296 C = self.fake_gerrit.addFakeChange('org/project', 'stable', 'C')
297 C.addApproval('code-review', 2)
298 self.fake_gerrit.addEvent(C.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 dict(name='project-test2', result='SUCCESS', changes='3,1')])
304
James E. Blaira5a12492017-05-03 11:40:48 -0700305 def test_crd_dynamic_config_branch(self):
306 # Test that we can create a job in one repo and be able to use
307 # it from a different branch on a different repo.
308
309 self.create_branch('org/project1', 'stable')
310
311 in_repo_conf = textwrap.dedent(
312 """
313 - job:
314 name: project-test2
315
316 - project:
317 name: org/project
318 check:
319 jobs:
320 - project-test2
321 """)
322
323 in_repo_playbook = textwrap.dedent(
324 """
325 - hosts: all
326 tasks: []
327 """)
328
329 file_dict = {'.zuul.yaml': in_repo_conf,
330 'playbooks/project-test2.yaml': in_repo_playbook}
331 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
332 files=file_dict)
333
334 second_repo_conf = textwrap.dedent(
335 """
336 - project:
337 name: org/project1
338 check:
339 jobs:
340 - project-test2
341 """)
342
343 second_file_dict = {'.zuul.yaml': second_repo_conf}
344 B = self.fake_gerrit.addFakeChange('org/project1', 'stable', 'B',
345 files=second_file_dict)
346 B.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
347 B.subject, A.data['id'])
348
349 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
350 self.waitUntilSettled()
351 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
352 self.waitUntilSettled()
353
354 self.assertEqual(A.reported, 1, "A should report")
355 self.assertHistory([
356 dict(name='project-test2', result='SUCCESS', changes='1,1'),
357 dict(name='project-test2', result='SUCCESS', changes='1,1 2,1'),
358 ])
359
James E. Blair149b69c2017-03-02 10:48:16 -0800360 def test_untrusted_syntax_error(self):
James E. Blaire53250c2017-03-01 14:34:36 -0800361 in_repo_conf = textwrap.dedent(
362 """
363 - job:
364 name: project-test2
365 foo: error
366 """)
367
368 file_dict = {'.zuul.yaml': in_repo_conf}
369 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
370 files=file_dict)
371 A.addApproval('code-review', 2)
372 self.fake_gerrit.addEvent(A.addApproval('approved', 1))
373 self.waitUntilSettled()
374
375 self.assertEqual(A.data['status'], 'NEW')
Tobias Henkel9842bd72017-05-16 13:40:03 +0200376 self.assertEqual(A.reported, 1,
377 "A should report failure")
378 self.assertIn('syntax error', A.messages[0],
James E. Blaire53250c2017-03-01 14:34:36 -0800379 "A should have a syntax error reported")
380
James E. Blair149b69c2017-03-02 10:48:16 -0800381 def test_trusted_syntax_error(self):
382 in_repo_conf = textwrap.dedent(
383 """
384 - job:
385 name: project-test2
386 foo: error
387 """)
388
389 file_dict = {'zuul.yaml': in_repo_conf}
390 A = self.fake_gerrit.addFakeChange('common-config', 'master', 'A',
391 files=file_dict)
392 A.addApproval('code-review', 2)
393 self.fake_gerrit.addEvent(A.addApproval('approved', 1))
394 self.waitUntilSettled()
395
396 self.assertEqual(A.data['status'], 'NEW')
Tobias Henkel9842bd72017-05-16 13:40:03 +0200397 self.assertEqual(A.reported, 1,
398 "A should report failure")
399 self.assertIn('syntax error', A.messages[0],
James E. Blair149b69c2017-03-02 10:48:16 -0800400 "A should have a syntax error reported")
401
James E. Blair6f140c72017-03-03 10:32:07 -0800402 def test_untrusted_yaml_error(self):
403 in_repo_conf = textwrap.dedent(
404 """
405 - job:
406 foo: error
407 """)
408
409 file_dict = {'.zuul.yaml': in_repo_conf}
410 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
411 files=file_dict)
412 A.addApproval('code-review', 2)
413 self.fake_gerrit.addEvent(A.addApproval('approved', 1))
414 self.waitUntilSettled()
415
416 self.assertEqual(A.data['status'], 'NEW')
Tobias Henkel9842bd72017-05-16 13:40:03 +0200417 self.assertEqual(A.reported, 1,
418 "A should report failure")
419 self.assertIn('syntax error', A.messages[0],
James E. Blair6f140c72017-03-03 10:32:07 -0800420 "A should have a syntax error reported")
421
James E. Blairdb04e6a2017-05-03 14:49:36 -0700422 def test_untrusted_shadow_error(self):
423 in_repo_conf = textwrap.dedent(
424 """
425 - job:
426 name: common-config-test
427 """)
428
429 file_dict = {'.zuul.yaml': in_repo_conf}
430 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
431 files=file_dict)
432 A.addApproval('code-review', 2)
433 self.fake_gerrit.addEvent(A.addApproval('approved', 1))
434 self.waitUntilSettled()
435
436 self.assertEqual(A.data['status'], 'NEW')
Tobias Henkel9842bd72017-05-16 13:40:03 +0200437 self.assertEqual(A.reported, 1,
438 "A should report failure")
439 self.assertIn('not permitted to shadow', A.messages[0],
James E. Blairdb04e6a2017-05-03 14:49:36 -0700440 "A should have a syntax error reported")
441
James E. Blaird5656ad2017-06-02 14:29:41 -0700442 def test_untrusted_pipeline_error(self):
443 in_repo_conf = textwrap.dedent(
444 """
445 - pipeline:
446 name: test
447 """)
448
449 file_dict = {'.zuul.yaml': in_repo_conf}
450 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
451 files=file_dict)
452 A.addApproval('code-review', 2)
453 self.fake_gerrit.addEvent(A.addApproval('approved', 1))
454 self.waitUntilSettled()
455
456 self.assertEqual(A.data['status'], 'NEW')
457 self.assertEqual(A.reported, 1,
458 "A should report failure")
459 self.assertIn('Pipelines may not be defined', A.messages[0],
460 "A should have a syntax error reported")
461
462 def test_untrusted_project_error(self):
463 in_repo_conf = textwrap.dedent(
464 """
465 - project:
466 name: org/project1
467 """)
468
469 file_dict = {'.zuul.yaml': in_repo_conf}
470 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
471 files=file_dict)
472 A.addApproval('code-review', 2)
473 self.fake_gerrit.addEvent(A.addApproval('approved', 1))
474 self.waitUntilSettled()
475
476 self.assertEqual(A.data['status'], 'NEW')
477 self.assertEqual(A.reported, 1,
478 "A should report failure")
479 self.assertIn('the only project definition permitted', A.messages[0],
480 "A should have a syntax error reported")
481
James E. Blaire64b0e42017-06-08 11:23:34 -0700482 def test_duplicate_node_error(self):
483 in_repo_conf = textwrap.dedent(
484 """
485 - nodeset:
486 name: duplicate
487 nodes:
488 - name: compute
James E. Blair16d96a02017-06-08 11:32:56 -0700489 label: foo
James E. Blaire64b0e42017-06-08 11:23:34 -0700490 - name: compute
James E. Blair16d96a02017-06-08 11:32:56 -0700491 label: foo
James E. Blaire64b0e42017-06-08 11:23:34 -0700492 """)
493
494 file_dict = {'.zuul.yaml': in_repo_conf}
495 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
496 files=file_dict)
497 A.addApproval('code-review', 2)
498 self.fake_gerrit.addEvent(A.addApproval('approved', 1))
499 self.waitUntilSettled()
500
501 self.assertEqual(A.data['status'], 'NEW')
502 self.assertEqual(A.reported, 1,
503 "A should report failure")
504 self.assertIn('appears multiple times', A.messages[0],
505 "A should have a syntax error reported")
506
507 def test_duplicate_group_error(self):
508 in_repo_conf = textwrap.dedent(
509 """
510 - nodeset:
511 name: duplicate
512 nodes:
513 - name: compute
James E. Blair16d96a02017-06-08 11:32:56 -0700514 label: foo
James E. Blaire64b0e42017-06-08 11:23:34 -0700515 groups:
516 - name: group
517 nodes: compute
518 - name: group
519 nodes: compute
520 """)
521
522 file_dict = {'.zuul.yaml': in_repo_conf}
523 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
524 files=file_dict)
525 A.addApproval('code-review', 2)
526 self.fake_gerrit.addEvent(A.addApproval('approved', 1))
527 self.waitUntilSettled()
528
529 self.assertEqual(A.data['status'], 'NEW')
530 self.assertEqual(A.reported, 1,
531 "A should report failure")
532 self.assertIn('appears multiple times', A.messages[0],
533 "A should have a syntax error reported")
534
James E. Blair09f9ffe2017-07-11 15:30:25 -0700535 def test_multi_repo(self):
536 downstream_repo_conf = textwrap.dedent(
537 """
538 - project:
539 name: org/project1
540 tenant-one-gate:
541 jobs:
542 - project-test1
543
544 - job:
545 name: project1-test1
546 parent: project-test1
547 """)
548
549 file_dict = {'.zuul.yaml': downstream_repo_conf}
550 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A',
551 files=file_dict)
552 A.addApproval('code-review', 2)
553 self.fake_gerrit.addEvent(A.addApproval('approved', 1))
554 self.waitUntilSettled()
555
556 self.assertEqual(A.data['status'], 'MERGED')
557 self.fake_gerrit.addEvent(A.getChangeMergedEvent())
558 self.waitUntilSettled()
559
560 upstream_repo_conf = textwrap.dedent(
561 """
562 - job:
563 name: project-test1
564
565 - job:
566 name: project-test2
567
568 - project:
569 name: org/project
570 tenant-one-gate:
571 jobs:
572 - project-test1
573 """)
574
575 file_dict = {'.zuul.yaml': upstream_repo_conf}
576 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B',
577 files=file_dict)
578 B.addApproval('code-review', 2)
579 self.fake_gerrit.addEvent(B.addApproval('approved', 1))
580 self.waitUntilSettled()
581
582 self.assertEqual(B.data['status'], 'MERGED')
583 self.fake_gerrit.addEvent(B.getChangeMergedEvent())
584 self.waitUntilSettled()
585
586 tenant = self.sched.abide.tenants.get('tenant-one')
587 # Ensure the latest change is reflected in the config; if it
588 # isn't this will raise an exception.
589 tenant.layout.getJob('project-test2')
590
James E. Blairc73c73a2017-01-20 15:15:15 -0800591
592class TestAnsible(AnsibleZuulTestCase):
593 # A temporary class to hold new tests while others are disabled
594
595 tenant_config_file = 'config/ansible/main.yaml'
596
597 def test_playbook(self):
598 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
599 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
600 self.waitUntilSettled()
Tobias Henkel077f2f32017-05-30 20:16:46 +0200601 build_timeout = self.getJobFromHistory('timeout')
602 self.assertEqual(build_timeout.result, 'TIMED_OUT')
603 build_faillocal = self.getJobFromHistory('faillocal')
604 self.assertEqual(build_faillocal.result, 'FAILURE')
605 build_failpost = self.getJobFromHistory('failpost')
606 self.assertEqual(build_failpost.result, 'POST_FAILURE')
607 build_check_vars = self.getJobFromHistory('check-vars')
608 self.assertEqual(build_check_vars.result, 'SUCCESS')
609 build_hello = self.getJobFromHistory('hello-world')
610 self.assertEqual(build_hello.result, 'SUCCESS')
611 build_python27 = self.getJobFromHistory('python27')
612 self.assertEqual(build_python27.result, 'SUCCESS')
613 flag_path = os.path.join(self.test_root, build_python27.uuid + '.flag')
James E. Blaira92cbc82017-01-23 14:56:49 -0800614 self.assertTrue(os.path.exists(flag_path))
Tobias Henkel077f2f32017-05-30 20:16:46 +0200615 copied_path = os.path.join(self.test_root, build_python27.uuid +
Monty Taylorc231d932017-02-03 09:57:15 -0600616 '.copied')
617 self.assertTrue(os.path.exists(copied_path))
Tobias Henkel077f2f32017-05-30 20:16:46 +0200618 failed_path = os.path.join(self.test_root, build_python27.uuid +
Monty Taylorc231d932017-02-03 09:57:15 -0600619 '.failed')
620 self.assertFalse(os.path.exists(failed_path))
Tobias Henkel077f2f32017-05-30 20:16:46 +0200621 pre_flag_path = os.path.join(self.test_root, build_python27.uuid +
James E. Blair66b274e2017-01-31 14:47:52 -0800622 '.pre.flag')
623 self.assertTrue(os.path.exists(pre_flag_path))
Tobias Henkel077f2f32017-05-30 20:16:46 +0200624 post_flag_path = os.path.join(self.test_root, build_python27.uuid +
James E. Blair66b274e2017-01-31 14:47:52 -0800625 '.post.flag')
626 self.assertTrue(os.path.exists(post_flag_path))
James E. Blair5ac93842017-01-20 06:47:34 -0800627 bare_role_flag_path = os.path.join(self.test_root,
Tobias Henkel077f2f32017-05-30 20:16:46 +0200628 build_python27.uuid +
629 '.bare-role.flag')
James E. Blair5ac93842017-01-20 06:47:34 -0800630 self.assertTrue(os.path.exists(bare_role_flag_path))
James E. Blairb9c0d772017-03-03 14:34:49 -0800631
James E. Blair18f86a32017-03-15 14:43:26 -0700632 secrets_path = os.path.join(self.test_root,
Tobias Henkel077f2f32017-05-30 20:16:46 +0200633 build_python27.uuid + '.secrets')
James E. Blair18f86a32017-03-15 14:43:26 -0700634 with open(secrets_path) as f:
635 self.assertEqual(f.read(), "test-username test-password")
636
Tobias Henkel077f2f32017-05-30 20:16:46 +0200637 msg = A.messages[0]
638 success = "{} https://success.example.com/zuul-logs/{}"
639 fail = "{} https://failure.example.com/zuul-logs/{}"
640 self.assertIn(success.format("python27", build_python27.uuid), msg)
641 self.assertIn(fail.format("faillocal", build_faillocal.uuid), msg)
642 self.assertIn(success.format("check-vars", build_check_vars.uuid), msg)
643 self.assertIn(success.format("hello-world", build_hello.uuid), msg)
644 self.assertIn(fail.format("timeout", build_timeout.uuid), msg)
645 self.assertIn(fail.format("failpost", build_failpost.uuid), msg)
646
James E. Blairb9c0d772017-03-03 14:34:49 -0800647
James E. Blaira4d4eef2017-06-30 14:49:17 -0700648class TestPrePlaybooks(AnsibleZuulTestCase):
649 # A temporary class to hold new tests while others are disabled
650
651 tenant_config_file = 'config/pre-playbook/main.yaml'
652
653 def test_pre_playbook_fail(self):
654 # Test that we run the post playbooks (but not the actual
655 # playbook) when a pre-playbook fails.
656 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
657 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
658 self.waitUntilSettled()
659 build = self.getJobFromHistory('python27')
660 self.assertIsNone(build.result)
661 self.assertIn('RETRY_LIMIT', A.messages[0])
662 flag_path = os.path.join(self.test_root, build.uuid +
663 '.main.flag')
664 self.assertFalse(os.path.exists(flag_path))
665 pre_flag_path = os.path.join(self.test_root, build.uuid +
666 '.pre.flag')
667 self.assertFalse(os.path.exists(pre_flag_path))
668 post_flag_path = os.path.join(self.test_root, build.uuid +
669 '.post.flag')
James E. Blair21037782017-07-19 11:56:55 -0700670 self.assertTrue(os.path.exists(post_flag_path),
671 "The file %s should exist" % post_flag_path)
James E. Blaira4d4eef2017-06-30 14:49:17 -0700672
673
James E. Blairb9c0d772017-03-03 14:34:49 -0800674class TestBrokenConfig(ZuulTestCase):
675 # Test that we get an appropriate syntax error if we start with a
676 # broken config.
677
678 tenant_config_file = 'config/broken/main.yaml'
679
680 def setUp(self):
681 with testtools.ExpectedException(
682 zuul.configloader.ConfigurationSyntaxError,
683 "\nZuul encountered a syntax error"):
684 super(TestBrokenConfig, self).setUp()
685
686 def test_broken_config_on_startup(self):
687 pass
Ricardo Carrillo Cruz22994f92016-12-02 11:41:58 +0000688
689
690class TestProjectKeys(ZuulTestCase):
691 # Test that we can generate project keys
692
693 # Normally the test infrastructure copies a static key in place
694 # for each project before starting tests. This saves time because
695 # Zuul's automatic key-generation on startup can be slow. To make
696 # sure we exercise that code, in this test we allow Zuul to create
697 # keys for the project on startup.
698 create_project_keys = True
699 tenant_config_file = 'config/in-repo/main.yaml'
700
701 def test_key_generation(self):
702 key_root = os.path.join(self.state_root, 'keys')
703 private_key_file = os.path.join(key_root, 'gerrit/org/project.pem')
704 # Make sure that a proper key was created on startup
705 with open(private_key_file, "rb") as f:
James E. Blairbf1a4f22017-03-17 10:59:37 -0700706 private_key, public_key = \
707 encryption.deserialize_rsa_keypair(f.read())
Ricardo Carrillo Cruz22994f92016-12-02 11:41:58 +0000708
709 with open(os.path.join(FIXTURE_DIR, 'private.pem')) as i:
710 fixture_private_key = i.read()
711
712 # Make sure that we didn't just end up with the static fixture
713 # key
714 self.assertNotEqual(fixture_private_key, private_key)
715
716 # Make sure it's the right length
717 self.assertEqual(4096, private_key.key_size)
James E. Blairbce76932017-05-04 10:03:15 -0700718
719
James E. Blairbb94dfa2017-07-11 07:45:19 -0700720class RoleTestCase(ZuulTestCase):
James E. Blair1b27f6a2017-07-14 14:09:07 -0700721 def _assertRolePath(self, build, playbook, content):
722 path = os.path.join(self.test_root, build.uuid,
723 'ansible', playbook, 'ansible.cfg')
724 roles_paths = []
725 with open(path) as f:
726 for line in f:
727 if line.startswith('roles_path'):
728 roles_paths.append(line)
729 print(roles_paths)
730 if content:
731 self.assertEqual(len(roles_paths), 1,
732 "Should have one roles_path line in %s" %
733 (playbook,))
734 self.assertIn(content, roles_paths[0])
735 else:
736 self.assertEqual(len(roles_paths), 0,
737 "Should have no roles_path line in %s" %
738 (playbook,))
739
James E. Blairbb94dfa2017-07-11 07:45:19 -0700740
741class TestRoles(RoleTestCase):
742 tenant_config_file = 'config/roles/main.yaml'
743
James E. Blairbce76932017-05-04 10:03:15 -0700744 def test_role(self):
745 # This exercises a proposed change to a role being checked out
746 # and used.
747 A = self.fake_gerrit.addFakeChange('bare-role', 'master', 'A')
748 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
749 B.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
750 B.subject, A.data['id'])
751 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
752 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
753 self.waitUntilSettled()
754 self.assertHistory([
755 dict(name='project-test', result='SUCCESS', changes='1,1 2,1'),
756 ])
James E. Blair6459db12017-06-29 14:57:20 -0700757
James E. Blair1b27f6a2017-07-14 14:09:07 -0700758 def test_role_inheritance(self):
759 self.executor_server.hold_jobs_in_build = True
760 conf = textwrap.dedent(
761 """
762 - job:
763 name: parent
764 roles:
765 - zuul: bare-role
766 pre-run: playbooks/parent-pre
767 post-run: playbooks/parent-post
768
769 - job:
770 name: project-test
771 parent: parent
772 roles:
773 - zuul: org/project
774
775 - project:
776 name: org/project
777 check:
778 jobs:
779 - project-test
780 """)
781
782 file_dict = {'.zuul.yaml': conf}
783 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
784 files=file_dict)
785 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
786 self.waitUntilSettled()
787
788 self.assertEqual(len(self.builds), 1)
789 build = self.getBuildByName('project-test')
790 self._assertRolePath(build, 'pre_playbook_0', 'role_0')
791 self._assertRolePath(build, 'playbook_0', 'role_0')
792 self._assertRolePath(build, 'playbook_0', 'role_1')
793 self._assertRolePath(build, 'post_playbook_0', 'role_0')
794
795 self.executor_server.hold_jobs_in_build = False
796 self.executor_server.release()
797 self.waitUntilSettled()
798
799 self.assertHistory([
800 dict(name='project-test', result='SUCCESS', changes='1,1'),
801 ])
802
James E. Blair6f699732017-07-18 14:19:11 -0700803 def test_role_error(self):
804 conf = textwrap.dedent(
805 """
806 - job:
807 name: project-test
808 roles:
809 - zuul: common-config
810
811 - project:
812 name: org/project
813 check:
814 jobs:
815 - project-test
816 """)
817
818 file_dict = {'.zuul.yaml': conf}
819 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
820 files=file_dict)
821 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
822 self.waitUntilSettled()
823 self.assertIn(
824 '- project-test project-test : ERROR Unable to find role',
825 A.messages[-1])
826
James E. Blair6459db12017-06-29 14:57:20 -0700827
James E. Blairbb94dfa2017-07-11 07:45:19 -0700828class TestImplicitRoles(RoleTestCase):
829 tenant_config_file = 'config/implicit-roles/main.yaml'
830
831 def test_missing_roles(self):
832 # Test implicit and explicit roles for a project which does
833 # not have roles. The implicit role should be silently
834 # ignored since the project doesn't supply roles, but if a
835 # user declares an explicit role, it should error.
836 self.executor_server.hold_jobs_in_build = True
837 A = self.fake_gerrit.addFakeChange('org/norole-project', 'master', 'A')
838 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
839 self.waitUntilSettled()
840
841 self.assertEqual(len(self.builds), 2)
842 build = self.getBuildByName('implicit-role-fail')
843 self._assertRolePath(build, 'playbook_0', None)
844
845 self.executor_server.hold_jobs_in_build = False
846 self.executor_server.release()
847 self.waitUntilSettled()
848 # The retry_limit doesn't get recorded
849 self.assertHistory([
850 dict(name='implicit-role-fail', result='SUCCESS', changes='1,1'),
851 ])
852
853 def test_roles(self):
854 # Test implicit and explicit roles for a project which does
855 # have roles. In both cases, we should end up with the role
856 # in the path. In the explicit case, ensure we end up with
857 # the name we specified.
858 self.executor_server.hold_jobs_in_build = True
859 A = self.fake_gerrit.addFakeChange('org/role-project', 'master', 'A')
860 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
861 self.waitUntilSettled()
862
863 self.assertEqual(len(self.builds), 2)
864 build = self.getBuildByName('implicit-role-ok')
865 self._assertRolePath(build, 'playbook_0', 'role_0')
866
867 build = self.getBuildByName('explicit-role-ok')
868 self._assertRolePath(build, 'playbook_0', 'role_0')
869
870 self.executor_server.hold_jobs_in_build = False
871 self.executor_server.release()
872 self.waitUntilSettled()
873 self.assertHistory([
874 dict(name='implicit-role-ok', result='SUCCESS', changes='1,1'),
875 dict(name='explicit-role-ok', result='SUCCESS', changes='1,1'),
876 ], ordered=False)
877
878
James E. Blair6459db12017-06-29 14:57:20 -0700879class TestShadow(ZuulTestCase):
880 tenant_config_file = 'config/shadow/main.yaml'
881
882 def test_shadow(self):
883 # Test that a repo is allowed to shadow another's job definitions.
884 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
885 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
886 self.waitUntilSettled()
887 self.assertHistory([
888 dict(name='test1', result='SUCCESS', changes='1,1'),
889 dict(name='test2', result='SUCCESS', changes='1,1'),
James E. Blairadafa6c2017-07-12 08:50:56 -0700890 ], ordered=False)
James E. Blair196f61a2017-06-30 15:42:29 -0700891
892
893class TestDataReturn(AnsibleZuulTestCase):
894 tenant_config_file = 'config/data-return/main.yaml'
895
896 def test_data_return(self):
897 # This exercises a proposed change to a role being checked out
898 # and used.
899 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
900 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
901 self.waitUntilSettled()
902 self.assertHistory([
903 dict(name='data-return', result='SUCCESS', changes='1,1'),
James E. Blair88e79c02017-07-07 13:36:54 -0700904 dict(name='data-return-relative', result='SUCCESS', changes='1,1'),
905 ], ordered=False)
906 self.assertIn('- data-return http://example.com/test/log/url/',
907 A.messages[-1])
908 self.assertIn('- data-return-relative '
909 'http://example.com/test/log/url/docs/index.html',
James E. Blair196f61a2017-06-30 15:42:29 -0700910 A.messages[-1])