diff --git a/proxmoxtf/resource/container.go b/proxmoxtf/resource/container.go index e52935d4..6df606ec 100644 --- a/proxmoxtf/resource/container.go +++ b/proxmoxtf/resource/container.go @@ -605,10 +605,12 @@ func Container() *schema.Resource { }, }, mkResourceVirtualEnvironmentContainerTags: { - Type: schema.TypeList, - Description: "Tags of the container. This is only meta information.", - Optional: true, - Elem: &schema.Schema{Type: schema.TypeString}, + Type: schema.TypeList, + Description: "Tags of the container. This is only meta information.", + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, + DiffSuppressFunc: suppressIfListsAreEqualIgnoringOrder, + DiffSuppressOnRefresh: true, }, mkResourceVirtualEnvironmentContainerTemplate: { Type: schema.TypeBool, diff --git a/proxmoxtf/resource/utils.go b/proxmoxtf/resource/utils.go index e36701c6..179ba0c0 100644 --- a/proxmoxtf/resource/utils.go +++ b/proxmoxtf/resource/utils.go @@ -9,7 +9,9 @@ package resource import ( "errors" "fmt" + "reflect" "regexp" + "sort" "strings" "time" "unicode" @@ -406,6 +408,42 @@ func getVMIDValidator() schema.SchemaValidateDiagFunc { }) } +// suppressIfListsAreEqualIgnoringOrder is a customdiff.SuppressionFunc that suppresses +// changes to a list if the old and new lists are equal, ignoring the order of the +// elements. +// It will be called for each list item, so it is not super efficient. It is +// recommended to use it only for small lists. +// Ref: https://github.com/hashicorp/terraform-plugin-sdk/issues/477 +func suppressIfListsAreEqualIgnoringOrder(key, _, _ string, d *schema.ResourceData) bool { + // the key is a path to the list item, not the list itself, e.g. "tags.0" + lastDotIndex := strings.LastIndex(key, ".") + if lastDotIndex != -1 { + key = key[:lastDotIndex] + } + oldData, newData := d.GetChange(key) + if oldData == nil || newData == nil { + return false + } + oldArray := oldData.([]interface{}) + newArray := newData.([]interface{}) + if len(oldArray) != len(newArray) { + return false + } + + oldEvents := make([]string, len(oldArray)) + newEvents := make([]string, len(newArray)) + for i, oldEvt := range oldArray { + oldEvents[i] = fmt.Sprint(oldEvt) + } + for j, newEvt := range newArray { + newEvents[j] = fmt.Sprint(newEvt) + } + + sort.Strings(oldEvents) + sort.Strings(newEvents) + return reflect.DeepEqual(oldEvents, newEvents) +} + func getDiskInfo(vm *proxmox.VirtualEnvironmentVMGetResponseData, d *schema.ResourceData) map[string]*proxmox.CustomStorageDevice { currentDisk := d.Get(mkResourceVirtualEnvironmentVMDisk) diff --git a/proxmoxtf/resource/vm.go b/proxmoxtf/resource/vm.go index dff6c776..085f00c2 100644 --- a/proxmoxtf/resource/vm.go +++ b/proxmoxtf/resource/vm.go @@ -1117,10 +1117,12 @@ func VM() *schema.Resource { Default: dvResourceVirtualEnvironmentVMTabletDevice, }, mkResourceVirtualEnvironmentVMTags: { - Type: schema.TypeList, - Description: "Tags of the virtual machine. This is only meta information.", - Optional: true, - Elem: &schema.Schema{Type: schema.TypeString}, + Type: schema.TypeList, + Description: "Tags of the virtual machine. This is only meta information.", + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, + DiffSuppressFunc: suppressIfListsAreEqualIgnoringOrder, + DiffSuppressOnRefresh: true, }, mkResourceVirtualEnvironmentVMTemplate: { Type: schema.TypeBool,