From 0c8d8d1a3e336fd2e26f4947d19af47a162c3762 Mon Sep 17 00:00:00 2001 From: Ernesto Puerta Date: Tue, 29 Jan 2019 13:16:54 +0100 Subject: [PATCH] mgr/dashboard: feature-toggles: Add REST hook Provide a hook for creating REST controllers and endpoints. Provide also a REST controller for Feature Toggles plugin. Fixes: http://tracker.ceph.com/issues/37530 Signed-off-by: Ernesto Puerta --- .../mgr/dashboard/controllers/__init__.py | 4 +++ .../mgr/dashboard/plugins/feature_toggles.py | 27 ++++++++++++++++--- .../mgr/dashboard/plugins/interfaces.py | 4 +-- 3 files changed, 29 insertions(+), 6 deletions(-) diff --git a/src/pybind/mgr/dashboard/controllers/__init__.py b/src/pybind/mgr/dashboard/controllers/__init__.py index 793331d543f..e8839a43b3c 100644 --- a/src/pybind/mgr/dashboard/controllers/__init__.py +++ b/src/pybind/mgr/dashboard/controllers/__init__.py @@ -24,6 +24,7 @@ from ..security import Scope, Permission from ..tools import wraps, getargspec, TaskManager, get_request_body_params from ..exceptions import ScopeNotValid, PermissionNotValid from ..services.auth import AuthManager, JwtManager +from ..plugins import PLUGIN_MANAGER class Controller(object): @@ -177,6 +178,9 @@ def load_controllers(): continue controllers.append(cls) + for clist in PLUGIN_MANAGER.hook.get_controllers() or []: + controllers.extend(clist) + return controllers diff --git a/src/pybind/mgr/dashboard/plugins/feature_toggles.py b/src/pybind/mgr/dashboard/plugins/feature_toggles.py index a8863f6fa36..5174f3f6d8e 100644 --- a/src/pybind/mgr/dashboard/plugins/feature_toggles.py +++ b/src/pybind/mgr/dashboard/plugins/feature_toggles.py @@ -89,7 +89,7 @@ Feature2Endpoint = { @PM.add_plugin class FeatureToggles(I.CanMgr, I.CanLog, I.Setupable, I.HasOptions, I.HasCommands, I.FilterRequest.BeforeHandler, - I.HasEndpoints): + I.HasControllers): OPTION_FMT = 'FEATURE_TOGGLE_{}' CACHE_MAX_SIZE = 128 # Optimum performance with 2^N sizes @@ -148,6 +148,10 @@ class FeatureToggles(I.CanMgr, I.CanLog, I.Setupable, I.HasOptions, return self.Endpoint2Feature[endpoint] return None + def _get_feature_status(self, feature): + return self.mgr.get_module_option( + self.OPTION_FMT.format(feature.value)) + @PM.add_hook def filter_request_before_handler(self, request): feature = self.__get_feature_from_path(request.path_info) @@ -155,7 +159,7 @@ class FeatureToggles(I.CanMgr, I.CanLog, I.Setupable, I.HasOptions, if feature is None: return - if self.mgr.get_module_option(self.OPTION_FMT.format(feature.value)) is False: + if self._get_feature_status(feature) is False: raise cherrypy.HTTPError( 501, "Feature='{}' (path='{}') disabled by option '{}'".format( feature.value, @@ -164,5 +168,20 @@ class FeatureToggles(I.CanMgr, I.CanLog, I.Setupable, I.HasOptions, )) @PM.add_hook - def register_endpoints(self): - pass + def get_controllers(self): + from ..controllers import ApiController,\ + RESTController, Endpoint, ReadPermission + from ..security import Scope + + @ApiController('/feature_toggles') + class FeatureTogglesEndpoint(RESTController): + + def list(_): + return { + feature.value: self._get_feature_status(feature) + for feature in Features + } + + return [ + FeatureTogglesEndpoint, + ] diff --git a/src/pybind/mgr/dashboard/plugins/interfaces.py b/src/pybind/mgr/dashboard/plugins/interfaces.py index 56cb1d9c045..e990b5abce9 100644 --- a/src/pybind/mgr/dashboard/plugins/interfaces.py +++ b/src/pybind/mgr/dashboard/plugins/interfaces.py @@ -38,9 +38,9 @@ class HasCommands(Interface): @PM.add_interface -class HasEndpoints(Interface): +class HasControllers(Interface): @PM.add_abcspec - def register_endpoints(self): pass + def get_controllers(self): pass class FilterRequest: -- 2.39.5