Hello Lambda

Lambda handler code

まずは、Lambda handlerのコードから書いていきます。

  1. 次のコマンドでLambdaをTypeScriptで記述しやすくするモジュールをインストールします。
    1. npm install --save-dev esbuild@0 @types/aws-lambda aws-sdk
  2. cdk-workshopディレクトリにlambdaディレクトリを作成します。
  3. lambda/hello.tsというファイルを追加し、以下の内容を記述します。
export const handler: AWSLambda.APIGatewayProxyHandler = async (event) => {
  console.log("request:", JSON.stringify(event, undefined, 2));
  return {
    statusCode: 200,
    headers: { "Content-Type": "text/plain" },
    body: `Hello, CDK! You've hit ${event.path}\n`
  };
};

これは、「Hello, CDK! You’ve hit [url path]」というテキストを返す単純なLambda関数です。 HTTPステータスコードとHTTPヘッダーが付加されたHTTPレスポンスとしてユーザーに応答するために、API Gatewayを使用します。

このLambda関数はTypeScriptで実装されていますが、実際のLambda上ではJavaScriptに変換されたコードが動作します。 これは、デプロイ時にはCDKがesbuildでJavaScriptにビルドしてくれるためです。 その他の言語での実装についてはAWS Lambdaのドキュメントを参照してください。

コピー&ペーストは使わずにコードを書いてみましょう

このワークショップでは、コピー&ペーストをするのではなく、実際にCDKのコードを入力することを強く推奨します(通常、入力する量は多くありません)。 これにより、CDKの使い方についてより理解していただけます。 IDEがオートコンプリート、インラインドキュメント、およびタイプセーフに対応しているのがご理解いただけるでしょう。

AWS Lambda関数をスタックに追加する

importステートメントをlib/cdk-workshop-stack.tsの冒頭に挿入し、lambda.Functionをスタックに追加します。

import { Stack, StackProps } from 'aws-cdk-lib';
import { Runtime } from 'aws-cdk-lib/aws-lambda';
import { NodejsFunction } from 'aws-cdk-lib/aws-lambda-nodejs';
import { Construct } from 'constructs';

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

    // AWS Lambdaリソースを定義
    const hello = new NodejsFunction(this, 'HelloHandler', {
      runtime: Runtime.NODEJS_16_X, // 実行環境
      entry: 'lambda/hello.ts', // エントリーファイルはhello.ts
    });
  }
}

注目すべきいくつかの点:

  • この関数はNODEJS_16_X(Nodejs v16.x)ランタイムを使用します。
  • ハンドラーコードは、先程作った lambda ディレクトリからロードされます。 パスは、cdk コマンドが実行されたディレクトリから相対パスです。

コンストラクト(constructs) と コンストラクター(constructors) について

ご覧のとおり、CdkWorkshopStackNodejsFunctionの両方のコンストラクタークラス(およびCDKの他の多くのクラス)は(scope, id, props)という同じような引数を受け取ります。 これは、これらのクラスがすべてコンストラクタであるためです。

コンストラクトはCDKアプリの基本的な構成要素です。 それらは「クラウドコンポーネント」を表現します。クラウドコンポーネントはスコープを介してより高いレベルの抽象化に構築できます。 スコープにはコンストラクトを含めることができ、そのコンストラクトには他のコンストラクトなどを含めることができます。

コンストラクトは常に別のコンストラクトのスコープ内で作成され、作成されたスコープ内で一意でなければならない識別子(id)を持っている必要があります。 したがって、コンストラクト初期化子(コンストラクター)には常に次のシグネチャが必要です。

  1. scope: : 最初の引数には、この構成が作成されるスコープを必ず指定します。 ほとんどすべての場合、現在の コンストラクトスコープ内でコンストラクトを定義することになります。 つまり、通常最初の引数にはthisを渡すだけです。

  2. id : 2番目の引数は、構造のローカルIDです。 これは、同じスコープ内のコンストラクト間で一意である必要があるIDです。 CDKはこのIDを使用して、 このスコープ内で定義された各リソースのCloudFormation 論理IDを計算します。 CDKのIDの詳細については、CDKユーザーマニュアルを参照してください。

  3. props : 最後の(場合によっては不要である場合もある)引数は、初期化プロパティのセットです。 これらは各コンストラクトで固有です。 たとえば、NodejsFunctionコンストラクトはruntimeentryのようなプロパティを受け取ります。 IDEのオートコンプリートまたはオンラインドキュメントを使用して、さまざまなオプションを調べられます。

Diff

コードを保存し、デプロイする前に差分を見てみましょう。

cdk diff

出力は次のようになります。

Stack CdkWorkshopStack
IAM Statement Changes
┌───┬─────────────────────────────────┬────────┬────────────────┬──────────────────────────────┬───────────┐
│   │ Resource                        │ Effect │ Action         │ Principal                    │ Condition │
├───┼─────────────────────────────────┼────────┼────────────────┼──────────────────────────────┼───────────┤
│ + │ ${HelloHandler/ServiceRole.Arn} │ Allow  │ sts:AssumeRole │ Service:lambda.amazonaws.com │           │
└───┴─────────────────────────────────┴────────┴────────────────┴──────────────────────────────┴───────────┘
IAM Policy Changes
┌───┬─────────────────────────────┬────────────────────────────────────────────────────────────────────────────────┐
│   │ Resource                    │ Managed Policy ARN                                                             │
├───┼─────────────────────────────┼────────────────────────────────────────────────────────────────────────────────┤
│ + │ ${HelloHandler/ServiceRole} │ arn:${AWS::Partition}:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole │
└───┴─────────────────────────────┴────────────────────────────────────────────────────────────────────────────────┘
(NOTE: There may be security-related changes not in this list. See https://github.com/aws/aws-cdk/issues/1299)

Resources
[+] AWS::IAM::Role HelloHandler/ServiceRole HelloHandlerServiceRole11EF7C63 
[+] AWS::Lambda::Function HelloHandler HelloHandler2E4FBA4D 

上記のとおり、このコードから AWS::Lambda::Function リソース用のCloudFormationテンプレートを生成しました。 また、ツールキットがハンドラーコードの場所を伝達するためにいくつかのCloudFormationパラメーターを利用しています。

Deploy

次にデプロイをします。

cdk deploy

cdk deploy を実行すると、CloudFormationスタックをデプロイするだけでなく、 初期構築したS3バケットに対して、ローカルの lambda ディレクトリを圧縮後、アップロードしていることがが分かるでしょう。

Lambda関数のテスト

AWS Lambdaコンソールに移動して、Lambda関数をテストしましょう。

  1. AWS Lambdaコンソール を開きます (正しいリージョンにいることを確認してください)。

    Lambda関数が表示されます。

  2. 関数名をクリックして、コンソールを移動します。

  3. テストタブをクリックします。

  4. イベント名testを入力します。

  5. テンプレートリストからAmazon API Gateway AWS Proxyを選択します。

  6. 保存をクリックします。

  7. テストをクリックし、実行が完了するまで待ちます。

  8. 実行結果ペインで詳細を展開すると、出力が表示されます。

👏