Example #1
0
 def convert_field_info_to_swagger_parameter(self, param_type,
                                             input_parameter_obj, type_dict,
                                             structure_svc, enum_svc,
                                             show_unreleased_apis):
     """
     Converts metamodel fieldinfo to swagger parameter.
     """
     parameter_obj = {}
     ref_path = "#/definitions/"
     tpHandler = RestTypeHandler(show_unreleased_apis)
     tpHandler.visit_type_category(input_parameter_obj.type, parameter_obj,
                                   type_dict, structure_svc, enum_svc,
                                   ref_path)
     if 'required' not in parameter_obj:
         parameter_obj['required'] = True
     parameter_obj['in'] = param_type
     parameter_obj['name'] = input_parameter_obj.name
     parameter_obj['description'] = input_parameter_obj.documentation
     # $ref should be encapsulated in 'schema' instead of parameter. -> this throws swagger validation error
     # hence another method is to to get data in $ref in parameter_obj
     # itself
     if '$ref' in parameter_obj:
         type_obj = type_dict[parameter_obj['$ref'][len(ref_path):]]
         description = parameter_obj['description']
         if 'description' in type_obj:
             description = ""
             description = "{ 1. " + type_obj['description'] + \
                 " }, { 2. " + parameter_obj['description'] + " }"
         parameter_obj.update(type_obj)
         parameter_obj['description'] = description
         del parameter_obj['$ref']
     return parameter_obj
Example #2
0
    def wrap_body_params(
            self,
            service_name,
            operation_name,
            body_param_list,
            type_dict,
            structure_svc,
            enum_svc,
            show_unreleased_apis):
        """
        Creates a  json object wrapper around request body parameters. parameter names are used as keys and the
        parameters as values.
        For instance, datacenter create operation takes CreateSpec whose parameter name is spec.
        This method creates a json wrapper object
        datacenter.create {
        'spec' : {spec obj representation  }
        }
        """
        # todo:
        # not unique enough. make it unique
        wrapper_name = service_name + '_' + operation_name
        body_obj = {}
        properties_obj = {}
        body_obj['type'] = 'object'
        body_obj['properties'] = properties_obj
        required = []
        ref_path = "#/components/schemas/"
        tpHandler = RestTypeHandler(show_unreleased_apis)
        for param in body_param_list:
            parameter_obj = {}
            tpHandler.visit_type_category(
                param.type,
                parameter_obj,
                type_dict,
                structure_svc,
                enum_svc,
                ref_path)
            parameter_obj['description'] = param.documentation
            properties_obj[param.name] = parameter_obj
            if 'required' not in parameter_obj:
                required.append(param.name)
            elif parameter_obj['required'] == 'true':
                required.append(param.name)

        if 'requestBodies' not in type_dict:
            type_dict['requestBodies'] = {}
        type_dict['requestBodies'][wrapper_name] = {
            'content': {
                'application/json': {
                    'schema': {
                        '$ref': ref_path + wrapper_name
                    }
                }
            }
        }
        type_dict[wrapper_name] = body_obj
        parameter_obj = {'$ref': "#/components/requestBodies/" + wrapper_name}

        return parameter_obj
Example #3
0
    def wrap_body_params(
            self,
            service_name,
            operation_name,
            body_param_list,
            type_dict,
            structure_svc,
            enum_svc,
            enable_filtering):
        """
        Creates a  json object wrapper around request body parameters. parameter names are used as keys and the
        parameters as values.
        For instance, datacenter create operation takes CreateSpec whose parameter name is spec.
        This method creates a json wrapper object
        datacenter.create {
        'spec' : {spec obj representation  }
        }
        """
        # todo:
        # not unique enough. make it unique
        wrapper_name = service_name + '_' + operation_name
        body_obj = {}
        properties_obj = {}
        body_obj['type'] = 'object'
        body_obj['properties'] = properties_obj
        required = []
        ref_path = "#/definitions/"
        tpHandler = RestTypeHandler()
        for param in body_param_list:
            parameter_obj = {}
            tpHandler.visit_type_category(
                param.type,
                parameter_obj,
                type_dict,
                structure_svc,
                enum_svc,
                ref_path,
                enable_filtering)
            parameter_obj['description'] = param.documentation
            properties_obj[param.name] = parameter_obj
            if 'required' not in parameter_obj:
                required.append(param.name)
            elif parameter_obj['required'] == 'true':
                required.append(param.name)

        parameter_obj = {'in': 'body', 'name': 'request_body'}
        if len(required) > 0:
            body_obj['required'] = required
            parameter_obj['required'] = True
        elif 'required' in body_obj:
            del body_obj['required']

        type_dict[wrapper_name] = body_obj

        schema_obj = {'$ref': ref_path + wrapper_name}
        parameter_obj['schema'] = schema_obj

        return parameter_obj
