Create a Lambda Function with AWS CLI - Complete Guide

avatar
Borislav Hadzhiev

Last updated: Feb 26, 2024
12 min

banner

# Table of Contents

  1. Creating the Role of the Lambda Function
  2. Creating the Lambda Function with AWS CLI
  3. Invoking a Lambda Function with AWS CLI
  4. Updating a Lambda Function with AWS CLI
  5. Updating a Lambda Function's Configuration with AWS CLI
  6. Creating Lambda layers with AWS CLI
  7. Create Lambda Environment Variables with AWS CLI

# Creating the Role of the Lambda Function

We will create and manage a Node.js Lambda function using the AWS CLI.

The second section creates Lambda Layers using the AWS CLI.

Every Lambda function requires an execution role. This is the role the function assumes before it runs.

Let's start by creating the trust policy for the role. In this case, the trust policy allows the Lambda service to assume the role.

Save the contents of the trust policy in a file named trust-policy.json:

trust-policy.json
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "Service": "lambda.amazonaws.com" }, "Action": "sts:AssumeRole" } ] }

Now open your terminal in the directory where trust-policy.json is stored and pass it to the create-role command:

shell
aws iam create-role --role-name lambda-example-role --assume-role-policy-document file://trust-policy.json

create lambda role

Copy and paste the role ARN into a notepad because we'll need it when creating the Lambda function.

The next step is to attach a policy to the role. This policy grants permissions to the Lambda function to log to CloudWatch.

shell
aws iam attach-role-policy --role-name lambda-example-role --policy-arn arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole

attach policy to role

# Creating the Lambda Function with AWS CLI

With the IAM role of the function created, let's create the index.js file which stores the code for our function:

index.js
exports.handler = async event => { const response = { statusCode: 200, body: JSON.stringify({ greeting: `Hello ${event.name}`, double: event.number * 2, department: process.env.DEPARTMENT, }), }; return response; };

The function expects that we provide the name and number parameters on the event object and set the DEPARTMENT environment variable.

The next step is to zip the code for the function:

shell
zip -r9 lambda.zip index.js

zip lambda

Since our Lambda function requires an environment variable called DEPARTMENT, create a file called environment.json, next to your index.js file, with the following JSON in it:

environment.json
{ "Variables": { "DEPARTMENT": "accounting" } }

Now we're ready to create the Lambda function using the AWS CLI.

Open your terminal in the directory where the lambda.zip file is stored and run the create-function command:

shell
aws lambda create-function --function-name lambda-example --runtime nodejs14.x --zip-file fileb://lambda.zip --handler index.handler --environment file://environment.json --role "arn:aws:iam::YOUR_ACCOUNT_NUMBER:role/lambda-example-role"

create lambda function

Anytime you pass a local file to an AWS CLI --parameter, you must prefix the file with file:// for human-readable files or fileb:// for binary (non human-readable) files.

In our case, we have prefixed the lambda.zip file with fileb:// because it's binary, non-human-readable and the environment.json file with file://, because it's human-readable.

# Invoking a Lambda Function with AWS CLI

Before we invoke the function, we have to store the event properties that the function expects into a file. Our Lambda function expects a name and a number property on the event object.

Create a file named event.json with the following JSON in it:

event.json
{ "name": "John Doe", "number": 42 }

Open your terminal in the directory where even.json is stored and run the invoke command:

shell
aws lambda invoke --function-name lambda-example --cli-binary-format raw-in-base64-out --payload file://event.json response.json

The invoke command takes the following parameters:

NameDescription
function-namethe name of the lambda function
cli-binary-formatby default, AWS CLI v2 takes base64 input, but we're passing a raw JSON string
payloadthe event, the function gets invoked with
response.jsona random name for a file where the function response should be stored

invoke lambda function aws cli

The contents of the response.json file show that the Lambda function responds as expected.

# Updating a Lambda Function with AWS CLI

Open your index.js file and update the function's code to the following.

index.js
exports.handler = async event => { const response = { statusCode: 200, body: JSON.stringify({ greeting: `Howdy ${event.name} 👋`, triple: event.number * 3, department: process.env.DEPARTMENT, }), }; return response; };

