]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
mgr/dashboard: restcontroller: support for detail methods
authorRicardo Dias <rdias@suse.com>
Wed, 11 Apr 2018 11:43:22 +0000 (12:43 +0100)
committerRicardo Dias <rdias@suse.com>
Fri, 13 Apr 2018 14:58:48 +0000 (15:58 +0100)
Signed-off-by: Ricardo Dias <rdias@suse.com>
src/pybind/mgr/dashboard/controllers/__init__.py
src/pybind/mgr/dashboard/tests/test_rest_tasks.py

index 7c36866c246298b19b3a7eabc1d72d663526384b..2cecd02a26ffec5da9341cdb0163c5fe6fd342b4 100644 (file)
@@ -428,6 +428,7 @@ class RESTController(BaseController):
 
     @classmethod
     def endpoints(cls):
+        # pylint: disable=too-many-branches
 
         def isfunction(m):
             return inspect.isfunction(m) or inspect.ismethod(m)
@@ -454,6 +455,18 @@ class RESTController(BaseController):
         if methods:
             result.append((methods, None, '_element', args))
 
+        for attr, val in inspect.getmembers(cls, predicate=isfunction):
+            if hasattr(val, '_collection_method_'):
+                result.append(
+                    (val._collection_method_, attr, '_handle_detail_method', []))
+
+        for attr, val in inspect.getmembers(cls, predicate=isfunction):
+            if hasattr(val, '_resource_method_'):
+                res_params = [":{}".format(arg) for arg in args]
+                url_suffix = "{}/{}".format("/".join(res_params), attr)
+                result.append(
+                    (val._resource_method_, url_suffix, '_handle_detail_method', []))
+
         return result
 
     @cherrypy.expose
@@ -464,6 +477,18 @@ class RESTController(BaseController):
     def _element(self, *vpath, **params):
         return self._rest_request(True, *vpath, **params)
 
+    def _handle_detail_method(self, *vpath, **params):
+        method = getattr(self, cherrypy.request.path_info.split('/')[-1])
+
+        if cherrypy.request.method not in ['GET', 'DELETE']:
+            method = RESTController._takes_json(method)
+
+        method = RESTController._returns_json(method)
+
+        cherrypy.response.status = 200
+
+        return method(*vpath, **params)
+
     def _rest_request(self, is_element, *vpath, **params):
         method_name, status_code = self._method_mapping[
             (cherrypy.request.method, is_element)]
@@ -526,3 +551,17 @@ class RESTController(BaseController):
             ret = func(*args, **kwargs)
             return json.dumps(ret).encode('utf8')
         return inner
+
+    @staticmethod
+    def resource(methods=None):
+        def _wrapper(func):
+            func._resource_method_ = methods
+            return func
+        return _wrapper
+
+    @staticmethod
+    def collection(methods=None):
+        def _wrapper(func):
+            func._collection_method_ = methods
+            return func
+        return _wrapper
index 1811902c530099f0061b7f2b7288b020a0f9d296..6f8f500f016e0c4fe28dc77ea11ea688ad415a6d 100644 (file)
@@ -31,6 +31,18 @@ class TaskTest(RESTController):
         # pylint: disable=unused-argument
         time.sleep(TaskTest.sleep_time)
 
+    @Task('task/foo', ['{param}'])
+    @RESTController.collection(['POST'])
+    @RESTController.args_from_json
+    def foo(self, param):
+        return {'my_param': param}
+
+    @Task('task/bar', ['{key}', '{param}'])
+    @RESTController.resource(['PUT'])
+    @RESTController.args_from_json
+    def bar(self, key, param=None):
+        return {'my_param': param, 'key': key}
+
 
 class TaskControllerTest(ControllerTestCase):
     @classmethod
@@ -59,3 +71,11 @@ class TaskControllerTest(ControllerTestCase):
 
     def test_delete_task(self):
         self._task_delete('/test/task/hello')
+
+    def test_foo_task(self):
+        self._task_post('/test/task/foo', {'param': 'hello'})
+        self.assertJsonBody({'my_param': 'hello'})
+
+    def test_bar_task(self):
+        self._task_put('/test/task/3/bar', {'param': 'hello'})
+        self.assertJsonBody({'my_param': 'hello', 'key': '3'})