From e87016cf9416041fcec182bbd6fdc491beb8b2a6 Mon Sep 17 00:00:00 2001 From: Jordan Liggitt Date: Wed, 30 Jun 2021 11:24:31 -0400 Subject: [PATCH] PodSecurity: add ability to skip failure cases if relevant features are disabled --- staging/publishing/import-restrictions.yaml | 1 + .../src/k8s.io/pod-security-admission/go.mod | 1 + .../pod-security-admission/test/fixtures.go | 15 +++++++++++++++ .../k8s.io/pod-security-admission/test/run.go | 17 +++++++++++++++++ 4 files changed, 34 insertions(+) diff --git a/staging/publishing/import-restrictions.yaml b/staging/publishing/import-restrictions.yaml index b64fd49a6cc..003ffa2f32b 100644 --- a/staging/publishing/import-restrictions.yaml +++ b/staging/publishing/import-restrictions.yaml @@ -271,4 +271,5 @@ - k8s.io/client-go - k8s.io/klog - k8s.io/pod-security-admission + - k8s.io/component-base/featuregate - k8s.io/utils diff --git a/staging/src/k8s.io/pod-security-admission/go.mod b/staging/src/k8s.io/pod-security-admission/go.mod index d785f67723e..f65ee084445 100644 --- a/staging/src/k8s.io/pod-security-admission/go.mod +++ b/staging/src/k8s.io/pod-security-admission/go.mod @@ -11,6 +11,7 @@ require ( k8s.io/apimachinery v0.0.0 k8s.io/apiserver v0.0.0 k8s.io/client-go v0.0.0 + k8s.io/component-base v0.0.0 k8s.io/klog/v2 v2.9.0 k8s.io/utils v0.0.0-20210521133846-da695404a2bc sigs.k8s.io/yaml v1.2.0 diff --git a/staging/src/k8s.io/pod-security-admission/test/fixtures.go b/staging/src/k8s.io/pod-security-admission/test/fixtures.go index 2d32d4324a6..8ba2062fcb5 100644 --- a/staging/src/k8s.io/pod-security-admission/test/fixtures.go +++ b/staging/src/k8s.io/pod-security-admission/test/fixtures.go @@ -20,6 +20,7 @@ import ( "fmt" corev1 "k8s.io/api/core/v1" + "k8s.io/component-base/featuregate" "k8s.io/pod-security-admission/api" "k8s.io/pod-security-admission/policy" "k8s.io/utils/pointer" @@ -90,6 +91,13 @@ type fixtureGenerator struct { // expectErrorSubstring is a substring to expect in the error message for failed pods. // if empty, the check ID is used. expectErrorSubstring string + + // failRequiresFeatures lists feature gates that must all be enabled for failure cases to fail properly. + // This allows failure cases depending on rejecting data populated in alpha or beta fields to be skipped when those features are not enabled. + // If empty, failure test cases are always run. + // Pass cases are not allowed to be feature-gated (pass cases must only depend on data existing in GA fields). + failRequiresFeatures []featuregate.Feature + // generatePass transforms a minimum valid pod into one or more valid pods. // pods do not need to populate metadata.name. generatePass func(*corev1.Pod) []*corev1.Pod @@ -102,6 +110,12 @@ type fixtureGenerator struct { type fixtureData struct { expectErrorSubstring string + // failRequiresFeatures lists feature gates that must all be enabled for failure cases to fail properly. + // This allows failure cases depending on rejecting data populated in alpha or beta fields to be skipped when those features are not enabled. + // If empty, failure test cases are always run. + // Pass cases are not allowed to be feature-gated (pass cases must only depend on data existing in GA fields). + failRequiresFeatures []featuregate.Feature + pass []*corev1.Pod fail []*corev1.Pod } @@ -148,6 +162,7 @@ func getFixtures(key fixtureKey) (fixtureData, error) { if generator, exists := fixtureGenerators[key]; exists { data := fixtureData{ expectErrorSubstring: generator.expectErrorSubstring, + failRequiresFeatures: generator.failRequiresFeatures, pass: generator.generatePass(validPodForLevel.DeepCopy()), fail: generator.generateFail(validPodForLevel.DeepCopy()), diff --git a/staging/src/k8s.io/pod-security-admission/test/run.go b/staging/src/k8s.io/pod-security-admission/test/run.go index 61e6d28e36a..3a3ccb48870 100644 --- a/staging/src/k8s.io/pod-security-admission/test/run.go +++ b/staging/src/k8s.io/pod-security-admission/test/run.go @@ -30,6 +30,7 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/client-go/kubernetes" "k8s.io/client-go/rest" + "k8s.io/component-base/featuregate" "k8s.io/pod-security-admission/api" "k8s.io/pod-security-admission/policy" ) @@ -41,6 +42,11 @@ type Options struct { // Required. ClientConfig *rest.Config + // Features optionally provides information about which feature gates are enabled. + // This is used to skip failure cases for negative tests of data in alpha/beta fields. + // If unset, all testcases are run. + Features featuregate.FeatureGate + // CreateNamespace is an optional stub for creating a namespace with the given name and labels. // Returning an error fails the test. // If nil, DefaultCreateNamespace is used. @@ -278,7 +284,18 @@ func Run(t *testing.T, opts Options) { createController(t, i, pod, true, "") } }) + + // see if any features required for failure cases are disabled + var disabledRequiredFeatures []featuregate.Feature + for _, f := range checkData.failRequiresFeatures { + if opts.Features != nil && !opts.Features.Enabled(f) { + disabledRequiredFeatures = append(disabledRequiredFeatures, f) + } + } t.Run(ns+"_fail_"+checkID, func(t *testing.T) { + if len(disabledRequiredFeatures) > 0 { + t.Skipf("features required for failure cases are disabled: %v", disabledRequiredFeatures) + } for i, pod := range checkData.fail { createPod(t, i, pod, false, checkData.expectErrorSubstring) createController(t, i, pod, false, checkData.expectErrorSubstring)