diff --git a/heat/engine/environment.py b/heat/engine/environment.py index 554d571ce8..00e79d2b57 100644 --- a/heat/engine/environment.py +++ b/heat/engine/environment.py @@ -273,6 +273,14 @@ class ResourceRegistry(object): return match def get_class(self, resource_type, resource_name=None): + if resource_type == "": + msg = _('Resource "%s" has no type') % resource_name + raise exception.StackValidationFailed(message=msg) + elif resource_type is None: + msg = _('Non-empty resource type is required ' + 'for resource "%s"') % resource_name + raise exception.StackValidationFailed(message=msg) + info = self.get_resource_info(resource_type, resource_name=resource_name) if info is None: diff --git a/heat/engine/resource.py b/heat/engine/resource.py index c31f03af61..9ec3c519ad 100644 --- a/heat/engine/resource.py +++ b/heat/engine/resource.py @@ -159,7 +159,7 @@ class Resource(object): return super(Resource, cls).__new__(cls) # Select the correct subclass to instantiate - ResourceClass = stack.env.get_class(json['Type'], + ResourceClass = stack.env.get_class(json.get('Type'), resource_name=name) return ResourceClass(name, json, stack) diff --git a/heat/tests/test_resource.py b/heat/tests/test_resource.py index 25c32f8d7b..31769a9aee 100644 --- a/heat/tests/test_resource.py +++ b/heat/tests/test_resource.py @@ -24,6 +24,7 @@ from heat.engine import resource from heat.engine import scheduler from heat.engine import template from heat.engine import environment +from heat.openstack.common.gettextutils import _ import heat.db.api as db_api from heat.tests import generic_resource as generic_rsrc @@ -67,6 +68,23 @@ class ResourceTest(HeatTestCase): self.assertRaises(exception.StackValidationFailed, resource.Resource, 'aresource', snippet, self.stack) + def test_resource_non_type(self): + snippet = {'Type': ''} + resource_name = 'aresource' + ex = self.assertRaises(exception.StackValidationFailed, + resource.Resource, resource_name, + snippet, self.stack) + self.assertIn(_('Resource "%s" has no type') % resource_name, str(ex)) + + def test_resource_missed_type(self): + snippet = {'not-a-Type': 'GenericResourceType'} + resource_name = 'aresource' + ex = self.assertRaises(exception.StackValidationFailed, + resource.Resource, resource_name, + snippet, self.stack) + self.assertIn(_('Non-empty resource type is required ' + 'for resource "%s"') % resource_name, str(ex)) + def test_state_defaults(self): tmpl = {'Type': 'Foo'} res = generic_rsrc.GenericResource('test_res_def', tmpl, self.stack)