--- /dev/null
+from __future__ import absolute_import
--- /dev/null
+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]
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
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 = {
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)
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*"
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
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']:
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)
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):
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
@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 = []
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.
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.
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
- max
- can_update_at_runtime
- flags
- type: object
+ type: array
description: OK
'400':
description: Operation exception. Please check the response body for details.
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
- plugin
- technique
- name
- type: object
+ type: array
description: OK
'400':
description: Operation exception. Please check the response body for details.
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.
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.
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.
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
- transports
- fsal
- clients
- type: object
+ type: array
description: OK
'400':
description: Operation exception. Please check the response body for details.
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
- 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.
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.
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.
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.
# # -*- 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
@ControllerDoc("Group description", group="FooGroup")
@ApiController("/doctest/", secure=False)
class DecoratedController(RESTController):
+ RESOURCE_ID = 'doctest'
+
@EndpointDoc(
description="Endpoint description",
group="BarGroup",
'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
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:
[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]