Now open your terminal in the directory where the index.js file is located and zip its contents.

shell
zip -r9 lambda.zip index.js

zip lambda

To update a Lambda function's code using the AWS CLI, run the update-function-code command:

shell
aws lambda update-function-code --function-name lambda-example --zip-file fileb://lambda.zip

update lambda function aws cli

Now that the function's code has been updated, let's run the invoke command again and look at the function's response:

shell
aws lambda invoke --function-name lambda-example --cli-binary-format raw-in-base64-out --payload file://event.json response.json

invoke updated lambda

The response shows that the function's code has been updated successfully.

# Updating a Lambda Function's Configuration with AWS CLI

Let's update the function to have 1024 MB of RAM (128 is the default) and set its timeout to 5 seconds (3 is the default).

To update the function's memory and timeout with the AWS CLI, run the update-function-configuration command.

shell
aws lambda update-function-configuration --function-name lambda-example --timeout 5 --memory-size 1024

update function configuration

Next, let's add environment variables to the function, using the AWS CLI.

Update the contents of the environment.json file to look as follows:

environment.json
{ "Variables": { "COLOR": "green", "FRUIT": "avocado" } }

To update a function's environment variables, we again use the update-function-configuration command:

shell
aws lambda update-function-configuration --function-name lambda-example --environment file://environment.json --query "Environment"

update lambda environment variables

In the command above, we've used the optional --query parameter to limit the output to only consist of the environment variables of the function.

However, if we look at the function's environment variables, we see that our DEPARTMENT env variable is missing.

The update-function-configuration command replaces any existing environment variables with the newly created environment variables.

The way to add environment variables to a function with the AWS CLI, rather than replace them, is to first list the function's current environment variables, by running the get-function-configuration command:

shell
aws lambda get-function-configuration --function-name lambda-example --query '{revisionId: RevisionId, env: Environment}'

list lambda environment variables

We used the --query parameter to filter the output to only relevant properties:

  • the function's environment variables.
  • the revisionId, which can be included in the update-function-configuration command and is only used when multiple people work on the same Lambda function.

The revisionId prevents the scenario where you would list a function's environment variables and a colleague of yours would update them before you update them, causing a race condition.

It only makes sense to include the revisionId in the update-function-configuration command if there are multiple people working on the same lambda function.

Now that we have the function's environment variables, let's update our environment.json file to include the department variable:

environment.json
{ "Variables": { "COLOR": "green", "FRUIT": "avocado", "DEPARTMENT": "accounting" } }

And finally, let's update the function's environment variable, passing in the revisionId to the update-function-configuration command:

shell
aws lambda update-function-configuration --function-name lambda-example --environment file://environment.json --revision-id "YOUR_REVISION_ID" --query "Environment"

add lambda environment variables

The way the update-function-configuration command works with environment variables applies to Lambda layers as well.

Using the command and passing in a layer, replaces any layers the function previously had, rather than adding them.

# Creating Lambda layers with AWS CLI

In this section of the article, we will create a Node.js Lambda function with 2 layers using AWS CLI.

The layers consist of:

  • a 3rd party library, called date-fns
  • our own helper function

Before creating the Lambda function, we must create a role for it.

The role needs to have a trust policy that allows the Lambda service to assume it.

The code for this article is available on GitHub

Save the following json into a trust-policy.json file:

trust-policy.json
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "Service": "lambda.amazonaws.com" }, "Action": "sts:AssumeRole" } ] }

Open your terminal in the directory where you stored the trust-policy.json file and pass it to the create-role command:

shell
aws iam aws iam create-role --role-name lambda-layers-role --assume-role-policy-document file://trust-policy.json

create lambda role

Copy and paste the role ARN into a notepad because we'll need it when creating the Lambda function.

Next, attach a policy to the role, which grants permissions to log to CloudWatch.

shell
aws iam attach-role-policy --role-name lambda-layers-role --policy-arn arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole

attach policy to role

# Creating the Lambda Function with AWS CLI

Now that we have the role, let's create the node.js Lambda function, create an index.js file with the following code:

