1.4.9.1. 重载文件
一般来说 Terraform 会加载模块内所有的 .tf
和 .tf.json
文件,并要求文件内定义了一组无重复的对象。如果两个文件尝试定义同一个对象,那么 Terraform 会报错。
在某些少见场景中,能够用单独的文件重载已有对象配置的特定部分将会十分有用。比如说,由工程师编写的配置文件能够在运行时被程序生成的 JSON 文件部分重载。
为支持这些少见场景,Terraform 会对后缀名为 override.tf
和 override.tf.json
的代码文件进行特殊处理。对于名为 override.tf
和 override.tf.json
的代码文件也会进行相同的特殊处理。
Terraform 一开始加载代码文件时会跳过这些重载文件,然后才会按照字典序一个一个处理重载文件。对重载文件中定义的所有顶级块(resource
、data
等),Terraform 会尝试找到对应的已有对象并且将重载内容合并进已有对象。
重载文件只应使用于特殊场景,过度使用会使得读者在阅读原始代码文件时被迫还要阅读所有的重载文件才能理解对象配置,从而降低了代码的可读性。使用重载文件时,请在原始文件被重载的部分添加相应注释,提醒未来的读者哪些部分会被重载文件修改。
1.4.9.1.1. 例子
如果我们有一个名为 example.tf
的代码文件:
resource "aws_instance" "web" {
instance_type = "t2.micro"
ami = "ami-408c7f28"
}
然后我们创建一个名为 override.tf
的文件:
resource "aws_instance" "web" {
ami = "foo"
}
Terraform 随后会合并两者,实际的配置会是这样的:
resource "aws_instance" "web" {
instance_type = "t2.micro"
ami = "foo"
}
1.4.9.1.2. 合并行为
不同的块类型有着些微不同的合并行为,某些特定块内的特殊构造会以特殊形式被合并。
一般来说:
- 重载文件内的顶级块会和普通文件内同类型同名的顶级块合并
- 重载文件内的顶级块配置册参数会覆盖普通文件内对应块内的同名参数
- 重载块内的内嵌块会取代普通文件内对应块内的所有同类型内嵌块。所有重载块内没有定义的内嵌块在普通文件内保持不变
- 内嵌块的内容不会进行合并
- 合并后的块仍然需要符合对应块类型的所有验证规则
如果有多个重载文件定义了同一个顶级块,那么重载效果是叠加的,后加载的重载块会在先前加载的重载块生效的基础上合并。重载操作首先按照文件名的字典序其次是在重载文件中的位置决定执行顺序。
有一些针对特定顶级块类型的特殊合并行为规则,我们将重载文件中定义的块称为重载块,重载块在普通文件中对应的块称为源块:
1.4.9.1.2.1. 合并 resource 块以及合并 data 块
在 resource
块内,所有 lifecycle
块的内容会按照参数逐条合并。比如说,一个重载块只定义了 create_before_destroy
参数而源块定义了 ignore_changes
,那么 create_before_destroy
被合并的同时 igonore_changes
将会被保留。
如果重载的 resource
块包含了一个或多个 provisioner
,那么源块内所有的 provisioner
会被忽略。
如果重载的 resource
块内包含了一个 connection
块,那么它将会完全覆盖所有源块内定义的 connection
块
不允许在重载块内定义 depends_on
参数,那将会引发一个错误。
1.4.9.1.2.2. 合并 variable 块
variable
块内参数的合并遵循上述的标准流程,但对于 type
和 default
参数的处理会有一些特殊的考虑。
如果源块定义了 default
值而重载块修改了变量的 type
,Terraform 会尝试将 default
值转换成新类型,如果转换失败则会报错。
同样的,如果源块定义了 type
参数而重载块修改了 default
值,那么新的 default
值必须能够被转换成原先的类型。
1.4.9.1.2.3. 合并 output 块
不允许在重载块内定义 depends_on
参数,这会引发一个错误。
1.4.9.1.2.4. 合并 locals 块
所有的 locals
块都定义了一个或多个命名值。针对 locals
的合并会是按照命名值的名字逐条执行的,不论命名值是在哪个 locals
块内被定义的。
1.4.9.1.2.5. 合并 terraform 块
如果重载块定义了 required_providers
参数,那么它的值会被逐条合并,这就允许重载块在不影响其他Provider的情况下调整单个 Provider 的版本约束。
重载块内的 requeired_version
和 required_providers
里的配置完全覆盖源块内的相应配置。如果源块和重载块都定义了 required_version
,那么源块的配置会被完全忽略。