From 15791619c9454d8807a4ca982a7b8099a0cd1d37 Mon Sep 17 00:00:00 2001 From: Fernando Ojeda Date: Tue, 28 Apr 2020 12:24:16 -0400 Subject: [PATCH 1/3] Add Account planned, unplanned and announcement events. --- SoftLayer/CLI/account/events.py | 88 ++++++++++++++++++++++++++------- SoftLayer/managers/account.py | 56 +++++++++++++++++---- tests/managers/account_tests.py | 45 ++++++++++++++++- 3 files changed, 158 insertions(+), 31 deletions(-) diff --git a/SoftLayer/CLI/account/events.py b/SoftLayer/CLI/account/events.py index 5cc91144d..c80614969 100644 --- a/SoftLayer/CLI/account/events.py +++ b/SoftLayer/CLI/account/events.py @@ -2,10 +2,10 @@ # :license: MIT, see LICENSE for more details. import click +from SoftLayer import utils from SoftLayer.CLI import environment from SoftLayer.CLI import formatting from SoftLayer.managers.account import AccountManager as AccountManager -from SoftLayer import utils @click.command() @@ -16,39 +16,89 @@ def cli(env, ack_all): """Summary and acknowledgement of upcoming and ongoing maintenance events""" manager = AccountManager(env.client) - events = manager.get_upcoming_events() + planned_events = manager.get_upcoming_events("PLANNED") + unplanned_events = manager.get_upcoming_events("UNPLANNED_INCIDENT") + announcement_events = manager.get_upcoming_events("ANNOUNCEMENT") + + add_ack_flag(planned_events, manager, ack_all) + env.fout(planned_event_table(planned_events)) + + add_ack_flag(unplanned_events, manager, ack_all) + env.fout(unplanned_event_table(unplanned_events)) + add_ack_flag(announcement_events, manager, ack_all) + env.fout(announcement_event_table(announcement_events)) + + +def add_ack_flag(events, manager, ack_all): if ack_all: for event in events: result = manager.ack_event(event['id']) event['acknowledgedFlag'] = result - env.fout(event_table(events)) -def event_table(events): +def planned_event_table(events): """Formats a table for events""" - table = formatting.Table([ - "Id", - "Start Date", - "End Date", - "Subject", - "Status", - "Acknowledged", - "Updates", - "Impacted Resources" - ], title="Upcoming Events") - table.align['Subject'] = 'l' - table.align['Impacted Resources'] = 'l' + planned_table = formatting.Table(['Event Data', 'Id', 'Event ID', 'Subject', 'Status', 'Items', 'Start Date', + 'End Date', 'Acknowledged', 'Updates'], title="Planned Events") + planned_table.align['Subject'] = 'l' + planned_table.align['Impacted Resources'] = 'l' for event in events: - table.add_row([ + planned_table.add_row([ + utils.clean_time(event.get('startDate')), event.get('id'), + event.get('systemTicketId'), + # Some subjects can have \r\n for some reason. + utils.clean_splitlines(event.get('subject')), + utils.lookup(event, 'statusCode', 'name'), + event.get('impactedResourceCount'), utils.clean_time(event.get('startDate')), utils.clean_time(event.get('endDate')), + event.get('acknowledgedFlag'), + event.get('updateCount'), + + ]) + return planned_table + + +def unplanned_event_table(events): + """Formats a table for events""" + unplanned_table = formatting.Table(['Id', 'Event ID', 'Subject', 'Status', 'Items', 'Start Date', + 'Last Updated', 'Acknowledged', 'Updates'], title="Unplanned Events") + unplanned_table.align['Subject'] = 'l' + unplanned_table.align['Impacted Resources'] = 'l' + for event in events: + print(event.get('modifyDate')) + unplanned_table.add_row([ + event.get('id'), + event.get('systemTicketId'), # Some subjects can have \r\n for some reason. utils.clean_splitlines(event.get('subject')), utils.lookup(event, 'statusCode', 'name'), + event.get('impactedResourceCount'), + utils.clean_time(event.get('startDate')), + utils.clean_time(event.get('modifyDate')), event.get('acknowledgedFlag'), event.get('updateCount'), - event.get('impactedResourceCount') ]) - return table + return unplanned_table + + +def announcement_event_table(events): + """Formats a table for events""" + announcement_table = formatting.Table( + ['Id', 'Event ID', 'Subject', 'Status', 'Items', 'Acknowledged', 'Updates'], title="Announcement Events") + announcement_table.align['Subject'] = 'l' + announcement_table.align['Impacted Resources'] = 'l' + for event in events: + announcement_table.add_row([ + event.get('id'), + event.get('systemTicketId'), + # Some subjects can have \r\n for some reason. + utils.clean_splitlines(event.get('subject')), + utils.lookup(event, 'statusCode', 'name'), + event.get('impactedResourceCount'), + event.get('acknowledgedFlag'), + event.get('updateCount') + ]) + return announcement_table diff --git a/SoftLayer/managers/account.py b/SoftLayer/managers/account.py index 4269bc7a5..56f951c28 100644 --- a/SoftLayer/managers/account.py +++ b/SoftLayer/managers/account.py @@ -47,25 +47,61 @@ def get_summary(self): """ return self.client.call('Account', 'getObject', mask=mask) - def get_upcoming_events(self): - """Retreives a list of Notification_Occurrence_Events that have not ended yet + def get_upcoming_events(self, event_type): + """Retrieves a list of Notification_Occurrence_Events that have not ended yet + :param: String event_type: notification event type. :return: SoftLayer_Notification_Occurrence_Event """ - mask = "mask[id, subject, startDate, endDate, statusCode, acknowledgedFlag, impactedResourceCount, updateCount]" + mask = "mask[id, subject, startDate, endDate, modifyDate, statusCode, acknowledgedFlag, " \ + "impactedResourceCount, updateCount, systemTicketId, notificationOccurrenceEventType[keyName]]" + _filter = { - 'endDate': { - 'operation': '> sysdate' - }, - 'startDate': { + 'notificationOccurrenceEventType': { + 'keyName': { + 'operation': event_type + } + } + } + + self.add_event_filter(_filter, event_type) + + return self.client.call('Notification_Occurrence_Event', 'getAllObjects', filter=_filter, mask=mask, iter=True) + + @staticmethod + def add_event_filter(_filter, event_type): + """Add data to the object filter. + + :param: _filter: event filter. + :param: string event_type: event type. + """ + if event_type == 'PLANNED': + _filter['endDate'] = { + 'operation': '> sysdate - 2' + } + _filter['startDate'] = { 'operation': 'orderBy', 'options': [{ 'name': 'sort', - 'value': ['ASC'] + 'value': ['DESC'] }] } - } - return self.client.call('Notification_Occurrence_Event', 'getAllObjects', filter=_filter, mask=mask, iter=True) + + if event_type == 'UNPLANNED_INCIDENT': + _filter['modifyDate'] = { + 'operation': '> sysdate - 2' + } + + if event_type == 'ANNOUNCEMENT': + _filter['statusCode'] = { + 'keyName': { + 'operation': 'in', + 'options': [{ + 'name': 'data', + 'value': ['PUBLISHED'] + }] + } + } def ack_event(self, event_id): """Acknowledge an event. This mostly prevents it from appearing as a notification in the control portal. diff --git a/tests/managers/account_tests.py b/tests/managers/account_tests.py index 513aa44ff..b47ec6abb 100644 --- a/tests/managers/account_tests.py +++ b/tests/managers/account_tests.py @@ -18,10 +18,51 @@ def test_get_summary(self): self.manager.get_summary() self.assert_called_with('SoftLayer_Account', 'getObject') - def test_get_upcoming_events(self): - self.manager.get_upcoming_events() + def test_get_planned_upcoming_events(self): + self.manager.get_upcoming_events("PLANNED") self.assert_called_with(self.SLNOE, 'getAllObjects') + def test_get_unplanned_upcoming_events(self): + self.manager.get_upcoming_events("UNPLANNED_INCIDENT") + self.assert_called_with(self.SLNOE, 'getAllObjects') + + def test_get_announcement_upcoming_events(self): + self.manager.get_upcoming_events("ANNOUNCEMENT") + self.assert_called_with(self.SLNOE, 'getAllObjects') + + def test_add_planned_event_filter(self): + event_type = 'PLANNED' + _filter = { + 'notificationOccurrenceEventType': { + 'keyName': { + 'operation': event_type + } + } + } + self.manager.add_event_filter(_filter, event_type) + + def test_add_unplanned_event_filter(self): + event_type = 'UNPLANNED_INCIDENT' + _filter = { + 'notificationOccurrenceEventType': { + 'keyName': { + 'operation': event_type + } + } + } + self.manager.add_event_filter(_filter, event_type) + + def test_add_announcement_event_filter(self): + event_type = 'ANNOUNCEMENT' + _filter = { + 'notificationOccurrenceEventType': { + 'keyName': { + 'operation': event_type + } + } + } + self.manager.add_event_filter(_filter, event_type) + def test_ack_event(self): self.manager.ack_event(12345) self.assert_called_with(self.SLNOE, 'acknowledgeNotification', identifier=12345) From 975435d0fcafe2cdc77acb71138132f82490357e Mon Sep 17 00:00:00 2001 From: Fernando Ojeda Date: Tue, 28 Apr 2020 12:50:54 -0400 Subject: [PATCH 2/3] fix analysis tox. --- SoftLayer/CLI/account/events.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SoftLayer/CLI/account/events.py b/SoftLayer/CLI/account/events.py index c80614969..689b5edad 100644 --- a/SoftLayer/CLI/account/events.py +++ b/SoftLayer/CLI/account/events.py @@ -2,10 +2,10 @@ # :license: MIT, see LICENSE for more details. import click -from SoftLayer import utils from SoftLayer.CLI import environment from SoftLayer.CLI import formatting from SoftLayer.managers.account import AccountManager as AccountManager +from SoftLayer import utils @click.command() From 7203df063f2927fcce42d154ba278d57a8dae847 Mon Sep 17 00:00:00 2001 From: Fernando Ojeda Date: Tue, 28 Apr 2020 15:01:15 -0400 Subject: [PATCH 3/3] fix analysis tox method docstring. --- SoftLayer/CLI/account/events.py | 1 + 1 file changed, 1 insertion(+) diff --git a/SoftLayer/CLI/account/events.py b/SoftLayer/CLI/account/events.py index 689b5edad..b5d8960cb 100644 --- a/SoftLayer/CLI/account/events.py +++ b/SoftLayer/CLI/account/events.py @@ -31,6 +31,7 @@ def cli(env, ack_all): def add_ack_flag(events, manager, ack_all): + """Add acknowledgedFlag to the event""" if ack_all: for event in events: result = manager.ack_event(event['id'])