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
72 changes: 67 additions & 5 deletions netbox/custom_fields.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package netbox

import (
"context"

"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
)

Expand All @@ -9,17 +11,77 @@ const customFieldsKey = "custom_fields"
var customFieldsSchema = &schema.Schema{
Type: schema.TypeMap,
Optional: true,
Computed: true,
Default: nil,
Elem: &schema.Schema{
Type: schema.TypeString,
Default: nil,
},
}

func getCustomFields(cf interface{}) map[string]interface{} {
cfm, ok := cf.(map[string]interface{})
if !ok || len(cfm) == 0 {
return nil
var customFieldsSchemaRead = &schema.Schema{
Type: schema.TypeMap,
Computed: true,
Elem: &schema.Schema{
Type: schema.TypeString,
},
}

func normalizeCustomFields(cfm map[string]interface{}) map[string]interface{} {
newcfm := make(map[string]interface{})

for k, v := range cfm {
if v != nil && v != "" {
newcfm[k] = v
}
}

return newcfm
}

func mergeCustomFields(oldcfm, newcfm map[string]interface{}) map[string]interface{} {
if newcfm == nil {
newcfm = make(map[string]interface{})
}

for k, v := range newcfm {
if v == nil {
newcfm[k] = ""
}
}

for k := range oldcfm {
if _, ok := newcfm[k]; !ok {
newcfm[k] = ""
}
}

return newcfm
}

func customFieldsDiff(ctx context.Context, d *schema.ResourceDiff, meta interface{}) error {
cfg := d.GetRawConfig().GetAttr(customFieldsKey)
cfm, ok := d.Get(customFieldsKey).(map[string]interface{})

if cfg.IsNull() || !ok {
d.SetNew(customFieldsKey, nil)
} else {
newcfm := normalizeCustomFields(cfm)
d.SetNew(customFieldsKey, newcfm)
}
return cfm

return nil
}

func computeCustomFieldsAttr(cf interface{}) map[string]interface{} {
cfm, _ := cf.(map[string]interface{})
return normalizeCustomFields(cfm)
}

func computeCustomFieldsModel(d *schema.ResourceData) interface{} {
oldcf, newcf := d.GetChange(customFieldsKey)

oldcfm, _ := oldcf.(map[string]interface{})
newcfm, _ := newcf.(map[string]interface{})
return mergeCustomFields(oldcfm, newcfm)
}
185 changes: 185 additions & 0 deletions netbox/custom_fields_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,185 @@
package netbox

import (
"testing"

"github.com/stretchr/testify/assert"
)

func TestCustomFields_normalize(t *testing.T) {
tests := []struct {
name string
input map[string]interface{}
expected map[string]interface{}
}{
{
name: "MapNil",
input: nil,
expected: map[string]interface{}{},
},
{
name: "MapEmpty",
input: map[string]interface{}{},
expected: map[string]interface{}{},
},
{
name: "MapFull",
input: map[string]interface{}{
"key1": "value1",
"key2": "value2",
},
expected: map[string]interface{}{
"key1": "value1",
"key2": "value2",
},
},
{
name: "MapMixed",
input: map[string]interface{}{
"key1": "value1",
"key2": "",
"key3": nil,
},
expected: map[string]interface{}{
"key1": "value1",
},
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
result := normalizeCustomFields(tt.input)
assert.Equal(t, tt.expected, result)
})
}
}

func TestCustomFields_merge(t *testing.T) {
tests := []struct {
name string
state map[string]interface{}
input map[string]interface{}
expected map[string]interface{}
}{
{
name: "MapNilBoth",
state: nil,
input: nil,
expected: map[string]interface{}{},
},
{
name: "MapNilNew",
state: map[string]interface{}{},
input: nil,
expected: map[string]interface{}{},
},
{
name: "MapNilOld",
state: nil,
input: map[string]interface{}{},
expected: map[string]interface{}{},
},
{
name: "MapUnsetWithMissing",
state: map[string]interface{}{
"key1": "value1",
},
input: map[string]interface{}{},
expected: map[string]interface{}{
"key1": "",
},
},
{
name: "MapUnsetWithNil",
state: map[string]interface{}{
"key1": "value1",
},
input: map[string]interface{}{
"key1": nil,
},
expected: map[string]interface{}{
"key1": "",
},
},
{
name: "MapUnsetWithEmpty",
state: map[string]interface{}{
"key1": "value1",
},
input: map[string]interface{}{},
expected: map[string]interface{}{
"key1": "",
},
},
{
name: "MapUnsetWithNilNotSet",
state: map[string]interface{}{},
input: map[string]interface{}{
"key1": nil,
},
expected: map[string]interface{}{
"key1": "",
},
},
{
name: "MapUnsetWithEmptyNotSet",
state: map[string]interface{}{},
input: map[string]interface{}{
"key1": "",
},
expected: map[string]interface{}{
"key1": "",
},
},
{
name: "MapSetNew",
state: map[string]interface{}{},
input: map[string]interface{}{
"key1": "test",
},
expected: map[string]interface{}{
"key1": "test",
},
},
{
name: "MapSetExisting",
state: map[string]interface{}{
"key1": " test",
},
input: map[string]interface{}{
"key1": "testnew",
},
expected: map[string]interface{}{
"key1": "testnew",
},
},
{
name: "MapMixed",
state: map[string]interface{}{
"key1": "value1",
"key2": "value2",
"key3": "",
"key4": nil,
},
input: map[string]interface{}{
"key1": "valuenew1",
"key2": nil,
"keynew": "valuenew2",
},
expected: map[string]interface{}{
"key1": "valuenew1",
"key2": "",
"key3": "",
"key4": "",
"keynew": "valuenew2",
},
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
result := mergeCustomFields(tt.state, tt.input)
assert.Equal(t, tt.expected, result)
})
}
}
13 changes: 5 additions & 8 deletions netbox/data_source_netbox_cluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,11 +53,8 @@ func dataSourceNetboxCluster() *schema.Resource {
Computed: true,
Optional: true,
},
"custom_fields": {
Type: schema.TypeMap,
Computed: true,
},
tagsKey: tagsSchemaRead,
customFieldsKey: customFieldsSchemaRead,
tagsKey: tagsSchemaRead,
},
}
}
Expand Down Expand Up @@ -116,10 +113,10 @@ func dataSourceNetboxClusterRead(d *schema.ResourceData, m interface{}) error {
} else {
d.Set("site_id", nil)
}
if result.CustomFields != nil {
d.Set("custom_fields", result.CustomFields)
}

