Produce more meaningful exception messages in nested stacks

This produces a nested exception like:
 'ValueError: resources.nested.resources.my_server: it is broken, sorry'

This re-uses the path mechanism that StackValidationFailed exception
uses.

Change-Id: Id5204c15ee96784e04522ab3c5a8e66900f9a1d3
Closes-bug: 1459837
changes/28/188228/13
Angus Salkeld 7 years ago
parent beafdb8cab
commit caa1bd8602
  1. 12
      contrib/rackspace/rackspace/tests/test_rackspace_cloud_server.py
  2. 75
      heat/common/exception.py
  3. 6
      heat/engine/resources/stack_resource.py
  4. 4
      heat/tests/autoscaling/test_launch_config.py
  5. 2
      heat/tests/autoscaling/test_scaling_group.py
  6. 15
      heat/tests/aws/test_instance.py
  7. 5
      heat/tests/aws/test_s3.py
  8. 10
      heat/tests/aws/test_volume.py
  9. 4
      heat/tests/aws/test_waitcondition.py
  10. 18
      heat/tests/neutron/test_neutron_firewall.py
  11. 21
      heat/tests/neutron/test_neutron_loadbalancer.py
  12. 12
      heat/tests/neutron/test_neutron_metering.py
  13. 3
      heat/tests/neutron/test_neutron_network_gateway.py
  14. 24
      heat/tests/neutron/test_neutron_vpnservice.py
  15. 8
      heat/tests/openstack/test_volume.py
  16. 8
      heat/tests/test_ceilometer_alarm.py
  17. 4
      heat/tests/test_engine_service.py
  18. 74
      heat/tests/test_exception.py
  19. 8
      heat/tests/test_glance_image.py
  20. 3
      heat/tests/test_manila_security_service.py
  21. 4
      heat/tests/test_manila_share.py
  22. 20
      heat/tests/test_mistral_workflow.py
  23. 20
      heat/tests/test_properties.py
  24. 24
      heat/tests/test_remote_stack.py
  25. 17
      heat/tests/test_resource.py
  26. 10
      heat/tests/test_sahara_cluster.py
  27. 6
      heat/tests/test_sahara_templates.py
  28. 30
      heat/tests/test_server.py
  29. 14
      heat/tests/test_stack.py
  30. 3
      heat/tests/test_stack_delete.py
  31. 14
      heat/tests/test_stack_resource.py
  32. 2
      heat/tests/test_swift.py
  33. 25
      heat/tests/test_swiftsignal.py
  34. 2
      heat/tests/test_trove_cluster.py
  35. 14
      heat/tests/test_validate.py
  36. 6
      heat/tests/test_zaqar_queue.py
  37. 2
      heat_integrationtests/common/test_resources/test_resource.py
  38. 36
      heat_integrationtests/functional/test_template_resource.py

