Skip to content

Commit 49364a2

Browse files
author
jennybuckley
committed
Implement prune
1 parent 5a99fcf commit 49364a2

File tree

1 file changed

+111
-22
lines changed

1 file changed

+111
-22
lines changed

merge/update.go

Lines changed: 111 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ func (s *Updater) update(oldObject, newObject typed.TypedValue, version fieldpat
3838
managers = fieldpath.ManagedFields{}
3939
}
4040
conflicts := fieldpath.ManagedFields{}
41+
removed := fieldpath.ManagedFields{}
4142
type Versioned struct {
4243
oldObject typed.TypedValue
4344
newObject typed.TypedValue
@@ -86,6 +87,13 @@ func (s *Updater) update(oldObject, newObject typed.TypedValue, version fieldpat
8687
APIVersion: managerSet.APIVersion,
8788
}
8889
}
90+
91+
if !compare.Removed.Empty() {
92+
removed[manager] = &fieldpath.VersionedSet{
93+
Set: compare.Removed,
94+
APIVersion: managerSet.APIVersion,
95+
}
96+
}
8997
}
9098

9199
if !force && len(conflicts) != 0 {
@@ -94,14 +102,15 @@ func (s *Updater) update(oldObject, newObject typed.TypedValue, version fieldpat
94102

95103
for manager, conflictSet := range conflicts {
96104
managers[manager].Set = managers[manager].Set.Difference(conflictSet.Set)
97-
if managers[manager].Set.Empty() {
98-
delete(managers, manager)
99-
}
100105
}
101106

102-
if _, ok := managers[workflow]; !ok {
103-
managers[workflow] = &fieldpath.VersionedSet{
104-
Set: fieldpath.NewSet(),
107+
for manager, removedSet := range removed {
108+
managers[manager].Set = managers[manager].Set.Difference(removedSet.Set)
109+
}
110+
111+
for manager := range managers {
112+
if managers[manager].Set.Empty() {
113+
delete(managers, manager)
105114
}
106115
}
107116

@@ -123,6 +132,11 @@ func (s *Updater) Update(liveObject, newObject typed.TypedValue, version fieldpa
123132
if err != nil {
124133
return fieldpath.ManagedFields{}, fmt.Errorf("failed to compare live and new objects: %v", err)
125134
}
135+
if _, ok := managers[manager]; !ok {
136+
managers[manager] = &fieldpath.VersionedSet{
137+
Set: fieldpath.NewSet(),
138+
}
139+
}
126140
managers[manager].Set = managers[manager].Set.Union(compare.Modified).Union(compare.Added).Difference(compare.Removed)
127141
managers[manager].APIVersion = version
128142
if managers[manager].Set.Empty() {
@@ -139,42 +153,117 @@ func (s *Updater) Apply(liveObject, configObject typed.TypedValue, version field
139153
if err != nil {
140154
return nil, fieldpath.ManagedFields{}, fmt.Errorf("failed to merge config: %v", err)
141155
}
142-
managers, err = s.update(liveObject, newObject, version, managers, manager, force)
143-
if err != nil {
144-
return nil, fieldpath.ManagedFields{}, err
145-
}
146-
newObject, err = s.removeDisownedItems(newObject, configObject, managers[manager])
147-
if err != nil {
148-
return nil, fieldpath.ManagedFields{}, fmt.Errorf("failed to remove fields: %v", err)
149-
}
150156
set, err := configObject.ToFieldSet()
151157
if err != nil {
152158
return nil, fieldpath.ManagedFields{}, fmt.Errorf("failed to get field set: %v", err)
153159
}
154-
managers[manager] = &fieldpath.VersionedSet{
160+
appliedSet := &fieldpath.VersionedSet{
155161
Set: set,
156162
APIVersion: version,
163+
Applied: true,
164+
}
165+
newObject, err = s.prune(newObject, managers, manager, appliedSet)
166+
if err != nil {
167+
return nil, fieldpath.ManagedFields{}, fmt.Errorf("failed to prune fields: %v", err)
157168
}
169+
managers, err = s.update(liveObject, newObject, version, managers, manager, force)
170+
if err != nil {
171+
return nil, fieldpath.ManagedFields{}, err
172+
}
173+
managers[manager] = appliedSet
158174
if managers[manager].Set.Empty() {
159175
delete(managers, manager)
160176
}
161177
return newObject, managers, nil
162178
}
163179

164-
func (s *Updater) removeDisownedItems(merged, applied typed.TypedValue, lastSet *fieldpath.VersionedSet) (typed.TypedValue, error) {
165-
if lastSet.Set.Empty() {
180+
func (s *Updater) prune(merged typed.TypedValue, managers fieldpath.ManagedFields, applyingManager string, appliedSet *fieldpath.VersionedSet) (typed.TypedValue, error) {
181+
lastSet := managers[applyingManager]
182+
if lastSet == nil || lastSet.Set.Empty() {
166183
return merged, nil
167184
}
168-
convertedApplied, err := s.Converter.Convert(applied, lastSet.APIVersion)
185+
convertedMerged, err := s.Converter.Convert(merged, lastSet.APIVersion)
186+
if err != nil {
187+
if s.Converter.IsMissingVersionError(err) {
188+
return merged, nil
189+
}
190+
return nil, fmt.Errorf("failed to convert merged object to last applied version: %v", err)
191+
}
192+
pruned := convertedMerged.RemoveItems(lastSet.Set)
193+
pruned, err = s.addBackOwnedItems(convertedMerged, pruned, managers, applyingManager, appliedSet)
194+
if err != nil {
195+
return nil, fmt.Errorf("failed add back owned items: %v", err)
196+
}
197+
pruned, err = s.addBackDanglingItems(convertedMerged, pruned, lastSet)
198+
if err != nil {
199+
return nil, fmt.Errorf("failed add back dangling items: %v", err)
200+
}
201+
return s.Converter.Convert(pruned, appliedSet.APIVersion)
202+
}
203+
204+
func (s *Updater) addBackOwnedItems(merged, pruned typed.TypedValue, managedFields fieldpath.ManagedFields, applyingManager string, appliedSet *fieldpath.VersionedSet) (typed.TypedValue, error) {
205+
var err error
206+
managersAtVersion := map[fieldpath.APIVersion][]string{}
207+
for manager, managerSet := range managedFields {
208+
if !managerSet.Applied {
209+
continue
210+
}
211+
if manager == applyingManager {
212+
managerSet = appliedSet
213+
}
214+
managersAtVersion[managerSet.APIVersion] = append(managersAtVersion[managerSet.APIVersion], manager)
215+
}
216+
for version, managers := range managersAtVersion {
217+
merged, err = s.Converter.Convert(merged, version)
218+
if err != nil {
219+
if s.Converter.IsMissingVersionError(err) {
220+
continue
221+
}
222+
return nil, fmt.Errorf("failed to convert merged object at version %v: %v", version, err)
223+
}
224+
pruned, err = s.Converter.Convert(pruned, version)
225+
if err != nil {
226+
if s.Converter.IsMissingVersionError(err) {
227+
continue
228+
}
229+
return nil, fmt.Errorf("failed to convert pruned object at version %v: %v", version, err)
230+
}
231+
mergedSet, err := merged.ToFieldSet()
232+
if err != nil {
233+
return nil, fmt.Errorf("failed to create field set from merged object at version %v: %v", version, err)
234+
}
235+
prunedSet, err := pruned.ToFieldSet()
236+
if err != nil {
237+
return nil, fmt.Errorf("failed to create field set from pruned object at version %v: %v", version, err)
238+
}
239+
toAddBack := prunedSet
240+
for _, manager := range managers {
241+
managerSet := managedFields[manager]
242+
if manager == applyingManager {
243+
managerSet = appliedSet
244+
}
245+
toAddBack = toAddBack.Union(managerSet.Set)
246+
}
247+
pruned = merged.RemoveItems(mergedSet.Difference(toAddBack))
248+
}
249+
return pruned, nil
250+
}
251+
252+
func (s *Updater) addBackDanglingItems(merged, pruned typed.TypedValue, lastSet *fieldpath.VersionedSet) (typed.TypedValue, error) {
253+
convertedPruned, err := s.Converter.Convert(pruned, lastSet.APIVersion)
169254
if err != nil {
170255
if s.Converter.IsMissingVersionError(err) {
171256
return merged, nil
172257
}
173-
return nil, fmt.Errorf("failed to convert applied config to last applied version: %v", err)
258+
return nil, fmt.Errorf("failed to convert pruned object to last applied version: %v", err)
259+
}
260+
prunedSet, err := convertedPruned.ToFieldSet()
261+
if err != nil {
262+
return nil, fmt.Errorf("failed to create field set from pruned object in last applied version: %v", err)
174263
}
175-
appliedSet, err := convertedApplied.ToFieldSet()
264+
mergedSet, err := merged.ToFieldSet()
176265
if err != nil {
177-
return nil, fmt.Errorf("failed to create field set from applied config in last applied version: %v", err)
266+
return nil, fmt.Errorf("failed to create field set from merged object in last applied version: %v", err)
178267
}
179-
return merged.RemoveItems(lastSet.Set.Difference(appliedSet)), nil
268+
return merged.RemoveItems(mergedSet.Difference(prunedSet).Intersection(lastSet.Set)), nil
180269
}

0 commit comments

Comments
 (0)