Tons of clean up, some new features, some bug fixes
* new function for cleaning up expired tokens * new function to cancel a task directly * lots of clean up * reworked some functions to work with more than one item Change-Id: I21683af24410c7a602c2d5a7fb93f7cbc1f605e5
This commit is contained in:
parent
726a43c9dd
commit
9b84cac78f
|
@ -1,5 +1,4 @@
|
|||
include AUTHORS
|
||||
include babel.cfg
|
||||
include LICENSE
|
||||
include README.md
|
||||
include ChangeLog
|
||||
|
|
|
@ -4,14 +4,12 @@
|
|||
|
||||
Babel>=1.3
|
||||
pbr<2.0,>=1.4
|
||||
argparse
|
||||
iso8601>=0.1.9
|
||||
PrettyTable<0.8,>=0.7
|
||||
oslo.i18n>=1.5.0 # Apache-2.0
|
||||
oslo.serialization>=1.4.0 # Apache-2.0
|
||||
oslo.utils>=2.0.0 # Apache-2.0
|
||||
oslo.i18n>=1.5.0
|
||||
oslo.serialization>=1.4.0
|
||||
oslo.utils>=2.0.0
|
||||
python-keystoneclient>=1.6.0
|
||||
python-swiftclient>=2.2.0
|
||||
PyYAML>=3.1.0
|
||||
requests>=2.5.2
|
||||
six>=1.9.0
|
||||
|
|
|
@ -35,9 +35,9 @@ class Client(object):
|
|||
"""Initialize a new client for the Stacktask v1 API."""
|
||||
self.http_client = http._construct_http_client(*args, **kwargs)
|
||||
|
||||
self.users = users.UsersManager(self.http_client)
|
||||
self.user_roles = roles.UserRolesManager(self.http_client)
|
||||
self.managed_roles = roles.ManagedRolesManager(self.http_client)
|
||||
self.users = users.UserManager(self.http_client)
|
||||
self.user_roles = roles.UserRoleManager(self.http_client)
|
||||
self.managed_roles = roles.ManagedRoleManager(self.http_client)
|
||||
self.tokens = tokens.TokenManager(self.http_client)
|
||||
self.tasks = tasks.TaskManager(self.http_client)
|
||||
self.notifications = notifications.NotificationManager(
|
||||
|
|
|
@ -24,7 +24,7 @@ class Notification(base.Resource):
|
|||
class NotificationManager(base.ManagerWithFind):
|
||||
resource_class = Notification
|
||||
|
||||
def show(self, note_id):
|
||||
def get(self, note_id):
|
||||
return self._get("/notifications/%s" % base.getid(note_id))
|
||||
|
||||
def list(self, filters, **kwargs):
|
||||
|
|
|
@ -18,21 +18,21 @@ from stacktaskclient.openstack.common.apiclient import base
|
|||
from stacktaskclient import exc
|
||||
|
||||
|
||||
class Roles(base.Resource):
|
||||
class Role(base.Resource):
|
||||
pass
|
||||
|
||||
|
||||
class ManagableRoles(base.Resource):
|
||||
class ManagableRole(base.Resource):
|
||||
pass
|
||||
|
||||
|
||||
class ManagedRolesManager(base.ManagerWithFind):
|
||||
resource_class = ManagableRoles
|
||||
class ManagedRoleManager(base.ManagerWithFind):
|
||||
resource_class = ManagableRole
|
||||
|
||||
def list(self, **kwargs):
|
||||
"""Get a list of roles that can be managed.
|
||||
|
||||
:rtype: list of :class:`Roles`
|
||||
:rtype: list of :class:`Role`
|
||||
"""
|
||||
params = {}
|
||||
url = '/openstack/roles?%(params)s' % {
|
||||
|
@ -40,7 +40,7 @@ class ManagedRolesManager(base.ManagerWithFind):
|
|||
}
|
||||
return self._list(url, 'roles')
|
||||
|
||||
def show(self, role_id):
|
||||
def get(self, role_id):
|
||||
"""
|
||||
Get a role by role_id
|
||||
"""
|
||||
|
@ -53,8 +53,8 @@ class ManagedRolesManager(base.ManagerWithFind):
|
|||
raise exc.NotFound()
|
||||
|
||||
|
||||
class UserRolesManager(base.BaseManager):
|
||||
resource_class = Roles
|
||||
class UserRoleManager(base.BaseManager):
|
||||
resource_class = Role
|
||||
|
||||
def list(self, **kwargs):
|
||||
"""List roles for a given user"""
|
||||
|
@ -62,15 +62,20 @@ class UserRolesManager(base.BaseManager):
|
|||
url = '/openstack/users/%s/roles' % kwargs['user']
|
||||
return self._list(url, 'roles')
|
||||
|
||||
def add(self, user, role, tenant=None):
|
||||
def add(self, user, role=None, roles=None):
|
||||
"""Add a role to a user"""
|
||||
# TODO: resolve the roles and users into id's
|
||||
# user_id = base.getid(user)
|
||||
user_id = user
|
||||
# role_id = role
|
||||
params = {
|
||||
'roles': [role]
|
||||
}
|
||||
if role:
|
||||
params = {
|
||||
'roles': [role]
|
||||
}
|
||||
elif roles:
|
||||
params = {
|
||||
'roles': roles
|
||||
}
|
||||
|
||||
route = '/openstack/users/%s/roles'
|
||||
url = route % (user_id)
|
||||
|
@ -82,12 +87,16 @@ class UserRolesManager(base.BaseManager):
|
|||
|
||||
return True
|
||||
|
||||
def remove(self, user_id, role_id, tenant=None):
|
||||
"""Remove a role from a user"""
|
||||
# TODO: perhaps support multiple roles?
|
||||
params = {
|
||||
'roles': [role_id]
|
||||
}
|
||||
def remove(self, user_id, role=None, roles=None):
|
||||
"""Remove a role or roles from a user"""
|
||||
if role:
|
||||
params = {
|
||||
'roles': [role]
|
||||
}
|
||||
elif roles:
|
||||
params = {
|
||||
'roles': roles
|
||||
}
|
||||
|
||||
route = '/openstack/users/%s/roles'
|
||||
url = route % (user_id)
|
||||
|
|
|
@ -47,16 +47,12 @@ def do_task_show(sc, args):
|
|||
Get individual task.
|
||||
"""
|
||||
try:
|
||||
task = sc.tasks.show(task_id=args.task_id)
|
||||
task = sc.tasks.get(task_id=args.task_id)
|
||||
|
||||
formatters = {
|
||||
'uuid': utils.text_wrap_formatter,
|
||||
'task_type': utils.text_wrap_formatter,
|
||||
'created_on': utils.text_wrap_formatter,
|
||||
'approved_on': utils.text_wrap_formatter,
|
||||
'completed_on': utils.text_wrap_formatter,
|
||||
'actions': utils.json_formatter,
|
||||
'action_notes': utils.json_formatter
|
||||
'action_notes': utils.json_formatter,
|
||||
'keystone_user': utils.json_formatter
|
||||
}
|
||||
utils.print_dict(task.to_dict(), formatters=formatters)
|
||||
except exc.HTTPNotFound:
|
||||
|
@ -70,7 +66,7 @@ def do_task_show(sc, args):
|
|||
help=_('Filters to use when getting the list.'))
|
||||
def do_task_list(sc, args):
|
||||
"""
|
||||
Show all tasks in the current tenant
|
||||
Show all tasks in the current project
|
||||
"""
|
||||
fields = [
|
||||
'uuid', 'task_type', 'created_on',
|
||||
|
@ -132,7 +128,24 @@ def do_task_reissue_token(sc, args):
|
|||
print e.message
|
||||
else:
|
||||
print 'Success:', ' '.join(resp.notes)
|
||||
do_user_list(sc, args)
|
||||
do_task_show(sc, args)
|
||||
|
||||
|
||||
@utils.arg('task_id', metavar='<taskid>',
|
||||
help=_('Task ID.'))
|
||||
def do_task_cancel(sc, args):
|
||||
"""
|
||||
Canel the task.
|
||||
"""
|
||||
try:
|
||||
resp = sc.tasks.cancel(args.task_id)
|
||||
except exc.HTTPNotFound as e:
|
||||
print e.message
|
||||
except exc.HTTPBadRequest as e:
|
||||
print e.message
|
||||
else:
|
||||
print 'Success: %s' % resp.json()['notes']
|
||||
do_task_show(sc, args)
|
||||
|
||||
|
||||
# Notifications
|
||||
|
@ -144,13 +157,10 @@ def do_notification_show(sc, args):
|
|||
Get individual notification.
|
||||
"""
|
||||
try:
|
||||
notification = sc.notifications.show(note_id=args.note_id)
|
||||
notification = sc.notifications.get(note_id=args.note_id)
|
||||
|
||||
formatters = {
|
||||
'uuid': utils.text_wrap_formatter,
|
||||
'task': utils.text_wrap_formatter,
|
||||
'notes': utils.json_formatter,
|
||||
'created_on': utils.text_wrap_formatter,
|
||||
'notes': utils.json_formatter
|
||||
}
|
||||
utils.print_dict(notification.to_dict(), formatters=formatters)
|
||||
except exc.HTTPNotFound:
|
||||
|
@ -173,14 +183,14 @@ def do_notification_list(sc, args):
|
|||
utils.print_list(notification_list, fields)
|
||||
|
||||
|
||||
@utils.arg('note_id', metavar='<noteid>',
|
||||
help=_('Notification ID.'))
|
||||
@utils.arg('note_ids', metavar='<noteids>', nargs='+',
|
||||
help=_('Notification IDs to acknowledge.'))
|
||||
def do_notification_acknowledge(sc, args):
|
||||
"""
|
||||
Acknowledge notification.
|
||||
"""
|
||||
try:
|
||||
resp = sc.notifications.acknowledge(note_id=args.note_id)
|
||||
resp = sc.notifications.acknowledge(note_list=args.note_ids)
|
||||
|
||||
print 'Success:', ' '.join(resp.notes)
|
||||
except exc.HTTPNotFound:
|
||||
|
@ -213,7 +223,7 @@ def do_token_show(sc, args):
|
|||
including the arguments required for submit
|
||||
"""
|
||||
try:
|
||||
token = sc.tokens.show(args.token)
|
||||
token = sc.tokens.get(args.token)
|
||||
except exc.HTTPNotFound as e:
|
||||
print e.message
|
||||
print "Requested Token was not found."
|
||||
|
@ -251,7 +261,7 @@ def do_token_submit(sc, args):
|
|||
Submit this token to finalise Task.
|
||||
"""
|
||||
try:
|
||||
sc.tokens.submit(args.token, args.data)
|
||||
sc.tokens.submit(args.token, json.loads(args.data))
|
||||
except exc.HTTPNotFound as e:
|
||||
print e.message
|
||||
print "Requested token was not found."
|
||||
|
@ -262,6 +272,25 @@ def do_token_submit(sc, args):
|
|||
print "Token submitted."
|
||||
|
||||
|
||||
def do_token_clear_expired(sc, args):
|
||||
"""
|
||||
Clear all expired tokens.
|
||||
|
||||
This is an admin only endpoint.
|
||||
"""
|
||||
try:
|
||||
resp = sc.tokens.clear_expired()
|
||||
except exc.HTTPNotFound as e:
|
||||
print e.message
|
||||
except exc.HTTPBadRequest as e:
|
||||
print e.message
|
||||
else:
|
||||
print 'Success: %s' % resp.json()['notes']
|
||||
fields = ['token', 'task', 'created_on', 'expires']
|
||||
token_list = sc.tokens.list({})
|
||||
utils.print_list(token_list, fields)
|
||||
|
||||
|
||||
# User
|
||||
|
||||
@utils.arg('user_id', metavar='<userid>',
|
||||
|
@ -280,39 +309,30 @@ def do_user_show(sc, args):
|
|||
|
||||
|
||||
def do_user_list(sc, args):
|
||||
"""List all users in tenant"""
|
||||
"""List all users in project"""
|
||||
kwargs = {}
|
||||
fields = ['id', 'email', 'name', 'roles', 'cohort', 'status']
|
||||
|
||||
tenant_users = sc.users.list(**kwargs)
|
||||
utils.print_list(tenant_users, fields, sortby_index=1)
|
||||
project_users = sc.users.list(**kwargs)
|
||||
utils.print_list(project_users, fields, sortby_index=1)
|
||||
|
||||
|
||||
@utils.arg('--roles', metavar='<roles>', nargs='+', required=True,
|
||||
help=_('Roles to grant to new user'))
|
||||
@utils.arg('--tenant', '--tenant-id', metavar='<tenant>', required=True,
|
||||
help=_('Invite to a particular tenant id'))
|
||||
@utils.arg('username', metavar='<username>', default=None,
|
||||
@utils.arg('--username', metavar='<username>', default=None,
|
||||
help=_('username of user to invite'))
|
||||
@utils.arg('email', metavar='<email>',
|
||||
@utils.arg('--email', metavar='<email>', required=True,
|
||||
help=_('Email address of user to invite'))
|
||||
def do_user_invite(sc, args):
|
||||
"""
|
||||
Invites a user to become a member of a tenant.
|
||||
Invites a user to become a member of a project.
|
||||
User does not need to have an existing openstack account.
|
||||
"""
|
||||
roles = args.roles or ['Member']
|
||||
|
||||
if args.tenant:
|
||||
# utils.find_resource(sc.tenants, args.tenant).id
|
||||
tenant_id = args.tenant
|
||||
else:
|
||||
tenant_id = None
|
||||
|
||||
try:
|
||||
sc.users.invite(
|
||||
username=args.username, email=args.email,
|
||||
tenant_id=tenant_id, role_list=roles)
|
||||
username=args.username, email=args.email, role_list=roles)
|
||||
except exc.HTTPNotFound as e:
|
||||
print e.message
|
||||
print e
|
||||
|
@ -320,7 +340,7 @@ def do_user_invite(sc, args):
|
|||
print "400 Bad Request: " + e.message
|
||||
print e
|
||||
else:
|
||||
print "Invitation sent. (todo: print only pending users)"
|
||||
print "Invitation sent."
|
||||
do_user_list(sc, args)
|
||||
|
||||
|
||||
|
@ -353,28 +373,22 @@ def do_user_role_list(sc, args):
|
|||
help=_('Name or ID of user.'))
|
||||
@utils.arg('--role', '--role-id', metavar='<role>', required=True,
|
||||
help=_('Name or ID of role.'))
|
||||
@utils.arg('--tenant', '--tenant-id', metavar='<tenant>',
|
||||
help=_('Name or ID of tenant.'))
|
||||
def do_user_role_add(sc, args):
|
||||
"""Add a role to user"""
|
||||
user = utils.find_resource(sc.users, args.user)
|
||||
role = utils.find_resource(sc.managed_roles, args.role)
|
||||
if sc.user_roles.add(user.id, role.name):
|
||||
do_user_role_list(sc, args)
|
||||
if sc.user_roles.add(args.user, role=role.name):
|
||||
do_user_list(sc, args)
|
||||
|
||||
|
||||
@utils.arg('--user', '--user-id', metavar='<user>',
|
||||
help=_('Name or ID of user.'))
|
||||
@utils.arg('--role', '--role-id', metavar='<role>', required=True,
|
||||
help=_('Name or ID of role.'))
|
||||
@utils.arg('--tenant', '--tenant-id', metavar='<tenant>',
|
||||
help=_('Name or ID of tenant.'))
|
||||
def do_user_role_remove(sc, args):
|
||||
"""Remove a role from a user"""
|
||||
user = utils.find_resource(sc.users, args.user)
|
||||
role = utils.find_resource(sc.managed_roles, args.role)
|
||||
if sc.user_roles.remove(user.id, role.name):
|
||||
do_user_role_list(sc, args)
|
||||
if sc.user_roles.remove(args.user, role=role.name):
|
||||
do_user_list(sc, args)
|
||||
|
||||
|
||||
@utils.arg('email', metavar='<email>',
|
||||
|
@ -392,7 +406,7 @@ def do_user_password_reset(sc, args):
|
|||
|
||||
|
||||
def do_managed_role_list(sc, args):
|
||||
"""List roles that may be managed in a given tenant"""
|
||||
"""List roles that may be managed in a given project"""
|
||||
fields = ['id', 'name']
|
||||
kwargs = {}
|
||||
roles = sc.managed_roles.list(**kwargs)
|
||||
|
@ -404,5 +418,9 @@ def do_managed_role_list(sc, args):
|
|||
def do_status(sc, args):
|
||||
"""Requests server status endpoint and returns details of the api server"""
|
||||
status = sc.status.get()
|
||||
print json.dumps(status, sort_keys=True,
|
||||
indent=4, separators=(',', ': '))
|
||||
if status.status_code != 200:
|
||||
print "Failed: %s" % status.reason
|
||||
return
|
||||
print json.dumps(
|
||||
status.json(), sort_keys=True,
|
||||
indent=4, separators=(',', ': '))
|
||||
|
|
|
@ -19,5 +19,4 @@ class StatusManager(base.BaseManager):
|
|||
|
||||
def get(self):
|
||||
url = '/status'
|
||||
body = self.client.get(url).json()
|
||||
return body
|
||||
return self.client.get(url)
|
||||
|
|
|
@ -24,7 +24,7 @@ class Task(base.Resource):
|
|||
class TaskManager(base.ManagerWithFind):
|
||||
resource_class = Task
|
||||
|
||||
def show(self, task_id):
|
||||
def get(self, task_id):
|
||||
return self._get("/tasks/%s" % base.getid(task_id))
|
||||
|
||||
def list(self, filters, **kwargs):
|
||||
|
|
|
@ -28,7 +28,7 @@ class TokenParam(base.Resource):
|
|||
class TokenManager(base.BaseManager):
|
||||
resource_class = Token
|
||||
|
||||
def show(self, token_id):
|
||||
def get(self, token_id):
|
||||
"""Get details on a particular token object"""
|
||||
url = 'tokens/%s' % token_id
|
||||
return self._get(url)
|
||||
|
@ -46,13 +46,17 @@ class TokenManager(base.BaseManager):
|
|||
|
||||
def submit(self, token_id, parameters):
|
||||
url = 'tokens/%s' % token_id
|
||||
json = parameters
|
||||
return self._post(url, json)
|
||||
return self._post(url, parameters)
|
||||
|
||||
def reissue(self, task_id):
|
||||
""" Given a task id, reissues the tokens associated with that task """
|
||||
url = 'tokens'
|
||||
json = {
|
||||
data = {
|
||||
'task': task_id
|
||||
}
|
||||
return self._post(url, json)
|
||||
return self._post(url, data)
|
||||
|
||||
def clear_expired(self):
|
||||
"""Clear all expired tokens."""
|
||||
url = '/tokens?'
|
||||
return self._delete(url)
|
||||
|
|
|
@ -18,9 +18,9 @@ from six.moves.urllib import parse
|
|||
from stacktaskclient.openstack.common.apiclient import base
|
||||
|
||||
|
||||
class Users(base.Resource):
|
||||
class User(base.Resource):
|
||||
def __repr__(self):
|
||||
return "<Users %s>" % self._info
|
||||
return "<User %s>" % self._info
|
||||
|
||||
def invite(self, **fields):
|
||||
return self.manager.create(self.identifier, **fields)
|
||||
|
@ -40,8 +40,8 @@ class Users(base.Resource):
|
|||
return '%s/%s' % (self.stack_name, self.id)
|
||||
|
||||
|
||||
class UsersManager(base.ManagerWithFind):
|
||||
resource_class = Users
|
||||
class UserManager(base.ManagerWithFind):
|
||||
resource_class = User
|
||||
|
||||
def get(self, user):
|
||||
return self._get("/openstack/users/%s" % base.getid(user))
|
||||
|
@ -52,7 +52,7 @@ class UsersManager(base.ManagerWithFind):
|
|||
:param limit: maximum number of users to return
|
||||
:param marker: begin returning users that appear later in the user
|
||||
list than that represented by this user id
|
||||
:rtype: list of :class:`Users`
|
||||
:rtype: list of :class:`User`
|
||||
"""
|
||||
def paginate(params):
|
||||
'''Paginate users, even if more than API limit.'''
|
||||
|
@ -81,13 +81,12 @@ class UsersManager(base.ManagerWithFind):
|
|||
|
||||
return paginate(params)
|
||||
|
||||
def invite(self, username, email, role_list, tenant_id=None):
|
||||
""" Invite a user to the current tenant. """
|
||||
def invite(self, username, email, role_list):
|
||||
""" Invite a user to the current project. """
|
||||
|
||||
fields = {
|
||||
'username': username,
|
||||
'email': email,
|
||||
'project_id': tenant_id,
|
||||
'roles': role_list
|
||||
}
|
||||
self.client.post('openstack/users', data=fields)
|
||||
|
|
Loading…
Reference in New Issue