]> git.apps.os.sepia.ceph.com Git - ceph-ci.git/commitdiff
mgr/dashboard_v2: Renamed/moved RESTResource to RESTController
authorRicardo Dias <rdias@suse.com>
Thu, 25 Jan 2018 14:28:04 +0000 (14:28 +0000)
committerRicardo Dias <rdias@suse.com>
Mon, 5 Mar 2018 13:07:00 +0000 (13:07 +0000)
Signed-off-by: Ricardo Dias <rdias@suse.com>
src/pybind/mgr/dashboard_v2/README.rst
src/pybind/mgr/dashboard_v2/controllers/auth.py
src/pybind/mgr/dashboard_v2/controllers/ping.py
src/pybind/mgr/dashboard_v2/restresource.py [deleted file]
src/pybind/mgr/dashboard_v2/tools.py

index 1b9853835f7c7b11e49e10c84b7e5366817c23ed..5c85e8a636f6281cd60c60d3a65cbc70a19c345f 100644 (file)
@@ -116,17 +116,16 @@ Reload the dashboard plugin, and then you can access the above controller
 from the web browser using the URL http://mgr_hostname:8080/api/ping2
 
 We also provide a simple mechanism to create REST based controllers using the
-``RESTResource`` class.
+``RESTController`` class.
 
 For example, we can adapt the above controller to return JSON when accessing
 the endpoint with a GET request::
 
   import cherrypy
-  from ..restresource import RESTResource
-  from ..tools import ApiController
+  from ..tools import ApiController, RESTController
 
   @ApiController('ping2')
-  class Ping2(RESTResource):
+  class Ping2(RESTController):
     def list(self):
       return {"msg": "Hello"}
 
@@ -140,12 +139,11 @@ add the ``AuthRequired`` decorator to your controller class.
 Example::
 
   import cherrypy
-  from ..restresource import RESTResource
-  from ..tools import ApiController, AuthRequired
+  from ..tools import ApiController, AuthRequired, RESTController
 
   @ApiController('ping2')
-  @AuthRequired
-  class Ping2(RESTResource):
+  @AuthRequired()
+  class Ping2(RESTController):
     def list(self):
       return {"msg": "Hello"}
 
index 7b0263ece05d4519f45a07fa9ae9afd65b4683ac..7ce3f87899ce6c5fc6f6289d29c3ae9688a6e3c9 100644 (file)
@@ -6,12 +6,11 @@ import cherrypy
 import time
 import sys
 
-from ..restresource import RESTResource
-from ..tools import ApiController, AuthRequired
+from ..tools import ApiController, AuthRequired, RESTController
 
 
 @ApiController('auth')