The code for this article is available on GitHub
index.js
const {format} = require('date-fns'); const {double} = require('calc'); exports.handler = async event => { const response = { statusCode: 200, body: JSON.stringify({ today: format(new Date(), "'Today is a' eeee"), doubled: double(15), }), }; return response; };

The function imports the layers and uses them to form the response.

Let's zip the Lambda function code so we can create it using the CLI:

shell
zip -r9 lambda.zip index.js

zip lambda function

And finally, let's create the function using the AWS CLI, open your terminal in the directory where you stored the lambda.zip file and run the create-function command:

shell
aws lambda create-function --function-name layers-function --runtime nodejs14.x --zip-file fileb://lambda.zip --handler index.handler --role "arn:aws:iam::YOUR_ACCOUNT_NUMBER:role/lambda-layers-role"

create lambda function

# Packaging and Deploying Lambda Layers with AWS CLI

At this point we've created the node.js function, however, we haven't packaged and deployed the layers it makes use of.

The directory paths for the layers are kind of tricky because Lambda expects a specific folder structure.

The code for this article is available on GitHub

Create the following folders and files in the directory where you stored the lambda's index.js file:

shell
layers calc nodejs node_modules calc.js date-fns nodejs package.json index.js

If you get confused about the folder structure, check out the GitHub repository.

Let's take care of the calc layer first. Open the calc.js file and enter the following code in it:

layers/calc/nodejs/node_modules/calc.js
exports.double = (number) => { return number * 2; }

The file exports a utility function that we can include as a layer and reuse in multiple Lambda functions.

Note that in most projects node_modules is added to .gitignore, since we are storing a helper function, in the node_modules directory and not a 3rd party package, make sure to exclude the file from your .gitignore, e.g. by adding the following line to your .gitignore - !layers/calc/**/node_modules.

Now let's take care of the layer that imports a 3rd party package. Open your terminal in the layers/date-fns/nodejs directory and run the following commands:

layers/date-fns/nodejs
# in the layers/date-fns/nodejs directory npm init -y npm install date-fns@2.24.0

Your folder structure should look as follows.

layers folder structure

At this point, we are ready to zip the code for the layers, create them and add them to the Lambda function.

Let's zip the code for the calc layer first, open your terminal in the layers/calc directory and run the zip command:

layers/calc
# in the layers/calc directory zip -r9 calc-layer.zip .

zip calc layer

To create the calc layer use the publish-layer-version command from the /layers/calc directory:

layers/calc
aws lambda publish-layer-version --layer-name calc-layer --description "added double fn" --zip-file fileb://calc-layer.zip --compatible-runtimes nodejs10.x nodejs12.x nodejs14.x

create calc layer

Copy and paste the value of the LayerVersionArn property in a notepad because we will need it when attaching the layer to the Lambda function. The LayerVersionArn will look something like: "arn:aws:lambda:YOUR_REGION:YOUR_ACCOUNT_ID:layer:calc-layer:1"

Let's also zip and publish the date-fns layer. Open your terminal in the layers/date-fns directory and run the zip command:

layers/date-fns
# in the layers/date-fns directory zip -r9 date-fns-layer.zip .

To create the date-fns layer, open your terminal in the layers/date-fns directory and run the publish-layer-version command:

layers/date-fns
# in the layers/date-fns directory aws lambda publish-layer-version --layer-name date-fns-layer --description "add date-fns library" --zip-file fileb://date-fns-layer.zip --compatible-runtimes nodejs10.x nodejs12.x nodejs14.x
Copy and paste the value of the LayerVersionArn property in a notepad because we will need it when attaching the layer to the Lambda function. The LayerVersionArn will look something like: "arn:aws:lambda:YOUR_REGION:YOUR_ACCOUNT_ID:layer:date-fns-layer:1"

create date fns layer

# Attaching Layers to a Lambda Function with AWS CLI

At this point, we've created the layers and all we have to do is attach the layers to the Lambda function.

We'll need the LayerVerionArns for both of the layers. In case you didn't copy the LayerVersionArns, run the following commands to retrieve them:

shell
aws lambda list-layer-versions --layer-name calc-layer --query "LayerVersions[*].LayerVersionArn" aws lambda list-layer-versions --layer-name date-fns-layer --query "LayerVersions[*].LayerVersionArn"

