在 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 个陷阱:

就这样?即:

  1. 添加 id 属性。
  2. Computed 属性 替换为 RequiredOptional

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已经是字符串类型,则不需要转换。