AWS CDKでAmazon EventBridgeを作成する

Amazon EventBridgeを使うことで、各種イベントを集約管理することができます。で、そうなってくるとこの管理サービスをコード管理したくなってきますので、さっそくみんな大好きAWS CDKで書き起こしてみました。

セットアップ

いつも通りのセットアップです。CDKのライブラリで@aws-cdk/aws-eventsを追加しています。

$ mkdir eventbridge && cd eventbridge
$ npx cdk init --language typescript
$ yarn add @aws-cdk/aws-events@1.18

スタックをTypeScriptで書き上げる

意外と短いコードでセットアップできました。

import cdk = require('@aws-cdk/core');
import EventBridge = require('@aws-cdk/aws-events');

export class EventbridgeStack extends cdk.Stack {
  constructor(scope: cdk.Construct, id: string, props?: cdk.StackProps) {
    super(scope, id, props);

    const bus = new EventBridge.CfnEventBus(this, 'bus-from-cdk', {
      name: 'fromCDK'
    })
    const rule = new EventBridge.CfnRule(this, 'rule-from-cdk', {
      name: 'FromCDKRule',
      description: 'trial',
      eventBusName: bus.attrName,
      eventPattern: {
        "detail-type": [
          "customer.created",
          "customer.updated"
        ],
        "source": [
          "Stripe"
        ]
      },
      state: "ENABLED",
      targets: [
        {
          id: "aaaaaa", 
          arn: "arn:aws:lambda:us-east-1:99999:function:first-function"
        }, 
        {
          id: "bbbbbb", 
          arn: "arn:aws:lambda:us-east-1:99999:function:second-function"
        }
    ]
    })
    rule.addDependsOn(bus)
  }
}

イベントバスの中にルールを複数登録していき、入力側はイベントバスに対してputEventする形となります。ですのでeventBusName="default"にしておくのが実は手早いです。ただし、defaultになんでもかんでもイベントを投げ込むと、ルールの数が増えてきた時に誤爆が発生する可能性もありますので、適宜分割しましょう。

targetsの中身はとりあえずLambdaのARNにしています。AWSリソースを呼び出したい場合は、EventBridge.CfnRuleProps.targetsの型情報を見ながら設定していくと良いでしょう。

動作確認スクリプト

上で作ったルール・バスの動作確認は、このような形で行いました。


const AWS = require('aws-sdk');
const eventbridge = new AWS.EventBridge();
const run = async () => {
  const params = {
    Entries: [
      {
        Detail: JSON.stringify({
          name: 'hello world'
        }),
        DetailType: 'customer.created',
        EventBusName: 'fromCDK',
        Resources: [],
        Source: 'Stripe',
        Time: new Date()
      },
    ]
  };

  return eventbridge.putEvents(params).promise()
}
run()
  .then(data => {
    console.log(data)
  }).catch(e => {
    console.log(e)
    console.log('===ERR===')
  })

targetsに指定したリソースが呼び出される条件は、以下の通りです。

  • Sourceに指定した文字列が、RuleのeventPattern.sourceに書いたリストに存在する
  • DetailTypeに指定した文字列が、RuleのeventPattern["detail-type"]に書いたリストに存在する

カスタムイベントありきで行なっていますが、AWSのイベントにすればもう少し簡単になるかもしれません。

Comment