class TestRestTypeHandler(unittest.TestCase):
    # Showing unreleased apis (disabled filtering)
    rest_tphandler = RestTypeHandler(True)

    def test_visit_generic(self):
        # case 1: when generic instantiation type is 'SET' and category is 'BUILT-IN'
        generic_instantiation_element_type_mock = mock.Mock() 
        generic_instantiation_element_type_mock.category = 'BUILTIN'
        generic_instantiation_element_type_mock.builtin_type = 'date-time'
        generic_instantiation_mock = mock.Mock()
        generic_instantiation_mock.generic_type = 'SET'
        generic_instantiation_mock.element_type = generic_instantiation_element_type_mock
        
        field_info_mock = mock.Mock()
        field_info_type = mock.Mock()
        field_info_type.category = 'BUILTIN'
        field_info_type.builtin_type = 'date-time'
        field_info_mock.type = field_info_type
        field_info_mock.generic_instantiation = generic_instantiation_mock
        field_info_mock.documentation = 'fieldInfoMockDescription'
        field_info_mock.name = 'fieldInfoMockName'
        field_info_mock.metadata = {}
        structure_info_mock = mock.Mock()
        structure_info_mock.fields = [field_info_mock]
        structure_dict = {
            'com.vmware.package.mock': structure_info_mock
        }
        '''
        The structure dict looks like: 
        structure_dict = {
            'com.vmware.package.mock': StructureInfo( fields = [ FieldInfo(
                name = 'fieldInfoMockName', documentation =  'fieldInfoMockDescription',
                generic_instantiation = GenericInstantiation( generic_type = 'SET',
                element_type = Type( category = 'BUILTIN', builtin_type = 'date-time'))
            )])
        }
        '''
        enum_dict = {}
        type_dict = {}
        new_prop = {}
        self.rest_tphandler.visit_generic(generic_instantiation_mock, new_prop, type_dict, structure_dict, enum_dict, '#/definitions/')
        new_prop_expected = {'type': 'array', 'uniqueItems': True, 'items': {'type': 'date-time'}}
        self.assertEqual(new_prop_expected, new_prop)

        # case 2: when generic instantiation type is 'OPTIONAL' and category is 'BUILT-IN'
        generic_instantiation_mock.generic_type = 'OPTIONAL'
        enum_dict = {}
        type_dict = {}
        new_prop = {}
        self.rest_tphandler.visit_generic(generic_instantiation_mock, new_prop, type_dict, structure_dict, enum_dict, '#/definitions/')
        new_prop_expected = {'required': False, 'type': 'date-time'}
        self.assertEqual(new_prop_expected, new_prop)

        # case 3: when generic instantiation type is 'LIST' and category is 'USER-DEFINED'
        generic_instantiation_mock.generic_type = 'LIST'
        user_defined_type_mock = mock.Mock()
        user_defined_type_mock.resource_type = 'com.vmware.vapi.structure'
        user_defined_type_mock.resource_id = 'com.vmware.package.mock'
        generic_instantiation_element_type_mock.category = 'USER_DEFINED'
        generic_instantiation_element_type_mock.user_defined_type = user_defined_type_mock
        '''
        The structure dict looks like: 
        structure_dict = {
            'com.vmware.package.mock': StructureInfo( fields = [ FieldInfo(
                name = 'fieldInfoMockName', documentation =  'fieldInfoMockDescription',
                generic_instantiation = GenericInstantiation( generic_type = 'LIST',
                element_type = Type( category = 'USER_DEFINED', user_defined_type = UserDefinedType(
                    resource_type = 'com.vmware.vapi.structure', resource_id = 'com.vmware.package.mock'
                )))
            )])
        }
        '''
        enum_dict = {}
        type_dict = {}
        new_prop = {}
        self.rest_tphandler.visit_generic(generic_instantiation_mock, new_prop, type_dict, structure_dict, enum_dict, '#/definitions/')
        new_prop_expected = {'type': 'array', 'items': {'$ref': '#/definitions/com.vmware.package.mock'}}
        self.assertEqual(new_prop_expected, new_prop)

        # case 4: when generic instantiation type is 'MAP'
        # case 4.1: map key and value type is 'BUILTIN'
        map_key_type_mock = mock.Mock()
        map_key_type_mock.category = 'BUILTIN'
        map_key_type_mock.builtin_type = 'long'
        map_value_type_mock = mock.Mock()
        map_value_type_mock.category = 'BUILTIN'
        map_value_type_mock.builtin_type = 'long'
        generic_instantiation_mock = mock.Mock()
        generic_instantiation_mock.generic_type = 'MAP'
        generic_instantiation_mock.map_key_type = map_key_type_mock
        generic_instantiation_mock.map_value_type = map_value_type_mock
        '''
        The structure dict looks like: 
        structure_dict = {
            'com.vmware.package.mock': StructureInfo( fields = [ FieldInfo(
                name = 'fieldInfoMockName', documentation =  'fieldInfoMockDescription',
                generic_instantiation = GenericInstantiation( generic_type = 'MAP',
                map_key_type = MapKeyType( category = 'BUILTIN', builtin_type = 'long'),
                map_value_type = MapValueType( category = 'BUILTIN', builtin_type = 'long')
                )
            )])
        }
        '''
        enum_dict = {}
        type_dict = {}
        new_prop = {}
        self.rest_tphandler.visit_generic(generic_instantiation_mock, new_prop, type_dict, structure_dict, enum_dict, '#/definitions/')
        new_prop_expected = {
            'type': 'array', 
            'items': {
                'type': 'object', 
                'properties': {
                    'key': {'type': 'integer'}, 
                    'value': {'type': 'integer'}
                    }
                }
            }
        self.assertEqual(new_prop_expected, new_prop)

        # case 4.2: map key and value type is 'USER_DEFINED'
        map_key_type_mock.category = 'USER_DEFINED'
        map_key_type_mock.user_defined_type = user_defined_type_mock
        map_value_type_mock.category = 'USER_DEFINED'
        map_value_type_mock.user_defined_type = user_defined_type_mock
        type_dict = {
            'com.vmware.package.mock': {}
        }
        new_prop = {}
        self.rest_tphandler.visit_generic(generic_instantiation_mock, new_prop, type_dict, structure_dict, enum_dict, '#/definitions/')
        new_prop_expected = {
            'type': 'array', 
            'items': {
                'type': 'object', 
                'properties': {
                    'key': {'$ref': '#/definitions/com.vmware.package.mock'}, 
                    'value': {'$ref': '#/definitions/com.vmware.package.mock'}
                    }
                }
            }
        self.assertEqual(new_prop_expected, new_prop)

        # case 4.3: map key and value type is 'GENERIC'
        generic_instantiation_element_type_mock.category = 'BUILTIN'
        generic_instantiation_element_type_mock.builtin_type = 'double'
        generic_instantiation_map_value_type_mock = mock.Mock()
        generic_instantiation_map_value_type_mock.generic_type = 'OPTIONAL'
        generic_instantiation_map_value_type_mock.element_type = generic_instantiation_element_type_mock
        map_key_type_mock.category = 'BUILTIN'
        map_key_type_mock.builtin_type = 'string'
        map_value_type_mock.category = 'GENERIC'
        map_value_type_mock.generic_instantiation = generic_instantiation_map_value_type_mock
        new_prop = {}
        self.rest_tphandler.visit_generic(generic_instantiation_mock, new_prop, type_dict, structure_dict, enum_dict, '#/definitions/')
        new_prop_expected = {
            'type': 'array', 
            'items': {
                'type': 'object', 
                'properties': {
                    'key': {'type': 'string'}, 
                    'value': {
                            'required': False,
                            'type': 'number', 'format': 'double'
                        }
                    }
                }
            }
        self.assertEqual(new_prop_expected, new_prop)
    def populate_response_map(self, output, errors, http_error_map, type_dict,
                              structure_svc, enum_svc, service_id,
                              operation_id, enable_filtering):

        response_map = {}
        ref_path = "#/definitions/"
        success_response = {'description': output.documentation}
        schema = {}
        tpHandler = RestTypeHandler()
        tpHandler.visit_type_category(output.type, schema, type_dict,
                                      structure_svc, enum_svc, ref_path,
                                      enable_filtering)
        # if type of schema is void, don't include it.
        # this prevents showing response as void in swagger-ui
        if schema is not None:
            if not ('type' in schema and schema['type'] == 'void'):
                # Handling Value wrappers for /rest and /api
                resp = {
                    'type': 'object',
                    'properties': {
                        'value': schema
                    },
                    'required': ['value']
                }
                if operation_id == 'get':
                    type_name = service_id
                else:
                    type_name = service_id + '.' + operation_id

                type_name = type_name + '_result'

                if type_name not in type_dict:
                    type_dict[type_name] = resp
                resp = {"$ref": ref_path + type_name}
                success_response['schema'] = resp

        # success response is not mapped through metamodel.
        # hardcode it for now.
        response_map[requests.codes.ok] = success_response

        for error in errors:
            status_code = http_error_map.error_rest_map.get(
                error.structure_id, http_client.INTERNAL_SERVER_ERROR)
            tpHandler.check_type('com.vmware.vapi.structure',
                                 error.structure_id, type_dict, structure_svc,
                                 enum_svc, ref_path, enable_filtering)
            schema_obj = {
                'type': 'object',
                'properties': {
                    'type': {
                        'type': 'string'
                    },
                    'value': {
                        '$ref': ref_path + error.structure_id
                    }
                }
            }
            type_dict[error.structure_id + '_error'] = schema_obj
            response_obj = {
                'description': error.documentation,
                'schema': {
                    '$ref': ref_path + error.structure_id + '_error'
                }
            }
            response_map[status_code] = response_obj

        return response_map
