blob: 573c8a697a3017783fc39aba68ff39bb305d3ef0 [file] [log] [blame]
James E. Blair59fdbac2015-12-07 17:08:06 -08001#!/usr/bin/env python
2
3# Copyright 2012 Hewlett-Packard Development Company, L.P.
4#
5# Licensed under the Apache License, Version 2.0 (the "License"); you may
6# not use this file except in compliance with the License. You may obtain
7# a copy of the License at
8#
9# http://www.apache.org/licenses/LICENSE-2.0
10#
11# Unless required by applicable law or agreed to in writing, software
12# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14# License for the specific language governing permissions and limitations
15# under the License.
16
Monty Taylor0e2489a2017-10-10 11:57:29 -050017import io
James E. Blaira00910c2017-08-23 09:15:04 -070018import json
Monty Taylor0e2489a2017-10-10 11:57:29 -050019import logging
James E. Blaira92cbc82017-01-23 14:56:49 -080020import os
James E. Blair14abdf42015-12-09 16:11:53 -080021import textwrap
James E. Blair3a098dd2017-10-04 14:37:29 -070022import gc
James E. Blairbacbb882017-10-17 09:48:23 -070023import time
James E. Blair3a098dd2017-10-04 14:37:29 -070024from unittest import skip
James E. Blair59fdbac2015-12-07 17:08:06 -080025
James E. Blairb9c0d772017-03-03 14:34:49 -080026import testtools
27
28import zuul.configloader
James E. Blairbf1a4f22017-03-17 10:59:37 -070029from zuul.lib import encryption
Ricardo Carrillo Cruz22994f92016-12-02 11:41:58 +000030from tests.base import AnsibleZuulTestCase, ZuulTestCase, FIXTURE_DIR
James E. Blair59fdbac2015-12-07 17:08:06 -080031
James E. Blair59fdbac2015-12-07 17:08:06 -080032
James E. Blair3f876d52016-07-22 13:07:14 -070033class TestMultipleTenants(AnsibleZuulTestCase):
James E. Blair59fdbac2015-12-07 17:08:06 -080034 # A temporary class to hold new tests while others are disabled
35
James E. Blair2a629ec2015-12-22 15:32:02 -080036 tenant_config_file = 'config/multi-tenant/main.yaml'
James E. Blair59fdbac2015-12-07 17:08:06 -080037
James E. Blair83005782015-12-11 14:46:03 -080038 def test_multiple_tenants(self):
James E. Blair96f26942015-12-09 10:15:59 -080039 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A')
Tobias Henkelbf24fd12017-07-27 06:13:07 +020040 A.addApproval('Code-Review', 2)
41 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
James E. Blair59fdbac2015-12-07 17:08:06 -080042 self.waitUntilSettled()
James E. Blair96f26942015-12-09 10:15:59 -080043 self.assertEqual(self.getJobFromHistory('project1-test1').result,
James E. Blair59fdbac2015-12-07 17:08:06 -080044 'SUCCESS')
James E. Blair96c6bf82016-01-15 16:20:40 -080045 self.assertEqual(self.getJobFromHistory('python27').result,
46 'SUCCESS')
James E. Blair59fdbac2015-12-07 17:08:06 -080047 self.assertEqual(A.data['status'], 'MERGED')
James E. Blair96f26942015-12-09 10:15:59 -080048 self.assertEqual(A.reported, 2,
49 "A should report start and success")
50 self.assertIn('tenant-one-gate', A.messages[1],
51 "A should transit tenant-one gate")
52 self.assertNotIn('tenant-two-gate', A.messages[1],
53 "A should *not* transit tenant-two gate")
James E. Blair59fdbac2015-12-07 17:08:06 -080054
James E. Blair96f26942015-12-09 10:15:59 -080055 B = self.fake_gerrit.addFakeChange('org/project2', 'master', 'B')
Tobias Henkelbf24fd12017-07-27 06:13:07 +020056 B.addApproval('Code-Review', 2)
57 self.fake_gerrit.addEvent(B.addApproval('Approved', 1))
James E. Blair96f26942015-12-09 10:15:59 -080058 self.waitUntilSettled()
James E. Blair96c6bf82016-01-15 16:20:40 -080059 self.assertEqual(self.getJobFromHistory('python27',
60 'org/project2').result,
61 'SUCCESS')
James E. Blair96f26942015-12-09 10:15:59 -080062 self.assertEqual(self.getJobFromHistory('project2-test1').result,
63 'SUCCESS')
64 self.assertEqual(B.data['status'], 'MERGED')
65 self.assertEqual(B.reported, 2,
66 "B should report start and success")
67 self.assertIn('tenant-two-gate', B.messages[1],
68 "B should transit tenant-two gate")
69 self.assertNotIn('tenant-one-gate', B.messages[1],
70 "B should *not* transit tenant-one gate")
James E. Blair59fdbac2015-12-07 17:08:06 -080071
James E. Blair96f26942015-12-09 10:15:59 -080072 self.assertEqual(A.reported, 2, "Activity in tenant two should"
73 "not affect tenant one")
James E. Blair14abdf42015-12-09 16:11:53 -080074
James E. Blair83005782015-12-11 14:46:03 -080075
Tobias Henkel130b0002017-11-26 20:27:59 +010076class TestProtected(ZuulTestCase):
Tobias Henkel130b0002017-11-26 20:27:59 +010077 tenant_config_file = 'config/protected/main.yaml'
78
79 def test_protected_ok(self):
James E. Blair979bf242017-09-15 21:13:32 -060080 # test clean usage of final parent job
81 in_repo_conf = textwrap.dedent(
82 """
83 - job:
84 name: job-protected
85 protected: true
86 run: playbooks/job-protected.yaml
Tobias Henkel130b0002017-11-26 20:27:59 +010087
James E. Blair979bf242017-09-15 21:13:32 -060088 - project:
89 name: org/project
90 check:
91 jobs:
92 - job-child-ok
Tobias Henkel130b0002017-11-26 20:27:59 +010093
James E. Blair979bf242017-09-15 21:13:32 -060094 - job:
95 name: job-child-ok
96 parent: job-protected
Tobias Henkel130b0002017-11-26 20:27:59 +010097
James E. Blair979bf242017-09-15 21:13:32 -060098 - project:
99 name: org/project
100 check:
101 jobs:
102 - job-child-ok
Tobias Henkel130b0002017-11-26 20:27:59 +0100103
James E. Blair979bf242017-09-15 21:13:32 -0600104 """)
Tobias Henkel130b0002017-11-26 20:27:59 +0100105
James E. Blair979bf242017-09-15 21:13:32 -0600106 file_dict = {'zuul.yaml': in_repo_conf}
107 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
108 files=file_dict)
109 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
110 self.waitUntilSettled()
Tobias Henkel130b0002017-11-26 20:27:59 +0100111
James E. Blair979bf242017-09-15 21:13:32 -0600112 self.assertEqual(A.reported, 1)
113 self.assertEqual(A.patchsets[-1]['approvals'][0]['value'], '1')
Tobias Henkel130b0002017-11-26 20:27:59 +0100114
115 def test_protected_reset(self):
116 # try to reset protected flag
117 in_repo_conf = textwrap.dedent(
118 """
119 - job:
120 name: job-protected
121 protected: true
122 run: playbooks/job-protected.yaml
123
124 - job:
125 name: job-child-reset-protected
126 parent: job-protected
127 protected: false
128
129 - project:
130 name: org/project
131 check:
132 jobs:
133 - job-child-reset-protected
134
135 """)
136
137 file_dict = {'zuul.yaml': in_repo_conf}
138 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
139 files=file_dict)
140 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
141 self.waitUntilSettled()
142
143 # The second patch tried to override some variables.
144 # Thus it should fail.
145 self.assertEqual(A.reported, 1)
146 self.assertEqual(A.patchsets[-1]['approvals'][0]['value'], '-1')
147 self.assertIn('Unable to reset protected attribute', A.messages[0])
148
149 def test_protected_inherit_not_ok(self):
150 # try to inherit from a protected job in different project
151 in_repo_conf = textwrap.dedent(
152 """
153 - job:
154 name: job-child-notok
155 run: playbooks/job-child-notok.yaml
156 parent: job-protected
157
158 - project:
159 name: org/project1
160 check:
161 jobs:
162 - job-child-notok
163
164 """)
165
166 file_dict = {'zuul.yaml': in_repo_conf}
167 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A',
168 files=file_dict)
169 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
170 self.waitUntilSettled()
171
172 self.assertEqual(A.reported, 1)
173 self.assertEqual(A.patchsets[-1]['approvals'][0]['value'], '-1')
174 self.assertIn(
175 "which is defined in review.example.com/org/project is protected "
176 "and cannot be inherited from other projects.", A.messages[0])
177
178
James E. Blair979bf242017-09-15 21:13:32 -0600179class TestAbstract(ZuulTestCase):
180 tenant_config_file = 'config/abstract/main.yaml'
181
182 def test_abstract_fail(self):
183 in_repo_conf = textwrap.dedent(
184 """
185 - project:
186 check:
187 jobs:
188 - job-abstract
189 """)
190
191 file_dict = {'zuul.yaml': in_repo_conf}
192 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
193 files=file_dict)
194 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
195 self.waitUntilSettled()
196
197 self.assertEqual(A.reported, 1)
198 self.assertEqual(A.patchsets[-1]['approvals'][0]['value'], '-1')
199 self.assertIn('may not be directly run', A.messages[0])
200
201 def test_child_of_abstract(self):
202 in_repo_conf = textwrap.dedent(
203 """
204 - project:
205 check:
206 jobs:
207 - job-child
208 """)
209
210 file_dict = {'zuul.yaml': in_repo_conf}
211 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
212 files=file_dict)
213 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
214 self.waitUntilSettled()
215
216 self.assertEqual(A.reported, 1)
217 self.assertEqual(A.patchsets[-1]['approvals'][0]['value'], '1')
218
219
Tobias Henkel83167622017-06-30 19:45:03 +0200220class TestFinal(ZuulTestCase):
221
222 tenant_config_file = 'config/final/main.yaml'
223
224 def test_final_variant_ok(self):
225 # test clean usage of final parent job
226 in_repo_conf = textwrap.dedent(
227 """
228 - project:
229 name: org/project
230 check:
231 jobs:
232 - job-final
233 """)
234
235 file_dict = {'.zuul.yaml': in_repo_conf}
236 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
237 files=file_dict)
238 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
239 self.waitUntilSettled()
240
241 self.assertEqual(A.reported, 1)
242 self.assertEqual(A.patchsets[-1]['approvals'][0]['value'], '1')
243
244 def test_final_variant_error(self):
245 # test misuse of final parent job
246 in_repo_conf = textwrap.dedent(
247 """
248 - project:
249 name: org/project
250 check:
251 jobs:
252 - job-final:
253 vars:
254 dont_override_this: bar
255 """)
256 file_dict = {'.zuul.yaml': in_repo_conf}
257 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
258 files=file_dict)
259 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
260 self.waitUntilSettled()
261
262 # The second patch tried to override some variables.
263 # Thus it should fail.
264 self.assertEqual(A.reported, 1)
265 self.assertEqual(A.patchsets[-1]['approvals'][0]['value'], '-1')
266 self.assertIn('Unable to modify final job', A.messages[0])
267
268 def test_final_inheritance(self):
269 # test misuse of final parent job
270 in_repo_conf = textwrap.dedent(
271 """
272 - job:
273 name: project-test
274 parent: job-final
James E. Blair2f589fe2017-10-26 12:57:41 -0700275 run: playbooks/project-test.yaml
Tobias Henkel83167622017-06-30 19:45:03 +0200276
277 - project:
278 name: org/project
279 check:
280 jobs:
281 - project-test
282 """)
283
284 in_repo_playbook = textwrap.dedent(
285 """
286 - hosts: all
287 tasks: []
288 """)
289
290 file_dict = {'.zuul.yaml': in_repo_conf,
291 'playbooks/project-test.yaml': in_repo_playbook}
292 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
293 files=file_dict)
294 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
295 self.waitUntilSettled()
296
297 # The second patch tried to override some variables.
298 # Thus it should fail.
299 self.assertEqual(A.reported, 1)
300 self.assertEqual(A.patchsets[-1]['approvals'][0]['value'], '-1')
James E. Blairc32a8352017-10-11 16:27:50 -0700301 self.assertIn('Unable to modify final job', A.messages[0])
Tobias Henkel83167622017-06-30 19:45:03 +0200302
303
James E. Blair1edfd972017-12-01 15:54:24 -0800304class TestBranchTag(ZuulTestCase):
305 tenant_config_file = 'config/branch-tag/main.yaml'
306
307 def test_negative_branch_match(self):
308 # Test that a negative branch matcher works with implied branches.
309 event = self.fake_gerrit.addFakeTag('org/project', 'master', 'foo')
310 self.fake_gerrit.addEvent(event)
311 self.waitUntilSettled()
312 self.assertHistory([
313 dict(name='test-job', result='SUCCESS', ref='refs/tags/foo')])
314
315
James E. Blair9ab8db42017-12-01 15:12:04 -0800316class TestBranchNegative(ZuulTestCase):
317 tenant_config_file = 'config/branch-negative/main.yaml'
318
319 def test_negative_branch_match(self):
320 # Test that a negative branch matcher works with implied branches.
321 self.create_branch('org/project', 'stable/pike')
322 self.fake_gerrit.addEvent(
323 self.fake_gerrit.getFakeBranchCreatedEvent(
324 'org/project', 'stable/pike'))
325 self.waitUntilSettled()
326
327 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
328 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
329 self.waitUntilSettled()
330 B = self.fake_gerrit.addFakeChange('org/project', 'stable/pike', 'A')
331 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
332 self.waitUntilSettled()
333 self.assertHistory([
334 dict(name='test-job', result='SUCCESS', changes='1,1')])
335
336
James E. Blaire36d1a32017-11-28 13:33:38 -0800337class TestBranchTemplates(ZuulTestCase):
338 tenant_config_file = 'config/branch-templates/main.yaml'
339
340 def test_template_removal_from_branch(self):
341 # Test that a template can be removed from one branch but not
342 # another.
343 # This creates a new branch with a copy of the config in master
344 self.create_branch('puppet-integration', 'stable/newton')
345 self.create_branch('puppet-integration', 'stable/ocata')
346 self.create_branch('puppet-tripleo', 'stable/newton')
347 self.create_branch('puppet-tripleo', 'stable/ocata')
348 self.fake_gerrit.addEvent(
349 self.fake_gerrit.getFakeBranchCreatedEvent(
350 'puppet-integration', 'stable/newton'))
351 self.fake_gerrit.addEvent(
352 self.fake_gerrit.getFakeBranchCreatedEvent(
353 'puppet-integration', 'stable/ocata'))
354 self.fake_gerrit.addEvent(
355 self.fake_gerrit.getFakeBranchCreatedEvent(
356 'puppet-tripleo', 'stable/newton'))
357 self.fake_gerrit.addEvent(
358 self.fake_gerrit.getFakeBranchCreatedEvent(
359 'puppet-tripleo', 'stable/ocata'))
360 self.waitUntilSettled()
361
362 in_repo_conf = textwrap.dedent(
363 """
364 - project:
365 name: puppet-tripleo
366 check:
367 jobs:
368 - puppet-something
369 """)
370
371 file_dict = {'.zuul.yaml': in_repo_conf}
372 A = self.fake_gerrit.addFakeChange('puppet-tripleo', 'stable/newton',
373 'A', files=file_dict)
374 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
375 self.waitUntilSettled()
376 self.assertHistory([
377 dict(name='puppet-something', result='SUCCESS', changes='1,1')])
378
379 def test_template_change_on_branch(self):
380 # Test that the contents of a template can be changed on one
381 # branch without affecting another.
382
383 # This creates a new branch with a copy of the config in master
384 self.create_branch('puppet-integration', 'stable/newton')
385 self.create_branch('puppet-integration', 'stable/ocata')
386 self.create_branch('puppet-tripleo', 'stable/newton')
387 self.create_branch('puppet-tripleo', 'stable/ocata')
388 self.fake_gerrit.addEvent(
389 self.fake_gerrit.getFakeBranchCreatedEvent(
390 'puppet-integration', 'stable/newton'))
391 self.fake_gerrit.addEvent(
392 self.fake_gerrit.getFakeBranchCreatedEvent(
393 'puppet-integration', 'stable/ocata'))
394 self.fake_gerrit.addEvent(
395 self.fake_gerrit.getFakeBranchCreatedEvent(
396 'puppet-tripleo', 'stable/newton'))
397 self.fake_gerrit.addEvent(
398 self.fake_gerrit.getFakeBranchCreatedEvent(
399 'puppet-tripleo', 'stable/ocata'))
400 self.waitUntilSettled()
401
402 in_repo_conf = textwrap.dedent("""
403 - job:
404 name: puppet-unit-base
405 run: playbooks/run-unit-tests.yaml
406
407 - job:
408 name: puppet-unit-3.8
409 parent: puppet-unit-base
410 branches: ^(stable/(newton|ocata)).*$
411 vars:
412 puppet_gem_version: 3.8
413
414 - job:
415 name: puppet-something
416 run: playbooks/run-unit-tests.yaml
417
418 - project-template:
419 name: puppet-unit
420 check:
421 jobs:
422 - puppet-something
423
424 - project:
425 name: puppet-integration
426 templates:
427 - puppet-unit
428 """)
429
430 file_dict = {'.zuul.yaml': in_repo_conf}
431 A = self.fake_gerrit.addFakeChange('puppet-integration',
432 'stable/newton',
433 'A', files=file_dict)
434 B = self.fake_gerrit.addFakeChange('puppet-tripleo',
435 'stable/newton',
436 'B')
437 B.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
438 B.subject, A.data['id'])
439 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
440 self.waitUntilSettled()
441 self.assertHistory([
442 dict(name='puppet-something', result='SUCCESS',
443 changes='1,1 2,1')])
444
445
James E. Blair09998792017-10-15 18:02:18 -0700446class TestBranchVariants(ZuulTestCase):
447 tenant_config_file = 'config/branch-variants/main.yaml'
448
449 def test_branch_variants(self):
450 # Test branch variants of jobs with inheritance
451 self.executor_server.hold_jobs_in_build = True
452 # This creates a new branch with a copy of the config in master
453 self.create_branch('puppet-integration', 'stable')
454 self.fake_gerrit.addEvent(
455 self.fake_gerrit.getFakeBranchCreatedEvent(
456 'puppet-integration', 'stable'))
457 self.waitUntilSettled()
458
459 A = self.fake_gerrit.addFakeChange('puppet-integration', 'stable', 'A')
460 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
461 self.waitUntilSettled()
462
463 self.assertEqual(len(self.builds[0].parameters['pre_playbooks']), 3)
464 self.executor_server.hold_jobs_in_build = False
465 self.executor_server.release()
466 self.waitUntilSettled()
467
James E. Blairc9e77592017-10-24 09:25:23 -0700468 def test_branch_variants_reconfigure(self):
469 # Test branch variants of jobs with inheritance
470 self.executor_server.hold_jobs_in_build = True
471 # This creates a new branch with a copy of the config in master
472 self.create_branch('puppet-integration', 'stable')
473 self.fake_gerrit.addEvent(
474 self.fake_gerrit.getFakeBranchCreatedEvent(
475 'puppet-integration', 'stable'))
476 self.waitUntilSettled()
477
478 with open(os.path.join(FIXTURE_DIR,
479 'config/branch-variants/git/',
480 'puppet-integration/.zuul.yaml')) as f:
481 config = f.read()
482
483 # Push a change that triggers a dynamic reconfiguration
484 file_dict = {'.zuul.yaml': config}
485 A = self.fake_gerrit.addFakeChange('puppet-integration', 'master', 'A',
486 files=file_dict)
487 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
488 self.waitUntilSettled()
489
490 ipath = self.builds[0].parameters['zuul']['_inheritance_path']
491 for i in ipath:
492 self.log.debug("inheritance path %s", i)
493 self.assertEqual(len(ipath), 5)
494 self.executor_server.hold_jobs_in_build = False
495 self.executor_server.release()
496 self.waitUntilSettled()
497
James E. Blairc32a8352017-10-11 16:27:50 -0700498 def test_branch_variants_divergent(self):
499 # Test branches can diverge and become independent
500 self.executor_server.hold_jobs_in_build = True
501 # This creates a new branch with a copy of the config in master
502 self.create_branch('puppet-integration', 'stable')
503 self.fake_gerrit.addEvent(
504 self.fake_gerrit.getFakeBranchCreatedEvent(
505 'puppet-integration', 'stable'))
506 self.waitUntilSettled()
507
508 with open(os.path.join(FIXTURE_DIR,
509 'config/branch-variants/git/',
510 'puppet-integration/stable.zuul.yaml')) as f:
511 config = f.read()
512
513 file_dict = {'.zuul.yaml': config}
514 C = self.fake_gerrit.addFakeChange('puppet-integration', 'stable', 'C',
515 files=file_dict)
516 C.addApproval('Code-Review', 2)
517 self.fake_gerrit.addEvent(C.addApproval('Approved', 1))
518 self.waitUntilSettled()
519 self.fake_gerrit.addEvent(C.getChangeMergedEvent())
520 self.waitUntilSettled()
521
522 A = self.fake_gerrit.addFakeChange('puppet-integration', 'master', 'A')
523 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
524 self.waitUntilSettled()
525 B = self.fake_gerrit.addFakeChange('puppet-integration', 'stable', 'B')
526 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
527 self.waitUntilSettled()
528
529 self.assertEqual(self.builds[0].parameters['zuul']['jobtags'],
530 ['master'])
531
532 self.assertEqual(self.builds[1].parameters['zuul']['jobtags'],
533 ['stable'])
534
535 self.executor_server.hold_jobs_in_build = False
536 self.executor_server.release()
537 self.waitUntilSettled()
538
James E. Blair09998792017-10-15 18:02:18 -0700539
James E. Blair7fb04512018-01-23 13:23:13 -0800540class TestBranchMismatch(ZuulTestCase):
541 tenant_config_file = 'config/branch-mismatch/main.yaml'
542
543 def test_job_override_branch(self):
544 "Test that override-checkout overrides branch matchers as well"
545
546 # Make sure the parent job repo is branched, so it gets
547 # implied branch matchers.
548 self.create_branch('org/project1', 'stable')
549 self.fake_gerrit.addEvent(
550 self.fake_gerrit.getFakeBranchCreatedEvent(
551 'org/project1', 'stable'))
552
553 # The child job repo should have a branch which does not exist
554 # in the parent job repo.
555 self.create_branch('org/project2', 'devel')
556 self.fake_gerrit.addEvent(
557 self.fake_gerrit.getFakeBranchCreatedEvent(
558 'org/project2', 'devel'))
559
560 # A job in a repo with a weird branch name should use the
561 # parent job from the parent job's master (default) branch.
562 A = self.fake_gerrit.addFakeChange('org/project2', 'devel', 'A')
563 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
564 self.waitUntilSettled()
565 # project-test2 should run because it inherits from
566 # project-test1 and we will use the fallback branch to find
567 # project-test1 variants, but project-test1 itself, even
568 # though it is in the project-pipeline config, should not run
569 # because it doesn't directly match.
570 self.assertHistory([
571 dict(name='project-test1', result='SUCCESS', changes='1,1'),
572 dict(name='project-test2', result='SUCCESS', changes='1,1'),
573 ], ordered=False)
574
575
James E. Blair5d71d1a2018-01-26 14:26:18 -0800576class TestAllowedProjects(ZuulTestCase):
577 tenant_config_file = 'config/allowed-projects/main.yaml'
578
579 def test_allowed_projects(self):
580 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A')
581 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
582 self.waitUntilSettled()
583 self.assertEqual(A.reported, 1)
584 self.assertIn('Build succeeded', A.messages[0])
585
586 B = self.fake_gerrit.addFakeChange('org/project2', 'master', 'B')
587 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
588 self.waitUntilSettled()
589 self.assertEqual(B.reported, 1)
590 self.assertIn('Project org/project2 is not allowed '
591 'to run job test-project2', B.messages[0])
592
593 C = self.fake_gerrit.addFakeChange('org/project3', 'master', 'C')
594 self.fake_gerrit.addEvent(C.getPatchsetCreatedEvent(1))
595 self.waitUntilSettled()
596 self.assertEqual(C.reported, 1)
597 self.assertIn('Project org/project3 is not allowed '
598 'to run job restricted-job', C.messages[0])
599
600 self.assertHistory([
601 dict(name='test-project1', result='SUCCESS', changes='1,1'),
602 dict(name='restricted-job', result='SUCCESS', changes='1,1'),
603 ], ordered=False)
604
605
James E. Blair2a664502017-10-27 11:39:33 -0700606class TestCentralJobs(ZuulTestCase):
607 tenant_config_file = 'config/central-jobs/main.yaml'
608
609 def setUp(self):
610 super(TestCentralJobs, self).setUp()
611 self.create_branch('org/project', 'stable')
612 self.fake_gerrit.addEvent(
613 self.fake_gerrit.getFakeBranchCreatedEvent(
614 'org/project', 'stable'))
615 self.waitUntilSettled()
616
617 def _updateConfig(self, config, branch):
618 file_dict = {'.zuul.yaml': config}
619 C = self.fake_gerrit.addFakeChange('org/project', branch, 'C',
620 files=file_dict)
621 C.addApproval('Code-Review', 2)
622 self.fake_gerrit.addEvent(C.addApproval('Approved', 1))
623 self.waitUntilSettled()
624 self.fake_gerrit.addEvent(C.getChangeMergedEvent())
625 self.waitUntilSettled()
626
627 def _test_central_job_on_branch(self, branch, other_branch):
628 # Test that a job defined on a branchless repo only runs on
629 # the branch applied
630 config = textwrap.dedent(
631 """
632 - project:
633 name: org/project
634 check:
635 jobs:
636 - central-job
637 """)
638 self._updateConfig(config, branch)
639
640 A = self.fake_gerrit.addFakeChange('org/project', branch, 'A')
641 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
642 self.waitUntilSettled()
643
644 self.assertHistory([
645 dict(name='central-job', result='SUCCESS', changes='2,1')])
646
647 # No jobs should run for this change.
648 B = self.fake_gerrit.addFakeChange('org/project', other_branch, 'B')
649 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
650 self.waitUntilSettled()
651
652 self.assertHistory([
653 dict(name='central-job', result='SUCCESS', changes='2,1')])
654
655 def test_central_job_on_stable(self):
656 self._test_central_job_on_branch('master', 'stable')
657
658 def test_central_job_on_master(self):
659 self._test_central_job_on_branch('stable', 'master')
660
661 def _test_central_template_on_branch(self, branch, other_branch):
662 # Test that a project-template defined on a branchless repo
663 # only runs on the branch applied
664 config = textwrap.dedent(
665 """
666 - project:
667 name: org/project
668 templates: ['central-jobs']
669 """)
670 self._updateConfig(config, branch)
671
672 A = self.fake_gerrit.addFakeChange('org/project', branch, 'A')
673 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
674 self.waitUntilSettled()
675
676 self.assertHistory([
677 dict(name='central-job', result='SUCCESS', changes='2,1')])
678
679 # No jobs should run for this change.
680 B = self.fake_gerrit.addFakeChange('org/project', other_branch, 'B')
681 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
682 self.waitUntilSettled()
683
684 self.assertHistory([
685 dict(name='central-job', result='SUCCESS', changes='2,1')])
686
687 def test_central_template_on_stable(self):
688 self._test_central_template_on_branch('master', 'stable')
689
690 def test_central_template_on_master(self):
691 self._test_central_template_on_branch('stable', 'master')
692
693
James E. Blairff555742017-02-19 11:34:27 -0800694class TestInRepoConfig(ZuulTestCase):
James E. Blair83005782015-12-11 14:46:03 -0800695 # A temporary class to hold new tests while others are disabled
696
Tobias Henkelabf973e2017-07-28 10:07:34 +0200697 config_file = 'zuul-connections-gerrit-and-github.conf'
James E. Blair2a629ec2015-12-22 15:32:02 -0800698 tenant_config_file = 'config/in-repo/main.yaml'
James E. Blair83005782015-12-11 14:46:03 -0800699
James E. Blair83005782015-12-11 14:46:03 -0800700 def test_in_repo_config(self):
James E. Blair14abdf42015-12-09 16:11:53 -0800701 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
Tobias Henkelbf24fd12017-07-27 06:13:07 +0200702 A.addApproval('Code-Review', 2)
703 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
James E. Blair14abdf42015-12-09 16:11:53 -0800704 self.waitUntilSettled()
705 self.assertEqual(self.getJobFromHistory('project-test1').result,
706 'SUCCESS')
707 self.assertEqual(A.data['status'], 'MERGED')
708 self.assertEqual(A.reported, 2,
709 "A should report start and success")
710 self.assertIn('tenant-one-gate', A.messages[1],
711 "A should transit tenant-one gate")
James E. Blairb97ed802015-12-21 15:55:35 -0800712
James E. Blair3a098dd2017-10-04 14:37:29 -0700713 @skip("This test is useful, but not reliable")
714 def test_full_and_dynamic_reconfig(self):
715 self.executor_server.hold_jobs_in_build = True
716 in_repo_conf = textwrap.dedent(
717 """
718 - job:
719 name: project-test1
720
721 - project:
722 name: org/project
723 tenant-one-gate:
724 jobs:
725 - project-test1
726 """)
727
728 file_dict = {'.zuul.yaml': in_repo_conf}
729 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
730 files=file_dict)
731 A.addApproval('Code-Review', 2)
732 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
733 self.waitUntilSettled()
734 self.sched.reconfigure(self.config)
735 self.waitUntilSettled()
736
737 gc.collect()
738 pipelines = [obj for obj in gc.get_objects()
739 if isinstance(obj, zuul.model.Pipeline)]
740 self.assertEqual(len(pipelines), 4)
741
742 self.executor_server.hold_jobs_in_build = False
743 self.executor_server.release()
744 self.waitUntilSettled()
745
James E. Blair8b1dc3f2016-07-05 16:49:00 -0700746 def test_dynamic_config(self):
747 in_repo_conf = textwrap.dedent(
748 """
749 - job:
Tobias Henkelf02cf512017-07-21 22:55:34 +0200750 name: project-test1
751
752 - job:
James E. Blair8b1dc3f2016-07-05 16:49:00 -0700753 name: project-test2
James E. Blair2f589fe2017-10-26 12:57:41 -0700754 run: playbooks/project-test2.yaml
James E. Blair8b1dc3f2016-07-05 16:49:00 -0700755
Tobias Henkel53aa2ad2017-12-22 09:59:45 +0100756 - job:
757 name: project-test3
758 run: playbooks/project-test2.yaml
759
760 # add a job by the short project name
James E. Blair8b1dc3f2016-07-05 16:49:00 -0700761 - project:
762 name: org/project
763 tenant-one-gate:
764 jobs:
765 - project-test2
Tobias Henkel53aa2ad2017-12-22 09:59:45 +0100766
767 # add a job by the canonical project name
768 - project:
769 name: review.example.com/org/project
770 tenant-one-gate:
771 jobs:
772 - project-test3
James E. Blair8b1dc3f2016-07-05 16:49:00 -0700773 """)
774
James E. Blairc73c73a2017-01-20 15:15:15 -0800775 in_repo_playbook = textwrap.dedent(
776 """
777 - hosts: all
778 tasks: []
779 """)
780
781 file_dict = {'.zuul.yaml': in_repo_conf,
782 'playbooks/project-test2.yaml': in_repo_playbook}
James E. Blair8b1dc3f2016-07-05 16:49:00 -0700783 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
James E. Blairc73c73a2017-01-20 15:15:15 -0800784 files=file_dict)
Tobias Henkelbf24fd12017-07-27 06:13:07 +0200785 A.addApproval('Code-Review', 2)
786 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
James E. Blair8b1dc3f2016-07-05 16:49:00 -0700787 self.waitUntilSettled()
James E. Blair8b1dc3f2016-07-05 16:49:00 -0700788 self.assertEqual(A.data['status'], 'MERGED')
789 self.assertEqual(A.reported, 2,
790 "A should report start and success")
791 self.assertIn('tenant-one-gate', A.messages[1],
792 "A should transit tenant-one gate")
James E. Blair646322f2017-01-27 15:50:34 -0800793 self.assertHistory([
Tobias Henkel53aa2ad2017-12-22 09:59:45 +0100794 dict(name='project-test2', result='SUCCESS', changes='1,1'),
795 dict(name='project-test3', result='SUCCESS', changes='1,1'),
796 ], ordered=False)
James E. Blair646322f2017-01-27 15:50:34 -0800797
James E. Blairc2a5ed72017-02-20 14:12:01 -0500798 self.fake_gerrit.addEvent(A.getChangeMergedEvent())
James E. Blair7bbd7a32017-03-06 11:36:13 -0800799 self.waitUntilSettled()
James E. Blairc2a5ed72017-02-20 14:12:01 -0500800
James E. Blair646322f2017-01-27 15:50:34 -0800801 # Now that the config change is landed, it should be live for
802 # subsequent changes.
803 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
Tobias Henkelbf24fd12017-07-27 06:13:07 +0200804 B.addApproval('Code-Review', 2)
805 self.fake_gerrit.addEvent(B.addApproval('Approved', 1))
James E. Blair646322f2017-01-27 15:50:34 -0800806 self.waitUntilSettled()
807 self.assertEqual(self.getJobFromHistory('project-test2').result,
808 'SUCCESS')
809 self.assertHistory([
810 dict(name='project-test2', result='SUCCESS', changes='1,1'),
Tobias Henkel53aa2ad2017-12-22 09:59:45 +0100811 dict(name='project-test3', result='SUCCESS', changes='1,1'),
812 dict(name='project-test2', result='SUCCESS', changes='2,1'),
813 dict(name='project-test3', result='SUCCESS', changes='2,1'),
814 ], ordered=False)
James E. Blairc73c73a2017-01-20 15:15:15 -0800815
James E. Blair6bc10482017-10-20 11:28:53 -0700816 def test_dynamic_template(self):
James E. Blair2a664502017-10-27 11:39:33 -0700817 # Tests that a project can't update a template in another
818 # project.
James E. Blair6bc10482017-10-20 11:28:53 -0700819 in_repo_conf = textwrap.dedent(
820 """
821 - job:
822 name: project-test1
823
824 - project-template:
825 name: common-config-template
826 check:
827 jobs:
828 - project-test1
829
830 - project:
831 name: org/project
832 templates: [common-config-template]
833 """)
834
835 file_dict = {'.zuul.yaml': in_repo_conf}
836 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
837 files=file_dict)
838 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
839 self.waitUntilSettled()
James E. Blair2a664502017-10-27 11:39:33 -0700840
841 self.assertEqual(A.patchsets[0]['approvals'][0]['value'], "-1")
842 self.assertIn('Project template common-config-template '
843 'is already defined',
844 A.messages[0],
845 "A should have failed the check pipeline")
James E. Blair6bc10482017-10-20 11:28:53 -0700846
Tobias Henkelf02cf512017-07-21 22:55:34 +0200847 def test_dynamic_config_non_existing_job(self):
848 """Test that requesting a non existent job fails"""
849 in_repo_conf = textwrap.dedent(
850 """
851 - job:
852 name: project-test1
853
854 - project:
855 name: org/project
856 check:
857 jobs:
858 - non-existent-job
859 """)
860
861 in_repo_playbook = textwrap.dedent(
862 """
863 - hosts: all
864 tasks: []
865 """)
866
867 file_dict = {'.zuul.yaml': in_repo_conf,
868 'playbooks/project-test2.yaml': in_repo_playbook}
869 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
870 files=file_dict)
871 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
872 self.waitUntilSettled()
873 self.assertEqual(A.reported, 1,
874 "A should report failure")
875 self.assertEqual(A.patchsets[0]['approvals'][0]['value'], "-1")
876 self.assertIn('Job non-existent-job not defined', A.messages[0],
877 "A should have failed the check pipeline")
878 self.assertHistory([])
879
880 def test_dynamic_config_non_existing_job_in_template(self):
881 """Test that requesting a non existent job fails"""
882 in_repo_conf = textwrap.dedent(
883 """
884 - job:
885 name: project-test1
886
887 - project-template:
888 name: test-template
889 check:
890 jobs:
891 - non-existent-job
892
893 - project:
894 name: org/project
895 templates:
896 - test-template
897 """)
898
899 in_repo_playbook = textwrap.dedent(
900 """
901 - hosts: all
902 tasks: []
903 """)
904
905 file_dict = {'.zuul.yaml': in_repo_conf,
906 'playbooks/project-test2.yaml': in_repo_playbook}
907 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
908 files=file_dict)
909 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
910 self.waitUntilSettled()
911 self.assertEqual(A.reported, 1,
912 "A should report failure")
913 self.assertEqual(A.patchsets[0]['approvals'][0]['value'], "-1")
914 self.assertIn('Job non-existent-job not defined', A.messages[0],
915 "A should have failed the check pipeline")
916 self.assertHistory([])
917
Tobias Henkel0f714002017-06-30 23:30:52 +0200918 def test_dynamic_config_new_patchset(self):
919 self.executor_server.hold_jobs_in_build = True
920
921 tenant = self.sched.abide.tenants.get('tenant-one')
922 check_pipeline = tenant.layout.pipelines['check']
923
924 in_repo_conf = textwrap.dedent(
925 """
926 - job:
Tobias Henkelf02cf512017-07-21 22:55:34 +0200927 name: project-test1
James E. Blair2f589fe2017-10-26 12:57:41 -0700928 run: playbooks/project-test1.yaml
Tobias Henkelf02cf512017-07-21 22:55:34 +0200929
930 - job:
Tobias Henkel0f714002017-06-30 23:30:52 +0200931 name: project-test2
James E. Blair2f589fe2017-10-26 12:57:41 -0700932 run: playbooks/project-test2.yaml
Tobias Henkel0f714002017-06-30 23:30:52 +0200933
934 - project:
935 name: org/project
936 check:
937 jobs:
938 - project-test2
939 """)
940
941 in_repo_playbook = textwrap.dedent(
942 """
943 - hosts: all
944 tasks: []
945 """)
946
947 file_dict = {'.zuul.yaml': in_repo_conf,
948 'playbooks/project-test2.yaml': in_repo_playbook}
949 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
950 files=file_dict)
951 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
952 self.waitUntilSettled()
953
954 items = check_pipeline.getAllItems()
955 self.assertEqual(items[0].change.number, '1')
956 self.assertEqual(items[0].change.patchset, '1')
957 self.assertTrue(items[0].live)
958
959 in_repo_conf = textwrap.dedent(
960 """
961 - job:
Tobias Henkel0ce7ec62017-07-21 22:50:17 +0200962 name: project-test1
James E. Blair2f589fe2017-10-26 12:57:41 -0700963 run: playbooks/project-test1.yaml
Tobias Henkel0ce7ec62017-07-21 22:50:17 +0200964
965 - job:
Tobias Henkel0f714002017-06-30 23:30:52 +0200966 name: project-test2
James E. Blair2f589fe2017-10-26 12:57:41 -0700967 run: playbooks/project-test2.yaml
Tobias Henkel0f714002017-06-30 23:30:52 +0200968
969 - project:
970 name: org/project
971 check:
972 jobs:
973 - project-test1
974 - project-test2
975 """)
976 file_dict = {'.zuul.yaml': in_repo_conf,
977 'playbooks/project-test2.yaml': in_repo_playbook}
978
979 A.addPatchset(files=file_dict)
980 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(2))
981
982 self.waitUntilSettled()
983
984 items = check_pipeline.getAllItems()
985 self.assertEqual(items[0].change.number, '1')
986 self.assertEqual(items[0].change.patchset, '2')
987 self.assertTrue(items[0].live)
988
989 self.executor_server.hold_jobs_in_build = False
Tobias Henkel0ce7ec62017-07-21 22:50:17 +0200990 self.executor_server.release('project-test1')
991 self.waitUntilSettled()
Tobias Henkel0f714002017-06-30 23:30:52 +0200992 self.executor_server.release()
993 self.waitUntilSettled()
994
Tobias Henkel0ce7ec62017-07-21 22:50:17 +0200995 self.assertHistory([
996 dict(name='project-test2', result='ABORTED', changes='1,1'),
997 dict(name='project-test1', result='SUCCESS', changes='1,2'),
998 dict(name='project-test2', result='SUCCESS', changes='1,2')])
999
James E. Blairff555742017-02-19 11:34:27 -08001000 def test_in_repo_branch(self):
1001 in_repo_conf = textwrap.dedent(
1002 """
1003 - job:
Tobias Henkelf02cf512017-07-21 22:55:34 +02001004 name: project-test1
1005
1006 - job:
James E. Blairff555742017-02-19 11:34:27 -08001007 name: project-test2
James E. Blair2f589fe2017-10-26 12:57:41 -07001008 run: playbooks/project-test2.yaml
James E. Blairff555742017-02-19 11:34:27 -08001009
1010 - project:
1011 name: org/project
1012 tenant-one-gate:
1013 jobs:
1014 - project-test2
1015 """)
1016
1017 in_repo_playbook = textwrap.dedent(
1018 """
1019 - hosts: all
1020 tasks: []
1021 """)
1022
1023 file_dict = {'.zuul.yaml': in_repo_conf,
1024 'playbooks/project-test2.yaml': in_repo_playbook}
1025 self.create_branch('org/project', 'stable')
James E. Blair72facdc2017-08-17 10:29:12 -07001026 self.fake_gerrit.addEvent(
1027 self.fake_gerrit.getFakeBranchCreatedEvent(
1028 'org/project', 'stable'))
James E. Blair6069f2b2017-09-26 16:34:11 -07001029 self.waitUntilSettled()
James E. Blairff555742017-02-19 11:34:27 -08001030 A = self.fake_gerrit.addFakeChange('org/project', 'stable', 'A',
1031 files=file_dict)
Tobias Henkelbf24fd12017-07-27 06:13:07 +02001032 A.addApproval('Code-Review', 2)
1033 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
James E. Blairff555742017-02-19 11:34:27 -08001034 self.waitUntilSettled()
1035 self.assertEqual(A.data['status'], 'MERGED')
1036 self.assertEqual(A.reported, 2,
1037 "A should report start and success")
1038 self.assertIn('tenant-one-gate', A.messages[1],
1039 "A should transit tenant-one gate")
1040 self.assertHistory([
1041 dict(name='project-test2', result='SUCCESS', changes='1,1')])
1042 self.fake_gerrit.addEvent(A.getChangeMergedEvent())
James E. Blair7bbd7a32017-03-06 11:36:13 -08001043 self.waitUntilSettled()
James E. Blairff555742017-02-19 11:34:27 -08001044
1045 # The config change should not affect master.
1046 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
Tobias Henkelbf24fd12017-07-27 06:13:07 +02001047 B.addApproval('Code-Review', 2)
1048 self.fake_gerrit.addEvent(B.addApproval('Approved', 1))
James E. Blairff555742017-02-19 11:34:27 -08001049 self.waitUntilSettled()
1050 self.assertHistory([
1051 dict(name='project-test2', result='SUCCESS', changes='1,1'),
1052 dict(name='project-test1', result='SUCCESS', changes='2,1')])
1053
1054 # The config change should be live for further changes on
1055 # stable.
1056 C = self.fake_gerrit.addFakeChange('org/project', 'stable', 'C')
Tobias Henkelbf24fd12017-07-27 06:13:07 +02001057 C.addApproval('Code-Review', 2)
1058 self.fake_gerrit.addEvent(C.addApproval('Approved', 1))
James E. Blairff555742017-02-19 11:34:27 -08001059 self.waitUntilSettled()
1060 self.assertHistory([
1061 dict(name='project-test2', result='SUCCESS', changes='1,1'),
1062 dict(name='project-test1', result='SUCCESS', changes='2,1'),
1063 dict(name='project-test2', result='SUCCESS', changes='3,1')])
1064
James E. Blaira5a12492017-05-03 11:40:48 -07001065 def test_crd_dynamic_config_branch(self):
1066 # Test that we can create a job in one repo and be able to use
1067 # it from a different branch on a different repo.
1068
1069 self.create_branch('org/project1', 'stable')
James E. Blair72facdc2017-08-17 10:29:12 -07001070 self.fake_gerrit.addEvent(
1071 self.fake_gerrit.getFakeBranchCreatedEvent(
1072 'org/project1', 'stable'))
James E. Blaira5a12492017-05-03 11:40:48 -07001073
1074 in_repo_conf = textwrap.dedent(
1075 """
1076 - job:
Tobias Henkelf02cf512017-07-21 22:55:34 +02001077 name: project-test1
1078
1079 - job:
James E. Blaira5a12492017-05-03 11:40:48 -07001080 name: project-test2
James E. Blair2f589fe2017-10-26 12:57:41 -07001081 run: playbooks/project-test2.yaml
James E. Blaira5a12492017-05-03 11:40:48 -07001082
1083 - project:
1084 name: org/project
1085 check:
1086 jobs:
1087 - project-test2
1088 """)
1089
1090 in_repo_playbook = textwrap.dedent(
1091 """
1092 - hosts: all
1093 tasks: []
1094 """)
1095
1096 file_dict = {'.zuul.yaml': in_repo_conf,
1097 'playbooks/project-test2.yaml': in_repo_playbook}
1098 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
1099 files=file_dict)
1100
1101 second_repo_conf = textwrap.dedent(
1102 """
1103 - project:
1104 name: org/project1
1105 check:
1106 jobs:
1107 - project-test2
1108 """)
1109
1110 second_file_dict = {'.zuul.yaml': second_repo_conf}
1111 B = self.fake_gerrit.addFakeChange('org/project1', 'stable', 'B',
1112 files=second_file_dict)
1113 B.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
1114 B.subject, A.data['id'])
1115
1116 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
1117 self.waitUntilSettled()
1118 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
1119 self.waitUntilSettled()
1120
1121 self.assertEqual(A.reported, 1, "A should report")
1122 self.assertHistory([
1123 dict(name='project-test2', result='SUCCESS', changes='1,1'),
1124 dict(name='project-test2', result='SUCCESS', changes='1,1 2,1'),
1125 ])
1126
James E. Blair97043882017-09-06 15:51:17 -07001127 def test_yaml_list_error(self):
1128 in_repo_conf = textwrap.dedent(
1129 """
1130 job: foo
1131 """)
1132
1133 file_dict = {'.zuul.yaml': in_repo_conf}
1134 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
1135 files=file_dict)
1136 A.addApproval('Code-Review', 2)
1137 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
1138 self.waitUntilSettled()
1139
1140 self.assertEqual(A.data['status'], 'NEW')
1141 self.assertEqual(A.reported, 1,
1142 "A should report failure")
1143 self.assertIn('not a list', A.messages[0],
1144 "A should have a syntax error reported")
1145
1146 def test_yaml_dict_error(self):
1147 in_repo_conf = textwrap.dedent(
1148 """
1149 - job
1150 """)
1151
1152 file_dict = {'.zuul.yaml': in_repo_conf}
1153 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
1154 files=file_dict)
1155 A.addApproval('Code-Review', 2)
1156 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
1157 self.waitUntilSettled()
1158
1159 self.assertEqual(A.data['status'], 'NEW')
1160 self.assertEqual(A.reported, 1,
1161 "A should report failure")
1162 self.assertIn('not a dictionary', A.messages[0],
1163 "A should have a syntax error reported")
1164
James E. Blairec953e12017-12-11 11:56:18 -08001165 def test_yaml_duplicate_key_error(self):
1166 in_repo_conf = textwrap.dedent(
1167 """
1168 - job:
1169 name: foo
1170 name: bar
1171 """)
1172
1173 file_dict = {'.zuul.yaml': in_repo_conf}
1174 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
1175 files=file_dict)
1176 A.addApproval('Code-Review', 2)
1177 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
1178 self.waitUntilSettled()
1179
1180 self.assertEqual(A.data['status'], 'NEW')
1181 self.assertEqual(A.reported, 1,
1182 "A should report failure")
1183 self.assertIn('appears more than once', A.messages[0],
1184 "A should have a syntax error reported")
1185
James E. Blair97043882017-09-06 15:51:17 -07001186 def test_yaml_key_error(self):
1187 in_repo_conf = textwrap.dedent(
1188 """
1189 - job:
1190 name: project-test2
1191 """)
1192
1193 file_dict = {'.zuul.yaml': in_repo_conf}
1194 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
1195 files=file_dict)
1196 A.addApproval('Code-Review', 2)
1197 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
1198 self.waitUntilSettled()
1199
1200 self.assertEqual(A.data['status'], 'NEW')
1201 self.assertEqual(A.reported, 1,
1202 "A should report failure")
1203 self.assertIn('has more than one key', A.messages[0],
1204 "A should have a syntax error reported")
1205
1206 def test_yaml_unknown_error(self):
1207 in_repo_conf = textwrap.dedent(
1208 """
1209 - foobar:
1210 foo: bar
1211 """)
1212
1213 file_dict = {'.zuul.yaml': in_repo_conf}
1214 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
1215 files=file_dict)
1216 A.addApproval('Code-Review', 2)
1217 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
1218 self.waitUntilSettled()
1219
1220 self.assertEqual(A.data['status'], 'NEW')
1221 self.assertEqual(A.reported, 1,
1222 "A should report failure")
1223 self.assertIn('not recognized', A.messages[0],
1224 "A should have a syntax error reported")
1225
James E. Blair149b69c2017-03-02 10:48:16 -08001226 def test_untrusted_syntax_error(self):
James E. Blaire53250c2017-03-01 14:34:36 -08001227 in_repo_conf = textwrap.dedent(
1228 """
1229 - job:
1230 name: project-test2
1231 foo: error
1232 """)
1233
1234 file_dict = {'.zuul.yaml': in_repo_conf}
1235 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
1236 files=file_dict)
Tobias Henkelbf24fd12017-07-27 06:13:07 +02001237 A.addApproval('Code-Review', 2)
1238 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
James E. Blaire53250c2017-03-01 14:34:36 -08001239 self.waitUntilSettled()
1240
1241 self.assertEqual(A.data['status'], 'NEW')
Tobias Henkel9842bd72017-05-16 13:40:03 +02001242 self.assertEqual(A.reported, 1,
1243 "A should report failure")
1244 self.assertIn('syntax error', A.messages[0],
James E. Blaire53250c2017-03-01 14:34:36 -08001245 "A should have a syntax error reported")
1246
James E. Blair149b69c2017-03-02 10:48:16 -08001247 def test_trusted_syntax_error(self):
1248 in_repo_conf = textwrap.dedent(
1249 """
1250 - job:
1251 name: project-test2
1252 foo: error
1253 """)
1254
1255 file_dict = {'zuul.yaml': in_repo_conf}
1256 A = self.fake_gerrit.addFakeChange('common-config', 'master', 'A',
1257 files=file_dict)
Tobias Henkelbf24fd12017-07-27 06:13:07 +02001258 A.addApproval('Code-Review', 2)
1259 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
James E. Blair149b69c2017-03-02 10:48:16 -08001260 self.waitUntilSettled()
1261
1262 self.assertEqual(A.data['status'], 'NEW')
Tobias Henkel9842bd72017-05-16 13:40:03 +02001263 self.assertEqual(A.reported, 1,
1264 "A should report failure")
1265 self.assertIn('syntax error', A.messages[0],
James E. Blair149b69c2017-03-02 10:48:16 -08001266 "A should have a syntax error reported")
1267
James E. Blair6f140c72017-03-03 10:32:07 -08001268 def test_untrusted_yaml_error(self):
1269 in_repo_conf = textwrap.dedent(
1270 """
1271 - job:
1272 foo: error
1273 """)
1274
1275 file_dict = {'.zuul.yaml': in_repo_conf}
1276 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
1277 files=file_dict)
Tobias Henkelbf24fd12017-07-27 06:13:07 +02001278 A.addApproval('Code-Review', 2)
1279 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
James E. Blair6f140c72017-03-03 10:32:07 -08001280 self.waitUntilSettled()
1281
1282 self.assertEqual(A.data['status'], 'NEW')
Tobias Henkel9842bd72017-05-16 13:40:03 +02001283 self.assertEqual(A.reported, 1,
1284 "A should report failure")
1285 self.assertIn('syntax error', A.messages[0],
James E. Blair6f140c72017-03-03 10:32:07 -08001286 "A should have a syntax error reported")
1287
James E. Blairdb04e6a2017-05-03 14:49:36 -07001288 def test_untrusted_shadow_error(self):
1289 in_repo_conf = textwrap.dedent(
1290 """
1291 - job:
1292 name: common-config-test
1293 """)
1294
1295 file_dict = {'.zuul.yaml': in_repo_conf}
1296 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
1297 files=file_dict)
Tobias Henkelbf24fd12017-07-27 06:13:07 +02001298 A.addApproval('Code-Review', 2)
1299 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
James E. Blairdb04e6a2017-05-03 14:49:36 -07001300 self.waitUntilSettled()
1301
1302 self.assertEqual(A.data['status'], 'NEW')
Tobias Henkel9842bd72017-05-16 13:40:03 +02001303 self.assertEqual(A.reported, 1,
1304 "A should report failure")
1305 self.assertIn('not permitted to shadow', A.messages[0],
James E. Blairdb04e6a2017-05-03 14:49:36 -07001306 "A should have a syntax error reported")
1307
James E. Blaird5656ad2017-06-02 14:29:41 -07001308 def test_untrusted_pipeline_error(self):
1309 in_repo_conf = textwrap.dedent(
1310 """
1311 - pipeline:
1312 name: test
1313 """)
1314
1315 file_dict = {'.zuul.yaml': in_repo_conf}
1316 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
1317 files=file_dict)
Tobias Henkelbf24fd12017-07-27 06:13:07 +02001318 A.addApproval('Code-Review', 2)
1319 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
James E. Blaird5656ad2017-06-02 14:29:41 -07001320 self.waitUntilSettled()
1321
1322 self.assertEqual(A.data['status'], 'NEW')
1323 self.assertEqual(A.reported, 1,
1324 "A should report failure")
1325 self.assertIn('Pipelines may not be defined', A.messages[0],
1326 "A should have a syntax error reported")
1327
1328 def test_untrusted_project_error(self):
1329 in_repo_conf = textwrap.dedent(
1330 """
1331 - project:
1332 name: org/project1
1333 """)
1334
1335 file_dict = {'.zuul.yaml': in_repo_conf}
1336 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
1337 files=file_dict)
Tobias Henkelbf24fd12017-07-27 06:13:07 +02001338 A.addApproval('Code-Review', 2)
1339 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
James E. Blaird5656ad2017-06-02 14:29:41 -07001340 self.waitUntilSettled()
1341
1342 self.assertEqual(A.data['status'], 'NEW')
1343 self.assertEqual(A.reported, 1,
1344 "A should report failure")
1345 self.assertIn('the only project definition permitted', A.messages[0],
1346 "A should have a syntax error reported")
1347
James E. Blairf03173b2017-10-10 10:46:43 -07001348 def test_untrusted_depends_on_trusted(self):
1349 with open(os.path.join(FIXTURE_DIR,
1350 'config/in-repo/git/',
1351 'common-config/zuul.yaml')) as f:
1352 common_config = f.read()
1353
1354 common_config += textwrap.dedent(
1355 """
1356 - job:
1357 name: project-test9
1358 """)
1359
1360 file_dict = {'zuul.yaml': common_config}
1361 A = self.fake_gerrit.addFakeChange('common-config', 'master', 'A',
1362 files=file_dict)
1363 in_repo_conf = textwrap.dedent(
1364 """
1365 - job:
1366 name: project-test1
1367 - project:
1368 name: org/project
1369 check:
1370 jobs:
1371 - project-test9
1372 """)
1373
1374 file_dict = {'zuul.yaml': in_repo_conf}
1375 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B',
1376 files=file_dict)
1377 B.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
1378 B.subject, A.data['id'])
1379 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
1380 self.waitUntilSettled()
1381
1382 self.assertEqual(B.data['status'], 'NEW')
1383 self.assertEqual(B.reported, 1,
1384 "B should report failure")
1385 self.assertIn('depends on a change to a config project',
1386 B.messages[0],
1387 "A should have a syntax error reported")
1388
James E. Blaire64b0e42017-06-08 11:23:34 -07001389 def test_duplicate_node_error(self):
1390 in_repo_conf = textwrap.dedent(
1391 """
1392 - nodeset:
1393 name: duplicate
1394 nodes:
1395 - name: compute
James E. Blair16d96a02017-06-08 11:32:56 -07001396 label: foo
James E. Blaire64b0e42017-06-08 11:23:34 -07001397 - name: compute
James E. Blair16d96a02017-06-08 11:32:56 -07001398 label: foo
James E. Blaire64b0e42017-06-08 11:23:34 -07001399 """)
1400
1401 file_dict = {'.zuul.yaml': in_repo_conf}
1402 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
1403 files=file_dict)
Tobias Henkelbf24fd12017-07-27 06:13:07 +02001404 A.addApproval('Code-Review', 2)
1405 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
James E. Blaire64b0e42017-06-08 11:23:34 -07001406 self.waitUntilSettled()
1407
1408 self.assertEqual(A.data['status'], 'NEW')
1409 self.assertEqual(A.reported, 1,
1410 "A should report failure")
1411 self.assertIn('appears multiple times', A.messages[0],
1412 "A should have a syntax error reported")
1413
1414 def test_duplicate_group_error(self):
1415 in_repo_conf = textwrap.dedent(
1416 """
1417 - nodeset:
1418 name: duplicate
1419 nodes:
1420 - name: compute
James E. Blair16d96a02017-06-08 11:32:56 -07001421 label: foo
James E. Blaire64b0e42017-06-08 11:23:34 -07001422 groups:
1423 - name: group
1424 nodes: compute
1425 - name: group
1426 nodes: compute
1427 """)
1428
1429 file_dict = {'.zuul.yaml': in_repo_conf}
1430 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
1431 files=file_dict)
Tobias Henkelbf24fd12017-07-27 06:13:07 +02001432 A.addApproval('Code-Review', 2)
1433 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
James E. Blaire64b0e42017-06-08 11:23:34 -07001434 self.waitUntilSettled()
1435
1436 self.assertEqual(A.data['status'], 'NEW')
1437 self.assertEqual(A.reported, 1,
1438 "A should report failure")
1439 self.assertIn('appears multiple times', A.messages[0],
1440 "A should have a syntax error reported")
1441
James E. Blair4ae399f2017-09-20 17:15:09 -07001442 def test_secret_not_found_error(self):
1443 in_repo_conf = textwrap.dedent(
1444 """
1445 - job:
1446 name: test
1447 secrets: does-not-exist
1448 """)
1449
1450 file_dict = {'.zuul.yaml': in_repo_conf}
1451 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
1452 files=file_dict)
1453 A.addApproval('Code-Review', 2)
1454 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
1455 self.waitUntilSettled()
1456
1457 self.assertEqual(A.data['status'], 'NEW')
1458 self.assertEqual(A.reported, 1,
1459 "A should report failure")
1460 self.assertIn('secret "does-not-exist" was not found', A.messages[0],
1461 "A should have a syntax error reported")
1462
1463 def test_nodeset_not_found_error(self):
1464 in_repo_conf = textwrap.dedent(
1465 """
1466 - job:
1467 name: test
1468 nodeset: does-not-exist
1469 """)
1470
1471 file_dict = {'.zuul.yaml': in_repo_conf}
1472 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
1473 files=file_dict)
1474 A.addApproval('Code-Review', 2)
1475 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
1476 self.waitUntilSettled()
1477
1478 self.assertEqual(A.data['status'], 'NEW')
1479 self.assertEqual(A.reported, 1,
1480 "A should report failure")
1481 self.assertIn('nodeset "does-not-exist" was not found', A.messages[0],
1482 "A should have a syntax error reported")
1483
James E. Blair89e25eb2017-09-26 09:11:31 -07001484 def test_template_not_found_error(self):
1485 in_repo_conf = textwrap.dedent(
1486 """
1487 - job:
1488 name: project-test1
1489 - project:
1490 name: org/project
1491 templates:
1492 - does-not-exist
1493 """)
1494
1495 file_dict = {'.zuul.yaml': in_repo_conf}
1496 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
1497 files=file_dict)
1498 A.addApproval('Code-Review', 2)
1499 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
1500 self.waitUntilSettled()
1501
1502 self.assertEqual(A.data['status'], 'NEW')
1503 self.assertEqual(A.reported, 1,
1504 "A should report failure")
1505 self.assertIn('project template "does-not-exist" was not found',
1506 A.messages[0],
1507 "A should have a syntax error reported")
1508
Monty Taylor8be3c0c2017-10-06 10:37:37 -05001509 def test_job_list_in_project_template_not_dict_error(self):
1510 in_repo_conf = textwrap.dedent(
1511 """
1512 - job:
1513 name: project-test1
1514 - project-template:
1515 name: some-jobs
1516 check:
1517 jobs:
1518 - project-test1:
1519 - required-projects:
1520 org/project2
1521 """)
1522
1523 file_dict = {'.zuul.yaml': in_repo_conf}
1524 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
1525 files=file_dict)
1526 A.addApproval('Code-Review', 2)
1527 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
1528 self.waitUntilSettled()
1529
1530 self.assertEqual(A.data['status'], 'NEW')
1531 self.assertEqual(A.reported, 1,
1532 "A should report failure")
1533 self.assertIn('expected str for dictionary value',
1534 A.messages[0], "A should have a syntax error reported")
1535
1536 def test_job_list_in_project_not_dict_error(self):
1537 in_repo_conf = textwrap.dedent(
1538 """
1539 - job:
1540 name: project-test1
1541 - project:
1542 name: org/project1
1543 check:
1544 jobs:
1545 - project-test1:
1546 - required-projects:
1547 org/project2
1548 """)
1549
1550 file_dict = {'.zuul.yaml': in_repo_conf}
1551 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
1552 files=file_dict)
1553 A.addApproval('Code-Review', 2)
1554 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
1555 self.waitUntilSettled()
1556
1557 self.assertEqual(A.data['status'], 'NEW')
1558 self.assertEqual(A.reported, 1,
1559 "A should report failure")
1560 self.assertIn('expected str for dictionary value',
1561 A.messages[0], "A should have a syntax error reported")
1562
James E. Blair1235f142017-10-07 09:11:43 -07001563 def test_project_template(self):
1564 # Tests that a project template is not modified when used, and
1565 # can therefore be used in subsequent reconfigurations.
1566 in_repo_conf = textwrap.dedent(
1567 """
1568 - job:
1569 name: project-test1
James E. Blair2f589fe2017-10-26 12:57:41 -07001570 run: playbooks/project-test1.yaml
James E. Blair1235f142017-10-07 09:11:43 -07001571 - project-template:
1572 name: some-jobs
1573 tenant-one-gate:
1574 jobs:
1575 - project-test1:
1576 required-projects:
1577 - org/project1
1578 - project:
1579 name: org/project
1580 templates:
1581 - some-jobs
1582 """)
1583
1584 file_dict = {'.zuul.yaml': in_repo_conf}
1585 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
1586 files=file_dict)
1587 A.addApproval('Code-Review', 2)
1588 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
1589 self.waitUntilSettled()
1590 self.assertEqual(A.data['status'], 'MERGED')
1591 self.fake_gerrit.addEvent(A.getChangeMergedEvent())
1592 self.waitUntilSettled()
1593 in_repo_conf = textwrap.dedent(
1594 """
1595 - project:
1596 name: org/project1
1597 templates:
1598 - some-jobs
1599 """)
1600 file_dict = {'.zuul.yaml': in_repo_conf}
1601 B = self.fake_gerrit.addFakeChange('org/project1', 'master', 'B',
1602 files=file_dict)
1603 B.addApproval('Code-Review', 2)
1604 self.fake_gerrit.addEvent(B.addApproval('Approved', 1))
1605 self.waitUntilSettled()
1606 self.assertEqual(B.data['status'], 'MERGED')
1607
James E. Blairbccdfcf2017-10-07 13:37:26 -07001608 def test_job_remove_add(self):
1609 # Tests that a job can be removed from one repo and added in another.
1610 # First, remove the current config for project1 since it
1611 # references the job we want to remove.
1612 file_dict = {'.zuul.yaml': None}
1613 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A',
1614 files=file_dict)
1615 A.setMerged()
1616 self.fake_gerrit.addEvent(A.getChangeMergedEvent())
1617 self.waitUntilSettled()
1618 # Then propose a change to delete the job from one repo...
1619 file_dict = {'.zuul.yaml': None}
1620 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B',
1621 files=file_dict)
1622 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
1623 self.waitUntilSettled()
1624 # ...and a second that depends on it that adds it to another repo.
1625 in_repo_conf = textwrap.dedent(
1626 """
1627 - job:
1628 name: project-test1
James E. Blair2f589fe2017-10-26 12:57:41 -07001629 run: playbooks/project-test1.yaml
James E. Blairbccdfcf2017-10-07 13:37:26 -07001630
1631 - project:
1632 name: org/project1
1633 check:
1634 jobs:
1635 - project-test1
1636 """)
1637 in_repo_playbook = textwrap.dedent(
1638 """
1639 - hosts: all
1640 tasks: []
1641 """)
1642 file_dict = {'.zuul.yaml': in_repo_conf,
1643 'playbooks/project-test1.yaml': in_repo_playbook}
1644 C = self.fake_gerrit.addFakeChange('org/project1', 'master', 'C',
1645 files=file_dict,
1646 parent='refs/changes/1/1/1')
1647 C.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
1648 C.subject, B.data['id'])
1649 self.fake_gerrit.addEvent(C.getPatchsetCreatedEvent(1))
1650 self.waitUntilSettled()
1651 self.assertHistory([
1652 dict(name='project-test1', result='SUCCESS', changes='2,1 3,1'),
1653 ], ordered=False)
1654
James E. Blair09f9ffe2017-07-11 15:30:25 -07001655 def test_multi_repo(self):
1656 downstream_repo_conf = textwrap.dedent(
1657 """
1658 - project:
1659 name: org/project1
1660 tenant-one-gate:
1661 jobs:
1662 - project-test1
1663
1664 - job:
1665 name: project1-test1
1666 parent: project-test1
1667 """)
1668
1669 file_dict = {'.zuul.yaml': downstream_repo_conf}
1670 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A',
1671 files=file_dict)
Tobias Henkelbf24fd12017-07-27 06:13:07 +02001672 A.addApproval('Code-Review', 2)
1673 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
James E. Blair09f9ffe2017-07-11 15:30:25 -07001674 self.waitUntilSettled()
1675
1676 self.assertEqual(A.data['status'], 'MERGED')
1677 self.fake_gerrit.addEvent(A.getChangeMergedEvent())
1678 self.waitUntilSettled()
1679
1680 upstream_repo_conf = textwrap.dedent(
1681 """
1682 - job:
1683 name: project-test1
James E. Blair2f589fe2017-10-26 12:57:41 -07001684 run: playbooks/project-test1.yaml
James E. Blair09f9ffe2017-07-11 15:30:25 -07001685
1686 - job:
1687 name: project-test2
1688
1689 - project:
1690 name: org/project
1691 tenant-one-gate:
1692 jobs:
1693 - project-test1
1694 """)
1695
1696 file_dict = {'.zuul.yaml': upstream_repo_conf}
1697 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B',
1698 files=file_dict)
Tobias Henkelbf24fd12017-07-27 06:13:07 +02001699 B.addApproval('Code-Review', 2)
1700 self.fake_gerrit.addEvent(B.addApproval('Approved', 1))
James E. Blair09f9ffe2017-07-11 15:30:25 -07001701 self.waitUntilSettled()
1702
1703 self.assertEqual(B.data['status'], 'MERGED')
1704 self.fake_gerrit.addEvent(B.getChangeMergedEvent())
1705 self.waitUntilSettled()
1706
1707 tenant = self.sched.abide.tenants.get('tenant-one')
1708 # Ensure the latest change is reflected in the config; if it
1709 # isn't this will raise an exception.
1710 tenant.layout.getJob('project-test2')
1711
James E. Blair332636e2017-09-05 10:14:35 -07001712 def test_pipeline_error(self):
1713 with open(os.path.join(FIXTURE_DIR,
1714 'config/in-repo/git/',
1715 'common-config/zuul.yaml')) as f:
1716 base_common_config = f.read()
1717
1718 in_repo_conf_A = textwrap.dedent(
1719 """
1720 - pipeline:
1721 name: periodic
1722 foo: error
1723 """)
1724
1725 file_dict = {'zuul.yaml': None,
1726 'zuul.d/main.yaml': base_common_config,
1727 'zuul.d/test1.yaml': in_repo_conf_A}
1728 A = self.fake_gerrit.addFakeChange('common-config', 'master', 'A',
1729 files=file_dict)
1730 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
1731 self.waitUntilSettled()
1732 self.assertEqual(A.reported, 1,
1733 "A should report failure")
1734 self.assertIn('syntax error',
1735 A.messages[0],
1736 "A should have an error reported")
1737
1738 def test_change_series_error(self):
1739 with open(os.path.join(FIXTURE_DIR,
1740 'config/in-repo/git/',
1741 'common-config/zuul.yaml')) as f:
1742 base_common_config = f.read()
1743
1744 in_repo_conf_A = textwrap.dedent(
1745 """
1746 - pipeline:
1747 name: periodic
1748 foo: error
1749 """)
1750
1751 file_dict = {'zuul.yaml': None,
1752 'zuul.d/main.yaml': base_common_config,
1753 'zuul.d/test1.yaml': in_repo_conf_A}
1754 A = self.fake_gerrit.addFakeChange('common-config', 'master', 'A',
1755 files=file_dict)
1756
1757 in_repo_conf_B = textwrap.dedent(
1758 """
1759 - job:
1760 name: project-test2
1761 foo: error
1762 """)
1763
1764 file_dict = {'zuul.yaml': None,
1765 'zuul.d/main.yaml': base_common_config,
1766 'zuul.d/test1.yaml': in_repo_conf_A,
1767 'zuul.d/test2.yaml': in_repo_conf_B}
1768 B = self.fake_gerrit.addFakeChange('common-config', 'master', 'B',
1769 files=file_dict)
1770 B.setDependsOn(A, 1)
1771 C = self.fake_gerrit.addFakeChange('common-config', 'master', 'C')
1772 C.setDependsOn(B, 1)
1773 self.fake_gerrit.addEvent(C.getPatchsetCreatedEvent(1))
1774 self.waitUntilSettled()
1775
1776 self.assertEqual(C.reported, 1,
1777 "C should report failure")
1778 self.assertIn('depends on a change that failed to merge',
1779 C.messages[0],
1780 "C should have an error reported")
1781
James E. Blair1ef8f7c2017-12-13 17:18:34 -08001782 def test_pipeline_debug(self):
1783 in_repo_conf = textwrap.dedent(
1784 """
1785 - job:
1786 name: project-test1
1787 run: playbooks/project-test1.yaml
1788 - project:
1789 name: org/project
1790 check:
1791 debug: True
1792 jobs:
1793 - project-test1
1794 """)
1795
1796 file_dict = {'.zuul.yaml': in_repo_conf}
1797 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
1798 files=file_dict)
1799 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
1800 self.waitUntilSettled()
1801
1802 self.assertEqual(A.data['status'], 'NEW')
1803 self.assertEqual(A.reported, 1,
1804 "A should report success")
1805 self.assertIn('Debug information:',
1806 A.messages[0], "A should have debug info")
1807
James E. Blairc73c73a2017-01-20 15:15:15 -08001808
James E. Blairc9455002017-09-06 09:22:19 -07001809class TestInRepoJoin(ZuulTestCase):
1810 # In this config, org/project is not a member of any pipelines, so
1811 # that we may test the changes that cause it to join them.
1812
1813 tenant_config_file = 'config/in-repo-join/main.yaml'
1814
1815 def test_dynamic_dependent_pipeline(self):
1816 # Test dynamically adding a project to a
1817 # dependent pipeline for the first time
1818 self.executor_server.hold_jobs_in_build = True
1819
1820 tenant = self.sched.abide.tenants.get('tenant-one')
1821 gate_pipeline = tenant.layout.pipelines['gate']
1822
1823 in_repo_conf = textwrap.dedent(
1824 """
1825 - job:
1826 name: project-test1
James E. Blair2f589fe2017-10-26 12:57:41 -07001827 run: playbooks/project-test1.yaml
James E. Blairc9455002017-09-06 09:22:19 -07001828
1829 - job:
1830 name: project-test2
James E. Blair2f589fe2017-10-26 12:57:41 -07001831 run: playbooks/project-test2.yaml
James E. Blairc9455002017-09-06 09:22:19 -07001832
1833 - project:
1834 name: org/project
1835 gate:
1836 jobs:
1837 - project-test2
1838 """)
1839
1840 in_repo_playbook = textwrap.dedent(
1841 """
1842 - hosts: all
1843 tasks: []
1844 """)
1845
1846 file_dict = {'.zuul.yaml': in_repo_conf,
1847 'playbooks/project-test2.yaml': in_repo_playbook}
1848 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
1849 files=file_dict)
1850 A.addApproval('Code-Review', 2)
1851 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
1852 self.waitUntilSettled()
1853
1854 items = gate_pipeline.getAllItems()
1855 self.assertEqual(items[0].change.number, '1')
1856 self.assertEqual(items[0].change.patchset, '1')
1857 self.assertTrue(items[0].live)
1858
1859 self.executor_server.hold_jobs_in_build = False
1860 self.executor_server.release()
1861 self.waitUntilSettled()
1862
1863 # Make sure the dynamic queue got cleaned up
1864 self.assertEqual(gate_pipeline.queues, [])
1865
1866 def test_dynamic_dependent_pipeline_failure(self):
1867 # Test that a change behind a failing change adding a project
1868 # to a dependent pipeline is dequeued.
1869 self.executor_server.hold_jobs_in_build = True
1870
1871 in_repo_conf = textwrap.dedent(
1872 """
1873 - job:
1874 name: project-test1
James E. Blair2f589fe2017-10-26 12:57:41 -07001875 run: playbooks/project-test1.yaml
James E. Blairc9455002017-09-06 09:22:19 -07001876
1877 - project:
1878 name: org/project
1879 gate:
1880 jobs:
1881 - project-test1
1882 """)
1883
1884 file_dict = {'.zuul.yaml': in_repo_conf}
1885 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
1886 files=file_dict)
1887 self.executor_server.failJob('project-test1', A)
1888 A.addApproval('Code-Review', 2)
1889 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
1890 self.waitUntilSettled()
1891
1892 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
1893 B.addApproval('Code-Review', 2)
1894 self.fake_gerrit.addEvent(B.addApproval('Approved', 1))
1895 self.waitUntilSettled()
1896
James E. Blair3490c5d2017-09-07 08:33:23 -07001897 self.orderedRelease()
James E. Blairc9455002017-09-06 09:22:19 -07001898 self.waitUntilSettled()
1899 self.assertEqual(A.reported, 2,
1900 "A should report start and failure")
1901 self.assertEqual(A.data['status'], 'NEW')
1902 self.assertEqual(B.reported, 1,
1903 "B should report start")
1904 self.assertHistory([
1905 dict(name='project-test1', result='FAILURE', changes='1,1'),
James E. Blair3490c5d2017-09-07 08:33:23 -07001906 dict(name='project-test1', result='ABORTED', changes='1,1 2,1'),
James E. Blairc9455002017-09-06 09:22:19 -07001907 ], ordered=False)
1908
James E. Blair0af198f2017-09-06 09:52:35 -07001909 def test_dynamic_dependent_pipeline_absent(self):
1910 # Test that a series of dependent changes don't report merge
1911 # failures to a pipeline they aren't in.
1912 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1913 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
1914 B.setDependsOn(A, 1)
1915
1916 A.addApproval('Code-Review', 2)
1917 A.addApproval('Approved', 1)
1918 B.addApproval('Code-Review', 2)
1919 self.fake_gerrit.addEvent(B.addApproval('Approved', 1))
1920 self.waitUntilSettled()
1921 self.assertEqual(A.reported, 0,
1922 "A should not report")
1923 self.assertEqual(A.data['status'], 'NEW')
1924 self.assertEqual(B.reported, 0,
1925 "B should not report")
1926 self.assertEqual(B.data['status'], 'NEW')
1927 self.assertHistory([])
1928
James E. Blairc9455002017-09-06 09:22:19 -07001929
James E. Blairc73c73a2017-01-20 15:15:15 -08001930class TestAnsible(AnsibleZuulTestCase):
1931 # A temporary class to hold new tests while others are disabled
1932
1933 tenant_config_file = 'config/ansible/main.yaml'
1934
1935 def test_playbook(self):
Jamie Lennox7655b552017-03-17 12:33:38 +11001936 # Keep the jobdir around so we can inspect contents if an
1937 # assert fails.
1938 self.executor_server.keep_jobdir = True
1939 # Output extra ansible info so we might see errors.
1940 self.executor_server.verbose = True
1941 # Add a site variables file, used by check-vars
1942 path = os.path.join(FIXTURE_DIR, 'config', 'ansible',
1943 'variables.yaml')
1944 self.config.set('executor', 'variables', path)
James E. Blairc73c73a2017-01-20 15:15:15 -08001945 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
1946 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
1947 self.waitUntilSettled()
Tobias Henkel077f2f32017-05-30 20:16:46 +02001948 build_timeout = self.getJobFromHistory('timeout')
Jamie Lennox7655b552017-03-17 12:33:38 +11001949 with self.jobLog(build_timeout):
1950 self.assertEqual(build_timeout.result, 'TIMED_OUT')
Tobias Henkel077f2f32017-05-30 20:16:46 +02001951 build_faillocal = self.getJobFromHistory('faillocal')
Jamie Lennox7655b552017-03-17 12:33:38 +11001952 with self.jobLog(build_faillocal):
1953 self.assertEqual(build_faillocal.result, 'FAILURE')
Tobias Henkel077f2f32017-05-30 20:16:46 +02001954 build_failpost = self.getJobFromHistory('failpost')
Jamie Lennox7655b552017-03-17 12:33:38 +11001955 with self.jobLog(build_failpost):
1956 self.assertEqual(build_failpost.result, 'POST_FAILURE')
Tobias Henkel077f2f32017-05-30 20:16:46 +02001957 build_check_vars = self.getJobFromHistory('check-vars')
Jamie Lennox7655b552017-03-17 12:33:38 +11001958 with self.jobLog(build_check_vars):
1959 self.assertEqual(build_check_vars.result, 'SUCCESS')
Monty Tayloraff8b402017-08-16 18:40:41 -05001960 build_check_secret_names = self.getJobFromHistory('check-secret-names')
1961 with self.jobLog(build_check_secret_names):
1962 self.assertEqual(build_check_secret_names.result, 'SUCCESS')
Tobias Henkel077f2f32017-05-30 20:16:46 +02001963 build_hello = self.getJobFromHistory('hello-world')
Jamie Lennox7655b552017-03-17 12:33:38 +11001964 with self.jobLog(build_hello):
1965 self.assertEqual(build_hello.result, 'SUCCESS')
Tobias Henkel077f2f32017-05-30 20:16:46 +02001966 build_python27 = self.getJobFromHistory('python27')
Jamie Lennox7655b552017-03-17 12:33:38 +11001967 with self.jobLog(build_python27):
1968 self.assertEqual(build_python27.result, 'SUCCESS')
1969 flag_path = os.path.join(self.test_root,
1970 build_python27.uuid + '.flag')
1971 self.assertTrue(os.path.exists(flag_path))
1972 copied_path = os.path.join(self.test_root, build_python27.uuid +
1973 '.copied')
1974 self.assertTrue(os.path.exists(copied_path))
1975 failed_path = os.path.join(self.test_root, build_python27.uuid +
1976 '.failed')
1977 self.assertFalse(os.path.exists(failed_path))
1978 pre_flag_path = os.path.join(self.test_root, build_python27.uuid +
1979 '.pre.flag')
1980 self.assertTrue(os.path.exists(pre_flag_path))
1981 post_flag_path = os.path.join(self.test_root, build_python27.uuid +
1982 '.post.flag')
1983 self.assertTrue(os.path.exists(post_flag_path))
1984 bare_role_flag_path = os.path.join(self.test_root,
1985 build_python27.uuid +
1986 '.bare-role.flag')
1987 self.assertTrue(os.path.exists(bare_role_flag_path))
1988 secrets_path = os.path.join(self.test_root,
1989 build_python27.uuid + '.secrets')
1990 with open(secrets_path) as f:
1991 self.assertEqual(f.read(), "test-username test-password")
James E. Blairb9c0d772017-03-03 14:34:49 -08001992
Jamie Lennox7655b552017-03-17 12:33:38 +11001993 msg = A.messages[0]
1994 success = "{} https://success.example.com/zuul-logs/{}"
1995 fail = "{} https://failure.example.com/zuul-logs/{}"
1996 self.assertIn(success.format("python27", build_python27.uuid), msg)
1997 self.assertIn(fail.format("faillocal", build_faillocal.uuid), msg)
1998 self.assertIn(success.format("check-vars",
1999 build_check_vars.uuid), msg)
2000 self.assertIn(success.format("hello-world", build_hello.uuid), msg)
2001 self.assertIn(fail.format("timeout", build_timeout.uuid), msg)
2002 self.assertIn(fail.format("failpost", build_failpost.uuid), msg)
Tobias Henkel077f2f32017-05-30 20:16:46 +02002003
James E. Blairabbaa6f2017-04-06 16:11:44 -07002004 def _add_job(self, job_name):
2005 conf = textwrap.dedent(
2006 """
2007 - job:
2008 name: %s
James E. Blair2f589fe2017-10-26 12:57:41 -07002009 run: playbooks/%s.yaml
James E. Blairabbaa6f2017-04-06 16:11:44 -07002010
2011 - project:
2012 name: org/plugin-project
2013 check:
2014 jobs:
2015 - %s
James E. Blair2f589fe2017-10-26 12:57:41 -07002016 """ % (job_name, job_name, job_name))
James E. Blairabbaa6f2017-04-06 16:11:44 -07002017
2018 file_dict = {'.zuul.yaml': conf}
2019 A = self.fake_gerrit.addFakeChange('org/plugin-project', 'master', 'A',
2020 files=file_dict)
2021 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2022 self.waitUntilSettled()
2023
2024 def test_plugins(self):
2025 # Keep the jobdir around so we can inspect contents if an
2026 # assert fails.
2027 self.executor_server.keep_jobdir = True
2028 # Output extra ansible info so we might see errors.
2029 self.executor_server.verbose = True
2030
2031 count = 0
2032 plugin_tests = [
2033 ('passwd', 'FAILURE'),
2034 ('cartesian', 'SUCCESS'),
2035 ('consul_kv', 'FAILURE'),
2036 ('credstash', 'FAILURE'),
2037 ('csvfile_good', 'SUCCESS'),
2038 ('csvfile_bad', 'FAILURE'),
Monty Taylor93ad2212017-08-02 14:59:50 -05002039 ('uri_bad_path', 'FAILURE'),
2040 ('uri_bad_scheme', 'FAILURE'),
Monty Taylor788a40e2017-08-02 16:14:05 -05002041 ('block_local_override', 'FAILURE'),
Monty Taylor8da768f2017-08-31 14:15:35 -05002042 ('file_local_good', 'SUCCESS'),
2043 ('file_local_bad', 'FAILURE'),
James E. Blairabbaa6f2017-04-06 16:11:44 -07002044 ]
2045 for job_name, result in plugin_tests:
2046 count += 1
2047 self._add_job(job_name)
2048
2049 job = self.getJobFromHistory(job_name)
2050 with self.jobLog(job):
2051 self.assertEqual(count, len(self.history))
2052 build = self.history[-1]
2053 self.assertEqual(build.result, result)
2054
2055 # TODOv3(jeblair): parse the ansible output and verify we're
2056 # getting the exception we expect.
2057
James E. Blairb9c0d772017-03-03 14:34:49 -08002058
James E. Blaira4d4eef2017-06-30 14:49:17 -07002059class TestPrePlaybooks(AnsibleZuulTestCase):
2060 # A temporary class to hold new tests while others are disabled
2061
2062 tenant_config_file = 'config/pre-playbook/main.yaml'
2063
2064 def test_pre_playbook_fail(self):
2065 # Test that we run the post playbooks (but not the actual
2066 # playbook) when a pre-playbook fails.
2067 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2068 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2069 self.waitUntilSettled()
2070 build = self.getJobFromHistory('python27')
2071 self.assertIsNone(build.result)
2072 self.assertIn('RETRY_LIMIT', A.messages[0])
2073 flag_path = os.path.join(self.test_root, build.uuid +
2074 '.main.flag')
2075 self.assertFalse(os.path.exists(flag_path))
2076 pre_flag_path = os.path.join(self.test_root, build.uuid +
2077 '.pre.flag')
2078 self.assertFalse(os.path.exists(pre_flag_path))
2079 post_flag_path = os.path.join(self.test_root, build.uuid +
2080 '.post.flag')
James E. Blair21037782017-07-19 11:56:55 -07002081 self.assertTrue(os.path.exists(post_flag_path),
2082 "The file %s should exist" % post_flag_path)
James E. Blaira4d4eef2017-06-30 14:49:17 -07002083
2084
James E. Blairbacbb882017-10-17 09:48:23 -07002085class TestPostPlaybooks(AnsibleZuulTestCase):
2086 tenant_config_file = 'config/post-playbook/main.yaml'
2087
2088 def test_post_playbook_abort(self):
2089 # Test that when we abort a job in the post playbook, that we
2090 # don't send back POST_FAILURE.
2091 self.executor_server.verbose = True
2092 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2093 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2094
2095 while not len(self.builds):
2096 time.sleep(0.1)
2097 build = self.builds[0]
2098
2099 post_start = os.path.join(self.test_root, build.uuid +
2100 '.post_start.flag')
2101 start = time.time()
2102 while time.time() < start + 90:
2103 if os.path.exists(post_start):
2104 break
2105 time.sleep(0.1)
2106 # The post playbook has started, abort the job
2107 self.fake_gerrit.addEvent(A.getChangeAbandonedEvent())
2108 self.waitUntilSettled()
2109
2110 build = self.getJobFromHistory('python27')
2111 self.assertEqual('ABORTED', build.result)
2112
2113 post_end = os.path.join(self.test_root, build.uuid +
2114 '.post_end.flag')
2115 self.assertTrue(os.path.exists(post_start))
2116 self.assertFalse(os.path.exists(post_end))
2117
2118
James E. Blairb9c0d772017-03-03 14:34:49 -08002119class TestBrokenConfig(ZuulTestCase):
2120 # Test that we get an appropriate syntax error if we start with a
2121 # broken config.
2122
2123 tenant_config_file = 'config/broken/main.yaml'
2124
2125 def setUp(self):
2126 with testtools.ExpectedException(
2127 zuul.configloader.ConfigurationSyntaxError,
2128 "\nZuul encountered a syntax error"):
2129 super(TestBrokenConfig, self).setUp()
2130
2131 def test_broken_config_on_startup(self):
2132 pass
Ricardo Carrillo Cruz22994f92016-12-02 11:41:58 +00002133
2134
2135class TestProjectKeys(ZuulTestCase):
2136 # Test that we can generate project keys
2137
2138 # Normally the test infrastructure copies a static key in place
2139 # for each project before starting tests. This saves time because
2140 # Zuul's automatic key-generation on startup can be slow. To make
2141 # sure we exercise that code, in this test we allow Zuul to create
2142 # keys for the project on startup.
2143 create_project_keys = True
Tobias Henkelabf973e2017-07-28 10:07:34 +02002144 config_file = 'zuul-connections-gerrit-and-github.conf'
Ricardo Carrillo Cruz22994f92016-12-02 11:41:58 +00002145 tenant_config_file = 'config/in-repo/main.yaml'
2146
2147 def test_key_generation(self):
2148 key_root = os.path.join(self.state_root, 'keys')
2149 private_key_file = os.path.join(key_root, 'gerrit/org/project.pem')
2150 # Make sure that a proper key was created on startup
2151 with open(private_key_file, "rb") as f:
James E. Blairbf1a4f22017-03-17 10:59:37 -07002152 private_key, public_key = \
2153 encryption.deserialize_rsa_keypair(f.read())
Ricardo Carrillo Cruz22994f92016-12-02 11:41:58 +00002154
2155 with open(os.path.join(FIXTURE_DIR, 'private.pem')) as i:
2156 fixture_private_key = i.read()
2157
2158 # Make sure that we didn't just end up with the static fixture
2159 # key
2160 self.assertNotEqual(fixture_private_key, private_key)
2161
2162 # Make sure it's the right length
2163 self.assertEqual(4096, private_key.key_size)
James E. Blairbce76932017-05-04 10:03:15 -07002164
2165
James E. Blairbb94dfa2017-07-11 07:45:19 -07002166class RoleTestCase(ZuulTestCase):
James E. Blair1b27f6a2017-07-14 14:09:07 -07002167 def _assertRolePath(self, build, playbook, content):
2168 path = os.path.join(self.test_root, build.uuid,
2169 'ansible', playbook, 'ansible.cfg')
2170 roles_paths = []
2171 with open(path) as f:
2172 for line in f:
2173 if line.startswith('roles_path'):
2174 roles_paths.append(line)
2175 print(roles_paths)
2176 if content:
2177 self.assertEqual(len(roles_paths), 1,
2178 "Should have one roles_path line in %s" %
2179 (playbook,))
2180 self.assertIn(content, roles_paths[0])
2181 else:
2182 self.assertEqual(len(roles_paths), 0,
2183 "Should have no roles_path line in %s" %
2184 (playbook,))
2185
James E. Blairbb94dfa2017-07-11 07:45:19 -07002186
2187class TestRoles(RoleTestCase):
2188 tenant_config_file = 'config/roles/main.yaml'
2189
James E. Blairbce76932017-05-04 10:03:15 -07002190 def test_role(self):
2191 # This exercises a proposed change to a role being checked out
2192 # and used.
2193 A = self.fake_gerrit.addFakeChange('bare-role', 'master', 'A')
2194 B = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2195 B.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
2196 B.subject, A.data['id'])
2197 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2198 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
2199 self.waitUntilSettled()
2200 self.assertHistory([
2201 dict(name='project-test', result='SUCCESS', changes='1,1 2,1'),
2202 ])
James E. Blair6459db12017-06-29 14:57:20 -07002203
James E. Blair1b27f6a2017-07-14 14:09:07 -07002204 def test_role_inheritance(self):
2205 self.executor_server.hold_jobs_in_build = True
2206 conf = textwrap.dedent(
2207 """
2208 - job:
2209 name: parent
2210 roles:
2211 - zuul: bare-role
Ian Wienand548c43c2017-12-05 14:16:32 +11002212 pre-run: playbooks/parent-pre.yaml
2213 post-run: playbooks/parent-post.yaml
James E. Blair1b27f6a2017-07-14 14:09:07 -07002214
2215 - job:
2216 name: project-test
2217 parent: parent
James E. Blair2f589fe2017-10-26 12:57:41 -07002218 run: playbooks/project-test.yaml
James E. Blair1b27f6a2017-07-14 14:09:07 -07002219 roles:
2220 - zuul: org/project
2221
2222 - project:
2223 name: org/project
2224 check:
2225 jobs:
2226 - project-test
2227 """)
2228
2229 file_dict = {'.zuul.yaml': conf}
2230 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
2231 files=file_dict)
2232 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2233 self.waitUntilSettled()
2234
2235 self.assertEqual(len(self.builds), 1)
2236 build = self.getBuildByName('project-test')
2237 self._assertRolePath(build, 'pre_playbook_0', 'role_0')
2238 self._assertRolePath(build, 'playbook_0', 'role_0')
2239 self._assertRolePath(build, 'playbook_0', 'role_1')
2240 self._assertRolePath(build, 'post_playbook_0', 'role_0')
2241
2242 self.executor_server.hold_jobs_in_build = False
2243 self.executor_server.release()
2244 self.waitUntilSettled()
2245
2246 self.assertHistory([
2247 dict(name='project-test', result='SUCCESS', changes='1,1'),
2248 ])
2249
James E. Blair6f699732017-07-18 14:19:11 -07002250 def test_role_error(self):
2251 conf = textwrap.dedent(
2252 """
2253 - job:
2254 name: project-test
James E. Blair2f589fe2017-10-26 12:57:41 -07002255 run: playbooks/project-test.yaml
James E. Blair6f699732017-07-18 14:19:11 -07002256 roles:
2257 - zuul: common-config
2258
2259 - project:
2260 name: org/project
2261 check:
2262 jobs:
2263 - project-test
2264 """)
2265
2266 file_dict = {'.zuul.yaml': conf}
2267 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
2268 files=file_dict)
2269 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2270 self.waitUntilSettled()
2271 self.assertIn(
2272 '- project-test project-test : ERROR Unable to find role',
2273 A.messages[-1])
2274
James E. Blair6459db12017-06-29 14:57:20 -07002275
James E. Blairbb94dfa2017-07-11 07:45:19 -07002276class TestImplicitRoles(RoleTestCase):
2277 tenant_config_file = 'config/implicit-roles/main.yaml'
2278
2279 def test_missing_roles(self):
2280 # Test implicit and explicit roles for a project which does
2281 # not have roles. The implicit role should be silently
2282 # ignored since the project doesn't supply roles, but if a
2283 # user declares an explicit role, it should error.
2284 self.executor_server.hold_jobs_in_build = True
2285 A = self.fake_gerrit.addFakeChange('org/norole-project', 'master', 'A')
2286 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2287 self.waitUntilSettled()
2288
2289 self.assertEqual(len(self.builds), 2)
2290 build = self.getBuildByName('implicit-role-fail')
2291 self._assertRolePath(build, 'playbook_0', None)
2292
2293 self.executor_server.hold_jobs_in_build = False
2294 self.executor_server.release()
2295 self.waitUntilSettled()
2296 # The retry_limit doesn't get recorded
2297 self.assertHistory([
2298 dict(name='implicit-role-fail', result='SUCCESS', changes='1,1'),
2299 ])
2300
2301 def test_roles(self):
2302 # Test implicit and explicit roles for a project which does
2303 # have roles. In both cases, we should end up with the role
2304 # in the path. In the explicit case, ensure we end up with
2305 # the name we specified.
2306 self.executor_server.hold_jobs_in_build = True
2307 A = self.fake_gerrit.addFakeChange('org/role-project', 'master', 'A')
2308 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2309 self.waitUntilSettled()
2310
2311 self.assertEqual(len(self.builds), 2)
2312 build = self.getBuildByName('implicit-role-ok')
2313 self._assertRolePath(build, 'playbook_0', 'role_0')
2314
2315 build = self.getBuildByName('explicit-role-ok')
2316 self._assertRolePath(build, 'playbook_0', 'role_0')
2317
2318 self.executor_server.hold_jobs_in_build = False
2319 self.executor_server.release()
2320 self.waitUntilSettled()
2321 self.assertHistory([
2322 dict(name='implicit-role-ok', result='SUCCESS', changes='1,1'),
2323 dict(name='explicit-role-ok', result='SUCCESS', changes='1,1'),
2324 ], ordered=False)
2325
2326
James E. Blair6459db12017-06-29 14:57:20 -07002327class TestShadow(ZuulTestCase):
2328 tenant_config_file = 'config/shadow/main.yaml'
2329
2330 def test_shadow(self):
2331 # Test that a repo is allowed to shadow another's job definitions.
2332 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2333 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2334 self.waitUntilSettled()
2335 self.assertHistory([
2336 dict(name='test1', result='SUCCESS', changes='1,1'),
2337 dict(name='test2', result='SUCCESS', changes='1,1'),
James E. Blairadafa6c2017-07-12 08:50:56 -07002338 ], ordered=False)
James E. Blair196f61a2017-06-30 15:42:29 -07002339
2340
2341class TestDataReturn(AnsibleZuulTestCase):
2342 tenant_config_file = 'config/data-return/main.yaml'
2343
2344 def test_data_return(self):
James E. Blair196f61a2017-06-30 15:42:29 -07002345 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2346 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2347 self.waitUntilSettled()
2348 self.assertHistory([
2349 dict(name='data-return', result='SUCCESS', changes='1,1'),
James E. Blair88e79c02017-07-07 13:36:54 -07002350 dict(name='data-return-relative', result='SUCCESS', changes='1,1'),
James E. Blair698703c2017-09-15 20:58:30 -06002351 dict(name='child', result='SUCCESS', changes='1,1'),
James E. Blair88e79c02017-07-07 13:36:54 -07002352 ], ordered=False)
2353 self.assertIn('- data-return http://example.com/test/log/url/',
2354 A.messages[-1])
2355 self.assertIn('- data-return-relative '
2356 'http://example.com/test/log/url/docs/index.html',
James E. Blair196f61a2017-06-30 15:42:29 -07002357 A.messages[-1])
Clint Byrumdc8a0902017-07-20 16:36:27 -07002358
2359
2360class TestDiskAccounting(AnsibleZuulTestCase):
2361 config_file = 'zuul-disk-accounting.conf'
2362 tenant_config_file = 'config/disk-accountant/main.yaml'
2363
2364 def test_disk_accountant_kills_job(self):
2365 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2366 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2367 self.waitUntilSettled()
2368 self.assertHistory([
2369 dict(name='dd-big-empty-file', result='ABORTED', changes='1,1')])
Tristan Cacqueray82f864b2017-08-01 05:54:42 +00002370
2371
2372class TestMaxNodesPerJob(AnsibleZuulTestCase):
2373 tenant_config_file = 'config/multi-tenant/main.yaml'
2374
Tristan Cacquerayc98bff72017-09-10 15:25:26 +00002375 def test_max_timeout_exceeded(self):
Tristan Cacqueray82f864b2017-08-01 05:54:42 +00002376 in_repo_conf = textwrap.dedent(
2377 """
2378 - job:
2379 name: test-job
James E. Blair7e3e6882017-09-20 15:47:13 -07002380 nodeset:
2381 nodes:
2382 - name: node01
2383 label: fake
2384 - name: node02
2385 label: fake
2386 - name: node03
2387 label: fake
2388 - name: node04
2389 label: fake
2390 - name: node05
2391 label: fake
2392 - name: node06
2393 label: fake
Tristan Cacqueray82f864b2017-08-01 05:54:42 +00002394 """)
2395 file_dict = {'.zuul.yaml': in_repo_conf}
2396 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A',
2397 files=file_dict)
2398 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2399 self.waitUntilSettled()
2400 self.assertIn('The job "test-job" exceeds tenant max-nodes-per-job 5.',
2401 A.messages[0], "A should fail because of nodes limit")
2402
2403 B = self.fake_gerrit.addFakeChange('org/project2', 'master', 'A',
2404 files=file_dict)
2405 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
2406 self.waitUntilSettled()
2407 self.assertNotIn("exceeds tenant max-nodes", B.messages[0],
2408 "B should not fail because of nodes limit")
James E. Blair2bab6e72017-08-07 09:52:45 -07002409
2410
Tristan Cacquerayc98bff72017-09-10 15:25:26 +00002411class TestMaxTimeout(AnsibleZuulTestCase):
2412 tenant_config_file = 'config/multi-tenant/main.yaml'
2413
2414 def test_max_nodes_reached(self):
2415 in_repo_conf = textwrap.dedent(
2416 """
2417 - job:
2418 name: test-job
2419 timeout: 3600
2420 """)
2421 file_dict = {'.zuul.yaml': in_repo_conf}
2422 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A',
2423 files=file_dict)
2424 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2425 self.waitUntilSettled()
2426 self.assertIn('The job "test-job" exceeds tenant max-job-timeout',
2427 A.messages[0], "A should fail because of timeout limit")
2428
2429 B = self.fake_gerrit.addFakeChange('org/project2', 'master', 'A',
2430 files=file_dict)
2431 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
2432 self.waitUntilSettled()
2433 self.assertNotIn("exceeds tenant max-job-timeout", B.messages[0],
2434 "B should not fail because of timeout limit")
2435
2436
James E. Blair7edc25f2017-10-26 10:47:14 -07002437class TestPragma(ZuulTestCase):
2438 tenant_config_file = 'config/pragma/main.yaml'
2439
2440 def test_no_pragma(self):
2441 self.create_branch('org/project', 'stable')
2442 with open(os.path.join(FIXTURE_DIR,
2443 'config/pragma/git/',
2444 'org_project/nopragma.yaml')) as f:
2445 config = f.read()
2446 file_dict = {'.zuul.yaml': config}
2447 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
2448 files=file_dict)
2449 A.addApproval('Code-Review', 2)
2450 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
2451 self.waitUntilSettled()
2452 self.fake_gerrit.addEvent(A.getChangeMergedEvent())
2453 self.waitUntilSettled()
2454
2455 # This is an untrusted repo with 2 branches, so it should have
2456 # an implied branch matcher for the job.
2457 tenant = self.sched.abide.tenants.get('tenant-one')
2458 jobs = tenant.layout.getJobs('test-job')
2459 self.assertEqual(len(jobs), 1)
2460 for job in tenant.layout.getJobs('test-job'):
2461 self.assertIsNotNone(job.branch_matcher)
2462
2463 def test_pragma(self):
2464 self.create_branch('org/project', 'stable')
2465 with open(os.path.join(FIXTURE_DIR,
2466 'config/pragma/git/',
2467 'org_project/pragma.yaml')) as f:
2468 config = f.read()
2469 file_dict = {'.zuul.yaml': config}
2470 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
2471 files=file_dict)
2472 A.addApproval('Code-Review', 2)
2473 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
2474 self.waitUntilSettled()
2475 self.fake_gerrit.addEvent(A.getChangeMergedEvent())
2476 self.waitUntilSettled()
2477
2478 # This is an untrusted repo with 2 branches, so it would
2479 # normally have an implied branch matcher, but our pragma
2480 # overrides it.
2481 tenant = self.sched.abide.tenants.get('tenant-one')
2482 jobs = tenant.layout.getJobs('test-job')
2483 self.assertEqual(len(jobs), 1)
2484 for job in tenant.layout.getJobs('test-job'):
2485 self.assertIsNone(job.branch_matcher)
2486
2487
James E. Blair37c3d8c2017-12-13 15:06:11 -08002488class TestPragmaMultibranch(ZuulTestCase):
2489 tenant_config_file = 'config/pragma-multibranch/main.yaml'
2490
2491 def test_no_branch_matchers(self):
2492 self.create_branch('org/project1', 'stable/pike')
2493 self.create_branch('org/project2', 'stable/jewel')
2494 self.fake_gerrit.addEvent(
2495 self.fake_gerrit.getFakeBranchCreatedEvent(
2496 'org/project1', 'stable/pike'))
2497 self.fake_gerrit.addEvent(
2498 self.fake_gerrit.getFakeBranchCreatedEvent(
2499 'org/project2', 'stable/jewel'))
2500 self.waitUntilSettled()
2501 # We want the jobs defined on the stable/pike branch of
2502 # project1 to apply to the stable/jewel branch of project2.
2503
2504 # First, without the pragma line, the jobs should not run
2505 # because in project1 they have branch matchers for pike, so
2506 # they will not match a jewel change.
2507 B = self.fake_gerrit.addFakeChange('org/project2', 'stable/jewel', 'B')
2508 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
2509 self.waitUntilSettled()
2510 self.assertHistory([])
2511
2512 # Add a pragma line to disable implied branch matchers in
2513 # project1, so that the jobs and templates apply to both
2514 # branches.
2515 with open(os.path.join(FIXTURE_DIR,
2516 'config/pragma-multibranch/git/',
2517 'org_project1/zuul.yaml')) as f:
2518 config = f.read()
2519 extra_conf = textwrap.dedent(
2520 """
2521 - pragma:
2522 implied-branch-matchers: False
2523 """)
2524 config = extra_conf + config
2525 file_dict = {'zuul.yaml': config}
2526 A = self.fake_gerrit.addFakeChange('org/project1', 'stable/pike', 'A',
2527 files=file_dict)
2528 A.addApproval('Code-Review', 2)
2529 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
2530 self.waitUntilSettled()
2531 self.fake_gerrit.addEvent(A.getChangeMergedEvent())
2532 self.waitUntilSettled()
2533
2534 # Now verify that when we propose a change to jewel, we get
2535 # the pike/jewel jobs.
2536 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
2537 self.waitUntilSettled()
2538 self.assertHistory([
2539 dict(name='test-job1', result='SUCCESS', changes='1,1'),
2540 dict(name='test-job2', result='SUCCESS', changes='1,1'),
2541 ], ordered=False)
2542
2543 def test_supplied_branch_matchers(self):
2544 self.create_branch('org/project1', 'stable/pike')
2545 self.create_branch('org/project2', 'stable/jewel')
2546 self.fake_gerrit.addEvent(
2547 self.fake_gerrit.getFakeBranchCreatedEvent(
2548 'org/project1', 'stable/pike'))
2549 self.fake_gerrit.addEvent(
2550 self.fake_gerrit.getFakeBranchCreatedEvent(
2551 'org/project2', 'stable/jewel'))
2552 self.waitUntilSettled()
2553 # We want the jobs defined on the stable/pike branch of
2554 # project1 to apply to the stable/jewel branch of project2.
2555
2556 # First, without the pragma line, the jobs should not run
2557 # because in project1 they have branch matchers for pike, so
2558 # they will not match a jewel change.
2559 B = self.fake_gerrit.addFakeChange('org/project2', 'stable/jewel', 'B')
2560 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
2561 self.waitUntilSettled()
2562 self.assertHistory([])
2563
2564 # Add a pragma line to disable implied branch matchers in
2565 # project1, so that the jobs and templates apply to both
2566 # branches.
2567 with open(os.path.join(FIXTURE_DIR,
2568 'config/pragma-multibranch/git/',
2569 'org_project1/zuul.yaml')) as f:
2570 config = f.read()
2571 extra_conf = textwrap.dedent(
2572 """
2573 - pragma:
2574 implied-branches:
2575 - stable/pike
2576 - stable/jewel
2577 """)
2578 config = extra_conf + config
2579 file_dict = {'zuul.yaml': config}
2580 A = self.fake_gerrit.addFakeChange('org/project1', 'stable/pike', 'A',
2581 files=file_dict)
2582 A.addApproval('Code-Review', 2)
2583 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
2584 self.waitUntilSettled()
2585 self.fake_gerrit.addEvent(A.getChangeMergedEvent())
2586 self.waitUntilSettled()
2587 # Now verify that when we propose a change to jewel, we get
2588 # the pike/jewel jobs.
2589 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
2590 self.waitUntilSettled()
2591 self.assertHistory([
2592 dict(name='test-job1', result='SUCCESS', changes='1,1'),
2593 dict(name='test-job2', result='SUCCESS', changes='1,1'),
2594 ], ordered=False)
2595
2596
James E. Blair2bab6e72017-08-07 09:52:45 -07002597class TestBaseJobs(ZuulTestCase):
2598 tenant_config_file = 'config/base-jobs/main.yaml'
2599
2600 def test_multiple_base_jobs(self):
2601 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2602 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2603 self.waitUntilSettled()
2604 self.assertHistory([
2605 dict(name='my-job', result='SUCCESS', changes='1,1'),
2606 dict(name='other-job', result='SUCCESS', changes='1,1'),
2607 ], ordered=False)
2608 self.assertEqual(self.getJobFromHistory('my-job').
2609 parameters['zuul']['jobtags'],
2610 ['mybase'])
2611 self.assertEqual(self.getJobFromHistory('other-job').
2612 parameters['zuul']['jobtags'],
2613 ['otherbase'])
2614
2615 def test_untrusted_base_job(self):
2616 """Test that a base job may not be defined in an untrusted repo"""
2617 in_repo_conf = textwrap.dedent(
2618 """
2619 - job:
2620 name: fail-base
2621 parent: null
2622 """)
2623
2624 file_dict = {'.zuul.yaml': in_repo_conf}
2625 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
2626 files=file_dict)
2627 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2628 self.waitUntilSettled()
2629 self.assertEqual(A.reported, 1,
2630 "A should report failure")
2631 self.assertEqual(A.patchsets[0]['approvals'][0]['value'], "-1")
2632 self.assertIn('Base jobs must be defined in config projects',
2633 A.messages[0])
2634 self.assertHistory([])
James E. Blairdb089032017-08-15 13:42:12 -07002635
2636
James E. Blaira17a8e72018-01-17 13:45:25 -08002637class TestSecrets(ZuulTestCase):
2638 tenant_config_file = 'config/secrets/main.yaml'
2639 secret = {'password': 'test-password',
2640 'username': 'test-username'}
2641
2642 def _getSecrets(self, job, pbtype):
2643 secrets = []
2644 build = self.getJobFromHistory(job)
2645 for pb in build.parameters[pbtype]:
2646 secrets.append(pb['secrets'])
2647 return secrets
2648
2649 def test_secret_branch(self):
2650 # Test that we can use a secret defined in another branch of
2651 # the same project.
2652 self.create_branch('org/project2', 'stable')
2653 self.fake_gerrit.addEvent(
2654 self.fake_gerrit.getFakeBranchCreatedEvent(
2655 'org/project2', 'stable'))
2656 self.waitUntilSettled()
2657
2658 with open(os.path.join(FIXTURE_DIR,
2659 'config/secrets/git/',
2660 'org_project2/zuul-secret.yaml')) as f:
2661 config = f.read()
2662
2663 file_dict = {'zuul.yaml': config}
2664 A = self.fake_gerrit.addFakeChange('org/project2', 'master', 'A',
2665 files=file_dict)
2666 A.addApproval('Code-Review', 2)
2667 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
2668 self.waitUntilSettled()
2669 self.assertEqual(A.data['status'], 'MERGED')
2670 self.fake_gerrit.addEvent(A.getChangeMergedEvent())
2671 self.waitUntilSettled()
2672
2673 in_repo_conf = textwrap.dedent(
2674 """
2675 - job:
2676 parent: base
2677 name: project2-secret
2678 run: playbooks/secret.yaml
2679 secrets: [project2_secret]
2680
2681 - project:
2682 check:
2683 jobs:
2684 - project2-secret
2685 gate:
2686 jobs:
2687 - noop
2688 """)
2689 file_dict = {'zuul.yaml': in_repo_conf}
2690 B = self.fake_gerrit.addFakeChange('org/project2', 'stable', 'B',
2691 files=file_dict)
2692 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
2693 self.waitUntilSettled()
2694 self.assertEqual(B.reported, 1, "B should report success")
2695 self.assertHistory([
2696 dict(name='project2-secret', result='SUCCESS', changes='2,1'),
2697 ])
2698 self.assertEqual(
2699 self._getSecrets('project2-secret', 'playbooks'),
2700 [{'project2_secret': self.secret}])
2701
2702 def test_secret_branch_duplicate(self):
2703 # Test that we can create a duplicate secret on a different
2704 # branch of the same project -- i.e., that when we branch
2705 # master to stable on a project with a secret, nothing
2706 # changes.
2707 self.create_branch('org/project1', 'stable')
2708 self.fake_gerrit.addEvent(
2709 self.fake_gerrit.getFakeBranchCreatedEvent(
2710 'org/project1', 'stable'))
2711 self.waitUntilSettled()
2712
2713 A = self.fake_gerrit.addFakeChange('org/project1', 'stable', 'A')
2714 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2715 self.waitUntilSettled()
2716 self.assertEqual(A.reported, 1,
2717 "A should report success")
2718 self.assertHistory([
2719 dict(name='project1-secret', result='SUCCESS', changes='1,1'),
2720 ])
2721 self.assertEqual(
2722 self._getSecrets('project1-secret', 'playbooks'),
2723 [{'project1_secret': self.secret}])
2724
2725 def test_secret_branch_error_same_branch(self):
2726 # Test that we are unable to define a secret twice on the same
2727 # project-branch.
2728 in_repo_conf = textwrap.dedent(
2729 """
2730 - secret:
2731 name: project1_secret
2732 data: {}
2733 - secret:
2734 name: project1_secret
2735 data: {}
2736 """)
2737 file_dict = {'zuul.yaml': in_repo_conf}
2738 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A',
2739 files=file_dict)
2740 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2741 self.waitUntilSettled()
2742 self.assertIn('already defined', A.messages[0])
2743
2744 def test_secret_branch_error_same_project(self):
2745 # Test that we are unable to create a secret which differs
2746 # from another with the same name -- i.e., that if we have a
2747 # duplicate secret on multiple branches of the same project,
2748 # they must be identical.
2749 self.create_branch('org/project1', 'stable')
2750 self.fake_gerrit.addEvent(
2751 self.fake_gerrit.getFakeBranchCreatedEvent(
2752 'org/project1', 'stable'))
2753 self.waitUntilSettled()
2754
2755 in_repo_conf = textwrap.dedent(
2756 """
2757 - secret:
2758 name: project1_secret
2759 data: {}
2760 """)
2761 file_dict = {'zuul.yaml': in_repo_conf}
2762 A = self.fake_gerrit.addFakeChange('org/project1', 'stable', 'A',
2763 files=file_dict)
2764 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2765 self.waitUntilSettled()
2766 self.assertIn('does not match existing definition in branch master',
2767 A.messages[0])
2768
2769 def test_secret_branch_error_other_project(self):
2770 # Test that we are unable to create a secret with the same
2771 # name as another. We're never allowed to have a secret with
2772 # the same name outside of a project.
2773 in_repo_conf = textwrap.dedent(
2774 """
2775 - secret:
2776 name: project1_secret
2777 data: {}
2778 """)
2779 file_dict = {'zuul.yaml': in_repo_conf}
2780 A = self.fake_gerrit.addFakeChange('org/project2', 'master', 'A',
2781 files=file_dict)
2782 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2783 self.waitUntilSettled()
2784 self.assertIn('already defined in project org/project1',
2785 A.messages[0])
2786
2787
James E. Blairdf91ab32017-10-25 17:57:13 -07002788class TestSecretInheritance(ZuulTestCase):
2789 tenant_config_file = 'config/secret-inheritance/main.yaml'
2790
2791 def _getSecrets(self, job, pbtype):
2792 secrets = []
2793 build = self.getJobFromHistory(job)
2794 for pb in build.parameters[pbtype]:
2795 secrets.append(pb['secrets'])
2796 return secrets
2797
2798 def _checkTrustedSecrets(self):
2799 secret = {'longpassword': 'test-passwordtest-password',
2800 'password': 'test-password',
2801 'username': 'test-username'}
2802 self.assertEqual(
2803 self._getSecrets('trusted-secrets', 'playbooks'),
James E. Blair2f589fe2017-10-26 12:57:41 -07002804 [{'trusted-secret': secret}])
James E. Blairdf91ab32017-10-25 17:57:13 -07002805 self.assertEqual(
2806 self._getSecrets('trusted-secrets', 'pre_playbooks'), [])
2807 self.assertEqual(
2808 self._getSecrets('trusted-secrets', 'post_playbooks'), [])
2809
2810 self.assertEqual(
2811 self._getSecrets('trusted-secrets-trusted-child',
James E. Blair2f589fe2017-10-26 12:57:41 -07002812 'playbooks'), [{}])
James E. Blairdf91ab32017-10-25 17:57:13 -07002813 self.assertEqual(
2814 self._getSecrets('trusted-secrets-trusted-child',
2815 'pre_playbooks'), [])
2816 self.assertEqual(
2817 self._getSecrets('trusted-secrets-trusted-child',
2818 'post_playbooks'), [])
2819
2820 self.assertEqual(
2821 self._getSecrets('trusted-secrets-untrusted-child',
James E. Blair2f589fe2017-10-26 12:57:41 -07002822 'playbooks'), [{}])
James E. Blairdf91ab32017-10-25 17:57:13 -07002823 self.assertEqual(
2824 self._getSecrets('trusted-secrets-untrusted-child',
2825 'pre_playbooks'), [])
2826 self.assertEqual(
2827 self._getSecrets('trusted-secrets-untrusted-child',
2828 'post_playbooks'), [])
2829
2830 def _checkUntrustedSecrets(self):
2831 secret = {'longpassword': 'test-passwordtest-password',
2832 'password': 'test-password',
2833 'username': 'test-username'}
2834 self.assertEqual(
2835 self._getSecrets('untrusted-secrets', 'playbooks'),
James E. Blair2f589fe2017-10-26 12:57:41 -07002836 [{'untrusted-secret': secret}])
James E. Blairdf91ab32017-10-25 17:57:13 -07002837 self.assertEqual(
2838 self._getSecrets('untrusted-secrets', 'pre_playbooks'), [])
2839 self.assertEqual(
2840 self._getSecrets('untrusted-secrets', 'post_playbooks'), [])
2841
2842 self.assertEqual(
2843 self._getSecrets('untrusted-secrets-trusted-child',
James E. Blair2f589fe2017-10-26 12:57:41 -07002844 'playbooks'), [{}])
James E. Blairdf91ab32017-10-25 17:57:13 -07002845 self.assertEqual(
2846 self._getSecrets('untrusted-secrets-trusted-child',
2847 'pre_playbooks'), [])
2848 self.assertEqual(
2849 self._getSecrets('untrusted-secrets-trusted-child',
2850 'post_playbooks'), [])
2851
2852 self.assertEqual(
2853 self._getSecrets('untrusted-secrets-untrusted-child',
James E. Blair2f589fe2017-10-26 12:57:41 -07002854 'playbooks'), [{}])
James E. Blairdf91ab32017-10-25 17:57:13 -07002855 self.assertEqual(
2856 self._getSecrets('untrusted-secrets-untrusted-child',
2857 'pre_playbooks'), [])
2858 self.assertEqual(
2859 self._getSecrets('untrusted-secrets-untrusted-child',
2860 'post_playbooks'), [])
2861
2862 def test_trusted_secret_inheritance_check(self):
2863 A = self.fake_gerrit.addFakeChange('common-config', 'master', 'A')
2864 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2865 self.waitUntilSettled()
2866 self.assertHistory([
2867 dict(name='trusted-secrets', result='SUCCESS', changes='1,1'),
2868 dict(name='trusted-secrets-trusted-child',
2869 result='SUCCESS', changes='1,1'),
2870 dict(name='trusted-secrets-untrusted-child',
2871 result='SUCCESS', changes='1,1'),
2872 ], ordered=False)
2873
2874 self._checkTrustedSecrets()
2875
2876 def test_untrusted_secret_inheritance_gate(self):
2877 A = self.fake_gerrit.addFakeChange('common-config', 'master', 'A')
2878 A.addApproval('Code-Review', 2)
2879 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
2880 self.waitUntilSettled()
2881 self.assertHistory([
2882 dict(name='untrusted-secrets', result='SUCCESS', changes='1,1'),
2883 dict(name='untrusted-secrets-trusted-child',
2884 result='SUCCESS', changes='1,1'),
2885 dict(name='untrusted-secrets-untrusted-child',
2886 result='SUCCESS', changes='1,1'),
2887 ], ordered=False)
2888
2889 self._checkUntrustedSecrets()
2890
2891 def test_untrusted_secret_inheritance_check(self):
2892 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
2893 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2894 self.waitUntilSettled()
2895 # This configuration tries to run untrusted secrets in an
2896 # non-post-review pipeline and should therefore run no jobs.
2897 self.assertHistory([])
2898
2899
James E. Blairdb089032017-08-15 13:42:12 -07002900class TestSecretLeaks(AnsibleZuulTestCase):
2901 tenant_config_file = 'config/secret-leaks/main.yaml'
2902
2903 def searchForContent(self, path, content):
2904 matches = []
2905 for (dirpath, dirnames, filenames) in os.walk(path):
2906 for filename in filenames:
2907 filepath = os.path.join(dirpath, filename)
2908 with open(filepath, 'rb') as f:
2909 if content in f.read():
2910 matches.append(filepath[len(path):])
2911 return matches
2912
2913 def _test_secret_file(self):
2914 # Or rather -- test that they *don't* leak.
2915 # Keep the jobdir around so we can inspect contents.
2916 self.executor_server.keep_jobdir = True
2917 conf = textwrap.dedent(
2918 """
2919 - project:
2920 name: org/project
2921 check:
2922 jobs:
2923 - secret-file
2924 """)
2925
2926 file_dict = {'.zuul.yaml': conf}
2927 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
2928 files=file_dict)
2929 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2930 self.waitUntilSettled()
2931 self.assertHistory([
2932 dict(name='secret-file', result='SUCCESS', changes='1,1'),
2933 ], ordered=False)
2934 matches = self.searchForContent(self.history[0].jobdir.root,
2935 b'test-password')
James E. Blaird6a71ca2017-08-18 14:15:05 -07002936 self.assertEqual(set(['/work/secret-file.txt']),
James E. Blairdb089032017-08-15 13:42:12 -07002937 set(matches))
2938
2939 def test_secret_file(self):
2940 self._test_secret_file()
2941
2942 def test_secret_file_verbose(self):
2943 # Output extra ansible info to exercise alternate logging code
2944 # paths.
2945 self.executor_server.verbose = True
2946 self._test_secret_file()
2947
2948 def _test_secret_file_fail(self):
2949 # Or rather -- test that they *don't* leak.
2950 # Keep the jobdir around so we can inspect contents.
2951 self.executor_server.keep_jobdir = True
2952 conf = textwrap.dedent(
2953 """
2954 - project:
2955 name: org/project
2956 check:
2957 jobs:
2958 - secret-file-fail
2959 """)
2960
2961 file_dict = {'.zuul.yaml': conf}
2962 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
2963 files=file_dict)
2964 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
2965 self.waitUntilSettled()
2966 self.assertHistory([
2967 dict(name='secret-file-fail', result='FAILURE', changes='1,1'),
2968 ], ordered=False)
2969 matches = self.searchForContent(self.history[0].jobdir.root,
2970 b'test-password')
James E. Blaird6a71ca2017-08-18 14:15:05 -07002971 self.assertEqual(set(['/work/failure-file.txt']),
James E. Blairdb089032017-08-15 13:42:12 -07002972 set(matches))
2973
2974 def test_secret_file_fail(self):
2975 self._test_secret_file_fail()
2976
2977 def test_secret_file_fail_verbose(self):
2978 # Output extra ansible info to exercise alternate logging code
2979 # paths.
2980 self.executor_server.verbose = True
2981 self._test_secret_file_fail()
James E. Blaira00910c2017-08-23 09:15:04 -07002982
2983
James E. Blair8446c412018-01-17 15:49:59 -08002984class TestNodesets(ZuulTestCase):
2985 tenant_config_file = 'config/nodesets/main.yaml'
2986
2987 def test_nodeset_branch(self):
2988 # Test that we can use a nodeset defined in another branch of
2989 # the same project.
2990 self.create_branch('org/project2', 'stable')
2991 self.fake_gerrit.addEvent(
2992 self.fake_gerrit.getFakeBranchCreatedEvent(
2993 'org/project2', 'stable'))
2994 self.waitUntilSettled()
2995
2996 with open(os.path.join(FIXTURE_DIR,
2997 'config/nodesets/git/',
2998 'org_project2/zuul-nodeset.yaml')) as f:
2999 config = f.read()
3000
3001 file_dict = {'zuul.yaml': config}
3002 A = self.fake_gerrit.addFakeChange('org/project2', 'master', 'A',
3003 files=file_dict)
3004 A.addApproval('Code-Review', 2)
3005 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
3006 self.waitUntilSettled()
3007 self.assertEqual(A.data['status'], 'MERGED')
3008 self.fake_gerrit.addEvent(A.getChangeMergedEvent())
3009 self.waitUntilSettled()
3010
3011 in_repo_conf = textwrap.dedent(
3012 """
3013 - job:
3014 parent: base
3015 name: project2-test
3016 nodeset: project2-nodeset
3017
3018 - project:
3019 check:
3020 jobs:
3021 - project2-test
3022 gate:
3023 jobs:
3024 - noop
3025 """)
3026 file_dict = {'zuul.yaml': in_repo_conf}
3027 B = self.fake_gerrit.addFakeChange('org/project2', 'stable', 'B',
3028 files=file_dict)
3029 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
3030 self.waitUntilSettled()
3031 self.assertEqual(B.reported, 1, "B should report success")
3032 self.assertHistory([
3033 dict(name='project2-test', result='SUCCESS', changes='2,1',
3034 node='ubuntu-xenial'),
3035 ])
3036
3037 def test_nodeset_branch_duplicate(self):
Monty Taylorbc1d0bb2018-01-22 17:05:31 -06003038 # Test that we can create a duplicate nodeset on a different
James E. Blair8446c412018-01-17 15:49:59 -08003039 # branch of the same project -- i.e., that when we branch
Monty Taylorbc1d0bb2018-01-22 17:05:31 -06003040 # master to stable on a project with a nodeset, nothing
James E. Blair8446c412018-01-17 15:49:59 -08003041 # changes.
3042 self.create_branch('org/project1', 'stable')
3043 self.fake_gerrit.addEvent(
3044 self.fake_gerrit.getFakeBranchCreatedEvent(
3045 'org/project1', 'stable'))
3046 self.waitUntilSettled()
3047
3048 A = self.fake_gerrit.addFakeChange('org/project1', 'stable', 'A')
3049 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
3050 self.waitUntilSettled()
3051 self.assertEqual(A.reported, 1,
3052 "A should report success")
3053 self.assertHistory([
3054 dict(name='project1-test', result='SUCCESS', changes='1,1',
3055 node='ubuntu-xenial'),
3056 ])
3057
3058 def test_nodeset_branch_error_same_branch(self):
3059 # Test that we are unable to define a nodeset twice on the same
3060 # project-branch.
3061 in_repo_conf = textwrap.dedent(
3062 """
3063 - nodeset:
3064 name: project1-nodeset
3065 nodes: []
3066 - nodeset:
3067 name: project1-nodeset
3068 nodes: []
3069 """)
3070 file_dict = {'zuul.yaml': in_repo_conf}
3071 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A',
3072 files=file_dict)
3073 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
3074 self.waitUntilSettled()
3075 self.assertIn('already defined', A.messages[0])
3076
3077 def test_nodeset_branch_error_same_project(self):
3078 # Test that we are unable to create a nodeset which differs
3079 # from another with the same name -- i.e., that if we have a
3080 # duplicate nodeset on multiple branches of the same project,
3081 # they must be identical.
3082 self.create_branch('org/project1', 'stable')
3083 self.fake_gerrit.addEvent(
3084 self.fake_gerrit.getFakeBranchCreatedEvent(
3085 'org/project1', 'stable'))
3086 self.waitUntilSettled()
3087
3088 in_repo_conf = textwrap.dedent(
3089 """
3090 - nodeset:
3091 name: project1-nodeset
3092 nodes: []
3093 """)
3094 file_dict = {'zuul.yaml': in_repo_conf}
3095 A = self.fake_gerrit.addFakeChange('org/project1', 'stable', 'A',
3096 files=file_dict)
3097 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
3098 self.waitUntilSettled()
3099 self.assertIn('does not match existing definition in branch master',
3100 A.messages[0])
3101
3102 def test_nodeset_branch_error_other_project(self):
3103 # Test that we are unable to create a nodeset with the same
3104 # name as another. We're never allowed to have a nodeset with
3105 # the same name outside of a project.
3106 in_repo_conf = textwrap.dedent(
3107 """
3108 - nodeset:
3109 name: project1-nodeset
3110 nodes: []
3111 """)
3112 file_dict = {'zuul.yaml': in_repo_conf}
3113 A = self.fake_gerrit.addFakeChange('org/project2', 'master', 'A',
3114 files=file_dict)
3115 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
3116 self.waitUntilSettled()
3117 self.assertIn('already defined in project org/project1',
3118 A.messages[0])
3119
3120
James E. Blair9596b942018-01-18 14:21:44 -08003121class TestSemaphoreBranches(ZuulTestCase):
3122 tenant_config_file = 'config/semaphore-branches/main.yaml'
3123
3124 def test_semaphore_branch(self):
3125 # Test that we can use a semaphore defined in another branch of
3126 # the same project.
3127 self.create_branch('org/project2', 'stable')
3128 self.fake_gerrit.addEvent(
3129 self.fake_gerrit.getFakeBranchCreatedEvent(
3130 'org/project2', 'stable'))
3131 self.waitUntilSettled()
3132
3133 with open(os.path.join(FIXTURE_DIR,
3134 'config/semaphore-branches/git/',
3135 'org_project2/zuul-semaphore.yaml')) as f:
3136 config = f.read()
3137
3138 file_dict = {'zuul.yaml': config}
3139 A = self.fake_gerrit.addFakeChange('org/project2', 'master', 'A',
3140 files=file_dict)
3141 A.addApproval('Code-Review', 2)
3142 self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
3143 self.waitUntilSettled()
3144 self.assertEqual(A.data['status'], 'MERGED')
3145 self.fake_gerrit.addEvent(A.getChangeMergedEvent())
3146 self.waitUntilSettled()
3147
3148 in_repo_conf = textwrap.dedent(
3149 """
3150 - job:
3151 parent: base
3152 name: project2-test
3153 semaphore: project2-semaphore
3154
3155 - project:
3156 check:
3157 jobs:
3158 - project2-test
3159 gate:
3160 jobs:
3161 - noop
3162 """)
3163 file_dict = {'zuul.yaml': in_repo_conf}
3164 B = self.fake_gerrit.addFakeChange('org/project2', 'stable', 'B',
3165 files=file_dict)
3166 self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
3167 self.waitUntilSettled()
3168 self.assertEqual(B.reported, 1, "B should report success")
3169 self.assertHistory([
3170 dict(name='project2-test', result='SUCCESS', changes='2,1')
3171 ])
3172
3173 def test_semaphore_branch_duplicate(self):
3174 # Test that we can create a duplicate semaphore on a different
3175 # branch of the same project -- i.e., that when we branch
3176 # master to stable on a project with a semaphore, nothing
3177 # changes.
3178 self.create_branch('org/project1', 'stable')
3179 self.fake_gerrit.addEvent(
3180 self.fake_gerrit.getFakeBranchCreatedEvent(
3181 'org/project1', 'stable'))
3182 self.waitUntilSettled()
3183
3184 A = self.fake_gerrit.addFakeChange('org/project1', 'stable', 'A')
3185 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
3186 self.waitUntilSettled()
3187 self.assertEqual(A.reported, 1,
3188 "A should report success")
3189 self.assertHistory([
3190 dict(name='project1-test', result='SUCCESS', changes='1,1')
3191 ])
3192
3193 def test_semaphore_branch_error_same_branch(self):
3194 # Test that we are unable to define a semaphore twice on the same
3195 # project-branch.
3196 in_repo_conf = textwrap.dedent(
3197 """
3198 - semaphore:
3199 name: project1-semaphore
3200 max: 2
3201 - semaphore:
3202 name: project1-semaphore
3203 max: 2
3204 """)
3205 file_dict = {'zuul.yaml': in_repo_conf}
3206 A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A',
3207 files=file_dict)
3208 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
3209 self.waitUntilSettled()
3210 self.assertIn('already defined', A.messages[0])
3211
3212 def test_semaphore_branch_error_same_project(self):
3213 # Test that we are unable to create a semaphore which differs
3214 # from another with the same name -- i.e., that if we have a
3215 # duplicate semaphore on multiple branches of the same project,
3216 # they must be identical.
3217 self.create_branch('org/project1', 'stable')
3218 self.fake_gerrit.addEvent(
3219 self.fake_gerrit.getFakeBranchCreatedEvent(
3220 'org/project1', 'stable'))
3221 self.waitUntilSettled()
3222
3223 in_repo_conf = textwrap.dedent(
3224 """
3225 - semaphore:
3226 name: project1-semaphore
3227 max: 4
3228 """)
3229 file_dict = {'zuul.yaml': in_repo_conf}
3230 A = self.fake_gerrit.addFakeChange('org/project1', 'stable', 'A',
3231 files=file_dict)
3232 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
3233 self.waitUntilSettled()
3234 self.assertIn('does not match existing definition in branch master',
3235 A.messages[0])
3236
3237 def test_semaphore_branch_error_other_project(self):
3238 # Test that we are unable to create a semaphore with the same
3239 # name as another. We're never allowed to have a semaphore with
3240 # the same name outside of a project.
3241 in_repo_conf = textwrap.dedent(
3242 """
3243 - semaphore:
3244 name: project1-semaphore
3245 max: 2
3246 """)
3247 file_dict = {'zuul.yaml': in_repo_conf}
3248 A = self.fake_gerrit.addFakeChange('org/project2', 'master', 'A',
3249 files=file_dict)
3250 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
3251 self.waitUntilSettled()
3252 self.assertIn('already defined in project org/project1',
3253 A.messages[0])
3254
3255
James E. Blaira00910c2017-08-23 09:15:04 -07003256class TestJobOutput(AnsibleZuulTestCase):
3257 tenant_config_file = 'config/job-output/main.yaml'
3258
3259 def _get_file(self, build, path):
3260 p = os.path.join(build.jobdir.root, path)
3261 with open(p) as f:
3262 return f.read()
3263
3264 def test_job_output(self):
Monty Taylor0e2489a2017-10-10 11:57:29 -05003265 # Verify that command standard output appears in the job output,
3266 # and that failures in the final playbook get logged.
James E. Blaira00910c2017-08-23 09:15:04 -07003267
3268 # This currently only verifies we receive output from
3269 # localhost. Notably, it does not verify we receive output
3270 # via zuul_console streaming.
3271 self.executor_server.keep_jobdir = True
3272 A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
3273 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
3274 self.waitUntilSettled()
3275 self.assertHistory([
3276 dict(name='job-output', result='SUCCESS', changes='1,1'),
3277 ], ordered=False)
3278
3279 token = 'Standard output test %s' % (self.history[0].jobdir.src_root)
3280 j = json.loads(self._get_file(self.history[0],
3281 'work/logs/job-output.json'))
3282 self.assertEqual(token,
3283 j[0]['plays'][0]['tasks'][0]
3284 ['hosts']['localhost']['stdout'])
3285
3286 print(self._get_file(self.history[0],
3287 'work/logs/job-output.txt'))
3288 self.assertIn(token,
3289 self._get_file(self.history[0],
3290 'work/logs/job-output.txt'))
Monty Taylor0e2489a2017-10-10 11:57:29 -05003291
3292 def test_job_output_failure_log(self):
3293 logger = logging.getLogger('zuul.AnsibleJob')
3294 output = io.StringIO()
3295 logger.addHandler(logging.StreamHandler(output))
3296
3297 # Verify that a failure in the last post playbook emits the contents
3298 # of the json output to the log
3299 self.executor_server.keep_jobdir = True
3300 A = self.fake_gerrit.addFakeChange('org/project2', 'master', 'A')
3301 self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
3302 self.waitUntilSettled()
3303 self.assertHistory([
3304 dict(name='job-output-failure',
3305 result='POST_FAILURE', changes='1,1'),
3306 ], ordered=False)
3307
3308 token = 'Standard output test %s' % (self.history[0].jobdir.src_root)
3309 j = json.loads(self._get_file(self.history[0],
3310 'work/logs/job-output.json'))
3311 self.assertEqual(token,
3312 j[0]['plays'][0]['tasks'][0]
3313 ['hosts']['localhost']['stdout'])
3314
3315 print(self._get_file(self.history[0],
3316 'work/logs/job-output.json'))
3317 self.assertIn(token,
3318 self._get_file(self.history[0],
3319 'work/logs/job-output.txt'))
3320
3321 log_output = output.getvalue()
3322 self.assertIn('Final playbook failed', log_output)
3323 self.assertIn('Failure test', log_output)