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



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

API 中的创建操作之一指定一个整数字段,该字段采用正值或-1作为默认值。如果在创建 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?

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

这似乎与您在此处的用例相匹配。如果取消设置Default并改为设置Computed: true(保留Optional: true以指示用户可以选择设置它(,则可以激活该行为。

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

如果没有,则可以在规划期间将其保留为未设置(在 Terraform 术语中,其值将为"未知"(,然后在CreateUpdate函数中调用d.Set,值在计划中显示为(known after apply)

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


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

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

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

您可以在架构属性上使用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 的回答可能通过使用Computed标志并使属性Optional提供了更好的选择。为了很好地工作,您需要防止人们将-1指定为此的值,您可以使用核心 SDK 中预定义验证列表中的IntAtLeast验证器来使用ValidateFunc

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

相关内容

最新更新