在 Terraform Providers 中实现数据源和资源有什么区别?
What's the difference between implementing data sources and resources in Terraform Providers?
上下文:我正在开发一个 TF 提供程序。
我找到了这个 HashiCorp 关于开发 TF 提供程序的 tutorial。
假设我已经为 TF 提供程序实施了资源 order
:
func resourceOrder() *schema.Resource {
return &schema.Resource{
CreateContext: resourceOrderCreate,
ReadContext: resourceOrderRead,
UpdateContext: resourceOrderUpdate,
DeleteContext: resourceOrderDelete,
Schema: map[string]*schema.Schema{...}
}
}
为了实现数据源 order
我几乎可以复制 resourceOrderRead
是否正确,但有 2 个陷阱:
就这样?即:
- 添加
id
属性。
- 将
Computed
属性 替换为 Required
或 Optional
。
I 运行 HashiCorp 教程提供的示例的并排差异:
而且它们看起来确实非常相似(假设 strconv.Itoa(d.Get("id").(int))
在语义上与 d.Id()
相同)。
是的,资源的读取函数通常可以很容易地转换为数据的读取函数。但是,您上面列出的那两项仅特定于本教程的订购咖啡示例。您需要针对您的特定提供商相应地调整它们,以了解那里存在的任何特定微妙之处。为了帮助解决这一点,这就是为什么需要进行这两项修改的原因。
顶级 ID 属性 -
在资源中,这将在创建或更新函数操作期间确定。因此,这将在代码执行期间计算,并且无法提前知道。如教程中所述,代码执行从 API 生成订单 ID,然后提供商将其存储在状态中作为 ID。在数据源中,这个ID已经存在了,因为只有一个Read函数对pre-existing资源进行了Read操作,所以这个ID是提前存在的。如果 ID 是资源的顶级属性,那么它还需要能够“预见未来”以确定订单和资源 ID 存在之前。
需要的项目未计算 -
并非每次都会在资源中计算您的所有属性。这恰好是本教程中的情况。这成为必需的原因与上面的推理相似。在 Create 或 Update 函数期间,这些属性可能不会在 Terraform 配置的资源参数中指定,因此这些属性是在代码执行期间计算的。这些函数针对 API 端点和响应负载中这些属性的 API returns 值调用。因此,属性值是“计算出来的”,而不是指定为与属性对应的参数的输入值。对于数据源,这些将成为必需的,因为它们都提前存在,并且不被计算。此外,还需要指定它们,以便 Read 函数正确识别所需的资源,并且 returns 数据源只有一个资源。
strconv.Itoa(d.Get("id").(int))
发生这种情况是因为 API 的响应负载中返回的 ID 是一个整数:
order = {
"id" = 1
"items" = [
{
"coffee_description" = ""
"coffee_id" = 1
"coffee_image" = "/packer.png"
"coffee_name" = "Packer Spiced Latte"
"coffee_price" = 350
"coffee_teaser" = "Packed with goodness to spice up your images"
"quantity" = 4
},
...
}
需要在 public Get
函数之后将其转换为字符串(如代码中所示,它需要类型 int
),因为这是Terraform 的 ID。如果ID已经是字符串类型,则不需要转换。
上下文:我正在开发一个 TF 提供程序。
我找到了这个 HashiCorp 关于开发 TF 提供程序的 tutorial。
假设我已经为 TF 提供程序实施了资源 order
:
func resourceOrder() *schema.Resource {
return &schema.Resource{
CreateContext: resourceOrderCreate,
ReadContext: resourceOrderRead,
UpdateContext: resourceOrderUpdate,
DeleteContext: resourceOrderDelete,
Schema: map[string]*schema.Schema{...}
}
}
为了实现数据源 order
我几乎可以复制 resourceOrderRead
是否正确,但有 2 个陷阱:
就这样?即:
- 添加
id
属性。 - 将
Computed
属性 替换为Required
或Optional
。
I 运行 HashiCorp 教程提供的示例的并排差异:
strconv.Itoa(d.Get("id").(int))
在语义上与 d.Id()
相同)。
是的,资源的读取函数通常可以很容易地转换为数据的读取函数。但是,您上面列出的那两项仅特定于本教程的订购咖啡示例。您需要针对您的特定提供商相应地调整它们,以了解那里存在的任何特定微妙之处。为了帮助解决这一点,这就是为什么需要进行这两项修改的原因。
顶级 ID 属性 -
在资源中,这将在创建或更新函数操作期间确定。因此,这将在代码执行期间计算,并且无法提前知道。如教程中所述,代码执行从 API 生成订单 ID,然后提供商将其存储在状态中作为 ID。在数据源中,这个ID已经存在了,因为只有一个Read函数对pre-existing资源进行了Read操作,所以这个ID是提前存在的。如果 ID 是资源的顶级属性,那么它还需要能够“预见未来”以确定订单和资源 ID 存在之前。
需要的项目未计算 -
并非每次都会在资源中计算您的所有属性。这恰好是本教程中的情况。这成为必需的原因与上面的推理相似。在 Create 或 Update 函数期间,这些属性可能不会在 Terraform 配置的资源参数中指定,因此这些属性是在代码执行期间计算的。这些函数针对 API 端点和响应负载中这些属性的 API returns 值调用。因此,属性值是“计算出来的”,而不是指定为与属性对应的参数的输入值。对于数据源,这些将成为必需的,因为它们都提前存在,并且不被计算。此外,还需要指定它们,以便 Read 函数正确识别所需的资源,并且 returns 数据源只有一个资源。
strconv.Itoa(d.Get("id").(int))
发生这种情况是因为 API 的响应负载中返回的 ID 是一个整数:
order = {
"id" = 1
"items" = [
{
"coffee_description" = ""
"coffee_id" = 1
"coffee_image" = "/packer.png"
"coffee_name" = "Packer Spiced Latte"
"coffee_price" = 350
"coffee_teaser" = "Packed with goodness to spice up your images"
"quantity" = 4
},
...
}
需要在 public Get
函数之后将其转换为字符串(如代码中所示,它需要类型 int
),因为这是Terraform 的 ID。如果ID已经是字符串类型,则不需要转换。