]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
mgr/dashboard: restcontroller: removed proxy methods
authorRicardo Dias <rdias@suse.com>
Tue, 24 Apr 2018 16:30:09 +0000 (17:30 +0100)
committerRicardo Dias <rdias@suse.com>
Thu, 24 May 2018 09:40:27 +0000 (10:40 +0100)
Now the dispatcher will call directly the RESTController methods:
list, create, delete, set, etc...

Signed-off-by: Ricardo Dias <rdias@suse.com>
src/pybind/mgr/dashboard/controllers/__init__.py
src/pybind/mgr/dashboard/controllers/pool.py
src/pybind/mgr/dashboard/tests/test_tools.py

index 60c5090b822a84df468100c6ebe051235059f271..019bff55722d8a945d0da4af74b819312283e6b3 100644 (file)
@@ -486,72 +486,63 @@ class RESTController(BaseController):
                     attr != '_collection' and attr != '_element':
                 result.append(([], attr, attr, cls._parse_function_args(val)))
 
-        methods = []
         for k, v in cls._method_mapping.items():
-            if not k[1] and hasattr(cls, v[0]):
-                methods.append(k[0])
-        if methods:
-            result.append((methods, None, '_collection', []))
-        methods = []
+            func = getattr(cls, v[0], None)
+            if not k[1] and func:
+                if k[0] != 'PATCH':  # we already wrapped in PUT
+                    wrapper = cls._rest_request_wrapper(func, v[1])
+                    setattr(cls, v[0], wrapper)
+                else:
+                    wrapper = func
+                result.append(([k[0]], None, v[0], []))
+
         args = []
         for k, v in cls._method_mapping.items():
-            if k[1] and hasattr(cls, v[0]):
-                methods.append(k[0])
+            func = getattr(cls, v[0], None)
+            if k[1] and func:
+                if k[0] != 'PATCH':  # we already wrapped in PUT
+                    wrapper = cls._rest_request_wrapper(func, v[1])
+                    setattr(cls, v[0], wrapper)
+                else:
+                    wrapper = func
                 if not args:
                     if cls.RESOURCE_ID is None:
-                        args = cls._parse_function_args(getattr(cls, v[0]))
+                        args = cls._parse_function_args(func)
                     else:
                         args = cls.RESOURCE_ID.split('/')
-        if methods:
-            result.append((methods, None, '_element', args))
+                result.append(([k[0]], None, v[0], args))
 
         for attr, val in inspect.getmembers(cls, predicate=callable):
             if hasattr(val, '_collection_method_'):
+                wrapper = cls._rest_request_wrapper(val, 200)
+                setattr(cls, attr, wrapper)
                 result.append(
-                    (val._collection_method_, attr, '_handle_detail_method', []))
+                    (val._collection_method_, attr, attr, []))
 
         for attr, val in inspect.getmembers(cls, predicate=callable):
             if hasattr(val, '_resource_method_'):
+                wrapper = cls._rest_request_wrapper(val, 200)
+                setattr(cls, attr, wrapper)
                 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', []))
+                    (val._resource_method_, url_suffix, attr, []))
 
         return result
 
-    @cherrypy.expose
-    def _collection(self, *vpath, **params):
-        return self._rest_request(False, *vpath, **params)
-
-    @cherrypy.expose
-    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)]
-        method = getattr(self, method_name, None)
-
-        if cherrypy.request.method not in ['GET', 'DELETE']:
-            method = RESTController._takes_json(method)
+    @classmethod
+    def _rest_request_wrapper(cls, func, status_code):
+        def wrapper(*vpath, **params):
+            method = func
+            if cherrypy.request.method not in ['GET', 'DELETE']:
+                method = RESTController._takes_json(method)
 
-        method = RESTController._returns_json(method)
+            method = RESTController._returns_json(method)
 
-        cherrypy.response.status = status_code
+            cherrypy.response.status = status_code
 
