Njoi
Njoi

Reputation: 445

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?

Upvotes: 20

Views: 40370

Answers (5)

Pat Myron
Pat Myron

Reputation: 4638

https://palletsprojects.com/p/jinja/ is another option for for-loops in CloudFormation templates. Render Jinja templates before passing them to CloudFormation, as CloudFormation itself cannot currently process Jinja.

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

That Jinja snippet produces:

  fr_myprod_bucket:
    Type: AWS::S3::Bucket
  
  us_myprod_bucket:
    Type: AWS::S3::Bucket
  
  gb_myprod_bucket:
    Type: AWS::S3::Bucket

Upvotes: 6

skzi
skzi

Reputation: 373

AWS now supports For loop in cloudformation for resources

AWSTemplateFormatVersion: 2010-09-09
Transform: 'AWS::LanguageExtensions'
Resources:
  'Fn::ForEach::Bucket': 
    - BucketName
    - - 'fr'
      - 'gb'
      - 'us'
    - 'MyBucket${BucketName}': ##resource name
        Type: 'AWS::S3::Bucket'
        Properties:
          BucketName: !Sub ${BucketName}_myprod_bucket

# Require CAPABILITY_AUTO_EXPAND, IAM with custom resources capability

Upvotes: 1

vsnyc
vsnyc

Reputation: 2257

This is now possible using Fn::ForEach. See the announcement and documentation for details.

You could do something like below:

AWSTemplateFormatVersion: 2010-09-09
Description: Create multiple Amazon S3 buckets using prefix from a comma delimited list
Transform: AWS::LanguageExtensions
Parameters:
  CountryNames:
    Description: Country prefix names
    Default: "fr,gb,us"
    Type: CommaDelimitedList
Resources:
  'Fn::ForEach::S3Buckets':
    - ParamName
    - !Ref CountryNames
    - 'Bucket${ParamName}':
        Type: AWS::S3::Bucket
        Properties:
          BucketName: !Sub '${ParamName}-my-prod-bucket-${AWS::Region}-${AWS::AccountId}'
          ## Add more configuration parameters for the buckets here...

Upvotes: 13

D.J.Duff
D.J.Duff

Reputation: 1575

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

Upvotes: 4

Fernando Espinosa
Fernando Espinosa

Reputation: 4825

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

Upvotes: 10

Related Questions