]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
mgr/dashboard: api doc: fix endpoint responses doc generation. 37375/head
authorAlfonso Martínez <almartin@redhat.com>
Tue, 6 Oct 2020 07:10:13 +0000 (09:10 +0200)
committerAlfonso Martínez <almartin@redhat.com>
Tue, 6 Oct 2020 07:10:13 +0000 (09:10 +0200)
Fixes: https://tracker.ceph.com/issues/47615
Signed-off-by: Alfonso Martínez <almartin@redhat.com>
src/pybind/mgr/dashboard/api/__init__.py [new file with mode: 0644]
src/pybind/mgr/dashboard/api/doc.py [new file with mode: 0644]
src/pybind/mgr/dashboard/controllers/__init__.py
src/pybind/mgr/dashboard/controllers/docs.py
src/pybind/mgr/dashboard/controllers/rgw.py
src/pybind/mgr/dashboard/openapi.yaml
src/pybind/mgr/dashboard/tests/test_docs.py
src/pybind/mgr/dashboard/tox.ini

diff --git a/src/pybind/mgr/dashboard/api/__init__.py b/src/pybind/mgr/dashboard/api/__init__.py
new file mode 100644 (file)
index 0000000..c396168
--- /dev/null
@@ -0,0 +1 @@
+from __future__ import absolute_import
diff --git a/src/pybind/mgr/dashboard/api/doc.py b/src/pybind/mgr/dashboard/api/doc.py
new file mode 100644 (file)
index 0000000..172d59d
--- /dev/null
@@ -0,0 +1,53 @@
+from enum import Enum
+from typing import Any, Dict, List, Optional
+
+
+class SchemaType(Enum):
+    """
+    Representation of the type property of a schema object:
+    http://spec.openapis.org/oas/v3.0.3.html#schema-object
+    """
+    ARRAY = 'array'
+    BOOLEAN = 'boolean'
+    INTEGER = 'integer'
+    NUMBER = 'number'
+    OBJECT = 'object'
+    STRING = 'string'
+
+    def __str__(self):
+        return str(self.value)
+
+
+class Schema:
+    """
+    Representation of a schema object:
+    http://spec.openapis.org/oas/v3.0.3.html#schema-object
+    """
+
+    def __init__(self, schema_type: SchemaType = SchemaType.OBJECT,
+                 properties: Optional[Dict] = None, required: Optional[List] = None):
+        self._type = schema_type
+        self._properties = properties if properties else {}
+        self._required = required if required else []
+
+    def as_dict(self) -> Dict[str, Any]:
+        schema: Dict[str, Any] = {'type': str(self._type)}
+
+        if self._type == SchemaType.ARRAY:
+            items = Schema(properties=self._properties)
+            schema['items'] = items.as_dict()
+        else:
+            schema['properties'] = self._properties
+
+        if self._required:
+            schema['required'] = self._required
+
+        return schema
+
+
+class SchemaInput:
+    """
+    Simple DTO to transfer data in a structured manner for creating a schema object.
+    """
+    type: SchemaType
+    params: List[Any]
index b77ea759eb403397d16bd4d9413de7c79b364b0c..4e52c21d8e436557303f0cf27d2d80b5cff2b188 100644 (file)
@@ -11,12 +11,13 @@ import os
 import pkgutil
 import re
 import sys
-import urllib
 from functools import wraps
+from urllib.parse import unquote
 
 # pylint: disable=wrong-import-position
 import cherrypy
 
+from ..api.doc import SchemaInput, SchemaType
 from ..exceptions import PermissionNotValid, ScopeNotValid
 from ..plugins import PLUGIN_MANAGER
 from ..security import Permission, Scope
@@ -107,7 +108,12 @@ def EndpointDoc(description="", group="", parameters=None, responses=None):  # n
     resp = {}
     if responses:
         for status_code, response_body in responses.items():
