『実践Terraform』でterraform applyするとError: Invalid indexとエラーが出る

## はじめに

Terraform初学者です。

『[実践Terraform](https://www.amazon.co.jp/dp/4844378139)』という書籍で勉強しています。

書籍のコードをそのまま記述するとエラーとなってしまう箇所があったため、備忘録としてまとめます。

この記事におけるバージョンは次のとおりです。

- Terraform: 1.9.5
- terraform-provider-aws: 5.65.0

## 問題

`第8章 ロードバランサーとDNS`のサンプルコードが対象です。

SSL証明書の検証用レコードを定義する箇所で次のコードが記述されていました。

```terraform:lb.tf
resource "aws_route53_record" "example_certificate" {
  name = aws_acm_certificate.example.domain_validation_options[0].resource_record_name
  type = aws_acm_certificate.example.domain_validation_options[0].resource_record_type
  records = [aws_acm_certificate.example.domain_validation_options[0].resource_record_value]
  zone_id = data.aws_route53_zone.example.id
  ttl = 60
}

resource "aws_acm_certificate_validation" "example" {
  certificate_arn = aws_acm_certificate.example.arn
  validation_record_fqdns = [aws_route53_record.example_certificate.fqdn]
}
```

書籍のとおりにコードを書き、`terraform apply`を実行すると次のエラーが出てしまいます。

```bash
│ Error: Invalid index
│ 
│   on lb.tf line 127, in resource "aws_route53_record" "example_certificate":
│  127:   name = aws_acm_certificate.example.domain_validation_options[0].resource_record_name
│ 
│ Elements of a set are identified only by their value and don't have any separate index or key to select with, so it's only possible to perform operations across
│ all elements of the set.
```

`domain_validation_options[0]`とインデックスで指定していますが、インデックスを持っていないと言われているようです。

## 原因

結論として、以下のように書くことで解決できました。

```terraform:lb.tf
resource "aws_route53_record" "example_certificate" {
  for_each = {
    for dvo in aws_acm_certificate.example.domain_validation_options : dvo.domain_name => {
      name = dvo.resource_record_name
      record = dvo.resource_record_value
      type = dvo.resource_record_type
    }
  }

  name = each.value.name
  type = each.value.type
  records = [each.value.record]
  zone_id = data.aws_route53_zone.example.zone_id
  ttl = 60
}

resource "aws_acm_certificate_validation" "example" {
  certificate_arn = aws_acm_certificate.example.arn
  validation_record_fqdns = [for record in aws_route53_record.example_certificate : record.fqdn]
}
```

これは現在の公式ドキュメントに掲載されている書き方です。

https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/acm_certificate_validation#example-usage

気になって調べてみたところ、`terraform-provider-aws`がバージョン3.0になったタイミングで仕様変更されたようです。

以下のアップグレードガイドにも記載されていました。

https://registry.terraform.io/providers/hashicorp/aws/latest/docs/guides/version-3-upgrade#resource-aws_acm_certificate

やはり公式ドキュメントの確認が大切ですね。

## おわりに

『[実践Terraform](https://www.amazon.co.jp/dp/4844378139)』はとてもわかりやすいため、初学者にもおすすめです。

ただし出版が2019年なので現在とは異なる点もあります。

今後もそういった箇所が見つかったら、公式ドキュメントと書籍を行ったり来たりしつつ、さらにTerraformの理解を深めていきたいと思います。

また、この記事に誤りがありましたらコメントにて教えていただけますと幸いです。

## 参考資料

https://www.amazon.co.jp/dp/4844378139

https://github.com/hashicorp/terraform-provider-aws/blob/release/3.x/CHANGELOG.md#300-july-31-2020

https://registry.terraform.io/providers/hashicorp/aws/latest/docs/guides/version-3-upgrade#resource-aws_acm_certificate

https://www.hashicorp.com/blog/announcing-v3-0-of-the-terraform-aws-provider

https://stackoverflow.com/questions/63235321/aws-acm-certificate-seems-to-have-changed-its-state-output-possibly-due-to-a-pro