Serverless Framework released 1.4.11 few days ago, which adds additional Capability when Transform is detected, it means we can now use AWS CloudFormation Macros to Perform Custom Processing from Serverless Framework.

In this post, I show an example of using CloudFormation custom resources and macros to add default article to sample application after each deployment.

CloudFormation macros and Custom resources

CloudFormation macros are like pre-processors of your CloudFormation templates. After you submit your CloudFormation template, macros are called to transform portions of your template before CloudFormation actually starts provisioning resources. Custom resources greatly expand what you can do with CloudFormation as you can run custom logic as part of your CloudFormation deployment.

Use case

I run my CloudFormation template that setups up An DynamoDb table and lambda functions. CloudFormation template then adds default welcome article to empty DynamoDb table after each deployment.

Prerequisites

The following must be done before following this guide:

Setup an AWS account

Install the AWS CLI

Configure the AWS CLI with user credentials

Install or update the Serverless framework (≥1.4.11) to latest version

$ npm install -g serverless

CloudFormation custom resources

Let’s see how to use custom resources, to use a CloudFormation custom resource, you’ll need:

Define custom resource.

Make custom resource logic available by deploying to an AWS Lambda function.

References Lambda function to use the custom resource in your yml template.

Here’s an example of a custom resource and lambda function:

As shown above, You must provide a ServiceToken property. The ServiceToken is an ARN of either an AWS Lambda function.

Problem

If we deploy above template, The Custom Resource are invoked on first deployment. it won’t trigger again. To fix this issue, We have to add a property with dynamic value to the custom resource.

In my example, I use CloudFormation macro which get stack’s last updated date time, and then injects the date time value into the custom resource’s property.

Setup CloudFormation Macro

Create a new Serverless framework project and add following config to serverless.yml

Note the new Cloudformation resource AWS::Cloudformation::Macro , which makes the Lambda function accessible from other CloudFormation templates.

Add Lambda function

Now, let’s update our handler.js, create lambda function to get CloudFormation stack’s LastUpdatedTime:

For above macro, we want to use stack name from provided CloudFormation Parameters in our CloudFormation template. The parameters will be provided on our Lambda event object under the Parameters key, and our CloudFormation template will be available in the fragment key.

Deploy CloudFormation Macro

The macro can be deployed like this:

$ sls deploy

Usage

The newly created macro can now be used, back to serverless.yml template of custom resource, add StackLastUpdatedTime Property to use our newly generated macro, forcing custom resource to recreate on each deployment using a unique parameter StackLastUpdatedTime:

Next, let’s create a lambda function that is triggered on each deployment and adds welcome article to DynamoDB table if it is empty.

Note that when the custom resource create request is successful, a response must be sent to the S3 bucket is similar to the following format:

{

StackId:

"arn:aws:cloudformation:ap-southeast-2:687416365397:stack/CustomResourceCMSDefaultPost-dev/67c30500-6741-11e9-9b67-0a8814e42c77",

RequestId: "5270edad-8d64-453a-8683-da2db12f7381",

Status: "SUCCESS",

PhysicalResourceId: "2019/04/25/[$LATEST]8c7b0002a0ba45c29ea6685b99e28977",

LogicalResourceId: "DefaultPost",

Data: {

LastUpdatedTime: "2019-04-25T12:07:16.747Z"

}

};

Deploy the service and Try it out!

$ sls deploy

Now run following commend to check whether default article has been added to DynamoDb table.

$ aws dynamodb scan --table-name devposts

Result

I hope you have found this article useful, You can find complete project in my GitHub repo.