def test_fetch_objs_http_error_500(self):
        """Test whether a warning is logged when a 500 HTTP error occurs"""

        saved_objs_page_1 = read_file('data/objects_1')
        saved_objs_page_2 = read_file('data/objects_2')
        saved_objs_page_3 = read_file('data/objects_empty')

        httpretty.register_uri(httpretty.GET,
                               SAVED_OBJECTS_URL + '/_find?page=3',
                               body=saved_objs_page_3,
                               status=200)

        httpretty.register_uri(httpretty.GET,
                               SAVED_OBJECTS_URL + '/_find?page=2',
                               body=saved_objs_page_2,
                               status=500)

        httpretty.register_uri(httpretty.GET,
                               SAVED_OBJECTS_URL + '/_find?page=1',
                               body=saved_objs_page_1,
                               status=200)

        client = SavedObjects(KIBANA_URL)
        with self.assertLogs(logger) as cm:
            _ = [
                obj for page_objs in client.find(obj_type='dashboard')
                for obj in page_objs
            ]

        self.assertEqual(
            cm.output[0],
            'WARNING:archimedes.clients.saved_objects:Impossible to retrieve object at page 2, '
            'url http://example.com/api/saved_objects/_find')
    def test_fetch_objs_internal_error(self):
        """Test whether a log error message is thrown when an internal error occurs with the method fetch_objs"""

        saved_objs_error = read_file('data/objects_error')
        saved_objs_empty = read_file('data/objects_empty')

        httpretty.register_uri(httpretty.GET,
                               SAVED_OBJECTS_URL + '/_find?page=2',
                               body=saved_objs_empty,
                               status=200)

        httpretty.register_uri(httpretty.GET,
                               SAVED_OBJECTS_URL + '/_find?page=1',
                               body=saved_objs_error,
                               status=200)

        client = SavedObjects(KIBANA_URL)
        with self.assertLogs(logger, level='ERROR') as cm:
            _ = [
                obj for page_objs in client.find(obj_type='dashboard')
                for obj in page_objs
            ]
            self.assertEqual(
                cm.output[0],
                'ERROR:archimedes.clients.saved_objects:Impossible to retrieve objects at page 1, '
                'url http://example.com/api/saved_objects/_find, An internal server error occurred'
            )
    def test_fetch_objs(self):
        """Test whether objects are correctly returned by the method fetch_objs"""

        saved_objs_page_1 = read_file('data/objects_1')
        saved_objs_page_2 = read_file('data/objects_2')
        saved_objs_page_3 = read_file('data/objects_empty')

        httpretty.register_uri(httpretty.GET,
                               SAVED_OBJECTS_URL + '/_find?page=3',
                               body=saved_objs_page_3,
                               status=200)

        httpretty.register_uri(httpretty.GET,
                               SAVED_OBJECTS_URL + '/_find?page=2',
                               body=saved_objs_page_2,
                               status=200)

        httpretty.register_uri(httpretty.GET,
                               SAVED_OBJECTS_URL + '/_find?page=1',
                               body=saved_objs_page_1,
                               status=200)

        client = SavedObjects(KIBANA_URL)
        fetched_objs = [
            obj for page_objs in client.find(obj_type='visualization')
            for obj in page_objs
        ]
        self.assertEqual(len(fetched_objs), 4)

        obj = fetched_objs[0]
        self.assertEqual(obj['id'], "0b84fff0-b1b6-11e8-8aac-ef7fd4d8cbad")
        self.assertEqual(obj['type'], "visualization")
        self.assertEqual(obj["version"], 1)

        obj = fetched_objs[1]
        self.assertEqual(obj['id'], "00cf9cf0-d074-11e8-8aac-ef7fd4d8cbad")
        self.assertEqual(obj['type'], "visualization")
        self.assertEqual(obj["version"], 1)

        obj = fetched_objs[2]
        self.assertEqual(obj['id'], "1a23fbd0-bc0e-11e8-8aac-ef7fd4d8cbad")
        self.assertEqual(obj['type'], "visualization")
        self.assertEqual(obj["version"], 2)

        obj = fetched_objs[3]
        self.assertEqual(obj['id'], "00fee5a0-7eb7-11e8-a4e7-6b1c6a13c58d")
        self.assertEqual(obj['type'], "visualization")
        self.assertEqual(obj["version"], 1)
    def test_fetch_objs_http_error(self):
        """Test whether an exception is thrown when the HTTP error is not 500"""

        saved_objs_page = read_file('data/objects_1')

        httpretty.register_uri(httpretty.GET,
                               SAVED_OBJECTS_URL + '/_find',
                               body=saved_objs_page,
                               status=404)

        client = SavedObjects(KIBANA_URL)
        with self.assertRaises(requests.exceptions.HTTPError):
            _ = [
                obj for page_objs in client.find(obj_type='dashboard')
                for obj in page_objs
            ]
    def test_fetch_objs_empty(self):
        """Test whether no objects are returned by the method fetch_objs"""

        saved_objs_empty = read_file('data/objects_empty')

        httpretty.register_uri(httpretty.GET,
                               SAVED_OBJECTS_URL + '/_find?page=1',
                               body=saved_objs_empty,
                               status=200)

        client = SavedObjects(KIBANA_URL)
        fetched_objs = [
            obj for page_objs in client.find(obj_type='dashboard')
            for obj in page_objs
        ]
        self.assertEqual(len(fetched_objs), 0)
