简体   繁体   English

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

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

I'm on AWS and using AWS SDK for JavaScript in Node.js .我在 AWS 上并在 Node.js 中使用 AWS SDK for JavaScript I'm trying to build an AWS Lambda function and inside I want to get a list of all my Amazon EC2 instances, but I just can't seem to get it working.我正在尝试构建一个 AWS Lambda 函数,在里面我想获取我所有的 Amazon EC2 实例的列表,但我似乎无法让它工作。 Can anyone spot what I'm doing wrong?谁能发现我做错了什么?

Here is my Lambda function code:这是我的 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!');  
};

And this is my policy (I think it's correct?)这是我的政策(我认为这是正确的?)

{
  "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:::*"
      ]
    }
  ]
}

And if I do a console.log on 'ec2' I get:如果我在'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/' } }

The most likely cause is that you are explicitly terminating your Lambda function before it completes the call to EC2 DescribeInstances API.最可能的原因是您在 Lambda 函数完成对 EC2 DescribeInstances API 的调用之前明确终止了它。

The reason is that Lambda assumes your code has finished executing as soon as you call context.done(...) .原因是 Lambda 假定您的代码在您调用context.done(...)后立即执行完毕。 And this is happening before the console.log(... data ...) call.这发生console.log(... data ...)调用之前。

This weird ordering happens because of how NodeJS works and how the AWS SDK for JavaScript works.之所以会出现这种奇怪的排序,是因为 NodeJS 的工作方式以及 AWS SDK for JavaScript 的工作方式。 In NodeJS you should never block the execution.在 NodeJS 中,你永远不应该阻止执行。 A call to a webservice (such as EC2) would block the execution.对 Web 服务(例如 EC2)的调用会阻止执行。 Therefore the AWS SDK for JavaScript (as well as most NodeJS libraries) works by making an asynchronous call.因此,适用于 JavaScript 的 AWS 开发工具包(以及大多数 NodeJS 库)通过异步调用来工作。

Most often, when you have an asynchronous call, you pass a callback function to that call.大多数情况下,当您进行异步调用时,您会将回调函数传递给该调用。 When the results are ready, NodeJS will execute the callback function.当结果准备好后,NodeJS 会执行回调函数。

In your code, that function(err, data) {...} is the callback function.在您的代码中,该function(err, data) {...}回调函数。 This is not executed immediately, but will be scheduled for execution when NodeJS sees that the ec2.describeInstances call has received the its results.这不会立即执行,而是会在 NodeJS 看到ec2.describeInstances调用已收到其结果时安排执行。

As soon as you schedule the execution of your call back, you are calling context.done(...) , which tells Lambda: I'm done, you can kill me .一旦你安排了回调的执行,你就会调用context.done(...) ,它告诉 Lambda:我完成了,你可以杀了我 And it's happily obeying and interrupting your function, before the EC2 DescribeInstances call receives its data and passes it to your callback function.在 EC2 DescribeInstances 调用接收其数据并将其传递给您的回调函数之前,它很乐意服从并中断您的函数。

How to solve the problem?如何解决问题?

The answer should be clear by now: just move your context.done(...) call to inside your callback function, right after the if/else block containing the console.log(...data...) call:答案现在应该很清楚了:只需将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!');  
});

As of 2019 (October), the given answer didn't help, after digging I found now it is promise based截至 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