Terraform の aws_route_table が何もしてないのに壊れた

Terraform の aws_route_table が何もしてないのに壊れた

月イチ連載になるのか？「何もしてないのに壊れた」シリーズ

2019-12にterraformしたAWS上の開発環境を、サブセットにしてもう一丁建立というタスクが発生したのです。

1. tf コード一式をコピー
2. 不要なところを削除
3. `tags.Name` とか `subnet.cidr_block` とかの環境固有部分を置換
4. `terraform init`
5. `terraform plan`
6. `terraform apply`
7. `serverspec` で疎通テスト

毎日とか毎週の頻度じゃないけど、いつもの段取りでやれる作業のはずだったのです。

## 未知のエラーとの遭遇

typoがないか、環境固有値の設定漏れがないか code差分チェックして、いよいよ `terraform plan` するとこれまで見たことのないエラーが出ました。

```
$ terraform plan
...
Error: expected "route.0.ipv6_cidr_block" to be a valid IPv4 Value, got : invalid CIDR address:

  on route.tf line 17, in resource "aws_route_table" "private-rt":
  17: resource "aws_route_table" "private-rt" {
```

なぜ？ ipv6 のところに IPv4 Value なの？ まあ、言われたとおりにしてみます。

```
            ipv6_cidr_block           = "0.0.0.0/0"
```

たしかに terraform plan は通るようになるのですが、 `terraform apply` すると

```
  Enter a value: yes

aws_route_table.private-rt: Modifying... [id=rtb-xxxxxxxxxxxxxxxx]

Error: Error creating route: InvalidParameterCombination: The parameter destinationCidrBlock cannot be used with the parameter destinationIpv6CidrBlock
        status code: 400, request id: xxxx

  on route.tf line 17, in resource "aws_route_table" "private-rt":
  17: resource "aws_route_table" "private-rt" {
```

そりゃそうだろうと。空文字列が気にいらなかったのかな、

```
            ipv6_cidr_block           = "::/0"
```

```
  Enter a value: yes

aws_route_table.private-rt: Modifying... [id=rtb-xxxxxxxxxxxxxxxx]

Error: Error creating route: InvalidParameterCombination: The parameter destinationCidrBlock cannot be used with the parameter destinationIpv6CidrBlock
```

`terraform plan` は通っても `terraform apply` はできない。



## terraform import

コピペ元の `aws_route_table` の resource文

```
resource "aws_route_table" "private-rt" {
    route            = [
        {
            cidr_block                = "0.0.0.0/0"
            egress_only_gateway_id    = ""
            gateway_id                = ""
            instance_id               = ""
            ipv6_cidr_block           = ""
            nat_gateway_id            = aws_nat_gateway.ngw.id
            network_interface_id      = ""
            transit_gateway_id        = ""
            vpc_peering_connection_id = ""
        },
    ]
    tags             = {
        "Name" = "private-rt"
    }
    vpc_id           = data.aws_vpc.vpc.id
}
```

このresource文の出所は、既存 route_table を `terraform import` して `terraform state show` した結果だったはず。

既存環境の route table の 現時点で state show した結果もこの形式になっています。

```
$ terraform state show aws_route_table."private-rt"
# aws_route_table.private-rt:
resource "aws_route_table" "private-rt" {
    id               = "rtb-xxxxxxxxxxxxxxxx"
    owner_id         = "xxxxxxxx"
    propagating_vgws = []
    route            = [
        {
            cidr_block                = "0.0.0.0/0"
            egress_only_gateway_id    = ""
            gateway_id                = ""
            instance_id               = ""
            ipv6_cidr_block           = ""
            nat_gateway_id            = "nat-xxxxxxxxxxxxxxxxf"
            network_interface_id      = ""
            transit_gateway_id        = ""
            vpc_peering_connection_id = ""
        },
    ]
    tags             = {
        "Name" = "private-rt"
    }
    vpc_id           = "vpc-xxxxxxxx"
}
```

「何もしてないのに壊れた」

## コード修正

https://www.terraform.io/docs/providers/aws/r/route_table.html
aws_route_table の公式構文は state show結果と随分と違うみたい。
こちらに合わせて下記で通った。


```
resource "aws_route_table" "private-rt" {
    route {
            cidr_block                = "0.0.0.0/0"
            nat_gateway_id            = aws_nat_gateway.ngw.id
    }
    tags             = {
        "Name" = "private-rt"
    }
    vpc_id           = data.aws_vpc.vpc.id
}
```

実行環境

- Amazon Linux 2
- Terraform v0.12.26
- aws-cli/1.16.102 Python/2.7.16 Linux/4.14.138-114.102.amzn2.x86_64 botocore/1.12.92