Skip to content

Commit a4e00e9

Browse files
authored
Merge pull request #184 from apelisse/fix-remove-structures
Fix remove structures
2 parents 9f9c770 + e71bab7 commit a4e00e9

File tree

7 files changed

+368
-7
lines changed

7 files changed

+368
-7
lines changed

fieldpath/set.go

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ package fieldpath
1919
import (
2020
"sort"
2121
"strings"
22+
23+
"sigs.k8s.io/structured-merge-diff/v4/schema"
2224
)
2325

2426
// Set identifies a set of fields.
@@ -110,6 +112,30 @@ func (s *Set) RecursiveDifference(s2 *Set) *Set {
110112
}
111113
}
112114

115+
// EnsureNamedFieldsAreMembers returns a Set that contains all the
116+
// fields in s, as well as all the named fields that are typically not
117+
// included. For example, a set made of "a.b.c" will end-up also owning
118+
// "a" if it's a named fields but not "a.b" if it's a map.
119+
func (s *Set) EnsureNamedFieldsAreMembers(sc *schema.Schema, tr schema.TypeRef) *Set {
120+
members := PathElementSet{
121+
members: make(sortedPathElements, 0, s.Members.Size()+len(s.Children.members)),
122+
}
123+
atom, _ := sc.Resolve(tr)
124+
members.members = append(members.members, s.Members.members...)
125+
for _, node := range s.Children.members {
126+
// Only insert named fields.
127+
if node.pathElement.FieldName != nil && atom.Map != nil {
128+
if _, has := atom.Map.FindField(*node.pathElement.FieldName); has {
129+
members.Insert(node.pathElement)
130+
}
131+
}
132+
}
133+
return &Set{
134+
Members: members,
135+
Children: *s.Children.EnsureNamedFieldsAreMembers(sc, tr),
136+
}
137+
}
138+
113139
// Size returns the number of members of the set.
114140
func (s *Set) Size() int {
115141
return s.Members.Size() + s.Children.Size()
@@ -391,6 +417,31 @@ func (s *SetNodeMap) RecursiveDifference(s2 *Set) *SetNodeMap {
391417
return out
392418
}
393419

420+
// EnsureNamedFieldsAreMembers returns a set that contains all the named fields along with the leaves.
421+
func (s *SetNodeMap) EnsureNamedFieldsAreMembers(sc *schema.Schema, tr schema.TypeRef) *SetNodeMap {
422+
out := make(sortedSetNode, 0, s.Size())
423+
atom, _ := sc.Resolve(tr)
424+
for _, member := range s.members {
425+
tr := schema.TypeRef{}
426+
if member.pathElement.FieldName != nil && atom.Map != nil {
427+
tr = atom.Map.ElementType
428+
if sf, ok := atom.Map.FindField(*member.pathElement.FieldName); ok {
429+
tr = sf.Type
430+
}
431+
} else if member.pathElement.Key != nil && atom.List != nil {
432+
tr = atom.List.ElementType
433+
}
434+
out = append(out, setNode{
435+
pathElement: member.pathElement,
436+
set: member.set.EnsureNamedFieldsAreMembers(sc, tr),
437+
})
438+
}
439+
440+
return &SetNodeMap{
441+
members: out,
442+
}
443+
}
444+
394445
// Iterate calls f for each PathElement in the set.
395446
func (s *SetNodeMap) Iterate(f func(PathElement)) {
396447
for _, n := range s.members {

fieldpath/set_test.go

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@ import (
2121
"fmt"
2222
"math/rand"
2323
"testing"
24+
25+
"gopkg.in/yaml.v2"
26+
"sigs.k8s.io/structured-merge-diff/v4/schema"
2427
)
2528

2629
type randomPathAlphabet []PathElement
@@ -541,6 +544,86 @@ func TestSetDifference(t *testing.T) {
541544
}
542545
}
543546

547+
var nestedSchema = func() (*schema.Schema, schema.TypeRef) {
548+
sc := &schema.Schema{}
549+
name := "type"
550+
err := yaml.Unmarshal([]byte(`types:
551+
- name: type
552+
map:
553+
elementType:
554+
namedType: type
555+
fields:
556+
- name: named
557+
type:
558+
namedType: type
559+
- name: list
560+
type:
561+
list:
562+
elementRelationShip: associative
563+
keys: ["name"]
564+
elementType:
565+
namedType: type
566+
- name: value
567+
type:
568+
scalar: numeric
569+
`), &sc)
570+
if err != nil {
571+
panic(err)
572+
}
573+
return sc, schema.TypeRef{NamedType: &name}
574+
}
575+
576+
var _P = MakePathOrDie
577+
578+
func TestEnsureNamedFieldsAreMembers(t *testing.T) {
579+
table := []struct {
580+
set, expected *Set
581+
}{
582+
{
583+
set: NewSet(_P("named", "named", "value")),
584+
expected: NewSet(
585+
_P("named", "named", "value"),
586+
_P("named", "named"),
587+
_P("named"),
588+
),
589+
},
590+
{
591+
set: NewSet(_P("named", "a", "named", "value"), _P("a", "named", "value"), _P("a", "b", "value")),
592+
expected: NewSet(
593+
_P("named", "a", "named", "value"),
594+
_P("named", "a", "named"),
595+
_P("named"),
596+
_P("a", "named", "value"),
597+
_P("a", "named"),
598+
_P("a", "b", "value"),
599+
),
600+
},
601+
{
602+
set: NewSet(_P("named", "list", KeyByFields("name", "a"), "named", "a", "value")),
603+
expected: NewSet(
604+
_P("named", "list", KeyByFields("name", "a"), "named", "a", "value"),
605+
_P("named", "list", KeyByFields("name", "a"), "named"),
606+
_P("named", "list"),
607+
_P("named"),
608+
),
609+
},
610+
}
611+
612+
for _, test := range table {
613+
t.Run(fmt.Sprintf("%v", test.set), func(t *testing.T) {
614+
got := test.set.EnsureNamedFieldsAreMembers(nestedSchema())
615+
if !got.Equals(test.expected) {
616+
t.Errorf("expected %v, got %v (missing: %v/superfluous: %v)",
617+
test.expected,
618+
got,
619+
test.expected.Difference(got),
620+
got.Difference(test.expected),
621+
)
622+
}
623+
})
624+
}
625+
}
626+
544627
func TestSetNodeMapIterate(t *testing.T) {
545628
set := &SetNodeMap{}
546629
toAdd := 5

merge/ignore_test.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,13 @@ func TestIgnoredFieldsUsesVersions(t *testing.T) {
190190
`,
191191
APIVersion: "v4",
192192
Managed: fieldpath.ManagedFields{
193+
"apply-one": fieldpath.NewVersionedSet(
194+
_NS(
195+
_P("mapOfMapsRecursive"),
196+
),
197+
"v4",
198+
false,
199+
),
193200
"apply-two": fieldpath.NewVersionedSet(
194201
_NS(
195202
_P("mapOfMapsRecursive", "aa"),

merge/multiple_appliers_test.go

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -554,11 +554,10 @@ func testMultipleAppliersFieldUnsetting(t *testing.T, v1, v2, v3 fieldpath.APIVe
554554
`,
555555
},
556556
},
557-
Object: typed.YAMLObject(fmt.Sprintf(`
557+
Object: typed.YAMLObject(`
558558
struct:
559559
name: a
560-
complexField_%s: null
561-
`, v3)),
560+
`),
562561
APIVersion: v3,
563562
Managed: fieldpath.ManagedFields{
564563
"apply-one": fieldpath.NewVersionedSet(
@@ -1072,6 +1071,13 @@ func TestMultipleAppliersNestedType(t *testing.T) {
10721071
`,
10731072
APIVersion: "v1",
10741073
Managed: fieldpath.ManagedFields{
1074+
"apply-one": fieldpath.NewVersionedSet(
1075+
_NS(
1076+
_P("mapOfMapsRecursive"),
1077+
),
1078+
"v4",
1079+
false,
1080+
),
10751081
"apply-two": fieldpath.NewVersionedSet(
10761082
_NS(
10771083
_P("mapOfMapsRecursive", "a"),
@@ -1285,6 +1291,13 @@ func TestMultipleAppliersRealConversion(t *testing.T) {
12851291
`,
12861292
APIVersion: "v4",
12871293
Managed: fieldpath.ManagedFields{
1294+
"apply-one": fieldpath.NewVersionedSet(
1295+
_NS(
1296+
_P("mapOfMapsRecursive"),
1297+
),
1298+
"v4",
1299+
false,
1300+
),
12881301
"apply-two": fieldpath.NewVersionedSet(
12891302
_NS(
12901303
_P("mapOfMapsRecursive", "aa"),

0 commit comments

Comments
 (0)