0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

WireMockを使ってローカルでEventBridgeをモックする

Posted at

概要

ローカル環境でEventBridgeをモックしたい。s3mockのように必要最低限の機能を提供している選択肢がなかったため、WireMockを用いて作成してみました。
(AWSの複数サービスを含んだ環境ごと擬似的に作成したい場合はLocalStackで実現できるのですが、今回はアプリケーション側の開発を進める場面を想定しています。)

やったこと

  • EventBridgeクライアントを用いてputEventをするだけのデモ用Spring Bootアプリを作成
  • WireMockでEventBridgeのAPI仕様を真似たマッピングを作成
  • docker-composeでアプリケーションとWireMockを構築

Spring Bootアプリケーション

Spring Bootで、AWS SDKのEventBrideクライアントを用いてPutEventsするだけのアプリケーションを作りました。
基本的にAWS SDK for Java コードの例 - PutEventsを参考にしています。
以下、主要な部分だけコードを抜粋します。

PutEventする機能の実装クラス

EventPublisherImpl.java
@Component
@RequiredArgsConstructor
@Slf4j
public class EventPublisherImpl implements EventPublisher {
    private final EventBridgeClient eventBridgeClient;
    @Override
    @Async
    public void publish(Person person) {
        PutEventsRequestEntry reqEntry = PutEventsRequestEntry.builder()
                .source("com.github.macaroni10y.DemoForMock")
                .detailType("person")
                .detail(person.asJson())
                .build();

        List<PutEventsRequestEntry> list = new ArrayList<>();
        list.add(reqEntry);

        PutEventsRequest eventsRequest = PutEventsRequest.builder()
                .entries(reqEntry)
                .build();

        log.info(person.asJson());
        eventBridgeClient.putEvents(eventsRequest);
    }
}

Config

EventBridgeClientはBean登録しておきました。ここで、クライアントはデフォルトでは本物のEventBridgeのエンドポイントに向けてリクエストを投げます。このままではモックができません。ローカル環境の場合のみ、EventBridgeのエンドポイントを上書きしてWimeMockでマッピングした向き先にするよう設定しました。
この記述が適切かどうかは分かりませんが、以下で実現できます。

DemoForMockConfig.java
@Configuration
public class DemoForMockConfig {
    @Bean
    public EventBridgeClient eventBridgeClient(@Value("${aws.event-bridge.endpoint:#{null}}") String endpoint) {
        System.out.println(endpoint);
        if (Objects.isNull(endpoint)) {
            return EventBridgeClient.builder()
                    .region(Region.AP_NORTHEAST_1)
                    .build();
        }
        return EventBridgeClient.builder()
                .endpointOverride(URI.create(endpoint))
                .region(Region.AP_NORTHEAST_1)
                .build();
    }
}

環境変数にaws.event-bridge.endpointが設定されている場合はそのエンドポイントで上書き、無ければデフォルトのエンドポイントになります。

Wiremockマッピング

普段EventBridgeClientを使う際は意識しないかもしれませんが、API Referenceが公開されているように、結局リクエストを投げているだけです。

以下のようなmappings.jsonを作成し、/home/wiremockにマウントしてマッピング登録しました。

mappings.json
{
  "mappings": [
    {
      "request": {
        "url": "/",
        "headers": {
          "Content-Type": {
            "equalTo": "application/x-amz-json-1.1"
          }
        },
        "bodyPatterns" : [{
          "matchesJsonPath" : "$.Entries"
        }]
      },
      "response": {
        "status": 200,
        "headers": {
          "Content-Type": "application/x-amz-json-1.1",
          "x-amzn-RequestId": "1111"
        },
        "body": "{\"FailedEntryCount\": \"0\", \"Entries\": [{\"EventId\": \"11710aed-b79e-4468-a20b-bb3c0c3b4860\"}]}"
      }
    }
  ]
}

