AWS DevOps Blog

CloudFormation and the New AWS CLI

CloudFormation provides a number of different ways to use the service. From the web API to language-specific SDKs to GUIs like the AWS Management Console, you choose the interface that’s right for you. For those of you using (or interested in using) the CloudFormation command line interface (CLI), this post’s for you.

The original CloudFormation CLI has been around for a few years, providing helpful tools that let you manage stacks from your command line. Commands like cfn-create-stack, cfn-describe-stack-resources, and cfn-delete-stack make it simple yet powerful to orchestrate and manage your AWS infrastructure and apps without touching a mouse. The new unified AWS CLI – which recently moved from Developer Preview to General Availability – replaces the original CLI and brings a ton of great new features: the new CLI includes all services in the same installation (and it’s simple to install), provides multiple outputs (from JSON to table-formatted), and gives you advanced features like command and parameter auto-completion. 

Let’s walk through a few of the actions many customers use the CloudFormation CLI for, and see how to do them in the new AWS CLI.

Create a Stack

Creating a new CloudFormation stack via the original CLI involved the cfn-create-stack command. For this example, I’m using a sample WordPress template stored in S3 (and publicly available as part of our sample template library) . To run the stack using the new AWS CLI I execute:

aws cloudformation create-stack --stack-name wordpress 
--template-url https://s3.amazonaws.com/cloudformation-templates-us-east-1/WordPress_Multi_AZ.template 
--parameters ParameterKey=KeyName,ParameterValue=YOUR_KEY_NAME

The output of that command is a JSON object with the ARN of the stack:

{
"StackId":"arn:aws:cloudformation:us-east-1:9...6:stack/wordpress/2e0-...-0b34c44"
}

If the default JSON output isn’t your style, you can choose text- or table-formatted output by adding an --output=text or –output=table argument to the command.

Although I provided parameters for the stack as inline arguments, you can also store launch parameters in a file or S3 object and reference them via the file:// or http://. This makes it simple to standardize and share stack launch commands with your team. For example, if my parameters were stored in a text file in S3, I might launch the stack with:

aws cloudformation create-stack --stack-name wordpress 
--template-url https://s3.amazonaws.com/cloudformation-templates-us-east-1/WordPress_Multi_AZ.template 
--parameters http://s3.amazonaws.com/my-bucket/wordpress_launch_params.json

Describe Stack Resources

CloudFormation makes it straightforward, repeatable, and predictable to create a complex environment in AWS, but once a stack is up and running CloudFormation also provides an API to locate individual resources in the stack, serving as a ‘resource catalog’ of sorts.

Using the WordPress example, let’s say I wanted to know the ID of the RDS database backing my blog so that I could connect to the database from a DB management tool (like MySQL Workbench). Looking at the template I see that the database is declared with a logical resource ID of “DBInstance”. I can get detailed information about the resource by calling the describe-stack-resource API:

aws cloudformation describe-stack-resource --stack-name wordpress 
--logical-resource-id DBInstance

By default the response returns a JSON-formatted string that includes the physical ID of the database:

{
    "StackResourceDetail": {
        "StackId": "…",
        "ResourceStatus": "CREATE_COMPLETE",
        "ResourceType": "AWS::RDS::DBInstance",
        "LastUpdatedTimestamp": "2013-08-25T01:47:00.739Z",
        "StackName": "wordpress",
        "PhysicalResourceId": "wdsxlxjjbe2rrc",
        "LogicalResourceId": "DBInstance"
    }
}

Now that I have the ID of the database, I can use the AWS CLI to ask RDS for the hostname of the database, using the PhysicalResourceId returned from the previous command:

aws rds describe-db-instances --db-instance-identifier wdsxlxjjbe2rrc

This command also returns a JSON-formatted string that includes the endpoint address (i.e., hostname) of my database. Here’s a snippet of the output:

{
    "DBInstances": [
        {
            "PubliclyAccessible": true,
            "MasterUsername": "admin",
            "LicenseModel": "general-public-license",
            "VpcSecurityGroups": [],
            "InstanceCreateTime": "2013-09-30T23:46:04.778Z",
            "OptionGroupMemberships": [
                {
                    "Status": "in-sync",
                    "OptionGroupName": "default:mysql-5-6"
                }
            ],
            "PendingModifiedValues": {},
            "Engine": "mysql",
	…
        }
}

We use Command Line Interfaces to be quick and efficient. If we just wanted to find the address of our RDS endpoint, we can use the awesome tool jq to help us parse the JSON response and chain the two commands together, returning the one piece of data we care about:

aws cloudformation describe-stack-resource --stack-name wordpress 
--logical-resource-id DBInstance 
| jq '.StackResourceDetail .PhysicalResourceId' 
| xargs aws rds describe-db-instances --db-instance-identifier 
| jq '.DBInstances[0] .Endpoint .Address'

Instead of the complete JSON response, we get exactly the piece of data we care about:

WDXXXXXXX22.chXXXXXXXXXimf.us-east-1.rds.amazonaws.com

Summary

We’re excited about the new AWS CLI, and we hope you are too. As you can see, usage is slightly different compared to the original cfn-* tools, but having the entire AWS CLI family in one easily installable package makes the automation we all crave that much easier. For a deeper look at CloudFormation and the AWS CLI, head on over to the CloudFormation documentation.