AWS
sam
lambda

AWS SAMのコマンドをまとめてみた

はじめに

AWS SAMの各コマンドをhelpを元にまとめてみました。

なお、最新情報は公式ドキュメントを参照してください。

環境

  • Windows 10
  • aws sam (Ver0.5.0)
  • Python 3.6

インストール等

こちらを参照ください。

コマンド組み合わせの一覧

OPTIONSを除いたコマンドの組み合わせは下記です。

コマンド サブコマンド 内容
sam init なし サンプル(雛形)を作成
sam local generate-event Lambdaのイベントパラメータを作成
invoke Lambdaのテスト実行
start-api APIのテスト用ローカルエンドポイントを準備
start-lambda Lambdaのテスト用ローカルエンドポイントを準備
sam validate なし SAMのテンプレートファイルが正しいか検証
sam package なし デプロイ用にパッケージ化
sam deploy なし Lambdaにデプロイ
sam logs なし Lambdaのログを取得

サンプル(雛形)を作成

概要

サンプルアプリケーションの作成を行います。

$ sam init [OPTIONS]

OPTIONS

OPTIONSは下記となります。

OPTIONS 内容
-l, --location TEXT gitでテンプレートとなるファイルを取得する。TEXTにはパスを記述。
-r, --runtime [python3.6, python2.7, python, nodejs6.10, nodejs8.10, nodejs4.3, nodejs, dotnetcore2.0, dotnetcore1.0, dotnetcore, dotnet, go1.x, go, java8, java] Lambdaの言語を指定する。
-o, --output-dir PATH 出力先のフォルダパスを指定する。
-n, --name TEXT プロジェクト名を指定する。この名前のフォルダが作成される。
--no-input プロンプトの入力を無効にしてデフォルトのテンプレート設定を使用する。
--debug デバッグログを表示する。
-h, --help ヘルプを表示する。

使用例

Python3.6でサンプルを作成します。

$ sam init --runtime python3.6 --name my_project_name

ローカル配置

SAMのコマンドではありませんが、必要ライブラリのインストールやbuildフォルダ以下に必要なファイルを集めておきます。

