swagger-ize pod-apis of testAPI 17/14717/2
authorSerenaFeng <feng.xiaowei@zte.com.cn>
Thu, 26 May 2016 10:07:35 +0000 (18:07 +0800)
committerSerenaFeng <feng.xiaowei@zte.com.cn>
Thu, 26 May 2016 10:17:41 +0000 (18:17 +0800)
JIRA: FUNCTEST-263

Change-Id: I293e05f565f882ea39bbf6368405f10241269716
Signed-off-by: SerenaFeng <feng.xiaowei@zte.com.cn>
utils/test/result_collection_api/resources/handlers.py
utils/test/result_collection_api/resources/pod_handler.py [new file with mode: 0644]
utils/test/result_collection_api/resources/pod_models.py
utils/test/result_collection_api/result_collection_api.py
utils/test/result_collection_api/tests/unit/test_base.py
utils/test/result_collection_api/tests/unit/test_pod.py

index 4353343..afee1cd 100644 (file)
@@ -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
@@ -24,7 +26,6 @@ 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
@@ -72,95 +73,43 @@ 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)
+    def _create(self, table, data, mark):
+        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))
 
     @asynchronous
     @gen.coroutine
-    def post(self):
-        """ Create a POD"""
-
-        if self.json_args is None:
-            raise HTTPError(HTTP_BAD_REQUEST)
-
-        query = {"name": self.json_args.get("name")}
-
-        # check for existing name in db
-        the_pod = yield self.db.pods.find_one(query)
-        if the_pod 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))
+    def _list(self, table, format_cls, query=None):
+        if query is None:
+            query = {}
+        res = []
+        cursor = self._eval_db(table, 'find', query)
+        while (yield cursor.fetch_next):
+            res.append(format_data(cursor.next_object(), format_cls))
+        self.finish_request({table: res})
 
     @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:
+    def _get_one(self, table, format_cls, query):
+        data = yield self._eval_db(table, 'find_one', query)
+        if data is None:
             raise HTTPError(HTTP_NOT_FOUND,
-                            "{} could not be found as a pod to be deleted"
-                            .format(pod_name))
+                            "{} Not Exist".format(query))
+        self.finish_request(format_data(data, format_cls))
 
-        # just delete it, or maybe save it elsewhere in a future
-        res = yield self.db.projects.remove(
-            {'name': pod_name})
+    def _eval_db(self, table, method, param):
+        return eval('self.db.%s.%s(param)' % (table, method))
 
-        self.finish_request(answer)
-        """
-        pass
+
+class VersionHandler(GenericApiHandler):
+    """ Display a message for the API version """
+    def get(self):
+        self.finish_request([{'v1': 'basics'}])
 
 
 class ProjectHandler(GenericApiHandler):
diff --git a/utils/test/result_collection_api/resources/pod_handler.py b/utils/test/result_collection_api/resources/pod_handler.py
new file mode 100644 (file)
index 0000000..7189967
--- /dev/null
@@ -0,0 +1,89 @@
+from tornado import gen
+from tornado.web import HTTPError, 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()
+
+    @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('pods', Pod)
+
+    # @asynchronous
+    @gen.coroutine
+    @swagger.operation(nickname='create')
+    def post(self):
+        """
+            @description: Create a POD
+            @param body: pod information 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
+        """
+        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')
+
+        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()
+
+    @swagger.operation(nickname='get-one')
+    def get(self, pod_name=None):
+        """
+            @description: Get a single pod by pod_name
+            @return 200: pod exist
+            @raise 404: pod not exist
+            @rtype: L{Pod}
+        """
+        query = dict()
+        query["name"] = pod_name
+        self._get_one('pods', Pod, 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
index b02e3c2..fcb4ddb 100644 (file)
@@ -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,6 +25,7 @@ class PodCreateRequest(object):
         }
 
 
+@swagger.model()
 class Pod(PodCreateRequest):
     """ describes a POD platform """
     def __init__(self, name='', mode='', details='', role="",
@@ -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
 
index 97aa58c..afd66f3 100644 (file)
@@ -29,14 +29,16 @@ TODOs :
 
 """
 
+import argparse
+
 import tornado.ioloop
 import motor
-import argparse
 
-from resources.handlers import VersionHandler, PodHandler, \
+from resources.handlers import VersionHandler, \
     ProjectHandler, TestcaseHandler, TestResultsHandler, DashboardHandler
+from resources.pod_handler import PodCLHandler, PodGURHandler
 from common.config import APIConfig
-
+from tornado_swagger_ui.tornado_swagger import swagger
 
 # optionally get config file from command line
 parser = argparse.ArgumentParser()
@@ -51,16 +53,16 @@ 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
@@ -70,10 +72,8 @@ def make_app():
 
             # 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
index 99b1de2..16ed07c 100644 (file)
@@ -2,7 +2,8 @@ import json
 from tornado.web import Application
 from tornado.testing import AsyncHTTPTestCase
 
-from resources.handlers import VersionHandler, PodHandler, \
+from resources.pod_handler import PodCLHandler, PodGURHandler
+from resources.handlers import VersionHandler, \
     ProjectHandler, TestcaseHandler, TestResultsHandler, DashboardHandler
 from resources.models import CreateResponse
 import fake_pymongo
@@ -26,8 +27,8 @@ class TestBase(AsyncHTTPTestCase):
         return Application(
             [
                 (r"/versions", VersionHandler),
-                (r"/api/v1/pods", PodHandler),
-                (r"/api/v1/pods/([^/]+)", PodHandler),
+                (r"/api/v1/pods", PodCLHandler),
+                (r"/api/v1/pods/([^/]+)", PodGURHandler),
                 (r"/api/v1/projects", ProjectHandler),
                 (r"/api/v1/projects/([^/]+)", ProjectHandler),
                 (r"/api/v1/projects/([^/]+)/cases", TestcaseHandler),
index d7f4c3a..8a93027 100644 (file)
@@ -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)