More identity client config

* move auth option checking back to OpenStackShell() to keep the shell-level
  interaction at that level; add checking for token flow options

* make identity.client.make_client() configure keystoneclient.v2_0.Client()
  properly for both password flow and token flow auth

* eliminated ClientManager.init_token(), set _service_catalog in __init__()

* compute client handles token flow

Change-Id: I42481b5424489387798c4ec6d3e2a723ab1e6067
This commit is contained in:
Dean Troyer 2012-05-09 17:15:43 -05:00
parent a7da2b8008
commit 6fb1a4e496
4 changed files with 68 additions and 47 deletions
openstackclient

@ -21,7 +21,6 @@ class ClientCache(object):
def __get__(self, instance, owner): def __get__(self, instance, owner):
# Tell the ClientManager to login to keystone # Tell the ClientManager to login to keystone
if self._handle is None: if self._handle is None:
instance.init_token()
self._handle = self.factory(instance) self._handle = self.factory(instance)
return self._handle return self._handle
@ -30,9 +29,7 @@ class ClientManager(object):
"""Manages access to API clients, including authentication. """Manages access to API clients, including authentication.
""" """
# Identity client is instantiated in init_token() identity = ClientCache(identity_client.make_client)
# otherwise we have a recursion problem
identity = None
compute = ClientCache(compute_client.make_client) compute = ClientCache(compute_client.make_client)
def __init__(self, token=None, url=None, def __init__(self, token=None, url=None,
@ -55,40 +52,16 @@ class ClientManager(object):
self._identity_api_version = identity_api_version self._identity_api_version = identity_api_version
self._compute_api_version = compute_api_version self._compute_api_version = compute_api_version
self._image_api_version = image_api_version self._image_api_version = image_api_version
self._service_catalog = None
def init_token(self): # Create the identity client
"""Return the auth token and endpoint. self.identity
"""
if self._token:
LOG.debug('using existing auth token')
return
LOG.debug('validating authentication options') if not self._url:
if not self._username: # Populate other password flow attributes
raise exc.CommandError( self._token = self.identity.auth_token
"You must provide a username via" self._service_catalog = self.identity.service_catalog
" either --os-username or env[OS_USERNAME]")
if not self._password:
raise exc.CommandError(
"You must provide a password via"
" either --os-password or env[OS_PASSWORD]")
if not (self._tenant_id or self._tenant_name):
raise exc.CommandError(
"You must provide a tenant_id via"
" either --os-tenant-id or via env[OS_TENANT_ID]")
if not self._auth_url:
raise exc.CommandError(
"You must provide an auth url via"
" either --os-auth-url or via env[OS_AUTH_URL]")
# Get an Identity client and keep a token and catalog
if not self.identity:
self.identity = identity_client.make_client(self)
self._token = self.identity.auth_token
self._service_catalog = self.identity.service_catalog
return return
def get_endpoint_for_service_type(self, service_type): def get_endpoint_for_service_type(self, service_type):

@ -28,8 +28,13 @@ def make_client(instance):
) )
# Populate the Nova client to skip another auth query to Identity # Populate the Nova client to skip another auth query to Identity
client.client.management_url = instance.get_endpoint_for_service_type( if instance._url:
'compute') # token flow
client.client.service_catalog = instance._service_catalog client.client.management_url = instance._url
else:
# password flow
client.client.management_url = instance.get_endpoint_for_service_type(
'compute')
client.client.service_catalog = instance._service_catalog
client.client.auth_token = instance._token client.client.auth_token = instance._token
return client return client

@ -8,13 +8,20 @@ LOG = logging.getLogger(__name__)
def make_client(instance): def make_client(instance):
"""Returns an identity service client. """Returns an identity service client.
""" """
LOG.debug('instantiating identity client') if instance._url:
client = identity_client.Client( LOG.debug('instantiating identity client: token flow')
username=instance._username, client = identity_client.Client(
password=instance._password, endpoint=instance._url,
tenant_name=instance._tenant_name, token=instance._token,
tenant_id=instance._tenant_id, )
auth_url=instance._auth_url, else:
region_name=instance._region_name, LOG.debug('instantiating identity client: password flow')
) client = identity_client.Client(
username=instance._username,
password=instance._password,
tenant_name=instance._tenant_name,
tenant_id=instance._tenant_id,
auth_url=instance._auth_url,
region_name=instance._region_name,
)
return client return client

@ -27,6 +27,7 @@ from cliff.app import App
from cliff.commandmanager import CommandManager from cliff.commandmanager import CommandManager
from openstackclient.common import clientmanager from openstackclient.common import clientmanager
from openstackclient.common import exceptions as exc
from openstackclient.common import utils from openstackclient.common import utils
@ -141,6 +142,41 @@ class OpenStackShell(App):
'image': self.options.os_image_api_version, 'image': self.options.os_image_api_version,
} }
self.log.debug('validating authentication options')
if self.options.os_token or self.options.os_url:
# Token flow auth takes priority
if not self.options.os_token:
raise exc.CommandError(
"You must provide a token via"
" either --os-token or env[OS_TOKEN]")
if not self.options.os_url:
raise exc.CommandError(
"You must provide a service URL via"
" either --os-url or env[OS_URL]")
else:
# Validate password flow auth
if not self.options.os_username:
raise exc.CommandError(
"You must provide a username via"
" either --os-username or env[OS_USERNAME]")
if not self.options.os_password:
raise exc.CommandError(
"You must provide a password via"
" either --os-password or env[OS_PASSWORD]")
if not (self.options.os_tenant_id or self.options.os_tenant_name):
raise exc.CommandError(
"You must provide a tenant_id via"
" either --os-tenant-id or via env[OS_TENANT_ID]")
if not self.options.os_auth_url:
raise exc.CommandError(
"You must provide an auth url via"
" either --os-auth-url or via env[OS_AUTH_URL]")
self.client_manager = clientmanager.ClientManager( self.client_manager = clientmanager.ClientManager(
token=self.options.os_token, token=self.options.os_token,
url=self.options.os_url, url=self.options.os_url,