
All code must use the context from Ginkgo when doing API calls or polling for a change, otherwise the code would not return immediately when the test gets aborted.
178 lines
6.9 KiB
Go
178 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"
|
|
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 {
|
|
podErr := e2epod.WaitTimeoutForPodRunningInNamespace(ctx, m.cs, pod.Name, pod.Namespace, 10*time.Second)
|
|
framework.ExpectError(podErr, "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)
|
|
})
|
|
})
|
|
})
|