Advanced solutions with CFNDSL and CloudFormation

This is the final post in our blog series about CFNDSL and we’ll be talking about some advanced use cases for the DSL and reviewing some troubleshooting techniques for both the DSL and CloudFormation.

Looking for the beginning? Check out our first and second parts of the series where we introduce CFNDSL and discuss how to use it:

 

Leveraging the CFNDSL Environment

Saved for last, the final notable feature of CFNDSL is the ability to leverage variables from your environment using a simple and concise API. You can provide context to your templates in three ways:

Through your shell environment. Since CFNDSL is a ruby script you have direct access to your environment via the ENV variable name. Using this method you can pull in information about the environment (perhaps your pipeline) when executing the template. This is a great tool to use in conjunction with the other methods of providing context since it’s inherently available.

EC2_Instance(:shortExample) {
  addTag(:source, ENV[‘USER’])
}

ProTip! The addTag method is a hidden little gem of CFNDSL that tends to be easier than dealing with the hash syntax. This method is available on all resources that support tagging.

By using a configuration file. Perhaps you have some application specific configurations on a shared set of CFNDSL templates. You can use a YAML or ruby-based configuration file that is loaded at compile time to provide your configuration.

Load a YAML file with the -y option

$ cfndsl my-template.rb -y my-yaml-configuration.yml

Load a ruby file with the -r option

$ cfndsl my-template.rb -r my-ruby-configuration.rb

Note: You can also use JSON as a configuration option — but that’s what we’re trying to avoid here entirely. The CFNDSL option is -j for JSON.

For some in-depth examples of using a configuration file, check out the project’s README — a well-made example needs not repeated.

Pass your variables through the command line. The -D option allows you to set a variable on the command line which can be used in the template. This is your best option for less complex solutions but likely to get unwieldy in solutions with a large number of parameters.

$ cfndsl my-template.rb -D ‘vpc=”vpc-1234567”’ -D ‘subnet=”subnet-1234567”’

Determining the best approach to providing context to your templates will vary wildly with your environment, pipeline or application. However, here’s some quick points to consider for each of the options:

  • Use environment variables for resources that are shared. Proxy configurations are a great example of this.
  • Configuration files are best when generated on the fly and when in large quantities. Perhaps your chef recipe can build this file from attributes.
  • Command-line configuration is best for quick changes or default overrides.
  • CloudFormation parameters are not listed above but also provide some post-compiled template changes which are great for development/testing.

Troubleshooting
If you’re like me and have some grossly complicated CloudFormation templates under your belt then you’ll be needing to troubleshoot. CFNDSL is pure business when it comes to giving output — so be prepared to be left to your own devices. I’ve picked up a few tricks along the way and I’d like to share them with you:

  • Validate your ruby code
  • Look at the JSON generated template
  • Validate the template with AWS
  • Launch the stack

If you’re experiencing issues with CFNDSL itself (e.g. cryptic exception) you can validate that your ruby syntax is valid with the following command:

$ ruby -c my-template.rb

The best way to debug your template is to simply look at it. Sometimes your template will compile and you’ll receive a template but your contents are bamboozling the end result. The raw output is unformatted JSON so you’re going to need to pretty print it. The way I recommend is installing a ruby gem called json_pp, which works on the STDIN to pretty print json.

$ cfndsl my-template.rb | json_pp

In addition to making the output human readable, you can always test the template in AWS. There’s a couple ways you can do this and ultimately you’ll want to do both. However, the first step: validation, will help weed out most errors before having to wait for a stack to be built.

Step 1: Use the AWS validation tool

$ aws cloudformation validate-template 
  --template-body file:///home/ubuntu/my-template.json

Step 2: Ship it!

$ aws cloudformation create-stack 
  --stack-name test-stack 
  --template-body file:///home/ubuntu/my-template.json

ProTip! How many times have you been 20 minutes invested into a CloudFormation stack creation and see the infamous ‘Required: CAPABILITY_IAM’ message? If you get into a habit of using the validation tool provided by AWS you can avoid this mistake.

Conclusion
I hope that by now you feel energized to dive into the world of CloudFormation using CFNDSL. It’s a fantastic tool that can swashbuckle with the most complex of applications or code pipelines. If you’re looking for another way to make positive impact on your infrastructure-as-code then I highly recommend adopting this tool — it’s maintainable, testable and provides great flexibility for your developers.


This was part three of our series: be sure to read parts one and two.

One thought on “Advanced solutions with CFNDSL and CloudFormation

Leave a Reply