From 6cfe69a12c0d768fba6272cf934f8463059f6828 Mon Sep 17 00:00:00 2001 From: ushabelgur Date: Fri, 7 Feb 2025 11:56:42 +0530 Subject: [PATCH] fix IRI volume list update --- .../controllers/machine_controller_test.go | 149 ++++++++++++++++++ .../controllers/machine_controller_volume.go | 2 +- 2 files changed, 150 insertions(+), 1 deletion(-) diff --git a/poollet/machinepoollet/controllers/machine_controller_test.go b/poollet/machinepoollet/controllers/machine_controller_test.go index fd6c975e5..7d5431747 100644 --- a/poollet/machinepoollet/controllers/machine_controller_test.go +++ b/poollet/machinepoollet/controllers/machine_controller_test.go @@ -482,6 +482,155 @@ var _ = Describe("MachineController", func() { })))) }) + It("should validate IRI volume update for machine", func(ctx SpecContext) { + By("creating a network") + network := &networkingv1alpha1.Network{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: ns.Name, + GenerateName: "network-", + }, + Spec: networkingv1alpha1.NetworkSpec{ + ProviderID: "foo", + }, + } + Expect(k8sClient.Create(ctx, network)).To(Succeed()) + + By("patching the network to be available") + Eventually(UpdateStatus(network, func() { + network.Status.State = networkingv1alpha1.NetworkStateAvailable + })).Should(Succeed()) + + By("creating a network interface") + nic := &networkingv1alpha1.NetworkInterface{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: ns.Name, + GenerateName: "nic-", + }, + Spec: networkingv1alpha1.NetworkInterfaceSpec{ + NetworkRef: corev1.LocalObjectReference{Name: network.Name}, + IPs: []networkingv1alpha1.IPSource{ + {Value: commonv1alpha1.MustParseNewIP("10.0.0.1")}, + }, + }, + } + Expect(k8sClient.Create(ctx, nic)).To(Succeed()) + + By("creating a volume") + volume := &storagev1alpha1.Volume{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: ns.Name, + GenerateName: "volume-", + }, + Spec: storagev1alpha1.VolumeSpec{}, + } + Expect(k8sClient.Create(ctx, volume)).To(Succeed()) + + By("patching the volume to be available") + Eventually(UpdateStatus(volume, func() { + volume.Status.State = storagev1alpha1.VolumeStateAvailable + volume.Status.Access = &storagev1alpha1.VolumeAccess{ + Driver: "test", + Handle: "testhandle", + } + })).Should(Succeed()) + + secondaryVolume := &storagev1alpha1.Volume{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: ns.Name, + GenerateName: "volume-", + }, + Spec: storagev1alpha1.VolumeSpec{}, + } + Expect(k8sClient.Create(ctx, secondaryVolume)).To(Succeed()) + + By("patching the secondary volume to be available") + Eventually(UpdateStatus(secondaryVolume, func() { + secondaryVolume.Status.State = storagev1alpha1.VolumeStateAvailable + secondaryVolume.Status.Access = &storagev1alpha1.VolumeAccess{ + Driver: "test", + Handle: "testhandle", + } + })).Should(Succeed()) + + By("creating a machine") + const fooAnnotationValue = "bar" + machine := &computev1alpha1.Machine{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: ns.Name, + GenerateName: "machine-", + Annotations: map[string]string{ + fooAnnotation: fooAnnotationValue, + }, + }, + Spec: computev1alpha1.MachineSpec{ + MachineClassRef: corev1.LocalObjectReference{Name: mc.Name}, + MachinePoolRef: &corev1.LocalObjectReference{Name: mp.Name}, + Volumes: []computev1alpha1.Volume{ + { + Name: "primary", + VolumeSource: computev1alpha1.VolumeSource{ + VolumeRef: &corev1.LocalObjectReference{Name: volume.Name}, + }, + }, + { + Name: "secondary", + VolumeSource: computev1alpha1.VolumeSource{ + VolumeRef: &corev1.LocalObjectReference{Name: secondaryVolume.Name}, + }, + }, + }, + NetworkInterfaces: []computev1alpha1.NetworkInterface{ + { + Name: "primary", + NetworkInterfaceSource: computev1alpha1.NetworkInterfaceSource{ + NetworkInterfaceRef: &corev1.LocalObjectReference{Name: nic.Name}, + }, + }, + }, + }, + } + Expect(k8sClient.Create(ctx, machine)).To(Succeed()) + + By("waiting for the runtime to report the machine, volume and network interface") + Eventually(srv).Should(SatisfyAll( + HaveField("Machines", HaveLen(1)), + )) + _, iriMachine := GetSingleMapEntry(srv.Machines) + + By("inspecting the iri machine volumes") + Expect(iriMachine.Spec.Volumes).To(ConsistOf(&iri.Volume{ + Name: "primary", + Device: "oda", + Connection: &iri.VolumeConnection{ + Driver: "test", + Handle: "testhandle", + }, + }, &iri.Volume{ + Name: "secondary", + Device: "odb", + Connection: &iri.VolumeConnection{ + Driver: "test", + Handle: "testhandle", + }, + })) + + By("patching the secondary volume to be in error state") + Eventually(UpdateStatus(secondaryVolume, func() { + secondaryVolume.Status.State = storagev1alpha1.VolumeStateError + })).Should(Succeed()) + + By("verifying only erroneous volume is detached") + Eventually(func() []*iri.Volume { + return srv.Machines[iriMachine.Metadata.Id].Spec.Volumes + }).Should(SatisfyAll((ConsistOf(&iri.Volume{ + Name: "primary", + Device: "oda", + Connection: &iri.VolumeConnection{ + Driver: "test", + Handle: "testhandle", + }, + })))) + }) }) func GetSingleMapEntry[K comparable, V any](m map[K]V) (K, V) { diff --git a/poollet/machinepoollet/controllers/machine_controller_volume.go b/poollet/machinepoollet/controllers/machine_controller_volume.go index 42b559bc2..45a4ba686 100644 --- a/poollet/machinepoollet/controllers/machine_controller_volume.go +++ b/poollet/machinepoollet/controllers/machine_controller_volume.go @@ -230,7 +230,7 @@ func (r *MachineReconciler) prepareIRIVolumes( actualVolumeNames := utilslices.ToSetFunc(iriVolumes, (*iri.Volume).GetName) missingVolumeNames := sets.List(expectedVolumeNames.Difference(actualVolumeNames)) r.Eventf(machine, corev1.EventTypeNormal, events.VolumeNotReady, "Machine volumes are not ready: %v", missingVolumeNames) - return nil, false, nil + return iriVolumes, false, nil } return iriVolumes, true, nil }