Allow NotFound to be created without args

It appears that the serialization used to wrap RPC exceptions
requires that the class be instantiated without any arguments.

Since the NotFound exception required a msg_fmt it could not be
deserialized in heat-api, which lead to no mapping in the FaultWrapper
so a 500 was raised instead of a 404.

This change adds a default value for msg_fmt for the NotFound exception.

The classes Error and ResourceFailure likely have this issue too, but it
is not as serious since they will raise a 500 error anyway.

Config/deployment API tests now check that NotFound can be deserialized by
calling to_remote_error, and checks that FaultWrapper converts that to
HTTPNotFound.

Change-Id: Ieb8de26465cb26aa015f15c134f80a06ebcae95c
Closes-Bug: #1301657
Related-Bug: #1304743
This commit is contained in:
Steve Baker 2014-04-09 14:38:48 +12:00
parent 638158a9a4
commit 712faf1717
2 changed files with 103 additions and 10 deletions

View File

@ -318,7 +318,7 @@ class Error(HeatException):
class NotFound(HeatException):
def __init__(self, msg_fmt):
def __init__(self, msg_fmt=_('Not found')):
self.msg_fmt = msg_fmt
super(NotFound, self).__init__()

View File

@ -3303,6 +3303,24 @@ class SoftwareConfigControllerTest(ControllerTest, HeatTestCase):
req, config_id=config_id, tenant_id=self.tenant)
self.assertEqual(expected, resp)
@mock.patch.object(policy.Enforcer, 'enforce')
def test_show_not_found(self, mock_enforce):
self._mock_enforce_setup(mock_enforce, 'show')
config_id = 'a45559cd-8736-4375-bc39-d6a7bb62ade2'
req = self._get('/software_configs/%s' % config_id)
error = heat_exc.NotFound('Not found %s' % config_id)
with mock.patch.object(
self.controller.rpc_client,
'show_software_config',
side_effect=to_remote_error(error)):
resp = request_with_middleware(fault.FaultWrapper,
self.controller.show,
req, config_id=config_id,
tenant_id=self.tenant)
self.assertEqual(404, resp.json['code'])
self.assertEqual('NotFound', resp.json['error']['type'])
@mock.patch.object(policy.Enforcer, 'enforce')
def test_create(self, mock_enforce):
self._mock_enforce_setup(mock_enforce, 'create')
@ -3346,15 +3364,35 @@ class SoftwareConfigControllerTest(ControllerTest, HeatTestCase):
self._mock_enforce_setup(mock_enforce, 'delete')
config_id = 'a45559cd-8736-4375-bc39-d6a7bb62ade2'
req = self._delete('/software_configs/%s' % config_id)
return_value = {'Error': 'something wrong'}
error = Exception('something wrong')
with mock.patch.object(
self.controller.rpc_client,
'delete_software_config',
return_value=return_value):
self.assertRaises(
webob.exc.HTTPBadRequest, self.controller.delete,
side_effect=to_remote_error(error)):
resp = request_with_middleware(
fault.FaultWrapper, self.controller.delete,
req, config_id=config_id, tenant_id=self.tenant)
self.assertEqual(500, resp.json['code'])
self.assertEqual('Exception', resp.json['error']['type'])
@mock.patch.object(policy.Enforcer, 'enforce')
def test_delete_not_found(self, mock_enforce):
self._mock_enforce_setup(mock_enforce, 'delete')
config_id = 'a45559cd-8736-4375-bc39-d6a7bb62ade2'
req = self._delete('/software_configs/%s' % config_id)
error = heat_exc.NotFound('Not found %s' % config_id)
with mock.patch.object(
self.controller.rpc_client,
'delete_software_config',
side_effect=to_remote_error(error)):
resp = request_with_middleware(
fault.FaultWrapper, self.controller.delete,
req, config_id=config_id, tenant_id=self.tenant)
self.assertEqual(404, resp.json['code'])
self.assertEqual('NotFound', resp.json['error']['type'])
class SoftwareDeploymentControllerTest(ControllerTest, HeatTestCase):
@ -3425,6 +3463,24 @@ class SoftwareDeploymentControllerTest(ControllerTest, HeatTestCase):
req, deployment_id=config_id, tenant_id=self.tenant)
self.assertEqual(expected, resp)
@mock.patch.object(policy.Enforcer, 'enforce')
def test_show_not_found(self, mock_enforce):
self._mock_enforce_setup(mock_enforce, 'show')
deployment_id = '38eccf10-97e5-4ae8-9d37-b577c9801750'
req = self._get('/software_deployments/%s' % deployment_id)
error = heat_exc.NotFound('Not found %s' % deployment_id)
with mock.patch.object(
self.controller.rpc_client,
'show_software_deployment',
side_effect=to_remote_error(error)):
resp = request_with_middleware(
fault.FaultWrapper, self.controller.show,
req, deployment_id=deployment_id, tenant_id=self.tenant)
self.assertEqual(404, resp.json['code'])
self.assertEqual('NotFound', resp.json['error']['type'])
@mock.patch.object(policy.Enforcer, 'enforce')
def test_create(self, mock_enforce):
self._mock_enforce_setup(mock_enforce, 'create')
@ -3465,7 +3521,8 @@ class SoftwareDeploymentControllerTest(ControllerTest, HeatTestCase):
return_value = body.copy()
deployment_id = 'a45559cd-8736-4375-bc39-d6a7bb62ade2'
return_value['id'] = deployment_id
req = self._put('/software_deployments/%s', json.dumps(body))
req = self._put('/software_deployments/%s' % deployment_id,
json.dumps(body))
return_value['server_id'] = server_id
expected = {'software_deployment': return_value}
with mock.patch.object(
@ -3477,6 +3534,24 @@ class SoftwareDeploymentControllerTest(ControllerTest, HeatTestCase):
body=body, tenant_id=self.tenant)
self.assertEqual(expected, resp)
@mock.patch.object(policy.Enforcer, 'enforce')
def test_update_not_found(self, mock_enforce):
self._mock_enforce_setup(mock_enforce, 'update')
deployment_id = 'a45559cd-8736-4375-bc39-d6a7bb62ade2'
req = self._put('/software_deployments/%s' % deployment_id,
'{}')
error = heat_exc.NotFound('Not found %s' % deployment_id)
with mock.patch.object(
self.controller.rpc_client,
'update_software_deployment',
side_effect=to_remote_error(error)):
resp = request_with_middleware(
fault.FaultWrapper, self.controller.update,
req, deployment_id=deployment_id,
body={}, tenant_id=self.tenant)
self.assertEqual(404, resp.json['code'])
self.assertEqual('NotFound', resp.json['error']['type'])
@mock.patch.object(policy.Enforcer, 'enforce')
def test_delete(self, mock_enforce):
self._mock_enforce_setup(mock_enforce, 'delete')
@ -3496,11 +3571,29 @@ class SoftwareDeploymentControllerTest(ControllerTest, HeatTestCase):
self._mock_enforce_setup(mock_enforce, 'delete')
deployment_id = 'a45559cd-8736-4375-bc39-d6a7bb62ade2'
req = self._delete('/software_deployments/%s' % deployment_id)
return_value = {'Error': 'something wrong'}
error = Exception('something wrong')
with mock.patch.object(
self.controller.rpc_client,
'delete_software_deployment',
return_value=return_value):
self.assertRaises(
webob.exc.HTTPBadRequest, self.controller.delete,
side_effect=to_remote_error(error)):
resp = request_with_middleware(
fault.FaultWrapper, self.controller.delete,
req, deployment_id=deployment_id, tenant_id=self.tenant)
self.assertEqual(500, resp.json['code'])
self.assertEqual('Exception', resp.json['error']['type'])
@mock.patch.object(policy.Enforcer, 'enforce')
def test_delete_not_found(self, mock_enforce):
self._mock_enforce_setup(mock_enforce, 'delete')
deployment_id = 'a45559cd-8736-4375-bc39-d6a7bb62ade2'
req = self._delete('/software_deployments/%s' % deployment_id)
error = heat_exc.NotFound('Not Found %s' % deployment_id)
with mock.patch.object(
self.controller.rpc_client,
'delete_software_deployment',
side_effect=to_remote_error(error)):
resp = request_with_middleware(
fault.FaultWrapper, self.controller.delete,
req, deployment_id=deployment_id, tenant_id=self.tenant)
self.assertEqual(404, resp.json['code'])
self.assertEqual('NotFound', resp.json['error']['type'])