如何使用适用于JavaScript的AWS开发工具包动态创建内联Lambda?

时间:2019-03-18 14:19:44

标签: node.js amazon-web-services aws-lambda aws-sdk

我需要以编程方式从另一个Lambda创建一个简单的Lambda。

这可以通过CloudFormation实现:

MyLambda:
  Type: AWS::Lambda::Function
  Properties:
    FunctionName: my-lambda
    Handler: index.handler
    Runtime: nodejs8.10
    Role: !GetAtt MyRole.Arn
    Code:
      ZipFile: >
        exports.handler = event => console.log('EVENT', event)

我想以编程方式以相同的方式创建Lambda。

当我将Lambda代码打包到一个zip文件中并上传包含Lambda代码的zip时,一切正常:

const lambda = new Lambda({apiVersion: '2015-03-31'});
...
await lambda.createFunction({
    FunctionName: 'my-lambda',
    Handler: 'index.handler',
    Runtime: 'nodejs8.10',
    Role: role.Role.Arn,
    Code: {
        ZipFile: fs.readFileSync('my-lambda.zip')
    }
}).promise();

但是将Lambda代码写入文件并随后进行压缩是很多样板代码。

如果我尝试将Lambda代码设置为内联:

...
Code: {
    ZipFile: "exports.handler = event => console.log('EVENT', event)"
}

我收到预期的错误:

  

失败:无法解压缩上传的文件。请检查您的文件,然后尝试再次上传。

有没有一种方法如何从另一个Lambda动态创建内联Lambda函数,类似于顶部提到的CloudFormation“ hack”?

编辑:该问题的重点在于动态创建代码,而无需首先压缩它。

2 个答案:

答案 0 :(得分:0)

TLDR 代码作为部署程序包(Zip文件)上传到Lambda。因此,您可以动态编写新的功能代码,但是在将其传递给lambda.createFunction之前,仍然需要动态创建Deployment Package zip。

其他信息: 在Lambda API文档中,Code元素必须是FunctionCode对象。带有FunctionCode对象的选项是指定本地Deployment Package zip文件,或者在s3上为Deployment Package zip文件指定位置。

FunctionCode对象参考:https://docs.aws.amazon.com/lambda/latest/dg/API_FunctionCode.html

语法:

"Code": { 
      "S3Bucket": "string",
      "S3Key": "string",
      "S3ObjectVersion": "string",
      "ZipFile": blob
   }

来源:https://docs.aws.amazon.com/lambda/latest/dg/API_CreateFunction.html

请记住一些Lambda部署程序包限制(撰写本文时的值):

  1. 如果直接将zip文件作为blob上传,则该文件的大小应小于50 MB。
  2. 如果大于50 MB,则需要先上传到s3,然后指定位置。
  3. 解压缩后的总大小仍需小于250 MB。

Lambda限制参考:https://docs.aws.amazon.com/lambda/latest/dg/limits.html

答案 1 :(得分:0)

我认为aws-cdk是一个不错的选择。它从javascript或打字稿生成cloudformation,并将代码行减少到最少。

在您的主要lambda项目中

npm i @aws-cdk/aws-lambda --save-exact

然后,您需要在/ tmp中创建目录,并使用node_cmd

从节点外壳运行cdk init

然后,您将让lambda将cdk Lambda模板导出到/tmp/output.js(类似于下面的内容)(我假设这是您想要的内联部分)

import lambda = require('@aws-cdk/aws-lambda');    
const fn = new lambda.Function(this, 'MyFunction', {
    runtime: lambda.Runtime.NodeJS810,
    handler: 'index.handler',
    code: lambda.Code.inline('exports.handler = function(event, ctx, cb) { return cb(null, "hello ttulka"); }')
});

然后,您需要使用node_cmd从节点外壳运行cdk --app 'node /tmp/output.js' synth