跳至主要内容

覆盖文件

OpenTofu 通常加载目录中所有 .tf.tofu.tf.json.tofu.json 文件,并期望每个文件定义一组不同的配置对象。如果两个文件尝试定义相同的对象,OpenTofu 将返回错误。

在某些罕见情况下,能够在单独的文件中覆盖现有配置对象的特定部分非常方便。例如,可以使用以 JSON 语法编写的程序生成的配置部分覆盖 OpenTofu 语言原生语法中的人工编辑的配置文件。

对于这些罕见情况,OpenTofu 对任何名称以 _override.tf_override.tofu_override.tf.json_override.tofu.json 结尾的配置文件进行特殊处理。此特殊处理也适用于字面名为 override.tfoverride.tofuoverride.tf.jsonoverride.tofu.json 的文件。

OpenTofu 最初在加载配置时会跳过这些覆盖文件,然后依次处理每个文件(按字典顺序)。对于在覆盖文件中定义的每个顶级块,OpenTofu 尝试查找与该块对应的已定义对象,然后将覆盖块的内容合并到现有对象中。

仅在特殊情况下使用覆盖文件。过度使用覆盖文件会降低可读性,因为仅查看原始文件的读者无法轻松地看出这些文件的某些部分已被覆盖,而无需查阅所有存在的覆盖文件。在使用覆盖文件时,请在原始文件中使用注释以警告将来的读者哪些覆盖文件会对每个块进行更改。

示例

如果您有一个 OpenTofu 配置 example.tf,其内容如下所示

代码块
resource "aws_instance" "web" {
instance_type = "t2.micro"
ami = "ami-408c7f28"
}

...并且您创建了一个包含以下内容的文件 override.tf

代码块
resource "aws_instance" "web" {
ami = "foo"
}

OpenTofu 将后者合并到前者中,其行为就像原始配置如下所示

代码块
resource "aws_instance" "web" {
instance_type = "t2.micro"
ami = "foo"
}

合并行为

每种块类型的合并行为略有不同,某些块中的某些特殊构造以特殊方式合并。

适用于大多数情况的一般规则是

  • 覆盖文件中的顶级块与普通配置文件中具有相同块头的块合并。块是块类型以及跟随其后的任何带引号的标签。

  • 在顶级块内,覆盖块中的属性参数将替换原始块中任何同名参数。

  • 在顶级块内,覆盖块中的任何嵌套块将替换原始块中所有相同类型的块。覆盖块中未出现的任何块类型将保留自原始块。

  • 嵌套配置块的内容不会合并。

  • 生成的合并块必须仍然符合适用于给定块类型的任何验证规则。

如果多个覆盖文件定义了相同的顶级块,则覆盖效果将叠加,后面的块优先于前面的块。覆盖按文件名(按字典顺序)然后按每个文件中的位置顺序处理。

以下部分描述了适用于某些顶级块类型内特定参数的特殊合并行为。

合并 resourcedata

resource 块内,任何 lifecycle 嵌套块的内容将按参数逐个基础进行合并。例如,如果覆盖块仅设置 create_before_destroy 参数,则原始块中的任何 ignore_changes 参数将被保留。

如果覆盖 resource 块包含一个或多个 provisioner 块,则原始块中的任何 provisioner 块将被忽略。

如果覆盖 resource 块包含 connection 块,则它将完全覆盖原始块中存在的任何 connection 块。

depends_on 元参数不能在覆盖块中使用,否则将产生错误。

合并 variable

variable 块内的参数以上面描述的标准方式合并,但由于 typedefault 参数之间的交互,会有一些特殊考虑因素。

如果原始块定义了 default 值,并且覆盖块更改了变量的 type,则 OpenTofu 将尝试将默认值转换为覆盖的类型,如果此转换不可行,则会产生错误。

相反,如果原始块定义了 type,并且覆盖块更改了 default,则覆盖的默认值必须与原始类型规范兼容。

合并 output

depends_on 元参数不能在覆盖块中使用,否则将产生错误。

合并 locals

每个 locals 块定义了一些命名值。覆盖是基于逐值应用的,忽略它们是在哪个 locals 块中定义的。

合并 terraform

合并时,terraform 块中的设置会被单独考虑。

如果设置了 required_providers 参数,则其值将基于逐元素进行合并,这允许覆盖块调整单个提供程序的约束,而不会影响其他提供程序的约束。

required_versionrequired_providers 设置中,每个覆盖约束都会完全替换原始块中相同组件的约束。如果基础块和覆盖块都设置了 required_version,则完全忽略基础块中的约束。

覆盖文件中定义后端块(cloudbackend)的存在始终优先于原始配置中定义的后端块。也就是说,如果原始配置中设置了 cloud 块,而在覆盖文件中设置了 backend 块,则 OpenTofu 在合并时将使用覆盖文件中指定的 backend 块。类似地,如果原始配置中设置了 backend 块,而在覆盖文件中设置了 cloud 块,则 OpenTofu 在合并时将使用覆盖文件中指定的 cloud 块。