The AWS Serverless Application Model: A One-Stop-Shop for your serverless apps
It won’t surprise you when I say that the cloud train has left the station a while ago and is gaining more and more speed every day.
Because this trend doesn’t seem to stop it is important to be able to act fast on your changing environment to meet your customers demand with the least effort and time involved. The most obvious way to achieve this is to be as cloud native as possible. This means that you have to aim to use the building blocks that your cloud provider provides. One of these building blocks the Amazon AWS cloud offers, is the Serverless Application Model.
In this blogpost I will explain and demonstrate the basics this framework has to offer.
What is the Serverless Application Model?
The AWS Serverless application model is a framework that can be used to build serverless applications. This framework consist of 2 components:
- The AWS SAM template specification
This specification is used to define your serverless application. It provides a clean and simple syntax to describe all necessary components to make your serverless application. The AWS SAM template specification is related and shares syntax with AWS Cloudformation.
- The AWS SAM command line interface
The AWS SAM CLI can be used to build serverless applications that you define using the template specification. It also enables you to verify the templates written and invoke lambda functions locally. The CLI can also be used to package and deploy serverless applications to the AWS cloud.
Why should you use AWS SAM?
Using AWS SAM provides a lot of benefits regarding the development of serverless applications on the AWS cloud:
- Single-deployment configuration. All required components are defined in one template.
- Extension of AWS Cloudformation. AWS SAM is an extension of AWS Cloudformation which brings us these reliable deployment capabilities for free.
- Built-in best practices. AWS SAM can be used to deploy your required infrastructure components as configuration. This enables you to check-in your template definition into your VCS and apply software development best practises like code reviews and such.
- Local debugging and testing: The AWS SAM makes it possible to locally build , test and debug your serverless applications your have defined in your SAM template. With the help of Docker it is also possible to locally test your application against other infrastructure components like DynamoDB.
- Deep integration with development tools. The AWS SAM makes it fairly simple to setup a Code deploy pipeline to build and deploy your serverless application on every vcs change.
A Simple yet complete REST-API
To demonstrate the capabilities of the SAM, we are going to create a REST-API that exposes CRUD actions on a DynamoDB. This app will cover most of the basic functionalities the Serverless Application Model provides
The high-level services that are part of AWS SAM are:
- Lambdas
- API Gateway
- DynamoDB Tables
For more servies you can add other resources as specified in the Cloudformation specification.
Lambdas
Lambdas are the one of the most pure serverless component: It empowers a developer to be able to focus on writing the business logic only without the need to worry about boilerplate and infrastructure. Just upload your code/ binary to s3 and configure the lambda with the required instructions regarding environment variables and/ or credentials and you are good to go. The best part is that you only have to pay for the time your lambda is actually doing work! Our app will consist of several lambdas which will ensure the correct data is stored and retrieved from storage.
API Gateway
In order to access the business logic that we put in our lambdas that cover the app functionality, we need to have a way to interact with this functionality from the internet. The most obvious way to do that is by deploying an API Gateway. An API Gateway can be configured to invoke various services available within the AWS landscape, like for example Lambdas. It supports various authentication mechanisms, out-of-the-box request logging and more advanced features like request throttling. The API Gateway can do some transformations before forwarding the request to the service of destination too. This feature can be very powerful. For example: when your lambdas evolve faster than your api users can keep up with, you can use transformations to convert the incoming request to the datamodel the lambda expects. Or vice versa: transform the response of your lambda to match the model of the defined api contract.
Persistence
The AWS SAM framework has support for DynamoDB which is profiled as a serverless document database solution ‘for any scale’TM. Since our requirements are not that fancy, DynamoDB will fit our requirements just fine: we only have to store our entries somehow and we need to be able to fetch them by specific criteria and be able to update an entry.
Putting it all together
We will create/ deploy the following resources using the Serverless Application Model:
- A few Lambda Functions
- An API Gateway
- A DynamoDB table
I’ve already created an application to illustrate the capabilities of the Serverless Application Model framework and it is available on GitHub. This application consists of 3 Lambdas that use DynamoDB to retrieve, store and update entries.
The Template
Now the Serverless application model magic happens. The template is the key component in this framework and will make sure AWS will create the desired resources in the cloud. Lets highlight some parts of the template than can be found in the before mentioned GitHub repository
An excerpt of the template.yml file
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: >
This template describes the resources to be deployed for the Todo app
Globals:
Function:
Timeout: 3
Resources:
ListTodosFunction:
Type: AWS::Serverless::Function
Properties:
CodeUri: functions/list-todos
Handler: list-todos.lambdaHandler
Runtime: nodejs12.x
Policies:
- DynamoDBCrudPolicy:
TableName: !Select [1, !Split ['/', !GetAtt DynamoTodosTable.Arn]]
Environment:
Variables:
TABLE_NAME: !Select [1, !Split ['/', !GetAtt DynamoTodosTable.Arn]]
Events:
ListTodos:
Type: Api
Properties:
Path: /list
Method: get
Most of this template.yml
looks quite similar to a Cloudformation template, and in a SAM-template the Resources
section is the most important/ interesting part too.
Lambdas
We see that there is a function definition of type AWS::Serverless::Function
that points to function code. Besides the type
this is similar to a Lambda definition in a Cloudformation template. However, this function definition also defines an event of type Api
which is an additional property the SAM framework provides.
When an event is defined of type Api
, the Serverless Application Model will deploy an API gateway for you! As can be seen in the template.yml
, there is also a Path
defined. The framework will automatically configure the API Gateway to route all HTTP GET
requests for /list
to the Lambda function this event is defined for!
To find out what all available options for functions are, please refer to the resource specification.
DynamoDB
As mentioned earlier, the Lambda functions require a DynamoDB table to store, update and retrieve entries. As you can see the template also contains a resource definition with name DynamoTodosTable
and type AWS::Serverless::SimpleTable
. This is the most simple way to define a DynamoDB table requiring minimal configuration:
DynamoTodosTable:
Type: AWS::Serverless::SimpleTable # if you want to define a more complex table, use AWS::DynamoDB::Table
TableName: !Ref TableName
PrimaryKey:
Name: todo-id
Type: String
BillingMode: PROVISIONED
ProvisionedThroughput:
ReadCapacityUnit: 1
WriteCapacityUnits: 1
Tags:
AppType: Serverless
The DynamoDB simple table definition can be configured via various parameters, like providing a meaningful table name, setting the number of provisioned read and write units and what the primary key look like.
Deployment
To deploy the application, we have to first build the application. Assuming you have installed the SAM CLI (if not, follow the instructions here), execute the sam build
command:
$ sam build
Building resource 'ListTodosFunction'
Running NodejsNpmBuilder:NpmPack
Running NodejsNpmBuilder:CopyNpmrc
Running NodejsNpmBuilder:CopySource
Running NodejsNpmBuilder:NpmInstall
Running NodejsNpmBuilder:CleanUpNpmrc
Building resource 'UpdateTodoFunction'
Running NodejsNpmBuilder:NpmPack
Running NodejsNpmBuilder:CopyNpmrc
Running NodejsNpmBuilder:CopySource
Running NodejsNpmBuilder:NpmInstall
Running NodejsNpmBuilder:CleanUpNpmrc
Building resource 'CreateTodoFunction'
Running NodejsNpmBuilder:NpmPack
Running NodejsNpmBuilder:CopyNpmrc
Running NodejsNpmBuilder:CopySource
Running NodejsNpmBuilder:NpmInstall
Running NodejsNpmBuilder:CleanUpNpmrc
Build Succeeded
Built Artifacts : .aws-sam/build
Built Template : .aws-sam/build/template.yaml
Commands you can use next
=========================
[*] Invoke Function: sam local invoke
[*] Deploy: sam deploy --guided
$
This command creates an application that is ready to be deployed by Cloudformation. You can review the result of this action in the folder .aws-sam/build
.
Now it is time to deploy the application to the AWS Cloud. To do so, execute the sam deploy --guided
command in a terminal window. The --guided
flag will cause the SAM CLI to prompt with some questions. Luckily, the answers can be saved for future use in a samconfig.toml
file and will be picked up by the SAM CLI automatically for future executions.
% sam deploy --guided
Configuring SAM deploy
======================
Looking for samconfig.toml : Not Found
Reading default arguments : Success
Setting default arguments for 'sam deploy'
=========================================
Stack Name [todos-app]: todos-app
AWS Region [eu-west-1]: eu-west-1
Parameter TableName [my-todos]: my-todos
#Shows you resources changes to be deployed and require a 'Y' to initiate deploy
Confirm changes before deploy [y/N]: y
#SAM needs permission to be able to create roles to connect to the resources in your template
Allow SAM CLI IAM role creation [Y/n]: Y
Save arguments to samconfig.toml [Y/n]: Y
Looking for resources needed for deployment: Found!
Initiating deployment
=====================
Waiting for changeset to be created..
CloudFormation stack changeset
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Operation LogicalResourceId ResourceType
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
* Modify CreateTodoFunction AWS::Lambda::Function
* Modify ListTodosFunction AWS::Lambda::Function
* Modify ServerlessRestApi AWS::ApiGateway::RestApi
* Modify UpdateTodoFunction AWS::Lambda::Function
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Changeset created successfully. arn:aws:cloudformation:eu-west-1:*********:changeSet/samcli-deploy15******/338abafc-adb7-489f-b677-1f87c4d6ab31
Previewing CloudFormation changeset before deployment
======================================================
Deploy this changeset? [y/N]:
The procedure will pause when it is ready for deployment, and wants you to confirm the deployment. It is possible to enable auto confirmation in the samconfig.toml
file.
Deploy this changeset? [y/N]: y
CloudFormation events from changeset
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
ResourceStatus ResourceType LogicalResourceId ResourceStatusReason
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
UPDATE_IN_PROGRESS AWS::Lambda::Function ListTodosFunction -
UPDATE_IN_PROGRESS AWS::Lambda::Function UpdateTodoFunction -
UPDATE_IN_PROGRESS AWS::Lambda::Function CreateTodoFunction -
UPDATE_COMPLETE AWS::Lambda::Function UpdateTodoFunction -
UPDATE_COMPLETE AWS::Lambda::Function CreateTodoFunction -
UPDATE_COMPLETE AWS::Lambda::Function ListTodosFunction -
UPDATE_COMPLETE_CLEANUP_IN_PROGRESS AWS::CloudFormation::Stack todos-app -
UPDATE_COMPLETE AWS::CloudFormation::Stack todos-app -
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
CloudFormation outputs from deployed stack
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Outputs
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Key TodoApi
Description API Gateway endpoint URL for Prod stage for the todos functions
Value https://8wthljigzd.execute-api.eu-west-1.amazonaws.com/Prod/
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Successfully created/updated stack - todos-app in eu-west-1
As you can see the url where we can find our deployed endpoints is printed in the console.
Validating our deployment
Let’s store a todo by executing a HTTP POST
request using curl
:
$ curl -i --location --request POST 'https://8wthljigzd.execute-api.eu-west-1.amazonaws.com/Prod/' \ --header 'Content-Type: application/json' \ --data-raw '{ "activity": "Write a Blog about AWS SAM", "done": false }'
HTTP/2 201
x-created-item-id: fZbbSVdm-
Lets use curl again to issue an update on the created todo, where we use the identifier as path variable:
$ curl -i --location --request PUT 'https://8wthljigzd.execute-api.eu-west-1.amazonaws.com/Prod/update/fZbbSVdm-' \ --header 'Content-Type: application/json' \ --data-raw '{"activity": "Write a Blog about AWS SAM","done": true}'
HTTP/2 204
Now, to check if the todo is updated, let’s list all the todo’s we have in our database:
$ curl -i https://8wthljigzd.execute-api.eu-west-1.amazonaws.com/Prod/list
HTTP/2 200
[{"id":"fZbbSVdm-","activity":"Write a Blog about AWS SAM","done":true}]
As we can see the list
endpoint returns exactly what we expected to see: An updated todo item!
Want to know more about what we do?
We are your dedicated partner. Reach out to us.