blob: 3904311ab6a58be665bae68c037db8cfc9ca9cb2 [file] [log] [blame]
Steve Bakerf547ec32014-10-20 14:34:41 +13001# 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
Steve Bakerf547ec32014-10-20 14:34:41 +130013
14from heat_integrationtests.common import test
15
16
Steve Bakerf547ec32014-10-20 14:34:41 +130017class UpdateStackTest(test.HeatIntegrationTest):
18
19 template = '''
20heat_template_version: 2013-05-23
21resources:
22 random1:
23 type: OS::Heat::RandomString
24'''
25 update_template = '''
26heat_template_version: 2013-05-23
27resources:
28 random1:
29 type: OS::Heat::RandomString
30 random2:
31 type: OS::Heat::RandomString
32'''
33
Steven Hardybe1ce2d2014-11-18 12:54:50 +000034 provider_template = '''
35heat_template_version: 2013-05-23
36resources:
37 random1:
38 type: My::RandomString
39'''
40
Steven Hardy417097e2014-11-18 16:30:35 +000041 provider_group_template = '''
42heat_template_version: 2013-05-23
43resources:
44 random_group:
45 type: OS::Heat::ResourceGroup
46 properties:
47 count: 2
48 resource_def:
49 type: My::RandomString
50'''
51
Steve Bakerf547ec32014-10-20 14:34:41 +130052 def setUp(self):
53 super(UpdateStackTest, self).setUp()
54 self.client = self.orchestration_client
55
Steve Bakerf547ec32014-10-20 14:34:41 +130056 def test_stack_update_nochange(self):
Steven Hardyf2c82c02014-11-20 14:02:17 +000057 stack_identifier = self.stack_create()
Steve Bakerf547ec32014-10-20 14:34:41 +130058 expected_resources = {'random1': 'OS::Heat::RandomString'}
59 self.assertEqual(expected_resources,
60 self.list_resources(stack_identifier))
61
62 # Update with no changes, resources should be unchanged
63 self.update_stack(stack_identifier, self.template)
64 self.assertEqual(expected_resources,
65 self.list_resources(stack_identifier))
66
67 def test_stack_update_add_remove(self):
Steven Hardyf2c82c02014-11-20 14:02:17 +000068 stack_identifier = self.stack_create()
Steve Bakerf547ec32014-10-20 14:34:41 +130069 initial_resources = {'random1': 'OS::Heat::RandomString'}
70 self.assertEqual(initial_resources,
71 self.list_resources(stack_identifier))
72
73 # Add one resource via a stack update
74 self.update_stack(stack_identifier, self.update_template)
Steve Bakerf547ec32014-10-20 14:34:41 +130075 updated_resources = {'random1': 'OS::Heat::RandomString',
76 'random2': 'OS::Heat::RandomString'}
77 self.assertEqual(updated_resources,
78 self.list_resources(stack_identifier))
79
80 # Then remove it by updating with the original template
81 self.update_stack(stack_identifier, self.template)
82 self.assertEqual(initial_resources,
83 self.list_resources(stack_identifier))
Steven Hardybe1ce2d2014-11-18 12:54:50 +000084
85 def test_stack_update_provider(self):
Steven Hardybe1ce2d2014-11-18 12:54:50 +000086 files = {'provider.yaml': self.template}
87 env = {'resource_registry':
88 {'My::RandomString': 'provider.yaml'}}
Steven Hardyf2c82c02014-11-20 14:02:17 +000089 stack_identifier = self.stack_create(
Steven Hardybe1ce2d2014-11-18 12:54:50 +000090 template=self.provider_template,
91 files=files,
Steven Hardybe1ce2d2014-11-18 12:54:50 +000092 environment=env
93 )
Steven Hardybe1ce2d2014-11-18 12:54:50 +000094
Steven Hardybe1ce2d2014-11-18 12:54:50 +000095 initial_resources = {'random1': 'My::RandomString'}
96 self.assertEqual(initial_resources,
97 self.list_resources(stack_identifier))
98
99 # Prove the resource is backed by a nested stack, save the ID
Angus Salkeld2bd63a42015-01-07 11:11:29 +1000100 nested_identifier = self.assert_resource_is_a_stack(stack_identifier,
101 'random1')
102 nested_id = nested_identifier.split('/')[-1]
Steven Hardybe1ce2d2014-11-18 12:54:50 +0000103
104 # Then check the expected resources are in the nested stack
105 nested_resources = {'random1': 'OS::Heat::RandomString'}
106 self.assertEqual(nested_resources,
107 self.list_resources(nested_identifier))
108
109 # Add one resource via a stack update by changing the nested stack
110 files['provider.yaml'] = self.update_template
111 self.update_stack(stack_identifier, self.provider_template,
112 environment=env, files=files)
Steven Hardybe1ce2d2014-11-18 12:54:50 +0000113
114 # Parent resources should be unchanged and the nested stack
115 # should have been updated in-place without replacement
116 self.assertEqual(initial_resources,
117 self.list_resources(stack_identifier))
118 rsrc = self.client.resources.get(stack_identifier, 'random1')
119 self.assertEqual(rsrc.physical_resource_id, nested_id)
120
121 # Then check the expected resources are in the nested stack
122 nested_resources = {'random1': 'OS::Heat::RandomString',
123 'random2': 'OS::Heat::RandomString'}
124 self.assertEqual(nested_resources,
125 self.list_resources(nested_identifier))
Steven Hardy417097e2014-11-18 16:30:35 +0000126
127 def test_stack_update_provider_group(self):
128 '''Test two-level nested update.'''
129 # Create a ResourceGroup (which creates a nested stack),
130 # containing provider resources (which create a nested
131 # stack), thus excercising an update which traverses
132 # two levels of nesting.
Steven Hardy417097e2014-11-18 16:30:35 +0000133 files = {'provider.yaml': self.template}
134 env = {'resource_registry':
135 {'My::RandomString': 'provider.yaml'}}
136
Steven Hardyf2c82c02014-11-20 14:02:17 +0000137 stack_identifier = self.stack_create(
Steven Hardy417097e2014-11-18 16:30:35 +0000138 template=self.provider_group_template,
139 files=files,
Steven Hardy417097e2014-11-18 16:30:35 +0000140 environment=env
141 )
Steven Hardy417097e2014-11-18 16:30:35 +0000142
Steven Hardy417097e2014-11-18 16:30:35 +0000143 initial_resources = {'random_group': 'OS::Heat::ResourceGroup'}
144 self.assertEqual(initial_resources,
145 self.list_resources(stack_identifier))
146
147 # Prove the resource is backed by a nested stack, save the ID
Angus Salkeld2bd63a42015-01-07 11:11:29 +1000148 nested_identifier = self.assert_resource_is_a_stack(stack_identifier,
149 'random_group')
Steven Hardy417097e2014-11-18 16:30:35 +0000150
151 # Then check the expected resources are in the nested stack
152 nested_resources = {'0': 'My::RandomString',
153 '1': 'My::RandomString'}
154 self.assertEqual(nested_resources,
155 self.list_resources(nested_identifier))
156
157 for n_rsrc in nested_resources:
158 rsrc = self.client.resources.get(nested_identifier, n_rsrc)
159 provider_stack = self.client.stacks.get(rsrc.physical_resource_id)
160 provider_identifier = '%s/%s' % (provider_stack.stack_name,
161 provider_stack.id)
162 provider_resources = {u'random1': u'OS::Heat::RandomString'}
163 self.assertEqual(provider_resources,
164 self.list_resources(provider_identifier))
165
166 # Add one resource via a stack update by changing the nested stack
167 files['provider.yaml'] = self.update_template
168 self.update_stack(stack_identifier, self.provider_group_template,
169 environment=env, files=files)
Steven Hardy417097e2014-11-18 16:30:35 +0000170
171 # Parent resources should be unchanged and the nested stack
172 # should have been updated in-place without replacement
173 self.assertEqual(initial_resources,
174 self.list_resources(stack_identifier))
175
176 # Resource group stack should also be unchanged (but updated)
177 nested_stack = self.client.stacks.get(nested_identifier)
178 self.assertEqual('UPDATE_COMPLETE', nested_stack.stack_status)
179 self.assertEqual(nested_resources,
180 self.list_resources(nested_identifier))
181
182 for n_rsrc in nested_resources:
183 rsrc = self.client.resources.get(nested_identifier, n_rsrc)
184 provider_stack = self.client.stacks.get(rsrc.physical_resource_id)
185 provider_identifier = '%s/%s' % (provider_stack.stack_name,
186 provider_stack.id)
187 provider_resources = {'random1': 'OS::Heat::RandomString',
188 'random2': 'OS::Heat::RandomString'}
189 self.assertEqual(provider_resources,
190 self.list_resources(provider_identifier))