Ejemplo n.º 1
0
    def perform_request(self):
        """
        Perform the request.
        See https://github.com/geopython/OWSLib/blob/
        master/tests/doctests/wms_GeoServerCapabilities.txt
        """

        # Test capabilities doc
        result = Result(True, 'Test Capabilities')
        result.start()
        try:
            wms = WebMapService(self._resource.url)
            title = wms.identification.title
            self.log('response: title=%s' % title)
        except Exception as err:
            result.set(False, str(err))

        # Do more rigorous stuff here below
        result.stop()

        self.result.add_result(result)
Ejemplo n.º 2
0
    def perform_request(self):
        """
        Perform the request.
        See https://github.com/geopython/OWSLib/blob/
        master/tests/doctests/wms_GeoServerCapabilities.txt
        """

        # Test capabilities doc
        result = Result(True, 'Test Capabilities')
        result.start()
        try:
            wms = WebMapService(self._resource.url)
            title = wms.identification.title
            self.log('response: title=%s' % title)
        except Exception as err:
            result.set(False, str(err))

        # Do more rigorous stuff here below
        result.stop()

        self.result.add_result(result)
Ejemplo n.º 3
0
    def perform_request(self):
        """
        Perform the drilldown.
        """

        # Be sure to use bare root URL http://.../FeatureServer
        fs_url = self._resource.url.split('?')[0]

        # Assemble request templates with root FS URL
        req_tpl = {
            'fs_caps':
            fs_url + '?f=json',
            'layer_caps':
            fs_url + '/%d?f=json',
            'get_features':
            fs_url + '/%d/query?where=1=1'
            '&outFields=*&resultOffset=0&'
            'resultRecordCount=1&f=json',
            'get_feature_by_id':
            fs_url + '/%d/query?where=%s=%s&outFields=*&f=json'
        }

        # 1. Test top Service endpoint existence
        result = Result(True, 'Test Service Endpoint')
        result.start()
        layers = []
        try:
            fs_caps = self.perform_esrifs_get_request(req_tpl['fs_caps'])
            for attr in ['currentVersion', 'layers']:
                val = fs_caps.get(attr, None)
                if val is None:
                    msg = 'Service: missing attr: %s' % attr
                    result = push_result(self, result, False, msg,
                                         'Test Layer:')
                    continue

            layers = fs_caps.get('layers', [])

        except Exception as err:
            result.set(False, str(err))

        result.stop()
        self.result.add_result(result)

        if len(layers) == 0:
            return

        # 2. Test each Layer Capabilities
        result = Result(True, 'Test Layer Capabilities')
        result.start()
        layer_ids = []
        layer_caps = []
        try:

            for layer in layers:
                layer_ids.append(layer['id'])

            for layer_id in layer_ids:
                layer_caps.append(
                    self.perform_esrifs_get_request(req_tpl['layer_caps'] %
                                                    layer_id))

        except Exception as err:
            result.set(False, str(err))

        result.stop()
        self.result.add_result(result)

        if self._parameters['drilldown_level'] == 'basic':
            return

        # ASSERTION: will do full drilldown from here

        # 3. Test getting Features from Layers
        result = Result(True, 'Test Layers')
        result.start()
        layer_id = 0
        try:
            for layer_id in layer_ids:

                try:
                    features = self.perform_esrifs_get_request(
                        req_tpl['get_features'] % layer_id)
                    obj_id_field_name = features['objectIdFieldName']
                    features = features['features']
                    if len(features) == 0:
                        continue

                    # At least one Feature: use first and try to get by id
                    object_id = features[0]['attributes'][obj_id_field_name]
                    feature = self.perform_get_request(
                        req_tpl['get_feature_by_id'] %
                        (layer_id, obj_id_field_name, str(object_id))).json()

                    feature = feature['features']
                    if len(feature) == 0:
                        msg = 'layer: %d: missing Feature - id: %s' \
                              % (layer_id, str(object_id))
                        result = push_result(self, result, False, msg,
                                             'Test Layer: %d' % layer_id)

                except Exception as e:
                    msg = 'GetLayer: id=%d: err=%s ' \
                          % (layer_id, str(e))
                    result = push_result(self, result, False, msg,
                                         'Test Get Features:')
                    continue

        except Exception as err:
            result.set(False, 'Layer: id=%d : err=%s' % (layer_id, str(err)))

        result.stop()

        # Add to overall Probe result
        self.result.add_result(result)
