diff --git a/Makefile b/Makefile index 39e39bb..7c468f8 100644 --- a/Makefile +++ b/Makefile @@ -35,10 +35,10 @@ clean-test: rm -fr htmlcov/ lint: - flake8 zeus tests + @flake8 zeus tests test: - python setup.py test + @python setup.py test test-all: tox diff --git a/setup.cfg b/setup.cfg index 5e40900..01daab3 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,2 +1,5 @@ [wheel] universal = 1 + +[flake8] +max-line-length = 90 diff --git a/tests/test_zeus_client.py b/tests/test_zeus_client.py index 2788265..de7634d 100755 --- a/tests/test_zeus_client.py +++ b/tests/test_zeus_client.py @@ -23,13 +23,13 @@ """ import json -import mock +from mock import patch import posixpath import unittest import urlparse from zeus import client -from zeus.interfaces.utils import validateDates, ZeusException +from zeus.interfaces.utils import validate_dates, ZeusException FAKE_TOKEN = 'ZeUsRoCkS' FAKE_SERVER = 'https://zeus.rocks' @@ -43,8 +43,9 @@ def setUp(self): 'Authorization': "Bearer {}".format(FAKE_TOKEN), 'content-type': 'application/json' } + self.fake_bucket_name = 'fake_org/fake_bucket' - def fake_header_with_z_resource(self, bucket_name): + def fake_header_with_bucket_name(self, bucket_name): """ Make HTTP Header :param bucket_name: bucket name @@ -56,41 +57,43 @@ def fake_header_with_z_resource(self, bucket_name): def test_initialization_no_https(self): z = client.ZeusClient(FAKE_TOKEN, "zeus.rocks") - assert z.server == "https://zeus.rocks" + assert z.endpoint == "https://zeus.rocks" + z = client.ZeusClient(FAKE_TOKEN, "http://zeus.rocks") - assert z.server == "https://zeus.rocks" + assert z.endpoint == "https://zeus.rocks" def test_validate_dates(self): # normal from_date = 12345 to_date = 12346 - validateDates(from_date, to_date) + validate_dates(from_date, to_date) # None value from_date = None to_date = 12346 - validateDates(from_date, to_date) + validate_dates(from_date, to_date) # invalid value from_date = 'wrongvalue' to_date = 12346 self.assertRaises( - ZeusException, validateDates, from_date, to_date) + ZeusException, validate_dates, from_date, to_date) # inversed order from_date = 12346 to_date = 12345 self.assertRaises( - ZeusException, validateDates, from_date, to_date) + ZeusException, validate_dates, from_date, to_date) - @mock.patch('zeus.interfaces.rest.requests') + @patch('zeus.client.requests') def test_post_empty_log(self, mock_requests): logs = [] - url = urlparse.urljoin(FAKE_SERVER, - posixpath.join('logs', FAKE_TOKEN, 'ZeusTest')) + url = urlparse.urljoin( + FAKE_SERVER, posixpath.join('logs', FAKE_TOKEN, 'ZeusTest')) + self.z.sendLog('ZeusTest', logs) mock_requests.post.assert_called_with( url, data={"logs": json.dumps(logs)}, - headers=self.fake_header_with_z_resource('ZeusTest'), timeout=20) + headers=self.fake_headers, timeout=20) - @mock.patch('zeus.interfaces.rest.requests') + @patch('zeus.client.requests') def test_post_single_log(self, mock_requests): url = urlparse.urljoin( FAKE_SERVER, posixpath.join('logs', FAKE_TOKEN, 'ZeusTest')) @@ -98,7 +101,22 @@ def test_post_single_log(self, mock_requests): self.z.sendLog('ZeusTest', logs) mock_requests.post.assert_called_with( url, data={"logs": json.dumps(logs)}, - headers=self.fake_header_with_z_resource('ZeusTest'), timeout=20) + headers=self.fake_headers, timeout=20) + + @patch('zeus.client.requests') + def test_send_log_with_bucket_name(self, mock_requests): + url = urlparse.urljoin( + FAKE_SERVER, posixpath.join('logs', FAKE_TOKEN, 'ZeusTest')) + logs = [{"timestamp": 123541423, "key": "TestLog", "key2": 123}] + + self.z.bucket(self.fake_bucket_name).sendLog('ZeusTest', logs) + + mock_requests.post.assert_called_with( + url, data={"logs": json.dumps(logs)}, + headers=self.fake_header_with_bucket_name(self.fake_bucket_name), + timeout=20) + + self.assertIsNone(self.z.bucket_name) def test_post_single_log_wrong_name(self): logs = [{"message": "TestLog", "value": 23}] @@ -118,7 +136,7 @@ def test_post_single_log_wrong_name(self): ZeusException, self.z.sendLog, '0123456789ABCDEF' * 16, logs) - @mock.patch('zeus.interfaces.rest.requests') + @patch('zeus.client.requests') def test_post_multiple_logs(self, mock_requests): url = urlparse.urljoin( FAKE_SERVER, posixpath.join('logs', FAKE_TOKEN, 'ZeusTest')) @@ -128,9 +146,9 @@ def test_post_multiple_logs(self, mock_requests): self.z.sendLog('ZeusTest', logs) mock_requests.post.assert_called_with( url, data={"logs": json.dumps(logs)}, - headers=self.fake_header_with_z_resource('ZeusTest'), timeout=20) + headers=self.fake_headers, timeout=20) - @mock.patch('zeus.interfaces.rest.requests') + @patch('zeus.client.requests') def test_get_logs(self, mock_requests): url = urlparse.urljoin(FAKE_SERVER, posixpath.join('logs', FAKE_TOKEN)) self.z.getLog('ZeusTest', @@ -150,9 +168,23 @@ def test_get_logs(self, mock_requests): 'to': 126235344235, 'offset': 23, 'limit': 10}, + headers=self.fake_headers, timeout=20) - @mock.patch('zeus.interfaces.rest.requests') + @patch('zeus.client.requests') + def test_get_logs_with_bucket_name(self, mock_requests): + url = urlparse.urljoin(FAKE_SERVER, posixpath.join('logs', FAKE_TOKEN)) + + self.z.bucket(self.fake_bucket_name).getLog('ZeusTest') + mock_requests.get.assert_called_with( + url, + params={'log_name': 'ZeusTest'}, + headers=self.fake_header_with_bucket_name(self.fake_bucket_name), + timeout=20 + ) + self.assertIsNone(self.z.bucket_name) + + @patch('zeus.client.requests') def test_post_empty_metric(self, mock_requests): url = urlparse.urljoin( FAKE_SERVER, posixpath.join('metrics', FAKE_TOKEN, 'ZeusTest')) @@ -160,9 +192,9 @@ def test_post_empty_metric(self, mock_requests): self.z.sendMetric('ZeusTest', metrics) mock_requests.post.assert_called_with( url, data={"metrics": json.dumps(metrics)}, - headers=self.fake_header_with_z_resource('ZeusTest'), timeout=20) + headers=self.fake_headers, timeout=20) - @mock.patch('zeus.interfaces.rest.requests') + @patch('zeus.client.requests') def test_post_single_metric(self, mock_requests): url = urlparse.urljoin( FAKE_SERVER, posixpath.join('metrics', FAKE_TOKEN, 'Zeus.Test')) @@ -170,7 +202,7 @@ def test_post_single_metric(self, mock_requests): self.z.sendMetric('Zeus.Test', metrics) mock_requests.post.assert_called_with( url, data={"metrics": json.dumps(metrics)}, - headers=self.fake_header_with_z_resource('Zeus.Test'), + headers=self.fake_headers, timeout=20) def test_post_single_metric_wrong_name(self): @@ -187,7 +219,7 @@ def test_post_single_metric_wrong_name(self): ZeusException, self.z.sendMetric, '0123456789ABCDEF' * 16, metrics) - @mock.patch('zeus.interfaces.rest.requests') + @patch('zeus.client.requests') def test_post_multiple_metrics(self, mock_requests): url = urlparse.urljoin( FAKE_SERVER, posixpath.join('metrics', FAKE_TOKEN, 'ZeusTest')) @@ -197,9 +229,9 @@ def test_post_multiple_metrics(self, mock_requests): self.z.sendMetric('ZeusTest', metrics) mock_requests.post.assert_called_with( url, data={"metrics": json.dumps(metrics)}, - headers=self.fake_header_with_z_resource('ZeusTest'), timeout=20) + headers=self.fake_headers, timeout=20) - @mock.patch('zeus.interfaces.rest.requests') + @patch('zeus.client.requests') def test_get_metric_values(self, mock_requests): self.z.getMetric(metric_name='ZeusTest', aggregator_function='sum', @@ -222,29 +254,35 @@ def test_get_metric_values(self, mock_requests): 'group_interval': '1m', 'filter_condition': 'value > 90', 'limit': 10, - 'offset': 20}, timeout=20) + 'offset': 20}, + headers=self.fake_headers, + timeout=20) - @mock.patch('zeus.interfaces.rest.requests') + @patch('zeus.client.requests') def test_get_metric_names(self, mock_requests): self.z.getMetricNames(metric_name='ZeusTest', limit=10, offset=20) - mock_requests.get.assert_called_with(FAKE_SERVER + '/metrics/' + - FAKE_TOKEN + '/_names', - params={'metric_name': 'ZeusTest', - 'limit': 10, - 'offset': 20}, timeout=20) + mock_requests.get.assert_called_with( + FAKE_SERVER + '/metrics/' + + FAKE_TOKEN + '/_names', + params={'metric_name': 'ZeusTest', + 'limit': 10, + 'offset': 20}, + headers=self.fake_headers, + timeout=20) - @mock.patch('zeus.interfaces.rest.requests') + @patch('zeus.client.requests') def test_get_delete_metric(self, mock_requests): self.z.deleteMetric('ZeusTest') mock_requests.delete.assert_called_with( FAKE_SERVER + '/metrics/' + FAKE_TOKEN + '/ZeusTest', + headers=self.fake_headers, timeout=20 ) - @mock.patch('zeus.interfaces.rest.requests') + @patch('zeus.client.requests') def test_create_alert(self, mock_requests): alert_name = "testerino" username = "pelegrino" @@ -278,7 +316,7 @@ def test_create_alert(self, mock_requests): FAKE_TOKEN, data=json.dumps(data), headers=self.fake_headers, timeout=20) - @mock.patch('zeus.interfaces.rest.requests') + @patch('zeus.client.requests') def test_modify_alert(self, mock_requests): alert_id = 42 alert_name = "testerino" @@ -313,73 +351,72 @@ def test_modify_alert(self, mock_requests): path, data=json.dumps(data), headers=self.fake_headers, timeout=20) - @mock.patch('zeus.interfaces.rest.requests') + @patch('zeus.client.requests') def test_get_alerts(self, mock_requests): self.z.getAlerts() path = FAKE_SERVER + '/alerts/' + FAKE_TOKEN - mock_requests.get.assert_called_with(path, params=None, timeout=20) + mock_requests.get.assert_called_with( + path, params=None, headers=self.fake_headers, timeout=20) - @mock.patch('zeus.interfaces.rest.requests') + @patch('zeus.client.requests') def test_get_alert(self, mock_requests): alert_id = 42 self.z.getAlert(alert_id) path = FAKE_SERVER + '/alerts/' + FAKE_TOKEN + '/' + str(alert_id) - mock_requests.get.assert_called_with(path, params=None, timeout=20) + mock_requests.get.assert_called_with( + path, params=None, headers=self.fake_headers, timeout=20) - @mock.patch('zeus.interfaces.rest.requests') + @patch('zeus.client.requests') def test_delete_alert(self, mock_requests): alert_id = 42 self.z.deleteAlert(alert_id) path = FAKE_SERVER + '/alerts/' + FAKE_TOKEN + '/' + str(alert_id) - mock_requests.delete.assert_called_with(path, timeout=20) + mock_requests.delete.assert_called_with( + path, headers=self.fake_headers, timeout=20) - @mock.patch('zeus.interfaces.rest.requests') + @patch('zeus.client.requests') def test_enable_alerts(self, mock_requests): alert_id_list = [19, 42] self.z.enableAlerts(alert_id_list) - data = { - 'id': alert_id_list - } + data = {'id': alert_id_list} path = FAKE_SERVER + '/alerts/' + FAKE_TOKEN + '/enable' mock_requests.post.assert_called_with( - path, data=json.dumps(data), - headers=self.fake_headers, timeout=20) + path, data=json.dumps(data), headers=self.fake_headers, timeout=20) - @mock.patch('zeus.interfaces.rest.requests') + @patch('zeus.client.requests') def test_disable_alerts(self, mock_requests): alert_id_list = [19, 42] self.z.disableAlerts(alert_id_list) - data = { - 'id': alert_id_list - } + data = {'id': alert_id_list} path = FAKE_SERVER + '/alerts/' + FAKE_TOKEN + '/disable' mock_requests.post.assert_called_with( - path, data=json.dumps(data), - headers=self.fake_headers, timeout=20) + path, data=json.dumps(data), headers=self.fake_headers, timeout=20) - @mock.patch('zeus.interfaces.rest.requests') + @patch('zeus.client.requests') def test_get_triggered_alerts(self, mock_requests): self.z.getTriggeredAlerts() path = FAKE_SERVER + '/triggeredalerts/' + FAKE_TOKEN - mock_requests.get.assert_called_with(path, params=None, timeout=20) + mock_requests.get.assert_called_with( + path, params=None, headers=self.fake_headers, timeout=20) - @mock.patch('zeus.interfaces.rest.requests') + @patch('zeus.client.requests') def test_get_triggered_alerts_last_24h(self, mock_requests): self.z.getTriggeredAlertsLast24Hours() path = FAKE_SERVER + '/triggeredalerts/' + FAKE_TOKEN + "/last24" - mock_requests.get.assert_called_with(path, params=None, timeout=20) + mock_requests.get.assert_called_with( + path, params=None, headers=self.fake_headers, timeout=20) def test_get_delete_metric_wrong_name(self): self.assertRaises(ZeusException, self.z.deleteMetric, '_WrongName') - @mock.patch('zeus.interfaces.rest.requests') + @patch('zeus.client.requests') def tearDown(self, mock_requests): pass diff --git a/zeus/client.py b/zeus/client.py index 1af4e93..d56413f 100755 --- a/zeus/client.py +++ b/zeus/client.py @@ -14,29 +14,53 @@ # See the License for the specific language governing permissions and # limitations under the License. -from interfaces.rest import RestClient -from interfaces.logs import LogsInterface -from interfaces.metrics import MetricsInterface -from interfaces.alerts import AlertsInterface -from interfaces.trigalerts import TrigAlertsInterface +import requests +import urlparse +from interfaces.logs import get_log +from interfaces.logs import send_log +from interfaces.metrics import send_metric +from interfaces.metrics import delete_metric +from interfaces.metrics import get_metric +from interfaces.metrics import get_metric_names +from interfaces.alerts import create_alert +from interfaces.alerts import delete_alert +from interfaces.alerts import disable_alerts +from interfaces.alerts import enable_alerts +from interfaces.alerts import get_alert +from interfaces.alerts import get_alerts +from interfaces.alerts import modify_alert +from interfaces.trigalerts import get_triggered_alerts +from interfaces.trigalerts import get_triggered_alerts_last24_hours -class ZeusClient(MetricsInterface, LogsInterface, AlertsInterface, TrigAlertsInterface): + +class ZeusClient(object): """ Zeus Client class, implementing wrapper methods for the Zeus API. """ - def __init__(self, user_token, server): - self.token = user_token + def __init__(self, token, endpoint='https://api.ciscozeus.io'): + """ + :param token: either user token or external token. + :type token: str + :param endpoint: URL endpoints + :type endpoint: str + """ + self.token = token + + # TODO 1. Better to separate into function and add test code against it. + url_object = urlparse.urlparse(endpoint) + url_parts = list(url_object) + url_parts[0] = "https://" + self.endpoint = ''.join(url_parts) + self.headers = { 'Authorization': "Bearer {}".format(self.token), 'content-type': 'application/json' } - rest_client = RestClient(server) - self.server = rest_client.server - self.bucket_name = None - super(ZeusClient, self).__init__(user_token, rest_client) + self.bucket_name = None + self.timeout_sec = 20 def bucket(self, bucket_name): """ @@ -49,3 +73,84 @@ def bucket(self, bucket_name): """ self.bucket_name = bucket_name return self + + def __build_header(self): + """ + Make HTTP Header + :return: Header Object + :rtype: dict + """ + if self.bucket_name is None: + return self.headers + + return dict(self.headers, **{'Bucket-Name': self.bucket_name}) + + def _request(self, method, path, data=None): + """ + :param method: HTTTP Method ['GET', 'POST', 'PUT'. 'DELETE'] + :type method: str + :param path: url path start with '/' + :type path: str + :param data: data to be sent + :type data: dict + :param headers: HTTP Header + :type headers: dict + """ + url = urlparse.urljoin(self.endpoint, path) + + if method.upper() == 'GET': + response = requests.get( + url, params=data, headers=self.__build_header(), + timeout=self.timeout_sec + ) + + elif method.upper() == 'POST': + response = requests.post( + url, data=data, headers=self.__build_header(), + timeout=self.timeout_sec + ) + + elif method.upper() == 'PUT': + response = requests.put( + url, data=data, headers=self.__build_header(), + timeout=self.timeout_sec + ) + + elif method.upper() == 'DELETE': + response = requests.delete( + url, headers=self.__build_header(), + timeout=self.timeout_sec + ) + + else: # TODO Define exception more properly + raise Exception('Unknown method {}'.format(method)) + + # TODO better to make a function to clean method chain related variables. + if self.bucket_name is not None: + self.bucket_name = None + + return response + + +# Logs +ZeusClient.getLog = get_log +ZeusClient.sendLog = send_log + +# Metrics +ZeusClient.sendMetric = send_metric +ZeusClient.deleteMetric = delete_metric +ZeusClient.getMetric = get_metric +ZeusClient.getMetricNames = get_metric_names + +# Alerts +ZeusClient.createAlert = create_alert +ZeusClient.deleteAlert = delete_alert +ZeusClient.disableAlerts = disable_alerts +ZeusClient.enableAlerts = enable_alerts +ZeusClient.getAlert = get_alert +ZeusClient.getAlerts = get_alerts +ZeusClient.modifyAlert = modify_alert + +# Trigger Alerts +ZeusClient.getTriggeredAlerts = get_triggered_alerts +ZeusClient.getTriggeredAlertsLast24Hours = get_triggered_alerts_last24_hours diff --git a/zeus/interfaces/alerts.py b/zeus/interfaces/alerts.py index 1511dd2..a5815d2 100644 --- a/zeus/interfaces/alerts.py +++ b/zeus/interfaces/alerts.py @@ -17,144 +17,151 @@ import json -class AlertsInterface(object): - def __init__(self, user_token, rest_client): - self.token = user_token - self.headers = { - 'Authorization': "Bearer {}".format(self.token), - 'content-type': 'application/json' - } - self.rest_client = rest_client - - def createAlert( - self, alert_name, username, alerts_type, alert_expression, - alert_severity, metric_name, emails, status, notify_period - ): - """Creates a new alert, returns status code of creation - and alert parameters - - :param alert_name: Name of the alert - :param username: User the alert belongs to - :param alerts_type: "metric" or "log" - :param alert_expression: expression to evaluate the alert - (eg. "cpu.value > 20") - :param alert_severity: severity level of the alert - :param metric_name: metric associated with the alert - :param emails: emails to receive notification when the alert triggers - :param status: if the alert is active or disable - :param notify_period: frequency of notifications - - :rtype: array - """ - - data = { - 'alert_name': alert_name, - 'username': username, - 'token': self.token, - 'alerts_type': alerts_type, - 'alert_expression': alert_expression, - 'alert_severity': alert_severity, - 'metric_name': metric_name, - 'emails': emails, - 'status': status, - 'notify_period': notify_period - } - url = '/alerts/{}'.format(self.token) - - return self.rest_client.sendPostRequest( - url, json.dumps(data), self.headers) - - def getAlerts(self): - """Return all alerts - - :rtype: array - """ - path = '/alerts/{}'.format(self.token) - return self.rest_client.sendGetRequest(path) - - def modifyAlert( - self, alert_id, alert_name, username, alerts_type, - alert_expression, alert_severity, metric_name, emails, status, - notify_period - ): - """Modifies an existing alert with new data - - :param alert_id: Id of the alert to be modified - :param alert_name: Name of the alert - :param username: User the alert belongs to - :param alerts_type: "metric" or "log" - :param alert_expression: expression to evaluate the alert - (eg. "cpu.value > 20") - :param alert_severity: severity level of the alert - :param metric_name: metric associated with the alert - :param emails: emails to receive notification when the alert triggers - :param status: if the alert is active or disable - :param notify_period: frequency of notifications - - :rtype: array - """ - - data = { - 'alert_name': alert_name, - 'username': username, - 'token': self.token, - 'alerts_type': alerts_type, - 'alert_expression': alert_expression, - 'alert_severity': alert_severity, - 'metric_name': metric_name, - 'emails': emails, - 'status': status, - 'notify_period': notify_period - } - path = '/alerts/{}/{}'.format(self.token, str(alert_id)) - - return self.rest_client.sendPutRequest( - path, json.dumps(data), self.headers) - - def getAlert(self, alert_id): - """Return an specific alert information - - :param alert_id: Id of the alert to be returned - - :rtype: array - """ - path = '/alerts/{}/{}'.format(self.token, str(alert_id)) - - return self.rest_client.sendGetRequest(path) - - def deleteAlert(self, alert_id): - """Delete an specific alert - - :param alert_id: Id of the alert to be deleted - - :rtype: array - """ - path = '/alerts/{}/{}'.format(self.token, str(alert_id)) - - return self.rest_client.sendDeleteRequest(path) - - def enableAlerts(self, alert_id_list): - """Bulk enable alerts - - :param alert_id_list: List of ids of the alerts to be enabled - - :rtype: array - """ - path = '/alerts/{}/enable'.format(self.token) - data = {'id': alert_id_list} - - return self.rest_client.sendPostRequest( - path, json.dumps(data), self.headers) - - def disableAlerts(self, alert_id_list): - """Bulk disable alerts - - :param alert_id_list: List of ids of the alerts to be disabled - - :rtype: array - """ - path = '/alerts/{}/disable'.format(self.token) - data = {'id': alert_id_list} - - return self.rest_client.sendPostRequest( - path, json.dumps(data), self.headers) +def create_alert( + cls, alert_name, username, alerts_type, alert_expression, + alert_severity, metric_name, emails, status, notify_period +): + """Creates a new alert, returns status code of creation + and alert parameters + + :param cls: class object + :type cls: ZeusClient + :param alert_name: Name of the alert + :param username: User the alert belongs to + :param alerts_type: "metric" or "log" + :param alert_expression: expression to evaluate the alert + (eg. "cpu.value > 20") + :param alert_severity: severity level of the alert + :param metric_name: metric associated with the alert + :param emails: emails to receive notification when the alert triggers + :param status: if the alert is active or disable + :param notify_period: frequency of notifications + + :rtype: array + """ + + data = { + 'alert_name': alert_name, + 'username': username, + 'token': cls.token, + 'alerts_type': alerts_type, + 'alert_expression': alert_expression, + 'alert_severity': alert_severity, + 'metric_name': metric_name, + 'emails': emails, + 'status': status, + 'notify_period': notify_period + } + path = '/alerts/{}'.format(cls.token) + + return cls._request('POST', path=path, data=json.dumps(data)) + + +def get_alerts(cls): + """Return all alerts + + :param cls: class object + :type cls: ZeusClient + + :rtype: array + """ + path = '/alerts/{}'.format(cls.token) + return cls._request('GET', path=path) + + +def modify_alert( + cls, alert_id, alert_name, username, alerts_type, + alert_expression, alert_severity, metric_name, emails, status, + notify_period +): + """Modifies an existing alert with new data + + :param cls: class object + :type cls: ZeusClient + :param alert_id: Id of the alert to be modified + :param alert_name: Name of the alert + :param username: User the alert belongs to + :param alerts_type: "metric" or "log" + :param alert_expression: expression to evaluate the alert + (eg. "cpu.value > 20") + :param alert_severity: severity level of the alert + :param metric_name: metric associated with the alert + :param emails: emails to receive notification when the alert triggers + :param status: if the alert is active or disable + :param notify_period: frequency of notifications + + :rtype: array + """ + + data = { + 'alert_name': alert_name, + 'username': username, + 'token': cls.token, + 'alerts_type': alerts_type, + 'alert_expression': alert_expression, + 'alert_severity': alert_severity, + 'metric_name': metric_name, + 'emails': emails, + 'status': status, + 'notify_period': notify_period + } + path = '/alerts/{}/{}'.format(cls.token, str(alert_id)) + + return cls._request('PUT', path=path, data=json.dumps(data)) + + +def get_alert(cls, alert_id): + """Return an specific alert information + + :param cls: class object + :type cls: ZeusClient + :param alert_id: Id of the alert to be returned + + :rtype: array + """ + path = '/alerts/{}/{}'.format(cls.token, str(alert_id)) + + return cls._request('GET', path=path) + + +def delete_alert(cls, alert_id): + """Delete an specific alert + + :param cls: class object + :type cls: ZeusClient + :param alert_id: Id of the alert to be deleted + + :rtype: array + """ + path = '/alerts/{}/{}'.format(cls.token, str(alert_id)) + return cls._request('DELETE', path=path) + + +def enable_alerts(cls, alert_id_list): + """Bulk enable alerts + + :param cls: class object + :type cls: ZeusClient + :param alert_id_list: List of ids of the alerts to be enabled + + :rtype: array + """ + path = '/alerts/{}/enable'.format(cls.token) + data = {'id': alert_id_list} + + return cls._request('POST', path=path, data=json.dumps(data)) + + +def disable_alerts(cls, alert_id_list): + """Bulk disable alerts + + :param cls: class object + :type cls: ZeusClient + :param alert_id_list: List of ids of the alerts to be disabled + + :rtype: array + """ + path = '/alerts/{}/disable'.format(cls.token) + data = {'id': alert_id_list} + + return cls._request('POST', path=path, data=json.dumps(data)) diff --git a/zeus/interfaces/logs.py b/zeus/interfaces/logs.py index ee11820..ea537f4 100644 --- a/zeus/interfaces/logs.py +++ b/zeus/interfaces/logs.py @@ -15,76 +15,60 @@ # limitations under the License. import json -from utils import validateLogName, validateDates +from utils import validate_log_name, validate_dates -class LogsInterface(object): - def __init__(self, user_token, rest_client): - self.token = user_token - self.headers = { - 'Authorization': "Bearer {}".format(self.token), - 'content-type': 'application/json' - } - self.rest_client = rest_client +def send_log(cls, log_name, logs): + """Return ``dict`` saying how many *logs* were successfully inserted + with *log_name*. - def sendLog(self, log_name, logs): - """Return ``dict`` saying how many *logs* were successfully inserted - with *log_name*. + :param cls: class object + :type cls: ZeusClient + :param string log_name: String with the name of the log. + :param dict logs: ``array`` of ``dict`` containing the logs to send. + :rtype: dict - :param string log_name: String with the name of the log. - :param dict logs: ``array`` of ``dict`` containing the logs to send. - :rtype: dict + """ + path = '/logs/{}/{}'.format(cls.token, log_name) - """ - url = '/logs/{}/{}'.format(self.token, log_name) + validate_log_name(log_name) + data = {'logs': json.dumps(logs)} - validateLogName(log_name) - data = {'logs': json.dumps(logs)} + return cls._request('POST', path=path, data=data) - return self.rest_client.sendPostRequest( - url, data, self.__build_header(log_name)) - def getLog(self, log_name, attribute_name=None, pattern=None, - from_date=None, to_date=None, offset=None, limit=None): - """Return ``array`` of ``dict`` with the logs that match the params. +def get_log(cls, log_name, attribute_name=None, pattern=None, + from_date=None, to_date=None, offset=None, limit=None): + """Return ``array`` of ``dict`` with the logs that match the params. - :param string log_name: Name of the log. - :param string attribute_name: Name of field to be searched. If omitted, - search all fields. - :param string pattern: Pattern to match the logs against. - :param string from_date: Unix formatted start date. - :param string to_date: Unix formatted end date. - :param string offset: Result offset. - :param string limit: Max number of results in the return. - :rtype: array + :param cls: class object + :type cls: ZeusClient + :param string log_name: Name of the log. + :param string attribute_name: Name of field to be searched. If omitted, + search all fields. + :param string pattern: Pattern to match the logs against. + :param string from_date: Unix formatted start date. + :param string to_date: Unix formatted end date. + :param string offset: Result offset. + :param string limit: Max number of results in the return. + :rtype: array - """ - url = '/logs/{}'.format(self.token) + """ + path = '/logs/{}'.format(cls.token) - validateDates(from_date, to_date) - data = {"log_name": log_name} - if attribute_name: - data['attribute_name'] = attribute_name - if pattern: - data['pattern'] = pattern - if from_date: - data['from'] = from_date - if to_date: - data['to'] = to_date - if offset: - data['offset'] = offset - if limit: - data['limit'] = limit + validate_dates(from_date, to_date) + data = {"log_name": log_name} + if attribute_name: + data['attribute_name'] = attribute_name + if pattern: + data['pattern'] = pattern + if from_date: + data['from'] = from_date + if to_date: + data['to'] = to_date + if offset: + data['offset'] = offset + if limit: + data['limit'] = limit - return self.rest_client.sendGetRequest( - url, data, self.__build_header(log_name)) - - def __build_header(self, bucket_name): - """ - Make HTTP Header - :param bucket_name: bucket name - :type bucket_name: str - :return: Header Object - :rtype: dict - """ - return dict(self.headers, **{'Bucket-Name': bucket_name}) + return cls._request('GET', path=path, data=data) diff --git a/zeus/interfaces/metrics.py b/zeus/interfaces/metrics.py index 1d95cfe..2e1f8b5 100644 --- a/zeus/interfaces/metrics.py +++ b/zeus/interfaces/metrics.py @@ -15,129 +15,117 @@ # limitations under the License. import json -from utils import validateMetricName, validateDates - - -class MetricsInterface(object): - def __init__(self, user_token, rest_client): - self.token = user_token - self.headers = { - 'Authorization': "Bearer {}".format(self.token), - 'content-type': 'application/json' - } - self.rest_client = rest_client - - def sendMetric(self, metric_name, metrics): - """Return ``dict`` saying how many *metrics* were successfully inserted - with *metric_name*. - - :param string metric_name: String with the name of the metric. - :param dict metrics: ``array`` of ``dict`` containing the metrics to - send. - :rtype: dict - - """ - - url = '/metrics/{}/{}'.format(self.token, metric_name) - validateMetricName(metric_name) - data = {'metrics': json.dumps(metrics)} - - return self.rest_client.sendPostRequest( - url, data=data, headers=self.__build_header(metric_name)) - - def getMetric(self, metric_name, - from_date=None, - to_date=None, - aggregator_function=None, - aggregator_column=None, - group_interval=None, - filter_condition=None, - offset=None, - limit=None): - """Return ``array`` of ``dict`` with the metrics that match the params. - - :param string metric_name: Name of the metric. - :param string from_date: Unix formatted start date. - :param string to_date: Unix formatted end date. - :param string aggregator_function: Aggregator function. ``sum``, - ``count``, ``min``, ``max``,... - :param string aggregator_column: Column to which - ``aggregator_function`` is to be applied. - :param string group_interval: Intervals in which to group the results. - :param string filter_condition: Filters to be applied to metric values. - :param string offset: Result offset. - :param string limit: Max number of results in the return. - :rtype: array - - """ - url = '/metrics/{}/_values'.format(self.token) - validateDates(from_date, to_date) - data = {"metric_name": metric_name} - if from_date: - data['from'] = from_date - if to_date: - data['to'] = to_date - if aggregator_function: - # EG. 'sum' - data['aggregator_function'] = aggregator_function - if aggregator_column: - # EG. 'sum' - data['aggregator_column'] = aggregator_column - if group_interval: - # EG. '1m' - data['group_interval'] = group_interval - if filter_condition: - # EG. '"Values" < 33' - data['filter_condition'] = filter_condition - if limit: - data['limit'] = limit - if offset: - data['offset'] = offset - - return self.rest_client.sendGetRequest( - url=url, data=data, headers=self.__build_header(metric_name)) - - def getMetricNames(self, metric_name=None, limit=None, offset=None): - """Return ``array`` of ``string`` with the metric names that match the - params. - - :param string metric_name: Pattern for the metric name. - :param string limit: Max number of results in the return. - :param string limit: Starting offset in the resulting list. The default - value is 0 (first result). - :rtype: array - - """ - url = '/metrics/{}/_names'.format(self.token) - data = {} - if metric_name: - data['metric_name'] = metric_name - if limit: - data['limit'] = limit - if offset: - data['offset'] = offset - - return self.rest_client.sendGetRequest( - url=url, data=data, headers=self.__build_header(metric_name)) - - def deleteMetric(self, metric_name): - """Delete an entire metric from Zeus. - - :param string metric_name: Pattern for the metric name. - :rtype: boolean - - """ - url = '/metrics/{}/{}'.format(self.token, metric_name) - validateMetricName(metric_name) - return self.rest_client.sendDeleteRequest( - url, data=None, headers=self.__build_header(metric_name)) - - def __build_header(self, bucket_name): - """ - Make HTTP Header - :param bucket_name: bucket name - :type bucket_name: str - :return: Header Object - :rtype: dict - """ - return dict(self.headers, **{'Bucket-Name': bucket_name}) +from utils import validate_metric_name, validate_dates + + +def send_metric(cls, metric_name, metrics): + """Return ``dict`` saying how many *metrics* were successfully inserted + with *metric_name*. + + :param cls: class object + :type cls: ZeusClient + :param string metric_name: String with the name of the metric. + :param dict metrics: ``array`` of ``dict`` containing the metrics to + send. + :rtype: dict + """ + + path = '/metrics/{}/{}'.format(cls.token, metric_name) + validate_metric_name(metric_name) + data = {'metrics': json.dumps(metrics)} + + return cls._request('POST', path=path, data=data) + + +def get_metric(cls, metric_name, + from_date=None, + to_date=None, + aggregator_function=None, + aggregator_column=None, + group_interval=None, + filter_condition=None, + offset=None, + limit=None): + """Return ``array`` of ``dict`` with the metrics that match the params. + + :param cls: class object + :type cls: ZeusClient + :param string metric_name: Name of the metric. + :param string from_date: Unix formatted start date. + :param string to_date: Unix formatted end date. + :param string aggregator_function: Aggregator function. ``sum``, + ``count``, ``min``, ``max``,... + :param string aggregator_column: Column to which + ``aggregator_function`` is to be applied. + :param string group_interval: Intervals in which to group the results. + :param string filter_condition: Filters to be applied to metric values. + :param string offset: Result offset. + :param string limit: Max number of results in the return. + :rtype: array + """ + + path = '/metrics/{}/_values'.format(cls.token) + validate_dates(from_date, to_date) + data = {"metric_name": metric_name} + if from_date: + data['from'] = from_date + if to_date: + data['to'] = to_date + if aggregator_function: + # EG. 'sum' + data['aggregator_function'] = aggregator_function + if aggregator_column: + # EG. 'sum' + data['aggregator_column'] = aggregator_column + if group_interval: + # EG. '1m' + data['group_interval'] = group_interval + if filter_condition: + # EG. '"Values" < 33' + data['filter_condition'] = filter_condition + if limit: + data['limit'] = limit + if offset: + data['offset'] = offset + + return cls._request('GET', path=path, data=data) + + +def get_metric_names(cls, metric_name=None, limit=None, offset=None): + """Return ``array`` of ``string`` with the metric names that match the + params. + + :param cls: class object + :type cls: ZeusClient + :param string metric_name: Pattern for the metric name. + :param string limit: Max number of results in the return. + :param string limit: Starting offset in the resulting list. The default + value is 0 (first result). + :rtype: array + """ + + path = '/metrics/{}/_names'.format(cls.token) + data = {} + if metric_name: + data['metric_name'] = metric_name + if limit: + data['limit'] = limit + if offset: + data['offset'] = offset + + return cls._request('GET', path=path, data=data) + + +def delete_metric(cls, metric_name): + """Delete an entire metric from Zeus. + + :param cls: class object + :type cls: ZeusClient + :param string metric_name: Pattern for the metric name. + :rtype: boolean + """ + + path = '/metrics/{}/{}'.format(cls.token, metric_name) + validate_metric_name(metric_name) + + return cls._request('DELETE', path=path) diff --git a/zeus/interfaces/trigalerts.py b/zeus/interfaces/trigalerts.py index 1af88f2..9111570 100644 --- a/zeus/interfaces/trigalerts.py +++ b/zeus/interfaces/trigalerts.py @@ -15,31 +15,25 @@ # limitations under the License. -class TrigAlertsInterface(object): - def __init__(self, user_token, rest_client): - self.token = user_token - self.headers = { - 'Authorization': "Bearer {}".format(self.token), - 'content-type': 'application/json' - } - self.rest_client = rest_client - - def getTriggeredAlerts(self): - """Return all triggered alerts - - :rtype: array - """ - url = '/triggeredalerts/{}'.format(self.token) - - return self.rest_client.sendGetRequest( - url=url, headers=self.headers) - - def getTriggeredAlertsLast24Hours(self): - """Return all triggered alerts in the last 24 hours - - :rtype: array - """ - url = '/triggeredalerts/{}/last24'.format(self.token) - - return self.rest_client.sendGetRequest( - url=url, headers=self.headers) +def get_triggered_alerts(cls): + """Return all triggered alerts + + :param cls: class object + :type cls: ZeusClient + :rtype: array + """ + path = '/triggeredalerts/{}'.format(cls.token) + + return cls._request('GET', path=path) + + +def get_triggered_alerts_last24_hours(cls): + """Return all triggered alerts in the last 24 hours + + :param cls: class object + :type cls: ZeusClient + :rtype: array + """ + path = '/triggeredalerts/{}/last24'.format(cls.token) + + return cls._request('GET', path=path) diff --git a/zeus/interfaces/utils.py b/zeus/interfaces/utils.py index 75806c0..dcba62c 100644 --- a/zeus/interfaces/utils.py +++ b/zeus/interfaces/utils.py @@ -17,7 +17,7 @@ import re -def validateMetricName(name): +def validate_metric_name(name): if name is None: raise ZeusException("Invalid input. Metric name cannot be None.") name_length = len(name) @@ -30,7 +30,7 @@ def validateMetricName(name): "_ - or .") -def validateDates(from_date, to_date): +def validate_dates(from_date, to_date): try: from_date_value = float(from_date) if from_date else None to_date_value = float(to_date) if to_date else None @@ -43,7 +43,7 @@ def validateDates(from_date, to_date): "after to_date.") -def validateLogName(name): +def validate_log_name(name): if name is None: raise ZeusException("Invalid input. Log name cannot be None.") name_length = len(name)