Terraform 提供程序应如何处理应用于服务器端的默认值?

Grz*_*zki 1 go terraform

上下文:我正在实现(我的第一个)Terraform 插件/提供程序作为现有公共 API 的包装器。

API 中的创建操作之一指定了一个整数字段,该字段采用正值或-1作为默认值。如果您-1在 create API 调用中指定,该值将被服务器端的某个默认值替换(例如field = 1000),并1000从现在开始存储。

如果我将其呈现给我的 Terraform 插件 ( terraform apply):

resource "something" "mysomething" {
  name  = "someName"
  field = -1
}
Run Code Online (Sandbox Code Playgroud)

调用不是幂等的。Terraform 继续看到漂移,随后提供:

  # something.mysomething will be updated in-place
  ~ resource "something" "mysomething" {
        id               = "165-1567498530352"
        name             = "someName"
      ~ field            = 1000 -> -1
    }

Plan: 0 to add, 1 to change, 0 to destroy.
Run Code Online (Sandbox Code Playgroud)

如何处理这样的API?

yda*_*coR 5

您可以使用DiffSuppressFunc架构属性上的标志来有条件地抑制差异,以便 Terraform 不会选择对差异执行任何操作。

这样的事情应该适合你:

package something

import (
    "github.com/hashicorp/terraform/helper/schema"
)

func somethingSomething() *schema.Resource {
    return &schema.Resource{
        // ...
        Schema: map[string]*schema.Schema{
            // ...
            "field": {
                Type:     schema.TypeInt,
                Optional: true,
                Default:  -1,
                DiffSuppressFunc: func(k, old, new string, d *schema.ResourceData) bool {
                    if new == "-1" {
                        return true
                    }
                    return false
                },
            },
        },
    }
}
Run Code Online (Sandbox Code Playgroud)

Martin 的回答可能通过使用Computed标志并制作属性提供了更好的选择Optional。为使其正常工作,您需要使用核心 SDK预定义验证列表中的验证器,防止人们将其指定-1为您可以使用 a 执行的值:ValidateFuncIntAtLeast

package something

import (
    "github.com/hashicorp/terraform/helper/schema"
    "github.com/hashicorp/terraform/helper/validation"
)

func somethingSomething() *schema.Resource {
    return &schema.Resource{
        // ...
        Schema: map[string]*schema.Schema{
            // ...
            "field": {
                Type:         schema.TypeInt,
                Optional:     true,
                Computed:     true,
                ValidateFunc: validation.IntAtLeast(1),
            },
        },
    }
}
Run Code Online (Sandbox Code Playgroud)


Mar*_*ins 5

Terraform SDK 包含一个特殊的模式标志Computed,这意味着“如果配置中没有给出值,则将在应用时选择默认值”。

这似乎与您的用例相匹配。如果您取消设置DefaultComputed: true改为设置- 保留Optional: true以指示用户可以选择设置它 - 那么您可以激活该行为。

如果您能够在计划步骤中,在创建或更新任何内容之前预测最终的“计算”值,那么您应该CustomizeDiff为资源实施并使用d.Set来提供该值,然后 Terraform 可以将其考虑在内以产生更多完整的计划。

如果没有,那么你可以把规划期间,取消设置(在Terraform而言,它的价值将是“未知”),然后调用d.SetCreateUpdate函数来代替,以表现为价值(known after apply)的计划。

使用此机制时,自洽很重要:如果您在计划使用期间提供已知值,CustomizeDiff则该值必须与在Create或期间选择的最终值完全匹配Update。如果不一致,那么在应用期间,当 Terraform Core 验证最终更改与计划内容一致时,在其他表达式中对此属性的任何引用都会导致错误。


这种方法目前有一个警告:由于当今 Terraform SDK 的 API 设计限制,提供程序代码无法判断以前在配置中设置的值现在何时不再设置。或者,换句话说,SDK 无法判断已经存储的值是通过显式配置选择的还是由提供程序填充的作为应用期间的默认值。

因此,如果用户取消设置,配置中最后设置的值将是“粘性的”,并且提供程序将无法将该值自动调整回服务器提供的默认值。

这个警告在实践中通常不是什么大问题,但值得注意的是,如果它在您的特定情况下确实很重要。SDK 的后续版本可能会提供一种机制来询问是否在配置中设置了特定值,与存储在状态中的内容分开。