-class Auth(RESTResource):
+class Auth(RESTController):
     """
     Provide login and logout actions.
 
@@ -34,7 +33,7 @@ class Auth(RESTResource):
         self._mod = Auth._mgr_module_
         self._log = self._mod.log
 
-    @RESTResource.args_from_json
+    @RESTController.args_from_json
     def create(self, username, password):
         now = time.time()
         config_username = self._mod.get_localized_config('username', None)
index f3d96d85700e958dfbc1498f52b21173e767235c..28ef35cd50462727463bba02dd2491aef4b1602f 100644 (file)
@@ -3,8 +3,7 @@ from __future__ import absolute_import
 
 import cherrypy
 
-from ..restresource import RESTResource
-from ..tools import ApiController, AuthRequired
+from ..tools import ApiController, AuthRequired, RESTController
 
 
 @ApiController('ping')
@@ -16,13 +15,13 @@ class Ping(object):
 
 
 @ApiController('echo1')
-class EchoArgs(RESTResource):
-    @RESTResource.args_from_json
+class EchoArgs(RESTController):
+    @RESTController.args_from_json
     def create(self, msg):
         return {'echo': msg}
 
 
 @ApiController('echo2')
-class Echo(RESTResource):
+class Echo(RESTController):
     def create(self, data):
         return {'echo': data['msg']}
diff --git a/src/pybind/mgr/dashboard_v2/restresource.py b/src/pybind/mgr/dashboard_v2/restresource.py
deleted file mode 100644 (file)
index 95bb9a4..0000000
+++ /dev/null
@@ -1,121 +0,0 @@
-# -*- coding: utf-8 -*-
-import inspect
-import json
-
-import cherrypy
-
-
-def _takes_json(func):
-    def inner(*args, **kwargs):
-        content_length = int(cherrypy.request.headers['Content-Length'])
-        body = cherrypy.request.body.read(content_length)
-        if not body:
-            raise cherrypy.HTTPError(400, 'Empty body. Content-Length={}'
-                                          .format(content_length))
-        try:
-            data = json.loads(body.decode('utf-8'))
-        except Exception as e:
-            raise cherrypy.HTTPError(400, 'Failed to decode JSON: {}'
-                                          .format(str(e)))
-        if hasattr(func, '_args_from_json_'):
-            f_args = inspect.getargspec(func).args
-            n_args = []
-            for arg in args:
-                n_args.append(arg)
-            for arg in f_args[1:]:
-                if arg in data:
-                    n_args.append(data[arg])
-                    data.pop(arg)
-            kwargs.update(data)
-            return func(*n_args, **kwargs)
-        else:
-            return func(data, *args, **kwargs)
-    return inner
-
-
-def _returns_json(func):
-    def inner(*args, **kwargs):
-        cherrypy.serving.response.headers['Content-Type'] = 'application/json'
-        ret = func(*args, **kwargs)
-        return json.dumps(ret).encode('utf8')
-    return inner
-
-
-def json_error_page(status, message, traceback, version):
-    return json.dumps(dict(status=status, detail=message, traceback=traceback,
-                           version=version))
-
-
-class RESTResource(object):
-    """
-    Base class for providing a RESTful interface to a resource.
-
-    To use this class, simply derive a class from it and implement the methods
-    you want to support.  The list of possible methods are:
-
-    * list()
-    * bulk_set(data)
-    * create(data)
-    * bulk_delete()
-    * get(key)
-    * set(data, key)
-    * delete(key)
-
-    Test with curl:
-
-    curl -H "Content-Type: application/json" -X POST \
-         -d '{"username":"xyz","password":"xyz"}'  http://127.0.0.1:8080/foo
-    curl http://127.0.0.1:8080/foo
-    curl http://127.0.0.1:8080/foo/0
-
-    """
-
-    _cp_config = {
-        'request.error_page': {'default': json_error_page},
-    }
-
-    def _not_implemented(self, is_element):
-        methods = [method
-                   for ((method, _is_element), (meth, _))
-                   in self._method_mapping.items()
-                   if _is_element == is_element and hasattr(self, meth)]
-        cherrypy.response.headers['Allow'] = ','.join(methods)
-        raise cherrypy.HTTPError(405, 'Method not implemented.')
-
-    _method_mapping = {
-        ('GET', False): ('list', 200),
-        ('PUT', False): ('bulk_set', 200),
-        ('PATCH', False): ('bulk_set', 200),
-        ('POST', False): ('create', 201),
-        ('DELETE', False): ('bulk_delete', 204),
-        ('GET', True): ('get', 200),
-        ('PUT', True): ('set', 200),
-        ('PATCH', True): ('set', 200),
-        ('DELETE', True): ('delete', 204),
-    }
-
-    @cherrypy.expose
-    def default(self, *vpath, **params):
-        cherrypy.config.update({'error_page.default': json_error_page})
-        is_element = len(vpath) > 0
-
-        (method_name, status_code) = self._method_mapping[
-                (cherrypy.request.method, is_element)]
-        method = getattr(self, method_name, None)
-        if not method:
-            self._not_implemented(is_element)
-
-        if cherrypy.request.method not in ['GET', 'DELETE']:
-            method = _takes_json(method)
-
-        if cherrypy.request.method != 'DELETE':
-            method = _returns_json(method)
-
-        cherrypy.response.status = status_code
-
-        return method(*vpath, **params)
-
-    @staticmethod
-    def args_from_json(func):
-        func._args_from_json_ = True
-        return func
index 043eb0c035046e2b20bfc2d85f19683965d19c5f..a27b995e6f8a2e5c5db0eec1ddc891015d512015 100644 (file)
@@ -2,10 +2,14 @@
 from __future__ import absolute_import
 
 import importlib
+import inspect
+import json
 import os
 import pkgutil
 import sys
 
+import cherrypy
+
 
 def ApiController(path):
     def decorate(cls):
@@ -64,3 +68,121 @@ def load_controller(mgrmodule, cls):
         if ctrl.__name__ == cls:
             return ctrl
     raise Exception("Controller class '{}' not found".format(cls))
+
+
+def _json_error_page(status, message, traceback, version):
+    return json.dumps(dict(status=status, detail=message, traceback=traceback,
+                           version=version))
+
+
+class RESTController(object):
+    """
+    Base class for providing a RESTful interface to a resource.
+
+    To use this class, simply derive a class from it and implement the methods
+    you want to support.  The list of possible methods are:
+
+    * list()
+    * bulk_set(data)
+    * create(data)
+    * bulk_delete()
+    * get(key)
+    * set(data, key)
+    * delete(key)
+
+    Test with curl:
+
+    curl -H "Content-Type: application/json" -X POST \
+         -d '{"username":"xyz","password":"xyz"}'  http://127.0.0.1:8080/foo
+    curl http://127.0.0.1:8080/foo
+    curl http://127.0.0.1:8080/foo/0
+
+    """
+
+    _cp_config = {
+        'request.error_page': {'default': _json_error_page},
+    }
+
+    def _not_implemented(self, is_element):
+        methods = [method
+                   for ((method, _is_element), (meth, _))
+                   in self._method_mapping.items()
+                   if _is_element == is_element and hasattr(self, meth)]
+        cherrypy.response.headers['Allow'] = ','.join(methods)
+        raise cherrypy.HTTPError(405, 'Method not implemented.')
+
+    _method_mapping = {
+        ('GET', False): ('list', 200),
+        ('PUT', False): ('bulk_set', 200),
+        ('PATCH', False): ('bulk_set', 200),
+        ('POST', False): ('create', 201),
+        ('DELETE', False): ('bulk_delete', 204),
+        ('GET', True): ('get', 200),
+        ('PUT', True): ('set', 200),
+        ('PATCH', True): ('set', 200),
+        ('DELETE', True): ('delete', 204),
+    }
+
+    @cherrypy.expose
+    def default(self, *vpath, **params):
+        cherrypy.config.update({
+            'error_page.default': _json_error_page})
+        is_element = len(vpath) > 0
+
+        (method_name, status_code) = self._method_mapping[
+                (cherrypy.request.method, is_element)]
+        method = getattr(self, method_name, None)
+        if not method:
+            self._not_implemented(is_element)
+
+        if cherrypy.request.method not in ['GET', 'DELETE']:
+            method = RESTController._takes_json(method)
+
+        if cherrypy.request.method != 'DELETE':
+            method = RESTController._returns_json(method)
+
+        cherrypy.response.status = status_code
+
+        return method(*vpath, **params)
+
+    @staticmethod
+    def args_from_json(func):
+        func._args_from_json_ = True
+        return func
+
+    @staticmethod
+    def _takes_json(func):
+        def inner(*args, **kwargs):
+            content_length = int(cherrypy.request.headers['Content-Length'])
+            body = cherrypy.request.body.read(content_length)
+            if not body:
+                raise cherrypy.HTTPError(400, 'Empty body. Content-Length={}'
+                                              .format(content_length))
+            try:
+                data = json.loads(body.decode('utf-8'))
+            except Exception as e:
+                raise cherrypy.HTTPError(400, 'Failed to decode JSON: {}'
+                                              .format(str(e)))
+            if hasattr(func, '_args_from_json_'):
+                f_args = inspect.getargspec(func).args
+                n_args = []
+                for arg in args:
+                    n_args.append(arg)
+                for arg in f_args[1:]:
+                    if arg in data:
+                        n_args.append(data[arg])
+                        data.pop(arg)
+                kwargs.update(data)
+                return func(*n_args, **kwargs)
+            else:
+                return func(data, *args, **kwargs)
+        return inner
+
+    @staticmethod
+    def _returns_json(func):
+        def inner(*args, **kwargs):
+            cherrypy.serving.response.headers['Content-Type'] = \
+                    'application/json'
+            ret = func(*args, **kwargs)
+            return json.dumps(ret).encode('utf8')
+        return inner