AWS recently released a new “game changing” feature for CloudFormation Templates – support for YAML. I’d like to give a first look at utilizing YAML for CloudFormation Templates (CFTs) and discuss how this feature might be incorporated in the architect and engineer’s toolbox for AWS. If you’re not familiar with YAML you’ll want to take a look at the guides here.
YAML Support
This is something the AWS community has been begging for, for quite a while. One of the easiest ways to tell that JSON is not sufficient is the numerous projects that exist to support JSON based templates (Troposphere, Sparkleformation, Terraform, etc). Now with YAML support we’re getting that much closer to that Infrastructure-as-Code feeling we’ve been missing. Let’s walk through some sample YAML CFT code and highlight where it has a major impact. The code samples below are borrowed almost entirely from the AWS UserGuide for CloudFormation.
AWSTemplateFormatVersion: "2010-09-09"
Description: A sample template
Parameters:
FilePath:
Description: The path of the file.
Type: String
Default: /home/ec2-user/userdata
Resources:
MyEC2Instance:
Type: "AWS::EC2::Instance" # 1 Quotes are unnecessary here - will they always be?
Properties:
ImageId: ami-c481fad3 # 2 Quotes removed from the example - still works
InstanceType: t2.nano
KeyName: 2ndwatch-sample-keypair
Tags: # 3 Here I switch to using single spaces
- Key: Role # 4 Tag list item is inline
Value: Test Instance
- # 5 Next list item is block
Key: Owner
Value: 2ndWatch
BlockDeviceMappings: # 6 Switch back to double spaces
-
DeviceName: /dev/sdm
Ebs:
VolumeType: gp2
VolumeSize: 10
UserData:
Fn::Base64: !Sub | # No more Fn::Join needed
#!/bin/bash
echo "Testing Userdata" > ${FilePath}
chown ec2-user.ec2-user ${FilePath}
A couple of things you notice in this example are how clean the code looks and the comments. These are both necessary to make code descriptive and clear. In the comments I call out a few considerations with the YAML format.
First, in many of the examples AWS provides there are quotes around values that don’t need them. When I removed them (comment 1 and 2), the CFT still worked. That said, you may want to codify on quotes/no quotes at the start of your project or for your entire department/company for consistency. Additionally, as you will notice in my second set of comments, I switch from 2-space to 1-space YAML formatting (comments #3 and #6). This is “legal” but annoying. Just as with JSON, you’ll need to set some of your own rules for how the formatting is done to ensure consistency.
Taking a look at the Tags section you’ll see that lists are supported using a hyphen notation. In the Tags property I’ve displayed two different formats for how a list item may be denoted. 1. There can be a hyphen alone on a line with a “block” underneath (comment #5) or 2. Inline with the hyphen and the rest following after with the same spacing (comment #4). As before, you’ll want to decide how you want to format lists. Multiple AWS examples do it in different ways.
Following on to the userdata property, the next thing you’ll notice is the lack of the Fn::Join function. This makes the creation of userdata scripts very close to the actual script you would run on the server. In a previous article I gave Terraform high marks for having similar functionality, and now AWS has brought CFT up to par. The new !Sub notation helps clean up the substitution a bit, too (it’s also available in JSON). Of course if you miss it, the Fn::Join can still be used like this:
Tags:
- Key: Name
Value:
Fn::Join:
- "-"
- - !Ref AWS::StackName
- PrivateRouteTable1
This would produce a tag of Name = StackName-PrivateRouteTable1 just like it did previously in JSON, but we would advise against doing this because the old notation is much less flexible and more prone to error than the new “joinless” formatting. Notice that nested lists are created using two hyphens.
Conversion Tools
In another bit of good news, you can utilize online conversion tools to update your JSON CFTs to YAML. As you might guess, it will take a bit of cleanup to bring it in line with whatever formatting decisions you’ve made, but it gets you most of the way there without a complete rewrite. Initial s on simple CFTs ran with no updates required (using https://www.json2yaml.com/). A second on a 3000-line CFT converted down to 2300 lines of YAML and also ran without needing any updates (YMMV). This is a big advantage over tools like Terraform where all new templates would have to be built from scratch, particularly since a conversion tool could probably be whipped together in short order.
In conclusion, the introduction of YAML support in CloudFormation Templates (CFTs) brings significant benefits to AWS users. With cleaner and more readable code, YAML makes it easier to create descriptive and clear templates. While some considerations, such as the usage of quotes and formatting rules, need to be addressed for consistency, the overall experience of writing CFTs is greatly improved. Moreover, the ability to convert existing JSON templates to YAML using online conversion tools adds convenience and saves time. This update reflects AWS’s commitment to enhancing the CloudFormation service. If you have any questions or need assistance with getting started, don’t hesitate to contact us at 2nd Watch.
All in all, this is a great update to the CloudFormation service and demonstrates AWS‘s commitment to pushing the service forward.
If you have questions or need help getting started, please Contact Us at 2nd Watch.
- Coin Graham, Sr Cloud Consultant, 2nd Watch
You can also use a simple python script to convert JSON to YAML.
https://gist.github.com/vishnu21/c7a8211a744b25f3c3eabba74429d9ff
Daniel,
If the order of your template is important this tool might be of use…
https://github.com/drbild/json2yaml
Developers rarely get the time to convert old (working) code to a newer format despite the advantages.
A utility to parse old the yaml syntax and convert all the Joins etc to use the new syntax would be a godsend.
Not sure if one can automate the Userdate Join -> Sub, but that would also be fantastic.