Add allowed-triggers and allowed-reporters tenant settings
This changes adds new tenant settings to limit the connection a tenant can use to trigger from or report to. Change-Id: I1793ec9c8a249b3a1ce90868086421c8d349d7aa
This commit is contained in:
parent
71f60674b9
commit
489812e041
@ -233,3 +233,17 @@ configuration. Some examples of tenant definitions are:
|
||||
This allows an administrator to configure a default base job to
|
||||
implement local policies such as node setup and artifact
|
||||
publishing.
|
||||
|
||||
.. attr:: allowed-triggers
|
||||
:default: all connections
|
||||
|
||||
The list of connections a tenant can trigger from. When set, this setting
|
||||
can be used to restrict what connections a tenant can use as trigger.
|
||||
Without this setting, the tenant can use any connection as a trigger.
|
||||
|
||||
.. attr:: allowed-reporters
|
||||
:default: all connections
|
||||
|
||||
The list of connections a tenant can report to. When set, this setting
|
||||
can be used to restrict what connections a tenant can use as reporter.
|
||||
Without this setting, the tenant can report to any connection.
|
||||
|
@ -0,0 +1,6 @@
|
||||
---
|
||||
features:
|
||||
- |
|
||||
New tenant options :attr:`tenant.allowed-triggers` and
|
||||
:attr:`tenant.allowed-reporters` can be used to restrict
|
||||
what connections a tenant has access to.
|
@ -39,3 +39,9 @@
|
||||
jobs:
|
||||
- python27
|
||||
- project1-test1
|
||||
|
||||
- project:
|
||||
name: tenant-one-config
|
||||
check:
|
||||
jobs:
|
||||
- noop
|
@ -39,3 +39,9 @@
|
||||
jobs:
|
||||
- python27
|
||||
- project2-test1
|
||||
|
||||
- project:
|
||||
name: tenant-two-config
|
||||
check:
|
||||
jobs:
|
||||
- noop
|
3
tests/fixtures/config/multi-tenant/main.yaml
vendored
3
tests/fixtures/config/multi-tenant/main.yaml
vendored
@ -1,6 +1,8 @@
|
||||
- tenant:
|
||||
name: tenant-one
|
||||
max-job-timeout: 1800
|
||||
allowed-reporters:
|
||||
- gerrit
|
||||
source:
|
||||
gerrit:
|
||||
config-projects:
|
||||
@ -12,6 +14,7 @@
|
||||
- tenant:
|
||||
name: tenant-two
|
||||
max-nodes-per-job: 10
|
||||
allowed-triggers: gerrit
|
||||
source:
|
||||
gerrit:
|
||||
config-projects:
|
||||
|
@ -3176,6 +3176,65 @@ class TestMaxTimeout(ZuulTestCase):
|
||||
"B should not fail because of timeout limit")
|
||||
|
||||
|
||||
class TestAllowedConnection(AnsibleZuulTestCase):
|
||||
config_file = 'zuul-connections-gerrit-and-github.conf'
|
||||
tenant_config_file = 'config/multi-tenant/main.yaml'
|
||||
|
||||
def test_allowed_triggers(self):
|
||||
in_repo_conf = textwrap.dedent(
|
||||
"""
|
||||
- pipeline:
|
||||
name: test
|
||||
manager: independent
|
||||
trigger:
|
||||
github:
|
||||
- event: pull_request
|
||||
""")
|
||||
file_dict = {'zuul.d/test.yaml': in_repo_conf}
|
||||
A = self.fake_gerrit.addFakeChange(
|
||||
'tenant-two-config', 'master', 'A', files=file_dict)
|
||||
self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
|
||||
self.waitUntilSettled()
|
||||
self.assertIn(
|
||||
'Unknown connection named "github"', A.messages[0],
|
||||
"A should fail because of allowed-trigger")
|
||||
|
||||
B = self.fake_gerrit.addFakeChange(
|
||||
'tenant-one-config', 'master', 'A', files=file_dict)
|
||||
self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
|
||||
self.waitUntilSettled()
|
||||
self.assertNotIn(
|
||||
'Unknown connection named "github"', B.messages[0],
|
||||
"B should not fail because of allowed-trigger")
|
||||
|
||||
def test_allowed_reporters(self):
|
||||
in_repo_conf = textwrap.dedent(
|
||||
"""
|
||||
- pipeline:
|
||||
name: test
|
||||
manager: independent
|
||||
success:
|
||||
outgoing_smtp:
|
||||
to: you@example.com
|
||||
""")
|
||||
file_dict = {'zuul.d/test.yaml': in_repo_conf}
|
||||
A = self.fake_gerrit.addFakeChange(
|
||||
'tenant-one-config', 'master', 'A', files=file_dict)
|
||||
self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
|
||||
self.waitUntilSettled()
|
||||
self.assertIn(
|
||||
'Unknown connection named "outgoing_smtp"', A.messages[0],
|
||||
"A should fail because of allowed-reporters")
|
||||
|
||||
B = self.fake_gerrit.addFakeChange(
|
||||
'tenant-two-config', 'master', 'A', files=file_dict)
|
||||
self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
|
||||
self.waitUntilSettled()
|
||||
self.assertNotIn(
|
||||
'Unknown connection named "outgoing_smtp"', B.messages[0],
|
||||
"B should not fail because of allowed-reporters")
|
||||
|
||||
|
||||
class TestPragma(ZuulTestCase):
|
||||
tenant_config_file = 'config/pragma/main.yaml'
|
||||
|
||||
|
@ -71,6 +71,14 @@ class DuplicateNodeError(Exception):
|
||||
super(DuplicateNodeError, self).__init__(message)
|
||||
|
||||
|
||||
class UnknownConnection(Exception):
|
||||
def __init__(self, connection_name):
|
||||
message = textwrap.dedent("""\
|
||||
Unknown connection named "{connection}".""")
|
||||
message = textwrap.fill(message.format(connection=connection_name))
|
||||
super(UnknownConnection, self).__init__(message)
|
||||
|
||||
|
||||
class MaxTimeoutError(Exception):
|
||||
def __init__(self, job, tenant):
|
||||
message = textwrap.dedent("""\
|
||||
@ -1085,9 +1093,13 @@ class PipelineParser(object):
|
||||
|
||||
for conf_key, action in self.reporter_actions.items():
|
||||
reporter_set = []
|
||||
allowed_reporters = self.pcontext.tenant.allowed_reporters
|
||||
if conf.get(conf_key):
|
||||
for reporter_name, params \
|
||||
in conf.get(conf_key).items():
|
||||
if allowed_reporters is not None and \
|
||||
reporter_name not in allowed_reporters:
|
||||
raise UnknownConnection(reporter_name)
|
||||
reporter = self.pcontext.connections.getReporter(
|
||||
reporter_name, pipeline, params)
|
||||
reporter.setAction(conf_key)
|
||||
@ -1136,6 +1148,9 @@ class PipelineParser(object):
|
||||
source.getRejectFilters(reject_config))
|
||||
|
||||
for trigger_name, trigger_config in conf.get('trigger').items():
|
||||
if self.pcontext.tenant.allowed_triggers is not None and \
|
||||
trigger_name not in self.pcontext.tenant.allowed_triggers:
|
||||
raise UnknownConnection(trigger_name)
|
||||
trigger = self.pcontext.connections.getTrigger(
|
||||
trigger_name, trigger_config)
|
||||
pipeline.triggers.append(trigger)
|
||||
@ -1265,6 +1280,8 @@ class TenantParser(object):
|
||||
'max-job-timeout': int,
|
||||
'source': self.validateTenantSources(),
|
||||
'exclude-unprotected-branches': bool,
|
||||
'allowed-triggers': to_list(str),
|
||||
'allowed-reporters': to_list(str),
|
||||
'default-parent': str,
|
||||
}
|
||||
return vs.Schema(tenant)
|
||||
@ -1279,6 +1296,8 @@ class TenantParser(object):
|
||||
if conf.get('exclude-unprotected-branches') is not None:
|
||||
tenant.exclude_unprotected_branches = \
|
||||
conf['exclude-unprotected-branches']
|
||||
tenant.allowed_triggers = conf.get('allowed-triggers')
|
||||
tenant.allowed_reporters = conf.get('allowed-reporters')
|
||||
tenant.default_base_job = conf.get('default-parent', 'base')
|
||||
|
||||
tenant.unparsed_config = conf
|
||||
@ -1736,7 +1755,9 @@ class TenantParser(object):
|
||||
# reference_exceptions has it; add tests if needed.
|
||||
if not skip_pipelines:
|
||||
for pipeline in parsed_config.pipelines:
|
||||
layout.addPipeline(pipeline)
|
||||
with reference_exceptions(
|
||||
'pipeline', pipeline, layout.loading_errors):
|
||||
layout.addPipeline(pipeline)
|
||||
|
||||
for nodeset in parsed_config.nodesets:
|
||||
with reference_exceptions(
|
||||
|
Loading…
x
Reference in New Issue
Block a user