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