- A Go AWS SDK example - Fri, Nov 11 2022
- Getting started with Jenkins - Tue, Aug 16 2022
- Pulumi vs. Terraform - Tue, Jul 5 2022
Why the AWS Serverless Application Model?
The AWS Serverless Application Model integrates with many other AWS resources to make building your Serverless application easier. Using AWS Cloud 9, which we will do, allows you to have a fully functioning IDE with the AWS SAM CLI and AWS CLI (among others) preinstalled. Using CodeBuild, CodeDeploy, and CodePipeline provides a mechanism to build a safe deployment pipeline.
AWS SAM is an extension of AWS CloudFormation and is Python based. We can define additional resources using CloudFormation inside our SAM template. In fact, anything available to use in CloudFormation, such as templates and intrinsic functions, is available in SAM. One other area to note is local debugging and testing. There are toolkits available for many popular IDEs, such as VSCode, which help to make debugging, testing, and deploying easier.
Using Cloud 9 to use AWS SAM
Instead of just talking about AWS SAM, let's dive in and start to understand what we are working with. I'm going to use Cloud 9 in this demo so that we will have a fully working environment, as opposed to downloading and installing the software locally.
Cloud 9 from AWS is an IDE for writing, running, and debugging code built on an underlying EC2 instance. If this is not something you have done before, check out the getting started guide by AWS.
Our project for this demo will look at AWS SAM's Hello World template. The Hello World application has a basic API backend that uses the Amazon API Gateway and a Lambda function. We can then send a GET request to the API gateway to invoke our lambda, which will return a message and our IP address.
There is a lot to take in and look at, so this will be a good place to start.
From your IDE, type sam init. This initializes a serverless application with an AWS SAM template:
You can pass arguments to the sam init command to skip some or all of the menu options. Take a look here to see some examples.
AWS SAM prompts you to provide the following information:
The source template for this demo will be AWS Quick Start Templates, so select Option 1. Next, we are asked how we want to package our app, either a zip file or an image uploaded to Amazon Elastic Container Registry service, also known as ECR. Select the zip package option. A list of runtimes that are available to use for our Lambda is displayed. I will choose Go. After choosing our runtime, we must add a project name.
Lastly, select the Hello World Example to complete the setup.
Once the project has been initialized, the folder structure will look as follows:
The key areas are the folder named after our application (hello-world), which contains the main code, and the template.yaml, which defines our application's AWS resources.
The code
The main.go file generated by our SAM project contains the following:
package main import ( "errors" "fmt" "io/ioutil" "net/http" "github.com/aws/aws-lambda-go/events" "github.com/aws/aws-lambda-go/lambda" ) var ( // DefaultHTTPGetAddress Default Address DefaultHTTPGetAddress = "https://checkip.amazonaws.com" // ErrNoIP No IP found in response ErrNoIP = errors.New("No IP in HTTP response") // ErrNon200Response non 200 status code in response ErrNon200Response = errors.New("Non 200 Response found") ) func handler(request events.APIGatewayProxyRequest) (events.APIGatewayProxyResponse, error) { resp, err := http.Get(DefaultHTTPGetAddress) if err != nil { return events.APIGatewayProxyResponse{}, err } if resp.StatusCode != 200 { return events.APIGatewayProxyResponse{}, ErrNon200Response } ip, err := ioutil.ReadAll(resp.Body) if err != nil { return events.APIGatewayProxyResponse{}, err } if len(ip) == 0 { return events.APIGatewayProxyResponse{}, ErrNoIP } return events.APIGatewayProxyResponse{ Body: fmt.Sprintf("Hello, %v", string(ip)), StatusCode: 200, }, nil } func main() { lambda.Start(handler) }
The code example contains a simple handler function that will return a message of hello along with your IP address if successful. There are some error checks in the form of if statements to handle an unsuccessful return.
Template.yaml
Looking at template.yaml, you could mistakenly think it just looks like a typical CloudFormation template, and you would be right. The AWS SAM template closely follows the CloudFormation template but with a few differences. Below is the template for our project:
AWSTemplateFormatVersion: '2010-09-09' Transform: AWS::Serverless-2016-10-31 Description: > hello-sam Sample SAM Template for hello-sam # More info about Globals: https://github.com/awslabs/serverless-application-model/blob/master/docs/globals.rst Globals: Function: Timeout: 5 Resources: HelloWorldFunction: Type: AWS::Serverless::Function # More info about Function Resource: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessfunction Properties: CodeUri: hello-world/ Handler: hello-world Runtime: go1.x Architectures: - x86_64 Tracing: Active # https://docs.aws.amazon.com/lambda/latest/dg/lambda-x-ray.html Events: CatchAll: Type: Api # More info about API Event Source: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#api Properties: Path: /hello Method: GET Environment: # More info about Env Vars: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#environment-object Variables: PARAM1: VALUE Outputs: # ServerlessRestApi is an implicit API created out of Events key under Serverless::Function # Find out more about other implicit resources you can reference within SAM # https://github.com/awslabs/serverless-application-model/blob/master/docs/internals/generated_resources.rst#api HelloWorldAPI: Description: "API Gateway endpoint URL for Prod environment for First Function" Value: !Sub "https://${ServerlessRestApi}.execute-api.${AWS::Region}.amazonaws.com/Prod/hello/" HelloWorldFunction: Description: "First Lambda Function ARN" Value: !GetAtt HelloWorldFunction.Arn HelloWorldFunctionIamRole: Description: "Implicit IAM Role created for Hello World function" Value: !GetAtt HelloWorldFunctionRole.Arn
The first thing to notice is the declaration transform, Transform: AWS::Serverless-2016-10-31, which identifies the CloudFormation template as an AWS SAM template.
The AWS SAM template has a Globals section that is not available with a CloudFormation template. This is where we add properties that are common to Serverless and APIs. We can define properties in the Globals section that we will use in the Resources section.
The Resource section can contain resources from CloudFormation as well as SAM. Sam has five special resources in AWS SAM Template properties:
- AWS::Serverless::Function
- AWS::Serverless::Api
- AWS::Serverless::SimpleTable
- AWS::Serverless::LayerVersion
- AWS::Serverless::Application
SAM also has a Parameter section. The SAM cli has a sam deploy --guided command to prompt the user for any additional information. We can define objects in the Parameter section to prompt the user for this extra information.
Building the application
To test our Serverless application or deploy it, we need to build it. To build our application, we can call the sam build command. The SAM build command will process our template.yaml, application code, and any dependencies.
When you run the sam build command, you will see output similar to the screenshot below, depending on your runtime:
Once the build has been completed, the source code can be found in the .aws-sam sub-directory.
Testing your application
We can test our application before deploying it into AWS. AWS SAM provides us with a command, sam local, that will run our application using Docker containers. The containers used simulate the execution of AWS Lambda. You will need to have Docker installed on your machine, or if, like me, you are using AWS Cloud 9, you will have Docker available out of the box.
From the Hello-sam project folder, type the following command:
Sam local invoke
Again, output similar to that shown below will be displayed:
Notice the last line to be displayed to the terminal. We have a StatusCode of 200 and a message at the end saying hello along with an IP address. This confirms that our Lambda application is working as expected.
We are now ready to deploy!
Deploying the application to AWS
We've confirmed our application is working and is now ready to deploy. Using the SAM CLI, we can run sam deploy –guided. SAM will prompt for arguments to deploy our application. The screenshot below shows what information is required.
Once SAM has the required information, it will start to create an IAM role and move the zipped application to S3.
The deployment on screen will first show what the CloudFormation template will be building:
The deployment will then carry on and start to build out your Lambda application, providing the steps and the status to the screen. If you have worked with CloudFormation, then this screen will look very familiar to you.
The SAM template, being CloudFormation, can be viewed from the console:
It is always interesting to view the Template tab. Switching the toggle to view processed template shows how much AWS SAM has done for us. Our SAM template file has doubled in size, from 44 lines of code to 98!
In addition to being able to see our build template in AWS CloudFormation, we can also view our Lambda application on the AWS Lambda console page.
Using the API endpoint URL from either the output screen of our SAM deployment or from the configuration section in the Lambda function inside the console, we can use the application inside the browser:
Summary
This article's intention was to provide you with a good foundation for getting up and running with AWS SAM. SAM allows you to focus on Lambda code and make building out other resources, such as API gateway, easier. You only have to write a few lines; SAM will then transform and expand the syntax into CloudFormation, building out your application faster. Having the ability to test applications through a Docker container is convenient and helpful.
There is a lot more to the AWS Serverless Application Model, which is worth exploring. I would recommend the AWS Serverless Application Repository, where you can discover and deploy ready-made apps and code samples.