From cdb9f5b3ed6d9be034c162fa5db7ec31707ef1dd Mon Sep 17 00:00:00 2001 From: Victor Morales Date: Tue, 4 Feb 2025 21:08:39 -0800 Subject: [PATCH] Add unit tests to delete resources use case --- cmd/kar/app/root.go | 2 +- cmd/kar/app/root_test.go | 8 +++++- cmd/kar/main.go | 2 +- internal/runner.go | 28 ++++++++++-------- internal/runner_test.go | 61 ++++++++++++++++++++++++++++++++++------ 5 files changed, 78 insertions(+), 23 deletions(-) diff --git a/cmd/kar/app/root.go b/cmd/kar/app/root.go index cbec2a8..3a6c89a 100644 --- a/cmd/kar/app/root.go +++ b/cmd/kar/app/root.go @@ -46,7 +46,7 @@ func run(ctx context.Context, runner runner.Runner, opts Opts) error { if err != nil { return errors.Wrap(err, "fail to create resources") } - defer runner.DeleteResources(ctx) + defer runner.DeleteResources(ctx, runner.GetDataVolumeName(), runner.GetDataVolumeName()) runner.WaitForVirtualMachineInstance(ctx) diff --git a/cmd/kar/app/root_test.go b/cmd/kar/app/root_test.go index adaba19..3b49691 100644 --- a/cmd/kar/app/root_test.go +++ b/cmd/kar/app/root_test.go @@ -45,6 +45,10 @@ func (m *mock) GetVMIName() string { return m.runnerName } +func (m *mock) GetDataVolumeName() string { + return m.runnerName +} + func (m *mock) CreateResources(_ context.Context, vmTemplate, runnerName, jitConfig string, ) error { m.vmTemplate = vmTemplate @@ -60,8 +64,10 @@ func (m *mock) WaitForVirtualMachineInstance(_ context.Context) { m.waitCalled = true } -func (m *mock) DeleteResources(_ context.Context) { +func (m *mock) DeleteResources(_ context.Context, _, _ string) error { m.deleteCalled = true + + return nil } var _ = Describe("Root Command", func() { diff --git a/cmd/kar/main.go b/cmd/kar/main.go index 2df96d3..02e2d8d 100644 --- a/cmd/kar/main.go +++ b/cmd/kar/main.go @@ -87,7 +87,7 @@ func main() { go func() { <-ctx.Done() - runner.DeleteResources(ctx) + runner.DeleteResources(ctx, runner.GetVMIName(), runner.GetDataVolumeName()) stop() }() diff --git a/internal/runner.go b/internal/runner.go index cd17a44..e315ac3 100644 --- a/internal/runner.go +++ b/internal/runner.go @@ -28,7 +28,6 @@ import ( k8smetav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/utils/ptr" v1 "kubevirt.io/api/core/v1" - cdiclient "kubevirt.io/client-go/containerizeddataimporter" "kubevirt.io/client-go/kubecli" "kubevirt.io/containerized-data-importer-api/pkg/apis/core/v1beta1" ) @@ -42,14 +41,14 @@ const ( type Runner interface { CreateResources(ctx context.Context, vmTemplate string, runnerName string, jitConfig string) error WaitForVirtualMachineInstance(ctx context.Context) - DeleteResources(ctx context.Context) + DeleteResources(ctx context.Context, vmi string, dv string) error Failed() bool GetVMIName() string + GetDataVolumeName() string } type KubevirtRunner struct { virtClient kubecli.KubevirtClient - cdiClient cdiclient.Interface namespace string dataVolume string virtualMachineInstance string @@ -66,6 +65,10 @@ func (rc *KubevirtRunner) GetVMIName() string { return rc.virtualMachineInstance } +func (rc *KubevirtRunner) GetDataVolumeName() string { + return rc.dataVolume +} + func (rc *KubevirtRunner) getResources(ctx context.Context, vmTemplate, runnerName, jitConfig string) ( *v1.VirtualMachineInstance, *v1beta1.DataVolume, error, ) { @@ -178,7 +181,7 @@ func (rc *KubevirtRunner) CreateResources(ctx context.Context, }, } - if _, err := rc.cdiClient.CdiV1beta1().DataVolumes( + if _, err := rc.virtClient.CdiClient().CdiV1beta1().DataVolumes( rc.namespace).Create(ctx, dataVolume, k8smetav1.CreateOptions{}); err != nil { return errors.Wrap(err, "cannot create data volume") } @@ -230,27 +233,28 @@ func (rc *KubevirtRunner) WaitForVirtualMachineInstance(ctx context.Context) { } } -func (rc *KubevirtRunner) DeleteResources(ctx context.Context) { +func (rc *KubevirtRunner) DeleteResources(ctx context.Context, virtualMachineInstance, dataVolume string) error { log.Printf("Cleaning %s Virtual Machine Instance resources\n", - rc.virtualMachineInstance) + virtualMachineInstance) if err := rc.virtClient.VirtualMachineInstance(rc.namespace).Delete( - ctx, rc.virtualMachineInstance, k8smetav1.DeleteOptions{}); err != nil { - log.Fatal(err.Error()) + ctx, virtualMachineInstance, k8smetav1.DeleteOptions{}); err != nil { + return errors.Wrap(err, "fail to delete runner instance") } - if len(rc.dataVolume) > 0 { - if err := rc.cdiClient.CdiV1beta1().DataVolumes(rc.namespace).Delete(ctx, rc.dataVolume, + if len(dataVolume) > 0 { + if err := rc.virtClient.CdiClient().CdiV1beta1().DataVolumes(rc.namespace).Delete(ctx, dataVolume, k8smetav1.DeleteOptions{}); err != nil { - log.Fatal(err.Error()) + return errors.Wrap(err, "fail to delete runner data volume") } } + + return nil } func NewRunner(namespace string, virtClient kubecli.KubevirtClient) *KubevirtRunner { return &KubevirtRunner{ namespace: namespace, virtClient: virtClient, - cdiClient: virtClient.CdiClient(), } } diff --git a/internal/runner_test.go b/internal/runner_test.go index b6b6ff7..3fb1214 100644 --- a/internal/runner_test.go +++ b/internal/runner_test.go @@ -29,6 +29,7 @@ import ( cdifake "kubevirt.io/client-go/containerizeddataimporter/fake" "kubevirt.io/client-go/kubecli" kubevirtfake "kubevirt.io/client-go/kubevirt/fake" + "kubevirt.io/containerized-data-importer-api/pkg/apis/core/v1beta1" ) var _ = Describe("Runner", func() { @@ -36,9 +37,16 @@ var _ = Describe("Runner", func() { var virtClientset *kubevirtfake.Clientset var karRunner runner.Runner + const ( + vmTemplate = "vm-template" + vmInstance = "runner-xyz123" + dataVolume = "dv-xyz123" + ) + BeforeEach(func() { - cdiClientset := cdifake.NewSimpleClientset() virtClient = kubecli.NewMockKubevirtClient(gomock.NewController(GinkgoT())) + virtClientset = kubevirtfake.NewSimpleClientset(NewVirtualMachineInstance(vmInstance), NewVirtualMachine(vmTemplate)) + cdiClientset := cdifake.NewSimpleClientset(NewDataVolume(dataVolume)) virtClient.EXPECT().CdiClient().Return(cdiClientset).AnyTimes() @@ -46,9 +54,6 @@ var _ = Describe("Runner", func() { }) DescribeTable("create resources", func(shouldSucceed bool, vmTemplate, runnerName, jitConfig string) { - vm := NewVirtualMachine(vmTemplate) - virtClientset = kubevirtfake.NewSimpleClientset(vm) - if shouldSucceed { virtClient.EXPECT().VirtualMachine(k8sv1.NamespaceDefault).Return( virtClientset.KubevirtV1().VirtualMachines(k8sv1.NamespaceDefault), @@ -76,16 +81,38 @@ var _ = Describe("Runner", func() { } } }, - Entry("when the valid information is provided", true, "vmTemplate", "runnerName", "jitConfig"), + Entry("when the valid information is provided", true, vmTemplate, "runnerName", "jitConfig"), Entry("when empty vm template is provided", false, "", "runnerName", "jitConfig"), - Entry("when empty runner name is provided", false, "vmTemplate", "", "jitConfig"), - Entry("when empty jit config is provided", false, "vmTemplate", "runnerName", ""), + Entry("when empty runner name is provided", false, vmTemplate, "", "jitConfig"), + Entry("when empty jit config is provided", false, vmTemplate, "runnerName", ""), + ) + + DescribeTable("delete resources", func(shouldSucceed bool, vmInstance, dataVolume string) { + virtClient.EXPECT().VirtualMachineInstance(k8sv1.NamespaceDefault).Return( + virtClientset.KubevirtV1().VirtualMachineInstances(k8sv1.NamespaceDefault), + ) + + err := karRunner.DeleteResources(context.TODO(), vmInstance, dataVolume) + + if shouldSucceed { + Expect(err).NotTo(HaveOccurred()) + } else { + Expect(err).To(HaveOccurred()) + } + }, + Entry("when the runner has a data volume", true, vmInstance, dataVolume), + Entry("when the runner doesn't have data volumes", true, vmInstance, ""), + Entry("when the runner doesn't exist", false, "runner-abc098", ""), + Entry("when the data volume doesn't exist", false, vmInstance, "dv-abc098"), ) }) func NewVirtualMachine(name string) *v1.VirtualMachine { return &v1.VirtualMachine{ - ObjectMeta: metav1.ObjectMeta{Name: name, Namespace: k8sv1.NamespaceDefault, ResourceVersion: "1", UID: "vm-uid"}, + ObjectMeta: metav1.ObjectMeta{ + Name: name, + Namespace: k8sv1.NamespaceDefault, + }, Spec: v1.VirtualMachineSpec{ Template: &v1.VirtualMachineInstanceTemplateSpec{ ObjectMeta: metav1.ObjectMeta{}, @@ -93,3 +120,21 @@ func NewVirtualMachine(name string) *v1.VirtualMachine { }, } } + +func NewVirtualMachineInstance(name string) *v1.VirtualMachineInstance { + return &v1.VirtualMachineInstance{ + ObjectMeta: metav1.ObjectMeta{ + Name: name, + Namespace: k8sv1.NamespaceDefault, + }, + } +} + +func NewDataVolume(name string) *v1beta1.DataVolume { + return &v1beta1.DataVolume{ + ObjectMeta: metav1.ObjectMeta{ + Name: name, + Namespace: k8sv1.NamespaceDefault, + }, + } +}