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


Consumer-Driven Contract テストをフレームワークさせるPactをつかったサンプルプロジェクトを前回のエントリでは紹介しました。
golang - kotlinのmicroservice構成のConsumer-Driven Contract testingをpactをつかって作ってみた - 平日インプット週末アウトプットぶろぐ前回のエントリではPactファイルをConsumerとProviderともにファイルシステムを用いて参照していました。
Pact Brokerを導入すればPactファイルのレポジトリ環境が構築できます。
今回のエントリではPact Brokerの構築を紹介します。

Pact Broker

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

Pact Brokerの特徴を抜粋すると

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

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のコンテナをぶら下げたいのですが、この課題を解決してくれるのがこちらの記事です。
dind(Docker in Docker)で複数のdocker-composeを管理する - tehepero note(・ω<)この記事に習い次のような構成でDocker in DockerをローカルPCに構築しました。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
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ファイル

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
{
	"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ファイルをパブリッシュする

1
2
3
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のリスト

パブリッシュしたPactファイルから生成されたAPIドキュメント

ConsumerとProviderのNetwork Graph

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

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

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

1
@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の知見を活かせるところを今後は探っていきます。

ソースを公開しています

関連エントリ

golang - kotlinのmicroservice構成のConsumer-Driven Contract testingをpactをつかって作ってみた - 平日インプット週末アウトプットぶろぐ