Skip to content

Commit d6411fd

Browse files
authored
Consolidate opt-in/opt-out handling to prevent flakes (#576)
tests sometimes fail when switching from opt-in to opt-out because it takes time for the k8s API to eventually consist the new labels behavior. In some places there is a sleep wait. Instead, add optInNamespaceForVMs() and optOutNamespaceForVMs() wrappers that perform the opt-mode change, wait for webhook configuration propagation using Eventually(). Replace sleep() calls throughout tests. Signed-off-by: Ram Lavi <ralavi@redhat.com>
1 parent 8357572 commit d6411fd

File tree

2 files changed

+66
-47
lines changed

2 files changed

+66
-47
lines changed

tests/tests.go

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,8 @@ const (
5656
podDeleteTimeout = 2 * time.Minute
5757
podDeleteInterval = 1 * time.Second
5858
deploymentAvailableTimeout = 2 * time.Minute
59+
webhookPropagationTimeout = 2 * time.Minute
60+
webhookPropagationInterval = 1 * time.Second
5961

6062
// String and format constants
6163
randomStringLength = 5
@@ -381,6 +383,61 @@ func addLabelsToNamespace(namespace string, labels map[string]string) error {
381383
return err
382384
}
383385

386+
// optInNamespaceForVMs opts in a namespace for VM MAC allocation and waits for the webhook
387+
func optInNamespaceForVMs(namespace string) {
388+
By(fmt.Sprintf("opting in namespace %s for VM MAC allocation", namespace))
389+
err := addLabelsToNamespace(namespace, map[string]string{vmNamespaceOptInLabel: "allocate"})
390+
Expect(err).ToNot(HaveOccurred(), "should be able to add opt-in label to namespace")
391+
392+
By("waiting for webhook to recognize namespace as opted-in")
393+
Eventually(func(g Gomega) {
394+
vm := CreateVMObject(namespace, []kubevirtv1.Interface{newInterface("br", "")},
395+
[]kubevirtv1.Network{newNetwork("br")})
396+
g.Expect(testClient.CRClient.Create(context.TODO(), vm)).To(Succeed())
397+
macAddress := vm.Spec.Template.Spec.Domain.Devices.Interfaces[0].MacAddress
398+
_ = testClient.CRClient.Delete(context.TODO(), vm)
399+
g.Expect(macAddress).ToNot(BeEmpty(), "VM should have MAC allocated in opted-in namespace")
400+
}, webhookPropagationTimeout, webhookPropagationInterval).Should(Succeed())
401+
}
402+
403+
// optOutNamespaceForVMs opts out a namespace from VM MAC allocation and waits for the webhook
404+
func optOutNamespaceForVMs(namespace string) {
405+
By(fmt.Sprintf("opting out namespace %s from VM MAC allocation", namespace))
406+
err := addLabelsToNamespace(namespace, map[string]string{vmNamespaceOptInLabel: "ignore"})
407+
Expect(err).ToNot(HaveOccurred(), "should be able to add opt-out label to namespace")
408+
409+
By("waiting for webhook to recognize namespace as opted-out")
410+
Eventually(func(g Gomega) {
411+
vm := CreateVMObject(namespace, []kubevirtv1.Interface{newInterface("br", "")},
412+
[]kubevirtv1.Network{newNetwork("br")})
413+
g.Expect(testClient.CRClient.Create(context.TODO(), vm)).To(Succeed())
414+
macAddress := vm.Spec.Template.Spec.Domain.Devices.Interfaces[0].MacAddress
415+
_ = testClient.CRClient.Delete(context.TODO(), vm)
416+
g.Expect(macAddress).To(BeEmpty(), "VM should not have MAC allocated in opted-out namespace")
417+
}, webhookPropagationTimeout, webhookPropagationInterval).Should(Succeed())
418+
}
419+
420+
func newInterface(name, macAddress string) kubevirtv1.Interface {
421+
return kubevirtv1.Interface{
422+
Name: name,
423+
InterfaceBindingMethod: kubevirtv1.InterfaceBindingMethod{
424+
Bridge: &kubevirtv1.InterfaceBridge{},
425+
},
426+
MacAddress: macAddress,
427+
}
428+
}
429+
430+
func newNetwork(name string) kubevirtv1.Network {
431+
return kubevirtv1.Network{
432+
Name: name,
433+
NetworkSource: kubevirtv1.NetworkSource{
434+
Multus: &kubevirtv1.MultusNetwork{
435+
NetworkName: name,
436+
},
437+
},
438+
}
439+
}
440+
384441
func getOptInLabel(webhookName string) metav1.LabelSelectorRequirement {
385442
return metav1.LabelSelectorRequirement{Key: webhookName, Operator: "In", Values: []string{"allocate"}}
386443
}

tests/virtual_machines_test.go

Lines changed: 9 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -97,9 +97,7 @@ var _ = Describe("[rfe_id:3503][crit:medium][vendor:cnv-qe@redhat.com][level:com
9797
Expect(err).ToNot(HaveOccurred(), "Should succeed getting the mutating webhook opt-mode")
9898

9999
if vmWebhookOptMode == optInMode {
100-
By("opting in the namespace")
101-
err := addLabelsToNamespace(TestNamespace, map[string]string{vmNamespaceOptInLabel: "allocate"})
102-
Expect(err).ToNot(HaveOccurred(), "should be able to add the namespace labels")
100+
optInNamespaceForVMs(TestNamespace)
103101
}
104102
})
105103

@@ -671,14 +669,12 @@ var _ = Describe("[rfe_id:3503][crit:medium][vendor:cnv-qe@redhat.com][level:com
671669
})
672670
Context("and another vm is created in an opted-in namespace", func() {
673671
BeforeEach(func() {
674-
By(fmt.Sprintf("opting in the %s namespace", managedNamespace))
675-
err := addLabelsToNamespace(managedNamespace, map[string]string{vmNamespaceOptInLabel: "allocate"})
676-
Expect(err).ToNot(HaveOccurred(), "should be able to add the namespace labels")
672+
optInNamespaceForVMs(managedNamespace)
677673

678674
By("creating a vm in the opted-in namespace")
679675
managedVM := CreateVMObject(managedNamespace, []kubevirtv1.Interface{newInterface("br", "")},
680676
[]kubevirtv1.Network{newNetwork("br")})
681-
err = testClient.CRClient.Create(context.TODO(), managedVM)
677+
err := testClient.CRClient.Create(context.TODO(), managedVM)
682678
Expect(err).ToNot(HaveOccurred(), "Should succeed creating the vm")
683679
allocatedMac = managedVM.Spec.Template.Spec.Domain.Devices.Interfaces[0].MacAddress
684680
})
@@ -732,19 +728,15 @@ var _ = Describe("[rfe_id:3503][crit:medium][vendor:cnv-qe@redhat.com][level:com
732728

733729
Context("and kubemacpool is opted-out on a namespace", func() {
734730
BeforeEach(func() {
735-
By("opting out the namespace")
736-
err := addLabelsToNamespace(TestNamespace, map[string]string{vmNamespaceOptInLabel: "ignore"})
737-
Expect(err).ToNot(HaveOccurred(), "should be able to add the namespace labels")
731+
optOutNamespaceForVMs(TestNamespace)
738732
})
739733
It("should create a VM object without a MAC assigned", func() {
740-
var err error
741734
vm := CreateVMObject(TestNamespace, []kubevirtv1.Interface{newInterface("br", "")},
742735
[]kubevirtv1.Network{newNetwork("br")})
743-
744-
err = testClient.CRClient.Create(context.TODO(), vm)
736+
err := testClient.CRClient.Create(context.TODO(), vm)
745737
Expect(err).ToNot(HaveOccurred(), "Should succeed creating the vm")
746738
Expect(vm.Spec.Template.Spec.Domain.Devices.Interfaces[0].MacAddress).Should(Equal(""),
747-
"should not allocated a mac to the opted-out vm")
739+
"should not allocate a mac to the opted-out vm")
748740
})
749741
})
750742

@@ -775,20 +767,12 @@ var _ = Describe("[rfe_id:3503][crit:medium][vendor:cnv-qe@redhat.com][level:com
775767
})
776768
Context("and then when we opt-out the namespace", func() {
777769
BeforeEach(func() {
778-
By("Adding namespace opt-out label to mark it as opted-out")
779-
err := addLabelsToNamespace(TestNamespace, map[string]string{vmNamespaceOptInLabel: "ignore"})
780-
Expect(err).ToNot(HaveOccurred(), "should be able to add the namespace labels")
781-
782-
By("Wait 5 seconds for namespace label clean-up to be propagated at server")
783-
time.Sleep(5 * time.Second)
770+
optOutNamespaceForVMs(TestNamespace)
784771
})
785772
AfterEach(func() {
786-
By("Removing namespace opt-out label to get kmp service again")
773+
By("Removing namespace opt-out label")
787774
err := cleanNamespaceLabels(TestNamespace)
788775
Expect(err).ToNot(HaveOccurred(), "should be able to remove the namespace labels")
789-
790-
By("Wait 5 seconds for opt-in label at namespace to be propagated at server")
791-
time.Sleep(5 * time.Second)
792776
})
793777
It("should able to be deleted", func() {
794778
By("Delete the VM after opt-out the namespace")
@@ -841,8 +825,7 @@ var _ = Describe("[rfe_id:3503][crit:medium][vendor:cnv-qe@redhat.com][level:com
841825
Expect(net.ParseMAC(vm1.Spec.Template.Spec.Domain.Devices.Interfaces[0].MacAddress)).ToNot(BeEmpty(),
842826
"Should successfully parse mac address")
843827

844-
err = addLabelsToNamespace(OtherTestNamespace, map[string]string{vmNamespaceOptInLabel: "ignore"})
845-
Expect(err).ToNot(HaveOccurred(), "should be able to add the namespace labels")
828+
optOutNamespaceForVMs(OtherTestNamespace)
846829

847830
By(fmt.Sprintf("Adding a vm with the same Mac Address %s on the unmanaged namespace", macAddress))
848831
conflictingVM = CreateVMObject(OtherTestNamespace,
@@ -899,27 +882,6 @@ var _ = Describe("[rfe_id:3503][crit:medium][vendor:cnv-qe@redhat.com][level:com
899882
})
900883
})
901884

902-
func newInterface(name, macAddress string) kubevirtv1.Interface {
903-
return kubevirtv1.Interface{
904-
Name: name,
905-
InterfaceBindingMethod: kubevirtv1.InterfaceBindingMethod{
906-
Bridge: &kubevirtv1.InterfaceBridge{},
907-
},
908-
MacAddress: macAddress,
909-
}
910-
}
911-
912-
func newNetwork(name string) kubevirtv1.Network {
913-
return kubevirtv1.Network{
914-
Name: name,
915-
NetworkSource: kubevirtv1.NetworkSource{
916-
Multus: &kubevirtv1.MultusNetwork{
917-
NetworkName: name,
918-
},
919-
},
920-
}
921-
}
922-
923885
func deleteVMI(vm *kubevirtv1.VirtualMachine) {
924886
By(fmt.Sprintf("Delete vm %s/%s", vm.Namespace, vm.Name))
925887
err := testClient.CRClient.Delete(context.TODO(), vm)

0 commit comments

Comments
 (0)