#node.js #amazon-web-services #aws-lambda #amazon-dynamodb
#node.js #amazon-web-services #aws-lambda #amazon-dynamodb
Вопрос:
У меня есть приведенная ниже функция Lambda, которая должна вносить изменения в существующую таблицу Dynamodb и вносить их в другую таблицу Dynamodb.
Я намеренно оставил код, который я пробовал, закомментированным, я дошел до двух путей, оба из которых выдают ошибки в разных местах.
Если я включаю SharedIniFileCredentials в код, я получаю следующую ошибку в журналах Cloudwatch:
{
"message": "Missing credentials in config, if using AWS_CONFIG_FILE, set AWS_SDK_LOAD_CONFIG=1",
"errno": -2,
"syscall": "open",
"code": "CredentialsError",
"path": "/home/sbx_user1051/.aws/credentials",
"time": "2020-11-16T02:57:31.177Z",
"originalError": {
"message": "Could not load credentials from SharedIniFileCredentials",
"errno": -2,
"syscall": "open",
"code": "CredentialsError",
"path": "/home/sbx_user1051/.aws/credentials",
"time": "2020-11-16T02:57:31.177Z",
"originalError": {
"errno": -2,
"syscall": "open",
"code": "ENOENT",
"path": "/home/sbx_user1051/.aws/credentials",
"message": "ENOENT: no such file or directory, open '/home/sbx_user1051/.aws/credentials'"
}
}
}
Если я удалю это, просто позвольте роли, которую я создал и прикрепил (что, по словам документации AWS, это все, что мне нужно сделать), выполнять работу для разрешений, я не получаю ошибок в журналах Cloudwatch, но я вижу в своих консольных операторах, что PutItem (или put, если я использую другой класс) никогда не используется.выполняется. Код возвращается до того, как он выполнит эти функции. Итак, если я перейду в консоль AWS и посмотрю на вкладку триггера в моей таблице Dynamodb, я увижу «ПРОБЛЕМА: сбой вызова функции».
У меня есть добавить переменную среды. Я жестко закодировал ключ / секрет в коде. Я попытался запустить это в командной строке с помощью AWS CLI. Я добавил переменные среды. Я убедился, что мои учетные данные и файлы конфигурации заполнены правильно. Те же две проблемы, что бы я ни делал.
Я даже пробовал AWS CLI. Если я запущу это в командной строке со следующей командой
aws lambda invoke --function-name myfunction --cli-binary-format raw-in-base64-out --payload file://mynewitem2.json output.txt
I get this after a few seconds go by
Тайм-аут чтения по URL конечной точки: «https://lambda.us-east-2.amazonaws.com/2015-03-31/functions/myfunction/invocations «
Если я добавлю инструкции файла конфигурации, а затем повторно запущу его в командной строке, я получу это, но журналы Cloudwatch не показывают, что я достиг команд PutItem или put:
{
"StatusCode": 200,
"ExecutedVersion": "$LATEST"
}
Does anyone have any suggestions here? I have looked through all the similar requests for help with no luck. I've looked at the AWS documentation over and over.
I'm completely stuck here. I must be missing something. I just don't know what it is. Do any of you??
Here is the Lambda function:
'use strict';
console.log("starting myplugin insertion . . . ");
var AWS = require("aws-sdk");
AWS.config.logger = console;
//AWS.config = new AWS.Config();
//AWS.config.accessKeyId = "...";
//AWS.config.secretAccessKey = "...";
//AWS.config.region = 'us-east-2';
//AWS.config.update({
// aws_access_key_id : '...',
// aws_secret_access_key : '...',
// region: 'us-east-2'
// });
var creds = new AWS.SharedIniFileCredentials({profile: 'myprofile'});
console.log('Creds problem: ', JSON.stringify(creds, null, 2));
AWS.config.credentials = creds;
AWS.config.getCredentials(function(err) {
if (err)
console.log('Cred problem: ', JSON.stringify(err, null, 2));
else {
console.log("Cred Access:", JSON.stringify(AWS.config.credentials, null, 2));
}
});
var ddb = new AWS.DynamoDB({
'apiVersion': '2012-08-10'
});
exports.handler = (event, context, callback) => {
console.log(JSON.stringify(event, null, 2));
event.Records.forEach((record) => {
console.log('my Stream record: ', JSON.stringify(record, null, 2));
if (record.eventName == 'INSERT') {
console.log('my INSERTING RECORD');
var params = {
TableName: 'myplugin_temp',
Item: {
"client" : record.dynamodb.NewImage.client,
"expiration" : record.dynamodb.NewImage.expiration,
"notificationurl" : record.dynamodb.NewImage.notificationurl,
"clientid" : record.dynamodb.NewImage.clientid,
"s3path" : record.dynamodb.NewImage.s3path,
"language" : record.dynamodb.NewImage.language,
"filename" : record.dynamodb.NewImage.filename,
"timecreated" : record.dynamodb.NewImage.timecreated,
"appid" : record.dynamodb.NewImage.appid,
"subtitle" : record.dynamodb.NewImage.subtitle,
"host" : record.dynamodb.NewImage.host,
"mediatype" : record.dynamodb.NewImage.mediatype,
"sourcemimtype" : record.dynamodb.NewImage.sourcemimetype,
}
};
console.log("my UP HERE");
ddb.putItem(params, function(err,data) {
console.log("my HERE");
if (err) {
console.log("my INSERTING Error", JSON.stringify(err, null, 2));
} else {
console.log("my INSERTING Success",JSON.stringify(data, null, 2));
console.log("my COMPLETED INSERTION MODULE");
}
});
}
if (record.eventName == 'REMOVE') {
console.log('my DELETING RECORD');
var params = {
TableName: 'myplugin_temp',
Item: {
"client" : record.dynamodb.NewImage.client,
"expiration" : record.dynamodb.NewImage.expiration,
"notificationurl" : record.dynamodb.NewImage.notificationurl,
"clientid" : record.dynamodb.NewImage.clientid,
"s3path" : record.dynamodb.NewImage.s3path,
"language" : record.dynamodb.NewImage.language,
"filename" : record.dynamodb.NewImage.filename,
"timecreated" : record.dynamodb.NewImage.timecreated,
"appid" : record.dynamodb.NewImage.appid,
"subtitle" : record.dynamodb.NewImage.subtitle,
"host" : record.dynamodb.NewImage.host,
"mediatype" : record.dynamodb.NewImage.mediatype,
"sourcemimtype" : record.dynamodb.NewImage.sourcemimetype,
}
};
ddb.deleteItem(params, function(err, data) {
if (err) {
console.log("my DELETING Error", JSON.stringify(err, null, 2));
} else {
console.log("my DEL Success", JSON.stringify(data, null, 2));
}
});
}
if (record.eventName == 'MODIFY') {
console.log('my MODIFYING RECORD');
var params = {
TableName: 'myplugin_temp',
Item: {
"client" : record.dynamodb.NewImage.client,
"expiration" : record.dynamodb.NewImage.expiration,
"notificationurl" : record.dynamodb.NewImage.notificationurl,
"clientid" : record.dynamodb.NewImage.clientid,
"s3path" : record.dynamodb.NewImage.s3path,
"language" : record.dynamodb.NewImage.language,
"filename" : record.dynamodb.NewImage.filename,
"timecreated" : record.dynamodb.NewImage.timecreated,
"appid" : record.dynamodb.NewImage.appid,
"subtitle" : record.dynamodb.NewImage.subtitle,
"host" : record.dynamodb.NewImage.host,
"mediatype" : record.dynamodb.NewImage.mediatype,
"sourcemimtype" : record.dynamodb.NewImage.sourcemimetype,
}
};
ddb.updateItem(params, function(err,data) {
if (err) {
console.log("my UPDATING Error", JSON.stringify(err, null, 2));
} else {
console.log("my UPDATING Success",JSON.stringify(data, null, 2));
}
});
}
});
//callback(null, `my Successfully processed records.`);
console.log(JSON.stringify(callback, null, 2));
};
Комментарии:
1. Я уничтожил все после копирования функции. Верните содержимое функции обратно. Настройте новую таблицу 1. Создал новую политику и роль из командной строки AWS. И, наконец, смог заставить это работать. Что было не так с другим? Понятия не имею. единственное отличие заключалось в том, что я заблокировал первую попытку до VPC.
Ответ №1:
Ну, некоторые примечания, которые нужно выделить :
-
AWS.SharedIniFileCredentials должен загружать определенный путь пользователя домой. В Linux это будет /home/[user]/.aws/credentials . В то время как функция lambda не имеет доступа к этому системному пути. Другими словами, AWS.SharedIniFileCredentials можно реализовать в системе, в которой у вас есть доступ к домашнему каталогу.
Загрузка учетных данных в Node.js из общего файла учетных данных
Есть два способа настроить разрешение для lambda на доступ к сервисам aws, т.е. dynamodb :
-
Создание роли IAM для lambda и добавление доступа dynamodb к политике. На самом деле он должен попросить вас создать новую политику ролей при создании новой функции lambda из консоли aws.
Как создать политику AWS IAM для предоставления AWS Lambda доступа к таблице Amazon DynamoDB
-
Использование пользовательских ключей IAM, которые вы сделали выше
-
-
Не забудьте ознакомиться с процессом асинхронности и синхронизации на javascript. Например, в вашей лямбда-функции вы пропускаете эту часть :
// it is a promise function that running async process ddb.putItem(params, function(err,data) { ... })
Я бы предпочел предложить изменить код, используя новейший подход, и aws обещает лучшую практику следующим образом :
exports.handler = async (event) => { try { let allTasks = []; event.Records.forEach((record) => { // set params here allTasks.push(ddb.putItem(params).promise()); ... }) if (allTasks.length > 0) { return Promise.all(allTasks).then(results => { console.log(results) }) } return } catch(e) { console.log(e) throw e } }