import boto
import boto3
import boto.ec2.autoscale
from boto.ec2.autoscale.launchconfig import LaunchConfiguration
from boto.ec2.autoscale.group import AutoScalingGroup
from boto.ec2.autoscale import Tag
import boto.ec2.elb
import sure  # noqa # pylint: disable=unused-import
from botocore.exceptions import ClientError
import pytest

from moto import (
    mock_autoscaling,
    mock_ec2_deprecated,
    mock_elb_deprecated,
    mock_elb,
    mock_autoscaling_deprecated,
    mock_ec2,
)
from moto.core import ACCOUNT_ID
from tests.helpers import requires_boto_gte

from .utils import (
    setup_networking,
    setup_networking_deprecated,
    setup_instance_with_networking,
)
from tests import EXAMPLE_AMI_ID


# Has boto3 equivalent
@mock_autoscaling_deprecated
@mock_elb_deprecated
@mock_ec2_deprecated
def test_create_autoscaling_group():
    mocked_networking = setup_networking_deprecated()
    elb_conn = boto.ec2.elb.connect_to_region("us-east-1")
    elb_conn.create_load_balancer("test_lb", zones=[], listeners=[(80, 8080, "http")])

    # we attach a couple of machines to the load balancer
    # that are not managed by the auto scaling group
    INSTANCE_COUNT_START = 3
    INSTANCE_COUNT_GROUP = 2
    ec2 = boto3.resource("ec2", region_name="us-east-1")
    instances = ec2.create_instances(
        ImageId=EXAMPLE_AMI_ID,
        InstanceType="t1.micro",
        MaxCount=INSTANCE_COUNT_START,
        MinCount=INSTANCE_COUNT_START,
        SubnetId=mocked_networking["subnet1"],
    )

    instances_ids = [_.id for _ in instances]
    elb_conn.register_instances(
        "test_lb", instances_ids,
    )

    conn = boto.ec2.autoscale.connect_to_region("us-east-1")
    config = LaunchConfiguration(
        name="tester", image_id=EXAMPLE_AMI_ID, instance_type="t2.medium"
    )
    conn.create_launch_configuration(config)

    group = AutoScalingGroup(
        name="tester_group",
        availability_zones=["us-east-1a", "us-east-1b"],
        default_cooldown=60,
        desired_capacity=INSTANCE_COUNT_GROUP,
        health_check_period=100,
        health_check_type="EC2",
        max_size=INSTANCE_COUNT_GROUP,
        min_size=INSTANCE_COUNT_GROUP,
        launch_config=config,
        load_balancers=["test_lb"],
        placement_group="test_placement",
        vpc_zone_identifier="{subnet1},{subnet2}".format(
            subnet1=mocked_networking["subnet1"], subnet2=mocked_networking["subnet2"]
        ),
        termination_policies=["OldestInstance", "NewestInstance"],
        tags=[
            Tag(
                resource_id="tester_group",
                key="test_key",
                value="test_value",
                propagate_at_launch=True,
            )
        ],
    )
    conn.create_auto_scaling_group(group)

    group = conn.get_all_groups()[0]
    group.name.should.equal("tester_group")
    set(group.availability_zones).should.equal(set(["us-east-1a", "us-east-1b"]))
    group.desired_capacity.should.equal(2)
    group.max_size.should.equal(INSTANCE_COUNT_GROUP)
    group.min_size.should.equal(INSTANCE_COUNT_GROUP)
    group.instances.should.have.length_of(INSTANCE_COUNT_GROUP)
    group.vpc_zone_identifier.should.equal(
        "{subnet1},{subnet2}".format(
            subnet1=mocked_networking["subnet1"], subnet2=mocked_networking["subnet2"]
        )
    )
    group.launch_config_name.should.equal("tester")
    group.default_cooldown.should.equal(60)
    group.health_check_period.should.equal(100)
    group.health_check_type.should.equal("EC2")
    list(group.load_balancers).should.equal(["test_lb"])
    group.placement_group.should.equal("test_placement")
    list(group.termination_policies).should.equal(["OldestInstance", "NewestInstance"])
    len(list(group.tags)).should.equal(1)
    tag = list(group.tags)[0]
    tag.resource_id.should.equal("tester_group")
    tag.key.should.equal("test_key")
    tag.value.should.equal("test_value")
    tag.propagate_at_launch.should.equal(True)

    instances_attached = elb_conn.describe_instance_health("test_lb")
    len(instances_attached).should.equal(INSTANCE_COUNT_START + INSTANCE_COUNT_GROUP)


