1.4.7.1. 数据源
数据源允许查询或计算一些数据以供其他地方使用。使用数据源可以使得 Terraform 代码使用在 Terraform 管理范围之外的一些信息,或者是读取其他 Terraform 代码保存的状态。
每一种 Provider 都可以在定义一些资源类型的同时定义一些数据源。
1.4.7.1.1. 使用数据源
数据源通过一种特殊的资源访问:data
资源。数据源通过 data
块声明:
data "aws_ami" "example" {
most_recent = true
owners = ["self"]
tags = {
Name = "app-server"
Tested = "true"
}
}
一个 data
块请求 Terraform 从一个指定的数据源 aws_ami
读取指定数据并且把结果输出到 Local Name 为 example
的实例中。我们可以在同一模块内的代码中通过数据源名称来引用数据源,但无法从模块外部直接访问数据源。
同资源类似,一个数据源类型以及它的名称一同构成了该数据源的标识符,所以数据源类型加名称的组合在同一模块内必须是唯一的。
在 data
块体({
与 }
中间的内容)是传给数据源的查询条件。查询条件参数的种类取决于数据源的类型,在上述例子中,most_recent
、owners
和 tags
都是定义查询 aws_ami
数据源时使用的查询条件。
与数据源这种特殊资源不同的是,我们在上一节介绍的主要资源(使用 resource
块定义的)是一种“托管资源”。这两种资源都可以接收参数并对外输出属性,但托管资源会触发 Terraform 对基础设施对象进行增删改操作,而数据源只会触发读取操作。简单来说,我们一般说的“资源”就是特指托管资源。
1.4.7.1.2. 数据源参数
每一种数据源资源都关联到一种外部数据源,数据源类型决定了它接收的查询参数以及输出的数据。每一种数据源类型都属于一个 Provider。大部分 data
块内的数据源参数都是由对应的数据源类型定义的,这些参数的赋值可以使用完整的 Terraform 表达式能力或其他 Terraform 语言的功能。
然而类似资源,Terraform 也为所有类型的数据源定义了一些元参数。这些元参数的限制和功能我们将在后续节当中叙述。
1.4.7.1.3. 数据源行为
如果数据源的查询参数涉及到的表达式只引用了字面量或是在执行 terraform plan
时就已知的数据(比如输入变量),那么数据源会在执行 Terraform 的 "refersh" 阶段时被读取,然后 Terraform 会构建变更计划。这保证了在制定变更计划时 Terraform 可以使用这些数据源的返回数据。
如果查询参数的表达式引用了那些只有执行部分执行变更计划以后才能知晓的数据,比如另一个还未被创建的托管资源的输出,那么数据源的读取操作会被推迟到 "apply" 阶段。以下几种情况下 Terraform 会推迟数据源的读取:
- 给定的参数中至少有一个是一个托管资源的属性或是其他值,Terraform 在执行步骤之前无法预测。
data
块内的查询参数引用了一个还未被创建的托管资源的输出。data
块内声明的precondition
或postcondition
直接或间接地依赖了一个在当前计划中有变更的托管资源。
任何引用该数据源输出的表达式的值在执行到数据源被读取完之前都是未知的。
1.4.7.1.4. 本地数据源
虽然绝大多数数据源都对应了一个通过远程基础设施 API 访问的外部数据源,但是也有一些特殊的数据源仅存在于 Terraform 进程内部,计算并对外输出一些数据。
比如说,本地数据源有 template_file
、local_file
、aws_iam_policy_document
等。
本地数据源的行为与其他数据源完全一致,但他们输出的结果数据只是临时存在于 Terraform 运行时,每次计算一个新的变更计划时这些值都会被重新计算。
1.4.7.1.5. 数据源的依赖关系
数据源有着与资源一样的依赖机制,我们也可以在 data
块内设置 depends_on
元参数来显式声明依赖关系,在此不再赘述。
注意:在 Terraform 0.12 及更早版本中,由于 data
会将尚不知晓值的读取推迟到 Apply 阶段,因此将 dependent_on
与 data
一起使用将强制将数据的读取推迟到 Apply 阶段,因此,使用 depends_on
的 data
数据源配置永远无法收敛。由于这种行为,我们不建议对 data
使用 depends_on
。
1.4.7.1.6. Precondition 与 Postcondition
您可以使用 precondition
和 postcondition
块来指定有关 data
如何运行的假设和验证。以下实力创建一个 postcondition
来检查 AMI 是否具有正确的标签:
data "aws_ami" "example" {
id = var.aws_ami_id
lifecycle {
# The AMI ID must refer to an existing AMI that has the tag "nomad-server".
postcondition {
condition = self.tags["Component"] == "nomad-server"
error_message = "tags[\"Component\"] must be \"nomad-server\"."
}
}
}
自定义条件检查可以声明对数据的假设,帮助未来的维护人员了解代码的设计和意图。它们还可以更早地在上下文中返回有关错误的有用信息,帮助使用者更轻松地诊断其配置中的问题。
1.4.7.1.7. 生命周期
同资源不一样,数据源目前的 lifecycle
块中只支持 precondition
和 postcondition
块。
1.4.7.1.8. 多数据源实例
与资源一样,数据源也可以通过设置 count
、for_each
元参数来创建一组多个数据源实例,并且 Terraform 也会把每个数据源实例单独创建并读取相应的外部数据,对 count.index
与 each
的使用也是一样的,在 count
与 for_each
之间选择的原则也是一样的。
1.4.7.1.9. 指定特定 Provider 实例
同资源一样,数据源也可以通过 provider
元参数指定使用特定 Provider 实例,在此不再赘述。
1.4.7.1.10. 例子
一个数据源定义例子如下:
# Find the latest available AMI that is tagged with Component = web
data "aws_ami" "web" {
filter {
name = "state"
values = ["available"]
}
filter {
name = "tag:Component"
values = ["web"]
}
most_recent = true
}
1.4.7.1.11. 引用数据源
引用数据源数据的语法是data.<TYPE>.<NAME>.<ATTRIBUTE>
:
resource "aws_instance" "web" {
ami = data.aws_ami.web.id
instance_type = "t1.micro"
}