diff --git a/karborclient/tests/unit/v1/test_quotas.py b/karborclient/tests/unit/v1/test_quotas.py new file mode 100644 index 0000000..b3c7bbb --- /dev/null +++ b/karborclient/tests/unit/v1/test_quotas.py @@ -0,0 +1,60 @@ +# 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 + +from karborclient.tests.unit import base +from karborclient.tests.unit.v1 import fakes + +cs = fakes.FakeClient() +mock_request_return = ({}, {'quota': {'plans': 50}}) + + +class QuotasTest(base.TestCaseShell): + + @mock.patch('karborclient.common.http.HTTPClient.json_request') + def test_quota_update(self, mock_request): + mock_request.return_value = mock_request_return + cs.quotas.update(fakes.PROJECT_ID, {'plans': 50}) + mock_request.assert_called_with( + 'PUT', + '/quotas/{project_id}'.format(project_id=fakes.PROJECT_ID), + data={'quota': {'plans': 50}}, headers={}) + + @mock.patch('karborclient.common.http.HTTPClient.json_request') + def test_show_quota(self, mock_request): + mock_request.return_value = mock_request_return + cs.quotas.get(fakes.PROJECT_ID, detail=False) + mock_request.assert_called_with( + 'GET', + '/quotas/{project_id}'.format(project_id=fakes.PROJECT_ID), + headers={}) + + @mock.patch('karborclient.common.http.HTTPClient.json_request') + def test_show_quota_with_detail(self, mock_request): + mock_request.return_value = mock_request_return + cs.quotas.get(fakes.PROJECT_ID, detail=True) + mock_request.assert_called_with( + 'GET', + '/quotas/{project_id}/detail'.format( + project_id=fakes.PROJECT_ID), + headers={}) + + @mock.patch('karborclient.common.http.HTTPClient.json_request') + def test_show_quota_with_default(self, mock_request): + mock_request.return_value = mock_request_return + cs.quotas.defaults(fakes.PROJECT_ID) + mock_request.assert_called_with( + 'GET', + '/quotas/{project_id}/defaults'.format( + project_id=fakes.PROJECT_ID), + headers={}) diff --git a/karborclient/v1/client.py b/karborclient/v1/client.py index 54394dc..e3cf0f3 100644 --- a/karborclient/v1/client.py +++ b/karborclient/v1/client.py @@ -18,6 +18,7 @@ from karborclient.v1 import operation_logs from karborclient.v1 import plans from karborclient.v1 import protectables from karborclient.v1 import providers +from karborclient.v1 import quotas from karborclient.v1 import restores from karborclient.v1 import scheduled_operations from karborclient.v1 import services @@ -50,3 +51,4 @@ class Client(object): self.verifications = verifications.VerificationManager( self.http_client) self.services = services.ServiceManager(self.http_client) + self.quotas = quotas.QuotaManager(self.http_client) diff --git a/karborclient/v1/quotas.py b/karborclient/v1/quotas.py new file mode 100644 index 0000000..f682e95 --- /dev/null +++ b/karborclient/v1/quotas.py @@ -0,0 +1,55 @@ +# 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 karborclient.common import base + + +class Quota(base.Resource): + def __repr__(self): + return "" % self._info + + +class QuotaManager(base.ManagerWithFind): + resource_class = Quota + + def list(self): + pass + + def update(self, project_id, data): + + body = {"quota": data} + + return self._update('/quotas/{project_id}' + .format(project_id=project_id), + body, "quota") + + def get(self, project_id, detail, session_id=None): + if session_id: + headers = {'X-Configuration-Session': session_id} + else: + headers = {} + base_url = "/quotas/{project_id}".format( + project_id=project_id) + if detail: + url = base_url + '/detail' + else: + url = base_url + return self._get(url, response_key="quota", headers=headers) + + def defaults(self, project_id, session_id=None): + if session_id: + headers = {'X-Configuration-Session': session_id} + else: + headers = {} + url = "/quotas/{project_id}/defaults".format( + project_id=project_id) + return self._get(url, response_key="quota", headers=headers) diff --git a/karborclient/v1/shell.py b/karborclient/v1/shell.py index c0a2aa4..a788314 100644 --- a/karborclient/v1/shell.py +++ b/karborclient/v1/shell.py @@ -1287,3 +1287,70 @@ def do_service_disable(cs, args): result = cs.services.disable(args.service_id) utils.print_list([result], ["Id", "Binary", "Host", "Status", "State", "Updated_at", "Disabled Reason"]) + + +@utils.arg( + '--tenant', + metavar='', + default=None, + help='ID of tenant to list the quotas for.') +@utils.arg( + '--detail', + action='store_true', + help='Optional flag to indicate whether to show quota in detail. ' + 'Default false.') +def do_quota_show(cs, args): + """List the quotas for a tenant.""" + project_id = args.tenant or cs.http_client.get_project_id() + kwargs = { + "project_id": project_id, + "detail": args.detail, + } + result = cs.quotas.get(**kwargs) + _quota_set_pretty_show(result) + + +def _quota_set_pretty_show(quotas): + """Convert quotas object to dict and display.""" + + new_quotas = {} + for quota_k, quota_v in sorted(quotas.to_dict().items()): + if isinstance(quota_v, dict): + quota_v = '\n'.join( + ['%s = %s' % (k, v) for k, v in sorted(quota_v.items())]) + new_quotas[quota_k] = quota_v + + utils.print_dict(new_quotas) + + +@utils.arg( + 'tenant', + metavar='', + help='ID of tenant to set the quotas for.') +@utils.arg( + '--plans', + metavar='', + type=int, + default=None, + help='New value for the "plans" quota.') +def do_quota_update(cs, args): + """Update the quotas for a project (Admin only).""" + project_id = args.tenant + data = { + "plans": args.plans, + } + result = cs.quotas.update(project_id, data) + _quota_set_pretty_show(result) + + +@utils.arg( + '--tenant', + metavar='', + default=None, + help='ID of tenant to list the quotas for.') +def do_quota_defaults(cs, args): + """List the default quotas for a tenant.""" + project_id = args.tenant or cs.http_client.get_project_id() + + result = cs.quotas.defaults(project_id) + _quota_set_pretty_show(result)