@mock_autoscaling
@mock_ec2
@mock_elb
def test_create_autoscaling_group_boto3_within_elb():
    mocked_networking = setup_networking()
    elb_client = boto3.client("elb", region_name="us-east-1")
    elb_client.create_load_balancer(
        LoadBalancerName="test_lb",
        Listeners=[{"Protocol": "http", "LoadBalancerPort": 80, "InstancePort": 8080}],
        AvailabilityZones=[],
    )

    # we attach a couple of machines to the load balancer
    # that are not managed by the auto scaling group
    INSTANCE_COUNT_START = 3
    INSTANCE_COUNT_GROUP = 2
    ec2 = boto3.resource("ec2", region_name="us-east-1")
    instances = ec2.create_instances(
        ImageId=EXAMPLE_AMI_ID,
        InstanceType="t1.micro",
        MaxCount=INSTANCE_COUNT_START,
        MinCount=INSTANCE_COUNT_START,
        SubnetId=mocked_networking["subnet1"],
    )

    instances_ids = [_.id for _ in instances]
    elb_client.register_instances_with_load_balancer(
        LoadBalancerName="test_lb",
        Instances=[{"InstanceId": id} for id in instances_ids],
    )

    as_client = boto3.client("autoscaling", region_name="us-east-1")
    as_client.create_launch_configuration(
        LaunchConfigurationName="tester",
        ImageId=EXAMPLE_AMI_ID,
        InstanceType="t2.medium",
    )

    as_client.create_auto_scaling_group(
        AutoScalingGroupName="tester_group",
        AvailabilityZones=["us-east-1a", "us-east-1b"],
        DefaultCooldown=60,
        DesiredCapacity=INSTANCE_COUNT_GROUP,
        HealthCheckGracePeriod=100,
        HealthCheckType="EC2",
        LaunchConfigurationName="tester",
        LoadBalancerNames=["test_lb"],
        MinSize=INSTANCE_COUNT_GROUP,
        MaxSize=INSTANCE_COUNT_GROUP,
        PlacementGroup="test_placement",
        Tags=[
            {
                "ResourceId": "tester_group",
                "ResourceType": "group",
                "Key": "test_key",
                "Value": "test_value",
                "PropagateAtLaunch": True,
            }
        ],
        TerminationPolicies=["OldestInstance", "NewestInstance"],
        VPCZoneIdentifier="{subnet1},{subnet2}".format(
            subnet1=mocked_networking["subnet1"], subnet2=mocked_networking["subnet2"]
        ),
    )

    group = as_client.describe_auto_scaling_groups()["AutoScalingGroups"][0]
    group["AutoScalingGroupName"].should.equal("tester_group")
    set(group["AvailabilityZones"]).should.equal(set(["us-east-1a", "us-east-1b"]))
    group["DesiredCapacity"].should.equal(2)
    group["MaxSize"].should.equal(INSTANCE_COUNT_GROUP)
    group["MinSize"].should.equal(INSTANCE_COUNT_GROUP)
    group["Instances"].should.have.length_of(INSTANCE_COUNT_GROUP)
    group["VPCZoneIdentifier"].should.equal(
        "{subnet1},{subnet2}".format(
            subnet1=mocked_networking["subnet1"], subnet2=mocked_networking["subnet2"]
        )
    )
    group["LaunchConfigurationName"].should.equal("tester")
    group["DefaultCooldown"].should.equal(60)
    group["HealthCheckGracePeriod"].should.equal(100)
    group["HealthCheckType"].should.equal("EC2")
    group["LoadBalancerNames"].should.equal(["test_lb"])
    group["PlacementGroup"].should.equal("test_placement")
    list(group["TerminationPolicies"]).should.equal(
        ["OldestInstance", "NewestInstance"]
    )
    list(group["Tags"]).should.have.length_of(1)
    tag = group["Tags"][0]
    tag["ResourceId"].should.equal("tester_group")
    tag["Key"].should.equal("test_key")
    tag["Value"].should.equal("test_value")
    tag["PropagateAtLaunch"].should.equal(True)

    instances_attached = elb_client.describe_instance_health(
        LoadBalancerName="test_lb"
    )["InstanceStates"]
    instances_attached.should.have.length_of(
        INSTANCE_COUNT_START + INSTANCE_COUNT_GROUP
    )
    attached_ids = [i["InstanceId"] for i in instances_attached]
    for ec2_instance_id in instances_ids:
        attached_ids.should.contain(ec2_instance_id)


# Has boto3 equivalent
@mock_autoscaling_deprecated
def test_create_autoscaling_groups_defaults():
    """Test with the minimum inputs and check that all of the proper defaults
    are assigned for the other attributes"""

    mocked_networking = setup_networking_deprecated()
    conn = boto.connect_autoscale()
    config = LaunchConfiguration(
        name="tester", image_id=EXAMPLE_AMI_ID, instance_type="t2.medium"
    )
    conn.create_launch_configuration(config)

    group = AutoScalingGroup(
        name="tester_group",
        max_size=2,
        min_size=2,
        launch_config=config,
        vpc_zone_identifier=mocked_networking["subnet1"],
    )
    conn.create_auto_scaling_group(group)

    group = conn.get_all_groups()[0]
    group.name.should.equal("tester_group")
    group.max_size.should.equal(2)
    group.min_size.should.equal(2)
    group.launch_config_name.should.equal("tester")

    # Defaults
    list(group.availability_zones).should.equal(["us-east-1a"])  # subnet1
    group.desired_capacity.should.equal(2)
    group.vpc_zone_identifier.should.equal(mocked_networking["subnet1"])
    group.default_cooldown.should.equal(300)
    group.health_check_period.should.equal(300)
    group.health_check_type.should.equal("EC2")
    list(group.load_balancers).should.equal([])
    group.placement_group.should.equal(None)
    list(group.termination_policies).should.equal([])
    list(group.tags).should.equal([])


@mock_autoscaling
def test_create_autoscaling_groups_defaults_boto3():
    """Test with the minimum inputs and check that all of the proper defaults
    are assigned for the other attributes"""

    mocked_networking = setup_networking()
    as_client = boto3.client("autoscaling", region_name="us-east-1")
    as_client.create_launch_configuration(
        LaunchConfigurationName="tester_config",
        ImageId=EXAMPLE_AMI_ID,
        InstanceType="t2.medium",
    )

    as_client.create_auto_scaling_group(
        AutoScalingGroupName="tester_group",
        LaunchConfigurationName="tester_config",
        MinSize=2,
        MaxSize=2,
        VPCZoneIdentifier=mocked_networking["subnet1"],
    )

    group = as_client.describe_auto_scaling_groups()["AutoScalingGroups"][0]
    group["AutoScalingGroupName"].should.equal("tester_group")
    group["MaxSize"].should.equal(2)
    group["MinSize"].should.equal(2)
    group["LaunchConfigurationName"].should.equal("tester_config")

    # Defaults
    group["AvailabilityZones"].should.equal(["us-east-1a"])  # subnet1
    group["DesiredCapacity"].should.equal(2)
    group["VPCZoneIdentifier"].should.equal(mocked_networking["subnet1"])
    group["DefaultCooldown"].should.equal(300)
    group["HealthCheckGracePeriod"].should.equal(300)
    group["HealthCheckType"].should.equal("EC2")
    group["LoadBalancerNames"].should.equal([])
    group.shouldnt.have.key("PlacementGroup")
    group["TerminationPolicies"].should.equal([])
    group["Tags"].should.equal([])


