[terraform]ECS タスク定義で前のリビジョンを消さずに新しいリビジョンを作る

タイトル長い

## 前提
ECSをterraform管理しようとした場合、タスク定義に以下のようなtfファイルを書きますよね

```task.tf
resource "aws_ecs_task_definition" "my_web_server_task" {
  family                = "my-web-server-task"
  container_definitions = "${file(format("%s/my-web-server-task.json", path.module))}"
  network_mode = "awsvpc"
  requires_compatibilities = ["FARGATE"]
  cpu = "256"
  memory = "512"
  task_role_arn            = "${aws_iam_role.ecs_task_role.arn}"
  execution_role_arn       = "${aws_iam_role.ecs_task_role.arn}"
}
```

```my-web-server-task.json
[
  {
    "name": "nginx",
    "image": "nginx:1.16.1",
    "essential": true,
    "portMappings": [
      {
        "containerPort": 8080,
        "hostPort": 8080
      }
    ]
  }
]
```

## 問題
上記tfファイルの定義の場合, `my-web-server-task.json` などに変更があった場合、 `terraform apply` コマンドの動作としてはreplaceになります

```diff
+++ b/terraform/ecs/my-web-server-task.json
@@ -1,7 +1,7 @@
 [
   {
     "name": "nginx",
-    "image": "nginx:1.16.1",
+    "image": "nginx:1.17.3",
     "essential": true,
     "portMappings": [
       {
```

```shell
$ terraform apply

An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
-/+ destroy and then create replacement

Terraform will perform the following actions:

  # module.m_ecs.aws_ecs_task_definition.my_web_server_task must be replaced
-/+ resource "aws_ecs_task_definition" "my_web_server_task" {
      ~ arn                      = "arn:aws:ecs:ap-northeast-1:<user>:task-definition/my-web-server-task:1" -> (known after apply)
      ~ container_definitions    = jsonencode(
          ~ [ # forces replacement
              ~ {
                  - cpu          = 0 -> null
                  - environment  = [] -> null
                    essential    = true
                  ~ image        = "nginx:1.16.1" -> "nginx:1.17.3"
~(略)~
```

「古いrevisionが削除され、新しいrevisionが作成される」という感じですね
せっかくaws側でrevision管理されているのだから過去分は残して欲しいところ

## 対策
`count` パラメタで新しいリソースを追加する形にしてあげれば、旧revisionを残したまま新しいrevisionを作成することができます

```task.tf
locals {
  revision = 1
}

resource "aws_ecs_task_definition" "my_web_server_task" {
  family                = "my-web-server-task"
  count = "${local.revision}"
  container_definitions = "${file(format("%s/my-web-server-task.json-%d", path.module, count.index+1))}"
  network_mode = "awsvpc"
  requires_compatibilities = ["FARGATE"]
  cpu = "256"
  memory = "512"
  task_role_arn            = "${aws_iam_role.ecs_task_role.arn}"
  execution_role_arn       = "${aws_iam_role.ecs_task_role.arn}"
}
```

jsonファイル名にはrevisionが入ります

```my-web-server-task-1.json
[
  {
    "name": "nginx",
    "image": "nginx:1.16.1",
    "essential": true,
    "portMappings": [
      {
        "containerPort": 8080,
        "hostPort": 8080
      }
    ]
  }
]
```

更新する場合は新たなrevisionに対応するjsonファイルを用意し、countの数値をひとつ増やします

```diff
diff --git a/terraform/ecs/task.tf b/terraform/ecs/task.tf
index 5b43885..c494b15 100644
--- a/terraform/ecs/task.tf
+++ b/terraform/ecs/task.tf
@@ -15,7 +15,7 @@
 # }

 locals {
-  revision = 1
+  revision = 2
 }
```

```my-web-server-task-2.json
[
  {
    "name": "nginx",
    "image": "nginx:1.17.3",
    "essential": true,
    "portMappings": [
      {
        "containerPort": 8080,
        "hostPort": 8080
      }
    ]
  }
]
```

```shell
$ terraform/local  terraform apply                                                                                                                                                                          

An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

```

createのみになりましたね

## 欠点
ただし、この方法を使用する場合、一度に複数revisionを作ろうとした場合に

```
Error: ClientException: Too many concurrent attempts to create a new revision of the specified family.
```
が出て作成できません、revisionがsequentialな番号を必要とするのに対してterraform側が並列に作りに行くのが理由ですね
仮に複数段作成の対応をするならrevisionをインクリメントしつつ `terraform apply` を実行してくれる外部ツールなどが必要ですね