From 50cc71e33c40a9e3be604b16f77d3c3cf030a63b Mon Sep 17 00:00:00 2001 From: kairat_kushaev Date: Mon, 16 Mar 2015 11:32:24 +1000 Subject: [PATCH] Remove capacity check from AWS::AG update When heat is trying to update autoscaling group resource with the same template an exception is raised because nested stack is not in (UPDATE, COMPLETE) state. It happens because heat doesn't change the state of nested stacks if size of Autoscaling group has not been changed. So fix allows handle_update in AWS::AutoscalingGroup to launch resize despite of changes in AG capacity. Change-Id: Ibb71f31f2ec7d1d37b995323a2474b799ea498bb Closes-bug: #1429134 --- .../aws/autoscaling/autoscaling_group.py | 5 --- .../autoscaling/test_heat_scaling_group.py | 30 ++++++++++++++++ heat/tests/autoscaling/test_scaling_group.py | 30 ++++++++++++++++ .../functional/test_heat_autoscaling.py | 36 +++++++++++++++++++ 4 files changed, 96 insertions(+), 5 deletions(-) diff --git a/heat/engine/resources/aws/autoscaling/autoscaling_group.py b/heat/engine/resources/aws/autoscaling/autoscaling_group.py index a46902250..017e41eb9 100644 --- a/heat/engine/resources/aws/autoscaling/autoscaling_group.py +++ b/heat/engine/resources/aws/autoscaling/autoscaling_group.py @@ -310,11 +310,6 @@ class AutoScalingGroup(instgrp.InstanceGroup, cooldown.CooldownMixin): new_capacity = _calculate_new_capacity(capacity, adjustment, adjustment_type, lower, upper) - total = grouputils.get_size(self, include_failed=True) - # if there are failed resources in nested_stack, has to change - if new_capacity == total: - LOG.debug('no change in capacity %d' % capacity) - return # send a notification before, on-error and on-success. notif = { diff --git a/heat/tests/autoscaling/test_heat_scaling_group.py b/heat/tests/autoscaling/test_heat_scaling_group.py index aacf8fbba..1ca6e8e1f 100644 --- a/heat/tests/autoscaling/test_heat_scaling_group.py +++ b/heat/tests/autoscaling/test_heat_scaling_group.py @@ -137,6 +137,36 @@ class TestGroupAdjust(common.HeatTestCase): self.group.adjust(1) self.assertEqual([], dont_call.call_args_list) + def test_scaling_same_capacity(self): + """Alway resize even if the capacity is the same.""" + self.patchobject(grouputils, 'get_size', return_value=3) + resize = self.patchobject(self.group, 'resize') + cd_stamp = self.patchobject(self.group, '_cooldown_timestamp') + notify = self.patch('heat.engine.notification.autoscaling.send') + self.patchobject(self.group, '_cooldown_inprogress', + return_value=False) + self.group.adjust(3, adjustment_type='ExactCapacity') + + expected_notifies = [ + mock.call( + capacity=3, suffix='start', + adjustment_type='ExactCapacity', + groupname=u'my-group', + message=u'Start resizing the group my-group', + adjustment=3, + stack=self.group.stack), + mock.call( + capacity=3, suffix='end', + adjustment_type='ExactCapacity', + groupname=u'my-group', + message=u'End resizing the group my-group', + adjustment=3, + stack=self.group.stack)] + + self.assertEqual(expected_notifies, notify.call_args_list) + resize.assert_called_once_with(3) + cd_stamp.assert_called_once_with('ExactCapacity : 3') + def test_scaling_policy_cooldown_ok(self): self.patchobject(grouputils, 'get_members', return_value=[]) resize = self.patchobject(self.group, 'resize') diff --git a/heat/tests/autoscaling/test_scaling_group.py b/heat/tests/autoscaling/test_scaling_group.py index c1909c997..89217cd8a 100644 --- a/heat/tests/autoscaling/test_scaling_group.py +++ b/heat/tests/autoscaling/test_scaling_group.py @@ -316,6 +316,36 @@ class TestGroupAdjust(common.HeatTestCase): self.group.adjust(1) self.assertEqual([], dont_call.call_args_list) + def test_scaling_same_capacity(self): + """Alway resize even if the capacity is the same.""" + self.patchobject(grouputils, 'get_size', return_value=3) + resize = self.patchobject(self.group, 'resize') + cd_stamp = self.patchobject(self.group, '_cooldown_timestamp') + notify = self.patch('heat.engine.notification.autoscaling.send') + self.patchobject(self.group, '_cooldown_inprogress', + return_value=False) + self.group.adjust(3, adjustment_type='ExactCapacity') + + expected_notifies = [ + mock.call( + capacity=3, suffix='start', + adjustment_type='ExactCapacity', + groupname=u'WebServerGroup', + message=u'Start resizing the group WebServerGroup', + adjustment=3, + stack=self.group.stack), + mock.call( + capacity=3, suffix='end', + adjustment_type='ExactCapacity', + groupname=u'WebServerGroup', + message=u'End resizing the group WebServerGroup', + adjustment=3, + stack=self.group.stack)] + + self.assertEqual(expected_notifies, notify.call_args_list) + resize.assert_called_once_with(3) + cd_stamp.assert_called_once_with('ExactCapacity : 3') + def test_scaling_policy_cooldown_ok(self): self.patchobject(grouputils, 'get_members', return_value=[]) resize = self.patchobject(self.group, 'resize') diff --git a/heat_integrationtests/functional/test_heat_autoscaling.py b/heat_integrationtests/functional/test_heat_autoscaling.py index 340038c85..0e6e0cb6e 100644 --- a/heat_integrationtests/functional/test_heat_autoscaling.py +++ b/heat_integrationtests/functional/test_heat_autoscaling.py @@ -97,3 +97,39 @@ outputs: expected_resources = {'random_group': 'OS::Heat::AutoScalingGroup'} self.assertEqual(expected_resources, self.list_resources(stack_id)) self._assert_output_values(stack_id) + + +class AutoScalingGroupUpdateWithNoChanges(test.HeatIntegrationTest): + + template = ''' +heat_template_version: 2013-05-23 + +resources: + test_group: + type: OS::Heat::AutoScalingGroup + properties: + desired_capacity: 0 + max_size: 0 + min_size: 0 + resource: + type: OS::Heat::RandomString + test_policy: + type: OS::Heat::ScalingPolicy + properties: + adjustment_type: change_in_capacity + auto_scaling_group_id: { get_resource: test_group } + scaling_adjustment: 1 +''' + + def setUp(self): + super(AutoScalingGroupUpdateWithNoChanges, self).setUp() + self.client = self.orchestration_client + + def test_as_group_update_without_resource_changes(self): + stack_identifier = self.stack_create(template=self.template) + new_template = self.template.replace( + 'scaling_adjustment: 1', + 'scaling_adjustment: 2') + + self.update_stack(stack_identifier, template=new_template) + self._wait_for_stack_status(stack_identifier, 'UPDATE_COMPLETE')