Skip to content

Commit 2157bda

Browse files
committed
Remove old flattening code.
Signed-off-by: Felix Fontein <felix@fontein.de>
1 parent ddd46bb commit 2157bda

2 files changed

Lines changed: 0 additions & 352 deletions

File tree

stores/flatten.go

Lines changed: 0 additions & 189 deletions
Original file line numberDiff line numberDiff line change
@@ -7,89 +7,12 @@ import (
77
"strconv"
88
"strings"
99

10-
"github.com/go-viper/mapstructure/v2"
11-
1210
"github.com/getsops/sops/v3"
1311
)
1412

1513
const mapSeparator = "__map_"
1614
const listSeparator = "__list_"
1715

18-
// flattenAndMerge flattens the provided value and merges into the
19-
// into map using prefix
20-
func flattenAndMerge(into map[string]interface{}, prefix string, value interface{}) {
21-
flattenedValue := flattenValue(value)
22-
if flattenedValue, ok := flattenedValue.(map[string]interface{}); ok {
23-
for flatK, flatV := range flattenedValue {
24-
into[prefix+flatK] = flatV
25-
}
26-
} else {
27-
into[prefix] = value
28-
}
29-
}
30-
31-
func flattenValue(value interface{}) interface{} {
32-
var output interface{}
33-
switch value := value.(type) {
34-
case map[string]interface{}:
35-
newMap := make(map[string]interface{})
36-
for k, v := range value {
37-
flattenAndMerge(newMap, mapSeparator+k, v)
38-
}
39-
output = newMap
40-
case []interface{}:
41-
newMap := make(map[string]interface{})
42-
for i, v := range value {
43-
flattenAndMerge(newMap, listSeparator+fmt.Sprintf("%d", i), v)
44-
}
45-
output = newMap
46-
case []map[string]interface{}: // mapstructure also emits these
47-
newMap := make(map[string]interface{})
48-
for i, v := range value {
49-
flattenAndMerge(newMap, listSeparator+fmt.Sprintf("%d", i), v)
50-
}
51-
output = newMap
52-
default:
53-
output = value
54-
}
55-
return output
56-
}
57-
58-
// Flatten flattens a map with potentially nested maps into a flat
59-
// map. Only string keys are allowed on both the top-level map and
60-
// child maps.
61-
func Flatten(in map[string]interface{}) map[string]interface{} {
62-
newMap := make(map[string]interface{})
63-
for k, v := range in {
64-
if flat, ok := flattenValue(v).(map[string]interface{}); ok {
65-
for flatK, flatV := range flat {
66-
newMap[k+flatK] = flatV
67-
}
68-
} else {
69-
newMap[k] = v
70-
}
71-
}
72-
return newMap
73-
}
74-
75-
// FlattenMetadata flattens a Metadata struct into a flat map.
76-
func FlattenMetadata(md Metadata) (map[string]interface{}, error) {
77-
var mdMap map[string]interface{}
78-
config := mapstructure.DecoderConfig{
79-
Result: &mdMap,
80-
}
81-
d, err := mapstructure.NewDecoder(&config)
82-
if err != nil {
83-
return nil, err
84-
}
85-
err = d.Decode(md)
86-
if err != nil {
87-
return nil, err
88-
}
89-
flat := Flatten(mdMap)
90-
return flat, nil
91-
}
92-
9316
type token interface{}
9417