Ejemplo n.º 4
0
    def perform_request(self):
        """
        Perform the validation.
        Uses https://github.com/p1c2u/openapi-spec-validator on
        the specfile (dict) returned from the OpenAPI endpoint.
        """

        # Step 1 basic sanity check
        result = Result(True, 'OpenAPI Sanity Check')
        result.start()
        api_doc = None
        try:
            wfs3 = WebFeatureService(self._resource.url, version='3.0')

            # TODO: OWSLib 0.17.1 has no call to '/api yet.
            api_doc = wfs3_api_doc(wfs3)

            # Basic sanity check
            for attr in ['components', 'paths', 'openapi']:
                val = api_doc.get(attr, None)
                if val is None:
                    msg = '/api: missing attr: %s' % attr
                    result.set(False, msg)
                    break
        except Exception as err:
            result.set(False, '%s:%s' % (result.message, str(err)))

        result.stop()
        self.result.add_result(result)

        # No use to proceed if OpenAPI basics not complied
        if api_doc is None or result.success is False:
            return

        # ASSERTION: /api exists, next OpenAPI Validation

        # Step 2 detailed OpenAPI Compliance test
        result = Result(True, 'Validate OpenAPI Compliance')
        result.start()
        try:
            # Call the openapi-spec-validator and iterate through errors
            errors_iterator = openapi_v3_spec_validator.iter_errors(api_doc)
            for error in errors_iterator:
                # Add each validation error as separate Result object
                result = push_result(self, result, False, str(error),
                                     'OpenAPI Compliance Result')
        except Exception as err:
            result.set(False, '%s:%s' % (result.message, str(err)))

        result.stop()

        # Add to overall Probe result
        self.result.add_result(result)
Ejemplo n.º 5
0
    def perform_request(self):
        """
        Perform the drilldown.
        See https://github.com/geopython/OWSLib/blob/
        master/tests/doctests/wfs3_GeoServerCapabilities.txt
        """
        wfs3 = None
        collections = None

        # 1.1 Test Landing Page
        result = Result(True, 'Test Landing Page')
        result.start()
        try:
            wfs3 = WebFeatureService(self._resource.url, version='3.0')
        except Exception as err:
            result.set(False, '%s:%s' % (result.message, str(err)))

        result.stop()
        self.result.add_result(result)

        # 1.2 Test top endpoints existence: /conformance
        result = Result(True, 'conformance endpoint exists')
        result.start()
        try:
            wfs3.conformance()
        except Exception as err:
            result.set(False, str(err))

        result.stop()
        self.result.add_result(result)

        # 1.3 Test top endpoints existence: /collections
        result = Result(True, 'Get collections')
        result.start()
        try:
            collections = wfs3.collections()
        except Exception as err:
            result.set(False, '%s:%s' % (result.message, str(err)))

        result.stop()
        self.result.add_result(result)

        # 1.4 Test top endpoints existence: OpenAPI doc
        result = Result(True, 'Test OpenAPI Doc')
        result.start()
        try:

            # TODO: OWSLib 0.17.1 has no call to '/api yet, upgrade when GHC
            #  supports Py3 to 0.19+.
            api = wfs3_api_doc(wfs3)
            for attr in ['components', 'paths', 'openapi']:
                val = api.get(attr, None)
                if val is None:
                    msg = 'missing attr: %s' % attr
                    result = push_result(self, result, False, msg,
                                         'Test OpenAPI doc')
                    continue
        except Exception as err:
            result.set(False, '%s:%s' % (result.message, str(err)))

        result.stop()
        self.result.add_result(result)

        if self._parameters['drilldown_level'] == 'basic':
            return

        # ASSERTION: will do full drilldown, level 2, from here

        # 2. Test layers
        # TODO: use parameters to work on less/more drilling
        # "full" could be all layers.
        result = Result(True, 'Test Collections')
        result.start()
        coll_id = ''
        try:
            for collection in collections:
                coll_id = collection['id']
                coll_id = coll_id

                try:
                    coll = wfs3.collection(coll_id)

                    # TODO: Maybe also add crs
                    for attr in ['id', 'links']:
                        val = coll.get(attr, None)
                        if val is None:
                            msg = '%s: missing attr: %s' \
                                  % (coll_id, attr)
                            result = push_result(self, result, False, msg,
                                                 'Test Collection')
                            continue
                except Exception as e:
                    msg = 'GetCollection %s: OWSLib err: %s ' \
                          % (str(e), coll_id)
                    result = push_result(self, result, False, msg,
                                         'Test GetCollection')
                    continue

                try:
                    items = wfs3.collection_items(coll_id, limit=1)
                except Exception as e:
                    msg = 'GetItems %s: OWSLib err: %s ' % (str(e), coll_id)
                    result = push_result(self, result, False, msg,
                                         'Test GetItems')
                    continue

                features = items.get('features', None)
                if features is None:
                    msg = 'GetItems %s: No features attr' % coll_id
                    result = push_result(self, result, False, msg,
                                         'Test GetItems')
                    continue

                type = items.get('type', '')
                if type != 'FeatureCollection':
                    msg = '%s:%s type not FeatureCollection: %s' \
                          % (coll_id, type, val)
                    result = push_result(self, result, False, msg,
                                         'Test GetItems')
                    continue

                if len(items['features']) > 0:

                    fid = items['features'][0]['id']
                    try:
                        item = wfs3.collection_item(coll_id, fid)
                    except Exception as e:
                        msg = 'GetItem %s: OWSLib err: %s' \
                              % (str(e), coll_id)
                        result = push_result(self, result, False, msg,
                                             'Test GetItem')
                        continue

                    for attr in \
                            ['id', 'links', 'properties', 'geometry', 'type']:
                        val = item.get(attr, None)
                        if val is None:
                            msg = '%s:%s missing attr: %s' \
                                  % (coll_id, str(fid), attr)
                            result = push_result(self, result, False, msg,
                                                 'Test GetItem')
                            continue

                        if attr == 'type' and val != 'Feature':
                            msg = '%s:%s type not Feature: %s' \
                                  % (coll_id, str(fid), val)
                            result = push_result(self, result, False, msg,
                                                 'Test GetItem')
                            continue

        except Exception as err:
            result.set(False,
                       'Collection err: %s : e=%s' % (coll_id, str(err)))

        result.stop()

        # Add to overall Probe result
        self.result.add_result(result)
