summaryrefslogtreecommitdiffstats
path: root/utils/test/result_collection_api/resources
diff options
context:
space:
mode:
authorSerenaFeng <feng.xiaowei@zte.com.cn>2016-05-30 19:14:52 +0800
committerSerenaFeng <feng.xiaowei@zte.com.cn>2016-05-30 20:05:11 +0800
commit99700863f3c28fb7fb36e6670b78da828cbbddd4 (patch)
treeef7cd061cafa164c850146d904e99403a954dc9a /utils/test/result_collection_api/resources
parent04578f6f8c56ae2585c9aec637812d812919be46 (diff)
swagger-ize dashboard and version apis of testAPI
JIRA: FUNCTEST-273 Change-Id: I6f2b1de5488ba684d0c00e9f40daee2487a011cc Signed-off-by: SerenaFeng <feng.xiaowei@zte.com.cn>
Diffstat (limited to 'utils/test/result_collection_api/resources')
-rw-r--r--utils/test/result_collection_api/resources/dashboard_handlers.py99
-rw-r--r--utils/test/result_collection_api/resources/handlers.py182
-rw-r--r--utils/test/result_collection_api/resources/models.py17
-rw-r--r--utils/test/result_collection_api/resources/result_handlers.py130
4 files changed, 246 insertions, 182 deletions
diff --git a/utils/test/result_collection_api/resources/dashboard_handlers.py b/utils/test/result_collection_api/resources/dashboard_handlers.py
new file mode 100644
index 000000000..320fcc2be
--- /dev/null
+++ b/utils/test/result_collection_api/resources/dashboard_handlers.py
@@ -0,0 +1,99 @@
+from tornado.web import HTTPError
+
+from common.constants import HTTP_NOT_FOUND
+from dashboard.dashboard_utils import check_dashboard_ready_project, \
+ check_dashboard_ready_case, get_dashboard_result
+from resources.result_handlers import GenericResultHandler
+from resources.result_models import TestResult
+from tornado_swagger_ui.tornado_swagger import swagger
+
+
+class GenericDashboardHandler(GenericResultHandler):
+ def __init__(self, application, request, **kwargs):
+ super(GenericDashboardHandler, self).__init__(application,
+ request,
+ **kwargs)
+ self.table = self.db_results
+ self.table_cls = TestResult
+
+
+class DashboardHandler(GenericDashboardHandler):
+ @swagger.operation(nickname='query')
+ def get(self):
+ """
+ @description: Retrieve dashboard ready result(s)
+ for a test project
+ @notes: Retrieve dashboard ready result(s) for a test project
+ Available filters for this request are :
+ - project : project name
+ - case : case name
+ - pod : pod name
+ - version : platform version (Arno-R1, ...)
+ - installer (fuel, ...)
+ - period : x (x last days)
+
+ GET /dashboard?project=functest&case=vPing&version=Colorado \
+ &pod=pod_name&period=15
+ @rtype: L{string}
+ @param pod: pod name
+ @type pod: L{string}
+ @in pod: query
+ @required pod: False
+ @param project: project name
+ @type project: L{string}
+ @in project: query
+ @required project: True
+ @param case: case name
+ @type case: L{string}
+ @in case: query
+ @required case: True
+ @param version: i.e. Colorado
+ @type version: L{string}
+ @in version: query
+ @required version: False
+ @param installer: fuel/apex/joid/compass
+ @type installer: L{string}
+ @in installer: query
+ @required installer: False
+ @param period: last days
+ @type period: L{string}
+ @in period: query
+ @required period: False
+ @return 200: test result exist
+ @raise 400: period is not in
+ @raise 404: project or case name missing,
+ or project or case is not dashboard ready
+ """
+
+ project_arg = self.get_query_argument("project", None)
+ case_arg = self.get_query_argument("case", None)
+
+ # on /dashboard retrieve the list of projects and testcases
+ # ready for dashboard
+ if project_arg is None:
+ raise HTTPError(HTTP_NOT_FOUND, "Project name missing")
+
+ if not check_dashboard_ready_project(project_arg):
+ raise HTTPError(HTTP_NOT_FOUND,
+ 'Project [{}] not dashboard ready'
+ .format(project_arg))
+
+ if case_arg is None:
+ raise HTTPError(
+ HTTP_NOT_FOUND,
+ 'Test case missing for project [{}]'.format(project_arg))
+
+ if not check_dashboard_ready_case(project_arg, case_arg):
+ raise HTTPError(
+ HTTP_NOT_FOUND,
+ 'Test case [{}] not dashboard ready for project [{}]'
+ .format(case_arg, project_arg))
+
+ # special case of status for project
+ if case_arg == 'status':
+ self.finish_request(get_dashboard_result(project_arg, case_arg))
+ else:
+ def get_result(res, project, case):
+ return get_dashboard_result(project, case, res)
+
+ self._list(self.set_query(), get_result, project_arg, case_arg)
diff --git a/utils/test/result_collection_api/resources/handlers.py b/utils/test/result_collection_api/resources/handlers.py
index b5f71450c..b4f7117a3 100644
--- a/utils/test/result_collection_api/resources/handlers.py
+++ b/utils/test/result_collection_api/resources/handlers.py
@@ -14,26 +14,22 @@
# feng.xiaowei@zte.com.cn refactor dashboard related handler 5-24-2016
# feng.xiaowei@zte.com.cn add methods to GenericApiHandler 5-26-2016
# feng.xiaowei@zte.com.cn remove PodHandler 5-26-2016
+# feng.xiaowei@zte.com.cn remove ProjectHandler 5-26-2016
+# feng.xiaowei@zte.com.cn remove TestcaseHandler 5-27-2016
+# feng.xiaowei@zte.com.cn remove ResultHandler 5-29-2016
+# feng.xiaowei@zte.com.cn remove DashboardHandler 5-30-2016
##############################################################################
import json
-from datetime import datetime, timedelta
+from datetime import datetime
from tornado.web import RequestHandler, asynchronous, HTTPError
from tornado import gen
from models import CreateResponse
-from resources.result_models import TestResult
from common.constants import DEFAULT_REPRESENTATION, HTTP_BAD_REQUEST, \
HTTP_NOT_FOUND, HTTP_FORBIDDEN
-from common.config import prepare_put_request
-from dashboard.dashboard_utils import check_dashboard_ready_project, \
- check_dashboard_ready_case, get_dashboard_result
-
-
-def format_data(data, cls):
- cls_data = cls.from_dict(data)
- return cls_data.format_http()
+from tornado_swagger_ui.tornado_swagger import swagger
class GenericApiHandler(RequestHandler):
@@ -70,15 +66,16 @@ class GenericApiHandler(RequestHandler):
href = self.request.full_url() + '/' + str(resource)
return CreateResponse(href=href).format()
+ def format_data(self, data):
+ cls_data = self.table_cls.from_dict(data)
+ return cls_data.format_http()
+
@asynchronous
@gen.coroutine
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)
- :return:
+ :param db_checks: [(table, exist, query, error)]
"""
if self.json_args is None:
raise HTTPError(HTTP_BAD_REQUEST, "no body")
@@ -94,7 +91,7 @@ class GenericApiHandler(RequestHandler):
data.__setattr__(k, v)
for table, exist, query, error in db_checks:
- check = yield self._eval_db(table, 'find_one', query(data))
+ check = yield self._eval_db_find_one(query(data), table)
if (exist and not check) or (not exist and check):
code, message = error(data)
raise HTTPError(code, message)
@@ -109,29 +106,33 @@ class GenericApiHandler(RequestHandler):
@asynchronous
@gen.coroutine
- def _list(self, query=None):
+ def _list(self, query=None, res_op=None, *args):
if query is None:
query = {}
- res = []
+ data = []
cursor = self._eval_db(self.table, 'find', query)
while (yield cursor.fetch_next):
- res.append(format_data(cursor.next_object(), self.table_cls))
- self.finish_request({self.table: res})
+ data.append(self.format_data(cursor.next_object()))
+ if res_op is None:
+ res = {self.table: data}
+ else:
+ res = res_op(data, *args)
+ self.finish_request(res)
@asynchronous
@gen.coroutine
def _get_one(self, query):
- data = yield self._eval_db(self.table, 'find_one', query)
+ data = yield self._eval_db_find_one(query)
if data is None:
raise HTTPError(HTTP_NOT_FOUND,
"[{}] not exist in table [{}]"
.format(query, self.table))
- self.finish_request(format_data(data, self.table_cls))
+ self.finish_request(self.format_data(data))
@asynchronous
@gen.coroutine
def _delete(self, query):
- data = yield self._eval_db(self.table, 'find_one', query)
+ data = yield self._eval_db_find_one(query)
if data is None:
raise HTTPError(HTTP_NOT_FOUND,
"[{}] not exit in table [{}]"
@@ -147,7 +148,7 @@ class GenericApiHandler(RequestHandler):
raise HTTPError(HTTP_BAD_REQUEST, "No payload")
# check old data exist
- from_data = yield self._eval_db(self.table, 'find_one', query)
+ from_data = yield self._eval_db_find_one(query)
if from_data is None:
raise HTTPError(HTTP_NOT_FOUND,
"{} could not be found in table [{}]"
@@ -157,7 +158,7 @@ class GenericApiHandler(RequestHandler):
# check new data exist
equal, new_query = self._update_query(db_keys, data)
if not equal:
- to_data = yield self._eval_db(self.table, 'find_one', new_query)
+ to_data = yield self._eval_db_find_one(new_query)
if to_data is not None:
raise HTTPError(HTTP_FORBIDDEN,
"{} already exists in table [{}]"
@@ -165,22 +166,37 @@ class GenericApiHandler(RequestHandler):
# we merge the whole document """
edit_request = data.format()
- edit_request.update(self._update_request(data))
+ edit_request.update(self._update_requests(data))
""" Updating the DB """
yield self._eval_db(self.table, 'update', query, edit_request)
edit_request['_id'] = str(data._id)
self.finish_request(edit_request)
- def _update_request(self, data):
+ def _update_requests(self, data):
request = dict()
for k, v in self.json_args.iteritems():
- request = prepare_put_request(request, k, v,
+ request = self._update_request(request, k, v,
data.__getattribute__(k))
if not request:
raise HTTPError(HTTP_FORBIDDEN, "Nothing to update")
return request
+ @staticmethod
+ def _update_request(edit_request, key, new_value, old_value):
+ """
+ This function serves to prepare the elements in the update request.
+ We try to avoid replace the exact values in the db
+ edit_request should be a dict in which we add an entry (key) after
+ comparing values
+ """
+ if not (new_value is None):
+ if len(new_value) > 0:
+ if new_value != old_value:
+ edit_request[key] = new_value
+
+ return edit_request
+
def _update_query(self, keys, data):
query = dict()
equal = True
@@ -197,111 +213,17 @@ class GenericApiHandler(RequestHandler):
def _eval_db(self, table, method, *args):
return eval('self.db.%s.%s(*args)' % (table, method))
-
-class VersionHandler(GenericApiHandler):
- """ Display a message for the API version """
- def get(self):
- self.finish_request([{'v1': 'basics'}])
+ def _eval_db_find_one(self, query, table=None):
+ if table is None:
+ table = self.table
+ return self._eval_db(table, 'find_one', query)
-class DashboardHandler(GenericApiHandler):
- """
- DashboardHandler Class
- Handle the requests about the Test project's results
- in a dahboard ready format
- HTTP Methdods :
- - GET : Get all test results and details about a specific one
- """
- def initialize(self):
- """ Prepares the database for the entire class """
- super(DashboardHandler, self).initialize()
- self.name = "dashboard"
-
- @asynchronous
- @gen.coroutine
+class VersionHandler(GenericApiHandler):
+ @swagger.operation(nickname='list')
def get(self):
"""
- Retrieve dashboard ready result(s) for a test project
- Available filters for this request are :
- - project : project name
- - case : case name
- - pod : pod name
- - version : platform version (Arno-R1, ...)
- - installer (fuel, ...)
- - period : x (x last days)
-
-
- :param result_id: Get a result by ID
- :raise HTTPError
-
- GET /dashboard?project=functest&case=vPing&version=Arno-R1 \
- &pod=pod_name&period=15
- => get results with optional filters
+ @description: Display a message for the API version
+ @rtype: L{Versions}
"""
-
- project_arg = self.get_query_argument("project", None)
- case_arg = self.get_query_argument("case", None)
- pod_arg = self.get_query_argument("pod", None)
- version_arg = self.get_query_argument("version", None)
- installer_arg = self.get_query_argument("installer", None)
- period_arg = self.get_query_argument("period", None)
-
- # prepare request
- query = dict()
-
- 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 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
-
- # on /dashboard retrieve the list of projects and testcases
- # ready for dashboard
- if project_arg is None:
- raise HTTPError(HTTP_NOT_FOUND, "Project name missing")
-
- if not check_dashboard_ready_project(project_arg):
- raise HTTPError(HTTP_NOT_FOUND,
- 'Project [{}] not dashboard ready'
- .format(project_arg))
-
- if case_arg is None:
- raise HTTPError(
- HTTP_NOT_FOUND,
- 'Test case missing for project [{}]'.format(project_arg))
-
- if not check_dashboard_ready_case(project_arg, case_arg):
- raise HTTPError(
- HTTP_NOT_FOUND,
- 'Test case [{}] not dashboard ready for project [{}]'
- .format(case_arg, project_arg))
-
- # special case of status for project
- res = []
- if case_arg != "status":
- cursor = self.db.results.find(query)
- while (yield cursor.fetch_next):
- result = TestResult.from_dict(cursor.next_object())
- res.append(result.format_http())
-
- # final response object
- self.finish_request(get_dashboard_result(project_arg, case_arg, res))
+ self.finish_request([{'v1': 'basics'}])
diff --git a/utils/test/result_collection_api/resources/models.py b/utils/test/result_collection_api/resources/models.py
index b4094dd2c..3c834fd48 100644
--- a/utils/test/result_collection_api/resources/models.py
+++ b/utils/test/result_collection_api/resources/models.py
@@ -13,6 +13,7 @@
# feng.xiaowei@zte.com.cn mv TestCase to testcase_models.py 5-20-2016
# feng.xiaowei@zte.com.cn mv TestResut to result_models.py 5-23-2016
##############################################################################
+from tornado_swagger_ui.tornado_swagger import swagger
class CreateResponse(object):
@@ -30,3 +31,19 @@ class CreateResponse(object):
def format(self):
return {'href': self.href}
+
+
+@swagger.model()
+class Versions(object):
+ """
+ @ptype versions: C{list} of L{Version}
+ """
+ def __init__(self, versions):
+ self.versions = versions
+
+
+@swagger.model()
+class Version(object):
+ def __init__(self, version=None, description=None):
+ self.version = version
+ self.description = description
diff --git a/utils/test/result_collection_api/resources/result_handlers.py b/utils/test/result_collection_api/resources/result_handlers.py
index d3fea1df7..d344f462b 100644
--- a/utils/test/result_collection_api/resources/result_handlers.py
+++ b/utils/test/result_collection_api/resources/result_handlers.py
@@ -17,67 +17,93 @@ class GenericResultHandler(GenericApiHandler):
self.table = self.db_results
self.table_cls = TestResult
+ def set_query(self):
+ query = dict()
+ for k in self.request.query_arguments.keys():
+ v = self.get_query_argument(k)
+ if k == 'project' or k == 'pod' or k == 'case':
+ query[k + '_name'] = v
+ elif k == 'period':
+ try:
+ v = int(v)
+ except:
+ raise HTTPError(HTTP_BAD_REQUEST, 'period must be int')
+ if v > 0:
+ period = datetime.now() - timedelta(days=v)
+ obj = {"$gte": str(period)}
+ query['creation_date'] = obj
+ else:
+ query[k] = v
+ return query
+
class ResultsCLHandler(GenericResultHandler):
@swagger.operation(nickname="list-all")
def get(self):
"""
- @description: list all test results consist with query
+ @description: Retrieve result(s) for a test project
+ on a specific pod.
+ @notes: 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
+
+ GET /results/project=functest&case=vPing&version=Arno-R1 \
+ &pod=pod_name&period=15
@return 200: all test results consist with query,
empty list if no result is found
@rtype: L{TestResults}
+ @param pod: pod name
+ @type pod: L{string}
+ @in pod: query
+ @required pod: False
+ @param project: project name
+ @type project: L{string}
+ @in project: query
+ @required project: True
+ @param case: case name
+ @type case: L{string}
+ @in case: query
+ @required case: True
+ @param version: i.e. Colorado
+ @type version: L{string}
+ @in version: query
+ @required version: False
+ @param installer: fuel/apex/joid/compass
+ @type installer: L{string}
+ @in installer: query
+ @required installer: False
+ @param build_tag: i.e. v3.0
+ @type build_tag: L{string}
+ @in build_tag: query
+ @required build_tag: False
+ @param scenario: i.e. odl
+ @type scenario: L{string}
+ @in scenario: query
+ @required scenario: False
+ @param criteria: i.e. passed
+ @type criteria: L{string}
+ @in criteria: query
+ @required criteria: False
+ @param period: last days
+ @type period: L{string}
+ @in period: query
+ @required period: False
+ @param trust_indicator: must be integer
+ @type trust_indicator: L{string}
+ @in trust_indicator: query
+ @required trust_indicator: False
"""
- 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)
+ self._list(self.set_query())
@swagger.operation(nickname="create")
def post(self):