Convert parser tests that need nested stacks to unit tests

Part of blueprint decouple-nested
Change-Id: Id64d88104ac11601beac95cf5792f814cad388c8
This commit is contained in:
Angus Salkeld
2015-01-05 14:57:27 +10:00
parent bac63f6144
commit 98d888dc8c
3 changed files with 122 additions and 73 deletions

View File

@@ -27,7 +27,6 @@ from heat.common import context
from heat.common import exception
from heat.common import heat_keystoneclient as hkc
from heat.common import template_format
from heat.common import urlfetch
import heat.db.api as db_api
from heat.engine.cfn import functions as cfn_funcs
from heat.engine.cfn import template as cfn_t
@@ -1047,75 +1046,71 @@ class StackTest(common.HeatTestCase):
status_reason='blarg')
self.assertEqual(1, stack.total_resources())
def _setup_nested(self, name):
nested_tpl = ('{"HeatTemplateFormatVersion" : "2012-12-12",'
'"Resources":{'
'"A": {"Type": "GenericResourceType"},'
'"B": {"Type": "GenericResourceType"}}}')
tpl = {'HeatTemplateFormatVersion': "2012-12-12",
'Resources':
{'A': {'Type': 'AWS::CloudFormation::Stack',
'Properties':
{'TemplateURL': 'http://server.test/nested.json'}},
'B': {'Type': 'GenericResourceType'}}}
self.m.StubOutWithMock(urlfetch, 'get')
urlfetch.get('http://server.test/nested.json').AndReturn(nested_tpl)
self.m.ReplayAll()
self.stack = parser.Stack(self.ctx, 'test_stack', parser.Template(tpl),
status_reason=name)
self.stack.store()
self.stack.create()
def test_total_resources_nested(self):
self._setup_nested('zyzzyx')
self.assertEqual(4, self.stack.total_resources())
self.assertIsNotNone(self.stack['A'].nested())
self.assertEqual(
2, self.stack['A'].nested().total_resources())
self.assertEqual(
4,
self.stack['A'].nested().root_stack.total_resources())
tpl = {'HeatTemplateFormatVersion': '2012-12-12',
'Resources':
{'A': {'Type': 'GenericResourceType'}}}
stack = parser.Stack(self.ctx, 'test_stack', parser.Template(tpl),
status_reason='blarg')
stack['A'].nested = mock.Mock()
stack['A'].nested.return_value.total_resources.return_value = 3
self.assertEqual(4, stack.total_resources())
def test_iter_resources(self):
self._setup_nested('iter_resources')
nested_stack = self.stack['A'].nested()
resource_generator = self.stack.iter_resources()
tpl = {'HeatTemplateFormatVersion': '2012-12-12',
'Resources':
{'A': {'Type': 'GenericResourceType'},
'B': {'Type': 'GenericResourceType'}}}
stack = parser.Stack(self.ctx, 'test_stack', parser.Template(tpl),
status_reason='blarg')
def get_more(nested_depth=0):
yield 'X'
yield 'Y'
yield 'Z'
stack['A'].nested = mock.MagicMock()
stack['A'].nested.return_value.iter_resources.side_effect = get_more
resource_generator = stack.iter_resources()
self.assertIsNot(resource_generator, list)
first_level_resources = list(resource_generator)
self.assertEqual(2, len(first_level_resources))
self.assertIn(self.stack['A'], first_level_resources)
self.assertIn(self.stack['B'], first_level_resources)
all_resources = list(stack.iter_resources(1))
self.assertEqual(5, len(all_resources))
all_resources = list(self.stack.iter_resources(1))
self.assertIn(self.stack['A'], first_level_resources)
self.assertIn(self.stack['B'], first_level_resources)
self.assertIn(nested_stack['A'], all_resources)
self.assertIn(nested_stack['B'], all_resources)
def test_root_stack_no_parent(self):
tpl = {'HeatTemplateFormatVersion': '2012-12-12',
'Resources':
{'A': {'Type': 'GenericResourceType'}}}
stack = parser.Stack(self.ctx, 'test_stack', parser.Template(tpl),
status_reason='blarg')
def test_root_stack(self):
self._setup_nested('toor')
self.assertEqual(self.stack, self.stack.root_stack)
self.assertIsNotNone(self.stack['A'].nested())
self.assertEqual(
self.stack, self.stack['A'].nested().root_stack)
self.assertEqual(stack, stack.root_stack)
def test_nested_stack_abandon(self):
self._setup_nested('nestedstack')
ret = self.stack.prepare_abandon()
self.assertIsNotNone(self.stack['A'].nested())
self.assertEqual(
self.stack, self.stack['A'].nested().root_stack)
def test_root_stack_parent_no_stack(self):
tpl = {'HeatTemplateFormatVersion': '2012-12-12',
'Resources':
{'A': {'Type': 'GenericResourceType'}}}
stack = parser.Stack(self.ctx, 'test_stack', parser.Template(tpl),
status_reason='blarg')
keys = ['name', 'id', 'action', 'status', 'template', 'resources',
'project_id', 'stack_user_project_id', 'environment']
stack.parent_resource = mock.Mock()
stack.parent_resource.stack = None
self.assertEqual(stack, stack.root_stack)
self.assertEqual(len(keys), len(ret))
nested_stack_data = ret['resources']['A']
self.assertEqual(len(keys), len(nested_stack_data))
for key in keys:
self.assertIn(key, ret)
self.assertIn(key, nested_stack_data)
def test_root_stack_with_parent(self):
tpl = {'HeatTemplateFormatVersion': '2012-12-12',
'Resources':
{'A': {'Type': 'GenericResourceType'}}}
stack = parser.Stack(self.ctx, 'test_stack', parser.Template(tpl),
status_reason='blarg')
stack.parent_resource = mock.Mock()
stack.parent_resource.stack.root_stack = 'test value'
self.assertEqual('test value', stack.root_stack)
def test_load_parent_resource(self):
self.stack = parser.Stack(self.ctx, 'load_parent_resource',
@@ -1851,12 +1846,17 @@ class StackTest(common.HeatTestCase):
self.m.VerifyAll()
def _get_stack_to_check(self, name):
tpl = {"HeatTemplateFormatVersion": "2012-12-12",
"Resources": {
"A": {"Type": "GenericResourceType"},
"B": {"Type": "GenericResourceType"}}}
self.stack = parser.Stack(self.ctx, name, parser.Template(tpl),
status_reason=name)
self.stack.store()
def _mock_check(res):
res.handle_check = mock.Mock()
if hasattr(res, 'nested'):
[_mock_check(r) for r in res.nested().resources.values()]
self._setup_nested(name)
[_mock_check(res) for res in self.stack.resources.values()]
return self.stack
@@ -1870,18 +1870,6 @@ class StackTest(common.HeatTestCase):
for res in stack.resources.values()]
self.assertNotIn('not fully supported', stack.status_reason)
def test_check_nested_stack(self):
def _mock_check(res):
res.handle_check = mock.Mock()
self._setup_nested('check-nested-stack')
nested = self.stack['A'].nested()
[_mock_check(res) for res in nested.resources.values()]
self.stack.check()
[self.assertTrue(res.handle_check.called)
for res in nested.resources.values()]
def test_check_not_supported(self):
stack = self._get_stack_to_check('check-not-supported')
del stack['B'].handle_check

