繁体   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