📝

tfstate から HCL を復元するツールを作った

2022/12/01に公開

最近作った tfstate から .tf ファイル[1]を復元する Terraform の wrapper コマンド、tfsalvage を紹介します。

https://github.com/azarashi2931/tfsalvage

これは 天久保 Advent Calendar 2022 の 1 日目の記事です。

背景

Terraform には、Terraform の管理下にないリソースを Terraform の管理下にインポートするためのサブコマンドがあります。

https://developer.hashicorp.com/terraform/cli/commands/import

ここで言う「Terraform の管理下にインポート」とは Terraform の管理下にないリソースを tfstate にインポートすることです。.tf ファイルを自動で作成してくれるわけではありません。
しかし Terraform にリソースをインポートする場合、同時に tfstate と一致する .tf ファイルを作成することが多いです。すべてのアトリビュートの値は tfstate に記録されているので、.tf ファイルは自動で生成できるように思えます。どうにかして .tf ファイルを自動で生成したいです。

Terraform の GitHub リポジトリの issue でも話題になっていますが、動いていないようです。

https://github.com/hashicorp/terraform/issues/15608

また、似たことを実現できるツールとして Terraformer というものもあります。

https://github.com/GoogleCloudPlatform/terraformer

このツールは Terraform の管理下にないリソースを tfstate にインポートしつつ .tf ファイルを生成してくれるため、一見必要な機能を備えているように見えます。
しかし、Terraformer でリソースをインポートするには Terraformer による Terraform provider ごとのサポートが必要です。サポートされていない Terraform provider のリソースに対しては使用できません。
また、Terraformer の README を読むとわかるのですが、このツールは terraform import が担う役割も内包しており、今回欲しい仕組みとは若干スコープが違います。

実装

そこで、tfsalvage というツールを作りました。
冒頭で言った通り .tf ファイルを tfstate から復元するツールです。terraform import したリソースから .tf ファイルを作成する時に使うことを想定しています。

https://github.com/azarashi2931/tfsalvage

仕組みとしては非常に簡単です。
まず前提として、Terraform には以下の 2 つのサブコマンドがあります。

https://developer.hashicorp.com/terraform/cli/commands/show

https://developer.hashicorp.com/terraform/cli/commands/providers/schema

terraform show は Terraform のワーキングディレクトリで実行すると、そのワーキングディレクトリの tfstate を閲覧できるサブコマンドです。オプションを指定すれば JSON で結果を出力できます。
このサブコマンドで tfstate のリストを取得します。

terraform providers schema は Terraform のワーキングディレクトリで実行すると、使われている provider のスキーマを出力できるサブコマンドです。こちらも JSON で結果を出力できます。
provider のスキーマにはその provider を使って定義できるリソースの種類やそれぞれのリソースが持つアトリビュートの情報が含まれています。
今回はこのスキーマに含まれるあるアトリビュートが .tf ファイルから入力すべき情報なのかを判定するフラグを用いてアトリビュートを抽出します。

以上のようにこの 2 つのサブコマンドを組み合わせることで、Terraform CLI に含まれる機能を使って tfstate から .tf ファイルに記録すべき情報を取得できます。

そして、この情報から HCL の AST を組み立てて hclwrite パッケージで出力すれば tfstate から復元された .tf ファイルの出来上がりです。

https://pkg.go.dev/github.com/hashicorp/hcl/v2/hclwrite

制約

このツールは terraform providers schematerraform show から取得できる以上の情報を知りません。そのため、以下のような制約があります。

  • デフォルト値のアトリビュートを削除できない。
    例えばあるリソースのあるアトリビュートのデフォルト値と tfstate に含まれるアトリビュートの値が一致していたらアトリビュートを .tf ファイルに出力しない、といった処理ができません。terraform providers schema で取得できるスキーマからデフォルト値の情報が取得できないためです。
    Terraform provider が提供するスキーマにはデフォルト値を記録するためのフィールドがあるので、他の方法で provider のスキーマを取得すればこの問題は解決できる可能性があります。
    Plugin Development - Schema Behaviors | Terraform | HashiCorp Developer

  • 参照関係を復元できない。
    Terraform でリソースを定義するとき、別のリソース定義のアトリビュートを参照したり、data ブロックでそのワーキングディレクトリにないリソースを参照したりすることがよくあるはずです。しかしこの参照関係の情報は tfstate に残されていないため復元できません。

また、それとは別に手を抜いたので以下の機能はありません。

  • このツールが出力するリソース定義の順序やブロック内のアトリビュートの順序を制御する機能

デフォルト値の削除、参照関係の復元や順序の変更などの .tf ファイルの体裁を整える作業は、このツールのスコープ外としています。

最後に

以上、tfsalvage の紹介でした。
天久保 Advent Calendar 2022 は今後も天久保のメンバーやメンバーでない人が技術に関連することや関連しないことをどしどし投稿していくので楽しんでいってください。

脚注
  1. 正確には Terraform の設定であるところの HCL ファイル。冗長なのでこの記事では .tf ファイルと呼ぶ。 ↩︎

Discussion