diff --git a/releasenotes/notes/add-quota-to-osc-c50c8ec190af8f58.yaml b/releasenotes/notes/add-quota-to-osc-c50c8ec190af8f58.yaml new file mode 100644 index 00000000..49464e3b --- /dev/null +++ b/releasenotes/notes/add-quota-to-osc-c50c8ec190af8f58.yaml @@ -0,0 +1,8 @@ +--- +features: + - | + The command ``trove quota-show`` is now available to use in the + python-openstackclient CLI as ``openstack database quota show``. + - | + The command ``trove quota-update`` is now available to use in the + python-openstackclient CLI as ``openstack database quota update``. diff --git a/setup.cfg b/setup.cfg index 25c63de1..33463052 100644 --- a/setup.cfg +++ b/setup.cfg @@ -61,6 +61,8 @@ openstack.database.v1 = database_instance_resize_flavor = troveclient.osc.v1.database_instances:ResizeDatabaseInstanceFlavor database_instance_show = troveclient.osc.v1.database_instances:ShowDatabaseInstance database_limit_list = troveclient.osc.v1.database_limits:ListDatabaseLimits + database_quota_show = troveclient.osc.v1.database_quota:ShowDatabaseQuota + database_quota_update = troveclient.osc.v1.database_quota:UpdateDatabaseQuota database_root_disable = troveclient.osc.v1.database_root:DisableDatabaseRoot database_root_enable = troveclient.osc.v1.database_root:EnableDatabaseRoot database_root_show = troveclient.osc.v1.database_root:ShowDatabaseRoot diff --git a/troveclient/osc/v1/database_quota.py b/troveclient/osc/v1/database_quota.py new file mode 100644 index 00000000..f257dd79 --- /dev/null +++ b/troveclient/osc/v1/database_quota.py @@ -0,0 +1,74 @@ +# 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. + +"""Database v1 Quota action implementations""" + +from osc_lib.command import command +from osc_lib import utils as osc_utils +import six + +from troveclient.i18n import _ + + +class ShowDatabaseQuota(command.Lister): + + _description = _("Show quotas for a tenant.") + columns = ['Resource', 'In Use', 'Reserved', 'Limit'] + + def get_parser(self, prog_name): + parser = super(ShowDatabaseQuota, self).get_parser(prog_name) + parser.add_argument( + 'tenant_id', + metavar='', + help=_('Id of tenant for which to show quotas.'), + ) + return parser + + def take_action(self, parsed_args): + db_quota = self.app.client_manager.database.quota + quota = [osc_utils.get_item_properties(q, self.columns) + for q in db_quota.show(parsed_args.tenant_id)] + return self.columns, quota + + +class UpdateDatabaseQuota(command.ShowOne): + + _description = _("Update quotas for a tenant.") + + def get_parser(self, prog_name): + parser = super(UpdateDatabaseQuota, self).get_parser(prog_name) + parser.add_argument( + 'tenant_id', + metavar='', + help=_('Id of tenant for which to update quotas.'), + ) + parser.add_argument( + 'resource', + metavar='', + help=_('Id of resource to change.'), + ) + parser.add_argument( + 'limit', + metavar='', + type=int, + help=_('New limit to set for the named resource.'), + ) + return parser + + def take_action(self, parsed_args): + db_quota = self.app.client_manager.database.quota + update_params = { + parsed_args.resource: parsed_args.limit + } + updated_quota = db_quota.update(parsed_args.tenant_id, + update_params) + return zip(*sorted(six.iteritems(updated_quota))) diff --git a/troveclient/tests/fakes.py b/troveclient/tests/fakes.py index 48557b2b..ac9c9e5e 100644 --- a/troveclient/tests/fakes.py +++ b/troveclient/tests/fakes.py @@ -759,3 +759,27 @@ class FakeHTTPClient(base_client.HTTPClient): "to_port": 3306, "security_group_id": "2", "cidr": "15.0.0.0/24", "id": 3}]}) + + def get_quotas(self, **kw): + return (200, {}, {"quotas": [ + { + "reserved": 1, + "resource": "instances", + "limit": 10, + "in_use": 2 + }, + { + "reserved": 3, + "resource": "backups", + "limit": 50, + "in_use": 4 + }, + { + "reserved": 5, + "resource": "volumes", + "limit": 40, + "in_use": 6 + }]}) + + def update_instances_quota(self, **kw): + return (200, {}, {"quotas": {"instances": 51}}) diff --git a/troveclient/tests/osc/v1/fakes.py b/troveclient/tests/osc/v1/fakes.py index cfaf2f2f..85a12077 100644 --- a/troveclient/tests/osc/v1/fakes.py +++ b/troveclient/tests/osc/v1/fakes.py @@ -23,6 +23,7 @@ from troveclient.v1 import datastores from troveclient.v1 import flavors from troveclient.v1 import instances from troveclient.v1 import limits +from troveclient.v1 import quota from troveclient.v1 import users @@ -157,3 +158,13 @@ class FakeRoot(object): def delete_instance_1234_root(self): return fakes.FakeHTTPClient().delete_instances_1234_root()[2] + + +class FakeQuota(object): + fake_quotas = fakes.FakeHTTPClient().get_quotas()[2]['quotas'] + fake_instances_quota = (fakes.FakeHTTPClient() + .update_instances_quota()[2]['quotas']) + + def get_quotas(self): + return [quota.Quotas.resource_class(None, q) + for q in self.fake_quotas] diff --git a/troveclient/tests/osc/v1/test_database_quota.py b/troveclient/tests/osc/v1/test_database_quota.py new file mode 100644 index 00000000..d15c7ead --- /dev/null +++ b/troveclient/tests/osc/v1/test_database_quota.py @@ -0,0 +1,59 @@ +# 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. + +from troveclient.osc.v1 import database_quota +from troveclient.tests.osc.v1 import fakes + + +class TestQuota(fakes.TestDatabasev1): + fake_quota = fakes.FakeQuota() + + def setUp(self): + super(TestQuota, self).setUp() + self.mock_client = self.app.client_manager.database + self.quota_client = self.app.client_manager.database.quota + + +class TestQuotaShow(TestQuota): + columns = database_quota.ShowDatabaseQuota.columns + values = [('instances', 2, 1, 10), + ('backups', 4, 3, 50), + ('volumes', 6, 5, 40)] + + def setUp(self): + super(TestQuotaShow, self).setUp() + self.cmd = database_quota.ShowDatabaseQuota(self.app, None) + self.data = self.fake_quota.get_quotas() + self.quota_client.show.return_value = self.data + + def test_show_quotas(self): + args = ['tenant_id'] + parsed_args = self.check_parser(self.cmd, args, []) + columns, data = self.cmd.take_action(parsed_args) + self.assertEqual(self.columns, columns) + self.assertEqual(self.values, data) + + +class TestQuotaUpdate(TestQuota): + + def setUp(self): + super(TestQuotaUpdate, self).setUp() + self.cmd = database_quota.UpdateDatabaseQuota(self.app, None) + self.data = self.fake_quota.fake_instances_quota + self.quota_client.update.return_value = self.data + + def test_update_quota(self): + args = ['tenant_id', 'instances', '51'] + parsed_args = self.check_parser(self.cmd, args, []) + columns, data = self.cmd.take_action(parsed_args) + self.assertEqual(('instances',), columns) + self.assertEqual((51,), data)