Merge pull request #134407 from natasha41575/ippr-tests

[InPlacePodVerticalScaling] add e2e coverage for pod resize 'read' and 'replace' endpoints
This commit is contained in:
Kubernetes Prow Robot 2025-10-16 16:54:39 -07:00 committed by GitHub
commit 5c7325dbda
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -24,8 +24,10 @@ import (
"time"
v1 "k8s.io/api/core/v1"
apiequality "k8s.io/apimachinery/pkg/api/equality"
"k8s.io/apimachinery/pkg/api/resource"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/types"
"k8s.io/kubernetes/pkg/features"
"k8s.io/kubernetes/test/e2e/common/node/framework/cgroups"
@ -35,6 +37,7 @@ import (
e2epod "k8s.io/kubernetes/test/e2e/framework/pod"
e2eskipper "k8s.io/kubernetes/test/e2e/framework/skipper"
"github.com/google/go-cmp/cmp"
"github.com/onsi/ginkgo/v2"
"github.com/onsi/gomega"
)
@ -301,7 +304,6 @@ func doBurstablePodResizeTests(f *framework.Framework) {
true,
),
)
}
func doPodResizePatchErrorTests(f *framework.Framework) {
@ -656,14 +658,93 @@ func doPodResizeMemoryLimitDecreaseTest(f *framework.Framework) {
})
}
// NOTE: Pod resize scheduler resource quota tests are out of scope in e2e_node tests,
// because in e2e_node tests
// a) scheduler and controller manager is not running by the Node e2e
// b) api-server in services doesn't start with --enable-admission-plugins=ResourceQuota
// and is not possible to start it from TEST_ARGS
// Above tests are performed by doSheduletTests() and doPodResizeResourceQuotaTests()
// in test/e2e/node/pod_resize.go
func doPodResizeReadAndReplaceTests(f *framework.Framework) {
// This test provides basic coverage for the `read` and `replace` endpoints.
// TODO: Promote to conformance prior to GA.
ginkgo.It("resize pod via the replace endpoint", func(ctx context.Context) {
podClient := e2epod.NewPodClient(f)
original := []podresize.ResizableContainerInfo{{
Name: "c1",
Resources: &cgroups.ContainerResources{CPUReq: originalCPU, MemReq: originalMem},
}}
desiredContainers := []podresize.ResizableContainerInfo{{
Name: "c1",
Resources: &cgroups.ContainerResources{CPUReq: increasedCPU, MemReq: increasedMem},
}}
desired := v1.ResourceRequirements{
Requests: v1.ResourceList{
v1.ResourceCPU: resource.MustParse(increasedCPU),
v1.ResourceMemory: resource.MustParse(increasedMem),
},
}
ginkgo.By("creating and verifying pod")
pod := createAndVerifyPod(ctx, f, podClient, original)
gomega.Expect(pod.Generation).To(gomega.BeEquivalentTo(1))
podToUpdate, err := podClient.Get(ctx, pod.Name, metav1.GetOptions{})
framework.ExpectNoError(err, "failed to get pod")
podToUpdate.Spec.Containers[0].Resources = desired
ginkgo.By("updating the pod resources")
_, err = podClient.UpdateResize(ctx, pod.Name, podToUpdate, metav1.UpdateOptions{})
framework.ExpectNoError(err, "failed to resize pod")
ginkgo.By("fetching updated pod")
updatedPod, err := podClient.Get(ctx, pod.Name, metav1.GetOptions{})
framework.ExpectNoError(err, "failed to get pod")
ginkgo.By("verifying pod resources")
podresize.VerifyPodResources(updatedPod, desiredContainers)
gomega.Expect(updatedPod.Generation).To(gomega.BeEquivalentTo(2))
ginkgo.By("verifying pod resources after patch")
expected := podresize.UpdateExpectedContainerRestarts(ctx, updatedPod, desiredContainers)
resizedPod := podresize.WaitForPodResizeActuation(ctx, f, podClient, updatedPod, expected)
podresize.ExpectPodResized(ctx, f, resizedPod, expected)
ginkgo.By("verifying pod fetched from resize subresource")
framework.ExpectNoError(framework.Gomega().
Eventually(ctx, framework.RetryNotFound(framework.GetObject(f.ClientSet.CoreV1().Pods(pod.Namespace).Get, pod.Name, metav1.GetOptions{}))).
WithTimeout(f.Timeouts.PodStart).
Should(framework.MakeMatcher(func(pod *v1.Pod) (func() string, error) {
// For some reason, the pod object returned from the client doesn't have the GVK populated.
pod.Kind = "Pod"
pod.APIVersion = "v1"
ginkgo.By("verifying pod fetched from resize subresource")
podResource := schema.GroupVersionResource{Group: "", Version: "v1", Resource: "pods"}
unstruct, err := f.DynamicClient.Resource(podResource).Namespace(f.Namespace.Name).Get(ctx, pod.Name, metav1.GetOptions{}, "resize")
if err != nil {
return func() string {
return fmt.Sprintf("failed to fetch pod after resize: %v", err.Error())
}, nil
}
updatedPodFromResize, err := unstructuredToPod(unstruct)
if err != nil {
return func() string {
return fmt.Sprintf("couldn't convert result to pod object: %v", err.Error())
}, nil
}
if !apiequality.Semantic.DeepEqual(pod, updatedPodFromResize) {
return func() string {
return fmt.Sprintf("pod from resize subresource not equivalent to pod; %s", cmp.Diff(pod, updatedPodFromResize))
}, nil
}
return nil, nil
})),
)
})
}
// NOTE: Pod resize scheduler, resource quota, limit ranger, deferred resize tests are out of scope in e2e_node tests,
//
// because in e2e_node tests
// a) scheduler and controller manager is not running by the Node e2e
// b) api-server in services doesn't start with --enable-admission-plugins=ResourceQuota
// and is not possible to start it from TEST_ARGS
// Above tests in test/e2e/node/pod_resize.go
var _ = SIGDescribe("Pod InPlace Resize Container", framework.WithFeatureGate(features.InPlacePodVerticalScaling), func() {
f := framework.NewDefaultFramework("pod-resize-tests")
@ -677,6 +758,7 @@ var _ = SIGDescribe("Pod InPlace Resize Container", framework.WithFeatureGate(fe
doGuaranteedPodResizeTests(f)
doBurstablePodResizeTests(f)
doPodResizeReadAndReplaceTests(f)
doPodResizePatchErrorTests(f)
doPodResizeMemoryLimitDecreaseTest(f)
})