Merge "Add instance name as parameter to CLI"

This commit is contained in:
Jenkins
2014-12-19 11:50:33 +00:00
committed by Gerrit Code Review
10 changed files with 301 additions and 108 deletions

View File

@@ -46,6 +46,8 @@ class BackupManagerTest(testtools.TestCase):
def setUp(self):
super(BackupManagerTest, self).setUp()
self.backups = backups.Backups(mock.Mock())
self.instance_with_id = mock.Mock()
self.instance_with_id.id = 215
def tearDown(self):
super(BackupManagerTest, self).tearDown()
@@ -66,6 +68,14 @@ class BackupManagerTest(testtools.TestCase):
self.backups.create(**args)
create_mock.assert_called_with('/backups', body, 'backup')
def test_create_with_instance_obj(self):
create_mock = mock.Mock()
self.backups._create = create_mock
args = {'name': 'test_backup', 'instance': self.instance_with_id.id}
body = {'backup': args}
self.backups.create('test_backup', self.instance_with_id)
create_mock.assert_called_with('/backups', body, 'backup')
def test_create_incremental(self):
create_mock = mock.Mock()
self.backups._create = create_mock

View File

@@ -0,0 +1,108 @@
# Copyright 2014 Tesora Inc.
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import mock
import testtools
from troveclient.v1 import databases
"""
Unit tests for databases.py
"""
class DatabaseTest(testtools.TestCase):
def setUp(self):
super(DatabaseTest, self).setUp()
self.orig__init = databases.Database.__init__
databases.Database.__init__ = mock.Mock(return_value=None)
self.database = databases.Database()
def tearDown(self):
super(DatabaseTest, self).tearDown()
databases.Database.__init__ = self.orig__init
class DatabasesTest(testtools.TestCase):
def setUp(self):
super(DatabasesTest, self).setUp()
self.orig__init = databases.Databases.__init__
databases.Databases.__init__ = mock.Mock(return_value=None)
self.databases = databases.Databases()
self.databases.api = mock.Mock()
self.databases.api.client = mock.Mock()
self.instance_with_id = mock.Mock()
self.instance_with_id.id = 215
self.fakedb1 = ['db1']
self.fakedb2 = ['db1', 'db2']
def tearDown(self):
super(DatabasesTest, self).tearDown()
databases.Databases.__init__ = self.orig__init
def _get_mock_method(self):
self._resp = mock.Mock()
self._body = None
self._url = None
def side_effect_func(url, body=None):
self._body = body
self._url = url
return (self._resp, body)
return mock.Mock(side_effect=side_effect_func)
def test_create(self):
self.databases.api.client.post = self._get_mock_method()
self._resp.status_code = 200
self.databases.create(23, self.fakedb1)
self.assertEqual('/instances/23/databases', self._url)
self.assertEqual({"databases": self.fakedb1}, self._body)
self.databases.create(23, self.fakedb2)
self.assertEqual('/instances/23/databases', self._url)
self.assertEqual({"databases": self.fakedb2}, self._body)
# test creation with the instance as an object
self.databases.create(self.instance_with_id, self.fakedb1)
self.assertEqual({"databases": self.fakedb1}, self._body)
def test_delete(self):
self.databases.api.client.delete = self._get_mock_method()
self._resp.status_code = 200
self.databases.delete(27, self.fakedb1[0])
self.assertEqual('/instances/27/databases/%s' % self.fakedb1[0],
self._url)
self.databases.delete(self.instance_with_id, self.fakedb1[0])
self.assertEqual('/instances/%s/databases/%s' %
(self.instance_with_id.id, self.fakedb1[0]),
self._url)
self._resp.status_code = 400
self.assertRaises(Exception, self.databases.delete, 34, self.fakedb1)
def test_list(self):
page_mock = mock.Mock()
self.databases._paginated = page_mock
self.databases.list('instance1')
page_mock.assert_called_with('/instances/instance1/databases',
'databases', None, None)
limit = 'test-limit'
marker = 'test-marker'
self.databases.list('instance1', limit, marker)
page_mock.assert_called_with('/instances/instance1/databases',
'databases', limit, marker)

View File

