Constants¶
A constant is a value that you write once and use in many places. cfnrain replaces the constants and removes their section when it packages the template.
cfnrain has two ways to write constants. Both work. Pick one system per template, so readers know where to look.
Constants: section |
Rain: section |
|
|---|---|---|
| Where | Top level of a template or module | Rain: Constants: |
In a !Sub |
${Const::Name} |
${Rain::Name} |
| Insert a value | !Ref Const::Name |
!Rain::Constant Name |
cfnrain replaces both ${Rain::Name} and ${Const::Name} in !Sub strings. If a !Sub has no variables left after cfnrain inserts the constants, cfnrain replaces it with a plain string.
The Constants section¶
A template or a module can have a top-level Constants: section. A constant is a string or an object.
Constants:
S3Arn: "arn:${AWS::Partition}:s3:::"
BucketName: "${Name}-${AWS::Region}-${AWS::AccountId}"
BucketArn: "${Const::S3Arn}${Const::BucketName}"
Tags:
Team: platform
Use a constant in two ways:
${Const::<Name>}inside a!Substring inserts a string constant.!Ref Const::<Name>inserts an object constant. You can only insert the whole object, not a part of it.
A constant can use the constants above it with ${Const::<Name>}. cfnrain replaces the constants before it processes the modules.
Example¶
The parent template:
Constants:
yyy: zzz
Metadata:
test: !Sub ${Const::yyy}
Modules:
Content:
Source: ./constant-module.yaml
The module, constant-module.yaml:
Constants:
foo: bar
sub: "${Const::foo}-abc-${AWS::AccountId}"
obj:
TestObject:
A: b
Resources:
Bucket:
Type: AWS::S3::Bucket
Metadata:
Test: !Sub ${Const::sub}-xyz
TestObj: !Ref Const::obj
Properties:
BucketName: !Sub ${Const::foo}
The packaged template:
Metadata:
test: zzz
Resources:
ContentBucket:
Type: AWS::S3::Bucket
Metadata:
Test:
Fn::Sub: bar-abc-${AWS::AccountId}-xyz
TestObj:
TestObject:
A: b
Properties:
BucketName: bar
The parent's ${Const::yyy} becomes the plain string zzz. In the module, ${Const::sub} keeps ${AWS::AccountId}, so it stays a Fn::Sub.
The Rain section¶
The Rain: section of a template can also hold constants:
Use a constant in two ways:
!Rain::Constant <Name>inserts the value. The value can be a string or an object.${Rain::<Name>}inside a!Substring inserts a string value.
A constant can use the constants above it, with ${Rain::<Name>} in a !Sub.
Example¶
The template:
Parameters:
Env:
Type: String
Rain:
Constants:
App: billing
Prefix: !Sub ${Env}-${Rain::App}
Resources:
Bucket:
Type: AWS::S3::Bucket
Properties:
BucketName: !Sub ${Env}-${Rain::App}-uploads
Table:
Type: AWS::DynamoDB::Table
Properties:
TableName: !Rain::Constant Prefix
The packaged template:
Parameters:
Env:
Type: String
Resources:
Bucket:
Type: AWS::S3::Bucket
Properties:
BucketName: !Sub ${Env}-billing-uploads
Table:
Type: AWS::DynamoDB::Table
Properties:
TableName: !Sub ${Env}-billing
${Env} stays in the output, because it is a template parameter that CloudFormation resolves.
Known issue: a !Sub constant inside another !Sub¶
This packages to an empty value
If a constant is itself a !Sub string, do not use it with ${Rain::<Name>} inside another !Sub. cfnrain packages it to an empty string and shows no error.
Rain:
Constants:
Prefix: !Sub ${Env}-billing
Resources:
Table:
Type: AWS::DynamoDB::Table
Properties:
TableName: !Sub ${Rain::Prefix}-orders # packages to "-orders"
Use !Rain::Constant Prefix instead, as in the example above. That works.