Skip to content

Commit dd6ac28

Browse files
Zuulopenstack-gerrit
authored andcommitted
Merge "Identity: Migrate 'role assignment' commands to SDK"
2 parents 887f1e9 + de9d0f9 commit dd6ac28

5 files changed

Lines changed: 723 additions & 467 deletions

File tree

openstackclient/identity/v3/role_assignment.py

Lines changed: 91 additions & 139 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,53 @@
1313

1414
"""Identity v3 Assignment action implementations"""
1515

16+
from openstack import exceptions as sdk_exceptions
1617
from osc_lib.command import command
17-
from osc_lib import utils
1818

1919
from openstackclient.i18n import _
2020
from openstackclient.identity import common
2121

2222

23+
def _format_role_assignment_(assignment, include_names):
24+
def _get_names(attr):
25+
return (
26+
(
27+
attr['name']
28+
+ (
29+
"@" + domain['name']
30+
if (domain := attr.get('domain'))
31+
else ''
32+
)
33+
)
34+
or ''
35+
if attr
36+
else ''
37+
)
38+
39+
def _get_ids(attr):
40+
return attr['id'] or '' if attr else ''
41+
42+
func = _get_names if include_names else _get_ids
43+
return (
44+
func(assignment.role),
45+
func(assignment.user),
46+
func(assignment.group),
47+
func(assignment.scope.get('project')),
48+
func(assignment.scope.get('domain')),
49+
'all' if assignment.scope.get("system") else '',
50+
assignment.scope.get("OS-INHERIT:inherited_to") == 'projects',
51+
)
52+
53+
54+
def _find_sdk_id(find_command, name_or_id, **kwargs):
55+
try:
56+
return find_command(
57+
name_or_id=name_or_id, ignore_missing=False, **kwargs
58+
).id
59+
except sdk_exceptions.ForbiddenException:
60+
return name_or_id
61+
62+
2363
class ListRoleAssignment(command.Lister):
2464
_description = _("List role assignments")
2565

@@ -28,7 +68,7 @@ def get_parser(self, prog_name):
2868
parser.add_argument(
2969
'--effective',
3070
action="store_true",
31-
default=False,
71+
default=None,
3272
help=_('Returns only effective role assignments'),
3373
)
3474
parser.add_argument(
@@ -88,81 +128,74 @@ def get_parser(self, prog_name):
88128
)
89129
return parser
90130

91-
def _as_tuple(self, assignment):
92-
return (
93-
assignment.role,
94-
assignment.user,
95-
assignment.group,
96-
assignment.project,
97-
assignment.domain,
98-
assignment.system,
99-
assignment.inherited,
100-
)
101-
102131
def take_action(self, parsed_args):
103-
identity_client = self.app.client_manager.identity
132+
identity_client = self.app.client_manager.sdk_connection.identity
104133
auth_ref = self.app.client_manager.auth_ref
105134

