Skip to content

Commit ce27773

Browse files
Merge pull request #1297 from ATGE/issue1280
Notification management
2 parents 034a72f + 9c94074 commit ce27773

File tree

8 files changed

+245
-0
lines changed

8 files changed

+245
-0
lines changed

SoftLayer/CLI/routes.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -316,6 +316,8 @@
316316
('user:detail', 'SoftLayer.CLI.user.detail:cli'),
317317
('user:permissions', 'SoftLayer.CLI.user.permissions:cli'),
318318
('user:edit-permissions', 'SoftLayer.CLI.user.edit_permissions:cli'),
319+
('user:notifications', 'SoftLayer.CLI.user.notifications:cli'),
320+
('user:edit-notifications', 'SoftLayer.CLI.user.edit_notifications:cli'),
319321
('user:edit-details', 'SoftLayer.CLI.user.edit_details:cli'),
320322
('user:create', 'SoftLayer.CLI.user.create:cli'),
321323
('user:delete', 'SoftLayer.CLI.user.delete:cli'),
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
"""Enable or Disable specific noticication for the current user"""
2+
# :license: MIT, see LICENSE for more details.
3+
4+
import click
5+
6+
import SoftLayer
7+
from SoftLayer.CLI import environment
8+
9+
10+
@click.command()
11+
@click.option('--enable/--disable', default=True,
12+
help="Enable (DEFAULT) or Disable selected notification")
13+
@click.argument('notification', nargs=-1, required=True)
14+
@environment.pass_env
15+
def cli(env, enable, notification):
16+
"""Enable or Disable specific notifications for the active user.
17+
18+
Notification names should be enclosed in quotation marks.
19+
Example::
20+
21+
slcli user edit-notifications --enable 'Order Approved' 'Reload Complete'
22+
23+
"""
24+
25+
mgr = SoftLayer.UserManager(env.client)
26+
27+
if enable:
28+
result = mgr.enable_notifications(notification)
29+
else:
30+
result = mgr.disable_notifications(notification)
31+
32+
if result:
33+
click.secho("Notifications updated successfully: %s" % ", ".join(notification), fg='green')
34+
else:
35+
click.secho("Failed to update notifications: %s" % ", ".join(notification), fg='red')
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
"""List user notifications"""
2+
import click
3+
4+
import SoftLayer
5+
from SoftLayer.CLI import environment
6+
from SoftLayer.CLI import formatting
7+
8+
9+
@click.command()
10+
@environment.pass_env
11+
def cli(env):
12+
"""My Notifications."""
13+
14+
mgr = SoftLayer.UserManager(env.client)
15+
16+
all_notifications = mgr.get_all_notifications()
17+
18+
env.fout(notification_table(all_notifications))
19+
20+
21+
def notification_table(all_notifications):
22+
"""Creates a table of available notifications"""
23+
24+
table = formatting.Table(['Id', 'Name', 'Description', 'Enabled'])
25+
table.align['Id'] = 'l'
26+
table.align['Name'] = 'l'
27+
table.align['Description'] = 'l'
28+
table.align['Enabled'] = 'l'
29+
for notification in all_notifications:
30+
table.add_row([notification['id'],
31+
notification['name'],
32+
notification['description'],
33+
notification['enabled']])
34+
return table
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
getAllObjects = [
2+
{'description': 'Email about your order.',
3+
'enabled': True,
4+
'id': 1,
5+
'name': 'Order Being Reviewed'
6+
},
7+
{'description': 'Maintenances that will or are likely to cause service '
8+
'outages and disruptions',
9+
'enabled': True,
10+
'id': 8,
11+
'name': 'High Impact'
12+
},
13+
{'description': 'Testing description.',
14+
'enabled': True,
15+
'id': 111,
16+
'name': 'Test notification'
17+
}
18+
]
19+
20+
enable = True
21+
22+
disable = True

SoftLayer/managers/user.py

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ def __init__(self, client):
3636
self.user_service = self.client['SoftLayer_User_Customer']
3737
self.override_service = self.client['Network_Service_Vpn_Overrides']
3838
self.account_service = self.client['SoftLayer_Account']
39+
self.subscription_service = self.client['SoftLayer_Email_Subscription']
3940
self.resolvers = [self._get_id_from_username]
4041
self.all_permissions = None
4142

