上下文:我(第一个实现)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?
答案 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.Set
和d.Set
函数中调用Create
,其值在计划中显示为Update
。
使用此机制时,保持一致非常重要:如果在使用(known after apply)
进行规划时提供了一个已知值,则该必须与{{1 }}或CustomizeDiff
。如果不一致,则当Terraform Core验证最终更改与计划的内容一致时,在其他表达式中对此属性的任何引用都将在应用期间导致错误。
目前有一种使用这种方法的警告:由于当今Terraform SDK的API设计限制,提供商代码无法告知何时不再配置中先前设置的 值。或者,换句话说,SDK不能告诉已经存储的值是通过显式配置选择的,还是提供者在应用过程中默认填充的值。
由于这个原因,如果用户取消配置,则在配置中设置的最后一个值将为“粘性”,并且提供程序将无法自动将该值重新设置为服务器提供的默认值。
该警告在实践中通常不是什么大问题,但值得注意的是,在特定情况下重要至关重要。如果在配置中设置了特定的值(与状态中存储的值分开),则SDK的后续版本可能会提供一种询问的机制。