moto/tests/test_autoscaling/test_autoscaling_cloudformation.py
2021-10-18 19:44:29 +00:00

467 lines
16 KiB
Python

import boto3
import sure # noqa # pylint: disable=unused-import
import json
from moto import mock_autoscaling, mock_cloudformation, mock_ec2, mock_elb
from .utils import setup_networking
from tests import EXAMPLE_AMI_ID
@mock_autoscaling
@mock_cloudformation
def test_launch_configuration():
cf_client = boto3.client("cloudformation", region_name="us-east-1")
client = boto3.client("autoscaling", region_name="us-east-1")
stack_name = "test-launch-configuration"
cf_template = """
Resources:
LaunchConfiguration:
Type: AWS::AutoScaling::LaunchConfiguration
Properties:
ImageId: {0}
InstanceType: t2.micro
LaunchConfigurationName: test_launch_configuration
Outputs:
LaunchConfigurationName:
Value: !Ref LaunchConfiguration
""".strip().format(
EXAMPLE_AMI_ID
)
cf_client.create_stack(
StackName=stack_name, TemplateBody=cf_template,
)
stack = cf_client.describe_stacks(StackName=stack_name)["Stacks"][0]
stack["Outputs"][0]["OutputValue"].should.be.equal("test_launch_configuration")
lc = client.describe_launch_configurations()["LaunchConfigurations"][0]
lc["LaunchConfigurationName"].should.be.equal("test_launch_configuration")
lc["ImageId"].should.be.equal(EXAMPLE_AMI_ID)
lc["InstanceType"].should.be.equal("t2.micro")
cf_template = """
Resources:
LaunchConfiguration:
Type: AWS::AutoScaling::LaunchConfiguration
Properties:
ImageId: {0}
InstanceType: m5.large
LaunchConfigurationName: test_launch_configuration
Outputs:
LaunchConfigurationName:
Value: !Ref LaunchConfiguration
""".strip().format(
EXAMPLE_AMI_ID
)
cf_client.update_stack(
StackName=stack_name, TemplateBody=cf_template,
)
stack = cf_client.describe_stacks(StackName=stack_name)["Stacks"][0]
stack["Outputs"][0]["OutputValue"].should.be.equal("test_launch_configuration")
lc = client.describe_launch_configurations()["LaunchConfigurations"][0]
lc["LaunchConfigurationName"].should.be.equal("test_launch_configuration")
lc["ImageId"].should.be.equal(EXAMPLE_AMI_ID)
lc["InstanceType"].should.be.equal("m5.large")
@mock_autoscaling
@mock_cloudformation
def test_autoscaling_group_from_launch_config():
subnet_id = setup_networking()["subnet1"]
cf_client = boto3.client("cloudformation", region_name="us-east-1")
client = boto3.client("autoscaling", region_name="us-east-1")
client.create_launch_configuration(
LaunchConfigurationName="test_launch_configuration",
InstanceType="t2.micro",
ImageId=EXAMPLE_AMI_ID,
)
stack_name = "test-auto-scaling-group"
cf_template = """
Parameters:
SubnetId:
Type: AWS::EC2::Subnet::Id
Resources:
AutoScalingGroup:
Type: AWS::AutoScaling::AutoScalingGroup
Properties:
AutoScalingGroupName: test_auto_scaling_group
AvailabilityZones:
- us-east-1a
LaunchConfigurationName: test_launch_configuration
MaxSize: "5"
MinSize: "1"
VPCZoneIdentifier:
- !Ref SubnetId
Outputs:
AutoScalingGroupName:
Value: !Ref AutoScalingGroup
""".strip()
cf_client.create_stack(
StackName=stack_name,
TemplateBody=cf_template,
Parameters=[{"ParameterKey": "SubnetId", "ParameterValue": subnet_id}],
)
stack = cf_client.describe_stacks(StackName=stack_name)["Stacks"][0]
stack["Outputs"][0]["OutputValue"].should.be.equal("test_auto_scaling_group")
asg = client.describe_auto_scaling_groups()["AutoScalingGroups"][0]
asg["AutoScalingGroupName"].should.be.equal("test_auto_scaling_group")
asg["MinSize"].should.be.equal(1)
asg["MaxSize"].should.be.equal(5)
asg["LaunchConfigurationName"].should.be.equal("test_launch_configuration")
client.create_launch_configuration(
LaunchConfigurationName="test_launch_configuration_new",
InstanceType="t2.micro",
ImageId=EXAMPLE_AMI_ID,
)
cf_template = """
Parameters:
SubnetId:
Type: AWS::EC2::Subnet::Id
Resources:
AutoScalingGroup:
Type: AWS::AutoScaling::AutoScalingGroup
Properties:
AutoScalingGroupName: test_auto_scaling_group
AvailabilityZones:
- us-east-1a
LaunchConfigurationName: test_launch_configuration_new
MaxSize: "6"
MinSize: "2"
VPCZoneIdentifier:
- !Ref SubnetId
Outputs:
AutoScalingGroupName:
Value: !Ref AutoScalingGroup
""".strip()
cf_client.update_stack(
StackName=stack_name,
TemplateBody=cf_template,
Parameters=[{"ParameterKey": "SubnetId", "ParameterValue": subnet_id}],
)
stack = cf_client.describe_stacks(StackName=stack_name)["Stacks"][0]
stack["Outputs"][0]["OutputValue"].should.be.equal("test_auto_scaling_group")
asg = client.describe_auto_scaling_groups()["AutoScalingGroups"][0]
asg["AutoScalingGroupName"].should.be.equal("test_auto_scaling_group")
asg["MinSize"].should.be.equal(2)
asg["MaxSize"].should.be.equal(6)
asg["LaunchConfigurationName"].should.be.equal("test_launch_configuration_new")
@mock_autoscaling
@mock_cloudformation
@mock_ec2
def test_autoscaling_group_from_launch_template():
subnet_id = setup_networking()["subnet1"]
cf_client = boto3.client("cloudformation", region_name="us-east-1")
ec2_client = boto3.client("ec2", region_name="us-east-1")
client = boto3.client("autoscaling", region_name="us-east-1")
template_response = ec2_client.create_launch_template(
LaunchTemplateName="test_launch_template",
LaunchTemplateData={"ImageId": EXAMPLE_AMI_ID, "InstanceType": "t2.micro",},
)
launch_template_id = template_response["LaunchTemplate"]["LaunchTemplateId"]
stack_name = "test-auto-scaling-group"
cf_template = """
Parameters:
SubnetId:
Type: AWS::EC2::Subnet::Id
LaunchTemplateId:
Type: String
Resources:
AutoScalingGroup:
Type: AWS::AutoScaling::AutoScalingGroup
Properties:
AutoScalingGroupName: test_auto_scaling_group
AvailabilityZones:
- us-east-1a
LaunchTemplate:
LaunchTemplateId: !Ref LaunchTemplateId
Version: "1"
MaxSize: "5"
MinSize: "1"
VPCZoneIdentifier:
- !Ref SubnetId
Outputs:
AutoScalingGroupName:
Value: !Ref AutoScalingGroup
""".strip()
cf_client.create_stack(
StackName=stack_name,
TemplateBody=cf_template,
Parameters=[
{"ParameterKey": "SubnetId", "ParameterValue": subnet_id},
{"ParameterKey": "LaunchTemplateId", "ParameterValue": launch_template_id},
],
)
stack = cf_client.describe_stacks(StackName=stack_name)["Stacks"][0]
stack["Outputs"][0]["OutputValue"].should.be.equal("test_auto_scaling_group")
asg = client.describe_auto_scaling_groups()["AutoScalingGroups"][0]
asg["AutoScalingGroupName"].should.be.equal("test_auto_scaling_group")
asg["MinSize"].should.be.equal(1)
asg["MaxSize"].should.be.equal(5)
lt = asg["LaunchTemplate"]
lt["LaunchTemplateId"].should.be.equal(launch_template_id)
lt["LaunchTemplateName"].should.be.equal("test_launch_template")
lt["Version"].should.be.equal("1")
template_response = ec2_client.create_launch_template(
LaunchTemplateName="test_launch_template_new",
LaunchTemplateData={"ImageId": EXAMPLE_AMI_ID, "InstanceType": "m5.large",},
)
launch_template_id = template_response["LaunchTemplate"]["LaunchTemplateId"]
cf_template = """
Parameters:
SubnetId:
Type: AWS::EC2::Subnet::Id
LaunchTemplateId:
Type: String
Resources:
AutoScalingGroup:
Type: AWS::AutoScaling::AutoScalingGroup
Properties:
AutoScalingGroupName: test_auto_scaling_group
AvailabilityZones:
- us-east-1a
LaunchTemplate:
LaunchTemplateId: !Ref LaunchTemplateId
Version: "1"
MaxSize: "6"
MinSize: "2"
VPCZoneIdentifier:
- !Ref SubnetId
Outputs:
AutoScalingGroupName:
Value: !Ref AutoScalingGroup
""".strip()
cf_client.update_stack(
StackName=stack_name,
TemplateBody=cf_template,
Parameters=[
{"ParameterKey": "SubnetId", "ParameterValue": subnet_id},
{"ParameterKey": "LaunchTemplateId", "ParameterValue": launch_template_id},
],
)
stack = cf_client.describe_stacks(StackName=stack_name)["Stacks"][0]
stack["Outputs"][0]["OutputValue"].should.be.equal("test_auto_scaling_group")
asg = client.describe_auto_scaling_groups()["AutoScalingGroups"][0]
asg["AutoScalingGroupName"].should.be.equal("test_auto_scaling_group")
asg["MinSize"].should.be.equal(2)
asg["MaxSize"].should.be.equal(6)
lt = asg["LaunchTemplate"]
lt["LaunchTemplateId"].should.be.equal(launch_template_id)
lt["LaunchTemplateName"].should.be.equal("test_launch_template_new")
lt["Version"].should.be.equal("1")
@mock_autoscaling
@mock_elb
@mock_cloudformation
@mock_ec2
def test_autoscaling_group_with_elb():
web_setup_template = {
"AWSTemplateFormatVersion": "2010-09-09",
"Resources": {
"my-as-group": {
"Type": "AWS::AutoScaling::AutoScalingGroup",
"Properties": {
"AvailabilityZones": ["us-east-1a"],
"LaunchConfigurationName": {"Ref": "my-launch-config"},
"MinSize": "2",
"MaxSize": "2",
"DesiredCapacity": "2",
"LoadBalancerNames": [{"Ref": "my-elb"}],
"Tags": [
{
"Key": "propagated-test-tag",
"Value": "propagated-test-tag-value",
"PropagateAtLaunch": True,
},
{
"Key": "not-propagated-test-tag",
"Value": "not-propagated-test-tag-value",
"PropagateAtLaunch": False,
},
],
},
},
"my-launch-config": {
"Type": "AWS::AutoScaling::LaunchConfiguration",
"Properties": {
"ImageId": EXAMPLE_AMI_ID,
"InstanceType": "t2.medium",
"UserData": "some user data",
},
},
"my-elb": {
"Type": "AWS::ElasticLoadBalancing::LoadBalancer",
"Properties": {
"AvailabilityZones": ["us-east-1a"],
"Listeners": [
{
"LoadBalancerPort": "80",
"InstancePort": "80",
"Protocol": "HTTP",
}
],
"LoadBalancerName": "my-elb",
"HealthCheck": {
"Target": "HTTP:80",
"HealthyThreshold": "3",
"UnhealthyThreshold": "5",
"Interval": "30",
"Timeout": "5",
},
},
},
},
}
web_setup_template_json = json.dumps(web_setup_template)
cf = boto3.client("cloudformation", region_name="us-east-1")
ec2 = boto3.client("ec2", region_name="us-east-1")
elb = boto3.client("elb", region_name="us-east-1")
client = boto3.client("autoscaling", region_name="us-east-1")
cf.create_stack(StackName="web_stack", TemplateBody=web_setup_template_json)
autoscale_group = client.describe_auto_scaling_groups()["AutoScalingGroups"][0]
autoscale_group["LaunchConfigurationName"].should.contain("my-launch-config")
autoscale_group["LoadBalancerNames"].should.equal(["my-elb"])
# Confirm the Launch config was actually created
client.describe_launch_configurations()[
"LaunchConfigurations"
].should.have.length_of(1)
# Confirm the ELB was actually created
elb.describe_load_balancers()["LoadBalancerDescriptions"].should.have.length_of(1)
resources = cf.list_stack_resources(StackName="web_stack")["StackResourceSummaries"]
as_group_resource = [
resource
for resource in resources
if resource["ResourceType"] == "AWS::AutoScaling::AutoScalingGroup"
][0]
as_group_resource["PhysicalResourceId"].should.contain("my-as-group")
launch_config_resource = [
resource
for resource in resources
if resource["ResourceType"] == "AWS::AutoScaling::LaunchConfiguration"
][0]
launch_config_resource["PhysicalResourceId"].should.contain("my-launch-config")
elb_resource = [
resource
for resource in resources
if resource["ResourceType"] == "AWS::ElasticLoadBalancing::LoadBalancer"
][0]
elb_resource["PhysicalResourceId"].should.contain("my-elb")
# confirm the instances were created with the right tags
reservations = ec2.describe_instances()["Reservations"]
reservations.should.have.length_of(1)
reservations[0]["Instances"].should.have.length_of(2)
for instance in reservations[0]["Instances"]:
tag_keys = [t["Key"] for t in instance["Tags"]]
tag_keys.should.contain("propagated-test-tag")
tag_keys.should_not.contain("not-propagated-test-tag")
@mock_autoscaling
@mock_cloudformation
@mock_ec2
def test_autoscaling_group_update():
asg_template = {
"AWSTemplateFormatVersion": "2010-09-09",
"Resources": {
"my-as-group": {
"Type": "AWS::AutoScaling::AutoScalingGroup",
"Properties": {
"AvailabilityZones": ["us-west-1a"],
"LaunchConfigurationName": {"Ref": "my-launch-config"},
"MinSize": "2",
"MaxSize": "2",
"DesiredCapacity": "2",
},
},
"my-launch-config": {
"Type": "AWS::AutoScaling::LaunchConfiguration",
"Properties": {
"ImageId": EXAMPLE_AMI_ID,
"InstanceType": "t2.medium",
"UserData": "some user data",
},
},
},
}
asg_template_json = json.dumps(asg_template)
cf = boto3.client("cloudformation", region_name="us-west-1")
ec2 = boto3.client("ec2", region_name="us-west-1")
client = boto3.client("autoscaling", region_name="us-west-1")
cf.create_stack(StackName="asg_stack", TemplateBody=asg_template_json)
asg = client.describe_auto_scaling_groups()["AutoScalingGroups"][0]
asg["MinSize"].should.equal(2)
asg["MaxSize"].should.equal(2)
asg["DesiredCapacity"].should.equal(2)
asg_template["Resources"]["my-as-group"]["Properties"]["MaxSize"] = 3
asg_template["Resources"]["my-as-group"]["Properties"]["Tags"] = [
{
"Key": "propagated-test-tag",
"Value": "propagated-test-tag-value",
"PropagateAtLaunch": True,
},
{
"Key": "not-propagated-test-tag",
"Value": "not-propagated-test-tag-value",
"PropagateAtLaunch": False,
},
]
asg_template_json = json.dumps(asg_template)
cf.update_stack(StackName="asg_stack", TemplateBody=asg_template_json)
asg = client.describe_auto_scaling_groups()["AutoScalingGroups"][0]
asg["MinSize"].should.equal(2)
asg["MaxSize"].should.equal(3)
asg["DesiredCapacity"].should.equal(2)
# confirm the instances were created with the right tags
reservations = ec2.describe_instances()["Reservations"]
running_instance_count = 0
for res in reservations:
for instance in res["Instances"]:
if instance["State"]["Name"] == "running":
running_instance_count += 1
instance["Tags"].should.contain(
{"Key": "propagated-test-tag", "Value": "propagated-test-tag-value"}
)
tag_keys = [t["Key"] for t in instance["Tags"]]
tag_keys.should_not.contain("not-propagated-test-tag")
running_instance_count.should.equal(2)