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

时间:2019-09-04 08:42:55

标签: go terraform

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

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

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

resource "something" "mysomething" {
  name  = "someName"
  field = -1
}

该呼叫不是幂等的。 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.

如何处理此类API?

2 个答案:

答案 0 :(得分:3)

您可以在模式属性上使用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
                },
            },
        },
    }
}

Martin's answer通过使用Computed flag并设置属性Optional可能提供了更好的选择。为了使此方法正常运行,您希望阻止人们使用{{3}列表中的ValidateFunc-1指定为此值,而您可以使用IntAtLeast validator }}:

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),
            },
        },
    }
}

答案 1 :(得分:2)

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

这似乎与您的用例相符。如果您取消设置Default并设置Computed: true(保留Optional: true来指示用户可以选择设置),则可以激活该行为。

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

如果没有,那么您可以在计划期间将其保留为未设置状态(以Terraform的形式,其值为“未知”),然后在d.Setd.Set函数中调用Create ,其值在计划中显示为Update

使用此机制时,保持一致非常重要:如果在使用(known after apply)进行规划时提供了一个已知值,则该必须与{{1 }}或CustomizeDiff。如果不一致,则当Terraform Core验证最终更改与计划的内容一致时,在其他表达式中对此属性的任何引用都将在应用期间导致错误。


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

由于这个原因,如果用户取消配置,则在配置中设置的最后一个值将为“粘性”,并且提供程序将无法自动将该值重新设置为服务器提供的默认值。

该警告在实践中通常不是什么大问题,但值得注意的是,在特定情况下重要至关重要。如果在配置中设置了特定的值(与状态中存储的值分开),则SDK的后续版本可能会提供一种询问的机制。