I am new to NodeJS and i am trying to post a message to AWS SNS from lambda. I took the code from AWS code samples and it is working fine in lambda.
But when i wrapped the same code in a function aand invoked from the main handler it is not working..
I tried returning and resolving the promise but nothing works.
// Load the AWS SDK for Node.js
var AWS = require('aws-sdk');
// Set region
exports.handler = async (event, context) => {
saveToSNS();
};
function saveToSNS() {
console.log("sdsdsd");
var AWS = require('aws-sdk');
var params = {
Message: 'MESSAGE_TEXT', /* required */
TopicArn: '<MY TOPIC>'
};
// Create promise and SNS service object
var publishTextPromise = new AWS.SNS({apiVersion: '2010-03-31'}).publish(params).promise();
// Handle promise's fulfilled/rejected states
return publishTextPromise.then(
function(data) {
console.log("sdsdsd");
console.log("Message ${params.Message} send sent to the topic ${params.TopicArn}");
console.log("MessageID is " + data.MessageId);
}).catch(
function(err) {
console.error(err, err.stack);
});
}
You need to place all code inside the handler as well. You can try like this:
exports.handler = async (event, context) => {
// Load the AWS SDK for Node.js
var AWS = require('aws-sdk');
// Set region
AWS.config.update({region: 'REGION'});
saveToSNS();
function saveToSNS() {
// Create publish parameters
var params = {
Message: 'MESSAGE_TEXT', /* required */
TopicArn: 'TOPIC_ARN'
};
// Create promise and SNS service object
var publishTextPromise = new AWS.SNS({apiVersion: '2010-03-31'}).publish(params).promise();
publishTextPromise.then(function(data) {
console.log("Message ${params.Message} send sent to the topic ${params.TopicArn}");
console.log("MessageID is " + data.MessageId);
}).catch(function(err) {
console.error(err, err.stack);
});
}
};
You can either use async/await like this:
// Load the AWS SDK for Node.js
var AWS = require('aws-sdk');
// Set region
exports.handler = async (event, context) => {
await saveToSNS();
};
async function saveToSNS() {
console.log("sdsdsd");
var AWS = require('aws-sdk');
var params = {
Message: 'MESSAGE_TEXT', /* required */
TopicArn: '<MY TOPIC>'
};
// Create promise and SNS service object
var publishTextPromise = new AWS.SNS({apiVersion: '2010-03-31'}).publish(params).promise();
// Handle promise's fulfilled/rejected states
return publishTextPromise.then(
function(data) {
console.log("sdsdsd");
console.log("Message ${params.Message} send sent to the topic ${params.TopicArn}");
console.log("MessageID is " + data.MessageId);
}).catch(
function(err) {
console.error(err, err.stack);
});
}
or add the return statement before calling saveToSNS() function, like this:
exports.handler = async (event, context) => {
return saveToSNS();
};
Related
I have a AWS Lambda function that checks if a site is online
var http = require('https');
var url = 'https://www.google.com';
exports.handler = function(event, context) {
http.get(url, function(res) {
console.log("Got response: " + res.statusCode);
context.succeed();
}).on('error', function(e) {
console.log("Got error: " + e.message);
context.done(null, 'FAILURE');
});
}
I would like to reboot an EC2 instance if the website is offline.
This is the Lambda function to reboot EC2:
var AWS = require('aws-sdk');
exports.handler = function(event, context) {
var ec2 = new AWS.EC2({region: 'us-east-1'});
ec2.rebootInstances({InstanceIds : ['i-xxxxxxxxxxxxxxx'] },function (err, data) {
if (err) console.log(err, err.stack);
else console.log(data);
context.done(err,data);
});
};
Both functions work.
Now I am trying to call the ec2 reboot function when the https request fails.
I have an extremely limited experience with node.js and aws so I tried many different ways but no result.
Can someone point me in the right direction?
you can invoke a lambda using the invoke function.
function checkWebsite(url, callback) {
https
.get(url, function(res) {
console.log(url, res.statusCode);
return callback(res.statusCode === 200);
})
.on("error", function(e) {
return callback(false);
});
}
var http = require('https');
exports.handler = function(event, context, callback) {
var url = 'https://www.google.com';
checkWebsite(url, (check) => {
if (!check) {
const lambda = new AWS.Lambda();
const params = {
FunctionName: "my-function",
Payload: '{"instanceId":"instance-1233x5"}'
};
lambda.invoke(params, function(err, data) {
if (err) console.log(err, err.stack); // an error occurred
else console.log(data); // successful response
// handle error/ success
// if you return the error, the lambda will be retried, hence returning a successful response
callback(null, 'successfully rebooted the instance')
});
} else {
callback(null, 'successfully completed')
}
})
}
Reference: Nodejs function to check if a website working
I am new to writing Lambda in JS. I want to be able to list the S3 buckets I have, however, below lambda doesn't return what I expect, ie. list of buckets.
What have I done wrong? The only thing I am aware of is the line "console.log('hihi')" didn't print in my Cloudwatch log, so something going on when listBuckets() is invoked but I can't see any relevant logs... Tks in advance for any help !!
var AWS = require('aws-sdk');
AWS.config.update({region: 'us-east-1'});
exports.handler = async (event) => {
// Create S3 service object
var s3 = new AWS.S3({apiVersion: '2006-03-01'});
var params = {};
// Call S3 to list the buckets
s3.listBuckets(params, function(err, data) {
console.log('hihi')
if (err) {
console.log("Error", err);
} else {
console.log("Success", data.Buckets);
}
});
// TODO implement
const response = {
statusCode: 200,
body: JSON.stringify('Hello from Lambda!'),
};
return response;
};
You are using async handler. Therefore, to your lambda does return before listBucket has a chance to execute. One way to overcome is through a Promise as shown in AWS docs.
Therefore, you could modify your code as follows:
var AWS = require('aws-sdk');
AWS.config.update({region: 'us-east-1'});
exports.handler = async (event) => {
const promise = new Promise(function(resolve, reject) {
// Create S3 service object
var s3 = new AWS.S3({apiVersion: '2006-03-01'});
var params = {};
// Call S3 to list the buckets
s3.listBuckets(params, function(err, data) {
console.log('hihi')
if (err) {
console.log("Error", err);
} else {
console.log("Success", data.Buckets);
}
});
})
return promise
};
I'm trying to list all of my cognito users in my lambda function, however i get nothing in the return as if the callback not getting executed. What am I doing wrong?
The output of the code below just gives me a hello in the console.
var AWS = require("aws-sdk");
const cognitoidentityserviceprovider = new AWS.CognitoIdentityServiceProvider();
export async function main() {
console.log("hello")
var params = {
UserPoolId: "myuserpoolid",
AttributesToGet: ["username"]
};
cognitoidentityserviceprovider.listUsers(params, (err, data) => {
if (err) {
console.log(err, err.stack);
return err;
} else {
console.log(data);
return data;
}
});
}
First of all, the structure of the code is wrong. The header of Lambda function should have a certain structure, either using async function or non-async function. Since you are using non-async code in your example I will show you how to do the later.
var AWS = require("aws-sdk");
const cognitoidentityserviceprovider = new AWS.CognitoIdentityServiceProvider();
exports.handler = function(event, context, callback) {
console.log("hello")
var params = {
UserPoolId: "myuserpoolid",
AttributesToGet: ["username"]
};
cognitoidentityserviceprovider.listUsers(params, (err, data) => {
if (err) {
console.log(err, err.stack);
callback(err) // here is the error return
} else {
console.log(data);
callback(null, data) // here is the success return
}
});
}
In this case, Lambda will finish only when callback is called (or when it times out).
Similarly, you can use async function but you will need to restructure your code accordingly. Here is an example taken from official docs. Note how the promise wrapper is used.
const https = require('https')
let url = "https://docs.aws.amazon.com/lambda/latest/dg/welcome.html"
exports.handler = async function(event) {
const promise = new Promise(function(resolve, reject) {
https.get(url, (res) => {
resolve(res.statusCode)
}).on('error', (e) => {
reject(Error(e))
})
})
return promise
}
For AttributesToGet, don't use username because it is one of the fields that always gets returned. The following are members of the Attributes array, and can be used in the AttributesToGet field:
sub, email_verified, phone_number_verified, phone_number, email.
e.g.
AttributesToGet: ["email","email_verified"]
I am attempting to list an S3 bucket from within my node.js (8.10) lambda function.
When I run the function below (in Lambda), I see "Checkpoint 1" and "Checkpoint 2" in my logs, but I don't see any logging from the listObjectsV2 call, neither error nor data. My timeout is set to 10 seconds and I am not seeing any log entries for timeouts, either. I think I may missing something about using asynchronous functions in lambda?
const AWS = require('aws-sdk');
const s3 = new AWS.S3({apiVersion: '2006-03-01'});
exports.handler = async (event, context) => {
// console.log('Received event:', JSON.stringify(event, null, 2));
var params = {
Bucket: 'bucket-name'
}
console.log("Checkpoint 1");
s3.listObjectsV2(params, function (err, data) {
if (err) {
console.log(err, err.stack);
} else {
console.log(data);
}
});
console.log("Checkpoint 2");
};
Can someone point me in the right direction for finding my error here?
Not only you need to return a promise, you also need to await on it, otherwise it has no effect. This is because your handler is async, meaning it will return a promise anyways. This means that if you don't await on the code you want to execute, it's very likely that Lambda will terminate before the promise is ever resolved.
Your code should look like this:
const AWS = require('aws-sdk');
const s3 = new AWS.S3({apiVersion: '2006-03-01'});
exports.handler = async (event, context) => {
// console.log('Received event:', JSON.stringify(event, null, 2));
var params = {
Bucket: 'bucket-name'
}
console.log("Checkpoint 1");
let s3Objects
try {
s3Objects = await s3.listObjectsV2(params).promise();
console.log(s3Objects)
} catch (e) {
console.log(e)
}
console.log("Checkpoint 2");
// Assuming you're using API Gateway
return {
statusCode: 200,
body: JSON.stringify(s3Objects || {message: 'No objects found in s3 bucket'})
}
};
AWS SDK can return a promise, just add .promise() to your function.
s3.listObjectsV2(params).promise();
I've written an AWS lambda function to send a text message when an S3 object is uploaded. I've confirmed the subscription and I can receive test messages sent from the SNS console.
When I test the lambda all the logs say the method succeeds but no sons message ever arrives. Here is the function (mostly just the sample template but changed my topic arn in this post for security). Any hints of things to test/try next are appreciated.
console.log('Loading function');
var aws = require('aws-sdk');
var s3 = new aws.S3({ apiVersion: '2006-03-01' });
exports.handler = function(event, context) {
var bucket = event.Records[0].s3.bucket.name;
var key = decodeURIComponent(event.Records[0].s3.object.key.replace(/\+/g, ' '));
var params = {
Bucket: bucket,
Key: key
};
var sns = new aws.SNS();
console.log('start of brians sns function')
var pubResult = sns.publish({
Message: 'Test publish to SNS from Lambda',
TopicArn: 'arn:aws:sns:us-east-1:xxxxxxxxxxxx:lambdatop'
}, function(err, data) {
if (err) {
console.log(err.stack);
return;
}
console.log('push sent');
console.log(data);
});
console.log('after sns publish:')
console.log(pubResult)
context.done(null, 'Brians Function Finished!');
};
You are calling context.done() right after calling publish(). The publish() function is an asynchronous call, and you aren't waiting for it to finish. Also, I don't think your variable pubResult contains what you expect it to.
Try this:
console.log('Loading function');
var aws = require('aws-sdk');
exports.handler = function(event, context) {
var sns = new aws.SNS();
console.log('start of brians sns function')
sns.publish({
Message: 'Test publish to SNS from Lambda',
TopicArn: 'arn:aws:sns:us-east-1:xxxxxxxxxxxx:lambdatop'
}, function(err, data) {
if (err) {
console.log(err.stack);
// Notify Lambda that we are finished, but with errors
context.done(err, 'Brians Function Finished with Errors!');
return;
}
console.log('push sent');
console.log(data);
// Notify Lambda that we are finished
context.done(null, 'Brians Function Finished!');
});
};
One more way to tackle this issue is wrap the SNS Publish in a Promise and wait for it to be resolved from the Lambda handler.
exports.handler = async (event) => {
await publishSNS(record, process.env.TOPIC_ARN);
}
async function publishSNS(payload, topicArn) {
await SNS.publish({
Message: JSON.stringify(payload),
TargetArn: topicArn
}).promise().then((data) => {
console.log('SNS push succeeded: ', data);
}).catch((err) => {
console.error(err);
});
}