diff --git a/contrib/rackspace/rackspace/tests/test_rackspace_cloud_server.py b/contrib/rackspace/rackspace/tests/test_rackspace_cloud_server.py index cf1715d698..c4a70051ec 100644 --- a/contrib/rackspace/rackspace/tests/test_rackspace_cloud_server.py +++ b/contrib/rackspace/rackspace/tests/test_rackspace_cloud_server.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): diff --git a/heat/common/exception.py b/heat/common/exception.py index bcab20b319..41ce15aa0f 100644 --- a/heat/common/exception.py +++ b/heat/common/exception.py @@ -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): diff --git a/heat/engine/resources/stack_resource.py b/heat/engine/resources/stack_resource.py index eaac14a97c..23e8c7f96a 100644 --- a/heat/engine/resources/stack_resource.py +++ b/heat/engine/resources/stack_resource.py @@ -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): diff --git a/heat/tests/autoscaling/test_launch_config.py b/heat/tests/autoscaling/test_launch_config.py index 29b7d9a67e..a4a2c824bd 100644 --- a/heat/tests/autoscaling/test_launch_config.py +++ b/heat/tests/autoscaling/test_launch_config.py @@ -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)) diff --git a/heat/tests/autoscaling/test_scaling_group.py b/heat/tests/autoscaling/test_scaling_group.py index 8b2a41b34d..cfd819be13 100644 --- a/heat/tests/autoscaling/test_scaling_group.py +++ b/heat/tests/autoscaling/test_scaling_group.py @@ -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.") diff --git a/heat/tests/aws/test_instance.py b/heat/tests/aws/test_instance.py index 71b752e45d..5bdbcb4a41 100644 --- a/heat/tests/aws/test_instance.py +++ b/heat/tests/aws/test_instance.py @@ -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() diff --git a/heat/tests/aws/test_s3.py b/heat/tests/aws/test_s3.py index 0e36b8ed02..f5c4749c55 100644 --- a/heat/tests/aws/test_s3.py +++ b/heat/tests/aws/test_s3.py @@ -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() diff --git a/heat/tests/aws/test_volume.py b/heat/tests/aws/test_volume.py index acd43afcad..721827f0a8 100644 --- a/heat/tests/aws/test_volume.py +++ b/heat/tests/aws/test_volume.py @@ -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) diff --git a/heat/tests/aws/test_waitcondition.py b/heat/tests/aws/test_waitcondition.py index 3dabf25814..579ba94e00 100644 --- a/heat/tests/aws/test_waitcondition.py +++ b/heat/tests/aws/test_waitcondition.py @@ -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() diff --git a/heat/tests/neutron/test_neutron_firewall.py b/heat/tests/neutron/test_neutron_firewall.py index 7703667196..cc51805f00 100644 --- a/heat/tests/neutron/test_neutron_firewall.py +++ b/heat/tests/neutron/test_neutron_firewall.py @@ -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() diff --git a/heat/tests/neutron/test_neutron_loadbalancer.py b/heat/tests/neutron/test_neutron_loadbalancer.py index d9ac10aaf8..e818ba9493 100644 --- a/heat/tests/neutron/test_neutron_loadbalancer.py +++ b/heat/tests/neutron/test_neutron_loadbalancer.py @@ -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() diff --git a/heat/tests/neutron/test_neutron_metering.py b/heat/tests/neutron/test_neutron_metering.py index 352bcdeb0b..ebc06439d1 100644 --- a/heat/tests/neutron/test_neutron_metering.py +++ b/heat/tests/neutron/test_neutron_metering.py @@ -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() diff --git a/heat/tests/neutron/test_neutron_network_gateway.py b/heat/tests/neutron/test_neutron_network_gateway.py index 9ec8cdb523..27f698b4a0 100644 --- a/heat/tests/neutron/test_neutron_network_gateway.py +++ b/heat/tests/neutron/test_neutron_network_gateway.py @@ -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)()) diff --git a/heat/tests/neutron/test_neutron_vpnservice.py b/heat/tests/neutron/test_neutron_vpnservice.py index 8b15feea4a..fc6098afd6 100644 --- a/heat/tests/neutron/test_neutron_vpnservice.py +++ b/heat/tests/neutron/test_neutron_vpnservice.py @@ -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() diff --git a/heat/tests/openstack/test_volume.py b/heat/tests/openstack/test_volume.py index fbf18726ac..e749cce137 100644 --- a/heat/tests/openstack/test_volume.py +++ b/heat/tests/openstack/test_volume.py @@ -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) diff --git a/heat/tests/test_ceilometer_alarm.py b/heat/tests/test_ceilometer_alarm.py index c693b36cc4..64fe0fcb42 100644 --- a/heat/tests/test_ceilometer_alarm.py +++ b/heat/tests/test_ceilometer_alarm.py @@ -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)) diff --git a/heat/tests/test_engine_service.py b/heat/tests/test_engine_service.py index 87eb7c7eb4..faf42e6d17 100644 --- a/heat/tests/test_engine_service.py +++ b/heat/tests/test_engine_service.py @@ -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) diff --git a/heat/tests/test_exception.py b/heat/tests/test_exception.py index 6c206aa705..727f47108b 100644 --- a/heat/tests/test_exception.py +++ b/heat/tests/test_exception.py @@ -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) diff --git a/heat/tests/test_glance_image.py b/heat/tests/test_glance_image.py index a4ec91b80a..53b140e5f9 100644 --- a/heat/tests/test_glance_image.py +++ b/heat/tests/test_glance_image.py @@ -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]') diff --git a/heat/tests/test_manila_security_service.py b/heat/tests/test_manila_security_service.py index bd70ec20b1..ae71af8c83 100644 --- a/heat/tests/test_manila_security_service.py +++ b/heat/tests/test_manila_security_service.py @@ -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() diff --git a/heat/tests/test_manila_share.py b/heat/tests/test_manila_share.py index acdcea7d72..2a59242eb1 100644 --- a/heat/tests/test_manila_share.py +++ b/heat/tests/test_manila_share.py @@ -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") diff --git a/heat/tests/test_mistral_workflow.py b/heat/tests/test_mistral_workflow.py index 7b42789093..485be5c5e1 100644 --- a/heat/tests/test_mistral_workflow.py +++ b/heat/tests/test_mistral_workflow.py @@ -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 ") 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 ") 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, diff --git a/heat/tests/test_properties.py b/heat/tests/test_properties.py index 66b0882f46..52cbb3d4ee 100644 --- a/heat/tests/test_properties.py +++ b/heat/tests/test_properties.py @@ -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): diff --git a/heat/tests/test_remote_stack.py b/heat/tests/test_remote_stack.py index 0ad7323b68..b4430f109e 100644 --- a/heat/tests/test_remote_stack.py +++ b/heat/tests/test_remote_stack.py @@ -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)) - error_msg = ('ResourceInError: Went to status SUSPEND_FAILED due to ' + error_msg = ('ResourceInError: resources.remote_stack: ' + 'Went to status SUSPEND_FAILED due to ' '"Remote stack suspend failed"') self.assertEqual(error_msg, six.text_type(error)) self.assertEqual((rsrc.SUSPEND, rsrc.FAILED), rsrc.state) @@ -567,7 +573,8 @@ class RemoteStackTest(tests_common.HeatTestCase): self.heat.actions.suspend = mock.MagicMock() error = self.assertRaises(exception.ResourceFailure, scheduler.TaskRunner(rsrc.suspend)) - error_msg = 'Error: Cannot suspend remote_stack, resource not found' + error_msg = ('Error: resources.remote_stack: ' + 'Cannot suspend remote_stack, resource not found') self.assertEqual(error_msg, six.text_type(error)) self.assertEqual((rsrc.SUSPEND, rsrc.FAILED), rsrc.state) # assert suspend was not called @@ -632,7 +639,8 @@ class RemoteStackTest(tests_common.HeatTestCase): error = self.assertRaises(exception.ResourceFailure, scheduler.TaskRunner(rsrc.update, update_snippet)) - error_msg = _('ResourceInError: Went to status UPDATE_FAILED due to ' + error_msg = _('ResourceInError: resources.remote_stack: ' + 'Went to status UPDATE_FAILED due to ' '"Remote stack update failed"') self.assertEqual(error_msg, six.text_type(error)) self.assertEqual((rsrc.UPDATE, rsrc.FAILED), rsrc.state) diff --git a/heat/tests/test_resource.py b/heat/tests/test_resource.py index b170b79684..6e70afe3f0 100644 --- a/heat/tests/test_resource.py +++ b/heat/tests/test_resource.py @@ -148,7 +148,8 @@ class ResourceTest(common.HeatTestCase): ev = self.patchobject(res, '_add_event') ex = self.assertRaises(exception.ResourceFailure, res.signal) - self.assertEqual('Exception: Cannot signal resource during ' + self.assertEqual('Exception: resources.res: ' + 'Cannot signal resource during ' '%s' % action, six.text_type(ex)) ev.assert_called_with( action, status, @@ -569,7 +570,7 @@ class ResourceTest(common.HeatTestCase): tmpl = rsrc_defn.ResourceDefinition(rname, 'Foo', {}) res = generic_rsrc.ResourceWithRequiredProps(rname, tmpl, self.stack) - estr = ('Property error : test_resource.Properties: ' + estr = ('Property error: test_resource.Properties: ' 'Property Foo not assigned') create = scheduler.TaskRunner(res.create) err = self.assertRaises(exception.ResourceFailure, create) @@ -582,8 +583,9 @@ class ResourceTest(common.HeatTestCase): {'Food': 'abc'}) res = generic_rsrc.ResourceWithProps(rname, tmpl, self.stack) - estr = ('StackValidationFailed: Property error : ' - 'test_resource.Properties: Unknown Property Food') + estr = ('StackValidationFailed: resources.test_resource: ' + 'Property error: test_resource.Properties: ' + 'Unknown Property Food') create = scheduler.TaskRunner(res.create) err = self.assertRaises(exception.ResourceFailure, create) self.assertIn(estr, six.text_type(err)) @@ -661,7 +663,8 @@ class ResourceTest(common.HeatTestCase): status_reason='just because')) self.m.ReplayAll() - estr = ('ResourceInError: Went to status ERROR due to "just because"') + estr = ('ResourceInError: resources.test_resource: ' + 'Went to status ERROR due to "just because"') create = scheduler.TaskRunner(res.create) err = self.assertRaises(exception.ResourceFailure, create) self.assertEqual(estr, six.text_type(err)) @@ -1563,7 +1566,7 @@ class ResourceAdoptTest(common.HeatTestCase): res = self.stack['foo'] adopt = scheduler.TaskRunner(res.adopt, None) self.assertRaises(exception.ResourceFailure, adopt) - expected = 'Exception: Resource ID was not provided.' + expected = 'Exception: resources.foo: Resource ID was not provided.' self.assertEqual(expected, res.status_reason) @@ -1775,7 +1778,7 @@ class ResourceDependenciesTest(common.HeatTestCase): stack = parser.Stack(utils.dummy_context(), 'test', tmpl) ex = self.assertRaises(exception.StackValidationFailed, stack.validate) - self.assertIn("Property error : resources.bar.properties.FooInt: " + self.assertIn("Property error: resources.bar.properties.FooInt: " "Value 'notanint' is not an integer", six.text_type(ex)) diff --git a/heat/tests/test_sahara_cluster.py b/heat/tests/test_sahara_cluster.py index 7c9ddf2c72..68bc89135e 100644 --- a/heat/tests/test_sahara_cluster.py +++ b/heat/tests/test_sahara_cluster.py @@ -117,7 +117,8 @@ class SaharaClusterTest(common.HeatTestCase): self.cl_mgr.get.return_value = FakeCluster(status='Error') create_task = scheduler.TaskRunner(cluster.create) ex = self.assertRaises(exception.ResourceFailure, create_task) - expected = 'ResourceInError: Went to status Error due to "Unknown"' + expected = ('ResourceInError: resources.super-cluster: ' + 'Went to status Error due to "Unknown"') self.assertEqual(expected, six.text_type(ex)) def test_cluster_delete_fails(self): @@ -125,7 +126,7 @@ class SaharaClusterTest(common.HeatTestCase): self.cl_mgr.delete.side_effect = sahara.sahara_base.APIException() delete_task = scheduler.TaskRunner(cluster.delete) ex = self.assertRaises(exception.ResourceFailure, delete_task) - expected = "APIException: None" + expected = "APIException: resources.super-cluster: None" self.assertEqual(expected, six.text_type(ex)) self.cl_mgr.delete.assert_called_once_with(self.fake_cl.id) @@ -144,7 +145,7 @@ class SaharaClusterTest(common.HeatTestCase): self.cl_mgr.get.reset_mock() delete_task = scheduler.TaskRunner(cluster.delete) ex = self.assertRaises(exception.ResourceFailure, delete_task) - expected = "APIException: None" + expected = "APIException: resources.super-cluster: None" self.assertEqual(expected, six.text_type(ex)) self.cl_mgr.delete.assert_called_once_with(self.fake_cl.id) self.assertEqual(2, self.cl_mgr.get.call_count) @@ -157,7 +158,8 @@ class SaharaClusterTest(common.HeatTestCase): self.cl_mgr.get.reset_mock() delete_task = scheduler.TaskRunner(cluster.delete) ex = self.assertRaises(exception.ResourceFailure, delete_task) - expected = 'ResourceInError: Went to status Error due to "Unknown"' + expected = ('ResourceInError: resources.super-cluster: ' + 'Went to status Error due to "Unknown"') self.assertEqual(expected, six.text_type(ex)) self.cl_mgr.delete.assert_called_once_with(self.fake_cl.id) self.assertEqual(2, self.cl_mgr.get.call_count) diff --git a/heat/tests/test_sahara_templates.py b/heat/tests/test_sahara_templates.py index 8fdddc970e..98ad27f3e3 100644 --- a/heat/tests/test_sahara_templates.py +++ b/heat/tests/test_sahara_templates.py @@ -146,7 +146,7 @@ class SaharaNodeGroupTemplateTest(common.HeatTestCase): self.ngt_mgr.delete.side_effect = sahara.sahara_base.APIException() delete_task = scheduler.TaskRunner(ngt.delete) ex = self.assertRaises(exception.ResourceFailure, delete_task) - expected = "APIException: None" + expected = "APIException: resources.node-group: None" self.assertEqual(expected, six.text_type(ex)) self.ngt_mgr.delete.assert_called_once_with(self.fake_ngt.id) @@ -188,7 +188,7 @@ class SaharaNodeGroupTemplateTest(common.HeatTestCase): self.patchobject(ngt, 'is_using_neutron').return_value = False ex = self.assertRaises(exception.StackValidationFailed, ngt.validate) - self.assertEqual(u"Property error : " + self.assertEqual(u"Property error: " u"resources.node-group.properties.flavor: " u"Error validating value u'm1.large'", six.text_type(ex)) @@ -262,7 +262,7 @@ class SaharaClusterTemplateTest(common.HeatTestCase): self.ct_mgr.delete.side_effect = sahara.sahara_base.APIException() delete_task = scheduler.TaskRunner(ct.delete) ex = self.assertRaises(exception.ResourceFailure, delete_task) - expected = "APIException: None" + expected = "APIException: resources.cluster-template: None" self.assertEqual(expected, six.text_type(ex)) self.ct_mgr.delete.assert_called_once_with(self.fake_ct.id) diff --git a/heat/tests/test_server.py b/heat/tests/test_server.py index 38211a16ca..19224c69a2 100644 --- a/heat/tests/test_server.py +++ b/heat/tests/test_server.py @@ -430,7 +430,7 @@ class ServersTest(common.HeatTestCase): create = scheduler.TaskRunner(server.create) error = self.assertRaises(exception.ResourceFailure, create) self.assertEqual( - "StackValidationFailed: Property error : " + "StackValidationFailed: resources.WebServer: Property error: " "WebServer.Properties.image: Error validating value 'Slackware': " "The Image (Slackware) could not be found.", six.text_type(error)) @@ -455,7 +455,7 @@ class ServersTest(common.HeatTestCase): create = scheduler.TaskRunner(server.create) error = self.assertRaises(exception.ResourceFailure, create) self.assertEqual( - 'StackValidationFailed: Property error : ' + 'StackValidationFailed: resources.WebServer: Property error: ' 'WebServer.Properties.image: Multiple physical ' 'resources were found with name (CentOS 5.2).', six.text_type(error)) @@ -480,7 +480,7 @@ class ServersTest(common.HeatTestCase): create = scheduler.TaskRunner(server.create) error = self.assertRaises(exception.ResourceFailure, create) self.assertEqual( - "StackValidationFailed: Property error : " + "StackValidationFailed: resources.WebServer: Property error: " "WebServer.Properties.image: Error validating value '1': " "The Image (1) could not be found.", six.text_type(error)) @@ -1055,7 +1055,7 @@ class ServersTest(common.HeatTestCase): error = self.assertRaises(exception.StackValidationFailed, server.validate) self.assertEqual( - "Property error : Resources.WebServer.Properties.key_name: " + "Property error: Resources.WebServer.Properties.key_name: " "Error validating value 'test2': The Key (test2) could not " "be found.", six.text_type(error)) self.m.VerifyAll() @@ -1547,8 +1547,8 @@ class ServersTest(common.HeatTestCase): updater = scheduler.TaskRunner(server.update, update_template) error = self.assertRaises(exception.ResourceFailure, updater) self.assertEqual( - "Error: Resizing to 'm1.small' failed, status 'ACTIVE'", - six.text_type(error)) + "Error: resources.srv_update2: Resizing to 'm1.small' failed, " + "status 'ACTIVE'", six.text_type(error)) self.assertEqual((server.UPDATE, server.FAILED), server.state) self.m.VerifyAll() @@ -1714,7 +1714,8 @@ class ServersTest(common.HeatTestCase): updater = scheduler.TaskRunner(server.update, update_template) error = self.assertRaises(exception.ResourceFailure, updater) self.assertEqual( - "Error: Rebuilding server failed, status 'ERROR'", + "Error: resources.srv_updrbldfail: " + "Rebuilding server failed, status 'ERROR'", six.text_type(error)) self.assertEqual((server.UPDATE, server.FAILED), server.state) self.m.VerifyAll() @@ -1758,7 +1759,8 @@ class ServersTest(common.HeatTestCase): ex = self.assertRaises(exception.ResourceFailure, scheduler.TaskRunner(server.suspend)) - self.assertEqual('Error: Cannot suspend srv_sus1, ' + self.assertEqual('Error: resources.srv_sus1: ' + 'Cannot suspend srv_sus1, ' 'resource_id not set', six.text_type(ex)) self.assertEqual((server.SUSPEND, server.FAILED), server.state) @@ -1779,7 +1781,8 @@ class ServersTest(common.HeatTestCase): ex = self.assertRaises(exception.ResourceFailure, scheduler.TaskRunner(server.suspend)) - self.assertEqual('NotFound: Failed to find server 1234', + self.assertEqual('NotFound: resources.srv_sus2: ' + 'Failed to find server 1234', six.text_type(ex)) self.assertEqual((server.SUSPEND, server.FAILED), server.state) @@ -1881,7 +1884,8 @@ class ServersTest(common.HeatTestCase): server.state_set(server.SUSPEND, server.COMPLETE) ex = self.assertRaises(exception.ResourceFailure, scheduler.TaskRunner(server.resume)) - self.assertEqual('Error: Cannot resume srv_susp_norid, ' + self.assertEqual('Error: resources.srv_susp_norid: ' + 'Cannot resume srv_susp_norid, ' 'resource_id not set', six.text_type(ex)) self.assertEqual((server.RESUME, server.FAILED), server.state) @@ -1907,7 +1911,8 @@ class ServersTest(common.HeatTestCase): ex = self.assertRaises(exception.ResourceFailure, scheduler.TaskRunner(server.resume)) - self.assertEqual('NotFound: Failed to find server 1234', + self.assertEqual('NotFound: resources.srv_res_nf: ' + 'Failed to find server 1234', six.text_type(ex)) self.assertEqual((server.RESUME, server.FAILED), server.state) @@ -3226,7 +3231,8 @@ class ServersTest(common.HeatTestCase): # update updater = scheduler.TaskRunner(server.update, update_template) err = self.assertRaises(exception.ResourceFailure, updater) - self.assertEqual('StackValidationFailed: Property error : ' + self.assertEqual('StackValidationFailed: resources.my_server: ' + 'Property error: ' 'WebServer.Properties.image: The Image ' '(Update Image) could not be found.', six.text_type(err)) diff --git a/heat/tests/test_stack.py b/heat/tests/test_stack.py index 45b1c8b955..685b0d29e8 100644 --- a/heat/tests/test_stack.py +++ b/heat/tests/test_stack.py @@ -598,7 +598,8 @@ class StackTest(common.HeatTestCase): self.assertEqual((self.stack.SUSPEND, self.stack.FAILED), self.stack.state) - self.assertEqual('Resource SUSPEND failed: Exception: foo', + self.assertEqual('Resource SUSPEND failed: Exception: ' + 'resources.AResource: foo', self.stack.status_reason) self.m.VerifyAll() @@ -626,7 +627,8 @@ class StackTest(common.HeatTestCase): self.assertEqual((self.stack.RESUME, self.stack.FAILED), self.stack.state) - self.assertEqual('Resource RESUME failed: Exception: foo', + self.assertEqual('Resource RESUME failed: Exception: ' + 'resources.AResource: foo', self.stack.status_reason) self.m.VerifyAll() @@ -795,8 +797,8 @@ class StackTest(common.HeatTestCase): self.stack.adopt() self.assertEqual((self.stack.ADOPT, self.stack.FAILED), self.stack.state) - expected = ('Resource ADOPT failed: Exception: Resource ID was not' - ' provided.') + expected = ('Resource ADOPT failed: Exception: resources.foo: ' + 'Resource ID was not provided.') self.assertEqual(expected, self.stack.status_reason) def test_adopt_stack_rollback(self): @@ -1562,7 +1564,7 @@ class StackTest(common.HeatTestCase): ex = self.assertRaises(exception.StackValidationFailed, self.stack.validate) - self.assertEqual('Output validation error : ' + self.assertEqual('Output validation error: ' 'Outputs.Resource_attr.Value: ' 'The Referenced Attribute ' '(AResource Bar) is incorrect.', @@ -1736,7 +1738,7 @@ class StackTest(common.HeatTestCase): ex = self.assertRaises(exception.StackValidationFailed, self.stack.validate) - self.assertEqual('Output validation error : ' + self.assertEqual('Output validation error: ' 'outputs.resource_attr.value: ' 'The Referenced Attribute ' '(AResource Bar) is incorrect.', diff --git a/heat/tests/test_stack_delete.py b/heat/tests/test_stack_delete.py index 1a2853e4ca..e839b7349b 100644 --- a/heat/tests/test_stack_delete.py +++ b/heat/tests/test_stack_delete.py @@ -417,7 +417,8 @@ class StackTest(common.HeatTestCase): mock_rd.assert_called_once() self.assertEqual((self.stack.DELETE, self.stack.FAILED), self.stack.state) - self.assertEqual('Resource DELETE failed: Exception: foo', + self.assertEqual('Resource DELETE failed: Exception: ' + 'resources.AResource: foo', self.stack.status_reason) def test_delete_stack_with_resource_log_is_clear(self): diff --git a/heat/tests/test_stack_resource.py b/heat/tests/test_stack_resource.py index b1f97e9223..ce9751994d 100644 --- a/heat/tests/test_stack_resource.py +++ b/heat/tests/test_stack_resource.py @@ -373,7 +373,7 @@ class StackResourceTest(StackResourceBaseTest): stack = parser.Stack(utils.dummy_context(), stack_name, templatem.Template(tmpl, files=files)) rsrc = stack['volume_server'] - raise_exc_msg = ('Failed to validate : resources.volume_server: ' + raise_exc_msg = ('Failed to validate: resources.volume_server: ' 'The specified reference "instance" ' '(in volume_attachment.Properties.instance_uuid) ' 'is incorrect.') @@ -708,6 +708,7 @@ class StackResourceCheckCompleteTest(StackResourceBaseTest): def setUp(self): super(StackResourceCheckCompleteTest, self).setUp() self.nested = mock.MagicMock() + self.nested.name = 'nested-stack' self.parent_resource.nested = mock.MagicMock(return_value=self.nested) self.parent_resource._nested = self.nested setattr(self.nested, self.action.upper(), self.action.upper()) @@ -732,10 +733,17 @@ class StackResourceCheckCompleteTest(StackResourceBaseTest): done but the nested stack is not in (,COMPLETE) state """ self.nested.status = 'FAILED' - self.nested.status_reason = 'broken on purpose' + reason = ('Resource %s failed: ValueError: ' + 'resources.%s: broken on purpose' % ( + self.action.upper(), + 'child_res')) + exp_path = 'resources.test.resources.child_res' + exp = 'ValueError: %s: broken on purpose' % exp_path + self.nested.status_reason = reason complete = getattr(self.parent_resource, 'check_%s_complete' % self.action) - self.assertRaises(resource.ResourceUnknownStatus, complete, None) + exc = self.assertRaises(exception.ResourceFailure, complete, None) + self.assertEqual(exp, six.text_type(exc)) self.parent_resource.nested.assert_called_once_with( show_deleted=self.show_deleted, force_reload=True) diff --git a/heat/tests/test_swift.py b/heat/tests/test_swift.py index 05e4027b67..b3c81d838d 100644 --- a/heat/tests/test_swift.py +++ b/heat/tests/test_swift.py @@ -283,7 +283,7 @@ class swiftTest(common.HeatTestCase): rsrc = self.create_resource(t, stack, 'SwiftContainer') deleter = scheduler.TaskRunner(rsrc.delete) ex = self.assertRaises(exception.ResourceFailure, deleter) - self.assertIn('ResourceActionNotSupported: ' + self.assertIn('ResourceActionNotSupported: resources.test_resource: ' 'Deleting non-empty container', six.text_type(ex)) diff --git a/heat/tests/test_swiftsignal.py b/heat/tests/test_swiftsignal.py index e3ed1ed09d..7e6dcec61a 100644 --- a/heat/tests/test_swiftsignal.py +++ b/heat/tests/test_swiftsignal.py @@ -202,7 +202,9 @@ class SwiftSignalHandleTest(common.HeatTestCase): rsrc = st.resources['test_wait_condition_handle'] exc = self.assertRaises(exception.ResourceFailure, scheduler.TaskRunner(rsrc.delete)) - self.assertEqual('ClientException: Overlimit: 413', six.text_type(exc)) + self.assertEqual('ClientException: ' + 'resources.test_wait_condition_handle: ' + 'Overlimit: 413', six.text_type(exc)) @mock.patch.object(swift.SwiftClientPlugin, '_create') @mock.patch.object(resource.Resource, 'physical_resource_name') @@ -231,7 +233,9 @@ class SwiftSignalHandleTest(common.HeatTestCase): rsrc = st.resources['test_wait_condition_handle'] exc = self.assertRaises(exception.ResourceFailure, scheduler.TaskRunner(rsrc.delete)) - self.assertEqual('ClientException: Overlimit: 413', six.text_type(exc)) + self.assertEqual('ClientException: ' + 'resources.test_wait_condition_handle: ' + 'Overlimit: 413', six.text_type(exc)) @mock.patch.object(swift.SwiftClientPlugin, '_create') @mock.patch.object(resource.Resource, 'physical_resource_name') @@ -386,11 +390,13 @@ class SwiftSignalTest(common.HeatTestCase): self.addCleanup(timeutils.clear_time_override) st.create() - self.assertIn("Resource CREATE failed: SwiftSignalTimeout", + self.assertIn("SwiftSignalTimeout: resources.test_wait_condition: " + "1 of 2 received - Signal 1 received", st.status_reason) wc = st['test_wait_condition'] - self.assertEqual("SwiftSignalTimeout: 1 of 2 received - Signal 1 " - "received", wc.status_reason) + self.assertEqual("SwiftSignalTimeout: resources.test_wait_condition: " + "1 of 2 received - Signal 1 received", + wc.status_reason) @mock.patch.object(swift.SwiftClientPlugin, '_create') @mock.patch.object(resource.Resource, 'physical_resource_name') @@ -448,7 +454,8 @@ class SwiftSignalTest(common.HeatTestCase): st.create() self.assertEqual(('CREATE', 'FAILED'), st.state) wc = st['test_wait_condition'] - self.assertEqual("SwiftSignalFailure: foo;bar", wc.status_reason) + self.assertEqual("SwiftSignalFailure: resources.test_wait_condition: " + "foo;bar", wc.status_reason) @mock.patch.object(swift.SwiftClientPlugin, '_create') @mock.patch.object(resource.Resource, 'physical_resource_name') @@ -766,7 +773,8 @@ class SwiftSignalTest(common.HeatTestCase): st.create() self.assertEqual(('CREATE', 'FAILED'), st.state) wc = st['test_wait_condition'] - self.assertEqual('Error: Failed to parse JSON data: {"status": ' + self.assertEqual('Error: resources.test_wait_condition: ' + 'Failed to parse JSON data: {"status": ' '"SUCCESS"', wc.status_reason) @mock.patch.object(swift.SwiftClientPlugin, '_create') @@ -791,7 +799,8 @@ class SwiftSignalTest(common.HeatTestCase): st.create() self.assertEqual(('CREATE', 'FAILED'), st.state) wc = st['test_wait_condition'] - self.assertEqual('Error: Unknown status: BOO', wc.status_reason) + self.assertEqual('Error: resources.test_wait_condition: ' + 'Unknown status: BOO', wc.status_reason) @mock.patch.object(swift.SwiftClientPlugin, '_create') @mock.patch.object(resource.Resource, 'physical_resource_name') diff --git a/heat/tests/test_trove_cluster.py b/heat/tests/test_trove_cluster.py index 26eb2ba3e8..76bfb1a530 100644 --- a/heat/tests/test_trove_cluster.py +++ b/heat/tests/test_trove_cluster.py @@ -160,7 +160,7 @@ class TroveClusterTest(common.HeatTestCase): self.rsrc_defn['Properties']['instances'][0]['flavor'] = 'm1.small' tc = trove_cluster.TroveCluster('cluster', self.rsrc_defn, self.stack) ex = self.assertRaises(exception.StackValidationFailed, tc.validate) - error_msg = ("Property error : " + error_msg = ("Property error: " "resources.cluster.properties.instances[0].flavor: " "Error validating value 'm1.small': " "The Flavor ID (m1.small) could not be found.") diff --git a/heat/tests/test_validate.py b/heat/tests/test_validate.py index 5f60ded467..a3b20f31bf 100644 --- a/heat/tests/test_validate.py +++ b/heat/tests/test_validate.py @@ -1073,7 +1073,7 @@ class validateTest(common.HeatTestCase): t = template_format.parse(test_template_invalid_property) engine = service.EngineService('a', 't') res = dict(engine.validate_template(None, t, {})) - self.assertEqual({'Error': 'Property error : WikiDatabase.Properties: ' + self.assertEqual({'Error': 'Property error: WikiDatabase.Properties: ' 'Unknown Property UnknownProperty'}, res) def test_invalid_resources(self): @@ -1123,7 +1123,7 @@ class validateTest(common.HeatTestCase): engine = service.EngineService('a', 't') res = dict(engine.validate_template(None, t, {})) self.assertEqual( - {'Error': 'Property error : WikiDatabase.Properties: ' + {'Error': 'Property error: WikiDatabase.Properties: ' 'Property SourceDestCheck not implemented yet'}, res) @@ -1407,7 +1407,7 @@ class validateTest(common.HeatTestCase): exc = self.assertRaises(exception.StackValidationFailed, stack.validate) - self.assertEqual(_('Parameter Groups error : ' + self.assertEqual(_('Parameter Groups error: ' 'parameter_groups.Database ' 'Group: The InstanceType parameter must be ' 'assigned to one parameter group only.'), @@ -1425,7 +1425,7 @@ class validateTest(common.HeatTestCase): exc = self.assertRaises(exception.StackValidationFailed, stack.validate) - self.assertEqual(_('Parameter Groups error : ' + self.assertEqual(_('Parameter Groups error: ' 'parameter_groups.Database Group: The grouped ' 'parameter SomethingNotHere does not ' 'reference a valid parameter.'), @@ -1438,7 +1438,7 @@ class validateTest(common.HeatTestCase): exc = self.assertRaises(exception.StackValidationFailed, stack.validate) - self.assertEqual(_('Parameter Groups error : parameter_groups.Server ' + self.assertEqual(_('Parameter Groups error: parameter_groups.Server ' 'Group: The parameters must be provided for each ' 'parameter group.'), six.text_type(exc)) @@ -1449,7 +1449,7 @@ class validateTest(common.HeatTestCase): exc = self.assertRaises(exception.StackValidationFailed, stack.validate) - self.assertEqual(_('Parameter Groups error : parameter_groups: ' + self.assertEqual(_('Parameter Groups error: parameter_groups: ' 'The parameter_groups should be ' 'a list.'), six.text_type(exc)) @@ -1460,7 +1460,7 @@ class validateTest(common.HeatTestCase): exc = self.assertRaises(exception.StackValidationFailed, stack.validate) - self.assertEqual(_('Parameter Groups error : ' + self.assertEqual(_('Parameter Groups error: ' 'parameter_groups.Server Group: ' 'The parameters of parameter group should be ' 'a list.'), six.text_type(exc)) diff --git a/heat/tests/test_zaqar_queue.py b/heat/tests/test_zaqar_queue.py index 3119805884..1f73943c57 100644 --- a/heat/tests/test_zaqar_queue.py +++ b/heat/tests/test_zaqar_queue.py @@ -137,7 +137,8 @@ class ZaqarMessageQueueTest(common.HeatTestCase): err = self.assertRaises(exception.ResourceFailure, scheduler.TaskRunner(queue.create)) - self.assertEqual("Error: Message queue myqueue already exists.", + self.assertEqual("Error: resources.MyQueue2: " + "Message queue myqueue already exists.", six.text_type(err)) self.m.VerifyAll() @@ -164,7 +165,8 @@ class ZaqarMessageQueueTest(common.HeatTestCase): err = self.assertRaises(exception.ResourceFailure, scheduler.TaskRunner(queue.create)) - self.assertEqual("Error: Message queue myqueue creation failed.", + self.assertEqual("Error: resources.MyQueue2: " + "Message queue myqueue creation failed.", six.text_type(err)) self.m.VerifyAll() diff --git a/heat_integrationtests/common/test_resources/test_resource.py b/heat_integrationtests/common/test_resources/test_resource.py index 88f1745fb8..55255a6e14 100644 --- a/heat_integrationtests/common/test_resources/test_resource.py +++ b/heat_integrationtests/common/test_resources/test_resource.py @@ -100,7 +100,7 @@ class TestResource(resource.Resource): # emulate failure if fail_prop: - raise Exception("Test Resource failed %s", self.name) + raise ValueError("Test Resource failed %s" % self.name) def handle_update(self, json_snippet=None, tmpl_diff=None, prop_diff=None): value = prop_diff.get(self.VALUE) diff --git a/heat_integrationtests/functional/test_template_resource.py b/heat_integrationtests/functional/test_template_resource.py index 5b189acd8f..0d5734b3ee 100644 --- a/heat_integrationtests/functional/test_template_resource.py +++ b/heat_integrationtests/functional/test_template_resource.py @@ -648,3 +648,39 @@ Outputs: self.client.actions.check(stack_id=stack_identifier) self._wait_for_stack_status(stack_identifier, 'CHECK_COMPLETE') + + +class TemplateResourceErrorMessageTest(test.HeatIntegrationTest): + """Prove that nested stack errors don't suck.""" + template = ''' +HeatTemplateFormatVersion: '2012-12-12' +Resources: + victim: + Type: fail.yaml +''' + nested_templ = ''' +HeatTemplateFormatVersion: '2012-12-12' +Resources: + oops: + Type: OS::Heat::TestResource + Properties: + fail: true + wait_secs: 2 +''' + + def setUp(self): + super(TemplateResourceErrorMessageTest, self).setUp() + self.client = self.orchestration_client + + def test_fail(self): + stack_identifier = self.stack_create( + template=self.template, + files={'fail.yaml': self.nested_templ}, + expected_status='CREATE_FAILED') + stack = self.client.stacks.get(stack_identifier) + + exp_path = 'resources.victim.resources.oops' + exp_msg = 'Test Resource failed oops' + exp = 'Resource CREATE failed: ValueError: %s: %s' % (exp_path, + exp_msg) + self.assertEqual(exp, stack.stack_status_reason)