@mock_autoscaling
def test_list_many_autoscaling_groups():
    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",
    )

    for i in range(51):
        conn.create_auto_scaling_group(
            AutoScalingGroupName="TestGroup%d" % i,
            MinSize=1,
            MaxSize=2,
            LaunchConfigurationName="TestLC",
            VPCZoneIdentifier=mocked_networking["subnet1"],
        )

    response = conn.describe_auto_scaling_groups()
    groups = response["AutoScalingGroups"]
    marker = response["NextToken"]
    groups.should.have.length_of(50)
    marker.should.equal(groups[-1]["AutoScalingGroupName"])

    response2 = conn.describe_auto_scaling_groups(NextToken=marker)

    groups.extend(response2["AutoScalingGroups"])
    groups.should.have.length_of(51)
    assert "NextToken" not in response2.keys()


@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"})


# Has boto3 equivalent
@mock_autoscaling_deprecated
def test_autoscaling_group_describe_filter():
    mocked_networking = setup_networking_deprecated()
    conn = boto.connect_autoscale()
    config = LaunchConfiguration(
        name="tester", image_id=EXAMPLE_AMI_ID, instance_type="t2.medium"
    )
    conn.create_launch_configuration(config)

    group = AutoScalingGroup(
        name="tester_group",
        max_size=2,
        min_size=2,
        launch_config=config,
        vpc_zone_identifier=mocked_networking["subnet1"],
    )
    conn.create_auto_scaling_group(group)
    group.name = "tester_group2"
    conn.create_auto_scaling_group(group)
    group.name = "tester_group3"
    conn.create_auto_scaling_group(group)

    conn.get_all_groups(names=["tester_group", "tester_group2"]).should.have.length_of(
        2
    )
    conn.get_all_groups().should.have.length_of(3)


# Has boto3 equivalent
@mock_autoscaling_deprecated
def test_autoscaling_update():
    mocked_networking = setup_networking_deprecated()
    conn = boto.connect_autoscale()
    config = LaunchConfiguration(
        name="tester", image_id=EXAMPLE_AMI_ID, instance_type="t2.medium"
    )
    conn.create_launch_configuration(config)

    group = AutoScalingGroup(
        name="tester_group",
        desired_capacity=2,
        max_size=2,
        min_size=2,
        launch_config=config,
        vpc_zone_identifier=mocked_networking["subnet1"],
    )
    conn.create_auto_scaling_group(group)

    group = conn.get_all_groups()[0]
    group.availability_zones.should.equal(["us-east-1a"])
    group.vpc_zone_identifier.should.equal(mocked_networking["subnet1"])

    group.availability_zones = ["us-east-1b"]
    group.vpc_zone_identifier = mocked_networking["subnet2"]
    group.update()

    group = conn.get_all_groups()[0]
    group.availability_zones.should.equal(["us-east-1b"])
    group.vpc_zone_identifier.should.equal(mocked_networking["subnet2"])


# Has boto3 equivalent
@mock_autoscaling_deprecated
def test_autoscaling_tags_update():
    mocked_networking = setup_networking_deprecated()
    conn = boto.connect_autoscale()
    config = LaunchConfiguration(
        name="tester", image_id=EXAMPLE_AMI_ID, instance_type="t2.medium"
    )
    conn.create_launch_configuration(config)

    group = AutoScalingGroup(
        name="tester_group",
        availability_zones=["us-east-1a"],
        desired_capacity=2,
        max_size=2,
        min_size=2,
        launch_config=config,
        tags=[
            Tag(
                resource_id="tester_group",
                key="test_key",
                value="test_value",
                propagate_at_launch=True,
            )
        ],
        vpc_zone_identifier=mocked_networking["subnet1"],
    )
    conn.create_auto_scaling_group(group)

    conn.create_or_update_tags(
        tags=[
            Tag(
                resource_id="tester_group",
                key="test_key",
                value="new_test_value",
                propagate_at_launch=True,
            ),
            Tag(
                resource_id="tester_group",
                key="test_key2",
                value="test_value2",
                propagate_at_launch=True,
            ),
        ]
    )
    group = conn.get_all_groups()[0]
    group.tags.should.have.length_of(2)


# Has boto3 equivalent
@mock_autoscaling_deprecated
def test_autoscaling_group_delete():
    mocked_networking = setup_networking_deprecated()
    conn = boto.connect_autoscale()
    config = LaunchConfiguration(
        name="tester", image_id=EXAMPLE_AMI_ID, instance_type="t2.medium"
    )
    conn.create_launch_configuration(config)

    group = AutoScalingGroup(
        name="tester_group",
        max_size=2,
        min_size=2,
        launch_config=config,
        vpc_zone_identifier=mocked_networking["subnet1"],
    )
    conn.create_auto_scaling_group(group)

    conn.get_all_groups().should.have.length_of(1)

    conn.delete_auto_scaling_group("tester_group")
    conn.get_all_groups().should.have.length_of(0)


@mock_autoscaling
def test_autoscaling_group_delete_boto3():
    mocked_networking = setup_networking()
    as_client = boto3.client("autoscaling", region_name="us-east-1")
    as_client.create_launch_configuration(
        LaunchConfigurationName="tester_config",
        ImageId=EXAMPLE_AMI_ID,
        InstanceType="t2.medium",
    )

    as_client.create_auto_scaling_group(
        AutoScalingGroupName="tester_group",
        LaunchConfigurationName="tester_config",
        MinSize=2,
        MaxSize=2,
        VPCZoneIdentifier=mocked_networking["subnet1"],
    )

    as_client.describe_auto_scaling_groups()["AutoScalingGroups"].should.have.length_of(
        1
    )

    as_client.delete_auto_scaling_group(AutoScalingGroupName="tester_group")
    as_client.describe_auto_scaling_groups()["AutoScalingGroups"].should.have.length_of(
        0
    )


