In my last blog
post,
I promised a rant about using YAML for CloudFormation templates. Here it
is. If you persevere to the end I’ll also show you have to convert your
existing JSON based templates to YAML.
Many of the points I raise below don’t just apply to CloudFormation.
They are general comments about why you should use YAML over JSON for
configuration when you have a choice.
One criticism of YAML is its reliance on indentation. A lot of the code
I write these days is Python, so indentation being significant is
normal. Use a decent editor or IDE and this isn’t a problem. It doesn’t
matter if you’re using JSON or YAML, you will want to validate and lint
your files anyway. How else will you find that trailing comma in your
JSON object?
Now we’ve got that out of the way, let me try to convince you to use
YAML.
As developers we are regularly told that we need to document our code.
CloudFormation is Infrastructure as Code. If it is code, then we need to
document it. That starts with the Description
property
at the top of the file. If you JSON for your templates, that’s it, you
have no other opportunity to document your templates. On the other hand,
if you use YAML you can add inline comments. Anywhere you need a
comment, drop in a hash #
and your comment. Your team
mates will thank you.
JSON templates don’t support multiline strings. These days many
developers have 4K or ultra wide monitors, we don’t want a string that
spans the full width of our 34″ screen. Text becomes harder to read once
you exceed that “90ish” character limit. With JSON your multiline string
becomes
"[90ish-characters]\n[another-90ish-characters]\n[and-so-on]"
.
If you opt for YAML, you can use the greater than symbol
(>
) and then start your multiline comment like so:
escription: >
This is the first line of my Description
and it continues on my second line
and I'll finish it on my third line.
As you can see it much easier to work with multiline string in YAML than
JSON.
“Folded blocks” like the one above are created using the
>
replace new lines with spaces. This allows you to
format your text in a more readable format, but allow a machine to use
it as intended. If you want to preserve the new line, use the pipe
(|
) to create a “literal block”. This is great for an
inline Lambda functions where the code remains readable and
maintainable.
APIFunction:
Type: AWS::Lambda::Function
Properties:
Code:
ZipFile: |
import json
import random
def lambda_handler(event, context):
return {"statusCode": 200, "body": json.dumps({"value": random.random()})}
FunctionName: "GetRandom"
Handler: "index.lambda_handler"
MemorySize: 128
Role: !GetAtt LambdaServiceRole.Arn
Runtime: "python3.7"
Timeout: 5
Both JSON and YAML require you to escape multibyte characters. That’s
less of an issue with CloudFormation templates as generally you’re only
using the ASCII character set.
In a YAML file generally you don’t need to quote your strings, but in
JSON double quotes are used every where, keys, string values and so on.
If your string contains a quote you need to escape it. The same goes for
tabs, new lines, backslashes and and so on. JSON based CloudFormation
templates can be hard to read because of all the escaping. It also makes
it harder to handcraft your JSON when your code is a long escaped string
on a single line.
Some configuration in CloudFormation can only be expressed as JSON. Step
Functions and some of the AppSync objects in CloudFormation only allow
inline JSON configuration. You can still use a YAML template and it is
easier if you do when working with these objects.
The JSON only configuration needs to be inlined in your template. If
you’re using JSON you have to supply this as an escaped string, rather
than nested objects. If you’re using YAML you can inline it as a literal
block. Both YAML and JSON templates support functions such as
Sub
being applied to these strings, it is so much more
readable with YAML. See this Step Function example lifted from the AWS
documentation:
MyStateMachine:
Type: "AWS::StepFunctions::StateMachine"
Properties:
DefinitionString:
!Sub |
{
"Comment": "A simple AWS Step Functions state machine that automates a call center support session.",
"StartAt": "Open Case",
"States": {
"Open Case": {
"Type": "Task",
"Resource": "arn:aws:lambda:${AWS::Region}:${AWS::AccountId}:function:open_case",
"Next": "Assign Case"
},
"Assign Case": {
"Type": "Task",
"Resource": "arn:aws:lambda:${AWS::Region}:${AWS::AccountId}:function:assign_case",
"Next": "Work on Case"
},
"Work on Case": {
"Type": "Task",
"Resource": "arn:aws:lambda:${AWS::Region}:${AWS::AccountId}:function:work_on_case",
"Next": "Is Case Resolved"
},
"Is Case Resolved": {
"Type" : "Choice",
"Choices": [
{
"Variable": "$.Status",
"NumericEquals": 1,
"Next": "Close Case"
},
{
"Variable": "$.Status",
"NumericEquals": 0,
"Next": "Escalate Case"
}
]
},
"Close Case": {
"Type": "Task",
"Resource": "arn:aws:lambda:${AWS::Region}:${AWS::AccountId}:function:close_case",
"End": true
},
"Escalate Case": {
"Type": "Task",
"Resource": "arn:aws:lambda:${AWS::Region}:${AWS::AccountId}:function:escalate_case",
"Next": "Fail"
},
"Fail": {
"Type": "Fail",
"Cause": "Engage Tier 2 Support."
}
}
}
If you’re feeling lazy you can use inline JSON for IAM policies that
you’ve copied from elsewhere. It’s quicker than converting them to YAML.
YAML templates are smaller and more compact than the same configuration
stored in a JSON based template. Smaller yet more readable is winning
all round in my book.
If you’re still not convinced that you should use YAML for your
CloudFormation templates, go read Amazon’s blog post from 2017
advocating the use of YAML based
templates.
Amazon makes it easy to convert your existing templates from JSON to
YAML.
cfn-flip
is aPython based AWS Labs tool for
converting CloudFormation templates between JSON and YAML. I will assume
you’ve already installed
cfn-flip.
Once you’ve done that, converting your templates with some automated
cleanups is just a command away:
cfn-flip --clean template.json template.yaml
git rm
the old json file, git add
the
new one and git commit
and git push
your
changes. Now you’re all set for your new life using YAML based
CloudFormation templates.
If you want to learn more about YAML files in general, I recommend you
check our Learn X in Y Minutes’ Guide to
YAML. If you want to learn
more about YAML based CloudFormation templates, check Amazon’s Guide to
CloudFormation
Templates.