Ejemplo n.º 6
0
    def perform_request(self):
        """
        Perform the drilldown.
        See https://github.com/geopython/OWSLib/blob/
        master/tests/doctests/wms_GeoServerCapabilities.txt
        """
        wms = None

        # 1. Test capabilities doc, parses
        result = Result(True, 'Test Capabilities')
        result.start()
        try:
            wms = WebMapService(self._resource.url)
            title = wms.identification.title
            self.log('response: title=%s' % title)
        except Exception as err:
            result.set(False, str(err))

        result.stop()
        self.result.add_result(result)

        # 2. Test layers
        # TODO: use parameters to work on less/more drilling
        # "full" could be all layers.
        result = Result(True, 'Test Layers')
        result.start()
        try:
            # Pick a random layer
            layer_name = random.sample(wms.contents.keys(), 1)[0]
            layer = wms[layer_name]

            # TODO Only use EPSG:4326, later random CRS
            if 'EPSG:4326' in layer.crsOptions \
                    and layer.boundingBoxWGS84:

                # Search GetMap operation
                get_map_oper = None
                for oper in wms.operations:
                    if oper.name == 'GetMap':
                        get_map_oper = oper
                        break

                format = None
                for format in get_map_oper.formatOptions:
                    if format.startswith('image/'):
                        break

                # format = random.sample(get_map_oper.formatOptions, 1)[0]

                self.log('testing layer: %s' % layer_name)
                layer_bbox = layer.boundingBoxWGS84
                wms.getmap(layers=[layer_name],
                           styles=[''],
                           srs='EPSG:4326',
                           bbox=(layer_bbox[0], layer_bbox[1], layer_bbox[2],
                                 layer_bbox[3]),
                           size=(256, 256),
                           format=format,
                           transparent=False)

                self.log('WMS GetMap: format=%s' % format)
                # Etc, to be finalized

        except Exception as err:
            result.set(False, str(err))

        result.stop()

        # Add to overall Probe result
        self.result.add_result(result)
Ejemplo n.º 7
0
    def perform_request(self):
        """
        Perform the drilldown.
        See https://github.com/geopython/OWSLib/blob/
        master/tests/doctests/wms_GeoServerCapabilities.txt
        """
        wms = None

        # 1. Test capabilities doc, parses
        result = Result(True, 'Test Capabilities')
        result.start()
        try:
            wms = WebMapService(self._resource.url)
            title = wms.identification.title
            self.log('response: title=%s' % title)
        except Exception as err:
            result.set(False, str(err))

        result.stop()
        self.result.add_result(result)

        # 2. Test layers
        # TODO: use parameters to work on less/more drilling
        # "full" could be all layers.
        result = Result(True, 'Test Layers')
        result.start()
        try:
            # Pick a random layer
            layer_name = random.sample(wms.contents.keys(), 1)[0]
            layer = wms[layer_name]

            # TODO Only use EPSG:4326, later random CRS
            if 'EPSG:4326' in layer.crsOptions \
                    and layer.boundingBoxWGS84:

                # Search GetMap operation
                get_map_oper = None
                for oper in wms.operations:
                    if oper.name == 'GetMap':
                        get_map_oper = oper
                        break

                format = None
                for format in get_map_oper.formatOptions:
                    if format.startswith('image/'):
                        break

                # format = random.sample(get_map_oper.formatOptions, 1)[0]

                self.log('testing layer: %s' % layer_name)
                layer_bbox = layer.boundingBoxWGS84
                wms.getmap(layers=[layer_name],
                           styles=[''],
                           srs='EPSG:4326',
                           bbox=(layer_bbox[0],
                                 layer_bbox[1],
                                 layer_bbox[2],
                                 layer_bbox[3]),
                           size=(256, 256),
                           format=format,
                           transparent=False)

                self.log('WMS GetMap: format=%s' % format)
                # Etc, to be finalized

        except Exception as err:
            result.set(False, str(err))

        result.stop()

        # Add to overall Probe result
        self.result.add_result(result)
