moto/tests/test_autoscaling/test_autoscaling.py

1268 lines
46 KiB
Python

import boto3
import sure # noqa # pylint: disable=unused-import
import pytest
from botocore.exceptions import ClientError
from moto import mock_autoscaling, mock_ec2
from moto.core import DEFAULT_ACCOUNT_ID as ACCOUNT_ID
from tests import EXAMPLE_AMI_ID
from .utils import setup_networking, setup_instance_with_networking
@mock_autoscaling
@mock_ec2
def test_propogate_tags():
mocked_networking = setup_networking()
conn = boto3.client("autoscaling", region_name="us-east-1")
conn.create_launch_configuration(
LaunchConfigurationName="TestLC",
ImageId=EXAMPLE_AMI_ID,
InstanceType="t2.medium",
)
conn.create_auto_scaling_group(
AutoScalingGroupName="TestGroup1",
MinSize=1,
MaxSize=2,
LaunchConfigurationName="TestLC",
Tags=[
{
"ResourceId": "TestGroup1",
"ResourceType": "auto-scaling-group",
"PropagateAtLaunch": True,
"Key": "TestTagKey1",
"Value": "TestTagValue1",
}
],
VPCZoneIdentifier=mocked_networking["subnet1"],
)
ec2 = boto3.client("ec2", region_name="us-east-1")
instances = ec2.describe_instances()
tags = instances["Reservations"][0]["Instances"][0]["Tags"]
tags.should.contain({"Value": "TestTagValue1", "Key": "TestTagKey1"})
tags.should.contain({"Value": "TestGroup1", "Key": "aws:autoscaling:groupName"})
@mock_autoscaling
def test_create_autoscaling_group_from_instance():
autoscaling_group_name = "test_asg"
image_id = EXAMPLE_AMI_ID
instance_type = "t2.micro"
mocked_instance_with_networking = setup_instance_with_networking(
image_id, instance_type
)
client = boto3.client("autoscaling", region_name="us-east-1")
response = client.create_auto_scaling_group(
AutoScalingGroupName=autoscaling_group_name,
InstanceId=mocked_instance_with_networking["instance"],
MinSize=1,
MaxSize=3,
DesiredCapacity=2,
VPCZoneIdentifier=mocked_instance_with_networking["subnet1"],
NewInstancesProtectedFromScaleIn=False,
)
response["ResponseMetadata"]["HTTPStatusCode"].should.equal(200)
describe_launch_configurations_response = client.describe_launch_configurations()
describe_launch_configurations_response[
"LaunchConfigurations"
].should.have.length_of(1)
launch_configuration_from_instance = describe_launch_configurations_response[
"LaunchConfigurations"
][0]
launch_configuration_from_instance["LaunchConfigurationName"].should.equal(
"test_asg"
)
launch_configuration_from_instance["ImageId"].should.equal(image_id)
launch_configuration_from_instance["InstanceType"].should.equal(instance_type)
@mock_autoscaling
def test_create_autoscaling_group_from_invalid_instance_id():
invalid_instance_id = "invalid_instance"
mocked_networking = setup_networking()
client = boto3.client("autoscaling", region_name="us-east-1")
with pytest.raises(ClientError) as ex:
client.create_auto_scaling_group(
AutoScalingGroupName="test_asg",
InstanceId=invalid_instance_id,
MinSize=9,
MaxSize=15,
DesiredCapacity=12,
VPCZoneIdentifier=mocked_networking["subnet1"],
NewInstancesProtectedFromScaleIn=False,
)
ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
ex.value.response["Error"]["Code"].should.equal("ValidationError")
ex.value.response["Error"]["Message"].should.equal(
"Instance [{0}] is invalid.".format(invalid_instance_id)
)
@mock_autoscaling
@mock_ec2
def test_create_autoscaling_group_from_template():
mocked_networking = setup_networking()
ec2_client = boto3.client("ec2", region_name="us-east-1")
template = ec2_client.create_launch_template(
LaunchTemplateName="test_launch_template",
LaunchTemplateData={"ImageId": EXAMPLE_AMI_ID, "InstanceType": "t2.micro"},
)["LaunchTemplate"]
client = boto3.client("autoscaling", region_name="us-east-1")
response = client.create_auto_scaling_group(
AutoScalingGroupName="test_asg",
LaunchTemplate={
"LaunchTemplateId": template["LaunchTemplateId"],
"Version": str(template["LatestVersionNumber"]),
},
MinSize=1,
MaxSize=3,
DesiredCapacity=2,
VPCZoneIdentifier=mocked_networking["subnet1"],
NewInstancesProtectedFromScaleIn=False,
)
response["ResponseMetadata"]["HTTPStatusCode"].should.equal(200)
@mock_ec2
@mock_autoscaling
def test_create_auto_scaling_from_template_version__latest():
ec2_client = boto3.client("ec2", region_name="us-west-1")
launch_template_name = "tester"
ec2_client.create_launch_template(
LaunchTemplateName=launch_template_name,
LaunchTemplateData={"ImageId": EXAMPLE_AMI_ID, "InstanceType": "t2.medium"},
)
asg_client = boto3.client("autoscaling", region_name="us-west-1")
asg_client.create_auto_scaling_group(
AutoScalingGroupName="name",
DesiredCapacity=1,
MinSize=1,
MaxSize=1,
LaunchTemplate={
"LaunchTemplateName": launch_template_name,
"Version": "$Latest",
},
AvailabilityZones=["us-west-1a"],
)
response = asg_client.describe_auto_scaling_groups(AutoScalingGroupNames=["name"])[
"AutoScalingGroups"
][0]
response.should.have.key("LaunchTemplate")
response["LaunchTemplate"].should.have.key("LaunchTemplateName").equals(
launch_template_name
)
response["LaunchTemplate"].should.have.key("Version").equals("$Latest")
@mock_ec2
@mock_autoscaling
def test_create_auto_scaling_from_template_version__default():
ec2_client = boto3.client("ec2", region_name="us-west-1")
launch_template_name = "tester"
ec2_client.create_launch_template(
LaunchTemplateName=launch_template_name,
LaunchTemplateData={"ImageId": EXAMPLE_AMI_ID, "InstanceType": "t2.medium"},
)
ec2_client.create_launch_template_version(
LaunchTemplateName=launch_template_name,
LaunchTemplateData={"ImageId": EXAMPLE_AMI_ID, "InstanceType": "t3.medium"},
VersionDescription="v2",
)
asg_client = boto3.client("autoscaling", region_name="us-west-1")
asg_client.create_auto_scaling_group(
AutoScalingGroupName="name",
DesiredCapacity=1,
MinSize=1,
MaxSize=1,
LaunchTemplate={
"LaunchTemplateName": launch_template_name,
"Version": "$Default",
},
AvailabilityZones=["us-west-1a"],
)
response = asg_client.describe_auto_scaling_groups(AutoScalingGroupNames=["name"])[
"AutoScalingGroups"
][0]
response.should.have.key("LaunchTemplate")
response["LaunchTemplate"].should.have.key("LaunchTemplateName").equals(
launch_template_name
)
response["LaunchTemplate"].should.have.key("Version").equals("$Default")
@mock_ec2
@mock_autoscaling
def test_create_auto_scaling_from_template_version__no_version():
ec2_client = boto3.client("ec2", region_name="us-west-1")
launch_template_name = "tester"
ec2_client.create_launch_template(
LaunchTemplateName=launch_template_name,
LaunchTemplateData={"ImageId": EXAMPLE_AMI_ID, "InstanceType": "t2.medium"},
)
asg_client = boto3.client("autoscaling", region_name="us-west-1")
asg_client.create_auto_scaling_group(
AutoScalingGroupName="name",
DesiredCapacity=1,
MinSize=1,
MaxSize=1,
LaunchTemplate={"LaunchTemplateName": launch_template_name},
AvailabilityZones=["us-west-1a"],
)
response = asg_client.describe_auto_scaling_groups(AutoScalingGroupNames=["name"])[
"AutoScalingGroups"
][0]
response.should.have.key("LaunchTemplate")
# We never specified the version - this is what it defaults to
response["LaunchTemplate"].should.have.key("Version").equals("$Default")
@mock_autoscaling
@mock_ec2
def test_create_autoscaling_group_no_template_ref():
mocked_networking = setup_networking()
ec2_client = boto3.client("ec2", region_name="us-east-1")
template = ec2_client.create_launch_template(
LaunchTemplateName="test_launch_template",
LaunchTemplateData={"ImageId": EXAMPLE_AMI_ID, "InstanceType": "t2.micro"},
)["LaunchTemplate"]
client = boto3.client("autoscaling", region_name="us-east-1")
with pytest.raises(ClientError) as ex:
client.create_auto_scaling_group(
AutoScalingGroupName="test_asg",
LaunchTemplate={"Version": str(template["LatestVersionNumber"])},
MinSize=0,
MaxSize=20,
DesiredCapacity=5,
VPCZoneIdentifier=mocked_networking["subnet1"],
NewInstancesProtectedFromScaleIn=False,
)
ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
ex.value.response["Error"]["Code"].should.equal("ValidationError")
ex.value.response["Error"]["Message"].should.equal(
"Valid requests must contain either launchTemplateId or LaunchTemplateName"
)
@mock_autoscaling
@mock_ec2
def test_create_autoscaling_group_multiple_template_ref():
mocked_networking = setup_networking()
ec2_client = boto3.client("ec2", region_name="us-east-1")
template = ec2_client.create_launch_template(
LaunchTemplateName="test_launch_template",
LaunchTemplateData={"ImageId": EXAMPLE_AMI_ID, "InstanceType": "t2.micro"},
)["LaunchTemplate"]
client = boto3.client("autoscaling", region_name="us-east-1")
with pytest.raises(ClientError) as ex:
client.create_auto_scaling_group(
AutoScalingGroupName="test_asg",
LaunchTemplate={
"LaunchTemplateId": template["LaunchTemplateId"],
"LaunchTemplateName": template["LaunchTemplateName"],
"Version": str(template["LatestVersionNumber"]),
},
MinSize=0,
MaxSize=20,
DesiredCapacity=5,
VPCZoneIdentifier=mocked_networking["subnet1"],
NewInstancesProtectedFromScaleIn=False,
)
ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
ex.value.response["Error"]["Code"].should.equal("ValidationError")
ex.value.response["Error"]["Message"].should.equal(
"Valid requests must contain either launchTemplateId or LaunchTemplateName"
)
@mock_autoscaling
def test_create_autoscaling_group_no_launch_configuration():
mocked_networking = setup_networking()
client = boto3.client("autoscaling", region_name="us-east-1")
with pytest.raises(ClientError) as ex:
client.create_auto_scaling_group(
AutoScalingGroupName="test_asg",
MinSize=0,
MaxSize=20,
DesiredCapacity=5,
VPCZoneIdentifier=mocked_networking["subnet1"],
NewInstancesProtectedFromScaleIn=False,
)
ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
ex.value.response["Error"]["Code"].should.equal("ValidationError")
ex.value.response["Error"]["Message"].should.equal(
"Valid requests must contain either LaunchTemplate, LaunchConfigurationName, "
"InstanceId or MixedInstancesPolicy parameter."
)
@mock_autoscaling
@mock_ec2
def test_create_autoscaling_group_multiple_launch_configurations():
mocked_networking = setup_networking()
ec2_client = boto3.client("ec2", region_name="us-east-1")
template = ec2_client.create_launch_template(
LaunchTemplateName="test_launch_template",
LaunchTemplateData={"ImageId": EXAMPLE_AMI_ID, "InstanceType": "t2.micro"},
)["LaunchTemplate"]
client = boto3.client("autoscaling", region_name="us-east-1")
client.create_launch_configuration(
LaunchConfigurationName="test_launch_configuration",
ImageId=EXAMPLE_AMI_ID,
InstanceType="t2.medium",
)
with pytest.raises(ClientError) as ex:
client.create_auto_scaling_group(
AutoScalingGroupName="test_asg",
LaunchConfigurationName="test_launch_configuration",
LaunchTemplate={
"LaunchTemplateId": template["LaunchTemplateId"],
"Version": str(template["LatestVersionNumber"]),
},
MinSize=0,
MaxSize=20,
DesiredCapacity=5,
VPCZoneIdentifier=mocked_networking["subnet1"],
NewInstancesProtectedFromScaleIn=False,
)
ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
ex.value.response["Error"]["Code"].should.equal("ValidationError")
ex.value.response["Error"]["Message"].should.equal(
"Valid requests must contain either LaunchTemplate, LaunchConfigurationName, "
"InstanceId or MixedInstancesPolicy parameter."
)
@mock_autoscaling
@mock_ec2
def test_describe_autoscaling_groups_launch_template():
mocked_networking = setup_networking()
ec2_client = boto3.client("ec2", region_name="us-east-1")
template = ec2_client.create_launch_template(
LaunchTemplateName="test_launch_template",
LaunchTemplateData={"ImageId": EXAMPLE_AMI_ID, "InstanceType": "t2.micro"},
)["LaunchTemplate"]
client = boto3.client("autoscaling", region_name="us-east-1")
client.create_auto_scaling_group(
AutoScalingGroupName="test_asg",
LaunchTemplate={"LaunchTemplateName": "test_launch_template", "Version": "1"},
MinSize=0,
MaxSize=20,
DesiredCapacity=5,
VPCZoneIdentifier=mocked_networking["subnet1"],
NewInstancesProtectedFromScaleIn=True,
)
expected_launch_template = {
"LaunchTemplateId": template["LaunchTemplateId"],
"LaunchTemplateName": "test_launch_template",
"Version": "1",
}
response = client.describe_auto_scaling_groups(AutoScalingGroupNames=["test_asg"])
response["ResponseMetadata"]["HTTPStatusCode"].should.equal(200)
group = response["AutoScalingGroups"][0]
group["AutoScalingGroupName"].should.equal("test_asg")
group["LaunchTemplate"].should.equal(expected_launch_template)
group.should_not.have.key("LaunchConfigurationName")
group["AvailabilityZones"].should.equal(["us-east-1a"])
group["VPCZoneIdentifier"].should.equal(mocked_networking["subnet1"])
group["NewInstancesProtectedFromScaleIn"].should.equal(True)
for instance in group["Instances"]:
instance["LaunchTemplate"].should.equal(expected_launch_template)
instance.should_not.have.key("LaunchConfigurationName")
instance["AvailabilityZone"].should.equal("us-east-1a")
instance["ProtectedFromScaleIn"].should.equal(True)
instance["InstanceType"].should.equal("t2.micro")
@mock_autoscaling
def test_describe_autoscaling_instances_launch_config():
mocked_networking = setup_networking()
client = boto3.client("autoscaling", region_name="us-east-1")
client.create_launch_configuration(
LaunchConfigurationName="test_launch_configuration",
InstanceType="t2.micro",
ImageId=EXAMPLE_AMI_ID,
)
client.create_auto_scaling_group(
AutoScalingGroupName="test_asg",
LaunchConfigurationName="test_launch_configuration",
MinSize=0,
MaxSize=20,
DesiredCapacity=5,
VPCZoneIdentifier=mocked_networking["subnet1"],
NewInstancesProtectedFromScaleIn=True,
)
response = client.describe_auto_scaling_instances()
len(response["AutoScalingInstances"]).should.equal(5)
for instance in response["AutoScalingInstances"]:
instance["LaunchConfigurationName"].should.equal("test_launch_configuration")
instance.should_not.have.key("LaunchTemplate")
instance["AutoScalingGroupName"].should.equal("test_asg")
instance["AvailabilityZone"].should.equal("us-east-1a")
instance["ProtectedFromScaleIn"].should.equal(True)
instance["InstanceType"].should.equal("t2.micro")
@mock_autoscaling
@mock_ec2
def test_describe_autoscaling_instances_launch_template():
mocked_networking = setup_networking()
ec2_client = boto3.client("ec2", region_name="us-east-1")
template = ec2_client.create_launch_template(
LaunchTemplateName="test_launch_template",
LaunchTemplateData={"ImageId": EXAMPLE_AMI_ID, "InstanceType": "t2.micro"},
)["LaunchTemplate"]
client = boto3.client("autoscaling", region_name="us-east-1")
client.create_auto_scaling_group(
AutoScalingGroupName="test_asg",
LaunchTemplate={"LaunchTemplateName": "test_launch_template", "Version": "1"},
MinSize=0,
MaxSize=20,
DesiredCapacity=5,
VPCZoneIdentifier=mocked_networking["subnet1"],
NewInstancesProtectedFromScaleIn=True,
)
expected_launch_template = {
"LaunchTemplateId": template["LaunchTemplateId"],
"LaunchTemplateName": "test_launch_template",
"Version": "1",
}
response = client.describe_auto_scaling_instances()
len(response["AutoScalingInstances"]).should.equal(5)
for instance in response["AutoScalingInstances"]:
instance["LaunchTemplate"].should.equal(expected_launch_template)
instance.should_not.have.key("LaunchConfigurationName")
instance["AutoScalingGroupName"].should.equal("test_asg")
instance["AvailabilityZone"].should.equal("us-east-1a")
instance["ProtectedFromScaleIn"].should.equal(True)
instance["InstanceType"].should.equal("t2.micro")
@mock_autoscaling
def test_describe_autoscaling_instances_instanceid_filter():
mocked_networking = setup_networking()
client = boto3.client("autoscaling", region_name="us-east-1")
_ = client.create_launch_configuration(
LaunchConfigurationName="test_launch_configuration",
ImageId=EXAMPLE_AMI_ID,
InstanceType="t2.medium",
)
_ = client.create_auto_scaling_group(
AutoScalingGroupName="test_asg",
LaunchConfigurationName="test_launch_configuration",
MinSize=0,
MaxSize=20,
DesiredCapacity=5,
VPCZoneIdentifier=mocked_networking["subnet1"],
NewInstancesProtectedFromScaleIn=True,
)
response = client.describe_auto_scaling_groups(AutoScalingGroupNames=["test_asg"])
instance_ids = [
instance["InstanceId"]
for instance in response["AutoScalingGroups"][0]["Instances"]
]
response = client.describe_auto_scaling_instances(
InstanceIds=instance_ids[0:2]
) # Filter by first 2 of 5
len(response["AutoScalingInstances"]).should.equal(2)
for instance in response["AutoScalingInstances"]:
instance["AutoScalingGroupName"].should.equal("test_asg")
instance["AvailabilityZone"].should.equal("us-east-1a")
instance["ProtectedFromScaleIn"].should.equal(True)
@mock_autoscaling
def test_update_autoscaling_group_launch_config():
mocked_networking = setup_networking()
client = boto3.client("autoscaling", region_name="us-east-1")
client.create_launch_configuration(
LaunchConfigurationName="test_launch_configuration",
ImageId=EXAMPLE_AMI_ID,
InstanceType="t2.medium",
)
client.create_launch_configuration(
LaunchConfigurationName="test_launch_configuration_new",
ImageId=EXAMPLE_AMI_ID,
InstanceType="t2.medium",
)
client.create_auto_scaling_group(
AutoScalingGroupName="test_asg",
LaunchConfigurationName="test_launch_configuration",
MinSize=0,
MaxSize=20,
DesiredCapacity=5,
VPCZoneIdentifier=mocked_networking["subnet1"],
NewInstancesProtectedFromScaleIn=True,
)
client.update_auto_scaling_group(
AutoScalingGroupName="test_asg",
LaunchConfigurationName="test_launch_configuration_new",
MinSize=1,
VPCZoneIdentifier="{subnet1},{subnet2}".format(
subnet1=mocked_networking["subnet1"], subnet2=mocked_networking["subnet2"]
),
NewInstancesProtectedFromScaleIn=False,
)
response = client.describe_auto_scaling_groups(AutoScalingGroupNames=["test_asg"])
group = response["AutoScalingGroups"][0]
group["LaunchConfigurationName"].should.equal("test_launch_configuration_new")
group["MinSize"].should.equal(1)
set(group["AvailabilityZones"]).should.equal({"us-east-1a", "us-east-1b"})
group["NewInstancesProtectedFromScaleIn"].should.equal(False)
@mock_autoscaling
@mock_ec2
def test_update_autoscaling_group_launch_template():
mocked_networking = setup_networking()
ec2_client = boto3.client("ec2", region_name="us-east-1")
ec2_client.create_launch_template(
LaunchTemplateName="test_launch_template",
LaunchTemplateData={"ImageId": EXAMPLE_AMI_ID, "InstanceType": "t2.micro"},
)
template = ec2_client.create_launch_template(
LaunchTemplateName="test_launch_template_new",
LaunchTemplateData={
"ImageId": "ami-1ea5b10a3d8867db4",
"InstanceType": "t2.micro",
},
)["LaunchTemplate"]
client = boto3.client("autoscaling", region_name="us-east-1")
client.create_auto_scaling_group(
AutoScalingGroupName="test_asg",
LaunchTemplate={"LaunchTemplateName": "test_launch_template", "Version": "1"},
MinSize=0,
MaxSize=20,
DesiredCapacity=5,
VPCZoneIdentifier=mocked_networking["subnet1"],
NewInstancesProtectedFromScaleIn=True,
)
client.update_auto_scaling_group(
AutoScalingGroupName="test_asg",
LaunchTemplate={
"LaunchTemplateName": "test_launch_template_new",
"Version": "1",
},
MinSize=1,
VPCZoneIdentifier="{subnet1},{subnet2}".format(
subnet1=mocked_networking["subnet1"], subnet2=mocked_networking["subnet2"]
),
NewInstancesProtectedFromScaleIn=False,
)
expected_launch_template = {
"LaunchTemplateId": template["LaunchTemplateId"],
"LaunchTemplateName": "test_launch_template_new",
"Version": "1",
}
response = client.describe_auto_scaling_groups(AutoScalingGroupNames=["test_asg"])
group = response["AutoScalingGroups"][0]
group["LaunchTemplate"].should.equal(expected_launch_template)
group["MinSize"].should.equal(1)
set(group["AvailabilityZones"]).should.equal({"us-east-1a", "us-east-1b"})
group["NewInstancesProtectedFromScaleIn"].should.equal(False)
@mock_autoscaling
def test_update_autoscaling_group_min_size_desired_capacity_change():
mocked_networking = setup_networking()
client = boto3.client("autoscaling", region_name="us-east-1")
client.create_launch_configuration(
LaunchConfigurationName="test_launch_configuration",
ImageId=EXAMPLE_AMI_ID,
InstanceType="t2.medium",
)
client.create_auto_scaling_group(
AutoScalingGroupName="test_asg",
LaunchConfigurationName="test_launch_configuration",
MinSize=2,
MaxSize=20,
DesiredCapacity=3,
VPCZoneIdentifier=mocked_networking["subnet1"],
)
client.update_auto_scaling_group(AutoScalingGroupName="test_asg", MinSize=5)
response = client.describe_auto_scaling_groups(AutoScalingGroupNames=["test_asg"])
group = response["AutoScalingGroups"][0]
group["DesiredCapacity"].should.equal(5)
group["MinSize"].should.equal(5)
group["Instances"].should.have.length_of(5)
@mock_autoscaling
def test_update_autoscaling_group_max_size_desired_capacity_change():
mocked_networking = setup_networking()
client = boto3.client("autoscaling", region_name="us-east-1")
client.create_launch_configuration(
LaunchConfigurationName="test_launch_configuration",
ImageId=EXAMPLE_AMI_ID,
InstanceType="t2.medium",
)
client.create_auto_scaling_group(
AutoScalingGroupName="test_asg",
LaunchConfigurationName="test_launch_configuration",
MinSize=2,
MaxSize=20,
DesiredCapacity=10,
VPCZoneIdentifier=mocked_networking["subnet1"],
)
client.update_auto_scaling_group(AutoScalingGroupName="test_asg", MaxSize=5)
response = client.describe_auto_scaling_groups(AutoScalingGroupNames=["test_asg"])
group = response["AutoScalingGroups"][0]
group["DesiredCapacity"].should.equal(5)
group["MaxSize"].should.equal(5)
group["Instances"].should.have.length_of(5)
@mock_autoscaling
def test_autoscaling_describe_policies():
mocked_networking = setup_networking()
client = boto3.client("autoscaling", region_name="us-east-1")
_ = client.create_launch_configuration(
LaunchConfigurationName="test_launch_configuration",
ImageId=EXAMPLE_AMI_ID,
InstanceType="t2.medium",
)
_ = client.create_auto_scaling_group(
AutoScalingGroupName="test_asg",
LaunchConfigurationName="test_launch_configuration",
MinSize=0,
MaxSize=20,
DesiredCapacity=5,
Tags=[
{
"ResourceId": "test_asg",
"Key": "test_key",
"Value": "test_value",
"PropagateAtLaunch": True,
}
],
VPCZoneIdentifier=mocked_networking["subnet1"],
)
client.put_scaling_policy(
AutoScalingGroupName="test_asg",
PolicyName="test_policy_down",
PolicyType="SimpleScaling",
MetricAggregationType="Minimum",
AdjustmentType="PercentChangeInCapacity",
ScalingAdjustment=-10,
Cooldown=60,
MinAdjustmentMagnitude=1,
)
client.put_scaling_policy(
AutoScalingGroupName="test_asg",
PolicyName="test_policy_up",
PolicyType="SimpleScaling",
AdjustmentType="PercentChangeInCapacity",
ScalingAdjustment=10,
Cooldown=60,
MinAdjustmentMagnitude=1,
)
response = client.describe_policies()
response["ScalingPolicies"].should.have.length_of(2)
response = client.describe_policies(AutoScalingGroupName="test_asg")
response["ScalingPolicies"].should.have.length_of(2)
response = client.describe_policies(PolicyTypes=["StepScaling"])
response["ScalingPolicies"].should.have.length_of(0)
response = client.describe_policies(
AutoScalingGroupName="test_asg",
PolicyNames=["test_policy_down"],
PolicyTypes=["SimpleScaling"],
)
response["ScalingPolicies"].should.have.length_of(1)
policy = response["ScalingPolicies"][0]
policy["PolicyType"].should.equal("SimpleScaling")
policy["MetricAggregationType"].should.equal("Minimum")
policy["AdjustmentType"].should.equal("PercentChangeInCapacity")
policy["ScalingAdjustment"].should.equal(-10)
policy["Cooldown"].should.equal(60)
policy["PolicyARN"].should.equal(
f"arn:aws:autoscaling:us-east-1:{ACCOUNT_ID}:scalingPolicy:c322761b-3172-4d56-9a21-0ed9d6161d67:autoScalingGroupName/test_asg:policyName/test_policy_down"
)
policy["PolicyName"].should.equal("test_policy_down")
policy.shouldnt.have.key("TargetTrackingConfiguration")
@mock_autoscaling
@mock_ec2
def test_create_autoscaling_policy_with_policytype__targettrackingscaling():
mocked_networking = setup_networking(region_name="us-west-1")
client = boto3.client("autoscaling", region_name="us-west-1")
configuration_name = "test"
asg_name = "asg_test"
client.create_launch_configuration(
LaunchConfigurationName=configuration_name,
ImageId=EXAMPLE_AMI_ID,
InstanceType="m1.small",
)
client.create_auto_scaling_group(
LaunchConfigurationName=configuration_name,
AutoScalingGroupName=asg_name,
MinSize=1,
MaxSize=2,
VPCZoneIdentifier=mocked_networking["subnet1"],
)
client.put_scaling_policy(
AutoScalingGroupName=asg_name,
PolicyName=configuration_name,
PolicyType="TargetTrackingScaling",
EstimatedInstanceWarmup=100,
TargetTrackingConfiguration={
"PredefinedMetricSpecification": {
"PredefinedMetricType": "ASGAverageNetworkIn",
},
"TargetValue": 1000000.0,
},
)
resp = client.describe_policies(AutoScalingGroupName=asg_name)
policy = resp["ScalingPolicies"][0]
policy.should.have.key("PolicyName").equals(configuration_name)
policy.should.have.key("PolicyARN").equals(
f"arn:aws:autoscaling:us-west-1:{ACCOUNT_ID}:scalingPolicy:c322761b-3172-4d56-9a21-0ed9d6161d67:autoScalingGroupName/{asg_name}:policyName/{configuration_name}"
)
policy.should.have.key("PolicyType").equals("TargetTrackingScaling")
policy.should.have.key("TargetTrackingConfiguration").should.equal(
{
"PredefinedMetricSpecification": {
"PredefinedMetricType": "ASGAverageNetworkIn",
},
"TargetValue": 1000000.0,
}
)
policy.shouldnt.have.key("ScalingAdjustment")
policy.shouldnt.have.key("Cooldown")
@mock_autoscaling
@mock_ec2
def test_create_autoscaling_policy_with_policytype__stepscaling():
mocked_networking = setup_networking(region_name="eu-west-1")
client = boto3.client("autoscaling", region_name="eu-west-1")
launch_config_name = "lg_name"
asg_name = "asg_test"
client.create_launch_configuration(
LaunchConfigurationName=launch_config_name,
ImageId=EXAMPLE_AMI_ID,
InstanceType="m1.small",
)
client.create_auto_scaling_group(
LaunchConfigurationName=launch_config_name,
AutoScalingGroupName=asg_name,
MinSize=1,
MaxSize=2,
VPCZoneIdentifier=mocked_networking["subnet1"],
)
client.put_scaling_policy(
AutoScalingGroupName=asg_name,
PolicyName=launch_config_name,
PolicyType="StepScaling",
StepAdjustments=[
{
"MetricIntervalLowerBound": 2,
"MetricIntervalUpperBound": 8,
"ScalingAdjustment": 1,
}
],
)
resp = client.describe_policies(AutoScalingGroupName=asg_name)
policy = resp["ScalingPolicies"][0]
policy.should.have.key("PolicyName").equals(launch_config_name)
policy.should.have.key("PolicyARN").equals(
f"arn:aws:autoscaling:eu-west-1:{ACCOUNT_ID}:scalingPolicy:c322761b-3172-4d56-9a21-0ed9d6161d67:autoScalingGroupName/{asg_name}:policyName/{launch_config_name}"
)
policy.should.have.key("PolicyType").equals("StepScaling")
policy.should.have.key("StepAdjustments").equal(
[
{
"MetricIntervalLowerBound": 2,
"MetricIntervalUpperBound": 8,
"ScalingAdjustment": 1,
}
]
)
policy.shouldnt.have.key("TargetTrackingConfiguration")
policy.shouldnt.have.key("ScalingAdjustment")
policy.shouldnt.have.key("Cooldown")
@mock_autoscaling
@mock_ec2
def test_create_autoscaling_policy_with_predictive_scaling_config():
mocked_networking = setup_networking(region_name="eu-west-1")
client = boto3.client("autoscaling", region_name="eu-west-1")
launch_config_name = "lg_name"
asg_name = "asg_test"
client.create_launch_configuration(
LaunchConfigurationName=launch_config_name,
ImageId=EXAMPLE_AMI_ID,
InstanceType="m1.small",
)
client.create_auto_scaling_group(
LaunchConfigurationName=launch_config_name,
AutoScalingGroupName=asg_name,
MinSize=1,
MaxSize=2,
VPCZoneIdentifier=mocked_networking["subnet1"],
)
client.put_scaling_policy(
AutoScalingGroupName=asg_name,
PolicyName=launch_config_name,
PolicyType="PredictiveScaling",
PredictiveScalingConfiguration={
"MetricSpecifications": [{"TargetValue": 5}],
"SchedulingBufferTime": 7,
},
)
resp = client.describe_policies(AutoScalingGroupName=asg_name)
policy = resp["ScalingPolicies"][0]
policy.should.have.key("PredictiveScalingConfiguration").equals(
{"MetricSpecifications": [{"TargetValue": 5.0}], "SchedulingBufferTime": 7}
)
@mock_autoscaling
@mock_ec2
def test_create_auto_scaling_group_with_mixed_instances_policy():
mocked_networking = setup_networking(region_name="eu-west-1")
client = boto3.client("autoscaling", region_name="eu-west-1")
ec2_client = boto3.client("ec2", region_name="eu-west-1")
asg_name = "asg_test"
lt = ec2_client.create_launch_template(
LaunchTemplateName="launchie",
LaunchTemplateData={"ImageId": EXAMPLE_AMI_ID},
)["LaunchTemplate"]
client.create_auto_scaling_group(
MixedInstancesPolicy={
"LaunchTemplate": {
"LaunchTemplateSpecification": {
"LaunchTemplateName": "launchie",
"Version": "$DEFAULT",
}
}
},
AutoScalingGroupName=asg_name,
MinSize=2,
MaxSize=2,
VPCZoneIdentifier=mocked_networking["subnet1"],
)
# Assert we can describe MixedInstancesPolicy
response = client.describe_auto_scaling_groups(AutoScalingGroupNames=[asg_name])
group = response["AutoScalingGroups"][0]
group.should.have.key("MixedInstancesPolicy").equals(
{
"LaunchTemplate": {
"LaunchTemplateSpecification": {
"LaunchTemplateId": lt["LaunchTemplateId"],
"LaunchTemplateName": "launchie",
"Version": "$DEFAULT",
}
}
}
)
# Assert the LaunchTemplate is known for the resulting instances
response = client.describe_auto_scaling_instances()
len(response["AutoScalingInstances"]).should.equal(2)
for instance in response["AutoScalingInstances"]:
instance["LaunchTemplate"].should.equal(
{
"LaunchTemplateId": lt["LaunchTemplateId"],
"LaunchTemplateName": "launchie",
"Version": "$DEFAULT",
}
)
@mock_autoscaling
@mock_ec2
def test_create_auto_scaling_group_with_mixed_instances_policy_overrides():
mocked_networking = setup_networking(region_name="eu-west-1")
client = boto3.client("autoscaling", region_name="eu-west-1")
ec2_client = boto3.client("ec2", region_name="eu-west-1")
asg_name = "asg_test"
lt = ec2_client.create_launch_template(
LaunchTemplateName="launchie",
LaunchTemplateData={"ImageId": EXAMPLE_AMI_ID},
)["LaunchTemplate"]
client.create_auto_scaling_group(
MixedInstancesPolicy={
"LaunchTemplate": {
"LaunchTemplateSpecification": {
"LaunchTemplateName": "launchie",
"Version": "$DEFAULT",
},
"Overrides": [
{
"InstanceType": "t2.medium",
"WeightedCapacity": "50",
}
],
}
},
AutoScalingGroupName=asg_name,
MinSize=2,
MaxSize=2,
VPCZoneIdentifier=mocked_networking["subnet1"],
)
# Assert we can describe MixedInstancesPolicy
response = client.describe_auto_scaling_groups(AutoScalingGroupNames=[asg_name])
group = response["AutoScalingGroups"][0]
group.should.have.key("MixedInstancesPolicy").equals(
{
"LaunchTemplate": {
"LaunchTemplateSpecification": {
"LaunchTemplateId": lt["LaunchTemplateId"],
"LaunchTemplateName": "launchie",
"Version": "$DEFAULT",
},
"Overrides": [
{
"InstanceType": "t2.medium",
"WeightedCapacity": "50",
}
],
}
}
)
@mock_autoscaling
def test_set_instance_protection():
mocked_networking = setup_networking()
client = boto3.client("autoscaling", region_name="us-east-1")
_ = client.create_launch_configuration(
LaunchConfigurationName="test_launch_configuration",
ImageId=EXAMPLE_AMI_ID,
InstanceType="t2.medium",
)
_ = client.create_auto_scaling_group(
AutoScalingGroupName="test_asg",
LaunchConfigurationName="test_launch_configuration",
MinSize=0,
MaxSize=20,
DesiredCapacity=5,
VPCZoneIdentifier=mocked_networking["subnet1"],
NewInstancesProtectedFromScaleIn=False,
)
response = client.describe_auto_scaling_groups(AutoScalingGroupNames=["test_asg"])
instance_ids = [
instance["InstanceId"]
for instance in response["AutoScalingGroups"][0]["Instances"]
]
protected = instance_ids[:3]
_ = client.set_instance_protection(
AutoScalingGroupName="test_asg",
InstanceIds=protected,
ProtectedFromScaleIn=True,
)
response = client.describe_auto_scaling_groups(AutoScalingGroupNames=["test_asg"])
for instance in response["AutoScalingGroups"][0]["Instances"]:
instance["ProtectedFromScaleIn"].should.equal(
instance["InstanceId"] in protected
)
@mock_autoscaling
def test_set_desired_capacity_up():
mocked_networking = setup_networking()
client = boto3.client("autoscaling", region_name="us-east-1")
_ = client.create_launch_configuration(
LaunchConfigurationName="test_launch_configuration",
ImageId=EXAMPLE_AMI_ID,
InstanceType="t2.medium",
)
_ = client.create_auto_scaling_group(
AutoScalingGroupName="test_asg",
LaunchConfigurationName="test_launch_configuration",
MinSize=0,
MaxSize=20,
DesiredCapacity=5,
VPCZoneIdentifier=mocked_networking["subnet1"],
NewInstancesProtectedFromScaleIn=True,
)
_ = client.set_desired_capacity(AutoScalingGroupName="test_asg", DesiredCapacity=10)
response = client.describe_auto_scaling_groups(AutoScalingGroupNames=["test_asg"])
instances = response["AutoScalingGroups"][0]["Instances"]
instances.should.have.length_of(10)
for instance in instances:
instance["ProtectedFromScaleIn"].should.equal(True)
@mock_autoscaling
def test_set_desired_capacity_down():
mocked_networking = setup_networking()
client = boto3.client("autoscaling", region_name="us-east-1")
_ = client.create_launch_configuration(
LaunchConfigurationName="test_launch_configuration",
ImageId=EXAMPLE_AMI_ID,
InstanceType="t2.medium",
)
_ = client.create_auto_scaling_group(
AutoScalingGroupName="test_asg",
LaunchConfigurationName="test_launch_configuration",
MinSize=0,
MaxSize=20,
DesiredCapacity=5,
VPCZoneIdentifier=mocked_networking["subnet1"],
NewInstancesProtectedFromScaleIn=True,
)
response = client.describe_auto_scaling_groups(AutoScalingGroupNames=["test_asg"])
instance_ids = [
instance["InstanceId"]
for instance in response["AutoScalingGroups"][0]["Instances"]
]
unprotected, protected = instance_ids[:2], instance_ids[2:]
_ = client.set_instance_protection(
AutoScalingGroupName="test_asg",
InstanceIds=unprotected,
ProtectedFromScaleIn=False,
)
_ = client.set_desired_capacity(AutoScalingGroupName="test_asg", DesiredCapacity=1)
response = client.describe_auto_scaling_groups(AutoScalingGroupNames=["test_asg"])
group = response["AutoScalingGroups"][0]
group["DesiredCapacity"].should.equal(1)
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_via_ec2_in_autoscaling_group():
mocked_networking = setup_networking()
client = boto3.client("autoscaling", region_name="us-east-1")
_ = client.create_launch_configuration(
LaunchConfigurationName="test_launch_configuration",
ImageId=EXAMPLE_AMI_ID,
InstanceType="t2.medium",
)
_ = 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)
@mock_ec2
@mock_autoscaling
def test_attach_instances():
asg_client = boto3.client("autoscaling", region_name="us-east-1")
ec2_client = boto3.client("ec2", region_name="us-east-1")
kwargs = {
"KeyName": "foobar",
"ImageId": EXAMPLE_AMI_ID,
"MinCount": 1,
"MaxCount": 1,
"InstanceType": "c4.2xlarge",
"TagSpecifications": [
{"ResourceType": "instance", "Tags": [{"Key": "key", "Value": "val"}]},
],
}
fake_instance = ec2_client.run_instances(**kwargs)["Instances"][0]
asg_client.create_launch_configuration(
LaunchConfigurationName="test_launch_configuration",
ImageId="ami-pytest",
InstanceType="t3.micro",
KeyName="foobar",
)
asg_client.create_auto_scaling_group(
AutoScalingGroupName="test_asg",
LaunchConfigurationName="test_launch_configuration",
MinSize=0,
MaxSize=1,
AvailabilityZones=[fake_instance["Placement"]["AvailabilityZone"]],
)
asg_client.attach_instances(
InstanceIds=[fake_instance["InstanceId"]], AutoScalingGroupName="test_asg"
)
response = asg_client.describe_auto_scaling_instances()
len(response["AutoScalingInstances"]).should.equal(1)
for instance in response["AutoScalingInstances"]:
instance["LaunchConfigurationName"].should.equal("test_launch_configuration")
instance["AutoScalingGroupName"].should.equal("test_asg")
instance["InstanceType"].should.equal("c4.2xlarge")
@mock_autoscaling
def test_autoscaling_lifecyclehook():
mocked_networking = setup_networking()
client = boto3.client("autoscaling", region_name="us-east-1")
client.create_launch_configuration(
LaunchConfigurationName="test_launch_configuration",
ImageId="ami-pytest",
InstanceType="t3.micro",
KeyName="foobar",
)
client.create_auto_scaling_group(
AutoScalingGroupName="test_asg",
LaunchConfigurationName="test_launch_configuration",
MinSize=0,
MaxSize=1,
VPCZoneIdentifier=mocked_networking["subnet1"],
)
client.put_lifecycle_hook(
LifecycleHookName="test-lifecyclehook",
AutoScalingGroupName="test_asg",
LifecycleTransition="autoscaling:EC2_INSTANCE_TERMINATING",
)
response = client.describe_lifecycle_hooks(
AutoScalingGroupName="test_asg", LifecycleHookNames=["test-lifecyclehook"]
)
len(response["LifecycleHooks"]).should.equal(1)
for hook in response["LifecycleHooks"]:
hook["LifecycleHookName"].should.equal("test-lifecyclehook")
hook["AutoScalingGroupName"].should.equal("test_asg")
hook["LifecycleTransition"].should.equal("autoscaling:EC2_INSTANCE_TERMINATING")
client.delete_lifecycle_hook(
LifecycleHookName="test-lifecyclehook", AutoScalingGroupName="test_asg"
)
response = client.describe_lifecycle_hooks(
AutoScalingGroupName="test_asg", LifecycleHookNames=["test-lifecyclehook"]
)
len(response["LifecycleHooks"]).should.equal(0)
@pytest.mark.parametrize("original,new", [(2, 1), (2, 3), (1, 5), (1, 1)])
@mock_autoscaling
def test_set_desired_capacity_without_protection(original, new):
mocked_networking = setup_networking()
client = boto3.client("autoscaling", region_name="us-east-1")
client.create_launch_configuration(
LaunchConfigurationName="test_launch_configuration",
ImageId=EXAMPLE_AMI_ID,
InstanceType="t2.medium",
)
client.create_auto_scaling_group(
AutoScalingGroupName="tester_group",
LaunchConfigurationName="test_launch_configuration",
AvailabilityZones=["us-east-1a"],
MinSize=original,
MaxSize=original,
DesiredCapacity=original,
VPCZoneIdentifier=mocked_networking["subnet1"],
)
group = client.describe_auto_scaling_groups()["AutoScalingGroups"][0]
group["DesiredCapacity"].should.equal(original)
instances = client.describe_auto_scaling_instances()["AutoScalingInstances"]
instances.should.have.length_of(original)
client.update_auto_scaling_group(
AutoScalingGroupName="tester_group", DesiredCapacity=new
)
group = client.describe_auto_scaling_groups()["AutoScalingGroups"][0]
group["DesiredCapacity"].should.equal(new)
instances = client.describe_auto_scaling_instances()["AutoScalingInstances"]
instances.should.have.length_of(new)
@mock_autoscaling
@mock_ec2
def test_create_template_with_block_device():
ec2_client = boto3.client("ec2", region_name="ap-southeast-2")
ec2_client.create_launch_template(
LaunchTemplateName="launchie",
LaunchTemplateData={
"ImageId": EXAMPLE_AMI_ID,
"BlockDeviceMappings": [
{
"DeviceName": "/dev/sda1",
"Ebs": {
"VolumeSize": 20,
"DeleteOnTermination": True,
"VolumeType": "gp3",
"Encrypted": True,
},
}
],
},
)
ec2_client.run_instances(
MaxCount=1, MinCount=1, LaunchTemplate={"LaunchTemplateName": "launchie"}
)
ec2_client = boto3.client("ec2", region_name="ap-southeast-2")
volumes = ec2_client.describe_volumes()["Volumes"]
# The standard root volume
volumes[0]["VolumeType"].should.equal("gp2")
volumes[0]["Size"].should.equal(8)
# Our Ebs-volume
volumes[1]["VolumeType"].should.equal("gp3")
volumes[1]["Size"].should.equal(20)