# Has boto3 equivalent
@mock_ec2_deprecated
@mock_autoscaling_deprecated
def test_autoscaling_group_describe_instances():
    mocked_networking = setup_networking_deprecated()
    conn = boto.ec2.autoscale.connect_to_region("us-east-1")
    config = LaunchConfiguration(
        name="tester", image_id=EXAMPLE_AMI_ID, instance_type="t2.medium"
    )
    conn.create_launch_configuration(config)

    group = AutoScalingGroup(
        name="tester_group",
        max_size=2,
        min_size=2,
        launch_config=config,
        vpc_zone_identifier=mocked_networking["subnet1"],
    )
    conn.create_auto_scaling_group(group)

    instances = list(conn.get_all_autoscaling_instances())
    instances.should.have.length_of(2)
    instances[0].launch_config_name.should.equal("tester")
    instances[0].health_status.should.equal("Healthy")
    autoscale_instance_ids = [instance.instance_id for instance in instances]

    ec2_conn = boto.ec2.connect_to_region("us-east-1")
    reservations = ec2_conn.get_all_reservations()
    instances = reservations[0].instances
    instances.should.have.length_of(2)
    instance_ids = [instance.id for instance in instances]
    set(autoscale_instance_ids).should.equal(set(instance_ids))
    instances[0].instance_type.should.equal("t2.medium")


# Has boto3 equivalent
@requires_boto_gte("2.8")
@mock_autoscaling_deprecated
def test_set_desired_capacity_up():
    mocked_networking = setup_networking_deprecated()
    conn = boto.connect_autoscale()
    config = LaunchConfiguration(
        name="tester", image_id=EXAMPLE_AMI_ID, instance_type="t2.medium"
    )
    conn.create_launch_configuration(config)

    group = AutoScalingGroup(
        name="tester_group",
        availability_zones=["us-east-1a"],
        desired_capacity=2,
        max_size=2,
        min_size=2,
        launch_config=config,
        vpc_zone_identifier=mocked_networking["subnet1"],
    )
    conn.create_auto_scaling_group(group)

    group = conn.get_all_groups()[0]
    group.desired_capacity.should.equal(2)
    instances = list(conn.get_all_autoscaling_instances())
    instances.should.have.length_of(2)

    conn.set_desired_capacity("tester_group", 3)
    group = conn.get_all_groups()[0]
    group.desired_capacity.should.equal(3)

    instances = list(conn.get_all_autoscaling_instances())
    instances.should.have.length_of(3)


# Has boto3 equivalent
@requires_boto_gte("2.8")
@mock_autoscaling_deprecated
def test_set_desired_capacity_down():
    mocked_networking = setup_networking_deprecated()
    conn = boto.connect_autoscale()
    config = LaunchConfiguration(
        name="tester", image_id=EXAMPLE_AMI_ID, instance_type="t2.medium"
    )
    conn.create_launch_configuration(config)

    group = AutoScalingGroup(
        name="tester_group",
        availability_zones=["us-east-1a"],
        desired_capacity=2,
        max_size=2,
        min_size=2,
        launch_config=config,
        vpc_zone_identifier=mocked_networking["subnet1"],
    )
    conn.create_auto_scaling_group(group)

    group = conn.get_all_groups()[0]
    group.desired_capacity.should.equal(2)
    instances = list(conn.get_all_autoscaling_instances())
    instances.should.have.length_of(2)

    conn.set_desired_capacity("tester_group", 1)
    group = conn.get_all_groups()[0]
    group.desired_capacity.should.equal(1)

    instances = list(conn.get_all_autoscaling_instances())
    instances.should.have.length_of(1)


# Has boto3 equivalent
@requires_boto_gte("2.8")
@mock_autoscaling_deprecated
def test_set_desired_capacity_the_same():
    mocked_networking = setup_networking_deprecated()
    conn = boto.connect_autoscale()
    config = LaunchConfiguration(
        name="tester", image_id=EXAMPLE_AMI_ID, instance_type="t2.medium"
    )
    conn.create_launch_configuration(config)

    group = AutoScalingGroup(
        name="tester_group",
        availability_zones=["us-east-1a"],
        desired_capacity=2,
        max_size=2,
        min_size=2,
        launch_config=config,
        vpc_zone_identifier=mocked_networking["subnet1"],
    )
    conn.create_auto_scaling_group(group)

    group = conn.get_all_groups()[0]
    group.desired_capacity.should.equal(2)
    instances = list(conn.get_all_autoscaling_instances())
    instances.should.have.length_of(2)

    conn.set_desired_capacity("tester_group", 2)
    group = conn.get_all_groups()[0]
    group.desired_capacity.should.equal(2)

    instances = list(conn.get_all_autoscaling_instances())
    instances.should.have.length_of(2)


# Has boto3 equivalent
@mock_autoscaling_deprecated
@mock_elb_deprecated
def test_autoscaling_group_with_elb():
    mocked_networking = setup_networking_deprecated()
    elb_conn = boto.connect_elb()
    zones = ["us-east-1a", "us-east-1b"]
    ports = [(80, 8080, "http"), (443, 8443, "tcp")]
    elb_conn.create_load_balancer("my-lb", zones, ports)
    instances_health = elb_conn.describe_instance_health("my-lb")
    instances_health.should.be.empty

    conn = boto.connect_autoscale()
    config = LaunchConfiguration(
        name="tester", image_id=EXAMPLE_AMI_ID, instance_type="t2.medium"
    )
    conn.create_launch_configuration(config)
    group = AutoScalingGroup(
        name="tester_group",
        max_size=2,
        min_size=2,
        launch_config=config,
        load_balancers=["my-lb"],
        vpc_zone_identifier=mocked_networking["subnet1"],
    )
    conn.create_auto_scaling_group(group)
    group = conn.get_all_groups()[0]
    elb = elb_conn.get_all_load_balancers()[0]
    group.desired_capacity.should.equal(2)
    elb.instances.should.have.length_of(2)

    autoscale_instance_ids = set(instance.instance_id for instance in group.instances)
    elb_instace_ids = set(instance.id for instance in elb.instances)
    autoscale_instance_ids.should.equal(elb_instace_ids)

    conn.set_desired_capacity("tester_group", 3)
    group = conn.get_all_groups()[0]
    elb = elb_conn.get_all_load_balancers()[0]
    group.desired_capacity.should.equal(3)
    elb.instances.should.have.length_of(3)

    autoscale_instance_ids = set(instance.instance_id for instance in group.instances)
    elb_instace_ids = set(instance.id for instance in elb.instances)
    autoscale_instance_ids.should.equal(elb_instace_ids)

    conn.delete_auto_scaling_group("tester_group")
    conn.get_all_groups().should.have.length_of(0)
    elb = elb_conn.get_all_load_balancers()[0]
    elb.instances.should.have.length_of(0)


