Implement enter_standby, exit_standby and terminate_instance_in_auto_scaling_group
This commit is contained in:
parent
755a08e137
commit
d745dfd3d2
@ -267,6 +267,9 @@ class FakeAutoScalingGroup(BaseModel):
|
||||
self.tags = tags if tags else []
|
||||
self.set_desired_capacity(desired_capacity)
|
||||
|
||||
def active_instances(self):
|
||||
return [x for x in self.instance_states if x.lifecycle_state == "InService"]
|
||||
|
||||
def _set_azs_and_vpcs(self, availability_zones, vpc_zone_identifier, update=False):
|
||||
# for updates, if only AZs are provided, they must not clash with
|
||||
# the AZs of existing VPCs
|
||||
@ -413,9 +416,11 @@ class FakeAutoScalingGroup(BaseModel):
|
||||
else:
|
||||
self.desired_capacity = new_capacity
|
||||
|
||||
curr_instance_count = len(self.instance_states)
|
||||
curr_instance_count = len(self.active_instances())
|
||||
|
||||
if self.desired_capacity == curr_instance_count:
|
||||
self.autoscaling_backend.update_attached_elbs(self.name)
|
||||
self.autoscaling_backend.update_attached_target_groups(self.name)
|
||||
return
|
||||
|
||||
if self.desired_capacity > curr_instance_count:
|
||||
@ -442,6 +447,8 @@ class FakeAutoScalingGroup(BaseModel):
|
||||
self.instance_states = list(
|
||||
set(self.instance_states) - set(instances_to_remove)
|
||||
)
|
||||
self.autoscaling_backend.update_attached_elbs(self.name)
|
||||
self.autoscaling_backend.update_attached_target_groups(self.name)
|
||||
|
||||
def get_propagated_tags(self):
|
||||
propagated_tags = {}
|
||||
@ -703,7 +710,7 @@ class AutoScalingBackend(BaseBackend):
|
||||
|
||||
def detach_instances(self, group_name, instance_ids, should_decrement):
|
||||
group = self.autoscaling_groups[group_name]
|
||||
original_size = len(group.instance_states)
|
||||
original_size = group.desired_capacity
|
||||
|
||||
detached_instances = [
|
||||
x for x in group.instance_states if x.instance.id in instance_ids
|
||||
@ -720,13 +727,8 @@ class AutoScalingBackend(BaseBackend):
|
||||
|
||||
if should_decrement:
|
||||
group.desired_capacity = original_size - len(instance_ids)
|
||||
else:
|
||||
count_needed = len(instance_ids)
|
||||
group.replace_autoscaling_group_instances(
|
||||
count_needed, group.get_propagated_tags()
|
||||
)
|
||||
|
||||
self.update_attached_elbs(group_name)
|
||||
group.set_desired_capacity(group.desired_capacity)
|
||||
return detached_instances
|
||||
|
||||
def set_desired_capacity(self, group_name, desired_capacity):
|
||||
@ -791,7 +793,9 @@ class AutoScalingBackend(BaseBackend):
|
||||
|
||||
def update_attached_elbs(self, group_name):
|
||||
group = self.autoscaling_groups[group_name]
|
||||
group_instance_ids = set(state.instance.id for state in group.instance_states)
|
||||
group_instance_ids = set(
|
||||
state.instance.id for state in group.active_instances()
|
||||
)
|
||||
|
||||
# skip this if group.load_balancers is empty
|
||||
# otherwise elb_backend.describe_load_balancers returns all available load balancers
|
||||
@ -908,15 +912,15 @@ class AutoScalingBackend(BaseBackend):
|
||||
autoscaling_group_name,
|
||||
autoscaling_group,
|
||||
) in self.autoscaling_groups.items():
|
||||
original_instance_count = len(autoscaling_group.instance_states)
|
||||
original_active_instance_count = len(autoscaling_group.active_instances())
|
||||
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
|
||||
difference = original_active_instance_count - len(
|
||||
autoscaling_group.active_instances()
|
||||
)
|
||||
if difference > 0:
|
||||
autoscaling_group.replace_autoscaling_group_instances(
|
||||
@ -924,6 +928,45 @@ class AutoScalingBackend(BaseBackend):
|
||||
)
|
||||
self.update_attached_elbs(autoscaling_group_name)
|
||||
|
||||
def enter_standby_instances(self, group_name, instance_ids, should_decrement):
|
||||
group = self.autoscaling_groups[group_name]
|
||||
original_size = group.desired_capacity
|
||||
standby_instances = []
|
||||
for instance_state in group.instance_states:
|
||||
if instance_state.instance.id in instance_ids:
|
||||
instance_state.lifecycle_state = "Standby"
|
||||
standby_instances.append(instance_state)
|
||||
if should_decrement:
|
||||
group.desired_capacity = group.desired_capacity - len(instance_ids)
|
||||
else:
|
||||
group.set_desired_capacity(group.desired_capacity)
|
||||
return standby_instances, original_size, group.desired_capacity
|
||||
|
||||
def exit_standby_instances(self, group_name, instance_ids):
|
||||
group = self.autoscaling_groups[group_name]
|
||||
original_size = group.desired_capacity
|
||||
standby_instances = []
|
||||
for instance_state in group.instance_states:
|
||||
if instance_state.instance.id in instance_ids:
|
||||
instance_state.lifecycle_state = "InService"
|
||||
standby_instances.append(instance_state)
|
||||
group.desired_capacity = group.desired_capacity + len(instance_ids)
|
||||
return standby_instances, original_size, group.desired_capacity
|
||||
|
||||
def terminate_instance(self, instance_id, should_decrement):
|
||||
instance = self.ec2_backend.get_instance(instance_id)
|
||||
instance_state = next(
|
||||
instance_state
|
||||
for group in self.autoscaling_groups.values()
|
||||
for instance_state in group.instance_states
|
||||
if instance_state.instance.id == instance.id
|
||||
)
|
||||
group = instance.autoscaling_group
|
||||
original_size = group.desired_capacity
|
||||
self.detach_instances(group.name, [instance.id], should_decrement)
|
||||
self.ec2_backend.terminate_instances([instance.id])
|
||||
return instance_state, original_size, group.desired_capacity
|
||||
|
||||
|
||||
autoscaling_backends = {}
|
||||
for region, ec2_backend in ec2_backends.items():
|
||||
|
@ -1,7 +1,12 @@
|
||||
from __future__ import unicode_literals
|
||||
import datetime
|
||||
|
||||
from moto.core.responses import BaseResponse
|
||||
from moto.core.utils import amz_crc32, amzn_request_id
|
||||
from moto.core.utils import (
|
||||
amz_crc32,
|
||||
amzn_request_id,
|
||||
iso_8601_datetime_with_milliseconds,
|
||||
)
|
||||
from .models import autoscaling_backends
|
||||
|
||||
|
||||
@ -291,6 +296,50 @@ class AutoScalingResponse(BaseResponse):
|
||||
template = self.response_template(DETACH_LOAD_BALANCERS_TEMPLATE)
|
||||
return template.render()
|
||||
|
||||
@amz_crc32
|
||||
@amzn_request_id
|
||||
def enter_standby(self):
|
||||
group_name = self._get_param("AutoScalingGroupName")
|
||||
instance_ids = self._get_multi_param("InstanceIds.member")
|
||||
should_decrement_string = self._get_param("ShouldDecrementDesiredCapacity")
|
||||
if should_decrement_string == "true":
|
||||
should_decrement = True
|
||||
else:
|
||||
should_decrement = False
|
||||
(
|
||||
standby_instances,
|
||||
original_size,
|
||||
desired_capacity,
|
||||
) = self.autoscaling_backend.enter_standby_instances(
|
||||
group_name, instance_ids, should_decrement
|
||||
)
|
||||
template = self.response_template(ENTER_STANDBY_TEMPLATE)
|
||||
return template.render(
|
||||
standby_instances=standby_instances,
|
||||
should_decrement=should_decrement,
|
||||
original_size=original_size,
|
||||
desired_capacity=desired_capacity,
|
||||
timestamp=iso_8601_datetime_with_milliseconds(datetime.datetime.utcnow()),
|
||||
)
|
||||
|
||||
@amz_crc32
|
||||
@amzn_request_id
|
||||
def exit_standby(self):
|
||||
group_name = self._get_param("AutoScalingGroupName")
|
||||
instance_ids = self._get_multi_param("InstanceIds.member")
|
||||
(
|
||||
standby_instances,
|
||||
original_size,
|
||||
desired_capacity,
|
||||
) = self.autoscaling_backend.exit_standby_instances(group_name, instance_ids)
|
||||
template = self.response_template(EXIT_STANDBY_TEMPLATE)
|
||||
return template.render(
|
||||
standby_instances=standby_instances,
|
||||
original_size=original_size,
|
||||
desired_capacity=desired_capacity,
|
||||
timestamp=iso_8601_datetime_with_milliseconds(datetime.datetime.utcnow()),
|
||||
)
|
||||
|
||||
def suspend_processes(self):
|
||||
autoscaling_group_name = self._get_param("AutoScalingGroupName")
|
||||
scaling_processes = self._get_multi_param("ScalingProcesses.member")
|
||||
@ -310,6 +359,29 @@ class AutoScalingResponse(BaseResponse):
|
||||
template = self.response_template(SET_INSTANCE_PROTECTION_TEMPLATE)
|
||||
return template.render()
|
||||
|
||||
@amz_crc32
|
||||
@amzn_request_id
|
||||
def terminate_instance_in_auto_scaling_group(self):
|
||||
instance_id = self._get_param("InstanceId")
|
||||
should_decrement_string = self._get_param("ShouldDecrementDesiredCapacity")
|
||||
if should_decrement_string == "true":
|
||||
should_decrement = True
|
||||
else:
|
||||
should_decrement = False
|
||||
(
|
||||
instance,
|
||||
original_size,
|
||||
desired_capacity,
|
||||
) = self.autoscaling_backend.terminate_instance(instance_id, should_decrement)
|
||||
template = self.response_template(TERMINATE_INSTANCES_TEMPLATE)
|
||||
return template.render(
|
||||
instance=instance,
|
||||
should_decrement=should_decrement,
|
||||
original_size=original_size,
|
||||
desired_capacity=desired_capacity,
|
||||
timestamp=iso_8601_datetime_with_milliseconds(datetime.datetime.utcnow()),
|
||||
)
|
||||
|
||||
|
||||
CREATE_LAUNCH_CONFIGURATION_TEMPLATE = """<CreateLaunchConfigurationResponse xmlns="http://autoscaling.amazonaws.com/doc/2011-01-01/">
|
||||
<ResponseMetadata>
|
||||
@ -707,3 +779,73 @@ SET_INSTANCE_PROTECTION_TEMPLATE = """<SetInstanceProtectionResponse xmlns="http
|
||||
<RequestId></RequestId>
|
||||
</ResponseMetadata>
|
||||
</SetInstanceProtectionResponse>"""
|
||||
|
||||
ENTER_STANDBY_TEMPLATE = """<EnterStandbyResponse xmlns="http://autoscaling.amazonaws.com/doc/2011-01-01/">
|
||||
<EnterStandbyResult>
|
||||
<Activities>
|
||||
{% for instance in standby_instances %}
|
||||
<member>
|
||||
<ActivityId>12345678-1234-1234-1234-123456789012</ActivityId>
|
||||
<AutoScalingGroupName>{{ group_name }}</AutoScalingGroupName>
|
||||
{% if should_decrement %}
|
||||
<Cause>At {{ timestamp }} instance {{ instance.instance.id }} was moved to standby in response to a user request, shrinking the capacity from {{ original_size }} to {{ desired_capacity }}.</Cause>
|
||||
{% else %}
|
||||
<Cause>At {{ timestamp }} instance {{ instance.instance.id }} was moved to standby in response to a user request.</Cause>
|
||||
{% endif %}
|
||||
<Description>Moving EC2 instance to Standby: {{ instance.instance.id }}</Description>
|
||||
<Progress>50</Progress>
|
||||
<StartTime>{{ timestamp }}</StartTime>
|
||||
<Details>{"Subnet ID":"??","Availability Zone":"{{ instance.instance.placement }}"}</Details>
|
||||
<StatusCode>InProgress</StatusCode>
|
||||
</member>
|
||||
{% endfor %}
|
||||
</Activities>
|
||||
</EnterStandbyResult>
|
||||
<ResponseMetadata>
|
||||
<RequestId>7c6e177f-f082-11e1-ac58-3714bEXAMPLE</RequestId>
|
||||
</ResponseMetadata>
|
||||
</EnterStandbyResponse>"""
|
||||
|
||||
EXIT_STANDBY_TEMPLATE = """<ExitStandbyResponse xmlns="http://autoscaling.amazonaws.com/doc/2011-01-01/">
|
||||
<ExitStandbyResult>
|
||||
<Activities>
|
||||
{% for instance in standby_instances %}
|
||||
<member>
|
||||
<ActivityId>12345678-1234-1234-1234-123456789012</ActivityId>
|
||||
<AutoScalingGroupName>{{ group_name }}</AutoScalingGroupName>
|
||||
<Description>Moving EC2 instance out of Standby: {{ instance.instance.id }}</Description>
|
||||
<Progress>30</Progress>
|
||||
<Cause>At {{ timestamp }} instance {{ instance.instance.id }} was moved out of standby in response to a user request, increasing the capacity from {{ original_size }} to {{ desired_capacity }}.</Cause>
|
||||
<StartTime>{{ timestamp }}</StartTime>
|
||||
<Details>{"Subnet ID":"??","Availability Zone":"{{ instance.instance.placement }}"}</Details>
|
||||
<StatusCode>PreInService</StatusCode>
|
||||
</member>
|
||||
{% endfor %}
|
||||
</Activities>
|
||||
</ExitStandbyResult>
|
||||
<ResponseMetadata>
|
||||
<RequestId>7c6e177f-f082-11e1-ac58-3714bEXAMPLE</RequestId>
|
||||
</ResponseMetadata>
|
||||
</ExitStandbyResponse>"""
|
||||
|
||||
TERMINATE_INSTANCES_TEMPLATE = """<TerminateInstanceInAutoScalingGroupResponse xmlns="http://autoscaling.amazonaws.com/doc/2011-01-01/">
|
||||
<TerminateInstanceInAutoScalingGroupResult>
|
||||
<Activity>
|
||||
<ActivityId>35b5c464-0b63-2fc7-1611-467d4a7f2497EXAMPLE</ActivityId>
|
||||
<AutoScalingGroupName>{{ group_name }}</AutoScalingGroupName>
|
||||
{% if should_decrement %}
|
||||
<Cause>At {{ timestamp }} instance {{ instance.instance.id }} was taken out of service in response to a user request, shrinking the capacity from {{ original_size }} to {{ desired_capacity }}.</Cause>
|
||||
{% else %}
|
||||
<Cause>At {{ timestamp }} instance {{ instance.instance.id }} was taken out of service in response to a user request.</Cause>
|
||||
{% endif %}
|
||||
<Description>Terminating EC2 instance: {{ instance.instance.id }}</Description>
|
||||
<Progress>0</Progress>
|
||||
<StartTime>{{ timestamp }}</StartTime>
|
||||
<Details>{"Subnet ID":"??","Availability Zone":"{{ instance.instance.placement }}"}</Details>
|
||||
<StatusCode>InProgress</StatusCode>
|
||||
</Activity>
|
||||
</TerminateInstanceInAutoScalingGroupResult>
|
||||
<ResponseMetadata>
|
||||
<RequestId>a1ba8fb9-31d6-4d9a-ace1-a7f76749df11EXAMPLE</RequestId>
|
||||
</ResponseMetadata>
|
||||
</TerminateInstanceInAutoScalingGroupResponse>"""
|
||||
|
@ -1102,8 +1102,6 @@ def test_detach_one_instance_decrement():
|
||||
|
||||
ec2_client = boto3.client("ec2", region_name="us-east-1")
|
||||
|
||||
response = ec2_client.describe_instances(InstanceIds=[instance_to_detach])
|
||||
|
||||
response = client.detach_instances(
|
||||
AutoScalingGroupName="test_asg",
|
||||
InstanceIds=[instance_to_detach],
|
||||
@ -1156,8 +1154,6 @@ def test_detach_one_instance():
|
||||
|
||||
ec2_client = boto3.client("ec2", region_name="us-east-1")
|
||||
|
||||
response = ec2_client.describe_instances(InstanceIds=[instance_to_detach])
|
||||
|
||||
response = client.detach_instances(
|
||||
AutoScalingGroupName="test_asg",
|
||||
InstanceIds=[instance_to_detach],
|
||||
@ -1178,6 +1174,516 @@ def test_detach_one_instance():
|
||||
tags.should.have.length_of(2)
|
||||
|
||||
|
||||
@mock_autoscaling
|
||||
@mock_ec2
|
||||
def test_standby_one_instance_decrement():
|
||||
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=0,
|
||||
MaxSize=2,
|
||||
DesiredCapacity=2,
|
||||
Tags=[
|
||||
{
|
||||
"ResourceId": "test_asg",
|
||||
"ResourceType": "auto-scaling-group",
|
||||
"Key": "propogated-tag-key",
|
||||
"Value": "propagate-tag-value",
|
||||
"PropagateAtLaunch": True,
|
||||
}
|
||||
],
|
||||
VPCZoneIdentifier=mocked_networking["subnet1"],
|
||||
)
|
||||
response = client.describe_auto_scaling_groups(AutoScalingGroupNames=["test_asg"])
|
||||
instance_to_standby = response["AutoScalingGroups"][0]["Instances"][0]["InstanceId"]
|
||||
instance_to_keep = response["AutoScalingGroups"][0]["Instances"][1]["InstanceId"]
|
||||
|
||||
ec2_client = boto3.client("ec2", region_name="us-east-1")
|
||||
|
||||
response = client.enter_standby(
|
||||
AutoScalingGroupName="test_asg",
|
||||
InstanceIds=[instance_to_standby],
|
||||
ShouldDecrementDesiredCapacity=True,
|
||||
)
|
||||
response["ResponseMetadata"]["HTTPStatusCode"].should.equal(200)
|
||||
|
||||
response = client.describe_auto_scaling_groups(AutoScalingGroupNames=["test_asg"])
|
||||
response["AutoScalingGroups"][0]["Instances"].should.have.length_of(2)
|
||||
response["AutoScalingGroups"][0]["DesiredCapacity"].should.equal(1)
|
||||
|
||||
response = client.describe_auto_scaling_instances(InstanceIds=[instance_to_standby])
|
||||
response["AutoScalingInstances"][0]["LifecycleState"].should.equal("Standby")
|
||||
|
||||
# test to ensure tag has been retained (standby instance is still part of the ASG)
|
||||
response = ec2_client.describe_instances()
|
||||
for reservation in response["Reservations"]:
|
||||
for instance in reservation["Instances"]:
|
||||
tags = instance["Tags"]
|
||||
tags.should.have.length_of(2)
|
||||
|
||||
|
||||
@mock_autoscaling
|
||||
@mock_ec2
|
||||
def test_standby_one_instance():
|
||||
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=0,
|
||||
MaxSize=2,
|
||||
DesiredCapacity=2,
|
||||
Tags=[
|
||||
{
|
||||
"ResourceId": "test_asg",
|
||||
"ResourceType": "auto-scaling-group",
|
||||
"Key": "propogated-tag-key",
|
||||
"Value": "propagate-tag-value",
|
||||
"PropagateAtLaunch": True,
|
||||
}
|
||||
],
|
||||
VPCZoneIdentifier=mocked_networking["subnet1"],
|
||||
)
|
||||
response = client.describe_auto_scaling_groups(AutoScalingGroupNames=["test_asg"])
|
||||
instance_to_standby = response["AutoScalingGroups"][0]["Instances"][0]["InstanceId"]
|
||||
instance_to_keep = response["AutoScalingGroups"][0]["Instances"][1]["InstanceId"]
|
||||
|
||||
ec2_client = boto3.client("ec2", region_name="us-east-1")
|
||||
|
||||
response = client.enter_standby(
|
||||
AutoScalingGroupName="test_asg",
|
||||
InstanceIds=[instance_to_standby],
|
||||
ShouldDecrementDesiredCapacity=False,
|
||||
)
|
||||
response["ResponseMetadata"]["HTTPStatusCode"].should.equal(200)
|
||||
|
||||
response = client.describe_auto_scaling_groups(AutoScalingGroupNames=["test_asg"])
|
||||
response["AutoScalingGroups"][0]["Instances"].should.have.length_of(3)
|
||||
response["AutoScalingGroups"][0]["DesiredCapacity"].should.equal(2)
|
||||
|
||||
response = client.describe_auto_scaling_instances(InstanceIds=[instance_to_standby])
|
||||
response["AutoScalingInstances"][0]["LifecycleState"].should.equal("Standby")
|
||||
|
||||
# test to ensure tag has been retained (standby instance is still part of the ASG)
|
||||
response = ec2_client.describe_instances()
|
||||
for reservation in response["Reservations"]:
|
||||
for instance in reservation["Instances"]:
|
||||
tags = instance["Tags"]
|
||||
tags.should.have.length_of(2)
|
||||
|
||||
|
||||
@mock_elb
|
||||
@mock_autoscaling
|
||||
@mock_ec2
|
||||
def test_standby_elb_update():
|
||||
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=0,
|
||||
MaxSize=2,
|
||||
DesiredCapacity=2,
|
||||
Tags=[
|
||||
{
|
||||
"ResourceId": "test_asg",
|
||||
"ResourceType": "auto-scaling-group",
|
||||
"Key": "propogated-tag-key",
|
||||
"Value": "propagate-tag-value",
|
||||
"PropagateAtLaunch": True,
|
||||
}
|
||||
],
|
||||
VPCZoneIdentifier=mocked_networking["subnet1"],
|
||||
)
|
||||
|
||||
elb_client = boto3.client("elb", region_name="us-east-1")
|
||||
elb_client.create_load_balancer(
|
||||
LoadBalancerName="my-lb",
|
||||
Listeners=[{"Protocol": "tcp", "LoadBalancerPort": 80, "InstancePort": 8080}],
|
||||
AvailabilityZones=["us-east-1a", "us-east-1b"],
|
||||
)
|
||||
|
||||
response = client.attach_load_balancers(
|
||||
AutoScalingGroupName="test_asg", LoadBalancerNames=["my-lb"]
|
||||
)
|
||||
response["ResponseMetadata"]["HTTPStatusCode"].should.equal(200)
|
||||
|
||||
response = client.describe_auto_scaling_groups(AutoScalingGroupNames=["test_asg"])
|
||||
instance_to_standby = response["AutoScalingGroups"][0]["Instances"][0]["InstanceId"]
|
||||
|
||||
response = client.enter_standby(
|
||||
AutoScalingGroupName="test_asg",
|
||||
InstanceIds=[instance_to_standby],
|
||||
ShouldDecrementDesiredCapacity=False,
|
||||
)
|
||||
response["ResponseMetadata"]["HTTPStatusCode"].should.equal(200)
|
||||
|
||||
response = client.describe_auto_scaling_groups(AutoScalingGroupNames=["test_asg"])
|
||||
response["AutoScalingGroups"][0]["Instances"].should.have.length_of(3)
|
||||
response["AutoScalingGroups"][0]["DesiredCapacity"].should.equal(2)
|
||||
|
||||
response = client.describe_auto_scaling_instances(InstanceIds=[instance_to_standby])
|
||||
response["AutoScalingInstances"][0]["LifecycleState"].should.equal("Standby")
|
||||
|
||||
response = elb_client.describe_load_balancers(LoadBalancerNames=["my-lb"])
|
||||
list(response["LoadBalancerDescriptions"][0]["Instances"]).should.have.length_of(2)
|
||||
|
||||
|
||||
@mock_autoscaling
|
||||
@mock_ec2
|
||||
def test_standby_terminate_instance_decrement():
|
||||
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=0,
|
||||
MaxSize=3,
|
||||
DesiredCapacity=2,
|
||||
Tags=[
|
||||
{
|
||||
"ResourceId": "test_asg",
|
||||
"ResourceType": "auto-scaling-group",
|
||||
"Key": "propogated-tag-key",
|
||||
"Value": "propagate-tag-value",
|
||||
"PropagateAtLaunch": True,
|
||||
}
|
||||
],
|
||||
VPCZoneIdentifier=mocked_networking["subnet1"],
|
||||
)
|
||||
|
||||
response = client.describe_auto_scaling_groups(AutoScalingGroupNames=["test_asg"])
|
||||
instance_to_standby_terminate = response["AutoScalingGroups"][0]["Instances"][0][
|
||||
"InstanceId"
|
||||
]
|
||||
|
||||
ec2_client = boto3.client("ec2", region_name="us-east-1")
|
||||
|
||||
response = client.enter_standby(
|
||||
AutoScalingGroupName="test_asg",
|
||||
InstanceIds=[instance_to_standby_terminate],
|
||||
ShouldDecrementDesiredCapacity=False,
|
||||
)
|
||||
response["ResponseMetadata"]["HTTPStatusCode"].should.equal(200)
|
||||
|
||||
response = client.describe_auto_scaling_groups(AutoScalingGroupNames=["test_asg"])
|
||||
response["AutoScalingGroups"][0]["Instances"].should.have.length_of(3)
|
||||
response["AutoScalingGroups"][0]["DesiredCapacity"].should.equal(2)
|
||||
|
||||
response = client.describe_auto_scaling_instances(
|
||||
InstanceIds=[instance_to_standby_terminate]
|
||||
)
|
||||
response["AutoScalingInstances"][0]["LifecycleState"].should.equal("Standby")
|
||||
|
||||
response = client.terminate_instance_in_auto_scaling_group(
|
||||
InstanceId=instance_to_standby_terminate, ShouldDecrementDesiredCapacity=True
|
||||
)
|
||||
response["ResponseMetadata"]["HTTPStatusCode"].should.equal(200)
|
||||
|
||||
# AWS still decrements desired capacity ASG if requested, even if the terminated instance is in standby
|
||||
response = client.describe_auto_scaling_groups(AutoScalingGroupNames=["test_asg"])
|
||||
response["AutoScalingGroups"][0]["Instances"].should.have.length_of(1)
|
||||
response["AutoScalingGroups"][0]["Instances"][0]["InstanceId"].should_not.equal(
|
||||
instance_to_standby_terminate
|
||||
)
|
||||
response["AutoScalingGroups"][0]["DesiredCapacity"].should.equal(1)
|
||||
|
||||
response = ec2_client.describe_instances(
|
||||
InstanceIds=[instance_to_standby_terminate]
|
||||
)
|
||||
response["Reservations"][0]["Instances"][0]["State"]["Name"].should.equal(
|
||||
"terminated"
|
||||
)
|
||||
|
||||
|
||||
@mock_autoscaling
|
||||
@mock_ec2
|
||||
def test_standby_terminate_instance_no_decrement():
|
||||
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=0,
|
||||
MaxSize=3,
|
||||
DesiredCapacity=2,
|
||||
Tags=[
|
||||
{
|
||||
"ResourceId": "test_asg",
|
||||
"ResourceType": "auto-scaling-group",
|
||||
"Key": "propogated-tag-key",
|
||||
"Value": "propagate-tag-value",
|
||||
"PropagateAtLaunch": True,
|
||||
}
|
||||
],
|
||||
VPCZoneIdentifier=mocked_networking["subnet1"],
|
||||
)
|
||||
|
||||
response = client.describe_auto_scaling_groups(AutoScalingGroupNames=["test_asg"])
|
||||
instance_to_standby_terminate = response["AutoScalingGroups"][0]["Instances"][0][
|
||||
"InstanceId"
|
||||
]
|
||||
|
||||
ec2_client = boto3.client("ec2", region_name="us-east-1")
|
||||
|
||||
response = client.enter_standby(
|
||||
AutoScalingGroupName="test_asg",
|
||||
InstanceIds=[instance_to_standby_terminate],
|
||||
ShouldDecrementDesiredCapacity=False,
|
||||
)
|
||||
response["ResponseMetadata"]["HTTPStatusCode"].should.equal(200)
|
||||
|
||||
response = client.describe_auto_scaling_groups(AutoScalingGroupNames=["test_asg"])
|
||||
response["AutoScalingGroups"][0]["Instances"].should.have.length_of(3)
|
||||
response["AutoScalingGroups"][0]["DesiredCapacity"].should.equal(2)
|
||||
|
||||
response = client.describe_auto_scaling_instances(
|
||||
InstanceIds=[instance_to_standby_terminate]
|
||||
)
|
||||
response["AutoScalingInstances"][0]["LifecycleState"].should.equal("Standby")
|
||||
|
||||
response = client.terminate_instance_in_auto_scaling_group(
|
||||
InstanceId=instance_to_standby_terminate, ShouldDecrementDesiredCapacity=False
|
||||
)
|
||||
response["ResponseMetadata"]["HTTPStatusCode"].should.equal(200)
|
||||
|
||||
response = client.describe_auto_scaling_groups(AutoScalingGroupNames=["test_asg"])
|
||||
group = response["AutoScalingGroups"][0]
|
||||
group["Instances"].should.have.length_of(2)
|
||||
instance_to_standby_terminate.shouldnt.be.within(
|
||||
[x["InstanceId"] for x in group["Instances"]]
|
||||
)
|
||||
group["DesiredCapacity"].should.equal(2)
|
||||
|
||||
response = ec2_client.describe_instances(
|
||||
InstanceIds=[instance_to_standby_terminate]
|
||||
)
|
||||
response["Reservations"][0]["Instances"][0]["State"]["Name"].should.equal(
|
||||
"terminated"
|
||||
)
|
||||
|
||||
|
||||
@mock_autoscaling
|
||||
@mock_ec2
|
||||
def test_standby_detach_instance_decrement():
|
||||
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=0,
|
||||
MaxSize=3,
|
||||
DesiredCapacity=2,
|
||||
Tags=[
|
||||
{
|
||||
"ResourceId": "test_asg",
|
||||
"ResourceType": "auto-scaling-group",
|
||||
"Key": "propogated-tag-key",
|
||||
"Value": "propagate-tag-value",
|
||||
"PropagateAtLaunch": True,
|
||||
}
|
||||
],
|
||||
VPCZoneIdentifier=mocked_networking["subnet1"],
|
||||
)
|
||||
|
||||
response = client.describe_auto_scaling_groups(AutoScalingGroupNames=["test_asg"])
|
||||
instance_to_standby_detach = response["AutoScalingGroups"][0]["Instances"][0][
|
||||
"InstanceId"
|
||||
]
|
||||
|
||||
ec2_client = boto3.client("ec2", region_name="us-east-1")
|
||||
|
||||
response = client.enter_standby(
|
||||
AutoScalingGroupName="test_asg",
|
||||
InstanceIds=[instance_to_standby_detach],
|
||||
ShouldDecrementDesiredCapacity=False,
|
||||
)
|
||||
response["ResponseMetadata"]["HTTPStatusCode"].should.equal(200)
|
||||
|
||||
response = client.describe_auto_scaling_groups(AutoScalingGroupNames=["test_asg"])
|
||||
response["AutoScalingGroups"][0]["Instances"].should.have.length_of(3)
|
||||
response["AutoScalingGroups"][0]["DesiredCapacity"].should.equal(2)
|
||||
|
||||
response = client.describe_auto_scaling_instances(
|
||||
InstanceIds=[instance_to_standby_detach]
|
||||
)
|
||||
response["AutoScalingInstances"][0]["LifecycleState"].should.equal("Standby")
|
||||
|
||||
response = client.detach_instances(
|
||||
AutoScalingGroupName="test_asg",
|
||||
InstanceIds=[instance_to_standby_detach],
|
||||
ShouldDecrementDesiredCapacity=True,
|
||||
)
|
||||
response["ResponseMetadata"]["HTTPStatusCode"].should.equal(200)
|
||||
|
||||
# AWS still decrements desired capacity ASG if requested, even if the detached instance was in standby
|
||||
response = client.describe_auto_scaling_groups(AutoScalingGroupNames=["test_asg"])
|
||||
response["AutoScalingGroups"][0]["Instances"].should.have.length_of(1)
|
||||
response["AutoScalingGroups"][0]["Instances"][0]["InstanceId"].should_not.equal(
|
||||
instance_to_standby_detach
|
||||
)
|
||||
response["AutoScalingGroups"][0]["DesiredCapacity"].should.equal(1)
|
||||
|
||||
response = ec2_client.describe_instances(InstanceIds=[instance_to_standby_detach])
|
||||
response["Reservations"][0]["Instances"][0]["State"]["Name"].should.equal("running")
|
||||
|
||||
|
||||
@mock_autoscaling
|
||||
@mock_ec2
|
||||
def test_standby_detach_instance_no_decrement():
|
||||
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=0,
|
||||
MaxSize=3,
|
||||
DesiredCapacity=2,
|
||||
Tags=[
|
||||
{
|
||||
"ResourceId": "test_asg",
|
||||
"ResourceType": "auto-scaling-group",
|
||||
"Key": "propogated-tag-key",
|
||||
"Value": "propagate-tag-value",
|
||||
"PropagateAtLaunch": True,
|
||||
}
|
||||
],
|
||||
VPCZoneIdentifier=mocked_networking["subnet1"],
|
||||
)
|
||||
|
||||
response = client.describe_auto_scaling_groups(AutoScalingGroupNames=["test_asg"])
|
||||
instance_to_standby_detach = response["AutoScalingGroups"][0]["Instances"][0][
|
||||
"InstanceId"
|
||||
]
|
||||
|
||||
ec2_client = boto3.client("ec2", region_name="us-east-1")
|
||||
|
||||
response = client.enter_standby(
|
||||
AutoScalingGroupName="test_asg",
|
||||
InstanceIds=[instance_to_standby_detach],
|
||||
ShouldDecrementDesiredCapacity=False,
|
||||
)
|
||||
response["ResponseMetadata"]["HTTPStatusCode"].should.equal(200)
|
||||
|
||||
response = client.describe_auto_scaling_groups(AutoScalingGroupNames=["test_asg"])
|
||||
response["AutoScalingGroups"][0]["Instances"].should.have.length_of(3)
|
||||
response["AutoScalingGroups"][0]["DesiredCapacity"].should.equal(2)
|
||||
|
||||
response = client.describe_auto_scaling_instances(
|
||||
InstanceIds=[instance_to_standby_detach]
|
||||
)
|
||||
response["AutoScalingInstances"][0]["LifecycleState"].should.equal("Standby")
|
||||
|
||||
response = client.detach_instances(
|
||||
AutoScalingGroupName="test_asg",
|
||||
InstanceIds=[instance_to_standby_detach],
|
||||
ShouldDecrementDesiredCapacity=False,
|
||||
)
|
||||
response["ResponseMetadata"]["HTTPStatusCode"].should.equal(200)
|
||||
|
||||
response = client.describe_auto_scaling_groups(AutoScalingGroupNames=["test_asg"])
|
||||
group = response["AutoScalingGroups"][0]
|
||||
group["Instances"].should.have.length_of(2)
|
||||
instance_to_standby_detach.shouldnt.be.within(
|
||||
[x["InstanceId"] for x in group["Instances"]]
|
||||
)
|
||||
group["DesiredCapacity"].should.equal(2)
|
||||
|
||||
response = ec2_client.describe_instances(InstanceIds=[instance_to_standby_detach])
|
||||
response["Reservations"][0]["Instances"][0]["State"]["Name"].should.equal("running")
|
||||
|
||||
|
||||
@mock_autoscaling
|
||||
@mock_ec2
|
||||
def test_standby_exit_standby():
|
||||
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=0,
|
||||
MaxSize=3,
|
||||
DesiredCapacity=2,
|
||||
Tags=[
|
||||
{
|
||||
"ResourceId": "test_asg",
|
||||
"ResourceType": "auto-scaling-group",
|
||||
"Key": "propogated-tag-key",
|
||||
"Value": "propagate-tag-value",
|
||||
"PropagateAtLaunch": True,
|
||||
}
|
||||
],
|
||||
VPCZoneIdentifier=mocked_networking["subnet1"],
|
||||
)
|
||||
|
||||
response = client.describe_auto_scaling_groups(AutoScalingGroupNames=["test_asg"])
|
||||
instance_to_standby_exit_standby = response["AutoScalingGroups"][0]["Instances"][0][
|
||||
"InstanceId"
|
||||
]
|
||||
|
||||
ec2_client = boto3.client("ec2", region_name="us-east-1")
|
||||
|
||||
response = client.enter_standby(
|
||||
AutoScalingGroupName="test_asg",
|
||||
InstanceIds=[instance_to_standby_exit_standby],
|
||||
ShouldDecrementDesiredCapacity=False,
|
||||
)
|
||||
response["ResponseMetadata"]["HTTPStatusCode"].should.equal(200)
|
||||
|
||||
response = client.describe_auto_scaling_groups(AutoScalingGroupNames=["test_asg"])
|
||||
response["AutoScalingGroups"][0]["Instances"].should.have.length_of(3)
|
||||
response["AutoScalingGroups"][0]["DesiredCapacity"].should.equal(2)
|
||||
|
||||
response = client.describe_auto_scaling_instances(
|
||||
InstanceIds=[instance_to_standby_exit_standby]
|
||||
)
|
||||
response["AutoScalingInstances"][0]["LifecycleState"].should.equal("Standby")
|
||||
|
||||
response = client.exit_standby(
|
||||
AutoScalingGroupName="test_asg", InstanceIds=[instance_to_standby_exit_standby],
|
||||
)
|
||||
response["ResponseMetadata"]["HTTPStatusCode"].should.equal(200)
|
||||
|
||||
response = client.describe_auto_scaling_groups(AutoScalingGroupNames=["test_asg"])
|
||||
group = response["AutoScalingGroups"][0]
|
||||
group["Instances"].should.have.length_of(3)
|
||||
instance_to_standby_exit_standby.should.be.within(
|
||||
[x["InstanceId"] for x in group["Instances"]]
|
||||
)
|
||||
group["DesiredCapacity"].should.equal(3)
|
||||
|
||||
response = ec2_client.describe_instances(
|
||||
InstanceIds=[instance_to_standby_exit_standby]
|
||||
)
|
||||
response["Reservations"][0]["Instances"][0]["State"]["Name"].should.equal("running")
|
||||
|
||||
|
||||
@mock_autoscaling
|
||||
@mock_ec2
|
||||
def test_attach_one_instance():
|
||||
@ -1411,7 +1917,7 @@ def test_set_desired_capacity_down_boto3():
|
||||
|
||||
@mock_autoscaling
|
||||
@mock_ec2
|
||||
def test_terminate_instance_in_autoscaling_group():
|
||||
def test_terminate_instance_via_ec2_in_autoscaling_group():
|
||||
mocked_networking = setup_networking()
|
||||
client = boto3.client("autoscaling", region_name="us-east-1")
|
||||
_ = client.create_launch_configuration(
|
||||
@ -1440,3 +1946,71 @@ def test_terminate_instance_in_autoscaling_group():
|
||||
for instance in response["AutoScalingGroups"][0]["Instances"]
|
||||
)
|
||||
replaced_instance_id.should_not.equal(original_instance_id)
|
||||
|
||||
|
||||
@mock_autoscaling
|
||||
@mock_ec2
|
||||
def test_terminate_instance_in_auto_scaling_group_decrement():
|
||||
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=0,
|
||||
DesiredCapacity=1,
|
||||
MaxSize=2,
|
||||
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"]
|
||||
)
|
||||
client.terminate_instance_in_auto_scaling_group(
|
||||
InstanceId=original_instance_id, ShouldDecrementDesiredCapacity=True
|
||||
)
|
||||
|
||||
response = client.describe_auto_scaling_groups(AutoScalingGroupNames=["test_asg"])
|
||||
response["AutoScalingGroups"][0]["Instances"].should.equal([])
|
||||
response["AutoScalingGroups"][0]["DesiredCapacity"].should.equal(0)
|
||||
|
||||
|
||||
@mock_autoscaling
|
||||
@mock_ec2
|
||||
def test_terminate_instance_in_auto_scaling_group_no_decrement():
|
||||
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=0,
|
||||
DesiredCapacity=1,
|
||||
MaxSize=2,
|
||||
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"]
|
||||
)
|
||||
client.terminate_instance_in_auto_scaling_group(
|
||||
InstanceId=original_instance_id, ShouldDecrementDesiredCapacity=False
|
||||
)
|
||||
|
||||
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)
|
||||
response["AutoScalingGroups"][0]["DesiredCapacity"].should.equal(1)
|
||||
|
Loading…
Reference in New Issue
Block a user