Learning AWS CLIs to Deploy AWS Lambda Functions Using VS Code

Seng Lin Shee
Level Up Coding
Published in
7 min readJun 8, 2020

--

Featured image showing random code on a laptop screen.

TD;DR

  1. This is a guided tutorial on setting up a sample AWS Lambda function and to tear it down quickly and cleanly.
  2. VS Code Development Container is used in this tutorial to demonstrate how it can provide an environment with all the necessary tools on your local machine to start building and deploying AWS services. It can also be reused for other toolchains.

Yet another tutorial?

It’s been a while since I last blogged. Oh boy, are there plenty of avenues to publish anything you so desire. This is my first post on Medium and I would like to share some steps that I have compiled to easily develop and deploy AWS services.

In this post, I am sharing an approach to quickly build and deploy a sample Lambda function using the AWS CLI tools.

In order to make this easier for anyone who doesn’t have any prior background on AWS to start learning and using the tools, I have created a container that has all the necessary tools to make this tutorial work out of the box.

VS Code supports (yes, it’s been released for quite a while now) code development inside a Docker container via the Remote — Containers extension for Visual Studio Code. As someone who has been working on projects that target different platforms and toolsets, I really appreciate that today’s development tools support project-specific environments (I previously achieved this by using Virtual Machines instead). You can imagine my excitement when I heard the news about Github Codespaces. There are alternatives to Github Codespaces, but I do see the lower cost of adoption if the integration is done in Github itself. I really hope that there will be a free option though.

What’s new

The DevContainer Project that I developed contains a few additional capabilities to the ones provided by the Micosoft vscode-dev-containers project, as follows:

  1. Installation of AWS Tools (aws cli, aws sam cli, aws fargate cli, etc.)
  2. Docker in Docker; run a docker engine within a docker container. In this example, the aws sam cli requires the use of Docker.

I have made 2 versions of this DevContainer; one for Java and another for Node:

  1. AWS Practice Project for Java
  2. AWS Practice Project for Node

Let’s Get Started

Before proceeding with this tutorial, please install the following tools on your local machine:

  1. Visual Studio Code
  2. Remote — Containers extension for Visual Studio Code
  3. Docker
  4. Git

Pick one of the above Practice Projects, say let’s choose Java.

$ git clone https://github.com/senglin/practice-aws-java.git

Open the cloned Git repository folder in VS Code.

Click on the quick actions Status Bar item in the lower left corner.

Select Remote-Containers:Reopen in Container. This step will take awhile as Docker images and the required packages will be downloaded and installed.

From the menu, select Terminal -> New Terminal. You can now use the installed tools to clone, develop and deploy to AWS.

For the rest of this tutorial, please use this terminal window from within VS Code.

Verify that you have the necessary CLIs installed.

$ aws --version
aws-cli/2.0.17 Python/3.7.3 Linux/4.19.76-linuxkit
$ sam --version
SAM CLI, version 0.52.0

Verify that the docker engine within the container is working. You should see versions of both the client and server. If you don’t, a good remedy is to click on the quick actions Status Bar item in the lower left corner and select Remote-Containers:Rebuild Container.

$ docker version
Client: Docker Engine - Community
Version: 19.03.9
API version: 1.40
Go version: go1.13.10
Git commit: 9d988398e7
Built: Fri May 15 00:25:25 2020
OS/Arch: linux/amd64
Experimental: false
Server: Docker Engine - Community
Engine:
Version: 19.03.9
API version: 1.40 (minimum version 1.12)
Go version: go1.13.10
Git commit: 9d988398e7
Built: Fri May 15 00:23:57 2020
OS/Arch: linux/amd64
Experimental: false
containerd:
Version: 1.2.13
GitCommit: 7ad184331fa3e55e52b890ea95e65ba581ae3429
runc:
Version: 1.0.0-rc10
GitCommit: dc9208a3303feef5b3839f4323d9beb36df0a9dd
docker-init:
Version: 0.18.0
GitCommit: fec3683

Congrats!

Set up Credentials

Please make sure you have set up an AWS account. You can take advantage of the AWS Free Tier which lasts 12 months.

If you haven’t done so, please set up your AWS credential environments. For information about access key IDs and secret access keys, see Managing Access Keys for IAM Users in the IAM User Guide. Make sure that region name is set (this is for convenience).

$ aws configure
AWS Access Key ID [None]: your_access_key_id
AWS Secret Access Key [None]: your_secret_access_key
Default region name [None]: us-west-2
Default output format [None]:

Download and test a sample Java Lambda app

The next steps follow closely to the ones in AWS SAM Guide.

  1. Download the sample app using the following flow:
$ sam init
Which template source would you like to use?
1 - AWS Quick Start Templates
2 - Custom Template Location
Choice: 1
Which runtime would you like to use?
1 - nodejs12.x
2 - python3.8
3 - ruby2.7
4 - go1.x
5 - java11
6 - dotnetcore3.1
7 - nodejs10.x
8 - python3.7
9 - python3.6
10 - python2.7
11 - ruby2.5
12 - java8
13 - dotnetcore2.1
Runtime: 5
Which dependency manager would you like to use?
1 - maven
2 - gradle
Dependency manager: 1
Project name [sam-app]:Cloning app templates from https://github.com/awslabs/aws-sam-cli-app-templates.gitAWS quick start application templates:
1 - Hello World Example: Maven
2 - EventBridge Hello World: Maven
3 - EventBridge App from scratch (100+ Event Schemas): Maven
4 - Step Functions Sample App (Stock Trader): Maven
Template selection: 1
-----------------------
Generating application:
-----------------------
Name: sam-app
Runtime: java11
Dependency Manager: maven
Application Template: hello-world
Output Directory: .
Next steps can be found in the README file at ./sam-app/README.md$

