]> review.fuel-infra Code Review - openstack-build/heat-build.git/commitdiff
Fix for bad content inside Resources element
authorDavanum Srinivas <dims@linux.vnet.ibm.com>
Wed, 24 Jul 2013 03:14:16 +0000 (23:14 -0400)
committerGerrit Code Review <review@openstack.org>
Tue, 30 Jul 2013 17:57:04 +0000 (17:57 +0000)
In validate_template check if we have a dict before we try to
get 'Type'. We also need to check the response back from
validate_template to see if there are any 'Error'(s) and present
that back to the user.

Fixes LP# 1204157

Change-Id: I0f636a6a84f6afc9a0aff3089e2bd13a8f88a470

heat/api/cfn/v1/stacks.py
heat/engine/service.py
heat/tests/test_api_cfn_v1.py
heat/tests/test_validate.py

index 764e6b0b29f06fdbf47090e37f179310bf2954e2..4d89ecaf0859f5b21c53c115123cacd3d1f109fc 100644 (file)
@@ -438,6 +438,10 @@ class StackController(object):
 
         try:
             res = self.engine_rpcapi.validate_template(con, template)
+            if 'Error' in res:
+                return api_utils.format_response('ValidateTemplate',
+                                                 res['Error'])
+
             res['Parameters'] = [format_validate_parameter(k, v)
                                  for k, v in res['Parameters'].items()]
             return api_utils.format_response('ValidateTemplate', res)
index add8e1a895f1b55d6dfc16baa3ca1b032f4ba133..0c438eef9ce887bb1391468527b2767295785d5b 100644 (file)
@@ -312,9 +312,19 @@ class EngineService(service.Service):
             return {'Error': 'At least one Resources member must be defined.'}
 
         for res in tmpl_resources.values():
-            if not res.get('Type'):
+            try:
+                if not res.get('Type'):
+                    return {'Error':
+                            'Every Resource object must '
+                            'contain a Type member.'}
+            except AttributeError:
+                type_res = type(res)
+                if isinstance(res, unicode):
+                    type_res = "string"
                 return {'Error':
-                        'Every Resources object must contain a Type member.'}
+                        'Resources must contain Resource. '
+                        'Found a [%s] instead' % type_res}
+
             ResourceClass = resource.get_class(res['Type'])
             props = properties.Properties(ResourceClass.properties_schema,
                                           res.get('Properties', {}))
index bb663efef04015733bea78ba798727698fe2ce88..b302770e6336c2e8938249851840912c5b1dee4e 100644 (file)
@@ -1076,6 +1076,40 @@ class CfnStackControllerTest(HeatTestCase):
         self.assertEqual(type(result),
                          exception.HeatInvalidParameterValueError)
 
+    def test_bad_resources_in_template(self):
+        # Format a dummy request
+        json_template = {
+            'template': {
+                'AWSTemplateFormatVersion': '2010-09-09',
+                'Resources': {
+                    'Type': 'AWS: : EC2: : Instance',
+                },
+            }
+        }
+        params = {'Action': 'ValidateTemplate',
+                  'TemplateBody': '%s' % json.dumps(json_template)}
+        response = {'Error': 'Resources must contain Resource. '
+                    'Found a [string] instead'}
+        dummy_req = self._dummy_GET_request(params)
+
+        # Stub out the RPC call to the engine with a pre-canned response
+        self.m.StubOutWithMock(rpc, 'call')
+        rpc.call(dummy_req.context, self.topic,
+                 {'namespace': None,
+                  'method': 'validate_template',
+                  'args': {'template': json_template},
+                  'version': self.api_version}, None).AndReturn(response)
+        self.m.ReplayAll()
+
+        response = self.controller.validate_template(dummy_req)
+
+        expected = {'ValidateTemplateResponse':
+                    {'ValidateTemplateResult':
+                     'Resources must contain Resource. '
+                     'Found a [string] instead'}}
+        self.assertEqual(expected, response)
+        self.m.VerifyAll()
+
     def test_delete(self):
         # Format a dummy request
         stack_name = "wordpress"
index 4c971f30762c5aa63aa54eca808c54e916d55827..c815d043d6fa284e54893ea94fccf3991e97ef68 100644 (file)
@@ -211,6 +211,31 @@ test_template_findinmap_invalid = '''
 }
 '''
 
+test_template_invalid_resources = '''
+{
+  "AWSTemplateFormatVersion" : "2010-09-09",
+  "Description" : "AWS CloudFormation Sample Template for xyz.",
+   "Parameters" : {
+        "InstanceType" : {
+            "Description" : "Defined instance type",
+            "Type" : "String",
+            "Default" : "node.ee",
+            "AllowedValues" : ["node.ee", "node.apache", "node.api"],
+            "ConstraintDescription" : "must be a valid instance type."
+        }
+    },
+    "Resources" : {
+        "Type" : "AWS::EC2::Instance",
+        "Metadata" : {
+        },
+        "Properties" : {
+            "ImageId" : { "Ref" : "centos-6.4-20130701-0" },
+            "InstanceType" : { "Ref" : "InstanceType" }
+         }
+    }
+}
+'''
+
 test_template_invalid_property = '''
 {
   "AWSTemplateFormatVersion" : "2010-09-09",
@@ -605,6 +630,18 @@ class validateTest(HeatTestCase):
         res = dict(engine.validate_template(None, t))
         self.assertEqual(res, {'Error': 'Unknown Property UnknownProperty'})
 
+    def test_invalid_resources(self):
+        t = template_format.parse(test_template_invalid_resources)
+        self.m.StubOutWithMock(instances.Instance, 'nova')
+        instances.Instance.nova().AndReturn(self.fc)
+        self.m.ReplayAll()
+
+        engine = service.EngineService('a', 't')
+        res = dict(engine.validate_template(None, t))
+        self.assertEqual({'Error': 'Resources must contain Resource. '
+                          'Found a [string] instead'},
+                         res)
+
     def test_unimplemented_property(self):
         t = template_format.parse(test_template_unimplemented_property)
         self.m.StubOutWithMock(instances.Instance, 'nova')