diff --git a/troveclient/tests/test_backups.py b/troveclient/tests/test_backups.py index 696f1878..34b2e5a1 100644 --- a/troveclient/tests/test_backups.py +++ b/troveclient/tests/test_backups.py @@ -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 diff --git a/troveclient/tests/test_databases.py b/troveclient/tests/test_databases.py new file mode 100644 index 00000000..51fdd6e3 --- /dev/null +++ b/troveclient/tests/test_databases.py @@ -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) diff --git a/troveclient/tests/test_instances.py b/troveclient/tests/test_instances.py index 2754b5c4..e893c3fe 100644 --- a/troveclient/tests/test_instances.py +++ b/troveclient/tests/test_instances.py @@ -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): diff --git a/troveclient/tests/test_users.py b/troveclient/tests/test_users.py index d91e759b..c8915c70 100644 --- a/troveclient/tests/test_users.py +++ b/troveclient/tests/test_users.py @@ -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) diff --git a/troveclient/v1/backups.py b/troveclient/v1/backups.py index 56939836..eba5d8a9 100644 --- a/troveclient/v1/backups.py +++ b/troveclient/v1/backups.py @@ -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: diff --git a/troveclient/v1/databases.py b/troveclient/v1/databases.py index 1e957967..230df749 100644 --- a/troveclient/v1/databases.py +++ b/troveclient/v1/databases.py @@ -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) diff --git a/troveclient/v1/instances.py b/troveclient/v1/instances.py index 9a10d87b..da2cb943 100644 --- a/troveclient/v1/instances.py +++ b/troveclient/v1/instances.py @@ -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. diff --git a/troveclient/v1/root.py b/troveclient/v1/root.py index 95f2088b..62462193 100644 --- a/troveclient/v1/root.py +++ b/troveclient/v1/root.py @@ -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) diff --git a/troveclient/v1/shell.py b/troveclient/v1/shell.py index 000ba29b..dd9408ee 100644 --- a/troveclient/v1/shell.py +++ b/troveclient/v1/shell.py @@ -234,11 +234,13 @@ def do_cluster_instances(cs, args): obj_is_dict=True) -@utils.arg('instance', metavar='', help='ID of the instance.') +@utils.arg('instance', metavar='', + 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='', help='ID of the cluster.') @@ -251,7 +253,7 @@ def do_cluster_delete(cs, args): @utils.arg('instance', metavar='', type=str, - help='UUID of the instance.') + help='ID or name of the instance.') @utils.arg('--name', metavar='', 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='', + metavar='', 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='', type=str, - help='ID of the instance.') + help='ID or name of the instance.') @utils.arg('flavor_id', metavar='', help='New flavor of the instance.') @@ -438,20 +444,21 @@ def do_resize_flavor(cs, args): @utils.arg('instance', metavar='', type=str, - help='ID of the instance.') + help='ID or name of the instance.') @utils.arg('flavor_id', metavar='', 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='', type=str, - help='ID of the instance.') + help='ID or name of the instance.') @utils.arg('size', metavar='', 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='', 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='', 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='', help='ID of the instance.') +@utils.arg('instance', metavar='', + help='ID or name of the instance.') @utils.arg('--limit', metavar='', 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='', help='ID of the instance.') +@utils.arg('instance', metavar='', + help='ID or name of the instance.') @utils.arg('name', metavar='', help='Name of the backup.') @utils.arg('--description', metavar='', 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='', help='ID of the instance.') +@utils.arg('instance', metavar='', + help='ID or name of the instance.') @utils.arg('name', metavar='', help='Name of the database.') @utils.arg('--character_set', metavar='', 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='', help='ID of the instance.') +@utils.arg('instance', metavar='', + 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='', help='ID of the instance.') +@utils.arg('instance', metavar='', + help='ID or name of the instance.') @utils.arg('database', metavar='', 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='', help='ID of the instance.') +@utils.arg('instance', metavar='', + help='ID or name of the instance.') @utils.arg('name', metavar='', help='Name of user.') @utils.arg('password', metavar='', help='Password of user.') @utils.arg('--host', metavar='', 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='', help='ID of the instance.') +@utils.arg('instance', metavar='', + 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='', help='ID of the instance.') +@utils.arg('instance', metavar='', + help='ID or name of the instance.') @utils.arg('name', metavar='', help='Name of user.') @utils.arg('--host', metavar='', 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='', help='ID of the instance.') +@utils.arg('instance', metavar='', + help='ID or name of the instance.') @utils.arg('name', metavar='', help='Name of user.') @utils.arg('--host', metavar='', 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='', help='ID of the instance.') +@utils.arg('instance', metavar='', + help='ID or name of the instance.') @utils.arg('name', metavar='', help='Name of user.') @utils.arg('--host', metavar='', 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='', help='ID of the instance.') +@utils.arg('instance', metavar='', + help='ID or name of the instance.') @utils.arg('name', metavar='', help='Name of user.') @utils.arg('--host', metavar='', 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='', help='ID of the instance.') +@utils.arg('instance', metavar='', + help='ID or name of the instance.') @utils.arg('name', metavar='', help='Name of user.') @utils.arg('--host', metavar='', 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='', help='ID of the instance.') +@utils.arg('instance', metavar='', + help='ID or name of the instance.') @utils.arg('name', metavar='', help='Name of user.') @utils.arg('database', metavar='', help='A single database.') @utils.arg('--host', metavar='', 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='', help='ID of the instance.') +@utils.arg('instance', metavar='', + 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='', help='ID of the instance.') +@utils.arg('instance', metavar='', + 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='', type=str, - help='ID of the instance.') + help='ID or name of the instance.') @utils.arg('configuration', metavar='', 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='', help='Name of the configuration group.') @@ -918,11 +959,12 @@ def do_configuration_create(cs, args): @utils.arg('instance', metavar='', 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='', 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='', diff --git a/troveclient/v1/users.py b/troveclient/v1/users.py index cf4d2059..6f018781 100644 --- a/troveclient/v1/users.py +++ b/troveclient/v1/users.py @@ -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,