summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJenkins <jenkins@review.openstack.org>2016-06-23 17:14:02 +0000
committerGerrit Code Review <review@openstack.org>2016-06-23 17:14:02 +0000
commitb7909252a586d84042bf2dfec82000b2ded6101e (patch)
treea88ec6999e3e6a1c7eb35436b361d95cfd83c03d
parent377daebaa43b60a6f33ee243286689baf6023657 (diff)
parent337d013c94378a4b3f0e8f90e4f5bd745448658f (diff)
downloadpython-openstackclient-b7909252a586d84042bf2dfec82000b2ded6101e.tar.gz
Merge "Use resource id when name given for identity show"
-rw-r--r--openstackclient/identity/common.py33
-rw-r--r--openstackclient/identity/v3/domain.py7
-rw-r--r--openstackclient/identity/v3/project.py7
-rw-r--r--openstackclient/identity/v3/user.py6
-rw-r--r--openstackclient/tests/identity/v3/fakes.py3
-rw-r--r--openstackclient/tests/identity/v3/test_domain.py10
-rw-r--r--openstackclient/tests/identity/v3/test_project.py38
-rw-r--r--openstackclient/tests/identity/v3/test_user.py11
-rw-r--r--releasenotes/notes/bug-1561599-d5f541f08ae6274a.yaml7
9 files changed, 117 insertions, 5 deletions
diff --git a/openstackclient/identity/common.py b/openstackclient/identity/common.py
index cd767d2f..379f4114 100644
--- a/openstackclient/identity/common.py
+++ b/openstackclient/identity/common.py
@@ -47,6 +47,39 @@ def find_service(identity_client, name_type_or_id):
raise exceptions.CommandError(msg % name_type_or_id)
+def _get_token_resource(client, resource, parsed_name):
+ """Peek into the user's auth token to get resource IDs
+
+ Look into a user's token to try and find the ID of a domain, project or
+ user, when given the name. Typically non-admin users will interact with
+ the CLI using names. However, by default, keystone does not allow look up
+ by name since it would involve listing all entities. Instead opt to use
+ the correct ID (from the token) instead.
+ :param client: An identity client
+ :param resource: A resource to look at in the token, this may be `domain`,
+ `project_domain`, `user_domain`, `project`, or `user`.
+ :param parsed_name: This is input from parsed_args that the user is hoping
+ to find in the token.
+
+ :returns: The ID of the resource from the token, or the original value from
+ parsed_args if it does not match.
+ """
+
+ try:
+ token = client.auth.client.get_token()
+ token_data = client.tokens.get_token_data(token)
+ token_dict = token_data['token']
+
+ # NOTE(stevemar): If domain is passed, just look at the project domain.
+ if resource == 'domain':
+ token_dict = token_dict['project']
+ obj = token_dict[resource]
+ return obj['id'] if obj['name'] == parsed_name else parsed_name
+ # diaper defense in case parsing the token fails
+ except Exception: # noqa
+ return parsed_name
+
+
def _get_domain_id_if_requested(identity_client, domain_name_or_id):
if not domain_name_or_id:
return None
diff --git a/openstackclient/identity/v3/domain.py b/openstackclient/identity/v3/domain.py
index 001d5201..8ba76c41 100644
--- a/openstackclient/identity/v3/domain.py
+++ b/openstackclient/identity/v3/domain.py
@@ -24,6 +24,7 @@ from osc_lib import utils
import six
from openstackclient.i18n import _
+from openstackclient.identity import common
LOG = logging.getLogger(__name__)
@@ -187,8 +188,12 @@ class ShowDomain(command.ShowOne):
def take_action(self, parsed_args):
identity_client = self.app.client_manager.identity
+
+ domain_str = common._get_token_resource(identity_client, 'domain',
+ parsed_args.domain)
+
domain = utils.find_resource(identity_client.domains,
- parsed_args.domain)
+ domain_str)
domain._info.pop('links')
return zip(*sorted(six.iteritems(domain._info)))
diff --git a/openstackclient/identity/v3/project.py b/openstackclient/identity/v3/project.py
index 4db5bef1..56c1d41a 100644
--- a/openstackclient/identity/v3/project.py
+++ b/openstackclient/identity/v3/project.py
@@ -321,18 +321,21 @@ class ShowProject(command.ShowOne):
def take_action(self, parsed_args):
identity_client = self.app.client_manager.identity
+ project_str = common._get_token_resource(identity_client, 'project',
+ parsed_args.project)
+
if parsed_args.domain:
domain = common.find_domain(identity_client, parsed_args.domain)
project = utils.find_resource(
identity_client.projects,
- parsed_args.project,
+ project_str,
domain_id=domain.id,
parents_as_list=parsed_args.parents,
subtree_as_list=parsed_args.children)
else:
project = utils.find_resource(
identity_client.projects,
- parsed_args.project,
+ project_str,
parents_as_list=parsed_args.parents,
subtree_as_list=parsed_args.children)
diff --git a/openstackclient/identity/v3/user.py b/openstackclient/identity/v3/user.py
index b0c80c14..dd5af06a 100644
--- a/openstackclient/identity/v3/user.py
+++ b/openstackclient/identity/v3/user.py
@@ -444,14 +444,16 @@ class ShowUser(command.ShowOne):
def take_action(self, parsed_args):
identity_client = self.app.client_manager.identity
+ user_str = common._get_token_resource(identity_client, 'user',
+ parsed_args.user)
if parsed_args.domain:
domain = common.find_domain(identity_client, parsed_args.domain)
user = utils.find_resource(identity_client.users,
- parsed_args.user,
+ user_str,
domain_id=domain.id)
else:
user = utils.find_resource(identity_client.users,
- parsed_args.user)
+ user_str)
user._info.pop('links')
return zip(*sorted(six.iteritems(user._info)))
diff --git a/openstackclient/tests/identity/v3/fakes.py b/openstackclient/tests/identity/v3/fakes.py
index cd1b4bd7..dd918616 100644
--- a/openstackclient/tests/identity/v3/fakes.py
+++ b/openstackclient/tests/identity/v3/fakes.py
@@ -502,6 +502,9 @@ class FakeIdentityv3Client(object):
self.role_assignments.resource_class = fakes.FakeResource(None, {})
self.auth_token = kwargs['token']
self.management_url = kwargs['endpoint']
+ self.auth = FakeAuth()
+ self.auth.client = mock.Mock()
+ self.auth.client.resource_class = fakes.FakeResource(None, {})
class FakeFederationManager(object):
diff --git a/openstackclient/tests/identity/v3/test_domain.py b/openstackclient/tests/identity/v3/test_domain.py
index f3777f12..e06e0681 100644
--- a/openstackclient/tests/identity/v3/test_domain.py
+++ b/openstackclient/tests/identity/v3/test_domain.py
@@ -389,6 +389,16 @@ class TestDomainShow(TestDomain):
('domain', identity_fakes.domain_id),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+ self.app.client_manager.identity.tokens.get_token_data.return_value = \
+ {'token':
+ {'project':
+ {'domain':
+ {'id': 'd1',
+ 'name': 'd1'
+ }
+ }
+ }
+ }
# In base command class ShowOne in cliff, abstract method take_action()
# returns a two-part tuple with a tuple of column names and a tuple of
diff --git a/openstackclient/tests/identity/v3/test_project.py b/openstackclient/tests/identity/v3/test_project.py
index 8fcada6e..93bf18af 100644
--- a/openstackclient/tests/identity/v3/test_project.py
+++ b/openstackclient/tests/identity/v3/test_project.py
@@ -749,6 +749,7 @@ class TestProjectShow(TestProject):
self.cmd = project.ShowProject(self.app, None)
def test_project_show(self):
+
arglist = [
identity_fakes.project_id,
]
@@ -757,6 +758,16 @@ class TestProjectShow(TestProject):
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+ self.app.client_manager.identity.tokens.get_token_data.return_value = \
+ {'token':
+ {'project':
+ {'domain': {},
+ 'name': parsed_args.project,
+ 'id': parsed_args.project
+ }
+ }
+ }
+
# In base command class ShowOne in cliff, abstract method take_action()
# returns a two-part tuple with a tuple of column names and a tuple of
# data to be shown.
@@ -797,6 +808,15 @@ class TestProjectShow(TestProject):
('children', False),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+ self.app.client_manager.identity.tokens.get_token_data.return_value = \
+ {'token':
+ {'project':
+ {'domain': {},
+ 'name': parsed_args.project,
+ 'id': parsed_args.project
+ }
+ }
+ }
columns, data = self.cmd.take_action(parsed_args)
self.projects_mock.get.assert_called_with(
@@ -845,6 +865,15 @@ class TestProjectShow(TestProject):
('children', True),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+ self.app.client_manager.identity.tokens.get_token_data.return_value = \
+ {'token':
+ {'project':
+ {'domain': {},
+ 'name': parsed_args.project,
+ 'id': parsed_args.project
+ }
+ }
+ }
columns, data = self.cmd.take_action(parsed_args)
self.projects_mock.get.assert_called_with(
@@ -895,6 +924,15 @@ class TestProjectShow(TestProject):
('children', True),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+ self.app.client_manager.identity.tokens.get_token_data.return_value = \
+ {'token':
+ {'project':
+ {'domain': {},
+ 'name': parsed_args.project,
+ 'id': parsed_args.project
+ }
+ }
+ }
columns, data = self.cmd.take_action(parsed_args)
self.projects_mock.get.assert_called_with(
diff --git a/openstackclient/tests/identity/v3/test_user.py b/openstackclient/tests/identity/v3/test_user.py
index 85522e57..c4fb1521 100644
--- a/openstackclient/tests/identity/v3/test_user.py
+++ b/openstackclient/tests/identity/v3/test_user.py
@@ -1094,6 +1094,17 @@ class TestUserShow(TestUser):
# Get the command object to test
self.cmd = user.ShowUser(self.app, None)
+ self.app.client_manager.identity.auth.client.get_user_id.\
+ return_value = 'bbbbbbb-aaaa-aaaa-aaaa-bbbbbbbaaaa'
+ self.app.client_manager.identity.tokens.get_token_data.return_value = \
+ {'token':
+ {'user':
+ {'domain': {},
+ 'id': 'bbbbbbb-aaaa-aaaa-aaaa-bbbbbbbaaaa',
+ 'name': 'bbbbbbb-aaaa-aaaa-aaaa-bbbbbbbaaaa'
+ }
+ }
+ }
def test_user_show(self):
arglist = [
diff --git a/releasenotes/notes/bug-1561599-d5f541f08ae6274a.yaml b/releasenotes/notes/bug-1561599-d5f541f08ae6274a.yaml
new file mode 100644
index 00000000..8624a95b
--- /dev/null
+++ b/releasenotes/notes/bug-1561599-d5f541f08ae6274a.yaml
@@ -0,0 +1,7 @@
+---
+fixes:
+ - When performing ``domain show``, ``project show`` or ``user show``, peek
+ into the user token to determine the ID or the resource (if supplied with
+ only a name). This should make finding information about the user and
+ their project easier for non-admin users.
+ [Bug `1561599 <https://bugs.launchpad.net/bugs/1561599>`_]