背景
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を記述したい場合には便利です。