Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

aws lambda layer shared library in node_modules not accesible in function

Tags:

aws-lambda

I recently changed my lambda functions to use the new aws Lambda Layer functionality, to share all the node_modules folder. I created the zip with the following structure:

nodejs/node_modules/<libraries, like 'async' and others..>
nodejs/package.json

I also linked the lambda function to the layer, and it succeed (checked both in the CLI and in the web console), see output below.. but anyway, always the lambda function fails on the require:

in lambda: require('async')

output: "errorMessage":"Cannot find module 'async'"

output of the update-function call:

aws lambda update-function-configuration --function-name MY_LAMBDA --layers arn:aws:lambda:us-west-2:MY_ID:layer:MY_LAYER:4
{
"Layers": [
{
"CodeSize": 21482560,
"Arn": "arn:aws:lambda:us-west-2:MY_ID:layer:MY_LAYER:4"
}
],
"FunctionName": "MY_LAMBDA",
"LastModified": "2018-12-18T23:44:34.062+0000",
"RevisionId": "f55a6ab7-7b0b-494a-840c-87fb8371a117",
"MemorySize": 128,
"Version": "$LATEST",
"Role": "arn:aws:iam::MY_ID:role/service-role/MY_ROLE",
"Timeout": 30,
"Runtime": "nodejs4.3",
"TracingConfig": {
"Mode": "PassThrough"
},
"CodeSha256": "hajYdqb+...=",
"Description": "",
"VpcConfig": { ... lot of stuff here .. },
"CodeSize": 429123,
"FunctionArn": "arn:aws:lambda:MY_ZONE:MY_ID:function:MY_LAMBDA",
"Handler": "MY_HANDLER"
}

notes: 1. my layer is in version 4. 2. I set the layer to all three node.js environments for support. 3. I checked the zip and it has all the node_modules content as expected.

any suggestion about what else to check is welcomed!

like image 290
cesarpachon Avatar asked Dec 19 '18 00:12

cesarpachon


People also ask

Can AWS Lambda share code between functions?

Before lambda layers, developers used to either duplicate common code in every lambda function or create local npm packages and refer them in lambdas. Now with lambda layers, you can securely share code among your lambda functions in the same AWS account, cross-accounts or in public.


3 Answers

I have also stuck in this problem and not able to figure it out because I have applied all mentioned things like permission and node zip but was n't successful after a while I used the const lodash = require('/opt/nodejs/node_modules/lodash') It works for me.

like image 171
shailesh sahu Avatar answered Oct 23 '22 10:10

shailesh sahu


You able to create the Layer and it's version properly and also able to retrieve information about them without any issues.

Even after that Lambda function is not able to use the libraries from the Layer, looks like the Lambda function is not able to access the Layer because it does not have the permission to do so.

You can confirm this by checking if the role associated with the Lambda is having any policy attached to it which allows lambda:GetLayerVersion permission.

If not you need to create a new policy with following JSON and some meaningful name.

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": "lambda:GetLayerVersion",
            "Resource": "*"
        }
    ]
}

Now you need to add attach this policy to the role arn:aws:iam::MY_ID:role/service-role/MY_ROLE which associated with the Lambda function.

Both of the above actions can be performed from AWS Console.

Once this is done, the Lambda function will have permission to get the layer version and should be able access the libraries from the Layer.

I hope this would help you resolve your issue. Feel free to ask if you need any clarifications.

like image 34
Chetan Avatar answered Oct 23 '22 10:10

Chetan


I was having an issue with this as well. Turns out you need to make sure you have your zip file set up correctly, using 'nodejs' as the folder name. If you create a folder named 'nodejs' with just your package.json, run npm install, and then zip that up, then you can use 'require' normally.

In my case, I am using the NPM packages axios, aws-sdk, and http. Here's the steps I took:

  • Create a 'nodejs' directory
  • Copy your package.json file into it
  • Run npm install in the nodejs directory
  • From one level up, zip the directory. On a Mac: zip nodejs.zip nodejs/ -r
  • Create a layer in AWS, import the zip, and give the layer the Node.js runtime
  • Add the layer to your lambda

Now I can use my require statements normally.

const axios = require('axios')
const AWS = require('aws-sdk');
const http = require('http');

Also note that your lambda's role, under Basic Settings, should have lambda permissions. For example, if your role has the AWSLambdaFullAccess policy attached, or another policy with the correct lambda permissions (like "lambda:*"), then you are fine.

like image 6
MattC Avatar answered Oct 23 '22 10:10

MattC