Skip to content

Commit 3a48989

Browse files
author
Tom Cocozzello
committed
Return names in list role assignments
Utilize the new include names functionality added to list role assignments (GET /role_assignments?include_names=True). Which will return the names of the entities instead of their IDs. Change-Id: I6dc03baf61ef9354a8a259a9f17ff47ce1665ce7 Depends-On: I4aa77c08660a0cbd021502155938a46121ca76ef Closes-Bug: #1479569 Implements: blueprint list-assignment-with-names
1 parent 1f378a0 commit 3a48989

5 files changed

Lines changed: 162 additions & 13 deletions

File tree

doc/source/command-objects/role-assignment.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,3 +66,7 @@ List role assignments
6666
.. option:: --inherited
6767

6868
Specifies if the role grant is inheritable to the sub projects
69+
70+
.. option:: --names
71+
72+
Returns role assignments with names instead of IDs

openstackclient/identity/v3/role_assignment.py

Lines changed: 34 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,11 @@ def get_parser(self, prog_name):
3939
metavar='<role>',
4040
help='Role to filter (name or ID)',
4141
)
42+
parser.add_argument(
43+
'--names',
44+
action="store_true",
45+
help='Display names instead of IDs',
46+
)
4247
user_or_group = parser.add_mutually_exclusive_group()
4348
user_or_group.add_argument(
4449
'--user',
@@ -113,6 +118,7 @@ def take_action(self, parsed_args):
113118
parsed_args.group_domain,
114119
)
115120

121+
include_names = True if parsed_args.names else False
116122
effective = True if parsed_args.effective else False
117123
self.log.debug('take_action(%s)' % parsed_args)
118124
columns = ('Role', 'User', 'Group', 'Project', 'Domain', 'Inherited')
@@ -125,17 +131,26 @@ def take_action(self, parsed_args):
125131
project=project,
126132
role=role,
127133
effective=effective,
128-
os_inherit_extension_inherited_to=inherited_to)
134+
os_inherit_extension_inherited_to=inherited_to,
135+
include_names=include_names)
129136

130137
data_parsed = []
131138
for assignment in data:
132139
# Removing the extra "scope" layer in the assignment json
133140
scope = assignment.scope
134141
if 'project' in scope:
135-
setattr(assignment, 'project', scope['project']['id'])
142+
if include_names:
143+
prj = '@'.join([scope['project']['name'],
144+
scope['project']['domain']['name']])
145+
setattr(assignment, 'project', prj)
146+
else:
147+
setattr(assignment, 'project', scope['project']['id'])
136148
assignment.domain = ''
137149
elif 'domain' in scope:
138-
setattr(assignment, 'domain', scope['domain']['id'])
150+
if include_names:
151+
setattr(assignment, 'domain', scope['domain']['name'])
152+
else:
153+
setattr(assignment, 'domain', scope['domain']['id'])
139154
assignment.project = ''
140155

141156
else:
@@ -148,17 +163,30 @@ def take_action(self, parsed_args):
148163
del assignment.scope
149164

150165
if hasattr(assignment, 'user'):
151-
setattr(assignment, 'user', assignment.user['id'])
166+
if include_names:
167+
usr = '@'.join([assignment.user['name'],
168+
assignment.user['domain']['name']])
169+
setattr(assignment, 'user', usr)
170+
else:
171+
setattr(assignment, 'user', assignment.user['id'])
152172
assignment.group = ''
153173
elif hasattr(assignment, 'group'):
154-
setattr(assignment, 'group', assignment.group['id'])
174+
if include_names:
175+
grp = '@'.join([assignment.group['name'],
176+
assignment.group['domain']['name']])
177+
setattr(assignment, 'group', grp)
178+
else:
179+
setattr(assignment, 'group', assignment.group['id'])
155180
assignment.user = ''
156181
else:
157182
assignment.user = ''
158183
assignment.group = ''
159184

160185
if hasattr(assignment, 'role'):
161-
setattr(assignment, 'role', assignment.role['id'])
186+
if include_names:
187+
setattr(assignment, 'role', assignment.role['name'])
188+
else:
189+
setattr(assignment, 'role', assignment.role['id'])
162190
else:
163191
assignment.role = ''
164192