@@ -85,6 +86,52 @@ def get_all_permissions(self):
8586
self.all_permissions = sorted(permissions, key=itemgetter('keyName'))
8687
return self.all_permissions
8788

89+
def get_all_notifications(self):
90+
"""Calls SoftLayer_Email_Subscription::getAllObjects
91+
92+
Stores the result in self.all_permissions
93+
:returns: A list of dictionaries that contains all valid permissions
94+
"""
95+
return self.subscription_service.getAllObjects(mask='mask[enabled]')
96+
97+
def enable_notifications(self, notifications_names):
98+
"""Enables a list of notifications for the current a user profile.
99+
100+
:param list notifications_names: List of notifications names to enable
101+
:returns: True on success
102+
103+
Example::
104+
enable_notifications(['Order Approved','Reload Complete'])
105+
"""
106+
107+
result = False
108+
notifications = self.gather_notifications(notifications_names)
109+
for notification in notifications:
110+
notification_id = notification.get('id')
111+
result = self.subscription_service.enable(id=notification_id)
112+
if not result:
113+
return False
114+
return result
115+
116+
def disable_notifications(self, notifications_names):
117+
"""Disable a list of notifications for the current a user profile.
118+
119+
:param list notifications_names: List of notifications names to disable
120+
:returns: True on success
121+
122+
Example::
123+
disable_notifications(['Order Approved','Reload Complete'])
124+
"""
125+
126+
result = False
127+
notifications = self.gather_notifications(notifications_names)
128+
for notification in notifications:
129+
notification_id = notification.get('id')
130+
result = self.subscription_service.disable(id=notification_id)
131+
if not result:
132+
return False
133+
return result
134+
88135
def add_permissions(self, user_id, permissions):
89136
"""Enables a list of permissions for a user
90137
@@ -237,6 +284,23 @@ def format_permission_object(self, permissions):
237284
raise exceptions.SoftLayerError("'%s' is not a valid permission" % permission)
238285
return pretty_permissions
239286

287+
def gather_notifications(self, notifications_names):
288+
"""Gets a list of notifications.
289+
290+
:param list notifications_names: A list of notifications names.
291+
:returns: list of notifications.
292+
"""
293+
notifications = []
294+
available_notifications = self.get_all_notifications()
295+
for notification in notifications_names:
296+
result = next((item for item in available_notifications
297+
if item.get('name') == notification), None)
298+
if result:
299+
notifications.append(result)
300+
else:
301+
raise exceptions.SoftLayerError("{} is not a valid notification name".format(notification))
302+
return notifications
303+
240304
def create_user(self, user_object, password):
241305
"""Blindly sends user_object to SoftLayer_User_Customer::createObject
242306

docs/cli/users.rst

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,18 @@ Version 5.6.0 introduces the ability to interact with user accounts from the cli
1212
:prog: user detail
1313
:show-nested:
1414

15+
.. click:: SoftLayer.CLI.user.notifications:cli
16+
:prog: user notifications
17+
:show-nested:
18+
1519
.. click:: SoftLayer.CLI.user.permissions:cli
1620
:prog: user permissions
1721
:show-nested:
1822

23+
.. click:: SoftLayer.CLI.user.edit_notifications:cli
24+
:prog: user edit-notifications
25+
:show-nested:
26+
1927
.. click:: SoftLayer.CLI.user.edit_permissions:cli
2028
:prog: user edit-permissions
2129
:show-nested:

