AWS Cloud Operations Blog

The Virtues of YAML CloudFormation and Using CloudFormation Designer to Convert JSON to YAML

AWS CloudFormation provides the framework to define infrastructure-as-code in AWS and, until last year, this could only be written in JSON. However, in 2016, AWS added YAML 1.1 support for CloudFormation. Let’s take a look at some of the advantages of using YAML over JSON, as well as how to overcome some of the challenges in getting started writing CloudFormation in YAML.

The virtues of YAML

YAML CloudFormation fully supports all of the same features and functions as JSON CloudFormation with some additional features to reduce the length of code and increase readability. Say goodbye to the curly braces and most of the quotation marks of JSON when you use YAML. YAML uses parent nodes, child nodes, and indentation to denote hierarchy rather than curly braces and commas as in JSON.

YAML also supports comments using the # character. CloudFormation templates can get complex. Including key comments in the code can make it easier to understand, especially as teams get started with CloudFormation and develop templates together.

Let’s look at a code sample. The following YAML and JSON CloudFormation templates perform the same function, they deploy an Amazon Linux EC2 instance serving a webpage via Apache HTTP Server.

JSON template

{
    "AWSTemplateFormatVersion": "2010-09-09",
    "Parameters": {
        "SubnetID": {
            "Type": "AWS::EC2::Subnet::Id",
            "Description": "Subnet to deploy EC2 instance into"
        },
        "SecurityGroupIDs": {
            "Type": "List<AWS::EC2::SecurityGroup::Id>",
            "Description": "List of Security Groups to add to EC2 instance"
        },
        "KeyName": {
            "Type": "AWS::EC2::KeyPair::KeyName",
            "Description": "Name of an existing EC2 KeyPair to enable SSH access to the instance"
        },
        "InstanceType": {
            "Description": "EC2 instance type",
            "Type": "String",
            "Default": "t2.micro"
        }
    },
    "Mappings": {
        "AWSRegionToAMI": {
            "us-east-1": {
                "AMIID": "ami-0b33d91d"
            },
            "us-east-2": {
                "AMIID": "ami-c55673a0"
            }
        }
    },
    "Resources": {
        "EC2Instance": {
            "Type": "AWS::EC2::Instance",
            "Properties": {
                "ImageId": {
                    "Fn::FindInMap": [
                        "AWSRegionToAMI",
                        {
                            "Ref": "AWS::Region"
                        },
                        "AMIID"
                    ]
                },
                "InstanceType": {
                    "Ref": "InstanceType"
                },
                "KeyName": {
                    "Ref": "KeyName"
                },
                "SecurityGroupIds": {
                    "Ref": "SecurityGroupIDs"
                },
                "SubnetId": {
                    "Ref": "SubnetID"
                },
                "UserData": {
                    "Fn::Base64": {
                        "Fn::Sub": "#!/bin/bash -ex\nyum install -y httpd;\necho \"<html>I love YAML CloudFormation!!</html>\" > /var/www/html/index.html;\ncd /var/www/html;\nchmod 755 index.html;\nservice httpd start;\nchkconfig httpd on;\n"
                    }
                },
                "Tags": [
                    {
                        "Key": "Name",
                        "Value": "CloudFormation Test - YAML"
                    },
                    {
                        "Key": "Environment",
                        "Value": "Development"
                    }
                ]
            }
        }
    }
}

YAML template

AWSTemplateFormatVersion: 2010-09-09
Parameters:
  SubnetID:
    Type: AWS::EC2::Subnet::Id
    Description: Subnet to deploy EC2 instance into
  SecurityGroupIDs:
    Type: List<AWS::EC2::SecurityGroup::Id>
    Description: List of Security Groups to add to EC2 instance
  KeyName:
    Type: AWS::EC2::KeyPair::KeyName
    Description: >-
      Name of an existing EC2 KeyPair to enable SSH access to the instance
  InstanceType:
    Description: EC2 instance type
    Type: String
    Default: t2.micro
Mappings:
  AWSRegionToAMI:
    us-east-1:
      AMIID: ami-0b33d91d
    us-east-2:
      AMIID: ami-c55673a0
