mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-19 09:52:49 +00:00
Using WaitTimeoutForPodRunningInNamespace followed by ExpectError was not very precise (any error passed the check, not just the expected timeout) and hard to read. Now the test's expectation is spelled out explicitly: the pod must stay in pending.
181 lines
6.9 KiB
Go
181 lines
6.9 KiB
Go
/*
|
|
Copyright 2022 The Kubernetes Authors.
|
|
|
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|
you may not use this file except in compliance with the License.
|
|
You may obtain a copy of the License at
|
|
|
|
http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
Unless required by applicable law or agreed to in writing, software
|
|
distributed under the License is distributed on an "AS IS" BASIS,
|
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
See the License for the specific language governing permissions and
|
|
limitations under the License.
|
|
*/
|
|
|
|
package csi_mock
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"time"
|
|
|
|
"github.com/onsi/ginkgo/v2"
|
|
"github.com/onsi/gomega"
|
|
v1 "k8s.io/api/core/v1"
|
|
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
|
"k8s.io/apimachinery/pkg/fields"
|
|
"k8s.io/kubernetes/pkg/kubelet/events"
|
|
"k8s.io/kubernetes/test/e2e/framework"
|
|
e2eevents "k8s.io/kubernetes/test/e2e/framework/events"
|
|
e2epod "k8s.io/kubernetes/test/e2e/framework/pod"
|
|
e2evolume "k8s.io/kubernetes/test/e2e/framework/volume"
|
|
storageframework "k8s.io/kubernetes/test/e2e/storage/framework"
|
|
"k8s.io/kubernetes/test/e2e/storage/utils"
|
|
admissionapi "k8s.io/pod-security-admission/api"
|
|
)
|
|
|
|
var _ = utils.SIGDescribe("CSI Mock volume attach", func() {
|
|
// The CSIDriverRegistry feature gate is needed for this test in Kubernetes 1.12.
|
|
f := framework.NewDefaultFramework("csi-mock-volumes-attach")
|
|
f.NamespacePodSecurityEnforceLevel = admissionapi.LevelPrivileged
|
|
m := newMockDriverSetup(f)
|
|
|
|
ginkgo.Context("CSI attach test using mock driver", func() {
|
|
tests := []struct {
|
|
name string
|
|
disableAttach bool
|
|
deployClusterRegistrar bool
|
|
volumeType volumeType
|
|
}{
|
|
{
|
|
name: "should not require VolumeAttach for drivers without attachment",
|
|
disableAttach: true,
|
|
deployClusterRegistrar: true,
|
|
},
|
|
{
|
|
name: "should require VolumeAttach for drivers with attachment",
|
|
deployClusterRegistrar: true,
|
|
},
|
|
{
|
|
name: "should require VolumeAttach for ephemermal volume and drivers with attachment",
|
|
deployClusterRegistrar: true,
|
|
volumeType: genericEphemeral,
|
|
},
|
|
{
|
|
name: "should preserve attachment policy when no CSIDriver present",
|
|
deployClusterRegistrar: false,
|
|
},
|
|
}
|
|
for _, t := range tests {
|
|
test := t
|
|
ginkgo.It(t.name, func(ctx context.Context) {
|
|
var err error
|
|
m.init(ctx, testParameters{registerDriver: test.deployClusterRegistrar, disableAttach: test.disableAttach})
|
|
ginkgo.DeferCleanup(m.cleanup)
|
|
|
|
volumeType := test.volumeType
|
|
if volumeType == "" {
|
|
volumeType = pvcReference
|
|
}
|
|
_, claim, pod := m.createPod(ctx, volumeType)
|
|
if pod == nil {
|
|
return
|
|
}
|
|
err = e2epod.WaitForPodNameRunningInNamespace(ctx, m.cs, pod.Name, pod.Namespace)
|
|
framework.ExpectNoError(err, "Failed to start pod: %v", err)
|
|
|
|
ginkgo.By("Checking if VolumeAttachment was created for the pod")
|
|
testConfig := storageframework.ConvertTestConfig(m.config)
|
|
attachmentName := e2evolume.GetVolumeAttachmentName(ctx, m.cs, testConfig, m.provisioner, claim.Name, claim.Namespace)
|
|
_, err = m.cs.StorageV1().VolumeAttachments().Get(context.TODO(), attachmentName, metav1.GetOptions{})
|
|
if err != nil {
|
|
if apierrors.IsNotFound(err) {
|
|
if !test.disableAttach {
|
|
framework.ExpectNoError(err, "Expected VolumeAttachment but none was found")
|
|
}
|
|
} else {
|
|
framework.ExpectNoError(err, "Failed to find VolumeAttachment")
|
|
}
|
|
}
|
|
if test.disableAttach {
|
|
framework.ExpectError(err, "Unexpected VolumeAttachment found")
|
|
}
|
|
})
|
|
|
|
}
|
|
})
|
|
|
|
ginkgo.Context("CSI CSIDriver deployment after pod creation using non-attachable mock driver", func() {
|
|
ginkgo.It("should bringup pod after deploying CSIDriver attach=false [Slow]", func(ctx context.Context) {
|
|
var err error
|
|
m.init(ctx, testParameters{registerDriver: false, disableAttach: true})
|
|
ginkgo.DeferCleanup(m.cleanup)
|
|
|
|
_, claim, pod := m.createPod(ctx, pvcReference) // late binding as specified above
|
|
if pod == nil {
|
|
return
|
|
}
|
|
|
|
ginkgo.By("Checking if attaching failed and pod cannot start")
|
|
eventSelector := fields.Set{
|
|
"involvedObject.kind": "Pod",
|
|
"involvedObject.name": pod.Name,
|
|
"involvedObject.namespace": pod.Namespace,
|
|
"reason": events.FailedAttachVolume,
|
|
}.AsSelector().String()
|
|
msg := "AttachVolume.Attach failed for volume"
|
|
|
|
err = e2eevents.WaitTimeoutForEvent(ctx, m.cs, pod.Namespace, eventSelector, msg, f.Timeouts.PodStart)
|
|
if err != nil {
|
|
getPod := e2epod.Get(m.cs, pod)
|
|
gomega.Consistently(ctx, getPod).WithTimeout(10*time.Second).Should(e2epod.BeInPhase(v1.PodPending),
|
|
"Pod should not be in running status because attaching should failed")
|
|
// Events are unreliable, don't depend on the event. It's used only to speed up the test.
|
|
framework.Logf("Attach should fail and the corresponding event should show up, error: %v", err)
|
|
}
|
|
|
|
// VolumeAttachment should be created because the default value for CSI attachable is true
|
|
ginkgo.By("Checking if VolumeAttachment was created for the pod")
|
|
testConfig := storageframework.ConvertTestConfig(m.config)
|
|
attachmentName := e2evolume.GetVolumeAttachmentName(ctx, m.cs, testConfig, m.provisioner, claim.Name, claim.Namespace)
|
|
_, err = m.cs.StorageV1().VolumeAttachments().Get(context.TODO(), attachmentName, metav1.GetOptions{})
|
|
if err != nil {
|
|
if apierrors.IsNotFound(err) {
|
|
framework.ExpectNoError(err, "Expected VolumeAttachment but none was found")
|
|
} else {
|
|
framework.ExpectNoError(err, "Failed to find VolumeAttachment")
|
|
}
|
|
}
|
|
|
|
ginkgo.By("Deploy CSIDriver object with attachRequired=false")
|
|
driverNamespace := m.config.DriverNamespace
|
|
|
|
canAttach := false
|
|
o := utils.PatchCSIOptions{
|
|
OldDriverName: "csi-mock",
|
|
NewDriverName: "csi-mock-" + f.UniqueName,
|
|
CanAttach: &canAttach,
|
|
}
|
|
err = utils.CreateFromManifests(ctx, f, driverNamespace, func(item interface{}) error {
|
|
return utils.PatchCSIDeployment(f, o, item)
|
|
}, "test/e2e/testing-manifests/storage-csi/mock/csi-mock-driverinfo.yaml")
|
|
if err != nil {
|
|
framework.Failf("fail to deploy CSIDriver object: %v", err)
|
|
}
|
|
|
|
ginkgo.By("Wait for the pod in running status")
|
|
err = e2epod.WaitForPodNameRunningInNamespace(ctx, m.cs, pod.Name, pod.Namespace)
|
|
framework.ExpectNoError(err, "Failed to start pod: %v", err)
|
|
|
|
ginkgo.By(fmt.Sprintf("Wait for the volumeattachment to be deleted up to %v", csiVolumeAttachmentTimeout))
|
|
// This step can be slow because we have to wait either a NodeUpdate event happens or
|
|
// the detachment for this volume timeout so that we can do a force detach.
|
|
err = e2evolume.WaitForVolumeAttachmentTerminated(ctx, attachmentName, m.cs, csiVolumeAttachmentTimeout)
|
|
framework.ExpectNoError(err, "Failed to delete VolumeAttachment: %v", err)
|
|
})
|
|
})
|
|
})
|