-            resp[str(status_code)] = _split_parameters(response_body)
+            schema_input = SchemaInput()
+            schema_input.type = SchemaType.ARRAY if \
+                isinstance(response_body, list) else SchemaType.OBJECT
+            schema_input.params = _split_parameters(response_body)
+
+            resp[str(status_code)] = schema_input
 
     def _wrapper(func):
         func.doc_info = {
@@ -662,7 +668,7 @@ class BaseController(object):
         def inner(*args, **kwargs):
             for key, value in kwargs.items():
                 if isinstance(value, str):
-                    kwargs[key] = urllib.parse.unquote(value)
+                    kwargs[key] = unquote(value)
 
             # Process method arguments.
             params = get_request_body_params(cherrypy.request)
index a537121993459c1c240d7a2c6df573cad0f32005..ddab096002bd50326f774215fcaf51c687056a97 100644 (file)
@@ -2,11 +2,12 @@
 from __future__ import absolute_import
 
 import logging
-from typing import Any, Dict, Union
+from typing import Any, Dict, List, Union
 
 import cherrypy
 
 from .. import mgr
+from ..api.doc import Schema, SchemaInput, SchemaType
 from . import ENDPOINT_MAP, BaseController, Controller, Endpoint, allow_empty_body
 
 NO_DESCRIPTION_AVAILABLE = "*No description available*"
@@ -71,35 +72,35 @@ class Docs(BaseController):
         param_name = param['name']
         def_value = param['default'] if 'default' in param else None
         if param_name.startswith("is_"):
-            return "boolean"
+            return str(SchemaType.BOOLEAN)
         if "size" in param_name:
-            return "integer"
+            return str(SchemaType.INTEGER)
         if "count" in param_name:
-            return "integer"
+            return str(SchemaType.INTEGER)
         if "num" in param_name:
-            return "integer"
+            return str(SchemaType.INTEGER)
         if isinstance(def_value, bool):
-            return "boolean"
+            return str(SchemaType.BOOLEAN)
         if isinstance(def_value, int):
-            return "integer"
-        return "string"
+            return str(SchemaType.INTEGER)
+        return str(SchemaType.STRING)
 
     @classmethod
     # isinstance doesn't work: input is always <type 'type'>.
     def _type_to_str(cls, type_as_type):
         """ Used if type is explicitly defined. """
         if type_as_type is str:
-            type_as_str = 'string'
+            type_as_str = str(SchemaType.STRING)
         elif type_as_type is int:
-            type_as_str = 'integer'
+            type_as_str = str(SchemaType.INTEGER)
         elif type_as_type is bool:
-            type_as_str = 'boolean'
+            type_as_str = str(SchemaType.BOOLEAN)
         elif type_as_type is list or type_as_type is tuple:
-            type_as_str = 'array'
+            type_as_str = str(SchemaType.ARRAY)
         elif type_as_type is float:
-            type_as_str = 'number'
+            type_as_str = str(SchemaType.NUMBER)
         else:
-            type_as_str = 'object'
+            type_as_str = str(SchemaType.OBJECT)
         return type_as_str
 
     @classmethod
@@ -143,13 +144,17 @@ class Docs(BaseController):
         return parameters
 
     @classmethod
-    def _gen_schema_for_content(cls, params):
+    def _gen_schema_for_content(cls, params: List[Any]) -> Dict[str, Any]:
         """
         Generates information to the content-object in OpenAPI Spec.
         Used to for request body and responses.
         """
         required_params = []
         properties = {}
+        schema_type = SchemaType.OBJECT
+        if isinstance(params, SchemaInput):
+            schema_type = params.type
+            params = params.params
 
         for param in params:
             if param['required']:
@@ -159,12 +164,12 @@ class Docs(BaseController):
             if 'type' in param:
                 props['type'] = cls._type_to_str(param['type'])
                 if 'nested_params' in param:
-                    if props['type'] == 'array':  # dict in array
+                    if props['type'] == str(SchemaType.ARRAY):  # dict in array
                         props['items'] = cls._gen_schema_for_content(param['nested_params'])
                     else:  # dict in dict
                         props = cls._gen_schema_for_content(param['nested_params'])
-                elif props['type'] == 'object':  # e.g. [int]
-                    props['type'] = 'array'
+                elif props['type'] == str(SchemaType.OBJECT):  # e.g. [int]
+                    props['type'] = str(SchemaType.ARRAY)
                     props['items'] = {'type': cls._type_to_str(param['type'][0])}
             else:
                 props['type'] = cls._gen_type(param)
@@ -174,13 +179,10 @@ class Docs(BaseController):
                 props['default'] = param['default']
             properties[param['name']] = props
 
-        schema = {
-            'type': 'object',
-            'properties': properties,
-        }
-        if required_params:
-            schema['required'] = required_params
-        return schema
+        schema = Schema(schema_type=schema_type, properties=properties,
+                        required=required_params)
+
+        return schema.as_dict()
 
     @classmethod
     def _gen_responses(cls, method, resp_object=None):
@@ -215,10 +217,11 @@ class Docs(BaseController):
 
         if resp_object:
             for status_code, response_body in resp_object.items():
-                resp[status_code].update({
-                    'content': {
-                        'application/json': {
-                            'schema': cls._gen_schema_for_content(response_body)}}})
+                if status_code in resp:
+                    resp[status_code].update({
+                        'content': {
+                            'application/json': {
+                                'schema': cls._gen_schema_for_content(response_body)}}})
 
         return resp
 
index e00a77b3cbf8d06c7f438ffd8892bdfa348932d4..984c8622d9bd1db0fc38f70587d818ee8e0df85f 100644 (file)
@@ -74,7 +74,7 @@ class Rgw(BaseController):
 @ControllerDoc("RGW Daemon Management API", "RgwDaemon")
 class RgwDaemon(RESTController):
     @EndpointDoc("Display RGW Daemons",
-                 responses={200: RGW_DAEMON_SCHEMA})
+                 responses={200: [RGW_DAEMON_SCHEMA]})
     def list(self):
         # type: () -> List[dict]
         daemons = []
index bba9a054a30eeabfa557ab2265d7742f0dd0eda8..efcde8b6223a5f0256c5e942bb267594a4c6775d 100644 (file)
@@ -144,23 +144,25 @@ paths:
           content:
             application/json:
               schema:
-                properties:
-                  pool_name:
-                    description: pool name
-                    type: string
-                  status:
-                    description: Status of the image
-                    type: integer
-                  value:
-                    description: ''
-                    items:
+                items:
+                  properties:
+                    pool_name:
+                      description: pool name
                       type: string
