亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

將 map[string]interface{} 類型的 terraform

將 map[string]interface{} 類型的 terraform

Go
撒科打諢 2023-01-03 10:13:26
我正在創建自定義 Terraform 提供程序,我遇到了這個問題。我試圖將一個schema.TypeList字段轉換為一個結構,TypeList 看起來像這樣:"template": {                Type:     schema.TypeList,                Required: true,                ForceNew: false,                Elem: &schema.Resource{                    Schema: map[string]*schema.Schema{                        "lists_test": {                            Type:     schema.TypeSet,                            Required: true,                            ForceNew: false,                            Elem: &schema.Schema{                                Type: schema.TypeString,                            },                        },                        "name_test": {                            Type:     schema.TypeString,                            Required: true,                            ForceNew: false,                        },},},我試圖對齊的結構看起來像這樣:type TestStruct struct {    NameTest string   `json:"name_test"`    ListsTests   []string `json:"lists_test"`}我嘗試了幾種解決方案,例如我嘗試將其解組為 json。像下面這樣的東西:template := d.Get("template").([]interface{})[0].(map[string]interface{})templateStr, err := json.Marshal(template)templateConverted := &TestStruct{}json.Unmarshal(template, templateConverted)但是,我收到一個錯誤json: unsupported type: SchemaSetFunc,這可能是因為它試圖編組一個schema.Schema類型而不是 map[string]interface{} 類型,這讓我感到困惑。我也嘗試使用gohcl.DecodeBody但我放棄了這個想法,因為它的用法似乎更傾向于讀取直接 tf 文件而不是*schema.ResourceData類型。有沒有人有處理這種情況的相同經驗?任何幫助或建議表示贊賞。謝謝!
查看完整描述

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可以直接解碼為適當形狀和適當標記的“正?!盙o 值。


我無法簡單地展示一個例子,因為它會假定提供程序以完全不同的方式編寫,但希望您可以從這兩個函數的簽名中看出它們的使用方式。在訪問狀態、配置和計劃中有更多的評論和示例。


查看完整回答
反對 回復 2023-01-03
  • 1 回答
  • 0 關注
  • 127 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號