Skip to content

Commit 8bfa180

Browse files
committed
Add system role functionality
This commit adds the necessary bits to expose system role assignments to openstackclient via python-keystoneclient. bp system-scope Depends-On: Iecbcbf020a15f2bec777334c648d4477f89f3b2c Change-Id: I261e84700b51e8715eaebdc3f8f8bc46b68542c2
1 parent 47d0d0e commit 8bfa180

7 files changed

Lines changed: 112 additions & 16 deletions

File tree

lower-constraints.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ python-heatclient==1.10.0
9595
python-ironic-inspector-client==1.5.0
9696
python-ironicclient==2.3.0
9797
python-karborclient==0.6.0
98-
python-keystoneclient==3.8.0
98+
python-keystoneclient==3.15.0
9999
python-mimeparse==1.6.0
100100
python-mistralclient==3.1.0
101101
python-muranoclient==0.8.2

openstackclient/identity/v3/role.py

Lines changed: 26 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -31,13 +31,18 @@
3131

3232

3333
def _add_identity_and_resource_options_to_parser(parser):
34-
domain_or_project = parser.add_mutually_exclusive_group()
35-
domain_or_project.add_argument(
34+
system_or_domain_or_project = parser.add_mutually_exclusive_group()
35+
system_or_domain_or_project.add_argument(
36+
'--system',
37+
metavar='<system>',
38+
help=_('Include <system> (all)'),
39+
)
40+
system_or_domain_or_project.add_argument(
3641
'--domain',
3742
metavar='<domain>',
3843
help=_('Include <domain> (name or ID)'),
3944
)
40-
domain_or_project.add_argument(
45+
system_or_domain_or_project.add_argument(
4146
'--project',
4247
metavar='<project>',
4348
help=_('Include <project> (name or ID)'),
@@ -62,7 +67,14 @@ def _add_identity_and_resource_options_to_parser(parser):
6267
def _process_identity_and_resource_options(parsed_args,
6368
identity_client_manager):
6469
kwargs = {}
65-
if parsed_args.user and parsed_args.domain:
70+
if parsed_args.user and parsed_args.system:
71+
kwargs['user'] = common.find_user(
72+
identity_client_manager,
73+
parsed_args.user,
74+
parsed_args.user_domain,
75+
).id
76+
kwargs['system'] = parsed_args.system
77+
elif parsed_args.user and parsed_args.domain:
6678
kwargs['user'] = common.find_user(
6779
identity_client_manager,
6880
parsed_args.user,
@@ -83,6 +95,13 @@ def _process_identity_and_resource_options(parsed_args,
8395
parsed_args.project,
8496
parsed_args.project_domain,
8597
).id
98+
elif parsed_args.group and parsed_args.system:
99+
kwargs['group'] = common.find_group(
100+
identity_client_manager,
101+
parsed_args.group,
102+
parsed_args.group_domain,
103+
).id
104+
kwargs['system'] = parsed_args.system
86105
elif parsed_args.group and parsed_args.domain:
87106
kwargs['group'] = common.find_group(
88107
identity_client_manager,
@@ -109,8 +128,8 @@ def _process_identity_and_resource_options(parsed_args,
109128

110129

111130
class AddRole(command.Command):
112-
_description = _("Adds a role assignment to a user or group on a domain "
113-
"or project")
131+
_description = _("Adds a role assignment to a user or group on the "
132+
"system, a domain, or a project")
114133

115134
def get_parser(self, prog_name):
116135
parser = super(AddRole, self).get_parser(prog_name)
@@ -381,7 +400,7 @@ def take_action(self, parsed_args):
381400

382401

383402
class RemoveRole(command.Command):
384-
_description = _("Removes a role assignment from domain/project : "
403+
_description = _("Removes a role assignment from system/domain/project : "
385404
"user/group")
386405

387406
def get_parser(self, prog_name):

openstackclient/identity/v3/role_assignment.py

Lines changed: 29 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -55,17 +55,22 @@ def get_parser(self, prog_name):
5555
help=_('Group to filter (name or ID)'),
5656
)
5757
common.add_group_domain_option_to_parser(parser)
58-
domain_or_project = parser.add_mutually_exclusive_group()
59-
domain_or_project.add_argument(
58+
system_or_domain_or_project = parser.add_mutually_exclusive_group()
59+
system_or_domain_or_project.add_argument(
6060
'--domain',
6161
metavar='<domain>',
6262
help=_('Domain to filter (name or ID)'),
6363
)
64-
domain_or_project.add_argument(
64+
system_or_domain_or_project.add_argument(
6565
'--project',
6666
metavar='<project>',
6767
help=_('Project to filter (name or ID)'),
6868
)
69+
system_or_domain_or_project.add_argument(
70+
'--system',
71+
metavar='<system>',
72+
help=_('Filter based on system role assignments'),
73+
)
6974
common.add_project_domain_option_to_parser(parser)
7075
common.add_inherited_option_to_parser(parser)
7176
parser.add_argument(
@@ -85,7 +90,8 @@ def get_parser(self, prog_name):
8590

8691
def _as_tuple(self, assignment):
8792
return (assignment.role, assignment.user, assignment.group,
88-
assignment.project, assignment.domain, assignment.inherited)
93+
assignment.project, assignment.domain, assignment.system,
94+
assignment.inherited)
8995

9096
def take_action(self, parsed_args):
9197
identity_client = self.app.client_manager.identity
@@ -117,6 +123,10 @@ def take_action(self, parsed_args):
117123
auth_ref.user_id
118124
)
119125

126+
system = None
127+
if parsed_args.system:
128+
system = parsed_args.system
129+
120130
domain = None
121131
if parsed_args.domain:
122132
domain = common.find_domain(
@@ -149,14 +159,17 @@ def take_action(self, parsed_args):
149159

150160
include_names = True if parsed_args.names else False
151161
effective = True if parsed_args.effective else False
152-
columns = ('Role', 'User', 'Group', 'Project', 'Domain', 'Inherited')
162+
columns = (
163+
'Role', 'User', 'Group', 'Project', 'Domain', 'System', 'Inherited'
164+
)
153165

154166
inherited_to = 'projects' if parsed_args.inherited else None
155167
data = identity_client.role_assignments.list(
156168
domain=domain,
157169
user=user,
158170
group=group,
159171
project=project,
172+
system=system,
160173
role=role,
161174
effective=effective,
162175
os_inherit_extension_inherited_to=inherited_to,
@@ -174,14 +187,24 @@ def take_action(self, parsed_args):
174187
else:
175188
setattr(assignment, 'project', scope['project']['id'])
176189
assignment.domain = ''
190+
assignment.system = ''
177191
elif 'domain' in scope:
178192
if include_names:
179193
setattr(assignment, 'domain', scope['domain']['name'])
180194
else:
181195
setattr(assignment, 'domain', scope['domain']['id'])
182196
assignment.project = ''
183-
197+
assignment.system = ''
198+
elif 'system' in scope:
199+
# NOTE(lbragstad): If, or when, keystone supports role
200+
# assignments on subsets of a system, this will have to evolve
201+
# to handle that case instead of hardcoding to the entire
202+
# system.
203+
setattr(assignment, 'system', 'all')
204+
assignment.domain = ''
205+
assignment.project = ''
184206
else:
207+
assignment.system = ''
185208
assignment.domain = ''
186209
assignment.project = ''
187210

openstackclient/identity/v3/token.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,12 @@ def take_action(self, parsed_args):
192192
data['user_id'] = auth_ref.user_id
193193
if auth_ref.domain_id:
194194
data['domain_id'] = auth_ref.domain_id
195+
if auth_ref.system_scoped:
196+
# NOTE(lbragstad): This could change in the future when, or if,
197+
# keystone supports the ability to scope to a subset of the entire
198+
# deployment system. When that happens, this will have to relay
199+
# scope information and IDs like we do for projects and domains.
200+
data['system'] = 'all'
195201
return zip(*sorted(six.iteritems(data)))
196202

197203

0 commit comments

Comments
 (0)