Part.1のおさらい
Part1では、主に以下のことを行いました。
- Lambda関数を作成する(SAM)
- Lambda関数をデプロイする(SAM)
- ステートマシンを構成する
- Lambda関数を呼び出す(だけ)
- ステートマシンをデプロイする(SAM)
- ステートマシンを実行する(マネジメントコンソール)
今回は、その続きからはじめてみます。
ここから始める方は、
https://github.com/hito-psv/sam-demo-004
のコードをgit clone
してもらっても大丈夫ですし、Part1からやってみてもらっても構いません。
今回のターゲット
- Lambdaに固定引数を渡してみる
- Lambdaに外部からの引数を渡してみる
- Lambdaにコンテキストオブジェクトを渡してみる
- Lambdaの戻り値を、別のTaskの引数に渡してみる
をターゲットにしてみたいと思います。
Lambda部分については、Part1で作成した「HelloWorld」の関数を少しだけいじって、色々試してみたいと思います。
準備
Lambda関数を修正する
基本的にHelloWorldのままですが、引数の内容を確認するために、CloudWatchに引数の内容を出力する記述だけ追記してみましょう。
hello_world/app.py
はテンプレートから作成されたデフォルトのままになっているので、リファクタリングも含めて、以下のようにしてみます。
import json
import logging
logger = logging.getLogger()
logger.setLevel(logging.INFO)
def lambda_handler(event, context):
logger.info(event)
return {
"statusCode": 200,
"body": json.dumps({
"message": "hello world",
})
}
ビルド・デプロイする
この状態で、sam build
、sam deploy --guided
を実行し、Lambda関数をデプロイしましょう。
Lambdaに固定引数を渡してみる
ステートマシン定義の修正
まずは、固定のパラメータですが、ステートマシンの定義を変更する必要があります。
変更点としては、Parameters
を追加することです。
{
"StartAt": "hello world",
"States": {
"hello world": {
"Type": "Task",
"Resource": "${HelloWorldFunction}",
"Parameters": {
"p1": 100,
"p2": "0123",
"p3": {
"p3-1": 20,
"p3-2": "xyz"
}
},
"End": true
}
}
}
ビルド・デプロイする
この状態で、sam build
、sam deploy --guided
を実行し、デプロイしましょう。
ステートマシンを実行してみる
マネジメントコンソールから、ステートマシンを実行してみましょう。
今回は、ステートマシンの定義に渡すパラメータを固定でセットしているので、入力は適当で構いません。
CloudWatch Logsを確認してみる
ステートマシンから、実行したLambda関数のCloudWatch Logsに遷移できるので、そこからログの中身をチェックしてみましょう。
Lambda関数の第一引数events
に、ステートマシン定義でセットしたパラメータが渡されてきていることが確認できると思います。
Lambdaに外部からの引数を渡してみる
ステートマシン定義の修正
続いて、ステートマシンへの入力値をパラメータに使用するために、ステートマシン定義を修正します。
ポイントは、
- Key部が「.$」で終わっているもののみが、入力値を使用できる
- Value部は「$.」の後ろに、入力パラメータのKey名を指定する
- 入力値を渡すKeyのValue部に「$」とすると、全入力値をパラメータとして渡すことができる
です。では、これらを考慮して修正してみます。
{
"StartAt": "hello world",
"States": {
"hello world": {
"Type": "Task",
"Resource": "${HelloWorldFunction}",
"Parameters": {
"p1.$": $.p1,
"p2.$": "$.p2",
"p3": {
"p3-1": 20,
"p3-2": "xyz"
},
"all.$": "$"
},
"End": true
}
}
}
ビルド・デプロイする
この状態で、sam build
、sam deploy --guided
を実行し、デプロイしましょう。
ステートマシンを実行してみる
マネジメントコンソールから、ステートマシンを実行してみましょう。
今回は、p1、p2を使用するため、入力蘭を以下のように指定してみます。
- p1に、9999数値を指定
- p2に「p2 strings.」という文字列を指定
CloudWatch Logsを確認してみる
では、Lambda関数のCloudWatch Logsを確認してみましょう。
- p1に9999という数値
- p2に「p2 strings.」という文字列
- allに、入力値全て
がセットされていることがわかります。
順序が入れ替わっていますが、Jsonデータとして参照する分には特に問題はありません。
入力値に、パラメータを指定しないとどうなる?
ステートマシン実行時に、
{
"Comment": "Insert your JSON here"
}
のように、ステートマシンの定義で必要としている「p1」や「p2」がないとどうなるかですが、ステートマシンの実行に失敗します。
この場合、Lambda関数を呼び出す前に、ステートマシンでエラー終了となります。
{
"error": "States.Runtime",
"cause": "An error occurred while executing the state 'hello world' (entered at the event id #2). The JSONPath '$.p1' specified for the field 'p1.$' could not be found in the input '{\n \"Comment\": \"Insert your JSON here\"\n}'"
}
Lambdaにコンテキストオブジェクトを渡してみる
ステートマシン定義の修正
同様にステートマシンを修正しますが、その前に、コンテキストオブジェクトとは?という疑問があります。
コンテキストオブジェクトとは、ステートマシンと実行に関する情報をさします。
具体的には、Roleの情報や、実行時間、タスク名などです。
コンテキストオブジェクトをLamnda関数に渡すには、
- Key部が「.$」で終わっているもののみが、入力値を使用できる
- 入力値を渡すKeyのValue部に「$$」を指定する
です。では、これらを考慮して修正してみます。
{
"StartAt": "hello world",
"States": {
"hello world": {
"Type": "Task",
"Resource": "${HelloWorldFunction}",
"Parameters": {
"p1.$": $.p1,
"p2.$": "$.p2",
"p3": {
"p3-1": 20,
"p3-2": "xyz"
},
"all.$": "$",
"context.$": "$$"
},
"End": true
}
}
}
ステートマシンを実行してみる
マネジメントコンソールから、ステートマシンを実行してみましょう。
「p1」「p2」を指定して実行してください。
CloudWatch Logsを確認してみる
では、Lambda関数のCloudWatch Logsを確認してみましょう。
- contextに、コンテキストオブジェクト(と思わしきもの)
がセットされていることがわかります。
Lambdaの戻り値を、別のTaskの引数に渡してみる
最後に、これです。
今回は、HelloWorldのLambda関数を使いまわしてみたいと思います。
Lambda関数の修正
まず、現在のHelloWorldのLambda関数は、以下のような結果を出力します。
{
"statusCode": 200,
"body": "{\"message\": \"hello world\"}"
}
実はこれだとちょっと面倒なことがあって、body
部の結果が文字列データになってしまっているのです。
そこで、Json構造のまま返せるように、Lambda関数をちょっといじりましょう。
単純に、結果を返すときに、余計な文字列化処理を削除するだけでOKです。
import logging
logger = logging.getLogger()
logger.setLevel(logging.INFO)
def lambda_handler(event, context):
logger.info(event)
return {
"statusCode": 200,
"body": {
"message": "hello world",
}
}
ステートマシン定義の修正
今回は、HelloWorldのLambda関数を2回呼び出すようにします。
今回の変更点は、大きく、以下の点です。
- ステート名を「hello world 1|2」の形式に変更
- それに伴い、
StartAt
で最初のステート名をhello world 1
に変更 -
hello world 1
に、ResultPath
、OutputPath
を追加 -
hello world 1
のNext
にhello world 2
を指定 -
hello world 2
を追加
hello_world_1
のResultPath
で、Lambda関数の結果をhello_world_result
というKey名で保持します。
その内容をOutputPath
で、入力内容全体に反映させます。
hello_world_2
では、InputPath
に「$」を指定することで、hello_world_result
を含むhello world 1
への入力値全体を、Lambda関数に渡しています。
{
"StartAt": "hello world 1",
"States": {
"hello world 1": {
"Type": "Task",
"Resource": "${HelloWorldFunction}",
"Parameters": {
"p1.$": $.p1,
"p2.$": "$.p2",
"p3": {
"p3-1": 20,
"p3-2": "xyz"
},
"all.$": "$"
},
"ResultPath": "$.hello_world_result",
"OutputPath": "$",
"Next": "hello world 2"
},
"hello world 2": {
"Type": "Task",
"Resource": "${HelloWorldFunction}",
"InputPath": "$",
"End": true
}
}
}
ステートマシンを実行してみる
マネジメントコンソールから、ステートマシンを実行してみましょう。
「p1」「p2」を指定して実行してください。
まずは、hello world 1
、hello world 2
と2回呼ばれているかを確認しましょう。
CloudWatch Logsを確認してみる
では、Lambda関数のCloudWatch Logsを確認してみましょう。
-
hello world 1
(赤枠)では、従来通りのパラメータ -
hello_world_2
(青枠)では、hello world 1
のパラメータに加え、hello world 1
のレスポンス(hello_world_result
)が付加されたパラメータ
がセットされていることがわかります。
まとめ
今回は、パラメータの受け渡し方の方法や、結果を受け渡していく方法について検証してみました。
「$」の使い方を覚えれば、それほど難しくないかと思います。
次回は、結果による分岐などについて検証してみたいと思います。
サンプルコードリポジトリ