Skip to content

Commit f350a98

Browse files
Merge pull request #1132 from FernandoOjeda/fo_object_storage_credentials
Fix object storage credentials.
2 parents 9d6bf59 + 665ad1d commit f350a98

File tree

10 files changed

+373
-0
lines changed

10 files changed

+373
-0
lines changed
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
"""Manages Object Storage S3 Credentials."""
2+
# :license: MIT, see LICENSE for more details.
3+
4+
import importlib
5+
import os
6+
7+
import click
8+
9+
CONTEXT = {'help_option_names': ['-h', '--help'],
10+
'max_content_width': 999}
11+
12+
13+
class CapacityCommands(click.MultiCommand):
14+
"""Loads module for object storage S3 credentials related commands."""
15+
16+
def __init__(self, **attrs):
17+
click.MultiCommand.__init__(self, **attrs)
18+
self.path = os.path.dirname(__file__)
19+
20+
def list_commands(self, ctx):
21+
"""List all sub-commands."""
22+
commands = []
23+
for filename in os.listdir(self.path):
24+
if filename == '__init__.py':
25+
continue
26+
if filename.endswith('.py'):
27+
commands.append(filename[:-3].replace("_", "-"))
28+
commands.sort()
29+
return commands
30+
31+
def get_command(self, ctx, cmd_name):
32+
"""Get command for click."""
33+
path = "%s.%s" % (__name__, cmd_name)
34+
path = path.replace("-", "_")
35+
module = importlib.import_module(path)
36+
return getattr(module, 'cli')
37+
38+
39+
# Required to get the sub-sub-sub command to work.
40+
@click.group(cls=CapacityCommands, context_settings=CONTEXT)
41+
def cli():
42+
"""Base command for all object storage credentials S3 related concerns"""
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
"""Create credentials for an IBM Cloud Object Storage Account."""
2+
# :license: MIT, see LICENSE for more details.
3+
4+
import click
5+
6+
import SoftLayer
7+
from SoftLayer.CLI import environment
8+
from SoftLayer.CLI import formatting
9+
10+
11+
@click.command()
12+
@click.argument('identifier')
13+
@environment.pass_env
14+
def cli(env, identifier):
15+
"""Create credentials for an IBM Cloud Object Storage Account"""
16+
17+
mgr = SoftLayer.ObjectStorageManager(env.client)
18+
credential = mgr.create_credential(identifier)
19+
table = formatting.Table(['id', 'password', 'username', 'type_name'])
20+
table.sortby = 'id'
21+
table.add_row([
22+
credential['id'],
23+
credential['password'],
24+
credential['username'],
25+
credential['type']['name']
26+
])
27+
28+
env.fout(table)
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
"""Delete the credential of an Object Storage Account."""
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.argument('identifier')
12+
@click.option('--credential_id', '-c', type=click.INT,
13+
help="This is the credential id associated with the volume")
14+
@environment.pass_env
15+
def cli(env, identifier, credential_id):
16+
"""Delete the credential of an Object Storage Account."""
17+
18+
mgr = SoftLayer.ObjectStorageManager(env.client)
19+
credential = mgr.delete_credential(identifier, credential_id=credential_id)
20+
21+
env.fout(credential)
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
""" Credential limits for this IBM Cloud Object Storage account."""
2+
# :license: MIT, see LICENSE for more details.
3+
4+
import click
5+
6+
import SoftLayer
7+
from SoftLayer.CLI import environment
8+
from SoftLayer.CLI import formatting
9+
10+
11+
@click.command()
12+
@click.argument('identifier')
13+
@environment.pass_env
14+
def cli(env, identifier):
15+
"""Credential limits for this IBM Cloud Object Storage account."""
16+
17+
mgr = SoftLayer.ObjectStorageManager(env.client)
18+
credential_limit = mgr.limit_credential(identifier)
19+
table = formatting.Table(['limit'])
20+
table.add_row([
21+
credential_limit,
22+
])
23+
24+
env.fout(table)
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
"""Retrieve credentials used for generating an AWS signature. Max of 2."""
2+
# :license: MIT, see LICENSE for more details.
3+
4+
import click
5+
6+
import SoftLayer
7+
from SoftLayer.CLI import environment
8+
from SoftLayer.CLI import formatting
9+
10+
11+
@click.command()
12+
@click.argument('identifier')
13+
@environment.pass_env
14+
def cli(env, identifier):
15+
"""Retrieve credentials used for generating an AWS signature. Max of 2."""
16+
17+
mgr = SoftLayer.ObjectStorageManager(env.client)
18+
credential_list = mgr.list_credential(identifier)
19+
table = formatting.Table(['id', 'password', 'username', 'type_name'])
20+
21+
for credential in credential_list:
22+
table.add_row([
23+
credential['id'],
24+
credential['password'],
25+
credential['username'],
26+
credential['type']['name']
27+
])
28+
29+
env.fout(table)