openstackclient/tests/identity/v3/fakes.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -314,6 +314,22 @@
314314
'role': {'id': role_id},
315315
}
316316

317+
ASSIGNMENT_WITH_PROJECT_ID_AND_USER_ID_INCLUDE_NAMES = {
318+
'scope': {
319+
'project': {
320+
'domain': {'id': domain_id,
321+
'name': domain_name},
322+
'id': project_id,
323+
'name': project_name}},
324+
'user': {
325+
'domain': {'id': domain_id,
326+
'name': domain_name},
327+
'id': user_id,
328+
'name': user_name},
329+
'role': {'id': role_id,
330+
'name': role_name},
331+
}
332+
317333
ASSIGNMENT_WITH_PROJECT_ID_AND_USER_ID_INHERITED = {
318334
'scope': {'project': {'id': project_id},
319335
'OS-INHERIT:inherited_to': 'projects'},
@@ -333,6 +349,19 @@
333349
'role': {'id': role_id},
334350
}
335351

352+
ASSIGNMENT_WITH_DOMAIN_ID_AND_USER_ID_INCLUDE_NAMES = {
353+
'scope': {
354+
'domain': {'id': domain_id,
355+
'name': domain_name}},
356+
'user': {
357+
'domain': {'id': domain_id,
358+
'name': domain_name},
359+
'id': user_id,
360+
'name': user_name},
361+
'role': {'id': role_id,
362+
'name': role_name},
363+
}
364+
336365
ASSIGNMENT_WITH_DOMAIN_ID_AND_USER_ID_INHERITED = {
337366
'scope': {'domain': {'id': domain_id},
338367
'OS-INHERIT:inherited_to': 'projects'},

openstackclient/tests/identity/v3/test_role_assignment.py

Lines changed: 89 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,8 @@ def test_role_assignment_list_no_filters(self):
9696
role=None,
9797
user=None,
9898
project=None,
99-
os_inherit_extension_inherited_to=None)
99+
os_inherit_extension_inherited_to=None,
100+
include_names=False)
100101

101102
self.assertEqual(self.columns, columns)
102103
datalist = ((
@@ -143,6 +144,7 @@ def test_role_assignment_list_user(self):
143144
('role', None),
144145
('effective', False),
145146
('inherited', False),
147+
('names', False),
146148
]
147149
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
148150

@@ -156,7 +158,8 @@ def test_role_assignment_list_user(self):
156158
project=None,
157159
role=None,
158160
effective=False,
159-
os_inherit_extension_inherited_to=None)
161+
os_inherit_extension_inherited_to=None,
162+
include_names=False)
160163

161164
self.assertEqual(self.columns, columns)
162165
datalist = ((
@@ -203,6 +206,7 @@ def test_role_assignment_list_group(self):
203206
('role', None),
204207
('effective', False),
205208
('inherited', False),
209+
('names', False),
206210
]
207211
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
208212

@@ -216,7 +220,8 @@ def test_role_assignment_list_group(self):
216220
project=None,
217221
role=None,
218222
user=None,
219-
os_inherit_extension_inherited_to=None)
223+
os_inherit_extension_inherited_to=None,
224+
include_names=False)
220225

221226
self.assertEqual(self.columns, columns)
222227
datalist = ((
@@ -263,6 +268,7 @@ def test_role_assignment_list_domain(self):
263268
('role', None),
264269
('effective', False),
265270
('inherited', False),
271+
('names', False),
266272
]
267273
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
268274

@@ -276,7 +282,8 @@ def test_role_assignment_list_domain(self):
276282
project=None,
277283
role=None,
278284
user=None,
279-
os_inherit_extension_inherited_to=None)
285+
os_inherit_extension_inherited_to=None,
286+
include_names=False)
280287

281288
self.assertEqual(self.columns, columns)
282289
datalist = ((
@@ -323,6 +330,7 @@ def test_role_assignment_list_project(self):
323330
('role', None),
324331
('effective', False),
325332
('inherited', False),
333+
('names', False),
326334
]
327335
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
328336

@@ -336,7 +344,8 @@ def test_role_assignment_list_project(self):
336344
project=self.projects_mock.get(),
337345
role=None,
338346
user=None,
339-
os_inherit_extension_inherited_to=None)
347+
os_inherit_extension_inherited_to=None,
348+
include_names=False)
340349

