OpenTofu 社区于 2026 年 5 月 14 日发布了 1.12.0 版本。这次更新并非彻底的重写,但确实解决了基础设施团队长期以来面临的一些问题。
人们讨论最热烈的功能是动态 prevent_destroy。以前,如果想防止资源被意外删除,就必须在配置中对这一决策进行硬编码。当你只管理一个环境时,这种做法还可以接受,但在共享的模块配置中——即同一模块在开发、预发布和生产环境中被重复使用的情况——该方案会立即失效。以往的解决方法无非是“复制模块”或“接受对开发数据库进行意外保护”的变体。这两种方案都不尽如人意。OpenTofu 1.12 允许将 prevent_destroy 关联到一个变量,这样生产环境的工作区就可以将其设为 true,而开发环境的工作区则保持 false 不变,不需要对模块进行分支。这听起来似乎微不足道。但对于那些需要通过共享模块代码管理数十个环境的团队来说,这绝非小事。
在这一点上,Terraform 与之形成了鲜明的对比。关于将 prevent_destroy 与变量关联的请求可以追溯到 2016 年的 Terraform 0.7 版本。多年来,问题跟踪系统上围绕这一主题已经累积了多个讨论帖。当团队尝试这种在 OpenTofu 1.12 中已经成为标准的模式时,会遇到“此处不允许使用变量”之类的错误。有人尝试使用动态生命周期块等变通方案,却又遭遇“此处不期望出现 lifecycle 类型块”的报错。还有人提议使用 TF_ALLOW_DESTROY 等环境变量覆盖作为变通方案——这正是当正确的修复方案迟迟未到时,人们会想出的那种权宜之计。HashiCorp 始终未正式发布该功能。在不同环境中使用共享模块的团队面临着艰难的抉择:要么复制模块代码,要么让开发环境和生产环境遵循相同的生命周期规则。OpenTofu 在 1.12 版本中解决了这一问题,距离首个相关请求提交至 Terraform 问题跟踪系统已经过去近十年。这一时间差折射出社区驱动开发与有优先级设定的产品路线图之间的节奏差异。
OpenTofu 还更改了其 OperProvider 校验和的处理方式。依赖锁文件历来是团队内部产生轻微摩擦的根源,特别是在使用共享提供程序插件缓存或本地镜像的配置中。运行 tofu init 会将 zh: 格式的校验和填入锁定文件,但随后你需要单独运行 tofu providers lock 命令,才能获取缓存或镜像所需的 h1: 格式校验和。OpenTofu 1.12 在注册表层修复了这一问题:OpenTofu 注册表现在会同时返回两种格式的校验和集合,因此, tofu init 只需一次运行就可以填入所有内容。升级后首次运行 init 时,你会看到锁定文件中出现了新的 h1: 条目,这是符合预期的正常行为。tofu providers lock 命令仍然保留着其原始用途:当你并非直接从 OpenTofu 注册表安装时,用于填充校验和。
第三个值得注意的新增功能是 -json-into=FILENAME 标志。现在,如果你希望从 OpenTofu 命令中获得机器可读的输出,就可以使用 -json。这会完全取代人类可读的终端输出。此前,任何基于 OpenTofu 输出构建工具的人,都必须先复现整个用户界面,才能发布任何有用的东西。新标志会将 JSON 流发送到文件(或命名管道,或用于并发处理的 /dev/fd/N),并保留正常的终端输出。如果你正在为内部平台创建一个显示应用程序实时进度的 UI,那么这会使集成过程变得更加简洁。你不需要在两种输出模式之间做选择。
该版本还新增了一个元参数:destroy = false。这会将资源从状态中移除,但不会销毁该对象。这是一种更简便的方式,可以实现用户过去通过变通方法 Terraform state rm 所做的事情。
在功能弃用方面,WinRM 配置程序支持将在 1.12 版本中逐步淘汰(会有警告提示),并将于 1.13 版本中完全移除。其底层的 Go 库已经无人维护,建议迁移至 OpenSSH for Windows。如果你仍然在使用 WinRM 运行配置程序,现在是时候开始迁移了,切勿拖延。官方 32 位架构版本也正在逐步淘汰,预计在 1.13 版本中会显示弃用警告,并在随后完全停止发布。
原文链接:https://www.infoq.com/news/2026/05/opentofu-release-terraform/





