AWS Lambda
開発者ガイド

SAM CLI を使用してサーバーレスアプリケーションをローカルでテストする

注記

この機能は、パブリックベータの一部として提供されており、随時変更される場合があります。

AWS SAM はサーバーレスアプリケーションを迅速かつ簡単にデプロイする方法です。これにより、シンプルなテンプレートを記述して関数およびイベントソース (Amazon API Gateway、Amazon S3、Kinesis など) を定義できます。

SAM CLI は、AWS SAM に基づくツールであり、サーバーレスアプリケーションを Lambda ランタイムにアップロードする前にローカルで開発、テスト、および分析するための環境を提供します。SAM CLI では、Linux、Mac、または Microsoft Windows を問わず、AWS ランタイム環境をシミュレートするローカルテスト環境を作成できます。SAM CLI により、Lambda 関数コードをより高速に反復開発できます。詳細については、「SAM CLI によるシンプルなアプリケーションの構築」を参照してください。

SAM CLI は、AWS SAM と連携するため、SAM テンプレートで定義された関数を直接呼び出すことも、API Gateway エンドポイント経由で呼び出すこともできます。SAM CLI の機能を使用して、独自のテスト環境でサーバーレスアプリケーションのパフォーマンスを分析し、必要に応じて更新できます。

SAM CLI には、実行時に SAM アプリケーションモデルの理解を深め、本番ニーズに合わせてアプリケーションを強化して完全に機能する SAM アプリケーションを提供する sam init コマンドも用意されています。詳細については、「Simple App (sam init) の作成 」を参照してください。

以下の例では、SAM CLI を使用するその他の利点をサンプルオペレーションコードで示します。たとえば、次の操作を実行できます。

  • サンプルの関数ペイロード (Amazon S3 イベントなど) を生成する。

    $ sam local generate-event s3 --bucket bucket-name --key key-name > event_file.json
  • Lambda 関数を使用してサンプルの関数ペイロードをローカルでテストする。

    $ sam local invoke function-name -e event_file.json
  • ローカルの API Gateway を生成して HTTP リクエストおよびレスポンスの機能をテストする。ホットリロード機能を使用することで、関数を再起動したり AWS ランタイムにリロードしたりせずにテストおよび反復実行できます。

    $ sam local start-api

    SAM CLI によって、SAM テンプレート内に API イベントソースが定義されている関数があれば自動的に検出され、定義された HTTP パスにマウントされます。次の例では、Ratings 関数が GET リクエストによって ratings.py:handler() /ratings にマウントします。

    Ratings: Type: AWS::Serverless::Function Properties: Handler: ratings.handler Runtime: python3.6 Events: Api: Type: Api Properties: Path: /ratings Method: get

    デフォルトでは、SAM CLI は Proxy との統合を使用して、Lambda 関数からのレスポンスに statusCodeheadersbody のいずれかが含まれるようにします。以下に例を示します。

    // Example of a Proxy Integration response exports.handler = (event, context, callback) => { callback(null, { statusCode: 200, headers: { "x-custom-header" : "my custom header value" }, body: "hello world" }); }

    Lambda 関数が有効な プロキシ統合レスポンスを返さない場合、関数にアクセスすると HTTP 500 (Internal Server Error) レスポンスが返されます。また、SAM CLI は次のエラーログメッセージを表示するため、問題の診断に役立ちます。

    ERROR: Function ExampleFunction returned an invalid response (must include one of: body, headers or statusCode in the response object)
  • メモリの最大使用量や Lambda 関数呼び出しのタイムアウト制限などのラインタイム制約を遵守していることを確認する。

  • AWS Lambda ランタイムログ、および Lambda 関数コード (console.log など) で指定されたカスタマイズされたログ出力を検査する。SAM CLI では、この出力が自動的に表示されます。例を以下に示します。

    START RequestId: 2137da9a-c79c-1d43-5716-406b4e6b5c0a Version: $LATEST 2017-05-18T13:18:57.852Z 2137da9a-c79c-1d43-5716-406b4e6b5c0a Error: any error information END RequestId: 2137da9a-c79c-1d43-5716-406b4e6b5c0a REPORT RequestId: 2137da9a-c79c-1d43-5716-406b4e6b5c0a Duration: 12.78 ms Billed Duration: 100 ms Memory Size: 128 MB Max Memory Used: 29 MB
  • AWS CLI で確定したセキュリティ認証情報を受け入れる。これにより、サーバーレスアプリケーションを構成している AWS のサービスを Lambda 関数でリモートから呼び出すことができます。AWS CLI をまだインストールしていない場合は、「AWS コマンドラインインターフェイスのインストール」を参照してください。

    AWS CLI および SDK と同様に、SAM CLI は次の順序で認証情報を検索します。

    • 環境変数 (AWS_ACCESS_KEY_IDAWS_SECRET_ACCESS_KEY)

    • AWS 認証情報ファイル (Linux、MacOS、Unix の ~/.aws/credentials、または Windows の C:\Users\USERNAME \.aws\credentials)

    • インスタンスプロファイル認証情報 (割り当てられたインスタンスロールで Amazon EC2 を実行している場合)

