Browse Source

OSC command for magnum quota's

Implemented Openstack command for quotas-create, quotas-update,
quotas-delete, quotas-show and quotas-list.

Change-Id: I889c2384afdf4cf113345af646b865271784c40c
Partially-Implements: blueprint deprecate-magnum-client
tags/2.10.0
M V P Nitesh 1 year ago
parent
commit
e6856282a3

+ 1
- 0
magnumclient/exceptions.py View File

@@ -30,6 +30,7 @@ class AmbiguousAuthSystem(ClientException):
30 30
     """Could not obtain token and endpoint using provided credentials."""
31 31
     pass
32 32
 
33
+
33 34
 # Alias for backwards compatibility
34 35
 AmbigiousAuthSystem = AmbiguousAuthSystem
35 36
 

+ 215
- 0
magnumclient/osc/v1/quotas.py View File

@@ -0,0 +1,215 @@
1
+# Copyright 2015 NEC Corporation.  All rights reserved.
2
+#
3
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
4
+#    not use this file except in compliance with the License. You may obtain
5
+#    a copy of the License at
6
+#
7
+#         http://www.apache.org/licenses/LICENSE-2.0
8
+#
9
+#    Unless required by applicable law or agreed to in writing, software
10
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12
+#    License for the specific language governing permissions and limitations
13
+#    under the License.
14
+
15
+from magnumclient.common import cliutils as utils
16
+from magnumclient.common import utils as magnum_utils
17
+from magnumclient.i18n import _
18
+from osc_lib.command import command
19
+
20
+QUOTA_ATTRIBUTES = [
21
+    'resource',
22
+    'created_at',
23
+    'updated_at',
24
+    'hard_limit',
25
+    'project_id',
26
+    'id'
27
+]
28
+
29
+
30
+def _show_quota(quota):
31
+    utils.print_dict(quota._info)
32
+
33
+
34
+class CreateQuotas(command.Command):
35
+    _description = _("Create a quota.")
36
+
37
+    def get_parser(self, prog_name):
38
+        parser = super(CreateQuotas, self).get_parser(prog_name)
39
+        parser.add_argument('--project-id',
40
+                            required=True,
41
+                            metavar='<project-id>',
42
+                            help='Project ID')
43
+        parser.add_argument('--resource',
44
+                            required=True,
45
+                            metavar='<resource>',
46
+                            help='Resource name.')
47
+        parser.add_argument('--hard-limit',
48
+                            metavar='<hard-limit>',
49
+                            type=int,
50
+                            default=1,
51
+                            help='Max resource limit (default: hard-limit=1)')
52
+        return parser
53
+
54
+    def take_action(self, parsed_args):
55
+        self.log.debug("take_action(%s)", parsed_args)
56
+
57
+        mag_client = self.app.client_manager.container_infra
58
+
59
+        opts = {
60
+            'project_id': parsed_args.project_id,
61
+            'resource': parsed_args.resource,
62
+            'hard_limit': parsed_args.hard_limit
63
+        }
64
+        try:
65
+            quota = mag_client.quotas.create(**opts)
66
+            _show_quota(quota)
67
+        except Exception as e:
68
+            print("Create quota for project_id %(id)s resource %(res)s failed:"
69
+                  " %(e)s" % {'id': parsed_args.project_id,
70
+                              'res': parsed_args.resource,
71
+                              'e': e})
72
+
73
+
74
+class DeleteQuotas(command.Command):
75
+    _description = _("Delete specified resource quota.")
76
+
77
+    def get_parser(self, prog_name):
78
+        parser = super(DeleteQuotas, self).get_parser(prog_name)
79
+        parser.add_argument('--project-id',
80
+                            required=True,
81
+                            metavar='<project-id>',
82
+                            help='Project ID')
83
+        parser.add_argument('--resource',
84
+                            required=True,
85
+                            metavar='<resource>',
86
+                            help='Resource name.')
87
+        return parser
88
+
89
+    def take_action(self, parsed_args):
90
+        self.log.debug("take_action(%s)", parsed_args)
91
+
92
+        mag_client = self.app.client_manager.container_infra
93
+
94
+        try:
95
+            mag_client.quotas.delete(parsed_args.project_id,
96
+                                     parsed_args.resource)
97
+            print("Request to delete quota for project id %(id)s and resource "
98
+                  "%(res)s has been accepted." % {'id': parsed_args.project_id,
99
+                                                  'res': parsed_args.resource})
100
+        except Exception as e:
101
+            print("Quota delete failed for project id %(id)s and resource "
102
+                  "%(res)s :%(e)s" % {'id': parsed_args.project_id,
103
+                                      'res': parsed_args.resource,
104
+                                      'e': e})
105
+
106
+
107
+class ShowQuotas(command.Command):
108
+    _description = _("Show details about the given project resource quota.")
109
+
110
+    def get_parser(self, prog_name):
111
+        parser = super(ShowQuotas, self).get_parser(prog_name)
112
+        parser.add_argument('--project-id',
113
+                            required=True,
114
+                            metavar='<project-id>',
115
+                            help='Project ID')
116
+        parser.add_argument('--resource',
117
+                            required=True,
118
+                            metavar='<resource>',
119
+                            help='Resource name.')
120
+        return parser
121
+
122
+    def take_action(self, parsed_args):
123
+        self.log.debug("take_action(%s)", parsed_args)
124
+
125
+        mag_client = self.app.client_manager.container_infra
126
+        project_id = parsed_args.project_id
127
+        resource = parsed_args.resource
128
+        quota = mag_client.quotas.get(project_id, resource)
129
+        _show_quota(quota)
130
+
131
+
132
+class UpdateQuotas(command.Command):
133
+    _description = _("Update information about the given "
134
+                     "project resource quota.")
135
+
136
+    def get_parser(self, prog_name):
137
+        parser = super(UpdateQuotas, self).get_parser(prog_name)
138
+        parser.add_argument('--project-id',
139
+                            required=True,
140
+                            metavar='<project-id>',
141
+                            help='Project ID')
142
+        parser.add_argument('--resource',
143
+                            required=True,
144
+                            metavar='<resource>',
145
+                            help='Resource name.')
146
+        parser.add_argument('--hard-limit',
147
+                            metavar='<hard-limit>',
148
+                            type=int,
149
+                            default=1,
150
+                            help='Max resource limit (default: hard-limit=1)')
151
+        return parser
152
+
153
+    def take_action(self, parsed_args):
154
+        self.log.debug("take_action(%s)", parsed_args)
155
+
156
+        mag_client = self.app.client_manager.container_infra
157
+
158
+        opts = {
159
+            'project_id': parsed_args.project_id,
160
+            'resource': parsed_args.resource,
161
+            'hard_limit': parsed_args.hard_limit
162
+        }
163
+        try:
164
+            quota = mag_client.quotas.update(parsed_args.project_id,
165
+                                             parsed_args.resource, opts)
166
+            _show_quota(quota)
167
+        except Exception as e:
168
+            print("Update quota for project_id %(id)s resource %(res)s failed:"
169
+                  " %(e)s" % {'id': parsed_args.project_id,
170
+                              'res': parsed_args.resource,
171
+                              'e': e})
172
+
173
+
174
+class ListQuotas(command.Command):
175
+    _description = _("Print a list of available quotas.")
176
+
177
+    def get_parser(self, prog_name):
178
+        parser = super(ListQuotas, self).get_parser(prog_name)
179
+        parser.add_argument('--marker',
180
+                            metavar='<marker>',
181
+                            default=None,
182
+                            help=_('The last quota UUID of the previous page; '
183
+                                   'displays list of quotas after "marker".'))
184
+        parser.add_argument('--limit',
185
+                            metavar='<limit>',
186
+                            type=int,
187
+                            help='Maximum number of quotas to return.')
188
+        parser.add_argument('--sort-key',
189
+                            metavar='<sort-key>',
190
+                            help='Column to sort results by.')
191
+        parser.add_argument('--sort-dir',
192
+                            metavar='<sort-dir>',
193
+                            choices=['desc', 'asc'],
194
+                            help='Direction to sort. "asc" or "desc".')
195
+        parser.add_argument('--all-tenants',
196
+                            action='store_true',
197
+                            default=False,
198
+                            help='Flag to indicate list all tenant quotas.')
199
+        return parser
200
+
201
+    def take_action(self, parsed_args):
202
+        self.log.debug("take_action(%s)", parsed_args)
203
+
204
+        mag_client = self.app.client_manager.container_infra
205
+
206
+        quotas = mag_client.quotas.list(marker=parsed_args.marker,
207
+                                        limit=parsed_args.limit,
208
+                                        sort_key=parsed_args.sort_key,
209
+                                        sort_dir=parsed_args.sort_dir,
210
+                                        all_tenants=parsed_args.all_tenants)
211
+        columns = ['project_id', 'resource', 'hard_limit']
212
+        utils.print_list(quotas, columns,
213
+                         {'versions':
214
+                          magnum_utils.print_list_field('versions')},
215
+                         sortby_index=None)

