Skip to content

IfParam and conditions

A module can include or leave out resources based on the properties that the parent sets. There are two ways: the IfParam and IfNotParam metadata, and normal CloudFormation conditions.

IfParam and IfNotParam

Add Metadata.Rain.IfParam or Metadata.Rain.IfNotParam to a resource in a module:

  • IfParam: <Parameter> keeps the resource only when the parent sets that property.
  • IfNotParam: <Parameter> keeps the resource only when the parent does not set that property.

cfnrain removes the IfParam and IfNotParam keys from the output. IfParam only works in modules.

Use IfParam for optional parts of a module, such as permissions for a resource that the parent passes in. Use IfNotParam when the parent can bring its own resource instead of the one that the module creates.

The module, queue-module.yaml:

Parameters:
  DeadLetterArn:
    Type: String

Resources:
  Queue:
    Type: AWS::SQS::Queue
    Metadata:
      Rain:
        IfParam: DeadLetterArn
    Properties:
      RedrivePolicy:
        deadLetterTargetArn: !Ref DeadLetterArn
        maxReceiveCount: 5
  SimpleQueue:
    Type: AWS::SQS::Queue
    Metadata:
      Rain:
        IfNotParam: DeadLetterArn

The parent template:

Modules:
  Orders:
    Source: ./queue-module.yaml
    Properties:
      DeadLetterArn: arn:aws:sqs:us-east-1:123456789012:orders-dlq
  Events:
    Source: ./queue-module.yaml

The packaged template:

Resources:
  OrdersQueue:
    Type: AWS::SQS::Queue
    Properties:
      RedrivePolicy:
        deadLetterTargetArn: arn:aws:sqs:us-east-1:123456789012:orders-dlq
        maxReceiveCount: 5

  EventsSimpleQueue:
    Type: AWS::SQS::Queue

Orders sets DeadLetterArn, so it gets Queue with a redrive policy. Events does not, so it gets SimpleQueue.

Conditions in modules

A module can have a Conditions section. cfnrain evaluates each condition when it packages the template:

  • If the condition resolves to false, cfnrain removes the resources, modules and outputs that use it, and picks the false branch of each Fn::If.
  • If the condition resolves to true, cfnrain keeps them and picks the true branch.
  • cfnrain removes values that are !Ref AWS::NoValue.
  • If cfnrain cannot resolve the condition, for example because it uses AWS::Region or a parameter of the parent template, it copies the condition to the parent template. The condition name gets the module name in front, like a logical ID.

Resolved conditions

The module:

Parameters:
  Foo:
    Type: String

Conditions:
  Show0:
    Fn::Equals:
      - !Ref Foo
      - bar
  Show1:
    Fn::And:
      - Fn::Equals:
        - !Ref Foo
        - bar
      - Condition: Show0
  Show2:
    Fn::Not:
    - Fn::Or:
        - Fn::Equals:
          - !Ref Foo
          - baz
        - Fn::Equals:
          - Fn::If:
            - Fn::Equals:
              - a
              - a
            - x
            - y
          - y

Resources:
  Bucket0:
    Type: AWS::S3::Bucket
    Condition: Show0
  Bucket1:
    Type: AWS::S3::Bucket
    Condition: Show1
  Bucket2:
    Type: AWS::S3::Bucket
    Condition: Show2

The parent template:

Modules:
  A:
    Source: ./cond-intrinsics-module.yaml
    Properties:
      Foo: bar
  B:
    Source: ./cond-intrinsics-module.yaml
    Properties:
      Foo: baz

The packaged template. Module A has Foo: bar, so every condition is true. Module B has Foo: baz, so every condition is false and none of its buckets are in the output.

Resources:
  ABucket0:
    Type: AWS::S3::Bucket
  ABucket1:
    Type: AWS::S3::Bucket
  ABucket2:
    Type: AWS::S3::Bucket

Unresolved conditions

The parent template:

Parameters:
  P:
    Type: String

Modules:
  Foo:
    Source: cond-unres-module.yaml
    Properties:
      P: !Ref P

The module, cond-unres-module.yaml:

Parameters:
  P:
    Type: String

Conditions:
  IsRegionUsEast1:
    Fn::Equals:
    - Ref: AWS::Region
    - us-east-1
  IsPTrue:
    Fn::Equals:
      - !Ref P
      - true

Modules:
  Sub:
    Source: cond-unres-submodule.yaml
    Properties:
      P: !Ref P

Resources:
  S3Bucket:
    Type: AWS::S3::Bucket
    Condition: IsRegionUsEast1
  A:
    Type: A::B::C
    Properties:
      Name:
        Fn::If:
          - IsRegionUsEast1
          - a-east
          - a-not-east
  C:
    Type: D::E::F
    Condition: IsPTrue

The submodule, cond-unres-submodule.yaml:

Parameters:
  P:
    Type: String

Conditions:
  IsParam:
    Fn::Equals:
      - !Ref P
      - true

Resources:
  B:
    Condition: IsParam
    Type: A::B::C

The packaged template. The conditions depend on the region and on the parent parameter P, so they move to the parent with the prefixes Foo and FooSub.

Parameters:
  P:
    Type: String
Conditions:
  FooIsRegionUsEast1:
    Fn::Equals:
    - Ref: AWS::Region
    - us-east-1
  FooIsPTrue:
    Fn::Equals:
      - !Ref P
      - true
  FooSubIsParam:
    Fn::Equals:
      - !Ref P
      - true

Resources:
  FooS3Bucket:
    Type: AWS::S3::Bucket
    Condition: FooIsRegionUsEast1
  FooA:
    Type: A::B::C
    Properties:
      Name:
        Fn::If:
          - FooIsRegionUsEast1
          - a-east
          - a-not-east
  FooSubB:
    Type: A::B::C
    Condition: FooSubIsParam
  FooC:
    Type: D::E::F
    Condition: FooIsPTrue