341350
self.assertEqual(self.columns, columns)
342351
datalist = ((
@@ -381,6 +390,7 @@ def test_role_assignment_list_effective(self):
381390
('role', None),
382391
('effective', True),
383392
('inherited', False),
393+
('names', False),
384394
]
385395
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
386396

@@ -394,7 +404,8 @@ def test_role_assignment_list_effective(self):
394404
project=None,
395405
role=None,
396406
user=None,
397-
os_inherit_extension_inherited_to=None)
407+
os_inherit_extension_inherited_to=None,
408+
include_names=False)
398409

399410
self.assertEqual(self.columns, columns)
400411
datalist = ((
@@ -441,6 +452,7 @@ def test_role_assignment_list_inherited(self):
441452
('role', None),
442453
('effective', False),
443454
('inherited', True),
455+
('names', False),
444456
]
445457
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
446458

@@ -454,7 +466,8 @@ def test_role_assignment_list_inherited(self):
454466
project=None,
455467
role=None,
456468
user=None,
457-
os_inherit_extension_inherited_to='projects')
469+
os_inherit_extension_inherited_to='projects',
470+
include_names=False)
458471

459472
self.assertEqual(self.columns, columns)
460473
datalist = ((
@@ -472,3 +485,72 @@ def test_role_assignment_list_inherited(self):
472485
True
473486
),)
474487
self.assertEqual(datalist, tuple(data))
488+
489+
def test_role_assignment_list_include_names(self):
490+
491+
self.role_assignments_mock.list.return_value = [
492+
fakes.FakeResource(
493+
None,
494+
copy.deepcopy(
495+
identity_fakes
496+
.ASSIGNMENT_WITH_PROJECT_ID_AND_USER_ID_INCLUDE_NAMES),
497+
loaded=True,
498+
),
499+
fakes.FakeResource(
500+
None,
501+
copy.deepcopy(
502+
identity_fakes
503+
.ASSIGNMENT_WITH_DOMAIN_ID_AND_USER_ID_INCLUDE_NAMES),
504+
loaded=True,
505+
),
506+
]
507+
508+
arglist = ['--names']
509+
verifylist = [
510+
('user', None),
511+
('group', None),
512+
('domain', None),
513+
('project', None),
514+
('role', None),
515+
('effective', False),
516+
('inherited', False),
517+
('names', True),
518+
]
519+
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
520+
521+
# DisplayCommandBase.take_action() returns two tuples
522+
523+
# This test will not run correctly until the patch in the python
524+
# client is merged. Once that is done 'data' should return the
525+
# correct information
526+
columns, data = self.cmd.take_action(parsed_args)
527+
528+
self.role_assignments_mock.list.assert_called_with(
529+
domain=None,
530+
group=None,
531+
effective=False,
532+
project=None,
533+
role=None,
534+
user=None,
535+
os_inherit_extension_inherited_to=None,
536+
include_names=True)
537+
538+
collist = ('Role', 'User', 'Group', 'Project', 'Domain', 'Inherited')
539+
self.assertEqual(columns, collist)
540+
541+
datalist1 = ((
542+
identity_fakes.role_name,
543+
'@'.join([identity_fakes.user_name, identity_fakes.domain_name]),
544+
'',
545+
'@'.join([identity_fakes.project_name,
546+
identity_fakes.domain_name]),
547+
'',
548+
False
549+
), (identity_fakes.role_name,
550+
'@'.join([identity_fakes.user_name, identity_fakes.domain_name]),
551+
'',
552+
'',
553+
identity_fakes.domain_name,
554+
False
555+
),)
556+
self.assertEqual(tuple(data), datalist1)
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
features:
3+
- >
4+
[`bug 1479569 <https://bugs.launchpad.net/python-keystoneclient/+bug/1479569>`_]
5+
Add an optional ``--names`` argument to the `role assignment list`` command. This
6+
will output names instead of IDs for users, groups, roles, projects, and domains.

0 commit comments

Comments
 (0)