diff --git a/moto/autoscaling/models.py b/moto/autoscaling/models.py index 24811be73..83de9712a 100644 --- a/moto/autoscaling/models.py +++ b/moto/autoscaling/models.py @@ -684,6 +684,18 @@ class AutoScalingBackend(BaseBackend): for instance in protected_instances: instance.protected_from_scale_in = protected_from_scale_in + def notify_terminate_instances(self, instance_ids): + for autoscaling_group_name, autoscaling_group in self.autoscaling_groups.items(): + original_instance_count = len(autoscaling_group.instance_states) + autoscaling_group.instance_states = list(filter( + lambda i_state: i_state.instance.id not in instance_ids, + autoscaling_group.instance_states + )) + difference = original_instance_count - len(autoscaling_group.instance_states) + if difference > 0: + autoscaling_group.replace_autoscaling_group_instances(difference, autoscaling_group.get_propagated_tags()) + self.update_attached_elbs(autoscaling_group_name) + autoscaling_backends = {} for region, ec2_backend in ec2_backends.items(): diff --git a/moto/ec2/responses/instances.py b/moto/ec2/responses/instances.py index 3f73d2e94..82c2b1997 100644 --- a/moto/ec2/responses/instances.py +++ b/moto/ec2/responses/instances.py @@ -1,5 +1,7 @@ from __future__ import unicode_literals from boto.ec2.instancetype import InstanceType + +from moto.autoscaling import autoscaling_backends from moto.core.responses import BaseResponse from moto.core.utils import camelcase_to_underscores from moto.ec2.utils import filters_from_querystring, \ @@ -65,6 +67,7 @@ class InstanceResponse(BaseResponse): instance_ids = self._get_multi_param('InstanceId') if self.is_not_dryrun('TerminateInstance'): instances = self.ec2_backend.terminate_instances(instance_ids) + autoscaling_backends[self.region].notify_terminate_instances(instance_ids) template = self.response_template(EC2_TERMINATE_INSTANCES) return template.render(instances=instances) diff --git a/tests/test_autoscaling/test_autoscaling.py b/tests/test_autoscaling/test_autoscaling.py index 750605c07..a0e5c395f 100644 --- a/tests/test_autoscaling/test_autoscaling.py +++ b/tests/test_autoscaling/test_autoscaling.py @@ -1269,3 +1269,36 @@ def test_set_desired_capacity_down_boto3(): instance_ids = {instance['InstanceId'] for instance in group['Instances']} set(protected).should.equal(instance_ids) set(unprotected).should_not.be.within(instance_ids) # only unprotected killed + + +@mock_autoscaling +@mock_ec2 +def test_terminate_instance_in_autoscaling_group(): + mocked_networking = setup_networking() + client = boto3.client('autoscaling', region_name='us-east-1') + _ = client.create_launch_configuration( + LaunchConfigurationName='test_launch_configuration' + ) + _ = client.create_auto_scaling_group( + AutoScalingGroupName='test_asg', + LaunchConfigurationName='test_launch_configuration', + MinSize=1, + MaxSize=20, + VPCZoneIdentifier=mocked_networking['subnet1'], + NewInstancesProtectedFromScaleIn=False + ) + + response = client.describe_auto_scaling_groups(AutoScalingGroupNames=['test_asg']) + original_instance_id = next( + instance['InstanceId'] + for instance in response['AutoScalingGroups'][0]['Instances'] + ) + ec2_client = boto3.client('ec2', region_name='us-east-1') + ec2_client.terminate_instances(InstanceIds=[original_instance_id]) + + response = client.describe_auto_scaling_groups(AutoScalingGroupNames=['test_asg']) + replaced_instance_id = next( + instance['InstanceId'] + for instance in response['AutoScalingGroups'][0]['Instances'] + ) + replaced_instance_id.should_not.equal(original_instance_id)