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

Signed-off-by: Alexander Wels <awels@redhat.com> Co-authored-by: Michael Henriksen <mhenriks@redhat.com>
587 lines
22 KiB
Go
587 lines
22 KiB
Go
package controller
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"reflect"
|
|
"strconv"
|
|
|
|
"k8s.io/apimachinery/pkg/runtime"
|
|
cdifake "kubevirt.io/containerized-data-importer/pkg/client/clientset/versioned/fake"
|
|
|
|
. "github.com/onsi/ginkgo"
|
|
"github.com/onsi/ginkgo/extensions/table"
|
|
. "github.com/onsi/gomega"
|
|
cdiv1 "kubevirt.io/containerized-data-importer/pkg/apis/core/v1alpha1"
|
|
"kubevirt.io/containerized-data-importer/pkg/common"
|
|
"sigs.k8s.io/controller-runtime/pkg/client/fake"
|
|
"sigs.k8s.io/controller-runtime/pkg/reconcile"
|
|
|
|
corev1 "k8s.io/api/core/v1"
|
|
"k8s.io/apimachinery/pkg/api/errors"
|
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
|
"k8s.io/apimachinery/pkg/types"
|
|
k8sfake "k8s.io/client-go/kubernetes/fake"
|
|
"k8s.io/client-go/kubernetes/scheme"
|
|
"k8s.io/client-go/tools/record"
|
|
)
|
|
|
|
const (
|
|
testEndPoint = "http://test.somewhere.tt.blah"
|
|
testImage = "test/image"
|
|
testPullPolicy = "Always"
|
|
)
|
|
|
|
var (
|
|
testStorageClass = "test-sc"
|
|
)
|
|
|
|
var _ = Describe("Test PVC annotations status", func() {
|
|
It("Should return complete if annotation is set", func() {
|
|
testPvc := createPvc("testPvc1", "default", map[string]string{AnnPodPhase: string(corev1.PodSucceeded)}, nil)
|
|
Expect(isPVCComplete(testPvc)).To(BeTrue())
|
|
})
|
|
|
|
It("Should NOT return complete if annotation is not succeeded", func() {
|
|
testPvc := createPvc("testPvc1", "default", map[string]string{AnnPodPhase: string(corev1.PodPending)}, nil)
|
|
Expect(isPVCComplete(testPvc)).To(BeFalse())
|
|
})
|
|
|
|
It("Should NOT return complete if annotation is missing", func() {
|
|
testPvc := createPvc("testPvc1", "default", map[string]string{}, nil)
|
|
Expect(isPVCComplete(testPvc)).To(BeFalse())
|
|
})
|
|
|
|
It("Should be interesting if NOT complete, and endpoint and source is set", func() {
|
|
testPvc := createPvc("testPvc1", "default", map[string]string{AnnPodPhase: string(corev1.PodPending), AnnEndpoint: testEndPoint, AnnSource: SourceHTTP}, nil)
|
|
Expect(shouldReconcilePVC(testPvc)).To(BeTrue())
|
|
})
|
|
|
|
It("Should NOT be interesting if complete, and endpoint and source is set", func() {
|
|
testPvc := createPvc("testPvc1", "default", map[string]string{AnnPodPhase: string(corev1.PodSucceeded), AnnEndpoint: testEndPoint, AnnSource: SourceHTTP}, nil)
|
|
Expect(shouldReconcilePVC(testPvc)).To(BeFalse())
|
|
})
|
|
|
|
It("Should be interesting if NOT complete, and endpoint missing and source is set", func() {
|
|
testPvc := createPvc("testPvc1", "default", map[string]string{AnnPodPhase: string(corev1.PodRunning), AnnSource: SourceHTTP}, nil)
|
|
Expect(shouldReconcilePVC(testPvc)).To(BeTrue())
|
|
})
|
|
|
|
It("Should be interesting if NOT complete, and endpoint set and source is missing", func() {
|
|
testPvc := createPvc("testPvc1", "default", map[string]string{AnnPodPhase: string(corev1.PodPending), AnnEndpoint: testEndPoint}, nil)
|
|
Expect(shouldReconcilePVC(testPvc)).To(BeTrue())
|
|
})
|
|
})
|
|
|
|
var _ = Describe("ImportConfig Controller reconcile loop", func() {
|
|
var (
|
|
reconciler *ImportReconciler
|
|
)
|
|
AfterEach(func() {
|
|
if reconciler != nil {
|
|
close(reconciler.recorder.(*record.FakeRecorder).Events)
|
|
reconciler = nil
|
|
}
|
|
})
|
|
|
|
It("Should return success if a PVC with no annotations is passed, due to it being ignored", func() {
|
|
reconciler = createImportReconciler(createPvc("testPvc1", "default", map[string]string{}, nil))
|
|
_, err := reconciler.Reconcile(reconcile.Request{NamespacedName: types.NamespacedName{Name: "testPvc1", Namespace: "default"}})
|
|
Expect(err).ToNot(HaveOccurred())
|
|
})
|
|
|
|
It("Should return success if no PVC can be found, due to it not existing", func() {
|
|
reconciler = createImportReconciler()
|
|
_, err := reconciler.Reconcile(reconcile.Request{})
|
|
Expect(err).ToNot(HaveOccurred())
|
|
})
|
|
|
|
It("Should return success if no PVC can be found due to not existing in passed namespace", func() {
|
|
reconciler = createImportReconciler(createPvc("testPvc1", "default", map[string]string{AnnEndpoint: testEndPoint}, nil))
|
|
_, err := reconciler.Reconcile(reconcile.Request{NamespacedName: types.NamespacedName{Name: "testPvc1", Namespace: "invalid"}})
|
|
Expect(err).ToNot(HaveOccurred())
|
|
})
|
|
|
|
It("Should succeed and be marked complete, if creating a block PVC with source none", func() {
|
|
reconciler = createImportReconciler(createBlockPvc("testPvc1", "block", map[string]string{AnnSource: SourceNone}, nil))
|
|
_, err := reconciler.Reconcile(reconcile.Request{NamespacedName: types.NamespacedName{Name: "testPvc1", Namespace: "block"}})
|
|
Expect(err).ToNot(HaveOccurred())
|
|
resultPvc := &corev1.PersistentVolumeClaim{}
|
|
err = reconciler.Client.Get(context.TODO(), types.NamespacedName{Name: "testPvc1", Namespace: "block"}, resultPvc)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
Expect(resultPvc.GetAnnotations()[AnnPodPhase]).To(BeEquivalentTo(corev1.PodSucceeded))
|
|
})
|
|
|
|
It("should do nothing and not error, if a PVC that is completed is passed", func() {
|
|
orgPvc := createPvc("testPvc1", "default", map[string]string{AnnEndpoint: testEndPoint, AnnPodPhase: string(corev1.PodSucceeded)}, nil)
|
|
orgPvc.TypeMeta.APIVersion = "v1"
|
|
orgPvc.TypeMeta.Kind = "PersistentVolumeClaim"
|
|
reconciler = createImportReconciler(orgPvc)
|
|
_, err := reconciler.Reconcile(reconcile.Request{})
|
|
Expect(err).ToNot(HaveOccurred())
|
|
resPvc := &corev1.PersistentVolumeClaim{}
|
|
err = reconciler.Client.Get(context.TODO(), types.NamespacedName{}, resPvc)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
Expect(reflect.DeepEqual(orgPvc, resPvc)).To(BeTrue())
|
|
})
|
|
|
|
It("Should create a POD if a PVC with all needed annotations is passed", func() {
|
|
reconciler = createImportReconciler(createPvc("testPvc1", "default", map[string]string{AnnEndpoint: testEndPoint}, nil))
|
|
_, err := reconciler.Reconcile(reconcile.Request{})
|
|
Expect(err).ToNot(HaveOccurred())
|
|
pod := &corev1.Pod{}
|
|
err = reconciler.Client.Get(context.TODO(), types.NamespacedName{Name: "importer-testPvc1", Namespace: "default"}, pod)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
foundEndPoint := false
|
|
for _, envVar := range pod.Spec.Containers[0].Env {
|
|
if envVar.Name == common.ImporterEndpoint {
|
|
foundEndPoint = true
|
|
Expect(envVar.Value).To(Equal(testEndPoint))
|
|
}
|
|
}
|
|
Expect(foundEndPoint).To(BeTrue())
|
|
})
|
|
|
|
It("Should error if a POD with the same name exists, but is not owned by the PVC, if a PVC with all needed annotations is passed", func() {
|
|
pod := &corev1.Pod{
|
|
TypeMeta: metav1.TypeMeta{
|
|
Kind: "Pod",
|
|
APIVersion: "v1",
|
|
},
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
Name: "importer-testPvc1",
|
|
Namespace: "default",
|
|
},
|
|
}
|
|
reconciler = createImportReconciler(createPvc("testPvc1", "default", map[string]string{AnnEndpoint: testEndPoint}, nil), pod)
|
|
_, err := reconciler.Reconcile(reconcile.Request{})
|
|
Expect(err).To(HaveOccurred())
|
|
Expect(err.Error()).To(ContainSubstring("Pod is not owned by PVC"))
|
|
})
|
|
})
|
|
|
|
var _ = Describe("Update PVC from POD", func() {
|
|
var (
|
|
reconciler *ImportReconciler
|
|
)
|
|
AfterEach(func() {
|
|
if reconciler != nil {
|
|
close(reconciler.recorder.(*record.FakeRecorder).Events)
|
|
reconciler = nil
|
|
}
|
|
})
|
|
|
|
It("Should update the PVC status to succeeded, if pod is succeeded and then delete the pod", func() {
|
|
pvc := createPvc("testPvc1", "default", map[string]string{AnnEndpoint: testEndPoint, AnnPodPhase: string(corev1.PodPending)}, nil)
|
|
pod := createImporterTestPod(pvc, "testPvc1", nil)
|
|
pod.Status = corev1.PodStatus{
|
|
Phase: corev1.PodSucceeded,
|
|
}
|
|
reconciler = createImportReconciler(pvc, pod)
|
|
resPod := &corev1.Pod{}
|
|
err := reconciler.Client.Get(context.TODO(), types.NamespacedName{Name: "importer-testPvc1", Namespace: "default"}, resPod)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
err = reconciler.updatePvcFromPod(pvc, pod, reconciler.Log)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
By("Checking import successful event recorded")
|
|
event := <-reconciler.recorder.(*record.FakeRecorder).Events
|
|
Expect(event).To(ContainSubstring("Import Successful"))
|
|
By("Checking pvc phase has been updated")
|
|
resPvc := &corev1.PersistentVolumeClaim{}
|
|
err = reconciler.Client.Get(context.TODO(), types.NamespacedName{Name: "testPvc1", Namespace: "default"}, resPvc)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
Expect(resPvc.GetAnnotations()[AnnPodPhase]).To(BeEquivalentTo(corev1.PodSucceeded))
|
|
By("Checking pod has been deleted")
|
|
resPod = &corev1.Pod{}
|
|
err = reconciler.Client.Get(context.TODO(), types.NamespacedName{Name: "importer-testPvc1", Namespace: "default"}, resPod)
|
|
Expect(err).To(HaveOccurred())
|
|
Expect(errors.IsNotFound(err)).To(BeTrue())
|
|
})
|
|
|
|
It("Should update the PVC status to running, if pod is running", func() {
|
|
pvc := createPvc("testPvc1", "default", map[string]string{AnnEndpoint: testEndPoint, AnnPodPhase: string(corev1.PodPending)}, nil)
|
|
pod := createImporterTestPod(pvc, "testPvc1", nil)
|
|
pod.Status = corev1.PodStatus{
|
|
Phase: corev1.PodRunning,
|
|
}
|
|
reconciler = createImportReconciler(pvc, pod)
|
|
resPod := &corev1.Pod{}
|
|
err := reconciler.Client.Get(context.TODO(), types.NamespacedName{Name: "importer-testPvc1", Namespace: "default"}, resPod)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
err = reconciler.updatePvcFromPod(pvc, pod, reconciler.Log)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
By("Checking pvc phase has been updated")
|
|
resPvc := &corev1.PersistentVolumeClaim{}
|
|
err = reconciler.Client.Get(context.TODO(), types.NamespacedName{Name: "testPvc1", Namespace: "default"}, resPvc)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
Expect(resPvc.GetAnnotations()[AnnPodPhase]).To(BeEquivalentTo(corev1.PodRunning))
|
|
Expect(resPvc.GetAnnotations()[AnnImportPod]).To(Equal(pod.Name))
|
|
By("Checking pod has NOT been deleted")
|
|
resPod = &corev1.Pod{}
|
|
err = reconciler.Client.Get(context.TODO(), types.NamespacedName{Name: "importer-testPvc1", Namespace: "default"}, resPod)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
By("Making sure the label has been added")
|
|
Expect(resPvc.GetLabels()[common.CDILabelKey]).To(Equal(common.CDILabelValue))
|
|
})
|
|
|
|
It("Should create scratch PVC, if pod is pending and PVC is marked with scratch", func() {
|
|
pvc := createPvcInStorageClass("testPvc1", "default", &testStorageClass, map[string]string{AnnEndpoint: testEndPoint, AnnPodPhase: string(corev1.PodPending), AnnRequiresScratch: "true"}, nil)
|
|
pod := createImporterTestPod(pvc, "testPvc1", nil)
|
|
pod.Status = corev1.PodStatus{
|
|
Phase: corev1.PodPending,
|
|
}
|
|
reconciler = createImportReconciler(pvc, pod)
|
|
err := reconciler.updatePvcFromPod(pvc, pod, reconciler.Log)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
By("Checking scratch PVC has been created")
|
|
// Once all controllers are converted, we will use the runtime lib client instead of client-go and retrieval needs to change here.
|
|
scratchPvc, err := reconciler.K8sClient.CoreV1().PersistentVolumeClaims("default").Get("testPvc1-scratch", metav1.GetOptions{})
|
|
Expect(err).ToNot(HaveOccurred())
|
|
Expect(scratchPvc.Spec.Resources).To(Equal(pvc.Spec.Resources))
|
|
|
|
resPvc := &corev1.PersistentVolumeClaim{}
|
|
err = reconciler.Client.Get(context.TODO(), types.NamespacedName{Name: "testPvc1", Namespace: "default"}, resPvc)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
Expect(resPvc.GetAnnotations()[AnnImportPod]).To(Equal(pod.Name))
|
|
})
|
|
|
|
// TODO: Update me to stay in progress if we were in progress already, its a pod failure and it will get restarted.
|
|
It("Should update phase on PVC, if pod exited with error state that is NOT scratchspace exit", func() {
|
|
pvc := createPvcInStorageClass("testPvc1", "default", &testStorageClass, map[string]string{AnnEndpoint: testEndPoint, AnnPodPhase: string(corev1.PodRunning)}, nil)
|
|
pod := createImporterTestPod(pvc, "testPvc1", nil)
|
|
pod.Status = corev1.PodStatus{
|
|
Phase: corev1.PodFailed,
|
|
ContainerStatuses: []corev1.ContainerStatus{
|
|
{
|
|
LastTerminationState: corev1.ContainerState{
|
|
Terminated: &corev1.ContainerStateTerminated{
|
|
ExitCode: 1,
|
|
Message: "I went poof",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
reconciler = createImportReconciler(pvc, pod)
|
|
err := reconciler.updatePvcFromPod(pvc, pod, reconciler.Log)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
By("Checking pvc phase has been updated")
|
|
resPvc := &corev1.PersistentVolumeClaim{}
|
|
err = reconciler.Client.Get(context.TODO(), types.NamespacedName{Name: "testPvc1", Namespace: "default"}, resPvc)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
Expect(resPvc.GetAnnotations()[AnnPodPhase]).To(BeEquivalentTo(corev1.PodFailed))
|
|
Expect(resPvc.GetAnnotations()[AnnImportPod]).To(Equal(pod.Name))
|
|
By("Checking error event recorded")
|
|
event := <-reconciler.recorder.(*record.FakeRecorder).Events
|
|
Expect(event).To(ContainSubstring("I went poof"))
|
|
})
|
|
|
|
It("Should update phase on PVC, if pod exited with error state that is scratchspace exit", func() {
|
|
pvc := createPvcInStorageClass("testPvc1", "default", &testStorageClass, map[string]string{AnnEndpoint: testEndPoint, AnnPodPhase: string(corev1.PodRunning)}, nil)
|
|
pod := createImporterTestPod(pvc, "testPvc1", nil)
|
|
pod.Status = corev1.PodStatus{
|
|
Phase: corev1.PodRunning,
|
|
ContainerStatuses: []corev1.ContainerStatus{
|
|
{
|
|
LastTerminationState: corev1.ContainerState{
|
|
Terminated: &corev1.ContainerStateTerminated{
|
|
ExitCode: common.ScratchSpaceNeededExitCode,
|
|
Message: "scratch space needed",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
reconciler = createImportReconciler(pvc, pod)
|
|
err := reconciler.updatePvcFromPod(pvc, pod, reconciler.Log)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
By("Checking pvc phase has been updated")
|
|
resPvc := &corev1.PersistentVolumeClaim{}
|
|
err = reconciler.Client.Get(context.TODO(), types.NamespacedName{Name: "testPvc1", Namespace: "default"}, resPvc)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
By("Verifying that the phase hasn't changed")
|
|
Expect(resPvc.GetAnnotations()[AnnPodPhase]).To(BeEquivalentTo(corev1.PodRunning))
|
|
Expect(resPvc.GetAnnotations()[AnnImportPod]).To(Equal(pod.Name))
|
|
// No scratch space because the pod is not in pending.
|
|
})
|
|
})
|
|
|
|
var _ = Describe("Create Importer Pod", func() {
|
|
var scratchPvcName = "scratchPvc"
|
|
|
|
table.DescribeTable("should", func(pvc *corev1.PersistentVolumeClaim, scratchPvcName *string) {
|
|
reconciler := createImportReconciler(pvc)
|
|
podEnvVar := &importPodEnvVar{
|
|
ep: "",
|
|
secretName: "",
|
|
source: "",
|
|
contentType: "",
|
|
imageSize: "1G",
|
|
certConfigMap: "",
|
|
insecureTLS: false,
|
|
}
|
|
pod, err := createImporterPod(reconciler.Log, reconciler.Client, reconciler.CdiClient, testImage, "5", testPullPolicy, podEnvVar, pvc, scratchPvcName)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
By("Verifying PVC owns pod")
|
|
Expect(len(pod.GetOwnerReferences())).To(Equal(1))
|
|
Expect(pod.GetOwnerReferences()[0].UID).To(Equal(pvc.GetUID()))
|
|
By("Verifying volume mode is correct")
|
|
if getVolumeMode(pvc) == corev1.PersistentVolumeBlock {
|
|
Expect(pod.Spec.Containers[0].VolumeDevices[0].Name).To(Equal(DataVolName))
|
|
Expect(pod.Spec.Containers[0].VolumeDevices[0].DevicePath).To(Equal(common.WriteBlockPath))
|
|
Expect(pod.Spec.SecurityContext.RunAsUser).To(Equal(&[]int64{0}[0]))
|
|
if scratchPvcName != nil {
|
|
By("Verifying scratch space is set if available")
|
|
Expect(len(pod.Spec.Containers[0].VolumeMounts)).To(Equal(1))
|
|
Expect(pod.Spec.Containers[0].VolumeMounts[0].Name).To(Equal(ScratchVolName))
|
|
Expect(pod.Spec.Containers[0].VolumeMounts[0].MountPath).To(Equal(common.ScratchDataDir))
|
|
}
|
|
} else {
|
|
Expect(pod.Spec.Containers[0].VolumeMounts[0].Name).To(Equal(DataVolName))
|
|
Expect(pod.Spec.Containers[0].VolumeMounts[0].MountPath).To(Equal(common.ImporterDataDir))
|
|
if scratchPvcName != nil {
|
|
By("Verifying scratch space is set if available")
|
|
Expect(len(pod.Spec.Containers[0].VolumeMounts)).To(Equal(2))
|
|
Expect(pod.Spec.Containers[0].VolumeMounts[1].Name).To(Equal(ScratchVolName))
|
|
Expect(pod.Spec.Containers[0].VolumeMounts[1].MountPath).To(Equal(common.ScratchDataDir))
|
|
}
|
|
}
|
|
By("Verifying container spec is correct")
|
|
Expect(pod.Spec.Containers[0].Image).To(Equal(testImage))
|
|
Expect(pod.Spec.Containers[0].ImagePullPolicy).To(BeEquivalentTo(testPullPolicy))
|
|
Expect(pod.Spec.Containers[0].Args[0]).To(Equal("-v=5"))
|
|
},
|
|
table.Entry("should create pod with file system volume mode", createPvc("testPvc1", "default", map[string]string{AnnEndpoint: testEndPoint, AnnPodPhase: string(corev1.PodPending)}, nil), nil),
|
|
table.Entry("should create pod with block volume mode", createBlockPvc("testBlockPvc1", "default", map[string]string{AnnEndpoint: testEndPoint, AnnPodPhase: string(corev1.PodPending)}, nil), nil),
|
|
table.Entry("should create pod with file system volume mode and scratchspace", createPvc("testPvc1", "default", map[string]string{AnnEndpoint: testEndPoint, AnnPodPhase: string(corev1.PodPending)}, nil), &scratchPvcName),
|
|
table.Entry("should create pod with block volume mode and scratchspace", createBlockPvc("testBlockPvc1", "default", map[string]string{AnnEndpoint: testEndPoint, AnnPodPhase: string(corev1.PodPending)}, nil), &scratchPvcName),
|
|
)
|
|
})
|
|
|
|
var _ = Describe("Import test env", func() {
|
|
const mockUID = "1111-1111-1111-1111"
|
|
|
|
It("Should create import env", func() {
|
|
testEnvVar := &importPodEnvVar{"myendpoint", "mysecret", SourceHTTP, string(cdiv1.DataVolumeKubeVirt), "1G", "", false}
|
|
Expect(reflect.DeepEqual(makeImportEnv(testEnvVar, mockUID), createImportTestEnv(testEnvVar, mockUID))).To(BeTrue())
|
|
})
|
|
})
|
|
|
|
func createImportReconciler(objects ...runtime.Object) *ImportReconciler {
|
|
objs := []runtime.Object{}
|
|
objs = append(objs, objects...)
|
|
|
|
// Register operator types with the runtime scheme.
|
|
s := scheme.Scheme
|
|
corev1.AddToScheme(s)
|
|
|
|
cdiConfig := MakeEmptyCDIConfigSpec(common.ConfigName)
|
|
cdiConfig.Status = cdiv1.CDIConfigStatus{
|
|
ScratchSpaceStorageClass: testStorageClass,
|
|
}
|
|
objs = append(objs, cdiConfig)
|
|
cdifakeclientset := cdifake.NewSimpleClientset(cdiConfig)
|
|
k8sfakeclientset := k8sfake.NewSimpleClientset(createStorageClass(testStorageClass, nil))
|
|
|
|
// Create a fake client to mock API calls.
|
|
cl := fake.NewFakeClientWithScheme(s, objs...)
|
|
|
|
rec := record.NewFakeRecorder(1)
|
|
// Create a ReconcileMemcached object with the scheme and fake client.
|
|
r := &ImportReconciler{
|
|
Client: cl,
|
|
Scheme: s,
|
|
Log: log,
|
|
recorder: rec,
|
|
CdiClient: cdifakeclientset,
|
|
K8sClient: k8sfakeclientset,
|
|
}
|
|
return r
|
|
}
|
|
|
|
func createImportTestEnv(podEnvVar *importPodEnvVar, uid string) []corev1.EnvVar {
|
|
env := []corev1.EnvVar{
|
|
{
|
|
Name: common.ImporterSource,
|
|
Value: podEnvVar.source,
|
|
},
|
|
{
|
|
Name: common.ImporterEndpoint,
|
|
Value: podEnvVar.ep,
|
|
},
|
|
{
|
|
Name: common.ImporterContentType,
|
|
Value: podEnvVar.contentType,
|
|
},
|
|
{
|
|
Name: common.ImporterImageSize,
|
|
Value: podEnvVar.imageSize,
|
|
},
|
|
{
|
|
Name: common.OwnerUID,
|
|
Value: string(uid),
|
|
},
|
|
{
|
|
Name: common.InsecureTLSVar,
|
|
Value: strconv.FormatBool(podEnvVar.insecureTLS),
|
|
},
|
|
}
|
|
|
|
if podEnvVar.secretName != "" {
|
|
env = append(env, corev1.EnvVar{
|
|
Name: common.ImporterAccessKeyID,
|
|
ValueFrom: &corev1.EnvVarSource{
|
|
SecretKeyRef: &corev1.SecretKeySelector{
|
|
LocalObjectReference: corev1.LocalObjectReference{
|
|
Name: podEnvVar.secretName,
|
|
},
|
|
Key: common.KeyAccess,
|
|
},
|
|
},
|
|
}, corev1.EnvVar{
|
|
Name: common.ImporterSecretKey,
|
|
ValueFrom: &corev1.EnvVarSource{
|
|
SecretKeyRef: &corev1.SecretKeySelector{
|
|
LocalObjectReference: corev1.LocalObjectReference{
|
|
Name: podEnvVar.secretName,
|
|
},
|
|
Key: common.KeySecret,
|
|
},
|
|
},
|
|
})
|
|
}
|
|
return env
|
|
}
|
|
|
|
func createImporterTestPod(pvc *corev1.PersistentVolumeClaim, dvname string, scratchPvc *corev1.PersistentVolumeClaim) *corev1.Pod {
|
|
// importer pod name contains the pvc name
|
|
podName := fmt.Sprintf("%s-%s", common.ImporterPodName, pvc.Name)
|
|
|
|
blockOwnerDeletion := true
|
|
isController := true
|
|
|
|
volumes := []corev1.Volume{
|
|
{
|
|
Name: dvname,
|
|
VolumeSource: corev1.VolumeSource{
|
|
PersistentVolumeClaim: &corev1.PersistentVolumeClaimVolumeSource{
|
|
ClaimName: pvc.Name,
|
|
ReadOnly: false,
|
|
},
|
|
},
|
|
},
|
|
}
|
|
|
|
if scratchPvc != nil {
|
|
volumes = append(volumes, corev1.Volume{
|
|
Name: ScratchVolName,
|
|
VolumeSource: corev1.VolumeSource{
|
|
PersistentVolumeClaim: &corev1.PersistentVolumeClaimVolumeSource{
|
|
ClaimName: scratchPvc.Name,
|
|
ReadOnly: false,
|
|
},
|
|
},
|
|
})
|
|
}
|
|
|
|
pod := &corev1.Pod{
|
|
TypeMeta: metav1.TypeMeta{
|
|
Kind: "Pod",
|
|
APIVersion: "v1",
|
|
},
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
Name: podName,
|
|
Namespace: pvc.Namespace,
|
|
Annotations: map[string]string{
|
|
AnnCreatedBy: "yes",
|
|
},
|
|
Labels: map[string]string{
|
|
common.CDILabelKey: common.CDILabelValue,
|
|
common.CDIComponentLabel: common.ImporterPodName,
|
|
LabelImportPvc: pvc.Name,
|
|
common.PrometheusLabel: "",
|
|
},
|
|
OwnerReferences: []metav1.OwnerReference{
|
|
{
|
|
APIVersion: "v1",
|
|
Kind: "PersistentVolumeClaim",
|
|
Name: pvc.Name,
|
|
UID: pvc.GetUID(),
|
|
BlockOwnerDeletion: &blockOwnerDeletion,
|
|
Controller: &isController,
|
|
},
|
|
},
|
|
},
|
|
Spec: corev1.PodSpec{
|
|
Containers: []corev1.Container{
|
|
{
|
|
Name: common.ImporterPodName,
|
|
Image: "test/myimage",
|
|
ImagePullPolicy: corev1.PullPolicy("Always"),
|
|
Args: []string{"-v=5"},
|
|
Ports: []corev1.ContainerPort{
|
|
{
|
|
Name: "metrics",
|
|
ContainerPort: 8443,
|
|
Protocol: corev1.ProtocolTCP,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
RestartPolicy: corev1.RestartPolicyOnFailure,
|
|
Volumes: volumes,
|
|
},
|
|
}
|
|
|
|
ep, _ := getEndpoint(pvc)
|
|
source := getSource(pvc)
|
|
contentType := getContentType(pvc)
|
|
imageSize, _ := getRequestedImageSize(pvc)
|
|
volumeMode := getVolumeMode(pvc)
|
|
|
|
env := []corev1.EnvVar{
|
|
{
|
|
Name: common.ImporterSource,
|
|
Value: source,
|
|
},
|
|
{
|
|
Name: common.ImporterEndpoint,
|
|
Value: ep,
|
|
},
|
|
{
|
|
Name: common.ImporterContentType,
|
|
Value: contentType,
|
|
},
|
|
{
|
|
Name: common.ImporterImageSize,
|
|
Value: imageSize,
|
|
},
|
|
{
|
|
Name: common.OwnerUID,
|
|
Value: string(pvc.UID),
|
|
},
|
|
{
|
|
Name: common.InsecureTLSVar,
|
|
Value: "false",
|
|
},
|
|
}
|
|
pod.Spec.Containers[0].Env = env
|
|
if volumeMode == corev1.PersistentVolumeBlock {
|
|
pod.Spec.Containers[0].VolumeDevices = addVolumeDevices()
|
|
pod.Spec.SecurityContext = &corev1.PodSecurityContext{
|
|
RunAsUser: &[]int64{0}[0],
|
|
}
|
|
} else {
|
|
pod.Spec.Containers[0].VolumeMounts = addImportVolumeMounts()
|
|
}
|
|
|
|
if scratchPvc != nil {
|
|
pod.Spec.Containers[0].VolumeMounts = append(pod.Spec.Containers[0].VolumeMounts, corev1.VolumeMount{
|
|
Name: ScratchVolName,
|
|
MountPath: common.ScratchDataDir,
|
|
})
|
|
}
|
|
|
|
return pod
|
|
}
|