api/handler/vm_export_test.go
Rama main · réplica de lectura del repositorio original.
package handler
import (
"context"
"testing"
"github.com/golang/mock/gomock"
"github.com/goodrain/rainbond/pkg/component/k8s"
kubecli "kubevirt.io/client-go/kubecli"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/client-go/dynamic"
"k8s.io/client-go/dynamic/fake"
k8sfake "k8s.io/client-go/kubernetes/fake"
kubevirtv1 "kubevirt.io/api/core/v1"
)
// capability_id: rainbond.vm-export.root-disk-url
func TestResolveVMRootPVC(t *testing.T) {
vm := &kubevirtv1.VirtualMachine{
Spec: kubevirtv1.VirtualMachineSpec{
Template: &kubevirtv1.VirtualMachineInstanceTemplateSpec{
Spec: kubevirtv1.VirtualMachineInstanceSpec{
Domain: kubevirtv1.DomainSpec{
Devices: kubevirtv1.Devices{
Disks: []kubevirtv1.Disk{
{
Name: "manual22",
BootOrder: func() *uint {
value := uint(1)
return &value
}(),
},
},
},
},
Volumes: []kubevirtv1.Volume{
{
Name: "manual22",
VolumeSource: kubevirtv1.VolumeSource{
DataVolume: &kubevirtv1.DataVolumeSource{Name: "manual22"},
},
},
},
},
},
},
}
pvc, err := resolveVMRootPVC(vm)
if err != nil {
t.Fatalf("expected no error, got %v", err)
}
if pvc != "manual22" {
t.Fatalf("expected manual22, got %s", pvc)
}
}
func TestCreateVMExport(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()
mockClient := kubecli.NewMockKubevirtClient(ctrl)
mockVMInterface := kubecli.NewMockVirtualMachineInterface(ctrl)
vmExportDynamicClient = func() dynamic.Interface {
return fake.NewSimpleDynamicClient(runtime.NewScheme())
}
defer func() {
vmExportDynamicClient = func() dynamic.Interface {
if k8s.Default() == nil {
return nil
}
return k8s.Default().DynamicClient
}
}()
mockClient.EXPECT().VirtualMachine("").Return(mockVMInterface)
mockVMInterface.EXPECT().List(gomock.Any(), metav1.ListOptions{LabelSelector: "service_id=service-1"}).Return(&kubevirtv1.VirtualMachineList{
Items: []kubevirtv1.VirtualMachine{
{
ObjectMeta: metav1.ObjectMeta{
Name: "demo-vm",
Namespace: "demo-ns",
},
Spec: kubevirtv1.VirtualMachineSpec{
Template: &kubevirtv1.VirtualMachineInstanceTemplateSpec{
Spec: kubevirtv1.VirtualMachineInstanceSpec{
Domain: kubevirtv1.DomainSpec{
Devices: kubevirtv1.Devices{
Disks: []kubevirtv1.Disk{
{
Name: "manual22",
BootOrder: func() *uint {
value := uint(1)
return &value
}(),
},
},
},
},
Volumes: []kubevirtv1.Volume{
{
Name: "manual22",
VolumeSource: kubevirtv1.VolumeSource{
DataVolume: &kubevirtv1.DataVolumeSource{Name: "manual22"},
},
},
},
},
},
},
},
},
}, nil)
kubeClient := k8sfake.NewSimpleClientset()
action := &ServiceAction{
kubevirtClient: mockClient,
kubeClient: kubeClient,
}
status, err := action.CreateVMExport("service-1", &VMExportRequest{
Name: "osdisk-export",
Description: "root disk export",
})
if err != nil {
t.Fatalf("expected no error, got %v", err)
}
if status.ExportName != "osdisk-export" {
t.Fatalf("unexpected export name: %#v", status)
}
if status.SourcePVC != "manual22" {
t.Fatalf("unexpected source pvc: %#v", status)
}
secret, err := kubeClient.CoreV1().Secrets("demo-ns").Get(context.Background(), "osdisk-export-token", metav1.GetOptions{})
if err != nil {
t.Fatalf("expected token secret, got %v", err)
}
if len(secret.Data["token"]) == 0 {
t.Fatalf("expected token secret to contain token")
}
if status.DownloadToken != string(secret.Data["token"]) {
t.Fatalf("expected export status to include download token")
}
}
func TestExtractVMExportDownloadURLPrefersGzip(t *testing.T) {
url := extractVMExportDownloadURL(map[string]interface{}{
"status": map[string]interface{}{
"links": map[string]interface{}{
"internal": map[string]interface{}{
"volumes": []interface{}{
map[string]interface{}{
"formats": []interface{}{
map[string]interface{}{
"format": "raw",
"url": "https://export.default.svc/volumes/root/disk.img",
},
map[string]interface{}{
"format": "gzip",
"url": "https://export.default.svc/volumes/root/disk.img.gz",
},
},
},
},
},
},
},
})
if url != "https://export.default.svc/volumes/root/disk.img.gz" {
t.Fatalf("expected gzip url, got %s", url)
}
}
func TestGetVMExport(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()
export := buildVMExport("demo-ns", "osdisk-export", "root disk export", "service-1", "manual22", "osdisk-export-token")
export.Object["status"] = map[string]interface{}{
"phase": "Ready",
"links": map[string]interface{}{
"internal": map[string]interface{}{
"volumes": []interface{}{
map[string]interface{}{
"formats": []interface{}{
map[string]interface{}{
"format": "gzip",
"url": "https://virt-export-osdisk-export.default.svc/volumes/manual22/disk.img.gz",
},
},
},
},
},
},
}
vmExportDynamicClient = func() dynamic.Interface {
return fake.NewSimpleDynamicClient(runtime.NewScheme(), export)
}
defer func() {
vmExportDynamicClient = func() dynamic.Interface {
if k8s.Default() == nil {
return nil
}
return k8s.Default().DynamicClient
}
}()
mockClient := kubecli.NewMockKubevirtClient(ctrl)
mockVMInterface := kubecli.NewMockVirtualMachineInterface(ctrl)
mockClient.EXPECT().VirtualMachine("").Return(mockVMInterface)
mockVMInterface.EXPECT().List(gomock.Any(), metav1.ListOptions{LabelSelector: "service_id=service-1"}).Return(&kubevirtv1.VirtualMachineList{
Items: []kubevirtv1.VirtualMachine{
{
ObjectMeta: metav1.ObjectMeta{
Name: "demo-vm",
Namespace: "demo-ns",
},
},
},
}, nil)
kubeClient := k8sfake.NewSimpleClientset(&corev1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: "osdisk-export-token",
Namespace: "demo-ns",
},
Data: map[string][]byte{
"token": []byte("download-token"),
},
})
action := &ServiceAction{kubevirtClient: mockClient, kubeClient: kubeClient}
status, err := action.GetVMExport("service-1", "osdisk-export")
if err != nil {
t.Fatalf("expected no error, got %v", err)
}
if status.Phase != "Ready" {
t.Fatalf("expected Ready phase, got %#v", status)
}
if status.SourcePVC != "manual22" {
t.Fatalf("expected manual22 source pvc, got %#v", status)
}
if status.DownloadURL != "https://virt-export-osdisk-export.default.svc/volumes/manual22/disk.img.gz" {
t.Fatalf("unexpected download url: %#v", status)
}
if status.DownloadToken != "download-token" {
t.Fatalf("unexpected download token: %#v", status)
}
}