@mock_autoscaling
@mock_elb
def test_describe_load_balancers():
    mocked_networking = setup_networking()
    INSTANCE_COUNT = 2

    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"],
    )

    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",
        LoadBalancerNames=["my-lb"],
        MinSize=0,
        MaxSize=INSTANCE_COUNT,
        DesiredCapacity=INSTANCE_COUNT,
        Tags=[
            {
                "ResourceId": "test_asg",
                "Key": "test_key",
                "Value": "test_value",
                "PropagateAtLaunch": True,
            }
        ],
        VPCZoneIdentifier=mocked_networking["subnet1"],
    )

    response = client.describe_load_balancers(AutoScalingGroupName="test_asg")
    assert response["ResponseMetadata"]["RequestId"]
    list(response["LoadBalancers"]).should.have.length_of(1)
    response["LoadBalancers"][0]["LoadBalancerName"].should.equal("my-lb")


@mock_autoscaling
@mock_elb
def test_create_elb_and_autoscaling_group_no_relationship():
    mocked_networking = setup_networking()
    INSTANCE_COUNT = 2
    ELB_NAME = "my-elb"

    elb_client = boto3.client("elb", region_name="us-east-1")
    elb_client.create_load_balancer(
        LoadBalancerName=ELB_NAME,
        Listeners=[{"Protocol": "tcp", "LoadBalancerPort": 80, "InstancePort": 8080}],
        AvailabilityZones=["us-east-1a", "us-east-1b"],
    )

    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=INSTANCE_COUNT,
        DesiredCapacity=INSTANCE_COUNT,
        VPCZoneIdentifier=mocked_networking["subnet1"],
    )

    # autoscaling group and elb should have no relationship
    response = client.describe_load_balancers(AutoScalingGroupName="test_asg")
    list(response["LoadBalancers"]).should.have.length_of(0)
    response = elb_client.describe_load_balancers(LoadBalancerNames=[ELB_NAME])
    list(response["LoadBalancerDescriptions"][0]["Instances"]).should.have.length_of(0)


@mock_autoscaling
@mock_elb
def test_attach_load_balancer():
    mocked_networking = setup_networking()
    INSTANCE_COUNT = 2

    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"],
    )

    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=INSTANCE_COUNT,
        DesiredCapacity=INSTANCE_COUNT,
        Tags=[
            {
                "ResourceId": "test_asg",
                "Key": "test_key",
                "Value": "test_value",
                "PropagateAtLaunch": True,
            }
        ],
        VPCZoneIdentifier=mocked_networking["subnet1"],
    )

    response = client.attach_load_balancers(
        AutoScalingGroupName="test_asg", LoadBalancerNames=["my-lb"]
    )
    response["ResponseMetadata"]["HTTPStatusCode"].should.equal(200)

    response = elb_client.describe_load_balancers(LoadBalancerNames=["my-lb"])
    list(response["LoadBalancerDescriptions"][0]["Instances"]).should.have.length_of(
        INSTANCE_COUNT
    )

    response = client.describe_auto_scaling_groups(AutoScalingGroupNames=["test_asg"])
    list(response["AutoScalingGroups"][0]["LoadBalancerNames"]).should.have.length_of(1)


@mock_autoscaling
@mock_elb
def test_detach_load_balancer():
    mocked_networking = setup_networking()
    INSTANCE_COUNT = 2

    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"],
    )

    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",
        LoadBalancerNames=["my-lb"],
        MinSize=0,
        MaxSize=INSTANCE_COUNT,
        DesiredCapacity=INSTANCE_COUNT,
        Tags=[
            {
                "ResourceId": "test_asg",
                "Key": "test_key",
                "Value": "test_value",
                "PropagateAtLaunch": True,
            }
        ],
        VPCZoneIdentifier=mocked_networking["subnet1"],
    )

    response = client.detach_load_balancers(
        AutoScalingGroupName="test_asg", LoadBalancerNames=["my-lb"]
    )
    response["ResponseMetadata"]["HTTPStatusCode"].should.equal(200)

    response = elb_client.describe_load_balancers(LoadBalancerNames=["my-lb"])
    list(response["LoadBalancerDescriptions"][0]["Instances"]).should.have.length_of(0)

    response = client.describe_load_balancers(AutoScalingGroupName="test_asg")
    list(response["LoadBalancers"]).should.have.length_of(0)


@mock_autoscaling
def test_create_autoscaling_group_boto3():
    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",
    )
    response = client.create_auto_scaling_group(
        AutoScalingGroupName="test_asg",
        LaunchConfigurationName="test_launch_configuration",
        MinSize=0,
        MaxSize=20,
        DesiredCapacity=5,
        Tags=[
            {
                "ResourceId": "test_asg",
                "ResourceType": "auto-scaling-group",
                "Key": "propogated-tag-key",
                "Value": "propagate-tag-value",
                "PropagateAtLaunch": True,
            },
            {
                "ResourceId": "test_asg",
                "ResourceType": "auto-scaling-group",
                "Key": "not-propogated-tag-key",
                "Value": "not-propagate-tag-value",
                "PropagateAtLaunch": False,
            },
        ],
        VPCZoneIdentifier=mocked_networking["subnet1"],
        NewInstancesProtectedFromScaleIn=False,
    )
    response["ResponseMetadata"]["HTTPStatusCode"].should.equal(200)


@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,
        Tags=[
            {
                "ResourceId": "test_asg",
                "ResourceType": "auto-scaling-group",
                "Key": "propogated-tag-key",
                "Value": "propagate-tag-value",
                "PropagateAtLaunch": True,
            },
            {
                "ResourceId": "test_asg",
                "ResourceType": "auto-scaling-group",
                "Key": "not-propogated-tag-key",
                "Value": "not-propagate-tag-value",
                "PropagateAtLaunch": False,
            },
        ],
        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_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_boto3_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_boto3_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
