Cloud formation "depends_on" #2845 Add depends on and update name type mapping (#2994)

* ENH: Add unit test for cloudformation DependsOn

* ENH: Add implementation of retrieving list of resources that account for dependencies

* ENH: Update the name mappings so that they are consistent with the latest cloudformation names

* ENH: Add launch configuration to type names

* ENH: Create subnet for test and test creation with dependencies

* CLN: Code reformatting

* CLN: Remove print statements

* BUG: Fix error resulting in possible infinite loop

* CLN: Remove commented out fixture decorator

* BUG: Remove subnet creation

* CLN: Remove main and ec2 dependencies

* BUG: Add back in instance profile name type

* CLN: Remove print

* BUG: Fix broken unit test

* CLN: Code reformatting

* CLN: Remove main

* ENH: Add autoscaling group name to type names

* ENH: Add unit test for string only dependency and add assertions to unit tests

* ENH: Add unit test for chained depends_on in cloudformation stack

* BUG: Remove f strings for python 2.7 compatibility

* BUG: List needs to be sorted for python2.7

* CLN: Fix code formatting
This commit is contained in:
Zach Brookler 2020-05-18 04:47:18 -04:00 committed by GitHub
commit 80b64f9b3f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 204 additions and 8 deletions

View file

@ -0,0 +1,143 @@
import boto3
from moto import mock_cloudformation, mock_ecs, mock_autoscaling, mock_s3
import json
depends_on_template_list = {
"AWSTemplateFormatVersion": "2010-09-09",
"Resources": {
"ECSCluster": {
"Type": "AWS::ECS::Cluster",
"Properties": {"ClusterName": "test-cluster"},
},
"AutoScalingGroup": {
"Type": "AWS::AutoScaling::AutoScalingGroup",
"Properties": {
"AutoScalingGroupName": "test-scaling-group",
"DesiredCapacity": 1,
"MinSize": 1,
"MaxSize": 50,
"LaunchConfigurationName": "test-launch-config",
"AvailabilityZones": ["us-east-1a"],
},
"DependsOn": ["ECSCluster", "LaunchConfig"],
},
"LaunchConfig": {
"Type": "AWS::AutoScaling::LaunchConfiguration",
"Properties": {"LaunchConfigurationName": "test-launch-config",},
},
},
}
depends_on_template_string = {
"AWSTemplateFormatVersion": "2010-09-09",
"Resources": {
"AutoScalingGroup": {
"Type": "AWS::AutoScaling::AutoScalingGroup",
"Properties": {
"AutoScalingGroupName": "test-scaling-group",
"DesiredCapacity": 1,
"MinSize": 1,
"MaxSize": 50,
"LaunchConfigurationName": "test-launch-config",
"AvailabilityZones": ["us-east-1a"],
},
"DependsOn": "LaunchConfig",
},
"LaunchConfig": {
"Type": "AWS::AutoScaling::LaunchConfiguration",
"Properties": {"LaunchConfigurationName": "test-launch-config",},
},
},
}
def make_chained_depends_on_template():
depends_on_template_linked_dependencies = {
"AWSTemplateFormatVersion": "2010-09-09",
"Resources": {
"Bucket1": {
"Type": "AWS::S3::Bucket",
"Properties": {"BucketName": "test-bucket-0-us-east-1"},
},
},
}
for i in range(1, 10):
depends_on_template_linked_dependencies["Resources"]["Bucket" + str(i)] = {
"Type": "AWS::S3::Bucket",
"Properties": {"BucketName": "test-bucket-" + str(i) + "-us-east-1"},
"DependsOn": ["Bucket" + str(i - 1)],
}
return json.dumps(depends_on_template_linked_dependencies)
depends_on_template_list_json = json.dumps(depends_on_template_list)
depends_on_template_string_json = json.dumps(depends_on_template_string)
@mock_cloudformation
@mock_autoscaling
@mock_ecs
def test_create_stack_with_depends_on():
boto3.client("cloudformation", region_name="us-east-1").create_stack(
StackName="depends_on_test", TemplateBody=depends_on_template_list_json
)
autoscaling = boto3.client("autoscaling", region_name="us-east-1")
autoscaling_group = autoscaling.describe_auto_scaling_groups()["AutoScalingGroups"][
0
]
assert autoscaling_group["AutoScalingGroupName"] == "test-scaling-group"
assert autoscaling_group["DesiredCapacity"] == 1
assert autoscaling_group["MinSize"] == 1
assert autoscaling_group["MaxSize"] == 50
assert autoscaling_group["AvailabilityZones"] == ["us-east-1a"]
launch_configuration = autoscaling.describe_launch_configurations()[
"LaunchConfigurations"
][0]
assert launch_configuration["LaunchConfigurationName"] == "test-launch-config"
ecs = boto3.client("ecs", region_name="us-east-1")
cluster_arn = ecs.list_clusters()["clusterArns"][0]
assert cluster_arn == "arn:aws:ecs:us-east-1:012345678910:cluster/test-cluster"
@mock_cloudformation
@mock_autoscaling
def test_create_stack_with_depends_on_string():
boto3.client("cloudformation", region_name="us-east-1").create_stack(
StackName="depends_on_string_test", TemplateBody=depends_on_template_string_json
)
autoscaling = boto3.client("autoscaling", region_name="us-east-1")
autoscaling_group = autoscaling.describe_auto_scaling_groups()["AutoScalingGroups"][
0
]
assert autoscaling_group["AutoScalingGroupName"] == "test-scaling-group"
assert autoscaling_group["DesiredCapacity"] == 1
assert autoscaling_group["MinSize"] == 1
assert autoscaling_group["MaxSize"] == 50
assert autoscaling_group["AvailabilityZones"] == ["us-east-1a"]
launch_configuration = autoscaling.describe_launch_configurations()[
"LaunchConfigurations"
][0]
assert launch_configuration["LaunchConfigurationName"] == "test-launch-config"
@mock_cloudformation
@mock_s3
def test_create_chained_depends_on_stack():
boto3.client("cloudformation", region_name="us-east-1").create_stack(
StackName="linked_depends_on_test",
TemplateBody=make_chained_depends_on_template(),
)
s3 = boto3.client("s3", region_name="us-east-1")
bucket_response = s3.list_buckets()["Buckets"]
assert sorted([bucket["Name"] for bucket in bucket_response]) == [
"test-bucket-" + str(i) + "-us-east-1" for i in range(1, 10)
]

View file

@ -49,7 +49,7 @@ from moto import (
from moto.core import ACCOUNT_ID
from moto.dynamodb2.models import Table
from .fixtures import (
from tests.test_cloudformation.fixtures import (
ec2_classic_eip,
fn_join,
rds_mysql_with_db_parameter_group,
@ -940,12 +940,10 @@ def test_iam_roles():
role_name_to_id = {}
for role_result in role_results:
role = iam_conn.get_role(role_result.role_name)
if "my-role" not in role.role_name:
# Role name is not specified, so randomly generated - can't check exact name
if "with-path" in role.role_name:
role_name_to_id["with-path"] = role.role_id
role.path.should.equal("my-path")
len(role.role_name).should.equal(
5
) # Role name is not specified, so randomly generated - can't check exact name
else:
role_name_to_id["no-path"] = role.role_id
role.role_name.should.equal("my-role-no-path-name")