Fix flavor profile API handling of None updates
The current flavor profile API does not properly handle clearing/reseting values on update. Some mandatory fields would return a database "cannot be Null" error. This patch raises the proper invalid option execption. Story: 2005374 Task: 33542 Change-Id: I5253c48871a8bb3bf91f82aa7791585cc4a6d529
This commit is contained in:
parent
21a54d6b78
commit
ab8a263674
@ -111,6 +111,24 @@ class FlavorProfileController(base.BaseController):
|
|||||||
db_flavor_profile, profile_types.FlavorProfileResponse)
|
db_flavor_profile, profile_types.FlavorProfileResponse)
|
||||||
return profile_types.FlavorProfileRootResponse(flavorprofile=result)
|
return profile_types.FlavorProfileRootResponse(flavorprofile=result)
|
||||||
|
|
||||||
|
def _validate_update_fp(self, context, id, flavorprofile):
|
||||||
|
if flavorprofile.name is None:
|
||||||
|
raise exceptions.InvalidOption(value=None, option=constants.NAME)
|
||||||
|
if flavorprofile.provider_name is None:
|
||||||
|
raise exceptions.InvalidOption(value=None,
|
||||||
|
option=constants.PROVIDER_NAME)
|
||||||
|
if flavorprofile.flavor_data is None:
|
||||||
|
raise exceptions.InvalidOption(value=None,
|
||||||
|
option=constants.FLAVOR_DATA)
|
||||||
|
|
||||||
|
# Don't allow changes to the flavor_data or provider_name if it
|
||||||
|
# is in use.
|
||||||
|
if (not isinstance(flavorprofile.flavor_data, wtypes.UnsetType) or
|
||||||
|
not isinstance(flavorprofile.provider_name, wtypes.UnsetType)):
|
||||||
|
if self.repositories.flavor.count(context.session,
|
||||||
|
flavor_profile_id=id) > 0:
|
||||||
|
raise exceptions.ObjectInUse(object='Flavor profile', id=id)
|
||||||
|
|
||||||
@wsme_pecan.wsexpose(profile_types.FlavorProfileRootResponse,
|
@wsme_pecan.wsexpose(profile_types.FlavorProfileRootResponse,
|
||||||
wtypes.text, status_code=200,
|
wtypes.text, status_code=200,
|
||||||
body=profile_types.FlavorProfileRootPUT)
|
body=profile_types.FlavorProfileRootPUT)
|
||||||
@ -121,13 +139,7 @@ class FlavorProfileController(base.BaseController):
|
|||||||
self._auth_validate_action(context, context.project_id,
|
self._auth_validate_action(context, context.project_id,
|
||||||
constants.RBAC_PUT)
|
constants.RBAC_PUT)
|
||||||
|
|
||||||
# Don't allow changes to the flavor_data or provider_name if it
|
self._validate_update_fp(context, id, flavorprofile)
|
||||||
# is in use.
|
|
||||||
if (not isinstance(flavorprofile.flavor_data, wtypes.UnsetType) or
|
|
||||||
not isinstance(flavorprofile.provider_name, wtypes.UnsetType)):
|
|
||||||
if self.repositories.flavor.count(context.session,
|
|
||||||
flavor_profile_id=id) > 0:
|
|
||||||
raise exceptions.ObjectInUse(object='Flavor profile', id=id)
|
|
||||||
|
|
||||||
if not isinstance(flavorprofile.flavor_data, wtypes.UnsetType):
|
if not isinstance(flavorprofile.flavor_data, wtypes.UnsetType):
|
||||||
# Do a basic JSON validation on the metadata
|
# Do a basic JSON validation on the metadata
|
||||||
|
@ -340,6 +340,8 @@ BYTES_IN = 'bytes_in'
|
|||||||
BYTES_OUT = 'bytes_out'
|
BYTES_OUT = 'bytes_out'
|
||||||
REQUEST_ERRORS = 'request_errors'
|
REQUEST_ERRORS = 'request_errors'
|
||||||
TOTAL_CONNECTIONS = 'total_connections'
|
TOTAL_CONNECTIONS = 'total_connections'
|
||||||
|
NAME = 'name'
|
||||||
|
PROVIDER_NAME = 'provider_name'
|
||||||
|
|
||||||
CERT_ROTATE_AMPHORA_FLOW = 'octavia-cert-rotate-amphora-flow'
|
CERT_ROTATE_AMPHORA_FLOW = 'octavia-cert-rotate-amphora-flow'
|
||||||
CREATE_AMPHORA_FLOW = 'octavia-create-amphora-flow'
|
CREATE_AMPHORA_FLOW = 'octavia-create-amphora-flow'
|
||||||
|
@ -328,7 +328,7 @@ class TestFlavorProfiles(base.BaseAPITest):
|
|||||||
self.assertEqual('{"hello": "world"}',
|
self.assertEqual('{"hello": "world"}',
|
||||||
response.get(constants.FLAVOR_DATA))
|
response.get(constants.FLAVOR_DATA))
|
||||||
|
|
||||||
def test_update_none(self):
|
def test_update_nothing(self):
|
||||||
fp = self.create_flavor_profile('test_profile', 'noop_driver',
|
fp = self.create_flavor_profile('test_profile', 'noop_driver',
|
||||||
'{"x": "y"}')
|
'{"x": "y"}')
|
||||||
body = self._build_body({})
|
body = self._build_body({})
|
||||||
@ -340,6 +340,25 @@ class TestFlavorProfiles(base.BaseAPITest):
|
|||||||
self.assertEqual('{"x": "y"}',
|
self.assertEqual('{"x": "y"}',
|
||||||
response.get(constants.FLAVOR_DATA))
|
response.get(constants.FLAVOR_DATA))
|
||||||
|
|
||||||
|
def test_update_name_none(self):
|
||||||
|
self._test_update_param_none(constants.NAME)
|
||||||
|
|
||||||
|
def test_update_provider_name_none(self):
|
||||||
|
self._test_update_param_none(constants.PROVIDER_NAME)
|
||||||
|
|
||||||
|
def test_update_flavor_data_none(self):
|
||||||
|
self._test_update_param_none(constants.FLAVOR_DATA)
|
||||||
|
|
||||||
|
def _test_update_param_none(self, param_name):
|
||||||
|
fp = self.create_flavor_profile('test_profile', 'noop_driver',
|
||||||
|
'{"x": "y"}')
|
||||||
|
expect_error_msg = ("None is not a valid option for %s" %
|
||||||
|
param_name)
|
||||||
|
body = self._build_body({param_name: None})
|
||||||
|
response = self.put(self.FP_PATH.format(fp_id=fp.get('id')), body,
|
||||||
|
status=400)
|
||||||
|
self.assertEqual(expect_error_msg, response.json['faultstring'])
|
||||||
|
|
||||||
def test_update_no_flavor_data(self):
|
def test_update_no_flavor_data(self):
|
||||||
fp = self.create_flavor_profile('test_profile', 'noop_driver',
|
fp = self.create_flavor_profile('test_profile', 'noop_driver',
|
||||||
'{"x": "y"}')
|
'{"x": "y"}')
|
||||||
|
@ -0,0 +1,6 @@
|
|||||||
|
---
|
||||||
|
fixes:
|
||||||
|
- |
|
||||||
|
Fixed the API handling of None (JSON null) on object update calls. The
|
||||||
|
API will now either clear the value from the field or will reset the value
|
||||||
|
of the field to the API default.
|
Loading…
Reference in New Issue
Block a user