2014-12-29 1 views
11

Я нахожусь на AWS и используя AWS SDK for JavaScript in Node.js. Я пытаюсь создать функцию AWS Lambda, и внутри я хочу получить список всех моих экземпляров Amazon EC2, но я просто не могу заставить его работать. Может ли кто-нибудь определить, что я делаю неправильно?Как я могу перечислить все экземпляры Amazon EC2 с помощью Node.js в AWS Lambda?

Вот мой Lambda код функции:

var AWS = require('aws-sdk'); 
AWS.config.region = 'us-west-1'; 

exports.handler = function(event, context) { 
    console.log("\n\nLoading handler\n\n"); 
    var ec2 = new AWS.EC2(); 
    ec2.describeInstances(function(err, data) { 
     console.log("\nIn describe instances:\n"); 
     if (err) console.log(err, err.stack); // an error occurred 
     else  console.log("\n\n" + data + "\n\n"); // successful response 
    }); 
    context.done(null, 'Function Finished!'); 
}; 

И это моя политика (? Я думаю, что это правильно)

{ 
    "Version": "2012-10-17", 
    "Statement": [ 
    { 
     "Effect": "Allow", 
     "Action": [ 
     "logs:*" 
     ], 
     "Resource": "arn:aws:logs:*:*:*" 
    }, 
    { 
    "Effect": "Allow", 
    "Action": [ 
     "ec2:*" 
    ], 
    "Resource": "arn:aws:ec2:*" 
    }, 
    { 
     "Effect": "Allow", 
     "Action": [ 
     "s3:GetObject", 
     "s3:PutObject" 
     ], 
     "Resource": [ 
     "arn:aws:s3:::*" 
     ] 
    } 
    ] 
} 

И если я делаю console.log на 'EC2' Я получить:

{ config: 
    { credentials: 
     { expired: false, 
     expireTime: null, 
     accessKeyId: 'XXXXXXXXXXXXXXXXXX', 
     sessionToken: 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX', 
     envPrefix: 'AWS' }, 
    credentialProvider: { providers: [Object] }, 
    region: 'us-west-1', 
    logger: null, 
    apiVersions: {}, 
    apiVersion: null, 
    endpoint: 'ec2.us-west-1.amazonaws.com', 
    httpOptions: { timeout: 120000 }, 
    maxRetries: undefined, 
    maxRedirects: 10, 
    paramValidation: true, 
    sslEnabled: true, 
    s3ForcePathStyle: false, 
    s3BucketEndpoint: false, 
    computeChecksums: true, 
    convertResponseTypes: true, 
    dynamoDbCrc32: true, 
    systemClockOffset: 0, 
    signatureVersion: 'v4' }, 
    isGlobalEndpoint: false, 
    endpoint: 
    { protocol: 'https:', 
    host: 'ec2.us-west-1.amazonaws.com', 
    port: 443, 
    hostname: 'ec2.us-west-1.amazonaws.com', 
    pathname: '/', 
    path: '/', 
    href: 'https://ec2.us-west-1.amazonaws.com/' } } 

ответ

11

Наиболее вероятной причиной является то, что вы явно завершаете свою функцию лямбда до того, как она завершит вызов EC2 D escribeInstances API.

Причина в том, что Lambda предполагает, что ваш код завершил выполнение, как только вы позвоните context.done(...). И это происходит доconsole.log(... data ...) звонок.

Это странное упорядочение происходит из-за того, как работает NodeJS и как работает AWS SDK для JavaScript. В NodeJS вы никогда не должны блок исполнение. Вызов веб-службы (например, EC2) блокирует выполнение. Поэтому AWS SDK для JavaScript (как и большинство библиотек NodeJS) работает, создавая асинхронный вызов .

Чаще всего, когда у вас есть асинхронный вызов, передать обратного вызова функции к этому вызову. Когда результаты будут готовы, NodeJS выполнит функцию callback.

В вашем коде function(err, data) {...} есть callback функция. Это не выполняется немедленно, но будет запланировано на выполнение, когда NodeJS увидит, что вызов ec2.describeInstances получил свои результаты.

Как только вы график выполнение Вашего обратного вызова, вы звоните context.done(...), который говорит Lambda: я сделал, вы можете убить меня. И он счастливо подчиняется и прерывает вашу функцию, прежде чем вызов EC2 DescribeInstances получит свои данные и передает его на ваш callback.

Как решить проблему?

Ответ должен быть ясен: просто переместить context.done(...) вызов внутри обратного вызова функции, сразу после того, если/иначе блок, содержащий console.log(...data...) вызова:

ec2.describeInstances(function(err, data) { 
    console.log("\nIn describe instances:\n"); 
    if (err) console.log(err, err.stack); // an error occurred 
    else  console.log("\n\n" + data + "\n\n"); // successful response 
    context.done(null, 'Function Finished!'); 
}); 
+0

Спасибо @Bruno. Как вы рекомендуете делать то же самое внутри цикла - например, создавать 10 очередей SQS, вставляя 20 сообщений [batch api существует, кроме того], если я помещаю context.done() внутри цикла, это не означает, что итерация остановка после однократного выполнения (1 затем частичное выполнение) –

Смежные вопросы