forked from hashicorp/terraform-provider-aws
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request hashicorp#10244 from terraform-providers/td-move-f…
…latmap resource/aws_cloudfront_distribution: Migrate flatmap package internally for now, add test covering existing active_trusted_signers behavior
- Loading branch information
Showing
7 changed files
with
441 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
# flatmap | ||
|
||
This package contains legacy code from `github.com/hashicorp/terraform/flatmap@v0.12.9`. The types and functions within this package should not be used in any future implementations. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
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)) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
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{}{ | ||
{ | ||
"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{}{ | ||
{ | ||
"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) | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
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 | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,120 @@ | ||
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{ | ||
{ | ||
"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) | ||
} | ||
} | ||
} |
Oops, something went wrong.