1 回答
TA贡献1877条经验 获得超1个赞
Terraform 的旧版 SDK (SDKv2) 并不是围绕解码成标记结构的范例而设计的,而是希望您使用d.Get并手动键入断言单个值,在您的情况下,这些值可能看起来像这样:
raw := d.Get("template").([]interface{})[0].(map[string]interface{})
t := &TestStruct{
NameTest: raw["name_test"].(string),
ListsTests: make([]string, len(raw["lists_test"].([]interface{})),
}
for i, itemRaw := range raw["lists_test"].([]interface{}) {
t.ListsTests[i] = itemRaw.(string)
}
大多数 Terraform 提供程序的惯用风格是为每个复杂类型的属性在单独的函数中编写这样的逻辑,其中每个属性返回目标平台 SDK 中适当类型的对象。通常还会有一个相反方向的匹配函数:从目标平台的 SDK 中给定一个对象,返回一个map[string]interface{}可以分配给该属性的d.Set.
然而,仅仅因为 SDK 中没有内置的东西来处理这个,并不意味着你不能使用其他库,这些库是更通用的实用程序,可用于任何 Go 程序。
一个示例库是github.com/mitchellh/mapstructure,它正是为您的目标而设计的:获取某种接口类型的值并尝试使用反射将其适合标记的结构类型。
如果你想使用那个库,那么你需要用mapstructure:,而不是json:那些来注释你的结构,然后将你的raw值传递给mapstructure.Decode函数:
raw := d.Get("template").([]interface{})[0].(map[string]interface{})
var t TestStruct
err := mapstructure.Decode(raw, &t)
由于schema.ResourceDataSDKv2 中的抽象保证根据您定义的模式返回特定数据类型,因此mapstructure.Decode只要您的模式和目标类型匹配,您通常不会收到错误,但无论如何检查错误仍然是一个好主意,否则您的t价值可能没有完全填充,导致下游混乱的破坏行为。
这不是官方提供程序中使用的典型实现样式,但如果您发现这种样式更方便或更易于维护,那么以这种方式编写您的提供程序并没有什么真正的坏处。
或者,如果您还没有深入研究 SDKv2,那么您可能希望考虑改用Terraform 插件框架。除了围绕现代 Terraform 的类型系统设计(而 SDKv2 是为 Terraform v0.11 及更早版本设计的),它还支持一种更像您所追求的编程风格,使用诸如tfsdk.Plan.Get和之类的方法tfsdk.Plan.GetAttribute可以直接解码为适当形状和适当标记的“正常”Go 值。
我无法简单地展示一个例子,因为它会假定提供程序以完全不同的方式编写,但希望您可以从这两个函数的签名中看出它们的使用方式。在访问状态、配置和计划中有更多的评论和示例。
- 1 回答
- 0 关注
- 112 浏览
添加回答
举报