跳至主要内容

templatefile 函数

templatefile 读取给定路径下的文件,并使用提供的模板变量集将其内容作为模板呈现。

代码块
templatefile(path, vars)

模板语法与 主 OpenTofu 语言中的字符串模板 相同,包括用 ${ ... } 分隔的插值序列。此函数只是允许将更长的模板序列分解为单独的文件以提高可读性。

“vars” 参数必须是一个对象。在模板文件中,映射中的每个键都可用作插值的变量。模板也可以使用 OpenTofu 语言中可用的任何其他函数。变量名必须以字母开头,后跟零个或多个字母、数字或下划线。

OpenTofu 语言中的字符串是 Unicode 字符序列,因此此函数将解释文件内容为 UTF-8 编码的文本,并返回生成的 Unicode 字符。如果文件包含无效的 UTF-8 序列,则此函数将产生错误。

此函数只能用于 OpenTofu 运行开始时磁盘上已存在的文件。函数不参与依赖项图,因此此函数不能用于在 OpenTofu 操作期间动态生成的。文件。

*.tftpl 是推荐用于模板文件的命名模式。OpenTofu 不会阻止您使用其他名称,但遵循此约定将有助于您的编辑器了解内容,并可能因此提供更好的编辑体验。

递归

如果将递归与 templatefile 一起使用,需要注意一些限制。

templatefile 的任何递归调用将具有有限的调用深度(默认情况下为 1024)。这是为了防止因意外的无限递归调用而导致的崩溃,并限制内存不足崩溃的可能性。

由于不支持尾递归,因此在调用栈可以展开之前,必须将调用栈中的所有文档加载到内存中。在大多数现代系统和配置上,这可能不会出现问题,但值得注意。

如果在执行过程中达到最大递归深度,将提供一个简洁的错误,该错误描述调用栈的前几步,以帮助您诊断问题。如果您需要完整的调用栈,请设置 TF_LOG=debug 将导致完整的 templatefile 调用栈打印到控制台。

如果您的配置需要更大的最大递归深度,您可以使用 TF_TEMPLATE_RECURSION_DEPTH 环境变量覆盖默认值。不推荐这样做,只作为紧急情况下的解决方法提供。此外,将其设置为低于 1024 的默认值可能会导致使用 templatefile 函数的模块出现问题。

示例

列表

给定一个模板文件 backends.tftpl,其内容如下

代码块
%{ for addr in ip_addrs ~}
backend ${addr}:${port}
%{ endfor ~}

templatefile 函数呈现模板

代码块
> templatefile("${path.module}/backends.tftpl", { port = 8080, ip_addrs = ["10.0.0.1", "10.0.0.2"] })
backend 10.0.0.1:8080
backend 10.0.0.2:8080

映射

给定一个模板文件 config.tftpl,其内容如下

代码块
%{ for config_key, config_value in config }
set ${config_key} = ${config_value}
%{ endfor ~}

templatefile 函数呈现模板

代码块
> templatefile(
"${path.module}/config.tftpl",
{
config = {
"x" = "y"
"foo" = "bar"
"key" = "value"
}
}
)
set foo = bar
set key = value
set x = y

从模板生成 JSON 或 YAML

如果您要生成的字符串将采用 JSON 或 YAML 语法,那么编写一个模板来生成有效的 JSON 或 YAML,以便在使用大量单独的插值序列和指令时被正确解释,通常会很麻烦和乏味。

相反,您可以编写一个模板,该模板仅包含对 jsonencodeyamlencode 的单个插值调用,使用 正常的 OpenTofu 表达式语法 指定要编码的值,如以下示例所示

代码块
${jsonencode({
"backends": [for addr in ip_addrs : "${addr}:${port}"],
})}
代码块
${yamlencode({
"backends": [for addr in ip_addrs : "${addr}:${port}"],
})}

给定与上一节中的 backends.tftpl 示例相同的输入,这将生成给定数据结构的有效 JSON 或 YAML 表示,而无需手动处理转义或分隔符。在上面的最新示例中,基于 ip_addrs 元素的重复是通过使用 for 表达式 而不是使用 模板指令 来实现的。

代码块
{"backends":["10.0.0.1:8080","10.0.0.2:8080"]}

如果生成的模板很小,您可以选择在主配置文件中内联编写 jsonencodeyamlencode 调用,并且根本不需要创建单独的模板文件。

代码块
locals {
backend_config_json = jsonencode({
"backends": [for addr in ip_addrs : "${addr}:${port}"],
})
}

有关更多信息,请参阅 jsonencodeyamlencode 的主要文档。

  • file 从磁盘读取文件并返回其字面内容,没有任何模板解释。
  • templatestring 使用提供的模板变量集,将字符串作为模板呈现。