+ 43
- 0
magnumclient/tests/osc/unit/v1/fakes.py View File

@@ -51,6 +51,17 @@ class FakeStatsModelManager(object):
51 51
         pass
52 52
 
53 53
 
54
+class FakeQuotasModelManager(object):
55
+    def get(self, id, resource):
56
+        pass
57
+
58
+    def create(self, **kwargs):
59
+        pass
60
+
61
+    def delete(self, id):
62
+        pass
63
+
64
+
54 65
 class MagnumFakeContainerInfra(object):
55 66
     def __init__(self):
56 67
         self.cluster_templates = FakeBaseModelManager()
@@ -58,6 +69,7 @@ class MagnumFakeContainerInfra(object):
58 69
         self.mservices = FakeBaseModelManager()
59 70
         self.certificates = FakeBaseModelManager()
60 71
         self.stats = FakeStatsModelManager()
72
+        self.quotas = FakeQuotasModelManager()
61 73
 
62 74
 
63 75
 class MagnumFakeClientManager(osc_fakes.FakeClientManager):
@@ -223,3 +235,34 @@ class FakeCluster(object):
223 235
         cluster = osc_fakes.FakeResource(info=copy.deepcopy(cluster_info),
224 236
                                          loaded=True)
225 237
         return cluster
238
+
239
+
240
+class FakeQuota(object):
241
+    """Fake one or more Quota"""
242
+
243
+    @staticmethod
244
+    def create_one_quota(attrs=None):
245
+        """Create a fake quota
246
+
247
+        :param Dictionary attrs:
248
+            A dictionary with all attributes
249
+        :return:
250
+            A FakeResource object, with project_id, resource and so on
251
+        """
252
+
253
+        attrs = attrs or {}
254
+
255
+        quota_info = {
256
+            'resource': 'Cluster',
257
+            'created_at': '2017-09-15T05:40:34+00:00',
258
+            'updated_at': '2017-09-15T05:40:34+00:00',
259
+            'hard_limit': 1,
260
+            'project_id': 'be24b6fba2ed4476b2bd01fa8f0ba74e',
261
+            'id': 10,
262
+            'name': 'fake-quota',
263
+        }
264
+
265
+        quota_info.update(attrs)
266
+        quota = osc_fakes.FakeResource(info=copy.deepcopy(quota_info),
267
+                                       loaded=True)
268
+        return quota