def test_describe_autoscaling_groups_boto3_launch_config():
    mocked_networking = setup_networking(region_name="eu-north-1")
    client = boto3.client("autoscaling", region_name="eu-north-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_groups(AutoScalingGroupNames=["test_asg"])
    response["ResponseMetadata"]["HTTPStatusCode"].should.equal(200)
    group = response["AutoScalingGroups"][0]
    group["AutoScalingGroupARN"].should.match(
        f"arn:aws:autoscaling:eu-north-1:{ACCOUNT_ID}:autoScalingGroup:"
    )
    group["AutoScalingGroupName"].should.equal("test_asg")
    group["LaunchConfigurationName"].should.equal("test_launch_configuration")
    group.should_not.have.key("LaunchTemplate")
    group["AvailabilityZones"].should.equal(["eu-north-1a"])
    group["VPCZoneIdentifier"].should.equal(mocked_networking["subnet1"])
    group["NewInstancesProtectedFromScaleIn"].should.equal(True)
    for instance in group["Instances"]:
        instance["LaunchConfigurationName"].should.equal("test_launch_configuration")
        instance.should_not.have.key("LaunchTemplate")
        instance["AvailabilityZone"].should.equal("eu-north-1a")
        instance["ProtectedFromScaleIn"].should.equal(True)
        instance["InstanceType"].should.equal("t2.micro")


@mock_autoscaling
@mock_ec2
def test_describe_autoscaling_groups_boto3_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_boto3_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_boto3_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_boto3_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_boto3_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_boto3():
    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",
        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["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_elb
@mock_autoscaling
@mock_ec2
def test_detach_one_instance_decrement():
    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=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_detach = 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.detach_instances(
        AutoScalingGroupName="test_asg",
        InstanceIds=[instance_to_detach],
        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(1)
    instance_to_detach.shouldnt.be.within(
        [x["InstanceId"] for x in response["AutoScalingGroups"][0]["Instances"]]
    )

    # test to ensure tag has been removed
    response = ec2_client.describe_instances(InstanceIds=[instance_to_detach])
    tags = response["Reservations"][0]["Instances"][0]["Tags"]
    tags.should.have.length_of(1)

    # test to ensure tag is present on other instance
    response = ec2_client.describe_instances(InstanceIds=[instance_to_keep])
    tags = response["Reservations"][0]["Instances"][0]["Tags"]
    tags.should.have.length_of(2)

    response = elb_client.describe_load_balancers(LoadBalancerNames=["my-lb"])
    list(response["LoadBalancerDescriptions"][0]["Instances"]).should.have.length_of(1)
    instance_to_detach.shouldnt.be.within(
        [x["InstanceId"] for x in response["LoadBalancerDescriptions"][0]["Instances"]]
    )


@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_elb
@mock_autoscaling
@mock_ec2
def test_detach_one_instance():
    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=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_detach = 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.detach_instances(
        AutoScalingGroupName="test_asg",
        InstanceIds=[instance_to_detach],
        ShouldDecrementDesiredCapacity=False,
    )
    response["ResponseMetadata"]["HTTPStatusCode"].should.equal(200)

    response = client.describe_auto_scaling_groups(AutoScalingGroupNames=["test_asg"])
    # test to ensure instance was replaced
    response["AutoScalingGroups"][0]["Instances"].should.have.length_of(2)

    response = ec2_client.describe_instances(InstanceIds=[instance_to_detach])
    tags = response["Reservations"][0]["Instances"][0]["Tags"]
    tags.should.have.length_of(1)

    response = ec2_client.describe_instances(InstanceIds=[instance_to_keep])
    tags = response["Reservations"][0]["Instances"][0]["Tags"]
    tags.should.have.length_of(2)

    response = elb_client.describe_load_balancers(LoadBalancerNames=["my-lb"])
    list(response["LoadBalancerDescriptions"][0]["Instances"]).should.have.length_of(2)
    instance_to_detach.shouldnt.be.within(
        [x["InstanceId"] for x in response["LoadBalancerDescriptions"][0]["Instances"]]
    )


@mock_elb
@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",
        ImageId=EXAMPLE_AMI_ID,
        InstanceType="t2.medium",
    )
    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"]

    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)

    response = elb_client.describe_load_balancers(LoadBalancerNames=["my-lb"])
    list(response["LoadBalancerDescriptions"][0]["Instances"]).should.have.length_of(1)
    instance_to_standby.shouldnt.be.within(
        [x["InstanceId"] for x in response["LoadBalancerDescriptions"][0]["Instances"]]
    )


@mock_elb
@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",
        ImageId=EXAMPLE_AMI_ID,
        InstanceType="t2.medium",
    )
    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"]

    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)

    response = elb_client.describe_load_balancers(LoadBalancerNames=["my-lb"])
    list(response["LoadBalancerDescriptions"][0]["Instances"]).should.have.length_of(2)
    instance_to_standby.shouldnt.be.within(
        [x["InstanceId"] for x in response["LoadBalancerDescriptions"][0]["Instances"]]
    )


@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",
        ImageId=EXAMPLE_AMI_ID,
        InstanceType="t2.medium",
    )
    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)
    instance_to_standby.shouldnt.be.within(
        [x["InstanceId"] for x in response["LoadBalancerDescriptions"][0]["Instances"]]
    )


@mock_elb
@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",
        ImageId=EXAMPLE_AMI_ID,
        InstanceType="t2.medium",
    )
    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"],
    )

    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_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"
    )

    response = elb_client.describe_load_balancers(LoadBalancerNames=["my-lb"])
    list(response["LoadBalancerDescriptions"][0]["Instances"]).should.have.length_of(1)
    instance_to_standby_terminate.shouldnt.be.within(
        [x["InstanceId"] for x in response["LoadBalancerDescriptions"][0]["Instances"]]
    )


