Skip to content

Commit

Permalink
tests: Add e2e tests for copying labels to DataSources
Browse files Browse the repository at this point in the history
Add e2e tests that cover all scenarios where labels should be copied
from the source of a DataSource to the DataSource itself.

Signed-off-by: Felix Matouschek <[email protected]>
  • Loading branch information
0xFelix committed Aug 9, 2024
1 parent 802be3c commit 6ad379d
Show file tree
Hide file tree
Showing 2 changed files with 112 additions and 23 deletions.
123 changes: 100 additions & 23 deletions tests/datasource_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,13 @@ var _ = Describe("DataSource", func() {
pvc2Name = "pvc2"
snap1Name = "snap1"
snap2Name = "snap2"

testKubevirtIoKey = "test.kubevirt.io/test"
testKubevirtIoValue = "testvalue"
testInstancetypeKubevirtIoKey = "instancetype.kubevirt.io/default-preference"
testInstancetypeKubevirtIoValue = "testpreference"
testKubevirtIoKeyExisting = "test.kubevirt.io/existing"
testKubevirtIoNewValueExisting = "newvalue"
)

f := framework.NewFramework("datasource-func-test")
Expand Down Expand Up @@ -59,9 +66,10 @@ var _ = Describe("DataSource", func() {
}

testURL := func() string { return fmt.Sprintf(utils.TinyCoreQcow2URL, f.CdiInstallNs) }
createDv := func(pvcName, url string) {
createDv := func(pvcName, url string, labels map[string]string) {
By(fmt.Sprintf("creating DataVolume %s %s", pvcName, url))
dv := utils.NewDataVolumeWithHTTPImport(pvcName, "1Gi", url)
dv.Labels = labels
dv, err := utils.CreateDataVolumeFromDefinition(f.CdiClient, f.Namespace.Name, dv)
Expect(err).ToNot(HaveOccurred())
By("verifying pvc was created")
Expand All @@ -70,6 +78,22 @@ var _ = Describe("DataSource", func() {
f.ForceBindIfWaitForFirstConsumer(pvc)
}

createSnap := func(name string, labels map[string]string) *snapshotv1.VolumeSnapshot {
pvcDef := utils.NewPVCDefinition("snap-source-pvc", "1Gi", nil, nil)
pvcDef.Namespace = f.Namespace.Name
pvc, err := f.K8sClient.CoreV1().PersistentVolumeClaims(f.Namespace.Name).Create(context.TODO(), pvcDef, metav1.CreateOptions{})
Expect(err).ToNot(HaveOccurred())
f.ForceBindIfWaitForFirstConsumer(pvc)

snapClass := f.GetSnapshotClass()
snapshot := utils.NewVolumeSnapshot(name, pvc.Namespace, pvc.Name, &snapClass.Name)
snapshot.Labels = labels
err = f.CrClient.Create(context.TODO(), snapshot)
Expect(err).ToNot(HaveOccurred())

return snapshot
}

It("[test_id:8041]status conditions should be updated on pvc create/update/delete", func() {
By("Create DataSource with no source PVC")
ds := newDataSource(ds1Name)
Expand Down Expand Up @@ -98,7 +122,7 @@ var _ = Describe("DataSource", func() {
f.ExpectEvent(dv.Namespace).Should(ContainSubstring(dvc.CloneWithoutSource))

By("Create import DV so the missing DataSource source PVC will be ready")
createDv(pvc1Name, testURL())
createDv(pvc1Name, testURL(), nil)
ds = waitForReadyCondition(ds, corev1.ConditionTrue, "Ready")

By("Wait for the clone DV success")
Expand All @@ -114,6 +138,74 @@ var _ = Describe("DataSource", func() {
_ = waitForReadyCondition(ds, corev1.ConditionFalse, "NoSource")
})

DescribeTable("[test_id:TODO] Labels should be copied to DataSource", func(sourceFn func() cdiv1.DataSourceSource, createSource func()) {
By("Create source for DataSource")
createSource()

By("Create DataSource")
ds := newDataSource(ds1Name)
ds.Spec.Source = sourceFn()
ds, err := f.CdiClient.CdiV1beta1().DataSources(ds.Namespace).Create(context.TODO(), ds, metav1.CreateOptions{})
Expect(err).ToNot(HaveOccurred())
ds = waitForReadyCondition(ds, corev1.ConditionTrue, "Ready")

By("Check for labels on DataSource")
Eventually(func(g Gomega) {
ds, err := f.CdiClient.CdiV1beta1().DataSources(ds.Namespace).Get(context.TODO(), ds.Name, metav1.GetOptions{})
g.Expect(err).ToNot(HaveOccurred())
g.Expect(ds.Labels).To(HaveKeyWithValue(testKubevirtIoKey, testKubevirtIoValue))
g.Expect(ds.Labels).To(HaveKeyWithValue(testInstancetypeKubevirtIoKey, testInstancetypeKubevirtIoValue))
g.Expect(ds.Labels).To(HaveKeyWithValue(testKubevirtIoKeyExisting, testKubevirtIoNewValueExisting))
}, 60*time.Second, pollingInterval).Should(Succeed())
},
Entry("from DataVolume",
func() cdiv1.DataSourceSource {
return cdiv1.DataSourceSource{
PVC: &cdiv1.DataVolumeSourcePVC{Namespace: f.Namespace.Name, Name: pvc1Name},
}
},
func() {
createDv(pvc1Name, testURL(), map[string]string{
testKubevirtIoKey: testKubevirtIoValue,
testInstancetypeKubevirtIoKey: testInstancetypeKubevirtIoValue,
testKubevirtIoKeyExisting: testKubevirtIoNewValueExisting,
})
},
),
Entry("from PersistentVolumeClaim",
func() cdiv1.DataSourceSource {
return cdiv1.DataSourceSource{
PVC: &cdiv1.DataVolumeSourcePVC{Namespace: f.Namespace.Name, Name: pvc1Name},
}
},
func() {
createDv(pvc1Name, testURL(), map[string]string{
testKubevirtIoKey: testKubevirtIoValue,
testInstancetypeKubevirtIoKey: testInstancetypeKubevirtIoValue,
testKubevirtIoKeyExisting: testKubevirtIoNewValueExisting,
})
err := utils.WaitForDataVolumePhase(f, f.Namespace.Name, cdiv1.Succeeded, pvc1Name)
Expect(err).ToNot(HaveOccurred())
err = utils.DeleteDataVolumeOrphanPVC(f.CdiClient, f.Namespace.Name, pvc1Name)
Expect(err).ToNot(HaveOccurred())
},
),
Entry("from VolumeSnapshot",
func() cdiv1.DataSourceSource {
return cdiv1.DataSourceSource{
Snapshot: &cdiv1.DataVolumeSourceSnapshot{Namespace: f.Namespace.Name, Name: snap1Name},
}
},
func() {
createSnap(snap1Name, map[string]string{
testKubevirtIoKey: testKubevirtIoValue,
testInstancetypeKubevirtIoKey: testInstancetypeKubevirtIoValue,
testKubevirtIoKeyExisting: testKubevirtIoNewValueExisting,
})
},
),
)

createDs := func(dsName, pvcName string) *cdiv1.DataSource {
By(fmt.Sprintf("creating DataSource %s -> %s", dsName, pvcName))
ds := newDataSource(dsName)
Expand All @@ -131,7 +223,7 @@ var _ = Describe("DataSource", func() {
}

It("[test_id:8067]status conditions should be updated when several DataSources refer the same pvc", func() {
createDv(pvc1Name, testURL())
createDv(pvc1Name, testURL(), nil)
ds1 := createDs(ds1Name, pvc1Name)
ds2 := createDs(ds2Name, pvc1Name)

Expand All @@ -142,7 +234,7 @@ var _ = Describe("DataSource", func() {
ds1 = waitForReadyCondition(ds1, corev1.ConditionFalse, "NotFound")
ds2 = waitForReadyCondition(ds2, corev1.ConditionFalse, "NotFound")

createDv(pvc2Name, testURL()+"bad")
createDv(pvc2Name, testURL()+"bad", nil)
updateDsPvc(ds1, pvc2Name)
updateDsPvc(ds2, pvc2Name)
ds1 = waitForReadyCondition(ds1, corev1.ConditionFalse, "ImportInProgress")
Expand All @@ -154,14 +246,14 @@ var _ = Describe("DataSource", func() {
})

It("status conditions timestamp should be updated when DataSource referred pvc is updated, although condition status does not change", func() {
createDv(pvc1Name, testURL())
createDv(pvc1Name, testURL(), nil)
ds := createDs(ds1Name, pvc1Name)
ds = waitForReadyCondition(ds, corev1.ConditionTrue, "Ready")
cond := controller.FindDataSourceConditionByType(ds, cdiv1.DataSourceReady)
Expect(cond).ToNot(BeNil())
ts := cond.LastTransitionTime

createDv(pvc2Name, testURL())
createDv(pvc2Name, testURL(), nil)
err := utils.WaitForDataVolumePhase(f, f.Namespace.Name, cdiv1.Succeeded, pvc2Name)
Expect(err).ToNot(HaveOccurred())
updateDsPvc(ds, pvc2Name)
Expand All @@ -177,21 +269,6 @@ var _ = Describe("DataSource", func() {
})

Context("snapshot source", func() {
createSnap := func(name string) *snapshotv1.VolumeSnapshot {
pvcDef := utils.NewPVCDefinition("snap-source-pvc", "1Gi", nil, nil)
pvcDef.Namespace = f.Namespace.Name
pvc, err := f.K8sClient.CoreV1().PersistentVolumeClaims(f.Namespace.Name).Create(context.TODO(), pvcDef, metav1.CreateOptions{})
Expect(err).ToNot(HaveOccurred())
f.ForceBindIfWaitForFirstConsumer(pvc)

snapClass := f.GetSnapshotClass()
snapshot := utils.NewVolumeSnapshot(name, pvc.Namespace, pvc.Name, &snapClass.Name)
err = f.CrClient.Create(context.TODO(), snapshot)
Expect(err).ToNot(HaveOccurred())

return snapshot
}

createSnapDs := func(dsName, snapName string) *cdiv1.DataSource {
By(fmt.Sprintf("creating DataSource %s -> %s", dsName, snapName))
ds := newDataSource(dsName)
Expand Down Expand Up @@ -235,7 +312,7 @@ var _ = Describe("DataSource", func() {
f.ExpectEvent(dv.Namespace).Should(ContainSubstring(dvc.CloneWithoutSource))

By("Create snapshot so the DataSource will be ready")
snapshot := createSnap(snap1Name)
snapshot := createSnap(snap1Name, nil)
ds = waitForReadyCondition(ds, corev1.ConditionTrue, "Ready")

By("Wait for the clone DV success")
Expand All @@ -253,7 +330,7 @@ var _ = Describe("DataSource", func() {
})

It("[test_id:9763] status conditions should be updated when several DataSources refer the same snapshot", func() {
snapshot := createSnap(snap1Name)
snapshot := createSnap(snap1Name, nil)
ds1 := createSnapDs(ds1Name, snap1Name)
ds2 := createSnapDs(ds2Name, snap1Name)

Expand Down
12 changes: 12 additions & 0 deletions tests/utils/datavolume.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import (
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/util/wait"
"k8s.io/client-go/kubernetes"
"k8s.io/utils/ptr"

cdiv1 "kubevirt.io/containerized-data-importer-api/pkg/apis/core/v1beta1"
cdiclientset "kubevirt.io/containerized-data-importer/pkg/client/clientset/versioned"
Expand Down Expand Up @@ -138,6 +139,17 @@ func DeleteDataVolume(clientSet *cdiclientset.Clientset, namespace, name string)
})
}

// DeleteDataVolumeOrphanPVC deletes the DataVolume with the given name and orphans the PVC owned by the DV
func DeleteDataVolumeOrphanPVC(clientSet *cdiclientset.Clientset, namespace, name string) error {
return wait.PollUntilContextTimeout(context.TODO(), dataVolumePollInterval, dataVolumeDeleteTime, true, func(ctx context.Context) (bool, error) {
err := clientSet.CdiV1beta1().DataVolumes(namespace).Delete(ctx, name, metav1.DeleteOptions{PropagationPolicy: ptr.To(metav1.DeletePropagationOrphan)})
if err == nil || apierrs.IsNotFound(err) {
return true, nil
}
return false, err
})
}

// CleanupDvPvc deletes DV or PVC if DV was GCed, and waits for PVC to be gone
func CleanupDvPvc(k8sClient *kubernetes.Clientset, cdiClient *cdiclientset.Clientset, namespace, name string) {
CleanupDvPvcNoWait(k8sClient, cdiClient, namespace, name)
Expand Down

0 comments on commit 6ad379d

Please sign in to comment.