def test_import_objects_error(self): """Test whether errors are logged for the objects which were not imported""" dashboard_objs = read_file('data/dashboard_error') dashboard_objs_json = json.loads(dashboard_objs) httpretty.register_uri(httpretty.POST, DASHBOARD_IMPORT_URL, body=dashboard_objs, status=200) client = Dashboard(KIBANA_URL) with self.assertLogs(logger, level='INFO') as cm: _ = client.import_objects(dashboard_objs_json) expected = {'force': ['false']} self.assertEqual( cm.output[0], 'ERROR:archimedes.clients.dashboard:dashboard with id Git not imported, ' 'an internal server error occurred') self.assertEqual( cm.output[1], 'INFO:archimedes.clients.dashboard:11/12 object(s) imported') self.assertDictEqual(httpretty.last_request().querystring, expected)
def test_export_dashboard_impossible(self): """Test whether an error message is logged when a 400 HTTP error is returned""" dashboard_objs = read_file('data/dashboard_error') httpretty.register_uri(httpretty.GET, DASHBOARD_EXPORT_URL, body=dashboard_objs, status=400) client = Dashboard(KIBANA_URL) with self.assertRaises(DataExportError): _ = client.export_dashboard(DASHBOARD_ID)
def test_export_dashboard(self): """Test whether a dashboard is correctly exported""" dashboard_objs = read_file('data/dashboard') httpretty.register_uri(httpretty.GET, DASHBOARD_EXPORT_URL, body=dashboard_objs, status=200) client = Dashboard(KIBANA_URL) objs = client.export_dashboard(DASHBOARD_ID) self.assertDictEqual(objs, json.loads(dashboard_objs))
def test_export_dashboard_http_error(self): """Test whether an exception is thrown when the HTTP error is not 400""" dashboard_objs = read_file('data/dashboard_error') httpretty.register_uri(httpretty.GET, DASHBOARD_EXPORT_URL, body=dashboard_objs, status=500) client = Dashboard(KIBANA_URL) with self.assertRaises(requests.exceptions.HTTPError): _ = client.export_dashboard(DASHBOARD_ID)
def test_initialization(self): """Test whether attributes are initialized""" client = Dashboard(KIBANA_URL) self.assertEqual(client.base_url, KIBANA_URL) self.assertIsNotNone(client.session) self.assertEqual(client.session.headers['kbn-xsrf'], HEADERS.get('kbn-xsrf')) self.assertEqual(client.session.headers['Content-Type'], HEADERS.get('Content-Type'))
def test_import_objects(self): """Test whether the objects that compose a dashboard are correctly imported""" dashboard_objs = read_file('data/dashboard') dashboard_objs_json = json.loads(dashboard_objs) httpretty.register_uri(httpretty.POST, DASHBOARD_IMPORT_URL, body=dashboard_objs, status=200) client = Dashboard(KIBANA_URL) with self.assertLogs(logger, level='INFO') as cm: _ = client.import_objects(dashboard_objs_json) expected = {'force': ['false']} self.assertEqual( cm.output[0], 'INFO:archimedes.clients.dashboard:12/12 object(s) imported') self.assertDictEqual(httpretty.last_request().querystring, expected) with self.assertLogs(logger, level='INFO') as cm: _ = client.import_objects(dashboard_objs_json, exclude_dashboards=True, exclude_index_patterns=True, exclude_visualizations=True, exclude_searches=True, force=True) expected = { 'force': ['true'], 'exclude': ['dashboard', 'index-pattern', 'visualization', 'search'] } self.assertEqual( cm.output[0], 'INFO:archimedes.clients.dashboard:12/12 object(s) imported') self.assertDictEqual(httpretty.last_request().querystring, expected)
def __init__(self, base_url): self.base_url = base_url self.dashboard = Dashboard(base_url) self.saved_objects = SavedObjects(base_url)
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.fetch_objs(url): for obj in page_objs: if obj['type'] == obj_type and 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.fetch_objs(url): for obj in page_objs: if obj['type'] == obj_type and 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 """ url = urijoin(self.base_url, self.saved_objects.API_SAVED_OBJECTS_URL) for page_objs in self.saved_objects.fetch_objs(url): for obj in page_objs: yield obj