Chris Mitchell Online

Chris blogging about cloud, IT, and programming. What could go wrong?

Lambda Layers

2019-03-06

Lambda layers allow you to pull in custom code and content into your Lambda functions. This is a great tool for NodeJS dependencies that are managed via NPM.

From the AWS Lambda documentation:

A layer is a ZIP archive that contains libraries, a custom runtime, or other dependencies. With layers, you can use libraries in your function without needing to include them in your deployment package.

For this example of using Lambda layers we are going to focus on a NodeJS Lambda function that connects to Salesforce to perform operations. This function includes an NPM package called jsforce and an object that lives in Salesforce.js with wrapper functions.

An important note: Your folder structure must contain a nodejs folder, later we’ll zip this folder and send to AWS.

Our file structure looks like this:

salesforce_layer
  -nodejs
   - node_modules
    - jsforce
    - ..
    - salesforce-service
   - package.json

Where salesforce-service is the name of or custom NPM package. This directory was built using NPM:

npm install jsforce, salesforce-service

To publish this code as a Lambda layer that we can use in our functions first we must zip up code. From within salesforce_layer folder:

zip -r salesforce_layer.zip nodejs

Then upload to S3 (See my not later in the Notes and Comments section)

aws s3 cp salesforce_layer.zip  s3://cm-lambda-code-deploy/salesforce_layer.zip

Using the Lambda publish-layer-version can publish our layer to AWS, again replacing bucket name with your bucket name:

aws lambda publish-layer-version --layer-name "salesforce"  --description "Salesforce" --license-info "MIT" --content S3Bucket=cm-lambda-code-deploy,S3Key=salesforce_layer.zip --compatible-runtimes nodejs8.10

The response from AWS will give you details about your layer, including its layerArn, Version, and LayerVersionArn, which will be helpful when we update our Lambda function to use this layer.

{
    "Content": {
        ...
    },
    "LayerArn": "arn:aws:lambda:us-east-1:xxx:layer:salesforce",
    "LayerVersionArn": "arn:aws:lambda:us-east-1:xxx:layer:salesforce:24",
    "Description": "Salesforce",
    "CreatedDate": "2019-03-14T18:33:40.385+0000",
    "Version": 24,
    "CompatibleRuntimes": [
        "nodejs8.10"
    ],
    "LicenseInfo": "MIT"
}

After publishing the layer a helpful tool is to list the layers available for your functions:

aws lambda list-layers --compatible-runtime nodejs8.10

Attaching a Layer to Lambda

After succesfully uploading the layer, you will need to update your Lambda functions to be able to use the code in this layer. In the following example my function name is hello-world and I supply the ARN of the new Lambda layer version that I want the function to use. You can get this ARN when publishing a new layer or an updated version from the AWS response, from the lambda list-layers command, or by visiting the web console:

aws lambda list-layers --compatible-runtime nodejs8.10

With the update-function-configuration tool you can also specify multiple layers with the –layers flag. In this case we just have our Salesforce layer.

aws lambda update-function-configuration --function-name hello-world \
--layers arn:aws:lambda:us-east-1:xxx:layer:salesforce:1

Similar to the publish layer command from earlier, the response from AWS will give details about the updated function.

Using Layer Code

Now that we have a published layer and have configured our function to use layers, we can use them in our function. Just require your packages in your Lambda function like you would any other NPM library, but now these will come from a layer instead of packaged with your code. For the simple hello world function we have a bare bones Lambda function that includes our salesforce-service which we require first in our function as a const and then use in our code as expected:


const SF = require("salesforce-service")
exports.handler = async (event) => {
    const salesforceWrapper=new SF();
    
    /*
    Do stuff with my SF module here
    */

    const response = {
        statusCode: 200,
        body: JSON.stringify('Hello World'),
    };
    return response;
}

Notes and Gotchas

Zip Files: The zip file MUST follow the format shown above! When zipping up the folder from the command line ensure you are a directory above, in this case from withiin the salesforce_layer folder and that you use the -r flag to grab every file and put it in a directory nodejs.

S3 Requirement:The AWS CLI docs state that you can specify a local zip file when calling publish-layer-version with the syntax:

--content ZipFile="my_zip.zip"

But this always retuned an error in testing. Instead I had to upload the zip file to an S3 bucket and provide the bucket name and key instead using the following command, where bucketname is your S3 bucket:

aws s3 cp salesforce_layer.zip s3://<bucketname>

Helpful Articles and References

https://docs.aws.amazon.com/lambda/latest/dg/configuration-layers.html

comments powered by Disqus