Handle FK error when creating/updating software deployments
Software deployments have FK constraints on software configs. This change ensures the DBReferenceError caused by the constraints is properly caught. With this change now heat returns 400 Bad Response, instead of 500 Internal Server Error when a user tries to create a software deployment with a non-existing software config. Also, the stack_user_project_id field is defined as 64-chars-long string in DB model, so we should ensure that the input value is shorter than 65 chars. Otherwise it also results in DB error. Story: 2010001 Task: 45098 Change-Id: I03274dc0cffa226140eb720458cce81e8b5ce187
This commit is contained in:
parent
17ed569181
commit
7860e7acbc
|
@ -1244,8 +1244,13 @@ def software_deployment_create(context, values):
|
|||
obj_ref = models.SoftwareDeployment()
|
||||
obj_ref.update(values)
|
||||
|
||||
with context.session.begin():
|
||||
obj_ref.save(context.session)
|
||||
try:
|
||||
with context.session.begin():
|
||||
obj_ref.save(context.session)
|
||||
except db_exception.DBReferenceError:
|
||||
# NOTE(tkajinam): config_id is the only FK in SoftwareDeployment
|
||||
err_msg = _('Config with id %s not found') % values['config_id']
|
||||
raise exception.Invalid(reason=err_msg)
|
||||
|
||||
return obj_ref
|
||||
|
||||
|
@ -1278,7 +1283,12 @@ def software_deployment_get_all(context, server_id=None):
|
|||
|
||||
def software_deployment_update(context, deployment_id, values):
|
||||
deployment = software_deployment_get(context, deployment_id)
|
||||
update_and_save(context, deployment, values)
|
||||
try:
|
||||
update_and_save(context, deployment, values)
|
||||
except db_exception.DBReferenceError:
|
||||
# NOTE(tkajinam): config_id is the only FK in SoftwareDeployment
|
||||
err_msg = _('Config with id %s not found') % values['config_id']
|
||||
raise exception.Invalid(reason=err_msg)
|
||||
return deployment
|
||||
|
||||
|
||||
|
|
|
@ -268,7 +268,11 @@ class SoftwareConfigService(object):
|
|||
input_values, action, status,
|
||||
status_reason, stack_user_project_id,
|
||||
deployment_id=None):
|
||||
|
||||
if stack_user_project_id is not None:
|
||||
if len(stack_user_project_id) > 64:
|
||||
raise exception.Invalid(
|
||||
reason='"stack_user_project_id" '
|
||||
'should be no more than 64 characters')
|
||||
if deployment_id is None:
|
||||
deployment_id = str(uuid.uuid4())
|
||||
sd = software_deployment_object.SoftwareDeployment.create(cnxt, {
|
||||
|
|
|
@ -504,6 +504,31 @@ class SoftwareConfigServiceTest(common.HeatTestCase):
|
|||
self.assertEqual(deployment_id, deployment['id'])
|
||||
self.assertEqual(kwargs['input_values'], deployment['input_values'])
|
||||
|
||||
def test_create_software_deployment_invalid_stack_user_project_id(self):
|
||||
sc_kwargs = {
|
||||
'group': 'Heat::Chef',
|
||||
'name': 'config_heat',
|
||||
'config': '...',
|
||||
'inputs': [{'name': 'mode'}],
|
||||
'outputs': [{'name': 'endpoint'}],
|
||||
'options': {}
|
||||
}
|
||||
config = self._create_software_config(**sc_kwargs)
|
||||
config_id = config['id']
|
||||
sd_kwargs = {
|
||||
'config_id': config_id,
|
||||
'input_values': {'mode': 'standalone'},
|
||||
'action': 'INIT',
|
||||
'status': 'COMPLETE',
|
||||
'status_reason': '',
|
||||
# stack_user_project should be no more than 64 characters
|
||||
'stack_user_project_id': 'a' * 65
|
||||
}
|
||||
ex = self.assertRaises(dispatcher.ExpectedException,
|
||||
self._create_software_deployment,
|
||||
**sd_kwargs)
|
||||
self.assertEqual(exception.Invalid, ex.exc_info[0])
|
||||
|
||||
@mock.patch.object(service_software_config.SoftwareConfigService,
|
||||
'_refresh_swift_software_deployment')
|
||||
def test_show_software_deployment_refresh(
|
||||
|
@ -1084,3 +1109,24 @@ class SoftwareConfigIOSchemaTest(common.HeatTestCase):
|
|||
|
||||
self.assertEqual({'type': 'Number', 'name': 'baz', 'default': ''},
|
||||
inp.as_dict())
|
||||
|
||||
|
||||
class SoftwareConfigServiceTestWithConstraint(SoftwareConfigServiceTest):
|
||||
"""Test cases which require FK constraints"""
|
||||
|
||||
def setUp(self):
|
||||
self.useFixture(utils.ForeignKeyConstraintFixture())
|
||||
super(SoftwareConfigServiceTestWithConstraint, self).setUp()
|
||||
|
||||
def test_create_software_deployment_invalid_config_id(self):
|
||||
kwargs = {
|
||||
'config_id': 'this_is_invalid',
|
||||
'input_values': {'mode': 'standalone'},
|
||||
'action': 'INIT',
|
||||
'status': 'COMPLETE',
|
||||
'status_reason': ''
|
||||
}
|
||||
ex = self.assertRaises(dispatcher.ExpectedException,
|
||||
self._create_software_deployment,
|
||||
**kwargs)
|
||||
self.assertEqual(exception.Invalid, ex.exc_info[0])
|
||||
|
|
Loading…
Reference in New Issue