@@ -197,8 +197,8 @@ func (u *Updater) Apply(ctx context.Context, baseObj *unstructured.Unstructured)
197197
198198func isSafeForUpdate (logger logr.Logger , inMemory * unstructured.Unstructured , onCluster * unstructured.Unstructured ) bool {
199199 // Compare metadata (excluding resourceVersion).
200- inMemoryMetadata := metadataWithoutResourceVersion (inMemory )
201- onClusterMetadata := metadataWithoutResourceVersion (onCluster )
200+ inMemoryMetadata := reducedMetadata (inMemory )
201+ onClusterMetadata := reducedMetadata (onCluster )
202202 if ! reflect .DeepEqual (inMemoryMetadata , onClusterMetadata ) {
203203 // Diff in metadata. Nothing we can do about it -> Fail.
204204 logger .V (1 ).Info ("Not refreshing object due to metadata mismatch" ,
@@ -221,21 +221,42 @@ func isSafeForUpdate(logger logr.Logger, inMemory *unstructured.Unstructured, on
221221 return true
222222}
223223
224- func metadataWithoutResourceVersion (u * unstructured.Unstructured ) map [string ]interface {} {
224+ // recudedMetadata returns the metadata of the given unstructured object,
225+ // excluding a couple of fields which should not be taken into account
226+ // for equality checks. The excluded fields are:
227+ //
228+ // - metadata.resourceVersion
229+ // - metadata.managedFields
230+ // - metadata.annotation."kubectl.kubernetes.io/last-applied-configuration"
231+ func reducedMetadata (u * unstructured.Unstructured ) map [string ]interface {} {
225232 metadata , ok := u .Object ["metadata" ].(map [string ]interface {})
226233 if ! ok {
227234 return nil
228235 }
229- modifiedMetadata := make (map [string ]interface {}, len (metadata ))
230- for k , v := range metadata {
231- if k == "resourceVersion" {
232- continue
233- }
234- modifiedMetadata [k ] = v
236+ modifiedMetadata := excludeFromMap (metadata , "resourceVersion" , "managedFields" )
237+ if annotations , found := modifiedMetadata ["annotations" ].(map [string ]interface {}); found {
238+ modifiedMetadata ["annotations" ] = excludeFromMap (annotations , "kubectl.kubernetes.io/last-applied-configuration" )
235239 }
240+
236241 return modifiedMetadata
237242}
238243
244+ // excludeFromMap returns a new map that contains all key-value pairs from inputMap
245+ // except those whose keys are in the keys slice.
246+ func excludeFromMap (inputMap map [string ]interface {}, keys ... string ) map [string ]interface {} {
247+ resultMap := make (map [string ]interface {}, len (inputMap ))
248+ excludeKeys := make (map [string ]struct {})
249+ for _ , k := range keys {
250+ excludeKeys [k ] = struct {}{}
251+ }
252+ for k , v := range inputMap {
253+ if _ , found := excludeKeys [k ]; ! found {
254+ resultMap [k ] = v
255+ }
256+ }
257+ return resultMap
258+ }
259+
239260func (u * Updater ) tryRefresh (ctx context.Context , obj * unstructured.Unstructured ) (bool , error ) {
240261 // Re-fetch object with client.
241262 current := & unstructured.Unstructured {}
0 commit comments