@ -179,7 +179,8 @@ class CloudServersTest(common.HeatTestCase):
self.m.ReplayAll()
create = scheduler.TaskRunner(server.create)
exc = self.assertRaises(exception.ResourceFailure, create)
self.assertEqual('Error: RackConnect automation FAILED',
self.assertEqual('Error: resources.test_rackconnect_failed: '
'RackConnect automation FAILED',
six.text_type(exc))
def test_rackconnect_unprocessable(self):
@ -210,7 +211,8 @@ class CloudServersTest(common.HeatTestCase):
self.m.ReplayAll()
create = scheduler.TaskRunner(server.create)
exc = self.assertRaises(exception.ResourceFailure, create)
self.assertEqual('Error: Unknown RackConnect automation status: FOO',
self.assertEqual('Error: resources.test_rackconnect_unknown: '
'Unknown RackConnect automation status: FOO',
six.text_type(exc))
def test_rackconnect_deploying(self):
@ -309,7 +311,8 @@ class CloudServersTest(common.HeatTestCase):
self.m.ReplayAll()
create = scheduler.TaskRunner(server.create)
exc = self.assertRaises(exception.ResourceFailure, create)
self.assertEqual('Error: Managed Cloud automation failed',
self.assertEqual('Error: resources.test_managed_cloud_build_error: '
'Managed Cloud automation failed',
six.text_type(exc))
def test_managed_cloud_unknown(self):
@ -323,7 +326,8 @@ class CloudServersTest(common.HeatTestCase):
self.m.ReplayAll()
create = scheduler.TaskRunner(server.create)
exc = self.assertRaises(exception.ResourceFailure, create)
self.assertEqual('Error: Unknown Managed Cloud automation status: FOO',
self.assertEqual('Error: resources.test_managed_cloud_unknown: '
'Unknown Managed Cloud automation status: FOO',
six.text_type(exc))
def _test_server_config_drive(self, user_data, config_drive, result):

@ -253,7 +253,7 @@ class StackExists(HeatException):
msg_fmt = _("The Stack (%(stack_name)s) already exists.")
class StackValidationFailed(HeatException):
class HeatExceptionWithPath(HeatException):
msg_fmt = _("%(error)s%(path)s%(message)s")
def __init__(self, error=None, path=None, message=None):
@ -275,8 +275,8 @@ class StackValidationFailed(HeatException):
result_path = path_item
self.error_message = message or ''
super(StackValidationFailed, self).__init__(
error=('%s : ' % self.error if self.error != '' else ''),
super(HeatExceptionWithPath, self).__init__(
error=('%s: ' % self.error if self.error != '' else ''),
path=('%s: ' % result_path if len(result_path) > 0 else ''),
message=self.error_message
)
@ -291,6 +291,10 @@ class StackValidationFailed(HeatException):
return self.error_message
class StackValidationFailed(HeatExceptionWithPath):
pass
class InvalidSchemaError(HeatException):
msg_fmt = _("%(message)s")
@ -333,18 +337,63 @@ class WatchRuleNotFound(HeatException):
msg_fmt = _("The Watch Rule (%(watch_name)s) could not be found.")
class ResourceFailure(HeatException):
msg_fmt = _("%(exc_type)s: %(message)s")
def __init__(self, exception, resource, action=None):
if isinstance(exception, ResourceFailure):
exception = getattr(exception, 'exc', exception)
self.exc = exception
class ResourceFailure(HeatExceptionWithPath):
def __init__(self, exception_or_error, resource, action=None):
self.resource = resource
self.action = action
exc_type = type(exception).__name__
super(ResourceFailure, self).__init__(exc_type=exc_type,
message=six.text_type(exception))
if action is None and resource is not None:
self.action = resource.action
path = []
res_path = []
if resource is not None:
res_path = [resource.stack.t.get_section_name('resources'),
resource.name]
if isinstance(exception_or_error, Exception):
if isinstance(exception_or_error, ResourceFailure):
self.exc = exception_or_error.exc
error = exception_or_error.error
message = exception_or_error.error_message
path = exception_or_error.path
else:
self.exc = exception_or_error
error = six.text_type(type(self.exc).__name__)
message = six.text_type(self.exc)
path = res_path
else:
self.exc = None
res_failed = 'Resource %s failed: ' % action.upper()
if res_failed in exception_or_error:
(error, message, new_path) = self._from_status_reason(
exception_or_error)
path = res_path + new_path
else:
path = res_path
error = None
message = exception_or_error
super(ResourceFailure, self).__init__(error=error, path=path,
message=message)
def _from_status_reason(self, status_reason):
"""Split the status_reason up into parts.
Given the following status_reason:
"Resource DELETE failed: Exception : resources.AResource: foo"
we are going to return:
("Exception", "resources.AResource", "foo")
"""
parsed = [sp.strip() for sp in status_reason.split(':')]
if len(parsed) >= 4:
error = parsed[1]
message = ': '.join(parsed[3:])
path = parsed[2].split('.')
else:
error = ''
message = status_reason
path = []
return (error, message, path)
class NotSupported(HeatException):

@ -370,12 +370,12 @@ class StackResource(resource.Resource):
elif nested.status == resource.Resource.COMPLETE:
return True
elif nested.status == resource.Resource.FAILED:
raise resource.ResourceUnknownStatus(
resource_status=nested.status,
status_reason=nested.status_reason)
raise exception.ResourceFailure(nested.status_reason, self,
action=action)
else:
raise resource.ResourceUnknownStatus(
resource_status=nested.status,
status_reason=nested.status_reason,
result=_('Stack unknown status'))
def check_adopt_complete(self, cookie=None):

@ -131,7 +131,7 @@ class LaunchConfigurationTest(common.HeatTestCase):
self.patchobject(nova.NovaClientPlugin, 'get_server',
side_effect=exception.EntityNotFound(
entity='Server', name='5678'))
msg = ("Property error : "
msg = ("Property error: "
"Resources.LaunchConfig.Properties.InstanceId: "
"Error validating value '5678': The Server (5678) "
"could not be found.")
@ -194,7 +194,7 @@ class LaunchConfigurationTest(common.HeatTestCase):
stack, 'LaunchConfig')
excepted_error = (
'Property error : '
'Property error: '
'Resources.LaunchConfig.Properties.BlockDeviceMappings[0]: '
'Property DeviceName not assigned')
self.assertIn(excepted_error, six.text_type(e))

@ -217,7 +217,7 @@ class TestAutoScalingGroupValidation(common.HeatTestCase):
rsrc = stack['WebServerGroup']
self._stub_nova_server_get(not_found=True)
self.m.ReplayAll()
msg = ("Property error : "
msg = ("Property error: "
"Resources.WebServerGroup.Properties.InstanceId: "
"Error validating value '5678': The Server (5678) could "
"not be found.")

@ -325,7 +325,7 @@ class InstancesTest(common.HeatTestCase):
exc = self.assertRaises(exception.StackValidationFailed,
instance.validate)
excepted_error = (
'Property error : '
'Property error: '
'Resources.WebServer.Properties.BlockDeviceMappings[0]: '
'Property DeviceName not assigned')
self.assertIn(excepted_error, six.text_type(exc))
@ -385,7 +385,8 @@ class InstancesTest(common.HeatTestCase):
create = scheduler.TaskRunner(instance.create)
error = self.assertRaises(exception.ResourceFailure, create)
self.assertEqual(
"StackValidationFailed: Property error : "
"StackValidationFailed: resources.instance_create_image_err: "
"Property error: "
"WebServer.Properties.ImageId: Error validating value "
"'Slackware': The Image (Slackware) could not be found.",
six.text_type(error))
@ -412,7 +413,8 @@ class InstancesTest(common.HeatTestCase):
create = scheduler.TaskRunner(instance.create)
error = self.assertRaises(exception.ResourceFailure, create)
self.assertEqual(
'StackValidationFailed: Property error : '
'StackValidationFailed: resources.instance_create_image_err: '
'Property error: '
'WebServer.Properties.ImageId: Multiple physical '
'resources were found with name (CentOS 5.2).',
six.text_type(error))
@ -436,8 +438,8 @@ class InstancesTest(common.HeatTestCase):
create = scheduler.TaskRunner(instance.create)
error = self.assertRaises(exception.ResourceFailure, create)
self.assertEqual(
'StackValidationFailed: Property error : '
'WebServer.Properties.ImageId: 404 (HTTP 404)',
'StackValidationFailed: resources.instance_create_image_err: '
'Property error: WebServer.Properties.ImageId: 404 (HTTP 404)',
six.text_type(error))
self.m.VerifyAll()
@ -711,7 +713,8 @@ class InstancesTest(common.HeatTestCase):
updater = scheduler.TaskRunner(instance.update, update_template)
error = self.assertRaises(exception.ResourceFailure, updater)
self.assertEqual(
"Error: Resizing to 'm1.small' failed, status 'ACTIVE'",
"Error: resources.ud_type_f: "
"Resizing to 'm1.small' failed, status 'ACTIVE'",
six.text_type(error))
self.assertEqual((instance.UPDATE, instance.FAILED), instance.state)
self.m.VerifyAll()

@ -249,8 +249,9 @@ class s3Test(common.HeatTestCase):
rsrc = self.create_resource(t, stack, 'S3Bucket')
deleter = scheduler.TaskRunner(rsrc.delete)
ex = self.assertRaises(exception.ResourceFailure, deleter)
self.assertIn("ResourceActionNotSupported: The bucket "
"you tried to delete is not empty", six.text_type(ex))
self.assertIn("ResourceActionNotSupported: resources.test_resource: "
"The bucket you tried to delete is not empty",
six.text_type(ex))
self.m.VerifyAll()

@ -203,7 +203,7 @@ class VolumeTest(vt_base.BaseVolumeTest):
ex = self.assertRaises(exception.StackValidationFailed,
self.create_volume, self.t, stack, 'DataVolume')
self.assertEqual("Property error : "
self.assertEqual("Property error: "
"Resources.DataVolume.Properties.Tags[0]: "
"Unknown Property Foo", six.text_type(ex))
@ -478,7 +478,8 @@ class VolumeTest(vt_base.BaseVolumeTest):
updater = scheduler.TaskRunner(rsrc.update, after)
ex = self.assertRaises(exception.ResourceFailure, updater)
self.assertIn("NotSupported: Update to properties "
self.assertIn("NotSupported: resources.DataVolume: "
"Update to properties "
"AvailabilityZone, Size, Tags of DataVolume "
"(AWS::EC2::Volume) is not supported",
six.text_type(ex))
@ -668,7 +669,7 @@ class VolumeTest(vt_base.BaseVolumeTest):
self.create_volume,
self.t, stack, 'DataVolume')
self.assertEqual(
"Property error : Resources.DataVolume.Properties.Size: "
"Property error: Resources.DataVolume.Properties.Size: "
"0 is out of range (min: 1, max: None)", six.text_type(error))
def test_volume_attachment_updates_not_supported(self):
@ -698,7 +699,8 @@ class VolumeTest(vt_base.BaseVolumeTest):
update_task = scheduler.TaskRunner(rsrc.update, after)
ex = self.assertRaises(exception.ResourceFailure, update_task)
self.assertIn('NotSupported: Update to properties Device, InstanceId, '
self.assertIn('NotSupported: resources.MountPoint: '
'Update to properties Device, InstanceId, '
'VolumeId of MountPoint (AWS::EC2::VolumeAttachment)',
six.text_type(ex))
self.assertEqual((rsrc.UPDATE, rsrc.FAILED), rsrc.state)

@ -651,7 +651,7 @@ class WaitConditionUpdateTest(common.HeatTestCase):
updater = scheduler.TaskRunner(rsrc.update, update_snippet)
ex = self.assertRaises(exception.ResourceFailure,
updater)
self.assertEqual("WaitConditionTimeout: 0 of 5 received",
six.text_type(ex))
self.assertEqual("WaitConditionTimeout: resources.WaitForTheHandle: "
"0 of 5 received", six.text_type(ex))
self.assertEqual(5, rsrc.properties['Count'])
self.m.VerifyAll()

@ -115,7 +115,8 @@ class FirewallTest(common.HeatTestCase):
error = self.assertRaises(exception.ResourceFailure,
scheduler.TaskRunner(rsrc.create))
self.assertEqual(
'NeutronClientException: An unknown exception occurred.',
'NeutronClientException: resources.firewall: '
'An unknown exception occurred.',
six.text_type(error))
self.assertEqual((rsrc.CREATE, rsrc.FAILED), rsrc.state)
self.m.VerifyAll()
@ -153,7 +154,8 @@ class FirewallTest(common.HeatTestCase):
error = self.assertRaises(exception.ResourceFailure,
scheduler.TaskRunner(rsrc.delete))
self.assertEqual(
'NeutronClientException: An unknown exception occurred.',
'NeutronClientException: resources.firewall: '
'An unknown exception occurred.',
six.text_type(error))
self.assertEqual((rsrc.DELETE, rsrc.FAILED), rsrc.state)
self.m.VerifyAll()
@ -243,7 +245,8 @@ class FirewallPolicyTest(common.HeatTestCase):
error = self.assertRaises(exception.ResourceFailure,
scheduler.TaskRunner(rsrc.create))
self.assertEqual(
'NeutronClientException: An unknown exception occurred.',
'NeutronClientException: resources.firewall_policy: '
'An unknown exception occurred.',
six.text_type(error))
self.assertEqual((rsrc.CREATE, rsrc.FAILED), rsrc.state)
self.m.VerifyAll()
@ -281,7 +284,8 @@ class FirewallPolicyTest(common.HeatTestCase):
error = self.assertRaises(exception.ResourceFailure,
scheduler.TaskRunner(rsrc.delete))
self.assertEqual(
'NeutronClientException: An unknown exception occurred.',
'NeutronClientException: resources.firewall_policy: '
'An unknown exception occurred.',
six.text_type(error))
self.assertEqual((rsrc.DELETE, rsrc.FAILED), rsrc.state)
self.m.VerifyAll()
@ -395,7 +399,8 @@ class FirewallRuleTest(common.HeatTestCase):
error = self.assertRaises(exception.ResourceFailure,
scheduler.TaskRunner(rsrc.create))
self.assertEqual(
'NeutronClientException: An unknown exception occurred.',
'NeutronClientException: resources.firewall_rule: '
'An unknown exception occurred.',
six.text_type(error))
self.assertEqual((rsrc.CREATE, rsrc.FAILED), rsrc.state)
self.m.VerifyAll()
@ -433,7 +438,8 @@ class FirewallRuleTest(common.HeatTestCase):
error = self.assertRaises(exception.ResourceFailure,
scheduler.TaskRunner(rsrc.delete))
self.assertEqual(
'NeutronClientException: An unknown exception occurred.',
'NeutronClientException: resources.firewall_rule: '
'An unknown exception occurred.',
six.text_type(error))
self.assertEqual((rsrc.DELETE, rsrc.FAILED), rsrc.state)
self.m.VerifyAll()

@ -214,7 +214,8 @@ class HealthMonitorTest(common.HeatTestCase):
error = self.assertRaises(exception.ResourceFailure,
scheduler.TaskRunner(rsrc.create))
self.assertEqual(
'NeutronClientException: An unknown exception occurred.',
'NeutronClientException: resources.monitor: '
'An unknown exception occurred.',
six.text_type(error))
self.assertEqual((rsrc.CREATE, rsrc.FAILED), rsrc.state)
self.m.VerifyAll()
@ -252,7 +253,8 @@ class HealthMonitorTest(common.HeatTestCase):
error = self.assertRaises(exception.ResourceFailure,
scheduler.TaskRunner(rsrc.delete))
self.assertEqual(
'NeutronClientException: An unknown exception occurred.',
'NeutronClientException: resources.monitor: '
'An unknown exception occurred.',
six.text_type(error))
self.assertEqual((rsrc.DELETE, rsrc.FAILED), rsrc.state)
self.m.VerifyAll()
@ -456,7 +458,8 @@ class PoolTest(common.HeatTestCase):
error = self.assertRaises(exception.ResourceFailure,
scheduler.TaskRunner(rsrc.create))
self.assertEqual(
'ResourceInError: Went to status ERROR due to "error in pool"',
'ResourceInError: resources.pool: '
'Went to status ERROR due to "error in pool"',
six.text_type(error))
self.assertEqual((rsrc.CREATE, rsrc.FAILED), rsrc.state)
self.m.VerifyAll()
@ -493,7 +496,8 @@ class PoolTest(common.HeatTestCase):
self.m.ReplayAll()
error = self.assertRaises(exception.ResourceFailure,
scheduler.TaskRunner(rsrc.create))
self.assertEqual('ResourceUnknownStatus: Pool creation failed due to '
self.assertEqual('ResourceUnknownStatus: resources.pool: '
'Pool creation failed due to '
'vip - Unknown status SOMETHING due to "Unknown"',
six.text_type(error))
self.assertEqual((rsrc.CREATE, rsrc.FAILED), rsrc.state)
@ -522,7 +526,8 @@ class PoolTest(common.HeatTestCase):
error = self.assertRaises(exception.ResourceFailure,
scheduler.TaskRunner(rsrc.create))
self.assertEqual(
'NeutronClientException: An unknown exception occurred.',
'NeutronClientException: resources.pool: '
'An unknown exception occurred.',
six.text_type(error))
self.assertEqual((rsrc.CREATE, rsrc.FAILED), rsrc.state)
self.m.VerifyAll()
@ -714,7 +719,8 @@ class PoolTest(common.HeatTestCase):
error = self.assertRaises(exception.ResourceFailure,
scheduler.TaskRunner(rsrc.delete))
self.assertEqual(
'NeutronClientException: An unknown exception occurred.',
'NeutronClientException: resources.pool: '
'An unknown exception occurred.',
six.text_type(error))
self.assertEqual((rsrc.DELETE, rsrc.FAILED), rsrc.state)
self.m.VerifyAll()
@ -731,7 +737,8 @@ class PoolTest(common.HeatTestCase):
error = self.assertRaises(exception.ResourceFailure,
scheduler.TaskRunner(rsrc.delete))
self.assertEqual(
'NeutronClientException: An unknown exception occurred.',
'NeutronClientException: resources.pool: '
'An unknown exception occurred.',
six.text_type(error))
self.assertEqual((rsrc.DELETE, rsrc.FAILED), rsrc.state)
self.m.VerifyAll()

@ -96,7 +96,8 @@ class MeteringLabelTest(common.HeatTestCase):
error = self.assertRaises(exception.ResourceFailure,
scheduler.TaskRunner(rsrc.create))
self.assertEqual(
'NeutronClientException: An unknown exception occurred.',
'NeutronClientException: resources.label: '
'An unknown exception occurred.',
six.text_type(error))
self.assertEqual((rsrc.CREATE, rsrc.FAILED), rsrc.state)
self.m.VerifyAll()
@ -134,7 +135,8 @@ class MeteringLabelTest(common.HeatTestCase):
error = self.assertRaises(exception.ResourceFailure,
scheduler.TaskRunner(rsrc.delete))
self.assertEqual(
'NeutronClientException: An unknown exception occurred.',
'NeutronClientException: resources.label: '
'An unknown exception occurred.',
six.text_type(error))
self.assertEqual((rsrc.DELETE, rsrc.FAILED), rsrc.state)
self.m.VerifyAll()
@ -210,7 +212,8 @@ class MeteringRuleTest(common.HeatTestCase):
error = self.assertRaises(exception.ResourceFailure,
scheduler.TaskRunner(rsrc.create))
self.assertEqual(
'NeutronClientException: An unknown exception occurred.',
'NeutronClientException: resources.rule: '
'An unknown exception occurred.',
six.text_type(error))
self.assertEqual((rsrc.CREATE, rsrc.FAILED), rsrc.state)
self.m.VerifyAll()
@ -248,7 +251,8 @@ class MeteringRuleTest(common.HeatTestCase):
error = self.assertRaises(exception.ResourceFailure,
scheduler.TaskRunner(rsrc.delete))
self.assertEqual(
'NeutronClientException: An unknown exception occurred.',
'NeutronClientException: resources.rule: '
'An unknown exception occurred.',
six.text_type(error))
self.assertEqual((rsrc.DELETE, rsrc.FAILED), rsrc.state)
self.m.VerifyAll()

@ -506,7 +506,8 @@ class NeutronNetworkGatewayTest(common.HeatTestCase):
error = self.assertRaises(exception.ResourceFailure,
scheduler.TaskRunner(rsrc.create))
self.assertEqual(
'NeutronClientException: An unknown exception occurred.',
'NeutronClientException: resources.network_gateway: '
'An unknown exception occurred.',
six.text_type(error))
self.assertEqual((rsrc.CREATE, rsrc.FAILED), rsrc.state)
self.assertIsNone(scheduler.TaskRunner(rsrc.delete)())

@ -194,7 +194,8 @@ class VPNServiceTest(common.HeatTestCase):
error = self.assertRaises(exception.ResourceFailure,
scheduler.TaskRunner(rsrc.create))
self.assertEqual(
'NeutronClientException: An unknown exception occurred.',
'NeutronClientException: resources.vpnservice: '
'An unknown exception occurred.',
six.text_type(error))
self.assertEqual((rsrc.CREATE, rsrc.FAILED), rsrc.state)
self.m.VerifyAll()
@ -229,7 +230,8 @@ class VPNServiceTest(common.HeatTestCase):
error = self.assertRaises(exception.ResourceFailure,
scheduler.TaskRunner(rsrc.delete))
self.assertEqual(
'NeutronClientException: An unknown exception occurred.',
'NeutronClientException: resources.vpnservice: '
'An unknown exception occurred.',
six.text_type(error))
self.assertEqual((rsrc.DELETE, rsrc.FAILED), rsrc.state)
self.m.VerifyAll()
@ -340,7 +342,8 @@ class IPsecSiteConnectionTest(common.HeatTestCase):
error = self.assertRaises(exception.ResourceFailure,
scheduler.TaskRunner(rsrc.create))
self.assertEqual(
'NeutronClientException: An unknown exception occurred.',
'NeutronClientException: resources.ipsec_site_connection: '
'An unknown exception occurred.',
six.text_type(error))
self.assertEqual((rsrc.CREATE, rsrc.FAILED), rsrc.state)
self.m.VerifyAll()
@ -375,7 +378,8 @@ class IPsecSiteConnectionTest(common.HeatTestCase):
error = self.assertRaises(exception.ResourceFailure,
scheduler.TaskRunner(rsrc.delete))
self.assertEqual(
'NeutronClientException: An unknown exception occurred.',
'NeutronClientException: resources.ipsec_site_connection: '
'An unknown exception occurred.',
six.text_type(error))
self.assertEqual((rsrc.DELETE, rsrc.FAILED), rsrc.state)
self.m.VerifyAll()
@ -485,7 +489,8 @@ class IKEPolicyTest(common.HeatTestCase):
error = self.assertRaises(exception.ResourceFailure,
scheduler.TaskRunner(rsrc.create))
self.assertEqual(
'NeutronClientException: An unknown exception occurred.',
'NeutronClientException: resources.ikepolicy: '
'An unknown exception occurred.',
six.text_type(error))
self.assertEqual((rsrc.CREATE, rsrc.FAILED), rsrc.state)
self.m.VerifyAll()
@ -520,7 +525,8 @@ class IKEPolicyTest(common.HeatTestCase):
error = self.assertRaises(exception.ResourceFailure,
scheduler.TaskRunner(rsrc.delete))
self.assertEqual(
'NeutronClientException: An unknown exception occurred.',
'NeutronClientException: resources.ikepolicy: '
'An unknown exception occurred.',
six.text_type(error))
self.assertEqual((rsrc.DELETE, rsrc.FAILED), rsrc.state)
self.m.VerifyAll()
@ -625,7 +631,8 @@ class IPsecPolicyTest(common.HeatTestCase):
error = self.assertRaises(exception.ResourceFailure,
scheduler.TaskRunner(rsrc.create))
self.assertEqual(
'NeutronClientException: An unknown exception occurred.',
'NeutronClientException: resources.ipsecpolicy: '
'An unknown exception occurred.',
six.text_type(error))
self.assertEqual((rsrc.CREATE, rsrc.FAILED), rsrc.state)
self.m.VerifyAll()
@ -660,7 +667,8 @@ class IPsecPolicyTest(common.HeatTestCase):
error = self.assertRaises(exception.ResourceFailure,
scheduler.TaskRunner(rsrc.delete))
self.assertEqual(
'NeutronClientException: An unknown exception occurred.',
'NeutronClientException: resources.ipsecpolicy: '
'An unknown exception occurred.',
six.text_type(error))
self.assertEqual((rsrc.DELETE, rsrc.FAILED), rsrc.state)
self.m.VerifyAll()

@ -104,7 +104,7 @@ class CinderVolumeTest(vt_base.BaseVolumeTest):
self.create_volume,
self.t, stack, 'volume')
self.assertEqual(
"Property error : resources.volume.properties.size: "
"Property error: resources.volume.properties.size: "
"0 is out of range (min: 1, max: None)", six.text_type(error))
def test_cinder_create(self):
@ -323,7 +323,8 @@ class CinderVolumeTest(vt_base.BaseVolumeTest):
update_task = scheduler.TaskRunner(rsrc.update, after)
ex = self.assertRaises(exception.ResourceFailure, update_task)
self.assertEqual('NotSupported: Shrinking volume is not supported.',
self.assertEqual('NotSupported: resources.volume: '
'Shrinking volume is not supported.',
six.text_type(ex))
self.assertEqual((rsrc.UPDATE, rsrc.FAILED), rsrc.state)
@ -557,7 +558,8 @@ class CinderVolumeTest(vt_base.BaseVolumeTest):
# if the volume api is v1, not support to retype
update_task = scheduler.TaskRunner(rsrc.update, after)
ex = self.assertRaises(exception.ResourceFailure, update_task)
self.assertEqual('NotSupported: Using Cinder API V1, '
self.assertEqual('NotSupported: resources.volume2: '
'Using Cinder API V1, '
'volume_type update is not supported.',
six.text_type(ex))
self.assertEqual((rsrc.UPDATE, rsrc.FAILED), rsrc.state)

@ -368,7 +368,7 @@ class CeilometerAlarmTest(common.HeatTestCase):
error = self.assertRaises(exception.StackValidationFailed,
rsrc.validate)
self.assertEqual(
"Property error : Resources.MEMAlarmHigh.Properties.%s: "
"Property error: Resources.MEMAlarmHigh.Properties.%s: "
"Value '60a' is not an integer" % p, six.text_type(error))
def test_mem_alarm_high_not_integer_parameters(self):
@ -383,7 +383,7 @@ class CeilometerAlarmTest(common.HeatTestCase):
error = self.assertRaises(exception.StackValidationFailed,
rsrc.validate)
self.assertEqual(
"Property error : Resources.MEMAlarmHigh.Properties.%s: "
"Property error: Resources.MEMAlarmHigh.Properties.%s: "
"int() argument must be a string or a number, not "
"'list'" % p, six.text_type(error))
@ -398,7 +398,7 @@ class CeilometerAlarmTest(common.HeatTestCase):
error = self.assertRaises(exception.StackValidationFailed,
rsrc.validate)
self.assertEqual(
"Property error : Resources.MEMAlarmHigh.Properties: "
"Property error: Resources.MEMAlarmHigh.Properties: "
"Property meter_name not assigned",
six.text_type(error))
@ -514,7 +514,7 @@ class CombinationAlarmTest(common.HeatTestCase):
error = self.assertRaises(exception.StackValidationFailed,
rsrc.validate)
self.assertEqual(
"Property error : Resources.CombinAlarm.Properties.alarm_ids: "
"Property error: Resources.CombinAlarm.Properties.alarm_ids: "
"length (0) is out of range (min: 1, max: None)",
six.text_type(error))

@ -550,8 +550,8 @@ class StackCreateTest(common.HeatTestCase):
stack.store()
stack.adopt()
self.assertIsNotNone(stack['WebServer'])
expected = ('Resource ADOPT failed: Exception: Resource ID was not'
' provided.')
expected = ('Resource ADOPT failed: Exception: resources.WebServer: '
'Resource ID was not provided.')
self.assertEqual(expected, stack.status_reason)
self.assertEqual((stack.ADOPT, stack.FAILED), stack.state)

@ -16,6 +16,7 @@
import fixtures
import mock
import six
from heat.common import exception
@ -49,7 +50,7 @@ class TestStackValidationFailed(common.HeatTestCase):
error='Error',
path=['some', 'path'],
message='Some message'),
expected='Error : some.path: Some message',
expected='Error: some.path: Some message',
called_error='Error',
called_path=['some', 'path'],
called_msg='Some message'
@ -67,7 +68,7 @@ class TestStackValidationFailed(common.HeatTestCase):
kwargs=dict(
error='Error',
message='Just no.'),
expected='Error : Just no.',
expected='Error: Just no.',
called_error='Error',
called_path=[],
called_msg='Just no.'
@ -76,7 +77,7 @@ class TestStackValidationFailed(common.HeatTestCase):
kwargs=dict(
error='Error',
path=['we', 'lost', 'our', 'message']),
expected='Error : we.lost.our.message: ',
expected='Error: we.lost.our.message: ',
called_error='Error',
called_path=['we', 'lost', 'our', 'message'],
called_msg=''
@ -127,3 +128,70 @@ class TestStackValidationFailed(common.HeatTestCase):
self.assertEqual(self.called_error, ex.error)
self.assertEqual(self.called_path, ex.path)
self.assertEqual(self.called_msg, ex.error_message)
class TestResourceFailure(common.HeatTestCase):
def test_status_reason_resource(self):
reason = ('Resource CREATE failed: ValueError: resources.oops: '
'Test Resource failed oops')
exc = exception.ResourceFailure(reason, None, action='CREATE')
self.assertEqual('ValueError', exc.error)
self.assertEqual(['resources', 'oops'], exc.path)
self.assertEqual('Test Resource failed oops', exc.error_message)
def test_status_reason_general(self):
reason = ('something strange happened')
exc = exception.ResourceFailure(reason, None, action='CREATE')
self.assertEqual('', exc.error)
self.assertEqual([], exc.path)
self.assertEqual('something strange happened', exc.error_message)
def test_status_reason_general_res(self):
res = mock.Mock()
res.name = 'fred'
res.stack.t.get_section_name.return_value = 'Resources'
reason = ('something strange happened')
exc = exception.ResourceFailure(reason, res, action='CREATE')
self.assertEqual('', exc.error)
self.assertEqual(['Resources', 'fred'], exc.path)
self.assertEqual('something strange happened', exc.error_message)
def test_std_exception(self):
base_exc = ValueError('sorry mom')
exc = exception.ResourceFailure(base_exc, None, action='UPDATE')
self.assertEqual('ValueError', exc.error)
self.assertEqual([], exc.path)
self.assertEqual('sorry mom', exc.error_message)
def test_std_exception_with_resource(self):
base_exc = ValueError('sorry mom')
res = mock.Mock()
res.name = 'fred'
res.stack.t.get_section_name.return_value = 'Resources'
exc = exception.ResourceFailure(base_exc, res, action='UPDATE')
self.assertEqual('ValueError', exc.error)
self.assertEqual(['Resources', 'fred'], exc.path)
self.assertEqual('sorry mom', exc.error_message)
def test_heat_exception(self):
base_exc = ValueError('sorry mom')
heat_exc = exception.ResourceFailure(base_exc, None, action='UPDATE')
exc = exception.ResourceFailure(heat_exc, None, action='UPDATE')
self.assertEqual('ValueError', exc.error)
self.assertEqual([], exc.path)
self.assertEqual('sorry mom', exc.error_message)
def test_nested_exceptions(self):
res = mock.Mock()
res.name = 'frodo'
res.stack.t.get_section_name.return_value = 'Resources'
reason = ('Resource UPDATE failed: ValueError: resources.oops: '
'Test Resource failed oops')
base_exc = exception.ResourceFailure(reason, res, action='UPDATE')
exc = exception.ResourceFailure(base_exc, res, action='UPDATE')
self.assertEqual(['Resources', 'frodo', 'resources', 'oops'], exc.path)
self.assertEqual('ValueError', exc.error)
self.assertEqual('Test Resource failed oops', exc.error_message)

@ -95,7 +95,7 @@ class GlanceImageTest(common.HeatTestCase):
)
image = stack['image']
image.t['Properties']['min_disk'] = -1
error_msg = ('Property error : resources.image.properties.min_disk: '
error_msg = ('Property error: resources.image.properties.min_disk: '
'-1 is out of range (min: 0, max: None)')
self._test_validate(image, error_msg)
@ -108,7 +108,7 @@ class GlanceImageTest(common.HeatTestCase):
)
image = stack['image']
image.t['Properties']['min_ram'] = -1
error_msg = ('Property error : resources.image.properties.min_ram: '
error_msg = ('Property error: resources.image.properties.min_ram: '
'-1 is out of range (min: 0, max: None)')
self._test_validate(image, error_msg)
@ -133,7 +133,7 @@ class GlanceImageTest(common.HeatTestCase):
)
image = stack['image']
image.t['Properties']['disk_format'] = 'incorrect_format'
error_msg = ('Property error : '
error_msg = ('Property error: '
'resources.image.properties.disk_format: '
'"incorrect_format" is not an allowed value '
'[ami, ari, aki, vhd, vmdk, raw, qcow2, vdi, iso]')
@ -160,7 +160,7 @@ class GlanceImageTest(common.HeatTestCase):
)
image = stack['image']
image.t['Properties']['container_format'] = 'incorrect_format'
error_msg = ('Property error : '
error_msg = ('Property error: '
'resources.image.properties.container_format: '
'"incorrect_format" is not an allowed value '
'[ami, ari, aki, bare, ova, ovf]')

@ -114,7 +114,8 @@ class ManilaSecurityServiceTest(common.HeatTestCase):
scheduler.TaskRunner(ss.create))
expected_state = (ss.CREATE, ss.FAILED)
self.assertEqual(expected_state, ss.state)
self.assertIn('Exception: error', six.text_type(exc))
self.assertIn('Exception: resources.security_service: error',
six.text_type(exc))
def test_resource_mapping(self):
mapping = security_service.resource_mapping()

@ -155,8 +155,8 @@ class ManilaShareTest(common.HeatTestCase):
share.client().shares.get.return_value = self.failed_share
exc = self.assertRaises(exception.ResourceFailure,
scheduler.TaskRunner(share.check))
self.assertIn("Error: 'status': expected '['available']'",
six.text_type(exc))
self.assertIn("Error: resources.test_share: 'status': expected "
"'['available']'", six.text_type(exc))
def test_share_update(self):
share = self._create_share("stack_share_update")

@ -250,7 +250,7 @@ class TestMistralWorkflow(common.HeatTestCase):
self.assertEqual([], wf.FnGetAtt('executions'))
def test_direct_workflow_validation_error(self):
error_msg = ("Mistral resource validation error : "
error_msg = ("Mistral resource validation error: "
"workflow.properties.tasks.second_task.requires: "
"task second_task contains property 'requires' "
"in case of direct workflow. Only reverse workflows "
@ -258,7 +258,7 @@ class TestMistralWorkflow(common.HeatTestCase):
self._test_validation_failed(workflow_template_bad, error_msg)
def test_wrong_params_using(self):
error_msg = ("Mistral resource validation error : "
error_msg = ("Mistral resource validation error: "
"workflow.properties.params: 'task_name' is not assigned "
"in 'params' in case of reverse type workflow.")
self._test_validation_failed(workflow_template_bad_reverse, error_msg)
@ -289,7 +289,8 @@ class TestMistralWorkflow(common.HeatTestCase):
scheduler.TaskRunner(wf.create))
expected_state = (wf.CREATE, wf.FAILED)
self.assertEqual(expected_state, wf.state)
self.assertIn('Exception: boom!', six.text_type(exc))
self.assertIn('Exception: resources.workflow: boom!',
six.text_type(exc))
def test_update_replace(self):
wf = self._create_resource('workflow', self.rsrc_defn, self.stack)
@ -386,7 +387,8 @@ class TestMistralWorkflow(common.HeatTestCase):
self.mistral.executions.create.side_effect = Exception('boom!')
err = self.assertRaises(exception.ResourceFailure,
scheduler.TaskRunner(wf.signal, details))
self.assertEqual('Exception: boom!', six.text_type(err))
self.assertEqual('Exception: resources.create_vm: boom!',
six.text_type(err))
def test_signal_wrong_input_and_params_type(self):
tmpl = template_format.parse(workflow_template_full)
@ -399,13 +401,15 @@ class TestMistralWorkflow(common.HeatTestCase):
details = {'input': '3'}
err = self.assertRaises(exception.ResourceFailure,
scheduler.TaskRunner(wf.signal, details))
error_message = ("StackValidationFailed: Signal data error : Input in"
error_message = ("StackValidationFailed: resources.create_vm: "
"Signal data error: Input in"
" signal data must be a map, find a <type 'str'>")
self.assertEqual(error_message, six.text_type(err))
details = {'params': '3'}
err = self.assertRaises(exception.ResourceFailure,
scheduler.TaskRunner(wf.signal, details))
error_message = ("StackValidationFailed: Signal data error : Params "
error_message = ("StackValidationFailed: resources.create_vm: "
"Signal data error: Params "
"must be a map, find a <type 'str'>")
self.assertEqual(error_message, six.text_type(err))
@ -420,8 +424,8 @@ class TestMistralWorkflow(common.HeatTestCase):
details = {'input': {'1': '3'}}
err = self.assertRaises(exception.ResourceFailure,
scheduler.TaskRunner(wf.signal, details))
error_message = ("StackValidationFailed: Signal data error :"
" Unknown input 1")
error_message = ("StackValidationFailed: resources.create_vm: "
"Signal data error: Unknown input 1")
self.assertEqual(error_message, six.text_type(err))
@testtools.skipIf(executions is None,

@ -882,7 +882,7 @@ class PropertyTest(common.HeatTestCase):
p = properties.Property({'Type': 'Map', 'Schema': map_schema})
ex = self.assertRaises(exception.StackValidationFailed,
p.get_value, {'valid': 'fish'}, True)
self.assertEqual('Property error : valid: "fish" is not a '
self.assertEqual('Property error: valid: "fish" is not a '
'valid boolean', six.text_type(ex))
def test_map_schema_missing_data(self):
@ -895,7 +895,7 @@ class PropertyTest(common.HeatTestCase):
p = properties.Property({'Type': 'Map', 'Schema': map_schema})
ex = self.assertRaises(exception.StackValidationFailed,
p.get_value, {}, True)
self.assertEqual('Property error : Property valid not assigned',
self.assertEqual('Property error: Property valid not assigned',
six.text_type(ex))
def test_list_schema_good(self):
@ -914,7 +914,7 @@ class PropertyTest(common.HeatTestCase):
ex = self.assertRaises(exception.StackValidationFailed,
p.get_value,
[{'valid': 'True'}, {'valid': 'fish'}], True)
self.assertEqual('Property error : [1].valid: "fish" is not '
self.assertEqual('Property error: [1].valid: "fish" is not '
'a valid boolean', six.text_type(ex))
def test_list_schema_int_good(self):
@ -927,7 +927,7 @@ class PropertyTest(common.HeatTestCase):
p = properties.Property({'Type': 'List', 'Schema': list_schema})
ex = self.assertRaises(exception.StackValidationFailed,
p.get_value, [42, 'fish'], True)
self.assertEqual("Property error : [1]: Value 'fish' is not "
self.assertEqual("Property error: [1]: Value 'fish' is not "
"an integer", six.text_type(ex))
@ -1539,14 +1539,14 @@ class PropertiesValidationTest(common.HeatTestCase):
schema = {'foo': {'Type': 'String'}}
props = properties.Properties(schema, {'foo': ['foo', 'bar']})
ex = self.assertRaises(exception.StackValidationFailed, props.validate)
self.assertEqual('Property error : foo: Value must be a string',
self.assertEqual('Property error: foo: Value must be a string',
six.text_type(ex))
def test_dict_instead_string(self):
schema = {'foo': {'Type': 'String'}}
props = properties.Properties(schema, {'foo': {'foo': 'bar'}})
ex = self.assertRaises(exception.StackValidationFailed, props.validate)
self.assertEqual('Property error : foo: Value must be a string',
self.assertEqual('Property error: foo: Value must be a string',
six.text_type(ex))
def test_none_string(self):
@ -1713,7 +1713,7 @@ class PropertiesValidationTest(common.HeatTestCase):
props = properties.Properties(schema, invalid_data)
ex = self.assertRaises(exception.StackValidationFailed,
props.validate)
self.assertEqual('Property error : foo[0]: Unknown Property bar',
self.assertEqual('Property error: foo[0]: Unknown Property bar',
six.text_type(ex))
def test_nested_properties_schema_invalid_property_in_map(self):
@ -1732,7 +1732,7 @@ class PropertiesValidationTest(common.HeatTestCase):
props = properties.Properties(schema, invalid_data)
ex = self.assertRaises(exception.StackValidationFailed,
props.validate)
self.assertEqual('Property error : foo.boo: Unknown Property bar',
self.assertEqual('Property error: foo.boo: Unknown Property bar',
six.text_type(ex))
def test_more_nested_properties_schema_invalid_property_in_list(self):
@ -1750,7 +1750,7 @@ class PropertiesValidationTest(common.HeatTestCase):
props = properties.Properties(schema, invalid_data)
ex = self.assertRaises(exception.StackValidationFailed,
props.validate)
self.assertEqual('Property error : foo[0].doo: Unknown Property bar',
self.assertEqual('Property error: foo[0].doo: Unknown Property bar',
six.text_type(ex))
def test_more_nested_properties_schema_invalid_property_in_map(self):
@ -1768,7 +1768,7 @@ class PropertiesValidationTest(common.HeatTestCase):
props = properties.Properties(schema, invalid_data)
ex = self.assertRaises(exception.StackValidationFailed,
props.validate)
self.assertEqual('Property error : foo.boo.doo: Unknown Property bar',
self.assertEqual('Property error: foo.boo.doo: Unknown Property bar',
six.text_type(ex))
def test_schema_to_template_empty_schema(self):

@ -315,7 +315,8 @@ class RemoteStackTest(tests_common.HeatTestCase):
rsrc = self.parent['remote_stack']
error = self.assertRaises(exception.ResourceFailure,
scheduler.TaskRunner(rsrc.create))
error_msg = ('ResourceInError: Went to status CREATE_FAILED due to '
error_msg = ('ResourceInError: resources.remote_stack: '
'Went to status CREATE_FAILED due to '
'"Remote stack creation failed"')
self.assertEqual(error_msg, six.text_type(error))
self.assertEqual((rsrc.CREATE, rsrc.FAILED), rsrc.state)
@ -360,7 +361,8 @@ class RemoteStackTest(tests_common.HeatTestCase):
remote_stack_id = rsrc.resource_id
error = self.assertRaises(exception.ResourceFailure,
scheduler.TaskRunner(rsrc.delete))
error_msg = ('ResourceInError: Went to status DELETE_FAILED due to '
error_msg = ('ResourceInError: resources.remote_stack: '
'Went to status DELETE_FAILED due to '
'"Remote stack deletion failed"')
self.assertIn(error_msg, six.text_type(error))
self.assertEqual((rsrc.DELETE, rsrc.FAILED), rsrc.state)
@ -481,7 +483,8 @@ class RemoteStackTest(tests_common.HeatTestCase):
self.heat.actions.resume = mock.MagicMock()
error = self.assertRaises(exception.ResourceFailure,
scheduler.TaskRunner(rsrc.check))
error_msg = ('ResourceInError: Went to status CHECK_FAILED due to '
error_msg = ('ResourceInError: resources.remote_stack: '
'Went to status CHECK_FAILED due to '
'"Remote stack check failed"')
self.assertEqual(error_msg, six.text_type(error))
self.assertEqual((rsrc.CHECK, rsrc.FAILED), rsrc.state)
@ -513,7 +516,8 @@ class RemoteStackTest(tests_common.HeatTestCase):
self.heat.actions.resume = mock.MagicMock()
error = self.assertRaises(exception.ResourceFailure,
scheduler.TaskRunner(rsrc.resume))
error_msg = ('ResourceInError: Went to status RESUME_FAILED due to '
error_msg = ('ResourceInError: resources.remote_stack: '
'Went to status RESUME_FAILED due to '
'"Remote stack resume failed"')
self.assertEqual(error_msg, six.text_type(error))
self.assertEqual((rsrc.RESUME, rsrc.FAILED), rsrc.state)
@ -525,7 +529,8 @@ class RemoteStackTest(tests_common.HeatTestCase):
rsrc.action = rsrc.SUSPEND
error = self.assertRaises(exception.ResourceFailure,
scheduler.TaskRunner(rsrc.resume))
error_msg = 'Error: Cannot resume remote_stack, resource not found'
error_msg = ('Error: resources.remote_stack: '
'Cannot resume remote_stack, resource not found')
self.assertEqual(error_msg, six.text_type(error))
self.assertEqual((rsrc.RESUME, rsrc.FAILED), rsrc.state)
@ -553,7 +558,8 @@ class RemoteStackTest(tests_common.HeatTestCase):
self.heat.actions.suspend = mock.MagicMock()
error = self.assertRaises(exception.ResourceFailure,
scheduler.TaskRunner(rsrc.suspend))