diff --git a/test/e2e/common/node/downwardapi.go b/test/e2e/common/node/downwardapi.go index 99fc8213590..1f1b32be914 100644 --- a/test/e2e/common/node/downwardapi.go +++ b/test/e2e/common/node/downwardapi.go @@ -25,6 +25,7 @@ import ( "k8s.io/apimachinery/pkg/util/uuid" "k8s.io/kubernetes/test/e2e/framework" e2enetwork "k8s.io/kubernetes/test/e2e/framework/network" + e2eskipper "k8s.io/kubernetes/test/e2e/framework/skipper" imageutils "k8s.io/kubernetes/test/utils/image" "github.com/onsi/ginkgo" @@ -283,6 +284,109 @@ var _ = SIGDescribe("Downward API", func() { }) }) +var _ = SIGDescribe("Downward API [Serial] [Disruptive] [NodeFeature:DownwardAPIHugePages]", func() { + f := framework.NewDefaultFramework("downward-api") + + ginkgo.Context("Downward API tests for hugepages", func() { + ginkgo.BeforeEach(func() { + e2eskipper.SkipUnlessDownwardAPIHugePagesEnabled() + }) + + ginkgo.It("should provide container's limits.hugepages- and requests.hugepages- as env vars", func() { + podName := "downward-api-" + string(uuid.NewUUID()) + env := []v1.EnvVar{ + { + Name: "HUGEPAGES_LIMIT", + ValueFrom: &v1.EnvVarSource{ + ResourceFieldRef: &v1.ResourceFieldSelector{ + Resource: "limits.hugepages-2Mi", + }, + }, + }, + { + Name: "HUGEPAGES_REQUEST", + ValueFrom: &v1.EnvVarSource{ + ResourceFieldRef: &v1.ResourceFieldSelector{ + Resource: "requests.hugepages-2Mi", + }, + }, + }, + } + + // Important: we explicitly request no hugepages so the test can run where none are present. + expectations := []string{ + fmt.Sprintf("HUGEPAGES_LIMIT=%d", 0), + fmt.Sprintf("HUGEPAGES_REQUEST=%d", 0), + } + pod := &v1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: podName, + Labels: map[string]string{"name": podName}, + }, + Spec: v1.PodSpec{ + Containers: []v1.Container{ + { + Name: "dapi-container", + Image: imageutils.GetE2EImage(imageutils.BusyBox), + Command: []string{"sh", "-c", "env"}, + Resources: v1.ResourceRequirements{ + Requests: v1.ResourceList{ + "cpu": resource.MustParse("10m"), + "hugepages-2Mi": resource.MustParse("0Mi"), + }, + Limits: v1.ResourceList{ + "hugepages-2Mi": resource.MustParse("0Mi"), + }, + }, + Env: env, + }, + }, + RestartPolicy: v1.RestartPolicyNever, + }, + } + testDownwardAPIUsingPod(f, pod, env, expectations) + }) + + ginkgo.It("should provide default limits.hugepages- from node allocatable", func() { + podName := "downward-api-" + string(uuid.NewUUID()) + env := []v1.EnvVar{ + { + Name: "HUGEPAGES_LIMIT", + ValueFrom: &v1.EnvVarSource{ + ResourceFieldRef: &v1.ResourceFieldSelector{ + Resource: "limits.hugepages-2Mi", + }, + }, + }, + } + // Important: we allow for 0 so the test passes in environments where no hugepages are allocated. + expectations := []string{ + "HUGEPAGES_LIMIT=((0)|([1-9][0-9]*))\n", + } + pod := &v1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: podName, + Labels: map[string]string{"name": podName}, + }, + Spec: v1.PodSpec{ + Containers: []v1.Container{ + { + Name: "dapi-container", + Image: imageutils.GetE2EImage(imageutils.BusyBox), + Command: []string{"sh", "-c", "env"}, + Env: env, + }, + }, + RestartPolicy: v1.RestartPolicyNever, + }, + } + + testDownwardAPIUsingPod(f, pod, env, expectations) + }) + }) + +}) + func testDownwardAPI(f *framework.Framework, podName string, env []v1.EnvVar, expectations []string) { pod := &v1.Pod{ ObjectMeta: metav1.ObjectMeta{ diff --git a/test/e2e/framework/skipper/skipper.go b/test/e2e/framework/skipper/skipper.go index 76d679649f7..265dd0afa6e 100644 --- a/test/e2e/framework/skipper/skipper.go +++ b/test/e2e/framework/skipper/skipper.go @@ -46,6 +46,8 @@ import ( // New local storage types to support local storage capacity isolation var localStorageCapacityIsolation featuregate.Feature = "LocalStorageCapacityIsolation" +var downwardAPIHugePages featuregate.Feature = "DownwardAPIHugePages" + func skipInternalf(caller int, format string, args ...interface{}) { msg := fmt.Sprintf(format, args...) framework.Logf(msg) @@ -137,6 +139,12 @@ func SkipUnlessLocalEphemeralStorageEnabled() { } } +func SkipUnlessDownwardAPIHugePagesEnabled() { + if !utilfeature.DefaultFeatureGate.Enabled(downwardAPIHugePages) { + skipInternalf(1, "Only supported when %v feature is enabled", downwardAPIHugePages) + } +} + // SkipIfMissingResource skips if the gvr resource is missing. func SkipIfMissingResource(dynamicClient dynamic.Interface, gvr schema.GroupVersionResource, namespace string) { resourceClient := dynamicClient.Resource(gvr).Namespace(namespace)