diff --git a/heat/common/exception.py b/heat/common/exception.py index c96959bd0..7b23fcbed 100644 --- a/heat/common/exception.py +++ b/heat/common/exception.py @@ -320,10 +320,18 @@ class SnapshotNotFound(HeatException): "could not be found.") +class TemplateNotFound(HeatException): + msg_fmt = _("%(message)s") + + class ResourceTypeNotFound(HeatException): msg_fmt = _("The Resource Type (%(type_name)s) could not be found.") +class InvalidResourceType(HeatException): + msg_fmt = _("%(message)s") + + class ResourceNotAvailable(HeatException): msg_fmt = _("The Resource (%(resource_name)s) is not available.") diff --git a/heat/engine/environment.py b/heat/engine/environment.py index ab53f2bf0..16fd188bc 100644 --- a/heat/engine/environment.py +++ b/heat/engine/environment.py @@ -391,20 +391,19 @@ class ResourceRegistry(object): 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) + raise exception.InvalidResourceType(message=msg) elif resource_type is None: msg = _('Non-empty resource type is required ' 'for resource "%s"') % resource_name - raise exception.StackValidationFailed(message=msg) + raise exception.InvalidResourceType(message=msg) elif not isinstance(resource_type, six.string_types): msg = _('Resource "%s" type is not a string') % resource_name - raise exception.StackValidationFailed(message=msg) + raise exception.InvalidResourceType(message=msg) info = self.get_resource_info(resource_type, resource_name=resource_name) if info is None: - msg = _("Unknown resource Type : %s") % resource_type - raise exception.StackValidationFailed(message=msg) + raise exception.ResourceTypeNotFound(type_name=resource_type) return info.get_class() def as_dict(self): diff --git a/heat/engine/resource.py b/heat/engine/resource.py index 49e1d0672..c480cf6a1 100644 --- a/heat/engine/resource.py +++ b/heat/engine/resource.py @@ -131,7 +131,7 @@ class Resource(object): try: ResourceClass = registry.get_class(definition.resource_type, resource_name=name) - except exception.NotFound: + except exception.TemplateNotFound: ResourceClass = template_resource.TemplateResource assert issubclass(ResourceClass, Resource) diff --git a/heat/engine/resources/openstack/heat/resource_group.py b/heat/engine/resources/openstack/heat/resource_group.py index 6648fe493..a3a7f6a7b 100644 --- a/heat/engine/resources/openstack/heat/resource_group.py +++ b/heat/engine/resources/openstack/heat/resource_group.py @@ -189,7 +189,7 @@ class ResourceGroup(stack_resource.StackResource): # make sure we can resolve the nested resource type try: self.stack.env.get_class(res_def.resource_type) - except exception.NotFound: + except exception.TemplateNotFound: # its a template resource pass diff --git a/heat/engine/resources/template_resource.py b/heat/engine/resources/template_resource.py index 4e9877dff..c27b7a7ae 100644 --- a/heat/engine/resources/template_resource.py +++ b/heat/engine/resources/template_resource.py @@ -81,7 +81,7 @@ class TemplateResource(stack_resource.StackResource): args = {'name': template_name, 'exc': six.text_type(r_exc)} msg = _('Could not fetch remote template ' '"%(name)s": %(exc)s') % args - raise exception.NotFound(msg_fmt=msg) + raise exception.TemplateNotFound(message=msg) @staticmethod def get_schemas(tmpl, param_defaults): @@ -94,7 +94,7 @@ class TemplateResource(stack_resource.StackResource): self._parsed_nested = None try: tmpl = template.Template(self.child_template()) - except (exception.NotFound, ValueError) as download_error: + except (exception.TemplateNotFound, ValueError) as download_error: self.validation_exception = download_error tmpl = template.Template( {"HeatTemplateFormatVersion": "2012-12-12"}) @@ -169,7 +169,7 @@ class TemplateResource(stack_resource.StackResource): try: t_data = self.get_template_file(self.template_name, self.allowed_schemes) - except exception.NotFound as err: + except exception.TemplateNotFound as err: reported_excp = err if t_data is None: diff --git a/heat/engine/service.py b/heat/engine/service.py index 7c3eb9a74..71ae150ff 100644 --- a/heat/engine/service.py +++ b/heat/engine/service.py @@ -1006,10 +1006,10 @@ class EngineService(service.Service): """ try: resource_class = resources.global_env().get_class(type_name) - except exception.StackValidationFailed: - raise exception.ResourceTypeNotFound(type_name=type_name) - except exception.NotFound as ex: - raise exception.StackValidationFailed(message=ex.message) + except (exception.InvalidResourceType, + exception.ResourceTypeNotFound, + exception.TemplateNotFound) as ex: + raise ex def properties_schema(): for name, schema_dict in resource_class.properties_schema.items(): @@ -1038,10 +1038,10 @@ class EngineService(service.Service): try: return resources.global_env().get_class( type_name).resource_to_template(type_name) - except exception.StackValidationFailed: - raise exception.ResourceTypeNotFound(type_name=type_name) - except exception.NotFound as ex: - raise exception.StackValidationFailed(message=ex.message) + except (exception.InvalidResourceType, + exception.ResourceTypeNotFound, + exception.TemplateNotFound) as ex: + raise ex @context.request_context def list_events(self, cnxt, stack_identity, filters=None, limit=None, diff --git a/heat/tests/test_engine_service.py b/heat/tests/test_engine_service.py index ecece759e..dc9a4d708 100644 --- a/heat/tests/test_engine_service.py +++ b/heat/tests/test_engine_service.py @@ -2380,7 +2380,7 @@ class StackServiceTest(common.HeatTestCase): mock_iterable = mock.MagicMock(return_value=iter([info])) with mock.patch('heat.engine.environment.ResourceRegistry.iterable_by', new=mock_iterable): - ex = self.assertRaises(exception.StackValidationFailed, + ex = self.assertRaises(exception.TemplateNotFound, function, self.ctx, type_name='ResourceWithWrongRefOnFile') diff --git a/heat/tests/test_provider_template.py b/heat/tests/test_provider_template.py index 62d8b6ec2..168eb5ee3 100644 --- a/heat/tests/test_provider_template.py +++ b/heat/tests/test_provider_template.py @@ -522,7 +522,7 @@ class ProviderTemplateTest(common.HeatTestCase): env_str = {'resource_registry': {'resources': {'fred': { "OS::ResourceType": "some_magic.yaml"}}}} env = environment.Environment(env_str) - ex = self.assertRaises(exception.NotFound, env.get_class, + ex = self.assertRaises(exception.TemplateNotFound, env.get_class, 'OS::ResourceType', 'fred') self.assertIn('Could not fetch remote template "some_magic.yaml"', six.text_type(ex)) diff --git a/heat/tests/test_resource.py b/heat/tests/test_resource.py index edf2fe567..7100c0f31 100644 --- a/heat/tests/test_resource.py +++ b/heat/tests/test_resource.py @@ -75,7 +75,7 @@ class ResourceTest(common.HeatTestCase): self.assertEqual(generic_rsrc.GenericResource, cls) def test_get_class_noexist(self): - self.assertRaises(exception.StackValidationFailed, + self.assertRaises(exception.ResourceTypeNotFound, resources.global_env().get_class, 'NoExistResourceType') @@ -109,13 +109,13 @@ class ResourceTest(common.HeatTestCase): def test_resource_new_err(self): snippet = rsrc_defn.ResourceDefinition('aresource', 'NoExistResourceType') - self.assertRaises(exception.StackValidationFailed, + self.assertRaises(exception.ResourceTypeNotFound, resource.Resource, 'aresource', snippet, self.stack) def test_resource_non_type(self): resource_name = 'aresource' snippet = rsrc_defn.ResourceDefinition(resource_name, '') - ex = self.assertRaises(exception.StackValidationFailed, + ex = self.assertRaises(exception.InvalidResourceType, resource.Resource, resource_name, snippet, self.stack) self.assertIn(_('Resource "%s" has no type') % resource_name, diff --git a/heat/tests/test_resource_group.py b/heat/tests/test_resource_group.py index e7c23da64..6640a97b0 100644 --- a/heat/tests/test_resource_group.py +++ b/heat/tests/test_resource_group.py @@ -308,9 +308,10 @@ class ResourceGroupTest(common.HeatTestCase): stack = utils.parse_stack(tmp) snip = stack.t.resource_definitions(stack)['group1'] resg = resource_group.ResourceGroup('test', snip, stack) - exc = self.assertRaises(exception.StackValidationFailed, + exc = self.assertRaises(exception.ResourceTypeNotFound, resg.validate) - self.assertIn('Unknown resource Type', six.text_type(exc)) + exp_msg = 'The Resource Type (idontexist) could not be found.' + self.assertIn(exp_msg, six.text_type(exc)) def test_reference_attr(self): stack = utils.parse_stack(template2) diff --git a/heat/tests/test_stack_resource.py b/heat/tests/test_stack_resource.py index f408db719..3f5c285c3 100644 --- a/heat/tests/test_stack_resource.py +++ b/heat/tests/test_stack_resource.py @@ -370,23 +370,29 @@ class StackResourceTest(common.HeatTestCase): rsrc.validate) self.assertIn(raise_exc_msg, six.text_type(exc)) - def _test_validate_unknown_resource_type(self, stack_name, - tmpl, resource_name): - raise_exc_msg = ('Unknown resource Type : idontexist') + def _test_validate_unknown_resource_type(self, stack_name, tmpl, + resource_name, + stack_resource=True): + raise_exc_msg = ('The Resource Type (idontexist) could not be found.') stack = parser.Stack(utils.dummy_context(), stack_name, tmpl) rsrc = stack[resource_name] - - exc = self.assertRaises(exception.StackValidationFailed, - rsrc.validate) + if stack_resource: + exc = self.assertRaises(exception.StackValidationFailed, + rsrc.validate) + else: + exc = self.assertRaises(exception.ResourceTypeNotFound, + rsrc.validate) self.assertIn(raise_exc_msg, six.text_type(exc)) def test_validate_resource_group(self): - # test validate without nested template + # resource group validate without nested template is a normal + # resource validation stack_name = 'validate_resource_group_template' t = template_format.parse(resource_group_template) tmpl = templatem.Template(t) self._test_validate_unknown_resource_type(stack_name, tmpl, - 'my_resource_group') + 'my_resource_group', + stack_resource=False) # validate with nested template res_prop = t['resources']['my_resource_group']['properties'] @@ -397,7 +403,7 @@ class StackResourceTest(common.HeatTestCase): 'my_resource_group') def test_validate_heat_autoscaling_group(self): - # test validate without nested template + # Autoscaling validation is a nested stack validation stack_name = 'validate_heat_autoscaling_group_template' t = template_format.parse(heat_autoscaling_group_template) tmpl = templatem.Template(t)