猿问

Terraform 自定义提供程序 - 数据源架构

我正在使用 terraform sdk 创建自定义 terraform 提供程序。我正在尝试从现有的 API GET 调用中读取数据。我发现很难将来自 API 的 JSON 响应映射到 Terraform 模式。这是我的数据源模式:


func dataSourceProjects() *schema.Resource {

  return &schema.Resource{

    ReadContext: dataSourceProjectsRead,

    Schema: map[string]*schema.Schema{

      "members": &schema.Schema{

        Type:     schema.TypeList,

        Elem:     &schema.Schema{Type: schema.TypeString},

        Computed: true,

      },

      "owners": &schema.Schema{

        Type:     schema.TypeList,

        Elem:     &schema.Schema{Type: schema.TypeString},

        Computed: true,

      },

    },

  }

}

这是 API JSON 响应:


{

  "members": [

    "test12",

    "test8800",

    "test0032",

    "test1234"

  ],

  "owners": [

    "test000",

    "test111",

    "test12",

    "test1234"

  ]

}

这是我的数据源读取功能


func dataSourceProjectsRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {


  client := &http.Client{Timeout: 10 * time.Second}


  // Warning or errors can be collected in a slice type

  var diags diag.Diagnostics


  req, err := http.NewRequest("GET", fmt.Sprintf("%s/test/team", "https://myurl/v1"), nil)

  req.Header.Add("Authorization", "Bearer xxxxx")

  if err != nil {

    return diag.FromErr(err)

  }


  r, err := client.Do(req)

  if err != nil {

    return diag.FromErr(err)

  }

  defer r.Body.Close()

  members := make([]string, 0)

  err = json.NewDecoder(r.Body).Decode(&members)

  if err != nil {

    return diag.FromErr(err)

  }


  if err := d.Set("members", members); err != nil {

    return diag.FromErr(err)

  }


  // always run

  d.SetId(strconv.FormatInt(time.Now().Unix(), 10))


  return diags

}

我不断收到此错误:


错误:json:无法将对象解组为 []string 类型的 Go 值


翻过高山走不出你
浏览 188回答 2
2回答

慕桂英546537

服务器.gopackage mainimport (    "log"    "net/http")func main() {    s := `    {      "members": [        "test12",        "test8800",        "test0032",        "test1234"      ],      "owners": [        "test000",        "test111",        "test12",        "test1234"      ]    }    `    http.HandleFunc("/projects", func(w http.ResponseWriter, _ *http.Request) {      log.Println("Getting Projects")      w.WriteHeader(http.StatusOK)      w.Write([]byte(s))    })    log.Println("Listening...")    log.Fatal(http.ListenAndServe(":8000", nil))}data_source_projects.gopackage hashicupsimport (    "context"    "encoding/json"    "fmt"    "net/http"    "strconv"    "time"    "github.com/hashicorp/terraform-plugin-sdk/v2/diag"    "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema")func dataSourceProjects() *schema.Resource {  return &schema.Resource{    ReadContext: dataSourceProjectsRead,    Schema: map[string]*schema.Schema{      "members": &schema.Schema{        Type:     schema.TypeList,        Elem:     &schema.Schema{Type: schema.TypeString},        Computed: true,      },      "owners": &schema.Schema{        Type:     schema.TypeList,        Elem:     &schema.Schema{Type: schema.TypeString},        Computed: true,      },    },  }}func dataSourceProjectsRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {    client := &http.Client{Timeout: 10 * time.Second}    // Warning or errors can be collected in a slice type    var diags diag.Diagnostics    req, err := http.NewRequest("GET", fmt.Sprintf("%s/projects", "http://localhost:8000"), nil)    if err != nil {        return diag.FromErr(err)    }    r, err := client.Do(req)    if err != nil {        return diag.FromErr(err)    }    defer r.Body.Close()    var projects map[string]interface{}    err = json.NewDecoder(r.Body).Decode(&projects)    if err != nil {        return diag.FromErr(err)    }    if err := d.Set("members", projects["members"]); err != nil {        return diag.FromErr(err)    }    if err := d.Set("owners", projects["owners"]); err != nil {        return diag.FromErr(err)    }    // always run    d.SetId(strconv.FormatInt(time.Now().Unix(), 10))    return diags}输出:Do you want to perform these actions?  Terraform will perform the actions described above.  Only 'yes' will be accepted to approve.  Enter a value: yesApply complete! Resources: 0 added, 0 changed, 0 destroyed.Outputs:project = {  "id" = "1651575329"  "members" = tolist([    "test12",    "test8800",    "test0032",    "test1234",  ])  "owners" = tolist([    "test000",    "test111",    "test12",    "test1234",  ])}

海绵宝宝撒

正如 Matt 和提到的错误代码一样,您正试图将您的身体解组为不正确的结构。基本上,您在 Body 中没有数组,您有一个包含字符串数组的字段的对象。你的解组方式适用于像这样的机构["test12", "test23", "test34"]尝试按如下方式对其进行解码,因此请使用具有显式映射的结构。package mainimport (    "encoding/json"    "fmt")type Schema struct {    Members []string `json:"members"`    Owners  []string `json:"owners"`}var jsonBody = `{  "members": [    "test12",    "test8800",    "test0032",    "test1234"  ],  "owners": [    "test000",    "test111",    "test12",    "test1234"  ]}`func main() {    var s Schema    err := json.Unmarshal([]byte(jsonBody), &s)    if err != nil {        fmt.Println(err)    } else {        fmt.Println(s)    }}
随时随地看视频慕课网APP

相关分类

Go
我要回答