@@ -38,6 +38,7 @@ func (s *Updater) update(oldObject, newObject typed.TypedValue, version fieldpat
38
38
managers = fieldpath.ManagedFields {}
39
39
}
40
40
conflicts := fieldpath.ManagedFields {}
41
+ removed := fieldpath.ManagedFields {}
41
42
type Versioned struct {
42
43
oldObject typed.TypedValue
43
44
newObject typed.TypedValue
@@ -86,6 +87,13 @@ func (s *Updater) update(oldObject, newObject typed.TypedValue, version fieldpat
86
87
APIVersion : managerSet .APIVersion ,
87
88
}
88
89
}
90
+
91
+ if ! compare .Removed .Empty () {
92
+ removed [manager ] = & fieldpath.VersionedSet {
93
+ Set : compare .Removed ,
94
+ APIVersion : managerSet .APIVersion ,
95
+ }
96
+ }
89
97
}
90
98
91
99
if ! force && len (conflicts ) != 0 {
@@ -94,14 +102,15 @@ func (s *Updater) update(oldObject, newObject typed.TypedValue, version fieldpat
94
102
95
103
for manager , conflictSet := range conflicts {
96
104
managers [manager ].Set = managers [manager ].Set .Difference (conflictSet .Set )
97
- if managers [manager ].Set .Empty () {
98
- delete (managers , manager )
99
- }
100
105
}
101
106
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 )
105
114
}
106
115
}
107
116
@@ -123,6 +132,11 @@ func (s *Updater) Update(liveObject, newObject typed.TypedValue, version fieldpa
123
132
if err != nil {
124
133
return fieldpath.ManagedFields {}, fmt .Errorf ("failed to compare live and new objects: %v" , err )
125
134
}
135
+ if _ , ok := managers [manager ]; ! ok {
136
+ managers [manager ] = & fieldpath.VersionedSet {
137
+ Set : fieldpath .NewSet (),
138
+ }
139
+ }
126
140
managers [manager ].Set = managers [manager ].Set .Union (compare .Modified ).Union (compare .Added ).Difference (compare .Removed )
127
141
managers [manager ].APIVersion = version
128
142
if managers [manager ].Set .Empty () {
@@ -139,42 +153,117 @@ func (s *Updater) Apply(liveObject, configObject typed.TypedValue, version field
139
153
if err != nil {
140
154
return nil , fieldpath.ManagedFields {}, fmt .Errorf ("failed to merge config: %v" , err )
141
155
}
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
- }
150
156
set , err := configObject .ToFieldSet ()
151
157
if err != nil {
152
158
return nil , fieldpath.ManagedFields {}, fmt .Errorf ("failed to get field set: %v" , err )
153
159
}
154
- managers [ manager ] = & fieldpath.VersionedSet {
160
+ appliedSet : = & fieldpath.VersionedSet {
155
161
Set : set ,
156
162
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 )
157
168
}
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
158
174
if managers [manager ].Set .Empty () {
159
175
delete (managers , manager )
160
176
}
161
177
return newObject , managers , nil
162
178
}
163
179
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 () {
166
183
return merged , nil
167
184
}
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 )
169
254
if err != nil {
170
255
if s .Converter .IsMissingVersionError (err ) {
171
256
return merged , nil
172
257
}
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 )
174
263
}
175
- appliedSet , err := convertedApplied .ToFieldSet ()
264
+ mergedSet , err := merged .ToFieldSet ()
176
265
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 )
178
267
}
179
- return merged .RemoveItems (lastSet . Set . Difference (appliedSet )), nil
268
+ return merged .RemoveItems (mergedSet . Difference (prunedSet ). Intersection ( lastSet . Set )), nil
180
269
}
0 commit comments