blob: f7d455a6754e0ea254da26ca12c7a3069a14f5e9 [file] [log] [blame]
Steven Hardy03da0742015-03-19 00:13:17 -04001# 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 logging
14
15import yaml
16
17from heat_integrationtests.common import test
18
19
20LOG = logging.getLogger(__name__)
21
22
23class HooksTest(test.HeatIntegrationTest):
24
25 def setUp(self):
26 super(HooksTest, self).setUp()
27 self.client = self.orchestration_client
28 self.template = {'heat_template_version': '2014-10-16',
29 'resources': {
30 'foo_step1': {'type': 'OS::Heat::RandomString'},
31 'foo_step2': {'type': 'OS::Heat::RandomString',
32 'depends_on': 'foo_step1'},
33 'foo_step3': {'type': 'OS::Heat::RandomString',
34 'depends_on': 'foo_step2'}}}
35
36 def test_hook_pre_create(self):
37 env = {'resource_registry':
38 {'resources':
39 {'foo_step2':
40 {'hooks': 'pre-create'}}}}
41 # Note we don't wait for CREATE_COMPLETE, because we need to
42 # signal to clear the hook before create will complete
43 stack_identifier = self.stack_create(
44 template=self.template,
45 environment=env,
46 expected_status='CREATE_IN_PROGRESS')
47 self._wait_for_resource_status(
48 stack_identifier, 'foo_step1', 'CREATE_COMPLETE')
49 self._wait_for_resource_status(
50 stack_identifier, 'foo_step2', 'INIT_COMPLETE')
51 ev = self.wait_for_event_with_reason(
52 stack_identifier,
53 reason='CREATE paused until Hook pre-create is cleared',
54 rsrc_name='foo_step2')
55 self.assertEqual('INIT_COMPLETE', ev[0].resource_status)
56 self.client.resources.signal(stack_identifier, 'foo_step2',
57 data={'unset_hook': 'pre-create'})
58 ev = self.wait_for_event_with_reason(
59 stack_identifier,
60 reason='Hook pre-create is cleared',
61 rsrc_name='foo_step2')
62 self.assertEqual('INIT_COMPLETE', ev[0].resource_status)
63 self._wait_for_resource_status(
64 stack_identifier, 'foo_step2', 'CREATE_COMPLETE')
65 self._wait_for_stack_status(stack_identifier, 'CREATE_COMPLETE')
66
67 def test_hook_pre_update_nochange(self):
68 env = {'resource_registry':
69 {'resources':
70 {'foo_step2':
71 {'hooks': 'pre-update'}}}}
72 stack_identifier = self.stack_create(
73 template=self.template,
74 environment=env)
75 res_before = self.client.resources.get(stack_identifier, 'foo_step2')
76 # Note we don't wait for UPDATE_COMPLETE, because we need to
77 # signal to clear the hook before update will complete
78 self.update_stack(
79 stack_identifier,
80 template=self.template,
81 environment=env,
82 expected_status='UPDATE_IN_PROGRESS')
83
84 # Note when a hook is specified, the resource status doesn't change
85 # when we hit the hook, so we look for the event, then assert the
86 # state is unchanged.
87 self._wait_for_resource_status(
88 stack_identifier, 'foo_step2', 'CREATE_COMPLETE')
89 ev = self.wait_for_event_with_reason(
90 stack_identifier,
91 reason='UPDATE paused until Hook pre-update is cleared',
92 rsrc_name='foo_step2')
93 self.assertEqual('CREATE_COMPLETE', ev[0].resource_status)
94 self.client.resources.signal(stack_identifier, 'foo_step2',
95 data={'unset_hook': 'pre-update'})
96 ev = self.wait_for_event_with_reason(
97 stack_identifier,
98 reason='Hook pre-update is cleared',
99 rsrc_name='foo_step2')
100 self.assertEqual('CREATE_COMPLETE', ev[0].resource_status)
101 self._wait_for_resource_status(
102 stack_identifier, 'foo_step2', 'CREATE_COMPLETE')
103 self._wait_for_stack_status(stack_identifier, 'UPDATE_COMPLETE')
104 res_after = self.client.resources.get(stack_identifier, 'foo_step2')
105 self.assertEqual(res_before.physical_resource_id,
106 res_after.physical_resource_id)
107
108 def test_hook_pre_update_replace(self):
109 env = {'resource_registry':
110 {'resources':
111 {'foo_step2':
112 {'hooks': 'pre-update'}}}}
113 stack_identifier = self.stack_create(
114 template=self.template,
115 environment=env)
116 res_before = self.client.resources.get(stack_identifier, 'foo_step2')
117 # Note we don't wait for UPDATE_COMPLETE, because we need to
118 # signal to clear the hook before update will complete
119 self.template['resources']['foo_step2']['properties'] = {'length': 10}
120 self.update_stack(
121 stack_identifier,
122 template=self.template,
123 environment=env,
124 expected_status='UPDATE_IN_PROGRESS')
125
126 # Note when a hook is specified, the resource status doesn't change
127 # when we hit the hook, so we look for the event, then assert the
128 # state is unchanged.
129 self._wait_for_resource_status(
130 stack_identifier, 'foo_step2', 'CREATE_COMPLETE')
131 ev = self.wait_for_event_with_reason(
132 stack_identifier,
133 reason='UPDATE paused until Hook pre-update is cleared',
134 rsrc_name='foo_step2')
135 self.assertEqual('CREATE_COMPLETE', ev[0].resource_status)
136 self.client.resources.signal(stack_identifier, 'foo_step2',
137 data={'unset_hook': 'pre-update'})
138 ev = self.wait_for_event_with_reason(
139 stack_identifier,
140 reason='Hook pre-update is cleared',
141 rsrc_name='foo_step2')
142 self.assertEqual('CREATE_COMPLETE', ev[0].resource_status)
143 self._wait_for_resource_status(
144 stack_identifier, 'foo_step2', 'CREATE_COMPLETE')
145 self._wait_for_stack_status(stack_identifier, 'UPDATE_COMPLETE')
146 res_after = self.client.resources.get(stack_identifier, 'foo_step2')
147 self.assertNotEqual(res_before.physical_resource_id,
148 res_after.physical_resource_id)
149
150 def test_hook_pre_update_in_place(self):
151 env = {'resource_registry':
152 {'resources':
153 {'rg':
154 {'hooks': 'pre-update'}}}}
155 template = {'heat_template_version': '2014-10-16',
156 'resources': {
157 'rg': {
158 'type': 'OS::Heat::ResourceGroup',
159 'properties': {
160 'count': 1,
161 'resource_def': {
162 'type': 'OS::Heat::RandomString'}}}}}
163 # Note we don't wait for CREATE_COMPLETE, because we need to
164 # signal to clear the hook before create will complete
165 stack_identifier = self.stack_create(
166 template=template,
167 environment=env)
168 res_before = self.client.resources.get(stack_identifier, 'rg')
169 template['resources']['rg']['properties']['count'] = 2
170 self.update_stack(
171 stack_identifier,
172 template=template,
173 environment=env,
174 expected_status='UPDATE_IN_PROGRESS')
175
176 # Note when a hook is specified, the resource status doesn't change
177 # when we hit the hook, so we look for the event, then assert the
178 # state is unchanged.
179 self._wait_for_resource_status(
180 stack_identifier, 'rg', 'CREATE_COMPLETE')
181 ev = self.wait_for_event_with_reason(
182 stack_identifier,
183 reason='UPDATE paused until Hook pre-update is cleared',
184 rsrc_name='rg')
185 self.assertEqual('CREATE_COMPLETE', ev[0].resource_status)
186 self.client.resources.signal(stack_identifier, 'rg',
187 data={'unset_hook': 'pre-update'})
188
189 ev = self.wait_for_event_with_reason(
190 stack_identifier,
191 reason='Hook pre-update is cleared',
192 rsrc_name='rg')
193 self.assertEqual('CREATE_COMPLETE', ev[0].resource_status)
194 self._wait_for_resource_status(
195 stack_identifier, 'rg', 'CREATE_COMPLETE')
196 self._wait_for_stack_status(stack_identifier, 'UPDATE_COMPLETE')
197 res_after = self.client.resources.get(stack_identifier, 'rg')
198 self.assertEqual(res_before.physical_resource_id,
199 res_after.physical_resource_id)
200
201 def test_hook_pre_create_nested(self):
202 files = {'nested.yaml': yaml.dump(self.template)}
203 env = {'resource_registry':
204 {'resources':
205 {'nested':
206 {'foo_step2':
207 {'hooks': 'pre-create'}}}}}
208 template = {'heat_template_version': '2014-10-16',
209 'resources': {
210 'nested': {'type': 'nested.yaml'}}}
211 # Note we don't wait for CREATE_COMPLETE, because we need to
212 # signal to clear the hook before create will complete
213 stack_identifier = self.stack_create(
214 template=template,
215 environment=env,
216 files=files,
217 expected_status='CREATE_IN_PROGRESS')
218 self._wait_for_resource_status(stack_identifier, 'nested',
219 'CREATE_IN_PROGRESS')
220 nested_identifier = self.assert_resource_is_a_stack(
221 stack_identifier, 'nested', wait=True)
222 self._wait_for_resource_status(
223 nested_identifier, 'foo_step1', 'CREATE_COMPLETE')
224 self._wait_for_resource_status(
225 nested_identifier, 'foo_step2', 'INIT_COMPLETE')
226 ev = self.wait_for_event_with_reason(
227 nested_identifier,
228 reason='CREATE paused until Hook pre-create is cleared',
229 rsrc_name='foo_step2')
230 self.assertEqual('INIT_COMPLETE', ev[0].resource_status)
231 self.client.resources.signal(nested_identifier, 'foo_step2',
232 data={'unset_hook': 'pre-create'})
233 ev = self.wait_for_event_with_reason(
234 nested_identifier,
235 reason='Hook pre-create is cleared',
236 rsrc_name='foo_step2')
237 self.assertEqual('INIT_COMPLETE', ev[0].resource_status)
238 self._wait_for_resource_status(
239 nested_identifier, 'foo_step2', 'CREATE_COMPLETE')
240 self._wait_for_stack_status(stack_identifier, 'CREATE_COMPLETE')
241
242 def test_hook_pre_create_wildcard(self):
243 env = {'resource_registry':
244 {'resources':
245 {'foo_*':
246 {'hooks': 'pre-create'}}}}
247 # Note we don't wait for CREATE_COMPLETE, because we need to
248 # signal to clear the hook before create will complete
249 stack_identifier = self.stack_create(
250 template=self.template,
251 environment=env,
252 expected_status='CREATE_IN_PROGRESS')
253 self._wait_for_resource_status(
254 stack_identifier, 'foo_step1', 'INIT_COMPLETE')
255 self.wait_for_event_with_reason(
256 stack_identifier,
257 reason='CREATE paused until Hook pre-create is cleared',
258 rsrc_name='foo_step1')
259 self.client.resources.signal(stack_identifier, 'foo_step1',
260 data={'unset_hook': 'pre-create'})
261 self.wait_for_event_with_reason(
262 stack_identifier,
263 reason='Hook pre-create is cleared',
264 rsrc_name='foo_step1')
265 self._wait_for_resource_status(
266 stack_identifier, 'foo_step2', 'INIT_COMPLETE')
267 self.wait_for_event_with_reason(
268 stack_identifier,
269 reason='CREATE paused until Hook pre-create is cleared',
270 rsrc_name='foo_step2')
271 self.client.resources.signal(stack_identifier, 'foo_step2',
272 data={'unset_hook': 'pre-create'})
273 self.wait_for_event_with_reason(
274 stack_identifier,
275 reason='Hook pre-create is cleared',
276 rsrc_name='foo_step2')
277 self._wait_for_resource_status(
278 stack_identifier, 'foo_step3', 'INIT_COMPLETE')
279 self.wait_for_event_with_reason(
280 stack_identifier,
281 reason='CREATE paused until Hook pre-create is cleared',
282 rsrc_name='foo_step3')
283 self.client.resources.signal(stack_identifier, 'foo_step3',
284 data={'unset_hook': 'pre-create'})
285 self.wait_for_event_with_reason(
286 stack_identifier,
287 reason='Hook pre-create is cleared',
288 rsrc_name='foo_step3')
289 self._wait_for_stack_status(stack_identifier, 'CREATE_COMPLETE')