diff options
author | Lars Wirzenius <liw@liw.fi> | 2017-11-26 16:41:33 +0100 |
---|---|---|
committer | Lars Wirzenius <liw@liw.fi> | 2017-11-26 17:59:59 +0100 |
commit | 964e646b2c26bcb007390dc6af625835f98887ec (patch) | |
tree | ae7ea88c5894ad71167959ed82d81b984f78b5e7 | |
parent | f0ccb8150a67b10e11b3358d6385e31619e6d1e3 (diff) | |
download | ick2-964e646b2c26bcb007390dc6af625835f98887ec.tar.gz |
Update: project and work apis to handle named pipelines
-rw-r--r-- | ick2/projectapi.py | 58 | ||||
-rw-r--r-- | ick2/projectapi_tests.py | 56 | ||||
-rw-r--r-- | ick2/workapi.py | 37 | ||||
-rw-r--r-- | ick2/workapi_tests.py | 25 |
4 files changed, 115 insertions, 61 deletions
diff --git a/ick2/projectapi.py b/ick2/projectapi.py index b0c9da1..f46fe14 100644 --- a/ick2/projectapi.py +++ b/ick2/projectapi.py @@ -50,33 +50,59 @@ class ProjectAPI(ick2.ResourceApiBase): def get_pipeline(self, project, pipeline, **kwargs): p = self._state.get_resource(self._type_name, project) - for pl in p['pipelines']: - if pl['name'] == pipeline: - return { - 'status': pl.get('status', 'idle'), - } - raise ick2.NotFound() + if pipeline not in p['pipelines']: + raise ick2.NotFound() + + pp = self._pipeline_instance_name(project, pipeline) + try: + pl = self._state.get_resource('pipeline_instances', pp) + except ick2.NotFound: + pl = {} + return { + 'status': pl.get('status', 'idle'), + } + + def _pipeline_instance_name(self, project_name, pipeline_name): + return '{} {}'.format(project_name, pipeline_name) def set_pipeline_callback( self, body, project, pipeline, **kwargs): # pragma: no cover return self.set_pipeline(body['status'], project, pipeline) - def set_pipeline(self, state, project, pipeline): + def set_pipeline(self, status, project, pipeline): + ick2.log.log( + 'trace', msg_text='Setting pipeline status', + project=project, pipeline=pipeline, status=status) + allowed_changes = { 'idle': 'triggered', 'triggered': 'building', 'building': 'idle', } + p = self._state.get_resource(self._type_name, project) - for pl in p['pipelines']: - if pl['name'] == pipeline: - old_state = pl.get('status', 'idle') - if allowed_changes[old_state] != state: - raise ick2.WrongPipelineStatus(state) - pl['status'] = state - self._state.update_resource(self._type_name, project, p) - return {'status': state} - raise ick2.NotFound() + if pipeline not in p['pipelines']: + ick2.log.log( + 'error', msg_text='Project not found', project=project) + raise ick2.NotFound() + ick2.log.log('trace', msg_text='Found project', project=p) + + pp = self._pipeline_instance_name(project, pipeline) + try: + pl = self._state.get_resource('pipeline_instances', pp) + except ick2.NotFound: + pl = { + 'name': pipeline, + 'status': 'idle', + } + self._state.add_resource('pipeline_instances', pp, pl) + + old_status = pl.get('status', 'idle') + if allowed_changes[old_status] != status: + raise ick2.WrongPipelineStatus(status) + pl['status'] = status + self._state.update_resource('pipeline_instances', pp, pl) + return {'status': status} # This needs to go away as it is not protected. Once an IDP is # added. diff --git a/ick2/projectapi_tests.py b/ick2/projectapi_tests.py index ae5190e..4e55ccf 100644 --- a/ick2/projectapi_tests.py +++ b/ick2/projectapi_tests.py @@ -36,28 +36,32 @@ class ProjectAPITests(unittest.TestCase): def create_api(self): return ick2.ProjectAPI(self.state) + def create_pipeline_api(self): + return ick2.PipelineAPI(self.state) + def test_has_not_projects_initially(self): api = self.create_api() self.assertEqual(api.list(), {'projects': []}) def test_creates_project(self): + pipeline = { + 'name': 'build', + 'actions': [ + {'shell': 'step-1'}, + ], + } + pipeapi = self.create_pipeline_api() + pipeapi.create(pipeline) + project = { 'project': 'foo', - 'pipelines': [ - { - 'name': 'build', - 'actions': [ - { - 'shell': 'step-1', - }, - ], - }, - ], + 'pipelines': ['build'], 'parameters': { 'foo': 'bar', } } api = self.create_api() + self.assertEqual(api.create(project), project) self.assertEqual(api.list(), {'projects': [project]}) self.assertEqual(api.get_pipeline('foo', 'build'), {'status': 'idle'}) @@ -85,7 +89,7 @@ class ProjectAPITests(unittest.TestCase): def test_loads_projects_from_state_directory(self): project = { 'project': 'foo', - 'shell_steps': ['build'], + 'pipelines': ['build'], } api = self.create_api() api.create(project) @@ -96,7 +100,7 @@ class ProjectAPITests(unittest.TestCase): def test_gets_named_project(self): project = { 'project': 'foo', - 'shell_steps': ['build'], + 'pipelines': ['build'], } api = self.create_api() api.create(project) @@ -105,7 +109,7 @@ class ProjectAPITests(unittest.TestCase): def test_updates_named_project(self): project_v1 = { 'project': 'foo', - 'shell_steps': ['build'], + 'pipelines': ['build'], } project_v2 = dict(project_v1) project_v2['shell_steps'] = ['build it using magic'] @@ -118,7 +122,7 @@ class ProjectAPITests(unittest.TestCase): def test_deletes_named_project(self): project = { 'project': 'foo', - 'shell_steps': ['build'], + 'pipelines': ['build'], } api = self.create_api() api.create(project) @@ -133,27 +137,29 @@ class ProjectAPITests(unittest.TestCase): api.delete('foo') def test_updates_pipeline_status(self): + pipeline = { + 'name': 'build', + 'actions': [ + {'shell': 'step-1'}, + ], + } + pipeapi = self.create_pipeline_api() + pipeapi.create(pipeline) + project = { 'project': 'foo', - 'pipelines': [ - { - 'name': 'build', - 'actions': [ - { - 'shell': 'step-1', - }, - ], - }, - ], + 'pipelines': ['build'], } api = self.create_api() api.create(project) self.assertEqual(api.get_pipeline('foo', 'build'), {'status': 'idle'}) + self.assertEqual(pipeapi.show('build'), pipeline) with self.assertRaises(ick2.WrongPipelineStatus): api.set_pipeline('building', 'foo', 'build') api.set_pipeline('triggered', 'foo', 'build') + self.assertEqual(pipeapi.show('build'), pipeline) self.assertEqual( api.get_pipeline('foo', 'build'), {'status': 'triggered'} @@ -163,6 +169,7 @@ class ProjectAPITests(unittest.TestCase): api.set_pipeline('idle', 'foo', 'build') api.set_pipeline('building', 'foo', 'build') + self.assertEqual(pipeapi.show('build'), pipeline) self.assertEqual( api.get_pipeline('foo', 'build'), {'status': 'building'} @@ -172,6 +179,7 @@ class ProjectAPITests(unittest.TestCase): api.set_pipeline('triggered', 'foo', 'build') api.set_pipeline('idle', 'foo', 'build') + self.assertEqual(pipeapi.show('build'), pipeline) self.assertEqual( api.get_pipeline('foo', 'build'), {'status': 'idle'} diff --git a/ick2/workapi.py b/ick2/workapi.py index 5935fe9..f84e355 100644 --- a/ick2/workapi.py +++ b/ick2/workapi.py @@ -46,7 +46,7 @@ class WorkAPI(ick2.APIbase): doing = {} else: pipeline['status'] = 'building' - self._projects.update_project(project) + self._update_pipeline(project, pipeline) build_id = project.get('build_id', 0) + 1 project['build_id'] = build_id @@ -78,11 +78,30 @@ class WorkAPI(ick2.APIbase): def _pick_triggered_pipeline(self): projects = self._projects.get_projects() for project in projects: - for pipeline in project['pipelines']: - if pipeline.get('status') == 'triggered': - return project, pipeline + for name in project['pipelines']: + pp = self._pipeline_instance_name(project['project'], name) + try: + pl = self._state.get_resource('pipeline_instances', pp) + except ick2.NotFound: + pass + else: + if pl.get('status') == 'triggered': + pt = self._state.get_resource('pipelines', name) + return project, pt return None, None + def _pipeline_instance_name(self, project_name, pipeline_name): + return '{} {}'.format(project_name, pipeline_name) + + def _update_pipeline(self, project, pipeline): + pp = self._pipeline_instance_name(project['project'], pipeline['name']) + try: + self._state.get_resource('pipeline_instances', pp) + except ick2.NotFound: # pragma: no cover + self._state.add_resource('pipeline_instances', pp, pipeline) + else: + self._state.update_resource('pipeline_instances', pp, pipeline) + def _start_build(self, project, pipeline, worker, build_id): ick2.log.log('info', msg_text='Starting new build', build_id=build_id) build = { @@ -136,6 +155,7 @@ class WorkAPI(ick2.APIbase): doing['step_index'] = index doing['step'] = actions[index] self._projects.update_project(project) + self._update_pipeline(project, pipeline) worker_state = { 'worker': update['worker'], @@ -146,7 +166,7 @@ class WorkAPI(ick2.APIbase): assert isinstance(exit_code, int) assert exit_code != 0 pipeline['status'] = 'idle' - self._projects.update_project(project) + self._update_pipeline(project, pipeline) self._finish_build(update) worker_state = { @@ -168,9 +188,10 @@ class WorkAPI(ick2.APIbase): def _get_pipeline(self, project, pipeline): # pragma: no cover projects = self._projects.get_projects() for p in projects: - for pl in p['pipelines']: - if pl.get('name') == pipeline: - return p, pl + for name in p['pipelines']: + if name == pipeline: + pt = self._state.get_resource('pipelines', name) + return p, pt raise ick2.NotFound() def _append_to_build_log(self, update): diff --git a/ick2/workapi_tests.py b/ick2/workapi_tests.py index f657687..c855895 100644 --- a/ick2/workapi_tests.py +++ b/ick2/workapi_tests.py @@ -34,24 +34,23 @@ class WorkAPITests(unittest.TestCase): shutil.rmtree(self.tempdir) def create_project_api(self): + pipeline = { + 'name': 'build', + 'actions': [ + {'shell': 'step-1'}, + {'shell': 'step-2'}, + ], + } + + pipeapi = ick2.PipelineAPI(self.state) + pipeapi.create(pipeline) + project = { 'project': 'foo', 'parameters': { 'foo': 'bar', }, - 'pipelines': [ - { - 'name': 'build', - 'actions': [ - { - 'shell': 'step-1', - }, - { - 'shell': 'step-2', - }, - ], - }, - ], + 'pipelines': ['build'], } api = ick2.ProjectAPI(self.state) api.create(project) |