parent
278f60f50b
commit
05367ff225
|
|
@ -25,8 +25,10 @@ website/node_modules
|
|||
*.test
|
||||
*.iml
|
||||
|
||||
.vscode/
|
||||
test/.terraform.lock.hcl
|
||||
website/vendor
|
||||
test/*.tfplan
|
||||
|
||||
# Test exclusions
|
||||
!command/test-fixtures/**/*.tfstate
|
||||
|
|
|
|||
|
|
@ -0,0 +1,27 @@
|
|||
---
|
||||
# generated by https://github.com/hashicorp/terraform-plugin-docs
|
||||
page_title: "nautobot_graphql Data Source - terraform-provider-nautobot"
|
||||
subcategory: ""
|
||||
description: |-
|
||||
Provide an interface to make GraphQL calls to Nautobot as a flexible data source.
|
||||
---
|
||||
|
||||
# nautobot_graphql (Data Source)
|
||||
|
||||
Provide an interface to make GraphQL calls to Nautobot as a flexible data source.
|
||||
|
||||
|
||||
|
||||
<!-- schema generated by tfplugindocs -->
|
||||
## Schema
|
||||
|
||||
### Required
|
||||
|
||||
- `query` (String) The GraphQL query that will be sent to Nautobot.
|
||||
|
||||
### Read-Only
|
||||
|
||||
- `data` (String) The data returned by the GraphQL query.
|
||||
- `id` (String) The ID of this resource.
|
||||
|
||||
|
||||
|
|
@ -1 +1,11 @@
|
|||
data "nautobot_manufacturers" "all" {}
|
||||
data "nautobot_manufacturers" "all" {}
|
||||
|
||||
data "nautobot_graphql" "vms" {
|
||||
query = <<EOF
|
||||
query {
|
||||
virtual_machines {
|
||||
id
|
||||
}
|
||||
}
|
||||
EOF
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,81 @@
|
|||
package provider
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
|
||||
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
|
||||
"github.com/tidwall/gjson"
|
||||
)
|
||||
|
||||
func dataSourceGraphQL() *schema.Resource {
|
||||
return &schema.Resource{
|
||||
Description: "Provide an interface to make GraphQL calls to Nautobot as a flexible data source.",
|
||||
|
||||
ReadContext: dataSourceGraphQLRead,
|
||||
|
||||
Schema: map[string]*schema.Schema{
|
||||
"query": {
|
||||
Description: "The GraphQL query that will be sent to Nautobot.",
|
||||
Type: schema.TypeString,
|
||||
Required: true,
|
||||
},
|
||||
"data": {
|
||||
Description: "The data returned by the GraphQL query.",
|
||||
Type: schema.TypeString,
|
||||
Computed: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
type reqBody struct {
|
||||
Query string `json:"query"`
|
||||
}
|
||||
|
||||
// Use this as reference: https://learn.hashicorp.com/tutorials/terraform/provider-setup?in=terraform/providers#implement-read
|
||||
func dataSourceGraphQLRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
|
||||
var diags diag.Diagnostics
|
||||
|
||||
c := meta.(*apiClient).BaseClient
|
||||
s := fmt.Sprintf("%sgraphql/", meta.(*apiClient).Server)
|
||||
t := meta.(*apiClient).Token
|
||||
query := d.Get("query").(string)
|
||||
|
||||
queryBody, _ := json.Marshal(reqBody{Query: query})
|
||||
req, err := http.NewRequestWithContext(ctx, "POST", s, bytes.NewBuffer(queryBody))
|
||||
if err != nil {
|
||||
return diag.Errorf("failed to create request with context %s: %s", s, err.Error())
|
||||
}
|
||||
req.Header.Add("Content-Type", "application/json")
|
||||
// Add the authorization header to our request.
|
||||
t.Intercept(ctx, req)
|
||||
|
||||
rsp, err := c.Client.Do(req)
|
||||
if err != nil {
|
||||
return diag.Errorf("failed to successfully call %s: %s", s, err.Error())
|
||||
}
|
||||
defer rsp.Body.Close()
|
||||
|
||||
body, err := io.ReadAll(rsp.Body)
|
||||
if err != nil {
|
||||
return diag.Errorf("failed to decode GraphQL response from %s: %s", s, err.Error())
|
||||
}
|
||||
|
||||
data := gjson.Get(string(body), "data")
|
||||
if err := d.Set("data", data.Raw); err != nil {
|
||||
return diag.FromErr(err)
|
||||
}
|
||||
|
||||
// always run
|
||||
d.SetId(strconv.FormatInt(time.Now().Unix(), 10))
|
||||
|
||||
return diags
|
||||
}
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
package provider
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
|
||||
)
|
||||
|
||||
func TestAccDataSourceGraphQL(t *testing.T) {
|
||||
// https://github.com/hashicorp/terraform-plugin-sdk/issues/952
|
||||
t.Skip("resource not yet implemented, remove this once you add your own code")
|
||||
|
||||
resource.UnitTest(t, resource.TestCase{
|
||||
PreCheck: func() { testAccPreCheck(t) },
|
||||
ProviderFactories: providerFactories,
|
||||
Steps: []resource.TestStep{
|
||||
{
|
||||
Config: testAccDataSourceGraphQL,
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
//resource.TestCheckResourceAttr("data.nautobot_manufacturers.list.manufacturers", "", ""),
|
||||
resource.TestCheckOutput("data_source_graphql", "virtual_machines"),
|
||||
),
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
const testAccDataSourceGraphQL = `
|
||||
provider "nautobot" {
|
||||
url = "https://demo.nautobot.com/api/"
|
||||
token = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||
}
|
||||
|
||||
data "nautobot_graphql" "vms" {
|
||||
query = <<EOF
|
||||
query {
|
||||
virtual_machines {
|
||||
id
|
||||
}
|
||||
}
|
||||
EOF
|
||||
}
|
||||
|
||||
output "data_source_graphql" {
|
||||
value = data.nautobot_graphql.vms
|
||||
}
|
||||
`
|
||||
|
|
@ -53,6 +53,7 @@ func New(version string) func() *schema.Provider {
|
|||
},
|
||||
DataSourcesMap: map[string]*schema.Resource{
|
||||
"nautobot_manufacturers": dataSourceManufacturers(),
|
||||
"nautobot_graphql": dataSourceGraphQL(),
|
||||
},
|
||||
ResourcesMap: map[string]*schema.Resource{
|
||||
"nautobot_manufacturer": resourceManufacturer(),
|
||||
|
|
@ -69,8 +70,10 @@ func New(version string) func() *schema.Provider {
|
|||
// you would need to setup to communicate with the upstream
|
||||
// API.
|
||||
type apiClient struct {
|
||||
Client *nb.ClientWithResponses
|
||||
Server string
|
||||
Client *nb.ClientWithResponses
|
||||
Server string
|
||||
Token *SecurityProviderNautobotToken
|
||||
BaseClient *nb.Client
|
||||
}
|
||||
|
||||
func configure(
|
||||
|
|
@ -102,10 +105,21 @@ func configure(
|
|||
diags[0].Severity = diag.Error
|
||||
return &apiClient{Server: serverURL}, diags
|
||||
}
|
||||
bc, err := nb.NewClient(
|
||||
serverURL,
|
||||
nb.WithRequestEditorFn(token.Intercept),
|
||||
)
|
||||
if err != nil {
|
||||
diags = diag.FromErr(err)
|
||||
diags[0].Severity = diag.Error
|
||||
return &apiClient{Server: serverURL}, diags
|
||||
}
|
||||
|
||||
return &apiClient{
|
||||
Client: c,
|
||||
Server: serverURL,
|
||||
Client: c,
|
||||
Server: serverURL,
|
||||
Token: token,
|
||||
BaseClient: bc,
|
||||
}, diags
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,4 +14,25 @@ output "data_source_example" {
|
|||
manufacturer.id => manufacturer
|
||||
if manufacturer.name == var.manufacturer_name
|
||||
}
|
||||
}
|
||||
}
|
||||
data "nautobot_graphql" "nodes" {
|
||||
query = <<EOF
|
||||
query {
|
||||
virtual_machines {
|
||||
name
|
||||
id
|
||||
}
|
||||
devices {
|
||||
name
|
||||
id
|
||||
}
|
||||
}
|
||||
EOF
|
||||
}
|
||||
|
||||
output "data_source_graphql" {
|
||||
value = data.nautobot_graphql.nodes
|
||||
}
|
||||
output "data_source_graphql_vm" {
|
||||
value = jsondecode(data.nautobot_graphql.nodes.data).virtual_machines
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue