[小ネタ] terraformで(known after apply)と出るけど本当は差分がない場合にどうするか

これは「[「はじめに」の Advent Calendar 2021](https://adventar.org/calendars/7037)」20日目の記事です。

## 差分が出る一例

### 変更前
```before.tf
resource "aws_vpc" "this" {
  cidr_block = "10.1.0.0/16"
  tags = {
    Name = "dev-vpc"
  }
  enable_dns_hostnames = true 
}

data "aws_vpc" "that" {
  id = "vpc-1234567890abcdef"
}

data "aws_vpc_peering_connection" "this_to_that" {
  vpc_id          = data.aws_vpc.that.id
  peer_cidr_block = aws_vpc.this.cidr_block
}

resource "aws_route_table" "this" {
  vpc_id   = aws_vpc.this.id
}

resource "aws_route" "this_to_that" {
  for_each                  = aws_route_table.private
  route_table_id            = aws_route_table.this.id
  destination_cidr_block    = data.aws_vpc.that.cidr_block
  vpc_peering_connection_id = data.aws_vpc_peering_connection.this_to_that.id
}
```

### 変更箇所 (VPCにタグを追加)
```before.tf
resource "aws_vpc" "this" {
  cidr_block = "10.1.0.0/16"
  tags = {
    Name = "dev-vpc"
    Env = "dev" #### <- ここだけ変更
  }
  enable_dns_hostnames = true 
}
```

### `terraform plan` の差分

```diff.tf
─────────────────────────────────────────────────────────────────────────────
Terraform used the selected providers to generate the following execution
plan. Resource actions are indicated with the following symbols:
  + create
  ~ update in-place
 <= read (data resources)

Terraform will perform the following actions:
  # data.aws_vpc_peering_connection.this_to_that will be read during apply
  # (config refers to values not yet known)
 <= data "aws_vpc_peering_connection" "this_to_that"  {
      ~ accepter            = {
          - "allow_classic_link_to_remote_vpc" = false
          - "allow_remote_vpc_dns_resolution"  = false
          - "allow_vpc_to_remote_classic_link" = false
        } -> (known after apply)
      ~ cidr_block          = "10.2.0.0/16" -> (known after apply)
      ~ cidr_block_set      = [
          - {
              - cidr_block = "10.2.0.0/16"
            },
        ] -> (known after apply)
      ~ id                  = "pcx-123456789012345" -> (known after apply)
      ~ owner_id            = "123456789012" -> (known after apply)
      ~ peer_cidr_block_set = [
          - {
              - cidr_block = "10.1.0.0/16"
            },
        ] -> (known after apply)
      ~ peer_owner_id       = "123456789012" -> (known after apply)
      ~ peer_region         = "ap-northeast-1" -> (known after apply)
      ~ peer_vpc_id         = "vpc-fedcba0987654321" -> (known after apply)
      ~ region              = "ap-northeast-1" -> (known after apply)
      ~ requester           = {
          - "allow_classic_link_to_remote_vpc" = false
          - "allow_remote_vpc_dns_resolution"  = false
          - "allow_vpc_to_remote_classic_link" = false
        } -> (known after apply)
      ~ status              = "active" -> (known after apply)
      ~ vpc_id              = "vpc-1234567890abcdef"
        # (1 unchanged attribute hidden)
    }

  # aws_route.this_to_that will be updated in-place
  ~ resource "aws_route" "this_to_that" {
        id                        = "r-rtb-123456789012123456789012"
      ~ vpc_peering_connection_id = "pcx-123456789012345" -> (known after apply)
        # (4 unchanged attributes hidden)
    }

  ~ resource "aws_vpc" "this" {
        id                               = "vpc-fedcba0987654321"
      ~ tags                             = {
          + "Env"  = "dev"
            # (1 unchanged element hidden)
        }
      ~ tags_all                         = {
          + "Env"  = "dev"
            # (1 unchanged element hidden)
        }
        # (14 unchanged attributes hidden)
    }
```

この下の差分は出てほしくない差分です。

```terraform
  ~ resource "aws_route" "this_to_that" {
        id                        = "r-rtb-123456789012123456789012"
      ~ vpc_peering_connection_id = "pcx-123456789012345" -> (known after apply)
        # (4 unchanged attributes hidden)
    }
```

## 何故出るのか

差分が出る理由としては、図に表すと下のような感じです。

```
(変更しているState)
VPC          route
↓              ↑
(data source)Peering
↑
(別Stateで作成したVPC)
```

依存関係が循環しているので、VPCが変更されると`cidr_block`が変わるかもしれない(とterraformは解釈する)
↓
`data.aws_vpc_peering_connection` の`peer_cidr_block`が変更されると利用する`vpc_peering_connection_id`が変わるかもしれない(とterraformは解釈する)
↓
`aws_route` の`vpc_peering_connection_id`も変わるかもしれない(とterraformは解釈する)

この、 `変わるかもしれない(とterraformは解釈する)` と書いた箇所が `plan` 時には解決できないので、 `(known after apply)` = `applyしたらわかるよ` となります

他の変更(一括でタグを追加するなど）をした時に、こんな差分が含まれていると、VPCペアリングが正しく設定されているかどうか不安になってしまいます(誰か手で変更したんじゃないか、とか)

不安、だけなので実際は `apply` してもタグ追加だけしか行われずこの変更は安全です。
しかし、そもそも差分が出てほしくはないです。

## 対処方法
以下のいずれか(しかないと思います・・・他にあったら教えて下さい)

1. 別のVPC(`that`)も同じStateで管理する
    1. 管理チームが違う場合はできない(AWSアカウントが別の場合もあるので)
1. VPCペアリングとそれに関連するrouteは別Stateに分ける
    1. 管理Stateが分割されるので管理コストは上がりそう