diff --git a/keystoneclient/service_catalog.py b/keystoneclient/service_catalog.py index faff74bfe..5f20e0f38 100644 --- a/keystoneclient/service_catalog.py +++ b/keystoneclient/service_catalog.py @@ -27,7 +27,16 @@ class ServiceCatalog(object): self.catalog = resource_dict def get_token(self): - """Fetch token details fron service catalog""" + """Fetch token details fron service catalog. + + Returns a dictionary containing the following:: + + - `id`: Token's ID + - `expires`: Token's expiration + - `user_id`: Authenticated user's ID + - `tenant_id`: Authorized project's ID + + """ token = {'id': self.catalog['token']['id'], 'expires': self.catalog['token']['expires']} try: @@ -46,6 +55,8 @@ class ServiceCatalog(object): a particular endpoint attribute. If no attribute is given, return the first endpoint of the specified type. + Valid endpoint types: `publicURL`, `internalURL`, `adminURL` + See tests for a sample service catalog. """ catalog = self.catalog.get('serviceCatalog', []) @@ -62,7 +73,7 @@ class ServiceCatalog(object): 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) + """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). diff --git a/keystoneclient/v2_0/client.py b/keystoneclient/v2_0/client.py index ffd0c2c03..130887235 100644 --- a/keystoneclient/v2_0/client.py +++ b/keystoneclient/v2_0/client.py @@ -76,10 +76,13 @@ class Client(client.HTTPClient): # extensions self.ec2 = ec2.CredentialsManager(self) + self.management_url = endpoint if endpoint is None: self.authenticate() - else: - self.management_url = endpoint + + def has_service_catalog(self): + """Returns True if this client provides a service catalog.""" + return hasattr(self, 'service_catalog') def authenticate(self): """ Authenticate against the Keystone API. diff --git a/keystoneclient/v2_0/shell.py b/keystoneclient/v2_0/shell.py index 522f98b86..98b3b51ed 100755 --- a/keystoneclient/v2_0/shell.py +++ b/keystoneclient/v2_0/shell.py @@ -20,9 +20,23 @@ import argparse from keystoneclient.v2_0 import client from keystoneclient import utils + CLIENT_CLASS = client.Client +def require_service_catalog(f): + msg = ('Configuration error: Client configured to run without a service ' + 'catalog. Run the client using --os-auth-url or OS_AUTH_URL, ' + 'instead of --os-endpoint or OS_SERVICE_ENDPOINT, for example.') + + def wrapped(kc, args): + if not kc.has_service_catalog(): + raise Exception(msg) + return f(kc, args) + + return wrapped + + @utils.arg('--tenant-id', metavar='', help='Tenant ID; lists all users if not specified') @utils.arg('--tenant_id', help=argparse.SUPPRESS) @@ -332,6 +346,7 @@ def do_ec2_credentials_delete(kc, args): @utils.arg('--service', metavar='', default=None, help='Service type to return') +@require_service_catalog def do_catalog(kc, args): """List service catalog, possibly filtered by service.""" endpoints = kc.service_catalog.get_endpoints(service_type=args.service) @@ -352,6 +367,7 @@ def do_catalog(kc, args): help='Service attribute to match for selection') @utils.arg('--value', metavar='', help='Value of attribute to match') +@require_service_catalog def do_endpoint_get(kc, args): """Find endpoint filtered by a specific attribute or service type""" kwargs = { @@ -408,6 +424,7 @@ def do_endpoint_delete(kc, args): @utils.arg('--wrap', metavar='', default=0, help='wrap PKI tokens to a specified length, or 0 to disable') +@require_service_catalog def do_token_get(kc, args): """Display the current user token""" utils.print_dict(kc.service_catalog.get_token(),