Как вы устраняете проблему с триггером Dynamodb «ПРОБЛЕМА: сбой вызова функции» или Lambda «Недостающие учетные данные в конфигурации»?

#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:

Ну, некоторые примечания, которые нужно выделить :

  1. AWS.SharedIniFileCredentials должен загружать определенный путь пользователя домой. В Linux это будет /home/[user]/.aws/credentials . В то время как функция lambda не имеет доступа к этому системному пути. Другими словами, AWS.SharedIniFileCredentials можно реализовать в системе, в которой у вас есть доступ к домашнему каталогу.

    Загрузка учетных данных в Node.js из общего файла учетных данных

    Есть два способа настроить разрешение для lambda на доступ к сервисам aws, т.е. dynamodb :

  2. Не забудьте ознакомиться с процессом асинхронности и синхронизации на 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
      }
    }