mirror of
https://github.com/ceph/ceph-csi.git
synced 2025-04-11 18:13:00 +00:00
e2e: test for PVC with volumeBindingMode on helm installation
Test PVC binding with WaitForFirstConsumer in Helm installation. Signed-off-by: ShravaniVangur <shravanivangur@gmail.com>
This commit is contained in:
parent
b6ef888dd8
commit
4eb795e535
@ -331,6 +331,23 @@ var _ = Describe(cephfsType, func() {
|
||||
})
|
||||
}
|
||||
|
||||
By("verify PVC and App Binding with volumeBindingMode:WaitForFirstConsumer", func() {
|
||||
err := createCephfsStorageClassWaitForFirstConsumer(f.ClientSet, f, true, nil)
|
||||
if err != nil {
|
||||
framework.Failf("failed to create CephFS storageclass: %v", err)
|
||||
}
|
||||
|
||||
err = validatePVCAndAppWaitForFirstConsumer(pvcPath, appPath, f)
|
||||
if err != nil {
|
||||
framework.Failf("failed to validate CephFS pvc and application binding: %v", err)
|
||||
}
|
||||
|
||||
err = deleteResource(cephFSExamplePath + "storageclass.yaml")
|
||||
if err != nil {
|
||||
framework.Failf("failed to delete CephFS storageclass: %v", err)
|
||||
}
|
||||
})
|
||||
|
||||
By("verify mountOptions support", func() {
|
||||
err := createCephfsStorageClass(f.ClientSet, f, true, nil)
|
||||
if err != nil {
|
||||
|
@ -26,6 +26,7 @@ import (
|
||||
|
||||
snapapi "github.com/kubernetes-csi/external-snapshotter/client/v8/apis/volumesnapshot/v1"
|
||||
v1 "k8s.io/api/core/v1"
|
||||
scv1 "k8s.io/api/storage/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/util/wait"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
@ -62,11 +63,49 @@ func createCephfsStorageClass(
|
||||
params map[string]string,
|
||||
) error {
|
||||
scPath := fmt.Sprintf("%s/%s", cephFSExamplePath, "storageclass.yaml")
|
||||
sc, err := getStorageClass(scPath)
|
||||
scValue, err := getStorageClass(scPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
sc := &scValue
|
||||
|
||||
err = updateStorageClassParameters(&scValue, params, enablePool, f)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return createStorageClass(c, sc)
|
||||
}
|
||||
|
||||
func createCephfsStorageClassWaitForFirstConsumer(c kubernetes.Interface, f *framework.Framework,
|
||||
enablePool bool,
|
||||
params map[string]string) error {
|
||||
scPath := fmt.Sprintf("%s/%s", cephFSExamplePath, "storageclass.yaml")
|
||||
scValue, err := getStorageClass(scPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
sc := &scValue
|
||||
|
||||
err = updateStorageClassParameters(&scValue, params, enablePool, f)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Set the volume binding mode to WaitForFirstConsumer
|
||||
value := scv1.VolumeBindingWaitForFirstConsumer
|
||||
sc.VolumeBindingMode = &value
|
||||
|
||||
return createStorageClass(c, sc)
|
||||
}
|
||||
|
||||
func updateStorageClassParameters(sc *scv1.StorageClass, params map[string]string, enablePool bool, f *framework.Framework) error {
|
||||
if sc == nil {
|
||||
return fmt.Errorf("StorageClass is nil")
|
||||
}
|
||||
|
||||
sc.Parameters["fsName"] = fileSystemName
|
||||
sc.Parameters["csi.storage.k8s.io/provisioner-secret-namespace"] = cephCSINamespace
|
||||
sc.Parameters["csi.storage.k8s.io/provisioner-secret-name"] = cephFSProvisionerSecretName
|
||||
@ -93,18 +132,20 @@ func createCephfsStorageClass(
|
||||
|
||||
// fetch and set fsID from the cluster if not set in params
|
||||
if _, found := params["clusterID"]; !found {
|
||||
var fsID string
|
||||
fsID, err = getClusterID(f)
|
||||
fsID, err := getClusterID(f)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get clusterID: %w", err)
|
||||
}
|
||||
sc.Parameters["clusterID"] = fsID
|
||||
}
|
||||
|
||||
timeout := time.Duration(deployTimeout) * time.Minute
|
||||
return nil
|
||||
}
|
||||
|
||||
func createStorageClass(c kubernetes.Interface, sc *scv1.StorageClass) error {
|
||||
timeout := time.Duration(deployTimeout) * time.Minute
|
||||
return wait.PollUntilContextTimeout(context.TODO(), poll, timeout, true, func(ctx context.Context) (bool, error) {
|
||||
_, err = c.StorageV1().StorageClasses().Create(ctx, &sc, metav1.CreateOptions{})
|
||||
_, err := c.StorageV1().StorageClasses().Create(ctx, sc, metav1.CreateOptions{})
|
||||
if err != nil {
|
||||
framework.Logf("error creating StorageClass %q: %v", sc.Name, err)
|
||||
if isRetryableAPIError(err) {
|
||||
|
@ -130,6 +130,15 @@ func createPVCAndPV(c kubernetes.Interface, pvc *v1.PersistentVolumeClaim, pv *v
|
||||
return err
|
||||
}
|
||||
|
||||
func createPVC(c kubernetes.Interface, pvc *v1.PersistentVolumeClaim) error {
|
||||
_, err := c.CoreV1().PersistentVolumeClaims(pvc.Namespace).Create(context.TODO(), pvc, metav1.CreateOptions{})
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to create pvc: %w", err)
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func deletePVCAndPV(c kubernetes.Interface, pvc *v1.PersistentVolumeClaim, pv *v1.PersistentVolume, t int) error {
|
||||
ctx := context.TODO()
|
||||
err := c.CoreV1().PersistentVolumeClaims(pvc.Namespace).Delete(ctx, pvc.Name, metav1.DeleteOptions{})
|
||||
|
54
e2e/utils.go
54
e2e/utils.go
@ -508,6 +508,60 @@ func validatePVCAndAppBinding(pvcPath, appPath string, f *framework.Framework) e
|
||||
return err
|
||||
}
|
||||
|
||||
// validatePVCAndAppWaitForFirstConsumer creates a Pending PVC, starts an app, and verifies it to become Bound.
|
||||
func validatePVCAndAppWaitForFirstConsumer(pvcPath, appPath string, f *framework.Framework) error {
|
||||
pvc, err := loadPVC(pvcPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
pvc.Namespace = f.UniqueName
|
||||
|
||||
app, err := loadApp(appPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
app.Namespace = f.UniqueName
|
||||
|
||||
err = createPVC(f.ClientSet, pvc)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = waitForPVCPhase(f.ClientSet, pvc.Namespace, pvc.Name, v1.ClaimPending, 30*time.Second)
|
||||
if err != nil {
|
||||
return fmt.Errorf("PVC did not stay in Pending state as expected: %w", err)
|
||||
}
|
||||
|
||||
err = createApp(f.ClientSet, app, deployTimeout)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = waitForPVCPhase(f.ClientSet, pvc.Namespace, pvc.Name, v1.ClaimBound, 30*time.Second)
|
||||
if err != nil {
|
||||
return fmt.Errorf("PVC did not reach Bound state after creating the pod: %w", err)
|
||||
}
|
||||
|
||||
err = deletePVCAndApp("", f, pvc, app)
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func waitForPVCPhase(c kubernetes.Interface, namespace, name string, phase v1.PersistentVolumeClaimPhase, timeout time.Duration) error {
|
||||
return wait.PollUntilContextTimeout(context.TODO(), poll, timeout, true, func(ctx context.Context) (bool, error) {
|
||||
pvc, err := c.CoreV1().PersistentVolumeClaims(namespace).Get(context.TODO(), name, metav1.GetOptions{})
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("error fetching PVC %q: %w", name, err)
|
||||
}
|
||||
if pvc.Status.Phase == phase {
|
||||
return true, nil
|
||||
}
|
||||
framework.Logf("Waiting for PVC %q to reach phase %q, current phase: %q", name, phase, pvc.Status.Phase)
|
||||
|
||||
return false, nil
|
||||
})
|
||||
}
|
||||
|
||||
func getMountType(selector, mountPath string, f *framework.Framework) (string, error) {
|
||||
opt := metav1.ListOptions{
|
||||
LabelSelector: selector,
|
||||
|
Loading…
Reference in New Issue
Block a user