AWS SAM Getting Started in Go

4 Aug 2019 aws golang sam lambda

In this post we’re going to set-up, deploy and, optionally, locally test an API Gateway and Lambda API backend. Using the default AWS SAM Go set-up we’re going to deploy a Lambda that will be invoked by a GET API Gateway request.

Command overview

Below is a quick list of commands we’re going to be running to deploy our backend.

# Creates a bucket for SAM to upload our packaged application to
aws s3 mb s3://{BUCKET_NAME}

# Creates the default SAM set-up for Go
sam init --runtime go

# Builds the application
cd sam-app
make build

# Package and uploads the backend
sam package --output-template packaged.yaml --s3-bucket {BUCKET_NAME}

# Deploys the backend via CloudFormation
sam deploy --template-file packaged.yaml --capabilities CAPABILITY_IAM --stack-name {STACK_NAME}

# Describes the SAM application stack to get us the API Gateway URL
aws cloudformation describe-stacks --stack-name {STACK_NAME} --query "Stacks[].Outputs"

# curl to invoke our lambda
curl https://{REST_API_ID}.execute-api.{REGION}.amazonaws.com/Prod/hello/

Prerequisites

We’re going to assume a few things in this guide

  1. Have an AWS account
  2. AWSCLI and SAMCLI installed
  3. Configured default IAM inside AWSCLI
  4. Installed Docker (optional, if you want to test the endpoint locally)

Step 1 - Make our S3 bucket

SAM requires a S3 bucket to deploy our application, so lets create our bucket. {BUCKET_NAME} should be chagned to your own value.

aws s3 mb s3://{BUCKET_NAME}

Example

tmp wesleystratton$ aws s3 mb s3://wesley-stratton-sam-getting-started-in-go
make_bucket: wesley-stratton-sam-getting-started-in-go

Step 2 - Initialize the Go SAM set-up

We initalize our SAM application by downloading the default AWS set-up from AWS.

sam init --runtime go

Example

tmp wesleystratton$ sam init --runtime go
[+] Initializing project structure...

Project generated: ./sam-app

Steps you can take next within the project folder
===================================================
[*] Install dependencies
[*] Invoke Function: sam local invoke HelloWorldFunction --event event.json
[*] Start API Gateway locally: sam local start-api

Read sam-app/README.md for further instructions

[*] Project initialization is now complete

Step 3 - Build our application

Thankfully the default application comes with a convientent Makefile that gives us a simple command to compile the Go application for Lambda.

cd sam-app
make build

Example

tmp wesleystratton$ cd sam-app/
sam-app wesleystratton$ make build
GOOS=linux GOARCH=amd64 go build -o hello-world/hello-world ./hello-world

Step 4 - Package your application for deployment

To deploy the application we need to package and upload a zip to S3 for SAM/Cloudformation to deploy the Lambda from. Again, we should be using the same {BUCKET_NAME} from Step 1.

sam package --output-template packaged.yaml --s3-bucket {BUCKET_NAME}

Example

sam-app wesleystratton$ sam package --output-template packaged.yaml --s3-bucket wesley-stratton-sam-getting-started-in-go
Uploading to 796bfad99ee70e5c5c3befce4ae3eec0  4926616 / 4926616.0  (100.00%)
Successfully packaged artifacts and wrote output template to file packaged.yaml.
Execute the following command to deploy the packaged template
aws cloudformation deploy --template-file /private/tmp/sam-app/packaged.yaml --stack-name <YOUR STACK NAME>

Step 5 - Deploy to AWS

Now that we’ve compile, packaged and uploaded our application the last step before making everything live is to deploy the application. Choose any {STACK_NAME} for your application. This step can take sometime, so don’t fret if it’s a couple of minutes before anything happens

sam deploy --template-file packaged.yaml --region us-west-2 --capabilities CAPABILITY_IAM --stack-name {STACK_NAME}

Example

sam-app wesleystratton$ sam deploy --template-file packaged.yaml --capabilities CAPABILITY_IAM --stack-name wesley-stratton-sam-getting-started-in-go-stack --profile serverlessUser

