]> review.fuel-infra Code Review - openstack-build/heat-build.git/commitdiff
Make error message for InvalidTemplateReference sane
authorZane Bitter <zbitter@redhat.com>
Tue, 3 Sep 2013 15:22:22 +0000 (17:22 +0200)
committerZane Bitter <zbitter@redhat.com>
Tue, 3 Sep 2013 15:32:09 +0000 (17:32 +0200)
Previously it was more or less incomprehensible. Now it will report the
non-existent resource the uesr tried to reference and the path (starting
with Resources) in the JSON document where the error occurred.

Change-Id: Id98eb4157df16674b8c8a9a190b82ee350c5386f

heat/common/exception.py
heat/engine/resource.py
heat/tests/test_resource.py
heat/tests/test_vpc.py

index 1f92baf4043af629e9201c02a41fb157b1e93a35..da1db5a51b95228f292e2515dbdf35dad0141da8 100644 (file)
@@ -236,7 +236,7 @@ class InvalidTemplateAttribute(HeatException):
 
 
 class InvalidTemplateReference(HeatException):
-    message = _("The specified reference (%(resource)s %(key)s)"
+    message = _("The specified reference \"%(resource)s\" (in %(key)s)"
                 " is incorrect.")
 
 
index c5b3cb70424d5b8ecc17168a28a0740123c94a73..c3e7b36f0b60c3bfbef57ca1e026c830d51a5100 100644 (file)
@@ -269,29 +269,29 @@ class Resource(object):
     def __str__(self):
         return '%s "%s"' % (self.__class__.__name__, self.name)
 
-    def _add_dependencies(self, deps, head, fragment):
+    def _add_dependencies(self, deps, path, fragment):
         if isinstance(fragment, dict):
             for key, value in fragment.items():
                 if key in ('DependsOn', 'Ref', 'Fn::GetAtt'):
                     if key == 'Fn::GetAtt':
-                        value, head = value
+                        value, att = value
 
                     try:
                         target = self.stack.resources[value]
                     except KeyError:
                         raise exception.InvalidTemplateReference(
                             resource=value,
-                            key=head)
+                            key=path)
                     if key == 'DependsOn' or target.strict_dependency:
                         deps += (self, target)
                 else:
-                    self._add_dependencies(deps, key, value)
+                    self._add_dependencies(deps, '%s.%s' % (path, key), value)
         elif isinstance(fragment, list):
-            for item in fragment:
-                self._add_dependencies(deps, head, item)
+            for index, item in enumerate(fragment):
+                self._add_dependencies(deps, '%s[%d]' % (path, index), item)
 
     def add_dependencies(self, deps):
-        self._add_dependencies(deps, None, self.t)
+        self._add_dependencies(deps, self.name, self.t)
         deps += (self, None)
 
     def required_by(self):
index 345f90303bda623f3eecc0b070b22bafeca01307..144889dc761e249eee688a383a1514d8aed3b3b3 100644 (file)
@@ -658,6 +658,23 @@ class ResourceDependenciesTest(HeatTestCase):
         self.assertIn(res, graph)
         self.assertIn(stack['foo'], graph[res])
 
+    def test_ref_fail(self):
+        tmpl = template.Template({
+            'Resources': {
+                'foo': {'Type': 'GenericResourceType'},
+                'bar': {
+                    'Type': 'ResourceWithPropsType',
+                    'Properties': {
+                        'Foo': {'Ref': 'baz'},
+                    }
+                }
+            }
+        })
+        ex = self.assertRaises(exception.InvalidTemplateReference,
+                               parser.Stack,
+                               None, 'test', tmpl)
+        self.assertIn('"baz" (in bar.Properties.Foo)', str(ex))
+
     def test_getatt(self):
         tmpl = template.Template({
             'Resources': {
@@ -724,6 +741,45 @@ class ResourceDependenciesTest(HeatTestCase):
         self.assertIn(res, graph)
         self.assertIn(stack['foo'], graph[res])
 
+    def test_getatt_fail(self):
+        tmpl = template.Template({
+            'Resources': {
+                'foo': {'Type': 'GenericResourceType'},
+                'bar': {
+                    'Type': 'ResourceWithPropsType',
+                    'Properties': {
+                        'Foo': {'Fn::GetAtt': ['baz', 'bar']},
+                    }
+                }
+            }
+        })
+        ex = self.assertRaises(exception.InvalidTemplateReference,
+                               parser.Stack,
+                               None, 'test', tmpl)
+        self.assertIn('"baz" (in bar.Properties.Foo)', str(ex))
+
+    def test_getatt_fail_nested_deep(self):
+        tmpl = template.Template({
+            'Resources': {
+                'foo': {'Type': 'GenericResourceType'},
+                'bar': {
+                    'Type': 'ResourceWithPropsType',
+                    'Properties': {
+                        'Foo': {'Fn::Join': [",", ["blarg",
+                                                   {'Fn::GetAtt': ['foo',
+                                                                   'bar']},
+                                                   "wibble",
+                                                   {'Fn::GetAtt': ['baz',
+                                                                   'bar']}]]},
+                    }
+                }
+            }
+        })
+        ex = self.assertRaises(exception.InvalidTemplateReference,
+                               parser.Stack,
+                               None, 'test', tmpl)
+        self.assertIn('"baz" (in bar.Properties.Foo.Fn::Join[1][3])', str(ex))
+
     def test_dependson(self):
         tmpl = template.Template({
             'Resources': {
@@ -743,6 +799,20 @@ class ResourceDependenciesTest(HeatTestCase):
         self.assertIn(res, graph)
         self.assertIn(stack['foo'], graph[res])
 
+    def test_dependson_fail(self):
+        tmpl = template.Template({
+            'Resources': {
+                'foo': {
+                    'Type': 'GenericResourceType',
+                    'DependsOn': 'wibble',
+                }
+            }
+        })
+        ex = self.assertRaises(exception.InvalidTemplateReference,
+                               parser.Stack,
+                               None, 'test', tmpl)
+        self.assertIn('"wibble" (in foo)', str(ex))
+
 
 class MetadataTest(HeatTestCase):
     def setUp(self):
index 2e53758b68bf637ceb696b90d8a0659497172884..fff4731cf70d0772db82270e6c5770790c63ed01 100644 (file)
@@ -668,7 +668,7 @@ Resources:
             self.test_template_error)
         expected_exception = exception.InvalidTemplateReference(
             resource='INVALID-REF-IN-TEMPLATE',
-            key='GroupSet')
+            key='the_nic.Properties.GroupSet[0]')
 
         self.assertEquals(str(expected_exception), str(real_exception))