+ 146
- 0
magnumclient/tests/osc/unit/v1/test_clusters.py View File

@@ -15,8 +15,18 @@
15 15
 
16 16
 import copy
17 17
 import mock
18
+import os
19
+import sys
20
+import tempfile
21
+
22
+from contextlib import contextmanager
23
+try:
24
+    from StringIO import StringIO
25
+except ImportError:
26
+    from io import StringIO
18 27
 from mock import call
19 28
 
29
+from magnumclient import exceptions
20 30
 from magnumclient.osc.v1 import clusters as osc_clusters
21 31
 from magnumclient.tests.osc.unit.v1 import fakes as magnum_fakes
22 32
 
@@ -327,3 +337,139 @@ class TestClusterShow(TestCluster):
327 337
 
328 338
         self.assertRaises(magnum_fakes.MagnumParseException,
329 339
                           self.check_parser, self.cmd, arglist, verifylist)
340
+
341
+
342
+@contextmanager
343
+def capture(command, *args, **kwargs):
344
+    out, sys.stdout = sys.stdout, StringIO()
345
+    try:
346
+        command(*args, **kwargs)
347
+        sys.stdout.seek(0)
348
+        yield sys.stdout.read()
349
+    finally:
350
+        sys.stdout = out
351
+
352
+
353
+class TestClusterConfig(TestCluster):
354
+
355
+    def setUp(self):
356
+        super(TestClusterConfig, self).setUp()
357
+
358
+        attr = dict()
359
+        attr['name'] = 'fake-cluster-1'
360
+        attr['status'] = 'CREATE_COMPLETE'
361
+        self._cluster = magnum_fakes.FakeCluster.create_one_cluster(attr)
362
+
363
+        self.clusters_mock.get = mock.Mock()
364
+        self.clusters_mock.get.return_value = self._cluster
365
+
366
+        # Fake the cluster_template
367
+        attr = dict()
368
+        attr['name'] = 'fake-ct'
369
+        attr['tls_disabled'] = True
370
+        self._cluster_template = \
371
+            magnum_fakes.FakeClusterTemplate.create_one_cluster_template(attr)
372
+
373
+        self.cluster_templates_mock = \
374
+            self.app.client_manager.container_infra.cluster_templates
375
+        self.cluster_templates_mock.get = mock.Mock()
376
+        self.cluster_templates_mock.get.return_value = self._cluster_template
377
+
378
+        # Get the command object to test
379
+        self.cmd = osc_clusters.ConfigCluster(self.app, None)
380
+
381
+    def test_cluster_config_no_cluster_fail(self):
382
+        arglist = []
383
+        verifylist = []
384
+
385
+        self.assertRaises(magnum_fakes.MagnumParseException,
386
+                          self.check_parser, self.cmd, arglist, verifylist)
387
+
388
+    @mock.patch.dict(os.environ, {'SHELL': '/bin/bash'})
389
+    def test_cluster_config_custom_dir_with_config_only_works_if_force(self):
390
+        tmp_dir = tempfile.mkdtemp()
391
+        open(os.path.join(tmp_dir, 'config'), 'a').close()  # touch config
392
+
393
+        arglist = ['fake-cluster', '--dir', tmp_dir]
394
+        verifylist = [
395
+            ('cluster', 'fake-cluster'),
396
+            ('force', False),
397
+            ('dir', tmp_dir),
398
+        ]
399
+        parsed_args = self.check_parser(self.cmd, arglist, verifylist)
400
+        self.assertRaises(exceptions.CommandError,
401
+                          self.cmd.take_action, parsed_args)
402
+
403
+        self.clusters_mock.get.assert_called_with('fake-cluster')
404
+
405
+        arglist = ['fake-cluster', '--force', '--dir', tmp_dir]
406
+        verifylist = [
407
+            ('cluster', 'fake-cluster'),
408
+            ('force', True),
409
+            ('dir', tmp_dir),
410
+        ]
411
+
412
+        parsed_args = self.check_parser(self.cmd, arglist, verifylist)
413
+        expected_value = '''\
414
+export KUBECONFIG={}/config
415
+
416
+'''.format(tmp_dir)
417
+
418
+        with capture(self.cmd.take_action, parsed_args) as output:
419
+            self.assertEqual(expected_value, output)
420
+
421
+        self.clusters_mock.get.assert_called_with('fake-cluster')
422
+
423
+    @mock.patch.dict(os.environ, {'SHELL': '/bin/bash'})
424
+    def test_cluster_config_with_custom_dir(self):
425
+        tmp_dir = tempfile.mkdtemp()
426
+
427
+        arglist = ['fake-cluster', '--dir', tmp_dir]
428
+        verifylist = [
429
+            ('cluster', 'fake-cluster'),
430
+            ('dir', tmp_dir),
431
+        ]
432
+        parsed_args = self.check_parser(self.cmd, arglist, verifylist)
433
+
434
+        expected_value = '''\
435
+export KUBECONFIG={}/config
436
+
437
+'''.format(tmp_dir)
438
+
439
+        with capture(self.cmd.take_action, parsed_args) as output:
440
+            self.assertEqual(expected_value, output)
441
+
442
+        self.clusters_mock.get.assert_called_with('fake-cluster')
443
+
444
+    @mock.patch.dict(os.environ, {'SHELL': '/bin/bash'})
445
+    def test_cluster_config_creates_config_in_cwd_if_not_dir_specified(self):
446
+        tmp_dir = tempfile.mkdtemp()
447
+        os.chdir(tmp_dir)
448
+
449
+        arglist = ['fake-cluster']
450
+        verifylist = [
451
+            ('cluster', 'fake-cluster'),
452
+        ]
453
+
454
+        parsed_args = self.check_parser(self.cmd, arglist, verifylist)
455
+        expected_value = '''\
456
+export KUBECONFIG={}/config
457
+
458
+'''.format(os.getcwd())
459
+
460
+        with capture(self.cmd.take_action, parsed_args) as output:
461
+            self.assertEqual(expected_value, output)
462
+
463
+        self.clusters_mock.get.assert_called_with('fake-cluster')
464
+
465
+    def test_cluster_config_with_in_progress_status(self):
466
+        self._cluster.status = 'CREATE_IN_PROGRESS'
467
+
468
+        arglist = ['fake-cluster-1']
469
+        verifylist = [
470
+            ('cluster', 'fake-cluster-1')
471
+        ]
472
+
473
+        parsed_args = self.check_parser(self.cmd, arglist, verifylist)
474
+        self.assertRaises(exceptions.CommandError,
475
+                          self.cmd.take_action, parsed_args)