d.Set(customFieldsKey, result.CustomFields)

d.Set(tagsKey, getTagListFromNestedTagList(result.Tags))

return nil
}
13 changes: 6 additions & 7 deletions netbox/data_source_netbox_prefix.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ func dataSourceNetboxPrefix() *schema.Resource {
ValidateFunc: validation.IsCIDR,
AtLeastOneOf: []string{"description", "family", "prefix", "vlan_vid", "vrf_id", "vlan_id", "tenant_id", "site_id", "role_id", "cidr", "tag", "status"},
},
customFieldsKey: customFieldsSchema,
"description": {
Type: schema.TypeString,
Optional: true,
Expand Down Expand Up @@ -100,7 +99,8 @@ for more information on available lookup expressions.`,
Optional: true,
AtLeastOneOf: []string{"description", "family", "prefix", "vlan_vid", "vrf_id", "vlan_id", "tenant_id", "site_id", "role_id", "cidr", "tag", "status"},
},
"tags": tagsSchemaRead,
customFieldsKey: customFieldsSchemaRead,
tagsKey: tagsSchemaRead,
},
}
}
Expand Down Expand Up @@ -189,12 +189,11 @@ func dataSourceNetboxPrefixRead(d *schema.ResourceData, m interface{}) error {
d.Set("status", result.Status.Value)
d.Set("description", result.Description)
d.Set("family", int(*result.Family.Value))
d.Set("tags", getTagListFromNestedTagList(result.Tags))

cf := getCustomFields(result.CustomFields)
if cf != nil {
d.Set(customFieldsKey, cf)
}
d.Set(customFieldsKey, result.CustomFields)

d.Set(tagsKey, getTagListFromNestedTagList(result.Tags))

if result.Role != nil {
d.Set("role_id", result.Role.ID)
}
Expand Down
13 changes: 6 additions & 7 deletions netbox/data_source_netbox_racks.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,6 @@ func dataSourceNetboxRacks() *schema.Resource {
Type: schema.TypeInt,
Computed: true,
},
tagsKey: tagsSchemaRead,
"tenant_id": {
Type: schema.TypeInt,
Computed: true,
Expand Down Expand Up @@ -136,10 +135,8 @@ func dataSourceNetboxRacks() *schema.Resource {
Type: schema.TypeString,
Computed: true,
},
"custom_fields": {
Type: schema.TypeMap,
Computed: true,
},
customFieldsKey: customFieldsSchemaRead,
tagsKey: tagsSchemaRead,
},
},
},
Expand Down Expand Up @@ -246,7 +243,6 @@ func dataSourceNetboxRacksRead(d *schema.ResourceData, m interface{}) error {
mapping["width"] = v.Width.Value
}
mapping["u_height"] = v.UHeight
mapping["tags"] = getTagListFromNestedTagList(v.Tags)
if v.Tenant != nil {
mapping["tenant_id"] = v.Tenant.ID
}
Expand All @@ -273,7 +269,10 @@ func dataSourceNetboxRacksRead(d *schema.ResourceData, m interface{}) error {
mapping["mounting_depth"] = v.MountingDepth
mapping["description"] = v.Description
mapping["comments"] = v.Comments
mapping["custom_fields"] = getCustomFields(v.CustomFields)

mapping[customFieldsKey] = v.CustomFields

mapping[tagsKey] = getTagListFromNestedTagList(v.Tags)

s = append(s, mapping)
}
Expand Down
Loading
Loading