@@ -81,13 +81,12 @@ class InstancesTest(testtools.TestCase):
self.instances.api.client = mock.Mock()
self.instances.resource_class = mock.Mock(return_value="instance-1")
self.orig_base_getid = base.getid
base.getid = mock.Mock(return_value="instance1")
self.instance_with_id = mock.Mock()
self.instance_with_id.id = 215
def tearDown(self):
super(InstancesTest, self).tearDown()
instances.Instances.__init__ = self.orig__init
base.getid = self.orig_base_getid
def test_create(self):
def side_effect_func(path, body, inst):
@@ -128,7 +127,7 @@ class InstancesTest(testtools.TestCase):
self.instances._get = mock.Mock(side_effect=side_effect_func)
self.assertEqual(('/instances/instance1', 'instance'),
self.instances.get(1))
self.instances.get('instance1'))
def test_delete(self):
resp = mock.Mock()
@@ -136,6 +135,7 @@ class InstancesTest(testtools.TestCase):
body = None
self.instances.api.client.delete = mock.Mock(return_value=(resp, body))
self.instances.delete('instance1')
self.instances.delete(self.instance_with_id)
resp.status_code = 500
self.assertRaises(Exception, self.instances.delete, 'instance1')
@@ -150,32 +150,52 @@ class InstancesTest(testtools.TestCase):
self.assertIsNone(self.instances._action(1, body))
def _set_action_mock(self):
def side_effect_func(instance_id, body):
self._instance_id = instance_id
def side_effect_func(instance, body):
self._instance_id = base.getid(instance)
self._body = body
self._instance_id = None
self._body = None
self.instances._action = mock.Mock(side_effect=side_effect_func)
def test_resize_volume(self):
def _test_resize_volume(self, instance, id):
self._set_action_mock()
self.instances.resize_volume(152, 512)
self.assertEqual(152, self._instance_id)
self.assertEqual({"resize": {"volume": {"size": 512}}}, self._body)
self.instances.resize_volume(instance, 1024)
self.assertEqual(id, self._instance_id)
self.assertEqual({"resize": {"volume": {"size": 1024}}}, self._body)
def test_resize_instance(self):
def test_resize_volume_with_id(self):
self._test_resize_volume(152, 152)
def test_resize_volume_with_obj(self):
self._test_resize_volume(self.instance_with_id,
self.instance_with_id.id)
def _test_resize_instance(self, instance, id):
self._set_action_mock()
self.instances.resize_instance(4725, 103)
self.assertEqual(4725, self._instance_id)
self.instances.resize_instance(instance, 103)
self.assertEqual(id, self._instance_id)
self.assertEqual({"resize": {"flavorRef": 103}}, self._body)
def test_restart(self):
def test_resize_instance_with_id(self):
self._test_resize_instance(4725, 4725)
def test_resize_instance_with_obj(self):
self._test_resize_instance(self.instance_with_id,
self.instance_with_id.id)
def _test_restart(self, instance, id):
self._set_action_mock()
self.instances.restart(253)
self.assertEqual(253, self._instance_id)
self.instances.restart(instance)
self.assertEqual(id, self._instance_id)
self.assertEqual({'restart': {}}, self._body)
def test_restart_with_id(self):
self._test_restart(253, 253)
def test_restart_with_obj(self):
self._test_restart(self.instance_with_id, self.instance_with_id.id)
def test_modify(self):
resp = mock.Mock()
resp.status_code = 200
@@ -183,6 +203,8 @@ class InstancesTest(testtools.TestCase):
self.instances.api.client.put = mock.Mock(return_value=(resp, body))
self.instances.modify(123)
self.instances.modify(123, 321)
self.instances.modify(self.instance_with_id)
self.instances.modify(self.instance_with_id, 123)
resp.status_code = 500
self.assertRaises(Exception, self.instances.modify, 'instance1')
@@ -195,6 +217,10 @@ class InstancesTest(testtools.TestCase):
self.instances.edit(123, 321)
self.instances.edit(123, 321, 'name-1234')
self.instances.edit(123, 321, 'name-1234', True)
self.instances.edit(self.instance_with_id)
self.instances.edit(self.instance_with_id, 123)
self.instances.edit(self.instance_with_id, 123, 'name-1234')
self.instances.edit(self.instance_with_id, 123, 'name-1234', True)
resp.status_code = 500
self.assertRaises(Exception, self.instances.edit, 'instance1')
@@ -204,7 +230,7 @@ class InstancesTest(testtools.TestCase):
self.instances._get = mock.Mock(side_effect=side_effect_func)
self.assertEqual(('/instances/instance1/configuration', 'instance'),
self.instances.configuration(1))
self.instances.configuration('instance1'))
class InstanceStatusTest(testtools.TestCase):

