Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to loop through values in a CloudFormation template

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?

like image 957
Njoi Avatar asked Jul 25 '19 05:07

Njoi


People also ask

How do you make a loop in CloudFormation?

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.

What part of a CloudFormation template allows you to pass values into the template?

Parameters (optional) Values to pass to your template at runtime (when you create or update a stack). You can refer to parameters from the Resources and Outputs sections of the template.

How do I reference another stack in CloudFormation?

To create a cross-stack reference, use the export field to flag the value of a resource output for export. Then, use the Fn::ImportValue intrinsic function to import the value in any stack within the same AWS Region and account. AWS CloudFormation identifies exported values by the names specified in the template.


3 Answers

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
like image 110
Fernando Espinosa Avatar answered Oct 22 '22 07:10

Fernando Espinosa


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.

like image 44
John Rotenstein Avatar answered Oct 22 '22 08:10

John Rotenstein


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
like image 5
Pat Myron Avatar answered Oct 22 '22 07:10

Pat Myron