@mock_elb
@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",
        ImageId=EXAMPLE_AMI_ID,
        InstanceType="t2.medium",
    )
    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"],
    )

    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_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"
    )

    response = elb_client.describe_load_balancers(LoadBalancerNames=["my-lb"])
    list(response["LoadBalancerDescriptions"][0]["Instances"]).should.have.length_of(2)
    instance_to_standby_terminate.shouldnt.be.within(
        [x["InstanceId"] for x in response["LoadBalancerDescriptions"][0]["Instances"]]
    )


@mock_elb
@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",
        ImageId=EXAMPLE_AMI_ID,
        InstanceType="t2.medium",
    )
    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"],
    )

    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_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")

    response = elb_client.describe_load_balancers(LoadBalancerNames=["my-lb"])
    list(response["LoadBalancerDescriptions"][0]["Instances"]).should.have.length_of(1)
    instance_to_standby_detach.shouldnt.be.within(
        [x["InstanceId"] for x in response["LoadBalancerDescriptions"][0]["Instances"]]
    )


@mock_elb
@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",
        ImageId=EXAMPLE_AMI_ID,
        InstanceType="t2.medium",
    )
    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"],
    )

    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_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")

    response = elb_client.describe_load_balancers(LoadBalancerNames=["my-lb"])
    list(response["LoadBalancerDescriptions"][0]["Instances"]).should.have.length_of(2)
    instance_to_standby_detach.shouldnt.be.within(
        [x["InstanceId"] for x in response["LoadBalancerDescriptions"][0]["Instances"]]
    )


@mock_elb
@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",
        ImageId=EXAMPLE_AMI_ID,
        InstanceType="t2.medium",
    )
    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"],
    )

    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_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")

    response = elb_client.describe_load_balancers(LoadBalancerNames=["my-lb"])
    list(response["LoadBalancerDescriptions"][0]["Instances"]).should.have.length_of(3)
    instance_to_standby_exit_standby.should.be.within(
        [x["InstanceId"] for x in response["LoadBalancerDescriptions"][0]["Instances"]]
    )


@mock_elb
@mock_autoscaling
@mock_ec2
def test_attach_one_instance():
    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=4,
        DesiredCapacity=2,
        Tags=[
            {
                "ResourceId": "test_asg",
                "ResourceType": "auto-scaling-group",
                "Key": "propogated-tag-key",
                "Value": "propagate-tag-value",
                "PropagateAtLaunch": True,
            }
        ],
        VPCZoneIdentifier=mocked_networking["subnet1"],
        NewInstancesProtectedFromScaleIn=True,
    )

    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)

    ec2 = boto3.resource("ec2", "us-east-1")
    instances_to_add = [
        x.id
        for x in ec2.create_instances(ImageId=EXAMPLE_AMI_ID, MinCount=1, MaxCount=1)
    ]

    response = client.attach_instances(
        AutoScalingGroupName="test_asg", InstanceIds=instances_to_add
    )
    response["ResponseMetadata"]["HTTPStatusCode"].should.equal(200)

    response = client.describe_auto_scaling_groups(AutoScalingGroupNames=["test_asg"])
    instances = response["AutoScalingGroups"][0]["Instances"]
    instances.should.have.length_of(3)
    for instance in instances:
        instance["ProtectedFromScaleIn"].should.equal(True)

    response = elb_client.describe_load_balancers(LoadBalancerNames=["my-lb"])
    list(response["LoadBalancerDescriptions"][0]["Instances"]).should.have.length_of(3)


@mock_autoscaling
@mock_ec2
def test_describe_instance_health():
    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=4,
        DesiredCapacity=2,
        VPCZoneIdentifier=mocked_networking["subnet1"],
    )

    response = client.describe_auto_scaling_groups(AutoScalingGroupNames=["test_asg"])

    instance1 = response["AutoScalingGroups"][0]["Instances"][0]
    instance1["HealthStatus"].should.equal("Healthy")


@mock_autoscaling
@mock_ec2
def test_set_instance_health():
    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=4,
        DesiredCapacity=2,
        VPCZoneIdentifier=mocked_networking["subnet1"],
    )

    response = client.describe_auto_scaling_groups(AutoScalingGroupNames=["test_asg"])

    instance1 = response["AutoScalingGroups"][0]["Instances"][0]
    instance1["HealthStatus"].should.equal("Healthy")

    client.set_instance_health(
        InstanceId=instance1["InstanceId"], HealthStatus="Unhealthy"
    )

    response = client.describe_auto_scaling_groups(AutoScalingGroupNames=["test_asg"])

    instance1 = response["AutoScalingGroups"][0]["Instances"][0]
    instance1["HealthStatus"].should.equal("Unhealthy")


@mock_autoscaling
def test_suspend_processes():
    mocked_networking = setup_networking()
    client = boto3.client("autoscaling", region_name="us-east-1")
    client.create_launch_configuration(
        LaunchConfigurationName="lc", ImageId=EXAMPLE_AMI_ID, InstanceType="t2.medium"
    )
    client.create_auto_scaling_group(
        LaunchConfigurationName="lc",
        AutoScalingGroupName="test-asg",
        MinSize=1,
        MaxSize=1,
        VPCZoneIdentifier=mocked_networking["subnet1"],
    )

    # When we suspend the 'Launch' process on the ASG client
    client.suspend_processes(
        AutoScalingGroupName="test-asg", ScalingProcesses=["Launch"]
    )

    res = client.describe_auto_scaling_groups(AutoScalingGroupNames=["test-asg"])

    # The 'Launch' process should, in fact, be suspended
    launch_suspended = False
    for proc in res["AutoScalingGroups"][0]["SuspendedProcesses"]:
        if proc.get("ProcessName") == "Launch":
            launch_suspended = True

    assert launch_suspended is True


