From 53382b932bf4c3df9aadd7f2c2af8f11fdad3205 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20Nie=C3=9F?= Date: Mon, 14 Nov 2022 18:15:22 +0100 Subject: [PATCH] fix: Custom fields default values not null Fixes: 180 - Fix field default. - Add group_name and ui_visibility to customfield --- .../netbox_extras_custom_field/import.sh | 2 + .../resource_netbox_extras_custom_field.go | 67 ++++++++++++++++--- ...netbox_extras_custom_field_boolean_test.go | 17 ++--- ...ce_netbox_extras_custom_field_date_test.go | 17 ++--- ...netbox_extras_custom_field_integer_test.go | 5 +- ...ce_netbox_extras_custom_field_json_test.go | 29 ++++---- ...etbox_extras_custom_field_longtext_test.go | 4 +- ...ox_extras_custom_field_multiobject_test.go | 23 ++++--- ...ox_extras_custom_field_multiselect_test.go | 17 ++--- ..._netbox_extras_custom_field_object_test.go | 23 ++++--- ..._netbox_extras_custom_field_select_test.go | 16 +++-- ...ce_netbox_extras_custom_field_text_test.go | 4 +- ...rce_netbox_extras_custom_field_url_test.go | 17 ++--- netbox/internal/util/nested.go | 8 +++ 14 files changed, 162 insertions(+), 87 deletions(-) create mode 100644 examples/resources/netbox_extras_custom_field/import.sh diff --git a/examples/resources/netbox_extras_custom_field/import.sh b/examples/resources/netbox_extras_custom_field/import.sh new file mode 100644 index 000000000..6f461e366 --- /dev/null +++ b/examples/resources/netbox_extras_custom_field/import.sh @@ -0,0 +1,2 @@ +# Custom fields can be imported by id +terraform import netbox_extras_custom_field.cf_text 1 diff --git a/netbox/extras/resource_netbox_extras_custom_field.go b/netbox/extras/resource_netbox_extras_custom_field.go index 4c7af4b6e..e20acf8d1 100644 --- a/netbox/extras/resource_netbox_extras_custom_field.go +++ b/netbox/extras/resource_netbox_extras_custom_field.go @@ -2,6 +2,7 @@ package extras import ( "context" + "encoding/json" "strconv" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" @@ -63,7 +64,7 @@ func ResourceNetboxExtrasCustomField() *schema.Resource { "default": { Type: schema.TypeString, Optional: true, - Description: "The default value for this custom field. Encoded as JSON.", + Description: "The default value for this custom field. This value must be valid Json. Strings, List and Dicts should be wrapped in jsonencode()", }, "description": { Type: schema.TypeString, @@ -79,6 +80,13 @@ func ResourceNetboxExtrasCustomField() *schema.Resource { ValidateFunc: validation.StringInSlice([]string{"disabled", "loose", "exact"}, false), Description: "The filter logic for this custom field. Allowed values: \"loose\" (default), \"exact\", \"disabled\"", }, + "group_name": { + Type: schema.TypeString, + Optional: true, + Default: nil, + ValidateFunc: validation.StringLenBetween(1, 50), + Description: "Custom fields within the same group will be displayed together.", + }, "label": { Type: schema.TypeString, Optional: true, @@ -123,6 +131,13 @@ func ResourceNetboxExtrasCustomField() *schema.Resource { }, false), Description: "Type of the custom field (text, longtext, integer, boolean, url, json, select, multiselect, object, multiobject).", }, + "ui_visibility": { + Type: schema.TypeString, + Optional: true, + Default: "read-write", + ValidateFunc: validation.StringInSlice([]string{"read-write", "read-only", "hidden"}, false), + Description: "The filter logic for this custom field. Allowed values: \"read-write\" (default), \"read-only\", \"hidden\"", + }, "url": { Type: schema.TypeString, Computed: true, @@ -167,7 +182,6 @@ func resourceNetboxExtrasCustomFieldCreate(ctx context.Context, d *schema.Resour client := m.(*netboxclient.NetBoxAPI) name := d.Get("name").(string) - defaultstring := d.Get("default").(string) validationMaximum := int64(d.Get("validation_maximum").(int)) var validationMaximumPtr *int64 if validationMaximum != 0 { @@ -187,20 +201,30 @@ func resourceNetboxExtrasCustomFieldCreate(ctx context.Context, d *schema.Resour newResource := &models.WritableCustomField{ Choices: util.ToListofStrings(d.Get("choices").(*schema.Set).List()), ContentTypes: util.ToListofStrings(d.Get("content_types").(*schema.Set).List()), - Default: &defaultstring, Description: d.Get("description").(string), FilterLogic: d.Get("filter_logic").(string), + GroupName: d.Get("group_name").(string), Label: d.Get("label").(string), Name: &name, ObjectType: d.Get("object_type").(string), Required: d.Get("required").(bool), Type: d.Get("type").(string), + UIVisibility: d.Get("ui_visibility").(string), ValidationMaximum: validationMaximumPtr, ValidationMinimum: validationMinimumPtr, ValidationRegex: d.Get("validation_regex").(string), Weight: &weight, } + if defaultstring := d.Get("default").(string); defaultstring != "" { + var jsonMap interface{} + err := json.Unmarshal([]byte(defaultstring), &jsonMap) + if err != nil { + return diag.FromErr(err) + } + newResource.Default = jsonMap + } + resource := extras.NewExtrasCustomFieldsCreateParams().WithData(newResource) resourceCreated, err := client.Extras.ExtrasCustomFieldsCreate(resource, nil) @@ -246,8 +270,15 @@ func resourceNetboxExtrasCustomFieldRead(ctx context.Context, d *schema.Resource if err = d.Set("data_type", resource.DataType); err != nil { return diag.FromErr(err) } - if err = d.Set("default", resource.Default); err != nil { - return diag.FromErr(err) + if resource.Default != nil { + jsonValue, _ := json.Marshal(resource.Default) + if err = d.Set("default", string(jsonValue)); err != nil { + return diag.FromErr(err) + } + } else { + if err = d.Set("default", nil); err != nil { + return diag.FromErr(err) + } } if err = d.Set("description", resource.Description); err != nil { return diag.FromErr(err) @@ -255,6 +286,9 @@ func resourceNetboxExtrasCustomFieldRead(ctx context.Context, d *schema.Resource if err = d.Set("filter_logic", resource.FilterLogic.Value); err != nil { return diag.FromErr(err) } + if err = d.Set("group_name", resource.GroupName); err != nil { + return diag.FromErr(err) + } if err = d.Set("label", resource.Label); err != nil { return diag.FromErr(err) } @@ -273,6 +307,9 @@ func resourceNetboxExtrasCustomFieldRead(ctx context.Context, d *schema.Resource if err = d.Set("type", resource.Type.Value); err != nil { return diag.FromErr(err) } + if err = d.Set("ui_visibility", util.GetCustomFieldUIVisibilityValue(resource.UIVisibility)); err != nil { + return diag.FromErr(err) + } if err = d.Set("url", resource.URL); err != nil { return diag.FromErr(err) } @@ -310,9 +347,16 @@ func resourceNetboxExtrasCustomFieldUpdate(ctx context.Context, d *schema.Resour params.ContentTypes = util.ToListofStrings(d.Get("content_types").(*schema.Set).List()) } if d.HasChange("default") { - defaultvalue := d.Get("default").(string) - params.Default = &defaultvalue - modifiedFields["default"] = defaultvalue + if defaultstring := d.Get("default").(string); defaultstring != "" { + var jsonMap interface{} + err := json.Unmarshal([]byte(defaultstring), &jsonMap) + if err != nil { + return diag.FromErr(err) + } + params.Default = jsonMap + } else { + modifiedFields["default"] = nil + } } if d.HasChange("description") { params.Description = d.Get("description").(string) @@ -321,6 +365,10 @@ func resourceNetboxExtrasCustomFieldUpdate(ctx context.Context, d *schema.Resour if d.HasChange("filter_logic") { params.FilterLogic = d.Get("filter_logic").(string) } + if d.HasChange("group_name") { + params.GroupName = d.Get("group_name").(string) + modifiedFields["group_name"] = params.GroupName + } if d.HasChange("label") { params.Label = d.Get("label").(string) modifiedFields["label"] = params.Label @@ -339,6 +387,9 @@ func resourceNetboxExtrasCustomFieldUpdate(ctx context.Context, d *schema.Resour if d.HasChange("type") { params.Type = d.Get("type").(string) } + if d.HasChange("ui_visibility") { + params.UIVisibility = d.Get("ui_visibility").(string) + } if d.HasChange("validation_maximum") { validationMaximum := int64(d.Get("validation_maximum").(int)) params.ValidationMaximum = &validationMaximum diff --git a/netbox/extras/resource_netbox_extras_custom_field_boolean_test.go b/netbox/extras/resource_netbox_extras_custom_field_boolean_test.go index 3cc80c64f..467bf8e34 100644 --- a/netbox/extras/resource_netbox_extras_custom_field_boolean_test.go +++ b/netbox/extras/resource_netbox_extras_custom_field_boolean_test.go @@ -98,15 +98,16 @@ func testAccCheckNetboxExtrasCustomFieldBooleanConfig(nameSuffix string, resourc "dcim.site", ] - type = "boolean" + type = "boolean" {{ if eq .resourcefull "true" }} - description = "Test custom field" - label = "Test Label for CF" - weight = 50 - #required = true - filter_logic = "disabled" - # Fixed in Netbox 3.3 - #default = true + description = "Test custom field" + group_name = "testgroup" + ui_visibility = "hidden" + label = "Test Label for CF" + weight = 50 + #required = true + filter_logic = "disabled" + default = true {{ end }} } ` diff --git a/netbox/extras/resource_netbox_extras_custom_field_date_test.go b/netbox/extras/resource_netbox_extras_custom_field_date_test.go index 11751ad0e..1c9bbcc1e 100644 --- a/netbox/extras/resource_netbox_extras_custom_field_date_test.go +++ b/netbox/extras/resource_netbox_extras_custom_field_date_test.go @@ -98,15 +98,16 @@ func testAccCheckNetboxExtrasCustomFieldDateConfig(nameSuffix string, resourceFu "dcim.site", ] - type = "date" + type = "date" {{ if eq .resourcefull "true" }} - description = "Test custom field" - label = "Test Label for CF" - weight = 50 - #required = true - filter_logic = "disabled" - # Fixed in Netbox 3.3 - #default = "2022-01-01" + description = "Test custom field" + group_name = "testgroup" + ui_visibility = "hidden" + label = "Test Label for CF" + weight = 50 + #required = true + filter_logic = "disabled" + default = jsonencode("2022-01-01") {{ end }} } ` diff --git a/netbox/extras/resource_netbox_extras_custom_field_integer_test.go b/netbox/extras/resource_netbox_extras_custom_field_integer_test.go index e3a24d171..85e7a5d6f 100644 --- a/netbox/extras/resource_netbox_extras_custom_field_integer_test.go +++ b/netbox/extras/resource_netbox_extras_custom_field_integer_test.go @@ -101,12 +101,13 @@ func testAccCheckNetboxExtrasCustomFieldIntegerConfig(nameSuffix string, resourc type = "integer" {{ if eq .resourcefull "true" }} description = "Test custom field" + group_name = "testgroup" + ui_visibility = "hidden" label = "Test Label for CF" weight = 50 #required = true filter_logic = "disabled" - # Fixed in Netbox 3.3 - #default = 50 + default = 50 validation_minimum = 1 validation_maximum = 500 {{ end }} diff --git a/netbox/extras/resource_netbox_extras_custom_field_json_test.go b/netbox/extras/resource_netbox_extras_custom_field_json_test.go index b25efef3d..9e40f8738 100644 --- a/netbox/extras/resource_netbox_extras_custom_field_json_test.go +++ b/netbox/extras/resource_netbox_extras_custom_field_json_test.go @@ -98,21 +98,22 @@ func testAccCheckNetboxExtrasCustomFieldJSONConfig(nameSuffix string, resourceFu "dcim.site", ] - type = "json" + type = "json" {{ if eq .resourcefull "true" }} - description = "Test custom field" - label = "Test Label for CF" - weight = 50 - #required = true - filter_logic = "disabled" - # Fixed in Netbox 3.3 - #default = jsonencode({ - # bool = false - # number = 1.5 - # dict = { - # text = "Some text"} - # } - #}) + description = "Test custom field" + group_name = "testgroup" + ui_visibility = "hidden" + label = "Test Label for CF" + weight = 50 + #required = true + filter_logic = "disabled" + default = jsonencode({ + bool = false + number = 1.5 + dict = { + text = "Some text" + } + }) {{ end }} } ` diff --git a/netbox/extras/resource_netbox_extras_custom_field_longtext_test.go b/netbox/extras/resource_netbox_extras_custom_field_longtext_test.go index 8e51c1496..51a63a973 100644 --- a/netbox/extras/resource_netbox_extras_custom_field_longtext_test.go +++ b/netbox/extras/resource_netbox_extras_custom_field_longtext_test.go @@ -101,11 +101,13 @@ func testAccCheckNetboxExtrasCustomFieldLongtextConfig(nameSuffix string, resour type = "longtext" {{ if eq .resourcefull "true" }} description = "Test custom field" + group_name = "testgroup" + ui_visibility = "hidden" label = "Test Label for CF" weight = 50 #required = true filter_logic = "disabled" - default = "Default text" + default = jsonencode("Default text") validation_regex = "^.*$" {{ end }} } diff --git a/netbox/extras/resource_netbox_extras_custom_field_multiobject_test.go b/netbox/extras/resource_netbox_extras_custom_field_multiobject_test.go index 2a9fc2c0f..231b9086c 100644 --- a/netbox/extras/resource_netbox_extras_custom_field_multiobject_test.go +++ b/netbox/extras/resource_netbox_extras_custom_field_multiobject_test.go @@ -105,18 +105,19 @@ func testAccCheckNetboxExtrasCustomFieldMultiObjectConfig(nameSuffix string, res "dcim.site", ] - type = "multiobject" - object_type = "dcim.platform" + type = "multiobject" + object_type = "dcim.platform" {{ if eq .resourcefull "true" }} - description = "Test custom field" - label = "Test Label for CF" - weight = 50 - #required = true - filter_logic = "disabled" - # Fixed in netbox 3.3 - #default = jsonencode([ - # netbox_dcim_platform.test.id - #]) + description = "Test custom field" + label = "Test Label for CF" + group_name = "testgroup" + ui_visibility = "hidden" + weight = 50 + #required = true + filter_logic = "disabled" + default = jsonencode([ + netbox_dcim_platform.test.id + ]) {{ end }} } ` diff --git a/netbox/extras/resource_netbox_extras_custom_field_multiselect_test.go b/netbox/extras/resource_netbox_extras_custom_field_multiselect_test.go index e9f4c438f..8e30a7846 100644 --- a/netbox/extras/resource_netbox_extras_custom_field_multiselect_test.go +++ b/netbox/extras/resource_netbox_extras_custom_field_multiselect_test.go @@ -98,19 +98,20 @@ func testAccCheckNetboxExtrasCustomFieldMultiSelectConfig(nameSuffix string, res "dcim.site", ] - type = "multiselect" + type = "multiselect" {{ if eq .resourcefull "true" }} - description = "Test custom field" + description = "Test custom field" choices = [ "test", "test2" ] - label = "Test Label for CF" - weight = 50 - #required = true - filter_logic = "disabled" - # Fixed in netbox 3.3 - #default = "test" + label = "Test Label for CF" + group_name = "testgroup" + ui_visibility = "hidden" + weight = 50 + #required = true + filter_logic = "disabled" + default = jsonencode(["test"]) {{ end }} } ` diff --git a/netbox/extras/resource_netbox_extras_custom_field_object_test.go b/netbox/extras/resource_netbox_extras_custom_field_object_test.go index d04e42594..cf4409df3 100644 --- a/netbox/extras/resource_netbox_extras_custom_field_object_test.go +++ b/netbox/extras/resource_netbox_extras_custom_field_object_test.go @@ -105,18 +105,19 @@ func testAccCheckNetboxExtrasCustomFieldObjectConfig(nameSuffix string, resource "dcim.site", ] - type = "object" - object_type = "dcim.platform" + type = "object" + object_type = "dcim.platform" {{ if eq .resourcefull "true" }} - description = "Test custom field" - label = "Test Label for CF" - weight = 50 - #required = true - filter_logic = "disabled" - # Fixed in netbox 3.3 - #default = jsonencode([ - # netbox_dcim_platform.test.id - #]) + description = "Test custom field" + group_name = "testgroup" + ui_visibility = "hidden" + label = "Test Label for CF" + weight = 50 + #required = true + filter_logic = "disabled" + default = jsonencode([ + netbox_dcim_platform.test.id + ]) {{ end }} } ` diff --git a/netbox/extras/resource_netbox_extras_custom_field_select_test.go b/netbox/extras/resource_netbox_extras_custom_field_select_test.go index 4cf39f072..a01806f4d 100644 --- a/netbox/extras/resource_netbox_extras_custom_field_select_test.go +++ b/netbox/extras/resource_netbox_extras_custom_field_select_test.go @@ -98,18 +98,20 @@ func testAccCheckNetboxExtrasCustomFieldSelectConfig(nameSuffix string, resource "dcim.site", ] - type = "select" + type = "select" {{ if eq .resourcefull "true" }} - description = "Test custom field" + description = "Test custom field" choices = [ "test", "test2" ] - label = "Test Label for CF" - weight = 50 - #required = true - filter_logic = "disabled" - default = "test" + label = "Test Label for CF" + group_name = "testgroup" + ui_visibility = "hidden" + weight = 50 + #required = true + filter_logic = "disabled" + default = jsonencode("test") {{ end }} } ` diff --git a/netbox/extras/resource_netbox_extras_custom_field_text_test.go b/netbox/extras/resource_netbox_extras_custom_field_text_test.go index 7dafedad7..b0daa1cf9 100644 --- a/netbox/extras/resource_netbox_extras_custom_field_text_test.go +++ b/netbox/extras/resource_netbox_extras_custom_field_text_test.go @@ -102,10 +102,12 @@ func testAccCheckNetboxExtrasCustomFieldTextConfig(nameSuffix string, resourceFu {{ if eq .resourcefull "true" }} description = "Test custom field" label = "Test Label for CF" + group_name = "testgroup" + ui_visibility = "hidden" weight = 50 #required = true filter_logic = "disabled" - default = "Default text" + default = jsonencode("Default text") validation_regex = "^.*$" {{ end }} } diff --git a/netbox/extras/resource_netbox_extras_custom_field_url_test.go b/netbox/extras/resource_netbox_extras_custom_field_url_test.go index 3a1a3cded..5ef50d748 100644 --- a/netbox/extras/resource_netbox_extras_custom_field_url_test.go +++ b/netbox/extras/resource_netbox_extras_custom_field_url_test.go @@ -98,15 +98,16 @@ func testAccCheckNetboxExtrasCustomFieldURLConfig(nameSuffix string, resourceFul "dcim.site", ] - type = "url" + type = "url" {{ if eq .resourcefull "true" }} - description = "Test custom field" - label = "Test Label for CF" - weight = 50 - #required = true - filter_logic = "disabled" - # Fixed in Netbox 3.3 - #default = "https://netbox.dev/" + description = "Test custom field" + label = "Test Label for CF" + group_name = "testgroup" + ui_visibility = "hidden" + weight = 50 + #required = true + filter_logic = "disabled" + default = jsonencode("https://netbox.dev/") {{ end }} } ` diff --git a/netbox/internal/util/nested.go b/netbox/internal/util/nested.go index 202a18138..00086a896 100644 --- a/netbox/internal/util/nested.go +++ b/netbox/internal/util/nested.go @@ -12,6 +12,14 @@ func GetClusterStatusValue(nested *models.ClusterStatus) *string { return nested.Value } +func GetCustomFieldUIVisibilityValue(nested *models.CustomFieldUIVisibility) *string { + if nested == nil { + return nil + } + + return nested.Value +} + func GetNestedIPAddressAddress(nested *models.NestedIPAddress) *string { if nested == nil { return nil