summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrey Kurilin <andr.kurilin@gmail.com>2017-01-23 19:22:14 +0200
committerMatt Riedemann <mriedem.os@gmail.com>2018-04-19 18:43:45 +0000
commit6049be67c0f66bd2d15c7b52f77dd89ac4ec2e94 (patch)
treed37ee5e9e338704f3d619782e0392193bae2dc6f
parent8cabab774c05f84ecb648f35d43fa1873adf5ef8 (diff)
downloadpython-novaclient-6049be67c0f66bd2d15c7b52f77dd89ac4ec2e94.tar.gz
[CLI] Fix token auth type10.2.0
There are 2 known issues which breaks token auth method in CLI: * The wrong check of flag (the check should be for --os-token since arguments are not parsed at that moment) is performed in CLI inner method `_append_global_identity_args`. It led to usage of "password" auth type by default[1] even if `--os-token` cli argument is specified. If `--os-auth-type` is specified to token, keystoneauth1 library makes the right decision[2]. * Based on an auth type, keystoneauth library registers different CLI arguments[3]. It means that `--os-username` argument is available only in password auth type, `--os-token` is available only in token auth type, etc. It also affects the way in which the python code should access such arguments. The arguments which are unrelated to the selected auth type are omitted from the parsed arguments object. That sounds reasonable, but unfortunately the code assumes the unrelated arguments are always present which leads to an AttributeError. Combination of these 2 issues made token auth type broken in CLI layer. [1] https://github.com/openstack/python-novaclient/blob/ee2221f0526c4a6bed431229e363c740d07b8ee9/novaclient/shell.py#L255-L257 [2] https://github.com/openstack/keystoneauth/blob/14dd37b34c4821abf145ea24e593eddaa9f607c8/keystoneauth1/loading/cli.py#L51-L52 [3] https://github.com/openstack/keystoneauth/blob/14dd37b34c4821abf145ea24e593eddaa9f607c8/keystoneauth1/loading/cli.py#L65-L73 Closes-Bug: #1659015 Change-Id: Ibc861d396b71fe105288d8336623cc22cf92523e
-rw-r--r--novaclient/shell.py34
-rw-r--r--novaclient/tests/functional/test_auth.py20
-rw-r--r--novaclient/tests/unit/test_shell.py12
3 files changed, 31 insertions, 35 deletions
diff --git a/novaclient/shell.py b/novaclient/shell.py
index 4ecae61e..2702fe23 100644
--- a/novaclient/shell.py
+++ b/novaclient/shell.py
@@ -249,11 +249,11 @@ class OpenStackComputeShell(object):
def _append_global_identity_args(self, parser, argv):
# Register the CLI arguments that have moved to the session object.
loading.register_session_argparse_arguments(parser)
- # Peek into argv to see if os-auth-token or os-token were given,
+ # Peek into argv to see if os-token was given,
# in which case, the token auth plugin is what the user wants
# else, we'll default to password
default_auth_plugin = 'password'
- if 'os-token' in argv:
+ if "--os-token" in argv:
default_auth_plugin = 'token'
loading.register_auth_argparse_arguments(
parser, argv, default=default_auth_plugin)
@@ -513,8 +513,10 @@ class OpenStackComputeShell(object):
api_version = api_versions.get_api_version(
args.os_compute_api_version)
- os_username = args.os_username
- os_user_id = args.os_user_id
+ auth_token = getattr(args, "os_token", None)
+
+ os_username = getattr(args, "os_username", None)
+ os_user_id = getattr(args, "os_user_id", None)
os_password = None # Fetched and set later as needed
os_project_name = getattr(
args, 'os_project_name', getattr(args, 'os_tenant_name', None))
@@ -529,13 +531,16 @@ class OpenStackComputeShell(object):
if (not args.os_project_domain_id and
not args.os_project_domain_name):
setattr(args, "os_project_domain_id", "default")
- if not args.os_user_domain_id and not args.os_user_domain_name:
+
+ # os_user_domain_id is redundant in case of Token auth type
+ if not auth_token and (not args.os_user_domain_id and
+ not args.os_user_domain_name):
setattr(args, "os_user_domain_id", "default")
os_project_domain_id = args.os_project_domain_id
os_project_domain_name = args.os_project_domain_name
- os_user_domain_id = args.os_project_domain_id
- os_user_domain_name = args.os_project_domain_name
+ os_user_domain_id = getattr(args, "os_user_domain_id", None)
+ os_user_domain_name = getattr(args, "os_user_domain_name", None)
endpoint_type = args.endpoint_type
insecure = args.insecure
@@ -550,13 +555,6 @@ class OpenStackComputeShell(object):
keystone_session = None
keystone_auth = None
- # We may have either, both or none of these.
- # If we have both, we don't need USERNAME, PASSWORD etc.
- # Finally, authenticate unless we have both.
- # Note if we don't auth we probably don't have a tenant ID so we can't
- # cache the token.
- auth_token = getattr(args, 'os_token', None)
-
if not endpoint_type:
endpoint_type = DEFAULT_NOVA_ENDPOINT_TYPE
@@ -579,11 +577,11 @@ class OpenStackComputeShell(object):
# for os_username or os_password but for compatibility it is not.
if must_auth and not skip_auth:
- if not os_username and not os_user_id:
+ if not any([auth_token, os_username, os_user_id]):
raise exc.CommandError(
- _("You must provide a username "
- "or user ID via --os-username, --os-user-id, "
- "env[OS_USERNAME] or env[OS_USER_ID]"))
+ _("You must provide a user name/id (via --os-username, "
+ "--os-user-id, env[OS_USERNAME] or env[OS_USER_ID]) or "
+ "an auth token (via --os-token)."))
if not any([os_project_name, os_project_id]):
raise exc.CommandError(_("You must provide a project name or"
diff --git a/novaclient/tests/functional/test_auth.py b/novaclient/tests/functional/test_auth.py
index 9f645c33..74fa7fb1 100644
--- a/novaclient/tests/functional/test_auth.py
+++ b/novaclient/tests/functional/test_auth.py
@@ -51,17 +51,15 @@ class TestAuthentication(base.ClientTestBase):
project_name=self.project_name, **kw)
nova.servers.list()
- # NOTE(andreykurilin): token auth is completely broken in CLI
- # flags = ('--os-username %s --os-tenant-name %s --os-auth-token %s '
- # '--os-auth-url %s --os-endpoint-type publicURL' % (
- # self.cli_clients.username,
- # self.cli_clients.tenant_name,
- # token, auth_url))
- # if self.cli_clients.insecure:
- # flags += ' --insecure '
- #
- # return tempest.lib.cli.base.execute(
- # "nova", action, flags, cli_dir=self.cli_clients.cli_dir)
+ flags = ('--os-tenant-name %(project_name)s --os-token %(token)s '
+ '--os-auth-url %(auth_url)s --os-endpoint-type publicURL'
+ % {"project_name": self.project_name,
+ "token": token, "auth_url": auth_url})
+ if self.cli_clients.insecure:
+ flags += ' --insecure '
+
+ tempest.lib.cli.base.execute(
+ "nova", "list", flags, cli_dir=self.cli_clients.cli_dir)
def test_auth_via_keystone_v2(self):
session = self.keystone.session
diff --git a/novaclient/tests/unit/test_shell.py b/novaclient/tests/unit/test_shell.py
index 8e589a47..86047923 100644
--- a/novaclient/tests/unit/test_shell.py
+++ b/novaclient/tests/unit/test_shell.py
@@ -467,9 +467,9 @@ class ShellTest(utils.TestCase):
matchers.MatchesRegex(r, re.DOTALL | re.MULTILINE))
def test_no_username(self):
- required = ('You must provide a username or user ID'
- ' via --os-username, --os-user-id,'
- ' env[OS_USERNAME] or env[OS_USER_ID]')
+ required = ('You must provide a user name/id (via --os-username, '
+ '--os-user-id, env[OS_USERNAME] or env[OS_USER_ID]) or '
+ 'an auth token (via --os-token).')
self.make_env(exclude='OS_USERNAME')
try:
self.shell('list')
@@ -479,9 +479,9 @@ class ShellTest(utils.TestCase):
self.fail('CommandError not raised')
def test_no_user_id(self):
- required = ('You must provide a username or user ID'
- ' via --os-username, --os-user-id,'
- ' env[OS_USERNAME] or env[OS_USER_ID]')
+ required = ('You must provide a user name/id (via --os-username, '
+ '--os-user-id, env[OS_USERNAME] or env[OS_USER_ID]) or '
+ 'an auth token (via --os-token).')
self.make_env(exclude='OS_USER_ID', fake_env=FAKE_ENV2)
try:
self.shell('list')