Skip to content

Commit 7a450b8

Browse files
committed
Add unit tests for AddPod()
1 parent 05a324b commit 7a450b8

File tree

1 file changed

+143
-0
lines changed

1 file changed

+143
-0
lines changed

pkg/kubelet/allocation/allocation_manager_test.go

Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -993,3 +993,146 @@ func makeAllocationManager(t *testing.T, runtime *containertest.FakeRuntime, all
993993

994994
return allocationManager
995995
}
996+
997+
// testPodAdmitHandler is a lifecycle.PodAdmitHandler for testing.
998+
type testPodAdmitHandler struct {
999+
// list of pods to reject.
1000+
podsToReject []*v1.Pod
1001+
}
1002+
1003+
// Admit rejects all pods in the podsToReject list with a matching UID.
1004+
func (a *testPodAdmitHandler) Admit(attrs *lifecycle.PodAdmitAttributes) lifecycle.PodAdmitResult {
1005+
for _, podToReject := range a.podsToReject {
1006+
if podToReject.UID == attrs.Pod.UID {
1007+
return lifecycle.PodAdmitResult{Admit: false, Reason: "Rejected", Message: "Pod is rejected"}
1008+
}
1009+
}
1010+
return lifecycle.PodAdmitResult{Admit: true}
1011+
}
1012+
1013+
func TestAllocationManagerAddPod(t *testing.T) {
1014+
if goruntime.GOOS == "windows" {
1015+
t.Skip("InPlacePodVerticalScaling is not currently supported for Windows")
1016+
}
1017+
featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.InPlacePodVerticalScaling, true)
1018+
1019+
const containerName = "c1"
1020+
1021+
basePod1 := &v1.Pod{
1022+
ObjectMeta: metav1.ObjectMeta{UID: "111", Name: "pod1", Namespace: "ns1"},
1023+
Spec: v1.PodSpec{Containers: []v1.Container{{Name: containerName, Image: "i1"}}},
1024+
}
1025+
basePod2 := &v1.Pod{
1026+
ObjectMeta: metav1.ObjectMeta{UID: "222", Name: "pod2", Namespace: "ns2"},
1027+
Spec: v1.PodSpec{Containers: []v1.Container{{Name: containerName, Image: "i2"}}},
1028+
}
1029+
1030+
cpu1Mem1G := v1.ResourceList{v1.ResourceCPU: resource.MustParse("1"), v1.ResourceMemory: resource.MustParse("1Gi")}
1031+
cpu2Mem2G := v1.ResourceList{v1.ResourceCPU: resource.MustParse("2"), v1.ResourceMemory: resource.MustParse("2Gi")}
1032+
1033+
newPodWithResources := func(basePod *v1.Pod, resources v1.ResourceList) *v1.Pod {
1034+
podCopy := basePod.DeepCopy()
1035+
podCopy.Spec.Containers[0].Resources = v1.ResourceRequirements{Requests: resources}
1036+
return podCopy
1037+
}
1038+
1039+
pod1v1 := newPodWithResources(basePod1, cpu1Mem1G) // Pod1 with 1 CPU and 1G Memory
1040+
pod1v2 := newPodWithResources(basePod1, cpu2Mem2G) // Pod1 with 2 CPU and 2G Memory
1041+
pod2v1 := newPodWithResources(basePod2, cpu1Mem1G) // Pod2 with 1 CPU and 1G Memory
1042+
1043+
testCases := []struct {
1044+
name string
1045+
initialAllocatedResourcesState map[types.UID]v1.ResourceList
1046+
activePods []*v1.Pod
1047+
podToAdd *v1.Pod
1048+
admitPod bool
1049+
expectedAllocatedResourcesState map[types.UID]v1.ResourceList
1050+
}{
1051+
{
1052+
name: "Pod added without resources changes",
1053+
initialAllocatedResourcesState: map[types.UID]v1.ResourceList{basePod1.UID: cpu1Mem1G, basePod2.UID: cpu1Mem1G},
1054+
activePods: []*v1.Pod{pod1v1, pod2v1},
1055+
podToAdd: pod1v1,
1056+
admitPod: true,
1057+
// exppected state is the same as initial state
1058+
expectedAllocatedResourcesState: map[types.UID]v1.ResourceList{basePod1.UID: cpu1Mem1G, basePod2.UID: cpu1Mem1G},
1059+
},
1060+
{
1061+
name: "Pod added with resources changes.",
1062+
initialAllocatedResourcesState: map[types.UID]v1.ResourceList{basePod1.UID: cpu1Mem1G, basePod2.UID: cpu1Mem1G},
1063+
activePods: []*v1.Pod{pod1v2, pod2v1},
1064+
podToAdd: pod1v2,
1065+
admitPod: true,
1066+
// Allocated Resources state must not be updated.
1067+
expectedAllocatedResourcesState: map[types.UID]v1.ResourceList{basePod1.UID: cpu1Mem1G, basePod2.UID: cpu1Mem1G},
1068+
},
1069+
{
1070+
name: "allocated resources updated when pod is admitted",
1071+
initialAllocatedResourcesState: map[types.UID]v1.ResourceList{basePod1.UID: cpu1Mem1G},
1072+
activePods: []*v1.Pod{pod1v1, pod2v1},
1073+
podToAdd: pod2v1,
1074+
admitPod: true,
1075+
// pod2's resources added to allocated resources
1076+
expectedAllocatedResourcesState: map[types.UID]v1.ResourceList{basePod1.UID: cpu1Mem1G, basePod2.UID: cpu1Mem1G},
1077+
},
1078+
{
1079+
name: "allocated resources not modified when pod is not admitted",
1080+
initialAllocatedResourcesState: map[types.UID]v1.ResourceList{basePod1.UID: cpu1Mem1G, basePod2.UID: cpu1Mem1G},
1081+
activePods: []*v1.Pod{pod1v1, pod2v1},
1082+
podToAdd: pod1v2,
1083+
admitPod: false,
1084+
// pod1's allocated resources not modified
1085+
expectedAllocatedResourcesState: map[types.UID]v1.ResourceList{basePod1.UID: cpu1Mem1G, basePod2.UID: cpu1Mem1G},
1086+
},
1087+
}
1088+
1089+
for _, tc := range testCases {
1090+
t.Run(tc.name, func(t *testing.T) {
1091+
allocationManager := makeAllocationManager(t, &containertest.FakeRuntime{}, []*v1.Pod{})
1092+
1093+
podForAllocation := func(uid types.UID, resources v1.ResourceList) *v1.Pod {
1094+
return &v1.Pod{
1095+
ObjectMeta: metav1.ObjectMeta{UID: uid},
1096+
Spec: v1.PodSpec{
1097+
Containers: []v1.Container{{
1098+
Name: containerName,
1099+
Resources: v1.ResourceRequirements{Requests: resources},
1100+
}},
1101+
},
1102+
}
1103+
}
1104+
1105+
for podUID, resources := range tc.initialAllocatedResourcesState {
1106+
err := allocationManager.SetAllocatedResources(podForAllocation(podUID, resources))
1107+
require.NoError(t, err)
1108+
}
1109+
1110+
if !tc.admitPod {
1111+
allocationManager.AddPodAdmitHandlers(lifecycle.PodAdmitHandlers{&testPodAdmitHandler{podsToReject: []*v1.Pod{tc.podToAdd}}})
1112+
}
1113+
ok, _, _ := allocationManager.AddPod(tc.activePods, tc.podToAdd)
1114+
require.Equal(t, tc.admitPod, ok)
1115+
1116+
for podUID, resources := range tc.expectedAllocatedResourcesState {
1117+
pod := podForAllocation(podUID, resources)
1118+
for _, container := range pod.Spec.Containers {
1119+
allocatedResources, found := allocationManager.GetContainerResourceAllocation(pod.UID, container.Name)
1120+
if pod.UID == tc.podToAdd.UID {
1121+
if tc.admitPod && !found {
1122+
t.Fatalf("resource allocation should exis for pod: %s", tc.podToAdd.Name)
1123+
}
1124+
if !tc.admitPod && found {
1125+
initialResources := tc.initialAllocatedResourcesState[pod.UID]
1126+
// allocated resources should not be modified when the pod is not admitted
1127+
assert.Equal(t, initialResources, allocatedResources.Requests, tc.name)
1128+
}
1129+
}
1130+
assert.Equal(t, container.Resources, allocatedResources, tc.name)
1131+
}
1132+
}
1133+
1134+
// Undo current modifications
1135+
allocationManager.RemovePod(tc.podToAdd.UID)
1136+
})
1137+
}
1138+
}

0 commit comments

Comments
 (0)