diff --git a/go.mod b/go.mod index 0954cc17e..f45af849f 100644 --- a/go.mod +++ b/go.mod @@ -15,7 +15,7 @@ require ( k8s.io/api v0.27.1 k8s.io/apimachinery v0.27.1 k8s.io/client-go v12.0.0+incompatible - k8s.io/utils v0.0.0-20230505201702-9f6742963106 + k8s.io/utils v0.0.0-20241210054802-24370beab758 kubevirt.io/api v1.0.0 kubevirt.io/client-go v1.0.0 sigs.k8s.io/controller-runtime v0.14.6 diff --git a/go.sum b/go.sum index a4ca57359..436359326 100644 --- a/go.sum +++ b/go.sum @@ -1948,8 +1948,8 @@ k8s.io/utils v0.0.0-20201110183641-67b214c5f920/go.mod h1:jPW/WVKK9YHAvNhRxK0md/ k8s.io/utils v0.0.0-20210802155522-efc7438f0176/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= k8s.io/utils v0.0.0-20220210201930-3a6ce19ff2f9/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= k8s.io/utils v0.0.0-20221107191617-1a15be271d1d/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= -k8s.io/utils v0.0.0-20230505201702-9f6742963106 h1:EObNQ3TW2D+WptiYXlApGNLVy0zm/JIBVY9i+M4wpAU= -k8s.io/utils v0.0.0-20230505201702-9f6742963106/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= +k8s.io/utils v0.0.0-20241210054802-24370beab758 h1:sdbE21q2nlQtFh65saZY+rRM6x6aJJI8IUa1AmH/qa0= +k8s.io/utils v0.0.0-20241210054802-24370beab758/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= kubevirt.io/api v1.0.0 h1:RBdXP5CDhE0v5qL2OUQdrYyRrHe/F68Z91GWqBDF6nw= kubevirt.io/api v1.0.0/go.mod h1:CJ4vZsaWhVN3jNbyc9y3lIZhw8nUHbWjap0xHABQiqc= kubevirt.io/client-go v1.0.0 h1:MMn41j/lFd+lJ7gWn7yuIZYW/aT9fI3bUimAuxAQ+Xk= diff --git a/tests/tests.go b/tests/tests.go index 4fa87ed4a..fc15ebfcd 100644 --- a/tests/tests.go +++ b/tests/tests.go @@ -25,6 +25,7 @@ import ( "k8s.io/apimachinery/pkg/util/rand" "k8s.io/client-go/util/retry" "k8s.io/utils/pointer" + "k8s.io/utils/ptr" kubevirtv1 "kubevirt.io/api/core/v1" "kubevirt.io/client-go/kubecli" @@ -91,11 +92,10 @@ func removeTestNamespaces() { Should(BeTrue(), "Namespace %s haven't been deleted within the given timeout", TestNamespace) } -func CreateVmObject(namespace string, running bool, interfaces []kubevirtv1.Interface, networks []kubevirtv1.Network) *kubevirtv1.VirtualMachine { +func CreateVmObject(namespace string, interfaces []kubevirtv1.Interface, networks []kubevirtv1.Network) *kubevirtv1.VirtualMachine { vm := getVMCirros() vm.Name = randName("testvm") vm.Namespace = namespace - vm.Spec.Running = &running vm.Spec.Template.Spec.Domain.Devices.Interfaces = interfaces vm.Spec.Template.Spec.Networks = networks @@ -537,7 +537,7 @@ func getVMCirros() *kubevirtv1.VirtualMachine { }, }, Spec: kubevirtv1.VirtualMachineSpec{ - Running: pointer.Bool(false), + RunStrategy: ptr.To(kubevirtv1.RunStrategyHalted), Template: &kubevirtv1.VirtualMachineInstanceTemplateSpec{ ObjectMeta: metav1.ObjectMeta{ Labels: map[string]string{ diff --git a/tests/virtual_machines_test.go b/tests/virtual_machines_test.go index 4d579a46f..48253718f 100644 --- a/tests/virtual_machines_test.go +++ b/tests/virtual_machines_test.go @@ -102,7 +102,7 @@ var _ = Describe("[rfe_id:3503][crit:medium][vendor:cnv-qe@redhat.com][level:com BeforeEach(func() { By("Creating a vm with dry run mode") var err error - vm := CreateVmObject(TestNamespace, false, []kubevirtv1.Interface{newInterface("br", "")}, []kubevirtv1.Network{newNetwork("br")}) + vm := CreateVmObject(TestNamespace, []kubevirtv1.Interface{newInterface("br", "")}, []kubevirtv1.Network{newNetwork("br")}) createOptions := &client.CreateOptions{} client.DryRunAll.ApplyToCreate(createOptions) @@ -116,7 +116,7 @@ var _ = Describe("[rfe_id:3503][crit:medium][vendor:cnv-qe@redhat.com][level:com PIt("should not allocate the Mac assigned in the dryRun request into the pool", func() { By("creating a vm with the same mac to make sure the dryRun assigned mac is not occupied on the macpool") var err error - vmDryRunOverlap := CreateVmObject(TestNamespace, false, []kubevirtv1.Interface{newInterface("brDryRunOverlap", macAddress)}, []kubevirtv1.Network{newNetwork("brDryRunOverlap")}) + vmDryRunOverlap := CreateVmObject(TestNamespace, []kubevirtv1.Interface{newInterface("brDryRunOverlap", macAddress)}, []kubevirtv1.Network{newNetwork("brDryRunOverlap")}) vmDryRunOverlap, err = testClient.VirtClient.VirtualMachine(vmDryRunOverlap.Namespace).Create(context.TODO(), vmDryRunOverlap) Expect(err).ToNot(HaveOccurred()) @@ -131,12 +131,12 @@ var _ = Describe("[rfe_id:3503][crit:medium][vendor:cnv-qe@redhat.com][level:com Context("When the MAC address is within range", func() { DescribeTable("[test_id:2166]should reject a vm creation with an already allocated MAC address", func(separator string) { var err error - vm := CreateVmObject(TestNamespace, false, []kubevirtv1.Interface{newInterface("br", "")}, []kubevirtv1.Network{newNetwork("br")}) + vm := CreateVmObject(TestNamespace, []kubevirtv1.Interface{newInterface("br", "")}, []kubevirtv1.Network{newNetwork("br")}) vm, err = testClient.VirtClient.VirtualMachine(vm.Namespace).Create(context.TODO(), vm) Expect(err).ToNot(HaveOccurred()) Expect(net.ParseMAC(vm.Spec.Template.Spec.Domain.Devices.Interfaces[0].MacAddress)).ToNot(BeEmpty(), "Should successfully parse mac address") - vmOverlap := CreateVmObject(TestNamespace, false, []kubevirtv1.Interface{newInterface("brOverlap", "")}, []kubevirtv1.Network{newNetwork("brOverlap")}) + vmOverlap := CreateVmObject(TestNamespace, []kubevirtv1.Interface{newInterface("brOverlap", "")}, []kubevirtv1.Network{newNetwork("brOverlap")}) // Allocated the same MAC address that was registered to the first vm vmOverlapMacAddress := strings.Replace(vm.Spec.Template.Spec.Domain.Devices.Interfaces[0].MacAddress, ":", separator, 5) vmOverlap.Spec.Template.Spec.Domain.Devices.Interfaces[0].MacAddress = vmOverlapMacAddress @@ -151,14 +151,14 @@ var _ = Describe("[rfe_id:3503][crit:medium][vendor:cnv-qe@redhat.com][level:com Context("and the MAC address is out of range", func() { It("[test_id:2167]should reject a vm creation with an already allocated MAC address", func() { var err error - vm := CreateVmObject(TestNamespace, false, []kubevirtv1.Interface{newInterface("br", "03:ff:ff:ff:ff:ff")}, + vm := CreateVmObject(TestNamespace, []kubevirtv1.Interface{newInterface("br", "03:ff:ff:ff:ff:ff")}, []kubevirtv1.Network{newNetwork("br")}) vm, err = testClient.VirtClient.VirtualMachine(vm.Namespace).Create(context.TODO(), vm) Expect(err).ToNot(HaveOccurred()) Expect(net.ParseMAC(vm.Spec.Template.Spec.Domain.Devices.Interfaces[0].MacAddress)).ToNot(BeEmpty(), "Should successfully parse mac address") // Allocated the same mac address that was registered to the first vm - vmOverlap := CreateVmObject(TestNamespace, false, []kubevirtv1.Interface{newInterface("brOverlap", "03:ff:ff:ff:ff:ff")}, + vmOverlap := CreateVmObject(TestNamespace, []kubevirtv1.Interface{newInterface("brOverlap", "03:ff:ff:ff:ff:ff")}, []kubevirtv1.Network{newNetwork("brOverlap")}) vmOverlap, err = testClient.VirtClient.VirtualMachine(vmOverlap.Namespace).Create(context.TODO(), vmOverlap) Expect(err).To(HaveOccurred()) @@ -171,7 +171,7 @@ var _ = Describe("[rfe_id:3503][crit:medium][vendor:cnv-qe@redhat.com][level:com Context("and when the MAC address is within range", func() { It("[test_id:2199]should reject a VM creation with two interfaces that share the same MAC address", func() { var err error - vm := CreateVmObject(TestNamespace, false, []kubevirtv1.Interface{newInterface("br1", "02:00:00:00:ff:ff"), + vm := CreateVmObject(TestNamespace, []kubevirtv1.Interface{newInterface("br1", "02:00:00:00:ff:ff"), newInterface("br2", "02:00:00:00:ff:ff")}, []kubevirtv1.Network{newNetwork("br1"), newNetwork("br2")}) vm, err = testClient.VirtClient.VirtualMachine(vm.Namespace).Create(context.TODO(), vm) Expect(err).To(HaveOccurred()) @@ -181,7 +181,7 @@ var _ = Describe("[rfe_id:3503][crit:medium][vendor:cnv-qe@redhat.com][level:com Context("and when the MAC address is out of range", func() { It("[test_id:2200]should reject a VM creation with two interfaces that share the same MAC address", func() { var err error - vm := CreateVmObject(TestNamespace, false, []kubevirtv1.Interface{newInterface("br1", "03:ff:ff:ff:ff:ff"), + vm := CreateVmObject(TestNamespace, []kubevirtv1.Interface{newInterface("br1", "03:ff:ff:ff:ff:ff"), newInterface("br2", "03:ff:ff:ff:ff:ff")}, []kubevirtv1.Network{newNetwork("br1"), newNetwork("br2")}) vm, err = testClient.VirtClient.VirtualMachine(vm.Namespace).Create(context.TODO(), vm) Expect(err).To(HaveOccurred()) @@ -193,12 +193,12 @@ var _ = Describe("[rfe_id:3503][crit:medium][vendor:cnv-qe@redhat.com][level:com It("[test_id:2164]should not return an error because the MAC addresses of the old VMs should have been released", func() { var err error //creating two VMs - vm1 := CreateVmObject(TestNamespace, false, []kubevirtv1.Interface{newInterface("br1", "")}, []kubevirtv1.Network{newNetwork("br1")}) + vm1 := CreateVmObject(TestNamespace, []kubevirtv1.Interface{newInterface("br1", "")}, []kubevirtv1.Network{newNetwork("br1")}) vm1, err = testClient.VirtClient.VirtualMachine(vm1.Namespace).Create(context.TODO(), vm1) Expect(err).ToNot(HaveOccurred()) Expect(net.ParseMAC(vm1.Spec.Template.Spec.Domain.Devices.Interfaces[0].MacAddress)).ToNot(BeEmpty(), "Should successfully parse mac address") - vm2 := CreateVmObject(TestNamespace, false, []kubevirtv1.Interface{newInterface("br2", "")}, []kubevirtv1.Network{newNetwork("br2")}) + vm2 := CreateVmObject(TestNamespace, []kubevirtv1.Interface{newInterface("br2", "")}, []kubevirtv1.Network{newNetwork("br2")}) vm2, err = testClient.VirtClient.VirtualMachine(vm2.Namespace).Create(context.TODO(), vm2) Expect(err).ToNot(HaveOccurred()) Expect(net.ParseMAC(vm2.Spec.Template.Spec.Domain.Devices.Interfaces[0].MacAddress)).ToNot(BeEmpty(), "Should successfully parse mac address") @@ -210,7 +210,7 @@ var _ = Describe("[rfe_id:3503][crit:medium][vendor:cnv-qe@redhat.com][level:com deleteVMI(vm1) deleteVMI(vm2) - newVM1 := CreateVmObject(TestNamespace, false, []kubevirtv1.Interface{newInterface("br1", vm1MacAddress)}, + newVM1 := CreateVmObject(TestNamespace, []kubevirtv1.Interface{newInterface("br1", vm1MacAddress)}, []kubevirtv1.Network{newNetwork("br1")}) Eventually(func() error { @@ -223,7 +223,7 @@ var _ = Describe("[rfe_id:3503][crit:medium][vendor:cnv-qe@redhat.com][level:com }, timeout, pollingInterval).ShouldNot(HaveOccurred(), "failed to apply the new vm object") Expect(net.ParseMAC(newVM1.Spec.Template.Spec.Domain.Devices.Interfaces[0].MacAddress)).ToNot(BeEmpty(), "Should successfully parse mac address") - newVM2 := CreateVmObject(TestNamespace, false, []kubevirtv1.Interface{newInterface("br2", vm2MacAddress)}, + newVM2 := CreateVmObject(TestNamespace, []kubevirtv1.Interface{newInterface("br2", vm2MacAddress)}, []kubevirtv1.Network{newNetwork("br2")}) Eventually(func() error { @@ -240,7 +240,7 @@ var _ = Describe("[rfe_id:3503][crit:medium][vendor:cnv-qe@redhat.com][level:com Context("and trying to create a VM after a MAC address has just been released due to a VM deletion", func() { It("[test_id:2165]should re-use the released MAC address for the creation of the new VM and not return an error", func() { var err error - vm1 := CreateVmObject(TestNamespace, false, []kubevirtv1.Interface{newInterface("br1", ""), + vm1 := CreateVmObject(TestNamespace, []kubevirtv1.Interface{newInterface("br1", ""), newInterface("br2", "")}, []kubevirtv1.Network{newNetwork("br1"), newNetwork("br2")}) vm1, err = testClient.VirtClient.VirtualMachine(vm1.Namespace).Create(context.TODO(), vm1) @@ -250,14 +250,14 @@ var _ = Describe("[rfe_id:3503][crit:medium][vendor:cnv-qe@redhat.com][level:com mac2, err := net.ParseMAC(vm1.Spec.Template.Spec.Domain.Devices.Interfaces[1].MacAddress) Expect(err).ToNot(HaveOccurred(), "Should succeed parsing vm1's second mac") - vm2 := CreateVmObject(TestNamespace, false, []kubevirtv1.Interface{newInterface("br3", "")}, + vm2 := CreateVmObject(TestNamespace, []kubevirtv1.Interface{newInterface("br3", "")}, []kubevirtv1.Network{newNetwork("br3")}) vm2, err = testClient.VirtClient.VirtualMachine(vm2.Namespace).Create(context.TODO(), vm2) Expect(err).ToNot(HaveOccurred(), "Should succeed creating vm2") Expect(net.ParseMAC(vm2.Spec.Template.Spec.Domain.Devices.Interfaces[0].MacAddress)).ToNot(BeEmpty(), "Should successfully parse vm2's mac address") - newVM1 := CreateVmObject(TestNamespace, false, []kubevirtv1.Interface{newInterface("br1", vm1.Spec.Template.Spec.Domain.Devices.Interfaces[0].MacAddress), + newVM1 := CreateVmObject(TestNamespace, []kubevirtv1.Interface{newInterface("br1", vm1.Spec.Template.Spec.Domain.Devices.Interfaces[0].MacAddress), newInterface("br2", vm1.Spec.Template.Spec.Domain.Devices.Interfaces[1].MacAddress)}, []kubevirtv1.Network{newNetwork("br1"), newNetwork("br2")}) deleteVMI(vm1) @@ -277,7 +277,7 @@ var _ = Describe("[rfe_id:3503][crit:medium][vendor:cnv-qe@redhat.com][level:com Context("and mac-pool is full", func() { It("should re-use the released MAC address for the creation of the new VM and not return an error, using automatic mac allocation of the mac left on the pool", func() { var err error - vm1 := CreateVmObject(TestNamespace, false, []kubevirtv1.Interface{newInterface("br1", ""), + vm1 := CreateVmObject(TestNamespace, []kubevirtv1.Interface{newInterface("br1", ""), newInterface("br2", "")}, []kubevirtv1.Network{newNetwork("br1"), newNetwork("br2")}) vm1, err = testClient.VirtClient.VirtualMachine(vm1.Namespace).Create(context.TODO(), vm1) @@ -287,7 +287,7 @@ var _ = Describe("[rfe_id:3503][crit:medium][vendor:cnv-qe@redhat.com][level:com mac2, err := net.ParseMAC(vm1.Spec.Template.Spec.Domain.Devices.Interfaces[1].MacAddress) Expect(err).ToNot(HaveOccurred(), "Should succeed parsing vm1's second mac") - vm2 := CreateVmObject(TestNamespace, false, []kubevirtv1.Interface{newInterface("br3", "")}, + vm2 := CreateVmObject(TestNamespace, []kubevirtv1.Interface{newInterface("br3", "")}, []kubevirtv1.Network{newNetwork("br3")}) vm2, err = testClient.VirtClient.VirtualMachine(vm2.Namespace).Create(context.TODO(), vm2) @@ -299,7 +299,7 @@ var _ = Describe("[rfe_id:3503][crit:medium][vendor:cnv-qe@redhat.com][level:com deleteVMI(vm1) - newVM1 := CreateVmObject(TestNamespace, false, []kubevirtv1.Interface{newInterface("br1", ""), + newVM1 := CreateVmObject(TestNamespace, []kubevirtv1.Interface{newInterface("br1", ""), newInterface("br2", "")}, []kubevirtv1.Network{newNetwork("br1"), newNetwork("br2")}) Eventually(func() error { _, err = testClient.VirtClient.VirtualMachine(newVM1.Namespace).Create(context.TODO(), newVM1) @@ -320,7 +320,7 @@ var _ = Describe("[rfe_id:3503][crit:medium][vendor:cnv-qe@redhat.com][level:com Context("and when restarting kubeMacPool and trying to create a VM with the same manually configured MAC as an older VM", func() { It("[test_id:2179]should return an error because the MAC address is taken by the older VM", func() { var err error - vm1 := CreateVmObject(TestNamespace, false, []kubevirtv1.Interface{newInterface("br1", "02:00:ff:ff:ff:ff")}, []kubevirtv1.Network{newNetwork("br1")}) + vm1 := CreateVmObject(TestNamespace, []kubevirtv1.Interface{newInterface("br1", "02:00:ff:ff:ff:ff")}, []kubevirtv1.Network{newNetwork("br1")}) vm1, err = testClient.VirtClient.VirtualMachine(vm1.Namespace).Create(context.TODO(), vm1) Expect(err).ToNot(HaveOccurred()) @@ -330,7 +330,7 @@ var _ = Describe("[rfe_id:3503][crit:medium][vendor:cnv-qe@redhat.com][level:com err = initKubemacpoolParams() Expect(err).ToNot(HaveOccurred()) - vm2 := CreateVmObject(TestNamespace, false, []kubevirtv1.Interface{newInterface("br2", "02:00:ff:ff:ff:ff")}, + vm2 := CreateVmObject(TestNamespace, []kubevirtv1.Interface{newInterface("br2", "02:00:ff:ff:ff:ff")}, []kubevirtv1.Network{newNetwork("br2")}) Eventually(func() error { @@ -352,7 +352,7 @@ var _ = Describe("[rfe_id:3503][crit:medium][vendor:cnv-qe@redhat.com][level:com networks[i] = newNetwork("br" + strconv.Itoa(i)) } - vm1 := CreateVmObject(TestNamespace, false, intrefaces, networks) + vm1 := CreateVmObject(TestNamespace, intrefaces, networks) updateObject := vm1.DeepCopy() var err error @@ -382,7 +382,7 @@ var _ = Describe("[rfe_id:3503][crit:medium][vendor:cnv-qe@redhat.com][level:com Context("and we re-apply a failed VM yaml", func() { It("[test_id:2633]should allow to assign to the VM the same MAC addresses, with name as requested before and do not return an error", func() { var err error - vm1 := CreateVmObject(TestNamespace, false, + vm1 := CreateVmObject(TestNamespace, []kubevirtv1.Interface{newInterface("br1", "02:00:ff:ff:ff:ff")}, []kubevirtv1.Network{newNetwork("br1"), newNetwork("br2")}) @@ -404,7 +404,7 @@ var _ = Describe("[rfe_id:3503][crit:medium][vendor:cnv-qe@redhat.com][level:com }) It("should allow to assign to the VM the same MAC addresses, different name as requested before and do not return an error", func() { var err error - vm1 := CreateVmObject(TestNamespace, false, + vm1 := CreateVmObject(TestNamespace, []kubevirtv1.Interface{newInterface("br1", "02:00:ff:ff:ff:ff")}, []kubevirtv1.Network{newNetwork("br1"), newNetwork("br2")}) @@ -437,7 +437,7 @@ var _ = Describe("[rfe_id:3503][crit:medium][vendor:cnv-qe@redhat.com][level:com interfaces = append(interfaces, newInterface("br"+strconv.Itoa(numOfIfaces), fmt.Sprintf("02:00:00:00:00:%02X", numOfIfaces))) networks = append(networks, newNetwork("br"+strconv.Itoa(numOfIfaces))) } - vm = CreateVmObject(TestNamespace, false, []kubevirtv1.Interface{}, []kubevirtv1.Network{}) + vm = CreateVmObject(TestNamespace, []kubevirtv1.Interface{}, []kubevirtv1.Network{}) By("Creating the vm with 0 interfaces") vm, err = testClient.VirtClient.VirtualMachine(vm.Namespace).Create(context.TODO(), vm) Expect(err).ToNot(HaveOccurred(), "Should succeed creating the vm") @@ -472,7 +472,7 @@ var _ = Describe("[rfe_id:3503][crit:medium][vendor:cnv-qe@redhat.com][level:com for ifaceIdx := 0; ifaceIdx < maxNumOfIfaces; ifaceIdx++ { Eventually(func() error { var err error - newVm := CreateVmObject(TestNamespace, false, []kubevirtv1.Interface{interfaces[ifaceIdx]}, []kubevirtv1.Network{networks[ifaceIdx]}) + newVm := CreateVmObject(TestNamespace, []kubevirtv1.Interface{interfaces[ifaceIdx]}, []kubevirtv1.Network{networks[ifaceIdx]}) newVm, err = testClient.VirtClient.VirtualMachine(newVm.Namespace).Create(context.TODO(), newVm) if err != nil { @@ -511,7 +511,7 @@ var _ = Describe("[rfe_id:3503][crit:medium][vendor:cnv-qe@redhat.com][level:com It("should not be able to allocate the occupied macs to new vms", func() { By(fmt.Sprintf("Creating %d vms, each with a MAC interface used in the base vm", maxNumOfIfaces)) for ifaceIdx := 0; ifaceIdx < maxNumOfIfaces; ifaceIdx++ { - newVm := CreateVmObject(TestNamespace, false, []kubevirtv1.Interface{interfaces[ifaceIdx]}, []kubevirtv1.Network{networks[ifaceIdx]}) + newVm := CreateVmObject(TestNamespace, []kubevirtv1.Interface{interfaces[ifaceIdx]}, []kubevirtv1.Network{networks[ifaceIdx]}) _, err = testClient.VirtClient.VirtualMachine(newVm.Namespace).Create(context.TODO(), newVm) Expect(err).To(HaveOccurred(), "Should fail creating the vm") } @@ -524,7 +524,7 @@ var _ = Describe("[rfe_id:3503][crit:medium][vendor:cnv-qe@redhat.com][level:com BeforeEach(func() { var err error By("Creating a vm with no NICs") - vm = CreateVmObject(TestNamespace, false, []kubevirtv1.Interface{}, []kubevirtv1.Network{}) + vm = CreateVmObject(TestNamespace, []kubevirtv1.Interface{}, []kubevirtv1.Network{}) vm, err = testClient.VirtClient.VirtualMachine(vm.Namespace).Create(context.TODO(), vm) Expect(err).ToNot(HaveOccurred(), "Should succeed creating the vm") @@ -559,7 +559,7 @@ var _ = Describe("[rfe_id:3503][crit:medium][vendor:cnv-qe@redhat.com][level:com By("trying to reuse the mac in a new vm") var err error - newVM := CreateVmObject(TestNamespace, false, []kubevirtv1.Interface{newInterface("br1", reusedMacAddress)}, + newVM := CreateVmObject(TestNamespace, []kubevirtv1.Interface{newInterface("br1", reusedMacAddress)}, []kubevirtv1.Network{newNetwork("br1")}) newVM, err = testClient.VirtClient.VirtualMachine(newVM.Namespace).Create(context.TODO(), newVM) Expect(err).Should(MatchError("admission webhook \"mutatevirtualmachines.kubemacpool.io\" denied the request: Failed to create virtual machine allocation error: Failed to allocate mac to the vm object: failed to allocate requested mac address"), "Should fail to allocate vm because the mac is already used") @@ -568,7 +568,7 @@ var _ = Describe("[rfe_id:3503][crit:medium][vendor:cnv-qe@redhat.com][level:com Context("and a VM's NIC is removed and a new VM is created with the same MAC", func() { It("[test_id:2995]should successfully release the MAC and the new VM should be created with no errors", func() { var err error - vm := CreateVmObject(TestNamespace, false, []kubevirtv1.Interface{newInterface("br1", ""), newInterface("br2", "")}, + vm := CreateVmObject(TestNamespace, []kubevirtv1.Interface{newInterface("br1", ""), newInterface("br2", "")}, []kubevirtv1.Network{newNetwork("br1"), newNetwork("br2")}) vm, err = testClient.VirtClient.VirtualMachine(vm.Namespace).Create(context.TODO(), vm) Expect(err).ToNot(HaveOccurred(), "Should succeed creating the vm") @@ -578,7 +578,7 @@ var _ = Describe("[rfe_id:3503][crit:medium][vendor:cnv-qe@redhat.com][level:com reusedMacAddress := vm.Spec.Template.Spec.Domain.Devices.Interfaces[0].MacAddress By("checking that a new VM cannot be created when the mac is already occupied") - newVM := CreateVmObject(TestNamespace, false, []kubevirtv1.Interface{newInterface("br1", reusedMacAddress)}, + newVM := CreateVmObject(TestNamespace, []kubevirtv1.Interface{newInterface("br1", reusedMacAddress)}, []kubevirtv1.Network{newNetwork("br1")}) _, err = testClient.VirtClient.VirtualMachine(newVM.Namespace).Create(context.TODO(), newVM) Expect(err).Should(MatchError("admission webhook \"mutatevirtualmachines.kubemacpool.io\" denied the request: Failed to create virtual machine allocation error: Failed to allocate mac to the vm object: failed to allocate requested mac address"), "Should fail to allocate vm because the mac is already used") @@ -617,7 +617,7 @@ var _ = Describe("[rfe_id:3503][crit:medium][vendor:cnv-qe@redhat.com][level:com Context("and mac-pool is full", func() { It("should successfully release the MAC and the new VM should be created with no errors with the only mac left allocated to it", func() { var err error - vm := CreateVmObject(TestNamespace, false, []kubevirtv1.Interface{newInterface("br1", ""), newInterface("br2", "")}, + vm := CreateVmObject(TestNamespace, []kubevirtv1.Interface{newInterface("br1", ""), newInterface("br2", "")}, []kubevirtv1.Network{newNetwork("br1"), newNetwork("br2")}) vm, err = testClient.VirtClient.VirtualMachine(vm.Namespace).Create(context.TODO(), vm) Expect(err).ToNot(HaveOccurred(), "Should succeed creating the vm") @@ -628,7 +628,7 @@ var _ = Describe("[rfe_id:3503][crit:medium][vendor:cnv-qe@redhat.com][level:com Expect(err).ToNot(HaveOccurred(), "Should succeed allocating all the mac pool") By("checking that a new VM cannot be created when the range is full") - newVM := CreateVmObject(TestNamespace, false, []kubevirtv1.Interface{newInterface("br1", "")}, + newVM := CreateVmObject(TestNamespace, []kubevirtv1.Interface{newInterface("br1", "")}, []kubevirtv1.Network{newNetwork("br1")}) _, err = testClient.VirtClient.VirtualMachine(newVM.Namespace).Create(context.TODO(), newVM) Expect(err).To(HaveOccurred(), "Should fail to allocate vm because there are no free mac addresses") @@ -692,7 +692,7 @@ var _ = Describe("[rfe_id:3503][crit:medium][vendor:cnv-qe@redhat.com][level:com }) It("Should remove the vm from cache", func() { var err error - vm := CreateVmObject(TestNamespace, false, + vm := CreateVmObject(TestNamespace, []kubevirtv1.Interface{newInterface("br1", allocatedMacAddress)}, []kubevirtv1.Network{newNetwork("br1")}) By("checking that the mac is occupied by trying to allocate it in a new vm") @@ -701,7 +701,7 @@ var _ = Describe("[rfe_id:3503][crit:medium][vendor:cnv-qe@redhat.com][level:com Expect(err).To(HaveOccurred(), "should fail creating a vm with the now occupied mac address") By("checking that the mac is released by trying to allocate it in a new vm") - vm1 := CreateVmObject(TestNamespace, false, + vm1 := CreateVmObject(TestNamespace, []kubevirtv1.Interface{newInterface("br1", allocatedMacAddress)}, []kubevirtv1.Network{newNetwork("br1")}) Eventually(func() error { @@ -714,7 +714,7 @@ var _ = Describe("[rfe_id:3503][crit:medium][vendor:cnv-qe@redhat.com][level:com Context("When a vm was successfully created in a version that uses the legacy configMap", func() { BeforeEach(func() { var err error - vm := CreateVmObject(TestNamespace, false, + vm := CreateVmObject(TestNamespace, []kubevirtv1.Interface{newInterface("br1", allocatedMacAddress)}, []kubevirtv1.Network{newNetwork("br1")}) By("simulating a vm created on version using legacy configMap") @@ -734,7 +734,7 @@ var _ = Describe("[rfe_id:3503][crit:medium][vendor:cnv-qe@redhat.com][level:com }) It("Should remove the vm from cache", func() { By("checking that the mac is occupied and not removed as stale by trying to allocate it in a new vm") - vm1 := CreateVmObject(TestNamespace, false, + vm1 := CreateVmObject(TestNamespace, []kubevirtv1.Interface{newInterface("br1", allocatedMacAddress)}, []kubevirtv1.Network{newNetwork("br1")}) Consistently(func() error { @@ -769,14 +769,14 @@ var _ = Describe("[rfe_id:3503][crit:medium][vendor:cnv-qe@redhat.com][level:com BeforeEach(func() { By("Adding a vm with no preset mac") var err error - notManagedVm1 = CreateVmObject(notManagedNamespace, false, []kubevirtv1.Interface{newInterface("br", "")}, + notManagedVm1 = CreateVmObject(notManagedNamespace, []kubevirtv1.Interface{newInterface("br", "")}, []kubevirtv1.Network{newNetwork("br")}) notManagedVm1, err = testClient.VirtClient.VirtualMachine(notManagedVm1.Namespace).Create(context.TODO(), notManagedVm1) Expect(err).ToNot(HaveOccurred(), "Should succeed creating the vm") By("Adding a vm with a preset mac") preSetMac = "02:00:ff:ff:ff:ff" - notManagedVm2 = CreateVmObject(notManagedNamespace, false, []kubevirtv1.Interface{newInterface("br", preSetMac)}, + notManagedVm2 = CreateVmObject(notManagedNamespace, []kubevirtv1.Interface{newInterface("br", preSetMac)}, []kubevirtv1.Network{newNetwork("br")}) notManagedVm2, err = testClient.VirtClient.VirtualMachine(notManagedVm2.Namespace).Create(context.TODO(), notManagedVm2) Expect(err).ToNot(HaveOccurred(), "Should succeed creating the vm") @@ -792,7 +792,7 @@ var _ = Describe("[rfe_id:3503][crit:medium][vendor:cnv-qe@redhat.com][level:com Expect(err).ToNot(HaveOccurred(), "should be able to add the namespace labels") By("creating a vm in the opted-in namespace") - managedVm := CreateVmObject(managedNamespace, false, []kubevirtv1.Interface{newInterface("br", "")}, + managedVm := CreateVmObject(managedNamespace, []kubevirtv1.Interface{newInterface("br", "")}, []kubevirtv1.Network{newNetwork("br")}) managedVm, err = testClient.VirtClient.VirtualMachine(managedVm.Namespace).Create(context.TODO(), managedVm) Expect(err).ToNot(HaveOccurred(), "Should succeed creating the vm") @@ -802,13 +802,13 @@ var _ = Describe("[rfe_id:3503][crit:medium][vendor:cnv-qe@redhat.com][level:com Expect(net.ParseMAC(allocatedMac)).ToNot(BeEmpty(), "Should successfully parse mac address") }) It("should reject a new opted-in VM object with the occupied MAC assigned", func() { - anotherManagedVm := CreateVmObject(managedNamespace, false, []kubevirtv1.Interface{newInterface("br", allocatedMac)}, + anotherManagedVm := CreateVmObject(managedNamespace, []kubevirtv1.Interface{newInterface("br", allocatedMac)}, []kubevirtv1.Network{newNetwork("br")}) _, err := testClient.VirtClient.VirtualMachine(anotherManagedVm.Namespace).Create(context.TODO(), anotherManagedVm) Expect(err).To(HaveOccurred(), "Should reject a new vm with occupied mac address") }) It("should not reject a new opted-in VM object with unmanaged preset MAC", func() { - anotherManagedVm := CreateVmObject(managedNamespace, false, []kubevirtv1.Interface{newInterface("br", preSetMac)}, + anotherManagedVm := CreateVmObject(managedNamespace, []kubevirtv1.Interface{newInterface("br", preSetMac)}, []kubevirtv1.Network{newNetwork("br")}) _, err := testClient.VirtClient.VirtualMachine(anotherManagedVm.Namespace).Create(context.TODO(), anotherManagedVm) Expect(err).ToNot(HaveOccurred(), "Should not reject a new vm if the mac is occupied on a non-opted-in namespace") @@ -822,13 +822,13 @@ var _ = Describe("[rfe_id:3503][crit:medium][vendor:cnv-qe@redhat.com][level:com }) It("should still reject a new opted-in VM object with the occupied MAC assigned", func() { - anotherManagedVm := CreateVmObject(managedNamespace, false, []kubevirtv1.Interface{newInterface("br", allocatedMac)}, + anotherManagedVm := CreateVmObject(managedNamespace, []kubevirtv1.Interface{newInterface("br", allocatedMac)}, []kubevirtv1.Network{newNetwork("br")}) _, err := testClient.VirtClient.VirtualMachine(anotherManagedVm.Namespace).Create(context.TODO(), anotherManagedVm) Expect(err).To(HaveOccurred(), "Should reject a new vm with occupied mac address") }) It("should still not reject a new opted-in VM object with unmanaged preset MAC", func() { - anotherManagedVm := CreateVmObject(managedNamespace, false, []kubevirtv1.Interface{newInterface("br", preSetMac)}, + anotherManagedVm := CreateVmObject(managedNamespace, []kubevirtv1.Interface{newInterface("br", preSetMac)}, []kubevirtv1.Network{newNetwork("br")}) _, err := testClient.VirtClient.VirtualMachine(anotherManagedVm.Namespace).Create(context.TODO(), anotherManagedVm) Expect(err).ToNot(HaveOccurred(), "Should not reject a new vm if the mac is occupied on a non-opted-in namespce") @@ -854,7 +854,7 @@ var _ = Describe("[rfe_id:3503][crit:medium][vendor:cnv-qe@redhat.com][level:com }) It("should create a VM object without a MAC assigned", func() { var err error - vm := CreateVmObject(TestNamespace, false, []kubevirtv1.Interface{newInterface("br", "")}, + vm := CreateVmObject(TestNamespace, []kubevirtv1.Interface{newInterface("br", "")}, []kubevirtv1.Network{newNetwork("br")}) vm, err = testClient.VirtClient.VirtualMachine(vm.Namespace).Create(context.TODO(), vm) @@ -867,7 +867,7 @@ var _ = Describe("[rfe_id:3503][crit:medium][vendor:cnv-qe@redhat.com][level:com var vm *kubevirtv1.VirtualMachine var allocatedMac string BeforeEach(func() { - vm = CreateVmObject(TestNamespace, false, []kubevirtv1.Interface{newInterface("br", "")}, + vm = CreateVmObject(TestNamespace, []kubevirtv1.Interface{newInterface("br", "")}, []kubevirtv1.Network{newNetwork("br")}) By("Create VM") @@ -885,7 +885,7 @@ var _ = Describe("[rfe_id:3503][crit:medium][vendor:cnv-qe@redhat.com][level:com Expect(net.ParseMAC(allocatedMac)).ToNot(BeEmpty(), "Should successfully parse mac address") }) It("should reject a new VM object with the occupied MAC assigned", func() { - vm = CreateVmObject(TestNamespace, false, []kubevirtv1.Interface{newInterface("br", allocatedMac)}, + vm = CreateVmObject(TestNamespace, []kubevirtv1.Interface{newInterface("br", allocatedMac)}, []kubevirtv1.Network{newNetwork("br")}) _, err := testClient.VirtClient.VirtualMachine(vm.Namespace).Create(context.TODO(), vm) Expect(err).To(HaveOccurred(), "Should reject a new vm with occupied mac address") @@ -917,7 +917,7 @@ var _ = Describe("[rfe_id:3503][crit:medium][vendor:cnv-qe@redhat.com][level:com Context("and trying to create a VM and mac-pool is full", func() { It("should return an error because no MAC address is available", func() { var err error - vm := CreateVmObject(TestNamespace, false, []kubevirtv1.Interface{newInterface("br1", ""), + vm := CreateVmObject(TestNamespace, []kubevirtv1.Interface{newInterface("br1", ""), newInterface("br2", "")}, []kubevirtv1.Network{newNetwork("br1"), newNetwork("br2")}) vm, err = testClient.VirtClient.VirtualMachine(vm.Namespace).Create(context.TODO(), vm) @@ -929,7 +929,7 @@ var _ = Describe("[rfe_id:3503][crit:medium][vendor:cnv-qe@redhat.com][level:com Expect(err).ToNot(HaveOccurred(), "Should succeed allocating all the mac pool") By("Trying to allocate a vm after there is no more macs to allocate") - starvingVM := CreateVmObject(TestNamespace, false, []kubevirtv1.Interface{newInterface("br", "")}, + starvingVM := CreateVmObject(TestNamespace, []kubevirtv1.Interface{newInterface("br", "")}, []kubevirtv1.Network{newNetwork("br")}) _, err = testClient.VirtClient.VirtualMachine(starvingVM.Namespace).Create(context.TODO(), starvingVM) @@ -941,7 +941,7 @@ var _ = Describe("[rfe_id:3503][crit:medium][vendor:cnv-qe@redhat.com][level:com var vm *kubevirtv1.VirtualMachine BeforeEach(func() { var err error - vm = CreateVmObject(TestNamespace, false, []kubevirtv1.Interface{newInterface("br", "")}, + vm = CreateVmObject(TestNamespace, []kubevirtv1.Interface{newInterface("br", "")}, []kubevirtv1.Network{newNetwork("br")}) vm, err = testClient.VirtClient.VirtualMachine(vm.Namespace).Create(context.TODO(), vm) Expect(err).ToNot(HaveOccurred()) @@ -973,7 +973,7 @@ var _ = Describe("[rfe_id:3503][crit:medium][vendor:cnv-qe@redhat.com][level:com macAddress := "02:00:ff:ff:ff:ff" By(fmt.Sprintf("Adding a vm with a Mac Address %s in the managed namespace", macAddress)) - vm1 := CreateVmObject(TestNamespace, false, []kubevirtv1.Interface{newInterface("br1", macAddress)}, []kubevirtv1.Network{newNetwork("br1")}) + vm1 := CreateVmObject(TestNamespace, []kubevirtv1.Interface{newInterface("br1", macAddress)}, []kubevirtv1.Network{newNetwork("br1")}) vm1, err = testClient.VirtClient.VirtualMachine(vm1.Namespace).Create(context.TODO(), vm1) Expect(err).ToNot(HaveOccurred()) Expect(net.ParseMAC(vm1.Spec.Template.Spec.Domain.Devices.Interfaces[0].MacAddress)).ToNot(BeEmpty(), "Should successfully parse mac address") @@ -982,7 +982,7 @@ var _ = Describe("[rfe_id:3503][crit:medium][vendor:cnv-qe@redhat.com][level:com Expect(err).ToNot(HaveOccurred(), "should be able to add the namespace labels") By(fmt.Sprintf("Adding a vm with the same Mac Address %s on the unmanaged namespace", macAddress)) - conflictingVM = CreateVmObject(OtherTestNamespace, false, []kubevirtv1.Interface{newInterface("br1", macAddress)}, []kubevirtv1.Network{newNetwork("br1")}) + conflictingVM = CreateVmObject(OtherTestNamespace, []kubevirtv1.Interface{newInterface("br1", macAddress)}, []kubevirtv1.Network{newNetwork("br1")}) conflictingVM, err = testClient.VirtClient.VirtualMachine(conflictingVM.Namespace).Create(context.TODO(), conflictingVM) Expect(err).ToNot(HaveOccurred()) Expect(net.ParseMAC(conflictingVM.Spec.Template.Spec.Domain.Devices.Interfaces[0].MacAddress)).ToNot(BeEmpty(), "Should successfully parse mac address") @@ -1063,7 +1063,7 @@ func AllocateFillerVms(macsToLeaveFree int64) error { var i int64 for i = 0; i < maxPoolSize-macsToLeaveFree; i++ { var err error - vm := CreateVmObject(TestNamespace, false, []kubevirtv1.Interface{newInterface("br", "")}, + vm := CreateVmObject(TestNamespace, []kubevirtv1.Interface{newInterface("br", "")}, []kubevirtv1.Network{newNetwork("br")}) vm.Name = fmt.Sprintf("vm-filler-%d", i) vm, err = testClient.VirtClient.VirtualMachine(vm.Namespace).Create(context.TODO(), vm) diff --git a/vendor/k8s.io/utils/clock/testing/fake_clock.go b/vendor/k8s.io/utils/clock/testing/fake_clock.go index 79e11deb6..462c40c2c 100644 --- a/vendor/k8s.io/utils/clock/testing/fake_clock.go +++ b/vendor/k8s.io/utils/clock/testing/fake_clock.go @@ -48,7 +48,6 @@ type fakeClockWaiter struct { stepInterval time.Duration skipIfBlocked bool destChan chan time.Time - fired bool afterFunc func() } @@ -198,12 +197,10 @@ func (f *FakeClock) setTimeLocked(t time.Time) { if w.skipIfBlocked { select { case w.destChan <- t: - w.fired = true default: } } else { w.destChan <- t - w.fired = true } if w.afterFunc != nil { @@ -305,44 +302,48 @@ func (f *fakeTimer) C() <-chan time.Time { return f.waiter.destChan } -// Stop stops the timer and returns true if the timer has not yet fired, or false otherwise. +// Stop prevents the Timer from firing. It returns true if the call stops the +// timer, false if the timer has already expired or been stopped. func (f *fakeTimer) Stop() bool { f.fakeClock.lock.Lock() defer f.fakeClock.lock.Unlock() + active := false newWaiters := make([]*fakeClockWaiter, 0, len(f.fakeClock.waiters)) for i := range f.fakeClock.waiters { w := f.fakeClock.waiters[i] if w != &f.waiter { newWaiters = append(newWaiters, w) + continue } + // If timer is found, it has not been fired yet. + active = true } f.fakeClock.waiters = newWaiters - return !f.waiter.fired + return active } -// Reset resets the timer to the fake clock's "now" + d. It returns true if the timer has not yet -// fired, or false otherwise. +// Reset changes the timer to expire after duration d. It returns true if the +// timer had been active, false if the timer had expired or been stopped. func (f *fakeTimer) Reset(d time.Duration) bool { f.fakeClock.lock.Lock() defer f.fakeClock.lock.Unlock() - active := !f.waiter.fired + active := false - f.waiter.fired = false f.waiter.targetTime = f.fakeClock.time.Add(d) - var isWaiting bool for i := range f.fakeClock.waiters { w := f.fakeClock.waiters[i] if w == &f.waiter { - isWaiting = true + // If timer is found, it has not been fired yet. + active = true break } } - if !isWaiting { + if !active { f.fakeClock.waiters = append(f.fakeClock.waiters, &f.waiter) } diff --git a/vendor/k8s.io/utils/integer/integer.go b/vendor/k8s.io/utils/integer/integer.go index e4e740cad..f64d64955 100644 --- a/vendor/k8s.io/utils/integer/integer.go +++ b/vendor/k8s.io/utils/integer/integer.go @@ -16,7 +16,10 @@ limitations under the License. package integer -// IntMax returns the maximum of the params +import "math" + +// IntMax returns the maximum of the params. +// Deprecated: for new code, use the max() builtin instead. func IntMax(a, b int) int { if b > a { return b @@ -24,7 +27,8 @@ func IntMax(a, b int) int { return a } -// IntMin returns the minimum of the params +// IntMin returns the minimum of the params. +// Deprecated: for new code, use the min() builtin instead. func IntMin(a, b int) int { if b < a { return b @@ -32,7 +36,8 @@ func IntMin(a, b int) int { return a } -// Int32Max returns the maximum of the params +// Int32Max returns the maximum of the params. +// Deprecated: for new code, use the max() builtin instead. func Int32Max(a, b int32) int32 { if b > a { return b @@ -40,7 +45,8 @@ func Int32Max(a, b int32) int32 { return a } -// Int32Min returns the minimum of the params +// Int32Min returns the minimum of the params. +// Deprecated: for new code, use the min() builtin instead. func Int32Min(a, b int32) int32 { if b < a { return b @@ -48,7 +54,8 @@ func Int32Min(a, b int32) int32 { return a } -// Int64Max returns the maximum of the params +// Int64Max returns the maximum of the params. +// Deprecated: for new code, use the max() builtin instead. func Int64Max(a, b int64) int64 { if b > a { return b @@ -56,7 +63,8 @@ func Int64Max(a, b int64) int64 { return a } -// Int64Min returns the minimum of the params +// Int64Min returns the minimum of the params. +// Deprecated: for new code, use the min() builtin instead. func Int64Min(a, b int64) int64 { if b < a { return b @@ -65,9 +73,7 @@ func Int64Min(a, b int64) int64 { } // RoundToInt32 rounds floats into integer numbers. +// Deprecated: use math.Round() and a cast directly. func RoundToInt32(a float64) int32 { - if a < 0 { - return int32(a - 0.5) - } - return int32(a + 0.5) + return int32(math.Round(a)) } diff --git a/vendor/k8s.io/utils/net/multi_listen.go b/vendor/k8s.io/utils/net/multi_listen.go new file mode 100644 index 000000000..7cb7795be --- /dev/null +++ b/vendor/k8s.io/utils/net/multi_listen.go @@ -0,0 +1,195 @@ +/* +Copyright 2024 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package net + +import ( + "context" + "fmt" + "net" + "sync" +) + +// connErrPair pairs conn and error which is returned by accept on sub-listeners. +type connErrPair struct { + conn net.Conn + err error +} + +// multiListener implements net.Listener +type multiListener struct { + listeners []net.Listener + wg sync.WaitGroup + + // connCh passes accepted connections, from child listeners to parent. + connCh chan connErrPair + // stopCh communicates from parent to child listeners. + stopCh chan struct{} +} + +// compile time check to ensure *multiListener implements net.Listener +var _ net.Listener = &multiListener{} + +// MultiListen returns net.Listener which can listen on and accept connections for +// the given network on multiple addresses. Internally it uses stdlib to create +// sub-listener and multiplexes connection requests using go-routines. +// The network must be "tcp", "tcp4" or "tcp6". +// It follows the semantics of net.Listen that primarily means: +// 1. If the host is an unspecified/zero IP address with "tcp" network, MultiListen +// listens on all available unicast and anycast IP addresses of the local system. +// 2. Use "tcp4" or "tcp6" to exclusively listen on IPv4 or IPv6 family, respectively. +// 3. The host can accept names (e.g, localhost) and it will create a listener for at +// most one of the host's IP. +func MultiListen(ctx context.Context, network string, addrs ...string) (net.Listener, error) { + var lc net.ListenConfig + return multiListen( + ctx, + network, + addrs, + func(ctx context.Context, network, address string) (net.Listener, error) { + return lc.Listen(ctx, network, address) + }) +} + +// multiListen implements MultiListen by consuming stdlib functions as dependency allowing +// mocking for unit-testing. +func multiListen( + ctx context.Context, + network string, + addrs []string, + listenFunc func(ctx context.Context, network, address string) (net.Listener, error), +) (net.Listener, error) { + if !(network == "tcp" || network == "tcp4" || network == "tcp6") { + return nil, fmt.Errorf("network %q not supported", network) + } + if len(addrs) == 0 { + return nil, fmt.Errorf("no address provided to listen on") + } + + ml := &multiListener{ + connCh: make(chan connErrPair), + stopCh: make(chan struct{}), + } + for _, addr := range addrs { + l, err := listenFunc(ctx, network, addr) + if err != nil { + // close all the sub-listeners and exit + _ = ml.Close() + return nil, err + } + ml.listeners = append(ml.listeners, l) + } + + for _, l := range ml.listeners { + ml.wg.Add(1) + go func(l net.Listener) { + defer ml.wg.Done() + for { + // Accept() is blocking, unless ml.Close() is called, in which + // case it will return immediately with an error. + conn, err := l.Accept() + // This assumes that ANY error from Accept() will terminate the + // sub-listener. We could maybe be more precise, but it + // doesn't seem necessary. + terminate := err != nil + + select { + case ml.connCh <- connErrPair{conn: conn, err: err}: + case <-ml.stopCh: + // In case we accepted a connection AND were stopped, and + // this select-case was chosen, just throw away the + // connection. This avoids potentially blocking on connCh + // or leaking a connection. + if conn != nil { + _ = conn.Close() + } + terminate = true + } + // Make sure we don't loop on Accept() returning an error and + // the select choosing the channel case. + if terminate { + return + } + } + }(l) + } + return ml, nil +} + +// Accept implements net.Listener. It waits for and returns a connection from +// any of the sub-listener. +func (ml *multiListener) Accept() (net.Conn, error) { + // wait for any sub-listener to enqueue an accepted connection + connErr, ok := <-ml.connCh + if !ok { + // The channel will be closed only when Close() is called on the + // multiListener. Closing of this channel implies that all + // sub-listeners are also closed, which causes a "use of closed + // network connection" error on their Accept() calls. We return the + // same error for multiListener.Accept() if multiListener.Close() + // has already been called. + return nil, fmt.Errorf("use of closed network connection") + } + return connErr.conn, connErr.err +} + +// Close implements net.Listener. It will close all sub-listeners and wait for +// the go-routines to exit. +func (ml *multiListener) Close() error { + // Make sure this can be called repeatedly without explosions. + select { + case <-ml.stopCh: + return fmt.Errorf("use of closed network connection") + default: + } + + // Tell all sub-listeners to stop. + close(ml.stopCh) + + // Closing the listeners causes Accept() to immediately return an error in + // the sub-listener go-routines. + for _, l := range ml.listeners { + _ = l.Close() + } + + // Wait for all the sub-listener go-routines to exit. + ml.wg.Wait() + close(ml.connCh) + + // Drain any already-queued connections. + for connErr := range ml.connCh { + if connErr.conn != nil { + _ = connErr.conn.Close() + } + } + return nil +} + +// Addr is an implementation of the net.Listener interface. It always returns +// the address of the first listener. Callers should use conn.LocalAddr() to +// obtain the actual local address of the sub-listener. +func (ml *multiListener) Addr() net.Addr { + return ml.listeners[0].Addr() +} + +// Addrs is like Addr, but returns the address for all registered listeners. +func (ml *multiListener) Addrs() []net.Addr { + var ret []net.Addr + for _, l := range ml.listeners { + ret = append(ret, l.Addr()) + } + return ret +} diff --git a/vendor/k8s.io/utils/pointer/pointer.go b/vendor/k8s.io/utils/pointer/pointer.go index b8103223a..b673a6425 100644 --- a/vendor/k8s.io/utils/pointer/pointer.go +++ b/vendor/k8s.io/utils/pointer/pointer.go @@ -14,12 +14,15 @@ See the License for the specific language governing permissions and limitations under the License. */ +// Deprecated: Use functions in k8s.io/utils/ptr instead: ptr.To to obtain +// a pointer, ptr.Deref to dereference a pointer, ptr.Equal to compare +// dereferenced pointers. package pointer import ( - "fmt" - "reflect" "time" + + "k8s.io/utils/ptr" ) // AllPtrFieldsNil tests whether all pointer fields in a struct are nil. This is useful when, @@ -28,383 +31,219 @@ import ( // // This function is only valid for structs and pointers to structs. Any other // type will cause a panic. Passing a typed nil pointer will return true. -func AllPtrFieldsNil(obj interface{}) bool { - v := reflect.ValueOf(obj) - if !v.IsValid() { - panic(fmt.Sprintf("reflect.ValueOf() produced a non-valid Value for %#v", obj)) - } - if v.Kind() == reflect.Ptr { - if v.IsNil() { - return true - } - v = v.Elem() - } - for i := 0; i < v.NumField(); i++ { - if v.Field(i).Kind() == reflect.Ptr && !v.Field(i).IsNil() { - return false - } - } - return true -} - -// Int returns a pointer to an int -func Int(i int) *int { - return &i -} +// +// Deprecated: Use ptr.AllPtrFieldsNil instead. +var AllPtrFieldsNil = ptr.AllPtrFieldsNil + +// Int returns a pointer to an int. +var Int = ptr.To[int] // IntPtr is a function variable referring to Int. // -// Deprecated: Use Int instead. +// Deprecated: Use ptr.To instead. var IntPtr = Int // for back-compat // IntDeref dereferences the int ptr and returns it if not nil, or else // returns def. -func IntDeref(ptr *int, def int) int { - if ptr != nil { - return *ptr - } - return def -} +var IntDeref = ptr.Deref[int] // IntPtrDerefOr is a function variable referring to IntDeref. // -// Deprecated: Use IntDeref instead. +// Deprecated: Use ptr.Deref instead. var IntPtrDerefOr = IntDeref // for back-compat // Int32 returns a pointer to an int32. -func Int32(i int32) *int32 { - return &i -} +var Int32 = ptr.To[int32] // Int32Ptr is a function variable referring to Int32. // -// Deprecated: Use Int32 instead. +// Deprecated: Use ptr.To instead. var Int32Ptr = Int32 // for back-compat // Int32Deref dereferences the int32 ptr and returns it if not nil, or else // returns def. -func Int32Deref(ptr *int32, def int32) int32 { - if ptr != nil { - return *ptr - } - return def -} +var Int32Deref = ptr.Deref[int32] // Int32PtrDerefOr is a function variable referring to Int32Deref. // -// Deprecated: Use Int32Deref instead. +// Deprecated: Use ptr.Deref instead. var Int32PtrDerefOr = Int32Deref // for back-compat // Int32Equal returns true if both arguments are nil or both arguments // dereference to the same value. -func Int32Equal(a, b *int32) bool { - if (a == nil) != (b == nil) { - return false - } - if a == nil { - return true - } - return *a == *b -} +var Int32Equal = ptr.Equal[int32] // Uint returns a pointer to an uint -func Uint(i uint) *uint { - return &i -} +var Uint = ptr.To[uint] // UintPtr is a function variable referring to Uint. // -// Deprecated: Use Uint instead. +// Deprecated: Use ptr.To instead. var UintPtr = Uint // for back-compat // UintDeref dereferences the uint ptr and returns it if not nil, or else // returns def. -func UintDeref(ptr *uint, def uint) uint { - if ptr != nil { - return *ptr - } - return def -} +var UintDeref = ptr.Deref[uint] // UintPtrDerefOr is a function variable referring to UintDeref. // -// Deprecated: Use UintDeref instead. +// Deprecated: Use ptr.Deref instead. var UintPtrDerefOr = UintDeref // for back-compat // Uint32 returns a pointer to an uint32. -func Uint32(i uint32) *uint32 { - return &i -} +var Uint32 = ptr.To[uint32] // Uint32Ptr is a function variable referring to Uint32. // -// Deprecated: Use Uint32 instead. +// Deprecated: Use ptr.To instead. var Uint32Ptr = Uint32 // for back-compat // Uint32Deref dereferences the uint32 ptr and returns it if not nil, or else // returns def. -func Uint32Deref(ptr *uint32, def uint32) uint32 { - if ptr != nil { - return *ptr - } - return def -} +var Uint32Deref = ptr.Deref[uint32] // Uint32PtrDerefOr is a function variable referring to Uint32Deref. // -// Deprecated: Use Uint32Deref instead. +// Deprecated: Use ptr.Deref instead. var Uint32PtrDerefOr = Uint32Deref // for back-compat // Uint32Equal returns true if both arguments are nil or both arguments // dereference to the same value. -func Uint32Equal(a, b *uint32) bool { - if (a == nil) != (b == nil) { - return false - } - if a == nil { - return true - } - return *a == *b -} +var Uint32Equal = ptr.Equal[uint32] // Int64 returns a pointer to an int64. -func Int64(i int64) *int64 { - return &i -} +var Int64 = ptr.To[int64] // Int64Ptr is a function variable referring to Int64. // -// Deprecated: Use Int64 instead. +// Deprecated: Use ptr.To instead. var Int64Ptr = Int64 // for back-compat // Int64Deref dereferences the int64 ptr and returns it if not nil, or else // returns def. -func Int64Deref(ptr *int64, def int64) int64 { - if ptr != nil { - return *ptr - } - return def -} +var Int64Deref = ptr.Deref[int64] // Int64PtrDerefOr is a function variable referring to Int64Deref. // -// Deprecated: Use Int64Deref instead. +// Deprecated: Use ptr.Deref instead. var Int64PtrDerefOr = Int64Deref // for back-compat // Int64Equal returns true if both arguments are nil or both arguments // dereference to the same value. -func Int64Equal(a, b *int64) bool { - if (a == nil) != (b == nil) { - return false - } - if a == nil { - return true - } - return *a == *b -} +var Int64Equal = ptr.Equal[int64] // Uint64 returns a pointer to an uint64. -func Uint64(i uint64) *uint64 { - return &i -} +var Uint64 = ptr.To[uint64] // Uint64Ptr is a function variable referring to Uint64. // -// Deprecated: Use Uint64 instead. +// Deprecated: Use ptr.To instead. var Uint64Ptr = Uint64 // for back-compat // Uint64Deref dereferences the uint64 ptr and returns it if not nil, or else // returns def. -func Uint64Deref(ptr *uint64, def uint64) uint64 { - if ptr != nil { - return *ptr - } - return def -} +var Uint64Deref = ptr.Deref[uint64] // Uint64PtrDerefOr is a function variable referring to Uint64Deref. // -// Deprecated: Use Uint64Deref instead. +// Deprecated: Use ptr.Deref instead. var Uint64PtrDerefOr = Uint64Deref // for back-compat // Uint64Equal returns true if both arguments are nil or both arguments // dereference to the same value. -func Uint64Equal(a, b *uint64) bool { - if (a == nil) != (b == nil) { - return false - } - if a == nil { - return true - } - return *a == *b -} +var Uint64Equal = ptr.Equal[uint64] // Bool returns a pointer to a bool. -func Bool(b bool) *bool { - return &b -} +var Bool = ptr.To[bool] // BoolPtr is a function variable referring to Bool. // -// Deprecated: Use Bool instead. +// Deprecated: Use ptr.To instead. var BoolPtr = Bool // for back-compat // BoolDeref dereferences the bool ptr and returns it if not nil, or else // returns def. -func BoolDeref(ptr *bool, def bool) bool { - if ptr != nil { - return *ptr - } - return def -} +var BoolDeref = ptr.Deref[bool] // BoolPtrDerefOr is a function variable referring to BoolDeref. // -// Deprecated: Use BoolDeref instead. +// Deprecated: Use ptr.Deref instead. var BoolPtrDerefOr = BoolDeref // for back-compat // BoolEqual returns true if both arguments are nil or both arguments // dereference to the same value. -func BoolEqual(a, b *bool) bool { - if (a == nil) != (b == nil) { - return false - } - if a == nil { - return true - } - return *a == *b -} +var BoolEqual = ptr.Equal[bool] // String returns a pointer to a string. -func String(s string) *string { - return &s -} +var String = ptr.To[string] // StringPtr is a function variable referring to String. // -// Deprecated: Use String instead. +// Deprecated: Use ptr.To instead. var StringPtr = String // for back-compat // StringDeref dereferences the string ptr and returns it if not nil, or else // returns def. -func StringDeref(ptr *string, def string) string { - if ptr != nil { - return *ptr - } - return def -} +var StringDeref = ptr.Deref[string] // StringPtrDerefOr is a function variable referring to StringDeref. // -// Deprecated: Use StringDeref instead. +// Deprecated: Use ptr.Deref instead. var StringPtrDerefOr = StringDeref // for back-compat // StringEqual returns true if both arguments are nil or both arguments // dereference to the same value. -func StringEqual(a, b *string) bool { - if (a == nil) != (b == nil) { - return false - } - if a == nil { - return true - } - return *a == *b -} +var StringEqual = ptr.Equal[string] // Float32 returns a pointer to a float32. -func Float32(i float32) *float32 { - return &i -} +var Float32 = ptr.To[float32] // Float32Ptr is a function variable referring to Float32. // -// Deprecated: Use Float32 instead. +// Deprecated: Use ptr.To instead. var Float32Ptr = Float32 // Float32Deref dereferences the float32 ptr and returns it if not nil, or else // returns def. -func Float32Deref(ptr *float32, def float32) float32 { - if ptr != nil { - return *ptr - } - return def -} +var Float32Deref = ptr.Deref[float32] // Float32PtrDerefOr is a function variable referring to Float32Deref. // -// Deprecated: Use Float32Deref instead. +// Deprecated: Use ptr.Deref instead. var Float32PtrDerefOr = Float32Deref // for back-compat // Float32Equal returns true if both arguments are nil or both arguments // dereference to the same value. -func Float32Equal(a, b *float32) bool { - if (a == nil) != (b == nil) { - return false - } - if a == nil { - return true - } - return *a == *b -} +var Float32Equal = ptr.Equal[float32] // Float64 returns a pointer to a float64. -func Float64(i float64) *float64 { - return &i -} +var Float64 = ptr.To[float64] // Float64Ptr is a function variable referring to Float64. // -// Deprecated: Use Float64 instead. +// Deprecated: Use ptr.To instead. var Float64Ptr = Float64 // Float64Deref dereferences the float64 ptr and returns it if not nil, or else // returns def. -func Float64Deref(ptr *float64, def float64) float64 { - if ptr != nil { - return *ptr - } - return def -} +var Float64Deref = ptr.Deref[float64] // Float64PtrDerefOr is a function variable referring to Float64Deref. // -// Deprecated: Use Float64Deref instead. +// Deprecated: Use ptr.Deref instead. var Float64PtrDerefOr = Float64Deref // for back-compat // Float64Equal returns true if both arguments are nil or both arguments // dereference to the same value. -func Float64Equal(a, b *float64) bool { - if (a == nil) != (b == nil) { - return false - } - if a == nil { - return true - } - return *a == *b -} +var Float64Equal = ptr.Equal[float64] // Duration returns a pointer to a time.Duration. -func Duration(d time.Duration) *time.Duration { - return &d -} +var Duration = ptr.To[time.Duration] // DurationDeref dereferences the time.Duration ptr and returns it if not nil, or else // returns def. -func DurationDeref(ptr *time.Duration, def time.Duration) time.Duration { - if ptr != nil { - return *ptr - } - return def -} +var DurationDeref = ptr.Deref[time.Duration] // DurationEqual returns true if both arguments are nil or both arguments // dereference to the same value. -func DurationEqual(a, b *time.Duration) bool { - if (a == nil) != (b == nil) { - return false - } - if a == nil { - return true - } - return *a == *b -} +var DurationEqual = ptr.Equal[time.Duration] diff --git a/vendor/k8s.io/utils/ptr/OWNERS b/vendor/k8s.io/utils/ptr/OWNERS new file mode 100644 index 000000000..0d6392752 --- /dev/null +++ b/vendor/k8s.io/utils/ptr/OWNERS @@ -0,0 +1,10 @@ +# See the OWNERS docs at https://go.k8s.io/owners + +approvers: +- apelisse +- stewart-yu +- thockin +reviewers: +- apelisse +- stewart-yu +- thockin diff --git a/vendor/k8s.io/utils/ptr/README.md b/vendor/k8s.io/utils/ptr/README.md new file mode 100644 index 000000000..2ca8073dc --- /dev/null +++ b/vendor/k8s.io/utils/ptr/README.md @@ -0,0 +1,3 @@ +# Pointer + +This package provides some functions for pointer-based operations. diff --git a/vendor/k8s.io/utils/ptr/ptr.go b/vendor/k8s.io/utils/ptr/ptr.go new file mode 100644 index 000000000..659ed3b9e --- /dev/null +++ b/vendor/k8s.io/utils/ptr/ptr.go @@ -0,0 +1,73 @@ +/* +Copyright 2023 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package ptr + +import ( + "fmt" + "reflect" +) + +// AllPtrFieldsNil tests whether all pointer fields in a struct are nil. This is useful when, +// for example, an API struct is handled by plugins which need to distinguish +// "no plugin accepted this spec" from "this spec is empty". +// +// This function is only valid for structs and pointers to structs. Any other +// type will cause a panic. Passing a typed nil pointer will return true. +func AllPtrFieldsNil(obj interface{}) bool { + v := reflect.ValueOf(obj) + if !v.IsValid() { + panic(fmt.Sprintf("reflect.ValueOf() produced a non-valid Value for %#v", obj)) + } + if v.Kind() == reflect.Ptr { + if v.IsNil() { + return true + } + v = v.Elem() + } + for i := 0; i < v.NumField(); i++ { + if v.Field(i).Kind() == reflect.Ptr && !v.Field(i).IsNil() { + return false + } + } + return true +} + +// To returns a pointer to the given value. +func To[T any](v T) *T { + return &v +} + +// Deref dereferences ptr and returns the value it points to if no nil, or else +// returns def. +func Deref[T any](ptr *T, def T) T { + if ptr != nil { + return *ptr + } + return def +} + +// Equal returns true if both arguments are nil or both arguments +// dereference to the same value. +func Equal[T comparable](a, b *T) bool { + if (a == nil) != (b == nil) { + return false + } + if a == nil { + return true + } + return *a == *b +} diff --git a/vendor/k8s.io/utils/trace/trace.go b/vendor/k8s.io/utils/trace/trace.go index 187eb5d8c..559aebb59 100644 --- a/vendor/k8s.io/utils/trace/trace.go +++ b/vendor/k8s.io/utils/trace/trace.go @@ -192,7 +192,7 @@ func (t *Trace) Log() { t.endTime = &endTime t.lock.Unlock() // an explicit logging request should dump all the steps out at the higher level - if t.parentTrace == nil { // We don't start logging until Log or LogIfLong is called on the root trace + if t.parentTrace == nil && klogV(2) { // We don't start logging until Log or LogIfLong is called on the root trace t.logTrace() } } diff --git a/vendor/modules.txt b/vendor/modules.txt index 3f4f6f8d5..827d451d9 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -623,7 +623,7 @@ k8s.io/kube-openapi/pkg/schemamutation k8s.io/kube-openapi/pkg/spec3 k8s.io/kube-openapi/pkg/util/proto k8s.io/kube-openapi/pkg/validation/spec -# k8s.io/utils v0.0.0-20230505201702-9f6742963106 +# k8s.io/utils v0.0.0-20241210054802-24370beab758 ## explicit; go 1.18 k8s.io/utils/buffer k8s.io/utils/clock @@ -632,6 +632,7 @@ k8s.io/utils/integer k8s.io/utils/internal/third_party/forked/golang/net k8s.io/utils/net k8s.io/utils/pointer +k8s.io/utils/ptr k8s.io/utils/strings/slices k8s.io/utils/trace # kubevirt.io/api v1.0.0