Skip to content

Commit f29a849

Browse files
Steve MartinelliDean Troyer
authored andcommitted
Finish up v3 role commands
* Add remove role * Add --role to group list * Add --role to user list * Fix groups in AddRole() * Remove the tweaks to utils.find_resource for domains; will address that across domains, projects, users and groups in another patch. I want to nail down the structure of these commands and get that into place Change-Id: I8673dd8221ef88978dada5a2833c187026bdb31a
1 parent d50b575 commit f29a849

6 files changed

Lines changed: 304 additions & 45 deletions

File tree

openstackclient/common/utils.py

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,20 +24,27 @@
2424

2525
def find_resource(manager, name_or_id):
2626
"""Helper for the _find_* methods."""
27-
# first try to get entity as integer id
27+
28+
# Try to get entity as integer id
2829
try:
2930
if isinstance(name_or_id, int) or name_or_id.isdigit():
3031
return manager.get(int(name_or_id))
3132
except exceptions.NotFound:
3233
pass
3334

34-
# now try to get entity as uuid
35+
# Try to get entity as uuid
3536
try:
3637
uuid.UUID(str(name_or_id))
3738
return manager.get(name_or_id)
3839
except (ValueError, exceptions.NotFound):
3940
pass
4041

42+
# Try directly using the passed value
43+
try:
44+
return manager.get(name_or_id)
45+
except Exception:
46+
pass
47+
4148
kwargs = {}
4249
if 'NAME_ATTR' in manager.resource_class.__dict__:
4350
# novaclient does this for oddball resources

openstackclient/identity/v3/group.py

Lines changed: 88 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -89,27 +89,108 @@ def take_action(self, parsed_args):
8989

9090

9191
class ListGroup(lister.Lister):
92-
"""List group command"""
92+
"""List groups and optionally roles assigned to groups"""
9393

9494
api = 'identity'
9595
log = logging.getLogger(__name__ + '.ListGroup')
9696

9797
def get_parser(self, prog_name):
9898
parser = super(ListGroup, self).get_parser(prog_name)
99+
parser.add_argument(
100+
'group',
101+
metavar='<group>',
102+
nargs='?',
103+
help='Name or ID of group to list [required with --role]',
104+
)
105+
parser.add_argument(
106+
'--role',
107+
action='store_true',
108+
default=False,
109+
help='List the roles assigned to <group>',
110+
)
111+
domain_or_project = parser.add_mutually_exclusive_group()
112+
domain_or_project.add_argument(
113+
'--domain',
114+
metavar='<domain>',
115+
help='Filter list by <domain> [Only valid with --role]',
116+
)
117+
domain_or_project.add_argument(
118+
'--project',
119+
metavar='<project>',
120+
help='Filter list by <project> [Only valid with --role]',
121+
)
99122
parser.add_argument(
100123
'--long',
101124
action='store_true',
102125
default=False,
103-
help='Additional fields are listed in output')
126+
help='Additional fields are listed in output',
127+
)
104128
return parser
105129

