0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

[AWS SAM] Lambda Layerの定義(nodejs)

Last updated at Posted at 2020-11-18

目的

前回記事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した際にファイル名の指定が必要

SAMテンプレート

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

Layerとして提供する機能はnodejsフォルダに入れることが決められているので、
ContentUriには、その1個手前までのパスを指定

cfn-response モジュール実装

index.js

index.jsにcfn-response モジュールの機能を実装する
githubで公開されているcfn-response モジュールのコードを基本コピペする
SUCCESS, FAILEDの定義値と、send関数を提供する

index.js
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が生成される

nodejs/cfn-response/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内でhttpsurlパッケージを使用しているが、これらはnodejsの標準モジュールのためインストールは不要

Layerの使用

SAMテンプレート

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

コード

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

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

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?