🐧

tfmv - Terraform のリソース名のリファクタリング

2024/12/23に公開

今年も残すところ僅かとなってきました。
年末の大掃除に Terraform のリソース名のリファクタリングはいかがでしょうか?
Terraform のリソース名を簡単に修正するツールを作ったので紹介します。

https://github.com/suzuki-shunsuke/tfmv

例: -_ に置換

tfmv -r '-/_'
-resource "github_repository" "example-1" {
+resource "github_repository" "example_1" {
   name = "example-1"
 }
 
 data "github_branch" "example_2" {
-  repository = github_repository.example-1.name
+  repository = github_repository.example_1.name
   branch     = "example"
 }

moved block も生成されます:

moved.tf
moved {
  from = github_repository.example-1
  to   = github_repository.example_1
}

tfmv は以下のことをするシンプルなツールです。

  1. リソース名の変更
  2. リソースの参照の変更
  3. moved block の生成

なお、ここでいうリソースは Terraform の以下のものを指します:

  • resource
  • data source
  • module

Remote State を参照したりしない静的なツールで事前に terraform init を実行したりする必要もありません。

リソース名を書き換えるロジック

リソース名を書き換える方法として現在 3 つサポートしています。
多くの場合は --replace (-r) で十分かと思いますが、より柔軟な修正をしたい場合は正規表現や Jsonnet が使えます。

  1. 固定文字列の置換 --replace (-r) '<置換前の文字列>/<置換後の文字列>'

マッチする文字列が全部置換されます。

  1. 正規表現による置換 --regexp '<正規表現>/<置換する文字列>'

e.g.

--regexp '^example-(\d+)/test-$1'

マッチする文字列が全部置換されます。
正規表現に関しては Go の regexp package を使っているのでそちらを参照してください。

  1. Jsonnet による置換 --jsonnet (-j) <jsonnet ファイルパス>

Jsonnet に対象の block の情報が External Variable として渡されるので、 Jsonnet で新しいリソース名を返すとその通りにリネームされます。
空文字や元のリソース名と同じ値を返すとリネームされません。
Jsonnet では幾つか Native function が定義されています。詳細はドキュメントを読んでください。

正規表現によるリソースのフィルタリング

リネーム対象のリソースを正規表現でフィルタリング出来ます。

  • --include <正規表現>: リソースのフルパスが正規表現にマッチするリソースのみに限定
  • --exclude <正規表現>: リソースのフルパスが正規表現にマッチしないリソースのみに限定

リソースのフルパス とはいかの値のことです。

  • resource: <リソースタイプ>.<リソース名> (e.g. aws_s3_bucket.foo)
  • data source: data.<リソースタイプ>.<リソース名> (e.g. data.aws_s3_bucket.foo)
  • module: module.<モジュール名> (e.g. module.foo)
aws provider のリソースに限定
tfmv -r '-/_' --include '^aws_'
aws provider のリソースを除外
tfmv -r '-/_' --exclude '^aws_'

Dry run --dry-run

Dry Run も出来ます

tfmv --dry-run -r '-/_'

変更対象のファイルの指定

デフォルトではカレントディレクトリの *.tf が対象になります。
--recursive (-R) オプションを指定するとカレントディレクトリと全サブディレクトリが対象になります。
ただし、 .git, .terraform, node_modules は除外されます。
コマンドライン引数でファイルを指定することも出来ます。

tfmv -r '-/_' foo.tf bar.tf

moved block の出力先の変更

デフォルトでは moved.tf というファイルに moved block は出力されます。
--moved (-m) <ファイル名> で変更できます。
same という値を指定すると、リネーム対象のリソースが定義されているファイルに出力されます。
ファイルがなければ新規作成され、あれば追記されます。

さいごに

以上、簡単ですが tfmv の紹介でした。

Discussion