106130
def take_action(self, parsed_args):
107131
self.log.debug('take_action(%s)' % parsed_args)
108-
if parsed_args.long:
109-
columns = ('ID', 'Name', 'Domain ID', 'Description')
132+
identity_client = self.app.client_manager.identity
133+
134+
if parsed_args.role:
135+
# List roles belonging to group
136+
137+
# Group is required here, bail if it is not supplied
138+
if not parsed_args.group:
139+
sys.stderr.write('Error: Group must be specified')
140+
# TODO(dtroyer): This lists the commands...I want it to
141+
# show the help for _this_ command.
142+
self.app.DeferredHelpAction(
143+
self.app.parser,
144+
self.app.parser,
145+
None,
146+
None,
147+
)
148+
return ([], [])
149+
150+
group = utils.find_resource(
151+
identity_client.groups,
152+
parsed_args.group,
153+
)
154+
155+
if parsed_args.domain:
156+
columns = ('ID', 'Name', 'Domain', 'Group')
157+
domain = utils.find_resource(
158+
identity_client.domains,
159+
parsed_args.domain,
160+
)
161+
data = identity_client.roles.list(
162+
group=group,
163+
domain=domain,
164+
)
165+
for group_role in data:
166+
group_role.group = group.name
167+
group_role.domain = domain.name
168+
elif parsed_args.project:
169+
columns = ('ID', 'Name', 'Project', 'Group')
170+
project = utils.find_resource(
171+
identity_client.projects,
172+
parsed_args.project,
173+
)
174+
data = identity_client.roles.list(
175+
group=group,
176+
project=project,
177+
)
178+
for group_role in data:
179+
group_role.group = group.name
180+
group_role.project = project.name
181+
else:
182+
# TODO(dtroyer): raise exception here, this really is an error
183+
sys.stderr.write("Error: Must specify --domain or --project "
184+
"with --role\n")
185+
return ([], [])
110186
else:
111-
columns = ('ID', 'Name')
112-
data = self.app.client_manager.identity.groups.list()
187+
# List groups
188+
if parsed_args.long:
189+
columns = ('ID', 'Name', 'Domain ID', 'Description')
190+
else:
191+
columns = ('ID', 'Name')
192+
data = identity_client.groups.list()
193+
113194
return (columns,
114195
(utils.get_item_properties(
115196
s, columns,
@@ -158,7 +239,7 @@ def take_action(self, parsed_args):
158239
kwargs['domain'] = domain
159240

160241
if not len(kwargs):
161-
sys.stdout.write("Group not updated, no arguments present")
242+
sys.stderr.write("Group not updated, no arguments present")
162243
return
163244
identity_client.groups.update(group.id, **kwargs)
164245
return

openstackclient/identity/v3/role.py

Lines changed: 108 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626

2727

2828
class AddRole(command.Command):
29-
"""Add role command"""
29+
"""Adds a role to a user or group on a domain or project"""
3030

3131
api = 'identity'
3232
log = logging.getLogger(__name__ + '.AddRole')
@@ -42,23 +42,24 @@ def get_parser(self, prog_name):
4242
user_or_group.add_argument(
4343
'--user',
4444
metavar='<user>',
45-
help='Name or ID of user to assign a role',
45+
help='Name or ID of user to add a role',
4646
)
4747
user_or_group.add_argument(
4848
'--group',
4949
metavar='<group>',
50-
help='Name or ID of group to assign a role',
50+
help='Name or ID of group to add a role',
5151
)
5252
domain_or_project = parser.add_mutually_exclusive_group()
5353
domain_or_project.add_argument(
5454
'--domain',
5555
metavar='<domain>',
56-
help='Name or ID of domain where user or group resides',
56+
default='default',
57+
help='Name or ID of domain associated with user or group',
5758
)
5859
domain_or_project.add_argument(
5960
'--project',
6061
metavar='<project>',
61-
help='Name or ID of project where user or group resides',
62+
help='Name or ID of project associated with user or group',
6263
)
6364
return parser
6465

@@ -68,42 +69,40 @@ def take_action(self, parsed_args):
6869

6970
if (not parsed_args.user and not parsed_args.domain
7071
and not parsed_args.group and not parsed_args.project):
71-
sys.stdout.write("Role not updated, no arguments present \n")
72+
sys.stderr.write("Role not added, no arguments present\n")
7273
return
7374

7475
role_id = utils.find_resource(identity_client.roles,
7576
parsed_args.role).id
7677

77-
if (parsed_args.user and parsed_args.domain):
78+
if parsed_args.user and parsed_args.domain:
7879
user = utils.find_resource(identity_client.users,
7980
parsed_args.user)
8081
domain = utils.find_resource(identity_client.domains,
8182
parsed_args.domain)
8283
identity_client.roles.grant(role_id, user=user, domain=domain)
83-
return
84-
elif (parsed_args.user and parsed_args.project):
84+
elif parsed_args.user and parsed_args.project:
8585
user = utils.find_resource(identity_client.users,
8686
parsed_args.user)
8787
project = utils.find_resource(identity_client.projects,
8888
parsed_args.project)
8989
identity_client.roles.grant(role_id, user=user, project=project)
90-
return
91-
elif (parsed_args.group and parsed_args.project):
90+
elif parsed_args.group and parsed_args.domain:
91+
group = utils.find_resource(identity_client.groups,
92+
parsed_args.group)
93+
domain = utils.find_resource(identity_client.domains,
94+
parsed_args.domain)
95+
identity_client.roles.grant(role_id, group=group, domain=domain)
96+
elif parsed_args.group and parsed_args.project:
9297
group = utils.find_resource(identity_client.group,
9398
parsed_args.group)
9499
project = utils.find_resource(identity_client.projects,
95100
parsed_args.project)
96101
identity_client.roles.grant(role_id, group=group, project=project)
97-
return
98-
elif (parsed_args.group and parsed_args.domain):
99-
group = utils.find_resource(identity_client.group,
100-
parsed_args.group)
101-
domain = utils.find_resource(identity_client.domains,
102-
parsed_args.domain)
103-
identity_client.roles.grant(role_id, group=group, domain=domain)
104-
return
105102
else:
106-
return
103+
sys.stderr.write("Role not added, incorrect set of arguments \
104+
provided. See openstack --help for more details\n")
105+
return
107106

108107

109108
class CreateRole(show.ShowOne):
@@ -115,15 +114,16 @@ class CreateRole(show.ShowOne):
115114
def get_parser(self, prog_name):
116115
parser = super(CreateRole, self).get_parser(prog_name)
117116
parser.add_argument(
118-
'role-name',
117+
'name',
119118
metavar='<role-name>',
120-
help='New role name')
119+
help='New role name',
120+
)
121121
return parser
122122

123123
def take_action(self, parsed_args):
124124
self.log.debug('take_action(%s)' % parsed_args)
125125
identity_client = self.app.client_manager.identity
126-
role = identity_client.roles.create(parsed_args.role_name)
126+
role = identity_client.roles.create(parsed_args.name)
127127

128128
return zip(*sorted(role._info.iteritems()))
129129

@@ -139,7 +139,8 @@ def get_parser(self, prog_name):
139139
parser.add_argument(
140140
'role',
141141
metavar='<role>',
142-
help='Name or ID of role to delete')
142+
help='Name or ID of role to delete',
143+
)
143144
return parser
144145

145146
def take_action(self, parsed_args):
@@ -168,6 +169,85 @@ def take_action(self, parsed_args):
168169
) for s in data))
169170

