EventBridge input transformerの紹介

AWS

こんにちは、ユウです!

業務でEventBridgeを使ってStep Functionsのステートマシンを起動しているのですが、起動したステートマシンの入力に情報(例:ステートマシンの起動時刻)を入れたい場面がありました。

調べたところ、EventBridgeのinput transformer(入力変換)を使うとそれができそうです。

本記事では、EventBridgeのinput transformerについて紹介します。

ユウ
ユウ

input transformerは色々な用途に使えそうなので、知っておいて損はないと思います

まず、EventBridgeについて説明します。

EventBridgeは、イベントを通じて様々なアプリ同士を簡単に接続できるようにするサービスです。AWSのサービスのほか、独自のアプリケーション、SaaS同士を接続し、イベント駆動型のアプリを簡単に構築できます。

ここで用語を説明します。

  • イベント
    • AWSサービス、独自アプリケーション、SaaS等の環境における変化を意味します。例えば、EC2インスタンスの状態が保留中から実行中に変更されると、Amazon EC2 はイベントを生成します。
  • イベントソース
    • イベントの発生源です。様々なAWSサービス・SaaS・カスタムアプリケーションがイベントソースになり得ます。例えば、イベントがEC2インスタンスの状態の変化の場合、イベントソースはEC2です。
  • ルール
    • イベントを受信し、ターゲットに送信するためのものです。ルールには、イベントパターンとスケジュールがあります。イベントパターンは、設定した検出パターンに一致するイベントを検出し、ターゲットに送信します。スケジュールは、定期的にターゲットを呼び出します。
  • ターゲット
    • イベントを送信するリソースまたはエンドポイントです。
出典:https://docs.aws.amazon.com/ja_jp/eventbridge/latest/userguide/eb-event-bus.html

input transformer

input transformer(入力変換)は、イベントソースからターゲットに渡す入力(イベント)をカスタマイズできる機能です。

イベントにおける値を参照する変数を定義し、その変数を使ってターゲットへの入力を構築できます。

input transformerでは、 「input paths」と「input template」が使われます。以下、これらを説明します。

input paths

input pathsは、変数を定義するのに使われます。JSON pathでイベントの値を参照できます。

まず、イベントソースからの入力は一般に次のようなJSON形式をとります。各フィールドの意味はドキュメントをご参照ください。

{
  "version": "0",
  "id": "UUID",
  "detail-type": "event name",
  "source": "event source",
  "account": "ARN",
  "time": "timestamp",
  "region": "region",
  "resources": [
    "ARN"
  ],
  "detail": {
    JSON object
  }
}

一例を挙げると、EC2からの入力は以下のようになります。

{
  "version": "0",
  "id": "7bf73129-1428-4cd3-a780-95db273d1602",
  "detail-type": "EC2 Instance State-change Notification",
  "source": "aws.ec2",
  "account": "123456789012",
  "time": "2015-11-11T21:29:54Z",
  "region": "us-east-1",
  "resources": [
    "arn:aws:ec2:us-east-1:123456789012:instance/i-abcd1111"
  ],
  "detail": {
    "instance-id": "i-0123456789",
    "state": "RUNNING"
  }
}

input pathsではJSON pathを使って変数を定義します。$.ABCとすることでイベント内のフィールドABCの値を参照できます。以下では、4つの変数timestamp、instance、state、resourceを定義しています。

{
  "instance" : "$.detail.instance-id", 
  "state" : "$.detail.state",
  "resource" : "$.resources[0]",
  "timestamp" : "$.time"
}

input pathsで定義した変数は次に説明するinput templateで使用できます。

input template

input templateは、ターゲットに渡される入力を定義します。

input pathsで定義した変数は<variable>のような形で使うことができます。

input templateは文字列またはJSONです。

例えば、先ほどinput pathsで定義した変数instance等を使ってinput templateを作ると以下のようになります。input templateの他の作成例についてはドキュメントをご参照ください。

# 文字列として構築する場合のinput template
"instance <instance> is in <state>"

