简体   繁体   中英

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::Su.net::Id> .

Individually, the nested template runs just fine. But when embedding AWS Console says Encountered unsupported property ELBSu.netList .

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 su.net 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" }
                }
            }
        }
    }
}

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.

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

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

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

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]

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM