From 0cc939c9040d9c35865603cc6806deaf6205004e Mon Sep 17 00:00:00 2001 From: Brian Waldon Date: Thu, 16 Feb 2012 09:05:17 -0800 Subject: [PATCH] Display token and service catalog for user * Adds commands 'token', 'catalog' and 'endpoint-get' to keystone CLI * Fixes bug 930421 Change-Id: I9eceea3bf98a5c87b122fa663c96f7119ef8d3cc --- keystoneclient/service_catalog.py | 29 +++++++++++++++++++-- keystoneclient/v2_0/client.py | 2 +- keystoneclient/v2_0/shell.py | 42 +++++++++++++++++++++++++++++++ tests/test_service_catalog.py | 21 ++++++++++++++++ 4 files changed, 91 insertions(+), 3 deletions(-) diff --git a/keystoneclient/service_catalog.py b/keystoneclient/service_catalog.py index 0e7cd88a4..91ac17032 100644 --- a/keystoneclient/service_catalog.py +++ b/keystoneclient/service_catalog.py @@ -27,7 +27,15 @@ class ServiceCatalog(object): self.catalog = resource_dict def get_token(self): - return self.catalog['token']['id'] + """Fetch token details fron service catalog""" + token = {'id': self.catalog['token']['id'], + 'expires': self.catalog['token']['expires']} + try: + token['tenant'] = self.catalog['token']['tenant']['id'] + except: + # just leave the tenant out if it doesn't exist + pass + return token def url_for(self, attr=None, filter_value=None, service_type='identity', endpoint_type='publicURL'): @@ -47,7 +55,24 @@ class ServiceCatalog(object): endpoints = service['endpoints'] for endpoint in endpoints: - if not filter_value or endpoint[attr] == filter_value: + if not filter_value or endpoint.get(attr) == filter_value: return endpoint[endpoint_type] raise exceptions.EndpointNotFound('Endpoint not found.') + + def get_endpoints(self, service_type=None, endpoint_type=None): + """Fetch and filter endpoints for the specified service(s) + + Returns endpoints for the specified service (or all) and + that contain the specified type (or all). + """ + sc = {} + for service in self.catalog.get('serviceCatalog', []): + if service_type and service_type != service['type']: + continue + sc[service['type']] = [] + for endpoint in service['endpoints']: + if endpoint_type and endpoint_type not in endpoint.keys(): + continue + sc[service['type']].append(endpoint) + return sc diff --git a/keystoneclient/v2_0/client.py b/keystoneclient/v2_0/client.py index 1cf018e70..3fd8f3a47 100644 --- a/keystoneclient/v2_0/client.py +++ b/keystoneclient/v2_0/client.py @@ -111,7 +111,7 @@ class Client(client.HTTPClient): """ Set the client's service catalog from the response data. """ self.service_catalog = service_catalog.ServiceCatalog(body) try: - self.auth_token = self.service_catalog.get_token() + self.auth_token = self.service_catalog.get_token()['id'] except KeyError: raise exceptions.AuthorizationFailure() diff --git a/keystoneclient/v2_0/shell.py b/keystoneclient/v2_0/shell.py index ff9804b37..7c8c65ba6 100755 --- a/keystoneclient/v2_0/shell.py +++ b/keystoneclient/v2_0/shell.py @@ -244,3 +244,45 @@ def do_ec2_delete_credentials(kc, args): print 'Deleted EC2 Credentials.' except: print 'Unable to delete EC2 Credentials.' + + +@utils.arg('--service', metavar='', + help='Service type to return', nargs='?', default=None) +def do_catalog(kc, args): + """List service catalog, possibly filtered by service""" + endpoints = kc.service_catalog.get_endpoints(service_type=args.service) + for (service, service_endpoints) in endpoints.iteritems(): + if len(service_endpoints) > 0: + print "Service: %s" % service + for ep in service_endpoints: + utils.print_dict(ep) + + +@utils.arg('--endpoint_type', metavar='', + help='Endpoint type to select', nargs='?', default='publicURL') +@utils.arg('--service', metavar='', + help='Service type to select', nargs='?', required=True) +@utils.arg('--attr', metavar='', + help='Attribute to match', nargs='?') +@utils.arg('--value', metavar='', + help='Value of attribute to match', nargs='?') +def do_endpoint_get(kc, args): + """Find endpoint filtered by a specific attribute or service type""" + kwargs = { + 'service_type': args.service, + 'endpoint_type': args.endpoint_type, + } + + if args.attr and args.value: + kwargs.update({'attr': args.attr, 'filter_value': args.value}) + elif args.attr or args.value: + print 'Both --attr and --value required.' + return + + url = kc.service_catalog.url_for(**kwargs) + utils.print_dict({'%s.%s' % (args.service, args.endpoint_type): url}) + + +def do_token(kc, args): + """Fetch the current user's token""" + utils.print_dict(kc.service_catalog.get_token()) diff --git a/tests/test_service_catalog.py b/tests/test_service_catalog.py index 6207a5028..cba2164db 100644 --- a/tests/test_service_catalog.py +++ b/tests/test_service_catalog.py @@ -107,3 +107,24 @@ class ServiceCatalogTest(utils.TestCase): self.assertRaises(exceptions.EndpointNotFound, sc.url_for, "region", "South", service_type='compute') + + def test_service_catalog_endpoints(self): + sc = service_catalog.ServiceCatalog(SERVICE_CATALOG['access']) + public_ep = sc.get_endpoints(service_type='compute', + endpoint_type='publicURL') + self.assertEquals(public_ep['compute'][1]['tenantId'], '2') + self.assertEquals(public_ep['compute'][1]['versionId'], '1.1') + self.assertEquals(public_ep['compute'][1]['internalURL'], + "https://compute.north.host/v1.1/3456") + + def test_token(self): + sc = service_catalog.ServiceCatalog(SERVICE_CATALOG['access']) + + self.assertEquals(sc.get_token(), + {'id': 'ab48a9efdfedb23ty3494', + 'tenant': '345', + 'expires': '2010-11-01T03:32:15-05:00'}) + self.assertEquals(sc.catalog['token']['expires'], + "2010-11-01T03:32:15-05:00") + self.assertEquals(sc.catalog['token']['tenant']['id'], + '345')