tests/CLI/modules/user_tests.py

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -305,3 +305,35 @@ def test_vpn_subnet_remove(self, click):
305305
result = self.run_command(['user', 'vpn-subnet', '12345', '--remove', '1234'])
306306
click.secho.assert_called_with('12345 updated successfully', fg='green')
307307
self.assert_no_fail(result)
308+
309+
"""User notification tests"""
310+
311+
def test_notificacions_list(self):
312+
result = self.run_command(['user', 'notifications'])
313+
self.assert_no_fail(result)
314+
self.assert_called_with('SoftLayer_Email_Subscription', 'getAllObjects', mask='mask[enabled]')
315+
316+
"""User edit-notification tests"""
317+
318+
def test_edit_notification_on(self):
319+
result = self.run_command(['user', 'edit-notifications', '--enable', 'Test notification'])
320+
self.assert_no_fail(result)
321+
self.assert_called_with('SoftLayer_Email_Subscription', 'enable', identifier=111)
322+
323+
def test_edit_notification_on_bad(self):
324+
result = self.run_command(['user', 'edit-notifications', '--enable', 'Test not exist'])
325+
self.assertEqual(result.exit_code, 1)
326+
327+
def test_edit_notifications_off(self):
328+
result = self.run_command(['user', 'edit-notifications', '--disable', 'Test notification'])
329+
self.assert_no_fail(result)
330+
self.assert_called_with('SoftLayer_Email_Subscription', 'disable', identifier=111)
331+
332+
@mock.patch('SoftLayer.CLI.user.edit_notifications.click')
333+
def test_edit_notification_off_failure(self, click):
334+
notification = self.set_mock('SoftLayer_Email_Subscription', 'disable')
335+
notification.return_value = False
336+
result = self.run_command(['user', 'edit-notifications', '--disable', 'Test notification'])
337+
click.secho.assert_called_with('Failed to update notifications: Test notification', fg='red')
338+
self.assert_no_fail(result)
339+
self.assert_called_with('SoftLayer_Email_Subscription', 'disable', identifier=111)

tests/managers/user_tests.py

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@
44
55
"""
66
import datetime
7+
78
import mock
9+
810
import SoftLayer
911
from SoftLayer import exceptions
1012
from SoftLayer import testing
@@ -246,3 +248,49 @@ def test_vpn_subnet_remove(self):
246248
self.manager.vpn_subnet_remove(user_id, [subnet_id])
247249
self.assert_called_with('SoftLayer_Network_Service_Vpn_Overrides', 'deleteObjects', args=expected_args)
248250
self.assert_called_with('SoftLayer_User_Customer', 'updateVpnUser', identifier=user_id)
251+
252+
def test_get_all_notifications(self):
253+
self.manager.get_all_notifications()
254+
self.assert_called_with('SoftLayer_Email_Subscription', 'getAllObjects')
255+
256+
def test_enable_notifications(self):
257+
self.manager.enable_notifications(['Test notification'])
258+
self.assert_called_with('SoftLayer_Email_Subscription', 'enable', identifier=111)
259+
260+
def test_disable_notifications(self):
261+
self.manager.disable_notifications(['Test notification'])
262+
self.assert_called_with('SoftLayer_Email_Subscription', 'disable', identifier=111)
263+
264+
def test_enable_notifications_fail(self):
265+
notification = self.set_mock('SoftLayer_Email_Subscription', 'enable')
266+
notification.return_value = False
267+
result = self.manager.enable_notifications(['Test notification'])
268+
self.assert_called_with('SoftLayer_Email_Subscription', 'enable', identifier=111)
269+
self.assertFalse(result)
270+
271+
def test_disable_notifications_fail(self):
272+
notification = self.set_mock('SoftLayer_Email_Subscription', 'disable')
273+
notification.return_value = False
274+
result = self.manager.disable_notifications(['Test notification'])
275+
self.assert_called_with('SoftLayer_Email_Subscription', 'disable', identifier=111)
276+
self.assertFalse(result)
277+
278+
def test_gather_notifications(self):
279+
expected_result = [
280+
{'description': 'Testing description.',
281+
'enabled': True,
282+
'id': 111,
283+
'name': 'Test notification'
284+
}
285+
]
286+
result = self.manager.gather_notifications(['Test notification'])
287+
self.assert_called_with('SoftLayer_Email_Subscription',
288+
'getAllObjects',
289+
mask='mask[enabled]')
290+
self.assertEqual(result, expected_result)
291+
292+
def test_gather_notifications_fail(self):
293+
ex = self.assertRaises(SoftLayer.SoftLayerError,
294+
self.manager.gather_notifications,
295+
['Test not exit'])
296+
self.assertEqual("Test not exit is not a valid notification name", str(ex))

0 commit comments

Comments
 (0)