# Copyright 2012 Hewlett-Packard Development Company, L.P.
|
|
#
|
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
|
# not use this file except in compliance with the License. You may obtain
|
|
# a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
# License for the specific language governing permissions and limitations
|
|
# under the License.
|
|
|
|
import io
|
|
import json
|
|
import logging
|
|
import os
|
|
import sys
|
|
import textwrap
|
|
import gc
|
|
from unittest import skip, skipIf
|
|
|
|
import paramiko
|
|
|
|
import zuul.configloader
|
|
from zuul.lib import encryption
|
|
from tests.base import (
|
|
AnsibleZuulTestCase,
|
|
ZuulTestCase,
|
|
ZuulDBTestCase,
|
|
FIXTURE_DIR,
|
|
simple_layout,
|
|
iterate_timeout,
|
|
)
|
|
|
|
|
|
class TestMultipleTenants(AnsibleZuulTestCase):
|
|
# A temporary class to hold new tests while others are disabled
|
|
|
|
tenant_config_file = 'config/multi-tenant/main.yaml'
|
|
|
|
def test_multiple_tenants(self):
|
|
A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A')
|
|
A.addApproval('Code-Review', 2)
|
|
self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
|
|
self.waitUntilSettled()
|
|
self.assertEqual(self.getJobFromHistory('project1-test1').result,
|
|
'SUCCESS')
|
|
self.assertEqual(self.getJobFromHistory('python27').result,
|
|
'SUCCESS')
|
|
self.assertEqual(A.data['status'], 'MERGED')
|
|
self.assertEqual(A.reported, 2,
|
|
"A should report start and success")
|
|
self.assertIn('tenant-one-gate', A.messages[1],
|
|
"A should transit tenant-one gate")
|
|
self.assertNotIn('tenant-two-gate', A.messages[1],
|
|
"A should *not* transit tenant-two gate")
|
|
|
|
B = self.fake_gerrit.addFakeChange('org/project2', 'master', 'B')
|
|
B.addApproval('Code-Review', 2)
|
|
self.fake_gerrit.addEvent(B.addApproval('Approved', 1))
|
|
self.waitUntilSettled()
|
|
self.assertEqual(self.getJobFromHistory('python27',
|
|
'org/project2').result,
|
|
'SUCCESS')
|
|
self.assertEqual(self.getJobFromHistory('project2-test1').result,
|
|
'SUCCESS')
|
|
self.assertEqual(B.data['status'], 'MERGED')
|
|
self.assertEqual(B.reported, 2,
|
|
"B should report start and success")
|
|
self.assertIn('tenant-two-gate', B.messages[1],
|
|
"B should transit tenant-two gate")
|
|
self.assertNotIn('tenant-one-gate', B.messages[1],
|
|
"B should *not* transit tenant-one gate")
|
|
|
|
self.assertEqual(A.reported, 2, "Activity in tenant two should"
|
|
"not affect tenant one")
|
|
|
|
|
|
class TestProtected(ZuulTestCase):
|
|
tenant_config_file = 'config/protected/main.yaml'
|
|
|
|
def test_protected_ok(self):
|
|
# test clean usage of final parent job
|
|
in_repo_conf = textwrap.dedent(
|
|
"""
|
|
- job:
|
|
name: job-protected
|
|
protected: true
|
|
run: playbooks/job-protected.yaml
|
|
|
|
- project:
|
|
name: org/project
|
|
check:
|
|
jobs:
|
|
- job-child-ok
|
|
|
|
- job:
|
|
name: job-child-ok
|
|
parent: job-protected
|
|
|
|
- project:
|
|
name: org/project
|
|
check:
|
|
jobs:
|
|
- job-child-ok
|
|
|
|
""")
|
|
|
|
file_dict = {'zuul.yaml': in_repo_conf}
|
|
A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
|
|
files=file_dict)
|
|
self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
|
|
self.waitUntilSettled()
|
|
|
|
self.assertEqual(A.reported, 1)
|
|
self.assertEqual(A.patchsets[-1]['approvals'][0]['value'], '1')
|
|
|
|
def test_protected_reset(self):
|
|
# try to reset protected flag
|
|
in_repo_conf = textwrap.dedent(
|
|
"""
|
|
- job:
|
|
name: job-protected
|
|
protected: true
|
|
run: playbooks/job-protected.yaml
|
|
|
|
- job:
|
|
name: job-child-reset-protected
|
|
parent: job-protected
|
|
protected: false
|
|
|
|
- project:
|
|
name: org/project
|
|
check:
|
|
jobs:
|
|
- job-child-reset-protected
|
|
|
|
""")
|
|
|
|
file_dict = {'zuul.yaml': in_repo_conf}
|
|
A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
|
|
files=file_dict)
|
|
self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
|
|
self.waitUntilSettled()
|
|
|
|
# The second patch tried to override some variables.
|
|
# Thus it should fail.
|
|
self.assertEqual(A.reported, 1)
|
|
self.assertEqual(A.patchsets[-1]['approvals'][0]['value'], '-1')
|
|
self.assertIn('Unable to reset protected attribute', A.messages[0])
|
|
|
|
def test_protected_inherit_not_ok(self):
|
|
# try to inherit from a protected job in different project
|
|
in_repo_conf = textwrap.dedent(
|
|
"""
|
|
- job:
|
|
name: job-child-notok
|
|
run: playbooks/job-child-notok.yaml
|
|
parent: job-protected
|
|
|
|
- project:
|
|
name: org/project1
|
|
check:
|
|
jobs:
|
|
- job-child-notok
|
|
|
|
""")
|
|
|
|
file_dict = {'zuul.yaml': in_repo_conf}
|
|
A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A',
|
|
files=file_dict)
|
|
self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
|
|
self.waitUntilSettled()
|
|
|
|
self.assertEqual(A.reported, 1)
|
|
self.assertEqual(A.patchsets[-1]['approvals'][0]['value'], '-1')
|
|
self.assertIn(
|
|
"which is defined in review.example.com/org/project is protected "
|
|
"and cannot be inherited from other projects.", A.messages[0])
|
|
|
|
|
|
class TestAbstract(ZuulTestCase):
|
|
tenant_config_file = 'config/abstract/main.yaml'
|
|
|
|
def test_abstract_fail(self):
|
|
in_repo_conf = textwrap.dedent(
|
|
"""
|
|
- project:
|
|
check:
|
|
jobs:
|
|
- job-abstract
|
|
""")
|
|
|
|
file_dict = {'zuul.yaml': in_repo_conf}
|
|
A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
|
|
files=file_dict)
|
|
self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
|
|
self.waitUntilSettled()
|
|
|
|
self.assertEqual(A.reported, 1)
|
|
self.assertEqual(A.patchsets[-1]['approvals'][0]['value'], '-1')
|
|
self.assertIn('may not be directly run', A.messages[0])
|
|
|
|
def test_child_of_abstract(self):
|
|
in_repo_conf = textwrap.dedent(
|
|
"""
|
|
- project:
|
|
check:
|
|
jobs:
|
|
- job-child
|
|
""")
|
|
|
|
file_dict = {'zuul.yaml': in_repo_conf}
|
|
A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
|
|
files=file_dict)
|
|
self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
|
|
self.waitUntilSettled()
|
|
|
|
self.assertEqual(A.reported, 1)
|
|
self.assertEqual(A.patchsets[-1]['approvals'][0]['value'], '1')
|
|
|
|
|
|
class TestIntermediate(ZuulTestCase):
|
|
tenant_config_file = 'config/intermediate/main.yaml'
|
|
|
|
def test_intermediate_fail(self):
|
|
# you can not instantiate from an intermediate job
|
|
in_repo_conf = textwrap.dedent(
|
|
"""
|
|
- job:
|
|
name: job-instantiate-intermediate
|
|
parent: job-abstract-intermediate
|
|
|
|
- project:
|
|
check:
|
|
jobs:
|
|
- job-instantiate-intermediate
|
|
""")
|
|
|
|
file_dict = {'zuul.yaml': in_repo_conf}
|
|
A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
|
|
files=file_dict)
|
|
self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
|
|
self.waitUntilSettled()
|
|
|
|
self.assertEqual(A.reported, 1)
|
|
self.assertEqual(A.patchsets[-1]['approvals'][0]['value'], '-1')
|
|
self.assertIn('may only inherit to another abstract job',
|
|
A.messages[0])
|
|
|
|
def test_intermediate_config_fail(self):
|
|
# an intermediate job must also be abstract
|
|
in_repo_conf = textwrap.dedent(
|
|
"""
|
|
- job:
|
|
name: job-intermediate-but-not-abstract
|
|
intermediate: true
|
|
abstract: false
|
|
|
|
- project:
|
|
check:
|
|
jobs:
|
|
- job-intermediate-but-not-abstract
|
|
""")
|
|
|
|
file_dict = {'zuul.yaml': in_repo_conf}
|
|
A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
|
|
files=file_dict)
|
|
self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
|
|
self.waitUntilSettled()
|
|
|
|
self.assertEqual(A.reported, 1)
|
|
self.assertEqual(A.patchsets[-1]['approvals'][0]['value'], '-1')
|
|
self.assertIn('An intermediate job must also be abstract',
|
|
A.messages[0])
|
|
|
|
def test_intermediate_several(self):
|
|
# test passing through several intermediate jobs
|
|
in_repo_conf = textwrap.dedent(
|
|
"""
|
|
- project:
|
|
name: org/project
|
|
check:
|
|
jobs:
|
|
- job-actual
|
|
""")
|
|
|
|
file_dict = {'.zuul.yaml': in_repo_conf}
|
|
A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
|
|
files=file_dict)
|
|
self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
|
|
self.waitUntilSettled()
|
|
|
|
self.assertEqual(A.reported, 1)
|
|
self.assertEqual(A.patchsets[-1]['approvals'][0]['value'], '1')
|
|
|
|
|
|
class TestFinal(ZuulTestCase):
|
|
|
|
tenant_config_file = 'config/final/main.yaml'
|
|
|
|
def test_final_variant_ok(self):
|
|
# test clean usage of final parent job
|
|
in_repo_conf = textwrap.dedent(
|
|
"""
|
|
- project:
|
|
name: org/project
|
|
check:
|
|
jobs:
|
|
- job-final
|
|
""")
|
|
|
|
file_dict = {'.zuul.yaml': in_repo_conf}
|
|
A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
|
|
files=file_dict)
|
|
self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
|
|
self.waitUntilSettled()
|
|
|
|
self.assertEqual(A.reported, 1)
|
|
self.assertEqual(A.patchsets[-1]['approvals'][0]['value'], '1')
|
|
|
|
def test_final_variant_error(self):
|
|
# test misuse of final parent job
|
|
in_repo_conf = textwrap.dedent(
|
|
"""
|
|
- project:
|
|
name: org/project
|
|
check:
|
|
jobs:
|
|
- job-final:
|
|
vars:
|
|
dont_override_this: bar
|
|
""")
|
|
file_dict = {'.zuul.yaml': in_repo_conf}
|
|
A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
|
|
files=file_dict)
|
|
self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
|
|
self.waitUntilSettled()
|
|
|
|
# The second patch tried to override some variables.
|
|
# Thus it should fail.
|
|
self.assertEqual(A.reported, 1)
|
|
self.assertEqual(A.patchsets[-1]['approvals'][0]['value'], '-1')
|
|
self.assertIn('Unable to modify final job', A.messages[0])
|
|
|
|
def test_final_inheritance(self):
|
|
# test misuse of final parent job
|
|
in_repo_conf = textwrap.dedent(
|
|
"""
|
|
- job:
|
|
name: project-test
|
|
parent: job-final
|
|
run: playbooks/project-test.yaml
|
|
|
|
- project:
|
|
name: org/project
|
|
check:
|
|
jobs:
|
|
- project-test
|
|
""")
|
|
|
|
in_repo_playbook = textwrap.dedent(
|
|
"""
|
|
- hosts: all
|
|
tasks: []
|
|
""")
|
|
|
|
file_dict = {'.zuul.yaml': in_repo_conf,
|
|
'playbooks/project-test.yaml': in_repo_playbook}
|
|
A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
|
|
files=file_dict)
|
|
self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
|
|
self.waitUntilSettled()
|
|
|
|
# The second patch tried to override some variables.
|
|
# Thus it should fail.
|
|
self.assertEqual(A.reported, 1)
|
|
self.assertEqual(A.patchsets[-1]['approvals'][0]['value'], '-1')
|
|
self.assertIn('Unable to modify final job', A.messages[0])
|
|
|
|
|
|
class TestBranchDeletion(ZuulTestCase):
|
|
tenant_config_file = 'config/branch-deletion/main.yaml'
|
|
|
|
def test_branch_delete(self):
|
|
# This tests a tenant reconfiguration on deleting a branch
|
|
# *after* an earlier failed tenant reconfiguration. This
|
|
# ensures that cached data are appropriately removed, even if
|
|
# we are recovering from an invalid config.
|
|
self.create_branch('org/project', 'stable/queens')
|
|
self.fake_gerrit.addEvent(
|
|
self.fake_gerrit.getFakeBranchCreatedEvent(
|
|
'org/project', 'stable/queens'))
|
|
self.waitUntilSettled()
|
|
|
|
in_repo_conf = textwrap.dedent(
|
|
"""
|
|
- project:
|
|
check:
|
|
jobs:
|
|
- nonexistent-job
|
|
""")
|
|
|
|
file_dict = {'zuul.yaml': in_repo_conf}
|
|
A = self.fake_gerrit.addFakeChange('org/project', 'stable/queens', 'A',
|
|
files=file_dict)
|
|
A.setMerged()
|
|
self.fake_gerrit.addEvent(A.getChangeMergedEvent())
|
|
self.waitUntilSettled()
|
|
|
|
self.delete_branch('org/project', 'stable/queens')
|
|
self.fake_gerrit.addEvent(
|
|
self.fake_gerrit.getFakeBranchDeletedEvent(
|
|
'org/project', 'stable/queens'))
|
|
self.waitUntilSettled()
|
|
|
|
in_repo_conf = textwrap.dedent(
|
|
"""
|
|
- project:
|
|
check:
|
|
jobs:
|
|
- base
|
|
""")
|
|
|
|
file_dict = {'zuul.yaml': in_repo_conf}
|
|
B = self.fake_gerrit.addFakeChange('org/project1', 'master', 'B',
|
|
files=file_dict)
|
|
self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
|
|
self.waitUntilSettled()
|
|
self.assertEqual(B.reported, 1)
|
|
self.assertHistory([
|
|
dict(name='base', result='SUCCESS', changes='2,1')])
|
|
|
|
def test_branch_delete_full_reconfiguration(self):
|
|
# This tests a full configuration after deleting a branch
|
|
# *after* an earlier failed tenant reconfiguration. This
|
|
# ensures that cached data are appropriately removed, even if
|
|
# we are recovering from an invalid config.
|
|
self.create_branch('org/project', 'stable/queens')
|
|
self.fake_gerrit.addEvent(
|
|
self.fake_gerrit.getFakeBranchCreatedEvent(
|
|
'org/project', 'stable/queens'))
|
|
self.waitUntilSettled()
|
|
|
|
in_repo_conf = textwrap.dedent(
|
|
"""
|
|
- project:
|
|
check:
|
|
jobs:
|
|
- nonexistent-job
|
|
""")
|
|
|
|
file_dict = {'zuul.yaml': in_repo_conf}
|
|
A = self.fake_gerrit.addFakeChange('org/project', 'stable/queens', 'A',
|
|
files=file_dict)
|
|
A.setMerged()
|
|
self.fake_gerrit.addEvent(A.getChangeMergedEvent())
|
|
self.waitUntilSettled()
|
|
|
|
self.delete_branch('org/project', 'stable/queens')
|
|
self.scheds.execute(lambda app: app.sched.reconfigure(app.config))
|
|
self.waitUntilSettled()
|
|
|
|
in_repo_conf = textwrap.dedent(
|
|
"""
|
|
- project:
|
|
check:
|
|
jobs:
|
|
- base
|
|
""")
|
|
|
|
file_dict = {'zuul.yaml': in_repo_conf}
|
|
B = self.fake_gerrit.addFakeChange('org/project1', 'master', 'B',
|
|
files=file_dict)
|
|
self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
|
|
self.waitUntilSettled()
|
|
self.assertEqual(B.reported, 1)
|
|
self.assertHistory([
|
|
dict(name='base', result='SUCCESS', changes='2,1')])
|
|
|
|
|
|
class TestBranchTag(ZuulTestCase):
|
|
tenant_config_file = 'config/branch-tag/main.yaml'
|
|
|
|
def test_no_branch_match(self):
|
|
# Test that tag jobs run with no explicit branch matchers
|
|
event = self.fake_gerrit.addFakeTag('org/project', 'master', 'foo')
|
|
self.fake_gerrit.addEvent(event)
|
|
self.waitUntilSettled()
|
|
self.assertHistory([
|
|
dict(name='central-job', result='SUCCESS', ref='refs/tags/foo'),
|
|
dict(name='test-job', result='SUCCESS', ref='refs/tags/foo')],
|
|
ordered=False)
|
|
|
|
def test_no_branch_match_multi_branch(self):
|
|
# Test that tag jobs run with no explicit branch matchers in a
|
|
# multi-branch project (where jobs generally get implied
|
|
# branch matchers)
|
|
self.create_branch('org/project', 'stable/pike')
|
|
self.fake_gerrit.addEvent(
|
|
self.fake_gerrit.getFakeBranchCreatedEvent(
|
|
'org/project', 'stable/pike'))
|
|
self.waitUntilSettled()
|
|
|
|
event = self.fake_gerrit.addFakeTag('org/project', 'master', 'foo')
|
|
self.fake_gerrit.addEvent(event)
|
|
self.waitUntilSettled()
|
|
# test-job does run in this case because it is defined in a
|
|
# branched repo with implied branch matchers, and the tagged
|
|
# commit is in both branches.
|
|
self.assertHistory([
|
|
dict(name='central-job', result='SUCCESS', ref='refs/tags/foo'),
|
|
dict(name='test-job', result='SUCCESS', ref='refs/tags/foo')],
|
|
ordered=False)
|
|
|
|
def test_no_branch_match_divergent_multi_branch(self):
|
|
# Test that tag jobs from divergent branches run different job
|
|
# variants.
|
|
self.create_branch('org/project', 'stable/pike')
|
|
self.fake_gerrit.addEvent(
|
|
self.fake_gerrit.getFakeBranchCreatedEvent(
|
|
'org/project', 'stable/pike'))
|
|
self.waitUntilSettled()
|
|
|
|
# Add a new job to master
|
|
in_repo_conf = textwrap.dedent(
|
|
"""
|
|
- job:
|
|
name: test2-job
|
|
run: playbooks/test-job.yaml
|
|
|
|
- project:
|
|
name: org/project
|
|
tag:
|
|
jobs:
|
|
- central-job
|
|
- test2-job
|
|
""")
|
|
|
|
file_dict = {'.zuul.yaml': in_repo_conf}
|
|
A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
|
|
files=file_dict)
|
|
A.setMerged()
|
|
self.fake_gerrit.addEvent(A.getChangeMergedEvent())
|
|
self.waitUntilSettled()
|
|
|
|
event = self.fake_gerrit.addFakeTag(
|
|
'org/project', 'stable/pike', 'foo')
|
|
self.fake_gerrit.addEvent(event)
|
|
self.waitUntilSettled()
|
|
# test-job runs because we tagged stable/pike, but test2-job does
|
|
# not, it only applied to master.
|
|
self.assertHistory([
|
|
dict(name='central-job', result='SUCCESS', ref='refs/tags/foo'),
|
|
dict(name='test-job', result='SUCCESS', ref='refs/tags/foo')],
|
|
ordered=False)
|
|
|
|
event = self.fake_gerrit.addFakeTag('org/project', 'master', 'bar')
|
|
self.fake_gerrit.addEvent(event)
|
|
self.waitUntilSettled()
|
|
# test2-job runs because we tagged master, but test-job does
|
|
# not, it only applied to stable/pike.
|
|
self.assertHistory([
|
|
dict(name='central-job', result='SUCCESS', ref='refs/tags/foo'),
|
|
dict(name='test-job', result='SUCCESS', ref='refs/tags/foo'),
|
|
dict(name='central-job', result='SUCCESS', ref='refs/tags/bar'),
|
|
dict(name='test2-job', result='SUCCESS', ref='refs/tags/bar')],
|
|
ordered=False)
|
|
|
|
|
|
class TestBranchNegative(ZuulTestCase):
|
|
tenant_config_file = 'config/branch-negative/main.yaml'
|
|
|
|
def test_negative_branch_match(self):
|
|
# Test that a negative branch matcher works with implied branches.
|
|
self.create_branch('org/project', 'stable/pike')
|
|
self.fake_gerrit.addEvent(
|
|
self.fake_gerrit.getFakeBranchCreatedEvent(
|
|
'org/project', 'stable/pike'))
|
|
self.waitUntilSettled()
|
|
|
|
A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
|
|
self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
|
|
self.waitUntilSettled()
|
|
B = self.fake_gerrit.addFakeChange('org/project', 'stable/pike', 'A')
|
|
self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
|
|
self.waitUntilSettled()
|
|
self.assertHistory([
|
|
dict(name='test-job', result='SUCCESS', changes='1,1')])
|
|
|
|
|
|
class TestBranchTemplates(ZuulTestCase):
|
|
tenant_config_file = 'config/branch-templates/main.yaml'
|
|
|
|
def test_template_removal_from_branch(self):
|
|
# Test that a template can be removed from one branch but not
|
|
# another.
|
|
# This creates a new branch with a copy of the config in master
|
|
self.create_branch('puppet-integration', 'stable/newton')
|
|
self.create_branch('puppet-integration', 'stable/ocata')
|
|
self.create_branch('puppet-tripleo', 'stable/newton')
|
|
self.create_branch('puppet-tripleo', 'stable/ocata')
|
|
self.fake_gerrit.addEvent(
|
|
self.fake_gerrit.getFakeBranchCreatedEvent(
|
|
'puppet-integration', 'stable/newton'))
|
|
self.fake_gerrit.addEvent(
|
|
self.fake_gerrit.getFakeBranchCreatedEvent(
|
|
'puppet-integration', 'stable/ocata'))
|
|
self.fake_gerrit.addEvent(
|
|
self.fake_gerrit.getFakeBranchCreatedEvent(
|
|
'puppet-tripleo', 'stable/newton'))
|
|
self.fake_gerrit.addEvent(
|
|
self.fake_gerrit.getFakeBranchCreatedEvent(
|
|
'puppet-tripleo', 'stable/ocata'))
|
|
self.waitUntilSettled()
|
|
|
|
in_repo_conf = textwrap.dedent(
|
|
"""
|
|
- project:
|
|
name: puppet-tripleo
|
|
check:
|
|
jobs:
|
|
- puppet-something
|
|
""")
|
|
|
|
file_dict = {'.zuul.yaml': in_repo_conf}
|
|
A = self.fake_gerrit.addFakeChange('puppet-tripleo', 'stable/newton',
|
|
'A', files=file_dict)
|
|
self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
|
|
self.waitUntilSettled()
|
|
self.assertHistory([
|
|
dict(name='puppet-something', result='SUCCESS', changes='1,1')])
|
|
|
|
def test_template_change_on_branch(self):
|
|
# Test that the contents of a template can be changed on one
|
|
# branch without affecting another.
|
|
|
|
# This creates a new branch with a copy of the config in master
|
|
self.create_branch('puppet-integration', 'stable/newton')
|
|
self.create_branch('puppet-integration', 'stable/ocata')
|
|
self.create_branch('puppet-tripleo', 'stable/newton')
|
|
self.create_branch('puppet-tripleo', 'stable/ocata')
|
|
self.fake_gerrit.addEvent(
|
|
self.fake_gerrit.getFakeBranchCreatedEvent(
|
|
'puppet-integration', 'stable/newton'))
|
|
self.fake_gerrit.addEvent(
|
|
self.fake_gerrit.getFakeBranchCreatedEvent(
|
|
'puppet-integration', 'stable/ocata'))
|
|
self.fake_gerrit.addEvent(
|
|
self.fake_gerrit.getFakeBranchCreatedEvent(
|
|
'puppet-tripleo', 'stable/newton'))
|
|
self.fake_gerrit.addEvent(
|
|
self.fake_gerrit.getFakeBranchCreatedEvent(
|
|
'puppet-tripleo', 'stable/ocata'))
|
|
self.waitUntilSettled()
|
|
|
|
in_repo_conf = textwrap.dedent("""
|
|
- job:
|
|
name: puppet-unit-base
|
|
run: playbooks/run-unit-tests.yaml
|
|
|
|
- job:
|
|
name: puppet-unit-3.8
|
|
parent: puppet-unit-base
|
|
branches: ^(stable/(newton|ocata)).*$
|
|
vars:
|
|
puppet_gem_version: 3.8
|
|
|
|
- job:
|
|
name: puppet-something
|
|
run: playbooks/run-unit-tests.yaml
|
|
|
|
- project-template:
|
|
name: puppet-unit
|
|
check:
|
|
jobs:
|
|
- puppet-something
|
|
|
|
- project:
|
|
name: puppet-integration
|
|
templates:
|
|
- puppet-unit
|
|
""")
|
|
|
|
file_dict = {'.zuul.yaml': in_repo_conf}
|
|
A = self.fake_gerrit.addFakeChange('puppet-integration',
|
|
'stable/newton',
|
|
'A', files=file_dict)
|
|
B = self.fake_gerrit.addFakeChange('puppet-tripleo',
|
|
'stable/newton',
|
|
'B')
|
|
B.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
|
|
B.subject, A.data['id'])
|
|
self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
|
|
self.waitUntilSettled()
|
|
self.assertHistory([
|
|
dict(name='puppet-something', result='SUCCESS',
|
|
changes='1,1 2,1')])
|
|
|
|
|
|
class TestBranchVariants(ZuulTestCase):
|
|
tenant_config_file = 'config/branch-variants/main.yaml'
|
|
|
|
def test_branch_variants(self):
|
|
# Test branch variants of jobs with inheritance
|
|
self.executor_server.hold_jobs_in_build = True
|
|
# This creates a new branch with a copy of the config in master
|
|
self.create_branch('puppet-integration', 'stable')
|
|
self.fake_gerrit.addEvent(
|
|
self.fake_gerrit.getFakeBranchCreatedEvent(
|
|
'puppet-integration', 'stable'))
|
|
self.waitUntilSettled()
|
|
|
|
A = self.fake_gerrit.addFakeChange('puppet-integration', 'stable', 'A')
|
|
self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
|
|
self.waitUntilSettled()
|
|
|
|
self.assertEqual(len(self.builds[0].parameters['pre_playbooks']), 3)
|
|
self.executor_server.hold_jobs_in_build = False
|
|
self.executor_server.release()
|
|
self.waitUntilSettled()
|
|
|
|
def test_branch_variants_reconfigure(self):
|
|
# Test branch variants of jobs with inheritance
|
|
self.executor_server.hold_jobs_in_build = True
|
|
# This creates a new branch with a copy of the config in master
|
|
self.create_branch('puppet-integration', 'stable')
|
|
self.fake_gerrit.addEvent(
|
|
self.fake_gerrit.getFakeBranchCreatedEvent(
|
|
'puppet-integration', 'stable'))
|
|
self.waitUntilSettled()
|
|
|
|
with open(os.path.join(FIXTURE_DIR,
|
|
'config/branch-variants/git/',
|
|
'puppet-integration/.zuul.yaml')) as f:
|
|
config = f.read()
|
|
|
|
# Push a change that triggers a dynamic reconfiguration
|
|
file_dict = {'.zuul.yaml': config}
|
|
A = self.fake_gerrit.addFakeChange('puppet-integration', 'master', 'A',
|
|
files=file_dict)
|
|
self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
|
|
self.waitUntilSettled()
|
|
|
|
ipath = self.builds[0].parameters['zuul']['_inheritance_path']
|
|
for i in ipath:
|
|
self.log.debug("inheritance path %s", i)
|
|
self.assertEqual(len(ipath), 5)
|
|
self.executor_server.hold_jobs_in_build = False
|
|
self.executor_server.release()
|
|
self.waitUntilSettled()
|
|
|
|
def test_branch_variants_divergent(self):
|
|
# Test branches can diverge and become independent
|
|
self.executor_server.hold_jobs_in_build = True
|
|
# This creates a new branch with a copy of the config in master
|
|
self.create_branch('puppet-integration', 'stable')
|
|
self.fake_gerrit.addEvent(
|
|
self.fake_gerrit.getFakeBranchCreatedEvent(
|
|
'puppet-integration', 'stable'))
|
|
self.waitUntilSettled()
|
|
|
|
with open(os.path.join(FIXTURE_DIR,
|
|
'config/branch-variants/git/',
|
|
'puppet-integration/stable.zuul.yaml')) as f:
|
|
config = f.read()
|
|
|
|
file_dict = {'.zuul.yaml': config}
|
|
C = self.fake_gerrit.addFakeChange('puppet-integration', 'stable', 'C',
|
|
files=file_dict)
|
|
C.addApproval('Code-Review', 2)
|
|
self.fake_gerrit.addEvent(C.addApproval('Approved', 1))
|
|
self.waitUntilSettled()
|
|
self.fake_gerrit.addEvent(C.getChangeMergedEvent())
|
|
self.waitUntilSettled()
|
|
|
|
A = self.fake_gerrit.addFakeChange('puppet-integration', 'master', 'A')
|
|
self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
|
|
self.waitUntilSettled()
|
|
B = self.fake_gerrit.addFakeChange('puppet-integration', 'stable', 'B')
|
|
self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
|
|
self.waitUntilSettled()
|
|
|
|
self.assertEqual(self.builds[0].parameters['zuul']['jobtags'],
|
|
['master'])
|
|
|
|
self.assertEqual(self.builds[1].parameters['zuul']['jobtags'],
|
|
['stable'])
|
|
|
|
self.executor_server.hold_jobs_in_build = False
|
|
self.executor_server.release()
|
|
self.waitUntilSettled()
|
|
|
|
|
|
class TestBranchMismatch(ZuulTestCase):
|
|
tenant_config_file = 'config/branch-mismatch/main.yaml'
|
|
|
|
def test_job_override_branch(self):
|
|
"Test that override-checkout overrides branch matchers as well"
|
|
|
|
# Make sure the parent job repo is branched, so it gets
|
|
# implied branch matchers.
|
|
self.create_branch('org/project1', 'stable')
|
|
self.fake_gerrit.addEvent(
|
|
self.fake_gerrit.getFakeBranchCreatedEvent(
|
|
'org/project1', 'stable'))
|
|
|
|
# The child job repo should have a branch which does not exist
|
|
# in the parent job repo.
|
|
self.create_branch('org/project2', 'devel')
|
|
self.fake_gerrit.addEvent(
|
|
self.fake_gerrit.getFakeBranchCreatedEvent(
|
|
'org/project2', 'devel'))
|
|
|
|
# A job in a repo with a weird branch name should use the
|
|
# parent job from the parent job's master (default) branch.
|
|
A = self.fake_gerrit.addFakeChange('org/project2', 'devel', 'A')
|
|
self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
|
|
self.waitUntilSettled()
|
|
# project-test2 should run because it inherits from
|
|
# project-test1 and we will use the fallback branch to find
|
|
# project-test1 variants, but project-test1 itself, even
|
|
# though it is in the project-pipeline config, should not run
|
|
# because it doesn't directly match.
|
|
self.assertHistory([
|
|
dict(name='project-test1', result='SUCCESS', changes='1,1'),
|
|
dict(name='project-test2', result='SUCCESS', changes='1,1'),
|
|
], ordered=False)
|
|
|
|
|
|
class TestAllowedProjects(ZuulTestCase):
|
|
tenant_config_file = 'config/allowed-projects/main.yaml'
|
|
|
|
def test_allowed_projects(self):
|
|
A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A')
|
|
self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
|
|
self.waitUntilSettled()
|
|
self.assertEqual(A.reported, 1)
|
|
self.assertIn('Build succeeded', A.messages[0])
|
|
|
|
B = self.fake_gerrit.addFakeChange('org/project2', 'master', 'B')
|
|
self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
|
|
self.waitUntilSettled()
|
|
self.assertEqual(B.reported, 1)
|
|
self.assertIn('Project org/project2 is not allowed '
|
|
'to run job test-project2', B.messages[0])
|
|
|
|
C = self.fake_gerrit.addFakeChange('org/project3', 'master', 'C')
|
|
self.fake_gerrit.addEvent(C.getPatchsetCreatedEvent(1))
|
|
self.waitUntilSettled()
|
|
self.assertEqual(C.reported, 1)
|
|
self.assertIn('Project org/project3 is not allowed '
|
|
'to run job restricted-job', C.messages[0])
|
|
|
|
self.assertHistory([
|
|
dict(name='test-project1', result='SUCCESS', changes='1,1'),
|
|
dict(name='restricted-job', result='SUCCESS', changes='1,1'),
|
|
], ordered=False)
|
|
|
|
def test_allowed_projects_dynamic_config(self):
|
|
# It is possible to circumvent allowed-projects with a
|
|
# depends-on.
|
|
in_repo_conf2 = textwrap.dedent(
|
|
"""
|
|
- job:
|
|
name: test-project2b
|
|
parent: restricted-job
|
|
allowed-projects:
|
|
- org/project1
|
|
""")
|
|
in_repo_conf1 = textwrap.dedent(
|
|
"""
|
|
- project:
|
|
check:
|
|
jobs:
|
|
- test-project2b
|
|
""")
|
|
|
|
file_dict = {'zuul.yaml': in_repo_conf2}
|
|
A = self.fake_gerrit.addFakeChange('org/project2', 'master', 'A',
|
|
files=file_dict)
|
|
file_dict = {'zuul.yaml': in_repo_conf1}
|
|
B = self.fake_gerrit.addFakeChange('org/project1', 'master', 'B',
|
|
files=file_dict)
|
|
B.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
|
|
B.subject, A.data['id'])
|
|
self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
|
|
self.waitUntilSettled()
|
|
self.assertHistory([
|
|
dict(name='test-project2b', result='SUCCESS', changes='1,1 2,1'),
|
|
], ordered=False)
|
|
|
|
def test_allowed_projects_dynamic_config_secret(self):
|
|
# It is not possible to circumvent allowed-projects with a
|
|
# depends-on if there is a secret involved.
|
|
in_repo_conf2 = textwrap.dedent(
|
|
"""
|
|
- secret:
|
|
name: project2_secret
|
|
data: {}
|
|
- job:
|
|
name: test-project2b
|
|
parent: restricted-job
|
|
secrets: project2_secret
|
|
allowed-projects:
|
|
- org/project1
|
|
""")
|
|
in_repo_conf1 = textwrap.dedent(
|
|
"""
|
|
- project:
|
|
check:
|
|
jobs:
|
|
- test-project2b
|
|
""")
|
|
|
|
file_dict = {'zuul.yaml': in_repo_conf2}
|
|
A = self.fake_gerrit.addFakeChange('org/project2', 'master', 'A',
|
|
files=file_dict)
|
|
file_dict = {'zuul.yaml': in_repo_conf1}
|
|
B = self.fake_gerrit.addFakeChange('org/project1', 'master', 'B',
|
|
files=file_dict)
|
|
B.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
|
|
B.subject, A.data['id'])
|
|
self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
|
|
self.waitUntilSettled()
|
|
self.assertHistory([])
|
|
self.assertEqual(B.reported, 1)
|
|
self.assertIn('Project org/project1 is not allowed '
|
|
'to run job test-project2b', B.messages[0])
|
|
|
|
|
|
class TestAllowedProjectsTrusted(ZuulTestCase):
|
|
tenant_config_file = 'config/allowed-projects-trusted/main.yaml'
|
|
|
|
def test_allowed_projects_secret_trusted(self):
|
|
# Test that an untrusted job defined in project1 can be used
|
|
# in project2, but only if attached by a config project.
|
|
A = self.fake_gerrit.addFakeChange('org/project2', 'master', 'A')
|
|
self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
|
|
self.waitUntilSettled()
|
|
self.assertEqual(A.reported, 1)
|
|
self.assertIn('Build succeeded', A.messages[0])
|
|
self.assertHistory([
|
|
dict(name='test-project1', result='SUCCESS', changes='1,1'),
|
|
], ordered=False)
|
|
|
|
|
|
class TestCentralJobs(ZuulTestCase):
|
|
tenant_config_file = 'config/central-jobs/main.yaml'
|
|
|
|
def setUp(self):
|
|
super(TestCentralJobs, self).setUp()
|
|
self.create_branch('org/project', 'stable')
|
|
self.fake_gerrit.addEvent(
|
|
self.fake_gerrit.getFakeBranchCreatedEvent(
|
|
'org/project', 'stable'))
|
|
self.waitUntilSettled()
|
|
|
|
def _updateConfig(self, config, branch):
|
|
file_dict = {'.zuul.yaml': config}
|
|
C = self.fake_gerrit.addFakeChange('org/project', branch, 'C',
|
|
files=file_dict)
|
|
C.addApproval('Code-Review', 2)
|
|
self.fake_gerrit.addEvent(C.addApproval('Approved', 1))
|
|
self.waitUntilSettled()
|
|
self.fake_gerrit.addEvent(C.getChangeMergedEvent())
|
|
self.waitUntilSettled()
|
|
|
|
def _test_central_job_on_branch(self, branch, other_branch):
|
|
# Test that a job defined on a branchless repo only runs on
|
|
# the branch applied
|
|
config = textwrap.dedent(
|
|
"""
|
|
- project:
|
|
name: org/project
|
|
check:
|
|
jobs:
|
|
- central-job
|
|
""")
|
|
self._updateConfig(config, branch)
|
|
|
|
A = self.fake_gerrit.addFakeChange('org/project', branch, 'A')
|
|
self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
|
|
self.waitUntilSettled()
|
|
|
|
self.assertHistory([
|
|
dict(name='central-job', result='SUCCESS', changes='2,1')])
|
|
|
|
# No jobs should run for this change.
|
|
B = self.fake_gerrit.addFakeChange('org/project', other_branch, 'B')
|
|
self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
|
|
self.waitUntilSettled()
|
|
|
|
self.assertHistory([
|
|
dict(name='central-job', result='SUCCESS', changes='2,1')])
|
|
|
|
def test_central_job_on_stable(self):
|
|
self._test_central_job_on_branch('master', 'stable')
|
|
|
|
def test_central_job_on_master(self):
|
|
self._test_central_job_on_branch('stable', 'master')
|
|
|
|
def _test_central_template_on_branch(self, branch, other_branch):
|
|
# Test that a project-template defined on a branchless repo
|
|
# only runs on the branch applied
|
|
config = textwrap.dedent(
|
|
"""
|
|
- project:
|
|
name: org/project
|
|
templates: ['central-jobs']
|
|
""")
|
|
self._updateConfig(config, branch)
|
|
|
|
A = self.fake_gerrit.addFakeChange('org/project', branch, 'A')
|
|
self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
|
|
self.waitUntilSettled()
|
|
|
|
self.assertHistory([
|
|
dict(name='central-job', result='SUCCESS', changes='2,1')])
|
|
|
|
# No jobs should run for this change.
|
|
B = self.fake_gerrit.addFakeChange('org/project', other_branch, 'B')
|
|
self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
|
|
self.waitUntilSettled()
|
|
|
|
self.assertHistory([
|
|
dict(name='central-job', result='SUCCESS', changes='2,1')])
|
|
|
|
def test_central_template_on_stable(self):
|
|
self._test_central_template_on_branch('master', 'stable')
|
|
|
|
def test_central_template_on_master(self):
|
|
self._test_central_template_on_branch('stable', 'master')
|
|
|
|
|
|
class TestInRepoConfig(ZuulTestCase):
|
|
# A temporary class to hold new tests while others are disabled
|
|
|
|
config_file = 'zuul-connections-gerrit-and-github.conf'
|
|
tenant_config_file = 'config/in-repo/main.yaml'
|
|
|
|
def test_in_repo_config(self):
|
|
A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
|
|
A.addApproval('Code-Review', 2)
|
|
self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
|
|
self.waitUntilSettled()
|
|
self.assertEqual(self.getJobFromHistory('project-test1').result,
|
|
'SUCCESS')
|
|
self.assertEqual(A.data['status'], 'MERGED')
|
|
self.assertEqual(A.reported, 2,
|
|
"A should report start and success")
|
|
self.assertIn('tenant-one-gate', A.messages[1],
|
|
"A should transit tenant-one gate")
|
|
|
|
@skip("This test is useful, but not reliable")
|
|
def test_full_and_dynamic_reconfig(self):
|
|
self.executor_server.hold_jobs_in_build = True
|
|
in_repo_conf = textwrap.dedent(
|
|
"""
|
|
- job:
|
|
name: project-test1
|
|
|
|
- project:
|
|
name: org/project
|
|
tenant-one-gate:
|
|
jobs:
|
|
- project-test1
|
|
""")
|
|
|
|
file_dict = {'.zuul.yaml': in_repo_conf}
|
|
A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
|
|
files=file_dict)
|
|
A.addApproval('Code-Review', 2)
|
|
self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
|
|
self.waitUntilSettled()
|
|
self.scheds.execute(lambda app: app.sched.reconfigure(app.config))
|
|
self.waitUntilSettled()
|
|
|
|
gc.collect()
|
|
pipelines = [obj for obj in gc.get_objects()
|
|
if isinstance(obj, zuul.model.Pipeline)]
|
|
self.assertEqual(len(pipelines), 4)
|
|
|
|
self.executor_server.hold_jobs_in_build = False
|
|
self.executor_server.release()
|
|
self.waitUntilSettled()
|
|
|
|
def test_dynamic_config(self):
|
|
in_repo_conf = textwrap.dedent(
|
|
"""
|
|
- job:
|
|
name: project-test1
|
|
|
|
- job:
|
|
name: project-test2
|
|
run: playbooks/project-test2.yaml
|
|
|
|
- job:
|
|
name: project-test3
|
|
run: playbooks/project-test2.yaml
|
|
|
|
# add a job by the short project name
|
|
- project:
|
|
name: org/project
|
|
tenant-one-gate:
|
|
jobs:
|
|
- project-test2
|
|
|
|
# add a job by the canonical project name
|
|
- project:
|
|
name: review.example.com/org/project
|
|
tenant-one-gate:
|
|
jobs:
|
|
- project-test3
|
|
""")
|
|
|
|
in_repo_playbook = textwrap.dedent(
|
|
"""
|
|
- hosts: all
|
|
tasks: []
|
|
""")
|
|
|
|
file_dict = {'.zuul.yaml': in_repo_conf,
|
|
'playbooks/project-test2.yaml': in_repo_playbook}
|
|
A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
|
|
files=file_dict)
|
|
A.addApproval('Code-Review', 2)
|
|
self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
|
|
self.waitUntilSettled()
|
|
self.assertEqual(A.data['status'], 'MERGED')
|
|
self.assertEqual(A.reported, 2,
|
|
"A should report start and success")
|
|
self.assertIn('tenant-one-gate', A.messages[1],
|
|
"A should transit tenant-one gate")
|
|
self.assertHistory([
|
|
dict(name='project-test2', result='SUCCESS', changes='1,1'),
|
|
dict(name='project-test3', result='SUCCESS', changes='1,1'),
|
|
], ordered=False)
|
|
|
|
self.fake_gerrit.addEvent(A.getChangeMergedEvent())
|
|
self.waitUntilSettled()
|
|
|
|
# Now that the config change is landed, it should be live for
|
|
# subsequent changes.
|
|
B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
|
|
B.addApproval('Code-Review', 2)
|
|
self.fake_gerrit.addEvent(B.addApproval('Approved', 1))
|
|
self.waitUntilSettled()
|
|
self.assertEqual(self.getJobFromHistory('project-test2').result,
|
|
'SUCCESS')
|
|
self.assertHistory([
|
|
dict(name='project-test2', result='SUCCESS', changes='1,1'),
|
|
dict(name='project-test3', result='SUCCESS', changes='1,1'),
|
|
dict(name='project-test2', result='SUCCESS', changes='2,1'),
|
|
dict(name='project-test3', result='SUCCESS', changes='2,1'),
|
|
], ordered=False)
|
|
|
|
def test_dynamic_template(self):
|
|
# Tests that a project can't update a template in another
|
|
# project.
|
|
in_repo_conf = textwrap.dedent(
|
|
"""
|
|
- job:
|
|
name: project-test1
|
|
|
|
- project-template:
|
|
name: common-config-template
|
|
check:
|
|
jobs:
|
|
- project-test1
|
|
|
|
- project:
|
|
name: org/project
|
|
templates: [common-config-template]
|
|
""")
|
|
|
|
file_dict = {'.zuul.yaml': in_repo_conf}
|
|
A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
|
|
files=file_dict)
|
|
self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
|
|
self.waitUntilSettled()
|
|
|
|
self.assertEqual(A.patchsets[0]['approvals'][0]['value'], "-1")
|
|
self.assertIn('Project template common-config-template '
|
|
'is already defined',
|
|
A.messages[0],
|
|
"A should have failed the check pipeline")
|
|
|
|
def test_dynamic_config_errors_not_accumulated(self):
|
|
"""Test that requesting broken dynamic configs
|
|
does not appear in tenant layout error accumulator"""
|
|
in_repo_conf = textwrap.dedent(
|
|
"""
|
|
- job:
|
|
name: project-test1
|
|
|
|
- project:
|
|
name: org/project
|
|
check:
|
|
jobs:
|
|
- non-existent-job
|
|
""")
|
|
|
|
in_repo_playbook = textwrap.dedent(
|
|
"""
|
|
- hosts: all
|
|
tasks: []
|
|
""")
|
|
|
|
file_dict = {'.zuul.yaml': in_repo_conf,
|
|
'playbooks/project-test2.yaml': in_repo_playbook}
|
|
A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
|
|
files=file_dict)
|
|
self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
|
|
self.waitUntilSettled()
|
|
tenant = self.scheds.first.sched.abide.tenants.get('tenant-one')
|
|
self.assertEquals(
|
|
len(tenant.layout.loading_errors), 0,
|
|
"No error should have been accumulated")
|
|
self.assertHistory([])
|
|
|
|
def test_dynamic_config_non_existing_job(self):
|
|
"""Test that requesting a non existent job fails"""
|
|
in_repo_conf = textwrap.dedent(
|
|
"""
|
|
- job:
|
|
name: project-test1
|
|
|
|
- project:
|
|
name: org/project
|
|
check:
|
|
jobs:
|
|
- non-existent-job
|
|
""")
|
|
|
|
in_repo_playbook = textwrap.dedent(
|
|
"""
|
|
- hosts: all
|
|
tasks: []
|
|
""")
|
|
|
|
file_dict = {'.zuul.yaml': in_repo_conf,
|
|
'playbooks/project-test2.yaml': in_repo_playbook}
|
|
A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
|
|
files=file_dict)
|
|
self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
|
|
self.waitUntilSettled()
|
|
self.assertEqual(A.reported, 1,
|
|
"A should report failure")
|
|
self.assertEqual(A.patchsets[0]['approvals'][0]['value'], "-1")
|
|
self.assertIn('Job non-existent-job not defined', A.messages[0],
|
|
"A should have failed the check pipeline")
|
|
self.assertHistory([])
|
|
self.assertEqual(len(A.comments), 1)
|
|
comments = sorted(A.comments, key=lambda x: x['line'])
|
|
self.assertEqual(comments[0],
|
|
{'file': '.zuul.yaml',
|
|
'line': 9,
|
|
'message': 'Job non-existent-job not defined',
|
|
'reviewer': {'email': 'zuul@example.com',
|
|
'name': 'Zuul',
|
|
'username': 'jenkins'},
|
|
'range': {'end_character': 0,
|
|
'end_line': 9,
|
|
'start_character': 2,
|
|
'start_line': 5},
|
|
})
|
|
|
|
def test_dynamic_config_non_existing_job_in_template(self):
|
|
"""Test that requesting a non existent job fails"""
|
|
in_repo_conf = textwrap.dedent(
|
|
"""
|
|
- job:
|
|
name: project-test1
|
|
|
|
- project-template:
|
|
name: test-template
|
|
check:
|
|
jobs:
|
|
- non-existent-job
|
|
|
|
- project:
|
|
name: org/project
|
|
templates:
|
|
- test-template
|
|
""")
|
|
|
|
in_repo_playbook = textwrap.dedent(
|
|
"""
|
|
- hosts: all
|
|
tasks: []
|
|
""")
|
|
|
|
file_dict = {'.zuul.yaml': in_repo_conf,
|
|
'playbooks/project-test2.yaml': in_repo_playbook}
|
|
A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
|
|
files=file_dict)
|
|
self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
|
|
self.waitUntilSettled()
|
|
self.assertEqual(A.reported, 1,
|
|
"A should report failure")
|
|
self.assertEqual(A.patchsets[0]['approvals'][0]['value'], "-1")
|
|
self.assertIn('Job non-existent-job not defined', A.messages[0],
|
|
"A should have failed the check pipeline")
|
|
self.assertHistory([])
|
|
|
|
def test_dynamic_config_new_patchset(self):
|
|
self.executor_server.hold_jobs_in_build = True
|
|
|
|
tenant = self.scheds.first.sched.abide.tenants.get('tenant-one')
|
|
check_pipeline = tenant.layout.pipelines['check']
|
|
|
|
in_repo_conf = textwrap.dedent(
|
|
"""
|
|
- job:
|
|
name: project-test1
|
|
run: playbooks/project-test1.yaml
|
|
|
|
- job:
|
|
name: project-test2
|
|
run: playbooks/project-test2.yaml
|
|
|
|
- project:
|
|
name: org/project
|
|
check:
|
|
jobs:
|
|
- project-test2
|
|
""")
|
|
|
|
in_repo_playbook = textwrap.dedent(
|
|
"""
|
|
- hosts: all
|
|
tasks: []
|
|
""")
|
|
|
|
file_dict = {'.zuul.yaml': in_repo_conf,
|
|
'playbooks/project-test2.yaml': in_repo_playbook}
|
|
A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
|
|
files=file_dict)
|
|
self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
|
|
self.waitUntilSettled()
|
|
|
|
items = check_pipeline.getAllItems()
|
|
self.assertEqual(items[0].change.number, '1')
|
|
self.assertEqual(items[0].change.patchset, '1')
|
|
self.assertTrue(items[0].live)
|
|
|
|
in_repo_conf = textwrap.dedent(
|
|
"""
|
|
- job:
|
|
name: project-test1
|
|
run: playbooks/project-test1.yaml
|
|
|
|
- job:
|
|
name: project-test2
|
|
run: playbooks/project-test2.yaml
|
|
|
|
- project:
|
|
name: org/project
|
|
check:
|
|
jobs:
|
|
- project-test1
|
|
- project-test2
|
|
""")
|
|
file_dict = {'.zuul.yaml': in_repo_conf,
|
|
'playbooks/project-test2.yaml': in_repo_playbook}
|
|
|
|
A.addPatchset(files=file_dict)
|
|
self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(2))
|
|
|
|
self.waitUntilSettled()
|
|
|
|
items = check_pipeline.getAllItems()
|
|
self.assertEqual(items[0].change.number, '1')
|
|
self.assertEqual(items[0].change.patchset, '2')
|
|
self.assertTrue(items[0].live)
|
|
|
|
self.executor_server.hold_jobs_in_build = False
|
|
self.executor_server.release('project-test1')
|
|
self.waitUntilSettled()
|
|
self.executor_server.release()
|
|
self.waitUntilSettled()
|
|
|
|
self.assertHistory([
|
|
dict(name='project-test2', result='ABORTED', changes='1,1'),
|
|
dict(name='project-test1', result='SUCCESS', changes='1,2'),
|
|
dict(name='project-test2', result='SUCCESS', changes='1,2')])
|
|
|
|
def test_in_repo_branch(self):
|
|
in_repo_conf = textwrap.dedent(
|
|
"""
|
|
- job:
|
|
name: project-test1
|
|
|
|
- job:
|
|
name: project-test2
|
|
run: playbooks/project-test2.yaml
|
|
|
|
- project:
|
|
name: org/project
|
|
tenant-one-gate:
|
|
jobs:
|
|
- project-test2
|
|
""")
|
|
|
|
in_repo_playbook = textwrap.dedent(
|
|
"""
|
|
- hosts: all
|
|
tasks: []
|
|
""")
|
|
|
|
file_dict = {'.zuul.yaml': in_repo_conf,
|
|
'playbooks/project-test2.yaml': in_repo_playbook}
|
|
self.create_branch('org/project', 'stable')
|
|
self.fake_gerrit.addEvent(
|
|
self.fake_gerrit.getFakeBranchCreatedEvent(
|
|
'org/project', 'stable'))
|
|
self.waitUntilSettled()
|
|
A = self.fake_gerrit.addFakeChange('org/project', 'stable', 'A',
|
|
files=file_dict)
|
|
A.addApproval('Code-Review', 2)
|
|
self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
|
|
self.waitUntilSettled()
|
|
self.assertEqual(A.data['status'], 'MERGED')
|
|
self.assertEqual(A.reported, 2,
|
|
"A should report start and success")
|
|
self.assertIn('tenant-one-gate', A.messages[1],
|
|
"A should transit tenant-one gate")
|
|
self.assertHistory([
|
|
dict(name='project-test2', result='SUCCESS', changes='1,1')])
|
|
self.fake_gerrit.addEvent(A.getChangeMergedEvent())
|
|
self.waitUntilSettled()
|
|
|
|
# The config change should not affect master.
|
|
B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
|
|
B.addApproval('Code-Review', 2)
|
|
self.fake_gerrit.addEvent(B.addApproval('Approved', 1))
|
|
self.waitUntilSettled()
|
|
self.assertHistory([
|
|
dict(name='project-test2', result='SUCCESS', changes='1,1'),
|
|
dict(name='project-test1', result='SUCCESS', changes='2,1')])
|
|
|
|
# The config change should be live for further changes on
|
|
# stable.
|
|
C = self.fake_gerrit.addFakeChange('org/project', 'stable', 'C')
|
|
C.addApproval('Code-Review', 2)
|
|
self.fake_gerrit.addEvent(C.addApproval('Approved', 1))
|
|
self.waitUntilSettled()
|
|
self.assertHistory([
|
|
dict(name='project-test2', result='SUCCESS', changes='1,1'),
|
|
dict(name='project-test1', result='SUCCESS', changes='2,1'),
|
|
dict(name='project-test2', result='SUCCESS', changes='3,1')])
|
|
|
|
def test_crd_dynamic_config_branch(self):
|
|
# Test that we can create a job in one repo and be able to use
|
|
# it from a different branch on a different repo.
|
|
|
|
self.create_branch('org/project1', 'stable')
|
|
self.fake_gerrit.addEvent(
|
|
self.fake_gerrit.getFakeBranchCreatedEvent(
|
|
'org/project1', 'stable'))
|
|
|
|
in_repo_conf = textwrap.dedent(
|
|
"""
|
|
- job:
|
|
name: project-test1
|
|
|
|
- job:
|
|
name: project-test2
|
|
run: playbooks/project-test2.yaml
|
|
|
|
- project:
|
|
name: org/project
|
|
check:
|
|
jobs:
|
|
- project-test2
|
|
""")
|
|
|
|
in_repo_playbook = textwrap.dedent(
|
|
"""
|
|
- hosts: all
|
|
tasks: []
|
|
""")
|
|
|
|
file_dict = {'.zuul.yaml': in_repo_conf,
|
|
'playbooks/project-test2.yaml': in_repo_playbook}
|
|
A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
|
|
files=file_dict)
|
|
|
|
second_repo_conf = textwrap.dedent(
|
|
"""
|
|
- project:
|
|
name: org/project1
|
|
check:
|
|
jobs:
|
|
- project-test2
|
|
""")
|
|
|
|
second_file_dict = {'.zuul.yaml': second_repo_conf}
|
|
B = self.fake_gerrit.addFakeChange('org/project1', 'stable', 'B',
|
|
files=second_file_dict)
|
|
B.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
|
|
B.subject, A.data['id'])
|
|
|
|
self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
|
|
self.waitUntilSettled()
|
|
self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
|
|
self.waitUntilSettled()
|
|
|
|
self.assertEqual(A.reported, 1, "A should report")
|
|
self.assertHistory([
|
|
dict(name='project-test2', result='SUCCESS', changes='1,1'),
|
|
dict(name='project-test2', result='SUCCESS', changes='1,1 2,1'),
|
|
])
|
|
|
|
def test_yaml_list_error(self):
|
|
in_repo_conf = textwrap.dedent(
|
|
"""
|
|
job: foo
|
|
""")
|
|
|
|
file_dict = {'.zuul.yaml': in_repo_conf}
|
|
A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
|
|
files=file_dict)
|
|
A.addApproval('Code-Review', 2)
|
|
self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
|
|
self.waitUntilSettled()
|
|
|
|
self.assertEqual(A.data['status'], 'NEW')
|
|
self.assertEqual(A.reported, 1,
|
|
"A should report failure")
|
|
self.assertIn('not a list', A.messages[0],
|
|
"A should have a syntax error reported")
|
|
self.assertIn('job: foo', A.messages[0],
|
|
"A should display the failing list")
|
|
|
|
def test_yaml_dict_error(self):
|
|
in_repo_conf = textwrap.dedent(
|
|
"""
|
|
- job_not_a_dict
|
|
""")
|
|
|
|
file_dict = {'.zuul.yaml': in_repo_conf}
|
|
A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
|
|
files=file_dict)
|
|
A.addApproval('Code-Review', 2)
|
|
self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
|
|
self.waitUntilSettled()
|
|
|
|
self.assertEqual(A.data['status'], 'NEW')
|
|
self.assertEqual(A.reported, 1,
|
|
"A should report failure")
|
|
self.assertIn('not a dictionary', A.messages[0],
|
|
"A should have a syntax error reported")
|
|
self.assertIn('job_not_a_dict', A.messages[0],
|
|
"A should list the bad key")
|
|
|
|
def test_yaml_duplicate_key_error(self):
|
|
in_repo_conf = textwrap.dedent(
|
|
"""
|
|
- job:
|
|
name: foo
|
|
name: bar
|
|
""")
|
|
|
|
file_dict = {'.zuul.yaml': in_repo_conf}
|
|
A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
|
|
files=file_dict)
|
|
A.addApproval('Code-Review', 2)
|
|
self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
|
|
self.waitUntilSettled()
|
|
|
|
self.assertEqual(A.data['status'], 'NEW')
|
|
self.assertEqual(A.reported, 1,
|
|
"A should report failure")
|
|
self.assertIn('appears more than once', A.messages[0],
|
|
"A should have a syntax error reported")
|
|
|
|
def test_yaml_key_error(self):
|
|
in_repo_conf = textwrap.dedent(
|
|
"""
|
|
- job:
|
|
name: project-test2
|
|
""")
|
|
|
|
file_dict = {'.zuul.yaml': in_repo_conf}
|
|
A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
|
|
files=file_dict)
|
|
A.addApproval('Code-Review', 2)
|
|
self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
|
|
self.waitUntilSettled()
|
|
|
|
self.assertEqual(A.data['status'], 'NEW')
|
|
self.assertEqual(A.reported, 1,
|
|
"A should report failure")
|
|
self.assertIn('has more than one key', A.messages[0],
|
|
"A should have a syntax error reported")
|
|
self.assertIn("job: null\n name: project-test2", A.messages[0],
|
|
"A should have the failing section displayed")
|
|
|
|
# This is non-deterministic without default dict ordering, which
|
|
# happended with python 3.7.
|
|
@skipIf(sys.version_info < (3, 7), "non-deterministic on < 3.7")
|
|
def test_yaml_error_truncation_message(self):
|
|
in_repo_conf = textwrap.dedent(
|
|
"""
|
|
- job:
|
|
name: project-test2
|
|
this: is
|
|
a: long
|
|
set: of
|
|
keys: that
|
|
should: be
|
|
truncated: ok
|
|
""")
|
|
|
|
file_dict = {'.zuul.yaml': in_repo_conf}
|
|
A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
|
|
files=file_dict)
|
|
A.addApproval('Code-Review', 2)
|
|
self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
|
|
self.waitUntilSettled()
|
|
|
|
self.assertEqual(A.data['status'], 'NEW')
|
|
self.assertEqual(A.reported, 1,
|
|
"A should report failure")
|
|
self.assertIn('has more than one key', A.messages[0],
|
|
"A should have a syntax error reported")
|
|
self.assertIn("job: null\n name: project-test2", A.messages[0],
|
|
"A should have the failing section displayed")
|
|
self.assertIn("...", A.messages[0],
|
|
"A should have the failing section truncated")
|
|
|
|
def test_yaml_unknown_error(self):
|
|
in_repo_conf = textwrap.dedent(
|
|
"""
|
|
- foobar:
|
|
foo: bar
|
|
""")
|
|
|
|
file_dict = {'.zuul.yaml': in_repo_conf}
|
|
A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
|
|
files=file_dict)
|
|
A.addApproval('Code-Review', 2)
|
|
self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
|
|
self.waitUntilSettled()
|
|
|
|
self.assertEqual(A.data['status'], 'NEW')
|
|
self.assertEqual(A.reported, 1,
|
|
"A should report failure")
|
|
self.assertIn('not recognized', A.messages[0],
|
|
"A should have a syntax error reported")
|
|
self.assertIn('foobar:\n foo: bar', A.messages[0],
|
|
"A should report the bad keys")
|
|
|
|
def test_invalid_job_secret_var_name(self):
|
|
in_repo_conf = textwrap.dedent(
|
|
"""
|
|
- secret:
|
|
name: foo-bar
|
|
data:
|
|
dummy: value
|
|
- job:
|
|
name: foobar
|
|
secrets:
|
|
- name: foo-bar
|
|
secret: foo-bar
|
|
""")
|
|
|
|
file_dict = {".zuul.yaml": in_repo_conf}
|
|
A = self.fake_gerrit.addFakeChange("org/project", "master", "A",
|
|
files=file_dict)
|
|
A.addApproval("Code-Review", 2)
|
|
self.fake_gerrit.addEvent(A.addApproval("Approved", 1))
|
|
self.waitUntilSettled()
|
|
|
|
self.assertEqual(A.data["status"], "NEW")
|
|
self.assertEqual(A.reported, 1,
|
|
"A should report failure")
|
|
self.assertIn("Ansible variable name 'foo-bar'", A.messages[0],
|
|
"A should have a syntax error reported")
|
|
|
|
def test_invalid_job_vars(self):
|
|
in_repo_conf = textwrap.dedent(
|
|
"""
|
|
- job:
|
|
name: foobar
|
|
vars:
|
|
foo-bar: value
|
|
""")
|
|
|
|
file_dict = {".zuul.yaml": in_repo_conf}
|
|
A = self.fake_gerrit.addFakeChange("org/project", "master", "A",
|
|
files=file_dict)
|
|
A.addApproval("Code-Review", 2)
|
|
self.fake_gerrit.addEvent(A.addApproval("Approved", 1))
|
|
self.waitUntilSettled()
|
|
|
|
self.assertEqual(A.data["status"], "NEW")
|
|
self.assertEqual(A.reported, 1,
|
|
"A should report failure")
|
|
self.assertIn("Ansible variable name 'foo-bar'", A.messages[0],
|
|
"A should have a syntax error reported")
|
|
|
|
def test_invalid_job_extra_vars(self):
|
|
in_repo_conf = textwrap.dedent(
|
|
"""
|
|
- job:
|
|
name: foobar
|
|
extra-vars:
|
|
foo-bar: value
|
|
""")
|
|
|
|
file_dict = {".zuul.yaml": in_repo_conf}
|
|
A = self.fake_gerrit.addFakeChange("org/project", "master", "A",
|
|
files=file_dict)
|
|
A.addApproval("Code-Review", 2)
|
|
self.fake_gerrit.addEvent(A.addApproval("Approved", 1))
|
|
self.waitUntilSettled()
|
|
|
|
self.assertEqual(A.data["status"], "NEW")
|
|
self.assertEqual(A.reported, 1,
|
|
"A should report failure")
|
|
self.assertIn("Ansible variable name 'foo-bar'", A.messages[0],
|
|
"A should have a syntax error reported")
|
|
|
|
def test_invalid_job_host_vars(self):
|
|
in_repo_conf = textwrap.dedent(
|
|
"""
|
|
- job:
|
|
name: foobar
|
|
host-vars:
|
|
host-name:
|
|
foo-bar: value
|
|
""")
|
|
|
|
file_dict = {".zuul.yaml": in_repo_conf}
|
|
A = self.fake_gerrit.addFakeChange("org/project", "master", "A",
|
|
files=file_dict)
|
|
A.addApproval("Code-Review", 2)
|
|
self.fake_gerrit.addEvent(A.addApproval("Approved", 1))
|
|
self.waitUntilSettled()
|
|
|
|
self.assertEqual(A.data["status"], "NEW")
|
|
self.assertEqual(A.reported, 1,
|
|
"A should report failure")
|
|
self.assertIn("Ansible variable name 'foo-bar'", A.messages[0],
|
|
"A should have a syntax error reported")
|
|
|
|
def test_invalid_job_group_vars(self):
|
|
in_repo_conf = textwrap.dedent(
|
|
"""
|
|
- job:
|
|
name: foobar
|
|
group-vars:
|
|
group-name:
|
|
foo-bar: value
|
|
""")
|
|
|
|
file_dict = {".zuul.yaml": in_repo_conf}
|
|
A = self.fake_gerrit.addFakeChange("org/project", "master", "A",
|
|
files=file_dict)
|
|
A.addApproval("Code-Review", 2)
|
|
self.fake_gerrit.addEvent(A.addApproval("Approved", 1))
|
|
self.waitUntilSettled()
|
|
|
|
self.assertEqual(A.data["status"], "NEW")
|
|
self.assertEqual(A.reported, 1,
|
|
"A should report failure")
|
|
self.assertIn("Ansible variable name 'foo-bar'", A.messages[0],
|
|
"A should have a syntax error reported")
|
|
|
|
def test_untrusted_syntax_error(self):
|
|
in_repo_conf = textwrap.dedent(
|
|
"""
|
|
- job:
|
|
name: project-test2
|
|
foo: error
|
|
""")
|
|
|
|
file_dict = {'.zuul.yaml': in_repo_conf}
|
|
A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
|
|
files=file_dict)
|
|
A.addApproval('Code-Review', 2)
|
|
self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
|
|
self.waitUntilSettled()
|
|
|
|
self.assertEqual(A.data['status'], 'NEW')
|
|
self.assertEqual(A.reported, 1,
|
|
"A should report failure")
|
|
self.assertIn('syntax error', A.messages[0],
|
|
"A should have a syntax error reported")
|
|
|
|
def test_trusted_syntax_error(self):
|
|
in_repo_conf = textwrap.dedent(
|
|
"""
|
|
- job:
|
|
name: project-test2
|
|
foo: error
|
|
""")
|
|
|
|
file_dict = {'zuul.yaml': in_repo_conf}
|
|
A = self.fake_gerrit.addFakeChange('common-config', 'master', 'A',
|
|
files=file_dict)
|
|
A.addApproval('Code-Review', 2)
|
|
self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
|
|
self.waitUntilSettled()
|
|
|
|
self.assertEqual(A.data['status'], 'NEW')
|
|
self.assertEqual(A.reported, 1,
|
|
"A should report failure")
|
|
self.assertIn('syntax error', A.messages[0],
|
|
"A should have a syntax error reported")
|
|
|
|
def test_untrusted_yaml_error(self):
|
|
in_repo_conf = textwrap.dedent(
|
|
"""
|
|
- job:
|
|
foo: error
|
|
""")
|
|
|
|
file_dict = {'.zuul.yaml': in_repo_conf}
|
|
A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
|
|
files=file_dict)
|
|
A.addApproval('Code-Review', 2)
|
|
self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
|
|
self.waitUntilSettled()
|
|
|
|
self.assertEqual(A.data['status'], 'NEW')
|
|
self.assertEqual(A.reported, 1,
|
|
"A should report failure")
|
|
self.assertIn('syntax error', A.messages[0],
|
|
"A should have a syntax error reported")
|
|
|
|
def test_untrusted_shadow_error(self):
|
|
in_repo_conf = textwrap.dedent(
|
|
"""
|
|
- job:
|
|
name: common-config-test
|
|
""")
|
|
|
|
file_dict = {'.zuul.yaml': in_repo_conf}
|
|
A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
|
|
files=file_dict)
|
|
A.addApproval('Code-Review', 2)
|
|
self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
|
|
self.waitUntilSettled()
|
|
|
|
self.assertEqual(A.data['status'], 'NEW')
|
|
self.assertEqual(A.reported, 1,
|
|
"A should report failure")
|
|
self.assertIn('not permitted to shadow', A.messages[0],
|
|
"A should have a syntax error reported")
|
|
|
|
def test_untrusted_pipeline_error(self):
|
|
in_repo_conf = textwrap.dedent(
|
|
"""
|
|
- pipeline:
|
|
name: test
|
|
""")
|
|
|
|
file_dict = {'.zuul.yaml': in_repo_conf}
|
|
A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
|
|
files=file_dict)
|
|
A.addApproval('Code-Review', 2)
|
|
self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
|
|
self.waitUntilSettled()
|
|
|
|
self.assertEqual(A.data['status'], 'NEW')
|
|
self.assertEqual(A.reported, 1,
|
|
"A should report failure")
|
|
self.assertIn('Pipelines may not be defined', A.messages[0],
|
|
"A should have a syntax error reported")
|
|
|
|
def test_untrusted_project_error(self):
|
|
in_repo_conf = textwrap.dedent(
|
|
"""
|
|
- project:
|
|
name: org/project1
|
|
""")
|
|
|
|
file_dict = {'.zuul.yaml': in_repo_conf}
|
|
A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
|
|
files=file_dict)
|
|
A.addApproval('Code-Review', 2)
|
|
self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
|
|
self.waitUntilSettled()
|
|
|
|
self.assertEqual(A.data['status'], 'NEW')
|
|
self.assertEqual(A.reported, 1,
|
|
"A should report failure")
|
|
self.assertIn('the only project definition permitted', A.messages[0],
|
|
"A should have a syntax error reported")
|
|
|
|
def test_untrusted_depends_on_trusted(self):
|
|
with open(os.path.join(FIXTURE_DIR,
|
|
'config/in-repo/git/',
|
|
'common-config/zuul.yaml')) as f:
|
|
common_config = f.read()
|
|
|
|
common_config += textwrap.dedent(
|
|
"""
|
|
- job:
|
|
name: project-test9
|
|
""")
|
|
|
|
file_dict = {'zuul.yaml': common_config}
|
|
A = self.fake_gerrit.addFakeChange('common-config', 'master', 'A',
|
|
files=file_dict)
|
|
in_repo_conf = textwrap.dedent(
|
|
"""
|
|
- job:
|
|
name: project-test1
|
|
- project:
|
|
name: org/project
|
|
check:
|
|
jobs:
|
|
- project-test9
|
|
""")
|
|
|
|
file_dict = {'zuul.yaml': in_repo_conf}
|
|
B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B',
|
|
files=file_dict)
|
|
B.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
|
|
B.subject, A.data['id'])
|
|
self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
|
|
self.waitUntilSettled()
|
|
|
|
self.assertEqual(B.data['status'], 'NEW')
|
|
self.assertEqual(B.reported, 1,
|
|
"B should report failure")
|
|
self.assertIn('depends on a change to a config project',
|
|
B.messages[0],
|
|
"A should have a syntax error reported")
|
|
|
|
def test_duplicate_node_error(self):
|
|
in_repo_conf = textwrap.dedent(
|
|
"""
|
|
- nodeset:
|
|
name: duplicate
|
|
nodes:
|
|
- name: compute
|
|
label: foo
|
|
- name: compute
|
|
label: foo
|
|
""")
|
|
|
|
file_dict = {'.zuul.yaml': in_repo_conf}
|
|
A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
|
|
files=file_dict)
|
|
A.addApproval('Code-Review', 2)
|
|
self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
|
|
self.waitUntilSettled()
|
|
|
|
self.assertEqual(A.data['status'], 'NEW')
|
|
self.assertEqual(A.reported, 1,
|
|
"A should report failure")
|
|
self.assertIn('appears multiple times', A.messages[0],
|
|
"A should have a syntax error reported")
|
|
|
|
def test_duplicate_group_error(self):
|
|
in_repo_conf = textwrap.dedent(
|
|
"""
|
|
- nodeset:
|
|
name: duplicate
|
|
nodes:
|
|
- name: compute
|
|
label: foo
|
|
groups:
|
|
- name: group
|
|
nodes: compute
|
|
- name: group
|
|
nodes: compute
|
|
""")
|
|
|
|
file_dict = {'.zuul.yaml': in_repo_conf}
|
|
A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
|
|
files=file_dict)
|
|
A.addApproval('Code-Review', 2)
|
|
self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
|
|
self.waitUntilSettled()
|
|
|
|
self.assertEqual(A.data['status'], 'NEW')
|
|
self.assertEqual(A.reported, 1,
|
|
"A should report failure")
|
|
self.assertIn('appears multiple times', A.messages[0],
|
|
"A should have a syntax error reported")
|
|
|
|
def test_secret_not_found_error(self):
|
|
in_repo_conf = textwrap.dedent(
|
|
"""
|
|
- job:
|
|
name: project-test1
|
|
run: playbooks/project-test1.yaml
|
|
secrets: does-not-exist
|
|
""")
|
|
|
|
file_dict = {'.zuul.yaml': in_repo_conf}
|
|
A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
|
|
files=file_dict)
|
|
A.addApproval('Code-Review', 2)
|
|
self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
|
|
self.waitUntilSettled()
|
|
|
|
self.assertEqual(A.data['status'], 'NEW')
|
|
self.assertEqual(A.reported, 1,
|
|
"A should report failure")
|
|
self.assertIn('secret "does-not-exist" was not found', A.messages[0],
|
|
"A should have a syntax error reported")
|
|
|
|
def test_nodeset_not_found_error(self):
|
|
in_repo_conf = textwrap.dedent(
|
|
"""
|
|
- job:
|
|
name: test
|
|
nodeset: does-not-exist
|
|
""")
|
|
|
|
file_dict = {'.zuul.yaml': in_repo_conf}
|
|
A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
|
|
files=file_dict)
|
|
A.addApproval('Code-Review', 2)
|
|
self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
|
|
self.waitUntilSettled()
|
|
|
|
self.assertEqual(A.data['status'], 'NEW')
|
|
self.assertEqual(A.reported, 1,
|
|
"A should report failure")
|
|
self.assertIn('nodeset "does-not-exist" was not found', A.messages[0],
|
|
"A should have a syntax error reported")
|
|
|
|
def test_required_project_not_found_error(self):
|
|
in_repo_conf = textwrap.dedent(
|
|
"""
|
|
- job:
|
|
name: project-test1
|
|
- job:
|
|
name: test
|
|
required-projects:
|
|
- does-not-exist
|
|
""")
|
|
|
|
file_dict = {'.zuul.yaml': in_repo_conf}
|
|
A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
|
|
files=file_dict)
|
|
A.addApproval('Code-Review', 2)
|
|
self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
|
|
self.waitUntilSettled()
|
|
|
|
self.assertEqual(A.data['status'], 'NEW')
|
|
self.assertEqual(A.reported, 1,
|
|
"A should report failure")
|
|
self.assertIn('Unknown projects: does-not-exist', A.messages[0],
|
|
"A should have a syntax error reported")
|
|
|
|
def test_required_project_not_found_multiple_error(self):
|
|
in_repo_conf = textwrap.dedent(
|
|
"""
|
|
- job:
|
|
name: project-test1
|
|
- job:
|
|
name: test
|
|
required-projects:
|
|
- does-not-exist
|
|
- also-does-not-exist
|
|
""")
|
|
|
|
file_dict = {'.zuul.yaml': in_repo_conf}
|
|
A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
|
|
files=file_dict)
|
|
A.addApproval('Code-Review', 2)
|
|
self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
|
|
self.waitUntilSettled()
|
|
|
|
self.assertEqual(A.data['status'], 'NEW')
|
|
self.assertEqual(A.reported, 1,
|
|
"A should report failure")
|
|
self.assertIn('Unknown projects: does-not-exist, also-does-not-exist',
|
|
A.messages[0], "A should have a syntax error reported")
|
|
|
|
def test_template_not_found_error(self):
|
|
in_repo_conf = textwrap.dedent(
|
|
"""
|
|
- job:
|
|
name: project-test1
|
|
- project:
|
|
name: org/project
|
|
templates:
|
|
- does-not-exist
|
|
""")
|
|
|
|
file_dict = {'.zuul.yaml': in_repo_conf}
|
|
A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
|
|
files=file_dict)
|
|
A.addApproval('Code-Review', 2)
|
|
self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
|
|
self.waitUntilSettled()
|
|
|
|
self.assertEqual(A.data['status'], 'NEW')
|
|
self.assertEqual(A.reported, 1,
|
|
"A should report failure")
|
|
self.assertIn('project template "does-not-exist" was not found',
|
|
A.messages[0],
|
|
"A should have a syntax error reported")
|
|
|
|
def test_job_list_in_project_template_not_dict_error(self):
|
|
in_repo_conf = textwrap.dedent(
|
|
"""
|
|
- job:
|
|
name: project-test1
|
|
- project-template:
|
|
name: some-jobs
|
|
check:
|
|
jobs:
|
|
- project-test1:
|
|
- required-projects:
|
|
org/project2
|
|
""")
|
|
|
|
file_dict = {'.zuul.yaml': in_repo_conf}
|
|
A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
|
|
files=file_dict)
|
|
A.addApproval('Code-Review', 2)
|
|
self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
|
|
self.waitUntilSettled()
|
|
|
|
self.assertEqual(A.data['status'], 'NEW')
|
|
self.assertEqual(A.reported, 1,
|
|
"A should report failure")
|
|
self.assertIn('expected str for dictionary value',
|
|
A.messages[0], "A should have a syntax error reported")
|
|
|
|
def test_job_list_in_project_not_dict_error(self):
|
|
in_repo_conf = textwrap.dedent(
|
|
"""
|
|
- job:
|
|
name: project-test1
|
|
- project:
|
|
name: org/project1
|
|
check:
|
|
jobs:
|
|
- project-test1:
|
|
- required-projects:
|
|
org/project2
|
|
""")
|
|
|
|
file_dict = {'.zuul.yaml': in_repo_conf}
|
|
A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
|
|
files=file_dict)
|
|
A.addApproval('Code-Review', 2)
|
|
self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
|
|
self.waitUntilSettled()
|
|
|
|
self.assertEqual(A.data['status'], 'NEW')
|
|
self.assertEqual(A.reported, 1,
|
|
"A should report failure")
|
|
self.assertIn('expected str for dictionary value',
|
|
A.messages[0], "A should have a syntax error reported")
|
|
|
|
def test_project_template(self):
|
|
# Tests that a project template is not modified when used, and
|
|
# can therefore be used in subsequent reconfigurations.
|
|
in_repo_conf = textwrap.dedent(
|
|
"""
|
|
- job:
|
|
name: project-test1
|
|
run: playbooks/project-test1.yaml
|
|
- project-template:
|
|
name: some-jobs
|
|
tenant-one-gate:
|
|
jobs:
|
|
- project-test1:
|
|
required-projects:
|
|
- org/project1
|
|
- project:
|
|
name: org/project
|
|
templates:
|
|
- some-jobs
|
|
""")
|
|
|
|
file_dict = {'.zuul.yaml': in_repo_conf}
|
|
A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
|
|
files=file_dict)
|
|
A.addApproval('Code-Review', 2)
|
|
self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
|
|
self.waitUntilSettled()
|
|
self.assertEqual(A.data['status'], 'MERGED')
|
|
self.fake_gerrit.addEvent(A.getChangeMergedEvent())
|
|
self.waitUntilSettled()
|
|
in_repo_conf = textwrap.dedent(
|
|
"""
|
|
- project:
|
|
name: org/project1
|
|
templates:
|
|
- some-jobs
|
|
""")
|
|
file_dict = {'.zuul.yaml': in_repo_conf}
|
|
B = self.fake_gerrit.addFakeChange('org/project1', 'master', 'B',
|
|
files=file_dict)
|
|
B.addApproval('Code-Review', 2)
|
|
self.fake_gerrit.addEvent(B.addApproval('Approved', 1))
|
|
self.waitUntilSettled()
|
|
self.assertEqual(B.data['status'], 'MERGED')
|
|
|
|
def test_job_remove_add(self):
|
|
# Tests that a job can be removed from one repo and added in another.
|
|
# First, remove the current config for project1 since it
|
|
# references the job we want to remove.
|
|
file_dict = {'.zuul.yaml': None}
|
|
A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A',
|
|
files=file_dict)
|
|
A.setMerged()
|
|
self.fake_gerrit.addEvent(A.getChangeMergedEvent())
|
|
self.waitUntilSettled()
|
|
# Then propose a change to delete the job from one repo...
|
|
file_dict = {'.zuul.yaml': None}
|
|
B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B',
|
|
files=file_dict)
|
|
self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
|
|
self.waitUntilSettled()
|
|
# ...and a second that depends on it that adds it to another repo.
|
|
in_repo_conf = textwrap.dedent(
|
|
"""
|
|
- job:
|
|
name: project-test1
|
|
run: playbooks/project-test1.yaml
|
|
|
|
- project:
|
|
name: org/project1
|
|
check:
|
|
jobs:
|
|
- project-test1
|
|
""")
|
|
in_repo_playbook = textwrap.dedent(
|
|
"""
|
|
- hosts: all
|
|
tasks: []
|
|
""")
|
|
file_dict = {'.zuul.yaml': in_repo_conf,
|
|
'playbooks/project-test1.yaml': in_repo_playbook}
|
|
C = self.fake_gerrit.addFakeChange('org/project1', 'master', 'C',
|
|
files=file_dict,
|
|
parent='refs/changes/1/1/1')
|
|
C.data['commitMessage'] = '%s\n\nDepends-On: %s\n' % (
|
|
C.subject, B.data['id'])
|
|
self.fake_gerrit.addEvent(C.getPatchsetCreatedEvent(1))
|
|
self.waitUntilSettled()
|
|
self.assertHistory([
|
|
dict(name='project-test1', result='SUCCESS', changes='2,1 3,1'),
|
|
], ordered=False)
|
|
|
|
def test_multi_repo(self):
|
|
downstream_repo_conf = textwrap.dedent(
|
|
"""
|
|
- project:
|
|
name: org/project1
|
|
tenant-one-gate:
|
|
jobs:
|
|
- project-test1
|
|
|
|
- job:
|
|
name: project1-test1
|
|
parent: project-test1
|
|
""")
|
|
|
|
file_dict = {'.zuul.yaml': downstream_repo_conf}
|
|
A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A',
|
|
files=file_dict)
|
|
A.addApproval('Code-Review', 2)
|
|
self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
|
|
self.waitUntilSettled()
|
|
|
|
self.assertEqual(A.data['status'], 'MERGED')
|
|
self.fake_gerrit.addEvent(A.getChangeMergedEvent())
|
|
self.waitUntilSettled()
|
|
|
|
upstream_repo_conf = textwrap.dedent(
|
|
"""
|
|
- job:
|
|
name: project-test1
|
|
run: playbooks/project-test1.yaml
|
|
|
|
- job:
|
|
name: project-test2
|
|
|
|
- project:
|
|
name: org/project
|
|
tenant-one-gate:
|
|
jobs:
|
|
- project-test1
|
|
""")
|
|
|
|
file_dict = {'.zuul.yaml': upstream_repo_conf}
|
|
B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B',
|
|
files=file_dict)
|
|
B.addApproval('Code-Review', 2)
|
|
self.fake_gerrit.addEvent(B.addApproval('Approved', 1))
|
|
self.waitUntilSettled()
|
|
|
|
self.assertEqual(B.data['status'], 'MERGED')
|
|
self.fake_gerrit.addEvent(B.getChangeMergedEvent())
|
|
self.waitUntilSettled()
|
|
|
|
tenant = self.scheds.first.sched.abide.tenants.get('tenant-one')
|
|
# Ensure the latest change is reflected in the config; if it
|
|
# isn't this will raise an exception.
|
|
tenant.layout.getJob('project-test2')
|
|
|
|
def test_pipeline_error(self):
|
|
with open(os.path.join(FIXTURE_DIR,
|
|
'config/in-repo/git/',
|
|
'common-config/zuul.yaml')) as f:
|
|
base_common_config = f.read()
|
|
|
|
in_repo_conf_A = textwrap.dedent(
|
|
"""
|
|
- pipeline:
|
|
name: periodic
|
|
foo: error
|
|
""")
|
|
|
|
file_dict = {'zuul.yaml': None,
|
|
'zuul.d/main.yaml': base_common_config,
|
|
'zuul.d/test1.yaml': in_repo_conf_A}
|
|
A = self.fake_gerrit.addFakeChange('common-config', 'master', 'A',
|
|
files=file_dict)
|
|
self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
|
|
self.waitUntilSettled()
|
|
self.assertEqual(A.reported, 1,
|
|
"A should report failure")
|
|
self.assertIn('syntax error',
|
|
A.messages[0],
|
|
"A should have an error reported")
|
|
|
|
def test_pipeline_supercedes_error(self):
|
|
with open(os.path.join(FIXTURE_DIR,
|
|
'config/in-repo/git/',
|
|
'common-config/zuul.yaml')) as f:
|
|
base_common_config = f.read()
|
|
|
|
in_repo_conf_A = textwrap.dedent(
|
|
"""
|
|
- pipeline:
|
|
name: periodic
|
|
manager: independent
|
|
supercedes: doesnotexist
|
|
trigger: {}
|
|
""")
|
|
|
|
file_dict = {'zuul.yaml': None,
|
|
'zuul.d/main.yaml': base_common_config,
|
|
'zuul.d/test1.yaml': in_repo_conf_A}
|
|
A = self.fake_gerrit.addFakeChange('common-config', 'master', 'A',
|
|
files=file_dict)
|
|
self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
|
|
self.waitUntilSettled()
|
|
self.assertEqual(A.reported, 1,
|
|
"A should report failure")
|
|
self.assertIn('supercedes an unknown',
|
|
A.messages[0],
|
|
"A should have an error reported")
|
|
|
|
def test_change_series_error(self):
|
|
with open(os.path.join(FIXTURE_DIR,
|
|
'config/in-repo/git/',
|
|
'common-config/zuul.yaml')) as f:
|
|
base_common_config = f.read()
|
|
|
|
in_repo_conf_A = textwrap.dedent(
|
|
"""
|
|
- pipeline:
|
|
name: periodic
|
|
foo: error
|
|
""")
|
|
|
|
file_dict = {'zuul.yaml': None,
|
|
'zuul.d/main.yaml': base_common_config,
|
|
'zuul.d/test1.yaml': in_repo_conf_A}
|
|
A = self.fake_gerrit.addFakeChange('common-config', 'master', 'A',
|
|
files=file_dict)
|
|
|
|
in_repo_conf_B = textwrap.dedent(
|
|
"""
|
|
- job:
|
|
name: project-test2
|
|
foo: error
|
|
""")
|
|
|
|
file_dict = {'zuul.yaml': None,
|
|
'zuul.d/main.yaml': base_common_config,
|
|
'zuul.d/test1.yaml': in_repo_conf_A,
|
|
'zuul.d/test2.yaml': in_repo_conf_B}
|
|
B = self.fake_gerrit.addFakeChange('common-config', 'master', 'B',
|
|
files=file_dict)
|
|
B.setDependsOn(A, 1)
|
|
C = self.fake_gerrit.addFakeChange('common-config', 'master', 'C')
|
|
C.setDependsOn(B, 1)
|
|
self.fake_gerrit.addEvent(C.getPatchsetCreatedEvent(1))
|
|
self.waitUntilSettled()
|
|
|
|
self.assertEqual(C.reported, 1,
|
|
"C should report failure")
|
|
self.assertIn('This change depends on a change '
|
|
'with an invalid configuration.',
|
|
C.messages[0],
|
|
"C should have an error reported")
|
|
|
|
def test_pipeline_debug(self):
|
|
in_repo_conf = textwrap.dedent(
|
|
"""
|
|
- job:
|
|
name: project-test1
|
|
run: playbooks/project-test1.yaml
|
|
- project:
|
|
name: org/project
|
|
check:
|
|
debug: True
|
|
jobs:
|
|
- project-test1
|
|
""")
|
|
|
|
file_dict = {'.zuul.yaml': in_repo_conf}
|
|
A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
|
|
files=file_dict)
|
|
self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
|
|
self.waitUntilSettled()
|
|
|
|
self.assertEqual(A.data['status'], 'NEW')
|
|
self.assertEqual(A.reported, 1,
|
|
"A should report success")
|
|
self.assertIn('Debug information:' |