Don't exclude config if excluded in earlier tenant

Consider the following scenario where tenant-one includes org/project1
without any config. Zuul currently doesn't load the config of
org/project1 in tenant-two as well.

- tenant:
    name: tenant-one
    source:
      gerrit:
        untrusted-projects:
          - org/project1:
              include: []

- tenant:
    name: tenant-two
    source:
      gerrit:
        untrusted-projects:
          - org/project1

This is caused because we cache an empty config if we exclude all
config from the repo the same way as if the repo wouldn't have any
config. This causes the cat job to be skipped when loading
tenant-two. This can be solved by marking the empty config that will
be cached as 'this has no config because it has been skipped'. Then we
can detect that case and still trigger a cat job if we need the config
in a later tenant.

Change-Id: I1e7e68f11ca4fb7d1e52eee6d4c9a9d8331b012c
This commit is contained in:
Tobias Henkel 2019-02-11 15:49:59 +01:00
parent 9019158139
commit fac26fb890
No known key found for this signature in database
GPG Key ID: 03750DEC158E5FA2
5 changed files with 49 additions and 4 deletions

View File

@ -0,0 +1,21 @@
- tenant:
name: tenant-one
source:
gerrit:
config-projects:
- common-config
untrusted-projects:
- org/project1:
include: []
- org/project2
- tenant:
name: tenant-two
source:
gerrit:
config-projects:
- common-config
untrusted-projects:
- org/project1
- org/project2
- org/project5

View File

@ -0,0 +1,3 @@
- job:
name: project5-job
parent: project1-job

View File

@ -312,6 +312,22 @@ class TestTenantUnprotectedBranches(TenantParserTestCase):
self.assertIsNone(tpc[project_name].exclude_unprotected_branches) self.assertIsNone(tpc[project_name].exclude_unprotected_branches)
class TestTenantExcludeAll(TenantParserTestCase):
tenant_config_file = 'config/tenant-parser/exclude-all.yaml'
def test_tenant_exclude_all(self):
"""
Tests that excluding all configuration of project1 in tenant-one
doesn't remove the configuration of project1 in tenant-two.
"""
# The config in org/project5 depends on config in org/project1 so
# validate that there are no config errors in that tenant.
tenant_two = self.sched.abide.tenants.get('tenant-two')
self.assertEquals(
len(tenant_two.layout.loading_errors), 0,
"No error should have been accumulated")
class TestSplitConfig(ZuulTestCase): class TestSplitConfig(ZuulTestCase):
tenant_config_file = 'config/split-config/main.yaml' tenant_config_file = 'config/split-config/main.yaml'

View File

@ -1563,8 +1563,9 @@ class TenantParser(object):
# in-repo configuration apply only to that branch. # in-repo configuration apply only to that branch.
branches = tenant.getProjectBranches(project) branches = tenant.getProjectBranches(project)
for branch in branches: for branch in branches:
if abide.getUnparsedConfig(project.canonical_name, unparsed_config = abide.getUnparsedConfig(
branch): project.canonical_name, branch)
if unparsed_config and not unparsed_config.load_skipped:
# We already have this branch cached. # We already have this branch cached.
continue continue
if not tpc.load_classes: if not tpc.load_classes:
@ -1573,7 +1574,7 @@ class TenantParser(object):
# data so we know we've looked at this branch. # data so we know we've looked at this branch.
abide.cacheUnparsedConfig( abide.cacheUnparsedConfig(
project.canonical_name, project.canonical_name,
branch, model.UnparsedConfig()) branch, model.UnparsedConfig(load_skipped=True))
continue continue
job = self.merger.getFiles( job = self.merger.getFiles(
project.source.connection.connection_name, project.source.connection.connection_name,

View File

@ -3215,7 +3215,7 @@ class UnparsedAbideConfig(object):
class UnparsedConfig(object): class UnparsedConfig(object):
"""A collection of yaml lists that has not yet been parsed into objects.""" """A collection of yaml lists that has not yet been parsed into objects."""
def __init__(self): def __init__(self, load_skipped=False):
self.pragmas = [] self.pragmas = []
self.pipelines = [] self.pipelines = []
self.jobs = [] self.jobs = []
@ -3225,6 +3225,10 @@ class UnparsedConfig(object):
self.secrets = [] self.secrets = []
self.semaphores = [] self.semaphores = []
# This indicates wether this is empty because we skipped loading
# earlier because all config items have been excluded.
self.load_skipped = load_skipped
def copy(self, trusted=None): def copy(self, trusted=None):
# If trusted is not None, update the source context of each # If trusted is not None, update the source context of each
# object in the copy. # object in the copy.