tfmv - 给 Terraform 重命名补上 moved block 的小工具
Terraform 代码里的命名债务很容易累积。早期为了快,resource 名称里混用了 -、_、环境后缀、缩写和不同团队的命名习惯;后来想整理时,又会碰到一个更麻烦的问题:只改 .tf 文件里的 block name 还不够,Terraform state 也要知道旧地址和新地址之间的关系。
Terraform 的 moved block 正是用来表达这种迁移关系的。但当一次改名涉及多个 resource、data source、module,以及很多引用关系时,手写 moved block 会很枯燥,也容易漏掉某个引用。今天推荐的 suzuki-shunsuke/tfmv 就是围绕这个小而具体的问题做的 CLI:重命名 Terraform blocks,并生成对应的 moved blocks。
GitHub 页面在发布时显示项目约 159 stars、6 forks,主要语言是 Go,许可是 MIT。项目创建于 2024-12-20,最近一次 push 是 2026-06-06;当前没有 GitHub latest release。
项目概览
| 属性 | 详情 |
|---|---|
| 仓库 | suzuki-shunsuke/tfmv |
| 定位 | Terraform resource、data source、module 重命名和 moved block 生成 |
| Stars | 约 159 |
| Forks | 6 |
| 主要语言 | Go |
| 许可 | MIT |
| Latest release | 暂无 |
它解决的是 Terraform 重命名的机械部分
Terraform 重命名有两层工作。第一层是源码层面的改名,比如把 github_repository.example-1 改成 github_repository.example_1,同时更新其他 block 里的引用。第二层是 state 迁移层面的说明,也就是告诉 Terraform 这个对象不是新建或删除,而是从旧地址移动到了新地址。
手动做这件事时,常见风险有三个:
- block name 改了,但引用没有全部跟上。
- 引用改了,但忘了写
movedblock。 - 写了
movedblock,但旧地址或新地址拼错。
tfmv 的价值就在这里。它把命名变换规则应用到 Terraform block 上,同时生成 moved.tf。这不是一个宏大的 IaC 平台,而是一个能放进真实整理任务里的小工具。
最简单的用法:把横线替换成下划线
README 里的基本例子很直观:
tfmv -r "-/_"
这里的 -r / --replace 表示简单替换。假设原来有这样的 resource:
resource "github_repository" "example-1" {
name = "example-1"
}
tfmv 会把 block name 迁到 example_1,并更新引用。与此同时,它会生成类似这样的 moved block:
moved {
from = github_repository.example-1
to = github_repository.example_1
}
这个设计适合处理命名规范统一。比如一个团队决定 Terraform block 名称统一使用下划线,不再使用横线;或者想批量去掉某些环境后缀。工具不需要运行 terraform init,默认会在当前目录查找 *.tf 文件。
不只是 resource,也包括 data source 和 module
tfmv 不只处理 resource。README 说明它可以重命名 Terraform resources、data sources 和 modules,并更新引用关系。这个范围很重要,因为真实模块里经常会有这样的链路:
resource的名字被data引用;module的名字出现在depends_on;output里又引用了 data source 或 resource;- 多个 block 的命名规则需要一起调整。
如果只做文本替换,很容易误伤普通字符串或漏掉 Terraform address 的语义。tfmv 的定位更接近“理解 Terraform block 地址的重命名器”,而不是普通 sed。
支持三种命名规则
tfmv 要求指定一种重命名方式:
--replace/-r:简单字符串替换,适合-到_这类直接迁移。--regexp:使用正则表达式重命名,适合移除后缀或匹配一批模式。--jsonnet/-j:用 Jsonnet 描述更灵活的命名逻辑。
简单规则可以直接写在命令行:
tfmv --regexp '-prod$/'
这类规则可以用来移除 -prod 后缀。更复杂时,可以写 Jsonnet。tfmv 会把每个输入对象的信息传给 Jsonnet,包括文件路径、block 类型、resource 类型和当前名称;Jsonnet 返回新名称。如果返回空字符串或名称不变,对象就不会被重命名。
这个分层是实用的。大多数整理任务只需要 -r,少数需要正则,真正复杂的命名策略才交给 Jsonnet。
可以过滤范围,降低大仓库风险
批量改 Terraform 名称时,范围控制很关键。tfmv 支持 --include 和 --exclude,用正则筛选要处理的对象:
tfmv -r "-/_" --include "^aws_"
tfmv -r "-/_" --exclude "^aws_"
它也支持把具体 .tf 文件作为参数传入:
tfmv -r "-/_" main.tf
如果要递归查找,可以加 -R:
tfmv -Rr "-/_"
递归模式下会忽略 .git、.terraform、node_modules。这些默认值比较符合 Terraform 项目的实际结构,避免扫进状态目录、依赖目录或工具缓存。
--dry-run 和 moved 文件位置
我会把 --dry-run 当成使用 tfmv 的第一步:
tfmv -r "-/_" --dry-run main.tf
README 说明 dry run 会输出日志,但不会真的重命名 blocks。对基础设施代码来说,这一步很值得保留。Terraform refactor 的风险通常不在语法,而在地址迁移是否符合预期。先看日志,再看 diff,最后跑 terraform plan,比直接批量改安全得多。
默认情况下,tfmv 会把 moved blocks 写到 moved.tf。如果团队希望换文件名,可以用 -m:
tfmv -r "-/_" -m moved_blocks.tf
也可以使用 -m same,把 moved blocks 输出到重命名发生的同一个文件里。这取决于团队偏好。有的团队喜欢把迁移块集中放在一个文件,方便后续清理;有的团队喜欢迁移说明贴近原模块。
它应该放在什么流程里
我更倾向把 tfmv 放在一次明确的 Terraform refactor 流程中,而不是日常无感自动运行:
- 新建一个只做命名迁移的分支。
- 先运行
tfmv --dry-run看将要影响的对象。 - 限定目录、文件或 include/exclude 范围。
- 运行 tfmv 生成源码改动和 moved blocks。
- 人工 review diff,重点看引用是否全部更新。
- 在目标 workspace 上跑
terraform plan。 - 合并后观察一次 apply,再按团队策略清理过期 moved blocks。
tfmv 能减少机械错误,但不能替代 plan 和 review。Terraform state 迁移是生产基础设施变更的一部分,工具应该帮你少写重复代码,而不是让你跳过验证。
和 terraform state mv 的关系
tfmv 生成的是 Terraform 配置里的 moved blocks,而不是直接执行 terraform state mv。这点很重要。
terraform state mv 是一次性的状态操作,适合某些手工迁移场景。moved block 则把迁移意图写进配置,让迁移随代码一起 review、提交和运行。对团队协作来说,后者更透明:PR 里能看到旧地址、新地址和源码改动,CI 或 plan 流程也能体现迁移关系。
这也是 tfmv 值得关注的原因。它不是只帮你改名字,而是帮助你把“改名”表达成 Terraform 能理解、团队能审计的迁移。
需要注意的边界
tfmv 的问题域很明确,所以使用时也要保留边界感。
- 它不会替你判断某个 Terraform 重命名是否应该发生。
- 它不能替代 provider 行为理解、plan 审查和环境验证。
- 批量规则写错时,仍然可能生成大量不想要的改名。
- 当前没有 GitHub latest release,采用时要看安装方式和仓库变更节奏。
因此,最稳妥的使用方式是:小范围、dry run、review diff、plan 验证。不要在很大的基础设施仓库里直接跑一次全局替换然后合并。
适合谁尝试
tfmv 适合这些场景:
- Terraform 仓库正在统一 block 命名规范。
- 你要把横线、后缀或历史命名习惯批量迁移掉。
- 模块里有大量引用关系,手动改名容易漏。
- 团队希望使用
movedblock,而不是只靠一次性 state 操作。 - 你想让命名迁移以 PR diff 的形式被 review。
如果只是改一个 resource,手写 moved block 可能更快。但一旦涉及几十个对象,或者命名规则有明确模式,tfmv 就能明显减少机械劳动。
小结
suzuki-shunsuke/tfmv 是一个很典型的小众开发者工具:功能窄,但问题真实。Terraform 重命名不是每天都会发生,可一旦发生,手动改地址、引用和 moved blocks 的过程非常容易出错。
我喜欢它把范围控制、dry run、正则、Jsonnet 和 moved 文件位置这些细节都补上了。它不会让 Terraform refactor 变成无风险操作,但能把最重复、最容易漏的部分自动化掉。对维护中大型 Terraform 仓库的人来说,这类工具很值得收进工具箱。