ランタイムのサポート

SAM CLI は以下の AWS ランタイムをサポートします。

  • node.js 4.3

  • node.js 6.10

  • node.js 8.10

  • python 2.7

  • python 3.6

  • java8

  • go 1.x

  • .NET 2.1

SAM CLI をまだインストールしていない場合は、「SAM CLI のインストール」を参照してください。

SAM CLI の使用開始

SAM CLI には次の CLI オペレーションが含まれます。

  • start-api: すべての Lambda 関数をホストするローカル HTTP サーバーを作成します。ブラウザまたは CLI を使用してアクセスすると、このオペレーションは Docker コンテナをローカルで起動して関数を呼び出します。AWS::Serverless::Function リソースの CodeUri プロパティを読み取り、Lambda 関数コードが含まれているファイルシステムのパスを見つけます。このパスは、プロジェクトのルートディレクトリ (Node.js や Python などの解釈された言語の場合)、コンパイル済みアーティファクトを保存するビルドディレクトリ、または .jar ファイル (Java の場合) です。

    解釈された言語を使用する場合、ローカルな変更は同じ Docker コンテナ内で使用可能になります。このアプローチでは、再デプロイすることなく、Lambda 関数の再呼び出しが可能です。複雑なパッキングサポートを必要とするコンパイル済み言語またはプロジェクトでは、独自のビルドソリューションを実行し、必要なビルドの依存関係ファイルがあるディレクトリを AWS SAM で参照することをお勧めします。

  • invoke: ローカル Lambda 関数を一度呼び出し、呼び出しの完了後に終了します。

    # Invoking function with event file $ sam local invoke "Ratings" -e event.json # Invoking function with event via stdin $ echo '{"message": "Hey, are you there?" }' | sam local invoke "Ratings" # For more options $ sam local invoke --help
  • start-lambda: AWS Lambda サービスのエンドポイントの呼び出しをエミュレートするローカルエンドポイントを開始します。自動テストからその関数を呼び出すことができます。このエンドポイントは、Lambda サービスのエンドポイント呼び出しをエミュレートするため、1 度テストを記述すると、ローカル Lambda 関数、またはデプロイされた Lambda 関数に対して、(変更なしで) テストを実行できます。CI/CD パイプラインのデプロイされた SAM スタックに対しても、同じテストを実行できます。例;

    • ローカル Lambda エンドポイントの開始: AWS SAM テンプレートを含むディレクトリで、次のコマンドを実行して、ローカル Lambda エンドポイントを開始します。

      sam local start-lambda

      このコマンドは、AWS Lambda サービスをエミュレートする http://127.0.0.1:3001 でローカルエンドポイントを開始します。このローカル Lambda エンドポイントに対して、自動テストを実行できます。AWS CLI または SDK を使用して、このエンドポイントに呼び出しを送信すると、リクエストで指定された Lambda 関数がローカルで実行されて、応答が返されます。
    • ローカル Lambda エンドポイントに対して統合テストを実行する: 統合テストでは、AWS SDK を使用して、テストデータを使用して、レスポンスを待機し、レスポンスが期待通りであることをアサートする、Lambda 関数を呼び出せます。ローカルで統合テストを実行するには、InvokeAPI コールを前のステップで開始したローカル Lambda エンドポイントに送信するように AWS SDK を設定する必要があります。以下に示しているのは、Python の例です (その他の言語の AWS SDK 設定も類似しています)。

      import boto3 # Set "running_locally" flag if you are running the integration test locally if running_locally: # Create Lambda SDK client to connect to appropriate Lambda endpoint lambda_client = boto3.client('lambda', endpoint_url="http://127.0.0.1:3001", use_ssl=False, verify=False, config=Config(signature_version=UNSIGNED, read_timeout=0, retries={'max_attempts': 0})) else: lambda_client = boto3.client('lambda') # Invoke your Lambda function as you normally usually do. The function will run # locally if it is configured to do so response = lambda_client.invoke(FunctionName="HelloWorldFunction") # Verify the response assert response == "Hello World"

      このコードは、デプロイされた Lambda 関数を変更せずに実行できます。これを行うには、running_locally フラグを False に設定します。これにより、クラウドで AWS Lambda サービスに接続するように AWS SDK がセットアップされます。

  • generate-event: 疑似サーバーレスイベントを生成します。これらを使用して、Amazon S3、Kinesis、DynamoDB などの非同期イベントに応答する関数をローカルで開発およびテストできます。generate-event オペレーションで使用できるコマンドオプションを以下に示します。

    sam local generate-event NAME: sam local generate-event - Generates Lambda events (e.g. for S3/Kinesis etc) that can be piped to 'sam local invoke' USAGE: sam local generate-event command [command options] [arguments...] COMMANDS: s3 Generates a sample Amazon S3 event sns Generates a sample Amazon SNS event kinesis Generates a sample Amazon Kinesis event dynamodb Generates a sample Amazon DynamoDB event api Generates a sample Amazon API Gateway event schedule Generates a sample scheduled event OPTIONS: --help, -h show help
  • validate: 正式な AWS Serverless Application Model 仕様に照らしてテンプレートを検証します。次に例を示します。

    $ sam validate ERROR: Resource "HelloWorld", property "Runtime": Invalid value node. Valid values are "nodejs4.3", "nodejs6.10", "nodejs8.10", "java8", "python2.7", "python3.6"(line: 11; col: 6) # Let's fix that error... $ sed -i 's/node/nodejs6.10/g' template.yaml $ sam validate Valid!
  • package および deploy: sam package および sam deploy は、AWS CloudFormation の package コマンドおよび deploy コマンドを暗黙で呼び出します。SAM アプリケーションのパッケージングおよびデプロイメントの詳細については、「パッケージ化とデプロイ」を参照してください。

    SAM CLI で package コマンドおよび deploy コマンドを使用する方法は以下のとおりです。

    # Package SAM template $ sam package --template-file sam.yaml --s3-bucket mybucket --output-template-file packaged.yaml # Deploy packaged SAM template $ sam deploy --template-file ./packaged.yaml --stack-name mystack --capabilities CAPABILITY_IAM
  • sam logs: sam logs コマンドを使用して、いくつかのターゲティングとフィルタオプションを含む、コマンドラインからの Lambda 関数によって生成されたログを取得します。詳細とサンプルについては、Lambda 関数ログの取得、末尾表示、フィルタ を参照してください。

