blob: c6813058866e067d5f4624099dd75ac40b998c1e [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. Blair59fdbac2015-12-07 17:08:06 -080020
James E. Blairb9c0d772017-03-03 14:34:49 -080021import testtools
22
23import zuul.configloader
James E. Blairbf1a4f22017-03-17 10:59:37 -070024from zuul.lib import encryption
Ricardo Carrillo Cruz22994f92016-12-02 11:41:58 +000025from tests.base import AnsibleZuulTestCase, ZuulTestCase, FIXTURE_DIR
James E. Blair59fdbac2015-12-07 17:08:06 -080026
James E. Blair59fdbac2015-12-07 17:08:06 -080027
James E. Blair3f876d52016-07-22 13:07:14 -070028class TestMultipleTenants(AnsibleZuulTestCase):
James E. Blair59fdbac2015-12-07 17:08:06 -080029 # A temporary class to hold new tests while others are disabled
30
James E. Blair2a629ec2015-12-22 15:32:02 -080031 tenant_config_file = 'config/multi-tenant/main.yaml'
James E. Blair59fdbac2015-12-07 17:08:06 -080032
James E. Blair83005782015-12-11 14:46:03 -080033 def test_multiple_tenants(self):
James E. Blair96f26942015-12-09 10:15:59 -080034 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A')
Tobias Henkelbf24fd12017-07-27 06:13:07 +020035 A.addApproval('Code-Review', 2)
36 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
James E. Blair59fdbac2015-12-07 17:08:06 -080037 self.waitUntilSettled()
James E. Blair96f26942015-12-09 10:15:59 -080038 self.assertEqual(self.getJobFromHistory('project1-test1').result,
James E. Blair59fdbac2015-12-07 17:08:06 -080039 'SUCCESS')
James E. Blair96c6bf82016-01-15 16:20:40 -080040 self.assertEqual(self.getJobFromHistory('python27').result,
41 'SUCCESS')
James E. Blair59fdbac2015-12-07 17:08:06 -080042 self.assertEqual(A.data['status'], 'MERGED')
James E. Blair96f26942015-12-09 10:15:59 -080043 self.assertEqual(A.reported, 2,
44 "A should report start and success")
45 self.assertIn('tenant-one-gate', A.messages[1],
46 "A should transit tenant-one gate")
47 self.assertNotIn('tenant-two-gate', A.messages[1],
48 "A should *not* transit tenant-two gate")
James E. Blair59fdbac2015-12-07 17:08:06 -080049
James E. Blair96f26942015-12-09 10:15:59 -080050 B = self.fake_gerrit.addFakeChange('org/project2', 'master', 'B')
Tobias Henkelbf24fd12017-07-27 06:13:07 +020051 B.addApproval('Code-Review', 2)
52 self.fake_gerrit.addEvent(B.addApproval('Approved', 1))
James E. Blair96f26942015-12-09 10:15:59 -080053 self.waitUntilSettled()
James E. Blair96c6bf82016-01-15 16:20:40 -080054 self.assertEqual(self.getJobFromHistory('python27',
55 'org/project2').result,
56 'SUCCESS')
James E. Blair96f26942015-12-09 10:15:59 -080057 self.assertEqual(self.getJobFromHistory('project2-test1').result,
58 'SUCCESS')
59 self.assertEqual(B.data['status'], 'MERGED')
60 self.assertEqual(B.reported, 2,
61 "B should report start and success")
62 self.assertIn('tenant-two-gate', B.messages[1],
63 "B should transit tenant-two gate")
64 self.assertNotIn('tenant-one-gate', B.messages[1],
65 "B should *not* transit tenant-one gate")
James E. Blair59fdbac2015-12-07 17:08:06 -080066
James E. Blair96f26942015-12-09 10:15:59 -080067 self.assertEqual(A.reported, 2, "Activity in tenant two should"
68 "not affect tenant one")
James E. Blair14abdf42015-12-09 16:11:53 -080069
James E. Blair83005782015-12-11 14:46:03 -080070
Tobias Henkel83167622017-06-30 19:45:03 +020071class TestFinal(ZuulTestCase):
72
73 tenant_config_file = 'config/final/main.yaml'
74
75 def test_final_variant_ok(self):
76 # test clean usage of final parent job
77 in_repo_conf = textwrap.dedent(
78 """
79 - project:
80 name: org/project
81 check:
82 jobs:
83 - job-final
84 """)
85
86 file_dict = {'.zuul.yaml': in_repo_conf}
87 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
88 files=file_dict)
89 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
90 self.waitUntilSettled()
91
92 self.assertEqual(A.reported, 1)
93 self.assertEqual(A.patchsets[-1]['approvals'][0]['value'], '1')
94
95 def test_final_variant_error(self):
96 # test misuse of final parent job
97 in_repo_conf = textwrap.dedent(
98 """
99 - project:
100 name: org/project
101 check:
102 jobs:
103 - job-final:
104 vars:
105 dont_override_this: bar
106 """)
107 file_dict = {'.zuul.yaml': in_repo_conf}
108 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
109 files=file_dict)
110 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
111 self.waitUntilSettled()
112
113 # The second patch tried to override some variables.
114 # Thus it should fail.
115 self.assertEqual(A.reported, 1)
116 self.assertEqual(A.patchsets[-1]['approvals'][0]['value'], '-1')
117 self.assertIn('Unable to modify final job', A.messages[0])
118
119 def test_final_inheritance(self):
120 # test misuse of final parent job
121 in_repo_conf = textwrap.dedent(
122 """
123 - job:
124 name: project-test
125 parent: job-final
126
127 - project:
128 name: org/project
129 check:
130 jobs:
131 - project-test
132 """)
133
134 in_repo_playbook = textwrap.dedent(
135 """
136 - hosts: all
137 tasks: []
138 """)
139
140 file_dict = {'.zuul.yaml': in_repo_conf,
141 'playbooks/project-test.yaml': in_repo_playbook}
142 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
143 files=file_dict)
144 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
145 self.waitUntilSettled()
146
147 # The second patch tried to override some variables.
148 # Thus it should fail.
149 self.assertEqual(A.reported, 1)
150 self.assertEqual(A.patchsets[-1]['approvals'][0]['value'], '-1')
151 self.assertIn('Unable to inherit from final job', A.messages[0])
152
153
James E. Blairff555742017-02-19 11:34:27 -0800154class TestInRepoConfig(ZuulTestCase):
James E. Blair83005782015-12-11 14:46:03 -0800155 # A temporary class to hold new tests while others are disabled
156
Tobias Henkelabf973e2017-07-28 10:07:34 +0200157 config_file = 'zuul-connections-gerrit-and-github.conf'
James E. Blair2a629ec2015-12-22 15:32:02 -0800158 tenant_config_file = 'config/in-repo/main.yaml'
James E. Blair83005782015-12-11 14:46:03 -0800159
James E. Blair83005782015-12-11 14:46:03 -0800160 def test_in_repo_config(self):
James E. Blair14abdf42015-12-09 16:11:53 -0800161 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
Tobias Henkelbf24fd12017-07-27 06:13:07 +0200162 A.addApproval('Code-Review', 2)
163 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
James E. Blair14abdf42015-12-09 16:11:53 -0800164 self.waitUntilSettled()
165 self.assertEqual(self.getJobFromHistory('project-test1').result,
166 'SUCCESS')
167 self.assertEqual(A.data['status'], 'MERGED')
168 self.assertEqual(A.reported, 2,
169 "A should report start and success")
170 self.assertIn('tenant-one-gate', A.messages[1],
171 "A should transit tenant-one gate")
James E. Blairb97ed802015-12-21 15:55:35 -0800172
James E. Blair8b1dc3f2016-07-05 16:49:00 -0700173 def test_dynamic_config(self):
174 in_repo_conf = textwrap.dedent(
175 """
176 - job:
Tobias Henkelf02cf512017-07-21 22:55:34 +0200177 name: project-test1
178
179 - job:
James E. Blair8b1dc3f2016-07-05 16:49:00 -0700180 name: project-test2
181
182 - project:
183 name: org/project
184 tenant-one-gate:
185 jobs:
186 - project-test2
187 """)
188
James E. Blairc73c73a2017-01-20 15:15:15 -0800189 in_repo_playbook = textwrap.dedent(
190 """
191 - hosts: all
192 tasks: []
193 """)
194
195 file_dict = {'.zuul.yaml': in_repo_conf,
196 'playbooks/project-test2.yaml': in_repo_playbook}
James E. Blair8b1dc3f2016-07-05 16:49:00 -0700197 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
James E. Blairc73c73a2017-01-20 15:15:15 -0800198 files=file_dict)
Tobias Henkelbf24fd12017-07-27 06:13:07 +0200199 A.addApproval('Code-Review', 2)
200 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
James E. Blair8b1dc3f2016-07-05 16:49:00 -0700201 self.waitUntilSettled()
James E. Blair8b1dc3f2016-07-05 16:49:00 -0700202 self.assertEqual(A.data['status'], 'MERGED')
203 self.assertEqual(A.reported, 2,
204 "A should report start and success")
205 self.assertIn('tenant-one-gate', A.messages[1],
206 "A should transit tenant-one gate")
James E. Blair646322f2017-01-27 15:50:34 -0800207 self.assertHistory([
208 dict(name='project-test2', result='SUCCESS', changes='1,1')])
209
James E. Blairc2a5ed72017-02-20 14:12:01 -0500210 self.fake_gerrit.addEvent(A.getChangeMergedEvent())
James E. Blair7bbd7a32017-03-06 11:36:13 -0800211 self.waitUntilSettled()
James E. Blairc2a5ed72017-02-20 14:12:01 -0500212
James E. Blair646322f2017-01-27 15:50:34 -0800213 # Now that the config change is landed, it should be live for
214 # subsequent changes.
215 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
Tobias Henkelbf24fd12017-07-27 06:13:07 +0200216 B.addApproval('Code-Review', 2)
217 self.fake_gerrit.addEvent(B.addApproval('Approved', 1))
James E. Blair646322f2017-01-27 15:50:34 -0800218 self.waitUntilSettled()
219 self.assertEqual(self.getJobFromHistory('project-test2').result,
220 'SUCCESS')
221 self.assertHistory([
222 dict(name='project-test2', result='SUCCESS', changes='1,1'),
223 dict(name='project-test2', result='SUCCESS', changes='2,1')])
James E. Blairc73c73a2017-01-20 15:15:15 -0800224
Tobias Henkelf02cf512017-07-21 22:55:34 +0200225 def test_dynamic_config_non_existing_job(self):
226 """Test that requesting a non existent job fails"""
227 in_repo_conf = textwrap.dedent(
228 """
229 - job:
230 name: project-test1
231
232 - project:
233 name: org/project
234 check:
235 jobs:
236 - non-existent-job
237 """)
238
239 in_repo_playbook = textwrap.dedent(
240 """
241 - hosts: all
242 tasks: []
243 """)
244
245 file_dict = {'.zuul.yaml': in_repo_conf,
246 'playbooks/project-test2.yaml': in_repo_playbook}
247 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
248 files=file_dict)
249 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
250 self.waitUntilSettled()
251 self.assertEqual(A.reported, 1,
252 "A should report failure")
253 self.assertEqual(A.patchsets[0]['approvals'][0]['value'], "-1")
254 self.assertIn('Job non-existent-job not defined', A.messages[0],
255 "A should have failed the check pipeline")
256 self.assertHistory([])
257
258 def test_dynamic_config_non_existing_job_in_template(self):
259 """Test that requesting a non existent job fails"""
260 in_repo_conf = textwrap.dedent(
261 """
262 - job:
263 name: project-test1
264
265 - project-template:
266 name: test-template
267 check:
268 jobs:
269 - non-existent-job
270
271 - project:
272 name: org/project
273 templates:
274 - test-template
275 """)
276
277 in_repo_playbook = textwrap.dedent(
278 """
279 - hosts: all
280 tasks: []
281 """)
282
283 file_dict = {'.zuul.yaml': in_repo_conf,
284 'playbooks/project-test2.yaml': in_repo_playbook}
285 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
286 files=file_dict)
287 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
288 self.waitUntilSettled()
289 self.assertEqual(A.reported, 1,
290 "A should report failure")
291 self.assertEqual(A.patchsets[0]['approvals'][0]['value'], "-1")
292 self.assertIn('Job non-existent-job not defined', A.messages[0],
293 "A should have failed the check pipeline")
294 self.assertHistory([])
295
Tobias Henkel0f714002017-06-30 23:30:52 +0200296 def test_dynamic_config_new_patchset(self):
297 self.executor_server.hold_jobs_in_build = True
298
299 tenant = self.sched.abide.tenants.get('tenant-one')
300 check_pipeline = tenant.layout.pipelines['check']
301
302 in_repo_conf = textwrap.dedent(
303 """
304 - job:
Tobias Henkelf02cf512017-07-21 22:55:34 +0200305 name: project-test1
306
307 - job:
Tobias Henkel0f714002017-06-30 23:30:52 +0200308 name: project-test2
309
310 - project:
311 name: org/project
312 check:
313 jobs:
314 - project-test2
315 """)
316
317 in_repo_playbook = textwrap.dedent(
318 """
319 - hosts: all
320 tasks: []
321 """)
322
323 file_dict = {'.zuul.yaml': in_repo_conf,
324 'playbooks/project-test2.yaml': in_repo_playbook}
325 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
326 files=file_dict)
327 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
328 self.waitUntilSettled()
329
330 items = check_pipeline.getAllItems()
331 self.assertEqual(items[0].change.number, '1')
332 self.assertEqual(items[0].change.patchset, '1')
333 self.assertTrue(items[0].live)
334
335 in_repo_conf = textwrap.dedent(
336 """
337 - job:
Tobias Henkel0ce7ec62017-07-21 22:50:17 +0200338 name: project-test1
339
340 - job:
Tobias Henkel0f714002017-06-30 23:30:52 +0200341 name: project-test2
342
343 - project:
344 name: org/project
345 check:
346 jobs:
347 - project-test1
348 - project-test2
349 """)
350 file_dict = {'.zuul.yaml': in_repo_conf,
351 'playbooks/project-test2.yaml': in_repo_playbook}
352
353 A.addPatchset(files=file_dict)
354 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(2))
355
356 self.waitUntilSettled()
357
358 items = check_pipeline.getAllItems()
359 self.assertEqual(items[0].change.number, '1')
360 self.assertEqual(items[0].change.patchset, '2')
361 self.assertTrue(items[0].live)
362
363 self.executor_server.hold_jobs_in_build = False
Tobias Henkel0ce7ec62017-07-21 22:50:17 +0200364 self.executor_server.release('project-test1')
365 self.waitUntilSettled()
Tobias Henkel0f714002017-06-30 23:30:52 +0200366 self.executor_server.release()
367 self.waitUntilSettled()
368
Tobias Henkel0ce7ec62017-07-21 22:50:17 +0200369 self.assertHistory([
370 dict(name='project-test2', result='ABORTED', changes='1,1'),
371 dict(name='project-test1', result='SUCCESS', changes='1,2'),
372 dict(name='project-test2', result='SUCCESS', changes='1,2')])
373
Jesse Keating78f544a2017-07-13 14:27:40 -0700374 def test_dynamic_dependent_pipeline(self):
375 # Test dynamically adding a project to a
376 # dependent pipeline for the first time
377 self.executor_server.hold_jobs_in_build = True
378
379 tenant = self.sched.abide.tenants.get('tenant-one')
380 gate_pipeline = tenant.layout.pipelines['gate']
381
382 in_repo_conf = textwrap.dedent(
383 """
384 - job:
Tobias Henkelf02cf512017-07-21 22:55:34 +0200385 name: project-test1
386
387 - job:
Jesse Keating78f544a2017-07-13 14:27:40 -0700388 name: project-test2
389
390 - project:
391 name: org/project
392 gate:
393 jobs:
394 - project-test2
395 """)
396
397 in_repo_playbook = textwrap.dedent(
398 """
399 - hosts: all
400 tasks: []
401 """)
402
403 file_dict = {'.zuul.yaml': in_repo_conf,
404 'playbooks/project-test2.yaml': in_repo_playbook}
405 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
406 files=file_dict)
Tobias Henkelbf24fd12017-07-27 06:13:07 +0200407 A.addApproval('Approved', 1)
408 self.fake_gerrit.addEvent(A.addApproval('Code-Review', 2))
Jesse Keating78f544a2017-07-13 14:27:40 -0700409 self.waitUntilSettled()
410
411 items = gate_pipeline.getAllItems()
412 self.assertEqual(items[0].change.number, '1')
413 self.assertEqual(items[0].change.patchset, '1')
414 self.assertTrue(items[0].live)
415
416 self.executor_server.hold_jobs_in_build = False
417 self.executor_server.release()
418 self.waitUntilSettled()
419
420 # Make sure the dynamic queue got cleaned up
421 self.assertEqual(gate_pipeline.queues, [])
422
James E. Blairff555742017-02-19 11:34:27 -0800423 def test_in_repo_branch(self):
424 in_repo_conf = textwrap.dedent(
425 """
426 - job:
Tobias Henkelf02cf512017-07-21 22:55:34 +0200427 name: project-test1
428
429 - job:
James E. Blairff555742017-02-19 11:34:27 -0800430 name: project-test2
431
432 - project:
433 name: org/project
434 tenant-one-gate:
435 jobs:
436 - project-test2
437 """)
438
439 in_repo_playbook = textwrap.dedent(
440 """
441 - hosts: all
442 tasks: []
443 """)
444
445 file_dict = {'.zuul.yaml': in_repo_conf,
446 'playbooks/project-test2.yaml': in_repo_playbook}
447 self.create_branch('org/project', 'stable')
James E. Blair72facdc2017-08-17 10:29:12 -0700448 self.fake_gerrit.addEvent(
449 self.fake_gerrit.getFakeBranchCreatedEvent(
450 'org/project', 'stable'))
James E. Blairff555742017-02-19 11:34:27 -0800451 A = self.fake_gerrit.addFakeChange('org/project', 'stable', 'A',
452 files=file_dict)
Tobias Henkelbf24fd12017-07-27 06:13:07 +0200453 A.addApproval('Code-Review', 2)
454 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
James E. Blairff555742017-02-19 11:34:27 -0800455 self.waitUntilSettled()
456 self.assertEqual(A.data['status'], 'MERGED')
457 self.assertEqual(A.reported, 2,
458 "A should report start and success")
459 self.assertIn('tenant-one-gate', A.messages[1],
460 "A should transit tenant-one gate")
461 self.assertHistory([
462 dict(name='project-test2', result='SUCCESS', changes='1,1')])
463 self.fake_gerrit.addEvent(A.getChangeMergedEvent())
James E. Blair7bbd7a32017-03-06 11:36:13 -0800464 self.waitUntilSettled()
James E. Blairff555742017-02-19 11:34:27 -0800465
466 # The config change should not affect master.
467 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
Tobias Henkelbf24fd12017-07-27 06:13:07 +0200468 B.addApproval('Code-Review', 2)
469 self.fake_gerrit.addEvent(B.addApproval('Approved', 1))
James E. Blairff555742017-02-19 11:34:27 -0800470 self.waitUntilSettled()
471 self.assertHistory([
472 dict(name='project-test2', result='SUCCESS', changes='1,1'),
473 dict(name='project-test1', result='SUCCESS', changes='2,1')])
474
475 # The config change should be live for further changes on
476 # stable.
477 C = self.fake_gerrit.addFakeChange('org/project', 'stable', 'C')
Tobias Henkelbf24fd12017-07-27 06:13:07 +0200478 C.addApproval('Code-Review', 2)
479 self.fake_gerrit.addEvent(C.addApproval('Approved', 1))
James E. Blairff555742017-02-19 11:34:27 -0800480 self.waitUntilSettled()
481 self.assertHistory([
482 dict(name='project-test2', result='SUCCESS', changes='1,1'),
483 dict(name='project-test1', result='SUCCESS', changes='2,1'),
484 dict(name='project-test2', result='SUCCESS', changes='3,1')])
485
James E. Blaira5a12492017-05-03 11:40:48 -0700486 def test_crd_dynamic_config_branch(self):
487 # Test that we can create a job in one repo and be able to use
488 # it from a different branch on a different repo.
489
490 self.create_branch('org/project1', 'stable')
James E. Blair72facdc2017-08-17 10:29:12 -0700491 self.fake_gerrit.addEvent(
492 self.fake_gerrit.getFakeBranchCreatedEvent(
493 'org/project1', 'stable'))
James E. Blaira5a12492017-05-03 11:40:48 -0700494
495 in_repo_conf = textwrap.dedent(
496 """
497 - job:
Tobias Henkelf02cf512017-07-21 22:55:34 +0200498 name: project-test1
499
500 - job:
James E. Blaira5a12492017-05-03 11:40:48 -0700501 name: project-test2
502
503 - project:
504 name: org/project
505 check:
506 jobs:
507 - project-test2
508 """)
509
510 in_repo_playbook = textwrap.dedent(
511 """
512 - hosts: all
513 tasks: []
514 """)
515
516 file_dict = {'.zuul.yaml': in_repo_conf,
517 'playbooks/project-test2.yaml': in_repo_playbook}
518 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
519 files=file_dict)
520
521 second_repo_conf = textwrap.dedent(
522 """
523 - project:
524 name: org/project1
525 check:
526 jobs:
527 - project-test2
528 """)
529
530 second_file_dict = {'.zuul.yaml': second_repo_conf}
531 B = self.fake_gerrit.addFakeChange('org/project1', 'stable', 'B',
532 files=second_file_dict)
533 B.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
534 B.subject, A.data['id'])
535
536 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
537 self.waitUntilSettled()
538 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
539 self.waitUntilSettled()
540
541 self.assertEqual(A.reported, 1, "A should report")
542 self.assertHistory([
543 dict(name='project-test2', result='SUCCESS', changes='1,1'),
544 dict(name='project-test2', result='SUCCESS', changes='1,1 2,1'),
545 ])
546
James E. Blair149b69c2017-03-02 10:48:16 -0800547 def test_untrusted_syntax_error(self):
James E. Blaire53250c2017-03-01 14:34:36 -0800548 in_repo_conf = textwrap.dedent(
549 """
550 - job:
551 name: project-test2
552 foo: error
553 """)
554
555 file_dict = {'.zuul.yaml': in_repo_conf}
556 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
557 files=file_dict)
Tobias Henkelbf24fd12017-07-27 06:13:07 +0200558 A.addApproval('Code-Review', 2)
559 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
James E. Blaire53250c2017-03-01 14:34:36 -0800560 self.waitUntilSettled()
561
562 self.assertEqual(A.data['status'], 'NEW')
Tobias Henkel9842bd72017-05-16 13:40:03 +0200563 self.assertEqual(A.reported, 1,
564 "A should report failure")
565 self.assertIn('syntax error', A.messages[0],
James E. Blaire53250c2017-03-01 14:34:36 -0800566 "A should have a syntax error reported")
567
James E. Blair149b69c2017-03-02 10:48:16 -0800568 def test_trusted_syntax_error(self):
569 in_repo_conf = textwrap.dedent(
570 """
571 - job:
572 name: project-test2
573 foo: error
574 """)
575
576 file_dict = {'zuul.yaml': in_repo_conf}
577 A = self.fake_gerrit.addFakeChange('common-config', 'master', 'A',
578 files=file_dict)
Tobias Henkelbf24fd12017-07-27 06:13:07 +0200579 A.addApproval('Code-Review', 2)
580 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
James E. Blair149b69c2017-03-02 10:48:16 -0800581 self.waitUntilSettled()
582
583 self.assertEqual(A.data['status'], 'NEW')
Tobias Henkel9842bd72017-05-16 13:40:03 +0200584 self.assertEqual(A.reported, 1,
585 "A should report failure")
586 self.assertIn('syntax error', A.messages[0],
James E. Blair149b69c2017-03-02 10:48:16 -0800587 "A should have a syntax error reported")
588
James E. Blair6f140c72017-03-03 10:32:07 -0800589 def test_untrusted_yaml_error(self):
590 in_repo_conf = textwrap.dedent(
591 """
592 - job:
593 foo: error
594 """)
595
596 file_dict = {'.zuul.yaml': in_repo_conf}
597 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
598 files=file_dict)
Tobias Henkelbf24fd12017-07-27 06:13:07 +0200599 A.addApproval('Code-Review', 2)
600 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
James E. Blair6f140c72017-03-03 10:32:07 -0800601 self.waitUntilSettled()
602
603 self.assertEqual(A.data['status'], 'NEW')
Tobias Henkel9842bd72017-05-16 13:40:03 +0200604 self.assertEqual(A.reported, 1,
605 "A should report failure")
606 self.assertIn('syntax error', A.messages[0],
James E. Blair6f140c72017-03-03 10:32:07 -0800607 "A should have a syntax error reported")
608
James E. Blairdb04e6a2017-05-03 14:49:36 -0700609 def test_untrusted_shadow_error(self):
610 in_repo_conf = textwrap.dedent(
611 """
612 - job:
613 name: common-config-test
614 """)
615
616 file_dict = {'.zuul.yaml': in_repo_conf}
617 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
618 files=file_dict)
Tobias Henkelbf24fd12017-07-27 06:13:07 +0200619 A.addApproval('Code-Review', 2)
620 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
James E. Blairdb04e6a2017-05-03 14:49:36 -0700621 self.waitUntilSettled()
622
623 self.assertEqual(A.data['status'], 'NEW')
Tobias Henkel9842bd72017-05-16 13:40:03 +0200624 self.assertEqual(A.reported, 1,
625 "A should report failure")
626 self.assertIn('not permitted to shadow', A.messages[0],
James E. Blairdb04e6a2017-05-03 14:49:36 -0700627 "A should have a syntax error reported")
628
James E. Blaird5656ad2017-06-02 14:29:41 -0700629 def test_untrusted_pipeline_error(self):
630 in_repo_conf = textwrap.dedent(
631 """
632 - pipeline:
633 name: test
634 """)
635
636 file_dict = {'.zuul.yaml': in_repo_conf}
637 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
638 files=file_dict)
Tobias Henkelbf24fd12017-07-27 06:13:07 +0200639 A.addApproval('Code-Review', 2)
640 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
James E. Blaird5656ad2017-06-02 14:29:41 -0700641 self.waitUntilSettled()
642
643 self.assertEqual(A.data['status'], 'NEW')
644 self.assertEqual(A.reported, 1,
645 "A should report failure")
646 self.assertIn('Pipelines may not be defined', A.messages[0],
647 "A should have a syntax error reported")
648
649 def test_untrusted_project_error(self):
650 in_repo_conf = textwrap.dedent(
651 """
652 - project:
653 name: org/project1
654 """)
655
656 file_dict = {'.zuul.yaml': in_repo_conf}
657 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
658 files=file_dict)
Tobias Henkelbf24fd12017-07-27 06:13:07 +0200659 A.addApproval('Code-Review', 2)
660 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
James E. Blaird5656ad2017-06-02 14:29:41 -0700661 self.waitUntilSettled()
662
663 self.assertEqual(A.data['status'], 'NEW')
664 self.assertEqual(A.reported, 1,
665 "A should report failure")
666 self.assertIn('the only project definition permitted', A.messages[0],
667 "A should have a syntax error reported")
668
James E. Blaire64b0e42017-06-08 11:23:34 -0700669 def test_duplicate_node_error(self):
670 in_repo_conf = textwrap.dedent(
671 """
672 - nodeset:
673 name: duplicate
674 nodes:
675 - name: compute
James E. Blair16d96a02017-06-08 11:32:56 -0700676 label: foo
James E. Blaire64b0e42017-06-08 11:23:34 -0700677 - name: compute
James E. Blair16d96a02017-06-08 11:32:56 -0700678 label: foo
James E. Blaire64b0e42017-06-08 11:23:34 -0700679 """)
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. Blaire64b0e42017-06-08 11:23:34 -0700686 self.waitUntilSettled()
687
688 self.assertEqual(A.data['status'], 'NEW')
689 self.assertEqual(A.reported, 1,
690 "A should report failure")
691 self.assertIn('appears multiple times', A.messages[0],
692 "A should have a syntax error reported")
693
694 def test_duplicate_group_error(self):
695 in_repo_conf = textwrap.dedent(
696 """
697 - nodeset:
698 name: duplicate
699 nodes:
700 - name: compute
James E. Blair16d96a02017-06-08 11:32:56 -0700701 label: foo
James E. Blaire64b0e42017-06-08 11:23:34 -0700702 groups:
703 - name: group
704 nodes: compute
705 - name: group
706 nodes: compute
707 """)
708
709 file_dict = {'.zuul.yaml': in_repo_conf}
710 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
711 files=file_dict)
Tobias Henkelbf24fd12017-07-27 06:13:07 +0200712 A.addApproval('Code-Review', 2)
713 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
James E. Blaire64b0e42017-06-08 11:23:34 -0700714 self.waitUntilSettled()
715
716 self.assertEqual(A.data['status'], 'NEW')
717 self.assertEqual(A.reported, 1,
718 "A should report failure")
719 self.assertIn('appears multiple times', A.messages[0],
720 "A should have a syntax error reported")
721
James E. Blair09f9ffe2017-07-11 15:30:25 -0700722 def test_multi_repo(self):
723 downstream_repo_conf = textwrap.dedent(
724 """
725 - project:
726 name: org/project1
727 tenant-one-gate:
728 jobs:
729 - project-test1
730
731 - job:
732 name: project1-test1
733 parent: project-test1
734 """)
735
736 file_dict = {'.zuul.yaml': downstream_repo_conf}
737 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A',
738 files=file_dict)
Tobias Henkelbf24fd12017-07-27 06:13:07 +0200739 A.addApproval('Code-Review', 2)
740 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
James E. Blair09f9ffe2017-07-11 15:30:25 -0700741 self.waitUntilSettled()
742
743 self.assertEqual(A.data['status'], 'MERGED')
744 self.fake_gerrit.addEvent(A.getChangeMergedEvent())
745 self.waitUntilSettled()
746
747 upstream_repo_conf = textwrap.dedent(
748 """
749 - job:
750 name: project-test1
751
752 - job:
753 name: project-test2
754
755 - project:
756 name: org/project
757 tenant-one-gate:
758 jobs:
759 - project-test1
760 """)
761
762 file_dict = {'.zuul.yaml': upstream_repo_conf}
763 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B',
764 files=file_dict)
Tobias Henkelbf24fd12017-07-27 06:13:07 +0200765 B.addApproval('Code-Review', 2)
766 self.fake_gerrit.addEvent(B.addApproval('Approved', 1))
James E. Blair09f9ffe2017-07-11 15:30:25 -0700767 self.waitUntilSettled()
768
769 self.assertEqual(B.data['status'], 'MERGED')
770 self.fake_gerrit.addEvent(B.getChangeMergedEvent())
771 self.waitUntilSettled()
772
773 tenant = self.sched.abide.tenants.get('tenant-one')
774 # Ensure the latest change is reflected in the config; if it
775 # isn't this will raise an exception.
776 tenant.layout.getJob('project-test2')
777
James E. Blair332636e2017-09-05 10:14:35 -0700778 def test_pipeline_error(self):
779 with open(os.path.join(FIXTURE_DIR,
780 'config/in-repo/git/',
781 'common-config/zuul.yaml')) as f:
782 base_common_config = f.read()
783
784 in_repo_conf_A = textwrap.dedent(
785 """
786 - pipeline:
787 name: periodic
788 foo: error
789 """)
790
791 file_dict = {'zuul.yaml': None,
792 'zuul.d/main.yaml': base_common_config,
793 'zuul.d/test1.yaml': in_repo_conf_A}
794 A = self.fake_gerrit.addFakeChange('common-config', 'master', 'A',
795 files=file_dict)
796 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
797 self.waitUntilSettled()
798 self.assertEqual(A.reported, 1,
799 "A should report failure")
800 self.assertIn('syntax error',
801 A.messages[0],
802 "A should have an error reported")
803
804 def test_change_series_error(self):
805 with open(os.path.join(FIXTURE_DIR,
806 'config/in-repo/git/',
807 'common-config/zuul.yaml')) as f:
808 base_common_config = f.read()
809
810 in_repo_conf_A = textwrap.dedent(
811 """
812 - pipeline:
813 name: periodic
814 foo: error
815 """)
816
817 file_dict = {'zuul.yaml': None,
818 'zuul.d/main.yaml': base_common_config,
819 'zuul.d/test1.yaml': in_repo_conf_A}
820 A = self.fake_gerrit.addFakeChange('common-config', 'master', 'A',
821 files=file_dict)
822
823 in_repo_conf_B = textwrap.dedent(
824 """
825 - job:
826 name: project-test2
827 foo: error
828 """)
829
830 file_dict = {'zuul.yaml': None,
831 'zuul.d/main.yaml': base_common_config,
832 'zuul.d/test1.yaml': in_repo_conf_A,
833 'zuul.d/test2.yaml': in_repo_conf_B}
834 B = self.fake_gerrit.addFakeChange('common-config', 'master', 'B',
835 files=file_dict)
836 B.setDependsOn(A, 1)
837 C = self.fake_gerrit.addFakeChange('common-config', 'master', 'C')
838 C.setDependsOn(B, 1)
839 self.fake_gerrit.addEvent(C.getPatchsetCreatedEvent(1))
840 self.waitUntilSettled()
841
842 self.assertEqual(C.reported, 1,
843 "C should report failure")
844 self.assertIn('depends on a change that failed to merge',
845 C.messages[0],
846 "C should have an error reported")
847
James E. Blairc73c73a2017-01-20 15:15:15 -0800848
849class TestAnsible(AnsibleZuulTestCase):
850 # A temporary class to hold new tests while others are disabled
851
852 tenant_config_file = 'config/ansible/main.yaml'
853
854 def test_playbook(self):
Jamie Lennox7655b552017-03-17 12:33:38 +1100855 # Keep the jobdir around so we can inspect contents if an
856 # assert fails.
857 self.executor_server.keep_jobdir = True
858 # Output extra ansible info so we might see errors.
859 self.executor_server.verbose = True
860 # Add a site variables file, used by check-vars
861 path = os.path.join(FIXTURE_DIR, 'config', 'ansible',
862 'variables.yaml')
863 self.config.set('executor', 'variables', path)
James E. Blairc73c73a2017-01-20 15:15:15 -0800864 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
865 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
866 self.waitUntilSettled()
Tobias Henkel077f2f32017-05-30 20:16:46 +0200867 build_timeout = self.getJobFromHistory('timeout')
Jamie Lennox7655b552017-03-17 12:33:38 +1100868 with self.jobLog(build_timeout):
869 self.assertEqual(build_timeout.result, 'TIMED_OUT')
Tobias Henkel077f2f32017-05-30 20:16:46 +0200870 build_faillocal = self.getJobFromHistory('faillocal')
Jamie Lennox7655b552017-03-17 12:33:38 +1100871 with self.jobLog(build_faillocal):
872 self.assertEqual(build_faillocal.result, 'FAILURE')
Tobias Henkel077f2f32017-05-30 20:16:46 +0200873 build_failpost = self.getJobFromHistory('failpost')
Jamie Lennox7655b552017-03-17 12:33:38 +1100874 with self.jobLog(build_failpost):
875 self.assertEqual(build_failpost.result, 'POST_FAILURE')
Tobias Henkel077f2f32017-05-30 20:16:46 +0200876 build_check_vars = self.getJobFromHistory('check-vars')
Jamie Lennox7655b552017-03-17 12:33:38 +1100877 with self.jobLog(build_check_vars):
878 self.assertEqual(build_check_vars.result, 'SUCCESS')
Monty Tayloraff8b402017-08-16 18:40:41 -0500879 build_check_secret_names = self.getJobFromHistory('check-secret-names')
880 with self.jobLog(build_check_secret_names):
881 self.assertEqual(build_check_secret_names.result, 'SUCCESS')
Tobias Henkel077f2f32017-05-30 20:16:46 +0200882 build_hello = self.getJobFromHistory('hello-world')
Jamie Lennox7655b552017-03-17 12:33:38 +1100883 with self.jobLog(build_hello):
884 self.assertEqual(build_hello.result, 'SUCCESS')
Tobias Henkel077f2f32017-05-30 20:16:46 +0200885 build_python27 = self.getJobFromHistory('python27')
Jamie Lennox7655b552017-03-17 12:33:38 +1100886 with self.jobLog(build_python27):
887 self.assertEqual(build_python27.result, 'SUCCESS')
888 flag_path = os.path.join(self.test_root,
889 build_python27.uuid + '.flag')
890 self.assertTrue(os.path.exists(flag_path))
891 copied_path = os.path.join(self.test_root, build_python27.uuid +
892 '.copied')
893 self.assertTrue(os.path.exists(copied_path))
894 failed_path = os.path.join(self.test_root, build_python27.uuid +
895 '.failed')
896 self.assertFalse(os.path.exists(failed_path))
897 pre_flag_path = os.path.join(self.test_root, build_python27.uuid +
898 '.pre.flag')
899 self.assertTrue(os.path.exists(pre_flag_path))
900 post_flag_path = os.path.join(self.test_root, build_python27.uuid +
901 '.post.flag')
902 self.assertTrue(os.path.exists(post_flag_path))
903 bare_role_flag_path = os.path.join(self.test_root,
904 build_python27.uuid +
905 '.bare-role.flag')
906 self.assertTrue(os.path.exists(bare_role_flag_path))
907 secrets_path = os.path.join(self.test_root,
908 build_python27.uuid + '.secrets')
909 with open(secrets_path) as f:
910 self.assertEqual(f.read(), "test-username test-password")
James E. Blairb9c0d772017-03-03 14:34:49 -0800911
Jamie Lennox7655b552017-03-17 12:33:38 +1100912 msg = A.messages[0]
913 success = "{} https://success.example.com/zuul-logs/{}"
914 fail = "{} https://failure.example.com/zuul-logs/{}"
915 self.assertIn(success.format("python27", build_python27.uuid), msg)
916 self.assertIn(fail.format("faillocal", build_faillocal.uuid), msg)
917 self.assertIn(success.format("check-vars",
918 build_check_vars.uuid), msg)
919 self.assertIn(success.format("hello-world", build_hello.uuid), msg)
920 self.assertIn(fail.format("timeout", build_timeout.uuid), msg)
921 self.assertIn(fail.format("failpost", build_failpost.uuid), msg)
Tobias Henkel077f2f32017-05-30 20:16:46 +0200922
James E. Blairabbaa6f2017-04-06 16:11:44 -0700923 def _add_job(self, job_name):
924 conf = textwrap.dedent(
925 """
926 - job:
927 name: %s
928
929 - project:
930 name: org/plugin-project
931 check:
932 jobs:
933 - %s
934 """ % (job_name, job_name))
935
936 file_dict = {'.zuul.yaml': conf}
937 A = self.fake_gerrit.addFakeChange('org/plugin-project', 'master', 'A',
938 files=file_dict)
939 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
940 self.waitUntilSettled()
941
942 def test_plugins(self):
943 # Keep the jobdir around so we can inspect contents if an
944 # assert fails.
945 self.executor_server.keep_jobdir = True
946 # Output extra ansible info so we might see errors.
947 self.executor_server.verbose = True
948
949 count = 0
950 plugin_tests = [
951 ('passwd', 'FAILURE'),
952 ('cartesian', 'SUCCESS'),
953 ('consul_kv', 'FAILURE'),
954 ('credstash', 'FAILURE'),
955 ('csvfile_good', 'SUCCESS'),
956 ('csvfile_bad', 'FAILURE'),
Monty Taylor93ad2212017-08-02 14:59:50 -0500957 ('uri_bad_path', 'FAILURE'),
958 ('uri_bad_scheme', 'FAILURE'),
Monty Taylor788a40e2017-08-02 16:14:05 -0500959 ('block_local_override', 'FAILURE'),
Monty Taylor8da768f2017-08-31 14:15:35 -0500960 ('file_local_good', 'SUCCESS'),
961 ('file_local_bad', 'FAILURE'),
James E. Blairabbaa6f2017-04-06 16:11:44 -0700962 ]
963 for job_name, result in plugin_tests:
964 count += 1
965 self._add_job(job_name)
966
967 job = self.getJobFromHistory(job_name)
968 with self.jobLog(job):
969 self.assertEqual(count, len(self.history))
970 build = self.history[-1]
971 self.assertEqual(build.result, result)
972
973 # TODOv3(jeblair): parse the ansible output and verify we're
974 # getting the exception we expect.
975
James E. Blairb9c0d772017-03-03 14:34:49 -0800976
James E. Blaira4d4eef2017-06-30 14:49:17 -0700977class TestPrePlaybooks(AnsibleZuulTestCase):
978 # A temporary class to hold new tests while others are disabled
979
980 tenant_config_file = 'config/pre-playbook/main.yaml'
981
982 def test_pre_playbook_fail(self):
983 # Test that we run the post playbooks (but not the actual
984 # playbook) when a pre-playbook fails.
985 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
986 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
987 self.waitUntilSettled()
988 build = self.getJobFromHistory('python27')
989 self.assertIsNone(build.result)
990 self.assertIn('RETRY_LIMIT', A.messages[0])
991 flag_path = os.path.join(self.test_root, build.uuid +
992 '.main.flag')
993 self.assertFalse(os.path.exists(flag_path))
994 pre_flag_path = os.path.join(self.test_root, build.uuid +
995 '.pre.flag')
996 self.assertFalse(os.path.exists(pre_flag_path))
997 post_flag_path = os.path.join(self.test_root, build.uuid +
998 '.post.flag')
James E. Blair21037782017-07-19 11:56:55 -0700999 self.assertTrue(os.path.exists(post_flag_path),
1000 "The file %s should exist" % post_flag_path)
James E. Blaira4d4eef2017-06-30 14:49:17 -07001001
1002
James E. Blairb9c0d772017-03-03 14:34:49 -08001003class TestBrokenConfig(ZuulTestCase):
1004 # Test that we get an appropriate syntax error if we start with a
1005 # broken config.
1006
1007 tenant_config_file = 'config/broken/main.yaml'
1008
1009 def setUp(self):
1010 with testtools.ExpectedException(
1011 zuul.configloader.ConfigurationSyntaxError,
1012 "\nZuul encountered a syntax error"):
1013 super(TestBrokenConfig, self).setUp()
1014
1015 def test_broken_config_on_startup(self):
1016 pass
Ricardo Carrillo Cruz22994f92016-12-02 11:41:58 +00001017
1018
1019class TestProjectKeys(ZuulTestCase):
1020 # Test that we can generate project keys
1021
1022 # Normally the test infrastructure copies a static key in place
1023 # for each project before starting tests. This saves time because
1024 # Zuul's automatic key-generation on startup can be slow. To make
1025 # sure we exercise that code, in this test we allow Zuul to create
1026 # keys for the project on startup.
1027 create_project_keys = True
Tobias Henkelabf973e2017-07-28 10:07:34 +02001028 config_file = 'zuul-connections-gerrit-and-github.conf'
Ricardo Carrillo Cruz22994f92016-12-02 11:41:58 +00001029 tenant_config_file = 'config/in-repo/main.yaml'
1030
1031 def test_key_generation(self):
1032 key_root = os.path.join(self.state_root, 'keys')
1033 private_key_file = os.path.join(key_root, 'gerrit/org/project.pem')
1034 # Make sure that a proper key was created on startup
1035 with open(private_key_file, "rb") as f:
James E. Blairbf1a4f22017-03-17 10:59:37 -07001036 private_key, public_key = \
1037 encryption.deserialize_rsa_keypair(f.read())
Ricardo Carrillo Cruz22994f92016-12-02 11:41:58 +00001038
1039 with open(os.path.join(FIXTURE_DIR, 'private.pem')) as i:
1040 fixture_private_key = i.read()
1041
1042 # Make sure that we didn't just end up with the static fixture
1043 # key
1044 self.assertNotEqual(fixture_private_key, private_key)
1045
1046 # Make sure it's the right length
1047 self.assertEqual(4096, private_key.key_size)
James E. Blairbce76932017-05-04 10:03:15 -07001048
1049
James E. Blairbb94dfa2017-07-11 07:45:19 -07001050class RoleTestCase(ZuulTestCase):
James E. Blair1b27f6a2017-07-14 14:09:07 -07001051 def _assertRolePath(self, build, playbook, content):
1052 path = os.path.join(self.test_root, build.uuid,
1053 'ansible', playbook, 'ansible.cfg')
1054 roles_paths = []
1055 with open(path) as f:
1056 for line in f:
1057 if line.startswith('roles_path'):
1058 roles_paths.append(line)
1059 print(roles_paths)
1060 if content:
1061 self.assertEqual(len(roles_paths), 1,
1062 "Should have one roles_path line in %s" %
1063 (playbook,))
1064 self.assertIn(content, roles_paths[0])
1065 else:
1066 self.assertEqual(len(roles_paths), 0,
1067 "Should have no roles_path line in %s" %
1068 (playbook,))
1069
James E. Blairbb94dfa2017-07-11 07:45:19 -07001070
1071class TestRoles(RoleTestCase):
1072 tenant_config_file = 'config/roles/main.yaml'
1073
James E. Blairbce76932017-05-04 10:03:15 -07001074 def test_role(self):
1075 # This exercises a proposed change to a role being checked out
1076 # and used.
1077 A = self.fake_gerrit.addFakeChange('bare-role', 'master', 'A')
1078 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1079 B.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
1080 B.subject, A.data['id'])
1081 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
1082 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
1083 self.waitUntilSettled()
1084 self.assertHistory([
1085 dict(name='project-test', result='SUCCESS', changes='1,1 2,1'),
1086 ])
James E. Blair6459db12017-06-29 14:57:20 -07001087
James E. Blair1b27f6a2017-07-14 14:09:07 -07001088 def test_role_inheritance(self):
1089 self.executor_server.hold_jobs_in_build = True
1090 conf = textwrap.dedent(
1091 """
1092 - job:
1093 name: parent
1094 roles:
1095 - zuul: bare-role
1096 pre-run: playbooks/parent-pre
1097 post-run: playbooks/parent-post
1098
1099 - job:
1100 name: project-test
1101 parent: parent
1102 roles:
1103 - zuul: org/project
1104
1105 - project:
1106 name: org/project
1107 check:
1108 jobs:
1109 - project-test
1110 """)
1111
1112 file_dict = {'.zuul.yaml': conf}
1113 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
1114 files=file_dict)
1115 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
1116 self.waitUntilSettled()
1117
1118 self.assertEqual(len(self.builds), 1)
1119 build = self.getBuildByName('project-test')
1120 self._assertRolePath(build, 'pre_playbook_0', 'role_0')
1121 self._assertRolePath(build, 'playbook_0', 'role_0')
1122 self._assertRolePath(build, 'playbook_0', 'role_1')
1123 self._assertRolePath(build, 'post_playbook_0', 'role_0')
1124
1125 self.executor_server.hold_jobs_in_build = False
1126 self.executor_server.release()
1127 self.waitUntilSettled()
1128
1129 self.assertHistory([
1130 dict(name='project-test', result='SUCCESS', changes='1,1'),
1131 ])
1132
James E. Blair6f699732017-07-18 14:19:11 -07001133 def test_role_error(self):
1134 conf = textwrap.dedent(
1135 """
1136 - job:
1137 name: project-test
1138 roles:
1139 - zuul: common-config
1140
1141 - project:
1142 name: org/project
1143 check:
1144 jobs:
1145 - project-test
1146 """)
1147
1148 file_dict = {'.zuul.yaml': conf}
1149 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
1150 files=file_dict)
1151 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
1152 self.waitUntilSettled()
1153 self.assertIn(
1154 '- project-test project-test : ERROR Unable to find role',
1155 A.messages[-1])
1156
James E. Blair6459db12017-06-29 14:57:20 -07001157
James E. Blairbb94dfa2017-07-11 07:45:19 -07001158class TestImplicitRoles(RoleTestCase):
1159 tenant_config_file = 'config/implicit-roles/main.yaml'
1160
1161 def test_missing_roles(self):
1162 # Test implicit and explicit roles for a project which does
1163 # not have roles. The implicit role should be silently
1164 # ignored since the project doesn't supply roles, but if a
1165 # user declares an explicit role, it should error.
1166 self.executor_server.hold_jobs_in_build = True
1167 A = self.fake_gerrit.addFakeChange('org/norole-project', 'master', 'A')
1168 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
1169 self.waitUntilSettled()
1170
1171 self.assertEqual(len(self.builds), 2)
1172 build = self.getBuildByName('implicit-role-fail')
1173 self._assertRolePath(build, 'playbook_0', None)
1174
1175 self.executor_server.hold_jobs_in_build = False
1176 self.executor_server.release()
1177 self.waitUntilSettled()
1178 # The retry_limit doesn't get recorded
1179 self.assertHistory([
1180 dict(name='implicit-role-fail', result='SUCCESS', changes='1,1'),
1181 ])
1182
1183 def test_roles(self):
1184 # Test implicit and explicit roles for a project which does
1185 # have roles. In both cases, we should end up with the role
1186 # in the path. In the explicit case, ensure we end up with
1187 # the name we specified.
1188 self.executor_server.hold_jobs_in_build = True
1189 A = self.fake_gerrit.addFakeChange('org/role-project', 'master', 'A')
1190 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
1191 self.waitUntilSettled()
1192
1193 self.assertEqual(len(self.builds), 2)
1194 build = self.getBuildByName('implicit-role-ok')
1195 self._assertRolePath(build, 'playbook_0', 'role_0')
1196
1197 build = self.getBuildByName('explicit-role-ok')
1198 self._assertRolePath(build, 'playbook_0', 'role_0')
1199
1200 self.executor_server.hold_jobs_in_build = False
1201 self.executor_server.release()
1202 self.waitUntilSettled()
1203 self.assertHistory([
1204 dict(name='implicit-role-ok', result='SUCCESS', changes='1,1'),
1205 dict(name='explicit-role-ok', result='SUCCESS', changes='1,1'),
1206 ], ordered=False)
1207
1208
James E. Blair6459db12017-06-29 14:57:20 -07001209class TestShadow(ZuulTestCase):
1210 tenant_config_file = 'config/shadow/main.yaml'
1211
1212 def test_shadow(self):
1213 # Test that a repo is allowed to shadow another's job definitions.
1214 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1215 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
1216 self.waitUntilSettled()
1217 self.assertHistory([
1218 dict(name='test1', result='SUCCESS', changes='1,1'),
1219 dict(name='test2', result='SUCCESS', changes='1,1'),
James E. Blairadafa6c2017-07-12 08:50:56 -07001220 ], ordered=False)
James E. Blair196f61a2017-06-30 15:42:29 -07001221
1222
1223class TestDataReturn(AnsibleZuulTestCase):
1224 tenant_config_file = 'config/data-return/main.yaml'
1225
1226 def test_data_return(self):
1227 # This exercises a proposed change to a role being checked out
1228 # and used.
1229 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1230 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
1231 self.waitUntilSettled()
1232 self.assertHistory([
1233 dict(name='data-return', result='SUCCESS', changes='1,1'),
James E. Blair88e79c02017-07-07 13:36:54 -07001234 dict(name='data-return-relative', result='SUCCESS', changes='1,1'),
1235 ], ordered=False)
1236 self.assertIn('- data-return http://example.com/test/log/url/',
1237 A.messages[-1])
1238 self.assertIn('- data-return-relative '
1239 'http://example.com/test/log/url/docs/index.html',
James E. Blair196f61a2017-06-30 15:42:29 -07001240 A.messages[-1])
Clint Byrumdc8a0902017-07-20 16:36:27 -07001241
1242
1243class TestDiskAccounting(AnsibleZuulTestCase):
1244 config_file = 'zuul-disk-accounting.conf'
1245 tenant_config_file = 'config/disk-accountant/main.yaml'
1246
1247 def test_disk_accountant_kills_job(self):
1248 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1249 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
1250 self.waitUntilSettled()
1251 self.assertHistory([
1252 dict(name='dd-big-empty-file', result='ABORTED', changes='1,1')])
Tristan Cacqueray82f864b2017-08-01 05:54:42 +00001253
1254
1255class TestMaxNodesPerJob(AnsibleZuulTestCase):
1256 tenant_config_file = 'config/multi-tenant/main.yaml'
1257
1258 def test_max_nodes_reached(self):
1259 in_repo_conf = textwrap.dedent(
1260 """
1261 - job:
1262 name: test-job
1263 nodes:
1264 - name: node01
1265 label: fake
1266 - name: node02
1267 label: fake
1268 - name: node03
1269 label: fake
1270 - name: node04
1271 label: fake
1272 - name: node05
1273 label: fake
1274 - name: node06
1275 label: fake
1276 """)
1277 file_dict = {'.zuul.yaml': in_repo_conf}
1278 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A',
1279 files=file_dict)
1280 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
1281 self.waitUntilSettled()
1282 self.assertIn('The job "test-job" exceeds tenant max-nodes-per-job 5.',
1283 A.messages[0], "A should fail because of nodes limit")
1284
1285 B = self.fake_gerrit.addFakeChange('org/project2', 'master', 'A',
1286 files=file_dict)
1287 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
1288 self.waitUntilSettled()
1289 self.assertNotIn("exceeds tenant max-nodes", B.messages[0],
1290 "B should not fail because of nodes limit")
James E. Blair2bab6e72017-08-07 09:52:45 -07001291
1292
1293class TestBaseJobs(ZuulTestCase):
1294 tenant_config_file = 'config/base-jobs/main.yaml'
1295
1296 def test_multiple_base_jobs(self):
1297 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1298 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
1299 self.waitUntilSettled()
1300 self.assertHistory([
1301 dict(name='my-job', result='SUCCESS', changes='1,1'),
1302 dict(name='other-job', result='SUCCESS', changes='1,1'),
1303 ], ordered=False)
1304 self.assertEqual(self.getJobFromHistory('my-job').
1305 parameters['zuul']['jobtags'],
1306 ['mybase'])
1307 self.assertEqual(self.getJobFromHistory('other-job').
1308 parameters['zuul']['jobtags'],
1309 ['otherbase'])
1310
1311 def test_untrusted_base_job(self):
1312 """Test that a base job may not be defined in an untrusted repo"""
1313 in_repo_conf = textwrap.dedent(
1314 """
1315 - job:
1316 name: fail-base
1317 parent: null
1318 """)
1319
1320 file_dict = {'.zuul.yaml': in_repo_conf}
1321 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
1322 files=file_dict)
1323 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
1324 self.waitUntilSettled()
1325 self.assertEqual(A.reported, 1,
1326 "A should report failure")
1327 self.assertEqual(A.patchsets[0]['approvals'][0]['value'], "-1")
1328 self.assertIn('Base jobs must be defined in config projects',
1329 A.messages[0])
1330 self.assertHistory([])
James E. Blairdb089032017-08-15 13:42:12 -07001331
1332
1333class TestSecretLeaks(AnsibleZuulTestCase):
1334 tenant_config_file = 'config/secret-leaks/main.yaml'
1335
1336 def searchForContent(self, path, content):
1337 matches = []
1338 for (dirpath, dirnames, filenames) in os.walk(path):
1339 for filename in filenames:
1340 filepath = os.path.join(dirpath, filename)
1341 with open(filepath, 'rb') as f:
1342 if content in f.read():
1343 matches.append(filepath[len(path):])
1344 return matches
1345
1346 def _test_secret_file(self):
1347 # Or rather -- test that they *don't* leak.
1348 # Keep the jobdir around so we can inspect contents.
1349 self.executor_server.keep_jobdir = True
1350 conf = textwrap.dedent(
1351 """
1352 - project:
1353 name: org/project
1354 check:
1355 jobs:
1356 - secret-file
1357 """)
1358
1359 file_dict = {'.zuul.yaml': conf}
1360 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
1361 files=file_dict)
1362 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
1363 self.waitUntilSettled()
1364 self.assertHistory([
1365 dict(name='secret-file', result='SUCCESS', changes='1,1'),
1366 ], ordered=False)
1367 matches = self.searchForContent(self.history[0].jobdir.root,
1368 b'test-password')
James E. Blaird6a71ca2017-08-18 14:15:05 -07001369 self.assertEqual(set(['/work/secret-file.txt']),
James E. Blairdb089032017-08-15 13:42:12 -07001370 set(matches))
1371
1372 def test_secret_file(self):
1373 self._test_secret_file()
1374
1375 def test_secret_file_verbose(self):
1376 # Output extra ansible info to exercise alternate logging code
1377 # paths.
1378 self.executor_server.verbose = True
1379 self._test_secret_file()
1380
1381 def _test_secret_file_fail(self):
1382 # Or rather -- test that they *don't* leak.
1383 # Keep the jobdir around so we can inspect contents.
1384 self.executor_server.keep_jobdir = True
1385 conf = textwrap.dedent(
1386 """
1387 - project:
1388 name: org/project
1389 check:
1390 jobs:
1391 - secret-file-fail
1392 """)
1393
1394 file_dict = {'.zuul.yaml': conf}
1395 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
1396 files=file_dict)
1397 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
1398 self.waitUntilSettled()
1399 self.assertHistory([
1400 dict(name='secret-file-fail', result='FAILURE', changes='1,1'),
1401 ], ordered=False)
1402 matches = self.searchForContent(self.history[0].jobdir.root,
1403 b'test-password')
James E. Blaird6a71ca2017-08-18 14:15:05 -07001404 self.assertEqual(set(['/work/failure-file.txt']),
James E. Blairdb089032017-08-15 13:42:12 -07001405 set(matches))
1406
1407 def test_secret_file_fail(self):
1408 self._test_secret_file_fail()
1409
1410 def test_secret_file_fail_verbose(self):
1411 # Output extra ansible info to exercise alternate logging code
1412 # paths.
1413 self.executor_server.verbose = True
1414 self._test_secret_file_fail()
James E. Blaira00910c2017-08-23 09:15:04 -07001415
1416
1417class TestJobOutput(AnsibleZuulTestCase):
1418 tenant_config_file = 'config/job-output/main.yaml'
1419
1420 def _get_file(self, build, path):
1421 p = os.path.join(build.jobdir.root, path)
1422 with open(p) as f:
1423 return f.read()
1424
1425 def test_job_output(self):
1426 # Verify that command standard output appears in the job output
1427
1428 # This currently only verifies we receive output from
1429 # localhost. Notably, it does not verify we receive output
1430 # via zuul_console streaming.
1431 self.executor_server.keep_jobdir = True
1432 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1433 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
1434 self.waitUntilSettled()
1435 self.assertHistory([
1436 dict(name='job-output', result='SUCCESS', changes='1,1'),
1437 ], ordered=False)
1438
1439 token = 'Standard output test %s' % (self.history[0].jobdir.src_root)
1440 j = json.loads(self._get_file(self.history[0],
1441 'work/logs/job-output.json'))
1442 self.assertEqual(token,
1443 j[0]['plays'][0]['tasks'][0]
1444 ['hosts']['localhost']['stdout'])
1445
1446 print(self._get_file(self.history[0],
1447 'work/logs/job-output.txt'))
1448 self.assertIn(token,
1449 self._get_file(self.history[0],
1450 'work/logs/job-output.txt'))