View File

@@ -189,6 +189,14 @@ class StackResourceTest(common.HeatTestCase):
preview = self.parent_resource.preview()
self.assertIsInstance(preview, stack_resource.StackResource)
def test_nested_stack_abandon(self):
nest = mock.MagicMock()
self.parent_resource.nested = nest
nest.return_value.prepare_abandon.return_value = {'X': 'Y'}
ret = self.parent_resource.prepare_abandon()
nest.return_value.prepare_abandon.assert_called_once_with()
self.assertEqual({'X': 'Y'}, ret)
def test_implementation_signature(self):
self.parent_resource.child_template = mock.Mock(
return_value=self.simple_template)

View File

@@ -420,3 +420,56 @@ Outputs:
self.assert_resource_is_a_stack(stack_identifier, 'the_nested')
stack = self.client.stacks.get(stack_identifier)
self.assertEqual('goopie', self._stack_output(stack, 'value'))
class TemplateResourceCheckTest(test.HeatIntegrationTest):
"""Prove that we can do template resource check."""
main_template = '''
HeatTemplateFormatVersion: '2012-12-12'
Resources:
the_nested:
Type: the.yaml
Properties:
one: my_name
Outputs:
identifier:
Value: {Ref: the_nested}
value:
Value: {'Fn::GetAtt': [the_nested, the_str]}
'''
nested_templ = '''
HeatTemplateFormatVersion: '2012-12-12'
Parameters:
one:
Default: foo
Type: String
Resources:
RealRandom:
Type: OS::Heat::RandomString
Properties:
salt: {Ref: one}
Outputs:
the_str:
Value: {'Fn::GetAtt': [RealRandom, value]}
'''
def setUp(self):
super(TemplateResourceCheckTest, self).setUp()
self.client = self.orchestration_client
def test_check(self):
stack_name = self._stack_rand_name()
self.client.stacks.create(
stack_name=stack_name,
template=self.main_template,
files={'the.yaml': self.nested_templ},
disable_rollback=True,
)
stack = self.client.stacks.get(stack_name)
stack_identifier = '%s/%s' % (stack_name, stack.id)
self._wait_for_stack_status(stack_identifier, 'CREATE_COMPLETE')
self.client.actions.check(stack_id=stack_identifier)
self._wait_for_stack_status(stack_identifier, 'CHECK_COMPLETE')