Skip to content

Commit 57e9a05

Browse files
authored
Merge pull request #8684 from adrianmoisey/e2e-tests-feature-gate
Switch e2e test with feature flag to use framework.WithFeatureGate
2 parents 09818ce + 9c0332a commit 57e9a05

File tree

6 files changed

+101
-75
lines changed

6 files changed

+101
-75
lines changed

vertical-pod-autoscaler/e2e/v1/admission_controller.go

Lines changed: 57 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,10 @@ import (
2525

2626
apiv1 "k8s.io/api/core/v1"
2727
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
28+
utilfeature "k8s.io/apiserver/pkg/util/feature"
2829
"k8s.io/autoscaler/vertical-pod-autoscaler/e2e/utils"
2930
vpa_types "k8s.io/autoscaler/vertical-pod-autoscaler/pkg/apis/autoscaling.k8s.io/v1"
31+
"k8s.io/autoscaler/vertical-pod-autoscaler/pkg/features"
3032
"k8s.io/autoscaler/vertical-pod-autoscaler/pkg/utils/test"
3133
"k8s.io/kubernetes/test/e2e/framework"
3234
podsecurity "k8s.io/pod-security-admission/api"
@@ -35,20 +37,28 @@ import (
3537
"github.com/onsi/gomega"
3638
)
3739

40+
func init() {
41+
// Dynamically register feature gates from the VPA's versioned feature gate configuration
42+
// This ensures consistency with the main VPA feature gate definitions
43+
if err := utilfeature.DefaultMutableFeatureGate.Add(features.MutableFeatureGate.GetAll()); err != nil {
44+
panic(fmt.Sprintf("Failed to add VPA feature gates: %v", err))
45+
}
46+
}
47+
3848
const (
3949
webhookConfigName = "vpa-webhook-config"
4050
webhookName = "vpa.k8s.io"
4151
)
4252

43-
var _ = AdmissionControllerE2eDescribe("Admission-controller", ginkgo.Label("FG:InPlaceOrRecreate"), func() {
53+
var _ = AdmissionControllerE2eDescribe("Admission-controller", func() {
4454
f := framework.NewDefaultFramework("vertical-pod-autoscaling")
4555
f.NamespacePodSecurityEnforceLevel = podsecurity.LevelBaseline
4656

4757
ginkgo.BeforeEach(func() {
4858
waitForVpaWebhookRegistration(f)
4959
})
5060

51-
ginkgo.It("starts pods with new recommended request with InPlaceOrRecreate mode", func() {
61+
f.It("starts pods with new recommended request with InPlaceOrRecreate mode", framework.WithFeatureGate(features.InPlaceOrRecreate), func() {
5262
d := NewHamsterDeploymentWithResources(f, ParseQuantityOrDie("100m") /*cpu*/, ParseQuantityOrDie("100Mi") /*memory*/)
5363

5464
ginkgo.By("Setting up a VPA CRD")
@@ -878,33 +888,49 @@ var _ = AdmissionControllerE2eDescribe("Admission-controller", ginkgo.Label("FG:
878888
expectedErr string
879889
}{
880890
{
881-
name: "Invalid oomBumpUpRatio (negative value)",
891+
name: "Invalid minAllowed (invalid requests field)",
882892
vpaJSON: `{
883893
"apiVersion": "autoscaling.k8s.io/v1",
884894
"kind": "VerticalPodAutoscaler",
885-
"metadata": {"name": "oom-test-vpa"},
895+
"metadata": {"name": "hamster-vpa-invalid"},
886896
"spec": {
887897
"targetRef": {
888898
"apiVersion": "apps/v1",
889899
"kind": "Deployment",
890-
"name": "oom-test"
891-
},
892-
"updatePolicy": {
893-
"updateMode": "Auto"
900+
"name": "hamster"
894901
},
895902
"resourcePolicy": {
896903
"containerPolicies": [{
897904
"containerName": "*",
898-
"oomBumpUpRatio": -1,
899-
"oomMinBumpUp": 104857600
905+
"minAllowed": {
906+
"requests": {
907+
"cpu": "50m"
908+
}
909+
}
900910
}]
901911
}
902912
}
903913
}`,
904-
expectedErr: "spec.resourcePolicy.containerPolicies[0].oomBumpUpRatio: Invalid value: -1: spec.resourcePolicy.containerPolicies[0].oomBumpUpRatio in body should be greater than or equal to 1",
914+
expectedErr: "admission webhook .*vpa.* denied the request:",
905915
},
916+
}
917+
for _, tc := range testCases {
918+
ginkgo.By(fmt.Sprintf("Testing %s", tc.name))
919+
err := InstallRawVPA(f, []byte(tc.vpaJSON))
920+
gomega.Expect(err).To(gomega.HaveOccurred(), "Invalid VPA object accepted")
921+
gomega.Expect(err.Error()).To(gomega.MatchRegexp(tc.expectedErr))
922+
}
923+
})
924+
925+
f.It("accepts valid and rejects invalid VPA object with features.PerVPAConfig enabled", framework.WithFeatureGate(features.PerVPAConfig), func() {
926+
ginkgo.By("Setting up invalid VPA objects")
927+
testCases := []struct {
928+
name string
929+
vpaJSON string
930+
expectedErr string
931+
}{
906932
{
907-
name: "Invalid oomBumpUpRatio (string value)",
933+
name: "Invalid oomBumpUpRatio (negative value)",
908934
vpaJSON: `{
909935
"apiVersion": "autoscaling.k8s.io/v1",
910936
"kind": "VerticalPodAutoscaler",
@@ -921,16 +947,16 @@ var _ = AdmissionControllerE2eDescribe("Admission-controller", ginkgo.Label("FG:
921947
"resourcePolicy": {
922948
"containerPolicies": [{
923949
"containerName": "*",
924-
"oomBumpUpRatio": "12",
950+
"oomBumpUpRatio": -1,
925951
"oomMinBumpUp": 104857600
926952
}]
927953
}
928954
}
929955
}`,
930-
expectedErr: "json: cannot unmarshal string into Go struct field ContainerResourcePolicy.spec.resourcePolicy.containerPolicies.oomBumpUpRatio of type float64",
956+
expectedErr: "admission webhook \"vpa.k8s.io\" denied the request: oomBumpUpRatio must be greater than or equal to 1.0, got -1",
931957
},
932958
{
933-
name: "Invalid oomBumpUpRatio (less than 1)",
959+
name: "Invalid oomBumpUpRatio (string value)",
934960
vpaJSON: `{
935961
"apiVersion": "autoscaling.k8s.io/v1",
936962
"kind": "VerticalPodAutoscaler",
@@ -947,16 +973,16 @@ var _ = AdmissionControllerE2eDescribe("Admission-controller", ginkgo.Label("FG:
947973
"resourcePolicy": {
948974
"containerPolicies": [{
949975
"containerName": "*",
950-
"oomBumpUpRatio": 0.5,
976+
"oomBumpUpRatio": "not-a-number",
951977
"oomMinBumpUp": 104857600
952978
}]
953979
}
954980
}
955981
}`,
956-
expectedErr: "spec.resourcePolicy.containerPolicies[0].oomBumpUpRatio: Invalid value: 0.5: spec.resourcePolicy.containerPolicies[0].oomBumpUpRatio in body should be greater than or equal to 1",
982+
expectedErr: "admission webhook \"vpa\\.k8s\\.io\" denied the request: quantities must match the regular expression",
957983
},
958984
{
959-
name: "Invalid oomMinBumpUp (negative value)",
985+
name: "Invalid oomBumpUpRatio (less than 1)",
960986
vpaJSON: `{
961987
"apiVersion": "autoscaling.k8s.io/v1",
962988
"kind": "VerticalPodAutoscaler",
@@ -973,45 +999,45 @@ var _ = AdmissionControllerE2eDescribe("Admission-controller", ginkgo.Label("FG:
973999
"resourcePolicy": {
9741000
"containerPolicies": [{
9751001
"containerName": "*",
976-
"oomBumpUpRatio": 2,
977-
"oomMinBumpUp": -1
1002+
"oomBumpUpRatio": 0.5,
1003+
"oomMinBumpUp": 104857600
9781004
}]
9791005
}
9801006
}
9811007
}`,
982-
expectedErr: "spec.resourcePolicy.containerPolicies[0].oomMinBumpUp: Invalid value: -1: spec.resourcePolicy.containerPolicies[0].oomMinBumpUp in body should be greater than or equal to 0",
1008+
expectedErr: "admission webhook \"vpa.k8s.io\" denied the request: oomBumpUpRatio must be greater than or equal to 1.0, got 0.5",
9831009
},
9841010
{
985-
name: "Invalid minAllowed (invalid requests field)",
1011+
name: "Invalid oomMinBumpUp (negative value)",
9861012
vpaJSON: `{
9871013
"apiVersion": "autoscaling.k8s.io/v1",
9881014
"kind": "VerticalPodAutoscaler",
989-
"metadata": {"name": "hamster-vpa-invalid"},
1015+
"metadata": {"name": "oom-test-vpa"},
9901016
"spec": {
9911017
"targetRef": {
9921018
"apiVersion": "apps/v1",
9931019
"kind": "Deployment",
994-
"name": "hamster"
1020+
"name": "oom-test"
1021+
},
1022+
"updatePolicy": {
1023+
"updateMode": "Auto"
9951024
},
9961025
"resourcePolicy": {
9971026
"containerPolicies": [{
9981027
"containerName": "*",
999-
"minAllowed": {
1000-
"requests": {
1001-
"cpu": "50m"
1002-
}
1003-
}
1028+
"oomBumpUpRatio": 2,
1029+
"oomMinBumpUp": -1
10041030
}]
10051031
}
10061032
}
10071033
}`,
1008-
expectedErr: "admission webhook .*vpa.* denied the request:",
1034+
expectedErr: "admission webhook \"vpa.k8s.io\" denied the request: oomMinBumpUp must be greater than or equal to 0, got -1 bytes",
10091035
},
10101036
}
10111037
for _, tc := range testCases {
10121038
ginkgo.By(fmt.Sprintf("Testing %s", tc.name))
10131039
err := InstallRawVPA(f, []byte(tc.vpaJSON))
1014-
gomega.Expect(err).To(gomega.HaveOccurred(), "Invalid VPA object accepted")
1040+
gomega.Expect(err).To(gomega.HaveOccurred(), fmt.Sprintf("Invalid VPA object accepted, name: \"%s\"", tc.name))
10151041
gomega.Expect(err.Error()).To(gomega.MatchRegexp(tc.expectedErr))
10161042
}
10171043
})

vertical-pod-autoscaler/e2e/v1/common.go

Lines changed: 0 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ import (
2020
"context"
2121
"encoding/json"
2222
"fmt"
23-
"strings"
2423
"time"
2524

2625
ginkgo "github.com/onsi/ginkgo/v2"
@@ -37,7 +36,6 @@ import (
3736
"k8s.io/autoscaler/vertical-pod-autoscaler/e2e/utils"
3837
vpa_types "k8s.io/autoscaler/vertical-pod-autoscaler/pkg/apis/autoscaling.k8s.io/v1"
3938
vpa_clientset "k8s.io/autoscaler/vertical-pod-autoscaler/pkg/client/clientset/versioned"
40-
"k8s.io/autoscaler/vertical-pod-autoscaler/pkg/features"
4139
clientset "k8s.io/client-go/kubernetes"
4240
"k8s.io/kubernetes/test/e2e/framework"
4341
framework_deployment "k8s.io/kubernetes/test/e2e/framework/deployment"
@@ -468,26 +466,3 @@ func WaitForPodsUpdatedWithoutEviction(f *framework.Framework, initialPods *apiv
468466
framework.Logf("finished waiting for at least one pod to be updated without eviction")
469467
return err
470468
}
471-
472-
// checkPerVPAConfigTestsEnabled checks if the PerVPAConfig feature gate is enabled
473-
// in the VPA recommender.
474-
func checkPerVPAConfigTestsEnabled(f *framework.Framework) {
475-
ginkgo.By("Checking PerVPAConfig feature gate is enabled for recommender")
476-
deploy, err := f.ClientSet.AppsV1().Deployments(VpaNamespace).Get(context.TODO(), "vpa-recommender", metav1.GetOptions{})
477-
gomega.Expect(err).NotTo(gomega.HaveOccurred())
478-
gomega.Expect(deploy.Spec.Template.Spec.Containers).To(gomega.HaveLen(1))
479-
vpaRecommenderPod := deploy.Spec.Template.Spec.Containers[0]
480-
gomega.Expect(vpaRecommenderPod.Name).To(gomega.Equal("recommender"))
481-
if !anyContainsSubstring(vpaRecommenderPod.Args, fmt.Sprintf("%s=true", string(features.PerVPAConfig))) {
482-
ginkgo.Skip("Skipping suite: PerVPAConfig feature gate is not enabled for the VPA recommender")
483-
}
484-
}
485-
486-
func anyContainsSubstring(arr []string, substr string) bool {
487-
for _, s := range arr {
488-
if strings.Contains(s, substr) {
489-
return true
490-
}
491-
}
492-
return false
493-
}

vertical-pod-autoscaler/e2e/v1/full_vpa.go

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,10 @@ import (
2626
"k8s.io/apimachinery/pkg/api/resource"
2727
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
2828
"k8s.io/apimachinery/pkg/util/wait"
29+
utilfeature "k8s.io/apiserver/pkg/util/feature"
2930
"k8s.io/autoscaler/vertical-pod-autoscaler/e2e/utils"
3031
vpa_types "k8s.io/autoscaler/vertical-pod-autoscaler/pkg/apis/autoscaling.k8s.io/v1"
32+
"k8s.io/autoscaler/vertical-pod-autoscaler/pkg/features"
3133
"k8s.io/autoscaler/vertical-pod-autoscaler/pkg/utils/test"
3234
"k8s.io/kubernetes/test/e2e/framework"
3335
podsecurity "k8s.io/pod-security-admission/api"
@@ -47,6 +49,14 @@ const (
4749
oomTestTimeout = 8 * time.Minute
4850
)
4951

52+
func init() {
53+
// Dynamically register feature gates from the VPA's versioned feature gate configuration
54+
// This ensures consistency with the main VPA feature gate definitions
55+
if err := utilfeature.DefaultMutableFeatureGate.Add(features.MutableFeatureGate.GetAll()); err != nil {
56+
panic(fmt.Sprintf("Failed to add VPA feature gates: %v", err))
57+
}
58+
}
59+
5060
var _ = FullVpaE2eDescribe("Pods under VPA", func() {
5161
var (
5262
rc *ResourceConsumer
@@ -62,7 +72,7 @@ var _ = FullVpaE2eDescribe("Pods under VPA", func() {
6272
f := framework.NewDefaultFramework("vertical-pod-autoscaling")
6373
f.NamespacePodSecurityEnforceLevel = podsecurity.LevelBaseline
6474

65-
ginkgo.Describe("with InPlaceOrRecreate update mode", ginkgo.Label("FG:InPlaceOrRecreate"), func() {
75+
f.Describe("with InPlaceOrRecreate update mode", framework.WithFeatureGate(features.InPlaceOrRecreate), func() {
6676
ginkgo.BeforeEach(func() {
6777
ns := f.Namespace.Name
6878
ginkgo.By("Setting up a hamster deployment")

vertical-pod-autoscaler/e2e/v1/recommender.go

Lines changed: 18 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,11 @@ import (
2929
"k8s.io/apimachinery/pkg/api/resource"
3030
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
3131
"k8s.io/apimachinery/pkg/fields"
32+
utilfeature "k8s.io/apiserver/pkg/util/feature"
3233
"k8s.io/autoscaler/vertical-pod-autoscaler/e2e/utils"
3334
vpa_types "k8s.io/autoscaler/vertical-pod-autoscaler/pkg/apis/autoscaling.k8s.io/v1"
3435
vpa_clientset "k8s.io/autoscaler/vertical-pod-autoscaler/pkg/client/clientset/versioned"
36+
"k8s.io/autoscaler/vertical-pod-autoscaler/pkg/features"
3537
"k8s.io/autoscaler/vertical-pod-autoscaler/pkg/recommender/model"
3638
"k8s.io/autoscaler/vertical-pod-autoscaler/pkg/utils/test"
3739
clientset "k8s.io/client-go/kubernetes"
@@ -41,6 +43,14 @@ import (
4143
podsecurity "k8s.io/pod-security-admission/api"
4244
)
4345

46+
func init() {
47+
// Dynamically register feature gates from the VPA's versioned feature gate configuration
48+
// This ensures consistency with the main VPA feature gate definitions
49+
if err := utilfeature.DefaultMutableFeatureGate.Add(features.MutableFeatureGate.GetAll()); err != nil {
50+
panic(fmt.Sprintf("Failed to add VPA feature gates: %v", err))
51+
}
52+
}
53+
4454
type resourceRecommendation struct {
4555
target, lower, upper int64
4656
}
@@ -51,7 +61,6 @@ func (r *resourceRecommendation) sub(other *resourceRecommendation) resourceReco
5161
lower: r.lower - other.lower,
5262
upper: r.upper - other.upper,
5363
}
54-
5564
}
5665

5766
func getResourceRecommendation(containerRecommendation *vpa_types.RecommendedContainerResources, r apiv1.ResourceName) resourceRecommendation {
@@ -411,45 +420,37 @@ var _ = utils.RecommenderE2eDescribe("VPA CRD object", func() {
411420
gomega.Expect(vpa.Status.Recommendation.ContainerRecommendations).Should(gomega.HaveLen(1), errMsg)
412421
gomega.Expect(vpa.Status.Recommendation.ContainerRecommendations[0].ContainerName).To(gomega.Equal(utils.GetHamsterContainerNameByIndex(1)), errMsg)
413422
})
414-
})
423+
f.It("have memory requests growing with OOMs more than the default", framework.WithFeatureGate(features.PerVPAConfig), func() {
424+
const replicas = 1
425+
const defaultOOMBumpUpRatio = model.DefaultOOMBumpUpRatio
426+
const oomBumpUpRatio = 3
415427

416-
var _ = utils.RecommenderE2eDescribe("OOM with custom config", ginkgo.Label("FG:PerVPAConfig"), func() {
417-
const replicas = 1
418-
const defaultOOMBumpUpRatio = model.DefaultOOMBumpUpRatio
419-
const oomBumpUpRatio = 3
420-
f := framework.NewDefaultFramework("vertical-pod-autoscaling")
421-
f.NamespacePodSecurityEnforceLevel = podsecurity.LevelBaseline
422-
var (
423-
vpaCRD *vpa_types.VerticalPodAutoscaler
424-
vpaClientSet vpa_clientset.Interface
425-
)
426-
ginkgo.BeforeEach(func() {
427-
checkPerVPAConfigTestsEnabled(f)
428428
ns := f.Namespace.Name
429429
vpaClientSet = utils.GetVpaClientSet(f)
430+
430431
ginkgo.By("Setting up a hamster deployment")
431432
runOomingReplicationController(
432433
f.ClientSet,
433434
ns,
434435
"hamster",
435436
replicas)
437+
436438
ginkgo.By("Setting up a VPA CRD")
437439
targetRef := &autoscaling.CrossVersionObjectReference{
438440
APIVersion: "v1",
439441
Kind: "Deployment",
440442
Name: "hamster",
441443
}
442444
containerName := utils.GetHamsterContainerNameByIndex(0)
443-
vpaCRD = test.VerticalPodAutoscaler().
445+
vpaCRD := test.VerticalPodAutoscaler().
444446
WithName("hamster-vpa").
445447
WithNamespace(f.Namespace.Name).
446448
WithTargetRef(targetRef).
447449
WithContainer(containerName).
448450
WithOOMBumpUpRatio(resource.NewQuantity(oomBumpUpRatio, resource.DecimalSI)).
449451
Get()
450452
utils.InstallVPA(f, vpaCRD)
451-
})
452-
ginkgo.It("have memory requests growing with OOMs more than the default", func() {
453+
453454
ginkgo.By("Waiting for recommendation to be filled")
454455
vpa, err := utils.WaitForRecommendationPresent(vpaClientSet, vpaCRD)
455456
gomega.Expect(err).NotTo(gomega.HaveOccurred())

vertical-pod-autoscaler/hack/run-e2e-locally.sh

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,14 @@ echo " loading image into kind"
8787
kind load docker-image localhost:5001/write-metrics:dev
8888

8989

90+
export FEATURE_GATES=""
91+
export TEST_WITH_FEATURE_GATES_ENABLED=""
92+
93+
if [ "${ENABLE_ALL_FEATURE_GATES:-}" == "true" ] ; then
94+
export FEATURE_GATES='AllAlpha=true,AllBeta=true'
95+
export TEST_WITH_FEATURE_GATES_ENABLED="true"
96+
fi
97+
9098
case ${SUITE} in
9199
recommender|recommender-externalmetrics|updater|admission-controller|actuation|full-vpa)
92100
${SCRIPT_ROOT}/hack/vpa-down.sh

0 commit comments

Comments
 (0)