blob: 1ec05d9934f976e5d70231914e1bc6276938b0ec [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
Rabi Mishra477efc92015-07-31 13:01:45 +0530248class TemplateResourceUpdateTest(functional_base.FunctionalTestsBase):
Angus Salkeld2bd63a42015-01-07 11:11:29 +1000249 """Prove that we can do template resource updates."""
250
251 main_template = '''
252HeatTemplateFormatVersion: '2012-12-12'
253Resources:
254 the_nested:
255 Type: the.yaml
256 Properties:
257 one: my_name
Rabi Mishrab1293ae2015-05-13 16:39:04 +0530258 two: your_name
259Outputs:
260 identifier:
261 Value: {Ref: the_nested}
262 value:
263 Value: {'Fn::GetAtt': [the_nested, the_str]}
264'''
265
266 main_template_change_prop = '''
267HeatTemplateFormatVersion: '2012-12-12'
268Resources:
269 the_nested:
270 Type: the.yaml
271 Properties:
272 one: updated_name
273 two: your_name
Angus Salkeld2bd63a42015-01-07 11:11:29 +1000274
275Outputs:
276 identifier:
277 Value: {Ref: the_nested}
278 value:
279 Value: {'Fn::GetAtt': [the_nested, the_str]}
280'''
281
Rabi Mishrab1293ae2015-05-13 16:39:04 +0530282 main_template_add_prop = '''
Angus Salkeld2bd63a42015-01-07 11:11:29 +1000283HeatTemplateFormatVersion: '2012-12-12'
284Resources:
285 the_nested:
286 Type: the.yaml
287 Properties:
Rabi Mishrab1293ae2015-05-13 16:39:04 +0530288 one: my_name
289 two: your_name
290 three: third_name
291
292Outputs:
293 identifier:
294 Value: {Ref: the_nested}
295 value:
296 Value: {'Fn::GetAtt': [the_nested, the_str]}
297'''
298
299 main_template_remove_prop = '''
300HeatTemplateFormatVersion: '2012-12-12'
301Resources:
302 the_nested:
303 Type: the.yaml
304 Properties:
305 one: my_name
Angus Salkeld2bd63a42015-01-07 11:11:29 +1000306
307Outputs:
308 identifier:
309 Value: {Ref: the_nested}
310 value:
311 Value: {'Fn::GetAtt': [the_nested, the_str]}
312'''
313
314 initial_tmpl = '''
315HeatTemplateFormatVersion: '2012-12-12'
316Parameters:
317 one:
318 Default: foo
319 Type: String
Rabi Mishrab1293ae2015-05-13 16:39:04 +0530320 two:
321 Default: bar
322 Type: String
323
Angus Salkeld2bd63a42015-01-07 11:11:29 +1000324Resources:
325 NestedResource:
326 Type: OS::Heat::RandomString
327 Properties:
328 salt: {Ref: one}
329Outputs:
330 the_str:
331 Value: {'Fn::GetAtt': [NestedResource, value]}
332'''
Rabi Mishrab1293ae2015-05-13 16:39:04 +0530333
Angus Salkeld2bd63a42015-01-07 11:11:29 +1000334 prop_change_tmpl = '''
335HeatTemplateFormatVersion: '2012-12-12'
336Parameters:
337 one:
338 Default: yikes
339 Type: String
340 two:
341 Default: foo
342 Type: String
343Resources:
344 NestedResource:
345 Type: OS::Heat::RandomString
346 Properties:
Rabi Mishrab1293ae2015-05-13 16:39:04 +0530347 salt: {Ref: two}
348Outputs:
349 the_str:
350 Value: {'Fn::GetAtt': [NestedResource, value]}
351'''
352
353 prop_add_tmpl = '''
354HeatTemplateFormatVersion: '2012-12-12'
355Parameters:
356 one:
357 Default: yikes
358 Type: String
359 two:
360 Default: foo
361 Type: String
362 three:
363 Default: bar
364 Type: String
365
366Resources:
367 NestedResource:
368 Type: OS::Heat::RandomString
369 Properties:
370 salt: {Ref: three}
371Outputs:
372 the_str:
373 Value: {'Fn::GetAtt': [NestedResource, value]}
374'''
375
376 prop_remove_tmpl = '''
377HeatTemplateFormatVersion: '2012-12-12'
378Parameters:
379 one:
380 Default: yikes
381 Type: String
382
383Resources:
384 NestedResource:
385 Type: OS::Heat::RandomString
386 Properties:
Angus Salkeld2bd63a42015-01-07 11:11:29 +1000387 salt: {Ref: one}
388Outputs:
389 the_str:
390 Value: {'Fn::GetAtt': [NestedResource, value]}
391'''
Rabi Mishrab1293ae2015-05-13 16:39:04 +0530392
Angus Salkeld2bd63a42015-01-07 11:11:29 +1000393 attr_change_tmpl = '''
394HeatTemplateFormatVersion: '2012-12-12'
395Parameters:
396 one:
397 Default: foo
398 Type: String
Rabi Mishrab1293ae2015-05-13 16:39:04 +0530399 two:
400 Default: bar
401 Type: String
402
Angus Salkeld2bd63a42015-01-07 11:11:29 +1000403Resources:
404 NestedResource:
405 Type: OS::Heat::RandomString
406 Properties:
407 salt: {Ref: one}
408Outputs:
409 the_str:
410 Value: {'Fn::GetAtt': [NestedResource, value]}
411 something_else:
412 Value: just_a_string
413'''
Rabi Mishrab1293ae2015-05-13 16:39:04 +0530414
Angus Salkeld2bd63a42015-01-07 11:11:29 +1000415 content_change_tmpl = '''
416HeatTemplateFormatVersion: '2012-12-12'
417Parameters:
418 one:
419 Default: foo
420 Type: String
Rabi Mishrab1293ae2015-05-13 16:39:04 +0530421 two:
422 Default: bar
423 Type: String
424
Angus Salkeld2bd63a42015-01-07 11:11:29 +1000425Resources:
426 NestedResource:
427 Type: OS::Heat::RandomString
428 Properties:
429 salt: yum
430Outputs:
431 the_str:
432 Value: {'Fn::GetAtt': [NestedResource, value]}
433'''
434
435 EXPECTED = (UPDATE, NOCHANGE) = ('update', 'nochange')
436 scenarios = [
437 ('no_changes', dict(template=main_template,
438 provider=initial_tmpl,
439 expect=NOCHANGE)),
Rabi Mishrab1293ae2015-05-13 16:39:04 +0530440 ('main_tmpl_change', dict(template=main_template_change_prop,
Angus Salkeld2bd63a42015-01-07 11:11:29 +1000441 provider=initial_tmpl,
442 expect=UPDATE)),
443 ('provider_change', dict(template=main_template,
444 provider=content_change_tmpl,
445 expect=UPDATE)),
446 ('provider_props_change', dict(template=main_template,
447 provider=prop_change_tmpl,
Rabi Mishrab1293ae2015-05-13 16:39:04 +0530448 expect=UPDATE)),
449 ('provider_props_add', dict(template=main_template_add_prop,
450 provider=prop_add_tmpl,
451 expect=UPDATE)),
452 ('provider_props_remove', dict(template=main_template_remove_prop,
453 provider=prop_remove_tmpl,
Angus Salkeld2bd63a42015-01-07 11:11:29 +1000454 expect=NOCHANGE)),
455 ('provider_attr_change', dict(template=main_template,
456 provider=attr_change_tmpl,
457 expect=NOCHANGE)),
458 ]
459
460 def setUp(self):
461 super(TemplateResourceUpdateTest, self).setUp()
Angus Salkeld2bd63a42015-01-07 11:11:29 +1000462
463 def test_template_resource_update_template_schema(self):
464 stack_identifier = self.stack_create(
465 template=self.main_template,
466 files={'the.yaml': self.initial_tmpl})
467 stack = self.client.stacks.get(stack_identifier)
468 initial_id = self._stack_output(stack, 'identifier')
469 initial_val = self._stack_output(stack, 'value')
470
471 self.update_stack(stack_identifier,
472 self.template,
473 files={'the.yaml': self.provider})
474 stack = self.client.stacks.get(stack_identifier)
475 self.assertEqual(initial_id,
476 self._stack_output(stack, 'identifier'))
477 if self.expect == self.NOCHANGE:
478 self.assertEqual(initial_val,
479 self._stack_output(stack, 'value'))
480 else:
481 self.assertNotEqual(initial_val,
482 self._stack_output(stack, 'value'))
483
484
Rabi Mishra477efc92015-07-31 13:01:45 +0530485class TemplateResourceUpdateFailedTest(functional_base.FunctionalTestsBase):
Angus Salkeld5a3e1dd2015-02-03 15:31:47 +1000486 """Prove that we can do updates on a nested stack to fix a stack."""
487 main_template = '''
488HeatTemplateFormatVersion: '2012-12-12'
489Resources:
490 keypair:
491 Type: OS::Nova::KeyPair
492 Properties:
493 name: replace-this
494 save_private_key: false
495 server:
496 Type: server_fail.yaml
497 DependsOn: keypair
498'''
499 nested_templ = '''
500HeatTemplateFormatVersion: '2012-12-12'
501Resources:
502 RealRandom:
503 Type: OS::Heat::RandomString
504'''
505
506 def setUp(self):
507 super(TemplateResourceUpdateFailedTest, self).setUp()
Sergey Krayneva265c132015-02-13 03:51:03 -0500508 self.assign_keypair()
Angus Salkeld5a3e1dd2015-02-03 15:31:47 +1000509
510 def test_update_on_failed_create(self):
Vikas Jainac6b02f2015-02-11 11:31:46 -0800511 # create a stack with "server" dependent on "keypair", but
Angus Salkeld5a3e1dd2015-02-03 15:31:47 +1000512 # keypair fails, so "server" is not created properly.
513 # We then fix the template and it should succeed.
514 broken_templ = self.main_template.replace('replace-this',
515 self.keypair_name)
516 stack_identifier = self.stack_create(
517 template=broken_templ,
518 files={'server_fail.yaml': self.nested_templ},
519 expected_status='CREATE_FAILED')
520
521 fixed_templ = self.main_template.replace('replace-this',
522 test.rand_name())
523 self.update_stack(stack_identifier,
524 fixed_templ,
525 files={'server_fail.yaml': self.nested_templ})
526
527
Rabi Mishra477efc92015-07-31 13:01:45 +0530528class TemplateResourceAdoptTest(functional_base.FunctionalTestsBase):
Angus Salkeld2bd63a42015-01-07 11:11:29 +1000529 """Prove that we can do template resource adopt/abandon."""
530
531 main_template = '''
532HeatTemplateFormatVersion: '2012-12-12'
533Resources:
534 the_nested:
535 Type: the.yaml
536 Properties:
537 one: my_name
538Outputs:
539 identifier:
540 Value: {Ref: the_nested}
541 value:
542 Value: {'Fn::GetAtt': [the_nested, the_str]}
543'''
544
545 nested_templ = '''
546HeatTemplateFormatVersion: '2012-12-12'
547Parameters:
548 one:
549 Default: foo
550 Type: String
551Resources:
552 RealRandom:
553 Type: OS::Heat::RandomString
554 Properties:
555 salt: {Ref: one}
556Outputs:
557 the_str:
558 Value: {'Fn::GetAtt': [RealRandom, value]}
559'''
560
561 def setUp(self):
562 super(TemplateResourceAdoptTest, self).setUp()
Angus Salkeld2bd63a42015-01-07 11:11:29 +1000563
564 def _yaml_to_json(self, yaml_templ):
565 return yaml.load(yaml_templ)
566
567 def test_abandon(self):
Sergey Kraynevbf67ce32015-04-17 10:54:20 -0400568 stack_identifier = self.stack_create(
Angus Salkeld2bd63a42015-01-07 11:11:29 +1000569 template=self.main_template,
570 files={'the.yaml': self.nested_templ},
Sergey Kraynevbf67ce32015-04-17 10:54:20 -0400571 enable_cleanup=False
Angus Salkeld2bd63a42015-01-07 11:11:29 +1000572 )
Angus Salkeld2bd63a42015-01-07 11:11:29 +1000573
Sirushti Murugesan04ee8022015-02-02 23:00:23 +0530574 info = self.stack_abandon(stack_id=stack_identifier)
Angus Salkeld2bd63a42015-01-07 11:11:29 +1000575 self.assertEqual(self._yaml_to_json(self.main_template),
576 info['template'])
577 self.assertEqual(self._yaml_to_json(self.nested_templ),
578 info['resources']['the_nested']['template'])
579
580 def test_adopt(self):
581 data = {
582 'resources': {
583 'the_nested': {
584 "type": "the.yaml",
585 "resources": {
586 "RealRandom": {
587 "type": "OS::Heat::RandomString",
588 'resource_data': {'value': 'goopie'},
589 'resource_id': 'froggy'
590 }
591 }
592 }
593 },
594 "environment": {"parameters": {}},
595 "template": yaml.load(self.main_template)
596 }
597
598 stack_identifier = self.stack_adopt(
599 adopt_data=json.dumps(data),
600 files={'the.yaml': self.nested_templ})
601
602 self.assert_resource_is_a_stack(stack_identifier, 'the_nested')
603 stack = self.client.stacks.get(stack_identifier)
604 self.assertEqual('goopie', self._stack_output(stack, 'value'))
Angus Salkeld87601722015-01-05 14:57:27 +1000605
606
Rabi Mishra477efc92015-07-31 13:01:45 +0530607class TemplateResourceCheckTest(functional_base.FunctionalTestsBase):
Angus Salkeld87601722015-01-05 14:57:27 +1000608 """Prove that we can do template resource check."""
609
610 main_template = '''
611HeatTemplateFormatVersion: '2012-12-12'
612Resources:
613 the_nested:
614 Type: the.yaml
615 Properties:
616 one: my_name
617Outputs:
618 identifier:
619 Value: {Ref: the_nested}
620 value:
621 Value: {'Fn::GetAtt': [the_nested, the_str]}
622'''
623
624 nested_templ = '''
625HeatTemplateFormatVersion: '2012-12-12'
626Parameters:
627 one:
628 Default: foo
629 Type: String
630Resources:
631 RealRandom:
632 Type: OS::Heat::RandomString
633 Properties:
634 salt: {Ref: one}
635Outputs:
636 the_str:
637 Value: {'Fn::GetAtt': [RealRandom, value]}
638'''
639
640 def setUp(self):
641 super(TemplateResourceCheckTest, self).setUp()
Angus Salkeld87601722015-01-05 14:57:27 +1000642
643 def test_check(self):
Sergey Kraynevbf67ce32015-04-17 10:54:20 -0400644 stack_identifier = self.stack_create(
Angus Salkeld87601722015-01-05 14:57:27 +1000645 template=self.main_template,
Sergey Kraynevbf67ce32015-04-17 10:54:20 -0400646 files={'the.yaml': self.nested_templ}
Angus Salkeld87601722015-01-05 14:57:27 +1000647 )
Angus Salkeld87601722015-01-05 14:57:27 +1000648
649 self.client.actions.check(stack_id=stack_identifier)
650 self._wait_for_stack_status(stack_identifier, 'CHECK_COMPLETE')
Angus Salkeld793b0fc2015-06-24 08:52:08 +1000651
652
Rabi Mishra477efc92015-07-31 13:01:45 +0530653class TemplateResourceErrorMessageTest(functional_base.FunctionalTestsBase):
Angus Salkeld793b0fc2015-06-24 08:52:08 +1000654 """Prove that nested stack errors don't suck."""
655 template = '''
656HeatTemplateFormatVersion: '2012-12-12'
657Resources:
658 victim:
659 Type: fail.yaml
660'''
661 nested_templ = '''
662HeatTemplateFormatVersion: '2012-12-12'
663Resources:
664 oops:
665 Type: OS::Heat::TestResource
666 Properties:
667 fail: true
668 wait_secs: 2
669'''
670
671 def setUp(self):
672 super(TemplateResourceErrorMessageTest, self).setUp()
Angus Salkeld793b0fc2015-06-24 08:52:08 +1000673
674 def test_fail(self):
675 stack_identifier = self.stack_create(
676 template=self.template,
677 files={'fail.yaml': self.nested_templ},
678 expected_status='CREATE_FAILED')
679 stack = self.client.stacks.get(stack_identifier)
680
681 exp_path = 'resources.victim.resources.oops'
682 exp_msg = 'Test Resource failed oops'
683 exp = 'Resource CREATE failed: ValueError: %s: %s' % (exp_path,
684 exp_msg)
685 self.assertEqual(exp, stack.stack_status_reason)
kairat_kushaev61a99e12015-07-31 16:22:45 +0300686
687
Rabi Mishra477efc92015-07-31 13:01:45 +0530688class TemplateResourceSuspendResumeTest(functional_base.FunctionalTestsBase):
kairat_kushaev61a99e12015-07-31 16:22:45 +0300689 """Prove that we can do template resource suspend/resume."""
690
691 main_template = '''
692heat_template_version: 2014-10-16
693parameters:
694resources:
695 the_nested:
696 type: the.yaml
697'''
698
699 nested_templ = '''
700heat_template_version: 2014-10-16
701resources:
702 test_random_string:
703 type: OS::Heat::RandomString
704'''
705
706 def setUp(self):
707 super(TemplateResourceSuspendResumeTest, self).setUp()
kairat_kushaev61a99e12015-07-31 16:22:45 +0300708
709 def test_suspend_resume(self):
710 """Basic test for template resource suspend resume"""
711 stack_identifier = self.stack_create(
712 template=self.main_template,
713 files={'the.yaml': self.nested_templ}
714 )
715
716 self.stack_suspend(stack_identifier=stack_identifier)
717 self.stack_resume(stack_identifier=stack_identifier)
Angus Salkeld6a20e3b2015-08-05 13:30:26 +1000718
719
720class ValidateFacadeTest(test.HeatIntegrationTest):
721 """Prove that nested stack errors don't suck."""
722 template = '''
723heat_template_version: 2015-10-15
724resources:
725 thisone:
726 type: OS::Thingy
727 properties:
728 one: pre
729 two: post
730outputs:
731 one:
732 value: {get_attr: [thisone, here-it-is]}
733'''
734 templ_facade = '''
735heat_template_version: 2015-04-30
736parameters:
737 one:
738 type: string
739 two:
740 type: string
741outputs:
742 here-it-is:
743 value: noop
744'''
745 env = '''
746resource_registry:
747 OS::Thingy: facade.yaml
748 resources:
749 thisone:
750 OS::Thingy: concrete.yaml
751'''
752
753 def setUp(self):
754 super(ValidateFacadeTest, self).setUp()
755 self.client = self.orchestration_client
756
757 def test_missing_param(self):
758 templ_missing_parameter = '''
759heat_template_version: 2015-04-30
760parameters:
761 one:
762 type: string
763resources:
764 str:
765 type: OS::Heat::RandomString
766outputs:
767 here-it-is:
768 value:
769 not-important
770'''
771 try:
772 self.stack_create(
773 template=self.template,
774 environment=self.env,
775 files={'facade.yaml': self.templ_facade,
776 'concrete.yaml': templ_missing_parameter},
777 expected_status='CREATE_FAILED')
778 except heat_exceptions.HTTPBadRequest as exc:
779 exp = ('ERROR: Required property two for facade '
780 'OS::Thingy missing in provider')
781 self.assertEqual(exp, six.text_type(exc))
782
783 def test_missing_output(self):
784 templ_missing_output = '''
785heat_template_version: 2015-04-30
786parameters:
787 one:
788 type: string
789 two:
790 type: string
791resources:
792 str:
793 type: OS::Heat::RandomString
794'''
795 try:
796 self.stack_create(
797 template=self.template,
798 environment=self.env,
799 files={'facade.yaml': self.templ_facade,
800 'concrete.yaml': templ_missing_output},
801 expected_status='CREATE_FAILED')
802 except heat_exceptions.HTTPBadRequest as exc:
803 exp = ('ERROR: Attribute here-it-is for facade '
804 'OS::Thingy missing in provider')
805 self.assertEqual(exp, six.text_type(exc))