170171

172+
class RemoveRole(command.Command):
173+
"""Remove role command"""
174+
175+
api = 'identity'
176+
log = logging.getLogger(__name__ + '.RemoveRole')
177+
178+
def get_parser(self, prog_name):
179+
parser = super(RemoveRole, self).get_parser(prog_name)
180+
parser.add_argument(
181+
'role',
182+
metavar='<role>',
183+
help='Name or ID of role to remove',
184+
)
185+
user_or_group = parser.add_mutually_exclusive_group()
186+
user_or_group.add_argument(
187+
'--user',
188+
metavar='<user>',
189+
help='Name or ID of user to remove a role',
190+
)
191+
user_or_group.add_argument(
192+
'--group',
193+
metavar='<group>',
194+
help='Name or ID of group to remove a role',
195+
)
196+
domain_or_project = parser.add_mutually_exclusive_group()
197+
domain_or_project.add_argument(
198+
'--domain',
199+
metavar='<domain>',
200+
help='Name or ID of domain associated with user or group',
201+
)
202+
domain_or_project.add_argument(
203+
'--project',
204+
metavar='<project>',
205+
help='Name or ID of project associated with user or group',
206+
)
207+
return parser
208+
209+
def take_action(self, parsed_args):
210+
self.log.debug('take_action(%s)' % parsed_args)
211+
identity_client = self.app.client_manager.identity
212+
213+
if (not parsed_args.user and not parsed_args.domain
214+
and not parsed_args.group and not parsed_args.project):
215+
sys.stdout.write("Role not updated, no arguments present\n")
216+
return
217+
218+
role_id = utils.find_resource(identity_client.roles,
219+
parsed_args.role).id
220+
221+
if parsed_args.user and parsed_args.domain:
222+
user = utils.find_resource(identity_client.users,
223+
parsed_args.user)
224+
domain = utils.find_resource(identity_client.domains,
225+
parsed_args.domain)
226+
identity_client.roles.revoke(role_id, user=user, domain=domain)
227+
elif parsed_args.user and parsed_args.project:
228+
user = utils.find_resource(identity_client.users,
229+
parsed_args.user)
230+
project = utils.find_resource(identity_client.projects,
231+
parsed_args.project)
232+
identity_client.roles.revoke(role_id, user=user, project=project)
233+
elif parsed_args.group and parsed_args.project:
234+
group = utils.find_resource(identity_client.group,
235+
parsed_args.group)
236+
project = utils.find_resource(identity_client.projects,
237+
parsed_args.project)
238+
identity_client.roles.revoke(role_id, group=group, project=project)
239+
elif parsed_args.group and parsed_args.domain:
240+
group = utils.find_resource(identity_client.group,
241+
parsed_args.group)
242+
domain = utils.find_resource(identity_client.domains,
243+
parsed_args.domain)
244+
identity_client.roles.revoke(role_id, group=group, domain=domain)
245+
else:
246+
sys.stderr.write("Role not removed, incorrect set of arguments \
247+
provided. See openstack --help for more details\n")
248+
return
249+
250+
171251
class SetRole(command.Command):
172252
"""Set role command"""
173253

@@ -179,7 +259,7 @@ def get_parser(self, prog_name):
179259
parser.add_argument(
180260
'role',
181261
metavar='<role>',
182-
help='Name or ID of role to change',
262+
help='Name or ID of role to update',
183263
)
184264
parser.add_argument(
185265
'--name',
@@ -195,7 +275,7 @@ def take_action(self, parsed_args):
195275
parsed_args.role)
196276

197277
if not parsed_args.name:
198-
sys.stdout.write("Role not updated, no arguments present")
278+
sys.stderr.write("Role not updated, no arguments present")
199279
return
200280

201281
identity_client.roles.update(role_id, parsed_args.name)
@@ -213,7 +293,8 @@ def get_parser(self, prog_name):
213293
parser.add_argument(
214294
'role',
215295
metavar='<role>',
216-
help='Name or ID of role to display')
296+
help='Name or ID of role to display',
297+
)
217298
return parser
218299

219300
def take_action(self, parsed_args):

0 commit comments

Comments
 (0)