Example #6
0
class Kibana:
    """Kibana class.

    This class defines operations performed against the Dashboard and
    the SavedObjects APIs, such as exporting and importing objects as well
    as searching objects by ID or title.

    :param base_url: the Kibana URL
    """
    def __init__(self, base_url):
        self.base_url = base_url
        self.dashboard = Dashboard(base_url)
        self.saved_objects = SavedObjects(base_url)

    def export_by_id(self, obj_type, obj_id):
        """Export an object identified by its ID.

        This method returns an object saved in Kibana based on its type and ID.

        An `ObjectTypeError` is thrown if the type of the object is not one of
        the following: dashboard, index pattern, search, visualization.

        A `NotFoundError` is thrown if the object is not found in the Kibana instance.

        :param obj_type: type of the target object
        :param obj_id: ID of the target object

        :returns the target Kibana object
        """
        if obj_type == DASHBOARD:
            obj = self.dashboard.export_dashboard(obj_id)
        elif obj_type in [INDEX_PATTERN, SEARCH, VISUALIZATION]:
            obj = self.saved_objects.get_object(obj_type, obj_id)
        else:
            cause = "Unknown type %s" % obj_type
            logger.error(cause)
            raise ObjectTypeError(cause=cause)

        if not obj:
            cause = "Impossible to export %s with id %s, not found" % (obj_type, obj_id)
            logger.error(cause)
            raise NotFoundError(cause=cause)

        return obj

    def export_by_title(self, obj_type, obj_title):
        """Export an object identified by its title.

        This method returns an object saved in Kibana based on its type and title.

        An `ObjectTypeError` is thrown if the type of the object is not one of
        the following: dashboard, index pattern, search, visualization.

        A `NotFoundError` is thrown if the object is not found in the Kibana instance.

        :param obj_type: type of the target object
        :param obj_title: title of the target object

        :returns the target Kibana object
        """
        if obj_type not in [DASHBOARD, INDEX_PATTERN, SEARCH, VISUALIZATION]:
            cause = "Unknown type %s" % obj_type
            logger.error(cause)
            raise ObjectTypeError(cause=cause)

        obj = self.find_by_title(obj_type, obj_title)

        if obj_type == DASHBOARD:
            obj_id = obj['id']
            obj = self.dashboard.export_dashboard(obj_id)

        if not obj:
            cause = "Impossible to export %s with title %s, not found" % (obj_type, obj_title)
            logger.error(cause)
            raise NotFoundError(cause=cause)

        return obj

    def import_objects(self, objects, force=False):
        """Import a list of objects to Kibana.

        This method imports a list of Kibana objects to Kibana by using the Dashboard API.

        :param objects: list of objects to import
        :param force: overwrite any existing objects on ID conflict
        """
        self.dashboard.import_objects(objects, force=force)

    def find_by_title(self, obj_type, obj_title):
        """Find an object by its type and title.

        This methods returns a Kibana object based on its type and title.

        A `NotFoundError` is thrown if the object is not found in the Kibana instance.

        :param obj_type: type of the target object
        :param obj_title: title of the target object

        :returns the target object or None if not found
        """
        url = urijoin(self.base_url, self.saved_objects.API_SAVED_OBJECTS_URL)
        found_obj = None

        for page_objs in self.saved_objects.find(obj_type):
            for obj in page_objs:
                if obj['attributes']['title'] == obj_title:
                    found_obj = obj
                    break

        if not found_obj:
            cause = "No %s found with title: %s" % (obj_type, obj_title)
            logger.error(cause)
            raise NotFoundError(cause=cause)

        return found_obj

    def find_by_id(self, obj_type, obj_id):
        """Find an object by its type and ID.

        This methods returns a Kibana object based on its type and ID.

        A `NotFoundError` is thrown if the object is not found in the Kibana instance.

        :param obj_type: type of the target object
        :param obj_id: ID of the target object

        :returns the target object or None if not found
        """
        url = urijoin(self.base_url, self.saved_objects.API_SAVED_OBJECTS_URL)
        found_obj = None

        for page_objs in self.saved_objects.find(obj_type):
            for obj in page_objs:
                if obj['id'] == obj_id:
                    found_obj = obj
                    break

        if not found_obj:
            cause = "No %s found with ID: %s" % (obj_type, obj_id)
            logger.error(cause)
            raise NotFoundError(cause=cause)

        return found_obj

    def find_all(self):
        """Find all objects stored in Kibana.

        This method returns all remote Kibana objects using the SavedObject API.

        :returns a generator of Kibana objects
        """
        obj_types = [DASHBOARD, INDEX_PATTERN, SEARCH, VISUALIZATION]
        for obj_type in obj_types:
            for page_objs in self.saved_objects.find(obj_type):
                for obj in page_objs:
                    yield obj