Merge "Add max-job-timeout tenant setting" into feature/zuulv3

This commit is contained in:
Zuul 2017-09-12 18:53:06 +00:00 committed by Gerrit Code Review
commit eaec061367
5 changed files with 50 additions and 1 deletions

View File

@ -163,6 +163,11 @@ configuration. An example tenant definition is:
The maximum number of nodes a job can request. A value of
'-1' value removes the limit.
.. attr:: max-job-timeout
:default: 10800
The maximum timeout for jobs. A value of '-1' value removes the limit.
.. attr:: exclude-unprotected-branches
:default: false

View File

@ -1,5 +1,6 @@
- tenant:
name: tenant-one
max-job-timeout: 1800
source:
gerrit:
config-projects:

View File

@ -1402,7 +1402,7 @@ class TestDiskAccounting(AnsibleZuulTestCase):
class TestMaxNodesPerJob(AnsibleZuulTestCase):
tenant_config_file = 'config/multi-tenant/main.yaml'
def test_max_nodes_reached(self):
def test_max_timeout_exceeded(self):
in_repo_conf = textwrap.dedent(
"""
- job:
@ -1437,6 +1437,32 @@ class TestMaxNodesPerJob(AnsibleZuulTestCase):
"B should not fail because of nodes limit")
class TestMaxTimeout(AnsibleZuulTestCase):
tenant_config_file = 'config/multi-tenant/main.yaml'
def test_max_nodes_reached(self):
in_repo_conf = textwrap.dedent(
"""
- job:
name: test-job
timeout: 3600
""")
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.assertIn('The job "test-job" exceeds tenant max-job-timeout',
A.messages[0], "A should fail because of timeout limit")
B = self.fake_gerrit.addFakeChange('org/project2', 'master', 'A',
files=file_dict)
self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
self.waitUntilSettled()
self.assertNotIn("exceeds tenant max-job-timeout", B.messages[0],
"B should not fail because of timeout limit")
class TestBaseJobs(ZuulTestCase):
tenant_config_file = 'config/base-jobs/main.yaml'

View File

@ -76,6 +76,15 @@ class MaxNodeError(Exception):
super(MaxNodeError, self).__init__(message)
class MaxTimeoutError(Exception):
def __init__(self, job, tenant):
message = textwrap.dedent("""\
The job "{job}" exceeds tenant max-job-timeout {maxtimeout}.""")
message = textwrap.fill(message.format(
job=job.name, maxtimeout=tenant.max_job_timeout))
super(MaxTimeoutError, self).__init__(message)
class DuplicateGroupError(Exception):
def __init__(self, nodeset, group):
message = textwrap.dedent("""\
@ -505,6 +514,10 @@ class JobParser(object):
if secrets and not conf['_source_context'].trusted:
job.post_review = True
if conf.get('timeout') and tenant.max_job_timeout != -1 and \
int(conf['timeout']) > tenant.max_job_timeout:
raise MaxTimeoutError(job, tenant)
if 'post-review' in conf:
if conf['post-review']:
job.post_review = True
@ -1059,6 +1072,7 @@ class TenantParser(object):
def getSchema(connections=None):
tenant = {vs.Required('name'): str,
'max-nodes-per-job': int,
'max-job-timeout': int,
'source': TenantParser.validateTenantSources(connections),
'exclude-unprotected-branches': bool,
'default-parent': str,
@ -1072,6 +1086,8 @@ class TenantParser(object):
tenant = model.Tenant(conf['name'])
if conf.get('max-nodes-per-job') is not None:
tenant.max_nodes_per_job = conf['max-nodes-per-job']
if conf.get('max-job-timeout') is not None:
tenant.max_job_timeout = int(conf['max-job-timeout'])
if conf.get('exclude-unprotected-branches') is not None:
tenant.exclude_unprotected_branches = \
conf['exclude-unprotected-branches']

View File

@ -2506,6 +2506,7 @@ class Tenant(object):
def __init__(self, name):
self.name = name
self.max_nodes_per_job = 5
self.max_job_timeout = 10800
self.exclude_unprotected_branches = False
self.default_base_job = None
self.layout = None