Merge "Allow user list to filter by project"
This commit is contained in:
commit
f38d6e7aee
@ -101,28 +101,26 @@ List users
|
|||||||
.. code:: bash
|
.. code:: bash
|
||||||
|
|
||||||
os user list
|
os user list
|
||||||
[--domain <domain>]
|
|
||||||
[--project <project>]
|
[--project <project>]
|
||||||
[--group <group>]
|
[--domain <domain>]
|
||||||
|
[--group <group> | --project <project>]
|
||||||
[--long]
|
[--long]
|
||||||
|
|
||||||
.. option:: --domain <domain>
|
|
||||||
|
|
||||||
Filter users by `<domain>` (name or ID)
|
|
||||||
|
|
||||||
.. versionadded:: 3
|
|
||||||
|
|
||||||
.. option:: --project <project>
|
.. option:: --project <project>
|
||||||
|
|
||||||
Filter users by `<project>` (name or ID)
|
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>
|
.. option:: --group <group>
|
||||||
|
|
||||||
Filter users by `<group>` membership (name or ID)
|
Filter users by `<group>` membership (name or ID)
|
||||||
|
|
||||||
.. versionadded:: 3
|
*Identity version 3 only*
|
||||||
|
|
||||||
.. option:: --long
|
.. option:: --long
|
||||||
|
|
||||||
|
@ -188,11 +188,17 @@ class ListUser(lister.Lister):
|
|||||||
metavar='<domain>',
|
metavar='<domain>',
|
||||||
help='Filter users by <domain> (name or ID)',
|
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',
|
'--group',
|
||||||
metavar='<group>',
|
metavar='<group>',
|
||||||
help='Filter users by <group> membership (name or ID)',
|
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(
|
parser.add_argument(
|
||||||
'--long',
|
'--long',
|
||||||
action='store_true',
|
action='store_true',
|
||||||
@ -219,7 +225,44 @@ class ListUser(lister.Lister):
|
|||||||
else:
|
else:
|
||||||
group = None
|
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:
|
if parsed_args.long:
|
||||||
columns = ['ID', 'Name', 'Default Project Id', 'Domain Id',
|
columns = ['ID', 'Name', 'Default Project Id', 'Domain Id',
|
||||||
'Description', 'Email', 'Enabled']
|
'Description', 'Email', 'Enabled']
|
||||||
@ -228,11 +271,7 @@ class ListUser(lister.Lister):
|
|||||||
column_headers[3] = 'Domain'
|
column_headers[3] = 'Domain'
|
||||||
else:
|
else:
|
||||||
columns = ['ID', 'Name']
|
columns = ['ID', 'Name']
|
||||||
column_headers = copy.deepcopy(columns)
|
column_headers = columns
|
||||||
data = identity_client.users.list(
|
|
||||||
domain=domain,
|
|
||||||
group=group,
|
|
||||||
)
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
column_headers,
|
column_headers,
|
||||||
|
@ -44,6 +44,11 @@ class TestUser(identity_fakes.TestIdentityv3):
|
|||||||
self.users_mock = self.app.client_manager.identity.users
|
self.users_mock = self.app.client_manager.identity.users
|
||||||
self.users_mock.reset_mock()
|
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):
|
class TestUserCreate(TestUser):
|
||||||
|
|
||||||
@ -511,6 +516,21 @@ class TestUserList(TestUser):
|
|||||||
loaded=True,
|
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
|
# Get the command object to test
|
||||||
self.cmd = user.ListUser(self.app, None)
|
self.cmd = user.ListUser(self.app, None)
|
||||||
|
|
||||||
@ -643,6 +663,33 @@ class TestUserList(TestUser):
|
|||||||
), )
|
), )
|
||||||
self.assertEqual(datalist, tuple(data))
|
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):
|
class TestUserSet(TestUser):
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user