Merge "Enforce FlavorExtraSpecs Key format."
This commit is contained in:
5 changed files with 80 additions and 1 deletions
@@ -20,11 +20,11 @@ from webob import exc
from nova.api.openstack import extensions
from nova.api.openstack import wsgi
from nova.api.openstack import xmlutil
from nova.compute import flavors
from nova import db
from nova import exception
from nova.openstack.common.gettextutils import _
authorize = extensions.extension_authorizer('compute', 'flavorextraspecs')
@@ -55,6 +55,12 @@ class FlavorExtraSpecsController(object):
expl = _('No Request Body')
raise exc.HTTPBadRequest(explanation=expl)
def _check_key_names(self, keys):
try:
flavors.validate_extra_spec_keys(keys)
except exception.InvalidInput as error:
raise exc.HTTPBadRequest(explanation=error.format_message())
@wsgi.serializers(xml=ExtraSpecsTemplate)
def index(self, req, flavor_id):
"""Returns the list of extra specs for a given flavor."""
@@ -68,6 +74,7 @@ class FlavorExtraSpecsController(object):
authorize(context, action='create')
self._check_body(body)
specs = body.get('extra_specs')
self._check_key_names(specs.keys())
try:
db.flavor_extra_specs_update_or_create(context,
flavor_id,
@@ -17,6 +17,7 @@ import webob
from nova.api.openstack import extensions
from nova.api.openstack import wsgi
from nova.compute import flavors
from nova import db
from nova import exception
from nova.openstack.common.db import exception as db_exc
@@ -41,6 +42,12 @@ class FlavorExtraSpecsController(object):
expl = _('No Request Body')
raise webob.exc.HTTPBadRequest(explanation=expl)
def _check_key_names(self, keys):
try:
flavors.validate_extra_spec_keys(keys)
except exception.InvalidInput as error:
raise webob.exc.HTTPBadRequest(explanation=error.format_message())
@extensions.expected_errors(())
def index(self, req, flavor_id):
"""Returns the list of extra specs for a given flavor."""
@@ -57,6 +64,7 @@ class FlavorExtraSpecsController(object):
specs = body.get('extra_specs', {})
if not specs or type(specs) is not dict:
raise webob.exc.HTTPBadRequest(_('No or bad extra_specs provided'))
self._check_key_names(specs.keys())
try:
db.flavor_extra_specs_update_or_create(context, flavor_id,
specs)
@@ -53,6 +53,9 @@ LOG = logging.getLogger(__name__)
VALID_ID_REGEX = re.compile("^[\w\.\- ]*$")
VALID_NAME_REGEX = re.compile("^[\w\.\- ]*$", re.UNICODE)
# Validate extra specs key names.
VALID_EXTRASPEC_NAME_REGEX = re.compile(r"[\w\.\- :]+$", re.UNICODE)
def _int_or_none(val):
if val is not None:
@@ -307,3 +310,11 @@ def delete_flavor_info(metadata, *prefixes):
del metadata[to_key]
pci_request.delete_flavor_pci_info(metadata, *prefixes)
return metadata
def validate_extra_spec_keys(key_names_list):
for key_name in key_names_list:
if not VALID_EXTRASPEC_NAME_REGEX.match(key_name):
expl = _('Key Names can only contain alphanumeric characters, '
'periods, dashes, underscores, colons and spaces.')
raise exception.InvalidInput(message=expl)
@@ -13,6 +13,7 @@
# License for the specific language governing permissions and limitations
# under the License.
import mock
import webob
from nova.api.openstack.compute.contrib import flavorextraspecs
@@ -151,6 +152,30 @@ class FlavorsExtraSpecsTest(test.TestCase):
self.assertRaises(webob.exc.HTTPBadRequest, self.controller.create,
req, 1, '')
@mock.patch('nova.db.flavor_extra_specs_update_or_create')
def test_create_invalid_specs_key(self, mock_flavor_extra_specs):
invalid_keys = ("key1/", "<key>", "$$akey$", "!akey", "")
mock_flavor_extra_specs.side_effects = return_create_flavor_extra_specs
for key in invalid_keys:
body = {"extra_specs": {key: "value1"}}
req = fakes.HTTPRequest.blank('/v2/fake/flavors/1/os-extra_specs',
use_admin_context=True)
self.assertRaises(webob.exc.HTTPBadRequest, self.controller.create,
req, 1, body)
@mock.patch('nova.db.flavor_extra_specs_update_or_create')
def test_create_valid_specs_key(self, mock_flavor_extra_specs):
valid_keys = ("key1", "month.price", "I_am-a Key", "finance:g2")
mock_flavor_extra_specs.side_effects = return_create_flavor_extra_specs
for key in valid_keys:
body = {"extra_specs": {key: "value1"}}
req = fakes.HTTPRequest.blank('/v2/fake/flavors/1/os-extra_specs',
use_admin_context=True)
res_dict = self.controller.create(req, 1, body)
self.assertEqual('value1', res_dict['extra_specs'][key])
def test_update_item(self):
self.stubs.Set(nova.db,
'flavor_extra_specs_update_or_create',
@@ -13,6 +13,7 @@
# License for the specific language governing permissions and limitations
# under the License.
import mock
import webob
from nova.api.openstack.compute.plugins.v3 import flavors_extraspecs
@@ -176,6 +177,33 @@ class FlavorsExtraSpecsTest(test.TestCase):
self.assertRaises(webob.exc.HTTPConflict, self.controller.create,
req, 1, body)
@mock.patch('nova.db.flavor_extra_specs_update_or_create')
def test_create_invalid_specs_key(self, mock_flavor_extra_specs):
invalid_keys = ("key1/", "<key>", "$$akey$", "!akey", "")
mock_flavor_extra_specs.side_effects = return_create_flavor_extra_specs
for key in invalid_keys:
body = {"extra_specs": {key: "value1"}}
req = fakes.HTTPRequest.blank('/v3/flavors/1/extra-specs',
use_admin_context=True)
self.assertRaises(webob.exc.HTTPBadRequest, self.controller.create,
req, 1, body)
@mock.patch('nova.db.flavor_extra_specs_update_or_create')
def test_create_valid_specs_key(self, mock_flavor_extra_specs):
valid_keys = ("key1", "month.price", "I_am-a Key", "finance:g2")
mock_flavor_extra_specs.side_effects = return_create_flavor_extra_specs
for key in valid_keys:
body = {"extra_specs": {key: "value1"}}
req = fakes.HTTPRequest.blank('/v3/flavors/1/extra-specs',
use_admin_context=True)
res_dict = self.controller.create(req, 1, body)
self.assertEqual('value1', res_dict['extra_specs'][key])
self.assertEqual(self.controller.create.wsgi_code, 201)
def test_update_item(self):
self.stubs.Set(nova.db,
'flavor_extra_specs_update_or_create',
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.