Pact Broker DockerコンテナをつかってPact Broker環境を構築してみた

Consumer-Driven Contract テストをフレームワークさせるPactをつかったサンプルプロジェクトを前回のエントリでは紹介しました。
naruto-io.hatenablog.com

前回のエントリではPactファイルをConsumerとProviderともにファイルシステムを用いて参照していました。
Pact Brokerを導入すればPactファイルのレポジトリ環境が構築できます。
今回のエントリではPact Brokerの構築を紹介します。

Pact Broker

Pact Brokerはこちらのgithubレポジトリから参照できます。
github.com

Pact Brokerの特徴を抜粋すると

  • ConsumerとProviderの間のPact共有の課題を解決する
  • Pactの管理をPact Brokerが一元管理するためConsumerとProviderともにPact管理/Pactリリースの手間がなくなる
  • 最新のAPIドキュメント管理をPact Borkerが保証する
  • サービスが提供するAPIのインタラクションが確認できる
  • microserviceの依存関係をビジュアライズする

特徴についてはスクリーンショットも合わせて参照ください。

Pact Broker Docker container

Pact Brokerをローカルに構築していきます。Pact BrokerのDockerコンテナが用意されていますので今回はこちらを使います。

https://hub.docker.com/r/dius/pact_broker/

DBにPostgresを推奨していますので合わせてPostgresのDocker Containerを使います。
ここで2つのコンテナが必要になったのでDocker Composeで構成をまとめるついでにMackerelのコンテナも構成に入れてコンテナ監視もさせてみます。

dind(Docker in Docker)をつかってローカルでPact Brokerを動かす

Mackerelコンテナはホストのdocker.sockをvolumesを用いてコンテナにリンクさせる必要があるのでローカルで動かすときはDocker In Dockerがしたくなります。
ローカルPCにホストとなるコンテナを立てて、その中にPact Broker、Postgres、Mackerelのコンテナをぶら下げたいのですが、この課題を解決してくれるのがこちらの記事です。
blog.stormcat.io

この記事に習い次のような構成でDocker in DockerをローカルPCに構築しました。

pact-broker-host
├── container
│   ├── mackerel-agent
│   │   ├── Dockerfile
│   │   ├── mackerel-agent
│   │   │   └── mackerel-agent.conf
│   │   └── startup.sh
│   ├── pact-broker
│   │   └── Dockerfile
│   └── postgres
│       ├── Dockerfile
│       └── init_db.sql
└── docker-compose.yml

dind + direnvコンボのローカル環境構築はとても捗ります。ぜひ参考に。

Pact Brokerの機能をザッと確認

先のコンテナ構成を起動しlocalhost:8080にアクセスするとPact Brokerの管理ツールがお目見えします。

1:ConsumerがPactファイルをPact Brokerにパブリッシュする

Pact BrokerにPactファイルがないと機能が確認できませんので次のPactファイルをPact Brokerへパブリッシュします。

Pactファイル

{
	"consumer": {
		"name": "gateway_service"
	},
	"provider": {
		"name": "user_service"
	},
	"interactions": [
		{
			"provider_state": "there is a user named 1192-User",
			"description": "a get request for a user",
			"request": {
				"method": "GET",
				"path": "/user/1192"
			},
			"response": {
				"body": {
					"Name": "1192-User"
				},
				"headers": {
					"Content-Type": "application/json"
				},
				"status": 200
			}
		}
	],
	"metaData": {
		"pactSpecificationVersion": "1.1.0"
	}
}

Pactファイルをパブリッシュする

curl -v -XPUT \-H "Content-Type: application/json" \
-d@pacts/gateway_service-user_service.json \
http://localhost:8080/pacts/provider/user_service/consumer/gateway_service/version/1.0.1

運用イメージとしてはこのパブリッシュアクションをCircleCIなどのビルドタスクに入れます。

※ 1.0.1のバージョンを更新していくことでPact Brokerがバージョン管理をしてくれます。

2:Pact Brokerではgateway_service(Consumer)とuser_serivce(Provider)の関係が管理されている

ConsumerとProviderのリスト
f:id:n_soushi:20170204232556p:plain

  • user_serviceのConsumerがProviderであることが明確になっています。


パブリッシュしたPactファイルから生成されたAPIドキュメント
f:id:n_soushi:20170204232645p:plain

  • 今回はAPIのインタラクションが1つだけでしたが複数登録すればAPIドキュメントがPact Brokerに一元管理できます。


ConsumerとProviderのNetwork Graph
f:id:n_soushi:20170204235439p:plain

  • サービスから矢印が向いているとConsumer→Providerの関係を表します。
  • このサービスはどのサービスから参照されているか図解してくれます。


※ 関係図を充実させるためにgateway_serviceとuser_serivce以外のサービスも増やしました。

3:Pact BrokerからPactファイルを参照してProvider側でCDCテストを実行する

サンプルのProviderはpact-jvmを使っています。
Pact Brokerと簡単に連携できる@アノテーションが用意されています。

@PactBroker(host = "localhost", port = "8080", tags = arrayOf("latest"))

上記のアノテーションを加えテストを実行するとPact BrokerからPactファイルを取り出しCDCテストが行われます。

まとめ

Pactを使えばCDCテストのフレームワーク化の恩恵が受けられ更にPact Brokerを導入することでPactファイルの管理からAPIドキュメント、ConsumerとProviderのNetwork GraphなどなどCDCテストの運用の手助けが手厚く受けられます。
管理下のmicroserviceすべてにCDCテスト + Pactの導入は腰が重いのでクリティカルなmicroservice間の連携の一部から導入を開始したり、外部に公開するAPIはProviderとしてPactファイルのテストを導入してConsumer側にAPI仕様をクリアにすることもできますしCDCテスト+Pactの知見を活かせるところを今後は探っていきます。

ソースを公開しています

github.com

関連エントリ

naruto-io.hatenablog.com