簡體   English   中英

如何在 AWS Lambda 中使用 Node.js 列出我的所有 Amazon EC2 實例?

[英]How can I list all my Amazon EC2 instances using Node.js in AWS Lambda?

我在 AWS 上並在 Node.js 中使用 AWS SDK for JavaScript 我正在嘗試構建一個 AWS Lambda 函數,在里面我想獲取我所有的 Amazon EC2 實例的列表,但我似乎無法讓它工作。 誰能發現我做錯了什么?

這是我的 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:::*"
      ]
    }
  ]
}

如果我在'ec2'上執行console.log,我會得到:

{ 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/' } }

最可能的原因是您在 Lambda 函數完成對 EC2 DescribeInstances API 的調用之前明確終止了它。

原因是 Lambda 假定您的代碼在您調用context.done(...)后立即執行完畢。 這發生console.log(... data ...)調用之前。

之所以會出現這種奇怪的排序,是因為 NodeJS 的工作方式以及 AWS SDK for JavaScript 的工作方式。 在 NodeJS 中,你永遠不應該阻止執行。 對 Web 服務(例如 EC2)的調用會阻止執行。 因此,適用於 JavaScript 的 AWS 開發工具包(以及大多數 NodeJS 庫)通過異步調用來工作。

大多數情況下,當您進行異步調用時,您會將回調函數傳遞給該調用。 當結果准備好后,NodeJS 會執行回調函數。

在您的代碼中,該function(err, data) {...}回調函數。 這不會立即執行,而是會在 NodeJS 看到ec2.describeInstances調用已收到其結果時安排執行。

一旦你安排了回調的執行,你就會調用context.done(...) ,它告訴 Lambda:我完成了,你可以殺了我 在 EC2 DescribeInstances 調用接收其數據並將其傳遞給您的回調函數之前,它很樂意服從並中斷您的函數。

如何解決問題?

答案現在應該很清楚了:只需將context.done(...)調用移到回調函數內部,就在包含console.log(...data...)調用的 if/else 塊之后:

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!');  
});

截至 2019 年(10 月),給定的答案沒有幫助,挖掘后我發現現在它是基於承諾的

exports.handler = async function(event) {
  const promise = new Promise(function(resolve, reject) {
      //your logic, goes here at the end just call resolve 
      resolve("data you want to return"); // here lamda exits 
    })
  return promise;// lamda does not  exits here, it waits for to resolve
}
  let data = await ec2.describeInstances();
  return data;

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM