'Passing parameters of type List<AWS::EC2::Subnet::Id> to nested CloudFormation template
I'm trying to nest a CloudFormation template into another by using the AWS::CloudFormation::Stack
resource type. The nested template has a parameter of type List<AWS::EC2::Subnet::Id>
.
Individually, the nested template runs just fine. But when embedding AWS Console says Encountered unsupported property ELBSubnetList.
Changing the parameter's type to String/CommaSeparated list seems to be a workaround, as dicussed here but I'd loose the fancy UI when creating the template interactivly via AWS Console.
Do you have any idea how to pass the list of subnet ids as a paramter?
This is the embedded template:
{
"AWSTemplateFormatVersion" : "2010-09-09",
"Parameters" : {
"ELBSubnetList" : {
"Type" : "List<AWS::EC2::Subnet::Id>",
"Description" : "Subnet List for Elastic Loadbalancer"
},
"ELBSecurityGroupList": {
"Type": "List<AWS::EC2::SecurityGroup::Id>",
"Description": "Security Group List for Elastic Loadbalancer"
}
},
"Resources" : {
"ELB" : {
"Type" : "AWS::ElasticLoadBalancing::LoadBalancer",
"Properties" : {
"Subnets": { "Ref": "ELBSubnetList" },
"CrossZone" : "true",
"SecurityGroups": { "Ref": "ELBSecurityGroupList" },
"LBCookieStickinessPolicy" : [ {
"PolicyName" : "CookieBasedPolicy",
"CookieExpirationPeriod" : "30"
}],
"Listeners" : [ {
"LoadBalancerPort" : "80",
"InstancePort" : "80",
"Protocol" : "HTTP",
"PolicyNames" : [ "CookieBasedPolicy" ]
} ],
"HealthCheck" : {
"Target" : "HTTP:80/wordpress/wp-admin/install.php",
"HealthyThreshold" : "2",
"UnhealthyThreshold" : "5",
"Interval" : "10",
"Timeout" : "5"
}
}
}
}
}
And the template that embedds:
{
"AWSTemplateFormatVersion" : "2010-09-09",
"Parameters": {
"ChildTemplate": {
"Type": "String",
"Default": "https://s3.eu-central-1.amazonaws.com/cf-templates-xxxxxxxxxxx-eu-central-1/sample_child.template"
},
"ELBSubnetList" : {
"Type" : "List<AWS::EC2::Subnet::Id>",
"Description" : "Subnet List for Elastic Loadbalancer"
},
"ELBSecurityGroupList": {
"Type": "List<AWS::EC2::SecurityGroup::Id>",
"Description": "Security Group List for Elastic Loadbalancer"
}
},
"Resources": {
"Child": {
"Type": "AWS::CloudFormation::Stack",
"Properties": {
"TemplateURL": { "Ref": "ChildTemplate" },
"Parameters": {
"ELBSubnetList": { "Ref": "ELBSubnetList" },
"ELBSecurityGroupList": { "Ref": "ELBSecurityGroupList" }
}
}
}
}
}
Solution 1:[1]
Lists can be converted into Strings and vice versa. So the working invocation is
{
"AWSTemplateFormatVersion" : "2010-09-09",
"Parameters": {
"ChildTemplate": {
"Type": "String",
"Default": "https://s3.eu-central-1.amazonaws.com/cf-templates-xxxxxxxxxxx-eu-central-1/sample_child.template"
},
"ELBSubnetList" : {
"Type" : "List<AWS::EC2::Subnet::Id>",
"Description" : "Subnet List for Elastic Loadbalancer"
},
"ELBSecurityGroupList": {
"Type": "List<AWS::EC2::SecurityGroup::Id>",
"Description": "Security Group List for Elastic Loadbalancer"
}
},
"Resources": {
"Child": {
"Type": "AWS::CloudFormation::Stack",
"Properties": {
"TemplateURL": { "Ref": "ChildTemplate" },
"Parameters": {
"ELBSubnetList": {"Fn::Join": [",", { "Ref": "ELBSubnetList" }]},
"ELBSecurityGroupList": {"Fn::Join": [",", { "Ref": "ELBSecurityGroupList" }]}
}
}
}
}
}
Solution 2:[2]
Successfully built in YAML using the following excerpt:
Parameters:
pSubnetIDs:
Description: The array of Subnet IDs for the Subnet group
Type: List<AWS::EC2::Subnet::Id>
Resources:
rDBSubnetGroup:
Type: "AWS::RDS::DBSubnetGroup"
Properties:
DBSubnetGroupDescription: The subnet group for the RDS instance
SubnetIds: !Ref pSubnetIDs
I tried a bunch of variations of !Join and !Ref with no success. Turns out it is just straightforward !Ref of the list.
Solution 3:[3]
To convert a list of SubnetIds to a list of Strings, use a combination of both JOIN and SPLIT.
TLDR;
In YAML, add
!Split [',', !Join [',', !Ref SubnetIds]]
The full answer is 2 parts.
Part 1: JOIN
Here SubnetIds
is a list of type Subnet.Id
. JOIN
will combine all IDs to be
one string. For example, a list of subnet ids JOIN
ed with ,
as the delimiter will be as follows:
[abc, def, hij]
=> "abc,def,hij"
.
Part 2: SPLIT
Now let's take the output from part 1, and SPLIT
on the delimiter ,
.
"abc,def,hij"
=> ["abc", "def", "hij"]
Here is an example of my use case with creating a Scheduled Task:
AWSTemplateFormatVersion: '2010-09-09'
Parameters
SubnetIds:
Type: List<AWS::EC2::Subnet::Id>
Description: Select at least two subnets in your selected VPC.
ScheduleTask:
Type: AWS::Events::Rule
Properties:
Description: !Sub 'Trigger Sitemap Generation according to the specified schedule'
ScheduleExpression: !Ref CronExpression
State: ENABLED
Targets:
- Id: 'targetId'
Arn: !GetAtt ECSCluster.Arn
RoleArn: !GetAtt ECSEventsRole.Arn
EcsParameters:
TaskDefinitionArn: !Ref TaskDefinition
TaskCount: 1
LaunchType: 'FARGATE'
PlatformVersion: 'LATEST'
NetworkConfiguration:
AwsVpcConfiguration:
AssignPublicIp: ENABLED
SecurityGroups:
- !Ref SecurityGroup
Subnets: !Split [',', !Join [',', !Ref SubnetIds]]
Solution 4:[4]
In YAML you need to "split" the Subnets by using Select. For example with two subnets :
!Join [",", [!Select [0, !Ref Subnets], !Select [1, !Ref Subnets]]]
Solution 5:[5]
Maybe help to another person: but for me works this:
In child template:
SubnetIds:
Description: Choose which subnets should be deployed to
Type: List<AWS::EC2::Subnet::Id>
but in the parent template
SubnetIds:
Description: Choose which subnets should be deployed to
Type: CommaDelimitedList
Stack:
Type: AWS::CloudFormation::Stack
Properties:
TemplateURL: {s3}
Parameters:
SubnetIds: !Join [',', !Ref SubnetIds]
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Stephan |
Solution 2 | molz |
Solution 3 | d_coder |
Solution 4 | Simon M. |
Solution 5 | Marco Guerrero Alfaro |