e2e: support admissionapi.LevelRestricted in test/e2e/framwork/pod

CreatePod and MakePod only accepted an `isPrivileged` boolean, which made it
impossible to write tests using those helpers which work in a default
framework.Framework, because the default there is LevelRestricted.

The simple boolean gets replaced with admissionapi.Level. Passing
LevelRestricted does the same as calling e2epod.MixinRestrictedPodSecurity.

Instead of explicitly passing a constant to these modified helpers, most tests
get updated to pass f.NamespacePodSecurityLevel. This has the advantage
that if that level gets lowered in the future, tests only need to be updated in
one place.

In some cases, helpers taking client+namespace+timeouts parameters get replaced
with passing the Framework instance to get access to
f.NamespacePodSecurityEnforceLevel. These helpers don't need separate
parameters because in practice all they ever used where the values from the
Framework instance.
This commit is contained in:
Patrick Ohly 2023-05-19 17:37:53 +02:00
parent 8c33d3ef7b
commit c903c29c3b
24 changed files with 163 additions and 129 deletions

View File

@ -643,7 +643,7 @@ func (b *builder) parameters(kv ...string) *v1.ConfigMap {
// makePod returns a simple pod with no resource claims.
// The pod prints its env and waits.
func (b *builder) pod() *v1.Pod {
pod := e2epod.MakePod(b.f.Namespace.Name, nil, nil, false, "env && sleep 100000")
pod := e2epod.MakePod(b.f.Namespace.Name, nil, nil, b.f.NamespacePodSecurityLevel, "env && sleep 100000")
pod.Labels = make(map[string]string)
pod.Spec.RestartPolicy = v1.RestartPolicyNever
// Let kubelet kill the pods quickly. Setting

View File

@ -30,6 +30,7 @@ import (
"k8s.io/kubernetes/test/e2e/framework"
e2epod "k8s.io/kubernetes/test/e2e/framework/pod"
testutils "k8s.io/kubernetes/test/utils"
admissionapi "k8s.io/pod-security-admission/api"
)
// UpdateDeploymentWithRetries updates the specified deployment with retries.
@ -71,8 +72,8 @@ func NewDeployment(deploymentName string, replicas int32, podLabels map[string]s
}
// CreateDeployment creates a deployment.
func CreateDeployment(ctx context.Context, client clientset.Interface, replicas int32, podLabels map[string]string, nodeSelector map[string]string, namespace string, pvclaims []*v1.PersistentVolumeClaim, command string) (*appsv1.Deployment, error) {
deploymentSpec := testDeployment(replicas, podLabels, nodeSelector, namespace, pvclaims, false, command)
func CreateDeployment(ctx context.Context, client clientset.Interface, replicas int32, podLabels map[string]string, nodeSelector map[string]string, namespace string, pvclaims []*v1.PersistentVolumeClaim, securityLevel admissionapi.Level, command string) (*appsv1.Deployment, error) {
deploymentSpec := testDeployment(replicas, podLabels, nodeSelector, namespace, pvclaims, securityLevel, command)
deployment, err := client.AppsV1().Deployments(namespace).Create(ctx, deploymentSpec, metav1.CreateOptions{})
if err != nil {
return nil, fmt.Errorf("deployment %q Create API error: %w", deploymentSpec.Name, err)
@ -175,7 +176,7 @@ func (o replicaSetsByCreationTimestamp) Less(i, j int) bool {
// testDeployment creates a deployment definition based on the namespace. The deployment references the PVC's
// name. A slice of BASH commands can be supplied as args to be run by the pod
func testDeployment(replicas int32, podLabels map[string]string, nodeSelector map[string]string, namespace string, pvclaims []*v1.PersistentVolumeClaim, isPrivileged bool, command string) *appsv1.Deployment {
func testDeployment(replicas int32, podLabels map[string]string, nodeSelector map[string]string, namespace string, pvclaims []*v1.PersistentVolumeClaim, securityLevel admissionapi.Level, command string) *appsv1.Deployment {
if len(command) == 0 {
command = "trap exit TERM; while true; do sleep 1; done"
}
@ -202,7 +203,7 @@ func testDeployment(replicas int32, podLabels map[string]string, nodeSelector ma
Name: "write-pod",
Image: e2epod.GetDefaultTestImage(),
Command: e2epod.GenerateScriptCmd(command),
SecurityContext: e2epod.GenerateContainerSecurityContext(isPrivileged),
SecurityContext: e2epod.GenerateContainerSecurityContext(securityLevel),
},
},
RestartPolicy: v1.RestartPolicyAlways,

View File

@ -26,6 +26,7 @@ import (
"k8s.io/apimachinery/pkg/util/uuid"
clientset "k8s.io/client-go/kubernetes"
imageutils "k8s.io/kubernetes/test/utils/image"
admissionapi "k8s.io/pod-security-admission/api"
)
const (
@ -40,7 +41,7 @@ type Config struct {
PVCs []*v1.PersistentVolumeClaim
PVCsReadOnly bool
InlineVolumeSources []*v1.VolumeSource
IsPrivileged bool
SecurityLevel admissionapi.Level
Command string
HostIPC bool
HostPID bool
@ -52,8 +53,8 @@ type Config struct {
}
// CreateUnschedulablePod with given claims based on node selector
func CreateUnschedulablePod(ctx context.Context, client clientset.Interface, namespace string, nodeSelector map[string]string, pvclaims []*v1.PersistentVolumeClaim, isPrivileged bool, command string) (*v1.Pod, error) {
pod := MakePod(namespace, nodeSelector, pvclaims, isPrivileged, command)
func CreateUnschedulablePod(ctx context.Context, client clientset.Interface, namespace string, nodeSelector map[string]string, pvclaims []*v1.PersistentVolumeClaim, securityLevel admissionapi.Level, command string) (*v1.Pod, error) {
pod := MakePod(namespace, nodeSelector, pvclaims, securityLevel, command)
pod, err := client.CoreV1().Pods(namespace).Create(ctx, pod, metav1.CreateOptions{})
if err != nil {
return nil, fmt.Errorf("pod Create API error: %w", err)
@ -73,12 +74,12 @@ func CreateUnschedulablePod(ctx context.Context, client clientset.Interface, nam
// CreateClientPod defines and creates a pod with a mounted PV. Pod runs infinite loop until killed.
func CreateClientPod(ctx context.Context, c clientset.Interface, ns string, pvc *v1.PersistentVolumeClaim) (*v1.Pod, error) {
return CreatePod(ctx, c, ns, nil, []*v1.PersistentVolumeClaim{pvc}, true, "")
return CreatePod(ctx, c, ns, nil, []*v1.PersistentVolumeClaim{pvc}, admissionapi.LevelPrivileged, "")
}
// CreatePod with given claims based on node selector
func CreatePod(ctx context.Context, client clientset.Interface, namespace string, nodeSelector map[string]string, pvclaims []*v1.PersistentVolumeClaim, isPrivileged bool, command string) (*v1.Pod, error) {
pod := MakePod(namespace, nodeSelector, pvclaims, isPrivileged, command)
func CreatePod(ctx context.Context, client clientset.Interface, namespace string, nodeSelector map[string]string, pvclaims []*v1.PersistentVolumeClaim, securityLevel admissionapi.Level, command string) (*v1.Pod, error) {
pod := MakePod(namespace, nodeSelector, pvclaims, securityLevel, command)
pod, err := client.CoreV1().Pods(namespace).Create(ctx, pod, metav1.CreateOptions{})
if err != nil {
return nil, fmt.Errorf("pod Create API error: %w", err)
@ -128,7 +129,7 @@ func CreateSecPodWithNodeSelection(ctx context.Context, client clientset.Interfa
// MakePod returns a pod definition based on the namespace. The pod references the PVC's
// name. A slice of BASH commands can be supplied as args to be run by the pod
func MakePod(ns string, nodeSelector map[string]string, pvclaims []*v1.PersistentVolumeClaim, isPrivileged bool, command string) *v1.Pod {
func MakePod(ns string, nodeSelector map[string]string, pvclaims []*v1.PersistentVolumeClaim, securityLevel admissionapi.Level, command string) *v1.Pod {
if len(command) == 0 {
command = "trap exit TERM; while true; do sleep 1; done"
}
@ -147,7 +148,7 @@ func MakePod(ns string, nodeSelector map[string]string, pvclaims []*v1.Persisten
Name: "write-pod",
Image: GetDefaultTestImage(),
Command: GenerateScriptCmd(command),
SecurityContext: GenerateContainerSecurityContext(isPrivileged),
SecurityContext: GenerateContainerSecurityContext(securityLevel),
},
},
RestartPolicy: v1.RestartPolicyOnFailure,
@ -157,6 +158,10 @@ func MakePod(ns string, nodeSelector map[string]string, pvclaims []*v1.Persisten
if nodeSelector != nil {
podSpec.Spec.NodeSelector = nodeSelector
}
if securityLevel == admissionapi.LevelRestricted {
podSpec = MustMixinRestrictedPodSecurity(podSpec)
}
return podSpec
}
@ -196,6 +201,10 @@ func MakePodSpec(podConfig *Config) *v1.PodSpec {
if podConfig.ImageID != imageutils.None {
image = podConfig.ImageID
}
securityLevel := podConfig.SecurityLevel
if securityLevel == "" {
securityLevel = admissionapi.LevelBaseline
}
podSpec := &v1.PodSpec{
HostIPC: podConfig.HostIPC,
HostPID: podConfig.HostPID,
@ -205,7 +214,7 @@ func MakePodSpec(podConfig *Config) *v1.PodSpec {
Name: "write-pod",
Image: GetTestImage(image),
Command: GenerateScriptCmd(podConfig.Command),
SecurityContext: GenerateContainerSecurityContext(podConfig.IsPrivileged),
SecurityContext: GenerateContainerSecurityContext(securityLevel),
},
},
RestartPolicy: v1.RestartPolicyOnFailure,

View File

@ -20,6 +20,7 @@ import (
"flag"
"fmt"
"github.com/onsi/ginkgo/v2"
"github.com/onsi/gomega"
v1 "k8s.io/api/core/v1"
@ -111,12 +112,25 @@ func GeneratePodSecurityContext(fsGroup *int64, seLinuxOptions *v1.SELinuxOption
// GenerateContainerSecurityContext generates the corresponding container security context with the given inputs
// If the Node OS is windows, currently we will ignore the inputs and return nil.
// TODO: Will modify it after windows has its own security context
func GenerateContainerSecurityContext(privileged bool) *v1.SecurityContext {
func GenerateContainerSecurityContext(level psaapi.Level) *v1.SecurityContext {
if NodeOSDistroIs("windows") {
return nil
}
return &v1.SecurityContext{
Privileged: &privileged,
switch level {
case psaapi.LevelBaseline:
return &v1.SecurityContext{
Privileged: pointer.Bool(false),
}
case psaapi.LevelPrivileged:
return &v1.SecurityContext{
Privileged: pointer.Bool(true),
}
case psaapi.LevelRestricted:
return GetRestrictedContainerSecurityContext()
default:
ginkgo.Fail(fmt.Sprintf("unknown k8s.io/pod-security-admission/policy.Level %q", level))
panic("not reached")
}
}

View File

@ -59,6 +59,7 @@ import (
e2epod "k8s.io/kubernetes/test/e2e/framework/pod"
e2epodoutput "k8s.io/kubernetes/test/e2e/framework/pod/output"
imageutils "k8s.io/kubernetes/test/utils/image"
admissionapi "k8s.io/pod-security-admission/api"
uexec "k8s.io/utils/exec"
"github.com/onsi/ginkgo/v2"
@ -398,8 +399,9 @@ func runVolumeTesterPod(ctx context.Context, client clientset.Interface, timeout
When SELinux is enabled on the host, client-pod can not read the content, with permission denied.
Invoking client-pod as privileged, so that it can access the volume content, even when SELinux is enabled on the host.
*/
if config.Prefix == "hostpathsymlink" || config.Prefix == "hostpath" {
privileged = true
securityLevel := admissionapi.LevelBaseline // TODO (#118184): also support LevelRestricted
if privileged || config.Prefix == "hostpathsymlink" || config.Prefix == "hostpath" {
securityLevel = admissionapi.LevelPrivileged
}
command = "while true ; do sleep 2; done "
seLinuxOptions := &v1.SELinuxOptions{Level: "s0:c0,c1"}
@ -443,9 +445,9 @@ func runVolumeTesterPod(ctx context.Context, client clientset.Interface, timeout
// a privileged container, so we don't go privileged for block volumes.
// https://github.com/moby/moby/issues/35991
if privileged && test.Mode == v1.PersistentVolumeBlock {
privileged = false
securityLevel = admissionapi.LevelBaseline
}
clientPod.Spec.Containers[0].SecurityContext = e2epod.GenerateContainerSecurityContext(privileged)
clientPod.Spec.Containers[0].SecurityContext = e2epod.GenerateContainerSecurityContext(securityLevel)
if test.Mode == v1.PersistentVolumeBlock {
clientPod.Spec.Containers[0].VolumeDevices = append(clientPod.Spec.Containers[0].VolumeDevices, v1.VolumeDevice{

View File

@ -141,7 +141,7 @@ var _ = utils.SIGDescribe("[Feature:Flexvolumes] Mounted flexvolume expand[Slow]
framework.ExpectEqual(len(pvs), 1)
ginkgo.By("Creating a deployment with the provisioned volume")
deployment, err := e2edeployment.CreateDeployment(ctx, c, int32(1), map[string]string{"test": "app"}, nodeKeyValueLabel, ns, pvcClaims, "")
deployment, err := e2edeployment.CreateDeployment(ctx, c, int32(1), map[string]string{"test": "app"}, nodeKeyValueLabel, ns, pvcClaims, admissionapi.LevelRestricted, "")
framework.ExpectNoError(err, "Failed creating deployment %v", err)
ginkgo.DeferCleanup(c.AppsV1().Deployments(ns).Delete, deployment.Name, metav1.DeleteOptions{})

View File

@ -111,7 +111,7 @@ var _ = utils.SIGDescribe("Mounted volume expand [Feature:StorageProvider]", fun
// Keeping pod on same node reproduces the scenario that volume might already be mounted when resize is attempted.
// We should consider adding a unit test that exercises this better.
ginkgo.By("Creating a deployment with selected PVC")
deployment, err := e2edeployment.CreateDeployment(ctx, c, int32(1), map[string]string{"test": "app"}, nodeKeyValueLabel, ns, pvcClaims, "")
deployment, err := e2edeployment.CreateDeployment(ctx, c, int32(1), map[string]string{"test": "app"}, nodeKeyValueLabel, ns, pvcClaims, admissionapi.LevelRestricted, "")
framework.ExpectNoError(err, "Failed creating deployment %v", err)
ginkgo.DeferCleanup(c.AppsV1().Deployments(ns).Delete, deployment.Name, metav1.DeleteOptions{})

View File

@ -178,7 +178,7 @@ var _ = utils.SIGDescribe("NFSPersistentVolumes[Disruptive][Flaky]", func() {
framework.ExpectNoError(e2epv.WaitOnPVandPVC(ctx, c, f.Timeouts, ns, pv2, pvc2))
ginkgo.By("Attaching both PVC's to a single pod")
clientPod, err = e2epod.CreatePod(ctx, c, ns, nil, []*v1.PersistentVolumeClaim{pvc1, pvc2}, true, "")
clientPod, err = e2epod.CreatePod(ctx, c, ns, nil, []*v1.PersistentVolumeClaim{pvc1, pvc2}, f.NamespacePodSecurityLevel, "")
framework.ExpectNoError(err)
})
@ -301,7 +301,7 @@ func initTestCase(ctx context.Context, f *framework.Framework, c clientset.Inter
}
}()
framework.ExpectNoError(err)
pod := e2epod.MakePod(ns, nil, []*v1.PersistentVolumeClaim{pvc}, true, "")
pod := e2epod.MakePod(ns, nil, []*v1.PersistentVolumeClaim{pvc}, f.NamespacePodSecurityLevel, "")
pod.Spec.NodeName = nodeName
framework.Logf("Creating NFS client pod.")
pod, err = c.CoreV1().Pods(ns).Create(ctx, pod, metav1.CreateOptions{})

View File

@ -285,7 +285,7 @@ var _ = utils.SIGDescribe("PersistentVolumes", func() {
// (and test) succeed.
ginkgo.It("should test that a PV becomes Available and is clean after the PVC is deleted.", func(ctx context.Context) {
ginkgo.By("Writing to the volume.")
pod := e2epod.MakePod(ns, nil, []*v1.PersistentVolumeClaim{pvc}, true, "touch /mnt/volume1/SUCCESS && (id -G | grep -E '\\b777\\b')")
pod := e2epod.MakePod(ns, nil, []*v1.PersistentVolumeClaim{pvc}, f.NamespacePodSecurityLevel, "touch /mnt/volume1/SUCCESS && (id -G | grep -E '\\b777\\b')")
pod, err = c.CoreV1().Pods(ns).Create(ctx, pod, metav1.CreateOptions{})
framework.ExpectNoError(err)
framework.ExpectNoError(e2epod.WaitForPodSuccessInNamespaceTimeout(ctx, c, pod.Name, ns, f.Timeouts.PodStart))
@ -303,7 +303,7 @@ var _ = utils.SIGDescribe("PersistentVolumes", func() {
// If a file is detected in /mnt, fail the pod and do not restart it.
ginkgo.By("Verifying the mount has been cleaned.")
mount := pod.Spec.Containers[0].VolumeMounts[0].MountPath
pod = e2epod.MakePod(ns, nil, []*v1.PersistentVolumeClaim{pvc}, true, fmt.Sprintf("[ $(ls -A %s | wc -l) -eq 0 ] && exit 0 || exit 1", mount))
pod = e2epod.MakePod(ns, nil, []*v1.PersistentVolumeClaim{pvc}, f.NamespacePodSecurityLevel, fmt.Sprintf("[ $(ls -A %s | wc -l) -eq 0 ] && exit 0 || exit 1", mount))
pod, err = c.CoreV1().Pods(ns).Create(ctx, pod, metav1.CreateOptions{})
framework.ExpectNoError(err)
framework.ExpectNoError(e2epod.WaitForPodSuccessInNamespaceTimeout(ctx, c, pod.Name, ns, f.Timeouts.PodStart))
@ -447,7 +447,7 @@ func makeStatefulSetWithPVCs(ns, cmd string, mounts []v1.VolumeMount, claims []v
// Has been shown to be necessary using Go 1.7.
func createWaitAndDeletePod(ctx context.Context, c clientset.Interface, t *framework.TimeoutContext, ns string, pvc *v1.PersistentVolumeClaim, command string) (err error) {
framework.Logf("Creating nfs test pod")
pod := e2epod.MakePod(ns, nil, []*v1.PersistentVolumeClaim{pvc}, true, command)
pod := e2epod.MakePod(ns, nil, []*v1.PersistentVolumeClaim{pvc}, admissionapi.LevelPrivileged, command)
runPod, err := c.CoreV1().Pods(ns).Create(ctx, pod, metav1.CreateOptions{})
if err != nil {
return fmt.Errorf("pod Create API error: %w", err)

View File

@ -95,7 +95,7 @@ var _ = utils.SIGDescribe("PVC Protection", func() {
ginkgo.By("Creating a Pod that becomes Running and therefore is actively using the PVC")
pvcClaims := []*v1.PersistentVolumeClaim{pvc}
pod, err = e2epod.CreatePod(ctx, client, nameSpace, nil, pvcClaims, false, "")
pod, err = e2epod.CreatePod(ctx, client, nameSpace, nil, pvcClaims, f.NamespacePodSecurityLevel, "")
framework.ExpectNoError(err, "While creating pod that uses the PVC or waiting for the Pod to become Running")
ginkgo.By("Waiting for PVC to become Bound")
@ -156,7 +156,7 @@ var _ = utils.SIGDescribe("PVC Protection", func() {
framework.ExpectNotEqual(pvc.ObjectMeta.DeletionTimestamp, nil)
ginkgo.By("Creating second Pod whose scheduling fails because it uses a PVC that is being deleted")
secondPod, err2 := e2epod.CreateUnschedulablePod(ctx, client, nameSpace, nil, []*v1.PersistentVolumeClaim{pvc}, false, "")
secondPod, err2 := e2epod.CreateUnschedulablePod(ctx, client, nameSpace, nil, []*v1.PersistentVolumeClaim{pvc}, f.NamespacePodSecurityLevel, "")
framework.ExpectNoError(err2, "While creating second pod that uses a PVC that is being deleted and that is Unschedulable")
ginkgo.By("Deleting the second pod that uses the PVC that is being deleted")

View File

@ -35,7 +35,6 @@ var _ = utils.SIGDescribe("Subpath", func() {
ginkgo.Context("Atomic writer volumes", func() {
var err error
var privilegedSecurityContext bool = false
ginkgo.BeforeEach(func(ctx context.Context) {
ginkgo.By("Setting up data")
@ -58,7 +57,7 @@ var _ = utils.SIGDescribe("Subpath", func() {
Description: Containers in a pod can read content from a secret mounted volume which was configured with a subpath.
*/
framework.ConformanceIt("should support subpaths with secret pod", func(ctx context.Context) {
pod := testsuites.SubpathTestPod(f, "secret-key", "secret", &v1.VolumeSource{Secret: &v1.SecretVolumeSource{SecretName: "my-secret"}}, privilegedSecurityContext)
pod := testsuites.SubpathTestPod(f, "secret-key", "secret", &v1.VolumeSource{Secret: &v1.SecretVolumeSource{SecretName: "my-secret"}}, f.NamespacePodSecurityLevel)
testsuites.TestBasicSubpath(ctx, f, "secret-value", pod)
})
@ -68,7 +67,7 @@ var _ = utils.SIGDescribe("Subpath", func() {
Description: Containers in a pod can read content from a configmap mounted volume which was configured with a subpath.
*/
framework.ConformanceIt("should support subpaths with configmap pod", func(ctx context.Context) {
pod := testsuites.SubpathTestPod(f, "configmap-key", "configmap", &v1.VolumeSource{ConfigMap: &v1.ConfigMapVolumeSource{LocalObjectReference: v1.LocalObjectReference{Name: "my-configmap"}}}, privilegedSecurityContext)
pod := testsuites.SubpathTestPod(f, "configmap-key", "configmap", &v1.VolumeSource{ConfigMap: &v1.ConfigMapVolumeSource{LocalObjectReference: v1.LocalObjectReference{Name: "my-configmap"}}}, f.NamespacePodSecurityLevel)
testsuites.TestBasicSubpath(ctx, f, "configmap-value", pod)
})
@ -78,7 +77,7 @@ var _ = utils.SIGDescribe("Subpath", func() {
Description: Containers in a pod can read content from a configmap mounted volume which was configured with a subpath and also using a mountpath that is a specific file.
*/
framework.ConformanceIt("should support subpaths with configmap pod with mountPath of existing file", func(ctx context.Context) {
pod := testsuites.SubpathTestPod(f, "configmap-key", "configmap", &v1.VolumeSource{ConfigMap: &v1.ConfigMapVolumeSource{LocalObjectReference: v1.LocalObjectReference{Name: "my-configmap"}}}, privilegedSecurityContext)
pod := testsuites.SubpathTestPod(f, "configmap-key", "configmap", &v1.VolumeSource{ConfigMap: &v1.ConfigMapVolumeSource{LocalObjectReference: v1.LocalObjectReference{Name: "my-configmap"}}}, f.NamespacePodSecurityLevel)
file := "/etc/resolv.conf"
pod.Spec.Containers[0].VolumeMounts[0].MountPath = file
testsuites.TestBasicSubpathFile(ctx, f, "configmap-value", pod, file)
@ -94,7 +93,7 @@ var _ = utils.SIGDescribe("Subpath", func() {
DownwardAPI: &v1.DownwardAPIVolumeSource{
Items: []v1.DownwardAPIVolumeFile{{Path: "downward/podname", FieldRef: &v1.ObjectFieldSelector{APIVersion: "v1", FieldPath: "metadata.name"}}},
},
}, privilegedSecurityContext)
}, f.NamespacePodSecurityLevel)
testsuites.TestBasicSubpath(ctx, f, pod.Name, pod)
})
@ -113,7 +112,7 @@ var _ = utils.SIGDescribe("Subpath", func() {
}},
},
},
}, privilegedSecurityContext)
}, f.NamespacePodSecurityLevel)
testsuites.TestBasicSubpath(ctx, f, "configmap-value", pod)
})

View File

@ -489,7 +489,7 @@ func (p *provisioningTestSuite) DefineTests(driver storageframework.TestDriver,
actualPVSize := c.Status.Capacity.Storage().Value()
createdClaims := []*v1.PersistentVolumeClaim{c}
pod, err := e2epod.CreatePod(ctx, l.testCase.Client, f.Namespace.Name, nil, createdClaims, true, "")
pod, err := e2epod.CreatePod(ctx, l.testCase.Client, f.Namespace.Name, nil, createdClaims, f.NamespacePodSecurityLevel, "")
framework.ExpectNoError(err, "Failed to create pod: %v", err)
// Mount path should not be empty.
@ -514,7 +514,7 @@ func (p *provisioningTestSuite) DefineTests(driver storageframework.TestDriver,
c2, err := l.testCase.Client.CoreV1().PersistentVolumeClaims(pvc2.Namespace).Create(ctx, pvc2, metav1.CreateOptions{})
framework.ExpectNoError(err, "Failed to create pvc: %v", err)
createdClaims2 := []*v1.PersistentVolumeClaim{c2}
pod2, err := e2epod.CreatePod(ctx, l.testCase.Client, f.Namespace.Name, nil, createdClaims2, true, "")
pod2, err := e2epod.CreatePod(ctx, l.testCase.Client, f.Namespace.Name, nil, createdClaims2, f.NamespacePodSecurityLevel, "")
framework.ExpectNoError(err, "Failed to create pod: %v", err)
// Mount path should not be empty.
@ -1010,9 +1010,9 @@ func (t StorageClassTest) TestBindingWaitForFirstConsumerMultiPVC(ctx context.Co
// Create a pod referring to the claim and wait for it to get to running
var pod *v1.Pod
if expectUnschedulable {
pod, err = e2epod.CreateUnschedulablePod(ctx, t.Client, namespace, nodeSelector, createdClaims, true /* isPrivileged */, "" /* command */)
pod, err = e2epod.CreateUnschedulablePod(ctx, t.Client, namespace, nodeSelector, createdClaims, admissionapi.LevelPrivileged, "" /* command */)
} else {
pod, err = e2epod.CreatePod(ctx, t.Client, namespace, nil /* nodeSelector */, createdClaims, true /* isPrivileged */, "" /* command */)
pod, err = e2epod.CreatePod(ctx, t.Client, namespace, nil /* nodeSelector */, createdClaims, admissionapi.LevelPrivileged, "" /* command */)
}
framework.ExpectNoError(err)
ginkgo.DeferCleanup(func(ctx context.Context) error {

View File

@ -155,7 +155,7 @@ func (s *subPathTestSuite) DefineTests(driver storageframework.TestDriver, patte
}
subPath := f.Namespace.Name
l.pod = SubpathTestPod(f, subPath, string(volType), l.resource.VolSource, true)
l.pod = SubpathTestPod(f, subPath, string(volType), l.resource.VolSource, admissionapi.LevelPrivileged)
e2epod.SetNodeSelection(&l.pod.Spec, l.config.ClientNodeSelection)
l.formatPod = volumeFormatPod(f, l.resource.VolSource)
@ -509,7 +509,7 @@ func generateSuffixForPodName(s string) string {
}
// SubpathTestPod returns a pod spec for subpath tests
func SubpathTestPod(f *framework.Framework, subpath, volumeType string, source *v1.VolumeSource, privilegedSecurityContext bool) *v1.Pod {
func SubpathTestPod(f *framework.Framework, subpath, volumeType string, source *v1.VolumeSource, securityLevel admissionapi.Level) *v1.Pod {
var (
suffix = generateSuffixForPodName(volumeType)
gracePeriod = int64(1)
@ -524,19 +524,19 @@ func SubpathTestPod(f *framework.Framework, subpath, volumeType string, source *
initSubpathContainer := e2epod.NewAgnhostContainer(
fmt.Sprintf("test-init-subpath-%s", suffix),
[]v1.VolumeMount{volumeSubpathMount, probeMount}, nil, "mounttest")
initSubpathContainer.SecurityContext = e2epod.GenerateContainerSecurityContext(privilegedSecurityContext)
initSubpathContainer.SecurityContext = e2epod.GenerateContainerSecurityContext(securityLevel)
initVolumeContainer := e2epod.NewAgnhostContainer(
fmt.Sprintf("test-init-volume-%s", suffix),
[]v1.VolumeMount{volumeMount, probeMount}, nil, "mounttest")
initVolumeContainer.SecurityContext = e2epod.GenerateContainerSecurityContext(privilegedSecurityContext)
initVolumeContainer.SecurityContext = e2epod.GenerateContainerSecurityContext(securityLevel)
subpathContainer := e2epod.NewAgnhostContainer(
fmt.Sprintf("test-container-subpath-%s", suffix),
[]v1.VolumeMount{volumeSubpathMount, probeMount}, nil, "mounttest")
subpathContainer.SecurityContext = e2epod.GenerateContainerSecurityContext(privilegedSecurityContext)
subpathContainer.SecurityContext = e2epod.GenerateContainerSecurityContext(securityLevel)
volumeContainer := e2epod.NewAgnhostContainer(
fmt.Sprintf("test-container-volume-%s", suffix),
[]v1.VolumeMount{volumeMount, probeMount}, nil, "mounttest")
volumeContainer.SecurityContext = e2epod.GenerateContainerSecurityContext(privilegedSecurityContext)
volumeContainer.SecurityContext = e2epod.GenerateContainerSecurityContext(securityLevel)
return &v1.Pod{
ObjectMeta: metav1.ObjectMeta{
@ -549,7 +549,7 @@ func SubpathTestPod(f *framework.Framework, subpath, volumeType string, source *
Name: fmt.Sprintf("init-volume-%s", suffix),
Image: e2epod.GetDefaultTestImage(),
VolumeMounts: []v1.VolumeMount{volumeMount, probeMount},
SecurityContext: e2epod.GenerateContainerSecurityContext(privilegedSecurityContext),
SecurityContext: e2epod.GenerateContainerSecurityContext(securityLevel),
},
initSubpathContainer,
initVolumeContainer,
@ -927,7 +927,7 @@ func TestPodContainerRestartWithConfigmapModified(ctx context.Context, f *framew
subpath = k
break
}
pod := SubpathTestPod(f, subpath, "configmap", &v1.VolumeSource{ConfigMap: &v1.ConfigMapVolumeSource{LocalObjectReference: v1.LocalObjectReference{Name: original.Name}}}, false)
pod := SubpathTestPod(f, subpath, "configmap", &v1.VolumeSource{ConfigMap: &v1.ConfigMapVolumeSource{LocalObjectReference: v1.LocalObjectReference{Name: original.Name}}}, admissionapi.LevelBaseline)
pod.Spec.InitContainers[0].Command = e2epod.GenerateScriptCmd(fmt.Sprintf("touch %v", probeFilePath))
modifiedValue := modified.Data[subpath]

View File

@ -136,7 +136,7 @@ func PodsUseStaticPVsOrFail(ctx context.Context, f *framework.Framework, podCoun
ginkgo.By("Creating pods for each static PV")
for _, config := range configs {
podConfig := e2epod.MakePod(ns, nil, []*v1.PersistentVolumeClaim{config.pvc}, false, "")
podConfig := e2epod.MakePod(ns, nil, []*v1.PersistentVolumeClaim{config.pvc}, f.NamespacePodSecurityLevel, "")
config.pod, err = c.CoreV1().Pods(ns).Create(ctx, podConfig, metav1.CreateOptions{})
framework.ExpectNoError(err)
}

View File

@ -139,7 +139,7 @@ var _ = utils.SIGDescribe("[Serial] Volume metrics", func() {
framework.ExpectNotEqual(pvc, nil)
}
pod := makePod(ns, pvc, ephemeral)
pod := makePod(f, pvc, ephemeral)
pod, err = c.CoreV1().Pods(ns).Create(ctx, pod, metav1.CreateOptions{})
framework.ExpectNoError(err)
@ -190,7 +190,7 @@ var _ = utils.SIGDescribe("[Serial] Volume metrics", func() {
}
ginkgo.By("Creating a pod and expecting it to fail")
pod := makePod(ns, pvc, ephemeral)
pod := makePod(f, pvc, ephemeral)
pod, err = c.CoreV1().Pods(ns).Create(ctx, pod, metav1.CreateOptions{})
framework.ExpectNoError(err, "failed to create Pod %s/%s", pod.Namespace, pod.Name)
@ -215,7 +215,7 @@ var _ = utils.SIGDescribe("[Serial] Volume metrics", func() {
framework.ExpectNotEqual(pvc, nil)
}
pod := makePod(ns, pvc, isEphemeral)
pod := makePod(f, pvc, isEphemeral)
pod, err = c.CoreV1().Pods(ns).Create(ctx, pod, metav1.CreateOptions{})
framework.ExpectNoError(err)
@ -280,7 +280,7 @@ var _ = utils.SIGDescribe("[Serial] Volume metrics", func() {
framework.ExpectNotEqual(pvcBlock, nil)
}
pod := makePod(ns, pvcBlock, isEphemeral)
pod := makePod(f, pvcBlock, isEphemeral)
pod.Spec.Containers[0].VolumeDevices = []v1.VolumeDevice{{
Name: pod.Spec.Volumes[0].Name,
DevicePath: "/mnt/" + pvcBlock.Name,
@ -346,7 +346,7 @@ var _ = utils.SIGDescribe("[Serial] Volume metrics", func() {
framework.ExpectNotEqual(pvc, nil)
}
pod := makePod(ns, pvc, isEphemeral)
pod := makePod(f, pvc, isEphemeral)
pod, err = c.CoreV1().Pods(ns).Create(ctx, pod, metav1.CreateOptions{})
framework.ExpectNoError(err)
@ -377,7 +377,7 @@ var _ = utils.SIGDescribe("[Serial] Volume metrics", func() {
framework.ExpectNotEqual(pvc, nil)
}
pod := makePod(ns, pvc, isEphemeral)
pod := makePod(f, pvc, isEphemeral)
pod, err = c.CoreV1().Pods(ns).Create(ctx, pod, metav1.CreateOptions{})
framework.ExpectNoError(err)
@ -407,7 +407,7 @@ var _ = utils.SIGDescribe("[Serial] Volume metrics", func() {
framework.ExpectNotEqual(pvc, nil)
}
pod := makePod(ns, pvc, isEphemeral)
pod := makePod(f, pvc, isEphemeral)
// Get metrics
controllerMetrics, err := metricsGrabber.GrabFromControllerManager(ctx)
@ -890,9 +890,9 @@ func waitForADControllerStatesMetrics(ctx context.Context, metricsGrabber *e2eme
// makePod creates a pod which either references the PVC or creates it via a
// generic ephemeral volume claim template.
func makePod(ns string, pvc *v1.PersistentVolumeClaim, isEphemeral bool) *v1.Pod {
func makePod(f *framework.Framework, pvc *v1.PersistentVolumeClaim, isEphemeral bool) *v1.Pod {
claims := []*v1.PersistentVolumeClaim{pvc}
pod := e2epod.MakePod(ns, nil, claims, false, "")
pod := e2epod.MakePod(f.Namespace.Name, nil, claims, f.NamespacePodSecurityLevel, "")
if isEphemeral {
volSrc := pod.Spec.Volumes[0]
volSrc.PersistentVolumeClaim = nil

View File

@ -148,7 +148,7 @@ var _ = utils.SIGDescribe("vcp at scale [Feature:vsphere] ", func() {
volumeCountPerInstance = volumeCount
}
volumeCount = volumeCount - volumeCountPerInstance
go VolumeCreateAndAttach(ctx, client, f.Timeouts, namespace, scArrays, volumeCountPerInstance, volumesPerPod, nodeSelectorList, nodeVolumeMapChan)
go VolumeCreateAndAttach(ctx, f, scArrays, volumeCountPerInstance, volumesPerPod, nodeSelectorList, nodeVolumeMapChan)
}
// Get the list of all volumes attached to each node from the go routines by reading the data from the channel
@ -188,8 +188,10 @@ func getClaimsForPod(pod *v1.Pod, volumesPerPod int) []string {
}
// VolumeCreateAndAttach peforms create and attach operations of vSphere persistent volumes at scale
func VolumeCreateAndAttach(ctx context.Context, client clientset.Interface, timeouts *framework.TimeoutContext, namespace string, sc []*storagev1.StorageClass, volumeCountPerInstance int, volumesPerPod int, nodeSelectorList []*NodeSelector, nodeVolumeMapChan chan map[string][]string) {
func VolumeCreateAndAttach(ctx context.Context, f *framework.Framework, sc []*storagev1.StorageClass, volumeCountPerInstance int, volumesPerPod int, nodeSelectorList []*NodeSelector, nodeVolumeMapChan chan map[string][]string) {
defer ginkgo.GinkgoRecover()
client := f.ClientSet
namespace := f.Namespace.Name
nodeVolumeMap := make(map[string][]string)
nodeSelectorIndex := 0
for index := 0; index < volumeCountPerInstance; index = index + volumesPerPod {
@ -205,13 +207,13 @@ func VolumeCreateAndAttach(ctx context.Context, client clientset.Interface, time
}
ginkgo.By("Waiting for claim to be in bound phase")
persistentvolumes, err := e2epv.WaitForPVClaimBoundPhase(ctx, client, pvclaims, timeouts.ClaimProvision)
persistentvolumes, err := e2epv.WaitForPVClaimBoundPhase(ctx, client, pvclaims, f.Timeouts.ClaimProvision)
framework.ExpectNoError(err)
ginkgo.By("Creating pod to attach PV to the node")
nodeSelector := nodeSelectorList[nodeSelectorIndex%len(nodeSelectorList)]
// Create pod to attach Volume to Node
pod, err := e2epod.CreatePod(ctx, client, namespace, map[string]string{nodeSelector.labelKey: nodeSelector.labelValue}, pvclaims, false, "")
pod, err := e2epod.CreatePod(ctx, client, namespace, map[string]string{nodeSelector.labelKey: nodeSelector.labelValue}, pvclaims, f.NamespacePodSecurityLevel, "")
framework.ExpectNoError(err)
for _, pv := range persistentvolumes {

View File

@ -153,7 +153,7 @@ func PerformVolumeLifeCycleInParallel(ctx context.Context, f *framework.Framewor
ginkgo.By(fmt.Sprintf("%v Creating Pod using the claim: %v", logPrefix, pvclaim.Name))
// Create pod to attach Volume to Node
pod, err := e2epod.CreatePod(ctx, client, namespace, nil, pvclaims, false, "")
pod, err := e2epod.CreatePod(ctx, client, namespace, nil, pvclaims, f.NamespacePodSecurityLevel, "")
framework.ExpectNoError(err)
ginkgo.By(fmt.Sprintf("%v Waiting for the Pod: %v to be in the running state", logPrefix, pod.Name))

View File

@ -72,54 +72,54 @@ var _ = utils.SIGDescribe("Volume FStype [Feature:vsphere]", func() {
f := framework.NewDefaultFramework("volume-fstype")
f.NamespacePodSecurityLevel = admissionapi.LevelPrivileged
var (
client clientset.Interface
namespace string
client clientset.Interface
)
ginkgo.BeforeEach(func(ctx context.Context) {
e2eskipper.SkipUnlessProviderIs("vsphere")
Bootstrap(f)
client = f.ClientSet
namespace = f.Namespace.Name
gomega.Expect(GetReadySchedulableNodeInfos(ctx, client)).NotTo(gomega.BeEmpty())
})
ginkgo.It("verify fstype - ext3 formatted volume", func(ctx context.Context) {
ginkgo.By("Invoking Test for fstype: ext3")
invokeTestForFstype(ctx, f, client, namespace, ext3FSType, ext3FSType)
invokeTestForFstype(ctx, f, ext3FSType, ext3FSType)
})
ginkgo.It("verify fstype - default value should be ext4", func(ctx context.Context) {
ginkgo.By("Invoking Test for fstype: Default Value - ext4")
invokeTestForFstype(ctx, f, client, namespace, "", ext4FSType)
invokeTestForFstype(ctx, f, "", ext4FSType)
})
ginkgo.It("verify invalid fstype", func(ctx context.Context) {
ginkgo.By("Invoking Test for fstype: invalid Value")
invokeTestForInvalidFstype(ctx, f, client, namespace, invalidFSType)
invokeTestForInvalidFstype(ctx, f, client, invalidFSType)
})
})
func invokeTestForFstype(ctx context.Context, f *framework.Framework, client clientset.Interface, namespace string, fstype string, expectedContent string) {
func invokeTestForFstype(ctx context.Context, f *framework.Framework, fstype string, expectedContent string) {
framework.Logf("Invoking Test for fstype: %s", fstype)
namespace := f.Namespace.Name
scParameters := make(map[string]string)
scParameters["fstype"] = fstype
// Create Persistent Volume
ginkgo.By("Creating Storage Class With Fstype")
pvclaim, persistentvolumes := createVolume(ctx, client, f.Timeouts, namespace, scParameters)
pvclaim, persistentvolumes := createVolume(ctx, f.ClientSet, f.Timeouts, f.Namespace.Name, scParameters)
// Create Pod and verify the persistent volume is accessible
pod := createPodAndVerifyVolumeAccessible(ctx, client, namespace, pvclaim, persistentvolumes)
pod := createPodAndVerifyVolumeAccessible(ctx, f, pvclaim, persistentvolumes)
_, err := e2eoutput.LookForStringInPodExec(namespace, pod.Name, []string{"/bin/cat", "/mnt/volume1/fstype"}, expectedContent, time.Minute)
framework.ExpectNoError(err)
// Detach and delete volume
detachVolume(ctx, f, client, pod, persistentvolumes[0].Spec.VsphereVolume.VolumePath)
err = e2epv.DeletePersistentVolumeClaim(ctx, client, pvclaim.Name, namespace)
detachVolume(ctx, f, pod, persistentvolumes[0].Spec.VsphereVolume.VolumePath)
err = e2epv.DeletePersistentVolumeClaim(ctx, f.ClientSet, pvclaim.Name, namespace)
framework.ExpectNoError(err)
}
func invokeTestForInvalidFstype(ctx context.Context, f *framework.Framework, client clientset.Interface, namespace string, fstype string) {
func invokeTestForInvalidFstype(ctx context.Context, f *framework.Framework, client clientset.Interface, fstype string) {
namespace := f.Namespace.Name
scParameters := make(map[string]string)
scParameters["fstype"] = fstype
@ -131,14 +131,14 @@ func invokeTestForInvalidFstype(ctx context.Context, f *framework.Framework, cli
var pvclaims []*v1.PersistentVolumeClaim
pvclaims = append(pvclaims, pvclaim)
// Create pod to attach Volume to Node
pod, err := e2epod.CreatePod(ctx, client, namespace, nil, pvclaims, false, execCommand)
pod, err := e2epod.CreatePod(ctx, client, namespace, nil, pvclaims, f.NamespacePodSecurityLevel, execCommand)
framework.ExpectError(err)
eventList, err := client.CoreV1().Events(namespace).List(ctx, metav1.ListOptions{})
framework.ExpectNoError(err)
// Detach and delete volume
detachVolume(ctx, f, client, pod, persistentvolumes[0].Spec.VsphereVolume.VolumePath)
detachVolume(ctx, f, pod, persistentvolumes[0].Spec.VsphereVolume.VolumePath)
err = e2epv.DeletePersistentVolumeClaim(ctx, client, pvclaim.Name, namespace)
framework.ExpectNoError(err)
@ -172,27 +172,27 @@ func createVolume(ctx context.Context, client clientset.Interface, timeouts *fra
return pvclaim, persistentvolumes
}
func createPodAndVerifyVolumeAccessible(ctx context.Context, client clientset.Interface, namespace string, pvclaim *v1.PersistentVolumeClaim, persistentvolumes []*v1.PersistentVolume) *v1.Pod {
func createPodAndVerifyVolumeAccessible(ctx context.Context, f *framework.Framework, pvclaim *v1.PersistentVolumeClaim, persistentvolumes []*v1.PersistentVolume) *v1.Pod {
var pvclaims []*v1.PersistentVolumeClaim
pvclaims = append(pvclaims, pvclaim)
ginkgo.By("Creating pod to attach PV to the node")
// Create pod to attach Volume to Node
pod, err := e2epod.CreatePod(ctx, client, namespace, nil, pvclaims, false, execCommand)
pod, err := e2epod.CreatePod(ctx, f.ClientSet, f.Namespace.Name, nil, pvclaims, f.NamespacePodSecurityLevel, execCommand)
framework.ExpectNoError(err)
// Asserts: Right disk is attached to the pod
ginkgo.By("Verify the volume is accessible and available in the pod")
verifyVSphereVolumesAccessible(ctx, client, pod, persistentvolumes)
verifyVSphereVolumesAccessible(ctx, f.ClientSet, pod, persistentvolumes)
return pod
}
// detachVolume delete the volume passed in the argument and wait until volume is detached from the node,
func detachVolume(ctx context.Context, f *framework.Framework, client clientset.Interface, pod *v1.Pod, volPath string) {
func detachVolume(ctx context.Context, f *framework.Framework, pod *v1.Pod, volPath string) {
pod, err := f.ClientSet.CoreV1().Pods(pod.Namespace).Get(ctx, pod.Name, metav1.GetOptions{})
framework.ExpectNoError(err)
nodeName := pod.Spec.NodeName
ginkgo.By("Deleting pod")
err = e2epod.DeletePodWithWait(ctx, client, pod)
err = e2epod.DeletePodWithWait(ctx, f.ClientSet, pod)
framework.ExpectNoError(err)
ginkgo.By("Waiting for volumes to be detached from the node")

View File

@ -101,7 +101,7 @@ var _ = utils.SIGDescribe("Node Poweroff [Feature:vsphere] [Slow] [Disruptive]",
volumePath := pvs[0].Spec.VsphereVolume.VolumePath
ginkgo.By("Creating a Deployment")
deployment, err := e2edeployment.CreateDeployment(ctx, client, int32(1), map[string]string{"test": "app"}, nil, namespace, pvclaims, "")
deployment, err := e2edeployment.CreateDeployment(ctx, client, int32(1), map[string]string{"test": "app"}, nil, namespace, pvclaims, admissionapi.LevelRestricted, "")
framework.ExpectNoError(err, fmt.Sprintf("Failed to create Deployment with err: %v", err))
ginkgo.DeferCleanup(framework.IgnoreNotFound(client.AppsV1().Deployments(namespace).Delete), deployment.Name, metav1.DeleteOptions{})

View File

@ -110,7 +110,7 @@ var _ = utils.SIGDescribe("Volume Operations Storm [Feature:vsphere]", func() {
framework.ExpectNoError(err)
ginkgo.By("Creating pod to attach PVs to the node")
pod, err := e2epod.CreatePod(ctx, client, namespace, nil, pvclaims, false, "")
pod, err := e2epod.CreatePod(ctx, client, namespace, nil, pvclaims, f.NamespacePodSecurityLevel, "")
framework.ExpectNoError(err)
ginkgo.By("Verify all volumes are accessible and available in the pod")

View File

@ -197,7 +197,7 @@ func invokeVolumeLifeCyclePerformance(ctx context.Context, f *framework.Framewor
start = time.Now()
for i, pvclaims := range totalpvclaims {
nodeSelector := nodeSelectorList[i%len(nodeSelectorList)]
pod, err := e2epod.CreatePod(ctx, client, namespace, map[string]string{nodeSelector.labelKey: nodeSelector.labelValue}, pvclaims, false, "")
pod, err := e2epod.CreatePod(ctx, client, namespace, map[string]string{nodeSelector.labelKey: nodeSelector.labelValue}, pvclaims, f.NamespacePodSecurityLevel, "")
framework.ExpectNoError(err)
totalpods = append(totalpods, pod)

View File

@ -276,7 +276,7 @@ func invokeValidPolicyTest(ctx context.Context, f *framework.Framework, client c
ginkgo.By("Creating pod to attach PV to the node")
// Create pod to attach Volume to Node
pod, err := e2epod.CreatePod(ctx, client, namespace, nil, pvclaims, false, "")
pod, err := e2epod.CreatePod(ctx, client, namespace, nil, pvclaims, f.NamespacePodSecurityLevel, "")
framework.ExpectNoError(err)
ginkgo.By("Verify the volume is accessible and available in the pod")

View File

@ -90,8 +90,6 @@ var _ = utils.SIGDescribe("Zone Support [Feature:vsphere]", func() {
f := framework.NewDefaultFramework("zone-support")
f.NamespacePodSecurityLevel = admissionapi.LevelPrivileged
var (
client clientset.Interface
namespace string
scParameters map[string]string
zones []string
vsanDatastore1 string
@ -108,9 +106,7 @@ var _ = utils.SIGDescribe("Zone Support [Feature:vsphere]", func() {
ginkgo.BeforeEach(func(ctx context.Context) {
e2eskipper.SkipUnlessProviderIs("vsphere")
Bootstrap(f)
client = f.ClientSet
e2eskipper.SkipUnlessMultizone(ctx, client)
namespace = f.Namespace.Name
e2eskipper.SkipUnlessMultizone(ctx, f.ClientSet)
vsanDatastore1 = GetAndExpectStringEnvVar(VCPZoneVsanDatastore1)
vsanDatastore2 = GetAndExpectStringEnvVar(VCPZoneVsanDatastore2)
localDatastore = GetAndExpectStringEnvVar(VCPZoneLocalDatastore)
@ -130,20 +126,20 @@ var _ = utils.SIGDescribe("Zone Support [Feature:vsphere]", func() {
ginkgo.It("Verify dynamically created pv with allowed zones specified in storage class, shows the right zone information on its labels", func(ctx context.Context) {
ginkgo.By(fmt.Sprintf("Creating storage class with the following zones : %s", zoneA))
zones = append(zones, zoneA)
verifyPVZoneLabels(ctx, client, f.Timeouts, namespace, nil, zones)
verifyPVZoneLabels(ctx, f, nil, zones)
})
ginkgo.It("Verify dynamically created pv with multiple zones specified in the storage class, shows both the zones on its labels", func(ctx context.Context) {
ginkgo.By(fmt.Sprintf("Creating storage class with the following zones : %s, %s", zoneA, zoneB))
zones = append(zones, zoneA)
zones = append(zones, zoneB)
verifyPVZoneLabels(ctx, client, f.Timeouts, namespace, nil, zones)
verifyPVZoneLabels(ctx, f, nil, zones)
})
ginkgo.It("Verify PVC creation with invalid zone specified in storage class fails", func(ctx context.Context) {
ginkgo.By(fmt.Sprintf("Creating storage class with unknown zone : %s", invalidZone))
zones = append(zones, invalidZone)
err := verifyPVCCreationFails(ctx, client, namespace, nil, zones, "")
err := verifyPVCCreationFails(ctx, f, nil, zones, "")
framework.ExpectError(err)
errorMsg := "Failed to find a shared datastore matching zone [" + invalidZone + "]"
if !strings.Contains(err.Error(), errorMsg) {
@ -154,28 +150,28 @@ var _ = utils.SIGDescribe("Zone Support [Feature:vsphere]", func() {
ginkgo.It("Verify a pod is created and attached to a dynamically created PV, based on allowed zones specified in storage class ", func(ctx context.Context) {
ginkgo.By(fmt.Sprintf("Creating storage class with zones :%s", zoneA))
zones = append(zones, zoneA)
verifyPVCAndPodCreationSucceeds(ctx, client, f.Timeouts, namespace, nil, zones, "")
verifyPVCAndPodCreationSucceeds(ctx, f, nil, zones, "")
})
ginkgo.It("Verify a pod is created and attached to a dynamically created PV, based on multiple zones specified in storage class ", func(ctx context.Context) {
ginkgo.By(fmt.Sprintf("Creating storage class with zones :%s, %s", zoneA, zoneB))
zones = append(zones, zoneA)
zones = append(zones, zoneB)
verifyPVCAndPodCreationSucceeds(ctx, client, f.Timeouts, namespace, nil, zones, "")
verifyPVCAndPodCreationSucceeds(ctx, f, nil, zones, "")
})
ginkgo.It("Verify a pod is created and attached to a dynamically created PV, based on the allowed zones and datastore specified in storage class", func(ctx context.Context) {
ginkgo.By(fmt.Sprintf("Creating storage class with zone :%s and datastore :%s", zoneA, vsanDatastore1))
scParameters[Datastore] = vsanDatastore1
zones = append(zones, zoneA)
verifyPVCAndPodCreationSucceeds(ctx, client, f.Timeouts, namespace, scParameters, zones, "")
verifyPVCAndPodCreationSucceeds(ctx, f, scParameters, zones, "")
})
ginkgo.It("Verify PVC creation with incompatible datastore and zone combination specified in storage class fails", func(ctx context.Context) {
ginkgo.By(fmt.Sprintf("Creating storage class with zone :%s and datastore :%s", zoneC, vsanDatastore1))
scParameters[Datastore] = vsanDatastore1
zones = append(zones, zoneC)
err := verifyPVCCreationFails(ctx, client, namespace, scParameters, zones, "")
err := verifyPVCCreationFails(ctx, f, scParameters, zones, "")
errorMsg := "No matching datastores found in the kubernetes cluster for zone " + zoneC
if !strings.Contains(err.Error(), errorMsg) {
framework.ExpectNoError(err, errorMsg)
@ -186,21 +182,21 @@ var _ = utils.SIGDescribe("Zone Support [Feature:vsphere]", func() {
ginkgo.By(fmt.Sprintf("Creating storage class with zone :%s and storage policy :%s", zoneA, compatPolicy))
scParameters[SpbmStoragePolicy] = compatPolicy
zones = append(zones, zoneA)
verifyPVCAndPodCreationSucceeds(ctx, client, f.Timeouts, namespace, scParameters, zones, "")
verifyPVCAndPodCreationSucceeds(ctx, f, scParameters, zones, "")
})
ginkgo.It("Verify a pod is created on a non-Workspace zone and attached to a dynamically created PV, based on the allowed zones and storage policy specified in storage class", func(ctx context.Context) {
ginkgo.By(fmt.Sprintf("Creating storage class with zone :%s and storage policy :%s", zoneB, compatPolicy))
scParameters[SpbmStoragePolicy] = compatPolicy
zones = append(zones, zoneB)
verifyPVCAndPodCreationSucceeds(ctx, client, f.Timeouts, namespace, scParameters, zones, "")
verifyPVCAndPodCreationSucceeds(ctx, f, scParameters, zones, "")
})
ginkgo.It("Verify PVC creation with incompatible storagePolicy and zone combination specified in storage class fails", func(ctx context.Context) {
ginkgo.By(fmt.Sprintf("Creating storage class with zone :%s and storage policy :%s", zoneA, nonCompatPolicy))
scParameters[SpbmStoragePolicy] = nonCompatPolicy
zones = append(zones, zoneA)
err := verifyPVCCreationFails(ctx, client, namespace, scParameters, zones, "")
err := verifyPVCCreationFails(ctx, f, scParameters, zones, "")
errorMsg := "No compatible datastores found that satisfy the storage policy requirements"
if !strings.Contains(err.Error(), errorMsg) {
framework.ExpectNoError(err, errorMsg)
@ -212,7 +208,7 @@ var _ = utils.SIGDescribe("Zone Support [Feature:vsphere]", func() {
scParameters[SpbmStoragePolicy] = compatPolicy
scParameters[Datastore] = vsanDatastore1
zones = append(zones, zoneA)
verifyPVCAndPodCreationSucceeds(ctx, client, f.Timeouts, namespace, scParameters, zones, "")
verifyPVCAndPodCreationSucceeds(ctx, f, scParameters, zones, "")
})
ginkgo.It("Verify PVC creation with incompatible storage policy along with compatible zone and datastore combination specified in storage class fails", func(ctx context.Context) {
@ -220,7 +216,7 @@ var _ = utils.SIGDescribe("Zone Support [Feature:vsphere]", func() {
scParameters[SpbmStoragePolicy] = nonCompatPolicy
scParameters[Datastore] = vsanDatastore1
zones = append(zones, zoneA)
err := verifyPVCCreationFails(ctx, client, namespace, scParameters, zones, "")
err := verifyPVCCreationFails(ctx, f, scParameters, zones, "")
errorMsg := "User specified datastore is not compatible with the storagePolicy: \\\"" + nonCompatPolicy + "\\\"."
if !strings.Contains(err.Error(), errorMsg) {
framework.ExpectNoError(err, errorMsg)
@ -232,7 +228,7 @@ var _ = utils.SIGDescribe("Zone Support [Feature:vsphere]", func() {
scParameters[SpbmStoragePolicy] = compatPolicy
scParameters[Datastore] = vsanDatastore2
zones = append(zones, zoneC)
err := verifyPVCCreationFails(ctx, client, namespace, scParameters, zones, "")
err := verifyPVCCreationFails(ctx, f, scParameters, zones, "")
errorMsg := "No matching datastores found in the kubernetes cluster for zone " + zoneC
if !strings.Contains(err.Error(), errorMsg) {
framework.ExpectNoError(err, errorMsg)
@ -241,7 +237,7 @@ var _ = utils.SIGDescribe("Zone Support [Feature:vsphere]", func() {
ginkgo.It("Verify PVC creation fails if no zones are specified in the storage class (No shared datastores exist among all the nodes)", func(ctx context.Context) {
ginkgo.By(fmt.Sprintf("Creating storage class with no zones"))
err := verifyPVCCreationFails(ctx, client, namespace, nil, nil, "")
err := verifyPVCCreationFails(ctx, f, nil, nil, "")
errorMsg := "No shared datastores found in the Kubernetes cluster"
if !strings.Contains(err.Error(), errorMsg) {
framework.ExpectNoError(err, errorMsg)
@ -251,7 +247,7 @@ var _ = utils.SIGDescribe("Zone Support [Feature:vsphere]", func() {
ginkgo.It("Verify PVC creation fails if only datastore is specified in the storage class (No shared datastores exist among all the nodes)", func(ctx context.Context) {
ginkgo.By(fmt.Sprintf("Creating storage class with datastore :%s", vsanDatastore1))
scParameters[Datastore] = vsanDatastore1
err := verifyPVCCreationFails(ctx, client, namespace, scParameters, nil, "")
err := verifyPVCCreationFails(ctx, f, scParameters, nil, "")
errorMsg := "No shared datastores found in the Kubernetes cluster"
if !strings.Contains(err.Error(), errorMsg) {
framework.ExpectNoError(err, errorMsg)
@ -261,7 +257,7 @@ var _ = utils.SIGDescribe("Zone Support [Feature:vsphere]", func() {
ginkgo.It("Verify PVC creation fails if only storage policy is specified in the storage class (No shared datastores exist among all the nodes)", func(ctx context.Context) {
ginkgo.By(fmt.Sprintf("Creating storage class with storage policy :%s", compatPolicy))
scParameters[SpbmStoragePolicy] = compatPolicy
err := verifyPVCCreationFails(ctx, client, namespace, scParameters, nil, "")
err := verifyPVCCreationFails(ctx, f, scParameters, nil, "")
errorMsg := "No shared datastores found in the Kubernetes cluster"
if !strings.Contains(err.Error(), errorMsg) {
framework.ExpectNoError(err, errorMsg)
@ -272,7 +268,7 @@ var _ = utils.SIGDescribe("Zone Support [Feature:vsphere]", func() {
ginkgo.By(fmt.Sprintf("Creating storage class with storage policy :%s and datastore :%s", compatPolicy, vsanDatastore1))
scParameters[SpbmStoragePolicy] = compatPolicy
scParameters[Datastore] = vsanDatastore1
err := verifyPVCCreationFails(ctx, client, namespace, scParameters, nil, "")
err := verifyPVCCreationFails(ctx, f, scParameters, nil, "")
errorMsg := "No shared datastores found in the Kubernetes cluster"
if !strings.Contains(err.Error(), errorMsg) {
framework.ExpectNoError(err, errorMsg)
@ -282,7 +278,7 @@ var _ = utils.SIGDescribe("Zone Support [Feature:vsphere]", func() {
ginkgo.It("Verify PVC creation fails if the availability zone specified in the storage class have no shared datastores under it.", func(ctx context.Context) {
ginkgo.By(fmt.Sprintf("Creating storage class with zone :%s", zoneC))
zones = append(zones, zoneC)
err := verifyPVCCreationFails(ctx, client, namespace, nil, zones, "")
err := verifyPVCCreationFails(ctx, f, nil, zones, "")
errorMsg := "No matching datastores found in the kubernetes cluster for zone " + zoneC
if !strings.Contains(err.Error(), errorMsg) {
framework.ExpectNoError(err, errorMsg)
@ -293,7 +289,7 @@ var _ = utils.SIGDescribe("Zone Support [Feature:vsphere]", func() {
ginkgo.By(fmt.Sprintf("Creating storage class with the following zones :%s and %s", zoneA, zoneC))
zones = append(zones, zoneA)
zones = append(zones, zoneC)
err := verifyPVCCreationFails(ctx, client, namespace, nil, zones, "")
err := verifyPVCCreationFails(ctx, f, nil, zones, "")
errorMsg := "No matching datastores found in the kubernetes cluster for zone " + zoneC
if !strings.Contains(err.Error(), errorMsg) {
framework.ExpectNoError(err, errorMsg)
@ -304,7 +300,7 @@ var _ = utils.SIGDescribe("Zone Support [Feature:vsphere]", func() {
ginkgo.By(fmt.Sprintf("Creating storage class with %s :%s and zone :%s", PolicyHostFailuresToTolerate, HostFailuresToTolerateCapabilityInvalidVal, zoneA))
scParameters[PolicyHostFailuresToTolerate] = HostFailuresToTolerateCapabilityInvalidVal
zones = append(zones, zoneA)
err := verifyPVCCreationFails(ctx, client, namespace, scParameters, zones, "")
err := verifyPVCCreationFails(ctx, f, scParameters, zones, "")
errorMsg := "Invalid value for " + PolicyHostFailuresToTolerate + "."
if !strings.Contains(err.Error(), errorMsg) {
framework.ExpectNoError(err, errorMsg)
@ -317,47 +313,47 @@ var _ = utils.SIGDescribe("Zone Support [Feature:vsphere]", func() {
scParameters[PolicyIopsLimit] = IopsLimitCapabilityVal
scParameters[Datastore] = vsanDatastore1
zones = append(zones, zoneA)
verifyPVCAndPodCreationSucceeds(ctx, client, f.Timeouts, namespace, scParameters, zones, "")
verifyPVCAndPodCreationSucceeds(ctx, f, scParameters, zones, "")
})
ginkgo.It("Verify a pod is created and attached to a dynamically created PV, based on the allowed zones specified in storage class when the datastore under the zone is present in another datacenter", func(ctx context.Context) {
ginkgo.By(fmt.Sprintf("Creating storage class with zone :%s", zoneD))
zones = append(zones, zoneD)
verifyPVCAndPodCreationSucceeds(ctx, client, f.Timeouts, namespace, scParameters, zones, "")
verifyPVCAndPodCreationSucceeds(ctx, f, scParameters, zones, "")
})
ginkgo.It("Verify a pod is created and attached to a dynamically created PV, based on the allowed zones and datastore specified in storage class when there are multiple datastores with the same name under different zones across datacenters", func(ctx context.Context) {
ginkgo.By(fmt.Sprintf("Creating storage class with zone :%s and datastore name :%s", zoneD, localDatastore))
scParameters[Datastore] = localDatastore
zones = append(zones, zoneD)
verifyPVCAndPodCreationSucceeds(ctx, client, f.Timeouts, namespace, scParameters, zones, "")
verifyPVCAndPodCreationSucceeds(ctx, f, scParameters, zones, "")
})
ginkgo.It("Verify a pod is created and attached to a dynamically created PV with storage policy specified in storage class in waitForFirstConsumer binding mode", func(ctx context.Context) {
ginkgo.By(fmt.Sprintf("Creating storage class with waitForFirstConsumer mode and storage policy :%s", compatPolicy))
scParameters[SpbmStoragePolicy] = compatPolicy
verifyPVCAndPodCreationSucceeds(ctx, client, f.Timeouts, namespace, scParameters, nil, storagev1.VolumeBindingWaitForFirstConsumer)
verifyPVCAndPodCreationSucceeds(ctx, f, scParameters, nil, storagev1.VolumeBindingWaitForFirstConsumer)
})
ginkgo.It("Verify a pod is created and attached to a dynamically created PV with storage policy specified in storage class in waitForFirstConsumer binding mode with allowedTopologies", func(ctx context.Context) {
ginkgo.By(fmt.Sprintf("Creating storage class with waitForFirstConsumer mode, storage policy :%s and zone :%s", compatPolicy, zoneA))
scParameters[SpbmStoragePolicy] = compatPolicy
zones = append(zones, zoneA)
verifyPVCAndPodCreationSucceeds(ctx, client, f.Timeouts, namespace, scParameters, zones, storagev1.VolumeBindingWaitForFirstConsumer)
verifyPVCAndPodCreationSucceeds(ctx, f, scParameters, zones, storagev1.VolumeBindingWaitForFirstConsumer)
})
ginkgo.It("Verify a pod is created and attached to a dynamically created PV with storage policy specified in storage class in waitForFirstConsumer binding mode with multiple allowedTopologies", func(ctx context.Context) {
ginkgo.By(fmt.Sprintf("Creating storage class with waitForFirstConsumer mode and zones : %s, %s", zoneA, zoneB))
zones = append(zones, zoneA)
zones = append(zones, zoneB)
verifyPVCAndPodCreationSucceeds(ctx, client, f.Timeouts, namespace, nil, zones, storagev1.VolumeBindingWaitForFirstConsumer)
verifyPVCAndPodCreationSucceeds(ctx, f, nil, zones, storagev1.VolumeBindingWaitForFirstConsumer)
})
ginkgo.It("Verify a PVC creation fails when multiple zones are specified in the storage class without shared datastores among the zones in waitForFirstConsumer binding mode", func(ctx context.Context) {
ginkgo.By(fmt.Sprintf("Creating storage class with waitForFirstConsumer mode and following zones :%s and %s", zoneA, zoneC))
zones = append(zones, zoneA)
zones = append(zones, zoneC)
err := verifyPodAndPvcCreationFailureOnWaitForFirstConsumerMode(ctx, client, namespace, nil, zones)
err := verifyPodAndPvcCreationFailureOnWaitForFirstConsumerMode(ctx, f, nil, zones)
framework.ExpectError(err)
errorMsg := "No matching datastores found in the kubernetes cluster for zone " + zoneC
if !strings.Contains(err.Error(), errorMsg) {
@ -374,11 +370,14 @@ var _ = utils.SIGDescribe("Zone Support [Feature:vsphere]", func() {
// nodeSelector set as zoneB
v1.LabelTopologyZone: zoneB,
}
verifyPodSchedulingFails(ctx, client, namespace, nodeSelectorMap, scParameters, zones, storagev1.VolumeBindingWaitForFirstConsumer)
verifyPodSchedulingFails(ctx, f, nodeSelectorMap, scParameters, zones, storagev1.VolumeBindingWaitForFirstConsumer)
})
})
func verifyPVCAndPodCreationSucceeds(ctx context.Context, client clientset.Interface, timeouts *framework.TimeoutContext, namespace string, scParameters map[string]string, zones []string, volumeBindingMode storagev1.VolumeBindingMode) {
func verifyPVCAndPodCreationSucceeds(ctx context.Context, f *framework.Framework, scParameters map[string]string, zones []string, volumeBindingMode storagev1.VolumeBindingMode) {
client := f.ClientSet
namespace := f.Namespace.Name
timeouts := f.Timeouts
storageclass, err := client.StorageV1().StorageClasses().Create(ctx, getVSphereStorageClassSpec("zone-sc", scParameters, zones, volumeBindingMode), metav1.CreateOptions{})
framework.ExpectNoError(err, fmt.Sprintf("Failed to create storage class with err: %v", err))
ginkgo.DeferCleanup(client.StorageV1().StorageClasses().Delete, storageclass.Name, metav1.DeleteOptions{})
@ -398,7 +397,7 @@ func verifyPVCAndPodCreationSucceeds(ctx context.Context, client clientset.Inter
}
ginkgo.By("Creating pod to attach PV to the node")
pod, err := e2epod.CreatePod(ctx, client, namespace, nil, pvclaims, false, "")
pod, err := e2epod.CreatePod(ctx, client, namespace, nil, pvclaims, f.NamespacePodSecurityLevel, "")
framework.ExpectNoError(err)
if volumeBindingMode == storagev1.VolumeBindingWaitForFirstConsumer {
@ -420,7 +419,9 @@ func verifyPVCAndPodCreationSucceeds(ctx context.Context, client clientset.Inter
framework.ExpectNoError(waitForVSphereDiskToDetach(ctx, persistentvolumes[0].Spec.VsphereVolume.VolumePath, pod.Spec.NodeName))
}
func verifyPodAndPvcCreationFailureOnWaitForFirstConsumerMode(ctx context.Context, client clientset.Interface, namespace string, scParameters map[string]string, zones []string) error {
func verifyPodAndPvcCreationFailureOnWaitForFirstConsumerMode(ctx context.Context, f *framework.Framework, scParameters map[string]string, zones []string) error {
client := f.ClientSet
namespace := f.Namespace.Name
storageclass, err := client.StorageV1().StorageClasses().Create(ctx, getVSphereStorageClassSpec("zone-sc", scParameters, zones, storagev1.VolumeBindingWaitForFirstConsumer), metav1.CreateOptions{})
framework.ExpectNoError(err, fmt.Sprintf("Failed to create storage class with err: %v", err))
ginkgo.DeferCleanup(client.StorageV1().StorageClasses().Delete, storageclass.Name, metav1.DeleteOptions{})
@ -434,7 +435,7 @@ func verifyPodAndPvcCreationFailureOnWaitForFirstConsumerMode(ctx context.Contex
pvclaims = append(pvclaims, pvclaim)
ginkgo.By("Creating a pod")
pod := e2epod.MakePod(namespace, nil, pvclaims, false, "")
pod := e2epod.MakePod(namespace, nil, pvclaims, f.NamespacePodSecurityLevel, "")
pod, err = client.CoreV1().Pods(namespace).Create(ctx, pod, metav1.CreateOptions{})
framework.ExpectNoError(err)
ginkgo.DeferCleanup(e2epod.DeletePodWithWait, client, pod)
@ -462,7 +463,9 @@ func waitForPVClaimBoundPhase(ctx context.Context, client clientset.Interface, p
return persistentvolumes
}
func verifyPodSchedulingFails(ctx context.Context, client clientset.Interface, namespace string, nodeSelector map[string]string, scParameters map[string]string, zones []string, volumeBindingMode storagev1.VolumeBindingMode) {
func verifyPodSchedulingFails(ctx context.Context, f *framework.Framework, nodeSelector map[string]string, scParameters map[string]string, zones []string, volumeBindingMode storagev1.VolumeBindingMode) {
client := f.ClientSet
namespace := f.Namespace.Name
storageclass, err := client.StorageV1().StorageClasses().Create(ctx, getVSphereStorageClassSpec("zone-sc", scParameters, zones, volumeBindingMode), metav1.CreateOptions{})
framework.ExpectNoError(err, fmt.Sprintf("Failed to create storage class with err: %v", err))
ginkgo.DeferCleanup(client.StorageV1().StorageClasses().Delete, storageclass.Name, metav1.DeleteOptions{})
@ -476,12 +479,14 @@ func verifyPodSchedulingFails(ctx context.Context, client clientset.Interface, n
pvclaims = append(pvclaims, pvclaim)
ginkgo.By("Creating a pod")
pod, err := e2epod.CreateUnschedulablePod(ctx, client, namespace, nodeSelector, pvclaims, false, "")
pod, err := e2epod.CreateUnschedulablePod(ctx, client, namespace, nodeSelector, pvclaims, f.NamespacePodSecurityLevel, "")
framework.ExpectNoError(err)
ginkgo.DeferCleanup(e2epod.DeletePodWithWait, client, pod)
}
func verifyPVCCreationFails(ctx context.Context, client clientset.Interface, namespace string, scParameters map[string]string, zones []string, volumeBindingMode storagev1.VolumeBindingMode) error {
func verifyPVCCreationFails(ctx context.Context, f *framework.Framework, scParameters map[string]string, zones []string, volumeBindingMode storagev1.VolumeBindingMode) error {
client := f.ClientSet
namespace := f.Namespace.Name
storageclass, err := client.StorageV1().StorageClasses().Create(ctx, getVSphereStorageClassSpec("zone-sc", scParameters, zones, volumeBindingMode), metav1.CreateOptions{})
framework.ExpectNoError(err, fmt.Sprintf("Failed to create storage class with err: %v", err))
ginkgo.DeferCleanup(client.StorageV1().StorageClasses().Delete, storageclass.Name, metav1.DeleteOptions{})
@ -502,7 +507,9 @@ func verifyPVCCreationFails(ctx context.Context, client clientset.Interface, nam
return fmt.Errorf("Failure message: %+q", eventList.Items[0].Message)
}
func verifyPVZoneLabels(ctx context.Context, client clientset.Interface, timeouts *framework.TimeoutContext, namespace string, scParameters map[string]string, zones []string) {
func verifyPVZoneLabels(ctx context.Context, f *framework.Framework, scParameters map[string]string, zones []string) {
client := f.ClientSet
namespace := f.Namespace.Name
storageclass, err := client.StorageV1().StorageClasses().Create(ctx, getVSphereStorageClassSpec("zone-sc", nil, zones, ""), metav1.CreateOptions{})
framework.ExpectNoError(err, fmt.Sprintf("Failed to create storage class with err: %v", err))
ginkgo.DeferCleanup(client.StorageV1().StorageClasses().Delete, storageclass.Name, metav1.DeleteOptions{})
@ -515,7 +522,7 @@ func verifyPVZoneLabels(ctx context.Context, client clientset.Interface, timeout
var pvclaims []*v1.PersistentVolumeClaim
pvclaims = append(pvclaims, pvclaim)
ginkgo.By("Waiting for claim to be in bound phase")
persistentvolumes, err := e2epv.WaitForPVClaimBoundPhase(ctx, client, pvclaims, timeouts.ClaimProvision)
persistentvolumes, err := e2epv.WaitForPVClaimBoundPhase(ctx, client, pvclaims, f.Timeouts.ClaimProvision)
framework.ExpectNoError(err)
ginkgo.By("Verify zone information is present in the volume labels")

View File

@ -84,7 +84,7 @@ func (t *PersistentVolumeUpgradeTest) Teardown(ctx context.Context, f *framework
// testPod creates a pod that consumes a pv and prints it out. The output is then verified.
func (t *PersistentVolumeUpgradeTest) testPod(ctx context.Context, f *framework.Framework, cmd string) {
pod := e2epod.MakePod(f.Namespace.Name, nil, []*v1.PersistentVolumeClaim{t.pvc}, false, cmd)
pod := e2epod.MakePod(f.Namespace.Name, nil, []*v1.PersistentVolumeClaim{t.pvc}, f.NamespacePodSecurityLevel, cmd)
expectedOutput := []string{pvTestData}
e2eoutput.TestContainerOutput(ctx, f, "pod consumes pv", pod, 0, expectedOutput)
}