SAM CLI によるシンプルなアプリケーションの構築

製品リストの作成、読み取り、更新、および削除を行うシンプルな RESTful API オペレーションを構築するとします。この場合、まず次のディレクトリ構造を作成します。

dir/products.js

dir/template.yaml

template.yaml ファイルは、Lambda 関数を記述する AWS SAM テンプレートです。この関数 1 つで、すべての API リクエストを処理します。

注記

デフォルトでは、start-api コマンドおよび invoke コマンドは template.yaml ファイルを作業ディレクトリで探します。別のディレクトリの template.yaml ファイルを参照する場合は、これらのオペレーションに -t パラメータまたは --template パラメータを追加して、このファイルへの絶対パスまたは相対パスを渡します。

template.yaml ファイルに以下の内容をコピーして貼り付けます。

AWSTemplateFormatVersion : '2010-09-09' Transform: AWS::Serverless-2016-10-31 Description: My first serverless application. Resources: Products: Type: AWS::Serverless::Function Properties: Handler: products.handler Runtime: nodejs6.10 Events: ListProducts: Type: Api Properties: Path: /products Method: get CreateProduct: Type: Api Properties: Path: /products Method: post Product: Type: Api Properties: Path: /products/{product} Method: any

前の例では、以下の RESTful API エンドポイントを設定します。

  • /products への POST リクエストで新しい製品を作成します。

  • /products への GET リクエストですべての製品を一覧表示します。

  • /products/{product} への GETPOST、または DELETE リクエストで製品の読み取り、更新、または削除を行います。

