]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
mgr/dashboard: removed browsable api
authorRicardo Dias <rdias@suse.com>
Fri, 27 Apr 2018 21:15:04 +0000 (22:15 +0100)
committerRicardo Dias <rdias@suse.com>
Thu, 24 May 2018 09:42:24 +0000 (10:42 +0100)
Signed-off-by: Ricardo Dias <rdias@suse.com>
qa/tasks/mgr/dashboard/test_auth.py
src/pybind/mgr/dashboard/controllers/__init__.py
src/pybind/mgr/dashboard/tests/test_exceptions.py
src/pybind/mgr/dashboard/tests/test_tools.py

index 1c71687a4d1f87dc0dadfad4949fd770c2b61515..29350e2dc92c2e09c96ba2cebc27bc773d370832 100644 (file)
@@ -72,5 +72,3 @@ class AuthTest(DashboardTestCase):
     def test_unauthorized(self):
         self._get("/api/host")
         self.assertStatus(401)
-        self._get("/api")
-        self.assertStatus(401)
index 019bff55722d8a945d0da4af74b819312283e6b3..db6b52defb1bae1f8e301be33328c13596a5d19e 100644 (file)
@@ -116,9 +116,6 @@ def generate_routes(url_prefix):
     for ctrl in ctrls:
         generate_controller_routes(ctrl, mapper, "{}/api".format(url_prefix))
 
-    mapper.connect(ApiRoot.__name__, "{}/api".format(url_prefix),
-                   controller=ApiRoot("{}/api".format(url_prefix),
-                                      ctrls))
     return mapper
 
 
@@ -128,170 +125,6 @@ def json_error_page(status, message, traceback, version):
                            version=version))
 
 
-class ApiRoot(object):
-
-    _cp_config = {
-        'tools.sessions.on': True,
-        'tools.authenticate.on': True
-    }
-
-    def __init__(self, base_url, ctrls):
-        self.base_url = base_url
-        self.ctrls = ctrls
-
-    def __call__(self):
-        tpl = """API Endpoints:<br>
-        <ul>
-        {lis}
-        </ul>
-        """
-        endpoints = ['<li><a href="{}/{}">{}</a></li>'
-                     .format(self.base_url, ctrl._cp_path_, ctrl.__name__) for
-                     ctrl in self.ctrls]
-        return tpl.format(lis='\n'.join(endpoints))
-
-
-def browsable_api_view(meth):
-    @wraps(meth)
-    def wrapper(self, *vpath, **kwargs):
-        assert isinstance(self, BaseController)
-        if not Settings.ENABLE_BROWSABLE_API:
-            return meth(self, *vpath, **kwargs)
-        if 'text/html' not in cherrypy.request.headers.get('Accept', ''):
-            return meth(self, *vpath, **kwargs)
-
-        if '_method' in kwargs:
-            cherrypy.request.method = kwargs.pop('_method').upper()
-
-        # Form typically use None as default, but HTML defaults to empty-string.
-        for k in kwargs:
-            if not kwargs[k]:
-                del kwargs[k]
-
-        if '_raw' in kwargs:
-            kwargs.pop('_raw')
-            return meth(self, *vpath, **kwargs)
-
-        sub_path = cherrypy.request.path_info.split(self._cp_path_, 1)[-1].strip('/').split('/')
-
-        template = """
-        <html>
-        <h1>Browsable API</h1>
-        {docstring}
-        <h2>Request</h2>
-        <p>{method} {breadcrump}</p>
-        {params}
-        <h2>Response</h2>
-        <p>Status: {status_code}<p>
-        <pre>{reponse_headers}</pre>
-        <form action="/api/{path}/{sub_path}" method="get">
-        <input type="hidden" name="_raw" value="true" />
-        <button type="submit">GET raw data</button>
-        </form>
-        <h2>Data</h2>
-        <pre>{data}</pre>
-        {exception}
-        {create_form}
-        {delete_form}
-        <h2>Note</h2>
-        <p>Please note that this API is not an official Ceph REST API to be
-        used by third-party applications. It's primary purpose is to serve
-        the requirements of the Ceph Dashboard and is subject to change at
-        any time. Use at your own risk.</p>
-        """
-
-        create_form_template = """
-        <h2>Create Form</h2>
-        <form action="/api/{path}/{sub_path}" method="post">
-        {fields}<br>
-        <input type="hidden" name="_method" value="post" />
-        <button type="submit">Create</button>
-        </form>
-        """
-
-        delete_form_template = """
-        <h2>Create Form</h2>
-        <form action="/api/{path}/{sub_path}" method="post">
-        <input type="hidden" name="_method" value="delete" />
-        <button type="submit">Delete</button>
-        </form>
-        """
-
-        def mk_exception(e):
-            except_template = """
-            <h2>Exception: {etype}: {tostr}</h2>
-            <pre>{trace}</pre>
-            """
-            import traceback
-            tb = sys.exc_info()[2]
-            cherrypy.response.headers['Content-Type'] = 'text/html'
-            return except_template.format(
-                etype=e.__class__.__name__,
-                tostr=str(e),
-                trace='\n'.join(traceback.format_tb(tb)),
-                kwargs=kwargs
-            )
-
-        try:
-            data = meth(self, *vpath, **kwargs)
-            exception = ''
-            if cherrypy.response.headers['Content-Type'] == 'application/json':
-                try:
-                    data = json.dumps(json.loads(data), indent=2, sort_keys=True)
-                except Exception:  # pylint: disable=broad-except
-                    pass
-        except (ViewCacheNoDataException, DashboardException) as e:
-            cherrypy.response.status = getattr(e, 'status', 400)
-            data = str(serialize_dashboard_exception(e))
-            exception = mk_exception(e)
-        except Exception as e:  # pylint: disable=broad-except
-            data = ''
-            exception = mk_exception(e)
-
-        try:
-            create = getattr(self, 'create')
-            f_args = RESTController._function_args(create)
-            input_fields = ['{name}:<input type="text" name="{name}">'.format(name=name) for name in
-                            f_args]
-            create_form = create_form_template.format(
-                fields='<br>'.join(input_fields),
-                path=self._cp_path_,
-                sub_path='/'.join(sub_path)
-            )
-        except AttributeError:
-            create_form = ''
-
-        def mk_breadcrump(elems):
-            return '/'.join([
-                '<a href="/{}">{}</a>'.format('/'.join(elems[0:i+1]), e)
-                for i, e in enumerate(elems)
-            ])
-
-        cherrypy.response.headers['Content-Type'] = 'text/html'
-        return template.format(
-            docstring='<pre>{}</pre>'.format(self.__doc__) if self.__doc__ else '',
-            method=cherrypy.request.method,
-            path=self._cp_path_,
-            sub_path='/'.join(sub_path),
-            breadcrump=mk_breadcrump(['api', self._cp_path_] + list(sub_path)),
-            status_code=cherrypy.response.status,
-            reponse_headers='\n'.join(
-                '{}: {}'.format(k, v) for k, v in cherrypy.response.headers.items()),
-            data=data,
-            exception=exception,
-            create_form=create_form,
-            delete_form=delete_form_template.format(path=self._cp_path_, sub_path='/'.join(
-                sub_path)) if sub_path else '',
-            params='<h2>Rrequest Params</h2><pre>{}</pre>'.format(
-                json.dumps(kwargs, indent=2)) if kwargs else '',
-        )
-
-    wrapper.exposed = True
-    if hasattr(meth, '_cp_config'):
-        wrapper._cp_config = meth._cp_config
-    return wrapper
-
-
 class Task(object):
     def __init__(self, name, metadata, wait_for=5.0, exception_handler=None):
         self.name = name
