diff options
author | Rakesh H S <rh-s@hpe.com> | 2016-03-01 12:08:42 +0530 |
---|---|---|
committer | Rakesh H S <rh-s@hpe.com> | 2016-03-01 12:08:42 +0530 |
commit | 645810eb4038bea334b7c996e49a4ed4f7379290 (patch) | |
tree | 4fe594b8fdb7082537a20a06afb7b67afe8cfca0 | |
parent | 4116ec36ba73bdcd33338db0a05f4b7b0bc9c0cc (diff) | |
download | heat-645810eb4038bea334b7c996e49a4ed4f7379290.tar.gz |
Raise ResourceTypeNotFound in get_resource_info()
Rather than return None when doing get_resource_info() on resource types
that don't exist, raise a ResourceTypeNotFound exception. We can then catch
that and turn it into StackValidationFailed where appropriate, but we don't
make assumptions about where the code is being called from at the point where
we raise the exception.
Change-Id: Idf6f837befea8ccb10fdaf9196490da3dd5be1fb
Related-Bug: #1447194
Related-Bug: #1518458
Closes-Bug: #1550179
-rw-r--r-- | heat/engine/environment.py | 21 | ||||
-rw-r--r-- | heat/engine/resource.py | 11 | ||||
-rw-r--r-- | heat/engine/resources/template_resource.py | 26 | ||||
-rw-r--r-- | heat/tests/test_environment.py | 25 | ||||
-rw-r--r-- | heat/tests/test_resource_group.py | 3 | ||||
-rw-r--r-- | heat/tests/test_stack_resource.py | 2 |
6 files changed, 55 insertions, 33 deletions
diff --git a/heat/engine/environment.py b/heat/engine/environment.py index af8b32830..8cd621651 100644 --- a/heat/engine/environment.py +++ b/heat/engine/environment.py @@ -420,8 +420,12 @@ class ResourceRegistry(object): giter) for info in sorted(matches): - match = info.get_resource_info(resource_type, - resource_name) + try: + match = info.get_resource_info(resource_type, + resource_name) + except exception.ResourceTypeNotFound: + continue + if registry_type is None or isinstance(match, registry_type): if ignore is not None and match == ignore: continue @@ -436,6 +440,8 @@ class ResourceRegistry(object): self._register_info([resource_type], info) return match + raise exception.ResourceTypeNotFound(type_name=resource_type) + def get_class(self, resource_type, resource_name=None, files=None): info = self.get_resource_info(resource_type, resource_name=resource_name) @@ -455,11 +461,12 @@ class ResourceRegistry(object): msg = _('Resource "%s" type is not a string') % resource_name raise exception.StackValidationFailed(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) + try: + info = self.get_resource_info(resource_type, + resource_name=resource_name) + except exception.ResourceTypeNotFound as exc: + raise exception.StackValidationFailed(message=six.text_type(exc)) + return info.get_class_to_instantiate() def as_dict(self): diff --git a/heat/engine/resource.py b/heat/engine/resource.py index e81da4029..324b306c3 100644 --- a/heat/engine/resource.py +++ b/heat/engine/resource.py @@ -422,9 +422,14 @@ class Resource(object): """ if self.type() == resource_type: return True - ri = self.stack.env.get_resource_info(self.type(), - self.name) - return ri is not None and ri.name == resource_type + + try: + ri = self.stack.env.get_resource_info(self.type(), + self.name) + except exception.ResourceTypeNotFound: + return False + else: + return ri.name == resource_type def implementation_signature(self): """Return a tuple defining the implementation. diff --git a/heat/engine/resources/template_resource.py b/heat/engine/resources/template_resource.py index eae54ad03..3200008df 100644 --- a/heat/engine/resources/template_resource.py +++ b/heat/engine/resources/template_resource.py @@ -71,11 +71,12 @@ class TemplateResource(stack_resource.StackResource): return TemplateResource def _get_resource_info(self, rsrc_defn): - tri = self.stack.env.get_resource_info( - rsrc_defn.resource_type, - resource_name=rsrc_defn.name, - registry_type=environment.TemplateResourceInfo) - if tri is None: + try: + tri = self.stack.env.get_resource_info( + rsrc_defn.resource_type, + resource_name=rsrc_defn.name, + registry_type=environment.TemplateResourceInfo) + except exception.ResourceTypeNotFound: self.validation_exception = ValueError(_( 'Only Templates with an extension of .yaml or ' '.template are supported')) @@ -88,7 +89,7 @@ class TemplateResource(stack_resource.StackResource): else: self.allowed_schemes = REMOTE_SCHEMES + LOCAL_SCHEMES - return tri + return tri @staticmethod def get_template_file(template_name, allowed_schemes): @@ -265,14 +266,17 @@ class TemplateResource(stack_resource.StackResource): except ValueError as ex: msg = _("Failed to retrieve template data: %s") % ex raise exception.StackValidationFailed(message=msg) - fri = self.stack.env.get_resource_info( - self.type(), - resource_name=self.name, - ignore=self.resource_info) # If we're using an existing resource type as a facade for this # template, check for compatibility between the interfaces. - if fri is not None: + try: + fri = self.stack.env.get_resource_info( + self.type(), + resource_name=self.name, + ignore=self.resource_info) + except exception.ResourceTypeNotFound: + pass + else: facade_cls = fri.get_class(files=self.stack.t.files) self._validate_against_facade(facade_cls) diff --git a/heat/tests/test_environment.py b/heat/tests/test_environment.py index c7d5509f3..9cb83578b 100644 --- a/heat/tests/test_environment.py +++ b/heat/tests/test_environment.py @@ -105,8 +105,9 @@ class EnvironmentTest(common.HeatTestCase): u'OS::Networking::FloatingIP': 'ip.yaml'}}}} env = environment.Environment() - self.assertIsNone(env.get_resource_info('OS::Networking::FloatingIP', - 'my_fip')) + self.assertRaises(exception.ResourceTypeNotFound, + env.get_resource_info, + 'OS::Networking::FloatingIP', 'my_fip') env.load(new_env) self.assertEqual('ip.yaml', @@ -203,7 +204,7 @@ class EnvironmentDuplicateTest(common.HeatTestCase): expected_equal=True)), ('diff_temp', dict(resource_type='not.yaml', expected_equal=False)), - ('diff_map', dict(resource_type='OS::SomethingElse', + ('diff_map', dict(resource_type='OS::Nova::Server', expected_equal=False)), ('diff_path', dict(resource_type='a/test.yaml', expected_equal=False)), @@ -377,7 +378,8 @@ class GlobalEnvLoadingTest(common.HeatTestCase): resources._load_global_environment(g_env) # 3. assert our resource is in now gone. - self.assertIsNone(g_env.get_resource_info('OS::Nova::Server')) + self.assertRaises(exception.ResourceTypeNotFound, + g_env.get_resource_info, 'OS::Nova::Server') # 4. make sure we haven't removed something we shouldn't have self.assertEqual(instance.Instance, @@ -402,7 +404,8 @@ class GlobalEnvLoadingTest(common.HeatTestCase): resources._load_global_environment(g_env) # 3. assert our resources are now gone. - self.assertIsNone(g_env.get_resource_info('AWS::EC2::Instance')) + self.assertRaises(exception.ResourceTypeNotFound, + g_env.get_resource_info, 'AWS::EC2::Instance') # 4. make sure we haven't removed something we shouldn't have self.assertEqual(server.Server, @@ -513,11 +516,12 @@ class ChildEnvTest(common.HeatTestCase): self.assertIsNotNone(victim) cenv = environment.get_child_environment(penv, None, item_to_remove=victim) - res = cenv.get_resource_info('OS::Food', resource_name='abc') - self.assertIsNone(res) + self.assertRaises(exception.ResourceTypeNotFound, + cenv.get_resource_info, + 'OS::Food', resource_name='abc') self.assertNotIn('OS::Food', cenv.user_env_as_dict()['resource_registry']) - # make sure the parent env is uneffected + # make sure the parent env is unaffected innocent = penv.get_resource_info('OS::Food', resource_name='abc') self.assertIsNotNone(innocent) @@ -578,8 +582,9 @@ class ChildEnvTest(common.HeatTestCase): self.assertIn('hooks', resources['nested_res']) self.assertIsNotNone( cenv.get_resource_info('OS::Food', resource_name='abc')) - self.assertIsNone( - cenv.get_resource_info('OS::Fruit', resource_name='a')) + self.assertRaises(exception.ResourceTypeNotFound, + cenv.get_resource_info, + 'OS::Fruit', resource_name='a') res = cenv.get_resource_info('OS::Fruit', resource_name='b') self.assertIsNotNone(res) self.assertEqual(u'carrots.yaml', res.value) diff --git a/heat/tests/test_resource_group.py b/heat/tests/test_resource_group.py index e01fc78d5..c984903a9 100644 --- a/heat/tests/test_resource_group.py +++ b/heat/tests/test_resource_group.py @@ -418,7 +418,8 @@ class ResourceGroupTest(common.HeatTestCase): resg = resource_group.ResourceGroup('test', snip, stack) exc = self.assertRaises(exception.StackValidationFailed, 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 179f22ee5..e980084fd 100644 --- a/heat/tests/test_stack_resource.py +++ b/heat/tests/test_stack_resource.py @@ -378,7 +378,7 @@ class StackResourceTest(StackResourceBaseTest): def _test_validate_unknown_resource_type(self, stack_name, tmpl, resource_name): - raise_exc_msg = ('Unknown resource Type : idontexist') + 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, |