blob: b4389ffd450afe47b152d3001240435109383936 [file] [log] [blame]
Angus Salkeldcecb8ed2015-08-05 13:19:45 +10001# Licensed under the Apache License, Version 2.0 (the "License"); you may
2# not use this file except in compliance with the License. You may obtain
3# a copy of the License at
4#
5# http://www.apache.org/licenses/LICENSE-2.0
6#
7# Unless required by applicable law or agreed to in writing, software
8# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
9# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
10# License for the specific language governing permissions and limitations
11# under the License.
12
13from heat_integrationtests.common import test
14from heatclient import exc
15import six
16
17
18class StackPreviewTest(test.HeatIntegrationTest):
19 template = '''
20heat_template_version: 2015-04-30
21parameters:
22 incomming:
23 type: string
24resources:
25 one:
26 type: OS::Heat::TestResource
27 properties:
28 value: fred
29 two:
30 type: OS::Heat::TestResource
31 properties:
32 value: {get_param: incomming}
33 depends_on: one
34outputs:
35 main_out:
36 value: {get_attr: [two, output]}
37 '''
38 env = '''
39parameters:
40 incomming: abc
41 '''
42
43 def setUp(self):
44 super(StackPreviewTest, self).setUp()
45 self.client = self.orchestration_client
46 self.project_id = self.identity_client.auth_ref.project_id
47
48 def _assert_resource(self, res, stack_name):
49 self.assertEqual(stack_name, res['stack_name'])
50 self.assertEqual('INIT', res['resource_action'])
51 self.assertEqual('COMPLETE', res['resource_status'])
52 for field in ('resource_status_reason', 'physical_resource_id',
53 'description'):
54 self.assertIn(field, res)
55 self.assertEqual('', res[field])
56 for field in ('creation_time', 'updated_time'):
57 self.assertIn(field, res)
58 self.assertIsNotNone(res[field])
59 self.assertIn('output', res['attributes'])
60
61 # resource_identity
62 self.assertEqual(stack_name,
63 res['resource_identity']['stack_name'])
64 self.assertEqual('None', res['resource_identity']['stack_id'])
65 self.assertEqual(self.project_id,
66 res['resource_identity']['tenant'])
67 self.assertEqual('/resources/%s' % res['resource_name'],
68 res['resource_identity']['path'])
69 # stack_identity
70 self.assertEqual(stack_name,
71 res['stack_identity']['stack_name'])
72 self.assertEqual('None', res['stack_identity']['stack_id'])
73 self.assertEqual(self.project_id,
74 res['stack_identity']['tenant'])
75 self.assertEqual('', res['stack_identity']['path'])
76
77 def _assert_results(self, result, stack_name):
78 # global stuff.
79 self.assertEqual(stack_name, result['stack_name'])
80 self.assertTrue(result['disable_rollback'])
81 self.assertEqual('None', result['id'])
82 self.assertIsNone(result['parent'])
83 self.assertEqual('No description', result['template_description'])
84
85 # parameters
86 self.assertEqual('None', result['parameters']['OS::stack_id'])
87 self.assertEqual(stack_name, result['parameters']['OS::stack_name'])
88 self.assertEqual('abc', result['parameters']['incomming'])
89
90 def test_basic_pass(self):
91 stack_name = self._stack_rand_name()
92 result = self.client.stacks.preview(
93 template=self.template,
94 stack_name=stack_name,
95 disable_rollback=True,
96 environment=self.env).to_dict()
97
98 self._assert_results(result, stack_name)
99 for res in result['resources']:
100 self._assert_resource(res, stack_name)
101 self.assertEqual('OS::Heat::TestResource',
102 res['resource_type'])
103
104 # common properties
105 self.assertEqual(False, res['properties']['fail'])
106 self.assertEqual(0, res['properties']['wait_secs'])
107 self.assertEqual(False, res['properties']['update_replace'])
108
109 if res['resource_name'] == 'one':
110 self.assertEqual('fred', res['properties']['value'])
111 self.assertEqual(['two'], res['required_by'])
112 if res['resource_name'] == 'two':
113 self.assertEqual('abc', res['properties']['value'])
114 self.assertEqual([], res['required_by'])
115
116 def test_basic_fail(self):
117 stack_name = self._stack_rand_name()
118
119 # break the template so it fails validation.
120 wont_work = self.template.replace('get_param: incomming',
121 'get_param: missing')
122 excp = self.assertRaises(exc.HTTPBadRequest,
123 self.client.stacks.preview,
124 template=wont_work,
125 stack_name=stack_name,
126 disable_rollback=True,
127 environment=self.env)
128
129 self.assertIn('Property error: : resources.two.properties.value: '
130 ': The Parameter (missing) was not provided.',
131 six.text_type(excp))
132
133 def test_nested_pass(self):
134 """Nested stacks need to recurse down the stacks."""
135 main_template = '''
136heat_template_version: 2015-04-30
137parameters:
138 incomming:
139 type: string
140resources:
141 main:
142 type: nested.yaml
143 properties:
144 value: {get_param: incomming}
145outputs:
146 main_out:
147 value: {get_attr: [main, output]}
148 '''
149 nested_template = '''
150heat_template_version: 2015-04-30
151parameters:
152 value:
153 type: string
154resources:
155 nested:
156 type: OS::Heat::TestResource
157 properties:
158 value: {get_param: value}
159outputs:
160 output:
161 value: {get_attr: [nested, output]}
162'''
163 stack_name = self._stack_rand_name()
164 result = self.client.stacks.preview(
165 disable_rollback=True,
166 stack_name=stack_name,
167 template=main_template,
168 files={'nested.yaml': nested_template},
169 environment=self.env).to_dict()
170
171 self._assert_results(result, stack_name)
172
173 # nested resources return a list of their resources.
174 res = result['resources'][0][0]
175 nested_stack_name = '%s-%s' % (stack_name,
176 res['parent_resource'])
177
178 self._assert_resource(res, nested_stack_name)
179 self.assertEqual('OS::Heat::TestResource',
180 res['resource_type'])
181
182 self.assertEqual(False, res['properties']['fail'])
183 self.assertEqual(0, res['properties']['wait_secs'])
184 self.assertEqual(False, res['properties']['update_replace'])
185
186 self.assertEqual('abc', res['properties']['value'])
187 self.assertEqual([], res['required_by'])