@@ -360,17 +193,6 @@ class Task(object):
         return wrapper
 
 
-class BaseControllerMeta(type):
-    def __new__(mcs, name, bases, dct):
-        new_cls = type.__new__(mcs, name, bases, dct)
-
-        for a_name, thing in new_cls.__dict__.items():
-            if callable(thing) and getattr(thing, 'exposed', False):
-                setattr(new_cls, a_name, browsable_api_view(thing))
-        return new_cls
-
-
-@add_metaclass(BaseControllerMeta)
 class BaseController(object):
     """
     Base class for all controllers providing API endpoints.
index 5443cbfb2433ade3f120316065284fbb994b5f7c..4fc9ef7f8fcb61688c1190049a7439cdd13ae351 100644 (file)
@@ -126,11 +126,6 @@ class RESTControllerTest(ControllerTestCase):
             {'detail': '[errno -42] list', 'code': "42", 'component': 'foo'}
         )
 
-    def test_error_send_command_bowsable_api(self):
-        self.getPage('/foo/error_send_command', headers=[('Accept', 'text/html')])
-        for err in ["'detail': '[errno -42] hi'", "'component': 'foo'"]:
-            self.assertIn(err.replace("'", "\'").encode('utf-8'), self.body)
-
     def test_error_foo_generic(self):
         self._get('/foo/error_generic')
         self.assertJsonBody({'detail': 'hi', 'code': 'Error', 'component': None})
index 72e6dc0bbb75038ae839cc8b28c8c51aaf5e7eb8..0972c51008cf4c59676bc1ea0965b75e937b86e2 100644 (file)
@@ -137,24 +137,6 @@ 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_create_form(self):
-        self.getPage('/fooargs', headers=[('Accept', 'text/html')])
-        self.assertIn('my_arg_name', self.body.decode('utf-8'))
-
     def test_generate_controller_routes(self):
         # We just need to add this controller in setup_server():
         # noinspection PyStatementEffect