How to reference a logical id created by ForEach using ampersand from another ForEach in Cloudformation

0

Consider the following code snippet below.

How do you reference logical ids created using ampersand in the 1st ForEach loop from another ForEach loop. When I run this, CFN complains that it cannot reference Cidr&{CIDR}

(1)
    'Fn::ForEach::PubCidrSubnets':
        - CIDR
        - !Ref PublicSubnetCidrs  
        - 'Cidr&{CIDR}':
            Type: 'AWS::EC2::Subnet'
            Properties:
                VpcId: !GetAtt VPC.VpcId
                CidrBlock: !Ref CIDR
                Tags: 
                    - Key: Name
                      Value: 
                        !Join ['-',[Ref: VpcName,"pub",'&{CIDR}']]
                    - Key: Owner
                      Value: 
                        Ref: ApplicationOwner
                    - Key: Environment
                      Value: 
                        Ref: Environment                
(2)
    'Fn::ForEach::PubRtbSubnetsAssoc':
        - CIDR
        - !Ref PublicSubnetCidrs  
        - 'RtbSubAssoc&{CIDR}':
            Type: 'AWS::EC2::SubnetRouteTableAssociation'
            Properties:
                RouteTableId: !Ref PublicRouteTable
                SubnetId: !Ref
                    Fn::Sub: 'Cidr&{CIDR}'
asked 6 days ago23 views
1 Answer
0

To reference logical IDs created using the ampersand syntax in a Fn::ForEach loop from another Fn::ForEach loop, you need to use a combination of Fn::Sub and the ampersand syntax. However, there's a small adjustment needed in your code.

In your second Fn::ForEach loop, you're trying to reference the subnet created in the first loop. The correct way to do this is to use Fn::Sub with the ampersand syntax, but without nesting it inside a !Ref. Here's the corrected version:

'Fn::ForEach::PubRtbSubnetsAssoc':
    - CIDR
    - !Ref PublicSubnetCidrs  
    - 'RtbSubAssoc&{CIDR}':
        Type: 'AWS::EC2::SubnetRouteTableAssociation'
        Properties:
            RouteTableId: !Ref PublicRouteTable
            SubnetId: 
                Fn::Sub: 'Cidr&${CIDR}'

In this corrected version, we're using Fn::Sub to construct the logical ID of the subnet created in the first loop. The '&' is included inside the string passed to Fn::Sub, and we use '${CIDR}' instead of '&{CIDR}' because we're already inside a Fn::Sub context.

This syntax allows you to reference the dynamically created logical IDs from the first Fn::ForEach loop in the second loop. The ampersand syntax in Fn::ForEach is specifically designed to allow non-alphanumeric characters in the Collection to be used in the OutputKey parameter, which is useful when you need to reference these resources later.

Remember that when using Fn::ForEach, you need to apply the AWS::LanguageExtensions transform to your template for it to work correctly.
Sources
Fn::ForEach - AWS CloudFormation
Examples of Fn::ForEach in the Conditions section - AWS CloudFormation

profile picture
answered 6 days ago
  • This is not working. I'm getting an error:

    Resource handler returned message: "The subnet ID 'cidr&10.0.4.0/24' does not exist (Service: Ec2, Status Code: 400, Request ID: 49ebf39d-4b87-44f1-9be1-d319f766654a)" (RequestToken: a842f23a-0d94-f877-2f8c-b3ecad3bb6d6, HandlerErrorCode: GeneralServiceException)

You are not logged in. Log in to post an answer.

A good answer clearly answers the question and provides constructive feedback and encourages professional growth in the question asker.

Guidelines for Answering Questions