Add helpful messages when authN'ing with password

Setting up auth options can be complicated, and we currently don't
do any checking before we build all our auth parameters to send off
to keystoneclient. We should do some basic checking to guide new
users.

Change-Id: I9c88f1c9637b3870c151952ecc797aaf65be271a
Closes-Bug: #1400531
This commit is contained in:
Steve Martinelli 2015-01-16 02:20:52 -05:00
parent 77097c6cd4
commit fff4a1cd23
4 changed files with 31 additions and 4 deletions

View File

@ -24,6 +24,7 @@ from keystoneclient.auth import base
from openstackclient.common import exceptions as exc from openstackclient.common import exceptions as exc
from openstackclient.common import utils from openstackclient.common import utils
from openstackclient.i18n import _
LOG = logging.getLogger(__name__) LOG = logging.getLogger(__name__)
@ -122,6 +123,25 @@ def build_auth_params(auth_plugin_name, cmd_options):
return (auth_plugin_class, auth_params) return (auth_plugin_class, auth_params)
def check_valid_auth_options(options, auth_plugin_name):
"""Perform basic option checking, provide helpful error messages"""
msg = ''
if auth_plugin_name.endswith('password'):
if not options.os_username:
msg += _('Set a username with --os-username or OS_USERNAME\n')
if not options.os_auth_url:
msg += _('Set an authentication URL, with --os-auth-url or'
' OS_AUTH_URL\n')
if (not options.os_project_id and not options.os_domain_id and not
options.os_domain_name and not options.os_project_name):
msg += _('Set a scope, such as a project or domain, with '
'--os-project-name or OS_PROJECT_NAME')
if msg:
raise exc.CommandError('Missing parameter(s): \n%s' % msg)
def build_auth_plugins_option_parser(parser): def build_auth_plugins_option_parser(parser):
"""Auth plugins options builder """Auth plugins options builder
@ -140,7 +160,7 @@ def build_auth_plugins_option_parser(parser):
' (Env: OS_AUTH_TYPE)', ' (Env: OS_AUTH_TYPE)',
choices=available_plugins choices=available_plugins
) )
# make sur we catch old v2.0 env values # make sure we catch old v2.0 env values
envs = { envs = {
'OS_PROJECT_NAME': utils.env( 'OS_PROJECT_NAME': utils.env(
'OS_PROJECT_NAME', 'OS_PROJECT_NAME',

View File

@ -74,13 +74,16 @@ class ClientManager(object):
:param pw_func: :param pw_func:
Callback function for asking the user for a password. The function Callback function for asking the user for a password. The function
takes an optional string for the prompt ('Password: ' on None) and takes an optional string for the prompt ('Password: ' on None) and
returns a string containig the password returns a string containing the password
""" """
# If no auth type is named by the user, select one based on # If no auth type is named by the user, select one based on
# the supplied options # the supplied options
self.auth_plugin_name = auth.select_auth_plugin(auth_options) self.auth_plugin_name = auth.select_auth_plugin(auth_options)
# Basic option checking to avoid unhelpful error messages
auth.check_valid_auth_options(auth_options, self.auth_plugin_name)
# Horrible hack alert...must handle prompt for null password if # Horrible hack alert...must handle prompt for null password if
# password auth is requested. # password auth is requested.
if (self.auth_plugin_name.endswith('password') and if (self.auth_plugin_name.endswith('password') and

View File

@ -126,7 +126,8 @@ class TestClientManager(utils.TestCase):
client_manager = clientmanager.ClientManager( client_manager = clientmanager.ClientManager(
auth_options=FakeOptions(os_auth_url=fakes.AUTH_URL, auth_options=FakeOptions(os_auth_url=fakes.AUTH_URL,
os_username=fakes.USERNAME, os_username=fakes.USERNAME,
os_password=fakes.PASSWORD), os_password=fakes.PASSWORD,
os_project_name=fakes.PROJECT_NAME),
api_version=API_VERSION, api_version=API_VERSION,
verify=False, verify=False,
) )
@ -183,6 +184,7 @@ class TestClientManager(utils.TestCase):
auth_options=FakeOptions(os_auth_url=fakes.AUTH_URL, auth_options=FakeOptions(os_auth_url=fakes.AUTH_URL,
os_username=fakes.USERNAME, os_username=fakes.USERNAME,
os_password=fakes.PASSWORD, os_password=fakes.PASSWORD,
os_project_name=fakes.PROJECT_NAME,
os_auth_type='v2password'), os_auth_type='v2password'),
api_version=API_VERSION, api_version=API_VERSION,
verify='cafile', verify='cafile',
@ -218,7 +220,8 @@ class TestClientManager(utils.TestCase):
# test password auth # test password auth
params = dict(os_auth_url=fakes.AUTH_URL, params = dict(os_auth_url=fakes.AUTH_URL,
os_username=fakes.USERNAME, os_username=fakes.USERNAME,
os_password=fakes.PASSWORD) os_password=fakes.PASSWORD,
os_project_name=fakes.PROJECT_NAME)
self._select_auth_plugin(params, '2.0', 'v2password') self._select_auth_plugin(params, '2.0', 'v2password')
self._select_auth_plugin(params, '3', 'v3password') self._select_auth_plugin(params, '3', 'v3password')
self._select_auth_plugin(params, 'XXX', 'password') self._select_auth_plugin(params, 'XXX', 'password')

View File

@ -25,6 +25,7 @@ AUTH_TOKEN = "foobar"
AUTH_URL = "http://0.0.0.0" AUTH_URL = "http://0.0.0.0"
USERNAME = "itchy" USERNAME = "itchy"
PASSWORD = "scratchy" PASSWORD = "scratchy"
PROJECT_NAME = "poochie"
TEST_RESPONSE_DICT = fixture.V2Token(token_id=AUTH_TOKEN, TEST_RESPONSE_DICT = fixture.V2Token(token_id=AUTH_TOKEN,
user_name=USERNAME) user_name=USERNAME)