SAM を使って CDK + Typescript で実装した Lambda をローカル環境で実行する

2022.02.04

CDK Dayを観ていたところSAM を使った CDK のローカル環境でのテスト方法が紹介されていたのでドキュメントを読みながら実際に使ってみました。

CDK Day ではsam-beta-cdkと呼ばれていましたが、ドキュメントを確認したところ SAM CLI と記述があったのでプライベートプレビュー時からパブリックプレビューになった段階で名称が変更された可能性があります。記事を執筆した段階で日本語ドキュメントはまだ最新ではなかったため英語のドキュメントを参照しながら進めました。

また、AWS SAMを使ったCDKのローカル環境での利用は2022.02.4現在パブリックプレビュー中なので今後後方互換性の無い変更が加えられる可能性があることにご注意ください。

前準備

CDK をローカルでテストするには AWS CDK、パブリックプレビューバージョンの AWS SAM CLI, Docker がインストールされている必要があります。

本記事では CDK のリソース定義と Lambda の記述には全て Typescript を使います。

tsc --version
Version 4.4.3

AWS CDK をインストール

npm install -g aws-cdk
cdk --version
2.10.0 (build e5b301f)

SAM をインストール

brew tap aws/tap
brew install aws-sam-cli
sam --version
SAM CLI, version 1.37.0

Docker をインストール

以下のページから Docker をインストールしてください。 Image の Pull は SAM がやってくれるのでマシンにインストールされていれば OK です。

Get Docker

テストする CDK プロジェクトの作成

新規 CDK プロジェクトを作成します。言語は Typescript を指定します。

mkdir cdk-sam-example
cd cdk-sam-example
cdk init app --language typescript

Lambda のリソースを追加

lib/cdk-sam-example-stack.tsを以下のコードに置き換えます。

import {Stack, StackProps} from "aws-cdk-lib";
import {Construct} from "constructs";
import * as lambda from "aws-cdk-lib/aws-lambda-nodejs";

export class CdkSamExampleStack extends Stack {
  constructor(scope: Construct, id: string, props?: StackProps) {
    super(scope, id, props);

    new lambda.NodejsFunction(this, "MyFunction", {
      entry: "lambda/hello.ts", // accepts .js, .jsx, .ts, .tsx and .mjs files
      handler: "handler", // defaults to 'handler'
    });
  }
}

Lambda を作成

mkdir lambda
cd lambda
touch hello.ts

Hello を返すだけの Lambda を作成します。

hello.ts

export const handler = async function (event, context) {
  return "HELLO!";
};

CDK をビルドする

以下のコマンドで CDK をビルドします。TS で記述したソースコードもここでトランスパイルしてくれます。 次に実行するsam localコマンドはここでビルドしたCloudFormationリソースを参照するため、sam localコマンドを実行する前には忘れずにsynthコマンドを実行しましょう。

cdk synth --no-staging

...
asset-output/index.js  1.4kb
⚡ Done in 88ms

sam local コマンドで Lambda をローカル実行

先ほどビルドが完了した Lambda をローカル環境で実行してみます。sam local コマンドに関数名と Stack 名を指定して実行します。

sam local invoke MyFunction --no-event -t ./cdk.out/CdkSamExampleStack.template.json

Invoking index.handler (nodejs14.x)
Skip pulling image and use local one: public.ecr.aws/sam/emulation-nodejs14.x:rapid-1.37.0-x86_64.

Mounting /src/cdk-sam-example/cdk.out/asset.82676b9ce25717685c203f944 as /var/task:ro,delegated inside runtime container
START RequestId: 667e3a88-0c5e-4ccb-a515 Version: $LATEST
END RequestId: 667e3a88-0c5e-4ccb-a515
REPORT RequestId: 667e3a88-0c5e-4ccb-a515  Init Duration: 1.13 ms  Duration: 924.19 ms     Billed Duration: 925 ms Memory Size: 128 MB     Max Memory Used: 128 MB
"HELLO!"%

Docker が起動して Lambda が実行され、HELLO!が出力されました。

References