AWS CloudFormation Serverless Recipes

AWS CloudFormation had a steep learning curve for me. I lacked recipe-based learning. So I thought I will start collecting recipes that I use frequently. I'll keep this post updated.

Defining Resources Conditionally Based on Environment

Here's an example that defines input for a scheduled Lambda event based on environment, using Conditions and Condition Functions.

Two important things:

  • During a stack update, you can't update conditions by themselves. You can update conditions only when you include changes that add, modify, or delete resources.
  • Where to put conditions: see How to use conditions overview
AWSTemplateFormatVersion: '2010-09-09'  
Transform: AWS::Serverless-2016-10-31

Parameters:  
  Environment:  
    Type: String  
    AllowedValues: 
      - acc  
      - prod

Conditions: # <-- define conditions here 
  IsProd: !Equals  
    - !Ref Environment  
    - prod
	
Resources:  
  Main:  
    Type: AWS::Serverless::Function  
	Events:  
	  PeriodicTrigger:  
		Type: Schedule  
		Properties:  
		  Schedule: rate(5 minutes)  
		  Input: !If [ IsProd, '"foo"', '"bar"' ]  #  🎉
	# ... CodeUri, etc...	  

Linter for CloudFormation templates

cfn-lint. There are IDE plugins as well. cfn-lint works well, speeding up the feedback loop. It could be setup as a git precommit hook.

Parameterize AWS Lambda with SSM Param Store

Here's a recipe that adds Slack channel and webhook url from SSM Parameter Store to AWS Lambda:

# cloudformation template
AWSTemplateFormatVersion: '2010-09-09'  
Transform: AWS::Serverless-2016-10-31

Parameters:
	SlackWebhookUrl:  
	  Type: AWS::SSM::Parameter::Value<String>  
	  Default: '/services/Slack/incomingWebhookUrl'  

	SlackChannel:  
	  Type: AWS::SSM::Parameter::Value<String>  
	  Default: '/services/Slack/channels/exampleChannel'
	  
Resources:  
  ExampleLambda:  
    Type: AWS::Serverless::Function  
    Properties:  
      Environment:  
        Variables:  
          SLACK_WEBHOOK_URL: !Ref SlackWebhookUrl  
          SLACK_CHANNEL: !Ref SlackChannel	  
	# ... CodeUri, etc...

in Lambda, read from env vars:

// in the Lambda handler (Typescript example)
const slack = Slack({  
	url: process.env.SLACK_WEBHOOK_URL,  
	channel: process.env.SLACK_CHANNEL,  
})

For local develoment and sam local invoke, use env-vars option or supply env vars to Lambda via bash:

# content of dev-env.sh
# better not in version control, because it contains secrets
export SLACK_CHANNEL=slack-integration-test  
export SLACK_WEBHOOK_URL=<your-slack-url>

followed by:

$ source dev-env.sh && sam local invoke Main #...remaining sam args

Integrating AWS Lambda with Sentry

See a dedicated post: Tracking AWS Lambda errors with Sentry (and CloudFormation)


Would you like to connect? Subscribe via email or RSS , or follow me on Twitter!