にゃみかんてっくろぐ

猫か百合を見守る壁になりたい

Amazon ECS: curl コンテナを使ってタスク定義だけでモックサーバを設定する

3 行まとめ

  • API のモック化ツール WireMock には、動的にスタブ/モックを定義できる Admin API がある
  • ECS タスク定義に「 Admin API を叩く curl コンテナ」を加えて WireMock のスタブ/モック定義を行う
  • タスク定義だけ完結するので楽

タスク定義だけでモックサーバを設定する

テスト用のモックサーバの 1 つに WireMock がありますが、この WireMock には動的にスタブ/モックを定義できる Admin API があります (Stubbing - WireMock) 。

この Admin API を利用します。 Amazon ECS のタスク定義に「 WireMock コンテナ」に加えて「 Admin API を叩く curl コンテナ」を用意することで、 WireMock の設定が可能になります。

タスク定義例

ポイントは 2 点です。

  • WireMock が起動したあとに curl を叩くよう、ヘルスチェックと依存関係を設定
  • curl コンテナは実行後終了するので essential: false とする
{
    "containerDefinitions": [
        {
            "portMappings": [
                {
                    "hostPort": 8080,
                    "protocol": "tcp",
                    "containerPort": 8080
                }
            ],
            "cpu": 0,
            "image": "rodolpheche/wiremock:latest",
            "healthCheck": {
                "retries": 3,
                "command": [
                    "CMD-SHELL",
                    "curl -f http://localhost:8080/__admin/mappings || exit 1"
                ],
                "timeout": 5,
                "interval": 10,
                "startPeriod": 30
            },
            "essential": true,
            "name": "wiremock"
        },
        {
            "command": [
                "curl", "-X", "POST", "--data", "{ \"request\": { \"url\": \"/test\", \"method\": \"GET\" }, \"response\": { \"status\": 200, \"body\": \"Hello world!\" }}", "http://localhost:8080/__admin/mappings"
            ],
            "cpu": 0,
            "image": "curlimages/curl:latest",
            "dependsOn": [
                {
                    "containerName": "wiremock",
                    "condition": "HEALTHY"
                }
            ],
            "essential": false,
            "name": "curl"
        }
    ],
    "memory": "512",
    "family": "fargate-wiremock-with-curl",
    "requiresCompatibilities": [
        "FARGATE"
    ],
    "networkMode": "awsvpc",
    "cpu": "256"
}

実行例

タスクを起動してしばらくすると、 curl コンテナは Admin API を叩いた後に終了します。

f:id:no_clock:20201001235224p:plain

GET /__admin/mappings で期待通り定義されていることが確認できます。また、 GET /test でも定義通りに WireMock がレスポンスを返却していることがわかります。

$ curl http://example.com:8080/__admin/mappings
{
  "mappings" : [ {
    "id" : "f8819ad0-32ca-408a-b248-d77a05767409",
    "request" : {
      "url" : "/test",
      "method" : "GET"
    },
    "response" : {
      "status" : 200,
      "body" : "Hello world!"
    },
    "uuid" : "f8819ad0-32ca-408a-b248-d77a05767409"
  } ],
  "meta" : {
    "total" : 1
  }
}
$ curl -v http://example.com:8080/test
(省略)
< HTTP/1.1 200 OK
< Matched-Stub-Id: f8819ad0-32ca-408a-b248-d77a05767409
< Vary: Accept-Encoding, User-Agent
< Transfer-Encoding: chunked
<
Hello world!

お手軽で再現性もある

実際に活用しましたが、ちょっとしたモックサーバを準備したいときにピッタリでした。

  • 設定ファイルを S3 からダウンロードしてマウントする、設定ファイルを含む自前の Docker イメージを作る、といった作業は不要
  • 手で Admin API を叩く場合と比較して、モック定義に再現性がある
  • タスク定義に閉じるため、管理するもの・考えるものが少なくて済む

参考