9518
type mapToken struct {
@@ -143,95 +66,6 @@ func tokenize(path string) []token {
14366
return tokens
14467
}
14568

146-
// unflatten takes the currentNode, currentToken, nextToken and value
147-
// and populates currentNode such that currentToken can be considered
148-
// processed. It inspects nextToken to decide what type to allocate
149-
// and assign under currentNode.
150-
func unflatten(currentNode interface{}, currentToken, nextToken token, value interface{}) interface{} {
151-
switch currentToken := currentToken.(type) {
152-
case mapToken:
153-
currentNode := currentNode.(map[string]interface{})
154-
switch nextToken := nextToken.(type) {
155-
case mapToken:
156-
if _, ok := currentNode[currentToken.key]; !ok {
157-
currentNode[currentToken.key] = make(map[string]interface{})
158-
}
159-
next := currentNode[currentToken.key].(map[string]interface{})
160-
return next
161-
case listToken:
162-
if _, ok := currentNode[currentToken.key]; !ok {
163-
currentNode[currentToken.key] = make([]interface{}, nextToken.position+1)
164-
}
165-
next := currentNode[currentToken.key].([]interface{})
166-
if nextToken.position >= len(next) {
167-
// Grow the slice and reassign it
168-
newNext := make([]interface{}, nextToken.position+1)
169-
copy(newNext, next)
170-
next = newNext
171-
currentNode[currentToken.key] = next
172-
}
173-
return next
174-
default:
175-
currentNode[currentToken.key] = value
176-
}
177-
case listToken:
178-
currentNode := currentNode.([]interface{})
179-
switch nextToken := nextToken.(type) {
180-
case mapToken:
181-
if currentNode[currentToken.position] == nil {
182-
currentNode[currentToken.position] = make(map[string]interface{})
183-
}
184-
next := currentNode[currentToken.position].(map[string]interface{})
185-
return next
186-
case listToken:
187-
if currentNode[currentToken.position] == nil {
188-
currentNode[currentToken.position] = make([]interface{}, nextToken.position+1)
189-
}
190-
next := currentNode[currentToken.position].([]interface{})
191-
if nextToken.position >= len(next) {
192-
// Grow the slice and reassign it
193-
newNext := make([]interface{}, nextToken.position+1)
194-
copy(newNext, next)
195-
next = newNext
196-
currentNode[currentToken.position] = next
197-
}
198-
return next
199-
default:
200-
currentNode[currentToken.position] = value
201-
}
202-
}
203-
return nil
204-
}
205-
206-
// Unflatten unflattens a map flattened by Flatten
207-
func Unflatten(in map[string]interface{}) map[string]interface{} {
208-
newMap := make(map[string]interface{})
209-
for k, v := range in {
210-
var current interface{} = newMap
211-
tokens := append(tokenize(k), nil)
212-
for i := 0; i < len(tokens)-1; i++ {
213-
current = unflatten(current, tokens[i], tokens[i+1], v)
214-
}
215-
}
216-
return newMap
217-
}
218-
219-
// UnflattenMetadata unflattens a map flattened by FlattenMetadata into Metadata
220-
func UnflattenMetadata(in map[string]interface{}) (Metadata, error) {
221-
m := Unflatten(in)
222-
var md Metadata
223-
config := mapstructure.DecoderConfig{
224-
Result: &md,
225-
WeaklyTypedInput: true,
226-
}
227-
d, err := mapstructure.NewDecoder(&config)
228-
if err != nil {
229-
return md, err
230-
}
231-
err = d.Decode(m)
232-
return md, err
233-
}
234-
23569
// DecodeNewLines replaces \\n with \n for all string values in the map.
23670
// Used by config stores that do not handle multi-line values (ini, dotenv).
23771
func DecodeNewLines(m map[string]interface{}) {
@@ -252,29 +86,6 @@ func EncodeNewLines(m map[string]interface{}) {
25286
}
25387
}
25488

255-
// EncodeNonStrings will look for known metadata keys that are not strings and will encode it to strings
256-
func EncodeNonStrings(m map[string]interface{}) {
257-
if v, found := m["mac_only_encrypted"]; found {
258-
if vBool, ok := v.(bool); ok {
259-
m["mac_only_encrypted"] = "false"
260-
if vBool {
261-
m["mac_only_encrypted"] = "true"
262-
}
263-
}
264-
}
265-
if v, found := m["shamir_threshold"]; found {
266-
if vInt, ok := v.(int); ok {
267-
m["shamir_threshold"] = fmt.Sprintf("%d", vInt)
268-
}
269-
// FlattenMetadata serializes the input as JSON and then deserializes it.
270-
// The JSON unserializer treats every number as a float, so the above 'if'
271-
// never applies in that situation.
272-
if vFloat, ok := v.(float64); ok {
273-
m["shamir_threshold"] = fmt.Sprintf("%.0f", vFloat)
274-
}
275-
}
276-
}
277-
27889
func descendMap(branch sops.TreeBranch, key string) (sops.TreeBranch, reflect.Value) {
27990
for idx, elt := range branch {
28091
if elt.Key == key {

stores/flatten_test.go

Lines changed: 0 additions & 163 deletions
Original file line numberDiff line numberDiff line change
@@ -7,112 +7,6 @@ import (
77
"github.com/stretchr/testify/assert"
88
)
99

10-
func TestFlat(t *testing.T) {
11-
input := map[string]interface{}{
12-
"foo": "bar",
13-
}
14-
expected := map[string]interface{}{
15-
"foo": "bar",
16-
}
17-
flattened := Flatten(input)
18-
assert.Equal(t, expected, flattened)
19-
unflattened := Unflatten(flattened)
20-
assert.Equal(t, input, unflattened)
21-
}
22-
23-
func TestMap(t *testing.T) {
24-
input := map[string]interface{}{
25-
"foo": map[string]interface{}{
26-
"bar": 0,
27-
"baz": 0,
28-
},
29-
}
30-
expected := map[string]interface{}{
31-
"foo" + mapSeparator + "bar": 0,
32-
"foo" + mapSeparator + "baz": 0,
33-
}
34-
flattened := Flatten(input)
35-
assert.Equal(t, expected, flattened)
36-
unflattened := Unflatten(flattened)
37-
assert.Equal(t, input, unflattened)
38-
}
39-
40-
func TestFlattenMapMoreNesting(t *testing.T) {
41-
input := map[string]interface{}{
42-
"foo": map[string]interface{}{
43-
"bar": map[string]interface{}{
44-
"baz": 0,
45-
},
46-
},
47-
}
48-
expected := map[string]interface{}{
49-
"foo" + mapSeparator + "bar" + mapSeparator + "baz": 0,
50-
}
51-
flattened := Flatten(input)
52-
assert.Equal(t, expected, flattened)
53-
unflattened := Unflatten(flattened)
54-
assert.Equal(t, input, unflattened)
55-
}
56-
57-
func TestFlattenList(t *testing.T) {
58-
input := map[string]interface{}{
59-
"foo": []interface{}{
60-
0,
61-
},
62-
}
63-
expected := map[string]interface{}{
64-
"foo" + listSeparator + "0": 0,
65-
}
66-
flattened := Flatten(input)
67-
assert.Equal(t, expected, flattened)
68-
unflattened := Unflatten(flattened)
69-
assert.Equal(t, input, unflattened)
70-
}
71-
72-
func TestFlattenListWithMap(t *testing.T) {
73-
input := map[string]interface{}{
74-
"foo": []interface{}{
75-
map[string]interface{}{
76-
"bar": 0,
77-
},
78-
},
79-
}
80-
expected := map[string]interface{}{
81-
"foo" + listSeparator + "0" + mapSeparator + "bar": 0,
82-
}
83-
flattened := Flatten(input)
84-
assert.Equal(t, expected, flattened)
85-
unflattened := Unflatten(flattened)
86-
assert.Equal(t, input, unflattened)
87-
}
88-
89-
func TestFlatten(t *testing.T) {
90-
input := map[string]interface{}{
91-
"foo": "bar",
92-
"baz": map[string]interface{}{
93-
"foo": 2,
94-
"bar": map[string]interface{}{
95-
"foo": 2,
96-
},
97-
},
98-
"qux": []interface{}{
99-
"hello", 1, 2,
100-
},
101-
}
102-
expected := map[string]interface{}{
103-
"foo": "bar",
104-
"baz" + mapSeparator + "foo": 2,
105-
"baz" + mapSeparator + "bar" + mapSeparator + "foo": 2,
106-
"qux" + listSeparator + "0": "hello",
107-
"qux" + listSeparator + "1": 1,
108-
"qux" + listSeparator + "2": 2,
109-
}
110-
flattened := Flatten(input)
111-
assert.Equal(t, expected, flattened)
112-
unflattened := Unflatten(flattened)
113-
assert.Equal(t, input, unflattened)
114-
}
115-
11610
func TestTokenizeFlat(t *testing.T) {
11711
input := "bar"
11812
expected := []token{mapToken{"bar"}}
@@ -141,46 +35,6 @@ func TestTokenizeNested(t *testing.T) {
14135
assert.Equal(t, expected, tokenized)
14236
}
14337

144-
func TestFlattenMetadata(t *testing.T) {
145-
tests := []struct {
146-
input Metadata
147-
want map[string]interface{}
148-
}{
149-
{Metadata{MACOnlyEncrypted: false}, map[string]interface{}{"mac_only_encrypted": nil}},
150-
{Metadata{MACOnlyEncrypted: true}, map[string]interface{}{"mac_only_encrypted": true}},
151-
{Metadata{MessageAuthenticationCode: "line1\nline2"}, map[string]interface{}{"mac": "line1\nline2"}},
152-
{Metadata{MessageAuthenticationCode: "line1\n\n\nline2\n\nline3"}, map[string]interface{}{"mac": "line1\n\n\nline2\n\nline3"}},
153-
}
154-
155-
for _, tt := range tests {
156-
got, err := FlattenMetadata(tt.input)
157-
assert.NoError(t, err)
158-
for k, v := range tt.want {
159-
assert.Equal(t, v, got[k])
160-
}
161-
}
162-
}
163-
164-
func TestFlattenMetadataToUnflattenMetadata(t *testing.T) {
165-
tests := []struct {
166-
input Metadata
167-
}{
168-
{Metadata{MACOnlyEncrypted: true}},
169-
{Metadata{MACOnlyEncrypted: false}},
170-
{Metadata{ShamirThreshold: 3}},
171-
{Metadata{MessageAuthenticationCode: "line1\nline2"}},
172-
{Metadata{MessageAuthenticationCode: "line1\n\n\nline2\n\nline3"}},
173-
}
174-
175-
for _, tt := range tests {
176-
flat, err := FlattenMetadata(tt.input)
177-
assert.NoError(t, err)
178-
md, err := UnflattenMetadata(flat)
179-
assert.NoError(t, err)
180-
assert.Equal(t, tt.input, md)
181-
}
182-
}
183-
18438
func TestDecodeNewLines(t *testing.T) {
18539
tests := []struct {
18640
input map[string]interface{}
@@ -215,23 +69,6 @@ func TestEncodeNewLines(t *testing.T) {
21569
}
21670
}
21771

218-
func TestEncodeNonStrings(t *testing.T) {
219-
tests := []struct {
220-
input map[string]interface{}
221-
want map[string]interface{}
222-
}{
223-
{map[string]interface{}{"mac_only_encrypted": false}, map[string]interface{}{"mac_only_encrypted": "false"}},
224-
{map[string]interface{}{"mac_only_encrypted": true}, map[string]interface{}{"mac_only_encrypted": "true"}},
225-
{map[string]interface{}{"shamir_threshold": 2}, map[string]interface{}{"shamir_threshold": "2"}},
226-
{map[string]interface{}{"shamir_threshold": 123}, map[string]interface{}{"shamir_threshold": "123"}},
227-
}
228-
229-
for _, tt := range tests {
230-
EncodeNonStrings(tt.input)
231-
assert.Equal(t, tt.want, tt.input)
232-
}
233-
}
234-
23572
func TestUnflattenTreeBranch(t *testing.T) {
23673
var (
23774
input = sops.TreeBranch{

0 commit comments

Comments
 (0)