How to loop through values in a CloudFormation template

19,381

Solution 1

https://palletsprojects.com/p/jinja/ is another option for adding for-loops to CloudFormation templates. You will need to render the Jinja template before passing it to CloudFormation, as CloudFormation itself cannot currently process Jinja templates.

  {% for country in ["fr", "us", "gb"] %}
  {{country}}_myprod_bucket:
    Type: AWS::S3::Bucket
  {% endfor %}

Rendering that Jinja snippet would produce:

  fr_myprod_bucket:
    Type: AWS::S3::Bucket

  us_myprod_bucket:
    Type: AWS::S3::Bucket

  gb_myprod_bucket:
    Type: AWS::S3::Bucket

Solution 2

You are correct — there is no concept of a loop in AWS CloudFormation.

AWS CloudFormation is a declarative language. It describes the output desired, but does not state how the outcome should be achieved.

To perform logic like you describe, you will need to create an AWS Lambda-backed Custom Resource. CloudFormation will call the supplied Lambda function, which can then make any desired API calls.

The the template is only creating these buckets, then there is actually no benefit in using CloudFormation. Just run a program or script that does it directly.

Solution 3

Use the Count macro!

The Count macro provides a template-wide Count property for CloudFormation resources. It allows you to specify multiple resources of the same type without having to cut and paste.

Thus, the the following:

AWSTemplateFormatVersion: "2010-09-09"
Transform: Count
Resources:
  Bucket:
    Type: AWS::S3::Bucket
    Properties:
      Tags:
        - Key: TestKey
          Value: my bucket %d
    Count: 3

Would be equivalent to:

AWSTemplateFormatVersion: "2010-09-09"
Resources:
  Bucket1:
    Type: AWS::S3::Bucket
    Properties:
      Tags:
        - Key: TestKey
          Value: my bucket 1
  Bucket2:
    Type: AWS::S3::Bucket
    Properties:
      Tags:
        - Key: TestKey
          Value: my bucket 2
  Bucket3:
    Type: AWS::S3::Bucket
    Properties:
      Tags:
        - Key: TestKey
          Value: my bucket 3

Solution 4

An alternative would be to use CDK, which wraps CloudFormation in Typescript, Python, Java, .NET or Golang.

Share:
19,381
Njoi
Author by

Njoi

Updated on June 05, 2022

Comments

  • Njoi
    Njoi almost 2 years

    I am trying to pass a list of comma separated parameters in an AWS CloudFormation template and create multiple Amazon S3 buckets based on those values.

    I have a requirement where I will be passing a comma separated- list of country names and then the CloudFormation template would build that many S3 buckets (based on the names of countries passed in parameters).

    For example, if I pass fr,us,gb in a parameter, the stack should create fr_myprod_bucket, us_myprod_bucket, gb_myprod_bucket.

    I know there is no for loop in CloudFormation, so not sure how I can achieve this?

  • Shabin Muhammed
    Shabin Muhammed about 4 years
    This requires installing the Count macro in your AWS account. Refer : github.com/awslabs/aws-cloudformation-templates/tree/master/‌​aws/…
  • Tom
    Tom over 2 years
    CDK only let's you have flow-control when compiling, not at run-time.
  • D.J.Duff
    D.J.Duff about 2 years
    @Tom Yes I should have clarified that in order to use CDK for this you would have to use CDK a level above the CloudFormation. The "compiling" (synth) can happen when you like though. And you can bring (docs.aws.amazon.com/cdk/v2/guide/use_cfn_template.html) CloudFormation in to your CDK .