# JSONとして構築する場合のinput template
{
  "instance" : <instance>,
  "state": <state>
}

予約語

以下の変数は、input pathsで定義しなくてもinput templateで使用することができます。これらは予約語で、同名の変数はinput pathsで定義できません。

  • aws.events.rule-arn: EventBridgeルールのARN
  • aws.events.rule-name: EventBridge ruleの名前
  • aws.events.event.ingestion-time: EventBridgeがイベントを受け付けた時間(ISO 8601 timestamp)
  • aws.events.event: 元のイベントのペイロード。JSONフィールドの値としてのみ使用可能。
  • aws.events.event.json: 完全な元のイベントのペイロードで、detailフィールドを含む。JSONフィールドの値としてのみ使用可能。

これらの予約後を使ったinput templateの作成例は以下のとおりです。

{
  "instance" : <instance>,
  "state": <state>,
  "ruleArn" : <aws.events.rule-arn>,
  "ruleName" : <aws.events.rule-name>,
  "originalEvent" : <aws.events.event.json>
}

terraformの構文

terraformでinput transformerを使うには次のようにaws_cloudwatch_event_targetリソースで定義します(参考)。

resource "aws_cloudwatch_event_target" "example" {
  arn  = aws_lambda_function.example.arn
  rule = aws_cloudwatch_event_rule.example.id

  input_transformer {
    input_paths = {
      instance = "$.detail.instance",
      status   = "$.detail.status",
    }
    input_template = "\"<instance> is in state <status>\""
  }
}

以上を踏まえ、サンプルコードを紹介します。

以下のサンプルコードでは、EventBridgeルールで定時起動したステートマシンの入力に、定時起動時刻などを入力するようにします。

サンプルコートは以下で公開しています。

GitHub - yiimori2/aws-input-transformer
Contribute to yiimori2/aws-input-transformer development by creating an account on GitHub.

まず、今回は以下のようなシンプルなステートマシンをEventBridgeで起動します。

入力を問わず、Hello, World!を出力するだけのステートマシンです。

コードはこのような感じです。

StartAt: SayHello
States:
    SayHello:
        End: true
        Type: Pass
        Result: "Hello, World!"

このステートマシンをEventBridgeを使って起動します。

その際、input transformerを使って入力をカスタマイズします。

関連するterraformのコードは以下となります。

resource "aws_cloudwatch_event_target" "state_machine_event_target" {
  rule     = aws_cloudwatch_event_rule.state_machine_event_rule.name
  arn      = aws_sfn_state_machine.state_machine_input_transformer.arn
  role_arn = aws_iam_role.eventbridge_state_machine_iam_role.arn
  # ここからinput transformerを定義
  input_transformer {
    # input_paths
    ## 変数を定義
    input_paths = {
      source  = "$.source" # イベントを発生させたサービス
      time   = "$.time"    # イベントを発生したサービスによって指定できるイベントのタイムスタンプ 
      detail = "$.detail"  # イベントに関する情報を含むJSONオブジェクト
    }
    # input_template
    ## ターゲットへの入力を定義
    input_template = <<EOF
{
  "source": <source>,
  "time": <time>,
  "detail": <detail>,
  "ruleName": <aws.events.rule-name>, # 予約語: EventBridge ルールの名前
  "integrationTime": <aws.events.event.ingestion-time> # EventBridgeがイベントを受信した時刻
}
    EOF
  }
}

するとステートマシンの入力は以下のようになります。ステートマシンの入力がカスタマイズできているのがわかります。

要部を拡大すると以下のとおりです。

以上、本記事ではEventBridgeのinput transformerを紹介しました。

本記事が少しでもお役に立てれば幸いです。

プロフィール
この記事を書いた人

30代半ばで未経験でプログラマーに転職し、日々奮闘中です
プログラミング、AI、NLP、キャリア関連などで少しでも役に立てる情報を発信していきます

ユウをフォローする
AWS
ユウをフォローする

コメント

タイトルとURLをコピーしました