Revision b173906e
b/astakosclient/astakosclient/__init__.py | ||
---|---|---|
56 | 56 |
|
57 | 57 |
# -------------------------------------------------------------------- |
58 | 58 |
# Astakos API urls |
59 |
UI_PREFIX = get_path(astakos_services, 'astakos_ui.prefix') |
|
59 | 60 |
ACCOUNTS_PREFIX = get_path(astakos_services, 'astakos_account.prefix') |
60 | 61 |
ACCOUNTS_PREFIX = join_urls(ACCOUNTS_PREFIX, 'v1.0') |
61 | 62 |
API_AUTHENTICATE = join_urls(ACCOUNTS_PREFIX, "authenticate") |
62 | 63 |
API_USERCATALOGS = join_urls(ACCOUNTS_PREFIX, "user_catalogs") |
63 | 64 |
API_SERVICE_USERCATALOGS = join_urls(ACCOUNTS_PREFIX, "service/user_catalogs") |
64 |
API_GETSERVICES = join_urls(ACCOUNTS_PREFIX, "get_services")
|
|
65 |
API_GETSERVICES = join_urls(UI_PREFIX, "get_services")
|
|
65 | 66 |
API_RESOURCES = join_urls(ACCOUNTS_PREFIX, "resources") |
66 | 67 |
API_QUOTAS = join_urls(ACCOUNTS_PREFIX, "quotas") |
67 | 68 |
API_SERVICE_QUOTAS = join_urls(ACCOUNTS_PREFIX, "service_quotas") |
... | ... | |
72 | 73 |
# -------------------------------------------------------------------- |
73 | 74 |
# Astakos Keystone API urls |
74 | 75 |
IDENTITY_PREFIX = get_path(astakos_services, 'astakos_identity.prefix') |
76 |
IDENTITY_PREFIX = join_urls(IDENTITY_PREFIX, "v2.0") |
|
75 | 77 |
API_TOKENS = join_urls(IDENTITY_PREFIX, "tokens") |
76 |
TOKENS_ENDPOINTS = join_urls(API_TOKENS, "endpoints") |
|
77 | 78 |
|
78 | 79 |
|
79 | 80 |
# -------------------------------------------------------------------- |
... | ... | |
362 | 363 |
self._call_astakos(token, path, None, req_body, "POST") |
363 | 364 |
|
364 | 365 |
# ---------------------------------- |
365 |
# do a GET to ``API_TOKENS``/<user_token>/``TOKENS_ENDPOINTS`` |
|
366 |
def get_endpoints(self, token, belongs_to=None, marker=None, limit=None): |
|
367 |
"""Request registered endpoints from astakos |
|
368 |
|
|
369 |
keyword arguments: |
|
370 |
token -- user's token (string) |
|
371 |
belongs_to -- user's uuid (string) |
|
372 |
marker -- return endpoints whose ID is higher than marker's (int) |
|
373 |
limit -- maximum number of endpoints to return (int) |
|
374 |
|
|
375 |
Return a json formatted dictionary containing information |
|
376 |
about registered endpoints. |
|
377 |
|
|
378 |
WARNING: This api call encodes the user's token inside the url. |
|
379 |
It's thoughs security unsafe to use it (both astakosclient and |
|
380 |
nginx tend to log requested urls). |
|
381 |
Avoid the use of get_endpoints method and use |
|
382 |
get_user_info_with_endpoints instead. |
|
383 |
|
|
384 |
""" |
|
385 |
params = {} |
|
386 |
if belongs_to is not None: |
|
387 |
params['belongsTo'] = str(belongs_to) |
|
388 |
if marker is not None: |
|
389 |
params['marker'] = str(marker) |
|
390 |
if limit is not None: |
|
391 |
params['limit'] = str(limit) |
|
392 |
path = API_TOKENS + "/" + token + "/" + \ |
|
393 |
TOKENS_ENDPOINTS + "?" + urllib.urlencode(params) |
|
394 |
return self._call_astakos(token, path) |
|
395 |
|
|
396 |
# ---------------------------------- |
|
397 | 366 |
# do a POST to ``API_TOKENS`` |
398 |
def get_user_info_with_endpoints(self, token, uuid=None):
|
|
367 |
def get_endpoints(self, token, uuid=None): |
|
399 | 368 |
""" Fallback call for authenticate |
400 | 369 |
|
401 | 370 |
Keyword arguments: |
b/astakosclient/astakosclient/tests.py | ||
---|---|---|
40 | 40 |
|
41 | 41 |
""" |
42 | 42 |
|
43 |
import re |
|
43 | 44 |
import sys |
44 | 45 |
import socket |
45 | 46 |
import simplejson |
... | ... | |
116 | 117 |
|
117 | 118 |
def _request_ok(conn, method, url, **kwargs): |
118 | 119 |
"""This request behaves like original Astakos does""" |
119 |
if url.startswith(astakosclient.API_AUTHENTICATE): |
|
120 |
if re.match('/?' + astakosclient.API_AUTHENTICATE, url) is not None: |
|
121 |
print "here 1" |
|
120 | 122 |
return _req_authenticate(conn, method, url, **kwargs) |
121 |
elif url.startswith(astakosclient.API_USERCATALOGS): |
|
123 |
elif re.match('/?' + astakosclient.API_USERCATALOGS, url) is not None: |
|
124 |
print "here 2" |
|
122 | 125 |
return _req_catalogs(conn, method, url, **kwargs) |
123 |
elif url.startswith(astakosclient.API_RESOURCES): |
|
126 |
elif re.match('/?' + astakosclient.API_RESOURCES, url) is not None: |
|
127 |
print "here 3" |
|
124 | 128 |
return _req_resources(conn, method, url, **kwargs) |
125 |
elif url.startswith(astakosclient.API_QUOTAS):
|
|
129 |
elif re.match('/?' + astakosclient.API_QUOTAS, url) is not None:
|
|
126 | 130 |
return _req_quotas(conn, method, url, **kwargs) |
127 |
elif url.startswith(astakosclient.API_COMMISSIONS):
|
|
131 |
elif re.match('/?' + astakosclient.API_COMMISSIONS, url) is not None:
|
|
128 | 132 |
return _req_commission(conn, method, url, **kwargs) |
129 |
elif url.startswith(astakosclient.API_TOKENS):
|
|
133 |
elif re.match('/?' + astakosclient.API_TOKENS, url) is not None:
|
|
130 | 134 |
return _req_endpoints(conn, method, url, **kwargs) |
131 | 135 |
else: |
136 |
print "here 4" |
|
132 | 137 |
return _request_status_404(conn, method, url, **kwargs) |
133 | 138 |
|
134 | 139 |
|
... | ... | |
242 | 247 |
if 'body' not in kwargs: |
243 | 248 |
return _request_status_400(conn, method, url, **kwargs) |
244 | 249 |
body = simplejson.loads(unicode(kwargs['body'])) |
245 |
if url == astakosclient.API_COMMISSIONS:
|
|
250 |
if re.match('/?'+astakosclient.API_COMMISSIONS+'$', url) is not None:
|
|
246 | 251 |
# Issue Commission |
247 | 252 |
# Check if we have enough resources to give |
248 | 253 |
if body['provisions'][1]['quantity'] > 420000000: |
... | ... | |
270 | 275 |
return ("", "", 200) |
271 | 276 |
|
272 | 277 |
elif method == "GET": |
273 |
if url == astakosclient.API_COMMISSIONS:
|
|
278 |
if re.match('/?'+astakosclient.API_COMMISSIONS+'$', url) is not None:
|
|
274 | 279 |
# Return pending commission |
275 | 280 |
return ("", simplejson.dumps(pending_commissions), 200) |
276 | 281 |
else: |
277 | 282 |
# Return commissions's description |
278 |
serial = url[25:]
|
|
283 |
serial = re.sub('/?' + astakosclient.API_COMMISSIONS, '', url)[1:]
|
|
279 | 284 |
if serial == str(57): |
280 | 285 |
return ("", simplejson.dumps(commission_description), 200) |
281 | 286 |
else: |
... | ... | |
291 | 296 |
# Check input |
292 | 297 |
if conn.__class__.__name__ != "HTTPSConnection": |
293 | 298 |
return _request_status_302(conn, method, url, **kwargs) |
299 |
if method != "POST": |
|
300 |
return _request_status_400(conn, method, url, **kwargs) |
|
294 | 301 |
|
295 | 302 |
token_head = kwargs['headers'].get('X-Auth-Token') |
296 |
if url == astakosclient.API_TOKENS: |
|
297 |
if method != "POST": |
|
298 |
return _request_status_400(conn, method, url, **kwargs) |
|
299 |
body = simplejson.loads(kwargs['body']) |
|
300 |
token = body['auth']['token']['id'] |
|
301 |
if token != token_1: |
|
302 |
return _request_status_401(conn, method, url, **kwargs) |
|
303 |
# Return |
|
304 |
return ("", simplejson.dumps(user_info_endpoints), 200) |
|
305 |
|
|
306 |
else: |
|
307 |
if method != "GET": |
|
308 |
return _request_status_400(conn, method, url, **kwargs) |
|
309 |
url_split = url[len(astakosclient.API_TOKENS):].split('/') |
|
310 |
token_url = url_split[1] |
|
311 |
if token_head != token_url: |
|
312 |
return _request_status_403(conn, method, url, **kwargs) |
|
313 |
if token_url != token_1: |
|
314 |
return _request_status_401(conn, method, url, **kwargs) |
|
315 |
# Return |
|
316 |
return ("", simplejson.dumps(endpoints), 200) |
|
303 |
if method != "POST": |
|
304 |
return _request_status_400(conn, method, url, **kwargs) |
|
305 |
body = simplejson.loads(kwargs['body']) |
|
306 |
token_body = body['auth']['token']['id'] |
|
307 |
if token_head != token_body: |
|
308 |
return _request_status_403(conn, method, url, **kwargs) |
|
309 |
if token_body != token_1: |
|
310 |
return _request_status_401(conn, method, url, **kwargs) |
|
311 |
# Return |
|
312 |
return ("", simplejson.dumps(user_info_endpoints), 200) |
|
317 | 313 |
|
318 | 314 |
|
319 | 315 |
# ---------------------------- |
... | ... | |
409 | 405 |
"description": "Virtual machine memory", |
410 | 406 |
"service": "cyclades"}} |
411 | 407 |
|
412 |
endpoints = { |
|
413 |
"endpoints": [ |
|
414 |
{"name": "cyclades", |
|
415 |
"region": "cyclades", |
|
416 |
"internalURL": "https://node1.example.com/ui/", |
|
417 |
"adminURL": "https://node1.example.com/v1/", |
|
418 |
"type": None, |
|
419 |
"id": 5, |
|
420 |
"publicURL": "https://node1.example.com/ui/"}, |
|
421 |
{"name": "pithos", |
|
422 |
"region": "pithos", |
|
423 |
"internalURL": "https://node2.example.com/ui/", |
|
424 |
"adminURL": "https://node2.example.com/v1", |
|
425 |
"type": None, |
|
426 |
"id": 6, |
|
427 |
"publicURL": "https://node2.example.com/ui/"}], |
|
428 |
"endpoint_links": [ |
|
429 |
{"href": "/astakos/api/tokens/0000/endpoints?marker=4&limit=10000", |
|
430 |
"rel": "next"}]} |
|
431 |
|
|
432 | 408 |
user_info_endpoints = \ |
433 | 409 |
{'serviceCatalog': [ |
434 | 410 |
{'endpoints': [{ |
... | ... | |
1178 | 1154 |
# ---------------------------------- |
1179 | 1155 |
def test_get_endpoints(self): |
1180 | 1156 |
"""Test function call of get_endpoints""" |
1181 |
global token_1, endpoints |
|
1182 |
_mock_request([_request_ok]) |
|
1183 |
try: |
|
1184 |
client = AstakosClient("https://example.com") |
|
1185 |
response = client.get_endpoints(token_1) |
|
1186 |
except Exception as err: |
|
1187 |
self.fail("Shouldn't raise Exception %s" % err) |
|
1188 |
self.assertEqual(response, endpoints) |
|
1189 |
|
|
1190 |
# ---------------------------------- |
|
1191 |
def test_get_endpoints_wrong_token(self): |
|
1192 |
"""Test function call of get_endpoints with wrong token""" |
|
1193 |
global token_2, endpoints |
|
1194 |
_mock_request([_request_ok]) |
|
1195 |
try: |
|
1196 |
client = AstakosClient("https://example.com") |
|
1197 |
client.get_endpoints(token_2, marker=2, limit=100) |
|
1198 |
except Unauthorized: |
|
1199 |
pass |
|
1200 |
except Exception as err: |
|
1201 |
self.fail("Shouldn't raise Exception %s" % err) |
|
1202 |
else: |
|
1203 |
self.fail("Should have raised Unauthorized Exception") |
|
1204 |
|
|
1205 |
# ---------------------------------- |
|
1206 |
def test_get_user_info_with_endpoints(self): |
|
1207 |
"""Test function call of get_user_info_with_endpoints""" |
|
1208 | 1157 |
global token_1, user_info_endpoints |
1209 | 1158 |
_mock_request([_request_ok]) |
1210 | 1159 |
try: |
1211 | 1160 |
client = AstakosClient("https://example.com") |
1212 |
response = client.get_user_info_with_endpoints(token_1)
|
|
1161 |
response = client.get_endpoints(token_1) |
|
1213 | 1162 |
except Exception as err: |
1214 | 1163 |
self.fail("Shouldn't raise Exception %s" % err) |
1215 | 1164 |
self.assertEqual(response, user_info_endpoints) |
b/astakosclient/docs/index.rst | ||
---|---|---|
129 | 129 |
In case of success returns nothing. |
130 | 130 |
Otherwise raise an AstakosClientException exception. |
131 | 131 |
|
132 |
**get_endpoints(**\ token, belongs_to, marker, limit\ **)** |
|
133 |
Given a user's authentication token, request registered |
|
134 |
endpoints from astakos service. If belongs_to is given (uuid) |
|
135 |
check that the token belongs to this user. If marker is given |
|
136 |
(int) return endpoints (ordered by ID) whose ID is higher than |
|
137 |
the marker. Limit (int) specifies the maximum number of |
|
138 |
endpoints to return. Return a json formatted dictionary containing |
|
139 |
information about registered endpoints. |
|
140 |
|
|
141 |
.. warning:: *get_endpoints* api call encodes the user's token inside |
|
142 |
the url. It's security unsafe to use it (both astakosclient |
|
143 |
and nginx tend to log requested urls). Use |
|
144 |
get_user_info_with_endpoints instead. |
|
145 |
|
|
146 |
**get_user_info_with_endpoints(**\ token, uuid=None\ **)** |
|
132 |
**get_endpoints(**\ token, uuid=None\ **)** |
|
147 | 133 |
Fallback call which receives the user token or the user uuid/token |
148 | 134 |
and returns back the token as well as information about the token |
149 | 135 |
holder and the services he/seh can access. |
Also available in: Unified diff