Home

Awesome

tfmv

License | Install

tfmv is a CLI to rename Terraform resources, data sources, and modules and generate moved blocks.

e.g. Replace - with _:

tfmv -r "-/_"
diff --git a/example/main.tf b/example/main.tf
index 48ef3bd..9110880 100644
--- a/example/main.tf
+++ b/example/main.tf
@@ -1,20 +1,20 @@
-resource "github_repository" "example-1" {
+resource "github_repository" "example_1" {
   name = "example-1"
 }
 
-data "github_branch" "example-2" {
-  repository = github_repository.example-1.name
+data "github_branch" "example_2" {
+  repository = github_repository.example_1.name
   branch     = "example"
   depends_on = [
-    github_repository.example-1,
-    module.example-3
+    github_repository.example_1,
+    module.example_3
   ]
 }
 
-module "example-3" {
+module "example_3" {
   source = "./foo/module"
 }
 
 output "branch_sha" {
-  value = data.github_branch.example-2.sha
+  value = data.github_branch.example_2.sha
 }

moved.tf is created:

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

moved {
  from = module.example-3
  to   = module.example_3
}

Getting Started

  1. Install tfmv
  2. Checkout this repository
git clone https://github.com/suzuki-shunsuke/tfmv
cd tfmv/example

main.tf:

resource "github_repository" "example-1" {
  name = "example-1"
}

data "github_branch" "example-2" {
  repository = github_repository.example-1.name
  branch     = "example"
  depends_on = [
    github_repository.example-1,
    module.example-3
  ]
}

module "example-3" {
  source = "./foo/module"
}

output "branch_sha" {
  value = data.github_branch.example-2.sha
}

Let's replace - with _. You must specify one of --replace (-r), --regexp, or --jsonnet (-j). In this case, let's use -r. If you need more flexible renaming, you can use regular expression or Jsonnet.

Run tfmv -r "-/_". You don't need to run terraform init.

tfmv -r "-/_"

Then a resource name is changed and moved.tf is created. By default, tfmv finds *.tf on the current directory.

main.tf:

diff --git a/example/main.tf b/example/main.tf
index 48ef3bd..9110880 100644
--- a/example/main.tf
+++ b/example/main.tf
@@ -1,20 +1,20 @@
-resource "github_repository" "example-1" {
+resource "github_repository" "example_1" {
   name = "example-1"
 }
 
-data "github_branch" "example-2" {
-  repository = github_repository.example-1.name
+data "github_branch" "example_2" {
+  repository = github_repository.example_1.name
   branch     = "example"
   depends_on = [
-    github_repository.example-1,
-    module.example-3
+    github_repository.example_1,
+    module.example_3
   ]
 }
 
-module "example-3" {
+module "example_3" {
   source = "./foo/module"
 }
 
 output "branch_sha" {
-  value = data.github_branch.example-2.sha
+  value = data.github_branch.example_2.sha
 }

moved.tf:

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

moved {
  from = module.example-3
  to   = module.example_3
}

Pass *.tf via arguments

You can also pass *.tf via arguments:

tfmv -r "-/_" foo/aws_s3_bucket.tf foo/aws_instance.tf

tfmv supports modules too.

tfmv -r "production/prod" foo/module_foo.tf

Dry Run: --dry-run

With --dry-run, tfmv outputs logs but doesn't rename blocks.

tfmv -r "-/_" --dry-run bar/main.tf

Rename resources by regular expression

With --regexp, tfmv renames resources by regular expression.

tfmv --regexp '^example-(\d+)/test-$1' regexp/main.tf

About regular expression, please see the following document:

Filter resources by regular expression

With --include <regular expression>, only resources matching the regular expression are renamed.

tfmv -r "-/_" --include "^aws_" bar/main.tf

With --exclude <regular expression>, only resources not matching the regular expression are renamed.

tfmv -r "-/_" --exclude "^null_resource" bar/main.tf

Change the filename for moved blocks

By default tfmv writes moved blocks to moved.tf. You can change the file name via -m option.

tfmv -r "-/_" -m moved_blocks.tf bar/main.tf

You can also write moved blocks to the same file with renamed resources and modules.

tfmv -r "-/_" -m same bar/foo.tf

--recursive (-R) Recursive option

By default, tfmv finds *.tf on the current directory. You can find files recursively using -R option.

tfmv -Rr "-/_"

The following directories are ignored:

Jsonnet

-r is simple and useful, but sometimes you need more flexible renaming. In that case, you can use --jsonnet (-j). Jsonnet is a powerful data configuration language.

tfmv.jsonnet (You can change the filename freely):

std.native("strings.Replace")(std.extVar('input').name, "-", "_", -1)[0]
tfmv -j tfmv.jsonnet

You need to define Jsonnet whose input is each resource and output is a new resource name. tfmv passes an input via External Variables. You can access an input by std.extVar('input').

local input = std.extVar('input');

The type of an external variable input is as following:

{
  "file": "A relative file path from the current directory to the Terraform configuration file",
  "block_type": "Either module or resource",
  "resource_type": "A resource type. e.g. null_resource. If block_type is module, resource_type is empty",
  "name": "A resource name. For example, the resource address is null_resource.foo, the name is foo."
}

e.g.

{
  "file": "foo/main.tf",
  "block_type": "resource",
  "resource_type": "null_resource",
  "name": "foo"
}

The Jsonnet must returns a new resource name. If the returned value is an empty string or not changed, the resource isn't renamed.

Native Functions

tfmv supports the following native functions.

You can executed these functions by std.native("{native function name}").

e.g.

std.native("strings.Replace")(input.name, "-", "_", -1)[0]

For details, please see Native functions.

LICENSE

MIT