View File

@@ -18,7 +18,6 @@
import mock
import testtools
from troveclient import base
from troveclient.v1 import users
"""
@@ -51,13 +50,12 @@ class UsersTest(testtools.TestCase):
self.users.api = mock.Mock()
self.users.api.client = mock.Mock()
self.orig_base_getid = base.getid
base.getid = mock.Mock(return_value="instance1")
self.instance_with_id = mock.Mock()
self.instance_with_id.id = 215
def tearDown(self):
super(UsersTest, self).tearDown()
users.Users.__init__ = self.orig__init
base.getid = self.orig_base_getid
def _get_mock_method(self):
self._resp = mock.Mock()
@@ -102,6 +100,10 @@ class UsersTest(testtools.TestCase):
self.users.create(23, [user])
self.assertEqual({"users": [user]}, self._body)
# test creation with the instance as an object
self.users.create(self.instance_with_id, [user])
self.assertEqual({"users": [user]}, self._body)
# Make sure that response of 400 is recognized as an error.
user['host'] = '%'
self._resp.status_code = 400
@@ -112,18 +114,21 @@ class UsersTest(testtools.TestCase):
self._resp.status_code = 200
self.users.delete(27, 'user1')
self.assertEqual('/instances/27/users/user1', self._url)
self.users.delete(self.instance_with_id, 'user1')
self.assertEqual('/instances/%s/users/user1' %
self.instance_with_id.id, self._url)
self._resp.status_code = 400
self.assertRaises(Exception, self.users.delete, 34, 'user1')
def test_list(self):
page_mock = mock.Mock()
self.users._paginated = page_mock
self.users.list(1)
self.users.list('instance1')
page_mock.assert_called_with('/instances/instance1/users',
'users', None, None)
limit = 'test-limit'
marker = 'test-marker'
self.users.list(1, limit, marker)
self.users.list('instance1', limit, marker)
page_mock.assert_called_with('/instances/instance1/users',
'users', limit, marker)

View File

@@ -60,7 +60,7 @@ class Backups(base.ManagerWithFind):
}
if instance:
body['backup']['instance'] = instance
body['backup']['instance'] = base.getid(instance)
if backup:
body["backup"]['backup'] = backup
if description:

View File

@@ -32,16 +32,16 @@ class Databases(base.ManagerWithFind):
"""Manage :class:`Databases` resources."""
resource_class = Database
def create(self, instance_id, databases):
def create(self, instance, databases):
"""Create new databases within the specified instance."""
body = {"databases": databases}
url = "/instances/%s/databases" % instance_id
url = "/instances/%s/databases" % base.getid(instance)
resp, body = self.api.client.post(url, body=body)
common.check_for_exceptions(resp, body, url)
def delete(self, instance_id, dbname):
def delete(self, instance, dbname):
"""Delete an existing database in the specified instance."""
url = "/instances/%s/databases/%s" % (instance_id, dbname)
url = "/instances/%s/databases/%s" % (base.getid(instance), dbname)
resp, body = self.api.client.delete(url)
common.check_for_exceptions(resp, body, url)

View File

@@ -80,22 +80,22 @@ class Instances(base.ManagerWithFind):
if configuration:
body["instance"]["configuration"] = configuration
if replica_of or slave_of:
body["instance"]["replica_of"] = replica_of or slave_of
body["instance"]["replica_of"] = base.getid(replica_of) or slave_of
return self._create("/instances", body, "instance")
def modify(self, instance_id, configuration=None):
def modify(self, instance, configuration=None):
body = {
"instance": {
}
}
if configuration is not None:
body["instance"]["configuration"] = configuration
url = "/instances/%s" % instance_id
url = "/instances/%s" % base.getid(instance)
resp, body = self.api.client.put(url, body=body)
common.check_for_exceptions(resp, body, url)
def edit(self, instance_id, configuration=None, name=None,
def edit(self, instance, configuration=None, name=None,
detach_replica_source=False, remove_configuration=False):
body = {
"instance": {
@@ -116,7 +116,7 @@ class Instances(base.ManagerWithFind):
body["instance"]["slave_of"] = None
body["instance"]["replica_of"] = None
url = "/instances/%s" % instance_id
url = "/instances/%s" % base.getid(instance)
resp, body = self.api.client.patch(url, body=body)
common.check_for_exceptions(resp, body, url)
@@ -147,38 +147,39 @@ class Instances(base.ManagerWithFind):
def delete(self, instance):
"""Delete the specified instance.
:param instance_id: The instance id to delete
:param instance: A reference to the instance to delete
"""
url = "/instances/%s" % base.getid(instance)
resp, body = self.api.client.delete(url)
common.check_for_exceptions(resp, body, url)
def _action(self, instance_id, body):
def _action(self, instance, body):
"""Perform a server "action" -- reboot/rebuild/resize/etc."""
url = "/instances/%s/action" % instance_id
url = "/instances/%s/action" % base.getid(instance)
resp, body = self.api.client.post(url, body=body)
common.check_for_exceptions(resp, body, url)
if body:
return self.resource_class(self, body, loaded=True)
return body
def resize_volume(self, instance_id, volume_size):
def resize_volume(self, instance, volume_size):
"""Resize the volume on an existing instances."""
body = {"resize": {"volume": {"size": volume_size}}}
self._action(instance_id, body)
self._action(instance, body)
def resize_instance(self, instance_id, flavor_id):
def resize_instance(self, instance, flavor_id):
"""Resizes an instance with a new flavor."""
body = {"resize": {"flavorRef": flavor_id}}
self._action(instance_id, body)
self._action(instance, body)
def restart(self, instance_id):
def restart(self, instance):
"""Restart the database instance.
:param instance_id: The :class:`Instance` (or its ID) to share onto.
:param instance: The :class:`Instance` (or its ID) of the database
instance to restart.
"""
body = {'restart': {}}
self._action(instance_id, body)
self._action(instance, body)
def configuration(self, instance):
"""Get a configuration on instances.

