Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions e2e/cephfs.go
Original file line number Diff line number Diff line change
Expand Up @@ -360,6 +360,26 @@ 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)
}

validateSubvolumeCount(f, 0, fileSystemName, subvolumegroup)
validateOmapCount(f, 0, cephfsType, metadataPool, volumesType)

err = deleteResource(cephFSExamplePath + "storageclass.yaml")
if err != nil {
framework.Failf("failed to delete CephFS storageclass: %v", err)
}
Comment thread
nixpanic marked this conversation as resolved.
})

By("verify mountOptions support", func() {
err := createCephfsStorageClass(f.ClientSet, f, true, nil)
if err != nil {
Expand Down
45 changes: 41 additions & 4 deletions e2e/cephfs_helper.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -67,6 +68,40 @@ func createCephfsStorageClass(
return err
}

err = updateStorageClassParameters(&sc, 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")
sc, err := getStorageClass(scPath)
if err != nil {
return err
}

err = updateStorageClassParameters(&sc, 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
Expand All @@ -93,18 +128,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) {
Expand Down
9 changes: 9 additions & 0 deletions e2e/pvc.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 nil
}

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{})
Expand Down
29 changes: 29 additions & 0 deletions e2e/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -557,6 +557,35 @@ 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 = createApp(f.ClientSet, app, deployTimeout)
if err != nil {
return err
}

err = deletePVCAndApp("", f, pvc, app)

return err
}

func getMountType(selector, mountPath string, f *framework.Framework) (string, error) {
opt := metav1.ListOptions{
LabelSelector: selector,
Expand Down