Merge "Validate project-id on quota create"

This commit is contained in:
Jenkins 2017-02-23 02:02:52 +00:00 committed by Gerrit Code Review
commit 121521934a
4 changed files with 59 additions and 7 deletions

View File

@ -23,6 +23,7 @@ from magnum.api.controllers.v1 import collection
from magnum.api.controllers.v1 import types
from magnum.api import expose
from magnum.api import utils as api_utils
from magnum.api import validation
from magnum.common import exception
from magnum.common import policy
from magnum.i18n import _
@ -164,6 +165,7 @@ class QuotaController(base.Controller):
return Quota.convert(quota)
@expose.expose(Quota, body=Quota, status_code=201)
@validation.enforce_valid_project_id_on_create()
def post(self, quota):
"""Create Quota.

View File

@ -17,7 +17,10 @@ import decorator
import pecan
from keystoneauth1 import exceptions as ka_exception
from magnum.api import utils as api_utils
from magnum.common import clients
from magnum.common import exception
import magnum.conf
from magnum.drivers.common import driver
@ -44,6 +47,26 @@ def enforce_cluster_type_supported():
return wrapper
def enforce_valid_project_id_on_create():
@decorator.decorator
def wrapper(func, *args, **kwargs):
quota = args[1]
_validate_project_id(quota.project_id)
return func(*args, **kwargs)
return wrapper
def _validate_project_id(project_id):
try:
context = pecan.request.context
osc = clients.OpenStackClients(context)
osc.keystone().domain_admin_client.projects.get(project_id)
except ka_exception.http.NotFound:
raise exception.ProjectNotFound(name='project_id',
id=project_id)
def enforce_network_driver_types_create():
@decorator.decorator
def wrapper(func, *args, **kwargs):

View File

@ -124,6 +124,11 @@ class ObjectNotFound(MagnumException):
message = _("The %(name)s %(id)s could not be found.")
class ProjectNotFound(ObjectNotFound):
message = _("The %(name)s %(id)s could not be found.")
code = 404
class ResourceNotFound(ObjectNotFound):
message = _("The %(name)s resource %(id)s could not be found.")
code = 404

View File

@ -12,7 +12,10 @@
import mock
from keystoneauth1 import exceptions as ka_exception
from magnum.api.controllers.v1 import quota as api_quota
from magnum.common import clients
from magnum.tests import base
from magnum.tests.unit.api import base as api_base
from magnum.tests.unit.api import utils as apiutils
@ -169,14 +172,28 @@ class TestQuota(api_base.FunctionalTest):
self.assertEqual(1, len(response['quotas']))
self.assertEqual('proj-id-2', response['quotas'][0]['project_id'])
def test_create_quota(self):
@mock.patch.object(clients.OpenStackClients, 'keystone')
def test_create_quota(self, mock_keystone):
quota_dict = apiutils.quota_post_data()
response = self.post_json('/quotas', quota_dict)
self.assertEqual('application/json', response.content_type)
self.assertEqual(201, response.status_int)
self.assertEqual(quota_dict['project_id'], response.json['project_id'])
def test_create_quota_invalid_resource(self):
@mock.patch.object(clients.OpenStackClients, 'keystone')
def test_create_quota_project_id_not_found(self, mock_keystone):
keystone = mock.MagicMock()
exp = ka_exception.http.NotFound()
keystone.domain_admin_client.projects .get.side_effect = exp
mock_keystone.return_value = keystone
quota_dict = apiutils.quota_post_data()
response = self.post_json('/quotas', quota_dict, expect_errors=True)
self.assertEqual('application/json', response.content_type)
self.assertEqual(404, response.status_int)
self.assertTrue(response.json['errors'])
@mock.patch.object(clients.OpenStackClients, 'keystone')
def test_create_quota_invalid_resource(self, mock_keystone):
quota_dict = apiutils.quota_post_data()
quota_dict['resource'] = 'invalid-res'
response = self.post_json('/quotas', quota_dict, expect_errors=True)
@ -184,7 +201,8 @@ class TestQuota(api_base.FunctionalTest):
self.assertEqual(400, response.status_int)
self.assertTrue(response.json['errors'])
def test_create_quota_invalid_hard_limit(self):
@mock.patch.object(clients.OpenStackClients, 'keystone')
def test_create_quota_invalid_hard_limit(self, mock_keystone):
quota_dict = apiutils.quota_post_data()
quota_dict['hard_limit'] = -10
response = self.post_json('/quotas', quota_dict, expect_errors=True)
@ -192,7 +210,8 @@ class TestQuota(api_base.FunctionalTest):
self.assertEqual(400, response.status_int)
self.assertTrue(response.json['errors'])
def test_create_quota_no_project_id(self):
@mock.patch.object(clients.OpenStackClients, 'keystone')
def test_create_quota_no_project_id(self, mock_keystone):
quota_dict = apiutils.quota_post_data()
del quota_dict['project_id']
response = self.post_json('/quotas', quota_dict, expect_errors=True)
@ -200,7 +219,8 @@ class TestQuota(api_base.FunctionalTest):
self.assertEqual(400, response.status_int)
self.assertTrue(response.json['errors'])
def test_patch_quota(self):
@mock.patch.object(clients.OpenStackClients, 'keystone')
def test_patch_quota(self, mock_keystone):
quota_dict = apiutils.quota_post_data(hard_limit=5)
response = self.post_json('/quotas', quota_dict)
self.assertEqual('application/json', response.content_type)
@ -214,7 +234,8 @@ class TestQuota(api_base.FunctionalTest):
self.assertEqual(202, response.status_int)
self.assertEqual(20, response.json['hard_limit'])
def test_patch_quota_not_found(self):
@mock.patch.object(clients.OpenStackClients, 'keystone')
def test_patch_quota_not_found(self, mock_keystone):
quota_dict = apiutils.quota_post_data()
response = self.post_json('/quotas', quota_dict)
self.assertEqual('application/json', response.content_type)
@ -229,7 +250,8 @@ class TestQuota(api_base.FunctionalTest):
self.assertEqual(404, response.status_int)
self.assertTrue(response.json['errors'])
def test_delete_quota(self):
@mock.patch.object(clients.OpenStackClients, 'keystone')
def test_delete_quota(self, mock_keystone):
quota_dict = apiutils.quota_post_data()
response = self.post_json('/quotas', quota_dict)
self.assertEqual('application/json', response.content_type)