こんにちは、ユウです!
業務でEventBridgeを使ってStep Functionsのステートマシンを起動しているのですが、起動したステートマシンの入力に情報(例:ステートマシンの起動時刻)を入れたい場面がありました。
調べたところ、EventBridgeのinput transformer(入力変換)を使うとそれができそうです。
本記事では、EventBridgeのinput transformerについて紹介します。
input transformerは色々な用途に使えそうなので、知っておいて損はないと思います
EventBridge
まず、EventBridgeについて説明します。
EventBridgeは、イベントを通じて様々なアプリ同士を簡単に接続できるようにするサービスです。AWSのサービスのほか、独自のアプリケーション、SaaS同士を接続し、イベント駆動型のアプリを簡単に構築できます。
ここで用語を説明します。
- イベント
- AWSサービス、独自アプリケーション、SaaS等の環境における変化を意味します。例えば、EC2インスタンスの状態が保留中から実行中に変更されると、Amazon EC2 はイベントを生成します。
- イベントソース
- イベントの発生源です。様々なAWSサービス・SaaS・カスタムアプリケーションがイベントソースになり得ます。例えば、イベントがEC2インスタンスの状態の変化の場合、イベントソースはEC2です。
- ルール
- イベントを受信し、ターゲットに送信するためのものです。ルールには、イベントパターンとスケジュールがあります。イベントパターンは、設定した検出パターンに一致するイベントを検出し、ターゲットに送信します。スケジュールは、定期的にターゲットを呼び出します。
- ターゲット
- イベントを送信するリソースまたはエンドポイントです。
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ルールのARNaws.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ルールで定時起動したステートマシンの入力に、定時起動時刻などを入力するようにします。
サンプルコートは以下で公開しています。
まず、今回は以下のようなシンプルなステートマシンを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を紹介しました。
本記事が少しでもお役に立てれば幸いです。
コメント