Ejemplo n.º 8
0
    def perform_request(self):
        """
        Perform the validation.
        Uses https://github.com/p1c2u/openapi-spec-validator on
        the specfile (dict) returned from the OpenAPI endpoint.
        """

        # Step 1 basic sanity check
        result = Result(True, 'OpenAPI Sanity Check')
        result.start()
        api_doc = None
        try:
            oa_feat = Features(self._resource.url,
                               headers=self.get_request_headers())

            set_accept_header(oa_feat, type_for_link(
                oa_feat.links, 'service-desc'))
            api_doc = oa_feat.api()

            # Basic sanity check
            for attr in ['components', 'paths', 'openapi']:
                val = api_doc.get(attr, None)
                if val is None:
                    msg = 'OpenAPI doc: missing attr: %s' % attr
                    result.set(False, msg)
                    break
        except Exception as err:
            result.set(False, '%s:%s' % (result.message, str(err)))

        result.stop()
        self.result.add_result(result)

        # No use to proceed if OpenAPI basics not complied
        if api_doc is None or result.success is False:
            return

        # ASSERTION: OpenAPI doc exists, next OpenAPI Validation

        # Step 2 detailed OpenAPI Compliance test
        result = Result(True, 'Validate OpenAPI Compliance')
        result.start()
        try:
            # Call the openapi-spec-validator and iterate through errors
            errors_iterator = openapi_v3_spec_validator.iter_errors(api_doc)
            for error in errors_iterator:
                # Add each validation error as separate Result object
                result = push_result(
                    self, result, False,
                    str(error), 'OpenAPI Compliance Result')
        except Exception as err:
            result.set(False, '%s:%s' % (result.message, str(err)))

        result.stop()

        # Add to overall Probe result
        self.result.add_result(result)
Ejemplo n.º 9
0
    def perform_request(self):
        """
        Perform the reporting.
        """

        # Be sure to use bare root URL http://.../FeatureServer
        ghc_url = self._resource.url.split('?')[0]

        # Assemble request templates with root FS URL

        summary_url = ghc_url + '/api/v1.0/summary/'

        # 1. Get the summary (JSON) report from GHC endpoint
        result = Result(True, 'Get GHC Report')
        result.start()
        try:
            response = self.perform_get_request(summary_url)
            status = response.status_code
            overall_status = status / 100
            if overall_status in [4, 5]:
                raise Exception('HTTP Error status=%d reason=%s' %
                                (status, response.reason))

            summary_report = response.json()
        except Exception as err:
            msg = 'Cannot get summary from %s err=%s' % \
                  (summary_url, str(err))
            result.set(False, msg)
            result.stop()
            self.result.add_result(result)
            return

        # ASSERTION - summary report fetch ok

        # 2. Do email reporting with summary report
        result = Result(True, 'Send Email')
        result.start()

        try:
            config = App.get_config()

            # Create message body with report
            template_vars = {'summary': summary_report, 'config': config}

            msg_body = render_template2('status_report_email.txt',
                                        template_vars)

            resource = self._resource
            to_addrs = self._parameters.get('email', None)
            if to_addrs is None:
                raise Exception(
                    'No emails set for GHCEmailReporter in resource=%s' %
                    resource.identifier)

            to_addrs = to_addrs.replace(' ', '')
            if len(to_addrs) == 0:
                raise Exception(
                    'No emails set for GHCEmailReporter in resource=%s' %
                    resource.identifier)

            to_addrs = to_addrs.split(',')
            msg = MIMEText(msg_body, 'plain', 'utf-8')
            msg['From'] = formataddr(
                (config['GHC_SITE_TITLE'], config['GHC_ADMIN_EMAIL']))
            msg['To'] = ', '.join(to_addrs)
            msg['Subject'] = '[%s] %s' % (config['GHC_SITE_TITLE'],
                                          gettext('Status summary'))

            from_addr = '%s <%s>' % (config['GHC_SITE_TITLE'],
                                     config['GHC_ADMIN_EMAIL'])

            msg_text = msg.as_string()
            send_email(config['GHC_SMTP'], from_addr, to_addrs, msg_text)
        except Exception as err:
            msg = 'Cannot send email. Contact admin: '
            LOGGER.warning(msg + ' err=' + str(err))
            result.set(False, 'Cannot send email: %s' % str(err))

        result.stop()

        # Add to overall Probe result
        self.result.add_result(result)
