mirror of
https://github.com/kubevirt/containerized-data-importer.git
synced 2025-06-03 06:30:22 +00:00

* touch up zero restoresize snapshot Signed-off-by: Michael Henriksen <mhenriks@redhat.com> * clone populator only supports PVC source now snapshot coming soon Signed-off-by: Michael Henriksen <mhenriks@redhat.com> * more unit tests Signed-off-by: Michael Henriksen <mhenriks@redhat.com> * unit test for clone populator Signed-off-by: Michael Henriksen <mhenriks@redhat.com> * func tests for clone populator Signed-off-by: Michael Henriksen <mhenriks@redhat.com> * move clone populator cleanup function to planner other review comments verifier pod should bount readonly Signed-off-by: Michael Henriksen <mhenriks@redhat.com> * add readonly flag to test executor pods synchronize get hash calls Signed-off-by: Michael Henriksen <mhenriks@redhat.com> * increase linter timeout Signed-off-by: Michael Henriksen <mhenriks@redhat.com> * better/explicit readonly support for test pods Signed-off-by: Michael Henriksen <mhenriks@redhat.com> * check pv for driver info before looking up storageclass as it may not exist Signed-off-by: Michael Henriksen <mhenriks@redhat.com> * addressed review comments Signed-off-by: Michael Henriksen <mhenriks@redhat.com> * chooseStrategy shoud generate more events Signed-off-by: Michael Henriksen <mhenriks@redhat.com> --------- Signed-off-by: Michael Henriksen <mhenriks@redhat.com>
624 lines
20 KiB
Go
624 lines
20 KiB
Go
/*
|
|
Copyright 2023 The CDI 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 clone
|
|
|
|
import (
|
|
"context"
|
|
"strings"
|
|
|
|
. "github.com/onsi/ginkgo"
|
|
. "github.com/onsi/gomega"
|
|
|
|
snapshotv1 "github.com/kubernetes-csi/external-snapshotter/client/v6/apis/volumesnapshot/v1"
|
|
corev1 "k8s.io/api/core/v1"
|
|
storagev1 "k8s.io/api/storage/v1"
|
|
k8serrors "k8s.io/apimachinery/pkg/api/errors"
|
|
"k8s.io/apimachinery/pkg/api/resource"
|
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
|
"k8s.io/apimachinery/pkg/runtime"
|
|
"k8s.io/apimachinery/pkg/types"
|
|
"k8s.io/client-go/kubernetes/scheme"
|
|
"k8s.io/client-go/tools/record"
|
|
"k8s.io/utils/pointer"
|
|
"sigs.k8s.io/controller-runtime/pkg/client"
|
|
"sigs.k8s.io/controller-runtime/pkg/client/fake"
|
|
logf "sigs.k8s.io/controller-runtime/pkg/log"
|
|
|
|
cdiv1 "kubevirt.io/containerized-data-importer-api/pkg/apis/core/v1beta1"
|
|
cc "kubevirt.io/containerized-data-importer/pkg/controller/common"
|
|
)
|
|
|
|
var _ = Describe("Planner test", func() {
|
|
log := logf.Log.WithName("planner-test")
|
|
|
|
const (
|
|
namespace = "ns"
|
|
sourceName = "source"
|
|
targetName = "target"
|
|
ownerLabel = "label"
|
|
volumeName = "sourceVolume"
|
|
driverName = "driver"
|
|
)
|
|
|
|
var (
|
|
storageClassName = "sc"
|
|
|
|
small = resource.MustParse("5Gi")
|
|
medium = resource.MustParse("10Gi")
|
|
large = resource.MustParse("15Gi")
|
|
)
|
|
|
|
createPlanner := func(objects ...runtime.Object) *Planner {
|
|
s := scheme.Scheme
|
|
_ = cdiv1.AddToScheme(s)
|
|
_ = snapshotv1.AddToScheme(s)
|
|
|
|
objects = append(objects, cc.MakeEmptyCDICR())
|
|
|
|
// Create a fake client to mock API calls.
|
|
builder := fake.NewClientBuilder().
|
|
WithScheme(s).
|
|
WithRuntimeObjects(objects...)
|
|
|
|
cl := builder.Build()
|
|
|
|
rec := record.NewFakeRecorder(10)
|
|
|
|
return &Planner{
|
|
RootObjectType: &corev1.PersistentVolumeClaimList{},
|
|
OwnershipLabel: ownerLabel,
|
|
UIDField: "uid",
|
|
Image: "image",
|
|
PullPolicy: corev1.PullIfNotPresent,
|
|
InstallerLabels: map[string]string{
|
|
"key": "value",
|
|
},
|
|
Client: cl,
|
|
Recorder: rec,
|
|
watchingSnapshots: true,
|
|
}
|
|
}
|
|
|
|
createDataSource := func() *cdiv1.VolumeCloneSource {
|
|
return &cdiv1.VolumeCloneSource{
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
Name: "vcs",
|
|
Namespace: namespace,
|
|
},
|
|
Spec: cdiv1.VolumeCloneSourceSpec{
|
|
Source: corev1.TypedLocalObjectReference{
|
|
Kind: "PersistentVolumeClaim",
|
|
Name: sourceName,
|
|
},
|
|
},
|
|
}
|
|
}
|
|
|
|
createClaim := func(name string) *corev1.PersistentVolumeClaim {
|
|
return &corev1.PersistentVolumeClaim{
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
Name: name,
|
|
Namespace: namespace,
|
|
UID: types.UID(name + "-uid"),
|
|
},
|
|
Spec: corev1.PersistentVolumeClaimSpec{
|
|
Resources: corev1.ResourceRequirements{
|
|
Requests: corev1.ResourceList{
|
|
corev1.ResourceStorage: medium,
|
|
},
|
|
},
|
|
StorageClassName: &storageClassName,
|
|
},
|
|
}
|
|
}
|
|
|
|
createTargetClaim := func() *corev1.PersistentVolumeClaim {
|
|
return createClaim(targetName)
|
|
}
|
|
|
|
createSourceClaim := func() *corev1.PersistentVolumeClaim {
|
|
s := createClaim(sourceName)
|
|
s.Spec.VolumeName = volumeName
|
|
s.Status.Capacity = corev1.ResourceList{
|
|
corev1.ResourceStorage: s.Spec.Resources.Requests[corev1.ResourceStorage],
|
|
}
|
|
return s
|
|
}
|
|
|
|
createSourceVolume := func() *corev1.PersistentVolume {
|
|
return &corev1.PersistentVolume{
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
Name: volumeName,
|
|
},
|
|
Spec: corev1.PersistentVolumeSpec{
|
|
Capacity: corev1.ResourceList{
|
|
corev1.ResourceStorage: small,
|
|
},
|
|
StorageClassName: storageClassName,
|
|
PersistentVolumeSource: corev1.PersistentVolumeSource{
|
|
CSI: &corev1.CSIPersistentVolumeSource{
|
|
Driver: driverName,
|
|
},
|
|
},
|
|
ClaimRef: &corev1.ObjectReference{
|
|
Namespace: namespace,
|
|
Name: sourceName,
|
|
},
|
|
},
|
|
}
|
|
}
|
|
|
|
createStorageClass := func() *storagev1.StorageClass {
|
|
return &storagev1.StorageClass{
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
Name: storageClassName,
|
|
},
|
|
Provisioner: driverName,
|
|
AllowVolumeExpansion: pointer.Bool(true),
|
|
}
|
|
}
|
|
|
|
createVolumeSnapshotClass := func() *snapshotv1.VolumeSnapshotClass {
|
|
return &snapshotv1.VolumeSnapshotClass{
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
Name: "vsc",
|
|
},
|
|
Driver: createStorageClass().Provisioner,
|
|
}
|
|
}
|
|
|
|
expectEvent := func(planner *Planner, event string) {
|
|
close(planner.Recorder.(*record.FakeRecorder).Events)
|
|
found := false
|
|
for e := range planner.Recorder.(*record.FakeRecorder).Events {
|
|
if strings.Contains(e, event) {
|
|
found = true
|
|
}
|
|
}
|
|
planner.Recorder = nil
|
|
Expect(found).To(BeTrue())
|
|
}
|
|
|
|
Context("ChooseStrategy tests", func() {
|
|
|
|
It("should error if unsupported kind", func() {
|
|
source := createDataSource()
|
|
source.Spec.Source.Kind = "UnsupportedKind"
|
|
args := &ChooseStrategyArgs{
|
|
DataSource: source,
|
|
Log: log,
|
|
}
|
|
planner := createPlanner()
|
|
_, err := planner.ChooseStrategy(context.Background(), args)
|
|
Expect(err).To(HaveOccurred())
|
|
Expect(err.Error()).To(Equal("unsupported datasource"))
|
|
})
|
|
|
|
It("should return nil if no storageclass name", func() {
|
|
tc := createTargetClaim()
|
|
tc.Spec.StorageClassName = nil
|
|
args := &ChooseStrategyArgs{
|
|
TargetClaim: tc,
|
|
DataSource: createDataSource(),
|
|
Log: log,
|
|
}
|
|
planner := createPlanner()
|
|
strategy, err := planner.ChooseStrategy(context.Background(), args)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
Expect(strategy).To(BeNil())
|
|
})
|
|
|
|
It("should error if emptystring storageclass name", func() {
|
|
tc := createTargetClaim()
|
|
tc.Spec.StorageClassName = pointer.String("")
|
|
args := &ChooseStrategyArgs{
|
|
TargetClaim: tc,
|
|
DataSource: createDataSource(),
|
|
Log: log,
|
|
}
|
|
planner := createPlanner()
|
|
strategy, err := planner.ChooseStrategy(context.Background(), args)
|
|
Expect(err).To(HaveOccurred())
|
|
Expect(err.Error()).To(Equal("claim has emptystring storageclass, will not work"))
|
|
Expect(strategy).To(BeNil())
|
|
})
|
|
|
|
It("should error if no storageclass exists", func() {
|
|
args := &ChooseStrategyArgs{
|
|
TargetClaim: createTargetClaim(),
|
|
DataSource: createDataSource(),
|
|
Log: log,
|
|
}
|
|
planner := createPlanner()
|
|
strategy, err := planner.ChooseStrategy(context.Background(), args)
|
|
Expect(err).To(HaveOccurred())
|
|
Expect(err.Error()).To(Equal("target storage class not found"))
|
|
Expect(strategy).To(BeNil())
|
|
})
|
|
|
|
It("should return nil if no source", func() {
|
|
args := &ChooseStrategyArgs{
|
|
TargetClaim: createTargetClaim(),
|
|
DataSource: createDataSource(),
|
|
Log: log,
|
|
}
|
|
planner := createPlanner(createStorageClass())
|
|
strategy, err := planner.ChooseStrategy(context.Background(), args)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
Expect(strategy).To(BeNil())
|
|
expectEvent(planner, CloneWithoutSource)
|
|
})
|
|
|
|
It("should fail target smaller", func() {
|
|
source := createSourceClaim()
|
|
target := createTargetClaim()
|
|
target.Spec.Resources.Requests[corev1.ResourceStorage] = small
|
|
args := &ChooseStrategyArgs{
|
|
TargetClaim: target,
|
|
DataSource: createDataSource(),
|
|
Log: log,
|
|
}
|
|
planner := createPlanner(createStorageClass(), source)
|
|
strategy, err := planner.ChooseStrategy(context.Background(), args)
|
|
Expect(err).To(HaveOccurred())
|
|
Expect(err.Error()).To(Equal("target resources requests storage size is smaller than the source"))
|
|
Expect(strategy).To(BeNil())
|
|
expectEvent(planner, CloneValidationFailed)
|
|
})
|
|
|
|
It("should return host assisted with no volumesnapshotclass", func() {
|
|
args := &ChooseStrategyArgs{
|
|
TargetClaim: createTargetClaim(),
|
|
DataSource: createDataSource(),
|
|
Log: log,
|
|
}
|
|
planner := createPlanner(createStorageClass(), createSourceClaim())
|
|
strategy, err := planner.ChooseStrategy(context.Background(), args)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
Expect(strategy).ToNot(BeNil())
|
|
Expect(*strategy).To(Equal(cdiv1.CloneStrategyHostAssisted))
|
|
expectEvent(planner, NoVolumeSnapshotClass)
|
|
})
|
|
|
|
It("should return snapshot with volumesnapshotclass", func() {
|
|
args := &ChooseStrategyArgs{
|
|
TargetClaim: createTargetClaim(),
|
|
DataSource: createDataSource(),
|
|
Log: log,
|
|
}
|
|
planner := createPlanner(createStorageClass(), createSourceClaim(), createVolumeSnapshotClass(), createSourceVolume())
|
|
strategy, err := planner.ChooseStrategy(context.Background(), args)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
Expect(strategy).ToNot(BeNil())
|
|
Expect(*strategy).To(Equal(cdiv1.CloneStrategySnapshot))
|
|
})
|
|
|
|
It("should return snapshot with volumesnapshotclass (no source vol)", func() {
|
|
args := &ChooseStrategyArgs{
|
|
TargetClaim: createTargetClaim(),
|
|
DataSource: createDataSource(),
|
|
Log: log,
|
|
}
|
|
planner := createPlanner(createStorageClass(), createSourceClaim(), createVolumeSnapshotClass())
|
|
strategy, err := planner.ChooseStrategy(context.Background(), args)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
Expect(strategy).ToNot(BeNil())
|
|
Expect(*strategy).To(Equal(cdiv1.CloneStrategySnapshot))
|
|
})
|
|
|
|
It("should return snapshot with volumesnapshotclass and source storageclass does not exist but same driver", func() {
|
|
sourceClaim := createSourceClaim()
|
|
sourceVolume := createSourceVolume()
|
|
sourceVolume.Spec.StorageClassName = "baz"
|
|
sourceClaim.Spec.StorageClassName = pointer.String(sourceVolume.Spec.StorageClassName)
|
|
args := &ChooseStrategyArgs{
|
|
TargetClaim: createTargetClaim(),
|
|
DataSource: createDataSource(),
|
|
Log: log,
|
|
}
|
|
planner := createPlanner(createStorageClass(), createVolumeSnapshotClass(), sourceClaim, sourceVolume)
|
|
strategy, err := planner.ChooseStrategy(context.Background(), args)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
Expect(strategy).ToNot(BeNil())
|
|
Expect(*strategy).To(Equal(cdiv1.CloneStrategySnapshot))
|
|
})
|
|
|
|
It("should returnsnapshot with bigger target", func() {
|
|
target := createTargetClaim()
|
|
target.Spec.Resources.Requests[corev1.ResourceStorage] = large
|
|
args := &ChooseStrategyArgs{
|
|
TargetClaim: target,
|
|
DataSource: createDataSource(),
|
|
Log: log,
|
|
}
|
|
planner := createPlanner(createStorageClass(), createSourceClaim(), createVolumeSnapshotClass())
|
|
strategy, err := planner.ChooseStrategy(context.Background(), args)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
Expect(strategy).ToNot(BeNil())
|
|
Expect(*strategy).To(Equal(cdiv1.CloneStrategySnapshot))
|
|
})
|
|
|
|
It("should return host assisted with bigger target and no volumeexpansion", func() {
|
|
storageClass := createStorageClass()
|
|
storageClass.AllowVolumeExpansion = nil
|
|
target := createTargetClaim()
|
|
target.Spec.Resources.Requests[corev1.ResourceStorage] = large
|
|
args := &ChooseStrategyArgs{
|
|
TargetClaim: target,
|
|
DataSource: createDataSource(),
|
|
Log: log,
|
|
}
|
|
planner := createPlanner(storageClass, createSourceClaim(), createVolumeSnapshotClass())
|
|
strategy, err := planner.ChooseStrategy(context.Background(), args)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
Expect(strategy).ToNot(BeNil())
|
|
Expect(*strategy).To(Equal(cdiv1.CloneStrategyHostAssisted))
|
|
expectEvent(planner, NoVolumeExpansion)
|
|
})
|
|
|
|
It("should return host assisted with non matching volume modes", func() {
|
|
bm := corev1.PersistentVolumeBlock
|
|
source := createSourceClaim()
|
|
source.Spec.VolumeMode = &bm
|
|
args := &ChooseStrategyArgs{
|
|
TargetClaim: createTargetClaim(),
|
|
DataSource: createDataSource(),
|
|
Log: log,
|
|
}
|
|
planner := createPlanner(createStorageClass(), createVolumeSnapshotClass(), source)
|
|
strategy, err := planner.ChooseStrategy(context.Background(), args)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
Expect(strategy).ToNot(BeNil())
|
|
Expect(*strategy).To(Equal(cdiv1.CloneStrategyHostAssisted))
|
|
expectEvent(planner, IncompatibleVolumeModes)
|
|
})
|
|
|
|
It("should return csi-clone if global override is set", func() {
|
|
cs := cdiv1.CloneStrategyCsiClone
|
|
args := &ChooseStrategyArgs{
|
|
TargetClaim: createTargetClaim(),
|
|
DataSource: createDataSource(),
|
|
Log: log,
|
|
}
|
|
planner := createPlanner(createStorageClass(), createSourceClaim())
|
|
cdi := &cdiv1.CDI{}
|
|
err := planner.Client.Get(context.Background(), client.ObjectKeyFromObject(cc.MakeEmptyCDICR()), cdi)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
cdi.Spec.CloneStrategyOverride = &cs
|
|
err = planner.Client.Update(context.Background(), cdi)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
strategy, err := planner.ChooseStrategy(context.Background(), args)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
Expect(strategy).ToNot(BeNil())
|
|
Expect(*strategy).To(Equal(cdiv1.CloneStrategyCsiClone))
|
|
})
|
|
|
|
It("should return csi-clone if storage profile is set", func() {
|
|
cs := cdiv1.CloneStrategyCsiClone
|
|
args := &ChooseStrategyArgs{
|
|
TargetClaim: createTargetClaim(),
|
|
DataSource: createDataSource(),
|
|
Log: log,
|
|
}
|
|
sp := &cdiv1.StorageProfile{
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
Name: storageClassName,
|
|
},
|
|
Status: cdiv1.StorageProfileStatus{
|
|
CloneStrategy: &cs,
|
|
},
|
|
}
|
|
planner := createPlanner(sp, createStorageClass(), createSourceClaim())
|
|
strategy, err := planner.ChooseStrategy(context.Background(), args)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
Expect(strategy).ToNot(BeNil())
|
|
Expect(*strategy).To(Equal(cdiv1.CloneStrategyCsiClone))
|
|
})
|
|
})
|
|
|
|
Context("Plan tests", func() {
|
|
cdiConfig := &cdiv1.CDIConfig{
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
Name: "config",
|
|
},
|
|
Status: cdiv1.CDIConfigStatus{
|
|
FilesystemOverhead: &cdiv1.FilesystemOverhead{
|
|
Global: "0.05",
|
|
},
|
|
},
|
|
}
|
|
|
|
validateHostClonePhase := func(planner *Planner, args *PlanArgs, p Phase) {
|
|
hc := p.(*HostClonePhase)
|
|
Expect(hc).ToNot(BeNil())
|
|
Expect(hc.Owner).To(Equal(args.TargetClaim))
|
|
Expect(hc.Namespace).To(Equal(namespace))
|
|
Expect(hc.SourceName).To(Equal(sourceName))
|
|
Expect(hc.ImmediateBind).To(BeTrue())
|
|
Expect(hc.OwnershipLabel).To(Equal(planner.OwnershipLabel))
|
|
desiredSize := hc.DesiredClaim.Spec.Resources.Requests[corev1.ResourceStorage]
|
|
requestedSize := args.TargetClaim.Spec.Resources.Requests[corev1.ResourceStorage]
|
|
Expect(desiredSize.Cmp(requestedSize)).To(Equal(1))
|
|
}
|
|
|
|
tmpClaimName := func(uid types.UID) string {
|
|
return "tmp-pvc-" + string(uid)
|
|
}
|
|
|
|
tmpSnapshotName := func(uid types.UID) string {
|
|
return "tmp-snapshot-" + string(uid)
|
|
}
|
|
|
|
validateRebindPhase := func(planner *Planner, args *PlanArgs, p Phase) {
|
|
rb := p.(*RebindPhase)
|
|
Expect(rb).ToNot(BeNil())
|
|
Expect(rb.SourceNamespace).To(Equal(namespace))
|
|
Expect(rb.SourceName).To(Equal(tmpClaimName(args.TargetClaim.UID)))
|
|
Expect(rb.TargetNamespace).To(Equal(namespace))
|
|
Expect(rb.TargetName).To(Equal(targetName))
|
|
}
|
|
|
|
validateSnapshotPhase := func(planner *Planner, args *PlanArgs, p Phase) {
|
|
sp := p.(*SnapshotPhase)
|
|
Expect(sp).ToNot(BeNil())
|
|
Expect(sp.Owner).To(Equal(args.TargetClaim))
|
|
Expect(sp.SourceNamespace).To(Equal(namespace))
|
|
Expect(sp.SourceName).To(Equal(sourceName))
|
|
Expect(sp.TargetName).To(Equal(tmpSnapshotName(args.TargetClaim.UID)))
|
|
Expect(sp.OwnershipLabel).To(Equal(planner.OwnershipLabel))
|
|
Expect(sp.VolumeSnapshotClass).To(Equal("vsc"))
|
|
}
|
|
|
|
validateSnapshotClonePhase := func(planner *Planner, args *PlanArgs, p Phase) {
|
|
scp := p.(*SnapshotClonePhase)
|
|
Expect(scp).ToNot(BeNil())
|
|
Expect(scp.Owner).To(Equal(args.TargetClaim))
|
|
Expect(scp.Namespace).To(Equal(namespace))
|
|
Expect(scp.SourceName).To(Equal(tmpSnapshotName(args.TargetClaim.UID)))
|
|
Expect(scp.DesiredClaim.Name).To(Equal(tmpClaimName(args.TargetClaim.UID)))
|
|
Expect(scp.OwnershipLabel).To(Equal(planner.OwnershipLabel))
|
|
}
|
|
|
|
validatePrepClaimPhase := func(planner *Planner, args *PlanArgs, p Phase) {
|
|
pcp := p.(*PrepClaimPhase)
|
|
Expect(pcp).ToNot(BeNil())
|
|
Expect(pcp.Owner).To(Equal(args.TargetClaim))
|
|
Expect(pcp.DesiredClaim.Name).To(Equal(tmpClaimName(args.TargetClaim.UID)))
|
|
Expect(pcp.Image).To(Equal(planner.Image))
|
|
Expect(pcp.PullPolicy).To(Equal(planner.PullPolicy))
|
|
Expect(pcp.InstallerLabels).To(Equal(planner.InstallerLabels))
|
|
Expect(pcp.OwnershipLabel).To(Equal(planner.OwnershipLabel))
|
|
}
|
|
|
|
validateCSIClonePhase := func(planner *Planner, args *PlanArgs, p Phase) {
|
|
ccp := p.(*CSIClonePhase)
|
|
Expect(ccp).ToNot(BeNil())
|
|
Expect(ccp.Owner).To(Equal(args.TargetClaim))
|
|
Expect(ccp.Namespace).To(Equal(namespace))
|
|
Expect(ccp.SourceName).To(Equal(sourceName))
|
|
Expect(ccp.DesiredClaim.Name).To(Equal(tmpClaimName(args.TargetClaim.UID)))
|
|
Expect(ccp.OwnershipLabel).To(Equal(planner.OwnershipLabel))
|
|
}
|
|
|
|
It("should plan host assited", func() {
|
|
source := createSourceClaim()
|
|
target := createTargetClaim()
|
|
args := &PlanArgs{
|
|
Strategy: cdiv1.CloneStrategyHostAssisted,
|
|
TargetClaim: target,
|
|
DataSource: createDataSource(),
|
|
Log: log,
|
|
}
|
|
planner := createPlanner(cdiConfig, createStorageClass(), source)
|
|
plan, err := planner.Plan(context.Background(), args)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
Expect(plan).ToNot(BeNil())
|
|
Expect(plan).To(HaveLen(2))
|
|
validateHostClonePhase(planner, args, plan[0])
|
|
validateRebindPhase(planner, args, plan[1])
|
|
})
|
|
|
|
It("should plan snapshot", func() {
|
|
source := createSourceClaim()
|
|
target := createTargetClaim()
|
|
args := &PlanArgs{
|
|
Strategy: cdiv1.CloneStrategySnapshot,
|
|
TargetClaim: target,
|
|
DataSource: createDataSource(),
|
|
Log: log,
|
|
}
|
|
planner := createPlanner(cdiConfig, createStorageClass(), createVolumeSnapshotClass(), source)
|
|
plan, err := planner.Plan(context.Background(), args)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
Expect(plan).ToNot(BeNil())
|
|
Expect(plan).To(HaveLen(4))
|
|
validateSnapshotPhase(planner, args, plan[0])
|
|
validateSnapshotClonePhase(planner, args, plan[1])
|
|
validatePrepClaimPhase(planner, args, plan[2])
|
|
validateRebindPhase(planner, args, plan[3])
|
|
})
|
|
|
|
It("should plan csi-clone", func() {
|
|
source := createSourceClaim()
|
|
target := createTargetClaim()
|
|
args := &PlanArgs{
|
|
Strategy: cdiv1.CloneStrategyCsiClone,
|
|
TargetClaim: target,
|
|
DataSource: createDataSource(),
|
|
Log: log,
|
|
}
|
|
planner := createPlanner(cdiConfig, createStorageClass(), source)
|
|
plan, err := planner.Plan(context.Background(), args)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
Expect(plan).ToNot(BeNil())
|
|
Expect(plan).To(HaveLen(3))
|
|
validateCSIClonePhase(planner, args, plan[0])
|
|
validatePrepClaimPhase(planner, args, plan[1])
|
|
validateRebindPhase(planner, args, plan[2])
|
|
})
|
|
})
|
|
|
|
Context("Cleanup tests", func() {
|
|
tempResources := func() []runtime.Object {
|
|
target := createTargetClaim()
|
|
return []runtime.Object{
|
|
&corev1.PersistentVolumeClaim{
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
Namespace: namespace,
|
|
Name: "tmpClaim",
|
|
Labels: map[string]string{
|
|
ownerLabel: string(target.UID),
|
|
},
|
|
},
|
|
},
|
|
&corev1.Pod{
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
Namespace: namespace,
|
|
Name: "tmpPod",
|
|
Labels: map[string]string{
|
|
ownerLabel: string(target.UID),
|
|
},
|
|
},
|
|
},
|
|
&snapshotv1.VolumeSnapshot{
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
Namespace: namespace,
|
|
Name: "tmpSnapshot",
|
|
Labels: map[string]string{
|
|
ownerLabel: string(target.UID),
|
|
},
|
|
},
|
|
},
|
|
}
|
|
}
|
|
|
|
It("should cleanup tmp resources", func() {
|
|
tempObjs := tempResources()
|
|
target := createTargetClaim()
|
|
planner := createPlanner(tempObjs...)
|
|
err := planner.Cleanup(context.Background(), log, target)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
for _, r := range tempResources() {
|
|
co := r.(client.Object)
|
|
err = planner.Client.Get(context.Background(), client.ObjectKeyFromObject(co), co)
|
|
Expect(err).To(HaveOccurred())
|
|
Expect(k8serrors.IsNotFound(err)).To(BeTrue())
|
|
}
|
|
})
|
|
})
|
|
})
|