don't include all aws-sdk for node lambdas - node.js

I have a bunch of aws lambdas written in node 12. I've discovered that require("aws-sdk") takes ages - like 3 seconds all by itself. I also discovered that if I just want to hit dynamo, I can just load a tiny little bit of it, by going:
const DynamoDB = require('aws-sdk/clients/dynamodb')
which ends up being heaps faster. However, I now need to call a lambda - ie I'm doing
const aws = require('aws-sdk');
const lambda = new aws.Lambda( );
but I couldn't find any way of requiring just lambda - eg I'd like something like this to work:
const Lambda = require("aws-sdk/Lambda");
const lambda = new Lambda();
but it doesn't. Is there any way of just including lambda functionality, without the whole aws sdk?

You should check the JS AWS SDK v3, quoting from their repo:
The AWS SDK for JavaScript v3 gamma is a rewrite of V2 with some great new features. As with version 2, it enables you to easily work with Amazon Web Services, but has been written in TypeScript and adds several frequently requested features, like modularized packages.
With it you can do things like:
const { Lambda } = require("#aws-sdk/client-lambda");
As the version suggests, it's still a pre-release so depending on your requirements and use case you might want to hold off until it's more stable.

so - turns out the solution was quite simple - Andre's answer made me look a lot closer and I came up with this:
const Lambda = require("aws-sdk/clients/lambda");

Related

How can I know whether it is running inside lambda?

I am deploying nodejs code to AWS lambda and I'd like to know how I can check whether it is running in lambda. Because I need to do something different in code between lambda and local.
AWS Lambda sets various runtime environment variables that you can leverage. You can use the following in Node.js, for example:
const isLambda = !!process.env.LAMBDA_TASK_ROOT;
console.log("Running on Lambda:", isLambda);
Note that the double bang !! converts a truthy/falsey object to a boolean (true/false).
I'd advise using a Lambda environment variable rather than attempting to check against any runtimes of the Lambda executing.
By doing this you can ensure that any infrastructure changes on the AWS side of Lambda will not affect your code.
It also allows you test it locally if you are trying to reproduce a scenario without the need to hardcode logic.

Firebase docs reference unknown module

Firebase has this piece of information here at https://firebase.google.com/docs/functions/locations:
Client-side location selection for callable functions Regarding the callable function, client callable setups should follow the same guidelines as HTTP functions. The client can also specify a region, and must do so if the function runs in any region other than us-central1.
To set regions on the client, specify the desired region at
initialization:
var functions = firebase.app().functions('us-central1');
I've been trying to find which node module firebase is referring to but I have had no luck.
I know that it is not 'firebase-admin' or 'firebase-functions' but thats about it.
Anyone have any ideas what this might be referring to?
Edit:
I have now also tried using this with the imports require('firebase') and require('firebase/app') (as suggested) but neither of those seem to work. I also tried generating the app with const app = firebase.initializeApp({}); and then running app.functions("region") or app().functions("region") but i keep receiving TypeErrors saying functions is not a function and app is not a function respectively.
firebase.app().functions('us-central1'); is a part of the firebase-js-sdk. With source code documented on GitHub
NPM component is #firebase/functions, that is documented on the npmjs.com.
However, it is not intended for standalone usage, and should be used along with package Firebase.
You can install it using:
$ npm i firebase

How to get past errors using putParameter with aws-sdk for nodejs in Lambda?

