- OpenTofu 语言
- OpenTofu v1.x 兼容性承诺
OpenTofu v1.x 兼容性承诺
OpenTofu v1.6 的发布代表着 OpenTofu 语言和工作流程开发中的一个重要里程碑。OpenTofu v1.x 是一个描述和管理基础设施的稳定平台。
在此版本中,我们定义了一些 OpenTofu 行为,我们打算在整个 1.x 版本中保持兼容。
- OpenTofu 语言功能的大部分子集。
- OpenTofu CLI 工作流命令的一个更保守的子集。
- OpenTofu Core 和 OpenTofu 提供程序之间通信的线协议。
- 提供程序和外部模块安装的线协议。
我们的目标是,为 OpenTofu v1.6 编写的模块将继续成功地进行计划和应用,无需修改,贯穿整个 v1.x 版本。
我们还打算,围绕本文档中描述的工作流子集构建的自动化将在所有未来的 v1.x 版本中无需更改即可工作。
最后,我们打算,根据当前记录的提供程序线协议构建的提供程序将与所有未来的 OpenTofu v1.x 版本(针对相同的操作系统和架构)兼容,无需修改源代码或重新编译二进制文件。
简而言之,我们的目标是使 v1.x 版本之间的升级变得简单,无需更改您的配置,无需运行额外的命令来执行升级步骤,也无需更改您围绕 OpenTofu 设置的任何自动化。
OpenTofu v1.x 系列将在 v1.6 发布后至少维护 18 个月。
以下部分包含一些关于我们在整个 v1.x 系列中将承诺的内容的具体指导,供希望获得完整详细信息的用户参考。但在更高的层次上,我们不打算进行任何会导致现有模块或自动化在升级到新的 v1.x 版本时需要更改的更改。我们通常会将新的 OpenTofu CLI 版本中的兼容性问题视为需要修复的错误,除非更改有非常充分的理由,例如解决关键的安全问题或匹配与我们无法直接控制的远程依赖项的重大更改。
OpenTofu 语言
主要的 OpenTofu 语言包括语言语法、顶级结构(如 resource
、module
和 provider
块)、这些块中的“元参数”以及表达式中可用的运算符和内置函数的已记录语义和行为。
OpenTofu 语言没有单一的正式规范,但 OpenTofu 网站上的文档的“配置”部分充当了语言功能及其预期行为的描述。
以下顶级块及其定义的“元参数”(即由 OpenTofu Core 而不是外部插件(如提供程序)定义的参数)将保留其当前功能
resource
和data
块用于声明资源,包括其嵌套的块类型lifecycle
、connection
和provisioner
,以及它们的元参数provider
。module
块用于调用其他模块,以及其元参数providers
。resource
、data
和module
块中的count
、for_each
和depends_on
元参数。provider
块用于配置提供程序,以及alias
元参数。variable
、output
和locals
块用于声明模块中各种类型的命名值。terraform
块,包括嵌套的required_version
和required_providers
参数,以及嵌套的backend
块用于后端配置。
我们还打算保持与所有 表达式运算符 和 内置函数 的兼容性,但 terraform.workspace
的引用除外,其行为可能会随着未来对工作区模型的更改而改变。
我们打算保留与 OpenTofu 语言功能的广泛兼容性,但也有一些具体的注意事项
-
如果 OpenTofu 可以创建并应用配置的计划,而无需报告任何错误,则我们认为该配置有效。
当前产生错误的配置可能会在 OpenTofu 的未来版本中生成不同的错误或表现出其他非错误行为。在应用阶段生成错误的配置可能会在未来在更早的阶段生成类似的错误,因为我们通常认为在尽可能早的阶段检测到错误更好。
一般来说,本文档中描述的兼容性承诺仅适用于有效配置。对无效配置的处理始终会随着未来 OpenTofu 版本的发布而发生变化。
-
如果某个功能的实际行为与我们明确记录的功能行为不同,我们通常会将其视为错误并更改该功能以匹配文档,尽管如果这些更改似乎可能导致广泛的兼容性问题,我们会避免进行此类更改。我们不能保证始终与以前的版本保持“错误兼容”,但我们会仔细考虑此类修复以最大程度地减少其影响。
-
任何实验性功能都可能在未来的版本中发生更改或完全删除。当实验性语言功能处于活动状态时,OpenTofu 始终会发出警告,以让您了解该风险。我们建议不要在生产模块中使用实验性功能。
-
我们将引入新的语言功能,如果您开始使用它们,那么您的配置将无法与之前不支持这些功能的 OpenTofu 版本一起使用。
-
提供程序是独立的插件,可以独立于 OpenTofu Core 更改,因此不受这些兼容性承诺的约束。如果您升级了正在使用的任何提供程序,则可能需要更改与这些提供程序相关的提供程序或资源配置。
-
OpenTofu v1.6 中仍有少量功能已弃用,并带有明确的警告。这些弃用周期将在未来的 v1.x 版本中结束,届时我们将移除相应的功能。
工作流程
有一组常用的 OpenTofu 工作流程,我们称之为受保护的工作流程。我们不会移除这些命令、子命令和标志,也不会对受保护工作流程的功能进行向后不兼容的更改。如果我们意外更改了这些内容,我们将视核心工作流程的向后不兼容更改为需要修复的错误。有关构成受保护工作流程的命令和选项组合的列表,请参阅受保护的工作流程命令。还有一组命令,我们明确地不对其进行兼容性承诺,因为我们预计它们的功能将在 v1.x 版本中发生变化:请参阅可能发生变化的命令。
外部软件与 OpenTofu 交互的支持方式是通过某些命令提供的 JSON 输出模式以及退出状态码。我们可能会扩展某些 JSON 格式以添加新的对象属性,但不会移除或对现有属性的定义进行重大更改。
自然语言命令输出或日志输出不是稳定的接口,可能会在任何新版本中发生更改。如果您编写解析此输出的软件,则在升级 OpenTofu 时可能需要更新它。如果您需要访问当前无法通过其中一个机器可读 JSON 接口获得的数据,我们建议您提交功能请求以讨论您的用例。
升级和降级
在整个 v1.x 系列版本中,我们希望您能够切换到更新的 OpenTofu 版本并像以前一样使用它,无需任何特殊的升级步骤。
您应该能够从任何 v1.x 版本升级到任何更高版本的 v1.x 版本。您也可能能够降级到早期 v1.x 版本,但这不能保证:更高版本可能会引入早期版本无法理解的新功能,包括 OpenTofu 状态快照的新存储格式。
如果您使用了在更高版本的 v1.x 版本中引入的功能,您的配置将与早于该功能的版本不兼容。例如,如果在 v1.7 中添加了语言功能并且您开始使用它,则您的 OpenTofu 配置将不再与 OpenTofu v1.6 兼容。
提供程序
OpenTofu 提供程序是使用已记录协议与 OpenTofu 通信的独立插件。因此,这些兼容性承诺只能涵盖 OpenTofu Core 实现的此协议的“客户端”端;各个提供程序的行为,包括它们支持的资源类型以及它们期望的参数,由提供程序开发团队决定,并且可以独立于 OpenTofu Core 版本发生变化。
如果您升级到新版本的提供程序,则可能需要更改配置中由该提供程序解释的部分,即使您仍在使用 OpenTofu v1.x 版本。
提供程序安装方法
OpenTofu 通常从实现提供程序注册表协议版本 1 的提供程序注册表中安装提供程序。所有 OpenTofu v1.x 版本都将与该协议保持兼容,因此正确实现的提供程序注册表将保持兼容。
OpenTofu 还支持从本地文件系统目录(文件系统镜像)和从网络镜像(实现提供程序镜像协议)安装提供程序。所有 OpenTofu v1.x 版本都将与这些安装方法保持兼容,包括隐式本地镜像目录。
特定的提供程序注册表或网络镜像独立于 OpenTofu 本身运行,因此它们自己的行为不受这些兼容性承诺的约束。
提供程序协议版本
截至 OpenTofu v1.6,提供程序插件协议的当前主版本为版本 5,它由描述物理线格式的 Protocol Buffers 模式和描述预期提供程序行为的其他散文文档共同定义。
我们将在整个 OpenTofu v1.x 版本中支持协议版本 5。如果我们在以后的版本中对协议版本 5 进行新的次要修订,我们将对其进行设计,以便现有的插件可以继续工作,只要它们正确地实现了协议。
我们可能会在 v1.x 系列期间引入新的协议主版本。如果是这样,我们将继续支持协议版本 5 以及这些新版本。各个提供程序团队可能会决定在以后的版本中移除对协议版本 5 的支持,在这种情况下,这些新的提供程序版本将与所有 OpenTofu v1.x 版本不兼容。
外部模块
模块是用 OpenTofu 语言编写的可重用基础设施组件。某些模块在某种意义上是“外部的”,因为 OpenTofu 会自动从当前配置目录以外的位置安装它们,在这种情况下,它们的内容可能会独立于对本地模块、您使用的提供程序以及 OpenTofu 本身的更改而发生变化。
模块安装方法
OpenTofu 支持从许多不同的模块源类型安装子模块。我们将继续在整个 v1.x 版本中支持所有现有的源类型。
支持的源类型之一是实现模块注册表协议版本 1 的模块注册表。所有 OpenTofu v1.x 版本都将与该协议的正确实现保持兼容。
某些模块源类型直接使用由第三方定义和运行的服务或协议。尽管我们不会移除 OpenTofu 自身的客户端对这些的支持,但我们不能保证它们的拥有者会继续运行这些服务,或者它们会与 OpenTofu 的客户端实现保持兼容。
外部模块兼容性
如果您的配置依赖于外部模块,则这些模块的更新版本可能包含重大更改。外部模块不是 OpenTofu 的一部分,因此不受这些兼容性承诺的约束。
供应器
我们将通过所有 v1.x 版本维护 file
、local-exec
和 remote-exec
供应器类型的兼容性。
OpenTofu 支持从某些本地文件系统目录加载其他供应器作为插件。我们将继续在整个 OpenTofu v1.x 版本中支持这一点,但由于此类插件与 OpenTofu Core 本身是分开的,因此它们自己的行为不受这些兼容性承诺的约束。但是,我们将继续支持在 OpenTofu v1.6 中定义的插件线协议,因此正确实现的供应器插件应与未来的 OpenTofu 版本保持兼容。
状态存储后端
当您使用远程状态时,OpenTofu 会通过网络与远程服务交互,以存储和管理 OpenTofu 状态的锁。
出于历史原因,所有支持的状态存储后端都包含在 OpenTofu CLI 中,但并非所有后端都由 OpenTofu 团队直接支持。只有以下由 OpenTofu 团队维护的后端受兼容性承诺约束
local
(默认值,当您不使用远程状态时)http
其他状态存储后端由外部团队通过对 OpenTofu CLI 代码库的贡献进行维护,因此即使在 v1.x 版本中,它们预期的配置参数或行为也可能会发生变化,尽管在可能的情况下,我们将努力确保良好的迁移路径。
我们正在考虑允许通过插件实现外部状态存储后端,类似于提供程序插件。如果我们在 v1.x 版本期间引入了这种机制,则您可能需要进行配置更改才能使用这些插件,并且一旦有等效的插件可用,OpenTofu CLI 的更高版本可能会移除除上述列出的后端以外的其他状态存储后端。
remote
后端
remote
后端的行为可能会发生变化,因此不受这些兼容性承诺的约束。
社区维护的状态存储后端
azurerm
、consul
、s3
和 kubernetes
后端由 HashiCorp 的其他团队维护。这些团队打算在整个 v1.x 版本中继续进行基本维护(例如错误修复),除非我们为后端实现了插件协议,届时这些后端的开发可能会仅在外部插件中继续进行,这可能需要进行配置更改才能切换到插件等效项。
cos
、oss
、pg
、gcs
和 etcdv3
后端由外部贡献者维护,不受这些兼容性承诺的约束。
未维护的状态存储后端
artifactory
、etcdv2
、manta
和 swift
状态存储后端目前没有任何维护者,因此以尽力而为的方式保留在 OpenTofu CLI 版本中。它们可能会在以后的 v1.x 版本中移除,并且在它们集成的服务发生任何重大更改时都不会更新。
支持的平台
在整个 v1.x 系列中,我们将继续为以下平台发布官方版本,并根据需要进行更改以支持这些操作系统的全新版本
- x64 CPU 上的 macOS(
darwin_amd64
) - x64 CPU 上的 Windows(
windows_amd64
) - x64、32 位 ARMv6 和 64 位 ARMv8 上的 Linux(分别为
linux_amd64
、linux_arm
和linux_arm64
)
随着时间的推移,我们可能会需要这些操作系统的更新版本。例如,v1.x 系列中的后续 OpenTofu 版本可能会停止支持早期版本的 macOS 或 Windows,或者停止支持早期版本的 Linux 内核。
历史上,我们出于方便这些平台的用户而为许多其他平台发布了官方版本,我们目前没有停止发布它们的计划,但我们无法保证在整个 v1.x 系列中持续发布或修复其他平台的错误。我们不会在除上述列出的平台以外的任何平台上例行测试 OpenTofu。
我们可能会在以后的 v1.x 版本中添加对新平台的支持。如果是这样,早于该支持的早期 OpenTofu 版本将无法在这些平台上使用。
所有 OpenTofu 插件,包括提供程序插件,都是独立的程序,它们有自己的平台支持策略。我们无法保证所有提供程序当前都支持或将继续支持上述列出的平台,即使 OpenTofu CLI 本身将支持它们。
这些承诺的后续修订
我们可能会在整个 v1.x 系列中扩展或完善这些承诺,以便描述与新功能相关的承诺,或者如果我们通过反馈发现我们之前的声明不清楚,则澄清现有承诺。
新功能的承诺将是增量的,这意味着它们将添加进一步的承诺,而不会撤回任何现有的承诺。对于仅适用于后续 v1.x 版本的承诺,我们将提及这些承诺适用的最早版本。
即使我们没有在此文档中添加明确的声明,我们也希望在后续 v1.x 版本中添加的任何非实验性功能至少将在整个 v1.x 系列中保持兼容,除非另有说明。
附录
受保护的工作流命令
以下是受这些兼容性承诺约束的 OpenTofu CLI 子命令和选项列表。如果您围绕这些命令构建自动化,则它应该与所有后续的 v1.x 版本兼容。
如上所述,与外部软件的兼容性仅限于显式机器可读输出(-json
和 -raw
模式)和退出代码。这些命令的任何自然语言输出都可能在后续版本中发生变化。
init
-backend=false
-backend-config=FILE
-backend-config="KEY=VALUE"
-force-copy
-get=false
-input=false
-migrate-state
-no-color
-plugin-dir=DIR
-reconfigure
-upgrade
validate
-json
-no-color
plan
-compact-warnings
-destroy
-detailed-exitcode
-lock=false
-lock-timeout=DURATION
-input=false
-json
-no-color
-out=FILE
-parallelism=N
-refresh=false
-refresh-only
-replace=ADDRESS
-target=ADDRESS
-var 'NAME=VALUE'
-var-file=FILE
apply
-auto-approve
-compact-warnings
-lock=false
-lock-timeout=DURATION
-input=false
-json
-no-color
-parallelism=N
-refresh=false
-refresh-only
-replace=ADDRESS
-target=ADDRESS
-var 'NAME=VALUE'
-var-file=FILE
show
-no-color
-json
- (带和不带计划文件)
providers
(无子命令)providers lock
-fs-mirror=PATH
-net-mirror=URL
-platform=OS_ARCH
providers mirror
-platform=OS_ARCH
providers schema
-json
fmt
-list=false
-write=false
-diff
-recursive
-check
version
-json
output
-no-color
-json
-raw
taint
-allow-missing
-lock=false
-lock-timeout=DURATION
-ignore-remote-version
untaint
-allow-missing
-lock=false
-lock-timeout=DURATION
-ignore-remote-version
force-unlock
-force
state list
-id=ID
state pull
state push
-force
-lock=false
-lock-timeout=DURATION
state show
-ignore-remote-version
login
对于不在上述列表中的命令或选项,我们仍将尽可能避免破坏性更改,但无法承诺在整个 v1.x 系列中完全兼容。如果您正在围绕 OpenTofu 构建自动化,请仅使用上述命令以避免在升级时需要进行更改。
请注意,尽管 OpenTofu 的内部日志(通过 TF_LOG
环境变量)以 JSON 格式提供,但这些日志行的特定语法或结构**不是**受支持的集成接口。日志仅以 JSON 格式提供,以帮助 OpenTofu 开发人员进行临时日志过滤和处理。
可能发生更改的命令
以下所有命令及其子命令/选项**均不受**兼容性承诺的约束,因为我们有现有的计划在 v1.x 系列中改进它们,或者因为我们意识到其设计中的不足之处,这些不足之处可能需要破坏性更改才能进行持续维护。
当您以交互方式运行 OpenTofu 时,可以自由使用这些命令(只要它们仍然受支持),但我们不建议将它们用作任何自动化的部分,除非您愿意在升级到后续 v1.x 版本时更新该自动化。
destroy
(请考虑使用tofu apply -destroy
代替)console
get
(请考虑使用tofu init
代替)graph
import
push
refresh
(请考虑使用tofu apply -refresh-only
代替)state mv
state replace-provider
state rm
workspace
的所有子命令(及其已弃用的别名env
)
虽然我们确实打算在未来的版本中保留对与这些命令相关的主要用例的支持,但我们无法承诺保留用于满足这些用例的确切命令名称或选项。
我们将如何履行这些承诺
自动化回归测试
OpenTofu 代码库包含各种单元和集成测试,旨在帮助我们在稳定版本中发布之前发现意外的行为回归。
但是,OpenTofu 是一个相对复杂的系统,它具有许多不同的功能,这些功能可以以有趣的方式交互。在过去,我们看到有报告称行为差异仅在以我们之前没有预料到或编写自动化测试的方式组合两个或多个功能时才会出现。
在每种情况下,我们都实施了更改以解决兼容性问题,并添加了一个或多个集成测试来表示这些功能组合的行为。我们打算继续这种方法,以便我们可以随着时间的推移改进 OpenTofu 的测试覆盖率。
预发布版本
我们预计这些承诺涵盖的大多数意外行为更改都将被现有测试捕获。但是,我们也承认我们的测试套件永远无法完美覆盖所有可能的特性交互或其他边缘情况,因此我们旨在在最终版本中包含每个重大更改之前,将其包含在 alpha 和 beta 版本中。
对于次要版本,我们通常也会在最终版本之前发布至少一个候选版本。候选版本表示计划开发已结束,并且我们已修复了基于 alpha 和 beta 版本报告的任何回归,因此后续的最终版本通常应完全或几乎完全与其最新的候选版本匹配。
最终版本中的回归
对于更模糊的功能组合,回归有可能在预发布期间未被检测到,因此包含在最终版本中。
如果有人在发布后不久发现并报告了此类回归,我们将将其视为错误并对其进行修复,以在将来的版本中恢复以前的行为,除非有非常重要的理由(例如安全建议)。在这些情况下,我们通常会建议受回归影响的任何人保留在以前的版本上,直到问题得到解决,然后直接跳到包含该修复程序的新版本。
您可以通过主动针对 alpha、beta 和候选版本包测试模块来最大程度地降低受最终版本中未发现的回归影响的风险。我们建议仅在隔离的开发或暂存环境中而不是在生产基础设施中执行此操作。如果您在预发布版本中发现与本文档中的承诺相矛盾的行为变化,请在 OpenTofu 的 GitHub 存储库中打开一个问题进行讨论。
延迟报告的回归
在最极端的情况下,可能存在功能组合的回归,这种回归非常罕见,以至于长期未被发现。
在更改包含在更多版本中之后,其他用户依赖于较新行为的可能性越来越大,因此我们需要权衡以决定是否恢复行为会比保留新行为产生更大的负面影响。我们始终会在充分考虑每种独特情况的影响的情况下做出此决定。
您可以通过及时升级到 OpenTofu 的新次要版本和补丁版本并报告在 OpenTofu 的 GitHub 存储库中遇到的任何兼容性问题,来最大程度地降低您的模块受延迟报告的回归影响的风险。
务实的例外
我们本着诚意做出上述承诺,目的是您的编写 OpenTofu 模块或自动化的投资不会因 OpenTofu 的未来更改而失效。但是,像上面这样的广泛承诺不可能涵盖我们在继续开发 OpenTofu 时可能出现的实际问题的全部细微差别。
因此,在某些情况下,我们可能仍然需要进行可能影响现有模块或自动化的更改
- 安全问题:我们可能会意识到存在设计问题,该问题具有重要的安全影响。根据我们对相关风险的判断,我们可能会选择破坏兼容性以实现更安全的系统。
- 外部依赖项:OpenTofu 的行为取决于外部代码库提供的接口,包括您选择的操作系统,以及在模块和提供程序安装等情况下的一些远程网络服务。这些外部系统可能会在我们无法控制的情况下发生变化,包括可能删除或更改 OpenTofu 自身功能依赖的功能。在这种情况下,如果没有合适的替代机制,我们可能需要更改 OpenTofu 的设计以适应新的约束。
- 选择加入的兼容性中断:一种语言的新功能的设计可能需要更改现有功能的行为或配置表示。如果是这样,我们通常只会让新功能选择加入以避免破坏现有模块,但是如果您更改模块以选择加入新功能,那么您也可能需要更改配置的其他部分以与新的语言设计一起使用。
- 新功能中的错误:如果我们在 OpenTofu 中引入一个新功能,并且初始实现存在问题导致其在发布时与记录的设计意图不符,我们可能会发布后续版本来修正实现以匹配记录的设计,即使这与初始实现相比代表了一个次要的兼容性回归。但是,一旦某个功能得到充分确立并被广泛使用,我们通常会默认已实现的行为,并改为更改文档以反映它。
- 现有功能的回归:如果我们了解到新的 OpenTofu 版本包含一个在开发和预发布期间未检测到的现有功能的回归,并且此了解是在新版本发布后立即获得的,我们通常会恢复之前的行为,即使这在技术上会导致与新版本的行为不兼容,我们假设受回归影响的用户多于依赖新引入行为的用户。
- 延迟报告的回归:如上一节所述,如果我们了解到在早期的版本中存在一个很少使用的功能或功能组合的意外回归,那么恢复之前的行为可能会对后续采用者表现为回归。如果我们认为修复回归会影响的用户多于回归本身影响的用户,那么我们可能会选择接受回归作为新的承诺行为。
- 我们无法预料的情况:虽然我们努力在这里考虑各种特定的异常情况,但 OpenTofu 及其开发过程并非与更广泛的上下文隔离开来,因此我们必须考虑可能存在我们无法预料的情况会影响 OpenTofu 的未来。在这些情况下,我们将始终尽最大努力找到一种行动方案,最大程度地减少对现有模块和自动化的影响。
我们对这些务实例外情况的意图只是承认,总会有一些情况是一般的兼容性承诺无法解决的。我们只会经过充分考虑并在万不得已的情况下才会使用这些例外情况。