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