@@ -36,6 +36,110 @@ func TestDropManagedFields(t *testing.T) {
36
36
37
37
ssaManager := "ssa-manager"
38
38
39
+ tests := []struct {
40
+ name string
41
+ updateManager string
42
+ obj client.Object
43
+ wantOwnershipToDrop bool
44
+ }{
45
+ {
46
+ name : "should drop ownership of fields if there is no entry for ssaManager" ,
47
+ wantOwnershipToDrop : true ,
48
+ },
49
+ {
50
+ name : "should not drop ownership of fields if there is an entry for ssaManager" ,
51
+ updateManager : ssaManager ,
52
+ wantOwnershipToDrop : false ,
53
+ },
54
+ }
55
+
56
+ for _ , tt := range tests {
57
+ t .Run (tt .name , func (t * testing.T ) {
58
+ g := NewWithT (t )
59
+
60
+ createCM := & corev1.ConfigMap {
61
+ // Have to set TypeMeta explicitly when using SSA with typed objects.
62
+ TypeMeta : metav1.TypeMeta {
63
+ APIVersion : "v1" ,
64
+ Kind : "ConfigMap" ,
65
+ },
66
+ ObjectMeta : metav1.ObjectMeta {
67
+ Name : "cm-1" ,
68
+ Namespace : "default" ,
69
+ Labels : map [string ]string {
70
+ "label-1" : "value-1" ,
71
+ },
72
+ Annotations : map [string ]string {
73
+ "annotation-1" : "value-1" ,
74
+ },
75
+ Finalizers : []string {"test.com/finalizer" },
76
+ },
77
+ Data : map [string ]string {
78
+ "test-key" : "test-value" ,
79
+ },
80
+ }
81
+ updateCM := createCM .DeepCopy ()
82
+ updateCM .Data ["test-key-update" ] = "test-value-update"
83
+
84
+ g .Expect (env .Client .Create (ctx , createCM , client .FieldOwner (classicManager ))).To (Succeed ())
85
+ t .Cleanup (func () {
86
+ createCMWithoutFinalizer := createCM .DeepCopy ()
87
+ createCMWithoutFinalizer .ObjectMeta .Finalizers = []string {}
88
+ g .Expect (env .Client .Patch (ctx , createCMWithoutFinalizer , client .MergeFrom (createCM ))).To (Succeed ())
89
+ g .Expect (env .CleanupAndWait (ctx , createCM )).To (Succeed ())
90
+ })
91
+
92
+ if tt .updateManager != "" {
93
+ // If updateManager is set, update the object with SSA
94
+ g .Expect (env .Client .Patch (ctx , updateCM , client .Apply , client .FieldOwner (tt .updateManager ))).To (Succeed ())
95
+ }
96
+
97
+ gotObj := createCM .DeepCopyObject ().(client.Object )
98
+ g .Expect (env .GetAPIReader ().Get (ctx , client .ObjectKeyFromObject (createCM ), gotObj )).To (Succeed ())
99
+ labelsAndAnnotationsManagedFieldPaths := []contract.Path {
100
+ {"f:metadata" , "f:annotations" },
101
+ {"f:metadata" , "f:labels" },
102
+ }
103
+ g .Expect (DropManagedFields (ctx , env .Client , gotObj , ssaManager , labelsAndAnnotationsManagedFieldPaths )).To (Succeed ())
104
+
105
+ if tt .wantOwnershipToDrop {
106
+ g .Expect (gotObj .GetManagedFields ()).ShouldNot (MatchFieldOwnership (
107
+ classicManager ,
108
+ metav1 .ManagedFieldsOperationUpdate ,
109
+ contract.Path {"f:metadata" , "f:labels" },
110
+ ))
111
+ g .Expect (gotObj .GetManagedFields ()).ShouldNot (MatchFieldOwnership (
112
+ classicManager ,
113
+ metav1 .ManagedFieldsOperationUpdate ,
114
+ contract.Path {"f:metadata" , "f:annotations" },
115
+ ))
116
+ } else {
117
+ g .Expect (gotObj .GetManagedFields ()).Should (MatchFieldOwnership (
118
+ classicManager ,
119
+ metav1 .ManagedFieldsOperationUpdate ,
120
+ contract.Path {"f:metadata" , "f:labels" },
121
+ ))
122
+ g .Expect (gotObj .GetManagedFields ()).Should (MatchFieldOwnership (
123
+ classicManager ,
124
+ metav1 .ManagedFieldsOperationUpdate ,
125
+ contract.Path {"f:metadata" , "f:annotations" },
126
+ ))
127
+ }
128
+ // Verify ownership of other fields is not affected.
129
+ g .Expect (gotObj .GetManagedFields ()).Should (MatchFieldOwnership (
130
+ classicManager ,
131
+ metav1 .ManagedFieldsOperationUpdate ,
132
+ contract.Path {"f:metadata" , "f:finalizers" },
133
+ ))
134
+ })
135
+ }
136
+ }
137
+
138
+ func TestDropManagedFieldsWithFakeClient (t * testing.T ) {
139
+ ctx := context .Background ()
140
+
141
+ ssaManager := "ssa-manager"
142
+
39
143
fieldV1Map := map [string ]interface {}{
40
144
"f:metadata" : map [string ]interface {}{
41
145
"f:name" : map [string ]interface {}{},
@@ -165,6 +269,137 @@ func TestCleanUpManagedFieldsForSSAAdoption(t *testing.T) {
165
269
166
270
ssaManager := "ssa-manager"
167
271
272
+ type managedFields struct {
273
+ Manager string
274
+ Operation metav1.ManagedFieldsOperationType
275
+ }
276
+ tests := []struct {
277
+ name string
278
+ createManager string
279
+ updateManager string
280
+ wantManagedFields []managedFields
281
+ }{
282
+ {
283
+ name : "should add an entry for ssaManager if it does not have one" ,
284
+ createManager : "unknown-manager" ,
285
+ wantManagedFields : []managedFields {
286
+ {
287
+ Manager : "unknown-manager" ,
288
+ Operation : metav1 .ManagedFieldsOperationUpdate ,
289
+ },
290
+ {
291
+ Manager : ssaManager ,
292
+ Operation : metav1 .ManagedFieldsOperationApply ,
293
+ },
294
+ },
295
+ },
296
+ {
297
+ name : "should add an entry for ssaManager and drop entry for classic manager if it exists" ,
298
+ createManager : classicManager ,
299
+ wantManagedFields : []managedFields {
300
+ {
301
+ Manager : ssaManager ,
302
+ Operation : metav1 .ManagedFieldsOperationApply ,
303
+ },
304
+ },
305
+ },
306
+ {
307
+ name : "should keep the entry for ssa-manager if it already has one (no-op)" ,
308
+ createManager : ssaManager ,
309
+ wantManagedFields : []managedFields {
310
+ {
311
+ Manager : ssaManager ,
312
+ Operation : metav1 .ManagedFieldsOperationApply ,
313
+ },
314
+ },
315
+ },
316
+ {
317
+ name : "should keep the entry with ssa-manager if it already has one - should not drop other manager entries (no-op)" ,
318
+ createManager : classicManager ,
319
+ updateManager : ssaManager ,
320
+ wantManagedFields : []managedFields {
321
+ {
322
+ Manager : classicManager ,
323
+ Operation : metav1 .ManagedFieldsOperationUpdate ,
324
+ },
325
+ {
326
+ Manager : ssaManager ,
327
+ Operation : metav1 .ManagedFieldsOperationApply ,
328
+ },
329
+ },
330
+ },
331
+ }
332
+
333
+ for _ , tt := range tests {
334
+ t .Run (tt .name , func (t * testing.T ) {
335
+ g := NewWithT (t )
336
+
337
+ createCM := & corev1.ConfigMap {
338
+ // Have to set TypeMeta explicitly when using SSA with typed objects.
339
+ TypeMeta : metav1.TypeMeta {
340
+ APIVersion : "v1" ,
341
+ Kind : "ConfigMap" ,
342
+ },
343
+ ObjectMeta : metav1.ObjectMeta {
344
+ Name : "cm-1" ,
345
+ Namespace : "default" ,
346
+ },
347
+ Data : map [string ]string {
348
+ "test-key" : "test-value" ,
349
+ },
350
+ }
351
+ updateCM := createCM .DeepCopy ()
352
+ updateCM .Data ["test-key-update" ] = "test-value-update"
353
+
354
+ if tt .createManager == ssaManager {
355
+ // If createManager is ssaManager, use SSA
356
+ g .Expect (env .Client .Patch (ctx , createCM , client .Apply , client .FieldOwner (tt .createManager ))).To (Succeed ())
357
+ } else {
358
+ // Otherwise use regular Create
359
+ g .Expect (env .Client .Create (ctx , createCM , client .FieldOwner (tt .createManager ))).To (Succeed ())
360
+ }
361
+ t .Cleanup (func () {
362
+ g .Expect (env .CleanupAndWait (ctx , createCM )).To (Succeed ())
363
+ })
364
+
365
+ if tt .updateManager != "" {
366
+ // If updateManager is set, update the object with SSA
367
+ g .Expect (env .Client .Patch (ctx , updateCM , client .Apply , client .FieldOwner (tt .updateManager ))).To (Succeed ())
368
+ }
369
+
370
+ // Validate object has exactly the field manager we expect.
371
+ gotObj := createCM .DeepCopyObject ().(client.Object )
372
+ g .Expect (env .GetAPIReader ().Get (ctx , client .ObjectKeyFromObject (createCM ), gotObj )).To (Succeed ())
373
+ expectedManager := []string {tt .createManager }
374
+ if tt .updateManager != "" {
375
+ expectedManager = append (expectedManager , tt .updateManager )
376
+ }
377
+ var gotManager []string
378
+ for _ , managedFields := range gotObj .GetManagedFields () {
379
+ gotManager = append (gotManager , managedFields .Manager )
380
+ }
381
+ g .Expect (gotManager ).To (ConsistOf (expectedManager ))
382
+
383
+ // Cleanup managed fields.
384
+ g .Expect (CleanUpManagedFieldsForSSAAdoption (ctx , env .Client , gotObj , ssaManager )).Should (Succeed ())
385
+
386
+ // Validate object has been cleaned up correctly
387
+ gotObj = createCM .DeepCopyObject ().(client.Object )
388
+ g .Expect (env .GetAPIReader ().Get (ctx , client .ObjectKeyFromObject (createCM ), gotObj )).To (Succeed ())
389
+ g .Expect (gotObj .GetManagedFields ()).To (HaveLen (len (tt .wantManagedFields )))
390
+ for _ , mf := range tt .wantManagedFields {
391
+ g .Expect (gotObj .GetManagedFields ()).Should (
392
+ ContainElement (MatchManagedFieldsEntry (mf .Manager , mf .Operation )))
393
+ }
394
+ })
395
+ }
396
+ }
397
+
398
+ func TestCleanUpManagedFieldsForSSAAdoptionWithFakeClient (t * testing.T ) {
399
+ ctx := context .Background ()
400
+
401
+ ssaManager := "ssa-manager"
402
+
168
403
objWithoutAnyManager := & corev1.ConfigMap {
169
404
ObjectMeta : metav1.ObjectMeta {
170
405
Name : "cm-1" ,
0 commit comments