Add tenant commands to cli

* Adds tenant-list, tenant-get and tenant-update to keystone command
* Removes tenant-enable and tenant-disable
* Fixes more overlap in cli args, clean up command args, particularly
  removing nargs from arguments that are not optional.
* Fixes bug 932235

Change-Id: I1aafec1b2a3943e0f6c86f0228ab29f181a7ffce
This commit is contained in:
Dean Troyer
2012-02-02 23:16:01 -06:00
parent 0cc939c904
commit bbd2561507
3 changed files with 145 additions and 74 deletions

View File

@@ -21,11 +21,8 @@ from keystoneclient import utils
CLIENT_CLASS = client.Client CLIENT_CLASS = client.Client
@utils.arg('tenant', @utils.arg('tenant', metavar='<tenant_id>', nargs='?',
metavar='<tenant_id>', help='ID of Tenant. (Optional)', default=None)
help='ID of Tenant. (Optional)',
nargs='?',
default=None)
def do_user_list(kc, args): def do_user_list(kc, args):
users = kc.users.list(tenant_id=args.tenant) users = kc.users.list(tenant_id=args.tenant)
utils.print_list(users, ['id', 'enabled', 'email', 'name', 'tenantId']) utils.print_list(users, ['id', 'enabled', 'email', 'name', 'tenantId'])
@@ -48,8 +45,7 @@ def do_user_create(kc, args):
utils.print_dict(user._info) utils.print_dict(user._info)
@utils.arg('id', metavar='<user_id>', nargs='?', @utils.arg('id', metavar='<user_id>', help='User ID to update.')
help='User ID to update.')
@utils.arg('name', metavar='<name>', nargs='?', @utils.arg('name', metavar='<name>', nargs='?',
help='New desired user name.') help='New desired user name.')
@utils.arg('email', metavar='<email>', nargs='?', @utils.arg('email', metavar='<email>', nargs='?',
@@ -65,7 +61,7 @@ def do_user_enable(kc, args):
kc.users.update_enabled(args.id, True) kc.users.update_enabled(args.id, True)
print 'User has been enabled.' print 'User has been enabled.'
except: except:
'Unable to enable user.' print 'Unable to enable user.'
@utils.arg('id', metavar='<user_id>', nargs='?', help='User ID to disable.') @utils.arg('id', metavar='<user_id>', nargs='?', help='User ID to disable.')
@@ -74,34 +70,44 @@ def do_user_disable(kc, args):
kc.users.update_enabled(args.id, False) kc.users.update_enabled(args.id, False)
print 'User has been disabled.' print 'User has been disabled.'
except: except:
'Unable to disable user.' print 'Unable to disable user.'
@utils.arg('id', metavar='<user_id>', nargs='?', help='User ID to update.') @utils.arg('id', metavar='<user_id>', help='User ID to update.')
@utils.arg('password', metavar='<password>', nargs='?', @utils.arg('password', metavar='<password>', help='New desired password.')
help='New desired password.')
def do_user_update_password(kc, args): def do_user_update_password(kc, args):
try: try:
kc.users.update_password(args.id, args.password) kc.users.update_password(args.id, args.password)
print 'User password has been udpated.' print 'User password has been udpated.'
except: except:
'Unable to update users password.' print 'Unable to update users password.'
@utils.arg('id', metavar='<user_id>', nargs='?', help='User ID to delete.') @utils.arg('id', metavar='<user_id>', help='User ID to delete.')
def do_user_delete(kc, args): def do_user_delete(kc, args):
try: try:
kc.users.delete(args.id) kc.users.delete(args.id)
print 'User has been deleted.' print 'User has been deleted.'
except: except:
'Unable to delete user.' print 'Unable to delete user.'
@utils.arg('--name', metavar='<name>', nargs='?', def do_tenant_list(kc, args):
tenants = kc.tenants.list()
utils.print_list(tenants, ['id', 'name', 'enabled'])
@utils.arg('id', metavar='<tenant_id>', help='Tenant ID to show.')
def do_tenant_get(kc, args):
tenant = kc.tenants.get(args.id)
utils.print_dict(tenant._info)
@utils.arg('--name', metavar='<tenant_name>', nargs='?',
help='Desired name of new tenant.') help='Desired name of new tenant.')
@utils.arg('--description', metavar='<description>', nargs='?', default=None, @utils.arg('--description', metavar='<description>', nargs='?', default=None,
help='Useful description of new tenant (optional, default is None)') help='Useful description of new tenant (optional, default is None)')
@utils.arg('--enabled', metavar='<enabled>', nargs='?', default=True, @utils.arg('--enabled', metavar='<True/False>', nargs='?', default=True,
help='Enable user immediately (Optional, default True)') help='Enable user immediately (Optional, default True)')
def do_tenant_create(kc, args): def do_tenant_create(kc, args):
tenant = kc.tenants.create(args.name, tenant = kc.tenants.create(args.name,
@@ -110,36 +116,48 @@ def do_tenant_create(kc, args):
utils.print_dict(tenant._info) utils.print_dict(tenant._info)
@utils.arg('id', metavar='<tenant_id>', nargs='?', help='Tenant ID to enable.') @utils.arg('--name', metavar='<tenant_name>', nargs='?',
def do_tenant_enable(kc, args): help='Desired name of tenant.')
@utils.arg('--description', metavar='<description>', nargs='?', default=None,
help='Desired description of tenant')
@utils.arg('--enabled', metavar='<True/False>', nargs='?', const=True,
help='Enable/disable tenant')
@utils.arg('id', metavar='<tenant_id>', help='Tenant ID to update')
def do_tenant_update(kc, args):
"""Update tenant name, description, enabled status"""
tenant = kc.tenants.get(args.id)
kwargs = {}
if args.name:
kwargs.update({'name': args.name})
if args.description:
kwargs.update({'description': args.description})
if args.enabled:
new_enable = args.enabled.lower() in ['true', 'yes', '1']
kwargs.update({'enabled': new_enable})
if kwargs == {}:
print "Tenant not updated, no arguments present."
return
try: try:
kc.tenants.update(args.id, enabled=True) tenant.update(**kwargs)
print 'Tenant has been enabled.' print 'Tenant has been updated.'
except: except Exception, e:
'Unable to enable tenant.' print 'Unable to update tenant: %s' % e
@utils.arg('id', metavar='<tenant_id>', nargs='?', help='Tenant ID to disable') @utils.arg('id', metavar='<tenant_id>', help='Tenant ID to delete')
def do_tenant_disable(kc, args):
try:
kc.tenants.update_enabled(args.id, enabled=False)
print 'Tenant has been disabled.'
except:
'Unable to disable tenant.'
@utils.arg('id', metavar='<tenant_id>', nargs='?', help='Tenant ID to delete')
def do_tenant_delete(kc, args): def do_tenant_delete(kc, args):
try: try:
kc.tenants.delete(args.id) kc.tenants.delete(args.id)
print 'Tenant has been deleted.' print 'Tenant has been deleted.'
except: except:
'Unable to delete tenant.' print 'Unable to delete tenant.'
@utils.arg('--name', metavar='<name>', nargs='?', @utils.arg('--name', metavar='<name>',
help='Desired name of service. (unique)') help='Desired name of service. (unique)')
@utils.arg('--type', metavar='<type>', nargs='?', @utils.arg('--type', metavar='<type>',
help='Possible service types: identity, compute, network, \ help='Possible service types: identity, compute, network, \
image, or object-store.') image, or object-store.')
@utils.arg('--description', metavar='<service_description>', nargs='?', @utils.arg('--description', metavar='<service_description>', nargs='?',
@@ -156,19 +174,13 @@ def do_service_list(kc, args):
utils.print_list(services, ['id', 'name', 'type', 'description']) utils.print_list(services, ['id', 'name', 'type', 'description'])
@utils.arg('id', @utils.arg('id', metavar='<service_id>', help='ID of Service to retrieve.')
metavar='<service_id>',
help='ID of Service to retrieve.',
nargs='?')
def do_service_get(kc, args): def do_service_get(kc, args):
service = kc.services.get(args.id) service = kc.services.get(args.id)
utils.print_dict(service._info) utils.print_dict(service._info)
@utils.arg('id', @utils.arg('id', metavar='<service_id>', help='ID of Service to delete')
metavar='<service_id>',
help='ID of Service to delete',
nargs='?')
def do_service_delete(kc, args): def do_service_delete(kc, args):
try: try:
kc.services.delete(args.id) kc.services.delete(args.id)
@@ -182,20 +194,19 @@ def do_role_list(kc, args):
utils.print_list(roles, ['id', 'name']) utils.print_list(roles, ['id', 'name'])
@utils.arg('id', metavar='<role_id>', help='ID of Role to fetch.', nargs='?') @utils.arg('id', metavar='<role_id>', help='ID of Role to fetch.')
def do_role_get(kc, args): def do_role_get(kc, args):
role = kc.roles.get(args.id) role = kc.roles.get(args.id)
utils.print_dict(role._info) utils.print_dict(role._info)
@utils.arg('--name', metavar='<name>', nargs='?', @utils.arg('--name', metavar='<name>', help='Desired name of new role.')
help='Desired name of new role.')
def do_role_create(kc, args): def do_role_create(kc, args):
role = kc.roles.create(args.name) role = kc.roles.create(args.name)
utils.print_dict(role._info) utils.print_dict(role._info)
@utils.arg('id', metavar='<role_id>', help='ID of Role to delete.', nargs='?') @utils.arg('id', metavar='<role_id>', help='ID of Role to delete.')
def do_role_delete(kc, args): def do_role_delete(kc, args):
try: try:
kc.roles.delete(args.id) kc.roles.delete(args.id)
@@ -205,30 +216,31 @@ def do_role_delete(kc, args):
# TODO(jakedahn): refactor this to allow role, user, and tenant names. # TODO(jakedahn): refactor this to allow role, user, and tenant names.
@utils.arg('user_id', metavar='<user_id>', help='ID of User', nargs='?') @utils.arg('user_id', metavar='<user_id>', help='ID of User')
@utils.arg('role_id', metavar='<role_id>', help='ID of Role', nargs='?') @utils.arg('role_id', metavar='<role_id>', help='ID of Role')
@utils.arg('tenant_id', metavar='<tenant_id>', help='ID of Tenant', nargs='?') @utils.arg('tenant', metavar='<tenant_id>',
help='ID of Tenant', nargs='?')
def do_add_user_role(kc, args): def do_add_user_role(kc, args):
kc.roles.add_user_role(args.user_id, args.role_id, args.tenant_id) kc.roles.add_user_role(args.user_id, args.role_id, args.tenant)
# TODO(jakedahn): refactor this to allow role, user, and tenant names. # TODO(jakedahn): refactor this to allow role, user, and tenant names.
@utils.arg('user_id', metavar='<user_id>', help='ID of User', nargs='?') @utils.arg('user_id', metavar='<user_id>', help='ID of User')
@utils.arg('role_id', metavar='<role_id>', help='ID of Role', nargs='?') @utils.arg('role_id', metavar='<role_id>', help='ID of Role')
@utils.arg('tenant_id', metavar='<tenant_id>', help='ID of Tenant', nargs='?') @utils.arg('tenant', metavar='<tenant_id>',
help='ID of Tenant', nargs='?')
def do_remove_user_role(kc, args): def do_remove_user_role(kc, args):
kc.roles.remove_user_role(args.user_id, args.role_id, args.tenant_id) kc.roles.remove_user_role(args.user_id, args.role_id, args.tenant)
@utils.arg('--tenant_id', metavar='<tenant_id>', help='ID of Tenant', @utils.arg('--tenant_id', metavar='<tenant_id>', help='ID of Tenant')
nargs='?') @utils.arg('--user_id', metavar='<user_id>', help='ID of User')
@utils.arg('--user_id', metavar='<user_id>', help='ID of User', nargs='?')
def do_ec2_create_credentials(kc, args): def do_ec2_create_credentials(kc, args):
credentials = kc.ec2.create(args.user_id, args.tenant_id) credentials = kc.ec2.create(args.user_id, args.tenant_id)
utils.print_dict(credentials._info) utils.print_dict(credentials._info)
@utils.arg('user_id', metavar='<user_id>', help='ID of User', nargs='?') @utils.arg('user_id', metavar='<user_id>', help='ID of User')
def do_ec2_list_credentials(kc, args): def do_ec2_list_credentials(kc, args):
credentials = kc.ec2.list(args.user_id) credentials = kc.ec2.list(args.user_id)
for cred in credentials: for cred in credentials:
@@ -236,8 +248,8 @@ def do_ec2_list_credentials(kc, args):
utils.print_list(credentials, ['tenant', 'key', 'secret']) utils.print_list(credentials, ['tenant', 'key', 'secret'])
@utils.arg('user_id', metavar='<user_id>', help='ID of User', nargs='?') @utils.arg('user_id', metavar='<user_id>', help='ID of User')
@utils.arg('key', metavar='<access_key>', help='Access Key', nargs='?') @utils.arg('key', metavar='<access_key>', help='Access Key')
def do_ec2_delete_credentials(kc, args): def do_ec2_delete_credentials(kc, args):
try: try:
kc.ec2.delete(args.user_id, args.key) kc.ec2.delete(args.user_id, args.key)

View File

@@ -26,9 +26,20 @@ class Tenant(base.Resource):
def delete(self): def delete(self):
return self.manager.delete(self) return self.manager.delete(self)
def update(self, description=None, enabled=None): def update(self, name=None, description=None, enabled=None):
# FIXME(ja): set the attributes in this object if successful # Preserve the existing settings; keystone legacy resets these?
return self.manager.update(self.id, description, enabled) new_name = name if name else self.name
new_description = description if description else self.description
new_enabled = enabled if enabled else self.enabled
try:
retval = self.manager.update(self.id, tenant_name=new_name,
description=new_description,
enabled=new_enabled)
self = retval
except Exception, e:
retval = None
return retval
def add_user(self, user, role): def add_user(self, user, role):
return self.manager.api.roles.add_user_to_tenant(self.id, return self.manager.api.roles.add_user_to_tenant(self.id,

View File

@@ -3,20 +3,29 @@ import mock
import httplib2 import httplib2
from keystoneclient import shell as openstack_shell from keystoneclient import shell as openstack_shell
from keystoneclient.v2_0 import shell as shell_v2_0
from keystoneclient import exceptions from keystoneclient import exceptions
from tests import utils from tests import utils
DEFAULT_USERNAME = 'username'
DEFAULT_PASSWORD = 'password'
DEFAULT_TENANT_ID = 'tenant_id'
DEFAULT_TENANT_NAME = 'tenant_name'
DEFAULT_AUTH_URL = 'http://127.0.0.1:5000/v2.0/'
class ShellTest(utils.TestCase): class ShellTest(utils.TestCase):
# Patch os.environ to avoid required auth info. # Patch os.environ to avoid required auth info.
def setUp(self): def setUp(self):
global _old_env global _old_env
fake_env = { fake_env = {
'OS_USERNAME': 'username', 'OS_USERNAME': DEFAULT_USERNAME,
'OS_PASSWORD': 'password', 'OS_PASSWORD': DEFAULT_PASSWORD,
'OS_TENANT_ID': 'tenant_id', 'OS_TENANT_ID': DEFAULT_TENANT_ID,
'OS_AUTH_URL': 'http://127.0.0.1:5000/v2.0', 'OS_TENANT_NAME': DEFAULT_TENANT_NAME,
'OS_AUTH_URL': DEFAULT_AUTH_URL,
} }
_old_env, os.environ = os.environ, fake_env.copy() _old_env, os.environ = os.environ, fake_env.copy()
@@ -37,3 +46,42 @@ class ShellTest(utils.TestCase):
httplib2.debuglevel = 0 httplib2.debuglevel = 0
shell('--debug help') shell('--debug help')
assert httplib2.debuglevel == 1 assert httplib2.debuglevel == 1
def test_shell_args(self):
do_tenant_mock = mock.MagicMock()
with mock.patch('keystoneclient.v2_0.shell.do_user_list',
do_tenant_mock):
shell('user-list')
assert do_tenant_mock.called
((a, b), c) = do_tenant_mock.call_args
assert (b.auth_url, b.password, b.tenant_id,
b.tenant_name, b.username, b.version) == \
(DEFAULT_AUTH_URL, DEFAULT_PASSWORD, DEFAULT_TENANT_ID,
DEFAULT_TENANT_NAME, DEFAULT_USERNAME, '')
shell('--auth-url http://0.0.0.0:5000/ --password xyzpdq '
'--tenant_id 1234 --tenant_name fred --username barney '
'--version 2.0 user-list')
assert do_tenant_mock.called
((a, b), c) = do_tenant_mock.call_args
assert (b.auth_url, b.password, b.tenant_id,
b.tenant_name, b.username, b.version) == \
('http://0.0.0.0:5000/', 'xyzpdq', '1234',
'fred', 'barney', '2.0')
def test_do_tenant_create(self):
do_tenant_mock = mock.MagicMock()
with mock.patch('keystoneclient.v2_0.shell.do_tenant_create',
do_tenant_mock):
shell('tenant-create')
assert do_tenant_mock.called
# FIXME(dtroyer): how do you test the decorators?
#shell('tenant-create --tenant-name wilma '
# '--description "fred\'s wife"')
#assert do_tenant_mock.called
def test_do_tenant_list(self):
do_tenant_mock = mock.MagicMock()
with mock.patch('keystoneclient.v2_0.shell.do_tenant_list',
do_tenant_mock):
shell('tenant-list')
assert do_tenant_mock.called