1.4.4.1. 输出值
我们在介绍输入变量时提到过,如果我们把一组 Terraform 代码想像成一个函数,那么输入变量就是函数的入参;函数可以有入参,也可以有返回值,同样的,Terraform 代码也可以有返回值,这就是输出值。
大部分语言的的函数只支持无返回值或是单返回值,但是 Terraform 支持多返回值。在当前模块 apply 一段 Terraform 代码,运行成功后命令行会输出代码中定义的返回值。另外我们也可以通过 terraform output
命令来输出当前模块对应的状态文件中的返回值。
1.4.4.1.1. 输出值的声明
输出值的声明使用输出块,例如:
output "instance_ip_addr" {
value = aws_instance.server.private_ip
}
output
关键字后紧跟的就是输出值的名称。在当前模块内的所有输出值的名字都必须是唯一的。output
块内的 value
参数即为输出值,它可以像是上面的例子里那样某个 resource 的输出属性,也可以是任意合法的表达式。
输出值只有在执行 terraform apply
后才会被计算,光是执行 terraform plan
并不会计算输出值。
Terraform 代码中无法引用本目录下定义的输出值。
output
块还有一些可选的属性:
1.4.4.1.1.1. 描述 description
output "instance_ip_addr" {
value = aws_instance.server.private_ip
description = "The private IP address of the main server instance."
}
与输入变量的description
类似,我们不再赘述。
1.4.4.1.1.2. 临时值(ephemeral)—— 避免将值存储到状态或计划文件中
注意:临时输出值是 Terraform v1.10 开始引入的功能
我们可以在子模块中将 output
标记为 ephemeral
,以在模块之间传递临时值,同时避免将这些值保留到状态或计划文件中。这对于管理我们不想存储在 Terraform 状态文件中的凭据、令牌或其他临时资源非常有用。
我们可以通过将 ephemeral
属性设置为 true
将子模块中的输出标记为临时输出值:
# modules/db/main.tf
output "secret_id" {
value = aws_secretsmanager_secret.secret_id
description = "Temporary secret ID for accessing database in AWS."
ephemeral = true
}
Terraform 可以在 plan
和 apply
操作期间访问 output
块的值。在 plan
或 apply
操作结束时,Terraform 不会保存任何临时输出的值。
我们只能在特定上下文中引用临时输出,否则 Terraform 会返回错误。以下是引用临时输出的有效上下文:
注意:我们不可以在根模块中将 output
声明为 ephemeral
。
1.4.4.1.1.3. 在命令行输出中隐藏值 sensitive
一个输出值可以标记 sensitive
为 true
,表示该输出值含有敏感信息。被标记 sensitive
的输出值只是在执行 terraform apply
命令成功后会打印 "<sensitive>"
以取代真实的输出值,执行 terraform output
时也会输出"<sensitive>"
,但仍然可以通过执行 terraform output -json
看到实际的敏感值。
需要注意的是,标记为 sensitive
输出值仍然会被记录在状态文件中,任何有权限读取状态文件的人仍然可以读取到敏感数据。
1.4.4.1.1.4. depends_on
关于 depends_on
的内容将在 resource 章节里详细介绍,所以这里我们只是粗略地介绍一下。
Terraform 会解析代码所定义的各种 data
、resource
,以及他们之间的依赖关系,例如,创建虚拟机时用的 image_id
参数是通过 data
查询而来的,那么虚拟机实例就依赖于这个镜像的 data
,Terraform 会首先创建 data
,得到查询结果后,再创建虚拟机 resource
。一般来说,data
、resource
之间的创建顺序是由 Terraform 自动计算的,不需要代码的编写者显式指定。但有时有些依赖关系无法通过分析代码得出,这时我们可以在代码中通过 depends_on
显式声明依赖关系。
一般 output
很少会需要显式依赖某些资源,但有一些特殊场景,例如某些资源的属性必须在另外一些资源被创建后才能被读取,这种情况下我们可以通过 depends_on
来显式声明依赖关系。
depends_on
的用法如下:
output "instance_ip_addr" {
value = aws_instance.server.private_ip
description = "The private IP address of the main server instance."
depends_on = [
# Security group rule must be created before this IP address could
# actually be used, otherwise the services will be unreachable.
aws_security_group_rule.local_access,
]
}
我们不鼓励针对 output
定义depends_on
,只能作为最后的手段加以应用。如果不得不针对 output
定义depends_on
,请务必通过注释说明原因,方便后人进行维护。
1.4.4.1.1.5. 断言 precondition
output
块从 Terraform v1.2.0 开始也可以包含一个 precondition
块。
output
块上的 precondition
对应于 variable
块中的 validation
块。validation
块检查输入变量值是否符合模块的要求,precondition
则确保模块的输出值满足某种要求。我们可以通过 precondition
来防止 Terraform 把一个不合法的输入值写入状态文件。我们可以在合适的场景下通过 precondition
来保护上一次 apply
留下的合法的输出值。
Terraform 在计算输出值的 value
表达式之前执行 precondition
检查,这可以防止 value
表达式中的潜在错误被激发。