Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions netbox/client.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
package netbox

import (
"encoding/json"
"fmt"
"io"
"net/http"
"time"

netboxclient "github.com/fbreckle/go-netbox/netbox/client"
"github.com/go-openapi/runtime"
httptransport "github.com/go-openapi/runtime/client"
"github.com/goware/urlx"
log "github.com/sirupsen/logrus"
Expand Down Expand Up @@ -83,6 +86,16 @@ func (cfg *Config) Client() (*netboxclient.NetBoxAPI, error) {
transport := httptransport.NewWithClient(parsedURL.Host, parsedURL.Path+netboxclient.DefaultBasePath, desiredRuntimeClientSchemes, httpClient)
transport.DefaultAuthentication = httptransport.APIKeyAuth("Authorization", "header", fmt.Sprintf("Token %v", cfg.APIToken))
transport.SetLogger(log.StandardLogger())

// Configure the transport to handle interface{} values properly
// This helps prevent TextConsumer issues with interface{} types
transport.Consumers["application/json"] = runtime.ConsumerFunc(func(reader io.Reader, data interface{}) error {
dec := json.NewDecoder(reader)
// Use json.Number to handle numeric values that might be interface{}
dec.UseNumber()
return dec.Decode(data)
})

netboxClient := netboxclient.New(transport, nil)

return netboxClient, nil
Expand Down
31 changes: 29 additions & 2 deletions netbox/custom_fields.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,19 @@ var customFieldsSchema = &schema.Schema{
Type: schema.TypeString,
Default: nil,
},
DiffSuppressFunc: func(k, old, new string, d *schema.ResourceData) bool {
if old == "" && new == "0" {
return true // treat empty and "0" as equal? Wait, for maps it's different
}
// For maps, old and new are JSON strings
if old == "{}" && new == "" {
return true
}
if old == "" && new == "{}" {
return true
}
return false
},
}

func getCustomFields(cf interface{}) map[string]interface{} {
Expand All @@ -31,7 +44,8 @@ func getCustomFields(cf interface{}) map[string]interface{} {
}

// flattenCustomFields converts custom fields to a map where all values are strings.
// Complex nested objects (like IP address references) are converted to JSON strings.
// Object references (maps with "id" field) are converted to just their ID string.
// Other complex types are converted to JSON strings.
func flattenCustomFields(cf interface{}) map[string]interface{} {
cfm, ok := cf.(map[string]interface{})
if !ok || len(cfm) == 0 {
Expand All @@ -51,8 +65,21 @@ func flattenCustomFields(cf interface{}) map[string]interface{} {
result[key] = v
case float64, int, int64, bool:
result[key] = fmt.Sprintf("%v", v)
case map[string]interface{}:
// Check if this is an object reference with an ID
if id, hasID := v["id"]; hasID {
// Extract just the ID for object references
result[key] = fmt.Sprintf("%v", id)
} else {
// For other complex objects without ID, convert to JSON
if jsonBytes, err := json.Marshal(value); err == nil {
result[key] = string(jsonBytes)
} else {
result[key] = fmt.Sprintf("%v", value)
}
}
default:
// For complex types (maps, arrays, objects), convert to JSON string
// For other complex types (arrays, etc.), convert to JSON string
if jsonBytes, err := json.Marshal(value); err == nil {
result[key] = string(jsonBytes)
} else {
Expand Down
16 changes: 5 additions & 11 deletions netbox/custom_fields_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ func TestFlattenCustomFields(t *testing.T) {
},
},
expected: map[string]interface{}{
"gateway": `{"address":"10.21.10.254/24","display":"10.21.10.254/24","family":{"label":"IPv4","value":4},"id":9,"url":"https://netbox.example.com/api/ipam/ip-addresses/9/"}`,
"gateway": "9",
},
},
{
Expand Down Expand Up @@ -191,21 +191,15 @@ func TestFlattenCustomFields_ComplexRealWorldExample(t *testing.T) {
t.Fatal("expected non-nil result")
}

// Check that gateway is a JSON string
// Check that gateway is extracted to just the ID string
gateway, ok := result["gateway"].(string)
if !ok {
t.Errorf("expected gateway to be a string, got %T", result["gateway"])
}

// Verify we can parse the gateway JSON
var gatewayObj map[string]interface{}
if err := json.Unmarshal([]byte(gateway), &gatewayObj); err != nil {
t.Errorf("failed to parse gateway JSON: %v", err)
}

// Verify the gateway object has expected fields
if gatewayObj["address"] != "10.21.10.254/24" {
t.Errorf("expected address 10.21.10.254/24, got %v", gatewayObj["address"])
// Verify the gateway is just the ID
if gateway != "9" {
t.Errorf("expected gateway=9, got %v", gateway)
}

// Check simple fields
Expand Down
2 changes: 1 addition & 1 deletion netbox/resource_netbox_cable.go
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@ func resourceNetboxCableRead(d *schema.ResourceData, m interface{}) error {
d.Set("description", cable.Description)
d.Set("comments", cable.Comments)

cf := getCustomFields(res.GetPayload().CustomFields)
cf := flattenCustomFields(res.GetPayload().CustomFields)
if cf != nil {
d.Set(customFieldsKey, cf)
}
Expand Down
2 changes: 1 addition & 1 deletion netbox/resource_netbox_circuit_termination.go
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,7 @@ func resourceNetboxCircuitTerminationRead(d *schema.ResourceData, m interface{})

api.readTags(d, term.Tags)

cf := getCustomFields(term.CustomFields)
cf := flattenCustomFields(term.CustomFields)
if cf != nil {
d.Set(customFieldsKey, cf)
}
Expand Down
2 changes: 1 addition & 1 deletion netbox/resource_netbox_device.go
Original file line number Diff line number Diff line change
Expand Up @@ -353,7 +353,7 @@ func resourceNetboxDeviceRead(ctx context.Context, d *schema.ResourceData, m int
d.Set("config_template_id", nil)
}

cf := getCustomFields(res.GetPayload().CustomFields)
cf := flattenCustomFields(res.GetPayload().CustomFields)
if cf != nil {
d.Set(customFieldsKey, cf)
}
Expand Down
2 changes: 1 addition & 1 deletion netbox/resource_netbox_device_bay.go
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ func resourceNetboxDeviceBayRead(d *schema.ResourceData, m interface{}) error {
}
d.Set("description", deviceBay.Description)

cf := getCustomFields(res.GetPayload().CustomFields)
cf := flattenCustomFields(res.GetPayload().CustomFields)
if cf != nil {
d.Set(customFieldsKey, cf)
}
Expand Down
2 changes: 1 addition & 1 deletion netbox/resource_netbox_device_console_port.go
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ func resourceNetboxDeviceConsolePortRead(d *schema.ResourceData, m interface{})
d.Set("description", consolePort.Description)
d.Set("mark_connected", consolePort.MarkConnected)

cf := getCustomFields(res.GetPayload().CustomFields)
cf := flattenCustomFields(res.GetPayload().CustomFields)
if cf != nil {
d.Set(customFieldsKey, cf)
}
Expand Down
2 changes: 1 addition & 1 deletion netbox/resource_netbox_device_console_server_port.go
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ func resourceNetboxDeviceConsoleServerPortRead(d *schema.ResourceData, m interfa
d.Set("description", consoleServerPort.Description)
d.Set("mark_connected", consoleServerPort.MarkConnected)

cf := getCustomFields(res.GetPayload().CustomFields)
cf := flattenCustomFields(res.GetPayload().CustomFields)
if cf != nil {
d.Set(customFieldsKey, cf)
}
Expand Down
2 changes: 1 addition & 1 deletion netbox/resource_netbox_device_front_port.go
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ func resourceNetboxDeviceFrontPortRead(d *schema.ResourceData, m interface{}) er
d.Set("description", frontPort.Description)
d.Set("mark_connected", frontPort.MarkConnected)

cf := getCustomFields(res.GetPayload().CustomFields)
cf := flattenCustomFields(res.GetPayload().CustomFields)
if cf != nil {
d.Set(customFieldsKey, cf)
}
Expand Down
2 changes: 1 addition & 1 deletion netbox/resource_netbox_device_module_bay.go
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ func resourceNetboxDeviceModuleBayRead(d *schema.ResourceData, m interface{}) er
d.Set("position", moduleBay.Position)
d.Set("description", moduleBay.Description)

cf := getCustomFields(res.GetPayload().CustomFields)
cf := flattenCustomFields(res.GetPayload().CustomFields)
if cf != nil {
d.Set(customFieldsKey, cf)
}
Expand Down
2 changes: 1 addition & 1 deletion netbox/resource_netbox_device_power_feed.go
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,7 @@ func resourceNetboxPowerFeedRead(d *schema.ResourceData, m interface{}) error {
d.Set("description", powerFeed.Description)
d.Set("comments", powerFeed.Comments)

cf := getCustomFields(res.GetPayload().CustomFields)
cf := flattenCustomFields(res.GetPayload().CustomFields)
if cf != nil {
d.Set(customFieldsKey, cf)
}
Expand Down
2 changes: 1 addition & 1 deletion netbox/resource_netbox_device_power_outlet.go
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ func resourceNetboxDevicePowerOutletRead(d *schema.ResourceData, m interface{})
d.Set("description", powerOutlet.Description)
d.Set("mark_connected", powerOutlet.MarkConnected)

cf := getCustomFields(res.GetPayload().CustomFields)
cf := flattenCustomFields(res.GetPayload().CustomFields)
if cf != nil {
d.Set(customFieldsKey, cf)
}
Expand Down
2 changes: 1 addition & 1 deletion netbox/resource_netbox_device_power_port.go
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ func resourceNetboxDevicePowerPortRead(d *schema.ResourceData, m interface{}) er
d.Set("description", powerPort.Description)
d.Set("mark_connected", powerPort.MarkConnected)

cf := getCustomFields(res.GetPayload().CustomFields)
cf := flattenCustomFields(res.GetPayload().CustomFields)
if cf != nil {
d.Set(customFieldsKey, cf)
}
Expand Down
2 changes: 1 addition & 1 deletion netbox/resource_netbox_device_rear_port.go
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ func resourceNetboxDeviceRearPortRead(d *schema.ResourceData, m interface{}) err
d.Set("description", rearPort.Description)
d.Set("mark_connected", rearPort.MarkConnected)

cf := getCustomFields(res.GetPayload().CustomFields)
cf := flattenCustomFields(res.GetPayload().CustomFields)
if cf != nil {
d.Set(customFieldsKey, cf)
}
Expand Down
2 changes: 1 addition & 1 deletion netbox/resource_netbox_inventory_item.go
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,7 @@ func resourceNetboxInventoryItemRead(d *schema.ResourceData, m interface{}) erro
d.Set("component_type", item.ComponentType)
d.Set("component_id", item.ComponentID)

cf := getCustomFields(res.GetPayload().CustomFields)
cf := flattenCustomFields(res.GetPayload().CustomFields)
if cf != nil {
d.Set(customFieldsKey, cf)
}
Expand Down
2 changes: 1 addition & 1 deletion netbox/resource_netbox_inventory_item_role.go
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ func resourceNetboxInventoryItemRoleRead(d *schema.ResourceData, m interface{})
d.Set("color_hex", role.Color)
d.Set("description", role.Description)

cf := getCustomFields(res.GetPayload().CustomFields)
cf := flattenCustomFields(res.GetPayload().CustomFields)
if cf != nil {
d.Set(customFieldsKey, cf)
}
Expand Down
2 changes: 1 addition & 1 deletion netbox/resource_netbox_ip_address.go
Original file line number Diff line number Diff line change
Expand Up @@ -274,7 +274,7 @@ func resourceNetboxIPAddressRead(d *schema.ResourceData, m interface{}) error {
d.Set("description", ipAddress.Description)
d.Set("status", ipAddress.Status.Value)
api.readTags(d, ipAddress.Tags)
cf := getCustomFields(res.GetPayload().CustomFields)
cf := flattenCustomFields(res.GetPayload().CustomFields)
if cf != nil {
d.Set(customFieldsKey, cf)
}
Expand Down
2 changes: 1 addition & 1 deletion netbox/resource_netbox_location.go
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ func resourceNetboxLocationRead(d *schema.ResourceData, m interface{}) error {
d.Set("tenant_id", nil)
}

cf := getCustomFields(res.GetPayload().CustomFields)
cf := flattenCustomFields(res.GetPayload().CustomFields)
if cf != nil {
d.Set(customFieldsKey, cf)
}
Expand Down
2 changes: 1 addition & 1 deletion netbox/resource_netbox_mac_address.go
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@ func resourceNetboxMACAddressRead(d *schema.ResourceData, m interface{}) error {
d.Set("comments", macAddress.Comments)
api.readTags(d, macAddress.Tags)

cf := getCustomFields(macAddress.CustomFields)
cf := flattenCustomFields(macAddress.CustomFields)
if cf != nil {
d.Set(customFieldsKey, cf)
}
Expand Down
2 changes: 1 addition & 1 deletion netbox/resource_netbox_module.go
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ func resourceNetboxModuleRead(d *schema.ResourceData, m interface{}) error {
d.Set("description", module.Description)
d.Set("comments", module.Comments)

cf := getCustomFields(res.GetPayload().CustomFields)
cf := flattenCustomFields(res.GetPayload().CustomFields)
if cf != nil {
d.Set(customFieldsKey, cf)
}
Expand Down
2 changes: 1 addition & 1 deletion netbox/resource_netbox_module_type.go
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ func resourceNetboxModuleTypeRead(d *schema.ResourceData, m interface{}) error {
d.Set("description", moduleType.Description)
d.Set("comments", moduleType.Comments)

cf := getCustomFields(res.GetPayload().CustomFields)
cf := flattenCustomFields(res.GetPayload().CustomFields)
if cf != nil {
d.Set(customFieldsKey, cf)
}
Expand Down
2 changes: 1 addition & 1 deletion netbox/resource_netbox_power_panel.go
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ func resourceNetboxPowerPanelRead(d *schema.ResourceData, m interface{}) error {
d.Set("description", powerPanel.Description)
d.Set("comments", powerPanel.Comments)

cf := getCustomFields(res.GetPayload().CustomFields)
cf := flattenCustomFields(res.GetPayload().CustomFields)
if cf != nil {
d.Set(customFieldsKey, cf)
}
Expand Down
2 changes: 1 addition & 1 deletion netbox/resource_netbox_prefix.go
Original file line number Diff line number Diff line change
Expand Up @@ -241,7 +241,7 @@ func resourceNetboxPrefixRead(d *schema.ResourceData, m interface{}) error {
d.Set("region_id", scopeID)
}
}
cf := getCustomFields(prefix.CustomFields)
cf := flattenCustomFields(prefix.CustomFields)
if cf != nil {
d.Set(customFieldsKey, cf)
}
Expand Down
2 changes: 1 addition & 1 deletion netbox/resource_netbox_rack.go
Original file line number Diff line number Diff line change
Expand Up @@ -313,7 +313,7 @@ func resourceNetboxRackRead(d *schema.ResourceData, m interface{}) error {
d.Set("form_factor", nil)
}

cf := getCustomFields(res.GetPayload().CustomFields)
cf := flattenCustomFields(res.GetPayload().CustomFields)
if cf != nil {
d.Set(customFieldsKey, cf)
}
Expand Down
2 changes: 1 addition & 1 deletion netbox/resource_netbox_service.go
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,7 @@ func resourceNetboxServiceRead(d *schema.ResourceData, m interface{}) error {
api.readTags(d, tags)
}

cf := getCustomFields(service.CustomFields)
cf := flattenCustomFields(service.CustomFields)
if cf != nil {
d.Set(customFieldsKey, cf)
}
Expand Down
2 changes: 1 addition & 1 deletion netbox/resource_netbox_site.go
Original file line number Diff line number Diff line change
Expand Up @@ -255,7 +255,7 @@ func resourceNetboxSiteRead(d *schema.ResourceData, m interface{}) error {
d.Set("tenant_id", nil)
}

cf := getCustomFields(res.GetPayload().CustomFields)
cf := flattenCustomFields(res.GetPayload().CustomFields)
if cf != nil {
d.Set(customFieldsKey, cf)
}
Expand Down
2 changes: 1 addition & 1 deletion netbox/resource_netbox_virtual_chassis.go
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ func resourceNetboxVirtualChassisRead(ctx context.Context, d *schema.ResourceDat
d.Set("description", virtualChassis.Description)
d.Set("comments", virtualChassis.Comments)

cf := getCustomFields(res.GetPayload().CustomFields)
cf := flattenCustomFields(res.GetPayload().CustomFields)
if cf != nil {
d.Set(customFieldsKey, cf)
}
Expand Down
2 changes: 1 addition & 1 deletion netbox/resource_netbox_virtual_disk.go
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ func resourceNetboxVirtualDisksRead(ctx context.Context, d *schema.ResourceData,
d.Set("virtual_machine_id", VirtualDisks.VirtualMachine.ID)
}

cf := getCustomFields(res.GetPayload().CustomFields)
cf := flattenCustomFields(res.GetPayload().CustomFields)
if cf != nil {
d.Set(customFieldsKey, cf)
}
Expand Down
2 changes: 1 addition & 1 deletion netbox/resource_netbox_virtual_machine.go
Original file line number Diff line number Diff line change
Expand Up @@ -324,7 +324,7 @@ func resourceNetboxVirtualMachineRead(ctx context.Context, d *schema.ResourceDat
}
api.readTags(d, vm.Tags)

cf := getCustomFields(vm.CustomFields)
cf := flattenCustomFields(vm.CustomFields)
if cf != nil {
d.Set(customFieldsKey, cf)
}
Expand Down
Loading