Skip to content

Commit b34bcab

Browse files
committed
Add envtest testcoverage for CleanUpManagedFieldsForSSAAdoption & DropManagedFields
1 parent 8610147 commit b34bcab

File tree

1 file changed

+235
-0
lines changed

1 file changed

+235
-0
lines changed

internal/util/ssa/managedfields_test.go

Lines changed: 235 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,110 @@ func TestDropManagedFields(t *testing.T) {
3636

3737
ssaManager := "ssa-manager"
3838

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+
39143
fieldV1Map := map[string]interface{}{
40144
"f:metadata": map[string]interface{}{
41145
"f:name": map[string]interface{}{},
@@ -165,6 +269,137 @@ func TestCleanUpManagedFieldsForSSAAdoption(t *testing.T) {
165269

166270
ssaManager := "ssa-manager"
167271

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+
168403
objWithoutAnyManager := &corev1.ConfigMap{
169404
ObjectMeta: metav1.ObjectMeta{
170405
Name: "cm-1",

0 commit comments

Comments
 (0)