summaryrefslogtreecommitdiffstats
path: root/utils
diff options
context:
space:
mode:
Diffstat (limited to 'utils')
-rw-r--r--utils/push-test-logs.sh10
-rw-r--r--utils/test/result_collection_api/resources/handlers.py267
-rw-r--r--utils/test/result_collection_api/resources/pod_handlers.py75
-rw-r--r--utils/test/result_collection_api/resources/pod_models.py16
-rw-r--r--utils/test/result_collection_api/resources/project_handlers.py124
-rw-r--r--utils/test/result_collection_api/resources/project_models.py34
-rw-r--r--utils/test/result_collection_api/result_collection_api.py27
-rw-r--r--utils/test/result_collection_api/tests/unit/test_base.py14
-rw-r--r--utils/test/result_collection_api/tests/unit/test_pod.py12
-rw-r--r--utils/test/result_collection_api/tests/unit/test_project.py12
-rw-r--r--utils/test/result_collection_api/tornado_swagger_ui/__init__.py1
-rw-r--r--utils/test/result_collection_api/tornado_swagger_ui/example/basic.py34
-rw-r--r--utils/test/result_collection_api/tornado_swagger_ui/setup.py25
-rw-r--r--utils/test/result_collection_api/tornado_swagger_ui/tornado_swagger/__init__.py1
-rw-r--r--utils/test/result_collection_api/tornado_swagger_ui/tornado_swagger/handlers.py31
-rw-r--r--utils/test/result_collection_api/tornado_swagger_ui/tornado_swagger/settings.py9
-rw-r--r--utils/test/result_collection_api/tornado_swagger_ui/tornado_swagger/swagger.py24
-rw-r--r--utils/test/result_collection_api/tornado_swagger_ui/tornado_swagger/views.py42
18 files changed, 445 insertions, 313 deletions
diff --git a/utils/push-test-logs.sh b/utils/push-test-logs.sh
index 972853b78..745645041 100644
--- a/utils/push-test-logs.sh
+++ b/utils/push-test-logs.sh
@@ -17,11 +17,13 @@ res_build_date=${1:-$(date -u +"%Y-%m-%d_%H-%M-%S")}
project=$PROJECT
branch=${GIT_BRANCH##*/}
testbed=$NODE_NAME
-dir_result="${HOME}/opnfv/$project/results/$branch"
+dir_result="${HOME}/opnfv/$project/results"
+# src: https://wiki.opnfv.org/display/INF/Hardware+Infrastructure
+# + intel-pod3 (vsperf)
node_list=(\
-'opnfv-jump-1' 'opnfv-jump-2' 'ericsson-pod1' 'ericsson-pod2' \
-'intelpod2-jumphost' 'intel-pod3' 'intel-pod5' 'intel-pod6' \
-'intel-pod8' 'huawei-us-deploy-bare-1' 'orange-fr-pod2')
+'lf-pod1' 'lf-pod2' 'intel-pod2' 'intel-pod3' \
+'intel-pod5' 'intel-pod6' 'intel-pod7' 'intel-pod8' \
+'ericsson-pod2' 'huawei-pod1')
if [[ ! " ${node_list[@]} " =~ " ${testbed} " ]]; then
echo "This is not a CI POD. Aborting pushing the logs to artifacts."
diff --git a/utils/test/result_collection_api/resources/handlers.py b/utils/test/result_collection_api/resources/handlers.py
index 435334341..3f9d8422c 100644
--- a/utils/test/result_collection_api/resources/handlers.py
+++ b/utils/test/result_collection_api/resources/handlers.py
@@ -12,6 +12,8 @@
# feng.xiaowei@zte.com.cn refactor testcase related handler 5-20-2016
# feng.xiaowei@zte.com.cn refactor result related handler 5-23-2016
# 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
##############################################################################
import json
@@ -23,8 +25,6 @@ from tornado import gen
from models import CreateResponse
from resources.result_models import TestResult
from resources.testcase_models import Testcase
-from resources.project_models import Project
-from resources.pod_models import Pod
from common.constants import DEFAULT_REPRESENTATION, HTTP_BAD_REQUEST, \
HTTP_NOT_FOUND, HTTP_FORBIDDEN
from common.config import prepare_put_request
@@ -38,15 +38,12 @@ def format_data(data, cls):
class GenericApiHandler(RequestHandler):
- """
- The purpose of this class is to take benefit of inheritance and prepare
- a set of common functions for
- the handlers
- """
-
- def initialize(self):
- """ Prepares the database for the entire class """
+ def __init__(self, application, request, **kwargs):
+ super(GenericApiHandler, self).__init__(application, request, **kwargs)
self.db = self.settings["db"]
+ self.json_args = None
+ self.table = None
+ self.table_cls = None
def prepare(self):
if self.request.method != "GET" and self.request.method != "DELETE":
@@ -59,8 +56,6 @@ class GenericApiHandler(RequestHandler):
raise HTTPError(HTTP_BAD_REQUEST,
"Bad Json format [{}]".
format(error))
- else:
- self.json_args = None
def finish_request(self, json_object=None):
if json_object:
@@ -72,232 +67,68 @@ class GenericApiHandler(RequestHandler):
href = self.request.full_url() + '/' + resource
return CreateResponse(href=href).format()
-
-class VersionHandler(GenericApiHandler):
- """ Display a message for the API version """
- def get(self):
- self.finish_request([{'v1': 'basics'}])
-
-
-class PodHandler(GenericApiHandler):
- """ Handle the requests about the POD Platforms
- HTTP Methdods :
- - GET : Get PODS
- - POST : Create a pod
- - DELETE : DELETE POD
- """
-
- def initialize(self):
- """ Prepares the database for the entire class """
- super(PodHandler, self).initialize()
-
@asynchronous
@gen.coroutine
- def get(self, pod_name=None):
- """
- Get all pods or a single pod
- :param pod_id:
- """
- query = dict()
-
- if pod_name is not None:
- query["name"] = pod_name
- answer = yield self.db.pods.find_one(query)
- if answer is None:
- raise HTTPError(HTTP_NOT_FOUND,
- "{} Not Exist".format(pod_name))
- else:
- answer = format_data(answer, Pod)
- else:
- res = []
- cursor = self.db.pods.find(query)
- while (yield cursor.fetch_next):
- res.append(format_data(cursor.next_object(), Pod))
- answer = {'pods': res}
-
- self.finish_request(answer)
-
- @asynchronous
- @gen.coroutine
- def post(self):
- """ Create a POD"""
-
+ def _create(self, error):
if self.json_args is None:
- raise HTTPError(HTTP_BAD_REQUEST)
+ raise HTTPError(HTTP_BAD_REQUEST, 'no body')
- query = {"name": self.json_args.get("name")}
+ 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]))
- # check for existing name in db
- the_pod = yield self.db.pods.find_one(query)
- if the_pod is not None:
+ exist_data = yield self._eval_db(self.table, 'find_one',
+ {"name": name})
+ if exist_data is not None:
raise HTTPError(HTTP_FORBIDDEN,
- "{} already exists as a pod".format(
- self.json_args.get("name")))
-
- pod = Pod.from_dict(self.json_args)
- pod.creation_date = datetime.now()
-
- yield self.db.pods.insert(pod.format())
- self.finish_request(self._create_response(pod.name))
+ error.format(name, self.table[:-1]))
+ data.creation_date = datetime.now()
+ yield self._eval_db(self.table, 'insert', data.format())
+ self.finish_request(self._create_response(name))
@asynchronous
@gen.coroutine
- def delete(self, pod_name):
- """ Remove a POD
-
- # check for an existing pod to be deleted
- mongo_dict = yield self.db.pods.find_one(
- {'name': pod_name})
- pod = TestProject.pod(mongo_dict)
- if pod is None:
- raise HTTPError(HTTP_NOT_FOUND,
- "{} could not be found as a pod to be deleted"
- .format(pod_name))
-
- # just delete it, or maybe save it elsewhere in a future
- res = yield self.db.projects.remove(
- {'name': pod_name})
-
- self.finish_request(answer)
- """
- pass
-
-
-class ProjectHandler(GenericApiHandler):
- """
- TestProjectHandler Class
- Handle the requests about the Test projects
- HTTP Methdods :
- - GET : Get all test projects and details about a specific one
- - POST : Add a test project
- - PUT : Edit test projects information (name and/or description)
- - DELETE : Remove a test project
- """
-
- def initialize(self):
- """ Prepares the database for the entire class """
- super(ProjectHandler, self).initialize()
-
- @asynchronous
- @gen.coroutine
- def get(self, project_name=None):
- """
- Get Project(s) info
- :param project_name:
- """
-
- query = dict()
-
- if project_name is not None:
- query["name"] = project_name
- answer = yield self.db.projects.find_one(query)
- if answer is None:
- raise HTTPError(HTTP_NOT_FOUND,
- "{} Not Exist".format(project_name))
- else:
- answer = format_data(answer, Project)
- else:
- res = []
- cursor = self.db.projects.find(query)
- while (yield cursor.fetch_next):
- res.append(format_data(cursor.next_object(), Project))
- answer = {'projects': res}
-
- self.finish_request(answer)
+ def _list(self, query=None):
+ if query is None:
+ query = {}
+ res = []
+ 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})
@asynchronous
@gen.coroutine
- def post(self):
- """ Create a test project"""
-
- if self.json_args is None:
- raise HTTPError(HTTP_BAD_REQUEST)
-
- query = {"name": self.json_args.get("name")}
-
- # check for name in db
- the_project = yield self.db.projects.find_one(query)
- if the_project is not None:
- raise HTTPError(HTTP_FORBIDDEN,
- "{} already exists as a project".format(
- self.json_args.get("name")))
-
- project = Project.from_dict(self.json_args)
- project.creation_date = datetime.now()
-
- yield self.db.projects.insert(project.format())
- self.finish_request(self._create_response(project.name))
+ def _get_one(self, query):
+ data = yield self._eval_db(self.table, '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))
@asynchronous
@gen.coroutine
- def put(self, project_name):
- """ Updates the name and description of a test project"""
-
- if self.json_args is None:
- raise HTTPError(HTTP_BAD_REQUEST)
-
- query = {'name': project_name}
- from_project = yield self.db.projects.find_one(query)
- if from_project is None:
+ def _delete(self, query):
+ data = yield self._eval_db(self.table, 'find_one', query)
+ if data is None:
raise HTTPError(HTTP_NOT_FOUND,
- "{} could not be found".format(project_name))
-
- project = Project.from_dict(from_project)
- new_name = self.json_args.get("name")
- new_description = self.json_args.get("description")
-
- # check for payload name parameter in db
- # avoid a request if the project name has not changed in the payload
- if new_name != project.name:
- to_project = yield self.db.projects.find_one(
- {"name": new_name})
- if to_project is not None:
- raise HTTPError(HTTP_FORBIDDEN,
- "{} already exists as a project"
- .format(new_name))
+ "[{}] not exit in table [{}]"
+ .format(query, self.table))
- # new dict for changes
- request = dict()
- request = prepare_put_request(request,
- "name",
- new_name,
- project.name)
- request = prepare_put_request(request,
- "description",
- new_description,
- project.description)
-
- """ raise exception if there isn't a change """
- if not request:
- raise HTTPError(HTTP_FORBIDDEN, "Nothing to update")
-
- """ we merge the whole document """
- edit_request = project.format()
- edit_request.update(request)
-
- """ Updating the DB """
- yield self.db.projects.update({'name': project_name}, edit_request)
- new_project = yield self.db.projects.find_one({"_id": project._id})
-
- self.finish_request(format_data(new_project, Project))
-
- @asynchronous
- @gen.coroutine
- def delete(self, project_name):
- """ Remove a test project"""
- query = {'name': project_name}
+ yield self._eval_db(self.table, 'remove', query)
+ self.finish_request()
- # check for an existing project to be deleted
- project = yield self.db.projects.find_one(query)
- if project is None:
- raise HTTPError(HTTP_NOT_FOUND,
- "{} could not be found as a project to be deleted"
- .format(project_name))
+ def _eval_db(self, table, method, param):
+ return eval('self.db.%s.%s(param)' % (table, method))
- # just delete it, or maybe save it elsewhere in a future
- yield self.db.projects.remove(query)
- self.finish_request()
+class VersionHandler(GenericApiHandler):
+ """ Display a message for the API version """
+ def get(self):
+ self.finish_request([{'v1': 'basics'}])
class TestcaseHandler(GenericApiHandler):
diff --git a/utils/test/result_collection_api/resources/pod_handlers.py b/utils/test/result_collection_api/resources/pod_handlers.py
new file mode 100644
index 000000000..590ae5baf
--- /dev/null
+++ b/utils/test/result_collection_api/resources/pod_handlers.py
@@ -0,0 +1,75 @@
+from tornado import gen
+from tornado.web import asynchronous
+
+from tornado_swagger_ui.tornado_swagger import swagger
+from handlers import GenericApiHandler
+from pod_models import Pod
+
+
+class GenericPodHandler(GenericApiHandler):
+ def __init__(self, application, request, **kwargs):
+ super(GenericPodHandler, self).__init__(application, request, **kwargs)
+ self.table = 'pods'
+ self.table_cls = Pod
+
+
+class PodCLHandler(GenericPodHandler):
+ @swagger.operation(nickname='list-all')
+ def get(self):
+ """
+ @description: list all pods
+ @return 200: list all pods, empty list is no pod exist
+ @rtype: L{Pods}
+ """
+ self._list()
+
+ @gen.coroutine
+ @swagger.operation(nickname='create')
+ def post(self):
+ """
+ @description: create a pod
+ @param body: pod to be created
+ @type body: L{PodCreateRequest}
+ @in body: body
+ @rtype: L{Pod}
+ @return 200: pod is created.
+ @raise 403: pod already exists
+ @raise 400: post without body
+ """
+ self._create('{} already exists as a {}')
+
+
+class PodGURHandler(GenericPodHandler):
+ @swagger.operation(nickname='get-one')
+ def get(self, pod_name):
+ """
+ @description: get a single pod by pod_name
+ @rtype: L{Pod}
+ @return 200: pod exist
+ @raise 404: pod not exist
+ """
+ query = dict()
+ query['name'] = pod_name
+ self._get_one(query)
+
+ @asynchronous
+ @gen.coroutine
+ def delete(self, pod_name):
+ """ Remove a POD
+
+ # check for an existing pod to be deleted
+ mongo_dict = yield self.db.pods.find_one(
+ {'name': pod_name})
+ pod = TestProject.pod(mongo_dict)
+ if pod is None:
+ raise HTTPError(HTTP_NOT_FOUND,
+ "{} could not be found as a pod to be deleted"
+ .format(pod_name))
+
+ # just delete it, or maybe save it elsewhere in a future
+ res = yield self.db.projects.remove(
+ {'name': pod_name})
+
+ self.finish_request(answer)
+ """
+ pass
diff --git a/utils/test/result_collection_api/resources/pod_models.py b/utils/test/result_collection_api/resources/pod_models.py
index b02e3c222..cc98c90ce 100644
--- a/utils/test/result_collection_api/resources/pod_models.py
+++ b/utils/test/result_collection_api/resources/pod_models.py
@@ -1,3 +1,5 @@
+from tornado_swagger_ui.tornado_swagger import swagger
+
__author__ = '__serena__'
# name: name of the POD e.g. zte-1
@@ -6,8 +8,9 @@ __author__ = '__serena__'
# role: ci-pod or community-pod or single-node
+@swagger.model()
class PodCreateRequest(object):
- def __init__(self, name='', mode='', details='', role=""):
+ def __init__(self, name, mode='', details='', role=""):
self.name = name
self.mode = mode
self.details = details
@@ -22,10 +25,11 @@ class PodCreateRequest(object):
}
+@swagger.model()
class Pod(PodCreateRequest):
- """ describes a POD platform """
- def __init__(self, name='', mode='', details='', role="",
- _id='', create_date=''):
+ def __init__(self,
+ name='', mode='', details='',
+ role="", _id='', create_date=''):
super(Pod, self).__init__(name, mode, details, role)
self._id = _id
self.creation_date = create_date
@@ -55,7 +59,11 @@ class Pod(PodCreateRequest):
return f
+@swagger.model()
class Pods(object):
+ """
+ @ptype pods: C{list} of L{Pod}
+ """
def __init__(self, pods=list()):
self.pods = pods
diff --git a/utils/test/result_collection_api/resources/project_handlers.py b/utils/test/result_collection_api/resources/project_handlers.py
new file mode 100644
index 000000000..69ce3b592
--- /dev/null
+++ b/utils/test/result_collection_api/resources/project_handlers.py
@@ -0,0 +1,124 @@
+from tornado import gen
+from tornado.web import HTTPError, asynchronous
+
+from tornado_swagger_ui.tornado_swagger import swagger
+from handlers import GenericApiHandler, prepare_put_request, format_data
+from common.constants import HTTP_BAD_REQUEST, HTTP_FORBIDDEN, HTTP_NOT_FOUND
+from project_models import Project
+
+
+class GenericProjectHandler(GenericApiHandler):
+ def __init__(self, application, request, **kwargs):
+ super(GenericProjectHandler, self).__init__(application,
+ request,
+ **kwargs)
+ self.table = 'projects'
+ self.table_cls = Project
+
+
+class ProjectCLHandler(GenericProjectHandler):
+ @swagger.operation(nickname="list-all")
+ def get(self):
+ """
+ @description: list all projects
+ @return 200: return all projects, empty list is no project exist
+ @rtype: L{Projects}
+ """
+ self._list()
+
+ @swagger.operation(nickname="create")
+ def post(self):
+ """
+ @description: create a project
+ @param body: project to be created
+ @type body: L{ProjectCreateRequest}
+ @in body: body
+ @rtype: L{Project}
+ @return 200: project is created.
+ @raise 403: project already exists
+ @raise 400: post without body
+ """
+ self._create('{} already exists as a {}')
+
+
+class ProjectGURHandler(GenericProjectHandler):
+ @swagger.operation(nickname='get-one')
+ def get(self, project_name):
+ """
+ @description: get a single project by project_name
+ @rtype: L{Project}
+ @return 200: project exist
+ @raise 404: project not exist
+ """
+ self._get_one({'name': project_name})
+
+ @asynchronous
+ @gen.coroutine
+ @swagger.operation(nickname="update")
+ def put(self, project_name):
+ """
+ @description: update a single project by project_name
+ @param body: project to be updated
+ @type body: L{ProjectUpdateRequest}
+ @in body: body
+ @rtype: L{Project}
+ @return 200: update success
+ @raise 404: project not exist
+ @raise 403: new project name already exist or nothing to update
+ """
+ if self.json_args is None:
+ raise HTTPError(HTTP_BAD_REQUEST)
+
+ query = {'name': project_name}
+ from_project = yield self.db.projects.find_one(query)
+ if from_project is None:
+ raise HTTPError(HTTP_NOT_FOUND,
+ "{} could not be found".format(project_name))
+
+ project = Project.from_dict(from_project)
+ new_name = self.json_args.get("name")
+ new_description = self.json_args.get("description")
+
+ # check for payload name parameter in db
+ # avoid a request if the project name has not changed in the payload
+ if new_name != project.name:
+ to_project = yield self.db.projects.find_one(
+ {"name": new_name})
+ if to_project is not None:
+ raise HTTPError(HTTP_FORBIDDEN,
+ "{} already exists as a project"
+ .format(new_name))
+
+ # new dict for changes
+ request = dict()
+ request = prepare_put_request(request,
+ "name",
+ new_name,
+ project.name)
+ request = prepare_put_request(request,
+ "description",
+ new_description,
+ project.description)
+
+ """ raise exception if there isn't a change """
+ if not request:
+ raise HTTPError(HTTP_FORBIDDEN, "Nothing to update")
+
+ """ we merge the whole document """
+ edit_request = project.format()
+ edit_request.update(request)
+
+ """ Updating the DB """
+ yield self.db.projects.update(query, edit_request)
+ new_project = yield self.db.projects.find_one({"_id": project._id})
+
+ self.finish_request(format_data(new_project, Project))
+
+ @swagger.operation(nickname='delete')
+ def delete(self, project_name):
+ """
+ @description: delete a project by project_name
+ @return 200: delete success
+ @raise 404: project not exist
+ """
+ self._delete({'name': project_name})
diff --git a/utils/test/result_collection_api/resources/project_models.py b/utils/test/result_collection_api/resources/project_models.py
index 895fc3e5e..a8f830932 100644
--- a/utils/test/result_collection_api/resources/project_models.py
+++ b/utils/test/result_collection_api/resources/project_models.py
@@ -1,7 +1,23 @@
+from tornado_swagger_ui.tornado_swagger import swagger
+
__author__ = '__serena__'
+@swagger.model()
class ProjectCreateRequest(object):
+ def __init__(self, name, description=''):
+ self.name = name
+ self.description = description
+
+ def format(self):
+ return {
+ "name": self.name,
+ "description": self.description,
+ }
+
+
+@swagger.model()
+class ProjectUpdateRequest(object):
def __init__(self, name='', description=''):
self.name = name
self.description = description
@@ -13,14 +29,14 @@ class ProjectCreateRequest(object):
}
+@swagger.model()
class Project:
- """ Describes a test project"""
-
- def __init__(self):
- self._id = None
- self.name = None
- self.description = None
- self.creation_date = None
+ def __init__(self,
+ name=None, _id=None, description=None, create_date=None):
+ self._id = _id
+ self.name = name
+ self.description = description
+ self.creation_date = create_date
@staticmethod
def from_dict(res_dict):
@@ -52,7 +68,11 @@ class Project:
}
+@swagger.model()
class Projects(object):
+ """
+ @ptype projects: C{list} of L{Project}
+ """
def __init__(self, projects=list()):
self.projects = projects
diff --git a/utils/test/result_collection_api/result_collection_api.py b/utils/test/result_collection_api/result_collection_api.py
index 97aa58c77..344e0d7b0 100644
--- a/utils/test/result_collection_api/result_collection_api.py
+++ b/utils/test/result_collection_api/result_collection_api.py
@@ -29,14 +29,17 @@ TODOs :
"""
+import argparse
+
import tornado.ioloop
import motor
-import argparse
-from resources.handlers import VersionHandler, PodHandler, \
- ProjectHandler, TestcaseHandler, TestResultsHandler, DashboardHandler
+from resources.handlers import VersionHandler, \
+ TestcaseHandler, TestResultsHandler, DashboardHandler
+from resources.pod_handlers import PodCLHandler, PodGURHandler
+from resources.project_handlers import ProjectCLHandler, ProjectGURHandler
from common.config import APIConfig
-
+from tornado_swagger_ui.tornado_swagger import swagger
# optionally get config file from command line
parser = argparse.ArgumentParser()
@@ -51,29 +54,27 @@ db = client[CONF.mongo_dbname]
def make_app():
- return tornado.web.Application(
+ return swagger.Application(
[
# GET /version => GET API version
(r"/versions", VersionHandler),
# few examples:
- # GET /pods => Get all pods
- # GET /pods/1 => Get details on POD 1
- (r"/api/v1/pods", PodHandler),
- (r"/api/v1/pods/([^/]+)", PodHandler),
+ # GET /api/v1/pods => Get all pods
+ # GET /api/v1/pods/1 => Get details on POD 1
+ (r"/api/v1/pods", PodCLHandler),
+ (r"/api/v1/pods/([^/]+)", PodGURHandler),
# few examples:
# GET /projects
# GET /projects/yardstick
- (r"/api/v1/projects", ProjectHandler),
- (r"/api/v1/projects/([^/]+)", ProjectHandler),
+ (r"/api/v1/projects", ProjectCLHandler),
+ (r"/api/v1/projects/([^/]+)", ProjectGURHandler),
# few examples
# GET /projects/qtip/cases => Get cases for qtip
- #
(r"/api/v1/projects/([^/]+)/cases", TestcaseHandler),
(r"/api/v1/projects/([^/]+)/cases/([^/]+)", TestcaseHandler),
- # (r"/test_cases/([^/]+)", TestCasesHandler),
# new path to avoid a long depth
# GET /results?project=functest&case=keystone.catalog&pod=1
diff --git a/utils/test/result_collection_api/tests/unit/test_base.py b/utils/test/result_collection_api/tests/unit/test_base.py
index 99b1de286..44e42b797 100644
--- a/utils/test/result_collection_api/tests/unit/test_base.py
+++ b/utils/test/result_collection_api/tests/unit/test_base.py
@@ -2,8 +2,10 @@ import json
from tornado.web import Application
from tornado.testing import AsyncHTTPTestCase
-from resources.handlers import VersionHandler, PodHandler, \
- ProjectHandler, TestcaseHandler, TestResultsHandler, DashboardHandler
+from resources.pod_handlers import PodCLHandler, PodGURHandler
+from resources.project_handlers import ProjectCLHandler, ProjectGURHandler
+from resources.handlers import VersionHandler, \
+ TestcaseHandler, TestResultsHandler, DashboardHandler
from resources.models import CreateResponse
import fake_pymongo
@@ -26,10 +28,10 @@ class TestBase(AsyncHTTPTestCase):
return Application(
[
(r"/versions", VersionHandler),
- (r"/api/v1/pods", PodHandler),
- (r"/api/v1/pods/([^/]+)", PodHandler),
- (r"/api/v1/projects", ProjectHandler),
- (r"/api/v1/projects/([^/]+)", ProjectHandler),
+ (r"/api/v1/pods", PodCLHandler),
+ (r"/api/v1/pods/([^/]+)", PodGURHandler),
+ (r"/api/v1/projects", ProjectCLHandler),
+ (r"/api/v1/projects/([^/]+)", ProjectGURHandler),
(r"/api/v1/projects/([^/]+)/cases", TestcaseHandler),
(r"/api/v1/projects/([^/]+)/cases/([^/]+)", TestcaseHandler),
(r"/api/v1/results", TestResultsHandler),
diff --git a/utils/test/result_collection_api/tests/unit/test_pod.py b/utils/test/result_collection_api/tests/unit/test_pod.py
index d7f4c3a63..8a9302738 100644
--- a/utils/test/result_collection_api/tests/unit/test_pod.py
+++ b/utils/test/result_collection_api/tests/unit/test_pod.py
@@ -32,6 +32,18 @@ class TestPodCreate(TestPodBase):
(code, body) = self.create()
self.assertEqual(code, HTTP_BAD_REQUEST)
+ def test_emptyName(self):
+ req_empty = PodCreateRequest('')
+ (code, body) = self.create(req_empty)
+ self.assertEqual(code, HTTP_BAD_REQUEST)
+ self.assertIn('pod name missing', body)
+
+ def test_noneName(self):
+ req_none = PodCreateRequest(None)
+ (code, body) = self.create(req_none)
+ self.assertEqual(code, HTTP_BAD_REQUEST)
+ self.assertIn('pod name missing', body)
+
def test_success(self):
code, body = self.create_d()
self.assertEqual(code, HTTP_OK)
diff --git a/utils/test/result_collection_api/tests/unit/test_project.py b/utils/test/result_collection_api/tests/unit/test_project.py
index c38078098..b07cb7ad6 100644
--- a/utils/test/result_collection_api/tests/unit/test_project.py
+++ b/utils/test/result_collection_api/tests/unit/test_project.py
@@ -30,6 +30,18 @@ class TestProjectCreate(TestProjectBase):
(code, body) = self.create()
self.assertEqual(code, HTTP_BAD_REQUEST)
+ def test_emptyName(self):
+ req_empty = ProjectCreateRequest('')
+ (code, body) = self.create(req_empty)
+ self.assertEqual(code, HTTP_BAD_REQUEST)
+ self.assertIn('project name missing', body)
+
+ def test_noneName(self):
+ req_none = ProjectCreateRequest(None)
+ (code, body) = self.create(req_none)
+ self.assertEqual(code, HTTP_BAD_REQUEST)
+ self.assertIn('project name missing', body)
+
def test_success(self):
(code, body) = self.create_d()
self.assertEqual(code, HTTP_OK)
diff --git a/utils/test/result_collection_api/tornado_swagger_ui/__init__.py b/utils/test/result_collection_api/tornado_swagger_ui/__init__.py
index 49b1b749e..031a4a20e 100644
--- a/utils/test/result_collection_api/tornado_swagger_ui/__init__.py
+++ b/utils/test/result_collection_api/tornado_swagger_ui/__init__.py
@@ -2,4 +2,3 @@
# -*- coding: utf-8 -*-
__author__ = 'serena'
-
diff --git a/utils/test/result_collection_api/tornado_swagger_ui/example/basic.py b/utils/test/result_collection_api/tornado_swagger_ui/example/basic.py
index 1731bfd17..93ff00b43 100644
--- a/utils/test/result_collection_api/tornado_swagger_ui/example/basic.py
+++ b/utils/test/result_collection_api/tornado_swagger_ui/example/basic.py
@@ -22,15 +22,21 @@ class PropertySubclass:
class Item:
"""
@description:
- This is an example of a model class that has parameters in its constructor
- and the fields in the swagger spec are derived from the parameters to __init__.
+ This is an example of a model class that has parameters in its
+ constructor and the fields in the swagger spec are derived from
+ the parameters to __init__.
@notes:
- In this case we would have property1, name as required parameters and property3 as optional parameter.
+ In this case we would have property1, name as required parameters
+ and property3 as optional parameter.
@property property3: Item description
@ptype property3: L{PropertySubclass}
@ptype property4: C{list} of L{PropertySubclass}
"""
- def __init__(self, property1, property2=None, property3=None, property4=None):
+ def __init__(self,
+ property1,
+ property2=None,
+ property3=None,
+ property4=None):
self.property1 = property1
self.property2 = property2
self.property3 = property3
@@ -78,17 +84,17 @@ class GenericApiHandler(RequestHandler):
pass
def prepare(self):
- if not (self.request.method == "GET" or self.request.method == "DELETE"):
- if self.request.headers.get("Content-Type") is not None:
- if self.request.headers["Content-Type"].startswith(DEFAULT_REPRESENTATION):
+ if self.request.method != "GET" and self.request.method != "DELETE":
+ self.json_args = None
+ content_type = self.request.headers.get("Content-Type")
+ if content_type is not None:
+ if content_type.startswith(DEFAULT_REPRESENTATION):
try:
self.json_args = json.loads(self.request.body)
except (ValueError, KeyError, TypeError) as error:
raise HTTPError(HTTP_BAD_REQUEST,
"Bad Json format [{}]".
format(error))
- else:
- self.json_args = None
def finish_request(self, json_object):
self.write(json.dumps(json_object))
@@ -138,7 +144,8 @@ class ItemHandler(GenericApiHandler):
@notes:
get a item,
- This will be added to the Implementation Notes.It lets you put very long text in your api.
+ This will be added to the Implementation Notes.
+ It lets you put very long text in your api.
"""
self.finish_request(items[arg].format_http())
@@ -148,8 +155,6 @@ class ItemHandler(GenericApiHandler):
@description: delete a item
@notes:
delete a item in items
-
- This will be added to the Implementation Notes.It lets you put very long text in your api.
"""
del items[arg]
self.finish_request("success")
@@ -161,8 +166,7 @@ class ItemOptionParamHandler(GenericApiHandler):
"""
@return 200: case is created
"""
- print("ProjectHandler.post: %s -- %s -- %s" % (arg1, arg2, self.request.full_url()))
- fs = open("/home/swagger/tornado-rest-swagger/%s/%s" % (arg1, arg2), "wb")
+ fs = open("/home/%s/%s" % (arg1, arg2), "wb")
fs.write(self.request.body)
self.write("success")
@@ -193,7 +197,7 @@ class ItemQueryHandler(GenericApiHandler):
res.append(value.format_http())
elif value.property2 == property2:
res.append(value.format_http())
- elif items.has_key(property1):
+ elif property1 in items:
if items.get(property1).property2 == property2:
res.append(items.get(property1).format_http())
diff --git a/utils/test/result_collection_api/tornado_swagger_ui/setup.py b/utils/test/result_collection_api/tornado_swagger_ui/setup.py
index 97655917c..57dc48a9a 100644
--- a/utils/test/result_collection_api/tornado_swagger_ui/setup.py
+++ b/utils/test/result_collection_api/tornado_swagger_ui/setup.py
@@ -3,8 +3,8 @@ try:
except ImportError:
from distutils.core import setup
-with open('README') as file:
- long_description = file.read()
+with open('README') as f:
+ long_description = f.read()
setup(name='tornado-swagger',
version='1.0',
@@ -12,20 +12,19 @@ setup(name='tornado-swagger',
zip_safe=False,
packages=['tornado_swagger'],
package_data={
- 'tornado_swagger': [
- 'static/*.*',
- 'static/css/*.*',
- 'static/images/*.*',
- 'static/lib/*.*',
- 'static/lib/shred/*.*',
- ]
+ 'tornado_swagger': [
+ 'static/*.*',
+ 'static/css/*.*',
+ 'static/images/*.*',
+ 'static/lib/*.*',
+ 'static/lib/shred/*.*'
+ ]
},
description='Extract swagger specs from your tornado project',
author='Serena Feng',
license='MIT',
long_description=long_description,
install_requires=[
- 'tornado>=3.1',
- 'epydoc>=0.3.1'
- ],
-)
+ 'tornado>=3.1',
+ 'epydoc>=0.3.1'
+ ])
diff --git a/utils/test/result_collection_api/tornado_swagger_ui/tornado_swagger/__init__.py b/utils/test/result_collection_api/tornado_swagger_ui/tornado_swagger/__init__.py
index 49b1b749e..031a4a20e 100644
--- a/utils/test/result_collection_api/tornado_swagger_ui/tornado_swagger/__init__.py
+++ b/utils/test/result_collection_api/tornado_swagger_ui/tornado_swagger/__init__.py
@@ -2,4 +2,3 @@
# -*- coding: utf-8 -*-
__author__ = 'serena'
-
diff --git a/utils/test/result_collection_api/tornado_swagger_ui/tornado_swagger/handlers.py b/utils/test/result_collection_api/tornado_swagger_ui/tornado_swagger/handlers.py
index 33c4b53be..8bcb9668f 100644
--- a/utils/test/result_collection_api/tornado_swagger_ui/tornado_swagger/handlers.py
+++ b/utils/test/result_collection_api/tornado_swagger_ui/tornado_swagger/handlers.py
@@ -2,8 +2,9 @@
# -*- coding: utf-8 -*-
from tornado.web import URLSpec, StaticFileHandler
-from settings import *
-from views import *
+from settings import default_settings, \
+ SWAGGER_API_DOCS, SWAGGER_API_LIST, SWAGGER_API_SPEC
+from views import SwaggerUIHandler, SwaggerResourcesHandler, SwaggerApiHandler
__author__ = 'serena'
@@ -12,9 +13,27 @@ def swagger_handlers():
prefix = default_settings.get('swagger_prefix', '/swagger')
if prefix[-1] != '/':
prefix += '/'
+
+ def _path(suffix):
+ return prefix + suffix
return [
- URLSpec(prefix + r'spec.html$', SwaggerUIHandler, default_settings, name=URL_SWAGGER_API_DOCS),
- URLSpec(prefix + r'spec.json$', SwaggerResourcesHandler, default_settings, name=URL_SWAGGER_API_LIST),
- URLSpec(prefix + r'spec$', SwaggerApiHandler, default_settings, name=URL_SWAGGER_API_SPEC),
- (prefix + r'(.*\.(css|png|gif|js))', StaticFileHandler, {'path': default_settings.get('static_path')}),
+ URLSpec(
+ _path(r'spec.html$'),
+ SwaggerUIHandler,
+ default_settings,
+ name=SWAGGER_API_DOCS),
+ URLSpec(
+ _path(r'spec.json$'),
+ SwaggerResourcesHandler,
+ default_settings,
+ name=SWAGGER_API_LIST),
+ URLSpec(
+ _path(r'spec$'),
+ SwaggerApiHandler,
+ default_settings,
+ name=SWAGGER_API_SPEC),
+ (
+ _path(r'(.*\.(css|png|gif|js))'),
+ StaticFileHandler,
+ {'path': default_settings.get('static_path')}),
]
diff --git a/utils/test/result_collection_api/tornado_swagger_ui/tornado_swagger/settings.py b/utils/test/result_collection_api/tornado_swagger_ui/tornado_swagger/settings.py
index bd70c179f..8f43c4a96 100644
--- a/utils/test/result_collection_api/tornado_swagger_ui/tornado_swagger/settings.py
+++ b/utils/test/result_collection_api/tornado_swagger_ui/tornado_swagger/settings.py
@@ -6,11 +6,12 @@ __author__ = 'serena'
SWAGGER_VERSION = '1.2'
-URL_SWAGGER_API_DOCS = 'swagger-api-docs'
-URL_SWAGGER_API_LIST = 'swagger-api-list'
-URL_SWAGGER_API_SPEC = 'swagger-api-spec'
+SWAGGER_API_DOCS = 'swagger-api-docs'
+SWAGGER_API_LIST = 'swagger-api-list'
+SWAGGER_API_SPEC = 'swagger-api-spec'
-STATIC_PATH = os.path.join(os.path.dirname(os.path.normpath(__file__)), 'static')
+STATIC_PATH = os.path.join(os.path.dirname(os.path.normpath(__file__)),
+ 'static')
default_settings = {
'base_url': '/',
diff --git a/utils/test/result_collection_api/tornado_swagger_ui/tornado_swagger/swagger.py b/utils/test/result_collection_api/tornado_swagger_ui/tornado_swagger/swagger.py
index 50b2cfe88..b290e058d 100644
--- a/utils/test/result_collection_api/tornado_swagger_ui/tornado_swagger/swagger.py
+++ b/utils/test/result_collection_api/tornado_swagger_ui/tornado_swagger/swagger.py
@@ -128,7 +128,7 @@ class DocParser(object):
if code is None:
self.properties.setdefault(arg, {}).update({
'type': link
- })
+ })
elif code == 'list':
self.properties.setdefault(arg, {}).update({
'type': 'array',
@@ -184,7 +184,7 @@ class model(DocParser):
self.required = []
self.cls = None
- def __call__(self, *args, **kwargs):
+ def __call__(self, *args):
if self.cls:
return self.cls
@@ -206,17 +206,21 @@ class model(DocParser):
argspec.args.remove("self")
defaults = {}
if argspec.defaults:
- defaults = list(zip(argspec.args[-len(argspec.defaults):], argspec.defaults))
+ defaults = list(zip(argspec.args[-len(argspec.defaults):],
+ argspec.defaults))
required_args_count = len(argspec.args) - len(defaults)
for arg in argspec.args[:required_args_count]:
self.required.append(arg)
self.properties.setdefault(arg, {'type': 'string'})
for arg, default in defaults:
- self.properties.setdefault(arg, {'type': 'string', "default": default})
+ self.properties.setdefault(arg, {
+ 'type': 'string',
+ "default": default
+ })
class operation(DocParser):
- def __init__(self, nickname=None, **kwds):
+ def __init__(self, nickname='apis', **kwds):
super(operation, self).__init__()
self.nickname = nickname
self.func = None
@@ -271,5 +275,11 @@ def docs(**opts):
class Application(tornado.web.Application):
- def __init__(self, handlers=None, default_host="", transforms=None, **settings):
- super(Application, self).__init__(swagger_handlers() + handlers, default_host, transforms, **settings)
+ def __init__(self, handlers=None,
+ default_host="",
+ transforms=None,
+ **settings):
+ super(Application, self).__init__(swagger_handlers() + handlers,
+ default_host,
+ transforms,
+ **settings)
diff --git a/utils/test/result_collection_api/tornado_swagger_ui/tornado_swagger/views.py b/utils/test/result_collection_api/tornado_swagger_ui/tornado_swagger/views.py
index 1882f00bf..7624023e8 100644
--- a/utils/test/result_collection_api/tornado_swagger_ui/tornado_swagger/views.py
+++ b/utils/test/result_collection_api/tornado_swagger_ui/tornado_swagger/views.py
@@ -5,13 +5,17 @@ import json
import inspect
import tornado.web
import tornado.template
-from settings import SWAGGER_VERSION, URL_SWAGGER_API_LIST, URL_SWAGGER_API_SPEC, models
+from settings import SWAGGER_VERSION, \
+ SWAGGER_API_LIST, \
+ SWAGGER_API_SPEC
+from settings import models
__author__ = 'serena'
def json_dumps(obj, pretty=False):
- return json.dumps(obj, sort_keys=True, indent=4, separators=(',', ': ')) if pretty else json.dumps(obj)
+ return json.dumps(obj, sort_keys=True, indent=4, separators=(',', ': ')) \
+ if pretty else json.dumps(obj)
class SwaggerUIHandler(tornado.web.RequestHandler):
@@ -22,7 +26,9 @@ class SwaggerUIHandler(tornado.web.RequestHandler):
return self.static_path
def get(self):
- discovery_url = urlparse.urljoin(self.request.full_url(), self.reverse_url(URL_SWAGGER_API_LIST))
+ discovery_url = \
+ urlparse.urljoin(self.request.full_url(),
+ self.reverse_url(SWAGGER_API_LIST))
self.render('index.html', discovery_url=discovery_url)
@@ -41,7 +47,7 @@ class SwaggerResourcesHandler(tornado.web.RequestHandler):
'produces': ["application/json"],
'description': 'Test Api Spec',
'apis': [{
- 'path': self.reverse_url(URL_SWAGGER_API_SPEC),
+ 'path': self.reverse_url(SWAGGER_API_SPEC),
'description': 'Test Api Spec'
}]
}
@@ -60,11 +66,14 @@ class SwaggerApiHandler(tornado.web.RequestHandler):
if apis is None:
raise tornado.web.HTTPError(404)
+ base_path = urlparse.urljoin(self.request.full_url(),
+ self.base_url)[:-1]
specs = {
'apiVersion': self.api_version,
'swaggerVersion': SWAGGER_VERSION,
- 'basePath': urlparse.urljoin(self.request.full_url(), self.base_url)[:-1],
- 'apis': [self.__get_api_spec__(path, spec, operations) for path, spec, operations in apis],
+ 'basePath': base_path,
+ 'apis': [self.__get_api_spec__(path, spec, operations)
+ for path, spec, operations in apis],
'models': self.__get_models_spec(models)
}
self.finish(json_dumps(specs, self.get_arguments('pretty')))
@@ -103,14 +112,19 @@ class SwaggerApiHandler(tornado.web.RequestHandler):
@staticmethod
def find_api(host_handlers):
+ def get_path(url, args):
+ return url % tuple(['{%s}' % arg for arg in args])
+
+ def get_operations(cls):
+ return [member.rest_api
+ for (_, member) in inspect.getmembers(cls)
+ if hasattr(member, 'rest_api')]
+
for host, handlers in host_handlers:
for spec in handlers:
- for (name, member) in inspect.getmembers(spec.handler_class):
- if inspect.ismethod(member) and hasattr(member, 'rest_api'):
- spec_path = spec._path % tuple(['{%s}' % arg for arg in member.rest_api.func_args])
- operations = [member.rest_api for (name, member) in inspect.getmembers(spec.handler_class)
- if hasattr(member, 'rest_api')]
- yield spec_path, spec, operations
+ for (_, mbr) in inspect.getmembers(spec.handler_class):
+ if inspect.ismethod(mbr) and hasattr(mbr, 'rest_api'):
+ path = get_path(spec._path, mbr.rest_api.func_args)
+ operations = get_operations(spec.handler_class)
+ yield path, spec, operations
break
-
-