From 4c5888e97aa2b08d32fd2dc3a4a6db2d834a7002 Mon Sep 17 00:00:00 2001 From: Nick Satterly Date: Sat, 17 Aug 2019 22:13:20 +0200 Subject: [PATCH 1/2] Refactor query output formats to support single-line option --- alertaclient/commands/cmd_query.py | 20 ++++--- alertaclient/models/alert.py | 88 ++++++++++-------------------- alertaclient/models/history.py | 4 +- 3 files changed, 44 insertions(+), 68 deletions(-) diff --git a/alertaclient/commands/cmd_query.py b/alertaclient/commands/cmd_query.py index 4215c72..fdc4293 100644 --- a/alertaclient/commands/cmd_query.py +++ b/alertaclient/commands/cmd_query.py @@ -21,9 +21,9 @@ @click.option('--ids', '-i', metavar='UUID', multiple=True, help='List of alert IDs (can use short 8-char id)') @click.option('--query', '-q', 'query', metavar='QUERY', help='severity:"warning" AND resource:web') @click.option('--filter', '-f', 'filters', metavar='FILTER', multiple=True, help='KEY=VALUE eg. serverity=warning resource=web') -@click.option('--tabular', 'display', flag_value='tabular', default=True, help='Tabular output') -@click.option('--compact', 'display', flag_value='compact', help='Compact output') -@click.option('--details', 'display', flag_value='details', help='Compact output with details') +@click.option('--oneline', 'display', flag_value='oneline', default=True, help='Show alerts using table format') +@click.option('--medium', 'display', flag_value='medium', help='Show important alert attributes') +@click.option('--full', 'display', flag_value='full', help='Show full alert details') @click.pass_obj def cli(obj, ids, query, filters, display, from_date=None): """Query for alerts based on search filter criteria.""" @@ -50,13 +50,15 @@ def cli(obj, ids, query, filters, display, from_date=None): last_time = r['lastTime'] auto_refresh = r['autoRefresh'] - if display == 'tabular': + if display == 'oneline': headers = {'id': 'ID', 'lastReceiveTime': 'LAST RECEIVED', 'severity': 'SEVERITY', 'status': 'STATUS', 'duplicateCount': 'DUPL', 'customer': 'CUSTOMER', 'environment': 'ENVIRONMENT', 'service': 'SERVICE', - 'resource': 'RESOURCE', 'group': 'GROUP', 'event': 'EVENT', 'value': 'VALUE', 'text': 'TEXT'} - click.echo(tabulate([a.tabular('summary', timezone) - for a in alerts], headers=headers, tablefmt=obj['output'])) - elif display in ['compact', 'details']: + 'resource': 'RESOURCE', 'group': 'GROUP', 'event': 'EVENT', 'value': 'VALUE', 'text': 'DESCRIPTION'} + + data = [{k: v for k, v in a.tabular(timezone).items() if k in headers.keys()} for a in alerts] + click.echo(tabulate(data, headers=headers, tablefmt=obj['output'])) + + else: for alert in reversed(alerts): color = COLOR_MAP.get(alert.severity, {'fg': 'white'}) click.secho('{}|{}|{}|{:5d}|{}|{:<5s}|{:<10s}|{:<18s}|{:12s}|{:16s}|{:12s}'.format( @@ -73,7 +75,7 @@ def cli(obj, ids, query, filters, display, from_date=None): alert.value or 'n/a'), fg=color['fg']) click.secho(' |{}'.format(alert.text), fg=color['fg']) - if display == 'details': + if display == 'full': click.secho(' severity | {} -> {}'.format(alert.previous_severity, alert.severity), fg=color['fg']) click.secho(' trend | {}'.format(alert.trend_indication), fg=color['fg']) diff --git a/alertaclient/models/alert.py b/alertaclient/models/alert.py index 2bb6af3..c31348c 100644 --- a/alertaclient/models/alert.py +++ b/alertaclient/models/alert.py @@ -97,61 +97,33 @@ def parse(cls, json): def get_id(self, short=False): return self.id[:8] if short else self.id - def tabular(self, fields='all', timezone=None): - if fields == 'summary': - return { - 'id': self.get_id(short=True), - 'lastReceiveTime': DateTime.localtime(self.last_receive_time, timezone), - 'severity': self.severity, - 'status': self.status, - 'duplicateCount': self.duplicate_count, - 'customer': self.customer, - 'environment': self.environment, - 'service': ','.join(self.service), - 'resource': self.resource, - 'group': self.group, - 'event': self.event, - 'value': self.value, - 'text': self.text - } - elif fields == 'details': - return { - 'severity': '{} -> {}'.format(self.previous_severity, self.severity), - 'trend': self.trend_indication, - 'status': self.status, - 'resource': self.resource, - 'group': self.group, - 'event': self.event, - 'value': self.value, - 'tags': ','.join(self.tags) - } - else: - return { - 'id': self.id, - 'resource': self.resource, - 'event': self.event, - 'environment': self.environment, - 'severity': self.severity, - 'correlate': self.correlate, - 'status': self.status, - 'service': ','.join(self.service), - 'group': self.group, - 'value': self.value, - 'text': self.text, - 'tags': ','.join(self.tags), - 'attributes': self.attributes, - 'origin': self.origin, - 'type': self.event_type, - 'createTime': DateTime.localtime(self.create_time, timezone), - 'timeout': self.timeout, - 'rawData': self.raw_data, - 'customer': self.customer, - 'duplicateCount': self.duplicate_count, - 'repeat': self.repeat, - 'previousSeverity': self.previous_severity, - 'trendIndication': self.trend_indication, - 'receiveTime': DateTime.localtime(self.receive_time, timezone), - 'lastReceiveId': self.last_receive_id, - 'lastReceiveTime': DateTime.localtime(self.last_receive_time, timezone), - 'history': self.history - } + def tabular(self, timezone=None): + return { + 'id': self.get_id(short=True), + 'lastReceiveTime': DateTime.localtime(self.last_receive_time, timezone), + 'severity': self.severity, + 'status': self.status, + 'duplicateCount': self.duplicate_count, + 'customer': self.customer, + 'environment': self.environment, + 'service': ','.join(self.service), + 'resource': self.resource, + 'group': self.group, + 'event': self.event, + 'correlate': self.correlate, + 'value': self.value, + 'text': self.text, + 'tags': ','.join(self.tags), + 'attributes': self.attributes, + 'origin': self.origin, + 'type': self.event_type, + 'createTime': DateTime.localtime(self.create_time, timezone), + 'timeout': self.timeout, + 'rawData': self.raw_data, + 'repeat': self.repeat, + 'previousSeverity': self.previous_severity, + 'trendIndication': self.trend_indication, + 'receiveTime': DateTime.localtime(self.receive_time, timezone), + 'lastReceiveId': self.last_receive_id, + 'history': self.history + } diff --git a/alertaclient/models/history.py b/alertaclient/models/history.py index 12c911c..e575206 100644 --- a/alertaclient/models/history.py +++ b/alertaclient/models/history.py @@ -12,9 +12,10 @@ def __init__(self, id, event, **kwargs): self.severity = kwargs.get('severity', None) self.status = kwargs.get('status', None) self.value = kwargs.get('value', None) - self.change_type = kwargs.get('change_type', kwargs.get('type', None)) or '' self.text = kwargs.get('text', None) + self.change_type = kwargs.get('change_type', kwargs.get('type', None)) or '' self.update_time = kwargs.get('update_time', None) or datetime.utcnow() + self.user = kwargs.get('user', None) def __repr__(self): return 'History(id={!r}, event={!r}, severity={!r}, status={!r}, type={!r})'.format( @@ -39,6 +40,7 @@ def __init__(self, resource, event, **kwargs): self.attributes = kwargs.get('attributes', None) or dict() self.origin = kwargs.get('origin', None) self.update_time = kwargs.get('update_time', None) + self.user = kwargs.get('user', None) self.change_type = kwargs.get('change_type', kwargs.get('type', None)) self.customer = kwargs.get('customer', None) From 4283cfd3e7eb11d119e9f25a92e29f52b6520114 Mon Sep 17 00:00:00 2001 From: Nick Satterly Date: Sun, 18 Aug 2019 08:23:50 +0200 Subject: [PATCH 2/2] Remove redundant unit test --- tests/test_formats.py | 105 ------------------------------------------ 1 file changed, 105 deletions(-) delete mode 100644 tests/test_formats.py diff --git a/tests/test_formats.py b/tests/test_formats.py deleted file mode 100644 index b0261ed..0000000 --- a/tests/test_formats.py +++ /dev/null @@ -1,105 +0,0 @@ -import unittest - -import requests_mock - -from alertaclient.api import Client - - -class FormatsTestCase(unittest.TestCase): - - def setUp(self): - self.client = Client() - - self.alert = """ - { - "alert": { - "attributes": { - "ip": "127.0.0.1" - }, - "correlate": [], - "createTime": "2018-04-08T19:01:44.979Z", - "customer": null, - "duplicateCount": 0, - "environment": "Development", - "event": "foo", - "group": "Misc", - "history": [ - { - "event": "foo", - "href": "https://alerta-api.herokuapp.com/alert/d1bb37cf-e976-429e-96f5-82b2a48aa50b", - "id": "d1bb37cf-e976-429e-96f5-82b2a48aa50b", - "severity": null, - "status": "shelved", - "text": "shelved by Test90", - "type": "status", - "updateTime": "2018-04-09T09:11:43.502Z", - "value": null - }, - { - "event": "foo", - "href": "https://alerta-api.herokuapp.com/alert/d1bb37cf-e976-429e-96f5-82b2a48aa50b", - "id": "d1bb37cf-e976-429e-96f5-82b2a48aa50b", - "severity": null, - "status": "open", - "text": "bulk status change via console by test", - "type": "status", - "updateTime": "2018-04-24T17:52:40.088Z", - "value": null - }, - { - "event": "foo", - "href": "https://alerta-api.herokuapp.com/alert/d1bb37cf-e976-429e-96f5-82b2a48aa50b", - "id": "d1bb37cf-e976-429e-96f5-82b2a48aa50b", - "severity": "minor", - "status": "shelved", - "text": "status change via console by Scott Wenzel", - "type": "action", - "updateTime": "2018-05-18T03:38:50.333Z", - "value": null - } - ], - "href": "https://alerta-api.herokuapp.com/alert/d1bb37cf-e976-429e-96f5-82b2a48aa50b", - "id": "d1bb37cf-e976-429e-96f5-82b2a48aa50b", - "lastReceiveId": "d1bb37cf-e976-429e-96f5-82b2a48aa50b", - "lastReceiveTime": "2018-04-08T19:01:46.090Z", - "origin": "alertad/fdaa33ca.lan", - "previousSeverity": "indeterminate", - "rawData": null, - "receiveTime": "2018-04-08T19:01:46.090Z", - "repeat": false, - "resource": "quux", - "service": [ - "Bar" - ], - "severity": "minor", - "status": "shelved", - "tags": [ - "watch:Scott Wenzel" - ], - "text": "", - "timeout": 3600, - "trendIndication": "moreSevere", - "type": "exceptionAlert", - "value": null - } - } - """ - - @requests_mock.mock() - def test_alert(self, m): - m.post('http://localhost:8080/alert', text=self.alert) - msg = {'event': 'foo', 'service': ['Bar']} - - id, alert, message = self.client.send_alert( - environment='Production', - resource='quux', - **msg - ) - alert_summary = alert.tabular(fields='summary', timezone='UTC') - self.assertEqual(alert_summary['id'], 'd1bb37cf') - - alert_summary = alert.tabular(fields='details', timezone='UTC') - self.assertEqual(alert_summary['severity'], 'indeterminate -> minor') - - alert_summary = alert.tabular(fields='all', timezone='UTC') - self.assertEqual(alert_summary['history'][0]['status'], 'shelved')