From 4e94f6174a0aa983ee304598002a325c07bf6230 Mon Sep 17 00:00:00 2001 From: Ricardo Carrillo Cruz Date: Mon, 25 Jul 2016 16:11:56 +0000 Subject: [PATCH] Add initial support for jobs authentication config Change-Id: I6da03f7092bf9667d30b2fe2abbb2268bc0f4c58 --- tests/test_model.py | 75 +++++++++++++++++++++++++++++++++++++++++ zuul/configloader.py | 32 +++++++++++------- zuul/launcher/client.py | 2 +- zuul/model.py | 8 +++-- 4 files changed, 101 insertions(+), 16 deletions(-) diff --git a/tests/test_model.py b/tests/test_model.py index 99cc57f913..fa670a4a8a 100644 --- a/tests/test_model.py +++ b/tests/test_model.py @@ -120,6 +120,81 @@ class TestJob(BaseTestCase): self.assertEqual(job.name, 'python27') self.assertEqual(job.timeout, 50) + def test_job_auth_inheritance(self): + layout = model.Layout() + project = model.Project('project') + + base = configloader.JobParser.fromYaml(layout, { + '_source_project': project, + 'name': 'base', + 'timeout': 30, + }) + layout.addJob(base) + pypi_upload_without_inherit = configloader.JobParser.fromYaml(layout, { + '_source_project': project, + 'name': 'pypi-upload-without-inherit', + 'parent': 'base', + 'timeout': 40, + 'auth': { + 'password': { + 'pypipassword': 'dummypassword' + } + } + }) + layout.addJob(pypi_upload_without_inherit) + pypi_upload_with_inherit = configloader.JobParser.fromYaml(layout, { + '_source_project': project, + 'name': 'pypi-upload-with-inherit', + 'parent': 'base', + 'timeout': 40, + 'auth': { + 'inherit': True, + 'password': { + 'pypipassword': 'dummypassword' + } + } + }) + layout.addJob(pypi_upload_with_inherit) + pypi_upload_with_inherit_false = configloader.JobParser.fromYaml( + layout, { + '_source_project': project, + 'name': 'pypi-upload-with-inherit-false', + 'parent': 'base', + 'timeout': 40, + 'auth': { + 'inherit': False, + 'password': { + 'pypipassword': 'dummypassword' + } + } + }) + layout.addJob(pypi_upload_with_inherit_false) + in_repo_job_without_inherit = configloader.JobParser.fromYaml(layout, { + '_source_project': project, + 'name': 'in-repo-job-without-inherit', + 'parent': 'pypi-upload-without-inherit', + }) + layout.addJob(in_repo_job_without_inherit) + in_repo_job_with_inherit = configloader.JobParser.fromYaml(layout, { + '_source_project': project, + 'name': 'in-repo-job-with-inherit', + 'parent': 'pypi-upload-with-inherit', + }) + layout.addJob(in_repo_job_with_inherit) + in_repo_job_with_inherit_false = configloader.JobParser.fromYaml( + layout, { + '_source_project': project, + 'name': 'in-repo-job-with-inherit-false', + 'parent': 'pypi-upload-with-inherit-false', + }) + layout.addJob(in_repo_job_with_inherit_false) + + self.assertNotIn('auth', in_repo_job_without_inherit.auth) + self.assertIn('password', in_repo_job_with_inherit.auth) + self.assertEquals(in_repo_job_with_inherit.auth['password'], + {'pypipassword': 'dummypassword'}) + self.assertNotIn('auth', in_repo_job_with_inherit_false.auth) + def test_job_inheritance_job_tree(self): layout = model.Layout() diff --git a/zuul/configloader.py b/zuul/configloader.py index 70a880df0c..65ec8033c7 100644 --- a/zuul/configloader.py +++ b/zuul/configloader.py @@ -40,17 +40,23 @@ def as_list(item): class JobParser(object): @staticmethod def getSchema(): - # TODOv3(jeblair, jhesketh): move to auth - swift = {vs.Required('name'): str, - 'container': str, - 'expiry': int, - 'max_file_size': int, - 'max-file-size': int, - 'max_file_count': int, - 'max-file-count': int, - 'logserver_prefix': str, - 'logserver-prefix': str, - } + swift_tmpurl = {vs.Required('name'): str, + 'container': str, + 'expiry': int, + 'max_file_size': int, + 'max-file-size': int, + 'max_file_count': int, + 'max-file-count': int, + 'logserver_prefix': str, + 'logserver-prefix': str, + } + + password = {str: str} + + auth = {'password': to_list(password), + 'inherit': bool, + 'swift-tmpurl': to_list(swift_tmpurl), + } node = {vs.Required('name'): str, vs.Required('image'): str, @@ -68,7 +74,7 @@ class JobParser(object): 'tags': to_list(str), 'branches': to_list(str), 'files': to_list(str), - 'swift': to_list(swift), + 'auth': to_list(auth), 'irrelevant-files': to_list(str), 'nodes': [node], 'timeout': int, @@ -81,6 +87,8 @@ class JobParser(object): def fromYaml(layout, conf): JobParser.getSchema()(conf) job = model.Job(conf['name']) + if 'auth' in conf: + job.auth = conf.get('auth') if 'parent' in conf: parent = layout.getJob(conf['parent']) job.inheritFrom(parent) diff --git a/zuul/launcher/client.py b/zuul/launcher/client.py index 8448422355..07a5e38fd5 100644 --- a/zuul/launcher/client.py +++ b/zuul/launcher/client.py @@ -259,7 +259,7 @@ class LaunchClient(object): # NOTE(jhesketh): The params need to stay in a key=value data pair # as workers cannot necessarily handle lists. - if job.swift and self.swift.connection: + if 'swift' in job.auth and self.swift.connection: for name, s in job.swift.items(): swift_instructions = {} diff --git a/zuul/model.py b/zuul/model.py index fd2f626bba..b85c80d42e 100644 --- a/zuul/model.py +++ b/zuul/model.py @@ -502,7 +502,7 @@ class Job(object): timeout=None, # variables={}, nodes=[], - # auth={}, + auth={}, workspace=None, pre_run=None, post_run=None, @@ -516,7 +516,6 @@ class Job(object): branch_matcher=None, file_matcher=None, irrelevant_file_matcher=None, # skip-if - swift=None, # TODOv3(jeblair): move to auth parameter_function=None, # TODOv3(jeblair): remove success_pattern=None, # TODOv3(jeblair): remove tags=set(), @@ -555,8 +554,11 @@ class Job(object): if not isinstance(other, Job): raise Exception("Job unable to inherit from %s" % (other,)) for k, v in self.attributes.items(): - if getattr(other, k) != v: + if getattr(other, k) != v and k != 'auth': setattr(self, k, getattr(other, k)) + # Inherit auth only if explicitly allowed + if other.auth and 'inherit' in other.auth and other.auth['inherit']: + setattr(self, 'auth', getattr(other, 'auth')) def changeMatches(self, change): if self.branch_matcher and not self.branch_matcher.matches(change):