When writing CloudFormation templates,
it is not uncommon for the documentation to state a property’s data type is
JSON. If you write your templates in JSON, this is no obstacle. However, I prefer
to write my templates in YAML, so I found myself looking for a toJSON
intrinsic
function to which I could pass a YAML object. My search came up empty, but I
did uncover a couple of ways to satisfy JSON property types while keeping my
templates readable.
To illustrate the problem, consider the EventBridge EventsRule resource. It
has a
property, EventPattern
, of type JSON.
Now the reason I am writing my template in YAML is because I prefer its
readability; I do not want to use JSON for this property. As it turns out, I
do not have to, and the solution is simple: create a YAML object that matches
the shape of the JSON object.
EventPattern:
account:
- !Sub '${AWS::AccountId}'
source:
- 'aws.ecr'
detail-type:
- 'ECR Image Action'
detail:
action-type:
- 'PUSH'
result:
- 'SUCCESS'
repository-name:
- !Ref EcrRepository
image-tag:
- 'latest'
Some CloudFormation properties expect a JSON string, and these properties have
a type String
. One such case is the
LifecyclePolicyText
property
of the Elastic Container Registry’s Repository > LifeCyclePolicy resource.
This property is a JSON string containing about 10 child properties, so I would prefer not to
place the entire string on a single line. Thankfully I
do not have to if I use the pipe symbol. The YAML specification instructs the
interpreter to interpret any indented text following the
pipe symbol as a single, multi-line value. This allows me to write a
JSON string in a readable format within my YAML template.
LifecyclePolicyText: |
{
"rules": [
{
"rulePriority": 1,
"description": "Keep only one untagged image, expire all others",
"selection": {
"tagStatus": "untagged",
"countType": "imageCountMoreThan",
"countNumber": 1
},
"action": {
"type": "expire"
}
}
]
}