X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;f=ceph%2Fsrc%2Fpybind%2Fmgr%2Fdashboard%2Fcontrollers%2Fdocs.py;h=866863cff913cc9098628d6baceb2ec4c372fc02;hb=39ae355f72b1d71f2212a99f2bd9f6c1e0d35528;hp=e7ed9742ab9d25e91915283c588dd9b4cdedd2fc;hpb=18d92ca7c59021ccfb5a5674c608dff59eb0a8a5;p=ceph.git diff --git a/ceph/src/pybind/mgr/dashboard/controllers/docs.py b/ceph/src/pybind/mgr/dashboard/controllers/docs.py index e7ed9742a..866863cff 100644 --- a/ceph/src/pybind/mgr/dashboard/controllers/docs.py +++ b/ceph/src/pybind/mgr/dashboard/controllers/docs.py @@ -1,21 +1,20 @@ # -*- coding: utf-8 -*- -from __future__ import absolute_import - import logging -from typing import Any, Dict, List, Union +from typing import Any, Dict, List, Optional, Union import cherrypy -from .. import DEFAULT_VERSION, mgr +from .. import mgr from ..api.doc import Schema, SchemaInput, SchemaType -from . import ENDPOINT_MAP, BaseController, Controller, Endpoint +from . import ENDPOINT_MAP, BaseController, Endpoint, Router +from ._version import APIVersion NO_DESCRIPTION_AVAILABLE = "*No description available*" logger = logging.getLogger('controllers.docs') -@Controller('/docs', secure=False) +@Router('/docs', secure=False) class Docs(BaseController): @classmethod @@ -34,7 +33,7 @@ class Docs(BaseController): list_of_ctrl.add(endpoint.ctrl) tag_map: Dict[str, str] = {} - for ctrl in list_of_ctrl: + for ctrl in sorted(list_of_ctrl, key=lambda ctrl: ctrl.__name__): tag_name = ctrl.__name__ tag_descr = "" if hasattr(ctrl, 'doc_info'): @@ -185,7 +184,8 @@ class Docs(BaseController): return schema.as_dict() @classmethod - def _gen_responses(cls, method, resp_object=None): + def _gen_responses(cls, method, resp_object=None, + version: Optional[APIVersion] = None): resp: Dict[str, Dict[str, Union[str, Any]]] = { '400': { "description": "Operation exception. Please check the " @@ -203,35 +203,40 @@ class Docs(BaseController): "response body for the stack trace." } } + + if not version: + version = APIVersion.DEFAULT + if method.lower() == 'get': resp['200'] = {'description': "OK", - 'content': {'application/vnd.ceph.api.v{}+json'.format(DEFAULT_VERSION): + 'content': {version.to_mime_type(): {'type': 'object'}}} if method.lower() == 'post': resp['201'] = {'description': "Resource created.", - 'content': {'application/vnd.ceph.api.v{}+json'.format(DEFAULT_VERSION): + 'content': {version.to_mime_type(): {'type': 'object'}}} if method.lower() == 'put': resp['200'] = {'description': "Resource updated.", - 'content': {'application/vnd.ceph.api.v{}+json'.format(DEFAULT_VERSION): + 'content': {version.to_mime_type(): {'type': 'object'}}} if method.lower() == 'delete': resp['204'] = {'description': "Resource deleted.", - 'content': {'application/vnd.ceph.api.v{}+json'.format(DEFAULT_VERSION): + 'content': {version.to_mime_type(): {'type': 'object'}}} if method.lower() in ['post', 'put', 'delete']: resp['202'] = {'description': "Operation is still executing." " Please check the task queue.", - 'content': {'application/vnd.ceph.api.v{}+json'.format(DEFAULT_VERSION): + 'content': {version.to_mime_type(): {'type': 'object'}}} if resp_object: for status_code, response_body in resp_object.items(): if status_code in resp: - resp[status_code].update({ - 'content': { - 'application/vnd.ceph.api.v{}+json'.format(DEFAULT_VERSION): { - 'schema': cls._gen_schema_for_content(response_body)}}}) + resp[status_code].update( + {'content': + {version.to_mime_type(): + {'schema': cls._gen_schema_for_content(response_body)} + }}) return resp @@ -263,7 +268,7 @@ class Docs(BaseController): return parameters @classmethod - def _gen_paths(cls, all_endpoints): + def gen_paths(cls, all_endpoints): # pylint: disable=R0912 method_order = ['get', 'post', 'put', 'delete'] paths = {} @@ -283,8 +288,19 @@ class Docs(BaseController): func = endpoint.func summary = '' + version = None resp = {} p_info = [] + + if hasattr(func, '__method_map_method__'): + version = func.__method_map_method__['version'] + + elif hasattr(func, '__resource_method__'): + version = func.__resource_method__['version'] + + elif hasattr(func, '__collection_method__'): + version = func.__collection_method__['version'] + if hasattr(func, 'doc_info'): if func.doc_info['summary']: summary = func.doc_info['summary'] @@ -304,7 +320,7 @@ class Docs(BaseController): 'tags': [cls._get_tag(endpoint)], 'description': func.__doc__, 'parameters': params, - 'responses': cls._gen_responses(method, resp) + 'responses': cls._gen_responses(method, resp, version) } if summary: methods[method.lower()]['summary'] = summary @@ -340,7 +356,7 @@ class Docs(BaseController): host = cherrypy.request.base.split('://', 1)[1] if not offline else 'example.com' logger.debug("Host: %s", host) - paths = cls._gen_paths(all_endpoints) + paths = cls.gen_paths(all_endpoints) if not base_url: base_url = "/" @@ -375,83 +391,20 @@ class Docs(BaseController): return spec - @Endpoint(path="api.json", version=None) - def api_json(self): + @Endpoint(path="openapi.json", version=None) + def open_api_json(self): return self._gen_spec(False, "/") @Endpoint(path="api-all.json", version=None) def api_all_json(self): return self._gen_spec(True, "/") - def _swagger_ui_page(self, all_endpoints=False): - base = cherrypy.request.base - if all_endpoints: - spec_url = "{}/docs/api-all.json".format(base) - else: - spec_url = "{}/docs/api.json".format(base) - - page = """ - - - - - - - - - -
- - - - - """.format(spec_url) - - return page - - @Endpoint(json_response=False, version=None) - def __call__(self, all_endpoints=False): - return self._swagger_ui_page(all_endpoints) - if __name__ == "__main__": import sys import yaml - from . import generate_routes - def fix_null_descr(obj): """ A hot fix for errors caused by null description values when generating @@ -461,7 +414,7 @@ if __name__ == "__main__": return {k: fix_null_descr(v) for k, v in obj.items() if v is not None} \ if isinstance(obj, dict) else obj - generate_routes("/api") + Router.generate_routes("/api") try: with open(sys.argv[1], 'w') as f: # pylint: disable=protected-access