summaryrefslogtreecommitdiffstats
path: root/result_collection_api
diff options
context:
space:
mode:
Diffstat (limited to 'result_collection_api')
-rw-r--r--result_collection_api/resources/handlers.py204
-rw-r--r--result_collection_api/resources/pod_handlers.py (renamed from result_collection_api/resources/pod_handler.py)58
-rw-r--r--result_collection_api/resources/pod_models.py6
-rw-r--r--result_collection_api/resources/project_handlers.py124
-rw-r--r--result_collection_api/resources/project_models.py34
-rw-r--r--result_collection_api/result_collection_api.py9
-rw-r--r--result_collection_api/tests/unit/test_base.py9
-rw-r--r--result_collection_api/tests/unit/test_project.py12
8 files changed, 241 insertions, 215 deletions
diff --git a/result_collection_api/resources/handlers.py b/result_collection_api/resources/handlers.py
index afee1cd..3f9d842 100644
--- a/result_collection_api/resources/handlers.py
+++ b/result_collection_api/resources/handlers.py
@@ -25,7 +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 common.constants import DEFAULT_REPRESENTATION, HTTP_BAD_REQUEST, \
HTTP_NOT_FOUND, HTTP_FORBIDDEN
from common.config import prepare_put_request
@@ -39,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":
@@ -60,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:
@@ -75,32 +69,57 @@ class GenericApiHandler(RequestHandler):
@asynchronous
@gen.coroutine
- def _create(self, table, data, mark):
+ def _create(self, error):
+ if self.json_args is None:
+ 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]))
+
+ exist_data = yield self._eval_db(self.table, 'find_one',
+ {"name": name})
+ if exist_data is not None:
+ raise HTTPError(HTTP_FORBIDDEN,
+ error.format(name, self.table[:-1]))
data.creation_date = datetime.now()
- _id = yield self._eval_db(table, 'insert', data.format())
- if mark is None:
- mark = _id
- self.finish_request(self._create_response(mark))
+ yield self._eval_db(self.table, 'insert', data.format())
+ self.finish_request(self._create_response(name))
@asynchronous
@gen.coroutine
- def _list(self, table, format_cls, query=None):
+ def _list(self, query=None):
if query is None:
query = {}
res = []
- cursor = self._eval_db(table, 'find', query)
+ cursor = self._eval_db(self.table, 'find', query)
while (yield cursor.fetch_next):
- res.append(format_data(cursor.next_object(), format_cls))
- self.finish_request({table: res})
+ res.append(format_data(cursor.next_object(), self.table_cls))
+ self.finish_request({self.table: res})
+
+ @asynchronous
+ @gen.coroutine
+ 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 _get_one(self, table, format_cls, query):
- data = yield self._eval_db(table, 'find_one', query)
+ def _delete(self, query):
+ data = yield self._eval_db(self.table, 'find_one', query)
if data is None:
raise HTTPError(HTTP_NOT_FOUND,
- "{} Not Exist".format(query))
- self.finish_request(format_data(data, format_cls))
+ "[{}] not exit in table [{}]"
+ .format(query, self.table))
+
+ yield self._eval_db(self.table, 'remove', query)
+ self.finish_request()
def _eval_db(self, table, method, param):
return eval('self.db.%s.%s(param)' % (table, method))
@@ -112,143 +131,6 @@ class VersionHandler(GenericApiHandler):
self.finish_request([{'v1': 'basics'}])
-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)
-
- @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))
-
- @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:
- 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({'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}
-
- # 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))
-
- # just delete it, or maybe save it elsewhere in a future
- yield self.db.projects.remove(query)
-
- self.finish_request()
-
-
class TestcaseHandler(GenericApiHandler):
"""
TestCasesHandler Class
diff --git a/result_collection_api/resources/pod_handler.py b/result_collection_api/resources/pod_handlers.py
index 7189967..590ae5b 100644
--- a/result_collection_api/resources/pod_handler.py
+++ b/result_collection_api/resources/pod_handlers.py
@@ -1,70 +1,56 @@
from tornado import gen
-from tornado.web import HTTPError, asynchronous
+from tornado.web import asynchronous
from tornado_swagger_ui.tornado_swagger import swagger
from handlers import GenericApiHandler
-from common.constants import HTTP_BAD_REQUEST, HTTP_FORBIDDEN
from pod_models import Pod
-class PodCLHandler(GenericApiHandler):
- def initialize(self):
- super(PodCLHandler, self).initialize()
+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
+ @description: list all pods
@return 200: list all pods, empty list is no pod exist
@rtype: L{Pods}
"""
- self._list('pods', Pod)
+ self._list()
- # @asynchronous
@gen.coroutine
@swagger.operation(nickname='create')
def post(self):
"""
- @description: Create a POD
- @param body: pod information to be created
+ @description: create a pod
+ @param body: pod to be created
@type body: L{PodCreateRequest}
@in body: body
- @return 200: pod is created.
@rtype: L{Pod}
- @raise 403: already exists as a pod
- @raise 400: bad request
+ @return 200: pod is created.
+ @raise 403: pod already exists
+ @raise 400: post without body
"""
- if self.json_args is None:
- raise HTTPError(HTTP_BAD_REQUEST, 'no payload')
-
- pod = Pod.from_dict(self.json_args)
- name = pod.name
- if name is None or name == '':
- raise HTTPError(HTTP_BAD_REQUEST, 'pod name missing')
+ self._create('{} already exists as a {}')
- the_pod = yield self.db.pods.find_one({'name': name})
- if the_pod is not None:
- raise HTTPError(HTTP_FORBIDDEN,
- "{} already exists as a pod".format(
- self.json_args.get("name")))
- self._create('pods', pod, name)
-
-
-class PodGURHandler(GenericApiHandler):
- def initialize(self):
- super(PodGURHandler, self).initialize()
+class PodGURHandler(GenericPodHandler):
@swagger.operation(nickname='get-one')
- def get(self, pod_name=None):
+ def get(self, pod_name):
"""
- @description: Get a single pod by pod_name
+ @description: get a single pod by pod_name
+ @rtype: L{Pod}
@return 200: pod exist
@raise 404: pod not exist
- @rtype: L{Pod}
"""
query = dict()
- query["name"] = pod_name
- self._get_one('pods', Pod, query)
+ query['name'] = pod_name
+ self._get_one(query)
@asynchronous
@gen.coroutine
diff --git a/result_collection_api/resources/pod_models.py b/result_collection_api/resources/pod_models.py
index fcb4ddb..cc98c90 100644
--- a/result_collection_api/resources/pod_models.py
+++ b/result_collection_api/resources/pod_models.py
@@ -27,9 +27,9 @@ 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
diff --git a/result_collection_api/resources/project_handlers.py b/result_collection_api/resources/project_handlers.py
new file mode 100644
index 0000000..69ce3b5
--- /dev/null
+++ b/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/result_collection_api/resources/project_models.py b/result_collection_api/resources/project_models.py
index 895fc3e..a8f8309 100644
--- a/result_collection_api/resources/project_models.py
+++ b/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/result_collection_api/result_collection_api.py b/result_collection_api/result_collection_api.py
index afd66f3..344e0d7 100644
--- a/result_collection_api/result_collection_api.py
+++ b/result_collection_api/result_collection_api.py
@@ -35,8 +35,9 @@ import tornado.ioloop
import motor
from resources.handlers import VersionHandler, \
- ProjectHandler, TestcaseHandler, TestResultsHandler, DashboardHandler
-from resources.pod_handler import PodCLHandler, PodGURHandler
+ 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
@@ -67,8 +68,8 @@ def make_app():
# 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
diff --git a/result_collection_api/tests/unit/test_base.py b/result_collection_api/tests/unit/test_base.py
index 16ed07c..44e42b7 100644
--- a/result_collection_api/tests/unit/test_base.py
+++ b/result_collection_api/tests/unit/test_base.py
@@ -2,9 +2,10 @@ import json
from tornado.web import Application
from tornado.testing import AsyncHTTPTestCase
-from resources.pod_handler import PodCLHandler, PodGURHandler
+from resources.pod_handlers import PodCLHandler, PodGURHandler
+from resources.project_handlers import ProjectCLHandler, ProjectGURHandler
from resources.handlers import VersionHandler, \
- ProjectHandler, TestcaseHandler, TestResultsHandler, DashboardHandler
+ TestcaseHandler, TestResultsHandler, DashboardHandler
from resources.models import CreateResponse
import fake_pymongo
@@ -29,8 +30,8 @@ class TestBase(AsyncHTTPTestCase):
(r"/versions", VersionHandler),
(r"/api/v1/pods", PodCLHandler),
(r"/api/v1/pods/([^/]+)", PodGURHandler),
- (r"/api/v1/projects", ProjectHandler),
- (r"/api/v1/projects/([^/]+)", ProjectHandler),
+ (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/result_collection_api/tests/unit/test_project.py b/result_collection_api/tests/unit/test_project.py
index c380780..b07cb7a 100644
--- a/result_collection_api/tests/unit/test_project.py
+++ b/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)