+ 315
- 0
magnumclient/tests/osc/unit/v1/test_quotas.py View File

@@ -0,0 +1,315 @@
1
+# Copyright 2015 NEC Corporation.  All rights reserved.
2
+#
3
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
4
+#    not use this file except in compliance with the License. You may obtain
5
+#    a copy of the License at
6
+#
7
+#         http://www.apache.org/licenses/LICENSE-2.0
8
+#
9
+#    Unless required by applicable law or agreed to in writing, software
10
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12
+#    License for the specific language governing permissions and limitations
13
+#    under the License.
14
+import mock
15
+
16
+from magnumclient.osc.v1 import quotas as osc_quotas
17
+from magnumclient.tests.osc.unit.v1 import fakes as magnum_fakes
18
+
19
+
20
+class TestQuotas(magnum_fakes.TestMagnumClientOSCV1):
21
+
22
+    def setUp(self):
23
+        super(TestQuotas, self).setUp()
24
+
25
+        self.quotas_mock = self.app.client_manager.container_infra.quotas
26
+
27
+
28
+class TestQuotasCreate(TestQuotas):
29
+
30
+    def setUp(self):
31
+        super(TestQuotasCreate, self).setUp()
32
+        attr = dict()
33
+        attr['name'] = 'fake-quota'
34
+        attr['project_id'] = 'abc'
35
+        attr['resource'] = 'Cluster'
36
+        self._quota = magnum_fakes.FakeQuota.create_one_quota(attr)
37
+
38
+        self._default_args = {
39
+            'project_id': 'abc',
40
+            'resource': 'Cluster',
41
+            'hard_limit': 1
42
+        }
43
+
44
+        self.quotas_mock.create = mock.Mock()
45
+        self.quotas_mock.create.return_value = self._quota
46
+
47
+        self.cmd = osc_quotas.CreateQuotas(self.app, None)
48
+
49
+        self.data = tuple(map(lambda x: getattr(self._quota, x),
50
+                              osc_quotas.QUOTA_ATTRIBUTES))
51
+
52
+    def test_quotas_create(self):
53
+        arglist = [
54
+            '--project-id', 'abc',
55
+            '--resource', 'Cluster'
56
+        ]
57
+        verifylist = [
58
+            ('project_id', 'abc'),
59
+            ('resource', 'Cluster')
60
+        ]
61
+        parsed_args = self.check_parser(self.cmd, arglist, verifylist)
62
+        self.cmd.take_action(parsed_args)
63
+        self.quotas_mock.create.assert_called_with(**self._default_args)
64
+
65
+    def test_quotas_create_with_hardlimit(self):
66
+        arglist = [
67
+            '--project-id', 'abc',
68
+            '--resource', 'Cluster',
69
+            '--hard-limit', '10'
70
+        ]
71
+        verifylist = [
72
+            ('project_id', 'abc'),
73
+            ('resource', 'Cluster'),
74
+            ('hard_limit', 10)
75
+        ]
76
+        self._default_args['hard_limit'] = 10
77
+        parsed_args = self.check_parser(self.cmd, arglist, verifylist)
78
+
79
+        self.cmd.take_action(parsed_args)
80
+        self.quotas_mock.create.assert_called_with(**self._default_args)
81
+
82
+    def test_quotas_create_wrong_projectid(self):
83
+        arglist = ['abcd']
84
+        verifylist = [
85
+            ('project_id', 'abcd')
86
+        ]
87
+
88
+        self.assertRaises(magnum_fakes.MagnumParseException,
89
+                          self.check_parser, self.cmd, arglist, verifylist)
90
+
91
+    def test_quotas_create_missing_args(self):
92
+        arglist = []
93
+        verifylist = []
94
+        self.assertRaises(magnum_fakes.MagnumParseException,
95
+                          self.check_parser, self.cmd, arglist, verifylist)
96
+
97
+    def test_quotas_create_with_wrong_args(self):
98
+        arglist = [
99
+            '--project-id', 'abc',
100
+            '--resources', 'Cluster',  # Misspelling 'resources'
101
+            '--hard-limit', '10'
102
+        ]
103
+        verifylist = []
104
+        self.assertRaises(magnum_fakes.MagnumParseException,
105
+                          self.check_parser, self.cmd, arglist, verifylist)
106
+
107
+
108
+class TestQuotasDelete(TestQuotas):
109
+
110
+    def setUp(self):
111
+        super(TestQuotasDelete, self).setUp()
112
+
113
+        self.quotas_mock.delete = mock.Mock()
114
+        self.quotas_mock.delete.return_value = None
115
+
116
+        self.cmd = osc_quotas.DeleteQuotas(self.app, None)
117
+
118
+    def test_quotas_delete(self):
119
+        arglist = [
120
+            '--project-id', 'abc',
121
+            '--resource', 'Cluster'
122
+        ]
123
+        verifylist = [
124
+            ('project_id', 'abc'),
125
+            ('resource', 'Cluster')
126
+        ]
127
+
128
+        parsed_args = self.check_parser(self.cmd, arglist, verifylist)
129
+        self.cmd.take_action(parsed_args)
130
+        self.quotas_mock.delete.assert_called_with('abc', 'Cluster')
131
+
132
+    def test_quotas_delete_no_project_id(self):
133
+        arglist = [
134
+            '--resource', 'Cluster'
135
+        ]
136
+        verifylist = [
137
+            ('resource', 'Cluster')
138
+        ]
139
+        self.assertRaises(magnum_fakes.MagnumParseException,
140
+                          self.check_parser, self.cmd, arglist, verifylist)
141
+
142
+    def test_quotas_delete_no_resource(self):
143
+        arglist = [
144
+            '--project-id', 'abc',
145
+        ]
146
+        verifylist = [
147
+            ('project_id', 'abc')
148
+        ]
149
+        self.assertRaises(magnum_fakes.MagnumParseException,
150
+                          self.check_parser, self.cmd, arglist, verifylist)
151
+
152
+    def test_quotas_delete_missing_args(self):
153
+        arglist = []
154
+        verifylist = []
155
+        self.assertRaises(magnum_fakes.MagnumParseException,
156
+                          self.check_parser, self.cmd, arglist, verifylist)
157
+
158
+    def test_quotas_delete_wrong_args(self):
159
+        arglist = [
160
+            '--project-ids', 'abc',  # Misspelling 'ids' instead of 'id'
161
+            '--resource', 'Cluster'
162
+        ]
163
+        verifylist = []
164
+        self.assertRaises(magnum_fakes.MagnumParseException,
165
+                          self.check_parser, self.cmd, arglist, verifylist)
166
+
167
+
168
+class TestQuotasShow(TestQuotas):
169
+
170
+    def setUp(self):
171
+        super(TestQuotasShow, self).setUp()
172
+
173
+        attr = dict()
174
+        attr['name'] = 'fake-quota'
175
+        attr['project_id'] = 'abc'
176
+        attr['resource'] = 'Cluster'
177
+        self._quota = magnum_fakes.FakeQuota.create_one_quota(attr)
178
+
179
+        self._default_args = {
180
+            'project_id': 'abc',
181
+            'resource': 'Cluster',
182
+        }
183
+
184
+        self.quotas_mock.get = mock.Mock()
185
+        self.quotas_mock.get.return_value = self._quota
186
+
187
+        self.cmd = osc_quotas.ShowQuotas(self.app, None)
188
+
189
+        self.data = tuple(map(lambda x: getattr(self._quota, x),
190
+                              osc_quotas.QUOTA_ATTRIBUTES))
191
+
192
+    def test_quotas_show(self):
193
+        arglist = [
194
+            '--project-id', 'abc',
195
+            '--resource', 'Cluster'
196
+        ]
197
+        verifylist = [
198
+            ('project_id', 'abc'),
199
+            ('resource', 'Cluster')
200
+        ]
201
+        parsed_args = self.check_parser(self.cmd, arglist, verifylist)
202
+        self.cmd.take_action(parsed_args)
203
+        self.quotas_mock.get.assert_called_with('abc', 'Cluster')
204
+
205
+    def test_quotas_show_missing_args(self):
206
+        arglist = []
207
+        verifylist = []
208
+        self.assertRaises(magnum_fakes.MagnumParseException,
209
+                          self.check_parser, self.cmd, arglist, verifylist)
210
+
211
+
212
+class TestQuotasUpdate(TestQuotas):
213
+
214
+    def setUp(self):
215
+        super(TestQuotasUpdate, self).setUp()
216
+        attr = dict()
217
+        attr['name'] = 'fake-quota'
218
+        attr['project_id'] = 'abc'
219
+        attr['resource'] = 'Cluster'
220
+        self._quota = magnum_fakes.FakeQuota.create_one_quota(attr)
221
+
222
+        self._default_args = {
223
+            'project_id': 'abc',
224
+            'resource': 'Cluster',
225
+            'hard_limit': 10
226
+        }
227
+
228
+        self.quotas_mock.update = mock.Mock()
229
+        self.quotas_mock.update.return_value = self._quota
230
+
231
+        self.cmd = osc_quotas.UpdateQuotas(self.app, None)
232
+
233
+    def test_quotas_update(self):
234
+        arglist = [
235
+            '--project-id', 'abc',
236
+            '--resource', 'Cluster',
237
+            '--hard-limit', '10'
238
+        ]
239
+        verifylist = [
240
+            ('project_id', 'abc'),
241
+            ('resource', 'Cluster'),
242
+            ('hard_limit', 10)
243
+        ]
244
+        parsed_args = self.check_parser(self.cmd, arglist, verifylist)
245
+        self.cmd.take_action(parsed_args)
246
+        self.quotas_mock.update.assert_called_with('abc', 'Cluster',
247
+                                                   self._default_args)
248
+
249
+    def test_quotas_update_missing_args(self):
250
+        arglist = ['abcd']
251
+        verifylist = [
252
+            ('project_id', 'abcd')
253
+        ]
254
+
255
+        self.assertRaises(magnum_fakes.MagnumParseException,
256
+                          self.check_parser, self.cmd, arglist, verifylist)
257
+
258
+    def test_quotas_update_wrong_args(self):
259
+        arglist = [
260
+            '--project-id', 'abc',
261
+            '--resource', 'Cluster',
262
+            '--hard-limits', '10'  # Misspelling 'hard-limits'
263
+        ]
264
+        verifylist = [
265
+            ('project_id', 'abc'),
266
+            ('resource', 'Cluster'),
267
+            ('hard_limit', 10)
268
+        ]
269
+
270
+        self.assertRaises(magnum_fakes.MagnumParseException,
271
+                          self.check_parser, self.cmd, arglist, verifylist)
272
+
273
+
274
+class TestQuotasList(TestQuotas):
275
+
276
+    def setUp(self):
277
+        super(TestQuotasList, self).setUp()
278
+        attr = dict()
279
+        attr['name'] = 'fake-quota'
280
+        attr['project_id'] = 'abc'
281
+        attr['resource'] = 'Cluster'
282
+        self._quota = magnum_fakes.FakeQuota.create_one_quota(attr)
283
+
284
+        self.quotas_mock.list = mock.Mock()
285
+        self.quotas_mock.list.return_value = [self._quota]
286
+
287
+        self.cmd = osc_quotas.ListQuotas(self.app, None)
288
+
289
+    def test_quotas_list_with_no_options(self):
290
+        arglist = [
291
+        ]
292
+        verifylist = [
293
+            ('limit', None),
294
+            ('sort_key', None),
295
+            ('sort_dir', None),
296
+            ('marker', None),
297
+            ('all_tenants', False)
298
+        ]
299
+        parsed_args = self.check_parser(self.cmd, arglist, verifylist)
300
+        self.cmd.take_action(parsed_args)
301
+        self.quotas_mock.list.assert_called_with(
302
+            limit=None,
303
+            sort_dir=None,
304
+            sort_key=None,
305
+            marker=None,
306
+            all_tenants=False
307
+        )
308
+
309
+    def test_quotas_list_wrong_args(self):
310
+        arglist = ['--wrong']
311
+        verifylist = [
312
+            ('wrong')
313
+        ]
314
+        self.assertRaises(magnum_fakes.MagnumParseException,
315
+                          self.check_parser, self.cmd, arglist, verifylist)

