在 Terraform SDKv2 中保存到 TF 状态时 DiffSuppressFunc 或更严格吗?
Is DiffSuppressFunc or being more restrictive when saving to TF state is preferable in Terraform SDKv2?
上下文:我正在向 TF 提供程序(使用 SDKv2)添加一个新资源,其架构大致如下:
resource "player" "football" {
type = "FOOTBALL"
...
config = {
"dribbling" = "50"
"speed" = "90"
"position" = "GOALKEEPER"
}
}
我表示为:
"config": {
Type: schema.TypeMap,
Elem: &schema.Schema{
Type: schema.TypeString,
},
Required: true,
ForceNew: true,
},
此处的重要细节对于不同的 palyer 实例类型,将有一组不同的必需属性(dribbling, speed, position
对于 football 和 height, can_dunk, arm_span
for basketball) -- 所有玩家共享相同的 API 端点,所以我只介绍了一个资源来覆盖他们。
我想支持导入玩家的能力,显然 READ
响应包括一堆在创建时可选的字段(我怀疑大多数用户不会在 Terraform 配置中拥有它们文件)导致我在保存整个配置时出现状态差异,例如:
d.Set("config", player.GetConfig()) # GetConfig includes a bunch of new attributes (optional on a create or even computed)
所以我有一个问题:以下两个选项中哪个更可取:
- 为
config
属性实现 DiffSuppressFunc
,我将忽略这些可选字段(缺点是我将在 main.tf
和 TF 状态文件之间隐式漂移) .
- 将配置写入 TF 状态文件时更加严格:
instead of
d.Set("config", player.GetConfig())
# filtered config will match config in main.tf
filteredConfig = ...
d.Set("config", filteredConfig)
在处理类似情况的其他一些 Terraform 提供程序中(其中特定参数混合了 configuration-provided 和 remote-system-provided 嵌套值),资源类型实现采取了有效公开的折衷位置两个不同属性中的相同数据,其中一个表示用户配置的内容,另一个表示远程系统返回的完整数据。例如,您可能要在配置中设置 config
,并且 expanded_config
表示服务器决定的完整元素集。
这种方法存在一个挑战,因为您可能需要在 Read
函数中使用一个特殊规则来以某种方式确定您在远程系统中检测到的更改是否构成相对于配置的“漂移”或者它只是服务器添加的附加元素。
根据您的描述,规则似乎是 config
中存在的任何键在先前状态(即 Read
中 d.Get
可见的值在您调用 d.Set
) 之前,它的值将被服务器返回的内容覆盖,但是之前不存在的任何键都将被完全忽略。这将产生这样的效果,即作者在配置中指定的任何密钥都被视为“由 Terraform 管理”,而任何其他密钥仅由 Terraform 读取而不是直接管理。
如果您采用该策略,那么有必要牢记在用户更改配置以包含新密钥或删除 previously-present 密钥的情况下会发生什么。 Read
操作是根据先前的状态而不是配置,因此该函数将看到上次应用结束时存在的键,而不是配置中当前存在的键。特别是这意味着,如果作者添加了服务器已经跟踪的新密钥,那么它将在后续计划中显示为已添加,即使在技术上将其显示为 in-place 更新 ~
或 no-op。这是我们有时需要做出妥协的一个例子,以便调整远程 API 以适应 Terraform 的资源实例模型。
上下文:我正在向 TF 提供程序(使用 SDKv2)添加一个新资源,其架构大致如下:
resource "player" "football" {
type = "FOOTBALL"
...
config = {
"dribbling" = "50"
"speed" = "90"
"position" = "GOALKEEPER"
}
}
我表示为:
"config": {
Type: schema.TypeMap,
Elem: &schema.Schema{
Type: schema.TypeString,
},
Required: true,
ForceNew: true,
},
此处的重要细节对于不同的 palyer 实例类型,将有一组不同的必需属性(dribbling, speed, position
对于 football 和 height, can_dunk, arm_span
for basketball) -- 所有玩家共享相同的 API 端点,所以我只介绍了一个资源来覆盖他们。
我想支持导入玩家的能力,显然 READ
响应包括一堆在创建时可选的字段(我怀疑大多数用户不会在 Terraform 配置中拥有它们文件)导致我在保存整个配置时出现状态差异,例如:
d.Set("config", player.GetConfig()) # GetConfig includes a bunch of new attributes (optional on a create or even computed)
所以我有一个问题:以下两个选项中哪个更可取:
- 为
config
属性实现DiffSuppressFunc
,我将忽略这些可选字段(缺点是我将在main.tf
和 TF 状态文件之间隐式漂移) . - 将配置写入 TF 状态文件时更加严格:
instead of
d.Set("config", player.GetConfig())
# filtered config will match config in main.tf
filteredConfig = ...
d.Set("config", filteredConfig)
在处理类似情况的其他一些 Terraform 提供程序中(其中特定参数混合了 configuration-provided 和 remote-system-provided 嵌套值),资源类型实现采取了有效公开的折衷位置两个不同属性中的相同数据,其中一个表示用户配置的内容,另一个表示远程系统返回的完整数据。例如,您可能要在配置中设置 config
,并且 expanded_config
表示服务器决定的完整元素集。
这种方法存在一个挑战,因为您可能需要在 Read
函数中使用一个特殊规则来以某种方式确定您在远程系统中检测到的更改是否构成相对于配置的“漂移”或者它只是服务器添加的附加元素。
根据您的描述,规则似乎是 config
中存在的任何键在先前状态(即 Read
中 d.Get
可见的值在您调用 d.Set
) 之前,它的值将被服务器返回的内容覆盖,但是之前不存在的任何键都将被完全忽略。这将产生这样的效果,即作者在配置中指定的任何密钥都被视为“由 Terraform 管理”,而任何其他密钥仅由 Terraform 读取而不是直接管理。
如果您采用该策略,那么有必要牢记在用户更改配置以包含新密钥或删除 previously-present 密钥的情况下会发生什么。 Read
操作是根据先前的状态而不是配置,因此该函数将看到上次应用结束时存在的键,而不是配置中当前存在的键。特别是这意味着,如果作者添加了服务器已经跟踪的新密钥,那么它将在后续计划中显示为已添加,即使在技术上将其显示为 in-place 更新 ~
或 no-op。这是我们有时需要做出妥协的一个例子,以便调整远程 API 以适应 Terraform 的资源实例模型。