mirror of
https://github.com/kubevirt/containerized-data-importer.git
synced 2025-06-03 06:30:22 +00:00
368 lines
11 KiB
Go
368 lines
11 KiB
Go
package controller
|
|
|
|
import (
|
|
"fmt"
|
|
"reflect"
|
|
"testing"
|
|
|
|
. "github.com/kubevirt/containerized-data-importer/pkg/common"
|
|
"k8s.io/api/core/v1"
|
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
|
"k8s.io/client-go/kubernetes"
|
|
k8sfake "k8s.io/client-go/kubernetes/fake"
|
|
"k8s.io/client-go/tools/cache"
|
|
k8stesting "k8s.io/client-go/tools/cache/testing"
|
|
"k8s.io/client-go/util/workqueue"
|
|
)
|
|
|
|
func TestNewImportController(t *testing.T) {
|
|
type args struct {
|
|
client kubernetes.Interface
|
|
pvcInformer cache.SharedIndexInformer
|
|
podInformer cache.SharedIndexInformer
|
|
importerImage string
|
|
pullPolicy string
|
|
verbose string
|
|
}
|
|
// Set up environment
|
|
myclient := k8sfake.NewSimpleClientset()
|
|
pvcSource := k8stesting.NewFakePVCControllerSource()
|
|
podSource := k8stesting.NewFakeControllerSource()
|
|
|
|
// create informers
|
|
pvcInformer := cache.NewSharedIndexInformer(pvcSource, nil, DEFAULT_RESYNC_PERIOD, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc})
|
|
podInformer := cache.NewSharedIndexInformer(podSource, nil, DEFAULT_RESYNC_PERIOD, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc})
|
|
|
|
tests := []struct {
|
|
name string
|
|
args args
|
|
want *ImportController
|
|
}{
|
|
{
|
|
name: "expect controller to be created with expected informers",
|
|
args: args{myclient, pvcInformer, podInformer, "test/image", "Always", "-v=5"},
|
|
want: &ImportController{myclient, nil, nil, pvcInformer, podInformer, "test/image", "Always", "-v=5"},
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
got := NewImportController(tt.args.client, tt.args.pvcInformer, tt.args.podInformer, tt.args.importerImage, tt.args.pullPolicy, tt.args.verbose)
|
|
if got == nil {
|
|
t.Errorf("NewImportController() not created - %v", got)
|
|
}
|
|
if !reflect.DeepEqual(got.podInformer, tt.want.podInformer) {
|
|
t.Errorf("NewImportController() podInformer = %v, want %v", got.podInformer, tt.want.podInformer)
|
|
}
|
|
if !reflect.DeepEqual(got.pvcInformer, tt.want.pvcInformer) {
|
|
t.Errorf("NewImportController() pvcInformer = %v, want %v", got.pvcInformer, tt.want.pvcInformer)
|
|
}
|
|
// queues are generated from the controller
|
|
if got.pvcQueue == nil {
|
|
t.Errorf("NewImportController() pvcQueue was not generated properly = %v", got.pvcQueue)
|
|
}
|
|
if got.podQueue == nil {
|
|
t.Errorf("NewImportController() podQueue was not generated properly = %v", got.podQueue)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestController_Run(t *testing.T) {
|
|
type fields struct {
|
|
clientset kubernetes.Interface
|
|
pvcQueue workqueue.RateLimitingInterface
|
|
podQueue workqueue.RateLimitingInterface
|
|
pvcInformer cache.SharedIndexInformer
|
|
podInformer cache.SharedIndexInformer
|
|
importerImage string
|
|
pullPolicy string
|
|
verbose string
|
|
}
|
|
type args struct {
|
|
threadiness int
|
|
stopCh <-chan struct{}
|
|
}
|
|
|
|
tests := []struct {
|
|
name string
|
|
fields fields
|
|
args args
|
|
wantErr bool
|
|
}{
|
|
// TODO: Add test cases.
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
c := &ImportController{
|
|
clientset: tt.fields.clientset,
|
|
pvcQueue: tt.fields.pvcQueue,
|
|
podQueue: tt.fields.podQueue,
|
|
pvcInformer: tt.fields.pvcInformer,
|
|
podInformer: tt.fields.podInformer,
|
|
importerImage: tt.fields.importerImage,
|
|
pullPolicy: tt.fields.pullPolicy,
|
|
verbose: tt.fields.verbose,
|
|
}
|
|
if err := c.Run(tt.args.threadiness, tt.args.stopCh); (err != nil) != tt.wantErr {
|
|
t.Errorf("Controller.Run() error = %v, wantErr %v", err, tt.wantErr)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestController_ProcessNextPodItem(t *testing.T) {
|
|
//create pod and pvc
|
|
pvcWithEndPointAnno := createPvc("testPvcWithEndPointAnno", "default", map[string]string{AnnEndpoint: "http://test"}, nil)
|
|
podWithCdiAnno := createPod(pvcWithEndPointAnno, DataVolName)
|
|
|
|
//create and run the informers
|
|
c, _, _, err := createImportController(pvcWithEndPointAnno, podWithCdiAnno, "default")
|
|
if err != nil {
|
|
t.Errorf("Controller.ProcessNextPodItem() failed to initialize fake controller error = %v", err)
|
|
return
|
|
}
|
|
|
|
tests := []struct {
|
|
name string
|
|
want bool
|
|
}{
|
|
{
|
|
name: "successfully process pod",
|
|
want: true,
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
if got := c.ProcessNextPodItem(); got != tt.want {
|
|
t.Errorf("Controller.ProcessNextPodItem() = %v, want %v", got, tt.want)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestController_processPodItem(t *testing.T) {
|
|
//create pod and pvc
|
|
const stageCount = 3
|
|
|
|
//Generate Staging Specs
|
|
// dictates what NS the spec is actually created in
|
|
stageNs := make([]string, stageCount)
|
|
stageNs[0] = "default"
|
|
stageNs[1] = "default"
|
|
stageNs[2] = "test"
|
|
|
|
// create pvc specs
|
|
stagePvcs := make([]*v1.PersistentVolumeClaim, stageCount)
|
|
stagePvcs[0] = createPvc("testPvc1", "default", map[string]string{AnnEndpoint: "http://test"}, nil)
|
|
stagePvcs[1] = createPvc("testPvc2", "default", map[string]string{AnnEndpoint: "http://test"}, nil)
|
|
stagePvcs[2] = createPvc("testPvc3", "default", map[string]string{AnnEndpoint: "http://test"}, nil)
|
|
|
|
// create pod specs with pvc reference
|
|
stagePods := make([]*v1.Pod, stageCount)
|
|
stagePods[0] = createPod(stagePvcs[0], DataVolName)
|
|
stagePods[1] = createPod(stagePvcs[1], "myvolume")
|
|
stagePods[2] = createPod(stagePvcs[2], DataVolName)
|
|
|
|
//create and run the informers passing back v1 processed pods
|
|
c, _, pods, err := createImportControllerMultiObject(stagePvcs, stagePods, stageNs)
|
|
if err != nil {
|
|
t.Errorf("Controller.ProcessPodItem() failed to initialize fake controller error = %v", err)
|
|
return
|
|
}
|
|
|
|
type args struct {
|
|
pod *v1.Pod
|
|
}
|
|
|
|
tests := []struct {
|
|
name string
|
|
args args
|
|
wantErr bool
|
|
}{
|
|
{
|
|
name: "successfully process pod",
|
|
args: args{pods[0]},
|
|
wantErr: false,
|
|
},
|
|
{
|
|
name: "expect error when processing pod with no cdi-data-volume",
|
|
args: args{pods[1]},
|
|
wantErr: true,
|
|
},
|
|
{
|
|
name: "expect error when proessing pvc with different NS than expected pod",
|
|
args: args{pods[2]},
|
|
wantErr: true,
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
if err := c.processPodItem(tt.args.pod); (err != nil) != tt.wantErr {
|
|
t.Errorf("Controller.processPodItem() error = %v, wantErr %v, Pod Name = %v, Pod ClaimRef = %v", err, tt.wantErr, tt.args.pod.Name, tt.args.pod.Spec.Volumes)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestController_ProcessNextPvcItem(t *testing.T) {
|
|
//create pod and pvc
|
|
const stageCount = 4
|
|
|
|
//Generate Staging Specs
|
|
// dictates what NS the spec is actually created in
|
|
stageNs := make([]string, stageCount)
|
|
stageNs[0] = "default"
|
|
stageNs[1] = "default"
|
|
stageNs[2] = "default"
|
|
stageNs[3] = "default"
|
|
|
|
// create pvc specs
|
|
stagePvcs := make([]*v1.PersistentVolumeClaim, stageCount)
|
|
stagePvcs[0] = createPvc("testPvc1", "default", map[string]string{AnnEndpoint: "http://test"}, nil)
|
|
stagePvcs[1] = createPvc("testPvc2", "default", map[string]string{AnnEndpoint: "http://test", AnnImportPod: "cdi-importer-pod"}, nil)
|
|
stagePvcs[2] = createPvc("testPvc3", "default", nil, nil)
|
|
stagePvcs[3] = createPvc("testPvc4", "default", map[string]string{AnnEndpoint: "http://test"}, nil)
|
|
|
|
// create pod specs with pvc reference
|
|
stagePods := make([]*v1.Pod, stageCount)
|
|
stagePods[0] = createPod(stagePvcs[0], DataVolName)
|
|
stagePods[1] = createPod(stagePvcs[1], DataVolName)
|
|
stagePods[2] = createPod(stagePvcs[2], DataVolName)
|
|
stagePods[3] = createPod(stagePvcs[3], DataVolName)
|
|
|
|
//create and run queues and informers
|
|
c, _, _, err := createImportControllerMultiObject(stagePvcs, stagePods, stageNs)
|
|
if err != nil {
|
|
t.Errorf("Controller.ProcessNextPvcItem() failed to initialize fake controller error = %v", err)
|
|
return
|
|
}
|
|
|
|
tests := []struct {
|
|
name string
|
|
want bool
|
|
}{
|
|
{
|
|
name: "expect successful processing of queue",
|
|
want: true,
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
if got := c.ProcessNextPvcItem(); got != tt.want {
|
|
t.Errorf("Controller.ProcessNextPvcItem() = %v, want %v", got, tt.want)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestController_processPvcItem(t *testing.T) {
|
|
//create pod and pvc
|
|
const stageCount = 2
|
|
|
|
//Generate Staging Specs
|
|
// create pvc specs
|
|
stagePvcs := make([]*v1.PersistentVolumeClaim, stageCount)
|
|
stagePvcs[0] = createPvc("testPvc1", "default", map[string]string{AnnEndpoint: "http://test"}, nil)
|
|
stagePvcs[1] = createPvc("testPvc2", "default", map[string]string{AnnEndpoint: "http://test", AnnImportPod: "cdi-importer-pod"}, nil)
|
|
|
|
//create and run queues and informers
|
|
c, _, _, err := createImportControllerMultiObject(stagePvcs, nil, nil)
|
|
if err != nil {
|
|
t.Errorf("Controller.ProcessPvcItem() failed to initialize fake controller error = %v", err)
|
|
return
|
|
}
|
|
|
|
type args struct {
|
|
pvc *v1.PersistentVolumeClaim
|
|
}
|
|
tests := []struct {
|
|
name string
|
|
args args
|
|
podName string
|
|
wantErr bool
|
|
wantFind bool
|
|
}{
|
|
{
|
|
name: "process pvc and expect importer pod to be created",
|
|
args: args{stagePvcs[0]},
|
|
podName: fmt.Sprintf("importer-%s-", stagePvcs[0].Name),
|
|
wantErr: false,
|
|
wantFind: true,
|
|
},
|
|
{
|
|
name: "process pvc and do not create importer pod",
|
|
args: args{stagePvcs[1]},
|
|
podName: fmt.Sprintf("importer-%s-", stagePvcs[1].Name),
|
|
wantErr: false,
|
|
wantFind: false,
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
if err := c.processPvcItem(tt.args.pvc); (err != nil) != tt.wantErr {
|
|
t.Errorf("Controller.processPvcItem() error = %v, wantErr %v", err, tt.wantErr)
|
|
}
|
|
//find importer pod
|
|
found := false
|
|
got, err := c.clientset.CoreV1().Pods(tt.args.pvc.Namespace).List(metav1.ListOptions{})
|
|
if (len(got.Items) == 0 || err != nil) && !tt.wantErr {
|
|
t.Errorf("Controller.processPvcItem() could not find any pods or got error = %v", err)
|
|
} else {
|
|
for _, p := range got.Items {
|
|
if p.GenerateName == tt.podName {
|
|
found = true
|
|
}
|
|
}
|
|
if found && !tt.wantFind {
|
|
t.Errorf("Controller.processPvcItem() found pod %v but expected not to find pod", tt.podName)
|
|
}
|
|
if !found && tt.wantFind {
|
|
t.Errorf("Controller.processPvcItem() did not find pod %v and expected to find pod", tt.podName)
|
|
}
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestController_forgetKey(t *testing.T) {
|
|
//create staging pvc and pod
|
|
pvcWithEndPointAnno := createPvc("testPvcWithEndPointAnno", "default", map[string]string{AnnEndpoint: "http://test"}, nil)
|
|
podWithCdiAnno := createPod(pvcWithEndPointAnno, DataVolName)
|
|
|
|
//run the informers
|
|
c, _, _, err := createImportController(pvcWithEndPointAnno, podWithCdiAnno, "default")
|
|
if err != nil {
|
|
t.Errorf("Controller.forgetKey() failed to initialize fake controller error = %v", err)
|
|
return
|
|
}
|
|
key, shutdown := c.pvcQueue.Get()
|
|
if shutdown {
|
|
t.Errorf("Controller.forgetKey() failed to retrieve key from pvcQueue")
|
|
return
|
|
}
|
|
defer c.pvcQueue.Done(key)
|
|
|
|
type args struct {
|
|
key interface{}
|
|
msg string
|
|
}
|
|
tests := []struct {
|
|
name string
|
|
args args
|
|
want bool
|
|
}{
|
|
{
|
|
name: "successfully forget key",
|
|
args: args{key, "test of forgetKey func"},
|
|
want: true,
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
if got := c.forgetKey(tt.args.key, tt.args.msg); got != tt.want {
|
|
t.Errorf("Controller.forgetKey() = %v, want %v", got, tt.want)
|
|
}
|
|
})
|
|
}
|
|
}
|