Amazon lambda nodejs elasticache store data in redis - amazon-web-services

I have a lambda function(runtime: Nodejs 4.3) and I need to store data in elasticache. The engine is redis. This is my function:
const redis = require("redis");
exports.handler = function (event, context, callback) {
callback(null, {});
};
Lambda returns "errorMessage": "Cannot find module 'redis'", error.
Should I add nom redis package in zip?

All npm modules needs to be installed in node_modules folder. You can use npm install --save package name command to install node_module and save its name in package.json. Refer this link for --save option explanation.
Zip the index.js and node_moule for upload. index.js file is your handler function, if your handler name is different, use that name for js file and zip file.
Note:- It is best to use node-lambda module for developing your code on local ec2 machine. Execute it with the node-lambda run and use node-lambda deploy for deploying the code over lambda. Zipping and all other things will be taken care by node-lambda.

Related

Cant Import packages from layers in AWS Lambda

I know this question exists several places, but even by following different guides/answers I still cant get it to work. I have no idea what I do wrong. I have a lambda Python function on AWS where i need to do a "import requests". This is my approach so far.
Create .zip directory of packages. Locally I do:
pip3 install requests -t ./
zip -r okta_layer.zip .
Upload .zip directory to a lambda layer:
I go to the AWS console and go to lambda layers. I create a new layer based on this .zip file.
I go to my lambda python function and add the layer to the function directly form the console. I can now see the layer under "Layers" for the lambda function. Then i run the script it still complains about:
Unable to import module 'lambda_function': No module named 'requests'
I solved the problem. Apparently I needed to have a .zip folder, with a "python" folder inside, and inside that "python" folder should be all the packages.
I only had all the packages in the zip folder directly without a "python" folder ...

AWS Lambda Console - Upgrade boto3 version

I am creating a DeepLens project to recognise people, when one of select group of people are scanned by the camera.
The project uses a lambda, which processes the images and triggers the 'rekognition' aws api.
When I trigger the API from my local machine - I get a good response
When I trigger the API from AWS console - I get failed response
Problem
After much digging, I found that the 'boto3' (AWS python library) is of version:
1.9.62 - on my local machine
1.8.9 - on AWS console
Question
Can I upgrade the 'boto3' library version on the AWS lambda console ?? If so, how ?
If you don't want to package a more recent boto3 version with you function, you can download boto3 with each invocation of the Lambda. Remember that /tmp/ is the directory that Lambda will allow you to download to, so you can use this to temporarily download boto3:
import sys
from pip._internal import main
main(['install', '-I', '-q', 'boto3', '--target', '/tmp/', '--no-cache-dir', '--disable-pip-version-check'])
sys.path.insert(0,'/tmp/')
import boto3
from botocore.exceptions import ClientError
def handler(event, context):
print(boto3.__version__)
You can achieve the same with either Python function with dependencies or with a Virtual Environment.
These are the available options other than that you also try to contact Amazon team if they can help you with up-gradation.
I know, you're asking for a solution through Console, but this is not possible (as of my knowledge).
To solve this you need to provide the boto3 version you require to your lambda (either with the solution from user1998671 or with what Shivang Agarwal is proposing). A third solution is to provide the required boto3 version as a layer for the lambda. The big advantage of the layer is that you can re-use it for all your lambdas.
This can be achieved by following the guide from AWS (the following is mainly copied from the linked guide from AWS):
IMPORTANT: Make sure to adjust boto3-mylayer with a for you suitable name.
Create a lib folder by running the following command:
LIB_DIR=boto3-mylayer/python
mkdir -p $LIB_DIR
Install the library to LIB_DIR by running the following command:
pip3 install boto3 -t $LIB_DIR
Zip all the dependencies to /tmp/boto3-mylayer.zip by running the following command:
cd boto3-mylayer
zip -r /tmp/boto3-mylayer.zip .
Publish the layer by running the following command:
aws lambda publish-layer-version --layer-name boto3-mylayer --zip-file fileb:///tmp/boto3-mylayer.zip
The command returns the new layer's Amazon Resource Name (ARN), similar to the following one:
arn:aws:lambda:region:$ACC_ID:layer:boto3-mylayer:1
To attach this layer to your lambda execute the following:
aws lambda update-function-configuration --function-name <name-of-your-lambda> --layers <layer ARN>
To verify the boto version in your lambda you can simply add the following two print commands in your lambda:
print(boto3.__version__)
print(botocore.__version__)

AWS Lambda returns "Unable to import module"