-                    type: array
+                    status:
+                      description: Status of the image
+                      type: integer
+                    value:
+                      description: ''
+                      items:
+                        type: string
+                      type: array
+                  type: object
                 required:
                 - status
                 - value
                 - pool_name
-                type: object
+                type: array
           description: OK
         '400':
           description: Operation exception. Please check the response body for details.
@@ -260,23 +262,25 @@ paths:
           content:
             application/json:
               schema:
-                properties:
-                  pool_name:
-                    description: pool name
-                    type: string
-                  status:
-                    description: ''
-                    type: integer
-                  value:
-                    description: ''
-                    items:
+                items:
+                  properties:
+                    pool_name:
+                      description: pool name
                       type: string
-                    type: array
+                    status:
+                      description: ''
+                      type: integer
+                    value:
+                      description: ''
+                      items:
+                        type: string
+                      type: array
+                  type: object
                 required:
                 - status
                 - value
                 - pool_name
-                type: object
+                type: array
           description: OK
         '400':
           description: Operation exception. Please check the response body for details.
@@ -1885,62 +1889,64 @@ paths:
           content:
             application/json:
               schema:
-                properties:
-                  can_update_at_runtime:
-                    description: Check if can update at runtime
-                    type: boolean
-                  daemon_default:
-                    description: Daemon specific default value
-                    type: string
-                  default:
-                    description: Default value for the config option
-                    type: string
-                  desc:
-                    description: Description of the configuration
-                    type: string
-                  enum_values:
-                    description: List of enums allowed
-                    items:
+                items:
+                  properties:
+                    can_update_at_runtime:
+                      description: Check if can update at runtime
+                      type: boolean
+                    daemon_default:
+                      description: Daemon specific default value
                       type: string
-                    type: array
-                  flags:
-                    description: List of flags associated
-                    items:
+                    default:
+                      description: Default value for the config option
                       type: string
-                    type: array
-                  level:
-                    description: Config option level
-                    type: string
-                  long_desc:
-                    description: Elaborated description
-                    type: string
-                  max:
-                    description: Maximum value
-                    type: string
-                  min:
-                    description: Minimum value
-                    type: string
-                  name:
-                    description: Name of the config option
-                    type: string
-                  see_also:
-                    description: Related config options
-                    items:
+                    desc:
+                      description: Description of the configuration
                       type: string
-                    type: array
-                  services:
-                    description: Services associated with the config option
-                    items:
+                    enum_values:
+                      description: List of enums allowed
+                      items:
+                        type: string
+                      type: array
+                    flags:
+                      description: List of flags associated
+                      items:
+                        type: string
+                      type: array
+                    level:
+                      description: Config option level
                       type: string
-                    type: array
-                  tags:
-                    description: Tags associated with the cluster
-                    items:
+                    long_desc:
+                      description: Elaborated description
                       type: string
-                    type: array
-                  type:
-                    description: Config option type
-                    type: string
+                    max:
+                      description: Maximum value
+                      type: string
+                    min:
+                      description: Minimum value
+                      type: string
+                    name:
+                      description: Name of the config option
+                      type: string
+                    see_also:
+                      description: Related config options
+                      items:
+                        type: string
+                      type: array
+                    services:
+                      description: Services associated with the config option
+                      items:
+                        type: string
+                      type: array
+                    tags:
+                      description: Tags associated with the cluster
+                      items:
+                        type: string
+                      type: array
+                    type:
+                      description: Config option type
+                      type: string
+                  type: object
                 required:
                 - name
                 - type
@@ -1957,7 +1963,7 @@ paths:
                 - max
                 - can_update_at_runtime
                 - flags
-                type: object
+                type: array
           description: OK
         '400':
           description: Operation exception. Please check the response body for details.
@@ -2178,25 +2184,27 @@ paths:
           content:
             application/json:
               schema:
-                properties:
-                  crush-failure-domain:
-                    description: ''
-                    type: string
-                  k:
-                    description: Number of data chunks
-                    type: integer
-                  m:
-                    description: Number of coding chunks
-                    type: integer
-                  name:
-                    description: Name of the profile
-                    type: string
-                  plugin:
-                    description: Plugin Info
-                    type: string
-                  technique:
-                    description: ''
-                    type: string
+                items:
+                  properties:
+                    crush-failure-domain:
+                      description: ''
+                      type: string
+                    k:
+                      description: Number of data chunks
+                      type: integer
+                    m:
+                      description: Number of coding chunks
+                      type: integer
+                    name:
+                      description: Name of the profile
+                      type: string
+                    plugin:
+                      description: Plugin Info
+                      type: string
+                    technique:
+                      description: ''
+                      type: string
+                  type: object
                 required:
                 - crush-failure-domain
                 - k
@@ -2204,7 +2212,7 @@ paths:
                 - plugin
                 - technique
                 - name
-                type: object
+                type: array
           description: OK
         '400':
           description: Operation exception. Please check the response body for details.
@@ -3113,25 +3121,27 @@ paths:
           content:
             application/json:
               schema:
