Return default quota from API

Currently the dashboard and magnum clients are unable to get the default
quota of a project, if a project does not have a quota set. This is due
to the API returning a QuotaNotFound exception, rather than falling back
to the default quota.

The result is that dashboard is not displaying quotas correctly. It also
means users are not able to see their default quota.

This patch updates the API by returning the default quota instead of a
QuotaNotFound exception. This makes magnum behave similarly to how other
projects like designate handles quota.

Story: 2006307
Task: 36029
Change-Id: I1b278d221d0f15d92d67869cd3ac897d041eaf90
This commit is contained in:
Jake Yip 2019-07-31 17:20:09 +10:00 committed by Feilong Wang
parent eebcc9b7a1
commit 6bb95dac2e
2 changed files with 38 additions and 12 deletions

View File

@ -25,10 +25,13 @@ from magnum.api import utils as api_utils
from magnum.api import validation
from magnum.common import exception
from magnum.common import policy
import magnum.conf
from magnum.i18n import _
from magnum import objects
from magnum.objects import fields
CONF = magnum.conf.CONF
class Quota(base.APIBase):
"""API representation of a project Quota.
@ -157,10 +160,16 @@ class QuotaController(base.Controller):
if not context.is_admin and project_id != context.project_id:
raise exception.NotAuthorized()
quota = objects.Quota.get_quota_by_project_id_resource(context,
project_id,
resource)
return Quota.convert(quota)
try:
quota = objects.Quota.get_quota_by_project_id_resource(context,
project_id,
resource)
quota = Quota.convert(quota)
except exception.QuotaNotFound:
# If explicit quota was not set for the project, use default limit
quota = Quota(project_id=project_id,
hard_limit=CONF.quotas.max_clusters_per_project)
return quota
@expose.expose(Quota, body=Quota, status_code=201)
@validation.enforce_valid_project_id_on_create()

View File

@ -16,11 +16,14 @@ from keystoneauth1 import exceptions as ka_exception
from magnum.api.controllers.v1 import quota as api_quota
from magnum.common import clients
import magnum.conf
from magnum.tests import base
from magnum.tests.unit.api import base as api_base
from magnum.tests.unit.api import utils as apiutils
from magnum.tests.unit.objects import utils as obj_utils
CONF = magnum.conf.CONF
class TestQuotaObject(base.TestCase):
def test_quota_init(self):
@ -60,14 +63,27 @@ class TestQuota(api_base.FunctionalTest):
self.assertEqual(quota.resource, response['resource'])
@mock.patch("magnum.common.policy.enforce")
def test_get_one_not_found(self, mock_policy):
def test_get_one_no_config_default(self, mock_policy):
mock_policy.return_value = True
response = self.get_json(
'/quotas/fake_project/invalid_res',
'/quotas/fake_project/Cluster',
expect_errors=True)
self.assertEqual(404, response.status_int)
self.assertEqual('application/json', response.content_type)
self.assertTrue(response.json['errors'])
self.assertEqual(200, response.status_int)
self.assertEqual('fake_project', response.json['project_id'])
self.assertEqual(CONF.quotas.max_clusters_per_project,
response.json['hard_limit'])
@mock.patch("magnum.common.policy.enforce")
def test_get_one_with_config_default(self, mock_policy):
mock_policy.return_value = True
quota = 15
CONF.set_override('max_clusters_per_project', quota, group='quotas')
response = self.get_json(
'/quotas/fake_project/Cluster',
expect_errors=True)
self.assertEqual(200, response.status_int)
self.assertEqual('fake_project', response.json['project_id'])
self.assertEqual(quota, response.json['hard_limit'])
def test_get_one_not_authorized(self):
obj_utils.create_test_quota(self.context)
@ -300,6 +316,7 @@ class TestQuota(api_base.FunctionalTest):
response = self.get_json(
'/quotas/%s/%s' % (project_id, resource),
expect_errors=True)
self.assertEqual(404, response.status_int)
self.assertEqual('application/json', response.content_type)
self.assertTrue(response.json['errors'])
self.assertEqual(200, response.status_int)
self.assertEqual('fake_project', response.json['project_id'])
self.assertEqual(CONF.quotas.max_clusters_per_project,
response.json['hard_limit'])