From a8998d36123d92f007aad8e216cddf73cef7e80d Mon Sep 17 00:00:00 2001 From: Qixiang Wan Date: Jul 10 2017 06:16:45 +0000 Subject: Add APIs for querying event types, build types and build states --- diff --git a/freshmaker/api_utils.py b/freshmaker/api_utils.py index 733c783..58278c0 100644 --- a/freshmaker/api_utils.py +++ b/freshmaker/api_utils.py @@ -19,7 +19,7 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. -from flask import request, url_for +from flask import request, url_for, jsonify from freshmaker import db from freshmaker.types import ArtifactType, ArtifactBuildState @@ -131,3 +131,11 @@ def filter_events(flask_request): page = flask_request.args.get('page', 1, type=int) per_page = flask_request.args.get('per_page', 10, type=int) return query.paginate(page, per_page, False) + + +def json_error(status, error, message): + response = jsonify({'status': status, + 'error': error, + 'message': message}) + response.status_code = status + return response diff --git a/freshmaker/views.py b/freshmaker/views.py index bbb882d..17a5c24 100644 --- a/freshmaker/views.py +++ b/freshmaker/views.py @@ -21,14 +21,64 @@ # # Written by Jan Kaluza +import six from flask import request, jsonify from flask.views import MethodView from freshmaker import app +from freshmaker import types from freshmaker import models -from freshmaker.api_utils import pagination_metadata, filter_artifact_builds, filter_events +from freshmaker.api_utils import pagination_metadata +from freshmaker.api_utils import filter_artifact_builds +from freshmaker.api_utils import filter_events +from freshmaker.api_utils import json_error api_v1 = { + 'event_types': { + 'event_types_list': { + 'url': '/freshmaker/1/event-types/', + 'options': { + 'defaults': {'id': None}, + 'methods': ['GET'], + } + }, + 'event_type': { + 'url': '/freshmaker/1/event-types/', + 'options': { + 'methods': ['GET'], + } + }, + }, + 'build_types': { + 'build_types_list': { + 'url': '/freshmaker/1/build-types/', + 'options': { + 'defaults': {'id': None}, + 'methods': ['GET'], + } + }, + 'build_type': { + 'url': '/freshmaker/1/build-types/', + 'options': { + 'methods': ['GET'], + } + }, + }, + 'build_states': { + 'build_states_list': { + 'url': '/freshmaker/1/build-states/', + 'options': { + 'defaults': {'id': None}, + 'methods': ['GET'], + } + }, + 'build_state': { + 'url': '/freshmaker/1/build-states/', + 'options': { + 'methods': ['GET'], + } + }, + }, 'events': { 'events_list': { 'url': '/freshmaker/1/events/', @@ -62,8 +112,70 @@ api_v1 = { } -class EventAPI(MethodView): +class EventTypeAPI(MethodView): + def get(self, id): + event_types = [] + for cls, val in six.iteritems(models.EVENT_TYPES): + event_types.append({'name': cls.__name__, 'id': val}) + if id is None: + json_data = {} + json_data['items'] = event_types + + return jsonify(json_data), 200 + + else: + event_type = [x for x in event_types if x['id'] == id] + + if event_type: + return jsonify(event_type.pop()), 200 + else: + return json_error(404, "Not Found", "No such event type found.") + + +class BuildTypeAPI(MethodView): + def get(self, id): + build_types = [] + for x in list(types.ArtifactType): + build_types.append({'name': x.name, 'id': x.value}) + + if id is None: + json_data = {} + json_data['items'] = build_types + + return jsonify(json_data), 200 + + else: + build_type = [x for x in build_types if x['id'] == id] + + if build_type: + return jsonify(build_type.pop()), 200 + else: + return json_error(404, "Not Found", "No such build type found.") + + +class BuildStateAPI(MethodView): + def get(self, id): + build_states = [] + for x in list(types.ArtifactBuildState): + build_states.append({'name': x.name, 'id': x.value}) + + if id is None: + json_data = {} + json_data['items'] = build_states + + return jsonify(json_data), 200 + + else: + build_state = [x for x in build_states if x['id'] == id] + + if build_state: + return jsonify(build_state.pop()), 200 + else: + return json_error(404, "Not Found", "No such build state found.") + + +class EventAPI(MethodView): def get(self, id): if id is None: p_query = filter_events(request) @@ -80,7 +192,7 @@ class EventAPI(MethodView): if event: return jsonify(event.json()), 200 else: - raise ValueError('No shuch event found.') + return json_error(404, "Not Found", "No such event found.") class BuildAPI(MethodView): @@ -100,12 +212,15 @@ class BuildAPI(MethodView): if build: return jsonify(build.json()), 200 else: - raise ValueError('No such build found.') + return json_error(404, "Not Found", "No such build found.") API_V1_MAPPING = { 'events': EventAPI, 'builds': BuildAPI, + 'event_types': EventTypeAPI, + 'build_types': BuildTypeAPI, + 'build_states': BuildStateAPI, } diff --git a/tests/test_views.py b/tests/test_views.py index 156f870..da3fa44 100644 --- a/tests/test_views.py +++ b/tests/test_views.py @@ -21,6 +21,7 @@ import unittest import json +import six from freshmaker import app, db, events, models from freshmaker.types import ArtifactType, ArtifactBuildState @@ -191,6 +192,63 @@ class TestViews(unittest.TestCase): self.assertEqual(len(evs), 1) self.assertEqual(evs[0]['search_key'], 'RHSA-2018-101') + def test_query_event_types(self): + resp = self.client.get('/freshmaker/1/event-types/') + event_types = json.loads(resp.data.decode('utf8'))['items'] + self.assertEqual(len(event_types), len(models.EVENT_TYPES)) + + def test_query_event_type(self): + for cls, val in six.iteritems(models.EVENT_TYPES): + resp = self.client.get('/freshmaker/1/event-types/%s' % val) + event = json.loads(resp.data.decode('utf8')) + self.assertEqual(event['id'], val) + self.assertEqual(event['name'], cls.__name__) + + def test_query_nonexist_event_type(self): + resp = self.client.get('/freshmaker/1/event-types/99999') + data = json.loads(resp.data.decode('utf8')) + self.assertEqual(data['status'], 404) + self.assertEqual(data['error'], 'Not Found') + self.assertEqual(data['message'], 'No such event type found.') + + def test_query_build_types(self): + resp = self.client.get('/freshmaker/1/build-types/') + build_types = json.loads(resp.data.decode('utf8'))['items'] + self.assertEqual(len(build_types), len(list(ArtifactType))) + + def test_query_build_type(self): + for t in list(ArtifactType): + resp = self.client.get('/freshmaker/1/build-types/%s' % t.value) + build_type = json.loads(resp.data.decode('utf8')) + self.assertEqual(build_type['id'], t.value) + self.assertEqual(build_type['name'], t.name) + + def test_query_nonexist_build_type(self): + resp = self.client.get('/freshmaker/1/build-types/99999') + data = json.loads(resp.data.decode('utf8')) + self.assertEqual(data['status'], 404) + self.assertEqual(data['error'], 'Not Found') + self.assertEqual(data['message'], 'No such build type found.') + + def test_query_build_states(self): + resp = self.client.get('/freshmaker/1/build-states/') + build_types = json.loads(resp.data.decode('utf8'))['items'] + self.assertEqual(len(build_types), len(list(ArtifactBuildState))) + + def test_query_build_state(self): + for t in list(ArtifactBuildState): + resp = self.client.get('/freshmaker/1/build-states/%s' % t.value) + build_type = json.loads(resp.data.decode('utf8')) + self.assertEqual(build_type['id'], t.value) + self.assertEqual(build_type['name'], t.name) + + def test_query_nonexist_build_state(self): + resp = self.client.get('/freshmaker/1/build-states/99999') + data = json.loads(resp.data.decode('utf8')) + self.assertEqual(data['status'], 404) + self.assertEqual(data['error'], 'Not Found') + self.assertEqual(data['message'], 'No such build state found.') + if __name__ == '__main__': unittest.main()