-                properties:
-                  mutual_password:
-                    description: ''
-                    type: string
-                  mutual_user:
-                    description: ''
-                    type: string
-                  password:
-                    description: password
-                    type: string
-                  user:
-                    description: username
-                    type: string
+                items:
+                  properties:
+                    mutual_password:
+                      description: ''
+                      type: string
+                    mutual_user:
+                      description: ''
+                      type: string
+                    password:
+                      description: password
+                      type: string
+                    user:
+                      description: username
+                      type: string
+                  type: object
                 required:
                 - user
                 - password
                 - mutual_user
                 - mutual_password
-                type: object
+                type: array
           description: OK
         '400':
           description: Operation exception. Please check the response body for details.
@@ -3477,87 +3487,89 @@ paths:
           content:
             application/json:
               schema:
-                properties:
-                  always_on:
-                    description: Is it an always on module?
-                    type: boolean
-                  enabled:
-                    description: Is Module Enabled
-                    type: boolean
-                  name:
-                    description: Module Name
-                    type: string
-                  options:
-                    description: Module Options
-                    properties:
-                      Option_name:
-                        description: Options
-                        properties:
-                          default_value:
-                            description: Default value for the option
-                            type: integer
-                          desc:
-                            description: Description of the option
-                            type: string
-                          enum_allowed:
-                            description: ''
-                            items:
+                items:
+                  properties:
+                    always_on:
+                      description: Is it an always on module?
+                      type: boolean
+                    enabled:
+                      description: Is Module Enabled
+                      type: boolean
+                    name:
+                      description: Module Name
+                      type: string
+                    options:
+                      description: Module Options
+                      properties:
+                        Option_name:
+                          description: Options
+                          properties:
+                            default_value:
+                              description: Default value for the option
+                              type: integer
+                            desc:
+                              description: Description of the option
                               type: string
-                            type: array
-                          flags:
-                            description: List of flags associated
-                            type: integer
-                          level:
-                            description: Option level
-                            type: string
-                          long_desc:
-                            description: Elaborated description
-                            type: string
-                          max:
-                            description: Maximum value
-                            type: string
-                          min:
-                            description: Minimum value
-                            type: string
-                          name:
-                            description: Name of the option
-                            type: string
-                          see_also:
-                            description: Related options
-                            items:
+                            enum_allowed:
+                              description: ''
+                              items:
+                                type: string
+                              type: array
+                            flags:
+                              description: List of flags associated
+                              type: integer
+                            level:
+                              description: Option level
                               type: string
-                            type: array
-                          tags:
-                            description: Tags associated with the option
-                            items:
+                            long_desc:
+                              description: Elaborated description
                               type: string
-                            type: array
-                          type:
-                            description: Type of the option
-                            type: string
-                        required:
-                        - name
-                        - type
-                        - level
-                        - flags
-                        - default_value
-                        - min
-                        - max
-                        - enum_allowed
-                        - desc
-                        - long_desc
-                        - tags
-                        - see_also
-                        type: object
-                    required:
-                    - Option_name
-                    type: object
+                            max:
+                              description: Maximum value
+                              type: string
+                            min:
+                              description: Minimum value
+                              type: string
+                            name:
+                              description: Name of the option
+                              type: string
+                            see_also:
+                              description: Related options
+                              items:
+                                type: string
+                              type: array
+                            tags:
+                              description: Tags associated with the option
+                              items:
+                                type: string
+                              type: array
+                            type:
+                              description: Type of the option
+                              type: string
+                          required:
+                          - name
+                          - type
+                          - level
+                          - flags
+                          - default_value
+                          - min
+                          - max
+                          - enum_allowed
+                          - desc
+                          - long_desc
+                          - tags
+                          - see_also
+                          type: object
+                      required:
+                      - Option_name
+                      type: object
+                  type: object
                 required:
                 - name
                 - enabled
                 - always_on
                 - options
-                type: object
+                type: array
           description: OK
         '400':
           description: Operation exception. Please check the response body for details.
@@ -4116,23 +4128,25 @@ paths:
           content:
             application/json:
               schema:
-                properties:
-                  cluster_id:
-                    description: Cluster identifier
-                    type: string
-                  daemon_id:
-                    description: Daemon identifier
-                    type: string
-                  desc:
-                    description: Error description (if status==-1)
-                    type: string
-                  status:
-                    description: Status of daemon (1=RUNNING, 0=STOPPED, -1=ERROR
-                    type: integer
+                items:
+                  properties:
+                    cluster_id:
+                      description: Cluster identifier
+                      type: string
+                    daemon_id:
+                      description: Daemon identifier
+                      type: string
+                    desc:
+                      description: Error description (if status==-1)
+                      type: string
+                    status:
+                      description: Status of daemon (1=RUNNING, 0=STOPPED, -1=ERROR
+                      type: integer
+                  type: object
                 required:
                 - daemon_id
                 - cluster_id
-                type: object
+                type: array
           description: OK
         '400':
           description: Operation exception. Please check the response body for details.
@@ -4156,88 +4170,90 @@ paths:
           content:
             application/json:
               schema:
-                properties:
-                  access_type:
-                    description: Export access type
-                    type: string
-                  clients:
-                    description: List of client configurations
-                    items:
+                items:
+                  properties:
+                    access_type:
+                      description: Export access type
+                      type: string
+                    clients:
+                      description: List of client configurations
+                      items:
+                        properties:
+                          access_type:
+                            description: Client access type
+                            type: string
+                          addresses:
+                            description: list of IP addresses
+                            items:
+                              type: string
+                            type: array
+                          squash:
+                            description: Client squash policy
+                            type: string
+                        required:
+                        - addresses
+                        - access_type
+                        - squash
+                        type: object
+                      type: array
+                    cluster_id:
+                      description: Cluster identifier
+                      type: string
+                    daemons:
+                      description: List of NFS Ganesha daemons identifiers
+                      items:
+                        type: string
+                      type: array
+                    export_id:
+                      description: Export ID
+                      type: integer
+                    fsal:
+                      description: FSAL configuration
                       properties:
-                        access_type:
-                          description: Client access type
+                        filesystem:
+                          description: CephFS filesystem ID
                           type: string
-                        addresses:
-                          description: list of IP addresses
-                          items:
-                            type: string
-                          type: array
-                        squash:
-                          description: Client squash policy
+                        name:
+                          description: name of FSAL
+                          type: string
+                        rgw_user_id:
+                          description: RGW user id
+                          type: string
+                        sec_label_xattr:
+                          description: Name of xattr for security label
+                          type: string
+                        user_id:
+                          description: CephX user id
                           type: string
                       required:
-                      - addresses
-                      - access_type
-                      - squash
+                      - name
                       type: object
-                    type: array
-                  cluster_id:
-                    description: Cluster identifier
-                    type: string
-                  daemons:
-                    description: List of NFS Ganesha daemons identifiers
-                    items:
+                    path:
+                      description: Export path
                       type: string
-                    type: array
-                  export_id:
-                    description: Export ID
-                    type: integer
-                  fsal:
-                    description: FSAL configuration
-                    properties:
-                      filesystem:
-                        description: CephFS filesystem ID
-                        type: string
-                      name:
-                        description: name of FSAL
-                        type: string
-                      rgw_user_id:
-                        description: RGW user id
-                        type: string
-                      sec_label_xattr:
-                        description: Name of xattr for security label
-                        type: string
-                      user_id:
-                        description: CephX user id
+                    protocols:
+                      description: List of protocol types
+                      items:
+                        type: integer
+                      type: array
+                    pseudo:
+                      description: Pseudo FS path
+                      type: string
+                    security_label:
+                      description: Security label
+                      type: string
+                    squash:
+                      description: Export squash policy
+                      type: string
+                    tag:
+                      description: NFSv3 export tag
+                      type: string
+                    transports:
+                      description: List of transport types
+                      items:
                         type: string
-                    required:
-                    - name
-                    type: object
-                  path:
-                    description: Export path
-                    type: string
-                  protocols:
-                    description: List of protocol types
-                    items:
-                      type: integer
-                    type: array
-                  pseudo:
-                    description: Pseudo FS path
-                    type: string
-                  security_label:
-                    description: Security label
-                    type: string
-                  squash:
-                    description: Export squash policy
-                    type: string
-                  tag:
-                    description: NFSv3 export tag
-                    type: string
-                  transports:
-                    description: List of transport types
-                    items:
-                      type: string
-                    type: array
+                      type: array
+                  type: object
                 required:
                 - export_id
                 - path
@@ -4252,7 +4268,7 @@ paths:
                 - transports
                 - fsal
                 - clients
-                type: object
+                type: array
           description: OK
         '400':
           description: Operation exception. Please check the response body for details.
@@ -5838,223 +5854,225 @@ paths:
           content:
             application/json:
               schema:
-                properties:
-                  application_metadata:
-                    description: ''
-                    items:
+                items:
+                  properties:
+                    application_metadata:
+                      description: ''
+                      items:
+                        type: string
+                      type: array
+                    auid:
+                      description: ''
+                      type: integer
+                    cache_min_evict_age:
+                      description: ''
+                      type: integer
+                    cache_min_flush_age:
+                      description: ''
+                      type: integer
+                    cache_mode:
+                      description: ''
                       type: string
-                    type: array
-                  auid:
-                    description: ''
-                    type: integer
-                  cache_min_evict_age:
-                    description: ''
-                    type: integer
-                  cache_min_flush_age:
-                    description: ''
-                    type: integer
-                  cache_mode:
-                    description: ''
-                    type: string
-                  cache_target_dirty_high_ratio_micro:
-                    description: ''
-                    type: integer
-                  cache_target_dirty_ratio_micro:
-                    description: ''
-                    type: integer
-                  cache_target_full_ratio_micro:
-                    description: ''
-                    type: integer
-                  create_time:
-                    description: ''
-                    type: string
-                  crush_rule:
-                    description: ''
-                    type: string
-                  erasure_code_profile:
-                    description: ''
-                    type: string
-                  expected_num_objects:
-                    description: ''
-                    type: integer
-                  fast_read:
-                    description: ''
-                    type: boolean
-                  flags:
-                    description: ''
-                    type: integer
-                  flags_names:
-                    description: flags name
-                    type: string
-                  grade_table:
-                    description: ''
-                    items:
+                    cache_target_dirty_high_ratio_micro:
+                      description: ''
+                      type: integer
+                    cache_target_dirty_ratio_micro:
+                      description: ''
+                      type: integer
+                    cache_target_full_ratio_micro:
+                      description: ''
+                      type: integer
+                    create_time:
+                      description: ''
                       type: string
-                    type: array
-                  hit_set_count:
-                    description: ''
-                    type: integer
-                  hit_set_grade_decay_rate:
-                    description: ''
-                    type: integer
-                  hit_set_params:
-                    description: ''
-                    properties:
-                      type:
-                        description: ''
-                        type: string
-                    required:
-                    - type
-                    type: object
-                  hit_set_period:
-                    description: ''
-                    type: integer
-                  hit_set_search_last_n:
-                    description: ''
-                    type: integer
-                  last_change:
-                    description: ''
-                    type: string
-                  last_force_op_resend:
-                    description: ''
-                    type: string
-                  last_force_op_resend_preluminous:
-                    description: ''
-                    type: string
-                  last_force_op_resend_prenautilus:
-                    description: ''
-                    type: string
-                  last_pg_merge_meta:
-                    description: ''
-                    properties:
-                      last_epoch_clean:
-                        description: ''
-                        type: integer
-                      last_epoch_started:
-                        description: ''
-                        type: integer
-                      ready_epoch:
-                        description: ''
-                        type: integer
-                      source_pgid:
-                        description: ''
+                    crush_rule:
+                      description: ''
+                      type: string
+                    erasure_code_profile:
+                      description: ''
+                      type: string
+                    expected_num_objects:
+                      description: ''
+                      type: integer
+                    fast_read:
+                      description: ''
+                      type: boolean
+                    flags:
+                      description: ''
+                      type: integer
+                    flags_names:
+                      description: flags name
+                      type: string
+                    grade_table:
+                      description: ''
+                      items:
                         type: string
-                      source_version:
-                        description: ''
+                      type: array
+                    hit_set_count:
+                      description: ''
+                      type: integer
+                    hit_set_grade_decay_rate:
+                      description: ''
+                      type: integer
+                    hit_set_params:
+                      description: ''
+                      properties:
+                        type:
+                          description: ''
+                          type: string
+                      required:
+                      - type
+                      type: object
+                    hit_set_period:
+                      description: ''
+                      type: integer
+                    hit_set_search_last_n:
+                      description: ''
+                      type: integer
+                    last_change:
+                      description: ''
+                      type: string
+                    last_force_op_resend:
+                      description: ''
+                      type: string
+                    last_force_op_resend_preluminous:
+                      description: ''
+                      type: string
+                    last_force_op_resend_prenautilus:
+                      description: ''
+                      type: string
+                    last_pg_merge_meta:
+                      description: ''
+                      properties:
+                        last_epoch_clean:
+                          description: ''
+                          type: integer
+                        last_epoch_started:
+                          description: ''
+                          type: integer
+                        ready_epoch:
+                          description: ''
+                          type: integer
+                        source_pgid:
+                          description: ''
+                          type: string
+                        source_version:
+                          description: ''
+                          type: string
+                        target_version:
+                          description: ''
+                          type: string
+                      required:
+                      - ready_epoch
+                      - last_epoch_started
+                      - last_epoch_clean
+                      - source_pgid
+                      - source_version
+                      - target_version
+                      type: object
+                    min_read_recency_for_promote:
+                      description: ''
+                      type: integer
+                    min_size:
+                      description: ''
+                      type: integer
+                    min_write_recency_for_promote:
+                      description: ''
+                      type: integer
+                    object_hash:
+                      description: ''
+                      type: integer
+                    options:
+                      description: ''
+                      properties:
+                        pg_num_min:
+                          description: ''
+                          type: integer
+                      required:
+                      - pg_num_min
+                      type: object
+                    pg_autoscale_mode:
+                      description: ''
+                      type: string
+                    pg_num:
+                      description: ''
+                      type: integer
+                    pg_num_pending:
+                      description: ''
+                      type: integer
+                    pg_num_target:
+                      description: ''
+                      type: integer
+                    pg_placement_num:
+                      description: ''
+                      type: integer
+                    pg_placement_num_target:
+                      description: ''
+                      type: integer
+                    pool:
+                      description: pool id
+                      type: integer
+                    pool_name:
+                      description: pool name
+                      type: string
+                    pool_snaps:
+                      description: ''
+                      items:
                         type: string
-                      target_version:
-                        description: ''
+                      type: array
+                    quota_max_bytes:
+                      description: ''
+                      type: integer
+                    quota_max_objects:
+                      description: ''
+                      type: integer
+                    read_tier:
+                      description: ''
+                      type: integer
+                    removed_snaps:
+                      description: ''
+                      items:
                         type: string
-                    required:
-                    - ready_epoch
-                    - last_epoch_started
-                    - last_epoch_clean
-                    - source_pgid
-                    - source_version
-                    - target_version
-                    type: object
-                  min_read_recency_for_promote:
-                    description: ''
-                    type: integer
-                  min_size:
-                    description: ''
-                    type: integer
-                  min_write_recency_for_promote:
-                    description: ''
-                    type: integer
-                  object_hash:
-                    description: ''
-                    type: integer
-                  options:
-                    description: ''
-                    properties:
-                      pg_num_min:
-                        description: ''
-                        type: integer
-                    required:
-                    - pg_num_min
-                    type: object
-                  pg_autoscale_mode:
-                    description: ''
-                    type: string
-                  pg_num:
-                    description: ''
-                    type: integer
-                  pg_num_pending:
-                    description: ''
-                    type: integer
-                  pg_num_target:
-                    description: ''
-                    type: integer
-                  pg_placement_num:
-                    description: ''
-                    type: integer
-                  pg_placement_num_target:
-                    description: ''
-                    type: integer
-                  pool:
-                    description: pool id
-                    type: integer
-                  pool_name:
-                    description: pool name
-                    type: string
-                  pool_snaps:
-                    description: ''
-                    items:
-                      type: string
-                    type: array
-                  quota_max_bytes:
-                    description: ''
-                    type: integer
-                  quota_max_objects:
-                    description: ''
-                    type: integer
-                  read_tier:
-                    description: ''
-                    type: integer
-                  removed_snaps:
-                    description: ''
-                    items:
+                      type: array
+                    size:
+                      description: pool size
+                      type: integer
+                    snap_epoch:
+                      description: ''
+                      type: integer
+                    snap_mode:
+                      description: ''
                       type: string
-                    type: array
-                  size:
-                    description: pool size
-                    type: integer
-                  snap_epoch:
-                    description: ''
-                    type: integer
-                  snap_mode:
-                    description: ''
-                    type: string
-                  snap_seq:
-                    description: ''
-                    type: integer
-                  stripe_width:
-                    description: ''
-                    type: integer
-                  target_max_bytes:
-                    description: ''
-                    type: integer
-                  target_max_objects:
-                    description: ''
-                    type: integer
-                  tier_of:
-                    description: ''
-                    type: integer
-                  tiers:
-                    description: ''
-                    items:
+                    snap_seq:
+                      description: ''
+                      type: integer
+                    stripe_width:
+                      description: ''
+                      type: integer
+                    target_max_bytes:
+                      description: ''
+                      type: integer
+                    target_max_objects:
+                      description: ''
+                      type: integer
+                    tier_of:
+                      description: ''
+                      type: integer
+                    tiers:
+                      description: ''
+                      items:
+                        type: string
+                      type: array
+                    type:
+                      description: type of pool
                       type: string
-                    type: array
-                  type:
-                    description: type of pool
-                    type: string
-                  use_gmt_hitset:
-                    description: ''
-                    type: boolean
-                  write_tier:
-                    description: ''
-                    type: integer
+                    use_gmt_hitset:
+                      description: ''
+                      type: boolean
+                    write_tier:
+                      description: ''
+                      type: integer
+                  type: object
                 required:
                 - pool
                 - pool_name
@@ -6112,7 +6130,7 @@ paths:
                 - last_force_op_resend_prenautilus
                 - last_force_op_resend_preluminous
                 - removed_snaps
-                type: object
+                type: array
           description: OK
         '400':
           description: Operation exception. Please check the response body for details.
@@ -6601,21 +6619,23 @@ paths:
           content:
             application/json:
               schema:
-                properties:
-                  id:
-                    description: Daemon ID
-                    type: string
-                  server_hostname:
-                    description: ''
-                    type: string
-                  version:
-                    description: Ceph Version
-                    type: string
+                items:
+                  properties:
+                    id:
+                      description: Daemon ID
+                      type: string
+                    server_hostname:
+                      description: ''
+                      type: string
+                    version:
+                      description: Ceph Version
+                      type: string
+                  type: object
                 required:
                 - id
                 - version
                 - server_hostname
-                type: object
+                type: array
           description: OK
         '400':
           description: Operation exception. Please check the response body for details.
@@ -7219,33 +7239,35 @@ paths:
           content:
             application/json:
               schema:
-                properties:
-                  description:
-                    description: Role Descriptions
-                    type: string
-                  name:
-                    description: Role Name
-                    type: string
-                  scopes_permissions:
-                    description: ''
-                    properties:
-                      cephfs:
-                        description: ''
-                        items:
-                          type: string
-                        type: array
-                    required:
-                    - cephfs
-                    type: object
-                  system:
-                    description: ''
-                    type: boolean
+                items:
+                  properties:
+                    description:
+                      description: Role Descriptions
+                      type: string
+                    name:
+                      description: Role Name
+                      type: string
+                    scopes_permissions:
+                      description: ''
+                      properties:
+                        cephfs:
+                          description: ''
+                          items:
+                            type: string
+                          type: array
+                      required:
+                      - cephfs
+                      type: object
+                    system:
+                      description: ''
+                      type: boolean
+                  type: object
                 required:
                 - name
                 - description
                 - scopes_permissions
                 - system
-                type: object
+                type: array
           description: OK
         '400':
           description: Operation exception. Please check the response body for details.
@@ -7587,25 +7609,27 @@ paths:
           content:
             application/json:
               schema:
-                properties:
-                  default:
-                    description: Default Settings
-                    type: boolean
-                  name:
-                    description: Settings Name
-                    type: string
-                  type:
-                    description: Type of Settings
-                    type: string
-                  value:
-                    description: Settings Value
-                    type: boolean
+                items:
+                  properties:
+                    default:
+                      description: Default Settings
+                      type: boolean
+                    name:
+                      description: Settings Name
+                      type: string
+                    type:
+                      description: Type of Settings
+                      type: string
+                    value:
+                      description: Settings Value
+                      type: boolean
+                  type: object
                 required:
                 - name
                 - default
                 - type
                 - value
-                type: object
+                type: array
           description: OK
         '400':
           description: Operation exception. Please check the response body for details.
index db5eefdddec388c5ce641d0531f3bee236eac1ea..a86f2b678f3c0291725fc4773191c7fc212ba8a6 100644 (file)
@@ -1,6 +1,7 @@
 # # -*- coding: utf-8 -*-
 from __future__ import absolute_import
 
+from ..api.doc import SchemaType
 from ..controllers import ApiController, ControllerDoc, Endpoint, EndpointDoc, RESTController
 from ..controllers.docs import Docs
 from . import ControllerTestCase  # pylint: disable=no-name-in-module
@@ -10,6 +11,8 @@ from . import ControllerTestCase  # pylint: disable=no-name-in-module
 @ControllerDoc("Group description", group="FooGroup")
 @ApiController("/doctest/", secure=False)
 class DecoratedController(RESTController):
+    RESOURCE_ID = 'doctest'
+
     @EndpointDoc(
         description="Endpoint description",
         group="BarGroup",
@@ -17,12 +20,16 @@ class DecoratedController(RESTController):
             'parameter': (int, "Description of parameter"),
         },
         responses={
-            200: {
-                'resp': (str, 'Description of response')
+            200: [{
+                'my_prop': (str, '200 property desc.')
+            }],
+            202: {
+                'my_prop': (str, '202 property desc.')
             },
         },
     )
     @Endpoint(json_response=False)
+    @RESTController.Resource('PUT')
     def decorated_func(self, parameter):
         pass
 
@@ -54,18 +61,48 @@ class DocDecoratorsTest(ControllerTestCase):
 class DocsTest(ControllerTestCase):
     @classmethod
     def setup_server(cls):
-        cls.setup_controllers([Docs], "/test")
+        cls.setup_controllers([DecoratedController, Docs], "/test")
 
     def test_type_to_str(self):
-        self.assertEqual(Docs()._type_to_str(str), "string")
+        self.assertEqual(Docs()._type_to_str(str), str(SchemaType.STRING))
+        self.assertEqual(Docs()._type_to_str(int), str(SchemaType.INTEGER))
+        self.assertEqual(Docs()._type_to_str(bool), str(SchemaType.BOOLEAN))
+        self.assertEqual(Docs()._type_to_str(list), str(SchemaType.ARRAY))
+        self.assertEqual(Docs()._type_to_str(tuple), str(SchemaType.ARRAY))
+        self.assertEqual(Docs()._type_to_str(float), str(SchemaType.NUMBER))
+        self.assertEqual(Docs()._type_to_str(object), str(SchemaType.OBJECT))
+        self.assertEqual(Docs()._type_to_str(None), str(SchemaType.OBJECT))
 
     def test_gen_paths(self):
-        outcome = Docs()._gen_paths(False)['/api/doctest//decorated_func/{parameter}']['get']
+        outcome = Docs()._gen_paths(False)['/api/doctest//{doctest}/decorated_func']['put']
         self.assertIn('tags', outcome)
         self.assertIn('summary', outcome)
         self.assertIn('parameters', outcome)
         self.assertIn('responses', outcome)
 
+        expected_response_content = {
+            '200': {
+                'application/json': {
+                    'schema': {'type': 'array',
+                               'items': {'type': 'object', 'properties': {
+                                   'my_prop': {
+                                       'type': 'string',
+                                       'description': '200 property desc.'}}},
+                               'required': ['my_prop']}}},
+            '202': {
+                'application/json': {
+                    'schema': {'type': 'object',
+                               'properties': {'my_prop': {
+                                   'type': 'string',
+                                   'description': '202 property desc.'}},
+                               'required': ['my_prop']}}
+            }
+        }
+        # Check that a schema of type 'array' is received in the response.
+        self.assertEqual(expected_response_content['200'], outcome['responses']['200']['content'])
+        # Check that a schema of type 'object' is received in the response.
+        self.assertEqual(expected_response_content['202'], outcome['responses']['202']['content'])
+
     def test_gen_paths_all(self):
         paths = Docs()._gen_paths(False)
         for key in paths:
index efe18ffc8d7fe5029b266beb5d04e1a85760a4f9..39ae748844cdb9eb1783de5993228a70be0872db 100644 (file)
@@ -84,7 +84,7 @@ wrap_length = 80
 [pylint]
 # Allow similarity/code duplication detection
 jobs = 1
-dirs = . controllers plugins services tests
+dirs = . api controllers plugins services tests
 addopts = -rn --rcfile=.pylintrc --jobs={[pylint]jobs}
 
 [rstlint]