@mock_autoscaling
def test_suspend_processes_all_by_default():
    mocked_networking = setup_networking()
    client = boto3.client("autoscaling", region_name="us-east-1")
    client.create_launch_configuration(
        LaunchConfigurationName="lc", ImageId=EXAMPLE_AMI_ID, InstanceType="t2.medium"
    )
    client.create_auto_scaling_group(
        LaunchConfigurationName="lc",
        AutoScalingGroupName="test-asg",
        MinSize=1,
        MaxSize=1,
        VPCZoneIdentifier=mocked_networking["subnet1"],
    )

    # When we suspend with no processes specified
    client.suspend_processes(AutoScalingGroupName="test-asg")

    res = client.describe_auto_scaling_groups(AutoScalingGroupNames=["test-asg"])

    # All processes should be suspended
    all_proc_names = [
        "Launch",
        "Terminate",
        "AddToLoadBalancer",
        "AlarmNotification",
        "AZRebalance",
        "HealthCheck",
        "InstanceRefresh",
        "ReplaceUnhealthy",
        "ScheduledActions",
    ]
    suspended_proc_names = [
        proc["ProcessName"]
        for proc in res["AutoScalingGroups"][0]["SuspendedProcesses"]
    ]
    set(suspended_proc_names).should.equal(set(all_proc_names))


@mock_autoscaling
def test_suspend_additional_processes():
    mocked_networking = setup_networking()
    client = boto3.client("autoscaling", region_name="us-east-1")
    client.create_launch_configuration(
        LaunchConfigurationName="lc", ImageId=EXAMPLE_AMI_ID, InstanceType="t2.medium"
    )
    client.create_auto_scaling_group(
        LaunchConfigurationName="lc",
        AutoScalingGroupName="test-asg",
        MinSize=1,
        MaxSize=1,
        VPCZoneIdentifier=mocked_networking["subnet1"],
    )

    # When we suspend the 'Launch' and 'Terminate' processes in separate calls
    client.suspend_processes(
        AutoScalingGroupName="test-asg", ScalingProcesses=["Launch"]
    )
    client.suspend_processes(
        AutoScalingGroupName="test-asg", ScalingProcesses=["Terminate"]
    )

    res = client.describe_auto_scaling_groups(AutoScalingGroupNames=["test-asg"])

    # Both 'Launch' and 'Terminate' should be suspended
    launch_suspended = False
    terminate_suspended = False
    for proc in res["AutoScalingGroups"][0]["SuspendedProcesses"]:
        if proc.get("ProcessName") == "Launch":
            launch_suspended = True
        if proc.get("ProcessName") == "Terminate":
            terminate_suspended = True

    assert launch_suspended is True
    assert terminate_suspended is True


@mock_autoscaling
def test_resume_processes():
    mocked_networking = setup_networking()
    client = boto3.client("autoscaling", region_name="us-east-1")
    client.create_launch_configuration(
        LaunchConfigurationName="lc", ImageId=EXAMPLE_AMI_ID, InstanceType="t2.medium"
    )
    client.create_auto_scaling_group(
        LaunchConfigurationName="lc",
        AutoScalingGroupName="test-asg",
        MinSize=1,
        MaxSize=1,
        VPCZoneIdentifier=mocked_networking["subnet1"],
    )

    # When we suspect 'Launch' and 'Termiate' process then resume 'Launch'
    client.suspend_processes(
        AutoScalingGroupName="test-asg", ScalingProcesses=["Launch", "Terminate"]
    )

    client.resume_processes(
        AutoScalingGroupName="test-asg", ScalingProcesses=["Launch"]
    )

    res = client.describe_auto_scaling_groups(AutoScalingGroupNames=["test-asg"])

    # Only 'Terminate' should be suspended
    expected_suspended_processes = [
        {"ProcessName": "Terminate", "SuspensionReason": ""}
    ]
    res["AutoScalingGroups"][0]["SuspendedProcesses"].should.equal(
        expected_suspended_processes
    )


@mock_autoscaling
def test_resume_processes_all_by_default():
    mocked_networking = setup_networking()
    client = boto3.client("autoscaling", region_name="us-east-1")
    client.create_launch_configuration(
        LaunchConfigurationName="lc", ImageId=EXAMPLE_AMI_ID, InstanceType="t2.medium"
    )
    client.create_auto_scaling_group(
        LaunchConfigurationName="lc",
        AutoScalingGroupName="test-asg",
        MinSize=1,
        MaxSize=1,
        VPCZoneIdentifier=mocked_networking["subnet1"],
    )

    # When we suspend two processes then resume with no process argument
    client.suspend_processes(
        AutoScalingGroupName="test-asg", ScalingProcesses=["Launch", "Terminate"]
    )

    client.resume_processes(AutoScalingGroupName="test-asg")

    res = client.describe_auto_scaling_groups(AutoScalingGroupNames=["test-asg"])

    # No processes should be suspended
    res["AutoScalingGroups"][0]["SuspendedProcesses"].should.equal([])


@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_boto3():
    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_boto3():
    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_elb
@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",
        ImageId=EXAMPLE_AMI_ID,
        InstanceType="t2.medium",
    )
    _ = client.create_auto_scaling_group(
        AutoScalingGroupName="test_asg",
        LaunchConfigurationName="test_launch_configuration",
        MinSize=0,
        DesiredCapacity=1,
        MaxSize=2,
        VPCZoneIdentifier=mocked_networking["subnet1"],
        NewInstancesProtectedFromScaleIn=False,
    )

    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"])
    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)

    response = elb_client.describe_load_balancers(LoadBalancerNames=["my-lb"])
    list(response["LoadBalancerDescriptions"][0]["Instances"]).should.have.length_of(0)


@mock_elb
@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",
        ImageId=EXAMPLE_AMI_ID,
        InstanceType="t2.medium",
    )
    _ = client.create_auto_scaling_group(
        AutoScalingGroupName="test_asg",
        LaunchConfigurationName="test_launch_configuration",
        MinSize=0,
        DesiredCapacity=1,
        MaxSize=2,
        VPCZoneIdentifier=mocked_networking["subnet1"],
        NewInstancesProtectedFromScaleIn=False,
    )

    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"])
    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)

    response = elb_client.describe_load_balancers(LoadBalancerNames=["my-lb"])
    list(response["LoadBalancerDescriptions"][0]["Instances"]).should.have.length_of(1)
    original_instance_id.shouldnt.be.within(
        [x["InstanceId"] for x in response["LoadBalancerDescriptions"][0]["Instances"]]
    )


@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": "ami-pytest",
        "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_boto3(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)