+ 5
- 0
magnumclient/v1/quotas_shell.py View File

@@ -39,6 +39,7 @@ def _show_quota(quota):
39 39
            action='store_true',
40 40
            default=False,
41 41
            help=_('Flag to indicate list all tenant quotas.'))
42
+@utils.deprecated(utils.MAGNUM_CLIENT_DEPRECATION_WARNING)
42 43
 def do_quotas_list(cs, args):
43 44
     """Print a list of available quotas."""
44 45
     quotas = cs.quotas.list(marker=args.marker,
@@ -65,6 +66,7 @@ def do_quotas_list(cs, args):
65 66
            type=int,
66 67
            default=1,
67 68
            help=_('Max resource limit.'))
69
+@utils.deprecated(utils.MAGNUM_CLIENT_DEPRECATION_WARNING)
68 70
 def do_quotas_create(cs, args):
69 71
     """Create a quota."""
70 72
 
@@ -91,6 +93,7 @@ def do_quotas_create(cs, args):
91 93
            required=True,
92 94
            metavar='<resource>',
93 95
            help=_('Resource name'))
96
+@utils.deprecated(utils.MAGNUM_CLIENT_DEPRECATION_WARNING)
94 97
 def do_quotas_delete(cs, args):
95 98
     """Delete specified resource quota."""