The command returns a list of all the LayerVersionArns of a layer, just pick the latest version if you have multiple.

Finally, let's add the layers to the Lambda function and test if everything works as expected.

Run the update-function-configuration command, setting the --layers parameter as our space-separated LayerVersionArns.

shell
aws lambda update-function-configuration --function-name layers-function --layers "CALC_LAYER_VERSION_ARN" "DATE_FNS_LAYER_VERSION_ARN"

add layers to lambda

Let's test if everything works as expected, invoke the lambda function, storing the response in a response.json file:

shell
aws lambda invoke --function-name layers-function response.json

invoke lambda with layers

The Lambda function's response shows that the layers work as expected.

Note that the update-function-configuration command that we used to attach the layers to the function simply replaces the existing function's layers (if any), with the new layers we specified.

To be on the safe side, we can list the existing function's layers and include the ARNs in the update-function-configuration command.

To list the function's layers, run the get-function-configuration command:

shell
aws lambda get-function-configuration --function-name layers-function --query "{layers: Layers, revisionId: RevisionId}"

list lambda layers

We used the --query parameter to limit the output to relevant to us properties:

  • the ARNs of the layers

  • the revisionId, which can be included in the update-function-configuration command and is only used when multiple people work on the same Lambda function.

    It allows us to be sure that no one of our colleagues updated the function in the time window we listed the function's layers and updated them. In other words, it helps us avoid race conditions.

In the case we wanted to add layers to the Lambda function and not replace the existing layers, we would copy the existing function's layer ARNs and include it in the update-function-configuration command.

# How to Create Lambda Environment Variables with AWS CLI

To create Environment Variables on a Lambda function using AWS CLI, run the update-function-configuration command, passing in the --environment parameter.

shell
aws lambda update-function-configuration --function-name YourFunction --environment "Variables={COLOR=green,FRUIT=avocado}" --query "Environment"

create lambda environment variables

In the command above, we've set 2 environment variables on the function, using the --environment parameter, COLOR=green and FRUIT=avocado.

The --query parameter is optional and filters the output from the command, returning only the environment variables.

When creating environment variables with the update-function-configuration command, all of the environment variables the Lambda previously had are replaced with the passed-in ones.

When trying to add environment variables to a Lambda function with the AWS CLI, and not necessarily replace them, it's best to first list the function's environment variables, using the get-function-configuration command:

shell
aws lambda get-function-configuration --function-name testFunction --query '{revisionId: RevisionId, env: Environment}'

list environment variables

In the command above, we used the optional --query parameter to output only the Lambda configuration properties that are relevant to us:

  • the environment variables the function has.
  • the revisionId, which you can include when creating environment variables, to make sure no one of your colleagues has created any other environment variables on the function in the meantime.

Depending on how many environment variables your function has, it's often easier to store them in a json file.

Copy and paste the value of the env property of the get-function-configuration command and store it in a file called environment.json, adding in any additional environment variables:

environment.json
{ "Variables": { "FRUIT": "avocado", "COLOR": "green", "FOOD": "pizza" } }

Next, open your terminal in the directory where the environment.json file is stored and run the update-function-configuration command, passing in the file to the --environment parameter:

shell
aws lambda update-function-configuration --function-name YourFunction --environment file://environment.json --revision-id "your-revision-id" --query "Environment"
It only makes sense to include the --revision-id parameter if multiple people are working on the function and there is a risk that they can override the environment variables of the function in a short period of time between you list the function's environment variables and update them.

update lambda environment variables

To verify the environment variables of the Lambda function have been updated, we can run the get-function-configuration command again:

shell
aws lambda get-function-configuration --function-name YourFunction --query '{revisionId: RevisionId, env: Environment}'

list updated environment variables

The output shows that the environment variables we stored in the json file have been created on the Lambda function and after the update the revisionId has changed.

# Additional Resources

You can learn more about the related topics by checking out the following tutorials:

I wrote a book in which I share everything I know about how to become a better, more efficient programmer.
book cover
You can use the search field on my Home Page to filter through all of my articles.