背景
Terraformで既存リソースを管理する場合、import
ブロックが利用可能です。
例えばAWSのIAM Roleは、以下のようなコードでインポート可能です。
import {
to = aws_iam_role.developer
id = "developer_name"
}
to
にTerraformでのリソースIDを、id
にはIAM Role名を記述します。
このimport
ブロックですが、リソースひとつごとにブロックが一つずつ必要になります。
for_each
も使用可能ですが、全リソースを一度にインポートしたい場合、for_each
を書くのも大変です。
import
サブコマンド
インポートするだけであれば、terraform import
サブコマンドを、スクリプトでループさせることでも可能です。
import
コマンドの場合、インポートしたリソースのHCL(tfファイル)を自分で書く必要があります。
terraform plan
で差分を確認しながら、大量のリソース定義を記述していくのは、現実的ではありません。
本題
Terraformは実は、HCLによるtfファイルだけでなく、JSONファイルでのリソース定義も可能です。
file.tf.json
のように、拡張子が.tf.json
のファイルを読み込んでくれます。
スクリプトで一括生成するなら、HCLよりもJSONの方が簡単ですので、今回はこれを活用します。
import
ブロックの場合、以下のような.tf.json
ファイルを用意すればインポート可能です。
{
"import": [
{
"id": "role1",
"to": "aws_iam_role.role1"
},
{
"id": "role2",
"to": "aws_iam_role.role2"
}
]
}
例:AWSアカウント内のIAM Role全てをインポートする
aws cliはJSONで結果を出力してくれます。
--query
オプションやjq
コマンドで加工し、import
ブロックの生成が可能です。
今回はaws cli単体で完結するよう、--query
オプションを使用したJMespath構文で記述します。
1. import
ブロックを記述した.tf.json
を生成
まず、以下のコマンドでimport.tf.json
ファイルを作成します。
aws iam list-roles --query "{import: @.Roles[].{id: RoleName, to: join('', ['aws_iam_role.',RoleName])}}" > import.tf.json
ファイル名は、.tf.json
で終わっていれば、なんでも構いません。
--query
オプションでやっていること解説
{import: @.Roles[].{id: RoleName, to: join('', ['aws_iam_role.',RoleName])}}
- Topレベルに
import
を定義 -
id
は、Terraformのドキュメント通りIAM Role名を指定 -
to
ではTerraform内でのリソースIDを指定するために、aws_iam_role.
とリソースIDを結合。リソースIDはIAM Role名をそのまま使用
2. .tf.json
で定義したリソースから、HCLを生成
import
を定義した状態でterraform plan
のオプション-generate-config-out=ファイル名
を指定すると、terraformコマンドがHCLを自動で生成してくれます。
terraform plan -generate-config-out=generated.tf
3. terraform apply
あとはいつも通りのterraform apply
でインポート完了です。
おわりに
JSONファイルでのTerraformの記述は、制約も少なくなく、通常は使いづらいものです。
しかし、HCLと違ってスクリプトによる生成がしやすいので、API呼び出し結果などからTerraformを記述したい場合には便利です。