Example #1
0
    def get_service_table_line(self, idx, name, docs, sio):
        name_fs_safe = 'service_{}'.format(fs_safe_name(name))
        file_name = '{}.rst'.format(name_fs_safe)

        summary = docs.summary
        if summary:
            summary = self._make_sphinx_safe(summary)

        return bunchify({
            'ns':
            unicode(idx),
            'orig_name':
            name,
            'sphinx_name':
            name.replace('_', '\_'),  # Needed for Sphinx to ignore undescores
            'name':
            name_fs_safe,
            'name_link':
            """:doc:`{} <./{}>`""".format(name, name_fs_safe),
            'file_name':
            file_name,
            'description':
            summary or no_value,
            'docs':
            docs,
            'sio':
            sio
        })
Example #2
0
    def handle_return_data(self, return_data):

        for item in return_data['items']:

            item.id = fs_safe_name('{}-{}'.format(item.name, item.pid))

            if item.last_gd_run:
                item.last_gd_run_utc = item.last_gd_run

                if item.last_gd_run_utc:
                    item.last_gd_run = from_utc_to_user(
                        item.last_gd_run_utc + '+00:00',
                        self.req.zato.user_profile)

            if item.last_task_run:
                item.last_task_run_utc = item.last_task_run
                item.last_task_run = from_utc_to_user(
                    item.last_task_run_utc + '+00:00',
                    self.req.zato.user_profile)

        return return_data
Example #3
0
    def handle_return_data(self, return_data):

        for item in return_data['items']:

            item.id = fs_safe_name(item.py_object)

            if item.last_sync:
                item.last_sync_utc = item.last_sync
                item.last_sync = from_utc_to_user(
                    item.last_sync_utc + '+00:00', self.req.zato.user_profile)

            if item.last_sync_sk:
                item.last_sync_sk_utc = item.last_sync_sk
                item.last_sync_sk = from_utc_to_user(
                    item.last_sync_sk_utc + '+00:00',
                    self.req.zato.user_profile)

            if item.last_iter_run:
                item.last_iter_run_utc = item.last_iter_run
                item.last_iter_run = from_utc_to_user(
                    item.last_iter_run_utc + '+00:00',
                    self.req.zato.user_profile)

        return return_data
Example #4
0
    def test_generate_open_api(self):

        MyClass = deepcopy(MyService)
        CySimpleIO.attach_sio(self.get_server_config(), MyClass)

        service_store_services = {
            'my.impl.name': {
                'name': service_name,
                'service_class': MyClass,
            }
        }
        include = ['*']
        exclude = []
        query   = ''
        tags    = 'public'

        generator = Generator(service_store_services, sio_config, include, exclude, query, tags, needs_sio_desc=False)

        info = generator.get_info()
        info = bunchify(info)

        channel_data = [{
            'service_name': service_name,
            'transport':    URL_TYPE.PLAIN_HTTP,
            'url_path':     '/test/{phone_number}',
            'match_target_compiled': _MatchTestCompiled()
        }]
        needs_api_invoke = True
        needs_rest_channels = True
        api_invoke_path = APISPEC.GENERIC_INVOKE_PATH

        open_api_generator = OpenAPIGenerator(info, channel_data, needs_api_invoke, needs_rest_channels, api_invoke_path)

        result = open_api_generator.generate()
        result = yaml_load(result, FullLoader)
        result = bunchify(result)

        result_components = result.components # type: Bunch
        result_info       = result.info       # type: Bunch
        result_openapi    = result.openapi    # type: Bunch
        result_paths      = result.paths      # type: Bunch
        result_servers    = result.servers    # type: Bunch

        localhost = result_servers[0]
        self.assertEqual(localhost.url, 'http://localhost:11223')

        self.assertEqual(result_info.title, 'API spec')
        self.assertEqual(result_info.version, '1.0')
        self.assertEqual(result_openapi, '3.0.2')

        self.assertEqual(len(result_components.schemas), 2)

        request_my_service_properties = result_components.schemas.request_my_service.properties
        request_my_service_required   = result_components.schemas.request_my_service.required
        request_my_service_title      = result_components.schemas.request_my_service.title
        request_my_service_type       = result_components.schemas.request_my_service.type

        response_my_service_required   = result_components.schemas.response_my_service.required
        response_my_service_title      = result_components.schemas.response_my_service.title
        response_my_service_type       = result_components.schemas.response_my_service.type

        self.assertEqual(request_my_service_title, 'Request object for my.service')
        self.assertEqual(response_my_service_title, 'Response object for my.service')

        self.assertEqual(request_my_service_type, 'object')
        self.assertEqual(response_my_service_type, 'object')

        self.assertListEqual(sorted(request_my_service_required), ['input_req_customer_id', 'input_req_user_id'])
        self.assertListEqual(sorted(response_my_service_required), ['output_req_address_id', 'output_req_address_name'])

        self.assertEqual(request_my_service_properties.input_req_user_id.type, 'integer')
        self.assertEqual(request_my_service_properties.input_req_user_id.format, 'int32')
        self.assertEqual(request_my_service_properties.input_req_user_id.description,
            'This is the first line.\nHere is another.\nAnd here are some more lines.')

        self.assertEqual(request_my_service_properties.input_req_customer_id.type, 'integer')
        self.assertEqual(request_my_service_properties.input_req_customer_id.format, 'int32')
        self.assertEqual(request_my_service_properties.input_req_customer_id.description, '')

        self.assertEqual(request_my_service_properties.input_opt_user_name.type, 'string')
        self.assertEqual(request_my_service_properties.input_opt_user_name.format, 'string')
        self.assertEqual(request_my_service_properties.input_opt_user_name.description, 'b111')

        self.assertEqual(request_my_service_properties.input_opt_customer_name.type, 'string')
        self.assertEqual(request_my_service_properties.input_opt_customer_name.format, 'string')
        self.assertEqual(request_my_service_properties.input_opt_customer_name.description, '')

        self.assertEqual(len(result_paths), 2)

        for url_path in ['/test/{phone_number}', '/zato/api/invoke/my.service']:

            my_service_path = result_paths[url_path] # type: Bunch
            post = my_service_path.post

            self.assertListEqual(post.consumes, ['application/json'])
            self.assertEqual(post.operationId, 'post_{}'.format(fs_safe_name(url_path)))
            self.assertTrue(post.requestBody.required)
            self.assertEqual(
                post.requestBody.content['application/json'].schema['$ref'], '#/components/schemas/request_my_service')
            self.assertEqual(
                post.responses['200'].content['application/json'].schema['$ref'], '#/components/schemas/response_my_service')
