From 319b2693c39798101c29a646d1a3296053e25c34 Mon Sep 17 00:00:00 2001 From: Quan Tian Date: Thu, 14 Dec 2023 11:54:03 +0800 Subject: [PATCH] Fix unit test TestReconcile cniServer.reconcile() now installs flows asynchorously. Signed-off-by: Quan Tian --- .../interface_configuration_linux_test.go | 2 +- .../cniserver/pod_configuration_linux_test.go | 20 +-- pkg/agent/cniserver/server_linux_test.go | 105 +++---------- pkg/agent/cniserver/server_test.go | 97 ++++++++++-- pkg/agent/cniserver/server_windows_test.go | 147 +++++------------- pkg/util/ip/ip.go | 8 + 6 files changed, 165 insertions(+), 214 deletions(-) diff --git a/pkg/agent/cniserver/interface_configuration_linux_test.go b/pkg/agent/cniserver/interface_configuration_linux_test.go index 2723ac67741..fb24bb5b81e 100644 --- a/pkg/agent/cniserver/interface_configuration_linux_test.go +++ b/pkg/agent/cniserver/interface_configuration_linux_test.go @@ -127,7 +127,7 @@ func (ns *fakeNS) clear() { } func createNS(t *testing.T, waitForComplete bool) *fakeNS { - nsPath := generateUUID(t) + nsPath := generateUUID() fakeNs := &fakeNS{path: nsPath, fd: uintptr(unsafe.Pointer(&nsPath)), waitCompleted: waitForComplete, stopCh: make(chan struct{})} validNSs.Store(nsPath, fakeNs) return fakeNs diff --git a/pkg/agent/cniserver/pod_configuration_linux_test.go b/pkg/agent/cniserver/pod_configuration_linux_test.go index 62e65069fc8..67b5440088a 100644 --- a/pkg/agent/cniserver/pod_configuration_linux_test.go +++ b/pkg/agent/cniserver/pod_configuration_linux_test.go @@ -136,7 +136,7 @@ func TestConnectInterceptedInterface(t *testing.T) { testPodName := "test-pod" podNamespace := testPodNamespace hostInterfaceName := util.GenerateContainerInterfaceName(testPodName, testPodNamespace, testPodInfraContainerID) - containerID := generateUUID(t) + containerID := generateUUID() containerNetNS := "container-ns" containerDev := "eth0" @@ -210,7 +210,7 @@ func TestConnectInterceptedInterface(t *testing.T) { if tc.migratedRoute { mockRoute.EXPECT().MigrateRoutesToGw(hostInterfaceName).Return(tc.migrateRouteErr) } - ovsPortID := generateUUID(t) + ovsPortID := generateUUID() if tc.connectedOVS { mockOVSBridgeClient.EXPECT().CreatePort(hostInterfaceName, gomock.Any(), gomock.Any()).Return(ovsPortID, tc.createOVSPortErr).Times(1) if tc.createOVSPortErr == nil { @@ -239,7 +239,7 @@ func TestConnectInterceptedInterface(t *testing.T) { func TestCreateOVSPort(t *testing.T) { controller := gomock.NewController(t) - containerID := generateUUID(t) + containerID := generateUUID() podName := "p0" podNamespace := testPodNamespace @@ -271,10 +271,10 @@ func TestCreateOVSPort(t *testing.T) { containerConfig := buildContainerConfig(tc.portName, containerID, podName, podNamespace, ¤t.Interface{Mac: "01:02:03:04:05:06"}, ipamResult.IPs, tc.vlanID) attachInfo := BuildOVSPortExternalIDs(containerConfig) if tc.createOVSPort { - mockOVSBridgeClient.EXPECT().CreatePort(tc.portName, tc.portName, attachInfo).Times(1).Return(generateUUID(t), nil) + mockOVSBridgeClient.EXPECT().CreatePort(tc.portName, tc.portName, attachInfo).Times(1).Return(generateUUID(), nil) } if tc.createOVSAccessPort { - mockOVSBridgeClient.EXPECT().CreateAccessPort(tc.portName, tc.portName, attachInfo, tc.vlanID).Times(1).Return(generateUUID(t), nil) + mockOVSBridgeClient.EXPECT().CreateAccessPort(tc.portName, tc.portName, attachInfo, tc.vlanID).Times(1).Return(generateUUID(), nil) } _, err := podConfigurator.createOVSPort(tc.portName, attachInfo, tc.vlanID) assert.NoError(t, err) @@ -283,8 +283,8 @@ func TestCreateOVSPort(t *testing.T) { } func TestParseOVSPortInterfaceConfig(t *testing.T) { - containerID := generateUUID(t) - portUUID := generateUUID(t) + containerID := generateUUID() + portUUID := generateUUID() ofPort := int32(1) containerIPs := "1.1.1.2,aabb:1122::101:102" parsedIPs := []net.IP{net.ParseIP("1.1.1.2"), net.ParseIP("aabb:1122::101:102")} @@ -398,14 +398,14 @@ func TestParseOVSPortInterfaceConfig(t *testing.T) { func TestCheckHostInterface(t *testing.T) { controller := gomock.NewController(t) hostIfaceName := "port1" - containerID := generateUUID(t) + containerID := generateUUID() containerIntf := ¤t.Interface{Name: ifname, Sandbox: netns, Mac: "01:02:03:04:05:06"} interfaces := []*current.Interface{containerIntf, {Name: hostIfaceName}} containeIPs := ipamResult.IPs ifaceMAC, _ := net.ParseMAC("01:02:03:04:05:06") containerInterface := interfacestore.NewContainerInterface(hostIfaceName, containerID, "pod1", testPodNamespace, ifaceMAC, []net.IP{containerIP}, 1) containerInterface.OVSPortConfig = &interfacestore.OVSPortConfig{ - PortUUID: generateUUID(t), + PortUUID: generateUUID(), OFPort: int32(10), } @@ -454,7 +454,7 @@ func TestCheckHostInterface(t *testing.T) { func TestConfigureSriovSecondaryInterface(t *testing.T) { controller := gomock.NewController(t) - containerID := generateUUID(t) + containerID := generateUUID() containerNS := "containerNS" for _, tc := range []struct { diff --git a/pkg/agent/cniserver/server_linux_test.go b/pkg/agent/cniserver/server_linux_test.go index 261116fafe9..52791d129b8 100644 --- a/pkg/agent/cniserver/server_linux_test.go +++ b/pkg/agent/cniserver/server_linux_test.go @@ -20,6 +20,7 @@ import ( "fmt" "net" "testing" + "time" cnitypes "github.com/containernetworking/cni/pkg/types" current "github.com/containernetworking/cni/pkg/types/100" @@ -27,9 +28,6 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "go.uber.org/mock/gomock" - v1 "k8s.io/api/core/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/runtime" fakeclientset "k8s.io/client-go/kubernetes/fake" "antrea.io/antrea/pkg/agent/cniserver/ipam" @@ -326,7 +324,7 @@ func TestCmdAdd(t *testing.T) { if tc.addLocalIPAMRoute { mockRoute.EXPECT().AddLocalAntreaFlexibleIPAMPodRule(gomock.Any()).Return(tc.addLocalIPAMRouteError).Times(1) } - ovsPortID := generateUUID(t) + ovsPortID := generateUUID() if tc.connectOVS { mockOVSBridgeClient.EXPECT().CreatePort(hostInterfaceName, gomock.Any(), gomock.Any()).Return(ovsPortID, nil).Times(1) mockOVSBridgeClient.EXPECT().GetOFPort(hostInterfaceName, false).Return(int32(100), nil).Times(1) @@ -366,7 +364,7 @@ func TestCmdAdd(t *testing.T) { } func TestCmdDel(t *testing.T) { - ovsPortID := generateUUID(t) + ovsPortID := generateUUID() ovsPort := int32(100) ctx := context.TODO() @@ -521,7 +519,7 @@ func TestCmdDel(t *testing.T) { func TestCmdCheck(t *testing.T) { controller := gomock.NewController(t) ipamMock := ipamtest.NewMockIPAMDriver(controller) - ovsPortID := generateUUID(t) + ovsPortID := generateUUID() ovsPort := int32(100) ctx := context.TODO() @@ -613,98 +611,33 @@ func TestReconcile(t *testing.T) { mockOFClient = openflowtest.NewMockClient(controller) ifaceStore = interfacestore.NewInterfaceStore() mockRoute = routetest.NewMockInterface(controller) - nodeName := "node1" cniServer := newCNIServer(t) cniServer.routeClient = mockRoute - gwMAC, _ := net.ParseMAC("00:00:11:11:11:11") cniServer.podConfigurator, _ = newPodConfigurator(mockOVSBridgeClient, mockOFClient, mockRoute, ifaceStore, gwMAC, "system", false, false, channel.NewSubscribableChannel("PodUpdate", 100)) cniServer.podConfigurator.ifConfigurator = newTestInterfaceConfigurator() cniServer.nodeConfig = &config.NodeConfig{ Name: nodeName, } - pods := []runtime.Object{ - &v1.Pod{ - ObjectMeta: metav1.ObjectMeta{ - Name: "p1", - Namespace: testPodNamespace, - }, - Spec: v1.PodSpec{ - NodeName: nodeName, - }, - }, - &v1.Pod{ - ObjectMeta: metav1.ObjectMeta{ - Name: "p2", - Namespace: testPodNamespace, - }, - Spec: v1.PodSpec{ - NodeName: nodeName, - HostNetwork: true, - }, - }, - &v1.Pod{ - ObjectMeta: metav1.ObjectMeta{ - Name: "p4", - Namespace: testPodNamespace, - }, - Spec: v1.PodSpec{ - NodeName: nodeName, - }, - }, - } - containerIfaces := map[string]*interfacestore.InterfaceConfig{ - "iface1": { - InterfaceName: "iface1", - Type: interfacestore.ContainerInterface, - OVSPortConfig: &interfacestore.OVSPortConfig{ - PortUUID: generateUUID(t), - OFPort: int32(3), - }, - ContainerInterfaceConfig: &interfacestore.ContainerInterfaceConfig{ - PodName: "p1", - PodNamespace: testPodNamespace, - ContainerID: generateUUID(t), - }, - }, - "iface3": { - InterfaceName: "iface3", - Type: interfacestore.ContainerInterface, - OVSPortConfig: &interfacestore.OVSPortConfig{ - PortUUID: generateUUID(t), - OFPort: int32(4), - }, - ContainerInterfaceConfig: &interfacestore.ContainerInterfaceConfig{ - PodName: "p3", - PodNamespace: testPodNamespace, - ContainerID: generateUUID(t), - }, - }, - "iface4": { - InterfaceName: "iface4", - Type: interfacestore.ContainerInterface, - OVSPortConfig: &interfacestore.OVSPortConfig{ - PortUUID: generateUUID(t), - OFPort: int32(-1), - }, - ContainerInterfaceConfig: &interfacestore.ContainerInterfaceConfig{ - PodName: "p4", - PodNamespace: testPodNamespace, - ContainerID: generateUUID(t), - }, - }, - } - kubeClient := fakeclientset.NewSimpleClientset(pods...) + kubeClient := fakeclientset.NewSimpleClientset(pod1, pod2, pod3) cniServer.kubeClient = kubeClient - for _, containerIface := range containerIfaces { + for _, containerIface := range []*interfacestore.InterfaceConfig{normalInterface, staleInterface, unconnectedInterface} { ifaceStore.AddInterface(containerIface) } - mockOFClient.EXPECT().InstallPodFlows("iface1", gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Times(1) - iface := containerIfaces["iface3"] - mockOFClient.EXPECT().UninstallPodFlows("iface3").Return(nil).Times(1) - mockOVSBridgeClient.EXPECT().DeletePort(iface.PortUUID).Return(nil).Times(1) + podFlowsInstalled := make(chan struct{}) + mockOFClient.EXPECT().InstallPodFlows(normalInterface.InterfaceName, normalInterface.IPs, normalInterface.MAC, uint32(normalInterface.OFPort), uint16(0), nil). + Do(func(_ string, _ []net.IP, _ net.HardwareAddr, _ uint32, _ uint16, _ *uint32) { + close(podFlowsInstalled) + }).Times(1) + mockOFClient.EXPECT().UninstallPodFlows(staleInterface.InterfaceName).Return(nil).Times(1) + mockOVSBridgeClient.EXPECT().DeletePort(staleInterface.PortUUID).Return(nil).Times(1) mockRoute.EXPECT().DeleteLocalAntreaFlexibleIPAMPodRule(gomock.Any()).Return(nil).Times(1) err := cniServer.reconcile() assert.NoError(t, err) - _, exists := ifaceStore.GetInterfaceByName("iface3") + _, exists := ifaceStore.GetInterfaceByName(staleInterface.InterfaceName) assert.False(t, exists) + select { + case <-podFlowsInstalled: + case <-time.After(500 * time.Millisecond): + t.Errorf("InstallPodFlows for %s should be called but was not", normalInterface.InterfaceName) + } } diff --git a/pkg/agent/cniserver/server_test.go b/pkg/agent/cniserver/server_test.go index c9267280147..f50e4f73a6c 100644 --- a/pkg/agent/cniserver/server_test.go +++ b/pkg/agent/cniserver/server_test.go @@ -23,13 +23,6 @@ import ( "strings" "testing" - cnitypes "github.com/containernetworking/cni/pkg/types" - current "github.com/containernetworking/cni/pkg/types/100" - "github.com/google/uuid" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - "go.uber.org/mock/gomock" - "antrea.io/antrea/pkg/agent/cniserver/ipam" ipamtest "antrea.io/antrea/pkg/agent/cniserver/ipam/testing" cniservertest "antrea.io/antrea/pkg/agent/cniserver/testing" @@ -43,7 +36,16 @@ import ( "antrea.io/antrea/pkg/cni" "antrea.io/antrea/pkg/ovs/ovsconfig" ovsconfigtest "antrea.io/antrea/pkg/ovs/ovsconfig/testing" + utilip "antrea.io/antrea/pkg/util/ip" "antrea.io/antrea/pkg/util/wait" + cnitypes "github.com/containernetworking/cni/pkg/types" + current "github.com/containernetworking/cni/pkg/types/100" + "github.com/google/uuid" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "go.uber.org/mock/gomock" + v1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) const ( @@ -76,6 +78,80 @@ var ( ifaceStore interfacestore.InterfaceStore emptyResponse = &cnipb.CniCmdResponse{CniResult: []byte("")} + + nodeName = "node1" + gwMAC = utilip.MustParseMAC("00:00:11:11:11:11") + pod1 = &v1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: "p1", + Namespace: testPodNamespace, + }, + Spec: v1.PodSpec{ + NodeName: nodeName, + }, + } + pod2 = &v1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: "p2", + Namespace: testPodNamespace, + }, + Spec: v1.PodSpec{ + NodeName: nodeName, + HostNetwork: true, + }, + } + pod3 = &v1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: "p3", + Namespace: testPodNamespace, + }, + Spec: v1.PodSpec{ + NodeName: nodeName, + }, + } + normalInterface = &interfacestore.InterfaceConfig{ + InterfaceName: "iface1", + Type: interfacestore.ContainerInterface, + IPs: []net.IP{net.ParseIP("1.1.1.1")}, + MAC: utilip.MustParseMAC("00:11:22:33:44:01"), + OVSPortConfig: &interfacestore.OVSPortConfig{ + PortUUID: generateUUID(), + OFPort: int32(3), + }, + ContainerInterfaceConfig: &interfacestore.ContainerInterfaceConfig{ + PodName: pod1.Name, + PodNamespace: testPodNamespace, + ContainerID: generateUUID(), + }, + } + staleInterface = &interfacestore.InterfaceConfig{ + InterfaceName: "iface3", + Type: interfacestore.ContainerInterface, + OVSPortConfig: &interfacestore.OVSPortConfig{ + PortUUID: generateUUID(), + OFPort: int32(4), + }, + ContainerInterfaceConfig: &interfacestore.ContainerInterfaceConfig{ + PodName: "non-existing-pod", + PodNamespace: testPodNamespace, + ContainerID: generateUUID(), + }, + } + unconnectedInterface = &interfacestore.InterfaceConfig{ + InterfaceName: "iface4", + Type: interfacestore.ContainerInterface, + IPs: []net.IP{net.ParseIP("1.1.1.2")}, + MAC: utilip.MustParseMAC("00:11:22:33:44:02"), + OVSPortConfig: &interfacestore.OVSPortConfig{ + PortUUID: generateUUID(), + OFPort: int32(-1), + }, + ContainerInterfaceConfig: &interfacestore.ContainerInterfaceConfig{ + PodName: pod3.Name, + PodNamespace: testPodNamespace, + ContainerID: generateUUID(), + }, + } ) func TestLoadNetConfig(t *testing.T) { @@ -712,11 +788,8 @@ func newRequest(args string, netCfg *types.NetworkConfig, path string, t *testin return cmdRequest, containerID } -func generateUUID(t *testing.T) string { - newID, err := uuid.NewUUID() - if err != nil { - t.Fatal("Failed to generate UUID") - } +func generateUUID() string { + newID, _ := uuid.NewUUID() return newID.String() } diff --git a/pkg/agent/cniserver/server_windows_test.go b/pkg/agent/cniserver/server_windows_test.go index 0a2d69399ca..600adb5bf8e 100644 --- a/pkg/agent/cniserver/server_windows_test.go +++ b/pkg/agent/cniserver/server_windows_test.go @@ -28,9 +28,6 @@ import ( current "github.com/containernetworking/cni/pkg/types/100" "github.com/stretchr/testify/assert" "go.uber.org/mock/gomock" - v1 "k8s.io/api/core/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/util/wait" fakeclientset "k8s.io/client-go/kubernetes/fake" @@ -326,8 +323,8 @@ func TestCmdAdd(t *testing.T) { dockerInfraContainer := "261a1970-5b6c-11ed-8caf-000c294e5d03" dockerWorkContainer := "261e579a-5b6c-11ed-8caf-000c294e5d03" - unknownInfraContainer := generateUUID(t) - containerdInfraContainer := generateUUID(t) + unknownInfraContainer := generateUUID() + containerdInfraContainer := generateUUID() defer mockHostInterfaceExists()() defer mockGetHnsNetworkByName()() @@ -450,7 +447,7 @@ func TestCmdAdd(t *testing.T) { podName: "pod8", containerID: containerdInfraContainer, infraContainerID: containerdInfraContainer, - netns: generateUUID(t), + netns: generateUUID(), ipamAdd: true, connectOVS: true, containerIfaceExist: true, @@ -459,7 +456,7 @@ func TestCmdAdd(t *testing.T) { podName: "pod9", containerID: containerdInfraContainer, infraContainerID: containerdInfraContainer, - netns: generateUUID(t), + netns: generateUUID(), oriIPAMResult: oriIPAMResult, connectOVS: true, containerIfaceExist: true, @@ -469,7 +466,7 @@ func TestCmdAdd(t *testing.T) { podName: "pod10", containerID: containerdInfraContainer, infraContainerID: containerdInfraContainer, - netns: generateUUID(t), + netns: generateUUID(), ipamDel: true, oriIPAMResult: oriIPAMResult, endpointAttachErr: fmt.Errorf("unable to attach HnsEndpoint"), @@ -483,14 +480,14 @@ func TestCmdAdd(t *testing.T) { } { t.Run(tc.name, func(t *testing.T) { isDocker := isDockerContainer(tc.netns) - testUtil := newHnsTestUtil(generateUUID(t), tc.existingHnsEndpoints, isDocker, tc.isAttached, tc.hnsEndpointCreateErr, tc.endpointAttachErr) + testUtil := newHnsTestUtil(generateUUID(), tc.existingHnsEndpoints, isDocker, tc.isAttached, tc.hnsEndpointCreateErr, tc.endpointAttachErr) testUtil.setFunctions() defer testUtil.restore() waiter := newAsyncWaiter(tc.podName, tc.infraContainerID) server := newMockCNIServer(t, controller, waiter.notifier) requestMsg, ovsPortName := prepareSetup(t, ipamType, tc.podName, tc.containerID, tc.infraContainerID, tc.netns, nil) if tc.endpointExists { - server.podConfigurator.ifConfigurator.(*ifConfigurator).addEndpoint(getHnsEndpoint(generateUUID(t), ovsPortName)) + server.podConfigurator.ifConfigurator.(*ifConfigurator).addEndpoint(getHnsEndpoint(generateUUID(), ovsPortName)) } if tc.oriIPAMResult != nil { ipam.AddIPAMResult(tc.infraContainerID, tc.oriIPAMResult) @@ -501,7 +498,7 @@ func TestCmdAdd(t *testing.T) { if tc.ipamDel { ipamMock.EXPECT().Del(gomock.Any(), gomock.Any(), gomock.Any()).Return(true, nil).Times(1) } - ovsPortID := generateUUID(t) + ovsPortID := generateUUID() if tc.connectOVS { if isDocker { mockOVSBridgeClient.EXPECT().CreateInternalPort(ovsPortName, int32(0), gomock.Any(), gomock.Any()).Return(ovsPortID, nil).Times(1) @@ -612,7 +609,7 @@ func TestCmdDel(t *testing.T) { t.Run(tc.name, func(t *testing.T) { isDocker := isDockerContainer(tc.netns) requestMsg, ovsPortName := prepareSetup(t, ipamType, testPodNameA, containerID, containerID, tc.netns, nil) - hnsEndpoint := getHnsEndpoint(generateUUID(t), ovsPortName) + hnsEndpoint := getHnsEndpoint(generateUUID(), ovsPortName) var existingHnsEndpoints []hcsshim.HNSEndpoint if tc.endpointExists { existingHnsEndpoints = append(existingHnsEndpoints, *hnsEndpoint) @@ -622,7 +619,7 @@ func TestCmdDel(t *testing.T) { defer testUtil.restore() waiter := newAsyncWaiter(testPodNameA, containerID) server := newMockCNIServer(t, controller, waiter.notifier) - ovsPortID := generateUUID(t) + ovsPortID := generateUUID() if tc.endpointExists { server.podConfigurator.ifConfigurator.(*ifConfigurator).addEndpoint(hnsEndpoint) } @@ -680,7 +677,7 @@ func TestCmdCheck(t *testing.T) { defer mockSetInterfaceMTU(nil)() defer mockListHnsEndpoint(nil, nil)() defer mockGetNetInterfaceAddrs(containerIPNet, nil)() - defer mockGetHnsEndpointByName(generateUUID(t), mac)() + defer mockGetHnsEndpointByName(generateUUID(), mac)() wrapperIPAMResult := func(ipamResult current.Result, interfaces []*current.Interface) *current.Result { result := ipamResult @@ -718,7 +715,7 @@ func TestCmdCheck(t *testing.T) { {Name: "pod0-6631b7", Mac: "11:22:33:44:33:22", Sandbox: ""}, {Name: "pod0-6631b7_eth0", Mac: "11:22:33:44:33:22", Sandbox: "none"}, }), - existingIface: wrapperContainerInterface("pod0-6631b7", containerID, "pod0", generateUUID(t), mac, containerIP), + existingIface: wrapperContainerInterface("pod0-6631b7", containerID, "pod0", generateUUID(), mac, containerIP), netInterface: &net.Interface{ Name: "vEthernet (pod0-6631b7)", HardwareAddr: mac, @@ -734,7 +731,7 @@ func TestCmdCheck(t *testing.T) { {Name: "pod1-6631b7", Mac: "11:22:33:44:33:22", Sandbox: ""}, {Name: "pod1-6631b7_eth0", Mac: "11:22:33:44:33:22", Sandbox: "invalid-namespace"}, }), - existingIface: wrapperContainerInterface("pod1-6631b7", containerID, "pod1", generateUUID(t), mac, containerIP), + existingIface: wrapperContainerInterface("pod1-6631b7", containerID, "pod1", generateUUID(), mac, containerIP), netInterface: &net.Interface{ Name: "vEthernet (pod1-6631b7)", HardwareAddr: mac, @@ -756,7 +753,7 @@ func TestCmdCheck(t *testing.T) { {Name: "pod2-6631b7", Mac: "11:22:33:44:33:22", Sandbox: ""}, {Name: "eth0", Mac: "11:22:33:44:33:22", Sandbox: "none"}, }), - existingIface: wrapperContainerInterface("pod2-6631b7", containerID, "pod2", generateUUID(t), mac, containerIP), + existingIface: wrapperContainerInterface("pod2-6631b7", containerID, "pod2", generateUUID(), mac, containerIP), netInterface: &net.Interface{ Name: "vEthernet (pod2-6631b7)", HardwareAddr: mac, @@ -778,7 +775,7 @@ func TestCmdCheck(t *testing.T) { {Name: "pod3-6631b7", Mac: "11:22:33:44:33:22", Sandbox: ""}, {Name: "pod3-6631b7_eth0", Mac: "11:22:33:44:33:33", Sandbox: "none"}, }), - existingIface: wrapperContainerInterface("pod3-6631b7", containerID, "pod3", generateUUID(t), mac, containerIP), + existingIface: wrapperContainerInterface("pod3-6631b7", containerID, "pod3", generateUUID(), mac, containerIP), netInterface: &net.Interface{ Name: "vEthernet (pod3-6631b7)", HardwareAddr: mac, @@ -853,10 +850,10 @@ func TestReconcile(t *testing.T) { mockOFClient = openflowtest.NewMockClient(controller) ifaceStore = interfacestore.NewInterfaceStore() mockRoute = routetest.NewMockInterface(controller) - nodeName := "node1" + defer mockHostInterfaceExists()() defer mockGetHnsNetworkByName()() - missingEndpoint := getHnsEndpoint(generateUUID(t), "iface4") + missingEndpoint := getHnsEndpoint(generateUUID(), "iface4") testUtil := newHnsTestUtil(missingEndpoint.Id, []hcsshim.HNSEndpoint{*missingEndpoint}, false, true, nil, nil) testUtil.createHnsEndpoint(missingEndpoint) testUtil.setFunctions() @@ -864,105 +861,45 @@ func TestReconcile(t *testing.T) { cniServer := newCNIServer(t) cniServer.routeClient = mockRoute - gwMAC, _ := net.ParseMAC("00:00:11:11:11:11") - pods := []runtime.Object{ - &v1.Pod{ - ObjectMeta: metav1.ObjectMeta{ - Name: "p1", - Namespace: testPodNamespace, - }, - Spec: v1.PodSpec{ - NodeName: nodeName, - }, - }, - &v1.Pod{ - ObjectMeta: metav1.ObjectMeta{ - Name: "p2", - Namespace: testPodNamespace, - }, - Spec: v1.PodSpec{ - NodeName: nodeName, - HostNetwork: true, - }, - }, - &v1.Pod{ - ObjectMeta: metav1.ObjectMeta{ - Name: "p4", - Namespace: testPodNamespace, - }, - Spec: v1.PodSpec{ - NodeName: nodeName, - }, - }, - } - kubeClient := fakeclientset.NewSimpleClientset(pods...) + kubeClient := fakeclientset.NewSimpleClientset(pod1, pod2, pod3) cniServer.kubeClient = kubeClient - containerIfaces := map[string]*interfacestore.InterfaceConfig{ - "iface1": { - InterfaceName: "iface1", - Type: interfacestore.ContainerInterface, - OVSPortConfig: &interfacestore.OVSPortConfig{ - PortUUID: generateUUID(t), - OFPort: int32(3), - }, - ContainerInterfaceConfig: &interfacestore.ContainerInterfaceConfig{ - PodName: "p1", - PodNamespace: testPodNamespace, - ContainerID: generateUUID(t), - }, - }, - "iface3": { - InterfaceName: "iface3", - Type: interfacestore.ContainerInterface, - OVSPortConfig: &interfacestore.OVSPortConfig{ - PortUUID: generateUUID(t), - OFPort: int32(4), - }, - ContainerInterfaceConfig: &interfacestore.ContainerInterfaceConfig{ - PodName: "p3", - PodNamespace: testPodNamespace, - ContainerID: generateUUID(t), - }, - }, - "iface4": { - InterfaceName: "iface4", - Type: interfacestore.ContainerInterface, - OVSPortConfig: &interfacestore.OVSPortConfig{ - PortUUID: generateUUID(t), - OFPort: int32(-1), - }, - ContainerInterfaceConfig: &interfacestore.ContainerInterfaceConfig{ - PodName: "p4", - PodNamespace: testPodNamespace, - ContainerID: generateUUID(t), - }, - }, - } - for _, containerIface := range containerIfaces { + for _, containerIface := range []*interfacestore.InterfaceConfig{normalInterface, staleInterface, unconnectedInterface} { ifaceStore.AddInterface(containerIface) } - pod4IfaceName := "iface4" - pod4Iface := containerIfaces["iface4"] - waiter := newAsyncWaiter(pod4Iface.PodName, pod4Iface.ContainerID) + waiter := newAsyncWaiter(unconnectedInterface.PodName, unconnectedInterface.ContainerID) cniServer.podConfigurator, _ = newPodConfigurator(mockOVSBridgeClient, mockOFClient, mockRoute, ifaceStore, gwMAC, "system", false, false, waiter.notifier) cniServer.nodeConfig = &config.NodeConfig{Name: nodeName} // Re-install Pod1 flows - mockOFClient.EXPECT().InstallPodFlows("iface1", gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Times(1) + podFlowsInstalled := make(chan string, 2) + mockOFClient.EXPECT().InstallPodFlows(normalInterface.InterfaceName, normalInterface.IPs, normalInterface.MAC, uint32(normalInterface.OFPort), uint16(0), nil). + Do(func(interfaceName string, _ []net.IP, _ net.HardwareAddr, _ uint32, _ uint16, _ *uint32) { + podFlowsInstalled <- interfaceName + }).Times(1) // Uninstall Pod3 flows which is deleted. - iface := containerIfaces["iface3"] - mockOFClient.EXPECT().UninstallPodFlows("iface3").Return(nil).Times(1) - mockOVSBridgeClient.EXPECT().DeletePort(iface.PortUUID).Return(nil).Times(1) + mockOFClient.EXPECT().UninstallPodFlows(staleInterface.InterfaceName).Return(nil).Times(1) + mockOVSBridgeClient.EXPECT().DeletePort(staleInterface.PortUUID).Return(nil).Times(1) mockRoute.EXPECT().DeleteLocalAntreaFlexibleIPAMPodRule(gomock.Any()).Return(nil).Times(1) // Re-connect to Pod4 - hostIfaces.Store(fmt.Sprintf("vEthernet (%s)", pod4IfaceName), true) - mockOVSBridgeClient.EXPECT().SetInterfaceType(pod4IfaceName, "internal").Return(nil).Times(1) - mockOVSBridgeClient.EXPECT().GetOFPort(pod4IfaceName, true).Return(int32(5), nil).Times(1) - mockOFClient.EXPECT().InstallPodFlows(pod4IfaceName, gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Times(1) + hostIfaces.Store(fmt.Sprintf("vEthernet (%s)", unconnectedInterface.InterfaceName), true) + mockOVSBridgeClient.EXPECT().SetInterfaceType(unconnectedInterface.InterfaceName, "internal").Return(nil).Times(1) + mockOVSBridgeClient.EXPECT().GetOFPort(unconnectedInterface.InterfaceName, true).Return(int32(5), nil).Times(1) + mockOFClient.EXPECT().InstallPodFlows(unconnectedInterface.InterfaceName, unconnectedInterface.IPs, unconnectedInterface.MAC, uint32(5), uint16(0), nil). + Do(func(interfaceName string, _ []net.IP, _ net.HardwareAddr, _ uint32, _ uint16, _ *uint32) { + podFlowsInstalled <- interfaceName + }).Times(1) err := cniServer.reconcile() assert.NoError(t, err) _, exists := ifaceStore.GetInterfaceByName("iface3") assert.False(t, exists) + for i := 0; i < 2; i++ { + select { + case <-podFlowsInstalled: + case <-time.After(500 * time.Millisecond): + t.Errorf("InstallPodFlows should be called 2 times but was only called %d times", i) + break + } + } waiter.wait() waiter.close() } diff --git a/pkg/util/ip/ip.go b/pkg/util/ip/ip.go index bd82ea18989..58563e2274c 100644 --- a/pkg/util/ip/ip.go +++ b/pkg/util/ip/ip.go @@ -195,6 +195,14 @@ func MustParseCIDR(cidr string) *net.IPNet { return ipNet } +func MustParseMAC(mac string) net.HardwareAddr { + addr, err := net.ParseMAC(mac) + if err != nil { + panic(fmt.Errorf("cannot parse '%v': %v", mac, err)) + } + return addr +} + // IPNetEqual returns if the provided IPNets are the same subnet. func IPNetEqual(ipNet1, ipNet2 *net.IPNet) bool { if ipNet1 == nil && ipNet2 == nil {