summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLars Wirzenius <liw@liw.fi>2017-11-26 16:41:33 +0100
committerLars Wirzenius <liw@liw.fi>2017-11-26 17:59:59 +0100
commit964e646b2c26bcb007390dc6af625835f98887ec (patch)
treeae7ea88c5894ad71167959ed82d81b984f78b5e7
parentf0ccb8150a67b10e11b3358d6385e31619e6d1e3 (diff)
downloadick2-964e646b2c26bcb007390dc6af625835f98887ec.tar.gz
Update: project and work apis to handle named pipelines
-rw-r--r--ick2/projectapi.py58
-rw-r--r--ick2/projectapi_tests.py56
-rw-r--r--ick2/workapi.py37
-rw-r--r--ick2/workapi_tests.py25
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)