Skip to content

Commit a45742b

Browse files
authored
Merge pull request kubernetes#126895 from googs1025/refactor/kubelet_podmanager_ut
refactor(kubelet): implement a table-driven test for pod_manager
2 parents c348d09 + e0dab78 commit a45742b

File tree

2 files changed

+233
-105
lines changed

2 files changed

+233
-105
lines changed

pkg/kubelet/pod/pod_manager.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ func NewBasicPodManager() Manager {
123123
return pm
124124
}
125125

126-
// Set the internal pods based on the new pods.
126+
// SetPods set the internal pods based on the new pods.
127127
func (pm *basicManager) SetPods(newPods []*v1.Pod) {
128128
pm.lock.Lock()
129129
defer pm.lock.Unlock()
@@ -336,5 +336,4 @@ func (pm *basicManager) GetPodAndMirrorPod(aPod *v1.Pod) (pod, mirrorPod *v1.Pod
336336
return pm.podByFullName[fullName], aPod, true
337337
}
338338
return aPod, pm.mirrorPodByFullName[fullName], false
339-
340339
}

pkg/kubelet/pod/pod_manager_test.go

Lines changed: 232 additions & 103 deletions
Original file line numberDiff line numberDiff line change
@@ -17,151 +17,280 @@ limitations under the License.
1717
package pod
1818

1919
import (
20-
"reflect"
20+
"fmt"
2121
"testing"
2222

23+
"github.com/google/go-cmp/cmp"
24+
"github.com/google/go-cmp/cmp/cmpopts"
25+
"github.com/stretchr/testify/assert"
26+
2327
v1 "k8s.io/api/core/v1"
2428
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
2529
"k8s.io/apimachinery/pkg/types"
26-
podtest "k8s.io/kubernetes/pkg/kubelet/pod/testing"
2730
kubetypes "k8s.io/kubernetes/pkg/kubelet/types"
2831
)
2932