Example #5
0
 def get_endpoint_name(cluster_name, server_name, target_pid):
     return fs_safe_name('{}-{}-{}'.format(cluster_name, server_name,
                                           target_pid))
Example #6
0
 def _get_response_name(self, service_name):
     return 'response_{}'.format(fs_safe_name(service_name))
Example #7
0
 def _get_request_name(self, service_name):
     return 'request_{}'.format(fs_safe_name(service_name))
Example #8
0
    def generate(self):
        # Basic information, always available
        out = Bunch()
        out.openapi = '3.0.2'
        out.info = {
            'title': 'API spec',
            'version': '1.0',
        }
        out.servers = [{'url': 'http://localhost:11223'}]

        # Responses to refer to in paths
        out.components = Bunch()
        out.components.schemas = Bunch()

        # REST paths
        out.paths = Bunch()

        # Schemas for all services - it is possible that not all of them will be output,
        # for instance, if a service is not exposed through any REST channel.
        request_schemas = self._get_message_schemas(self.data, True)
        response_schemas = self._get_message_schemas(self.data, False)

        schemas = {}
        schemas.update(request_schemas)
        schemas.update(response_schemas)

        out.components.schemas.update(schemas)

        for item in self.data.services:

            # Container for all the URL paths found for this item (service)
            url_paths = []

            # Parameters carried in URL paths, e.g. /user/{username}/{lang_code},
            # all of them will be treated as required and all of them will be string ones.
            channel_params = []

            # Now, collect all the paths that the spec will contain ..

            # .. generic API invoker, e.g. /zato/api/invoke/{service_name} ..
            if self.needs_api_invoke and self.api_invoke_path:
                for path in self.api_invoke_path:
                    url_paths.append(path.format(service_name=item.name))

            # .. per-service specific REST channels.
            if self.needs_rest_channels:
                rest_channel = self.get_rest_channel(item.name)

                if rest_channel:

                    # This is always needed, whether path parameters exist or not
                    url_paths.append(rest_channel.url_path)

                    # Path parameters
                    group_names = rest_channel.match_target_compiled.group_names
                    if group_names:

                        # Populate details of path parameters
                        for channel_param_name in sorted(
                                group_names):  # type: str
                            channel_params.append({
                                'name': channel_param_name,
                                'description': '',
                                'in': 'path',
                                'required': True,
                                'schema': {
                                    'type': 'string',
                                    'format': 'string',
                                }
                            })

            # Translate the service name into a normalised form
            service_name_fs = fs_safe_name(item.name)

            for url_path in url_paths:

                out_path = out.paths.setdefault(url_path,
                                                Bunch())  # type: Bunch
                post = out_path.setdefault('post', Bunch())  # type: Bunch

                operation_id = 'post_{}'.format(fs_safe_name(url_path))
                consumes = ['application/json']

                request_ref = '#/components/schemas/{}'.format(
                    self._get_request_name(service_name_fs))
                response_ref = '#/components/schemas/{}'.format(
                    self._get_response_name(service_name_fs))

                request_body = Bunch()
                request_body.required = True

                request_body.content = Bunch()
                request_body.content['application/json'] = Bunch()
                request_body.content['application/json'].schema = Bunch()
                request_body.content['application/json'].schema[
                    '$ref'] = request_ref

                responses = Bunch()
                responses['200'] = Bunch()
                responses['200'].content = Bunch()
                responses['200'].content['application/json'] = Bunch()
                responses['200'].content['application/json'].schema = Bunch()
                responses['200'].content['application/json'].schema[
                    '$ref'] = response_ref

                post['operationId'] = operation_id
                post['consumes'] = consumes
                post['requestBody'] = request_body
                post['responses'] = responses

                if channel_params:
                    post['parameters'] = channel_params

        return yaml_dump(out.toDict(),
                         Dumper=YAMLDumper,
                         default_flow_style=False)