Merge "Use resource id when name given for identity show"
This commit is contained in:
commit
b7909252a5
@ -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
|
||||
|
@ -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)))
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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)))
|
||||
|
@ -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):
|
||||
|
@ -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
|
||||
|
@ -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(
|
||||
|
@ -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 = [
|
||||
|
7
releasenotes/notes/bug-1561599-d5f541f08ae6274a.yaml
Normal file
7
releasenotes/notes/bug-1561599-d5f541f08ae6274a.yaml
Normal file
@ -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>`_]
|
Loading…
Reference in New Issue
Block a user