Code Coverage

Cobertura Coverage Report > osmclient.cli_commands >

rbac.py

Trend

Classes100%
 
Lines42%
   
Conditionals100%
 

File Coverage summary

NameClassesLinesConditionals
rbac.py
100%
1/1
42%
88/212
100%
0/0

Coverage Breakdown by Class

NameLinesConditionals
rbac.py
42%
88/212
N/A

Source

osmclient/cli_commands/rbac.py
1 # Copyright ETSI Contributors and Others.
2 # All Rights Reserved.
3 #
4 #    Licensed under the Apache License, Version 2.0 (the "License"); you may
5 #    not use this file except in compliance with the License. You may obtain
6 #    a copy of the License at
7 #
8 #         http://www.apache.org/licenses/LICENSE-2.0
9 #
10 #    Unless required by applicable law or agreed to in writing, software
11 #    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12 #    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13 #    License for the specific language governing permissions and limitations
14 #    under the License.
15
16 1 import click
17 1 from osmclient.common.exceptions import ClientException
18 1 from osmclient.cli_commands import utils
19 1 from prettytable import PrettyTable
20 1 import json
21 1 import logging
22
23 1 logger = logging.getLogger("osmclient")
24
25
26 ##############################
27 # Role Management Operations #
28 ##############################
29
30
31 1 @click.command(name="role-create", short_help="creates a new role")
32 1 @click.argument("name")
33 1 @click.option("--permissions", default=None, help="role permissions using a dictionary")
34 1 @click.pass_context
35 1 def role_create(ctx, name, permissions):
36     """
37     Creates a new role.
38
39     \b
40     NAME: Name or ID of the role.
41     DEFINITION: Definition of grant/denial of access to resources.
42     """
43 0     logger.debug("")
44 0     utils.check_client_version(ctx.obj, ctx.command.name)
45 0     ctx.obj.role.create(name, permissions)
46
47
48 1 @click.command(name="role-update", short_help="updates a role")
49 1 @click.argument("name")
50 1 @click.option("--set-name", default=None, help="change name of rle")
51 1 @click.option(
52     "--add",
53     default=None,
54     help="yaml format dictionary with permission: True/False to access grant/denial",
55 )
56 1 @click.option("--remove", default=None, help="yaml format list to remove a permission")
57 1 @click.pass_context
58 1 def role_update(ctx, name, set_name, add, remove):
59     """
60     Updates a role.
61
62     \b
63     NAME: Name or ID of the role.
64     DEFINITION: Definition overwrites the old definition.
65     ADD: Grant/denial of access to resource to add.
66     REMOVE: Grant/denial of access to resource to remove.
67     """
68 0     logger.debug("")
69 0     utils.check_client_version(ctx.obj, ctx.command.name)
70 0     ctx.obj.role.update(name, set_name, None, add, remove)
71
72
73 1 @click.command(name="role-delete", short_help="deletes a role")
74 1 @click.argument("name")
75 1 @click.pass_context
76 1 def role_delete(ctx, name):
77     """
78     Deletes a role.
79
80     \b
81     NAME: Name or ID of the role.
82     """
83 0     logger.debug("")
84 0     utils.check_client_version(ctx.obj, ctx.command.name)
85 0     ctx.obj.role.delete(name)
86
87
88 1 @click.command(name="role-list", short_help="list all roles")
89 1 @click.option(
90     "--filter",
91     default=None,
92     multiple=True,
93     help="restricts the list to the projects matching the filter",
94 )
95 1 @click.pass_context
96 1 def role_list(ctx, filter):
97     """
98     List all roles.
99     """
100 0     logger.debug("")
101 0     utils.check_client_version(ctx.obj, ctx.command.name)
102 0     if filter:
103 0         filter = "&".join(filter)
104 0     resp = ctx.obj.role.list(filter)
105 0     table = PrettyTable(["name", "id"])
106 0     for role in resp:
107 0         table.add_row([role["name"], role["_id"]])
108 0     table.align = "l"
109 0     print(table)
110
111
112 1 @click.command(name="role-show", short_help="show specific role")
113 1 @click.argument("name")
114 1 @click.pass_context
115 1 def role_show(ctx, name):
116     """
117     Shows the details of a role.
118
119     \b
120     NAME: Name or ID of the role.
121     """
122 0     logger.debug("")
123 0     utils.check_client_version(ctx.obj, ctx.command.name)
124 0     resp = ctx.obj.role.get(name)
125
126 0     table = PrettyTable(["key", "attribute"])
127 0     for k, v in resp.items():
128 0         table.add_row([k, json.dumps(v, indent=2)])
129 0     table.align = "l"
130 0     print(table)
131
132
133 ####################
134 # Project mgmt operations
135 ####################
136
137
138 1 @click.command(name="project-create", short_help="creates a new project")
139 1 @click.argument("name")
140 # @click.option('--description',
141 #              default='no description',
142 #              help='human readable description')
143 1 @click.option("--domain-name", "domain_name", default=None, help="assign to a domain")
144 1 @click.option(
145     "--quotas",
146     "quotas",
147     multiple=True,
148     default=None,
149     help="provide quotas. Can be used several times: 'quota1=number[,quota2=number,...]'. Quotas can be one "
150     "of vnfds, nsds, nsts, pdus, nsrs, nsis, vim_accounts, wim_accounts, sdns, k8sclusters, k8srepos",
151 )
152 1 @click.pass_context
153 1 def project_create(ctx, name, domain_name, quotas):
154     """Creates a new project
155
156     NAME: name of the project
157     DOMAIN_NAME: optional domain name for the project when keystone authentication is used
158     QUOTAS: set quotas for the project
159     """
160 0     logger.debug("")
161 0     project = {"name": name}
162 0     if domain_name:
163 0         project["domain_name"] = domain_name
164 0     quotas_dict = _process_project_quotas(quotas)
165 0     if quotas_dict:
166 0         project["quotas"] = quotas_dict
167
168 0     utils.check_client_version(ctx.obj, ctx.command.name)
169 0     ctx.obj.project.create(name, project)
170
171
172 1 def _process_project_quotas(quota_list):
173 0     quotas_dict = {}
174 0     if not quota_list:
175 0         return quotas_dict
176 0     try:
177 0         for quota in quota_list:
178 0             for single_quota in quota.split(","):
179 0                 k, v = single_quota.split("=")
180 0                 quotas_dict[k] = None if v in ("None", "null", "") else int(v)
181 0     except (ValueError, TypeError):
182 0         raise ClientException(
183             "invalid format for 'quotas'. Use 'k1=v1,v1=v2'. v must be a integer or null"
184         )
185 0     return quotas_dict
186
187
188 1 @click.command(name="project-delete", short_help="deletes a project")
189 1 @click.argument("name")
190 1 @click.pass_context
191 1 def project_delete(ctx, name):
192     """deletes a project
193
194     NAME: name or ID of the project to be deleted
195     """
196 0     logger.debug("")
197 0     utils.check_client_version(ctx.obj, ctx.command.name)
198 0     ctx.obj.project.delete(name)
199
200
201 1 @click.command(name="project-list", short_help="list all projects")
202 1 @click.option(
203     "--filter",
204     default=None,
205     multiple=True,
206     help="restricts the list to the projects matching the filter",
207 )
208 1 @click.pass_context
209 1 def project_list(ctx, filter):
210     """list all projects"""
211 0     logger.debug("")
212 0     utils.check_client_version(ctx.obj, ctx.command.name)
213 0     if filter:
214 0         filter = "&".join(filter)
215 0     resp = ctx.obj.project.list(filter)
216 0     table = PrettyTable(["name", "id"])
217 0     for proj in resp:
218 0         table.add_row([proj["name"], proj["_id"]])
219 0     table.align = "l"
220 0     print(table)
221
222
223 1 @click.command(name="project-show", short_help="shows the details of a project")
224 1 @click.argument("name")
225 1 @click.pass_context
226 1 def project_show(ctx, name):
227     """shows the details of a project
228
229     NAME: name or ID of the project
230     """
231 0     logger.debug("")
232 0     utils.check_client_version(ctx.obj, ctx.command.name)
233 0     resp = ctx.obj.project.get(name)
234
235 0     table = PrettyTable(["key", "attribute"])
236 0     for k, v in resp.items():
237 0         table.add_row([k, json.dumps(v, indent=2)])
238 0     table.align = "l"
239 0     print(table)
240
241
242 1 @click.command(
243     name="project-update", short_help="updates a project (only the name can be updated)"
244 )
245 1 @click.argument("project")
246 1 @click.option("--name", default=None, help="new name for the project")
247 1 @click.option(
248     "--quotas",
249     "quotas",
250     multiple=True,
251     default=None,
252     help="change quotas. Can be used several times: 'quota1=number|empty[,quota2=...]' "
253     "(use empty to reset quota to default",
254 )
255 1 @click.pass_context
256 1 def project_update(ctx, project, name, quotas):
257     """
258     Update a project name
259
260     :param ctx:
261     :param project: id or name of the project to modify
262     :param name:  new name for the project
263     :param quotas:  change quotas of the project
264     :return:
265     """
266 0     logger.debug("")
267 0     project_changes = {}
268 0     if name:
269 0         project_changes["name"] = name
270 0     quotas_dict = _process_project_quotas(quotas)
271 0     if quotas_dict:
272 0         project_changes["quotas"] = quotas_dict
273
274 0     utils.check_client_version(ctx.obj, ctx.command.name)
275 0     ctx.obj.project.update(project, project_changes)
276
277
278 ####################
279 # User mgmt operations
280 ####################
281
282
283 1 @click.command(name="user-create", short_help="creates a new user")
284 1 @click.argument("username")
285 1 @click.option(
286     "--password",
287     prompt=True,
288     hide_input=True,
289     confirmation_prompt=True,
290     help="user password",
291 )
292 1 @click.option(
293     "--projects",
294     # prompt="Comma separate list of projects",
295     multiple=True,
296     callback=lambda ctx, param, value: "".join(value).split(",")
297     if all(len(x) == 1 for x in value)
298     else value,
299     help="list of project ids that the user belongs to",
300 )
301 1 @click.option(
302     "--project-role-mappings",
303     "project_role_mappings",
304     default=None,
305     multiple=True,
306     help="assign role(s) in a project. Can be used several times: 'project,role1[,role2,...]'",
307 )
308 1 @click.option("--domain-name", "domain_name", default=None, help="assign to a domain")
309 1 @click.pass_context
310 1 def user_create(ctx, username, password, projects, project_role_mappings, domain_name):
311     """Creates a new user
312
313     \b
314     USERNAME: name of the user
315     PASSWORD: password of the user
316     PROJECTS: projects assigned to user (internal only)
317     PROJECT_ROLE_MAPPING: roles in projects assigned to user (keystone)
318     DOMAIN_NAME: optional domain name for the user when keystone authentication is used
319     """
320 0     logger.debug("")
321 0     user = {}
322 0     user["username"] = username
323 0     user["password"] = password
324 0     user["projects"] = projects
325 0     user["project_role_mappings"] = project_role_mappings
326 0     if domain_name:
327 0         user["domain_name"] = domain_name
328
329 0     utils.check_client_version(ctx.obj, ctx.command.name)
330 0     ctx.obj.user.create(username, user)
331
332
333 1 @click.command(name="user-update", short_help="updates user information")
334 1 @click.argument("username")
335 1 @click.option(
336     "--password",
337     # prompt=True,
338     # hide_input=True,
339     # confirmation_prompt=True,
340     help="user password",
341 )
342 1 @click.option("--set-username", "set_username", default=None, help="change username")
343 1 @click.option(
344     "--set-project",
345     "set_project",
346     default=None,
347     multiple=True,
348     help="create/replace the roles for this project: 'project,role1[,role2,...]'",
349 )
350 1 @click.option(
351     "--remove-project",
352     "remove_project",
353     default=None,
354     multiple=True,
355     help="removes project from user: 'project'",
356 )
357 1 @click.option(
358     "--add-project-role",
359     "add_project_role",
360     default=None,
361     multiple=True,
362     help="assign role(s) in a project. Can be used several times: 'project,role1[,role2,...]'",
363 )
364 1 @click.option(
365     "--remove-project-role",
366     "remove_project_role",
367     default=None,
368     multiple=True,
369     help="remove role(s) in a project. Can be used several times: 'project,role1[,role2,...]'",
370 )
371 1 @click.option("--change_password", "change_password", help="user's current password")
372 1 @click.option(
373     "--new_password",
374     "new_password",
375     help="user's new password to update in expiry condition",
376 )
377 1 @click.pass_context
378 1 def user_update(
379     ctx,
380     username,
381     password,
382     set_username,
383     set_project,
384     remove_project,
385     add_project_role,
386     remove_project_role,
387     change_password,
388     new_password,
389 ):
390     """Update a user information
391
392     \b
393     USERNAME: name of the user
394     PASSWORD: new password
395     SET_USERNAME: new username
396     SET_PROJECT: creating mappings for project/role(s)
397     REMOVE_PROJECT: deleting mappings for project/role(s)
398     ADD_PROJECT_ROLE: adding mappings for project/role(s)
399     REMOVE_PROJECT_ROLE: removing mappings for project/role(s)
400     CHANGE_PASSWORD: user's current password to change
401     NEW_PASSWORD: user's new password to update in expiry condition
402     """
403 0     logger.debug("")
404 0     user = {}
405 0     user["password"] = password
406 0     user["username"] = set_username
407 0     user["set-project"] = set_project
408 0     user["remove-project"] = remove_project
409 0     user["add-project-role"] = add_project_role
410 0     user["remove-project-role"] = remove_project_role
411 0     user["change_password"] = change_password
412 0     user["new_password"] = new_password
413
414 0     utils.check_client_version(ctx.obj, ctx.command.name)
415 0     ctx.obj.user.update(username, user)
416 0     if not user.get("change_password"):
417 0         ctx.obj.user.update(username, user)
418     else:
419 0         ctx.obj.user.update(username, user, pwd_change=True)
420
421
422 1 @click.command(name="user-delete", short_help="deletes a user")
423 1 @click.argument("name")
424 # @click.option('--force', is_flag=True, help='forces the deletion bypassing pre-conditions')
425 1 @click.pass_context
426 1 def user_delete(ctx, name):
427     """deletes a user
428
429     \b
430     NAME: name or ID of the user to be deleted
431     """
432 0     logger.debug("")
433 0     utils.check_client_version(ctx.obj, ctx.command.name)
434 0     ctx.obj.user.delete(name)
435
436
437 1 @click.command(name="user-list", short_help="list all users")
438 1 @click.option(
439     "--filter",
440     default=None,
441     multiple=True,
442     help="restricts the list to the users matching the filter",
443 )
444 1 @click.pass_context
445 1 def user_list(ctx, filter):
446     """list all users"""
447 0     utils.check_client_version(ctx.obj, ctx.command.name)
448 0     if filter:
449 0         filter = "&".join(filter)
450 0     resp = ctx.obj.user.list(filter)
451 0     table = PrettyTable(["name", "id"])
452 0     for user in resp:
453 0         table.add_row([user["username"], user["_id"]])
454 0     table.align = "l"
455 0     print(table)
456
457
458 1 @click.command(name="user-show", short_help="shows the details of a user")
459 1 @click.argument("name")
460 1 @click.pass_context
461 1 def user_show(ctx, name):
462     """shows the details of a user
463
464     NAME: name or ID of the user
465     """
466 0     logger.debug("")
467 0     utils.check_client_version(ctx.obj, ctx.command.name)
468 0     resp = ctx.obj.user.get(name)
469 0     if "password" in resp:
470 0         resp["password"] = "********"
471
472 0     table = PrettyTable(["key", "attribute"])
473 0     for k, v in resp.items():
474 0         table.add_row([k, json.dumps(v, indent=2)])
475 0     table.align = "l"
476 0     print(table)