今回は、DetailTypeに関わらずEventBridgeのリクエスト形式ならマッチするようにしました。レスポンスの再現性に関しても、必要に応じて厳密にしていけばよいかと思います。(上の例は正常系のみですし、リクエストに応じた動的なレスポンスでもないので手抜きです。)

docker-compose

docker-compose.yaml
services:
  application:
    image: demo-for-mock/application:latest
    ports:
      - 8080:8080
    volumes:
      - ./application.yaml:/app/application.yaml
    working_dir: /app
    environment:
      AWS_ACCESS_KEY_ID: dummy
      AWS_SECRET_ACCESS_KEY: dummy
      EB_ENDPOINT: http://wiremock:8080/

  wiremock:
    image: wiremock/wiremock:2.32.0
    ports:
      - 9090:8080
    volumes:
      - ./wiremock:/home/wiremock
    command:
      - --verbose

EventBridgeClientが必要とするcredentialsを環境変数に定義しています(WireMockを使うため、値はdummyにしています。また、本番環境ではハードコーディングした認証情報ではなく、IAMロールを使用します。)

--verboseオプションで、リクエストがマッチした場合もログ出力されます。

動作確認

ログ(一部抜粋、改変)
local-application-1  | 2022-02-04 16:29:56.585  INFO 1 --- [         task-1] i.g.m.D.infra.EventPublisherImpl         : {"name":"name","age":10}
local-wiremock-1     | 2022-02-04 16:29:57.488 Request received:
local-wiremock-1     | 172.30.0.2 - POST /
local-wiremock-1     | 
local-wiremock-1     | Authorization: [AWS4-HMAC-SHA256 Credential=dummy/20220204/ap-northeast-1/events/aws4_request, SignedHeaders=amz-sdk-invocation-id;amz-sdk-request;content-length;content-type;host;x-amz-date;x-amz-target, Signature=xxx]
local-wiremock-1     | X-Amz-Date: [20220204T162956Z]
local-wiremock-1     | User-Agent: [aws-sdk-java/2.17.121 Linux/5.10.76-linuxkit OpenJDK_64-Bit_Server_VM/17-ea+14 Java/17-ea vendor/Oracle_Corporation io/sync http/Apache cfg/retry-mode/legacy]
local-wiremock-1     | Connection: [keep-alive]
local-wiremock-1     | Host: [wiremock:8080]
local-wiremock-1     | amz-sdk-invocation-id: [xxx]
local-wiremock-1     | amz-sdk-request: [attempt=1; max=4]
local-wiremock-1     | Content-Length: [124]
local-wiremock-1     | X-Amz-Target: [AWSEvents.PutEvents]
local-wiremock-1     | Content-Type: [application/x-amz-json-1.1]
local-wiremock-1     | {"Entries":[{"Source":"io.github.macaroni10y.DemoForMock","DetailType":"person","Detail":"{\"name\":\"name\",\"age\":10}"}]}
local-wiremock-1     | 
local-wiremock-1     | 
local-wiremock-1     | Matched response definition:
local-wiremock-1     | {
local-wiremock-1     |   "status" : 200,
local-wiremock-1     |   "body" : "{\"FailedEntryCount\": \"0\", \"Entries\": [{\"EventId\": \"11710aed-b79e-4468-a20b-bb3c0c3b4860\"}]}",
local-wiremock-1     |   "headers" : {
local-wiremock-1     |     "Content-Type" : "application/x-amz-json-1.1",
local-wiremock-1     |     "x-amzn-RequestId" : "1111"
local-wiremock-1     |   }
local-wiremock-1     | }
local-wiremock-1     | 
local-wiremock-1     | Response:
local-wiremock-1     | HTTP/1.1 200
local-wiremock-1     | Content-Type: [application/x-amz-json-1.1]

おわりに

EventBridgeをWireMockでモックしてみました。状況によっては使いどころがあるかもしれません・・・。

参考

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?