Skip to main content
Nordlys logo, simplified northern lights aurora visualization Matt Ellis

Back to all posts

CloudFormation dry-run

Published on by Skux4life · 3 min read

Recently I’ve been delving into CloudFormation, particularly writing templates. I often use a pretty minimal setup consisting of a devcontainer with an Ubuntu base image and Vim. One challenge I kept hitting, discovering errors only after triggering a deployment.

Now, I could use some editor like VSCode and add some plugins and it would help provide some feedback. But, that’s not how I roll, I needed some other way of getting feedback. Also, being frugal (cheap), if I can write a valid template and avoid deploying it and any associated costs, that’s a win!

The solution

I managed to find a few tools that I can use that together provide me with what I call a “dry-run” of a CloudFormation template. They all fit well with my command line focused workflow and are easy to use.

cfn-lint

This will check your template against the actual AWS resource structure. Basically it’s way to make sure your template uses the correct properties and valid values. This will catch most typos and other syntax errors.

It’s written in python, so you can install it using pip. Then it’s simple to use.

Terminal window
# you may want it in a virtual environment
python3 -m venv .venv
source .venv/bin/activate
pip install cfn-lint
cfn-lint template.yaml

validate-template

The CloudFormation API has a validate-template command. AWS will parse the file and ensure the overall schema and syntax is correct. This includes instrinsic functions eg: Fn::Sub or Fn::GetAtt. The difference here with cfn-lint is that cfn-lint runs checks locally (more checks) and validate-template runs against the actual AWS API. This confirms AWS understands your template.

You use the aws cli for this:

Terminal window
aws cloudformation validate-template --template-body file://template.yaml

Change sets

To actually see what resources will be created then you can use a change set. CloudFormation will evaluate the template against your live AWS account. This can pick up issues like resource name conflicts or invalid IAM principals or malformed policy statements.

First you need to generate a preview. The --no-execute-changeset option is important to include for this.

Terminal window
aws cloudformation deploy \
--template-file template.yaml \
--stack-name my-dev-stack \
--no-execute-changeset

Then you view the preview. The output of the above command will provide you another command to run to review the changes.

Terminal window
# otherwise you can do the following to get the changeset name
aws cloudformation list-change-sets --stack-name my-dev-stack
# Then, view the details
aws cloudformation describe-change-set \
--stack-name my-dev-stack \
--change-set-name <your-change-set-name-or-arn>

After this, you can choose to execute or delete the change-set.

Terminal window
# delete example
aws cloudformation delete-change-set --change-set-name <change-set-name-or-arn>
# you will need to delete stack if it was a brand new one
aws cloudformation delete-stack --stack-name <my-stack-name>

Limitations of this dry-run

Even if a change set is created successfully, it does not mean the deployment will succeed.

A couple of examples of issues (not-exhaustive) that can still arise at deployment time:

  • The role that executes the deployment may not have necessary permissions so the deployment will fail.
  • You reach a service quota limit. This could be an IAM role limit for the account or you’ve reached the limit for elastic IPs.

Whilst not perfect, I’ve found this dry-run a very welcome addition to my workflow when crafting CloudFormation templates.