Waiting for changeset to be created..
Waiting for stack create/update to complete
Successfully created/updated stack - wesley-stratton-sam-getting-started-in-go-stack

Step 6 - Test in AWS

Yay, we’ve deployed to AWS cloud! Now we can try and hit the API Gateway endpoint directly. First we need to find what our API Gateway endpoint is and then curl that endpoint.

aws cloudformation describe-stacks --stack-name {STACK_NAME} --query "Stacks[].Outputs"
curl https://{REST_API_ID}.execute-api.{REGION}.amazonaws.com/Prod/hello/

Example

sam-app wesleystratton$ aws cloudformation describe-stacks --stack-name wesley-stratton-sam-getting-started-in-go-stack --query "Stacks[].Outputs" --profile serverlessUser
[
    [
        {
            "OutputKey": "HelloWorldFunctionIamRole",
            "OutputValue": "arn:aws:iam::474592883549:role/wesley-stratton-sam-getting-HelloWorldFunctionRole-TEHHHHHM038A",
            "Description": "Implicit IAM Role created for Hello World function"
        },
        {
            "OutputKey": "HelloWorldAPI",
            "OutputValue": "https://iqcjnyu5dd.execute-api.us-east-1.amazonaws.com/Prod/hello/",
            "Description": "API Gateway endpoint URL for Prod environment for First Function"
        },
        {
            "OutputKey": "HelloWorldFunction",
            "OutputValue": "arn:aws:lambda:us-east-1:474592883549:function:wesley-stratton-sam-getting-sta-HelloWorldFunction-ELKSKFD9YRZO",
            "Description": "First Lambda Function ARN"
        }
    ]
]
sam-app wesleystratton$ curl https://iqcjnyu5dd.execute-api.us-east-1.amazonaws.com/Prod/hello/
Hello, 18.212.53.91

Step 7 (Optional) - Test locally with Docker

SAM gives us the option to also test our set-up locally without the need for AWS services. To do this we need Docker installed and running. We run each of these commands in different terminal tabs

sam local start-api
curl http://127.0.0.1:3000/hello

Example SAM local tab

sam-app wesleystratton$ sam local start-api
2019-08-04 22:48:38 Mounting HelloWorldFunction at http://127.0.0.1:3000/hello [GET]
2019-08-04 22:48:38 You can now browse to the above endpoints to invoke your functions. You do not need to restart/reload SAM CLI while working on your functions, changes will be reflected instantly/automatically. You only need to restart SAM CLI if you update your AWS SAM template
2019-08-04 22:48:38  * Running on http://127.0.0.1:3000/ (Press CTRL+C to quit)
2019-08-04 22:48:42 Invoking hello-world (go1.x)
2019-08-04 22:48:42 Found credentials in shared credentials file: ~/.aws/credentials

Fetching lambci/lambda:go1.x Docker container image......
2019-08-04 22:48:44 Mounting /private/tmp/sam-app/hello-world as /var/task:ro,delegated inside runtime container
START RequestId: cd705b0e-1ae2-186f-6efd-d74852c10b29 Version: $LATEST
END RequestId: cd705b0e-1ae2-186f-6efd-d74852c10b29
REPORT RequestId: cd705b0e-1ae2-186f-6efd-d74852c10b29	Duration: 512.33 ms	Billed Duration: 600 ms	Memory Size: 128 MB	Max Memory Used: 11 MB	
2019-08-04 22:48:46 No Content-Type given. Defaulting to 'application/json'.
2019-08-04 22:48:46 127.0.0.1 - - [04/Aug/2019 22:48:46] "GET /hello HTTP/1.1" 200 -

curl tab

tmp wesleystratton$ curl http://127.0.0.1:3000/hello
Hello, 192.168.0.0

Conclusion

There we have it. A quick and simple introduction to setting up a API Gateway/Lambda backend in AWS cloud using AWS SAM and Go.

Clean-up

If you don’t want all of the above hanging around in your AWS account the below commands will help clean things up.

aws cloudformation delete-stack --stack-name {STACK_NAME}
aws s3 rb s3://{BUCKET_NAME} --force