-        return method(*vpath, **params)
+            return method(*vpath, **params)
+        return wrapper
 
     @staticmethod
     def _function_args(func):
@@ -589,6 +580,9 @@ class RESTController(BaseController):
 
     @staticmethod
     def resource(methods=None):
+        if not methods:
+            methods = ['GET']
+
         def _wrapper(func):
             func._resource_method_ = methods
             return func
@@ -596,6 +590,9 @@ class RESTController(BaseController):
 
     @staticmethod
     def collection(methods=None):
+        if not methods:
+            methods = ['GET']
+
         def _wrapper(func):
             func._collection_method_ = methods
             return func
index b9719834347d830bc01c8f09fe268d2bf8421e56..402225ad88098ce7ef2736042e5ea41bdadd8acb 100644 (file)
@@ -43,7 +43,7 @@ class Pool(RESTController):
             return var
         return var.lower() in ("true", "yes", "1", 1)
 
-    def list(self, attrs=None, stats=False):
+    def _pool_list(self, attrs=None, stats=False):
         if attrs:
             attrs = attrs.split(',')
 
@@ -54,8 +54,11 @@ class Pool(RESTController):
 
         return [self._serialize_pool(pool, attrs) for pool in pools]
 
+    def list(self, attrs=None, stats=False):
+        return self._pool_list(attrs, stats)
+
     def get(self, pool_name, attrs=None, stats=False):
-        pools = self.list(attrs, stats)
+        pools = self._pool_list(attrs, stats)
         pool = [pool for pool in pools if pool['pool_name'] == pool_name]
         if not pool:
             return cherrypy.NotFound('No such pool')
@@ -103,7 +106,7 @@ class Pool(RESTController):
                     if o['name'] == conf_name][0]
 
         return {
-            "pool_names": [p['pool_name'] for p in self.list()],
+            "pool_names": [p['pool_name'] for p in self._pool_list()],
             "crush_rules_replicated": rules(1),
             "crush_rules_erasure": rules(3),
             "is_all_bluestore": all_bluestore(),
index b45e16913d58e0d2538c5442d211fc842d6c3e64..72e6dc0bbb75038ae839cc8b28c8c51aaf5e7eb8 100644 (file)
@@ -137,19 +137,19 @@ class RESTControllerTest(ControllerTestCase):
         self._post('/foo/1/detail', 'post-data')
         self.assertStatus(404)
 
-    def test_developer_page(self):
-        self.getPage('/foo', headers=[('Accept', 'text/html')])
-        self.assertIn('<p>GET', self.body.decode('utf-8'))
-        self.assertIn('Content-Type: text/html', self.body.decode('utf-8'))
-        self.assertIn('<form action="/api/foo/" method="post">', self.body.decode('utf-8'))
-        self.assertIn('<input type="hidden" name="_method" value="post" />',
-                      self.body.decode('utf-8'))
-
-    def test_developer_exception_page(self):
-        self.getPage('/foo',
-                     headers=[('Accept', 'text/html'), ('Content-Length', '0')],
-                     method='put')
-        self.assertStatus(404)
+    def test_developer_page(self):
+        self.getPage('/foo', headers=[('Accept', 'text/html')])
+        self.assertIn('<p>GET', self.body.decode('utf-8'))
+        self.assertIn('Content-Type: text/html', self.body.decode('utf-8'))
+        self.assertIn('<form action="/api/foo/" method="post">', self.body.decode('utf-8'))
+        self.assertIn('<input type="hidden" name="_method" value="post" />',
+                      self.body.decode('utf-8'))
+
+    def test_developer_exception_page(self):
+        self.getPage('/foo',
+                     headers=[('Accept', 'text/html'), ('Content-Length', '0')],
+                     method='put')
+        self.assertStatus(404)
 
     def test_create_form(self):
         self.getPage('/fooargs', headers=[('Accept', 'text/html')])