Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add instance scale-in protection to Auto Scaling #2207

Open
wants to merge 15 commits into
base: main
Choose a base branch
from
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
minor_changes:
- autoscaling_group: Added a boolean parameter `protected_from_scale_in` to toggle protection from scale-in. This allows users to enable or disable scale-in protection for instances in an autoscaling group. (https://github.com/ansible-collections/amazon.aws/pull/2207)
braydencw1 marked this conversation as resolved.
Show resolved Hide resolved
16 changes: 13 additions & 3 deletions plugins/modules/autoscaling_group.py
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,11 @@
- List of VPC subnets to use
type: list
elements: str
protected_from_scale_in:
description:
- If V(true), instances will have scale-in protection enabled.
type: bool
default: false
tags:
description:
- A list of tags to add to the Auto Scale Group.
Expand Down Expand Up @@ -1128,6 +1133,7 @@ def create_autoscaling_group(connection):
vpc_zone_identifier = module.params.get("vpc_zone_identifier")
set_tags = module.params.get("tags")
purge_tags = module.params.get("purge_tags")
protected_from_scale_in = module.params.get("protected_from_scale_in")
health_check_period = module.params.get("health_check_period")
health_check_type = module.params.get("health_check_type")
default_cooldown = module.params.get("default_cooldown")
Expand Down Expand Up @@ -1186,6 +1192,7 @@ def create_autoscaling_group(connection):
HealthCheckType=health_check_type,
DefaultCooldown=default_cooldown,
TerminationPolicies=termination_policies,
NewInstancesProtectedFromScaleIn=protected_from_scale_in,
)
if vpc_zone_identifier:
ag["VPCZoneIdentifier"] = vpc_zone_identifier
Expand Down Expand Up @@ -1483,14 +1490,15 @@ def get_chunks(l, n):
yield l[i:i + n] # fmt: skip


def update_size(connection, group, max_size, min_size, dc):
def update_size(connection, group, max_size, min_size, dc, protected_from_scale_in):
module.debug("setting ASG sizes")
module.debug(f"minimum size: {min_size}, desired_capacity: {dc}, max size: {max_size}")
updated_group = dict()
updated_group["AutoScalingGroupName"] = group["AutoScalingGroupName"]
updated_group["MinSize"] = min_size
updated_group["MaxSize"] = max_size
updated_group["DesiredCapacity"] = dc
updated_group["NewInstancesProtectedFromScaleIn"] = protected_from_scale_in
update_asg(connection, **updated_group)


Expand All @@ -1501,6 +1509,7 @@ def replace(connection):
group_name = module.params.get("name")
max_size = module.params.get("max_size")
min_size = module.params.get("min_size")
protected_from_scale_in = module.params.get("protected_from_scale_in")
desired_capacity = module.params.get("desired_capacity")
launch_config_name = module.params.get("launch_config_name")

Expand Down Expand Up @@ -1570,7 +1579,7 @@ def replace(connection):
# This should get overwritten if the number of instances left is less than the batch size.

as_group = describe_autoscaling_groups(connection, group_name)[0]
update_size(connection, as_group, max_size + batch_size, min_size + batch_size, desired_capacity + batch_size)
update_size(connection, as_group, max_size + batch_size, min_size + batch_size, desired_capacity + batch_size, protected_from_scale_in)

if wait_for_instances:
wait_for_new_inst(connection, group_name, wait_timeout, as_group["MinSize"] + batch_size, "viable_instances")
Expand Down Expand Up @@ -1598,7 +1607,7 @@ def replace(connection):
module.debug("breaking loop")
break

update_size(connection, as_group, max_size, min_size, desired_capacity)
update_size(connection, as_group, max_size, min_size, desired_capacity, protected_from_scale_in)
as_group = describe_autoscaling_groups(connection, group_name)[0]
asg_properties = get_properties(as_group)
module.debug("Rolling update complete.")
Expand Down Expand Up @@ -1902,6 +1911,7 @@ def main():
state=dict(default="present", choices=["present", "absent"]),
tags=dict(type="list", default=[], elements="dict"),
purge_tags=dict(type="bool", default=False),
protected_from_scale_in=dict(type="bool", default=False),
health_check_period=dict(type="int", default=300),
health_check_type=dict(default="EC2", choices=["EC2", "ELB"]),
default_cooldown=dict(type="int", default=300),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -580,3 +580,29 @@
- output.target_group_arns | length == 1
- output.target_group_arns[0] == out_tg1.target_group_arn
- output.changed == false
# ============================================================
- name: Create autosclaing group with instance protection enabled
amazon.aws.autoscaling_group:
name: "{{ resource_prefix }}-asg"
protected_from_scale_in: true
register: output

- name: Assert ASG created
ansible.builtin.assert:
that:
- output.changed == true

- name: Disable instance protection from asg
amazon.aws.autoscaling_group:
name: "{{ resource_prefix }}-asg"
protected_from_scale_in: false
register: modified_output

- name: Assert ASG modification
ansible.builtin.assert:
that:
- protected_from_scale_in.changed == true
- name: Destroy asg
amazon.aws.autoscaling_group:
name: "{{ resource_prefix }}-asg"
state: absent
Loading