LoginSignup
2
0

More than 3 years have passed since last update.

[AWS] Step Functionsで遊んでみる(SAM + Lambda) Part.2(パラメータ編)

Last updated at Posted at 2020-08-16

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はテンプレートから作成されたデフォルトのままになっているので、リファクタリングも含めて、以下のようにしてみます。

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 buildsam deploy --guidedを実行し、Lambda関数をデプロイしましょう。

Lambdaに固定引数を渡してみる

ステートマシン定義の修正

まずは、固定のパラメータですが、ステートマシンの定義を変更する必要があります。
変更点としては、Parametersを追加することです。

step_functions/state_machine.json
{
    "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 buildsam deploy --guidedを実行し、デプロイしましょう。

ステートマシンを実行してみる

マネジメントコンソールから、ステートマシンを実行してみましょう。
今回は、ステートマシンの定義に渡すパラメータを固定でセットしているので、入力は適当で構いません。

sf1.png

CloudWatch Logsを確認してみる

ステートマシンから、実行したLambda関数のCloudWatch Logsに遷移できるので、そこからログの中身をチェックしてみましょう。

cw1.png

Lambda関数の第一引数eventsに、ステートマシン定義でセットしたパラメータが渡されてきていることが確認できると思います。

Lambdaに外部からの引数を渡してみる

ステートマシン定義の修正

続いて、ステートマシンへの入力値をパラメータに使用するために、ステートマシン定義を修正します。
ポイントは、

  • Key部が「.$」で終わっているもののみが、入力値を使用できる
  • Value部は「$.」の後ろに、入力パラメータのKey名を指定する
  • 入力値を渡すKeyのValue部に「$」とすると、全入力値をパラメータとして渡すことができる

です。では、これらを考慮して修正してみます。

step_functions/state_machine.json
{
    "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 buildsam deploy --guidedを実行し、デプロイしましょう。

ステートマシンを実行してみる

マネジメントコンソールから、ステートマシンを実行してみましょう。
今回は、p1、p2を使用するため、入力蘭を以下のように指定してみます。

sf2.png

  • p1に、9999数値を指定
  • p2に「p2 strings.」という文字列を指定

CloudWatch Logsを確認してみる

では、Lambda関数のCloudWatch Logsを確認してみましょう。

  • p1に9999という数値
  • p2に「p2 strings.」という文字列
  • allに、入力値全て

がセットされていることがわかります。
順序が入れ替わっていますが、Jsonデータとして参照する分には特に問題はありません。

cw2.png

入力値に、パラメータを指定しないとどうなる?

ステートマシン実行時に、

{
    "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部に「$$」を指定する

です。では、これらを考慮して修正してみます。

step_functions/state_machine.json
{
    "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に、コンテキストオブジェクト(と思わしきもの)

がセットされていることがわかります。

cw3.png

Lambdaの戻り値を、別のTaskの引数に渡してみる

最後に、これです。
今回は、HelloWorldのLambda関数を使いまわしてみたいと思います。

Lambda関数の修正

まず、現在のHelloWorldのLambda関数は、以下のような結果を出力します。

{
  "statusCode": 200,
  "body": "{\"message\": \"hello world\"}"
}

実はこれだとちょっと面倒なことがあって、body部の結果が文字列データになってしまっているのです。
そこで、Json構造のまま返せるように、Lambda関数をちょっといじりましょう。
単純に、結果を返すときに、余計な文字列化処理を削除するだけでOKです。

hello_world/app.py
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に、ResultPathOutputPathを追加
  • hello world 1Nexthello world 2を指定
  • hello world 2を追加

hello_world_1ResultPathで、Lambda関数の結果をhello_world_resultというKey名で保持します。
その内容をOutputPathで、入力内容全体に反映させます。
hello_world_2では、InputPathに「$」を指定することで、hello_world_resultを含むhello world 1への入力値全体を、Lambda関数に渡しています。

step_functions/state_machine.json
{
  "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 1hello world 2と2回呼ばれているかを確認しましょう。

sf5.png

CloudWatch Logsを確認してみる

では、Lambda関数のCloudWatch Logsを確認してみましょう。

  • hello world 1(赤枠)では、従来通りのパラメータ
  • hello_world_2(青枠)では、hello world 1のパラメータに加え、hello world 1のレスポンス(hello_world_result)が付加されたパラメータ

がセットされていることがわかります。

cw5.png

まとめ

今回は、パラメータの受け渡し方の方法や、結果を受け渡していく方法について検証してみました。
「$」の使い方を覚えれば、それほど難しくないかと思います。

次回は、結果による分岐などについて検証してみたいと思います。

サンプルコードリポジトリ

2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0