Ejemplo n.º 10
0
    def perform_request(self):
        """
        Perform the drilldown.
        See https://github.com/geopython/OWSLib/blob/
        master/tests/doctests/wfs3_GeoServerCapabilities.txt
        """
        wfs3 = None
        collections = None

        # 1. Test top endpoints existence
        result = Result(True, 'Test Top Endpoints')
        result.start()
        try:
            wfs3 = WebFeatureService(self._resource.url, version='3.0')
            wfs3.conformance()

            # TODO: OWSLib 0.17.1 has no call to '/api yet.
            url = wfs3._build_url('api')
            api = requests.get(url).json()
            for attr in ['components', 'paths', 'openapi']:
                val = api.get(attr, None)
                if val is None:
                    msg = '/api: missing attr: %s' % attr
                    result = push_result(self, result, False, msg,
                                         'Test Collection')
                    continue

            collections = wfs3.collections()
        except Exception as err:
            result.set(False, str(err))

        result.stop()
        self.result.add_result(result)

        if self._parameters['drilldown_level'] == 'basic':
            return

        # ASSERTION: will do full drilldown from here

        # 2. Test layers
        # TODO: use parameters to work on less/more drilling
        # "full" could be all layers.
        result = Result(True, 'Test Collections')
        result.start()
        coll_name = ''
        try:
            for collection in collections:
                coll_name = collection['name']
                coll_name = coll_name.encode('utf-8')

                try:
                    coll = wfs3.collection(coll_name)

                    # TODO: Maybe also add crs
                    for attr in ['name', 'links']:
                        val = coll.get(attr, None)
                        if val is None:
                            msg = '%s: missing attr: %s' \
                                  % (coll_name, attr)
                            result = push_result(self, result, False, msg,
                                                 'Test Collection')
                            continue
                except Exception as e:
                    msg = 'GetCollection %s: OWSLib err: %s ' \
                          % (str(e), coll_name)
                    result = push_result(self, result, False, msg,
                                         'Test GetCollection')
                    continue

                try:
                    items = wfs3.collection_items(coll_name, limit=1)
                except Exception as e:
                    msg = 'GetItems %s: OWSLib err: %s ' % (str(e), coll_name)
                    result = push_result(self, result, False, msg,
                                         'Test GetItems')
                    continue

                features = items.get('features', None)
                if features is None:
                    msg = 'GetItems %s: No features attr' % coll_name
                    result = push_result(self, result, False, msg,
                                         'Test GetItems')
                    continue

                type = items.get('type', '')
                if type != 'FeatureCollection':
                    msg = '%s:%s type not FeatureCollection: %s' \
                          % (coll_name, type, val)
                    result = push_result(self, result, False, msg,
                                         'Test GetItems')
                    continue

                if len(items['features']) > 0:

                    fid = items['features'][0]['id']
                    try:
                        item = wfs3.collection_item(coll_name, fid)
                    except Exception as e:
                        msg = 'GetItem %s: OWSLib err: %s' \
                              % (str(e), coll_name)
                        result = push_result(self, result, False, msg,
                                             'Test GetItem')
                        continue

                    for attr in \
                            ['id', 'links', 'properties', 'geometry', 'type']:
                        val = item.get(attr, None)
                        if val is None:
                            msg = '%s:%s missing attr: %s' \
                                  % (coll_name, str(fid), attr)
                            result = push_result(self, result, False, msg,
                                                 'Test GetItem')
                            continue

                        if attr == 'type' and val != 'Feature':
                            msg = '%s:%s type not Feature: %s' \
                                  % (coll_name, str(fid), val)
                            result = push_result(self, result, False, msg,
                                                 'Test GetItem')
                            continue

        except Exception as err:
            result.set(False,
                       'Collection err: %s : e=%s' % (coll_name, str(err)))

        result.stop()

        # Add to overall Probe result
        self.result.add_result(result)