View File

@@ -24,19 +24,19 @@ class Root(base.ManagerWithFind):
resource_class = users.User
url = "/instances/%s/root"
def create(self, instance_id):
def create(self, instance):
"""Implements root-enable API.
Enable the root user and return the root password for the
specified db instance.
"""
resp, body = self.api.client.post(self.url % instance_id)
resp, body = self.api.client.post(self.url % base.getid(instance))
common.check_for_exceptions(resp, body, self.url)
return body['user']['name'], body['user']['password']
def is_root_enabled(self, instance_id):
def is_root_enabled(self, instance):
"""Return whether root is enabled for the instance."""
resp, body = self.api.client.get(self.url % instance_id)
resp, body = self.api.client.get(self.url % base.getid(instance))
common.check_for_exceptions(resp, body, self.url)
return self.resource_class(self, body, loaded=True)

View File

@@ -234,11 +234,13 @@ def do_cluster_instances(cs, args):
obj_is_dict=True)
@utils.arg('instance', metavar='<instance>', help='ID of the instance.')
@utils.arg('instance', metavar='<instance>',
help='ID or name of the instance.')
@utils.service_type('database')
def do_delete(cs, args):
"""Deletes an instance."""
cs.instances.delete(args.instance)
instance = _find_instance(cs, args.instance)
cs.instances.delete(instance)
@utils.arg('cluster', metavar='<cluster>', help='ID of the cluster.')
@@ -251,7 +253,7 @@ def do_cluster_delete(cs, args):
@utils.arg('instance',
metavar='<instance>',
type=str,
help='UUID of the instance.')
help='ID or name of the instance.')
@utils.arg('--name',
metavar='<name>',
type=str,
@@ -275,7 +277,8 @@ def do_cluster_delete(cs, args):
@utils.service_type('database')
def do_update(cs, args):
"""Updates an instance: Edits name, configuration, or replica source."""
cs.instances.edit(args.instance, args.configuration, args.name,
instance = _find_instance(cs, args.instance)
cs.instances.edit(instance, args.configuration, args.name,
args.detach_replica_source, args.remove_configuration)
@@ -331,18 +334,21 @@ def do_update(cs, args):
default=None,
help='ID of the configuration group to attach to the instance.')
@utils.arg('--replica_of',
metavar='<source_id>',
metavar='<source_instance>',
default=None,
help='ID of an existing instance to replicate from.')
help='ID or name of an existing instance to replicate from.')
@utils.service_type('database')
def do_create(cs, args):
"""Creates a new instance."""
volume = None
replica_of_instance = None
if args.size:
volume = {"size": args.size}
restore_point = None
if args.backup:
restore_point = {"backupRef": args.backup}
if args.replica_of:
replica_of_instance = _find_instance(cs, args.replica_of)
databases = [{'name': value} for value in args.databases]
users = [{'name': n, 'password': p, 'databases': databases} for (n, p) in
[z.split(':')[:2] for z in args.users]]
@@ -368,7 +374,7 @@ def do_create(cs, args):
datastore_version=args.datastore_version,
nics=nics,
configuration=args.configuration,
replica_of=args.replica_of)
replica_of=replica_of_instance)
_print_instance(instance)
@@ -425,7 +431,7 @@ def do_cluster_create(cs, args):
@utils.arg('instance',
metavar='<instance>',
type=str,
help='ID of the instance.')
help='ID or name of the instance.')
@utils.arg('flavor_id',
metavar='<flavor_id>',
help='New flavor of the instance.')
@@ -438,20 +444,21 @@ def do_resize_flavor(cs, args):
@utils.arg('instance',
metavar='<instance>',
type=str,
help='ID of the instance.')
help='ID or name of the instance.')
@utils.arg('flavor_id',
metavar='<flavor_id>',
help='New flavor of the instance.')
@utils.service_type('database')
def do_resize_instance(cs, args):
"""Resizes an instance with a new flavor."""
cs.instances.resize_instance(args.instance, args.flavor_id)
instance = _find_instance(cs, args.instance)
cs.instances.resize_instance(instance, args.flavor_id)
@utils.arg('instance',
metavar='<instance>',
type=str,
help='ID of the instance.')
help='ID or name of the instance.')
@utils.arg('size',
metavar='<size>',
type=int,
@@ -460,26 +467,29 @@ def do_resize_instance(cs, args):
@utils.service_type('database')
def do_resize_volume(cs, args):
"""Resizes the volume size of an instance."""
cs.instances.resize_volume(args.instance, args.size)
instance = _find_instance(cs, args.instance)
cs.instances.resize_volume(instance, args.size)
@utils.arg('instance',
metavar='<instance>',
type=str,
help='ID of the instance.')
help='ID or name of the instance.')
@utils.service_type('database')
def do_restart(cs, args):
"""Restarts an instance."""
cs.instances.restart(args.instance)
instance = _find_instance(cs, args.instance)
cs.instances.restart(instance)
@utils.arg('instance',
metavar='<instance>',
type=str,
help='ID of the instance.')
help='ID or name of the instance.')
def do_detach_replica(cs, args):
"""Detaches a replica instance from its replication source."""
cs.instances.edit(args.instance, detach_replica_source=True)
instance = _find_instance(cs, args.instance)
cs.instances.edit(instance, detach_replica_source=True)
# Backup related commands
@@ -492,17 +502,19 @@ def do_backup_show(cs, args):
_print_object(backup)
@utils.arg('instance', metavar='<instance>', help='ID of the instance.')
@utils.arg('instance', metavar='<instance>',
help='ID or name of the instance.')
@utils.arg('--limit', metavar='<limit>',
default=None,
help='Return up to N number of the most recent backups.')
@utils.service_type('database')
def do_backup_list_instance(cs, args):
"""Lists available backups for an instance."""
wrapper = cs.instances.backups(args.instance, limit=args.limit)
instance = _find_instance(cs, args.instance)
wrapper = cs.instances.backups(instance, limit=args.limit)
backups = wrapper.items
while wrapper.next and not args.limit:
wrapper = cs.instances.backups(args.instance, marker=wrapper.next)
wrapper = cs.instances.backups(instance, marker=wrapper.next)
backups += wrapper.items
utils.print_list(backups, ['id', 'name', 'status',
'parent_id', 'updated'],
@@ -535,7 +547,8 @@ def do_backup_delete(cs, args):
cs.backups.delete(args.backup)
@utils.arg('instance', metavar='<instance>', help='ID of the instance.')
@utils.arg('instance', metavar='<instance>',
help='ID or name of the instance.')
@utils.arg('name', metavar='<name>', help='Name of the backup.')
@utils.arg('--description', metavar='<description>',
default=None,
@@ -546,7 +559,8 @@ def do_backup_delete(cs, args):
@utils.service_type('database')
def do_backup_create(cs, args):
"""Creates a backup of an instance."""
backup = cs.backups.create(args.name, args.instance,
instance = _find_instance(cs, args.instance)
backup = cs.backups.create(args.name, instance,
description=args.description,
parent_id=args.parent)
_print_object(backup)
@@ -578,7 +592,8 @@ def do_backup_copy(cs, args):
# Database related actions
@utils.arg('instance', metavar='<instance>', help='ID of the instance.')
@utils.arg('instance', metavar='<instance>',
help='ID or name of the instance.')
@utils.arg('name', metavar='<name>', help='Name of the database.')
@utils.arg('--character_set', metavar='<character_set>',
default=None,
@@ -588,39 +603,45 @@ def do_backup_copy(cs, args):
@utils.service_type('database')
def do_database_create(cs, args):
"""Creates a database on an instance."""
instance = _find_instance(cs, args.instance)
database_dict = {'name': args.name}
if args.collate:
database_dict['collate'] = args.collate
if args.character_set:
database_dict['character_set'] = args.character_set
cs.databases.create(args.instance,
cs.databases.create(instance,
[database_dict])
@utils.arg('instance', metavar='<instance>', help='ID of the instance.')
@utils.arg('instance', metavar='<instance>',
help='ID or name of the instance.')
@utils.service_type('database')
def do_database_list(cs, args):
"""Lists available databases on an instance."""
wrapper = cs.databases.list(args.instance)
instance = _find_instance(cs, args.instance)
wrapper = cs.databases.list(instance)
databases = wrapper.items
while (wrapper.next):
wrapper = cs.databases.list(args.instance, marker=wrapper.next)
wrapper = cs.databases.list(instance, marker=wrapper.next)
databases += wrapper.items
utils.print_list(databases, ['name'])
@utils.arg('instance', metavar='<instance>', help='ID of the instance.')
@utils.arg('instance', metavar='<instance>',
help='ID or name of the instance.')
@utils.arg('database', metavar='<database>', help='Name of the database.')
@utils.service_type('database')
def do_database_delete(cs, args):
"""Deletes a database from an instance."""
cs.databases.delete(args.instance, args.database)
instance = _find_instance(cs, args.instance)
cs.databases.delete(instance, args.database)
# User related actions
@utils.arg('instance', metavar='<instance>', help='ID of the instance.')
@utils.arg('instance', metavar='<instance>',
help='ID or name of the instance.')
@utils.arg('name', metavar='<name>', help='Name of user.')
@utils.arg('password', metavar='<password>', help='Password of user.')
@utils.arg('--host', metavar='<host>', default=None,
@@ -631,22 +652,25 @@ def do_database_delete(cs, args):
@utils.service_type('database')
def do_user_create(cs, args):
"""Creates a user on an instance."""
instance = _find_instance(cs, args.instance)
databases = [{'name': value} for value in args.databases]
user = {'name': args.name, 'password': args.password,
'databases': databases}
if args.host:
user['host'] = args.host
cs.users.create(args.instance, [user])
cs.users.create(instance, [user])
@utils.arg('instance', metavar='<instance>', help='ID of the instance.')
@utils.arg('instance', metavar='<instance>',
help='ID or name of the instance.')
@utils.service_type('database')
def do_user_list(cs, args):
"""Lists the users for an instance."""
wrapper = cs.users.list(args.instance)
instance = _find_instance(cs, args.instance)
wrapper = cs.users.list(instance)
users = wrapper.items
while (wrapper.next):
wrapper = cs.users.list(args.instance, marker=wrapper.next)
wrapper = cs.users.list(instance, marker=wrapper.next)
users += wrapper.items
for user in users:
db_names = [db['name'] for db in user.databases]
@@ -654,39 +678,46 @@ def do_user_list(cs, args):
utils.print_list(users, ['name', 'host', 'databases'])
@utils.arg('instance', metavar='<instance>', help='ID of the instance.')
@utils.arg('instance', metavar='<instance>',
help='ID or name of the instance.')
@utils.arg('name', metavar='<name>', help='Name of user.')
@utils.arg('--host', metavar='<host>', default=None,
help='Optional host of user.')
@utils.service_type('database')
def do_user_delete(cs, args):
"""Deletes a user from an instance."""
cs.users.delete(args.instance, args.name, hostname=args.host)
instance = _find_instance(cs, args.instance)
cs.users.delete(instance, args.name, hostname=args.host)
@utils.arg('instance', metavar='<instance>', help='ID of the instance.')
@utils.arg('instance', metavar='<instance>',
help='ID or name of the instance.')
@utils.arg('name', metavar='<name>', help='Name of user.')
@utils.arg('--host', metavar='<host>', default=None,
help='Optional host of user.')
@utils.service_type('database')
def do_user_show(cs, args):
"""Shows details of a user of an instance."""
user = cs.users.get(args.instance, args.name, hostname=args.host)
instance = _find_instance(cs, args.instance)
user = cs.users.get(instance, args.name, hostname=args.host)
_print_object(user)
@utils.arg('instance', metavar='<instance>', help='ID of the instance.')
@utils.arg('instance', metavar='<instance>',
help='ID or name of the instance.')
@utils.arg('name', metavar='<name>', help='Name of user.')
@utils.arg('--host', metavar='<host>', default=None,
help='Optional host of user.')
@utils.service_type('database')
def do_user_show_access(cs, args):
"""Shows access details of a user of an instance."""
access = cs.users.list_access(args.instance, args.name, hostname=args.host)
instance = _find_instance(cs, args.instance)
access = cs.users.list_access(instance, args.name, hostname=args.host)
utils.print_list(access, ['name'])
@utils.arg('instance', metavar='<instance>', help='ID of the instance.')
@utils.arg('instance', metavar='<instance>',
help='ID or name of the instance.')
@utils.arg('name', metavar='<name>', help='Name of user.')
@utils.arg('--host', metavar='<host>', default=None,
help='Optional host of user.')
@@ -701,6 +732,7 @@ def do_user_update_attributes(cs, args):
"""Updates a user's attributes on an instance.
At least one optional argument must be provided.
"""
instance = _find_instance(cs, args.instance)
new_attrs = {}
if args.new_name:
new_attrs['name'] = args.new_name
@@ -708,11 +740,12 @@ def do_user_update_attributes(cs, args):
new_attrs['password'] = args.new_password
if args.new_host:
new_attrs['host'] = args.new_host
cs.users.update_attributes(args.instance, args.name,
cs.users.update_attributes(instance, args.name,
newuserattr=new_attrs, hostname=args.host)
@utils.arg('instance', metavar='<instance>', help='ID of the instance.')
@utils.arg('instance', metavar='<instance>',
help='ID or name of the instance.')
@utils.arg('name', metavar='<name>', help='Name of user.')
@utils.arg('--host', metavar='<host>', default=None,
help='Optional host of user.')
@@ -722,11 +755,13 @@ def do_user_update_attributes(cs, args):
@utils.service_type('database')
def do_user_grant_access(cs, args):
"""Grants access to a database(s) for a user."""
cs.users.grant(args.instance, args.name,
instance = _find_instance(cs, args.instance)
cs.users.grant(instance, args.name,
args.databases, hostname=args.host)
@utils.arg('instance', metavar='<instance>', help='ID of the instance.')
@utils.arg('instance', metavar='<instance>',
help='ID or name of the instance.')
@utils.arg('name', metavar='<name>', help='Name of user.')
@utils.arg('database', metavar='<database>', help='A single database.')
@utils.arg('--host', metavar='<host>', default=None,
@@ -734,7 +769,8 @@ def do_user_grant_access(cs, args):
@utils.service_type('database')
def do_user_revoke_access(cs, args):
"""Revokes access to a database for a user."""
cs.users.revoke(args.instance, args.name,
instance = _find_instance(cs, args.instance)
cs.users.revoke(instance, args.name,
args.database, hostname=args.host)
@@ -752,19 +788,23 @@ def do_limit_list(cs, args):
# Root related commands
@utils.arg('instance', metavar='<instance>', help='ID of the instance.')
@utils.arg('instance', metavar='<instance>',
help='ID or name of the instance.')
@utils.service_type('database')
def do_root_enable(cs, args):
"""Enables root for an instance and resets if already exists."""
root = cs.root.create(args.instance)
instance = _find_instance(cs, args.instance)
root = cs.root.create(instance)
utils.print_dict({'name': root[0], 'password': root[1]})
@utils.arg('instance', metavar='<instance>', help='ID of the instance.')
@utils.arg('instance', metavar='<instance>',
help='ID or name of the instance.')
@utils.service_type('database')
def do_root_show(cs, args):
"""Gets status if root was ever enabled for an instance."""
root = cs.root.is_root_enabled(args.instance)
instance = _find_instance(cs, args.instance)
root = cs.root.is_root_enabled(instance)
utils.print_dict({'is_root_enabled': root.rootEnabled})
@@ -881,7 +921,7 @@ def do_datastore_version_show(cs, args):
@utils.arg('instance',
metavar='<instance>',
type=str,
help='ID of the instance.')
help='ID or name of the instance.')
@utils.arg('configuration',
metavar='<configuration>',
type=str,
@@ -889,7 +929,8 @@ def do_datastore_version_show(cs, args):
@utils.service_type('database')
def do_configuration_attach(cs, args):
"""Attaches a configuration group to an instance."""
cs.instances.modify(args.instance, args.configuration)
instance = _find_instance(cs, args.instance)
cs.instances.modify(instance, args.configuration)
@utils.arg('name', metavar='<name>', help='Name of the configuration group.')
@@ -918,11 +959,12 @@ def do_configuration_create(cs, args):
@utils.arg('instance',
metavar='<instance>',
type=str,
help='ID of the instance.')
help='ID or name of the instance.')
@utils.service_type('database')
def do_configuration_default(cs, args):
"""Shows the default configuration of an instance."""
configs = cs.instances.configuration(args.instance)
instance = _find_instance(cs, args.instance)
configs = cs.instances.configuration(instance)
utils.print_dict(configs._info['configuration'])
@@ -937,11 +979,12 @@ def do_configuration_delete(cs, args):
@utils.arg('instance',
metavar='<instance>',
type=str,
help='ID of the instance.')
help='ID or name of the instance.')
@utils.service_type('database')
def do_configuration_detach(cs, args):
"""Detaches a configuration group from an instance."""
cs.instances.modify(args.instance)
instance = _find_instance(cs, args.instance)
cs.instances.modify(instance)
@utils.arg('--datastore', metavar='<datastore>',

View File

@@ -29,17 +29,17 @@ class Users(base.ManagerWithFind):
"""Manage :class:`Users` resources."""
resource_class = User
def create(self, instance_id, users):
def create(self, instance, users):
"""Create users with permissions to the specified databases."""
body = {"users": users}
url = "/instances/%s/users" % instance_id
url = "/instances/%s/users" % base.getid(instance)
resp, body = self.api.client.post(url, body=body)
common.check_for_exceptions(resp, body, url)
def delete(self, instance_id, username, hostname=None):
def delete(self, instance, username, hostname=None):
"""Delete an existing user in the specified instance."""
user = common.quote_user_host(username, hostname)
url = "/instances/%s/users/%s" % (instance_id, user)
url = "/instances/%s/users/%s" % (base.getid(instance), user)
resp, body = self.api.client.delete(url)
common.check_for_exceptions(resp, body, url)
@@ -51,13 +51,13 @@ class Users(base.ManagerWithFind):
url = "/instances/%s/users" % base.getid(instance)
return self._paginated(url, "users", limit, marker)
def get(self, instance_id, username, hostname=None):
def get(self, instance, username, hostname=None):
"""Get a single User from the instance's Database.
:rtype: :class:`User`.
"""
user = common.quote_user_host(username, hostname)
url = "/instances/%s/users/%s" % (instance_id, user)
url = "/instances/%s/users/%s" % (base.getid(instance), user)
return self._get(url, "user")
def update_attributes(self, instance, username, newuserattr=None,