From b87027a3c7d3bc88e2674c9e22c8745c9dbf1043 Mon Sep 17 00:00:00 2001 From: Lars Wirzenius Date: Sat, 20 Jul 2019 17:18:23 +0300 Subject: Add: MuckStore --- ick2/__init__.py | 2 ++ ick2/apibase.py | 3 +- ick2/exceptions.py | 6 ++++ ick2/store.py | 83 +++++++++++++++++++++++++++++++++++++++++++ yarns/100-projects.yarn | 1 + yarns/150-pipelines.yarn | 1 + yarns/300-workers.yarn | 1 + yarns/400-build.yarn | 3 ++ yarns/500-build-fail.yarn | 1 + yarns/600-unauthz.yarn | 1 + yarns/700-artifact-store.yarn | 1 + 11 files changed, 102 insertions(+), 1 deletion(-) diff --git a/ick2/__init__.py b/ick2/__init__.py index 2720d61..235ee96 100644 --- a/ick2/__init__.py +++ b/ick2/__init__.py @@ -17,6 +17,7 @@ from .version import __version__, __version_info__ from .logging import setup_logging, log from .store import ( MemoryStore, + MuckStore, ) from .resource import ( Resource, @@ -51,6 +52,7 @@ from .exceptions import ( NotFound, ExistsAlready, Conflict, + StoreError, IckException, MethodNotAllowed, ClientIdMissing, diff --git a/ick2/apibase.py b/ick2/apibase.py index 3827f6e..46c17cf 100644 --- a/ick2/apibase.py +++ b/ick2/apibase.py @@ -23,7 +23,8 @@ class APIbase: def __init__(self, state): assert (state is None or - isinstance(state, ick2.MemoryStore)) + isinstance(state, ick2.MemoryStore) or + isinstance(state, ick2.MuckStore)) self._trans = ick2.TransactionalState(state) def get_routes(self, path): diff --git a/ick2/exceptions.py b/ick2/exceptions.py index bd394af..8467e7a 100644 --- a/ick2/exceptions.py +++ b/ick2/exceptions.py @@ -40,6 +40,12 @@ class Conflict(IckException): rid, expected, got)) +class StoreError(IckException): + + def __init__(self, msg): + super().__init__('Error accessing persistent store: {}'.format(msg)) + + class BadUpdate(IckException): def __init__(self, how): diff --git a/ick2/store.py b/ick2/store.py index 5c01f89..83a008b 100644 --- a/ick2/store.py +++ b/ick2/store.py @@ -15,9 +15,13 @@ import copy +import json import uuid +import requests + + import ick2 @@ -75,3 +79,82 @@ class MemoryStore(StoreInterface): def delete(self, token, rid): del self._objs[rid] + + +class MuckStore(StoreInterface): # pragma: no cover + + def __init__(self, muck_url): + self._url = muck_url + ick2.log.log('info', msg_text='MuckStore created', muck_url=muck_url) + + def _request(self, func, path, token, headers=None, body=None): + url = '{}{}'.format(self._url, path) + if headers is None: + headers = {} + headers['Authorization'] = 'Bearer {}'.format(token) + r = func(url, headers=headers, data=body) + ick2.log.log( + 'trace', msg_text='Accessing Muck', + func=repr(func), url=url, path=path, headers=headers, data=body, + status=r.status_code, text=r.text) + if not r.ok: + raise ick2.StoreError(r.text) + return r + + def search(self, token, cond): + headers = { + 'Content-Type': 'application/json', + } + cond = { + 'cond': [ + { + 'where': 'meta', + 'field': 'id', + 'op': '>=', + 'pattern': '', + } + ], + } + body = json.dumps(cond) + r = self._request( + requests.get, '/search', token, headers=headers, body=body) + obj = r.json() + return obj['resources'] + + def create(self, token, obj): + headers = { + 'Content-Type': 'application/json', + } + body = json.dumps(obj) + r = self._request( + requests.post, '/res', token, headers=headers, body=body) + rid = r.headers['Muck-Id'] + rev = r.headers['Muck-Revision'] + return rid, rev + + def show(self, token, rid): + headers = { + 'Muck-Id': rid, + } + r = self._request(requests.get, '/res', token, headers=headers) + rev = r.headers['Muck-Revision'] + as_dict = r.json() + return as_dict, rev + + def update(self, token, rid, obj, revision): + headers = { + 'Content-Type': 'application/json', + 'Muck-Id': rid, + 'Muck-Revision': revision, + } + body = json.dumps(obj) + r = self._request( + requests.put, '/res', token, headers=headers, body=body) + rev = r.headers['Muck-Revision'] + return rev + + def delete(self, token, rid): + headers = { + 'Muck-Id': rid, + } + self._request(requests.delete, '/res', token, headers=headers) diff --git a/yarns/100-projects.yarn b/yarns/100-projects.yarn index 4c5291f..3c4edbc 100644 --- a/yarns/100-projects.yarn +++ b/yarns/100-projects.yarn @@ -53,6 +53,7 @@ building them. We start by starting an instance of the controller. ... uapi_projects_id_get ... uapi_projects_id_put ... uapi_projects_id_delete + ... create update show delete AND a running ick controller WHEN user makes request GET /projects diff --git a/yarns/150-pipelines.yarn b/yarns/150-pipelines.yarn index 6a303eb..7b3a339 100644 --- a/yarns/150-pipelines.yarn +++ b/yarns/150-pipelines.yarn @@ -64,6 +64,7 @@ running them. We start by starting an instance of the controller. ... uapi_pipelines_id_get ... uapi_pipelines_id_put ... uapi_pipelines_id_delete + ... create update show delete AND a running ick controller WHEN user makes request GET /pipelines diff --git a/yarns/300-workers.yarn b/yarns/300-workers.yarn index cea6c81..2375a31 100644 --- a/yarns/300-workers.yarn +++ b/yarns/300-workers.yarn @@ -57,6 +57,7 @@ controller API. It doesn't actually talk to the worker itself. ... uapi_workers_id_get ... uapi_workers_id_put ... uapi_workers_id_delete + ... create update show delete AND an access token for obelix with scopes ... uapi_workers_post AND a running ick controller diff --git a/yarns/400-build.yarn b/yarns/400-build.yarn index 13eefce..08eb8f9 100644 --- a/yarns/400-build.yarn +++ b/yarns/400-build.yarn @@ -43,6 +43,7 @@ Set up the controller. ... uapi_logs_get ... uapi_logs_id_delete ... uapi_logs_id_get + ... create update show delete AND a running ick controller Add up a project with some named pipelines. @@ -886,6 +887,7 @@ Set up the controller. ... uapi_logs_get ... uapi_logs_id_delete ... uapi_logs_id_get + ... create update show delete AND a running ick controller Add a couple of projects. @@ -1119,6 +1121,7 @@ Set up the controller. ... uapi_logs_get ... uapi_logs_id_delete ... uapi_logs_id_get + ... create update show delete AND a running ick controller Add a couple of projects. diff --git a/yarns/500-build-fail.yarn b/yarns/500-build-fail.yarn index 6ca06c6..08592a7 100644 --- a/yarns/500-build-fail.yarn +++ b/yarns/500-build-fail.yarn @@ -45,6 +45,7 @@ Set up the controller. ... uapi_logs_get ... uapi_logs_id_delete ... uapi_logs_id_get + ... create update show delete AND a running ick controller Add up a project and its pipelines. diff --git a/yarns/600-unauthz.yarn b/yarns/600-unauthz.yarn index ab33404..cca142e 100644 --- a/yarns/600-unauthz.yarn +++ b/yarns/600-unauthz.yarn @@ -37,6 +37,7 @@ Set up the controller. ... uapi_builds_get ... uapi_builds_id_get ... uapi_logs_id_get + ... create update show delete AND a running ick controller WHEN user makes request POST /projects with a valid token and body diff --git a/yarns/700-artifact-store.yarn b/yarns/700-artifact-store.yarn index cadc83c..e562957 100644 --- a/yarns/700-artifact-store.yarn +++ b/yarns/700-artifact-store.yarn @@ -31,6 +31,7 @@ Set up the artifact store. ... uapi_blobs_id_delete ... uapi_blobs_id_put ... uapi_blobs_id_get + ... create update show delete AND a running ick controller