AWS EventBridge Pattern DSL

EventBridge had been lately updated with set of new pattern matching capabilities that had been nicely captured in the blog post by James Beswick. The existing functionality of matching the event based on exact equality of certain fields has now been expanded to support operations like prefix matches, not matches or matching base on a presence of certain attributes. This altogether helps to pre filter the events based on specific criteria, that previously was not only achievable by adding the needed boilerplate logic to your events consumer and dropping all events that are not meeting certain criteria.

Even before the pattern matching syntax had expanded with additional keywords and operators it was not uncommon to mis configure your event pattern by specifying wrong attribute name or pattern syntax, no matter whether use with AWS CLI, CloudFormation or through AWS Console.

To avoid this scenario and first of all make the creation of the Rule pattern more bulletproof experience as well as allow it to be fully reproducible and testable I had create a very small utility Java library that introduce DSL for EventBridge pattern language.

You can add the library to your existing project by simply dropping it to your Maven (or Gradle) project.

<dependency>
  <groupId>io.jmnarloch</groupId>
  <artifactId>aws-eventbridge-pattern-builder</artifactId>
  <version>1.0.0</version>
</dependency>

The utility is really simple to use. It defines a `EventsPattern` with flow API for defining the constraints of the matched events.

As an example a pattern that matches an event published by aws.ec2 that would be expressed in JSON like:

{
  "source": [ "aws.ec2" ]
}

Can be turn into small Java snippet.

EventsPattern.builder()
        .equal("source", "aws.ec2")
        .build();

Once a pattern had been created it can be turn into JSON simply by calling `toJson` method.

The newly supported operators are also supported.

Prefix matching
For instance if we wish to match events from specifying AWS regions we can create a pattern.

EventsPattern.builder()
        .prefix("region", "eu-")
        .build();

Will corespond to JSON syntax

{
  "region": [{"prefix": "eu-"}]
}

Anything but
Can be used to match everything except certain value.

EventsPattern.builder()
        .path("detail")
                .anythingBut("state", "initializing")
                .parent()
        .build();

Will result in.

{
  "detail": {
    "state": [ {"anything-but":"initializing"} ]
  }
}

AWS SDK

The above examples can be used as drop replacement whenever using the vanilla AWS SDK.

EventsPattern pattern = EventsPattern.builder()
        .equal("source", "aws.ec2")
        .build();

AmazonCloudWatchEvents eventsClient = AmazonCloudWatchEventsClient.builder().build();
eventsClient.putRule(new PutRuleRequest()
        .withName("EC2-Rule")
        .withRoleArn("arn:aws:iam::123456789012:role/ec2-events-delivery-role")
        .withEventPattern(pattern.toJson()));

Testability

The biggest benefit for moving the rule to the code would be arguable the possibility to test the rule even before it’s deployed. For that purpose a dedicated test could be added that would be part of the integration test suite.

    @Test
    public void patternShouldMatchEvent() {

        String event = "{\"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-abcd1111\",  \"state\":\"pending\"  }}";

        EventsPattern pattern = EventsPattern.builder()
                .equal("source", "aws.ec2")
                .build();

        AmazonCloudWatchEvents eventsClient = AmazonCloudWatchEventsClient.builder().build();
        TestEventPatternResult matchResult = eventsClient.testEventPattern(new TestEventPatternRequest()
                .withEvent(event)
                .withEventPattern(pattern.toJson()));
        assertTrue(matchResult.getResult());
    }

Now each time the event structure itself changes there is regression test in place that can guarantee that the created pattern will still be matching the event. Useful during early development stages or for prototyping purposes.

AWS CDK

AWS CDK is a development framework that allows you to define your AWS infrastructure as a code. At the moment the CDK does not yet support the full syntax of the pattern matching, but the ultimate goal would be to introduce such capacity in the CDK directly.

The project is open source and available on Github repo.

For additional information on the event matching capabilities please refer to the EventBridge documentation.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s