blob: 54f8a79f740dabf6ed7fce9d69c7a40aa8ceaee4 [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
Stefan Nica4750ea42017-06-20 14:45:14 +020013from heat_integrationtests.functional import functional_base
Angus Salkeldcecb8ed2015-08-05 13:19:45 +100014from heatclient import exc
15import six
16
17
Stefan Nica4750ea42017-06-20 14:45:14 +020018class StackPreviewTest(functional_base.FunctionalTestsBase):
Angus Salkeldcecb8ed2015-08-05 13:19:45 +100019 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
Rabi Mishra65493fb2016-01-29 22:23:21 +053046 self.project_id = self.identity_client.project_id
Angus Salkeldcecb8ed2015-08-05 13:19:45 +100047
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])
huangtianhuacce999a2015-08-03 16:13:25 +080056 # 'creation_time' and 'updated_time' are None when preview
Angus Salkeldcecb8ed2015-08-05 13:19:45 +100057 for field in ('creation_time', 'updated_time'):
58 self.assertIn(field, res)
huangtianhuacce999a2015-08-03 16:13:25 +080059 self.assertIsNone(res[field])
Angus Salkeldcecb8ed2015-08-05 13:19:45 +100060 self.assertIn('output', res['attributes'])
61
62 # resource_identity
63 self.assertEqual(stack_name,
64 res['resource_identity']['stack_name'])
65 self.assertEqual('None', res['resource_identity']['stack_id'])
66 self.assertEqual(self.project_id,
67 res['resource_identity']['tenant'])
68 self.assertEqual('/resources/%s' % res['resource_name'],
69 res['resource_identity']['path'])
70 # stack_identity
71 self.assertEqual(stack_name,
72 res['stack_identity']['stack_name'])
73 self.assertEqual('None', res['stack_identity']['stack_id'])
74 self.assertEqual(self.project_id,
75 res['stack_identity']['tenant'])
76 self.assertEqual('', res['stack_identity']['path'])
77
78 def _assert_results(self, result, stack_name):
79 # global stuff.
80 self.assertEqual(stack_name, result['stack_name'])
81 self.assertTrue(result['disable_rollback'])
82 self.assertEqual('None', result['id'])
83 self.assertIsNone(result['parent'])
84 self.assertEqual('No description', result['template_description'])
85
86 # parameters
87 self.assertEqual('None', result['parameters']['OS::stack_id'])
88 self.assertEqual(stack_name, result['parameters']['OS::stack_name'])
89 self.assertEqual('abc', result['parameters']['incomming'])
90
91 def test_basic_pass(self):
92 stack_name = self._stack_rand_name()
93 result = self.client.stacks.preview(
94 template=self.template,
95 stack_name=stack_name,
96 disable_rollback=True,
97 environment=self.env).to_dict()
98
99 self._assert_results(result, stack_name)
100 for res in result['resources']:
101 self._assert_resource(res, stack_name)
102 self.assertEqual('OS::Heat::TestResource',
103 res['resource_type'])
104
105 # common properties
Bertrand Lallau855d1c02015-10-26 16:37:37 +0100106 self.assertFalse(res['properties']['fail'])
Angus Salkeldcecb8ed2015-08-05 13:19:45 +1000107 self.assertEqual(0, res['properties']['wait_secs'])
Bertrand Lallau855d1c02015-10-26 16:37:37 +0100108 self.assertFalse(res['properties']['update_replace'])
Angus Salkeldcecb8ed2015-08-05 13:19:45 +1000109
110 if res['resource_name'] == 'one':
111 self.assertEqual('fred', res['properties']['value'])
112 self.assertEqual(['two'], res['required_by'])
113 if res['resource_name'] == 'two':
114 self.assertEqual('abc', res['properties']['value'])
115 self.assertEqual([], res['required_by'])
116
117 def test_basic_fail(self):
118 stack_name = self._stack_rand_name()
119
120 # break the template so it fails validation.
121 wont_work = self.template.replace('get_param: incomming',
122 'get_param: missing')
123 excp = self.assertRaises(exc.HTTPBadRequest,
124 self.client.stacks.preview,
125 template=wont_work,
126 stack_name=stack_name,
127 disable_rollback=True,
128 environment=self.env)
129
130 self.assertIn('Property error: : resources.two.properties.value: '
131 ': The Parameter (missing) was not provided.',
132 six.text_type(excp))
133
134 def test_nested_pass(self):
135 """Nested stacks need to recurse down the stacks."""
136 main_template = '''
137heat_template_version: 2015-04-30
138parameters:
139 incomming:
140 type: string
141resources:
142 main:
143 type: nested.yaml
144 properties:
145 value: {get_param: incomming}
146outputs:
147 main_out:
148 value: {get_attr: [main, output]}
149 '''
150 nested_template = '''
151heat_template_version: 2015-04-30
152parameters:
153 value:
154 type: string
155resources:
156 nested:
157 type: OS::Heat::TestResource
158 properties:
159 value: {get_param: value}
160outputs:
161 output:
162 value: {get_attr: [nested, output]}
163'''
164 stack_name = self._stack_rand_name()
165 result = self.client.stacks.preview(
166 disable_rollback=True,
167 stack_name=stack_name,
168 template=main_template,
169 files={'nested.yaml': nested_template},
170 environment=self.env).to_dict()
171
172 self._assert_results(result, stack_name)
173
174 # nested resources return a list of their resources.
175 res = result['resources'][0][0]
176 nested_stack_name = '%s-%s' % (stack_name,
177 res['parent_resource'])
178
179 self._assert_resource(res, nested_stack_name)
180 self.assertEqual('OS::Heat::TestResource',
181 res['resource_type'])
182
Bertrand Lallau855d1c02015-10-26 16:37:37 +0100183 self.assertFalse(res['properties']['fail'])
Angus Salkeldcecb8ed2015-08-05 13:19:45 +1000184 self.assertEqual(0, res['properties']['wait_secs'])
Bertrand Lallau855d1c02015-10-26 16:37:37 +0100185 self.assertFalse(res['properties']['update_replace'])
Angus Salkeldcecb8ed2015-08-05 13:19:45 +1000186
187 self.assertEqual('abc', res['properties']['value'])
188 self.assertEqual([], res['required_by'])
Oleksii Chuprykov793c23e2016-03-04 19:42:20 +0200189
190 def test_res_group_with_nested_template(self):
191 main_template = '''
192heat_template_version: 2015-04-30
193resources:
194 fixed_network:
195 type: "OS::Neutron::Net"
196 rg:
197 type: "OS::Heat::ResourceGroup"
198 properties:
199 count: 1
200 resource_def:
201 type: nested.yaml
202 properties:
203 fixed_network_id: {get_resource: fixed_network}
204 '''
205 nested_template = '''
206heat_template_version: 2015-04-30
207
208parameters:
209 fixed_network_id:
210 type: string
211resources:
212 port:
213 type: "OS::Neutron::Port"
214 properties:
215 network_id:
216 get_param: fixed_network_id
217
218'''
219 stack_name = self._stack_rand_name()
220 result = self.client.stacks.preview(
221 disable_rollback=True,
222 stack_name=stack_name,
223 template=main_template,
224 files={'nested.yaml': nested_template}).to_dict()
rabiffdd10f2017-03-29 09:29:56 +0530225
226 resource_names = []
227
228 def get_resource_names(resources):
229 for item in resources:
230 if isinstance(item, dict):
231 resource_names.append(item['resource_name'])
232 else:
233 get_resource_names(item)
234 get_resource_names(result['resources'])
Oleksii Chuprykov793c23e2016-03-04 19:42:20 +0200235 # ensure that fixed network and port here
rabiffdd10f2017-03-29 09:29:56 +0530236 self.assertIn('fixed_network', resource_names)
237 self.assertIn('port', resource_names)