diff --git a/tripleo_common/actions/templates.py b/tripleo_common/actions/templates.py index 7793353d9..3475e20f0 100644 --- a/tripleo_common/actions/templates.py +++ b/tripleo_common/actions/templates.py @@ -22,6 +22,7 @@ import tempfile as tf import yaml from heatclient.common import template_utils +from heatclient import exc as heat_exc from mistral_lib import actions from swiftclient import exceptions as swiftexceptions @@ -157,25 +158,32 @@ class ProcessTemplatesAction(base.TripleOAction): "the J2 excludes list to: %s" % j2_excl_data) return j2_excl_data - def _heat_resource_exists(self, resource_name, context): + def _heat_resource_exists(self, nested_stack_name, resource_name, context): heatclient = self.get_orchestration_client(context) - stack_exists = False - for stack in heatclient.stacks.list(): - if self.container == str(stack.stack_name): - stack_exists = True - break - if not stack_exists: + try: + stack = heatclient.stacks.get(self.container) + except heat_exc.HTTPNotFound: LOG.debug("Resource does not exist because stack does not exist") return False - resources = heatclient.resources.list(self.container, nested_depth=6) - for resource in resources: - if str(resource.resource_name) == resource_name: - LOG.debug("Resource exists: {}".format(resource_name)) - return True + try: + nested_stack = heatclient.resources.get(stack.id, + nested_stack_name) + except heat_exc.HTTPNotFound: + LOG.debug( + "Resource does not exist because {} stack does " + "not exist".format(nested_stack_name)) + return False - LOG.debug("Resource does not exist: {}".format(resource_name)) - return False + try: + heatclient.resources.get(nested_stack.physical_resource_id, + resource_name) + except heat_exc.HTTPNotFound: + LOG.debug("Resource does not exist: {}".format(resource_name)) + return False + else: + LOG.debug("Resource exists: {}".format(resource_name)) + return True def _process_custom_roles(self, context): swift = self.get_object_client(context) @@ -228,7 +236,7 @@ class ProcessTemplatesAction(base.TripleOAction): # Check to see if legacy named API network exists # and if so we need to set compat_name api_net = "{}Network".format(constants.LEGACY_API_NETWORK) - if self._heat_resource_exists(api_net, context): + if self._heat_resource_exists('Networks', api_net, context): n['compat_name'] = 'Internal' LOG.info("Upgrade compatibility enabled for legacy " "network resource Internal.") diff --git a/tripleo_common/tests/actions/test_templates.py b/tripleo_common/tests/actions/test_templates.py index 41504b919..91d16ef29 100644 --- a/tripleo_common/tests/actions/test_templates.py +++ b/tripleo_common/tests/actions/test_templates.py @@ -16,6 +16,7 @@ import jinja2 import mock import yaml +from heatclient import exc as heat_exc from swiftclient import exceptions as swiftexceptions from tripleo_common.actions import templates @@ -503,50 +504,41 @@ class ProcessTemplatesActionTest(base.TestCase): def test_heat_resource_exists(self, client_mock): mock_ctx = mock.MagicMock() heat_client = mock.MagicMock() - heat_client.stacks.list.return_value = [ - mock.MagicMock(stack_name='overcloud') - ] - heat_client.resources.list.return_value = [ - mock.MagicMock( - links=[{'rel': 'stack', - 'href': 'http://192.0.2.1:8004/v1/' - 'a959ac7d6a4a475daf2428df315c41ef/' - 'stacks/overcloud/123'}], - logical_resource_id='logical_id', - physical_resource_id='resource_id', - resource_type='OS::Heat::ResourceGroup', - resource_name='InternalNetwork' - ), - ] + heat_client.stacks.get.return_value = mock.MagicMock( + stack_name='overcloud') + heat_client.resources.get.return_value = mock.MagicMock( + links=[{'rel': 'stack', + 'href': 'http://192.0.2.1:8004/v1/' + 'a959ac7d6a4a475daf2428df315c41ef/' + 'stacks/overcloud/123'}], + logical_resource_id='logical_id', + physical_resource_id='resource_id', + resource_type='OS::Heat::ResourceGroup', + resource_name='InternalApiNetwork' + ) client_mock.return_value = heat_client action = templates.ProcessTemplatesAction() - self.assertTrue(action._heat_resource_exists('InternalNetwork', - mock_ctx)) + self.assertTrue( + action._heat_resource_exists( + 'Networks', 'InternalNetwork', mock_ctx)) @mock.patch('tripleo_common.actions.base.TripleOAction.' 'get_orchestration_client') def test_no_heat_resource_exists(self, client_mock): mock_ctx = mock.MagicMock() heat_client = mock.MagicMock() - heat_client.stacks.list.return_value = [ - mock.MagicMock(stack_name='overcloud') - ] - heat_client.resources.list.return_value = [ - mock.MagicMock( - links=[{'rel': 'stack', - 'href': 'http://192.0.2.1:8004/v1/' - 'a959ac7d6a4a475daf2428df315c41ef/' - 'stacks/overcloud/123'}], - logical_resource_id='logical_id', - physical_resource_id='resource_id', - resource_type='OS::Heat::ResourceGroup', - resource_name='InternalApiNetwork' - ), - ] + heat_client.stacks.get.return_value = mock.MagicMock( + stack_name='overcloud') + + def return_not_found(*args): + raise heat_exc.HTTPNotFound() + + heat_client.resources.get.side_effect = return_not_found client_mock.return_value = heat_client action = templates.ProcessTemplatesAction() - self.assertFalse(action._heat_resource_exists('InternalNetwork', - mock_ctx)) + self.assertFalse( + action._heat_resource_exists( + 'Networks', 'InternalNetwork', mock_ctx)) @mock.patch('tripleo_common.actions.templates.ProcessTemplatesAction' '._heat_resource_exists')