SoftLayer/CLI/routes.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,8 @@
199199
'SoftLayer.CLI.object_storage.list_accounts:cli'),
200200
('object-storage:endpoints',
201201
'SoftLayer.CLI.object_storage.list_endpoints:cli'),
202+
('object-storage:credential',
203+
'SoftLayer.CLI.object_storage.credential:cli'),
202204

203205
('order', 'SoftLayer.CLI.order'),
204206
('order:category-list', 'SoftLayer.CLI.order.category_list:cli'),
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
credentialCreate = {
2+
"accountId": "12345",
3+
"createDate": "2019-04-05T13:25:25-06:00",
4+
"id": 11111,
5+
"password": "nwUEUsx6PiEoN0B1Xe9z9hUCyXMkAFhDOjHqYJva",
6+
"username": "XfHhBNBPlPdlWyaPPJAI",
7+
"type": {
8+
"description": "A credential for generating S3 Compatible Signatures.",
9+
"keyName": "S3_COMPATIBLE_SIGNATURE",
10+
"name": "S3 Compatible Signature"
11+
}
12+
}
13+
14+
getCredentials = [
15+
{
16+
"accountId": "12345",
17+
"createDate": "2019-04-05T13:25:25-06:00",
18+
"id": 11111,
19+
"password": "nwUEUsx6PiEoN0B1Xe9z9hUCyXMkAFhDOjHqYJva",
20+
"username": "XfHhBNBPlPdlWyaPPJAI",
21+
"type": {
22+
"description": "A credential for generating S3 Compatible Signatures.",
23+
"keyName": "S3_COMPATIBLE_SIGNATURE",
24+
"name": "S3 Compatible Signature"
25+
}
26+
},
27+
{
28+
"accountId": "12345",
29+
"createDate": "2019-04-05T13:25:25-06:00",
30+
"id": 11111,
31+
"password": "nwUEUsx6PiEoN0B1Xe9z9hUCyXMkAFhDOjHqYJva",
32+
"username": "XfHhBNBPlPdlWyaPPJAI",
33+
"type": {
34+
"description": "A credential for generating S3 Compatible Signatures.",
35+
"keyName": "S3_COMPATIBLE_SIGNATURE",
36+
"name": "S3 Compatible Signature"
37+
}
38+
}
39+
]

SoftLayer/managers/object_storage.py

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,3 +52,47 @@ def list_endpoints(self):
5252
})
5353