$ pip install -r requirements.txt -t hello_world/build/
$ cp hello_world/*.py hello_world/build/

Lambdaのイベントパラメータを作成

概要

Lambda関数を実行する際のペイロード(実行時の引数)のサンプルを作成できます。
後ほど紹介する「Lambdaのテスト実行」で使用します。

$ sam local generate-event [OPTIONS] COMMANDS [ARGS]...

OPTIONS

OPTIONSは下記となります。

OPTIONS 内容
-h, --help ヘルプを表示する。

COMMANDSとARGS

COMMANDSとARGSは下記となります。

COMMANDS 内容
api API Gatewayのイベントを作成する。
dynamodb DynamoDBのイベントを作成する。
kinesis Kinesisのイベントを作成する。
s3 S3のイベントを作成する。
schedule Scheduleのイベントを作成する。
sns SNSのイベントを作成する。

このうち、S3についてはバケット名なども指定します。

$ sam local generate-event s3 --bucket <bucket> --key <key>

使用例

API Gatewayのイベントを作成します。結果を外部ファイルに保存しておくと便利です。

$ sam local generate-event api > event_api.json

作成したペイロードのbody部分がAPIを叩いた際のペイロードとなります。任意のデータに変更しましょう!

event_api.json(抜粋)
{
    "httpMethod": "POST",
    "body": "{ \"test\": \"body\"}",
}

Lambdaのテスト実行

概要

Lambda関数をローカルで実行することで動作確認を行えます。

Lambda関数を実行する際のペイロードは、stdinでその場で渡すことも可能ですが、予め作成しておくと便利です。

$ sam local invoke [OPTIONS] [FUNCTION_IDENTIFIER]

OPTIONS

OPTIONSは下記となります。

OPTIONS 内容
-e, --event PATH Lambda実行時のイベントファイル(json)を指定する。未指定時は、stdinでjsonを入力する。
-t, --template PATH AWS SAMのテンプレートファイルを指定する。未指定時はtemplate.yamlまたはtemplate.ymlとする。
-n, --env-vars PATH 環境変数を記述したjsonファイルを指定する。
-d, --debug-port TEXT ローカルデバッグ用のポート番号を指定する。(詳細不明。IDEでいい感じにできる?)
--debug-args TEXT デバッガに渡す追加の引数を指定する。
-v, --docker-volume-basedir TEXT Dockerでリモートデバッグをいい感じにする?(詳細不明)
--docker-network TEXT 既存のDockerネットワークに接続する。
-l, --log-file TEXT ログの出力ファイルを指定する。
--skip-pull-image Lambda用の最新Dockerファイルの取得をスキップする。
--profile TEXT AWSの認証プロファイルを指定する。
--debug デバッグログを表示する。
-h, --help ヘルプを表示する。

環境変数ファイルは、例えば下記のようになります。

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

FUNCTION_IDENTIFIER

実行対象となるLambda関数のIDを指定します。template.yamlに記載されています。

例えば、sam initで作成したtemplate.yamlだと、下記のHelloWorldFunctionが該当します。

template.yaml(抜粋)
Resources:
    HelloWorldFunction:
        Type: AWS::Serverless::Function

使用例

「Lambdaのイベントパラメータを作成」で作成したAPI Gatewayのイベントパラメータを使用して、Lambdaをローカル実行します。

$ sam local invoke "HelloWorldFunction" -e event_api.json

うまくいかない場合は、例えば下記のようにするのも手です。

$ echo '{"test": "aaaaa" }' | sam local invoke "HelloWorldFunction"

APIのテスト用ローカルエンドポイントを準備

概要

Lambda関数に対するローカルHTTPサーバを作成することで、API Gatewayを経由した動作確認を行うことができます。

$ sam local start-api [OPTIONS]

OPTIONS

OPTIONSは下記となります。ほぼsam init invokeと同じです。

OPTIONS 内容
--host TEXT ローカルホストまたはIPアドレスを指定する。(デフォルトは127.0.0.1)
-p, --port INTEGER ローカルポート番号を指定する。(デフォルトは3000)
-s, --static-dir TEXT CSS/JavaScript/HTMLなどの静的アセットを指定する。
-t, --template PATH AWS SAMのテンプレートファイルを指定する。未指定時はtemplate.yamlまたはtemplate.ymlとする。
-n, --env-vars PATH 環境変数を記述したjsonファイルを指定する。
-d, --debug-port TEXT ローカルデバッグ用のポート番号を指定する。(詳細不明。IDEでいい感じにできる?)
--debug-args TEXT デバッガに渡す追加の引数を指定する。
-v, --docker-volume-basedir TEXT Dockerでリモートデバッグをいい感じにする?(詳細不明)
--docker-network TEXT 既存のDockerネットワークに接続する。
-l, --log-file TEXT ログの出力ファイルを指定する。
--skip-pull-image Lambda用の最新Dockerファイルの取得をスキップする。
--profile TEXT AWSの認証プロファイルを指定する。
--debug デバッグログを表示する。
--help ヘルプを表示する。

使用例

OPTION無しでも良いのですが、ログを外部出力させてみます。

$ sam local start-api --log-file output-api.log
2018-08-26 00:22:28 Mounting HelloWorldFunction at http://127.0.0.1:3000/hello [GET]
2018-08-26 00:22:28 You can now browse to the above endpoints to invoke your functions. You do not need to restart/reload SAM CLI while working on your functions changes will be reflected instantly/automatically. You only need to restart SAM CLI if you update your AWS SAM template
2018-08-26 00:22:28  * Running on http://127.0.0.1:3000/ (Press CTRL+C to quit)

マウントしているアドレスにアクセスします。方法は何でも良いのですが、ここではcurlコマンドを使用します。

$ curl http://127.0.0.1:3000/hello
PS C:\Users\tdd1> curl http://127.0.0.1:3000/hello

StatusCode        : 200
StatusDescription : OK
Content           : {"message": "hello world", "location": "125.xxx.xxx.xxx"}
RawContent        : HTTP/1.0 200 OK
                    Content-Length: 57
                    Content-Type: application/json
                    Date: Sat, 25 Aug 2018 15:24:25 GMT
                    Server: Werkzeug/0.14.1 Python/3.6.3

                    {"message": "hello world", "location": "125.xxx.xxx.xxx...
Forms             : {}
Headers           : {[Content-Length, 57], [Content-Type, application/json], [Date, Sat, 25 Aug 2018 15:24:25 GMT], [Se
                    rver, Werkzeug/0.14.1 Python/3.6.3]}
Images            : {}
InputFields       : {}
Links             : {}
ParsedHtml        : mshtml.HTMLDocumentClass
RawContentLength  : 57

終了する場合は、CTRL+CでOKです。

ログファイルは下記のようになっています。CloudWatch Logsに残るようなやつですね。

output-api.log
START RequestId: 420dcc0d-107d-4c91-a943-bbf66854fc33 Version: $LATEST
END RequestId: 420dcc0d-107d-4c91-a943-bbf66854fc33
REPORT RequestId: 420dcc0d-107d-4c91-a943-bbf66854fc33 Duration: 783 ms Billed Duration: 800 ms Memory Size: 128 MB Max Memory Used: 22 MB

Lambdaのテスト用ローカルエンドポイントを準備

概要

Lambda関数をテストするためのローカルエンドポイントを作成します。
sam local start-apiと似ていますが、HTTPサーバか否かが異なります。
API Gateway経由で公開しないLambdaはこちらを使えば良いと思います。

ローカルエンドポイントの作成後は、AWS CLIまたはSDKを使用して呼び出しを行います。プログラムから呼び出せるので、自動テストなどを作れます。

$ sam local start-lambda [OPTIONS]

OPTIONS

OPTIONSは下記となります。ほぼsam init invokeと同じです。

OPTIONS 内容
--host TEXT ローカルホストまたはIPアドレスを指定する。(デフォルトは127.0.0.1)
-p, --port INTEGER ローカルポート番号を指定する。(デフォルトは3000)
-t, --template PATH AWS SAMのテンプレートファイルを指定する。未指定時はtemplate.yamlまたはtemplate.ymlとする。
-n, --env-vars PATH 環境変数を記述したjsonファイルを指定する。
-d, --debug-port TEXT ローカルデバッグ用のポート番号を指定する。(詳細不明。IDEでいい感じにできる?)
--debug-args TEXT デバッガに渡す追加の引数を指定する。
-v, --docker-volume-basedir TEXT Dockerでリモートデバッグをいい感じにする?(詳細不明)
--docker-network TEXT 既存のDockerネットワークに接続する。
-l, --log-file TEXT ログの出力ファイルを指定する。
--skip-pull-image Lambda用の最新Dockerファイルの取得をスキップする。
--profile TEXT AWSの認証プロファイルを指定する。
--debug デバッグログを表示する。
--help ヘルプを表示する。

使用例

まずはLambda関数のローカルエンドポイントを作成します。

$ sam local start-lambda --log-file output-lambda.log

AWS CLIで実行

下記コマンドで実行します。ステータスコードが返ってきます。

$ aws lambda invoke --function-name "HelloWorldFunction" --endpoint-url "http://127.0.0.1:3001" --no-verify-ssl out.txt
{
    "StatusCode": 200
}

ログファイルはそれぞれ下記となっています。

output-lambda.log
START RequestId: 915b8e43-d8cf-4cef-8a65-849a9d42e746 Version: $LATEST
END RequestId: 915b8e43-d8cf-4cef-8a65-849a9d42e746
REPORT RequestId: 915b8e43-d8cf-4cef-8a65-849a9d42e746 Duration: 745 ms Billed Duration: 800 ms Memory Size: 128 MB Max Memory Used: 22 MB
out.txt
{"statusCode": 200, "body": "{\"message\": \"hello world\", \"location\": \"125.xxx.xxx.xxx\"}"}

実行時のペイロードを指定することもできます。これらはAWS SAMではなく、AWS CLIの機能になります。詳細は下記を参照してください。

SDKで実行

下記のPythonプログラムでLambdaを実行してみます。

test_lambda_invoke.py
import boto3
from botocore import UNSIGNED
from botocore.client import Config

def main():
    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=30,
                                                retries={'max_attempts': 0}))
    res = lambda_client.invoke(
                            FunctionName="HelloWorldFunction",
                            InvocationType="RequestResponse")
    print(res)

if __name__ == "__main__":
    main()

実行時のコマンドを結果は下記です。

$ python test_lambda_invoke.py
{'ResponseMetadata': {'HTTPStatusCode': 200, 'HTTPHeaders': {'content-type': 'application/json', 'content-length': '96', 'server': 'Werkzeug/0.14.1 Python/3.6.3', 'date': 'Sat, 25 Aug 2018 16:09:20 GMT'}, 'RetryAttempts': 0}, 'StatusCode': 200, 'Payload': <botocore.response.StreamingBody object at 0x03599C70>}

output-lambda.logは似た内容なので割愛します。

SAMのテンプレートファイルが正しいか検証

概要

AWS SAMのテンプレートファイルが正しく作成できているか検証します。ただし、内容の検証ではなくYAMLファイルとしてのフォーマットを検証するだけです。

$ sam validate [OPTIONS]

OPTIONS

OPTIONSは下記となります。

OPTIONS 内容
-t, --template PATH AWS SAMのテンプレートファイルを指定する。未指定時はtemplate.yamlまたはtemplate.ymlとする。
--debug デバッグログを表示する。
--help ヘルプを表示する。

使用例

OKの場合

$ sam validate
2018-08-26 01:16:19 Found credentials in shared credentials file: ~/.aws/credentials
2018-08-26 01:16:19 Starting new HTTPS connection (1): iam.amazonaws.com
D:\xxx\yyy\zzz\template.yaml is a valid SAM Template

NGの場合

意図的にNGのテンプレートファイルを作成し、検証してみます。

template_ng.yaml
#略
Resources:
    HelloWorldFunction:
        Type: AWS::Serverless::Function
        Properties #Remove ':'
            CodeUri: hello_world/build/
            Handler: app.lambda_handler
            Runtime: python3.6
#略

では検証してみましょう。

$ sam validate --template template_ng.yaml
()
yaml.scanner.ScannerError: while scanning a simple key
  in "<unicode string>", line 18, column 9:
            Properties #Remove ':'
            ^
could not find expected ':'
  in "<unicode string>", line 19, column 13:
                CodeUri: hello_world/build/

怒られました。

デプロイ用にパッケージ化

概要

コード類をまとめてS3にアップロードし、CloudFormationでLambdaにデプロイできるSAMテンプレートファイルを生成します。

$ sam package [OPTIONS] [ARGS]...

OPTIONS

OPTIONSは下記となります。

OPTIONS 内容
--template-file テンプレートファイルを指定する。
--output-template-file 作成するデプロイ用のテンプレートファイルを指定する。
--s3-bucket アップロード先のS3バケット名を指定する。
--debug デバッグログを表示する。
--help ヘルプを表示する。

使用例

予めS3バケットを作成しておきます。

$ aws s3 mb s3://mybucket

実行します。バケット名の指定を忘れないようにします。

$ sam package --template-file template.yaml --output-template-file packaged.yaml --s3-bucket mybucket

Lambdaにデプロイ

概要

S3にパッケージ化したものをLambdaにデプロイします。

$ sam deploy [OPTIONS] [ARGS]...

OPTIONS

OPTIONSは下記となります。

OPTIONS 内容
--template-file デプロイに使用するテンプレートファイルを指定する。
--stack-name CloudFormationのスタック名を指定する。
--capabilities ロール作成を明示する。
--debug デバッグログを表示する。
--help ヘルプを表示する。

使用例

実行します。stack-nameは見分けがつく名前にしておきましょう。

$ sam deploy --template-file ./packaged.yaml --stack-name mystack --capabilities CAPABILITY_IAM

少し時間が掛かるので待ちます。

Lambdaのログを取得

概要

Lambdaのログを取得します。

$ sam logs [OPTIONS]

OPTIONS

OPTIONSは下記となります。

OPTIONS 内容
-n, --name TEXT Lambda関数名またはLogicalIDを指定する。
--stack-name TEXT CloudFormation之スタック名を指定する。
--filter TEXT フィルタワードを指定する。
-s, --start-time TEXT 取得するログの開始時刻を指定する。(デフォルトは10分前)
-e, --end-time TEXT 取得するログの終了時刻を指定する。
-t, --tail 最新ログを取得する。(tailコマンド同様)
--debug デバッグログを表示する。
--profile TEXT AWSの認証プロファイルを指定する。
--region TEXT リージョンを指定する。
-h, --help ヘルプを表示する。

使用例

$ sam logs -n HelloWorldFunction --stack-name mystack

他の取得方法は公式ドキュメントを見たほうがわかりやすいです。

参考