I'm trying to set a parameter using putParameter in the AWS SDK for JavaScript in Node.js. In particular, I'd like to take advantage of the "Advanced" Tier, with an Expiration policy and Tags if possible. When I execute my code, I keep getting errors like:
There were 2 validation errors:
* UnexpectedParameter: Unexpected key 'Policies' found in params
* UnexpectedParameter: Unexpected key 'Tier' found in params
I suspected the issue was around the aws-sdk version I was using, so I've tried running the code locally using SAM local, and from Lambda functions using the nodejs8.10 and nodejs10.x environments. The errors do not go away.
const AWS = require('aws-sdk');
AWS.config.update({region: 'us-east-1'});
const ssm = new AWS.SSM({apiVersion: '2014-11-06'});
exports.lambdaHandler = async () => {
const tokenExpiration = new Date();
tokenExpiration.setSeconds(tokenExpiration.getSeconds() + 60);
await ssm.putParameter({
Name: 'SECRET_TOKEN',
Type: 'SecureString',
Value: '12345',
Policies: JSON.stringify([
{
"Type":"Expiration",
"Version":"1.0",
"Attributes":{
"Timestamp": tokenExpiration.toISOString()
}
}
]),
Overwrite: true,
Tier: 'Advanced'
}).promise();
};
I would expect this code to work and set a parameter with the expiration. However, it appears that the sdk doesn't recognize the "Policies" and "Tier" parameters, which are available according to the documentation. I don't know if it's an issue of waiting for the newest AWS SDK for JavaScript, but the runtimes page suggest that nodejs10.x is running AWS SDK for JavaScript 2.437.0.
It might be helpful to know that I can get the code running correctly without the parameters in question (ie, just the "Name", "Type", and "Value" parameters).
Unfortunately both Tier and Policies weren't added until v2.442.0 (see diff)
This means that to use these features you'll have to deploy with the version of the aws-sdk you're developing against.
It should be noted that either developing/testing against the built-in version, or deploying with the aws-sdk you do use, is often cited as good practice. If you're deploying your version you can use explicit client imports (e.g. const SSM = require('aws-sdk/clients/ssm') to keep the deployment size down. This is even more effective if you develop against the preview AWS-SDK Version 3.

SageMaker NodeJS's SDK is not locking the API Version

I am running some code in AWS Lambda that dynamically creates SageMaker models.
I am locking Sagemaker's API version like so:
const sagemaker = new AWS.SageMaker({apiVersion: '2017-07-24'});
And here's the code to create the model:
await sagemaker.createModel({
ExecutionRoleArn: 'xxxxxx',
ModelName: sageMakerConfigId,
Containers: [{
Image: ecrUrl
}]
}).promise()
This code runs just fine locally with aws-sdk on 2.418.0.
However, when this code is deployed to Lambda, it doesn't work due to some validation errors upon creating the model:
MissingRequiredParameter: Missing required key 'PrimaryContainer' in params
UnexpectedParameter: Unexpected key 'Containers' found in params
Is anyone aware of existing bugs in the aws-sdk for NodeJS using the SDK provided by AWS in the Lambda context? I believe the SDK available inside AWS Lambda is more up-to-date than 2.418.0 but apparently there are compatibility issues.
As you've noticed the 'embedded' lambda version of the aws-sdk lags behind. It's actually on 2.290.0 (you can see the full details on the environment here: https://docs.aws.amazon.com/lambda/latest/dg/current-supported-versions.html)
You can see here: https://github.com/aws/aws-sdk-js/blame/master/clients/sagemaker.d.ts that it is not until 2.366.0 that the params for this method included Containers and did not require PrimaryContainer.
As you've noted, the workaround is to deploy your lambda with the aws-sdk version that you're using. This is sometimes noted as a best practice, as it pins the aws-sdk on the functionality you've built and tested against.

Do I need to specify the region when instantiating a AWS Helper Class in AWS Lambda?

If I want to call AWS SES from AWS Lambda, I normally write the following when instantiating the AWS Helper Class:
var ses = new aws.SES({apiVersion: '2010-12-01', region: 'eu-west-1'});
I'm wondering, do I actually need to specify the AWS Region? Or will the AWS SES helper class just run in the region where the AWS Lambda Function is running.
What is the best practice here? Might I encounter problems later if I omit this?
I have always specified the region for the sake of being explicit. I went and changed one of my NodeJS Lambda functions using SNS to using an empty constructor instead of providing region and deployed it...it appears to still work. It looks like the service will try to run in the region of the lambda function it is being called from. I imagine the IAM role for the lambda function would play a part as well. As far as best practice, I think it is best to be explicit when possible assuming it isn't creating a ton of overhead/hassle. The problem you risk running into in the future is the use of a resource that isn't in certain regions.

Resources