5454
return endpoints
55+
56+
def create_credential(self, identifier):
57+
"""Create object storage credential.
58+
59+
:param int identifier: The object storage account identifier.
60+
61+
"""
62+
63+
return self.client.call('SoftLayer_Network_Storage_Hub_Cleversafe_Account', 'credentialCreate',
64+
id=identifier)
65+
66+
def delete_credential(self, identifier, credential_id=None):
67+
"""Delete the object storage credential.
68+
69+
:param int id: The object storage account identifier.
70+
:param int credential_id: The credential id to be deleted.
71+
72+
"""
73+
credential = {
74+
'id': credential_id
75+
}
76+
77+
return self.client.call('SoftLayer_Network_Storage_Hub_Cleversafe_Account', 'credentialDelete',
78+
credential, id=identifier)
79+
80+
def limit_credential(self, identifier):
81+
"""Limit object storage credentials.
82+
83+
:param int identifier: The object storage account identifier.
84+
85+
"""
86+
87+
return self.client.call('SoftLayer_Network_Storage_Hub_Cleversafe_Account', 'getCredentialLimit',
88+
id=identifier)
89+
90+
def list_credential(self, identifier):
91+
"""List the object storage credentials.
92+
93+
:param int identifier: The object storage account identifier.
94+
95+
"""
96+
97+
return self.client.call('SoftLayer_Network_Storage_Hub_Cleversafe_Account', 'getCredentials',
98+
id=identifier)

tests/CLI/modules/object_storage_tests.py

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,3 +37,70 @@ def test_list_endpoints(self):
3737
[{'datacenter': 'dal05',
3838
'private': 'https://dal05/auth/v1.0/',
3939
'public': 'https://dal05/auth/v1.0/'}])
40+
41+
def test_create_credential(self):
42+
accounts = self.set_mock('SoftLayer_Network_Storage_Hub_Cleversafe_Account', 'credentialCreate')
43+
accounts.return_value = {
44+
"accountId": "12345",
45+
"createDate": "2019-04-05T13:25:25-06:00",
46+
"id": 11111,
47+
"password": "nwUEUsx6PiEoN0B1Xe9z9hUCy",
48+
"username": "XfHhBNBPlPdl",
49+
"type": {
50+
"description": "A credential for generating S3 Compatible Signatures.",
51+
"keyName": "S3_COMPATIBLE_SIGNATURE",
52+
"name": "S3 Compatible Signature"
53+
}
54+
}
55+
56+
result = self.run_command(['object-storage', 'credential', 'create', '100'])
57+
58+
self.assert_no_fail(result)
59+
self.assertEqual(json.loads(result.output),
60+
[{'id': 11111,
61+
'password': 'nwUEUsx6PiEoN0B1Xe9z9hUCy',
62+
'type_name': 'S3 Compatible Signature',
63+
'username': 'XfHhBNBPlPdl'}]
64+
)
65+
66+
def test_delete_credential(self):
67+
accounts = self.set_mock('SoftLayer_Network_Storage_Hub_Cleversafe_Account', 'credentialDelete')
68+
accounts.return_value = True
69+
70+
result = self.run_command(['object-storage', 'credential', 'delete', '-c', 100, '100'])
71+
72+
self.assert_no_fail(result)
73+
self.assertEqual(result.output, 'True\n')
74+
75+
def test_limit_credential(self):
76+
accounts = self.set_mock('SoftLayer_Network_Storage_Hub_Cleversafe_Account', 'getCredentialLimit')
77+
accounts.return_value = 2
78+
79+
result = self.run_command(['object-storage', 'credential', 'limit', '100'])
80+
81+
self.assert_no_fail(result)
82+
self.assertEqual(json.loads(result.output), [{'limit': 2}])
83+
84+
def test_list_credential(self):
85+
accounts = self.set_mock('SoftLayer_Network_Storage_Hub_Cleversafe_Account', 'getCredentials')
86+
accounts.return_value = [{'id': 1103123,
87+
'password': 'nwUEUsx6PiEoN0B1Xe9z9hUCyXM',
88+
'type': {'name': 'S3 Compatible Signature'},
89+
'username': 'XfHhBNBPlPdlWya'},
90+
{'id': 1103333,
91+
'password': 'nwUEUsx6PiEoN0B1Xe9z9',
92+
'type': {'name': 'S3 Compatible Signature'},
93+
'username': 'XfHhBNBPlPd'}]
94+
95+
result = self.run_command(['object-storage', 'credential', 'list', '100'])
96+
97+
self.assert_no_fail(result)
98+
self.assertEqual(json.loads(result.output),
99+
[{'id': 1103123,
100+
'password': 'nwUEUsx6PiEoN0B1Xe9z9hUCyXM',
101+
'type_name': 'S3 Compatible Signature',
102+
'username': 'XfHhBNBPlPdlWya'},
103+
{'id': 1103333,
104+
'password': 'nwUEUsx6PiEoN0B1Xe9z9',
105+
'type_name': 'S3 Compatible Signature',
106+
'username': 'XfHhBNBPlPd'}])