I am running the AWS DevSecOps project present here:
In the StaticCodeAnalysis stage of the pipeline I am getting AWS Lambda function failed.
On checking the log the error is:
"Unable to import module cfn_validate_lambda: No module named cfn_validate_lambda".
I checked that the S3 bucket that has the python code Zip and also ensured that the zip file has Public in the permissions.
Please let me know how to resolve this.
Thanks.
You have to package and zip the dependencies carefully...
The problem lies in the packaging hierarchy. After you install the dependencies in a directory, zip the lambda function as follows (in the example below, lambda_function is the name of my function)
Try this:
pip install requests -t .
zip -r9 lambda_function.zip .
zip -g lambda_function.zip lambda_function.py

How do I run my CDK app?

I created and built a new CDK project:
mkdir myproj
cd myproj
cdk init --language typescript
npm run build
If I try to run the resulting javascript, I see the following:
PS C:\repos\myproj> node .\bin\myproj.js
CloudExecutable/1.0
Usage:
C:\repos\myproj\bin\myproj.js REQUEST
REQUEST is a JSON-encoded request object.
What is the right way to run my app?
You don't need to run your CDK programs directly, but rather use the CDK Toolkit instead.
To synthesize an AWS CloudFormation from your app:
cdk synth --app "node .\bin\myproj.js"
To avoid re-typing the --app switch every time, you can setup a cdk.json file with:
{ "app": "node .\app\myproj.js" }
Note: A default cdk.json is created by cdk init, so you should already see it under C:\repos\myproj.
You can also use the toolkit to deploy your app into an AWS environment:
cdk deploy
Or list all the stacks in your app:
cdk ls
The CDK application expects a request to be provided as a positional CLI argument when you're using the low-level API (aka running the app directly), for example:
node .\bin\myproj.js '{"type":"list"}'
It can also be passed as a Base64-encoded blob instead (that can make quoting the JSON less painful in a number of cases) - the Base64 needs to be prefixed with base64: in this case.
node .\bin\myproj.js base64:eyAidHlwZSI6ICJsaXN0IiB9Cg==
In order to determine what are the APIs that are available, and what arguments they expect, you can refer to the #aws-cdk/cx-api specification.

How to execute .jar file from AWS Lambda Serverless?

I have tried with following code.
var exec = require('child_process').execFile;
var runCmd = 'java -jar ' + process.env.LAMBDA_TASK_ROOT + '/src/' + 'myjar.jar'
exec(runCmd,
function (err, resp) {
if (err) {
cb(null, { err: err})
} else {
cb(null, { resp: resp})
}
)
Here, I have put my jar file in the root folder and src folder also.
but it is giving my following error. I have already added the.jar file with the code.but i got following error.
"err": {
"code": "ENOENT",
"errno": "ENOENT",
"syscall": "spawn java -jar /var/task/src/myjar.jar",
"path": "java -jar /var/task/src/myjar.jar",
"spawnargs": [],
"cmd": "java -jar /var/task/src/myjar.jar"
}
So How, Can I execute this .jar file in AWS Lambda environment?
Please help me.
With Lambda Layers you can now bring in multiple runtimes.
https://github.com/lambci/yumda and https://github.com/mthenw/awesome-layers both have a lot of prebuilt packages that you can use to create a layer so you have a second runtime available in your environment.
For instance, I'm currently working on a project that uses the Ruby 2.5 runtime on top of a custom layer built from lambci/yumbda to provide Java.
mkdir dependencies
docker run --rm -v "$PWD"/dependencies:/lambda/opt lambci/yumda:1 yum install -y java-1.8.0-openjdk-devel.x86_64
cd dependencies
zip -yr ../javaLayer .
upload javaLayer.zip to aws lambda as a layer
add layer to your function
within your function, java will be located at /opt/lib/jvm/{YOUR_SPECIFIC_JAVA_VERSION}/jre/bin/java
AWS Lambda lets you select a runtime at the time of creation of that lambda function, or later you can change it again.
So, as you are running the Lambda function with NodeJs runtime, the container will not have Java runtime available to it.
You can only have one type of runtime in one container in case of AWS Lambda.
So, Create a separate Lambda with the Jar file that you want to run having Java as the runtime and then you can trigger that lambda function from your current NodeJS lambda function if that's what you ultimately want.
Following is an example of how you can call another Lambda function using NodeJS
var aws = require('aws-sdk');
var lambda = new aws.Lambda({
region: 'put_your_region_here'
});
lambda.invoke({
FunctionName: 'lambda_function_name',
Payload: JSON.stringify(event, null, 2)
}, function(error, data) {
if (error) {
context.done('error', error);
}
if(data.Payload){
context.succeed(data.Payload)
}
});
You can refer to the official documentation for more details.
In addition to the other answers: Since 2020 December, Lambda supports container images: https://aws.amazon.com/blogs/aws/new-for-aws-lambda-container-image-support/
Ex.: I created a container image using AWS's open-source base image for python, adding a line to install java. One thing my python code did was execute a .jar file using a sys call.