AWS CloudFormation Update Evaluation - YAML, Cross-Stack References, Simplified Substitution
In mid-September, AWS released a big update to CloudFormation.
The update contained:
- YAML Support – You can now write your CloudFormation templates in YAML.
- Cross Stack References – You can now export values from one stack and use them in another.
- Simplified Substitution – You can more easily embed variables in strings.
After one month of using the new features, I want to share my learnings with you.
YAML Support
During the last 4 weeks I discovered three main advantages of using YAML over JSON to describe my CloudFormation templates:
- Support for multi-line strings
- It is possible to use comments within a template
- YAML is more compact than JSON
Let me explain them in more detail.
Support for multi-line strings
The UserData
property usually consists of many lines. In JSON there was no elegant way to express this. Instead, you used the Fn::Join
function of CloudFormation.
{ |
In YAML this looks much nicer:
|
Use comments within a template
In YAML you can add comments.
|
Nothing fancy, but very helpful :)
YAML is more compact than JSON
I converted all our Free Templates for AWS CloudFormation from JSON to YAML. See how the number of lines changed:
template | JSON lines | YAML lines |
---|---|---|
ec2/ec2-auto-recovery | 460 | 403 (-13%) |
jenkins/jenkins2-ha-agents | 1636 | 1599 (-3%) |
jenkins/jenkins2-ha | 747 | 656 (-13%) |
security/account-password-policy | 160 | 161 (+0%) |
security/cloudtrail | 134 | 101 (-25%) |
security/config | 92 | 77 (-17%) |
static-website/static-website | 147 | 183 (+24%) |
vpc/vpc-2azs | 289 | 253 (-13%) |
vpc/vpc-3azs | 356 | 306 (-15%) |
vpc/vpc-4azs | 423 | 359 (-16%) |
vpc/vpc-nat-gateway | 39 | 51 (+30%) |
vpc/vpc-nat-instance | 518 | 446 (-14%) |
wordpress/wordpress-ha | 670 | 602 (-11%) |
On average the templates get smaller.
Ouch
What I do not like is that there is more than one way to represent strings:
- Sometimes you need quotes; sometimes they are optional
- Sometimes you need single quotes; sometimes you can use double quotes
The rules seem to be more complicated than just using double quotes all the time like in JSON. I finally ended up with using single quotes all the time unless the string contains only [a-zA-Z0-9]. However, that is just my personal style. It ends up in a total mess if multiple people work on a single template.
Cross Stack References
Instead of putting everything in a single template it can make sense to split them up. One very common example is the VPC. You create one CloudFormation stack that contains your VPC. Each application that you run is also a stack, but they depend on the VPC stack. Before Cross Stack References you could solve this problem with Parameters.
Application template
{ |
with Cross Stack References you can export values in one stack and import them in another stack. Let’s see how this works.
VPC template
|
The vpc stack now exports the subnet id under the name vpc-subnet
.
Application template
|
The application stack imports the subnet id.
With Cross Stack References you can pass data from one stack to another.
Ouch
It is not possible to export and import a list of values at the moment. You can export a comma separated string, but you are not able to import that string as a list.
Keep in mind that you can not change exported values.
Simplified Substitution
Let’s again have a look at the UserData
property. It usually not only consists of many lines, but it also references some resources. In JSON I used Fn::Join
and Ref
for this like crazy:
{ |
In YAML this looks cleaner:
|
So the magic is the Fn::Sub
function or shorter !Sub
. It substitutes references inside ${}
automatically with the value.
Ouch
Unfortunately, it is not possible to write !Base64 !Sub |
. The documentation tells us:
If you use the short form and immediately include another function in the valueToEncode parameter, use the full function name for at least one of the functions. For example, the following syntax is invalid:
!Base64 !Sub string |
Instead, use the full function name for at least one of the functions, as shown in the following examples:
'Fn::Base64': |
I hope this is fixed shortly.
Summary
The CloudFormation update makes our lives easier:
- We can now write the template in YAML which makes them shorter.
- We can add comments and deal with multi-line strings without struggles.
- The simplified substitution removes complex
Fn::Join
s from our templates. - We can pass data between stacks with Cross Stack References.
As always, new features have rough edges:
- I is not possible to write
!Base64 !Sub |
instead we need to write:'Fn::Base64': !Sub |
- It is not possible to export and import a list values with Cross Stack References.
- YAML and strings are complicated. Many options and many ways to do express the same in different ways.
All in all, I can recommend the new YAML format.
I started with an automatic conversion from JSON to YAML with:
ruby -ryaml -rjson -e 'puts YAML.dump(JSON.parse(STDIN.read))' < template.json > template.yaml |
and then that hard manual work begins when you want to use simplified substitution and YAML multi line support.
Further reading
- Article New CloudFormation Template - Authentication Proxy using your GitHub Organization and YAML
- Article Interacting with AWS to turn system diagrams into reality
- Article Understanding Infrastructure as Code
- Article CloudFormation vs Engineers: How to protect your CloudFormation managed AWS account from human intervention
- Tag cloudformation