cfn-flow

An opinionated command-line workflow for developing AWS CloudFormation templates. Track template changes in git and upload versioned releases to AWS S3.

Opinions

  1. Optimize for onboarding. The workflow should be simple to learn & understand.
  2. Optimize for happiness. The workflow should be easy and enjoyable to use.
  3. Auditable history. Know who changed what when. Leverage git for auditing.
  4. Immutable releases. The code in a release never changes.

Installation

Via rubygems:

gem install cfn-flow

The git command is also needed.

Usage

Poke around:

cfn-flow help

Dev mode (default)

Dev mode allows you to quickly test template changes. cfn-flow validates all templates and uploads them to your personal prefix, overwriting existing templates.

Dev mode does not verify that your local changes are committed to git (as opposed to release mode).

You should use dev mode for testing & verifying changes in non-production stacks.

# Set a personal name to prefix your templates.
export CFN_FLOW_DEV_NAME=aaron

# Validate and upload all CloudFormation templates in your working directory to
s3://my-bucket/dev/aaron/*
# NB that this overwrites existing templates in your CFN_FLOW_DEV_NAME
namespace.

cfn-flow

You can launch or update test stacks using your dev template path to quickly test your template changes.

Release mode

Release mode publishes your templates to a versioned S3 path, and pushes a git tag of the version.

# uploads templates to `s3://my-bucket/release/<git sha>/*`
tag
cfn-flow --release

Release mode ensures there are no uncommitted changes in your git working directory.

Inspecting the differences between releases is possible using git log and git diff.

Configuration

You can configure cfn-flow defaults by creating a cfn-flow.yml file in same directory you run cfn-flow (presumably the root of your project).

Settings in the configuration file are overridden by environment variables. And environment variables are overridden by command line arguments.

# cfn-flow.yml in the root of your project
# You can specify an alternative path by setting the CFN_FLOW_CONFIG environment
# variable.
#
# All options in this config can be overridden with command line arguments
---
# S3 bucket where templates are uploaded. No default.
# Override with CFN_FLOW_BUCKET env var
bucket: 'my-s3-bucket'

# S3 path prefix. Default: none
# Override with CFN_FLOW_TO env var
to: my/project/prefix

# Local path in which to recursively search for templates. Default: .
# Override with CFN_FLOW_FROM env var
from: my/local/prefix

# AWS Region
# Override with AWS_REGION env var
region: us-east-1 # AWS region

AWS credentials

AWS credentials can only be set using the AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY environment variables; or by using an EC2 instance's IAM role.

Sweet Features

YAML > JSON

cfn-flow lets you write templates in either JSON or YAML. YAML is a superset of JSON that allows a terser, less cluttered syntax, inline comments, and code re-use with variables. YAML templates are transparently converted to JSON when uploaded to S3 for use in CloudFormation stacks.

Use versions in nested stack template URLs

cfn-flow works great with nested stack resources. Use Fn::Join to construct the TemplateURL from a parameter:

{
   "Type" : "AWS::CloudFormation::Stack",
   "Properties" : {
      "TemplateURL" : {
        "Fn::Join" : [ ":",
          [ "https://s3.amazonaws.com/my-bucket", {"Ref": "prefix"}, "my-template.json" ]
          ]
      }
   }
}

While testing, set the prefix parameter to a dev prefix like dev/aaron. When you're confident your changes work, release them with cfn-flow and change the prefix parameter to release/<git sha> for production.

Continuous integration

Github commit status

Minimal AWS credentials

TODO: example IAM policy