[AWS SAM] Lambda层的定义(nodejs)

为了达到的结果或目标。

在上一篇文章中,我们使用了cfn-response模块,但它只支持内联实现,不够方便。因此,我们需要将它作为一个Layer进行实施。

文件结构

lambda-layer/
 ├─ layers/
 │    └─ cfn-response-layer/
 │              └─ nodejs/
 │                   ├─ node_modules/  # [npm i cfn-response] で生成
 │                   ├─ cfn-response/
 │                   │       ├─ package.json # [npm init] で生成
 │                   │       └─ index.js  # Layerとして提供する機能
 │                   │
 │                   ├─ package.json
 │                   └─ package-lock.json  # [npm i cfn-response] で生成
 
 └─ template.yaml # SAMテンプレート

※nodejs文件夹名称不可更改
※index.js文件可以更改名称,但如果更改为其他名称,则在执行npm init时需要指定文件名

山姆的模板

  CfnResponse:
    Type: AWS::Serverless::LayerVersion
    Properties:
      LayerName: !Sub ${RootStackName}_cfn-response
      ContentUri: layers/cfn-response-layer
      CompatibleRuntimes:
        - nodejs12.x
      RetentionPolicy: Delete

在提供层功能方面,决定将其放置在nodejs文件夹中,
对于ContentUri,请指定路径到前一个目录。

cfn-response 模块的实现

index.js 索引.js

在index.js中实现cfn-response模块的功能
复制github上公开的cfn-response模块代码
提供SUCCESS和FAILED的定义值以及send函数

const https = require('https');
const url = require('url');

module.exports = {
  SUCCESS: 'SUCCESS',
  FAILED: 'FAILED',
  send(
    event,
    context,
    responseStatus,
    responseData,
    physicalResourceId,
    noEcho,
  ) {
    return new Promise((resolve, reject) => {
      const responseBody = JSON.stringify({
        Status: responseStatus,
        Reason: `See the details in CloudWatch Log Stream: ${context.logStreamName}`,
        PhysicalResourceId: physicalResourceId || context.logStreamName,
        StackId: event.StackId,
        RequestId: event.RequestId,
        LogicalResourceId: event.LogicalResourceId,
        NoEcho: noEcho || false,
        Data: responseData,
      });

      console.log('Response body:\n', responseBody);

      const parsedUrl = url.parse(event.ResponseURL);
      const options = {
        hostname: parsedUrl.hostname,
        port: 443,
        path: parsedUrl.path,
        method: 'PUT',
        headers: {
          'content-type': '',
          'content-length': responseBody.length,
        },
      };

      const request = https.request(options, response => {
        console.log(`Status code: ${response.statusCode}`);
        console.log(`Status message: ${response.statusMessage}`);
        resolve(context.done());
      });

      request.on('error', error => {
        console.log(`send(..) failed executing https.request(..): ${error}`);
        reject(context.done(error));
      });

      request.write(responseBody);
      request.end();
    });
  },
};

nodejs/cfn-response/package.json的中文翻译:

在nodejs/cfn-response/的目录下运行npm init
如果全部选择默认值,将会生成以下的package.json文件

{
  "name": "cfn-response",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC"
}

nodejs/package.json可以在此处找到。

仅使用内容{}创建package.json文件
当执行npm install <包名称>,将会添加附加内容

node_modules和package-lock.json

在nodejs文件夹及其子文件夹中运行npm i cfn-response命令会生成index.js文件。该文件使用https和url包,因为这些是nodejs的标准模块,所以无需安装。

使用Layer

SAM模板

  ApplyNotificationFunction:
    Type: AWS::Serverless::Function
    Properties:
      FunctionName: !Sub ${RootStackName}-ApplyNotificationFunction
      CodeUri: handlers
      Role: !GetAtt 'ApplyNotificationFunctionRole.Arn'
      Layers:
        - !Ref CfnResponse  # 先ほどSAMテンプレートで定義したLayerを参照

code

const cfnResponse = require('cfn-response');

exports.handler = async (event, context) => {
  try {
    if (event.RequestType !== 'Create') {
      await cfnResponse.send(event, context, cfnResponse.SUCCESS);
      return;
    }
    ...

bannerAds