tests/managers/object_storage_tests.py

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,3 +42,80 @@ def test_list_endpoints_no_results(self):
4242
endpoints = self.object_storage.list_endpoints()
4343
self.assertEqual(endpoints,
4444
[])
45+
46+
def test_create_credential(self):
47+
accounts = self.set_mock('SoftLayer_Network_Storage_Hub_Cleversafe_Account', 'credentialCreate')
48+
accounts.return_value = {
49+
"id": 1103123,
50+
"password": "nwUEUsx6PiEoN0B1Xe9z9hUCyXMkAF",
51+
"username": "XfHhBNBPlPdlWyaP",
52+
"type": {
53+
"name": "S3 Compatible Signature"
54+
}
55+
}
56+
credential = self.object_storage.create_credential(100)
57+
self.assertEqual(credential,
58+
{
59+
"id": 1103123,
60+
"password": "nwUEUsx6PiEoN0B1Xe9z9hUCyXMkAF",
61+
"username": "XfHhBNBPlPdlWyaP",
62+
"type": {
63+
"name": "S3 Compatible Signature"
64+
}
65+
})
66+
67+
def test_delete_credential(self):
68+
accounts = self.set_mock('SoftLayer_Network_Storage_Hub_Cleversafe_Account', 'credentialDelete')
69+
accounts.return_value = True
70+
71+
credential = self.object_storage.delete_credential(100)
72+
self.assertEqual(credential, True)
73+
74+
def test_limit_credential(self):
75+
accounts = self.set_mock('SoftLayer_Network_Storage_Hub_Cleversafe_Account', 'getCredentialLimit')
76+
accounts.return_value = 2
77+
78+
credential = self.object_storage.limit_credential(100)
79+
self.assertEqual(credential, 2)
80+
81+
def test_list_credential(self):
82+
accounts = self.set_mock('SoftLayer_Network_Storage_Hub_Cleversafe_Account', 'getCredentials')
83+
accounts.return_value = [
84+
{
85+
"id": 1103123,
86+
"password": "nwUEUsx6PiEoN0B1Xe9z9hUCyXsf4sf",
87+
"username": "XfHhBNBPlPdlWyaP3fsd",
88+
"type": {
89+
"name": "S3 Compatible Signature"
90+
}
91+
},
92+
{
93+
"id": 1102341,
94+
"password": "nwUEUsx6PiEoN0B1Xe9z9hUCyXMkAF",
95+
"username": "XfHhBNBPlPdlWyaP",
96+
"type": {
97+
"name": "S3 Compatible Signature"
98+
}
99+
}
100+
]
101+
credential = self.object_storage.list_credential(100)
102+
self.assertEqual(credential,
103+
[
104+
{
105+
"id": 1103123,
106+
"password": "nwUEUsx6PiEoN0B1Xe9z9hUCyXsf4sf",
107+
"username": "XfHhBNBPlPdlWyaP3fsd",
108+
"type": {
109+
"name": "S3 Compatible Signature"
110+
}
111+
},
112+
{
113+
"id": 1102341,
114+
"password": "nwUEUsx6PiEoN0B1Xe9z9hUCyXMkAF",
115+
"username": "XfHhBNBPlPdlWyaP",
116+
"type": {
117+
"name": "S3 Compatible Signature"
118+
}
119+
}
120+
]
121+
)

0 commit comments

Comments
 (0)