Resources:
  EC2Instance:
    Type: AWS::EC2::Instance                     
    Properties:
      ImageId:
        !FindInMap                                 # This is an example of the short form YAML FindInMap function
          - AWSRegionToAMI                         # It accepts three parameters each denoted by a hyphen (-)
          - !Ref AWS::Region
          - AMIID
      InstanceType: !Ref InstanceType
      KeyName: !Ref KeyName
      SecurityGroupIds: !Ref SecurityGroupIDs
      SubnetId: !Ref SubnetID
      UserData:
        Fn::Base64:                                # YAML makes userdata much cleaner
          !Sub |
              #!/bin/bash -ex
              yum install -y httpd;
              echo "<html>I love YAML CloudFormation!!</html>" > /var/www/html/index.html;
              cd /var/www/html;
              chmod 755 index.html;
              service httpd start;
              chkconfig httpd on;
      Tags:                                      # Tags are an example of a sequence of mappings in YAML,
        -                                        # each key/value pair is separated by a hyphen
          Key: Name
          Value: CloudFormation Test - YAML      
        -
          Key: Environment
          Value: Development

From a readability perspective, it’s pretty clear YAML is the winner. The JSON template is 1200 characters with whitespace removed. The YAML template is 972 characters for the exact same functionality with whitespace and comments removed. Shorter templates are not only more readable and make troubleshooting errors easier, but they also allow more resources to be deployed in a single template without hitting CloudFormation limits for template body size.

Converting a JSON CloudFormation template to YAML

We’ve established there are some advantages to using YAML, but many organizations already have libraries of JSON-formatted CloudFormation templates and employees with expertise writing JSON. Additionally, many publically available code samples are written in JSON along with many AWS QuickStarts. If only there were an easy, secure way to convert JSON CloudFormation to YAML. Old JSON templates could be reused and public samples could be converted to make learning YAML easier.

Enter CloudFormation Designer

CloudFormation Designer is an easy-to-use graphical user interface to create, edit, and view CloudFormation templates. The Designer is free and is part of the AWS Management Console. One fantastic feature is the ability to convert CloudFormation templates from JSON to YAML, and back again, with the click of a button. There are other online converters out there but the Designer is part of your AWS Management Console, so the code never leaves your possession.

 

Let’s convert our JSON template to YAML:

1. Open the AWS Management Console and navigate to the CloudFormation service.

2. Choose the Design template button to open the Designer.

 

3. Open the JSON CloudFormation template by choosing the File icon, then choosing Open from the menu.

 

4. Select the file, either a local file on your workstation or a file in an Amazon S3 bucket. This opens the CloudFormation template in Designer. We see the familiar JSON code of our template in the bottom pane. In the upper-right pane, we see a graphical representation of the EC2 instance described in our template. Finally, in the upper-left pane, we can optionally drag and drop a variety of Resource Types onto the canvas to include them in our template.

 

5. In the upper right-hand corner of the code pane, note the Choose template language radio button. Choose the button next to YAML to convert the template to YAML. Just like that our JSON is perfectly formatted YAML. Choosing the JSON button will convert the template back to JSON.

Caution: Converting a commented YAML template to JSON will remove all comments. Comments will not re-appear if the template is toggled back to YAML.

 

6. Save the template in YAML format by once again choosing the File icon and choosing Save from the menu.

Conclusion

In this blog post, we discussed some reasons to convert CloudFormation templates from JSON to YAML format and to code in YAML. We also did a side-by-side comparison of the readability of JSON and YAML using a sample template. Finally, we walked through how to convert existing JSON CloudFormation templates to YAML using CloudFormation Designer. There’s no better time than the present to dive in and get started with CloudFormation YAML. Happy coding!


About the Author

Aaron Fagan is a Senior Cloud Infrastructure Architect on the Boston AWS Professional Services team where he works with Enterprises to accelerate and optimize their adoption of the AWS public cloud. When not coding CloudFormation in YAML, he enjoys weightlifting and cooking.