为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

Go
翻过高山走不出你 2022-12-05 17:30:02
我正在使用 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 值
查看完整描述

2 回答

?
慕桂英546537

TA贡献1848条经验 获得超10个赞

服务器.go


package main


import (

    "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.go


package hashicups


import (

    "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: yes



Apply complete! Resources: 0 added, 0 changed, 0 destroyed.


Outputs:


project = {

  "id" = "1651575329"

  "members" = tolist([

    "test12",

    "test8800",

    "test0032",

    "test1234",

  ])

  "owners" = tolist([

    "test000",

    "test111",

    "test12",

    "test1234",

  ])

}


查看完整回答
反对 回复 2022-12-05
?
海绵宝宝撒

TA贡献1809条经验 获得超8个赞

正如 Matt 和提到的错误代码一样,您正试图将您的身体解组为不正确的结构。


基本上,您在 Body 中没有数组,您有一个包含字符串数组的字段的对象。


你的解组方式适用于像这样的机构


["test12", "test23", "test34"]

尝试按如下方式对其进行解码,因此请使用具有显式映射的结构。


package main


import (

    "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)

    }


}


查看完整回答
反对 回复 2022-12-05
  • 2 回答
  • 0 关注
  • 187 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号