diff --git a/e2e/clone.go b/e2e/clone.go new file mode 100644 index 000000000..4f508ecad --- /dev/null +++ b/e2e/clone.go @@ -0,0 +1,100 @@ +/* +Copyright 2021 The Ceph-CSI 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 e2e + +import ( + "fmt" + + v1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/resource" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/kubernetes/test/e2e/framework" + e2elog "k8s.io/kubernetes/test/e2e/framework/log" +) + +func validateBiggerCloneFromPVC(f *framework.Framework, + pvcPath, + appPath, + pvcClonePath, + appClonePath string) error { + const ( + size = "1Gi" + newSize = "2Gi" + ) + pvc, err := loadPVC(pvcPath) + if err != nil { + return fmt.Errorf("failed to load PVC: %w", err) + } + label := make(map[string]string) + pvc.Namespace = f.UniqueName + pvc.Spec.Resources.Requests[v1.ResourceStorage] = resource.MustParse(size) + app, err := loadApp(appPath) + if err != nil { + return fmt.Errorf("failed to load app: %w", err) + } + label[appKey] = appLabel + app.Namespace = f.UniqueName + app.Labels = label + opt := metav1.ListOptions{ + LabelSelector: fmt.Sprintf("%s=%s", appKey, label[appKey]), + } + err = createPVCAndApp("", f, pvc, app, deployTimeout) + if err != nil { + return fmt.Errorf("failed to create pvc and application: %w", err) + } + + pvcClone, err := loadPVC(pvcClonePath) + if err != nil { + e2elog.Failf("failed to load PVC: %v", err) + } + pvcClone.Namespace = f.UniqueName + pvcClone.Spec.DataSource.Name = pvc.Name + pvcClone.Spec.Resources.Requests[v1.ResourceStorage] = resource.MustParse(newSize) + appClone, err := loadApp(appClonePath) + if err != nil { + e2elog.Failf("failed to load application: %v", err) + } + appClone.Namespace = f.UniqueName + appClone.Labels = label + err = createPVCAndApp("", f, pvcClone, appClone, deployTimeout) + if err != nil { + return fmt.Errorf("failed to create pvc clone and application: %w", err) + } + err = deletePVCAndApp("", f, pvc, app) + if err != nil { + return fmt.Errorf("failed to delete pvc and application: %w", err) + } + if pvcClone.Spec.VolumeMode == nil || *pvcClone.Spec.VolumeMode == v1.PersistentVolumeFilesystem { + err = checkDirSize(appClone, f, &opt, newSize) + if err != nil { + return err + } + } + + if pvcClone.Spec.VolumeMode != nil && *pvcClone.Spec.VolumeMode == v1.PersistentVolumeBlock { + err = checkDeviceSize(appClone, f, &opt, newSize) + if err != nil { + return err + } + } + err = deletePVCAndApp("", f, pvcClone, appClone) + if err != nil { + return fmt.Errorf("failed to delete pvc and application: %w", err) + } + + return nil +} diff --git a/e2e/rbd.go b/e2e/rbd.go index 3f6cc729b..3b6d42a7e 100644 --- a/e2e/rbd.go +++ b/e2e/rbd.go @@ -3444,6 +3444,77 @@ var _ = Describe("RBD", func() { }) }) + By("clone PVC to a bigger size PVC", func() { + By("clone PVC to bigger size encrypted PVC with VaultKMS", func() { + scOpts := map[string]string{ + "encrypted": "true", + "encryptionKMSID": "vault-test", + } + err := createRBDStorageClass(f.ClientSet, f, defaultSCName, nil, scOpts, deletePolicy) + if err != nil { + e2elog.Failf("failed to create storageclass: %v", err) + } + defer func() { + err = deleteResource(rbdExamplePath + "storageclass.yaml") + if err != nil { + e2elog.Failf("failed to delete storageclass: %v", err) + } + }() + + // validate filesystem mode PVC + err = validateBiggerCloneFromPVC(f, + pvcPath, + appPath, + pvcSmartClonePath, + appSmartClonePath) + if err != nil { + e2elog.Failf("failed to validate bigger size clone: %v", err) + } + // validate block mode PVC + err = validateBiggerCloneFromPVC(f, + rawPvcPath, + rawAppPath, + pvcBlockSmartClonePath, + appBlockSmartClonePath) + if err != nil { + e2elog.Failf("failed to validate bigger size clone: %v", err) + } + }) + + By("clone PVC to bigger size pvc", func() { + err := createRBDStorageClass(f.ClientSet, f, defaultSCName, nil, nil, deletePolicy) + if err != nil { + e2elog.Failf("failed to create storageclass: %v", err) + } + // validate filesystem mode PVC + err = validateBiggerCloneFromPVC(f, + pvcPath, + appPath, + pvcSmartClonePath, + appSmartClonePath) + if err != nil { + e2elog.Failf("failed to validate bigger size clone: %v", err) + } + // validate block mode PVC + err = validateBiggerCloneFromPVC(f, + rawPvcPath, + rawAppPath, + pvcBlockSmartClonePath, + appBlockSmartClonePath) + if err != nil { + e2elog.Failf("failed to validate bigger size clone: %v", err) + } + }) + + By("validate image deletion", func() { + validateRBDImageCount(f, 0, defaultRBDPool) + err := waitToRemoveImagesFromTrash(f, defaultRBDPool, deployTimeout) + if err != nil { + e2elog.Failf("failed to validate rbd images in pool %s trash: %v", defaultRBDPool, err) + } + }) + }) + // Make sure this should be last testcase in this file, because // it deletes pool By("Create a PVC and delete PVC when backend pool deleted", func() {