blob: e8f0309a1ba0987981ce01f0a2c3e1b590b6d3c3 [file] [log] [blame]
Angus Salkeldebf15d72014-12-10 17:03:15 +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
Angus Salkeld771235a2015-01-20 15:11:42 +100013import copy
14import json
Angus Salkeldebf15d72014-12-10 17:03:15 +100015
Angus Salkeld771235a2015-01-20 15:11:42 +100016from testtools import matchers
17
Rabi Mishra477efc92015-07-31 13:01:45 +053018from heat_integrationtests.functional import functional_base
Angus Salkeldebf15d72014-12-10 17:03:15 +100019
20
Rabi Mishra477efc92015-07-31 13:01:45 +053021class InstanceGroupTest(functional_base.FunctionalTestsBase):
Angus Salkeldebf15d72014-12-10 17:03:15 +100022
23 template = '''
24{
25 "AWSTemplateFormatVersion" : "2010-09-09",
26 "Description" : "Template to create multiple instances.",
27 "Parameters" : {"size": {"Type": "String", "Default": "1"},
28 "AZ": {"Type": "String", "Default": "nova"},
29 "image": {"Type": "String"},
rabic333f762016-09-29 08:34:03 +053030 "flavor": {"Type": "String"},
31 "user_data": {"Type": "String", "Default": "jsconfig data"}},
Angus Salkeldebf15d72014-12-10 17:03:15 +100032 "Resources": {
33 "JobServerGroup": {
34 "Type": "OS::Heat::InstanceGroup",
35 "Properties": {
36 "LaunchConfigurationName" : {"Ref": "JobServerConfig"},
37 "Size" : {"Ref": "size"},
38 "AvailabilityZones" : [{"Ref": "AZ"}]
39 }
40 },
41
42 "JobServerConfig" : {
43 "Type" : "AWS::AutoScaling::LaunchConfiguration",
44 "Metadata": {"foo": "bar"},
45 "Properties": {
46 "ImageId" : {"Ref": "image"},
47 "InstanceType" : {"Ref": "flavor"},
Angus Salkeldebf15d72014-12-10 17:03:15 +100048 "SecurityGroups" : [ "sg-1" ],
rabic333f762016-09-29 08:34:03 +053049 "UserData" : {"Ref": "user_data"}
Angus Salkeldebf15d72014-12-10 17:03:15 +100050 }
51 }
52 },
53 "Outputs": {
54 "InstanceList": {"Value": {
Angus Salkeld771235a2015-01-20 15:11:42 +100055 "Fn::GetAtt": ["JobServerGroup", "InstanceList"]}},
56 "JobServerConfigRef": {"Value": {
57 "Ref": "JobServerConfig"}}
Angus Salkeldebf15d72014-12-10 17:03:15 +100058 }
59}
60'''
61
62 instance_template = '''
63heat_template_version: 2013-05-23
64parameters:
65 ImageId: {type: string}
66 InstanceType: {type: string}
Angus Salkeldebf15d72014-12-10 17:03:15 +100067 SecurityGroups: {type: comma_delimited_list}
68 UserData: {type: string}
69 Tags: {type: comma_delimited_list}
70
71resources:
72 random1:
73 type: OS::Heat::RandomString
Angus Salkeld771235a2015-01-20 15:11:42 +100074 properties:
rabic333f762016-09-29 08:34:03 +053075 salt: {get_param: UserData}
Angus Salkeldebf15d72014-12-10 17:03:15 +100076outputs:
77 PublicIp:
78 value: {get_attr: [random1, value]}
79'''
80
Angus Salkeldd67cf702014-12-18 10:40:47 +100081 # This is designed to fail.
82 bad_instance_template = '''
83heat_template_version: 2013-05-23
84parameters:
85 ImageId: {type: string}
86 InstanceType: {type: string}
Angus Salkeldd67cf702014-12-18 10:40:47 +100087 SecurityGroups: {type: comma_delimited_list}
88 UserData: {type: string}
89 Tags: {type: comma_delimited_list}
90
91resources:
92 random1:
93 type: OS::Heat::RandomString
94 depends_on: waiter
95 ready_poster:
96 type: AWS::CloudFormation::WaitConditionHandle
97 waiter:
98 type: AWS::CloudFormation::WaitCondition
99 properties:
100 Handle: {Ref: ready_poster}
101 Timeout: 1
102outputs:
103 PublicIp:
104 value: {get_attr: [random1, value]}
105'''
106
Angus Salkeldebf15d72014-12-10 17:03:15 +1000107 def setUp(self):
108 super(InstanceGroupTest, self).setUp()
Angus Salkeld771235a2015-01-20 15:11:42 +1000109 if not self.conf.minimal_image_ref:
110 raise self.skipException("No minimal image configured to test")
Angus Salkeldebf15d72014-12-10 17:03:15 +1000111 if not self.conf.instance_type:
112 raise self.skipException("No flavor configured to test")
113
Angus Salkeldbfc7e932014-12-15 11:15:45 +1000114 def assert_instance_count(self, stack, expected_count):
115 inst_list = self._stack_output(stack, 'InstanceList')
116 self.assertEqual(expected_count, len(inst_list.split(',')))
117
Angus Salkeldd67cf702014-12-18 10:40:47 +1000118 def _assert_instance_state(self, nested_identifier,
119 num_complete, num_failed):
120 for res in self.client.resources.list(nested_identifier):
121 if 'COMPLETE' in res.resource_status:
122 num_complete = num_complete - 1
123 elif 'FAILED' in res.resource_status:
124 num_failed = num_failed - 1
125 self.assertEqual(0, num_failed)
126 self.assertEqual(0, num_complete)
127
Angus Salkeld771235a2015-01-20 15:11:42 +1000128
129class InstanceGroupBasicTest(InstanceGroupTest):
130
Angus Salkeldebf15d72014-12-10 17:03:15 +1000131 def test_basic_create_works(self):
132 """Make sure the working case is good.
Peter Razumovskyf0ac9582015-09-24 16:49:03 +0300133
Angus Salkeldebf15d72014-12-10 17:03:15 +1000134 Note this combines test_override_aws_ec2_instance into this test as
135 well, which is:
136 If AWS::EC2::Instance is overridden, InstanceGroup will automatically
137 use that overridden resource type.
138 """
139
Angus Salkeldebf15d72014-12-10 17:03:15 +1000140 files = {'provider.yaml': self.instance_template}
141 env = {'resource_registry': {'AWS::EC2::Instance': 'provider.yaml'},
142 'parameters': {'size': 4,
rabic333f762016-09-29 08:34:03 +0530143 'image': self.conf.minimal_image_ref,
Angus Salkeldebf15d72014-12-10 17:03:15 +1000144 'flavor': self.conf.instance_type}}
Angus Salkeldbfc7e932014-12-15 11:15:45 +1000145 stack_identifier = self.stack_create(template=self.template,
146 files=files, environment=env)
Angus Salkeldebf15d72014-12-10 17:03:15 +1000147 initial_resources = {
148 'JobServerConfig': 'AWS::AutoScaling::LaunchConfiguration',
149 'JobServerGroup': 'OS::Heat::InstanceGroup'}
150 self.assertEqual(initial_resources,
151 self.list_resources(stack_identifier))
152
Angus Salkeldbfc7e932014-12-15 11:15:45 +1000153 stack = self.client.stacks.get(stack_identifier)
154 self.assert_instance_count(stack, 4)
155
156 def test_size_updates_work(self):
157 files = {'provider.yaml': self.instance_template}
158 env = {'resource_registry': {'AWS::EC2::Instance': 'provider.yaml'},
159 'parameters': {'size': 2,
rabic333f762016-09-29 08:34:03 +0530160 'image': self.conf.minimal_image_ref,
Angus Salkeldbfc7e932014-12-15 11:15:45 +1000161 'flavor': self.conf.instance_type}}
162
163 stack_identifier = self.stack_create(template=self.template,
164 files=files,
165 environment=env)
166 stack = self.client.stacks.get(stack_identifier)
167 self.assert_instance_count(stack, 2)
168
169 # Increase min size to 5
170 env2 = {'resource_registry': {'AWS::EC2::Instance': 'provider.yaml'},
171 'parameters': {'size': 5,
rabic333f762016-09-29 08:34:03 +0530172 'image': self.conf.minimal_image_ref,
Angus Salkeldbfc7e932014-12-15 11:15:45 +1000173 'flavor': self.conf.instance_type}}
174 self.update_stack(stack_identifier, self.template,
175 environment=env2, files=files)
Angus Salkeldbfc7e932014-12-15 11:15:45 +1000176 stack = self.client.stacks.get(stack_identifier)
177 self.assert_instance_count(stack, 5)
Angus Salkeldcd21b1b2014-12-15 11:27:04 +1000178
179 def test_update_group_replace(self):
Peter Razumovskyf0ac9582015-09-24 16:49:03 +0300180 """Test case for ensuring non-updatable props case a replacement.
181
182 Make sure that during a group update the non-updatable properties cause
183 a replacement.
Angus Salkeldcd21b1b2014-12-15 11:27:04 +1000184 """
185 files = {'provider.yaml': self.instance_template}
186 env = {'resource_registry':
187 {'AWS::EC2::Instance': 'provider.yaml'},
188 'parameters': {'size': 1,
rabic333f762016-09-29 08:34:03 +0530189 'image': self.conf.minimal_image_ref,
Angus Salkeldcd21b1b2014-12-15 11:27:04 +1000190 'flavor': self.conf.instance_type}}
191
192 stack_identifier = self.stack_create(template=self.template,
193 files=files,
194 environment=env)
195 rsrc = self.client.resources.get(stack_identifier, 'JobServerGroup')
196 orig_asg_id = rsrc.physical_resource_id
197
198 env2 = {'resource_registry':
199 {'AWS::EC2::Instance': 'provider.yaml'},
200 'parameters': {'size': '2',
201 'AZ': 'wibble',
rabic333f762016-09-29 08:34:03 +0530202 'image': self.conf.minimal_image_ref,
203 'flavor': self.conf.instance_type,
204 'user_data': 'new data'}}
Angus Salkeldcd21b1b2014-12-15 11:27:04 +1000205 self.update_stack(stack_identifier, self.template,
206 environment=env2, files=files)
207
208 # replacement will cause the resource physical_resource_id to change.
209 rsrc = self.client.resources.get(stack_identifier, 'JobServerGroup')
210 self.assertNotEqual(orig_asg_id, rsrc.physical_resource_id)
Angus Salkeldd67cf702014-12-18 10:40:47 +1000211
212 def test_create_instance_error_causes_group_error(self):
Peter Razumovskyf0ac9582015-09-24 16:49:03 +0300213 """Test create failing a resource in the instance group.
214
215 If a resource in an instance group fails to be created, the instance
Angus Salkeldd67cf702014-12-18 10:40:47 +1000216 group itself will fail and the broken inner resource will remain.
217 """
218 stack_name = self._stack_rand_name()
219 files = {'provider.yaml': self.bad_instance_template}
220 env = {'resource_registry': {'AWS::EC2::Instance': 'provider.yaml'},
221 'parameters': {'size': 2,
rabic333f762016-09-29 08:34:03 +0530222 'image': self.conf.minimal_image_ref,
Angus Salkeldd67cf702014-12-18 10:40:47 +1000223 'flavor': self.conf.instance_type}}
224
225 self.client.stacks.create(
226 stack_name=stack_name,
227 template=self.template,
228 files=files,
229 disable_rollback=True,
230 parameters={},
231 environment=env
232 )
Steve Bakerdbea6ab2015-08-19 13:37:08 +1200233 self.addCleanup(self._stack_delete, stack_name)
Angus Salkeldd67cf702014-12-18 10:40:47 +1000234 stack = self.client.stacks.get(stack_name)
235 stack_identifier = '%s/%s' % (stack_name, stack.id)
236 self._wait_for_stack_status(stack_identifier, 'CREATE_FAILED')
237 initial_resources = {
238 'JobServerConfig': 'AWS::AutoScaling::LaunchConfiguration',
239 'JobServerGroup': 'OS::Heat::InstanceGroup'}
240 self.assertEqual(initial_resources,
241 self.list_resources(stack_identifier))
242
Angus Salkeld771235a2015-01-20 15:11:42 +1000243 nested_ident = self.assert_resource_is_a_stack(stack_identifier,
244 'JobServerGroup')
Angus Salkeldd67cf702014-12-18 10:40:47 +1000245 self._assert_instance_state(nested_ident, 0, 2)
246
247 def test_update_instance_error_causes_group_error(self):
Peter Razumovskyf0ac9582015-09-24 16:49:03 +0300248 """Test update failing a resource in the instance group.
249
250 If a resource in an instance group fails to be created during an
Angus Salkeldd67cf702014-12-18 10:40:47 +1000251 update, the instance group itself will fail and the broken inner
252 resource will remain.
253 """
254 files = {'provider.yaml': self.instance_template}
255 env = {'resource_registry': {'AWS::EC2::Instance': 'provider.yaml'},
256 'parameters': {'size': 2,
rabic333f762016-09-29 08:34:03 +0530257 'image': self.conf.minimal_image_ref,
Angus Salkeldd67cf702014-12-18 10:40:47 +1000258 'flavor': self.conf.instance_type}}
259
260 stack_identifier = self.stack_create(template=self.template,
261 files=files,
262 environment=env)
263 initial_resources = {
264 'JobServerConfig': 'AWS::AutoScaling::LaunchConfiguration',
265 'JobServerGroup': 'OS::Heat::InstanceGroup'}
266 self.assertEqual(initial_resources,
267 self.list_resources(stack_identifier))
268
269 stack = self.client.stacks.get(stack_identifier)
270 self.assert_instance_count(stack, 2)
Angus Salkeld771235a2015-01-20 15:11:42 +1000271 nested_ident = self.assert_resource_is_a_stack(stack_identifier,
272 'JobServerGroup')
Angus Salkeldd67cf702014-12-18 10:40:47 +1000273 self._assert_instance_state(nested_ident, 2, 0)
Angus Salkeld545dfeb2015-02-03 11:27:40 +1000274 initial_list = [res.resource_name
275 for res in self.client.resources.list(nested_ident)]
Angus Salkeldd67cf702014-12-18 10:40:47 +1000276
277 env['parameters']['size'] = 3
278 files2 = {'provider.yaml': self.bad_instance_template}
279 self.client.stacks.update(
280 stack_id=stack_identifier,
281 template=self.template,
282 files=files2,
283 disable_rollback=True,
284 parameters={},
285 environment=env
286 )
287 self._wait_for_stack_status(stack_identifier, 'UPDATE_FAILED')
288
Angus Salkeld771235a2015-01-20 15:11:42 +1000289 nested_ident = self.assert_resource_is_a_stack(stack_identifier,
290 'JobServerGroup')
Angus Salkeld545dfeb2015-02-03 11:27:40 +1000291 # assert that there are 3 bad instances
292 # 2 resources should be in update failed, and one create failed.
293 for res in self.client.resources.list(nested_ident):
294 if res.resource_name in initial_list:
295 self._wait_for_resource_status(nested_ident,
296 res.resource_name,
297 'UPDATE_FAILED')
298 else:
299 self._wait_for_resource_status(nested_ident,
300 res.resource_name,
301 'CREATE_FAILED')
Angus Salkeld771235a2015-01-20 15:11:42 +1000302
303
304class InstanceGroupUpdatePolicyTest(InstanceGroupTest):
305
306 def ig_tmpl_with_updt_policy(self):
307 templ = json.loads(copy.deepcopy(self.template))
308 up = {"RollingUpdate": {
309 "MinInstancesInService": "1",
310 "MaxBatchSize": "2",
311 "PauseTime": "PT1S"}}
312 templ['Resources']['JobServerGroup']['UpdatePolicy'] = up
313 return templ
314
315 def update_instance_group(self, updt_template,
316 num_updates_expected_on_updt,
317 num_creates_expected_on_updt,
318 num_deletes_expected_on_updt,
319 update_replace):
320
321 # setup stack from the initial template
322 files = {'provider.yaml': self.instance_template}
Angus Salkeld45a4e492015-03-05 17:55:36 +1000323 size = 5
Angus Salkeld771235a2015-01-20 15:11:42 +1000324 env = {'resource_registry': {'AWS::EC2::Instance': 'provider.yaml'},
325 'parameters': {'size': size,
rabic333f762016-09-29 08:34:03 +0530326 'image': self.conf.minimal_image_ref,
327 'flavor': self.conf.minimal_instance_type}}
Angus Salkeld771235a2015-01-20 15:11:42 +1000328 stack_name = self._stack_rand_name()
329 stack_identifier = self.stack_create(
330 stack_name=stack_name,
331 template=self.ig_tmpl_with_updt_policy(),
332 files=files,
333 environment=env)
334 stack = self.client.stacks.get(stack_identifier)
335 nested_ident = self.assert_resource_is_a_stack(stack_identifier,
336 'JobServerGroup')
337
338 # test that physical resource name of launch configuration is used
339 conf_name = self._stack_output(stack, 'JobServerConfigRef')
340 conf_name_pattern = '%s-JobServerConfig-[a-zA-Z0-9]+$' % stack_name
341 self.assertThat(conf_name,
342 matchers.MatchesRegex(conf_name_pattern))
343
344 # test the number of instances created
345 self.assert_instance_count(stack, size)
346 # saves info from initial list of instances for comparison later
347 init_instances = self.client.resources.list(nested_ident)
348 init_names = [inst.resource_name for inst in init_instances]
349
350 # test stack update
351 self.update_stack(stack_identifier, updt_template,
352 environment=env, files=files)
Angus Salkeld771235a2015-01-20 15:11:42 +1000353 updt_stack = self.client.stacks.get(stack_identifier)
354
355 # test that the launch configuration is replaced
356 updt_conf_name = self._stack_output(updt_stack, 'JobServerConfigRef')
357 self.assertThat(updt_conf_name,
358 matchers.MatchesRegex(conf_name_pattern))
359 self.assertNotEqual(conf_name, updt_conf_name)
360
361 # test that the group size are the same
362 updt_instances = self.client.resources.list(nested_ident)
363 updt_names = [inst.resource_name for inst in updt_instances]
364 self.assertEqual(len(init_names), len(updt_names))
365 for res in updt_instances:
366 self.assertEqual('UPDATE_COMPLETE', res.resource_status)
367
368 # test that the appropriate number of instance names are the same
369 matched_names = set(updt_names) & set(init_names)
370 self.assertEqual(num_updates_expected_on_updt, len(matched_names))
371
372 # test that the appropriate number of new instances are created
373 self.assertEqual(num_creates_expected_on_updt,
374 len(set(updt_names) - set(init_names)))
375
376 # test that the appropriate number of instances are deleted
377 self.assertEqual(num_deletes_expected_on_updt,
378 len(set(init_names) - set(updt_names)))
379
380 # test that the older instances are the ones being deleted
381 if num_deletes_expected_on_updt > 0:
382 deletes_expected = init_names[:num_deletes_expected_on_updt]
383 self.assertNotIn(deletes_expected, updt_names)
384
385 def test_instance_group_update_replace(self):
Peter Razumovskyf0ac9582015-09-24 16:49:03 +0300386 """Test simple update replace with no conflict.
387
Angus Salkeld771235a2015-01-20 15:11:42 +1000388 Test simple update replace with no conflict in batch size and
389 minimum instances in service.
390 """
391 updt_template = self.ig_tmpl_with_updt_policy()
392 grp = updt_template['Resources']['JobServerGroup']
393 policy = grp['UpdatePolicy']['RollingUpdate']
394 policy['MinInstancesInService'] = '1'
395 policy['MaxBatchSize'] = '3'
396 config = updt_template['Resources']['JobServerConfig']
rabic333f762016-09-29 08:34:03 +0530397 config['Properties']['UserData'] = 'new data'
Angus Salkeld771235a2015-01-20 15:11:42 +1000398
399 self.update_instance_group(updt_template,
Angus Salkeld45a4e492015-03-05 17:55:36 +1000400 num_updates_expected_on_updt=5,
Angus Salkeld771235a2015-01-20 15:11:42 +1000401 num_creates_expected_on_updt=0,
402 num_deletes_expected_on_updt=0,
403 update_replace=True)
404
405 def test_instance_group_update_replace_with_adjusted_capacity(self):
Peter Razumovskyf0ac9582015-09-24 16:49:03 +0300406 """Test update replace with capacity adjustment.
407
Angus Salkeld771235a2015-01-20 15:11:42 +1000408 Test update replace with capacity adjustment due to conflict in
409 batch size and minimum instances in service.
410 """
411 updt_template = self.ig_tmpl_with_updt_policy()
412 grp = updt_template['Resources']['JobServerGroup']
413 policy = grp['UpdatePolicy']['RollingUpdate']
Angus Salkeld45a4e492015-03-05 17:55:36 +1000414 policy['MinInstancesInService'] = '4'
Angus Salkeld771235a2015-01-20 15:11:42 +1000415 policy['MaxBatchSize'] = '4'
416 config = updt_template['Resources']['JobServerConfig']
rabic333f762016-09-29 08:34:03 +0530417 config['Properties']['UserData'] = 'new data'
Angus Salkeld771235a2015-01-20 15:11:42 +1000418
419 self.update_instance_group(updt_template,
Angus Salkeld45a4e492015-03-05 17:55:36 +1000420 num_updates_expected_on_updt=2,
421 num_creates_expected_on_updt=3,
422 num_deletes_expected_on_updt=3,
Angus Salkeld771235a2015-01-20 15:11:42 +1000423 update_replace=True)
424
425 def test_instance_group_update_replace_huge_batch_size(self):
Peter Razumovskyf0ac9582015-09-24 16:49:03 +0300426 """Test update replace with a huge batch size."""
Angus Salkeld771235a2015-01-20 15:11:42 +1000427 updt_template = self.ig_tmpl_with_updt_policy()
428 group = updt_template['Resources']['JobServerGroup']
429 policy = group['UpdatePolicy']['RollingUpdate']
430 policy['MinInstancesInService'] = '0'
431 policy['MaxBatchSize'] = '20'
432 config = updt_template['Resources']['JobServerConfig']
rabic333f762016-09-29 08:34:03 +0530433 config['Properties']['UserData'] = 'new data'
Angus Salkeld771235a2015-01-20 15:11:42 +1000434
435 self.update_instance_group(updt_template,
Angus Salkeld45a4e492015-03-05 17:55:36 +1000436 num_updates_expected_on_updt=5,
Angus Salkeld771235a2015-01-20 15:11:42 +1000437 num_creates_expected_on_updt=0,
438 num_deletes_expected_on_updt=0,
439 update_replace=True)
440
441 def test_instance_group_update_replace_huge_min_in_service(self):
Peter Razumovskyf0ac9582015-09-24 16:49:03 +0300442 """Update replace with huge number of minimum instances in service."""
Angus Salkeld771235a2015-01-20 15:11:42 +1000443 updt_template = self.ig_tmpl_with_updt_policy()
444 group = updt_template['Resources']['JobServerGroup']
445 policy = group['UpdatePolicy']['RollingUpdate']
446 policy['MinInstancesInService'] = '20'
Angus Salkeld45a4e492015-03-05 17:55:36 +1000447 policy['MaxBatchSize'] = '2'
Angus Salkeld771235a2015-01-20 15:11:42 +1000448 policy['PauseTime'] = 'PT0S'
449 config = updt_template['Resources']['JobServerConfig']
rabic333f762016-09-29 08:34:03 +0530450 config['Properties']['UserData'] = 'new data'
Angus Salkeld771235a2015-01-20 15:11:42 +1000451
452 self.update_instance_group(updt_template,
Angus Salkeld45a4e492015-03-05 17:55:36 +1000453 num_updates_expected_on_updt=3,
454 num_creates_expected_on_updt=2,
455 num_deletes_expected_on_updt=2,
Angus Salkeld771235a2015-01-20 15:11:42 +1000456 update_replace=True)
457
458 def test_instance_group_update_no_replace(self):
Peter Razumovskyf0ac9582015-09-24 16:49:03 +0300459 """Test simple update only and no replace with no conflict.
460
Angus Salkeld771235a2015-01-20 15:11:42 +1000461 Test simple update only and no replace (i.e. updated instance flavor
462 in Launch Configuration) with no conflict in batch size and
463 minimum instances in service.
464 """
465 updt_template = self.ig_tmpl_with_updt_policy()
466 group = updt_template['Resources']['JobServerGroup']
467 policy = group['UpdatePolicy']['RollingUpdate']
468 policy['MinInstancesInService'] = '1'
469 policy['MaxBatchSize'] = '3'
470 policy['PauseTime'] = 'PT0S'
471 config = updt_template['Resources']['JobServerConfig']
472 config['Properties']['InstanceType'] = 'm1.tiny'
473
474 self.update_instance_group(updt_template,
Angus Salkeld45a4e492015-03-05 17:55:36 +1000475 num_updates_expected_on_updt=5,
Angus Salkeld771235a2015-01-20 15:11:42 +1000476 num_creates_expected_on_updt=0,
477 num_deletes_expected_on_updt=0,
478 update_replace=False)
479
480 def test_instance_group_update_no_replace_with_adjusted_capacity(self):
Peter Razumovskyf0ac9582015-09-24 16:49:03 +0300481 """Test update only and no replace with capacity adjustment.
482
Angus Salkeld771235a2015-01-20 15:11:42 +1000483 Test update only and no replace (i.e. updated instance flavor in
484 Launch Configuration) with capacity adjustment due to conflict in
485 batch size and minimum instances in service.
486 """
487 updt_template = self.ig_tmpl_with_updt_policy()
488 group = updt_template['Resources']['JobServerGroup']
489 policy = group['UpdatePolicy']['RollingUpdate']
Angus Salkeld45a4e492015-03-05 17:55:36 +1000490 policy['MinInstancesInService'] = '4'
Angus Salkeld771235a2015-01-20 15:11:42 +1000491 policy['MaxBatchSize'] = '4'
492 policy['PauseTime'] = 'PT0S'
493 config = updt_template['Resources']['JobServerConfig']
494 config['Properties']['InstanceType'] = 'm1.tiny'
495
496 self.update_instance_group(updt_template,
Angus Salkeld45a4e492015-03-05 17:55:36 +1000497 num_updates_expected_on_updt=2,
498 num_creates_expected_on_updt=3,
499 num_deletes_expected_on_updt=3,
Angus Salkeld771235a2015-01-20 15:11:42 +1000500 update_replace=False)