blob: 9609664a449cc22021e29a195d8655d3c471f4ba [file] [log] [blame]
Angus Salkeld2bd63a42015-01-07 11:11:29 +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
13import json
Pavlo Shchelokovskyy60e0ecd2014-12-14 22:17:21 +020014
Angus Salkeld6a20e3b2015-08-05 13:30:26 +100015from heatclient import exc as heat_exceptions
16import six
Angus Salkeld2bd63a42015-01-07 11:11:29 +100017import yaml
18
19from heat_integrationtests.common import test
Rabi Mishra477efc92015-07-31 13:01:45 +053020from heat_integrationtests.functional import functional_base
Angus Salkeld2bd63a42015-01-07 11:11:29 +100021
22
Rabi Mishra477efc92015-07-31 13:01:45 +053023class TemplateResourceTest(functional_base.FunctionalTestsBase):
Angus Salkeld2bd63a42015-01-07 11:11:29 +100024 """Prove that we can use the registry in a nested provider."""
Angus Salkeld95403d82015-02-12 14:06:01 +100025
26 template = '''
27heat_template_version: 2013-05-23
28resources:
29 secret1:
30 type: OS::Heat::RandomString
31outputs:
32 secret-out:
33 value: { get_attr: [secret1, value] }
34'''
35 nested_templ = '''
36heat_template_version: 2013-05-23
37resources:
38 secret2:
39 type: OS::Heat::RandomString
40outputs:
41 value:
42 value: { get_attr: [secret2, value] }
43'''
44
45 env_templ = '''
46resource_registry:
47 "OS::Heat::RandomString": nested.yaml
48'''
49
Angus Salkeld2bd63a42015-01-07 11:11:29 +100050 def setUp(self):
51 super(TemplateResourceTest, self).setUp()
Angus Salkeld2bd63a42015-01-07 11:11:29 +100052
53 def test_nested_env(self):
54 main_templ = '''
55heat_template_version: 2013-05-23
56resources:
57 secret1:
58 type: My::NestedSecret
59outputs:
60 secret-out:
61 value: { get_attr: [secret1, value] }
62'''
63
64 nested_templ = '''
65heat_template_version: 2013-05-23
66resources:
67 secret2:
68 type: My::Secret
69outputs:
70 value:
71 value: { get_attr: [secret2, value] }
72'''
73
74 env_templ = '''
75resource_registry:
76 "My::Secret": "OS::Heat::RandomString"
77 "My::NestedSecret": nested.yaml
78'''
79
80 stack_identifier = self.stack_create(
81 template=main_templ,
82 files={'nested.yaml': nested_templ},
83 environment=env_templ)
Angus Salkeld2e61f9f2015-04-07 09:25:50 +100084 nested_ident = self.assert_resource_is_a_stack(stack_identifier,
85 'secret1')
86 # prove that resource.parent_resource is populated.
87 sec2 = self.client.resources.get(nested_ident, 'secret2')
88 self.assertEqual('secret1', sec2.parent_resource)
Angus Salkeld2bd63a42015-01-07 11:11:29 +100089
90 def test_no_infinite_recursion(self):
91 """Prove that we can override a python resource.
92
93 And use that resource within the template resource.
94 """
Angus Salkeld2bd63a42015-01-07 11:11:29 +100095 stack_identifier = self.stack_create(
Angus Salkeld95403d82015-02-12 14:06:01 +100096 template=self.template,
97 files={'nested.yaml': self.nested_templ},
98 environment=self.env_templ)
Angus Salkeld2bd63a42015-01-07 11:11:29 +100099 self.assert_resource_is_a_stack(stack_identifier, 'secret1')
100
Angus Salkeld95403d82015-02-12 14:06:01 +1000101 def test_nested_stack_delete_then_delete_parent_stack(self):
102 """Check the robustness of stack deletion.
103
104 This tests that if you manually delete a nested
105 stack, the parent stack is still deletable.
106 """
Sergey Kraynevbf67ce32015-04-17 10:54:20 -0400107 # disable cleanup so we can call _stack_delete() directly.
108 stack_identifier = self.stack_create(
Angus Salkeld95403d82015-02-12 14:06:01 +1000109 template=self.template,
110 files={'nested.yaml': self.nested_templ},
111 environment=self.env_templ,
Sergey Kraynevbf67ce32015-04-17 10:54:20 -0400112 enable_cleanup=False)
Angus Salkeld95403d82015-02-12 14:06:01 +1000113
114 nested_ident = self.assert_resource_is_a_stack(stack_identifier,
115 'secret1')
116
117 self._stack_delete(nested_ident)
118 self._stack_delete(stack_identifier)
119
Angus Salkeld19b9e1d2015-05-08 11:02:38 +1000120 def test_change_in_file_path(self):
121 stack_identifier = self.stack_create(
122 template=self.template,
123 files={'nested.yaml': self.nested_templ},
124 environment=self.env_templ)
125 stack = self.client.stacks.get(stack_identifier)
126 secret_out1 = self._stack_output(stack, 'secret-out')
127
128 nested_templ_2 = '''
129heat_template_version: 2013-05-23
130resources:
131 secret2:
132 type: OS::Heat::RandomString
133outputs:
134 value:
135 value: freddy
136'''
137 env_templ_2 = '''
138resource_registry:
139 "OS::Heat::RandomString": new/nested.yaml
140'''
141 self.update_stack(stack_identifier,
142 template=self.template,
143 files={'new/nested.yaml': nested_templ_2},
144 environment=env_templ_2)
145 stack = self.client.stacks.get(stack_identifier)
146 secret_out2 = self._stack_output(stack, 'secret-out')
147 self.assertNotEqual(secret_out1, secret_out2)
148 self.assertEqual('freddy', secret_out2)
149
Angus Salkeld2bd63a42015-01-07 11:11:29 +1000150
Rabi Mishra477efc92015-07-31 13:01:45 +0530151class NestedAttributesTest(functional_base.FunctionalTestsBase):
Angus Salkeld2bd63a42015-01-07 11:11:29 +1000152 """Prove that we can use the template resource references."""
153
154 main_templ = '''
155heat_template_version: 2014-10-16
156resources:
157 secret2:
158 type: My::NestedSecret
159outputs:
160 old_way:
161 value: { get_attr: [secret2, nested_str]}
162 test_attr1:
163 value: { get_attr: [secret2, resource.secret1, value]}
164 test_attr2:
165 value: { get_attr: [secret2, resource.secret1.value]}
166 test_ref:
167 value: { get_resource: secret2 }
168'''
169
170 env_templ = '''
171resource_registry:
172 "My::NestedSecret": nested.yaml
173'''
174
175 def setUp(self):
176 super(NestedAttributesTest, self).setUp()
Angus Salkeld2bd63a42015-01-07 11:11:29 +1000177
178 def test_stack_ref(self):
179 nested_templ = '''
180heat_template_version: 2014-10-16
181resources:
182 secret1:
183 type: OS::Heat::RandomString
Angus Salkelda89a0282015-07-24 15:47:38 +1000184outputs:
185 nested_str:
186 value: {get_attr: [secret1, value]}
Angus Salkeld2bd63a42015-01-07 11:11:29 +1000187'''
188 stack_identifier = self.stack_create(
189 template=self.main_templ,
190 files={'nested.yaml': nested_templ},
191 environment=self.env_templ)
192 self.assert_resource_is_a_stack(stack_identifier, 'secret2')
193 stack = self.client.stacks.get(stack_identifier)
194 test_ref = self._stack_output(stack, 'test_ref')
195 self.assertIn('arn:openstack:heat:', test_ref)
196
197 def test_transparent_ref(self):
198 """With the addition of OS::stack_id we can now use the nested resource
199 more transparently.
200 """
201 nested_templ = '''
202heat_template_version: 2014-10-16
203resources:
204 secret1:
205 type: OS::Heat::RandomString
206outputs:
207 OS::stack_id:
208 value: {get_resource: secret1}
209 nested_str:
210 value: {get_attr: [secret1, value]}
211'''
212 stack_identifier = self.stack_create(
213 template=self.main_templ,
214 files={'nested.yaml': nested_templ},
215 environment=self.env_templ)
216 self.assert_resource_is_a_stack(stack_identifier, 'secret2')
217 stack = self.client.stacks.get(stack_identifier)
218 test_ref = self._stack_output(stack, 'test_ref')
219 test_attr = self._stack_output(stack, 'old_way')
220
221 self.assertNotIn('arn:openstack:heat', test_ref)
222 self.assertEqual(test_attr, test_ref)
223
224 def test_nested_attributes(self):
225 nested_templ = '''
226heat_template_version: 2014-10-16
227resources:
228 secret1:
229 type: OS::Heat::RandomString
230outputs:
231 nested_str:
232 value: {get_attr: [secret1, value]}
233'''
234 stack_identifier = self.stack_create(
235 template=self.main_templ,
236 files={'nested.yaml': nested_templ},
237 environment=self.env_templ)
238 self.assert_resource_is_a_stack(stack_identifier, 'secret2')
239 stack = self.client.stacks.get(stack_identifier)
240 old_way = self._stack_output(stack, 'old_way')
241 test_attr1 = self._stack_output(stack, 'test_attr1')
242 test_attr2 = self._stack_output(stack, 'test_attr2')
243
244 self.assertEqual(old_way, test_attr1)
245 self.assertEqual(old_way, test_attr2)
246
247
Angus Salkelddd5a6072015-09-02 09:10:04 +1000248class TemplateResourceFacadeTest(functional_base.FunctionalTestsBase):
249 """Prove that we can use ResourceFacade in a HOT template."""
250
251 main_template = '''
252heat_template_version: 2013-05-23
253resources:
254 the_nested:
255 type: the.yaml
256 metadata:
257 foo: bar
258outputs:
259 value:
260 value: {get_attr: [the_nested, output]}
261'''
262
263 nested_templ = '''
264heat_template_version: 2013-05-23
265resources:
266 test:
267 type: OS::Heat::TestResource
268 properties:
269 value: {"Fn::Select": [foo, {resource_facade: metadata}]}
270outputs:
271 output:
272 value: {get_attr: [test, output]}
273 '''
274
275 def test_metadata(self):
276 stack_identifier = self.stack_create(
277 template=self.main_template,
278 files={'the.yaml': self.nested_templ})
279 stack = self.client.stacks.get(stack_identifier)
280 value = self._stack_output(stack, 'value')
281 self.assertEqual('bar', value)
282
283
Rabi Mishra477efc92015-07-31 13:01:45 +0530284class TemplateResourceUpdateTest(functional_base.FunctionalTestsBase):
Angus Salkeld2bd63a42015-01-07 11:11:29 +1000285 """Prove that we can do template resource updates."""
286
287 main_template = '''
288HeatTemplateFormatVersion: '2012-12-12'
289Resources:
290 the_nested:
291 Type: the.yaml
292 Properties:
293 one: my_name
Rabi Mishrab1293ae2015-05-13 16:39:04 +0530294 two: your_name
295Outputs:
296 identifier:
297 Value: {Ref: the_nested}
298 value:
299 Value: {'Fn::GetAtt': [the_nested, the_str]}
300'''
301
302 main_template_change_prop = '''
303HeatTemplateFormatVersion: '2012-12-12'
304Resources:
305 the_nested:
306 Type: the.yaml
307 Properties:
308 one: updated_name
309 two: your_name
Angus Salkeld2bd63a42015-01-07 11:11:29 +1000310
311Outputs:
312 identifier:
313 Value: {Ref: the_nested}
314 value:
315 Value: {'Fn::GetAtt': [the_nested, the_str]}
316'''
317
Rabi Mishrab1293ae2015-05-13 16:39:04 +0530318 main_template_add_prop = '''
Angus Salkeld2bd63a42015-01-07 11:11:29 +1000319HeatTemplateFormatVersion: '2012-12-12'
320Resources:
321 the_nested:
322 Type: the.yaml
323 Properties:
Rabi Mishrab1293ae2015-05-13 16:39:04 +0530324 one: my_name
325 two: your_name
326 three: third_name
327
328Outputs:
329 identifier:
330 Value: {Ref: the_nested}
331 value:
332 Value: {'Fn::GetAtt': [the_nested, the_str]}
333'''
334
335 main_template_remove_prop = '''
336HeatTemplateFormatVersion: '2012-12-12'
337Resources:
338 the_nested:
339 Type: the.yaml
340 Properties:
341 one: my_name
Angus Salkeld2bd63a42015-01-07 11:11:29 +1000342
343Outputs:
344 identifier:
345 Value: {Ref: the_nested}
346 value:
347 Value: {'Fn::GetAtt': [the_nested, the_str]}
348'''
349
350 initial_tmpl = '''
351HeatTemplateFormatVersion: '2012-12-12'
352Parameters:
353 one:
354 Default: foo
355 Type: String
Rabi Mishrab1293ae2015-05-13 16:39:04 +0530356 two:
357 Default: bar
358 Type: String
359
Angus Salkeld2bd63a42015-01-07 11:11:29 +1000360Resources:
361 NestedResource:
362 Type: OS::Heat::RandomString
363 Properties:
364 salt: {Ref: one}
365Outputs:
366 the_str:
367 Value: {'Fn::GetAtt': [NestedResource, value]}
368'''
Rabi Mishrab1293ae2015-05-13 16:39:04 +0530369
Angus Salkeld2bd63a42015-01-07 11:11:29 +1000370 prop_change_tmpl = '''
371HeatTemplateFormatVersion: '2012-12-12'
372Parameters:
373 one:
374 Default: yikes
375 Type: String
376 two:
377 Default: foo
378 Type: String
379Resources:
380 NestedResource:
381 Type: OS::Heat::RandomString
382 Properties:
Rabi Mishrab1293ae2015-05-13 16:39:04 +0530383 salt: {Ref: two}
384Outputs:
385 the_str:
386 Value: {'Fn::GetAtt': [NestedResource, value]}
387'''
388
389 prop_add_tmpl = '''
390HeatTemplateFormatVersion: '2012-12-12'
391Parameters:
392 one:
393 Default: yikes
394 Type: String
395 two:
396 Default: foo
397 Type: String
398 three:
399 Default: bar
400 Type: String
401
402Resources:
403 NestedResource:
404 Type: OS::Heat::RandomString
405 Properties:
406 salt: {Ref: three}
407Outputs:
408 the_str:
409 Value: {'Fn::GetAtt': [NestedResource, value]}
410'''
411
412 prop_remove_tmpl = '''
413HeatTemplateFormatVersion: '2012-12-12'
414Parameters:
415 one:
416 Default: yikes
417 Type: String
418
419Resources:
420 NestedResource:
421 Type: OS::Heat::RandomString
422 Properties:
Angus Salkeld2bd63a42015-01-07 11:11:29 +1000423 salt: {Ref: one}
424Outputs:
425 the_str:
426 Value: {'Fn::GetAtt': [NestedResource, value]}
427'''
Rabi Mishrab1293ae2015-05-13 16:39:04 +0530428
Angus Salkeld2bd63a42015-01-07 11:11:29 +1000429 attr_change_tmpl = '''
430HeatTemplateFormatVersion: '2012-12-12'
431Parameters:
432 one:
433 Default: foo
434 Type: String
Rabi Mishrab1293ae2015-05-13 16:39:04 +0530435 two:
436 Default: bar
437 Type: String
438
Angus Salkeld2bd63a42015-01-07 11:11:29 +1000439Resources:
440 NestedResource:
441 Type: OS::Heat::RandomString
442 Properties:
443 salt: {Ref: one}
444Outputs:
445 the_str:
446 Value: {'Fn::GetAtt': [NestedResource, value]}
447 something_else:
448 Value: just_a_string
449'''
Rabi Mishrab1293ae2015-05-13 16:39:04 +0530450
Angus Salkeld2bd63a42015-01-07 11:11:29 +1000451 content_change_tmpl = '''
452HeatTemplateFormatVersion: '2012-12-12'
453Parameters:
454 one:
455 Default: foo
456 Type: String
Rabi Mishrab1293ae2015-05-13 16:39:04 +0530457 two:
458 Default: bar
459 Type: String
460
Angus Salkeld2bd63a42015-01-07 11:11:29 +1000461Resources:
462 NestedResource:
463 Type: OS::Heat::RandomString
464 Properties:
465 salt: yum
466Outputs:
467 the_str:
468 Value: {'Fn::GetAtt': [NestedResource, value]}
469'''
470
471 EXPECTED = (UPDATE, NOCHANGE) = ('update', 'nochange')
472 scenarios = [
473 ('no_changes', dict(template=main_template,
474 provider=initial_tmpl,
475 expect=NOCHANGE)),
Rabi Mishrab1293ae2015-05-13 16:39:04 +0530476 ('main_tmpl_change', dict(template=main_template_change_prop,
Angus Salkeld2bd63a42015-01-07 11:11:29 +1000477 provider=initial_tmpl,
478 expect=UPDATE)),
479 ('provider_change', dict(template=main_template,
480 provider=content_change_tmpl,
481 expect=UPDATE)),
482 ('provider_props_change', dict(template=main_template,
483 provider=prop_change_tmpl,
Rabi Mishrab1293ae2015-05-13 16:39:04 +0530484 expect=UPDATE)),
485 ('provider_props_add', dict(template=main_template_add_prop,
486 provider=prop_add_tmpl,
487 expect=UPDATE)),
488 ('provider_props_remove', dict(template=main_template_remove_prop,
489 provider=prop_remove_tmpl,
Angus Salkeld2bd63a42015-01-07 11:11:29 +1000490 expect=NOCHANGE)),
491 ('provider_attr_change', dict(template=main_template,
492 provider=attr_change_tmpl,
493 expect=NOCHANGE)),
494 ]
495
496 def setUp(self):
497 super(TemplateResourceUpdateTest, self).setUp()
Angus Salkeld2bd63a42015-01-07 11:11:29 +1000498
499 def test_template_resource_update_template_schema(self):
500 stack_identifier = self.stack_create(
501 template=self.main_template,
502 files={'the.yaml': self.initial_tmpl})
503 stack = self.client.stacks.get(stack_identifier)
504 initial_id = self._stack_output(stack, 'identifier')
505 initial_val = self._stack_output(stack, 'value')
506
507 self.update_stack(stack_identifier,
508 self.template,
509 files={'the.yaml': self.provider})
510 stack = self.client.stacks.get(stack_identifier)
511 self.assertEqual(initial_id,
512 self._stack_output(stack, 'identifier'))
513 if self.expect == self.NOCHANGE:
514 self.assertEqual(initial_val,
515 self._stack_output(stack, 'value'))
516 else:
517 self.assertNotEqual(initial_val,
518 self._stack_output(stack, 'value'))
519
520
Rabi Mishra477efc92015-07-31 13:01:45 +0530521class TemplateResourceUpdateFailedTest(functional_base.FunctionalTestsBase):
Angus Salkeld5a3e1dd2015-02-03 15:31:47 +1000522 """Prove that we can do updates on a nested stack to fix a stack."""
523 main_template = '''
524HeatTemplateFormatVersion: '2012-12-12'
525Resources:
526 keypair:
527 Type: OS::Nova::KeyPair
528 Properties:
529 name: replace-this
530 save_private_key: false
531 server:
532 Type: server_fail.yaml
533 DependsOn: keypair
534'''
535 nested_templ = '''
536HeatTemplateFormatVersion: '2012-12-12'
537Resources:
538 RealRandom:
539 Type: OS::Heat::RandomString
540'''
541
542 def setUp(self):
543 super(TemplateResourceUpdateFailedTest, self).setUp()
Sergey Krayneva265c132015-02-13 03:51:03 -0500544 self.assign_keypair()
Angus Salkeld5a3e1dd2015-02-03 15:31:47 +1000545
546 def test_update_on_failed_create(self):
Vikas Jainac6b02f2015-02-11 11:31:46 -0800547 # create a stack with "server" dependent on "keypair", but
Angus Salkeld5a3e1dd2015-02-03 15:31:47 +1000548 # keypair fails, so "server" is not created properly.
549 # We then fix the template and it should succeed.
550 broken_templ = self.main_template.replace('replace-this',
551 self.keypair_name)
552 stack_identifier = self.stack_create(
553 template=broken_templ,
554 files={'server_fail.yaml': self.nested_templ},
555 expected_status='CREATE_FAILED')
556
557 fixed_templ = self.main_template.replace('replace-this',
558 test.rand_name())
559 self.update_stack(stack_identifier,
560 fixed_templ,
561 files={'server_fail.yaml': self.nested_templ})
562
563
Rabi Mishra477efc92015-07-31 13:01:45 +0530564class TemplateResourceAdoptTest(functional_base.FunctionalTestsBase):
Angus Salkeld2bd63a42015-01-07 11:11:29 +1000565 """Prove that we can do template resource adopt/abandon."""
566
567 main_template = '''
568HeatTemplateFormatVersion: '2012-12-12'
569Resources:
570 the_nested:
571 Type: the.yaml
572 Properties:
573 one: my_name
574Outputs:
575 identifier:
576 Value: {Ref: the_nested}
577 value:
578 Value: {'Fn::GetAtt': [the_nested, the_str]}
579'''
580
581 nested_templ = '''
582HeatTemplateFormatVersion: '2012-12-12'
583Parameters:
584 one:
585 Default: foo
586 Type: String
587Resources:
588 RealRandom:
589 Type: OS::Heat::RandomString
590 Properties:
591 salt: {Ref: one}
592Outputs:
593 the_str:
594 Value: {'Fn::GetAtt': [RealRandom, value]}
595'''
596
597 def setUp(self):
598 super(TemplateResourceAdoptTest, self).setUp()
Angus Salkeld2bd63a42015-01-07 11:11:29 +1000599
600 def _yaml_to_json(self, yaml_templ):
601 return yaml.load(yaml_templ)
602
603 def test_abandon(self):
Sergey Kraynevbf67ce32015-04-17 10:54:20 -0400604 stack_identifier = self.stack_create(
Angus Salkeld2bd63a42015-01-07 11:11:29 +1000605 template=self.main_template,
606 files={'the.yaml': self.nested_templ},
Sergey Kraynevbf67ce32015-04-17 10:54:20 -0400607 enable_cleanup=False
Angus Salkeld2bd63a42015-01-07 11:11:29 +1000608 )
Angus Salkeld2bd63a42015-01-07 11:11:29 +1000609
Sirushti Murugesan04ee8022015-02-02 23:00:23 +0530610 info = self.stack_abandon(stack_id=stack_identifier)
Angus Salkeld2bd63a42015-01-07 11:11:29 +1000611 self.assertEqual(self._yaml_to_json(self.main_template),
612 info['template'])
613 self.assertEqual(self._yaml_to_json(self.nested_templ),
614 info['resources']['the_nested']['template'])
615
616 def test_adopt(self):
617 data = {
618 'resources': {
619 'the_nested': {
620 "type": "the.yaml",
621 "resources": {
622 "RealRandom": {
623 "type": "OS::Heat::RandomString",
624 'resource_data': {'value': 'goopie'},
625 'resource_id': 'froggy'
626 }
627 }
628 }
629 },
630 "environment": {"parameters": {}},
631 "template": yaml.load(self.main_template)
632 }
633
634 stack_identifier = self.stack_adopt(
635 adopt_data=json.dumps(data),
636 files={'the.yaml': self.nested_templ})
637
638 self.assert_resource_is_a_stack(stack_identifier, 'the_nested')
639 stack = self.client.stacks.get(stack_identifier)
640 self.assertEqual('goopie', self._stack_output(stack, 'value'))
Angus Salkeld87601722015-01-05 14:57:27 +1000641
642
Rabi Mishra477efc92015-07-31 13:01:45 +0530643class TemplateResourceCheckTest(functional_base.FunctionalTestsBase):
Angus Salkeld87601722015-01-05 14:57:27 +1000644 """Prove that we can do template resource check."""
645
646 main_template = '''
647HeatTemplateFormatVersion: '2012-12-12'
648Resources:
649 the_nested:
650 Type: the.yaml
651 Properties:
652 one: my_name
653Outputs:
654 identifier:
655 Value: {Ref: the_nested}
656 value:
657 Value: {'Fn::GetAtt': [the_nested, the_str]}
658'''
659
660 nested_templ = '''
661HeatTemplateFormatVersion: '2012-12-12'
662Parameters:
663 one:
664 Default: foo
665 Type: String
666Resources:
667 RealRandom:
668 Type: OS::Heat::RandomString
669 Properties:
670 salt: {Ref: one}
671Outputs:
672 the_str:
673 Value: {'Fn::GetAtt': [RealRandom, value]}
674'''
675
676 def setUp(self):
677 super(TemplateResourceCheckTest, self).setUp()
Angus Salkeld87601722015-01-05 14:57:27 +1000678
679 def test_check(self):
Sergey Kraynevbf67ce32015-04-17 10:54:20 -0400680 stack_identifier = self.stack_create(
Angus Salkeld87601722015-01-05 14:57:27 +1000681 template=self.main_template,
Sergey Kraynevbf67ce32015-04-17 10:54:20 -0400682 files={'the.yaml': self.nested_templ}
Angus Salkeld87601722015-01-05 14:57:27 +1000683 )
Angus Salkeld87601722015-01-05 14:57:27 +1000684
685 self.client.actions.check(stack_id=stack_identifier)
686 self._wait_for_stack_status(stack_identifier, 'CHECK_COMPLETE')
Angus Salkeld793b0fc2015-06-24 08:52:08 +1000687
688
Rabi Mishra477efc92015-07-31 13:01:45 +0530689class TemplateResourceErrorMessageTest(functional_base.FunctionalTestsBase):
Angus Salkeld793b0fc2015-06-24 08:52:08 +1000690 """Prove that nested stack errors don't suck."""
691 template = '''
692HeatTemplateFormatVersion: '2012-12-12'
693Resources:
694 victim:
695 Type: fail.yaml
696'''
697 nested_templ = '''
698HeatTemplateFormatVersion: '2012-12-12'
699Resources:
700 oops:
701 Type: OS::Heat::TestResource
702 Properties:
703 fail: true
704 wait_secs: 2
705'''
706
707 def setUp(self):
708 super(TemplateResourceErrorMessageTest, self).setUp()
Angus Salkeld793b0fc2015-06-24 08:52:08 +1000709
710 def test_fail(self):
711 stack_identifier = self.stack_create(
712 template=self.template,
713 files={'fail.yaml': self.nested_templ},
714 expected_status='CREATE_FAILED')
715 stack = self.client.stacks.get(stack_identifier)
716
717 exp_path = 'resources.victim.resources.oops'
718 exp_msg = 'Test Resource failed oops'
719 exp = 'Resource CREATE failed: ValueError: %s: %s' % (exp_path,
720 exp_msg)
721 self.assertEqual(exp, stack.stack_status_reason)
kairat_kushaev61a99e12015-07-31 16:22:45 +0300722
723
Rabi Mishra477efc92015-07-31 13:01:45 +0530724class TemplateResourceSuspendResumeTest(functional_base.FunctionalTestsBase):
kairat_kushaev61a99e12015-07-31 16:22:45 +0300725 """Prove that we can do template resource suspend/resume."""
726
727 main_template = '''
728heat_template_version: 2014-10-16
729parameters:
730resources:
731 the_nested:
732 type: the.yaml
733'''
734
735 nested_templ = '''
736heat_template_version: 2014-10-16
737resources:
738 test_random_string:
739 type: OS::Heat::RandomString
740'''
741
742 def setUp(self):
743 super(TemplateResourceSuspendResumeTest, self).setUp()
kairat_kushaev61a99e12015-07-31 16:22:45 +0300744
745 def test_suspend_resume(self):
746 """Basic test for template resource suspend resume"""
747 stack_identifier = self.stack_create(
748 template=self.main_template,
749 files={'the.yaml': self.nested_templ}
750 )
751
752 self.stack_suspend(stack_identifier=stack_identifier)
753 self.stack_resume(stack_identifier=stack_identifier)
Angus Salkeld6a20e3b2015-08-05 13:30:26 +1000754
755
756class ValidateFacadeTest(test.HeatIntegrationTest):
757 """Prove that nested stack errors don't suck."""
758 template = '''
759heat_template_version: 2015-10-15
760resources:
761 thisone:
762 type: OS::Thingy
763 properties:
764 one: pre
765 two: post
766outputs:
767 one:
768 value: {get_attr: [thisone, here-it-is]}
769'''
770 templ_facade = '''
771heat_template_version: 2015-04-30
772parameters:
773 one:
774 type: string
775 two:
776 type: string
777outputs:
778 here-it-is:
779 value: noop
780'''
781 env = '''
782resource_registry:
783 OS::Thingy: facade.yaml
784 resources:
785 thisone:
786 OS::Thingy: concrete.yaml
787'''
788
789 def setUp(self):
790 super(ValidateFacadeTest, self).setUp()
791 self.client = self.orchestration_client
792
793 def test_missing_param(self):
794 templ_missing_parameter = '''
795heat_template_version: 2015-04-30
796parameters:
797 one:
798 type: string
799resources:
800 str:
801 type: OS::Heat::RandomString
802outputs:
803 here-it-is:
804 value:
805 not-important
806'''
807 try:
808 self.stack_create(
809 template=self.template,
810 environment=self.env,
811 files={'facade.yaml': self.templ_facade,
812 'concrete.yaml': templ_missing_parameter},
813 expected_status='CREATE_FAILED')
814 except heat_exceptions.HTTPBadRequest as exc:
815 exp = ('ERROR: Required property two for facade '
816 'OS::Thingy missing in provider')
817 self.assertEqual(exp, six.text_type(exc))
818
819 def test_missing_output(self):
820 templ_missing_output = '''
821heat_template_version: 2015-04-30
822parameters:
823 one:
824 type: string
825 two:
826 type: string
827resources:
828 str:
829 type: OS::Heat::RandomString
830'''
831 try:
832 self.stack_create(
833 template=self.template,
834 environment=self.env,
835 files={'facade.yaml': self.templ_facade,
836 'concrete.yaml': templ_missing_output},
837 expected_status='CREATE_FAILED')
838 except heat_exceptions.HTTPBadRequest as exc:
839 exp = ('ERROR: Attribute here-it-is for facade '
840 'OS::Thingy missing in provider')
841 self.assertEqual(exp, six.text_type(exc))