Terraform自定义提供程序-数据源模式



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

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: cannot unmarshal object into []string类型的Go值

server.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",
])
}

正如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)
}
}

最新更新