Implement enter_standby, exit_standby and terminate_instance_in_auto_scaling_group
This commit is contained in:
parent
755a08e137
commit
d745dfd3d2
3 changed files with 777 additions and 18 deletions
|
|
@ -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>"""
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue