mirror of
https://github.com/ceph/ceph
synced 2025-01-01 00:22:25 +00:00
mgr/dashboard_v2: Refactor controller base class
Make it a little bit more OO. This way the mgr and logger properties are well designed and documented which should help contributors to understand the code. Signed-off-by: Volker Theile <vtheile@suse.com>
This commit is contained in:
parent
d0b166cfe8
commit
f416efcf8c
1
src/pybind/mgr/dashboard_v2/.gitignore
vendored
1
src/pybind/mgr/dashboard_v2/.gitignore
vendored
@ -9,6 +9,7 @@ __pycache__
|
||||
# IDE
|
||||
.vscode
|
||||
.idea
|
||||
*.egg
|
||||
|
||||
# virtualenv
|
||||
venv
|
||||
|
@ -98,25 +98,25 @@ Developer Notes
|
||||
How to add a new controller?
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
If you want to add a new endpoint to the backend, you just need to add
|
||||
a class decorated with ``ApiController`` in a python file located under the
|
||||
``controllers`` directory. The dashboard plugin will automatically load your
|
||||
new controller upon start.
|
||||
If you want to add a new endpoint to the backend, you just need to add a
|
||||
class derived from ``BaseController`` decorated with ``ApiController`` in a
|
||||
Python file located under the ``controllers`` directory. The Dashboard module
|
||||
will automatically load your new controller upon start.
|
||||
|
||||
For example create a file ``ping2.py`` under ``controllers`` directory with the
|
||||
following code::
|
||||
|
||||
import cherrypy
|
||||
from ..tools import ApiController
|
||||
from ..tools import ApiController, BaseController
|
||||
|
||||
@ApiController('ping2')
|
||||
class Ping2(object):
|
||||
class Ping2(BaseController):
|
||||
@cherrypy.expose
|
||||
def default(self, *args):
|
||||
return "Hello"
|
||||
|
||||
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
|
||||
Reload the Dashboard module 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
|
||||
``RESTController`` class.
|
||||
@ -156,9 +156,9 @@ Now only authenticated users will be able to "ping" your controller.
|
||||
How to access the manager module instance from a controller?
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Each controller class annoted with the ``ApiController`` decorator is injected
|
||||
with a class property that points to the manager module global instance. The
|
||||
property is named ``mgr``.
|
||||
Each controller class derived from ``BaseController``has a class property that
|
||||
points to the manager module global instance. The property is named ``mgr``.
|
||||
There is another class property called ``logger`` to easily add log messages.
|
||||
|
||||
Example::
|
||||
|
||||
@ -171,9 +171,6 @@ Example::
|
||||
self.logger.debug('Listing available servers')
|
||||
return {'servers': self.mgr.list_servers()}
|
||||
|
||||
We also inject a class property ``logger`` that is provided by the module class
|
||||
to easily add log messages.
|
||||
|
||||
|
||||
How to write a unit test for a controller?
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
@ -3,12 +3,12 @@ from __future__ import absolute_import
|
||||
|
||||
import cherrypy
|
||||
|
||||
from ..tools import ApiController, AuthRequired, RESTController
|
||||
from ..tools import ApiController, AuthRequired, RESTController, BaseController
|
||||
|
||||
|
||||
@ApiController('ping')
|
||||
@AuthRequired()
|
||||
class Ping(object):
|
||||
class Ping(BaseController):
|
||||
@cherrypy.expose
|
||||
def default(self):
|
||||
return 'pong'
|
||||
|
@ -9,6 +9,7 @@ import os
|
||||
import pkgutil
|
||||
import sys
|
||||
|
||||
import six
|
||||
import cherrypy
|
||||
|
||||
|
||||
@ -55,10 +56,10 @@ def load_controllers(mgrmodule):
|
||||
mod = importlib.import_module('.controllers.{}'.format(mod_name),
|
||||
package='dashboard_v2')
|
||||
for _, cls in mod.__dict__.items():
|
||||
if isinstance(cls, type) and hasattr(cls, '_cp_controller_'):
|
||||
# found controller
|
||||
# Controllers MUST be derived from the class BaseController.
|
||||
if isinstance(cls, BaseControllerMeta) and \
|
||||
hasattr(cls, '_cp_controller_'):
|
||||
cls.mgr = mgrmodule
|
||||
cls.logger = mgrmodule.log
|
||||
controllers.append(cls)
|
||||
|
||||
return controllers
|
||||
@ -69,7 +70,51 @@ def _json_error_page(status, message, traceback, version):
|
||||
version=version))
|
||||
|
||||
|
||||
class RESTController(object):
|
||||
class BaseControllerMeta(type):
|
||||
@property
|
||||
def mgr(cls):
|
||||
"""
|
||||
:return: Returns the MgrModule instance of this Ceph dashboard module.
|
||||
"""
|
||||
return cls._mgr_module
|
||||
|
||||
@mgr.setter
|
||||
def mgr(cls, value):
|
||||
"""
|
||||
:param value: The MgrModule instance of the Ceph dashboard module.
|
||||
"""
|
||||
cls._mgr_module = value
|
||||
|
||||
@property
|
||||
def logger(cls):
|
||||
"""
|
||||
:return: Returns the logger belonging to the Ceph dashboard module.
|
||||
"""
|
||||
return cls.mgr.log
|
||||
|
||||
|
||||
class BaseController(six.with_metaclass(BaseControllerMeta, object)):
|
||||
"""
|
||||
Base class for all controllers providing API endpoints.
|
||||
"""
|
||||
_mgr_module = None
|
||||
|
||||
@property
|
||||
def mgr(self):
|
||||
"""
|
||||
:return: Returns the MgrModule instance of this Ceph module.
|
||||
"""
|
||||
return self._mgr_module
|
||||
|
||||
@property
|
||||
def logger(self):
|
||||
"""
|
||||
:return: Returns the logger belonging to the Ceph dashboard module.
|
||||
"""
|
||||
return self.mgr.log
|
||||
|
||||
|
||||
class RESTController(BaseController):
|
||||
"""
|
||||
Base class for providing a RESTful interface to a resource.
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user