This package provides a simple interface for the deployment of a CloudFormation stack. It implements the following deployment pattern, avoiding the use of stack updates in favor of stack creation and deletion:
- Request stack creation.
- Wait on the stack status to show show success.
- Update existing resources to point to the new stack.
- Delete any previous instances of the stack once the switchover is done.
This is well suited to deploying webserver stacks that include an Auto Scaling Group and Elastic Load Balancer. The update step between successful creation of a new stack and starting the deletion of an old stack might consist of updating a Route 53 CNAME record to point to the new stack and then allowing time for propagation.
Obtain CloudFormation Deploy via NPM:
npm install cloudformation-deploy
See the examples directory for ready to run examples.
For deployment to work, suitable credentials for the destination AWS account must be present. The credentials must at a minimum allow interaction with CloudFormation stacks and granting all suitable permissions to stack resources via IAM roles.
To make credentials available, either create a credentials file in the standard location, set environment variables to hold the key, secret key and region, or run on an EC2 instance with an IAM role that has suitable permissions. These options are described in the AWS SDK documentation.
For example, if using environment variables:
export AWS_ACCESS_KEY_ID=<key>
export AWS_SECRET_ACCESS_KEY=<secret key>
export AWS_REGION=us-east-1
Alternatively, CloudFormation Deploy accepts an optional configuration object that is passed to the AWS SDK CloudFormation client instance if present. See the configuration details below. This is not recommended: it is bad practice to specify access keys in code or configuration for code. You should always add them to the environment in one of the ways noted above.
Generate or load the CloudFormation template. This module can accept the template as either a JSON string, an object, or a URL to a template uploaded to S3. Use the latter method for larger templates, as it has a larger maximum size limit.
Run the following code.
cloudFormationDeploy = require('cloudformation-deploy');
// Pull in the CloudFormation template from a JSON file or object.
//var template = fs.readFileSync('example.json', { encoding: 'utf8' });
//var template = { ... };
// Or specify a URL.
var template = 'http://s3.amazonaws.com/bucket/example.json';
var config = {
// --------------------
// Required properties.
// --------------------
// The baseName and deployId are combined to form a unique name.
//
// Tags are automatically added based on these values and the version, and are
// used when deleting old stacks from earlier versions and prior deployments.
//
// The deployId property is along the lines of BUILD_NUMBER in Jenkins or
// a similar values generated by another task framework. Using a Unix
// timestamp is an acceptable fallback if nothing else is available.
baseName: 'example-stack',
deployId: '15',
version: '0.1.0',
// --------------------
// Optional properties.
// --------------------
// If defined, this property is passed to the AWS SDK client. It is not
// recommended to use this approach, see above for comments on configuring
// AWS access via the environment.
// clientOptions : {
// accessKeyId: 'akid',
// secretAccessKey: 'secret',
// region: 'us-east-1'
// },
// Timeout in minutes for the process of stack creation.
createStackTimeoutInMinutes: 10,
// Specify additional tags to apply to the stack.
tags: {
name: 'value'
},
// Pass in any parameters required by the template.
parameters: {
name: 'value'
},
// Seconds to wait between each check on the progress of stack creation or
// deletion.
progressCheckIntervalInSeconds: 10,
// A function invoked whenever a CloudFormation event is created during
// stack creation or deletion.
onEventFn: function (event) {
console.log(event);
},
// A function invoked after the CloudFormation stack is successfully created
// but before any prior stack is deleted. This allows for a clean switchover
// of resources to use the new stack.
//
// The provided stackDescription object is the standard output from the
// describeStacks API for the created stack.
postCreationFn: function (stackDescription, callback) {
// Take action here, such as updating a Route 53 DNS entry and waiting for
// propagation to complete.
callback();
},
// What to do with prior instances of this stack, which is defined as any
// stack deployed with the same baseName.
priorInstance: cloudFormationDeploy.priorInstance.DELETE,
// What to do with this deployed stack should it fail to complete
// successfully.
onFailure: cloudFormationDeploy.onFailure.DELETE
};
cloudFormationDeploy.deploy(config, template, function (error, results) {
if (error) {
console.error(error);
}
// Whether or not there is an error, the results object is returned. It will
// usually have additional useful information on why the stack deployment
// failed. On success it will include the stack description, outputs
// defined in the CloudFormation template, and events.
console.log(results);
});
The config
object passed to cloudFormationDeploy.deploy
supports the
following required and optional properties.
baseName
- string
- Combined with deployId
to generat the stack name.
version
- string
- The version of the application deployed to the stack.
deployId
- string
- A distinguishing string for this stack baseName, such as
a build number, to ensure this stack name is unique even for multiple
deployments of the same version.
createStackTimeoutInMinutes
- number
- A timeout in minutes for stack
creation or deletion. Defaults to 10
.
tags
- object
- The tags to apply to the stack in addition to those created
automatically based on the baseName
. Tag values must be strings.
parameters
- object
- Values to apply to the parameters in the
CloudFormation template. Parameter values must be strings.
progressCheckIntervalInSeconds
- number
- Number of seconds to wait between each
check on the progress of stack creation or deletion. Defaults to 10
.
onEventFn
- function
- A function invoked whenever a new event is
created during stack creation or deletion.
function (event) {
console.log(event);
}
postCreationFunction
- function
- A function invoked after a stack is
successfully created but before any prior instance of the stack with the same
baseName
is destroyed. This allows resources to be updated to use the new
stack.
function (stackDescription, callback) {
// Take action here, such as updating a Route 53 DNS entry and waiting for
// propagation to complete.
callback();
}
priorInstance
- string
- One of the allowed values describing what to do
with previously deployed stacks with the same baseName
. Defaults to
cloudFormationDeploy.priorInstance.DELETE
and the allowed values are:
cloudFormationDeploy.priorInstance.DELETE
cloudFormationDeploy.priorInstance.DO_NOTHING
onFailure
- string
- One of the allowed values describing what to do with
the deployed stack on failure. Defaults to
cloudFormationDeploy.onFailure.DELETE
and the allowed values are:
cloudFormationDeploy.onFailure.DELETE
cloudFormationDeploy.onFailure.DO_NOTHING
All failure cases will result in cloudFormationDeploy.deploy
calling back with
an error. The state of the stacks depends on where in the process that error
occurred, however.
- If the stack creation fails, then:
- The
postCreationFn
function is not invoked. - The failed stack is deleted if
priorInstance
iscloudFormationDeploy.onFailure.DELETE
. - Any prior stacks are left untouched.
- If the stack creation succeeds, but subsequent calls to obtain the stack details fail, then:
- The
postCreationFn
function is not invoked. - The newly created stack is not deleted.
- Any prior stacks are left untouched.
- If the
postCreationFn
calls back with an error due to failure, then:
- The newly created stack is not deleted.
- Any prior stacks are left untouched.
- If the deletion of prior stacks fails, then:
- The newly created stack is not deleted.
- Any prior stacks are left in whatever state the deletion failure leaves them in.