Allow user list to filter by project

Adds a --project filter to `os user list`, which really
calls the role assignment manager behind the scenes.

Change-Id: I57a75018f12ed3acdf8f6611b6b58bd974f91da2
Closes-Bug: #1397251
This commit is contained in:
Steve Martinelli 2014-12-16 15:16:41 -05:00
parent cbb26724fc
commit 0ff28d5251
3 changed files with 101 additions and 17 deletions
doc/source/command-objects
openstackclient
identity/v3
tests/identity/v3

@ -101,28 +101,26 @@ List users
.. code:: bash
os user list
[--domain <domain>]
[--project <project>]
[--group <group>]
[--domain <domain>]
[--group <group> | --project <project>]
[--long]
.. option:: --domain <domain>
Filter users by `<domain>` (name or ID)
.. versionadded:: 3
.. option:: --project <project>
Filter users by `<project>` (name or ID)
*Removed in version 3.*
.. option:: --domain <domain>
Filter users by `<domain>` (name or ID)
*Identity version 3 only*
.. option:: --group <group>
Filter users by `<group>` membership (name or ID)
.. versionadded:: 3
*Identity version 3 only*
.. option:: --long

@ -188,11 +188,17 @@ class ListUser(lister.Lister):
metavar='<domain>',
help='Filter users by <domain> (name or ID)',
)
parser.add_argument(
project_or_group = parser.add_mutually_exclusive_group()
project_or_group.add_argument(
'--group',
metavar='<group>',
help='Filter users by <group> membership (name or ID)',
)
project_or_group.add_argument(
'--project',
metavar='<project>',
help='Filter users by <project> (name or ID)',
)
parser.add_argument(
'--long',
action='store_true',
@ -219,7 +225,44 @@ class ListUser(lister.Lister):
else:
group = None
# List users
if parsed_args.project:
if domain is not None:
project = utils.find_resource(
identity_client.projects,
parsed_args.project,
domain_id=domain
).id
else:
project = utils.find_resource(
identity_client.projects,
parsed_args.project,
).id
assignments = identity_client.role_assignments.list(
project=project)
# NOTE(stevemar): If a user has more than one role on a project
# then they will have two entries in the returned data. Since we
# are looking for any role, let's just track unique user IDs.
user_ids = set()
for assignment in assignments:
if hasattr(assignment, 'user'):
user_ids.add(assignment.user['id'])
# NOTE(stevemar): Call find_resource once we have unique IDs, so
# it's fewer trips to the Identity API, then collect the data.
data = []
for user_id in user_ids:
user = utils.find_resource(identity_client.users, user_id)
data.append(user)
else:
data = identity_client.users.list(
domain=domain,
group=group,
)
# Column handling
if parsed_args.long:
columns = ['ID', 'Name', 'Default Project Id', 'Domain Id',
'Description', 'Email', 'Enabled']
@ -228,11 +271,7 @@ class ListUser(lister.Lister):
column_headers[3] = 'Domain'
else:
columns = ['ID', 'Name']
column_headers = copy.deepcopy(columns)
data = identity_client.users.list(
domain=domain,
group=group,
)
column_headers = columns
return (
column_headers,

@ -44,6 +44,11 @@ class TestUser(identity_fakes.TestIdentityv3):
self.users_mock = self.app.client_manager.identity.users
self.users_mock.reset_mock()
# Shortcut for RoleAssignmentManager Mock
self.role_assignments_mock = self.app.client_manager.identity.\
role_assignments
self.role_assignments_mock.reset_mock()
class TestUserCreate(TestUser):
@ -511,6 +516,21 @@ class TestUserList(TestUser):
loaded=True,
)
self.projects_mock.get.return_value = fakes.FakeResource(
None,
copy.deepcopy(identity_fakes.PROJECT),
loaded=True,
)
self.role_assignments_mock.list.return_value = [
fakes.FakeResource(
None,
copy.deepcopy(
identity_fakes.ASSIGNMENT_WITH_PROJECT_ID_AND_USER_ID),
loaded=True,
)
]
# Get the command object to test
self.cmd = user.ListUser(self.app, None)
@ -643,6 +663,33 @@ class TestUserList(TestUser):
), )
self.assertEqual(datalist, tuple(data))
def test_user_list_project(self):
arglist = [
'--project', identity_fakes.project_name,
]
verifylist = [
('project', identity_fakes.project_name),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
# DisplayCommandBase.take_action() returns two tuples
columns, data = self.cmd.take_action(parsed_args)
kwargs = {
'project': identity_fakes.project_id,
}
self.role_assignments_mock.list.assert_called_with(**kwargs)
self.users_mock.get.assert_called_with(identity_fakes.user_id)
collist = ['ID', 'Name']
self.assertEqual(columns, collist)
datalist = ((
identity_fakes.user_id,
identity_fakes.user_name,
), )
self.assertEqual(datalist, tuple(data))
class TestUserSet(TestUser):