Terraformerの罠

# はじめに
こんばんは。本記事はProgaku Advent Calendar 2022 3日目担当のきよすけと申します。
早速本題ですが、みなさん、IaaCしてますか？？(ド直球)時間がなくて既存のインフラはあるけどまだコード化はできてない・・・とはいえ今から1からコード化はしんどいな・・そんな人も多いのではないのでしょうか？
そんなときが筆者が見つけたのが[Terraformer](https://github.com/GoogleCloudPlatform/terraformer)というツールです。「ふむふむ・・なんやらAWSのリソースを指定してインポートするだけで.tfファイルを自動生成してくれる・・!？これは神ツールじゃない？？使わない手がないやんけ!!」てな感じで即断で使うことを決意しました。

たが、こいつは決っして銀の弾丸では無かったです・・。
少し駆け足になりますが、簡単に罠についてまとめて見たのでご参考ください。

# 対象読者
- AWS、Terraformについての基礎知識がある方
- 既存のインフラをコード化したい方

# 環境
- M1 Mac Big Sur 11.6
- Terraformer v0.8.21
- Terraform v1.2.3

## Terraformerとは

- 上記でも解説したように既存のインフラストラクチャからTerraformコードを生成してくれるツール。インポートするとデフォルトで`generated`ディレクトリが作られ、そのなかにコードが自動生成される。
    - コードは一つのファイルにまとまって出力される。

```
      $ echo ‘provider “aws” {}’ > main.tf
      $ terraform init
      $ terraformer import aws --resources sg --regions <リージョン名>
      $ tree -a

.
├── .terraform
│   └── providers
│       └── registry.terraform.io
│           └── hashicorp
│               └── aws
│                   └── 3.22.0
│                       └── darwin_amd64
│                           └── terraform-provider-aws_v3.22.0_x5
├── .terraform.lock.hcl
├── generated
│   └── aws
│       └── sg
│           ├── outputs.tf
│           ├── provider.tf
│           ├── security_group.tf
│           ├── terraform.tfstate
│           └── variables.tf
└── main.tf
10 directories, 8 files
```

## インポート時の罠
- [SSO](https://www.fenet.jp/aws/column/technique/400/)の認証情報ではインポート時に認証エラーになる。(SSOで使っているユーザーのプロファイルを指定してインポートが出来ない)
    - TerraformではSSOユーザープロファイルでCLIの実行ができるが、Terraformerの場合は、Terraformer実行用のIAMユーザーを用意し、このユーザープロファイルを指定する必要があった。
        - このとき、TerraformerのIAMに適切な権限を設定する必要があるが結構めんどくさいので注意。
    -  TerraformerはAWS CLIのプロファイルに対応していなかったが試してみた所現在は対応しているっぽい。
  

### デフォルトのポリシーなども読み込んでしまう
- AWSS3FullAccessとか元々あるポリシーもコード化されてしまう。
    - タグ付けやIDでフィルタリングできるのでこれらのオプションを駆使して工夫して実際にコード化したいリソースをインポートする必要がある。
        - リソースIDでフィルタリング
            - `$ terraformer import aws --resources=vpc,subnet --filter=vpc=myvpcid --regions=eu-west-1`
        - タグ指定でフィルタリング
            - `$ terraformer import aws --resources=s3 --filter=“Name=tags.Abc” --regions=eu-west-1`
## 使えるTerraformのバージョンが古い
- terraform0.13.6までの対応(1系はサポートしていない)。
## 依存関係は解決してくれない

こいつがおそらく一番厄介で面倒なポイントだと思います。
たとえばVPCとサブネットをインポートするとTerraformerは下記のようなソースを自動生成します。
どこが問題かわかりますでしょうか？(普段Terraformを書く方ならどこが問題かわかるかと思います。)

```terraform
resource "aws_vpc" "example-ecs-vpc" {
  cidr_block = "10.1.0.0/16"
  enable_dns_hostnames = true
  enable_dns_support = true
  tags  = {
    "Name" = "example-ecs-vpc"
  }
  tags_all = {
    "Name" = "example-ecs-vpc"
  }
}
```

```terraform
resource "aws_subnet" "tfer--subnet-00e08070gur80898" {
  assign_ipv6_address_on_creation                = "false"
  cidr_block                                     = "10.1.144.0/20"

  (…省略…)

  availability_zone = "ap-northeast-1c"
  tags = {
    ENV  = "example-ecs"
    Name = "example-ecs-subnet-private2-ap-northeast-1c"
  }
  tags_all = {
    ENV  = "example-ecs"
    Name = "example-ecs-subnet-private2-ap-northeast-1c"
  }
  vpc_id = "vpc-01234567890abcdef"

}
```

そうです。`aws_subnet`の`vpc_id`がハードコーディングされてしまっていますね。
本来であれば
```terraform
vpc_id = aws_vpc.example-ecs-vpc.id
```
と書くべき所ですね。

しかし、基本Terraformで生成されるソースはsubnet_idやvpc_id、IAMのロール名やARNなどがハードコーディングされた状態で自動生成されてしまいます。これではTerraform側でリソース同士の依存解決がされないため

- VPCより先にサブネットを作ろうとする
- またIAMロールが作成されていないのにEC2にアタッチしようとする

みたいなことが起きてTerraformから「そんなリソースねえよ」と怒られてしまいます。
しかもこいつはドライラン(`terraform plan`)ではなく`terraform apply`実行時でないとわからなかったりするので地道にトライアンドエラーで潰していくしかないと思います。


# 自動生成されたコードはそのまま使えない
これ、言ったら元も子もない感があるんですが、上記の依存解決をしても割りとエラー起こるんでそこそこ手で修正する必要が出てきます。非推奨のプロパティを使っていたり、そもそも指定する必要の無いプロパディまでソースコード化されてしまったりするので注意が必要です。また、そもそもインポートすべきリソースができていないなんてことが後から発覚したりします。筆者の場合そういうときは素直に`terraform import`してtfstate見ながらTerraform書いた方が結果はやくて正確な作業ができたのでスポット作業だったらこちらを使うのも手かと思います。

# まとめ
- **Terraformerは決して銀の弾丸ではない**
- インポート時は必要なものを絞って戦略的に行う
  - SSOを使っている場合でも別途Terraformer実行用のIAMユーザーの作成が必要(ここは改善されるかもしれない)
- 自動生成されたコードはそのままでは使えないので、結局手でそこそこ修正する必要がある
    - 場合によっては`terraform import`を活用すべし
- **とはいえ、1からTerraformを書くよりTerraformerで叩き実装をしてやっていったほうがはやいとは思う!**