Skip to content

Commit 819bbdb

Browse files
author
Kevin Wiesmüller
committed
add extended remove method for typed values
1 parent cf335e0 commit 819bbdb

File tree

3 files changed

+158
-4
lines changed

3 files changed

+158
-4
lines changed

typed/remove.go

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,15 @@ type removingWalker struct {
2424
out interface{}
2525
schema *schema.Schema
2626
toRemove *fieldpath.Set
27+
shallow bool
2728
}
2829

29-
func removeItemsWithSchema(val value.Value, toRemove *fieldpath.Set, schema *schema.Schema, typeRef schema.TypeRef) value.Value {
30+
func removeItemsWithSchema(val value.Value, toRemove *fieldpath.Set, schema *schema.Schema, typeRef schema.TypeRef, shallow bool) value.Value {
3031
w := &removingWalker{
3132
value: val,
3233
schema: schema,
3334
toRemove: toRemove,
35+
shallow: shallow,
3436
}
3537
resolveSchema(schema, typeRef, val, w)
3638
return value.NewValueInterface(w.out)
@@ -59,7 +61,7 @@ func (w *removingWalker) doList(t *schema.List) (errs ValidationErrors) {
5961
continue
6062
}
6163
if subset := w.toRemove.WithPrefix(pe); !subset.Empty() {
62-
item = removeItemsWithSchema(item, subset, w.schema, t.ElementType)
64+
item = removeItemsWithSchema(item, subset, w.schema, t.ElementType, w.shallow)
6365
}
6466
newItems = append(newItems, item.Unstructured())
6567
}
@@ -86,6 +88,13 @@ func (w *removingWalker) doMap(t *schema.Map) ValidationErrors {
8688
m.Iterate(func(k string, val value.Value) bool {
8789
pe := fieldpath.PathElement{FieldName: &k}
8890
path, _ := fieldpath.MakePath(pe)
91+
92+
if w.shallow {
93+
if w.toRemove.Has(path) {
94+
return true
95+
}
96+
}
97+
8998
fieldType := t.ElementType
9099
if ft, ok := fieldTypes[k]; ok {
91100
fieldType = ft
@@ -95,7 +104,7 @@ func (w *removingWalker) doMap(t *schema.Map) ValidationErrors {
95104
}
96105
}
97106
if subset := w.toRemove.WithPrefix(pe); !subset.Empty() {
98-
val = removeItemsWithSchema(val, subset, w.schema, fieldType)
107+
val = removeItemsWithSchema(val, subset, w.schema, fieldType, w.shallow)
99108
}
100109
newMap[k] = val.Unstructured()
101110
return true

typed/remove_test.go

Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
package typed
2+
3+
import (
4+
"testing"
5+
6+
"sigs.k8s.io/structured-merge-diff/fieldpath"
7+
"sigs.k8s.io/structured-merge-diff/schema"
8+
"sigs.k8s.io/structured-merge-diff/value"
9+
)
10+
11+
func TestRemoveShallowRemovesParents(t *testing.T) {
12+
13+
test, err := value.FromJSON([]byte(`
14+
{
15+
"removeMap": {
16+
"child": "value"
17+
},
18+
"removeList": [
19+
{"child": "value"}
20+
],
21+
"keep": "value",
22+
"keepMap": {
23+
"child": "value"
24+
},
25+
"keepList": [
26+
{"child": "value"}
27+
]
28+
}`))
29+
if err != nil {
30+
t.Fatal(err)
31+
}
32+
33+
remove := fieldpath.NewSet(
34+
fieldpath.MakePathOrDie("removeMap"),
35+
fieldpath.MakePathOrDie("removeList"),
36+
)
37+
38+
str := schema.String
39+
40+
atom := schema.Atom{
41+
Map: &schema.Map{
42+
Fields: []schema.StructField{
43+
schema.StructField{
44+
Name: "removeMap",
45+
Type: schema.TypeRef{
46+
Inlined: schema.Atom{Map: &schema.Map{
47+
Fields: []schema.StructField{
48+
schema.StructField{Name: "child", Type: schema.TypeRef{Inlined: schema.Atom{Scalar: &str}}}}},
49+
},
50+
},
51+
},
52+
schema.StructField{
53+
Name: "removeList",
54+
Type: schema.TypeRef{
55+
Inlined: schema.Atom{
56+
List: &schema.List{
57+
ElementRelationship: schema.Separable,
58+
ElementType: schema.TypeRef{
59+
Inlined: schema.Atom{Map: &schema.Map{
60+
Fields: []schema.StructField{
61+
schema.StructField{Name: "child", Type: schema.TypeRef{Inlined: schema.Atom{Scalar: &str}}}}},
62+
},
63+
},
64+
},
65+
},
66+
},
67+
},
68+
schema.StructField{
69+
Name: "keep",
70+
Type: schema.TypeRef{
71+
Inlined: schema.Atom{
72+
Scalar: &str,
73+
},
74+
},
75+
},
76+
schema.StructField{
77+
Name: "keepMap",
78+
Type: schema.TypeRef{
79+
Inlined: schema.Atom{Map: &schema.Map{
80+
Fields: []schema.StructField{
81+
schema.StructField{Name: "child", Type: schema.TypeRef{Inlined: schema.Atom{Scalar: &str}}}}},
82+
},
83+
},
84+
},
85+
schema.StructField{
86+
Name: "keepList",
87+
Type: schema.TypeRef{
88+
Inlined: schema.Atom{
89+
List: &schema.List{
90+
ElementRelationship: schema.Separable,
91+
ElementType: schema.TypeRef{
92+
Inlined: schema.Atom{Map: &schema.Map{
93+
Fields: []schema.StructField{
94+
schema.StructField{Name: "child", Type: schema.TypeRef{Inlined: schema.Atom{Scalar: &str}}}}},
95+
},
96+
},
97+
},
98+
},
99+
},
100+
},
101+
},
102+
},
103+
}
104+
105+
typeDef := schema.TypeDef{
106+
Name: "test",
107+
Atom: atom,
108+
}
109+
110+
typeRef := schema.TypeRef{
111+
Inlined: atom,
112+
}
113+
114+
schema := &schema.Schema{
115+
Types: []schema.TypeDef{
116+
typeDef,
117+
},
118+
}
119+
120+
removeItemsWithSchema(&test, remove, schema, typeRef, false)
121+
122+
expect, err := value.FromJSON([]byte(`{"keep": "value", "keepMap": {"child": "value"}, "keepList": [{"child": "value"}], "removeMap": {"child":"value"}, "removeList": [{"child": "value"}]}`))
123+
if err != nil {
124+
t.Fatal(err)
125+
}
126+
if !test.Equals(expect) {
127+
t.Fatalf("unexpected result after remove:\ngot: %v\nexp: %v", test.String(), expect.String())
128+
}
129+
130+
removeItemsWithSchema(&test, remove, schema, typeRef, true)
131+
132+
expect, err = value.FromJSON([]byte(`{"keep": "value", "keepMap": {"child": "value"}, "keepList": [{"child": "value"}]}`))
133+
if err != nil {
134+
t.Fatal(err)
135+
}
136+
if !test.Equals(expect) {
137+
t.Fatalf("unexpected result after remove:\ngot: %v\nexp: %v", test.String(), expect.String())
138+
}
139+
}

typed/typed.go

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,13 @@ func (tv TypedValue) Compare(rhs *TypedValue) (c *Comparison, err error) {
140140

141141
// RemoveItems removes each provided list or map item from the value.
142142
func (tv TypedValue) RemoveItems(items *fieldpath.Set) *TypedValue {
143-
tv.value = removeItemsWithSchema(tv.value, items, tv.schema, tv.typeRef)
143+
tv.value = removeItemsWithSchema(tv.value, items, tv.schema, tv.typeRef, false)
144+
return &tv
145+
}
146+
147+
// Remove removes each provided path from the value.
148+
func (tv TypedValue) Remove(paths *fieldpath.Set) *TypedValue {
149+
tv.value = removeItemsWithSchema(tv.value, paths, tv.schema, tv.typeRef, false)
144150
return &tv
145151
}
146152

0 commit comments

Comments
 (0)