96 99
     try:
@@ -113,6 +116,7 @@ def do_quotas_delete(cs, args):
113 116
            required=True,
114 117
            metavar='<resource>',
115 118
            help=_('Resource name'))
119
+@utils.deprecated(utils.MAGNUM_CLIENT_DEPRECATION_WARNING)
116 120
 def do_quotas_show(cs, args):
117 121
     """Show details about the given project resource quota."""
118 122
     quota = cs.quotas.get(args.project_id, args.resource)
@@ -132,6 +136,7 @@ def do_quotas_show(cs, args):
132 136
            type=int,
133 137
            default=1,
134 138
            help=_('Max resource limit.'))
139
+@utils.deprecated(utils.MAGNUM_CLIENT_DEPRECATION_WARNING)
135 140
 def do_quotas_update(cs, args):
136 141
     """Update information about the given project resource quota."""
137 142
     patch = dict()

+ 6
- 0
releasenotes/notes/partial_osc_implementation_for_quotas-33f44c0496d721f8.yaml View File

@@ -0,0 +1,6 @@
1
+---
2
+features:
3
+  - |
4
+    Implemented Openstack command for quotas-create,
5
+    quotas-update, quotas-delete, quotas-show and
6
+    quotas-list

+ 5
- 0
setup.cfg View File

@@ -46,6 +46,11 @@ openstack.container_infra.v1 =
46 46
     coe_ca_show = magnumclient.osc.v1.certificates:ShowCa
47 47
     coe_ca_sign = magnumclient.osc.v1.certificates:SignCa
48 48
     coe_stats_list = magnumclient.osc.v1.stats:ListStats
49
+    coe_quotas_create = magclient.osc.v1.quotas:CreateQuotas
50
+    coe_quotas_delete = magclient.osc.v1.quotas:DeleteQuotas
51
+    coe_quotas_update = magclient.osc.v1.quotas:UpdateQuotas
52
+    coe_quotas_show = magclient.osc.v1.quotas:ShowQuotas
53
+    coe_quotas_list = magclient.osc.v1.quotas:ListQuotas
49 54
 
50 55
     coe_service_list = magnumclient.osc.v1.mservices:ListService
51 56
 

Loading…
Cancel
Save