diff options
author | Morgan Richomme <morgan.richomme@orange.com> | 2016-05-30 06:52:58 +0000 |
---|---|---|
committer | Gerrit Code Review <gerrit@172.30.200.206> | 2016-05-30 06:52:58 +0000 |
commit | 04578f6f8c56ae2585c9aec637812d812919be46 (patch) | |
tree | 8ca191c076cdd44db3e4ecb990648928f696794a /utils/test/result_collection_api/resources | |
parent | 9a4aee1b758d5b518b20e90aee4fe75eb01aa774 (diff) | |
parent | 534ca019931d48a2a5f4075c0ca36b501d8f793d (diff) |
Merge "swagger-ize result-apis of testAPI"
Diffstat (limited to 'utils/test/result_collection_api/resources')
7 files changed, 168 insertions, 187 deletions
diff --git a/utils/test/result_collection_api/resources/handlers.py b/utils/test/result_collection_api/resources/handlers.py index 7d2e8161e..b5f71450c 100644 --- a/utils/test/result_collection_api/resources/handlers.py +++ b/utils/test/result_collection_api/resources/handlers.py @@ -67,13 +67,14 @@ class GenericApiHandler(RequestHandler): self.finish() def _create_response(self, resource): - href = self.request.full_url() + '/' + resource + href = self.request.full_url() + '/' + str(resource) return CreateResponse(href=href).format() @asynchronous @gen.coroutine - def _create(self, db_checks, **kwargs): + def _create(self, miss_checks, db_checks, **kwargs): """ + :param miss_checks: [miss1, miss2] :param db_checks: [(table, exist, query, (error, message))] :param db_op: (insert/remove) :param res_op: (_create_response/None) @@ -83,10 +84,11 @@ class GenericApiHandler(RequestHandler): raise HTTPError(HTTP_BAD_REQUEST, "no body") data = self.table_cls.from_dict(self.json_args) - name = data.name - if name is None or name == '': - raise HTTPError(HTTP_BAD_REQUEST, - '{} name missing'.format(self.table[:-1])) + for miss in miss_checks: + miss_data = data.__getattribute__(miss) + if miss_data is None or miss_data == '': + raise HTTPError(HTTP_BAD_REQUEST, + '{} missing'.format(miss)) for k, v in kwargs.iteritems(): data.__setattr__(k, v) @@ -98,8 +100,12 @@ class GenericApiHandler(RequestHandler): raise HTTPError(code, message) data.creation_date = datetime.now() - yield self._eval_db(self.table, 'insert', data.format()) - self.finish_request(self._create_response(name)) + _id = yield self._eval_db(self.table, 'insert', data.format()) + if 'name' in self.json_args: + resource = data.name + else: + resource = _id + self.finish_request(self._create_response(resource)) @asynchronous @gen.coroutine @@ -198,172 +204,6 @@ class VersionHandler(GenericApiHandler): self.finish_request([{'v1': 'basics'}]) -class TestResultsHandler(GenericApiHandler): - """ - TestResultsHandler Class - Handle the requests about the Test project's results - HTTP Methdods : - - GET : Get all test results and details about a specific one - - POST : Add a test results - - DELETE : Remove a test result - """ - - def initialize(self): - """ Prepares the database for the entire class """ - super(TestResultsHandler, self).initialize() - self.name = "test_result" - - @asynchronous - @gen.coroutine - def get(self, result_id=None): - """ - Retrieve result(s) for a test project on a specific POD. - Available filters for this request are : - - project : project name - - case : case name - - pod : pod name - - version : platform version (Arno-R1, ...) - - installer (fuel, ...) - - build_tag : Jenkins build tag name - - period : x (x last days) - - scenario : the test scenario (previously version) - - criteria : the global criteria status passed or failed - - trust_indicator : evaluate the stability of the test case to avoid - running systematically long and stable test case - - - :param result_id: Get a result by ID - :raise HTTPError - - GET /results/project=functest&case=vPing&version=Arno-R1 \ - &pod=pod_name&period=15 - => get results with optional filters - """ - - # prepare request - query = dict() - if result_id is not None: - query["_id"] = result_id - answer = yield self.db.results.find_one(query) - if answer is None: - raise HTTPError(HTTP_NOT_FOUND, - "test result {} Not Exist".format(result_id)) - else: - answer = format_data(answer, TestResult) - else: - pod_arg = self.get_query_argument("pod", None) - project_arg = self.get_query_argument("project", None) - case_arg = self.get_query_argument("case", None) - version_arg = self.get_query_argument("version", None) - installer_arg = self.get_query_argument("installer", None) - build_tag_arg = self.get_query_argument("build_tag", None) - scenario_arg = self.get_query_argument("scenario", None) - criteria_arg = self.get_query_argument("criteria", None) - period_arg = self.get_query_argument("period", None) - trust_indicator_arg = self.get_query_argument("trust_indicator", - None) - - if project_arg is not None: - query["project_name"] = project_arg - - if case_arg is not None: - query["case_name"] = case_arg - - if pod_arg is not None: - query["pod_name"] = pod_arg - - if version_arg is not None: - query["version"] = version_arg - - if installer_arg is not None: - query["installer"] = installer_arg - - if build_tag_arg is not None: - query["build_tag"] = build_tag_arg - - if scenario_arg is not None: - query["scenario"] = scenario_arg - - if criteria_arg is not None: - query["criteria_tag"] = criteria_arg - - if trust_indicator_arg is not None: - query["trust_indicator_arg"] = trust_indicator_arg - - if period_arg is not None: - try: - period_arg = int(period_arg) - except: - raise HTTPError(HTTP_BAD_REQUEST) - - if period_arg > 0: - period = datetime.now() - timedelta(days=period_arg) - obj = {"$gte": str(period)} - query["creation_date"] = obj - - res = [] - cursor = self.db.results.find(query) - while (yield cursor.fetch_next): - res.append(format_data(cursor.next_object(), TestResult)) - answer = {'results': res} - - self.finish_request(answer) - - @asynchronous - @gen.coroutine - def post(self): - """ - Create a new test result - :return: status of the request - :raise HTTPError - """ - - # check for request payload - if self.json_args is None: - raise HTTPError(HTTP_BAD_REQUEST, 'no payload') - - result = TestResult.from_dict(self.json_args) - - # check for pod_name instead of id, - # keeping id for current implementations - if result.pod_name is None: - raise HTTPError(HTTP_BAD_REQUEST, 'pod is not provided') - - # check for missing parameters in the request payload - if result.project_name is None: - raise HTTPError(HTTP_BAD_REQUEST, 'project is not provided') - - if result.case_name is None: - raise HTTPError(HTTP_BAD_REQUEST, 'testcase is not provided') - - # TODO : replace checks with jsonschema - # check for pod - the_pod = yield self.db.pods.find_one({"name": result.pod_name}) - if the_pod is None: - raise HTTPError(HTTP_NOT_FOUND, - "Could not find POD [{}] " - .format(self.json_args.get("pod_name"))) - - # check for project - the_project = yield self.db.projects.find_one( - {"name": result.project_name}) - if the_project is None: - raise HTTPError(HTTP_NOT_FOUND, "Could not find project [{}] " - .format(result.project_name)) - - # check for testcase - the_testcase = yield self.db.testcases.find_one( - {"name": result.case_name}) - if the_testcase is None: - raise HTTPError(HTTP_NOT_FOUND, - "Could not find testcase [{}] " - .format(result.case_name)) - - _id = yield self.db.results.insert(result.format(), check_keys=False) - - self.finish_request(self._create_response(_id)) - - class DashboardHandler(GenericApiHandler): """ DashboardHandler Class diff --git a/utils/test/result_collection_api/resources/pod_handlers.py b/utils/test/result_collection_api/resources/pod_handlers.py index c50ec51e3..9f583bbfc 100644 --- a/utils/test/result_collection_api/resources/pod_handlers.py +++ b/utils/test/result_collection_api/resources/pod_handlers.py @@ -31,7 +31,7 @@ class PodCLHandler(GenericPodHandler): @rtype: L{Pod} @return 200: pod is created. @raise 403: pod already exists - @raise 400: post without body + @raise 400: body or name not provided """ def query(data): return {'name': data.name} @@ -40,8 +40,9 @@ class PodCLHandler(GenericPodHandler): message = '{} already exists as a pod'.format(data.name) return HTTP_FORBIDDEN, message - db_check = [(self.table, False, query, error)] - self._create(db_check) + miss_checks = ['name'] + db_checks = [(self.table, False, query, error)] + self._create(miss_checks, db_checks) class PodGURHandler(GenericPodHandler): diff --git a/utils/test/result_collection_api/resources/project_handlers.py b/utils/test/result_collection_api/resources/project_handlers.py index e56c01c36..0bc1a61bd 100644 --- a/utils/test/result_collection_api/resources/project_handlers.py +++ b/utils/test/result_collection_api/resources/project_handlers.py @@ -33,7 +33,7 @@ class ProjectCLHandler(GenericProjectHandler): @rtype: L{Project} @return 200: project is created. @raise 403: project already exists - @raise 400: post without body + @raise 400: body or name not provided """ def query(data): return {'name': data.name} @@ -42,8 +42,9 @@ class ProjectCLHandler(GenericProjectHandler): message = '{} already exists as a project'.format(data.name) return HTTP_FORBIDDEN, message - db_check = [(self.table, False, query, error)] - self._create(db_check) + miss_checks = ['name'] + db_checks = [(self.table, False, query, error)] + self._create(miss_checks, db_checks) class ProjectGURHandler(GenericProjectHandler): diff --git a/utils/test/result_collection_api/resources/result_handlers.py b/utils/test/result_collection_api/resources/result_handlers.py new file mode 100644 index 000000000..d3fea1df7 --- /dev/null +++ b/utils/test/result_collection_api/resources/result_handlers.py @@ -0,0 +1,134 @@ +from datetime import datetime, timedelta + +from bson.objectid import ObjectId +from tornado.web import HTTPError + +from common.constants import HTTP_BAD_REQUEST, HTTP_NOT_FOUND +from resources.handlers import GenericApiHandler +from resources.result_models import TestResult +from tornado_swagger_ui.tornado_swagger import swagger + + +class GenericResultHandler(GenericApiHandler): + def __init__(self, application, request, **kwargs): + super(GenericResultHandler, self).__init__(application, + request, + **kwargs) + self.table = self.db_results + self.table_cls = TestResult + + +class ResultsCLHandler(GenericResultHandler): + @swagger.operation(nickname="list-all") + def get(self): + """ + @description: list all test results consist with query + @return 200: all test results consist with query, + empty list if no result is found + @rtype: L{TestResults} + """ + query = dict() + pod_arg = self.get_query_argument("pod", None) + project_arg = self.get_query_argument("project", None) + case_arg = self.get_query_argument("case", None) + version_arg = self.get_query_argument("version", None) + installer_arg = self.get_query_argument("installer", None) + build_tag_arg = self.get_query_argument("build_tag", None) + scenario_arg = self.get_query_argument("scenario", None) + criteria_arg = self.get_query_argument("criteria", None) + period_arg = self.get_query_argument("period", None) + trust_indicator_arg = self.get_query_argument("trust_indicator", None) + + if project_arg is not None: + query["project_name"] = project_arg + + if case_arg is not None: + query["case_name"] = case_arg + + if pod_arg is not None: + query["pod_name"] = pod_arg + + if version_arg is not None: + query["version"] = version_arg + + if installer_arg is not None: + query["installer"] = installer_arg + + if build_tag_arg is not None: + query["build_tag"] = build_tag_arg + + if scenario_arg is not None: + query["scenario"] = scenario_arg + + if criteria_arg is not None: + query["criteria_tag"] = criteria_arg + + if trust_indicator_arg is not None: + query["trust_indicator_arg"] = trust_indicator_arg + + if period_arg is not None: + try: + period_arg = int(period_arg) + except: + raise HTTPError(HTTP_BAD_REQUEST) + + if period_arg > 0: + period = datetime.now() - timedelta(days=period_arg) + obj = {"$gte": str(period)} + query["creation_date"] = obj + + self._list(query) + + @swagger.operation(nickname="create") + def post(self): + """ + @description: create a test result + @param body: result to be created + @type body: L{ResultCreateRequest} + @in body: body + @rtype: L{TestResult} + @return 200: result is created. + @raise 404: pod/project/testcase not exist + @raise 400: body/pod_name/project_name/case_name not provided + """ + def pod_query(data): + return {'name': data.pod_name} + + def pod_error(data): + message = 'Could not find pod [{}]'.format(data.pod_name) + return HTTP_NOT_FOUND, message + + def project_query(data): + return {'name': data.project_name} + + def project_error(data): + message = 'Could not find project [{}]'.format(data.project_name) + return HTTP_NOT_FOUND, message + + def testcase_query(data): + return {'project_name': data.project_name, 'name': data.case_name} + + def testcase_error(data): + message = 'Could not find testcase [{}] in project [{}]'\ + .format(data.case_name, data.project_name) + return HTTP_NOT_FOUND, message + + miss_checks = ['pod_name', 'project_name', 'case_name'] + db_checks = [('pods', True, pod_query, pod_error), + ('projects', True, project_query, project_error), + ('testcases', True, testcase_query, testcase_error)] + self._create(miss_checks, db_checks) + + +class ResultsGURHandler(GenericResultHandler): + @swagger.operation(nickname='get-one') + def get(self, result_id): + """ + @description: get a single result by result_id + @rtype: L{TestResult} + @return 200: test result exist + @raise 404: test result not exist + """ + query = dict() + query["_id"] = ObjectId(result_id) + self._get_one(query) diff --git a/utils/test/result_collection_api/resources/result_models.py b/utils/test/result_collection_api/resources/result_models.py index 15684e229..7faac16d4 100644 --- a/utils/test/result_collection_api/resources/result_models.py +++ b/utils/test/result_collection_api/resources/result_models.py @@ -1,4 +1,7 @@ +from tornado_swagger_ui.tornado_swagger import swagger + +@swagger.model() class ResultCreateRequest(object): def __init__(self, pod_name=None, @@ -43,9 +46,8 @@ class ResultCreateRequest(object): } -class TestResult: - """ Describes a test result""" - +@swagger.model() +class TestResult(object): def __init__(self): self._id = None self.case_name = None @@ -132,7 +134,11 @@ class TestResult: } +@swagger.model() class TestResults(object): + """ + @ptype testcases: C{list} of L{TestResult} + """ def __init__(self, results=list()): self.results = results diff --git a/utils/test/result_collection_api/resources/testcase_handlers.py b/utils/test/result_collection_api/resources/testcase_handlers.py index 9c0eb6363..8f3bea617 100644 --- a/utils/test/result_collection_api/resources/testcase_handlers.py +++ b/utils/test/result_collection_api/resources/testcase_handlers.py @@ -37,7 +37,7 @@ class TestcaseCLHandler(GenericTestcaseHandler): @return 200: testcase is created in this project. @raise 403: project not exist or testcase already exists in this project - @raise 400: post without body + @raise 400: body or name not provided """ def p_query(data): return {'name': data.project_name} @@ -57,9 +57,10 @@ class TestcaseCLHandler(GenericTestcaseHandler): .format(data.name, data.project_name) return HTTP_FORBIDDEN, message + miss_checks = ['name'] db_checks = [(self.db_projects, True, p_query, p_error), (self.db_testcases, False, tc_query, tc_error)] - self._create(db_checks, project_name=project_name) + self._create(miss_checks, db_checks, project_name=project_name) class TestcaseGURHandler(GenericTestcaseHandler): diff --git a/utils/test/result_collection_api/resources/testcase_models.py b/utils/test/result_collection_api/resources/testcase_models.py index f3867649f..90b3f75e9 100644 --- a/utils/test/result_collection_api/resources/testcase_models.py +++ b/utils/test/result_collection_api/resources/testcase_models.py @@ -35,8 +35,6 @@ class TestcaseUpdateRequest(object): @swagger.model() class Testcase(object): - """ Describes a test case""" - def __init__(self): self._id = None self.name = None |