次に、以下のコードをコピーして products.js ファイル内に貼り付けます。

'use strict'; exports.handler = (event, context, callback) => { let id = (event.pathParameters || {}).product || false; switch(event.httpMethod){ case "GET": if(id) { callback(null, {body: "This is a READ operation on product ID " + id}); return; } callback(null, {body: "This is a LIST operation, return all products"}); break; case "POST": callback(null, {body: "This is a CREATE operation"}); break; case "PUT": callback(null, {body: "This is an UPDATE operation on product ID " + id}); break; case "DELETE": callback(null, {body:"This is a DELETE operation on product ID " + id}); break; default: // Send HTTP 501: Not Implemented console.log("Error: unsupported HTTP method (" + event.httpMethod + ")"); callback(null, { statusCode: 501 }) } }

start-api コマンドを呼び出して API オペレーションのローカルコピーを起動します。

$ sam local start-api 2017/05/18 14:03:01 Successfully parsed template.yaml (AWS::Serverless-2016-10-31) 2017/05/18 14:03:01 Found 1 AWS::Serverless::Function 2017/05/18 14:03:01 Mounting products.handler (nodejs6.10) at /products [POST] 2017/05/18 14:03:01 Mounting products.handler (nodejs6.10) at /products/{product} [OPTIONS GET HEAD POST PUT DELETE TRACE CONNECT] 2017/05/18 14:03:01 Mounting products.handler (nodejs6.10) at /products [GET] 2017/05/18 14:03:01 Listening on http://localhost:3000 You can now browse to the above endpoints to invoke your functions. You do not need to restart/reload while working on your functions, changes will be reflected instantly/automatically. You only need to restart if you update your AWS SAM template.

次に、ブラウザまたは CLI を使用して API エンドポイントをローカルでテストできます。

$ curl http://localhost:3000/products "This is a LIST operation, return all products" $ curl -XDELETE http://localhost:3000/products/1 "This is a DELETE operation on product ID 1"

ローカルなログ記録

invoke コマンドおよび start-api コマンドを使用して、Lambda 関数の呼び出しのログをファイルにパイプできます。このアプローチは、SAM CLI に対して自動テストを実行し、分析用のログを取得する場合に便利です。次に例を示します。

$ sam local invoke --log-file ./output.log

環境変数ファイルの使用

Lambda 関数で Environment Variables を使用すると、SAM CLI は invoke コマンドと start-api コマンドの両方に --env-vars 引数を渡します。この引数では、関数に定義されている環境変数の値がある JSON ファイルを使用できます。JSON ファイルの構造は次のようになります。

{ "MyFunction1": { "TABLE_NAME": "localtable", "BUCKET_NAME": "testBucket" }, "MyFunction2": { "TABLE_NAME": "localtable", "STAGE": "dev" }, }

次に、以下のコマンドを使用して JSON ファイルにアクセスします。

$ sam local start-api --env-vars env.json

シェル環境の使用

シェル環境で定義された変数は、Lambda 関数の変数にマッピングされると、Docker コンテナに渡されます。シェル変数は関数からグローバルにアクセスできます。たとえば、2 つの関数として MyFunction1 および MyFunction2 があり、どちらにも TABLE_NAME という変数があるとします。この場合、シェル環境を通じて提供される TABLE_NAME の値は両方の関数で使用できます。

次のコマンドは、両方の関数で TABLE_NAME の値を myTable に設定します。

$ TABLE_NAME=mytable sam local start-api

注記

柔軟性を増すために、シェル変数と組み合わせて環境変数を保持する外部 JSON ファイルを使用できます。変数が両方の場所に定義されている場合、外部ファイルの変数によってシェルバージョンが上書きされます。以下は優先順位 (最高から最低) です。

  • 環境変数ファイル

  • シェル環境

  • SAM テンプレート内のハードコードされた値

SAM CLI でのデバッグ

sam local invoke および sam local start-api は、いずれも関数のローカルデバッグをサポートします。デバッグサポートを有効にして SAM CLI を実行するには、コマンドラインで --debug-port または -d を指定します。

# Invoke a function locally in debug mode on port 5858 $ sam local invoke -d 5858 function logical id # Start local API Gateway in debug mode on port 5858 $ sam local start-api -d 5858

注記

sam local start-api を使用する場合、ローカル API Gateway はすべての Lambda 関数を公開します。ただし、指定できるデバッグポートは 1 つのみであるため、一度に 1 つの関数のみデバッグできます。

複雑なパッケージングサポートを必要とするコンパイル済み言語またはプロジェクトでは、独自のビルドソリューションを実行し、必要なビルドの依存関係ファイルがあるディレクトリを AWS SAM で参照することをお勧めします。次の IDE のいずれかを使用することもできます。

Python で記述された関数のデバッグ

Node.js、.NET や Java とは異なり、Python では Lambda 関数コードでリモートデバッグを有効にする必要があります。Python ランタイム (2.7 または 3.6) のいずれかを使用する関数に対して (上述の --debug-port オプションまたは -d オプションを使用して) デバッグを有効にすると、SAM CLI はそのポートを通じてホストマシンから Lambda コンテナへのマッピングを行います。リモートデバッグを有効にするには、remote-pdb などの Python パッケージを使用します。

重要

ホストの設定時に、デバッガーはコードでリスンするため、127.0.0.1 ではなく 0.0.0.0 を必ず使用します。

Lambda 関数ログの取得、末尾表示、フィルタ

トラブルシューティングを簡単にするため、SAM CLI には、コマンドラインからの Lambda 関数によって生成されたログを取得する sam logs というコマンドがあります。ターミナルでログを出力することに加えて、このコマンドにはバグをすばやく見つけるためのさまざまな機能があります。

注記

このコマンドは、SAM を使用してデプロイするものだけでなく、AWS Lambda 関数すべてに機能します。

  • CloudFormation スタックの使用: 機能が AWS CloudFormation スタックの一部である場合、関数の LogicalID を使用してログを取得できます。

    sam logs -n HelloWorldFunction --stack-name mystack
  • Lambda 関数名の使用: 関数名を使用してログを取得することもできます。

    sam logs -n mystack-HelloWorldFunction-1FJ8PD
  • ログ末尾: 新しいログを待機する --tail option を追加して、新しいログが生成されると表示します。これは、デプロイ中または実稼働上の問題のトラブルシューティングにかなり役立ちます。

    sam logs -n HelloWorldFunction --stack-name mystack --tail
  • 指定時間範囲のログの表示: -s および -e オプションを使用して、指定した時間範囲のログを表示できます。

    sam logs -n HelloWorldFunction --stack-name mystack -s '10min ago' -e '2min ago'
  • ログのフィルタ: --filter オプションを使用して、一致する語句、フレーズ、または値をログイベントですばやく検索します。

    sam logs -n HelloWorldFunction --stack-name mystack --filter "error"

    出力で、SAM CLI は「error」という単語のすべての出現箇所に下線を引くので、ログ出力内のフィルタキーワードを簡単に見つけることができます。

  • ログのフィルタ: --filter オプションを使用して、一致する語句、フレーズ、または値をログイベントですばやく検索します。

    sam logs -n HelloWorldFunction --stack-name mystack --filter "error"

    出力で、SAM CLI は「error」という単語のすべての出現箇所に下線を引くので、ログ出力内のフィルタキーワードを簡単に見つけることができます。

  • エラーのハイライト: Lambda 関数がクラッシュするか、タイムアウトすると、SAM CLI はタイムアウトメッセージを赤色で強調表示します。これにより、ログ出力の巨大なストリーム内でタイムアウトしている特定の実行を簡単に見つけることができます。

  • JSON 整形表示: ログメッセージが JSON 文字列で出力される場合、SAM CLI は JSON を視覚的に解析して理解できるように、SAM CLI は自動的に JSON を整形表示します。