From 4ad7c41ab42889ba79334e7f17a8e283015320b7 Mon Sep 17 00:00:00 2001 From: James Bardin Date: Tue, 1 Dec 2020 16:17:18 -0500 Subject: [PATCH] unused --- flatmap/expand.go | 152 --------------------------- flatmap/expand_test.go | 225 ---------------------------------------- flatmap/flatten.go | 71 ------------- flatmap/flatten_test.go | 88 ---------------- flatmap/map.go | 82 --------------- flatmap/map_test.go | 120 --------------------- 6 files changed, 738 deletions(-) delete mode 100644 flatmap/expand.go delete mode 100644 flatmap/expand_test.go delete mode 100644 flatmap/flatten.go delete mode 100644 flatmap/flatten_test.go delete mode 100644 flatmap/map.go delete mode 100644 flatmap/map_test.go diff --git a/flatmap/expand.go b/flatmap/expand.go deleted file mode 100644 index b9d15461e..000000000 --- a/flatmap/expand.go +++ /dev/null @@ -1,152 +0,0 @@ -package flatmap - -import ( - "fmt" - "sort" - "strconv" - "strings" - - "github.com/hashicorp/terraform/configs/hcl2shim" -) - -// Expand takes a map and a key (prefix) and expands that value into -// a more complex structure. This is the reverse of the Flatten operation. -func Expand(m map[string]string, key string) interface{} { - // If the key is exactly a key in the map, just return it - if v, ok := m[key]; ok { - if v == "true" { - return true - } else if v == "false" { - return false - } - - return v - } - - // Check if the key is an array, and if so, expand the array - if v, ok := m[key+".#"]; ok { - // If the count of the key is unknown, then just put the unknown - // value in the value itself. This will be detected by Terraform - // core later. - if v == hcl2shim.UnknownVariableValue { - return v - } - - return expandArray(m, key) - } - - // Check if this is a prefix in the map - prefix := key + "." - for k := range m { - if strings.HasPrefix(k, prefix) { - return expandMap(m, prefix) - } - } - - return nil -} - -func expandArray(m map[string]string, prefix string) []interface{} { - num, err := strconv.ParseInt(m[prefix+".#"], 0, 0) - if err != nil { - panic(err) - } - - // If the number of elements in this array is 0, then return an - // empty slice as there is nothing to expand. Trying to expand it - // anyway could lead to crashes as any child maps, arrays or sets - // that no longer exist are still shown as empty with a count of 0. - if num == 0 { - return []interface{}{} - } - - // NOTE: "num" is not necessarily accurate, e.g. if a user tampers - // with state, so the following code should not crash when given a - // number of items more or less than what's given in num. The - // num key is mainly just a hint that this is a list or set. - - // The Schema "Set" type stores its values in an array format, but - // using numeric hash values instead of ordinal keys. Take the set - // of keys regardless of value, and expand them in numeric order. - // See GH-11042 for more details. - keySet := map[int]bool{} - computed := map[string]bool{} - for k := range m { - if !strings.HasPrefix(k, prefix+".") { - continue - } - - key := k[len(prefix)+1:] - idx := strings.Index(key, ".") - if idx != -1 { - key = key[:idx] - } - - // skip the count value - if key == "#" { - continue - } - - // strip the computed flag if there is one - if strings.HasPrefix(key, "~") { - key = key[1:] - computed[key] = true - } - - k, err := strconv.Atoi(key) - if err != nil { - panic(err) - } - keySet[int(k)] = true - } - - keysList := make([]int, 0, num) - for key := range keySet { - keysList = append(keysList, key) - } - sort.Ints(keysList) - - result := make([]interface{}, len(keysList)) - for i, key := range keysList { - keyString := strconv.Itoa(key) - if computed[keyString] { - keyString = "~" + keyString - } - result[i] = Expand(m, fmt.Sprintf("%s.%s", prefix, keyString)) - } - - return result -} - -func expandMap(m map[string]string, prefix string) map[string]interface{} { - // Submaps may not have a '%' key, so we can't count on this value being - // here. If we don't have a count, just proceed as if we have have a map. - if count, ok := m[prefix+"%"]; ok && count == "0" { - return map[string]interface{}{} - } - - result := make(map[string]interface{}) - for k := range m { - if !strings.HasPrefix(k, prefix) { - continue - } - - key := k[len(prefix):] - idx := strings.Index(key, ".") - if idx != -1 { - key = key[:idx] - } - if _, ok := result[key]; ok { - continue - } - - // skip the map count value - if key == "%" { - continue - } - - result[key] = Expand(m, k[:len(prefix)+len(key)]) - } - - return result -} diff --git a/flatmap/expand_test.go b/flatmap/expand_test.go deleted file mode 100644 index 707c015da..000000000 --- a/flatmap/expand_test.go +++ /dev/null @@ -1,225 +0,0 @@ -package flatmap - -import ( - "reflect" - "testing" - - "github.com/hashicorp/terraform/configs/hcl2shim" -) - -func TestExpand(t *testing.T) { - cases := []struct { - Map map[string]string - Key string - Output interface{} - }{ - { - Map: map[string]string{ - "foo": "bar", - "bar": "baz", - }, - Key: "foo", - Output: "bar", - }, - - { - Map: map[string]string{ - "foo.#": "2", - "foo.0": "one", - "foo.1": "two", - }, - Key: "foo", - Output: []interface{}{ - "one", - "two", - }, - }, - - { - Map: map[string]string{ - // # mismatches actual number of keys; actual number should - // "win" here, since the # is just a hint that this is a list. - "foo.#": "1", - "foo.0": "one", - "foo.1": "two", - "foo.2": "three", - }, - Key: "foo", - Output: []interface{}{ - "one", - "two", - "three", - }, - }, - - { - Map: map[string]string{ - // # mismatches actual number of keys; actual number should - // "win" here, since the # is just a hint that this is a list. - "foo.#": "5", - "foo.0": "one", - "foo.1": "two", - "foo.2": "three", - }, - Key: "foo", - Output: []interface{}{ - "one", - "two", - "three", - }, - }, - - { - Map: map[string]string{ - "foo.#": "1", - "foo.0.name": "bar", - "foo.0.port": "3000", - "foo.0.enabled": "true", - }, - Key: "foo", - Output: []interface{}{ - map[string]interface{}{ - "name": "bar", - "port": "3000", - "enabled": true, - }, - }, - }, - - { - Map: map[string]string{ - "foo.#": "1", - "foo.0.name": "bar", - "foo.0.ports.#": "2", - "foo.0.ports.0": "1", - "foo.0.ports.1": "2", - }, - Key: "foo", - Output: []interface{}{ - map[string]interface{}{ - "name": "bar", - "ports": []interface{}{ - "1", - "2", - }, - }, - }, - }, - - { - Map: map[string]string{ - "list_of_map.#": "2", - "list_of_map.0.%": "1", - "list_of_map.0.a": "1", - "list_of_map.1.%": "2", - "list_of_map.1.b": "2", - "list_of_map.1.c": "3", - }, - Key: "list_of_map", - Output: []interface{}{ - map[string]interface{}{ - "a": "1", - }, - map[string]interface{}{ - "b": "2", - "c": "3", - }, - }, - }, - - { - Map: map[string]string{ - "map_of_list.%": "2", - "map_of_list.list2.#": "1", - "map_of_list.list2.0": "c", - "map_of_list.list1.#": "2", - "map_of_list.list1.0": "a", - "map_of_list.list1.1": "b", - }, - Key: "map_of_list", - Output: map[string]interface{}{ - "list1": []interface{}{"a", "b"}, - "list2": []interface{}{"c"}, - }, - }, - - { - Map: map[string]string{ - "set.#": "3", - "set.1234": "a", - "set.1235": "b", - "set.1236": "c", - }, - Key: "set", - Output: []interface{}{"a", "b", "c"}, - }, - - { - Map: map[string]string{ - "computed_set.#": "1", - "computed_set.~1234.a": "a", - "computed_set.~1234.b": "b", - "computed_set.~1234.c": "c", - }, - Key: "computed_set", - Output: []interface{}{ - map[string]interface{}{"a": "a", "b": "b", "c": "c"}, - }, - }, - - { - Map: map[string]string{ - "struct.#": "1", - "struct.0.name": "hello", - "struct.0.rules.#": hcl2shim.UnknownVariableValue, - }, - Key: "struct", - Output: []interface{}{ - map[string]interface{}{ - "name": "hello", - "rules": hcl2shim.UnknownVariableValue, - }, - }, - }, - - { - Map: map[string]string{ - "struct.#": "1", - "struct.0.name": "hello", - "struct.0.set.#": "0", - "struct.0.set.0.key": "value", - }, - Key: "struct", - Output: []interface{}{ - map[string]interface{}{ - "name": "hello", - "set": []interface{}{}, - }, - }, - }, - - { - Map: map[string]string{ - "empty_map_of_sets.%": "0", - "empty_map_of_sets.set1.#": "0", - "empty_map_of_sets.set1.1234": "x", - }, - Key: "empty_map_of_sets", - Output: map[string]interface{}{}, - }, - } - - for _, tc := range cases { - t.Run(tc.Key, func(t *testing.T) { - actual := Expand(tc.Map, tc.Key) - if !reflect.DeepEqual(actual, tc.Output) { - t.Errorf( - "Key: %v\nMap:\n\n%#v\n\nOutput:\n\n%#v\n\nExpected:\n\n%#v\n", - tc.Key, - tc.Map, - actual, - tc.Output) - } - }) - } -} diff --git a/flatmap/flatten.go b/flatmap/flatten.go deleted file mode 100644 index 9ff6e4265..000000000 --- a/flatmap/flatten.go +++ /dev/null @@ -1,71 +0,0 @@ -package flatmap - -import ( - "fmt" - "reflect" -) - -// Flatten takes a structure and turns into a flat map[string]string. -// -// Within the "thing" parameter, only primitive values are allowed. Structs are -// not supported. Therefore, it can only be slices, maps, primitives, and -// any combination of those together. -// -// See the tests for examples of what inputs are turned into. -func Flatten(thing map[string]interface{}) Map { - result := make(map[string]string) - - for k, raw := range thing { - flatten(result, k, reflect.ValueOf(raw)) - } - - return Map(result) -} - -func flatten(result map[string]string, prefix string, v reflect.Value) { - if v.Kind() == reflect.Interface { - v = v.Elem() - } - - switch v.Kind() { - case reflect.Bool: - if v.Bool() { - result[prefix] = "true" - } else { - result[prefix] = "false" - } - case reflect.Int: - result[prefix] = fmt.Sprintf("%d", v.Int()) - case reflect.Map: - flattenMap(result, prefix, v) - case reflect.Slice: - flattenSlice(result, prefix, v) - case reflect.String: - result[prefix] = v.String() - default: - panic(fmt.Sprintf("Unknown: %s", v)) - } -} - -func flattenMap(result map[string]string, prefix string, v reflect.Value) { - for _, k := range v.MapKeys() { - if k.Kind() == reflect.Interface { - k = k.Elem() - } - - if k.Kind() != reflect.String { - panic(fmt.Sprintf("%s: map key is not string: %s", prefix, k)) - } - - flatten(result, fmt.Sprintf("%s.%s", prefix, k.String()), v.MapIndex(k)) - } -} - -func flattenSlice(result map[string]string, prefix string, v reflect.Value) { - prefix = prefix + "." - - result[prefix+"#"] = fmt.Sprintf("%d", v.Len()) - for i := 0; i < v.Len(); i++ { - flatten(result, fmt.Sprintf("%s%d", prefix, i), v.Index(i)) - } -} diff --git a/flatmap/flatten_test.go b/flatmap/flatten_test.go deleted file mode 100644 index 1aa4940f8..000000000 --- a/flatmap/flatten_test.go +++ /dev/null @@ -1,88 +0,0 @@ -package flatmap - -import ( - "reflect" - "testing" -) - -func TestFlatten(t *testing.T) { - cases := []struct { - Input map[string]interface{} - Output map[string]string - }{ - { - Input: map[string]interface{}{ - "foo": "bar", - "bar": "baz", - }, - Output: map[string]string{ - "foo": "bar", - "bar": "baz", - }, - }, - - { - Input: map[string]interface{}{ - "foo": []string{ - "one", - "two", - }, - }, - Output: map[string]string{ - "foo.#": "2", - "foo.0": "one", - "foo.1": "two", - }, - }, - - { - Input: map[string]interface{}{ - "foo": []map[interface{}]interface{}{ - map[interface{}]interface{}{ - "name": "bar", - "port": 3000, - "enabled": true, - }, - }, - }, - Output: map[string]string{ - "foo.#": "1", - "foo.0.name": "bar", - "foo.0.port": "3000", - "foo.0.enabled": "true", - }, - }, - - { - Input: map[string]interface{}{ - "foo": []map[interface{}]interface{}{ - map[interface{}]interface{}{ - "name": "bar", - "ports": []string{ - "1", - "2", - }, - }, - }, - }, - Output: map[string]string{ - "foo.#": "1", - "foo.0.name": "bar", - "foo.0.ports.#": "2", - "foo.0.ports.0": "1", - "foo.0.ports.1": "2", - }, - }, - } - - for _, tc := range cases { - actual := Flatten(tc.Input) - if !reflect.DeepEqual(actual, Map(tc.Output)) { - t.Fatalf( - "Input:\n\n%#v\n\nOutput:\n\n%#v\n\nExpected:\n\n%#v\n", - tc.Input, - actual, - tc.Output) - } - } -} diff --git a/flatmap/map.go b/flatmap/map.go deleted file mode 100644 index 46b72c401..000000000 --- a/flatmap/map.go +++ /dev/null @@ -1,82 +0,0 @@ -package flatmap - -import ( - "strings" -) - -// Map is a wrapper around map[string]string that provides some helpers -// above it that assume the map is in the format that flatmap expects -// (the result of Flatten). -// -// All modifying functions such as Delete are done in-place unless -// otherwise noted. -type Map map[string]string - -// Contains returns true if the map contains the given key. -func (m Map) Contains(key string) bool { - for _, k := range m.Keys() { - if k == key { - return true - } - } - - return false -} - -// Delete deletes a key out of the map with the given prefix. -func (m Map) Delete(prefix string) { - for k, _ := range m { - match := k == prefix - if !match { - if !strings.HasPrefix(k, prefix) { - continue - } - - if k[len(prefix):len(prefix)+1] != "." { - continue - } - } - - delete(m, k) - } -} - -// Keys returns all of the top-level keys in this map -func (m Map) Keys() []string { - ks := make(map[string]struct{}) - for k, _ := range m { - idx := strings.Index(k, ".") - if idx == -1 { - idx = len(k) - } - - ks[k[:idx]] = struct{}{} - } - - result := make([]string, 0, len(ks)) - for k, _ := range ks { - result = append(result, k) - } - - return result -} - -// Merge merges the contents of the other Map into this one. -// -// This merge is smarter than a simple map iteration because it -// will fully replace arrays and other complex structures that -// are present in this map with the other map's. For example, if -// this map has a 3 element "foo" list, and m2 has a 2 element "foo" -// list, then the result will be that m has a 2 element "foo" -// list. -func (m Map) Merge(m2 Map) { - for _, prefix := range m2.Keys() { - m.Delete(prefix) - - for k, v := range m2 { - if strings.HasPrefix(k, prefix) { - m[k] = v - } - } - } -} diff --git a/flatmap/map_test.go b/flatmap/map_test.go deleted file mode 100644 index e3b4cb1bd..000000000 --- a/flatmap/map_test.go +++ /dev/null @@ -1,120 +0,0 @@ -package flatmap - -import ( - "reflect" - "sort" - "testing" -) - -func TestMapContains(t *testing.T) { - cases := []struct { - Input map[string]string - Key string - Result bool - }{ - { - Input: map[string]string{ - "foo": "bar", - "bar": "nope", - }, - Key: "foo", - Result: true, - }, - - { - Input: map[string]string{ - "foo": "bar", - "bar": "nope", - }, - Key: "baz", - Result: false, - }, - } - - for i, tc := range cases { - actual := Map(tc.Input).Contains(tc.Key) - if actual != tc.Result { - t.Fatalf("case %d bad: %#v", i, tc.Input) - } - } -} - -func TestMapDelete(t *testing.T) { - m := Flatten(map[string]interface{}{ - "foo": "bar", - "routes": []map[string]string{ - map[string]string{ - "foo": "bar", - }, - }, - }) - - m.Delete("routes") - - expected := Map(map[string]string{"foo": "bar"}) - if !reflect.DeepEqual(m, expected) { - t.Fatalf("bad: %#v", m) - } -} - -func TestMapKeys(t *testing.T) { - cases := []struct { - Input map[string]string - Output []string - }{ - { - Input: map[string]string{ - "foo": "bar", - "bar.#": "bar", - "bar.0.foo": "bar", - "bar.0.baz": "bar", - }, - Output: []string{ - "bar", - "foo", - }, - }, - } - - for _, tc := range cases { - actual := Map(tc.Input).Keys() - - // Sort so we have a consistent view of the output - sort.Strings(actual) - - if !reflect.DeepEqual(actual, tc.Output) { - t.Fatalf("input: %#v\n\nbad: %#v", tc.Input, actual) - } - } -} - -func TestMapMerge(t *testing.T) { - cases := []struct { - One map[string]string - Two map[string]string - Result map[string]string - }{ - { - One: map[string]string{ - "foo": "bar", - "bar": "nope", - }, - Two: map[string]string{ - "bar": "baz", - "baz": "buz", - }, - Result: map[string]string{ - "foo": "bar", - "bar": "baz", - "baz": "buz", - }, - }, - } - - for i, tc := range cases { - Map(tc.One).Merge(Map(tc.Two)) - if !reflect.DeepEqual(tc.One, tc.Result) { - t.Fatalf("case %d bad: %#v", i, tc.One) - } - } -}