mirror of
https://github.com/bpg/terraform-provider-proxmox.git
synced 2025-06-29 18:21:10 +00:00
* feat(lxc): increase number of supported mount points to 256 * fix(container): correct condition for setting replicate value for rootfs Signed-off-by: Pavel Boldyrev <627562+bpg@users.noreply.github.com>
164 lines
4.4 KiB
Go
164 lines
4.4 KiB
Go
/*
|
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
*/
|
|
|
|
package utils
|
|
|
|
import (
|
|
"reflect"
|
|
"slices"
|
|
"strconv"
|
|
"strings"
|
|
)
|
|
|
|
// OrderedListFromMap generates a list from a map's values. The values are sorted based on the map's keys.
|
|
// The sorting is done using a custom comparison function that compares the keys with special rules, assuming they
|
|
// are strings representing device names or similar, i.e. "disk0", "net1", etc.
|
|
func OrderedListFromMap(inputMap map[string]interface{}) []interface{} {
|
|
itemCount := len(inputMap)
|
|
keyList := make([]string, itemCount)
|
|
i := 0
|
|
|
|
for key := range inputMap {
|
|
keyList[i] = key
|
|
i++
|
|
}
|
|
|
|
slices.SortFunc(keyList, compareWithPrefix)
|
|
|
|
return OrderedListFromMapByKeyValues(inputMap, keyList)
|
|
}
|
|
|
|
// CompareWithPrefix compares two string values with special rules:
|
|
// - If both start with the same prefix, trims the prefix and compares the rest as numbers if possible.
|
|
// - If numbers are equal, falls back to string comparison (preserving digit formatting).
|
|
// - If numeric parsing fails, falls back to string comparison.
|
|
// - If prefixes differ, compares the whole values as strings.
|
|
func compareWithPrefix(a, b string) int {
|
|
prefix := commonPrefix(a, b)
|
|
|
|
if prefix != "" {
|
|
aRest := strings.TrimPrefix(a, prefix)
|
|
bRest := strings.TrimPrefix(b, prefix)
|
|
|
|
aNum, aErr := strconv.Atoi(aRest)
|
|
bNum, bErr := strconv.Atoi(bRest)
|
|
|
|
if aErr == nil && bErr == nil {
|
|
if aNum != bNum {
|
|
if aNum < bNum {
|
|
return -1
|
|
}
|
|
|
|
return 1
|
|
}
|
|
// numeric values equal, fallback to string comparison
|
|
return strings.Compare(aRest, bRest)
|
|
}
|
|
|
|
return strings.Compare(aRest, bRest)
|
|
}
|
|
|
|
return strings.Compare(a, b)
|
|
}
|
|
|
|
// commonPrefix returns the longest common prefix of two strings.
|
|
func commonPrefix(a, b string) string {
|
|
minLen := len(a)
|
|
if len(b) < minLen {
|
|
minLen = len(b)
|
|
}
|
|
|
|
for i := range minLen {
|
|
if a[i] != b[i] {
|
|
return a[:i]
|
|
}
|
|
}
|
|
|
|
return a[:minLen]
|
|
}
|
|
|
|
// ListResourcesAttributeValue generates a list of strings from a Terraform resource list (which is list of maps).
|
|
// The list is generated by extracting a specific key attribute from each resource. If the attribute is not found in a
|
|
// resource, it is skipped.
|
|
func ListResourcesAttributeValue(resourceList []interface{}, keyAttr string) []string {
|
|
var l []string
|
|
|
|
for _, resource := range resourceList {
|
|
if resource == nil {
|
|
continue
|
|
}
|
|
|
|
r := resource.(map[string]interface{})
|
|
if value, ok := r[keyAttr].(string); ok {
|
|
l = append(l, value)
|
|
}
|
|
}
|
|
|
|
return l
|
|
}
|
|
|
|
// MapResourcesByAttribute generates a map of resources from a resource list, using a specified attribute as the key
|
|
// and the resource as the value. If the attribute is not found in a resource, it is skipped.
|
|
func MapResourcesByAttribute(resourceList []interface{}, keyAttr string) map[string]interface{} {
|
|
m := make(map[string]interface{}, len(resourceList))
|
|
|
|
for _, resource := range resourceList {
|
|
if resource == nil {
|
|
continue
|
|
}
|
|
|
|
r := resource.(map[string]interface{})
|
|
if key, ok := r[keyAttr].(string); ok {
|
|
m[key] = r
|
|
}
|
|
}
|
|
|
|
return m
|
|
}
|
|
|
|
// OrderedListFromMapByKeyValues generates a list from a map's values.
|
|
// The values are sorted based on the provided key list. If a key is not found in the map, it is skipped.
|
|
func OrderedListFromMapByKeyValues(inputMap map[string]interface{}, keyList []string) []interface{} {
|
|
orderedList := make([]interface{}, len(keyList))
|
|
|
|
for i, k := range keyList {
|
|
val, ok := inputMap[k]
|
|
if ok {
|
|
orderedList[i] = val
|
|
}
|
|
}
|
|
|
|
return orderedList
|
|
}
|
|
|
|
// MapDiff compares the difference between two maps and returns the elements that are in the plan but not
|
|
// in the state (toCreate), the elements that are in the plan and in the state but are different (toUpdate),
|
|
// and the elements that are in the state but not in the plan (toDelete).
|
|
// The keyFunc is used to extract a unique key from each element to compare them.
|
|
func MapDiff[T any](plan map[string]T, state map[string]T) (map[string]T, map[string]T, map[string]T) {
|
|
toCreate := map[string]T{}
|
|
toUpdate := map[string]T{}
|
|
toDelete := map[string]T{}
|
|
|
|
for key, p := range plan {
|
|
s, ok := state[key]
|
|
if !ok {
|
|
toCreate[key] = p
|
|
} else if !reflect.DeepEqual(p, s) {
|
|
toUpdate[key] = p
|
|
}
|
|
}
|
|
|
|
for key, s := range state {
|
|
_, ok := plan[key]
|
|
if !ok {
|
|
toDelete[key] = s
|
|
}
|
|
}
|
|
|
|
return toCreate, toUpdate, toDelete
|
|
}
|