2. Change into the newly create a directory and build the project.

$ cd sam-app/
$ sam build
Building function 'HelloWorldFunction'
Running JavaMavenWorkflow:CopySource
Running JavaMavenWorkflow:MavenBuild
Running JavaMavenWorkflow:MavenCopyDependency
Running JavaMavenWorkflow:MavenCopyArtifacts
Build SucceededBuilt 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
$

3. With the current environment, you may execute the following function to test the lambda function locally.

$ sam local invoke
Invoking helloworld.App::handleRequest (java11)
Fetching lambci/lambda:java11 Docker container image....................................................................................................................................................................................................................................................
Mounting /workspaces/practice-aws-java/sam-app/.aws-sam/build/HelloWorldFunction as /var/task:ro,delegated inside runtime container
START RequestId: aba29d4d-6554-1ca6-ebc0-16d26831ec6a Version: $LATEST
END RequestId: aba29d4d-6554-1ca6-ebc0-16d26831ec6a
REPORT RequestId: aba29d4d-6554-1ca6-ebc0-16d26831ec6a Init Duration: 265.90 ms Duration: 1159.41 ms Billed Duration: 1200 ms Memory Size: 512 MB Max Memory Used: 90 MB
{"body":"{ \"message\": \"hello world\", \"location\": \"<redacted>\" }","headers":{"X-Custom-Header":"application/json","Content-Type":"application/json"},"statusCode":200}$

This command invokes the HelloWorldFunction defined in template.yml using the default event events\event.json.

4. You may deploy the function locally too:

$ sam local start-api
Mounting HelloWorldFunction at http://127.0.0.1:3000/hello [GET]
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
2020-06-07 09:16:18 * Running on http://127.0.0.1:3000/ (Press CTRL+C to quit)

5. This starts a running process. From the menu, select Terminal -> New Terminal and make the following curl request.

$ curl http://127.0.0.1:3000/hello
{ "message": "hello world", "location": "<redacted>" }

6. You may close the service by using Ctrl-C in the previous terminal window.

Deployment

Now you have the chance to deploy to AWS. The deployment architecture is the following:

Figure showing 2 cloud formation stacks. 1 for the sam-app and 1 for the aws-sam-cli.
AWS SAM CLI provisions it’s own database for its own use and creates new cloud formation instances for each new deployment.

Run the following command, followed by answering the prompts. Ensure that you choose the same region as the ones you have providedright at the beginning of this tutorial.

$ sam deploy --guidedConfiguring SAM deploy
======================
Looking for samconfig.toml : Not foundSetting default arguments for 'sam deploy'
=========================================
Stack Name [sam-app]:
AWS Region [us-east-1]: us-west-2
#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]:
HelloWorldFunction may not have authorization defined, Is this okay? [y/N]: y
Save arguments to samconfig.toml [Y/n]:

The flow will end with an output similar to the following:

CloudFormation outputs from deployed stack
--------------------------------------------------------------------
Outputs
--------------------------------------------------------------------
Key HelloWorldFunctionIamRole
Description Implicit IAM Role created for Hello World function
Value arn:aws:iam:redacted
Key HelloWorldApi
Description API Gateway endpoint URL for Prod stage for Hello World function
Value https://<redacted>.execute-api.us-west-2.amazonaws.com/Prod/hello/
Key HelloWorldFunction
Description Hello World Lambda Function ARN
Value arn:aws:lambda:redacted
--------------------------------------------------------------------
Successfully created/updated stack - sam-app in us-west-2

Once this flow is complete, you can run the following request (find your relevant url from the output above):

$ curl https://<redacted>.execute-api.us-west-2.amazonaws.com/Prod/hello/

Clean Up

You should delete the deployment after you are done experimenting with it, so that you don’t incur cost / use up your free quota.

$ aws cloudformation delete-stack --stack-name sam-app

The above only deletes the Lambda function. However, AWS SAM CLI stores information regarding the build/deployment in a separate S3 bucket. You can see that S3 bucket in your list:

$ aws s3 ls
2020-06-07 19:00:04 aws-sam-cli-managed-default-samclisourcebucket-<redacted>

If you would like to completely remove that, please continue with the following.

I found a useful script that automates the emptying of S3 buckets that have versioning enabled (there are a few scripts out there, but I just chose one — thank you to the community!)

$ aws-s3-empty-bucket.sh --bucket $(aws cloudformation describe-stacks --stack-name aws-sam-cli-managed-default | jq -r '.Stacks[0].Outputs[] | select(.OutputKey=="SourceBucket") | .OutputValue')
$ aws s3 rb s3://$(aws cloudformation describe-stacks --stack-name aws-sam-cli-managed-default | jq -r '.Stacks[0].Outputs[] | select(.OutputKey=="SourceBucket") | .OutputValue')
$ aws cloudformation delete-stack --stack-name aws-sam-cli-managed-default

The aws-sam-cli-managed-default-samclisourcebucket bucket should now have been removed completely.

Summary

By the end of this tutorial, you would have deployed and tested an endpoint implemented using a Lambda function, as well as being familiarized with the basic commands of the AWS CLI.

Do let me know if you have any issues following the tutorial. My intention is to introduce a framework (devcontainer project) that speeds up the environment creation with the necessary tools for deploying your projects to AWS using the VSCode Remote Container feature.

Next, what’s after Lambda functions? Fargate containerized services! Read on to Develop Code & Deploy to AWS Fargate Using Visual Studio Code

--

--

Love understanding how different pieces can make something beautiful. Still comprehending that building software is part engineering, art and social science.