Skip to content

Commit 86038ae

Browse files
authored
Merge pull request kubernetes#116846 from moshe010/e2e--node-pod-resources
kubelet pod-resources: add e2e for KubeletPodResourcesGet feature
2 parents bc01306 + 3822201 commit 86038ae

File tree

1 file changed

+131
-31
lines changed

1 file changed

+131
-31
lines changed

test/e2e_node/podresources_test.go

Lines changed: 131 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -141,14 +141,9 @@ func logPodResources(podIdx int, pr *kubeletpodresourcesv1.PodResources) {
141141

142142
type podResMap map[string]map[string]kubeletpodresourcesv1.ContainerResources
143143

144-
func getPodResourcesValues(ctx context.Context, cli kubeletpodresourcesv1.PodResourcesListerClient) (podResMap, error) {
145-
resp, err := cli.List(ctx, &kubeletpodresourcesv1.ListPodResourcesRequest{})
146-
if err != nil {
147-
return nil, err
148-
}
149-
144+
func convertToMap(podsResources []*kubeletpodresourcesv1.PodResources) podResMap {
150145
res := make(map[string]map[string]kubeletpodresourcesv1.ContainerResources)
151-
for idx, podResource := range resp.GetPodResources() {
146+
for idx, podResource := range podsResources {
152147
// to make troubleshooting easier
153148
logPodResources(idx, podResource)
154149

@@ -158,7 +153,15 @@ func getPodResourcesValues(ctx context.Context, cli kubeletpodresourcesv1.PodRes
158153
}
159154
res[podResource.GetName()] = cnts
160155
}
161-
return res, nil
156+
return res
157+
}
158+
159+
func getPodResourcesValues(ctx context.Context, cli kubeletpodresourcesv1.PodResourcesListerClient) (podResMap, error) {
160+
resp, err := cli.List(ctx, &kubeletpodresourcesv1.ListPodResourcesRequest{})
161+
if err != nil {
162+
return nil, err
163+
}
164+
return convertToMap(resp.GetPodResources()), nil
162165
}
163166

164167
type testPodData struct {
@@ -293,7 +296,7 @@ func podresourcesListTests(ctx context.Context, f *framework.Framework, cli kube
293296
var err error
294297
ginkgo.By("checking the output when no pods are present")
295298
found, err = getPodResourcesValues(ctx, cli)
296-
framework.ExpectNoError(err)
299+
framework.ExpectNoError(err, "getPodResourcesValues() failed err: %v", err)
297300
gomega.ExpectWithOffset(1, found).To(gomega.HaveLen(expectedBasePods), "base pod expectation mismatch")
298301

299302
tpd = newTestPodData()
@@ -568,6 +571,53 @@ func podresourcesGetAllocatableResourcesTests(ctx context.Context, cli kubeletpo
568571
}
569572
}
570573

574+
func podresourcesGetTests(ctx context.Context, f *framework.Framework, cli kubeletpodresourcesv1.PodResourcesListerClient) {
575+
//var err error
576+
ginkgo.By("checking the output when no pods are present")
577+
expected := []podDesc{}
578+
resp, err := cli.Get(ctx, &kubeletpodresourcesv1.GetPodResourcesRequest{PodName: "test", PodNamespace: f.Namespace.Name})
579+
podResourceList := []*kubeletpodresourcesv1.PodResources{resp.GetPodResources()}
580+
framework.ExpectError(err, "pod not found")
581+
res := convertToMap(podResourceList)
582+
err = matchPodDescWithResources(expected, res)
583+
framework.ExpectNoError(err, "matchPodDescWithResources() failed err %v", err)
584+
585+
tpd := newTestPodData()
586+
ginkgo.By("checking the output when only pods which don't require resources are present")
587+
expected = []podDesc{
588+
{
589+
podName: "pod-00",
590+
cntName: "cnt-00",
591+
},
592+
}
593+
tpd.createPodsForTest(ctx, f, expected)
594+
resp, err = cli.Get(ctx, &kubeletpodresourcesv1.GetPodResourcesRequest{PodName: "pod-00", PodNamespace: f.Namespace.Name})
595+
framework.ExpectNoError(err, "Get() call failed for pod %s/%s", f.Namespace.Name, "pod-00")
596+
podResourceList = []*kubeletpodresourcesv1.PodResources{resp.GetPodResources()}
597+
res = convertToMap(podResourceList)
598+
err = matchPodDescWithResources(expected, res)
599+
framework.ExpectNoError(err, "matchPodDescWithResources() failed err %v", err)
600+
tpd.deletePodsForTest(ctx, f)
601+
602+
tpd = newTestPodData()
603+
ginkgo.By("checking the output when only pod require CPU")
604+
expected = []podDesc{
605+
{
606+
podName: "pod-01",
607+
cntName: "cnt-00",
608+
cpuRequest: 2000,
609+
},
610+
}
611+
tpd.createPodsForTest(ctx, f, expected)
612+
resp, err = cli.Get(ctx, &kubeletpodresourcesv1.GetPodResourcesRequest{PodName: "pod-01", PodNamespace: f.Namespace.Name})
613+
framework.ExpectNoError(err, "Get() call failed for pod %s/%s", f.Namespace.Name, "pod-01")
614+
podResourceList = []*kubeletpodresourcesv1.PodResources{resp.GetPodResources()}
615+
res = convertToMap(podResourceList)
616+
err = matchPodDescWithResources(expected, res)
617+
framework.ExpectNoError(err, "matchPodDescWithResources() failed err %v", err)
618+
tpd.deletePodsForTest(ctx, f)
619+
}
620+
571621
// Serial because the test updates kubelet configuration.
572622
var _ = SIGDescribe("POD Resources [Serial] [Feature:PodResources][NodeFeature:PodResources]", func() {
573623
f := framework.NewDefaultFramework("podresources-test")
@@ -606,7 +656,7 @@ var _ = SIGDescribe("POD Resources [Serial] [Feature:PodResources][NodeFeature:P
606656

607657
ginkgo.It("should return the expected responses", func(ctx context.Context) {
608658
onlineCPUs, err := getOnlineCPUs()
609-
framework.ExpectNoError(err)
659+
framework.ExpectNoError(err, "getOnlineCPUs() failed err: %v", err)
610660

611661
configMap := getSRIOVDevicePluginConfigMap(framework.TestContext.SriovdpConfigMapFile)
612662
sd := setupSRIOVConfigOrFail(ctx, f, configMap)
@@ -615,10 +665,10 @@ var _ = SIGDescribe("POD Resources [Serial] [Feature:PodResources][NodeFeature:P
615665
waitForSRIOVResources(ctx, f, sd)
616666

617667
endpoint, err := util.LocalEndpoint(defaultPodResourcesPath, podresources.Socket)
618-
framework.ExpectNoError(err)
668+
framework.ExpectNoError(err, "LocalEndpoint() failed err: %v", err)
619669

620670
cli, conn, err := podresources.GetV1Client(endpoint, defaultPodResourcesTimeout, defaultPodResourcesMaxSize)
621-
framework.ExpectNoError(err)
671+
framework.ExpectNoError(err, "GetV1Client() failed err: %v", err)
622672
defer conn.Close()
623673

624674
waitForSRIOVResources(ctx, f, sd)
@@ -644,10 +694,10 @@ var _ = SIGDescribe("POD Resources [Serial] [Feature:PodResources][NodeFeature:P
644694
waitForSRIOVResources(ctx, f, sd)
645695

646696
endpoint, err := util.LocalEndpoint(defaultPodResourcesPath, podresources.Socket)
647-
framework.ExpectNoError(err)
697+
framework.ExpectNoError(err, "LocalEndpoint() failed err: %v", err)
648698

649699
cli, conn, err := podresources.GetV1Client(endpoint, defaultPodResourcesTimeout, defaultPodResourcesMaxSize)
650-
framework.ExpectNoError(err)
700+
framework.ExpectNoError(err, "GetV1Client() failed err: %v", err)
651701
defer conn.Close()
652702

653703
waitForSRIOVResources(ctx, f, sd)
@@ -686,32 +736,37 @@ var _ = SIGDescribe("POD Resources [Serial] [Feature:PodResources][NodeFeature:P
686736
cpus := reservedSystemCPUs.String()
687737
framework.Logf("configurePodResourcesInKubelet: using reservedSystemCPUs=%q", cpus)
688738
initialConfig.ReservedSystemCPUs = cpus
739+
if initialConfig.FeatureGates == nil {
740+
initialConfig.FeatureGates = make(map[string]bool)
741+
}
742+
initialConfig.FeatureGates[string(kubefeatures.KubeletPodResourcesGet)] = true
689743
})
690744

691745
ginkgo.It("should return the expected responses", func(ctx context.Context) {
692746
onlineCPUs, err := getOnlineCPUs()
693-
framework.ExpectNoError(err)
747+
framework.ExpectNoError(err, "getOnlineCPUs() failed err: %v", err)
694748

695749
endpoint, err := util.LocalEndpoint(defaultPodResourcesPath, podresources.Socket)
696-
framework.ExpectNoError(err)
750+
framework.ExpectNoError(err, "LocalEndpoint() failed err: %v", err)
697751

698752
cli, conn, err := podresources.GetV1Client(endpoint, defaultPodResourcesTimeout, defaultPodResourcesMaxSize)
699-
framework.ExpectNoError(err)
753+
framework.ExpectNoError(err, "GetV1Client() failed err: %v", err)
700754
defer conn.Close()
701755

702756
podresourcesListTests(ctx, f, cli, nil)
703757
podresourcesGetAllocatableResourcesTests(ctx, cli, nil, onlineCPUs, reservedSystemCPUs)
758+
podresourcesGetTests(ctx, f, cli)
704759
})
705760
})
706761
})
707762

708763
ginkgo.Context("with CPU manager None policy", func() {
709764
ginkgo.It("should return the expected responses", func(ctx context.Context) {
710765
endpoint, err := util.LocalEndpoint(defaultPodResourcesPath, podresources.Socket)
711-
framework.ExpectNoError(err)
766+
framework.ExpectNoError(err, "LocalEndpoint() failed err: %v", err)
712767

713768
cli, conn, err := podresources.GetV1Client(endpoint, defaultPodResourcesTimeout, defaultPodResourcesMaxSize)
714-
framework.ExpectNoError(err)
769+
framework.ExpectNoError(err, "GetV1Client() failed err: %v", err)
715770
defer conn.Close()
716771

717772
// intentionally passing empty cpuset instead of onlineCPUs because with none policy
@@ -730,10 +785,10 @@ var _ = SIGDescribe("POD Resources [Serial] [Feature:PodResources][NodeFeature:P
730785

731786
ginkgo.It("should return the expected error with the feature gate disabled", func(ctx context.Context) {
732787
endpoint, err := util.LocalEndpoint(defaultPodResourcesPath, podresources.Socket)
733-
framework.ExpectNoError(err)
788+
framework.ExpectNoError(err, "LocalEndpoint() failed err: %v", err)
734789

735790
cli, conn, err := podresources.GetV1Client(endpoint, defaultPodResourcesTimeout, defaultPodResourcesMaxSize)
736-
framework.ExpectNoError(err)
791+
framework.ExpectNoError(err, "GetV1Client() failed err: %v", err)
737792
defer conn.Close()
738793

739794
ginkgo.By("checking GetAllocatableResources fail if the feature gate is not enabled")
@@ -742,6 +797,23 @@ var _ = SIGDescribe("POD Resources [Serial] [Feature:PodResources][NodeFeature:P
742797
framework.ExpectError(err, "With feature gate disabled, the call must fail")
743798
})
744799
})
800+
801+
ginkgo.Context("with disabled KubeletPodResourcesGet feature gate", func() {
802+
803+
ginkgo.It("should return the expected error with the feature gate disabled", func(ctx context.Context) {
804+
endpoint, err := util.LocalEndpoint(defaultPodResourcesPath, podresources.Socket)
805+
framework.ExpectNoError(err, "LocalEndpoint() faild err %v", err)
806+
807+
cli, conn, err := podresources.GetV1Client(endpoint, defaultPodResourcesTimeout, defaultPodResourcesMaxSize)
808+
framework.ExpectNoError(err, "GetV1Client() failed err %v", err)
809+
defer conn.Close()
810+
811+
ginkgo.By("checking Get fail if the feature gate is not enabled")
812+
getRes, err := cli.Get(ctx, &kubeletpodresourcesv1.GetPodResourcesRequest{PodName: "test", PodNamespace: f.Namespace.Name})
813+
framework.Logf("Get result: %v, err: %v", getRes, err)
814+
framework.ExpectError(err, "With feature gate disabled, the call must fail")
815+
})
816+
})
745817
})
746818

747819
ginkgo.Context("with a topology-unaware device plugin, which reports resources w/o hardware topology", func() {
@@ -776,10 +848,10 @@ var _ = SIGDescribe("POD Resources [Serial] [Feature:PodResources][NodeFeature:P
776848
waitForTopologyUnawareResources(ctx, f)
777849

778850
endpoint, err := util.LocalEndpoint(defaultPodResourcesPath, podresources.Socket)
779-
framework.ExpectNoError(err)
851+
framework.ExpectNoError(err, "LocalEndpoint() failed err: %v", err)
780852

781853
cli, conn, err := podresources.GetV1Client(endpoint, defaultPodResourcesTimeout, defaultPodResourcesMaxSize)
782-
framework.ExpectNoError(err)
854+
framework.ExpectNoError(err, "GetV1Client() failed err: %v", err)
783855
defer conn.Close()
784856

785857
ginkgo.By("checking List and resources topology unaware resource should be without topology")
@@ -824,20 +896,45 @@ var _ = SIGDescribe("POD Resources [Serial] [Feature:PodResources][NodeFeature:P
824896
})
825897

826898
ginkgo.Context("when querying /metrics [NodeConformance]", func() {
899+
tempSetCurrentKubeletConfig(f, func(ctx context.Context, initialConfig *kubeletconfig.KubeletConfiguration) {
900+
if initialConfig.FeatureGates == nil {
901+
initialConfig.FeatureGates = make(map[string]bool)
902+
}
903+
initialConfig.FeatureGates[string(kubefeatures.KubeletPodResourcesGet)] = true
904+
})
827905
ginkgo.BeforeEach(func(ctx context.Context) {
828906
// ensure APIs have been called at least once
829907
endpoint, err := util.LocalEndpoint(defaultPodResourcesPath, podresources.Socket)
830-
framework.ExpectNoError(err)
908+
framework.ExpectNoError(err, "LocalEndpoint() failed err %v", err)
831909

832910
cli, conn, err := podresources.GetV1Client(endpoint, defaultPodResourcesTimeout, defaultPodResourcesMaxSize)
833-
framework.ExpectNoError(err)
911+
framework.ExpectNoError(err, "GetV1Client() failed err %v", err)
834912
defer conn.Close()
835913

836914
_, err = cli.List(ctx, &kubeletpodresourcesv1.ListPodResourcesRequest{})
837-
framework.ExpectNoError(err)
915+
framework.ExpectNoError(err, "List() failed err %v", err)
838916

839917
_, err = cli.GetAllocatableResources(ctx, &kubeletpodresourcesv1.AllocatableResourcesRequest{})
840-
framework.ExpectNoError(err)
918+
framework.ExpectNoError(err, "GetAllocatableResources() failed err %v", err)
919+
920+
desc := podDesc{
921+
podName: "pod-01",
922+
cntName: "cnt-01",
923+
}
924+
tpd := newTestPodData()
925+
tpd.createPodsForTest(ctx, f, []podDesc{
926+
desc,
927+
})
928+
expectPodResources(ctx, 1, cli, []podDesc{desc})
929+
930+
expected := []podDesc{}
931+
resp, err := cli.Get(ctx, &kubeletpodresourcesv1.GetPodResourcesRequest{PodName: "pod-01", PodNamespace: f.Namespace.Name})
932+
framework.ExpectNoError(err, "Get() call failed for pod %s/%s", f.Namespace.Name, "pod-01")
933+
podResourceList := []*kubeletpodresourcesv1.PodResources{resp.GetPodResources()}
934+
res := convertToMap(podResourceList)
935+
err = matchPodDescWithResources(expected, res)
936+
framework.ExpectNoError(err, "matchPodDescWithResources() failed err %v", err)
937+
tpd.deletePodsForTest(ctx, f)
841938
})
842939

843940
ginkgo.It("should report the values for the podresources metrics", func(ctx context.Context) {
@@ -855,6 +952,9 @@ var _ = SIGDescribe("POD Resources [Serial] [Feature:PodResources][NodeFeature:P
855952
"kubelet_pod_resources_endpoint_requests_get_allocatable": gstruct.MatchAllElements(nodeID, gstruct.Elements{
856953
"": timelessSampleAtLeast(1),
857954
}),
955+
"kubelet_pod_resources_endpoint_requests_get": gstruct.MatchAllElements(nodeID, gstruct.Elements{
956+
"": timelessSampleAtLeast(1),
957+
}),
858958
// not checking errors: the calls don't have non-catastrophic (e.g. out of memory) error conditions yet.
859959
})
860960

@@ -869,11 +969,11 @@ var _ = SIGDescribe("POD Resources [Serial] [Feature:PodResources][NodeFeature:P
869969
ginkgo.It("should hit throttling when calling podresources List in a tight loop", func(ctx context.Context) {
870970
// ensure APIs have been called at least once
871971
endpoint, err := util.LocalEndpoint(defaultPodResourcesPath, podresources.Socket)
872-
framework.ExpectNoError(err)
972+
framework.ExpectNoError(err, "LocalEndpoint() failed err %v", err)
873973

874974
ginkgo.By("Connecting to the kubelet endpoint")
875975
cli, conn, err := podresources.GetV1Client(endpoint, defaultPodResourcesTimeout, defaultPodResourcesMaxSize)
876-
framework.ExpectNoError(err)
976+
framework.ExpectNoError(err, "GetV1Client() failed err %v", err)
877977
defer conn.Close()
878978

879979
tries := podresourcesgrpc.DefaultQPS * 2 // This should also be greater than DefaultBurstTokens
@@ -943,7 +1043,7 @@ func setupSampleDevicePluginOrFail(ctx context.Context, f *framework.Framework)
9431043
if err != nil {
9441044
framework.Logf("Sample Device Pod %v took too long to enter running/ready: %v", dp.Name, err)
9451045
}
946-
framework.ExpectNoError(err)
1046+
framework.ExpectNoError(err, "WaitForPodCondition() failed err: %v", err)
9471047

9481048
return dpPod
9491049
}
@@ -956,7 +1056,7 @@ func teardownSampleDevicePluginOrFail(ctx context.Context, f *framework.Framewor
9561056
ginkgo.By(fmt.Sprintf("Delete sample device plugin pod %s/%s", pod.Namespace, pod.Name))
9571057
err := f.ClientSet.CoreV1().Pods(pod.Namespace).Delete(ctx, pod.Name, deleteOptions)
9581058

959-
framework.ExpectNoError(err)
1059+
framework.ExpectNoError(err, "Failed to delete Pod %v in Namspace %v", pod.Name, pod.Namespace)
9601060
waitForAllContainerRemoval(ctx, pod.Name, pod.Namespace)
9611061
}
9621062

0 commit comments

Comments
 (0)