Example #6
0
    def flatten_query_param_spec(self, query_param_info, type_dict,
                                 structure_svc, enum_svc,
                                 show_unreleased_apis):
        """
        Flattens query parameters specs.
        1. Create a query parameter for every field in spec.
            Example 1:
                consider datacenter get which accepts optional filterspec.
                Optional<Datacenter.FilterSpec> filter)
                The method would convert the filterspec to 3 separate query parameters
                filter.datacenters, filter.names and filter.folders.
            Example 2:
                consider /vcenter/deployment/install/initial-config/remote-psc/thumbprint get
                which accepts parameter
                vcenter.deployment.install.initial_config.remote_psc.thumbprint.remote_spec.
                The two members defined under remote_spec
                address and https_port are converted to two separate query parameters
                address(required) and https_port(optional).
        2. The field info is simple type. i.e the type is string, integer
            then it is converted it to swagger parameter.
            Example:
                consider /com/vmware/content/library/item get
                which accepts parameter 'library_id'. The field is converted
                to library_id query parameter.
        3. This field has references to a spec but the spec is not
            a complex type and does not have property 'properties'.
            i.e the type is string, integer. The members defined under the spec are
            converted to query parameter.
            Example:
                consider /appliance/update/pending get which accepts two parameter
                'source_type' and url. Where source_type is defined in the spec
                'appliance.update.pending.source_type' and field url
                is of type string.
                The fields 'source_type' and 'url' are converted to query parameter
                of type string.
        """
        prop_array = []
        parameter_obj = {}
        ref_path = "#/components/schemas/"
        tpHandler = RestTypeHandler(show_unreleased_apis)
        tpHandler.visit_type_category(query_param_info.type, parameter_obj,
                                      type_dict, structure_svc, enum_svc,
                                      ref_path)
        if '$ref' in parameter_obj:
            reference = parameter_obj['$ref'].replace(ref_path, '')
            type_ref = type_dict.get(reference, None)
            if type_ref is None:
                return None
            if 'properties' in type_ref:
                for property_name, property_value in six.iteritems(
                        type_ref['properties']):
                    prop = {
                        'in': 'query',
                        'name': query_param_info.name + '.' + property_name
                    }
                    prop['schema'] = {}
                    if 'type' in property_value:
                        prop['schema']['type'] = property_value['type']
                        if property_value['type'] == 'array':
                            prop['schema']['items'] = property_value['items']
                            if '$ref' in property_value['items']:
                                ref = property_value['items']['$ref'].replace(
                                    ref_path, '')
                                type_ref = type_dict[ref]
                                prop['schema']['items'] = type_ref
                                if 'description' in prop['schema']['items']:
                                    del prop['schema']['items']['description']
                        if 'description' in property_value:
                            prop['description'] = property_value['description']
                    elif '$ref' in property_value:
                        reference = property_value['$ref'].replace(
                            ref_path, '')
                        prop_obj = type_dict[reference]
                        prop['schema'] = prop_obj
                    if 'required' in type_ref:
                        if property_name in type_ref['required']:
                            prop['required'] = True
                        else:
                            prop['required'] = False
                    prop_array.append(prop)
            else:
                prop = {
                    'in': 'query',
                    'name': query_param_info.name,
                    'description': type_ref['description'],
                    'schema': type_ref
                }
                prop_array.append(prop)
        else:
            parameter_obj['in'] = 'query'
            parameter_obj['name'] = query_param_info.name
            parameter_obj['description'] = query_param_info.documentation
            if 'required' not in parameter_obj:
                parameter_obj['required'] = True

            parameter_obj['schema'] = {"type": parameter_obj['type']}
            del parameter_obj['type']

            prop_array.append(parameter_obj)
        return prop_array