From d09b7856425bd1dc617f19c2f23a64671c4766d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bindewald=2C=20Andr=C3=A9=20=28UIT=29?= Date: Mon, 6 Nov 2023 21:52:36 +0100 Subject: [PATCH 1/3] fix(virtual_network): The ordering of `address_space` elems has no effect and is not updated by Azure if the element vals are not changing --- internal/services/network/virtual_network_resource.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/services/network/virtual_network_resource.go b/internal/services/network/virtual_network_resource.go index 1fb04508d397..7c7886668047 100644 --- a/internal/services/network/virtual_network_resource.go +++ b/internal/services/network/virtual_network_resource.go @@ -67,7 +67,7 @@ func resourceVirtualNetworkSchema() map[string]*pluginsdk.Schema { "location": commonschema.Location(), "address_space": { - Type: pluginsdk.TypeList, + Type: pluginsdk.TypeSet, Required: true, MinItems: 1, Elem: &pluginsdk.Schema{ From d487f5a0291804fb4ad7ca551e5b2cce4e988d96 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bindewald=2C=20Andr=C3=A9=20=28UIT=29?= Date: Fri, 10 Nov 2023 18:52:24 +0100 Subject: [PATCH 2/3] Use DiffSuppressFunc to ignore string slice ordering changes --- .../network/virtual_network_resource.go | 4 +- internal/tf/suppress/list.go | 45 +++++++++++++++++ internal/tf/suppress/list_test.go | 48 +++++++++++++++++++ 3 files changed, 96 insertions(+), 1 deletion(-) create mode 100644 internal/tf/suppress/list.go create mode 100644 internal/tf/suppress/list_test.go diff --git a/internal/services/network/virtual_network_resource.go b/internal/services/network/virtual_network_resource.go index 7c7886668047..2bac168cb773 100644 --- a/internal/services/network/virtual_network_resource.go +++ b/internal/services/network/virtual_network_resource.go @@ -23,6 +23,7 @@ import ( "github.com/hashicorp/terraform-provider-azurerm/internal/services/network/validate" "github.com/hashicorp/terraform-provider-azurerm/internal/tags" "github.com/hashicorp/terraform-provider-azurerm/internal/tf/pluginsdk" + "github.com/hashicorp/terraform-provider-azurerm/internal/tf/suppress" "github.com/hashicorp/terraform-provider-azurerm/internal/tf/validation" "github.com/hashicorp/terraform-provider-azurerm/internal/timeouts" "github.com/hashicorp/terraform-provider-azurerm/utils" @@ -67,9 +68,10 @@ func resourceVirtualNetworkSchema() map[string]*pluginsdk.Schema { "location": commonschema.Location(), "address_space": { - Type: pluginsdk.TypeSet, + Type: pluginsdk.TypeList, Required: true, MinItems: 1, + DiffSuppressFunc: suppress.ListOrder, Elem: &pluginsdk.Schema{ Type: pluginsdk.TypeString, ValidateFunc: validation.StringIsNotEmpty, diff --git a/internal/tf/suppress/list.go b/internal/tf/suppress/list.go new file mode 100644 index 000000000000..89b475a6bd56 --- /dev/null +++ b/internal/tf/suppress/list.go @@ -0,0 +1,45 @@ +package suppress + +import ( + "fmt" + "reflect" + "sort" + "strings" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" +) + +func ListOrder(key, old, new string, d *schema.ResourceData) bool { + // Taken from https://github.com/hashicorp/terraform-plugin-sdk/issues/477#issuecomment-1238807249 + // For a list, the key is path to the element, rather than the list. + // E.g. "node_groups.2.ips.0" + lastDotIndex := strings.LastIndex(key, ".") + if lastDotIndex != -1 { + key = key[:lastDotIndex] + } + + oldData, newData := d.GetChange(key) + if oldData == nil || newData == nil { + return false + } + + sOld := make([]string, len(oldData.([]interface{}))) + sNew := make([]string, len(newData.([]interface{}))) + + for i, v := range oldData.([]interface{}) { + sOld[i] = fmt.Sprint(v) + } + + for i, v := range newData.([]interface{}) { + sNew[i] = fmt.Sprint(v) + } + + return stringSlicesAreEqual(sOld, sNew) +} + +func stringSlicesAreEqual(a []string, b []string) bool { + sort.Strings(a) + sort.Strings(b) + + return reflect.DeepEqual(a, b) +} diff --git a/internal/tf/suppress/list_test.go b/internal/tf/suppress/list_test.go new file mode 100644 index 000000000000..a5ce5b88f812 --- /dev/null +++ b/internal/tf/suppress/list_test.go @@ -0,0 +1,48 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package suppress + +import "testing" + +func TestStringSlicesAreEqual(t *testing.T) { + cases := []struct { + Name string + SliceA []string + SliceB []string + Suppress bool + }{ + { + Name: "empty", + SliceA: []string{""}, + SliceB: []string{""}, + Suppress: true, + }, + { + Name: "same", + SliceA: []string{"value1", "value2"}, + SliceB: []string{"value1", "value2"}, + Suppress: true, + }, + { + Name: "different_order", + SliceA: []string{"value1", "value2"}, + SliceB: []string{"value2", "value1"}, + Suppress: true, + }, + { + Name: "different_values", + SliceA: []string{"value1", "value2"}, + SliceB: []string{"value1", "value2", "value3"}, + Suppress: false, + }, + } + + for _, tc := range cases { + t.Run(tc.Name, func(t *testing.T) { + if stringSlicesAreEqual(tc.SliceA, tc.SliceB) != tc.Suppress { + t.Fatalf("Expected stringSlicesAreEqual to return %t for '%q' == '%q'", tc.Suppress, tc.SliceA, tc.SliceB) + } + }) + } +} From 3a6e155d7a50251478d0618b5f658e572e55d72b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bindewald=2C=20Andr=C3=A9=20=28UIT=29?= Date: Fri, 10 Nov 2023 18:57:53 +0100 Subject: [PATCH 3/3] make fmt --- internal/services/network/virtual_network_resource.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/internal/services/network/virtual_network_resource.go b/internal/services/network/virtual_network_resource.go index 2bac168cb773..b9ca9660c742 100644 --- a/internal/services/network/virtual_network_resource.go +++ b/internal/services/network/virtual_network_resource.go @@ -68,9 +68,9 @@ func resourceVirtualNetworkSchema() map[string]*pluginsdk.Schema { "location": commonschema.Location(), "address_space": { - Type: pluginsdk.TypeList, - Required: true, - MinItems: 1, + Type: pluginsdk.TypeList, + Required: true, + MinItems: 1, DiffSuppressFunc: suppress.ListOrder, Elem: &pluginsdk.Schema{ Type: pluginsdk.TypeString,