106-
role = None
135+
role_id = None
107136
role_domain_id = None
108137
if parsed_args.role_domain:
109-
role_domain_id = common.find_domain(
110-
identity_client, parsed_args.role_domain
111-
).id
138+
role_domain_id = _find_sdk_id(
139+
identity_client.find_domain,
140+
name_or_id=parsed_args.role_domain,
141+
)
112142
if parsed_args.role:
113-
role = utils.find_resource(
114-
identity_client.roles,
115-
parsed_args.role,
143+
role_id = _find_sdk_id(
144+
identity_client.find_role,
145+
name_or_id=parsed_args.role,
116146
domain_id=role_domain_id,
117147
)
118148

119-
user = None
149+
user_id = None
120150
if parsed_args.user:
121-
user = common.find_user(
122-
identity_client,
123-
parsed_args.user,
124-
parsed_args.user_domain,
151+
user_id = _find_sdk_id(
152+
identity_client.find_user,
153+
name_or_id=parsed_args.user,
154+
domain_id=parsed_args.user_domain,
125155
)
126156
elif parsed_args.authuser:
127157
if auth_ref:
128-
user = common.find_user(identity_client, auth_ref.user_id)
158+
user_id = _find_sdk_id(
159+
identity_client.find_user,
160+
name_or_id=auth_ref.user_id,
161+
)
129162

130163
system = None
131164
if parsed_args.system:
132165
system = parsed_args.system
133166

134-
domain = None
167+
domain_id = None
135168
if parsed_args.domain:
136-
domain = common.find_domain(
137-
identity_client,
138-
parsed_args.domain,
169+
domain_id = _find_sdk_id(
170+
identity_client.find_domain,
171+
name_or_id=parsed_args.domain,
139172
)
140173

141-
project = None
174+
project_id = None
142175
if parsed_args.project:
143-
project = common.find_project(
144-
identity_client,
145-
common._get_token_resource(
176+
project_id = _find_sdk_id(
177+
identity_client.find_project,
178+
name_or_id=common._get_token_resource(
146179
identity_client, 'project', parsed_args.project
147180
),
148-
parsed_args.project_domain,
181+
domain_id=parsed_args.project_domain,
149182
)
150183
elif parsed_args.authproject:
151184
if auth_ref:
152-
project = common.find_project(
153-
identity_client, auth_ref.project_id
185+
project_id = _find_sdk_id(
186+
identity_client.find_project,
187+
name_or_id=auth_ref.project_id,
154188
)
155189

156-
group = None
190+
group_id = None
157191
if parsed_args.group:
158-
group = common.find_group(
159-
identity_client,
160-
parsed_args.group,
161-
parsed_args.group_domain,
192+
group_id = _find_sdk_id(
193+
identity_client.find_group,
194+
name_or_id=parsed_args.group,
195+
domain_id=parsed_args.group_domain,
162196
)
163197

164-
include_names = True if parsed_args.names else False
165-
effective = True if parsed_args.effective else False
198+
include_names = True if parsed_args.names else None
166199
columns = (
167200
'Role',
168201
'User',
@@ -174,104 +207,23 @@ def take_action(self, parsed_args):
174207
)
175208

176209
inherited_to = 'projects' if parsed_args.inherited else None
177-
data = identity_client.role_assignments.list(
178-
domain=domain,
179-
user=user,
180-
group=group,
181-
project=project,
182-
system=system,
183-
role=role,
184-
effective=effective,
185-
os_inherit_extension_inherited_to=inherited_to,
210+
211+
data = identity_client.role_assignments(
212+
role_id=role_id,
213+
user_id=user_id,
214+
group_id=group_id,
215+
scope_project_id=project_id,
216+
scope_domain_id=domain_id,
217+
scope_system=system,
218+
effective=parsed_args.effective,
186219
include_names=include_names,
220+
inherited_to=inherited_to,
187221
)
188222

189223
data_parsed = []
190224
for assignment in data:
191-
# Removing the extra "scope" layer in the assignment json
192-
scope = assignment.scope
193-
if 'project' in scope:
194-
if include_names:
195-
prj = '@'.join(
196-
[
197-
scope['project']['name'],
198-
scope['project']['domain']['name'],
199-
]
200-
)
201-
setattr(assignment, 'project', prj)
202-
else:
203-
setattr(assignment, 'project', scope['project']['id'])
204-
assignment.domain = ''
205-
assignment.system = ''
206-
elif 'domain' in scope:
207-
if include_names:
208-
setattr(assignment, 'domain', scope['domain']['name'])
209-
else:
210-
setattr(assignment, 'domain', scope['domain']['id'])
211-
assignment.project = ''
212-
assignment.system = ''
213-
elif 'system' in scope:
214-
# NOTE(lbragstad): If, or when, keystone supports role
215-
# assignments on subsets of a system, this will have to evolve
216-
# to handle that case instead of hardcoding to the entire
217-
# system.
218-
setattr(assignment, 'system', 'all')
219-
assignment.domain = ''
220-
assignment.project = ''
221-
else:
222-
assignment.system = ''
223-
assignment.domain = ''
224-
assignment.project = ''
225-
226-
inherited = scope.get('OS-INHERIT:inherited_to') == 'projects'
227-
assignment.inherited = inherited
228-
229-
del assignment.scope
230-
231-
if hasattr(assignment, 'user'):
232-
if include_names:
233-
usr = '@'.join(
234-
[
235-
assignment.user['name'],
236-
assignment.user['domain']['name'],
237-
]
238-
)
239-
setattr(assignment, 'user', usr)
240-
else:
241-
setattr(assignment, 'user', assignment.user['id'])
242-
assignment.group = ''
243-
elif hasattr(assignment, 'group'):
244-
if include_names:
245-
grp = '@'.join(
246-
[
247-
assignment.group['name'],
248-
assignment.group['domain']['name'],
249-
]
250-
)
251-
setattr(assignment, 'group', grp)
252-
else:
253-
setattr(assignment, 'group', assignment.group['id'])
254-
assignment.user = ''
255-
else:
256-
assignment.user = ''
257-
assignment.group = ''
258-
259-
if hasattr(assignment, 'role'):
260-
if include_names:
261-
# TODO(henry-nash): If this is a domain specific role it
262-
# would be good show this as role@domain, although this
263-
# domain info is not yet included in the response from the
264-
# server. Although we could get it by re-reading the role
265-
# from the ID, let's wait until the server does the right
266-
# thing.
267-
setattr(assignment, 'role', assignment.role['name'])
268-
else:
269-
setattr(assignment, 'role', assignment.role['id'])
270-
else:
271-
assignment.role = ''
272-
273-
# Creating a tuple from data object fields
274-
# (including the blank ones)
275-
data_parsed.append(self._as_tuple(assignment))
225+
data_parsed.append(
226+
_format_role_assignment_(assignment, include_names)
227+
)
276228

277229
return columns, tuple(data_parsed)

openstackclient/tests/functional/identity/v3/common.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,15 @@ class IdentityTests(base.TestCase):
103103
'Implied Role ID',
104104
'Implied Role Name',
105105
]
106+
ROLE_ASSIGNMENT_LIST_HEADERS = [
107+
'Role',
108+
'User',
109+
'Group',
110+
'Project',
111+
'Domain',
112+
'System',
113+
'Inherited',
114+
]
106115
REGISTERED_LIMIT_FIELDS = [
107116
'id',
108117
'service_id',

0 commit comments

Comments
 (0)