30-
// Stub out mirror client for testing purpose.
31-
func newTestManager() (*basicManager, *podtest.FakeMirrorClient) {
32-
fakeMirrorClient := podtest.NewFakeMirrorClient()
33-
manager := NewBasicPodManager().(*basicManager)
34-
return manager, fakeMirrorClient
35-
}
33+
var (
34+
mirrorPodUID = "mirror-pod-uid"
35+
staticPodUID = "static-pod-uid"
36+
normalPodUID = "normal-pod-uid"
37+
mirrorPodName = "mirror-static-pod-name"
38+
staticPodName = "mirror-static-pod-name"
39+
normalPodName = "normal-pod-name"
3640

37-
// Tests that pods/maps are properly set after the pod update, and the basic
38-
// methods work correctly.
39-
func TestGetSetPods(t *testing.T) {
40-
mirrorPod := &v1.Pod{
41+
mirrorPod = &v1.Pod{
4142
ObjectMeta: metav1.ObjectMeta{
42-
UID: "987654321",
43-
Name: "bar",
44-
Namespace: "default",
43+
UID: types.UID(mirrorPodUID),
44+
Name: mirrorPodName,
45+
Namespace: metav1.NamespaceDefault,
4546
Annotations: map[string]string{
4647
kubetypes.ConfigSourceAnnotationKey: "api",
4748
kubetypes.ConfigMirrorAnnotationKey: "mirror",
49+
kubetypes.ConfigHashAnnotationKey: "mirror",
4850
},
4951
},
5052
}
51-
staticPod := &v1.Pod{
53+
staticPod = &v1.Pod{
5254
ObjectMeta: metav1.ObjectMeta{
53-
UID: "123456789",
54-
Name: "bar",
55-
Namespace: "default",
55+
UID: types.UID(staticPodUID),
56+
Name: staticPodName,
57+
Namespace: metav1.NamespaceDefault,
5658
Annotations: map[string]string{kubetypes.ConfigSourceAnnotationKey: "file"},
5759
},
5860
}
61+
normalPod = &v1.Pod{
62+
ObjectMeta: metav1.ObjectMeta{
63+
UID: types.UID(normalPodUID),
64+
Name: normalPodName,
65+
Namespace: metav1.NamespaceDefault,
66+
Annotations: map[string]string{},
67+
},
68+
}
69+
sortOpt = cmpopts.SortSlices(func(a, b *v1.Pod) bool { return a.Name < b.Name })
70+
)
5971

60-
expectedPods := []*v1.Pod{
72+
func TestAddOrUpdatePod(t *testing.T) {
73+
tests := []struct {
74+
name string
75+
isMirror bool
76+
pod *v1.Pod
77+
}{
6178
{
62-
ObjectMeta: metav1.ObjectMeta{
63-
UID: "999999999",
64-
Name: "taco",
65-
Namespace: "default",
66-
Annotations: map[string]string{kubetypes.ConfigSourceAnnotationKey: "api"},
67-
},
79+
name: "mirror pod",
80+
pod: mirrorPod,
81+
isMirror: true,
82+
},
83+
{
84+
name: "static pod",
85+
pod: staticPod,
86+
isMirror: false,
87+
},
88+
{
89+
name: "normal pod",
90+
pod: normalPod,
91+
isMirror: false,
6892
},
69-
staticPod,
70-
}
71-
updates := append(expectedPods, mirrorPod)
72-
podManager, _ := newTestManager()
73-
podManager.SetPods(updates)
74-
75-
// Tests that all regular pods are recorded correctly.
76-
actualPods := podManager.GetPods()
77-
if len(actualPods) != len(expectedPods) {
78-
t.Errorf("expected %d pods, got %d pods; expected pods %#v, got pods %#v", len(expectedPods), len(actualPods),
79-
expectedPods, actualPods)
8093
}
81-
for _, expected := range expectedPods {
82-
found := false
83-
for _, actual := range actualPods {
84-
if actual.UID == expected.UID {
85-
if !reflect.DeepEqual(&expected, &actual) {
86-
t.Errorf("pod was recorded incorrectly. expect: %#v, got: %#v", expected, actual)
87-
}
88-
found = true
89-
break
94+
95+
for _, test := range tests {
96+
t.Run(test.name, func(t *testing.T) {
97+
pm := &basicManager{
98+
podByUID: make(map[kubetypes.ResolvedPodUID]*v1.Pod),
99+
mirrorPodByUID: make(map[kubetypes.MirrorPodUID]*v1.Pod),
100+
podByFullName: make(map[string]*v1.Pod),
101+
mirrorPodByFullName: make(map[string]*v1.Pod),
102+
translationByUID: make(map[kubetypes.MirrorPodUID]kubetypes.ResolvedPodUID),
90103
}
91-
}
92-
if !found {
93-
t.Errorf("pod %q was not found in %#v", expected.UID, actualPods)
94-
}
95-
}
96-
// Tests UID translation works as expected. Convert static pod UID for comparison only.
97-
if uid := podManager.TranslatePodUID(mirrorPod.UID); uid != kubetypes.ResolvedPodUID(staticPod.UID) {
98-
t.Errorf("unable to translate UID %q to the static POD's UID %q; %#v",
99-
mirrorPod.UID, staticPod.UID, podManager.mirrorPodByUID)
104+
pm.AddPod(test.pod)
105+
verify(t, pm, test.isMirror, test.pod)
106+
test.pod.Annotations["testLabel"] = "updated"
107+
pm.UpdatePod(test.pod)
108+
verify(t, pm, test.isMirror, test.pod)
109+
})
100110
}
101111

102-
// Test the basic Get methods.
103-
actualPod, ok := podManager.GetPodByFullName("bar_default")
104-
if !ok || !reflect.DeepEqual(actualPod, staticPod) {
105-
t.Errorf("unable to get pod by full name; expected: %#v, got: %#v", staticPod, actualPod)
106-
}
107-
actualPod, ok = podManager.GetPodByName("default", "bar")
108-
if !ok || !reflect.DeepEqual(actualPod, staticPod) {
109-
t.Errorf("unable to get pod by name; expected: %#v, got: %#v", staticPod, actualPod)
110-
}
112+
}
111113

114+
func verify(t *testing.T, pm *basicManager, isMirror bool, expectedPod *v1.Pod) {
115+
fullName := fmt.Sprintf("%s_%s", expectedPod.Name, expectedPod.Namespace)
116+
if isMirror {
117+
inputPod, ok := pm.mirrorPodByUID[kubetypes.MirrorPodUID(expectedPod.UID)]
118+
assert.True(t, ok)
119+
assert.Empty(t, cmp.Diff(expectedPod, inputPod), "MirrorPodByUID map verification failed.")
120+
inputPod, ok = pm.mirrorPodByFullName[fullName]
121+
assert.True(t, ok)
122+
assert.Empty(t, cmp.Diff(expectedPod, inputPod), "MirrorPodByFullName map verification failed.")
123+
} else {
124+
inputPod, ok := pm.podByUID[kubetypes.ResolvedPodUID(expectedPod.UID)]
125+
assert.True(t, ok)
126+
assert.Empty(t, cmp.Diff(expectedPod, inputPod), "PodByUID map verification failed.")
127+
inputPod, ok = pm.podByFullName[fullName]
128+
assert.True(t, ok)
129+
assert.Empty(t, cmp.Diff(expectedPod, inputPod), "PodByFullName map verification failed.")
130+
}
112131
}
113132

114-
func TestRemovePods(t *testing.T) {
115-
mirrorPod := &v1.Pod{
116-
ObjectMeta: metav1.ObjectMeta{
117-
UID: types.UID("mirror-pod-uid"),
118-
Name: "mirror-static-pod-name",
119-
Namespace: metav1.NamespaceDefault,
120-
Annotations: map[string]string{
121-
kubetypes.ConfigSourceAnnotationKey: "api",
122-
kubetypes.ConfigMirrorAnnotationKey: "mirror",
133+
// Tests that pods/maps are properly set after the pod update, and the basic
134+
// methods work correctly.
135+
func TestGetSetPods(t *testing.T) {
136+
testCase := []struct {
137+
name string
138+
podList []*v1.Pod
139+
wantUID types.UID
140+
wantPod *v1.Pod
141+
isMirrorPod bool
142+
expectPods []*v1.Pod
143+
expectPod *v1.Pod
144+
expectedMirrorPod *v1.Pod
145+
expectUID types.UID
146+
expectPodToMirrorMap map[kubetypes.ResolvedPodUID]kubetypes.MirrorPodUID
147+
expectMirrorToPodMap map[kubetypes.MirrorPodUID]kubetypes.ResolvedPodUID
148+
}{
149+
{
150+
name: "Get normal pod",
151+
podList: []*v1.Pod{mirrorPod, staticPod, normalPod},
152+
wantUID: types.UID("normal-pod-uid"),
153+
wantPod: normalPod,
154+
isMirrorPod: false,
155+
expectedMirrorPod: nil,
156+
expectPods: []*v1.Pod{staticPod, normalPod},
157+
expectPod: normalPod,
158+
expectUID: types.UID("normal-pod-uid"),
159+
expectPodToMirrorMap: map[kubetypes.ResolvedPodUID]kubetypes.MirrorPodUID{
160+
kubetypes.ResolvedPodUID("static-pod-uid"): kubetypes.MirrorPodUID("mirror-pod-uid"),
161+
},
162+
expectMirrorToPodMap: map[kubetypes.MirrorPodUID]kubetypes.ResolvedPodUID{
163+
kubetypes.MirrorPodUID("mirror-pod-uid"): kubetypes.ResolvedPodUID("static-pod-uid"),
123164
},
124165
},
125-
}
126-
staticPod := &v1.Pod{
127-
ObjectMeta: metav1.ObjectMeta{
128-
UID: types.UID("static-pod-uid"),
129-
Name: "mirror-static-pod-name",
130-
Namespace: metav1.NamespaceDefault,
131-
Annotations: map[string]string{kubetypes.ConfigSourceAnnotationKey: "file"},
166+
{
167+
name: "Get static pod",
168+
podList: []*v1.Pod{mirrorPod, staticPod, normalPod},
169+
wantUID: types.UID("static-pod-uid"),
170+
wantPod: staticPod,
171+
isMirrorPod: false,
172+
expectPods: []*v1.Pod{staticPod, normalPod},
173+
expectPod: staticPod,
174+
expectedMirrorPod: mirrorPod,
175+
expectUID: types.UID("static-pod-uid"),
176+
expectPodToMirrorMap: map[kubetypes.ResolvedPodUID]kubetypes.MirrorPodUID{
177+
kubetypes.ResolvedPodUID("static-pod-uid"): kubetypes.MirrorPodUID("mirror-pod-uid"),
178+
},
179+
expectMirrorToPodMap: map[kubetypes.MirrorPodUID]kubetypes.ResolvedPodUID{
180+
kubetypes.MirrorPodUID("mirror-pod-uid"): kubetypes.ResolvedPodUID("static-pod-uid"),
181+
},
132182
},
133-
}
134-
135-
expectedPods := []*v1.Pod{
136183
{
137-
ObjectMeta: metav1.ObjectMeta{
138-
UID: types.UID("extra-pod-uid"),
139-
Name: "extra-pod-name",
140-
Namespace: metav1.NamespaceDefault,
141-
Annotations: map[string]string{kubetypes.ConfigSourceAnnotationKey: "api"},
184+
name: "Get mirror pod",
185+
podList: []*v1.Pod{mirrorPod, staticPod, normalPod},
186+
wantUID: types.UID("static-pod-uid"),
187+
wantPod: mirrorPod,
188+
isMirrorPod: true,
189+
expectPods: []*v1.Pod{staticPod, normalPod},
190+
expectPod: staticPod,
191+
expectedMirrorPod: mirrorPod,
192+
expectUID: types.UID("static-pod-uid"),
193+
expectPodToMirrorMap: map[kubetypes.ResolvedPodUID]kubetypes.MirrorPodUID{
194+
kubetypes.ResolvedPodUID("static-pod-uid"): kubetypes.MirrorPodUID("mirror-pod-uid"),
195+
},
196+
expectMirrorToPodMap: map[kubetypes.MirrorPodUID]kubetypes.ResolvedPodUID{
197+
kubetypes.MirrorPodUID("mirror-pod-uid"): kubetypes.ResolvedPodUID("static-pod-uid"),
142198
},
143199
},
144-
staticPod,
145200
}
146-
updates := append(expectedPods, mirrorPod)
147-
podManager, _ := newTestManager()
148-
podManager.SetPods(updates)
201+
for _, test := range testCase {
202+
t.Run(test.name, func(t *testing.T) {
203+
podManager := NewBasicPodManager()
204+
podManager.SetPods(test.podList)
205+
actualPods := podManager.GetPods()
206+
assert.Empty(t, cmp.Diff(test.expectPods, actualPods, sortOpt), "actualPods and expectPods differ")
207+
208+
uid := podManager.TranslatePodUID(test.wantPod.UID)
209+
assert.Equal(t, kubetypes.ResolvedPodUID(test.expectUID), uid, "unable to translate pod UID")
149210

150-
podManager.RemovePod(staticPod)
211+
fullName := fmt.Sprintf("%s_%s", test.wantPod.Name, test.wantPod.Namespace)
212+
actualPod, ok := podManager.GetPodByFullName(fullName)
213+
assert.True(t, ok)
214+
assert.Empty(t, cmp.Diff(test.expectPod, actualPod), "actualPod by full name and expectGetPod differ")
151215

152-
actualPods := podManager.GetPods()
153-
if len(actualPods) == len(expectedPods) {
154-
t.Fatalf("Run RemovePod() error, expected %d pods, got %d pods; ", len(expectedPods)-1, len(actualPods))
216+
actualPod, ok = podManager.GetPodByName(test.wantPod.Namespace, test.wantPod.Name)
217+
assert.True(t, ok)
218+
assert.Empty(t, cmp.Diff(test.expectPod, actualPod), "actualPod by name and expectGetPod differ")
219+
220+
actualPod, ok = podManager.GetPodByUID(test.wantUID)
221+
assert.True(t, ok)
222+
assert.Empty(t, cmp.Diff(test.expectPod, actualPod), "actualPod and expectGetPod differ")
223+
224+
podToMirror, mirrorToPod := podManager.GetUIDTranslations()
225+
assert.Empty(t, cmp.Diff(test.expectPodToMirrorMap, podToMirror), "podToMirror and expectPodToMirror differ")
226+
assert.Empty(t, cmp.Diff(test.expectMirrorToPodMap, mirrorToPod), "mirrorToPod and expectMirrorToPod differ")
227+
228+
actualPod, ok = podManager.GetMirrorPodByPod(test.wantPod)
229+
assert.Equal(t, test.expectedMirrorPod != nil, ok)
230+
assert.Empty(t, cmp.Diff(test.expectedMirrorPod, actualPod), "actualPod and expectShouldBeMirrorPod differ")
231+
232+
actualPod, actualMirrorPod, isMirrorPod := podManager.GetPodAndMirrorPod(test.wantPod)
233+
assert.Equal(t, test.isMirrorPod, isMirrorPod)
234+
assert.Empty(t, cmp.Diff(test.expectPod, actualPod), "actualPod and expectGetPod differ")
235+
assert.Empty(t, cmp.Diff(test.expectedMirrorPod, actualMirrorPod), "actualMirrorPod and shouldBeMirrorPod differ")
236+
237+
isMirrorPod = IsMirrorPodOf(test.wantPod, mirrorPod)
238+
assert.Equal(t, test.isMirrorPod, isMirrorPod)
239+
240+
if test.isMirrorPod {
241+
actualPod, ok = podManager.GetPodByMirrorPod(test.wantPod)
242+
assert.Equal(t, test.expectedMirrorPod != nil, ok)
243+
assert.Empty(t, cmp.Diff(test.expectPod, actualPod), "actualPod by name and expectGetPod differ")
244+
}
245+
})
155246
}
247+
}
156248

157-
_, _, orphanedMirrorPodNames := podManager.GetPodsAndMirrorPods()
158-
expectedOrphanedMirrorPodNameNum := 1
159-
if len(orphanedMirrorPodNames) != expectedOrphanedMirrorPodNameNum {
160-
t.Fatalf("Run getOrphanedMirrorPodNames() error, expected %d orphaned mirror pods, got %d orphaned mirror pods; ", expectedOrphanedMirrorPodNameNum, len(orphanedMirrorPodNames))
249+
func TestRemovePods(t *testing.T) {
250+
testCase := []struct {
251+
name string
252+
podList []*v1.Pod
253+
needToRemovePod *v1.Pod
254+
expectPods []*v1.Pod
255+
expectMirrorPods []*v1.Pod
256+
expectOrphanedMirrorPodFullnames []string
257+
}{
258+
{
259+
name: "Remove mirror pod",
260+
podList: []*v1.Pod{mirrorPod, staticPod, normalPod},
261+
needToRemovePod: mirrorPod,
262+
expectPods: []*v1.Pod{normalPod, staticPod},
263+
expectMirrorPods: []*v1.Pod{},
264+
},
265+
{
266+
name: "Remove static pod",
267+
podList: []*v1.Pod{mirrorPod, staticPod, normalPod},
268+
needToRemovePod: staticPod,
269+
expectPods: []*v1.Pod{normalPod},
270+
expectMirrorPods: []*v1.Pod{mirrorPod},
271+
expectOrphanedMirrorPodFullnames: []string{"mirror-static-pod-name_default"},
272+
},
273+
{
274+
name: "Remove normal pod",
275+
podList: []*v1.Pod{mirrorPod, staticPod, normalPod},
276+
needToRemovePod: normalPod,
277+
expectPods: []*v1.Pod{staticPod},
278+
expectMirrorPods: []*v1.Pod{mirrorPod},
279+
},
161280
}
162281

163-
expectedOrphanedMirrorPodName := mirrorPod.Name + "_" + mirrorPod.Namespace
164-
if orphanedMirrorPodNames[0] != expectedOrphanedMirrorPodName {
165-
t.Fatalf("Run getOrphanedMirrorPodNames() error, expected orphaned mirror pod name : %s, got orphaned mirror pod name %s; ", expectedOrphanedMirrorPodName, orphanedMirrorPodNames[0])
282+
for _, test := range testCase {
283+
t.Run(test.name, func(t *testing.T) {
284+
podManager := NewBasicPodManager()
285+
podManager.SetPods(test.podList)
286+
podManager.RemovePod(test.needToRemovePod)
287+
actualPods1 := podManager.GetPods()
288+
actualPods2, actualMirrorPods, orphanedMirrorPodFullnames := podManager.GetPodsAndMirrorPods()
289+
// Check if the actual pods and mirror pods match the expected ones.
290+
assert.Empty(t, cmp.Diff(actualPods1, actualPods2, sortOpt), "actualPods by GetPods() and GetPodsAndMirrorPods() differ")
291+
assert.Empty(t, cmp.Diff(test.expectPods, actualPods1, sortOpt), "actualPods and expectPods differ")
292+
assert.Empty(t, cmp.Diff(test.expectMirrorPods, actualMirrorPods, sortOpt), "actualMirrorPods and expectMirrorPods differ")
293+
assert.Empty(t, cmp.Diff(test.expectOrphanedMirrorPodFullnames, orphanedMirrorPodFullnames), "orphanedMirrorPodFullnames and expectOrphanedMirrorPodFullnames differ")
294+
})
166295
}
167296
}

0 commit comments

Comments
 (0)