📌

【EventBridge】イベントパターンで使用する比較演算子を試してみた

に公開

はじめに

Amazon EventBridge は、AWSを利用したイベント駆動型サービスです。
これにより AWS やアプリケーションのイベントをトリガーとして特定の動作を自動実行するよう指示することができます。

Amazon EventBridge のイベントパターンマッチングを使うと、特定の条件に一致するイベントだけをフィルタして処理できます。
今回は、EventBridgeルールの「イベントパターン(パスパターン)」にどのような書き方ができるのかを検証し、マッチ条件ごとの動作を確認します。

ドキュメントに書いてあるものをいくつかピックアップして検証していきます。
https://docs.aws.amazon.com/ja_jp/eventbridge/latest/userguide/eb-create-pattern-operators.html

Amazon EventBridge の構成要素

Amazon EventBridge は、イベント駆動アーキテクチャを支える強力なサービスであり、以下の主要なコンポーネントによって構成されています。

1. イベントソース
イベントソースは、EventBridge にイベントを送信する発信元です。
AWSサービス(例:S3、EC2)やカスタムアプリケーションが該当し、アクション(例:S3バケットへのファイルアップロード)発生時にイベントを生成し、イベントバスに送信します。

2. イベントバス
イベントバスは、イベントを受け取り、中継する中心的な役割を担います。
デフォルトイベントバスは AWSサービスイベント用、カスタムイベントバスはアプリケーションごとの独自ルーティングに活用できます。
※ AWSサービスからのイベントを受ける場合は、デフォルトのイベントバスを使用します。

3. イベントパターン
イベントパターンは、どのイベントを処理対象とするかを定義する条件式です。
ソース、詳細タイプ、フィールドの値などに基づき、特定のイベントのみをフィルタリングして受け取れます。
例:特定のS3バケット名や、エラーコードに基づいた条件分岐。

4. ルール
ルールは、イベントパターンとターゲットを結びつける設定です。
イベントがパターンにマッチしたときに、どのターゲットへ送るかを制御します。
複数のルールを設定することで、同じイベントに対して複数の処理を同時に実行できます。

5. ターゲット
ターゲットは、ルールにマッチしたイベントを受け取り、アクションを実行する宛先です。
Lambda、SNS、SQS、Kinesisなど多くのAWSサービスが指定可能で、通知・データ処理・ワークフロー起動などを行えます。

テスト方法

テスト方法としては、以下の構成のようにLambdaでイベント送信 → EventBridgeが受信・マッチング → 別のLambdaで処理というようなシンプルな構成でテストをしていきます。
トリガーLambdaの確認方法はCloudWatchで確認していきます。

PutEventsに使えるキーの種類

https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/events/client/put_events.html#

プレフィックスマッチング

次のイベントパターンは、"time": "2017-10-02T18:43:48Z" のように "time"フィールドが "2017-10-02" で始まるすべてのイベントに一致します。

EventBridgeルール
{
  "source": ["test.app"],
  "time": [{
    "prefix": "2017-10-02"
  }]
}
lambda_handler
import boto3
import json
from datetime import datetime

def lambda_handler(event, context):
    eventbridge = boto3.client('events')
    
    response = eventbridge.put_events(
        Entries=[
            {
                'Source': 'test.app',#必須
                'DetailType': 'prefix.test',#必須
                'Detail': json.dumps(event),#必須
                'Time': datetime.strptime("1017-10-02T12:00:00Z", "%Y-%m-%dT%H:%M:%SZ")
            }
        ]
    )
    
    print("Response:", response)

大文字と小文字を無視する際のプレフィックスマッチング

equals-ignore-caseprefix を組み合わせて、値が始まる文字の大文字と小文字に関係なく、プレフィックス値を一致させることもできます。
例えば、次のイベントパターンは、service フィールドが文字列 EventB で始まるイベントだけでなく、EVENTB、eventb、またはそれらの文字の大文字と小文字も一致させます。

EventBridgeルール
{
  "source": ["test.app"],
  "detail": {
    "service": [{
      "prefix": {
        "equals-ignore-case": "EventB"
      }
    }]
  }
}
lambda_handler
import boto3
import json
from datetime import datetime

def lambda_handler(event, context):
    eventbridge = boto3.client('events')
    
    response = eventbridge.put_events(
        Entries=[
            {
                'Source': 'test.app',#必須
                'DetailType': 'prefix.test',#必須
                'Detail': json.dumps(event),#必須
            }
        ]
    )
    print("Event:", event)
    
    print("Response:", response)
テスト
//成功
{
  "service": "eventB"
}
//失敗
{
  "service": "eventc"
}

サフィックスマッチング

イベントソース内の値のサフィックスに応じてイベントをマッチングすることができます。文字列値にはサフィックスマッチングを使用できます。
例えば、次のイベントパターンは、"FileName" フィールドが .png ファイル拡張子で終わるすべてのイベントに一致します。

EventBridgeルール
{
  "source": ["test.app"],
  "detail": {
    "FileName": [{
      "suffix": ".png"
    }]
  }
}
lambda_handler
import boto3
import json
from datetime import datetime

def lambda_handler(event, context):
    eventbridge = boto3.client('events')
    
    response = eventbridge.put_events(
        Entries=[
            {
                'Source': 'test.app',#必須
                'DetailType': 'prefix.test',#必須
                'Detail': json.dumps(event),#必須
            }
        ]
    )
    print("Event:", event)
    
    print("Response:", response)
テスト
//成功
{
  "FileName": "xxxx.png"
}
//失敗
{
  "FileName": "xxxx.jpg"
}

「以外」のマッチング

指定したもの以外のマッチングは、ルールで指定されているもの以外のすべてに一致します。
文字列のみを含むリスト、または数字のみを含むリストを含む、文字列および数値で「以外」のマッチングを使用できます。

文字列を使った「以外」のマッチング

数字の場合は、""を外す。

EventBridgeルール
{
  "source": ["test.app"],
  "detail": {
    "state": [{
      "anything-but": "initializing"
    }]
  }
}
lambda_handler
import boto3
import json
from datetime import datetime

def lambda_handler(event, context):
    eventbridge = boto3.client('events')
    
    response = eventbridge.put_events(
        Entries=[
            {
                'Source': 'test.app',#必須
                'DetailType': 'prefix.test',#必須
                'Detail': json.dumps(event),#必須
            }
        ]
    )
    print("Event:", event)
    
    print("Response:", response)
テスト
//成功
{
  "state": "initializingTest"
}
//失敗
{
  "state": "initializing"
}

文字列のリストを使った「以外」のマッチング

リストがstoppedのみ、overloadedのみ、stopped,overloadedのみの場合、実行しない。
stopped,testは実行される。

EventBridgeルール
{
  "source": ["test.app"],
  "detail": {
    "state": [{
      "anything-but": [ "stopped", "overloaded" ]
    }]
  }
}
テスト
//成功
{
  "state": [ "stopped", "overloaded" ]
}
//失敗
{
  "state": [ "stopped", "test" ]
}

「以外」マッチング (ワイルドカードを使用)

ワイルドカード文字 (*) は、「以外」マッチングで指定した値の中で使用できます。これには、単一の値、または値のリストが含まれます。

次のイベントパターンは、/lib/ を含まない FilePath フィールドの値と一致します。

EventBridgeルール
{
  "source": ["test.app"],
  "detail": {
    "FilePath": [{
      "anything-but": { "wildcard": "*/lib/*" }
    }]
  }
}
テスト
//成功
{
  "FilePath": "/test/test/
}
//失敗
{
  "FilePath": "/test/lib/test/test/"
}

Discussion